xref: /netbsd-src/external/gpl3/gdb/dist/readline/readline/display.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
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   lpos = prompt_physical_chars + modmark;
936 
937 #if defined (HANDLE_MULTIBYTE)
938   memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
939   num = 0;
940 #endif
941 
942   /* prompt_invis_chars_first_line is the number of invisible characters (bytes)
943      in the first physical line of the prompt.
944      wrap_offset - prompt_invis_chars_first_line is usually the number of
945      invis chars on the second (or, more generally, last) line. */
946 
947   /* This is zero-based, used to set the newlines */
948   prompt_lines_estimate = lpos / _rl_screenwidth;
949 
950   /* what if lpos is already >= _rl_screenwidth before we start drawing the
951      contents of the command line? */
952   if (lpos >= _rl_screenwidth)
953     {
954       temp = 0;
955 
956       /* first copy the linebreaks array we computed in expand_prompt */
957       while (local_prompt_newlines[newlines+1] != -1)
958 	{
959 	  temp = local_prompt_newlines[newlines+1];
960 	  inv_lbreaks[++newlines] = temp;
961 	}
962 
963       /* Now set lpos from the last newline */
964       if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
965         lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
966       else
967         lpos -= (_rl_screenwidth * newlines);
968     }
969 
970   prompt_last_screen_line = newlines;
971 
972   /* Draw the rest of the line (after the prompt) into invisible_line, keeping
973      track of where the cursor is (cpos_buffer_position), the number of the
974      line containing the cursor (lb_linenum), the last line number (lb_botlin
975      and inv_botlin).
976      It maintains an array of line breaks for display (inv_lbreaks).
977      This handles expanding tabs for display and displaying meta characters. */
978   lb_linenum = 0;
979 #if defined (HANDLE_MULTIBYTE)
980   in = 0;
981   if (mb_cur_max > 1 && rl_byte_oriented == 0)
982     {
983       memset (&ps, 0, sizeof (mbstate_t));
984       if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[0]))
985 	{
986 	  wc = (wchar_t)rl_line_buffer[0];
987 	  wc_bytes = 1;
988 	}
989       else
990 	wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
991     }
992   else
993     wc_bytes = 1;
994   while (in < rl_end)
995 #else
996   for (in = 0; in < rl_end; in++)
997 #endif
998     {
999       if (in == hl_begin)
1000 	cur_face = FACE_STANDOUT;
1001       else if (in == hl_end)
1002 	cur_face = FACE_NORMAL;
1003 
1004       c = (unsigned char)rl_line_buffer[in];
1005 
1006 #if defined (HANDLE_MULTIBYTE)
1007       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1008 	{
1009 	  if (MB_INVALIDCH (wc_bytes))
1010 	    {
1011 	      /* Byte sequence is invalid or shortened.  Assume that the
1012 	         first byte represents a character. */
1013 	      wc_bytes = 1;
1014 	      /* Assume that a character occupies a single column. */
1015 	      wc_width = 1;
1016 	      memset (&ps, 0, sizeof (mbstate_t));
1017 	    }
1018 	  else if (MB_NULLWCH (wc_bytes))
1019 	    break;			/* Found '\0' */
1020 	  else
1021 	    {
1022 	      temp = WCWIDTH (wc);
1023 	      wc_width = (temp >= 0) ? temp : 1;
1024 	    }
1025 	}
1026 #endif
1027 
1028       if (in == rl_point)
1029 	{
1030 	  cpos_buffer_position = out;
1031 	  lb_linenum = newlines;
1032 	}
1033 
1034 #if defined (HANDLE_MULTIBYTE)
1035       if (META_CHAR (c) && _rl_output_meta_chars == 0)	/* XXX - clean up */
1036 #else
1037       if (META_CHAR (c))
1038 #endif
1039 	{
1040 	  if (_rl_output_meta_chars == 0)
1041 	    {
1042 	      char obuf[5];
1043 	      int olen;
1044 
1045 	      olen = sprintf (obuf, "\\%o", c);
1046 
1047 	      if (lpos + olen >= _rl_screenwidth)
1048 		{
1049 		  temp = _rl_screenwidth - lpos;
1050 		  CHECK_INV_LBREAKS ();
1051 		  inv_lbreaks[++newlines] = out + temp;
1052 #if defined (HANDLE_MULTIBYTE)
1053 		  line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1054 #endif
1055 		  lpos = olen - temp;
1056 		}
1057 	      else
1058 		lpos += olen;
1059 
1060 	      for (temp = 0; temp < olen; temp++)
1061 		{
1062 		  invis_addc (&out, obuf[temp], cur_face);
1063 		  CHECK_LPOS ();
1064 		}
1065 	    }
1066 	  else
1067 	    {
1068 	      invis_addc (&out, c, cur_face);
1069 	      CHECK_LPOS();
1070 	    }
1071 	}
1072 #if defined (DISPLAY_TABS)
1073       else if (c == '\t')
1074 	{
1075 	  register int newout;
1076 
1077 	  newout = out + 8 - lpos % 8;
1078 	  temp = newout - out;
1079 	  if (lpos + temp >= _rl_screenwidth)
1080 	    {
1081 	      register int temp2;
1082 	      temp2 = _rl_screenwidth - lpos;
1083 	      CHECK_INV_LBREAKS ();
1084 	      inv_lbreaks[++newlines] = out + temp2;
1085 #if defined (HANDLE_MULTIBYTE)
1086 	      line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1087 #endif
1088 	      lpos = temp - temp2;
1089 	      while (out < newout)
1090 		invis_addc (&out, ' ', cur_face);
1091 	    }
1092 	  else
1093 	    {
1094 	      while (out < newout)
1095 		invis_addc (&out, ' ', cur_face);
1096 	      lpos += temp;
1097 	    }
1098 	}
1099 #endif
1100       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1101 	{
1102 	  invis_addc (&out, '\0', cur_face);
1103 	  CHECK_INV_LBREAKS ();
1104 	  inv_lbreaks[++newlines] = out;
1105 #if defined (HANDLE_MULTIBYTE)
1106 	  line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1107 #endif
1108 	  lpos = 0;
1109 	}
1110       else if (CTRL_CHAR (c) || c == RUBOUT)
1111 	{
1112 	  invis_addc (&out, '^', cur_face);
1113 	  CHECK_LPOS();
1114 	  invis_addc (&out, CTRL_CHAR (c) ? UNCTRL (c) : '?', cur_face);
1115 	  CHECK_LPOS();
1116 	}
1117       else
1118 	{
1119 #if defined (HANDLE_MULTIBYTE)
1120 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1121 	    {
1122 	      register int i;
1123 
1124 	      _rl_wrapped_multicolumn = 0;
1125 
1126 	      if (_rl_screenwidth < lpos + wc_width)
1127 		for (i = lpos; i < _rl_screenwidth; i++)
1128 		  {
1129 		    /* The space will be removed in update_line() */
1130 		    invis_addc (&out, ' ', cur_face);
1131 		    _rl_wrapped_multicolumn++;
1132 		    CHECK_LPOS();
1133 		  }
1134 	      if (in == rl_point)
1135 		{
1136 		  cpos_buffer_position = out;
1137 		  lb_linenum = newlines;
1138 		}
1139 	      for (i = in; i < in+wc_bytes; i++)
1140 		invis_addc (&out, rl_line_buffer[i], cur_face);
1141 	      for (i = 0; i < wc_width; i++)
1142 		CHECK_LPOS();
1143 	    }
1144 	  else
1145 	    {
1146 	      invis_addc (&out, c, cur_face);
1147 	      CHECK_LPOS();
1148 	    }
1149 #else
1150 	  invis_addc (&out, c, cur_face);
1151 	  CHECK_LPOS();
1152 #endif
1153 	}
1154 
1155 #if defined (HANDLE_MULTIBYTE)
1156       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1157 	{
1158 	  in += wc_bytes;
1159 	  if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[in]))
1160 	    {
1161 	      wc = (wchar_t)rl_line_buffer[in];
1162 	      wc_bytes = 1;
1163 	      memset (&ps, 0, sizeof (mbstate_t));	/* re-init state */
1164 	    }
1165 	  else
1166 	    wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
1167 	}
1168       else
1169         in++;
1170 #endif
1171     }
1172   invis_nul (&out);
1173   line_totbytes = out;
1174   if (cpos_buffer_position < 0)
1175     {
1176       cpos_buffer_position = out;
1177       lb_linenum = newlines;
1178     }
1179 
1180   /* If we are switching from one line to multiple wrapped lines, we don't
1181      want to do a dumb update (or we want to make it smarter). */
1182   if (_rl_quick_redisplay && newlines > 0)
1183     _rl_quick_redisplay = 0;
1184 
1185   inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
1186   CHECK_INV_LBREAKS ();
1187   inv_lbreaks[newlines+1] = out;
1188 #if defined (HANDLE_MULTIBYTE)
1189   /* This should be 0 anyway */
1190   line_state_invisible->wrapped_line[newlines+1] = _rl_wrapped_multicolumn;
1191 #endif
1192   cursor_linenum = lb_linenum;
1193 
1194   /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
1195      CURSOR_LINENUM == line number where the cursor should be placed. */
1196 
1197   /* PWP: now is when things get a bit hairy.  The visible and invisible
1198      line buffers are really multiple lines, which would wrap every
1199      (screenwidth - 1) characters.  Go through each in turn, finding
1200      the changed region and updating it.  The line order is top to bottom. */
1201 
1202   /* If we can move the cursor up and down, then use multiple lines,
1203      otherwise, let long lines display in a single terminal line, and
1204      horizontally scroll it. */
1205   displaying_prompt_first_line = 1;
1206   if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1207     {
1208       int nleft, pos, changed_screen_line, tx;
1209 
1210       if (!rl_display_fixed || forced_display)
1211 	{
1212 	  forced_display = 0;
1213 
1214 	  /* If we have more than a screenful of material to display, then
1215 	     only display a screenful.  We should display the last screen,
1216 	     not the first.  */
1217 	  if (out >= _rl_screenchars)
1218 	    {
1219 #if defined (HANDLE_MULTIBYTE)
1220 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
1221 		out = _rl_find_prev_mbchar (invisible_line, _rl_screenchars, MB_FIND_ANY);
1222 	      else
1223 #endif
1224 		out = _rl_screenchars - 1;
1225 	    }
1226 
1227 	  /* The first line is at character position 0 in the buffer.  The
1228 	     second and subsequent lines start at inv_lbreaks[N], offset by
1229 	     OFFSET (which has already been calculated above).  */
1230 
1231 #define INVIS_FIRST()	(prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
1232 #define WRAP_OFFSET(line, offset)  ((line == 0) \
1233 					? (offset ? INVIS_FIRST() : 0) \
1234 					: ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
1235 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
1236 #define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
1237 #define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
1238 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
1239 #define VIS_FACE(line) (vis_face + vis_lbreaks[line])
1240 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
1241 #define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
1242 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
1243 #define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
1244 
1245 #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
1246 			_rl_last_c_pos != o_cpos && \
1247 			_rl_last_c_pos > wrap_offset && \
1248 			o_cpos < prompt_last_invisible)
1249 
1250 
1251 	  /* We don't want to highlight anything that's going to be off the top
1252 	     of the display; if the current line takes up more than an entire
1253 	    screen, just mark the lines that won't be displayed as having a
1254 	    `normal' face.
1255 	    It's imperfect, but better than display corruption. */
1256 	  if (rl_mark_active_p () && inv_botlin > _rl_screenheight)
1257 	    {
1258 	      int extra;
1259 
1260 	      extra = inv_botlin - _rl_screenheight;
1261 	      for (linenum = 0; linenum <= extra; linenum++)
1262 		norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
1263 	    }
1264 
1265 	  /* For each line in the buffer, do the updating display. */
1266 	  for (linenum = 0; linenum <= inv_botlin; linenum++)
1267 	    {
1268 	      /* This can lead us astray if we execute a program that changes
1269 		 the locale from a non-multibyte to a multibyte one. */
1270 	      o_cpos = _rl_last_c_pos;
1271 	      cpos_adjusted = 0;
1272 	      update_line (VIS_LINE(linenum), VIS_LINE_FACE(linenum),
1273 			   INV_LINE(linenum), INV_LINE_FACE(linenum),
1274 			   linenum,
1275 			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
1276 
1277 	      /* update_line potentially changes _rl_last_c_pos, but doesn't
1278 		 take invisible characters into account, since _rl_last_c_pos
1279 		 is an absolute cursor position in a multibyte locale.  We
1280 		 choose to (mostly) compensate for that here, rather than
1281 		 change update_line itself.  There are several cases in which
1282 		 update_line adjusts _rl_last_c_pos itself (so it can pass
1283 		 _rl_move_cursor_relative accurate values); it communicates
1284 		 this back by setting cpos_adjusted.  If we assume that
1285 		 _rl_last_c_pos is correct (an absolute cursor position) each
1286 		 time update_line is called, then we can assume in our
1287 		 calculations that o_cpos does not need to be adjusted by
1288 		 wrap_offset. */
1289 	      if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
1290 		_rl_last_c_pos -= prompt_invis_chars_first_line;	/* XXX - was wrap_offset */
1291 	      else if (cpos_adjusted == 0 &&
1292 			linenum == prompt_last_screen_line &&
1293 			prompt_physical_chars > _rl_screenwidth &&
1294 			(mb_cur_max > 1 && rl_byte_oriented == 0) &&
1295 			_rl_last_c_pos != o_cpos &&
1296 			_rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))	/* XXX - rethink this last one */
1297 		/* This assumes that all the invisible characters are split
1298 		   between the first and last lines of the prompt, if the
1299 		   prompt consumes more than two lines. It's usually right */
1300 		/* XXX - not sure this is ever executed */
1301 		_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
1302 
1303 	      /* If this is the line with the prompt, we might need to
1304 		 compensate for invisible characters in the new line. Do
1305 		 this only if there is not more than one new line (which
1306 		 implies that we completely overwrite the old visible line)
1307 		 and the new line is shorter than the old.  Make sure we are
1308 		 at the end of the new line before clearing. */
1309 	      if (linenum == 0 &&
1310 		  inv_botlin == 0 && _rl_last_c_pos == out &&
1311 		  (wrap_offset > visible_wrap_offset) &&
1312 		  (_rl_last_c_pos < visible_first_line_len))
1313 		{
1314 		  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1315 		    nleft = _rl_screenwidth - _rl_last_c_pos;
1316 		  else
1317 		    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1318 		  if (nleft)
1319 		    _rl_clear_to_eol (nleft);
1320 		}
1321 #if 0
1322 	      /* This segment is intended to handle the case where the old
1323 		 visible prompt has invisible characters and the new line
1324 		 to be displayed needs to clear the rest of the old characters
1325 		 out (e.g., when printing the i-search prompt): in general,
1326 		 the case of the new line being shorter than the old.  We need
1327 		 to be at the end of the new line and the old line needs to be
1328 		 longer than the current cursor position. It's not perfect,
1329 		 since it uses the byte length of the first line, but this will
1330 		 at worst result in some extra clear-to-end-of-lines. We can't
1331 		 use the prompt length variables because they may not
1332 		 correspond to the visible line (see printing the i-search
1333 		 prompt above). The tests for differing numbers of invisible
1334 		 characters may not matter and can probably be removed. */
1335 	      else if (linenum == 0 &&
1336 		       linenum == prompt_last_screen_line &&
1337 		       _rl_last_c_pos == out &&
1338 		       _rl_last_c_pos < visible_first_line_len &&
1339 		       visible_wrap_offset &&
1340 		       visible_wrap_offset != wrap_offset)
1341 		{
1342 		  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1343 		    nleft = _rl_screenwidth - _rl_last_c_pos;
1344 		  else
1345 		    nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1346 		  if (nleft)
1347 		    _rl_clear_to_eol (nleft);
1348 		}
1349 #endif
1350 
1351 	      /* Since the new first line is now visible, save its length. */
1352 	      if (linenum == 0)
1353 		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
1354 	    }
1355 
1356 	  /* We may have deleted some lines.  If so, clear the left over
1357 	     blank ones at the bottom out. */
1358 	  if (_rl_vis_botlin > inv_botlin)
1359 	    {
1360 	      char *tt;
1361 	      for (; linenum <= _rl_vis_botlin; linenum++)
1362 		{
1363 		  tt = VIS_CHARS (linenum);
1364 		  _rl_move_vert (linenum);
1365 		  _rl_move_cursor_relative (0, tt, VIS_FACE(linenum));
1366 		  _rl_clear_to_eol
1367 		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
1368 		}
1369 	    }
1370 	  _rl_vis_botlin = inv_botlin;
1371 
1372 	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
1373 	     different screen line during this redisplay. */
1374 	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
1375 	  if (changed_screen_line)
1376 	    {
1377 	      _rl_move_vert (cursor_linenum);
1378 	      /* If we moved up to the line with the prompt using _rl_term_up,
1379 		 the physical cursor position on the screen stays the same,
1380 		 but the buffer position needs to be adjusted to account
1381 		 for invisible characters. */
1382 	      if ((mb_cur_max == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
1383 		_rl_last_c_pos += wrap_offset;
1384 	    }
1385 
1386 	  /* Now we move the cursor to where it needs to be.  First, make
1387 	     sure we are on the correct line (cursor_linenum). */
1388 
1389 	  /* We have to reprint the prompt if it contains invisible
1390 	     characters, since it's not generally OK to just reprint
1391 	     the characters from the current cursor position.  But we
1392 	     only need to reprint it if the cursor is before the last
1393 	     invisible character in the prompt string. */
1394 	  /* XXX - why not use local_prompt_len? */
1395 	  nleft = prompt_visible_length + wrap_offset;
1396 	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1397 	      _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1398 	    {
1399 	      _rl_cr ();
1400 	      if (modmark)
1401 		_rl_output_some_chars ("*", 1);
1402 
1403 	      _rl_output_some_chars (local_prompt, nleft);
1404 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
1405 		_rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
1406 	      else
1407 		_rl_last_c_pos = nleft + modmark;
1408 	    }
1409 
1410 	  /* Where on that line?  And where does that line start
1411 	     in the buffer? */
1412 	  pos = inv_lbreaks[cursor_linenum];
1413 	  /* nleft == number of characters (bytes) in the line buffer between
1414 	     the start of the line and the desired cursor position. */
1415 	  nleft = cpos_buffer_position - pos;
1416 
1417 	  /* NLEFT is now a number of characters in a buffer.  When in a
1418 	     multibyte locale, however, _rl_last_c_pos is an absolute cursor
1419 	     position that doesn't take invisible characters in the prompt
1420 	     into account.  We use a fudge factor to compensate. */
1421 
1422 	  /* Since _rl_backspace() doesn't know about invisible characters in
1423 	     the prompt, and there's no good way to tell it, we compensate for
1424 	     those characters here and call _rl_backspace() directly if
1425 	     necessary */
1426 	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
1427 	    {
1428 	      /* TX == new physical cursor position in multibyte locale. */
1429 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
1430 		tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
1431 	      else
1432 		tx = nleft;
1433 	      if (tx >= 0 && _rl_last_c_pos > tx)
1434 		{
1435 	          _rl_backspace (_rl_last_c_pos - tx);	/* XXX */
1436 	          _rl_last_c_pos = tx;
1437 		}
1438 	    }
1439 
1440 	  /* We need to note that in a multibyte locale we are dealing with
1441 	     _rl_last_c_pos as an absolute cursor position, but moving to a
1442 	     point specified by a buffer position (NLEFT) that doesn't take
1443 	     invisible characters into account. */
1444 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
1445 	    _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1446 	  else if (nleft != _rl_last_c_pos)
1447 	    _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1448 	}
1449     }
1450   else				/* Do horizontal scrolling. Much simpler */
1451     {
1452 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
1453       int lmargin, ndisp, nleft, phys_c_pos, t;
1454 
1455       /* Always at top line. */
1456       _rl_last_v_pos = 0;
1457 
1458       /* Compute where in the buffer the displayed line should start.  This
1459 	 will be LMARGIN. */
1460 
1461       /* The number of characters that will be displayed before the cursor. */
1462       ndisp = cpos_buffer_position - wrap_offset;
1463       nleft  = prompt_visible_length + wrap_offset;
1464       /* Where the new cursor position will be on the screen.  This can be
1465 	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1466       phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
1467       t = _rl_screenwidth / 3;
1468 
1469       /* If the number of characters had already exceeded the screenwidth,
1470 	 last_lmargin will be > 0. */
1471 
1472       /* If the number of characters to be displayed is more than the screen
1473 	 width, compute the starting offset so that the cursor is about
1474 	 two-thirds of the way across the screen. */
1475       if (phys_c_pos > _rl_screenwidth - 2)
1476 	{
1477 	  lmargin = cpos_buffer_position - (2 * t);
1478 	  if (lmargin < 0)
1479 	    lmargin = 0;
1480 	  /* If the left margin would be in the middle of a prompt with
1481 	     invisible characters, don't display the prompt at all. */
1482 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
1483 	    lmargin = nleft;
1484 	}
1485       else if (ndisp < _rl_screenwidth - 2)		/* XXX - was -1 */
1486 	lmargin = 0;
1487       else if (phys_c_pos < 1)
1488 	{
1489 	  /* If we are moving back towards the beginning of the line and
1490 	     the last margin is no longer correct, compute a new one. */
1491 	  lmargin = ((cpos_buffer_position - 1) / t) * t;	/* XXX */
1492 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
1493 	    lmargin = nleft;
1494 	}
1495       else
1496 	lmargin = last_lmargin;
1497 
1498       displaying_prompt_first_line = lmargin < nleft;
1499 
1500       /* If the first character on the screen isn't the first character
1501 	 in the display line, indicate this with a special character. */
1502       if (lmargin > 0)
1503 	invisible_line[lmargin] = '<';
1504 
1505       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
1506 	 the whole line, indicate that with a special character at the
1507 	 right edge of the screen.  If LMARGIN is 0, we need to take the
1508 	 wrap offset into account. */
1509       t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1510       if (t > 0 && t < out)
1511 	invisible_line[t - 1] = '>';
1512 
1513       if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
1514 	{
1515 	  forced_display = 0;
1516 	  o_cpos = _rl_last_c_pos;
1517 	  cpos_adjusted = 0;
1518 	  update_line (&visible_line[last_lmargin], &vis_face[last_lmargin],
1519 		       &invisible_line[lmargin], &inv_face[lmargin],
1520 		       0,
1521 		       _rl_screenwidth + visible_wrap_offset,
1522 		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
1523 		       0);
1524 
1525 	  if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1526 		displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
1527 	    _rl_last_c_pos -= prompt_invis_chars_first_line;	/* XXX - was wrap_offset */
1528 
1529 	  /* If the visible new line is shorter than the old, but the number
1530 	     of invisible characters is greater, and we are at the end of
1531 	     the new line, we need to clear to eol. */
1532 	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
1533 	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
1534 	      (_rl_last_c_pos == out) && displaying_prompt_first_line &&
1535 	      t < visible_first_line_len)
1536 	    {
1537 	      nleft = _rl_screenwidth - t;
1538 	      _rl_clear_to_eol (nleft);
1539 	    }
1540 	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
1541 	  if (visible_first_line_len > _rl_screenwidth)
1542 	    visible_first_line_len = _rl_screenwidth;
1543 
1544 	  _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin], &inv_face[lmargin]);
1545 	  last_lmargin = lmargin;
1546 	}
1547     }
1548   fflush (rl_outstream);
1549 
1550   /* Swap visible and non-visible lines. */
1551   {
1552     struct line_state *vtemp = line_state_visible;
1553 
1554     line_state_visible = line_state_invisible;
1555     line_state_invisible = vtemp;
1556 
1557     rl_display_fixed = 0;
1558     /* If we are displaying on a single line, and last_lmargin is > 0, we
1559        are not displaying any invisible characters, so set visible_wrap_offset
1560        to 0. */
1561     if (_rl_horizontal_scroll_mode && last_lmargin)
1562       visible_wrap_offset = 0;
1563     else
1564       visible_wrap_offset = wrap_offset;
1565 
1566     _rl_quick_redisplay = 0;
1567   }
1568 
1569   RL_UNSETSTATE (RL_STATE_REDISPLAYING);
1570   _rl_release_sigint ();
1571 }
1572 
1573 static void
putc_face(int c,int face,char * cur_face)1574 putc_face (int c, int face, char *cur_face)
1575 {
1576   char cf;
1577   cf = *cur_face;
1578   if (cf != face)
1579     {
1580       if (cf != FACE_NORMAL && cf != FACE_STANDOUT)
1581 	return;
1582       if (face != FACE_NORMAL && face != FACE_STANDOUT)
1583 	return;
1584       if (face == FACE_STANDOUT && cf == FACE_NORMAL)
1585         _rl_standout_on ();
1586       if (face == FACE_NORMAL && cf == FACE_STANDOUT)
1587         _rl_standout_off ();
1588       *cur_face = face;
1589     }
1590   if (c != EOF)
1591     putc (c, rl_outstream);
1592 }
1593 
1594 static void
puts_face(const char * str,const char * face,int n)1595 puts_face (const char *str, const char *face, int n)
1596 {
1597   int i;
1598   char cur_face;
1599 
1600   for (cur_face = FACE_NORMAL, i = 0; i < n; i++)
1601     putc_face (str[i], face[i], &cur_face);
1602   putc_face (EOF, FACE_NORMAL, &cur_face);
1603 }
1604 
1605 static void
norm_face(char * face,int n)1606 norm_face (char *face, int n)
1607 {
1608   memset (face, FACE_NORMAL, n);
1609 }
1610 
1611 #define ADJUST_CPOS(x) do { _rl_last_c_pos -= (x) ; cpos_adjusted = 1; } while (0)
1612 
1613 /* PWP: update_line() is based on finding the middle difference of each
1614    line on the screen; vis:
1615 
1616 			     /old first difference
1617 	/beginning of line   |              /old last same       /old EOL
1618 	v 		     v              v                    v
1619 old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1620 new:	eddie> Oh, my little buggy says to me, as lurgid as
1621 	^		     ^        ^			   ^
1622 	\beginning of line   |	      \new last same	   \new end of line
1623 			     \new first difference
1624 
1625    All are character pointers for the sake of speed.  Special cases for
1626    no differences, as well as for end of line additions must be handled.
1627 
1628    Could be made even smarter, but this works well enough */
1629 static void
update_line(char * old,char * old_face,char * new,char * new_face,int current_line,int omax,int nmax,int inv_botlin)1630 update_line (char *old, char *old_face, char *new, char *new_face, int current_line, int omax, int nmax, int inv_botlin)
1631 {
1632   char *ofd, *ols, *oe, *nfd, *nls, *ne;
1633   char *ofdf, *nfdf, *olsf, *nlsf;
1634   int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
1635   int current_invis_chars;
1636   int col_lendiff, col_temp;
1637   int bytes_to_insert;
1638   int mb_cur_max = MB_CUR_MAX;
1639 #if defined (HANDLE_MULTIBYTE)
1640   mbstate_t ps_new, ps_old;
1641   int new_offset, old_offset;
1642 #endif
1643 
1644   /* If we're at the right edge of a terminal that supports xn, we're
1645      ready to wrap around, so do so.  This fixes problems with knowing
1646      the exact cursor position and cut-and-paste with certain terminal
1647      emulators.  In this calculation, TEMP is the physical screen
1648      position of the cursor. */
1649   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1650     temp = _rl_last_c_pos;
1651   else
1652     temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
1653   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1654 	&& _rl_last_v_pos == current_line - 1)
1655     {
1656       /* We're going to wrap around by writing the first character of NEW to
1657 	 the screen and dealing with changes to what's visible by modifying
1658 	 OLD to match it.  Complicated by the presence of multi-width
1659 	 characters at the end of the line or beginning of the new one. */
1660       /* old is always somewhere in visible_line; new is always somewhere in
1661          invisible_line.  These should always be null-terminated. */
1662 #if defined (HANDLE_MULTIBYTE)
1663       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1664 	{
1665 	  wchar_t wc;
1666 	  mbstate_t ps;
1667 	  int oldwidth, newwidth;
1668 	  int oldbytes, newbytes;
1669 	  size_t ret;
1670 
1671 	  /* This fixes only double-column characters, but if the wrapped
1672 	     character consumes more than three columns, spaces will be
1673 	     inserted in the string buffer. */
1674 	  /* XXX remember that we are working on the invisible line right now;
1675 	     we don't swap visible and invisible until just before rl_redisplay
1676 	     returns */
1677 	  /* This will remove the extra placeholder space we added with
1678 	     _rl_wrapped_multicolumn */
1679 	  if (current_line < line_state_invisible->wbsize && line_state_invisible->wrapped_line[current_line] > 0)
1680 	    _rl_clear_to_eol (line_state_invisible->wrapped_line[current_line]);
1681 
1682 	  /* 1. how many screen positions does first char in old consume? */
1683 	  memset (&ps, 0, sizeof (mbstate_t));
1684 	  ret = mbrtowc (&wc, old, mb_cur_max, &ps);
1685 	  oldbytes = ret;
1686 	  if (MB_INVALIDCH (ret))
1687 	    {
1688 	      oldwidth = 1;
1689 	      oldbytes = 1;
1690 	    }
1691 	  else if (MB_NULLWCH (ret))
1692 	    oldwidth = 0;
1693 	  else
1694 	    oldwidth = WCWIDTH (wc);
1695 	  if (oldwidth < 0)
1696 	    oldwidth = 1;
1697 
1698 	  /* 2. how many screen positions does the first char in new consume? */
1699 	  memset (&ps, 0, sizeof (mbstate_t));
1700 	  ret = mbrtowc (&wc, new, mb_cur_max, &ps);
1701 	  newbytes = ret;
1702 	  if (MB_INVALIDCH (ret))
1703 	    {
1704 	      newwidth = 1;
1705 	      newbytes = 1;
1706 	    }
1707 	  else if (MB_NULLWCH (ret))
1708 	    newwidth = 0;
1709 	  else
1710 	    newwidth = WCWIDTH (wc);
1711 	  if (newwidth < 0)
1712 	    newwidth = 1;
1713 
1714 	  /* 3. if the new width is less than the old width, we need to keep
1715 	     going in new until we have consumed at least that many screen
1716 	     positions, and figure out how many bytes that will take */
1717 	  while (newbytes < nmax && newwidth < oldwidth)
1718 	    {
1719 	      int t;
1720 
1721 	      ret = mbrtowc (&wc, new+newbytes, mb_cur_max, &ps);
1722 	      if (MB_INVALIDCH (ret))
1723 		{
1724 		  newwidth += 1;
1725 		  newbytes += 1;
1726 		}
1727 	      else if (MB_NULLWCH (ret))
1728 	        break;
1729 	      else
1730 		{
1731 		  t = WCWIDTH (wc);
1732 		  newwidth += (t >= 0) ? t : 1;
1733 		  newbytes += ret;
1734 		}
1735 	    }
1736 	  /* 4. If the new width is more than the old width, keep going in old
1737 	     until we have consumed exactly that many screen positions, and
1738 	     figure out how many bytes that will take.  This is an optimization */
1739 	  while (oldbytes < omax && oldwidth < newwidth)
1740 	    {
1741 	      int t;
1742 
1743 	      ret = mbrtowc (&wc, old+oldbytes, mb_cur_max, &ps);
1744 	      if (MB_INVALIDCH (ret))
1745 		{
1746 		  oldwidth += 1;
1747 		  oldbytes += 1;
1748 		}
1749 	      else if (MB_NULLWCH (ret))
1750 	        break;
1751 	      else
1752 		{
1753 		  t = WCWIDTH (wc);
1754 		  oldwidth += (t >= 0) ? t : 1;
1755 		  oldbytes += ret;
1756 		}
1757 	    }
1758 	  /* 5. write the first newbytes of new, which takes newwidth.  This is
1759 	     where the screen wrapping takes place, and we are now writing
1760 	     characters onto the new line. We need to fix up old so it
1761 	     accurately reflects what is on the screen after the
1762 	     _rl_output_some_chars below. */
1763 	  if (newwidth > 0)
1764 	    {
1765 	      int count, i, j;
1766 	      char *optr;
1767 
1768 	      puts_face (new, new_face, newbytes);
1769 	      _rl_last_c_pos = newwidth;
1770 	      _rl_last_v_pos++;
1771 
1772 	      /* 5a. If the number of screen positions doesn't match, punt
1773 		 and do a dumb update.
1774 		 5b. If the number of bytes is greater in the new line than
1775 		 the old, do a dumb update, because there is no guarantee we
1776 		 can extend the old line enough to fit the new bytes. */
1777 	      if (newwidth != oldwidth || newbytes > oldbytes)
1778 		{
1779 		  oe = old + omax;
1780 		  ne = new + nmax;
1781 		  nd = newbytes;
1782 		  nfd = new + nd;
1783 		  ofdf = old_face + oldbytes;
1784 		  nfdf = new_face + newbytes;
1785 
1786 		  goto dumb_update;
1787 		}
1788 	      if (oldbytes != 0 && newbytes != 0)
1789 		{
1790 		  /* We have written as many bytes from new as we need to
1791 		     consume the first character of old. Fix up `old' so it
1792 		     reflects the new screen contents.  We use +1 in the
1793 		     memmove call to copy the trailing NUL. */
1794 		  /* (strlen(old+oldbytes) == (omax - oldbytes - 1)) */
1795 
1796 		  /* Don't bother trying to fit the bytes if the number of bytes
1797 		     doesn't change. */
1798 		  if (oldbytes != newbytes)
1799 		    {
1800 		      memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
1801 		      memmove (old_face+newbytes, old_face+oldbytes, strlen (old+oldbytes) + 1);
1802 		    }
1803 		  memcpy (old, new, newbytes);
1804 		  memcpy (old_face, new_face, newbytes);
1805 		  j = newbytes - oldbytes;
1806 		  omax += j;
1807 		  /* Fix up indices if we copy data from one line to another */
1808 		  for (i = current_line+1; j != 0 && i <= inv_botlin+1 && i <=_rl_vis_botlin+1; i++)
1809 		    vis_lbreaks[i] += j;
1810 		}
1811 	    }
1812 	  else
1813 	    {
1814 	      putc (' ', rl_outstream);
1815 	      _rl_last_c_pos = 1;
1816 	      _rl_last_v_pos++;
1817 	      if (old[0] && new[0])
1818 		{
1819 		  old[0] = new[0];
1820 		  old_face[0] = new_face[0];
1821 		}
1822 	    }
1823 	}
1824       else
1825 #endif
1826 	{
1827 	  if (new[0])
1828 	    puts_face (new, new_face, 1);
1829 	  else
1830 	    putc (' ', rl_outstream);
1831 	  _rl_last_c_pos = 1;
1832 	  _rl_last_v_pos++;
1833 	  if (old[0] && new[0])
1834 	    {
1835 	      old[0] = new[0];
1836 	      old_face[0] = new_face[0];
1837 	    }
1838 	}
1839     }
1840 
1841   /* We know that we are dealing with a single screen line here */
1842   if (_rl_quick_redisplay)
1843     {
1844       nfd = new;
1845       nfdf = new_face;
1846       ofd = old;
1847       ofdf = old_face;
1848       for (od = 0, oe = ofd; od < omax && *oe; oe++, od++);
1849       for (nd = 0, ne = nfd; nd < nmax && *ne; ne++, nd++);
1850       od = nd = 0;
1851       _rl_move_cursor_relative (0, old, old_face);
1852 
1853       bytes_to_insert = ne - nfd;
1854       if (bytes_to_insert < local_prompt_len)	/* ??? */
1855 	goto dumb_update;
1856 
1857       /* output the prompt, output the line contents, clear the rest */
1858       _rl_output_some_chars (nfd, local_prompt_len);
1859       if (mb_cur_max > 1 && rl_byte_oriented == 0)
1860 	_rl_last_c_pos = prompt_physical_chars;
1861       else
1862 	_rl_last_c_pos = local_prompt_len;
1863 
1864       bytes_to_insert -= local_prompt_len;
1865       if (bytes_to_insert > 0)
1866 	{
1867 	  puts_face (new+local_prompt_len, nfdf+local_prompt_len, bytes_to_insert);
1868 	  if (mb_cur_max > 1 && rl_byte_oriented)
1869 	    _rl_last_c_pos += _rl_col_width (new, local_prompt_len, ne-new, 1);
1870 	  else
1871 	    _rl_last_c_pos += bytes_to_insert;
1872 	}
1873 
1874       /* See comments at dumb_update: for an explanation of this heuristic */
1875       if (nmax < omax)
1876 	goto clear_rest_of_line;
1877       else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
1878 	goto clear_rest_of_line;
1879       else
1880 	return;
1881     }
1882 
1883   /* Find first difference. */
1884 #if defined (HANDLE_MULTIBYTE)
1885   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1886     {
1887       /* See if the old line is a subset of the new line, so that the
1888 	 only change is adding characters. */
1889       temp = (omax < nmax) ? omax : nmax;
1890       if (memcmp (old, new, temp) == 0 && memcmp (old_face, new_face, temp) == 0)
1891 	{
1892 	  new_offset = old_offset = temp;	/* adding at the end */
1893 	  ofd = old + temp;
1894 	  ofdf = old_face + temp;
1895 	  nfd = new + temp;
1896 	  nfdf = new_face + temp;
1897 	}
1898       else
1899 	{
1900 	  memset (&ps_new, 0, sizeof(mbstate_t));
1901 	  memset (&ps_old, 0, sizeof(mbstate_t));
1902 
1903 	  /* Are the old and new lines the same? */
1904 	  if (omax == nmax && memcmp (new, old, omax) == 0 && memcmp (new_face, old_face, omax) == 0)
1905 	    {
1906 	      old_offset = omax;
1907 	      new_offset = nmax;
1908 	      ofd = old + omax;
1909 	      ofdf = old_face + omax;
1910 	      nfd = new + nmax;
1911 	      nfdf = new_face + nmax;
1912 	    }
1913 	  else
1914 	    {
1915 	      /* Go through the line from the beginning and find the first
1916 		 difference. We assume that faces change at (possibly multi-
1917 		 byte) character boundaries. */
1918 	      new_offset = old_offset = 0;
1919 	      for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
1920 		    (ofd - old < omax) && *ofd &&
1921 		    _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new) &&
1922 		    *ofdf == *nfdf; )
1923 		{
1924 		  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1925 		  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1926 
1927 		  ofd = old + old_offset;
1928 		  ofdf = old_face + old_offset;
1929 		  nfd = new + new_offset;
1930 		  nfdf = new_face + new_offset;
1931 		}
1932 	    }
1933 	}
1934     }
1935   else
1936 #endif
1937   for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
1938        (ofd - old < omax) && *ofd && (*ofd == *nfd) && (*ofdf == *nfdf);
1939        ofd++, nfd++, ofdf++, nfdf++)
1940     ;
1941 
1942   /* Move to the end of the screen line.  ND and OD are used to keep track
1943      of the distance between ne and new and oe and old, respectively, to
1944      move a subtraction out of each loop. */
1945   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1946   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1947 
1948   /* If no difference, continue to next line. */
1949   if (ofd == oe && nfd == ne)
1950     return;
1951 
1952 #if defined (HANDLE_MULTIBYTE)
1953   if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
1954     {
1955       wchar_t wc;
1956       mbstate_t ps = { 0 };
1957       int t;
1958 
1959       /* If the first character in the difference is a zero-width character,
1960 	 assume it's a combining character and back one up so the two base
1961 	 characters no longer compare equivalently. */
1962       t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
1963       if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
1964 	{
1965 	  old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
1966 	  new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
1967 	  ofd = old + old_offset;	/* equal by definition */
1968 	  ofdf = old_face + old_offset;
1969 	  nfd = new + new_offset;
1970 	  nfdf = new_face + new_offset;
1971 	}
1972     }
1973 #endif
1974 
1975   wsatend = 1;			/* flag for trailing whitespace */
1976 
1977 #if defined (HANDLE_MULTIBYTE)
1978   /* Find the last character that is the same between the two lines.  This
1979      bounds the region that needs to change. */
1980   if (mb_cur_max > 1 && rl_byte_oriented == 0)
1981     {
1982       ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1983       olsf = old_face + (ols - old);
1984       nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1985       nlsf = new_face + (nls - new);
1986 
1987       while ((ols > ofd) && (nls > nfd))
1988 	{
1989 	  memset (&ps_old, 0, sizeof (mbstate_t));
1990 	  memset (&ps_new, 0, sizeof (mbstate_t));
1991 
1992 	  if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0 ||
1993 		*olsf != *nlsf)
1994 	    break;
1995 
1996 	  if (*ols == ' ')
1997 	    wsatend = 0;
1998 
1999 	  ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
2000 	  olsf = old_face + (ols - old);
2001 	  nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
2002 	  nlsf = new_face + (nls - new);
2003 	}
2004     }
2005   else
2006     {
2007 #endif /* HANDLE_MULTIBYTE */
2008   ols = oe - 1;			/* find last same */
2009   olsf = old_face + (ols - old);
2010   nls = ne - 1;
2011   nlsf = new_face + (nls - new);
2012   while ((ols > ofd) && (nls > nfd) && (*ols == *nls) && (*olsf == *nlsf))
2013     {
2014       if (*ols != ' ')
2015 	wsatend = 0;
2016       ols--; olsf--;
2017       nls--; nlsf--;
2018     }
2019 #if defined (HANDLE_MULTIBYTE)
2020     }
2021 #endif
2022 
2023   if (wsatend)
2024     {
2025       ols = oe;
2026       olsf = old_face + (ols - old);
2027       nls = ne;
2028       nlsf = new_face + (nls - new);
2029     }
2030 #if defined (HANDLE_MULTIBYTE)
2031   /* This may not work for stateful encoding, but who cares?  To handle
2032      stateful encoding properly, we have to scan each string from the
2033      beginning and compare. */
2034   else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0 || *olsf != *nlsf)
2035 #else
2036   else if (*ols != *nls || *olsf != *nlsf)
2037 #endif
2038     {
2039       if (*ols)			/* don't step past the NUL */
2040 	{
2041 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
2042 	    ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
2043 	  else
2044 	    ols++;
2045 	}
2046       if (*nls)
2047 	{
2048 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
2049 	    nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
2050 	  else
2051 	    nls++;
2052 	}
2053       olsf = old_face + (ols - old);
2054       nlsf = new_face + (nls - new);
2055     }
2056 
2057   /* count of invisible characters in the current invisible line. */
2058   current_invis_chars = W_OFFSET (current_line, wrap_offset);
2059   if (_rl_last_v_pos != current_line)
2060     {
2061       _rl_move_vert (current_line);
2062       /* We have moved up to a new screen line.  This line may or may not have
2063          invisible characters on it, but we do our best to recalculate
2064          visible_wrap_offset based on what we know. */
2065       if (current_line == 0)
2066 	visible_wrap_offset = prompt_invis_chars_first_line;	/* XXX */
2067 #if 0		/* XXX - not yet */
2068       else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
2069 	visible_wrap_offset = wrap_offset - prompt_invis_chars_first_line
2070 #endif
2071       if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
2072 	_rl_last_c_pos += visible_wrap_offset;
2073     }
2074 
2075   /* If this is the first line and there are invisible characters in the
2076      prompt string, and the prompt string has not changed, and the current
2077      cursor position is before the last invisible character in the prompt,
2078      and the index of the character to move to is past the end of the prompt
2079      string, then redraw the entire prompt string.  We can only do this
2080      reliably if the terminal supports a `cr' capability.
2081 
2082      This can also happen if the prompt string has changed, and the first
2083      difference in the line is in the middle of the prompt string, after a
2084      sequence of invisible characters (worst case) and before the end of
2085      the prompt.  In this case, we have to redraw the entire prompt string
2086      so that the entire sequence of invisible characters is drawn.  We need
2087      to handle the worst case, when the difference is after (or in the middle
2088      of) a sequence of invisible characters that changes the text color and
2089      before the sequence that restores the text color to normal.  Then we have
2090      to make sure that the lines still differ -- if they don't, we can
2091      return immediately.
2092 
2093      This is not an efficiency hack -- there is a problem with redrawing
2094      portions of the prompt string if they contain terminal escape
2095      sequences (like drawing the `unbold' sequence without a corresponding
2096      `bold') that manifests itself on certain terminals. */
2097 
2098   lendiff = local_prompt_len;
2099   if (lendiff > nmax)
2100     lendiff = nmax;
2101   od = ofd - old;	/* index of first difference in visible line */
2102   nd = nfd - new;	/* nd, od are buffer indexes */
2103   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
2104       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
2105       (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
2106 		((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
2107     {
2108       _rl_cr ();
2109       if (modmark)
2110 	_rl_output_some_chars ("*", 1);
2111       _rl_output_some_chars (local_prompt, lendiff);
2112       if (mb_cur_max > 1 && rl_byte_oriented == 0)
2113 	{
2114 	  /* If we just output the entire prompt string we can take advantage
2115 	     of knowing the number of physical characters in the prompt. If
2116 	     the prompt wraps lines (lendiff clamped at nmax), we can't. */
2117 	  if (lendiff == local_prompt_len)
2118 	    _rl_last_c_pos = prompt_physical_chars + modmark;
2119 	  else
2120 	    /* We take wrap_offset into account here so we can pass correct
2121 	       information to _rl_move_cursor_relative. */
2122 	    _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
2123 	  cpos_adjusted = 1;
2124 	}
2125       else
2126 	_rl_last_c_pos = lendiff + modmark;
2127 
2128       /* Now if we have printed the prompt string because the first difference
2129 	 was within the prompt, see if we need to recompute where the lines
2130 	 differ.  Check whether where we are now is past the last place where
2131 	 the old and new lines are the same and short-circuit now if we are. */
2132       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible) &&
2133           omax == nmax &&
2134 	  lendiff > (ols-old) && lendiff > (nls-new))
2135 	return;
2136 
2137       /* XXX - we need to fix up our calculations if we are now past the
2138 	 old ofd/nfd and the prompt length (or line length) has changed.
2139 	 We punt on the problem and do a dumb update.  We'd like to be able
2140 	 to just output the prompt from the beginning of the line up to the
2141 	 first difference, but you don't know the number of invisible
2142 	 characters in that case.
2143 	 This needs a lot of work to be efficient, but it usually doesn't matter. */
2144       if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
2145 	{
2146 	  nfd = new + lendiff;	/* number of characters we output above */
2147 	  nfdf = new_face + lendiff;
2148 	  nd = lendiff;
2149 
2150 	  /* Do a dumb update and return */
2151 dumb_update:
2152 	  temp = ne - nfd;
2153 	  if (temp > 0)
2154 	    {
2155 	      puts_face (nfd, nfdf, temp);
2156 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
2157 		{
2158 		  _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
2159 		  /* Need to adjust here based on wrap_offset. Guess that if
2160 		     this is the line containing the last line of the prompt
2161 		     we need to adjust by
2162 		     	wrap_offset-prompt_invis_chars_first_line
2163 		     on the assumption that this is the number of invisible
2164 		     characters in the last line of the prompt. */
2165 		  if (wrap_offset > prompt_invis_chars_first_line &&
2166 		      current_line == prompt_last_screen_line &&
2167 		      prompt_physical_chars > _rl_screenwidth &&
2168 		      _rl_horizontal_scroll_mode == 0)
2169 		    ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
2170 
2171 		  /* If we just output a new line including the prompt, and
2172 		     the prompt includes invisible characters, we need to
2173 		     account for them in the _rl_last_c_pos calculation, since
2174 		     _rl_col_width does not. This happens when other code does
2175 		     a goto dumb_update; */
2176 		  else if (current_line == 0 &&
2177 			   nfd == new &&
2178 			   prompt_invis_chars_first_line &&
2179 			   local_prompt_len <= temp &&
2180 			   wrap_offset >= prompt_invis_chars_first_line &&
2181 			   _rl_horizontal_scroll_mode == 0)
2182 		    ADJUST_CPOS (prompt_invis_chars_first_line);
2183 		}
2184 	      else
2185 		_rl_last_c_pos += temp;
2186 	    }
2187 	  /* This is a useful heuristic, but what we really want is to clear
2188 	     if the new number of visible screen characters is less than the
2189 	     old number of visible screen characters. If the prompt has changed,
2190 	     we don't really have enough information about the visible line to
2191 	     know for sure, so we use another heuristic calclulation below. */
2192 	  if (nmax < omax)
2193 	    goto clear_rest_of_line;	/* XXX */
2194 	  else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
2195 	    goto clear_rest_of_line;
2196 	  else
2197 	    return;
2198 	}
2199     }
2200 
2201   o_cpos = _rl_last_c_pos;
2202 
2203   /* When this function returns, _rl_last_c_pos is correct, and an absolute
2204      cursor position in multibyte mode, but a buffer index when not in a
2205      multibyte locale. */
2206   _rl_move_cursor_relative (od, old, old_face);
2207 
2208 #if defined (HANDLE_MULTIBYTE)
2209   /* We need to indicate that the cursor position is correct in the presence of
2210      invisible characters in the prompt string.  Let's see if setting this when
2211      we make sure we're at the end of the drawn prompt string works. */
2212   if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
2213       (_rl_last_c_pos > 0 || o_cpos > 0) &&
2214       _rl_last_c_pos == prompt_physical_chars)
2215     cpos_adjusted = 1;
2216 #endif
2217 
2218   /* if (len (new) > len (old))
2219      lendiff == difference in buffer (bytes)
2220      col_lendiff == difference on screen (columns)
2221      When not using multibyte characters, these are equal */
2222   lendiff = (nls - nfd) - (ols - ofd);
2223   if (mb_cur_max > 1 && rl_byte_oriented == 0)
2224     {
2225       int newchars, newwidth, newind;
2226       int oldchars, oldwidth, oldind;
2227 
2228       newchars = nls - new;
2229       oldchars = ols - old;
2230 
2231       /* If we can do it, try to adjust nls and ols so that nls-new will
2232 	 contain the entire new prompt string. That way we can use
2233 	 prompt_physical_chars and not have to recompute column widths.
2234 	 _rl_col_width adds wrap_offset and expects the caller to compensate,
2235 	 which we do below, so we do the same thing if we don't call
2236 	 _rl_col_width.
2237 	 We don't have to compare, since we know the characters are the same.
2238 	 The check of differing numbers of invisible chars may be extraneous.
2239 	 XXX - experimental */
2240       if (current_line == 0 && nfd == new && newchars > prompt_last_invisible &&
2241 	  newchars <= local_prompt_len &&
2242 	  local_prompt_len <= nmax &&
2243 	  current_invis_chars != visible_wrap_offset)
2244 	{
2245 	  while (newchars < nmax && oldchars < omax &&  newchars < local_prompt_len)
2246 	    {
2247 #if defined (HANDLE_MULTIBYTE)
2248 	      newind = _rl_find_next_mbchar (new, newchars, 1, MB_FIND_NONZERO);
2249 	      oldind = _rl_find_next_mbchar (old, oldchars, 1, MB_FIND_NONZERO);
2250 
2251 	      nls += newind - newchars;
2252 	      ols += oldind - oldchars;
2253 
2254 	      newchars = newind;
2255 	      oldchars = oldind;
2256 #else
2257 	      nls++; ols++;
2258 	      newchars++; oldchars++;
2259 #endif
2260 	    }
2261 	  newwidth = (newchars == local_prompt_len) ? prompt_physical_chars + wrap_offset
2262 	  					    : _rl_col_width (new, 0, nls - new, 1);
2263 	  /* if we changed nls and ols, we need to recompute lendiff */
2264 	  lendiff = (nls - nfd) - (ols - ofd);
2265 
2266 	  nlsf = new_face + (nls - new);
2267 	  olsf = old_face + (ols - old);
2268 	}
2269       else
2270 	newwidth = _rl_col_width (new, nfd - new, nls - new, 1);
2271 
2272       oldwidth = _rl_col_width (old, ofd - old, ols - old, 1);
2273 
2274       col_lendiff = newwidth - oldwidth;
2275     }
2276   else
2277     col_lendiff = lendiff;
2278 
2279   /* col_lendiff uses _rl_col_width(), which doesn't know about whether or not
2280      the multibyte characters it counts are invisible, so unless we're printing
2281      the entire prompt string (in which case we can use prompt_physical_chars)
2282      the count is short by the number of bytes in the invisible multibyte
2283      characters - the number of multibyte characters.
2284 
2285      We don't have a good way to solve this without moving to something like
2286      a bitmap that indicates which characters are visible and which are
2287      invisible. We fix it up (imperfectly) in the caller and by trying to use
2288      the entire prompt string wherever we can. */
2289 
2290   /* If we are changing the number of invisible characters in a line, and
2291      the spot of first difference is before the end of the invisible chars,
2292      lendiff needs to be adjusted. */
2293   if (current_line == 0 && current_invis_chars != visible_wrap_offset)
2294     {
2295       if (mb_cur_max > 1 && rl_byte_oriented == 0)
2296 	{
2297 	  lendiff += visible_wrap_offset - current_invis_chars;
2298 	  col_lendiff += visible_wrap_offset - current_invis_chars;
2299 	}
2300       else
2301 	{
2302 	  lendiff += visible_wrap_offset - current_invis_chars;
2303 	  col_lendiff = lendiff;
2304 	}
2305     }
2306 
2307   /* We use temp as a count of the number of bytes from the first difference
2308      to the end of the new line.  col_temp is the corresponding number of
2309      screen columns.  A `dumb' update moves to the spot of first difference
2310      and writes TEMP bytes. */
2311   /* Insert (diff (len (old), len (new)) ch. */
2312   temp = ne - nfd;
2313   if (mb_cur_max > 1 && rl_byte_oriented == 0)
2314     col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
2315   else
2316     col_temp = temp;
2317 
2318   /* how many bytes from the new line buffer to write to the display */
2319   bytes_to_insert = nls - nfd;
2320 
2321   /* col_lendiff > 0 if we are adding characters to the line */
2322   if (col_lendiff > 0)	/* XXX - was lendiff */
2323     {
2324       /* Non-zero if we're increasing the number of lines. */
2325       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
2326 
2327       /* If col_lendiff is > 0, implying that the new string takes up more
2328 	 screen real estate than the old, but lendiff is < 0, meaning that it
2329 	 takes fewer bytes, we need to just output the characters starting
2330 	 from the first difference.  These will overwrite what is on the
2331 	 display, so there's no reason to do a smart update.  This can really
2332 	 only happen in a multibyte environment. */
2333       if (lendiff < 0)
2334 	{
2335 	  puts_face (nfd, nfdf, temp);
2336 	  _rl_last_c_pos += col_temp;
2337 	  /* If nfd begins before any invisible characters in the prompt,
2338 	     adjust _rl_last_c_pos to account for wrap_offset and set
2339 	     cpos_adjusted to let the caller know. */
2340 	  if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2341 	    ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
2342 	  return;
2343 	}
2344       /* Sometimes it is cheaper to print the characters rather than
2345 	 use the terminal's capabilities.  If we're growing the number
2346 	 of lines, make sure we actually cause the new line to wrap
2347 	 around on auto-wrapping terminals. */
2348       else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
2349 	{
2350 	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
2351 	     _rl_horizontal_scroll_mode == 1, inserting the characters with
2352 	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
2353 	     invisible characters.  We need to just draw them. */
2354 	  /* The same thing happens if we're trying to draw before the last
2355 	     invisible character in the prompt string or we're increasing the
2356 	     number of invisible characters in the line and we're not drawing
2357 	     the entire prompt string. */
2358 	  if (*ols && ((_rl_horizontal_scroll_mode &&
2359 			_rl_last_c_pos == 0 &&
2360 			lendiff > prompt_visible_length &&
2361 			current_invis_chars > 0) == 0) &&
2362 		      (((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2363 		        current_line == 0 && wrap_offset &&
2364 		        ((nfd - new) <= prompt_last_invisible) &&
2365 		        (col_lendiff < prompt_visible_length)) == 0) &&
2366 		      (visible_wrap_offset >= current_invis_chars))
2367 	    {
2368 	      open_some_spaces (col_lendiff);
2369 	      puts_face (nfd, nfdf, bytes_to_insert);
2370 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
2371 		_rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2372 	      else
2373 		_rl_last_c_pos += bytes_to_insert;
2374 	    }
2375 	  else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
2376 	    {
2377 	      /* At the end of a line the characters do not have to
2378 		 be "inserted".  They can just be placed on the screen. */
2379 	      puts_face (nfd, nfdf, temp);
2380 	      _rl_last_c_pos += col_temp;
2381 	      return;
2382 	    }
2383 	  else	/* just write from first difference to end of new line */
2384 	    {
2385 	      puts_face (nfd, nfdf, temp);
2386 	      _rl_last_c_pos += col_temp;
2387 	      /* If nfd begins before the last invisible character in the
2388 		 prompt, adjust _rl_last_c_pos to account for wrap_offset
2389 		 and set cpos_adjusted to let the caller know. */
2390 	      if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2391 		ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
2392 	      return;
2393 	    }
2394 
2395 	  if (bytes_to_insert > lendiff)
2396 	    {
2397 	      /* If nfd begins before the last invisible character in the
2398 		 prompt, adjust _rl_last_c_pos to account for wrap_offset
2399 		 and set cpos_adjusted to let the caller know. */
2400 	      if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2401 		ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
2402 	    }
2403 	}
2404       else
2405 	{
2406 	  /* cannot insert chars, write to EOL */
2407 	  puts_face (nfd, nfdf, temp);
2408 	  _rl_last_c_pos += col_temp;
2409 	  /* If we're in a multibyte locale and were before the last invisible
2410 	     char in the current line (which implies we just output some invisible
2411 	     characters) we need to adjust _rl_last_c_pos, since it represents
2412 	     a physical character position. */
2413 	  /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a
2414 	     crude attempt to compute how far into the new line buffer we are.
2415 	     It doesn't work well in the face of multibyte characters and needs
2416 	     to be rethought. XXX */
2417 	  if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2418 		current_line == prompt_last_screen_line && wrap_offset &&
2419 		displaying_prompt_first_line &&
2420 		wrap_offset != prompt_invis_chars_first_line &&
2421 		((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
2422 	    ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
2423 
2424 	  /* XXX - what happens if wrap_offset == prompt_invis_chars_first_line
2425 	     and we are drawing the first line (current_line == 0)? We should
2426 	     adjust by _rl_last_c_pos -= prompt_invis_chars_first_line */
2427 	}
2428     }
2429   else				/* Delete characters from line. */
2430     {
2431       /* If possible and inexpensive to use terminal deletion, then do so. */
2432       if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
2433 	{
2434 	  /* If all we're doing is erasing the invisible characters in the
2435 	     prompt string, don't bother.  It screws up the assumptions
2436 	     about what's on the screen. */
2437 	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
2438 	      displaying_prompt_first_line &&
2439 	      -lendiff == visible_wrap_offset)
2440 	    col_lendiff = 0;
2441 
2442 	  /* If we have moved lmargin and we're shrinking the line, we've
2443 	     already moved the cursor to the first character of the new line,
2444 	     so deleting -col_lendiff characters will mess up the cursor
2445 	     position calculation */
2446 	  if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
2447 		col_lendiff && _rl_last_c_pos < -col_lendiff)
2448 	    col_lendiff = 0;
2449 
2450 	  if (col_lendiff)
2451 	    delete_chars (-col_lendiff); /* delete (diff) characters */
2452 
2453 	  /* Copy (new) chars to screen from first diff to last match,
2454 	     overwriting what is there. */
2455 	  if (bytes_to_insert > 0)
2456 	    {
2457 	      /* If nfd begins at the prompt, or before the invisible
2458 		 characters in the prompt, we need to adjust _rl_last_c_pos
2459 		 in a multibyte locale to account for the wrap offset and
2460 		 set cpos_adjusted accordingly. */
2461 	      puts_face (nfd, nfdf, bytes_to_insert);
2462 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
2463 		{
2464 		  /* This still doesn't take into account whether or not the
2465 		     characters that this counts are invisible. */
2466 		  _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2467 		  if (current_line == 0 && wrap_offset &&
2468 			displaying_prompt_first_line &&
2469 			prompt_invis_chars_first_line &&
2470 			_rl_last_c_pos >= prompt_invis_chars_first_line &&
2471 			((nfd - new) <= prompt_last_invisible))
2472 		    ADJUST_CPOS (prompt_invis_chars_first_line);
2473 
2474 #if 1
2475 #ifdef HANDLE_MULTIBYTE
2476 		  /* If we write a non-space into the last screen column,
2477 		     remove the note that we added a space to compensate for
2478 		     a multibyte double-width character that didn't fit, since
2479 		     it's only valid for what was previously there. */
2480 		  /* XXX - watch this */
2481 		  if (_rl_last_c_pos == _rl_screenwidth &&
2482 			line_state_invisible->wrapped_line[current_line+1] &&
2483 			nfd[bytes_to_insert-1] != ' ')
2484 		    line_state_invisible->wrapped_line[current_line+1] = 0;
2485 #endif
2486 #endif
2487 		}
2488 	      else
2489 		_rl_last_c_pos += bytes_to_insert;
2490 
2491 	      /* XXX - we only want to do this if we are at the end of the line
2492 		 so we move there with _rl_move_cursor_relative */
2493 	      if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
2494 		{
2495 		  _rl_move_cursor_relative (ne-new, new, new_face);
2496 		  goto clear_rest_of_line;
2497 		}
2498 	    }
2499 	}
2500       /* Otherwise, print over the existing material. */
2501       else
2502 	{
2503 	  if (temp > 0)
2504 	    {
2505 	      /* If nfd begins at the prompt, or before the invisible
2506 		 characters in the prompt, we need to adjust _rl_last_c_pos
2507 		 in a multibyte locale to account for the wrap offset and
2508 		 set cpos_adjusted accordingly. */
2509 	      puts_face (nfd, nfdf, temp);
2510 	      _rl_last_c_pos += col_temp;		/* XXX */
2511 	      if (mb_cur_max > 1 && rl_byte_oriented == 0)
2512 		{
2513 		  if (current_line == 0 && wrap_offset &&
2514 			displaying_prompt_first_line &&
2515 			_rl_last_c_pos > wrap_offset &&
2516 			((nfd - new) <= prompt_last_invisible))
2517 		    ADJUST_CPOS (wrap_offset);	/* XXX - prompt_invis_chars_first_line? */
2518 		}
2519 	    }
2520 clear_rest_of_line:
2521 	  lendiff = (oe - old) - (ne - new);
2522 	  if (mb_cur_max > 1 && rl_byte_oriented == 0)
2523 	    col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
2524 	  else
2525 	    col_lendiff = lendiff;
2526 
2527 	  /* If we've already printed over the entire width of the screen,
2528 	     including the old material, then col_lendiff doesn't matter and
2529 	     space_to_eol will insert too many spaces.  XXX - maybe we should
2530 	     adjust col_lendiff based on the difference between _rl_last_c_pos
2531 	     and _rl_screenwidth */
2532 	  if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
2533 	    {
2534 	      if (_rl_term_autowrap && current_line < inv_botlin)
2535 		space_to_eol (col_lendiff);
2536 	      else
2537 		_rl_clear_to_eol (col_lendiff);
2538 	    }
2539 	}
2540     }
2541 }
2542 
2543 /* Tell the update routines that we have moved onto a new (empty) line. */
2544 int
rl_on_new_line(void)2545 rl_on_new_line (void)
2546 {
2547   if (visible_line)
2548     visible_line[0] = '\0';
2549 
2550   _rl_last_c_pos = _rl_last_v_pos = 0;
2551   _rl_vis_botlin = last_lmargin = 0;
2552   if (vis_lbreaks)
2553     vis_lbreaks[0] = vis_lbreaks[1] = 0;
2554   visible_wrap_offset = 0;
2555   return 0;
2556 }
2557 
2558 /* Clear all screen lines occupied by the current readline line buffer
2559    (visible line) */
2560 int
rl_clear_visible_line(void)2561 rl_clear_visible_line (void)
2562 {
2563   int curr_line;
2564 
2565   /* Make sure we move to column 0 so we clear the entire line */
2566   _rl_cr ();
2567   _rl_last_c_pos = 0;
2568 
2569   /* Move to the last screen line of the current visible line */
2570   _rl_move_vert (_rl_vis_botlin);
2571 
2572   /* And erase screen lines going up to line 0 (first visible line) */
2573   for (curr_line = _rl_last_v_pos; curr_line >= 0; curr_line--)
2574     {
2575       _rl_move_vert (curr_line);
2576       _rl_clear_to_eol (0);
2577     }
2578 
2579   return 0;
2580 }
2581 
2582 /* Tell the update routines that we have moved onto a new line with the
2583    prompt already displayed.  Code originally from the version of readline
2584    distributed with CLISP.  rl_expand_prompt must have already been called
2585    (explicitly or implicitly).  This still doesn't work exactly right; it
2586    should use expand_prompt() */
2587 int
rl_on_new_line_with_prompt(void)2588 rl_on_new_line_with_prompt (void)
2589 {
2590   int prompt_size, i, l, real_screenwidth, newlines;
2591   char *prompt_last_line, *lprompt;
2592 
2593   /* Initialize visible_line and invisible_line to ensure that they can hold
2594      the already-displayed prompt. */
2595   prompt_size = strlen (rl_prompt) + 1;
2596   init_line_structures (prompt_size);
2597 
2598   /* Make sure the line structures hold the already-displayed prompt for
2599      redisplay. */
2600   lprompt = local_prompt ? local_prompt : rl_prompt;
2601   strcpy (visible_line, lprompt);
2602   strcpy (invisible_line, lprompt);
2603 
2604   /* If the prompt contains newlines, take the last tail. */
2605   prompt_last_line = strrchr (rl_prompt, '\n');
2606   if (!prompt_last_line)
2607     prompt_last_line = rl_prompt;
2608 
2609   l = strlen (prompt_last_line);
2610   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2611     _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1);	/* XXX */
2612   else
2613     _rl_last_c_pos = l;
2614 
2615   /* Dissect prompt_last_line into screen lines. Note that here we have
2616      to use the real screenwidth. Readline's notion of screenwidth might be
2617      one less, see terminal.c. */
2618   real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
2619   _rl_last_v_pos = l / real_screenwidth;
2620   /* If the prompt length is a multiple of real_screenwidth, we don't know
2621      whether the cursor is at the end of the last line, or already at the
2622      beginning of the next line. Output a newline just to be safe. */
2623   if (l > 0 && (l % real_screenwidth) == 0)
2624     _rl_output_some_chars ("\n", 1);
2625   last_lmargin = 0;
2626 
2627   newlines = 0; i = 0;
2628   while (i <= l)
2629     {
2630       _rl_vis_botlin = newlines;
2631       vis_lbreaks[newlines++] = i;
2632       i += real_screenwidth;
2633     }
2634   vis_lbreaks[newlines] = l;
2635   visible_wrap_offset = 0;
2636 
2637   rl_display_prompt = rl_prompt;	/* XXX - make sure it's set */
2638 
2639   return 0;
2640 }
2641 
2642 /* Actually update the display, period. */
2643 int
rl_forced_update_display(void)2644 rl_forced_update_display (void)
2645 {
2646   register char *temp;
2647 
2648   if (visible_line)
2649     {
2650       temp = visible_line;
2651       while (*temp)
2652 	*temp++ = '\0';
2653     }
2654   rl_on_new_line ();
2655   forced_display++;
2656   (*rl_redisplay_function) ();
2657   return 0;
2658 }
2659 
2660 /* Redraw only the last line of a multi-line prompt. */
2661 void
rl_redraw_prompt_last_line(void)2662 rl_redraw_prompt_last_line (void)
2663 {
2664   char *t;
2665 
2666   t = strrchr (rl_display_prompt, '\n');
2667   if (t)
2668     redraw_prompt (++t);
2669   else
2670     rl_forced_update_display ();
2671 }
2672 
2673 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
2674    (Well, when we don't have multibyte characters, _rl_last_c_pos is a
2675    buffer index.)
2676    DATA is the contents of the screen line of interest; i.e., where
2677    the movement is being done.
2678    DATA is always the visible line or the invisible line */
2679 static void
_rl_move_cursor_relative(int new,const char * data,const char * dataf)2680 _rl_move_cursor_relative (int new, const char *data, const char *dataf)
2681 {
2682   register int i;
2683   int woff;			/* number of invisible chars on current line */
2684   int cpos, dpos;		/* current and desired cursor positions */
2685   int adjust;
2686   int in_invisline;
2687   int mb_cur_max = MB_CUR_MAX;
2688 
2689   woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
2690   cpos = _rl_last_c_pos;
2691 
2692   if (cpos == 0 && cpos == new)
2693     return;
2694 
2695 #if defined (HANDLE_MULTIBYTE)
2696   /* If we have multibyte characters, NEW is indexed by the buffer point in
2697      a multibyte string, but _rl_last_c_pos is the display position.  In
2698      this case, NEW's display position is not obvious and must be
2699      calculated.  We need to account for invisible characters in this line,
2700      as long as we are past them and they are counted by _rl_col_width. */
2701   if (mb_cur_max > 1 && rl_byte_oriented == 0)
2702     {
2703       adjust = 1;
2704       /* Try to short-circuit common cases and eliminate a bunch of multibyte
2705 	 character function calls. */
2706       /* 1.  prompt string */
2707       if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2708 	{
2709 	  dpos = prompt_physical_chars;
2710 	  cpos_adjusted = 1;
2711 	  adjust = 0;
2712 	}
2713       /* 2.  prompt_string + line contents */
2714       else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2715 	{
2716 	  dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2717 	  cpos_adjusted = 1;
2718 	  adjust = 0;
2719 	}
2720       else
2721         dpos = _rl_col_width (data, 0, new, 1);
2722 
2723       if (displaying_prompt_first_line == 0)
2724 	adjust = 0;
2725 
2726       /* yet another special case: printing the last line of a prompt with
2727 	 multibyte characters and invisible characters whose printable length
2728 	 exceeds the screen width with the last invisible character
2729 	 (prompt_last_invisible) in the last line.  IN_INVISLINE is the
2730 	 offset of DATA in invisible_line */
2731       in_invisline = 0;
2732       if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
2733 	in_invisline = data - invisible_line;
2734 
2735       /* Use NEW when comparing against the last invisible character in the
2736 	 prompt string, since they're both buffer indices and DPOS is a
2737 	 desired display position. */
2738       /* NEW is relative to the current displayed line, while
2739 	 PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line.
2740 	 Need a way to reconcile these two variables by turning NEW into a
2741 	 buffer position relative to the start of the line */
2742       if (adjust && ((new > prompt_last_invisible) ||		/* XXX - don't use woff here */
2743 		     (new+in_invisline > prompt_last_invisible) ||	/* invisible line */
2744 	  (prompt_physical_chars >= _rl_screenwidth &&		/* visible line */
2745 	   _rl_last_v_pos == prompt_last_screen_line &&
2746 	   wrap_offset >= woff && dpos >= woff &&
2747 	   new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset))))
2748 	   /* XXX last comparison might need to be >= */
2749 	{
2750 	  dpos -= woff;
2751 	  /* Since this will be assigned to _rl_last_c_pos at the end (more
2752 	     precisely, _rl_last_c_pos == dpos when this function returns),
2753 	     let the caller know. */
2754 	  cpos_adjusted = 1;
2755 	}
2756     }
2757   else
2758 #endif
2759     dpos = new;
2760 
2761   /* If we don't have to do anything, then return. */
2762   if (cpos == dpos)
2763     return;
2764 
2765   /* It may be faster to output a CR, and then move forwards instead
2766      of moving backwards. */
2767   /* i == current physical cursor position. */
2768 #if defined (HANDLE_MULTIBYTE)
2769   if (mb_cur_max > 1 && rl_byte_oriented == 0)
2770     i = _rl_last_c_pos;
2771   else
2772 #endif
2773   i = _rl_last_c_pos - woff;
2774   if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
2775       (_rl_term_autowrap && i == _rl_screenwidth))
2776     {
2777       _rl_cr ();
2778       cpos = _rl_last_c_pos = 0;
2779     }
2780 
2781   if (cpos < dpos)
2782     {
2783       /* Move the cursor forward.  We do it by printing the command
2784 	 to move the cursor forward if there is one, else print that
2785 	 portion of the output buffer again.  Which is cheaper? */
2786 
2787       /* The above comment is left here for posterity.  It is faster
2788 	 to print one character (non-control) than to print a control
2789 	 sequence telling the terminal to move forward one character.
2790 	 That kind of control is for people who don't know what the
2791 	 data is underneath the cursor. */
2792 
2793       /* However, we need a handle on where the current display position is
2794 	 in the buffer for the immediately preceding comment to be true.
2795 	 In multibyte locales, we don't currently have that info available.
2796 	 Without it, we don't know where the data we have to display begins
2797 	 in the buffer and we have to go back to the beginning of the screen
2798 	 line.  In this case, we can use the terminal sequence to move forward
2799 	 if it's available. */
2800       if (mb_cur_max > 1 && rl_byte_oriented == 0)
2801 	{
2802 	  if (_rl_term_forward_char)
2803 	    {
2804 	      for (i = cpos; i < dpos; i++)
2805 	        tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2806 	    }
2807 	  else
2808 	    {
2809 	      _rl_cr ();
2810 	      puts_face (data, dataf, new);
2811 	    }
2812 	}
2813       else
2814 	puts_face (data + cpos, dataf + cpos, new - cpos);
2815     }
2816 
2817 #if defined (HANDLE_MULTIBYTE)
2818   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2819      The byte length of the string is probably bigger than the column width
2820      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2821      display point is less than _rl_last_c_pos. */
2822 #endif
2823   else if (cpos > dpos)
2824     _rl_backspace (cpos - dpos);
2825 
2826   _rl_last_c_pos = dpos;
2827 }
2828 
2829 /* PWP: move the cursor up or down. */
2830 void
_rl_move_vert(int to)2831 _rl_move_vert (int to)
2832 {
2833   register int delta, i;
2834 
2835   if (_rl_last_v_pos == to || to > _rl_screenheight)
2836     return;
2837 
2838   if ((delta = to - _rl_last_v_pos) > 0)
2839     {
2840       for (i = 0; i < delta; i++)
2841 	putc ('\n', rl_outstream);
2842       _rl_cr ();
2843       _rl_last_c_pos = 0;
2844     }
2845   else
2846     {			/* delta < 0 */
2847 #ifdef __DJGPP__
2848       int row, col;
2849 
2850       fflush (rl_outstream);
2851       ScreenGetCursor (&row, &col);
2852       ScreenSetCursor (row + delta, col);
2853       i = -delta;
2854 #else
2855       if (_rl_term_up && *_rl_term_up)
2856 	for (i = 0; i < -delta; i++)
2857 	  tputs (_rl_term_up, 1, _rl_output_character_function);
2858 #endif /* !__DJGPP__ */
2859     }
2860 
2861   _rl_last_v_pos = to;		/* Now TO is here */
2862 }
2863 
2864 /* Physically print C on rl_outstream.  This is for functions which know
2865    how to optimize the display.  Return the number of characters output. */
2866 int
rl_show_char(int c)2867 rl_show_char (int c)
2868 {
2869   int n = 1;
2870   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2871     {
2872       fprintf (rl_outstream, "M-");
2873       n += 2;
2874       c = UNMETA (c);
2875     }
2876 
2877 #if defined (DISPLAY_TABS)
2878   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
2879 #else
2880   if (CTRL_CHAR (c) || c == RUBOUT)
2881 #endif /* !DISPLAY_TABS */
2882     {
2883       fprintf (rl_outstream, "C-");
2884       n += 2;
2885       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
2886     }
2887 
2888   putc (c, rl_outstream);
2889   fflush (rl_outstream);
2890   return n;
2891 }
2892 
2893 int
rl_character_len(int c,int pos)2894 rl_character_len (int c, int pos)
2895 {
2896   unsigned char uc;
2897 
2898   uc = (unsigned char)c;
2899 
2900   if (META_CHAR (uc))
2901     return ((_rl_output_meta_chars == 0) ? 4 : 1);
2902 
2903   if (uc == '\t')
2904     {
2905 #if defined (DISPLAY_TABS)
2906       return (((pos | 7) + 1) - pos);
2907 #else
2908       return (2);
2909 #endif /* !DISPLAY_TABS */
2910     }
2911 
2912   if (CTRL_CHAR (c) || c == RUBOUT)
2913     return (2);
2914 
2915   return ((ISPRINT (uc)) ? 1 : 2);
2916 }
2917 /* How to print things in the "echo-area".  The prompt is treated as a
2918    mini-modeline. */
2919 static int msg_saved_prompt = 0;
2920 
2921 #if defined (USE_VARARGS)
2922 int
2923 #if defined (PREFER_STDARG)
rl_message(const char * format,...)2924 rl_message (const char *format, ...)
2925 #else
2926 rl_message (va_alist)
2927      va_dcl
2928 #endif
2929 {
2930   va_list args;
2931 #if defined (PREFER_VARARGS)
2932   char *format;
2933 #endif
2934 #if defined (HAVE_VSNPRINTF)
2935   int bneed;
2936 #endif
2937 
2938 #if defined (PREFER_STDARG)
2939   va_start (args, format);
2940 #else
2941   va_start (args);
2942   format = va_arg (args, char *);
2943 #endif
2944 
2945   if (msg_buf == 0)
2946     msg_buf = xmalloc (msg_bufsiz = 128);
2947 
2948 #if defined (HAVE_VSNPRINTF)
2949   bneed = vsnprintf (msg_buf, msg_bufsiz, format, args);
2950   if (bneed >= msg_bufsiz - 1)
2951     {
2952       msg_bufsiz = bneed + 1;
2953       msg_buf = xrealloc (msg_buf, msg_bufsiz);
2954       va_end (args);
2955 
2956 #if defined (PREFER_STDARG)
2957       va_start (args, format);
2958 #else
2959       va_start (args);
2960       format = va_arg (args, char *);
2961 #endif
2962       vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2963     }
2964 #else
2965   vsprintf (msg_buf, format, args);
2966   msg_buf[msg_bufsiz - 1] = '\0';	/* overflow? */
2967 #endif
2968   va_end (args);
2969 
2970   if (saved_local_prompt == 0)
2971     {
2972       rl_save_prompt ();
2973       msg_saved_prompt = 1;
2974     }
2975   else if (local_prompt != saved_local_prompt)
2976     {
2977       FREE (local_prompt);
2978       FREE (local_prompt_prefix);
2979       local_prompt = (char *)NULL;
2980     }
2981   rl_display_prompt = msg_buf;
2982   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
2983 					    &prompt_last_invisible,
2984 					    &prompt_invis_chars_first_line,
2985 					    &prompt_physical_chars);
2986   local_prompt_prefix = (char *)NULL;
2987   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2988   (*rl_redisplay_function) ();
2989 
2990   return 0;
2991 }
2992 #else /* !USE_VARARGS */
2993 int
rl_message(format,arg1,arg2)2994 rl_message (format, arg1, arg2)
2995      char *format;
2996 {
2997   if (msg_buf == 0)
2998     msg_buf = xmalloc (msg_bufsiz = 128);
2999 
3000   sprintf (msg_buf, format, arg1, arg2);
3001   msg_buf[msg_bufsiz - 1] = '\0';	/* overflow? */
3002 
3003   rl_display_prompt = msg_buf;
3004   if (saved_local_prompt == 0)
3005     {
3006       rl_save_prompt ();
3007       msg_saved_prompt = 1;
3008     }
3009   else if (local_prompt != saved_local_prompt)
3010     {
3011       FREE (local_prompt);
3012       FREE (local_prompt_prefix);
3013       local_prompt = (char *)NULL;
3014     }
3015   local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
3016 					    &prompt_last_invisible,
3017 					    &prompt_invis_chars_first_line,
3018 					    &prompt_physical_chars);
3019   local_prompt_prefix = (char *)NULL;
3020   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
3021   (*rl_redisplay_function) ();
3022 
3023   return 0;
3024 }
3025 #endif /* !USE_VARARGS */
3026 
3027 /* How to clear things from the "echo-area". */
3028 int
rl_clear_message(void)3029 rl_clear_message (void)
3030 {
3031   rl_display_prompt = rl_prompt;
3032   if (msg_saved_prompt)
3033     {
3034       rl_restore_prompt ();
3035       msg_saved_prompt = 0;
3036     }
3037   (*rl_redisplay_function) ();
3038   return 0;
3039 }
3040 
3041 int
rl_reset_line_state(void)3042 rl_reset_line_state (void)
3043 {
3044   rl_on_new_line ();
3045 
3046   rl_display_prompt = rl_prompt ? rl_prompt : "";
3047   forced_display = 1;
3048   return 0;
3049 }
3050 
3051 /* Save all of the variables associated with the prompt and its display. Most
3052    of the complexity is dealing with the invisible characters in the prompt
3053    string and where they are. There are enough of these that I should consider
3054    a struct. */
3055 void
rl_save_prompt(void)3056 rl_save_prompt (void)
3057 {
3058   saved_local_prompt = local_prompt;
3059   saved_local_prefix = local_prompt_prefix;
3060   saved_prefix_length = prompt_prefix_length;
3061   saved_local_length = local_prompt_len;
3062   saved_last_invisible = prompt_last_invisible;
3063   saved_visible_length = prompt_visible_length;
3064   saved_invis_chars_first_line = prompt_invis_chars_first_line;
3065   saved_physical_chars = prompt_physical_chars;
3066   saved_local_prompt_newlines = local_prompt_newlines;
3067 
3068   local_prompt = local_prompt_prefix = (char *)0;
3069   local_prompt_len = 0;
3070   local_prompt_newlines = (int *)0;
3071 
3072   prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
3073   prompt_invis_chars_first_line = prompt_physical_chars = 0;
3074 }
3075 
3076 void
rl_restore_prompt(void)3077 rl_restore_prompt (void)
3078 {
3079   FREE (local_prompt);
3080   FREE (local_prompt_prefix);
3081   FREE (local_prompt_newlines);
3082 
3083   local_prompt = saved_local_prompt;
3084   local_prompt_prefix = saved_local_prefix;
3085   local_prompt_len = saved_local_length;
3086   local_prompt_newlines = saved_local_prompt_newlines;
3087 
3088   prompt_prefix_length = saved_prefix_length;
3089   prompt_last_invisible = saved_last_invisible;
3090   prompt_visible_length = saved_visible_length;
3091   prompt_invis_chars_first_line = saved_invis_chars_first_line;
3092   prompt_physical_chars = saved_physical_chars;
3093 
3094   /* can test saved_local_prompt to see if prompt info has been saved. */
3095   saved_local_prompt = saved_local_prefix = (char *)0;
3096   saved_local_length = 0;
3097   saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
3098   saved_invis_chars_first_line = saved_physical_chars = 0;
3099   saved_local_prompt_newlines = 0;
3100 }
3101 
3102 char *
_rl_make_prompt_for_search(int pchar)3103 _rl_make_prompt_for_search (int pchar)
3104 {
3105   int len;
3106   char *pmt, *p;
3107 
3108   rl_save_prompt ();
3109 
3110   /* We've saved the prompt, and can do anything with the various prompt
3111      strings we need before they're restored.  We want the unexpanded
3112      portion of the prompt string after any final newline. */
3113   p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
3114   if (p == 0)
3115     {
3116       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
3117       pmt = (char *)xmalloc (len + 2);
3118       if (len)
3119 	strcpy (pmt, rl_prompt);
3120       pmt[len] = pchar;
3121       pmt[len+1] = '\0';
3122     }
3123   else
3124     {
3125       p++;
3126       len = strlen (p);
3127       pmt = (char *)xmalloc (len + 2);
3128       if (len)
3129 	strcpy (pmt, p);
3130       pmt[len] = pchar;
3131       pmt[len+1] = '\0';
3132     }
3133 
3134   /* will be overwritten by expand_prompt, called from rl_message */
3135   prompt_physical_chars = saved_physical_chars + 1;
3136   return pmt;
3137 }
3138 
3139 /* Quick redisplay hack when erasing characters at the end of the line. */
3140 void
_rl_erase_at_end_of_line(int l)3141 _rl_erase_at_end_of_line (int l)
3142 {
3143   register int i;
3144 
3145   _rl_backspace (l);
3146   for (i = 0; i < l; i++)
3147     putc (' ', rl_outstream);
3148   _rl_backspace (l);
3149   for (i = 0; i < l; i++)
3150     visible_line[--_rl_last_c_pos] = '\0';
3151   rl_display_fixed++;
3152 }
3153 
3154 /* Clear to the end of the line.  COUNT is the minimum
3155    number of character spaces to clear, but we use a terminal escape
3156    sequence if available. */
3157 void
_rl_clear_to_eol(int count)3158 _rl_clear_to_eol (int count)
3159 {
3160 #ifndef __MSDOS__
3161   if (_rl_term_clreol)
3162     tputs (_rl_term_clreol, 1, _rl_output_character_function);
3163   else
3164 #endif
3165     if (count)
3166       space_to_eol (count);
3167 }
3168 
3169 /* Clear to the end of the line using spaces.  COUNT is the minimum
3170    number of character spaces to clear, */
3171 static void
space_to_eol(int count)3172 space_to_eol (int count)
3173 {
3174   register int i;
3175 
3176   for (i = 0; i < count; i++)
3177     putc (' ', rl_outstream);
3178 
3179   _rl_last_c_pos += count;
3180 }
3181 
3182 void
_rl_clear_screen(int clrscr)3183 _rl_clear_screen (int clrscr)
3184 {
3185 #if defined (__DJGPP__)
3186   ScreenClear ();
3187   ScreenSetCursor (0, 0);
3188 #else
3189   if (_rl_term_clrpag)
3190     {
3191       tputs (_rl_term_clrpag, 1, _rl_output_character_function);
3192       if (clrscr && _rl_term_clrscroll)
3193 	tputs (_rl_term_clrscroll, 1, _rl_output_character_function);
3194     }
3195   else
3196     rl_crlf ();
3197 #endif /* __DJGPP__ */
3198 }
3199 
3200 /* Insert COUNT characters from STRING to the output stream at column COL. */
3201 static void
insert_some_chars(char * string,int count,int col)3202 insert_some_chars (char *string, int count, int col)
3203 {
3204   open_some_spaces (col);
3205   _rl_output_some_chars (string, count);
3206 }
3207 
3208 /* Insert COL spaces, keeping the cursor at the same position.  We follow the
3209    ncurses documentation and use either im/ei with explicit spaces, or IC/ic
3210    by itself.  We assume there will either be ei or we don't need to use it. */
3211 static void
open_some_spaces(int col)3212 open_some_spaces (int col)
3213 {
3214 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
3215   char *buffer;
3216   register int i;
3217 
3218   /* If IC is defined, then we do not have to "enter" insert mode. */
3219   if (_rl_term_IC)
3220     {
3221       buffer = tgoto (_rl_term_IC, 0, col);
3222       tputs (buffer, 1, _rl_output_character_function);
3223     }
3224   else if (_rl_term_im && *_rl_term_im)
3225     {
3226       tputs (_rl_term_im, 1, _rl_output_character_function);
3227       /* just output the desired number of spaces */
3228       for (i = col; i--; )
3229 	_rl_output_character_function (' ');
3230       /* If there is a string to turn off insert mode, use it now. */
3231       if (_rl_term_ei && *_rl_term_ei)
3232 	tputs (_rl_term_ei, 1, _rl_output_character_function);
3233       /* and move back the right number of spaces */
3234       _rl_backspace (col);
3235     }
3236   else if (_rl_term_ic && *_rl_term_ic)
3237     {
3238       /* If there is a special command for inserting characters, then
3239 	 use that first to open up the space. */
3240       for (i = col; i--; )
3241 	tputs (_rl_term_ic, 1, _rl_output_character_function);
3242     }
3243 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
3244 }
3245 
3246 /* Delete COUNT characters from the display line. */
3247 static void
delete_chars(int count)3248 delete_chars (int count)
3249 {
3250   if (count > _rl_screenwidth)	/* XXX */
3251     return;
3252 
3253 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
3254   if (_rl_term_DC && *_rl_term_DC)
3255     {
3256       char *buffer;
3257       buffer = tgoto (_rl_term_DC, count, count);
3258       tputs (buffer, count, _rl_output_character_function);
3259     }
3260   else
3261     {
3262       if (_rl_term_dc && *_rl_term_dc)
3263 	while (count--)
3264 	  tputs (_rl_term_dc, 1, _rl_output_character_function);
3265     }
3266 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
3267 }
3268 
3269 void
_rl_update_final(void)3270 _rl_update_final (void)
3271 {
3272   int full_lines, woff, botline_length;
3273 
3274   if (line_structures_initialized == 0)
3275     return;
3276 
3277   full_lines = 0;
3278   /* If the cursor is the only thing on an otherwise-blank last line,
3279      compensate so we don't print an extra CRLF. */
3280   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
3281 	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
3282     {
3283       _rl_vis_botlin--;
3284       full_lines = 1;
3285     }
3286   _rl_move_vert (_rl_vis_botlin);
3287   woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
3288   botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
3289   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
3290   if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
3291     {
3292       char *last_line, *last_face;
3293 
3294       /* LAST_LINE includes invisible characters, so if you want to get the
3295 	 last character of the first line, you have to take WOFF into account.
3296 	 This needs to be done for both calls to _rl_move_cursor_relative,
3297 	 which takes a buffer position as the first argument, and any direct
3298 	 subscripts of LAST_LINE. */
3299       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
3300       last_face = &vis_face[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
3301       cpos_buffer_position = -1;	/* don't know where we are in buffer */
3302       _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line, last_face);	/* XXX */
3303       _rl_clear_to_eol (0);
3304       puts_face (&last_line[_rl_screenwidth - 1 + woff],
3305 		 &last_face[_rl_screenwidth - 1 + woff], 1);
3306     }
3307   _rl_vis_botlin = 0;
3308   if (botline_length > 0 || _rl_last_c_pos > 0)
3309     rl_crlf ();
3310   fflush (rl_outstream);
3311   rl_display_fixed++;
3312 }
3313 
3314 /* Move to the start of the current line. */
3315 static void
cr(void)3316 cr (void)
3317 {
3318   _rl_cr ();
3319   _rl_last_c_pos = 0;
3320 }
3321 
3322 /* Redraw the last line of a multi-line prompt that may possibly contain
3323    terminal escape sequences.  Called with the cursor at column 0 of the
3324    line to draw the prompt on. */
3325 static void
redraw_prompt(char * t)3326 redraw_prompt (char *t)
3327 {
3328   char *oldp;
3329 
3330   oldp = rl_display_prompt;
3331   rl_save_prompt ();
3332 
3333   rl_display_prompt = t;
3334   local_prompt = expand_prompt (t, PMT_MULTILINE,
3335 				   &prompt_visible_length,
3336 				   &prompt_last_invisible,
3337 				   &prompt_invis_chars_first_line,
3338 				   &prompt_physical_chars);
3339   local_prompt_prefix = (char *)NULL;
3340   local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
3341 
3342   rl_forced_update_display ();
3343 
3344   rl_display_prompt = oldp;
3345   rl_restore_prompt();
3346 }
3347 
3348 /* Redisplay the current line after a SIGWINCH is received. */
3349 void
_rl_redisplay_after_sigwinch(void)3350 _rl_redisplay_after_sigwinch (void)
3351 {
3352   char *t;
3353 
3354   /* Clear the last line (assuming that the screen size change will result in
3355      either more or fewer characters on that line only) and put the cursor at
3356      column 0.  Make sure the right thing happens if we have wrapped to a new
3357      screen line. */
3358   if (_rl_term_cr)
3359     {
3360       _rl_move_vert (_rl_vis_botlin);
3361 
3362       _rl_cr ();
3363       _rl_last_c_pos = 0;
3364 
3365 #if !defined (__MSDOS__)
3366       if (_rl_term_clreol)
3367 	tputs (_rl_term_clreol, 1, _rl_output_character_function);
3368       else
3369 #endif
3370 	{
3371 	  space_to_eol (_rl_screenwidth);
3372 	  _rl_cr ();
3373 	}
3374 
3375       if (_rl_last_v_pos > 0)
3376 	_rl_move_vert (0);
3377     }
3378   else
3379     rl_crlf ();
3380 
3381   /* Redraw only the last line of a multi-line prompt. */
3382   t = strrchr (rl_display_prompt, '\n');
3383   if (t)
3384     redraw_prompt (++t);
3385   else
3386     rl_forced_update_display ();
3387 }
3388 
3389 void
_rl_clean_up_for_exit(void)3390 _rl_clean_up_for_exit (void)
3391 {
3392   if (_rl_echoing_p)
3393     {
3394       if (_rl_vis_botlin > 0)	/* minor optimization plus bug fix */
3395 	_rl_move_vert (_rl_vis_botlin);
3396       _rl_vis_botlin = 0;
3397       fflush (rl_outstream);
3398       rl_restart_output (1, 0);
3399     }
3400 }
3401 
3402 void
_rl_erase_entire_line(void)3403 _rl_erase_entire_line (void)
3404 {
3405   cr ();
3406   _rl_clear_to_eol (0);
3407   cr ();
3408   fflush (rl_outstream);
3409 }
3410 
3411 void
_rl_ttyflush(void)3412 _rl_ttyflush (void)
3413 {
3414   fflush (rl_outstream);
3415 }
3416 
3417 /* return the `current display line' of the cursor -- the number of lines to
3418    move up to get to the first screen line of the current readline line. */
3419 int
_rl_current_display_line(void)3420 _rl_current_display_line (void)
3421 {
3422   int ret, nleft;
3423 
3424   /* Find out whether or not there might be invisible characters in the
3425      editing buffer. */
3426   if (rl_display_prompt == rl_prompt)
3427     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
3428   else
3429     nleft = _rl_last_c_pos - _rl_screenwidth;
3430 
3431   if (nleft > 0)
3432     ret = 1 + nleft / _rl_screenwidth;
3433   else
3434     ret = 0;
3435 
3436   return ret;
3437 }
3438 
3439 void
_rl_refresh_line(void)3440 _rl_refresh_line (void)
3441 {
3442   rl_clear_visible_line ();
3443   rl_redraw_prompt_last_line ();
3444   rl_keep_mark_active ();
3445 }
3446 
3447 #if defined (HANDLE_MULTIBYTE)
3448 /* Calculate the number of screen columns occupied by STR from START to END.
3449    In the case of multibyte characters with stateful encoding, we have to
3450    scan from the beginning of the string to take the state into account. */
3451 static int
_rl_col_width(const char * str,int start,int end,int flags)3452 _rl_col_width (const char *str, int start, int end, int flags)
3453 {
3454   wchar_t wc;
3455   mbstate_t ps;
3456   int tmp, point, width, max;
3457 
3458   if (end <= start)
3459     return 0;
3460   if (MB_CUR_MAX == 1 || rl_byte_oriented)
3461     /* this can happen in some cases where it's inconvenient to check */
3462     return (end - start);
3463 
3464   memset (&ps, 0, sizeof (mbstate_t));
3465 
3466   point = 0;
3467   max = end;
3468 
3469   /* Try to short-circuit common cases.  The adjustment to remove wrap_offset
3470      is done by the caller. */
3471   /* 1.  prompt string */
3472   if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
3473     return (prompt_physical_chars + wrap_offset);
3474   /* 2.  prompt string + line contents */
3475   else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
3476     {
3477       tmp = prompt_physical_chars + wrap_offset;
3478       /* XXX - try to call ourselves recursively with non-prompt portion */
3479       tmp += _rl_col_width (str, local_prompt_len, end, flags);
3480       return (tmp);
3481     }
3482 
3483   while (point < start)
3484     {
3485       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3486 	{
3487 	  memset (&ps, 0, sizeof (mbstate_t));
3488 	  tmp = 1;
3489 	}
3490       else
3491 	tmp = mbrlen (str + point, max, &ps);
3492       if (MB_INVALIDCH ((size_t)tmp))
3493 	{
3494 	  /* In this case, the bytes are invalid or too short to compose a
3495 	     multibyte character, so we assume that the first byte represents
3496 	     a single character. */
3497 	  point++;
3498 	  max--;
3499 
3500 	  /* Clear the state of the byte sequence, because in this case the
3501 	     effect of mbstate is undefined. */
3502 	  memset (&ps, 0, sizeof (mbstate_t));
3503 	}
3504       else if (MB_NULLWCH (tmp))
3505 	break;		/* Found '\0' */
3506       else
3507 	{
3508 	  point += tmp;
3509 	  max -= tmp;
3510 	}
3511     }
3512 
3513   /* If START is not a byte that starts a character, then POINT will be
3514      greater than START.  In this case, assume that (POINT - START) gives
3515      a byte count that is the number of columns of difference. */
3516   width = point - start;
3517 
3518   while (point < end)
3519     {
3520       if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3521 	{
3522 	  tmp = 1;
3523 	  wc = (wchar_t) str[point];
3524 	}
3525       else
3526 	tmp = mbrtowc (&wc, str + point, max, &ps);
3527       if (MB_INVALIDCH ((size_t)tmp))
3528 	{
3529 	  /* In this case, the bytes are invalid or too short to compose a
3530 	     multibyte character, so we assume that the first byte represents
3531 	     a single character. */
3532 	  point++;
3533 	  max--;
3534 
3535 	  /* and assume that the byte occupies a single column. */
3536 	  width++;
3537 
3538 	  /* Clear the state of the byte sequence, because in this case the
3539 	     effect of mbstate is undefined. */
3540 	  memset (&ps, 0, sizeof (mbstate_t));
3541 	}
3542       else if (MB_NULLWCH (tmp))
3543 	break;			/* Found '\0' */
3544       else
3545 	{
3546 	  point += tmp;
3547 	  max -= tmp;
3548 	  tmp = WCWIDTH(wc);
3549 	  width += (tmp >= 0) ? tmp : 1;
3550 	}
3551     }
3552 
3553   width += point - end;
3554 
3555   return width;
3556 }
3557 #endif /* HANDLE_MULTIBYTE */
3558