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