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