Imported from ../bash-2.04.tar.gz.
[platform/upstream/bash.git] / lib / readline / display.c
1 /* display.c -- readline redisplay facility. */
2
3 /* Copyright (C) 1987, 1989, 1992 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 /* System-specific feature definitions and include files. */
45 #include "rldefs.h"
46
47 /* Termcap library stuff. */
48 #include "tcap.h"
49
50 /* Some standard library routines. */
51 #include "readline.h"
52 #include "history.h"
53
54 #include "rlprivate.h"
55 #include "xmalloc.h"
56
57 #if !defined (strchr) && !defined (__STDC__)
58 extern char *strchr (), *strrchr ();
59 #endif /* !strchr && !__STDC__ */
60
61 #if defined (HACK_TERMCAP_MOTION)
62 extern char *term_forward_char;
63 #endif
64
65 static void update_line __P((char *, char *, int, int, int, int));
66 static void space_to_eol __P((int));
67 static void delete_chars __P((int));
68 static void insert_some_chars __P((char *, int));
69 static void cr __P((void));
70
71 static int *inv_lbreaks, *vis_lbreaks;
72 static int inv_lbsize, vis_lbsize;
73
74 /* Heuristic used to decide whether it is faster to move from CUR to NEW
75    by backing up or outputting a carriage return and moving forward. */
76 #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
77
78 /* **************************************************************** */
79 /*                                                                  */
80 /*                      Display stuff                               */
81 /*                                                                  */
82 /* **************************************************************** */
83
84 /* This is the stuff that is hard for me.  I never seem to write good
85    display routines in C.  Let's see how I do this time. */
86
87 /* (PWP) Well... Good for a simple line updater, but totally ignores
88    the problems of input lines longer than the screen width.
89
90    update_line and the code that calls it makes a multiple line,
91    automatically wrapping line update.  Careful attention needs
92    to be paid to the vertical position variables. */
93
94 /* Keep two buffers; one which reflects the current contents of the
95    screen, and the other to draw what we think the new contents should
96    be.  Then compare the buffers, and make whatever changes to the
97    screen itself that we should.  Finally, make the buffer that we
98    just drew into be the one which reflects the current contents of the
99    screen, and place the cursor where it belongs.
100
101    Commands that want to can fix the display themselves, and then let
102    this function know that the display has been fixed by setting the
103    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
104
105 /* Application-specific redisplay function. */
106 VFunction *rl_redisplay_function = rl_redisplay;
107
108 /* Global variables declared here. */
109 /* What YOU turn on when you have handled all redisplay yourself. */
110 int rl_display_fixed = 0;
111
112 int _rl_suppress_redisplay = 0;
113
114 /* The stuff that gets printed out before the actual text of the line.
115    This is usually pointing to rl_prompt. */
116 char *rl_display_prompt = (char *)NULL;
117
118 /* Pseudo-global variables declared here. */
119 /* The visible cursor position.  If you print some text, adjust this. */
120 int _rl_last_c_pos = 0;
121 int _rl_last_v_pos = 0;
122
123 /* Number of lines currently on screen minus 1. */
124 int _rl_vis_botlin = 0;
125
126 /* Variables used only in this file. */
127 /* The last left edge of text that was displayed.  This is used when
128    doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
129 static int last_lmargin;
130
131 /* The line display buffers.  One is the line currently displayed on
132    the screen.  The other is the line about to be displayed. */
133 static char *visible_line = (char *)NULL;
134 static char *invisible_line = (char *)NULL;
135
136 /* A buffer for `modeline' messages. */
137 static char msg_buf[128];
138
139 /* Non-zero forces the redisplay even if we thought it was unnecessary. */
140 static int forced_display;
141
142 /* Default and initial buffer size.  Can grow. */
143 static int line_size = 1024;
144
145 static char *local_prompt, *local_prompt_prefix;
146 static int visible_length, prefix_length;
147
148 /* The number of invisible characters in the line currently being
149    displayed on the screen. */
150 static int visible_wrap_offset;
151
152 /* static so it can be shared between rl_redisplay and update_line */
153 static int wrap_offset;
154
155 /* The index of the last invisible_character in the prompt string. */
156 static int last_invisible;
157
158 /* The length (buffer offset) of the first line of the last (possibly
159    multi-line) buffer displayed on the screen. */
160 static int visible_first_line_len;
161
162 /* Expand the prompt string S and return the number of visible
163    characters in *LP, if LP is not null.  This is currently more-or-less
164    a placeholder for expansion.  LIP, if non-null is a place to store the
165    index of the last invisible character in the returned string. */
166
167 /* Current implementation:
168         \001 (^A) start non-visible characters
169         \002 (^B) end non-visible characters
170    all characters except \001 and \002 (following a \001) are copied to
171    the returned string; all characters except those between \001 and
172    \002 are assumed to be `visible'. */ 
173
174 static char *
175 expand_prompt (pmt, lp, lip)
176      char *pmt;
177      int *lp, *lip;
178 {
179   char *r, *ret, *p;
180   int l, rl, last, ignoring;
181
182   /* Short-circuit if we can. */
183   if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
184     {
185       r = savestring (pmt);
186       if (lp)
187         *lp = strlen (r);
188       return r;
189     }
190
191   l = strlen (pmt);
192   r = ret = xmalloc (l + 1);
193   
194   for (rl = ignoring = last = 0, p = pmt; p && *p; p++)
195     {
196       /* This code strips the invisible character string markers
197          RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
198       if (*p == RL_PROMPT_START_IGNORE)
199         {
200           ignoring++;
201           continue;
202         }
203       else if (ignoring && *p == RL_PROMPT_END_IGNORE)
204         {
205           ignoring = 0;
206           last = r - ret - 1;
207           continue;
208         }
209       else
210         {
211           *r++ = *p;
212           if (!ignoring)
213             rl++;
214         }
215     }
216
217   *r = '\0';
218   if (lp)
219     *lp = rl;
220   if (lip)
221     *lip = last;
222   return ret;
223 }
224
225 /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
226    PMT and return the rest of PMT. */
227 char *
228 _rl_strip_prompt (pmt)
229      char *pmt;
230 {
231   char *ret;
232
233   ret = expand_prompt (pmt, (int *)NULL, (int *)NULL);
234   return ret;
235 }
236
237 /*
238  * Expand the prompt string into the various display components, if
239  * necessary.
240  *
241  * local_prompt = expanded last line of string in rl_display_prompt
242  *                (portion after the final newline)
243  * local_prompt_prefix = portion before last newline of rl_display_prompt,
244  *                       expanded via expand_prompt
245  * visible_length = number of visible characters in local_prompt
246  * prefix_length = number of visible characters in local_prompt_prefix
247  *
248  * This function is called once per call to readline().  It may also be
249  * called arbitrarily to expand the primary prompt.
250  *
251  * The return value is the number of visible characters on the last line
252  * of the (possibly multi-line) prompt.
253  */
254 int
255 rl_expand_prompt (prompt)
256      char *prompt;
257 {
258   char *p, *t;
259   int c;
260
261   /* Clear out any saved values. */
262   if (local_prompt)
263     free (local_prompt);
264   if (local_prompt_prefix)
265     free (local_prompt_prefix);
266   local_prompt = local_prompt_prefix = (char *)0;
267   last_invisible = visible_length = 0;
268
269   if (prompt == 0 || *prompt == 0)
270     return (0);
271
272   p = strrchr (prompt, '\n');
273   if (!p)
274     {
275       /* The prompt is only one line. */
276       local_prompt = expand_prompt (prompt, &visible_length, &last_invisible);
277       local_prompt_prefix = (char *)0;
278       return (visible_length);
279     }
280   else
281     {
282       /* The prompt spans multiple lines. */
283       t = ++p;
284       local_prompt = expand_prompt (p, &visible_length, &last_invisible);
285       c = *t; *t = '\0';
286       /* The portion of the prompt string up to and including the
287          final newline is now null-terminated. */
288       local_prompt_prefix = expand_prompt (prompt, &prefix_length, (int *)NULL);
289       *t = c;
290       return (prefix_length);
291     }
292 }
293
294 /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
295    arrays of line break markers.  MINSIZE is the minimum size of VISIBLE_LINE
296    and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
297    increased.  If the lines have already been allocated, this ensures that
298    they can hold at least MINSIZE characters. */
299 static void
300 init_line_structures (minsize)
301       int minsize;
302 {
303   register int n;
304
305   if (invisible_line == 0)      /* initialize it */
306     {
307       if (line_size < minsize)
308         line_size = minsize;
309       visible_line = xmalloc (line_size);
310       invisible_line = xmalloc (line_size);
311     }
312   else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
313     {
314       line_size *= 2;
315       if (line_size < minsize)
316         line_size = minsize;
317       visible_line = xrealloc (visible_line, line_size);
318       invisible_line = xrealloc (invisible_line, line_size);
319     }
320
321   for (n = minsize; n < line_size; n++)
322     {
323       visible_line[n] = 0;
324       invisible_line[n] = 1;
325     }
326
327   if (vis_lbreaks == 0)
328     {
329       /* should be enough. */
330       inv_lbsize = vis_lbsize = 256;
331       inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
332       vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
333       inv_lbreaks[0] = vis_lbreaks[0] = 0;
334     }
335 }
336   
337 /* Basic redisplay algorithm. */
338 void
339 rl_redisplay ()
340 {
341   register int in, out, c, linenum, cursor_linenum;
342   register char *line;
343   int c_pos, inv_botlin, lb_botlin, lb_linenum;
344   int newlines, lpos, temp;
345   char *prompt_this_line;
346
347   if (!readline_echoing_p)
348     return;
349
350   if (!rl_display_prompt)
351     rl_display_prompt = "";
352
353   if (invisible_line == 0)
354     {
355       init_line_structures (0);
356       rl_on_new_line ();
357     }
358
359   /* Draw the line into the buffer. */
360   c_pos = -1;
361
362   line = invisible_line;
363   out = inv_botlin = 0;
364
365   /* Mark the line as modified or not.  We only do this for history
366      lines. */
367   if (_rl_mark_modified_lines && current_history () && rl_undo_list)
368     {
369       line[out++] = '*';
370       line[out] = '\0';
371     }
372
373   /* If someone thought that the redisplay was handled, but the currently
374      visible line has a different modification state than the one about
375      to become visible, then correct the caller's misconception. */
376   if (visible_line[0] != invisible_line[0])
377     rl_display_fixed = 0;
378
379   /* If the prompt to be displayed is the `primary' readline prompt (the
380      one passed to readline()), use the values we have already expanded.
381      If not, use what's already in rl_display_prompt.  WRAP_OFFSET is the
382      number of non-visible characters in the prompt string. */
383   if (rl_display_prompt == rl_prompt || local_prompt)
384     {
385       int local_len = local_prompt ? strlen (local_prompt) : 0;
386       if (local_prompt_prefix && forced_display)
387         _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
388
389       if (local_len > 0)
390         {
391           temp = local_len + out + 2;
392           if (temp >= line_size)
393             {
394               line_size = (temp + 1024) - (temp % 1024);
395               visible_line = xrealloc (visible_line, line_size);
396               line = invisible_line = xrealloc (invisible_line, line_size);
397             }
398           strncpy (line + out, local_prompt, local_len);
399           out += local_len;
400         }
401       line[out] = '\0';
402       wrap_offset = local_len - visible_length;
403     }
404   else
405     {
406       int pmtlen;
407       prompt_this_line = strrchr (rl_display_prompt, '\n');
408       if (!prompt_this_line)
409         prompt_this_line = rl_display_prompt;
410       else
411         {
412           prompt_this_line++;
413           pmtlen = prompt_this_line - rl_display_prompt;        /* temp var */
414           if (forced_display)
415             {
416               _rl_output_some_chars (rl_display_prompt, pmtlen);
417               /* Make sure we are at column zero even after a newline,
418                  regardless of the state of terminal output processing. */
419               if (pmtlen < 2 || prompt_this_line[-2] != '\r')
420                 cr ();
421             }
422         }
423
424       pmtlen = strlen (prompt_this_line);
425       temp = pmtlen + out + 2;
426       if (temp >= line_size)
427         {
428           line_size = (temp + 1024) - (temp % 1024);
429           visible_line = xrealloc (visible_line, line_size);
430           line = invisible_line = xrealloc (invisible_line, line_size);
431         }
432       strncpy (line + out,  prompt_this_line, pmtlen);
433       out += pmtlen;
434       line[out] = '\0';
435       wrap_offset = 0;
436     }
437
438 #define CHECK_INV_LBREAKS() \
439       do { \
440         if (newlines >= (inv_lbsize - 2)) \
441           { \
442             inv_lbsize *= 2; \
443             inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
444           } \
445       } while (0)
446           
447 #define CHECK_LPOS() \
448       do { \
449         lpos++; \
450         if (lpos >= screenwidth) \
451           { \
452             if (newlines >= (inv_lbsize - 2)) \
453               { \
454                 inv_lbsize *= 2; \
455                 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
456               } \
457             inv_lbreaks[++newlines] = out; \
458             lpos = 0; \
459           } \
460       } while (0)
461
462   /* inv_lbreaks[i] is where line i starts in the buffer. */
463   inv_lbreaks[newlines = 0] = 0;
464   lpos = out - wrap_offset;
465
466   /* XXX - what if lpos is already >= screenwidth before we start drawing the
467      contents of the command line? */
468   while (lpos >= screenwidth)
469     {
470       /* XXX - possible fix from Darin Johnson <darin@acuson.com> for prompt
471          string with invisible characters that is longer than the screen
472          width.  XXX - this doesn't work right if invisible characters have
473          to be put on the second screen line -- it adds too much (the number
474          of invisible chars after the screenwidth). */
475       temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0);
476
477       inv_lbreaks[++newlines] = temp;
478       lpos -= screenwidth;
479     }
480
481   lb_linenum = 0;
482   for (in = 0; in < rl_end; in++)
483     {
484       c = (unsigned char)rl_line_buffer[in];
485
486       if (out + 8 >= line_size)         /* XXX - 8 for \t */
487         {
488           line_size *= 2;
489           visible_line = xrealloc (visible_line, line_size);
490           invisible_line = xrealloc (invisible_line, line_size);
491           line = invisible_line;
492         }
493
494       if (in == rl_point)
495         {
496           c_pos = out;
497           lb_linenum = newlines;
498         }
499
500       if (META_CHAR (c))
501         {
502           if (_rl_output_meta_chars == 0)
503             {
504               sprintf (line + out, "\\%o", c);
505
506               if (lpos + 4 >= screenwidth)
507                 {
508                   temp = screenwidth - lpos;
509                   CHECK_INV_LBREAKS ();
510                   inv_lbreaks[++newlines] = out + temp;
511                   lpos = 4 - temp;
512                 }
513               else
514                 lpos += 4;
515
516               out += 4;
517             }
518           else
519             {
520               line[out++] = c;
521               CHECK_LPOS();
522             }
523         }
524 #if defined (DISPLAY_TABS)
525       else if (c == '\t')
526         {
527           register int temp, newout;
528
529 #if 0
530           newout = (out | (int)7) + 1;
531 #else
532           newout = out + 8 - lpos % 8;
533 #endif
534           temp = newout - out;
535           if (lpos + temp >= screenwidth)
536             {
537               register int temp2;
538               temp2 = screenwidth - lpos;
539               CHECK_INV_LBREAKS ();
540               inv_lbreaks[++newlines] = out + temp2;
541               lpos = temp - temp2;
542               while (out < newout)
543                 line[out++] = ' ';
544             }
545           else
546             {
547               while (out < newout)
548                 line[out++] = ' ';
549               lpos += temp;
550             }
551         }
552 #endif
553       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && term_up && *term_up)
554         {
555           line[out++] = '\0';   /* XXX - sentinel */
556           CHECK_INV_LBREAKS ();
557           inv_lbreaks[++newlines] = out;
558           lpos = 0;
559         }
560       else if (CTRL_CHAR (c) || c == RUBOUT)
561         {
562           line[out++] = '^';
563           CHECK_LPOS();
564           line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
565           CHECK_LPOS();
566         }
567       else
568         {
569           line[out++] = c;
570           CHECK_LPOS();
571         }
572     }
573   line[out] = '\0';
574   if (c_pos < 0)
575     {
576       c_pos = out;
577       lb_linenum = newlines;
578     }
579
580   inv_botlin = lb_botlin = newlines;
581   CHECK_INV_LBREAKS ();
582   inv_lbreaks[newlines+1] = out;
583   cursor_linenum = lb_linenum;
584
585   /* C_POS == position in buffer where cursor should be placed. */
586
587   /* PWP: now is when things get a bit hairy.  The visible and invisible
588      line buffers are really multiple lines, which would wrap every
589      (screenwidth - 1) characters.  Go through each in turn, finding
590      the changed region and updating it.  The line order is top to bottom. */
591
592   /* If we can move the cursor up and down, then use multiple lines,
593      otherwise, let long lines display in a single terminal line, and
594      horizontally scroll it. */
595
596   if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up)
597     {
598       int nleft, pos, changed_screen_line;
599
600       if (!rl_display_fixed || forced_display)
601         {
602           forced_display = 0;
603
604           /* If we have more than a screenful of material to display, then
605              only display a screenful.  We should display the last screen,
606              not the first.  */
607           if (out >= screenchars)
608             out = screenchars - 1;
609
610           /* The first line is at character position 0 in the buffer.  The
611              second and subsequent lines start at inv_lbreaks[N], offset by
612              OFFSET (which has already been calculated above).  */
613
614 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
615 #define VIS_LLEN(l)     ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
616 #define INV_LLEN(l)     (inv_lbreaks[l+1] - inv_lbreaks[l])
617 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
618 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
619 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
620
621           /* For each line in the buffer, do the updating display. */
622           for (linenum = 0; linenum <= inv_botlin; linenum++)
623             {
624               update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
625                            VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
626
627               /* If this is the line with the prompt, we might need to
628                  compensate for invisible characters in the new line. Do
629                  this only if there is not more than one new line (which
630                  implies that we completely overwrite the old visible line)
631                  and the new line is shorter than the old.  Make sure we are
632                  at the end of the new line before clearing. */
633               if (linenum == 0 &&
634                   inv_botlin == 0 && _rl_last_c_pos == out &&
635                   (wrap_offset > visible_wrap_offset) &&
636                   (_rl_last_c_pos < visible_first_line_len))
637                 {
638                   nleft = screenwidth + wrap_offset - _rl_last_c_pos;
639                   if (nleft)
640                     _rl_clear_to_eol (nleft);
641                 }
642
643               /* Since the new first line is now visible, save its length. */
644               if (linenum == 0)
645                 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
646             }
647
648           /* We may have deleted some lines.  If so, clear the left over
649              blank ones at the bottom out. */
650           if (_rl_vis_botlin > inv_botlin)
651             {
652               char *tt;
653               for (; linenum <= _rl_vis_botlin; linenum++)
654                 {
655                   tt = VIS_CHARS (linenum);
656                   _rl_move_vert (linenum);
657                   _rl_move_cursor_relative (0, tt);
658                   _rl_clear_to_eol
659                     ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
660                 }
661             }
662           _rl_vis_botlin = inv_botlin;
663
664           /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
665              different screen line during this redisplay. */
666           changed_screen_line = _rl_last_v_pos != cursor_linenum;
667           if (changed_screen_line)
668             {
669               _rl_move_vert (cursor_linenum);
670               /* If we moved up to the line with the prompt using term_up,
671                  the physical cursor position on the screen stays the same,
672                  but the buffer position needs to be adjusted to account
673                  for invisible characters. */
674               if (cursor_linenum == 0 && wrap_offset)
675                 _rl_last_c_pos += wrap_offset;
676             }
677
678           /* We have to reprint the prompt if it contains invisible
679              characters, since it's not generally OK to just reprint
680              the characters from the current cursor position.  But we
681              only need to reprint it if the cursor is before the last
682              invisible character in the prompt string. */
683           nleft = visible_length + wrap_offset;
684           if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
685               _rl_last_c_pos <= last_invisible && local_prompt)
686             {
687 #if defined (__MSDOS__)
688               putc ('\r', rl_outstream);
689 #else
690               if (term_cr)
691                 tputs (term_cr, 1, _rl_output_character_function);
692 #endif
693               _rl_output_some_chars (local_prompt, nleft);
694               _rl_last_c_pos = nleft;
695             }
696
697           /* Where on that line?  And where does that line start
698              in the buffer? */
699           pos = inv_lbreaks[cursor_linenum];
700           /* nleft == number of characters in the line buffer between the
701              start of the line and the cursor position. */
702           nleft = c_pos - pos;
703
704           /* Since _rl_backspace() doesn't know about invisible characters in the
705              prompt, and there's no good way to tell it, we compensate for
706              those characters here and call _rl_backspace() directly. */
707           if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
708             {
709               _rl_backspace (_rl_last_c_pos - nleft);
710               _rl_last_c_pos = nleft;
711             }
712
713           if (nleft != _rl_last_c_pos)
714             _rl_move_cursor_relative (nleft, &invisible_line[pos]);
715         }
716     }
717   else                          /* Do horizontal scrolling. */
718     {
719 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
720       int lmargin, ndisp, nleft, phys_c_pos, t;
721
722       /* Always at top line. */
723       _rl_last_v_pos = 0;
724
725       /* Compute where in the buffer the displayed line should start.  This
726          will be LMARGIN. */
727
728       /* The number of characters that will be displayed before the cursor. */
729       ndisp = c_pos - wrap_offset;
730       nleft  = visible_length + wrap_offset;
731       /* Where the new cursor position will be on the screen.  This can be
732          longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
733       phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
734       t = screenwidth / 3;
735
736       /* If the number of characters had already exceeded the screenwidth,
737          last_lmargin will be > 0. */
738
739       /* If the number of characters to be displayed is more than the screen
740          width, compute the starting offset so that the cursor is about
741          two-thirds of the way across the screen. */
742       if (phys_c_pos > screenwidth - 2)
743         {
744           lmargin = c_pos - (2 * t);
745           if (lmargin < 0)
746             lmargin = 0;
747           /* If the left margin would be in the middle of a prompt with
748              invisible characters, don't display the prompt at all. */
749           if (wrap_offset && lmargin > 0 && lmargin < nleft)
750             lmargin = nleft;
751         }
752       else if (ndisp < screenwidth - 2)         /* XXX - was -1 */
753         lmargin = 0;
754       else if (phys_c_pos < 1)
755         {
756           /* If we are moving back towards the beginning of the line and
757              the last margin is no longer correct, compute a new one. */
758           lmargin = ((c_pos - 1) / t) * t;      /* XXX */
759           if (wrap_offset && lmargin > 0 && lmargin < nleft)
760             lmargin = nleft;
761         }
762       else
763         lmargin = last_lmargin;
764
765       /* If the first character on the screen isn't the first character
766          in the display line, indicate this with a special character. */
767       if (lmargin > 0)
768         line[lmargin] = '<';
769
770       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
771          the whole line, indicate that with a special character at the
772          right edge of the screen.  If LMARGIN is 0, we need to take the
773          wrap offset into account. */
774       t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
775       if (t < out)
776         line[t - 1] = '>';
777
778       if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
779         {
780           forced_display = 0;
781           update_line (&visible_line[last_lmargin],
782                        &invisible_line[lmargin],
783                        0,
784                        screenwidth + visible_wrap_offset,
785                        screenwidth + (lmargin ? 0 : wrap_offset),
786                        0);
787
788           /* If the visible new line is shorter than the old, but the number
789              of invisible characters is greater, and we are at the end of
790              the new line, we need to clear to eol. */
791           t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
792           if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
793               (_rl_last_c_pos == out) &&
794               t < visible_first_line_len)
795             {
796               nleft = screenwidth - t;
797               _rl_clear_to_eol (nleft);
798             }
799           visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
800           if (visible_first_line_len > screenwidth)
801             visible_first_line_len = screenwidth;
802
803           _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
804           last_lmargin = lmargin;
805         }
806     }
807   fflush (rl_outstream);
808
809   /* Swap visible and non-visible lines. */
810   {
811     char *temp = visible_line;
812     int *itemp = vis_lbreaks, ntemp = vis_lbsize;
813
814     visible_line = invisible_line;
815     invisible_line = temp;
816
817     vis_lbreaks = inv_lbreaks;
818     inv_lbreaks = itemp;
819
820     vis_lbsize = inv_lbsize;
821     inv_lbsize = ntemp;
822
823     rl_display_fixed = 0;
824     /* If we are displaying on a single line, and last_lmargin is > 0, we
825        are not displaying any invisible characters, so set visible_wrap_offset
826        to 0. */
827     if (_rl_horizontal_scroll_mode && last_lmargin)
828       visible_wrap_offset = 0;
829     else
830       visible_wrap_offset = wrap_offset;
831   }
832 }
833
834 /* PWP: update_line() is based on finding the middle difference of each
835    line on the screen; vis:
836
837                              /old first difference
838         /beginning of line   |        /old last same       /old EOL
839         v                    v        v             v
840 old:    eddie> Oh, my little gruntle-buggy is to me, as lurgid as
841 new:    eddie> Oh, my little buggy says to me, as lurgid as
842         ^                    ^  ^                          ^
843         \beginning of line   |  \new last same     \new end of line
844                              \new first difference
845
846    All are character pointers for the sake of speed.  Special cases for
847    no differences, as well as for end of line additions must be handled.
848
849    Could be made even smarter, but this works well enough */
850 static void
851 update_line (old, new, current_line, omax, nmax, inv_botlin)
852      register char *old, *new;
853      int current_line, omax, nmax, inv_botlin;
854 {
855   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
856   int temp, lendiff, wsatend, od, nd;
857   int current_invis_chars;
858
859   /* If we're at the right edge of a terminal that supports xn, we're
860      ready to wrap around, so do so.  This fixes problems with knowing
861      the exact cursor position and cut-and-paste with certain terminal
862      emulators.  In this calculation, TEMP is the physical screen
863      position of the cursor. */
864   temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
865   if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
866       && _rl_last_v_pos == current_line - 1)
867     {
868       if (new[0])
869         putc (new[0], rl_outstream);
870       else
871         putc (' ', rl_outstream);
872       _rl_last_c_pos = 1;               /* XXX */
873       _rl_last_v_pos++;
874       if (old[0] && new[0])
875         old[0] = new[0];
876     }
877       
878   /* Find first difference. */
879   for (ofd = old, nfd = new;
880        (ofd - old < omax) && *ofd && (*ofd == *nfd);
881        ofd++, nfd++)
882     ;
883
884   /* Move to the end of the screen line.  ND and OD are used to keep track
885      of the distance between ne and new and oe and old, respectively, to
886      move a subtraction out of each loop. */
887   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
888   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
889
890   /* If no difference, continue to next line. */
891   if (ofd == oe && nfd == ne)
892     return;
893
894   wsatend = 1;                  /* flag for trailing whitespace */
895   ols = oe - 1;                 /* find last same */
896   nls = ne - 1;
897   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
898     {
899       if (*ols != ' ')
900         wsatend = 0;
901       ols--;
902       nls--;
903     }
904
905   if (wsatend)
906     {
907       ols = oe;
908       nls = ne;
909     }
910   else if (*ols != *nls)
911     {
912       if (*ols)                 /* don't step past the NUL */
913         ols++;
914       if (*nls)
915         nls++;
916     }
917
918   /* count of invisible characters in the current invisible line. */
919   current_invis_chars = W_OFFSET (current_line, wrap_offset);
920   if (_rl_last_v_pos != current_line)
921     {
922       _rl_move_vert (current_line);
923       if (current_line == 0 && visible_wrap_offset)
924         _rl_last_c_pos += visible_wrap_offset;
925     }
926
927   /* If this is the first line and there are invisible characters in the
928      prompt string, and the prompt string has not changed, and the current
929      cursor position is before the last invisible character in the prompt,
930      and the index of the character to move to is past the end of the prompt
931      string, then redraw the entire prompt string.  We can only do this
932      reliably if the terminal supports a `cr' capability.
933
934      This is not an efficiency hack -- there is a problem with redrawing
935      portions of the prompt string if they contain terminal escape
936      sequences (like drawing the `unbold' sequence without a corresponding
937      `bold') that manifests itself on certain terminals. */
938
939   lendiff = local_prompt ? strlen (local_prompt) : 0;
940   od = ofd - old;       /* index of first difference in visible line */
941   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
942       term_cr && lendiff > visible_length && _rl_last_c_pos > 0 &&
943       od > lendiff && _rl_last_c_pos < last_invisible)
944     {
945 #if defined (__MSDOS__)
946       putc ('\r', rl_outstream);
947 #else
948       tputs (term_cr, 1, _rl_output_character_function);
949 #endif
950       _rl_output_some_chars (local_prompt, lendiff);
951       _rl_last_c_pos = lendiff;
952     }
953
954   _rl_move_cursor_relative (od, old);
955
956   /* if (len (new) > len (old)) */
957   lendiff = (nls - nfd) - (ols - ofd);
958
959   /* If we are changing the number of invisible characters in a line, and
960      the spot of first difference is before the end of the invisible chars,
961      lendiff needs to be adjusted. */
962   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
963       current_invis_chars != visible_wrap_offset)
964     lendiff += visible_wrap_offset - current_invis_chars;
965
966   /* Insert (diff (len (old), len (new)) ch. */
967   temp = ne - nfd;
968   if (lendiff > 0)
969     {
970       /* Non-zero if we're increasing the number of lines. */
971       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
972       /* Sometimes it is cheaper to print the characters rather than
973          use the terminal's capabilities.  If we're growing the number
974          of lines, make sure we actually cause the new line to wrap
975          around on auto-wrapping terminals. */
976       if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl))
977         {
978           /* If lendiff > visible_length and _rl_last_c_pos == 0 and
979              _rl_horizontal_scroll_mode == 1, inserting the characters with
980              term_IC or term_ic will screw up the screen because of the
981              invisible characters.  We need to just draw them. */
982           if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
983                         lendiff <= visible_length || !current_invis_chars))
984             {
985               insert_some_chars (nfd, lendiff);
986               _rl_last_c_pos += lendiff;
987             }
988           else if (*ols == 0)
989             {
990               /* At the end of a line the characters do not have to
991                  be "inserted".  They can just be placed on the screen. */
992               /* However, this screws up the rest of this block, which
993                  assumes you've done the insert because you can. */
994               _rl_output_some_chars (nfd, lendiff);
995               _rl_last_c_pos += lendiff;
996             }
997           else
998             {
999               /* We have horizontal scrolling and we are not inserting at
1000                  the end.  We have invisible characters in this line.  This
1001                  is a dumb update. */
1002               _rl_output_some_chars (nfd, temp);
1003               _rl_last_c_pos += temp;
1004               return;
1005             }
1006           /* Copy (new) chars to screen from first diff to last match. */
1007           temp = nls - nfd;
1008           if ((temp - lendiff) > 0)
1009             {
1010               _rl_output_some_chars (nfd + lendiff, temp - lendiff);
1011               _rl_last_c_pos += temp - lendiff;
1012             }
1013         }
1014       else
1015         {
1016           /* cannot insert chars, write to EOL */
1017           _rl_output_some_chars (nfd, temp);
1018           _rl_last_c_pos += temp;
1019         }
1020     }
1021   else                          /* Delete characters from line. */
1022     {
1023       /* If possible and inexpensive to use terminal deletion, then do so. */
1024       if (term_dc && (2 * temp) >= -lendiff)
1025         {
1026           /* If all we're doing is erasing the invisible characters in the
1027              prompt string, don't bother.  It screws up the assumptions
1028              about what's on the screen. */
1029           if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
1030               -lendiff == visible_wrap_offset)
1031             lendiff = 0;
1032
1033           if (lendiff)
1034             delete_chars (-lendiff); /* delete (diff) characters */
1035
1036           /* Copy (new) chars to screen from first diff to last match */
1037           temp = nls - nfd;
1038           if (temp > 0)
1039             {
1040               _rl_output_some_chars (nfd, temp);
1041               _rl_last_c_pos += temp;
1042             }
1043         }
1044       /* Otherwise, print over the existing material. */
1045       else
1046         {
1047           if (temp > 0)
1048             {
1049               _rl_output_some_chars (nfd, temp);
1050               _rl_last_c_pos += temp;
1051             }
1052           lendiff = (oe - old) - (ne - new);
1053           if (lendiff)
1054             {     
1055               if (_rl_term_autowrap && current_line < inv_botlin)
1056                 space_to_eol (lendiff);
1057               else
1058                 _rl_clear_to_eol (lendiff);
1059             }
1060         }
1061     }
1062 }
1063
1064 /* Tell the update routines that we have moved onto a new (empty) line. */
1065 int
1066 rl_on_new_line ()
1067 {
1068   if (visible_line)
1069     visible_line[0] = '\0';
1070
1071   _rl_last_c_pos = _rl_last_v_pos = 0;
1072   _rl_vis_botlin = last_lmargin = 0;
1073   if (vis_lbreaks)
1074     vis_lbreaks[0] = vis_lbreaks[1] = 0;
1075   visible_wrap_offset = 0;
1076   return 0;
1077 }
1078
1079 /* Tell the update routines that we have moved onto a new line with the
1080    prompt already displayed.  Code originally from the version of readline
1081    distributed with CLISP. */
1082 int
1083 rl_on_new_line_with_prompt ()
1084 {
1085   int prompt_size, i, l, real_screenwidth, newlines;
1086   char *prompt_last_line;
1087
1088   /* Initialize visible_line and invisible_line to ensure that they can hold
1089      the already-displayed prompt. */
1090   prompt_size = strlen (rl_prompt) + 1;
1091   init_line_structures (prompt_size);
1092
1093   /* Make sure the line structures hold the already-displayed prompt for
1094      redisplay. */
1095   strcpy (visible_line, rl_prompt);
1096   strcpy (invisible_line, rl_prompt);
1097
1098   /* If the prompt contains newlines, take the last tail. */
1099   prompt_last_line = strrchr (rl_prompt, '\n');
1100   if (!prompt_last_line)
1101     prompt_last_line = rl_prompt;
1102
1103   l = strlen (prompt_last_line);
1104   _rl_last_c_pos = l;
1105
1106   /* Dissect prompt_last_line into screen lines. Note that here we have
1107      to use the real screenwidth. Readline's notion of screenwidth might be
1108      one less, see terminal.c. */
1109   real_screenwidth = screenwidth + (_rl_term_autowrap ? 0 : 1);
1110   _rl_last_v_pos = l / real_screenwidth;
1111   /* If the prompt length is a multiple of real_screenwidth, we don't know
1112      whether the cursor is at the end of the last line, or already at the
1113      beginning of the next line. Output a newline just to be safe. */
1114   if (l > 0 && (l % real_screenwidth) == 0)
1115     _rl_output_some_chars ("\n", 1);
1116   last_lmargin = 0;
1117
1118   newlines = 0; i = 0;
1119   while (i <= l)
1120     {
1121       _rl_vis_botlin = newlines;
1122       vis_lbreaks[newlines++] = i;
1123       i += real_screenwidth;
1124     }
1125   vis_lbreaks[newlines] = l;
1126   visible_wrap_offset = 0;
1127
1128   return 0;
1129 }
1130
1131 /* Actually update the display, period. */
1132 int
1133 rl_forced_update_display ()
1134 {
1135   if (visible_line)
1136     {
1137       register char *temp = visible_line;
1138
1139       while (*temp)
1140         *temp++ = '\0';
1141     }
1142   rl_on_new_line ();
1143   forced_display++;
1144   (*rl_redisplay_function) ();
1145   return 0;
1146 }
1147
1148 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1149    DATA is the contents of the screen line of interest; i.e., where
1150    the movement is being done. */
1151 void
1152 _rl_move_cursor_relative (new, data)
1153      int new;
1154      char *data;
1155 {
1156   register int i;
1157
1158   /* If we don't have to do anything, then return. */
1159   if (_rl_last_c_pos == new) return;
1160
1161   /* It may be faster to output a CR, and then move forwards instead
1162      of moving backwards. */
1163   /* i == current physical cursor position. */
1164   i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1165   if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
1166       (_rl_term_autowrap && i == screenwidth))
1167     {
1168 #if defined (__MSDOS__)
1169       putc ('\r', rl_outstream);
1170 #else
1171       tputs (term_cr, 1, _rl_output_character_function);
1172 #endif /* !__MSDOS__ */
1173       _rl_last_c_pos = 0;
1174     }
1175
1176   if (_rl_last_c_pos < new)
1177     {
1178       /* Move the cursor forward.  We do it by printing the command
1179          to move the cursor forward if there is one, else print that
1180          portion of the output buffer again.  Which is cheaper? */
1181
1182       /* The above comment is left here for posterity.  It is faster
1183          to print one character (non-control) than to print a control
1184          sequence telling the terminal to move forward one character.
1185          That kind of control is for people who don't know what the
1186          data is underneath the cursor. */
1187 #if defined (HACK_TERMCAP_MOTION)
1188       if (term_forward_char)
1189         for (i = _rl_last_c_pos; i < new; i++)
1190           tputs (term_forward_char, 1, _rl_output_character_function);
1191       else
1192         for (i = _rl_last_c_pos; i < new; i++)
1193           putc (data[i], rl_outstream);
1194 #else
1195       for (i = _rl_last_c_pos; i < new; i++)
1196         putc (data[i], rl_outstream);
1197 #endif /* HACK_TERMCAP_MOTION */
1198     }
1199   else if (_rl_last_c_pos > new)
1200     _rl_backspace (_rl_last_c_pos - new);
1201   _rl_last_c_pos = new;
1202 }
1203
1204 /* PWP: move the cursor up or down. */
1205 void
1206 _rl_move_vert (to)
1207      int to;
1208 {
1209   register int delta, i;
1210
1211   if (_rl_last_v_pos == to || to > screenheight)
1212     return;
1213
1214   if ((delta = to - _rl_last_v_pos) > 0)
1215     {
1216       for (i = 0; i < delta; i++)
1217         putc ('\n', rl_outstream);
1218 #if defined (__MSDOS__)
1219       putc ('\r', rl_outstream);
1220 #else
1221       tputs (term_cr, 1, _rl_output_character_function);
1222 #endif
1223       _rl_last_c_pos = 0;
1224     }
1225   else
1226     {                   /* delta < 0 */
1227       if (term_up && *term_up)
1228         for (i = 0; i < -delta; i++)
1229           tputs (term_up, 1, _rl_output_character_function);
1230     }
1231
1232   _rl_last_v_pos = to;          /* Now TO is here */
1233 }
1234
1235 /* Physically print C on rl_outstream.  This is for functions which know
1236    how to optimize the display.  Return the number of characters output. */
1237 int
1238 rl_show_char (c)
1239      int c;
1240 {
1241   int n = 1;
1242   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
1243     {
1244       fprintf (rl_outstream, "M-");
1245       n += 2;
1246       c = UNMETA (c);
1247     }
1248
1249 #if defined (DISPLAY_TABS)
1250   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
1251 #else
1252   if (CTRL_CHAR (c) || c == RUBOUT)
1253 #endif /* !DISPLAY_TABS */
1254     {
1255       fprintf (rl_outstream, "C-");
1256       n += 2;
1257       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1258     }
1259
1260   putc (c, rl_outstream);
1261   fflush (rl_outstream);
1262   return n;
1263 }
1264
1265 int
1266 rl_character_len (c, pos)
1267      register int c, pos;
1268 {
1269   unsigned char uc;
1270
1271   uc = (unsigned char)c;
1272
1273   if (META_CHAR (uc))
1274     return ((_rl_output_meta_chars == 0) ? 4 : 1);
1275
1276   if (uc == '\t')
1277     {
1278 #if defined (DISPLAY_TABS)
1279       return (((pos | 7) + 1) - pos);
1280 #else
1281       return (2);
1282 #endif /* !DISPLAY_TABS */
1283     }
1284
1285   if (CTRL_CHAR (c) || c == RUBOUT)
1286     return (2);
1287
1288   return ((isprint (uc)) ? 1 : 2);
1289 }
1290
1291 /* How to print things in the "echo-area".  The prompt is treated as a
1292    mini-modeline. */
1293
1294 #if defined (USE_VARARGS)
1295 int
1296 #if defined (PREFER_STDARG)
1297 rl_message (const char *format, ...)
1298 #else
1299 rl_message (va_alist)
1300      va_dcl
1301 #endif
1302 {
1303   va_list args;
1304 #if defined (PREFER_VARARGS)
1305   char *format;
1306 #endif
1307
1308 #if defined (PREFER_STDARG)
1309   va_start (args, format);
1310 #else
1311   va_start (args);
1312   format = va_arg (args, char *);
1313 #endif
1314
1315   vsprintf (msg_buf, format, args);
1316   va_end (args);
1317
1318   rl_display_prompt = msg_buf;
1319   (*rl_redisplay_function) ();
1320   return 0;
1321 }
1322 #else /* !USE_VARARGS */
1323 int
1324 rl_message (format, arg1, arg2)
1325      char *format;
1326 {
1327   sprintf (msg_buf, format, arg1, arg2);
1328   rl_display_prompt = msg_buf;
1329   (*rl_redisplay_function) ();
1330   return 0;
1331 }
1332 #endif /* !USE_VARARGS */
1333
1334 /* How to clear things from the "echo-area". */
1335 int
1336 rl_clear_message ()
1337 {
1338   rl_display_prompt = rl_prompt;
1339   (*rl_redisplay_function) ();
1340   return 0;
1341 }
1342
1343 int
1344 rl_reset_line_state ()
1345 {
1346   rl_on_new_line ();
1347
1348   rl_display_prompt = rl_prompt ? rl_prompt : "";
1349   forced_display = 1;
1350   return 0;
1351 }
1352
1353 static char *saved_local_prompt;
1354 static char *saved_local_prefix;
1355 static int saved_last_invisible;
1356 static int saved_visible_length;
1357
1358 void
1359 rl_save_prompt ()
1360 {
1361   saved_local_prompt = local_prompt;
1362   saved_local_prefix = local_prompt_prefix;
1363   saved_last_invisible = last_invisible;
1364   saved_visible_length = visible_length;
1365
1366   local_prompt = local_prompt_prefix = (char *)0;
1367   last_invisible = visible_length = 0;
1368 }
1369
1370 void
1371 rl_restore_prompt ()
1372 {
1373   if (local_prompt)
1374     free (local_prompt);
1375   if (local_prompt_prefix)
1376     free (local_prompt_prefix);
1377
1378   local_prompt = saved_local_prompt;
1379   local_prompt_prefix = saved_local_prefix;
1380   last_invisible = saved_last_invisible;
1381   visible_length = saved_visible_length;
1382 }
1383
1384 char *
1385 _rl_make_prompt_for_search (pchar)
1386      int pchar;
1387 {
1388   int len;
1389   char *pmt;
1390
1391   rl_save_prompt ();
1392
1393   if (saved_local_prompt == 0)
1394     {
1395       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
1396       pmt = xmalloc (len + 2);
1397       if (len)
1398         strcpy (pmt, rl_prompt);
1399       pmt[len] = pchar;
1400       pmt[len+1] = '\0';
1401     }
1402   else
1403     {
1404       len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
1405       pmt = xmalloc (len + 2);
1406       if (len)
1407         strcpy (pmt, saved_local_prompt);
1408       pmt[len] = pchar;
1409       pmt[len+1] = '\0';
1410       local_prompt = savestring (pmt);
1411       last_invisible = saved_last_invisible;
1412       visible_length = saved_visible_length + 1;
1413     }
1414   return pmt;
1415 }
1416
1417 /* Quick redisplay hack when erasing characters at the end of the line. */
1418 void
1419 _rl_erase_at_end_of_line (l)
1420      int l;
1421 {
1422   register int i;
1423
1424   _rl_backspace (l);
1425   for (i = 0; i < l; i++)
1426     putc (' ', rl_outstream);
1427   _rl_backspace (l);
1428   for (i = 0; i < l; i++)
1429     visible_line[--_rl_last_c_pos] = '\0';
1430   rl_display_fixed++;
1431 }
1432
1433 /* Clear to the end of the line.  COUNT is the minimum
1434    number of character spaces to clear, */
1435 void
1436 _rl_clear_to_eol (count)
1437      int count;
1438 {
1439   if (term_clreol)
1440     tputs (term_clreol, 1, _rl_output_character_function);
1441   else if (count)
1442     space_to_eol (count);
1443 }
1444
1445 /* Clear to the end of the line using spaces.  COUNT is the minimum
1446    number of character spaces to clear, */
1447 static void
1448 space_to_eol (count)
1449      int count;
1450 {
1451   register int i;
1452
1453   for (i = 0; i < count; i++)
1454    putc (' ', rl_outstream);
1455
1456   _rl_last_c_pos += count;
1457 }
1458
1459 void
1460 _rl_clear_screen ()
1461 {
1462   if (term_clrpag)
1463     tputs (term_clrpag, 1, _rl_output_character_function);
1464   else
1465     crlf ();
1466 }
1467
1468 /* Insert COUNT characters from STRING to the output stream. */
1469 static void
1470 insert_some_chars (string, count)
1471      char *string;
1472      int count;
1473 {
1474   /* If IC is defined, then we do not have to "enter" insert mode. */
1475   if (term_IC)
1476     {
1477       char *buffer;
1478       buffer = tgoto (term_IC, 0, count);
1479       tputs (buffer, 1, _rl_output_character_function);
1480       _rl_output_some_chars (string, count);
1481     }
1482   else
1483     {
1484       register int i;
1485
1486       /* If we have to turn on insert-mode, then do so. */
1487       if (term_im && *term_im)
1488         tputs (term_im, 1, _rl_output_character_function);
1489
1490       /* If there is a special command for inserting characters, then
1491          use that first to open up the space. */
1492       if (term_ic && *term_ic)
1493         {
1494           for (i = count; i--; )
1495             tputs (term_ic, 1, _rl_output_character_function);
1496         }
1497
1498       /* Print the text. */
1499       _rl_output_some_chars (string, count);
1500
1501       /* If there is a string to turn off insert mode, we had best use
1502          it now. */
1503       if (term_ei && *term_ei)
1504         tputs (term_ei, 1, _rl_output_character_function);
1505     }
1506 }
1507
1508 /* Delete COUNT characters from the display line. */
1509 static void
1510 delete_chars (count)
1511      int count;
1512 {
1513   if (count > screenwidth)      /* XXX */
1514     return;
1515
1516   if (term_DC && *term_DC)
1517     {
1518       char *buffer;
1519       buffer = tgoto (term_DC, count, count);
1520       tputs (buffer, count, _rl_output_character_function);
1521     }
1522   else
1523     {
1524       if (term_dc && *term_dc)
1525         while (count--)
1526           tputs (term_dc, 1, _rl_output_character_function);
1527     }
1528 }
1529
1530 void
1531 _rl_update_final ()
1532 {
1533   int full_lines;
1534
1535   full_lines = 0;
1536   /* If the cursor is the only thing on an otherwise-blank last line,
1537      compensate so we don't print an extra CRLF. */
1538   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
1539         visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
1540     {
1541       _rl_vis_botlin--;
1542       full_lines = 1;
1543     }
1544   _rl_move_vert (_rl_vis_botlin);
1545   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
1546   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == screenwidth))
1547     {
1548       char *last_line;
1549 #if 0
1550       last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
1551 #else
1552       last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
1553 #endif
1554       _rl_move_cursor_relative (screenwidth - 1, last_line);
1555       _rl_clear_to_eol (0);
1556       putc (last_line[screenwidth - 1], rl_outstream);
1557     }
1558   _rl_vis_botlin = 0;
1559   crlf ();
1560   fflush (rl_outstream);
1561   rl_display_fixed++;
1562 }
1563
1564 /* Move to the start of the current line. */
1565 static void
1566 cr ()
1567 {
1568   if (term_cr)
1569     {
1570 #if defined (__MSDOS__)
1571       putc ('\r', rl_outstream);
1572 #else
1573       tputs (term_cr, 1, _rl_output_character_function);
1574 #endif
1575       _rl_last_c_pos = 0;
1576     }
1577 }
1578
1579 /* Redraw the last line of a multi-line prompt that may possibly contain
1580    terminal escape sequences.  Called with the cursor at column 0 of the
1581    line to draw the prompt on. */
1582 static void
1583 redraw_prompt (t)
1584      char *t;
1585 {
1586   char *oldp, *oldl, *oldlprefix;
1587   int oldlen, oldlast, oldplen;
1588
1589   /* Geez, I should make this a struct. */
1590   oldp = rl_display_prompt;
1591   oldl = local_prompt;
1592   oldlprefix = local_prompt_prefix;
1593   oldlen = visible_length;
1594   oldplen = prefix_length;
1595   oldlast = last_invisible;
1596
1597   rl_display_prompt = t;
1598   local_prompt = expand_prompt (t, &visible_length, &last_invisible);
1599   local_prompt_prefix = (char *)NULL;
1600   rl_forced_update_display ();
1601
1602   rl_display_prompt = oldp;
1603   local_prompt = oldl;
1604   local_prompt_prefix = oldlprefix;
1605   visible_length = oldlen;
1606   prefix_length = oldplen;
1607   last_invisible = oldlast;
1608 }
1609       
1610 /* Redisplay the current line after a SIGWINCH is received. */
1611 void
1612 _rl_redisplay_after_sigwinch ()
1613 {
1614   char *t;
1615
1616   /* Clear the current line and put the cursor at column 0.  Make sure
1617      the right thing happens if we have wrapped to a new screen line. */
1618   if (term_cr)
1619     {
1620 #if defined (__MSDOS__)
1621       putc ('\r', rl_outstream);
1622 #else
1623       tputs (term_cr, 1, _rl_output_character_function);
1624 #endif
1625       _rl_last_c_pos = 0;
1626 #if defined (__MSDOS__)
1627       space_to_eol (screenwidth);
1628       putc ('\r', rl_outstream);
1629 #else
1630       if (term_clreol)
1631         tputs (term_clreol, 1, _rl_output_character_function);
1632       else
1633         {
1634           space_to_eol (screenwidth);
1635           tputs (term_cr, 1, _rl_output_character_function);
1636         }
1637 #endif
1638       if (_rl_last_v_pos > 0)
1639         _rl_move_vert (0);
1640     }
1641   else
1642     crlf ();
1643
1644   /* Redraw only the last line of a multi-line prompt. */
1645   t = strrchr (rl_display_prompt, '\n');
1646   if (t)
1647     redraw_prompt (++t);
1648   else
1649     rl_forced_update_display ();
1650 }
1651
1652 void
1653 _rl_clean_up_for_exit ()
1654 {
1655   if (readline_echoing_p)
1656     {
1657       _rl_move_vert (_rl_vis_botlin);
1658       _rl_vis_botlin = 0;
1659       fflush (rl_outstream);
1660       rl_restart_output (1, 0);
1661     }
1662 }
1663
1664 void
1665 _rl_erase_entire_line ()
1666 {
1667   cr ();
1668   _rl_clear_to_eol (0);
1669   cr ();
1670   fflush (rl_outstream);
1671 }
1672
1673 /* return the `current display line' of the cursor -- the number of lines to
1674    move up to get to the first screen line of the current readline line. */
1675 int
1676 _rl_current_display_line ()
1677 {
1678   int ret, nleft;
1679
1680   /* Find out whether or not there might be invisible characters in the
1681      editing buffer. */
1682   if (rl_display_prompt == rl_prompt)
1683     nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length;
1684   else
1685     nleft = _rl_last_c_pos - screenwidth;
1686
1687   if (nleft > 0)
1688     ret = 1 + nleft / screenwidth;
1689   else
1690     ret = 0;
1691
1692   return ret;
1693 }