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