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