25aba64ca67de4154ee082bfc057f116994aa78f
[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 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 = visible_length = 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           temp = local_len + out + 2;
377           if (temp >= line_size)
378             {
379               line_size = (temp + 1024) - (temp % 1024);
380               visible_line = xrealloc (visible_line, line_size);
381               line = invisible_line = xrealloc (invisible_line, line_size);
382             }
383           strncpy (line + out, local_prompt, local_len);
384           out += local_len;
385         }
386       line[out] = '\0';
387       wrap_offset = local_len - visible_length;
388     }
389   else
390     {
391       int pmtlen;
392       prompt_this_line = strrchr (rl_display_prompt, '\n');
393       if (!prompt_this_line)
394         prompt_this_line = rl_display_prompt;
395       else
396         {
397           prompt_this_line++;
398           if (forced_display)
399             {
400               _rl_output_some_chars (rl_display_prompt, prompt_this_line - rl_display_prompt);
401               /* Make sure we are at column zero even after a newline,
402                  regardless of the state of terminal output processing. */
403               if (prompt_this_line[-2] != '\r')
404                 cr ();
405             }
406         }
407
408       pmtlen = strlen (prompt_this_line);
409       temp = pmtlen + out + 2;
410       if (temp >= line_size)
411         {
412           line_size = (temp + 1024) - (temp % 1024);
413           visible_line = xrealloc (visible_line, line_size);
414           line = invisible_line = xrealloc (invisible_line, line_size);
415         }
416       strncpy (line + out,  prompt_this_line, pmtlen);
417       out += pmtlen;
418       line[out] = '\0';
419       wrap_offset = 0;
420     }
421
422 #define CHECK_LPOS() \
423       do { \
424         lpos++; \
425         if (lpos >= screenwidth) \
426           { \
427             inv_lbreaks[++newlines] = out; \
428             lpos = 0; \
429           } \
430       } while (0)
431
432   /* inv_lbreaks[i] is where line i starts in the buffer. */
433   inv_lbreaks[newlines = 0] = 0;
434   lpos = out - wrap_offset;
435
436   /* XXX - what if lpos is already >= screenwidth before we start drawing the
437      contents of the command line? */
438   while (lpos >= screenwidth)
439     {
440 #if 0
441       temp = ((newlines + 1) * screenwidth) - ((newlines == 0) ? wrap_offset : 0);
442 #else
443       /* XXX - possible fix from Darin Johnson <darin@acuson.com> for prompt
444          string with invisible characters that is longer than the screen
445          width. */
446       temp = ((newlines + 1) * screenwidth) + ((newlines == 0) ? wrap_offset : 0);
447 #endif
448       inv_lbreaks[++newlines] = temp;
449       lpos -= screenwidth;
450     }
451
452   lb_linenum = 0;
453   for (in = 0; in < rl_end; in++)
454     {
455       c = (unsigned char)rl_line_buffer[in];
456
457       if (out + 8 >= line_size)         /* XXX - 8 for \t */
458         {
459           line_size *= 2;
460           visible_line = xrealloc (visible_line, line_size);
461           invisible_line = xrealloc (invisible_line, line_size);
462           line = invisible_line;
463         }
464
465       if (in == rl_point)
466         {
467           c_pos = out;
468           lb_linenum = newlines;
469         }
470
471       if (META_CHAR (c))
472         {
473           if (_rl_output_meta_chars == 0)
474             {
475               sprintf (line + out, "\\%o", c);
476
477               if (lpos + 4 >= screenwidth)
478                 {
479                   temp = screenwidth - lpos;
480                   inv_lbreaks[++newlines] = out + temp;
481                   lpos = 4 - temp;
482                 }
483               else
484                 lpos += 4;
485
486               out += 4;
487             }
488           else
489             {
490               line[out++] = c;
491               CHECK_LPOS();
492             }
493         }
494 #if defined (DISPLAY_TABS)
495       else if (c == '\t')
496         {
497           register int temp, newout;
498
499 #if 0
500           newout = (out | (int)7) + 1;
501 #else
502           newout = out + 8 - lpos % 8;
503 #endif
504           temp = newout - out;
505           if (lpos + temp >= screenwidth)
506             {
507               register int temp2;
508               temp2 = screenwidth - lpos;
509               inv_lbreaks[++newlines] = out + temp2;
510               lpos = temp - temp2;
511               while (out < newout)
512                 line[out++] = ' ';
513             }
514           else
515             {
516               while (out < newout)
517                 line[out++] = ' ';
518               lpos += temp;
519             }
520         }
521 #endif
522       else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && term_up && *term_up)
523         {
524           line[out++] = '\0';   /* XXX - sentinel */
525           inv_lbreaks[++newlines] = out;
526           lpos = 0;
527         }
528       else if (CTRL_CHAR (c) || c == RUBOUT)
529         {
530           line[out++] = '^';
531           CHECK_LPOS();
532           line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
533           CHECK_LPOS();
534         }
535       else
536         {
537           line[out++] = c;
538           CHECK_LPOS();
539         }
540     }
541   line[out] = '\0';
542   if (c_pos < 0)
543     {
544       c_pos = out;
545       lb_linenum = newlines;
546     }
547
548   inv_botlin = lb_botlin = newlines;
549   inv_lbreaks[newlines+1] = out;
550   cursor_linenum = lb_linenum;
551
552   /* C_POS == position in buffer where cursor should be placed. */
553
554   /* PWP: now is when things get a bit hairy.  The visible and invisible
555      line buffers are really multiple lines, which would wrap every
556      (screenwidth - 1) characters.  Go through each in turn, finding
557      the changed region and updating it.  The line order is top to bottom. */
558
559   /* If we can move the cursor up and down, then use multiple lines,
560      otherwise, let long lines display in a single terminal line, and
561      horizontally scroll it. */
562
563   if (_rl_horizontal_scroll_mode == 0 && term_up && *term_up)
564     {
565       int nleft, pos, changed_screen_line;
566
567       if (!rl_display_fixed || forced_display)
568         {
569           forced_display = 0;
570
571           /* If we have more than a screenful of material to display, then
572              only display a screenful.  We should display the last screen,
573              not the first.  */
574           if (out >= screenchars)
575             out = screenchars - 1;
576
577           /* The first line is at character position 0 in the buffer.  The
578              second and subsequent lines start at inv_lbreaks[N], offset by
579              OFFSET (which has already been calculated above).  */
580
581 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
582 #define VIS_LLEN(l)     ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
583 #define INV_LLEN(l)     (inv_lbreaks[l+1] - inv_lbreaks[l])
584 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
585 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
586 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
587
588           /* For each line in the buffer, do the updating display. */
589           for (linenum = 0; linenum <= inv_botlin; linenum++)
590             {
591               update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
592                            VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
593
594               /* If this is the line with the prompt, we might need to
595                  compensate for invisible characters in the new line. Do
596                  this only if there is not more than one new line (which
597                  implies that we completely overwrite the old visible line)
598                  and the new line is shorter than the old.  Make sure we are
599                  at the end of the new line before clearing. */
600               if (linenum == 0 &&
601                   inv_botlin == 0 && _rl_last_c_pos == out &&
602                   (wrap_offset > visible_wrap_offset) &&
603                   (_rl_last_c_pos < visible_first_line_len))
604                 {
605                   nleft = screenwidth + wrap_offset - _rl_last_c_pos;
606                   if (nleft)
607                     _rl_clear_to_eol (nleft);
608                 }
609
610               /* Since the new first line is now visible, save its length. */
611               if (linenum == 0)
612                 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
613             }
614
615           /* We may have deleted some lines.  If so, clear the left over
616              blank ones at the bottom out. */
617           if (_rl_vis_botlin > inv_botlin)
618             {
619               char *tt;
620               for (; linenum <= _rl_vis_botlin; linenum++)
621                 {
622                   tt = VIS_CHARS (linenum);
623                   _rl_move_vert (linenum);
624                   _rl_move_cursor_relative (0, tt);
625                   _rl_clear_to_eol
626                     ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
627                 }
628             }
629           _rl_vis_botlin = inv_botlin;
630
631           /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
632              different screen line during this redisplay. */
633           changed_screen_line = _rl_last_v_pos != cursor_linenum;
634           if (changed_screen_line)
635             {
636               _rl_move_vert (cursor_linenum);
637               /* If we moved up to the line with the prompt using term_up,
638                  the physical cursor position on the screen stays the same,
639                  but the buffer position needs to be adjusted to account
640                  for invisible characters. */
641               if (cursor_linenum == 0 && wrap_offset)
642                 _rl_last_c_pos += wrap_offset;
643             }
644
645           /* We have to reprint the prompt if it contains invisible
646              characters, since it's not generally OK to just reprint
647              the characters from the current cursor position.  But we
648              only need to reprint it if the cursor is before the last
649              invisible character in the prompt string. */
650           nleft = visible_length + wrap_offset;
651           if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
652               _rl_last_c_pos <= last_invisible && local_prompt)
653             {
654               if (term_cr)
655                 tputs (term_cr, 1, _rl_output_character_function);
656               _rl_output_some_chars (local_prompt, nleft);
657               _rl_last_c_pos = nleft;
658             }
659
660           /* Where on that line?  And where does that line start
661              in the buffer? */
662           pos = inv_lbreaks[cursor_linenum];
663           /* nleft == number of characters in the line buffer between the
664              start of the line and the cursor position. */
665           nleft = c_pos - pos;
666
667           /* Since _rl_backspace() doesn't know about invisible characters in the
668              prompt, and there's no good way to tell it, we compensate for
669              those characters here and call _rl_backspace() directly. */
670           if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
671             {
672               _rl_backspace (_rl_last_c_pos - nleft);
673               _rl_last_c_pos = nleft;
674             }
675
676           if (nleft != _rl_last_c_pos)
677             _rl_move_cursor_relative (nleft, &invisible_line[pos]);
678         }
679     }
680   else                          /* Do horizontal scrolling. */
681     {
682 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
683       int lmargin, ndisp, nleft, phys_c_pos, t;
684
685       /* Always at top line. */
686       _rl_last_v_pos = 0;
687
688       /* Compute where in the buffer the displayed line should start.  This
689          will be LMARGIN. */
690
691       /* The number of characters that will be displayed before the cursor. */
692       ndisp = c_pos - wrap_offset;
693       nleft  = visible_length + wrap_offset;
694       /* Where the new cursor position will be on the screen.  This can be
695          longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
696       phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
697       t = screenwidth / 3;
698
699       /* If the number of characters had already exceeded the screenwidth,
700          last_lmargin will be > 0. */
701
702       /* If the number of characters to be displayed is more than the screen
703          width, compute the starting offset so that the cursor is about
704          two-thirds of the way across the screen. */
705       if (phys_c_pos > screenwidth - 2)
706         {
707           lmargin = c_pos - (2 * t);
708           if (lmargin < 0)
709             lmargin = 0;
710           /* If the left margin would be in the middle of a prompt with
711              invisible characters, don't display the prompt at all. */
712           if (wrap_offset && lmargin > 0 && lmargin < nleft)
713             lmargin = nleft;
714         }
715       else if (ndisp < screenwidth - 2)         /* XXX - was -1 */
716         lmargin = 0;
717       else if (phys_c_pos < 1)
718         {
719           /* If we are moving back towards the beginning of the line and
720              the last margin is no longer correct, compute a new one. */
721           lmargin = ((c_pos - 1) / t) * t;      /* XXX */
722           if (wrap_offset && lmargin > 0 && lmargin < nleft)
723             lmargin = nleft;
724         }
725       else
726         lmargin = last_lmargin;
727
728       /* If the first character on the screen isn't the first character
729          in the display line, indicate this with a special character. */
730       if (lmargin > 0)
731         line[lmargin] = '<';
732
733       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
734          the whole line, indicate that with a special character at the
735          right edge of the screen.  If LMARGIN is 0, we need to take the
736          wrap offset into account. */
737       t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
738       if (t < out)
739         line[t - 1] = '>';
740
741       if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
742         {
743           forced_display = 0;
744           update_line (&visible_line[last_lmargin],
745                        &invisible_line[lmargin],
746                        0,
747                        screenwidth + visible_wrap_offset,
748                        screenwidth + (lmargin ? 0 : wrap_offset),
749                        0);
750
751           /* If the visible new line is shorter than the old, but the number
752              of invisible characters is greater, and we are at the end of
753              the new line, we need to clear to eol. */
754           t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
755           if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
756               (_rl_last_c_pos == out) &&
757               t < visible_first_line_len)
758             {
759               nleft = screenwidth - t;
760               _rl_clear_to_eol (nleft);
761             }
762           visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
763           if (visible_first_line_len > screenwidth)
764             visible_first_line_len = screenwidth;
765
766           _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
767           last_lmargin = lmargin;
768         }
769     }
770   fflush (rl_outstream);
771
772   /* Swap visible and non-visible lines. */
773   {
774     char *temp = visible_line;
775     int *itemp = vis_lbreaks;
776     visible_line = invisible_line;
777     invisible_line = temp;
778     vis_lbreaks = inv_lbreaks;
779     inv_lbreaks = itemp;
780     rl_display_fixed = 0;
781     /* If we are displaying on a single line, and last_lmargin is > 0, we
782        are not displaying any invisible characters, so set visible_wrap_offset
783        to 0. */
784     if (_rl_horizontal_scroll_mode && last_lmargin)
785       visible_wrap_offset = 0;
786     else
787       visible_wrap_offset = wrap_offset;
788   }
789 }
790
791 /* PWP: update_line() is based on finding the middle difference of each
792    line on the screen; vis:
793
794                              /old first difference
795         /beginning of line   |        /old last same       /old EOL
796         v                    v        v             v
797 old:    eddie> Oh, my little gruntle-buggy is to me, as lurgid as
798 new:    eddie> Oh, my little buggy says to me, as lurgid as
799         ^                    ^  ^                          ^
800         \beginning of line   |  \new last same     \new end of line
801                              \new first difference
802
803    All are character pointers for the sake of speed.  Special cases for
804    no differences, as well as for end of line additions must be handled.
805
806    Could be made even smarter, but this works well enough */
807 static void
808 update_line (old, new, current_line, omax, nmax, inv_botlin)
809      register char *old, *new;
810      int current_line, omax, nmax, inv_botlin;
811 {
812   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
813   int temp, lendiff, wsatend, od, nd;
814   int current_invis_chars;
815
816   /* If we're at the right edge of a terminal that supports xn, we're
817      ready to wrap around, so do so.  This fixes problems with knowing
818      the exact cursor position and cut-and-paste with certain terminal
819      emulators.  In this calculation, TEMP is the physical screen
820      position of the cursor. */
821   temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
822   if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
823       && _rl_last_v_pos == current_line - 1)
824     {
825       if (new[0])
826         putc (new[0], rl_outstream);
827       else
828         putc (' ', rl_outstream);
829       _rl_last_c_pos = 1;               /* XXX */
830       _rl_last_v_pos++;
831       if (old[0] && new[0])
832         old[0] = new[0];
833     }
834       
835   /* Find first difference. */
836   for (ofd = old, nfd = new;
837        (ofd - old < omax) && *ofd && (*ofd == *nfd);
838        ofd++, nfd++)
839     ;
840
841   /* Move to the end of the screen line.  ND and OD are used to keep track
842      of the distance between ne and new and oe and old, respectively, to
843      move a subtraction out of each loop. */
844   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
845   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
846
847   /* If no difference, continue to next line. */
848   if (ofd == oe && nfd == ne)
849     return;
850
851   wsatend = 1;                  /* flag for trailing whitespace */
852   ols = oe - 1;                 /* find last same */
853   nls = ne - 1;
854   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
855     {
856       if (*ols != ' ')
857         wsatend = 0;
858       ols--;
859       nls--;
860     }
861
862   if (wsatend)
863     {
864       ols = oe;
865       nls = ne;
866     }
867   else if (*ols != *nls)
868     {
869       if (*ols)                 /* don't step past the NUL */
870         ols++;
871       if (*nls)
872         nls++;
873     }
874
875   /* count of invisible characters in the current invisible line. */
876   current_invis_chars = W_OFFSET (current_line, wrap_offset);
877   if (_rl_last_v_pos != current_line)
878     {
879       _rl_move_vert (current_line);
880       if (current_line == 0 && visible_wrap_offset)
881         _rl_last_c_pos += visible_wrap_offset;
882     }
883
884   /* If this is the first line and there are invisible characters in the
885      prompt string, and the prompt string has not changed, and the current
886      cursor position is before the last invisible character in the prompt,
887      and the index of the character to move to is past the end of the prompt
888      string, then redraw the entire prompt string.  We can only do this
889      reliably if the terminal supports a `cr' capability.
890
891      This is not an efficiency hack -- there is a problem with redrawing
892      portions of the prompt string if they contain terminal escape
893      sequences (like drawing the `unbold' sequence without a corresponding
894      `bold') that manifests itself on certain terminals. */
895
896   lendiff = local_prompt ? strlen (local_prompt) : 0;
897   od = ofd - old;       /* index of first difference in visible line */
898   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
899       term_cr && lendiff > visible_length && _rl_last_c_pos > 0 &&
900       od > lendiff && _rl_last_c_pos < last_invisible)
901     {
902       tputs (term_cr, 1, _rl_output_character_function);
903       _rl_output_some_chars (local_prompt, lendiff);
904       _rl_last_c_pos = lendiff;
905     }
906
907   _rl_move_cursor_relative (od, old);
908
909   /* if (len (new) > len (old)) */
910   lendiff = (nls - nfd) - (ols - ofd);
911
912   /* If we are changing the number of invisible characters in a line, and
913      the spot of first difference is before the end of the invisible chars,
914      lendiff needs to be adjusted. */
915   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
916       current_invis_chars != visible_wrap_offset)
917     lendiff += visible_wrap_offset - current_invis_chars;
918
919   /* Insert (diff (len (old), len (new)) ch. */
920   temp = ne - nfd;
921   if (lendiff > 0)
922     {
923       /* Non-zero if we're increasing the number of lines. */
924       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
925       /* Sometimes it is cheaper to print the characters rather than
926          use the terminal's capabilities.  If we're growing the number
927          of lines, make sure we actually cause the new line to wrap
928          around on auto-wrapping terminals. */
929       if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl))
930         {
931           /* If lendiff > visible_length and _rl_last_c_pos == 0 and
932              _rl_horizontal_scroll_mode == 1, inserting the characters with
933              term_IC or term_ic will screw up the screen because of the
934              invisible characters.  We need to just draw them. */
935           if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
936                         lendiff <= visible_length || !current_invis_chars))
937             {
938               insert_some_chars (nfd, lendiff);
939               _rl_last_c_pos += lendiff;
940             }
941           else if (*ols == 0)
942             {
943               /* At the end of a line the characters do not have to
944                  be "inserted".  They can just be placed on the screen. */
945               /* However, this screws up the rest of this block, which
946                  assumes you've done the insert because you can. */
947               _rl_output_some_chars (nfd, lendiff);
948               _rl_last_c_pos += lendiff;
949             }
950           else
951             {
952               /* We have horizontal scrolling and we are not inserting at
953                  the end.  We have invisible characters in this line.  This
954                  is a dumb update. */
955               _rl_output_some_chars (nfd, temp);
956               _rl_last_c_pos += temp;
957               return;
958             }
959           /* Copy (new) chars to screen from first diff to last match. */
960           temp = nls - nfd;
961           if ((temp - lendiff) > 0)
962             {
963               _rl_output_some_chars (nfd + lendiff, temp - lendiff);
964               _rl_last_c_pos += temp - lendiff;
965             }
966         }
967       else
968         {
969           /* cannot insert chars, write to EOL */
970           _rl_output_some_chars (nfd, temp);
971           _rl_last_c_pos += temp;
972         }
973     }
974   else                          /* Delete characters from line. */
975     {
976       /* If possible and inexpensive to use terminal deletion, then do so. */
977       if (term_dc && (2 * temp) >= -lendiff)
978         {
979           /* If all we're doing is erasing the invisible characters in the
980              prompt string, don't bother.  It screws up the assumptions
981              about what's on the screen. */
982           if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
983               -lendiff == visible_wrap_offset)
984             lendiff = 0;
985
986           if (lendiff)
987             delete_chars (-lendiff); /* delete (diff) characters */
988
989           /* Copy (new) chars to screen from first diff to last match */
990           temp = nls - nfd;
991           if (temp > 0)
992             {
993               _rl_output_some_chars (nfd, temp);
994               _rl_last_c_pos += temp;
995             }
996         }
997       /* Otherwise, print over the existing material. */
998       else
999         {
1000           if (temp > 0)
1001             {
1002               _rl_output_some_chars (nfd, temp);
1003               _rl_last_c_pos += temp;
1004             }
1005           lendiff = (oe - old) - (ne - new);
1006           if (lendiff)
1007             {     
1008               if (_rl_term_autowrap && current_line < inv_botlin)
1009                 space_to_eol (lendiff);
1010               else
1011                 _rl_clear_to_eol (lendiff);
1012             }
1013         }
1014     }
1015 }
1016
1017 /* Tell the update routines that we have moved onto a new (empty) line. */
1018 int
1019 rl_on_new_line ()
1020 {
1021   if (visible_line)
1022     visible_line[0] = '\0';
1023
1024   _rl_last_c_pos = _rl_last_v_pos = 0;
1025   _rl_vis_botlin = last_lmargin = 0;
1026   if (vis_lbreaks)
1027     vis_lbreaks[0] = vis_lbreaks[1] = 0;
1028   visible_wrap_offset = 0;
1029   return 0;
1030 }
1031
1032 /* Actually update the display, period. */
1033 int
1034 rl_forced_update_display ()
1035 {
1036   if (visible_line)
1037     {
1038       register char *temp = visible_line;
1039
1040       while (*temp)
1041         *temp++ = '\0';
1042     }
1043   rl_on_new_line ();
1044   forced_display++;
1045   (*rl_redisplay_function) ();
1046   return 0;
1047 }
1048
1049 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1050    DATA is the contents of the screen line of interest; i.e., where
1051    the movement is being done. */
1052 void
1053 _rl_move_cursor_relative (new, data)
1054      int new;
1055      char *data;
1056 {
1057   register int i;
1058
1059   /* If we don't have to do anything, then return. */
1060   if (_rl_last_c_pos == new) return;
1061
1062   /* It may be faster to output a CR, and then move forwards instead
1063      of moving backwards. */
1064   /* i == current physical cursor position. */
1065   i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1066   if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
1067       (_rl_term_autowrap && i == screenwidth))
1068     {
1069 #if defined (__MSDOS__)
1070       putc ('\r', rl_outstream);
1071 #else
1072       tputs (term_cr, 1, _rl_output_character_function);
1073 #endif /* !__MSDOS__ */
1074       _rl_last_c_pos = 0;
1075     }
1076
1077   if (_rl_last_c_pos < new)
1078     {
1079       /* Move the cursor forward.  We do it by printing the command
1080          to move the cursor forward if there is one, else print that
1081          portion of the output buffer again.  Which is cheaper? */
1082
1083       /* The above comment is left here for posterity.  It is faster
1084          to print one character (non-control) than to print a control
1085          sequence telling the terminal to move forward one character.
1086          That kind of control is for people who don't know what the
1087          data is underneath the cursor. */
1088 #if defined (HACK_TERMCAP_MOTION)
1089       extern char *term_forward_char;
1090
1091       if (term_forward_char)
1092         for (i = _rl_last_c_pos; i < new; i++)
1093           tputs (term_forward_char, 1, _rl_output_character_function);
1094       else
1095         for (i = _rl_last_c_pos; i < new; i++)
1096           putc (data[i], rl_outstream);
1097 #else
1098       for (i = _rl_last_c_pos; i < new; i++)
1099         putc (data[i], rl_outstream);
1100 #endif /* HACK_TERMCAP_MOTION */
1101     }
1102   else if (_rl_last_c_pos > new)
1103     _rl_backspace (_rl_last_c_pos - new);
1104   _rl_last_c_pos = new;
1105 }
1106
1107 /* PWP: move the cursor up or down. */
1108 void
1109 _rl_move_vert (to)
1110      int to;
1111 {
1112   register int delta, i;
1113
1114   if (_rl_last_v_pos == to || to > screenheight)
1115     return;
1116
1117 #if defined (__GO32__)
1118   {
1119     int row, col;
1120
1121     ScreenGetCursor (&row, &col);
1122     ScreenSetCursor ((row + to - _rl_last_v_pos), col);
1123   }
1124 #else /* !__GO32__ */
1125
1126   if ((delta = to - _rl_last_v_pos) > 0)
1127     {
1128       for (i = 0; i < delta; i++)
1129         putc ('\n', rl_outstream);
1130       tputs (term_cr, 1, _rl_output_character_function);
1131       _rl_last_c_pos = 0;
1132     }
1133   else
1134     {                   /* delta < 0 */
1135       if (term_up && *term_up)
1136         for (i = 0; i < -delta; i++)
1137           tputs (term_up, 1, _rl_output_character_function);
1138     }
1139 #endif /* !__GO32__ */
1140   _rl_last_v_pos = to;          /* Now TO is here */
1141 }
1142
1143 /* Physically print C on rl_outstream.  This is for functions which know
1144    how to optimize the display.  Return the number of characters output. */
1145 int
1146 rl_show_char (c)
1147      int c;
1148 {
1149   int n = 1;
1150   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
1151     {
1152       fprintf (rl_outstream, "M-");
1153       n += 2;
1154       c = UNMETA (c);
1155     }
1156
1157 #if defined (DISPLAY_TABS)
1158   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
1159 #else
1160   if (CTRL_CHAR (c) || c == RUBOUT)
1161 #endif /* !DISPLAY_TABS */
1162     {
1163       fprintf (rl_outstream, "C-");
1164       n += 2;
1165       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1166     }
1167
1168   putc (c, rl_outstream);
1169   fflush (rl_outstream);
1170   return n;
1171 }
1172
1173 int
1174 rl_character_len (c, pos)
1175      register int c, pos;
1176 {
1177   unsigned char uc;
1178
1179   uc = (unsigned char)c;
1180
1181   if (META_CHAR (uc))
1182     return ((_rl_output_meta_chars == 0) ? 4 : 1);
1183
1184   if (uc == '\t')
1185     {
1186 #if defined (DISPLAY_TABS)
1187       return (((pos | 7) + 1) - pos);
1188 #else
1189       return (2);
1190 #endif /* !DISPLAY_TABS */
1191     }
1192
1193   if (CTRL_CHAR (c) || c == RUBOUT)
1194     return (2);
1195
1196   return ((isprint (uc)) ? 1 : 2);
1197 }
1198
1199 /* How to print things in the "echo-area".  The prompt is treated as a
1200    mini-modeline. */
1201
1202 #if defined (USE_VARARGS)
1203 int
1204 #if defined (PREFER_STDARG)
1205 rl_message (const char *format, ...)
1206 #else
1207 rl_message (va_alist)
1208      va_dcl
1209 #endif
1210 {
1211   va_list args;
1212 #if defined (PREFER_VARARGS)
1213   char *format;
1214 #endif
1215
1216 #if defined (PREFER_STDARG)
1217   va_start (args, format);
1218 #else
1219   va_start (args);
1220   format = va_arg (args, char *);
1221 #endif
1222
1223   vsprintf (msg_buf, format, args);
1224   va_end (args);
1225
1226   rl_display_prompt = msg_buf;
1227   (*rl_redisplay_function) ();
1228   return 0;
1229 }
1230 #else /* !USE_VARARGS */
1231 int
1232 rl_message (format, arg1, arg2)
1233      char *format;
1234 {
1235   sprintf (msg_buf, format, arg1, arg2);
1236   rl_display_prompt = msg_buf;
1237   (*rl_redisplay_function) ();
1238   return 0;
1239 }
1240 #endif /* !USE_VARARGS */
1241
1242 /* How to clear things from the "echo-area". */
1243 int
1244 rl_clear_message ()
1245 {
1246   rl_display_prompt = rl_prompt;
1247   (*rl_redisplay_function) ();
1248   return 0;
1249 }
1250
1251 int
1252 rl_reset_line_state ()
1253 {
1254   rl_on_new_line ();
1255
1256   rl_display_prompt = rl_prompt ? rl_prompt : "";
1257   forced_display = 1;
1258   return 0;
1259 }
1260
1261 static char *saved_local_prompt;
1262 static char *saved_local_prefix;
1263 static int saved_last_invisible;
1264 static int saved_visible_length;
1265
1266 void
1267 rl_save_prompt ()
1268 {
1269   saved_local_prompt = local_prompt;
1270   saved_local_prefix = local_prompt_prefix;
1271   saved_last_invisible = last_invisible;
1272   saved_visible_length = visible_length;
1273
1274   local_prompt = local_prompt_prefix = (char *)0;
1275   last_invisible = visible_length = 0;
1276 }
1277
1278 void
1279 rl_restore_prompt ()
1280 {
1281   if (local_prompt)
1282     free (local_prompt);
1283   if (local_prompt_prefix)
1284     free (local_prompt_prefix);
1285
1286   local_prompt = saved_local_prompt;
1287   local_prompt_prefix = saved_local_prefix;
1288   last_invisible = saved_last_invisible;
1289   visible_length = saved_visible_length;
1290 }
1291
1292 char *
1293 _rl_make_prompt_for_search (pchar)
1294      int pchar;
1295 {
1296   int len;
1297   char *pmt;
1298
1299   rl_save_prompt ();
1300
1301   if (saved_local_prompt == 0)
1302     {
1303       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
1304       pmt = xmalloc (len + 2);
1305       if (len)
1306         strcpy (pmt, rl_prompt);
1307       pmt[len] = pchar;
1308       pmt[len+1] = '\0';
1309     }
1310   else
1311     {
1312       len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
1313       pmt = xmalloc (len + 2);
1314       if (len)
1315         strcpy (pmt, saved_local_prompt);
1316       pmt[len] = pchar;
1317       pmt[len+1] = '\0';
1318       local_prompt = savestring (pmt);
1319       last_invisible = saved_last_invisible;
1320       visible_length = saved_visible_length + 1;
1321     }
1322   return pmt;
1323 }
1324
1325 /* Quick redisplay hack when erasing characters at the end of the line. */
1326 void
1327 _rl_erase_at_end_of_line (l)
1328      int l;
1329 {
1330   register int i;
1331
1332   _rl_backspace (l);
1333   for (i = 0; i < l; i++)
1334     putc (' ', rl_outstream);
1335   _rl_backspace (l);
1336   for (i = 0; i < l; i++)
1337     visible_line[--_rl_last_c_pos] = '\0';
1338   rl_display_fixed++;
1339 }
1340
1341 /* Clear to the end of the line.  COUNT is the minimum
1342    number of character spaces to clear, */
1343 void
1344 _rl_clear_to_eol (count)
1345      int count;
1346 {
1347 #if !defined (__GO32__)
1348   if (term_clreol)
1349     tputs (term_clreol, 1, _rl_output_character_function);
1350   else if (count)
1351 #endif /* !__GO32__ */
1352     space_to_eol (count);
1353 }
1354
1355 /* Clear to the end of the line using spaces.  COUNT is the minimum
1356    number of character spaces to clear, */
1357 static void
1358 space_to_eol (count)
1359      int count;
1360 {
1361   register int i;
1362
1363   for (i = 0; i < count; i++)
1364    putc (' ', rl_outstream);
1365
1366   _rl_last_c_pos += count;
1367 }
1368
1369 void
1370 _rl_clear_screen ()
1371 {
1372 #if !defined (__GO32__)
1373   if (term_clrpag)
1374     tputs (term_clrpag, 1, _rl_output_character_function);
1375   else
1376 #endif /* !__GO32__ */
1377     crlf ();
1378 }
1379
1380 /* Insert COUNT characters from STRING to the output stream. */
1381 static void
1382 insert_some_chars (string, count)
1383      char *string;
1384      int count;
1385 {
1386 #if defined (__GO32__)
1387   int row, col, width;
1388   char *row_start;
1389
1390   ScreenGetCursor (&row, &col);
1391   width = ScreenCols ();
1392   row_start = ScreenPrimary + (row * width);
1393
1394   memcpy (row_start + col + count, row_start + col, width - col - count);
1395
1396   /* Place the text on the screen. */
1397   _rl_output_some_chars (string, count);
1398 #else /* !_GO32 */
1399
1400   /* If IC is defined, then we do not have to "enter" insert mode. */
1401   if (term_IC)
1402     {
1403       char *buffer;
1404       buffer = tgoto (term_IC, 0, count);
1405       tputs (buffer, 1, _rl_output_character_function);
1406       _rl_output_some_chars (string, count);
1407     }
1408   else
1409     {
1410       register int i;
1411
1412       /* If we have to turn on insert-mode, then do so. */
1413       if (term_im && *term_im)
1414         tputs (term_im, 1, _rl_output_character_function);
1415
1416       /* If there is a special command for inserting characters, then
1417          use that first to open up the space. */
1418       if (term_ic && *term_ic)
1419         {
1420           for (i = count; i--; )
1421             tputs (term_ic, 1, _rl_output_character_function);
1422         }
1423
1424       /* Print the text. */
1425       _rl_output_some_chars (string, count);
1426
1427       /* If there is a string to turn off insert mode, we had best use
1428          it now. */
1429       if (term_ei && *term_ei)
1430         tputs (term_ei, 1, _rl_output_character_function);
1431     }
1432 #endif /* !__GO32__ */
1433 }
1434
1435 /* Delete COUNT characters from the display line. */
1436 static void
1437 delete_chars (count)
1438      int count;
1439 {
1440 #if defined (__GO32__)
1441   int row, col, width;
1442   char *row_start;
1443
1444   ScreenGetCursor (&row, &col);
1445   width = ScreenCols ();
1446   row_start = ScreenPrimary + (row * width);
1447
1448   memcpy (row_start + col, row_start + col + count, width - col - count);
1449   memset (row_start + width - count, 0, count * 2);
1450 #else /* !_GO32 */
1451
1452   if (count > screenwidth)      /* XXX */
1453     return;
1454
1455   if (term_DC && *term_DC)
1456     {
1457       char *buffer;
1458       buffer = tgoto (term_DC, count, count);
1459       tputs (buffer, count, _rl_output_character_function);
1460     }
1461   else
1462     {
1463       if (term_dc && *term_dc)
1464         while (count--)
1465           tputs (term_dc, 1, _rl_output_character_function);
1466     }
1467 #endif /* !__GO32__ */
1468 }
1469
1470 void
1471 _rl_update_final ()
1472 {
1473   int full_lines;
1474
1475   full_lines = 0;
1476   /* If the cursor is the only thing on an otherwise-blank last line,
1477      compensate so we don't print an extra CRLF. */
1478   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
1479         visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
1480     {
1481       _rl_vis_botlin--;
1482       full_lines = 1;
1483     }
1484   _rl_move_vert (_rl_vis_botlin);
1485   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
1486   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == screenwidth))
1487     {
1488       char *last_line;
1489       last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
1490       _rl_move_cursor_relative (screenwidth - 1, last_line);
1491       _rl_clear_to_eol (0);
1492       putc (last_line[screenwidth - 1], rl_outstream);
1493     }
1494   _rl_vis_botlin = 0;
1495   crlf ();
1496   fflush (rl_outstream);
1497   rl_display_fixed++;
1498 }
1499
1500 /* Move to the start of the current line. */
1501 static void
1502 cr ()
1503 {
1504   if (term_cr)
1505     {
1506       tputs (term_cr, 1, _rl_output_character_function);
1507       _rl_last_c_pos = 0;
1508     }
1509 }
1510
1511 /* Redisplay the current line after a SIGWINCH is received. */
1512 void
1513 _rl_redisplay_after_sigwinch ()
1514 {
1515   char *t, *oldp, *oldl, *oldlprefix;
1516
1517   /* Clear the current line and put the cursor at column 0.  Make sure
1518      the right thing happens if we have wrapped to a new screen line. */
1519   if (term_cr)
1520     {
1521       tputs (term_cr, 1, _rl_output_character_function);
1522       _rl_last_c_pos = 0;
1523       if (term_clreol)
1524         tputs (term_clreol, 1, _rl_output_character_function);
1525       else
1526         {
1527           space_to_eol (screenwidth);
1528           tputs (term_cr, 1, _rl_output_character_function);
1529         }
1530       if (_rl_last_v_pos > 0)
1531         _rl_move_vert (0);
1532     }
1533   else
1534     crlf ();
1535
1536   /* Redraw only the last line of a multi-line prompt. */
1537   t = strrchr (rl_display_prompt, '\n');
1538   if (t)
1539     {
1540       oldp = rl_display_prompt;
1541       oldl = local_prompt;
1542       oldlprefix = local_prompt_prefix;
1543       rl_display_prompt = ++t;
1544       local_prompt = local_prompt_prefix = (char *)NULL;
1545       rl_forced_update_display ();
1546       rl_display_prompt = oldp;
1547       local_prompt = oldl;
1548       local_prompt_prefix = oldlprefix;
1549     }
1550   else
1551     rl_forced_update_display ();
1552 }
1553
1554 void
1555 _rl_clean_up_for_exit ()
1556 {
1557   if (readline_echoing_p)
1558     {
1559       _rl_move_vert (_rl_vis_botlin);
1560       _rl_vis_botlin = 0;
1561       fflush (rl_outstream);
1562       rl_restart_output (1, 0);
1563     }
1564 }
1565
1566 void
1567 _rl_erase_entire_line ()
1568 {
1569   cr ();
1570   _rl_clear_to_eol (0);
1571   cr ();
1572   fflush (rl_outstream);
1573 }