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