xref: /openbsd/gnu/lib/libreadline/display.c (revision 9704b281)
1 /* display.c -- readline redisplay facility. */
2 
3 /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
4 
5    This file is part of the GNU Readline Library, a library for
6    reading lines of text with interactive input and history editing.
7 
8    The GNU Readline Library is free software; you can redistribute it
9    and/or modify it under the terms of the GNU General Public License
10    as published by the Free Software Foundation; either version 2, or
11    (at your option) any later version.
12 
13    The GNU Readline Library is distributed in the hope that it will be
14    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    The GNU General Public License is often shipped with GNU software, and
19    is generally kept in a file called COPYING or LICENSE.  If you do not
20    have a copy of the license, write to the Free Software Foundation,
21    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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 /* System-specific feature definitions and include files. */
45 #include "rldefs.h"
46 #include "rlmbutil.h"
47 
48 /* Termcap library stuff. */
49 #include "tcap.h"
50 
51 /* Some standard library routines. */
52 #include "readline.h"
53 #include "history.h"
54 
55 #include "rlprivate.h"
56 #include "xmalloc.h"
57 
58 #if !defined (strchr) && !defined (__STDC__)
59 extern char *strchr (), *strrchr ();
60 #endif /* !strchr && !__STDC__ */
61 
62 #if defined (HACK_TERMCAP_MOTION)
63 extern char *_rl_term_forward_char;
64 #endif
65 
66 static void update_line PARAMS((char *, char *, int, int, int, int));
67 static void space_to_eol PARAMS((int));
68 static void delete_chars PARAMS((int));
69 static void insert_some_chars PARAMS((char *, int, int));
70 static void cr PARAMS((void));
71 
72 #if defined (HANDLE_MULTIBYTE)
73 static int _rl_col_width PARAMS((const char *, int, int));
74 static int *_rl_wrapped_line;
75 #else
76 #  define _rl_col_width(l, s, e)	(((e) <= (s)) ? 0 : (e) - (s))
77 #endif
78 
79 static int *inv_lbreaks, *vis_lbreaks;
80 static int inv_lbsize, vis_lbsize;
81 
82 /* Heuristic used to decide whether it is faster to move from CUR to NEW
83    by backing up or outputting a carriage return and moving forward. */
84 #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
85 
86 /* **************************************************************** */
87 /*								    */
88 /*			Display stuff				    */
89 /*								    */
90 /* **************************************************************** */
91 
92 /* This is the stuff that is hard for me.  I never seem to write good
93    display routines in C.  Let's see how I do this time. */
94 
95 /* (PWP) Well... Good for a simple line updater, but totally ignores
96    the problems of input lines longer than the screen width.
97 
98    update_line and the code that calls it makes a multiple line,
99    automatically wrapping line update.  Careful attention needs
100    to be paid to the vertical position variables. */
101 
102 /* Keep two buffers; one which reflects the current contents of the
103    screen, and the other to draw what we think the new contents should
104    be.  Then compare the buffers, and make whatever changes to the
105    screen itself that we should.  Finally, make the buffer that we
106    just drew into be the one which reflects the current contents of the
107    screen, and place the cursor where it belongs.
108 
109    Commands that want to can fix the display themselves, and then let
110    this function know that the display has been fixed by setting the
111    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
112 
113 /* Application-specific redisplay function. */
114 rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
115 
116 /* Global variables declared here. */
117 /* What YOU turn on when you have handled all redisplay yourself. */
118 int rl_display_fixed = 0;
119 
120 int _rl_suppress_redisplay = 0;
121 
122 /* The stuff that gets printed out before the actual text of the line.
123    This is usually pointing to rl_prompt. */
124 char *rl_display_prompt = (char *)NULL;
125 
126 /* Pseudo-global variables declared here. */
127 /* The visible cursor position.  If you print some text, adjust this. */
128 int _rl_last_c_pos = 0;
129 int _rl_last_v_pos = 0;
130 
131 /* Number of lines currently on screen minus 1. */
132 int _rl_vis_botlin = 0;
133 
134 /* Variables used only in this file. */
135 /* The last left edge of text that was displayed.  This is used when
136    doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
137 static int last_lmargin;
138 
139 /* The line display buffers.  One is the line currently displayed on
140    the screen.  The other is the line about to be displayed. */
141 static char *visible_line = (char *)NULL;
142 static char *invisible_line = (char *)NULL;
143 
144 /* A buffer for `modeline' messages. */
145 static char msg_buf[128];
146 
147 /* Non-zero forces the redisplay even if we thought it was unnecessary. */
148 static int forced_display;
149 
150 /* Default and initial buffer size.  Can grow. */
151 static int line_size = 1024;
152 
153 /* Variables to keep track of the expanded prompt string, which may
154    include invisible characters. */
155 
156 static char *local_prompt, *local_prompt_prefix;
157 static int prompt_visible_length, prompt_prefix_length;
158 
159 /* The number of invisible characters in the line currently being
160    displayed on the screen. */
161 static int visible_wrap_offset;
162 
163 /* The number of invisible characters in the prompt string.  Static so it
164    can be shared between rl_redisplay and update_line */
165 static int wrap_offset;
166 
167 /* The index of the last invisible character in the prompt string. */
168 static int prompt_last_invisible;
169 
170 /* The length (buffer offset) of the first line of the last (possibly
171    multi-line) buffer displayed on the screen. */
172 static int visible_first_line_len;
173 
174 /* Number of invisible characters on the first physical line of the prompt.
175    Only valid when the number of physical characters in the prompt exceeds
176    (or is equal to) _rl_screenwidth. */
177 static int prompt_invis_chars_first_line;
178 
179 static int prompt_last_screen_line;
180 
181 /* Expand the prompt string S and return the number of visible
182    characters in *LP, if LP is not null.  This is currently more-or-less
183    a placeholder for expansion.  LIP, if non-null is a place to store the
184    index of the last invisible character in the returned string. NIFLP,
185    if non-zero, is a place to store the number of invisible characters in
186    the first prompt line. */
187 
188 /* Current implementation:
189 	\001 (^A) start non-visible characters
190 	\002 (^B) end non-visible characters
191    all characters except \001 and \002 (following a \001) are copied to
192    the returned string; all characters except those between \001 and
193    \002 are assumed to be `visible'. */
194 
195 static char *
expand_prompt(pmt,lp,lip,niflp)196 expand_prompt (pmt, lp, lip, niflp)
197      char *pmt;
198      int *lp, *lip, *niflp;
199 {
200   char *r, *ret, *p;
201   int l, rl, last, ignoring, ninvis, invfl;
202 
203   /* Short-circuit if we can. */
204   if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
205     {
206       r = savestring (pmt);
207       if (lp)
208 	*lp = strlen (r);
209       return r;
210     }
211 
212   l = strlen (pmt);
213   r = ret = (char *)xmalloc (l + 1);
214 
215   invfl = 0;	/* invisible chars in first line of prompt */
216 
217   for (rl = ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
218     {
219       /* This code strips the invisible character string markers
220 	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
221       if (*p == RL_PROMPT_START_IGNORE)
222 	{
223 	  ignoring++;
224 	  continue;
225 	}
226       else if (ignoring && *p == RL_PROMPT_END_IGNORE)
227 	{
228 	  ignoring = 0;
229 	  last = r - ret - 1;
230 	  continue;
231 	}
232       else
233 	{
234 	  *r++ = *p;
235 	  if (!ignoring)
236 	    rl++;
237 	  else
238 	    ninvis++;
239 	  if (rl == _rl_screenwidth)
240 	    invfl = ninvis;
241 	}
242     }
243 
244   if (rl < _rl_screenwidth)
245     invfl = ninvis;
246 
247   *r = '\0';
248   if (lp)
249     *lp = rl;
250   if (lip)
251     *lip = last;
252   if (niflp)
253     *niflp = invfl;
254   return ret;
255 }
256 
257 /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
258    PMT and return the rest of PMT. */
259 char *
_rl_strip_prompt(pmt)260 _rl_strip_prompt (pmt)
261      char *pmt;
262 {
263   char *ret;
264 
265   ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL);
266   return ret;
267 }
268 
269 /*
270  * Expand the prompt string into the various display components, if
271  * necessary.
272  *
273  * local_prompt = expanded last line of string in rl_display_prompt
274  *		  (portion after the final newline)
275  * local_prompt_prefix = portion before last newline of rl_display_prompt,
276  *			 expanded via expand_prompt
277  * prompt_visible_length = number of visible characters in local_prompt
278  * prompt_prefix_length = number of visible characters in local_prompt_prefix
279  *
280  * This function is called once per call to readline().  It may also be
281  * called arbitrarily to expand the primary prompt.
282  *
283  * The return value is the number of visible characters on the last line
284  * of the (possibly multi-line) prompt.
285  */
286 int
rl_expand_prompt(prompt)287 rl_expand_prompt (prompt)
288      char *prompt;
289 {
290   char *p, *t;
291   int c;
292 
293   /* Clear out any saved values. */
294   FREE (local_prompt);
295   FREE (local_prompt_prefix);
296 
297   local_prompt = local_prompt_prefix = (char *)0;
298   prompt_last_invisible = prompt_visible_length = 0;
299 
300   if (prompt == 0 || *prompt == 0)
301     return (0);
302 
303   p = strrchr (prompt, '\n');
304   if (!p)
305     {
306       /* The prompt is only one logical line, though it might wrap. */
307       local_prompt = expand_prompt (prompt, &prompt_visible_length,
308 					    &prompt_last_invisible,
309 					    &prompt_invis_chars_first_line);
310       local_prompt_prefix = (char *)0;
311       return (prompt_visible_length);
312     }
313   else
314     {
315       /* The prompt spans multiple lines. */
316       t = ++p;
317       local_prompt = expand_prompt (p, &prompt_visible_length,
318 				       &prompt_last_invisible,
319 				       &prompt_invis_chars_first_line);
320       c = *t; *t = '\0';
321       /* The portion of the prompt string up to and including the
322 	 final newline is now null-terminated. */
323       local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
324 						   (int *)NULL,
325 						   &prompt_invis_chars_first_line);
326       *t = c;
327       return (prompt_prefix_length);
328     }
329 }
330 
331 /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
332    arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
333    and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
334    increased.  If the lines have already been allocated, this ensures that
335    they can hold at least MINSIZE characters. */
336 static void
init_line_structures(minsize)337 init_line_structures (minsize)
338       int minsize;
339 {
340   register int n;
341 
342   if (invisible_line == 0)	/* initialize it */
343     {
344       if (line_size < minsize)
345 	line_size = minsize;
346       visible_line = (char *)xmalloc (line_size);
347       invisible_line = (char *)xmalloc (line_size);
348     }
349   else if (line_size < minsize)	/* ensure it can hold MINSIZE chars */
350     {
351       line_size *= 2;
352       if (line_size < minsize)
353 	line_size = minsize;
354       visible_line = (char *)xrealloc (visible_line, line_size);
355       invisible_line = (char *)xrealloc (invisible_line, line_size);
356     }
357 
358   for (n = minsize; n < line_size; n++)
359     {
360       visible_line[n] = 0;
361       invisible_line[n] = 1;
362     }
363 
364   if (vis_lbreaks == 0)
365     {
366       /* should be enough. */
367       inv_lbsize = vis_lbsize = 256;
368       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
369       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
370 #if defined (HANDLE_MULTIBYTE)
371       _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
372 #endif
373       inv_lbreaks[0] = vis_lbreaks[0] = 0;
374     }
375 }
376 
377 /* Basic redisplay algorithm. */
378 void
rl_redisplay()379 rl_redisplay ()
380 {
381   register int in, out, c, linenum, cursor_linenum;
382   register char *line;
383   int c_pos, inv_botlin, lb_botlin, lb_linenum;
384   int newlines, lpos, temp;
385   char *prompt_this_line;
386 #if defined (HANDLE_MULTIBYTE)
387   wchar_t wc;
388   size_t wc_bytes;
389   int wc_width;
390   mbstate_t ps;
391   int _rl_wrapped_multicolumn = 0;
392 #endif
393 
394   if (!readline_echoing_p)
395     return;
396 
397   if (!rl_display_prompt)
398     rl_display_prompt = "";
399 
400   if (invisible_line == 0)
401     {
402       init_line_structures (0);
403       rl_on_new_line ();
404     }
405 
406   /* Draw the line into the buffer. */
407   c_pos = -1;
408 
409   line = invisible_line;
410   out = inv_botlin = 0;
411 
412   /* Mark the line as modified or not.  We only do this for history
413      lines. */
414   if (_rl_mark_modified_lines && current_history () && rl_undo_list)
415     {
416       line[out++] = '*';
417       line[out] = '\0';
418     }
419 
420   /* If someone thought that the redisplay was handled, but the currently
421      visible line has a different modification state than the one about
422      to become visible, then correct the caller's misconception. */
423   if (visible_line[0] != invisible_line[0])
424     rl_display_fixed = 0;
425 
426   /* If the prompt to be displayed is the `primary' readline prompt (the
427      one passed to readline()), use the values we have already expanded.
428      If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
429      number of non-visible characters in the prompt string. */
430   if (rl_display_prompt == rl_prompt || local_prompt)
431     {
432       int local_len = local_prompt ? strlen (local_prompt) : 0;
433       if (local_prompt_prefix && forced_display)
434 	_rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
435 
436       if (local_len > 0)
437 	{
438 	  temp = local_len + out + 2;
439 	  if (temp >= line_size)
440 	    {
441 	      line_size = (temp + 1024) - (temp % 1024);
442 	      visible_line = (char *)xrealloc (visible_line, line_size);
443 	      line = invisible_line = (char *)xrealloc (invisible_line, line_size);
444 	    }
445 	  strncpy (line + out, local_prompt, local_len);
446 	  out += local_len;
447 	}
448       line[out] = '\0';
449       wrap_offset = local_len - prompt_visible_length;
450     }
451   else
452     {
453       int pmtlen;
454       prompt_this_line = strrchr (rl_display_prompt, '\n');
455       if (!prompt_this_line)
456 	prompt_this_line = rl_display_prompt;
457       else
458 	{
459 	  prompt_this_line++;
460 	  pmtlen = prompt_this_line - rl_display_prompt;	/* temp var */
461 	  if (forced_display)
462 	    {
463 	      _rl_output_some_chars (rl_display_prompt, pmtlen);
464 	      /* Make sure we are at column zero even after a newline,
465 		 regardless of the state of terminal output processing. */
466 	      if (pmtlen < 2 || prompt_this_line[-2] != '\r')
467 		cr ();
468 	    }
469 	}
470 
471       pmtlen = strlen (prompt_this_line);
472       temp = pmtlen + out + 2;
473       if (temp >= line_size)
474 	{
475 	  line_size = (temp + 1024) - (temp % 1024);
476 	  visible_line = (char *)xrealloc (visible_line, line_size);
477 	  line = invisible_line = (char *)xrealloc (invisible_line, line_size);
478 	}
479       strncpy (line + out,  prompt_this_line, pmtlen);
480       out += pmtlen;
481       line[out] = '\0';
482       wrap_offset = prompt_invis_chars_first_line = 0;
483     }
484 
485 #define CHECK_INV_LBREAKS() \
486       do { \
487 	if (newlines >= (inv_lbsize - 2)) \
488 	  { \
489 	    inv_lbsize *= 2; \
490 	    inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
491 	  } \
492       } while (0)
493 
494 #if defined (HANDLE_MULTIBYTE)
495 #define CHECK_LPOS() \
496       do { \
497 	lpos++; \
498 	if (lpos >= _rl_screenwidth) \
499 	  { \
500 	    if (newlines >= (inv_lbsize - 2)) \
501 	      { \
502 		inv_lbsize *= 2; \
503 		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
504 		_rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
505 	      } \
506 	    inv_lbreaks[++newlines] = out; \
507 	    _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
508 	    lpos = 0; \
509 	  } \
510       } while (0)
511 #else
512 #define CHECK_LPOS() \
513       do { \
514 	lpos++; \
515 	if (lpos >= _rl_screenwidth) \
516 	  { \
517 	    if (newlines >= (inv_lbsize - 2)) \
518 	      { \
519 		inv_lbsize *= 2; \
520 		inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
521 	      } \
522 	    inv_lbreaks[++newlines] = out; \
523 	    lpos = 0; \
524 	  } \
525       } while (0)
526 #endif
527 
528   /* inv_lbreaks[i] is where line i starts in the buffer. */
529   inv_lbreaks[newlines = 0] = 0;
530   lpos = out - wrap_offset;
531 #if defined (HANDLE_MULTIBYTE)
532   memset (_rl_wrapped_line, 0, vis_lbsize);
533 #endif
534 
535   /* prompt_invis_chars_first_line is the number of invisible characters in
536      the first physical line of the prompt.
537      wrap_offset - prompt_invis_chars_first_line is the number of invis
538      chars on the second line. */
539 
540   /* what if lpos is already >= _rl_screenwidth before we start drawing the
541      contents of the command line? */
542   while (lpos >= _rl_screenwidth)
543     {
544       /* fix from Darin Johnson <darin@acuson.com> for prompt string with
545          invisible characters that is longer than the screen width.  The
546          prompt_invis_chars_first_line variable could be made into an array
547          saying how many invisible characters there are per line, but that's
548          probably too much work for the benefit gained.  How many people have
549          prompts that exceed two physical lines? */
550       temp = ((newlines + 1) * _rl_screenwidth) +
551 #if 0
552              ((newlines == 0) ? prompt_invis_chars_first_line : 0) +
553 #else
554              ((newlines == 0 && local_prompt_prefix == 0) ? prompt_invis_chars_first_line : 0) +
555 #endif
556              ((newlines == 1) ? wrap_offset : 0);
557 
558       inv_lbreaks[++newlines] = temp;
559       lpos -= _rl_screenwidth;
560     }
561 
562   prompt_last_screen_line = newlines;
563 
564   /* Draw the rest of the line (after the prompt) into invisible_line, keeping
565      track of where the cursor is (c_pos), the number of the line containing
566      the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
567      It maintains an array of line breaks for display (inv_lbreaks).
568      This handles expanding tabs for display and displaying meta characters. */
569   lb_linenum = 0;
570 #if defined (HANDLE_MULTIBYTE)
571   in = 0;
572   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
573     {
574       memset (&ps, 0, sizeof (mbstate_t));
575       wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
576     }
577   else
578     wc_bytes = 1;
579   while (in < rl_end)
580 #else
581   for (in = 0; in < rl_end; in++)
582 #endif
583     {
584       c = (unsigned char)rl_line_buffer[in];
585 
586 #if defined (HANDLE_MULTIBYTE)
587       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
588 	{
589 	  if (wc_bytes == (size_t)-1 || wc_bytes == (size_t)-2)
590 	    {
591 	      /* Byte sequence is invalid or shortened.  Assume that the
592 	         first byte represents a character. */
593 	      wc_bytes = 1;
594 	      /* Assume that a character occupies a single column. */
595 	      wc_width = 1;
596 	      memset (&ps, 0, sizeof (mbstate_t));
597 	    }
598 	  else if (wc_bytes == (size_t)0)
599 	    break;			/* Found '\0' */
600 	  else
601 	    {
602 	      temp = wcwidth (wc);
603 	      wc_width = (temp < 0) ? 1 : temp;
604 	    }
605 	}
606 #endif
607 
608       if (out + 8 >= line_size)		/* XXX - 8 for \t */
609 	{
610 	  line_size *= 2;
611 	  visible_line = (char *)xrealloc (visible_line, line_size);
612 	  invisible_line = (char *)xrealloc (invisible_line, line_size);
613 	  line = invisible_line;
614 	}
615 
616       if (in == rl_point)
617 	{
618 	  c_pos = out;
619 	  lb_linenum = newlines;
620 	}
621 
622 #if defined (HANDLE_MULTIBYTE)
623       if (META_CHAR (c) && _rl_output_meta_chars == 0)	/* XXX - clean up */
624 #else
625       if (META_CHAR (c))
626 #endif
627 	{
628 	  if (_rl_output_meta_chars == 0)
629 	    {
630 	      snprintf (line + out, line_size - out, "\\%o", c);
631 
632 	      if (lpos + 4 >= _rl_screenwidth)
633 		{
634 		  temp = _rl_screenwidth - lpos;
635 		  CHECK_INV_LBREAKS ();
636 		  inv_lbreaks[++newlines] = out + temp;
637 		  lpos = 4 - temp;
638 		}
639 	      else
640 		lpos += 4;
641 
642 	      out += 4;
643 	    }
644 	  else
645 	    {
646 	      line[out++] = c;
647 	      CHECK_LPOS();
648 	    }
649 	}
650 #if defined (DISPLAY_TABS)
651       else if (c == '\t')
652 	{
653 	  register int newout;
654 
655 #if 0
656 	  newout = (out | (int)7) + 1;
657 #else
658 	  newout = out + 8 - lpos % 8;
659 #endif
660 	  temp = newout - out;
661 	  if (lpos + temp >= _rl_screenwidth)
662 	    {
663 	      register int temp2;
664 	      temp2 = _rl_screenwidth - lpos;
665 	      CHECK_INV_LBREAKS ();
666 	      inv_lbreaks[++newlines] = out + temp2;
667 	      lpos = temp - temp2;
668 	      while (out < newout)
669 		line[out++] = ' ';
670 	    }
671 	  else
672 	    {
673 	      while (out < newout)
674 		line[out++] = ' ';
675 	      lpos += temp;
676 	    }
677 	}
678 #endif
679       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
680 	{
681 	  line[out++] = '\0';	/* XXX - sentinel */
682 	  CHECK_INV_LBREAKS ();
683 	  inv_lbreaks[++newlines] = out;
684 	  lpos = 0;
685 	}
686       else if (CTRL_CHAR (c) || c == RUBOUT)
687 	{
688 	  line[out++] = '^';
689 	  CHECK_LPOS();
690 	  line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
691 	  CHECK_LPOS();
692 	}
693       else
694 	{
695 #if defined (HANDLE_MULTIBYTE)
696 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
697 	    {
698 	      register int i;
699 
700 	      _rl_wrapped_multicolumn = 0;
701 
702 	      if (_rl_screenwidth < lpos + wc_width)
703 		for (i = lpos; i < _rl_screenwidth; i++)
704 		  {
705 		    /* The space will be removed in update_line() */
706 		    line[out++] = ' ';
707 		    _rl_wrapped_multicolumn++;
708 		    CHECK_LPOS();
709 		  }
710 	      if (in == rl_point)
711 		{
712 		  c_pos = out;
713 		  lb_linenum = newlines;
714 		}
715 	      for (i = in; i < in+wc_bytes; i++)
716 		line[out++] = rl_line_buffer[i];
717 	      for (i = 0; i < wc_width; i++)
718 		CHECK_LPOS();
719 	    }
720 	  else
721 	    {
722 	      line[out++] = c;
723 	      CHECK_LPOS();
724 	    }
725 #else
726 	  line[out++] = c;
727 	  CHECK_LPOS();
728 #endif
729 	}
730 
731 #if defined (HANDLE_MULTIBYTE)
732       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
733 	{
734 	  in += wc_bytes;
735 	  wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
736 	}
737       else
738         in++;
739 #endif
740 
741     }
742   line[out] = '\0';
743   if (c_pos < 0)
744     {
745       c_pos = out;
746       lb_linenum = newlines;
747     }
748 
749   inv_botlin = lb_botlin = newlines;
750   CHECK_INV_LBREAKS ();
751   inv_lbreaks[newlines+1] = out;
752   cursor_linenum = lb_linenum;
753 
754   /* C_POS == position in buffer where cursor should be placed.
755      CURSOR_LINENUM == line number where the cursor should be placed. */
756 
757   /* PWP: now is when things get a bit hairy.  The visible and invisible
758      line buffers are really multiple lines, which would wrap every
759      (screenwidth - 1) characters.  Go through each in turn, finding
760      the changed region and updating it.  The line order is top to bottom. */
761 
762   /* If we can move the cursor up and down, then use multiple lines,
763      otherwise, let long lines display in a single terminal line, and
764      horizontally scroll it. */
765 
766   if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
767     {
768       int nleft, pos, changed_screen_line;
769 
770       if (!rl_display_fixed || forced_display)
771 	{
772 	  forced_display = 0;
773 
774 	  /* If we have more than a screenful of material to display, then
775 	     only display a screenful.  We should display the last screen,
776 	     not the first.  */
777 	  if (out >= _rl_screenchars)
778 	    {
779 	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
780 		out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
781 	      else
782 		out = _rl_screenchars - 1;
783 	    }
784 
785 	  /* The first line is at character position 0 in the buffer.  The
786 	     second and subsequent lines start at inv_lbreaks[N], offset by
787 	     OFFSET (which has already been calculated above).  */
788 
789 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
790 #define VIS_LLEN(l)	((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
791 #define INV_LLEN(l)	(inv_lbreaks[l+1] - inv_lbreaks[l])
792 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
793 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
794 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
795 
796 	  /* For each line in the buffer, do the updating display. */
797 	  for (linenum = 0; linenum <= inv_botlin; linenum++)
798 	    {
799 	      update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
800 			   VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
801 
802 	      /* If this is the line with the prompt, we might need to
803 		 compensate for invisible characters in the new line. Do
804 		 this only if there is not more than one new line (which
805 		 implies that we completely overwrite the old visible line)
806 		 and the new line is shorter than the old.  Make sure we are
807 		 at the end of the new line before clearing. */
808 	      if (linenum == 0 &&
809 		  inv_botlin == 0 && _rl_last_c_pos == out &&
810 		  (wrap_offset > visible_wrap_offset) &&
811 		  (_rl_last_c_pos < visible_first_line_len))
812 		{
813 		  nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
814 		  if (nleft)
815 		    _rl_clear_to_eol (nleft);
816 		}
817 
818 	      /* Since the new first line is now visible, save its length. */
819 	      if (linenum == 0)
820 		visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
821 	    }
822 
823 	  /* We may have deleted some lines.  If so, clear the left over
824 	     blank ones at the bottom out. */
825 	  if (_rl_vis_botlin > inv_botlin)
826 	    {
827 	      char *tt;
828 	      for (; linenum <= _rl_vis_botlin; linenum++)
829 		{
830 		  tt = VIS_CHARS (linenum);
831 		  _rl_move_vert (linenum);
832 		  _rl_move_cursor_relative (0, tt);
833 		  _rl_clear_to_eol
834 		    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
835 		}
836 	    }
837 	  _rl_vis_botlin = inv_botlin;
838 
839 	  /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
840 	     different screen line during this redisplay. */
841 	  changed_screen_line = _rl_last_v_pos != cursor_linenum;
842 	  if (changed_screen_line)
843 	    {
844 	      _rl_move_vert (cursor_linenum);
845 	      /* If we moved up to the line with the prompt using _rl_term_up,
846 		 the physical cursor position on the screen stays the same,
847 		 but the buffer position needs to be adjusted to account
848 		 for invisible characters. */
849 	      if (cursor_linenum == 0 && wrap_offset)
850 		_rl_last_c_pos += wrap_offset;
851 	    }
852 
853 	  /* We have to reprint the prompt if it contains invisible
854 	     characters, since it's not generally OK to just reprint
855 	     the characters from the current cursor position.  But we
856 	     only need to reprint it if the cursor is before the last
857 	     invisible character in the prompt string. */
858 	  nleft = prompt_visible_length + wrap_offset;
859 	  if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
860 	      _rl_last_c_pos <= prompt_last_invisible && local_prompt)
861 	    {
862 #if defined (__MSDOS__)
863 	      putc ('\r', rl_outstream);
864 #else
865 	      if (_rl_term_cr)
866 		tputs (_rl_term_cr, 1, _rl_output_character_function);
867 #endif
868 	      _rl_output_some_chars (local_prompt, nleft);
869 	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
870 		_rl_last_c_pos = _rl_col_width(local_prompt, 0, nleft);
871 	      else
872 		_rl_last_c_pos = nleft;
873 	    }
874 
875 	  /* Where on that line?  And where does that line start
876 	     in the buffer? */
877 	  pos = inv_lbreaks[cursor_linenum];
878 	  /* nleft == number of characters in the line buffer between the
879 	     start of the line and the cursor position. */
880 	  nleft = c_pos - pos;
881 
882 	  /* Since _rl_backspace() doesn't know about invisible characters in the
883 	     prompt, and there's no good way to tell it, we compensate for
884 	     those characters here and call _rl_backspace() directly. */
885 	  if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
886 	    {
887 	      _rl_backspace (_rl_last_c_pos - nleft);
888 	      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
889 		_rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft);
890 	      else
891 		_rl_last_c_pos = nleft;
892 	    }
893 
894 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
895 	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
896 	  else if (nleft != _rl_last_c_pos)
897 	    _rl_move_cursor_relative (nleft, &invisible_line[pos]);
898 	}
899     }
900   else				/* Do horizontal scrolling. */
901     {
902 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
903       int lmargin, ndisp, nleft, phys_c_pos, t;
904 
905       /* Always at top line. */
906       _rl_last_v_pos = 0;
907 
908       /* Compute where in the buffer the displayed line should start.  This
909 	 will be LMARGIN. */
910 
911       /* The number of characters that will be displayed before the cursor. */
912       ndisp = c_pos - wrap_offset;
913       nleft  = prompt_visible_length + wrap_offset;
914       /* Where the new cursor position will be on the screen.  This can be
915 	 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
916       phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
917       t = _rl_screenwidth / 3;
918 
919       /* If the number of characters had already exceeded the screenwidth,
920 	 last_lmargin will be > 0. */
921 
922       /* If the number of characters to be displayed is more than the screen
923 	 width, compute the starting offset so that the cursor is about
924 	 two-thirds of the way across the screen. */
925       if (phys_c_pos > _rl_screenwidth - 2)
926 	{
927 	  lmargin = c_pos - (2 * t);
928 	  if (lmargin < 0)
929 	    lmargin = 0;
930 	  /* If the left margin would be in the middle of a prompt with
931 	     invisible characters, don't display the prompt at all. */
932 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
933 	    lmargin = nleft;
934 	}
935       else if (ndisp < _rl_screenwidth - 2)		/* XXX - was -1 */
936 	lmargin = 0;
937       else if (phys_c_pos < 1)
938 	{
939 	  /* If we are moving back towards the beginning of the line and
940 	     the last margin is no longer correct, compute a new one. */
941 	  lmargin = ((c_pos - 1) / t) * t;	/* XXX */
942 	  if (wrap_offset && lmargin > 0 && lmargin < nleft)
943 	    lmargin = nleft;
944 	}
945       else
946 	lmargin = last_lmargin;
947 
948       /* If the first character on the screen isn't the first character
949 	 in the display line, indicate this with a special character. */
950       if (lmargin > 0)
951 	line[lmargin] = '<';
952 
953       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
954 	 the whole line, indicate that with a special character at the
955 	 right edge of the screen.  If LMARGIN is 0, we need to take the
956 	 wrap offset into account. */
957       t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
958       if (t < out)
959 	line[t - 1] = '>';
960 
961       if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
962 	{
963 	  forced_display = 0;
964 	  update_line (&visible_line[last_lmargin],
965 		       &invisible_line[lmargin],
966 		       0,
967 		       _rl_screenwidth + visible_wrap_offset,
968 		       _rl_screenwidth + (lmargin ? 0 : wrap_offset),
969 		       0);
970 
971 	  /* If the visible new line is shorter than the old, but the number
972 	     of invisible characters is greater, and we are at the end of
973 	     the new line, we need to clear to eol. */
974 	  t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
975 	  if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
976 	      (_rl_last_c_pos == out) &&
977 	      t < visible_first_line_len)
978 	    {
979 	      nleft = _rl_screenwidth - t;
980 	      _rl_clear_to_eol (nleft);
981 	    }
982 	  visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
983 	  if (visible_first_line_len > _rl_screenwidth)
984 	    visible_first_line_len = _rl_screenwidth;
985 
986 	  _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
987 	  last_lmargin = lmargin;
988 	}
989     }
990   fflush (rl_outstream);
991 
992   /* Swap visible and non-visible lines. */
993   {
994     char *vtemp = visible_line;
995     int *itemp = vis_lbreaks, ntemp = vis_lbsize;
996 
997     visible_line = invisible_line;
998     invisible_line = vtemp;
999 
1000     vis_lbreaks = inv_lbreaks;
1001     inv_lbreaks = itemp;
1002 
1003     vis_lbsize = inv_lbsize;
1004     inv_lbsize = ntemp;
1005 
1006     rl_display_fixed = 0;
1007     /* If we are displaying on a single line, and last_lmargin is > 0, we
1008        are not displaying any invisible characters, so set visible_wrap_offset
1009        to 0. */
1010     if (_rl_horizontal_scroll_mode && last_lmargin)
1011       visible_wrap_offset = 0;
1012     else
1013       visible_wrap_offset = wrap_offset;
1014   }
1015 }
1016 
1017 /* PWP: update_line() is based on finding the middle difference of each
1018    line on the screen; vis:
1019 
1020 			     /old first difference
1021 	/beginning of line   |	      /old last same       /old EOL
1022 	v		     v	      v		    v
1023 old:	eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1024 new:	eddie> Oh, my little buggy says to me, as lurgid as
1025 	^		     ^	^			   ^
1026 	\beginning of line   |	\new last same	   \new end of line
1027 			     \new first difference
1028 
1029    All are character pointers for the sake of speed.  Special cases for
1030    no differences, as well as for end of line additions must be handled.
1031 
1032    Could be made even smarter, but this works well enough */
1033 static void
update_line(old,new,current_line,omax,nmax,inv_botlin)1034 update_line (old, new, current_line, omax, nmax, inv_botlin)
1035      register char *old, *new;
1036      int current_line, omax, nmax, inv_botlin;
1037 {
1038   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
1039   int temp, lendiff, wsatend, od, nd;
1040   int current_invis_chars;
1041   int col_lendiff, col_temp;
1042 #if defined (HANDLE_MULTIBYTE)
1043   mbstate_t ps_new, ps_old;
1044   int new_offset, old_offset, tmp;
1045 #endif
1046 
1047   /* If we're at the right edge of a terminal that supports xn, we're
1048      ready to wrap around, so do so.  This fixes problems with knowing
1049      the exact cursor position and cut-and-paste with certain terminal
1050      emulators.  In this calculation, TEMP is the physical screen
1051      position of the cursor. */
1052   temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1053   if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1054 	&& _rl_last_v_pos == current_line - 1)
1055     {
1056 #if defined (HANDLE_MULTIBYTE)
1057       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1058 	{
1059 	  wchar_t wc;
1060 	  mbstate_t ps;
1061 	  int tempwidth, bytes;
1062 	  size_t ret;
1063 
1064 	  /* This fixes only double-column characters, but if the wrapped
1065 	     character comsumes more than three columns, spaces will be
1066 	     inserted in the string buffer. */
1067 	  if (_rl_wrapped_line[current_line] > 0)
1068 	    _rl_clear_to_eol (_rl_wrapped_line[current_line]);
1069 
1070 	  memset (&ps, 0, sizeof (mbstate_t));
1071 	  ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
1072 	  if (ret == (size_t)-1 || ret == (size_t)-2)
1073 	    {
1074 	      tempwidth = 1;
1075 	      ret = 1;
1076 	    }
1077 	  else if (ret == 0)
1078 	    tempwidth = 0;
1079 	  else
1080 	    tempwidth = wcwidth (wc);
1081 
1082 	  if (tempwidth > 0)
1083 	    {
1084 	      int count;
1085 	      bytes = ret;
1086 	      for (count = 0; count < bytes; count++)
1087 		putc (new[count], rl_outstream);
1088 	      _rl_last_c_pos = tempwidth;
1089 	      _rl_last_v_pos++;
1090 	      memset (&ps, 0, sizeof (mbstate_t));
1091 	      ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
1092 	      if (ret != 0 && bytes != 0)
1093 		{
1094 		  if (ret == (size_t)-1 || ret == (size_t)-2)
1095 		    memmove (old+bytes, old+1, strlen (old+1));
1096 		  else
1097 		    memmove (old+bytes, old+ret, strlen (old+ret));
1098 		  memcpy (old, new, bytes);
1099 		}
1100 	    }
1101 	  else
1102 	    {
1103 	      putc (' ', rl_outstream);
1104 	      _rl_last_c_pos = 1;
1105 	      _rl_last_v_pos++;
1106 	      if (old[0] && new[0])
1107 		old[0] = new[0];
1108 	    }
1109 	}
1110       else
1111 #endif
1112 	{
1113 	  if (new[0])
1114 	    putc (new[0], rl_outstream);
1115 	  else
1116 	    putc (' ', rl_outstream);
1117 	  _rl_last_c_pos = 1;		/* XXX */
1118 	  _rl_last_v_pos++;
1119 	  if (old[0] && new[0])
1120 	    old[0] = new[0];
1121 	}
1122     }
1123 
1124 
1125   /* Find first difference. */
1126 #if defined (HANDLE_MULTIBYTE)
1127   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1128     {
1129       memset (&ps_new, 0, sizeof(mbstate_t));
1130       memset (&ps_old, 0, sizeof(mbstate_t));
1131 
1132       new_offset = old_offset = 0;
1133       for (ofd = old, nfd = new;
1134 	   (ofd - old < omax) && *ofd &&
1135 	     _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
1136 	{
1137 	  old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1138 	  new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1139 	  ofd = old + old_offset;
1140 	  nfd = new + new_offset;
1141 	}
1142     }
1143   else
1144 #endif
1145   for (ofd = old, nfd = new;
1146        (ofd - old < omax) && *ofd && (*ofd == *nfd);
1147        ofd++, nfd++)
1148     ;
1149 
1150   /* Move to the end of the screen line.  ND and OD are used to keep track
1151      of the distance between ne and new and oe and old, respectively, to
1152      move a subtraction out of each loop. */
1153   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1154   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1155 
1156   /* If no difference, continue to next line. */
1157   if (ofd == oe && nfd == ne)
1158     return;
1159 
1160   wsatend = 1;			/* flag for trailing whitespace */
1161 
1162 #if defined (HANDLE_MULTIBYTE)
1163   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1164     {
1165       ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1166       nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1167       while ((ols > ofd) && (nls > nfd))
1168 	{
1169 	  memset (&ps_old, 0, sizeof (mbstate_t));
1170 	  memset (&ps_new, 0, sizeof (mbstate_t));
1171 
1172 	  _rl_adjust_point (old, ols - old, &ps_old);
1173 	  _rl_adjust_point (new, nls - new, &ps_new);
1174 
1175 	  if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
1176 	    break;
1177 
1178 	  if (*ols == ' ')
1179 	    wsatend = 0;
1180 
1181 	  ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1182 	  nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1183 	}
1184     }
1185   else
1186     {
1187 #endif /* HANDLE_MULTIBYTE */
1188   ols = oe - 1;			/* find last same */
1189   nls = ne - 1;
1190   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
1191     {
1192       if (*ols != ' ')
1193 	wsatend = 0;
1194       ols--;
1195       nls--;
1196     }
1197 #if defined (HANDLE_MULTIBYTE)
1198     }
1199 #endif
1200 
1201   if (wsatend)
1202     {
1203       ols = oe;
1204       nls = ne;
1205     }
1206 #if defined (HANDLE_MULTIBYTE)
1207   /* This may not work for stateful encoding, but who cares?  To handle
1208      stateful encoding properly, we have to scan each string from the
1209      beginning and compare. */
1210   else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
1211 #else
1212   else if (*ols != *nls)
1213 #endif
1214     {
1215       if (*ols)			/* don't step past the NUL */
1216 	{
1217 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1218 	    ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
1219 	  else
1220 	    ols++;
1221 	}
1222       if (*nls)
1223 	{
1224 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1225 	    nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
1226 	  else
1227 	    nls++;
1228 	}
1229     }
1230 
1231   /* count of invisible characters in the current invisible line. */
1232   current_invis_chars = W_OFFSET (current_line, wrap_offset);
1233   if (_rl_last_v_pos != current_line)
1234     {
1235       _rl_move_vert (current_line);
1236       if (current_line == 0 && visible_wrap_offset)
1237 	_rl_last_c_pos += visible_wrap_offset;
1238     }
1239 
1240   /* If this is the first line and there are invisible characters in the
1241      prompt string, and the prompt string has not changed, and the current
1242      cursor position is before the last invisible character in the prompt,
1243      and the index of the character to move to is past the end of the prompt
1244      string, then redraw the entire prompt string.  We can only do this
1245      reliably if the terminal supports a `cr' capability.
1246 
1247      This is not an efficiency hack -- there is a problem with redrawing
1248      portions of the prompt string if they contain terminal escape
1249      sequences (like drawing the `unbold' sequence without a corresponding
1250      `bold') that manifests itself on certain terminals. */
1251 
1252   lendiff = local_prompt ? strlen (local_prompt) : 0;
1253   od = ofd - old;	/* index of first difference in visible line */
1254   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1255       _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1256       od >= lendiff && _rl_last_c_pos <= prompt_last_invisible)
1257     {
1258 #if defined (__MSDOS__)
1259       putc ('\r', rl_outstream);
1260 #else
1261       tputs (_rl_term_cr, 1, _rl_output_character_function);
1262 #endif
1263       _rl_output_some_chars (local_prompt, lendiff);
1264       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1265 	_rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff);
1266       else
1267 	_rl_last_c_pos = lendiff;
1268     }
1269 
1270   _rl_move_cursor_relative (od, old);
1271 
1272   /* if (len (new) > len (old))
1273      lendiff == difference in buffer
1274      col_lendiff == difference on screen
1275      When not using multibyte characters, these are equal */
1276   lendiff = (nls - nfd) - (ols - ofd);
1277   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1278     col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
1279   else
1280     col_lendiff = lendiff;
1281 
1282   /* If we are changing the number of invisible characters in a line, and
1283      the spot of first difference is before the end of the invisible chars,
1284      lendiff needs to be adjusted. */
1285   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1286       current_invis_chars != visible_wrap_offset)
1287     {
1288       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1289 	{
1290 	  lendiff += visible_wrap_offset - current_invis_chars;
1291 	  col_lendiff += visible_wrap_offset - current_invis_chars;
1292 	}
1293       else
1294 	{
1295 	  lendiff += visible_wrap_offset - current_invis_chars;
1296 	  col_lendiff = lendiff;
1297 	}
1298     }
1299 
1300   /* Insert (diff (len (old), len (new)) ch. */
1301   temp = ne - nfd;
1302   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1303     col_temp = _rl_col_width (new, nfd - new, ne - new);
1304   else
1305     col_temp = temp;
1306 
1307   if (col_lendiff > 0)	/* XXX - was lendiff */
1308     {
1309       /* Non-zero if we're increasing the number of lines. */
1310       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1311       /* Sometimes it is cheaper to print the characters rather than
1312 	 use the terminal's capabilities.  If we're growing the number
1313 	 of lines, make sure we actually cause the new line to wrap
1314 	 around on auto-wrapping terminals. */
1315       if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
1316 	{
1317 	  /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
1318 	     _rl_horizontal_scroll_mode == 1, inserting the characters with
1319 	     _rl_term_IC or _rl_term_ic will screw up the screen because of the
1320 	     invisible characters.  We need to just draw them. */
1321 	  if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
1322 			lendiff <= prompt_visible_length || !current_invis_chars))
1323 	    {
1324 	      insert_some_chars (nfd, lendiff, col_lendiff);
1325 	      _rl_last_c_pos += col_lendiff;
1326 	    }
1327 	  else if (*ols == 0)
1328 	    {
1329 	      /* At the end of a line the characters do not have to
1330 		 be "inserted".  They can just be placed on the screen. */
1331 	      /* However, this screws up the rest of this block, which
1332 		 assumes you've done the insert because you can. */
1333 	      _rl_output_some_chars (nfd, lendiff);
1334 	      _rl_last_c_pos += col_lendiff;
1335 	    }
1336 	  else
1337 	    {
1338 	      /* We have horizontal scrolling and we are not inserting at
1339 		 the end.  We have invisible characters in this line.  This
1340 		 is a dumb update. */
1341 	      _rl_output_some_chars (nfd, temp);
1342 	      _rl_last_c_pos += col_temp;
1343 	      return;
1344 	    }
1345 	  /* Copy (new) chars to screen from first diff to last match. */
1346 	  temp = nls - nfd;
1347 	  if ((temp - lendiff) > 0)
1348 	    {
1349 	      _rl_output_some_chars (nfd + lendiff, temp - lendiff);
1350 #if 0
1351 	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
1352 #else
1353 	      _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
1354 #endif
1355 	    }
1356 	}
1357       else
1358 	{
1359 	  /* cannot insert chars, write to EOL */
1360 	  _rl_output_some_chars (nfd, temp);
1361 	  _rl_last_c_pos += col_temp;
1362 	}
1363     }
1364   else				/* Delete characters from line. */
1365     {
1366       /* If possible and inexpensive to use terminal deletion, then do so. */
1367       if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
1368 	{
1369 	  /* If all we're doing is erasing the invisible characters in the
1370 	     prompt string, don't bother.  It screws up the assumptions
1371 	     about what's on the screen. */
1372 	  if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
1373 	      -lendiff == visible_wrap_offset)
1374 	    col_lendiff = 0;
1375 
1376 	  if (col_lendiff)
1377 	    delete_chars (-col_lendiff); /* delete (diff) characters */
1378 
1379 	  /* Copy (new) chars to screen from first diff to last match */
1380 	  temp = nls - nfd;
1381 	  if (temp > 0)
1382 	    {
1383 	      _rl_output_some_chars (nfd, temp);
1384 	      _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
1385 	    }
1386 	}
1387       /* Otherwise, print over the existing material. */
1388       else
1389 	{
1390 	  if (temp > 0)
1391 	    {
1392 	      _rl_output_some_chars (nfd, temp);
1393 	      _rl_last_c_pos += col_temp;
1394 	    }
1395 	  lendiff = (oe - old) - (ne - new);
1396 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1397 	    col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
1398 	  else
1399 	    col_lendiff = lendiff;
1400 
1401 	  if (col_lendiff)
1402 	    {
1403 	      if (_rl_term_autowrap && current_line < inv_botlin)
1404 		space_to_eol (col_lendiff);
1405 	      else
1406 		_rl_clear_to_eol (col_lendiff);
1407 	    }
1408 	}
1409     }
1410 }
1411 
1412 /* Tell the update routines that we have moved onto a new (empty) line. */
1413 int
rl_on_new_line()1414 rl_on_new_line ()
1415 {
1416   if (visible_line)
1417     visible_line[0] = '\0';
1418 
1419   _rl_last_c_pos = _rl_last_v_pos = 0;
1420   _rl_vis_botlin = last_lmargin = 0;
1421   if (vis_lbreaks)
1422     vis_lbreaks[0] = vis_lbreaks[1] = 0;
1423   visible_wrap_offset = 0;
1424   return 0;
1425 }
1426 
1427 /* Tell the update routines that we have moved onto a new line with the
1428    prompt already displayed.  Code originally from the version of readline
1429    distributed with CLISP. */
1430 int
rl_on_new_line_with_prompt()1431 rl_on_new_line_with_prompt ()
1432 {
1433   int prompt_size, i, l, real_screenwidth, newlines;
1434   char *prompt_last_line;
1435 
1436   /* Initialize visible_line and invisible_line to ensure that they can hold
1437      the already-displayed prompt. */
1438   prompt_size = strlen (rl_prompt) + 1;
1439   init_line_structures (prompt_size);
1440 
1441   /* Make sure the line structures hold the already-displayed prompt for
1442      redisplay. */
1443   strlcpy (visible_line, rl_prompt, line_size);
1444   strlcpy (invisible_line, rl_prompt, line_size);
1445 
1446   /* If the prompt contains newlines, take the last tail. */
1447   prompt_last_line = strrchr (rl_prompt, '\n');
1448   if (!prompt_last_line)
1449     prompt_last_line = rl_prompt;
1450 
1451   l = strlen (prompt_last_line);
1452   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1453     _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l);
1454   else
1455     _rl_last_c_pos = l;
1456 
1457   /* Dissect prompt_last_line into screen lines. Note that here we have
1458      to use the real screenwidth. Readline's notion of screenwidth might be
1459      one less, see terminal.c. */
1460   real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
1461   _rl_last_v_pos = l / real_screenwidth;
1462   /* If the prompt length is a multiple of real_screenwidth, we don't know
1463      whether the cursor is at the end of the last line, or already at the
1464      beginning of the next line. Output a newline just to be safe. */
1465   if (l > 0 && (l % real_screenwidth) == 0)
1466     _rl_output_some_chars ("\n", 1);
1467   last_lmargin = 0;
1468 
1469   newlines = 0; i = 0;
1470   while (i <= l)
1471     {
1472       _rl_vis_botlin = newlines;
1473       vis_lbreaks[newlines++] = i;
1474       i += real_screenwidth;
1475     }
1476   vis_lbreaks[newlines] = l;
1477   visible_wrap_offset = 0;
1478 
1479   return 0;
1480 }
1481 
1482 /* Actually update the display, period. */
1483 int
rl_forced_update_display()1484 rl_forced_update_display ()
1485 {
1486   if (visible_line)
1487     {
1488       register char *temp = visible_line;
1489 
1490       while (*temp)
1491 	*temp++ = '\0';
1492     }
1493   rl_on_new_line ();
1494   forced_display++;
1495   (*rl_redisplay_function) ();
1496   return 0;
1497 }
1498 
1499 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1500    DATA is the contents of the screen line of interest; i.e., where
1501    the movement is being done. */
1502 void
_rl_move_cursor_relative(new,data)1503 _rl_move_cursor_relative (new, data)
1504      int new;
1505      const char *data;
1506 {
1507   register int i;
1508 
1509   /* If we don't have to do anything, then return. */
1510 #if defined (HANDLE_MULTIBYTE)
1511   /* If we have multibyte characters, NEW is indexed by the buffer point in
1512      a multibyte string, but _rl_last_c_pos is the display position.  In
1513      this case, NEW's display position is not obvious and must be
1514      calculated. */
1515   if (MB_CUR_MAX == 1 || rl_byte_oriented)
1516     {
1517       if (_rl_last_c_pos == new)
1518 	return;
1519     }
1520   else if (_rl_last_c_pos == _rl_col_width (data, 0, new))
1521     return;
1522 #else
1523   if (_rl_last_c_pos == new) return;
1524 #endif
1525 
1526   /* It may be faster to output a CR, and then move forwards instead
1527      of moving backwards. */
1528   /* i == current physical cursor position. */
1529   i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1530   if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
1531       (_rl_term_autowrap && i == _rl_screenwidth))
1532     {
1533 #if defined (__MSDOS__)
1534       putc ('\r', rl_outstream);
1535 #else
1536       tputs (_rl_term_cr, 1, _rl_output_character_function);
1537 #endif /* !__MSDOS__ */
1538       _rl_last_c_pos = 0;
1539     }
1540 
1541   if (_rl_last_c_pos < new)
1542     {
1543       /* Move the cursor forward.  We do it by printing the command
1544 	 to move the cursor forward if there is one, else print that
1545 	 portion of the output buffer again.  Which is cheaper? */
1546 
1547       /* The above comment is left here for posterity.  It is faster
1548 	 to print one character (non-control) than to print a control
1549 	 sequence telling the terminal to move forward one character.
1550 	 That kind of control is for people who don't know what the
1551 	 data is underneath the cursor. */
1552 #if defined (HACK_TERMCAP_MOTION)
1553       if (_rl_term_forward_char)
1554 	{
1555 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1556 	    {
1557 	      int width;
1558 	      width = _rl_col_width (data, _rl_last_c_pos, new);
1559 	      for (i = 0; i < width; i++)
1560 		tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1561 	    }
1562 	  else
1563 	    {
1564 	      for (i = _rl_last_c_pos; i < new; i++)
1565 		tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1566 	    }
1567 	}
1568       else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1569 	{
1570 	  tputs (_rl_term_cr, 1, _rl_output_character_function);
1571 	  for (i = 0; i < new; i++)
1572 	    putc (data[i], rl_outstream);
1573 	}
1574       else
1575 	for (i = _rl_last_c_pos; i < new; i++)
1576 	  putc (data[i], rl_outstream);
1577 
1578 #else /* !HACK_TERMCAP_MOTION */
1579 
1580       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1581 	{
1582 	  tputs (_rl_term_cr, 1, _rl_output_character_function);
1583 	  for (i = 0; i < new; i++)
1584 	    putc (data[i], rl_outstream);
1585 	}
1586       else
1587 	for (i = _rl_last_c_pos; i < new; i++)
1588 	  putc (data[i], rl_outstream);
1589 
1590 #endif /* !HACK_TERMCAP_MOTION */
1591 
1592     }
1593 #if defined (HANDLE_MULTIBYTE)
1594   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
1595      The byte length of the string is probably bigger than the column width
1596      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
1597      display point is less than _rl_last_c_pos. */
1598   else if (_rl_last_c_pos >= new)
1599 #else
1600   else if (_rl_last_c_pos > new)
1601 #endif
1602     {
1603       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1604 	_rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new));
1605       else
1606 	_rl_backspace (_rl_last_c_pos - new);
1607     }
1608 
1609   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1610     _rl_last_c_pos =  _rl_col_width (data, 0, new);
1611   else
1612     _rl_last_c_pos = new;
1613 }
1614 
1615 /* PWP: move the cursor up or down. */
1616 void
_rl_move_vert(to)1617 _rl_move_vert (to)
1618      int to;
1619 {
1620   register int delta, i;
1621 
1622   if (_rl_last_v_pos == to || to > _rl_screenheight)
1623     return;
1624 
1625   if ((delta = to - _rl_last_v_pos) > 0)
1626     {
1627       for (i = 0; i < delta; i++)
1628 	putc ('\n', rl_outstream);
1629 #if defined (__MSDOS__)
1630       putc ('\r', rl_outstream);
1631 #else
1632       tputs (_rl_term_cr, 1, _rl_output_character_function);
1633 #endif
1634       _rl_last_c_pos = 0;
1635     }
1636   else
1637     {			/* delta < 0 */
1638       if (_rl_term_up && *_rl_term_up)
1639 	for (i = 0; i < -delta; i++)
1640 	  tputs (_rl_term_up, 1, _rl_output_character_function);
1641     }
1642 
1643   _rl_last_v_pos = to;		/* Now TO is here */
1644 }
1645 
1646 /* Physically print C on rl_outstream.  This is for functions which know
1647    how to optimize the display.  Return the number of characters output. */
1648 int
rl_show_char(c)1649 rl_show_char (c)
1650      int c;
1651 {
1652   int n = 1;
1653   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
1654     {
1655       fprintf (rl_outstream, "M-");
1656       n += 2;
1657       c = UNMETA (c);
1658     }
1659 
1660 #if defined (DISPLAY_TABS)
1661   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
1662 #else
1663   if (CTRL_CHAR (c) || c == RUBOUT)
1664 #endif /* !DISPLAY_TABS */
1665     {
1666       fprintf (rl_outstream, "C-");
1667       n += 2;
1668       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1669     }
1670 
1671   putc (c, rl_outstream);
1672   fflush (rl_outstream);
1673   return n;
1674 }
1675 
1676 int
rl_character_len(c,pos)1677 rl_character_len (c, pos)
1678      register int c, pos;
1679 {
1680   unsigned char uc;
1681 
1682   uc = (unsigned char)c;
1683 
1684   if (META_CHAR (uc))
1685     return ((_rl_output_meta_chars == 0) ? 4 : 1);
1686 
1687   if (uc == '\t')
1688     {
1689 #if defined (DISPLAY_TABS)
1690       return (((pos | 7) + 1) - pos);
1691 #else
1692       return (2);
1693 #endif /* !DISPLAY_TABS */
1694     }
1695 
1696   if (CTRL_CHAR (c) || c == RUBOUT)
1697     return (2);
1698 
1699   return ((ISPRINT (uc)) ? 1 : 2);
1700 }
1701 
1702 /* How to print things in the "echo-area".  The prompt is treated as a
1703    mini-modeline. */
1704 
1705 #if defined (USE_VARARGS)
1706 int
1707 #if defined (PREFER_STDARG)
rl_message(const char * format,...)1708 rl_message (const char *format, ...)
1709 #else
1710 rl_message (va_alist)
1711      va_dcl
1712 #endif
1713 {
1714   va_list args;
1715 #if defined (PREFER_VARARGS)
1716   char *format;
1717 #endif
1718 
1719 #if defined (PREFER_STDARG)
1720   va_start (args, format);
1721 #else
1722   va_start (args);
1723   format = va_arg (args, char *);
1724 #endif
1725 
1726 #if defined (HAVE_VSNPRINTF)
1727   vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
1728 #else
1729   vsprintf (msg_buf, format, args);
1730   msg_buf[sizeof(msg_buf) - 1] = '\0';	/* overflow? */
1731 #endif
1732   va_end (args);
1733 
1734   rl_display_prompt = msg_buf;
1735   (*rl_redisplay_function) ();
1736   return 0;
1737 }
1738 #else /* !USE_VARARGS */
1739 int
rl_message(format,arg1,arg2)1740 rl_message (format, arg1, arg2)
1741      char *format;
1742 {
1743   snprintf (msg_buf, sizeof(msg_buf), format, arg1, arg2);
1744   rl_display_prompt = msg_buf;
1745   (*rl_redisplay_function) ();
1746   return 0;
1747 }
1748 #endif /* !USE_VARARGS */
1749 
1750 /* How to clear things from the "echo-area". */
1751 int
rl_clear_message()1752 rl_clear_message ()
1753 {
1754   rl_display_prompt = rl_prompt;
1755   (*rl_redisplay_function) ();
1756   return 0;
1757 }
1758 
1759 int
rl_reset_line_state()1760 rl_reset_line_state ()
1761 {
1762   rl_on_new_line ();
1763 
1764   rl_display_prompt = rl_prompt ? rl_prompt : "";
1765   forced_display = 1;
1766   return 0;
1767 }
1768 
1769 static char *saved_local_prompt;
1770 static char *saved_local_prefix;
1771 static int saved_last_invisible;
1772 static int saved_visible_length;
1773 
1774 void
rl_save_prompt()1775 rl_save_prompt ()
1776 {
1777   saved_local_prompt = local_prompt;
1778   saved_local_prefix = local_prompt_prefix;
1779   saved_last_invisible = prompt_last_invisible;
1780   saved_visible_length = prompt_visible_length;
1781 
1782   local_prompt = local_prompt_prefix = (char *)0;
1783   prompt_last_invisible = prompt_visible_length = 0;
1784 }
1785 
1786 void
rl_restore_prompt()1787 rl_restore_prompt ()
1788 {
1789   FREE (local_prompt);
1790   FREE (local_prompt_prefix);
1791 
1792   local_prompt = saved_local_prompt;
1793   local_prompt_prefix = saved_local_prefix;
1794   prompt_last_invisible = saved_last_invisible;
1795   prompt_visible_length = saved_visible_length;
1796 }
1797 
1798 char *
_rl_make_prompt_for_search(pchar)1799 _rl_make_prompt_for_search (pchar)
1800      int pchar;
1801 {
1802   int len;
1803   char *pmt;
1804 
1805   rl_save_prompt ();
1806 
1807   if (saved_local_prompt == 0)
1808     {
1809       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
1810       pmt = (char *)xmalloc (len + 2);
1811       if (len)
1812 	strlcpy (pmt, rl_prompt, len + 2);
1813       pmt[len] = pchar;
1814       pmt[len+1] = '\0';
1815     }
1816   else
1817     {
1818       len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
1819       pmt = (char *)xmalloc (len + 2);
1820       if (len)
1821 	strlcpy (pmt, saved_local_prompt, len + 2);
1822       pmt[len] = pchar;
1823       pmt[len+1] = '\0';
1824       local_prompt = savestring (pmt);
1825       prompt_last_invisible = saved_last_invisible;
1826       prompt_visible_length = saved_visible_length + 1;
1827     }
1828   return pmt;
1829 }
1830 
1831 /* Quick redisplay hack when erasing characters at the end of the line. */
1832 void
_rl_erase_at_end_of_line(l)1833 _rl_erase_at_end_of_line (l)
1834      int l;
1835 {
1836   register int i;
1837 
1838   _rl_backspace (l);
1839   for (i = 0; i < l; i++)
1840     putc (' ', rl_outstream);
1841   _rl_backspace (l);
1842   for (i = 0; i < l; i++)
1843     visible_line[--_rl_last_c_pos] = '\0';
1844   rl_display_fixed++;
1845 }
1846 
1847 /* Clear to the end of the line.  COUNT is the minimum
1848    number of character spaces to clear, */
1849 void
_rl_clear_to_eol(count)1850 _rl_clear_to_eol (count)
1851      int count;
1852 {
1853   if (_rl_term_clreol)
1854     tputs (_rl_term_clreol, 1, _rl_output_character_function);
1855   else if (count)
1856     space_to_eol (count);
1857 }
1858 
1859 /* Clear to the end of the line using spaces.  COUNT is the minimum
1860    number of character spaces to clear, */
1861 static void
space_to_eol(count)1862 space_to_eol (count)
1863      int count;
1864 {
1865   register int i;
1866 
1867   for (i = 0; i < count; i++)
1868    putc (' ', rl_outstream);
1869 
1870   _rl_last_c_pos += count;
1871 }
1872 
1873 void
_rl_clear_screen()1874 _rl_clear_screen ()
1875 {
1876   if (_rl_term_clrpag)
1877     tputs (_rl_term_clrpag, 1, _rl_output_character_function);
1878   else
1879     rl_crlf ();
1880 }
1881 
1882 /* Insert COUNT characters from STRING to the output stream at column COL. */
1883 static void
insert_some_chars(string,count,col)1884 insert_some_chars (string, count, col)
1885      char *string;
1886      int count, col;
1887 {
1888   /* DEBUGGING */
1889   if (MB_CUR_MAX == 1 || rl_byte_oriented)
1890     if (count != col)
1891       fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
1892 
1893   /* If IC is defined, then we do not have to "enter" insert mode. */
1894   if (_rl_term_IC)
1895     {
1896       char *buffer;
1897 
1898       buffer = tgoto (_rl_term_IC, 0, col);
1899       tputs (buffer, 1, _rl_output_character_function);
1900       _rl_output_some_chars (string, count);
1901     }
1902   else
1903     {
1904       register int i;
1905 
1906       /* If we have to turn on insert-mode, then do so. */
1907       if (_rl_term_im && *_rl_term_im)
1908 	tputs (_rl_term_im, 1, _rl_output_character_function);
1909 
1910       /* If there is a special command for inserting characters, then
1911 	 use that first to open up the space. */
1912       if (_rl_term_ic && *_rl_term_ic)
1913 	{
1914 	  for (i = col; i--; )
1915 	    tputs (_rl_term_ic, 1, _rl_output_character_function);
1916 	}
1917 
1918       /* Print the text. */
1919       _rl_output_some_chars (string, count);
1920 
1921       /* If there is a string to turn off insert mode, we had best use
1922 	 it now. */
1923       if (_rl_term_ei && *_rl_term_ei)
1924 	tputs (_rl_term_ei, 1, _rl_output_character_function);
1925     }
1926 }
1927 
1928 /* Delete COUNT characters from the display line. */
1929 static void
delete_chars(count)1930 delete_chars (count)
1931      int count;
1932 {
1933   if (count > _rl_screenwidth)	/* XXX */
1934     return;
1935 
1936   if (_rl_term_DC && *_rl_term_DC)
1937     {
1938       char *buffer;
1939       buffer = tgoto (_rl_term_DC, count, count);
1940       tputs (buffer, count, _rl_output_character_function);
1941     }
1942   else
1943     {
1944       if (_rl_term_dc && *_rl_term_dc)
1945 	while (count--)
1946 	  tputs (_rl_term_dc, 1, _rl_output_character_function);
1947     }
1948 }
1949 
1950 void
_rl_update_final()1951 _rl_update_final ()
1952 {
1953   int full_lines;
1954 
1955   full_lines = 0;
1956   /* If the cursor is the only thing on an otherwise-blank last line,
1957      compensate so we don't print an extra CRLF. */
1958   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
1959 	visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
1960     {
1961       _rl_vis_botlin--;
1962       full_lines = 1;
1963     }
1964   _rl_move_vert (_rl_vis_botlin);
1965   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
1966   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
1967     {
1968       char *last_line;
1969 
1970       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
1971       _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
1972       _rl_clear_to_eol (0);
1973       putc (last_line[_rl_screenwidth - 1], rl_outstream);
1974     }
1975   _rl_vis_botlin = 0;
1976   rl_crlf ();
1977   fflush (rl_outstream);
1978   rl_display_fixed++;
1979 }
1980 
1981 /* Move to the start of the current line. */
1982 static void
cr()1983 cr ()
1984 {
1985   if (_rl_term_cr)
1986     {
1987 #if defined (__MSDOS__)
1988       putc ('\r', rl_outstream);
1989 #else
1990       tputs (_rl_term_cr, 1, _rl_output_character_function);
1991 #endif
1992       _rl_last_c_pos = 0;
1993     }
1994 }
1995 
1996 /* Redraw the last line of a multi-line prompt that may possibly contain
1997    terminal escape sequences.  Called with the cursor at column 0 of the
1998    line to draw the prompt on. */
1999 static void
redraw_prompt(t)2000 redraw_prompt (t)
2001      char *t;
2002 {
2003   char *oldp, *oldl, *oldlprefix;
2004   int oldlen, oldlast, oldplen, oldninvis;
2005 
2006   /* Geez, I should make this a struct. */
2007   oldp = rl_display_prompt;
2008   oldl = local_prompt;
2009   oldlprefix = local_prompt_prefix;
2010   oldlen = prompt_visible_length;
2011   oldplen = prompt_prefix_length;
2012   oldlast = prompt_last_invisible;
2013   oldninvis = prompt_invis_chars_first_line;
2014 
2015   rl_display_prompt = t;
2016   local_prompt = expand_prompt (t, &prompt_visible_length,
2017 				   &prompt_last_invisible,
2018 				   &prompt_invis_chars_first_line);
2019   local_prompt_prefix = (char *)NULL;
2020   rl_forced_update_display ();
2021 
2022   rl_display_prompt = oldp;
2023   local_prompt = oldl;
2024   local_prompt_prefix = oldlprefix;
2025   prompt_visible_length = oldlen;
2026   prompt_prefix_length = oldplen;
2027   prompt_last_invisible = oldlast;
2028   prompt_invis_chars_first_line = oldninvis;
2029 }
2030 
2031 /* Redisplay the current line after a SIGWINCH is received. */
2032 void
_rl_redisplay_after_sigwinch()2033 _rl_redisplay_after_sigwinch ()
2034 {
2035   char *t;
2036 
2037   /* Clear the current line and put the cursor at column 0.  Make sure
2038      the right thing happens if we have wrapped to a new screen line. */
2039   if (_rl_term_cr)
2040     {
2041 #if defined (__MSDOS__)
2042       putc ('\r', rl_outstream);
2043 #else
2044       tputs (_rl_term_cr, 1, _rl_output_character_function);
2045 #endif
2046       _rl_last_c_pos = 0;
2047 #if defined (__MSDOS__)
2048       space_to_eol (_rl_screenwidth);
2049       putc ('\r', rl_outstream);
2050 #else
2051       if (_rl_term_clreol)
2052 	tputs (_rl_term_clreol, 1, _rl_output_character_function);
2053       else
2054 	{
2055 	  space_to_eol (_rl_screenwidth);
2056 	  tputs (_rl_term_cr, 1, _rl_output_character_function);
2057 	}
2058 #endif
2059       if (_rl_last_v_pos > 0)
2060 	_rl_move_vert (0);
2061     }
2062   else
2063     rl_crlf ();
2064 
2065   /* Redraw only the last line of a multi-line prompt. */
2066   t = strrchr (rl_display_prompt, '\n');
2067   if (t)
2068     redraw_prompt (++t);
2069   else
2070     rl_forced_update_display ();
2071 }
2072 
2073 void
_rl_clean_up_for_exit()2074 _rl_clean_up_for_exit ()
2075 {
2076   if (readline_echoing_p)
2077     {
2078       _rl_move_vert (_rl_vis_botlin);
2079       _rl_vis_botlin = 0;
2080       fflush (rl_outstream);
2081       rl_restart_output (1, 0);
2082     }
2083 }
2084 
2085 void
_rl_erase_entire_line()2086 _rl_erase_entire_line ()
2087 {
2088   cr ();
2089   _rl_clear_to_eol (0);
2090   cr ();
2091   fflush (rl_outstream);
2092 }
2093 
2094 /* return the `current display line' of the cursor -- the number of lines to
2095    move up to get to the first screen line of the current readline line. */
2096 int
_rl_current_display_line()2097 _rl_current_display_line ()
2098 {
2099   int ret, nleft;
2100 
2101   /* Find out whether or not there might be invisible characters in the
2102      editing buffer. */
2103   if (rl_display_prompt == rl_prompt)
2104     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
2105   else
2106     nleft = _rl_last_c_pos - _rl_screenwidth;
2107 
2108   if (nleft > 0)
2109     ret = 1 + nleft / _rl_screenwidth;
2110   else
2111     ret = 0;
2112 
2113   return ret;
2114 }
2115 
2116 #if defined (HANDLE_MULTIBYTE)
2117 /* Calculate the number of screen columns occupied by STR from START to END.
2118    In the case of multibyte characters with stateful encoding, we have to
2119    scan from the beginning of the string to take the state into account. */
2120 static int
_rl_col_width(str,start,end)2121 _rl_col_width (str, start, end)
2122      const char *str;
2123      int start, end;
2124 {
2125   wchar_t wc;
2126   mbstate_t ps = {0};
2127   int tmp, point, width, max;
2128 
2129   if (end <= start)
2130     return 0;
2131 
2132   point = 0;
2133   max = end;
2134 
2135   while (point < start)
2136     {
2137       tmp = mbrlen (str + point, max, &ps);
2138       if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
2139 	{
2140 	  /* In this case, the bytes are invalid or too short to compose a
2141 	     multibyte character, so we assume that the first byte represents
2142 	     a single character. */
2143 	  point++;
2144 	  max--;
2145 
2146 	  /* Clear the state of the byte sequence, because in this case the
2147 	     effect of mbstate is undefined. */
2148 	  memset (&ps, 0, sizeof (mbstate_t));
2149 	}
2150       else if (tmp == 0)
2151         break;		/* Found '\0' */
2152       else
2153 	{
2154 	  point += tmp;
2155 	  max -= tmp;
2156 	}
2157     }
2158 
2159   /* If START is not a byte that starts a character, then POINT will be
2160      greater than START.  In this case, assume that (POINT - START) gives
2161      a byte count that is the number of columns of difference. */
2162   width = point - start;
2163 
2164   while (point < end)
2165     {
2166       tmp = mbrtowc (&wc, str + point, max, &ps);
2167       if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
2168 	{
2169 	  /* In this case, the bytes are invalid or too short to compose a
2170 	     multibyte character, so we assume that the first byte represents
2171 	     a single character. */
2172 	  point++;
2173 	  max--;
2174 
2175 	  /* and assume that the byte occupies a single column. */
2176 	  width++;
2177 
2178 	  /* Clear the state of the byte sequence, because in this case the
2179 	     effect of mbstate is undefined. */
2180 	  memset (&ps, 0, sizeof (mbstate_t));
2181 	}
2182       else if (tmp == 0)
2183         break;			/* Found '\0' */
2184       else
2185 	{
2186 	  point += tmp;
2187 	  max -= tmp;
2188 	  tmp = wcwidth(wc);
2189 	  width += (tmp >= 0) ? tmp : 1;
2190 	}
2191     }
2192 
2193   width += point - end;
2194 
2195   return width;
2196 }
2197 #endif /* HANDLE_MULTIBYTE */
2198