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