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