1 /* display.c -- readline redisplay facility. */
2 
3 /* Copyright (C) 1987-2017 Free Software Foundation, Inc.
4 
5    This file is part of the GNU Readline Library (Readline), a library
6    for reading lines of text with interactive input and history editing.
7 
8    Readline is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation, either version 3 of the License, or
11    (at your option) any later version.
12 
13    Readline is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #define READLINE_LIBRARY
23 
24 #if defined (HAVE_CONFIG_H)
25 #  include <config.h>
26 #endif
27 
28 #include <sys/types.h>
29 
30 #if defined (HAVE_UNISTD_H)
31 #  include <unistd.h>
32 #endif /* HAVE_UNISTD_H */
33 
34 #include "posixstat.h"
35 
36 #if defined (HAVE_STDLIB_H)
37 #  include <stdlib.h>
38 #else
39 #  include "ansi_stdlib.h"
40 #endif /* HAVE_STDLIB_H */
41 
42 #include <stdio.h>
43 
44 #ifdef __MSDOS__
45 #  include <pc.h>
46 #endif
47 
48 /* System-specific feature definitions and include files. */
49 #include "rldefs.h"
50 #include "rlmbutil.h"
51 
52 /* Termcap library stuff. */
53 #include "tcap.h"
54 
55 /* Some standard library routines. */
56 #include "readline.h"
57 #include "history.h"
58 
59 #include "rlprivate.h"
60 #include "xmalloc.h"
61 
62 #if !defined (strchr) && !defined (__STDC__)
63 extern char *strchr (), *strrchr ();
64 #endif /* !strchr && !__STDC__ */
65 
66 static void update_line PARAMS((char *, char *, int, int, int, int));
67 static void space_to_eol PARAMS((int));
68 static void delete_chars PARAMS((int));
69 static void insert_some_chars PARAMS((char *, int, int));
70 static void open_some_spaces PARAMS((int));
71 static void cr PARAMS((void));
72 static void redraw_prompt PARAMS((char *));
73 
74 /* Values for FLAGS */
75 #define PMT_MULTILINE	0x01
76 
77 static char *expand_prompt PARAMS((char *, int, int *, int *, int *, int *));
78 
79 /* State of visible and invisible lines. */
80 struct line_state
81   {
82     char *line;
83     int *lbreaks;
84     int lbsize;
85 #if defined (HANDLE_MULTIBYTE)
86     int wbsize;
87     int *wrapped_line;
88 #endif
89   };
90 
91 /* The line display buffers.  One is the line currently displayed on
92    the screen.  The other is the line about to be displayed. */
93 static struct line_state line_state_array[2];
94 static struct line_state *line_state_visible = &line_state_array[0];
95 static struct line_state *line_state_invisible = &line_state_array[1];
96 static int line_structures_initialized = 0;
97 
98 /* Backwards-compatible names. */
99 #define inv_lbreaks	(line_state_invisible->lbreaks)
100 #define inv_lbsize	(line_state_invisible->lbsize)
101 #define vis_lbreaks	(line_state_visible->lbreaks)
102 #define vis_lbsize	(line_state_visible->lbsize)
103 
104 #define visible_line	(line_state_visible->line)
105 #define invisible_line	(line_state_invisible->line)
106 
107 #if defined (HANDLE_MULTIBYTE)
108 static int _rl_col_width PARAMS((const char *, int, int, int));
109 #else
110 #  define _rl_col_width(l, s, e, f)	(((e) <= (s)) ? 0 : (e) - (s))
111 #endif
112 
113 /* Heuristic used to decide whether it is faster to move from CUR to NEW
114    by backing up or outputting a carriage return and moving forward.  CUR
115    and NEW are either both buffer positions or absolute screen positions. */
116 #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
117 
118 /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
119    buffer index in others.  This macro is used when deciding whether the
120    current cursor position is in the middle of a prompt string containing
121    invisible characters.  XXX - might need to take `modmark' into account. */
122 /* XXX - only valid when tested against _rl_last_c_pos; buffer indices need
123    to use prompt_last_invisible directly. */
124 #define PROMPT_ENDING_INDEX \
125   ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
126 
127 /* **************************************************************** */
128 /*								    */
129 /*			Display stuff				    */
130 /*								    */
131 /* **************************************************************** */
132 
133 /* This is the stuff that is hard for me.  I never seem to write good
134    display routines in C.  Let's see how I do this time. */
135 
136 /* (PWP) Well... Good for a simple line updater, but totally ignores
137    the problems of input lines longer than the screen width.
138 
139    update_line and the code that calls it makes a multiple line,
140    automatically wrapping line update.  Careful attention needs
141    to be paid to the vertical position variables. */
142 
143 /* Keep two buffers; one which reflects the current contents of the
144    screen, and the other to draw what we think the new contents should
145    be.  Then compare the buffers, and make whatever changes to the
146    screen itself that we should.  Finally, make the buffer that we
147    just drew into be the one which reflects the current contents of the
148    screen, and place the cursor where it belongs.
149 
150    Commands that want to can fix the display themselves, and then let
151    this function know that the display has been fixed by setting the
152    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
153 
154 /* Application-specific redisplay function. */
155 rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
156 
157 /* Global variables declared here. */
158 /* What YOU turn on when you have handled all redisplay yourself. */
159 int rl_display_fixed = 0;
160 
161 /* The stuff that gets printed out before the actual text of the line.
162    This is usually pointing to rl_prompt. */
163 char *rl_display_prompt = (char *)NULL;
164 
165 /* Variables used to include the editing mode in the prompt. */
166 char *_rl_emacs_mode_str;
167 int _rl_emacs_modestr_len;
168 
169 char *_rl_vi_ins_mode_str;
170 int _rl_vi_ins_modestr_len;
171 
172 char *_rl_vi_cmd_mode_str;
173 int _rl_vi_cmd_modestr_len;
174 
175 /* Pseudo-global variables declared here. */
176 
177 /* Hints for other parts of readline to give to the display engine. */
178 int _rl_suppress_redisplay = 0;
179 int _rl_want_redisplay = 0;
180 
181 /* The visible cursor position.  If you print some text, adjust this. */
182 /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
183    supporting multibyte characters, and an absolute cursor position when
184    in such a locale.  This is an artifact of the donated multibyte support.
185    Care must be taken when modifying its value. */
186 int _rl_last_c_pos = 0;
187 int _rl_last_v_pos = 0;
188 
189 /* Number of physical lines consumed by the current line buffer currently
190   on screen minus 1. */
191 int _rl_vis_botlin = 0;
192 
193 /* This is a hint update_line gives to rl_redisplay that it has adjusted the
194    value of _rl_last_c_pos *and* taken the presence of any invisible chars in
195    the prompt into account.  rl_redisplay notes this and does not do the
196    adjustment itself. */
197 static int cpos_adjusted;
198 
199 /* The index into the line buffer corresponding to the cursor position */
200 static int cpos_buffer_position;
201 
202 /* A flag to note when we're displaying the first line of the prompt */
203 static int displaying_prompt_first_line;
204 /* The number of multibyte characters in the prompt, if any */
205 static int prompt_multibyte_chars;
206 
207 static int _rl_inv_botlin = 0;
208 
209 /* Variables used only in this file. */
210 /* The last left edge of text that was displayed.  This is used when
211    doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
212 static int last_lmargin;
213 
214 /* A buffer for `modeline' messages. */
215 static char *msg_buf = 0;
216 static int msg_bufsiz = 0;
217 
218 /* Non-zero forces the redisplay even if we thought it was unnecessary. */
219 static int forced_display;
220 
221 /* Default and initial buffer size.  Can grow. */
222 static int line_size = 1024;
223 
224 /* Variables to keep track of the expanded prompt string, which may
225    include invisible characters. */
226 
227 static char *local_prompt, *local_prompt_prefix;
228 static int local_prompt_len;
229 static int prompt_prefix_length;
230 /* Number of chars in the buffer that contribute to visible chars on the screen.
231    This might be different from the number of physical chars in the presence
232    of multibyte characters */
233 static int prompt_visible_length;
234 
235 /* The number of invisible characters in the line currently being
236    displayed on the screen. */
237 static int visible_wrap_offset;
238 
239 /* The number of invisible characters in the prompt string.  Static so it
240    can be shared between rl_redisplay and update_line */
241 static int wrap_offset;
242 
243 /* The index of the last invisible character in the prompt string. */
244 static int prompt_last_invisible;
245 
246 /* The length (buffer offset) of the first line of the last (possibly
247    multi-line) buffer displayed on the screen. */
248 static int visible_first_line_len;
249 
250 /* Number of invisible characters on the first physical line of the prompt.
251    Only valid when the number of physical characters in the prompt exceeds
252    (or is equal to) _rl_screenwidth. */
253 static int prompt_invis_chars_first_line;
254 
255 static int prompt_last_screen_line;
256 
257 static int prompt_physical_chars;
258 
259 /* An array of indexes into the prompt string where we will break physical
260    screen lines.  It's easier to compute in expand_prompt and use later in
261    rl_redisplay instead of having rl_redisplay try to guess about invisible
262    characters in the prompt or use heuristics about where they are. */
263 static int *local_prompt_newlines;
264 
265 /* set to a non-zero value by rl_redisplay if we are marking modified history
266    lines and the current line is so marked. */
267 static int modmark;
268 
269 static int line_totbytes;
270 
271 /* Variables to save and restore prompt and display information. */
272 
273 /* These are getting numerous enough that it's time to create a struct. */
274 
275 static char *saved_local_prompt;
276 static char *saved_local_prefix;
277 static int *saved_local_prompt_newlines;
278 
279 static int saved_last_invisible;
280 static int saved_visible_length;
281 static int saved_prefix_length;
282 static int saved_local_length;
283 static int saved_invis_chars_first_line;
284 static int saved_physical_chars;
285 
286 /* Return a string indicating the editing mode, for use in the prompt. */
287 
288 static char *
prompt_modestr(int * lenp)289 prompt_modestr (int *lenp)
290 {
291   if (rl_editing_mode == emacs_mode)
292     {
293       if (lenp)
294 	*lenp = _rl_emacs_mode_str ? _rl_emacs_modestr_len : RL_EMACS_MODESTR_DEFLEN;
295       return _rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT;
296     }
297   else if (_rl_keymap == vi_insertion_keymap)
298     {
299       if (lenp)
300 	*lenp = _rl_vi_ins_mode_str ? _rl_vi_ins_modestr_len : RL_VI_INS_MODESTR_DEFLEN;
301       return _rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT;		/* vi insert mode */
302     }
303   else
304     {
305       if (lenp)
306 	*lenp = _rl_vi_cmd_mode_str ? _rl_vi_cmd_modestr_len : RL_VI_CMD_MODESTR_DEFLEN;
307       return _rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT;		/* vi command mode */
308     }
309 }
310 
311 /* Expand the prompt string S and return the number of visible
312    characters in *LP, if LP is not null.  This is currently more-or-less
313    a placeholder for expansion.  LIP, if non-null is a place to store the
314    index of the last invisible character in the returned string. NIFLP,
315    if non-zero, is a place to store the number of invisible characters in
316    the first prompt line.  The previous are used as byte counts -- indexes
317    into a character buffer.  *VLP gets the number of physical characters in
318    the expanded prompt (visible length) */
319 
320 /* Current implementation:
321 	\001 (^A) start non-visible characters
322 	\002 (^B) end non-visible characters
323    all characters except \001 and \002 (following a \001) are copied to
324    the returned string; all characters except those between \001 and
325    \002 are assumed to be `visible'. */
326 
327 /* Possible values for FLAGS:
328 	PMT_MULTILINE	caller indicates that this is part of a multiline prompt
329 */
330 
331 /* This approximates the number of lines the prompt will take when displayed */
332 #define APPROX_DIV(n, d)	(((n) < (d)) ? 1 : ((n) / (d)) + 1)
333 
334 static char *
expand_prompt(char * pmt,int flags,int * lp,int * lip,int * niflp,int * vlp)335 expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
336 {
337   char *r, *ret, *p, *igstart, *nprompt, *ms;
338   int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
339   int mlen, newlines, newlines_guess, bound;
340   int mb_cur_max;
341 
342   /* We only expand the mode string for the last line of a multiline prompt
343      (a prompt with embedded newlines). */
344   ms = (((pmt == rl_prompt) ^ (flags & PMT_MULTILINE)) && _rl_show_mode_in_prompt) ? prompt_modestr (&mlen) : 0;
345   if (ms)
346     {
347       l = strlen (pmt);
348       nprompt = (char *)xmalloc (l + mlen + 1);
349       memcpy (nprompt, ms, mlen);
350       strcpy (nprompt + mlen, pmt);
351     }
352   else
353     nprompt = pmt;
354 
355   mb_cur_max = MB_CUR_MAX;
356 
357   if (_rl_screenwidth == 0)
358     _rl_get_screen_size (0, 0);	/* avoid division by zero */
359 
360   /* Short-circuit if we can.  We can do this if we are treating the prompt as
361      a sequence of bytes and there are no invisible characters in the prompt
362      to deal with. Since we populate local_prompt_newlines, we have to run
363      through the rest of the function if this prompt looks like it's going to
364      be longer than one screen line. */
365   if ((mb_cur_max <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0)
366     {
367       l = strlen (nprompt);
368       if (l < (_rl_screenwidth > 0 ? _rl_screenwidth : 80))
369         {
370 	  r = (nprompt == pmt) ? savestring (pmt) : nprompt;
371 	  if (lp)
372 	    *lp = l;
373 	  if (lip)
374 	    *lip = 0;
375 	  if (niflp)
376 	    *niflp = 0;
377 	  if (vlp)
378 	    *vlp = l;
379 
380 	  local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * 2);
381 	  local_prompt_newlines[0] = 0;
382 	  local_prompt_newlines[1] = -1;
383 
384 	  return r;
385         }
386     }
387 
388   l = strlen (nprompt);			/* XXX */
389   r = ret = (char *)xmalloc (l + 1);
390 
391   /* Guess at how many screen lines the prompt will take to size the array that
392      keeps track of where the line wraps happen */
393   newlines_guess = (_rl_screenwidth > 0) ? APPROX_DIV(l,  _rl_screenwidth) : APPROX_DIV(l, 80);
394   local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1));
395   local_prompt_newlines[newlines = 0] = 0;
396   for (rl = 1; rl <= newlines_guess; rl++)
397     local_prompt_newlines[rl] = -1;
398 
399   rl = physchars = 0;	/* mode string now part of nprompt */
400   invfl = 0;		/* invisible chars in first line of prompt */
401   invflset = 0;		/* we only want to set invfl once */
402   igstart = 0;		/* we're not ignoring any characters yet */
403 
404   for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++)
405     {
406       /* This code strips the invisible character string markers
407 	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
408       if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE)		/* XXX - check ignoring? */
409 	{
410 	  ignoring = 1;
411 	  igstart = p;
412 	  continue;
413 	}
414       else if (ignoring && *p == RL_PROMPT_END_IGNORE)
415 	{
416 	  ignoring = 0;
417 	  if (p != (igstart + 1))
418 	    last = r - ret - 1;
419 	  continue;
420 	}
421       else
422 	{
423 #if defined (HANDLE_MULTIBYTE)
424 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
425 	    {
426 	      pind = p - nprompt;
427 	      ind = _rl_find_next_mbchar (nprompt, pind, 1, MB_FIND_NONZERO);
428 	      l = ind - pind;
429 	      while (l--)
430 	        *r++ = *p++;
431 	      if (!ignoring)
432 		{
433 		  /* rl ends up being assigned to prompt_visible_length,
434 		     which is the number of characters in the buffer that
435 		     contribute to characters on the screen, which might
436 		     not be the same as the number of physical characters
437 		     on the screen in the presence of multibyte characters */
438 		  rl += ind - pind;
439 		  physchars += _rl_col_width (nprompt, pind, ind, 0);
440 		}
441 	      else
442 		ninvis += ind - pind;
443 	      p--;			/* compensate for later increment */
444 	    }
445 	  else
446 #endif
447 	    {
448 	      *r++ = *p;
449 	      if (!ignoring)
450 		{
451 		  rl++;			/* visible length byte counter */
452 		  physchars++;
453 		}
454 	      else
455 		ninvis++;		/* invisible chars byte counter */
456 	    }
457 
458 	  if (invflset == 0 && physchars >= _rl_screenwidth)
459 	    {
460 	      invfl = ninvis;
461 	      invflset = 1;
462 	    }
463 
464 	  if (physchars >= (bound = (newlines + 1) * _rl_screenwidth) && local_prompt_newlines[newlines+1] == -1)
465 	    {
466 	      int new;
467 	      if (physchars > bound)		/* should rarely happen */
468 		{
469 #if defined (HANDLE_MULTIBYTE)
470 		  *r = '\0';	/* need null-termination for strlen */
471 		  if (mb_cur_max > 1 && rl_byte_oriented == 0)
472 		    new = _rl_find_prev_mbchar (ret, r - ret, MB_FIND_ANY);
473 		  else
474 #endif
475 		    new = r - ret - (physchars - bound);	/* XXX */
476 		}
477 	      else
478 	        new = r - ret;
479 	      local_prompt_newlines[++newlines] = new;
480 	    }
481 	}
482     }
483 
484   if (rl < _rl_screenwidth)
485     invfl = ninvis;
486 
487   *r = '\0';
488   if (lp)
489     *lp = rl;
490   if (lip)
491     *lip = last;
492   if (niflp)
493     *niflp = invfl;
494   if  (vlp)
495     *vlp = physchars;
496 
497   if (nprompt != pmt)
498     free (nprompt);
499 
500   return ret;
501 }
502 
503 /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
504    PMT and return the rest of PMT. */
505 char *
_rl_strip_prompt(char * pmt)506 _rl_strip_prompt (char *pmt)
507 {
508   char *ret;
509 
510   ret = expand_prompt (pmt, 0, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
511   return ret;
512 }
513 
514 void
_rl_reset_prompt(void)515 _rl_reset_prompt (void)
516 {
517   rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
518 }
519 
520 /*
521  * Expand the prompt string into the various display components, if
522  * necessary.
523  *
524  * local_prompt = expanded last line of string in rl_display_prompt
525  *		  (portion after the final newline)
526  * local_prompt_prefix = portion before last newline of rl_display_prompt,
527  *			 expanded via expand_prompt
528  * prompt_visible_length = number of visible characters in local_prompt
529  * prompt_prefix_length = number of visible characters in local_prompt_prefix
530  *
531  * It also tries to keep track of the number of invisible characters in the
532  * prompt string, and where they are.
533  *
534  * This function is called once per call to readline().  It may also be
535  * called arbitrarily to expand the primary prompt.
536  *
537  * The return value is the number of visible characters on the last line
538  * of the (possibly multi-line) prompt.  In this case, multi-line means
539  * there are embedded newlines in the prompt string itself, not that the
540  * number of physical characters exceeds the screen width and the prompt
541  * wraps.
542  */
543 int
rl_expand_prompt(char * prompt)544 rl_expand_prompt (char *prompt)
545 {
546   char *p, *t;
547   int c;
548 
549   /* Clear out any saved values. */
550   FREE (local_prompt);
551   FREE (local_prompt_prefix);
552 
553   local_prompt = local_prompt_prefix = (char *)0;
554   local_prompt_len = 0;
555   prompt_last_invisible = prompt_invis_chars_first_line = 0;
556   prompt_visible_length = prompt_physical_chars = 0;
557 
558   if (prompt == 0 || *prompt == 0)
559     return (0);
560 
561   p = strrchr (prompt, '\n');
562   if (p == 0)
563     {
564       /* The prompt is only one logical line, though it might wrap. */
565       local_prompt = expand_prompt (prompt, 0, &prompt_visible_length,
566 					       &prompt_last_invisible,
567 					       &prompt_invis_chars_first_line,
568 					       &prompt_physical_chars);
569       local_prompt_prefix = (char *)0;
570       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
571       return (prompt_visible_length);
572     }
573   else
574     {
575       /* The prompt spans multiple lines. */
576       t = ++p;
577       local_prompt = expand_prompt (p, PMT_MULTILINE,
578 				       &prompt_visible_length,
579 				       &prompt_last_invisible,
580 				       &prompt_invis_chars_first_line,
581 				       &prompt_physical_chars);
582       c = *t; *t = '\0';
583       /* The portion of the prompt string up to and including the
584 	 final newline is now null-terminated. */
585       local_prompt_prefix = expand_prompt (prompt, PMT_MULTILINE,
586 						   &prompt_prefix_length,
587 						   (int *)NULL,
588 						   (int *)NULL,
589 						   (int *)NULL);
590       *t = c;
591       local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
592       return (prompt_prefix_length);
593     }
594 }
595 
596 /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
597    arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
598    and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
599    increased.  If the lines have already been allocated, this ensures that
600    they can hold at least MINSIZE characters. */
601 static void
init_line_structures(int minsize)602 init_line_structures (int minsize)
603 {
604   register int n;
605   int original_minsize = minsize;
606 
607   if (minsize <= _rl_screenwidth)	/* XXX - for gdb */
608     minsize = _rl_screenwidth + 1;
609 
610   if (invisible_line == 0)	/* initialize it */
611     {
612       if (line_size < minsize)
613 	line_size = minsize;
614       visible_line = (char *)xmalloc (line_size);
615       invisible_line = (char *)xmalloc (line_size);
616     }
617   else if (line_size < minsize)	/* ensure it can hold MINSIZE chars */
618     {
619       line_size *= 2;
620       if (line_size < minsize)
621 	line_size = minsize;
622       visible_line = (char *)xrealloc (visible_line, line_size);
623       invisible_line = (char *)xrealloc (invisible_line, line_size);
624     }
625 
626   for (n = original_minsize; n < line_size; n++)
627     {
628       visible_line[n] = 0;
629       invisible_line[n] = 1;
630     }
631 
632   if (vis_lbreaks == 0)
633     {
634       /* should be enough. */
635       inv_lbsize = vis_lbsize = 256;
636 
637 #if defined (HANDLE_MULTIBYTE)
638       line_state_visible->wbsize = vis_lbsize;
639       line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
640 
641       line_state_invisible->wbsize = inv_lbsize;
642       line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
643 #endif
644 
645       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
646       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
647       inv_lbreaks[0] = vis_lbreaks[0] = 0;
648     }
649 
650   line_structures_initialized = 1;
651 }
652 
653 /* Basic redisplay algorithm.  See comments inline. */
654 void
rl_redisplay(void)655 rl_redisplay (void)
656 {
657   register int in, out, c, linenum, cursor_linenum;
658   register char *line;
659   int inv_botlin, lb_botlin, lb_linenum, o_cpos;
660   int newlines, lpos, temp, n0, num, prompt_lines_estimate;
661   char *prompt_this_line;
662   int mb_cur_max = MB_CUR_MAX;
663 #if defined (HANDLE_MULTIBYTE)
664   wchar_t wc;
665   size_t wc_bytes;
666   int wc_width;
667   mbstate_t ps;
668   int _rl_wrapped_multicolumn = 0;
669 #endif
670 
671   if (_rl_echoing_p == 0)
672     return;
673 
674   /* Block keyboard interrupts because this function manipulates global
675      data structures. */
676   _rl_block_sigint ();
677   RL_SETSTATE (RL_STATE_REDISPLAYING);
678 
679   if (!rl_display_prompt)
680     rl_display_prompt = "";
681 
682   if (line_structures_initialized == 0)
683     {
684       init_line_structures (0);
685       rl_on_new_line ();
686     }
687   else if (line_size <= _rl_screenwidth)
688     init_line_structures (_rl_screenwidth + 1);
689 
690   /* Draw the line into the buffer. */
691   cpos_buffer_position = -1;
692 
693   prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
694 
695   line = invisible_line;
696   out = inv_botlin = 0;
697 
698   /* Mark the line as modified or not.  We only do this for history
699      lines. */
700   modmark = 0;
701   if (_rl_mark_modified_lines && current_history () && rl_undo_list)
702     {
703       line[out++] = '*';
704       line[out] = '\0';
705       modmark = 1;
706     }
707 
708   /* If someone thought that the redisplay was handled, but the currently
709      visible line has a different modification state than the one about
710      to become visible, then correct the caller's misconception. */
711   if (visible_line[0] != invisible_line[0])
712     rl_display_fixed = 0;
713 
714   /* If the prompt to be displayed is the `primary' readline prompt (the
715      one passed to readline()), use the values we have already expanded.
716      If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
717      number of non-visible characters in the prompt string. */
718   /* This is where we output the characters in the prompt before the last
719      newline, if any.  If there aren't any embedded newlines, we don't
720      write anything. Copy the last line of the prompt string into the line in
721      any case */
722   if (rl_display_prompt == rl_prompt || local_prompt)
723     {
724       if (local_prompt_prefix && forced_display)
725 	_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
726 
727       if (local_prompt_len > 0)
728 	{
729 	  temp = local_prompt_len + out + 2;
730 	  if (temp >= line_size)
731 	    {
732 	      line_size = (temp + 1024) - (temp % 1024);
733 	      visible_line = (char *)xrealloc (visible_line, line_size);
734 	      line = invisible_line = (char *)xrealloc (invisible_line, line_size);
735 	    }
736 	  strncpy (line + out, local_prompt, local_prompt_len);
737 	  out += local_prompt_len;
738 	}
739       line[out] = '\0';
740       wrap_offset = local_prompt_len - prompt_visible_length;
741     }
742   else
743     {
744       int pmtlen;
745       prompt_this_line = strrchr (rl_display_prompt, '\n');
746       if (!prompt_this_line)
747 	prompt_this_line = rl_display_prompt;
748       else
749 	{
750 	  prompt_this_line++;
751 	  pmtlen = prompt_this_line - rl_display_prompt;	/* temp var */
752 	  if (forced_display)
753 	    {
754 	      _rl_output_some_chars (rl_display_prompt, pmtlen);
755 	      /* Make sure we are at column zero even after a newline,
756 		 regardless of the state of terminal output processing. */
757 	      if (pmtlen < 2 || prompt_this_line[-2] != '\r')
758 		cr ();
759 	    }
760 	}
761 
762       prompt_physical_chars = pmtlen = strlen (prompt_this_line);
763       temp = pmtlen + out + 2;
764       if (temp >= line_size)
765 	{
766 	  line_size = (temp + 1024) - (temp % 1024);
767 	  visible_line = (char *)xrealloc (visible_line, line_size);
768 	  line = invisible_line = (char *)xrealloc (invisible_line, line_size);
769 	}
770       strncpy (line + out,  prompt_this_line, pmtlen);
771       out += pmtlen;
772       line[out] = '\0';
773       wrap_offset = prompt_invis_chars_first_line = 0;
774     }
775 
776 #if defined (HANDLE_MULTIBYTE)
777 #define CHECK_INV_LBREAKS() \
778       do { \
779 	if (newlines >= (inv_lbsize - 2)) \
780 	  { \
781 	    inv_lbsize *= 2; \
782 	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
783 	  } \
784 	if (newlines >= (line_state_invisible->wbsize - 2)) \
785 	  { \
786 	    line_state_invisible->wbsize *= 2; \
787 	    line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
788 	  } \
789       } while (0)
790 #else
791 #define CHECK_INV_LBREAKS() \
792       do { \
793 	if (newlines >= (inv_lbsize - 2)) \
794 	  { \
795 	    inv_lbsize *= 2; \
796 	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
797 	  } \
798       } while (0)
799 #endif /* !HANDLE_MULTIBYTE */
800 
801 #if defined (HANDLE_MULTIBYTE)
802 #define CHECK_LPOS() \
803       do { \
804 	lpos++; \
805 	if (lpos >= _rl_screenwidth) \
806 	  { \
807 	    if (newlines >= (inv_lbsize - 2)) \
808 	      { \
809 		inv_lbsize *= 2; \
810 		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
811 	      } \
812 	    inv_lbreaks[++newlines] = out; \
813 	    if (newlines >= (line_state_invisible->wbsize - 2)) \
814 	      { \
815 		line_state_invisible->wbsize *= 2; \
816 		line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
817 	      } \
818 	    line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
819 	    lpos = 0; \
820 	  } \
821       } while (0)
822 #else
823 #define CHECK_LPOS() \
824       do { \
825 	lpos++; \
826 	if (lpos >= _rl_screenwidth) \
827 	  { \
828 	    if (newlines >= (inv_lbsize - 2)) \
829 	      { \
830 		inv_lbsize *= 2; \
831 		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
832 	      } \
833 	    inv_lbreaks[++newlines] = out; \
834 	    lpos = 0; \
835 	  } \
836       } while (0)
837 #endif
838 
839   /* inv_lbreaks[i] is where line i starts in the buffer. */
840   inv_lbreaks[newlines = 0] = 0;
841   /* lpos is a physical cursor position, so it needs to be adjusted by the
842      number of invisible characters in the prompt, per line.  We compute
843      the line breaks in the prompt string in expand_prompt, taking invisible
844      characters into account, and if lpos exceeds the screen width, we copy
845      the data in the loop below. */
846   lpos = prompt_physical_chars + modmark;
847 
848 #if defined (HANDLE_MULTIBYTE)
849   memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
850   num = 0;
851 #endif
852 
853   /* prompt_invis_chars_first_line is the number of invisible characters in
854      the first physical line of the prompt.
855      wrap_offset - prompt_invis_chars_first_line is usually the number of
856      invis chars on the second (or, more generally, last) line. */
857 
858   /* This is zero-based, used to set the newlines */
859   prompt_lines_estimate = lpos / _rl_screenwidth;
860 
861   /* what if lpos is already >= _rl_screenwidth before we start drawing the
862      contents of the command line? */
863   if (lpos >= _rl_screenwidth)
864     {
865       temp = 0;
866 
867       /* first copy the linebreaks array we computed in expand_prompt */
868       while (local_prompt_newlines[newlines+1] != -1)
869 	{
870 	  temp = local_prompt_newlines[newlines+1];
871 	  inv_lbreaks[++newlines] = temp;
872 	}
873 
874       /* Now set lpos from the last newline */
875       if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
876         lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
877       else
878         lpos -= (_rl_screenwidth * newlines);
879     }
880 
881   prompt_last_screen_line = newlines;
882 
883   /* Draw the rest of the line (after the prompt) into invisible_line, keeping
884      track of where the cursor is (cpos_buffer_position), the number of the
885      line containing the cursor (lb_linenum), the last line number (lb_botlin
886      and inv_botlin).
887      It maintains an array of line breaks for display (inv_lbreaks).
888      This handles expanding tabs for display and displaying meta characters. */
889   lb_linenum = 0;
890 #if defined (HANDLE_MULTIBYTE)
891   in = 0;
892   if (mb_cur_max > 1 && rl_byte_oriented == 0)
893     {
894       memset (&ps, 0, sizeof (mbstate_t));
895       if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[0]))
896 	{
897 	  wc = (wchar_t)rl_line_buffer[0];
898 	  wc_bytes = 1;
899 	}
900       else
901 	wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
902     }
903   else
904     wc_bytes = 1;
905   while (in < rl_end)
906 #else
907   for (in = 0; in < rl_end; in++)
908 #endif
909     {
910       c = (unsigned char)rl_line_buffer[in];
911 
912 #if defined (HANDLE_MULTIBYTE)
913       if (mb_cur_max > 1 && rl_byte_oriented == 0)
914 	{
915 	  if (MB_INVALIDCH (wc_bytes))
916 	    {
917 	      /* Byte sequence is invalid or shortened.  Assume that the
918 	         first byte represents a character. */
919 	      wc_bytes = 1;
920 	      /* Assume that a character occupies a single column. */
921 	      wc_width = 1;
922 	      memset (&ps, 0, sizeof (mbstate_t));
923 	    }
924 	  else if (MB_NULLWCH (wc_bytes))
925 	    break;			/* Found '\0' */
926 	  else
927 	    {
928 	      temp = WCWIDTH (wc);
929 	      wc_width = (temp >= 0) ? temp : 1;
930 	    }
931 	}
932 #endif
933 
934       if (out + 8 >= line_size)		/* XXX - 8 for \t */
935 	{
936 	  line_size *= 2;
937 	  visible_line = (char *)xrealloc (visible_line, line_size);
938 	  invisible_line = (char *)xrealloc (invisible_line, line_size);
939 	  line = invisible_line;
940 	}
941 
942       if (in == rl_point)
943 	{
944 	  cpos_buffer_position = out;
945 	  lb_linenum = newlines;
946 	}
947 
948 #if defined (HANDLE_MULTIBYTE)
949       if (META_CHAR (c) && _rl_output_meta_chars == 0)	/* XXX - clean up */
950 #else
951       if (META_CHAR (c))
952 #endif
953 	{
954 	  if (_rl_output_meta_chars == 0)
955 	    {
956 	      sprintf (line + out, "\\%o", c);
957 
958 	      if (lpos + 4 >= _rl_screenwidth)
959 		{
960 		  temp = _rl_screenwidth - lpos;
961 		  CHECK_INV_LBREAKS ();
962 		  inv_lbreaks[++newlines] = out + temp;
963 #if defined (HANDLE_MULTIBYTE)
964 		  line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
965 #endif
966 		  lpos = 4 - temp;
967 		}
968 	      else
969 		lpos += 4;
970 
971 	      out += 4;
972 	    }
973 	  else
974 	    {
975 	      line[out++] = c;
976 	      CHECK_LPOS();
977 	    }
978 	}
979 #if defined (DISPLAY_TABS)
980       else if (c == '\t')
981 	{
982 	  register int newout;
983 
984 #if 0
985 	  newout = (out | (int)7) + 1;
986 #else
987 	  newout = out + 8 - lpos % 8;
988 #endif
989 	  temp = newout - out;
990 	  if (lpos + temp >= _rl_screenwidth)
991 	    {
992 	      register int temp2;
993 	      temp2 = _rl_screenwidth - lpos;
994 	      CHECK_INV_LBREAKS ();
995 	      inv_lbreaks[++newlines] = out + temp2;
996 #if defined (HANDLE_MULTIBYTE)
997 	      line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
998 #endif
999 	      lpos = temp - temp2;
1000 	      while (out < newout)
1001 		line[out++] = ' ';
1002 	    }
1003 	  else
1004 	    {
1005 	      while (out < newout)
1006 		line[out++] = ' ';
1007 	      lpos += temp;
1008 	    }
1009 	}
1010 #endif
1011       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1012 	{
1013 	  line[out++] = '\0';	/* XXX - sentinel */
1014 	  CHECK_INV_LBREAKS ();
1015 	  inv_lbreaks[++newlines] = out;
1016 #if defined (HANDLE_MULTIBYTE)
1017 	  line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1018 #endif
1019 	  lpos = 0;
1020 	}
1021       else if (CTRL_CHAR (c) || c == RUBOUT)
1022 	{
1023 	  line[out++] = '^';
1024 	  CHECK_LPOS();
1025 	  line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1026 	  CHECK_LPOS();
1027 	}
1028       else
1029 	{
1030 #if defined (HANDLE_MULTIBYTE)
1031 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1032 	    {
1033 	      register int i;
1034 
1035 	      _rl_wrapped_multicolumn = 0;
1036 
1037 	      if (_rl_screenwidth < lpos + wc_width)
1038 		for (i = lpos; i < _rl_screenwidth; i++)
1039 		  {
1040 		    /* The space will be removed in update_line() */
1041 		    line[out++] = ' ';
1042 		    _rl_wrapped_multicolumn++;
1043 		    CHECK_LPOS();
1044 		  }
1045 	      if (in == rl_point)
1046 		{
1047 		  cpos_buffer_position = out;
1048 		  lb_linenum = newlines;
1049 		}
1050 	      for (i = in; i < in+wc_bytes; i++)
1051 		line[out++] = rl_line_buffer[i];
1052 	      for (i = 0; i < wc_width; i++)
1053 		CHECK_LPOS();
1054 	    }
1055 	  else
1056 	    {
1057 	      line[out++] = c;
1058 	      CHECK_LPOS();
1059 	    }
1060 #else
1061 	  line[out++] = c;
1062 	  CHECK_LPOS();
1063 #endif
1064 	}
1065 
1066 #if defined (HANDLE_MULTIBYTE)
1067       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1068 	{
1069 	  in += wc_bytes;
1070 	  if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[in]))
1071 	    {
1072 	      wc = (wchar_t)rl_line_buffer[in];
1073 	      wc_bytes = 1;
1074 	      memset (&ps, 0, sizeof (mbstate_t));	/* re-init state */
1075 	    }
1076 	  else
1077 	    wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
1078 	}
1079       else
1080         in++;
1081 #endif
1082     }
1083   line[out] = '\0';
1084   line_totbytes = out;
1085   if (cpos_buffer_position < 0)
1086     {
1087       cpos_buffer_position = out;
1088       lb_linenum = newlines;
1089     }
1090 
1091   inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
1092   CHECK_INV_LBREAKS ();
1093   inv_lbreaks[newlines+1] = out;
1094 #if defined (HANDLE_MULTIBYTE)
1095   /* This should be 0 anyway */
1096   line_state_invisible->wrapped_line[newlines+1] = _rl_wrapped_multicolumn;
1097 #endif
1098   cursor_linenum = lb_linenum;
1099 
1100   /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
1101      CURSOR_LINENUM == line number where the cursor should be placed. */
1102 
1103   /* PWP: now is when things get a bit hairy.  The visible and invisible
1104      line buffers are really multiple lines, which would wrap every
1105      (screenwidth - 1) characters.  Go through each in turn, finding
1106      the changed region and updating it.  The line order is top to bottom. */
1107 
1108   /* If we can move the cursor up and down, then use multiple lines,
1109      otherwise, let long lines display in a single terminal line, and
1110      horizontally scroll it. */
1111   displaying_prompt_first_line = 1;
1112   if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1113     {
1114       int nleft, pos, changed_screen_line, tx;
1115 
1116       if (!rl_display_fixed || forced_display)
1117 	{
1118 	  forced_display = 0;
1119 
1120 	  /* If we have more than a screenful of material to display, then
1121 	     only display a screenful.  We should display the last screen,
1122 	     not the first.  */
1123 	  if (out >= _rl_screenchars)
1124 	    {
1125 #if defined (HANDLE_MULTIBYTE)
1126 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
1127 		out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
1128 	      else
1129 #endif
1130 		out = _rl_screenchars - 1;
1131 	    }
1132 
1133 	  /* The first line is at character position 0 in the buffer.  The
1134 	     second and subsequent lines start at inv_lbreaks[N], offset by
1135 	     OFFSET (which has already been calculated above).  */
1136 
1137 #define INVIS_FIRST()	(prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
1138 #define WRAP_OFFSET(line, offset)  ((line == 0) \
1139 					? (offset ? INVIS_FIRST() : 0) \
1140 					: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
1141 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
1142 #define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
1143 #define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
1144 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
1145 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
1146 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
1147 
1148 #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
1149 			_rl_last_c_pos != o_cpos && \
1150 			_rl_last_c_pos > wrap_offset && \
1151 			o_cpos < prompt_last_invisible)
1152 
1153 	  /* For each line in the buffer, do the updating display. */
1154 	  for (linenum = 0; linenum <= inv_botlin; linenum++)
1155 	    {
1156 	      /* This can lead us astray if we execute a program that changes
1157 		 the locale from a non-multibyte to a multibyte one. */
1158 	      o_cpos = _rl_last_c_pos;
1159 	      cpos_adjusted = 0;
1160 	      update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
1161 			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
1162 
1163 	      /* update_line potentially changes _rl_last_c_pos, but doesn't
1164 		 take invisible characters into account, since _rl_last_c_pos
1165 		 is an absolute cursor position in a multibyte locale.  We
1166 		 choose to (mostly) compensate for that here, rather than
1167 		 change update_line itself.  There are several cases in which
1168 		 update_line adjusts _rl_last_c_pos itself (so it can pass
1169 		 _rl_move_cursor_relative accurate values); it communicates
1170 		 this back by setting cpos_adjusted.  If we assume that
1171 		 _rl_last_c_pos is correct (an absolute cursor position) each
1172 		 time update_line is called, then we can assume in our
1173 		 calculations that o_cpos does not need to be adjusted by
1174 		 wrap_offset. */
1175 	      if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
1176 		_rl_last_c_pos -= prompt_invis_chars_first_line;	/* XXX - was wrap_offset */
1177 	      else if (cpos_adjusted == 0 &&
1178 			linenum == prompt_last_screen_line &&
1179 			prompt_physical_chars > _rl_screenwidth &&
1180 			(mb_cur_max > 1 && rl_byte_oriented == 0) &&
1181 			_rl_last_c_pos != o_cpos &&
1182 			_rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))	/* XXX - rethink this last one */
1183 		/* This assumes that all the invisible characters are split
1184 		   between the first and last lines of the prompt, if the
1185 		   prompt consumes more than two lines. It's usually right */
1186 		/* XXX - not sure this is ever executed */
1187 		_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
1188 
1189 	      /* If this is the line with the prompt, we might need to
1190 		 compensate for invisible characters in the new line. Do
1191 		 this only if there is not more than one new line (which
1192 		 implies that we completely overwrite the old visible line)
1193 		 and the new line is shorter than the old.  Make sure we are
1194 		 at the end of the new line before clearing. */
1195 	      if (linenum == 0 &&
1196 		  inv_botlin == 0 && _rl_last_c_pos == out &&
1197 		  (wrap_offset > visible_wrap_offset) &&
1198 		  (_rl_last_c_pos < visible_first_line_len))
1199 		{
1200 		  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1201 		    nleft = _rl_screenwidth - _rl_last_c_pos;
1202 		  else
1203 		    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1204 		  if (nleft)
1205 		    _rl_clear_to_eol (nleft);
1206 		}
1207 #if 0
1208 	      /* This segment is intended to handle the case where the prompt
1209 		 has invisible characters on the second line and the new line
1210 		 to be displayed needs to clear the rest of the old characters
1211 		 out (e.g., when printing the i-search prompt).  In general,
1212 		 the case of the new line being shorter than the old.
1213 		 Incomplete */
1214 	      else if (linenum == prompt_last_screen_line &&
1215 		       prompt_physical_chars > _rl_screenwidth &&
1216 		       wrap_offset != prompt_invis_chars_first_line &&
1217 		       _rl_last_c_pos == out &&
1218 #endif
1219 
1220 
1221 	      /* Since the new first line is now visible, save its length. */
1222 	      if (linenum == 0)
1223 		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
1224 	    }
1225 
1226 	  /* We may have deleted some lines.  If so, clear the left over
1227 	     blank ones at the bottom out. */
1228 	  if (_rl_vis_botlin > inv_botlin)
1229 	    {
1230 	      char *tt;
1231 	      for (; linenum <= _rl_vis_botlin; linenum++)
1232 		{
1233 		  tt = VIS_CHARS (linenum);
1234 		  _rl_move_vert (linenum);
1235 		  _rl_move_cursor_relative (0, tt);
1236 		  _rl_clear_to_eol
1237 		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
1238 		}
1239 	    }
1240 	  _rl_vis_botlin = inv_botlin;
1241 
1242 	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
1243 	     different screen line during this redisplay. */
1244 	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
1245 	  if (changed_screen_line)
1246 	    {
1247 	      _rl_move_vert (cursor_linenum);
1248 	      /* If we moved up to the line with the prompt using _rl_term_up,
1249 		 the physical cursor position on the screen stays the same,
1250 		 but the buffer position needs to be adjusted to account
1251 		 for invisible characters. */
1252 	      if ((mb_cur_max == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
1253 		_rl_last_c_pos += wrap_offset;
1254 	    }
1255 
1256 	  /* Now we move the cursor to where it needs to be.  First, make
1257 	     sure we are on the correct line (cursor_linenum). */
1258 
1259 	  /* We have to reprint the prompt if it contains invisible
1260 	     characters, since it's not generally OK to just reprint
1261 	     the characters from the current cursor position.  But we
1262 	     only need to reprint it if the cursor is before the last
1263 	     invisible character in the prompt string. */
1264 	  nleft = prompt_visible_length + wrap_offset;
1265 	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1266 #if 0
1267 	      _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
1268 #else
1269 	      _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1270 #endif
1271 	    {
1272 #if defined (__MSDOS__)
1273 	      putc ('\r', rl_outstream);
1274 #else
1275 	      if (_rl_term_cr)
1276 		tputs (_rl_term_cr, 1, _rl_output_character_function);
1277 #endif
1278 	      if (modmark)
1279 		_rl_output_some_chars ("*", 1);
1280 
1281 	      _rl_output_some_chars (local_prompt, nleft);
1282 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
1283 		_rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
1284 	      else
1285 		_rl_last_c_pos = nleft + modmark;
1286 	    }
1287 
1288 	  /* Where on that line?  And where does that line start
1289 	     in the buffer? */
1290 	  pos = inv_lbreaks[cursor_linenum];
1291 	  /* nleft == number of characters in the line buffer between the
1292 	     start of the line and the desired cursor position. */
1293 	  nleft = cpos_buffer_position - pos;
1294 
1295 	  /* NLEFT is now a number of characters in a buffer.  When in a
1296 	     multibyte locale, however, _rl_last_c_pos is an absolute cursor
1297 	     position that doesn't take invisible characters in the prompt
1298 	     into account.  We use a fudge factor to compensate. */
1299 
1300 	  /* Since _rl_backspace() doesn't know about invisible characters in
1301 	     the prompt, and there's no good way to tell it, we compensate for
1302 	     those characters here and call _rl_backspace() directly if
1303 	     necessary */
1304 	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
1305 	    {
1306 	      /* TX == new physical cursor position in multibyte locale. */
1307 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
1308 		tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
1309 	      else
1310 		tx = nleft;
1311 	      if (tx >= 0 && _rl_last_c_pos > tx)
1312 		{
1313 	          _rl_backspace (_rl_last_c_pos - tx);	/* XXX */
1314 	          _rl_last_c_pos = tx;
1315 		}
1316 	    }
1317 
1318 	  /* We need to note that in a multibyte locale we are dealing with
1319 	     _rl_last_c_pos as an absolute cursor position, but moving to a
1320 	     point specified by a buffer position (NLEFT) that doesn't take
1321 	     invisible characters into account. */
1322 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1323 	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1324 	  else if (nleft != _rl_last_c_pos)
1325 	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1326 	}
1327     }
1328   else				/* Do horizontal scrolling. Much simpler */
1329     {
1330 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
1331       int lmargin, ndisp, nleft, phys_c_pos, t;
1332 
1333       /* Always at top line. */
1334       _rl_last_v_pos = 0;
1335 
1336       /* Compute where in the buffer the displayed line should start.  This
1337 	 will be LMARGIN. */
1338 
1339       /* The number of characters that will be displayed before the cursor. */
1340       ndisp = cpos_buffer_position - wrap_offset;
1341       nleft  = prompt_visible_length + wrap_offset;
1342       /* Where the new cursor position will be on the screen.  This can be
1343 	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1344       phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
1345       t = _rl_screenwidth / 3;
1346 
1347       /* If the number of characters had already exceeded the screenwidth,
1348 	 last_lmargin will be > 0. */
1349 
1350       /* If the number of characters to be displayed is more than the screen
1351 	 width, compute the starting offset so that the cursor is about
1352 	 two-thirds of the way across the screen. */
1353       if (phys_c_pos > _rl_screenwidth - 2)
1354 	{
1355 	  lmargin = cpos_buffer_position - (2 * t);
1356 	  if (lmargin < 0)
1357 	    lmargin = 0;
1358 	  /* If the left margin would be in the middle of a prompt with
1359 	     invisible characters, don't display the prompt at all. */
1360 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
1361 	    lmargin = nleft;
1362 	}
1363       else if (ndisp < _rl_screenwidth - 2)		/* XXX - was -1 */
1364 	lmargin = 0;
1365       else if (phys_c_pos < 1)
1366 	{
1367 	  /* If we are moving back towards the beginning of the line and
1368 	     the last margin is no longer correct, compute a new one. */
1369 	  lmargin = ((cpos_buffer_position - 1) / t) * t;	/* XXX */
1370 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
1371 	    lmargin = nleft;
1372 	}
1373       else
1374 	lmargin = last_lmargin;
1375 
1376       displaying_prompt_first_line = lmargin < nleft;
1377 
1378       /* If the first character on the screen isn't the first character
1379 	 in the display line, indicate this with a special character. */
1380       if (lmargin > 0)
1381 	line[lmargin] = '<';
1382 
1383       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
1384 	 the whole line, indicate that with a special character at the
1385 	 right edge of the screen.  If LMARGIN is 0, we need to take the
1386 	 wrap offset into account. */
1387       t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1388       if (t > 0 && t < out)
1389 	line[t - 1] = '>';
1390 
1391       if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
1392 	{
1393 	  forced_display = 0;
1394 	  o_cpos = _rl_last_c_pos;
1395 	  cpos_adjusted = 0;
1396 	  update_line (&visible_line[last_lmargin],
1397 		       &invisible_line[lmargin],
1398 		       0,
1399 		       _rl_screenwidth + visible_wrap_offset,
1400 		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
1401 		       0);
1402 
1403 	  if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1404 		displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
1405 	    _rl_last_c_pos -= prompt_invis_chars_first_line;	/* XXX - was wrap_offset */
1406 
1407 	  /* If the visible new line is shorter than the old, but the number
1408 	     of invisible characters is greater, and we are at the end of
1409 	     the new line, we need to clear to eol. */
1410 	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
1411 	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
1412 	      (_rl_last_c_pos == out) && displaying_prompt_first_line &&
1413 	      t < visible_first_line_len)
1414 	    {
1415 	      nleft = _rl_screenwidth - t;
1416 	      _rl_clear_to_eol (nleft);
1417 	    }
1418 	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
1419 	  if (visible_first_line_len > _rl_screenwidth)
1420 	    visible_first_line_len = _rl_screenwidth;
1421 
1422 	  _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
1423 	  last_lmargin = lmargin;
1424 	}
1425     }
1426   fflush (rl_outstream);
1427 
1428   /* Swap visible and non-visible lines. */
1429   {
1430     struct line_state *vtemp = line_state_visible;
1431 
1432     line_state_visible = line_state_invisible;
1433     line_state_invisible = vtemp;
1434 
1435     rl_display_fixed = 0;
1436     /* If we are displaying on a single line, and last_lmargin is > 0, we
1437        are not displaying any invisible characters, so set visible_wrap_offset
1438        to 0. */
1439     if (_rl_horizontal_scroll_mode && last_lmargin)
1440       visible_wrap_offset = 0;
1441     else
1442       visible_wrap_offset = wrap_offset;
1443   }
1444 
1445   RL_UNSETSTATE (RL_STATE_REDISPLAYING);
1446   _rl_release_sigint ();
1447 }
1448 
1449 /* PWP: update_line() is based on finding the middle difference of each
1450    line on the screen; vis:
1451 
1452 			     /old first difference
1453 	/beginning of line   |	      /old last same       /old EOL
1454 	v		     v	      v		    v
1455 old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1456 new:	eddie> Oh, my little buggy says to me, as lurgid as
1457 	^		     ^	^			   ^
1458 	\beginning of line   |	\new last same	   \new end of line
1459 			     \new first difference
1460 
1461    All are character pointers for the sake of speed.  Special cases for
1462    no differences, as well as for end of line additions must be handled.
1463 
1464    Could be made even smarter, but this works well enough */
1465 static void
update_line(char * old,char * new,int current_line,int omax,int nmax,int inv_botlin)1466 update_line (char *old, char *new, int current_line, int omax, int nmax, int inv_botlin)
1467 {
1468   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
1469   int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
1470   int current_invis_chars;
1471   int col_lendiff, col_temp;
1472   int bytes_to_insert;
1473   int mb_cur_max = MB_CUR_MAX;
1474 #if defined (HANDLE_MULTIBYTE)
1475   mbstate_t ps_new, ps_old;
1476   int new_offset, old_offset;
1477 #endif
1478 
1479   /* If we're at the right edge of a terminal that supports xn, we're
1480      ready to wrap around, so do so.  This fixes problems with knowing
1481      the exact cursor position and cut-and-paste with certain terminal
1482      emulators.  In this calculation, TEMP is the physical screen
1483      position of the cursor. */
1484   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1485     temp = _rl_last_c_pos;
1486   else
1487     temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
1488   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1489 	&& _rl_last_v_pos == current_line - 1)
1490     {
1491       /* We're going to wrap around by writing the first character of NEW to
1492 	 the screen and dealing with changes to what's visible by modifying
1493 	 OLD to match it.  Complicated by the presence of multi-width
1494 	 characters at the end of the line or beginning of the new one. */
1495       /* old is always somewhere in visible_line; new is always somewhere in
1496          invisible_line.  These should always be null-terminated. */
1497 #if defined (HANDLE_MULTIBYTE)
1498       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1499 	{
1500 	  wchar_t wc;
1501 	  mbstate_t ps;
1502 	  int oldwidth, newwidth;
1503 	  int oldbytes, newbytes;
1504 	  size_t ret;
1505 
1506 	  /* This fixes only double-column characters, but if the wrapped
1507 	     character consumes more than three columns, spaces will be
1508 	     inserted in the string buffer. */
1509 	  /* XXX remember that we are working on the invisible line right now;
1510 	     we don't swap visible and invisible until just before rl_redisplay
1511 	     returns */
1512 	  /* This will remove the extra placeholder space we added with
1513 	     _rl_wrapped_multicolumn */
1514 	  if (current_line < line_state_invisible->wbsize && line_state_invisible->wrapped_line[current_line] > 0)
1515 	    _rl_clear_to_eol (line_state_invisible->wrapped_line[current_line]);
1516 
1517 	  /* 1. how many screen positions does first char in old consume? */
1518 	  memset (&ps, 0, sizeof (mbstate_t));
1519 	  ret = mbrtowc (&wc, old, mb_cur_max, &ps);
1520 	  oldbytes = ret;
1521 	  if (MB_INVALIDCH (ret))
1522 	    {
1523 	      oldwidth = 1;
1524 	      oldbytes = 1;
1525 	    }
1526 	  else if (MB_NULLWCH (ret))
1527 	    oldwidth = 0;
1528 	  else
1529 	    oldwidth = WCWIDTH (wc);
1530 	  if (oldwidth < 0)
1531 	    oldwidth = 1;
1532 
1533 	  /* 2. how many screen positions does the first char in new consume? */
1534 	  memset (&ps, 0, sizeof (mbstate_t));
1535 	  ret = mbrtowc (&wc, new, mb_cur_max, &ps);
1536 	  newbytes = ret;
1537 	  if (MB_INVALIDCH (ret))
1538 	    {
1539 	      newwidth = 1;
1540 	      newbytes = 1;
1541 	    }
1542 	  else if (MB_NULLWCH (ret))
1543 	    newwidth = 0;
1544 	  else
1545 	    newwidth = WCWIDTH (wc);
1546 	  if (newwidth < 0)
1547 	    newwidth = 1;
1548 
1549 	  /* 3. if the new width is less than the old width, we need to keep
1550 	     going in new until we have consumed at least that many screen
1551 	     positions, and figure out how many bytes that will take */
1552 	  while (newbytes < nmax && newwidth < oldwidth)
1553 	    {
1554 	      int t;
1555 
1556 	      ret = mbrtowc (&wc, new+newbytes, mb_cur_max, &ps);
1557 	      if (MB_INVALIDCH (ret))
1558 		{
1559 		  newwidth += 1;
1560 		  newbytes += 1;
1561 		}
1562 	      else if (MB_NULLWCH (ret))
1563 	        break;
1564 	      else
1565 		{
1566 		  t = WCWIDTH (wc);
1567 		  newwidth += (t >= 0) ? t : 1;
1568 		  newbytes += ret;
1569 		}
1570 	    }
1571 	  /* 4. If the new width is more than the old width, keep going in old
1572 	     until we have consumed exactly that many screen positions, and
1573 	     figure out how many bytes that will take.  This is an optimization */
1574 	  while (oldbytes < omax && oldwidth < newwidth)
1575 	    {
1576 	      int t;
1577 
1578 	      ret = mbrtowc (&wc, old+oldbytes, mb_cur_max, &ps);
1579 	      if (MB_INVALIDCH (ret))
1580 		{
1581 		  oldwidth += 1;
1582 		  oldbytes += 1;
1583 		}
1584 	      else if (MB_NULLWCH (ret))
1585 	        break;
1586 	      else
1587 		{
1588 		  t = WCWIDTH (wc);
1589 		  oldwidth += (t >= 0) ? t : 1;
1590 		  oldbytes += ret;
1591 		}
1592 	    }
1593 	  /* 5. write the first newbytes of new, which takes newwidth.  This is
1594 	     where the screen wrapping takes place, and we are now writing
1595 	     characters onto the new line. We need to fix up old so it
1596 	     accurately reflects what is on the screen after the
1597 	     _rl_output_some_chars below. */
1598 	  if (newwidth > 0)
1599 	    {
1600 	      int count, i, j;
1601 	      char *optr;
1602 
1603 	      _rl_output_some_chars (new, newbytes);
1604 	      _rl_last_c_pos = newwidth;
1605 	      _rl_last_v_pos++;
1606 
1607 	      /* 5a. If the number of screen positions doesn't match, punt
1608 		 and do a dumb update. */
1609 	      if (newwidth != oldwidth)
1610 		{
1611 		  ne = new + nmax;
1612 		  nd = newbytes;
1613 		  nfd = new + nd;
1614 		  goto dumb_update;
1615 		}
1616 	      if (oldbytes != 0 && newbytes != 0)
1617 		{
1618 		  /* We have written as many bytes from new as we need to
1619 		     consume the first character of old. Fix up `old' so it
1620 		     reflects the new screen contents.  We use +1 in the
1621 		     memmove call to copy the trailing NUL. */
1622 		  memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
1623 		  memcpy (old, new, newbytes);
1624 		  j = newbytes - oldbytes;
1625 
1626 		  omax += j;
1627 		  /* Fix up indices if we copy data from one line to another */
1628 		  for (i = current_line+1; i <= inv_botlin+1; i++)
1629 		    vis_lbreaks[i] += j;
1630 		}
1631 	    }
1632 	  else
1633 	    {
1634 	      putc (' ', rl_outstream);
1635 	      _rl_last_c_pos = 1;
1636 	      _rl_last_v_pos++;
1637 	      if (old[0] && new[0])
1638 		old[0] = new[0];
1639 	    }
1640 	}
1641       else
1642 #endif
1643 	{
1644 	  if (new[0])
1645 	    putc (new[0], rl_outstream);
1646 	  else
1647 	    putc (' ', rl_outstream);
1648 	  _rl_last_c_pos = 1;
1649 	  _rl_last_v_pos++;
1650 	  if (old[0] && new[0])
1651 	    old[0] = new[0];
1652 	}
1653     }
1654 
1655   /* Find first difference. */
1656 #if defined (HANDLE_MULTIBYTE)
1657   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1658     {
1659       /* See if the old line is a subset of the new line, so that the
1660 	 only change is adding characters. */
1661       temp = (omax < nmax) ? omax : nmax;
1662       if (memcmp (old, new, temp) == 0)		/* adding at the end */
1663 	{
1664 	  new_offset = old_offset = temp;
1665 	  ofd = old + temp;
1666 	  nfd = new + temp;
1667 	}
1668       else
1669 	{
1670 	  memset (&ps_new, 0, sizeof(mbstate_t));
1671 	  memset (&ps_old, 0, sizeof(mbstate_t));
1672 
1673 	  /* Are the old and new lines the same? */
1674 	  if (omax == nmax && STREQN (new, old, omax))
1675 	    {
1676 	      old_offset = omax;
1677 	      new_offset = nmax;
1678 	      ofd = old + omax;
1679 	      nfd = new + nmax;
1680 	    }
1681 	  else
1682 	    {
1683 	      /* Go through the line from the beginning and find the first
1684 		 difference. */
1685 	      new_offset = old_offset = 0;
1686 	      for (ofd = old, nfd = new;
1687 		    (ofd - old < omax) && *ofd &&
1688 		    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
1689 		{
1690 		  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1691 		  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1692 
1693 		  ofd = old + old_offset;
1694 		  nfd = new + new_offset;
1695 		}
1696 	    }
1697 	}
1698     }
1699   else
1700 #endif
1701   for (ofd = old, nfd = new;
1702        (ofd - old < omax) && *ofd && (*ofd == *nfd);
1703        ofd++, nfd++)
1704     ;
1705 
1706   /* Move to the end of the screen line.  ND and OD are used to keep track
1707      of the distance between ne and new and oe and old, respectively, to
1708      move a subtraction out of each loop. */
1709   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1710   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1711 
1712   /* If no difference, continue to next line. */
1713   if (ofd == oe && nfd == ne)
1714     return;
1715 
1716 #if defined (HANDLE_MULTIBYTE)
1717   if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
1718     {
1719       wchar_t wc;
1720       mbstate_t ps = { 0 };
1721       int t;
1722 
1723       /* If the first character in the difference is a zero-width character,
1724 	 assume it's a combining character and back one up so the two base
1725 	 characters no longer compare equivalently. */
1726       t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
1727       if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
1728 	{
1729 	  old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
1730 	  new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
1731 	  ofd = old + old_offset;	/* equal by definition */
1732 	  nfd = new + new_offset;
1733 	}
1734     }
1735 #endif
1736 
1737   wsatend = 1;			/* flag for trailing whitespace */
1738 
1739 #if defined (HANDLE_MULTIBYTE)
1740   /* Find the last character that is the same between the two lines.  This
1741      bounds the region that needs to change. */
1742   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1743     {
1744       ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1745       nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1746 
1747       while ((ols > ofd) && (nls > nfd))
1748 	{
1749 	  memset (&ps_old, 0, sizeof (mbstate_t));
1750 	  memset (&ps_new, 0, sizeof (mbstate_t));
1751 
1752 #if 0
1753 	  /* On advice from jir@yamato.ibm.com */
1754 	  _rl_adjust_point (old, ols - old, &ps_old);
1755 	  _rl_adjust_point (new, nls - new, &ps_new);
1756 #endif
1757 
1758 	  if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
1759 	    break;
1760 
1761 	  if (*ols == ' ')
1762 	    wsatend = 0;
1763 
1764 	  ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1765 	  nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1766 	}
1767     }
1768   else
1769     {
1770 #endif /* HANDLE_MULTIBYTE */
1771   ols = oe - 1;			/* find last same */
1772   nls = ne - 1;
1773   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
1774     {
1775       if (*ols != ' ')
1776 	wsatend = 0;
1777       ols--;
1778       nls--;
1779     }
1780 #if defined (HANDLE_MULTIBYTE)
1781     }
1782 #endif
1783 
1784   if (wsatend)
1785     {
1786       ols = oe;
1787       nls = ne;
1788     }
1789 #if defined (HANDLE_MULTIBYTE)
1790   /* This may not work for stateful encoding, but who cares?  To handle
1791      stateful encoding properly, we have to scan each string from the
1792      beginning and compare. */
1793   else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
1794 #else
1795   else if (*ols != *nls)
1796 #endif
1797     {
1798       if (*ols)			/* don't step past the NUL */
1799 	{
1800 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1801 	    ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
1802 	  else
1803 	    ols++;
1804 	}
1805       if (*nls)
1806 	{
1807 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1808 	    nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
1809 	  else
1810 	    nls++;
1811 	}
1812     }
1813 
1814   /* count of invisible characters in the current invisible line. */
1815   current_invis_chars = W_OFFSET (current_line, wrap_offset);
1816   if (_rl_last_v_pos != current_line)
1817     {
1818       _rl_move_vert (current_line);
1819       /* We have moved up to a new screen line.  This line may or may not have
1820          invisible characters on it, but we do our best to recalculate
1821          visible_wrap_offset based on what we know. */
1822       if (current_line == 0)
1823 	visible_wrap_offset = prompt_invis_chars_first_line;	/* XXX */
1824       if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
1825 	_rl_last_c_pos += visible_wrap_offset;
1826     }
1827 
1828   /* If this is the first line and there are invisible characters in the
1829      prompt string, and the prompt string has not changed, and the current
1830      cursor position is before the last invisible character in the prompt,
1831      and the index of the character to move to is past the end of the prompt
1832      string, then redraw the entire prompt string.  We can only do this
1833      reliably if the terminal supports a `cr' capability.
1834 
1835      This can also happen if the prompt string has changed, and the first
1836      difference in the line is in the middle of the prompt string, after a
1837      sequence of invisible characters (worst case) and before the end of
1838      the prompt.  In this case, we have to redraw the entire prompt string
1839      so that the entire sequence of invisible characters is drawn.  We need
1840      to handle the worst case, when the difference is after (or in the middle
1841      of) a sequence of invisible characters that changes the text color and
1842      before the sequence that restores the text color to normal.  Then we have
1843      to make sure that the lines still differ -- if they don't, we can
1844      return immediately.
1845 
1846      This is not an efficiency hack -- there is a problem with redrawing
1847      portions of the prompt string if they contain terminal escape
1848      sequences (like drawing the `unbold' sequence without a corresponding
1849      `bold') that manifests itself on certain terminals. */
1850 
1851   lendiff = local_prompt_len;
1852   if (lendiff > nmax)
1853     lendiff = nmax;
1854   od = ofd - old;	/* index of first difference in visible line */
1855   nd = nfd - new;	/* nd, od are buffer indexes */
1856   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1857       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1858       (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
1859 		((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
1860     {
1861 #if defined (__MSDOS__)
1862       putc ('\r', rl_outstream);
1863 #else
1864       tputs (_rl_term_cr, 1, _rl_output_character_function);
1865 #endif
1866       if (modmark)
1867 	_rl_output_some_chars ("*", 1);
1868       _rl_output_some_chars (local_prompt, lendiff);
1869       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1870 	{
1871 	  /* We take wrap_offset into account here so we can pass correct
1872 	     information to _rl_move_cursor_relative. */
1873 	  _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
1874 	  cpos_adjusted = 1;
1875 	}
1876       else
1877 	_rl_last_c_pos = lendiff + modmark;
1878 
1879       /* Now if we have printed the prompt string because the first difference
1880 	 was within the prompt, see if we need to recompute where the lines
1881 	 differ.  Check whether where we are now is past the last place where
1882 	 the old and new lines are the same and short-circuit now if we are. */
1883       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible) &&
1884           omax == nmax &&
1885 	  lendiff > (ols-old) && lendiff > (nls-new))
1886 	return;
1887 
1888       /* XXX - we need to fix up our calculations if we are now past the
1889 	 old ofd/nfd and the prompt length (or line length) has changed.
1890 	 We punt on the problem and do a dumb update.  We'd like to be able
1891 	 to just output the prompt from the beginning of the line up to the
1892 	 first difference, but you don't know the number of invisible
1893 	 characters in that case.
1894 	 This needs a lot of work to be efficient. */
1895       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
1896 	{
1897 	  nfd = new + lendiff;	/* number of characters we output above */
1898 	  nd = lendiff;
1899 
1900 	  /* Do a dumb update and return */
1901 dumb_update:
1902 	  temp = ne - nfd;
1903 	  if (temp > 0)
1904 	    {
1905 	      _rl_output_some_chars (nfd, temp);
1906 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
1907 		{
1908 		  _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
1909 		  /* Need to adjust here based on wrap_offset. Guess that if
1910 		     this is the line containing the last line of the prompt
1911 		     we need to adjust by
1912 		     	wrap_offset-prompt_invis_chars_first_line
1913 		     on the assumption that this is the number of invisible
1914 		     characters in the last line of the prompt. */
1915 		  if (wrap_offset > prompt_invis_chars_first_line &&
1916 		      current_line == prompt_last_screen_line &&
1917 		      prompt_physical_chars > _rl_screenwidth &&
1918 		      _rl_horizontal_scroll_mode == 0)
1919 		    {
1920 		      _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
1921 		      cpos_adjusted = 1;
1922 		    }
1923 		}
1924 	      else
1925 		_rl_last_c_pos += temp;
1926 	    }
1927 	  if (nmax < omax)
1928 	    goto clear_rest_of_line;	/* XXX */
1929 	  else
1930 	    return;
1931 	}
1932     }
1933 
1934   o_cpos = _rl_last_c_pos;
1935 
1936   /* When this function returns, _rl_last_c_pos is correct, and an absolute
1937      cursor position in multibyte mode, but a buffer index when not in a
1938      multibyte locale. */
1939   _rl_move_cursor_relative (od, old);
1940 
1941 #if defined (HANDLE_MULTIBYTE)
1942   /* We need to indicate that the cursor position is correct in the presence of
1943      invisible characters in the prompt string.  Let's see if setting this when
1944      we make sure we're at the end of the drawn prompt string works. */
1945   if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
1946       (_rl_last_c_pos > 0 || o_cpos > 0) &&
1947       _rl_last_c_pos == prompt_physical_chars)
1948     cpos_adjusted = 1;
1949 #endif
1950 
1951   /* if (len (new) > len (old))
1952      lendiff == difference in buffer (bytes)
1953      col_lendiff == difference on screen (columns)
1954      When not using multibyte characters, these are equal */
1955   lendiff = (nls - nfd) - (ols - ofd);
1956   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1957     col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
1958   else
1959     col_lendiff = lendiff;
1960 
1961   /* If we are changing the number of invisible characters in a line, and
1962      the spot of first difference is before the end of the invisible chars,
1963      lendiff needs to be adjusted. */
1964   if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */
1965       current_invis_chars != visible_wrap_offset)
1966     {
1967       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1968 	{
1969 	  lendiff += visible_wrap_offset - current_invis_chars;
1970 	  col_lendiff += visible_wrap_offset - current_invis_chars;
1971 	}
1972       else
1973 	{
1974 	  lendiff += visible_wrap_offset - current_invis_chars;
1975 	  col_lendiff = lendiff;
1976 	}
1977     }
1978 
1979   /* We use temp as a count of the number of bytes from the first difference
1980      to the end of the new line.  col_temp is the corresponding number of
1981      screen columns.  A `dumb' update moves to the spot of first difference
1982      and writes TEMP bytes. */
1983   /* Insert (diff (len (old), len (new)) ch. */
1984   temp = ne - nfd;
1985   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1986     col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
1987   else
1988     col_temp = temp;
1989 
1990   /* how many bytes from the new line buffer to write to the display */
1991   bytes_to_insert = nls - nfd;
1992 
1993   /* col_lendiff > 0 if we are adding characters to the line */
1994   if (col_lendiff > 0)	/* XXX - was lendiff */
1995     {
1996       /* Non-zero if we're increasing the number of lines. */
1997       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1998 
1999       /* If col_lendiff is > 0, implying that the new string takes up more
2000 	 screen real estate than the old, but lendiff is < 0, meaning that it
2001 	 takes fewer bytes, we need to just output the characters starting
2002 	 from the first difference.  These will overwrite what is on the
2003 	 display, so there's no reason to do a smart update.  This can really
2004 	 only happen in a multibyte environment. */
2005       if (lendiff < 0)
2006 	{
2007 	  _rl_output_some_chars (nfd, temp);
2008 	  _rl_last_c_pos += col_temp;	/* XXX - was _rl_col_width (nfd, 0, temp, 1); */
2009 	  /* If nfd begins before any invisible characters in the prompt,
2010 	     adjust _rl_last_c_pos to account for wrap_offset and set
2011 	     cpos_adjusted to let the caller know. */
2012 	  if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2013 	    {
2014 	      _rl_last_c_pos -= wrap_offset;	/* XXX - prompt_invis_chars_first_line? */
2015 	      cpos_adjusted = 1;
2016 	    }
2017 	  return;
2018 	}
2019       /* Sometimes it is cheaper to print the characters rather than
2020 	 use the terminal's capabilities.  If we're growing the number
2021 	 of lines, make sure we actually cause the new line to wrap
2022 	 around on auto-wrapping terminals. */
2023       else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
2024 	{
2025 	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
2026 	     _rl_horizontal_scroll_mode == 1, inserting the characters with
2027 	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
2028 	     invisible characters.  We need to just draw them. */
2029 	  /* The same thing happens if we're trying to draw before the last
2030 	     invisible character in the prompt string or we're increasing the
2031 	     number of invisible characters in the line and we're not drawing
2032 	     the entire prompt string. */
2033 	  if (*ols && ((_rl_horizontal_scroll_mode &&
2034 			_rl_last_c_pos == 0 &&
2035 			lendiff > prompt_visible_length &&
2036 			current_invis_chars > 0) == 0) &&
2037 		      (((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2038 		        current_line == 0 && wrap_offset &&
2039 		        ((nfd - new) <= prompt_last_invisible) &&
2040 		        (col_lendiff < prompt_visible_length)) == 0) &&
2041 		      (visible_wrap_offset >= current_invis_chars))
2042 	    {
2043 	      open_some_spaces (col_lendiff);
2044 	      _rl_output_some_chars (nfd, bytes_to_insert);
2045 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
2046 		_rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2047 	      else
2048 		_rl_last_c_pos += bytes_to_insert;
2049 	    }
2050 	  else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
2051 	    {
2052 	      /* At the end of a line the characters do not have to
2053 		 be "inserted".  They can just be placed on the screen. */
2054 	      _rl_output_some_chars (nfd, temp);
2055 	      _rl_last_c_pos += col_temp;
2056 	      return;
2057 	    }
2058 	  else	/* just write from first difference to end of new line */
2059 	    {
2060 	      _rl_output_some_chars (nfd, temp);
2061 	      _rl_last_c_pos += col_temp;
2062 	      /* If nfd begins before the last invisible character in the
2063 		 prompt, adjust _rl_last_c_pos to account for wrap_offset
2064 		 and set cpos_adjusted to let the caller know. */
2065 	      if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2066 		{
2067 		  _rl_last_c_pos -= wrap_offset;	/* XXX - prompt_invis_chars_first_line? */
2068 		  cpos_adjusted = 1;
2069 		}
2070 	      return;
2071 	    }
2072 
2073 	  if (bytes_to_insert > lendiff)
2074 	    {
2075 	      /* If nfd begins before the last invisible character in the
2076 		 prompt, adjust _rl_last_c_pos to account for wrap_offset
2077 		 and set cpos_adjusted to let the caller know. */
2078 	      if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2079 		{
2080 		  _rl_last_c_pos -= wrap_offset;	/* XXX - prompt_invis_chars_first_line? */
2081 		  cpos_adjusted = 1;
2082 		}
2083 	    }
2084 	}
2085       else
2086 	{
2087 	  /* cannot insert chars, write to EOL */
2088 	  _rl_output_some_chars (nfd, temp);
2089 	  _rl_last_c_pos += col_temp;
2090 	  /* If we're in a multibyte locale and were before the last invisible
2091 	     char in the current line (which implies we just output some invisible
2092 	     characters) we need to adjust _rl_last_c_pos, since it represents
2093 	     a physical character position. */
2094 	  /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a
2095 	     crude attempt to compute how far into the new line buffer we are.
2096 	     It doesn't work well in the face of multibyte characters and needs
2097 	     to be rethought. XXX */
2098 	  if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2099 		current_line == prompt_last_screen_line && wrap_offset &&
2100 		displaying_prompt_first_line &&
2101 		wrap_offset != prompt_invis_chars_first_line &&
2102 		((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
2103 	    {
2104 	      _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
2105 	      cpos_adjusted = 1;
2106 	    }
2107 	}
2108     }
2109   else				/* Delete characters from line. */
2110     {
2111       /* If possible and inexpensive to use terminal deletion, then do so. */
2112       if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
2113 	{
2114 	  /* If all we're doing is erasing the invisible characters in the
2115 	     prompt string, don't bother.  It screws up the assumptions
2116 	     about what's on the screen. */
2117 	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
2118 	      displaying_prompt_first_line &&
2119 	      -lendiff == visible_wrap_offset)
2120 	    col_lendiff = 0;
2121 
2122 	  /* If we have moved lmargin and we're shrinking the line, we've
2123 	     already moved the cursor to the first character of the new line,
2124 	     so deleting -col_lendiff characters will mess up the cursor
2125 	     position calculation */
2126 	  if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
2127 		col_lendiff && _rl_last_c_pos < -col_lendiff)
2128 	    col_lendiff = 0;
2129 
2130 	  if (col_lendiff)
2131 	    delete_chars (-col_lendiff); /* delete (diff) characters */
2132 
2133 	  /* Copy (new) chars to screen from first diff to last match,
2134 	     overwriting what is there. */
2135 	  if (bytes_to_insert > 0)
2136 	    {
2137 	      /* If nfd begins at the prompt, or before the invisible
2138 		 characters in the prompt, we need to adjust _rl_last_c_pos
2139 		 in a multibyte locale to account for the wrap offset and
2140 		 set cpos_adjusted accordingly. */
2141 	      _rl_output_some_chars (nfd, bytes_to_insert);
2142 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
2143 		{
2144 		  _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2145 		  if (current_line == 0 && wrap_offset &&
2146 			displaying_prompt_first_line &&
2147 			_rl_last_c_pos >= wrap_offset &&	/* XXX was > */
2148 			((nfd - new) <= prompt_last_invisible))
2149 		    {
2150 		      _rl_last_c_pos -= wrap_offset;	/* XXX - prompt_invis_chars_first_line? */
2151 		      cpos_adjusted = 1;
2152 		    }
2153 
2154 #if 1
2155 #ifdef HANDLE_MULTIBYTE
2156 		  /* If we write a non-space into the last screen column,
2157 		     remove the note that we added a space to compensate for
2158 		     a multibyte double-width character that didn't fit, since
2159 		     it's only valid for what was previously there. */
2160 		  /* XXX - watch this */
2161 		  if (_rl_last_c_pos == _rl_screenwidth &&
2162 			line_state_invisible->wrapped_line[current_line+1] &&
2163 			nfd[bytes_to_insert-1] != ' ')
2164 		    line_state_invisible->wrapped_line[current_line+1] = 0;
2165 #endif
2166 #endif
2167 		}
2168 	      else
2169 		_rl_last_c_pos += bytes_to_insert;
2170 
2171 	      /* XXX - we only want to do this if we are at the end of the line
2172 		 so we move there with _rl_move_cursor_relative */
2173 	      if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
2174 		{
2175 		  _rl_move_cursor_relative (ne-new, new);
2176 		  goto clear_rest_of_line;
2177 		}
2178 	    }
2179 	}
2180       /* Otherwise, print over the existing material. */
2181       else
2182 	{
2183 	  if (temp > 0)
2184 	    {
2185 	      /* If nfd begins at the prompt, or before the invisible
2186 		 characters in the prompt, we need to adjust _rl_last_c_pos
2187 		 in a multibyte locale to account for the wrap offset and
2188 		 set cpos_adjusted accordingly. */
2189 	      _rl_output_some_chars (nfd, temp);
2190 	      _rl_last_c_pos += col_temp;		/* XXX */
2191 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
2192 		{
2193 		  if (current_line == 0 && wrap_offset &&
2194 			displaying_prompt_first_line &&
2195 			_rl_last_c_pos > wrap_offset &&
2196 			((nfd - new) <= prompt_last_invisible))
2197 		    {
2198 		      _rl_last_c_pos -= wrap_offset;	/* XXX - prompt_invis_chars_first_line? */
2199 		      cpos_adjusted = 1;
2200 		    }
2201 		}
2202 	    }
2203 clear_rest_of_line:
2204 	  lendiff = (oe - old) - (ne - new);
2205 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
2206 	    col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
2207 	  else
2208 	    col_lendiff = lendiff;
2209 
2210 	  /* If we've already printed over the entire width of the screen,
2211 	     including the old material, then col_lendiff doesn't matter and
2212 	     space_to_eol will insert too many spaces.  XXX - maybe we should
2213 	     adjust col_lendiff based on the difference between _rl_last_c_pos
2214 	     and _rl_screenwidth */
2215 	  if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
2216 	    {
2217 	      if (_rl_term_autowrap && current_line < inv_botlin)
2218 		space_to_eol (col_lendiff);
2219 	      else
2220 		_rl_clear_to_eol (col_lendiff);
2221 	    }
2222 	}
2223     }
2224 }
2225 
2226 /* Tell the update routines that we have moved onto a new (empty) line. */
2227 int
rl_on_new_line(void)2228 rl_on_new_line (void)
2229 {
2230   if (visible_line)
2231     visible_line[0] = '\0';
2232 
2233   _rl_last_c_pos = _rl_last_v_pos = 0;
2234   _rl_vis_botlin = last_lmargin = 0;
2235   if (vis_lbreaks)
2236     vis_lbreaks[0] = vis_lbreaks[1] = 0;
2237   visible_wrap_offset = 0;
2238   return 0;
2239 }
2240 
2241 /* Clear all screen lines occupied by the current readline line buffer
2242    (visible line) */
2243 int
rl_clear_visible_line(void)2244 rl_clear_visible_line (void)
2245 {
2246   int curr_line;
2247 
2248   /* Make sure we move to column 0 so we clear the entire line */
2249 #if defined (__MSDOS__)
2250   putc ('\r', rl_outstream);
2251 #else
2252   tputs (_rl_term_cr, 1, _rl_output_character_function);
2253 #endif
2254   _rl_last_c_pos = 0;
2255 
2256   /* Move to the last screen line of the current visible line */
2257   _rl_move_vert (_rl_vis_botlin);
2258 
2259   /* And erase screen lines going up to line 0 (first visible line) */
2260   for (curr_line = _rl_last_v_pos; curr_line >= 0; curr_line--)
2261     {
2262       _rl_move_vert (curr_line);
2263       _rl_clear_to_eol (0);
2264     }
2265 
2266   return 0;
2267 }
2268 
2269 /* Tell the update routines that we have moved onto a new line with the
2270    prompt already displayed.  Code originally from the version of readline
2271    distributed with CLISP.  rl_expand_prompt must have already been called
2272    (explicitly or implicitly).  This still doesn't work exactly right; it
2273    should use expand_prompt() */
2274 int
rl_on_new_line_with_prompt(void)2275 rl_on_new_line_with_prompt (void)
2276 {
2277   int prompt_size, i, l, real_screenwidth, newlines;
2278   char *prompt_last_line, *lprompt;
2279 
2280   /* Initialize visible_line and invisible_line to ensure that they can hold
2281      the already-displayed prompt. */
2282   prompt_size = strlen (rl_prompt) + 1;
2283   init_line_structures (prompt_size);
2284 
2285   /* Make sure the line structures hold the already-displayed prompt for
2286      redisplay. */
2287   lprompt = local_prompt ? local_prompt : rl_prompt;
2288   strcpy (visible_line, lprompt);
2289   strcpy (invisible_line, lprompt);
2290 
2291   /* If the prompt contains newlines, take the last tail. */
2292   prompt_last_line = strrchr (rl_prompt, '\n');
2293   if (!prompt_last_line)
2294     prompt_last_line = rl_prompt;
2295 
2296   l = strlen (prompt_last_line);
2297   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2298     _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1);	/* XXX */
2299   else
2300     _rl_last_c_pos = l;
2301 
2302   /* Dissect prompt_last_line into screen lines. Note that here we have
2303      to use the real screenwidth. Readline's notion of screenwidth might be
2304      one less, see terminal.c. */
2305   real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
2306   _rl_last_v_pos = l / real_screenwidth;
2307   /* If the prompt length is a multiple of real_screenwidth, we don't know
2308      whether the cursor is at the end of the last line, or already at the
2309      beginning of the next line. Output a newline just to be safe. */
2310   if (l > 0 && (l % real_screenwidth) == 0)
2311     _rl_output_some_chars ("\n", 1);
2312   last_lmargin = 0;
2313 
2314   newlines = 0; i = 0;
2315   while (i <= l)
2316     {
2317       _rl_vis_botlin = newlines;
2318       vis_lbreaks[newlines++] = i;
2319       i += real_screenwidth;
2320     }
2321   vis_lbreaks[newlines] = l;
2322   visible_wrap_offset = 0;
2323 
2324   rl_display_prompt = rl_prompt;	/* XXX - make sure it's set */
2325 
2326   return 0;
2327 }
2328 
2329 /* Actually update the display, period. */
2330 int
rl_forced_update_display(void)2331 rl_forced_update_display (void)
2332 {
2333   register char *temp;
2334 
2335   if (visible_line)
2336     {
2337       temp = visible_line;
2338       while (*temp)
2339 	*temp++ = '\0';
2340     }
2341   rl_on_new_line ();
2342   forced_display++;
2343   (*rl_redisplay_function) ();
2344   return 0;
2345 }
2346 
2347 /* Redraw only the last line of a multi-line prompt. */
2348 void
rl_redraw_prompt_last_line(void)2349 rl_redraw_prompt_last_line (void)
2350 {
2351   char *t;
2352 
2353   t = strrchr (rl_display_prompt, '\n');
2354   if (t)
2355     redraw_prompt (++t);
2356   else
2357     rl_forced_update_display ();
2358 }
2359 
2360 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
2361    (Well, when we don't have multibyte characters, _rl_last_c_pos is a
2362    buffer index.)
2363    DATA is the contents of the screen line of interest; i.e., where
2364    the movement is being done.
2365    DATA is always the visible line or the invisible line */
2366 void
_rl_move_cursor_relative(int new,const char * data)2367 _rl_move_cursor_relative (int new, const char *data)
2368 {
2369   register int i;
2370   int woff;			/* number of invisible chars on current line */
2371   int cpos, dpos;		/* current and desired cursor positions */
2372   int adjust;
2373   int in_invisline;
2374   int mb_cur_max = MB_CUR_MAX;
2375 
2376   woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
2377   cpos = _rl_last_c_pos;
2378 
2379   if (cpos == 0 && cpos == new)
2380     return;
2381 
2382 #if defined (HANDLE_MULTIBYTE)
2383   /* If we have multibyte characters, NEW is indexed by the buffer point in
2384      a multibyte string, but _rl_last_c_pos is the display position.  In
2385      this case, NEW's display position is not obvious and must be
2386      calculated.  We need to account for invisible characters in this line,
2387      as long as we are past them and they are counted by _rl_col_width. */
2388   if (mb_cur_max > 1 && rl_byte_oriented == 0)
2389     {
2390       adjust = 1;
2391       /* Try to short-circuit common cases and eliminate a bunch of multibyte
2392 	 character function calls. */
2393       /* 1.  prompt string */
2394       if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2395 	{
2396 	  dpos = prompt_physical_chars;
2397 	  cpos_adjusted = 1;
2398 	  adjust = 0;
2399 	}
2400       /* 2.  prompt_string + line contents */
2401       else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2402 	{
2403 	  dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2404 	  cpos_adjusted = 1;
2405 	  adjust = 0;
2406 	}
2407       else
2408         dpos = _rl_col_width (data, 0, new, 1);
2409 
2410       if (displaying_prompt_first_line == 0)
2411 	adjust = 0;
2412 
2413       /* yet another special case: printing the last line of a prompt with
2414 	 multibyte characters and invisible characters whose printable length
2415 	 exceeds the screen width with the last invisible character
2416 	 (prompt_last_invisible) in the last line.  IN_INVISLINE is the
2417 	 offset of DATA in invisible_line */
2418       in_invisline = 0;
2419       if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
2420 	in_invisline = data - invisible_line;
2421 
2422       /* Use NEW when comparing against the last invisible character in the
2423 	 prompt string, since they're both buffer indices and DPOS is a
2424 	 desired display position. */
2425       /* NEW is relative to the current displayed line, while
2426 	 PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line.
2427 	 Need a way to reconcile these two variables by turning NEW into a
2428 	 buffer position relative to the start of the line */
2429       if (adjust && ((new > prompt_last_invisible) ||		/* XXX - don't use woff here */
2430 		     (new+in_invisline > prompt_last_invisible) ||	/* invisible line */
2431 	  (prompt_physical_chars >= _rl_screenwidth &&		/* visible line */
2432 	   _rl_last_v_pos == prompt_last_screen_line &&
2433 	   wrap_offset >= woff && dpos >= woff &&
2434 	   new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset))))
2435 	   /* XXX last comparison might need to be >= */
2436 	{
2437 	  dpos -= woff;
2438 	  /* Since this will be assigned to _rl_last_c_pos at the end (more
2439 	     precisely, _rl_last_c_pos == dpos when this function returns),
2440 	     let the caller know. */
2441 	  cpos_adjusted = 1;
2442 	}
2443     }
2444   else
2445 #endif
2446     dpos = new;
2447 
2448   /* If we don't have to do anything, then return. */
2449   if (cpos == dpos)
2450     return;
2451 
2452   /* It may be faster to output a CR, and then move forwards instead
2453      of moving backwards. */
2454   /* i == current physical cursor position. */
2455 #if defined (HANDLE_MULTIBYTE)
2456   if (mb_cur_max > 1 && rl_byte_oriented == 0)
2457     i = _rl_last_c_pos;
2458   else
2459 #endif
2460   i = _rl_last_c_pos - woff;
2461   if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
2462       (_rl_term_autowrap && i == _rl_screenwidth))
2463     {
2464 #if defined (__MSDOS__)
2465       putc ('\r', rl_outstream);
2466 #else
2467       tputs (_rl_term_cr, 1, _rl_output_character_function);
2468 #endif /* !__MSDOS__ */
2469       cpos = _rl_last_c_pos = 0;
2470     }
2471 
2472   if (cpos < dpos)
2473     {
2474       /* Move the cursor forward.  We do it by printing the command
2475 	 to move the cursor forward if there is one, else print that
2476 	 portion of the output buffer again.  Which is cheaper? */
2477 
2478       /* The above comment is left here for posterity.  It is faster
2479 	 to print one character (non-control) than to print a control
2480 	 sequence telling the terminal to move forward one character.
2481 	 That kind of control is for people who don't know what the
2482 	 data is underneath the cursor. */
2483 
2484       /* However, we need a handle on where the current display position is
2485 	 in the buffer for the immediately preceding comment to be true.
2486 	 In multibyte locales, we don't currently have that info available.
2487 	 Without it, we don't know where the data we have to display begins
2488 	 in the buffer and we have to go back to the beginning of the screen
2489 	 line.  In this case, we can use the terminal sequence to move forward
2490 	 if it's available. */
2491       if (mb_cur_max > 1 && rl_byte_oriented == 0)
2492 	{
2493 	  if (_rl_term_forward_char)
2494 	    {
2495 	      for (i = cpos; i < dpos; i++)
2496 	        tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2497 	    }
2498 	  else
2499 	    {
2500 	      tputs (_rl_term_cr, 1, _rl_output_character_function);
2501 	      for (i = 0; i < new; i++)
2502 		putc (data[i], rl_outstream);
2503 	    }
2504 	}
2505       else
2506 	for (i = cpos; i < new; i++)
2507 	  putc (data[i], rl_outstream);
2508     }
2509 
2510 #if defined (HANDLE_MULTIBYTE)
2511   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2512      The byte length of the string is probably bigger than the column width
2513      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2514      display point is less than _rl_last_c_pos. */
2515 #endif
2516   else if (cpos > dpos)
2517     _rl_backspace (cpos - dpos);
2518 
2519   _rl_last_c_pos = dpos;
2520 }
2521 
2522 /* PWP: move the cursor up or down. */
2523 void
_rl_move_vert(int to)2524 _rl_move_vert (int to)
2525 {
2526   register int delta, i;
2527 
2528   if (_rl_last_v_pos == to || to > _rl_screenheight)
2529     return;
2530 
2531   if ((delta = to - _rl_last_v_pos) > 0)
2532     {
2533       for (i = 0; i < delta; i++)
2534 	putc ('\n', rl_outstream);
2535 #if defined (__MSDOS__)
2536       putc ('\r', rl_outstream);
2537 #else
2538       tputs (_rl_term_cr, 1, _rl_output_character_function);
2539 #endif
2540       _rl_last_c_pos = 0;
2541     }
2542   else
2543     {			/* delta < 0 */
2544 #ifdef __DJGPP__
2545       int row, col;
2546 
2547       fflush (rl_outstream);
2548       ScreenGetCursor (&row, &col);
2549       ScreenSetCursor (row + delta, col);
2550       i = -delta;
2551 #else
2552       if (_rl_term_up && *_rl_term_up)
2553 	for (i = 0; i < -delta; i++)
2554 	  tputs (_rl_term_up, 1, _rl_output_character_function);
2555 #endif /* !__DJGPP__ */
2556     }
2557 
2558   _rl_last_v_pos = to;		/* Now TO is here */
2559 }
2560 
2561 /* Physically print C on rl_outstream.  This is for functions which know
2562    how to optimize the display.  Return the number of characters output. */
2563 int
rl_show_char(int c)2564 rl_show_char (int c)
2565 {
2566   int n = 1;
2567   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2568     {
2569       fprintf (rl_outstream, "M-");
2570       n += 2;
2571       c = UNMETA (c);
2572     }
2573 
2574 #if defined (DISPLAY_TABS)
2575   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
2576 #else
2577   if (CTRL_CHAR (c) || c == RUBOUT)
2578 #endif /* !DISPLAY_TABS */
2579     {
2580       fprintf (rl_outstream, "C-");
2581       n += 2;
2582       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
2583     }
2584 
2585   putc (c, rl_outstream);
2586   fflush (rl_outstream);
2587   return n;
2588 }
2589 
2590 int
rl_character_len(int c,int pos)2591 rl_character_len (int c, int pos)
2592 {
2593   unsigned char uc;
2594 
2595   uc = (unsigned char)c;
2596 
2597   if (META_CHAR (uc))
2598     return ((_rl_output_meta_chars == 0) ? 4 : 1);
2599 
2600   if (uc == '\t')
2601     {
2602 #if defined (DISPLAY_TABS)
2603       return (((pos | 7) + 1) - pos);
2604 #else
2605       return (2);
2606 #endif /* !DISPLAY_TABS */
2607     }
2608 
2609   if (CTRL_CHAR (c) || c == RUBOUT)
2610     return (2);
2611 
2612   return ((ISPRINT (uc)) ? 1 : 2);
2613 }
2614 /* How to print things in the "echo-area".  The prompt is treated as a
2615    mini-modeline. */
2616 static int msg_saved_prompt = 0;
2617 
2618 #if defined (USE_VARARGS)
2619 int
2620 #if defined (PREFER_STDARG)
rl_message(const char * format,...)2621 rl_message (const char *format, ...)
2622 #else
2623 rl_message (va_alist)
2624      va_dcl
2625 #endif
2626 {
2627   va_list args;
2628 #if defined (PREFER_VARARGS)
2629   char *format;
2630 #endif
2631 #if defined (HAVE_VSNPRINTF)
2632   int bneed;
2633 #endif
2634 
2635 #if defined (PREFER_STDARG)
2636   va_start (args, format);
2637 #else
2638   va_start (args);
2639   format = va_arg (args, char *);
2640 #endif
2641 
2642   if (msg_buf == 0)
2643     msg_buf = xmalloc (msg_bufsiz = 128);
2644 
2645 #if defined (HAVE_VSNPRINTF)
2646   bneed = vsnprintf (msg_buf, msg_bufsiz, format, args);
2647   if (bneed >= msg_bufsiz - 1)
2648     {
2649       msg_bufsiz = bneed + 1;
2650       msg_buf = xrealloc (msg_buf, msg_bufsiz);
2651       va_end (args);
2652 
2653 #if defined (PREFER_STDARG)
2654       va_start (args, format);
2655 #else
2656       va_start (args);
2657       format = va_arg (args, char *);
2658 #endif
2659       vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2660     }
2661 #else
2662   vsprintf (msg_buf, format, args);
2663   msg_buf[msg_bufsiz - 1] = '\0';	/* overflow? */
2664 #endif
2665   va_end (args);
2666 
2667   if (saved_local_prompt == 0)
2668     {
2669       rl_save_prompt ();
2670       msg_saved_prompt = 1;
2671     }
2672   else if (local_prompt != saved_local_prompt)
2673     {
2674       FREE (local_prompt);
2675       FREE (local_prompt_prefix);
2676       local_prompt = (char *)NULL;
2677     }
2678   rl_display_prompt = msg_buf;
2679   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
2680 					    &prompt_last_invisible,
2681 					    &prompt_invis_chars_first_line,
2682 					    &prompt_physical_chars);
2683   local_prompt_prefix = (char *)NULL;
2684   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2685   (*rl_redisplay_function) ();
2686 
2687   return 0;
2688 }
2689 #else /* !USE_VARARGS */
2690 int
rl_message(format,arg1,arg2)2691 rl_message (format, arg1, arg2)
2692      char *format;
2693 {
2694   if (msg_buf == 0)
2695     msg_buf = xmalloc (msg_bufsiz = 128);
2696 
2697   sprintf (msg_buf, format, arg1, arg2);
2698   msg_buf[msg_bufsiz - 1] = '\0';	/* overflow? */
2699 
2700   rl_display_prompt = msg_buf;
2701   if (saved_local_prompt == 0)
2702     {
2703       rl_save_prompt ();
2704       msg_saved_prompt = 1;
2705     }
2706   else if (local_prompt != saved_local_prompt)
2707     {
2708       FREE (local_prompt);
2709       FREE (local_prompt_prefix);
2710       local_prompt = (char *)NULL;
2711     }
2712   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
2713 					    &prompt_last_invisible,
2714 					    &prompt_invis_chars_first_line,
2715 					    &prompt_physical_chars);
2716   local_prompt_prefix = (char *)NULL;
2717   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2718   (*rl_redisplay_function) ();
2719 
2720   return 0;
2721 }
2722 #endif /* !USE_VARARGS */
2723 
2724 /* How to clear things from the "echo-area". */
2725 int
rl_clear_message(void)2726 rl_clear_message (void)
2727 {
2728   rl_display_prompt = rl_prompt;
2729   if (msg_saved_prompt)
2730     {
2731       rl_restore_prompt ();
2732       msg_saved_prompt = 0;
2733     }
2734   (*rl_redisplay_function) ();
2735   return 0;
2736 }
2737 
2738 int
rl_reset_line_state(void)2739 rl_reset_line_state (void)
2740 {
2741   rl_on_new_line ();
2742 
2743   rl_display_prompt = rl_prompt ? rl_prompt : "";
2744   forced_display = 1;
2745   return 0;
2746 }
2747 
2748 /* Save all of the variables associated with the prompt and its display. Most
2749    of the complexity is dealing with the invisible characters in the prompt
2750    string and where they are. There are enough of these that I should consider
2751    a struct. */
2752 void
rl_save_prompt(void)2753 rl_save_prompt (void)
2754 {
2755   saved_local_prompt = local_prompt;
2756   saved_local_prefix = local_prompt_prefix;
2757   saved_prefix_length = prompt_prefix_length;
2758   saved_local_length = local_prompt_len;
2759   saved_last_invisible = prompt_last_invisible;
2760   saved_visible_length = prompt_visible_length;
2761   saved_invis_chars_first_line = prompt_invis_chars_first_line;
2762   saved_physical_chars = prompt_physical_chars;
2763   saved_local_prompt_newlines = local_prompt_newlines;
2764 
2765   local_prompt = local_prompt_prefix = (char *)0;
2766   local_prompt_len = 0;
2767   local_prompt_newlines = (int *)0;
2768 
2769   prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
2770   prompt_invis_chars_first_line = prompt_physical_chars = 0;
2771 }
2772 
2773 void
rl_restore_prompt(void)2774 rl_restore_prompt (void)
2775 {
2776   FREE (local_prompt);
2777   FREE (local_prompt_prefix);
2778   FREE (local_prompt_newlines);
2779 
2780   local_prompt = saved_local_prompt;
2781   local_prompt_prefix = saved_local_prefix;
2782   local_prompt_len = saved_local_length;
2783   local_prompt_newlines = saved_local_prompt_newlines;
2784 
2785   prompt_prefix_length = saved_prefix_length;
2786   prompt_last_invisible = saved_last_invisible;
2787   prompt_visible_length = saved_visible_length;
2788   prompt_invis_chars_first_line = saved_invis_chars_first_line;
2789   prompt_physical_chars = saved_physical_chars;
2790 
2791   /* can test saved_local_prompt to see if prompt info has been saved. */
2792   saved_local_prompt = saved_local_prefix = (char *)0;
2793   saved_local_length = 0;
2794   saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2795   saved_invis_chars_first_line = saved_physical_chars = 0;
2796   saved_local_prompt_newlines = 0;
2797 }
2798 
2799 char *
_rl_make_prompt_for_search(int pchar)2800 _rl_make_prompt_for_search (int pchar)
2801 {
2802   int len;
2803   char *pmt, *p;
2804 
2805   rl_save_prompt ();
2806 
2807   /* We've saved the prompt, and can do anything with the various prompt
2808      strings we need before they're restored.  We want the unexpanded
2809      portion of the prompt string after any final newline. */
2810   p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2811   if (p == 0)
2812     {
2813       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
2814       pmt = (char *)xmalloc (len + 2);
2815       if (len)
2816 	strcpy (pmt, rl_prompt);
2817       pmt[len] = pchar;
2818       pmt[len+1] = '\0';
2819     }
2820   else
2821     {
2822       p++;
2823       len = strlen (p);
2824       pmt = (char *)xmalloc (len + 2);
2825       if (len)
2826 	strcpy (pmt, p);
2827       pmt[len] = pchar;
2828       pmt[len+1] = '\0';
2829     }
2830 
2831   /* will be overwritten by expand_prompt, called from rl_message */
2832   prompt_physical_chars = saved_physical_chars + 1;
2833   return pmt;
2834 }
2835 
2836 /* Quick redisplay hack when erasing characters at the end of the line. */
2837 void
_rl_erase_at_end_of_line(int l)2838 _rl_erase_at_end_of_line (int l)
2839 {
2840   register int i;
2841 
2842   _rl_backspace (l);
2843   for (i = 0; i < l; i++)
2844     putc (' ', rl_outstream);
2845   _rl_backspace (l);
2846   for (i = 0; i < l; i++)
2847     visible_line[--_rl_last_c_pos] = '\0';
2848   rl_display_fixed++;
2849 }
2850 
2851 /* Clear to the end of the line.  COUNT is the minimum
2852    number of character spaces to clear, but we use a terminal escape
2853    sequence if available. */
2854 void
_rl_clear_to_eol(int count)2855 _rl_clear_to_eol (int count)
2856 {
2857 #ifndef __MSDOS__
2858   if (_rl_term_clreol)
2859     tputs (_rl_term_clreol, 1, _rl_output_character_function);
2860   else
2861 #endif
2862     if (count)
2863       space_to_eol (count);
2864 }
2865 
2866 /* Clear to the end of the line using spaces.  COUNT is the minimum
2867    number of character spaces to clear, */
2868 static void
space_to_eol(int count)2869 space_to_eol (int count)
2870 {
2871   register int i;
2872 
2873   for (i = 0; i < count; i++)
2874     putc (' ', rl_outstream);
2875 
2876   _rl_last_c_pos += count;
2877 }
2878 
2879 void
_rl_clear_screen(void)2880 _rl_clear_screen (void)
2881 {
2882 #if defined (__DJGPP__)
2883   ScreenClear ();
2884   ScreenSetCursor (0, 0);
2885 #else
2886   if (_rl_term_clrpag)
2887     tputs (_rl_term_clrpag, 1, _rl_output_character_function);
2888   else
2889     rl_crlf ();
2890 #endif /* __DJGPP__ */
2891 }
2892 
2893 /* Insert COUNT characters from STRING to the output stream at column COL. */
2894 static void
insert_some_chars(char * string,int count,int col)2895 insert_some_chars (char *string, int count, int col)
2896 {
2897   open_some_spaces (col);
2898   _rl_output_some_chars (string, count);
2899 }
2900 
2901 /* Insert COL spaces, keeping the cursor at the same position.  We follow the
2902    ncurses documentation and use either im/ei with explicit spaces, or IC/ic
2903    by itself.  We assume there will either be ei or we don't need to use it. */
2904 static void
open_some_spaces(int col)2905 open_some_spaces (int col)
2906 {
2907 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
2908   char *buffer;
2909   register int i;
2910 
2911   /* If IC is defined, then we do not have to "enter" insert mode. */
2912   if (_rl_term_IC)
2913     {
2914       buffer = tgoto (_rl_term_IC, 0, col);
2915       tputs (buffer, 1, _rl_output_character_function);
2916     }
2917   else if (_rl_term_im && *_rl_term_im)
2918     {
2919       tputs (_rl_term_im, 1, _rl_output_character_function);
2920       /* just output the desired number of spaces */
2921       for (i = col; i--; )
2922 	_rl_output_character_function (' ');
2923       /* If there is a string to turn off insert mode, use it now. */
2924       if (_rl_term_ei && *_rl_term_ei)
2925 	tputs (_rl_term_ei, 1, _rl_output_character_function);
2926       /* and move back the right number of spaces */
2927       _rl_backspace (col);
2928     }
2929   else if (_rl_term_ic && *_rl_term_ic)
2930     {
2931       /* If there is a special command for inserting characters, then
2932 	 use that first to open up the space. */
2933       for (i = col; i--; )
2934 	tputs (_rl_term_ic, 1, _rl_output_character_function);
2935     }
2936 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
2937 }
2938 
2939 /* Delete COUNT characters from the display line. */
2940 static void
delete_chars(int count)2941 delete_chars (int count)
2942 {
2943   if (count > _rl_screenwidth)	/* XXX */
2944     return;
2945 
2946 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
2947   if (_rl_term_DC && *_rl_term_DC)
2948     {
2949       char *buffer;
2950       buffer = tgoto (_rl_term_DC, count, count);
2951       tputs (buffer, count, _rl_output_character_function);
2952     }
2953   else
2954     {
2955       if (_rl_term_dc && *_rl_term_dc)
2956 	while (count--)
2957 	  tputs (_rl_term_dc, 1, _rl_output_character_function);
2958     }
2959 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
2960 }
2961 
2962 void
_rl_update_final(void)2963 _rl_update_final (void)
2964 {
2965   int full_lines, woff, botline_length;
2966 
2967   full_lines = 0;
2968   /* If the cursor is the only thing on an otherwise-blank last line,
2969      compensate so we don't print an extra CRLF. */
2970   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
2971 	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
2972     {
2973       _rl_vis_botlin--;
2974       full_lines = 1;
2975     }
2976   _rl_move_vert (_rl_vis_botlin);
2977   woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
2978   botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
2979   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
2980   if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
2981     {
2982       char *last_line;
2983 
2984       /* LAST_LINE includes invisible characters, so if you want to get the
2985 	 last character of the first line, you have to take WOFF into account.
2986 	 This needs to be done for both calls to _rl_move_cursor_relative,
2987 	 which takes a buffer position as the first argument, and any direct
2988 	 subscripts of LAST_LINE. */
2989       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
2990       cpos_buffer_position = -1;	/* don't know where we are in buffer */
2991       _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line);	/* XXX */
2992       _rl_clear_to_eol (0);
2993       putc (last_line[_rl_screenwidth - 1 + woff], rl_outstream);
2994     }
2995   _rl_vis_botlin = 0;
2996   if (botline_length > 0 || _rl_last_c_pos > 0)
2997     rl_crlf ();
2998   fflush (rl_outstream);
2999   rl_display_fixed++;
3000 }
3001 
3002 /* Move to the start of the current line. */
3003 static void
cr(void)3004 cr (void)
3005 {
3006   if (_rl_term_cr)
3007     {
3008 #if defined (__MSDOS__)
3009       putc ('\r', rl_outstream);
3010 #else
3011       tputs (_rl_term_cr, 1, _rl_output_character_function);
3012 #endif
3013       _rl_last_c_pos = 0;
3014     }
3015 }
3016 
3017 /* Redraw the last line of a multi-line prompt that may possibly contain
3018    terminal escape sequences.  Called with the cursor at column 0 of the
3019    line to draw the prompt on. */
3020 static void
redraw_prompt(char * t)3021 redraw_prompt (char *t)
3022 {
3023   char *oldp;
3024 
3025   oldp = rl_display_prompt;
3026   rl_save_prompt ();
3027 
3028   rl_display_prompt = t;
3029   local_prompt = expand_prompt (t, PMT_MULTILINE,
3030 				   &prompt_visible_length,
3031 				   &prompt_last_invisible,
3032 				   &prompt_invis_chars_first_line,
3033 				   &prompt_physical_chars);
3034   local_prompt_prefix = (char *)NULL;
3035   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
3036 
3037   rl_forced_update_display ();
3038 
3039   rl_display_prompt = oldp;
3040   rl_restore_prompt();
3041 }
3042 
3043 /* Redisplay the current line after a SIGWINCH is received. */
3044 void
_rl_redisplay_after_sigwinch(void)3045 _rl_redisplay_after_sigwinch (void)
3046 {
3047   char *t;
3048 
3049   /* Clear the last line (assuming that the screen size change will result in
3050      either more or fewer characters on that line only) and put the cursor at
3051      column 0.  Make sure the right thing happens if we have wrapped to a new
3052      screen line. */
3053   if (_rl_term_cr)
3054     {
3055       _rl_move_vert (_rl_vis_botlin);
3056 
3057 #if defined (__MSDOS__)
3058       putc ('\r', rl_outstream);
3059 #else
3060       tputs (_rl_term_cr, 1, _rl_output_character_function);
3061 #endif
3062       _rl_last_c_pos = 0;
3063 #if defined (__MSDOS__)
3064       space_to_eol (_rl_screenwidth);
3065       putc ('\r', rl_outstream);
3066 #else
3067       if (_rl_term_clreol)
3068 	tputs (_rl_term_clreol, 1, _rl_output_character_function);
3069       else
3070 	{
3071 	  space_to_eol (_rl_screenwidth);
3072 	  tputs (_rl_term_cr, 1, _rl_output_character_function);
3073 	}
3074 #endif
3075       if (_rl_last_v_pos > 0)
3076 	_rl_move_vert (0);
3077     }
3078   else
3079     rl_crlf ();
3080 
3081   /* Redraw only the last line of a multi-line prompt. */
3082   t = strrchr (rl_display_prompt, '\n');
3083   if (t)
3084     redraw_prompt (++t);
3085   else
3086     rl_forced_update_display ();
3087 }
3088 
3089 void
_rl_clean_up_for_exit(void)3090 _rl_clean_up_for_exit (void)
3091 {
3092   if (_rl_echoing_p)
3093     {
3094       if (_rl_vis_botlin > 0)	/* minor optimization plus bug fix */
3095 	_rl_move_vert (_rl_vis_botlin);
3096       _rl_vis_botlin = 0;
3097       fflush (rl_outstream);
3098       rl_restart_output (1, 0);
3099     }
3100 }
3101 
3102 void
_rl_erase_entire_line(void)3103 _rl_erase_entire_line (void)
3104 {
3105   cr ();
3106   _rl_clear_to_eol (0);
3107   cr ();
3108   fflush (rl_outstream);
3109 }
3110 
3111 void
_rl_ttyflush(void)3112 _rl_ttyflush (void)
3113 {
3114   fflush (rl_outstream);
3115 }
3116 
3117 /* return the `current display line' of the cursor -- the number of lines to
3118    move up to get to the first screen line of the current readline line. */
3119 int
_rl_current_display_line(void)3120 _rl_current_display_line (void)
3121 {
3122   int ret, nleft;
3123 
3124   /* Find out whether or not there might be invisible characters in the
3125      editing buffer. */
3126   if (rl_display_prompt == rl_prompt)
3127     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
3128   else
3129     nleft = _rl_last_c_pos - _rl_screenwidth;
3130 
3131   if (nleft > 0)
3132     ret = 1 + nleft / _rl_screenwidth;
3133   else
3134     ret = 0;
3135 
3136   return ret;
3137 }
3138 
3139 #if defined (HANDLE_MULTIBYTE)
3140 /* Calculate the number of screen columns occupied by STR from START to END.
3141    In the case of multibyte characters with stateful encoding, we have to
3142    scan from the beginning of the string to take the state into account. */
3143 static int
_rl_col_width(const char * str,int start,int end,int flags)3144 _rl_col_width (const char *str, int start, int end, int flags)
3145 {
3146   wchar_t wc;
3147   mbstate_t ps;
3148   int tmp, point, width, max;
3149 
3150   if (end <= start)
3151     return 0;
3152   if (MB_CUR_MAX == 1 || rl_byte_oriented)
3153     /* this can happen in some cases where it's inconvenient to check */
3154     return (end - start);
3155 
3156   memset (&ps, 0, sizeof (mbstate_t));
3157 
3158   point = 0;
3159   max = end;
3160 
3161   /* Try to short-circuit common cases.  The adjustment to remove wrap_offset
3162      is done by the caller. */
3163   /* 1.  prompt string */
3164   if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
3165     return (prompt_physical_chars + wrap_offset);
3166   /* 2.  prompt string + line contents */
3167   else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
3168     {
3169       tmp = prompt_physical_chars + wrap_offset;
3170       /* XXX - try to call ourselves recursively with non-prompt portion */
3171       tmp += _rl_col_width (str, local_prompt_len, end, flags);
3172       return (tmp);
3173     }
3174 
3175   while (point < start)
3176     {
3177       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3178 	{
3179 	  memset (&ps, 0, sizeof (mbstate_t));
3180 	  tmp = 1;
3181 	}
3182       else
3183 	tmp = mbrlen (str + point, max, &ps);
3184       if (MB_INVALIDCH ((size_t)tmp))
3185 	{
3186 	  /* In this case, the bytes are invalid or too short to compose a
3187 	     multibyte character, so we assume that the first byte represents
3188 	     a single character. */
3189 	  point++;
3190 	  max--;
3191 
3192 	  /* Clear the state of the byte sequence, because in this case the
3193 	     effect of mbstate is undefined. */
3194 	  memset (&ps, 0, sizeof (mbstate_t));
3195 	}
3196       else if (MB_NULLWCH (tmp))
3197 	break;		/* Found '\0' */
3198       else
3199 	{
3200 	  point += tmp;
3201 	  max -= tmp;
3202 	}
3203     }
3204 
3205   /* If START is not a byte that starts a character, then POINT will be
3206      greater than START.  In this case, assume that (POINT - START) gives
3207      a byte count that is the number of columns of difference. */
3208   width = point - start;
3209 
3210   while (point < end)
3211     {
3212       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3213 	{
3214 	  tmp = 1;
3215 	  wc = (wchar_t) str[point];
3216 	}
3217       else
3218 	tmp = mbrtowc (&wc, str + point, max, &ps);
3219       if (MB_INVALIDCH ((size_t)tmp))
3220 	{
3221 	  /* In this case, the bytes are invalid or too short to compose a
3222 	     multibyte character, so we assume that the first byte represents
3223 	     a single character. */
3224 	  point++;
3225 	  max--;
3226 
3227 	  /* and assume that the byte occupies a single column. */
3228 	  width++;
3229 
3230 	  /* Clear the state of the byte sequence, because in this case the
3231 	     effect of mbstate is undefined. */
3232 	  memset (&ps, 0, sizeof (mbstate_t));
3233 	}
3234       else if (MB_NULLWCH (tmp))
3235 	break;			/* Found '\0' */
3236       else
3237 	{
3238 	  point += tmp;
3239 	  max -= tmp;
3240 	  tmp = WCWIDTH(wc);
3241 	  width += (tmp >= 0) ? tmp : 1;
3242 	}
3243     }
3244 
3245   width += point - end;
3246 
3247   return width;
3248 }
3249 #endif /* HANDLE_MULTIBYTE */
3250