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