OSDN Git Service

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