Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / lib / readline / display.c
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((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 *
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 *
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
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
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
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               sprintf (line + 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
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-lendiff) - col_lendiff;
1352 #else
1353               _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_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
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
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   strcpy (visible_line, rl_prompt);
1444   strcpy (invisible_line, rl_prompt);
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
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
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. */
1514   if ((MB_CUR_MAX == 1 || rl_byte_oriented ) && _rl_last_c_pos == new) return;
1515 #else
1516   if (_rl_last_c_pos == new) return;
1517 #endif
1518
1519   /* It may be faster to output a CR, and then move forwards instead
1520      of moving backwards. */
1521   /* i == current physical cursor position. */
1522   i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1523   if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
1524       (_rl_term_autowrap && i == _rl_screenwidth))
1525     {
1526 #if defined (__MSDOS__)
1527       putc ('\r', rl_outstream);
1528 #else
1529       tputs (_rl_term_cr, 1, _rl_output_character_function);
1530 #endif /* !__MSDOS__ */
1531       _rl_last_c_pos = 0;
1532     }
1533
1534   if (_rl_last_c_pos < new)
1535     {
1536       /* Move the cursor forward.  We do it by printing the command
1537          to move the cursor forward if there is one, else print that
1538          portion of the output buffer again.  Which is cheaper? */
1539
1540       /* The above comment is left here for posterity.  It is faster
1541          to print one character (non-control) than to print a control
1542          sequence telling the terminal to move forward one character.
1543          That kind of control is for people who don't know what the
1544          data is underneath the cursor. */
1545 #if defined (HACK_TERMCAP_MOTION)
1546       if (_rl_term_forward_char)
1547         {
1548           if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1549             {
1550               int width;
1551               width = _rl_col_width (data, _rl_last_c_pos, new);
1552               for (i = 0; i < width; i++)
1553                 tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1554             }
1555           else
1556             {
1557               for (i = _rl_last_c_pos; i < new; i++)
1558                 tputs (_rl_term_forward_char, 1, _rl_output_character_function);
1559             }
1560         }
1561       else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1562         {
1563           tputs (_rl_term_cr, 1, _rl_output_character_function);
1564           for (i = 0; i < new; i++)
1565             putc (data[i], rl_outstream);
1566         }
1567       else
1568         for (i = _rl_last_c_pos; i < new; i++)
1569           putc (data[i], rl_outstream);
1570
1571 #else /* !HACK_TERMCAP_MOTION */
1572
1573       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1574         {
1575           tputs (_rl_term_cr, 1, _rl_output_character_function);
1576           for (i = 0; i < new; i++)
1577             putc (data[i], rl_outstream);
1578         }
1579       else
1580         for (i = _rl_last_c_pos; i < new; i++)
1581           putc (data[i], rl_outstream);
1582
1583 #endif /* !HACK_TERMCAP_MOTION */
1584
1585     }
1586 #if defined (HANDLE_MULTIBYTE)
1587   /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
1588      The byte length of the string is probably bigger than the column width
1589      of the string, which means that if NEW == _rl_last_c_pos, then NEW's
1590      display point is less than _rl_last_c_pos. */
1591   else if (_rl_last_c_pos >= new)
1592 #else
1593   else if (_rl_last_c_pos > new)
1594 #endif
1595     {
1596       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1597         {
1598           tputs (_rl_term_cr, 1, _rl_output_character_function);
1599           for (i = 0; i < new; i++)
1600             putc (data[i], rl_outstream);
1601         }
1602       else
1603         _rl_backspace (_rl_last_c_pos - new);
1604     }
1605
1606   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1607     _rl_last_c_pos =  _rl_col_width (data, 0, new);
1608   else
1609     _rl_last_c_pos = new;
1610 }
1611
1612 /* PWP: move the cursor up or down. */
1613 void
1614 _rl_move_vert (to)
1615      int to;
1616 {
1617   register int delta, i;
1618
1619   if (_rl_last_v_pos == to || to > _rl_screenheight)
1620     return;
1621
1622   if ((delta = to - _rl_last_v_pos) > 0)
1623     {
1624       for (i = 0; i < delta; i++)
1625         putc ('\n', rl_outstream);
1626 #if defined (__MSDOS__)
1627       putc ('\r', rl_outstream);
1628 #else
1629       tputs (_rl_term_cr, 1, _rl_output_character_function);
1630 #endif
1631       _rl_last_c_pos = 0;
1632     }
1633   else
1634     {                   /* delta < 0 */
1635       if (_rl_term_up && *_rl_term_up)
1636         for (i = 0; i < -delta; i++)
1637           tputs (_rl_term_up, 1, _rl_output_character_function);
1638     }
1639
1640   _rl_last_v_pos = to;          /* Now TO is here */
1641 }
1642
1643 /* Physically print C on rl_outstream.  This is for functions which know
1644    how to optimize the display.  Return the number of characters output. */
1645 int
1646 rl_show_char (c)
1647      int c;
1648 {
1649   int n = 1;
1650   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
1651     {
1652       fprintf (rl_outstream, "M-");
1653       n += 2;
1654       c = UNMETA (c);
1655     }
1656
1657 #if defined (DISPLAY_TABS)
1658   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
1659 #else
1660   if (CTRL_CHAR (c) || c == RUBOUT)
1661 #endif /* !DISPLAY_TABS */
1662     {
1663       fprintf (rl_outstream, "C-");
1664       n += 2;
1665       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1666     }
1667
1668   putc (c, rl_outstream);
1669   fflush (rl_outstream);
1670   return n;
1671 }
1672
1673 int
1674 rl_character_len (c, pos)
1675      register int c, pos;
1676 {
1677   unsigned char uc;
1678
1679   uc = (unsigned char)c;
1680
1681   if (META_CHAR (uc))
1682     return ((_rl_output_meta_chars == 0) ? 4 : 1);
1683
1684   if (uc == '\t')
1685     {
1686 #if defined (DISPLAY_TABS)
1687       return (((pos | 7) + 1) - pos);
1688 #else
1689       return (2);
1690 #endif /* !DISPLAY_TABS */
1691     }
1692
1693   if (CTRL_CHAR (c) || c == RUBOUT)
1694     return (2);
1695
1696   return ((ISPRINT (uc)) ? 1 : 2);
1697 }
1698
1699 /* How to print things in the "echo-area".  The prompt is treated as a
1700    mini-modeline. */
1701
1702 #if defined (USE_VARARGS)
1703 int
1704 #if defined (PREFER_STDARG)
1705 rl_message (const char *format, ...)
1706 #else
1707 rl_message (va_alist)
1708      va_dcl
1709 #endif
1710 {
1711   va_list args;
1712 #if defined (PREFER_VARARGS)
1713   char *format;
1714 #endif
1715
1716 #if defined (PREFER_STDARG)
1717   va_start (args, format);
1718 #else
1719   va_start (args);
1720   format = va_arg (args, char *);
1721 #endif
1722
1723 #if defined (HAVE_VSNPRINTF)
1724   vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
1725 #else
1726   vsprintf (msg_buf, format, args);
1727   msg_buf[sizeof(msg_buf) - 1] = '\0';  /* overflow? */
1728 #endif
1729   va_end (args);
1730
1731   rl_display_prompt = msg_buf;
1732   (*rl_redisplay_function) ();
1733   return 0;
1734 }
1735 #else /* !USE_VARARGS */
1736 int
1737 rl_message (format, arg1, arg2)
1738      char *format;
1739 {
1740   sprintf (msg_buf, format, arg1, arg2);
1741   msg_buf[sizeof(msg_buf) - 1] = '\0';  /* overflow? */
1742   rl_display_prompt = msg_buf;
1743   (*rl_redisplay_function) ();
1744   return 0;
1745 }
1746 #endif /* !USE_VARARGS */
1747
1748 /* How to clear things from the "echo-area". */
1749 int
1750 rl_clear_message ()
1751 {
1752   rl_display_prompt = rl_prompt;
1753   (*rl_redisplay_function) ();
1754   return 0;
1755 }
1756
1757 int
1758 rl_reset_line_state ()
1759 {
1760   rl_on_new_line ();
1761
1762   rl_display_prompt = rl_prompt ? rl_prompt : "";
1763   forced_display = 1;
1764   return 0;
1765 }
1766
1767 static char *saved_local_prompt;
1768 static char *saved_local_prefix;
1769 static int saved_last_invisible;
1770 static int saved_visible_length;
1771
1772 void
1773 rl_save_prompt ()
1774 {
1775   saved_local_prompt = local_prompt;
1776   saved_local_prefix = local_prompt_prefix;
1777   saved_last_invisible = prompt_last_invisible;
1778   saved_visible_length = prompt_visible_length;
1779
1780   local_prompt = local_prompt_prefix = (char *)0;
1781   prompt_last_invisible = prompt_visible_length = 0;
1782 }
1783
1784 void
1785 rl_restore_prompt ()
1786 {
1787   FREE (local_prompt);
1788   FREE (local_prompt_prefix);
1789
1790   local_prompt = saved_local_prompt;
1791   local_prompt_prefix = saved_local_prefix;
1792   prompt_last_invisible = saved_last_invisible;
1793   prompt_visible_length = saved_visible_length;
1794 }
1795
1796 char *
1797 _rl_make_prompt_for_search (pchar)
1798      int pchar;
1799 {
1800   int len;
1801   char *pmt;
1802
1803   rl_save_prompt ();
1804
1805   if (saved_local_prompt == 0)
1806     {
1807       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
1808       pmt = (char *)xmalloc (len + 2);
1809       if (len)
1810         strcpy (pmt, rl_prompt);
1811       pmt[len] = pchar;
1812       pmt[len+1] = '\0';
1813     }
1814   else
1815     {
1816       len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
1817       pmt = (char *)xmalloc (len + 2);
1818       if (len)
1819         strcpy (pmt, saved_local_prompt);
1820       pmt[len] = pchar;
1821       pmt[len+1] = '\0';
1822       local_prompt = savestring (pmt);
1823       prompt_last_invisible = saved_last_invisible;
1824       prompt_visible_length = saved_visible_length + 1;
1825     }
1826   return pmt;
1827 }
1828
1829 /* Quick redisplay hack when erasing characters at the end of the line. */
1830 void
1831 _rl_erase_at_end_of_line (l)
1832      int l;
1833 {
1834   register int i;
1835
1836   _rl_backspace (l);
1837   for (i = 0; i < l; i++)
1838     putc (' ', rl_outstream);
1839   _rl_backspace (l);
1840   for (i = 0; i < l; i++)
1841     visible_line[--_rl_last_c_pos] = '\0';
1842   rl_display_fixed++;
1843 }
1844
1845 /* Clear to the end of the line.  COUNT is the minimum
1846    number of character spaces to clear, */
1847 void
1848 _rl_clear_to_eol (count)
1849      int count;
1850 {
1851   if (_rl_term_clreol)
1852     tputs (_rl_term_clreol, 1, _rl_output_character_function);
1853   else if (count)
1854     space_to_eol (count);
1855 }
1856
1857 /* Clear to the end of the line using spaces.  COUNT is the minimum
1858    number of character spaces to clear, */
1859 static void
1860 space_to_eol (count)
1861      int count;
1862 {
1863   register int i;
1864
1865   for (i = 0; i < count; i++)
1866    putc (' ', rl_outstream);
1867
1868   _rl_last_c_pos += count;
1869 }
1870
1871 void
1872 _rl_clear_screen ()
1873 {
1874   if (_rl_term_clrpag)
1875     tputs (_rl_term_clrpag, 1, _rl_output_character_function);
1876   else
1877     rl_crlf ();
1878 }
1879
1880 /* Insert COUNT characters from STRING to the output stream at column COL. */
1881 static void
1882 insert_some_chars (string, count, col)
1883      char *string;
1884      int count, col;
1885 {
1886   /* DEBUGGING */
1887   if (MB_CUR_MAX == 1 || rl_byte_oriented)
1888     if (count != col)
1889       fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
1890
1891   /* If IC is defined, then we do not have to "enter" insert mode. */
1892   if (_rl_term_IC)
1893     {
1894       char *buffer;
1895
1896       buffer = tgoto (_rl_term_IC, 0, col);
1897       tputs (buffer, 1, _rl_output_character_function);
1898       _rl_output_some_chars (string, count);
1899     }
1900   else
1901     {
1902       register int i;
1903
1904       /* If we have to turn on insert-mode, then do so. */
1905       if (_rl_term_im && *_rl_term_im)
1906         tputs (_rl_term_im, 1, _rl_output_character_function);
1907
1908       /* If there is a special command for inserting characters, then
1909          use that first to open up the space. */
1910       if (_rl_term_ic && *_rl_term_ic)
1911         {
1912           for (i = col; i--; )
1913             tputs (_rl_term_ic, 1, _rl_output_character_function);
1914         }
1915
1916       /* Print the text. */
1917       _rl_output_some_chars (string, count);
1918
1919       /* If there is a string to turn off insert mode, we had best use
1920          it now. */
1921       if (_rl_term_ei && *_rl_term_ei)
1922         tputs (_rl_term_ei, 1, _rl_output_character_function);
1923     }
1924 }
1925
1926 /* Delete COUNT characters from the display line. */
1927 static void
1928 delete_chars (count)
1929      int count;
1930 {
1931   if (count > _rl_screenwidth)  /* XXX */
1932     return;
1933
1934   if (_rl_term_DC && *_rl_term_DC)
1935     {
1936       char *buffer;
1937       buffer = tgoto (_rl_term_DC, count, count);
1938       tputs (buffer, count, _rl_output_character_function);
1939     }
1940   else
1941     {
1942       if (_rl_term_dc && *_rl_term_dc)
1943         while (count--)
1944           tputs (_rl_term_dc, 1, _rl_output_character_function);
1945     }
1946 }
1947
1948 void
1949 _rl_update_final ()
1950 {
1951   int full_lines;
1952
1953   full_lines = 0;
1954   /* If the cursor is the only thing on an otherwise-blank last line,
1955      compensate so we don't print an extra CRLF. */
1956   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
1957         visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
1958     {
1959       _rl_vis_botlin--;
1960       full_lines = 1;
1961     }
1962   _rl_move_vert (_rl_vis_botlin);
1963   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
1964   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
1965     {
1966       char *last_line;
1967
1968       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
1969       _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
1970       _rl_clear_to_eol (0);
1971       putc (last_line[_rl_screenwidth - 1], rl_outstream);
1972     }
1973   _rl_vis_botlin = 0;
1974   rl_crlf ();
1975   fflush (rl_outstream);
1976   rl_display_fixed++;
1977 }
1978
1979 /* Move to the start of the current line. */
1980 static void
1981 cr ()
1982 {
1983   if (_rl_term_cr)
1984     {
1985 #if defined (__MSDOS__)
1986       putc ('\r', rl_outstream);
1987 #else
1988       tputs (_rl_term_cr, 1, _rl_output_character_function);
1989 #endif
1990       _rl_last_c_pos = 0;
1991     }
1992 }
1993
1994 /* Redraw the last line of a multi-line prompt that may possibly contain
1995    terminal escape sequences.  Called with the cursor at column 0 of the
1996    line to draw the prompt on. */
1997 static void
1998 redraw_prompt (t)
1999      char *t;
2000 {
2001   char *oldp, *oldl, *oldlprefix;
2002   int oldlen, oldlast, oldplen, oldninvis;
2003
2004   /* Geez, I should make this a struct. */
2005   oldp = rl_display_prompt;
2006   oldl = local_prompt;
2007   oldlprefix = local_prompt_prefix;
2008   oldlen = prompt_visible_length;
2009   oldplen = prompt_prefix_length;
2010   oldlast = prompt_last_invisible;
2011   oldninvis = prompt_invis_chars_first_line;
2012
2013   rl_display_prompt = t;
2014   local_prompt = expand_prompt (t, &prompt_visible_length,
2015                                    &prompt_last_invisible,
2016                                    &prompt_invis_chars_first_line);
2017   local_prompt_prefix = (char *)NULL;
2018   rl_forced_update_display ();
2019
2020   rl_display_prompt = oldp;
2021   local_prompt = oldl;
2022   local_prompt_prefix = oldlprefix;
2023   prompt_visible_length = oldlen;
2024   prompt_prefix_length = oldplen;
2025   prompt_last_invisible = oldlast;
2026   prompt_invis_chars_first_line = oldninvis;
2027 }
2028       
2029 /* Redisplay the current line after a SIGWINCH is received. */
2030 void
2031 _rl_redisplay_after_sigwinch ()
2032 {
2033   char *t;
2034
2035   /* Clear the current line and put the cursor at column 0.  Make sure
2036      the right thing happens if we have wrapped to a new screen line. */
2037   if (_rl_term_cr)
2038     {
2039 #if defined (__MSDOS__)
2040       putc ('\r', rl_outstream);
2041 #else
2042       tputs (_rl_term_cr, 1, _rl_output_character_function);
2043 #endif
2044       _rl_last_c_pos = 0;
2045 #if defined (__MSDOS__)
2046       space_to_eol (_rl_screenwidth);
2047       putc ('\r', rl_outstream);
2048 #else
2049       if (_rl_term_clreol)
2050         tputs (_rl_term_clreol, 1, _rl_output_character_function);
2051       else
2052         {
2053           space_to_eol (_rl_screenwidth);
2054           tputs (_rl_term_cr, 1, _rl_output_character_function);
2055         }
2056 #endif
2057       if (_rl_last_v_pos > 0)
2058         _rl_move_vert (0);
2059     }
2060   else
2061     rl_crlf ();
2062
2063   /* Redraw only the last line of a multi-line prompt. */
2064   t = strrchr (rl_display_prompt, '\n');
2065   if (t)
2066     redraw_prompt (++t);
2067   else
2068     rl_forced_update_display ();
2069 }
2070
2071 void
2072 _rl_clean_up_for_exit ()
2073 {
2074   if (readline_echoing_p)
2075     {
2076       _rl_move_vert (_rl_vis_botlin);
2077       _rl_vis_botlin = 0;
2078       fflush (rl_outstream);
2079       rl_restart_output (1, 0);
2080     }
2081 }
2082
2083 void
2084 _rl_erase_entire_line ()
2085 {
2086   cr ();
2087   _rl_clear_to_eol (0);
2088   cr ();
2089   fflush (rl_outstream);
2090 }
2091
2092 /* return the `current display line' of the cursor -- the number of lines to
2093    move up to get to the first screen line of the current readline line. */
2094 int
2095 _rl_current_display_line ()
2096 {
2097   int ret, nleft;
2098
2099   /* Find out whether or not there might be invisible characters in the
2100      editing buffer. */
2101   if (rl_display_prompt == rl_prompt)
2102     nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
2103   else
2104     nleft = _rl_last_c_pos - _rl_screenwidth;
2105
2106   if (nleft > 0)
2107     ret = 1 + nleft / _rl_screenwidth;
2108   else
2109     ret = 0;
2110
2111   return ret;
2112 }
2113
2114 #if defined (HANDLE_MULTIBYTE)
2115 /* Calculate the number of screen columns occupied by STR from START to END.
2116    In the case of multibyte characters with stateful encoding, we have to
2117    scan from the beginning of the string to take the state into account. */
2118 static int
2119 _rl_col_width (str, start, end)
2120      char *str;
2121      int start, end;
2122 {
2123   wchar_t wc;
2124   mbstate_t ps = {0};
2125   int tmp, point, width, max;
2126
2127   if (end <= start)
2128     return 0;
2129
2130   point = 0;
2131   max = end;
2132
2133   while (point < start)
2134     {
2135       tmp = mbrlen (str + point, max, &ps);
2136       if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
2137         {
2138           /* In this case, the bytes are invalid or too short to compose a
2139              multibyte character, so we assume that the first byte represents
2140              a single character. */
2141           point++;
2142           max--;
2143
2144           /* Clear the state of the byte sequence, because in this case the
2145              effect of mbstate is undefined. */
2146           memset (&ps, 0, sizeof (mbstate_t));
2147         }
2148       else if (tmp == 0)
2149         break;          /* Found '\0' */
2150       else
2151         {
2152           point += tmp;
2153           max -= tmp;
2154         }
2155     }
2156
2157   /* If START is not a byte that starts a character, then POINT will be
2158      greater than START.  In this case, assume that (POINT - START) gives
2159      a byte count that is the number of columns of difference. */
2160   width = point - start;
2161
2162   while (point < end)
2163     {
2164       tmp = mbrtowc (&wc, str + point, max, &ps);
2165       if ((size_t)tmp == (size_t)-1 || (size_t)tmp == (size_t)-2)
2166         {
2167           /* In this case, the bytes are invalid or too short to compose a
2168              multibyte character, so we assume that the first byte represents
2169              a single character. */
2170           point++;
2171           max--;
2172
2173           /* and assume that the byte occupies a single column. */
2174           width++;
2175
2176           /* Clear the state of the byte sequence, because in this case the
2177              effect of mbstate is undefined. */
2178           memset (&ps, 0, sizeof (mbstate_t));
2179         }
2180       else if (tmp == 0)
2181         break;                  /* Found '\0' */
2182       else
2183         {
2184           point += tmp;
2185           max -= tmp;
2186           tmp = wcwidth(wc);
2187           width += (tmp >= 0) ? tmp : 1;
2188         }
2189     }
2190
2191   width += point - end;
2192
2193   return width;
2194 }
2195 #endif /* HANDLE_MULTIBYTE */
2196