This commit was generated by cvs2svn to track changes on a CVS vendor
[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 = 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 defined (__MSDOS__)
655               putc ('\r', rl_outstream);
656 #else
657               if (term_cr)
658                 tputs (term_cr, 1, _rl_output_character_function);
659 #endif
660               _rl_output_some_chars (local_prompt, nleft);
661               _rl_last_c_pos = nleft;
662             }
663
664           /* Where on that line?  And where does that line start
665              in the buffer? */
666           pos = inv_lbreaks[cursor_linenum];
667           /* nleft == number of characters in the line buffer between the
668              start of the line and the cursor position. */
669           nleft = c_pos - pos;
670
671           /* Since _rl_backspace() doesn't know about invisible characters in the
672              prompt, and there's no good way to tell it, we compensate for
673              those characters here and call _rl_backspace() directly. */
674           if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
675             {
676               _rl_backspace (_rl_last_c_pos - nleft);
677               _rl_last_c_pos = nleft;
678             }
679
680           if (nleft != _rl_last_c_pos)
681             _rl_move_cursor_relative (nleft, &invisible_line[pos]);
682         }
683     }
684   else                          /* Do horizontal scrolling. */
685     {
686 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
687       int lmargin, ndisp, nleft, phys_c_pos, t;
688
689       /* Always at top line. */
690       _rl_last_v_pos = 0;
691
692       /* Compute where in the buffer the displayed line should start.  This
693          will be LMARGIN. */
694
695       /* The number of characters that will be displayed before the cursor. */
696       ndisp = c_pos - wrap_offset;
697       nleft  = visible_length + wrap_offset;
698       /* Where the new cursor position will be on the screen.  This can be
699          longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
700       phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
701       t = screenwidth / 3;
702
703       /* If the number of characters had already exceeded the screenwidth,
704          last_lmargin will be > 0. */
705
706       /* If the number of characters to be displayed is more than the screen
707          width, compute the starting offset so that the cursor is about
708          two-thirds of the way across the screen. */
709       if (phys_c_pos > screenwidth - 2)
710         {
711           lmargin = c_pos - (2 * t);
712           if (lmargin < 0)
713             lmargin = 0;
714           /* If the left margin would be in the middle of a prompt with
715              invisible characters, don't display the prompt at all. */
716           if (wrap_offset && lmargin > 0 && lmargin < nleft)
717             lmargin = nleft;
718         }
719       else if (ndisp < screenwidth - 2)         /* XXX - was -1 */
720         lmargin = 0;
721       else if (phys_c_pos < 1)
722         {
723           /* If we are moving back towards the beginning of the line and
724              the last margin is no longer correct, compute a new one. */
725           lmargin = ((c_pos - 1) / t) * t;      /* XXX */
726           if (wrap_offset && lmargin > 0 && lmargin < nleft)
727             lmargin = nleft;
728         }
729       else
730         lmargin = last_lmargin;
731
732       /* If the first character on the screen isn't the first character
733          in the display line, indicate this with a special character. */
734       if (lmargin > 0)
735         line[lmargin] = '<';
736
737       /* If SCREENWIDTH characters starting at LMARGIN do not encompass
738          the whole line, indicate that with a special character at the
739          right edge of the screen.  If LMARGIN is 0, we need to take the
740          wrap offset into account. */
741       t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth;
742       if (t < out)
743         line[t - 1] = '>';
744
745       if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
746         {
747           forced_display = 0;
748           update_line (&visible_line[last_lmargin],
749                        &invisible_line[lmargin],
750                        0,
751                        screenwidth + visible_wrap_offset,
752                        screenwidth + (lmargin ? 0 : wrap_offset),
753                        0);
754
755           /* If the visible new line is shorter than the old, but the number
756              of invisible characters is greater, and we are at the end of
757              the new line, we need to clear to eol. */
758           t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
759           if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
760               (_rl_last_c_pos == out) &&
761               t < visible_first_line_len)
762             {
763               nleft = screenwidth - t;
764               _rl_clear_to_eol (nleft);
765             }
766           visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
767           if (visible_first_line_len > screenwidth)
768             visible_first_line_len = screenwidth;
769
770           _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
771           last_lmargin = lmargin;
772         }
773     }
774   fflush (rl_outstream);
775
776   /* Swap visible and non-visible lines. */
777   {
778     char *temp = visible_line;
779     int *itemp = vis_lbreaks;
780     visible_line = invisible_line;
781     invisible_line = temp;
782     vis_lbreaks = inv_lbreaks;
783     inv_lbreaks = itemp;
784     rl_display_fixed = 0;
785     /* If we are displaying on a single line, and last_lmargin is > 0, we
786        are not displaying any invisible characters, so set visible_wrap_offset
787        to 0. */
788     if (_rl_horizontal_scroll_mode && last_lmargin)
789       visible_wrap_offset = 0;
790     else
791       visible_wrap_offset = wrap_offset;
792   }
793 }
794
795 /* PWP: update_line() is based on finding the middle difference of each
796    line on the screen; vis:
797
798                              /old first difference
799         /beginning of line   |        /old last same       /old EOL
800         v                    v        v             v
801 old:    eddie> Oh, my little gruntle-buggy is to me, as lurgid as
802 new:    eddie> Oh, my little buggy says to me, as lurgid as
803         ^                    ^  ^                          ^
804         \beginning of line   |  \new last same     \new end of line
805                              \new first difference
806
807    All are character pointers for the sake of speed.  Special cases for
808    no differences, as well as for end of line additions must be handled.
809
810    Could be made even smarter, but this works well enough */
811 static void
812 update_line (old, new, current_line, omax, nmax, inv_botlin)
813      register char *old, *new;
814      int current_line, omax, nmax, inv_botlin;
815 {
816   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
817   int temp, lendiff, wsatend, od, nd;
818   int current_invis_chars;
819
820   /* If we're at the right edge of a terminal that supports xn, we're
821      ready to wrap around, so do so.  This fixes problems with knowing
822      the exact cursor position and cut-and-paste with certain terminal
823      emulators.  In this calculation, TEMP is the physical screen
824      position of the cursor. */
825   temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
826   if (temp == screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
827       && _rl_last_v_pos == current_line - 1)
828     {
829       if (new[0])
830         putc (new[0], rl_outstream);
831       else
832         putc (' ', rl_outstream);
833       _rl_last_c_pos = 1;               /* XXX */
834       _rl_last_v_pos++;
835       if (old[0] && new[0])
836         old[0] = new[0];
837     }
838       
839   /* Find first difference. */
840   for (ofd = old, nfd = new;
841        (ofd - old < omax) && *ofd && (*ofd == *nfd);
842        ofd++, nfd++)
843     ;
844
845   /* Move to the end of the screen line.  ND and OD are used to keep track
846      of the distance between ne and new and oe and old, respectively, to
847      move a subtraction out of each loop. */
848   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
849   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
850
851   /* If no difference, continue to next line. */
852   if (ofd == oe && nfd == ne)
853     return;
854
855   wsatend = 1;                  /* flag for trailing whitespace */
856   ols = oe - 1;                 /* find last same */
857   nls = ne - 1;
858   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
859     {
860       if (*ols != ' ')
861         wsatend = 0;
862       ols--;
863       nls--;
864     }
865
866   if (wsatend)
867     {
868       ols = oe;
869       nls = ne;
870     }
871   else if (*ols != *nls)
872     {
873       if (*ols)                 /* don't step past the NUL */
874         ols++;
875       if (*nls)
876         nls++;
877     }
878
879   /* count of invisible characters in the current invisible line. */
880   current_invis_chars = W_OFFSET (current_line, wrap_offset);
881   if (_rl_last_v_pos != current_line)
882     {
883       _rl_move_vert (current_line);
884       if (current_line == 0 && visible_wrap_offset)
885         _rl_last_c_pos += visible_wrap_offset;
886     }
887
888   /* If this is the first line and there are invisible characters in the
889      prompt string, and the prompt string has not changed, and the current
890      cursor position is before the last invisible character in the prompt,
891      and the index of the character to move to is past the end of the prompt
892      string, then redraw the entire prompt string.  We can only do this
893      reliably if the terminal supports a `cr' capability.
894
895      This is not an efficiency hack -- there is a problem with redrawing
896      portions of the prompt string if they contain terminal escape
897      sequences (like drawing the `unbold' sequence without a corresponding
898      `bold') that manifests itself on certain terminals. */
899
900   lendiff = local_prompt ? strlen (local_prompt) : 0;
901   od = ofd - old;       /* index of first difference in visible line */
902   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
903       term_cr && lendiff > visible_length && _rl_last_c_pos > 0 &&
904       od > lendiff && _rl_last_c_pos < last_invisible)
905     {
906 #if defined (__MSDOS__)
907       putc ('\r', rl_outstream);
908 #else
909       tputs (term_cr, 1, _rl_output_character_function);
910 #endif /* !__MSDOS__ */
911       _rl_output_some_chars (local_prompt, lendiff);
912       _rl_last_c_pos = lendiff;
913     }
914
915   _rl_move_cursor_relative (od, old);
916
917   /* if (len (new) > len (old)) */
918   lendiff = (nls - nfd) - (ols - ofd);
919
920   /* If we are changing the number of invisible characters in a line, and
921      the spot of first difference is before the end of the invisible chars,
922      lendiff needs to be adjusted. */
923   if (current_line == 0 && !_rl_horizontal_scroll_mode &&
924       current_invis_chars != visible_wrap_offset)
925     lendiff += visible_wrap_offset - current_invis_chars;
926
927   /* Insert (diff (len (old), len (new)) ch. */
928   temp = ne - nfd;
929   if (lendiff > 0)
930     {
931       /* Non-zero if we're increasing the number of lines. */
932       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
933       /* Sometimes it is cheaper to print the characters rather than
934          use the terminal's capabilities.  If we're growing the number
935          of lines, make sure we actually cause the new line to wrap
936          around on auto-wrapping terminals. */
937       if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!_rl_term_autowrap || !gl))
938         {
939           /* If lendiff > visible_length and _rl_last_c_pos == 0 and
940              _rl_horizontal_scroll_mode == 1, inserting the characters with
941              term_IC or term_ic will screw up the screen because of the
942              invisible characters.  We need to just draw them. */
943           if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
944                         lendiff <= visible_length || !current_invis_chars))
945             {
946               insert_some_chars (nfd, lendiff);
947               _rl_last_c_pos += lendiff;
948             }
949           else if (*ols == 0)
950             {
951               /* At the end of a line the characters do not have to
952                  be "inserted".  They can just be placed on the screen. */
953               /* However, this screws up the rest of this block, which
954                  assumes you've done the insert because you can. */
955               _rl_output_some_chars (nfd, lendiff);
956               _rl_last_c_pos += lendiff;
957             }
958           else
959             {
960               /* We have horizontal scrolling and we are not inserting at
961                  the end.  We have invisible characters in this line.  This
962                  is a dumb update. */
963               _rl_output_some_chars (nfd, temp);
964               _rl_last_c_pos += temp;
965               return;
966             }
967           /* Copy (new) chars to screen from first diff to last match. */
968           temp = nls - nfd;
969           if ((temp - lendiff) > 0)
970             {
971               _rl_output_some_chars (nfd + lendiff, temp - lendiff);
972               _rl_last_c_pos += temp - lendiff;
973             }
974         }
975       else
976         {
977           /* cannot insert chars, write to EOL */
978           _rl_output_some_chars (nfd, temp);
979           _rl_last_c_pos += temp;
980         }
981     }
982   else                          /* Delete characters from line. */
983     {
984       /* If possible and inexpensive to use terminal deletion, then do so. */
985       if (term_dc && (2 * temp) >= -lendiff)
986         {
987           /* If all we're doing is erasing the invisible characters in the
988              prompt string, don't bother.  It screws up the assumptions
989              about what's on the screen. */
990           if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
991               -lendiff == visible_wrap_offset)
992             lendiff = 0;
993
994           if (lendiff)
995             delete_chars (-lendiff); /* delete (diff) characters */
996
997           /* Copy (new) chars to screen from first diff to last match */
998           temp = nls - nfd;
999           if (temp > 0)
1000             {
1001               _rl_output_some_chars (nfd, temp);
1002               _rl_last_c_pos += temp;
1003             }
1004         }
1005       /* Otherwise, print over the existing material. */
1006       else
1007         {
1008           if (temp > 0)
1009             {
1010               _rl_output_some_chars (nfd, temp);
1011               _rl_last_c_pos += temp;
1012             }
1013           lendiff = (oe - old) - (ne - new);
1014           if (lendiff)
1015             {     
1016               if (_rl_term_autowrap && current_line < inv_botlin)
1017                 space_to_eol (lendiff);
1018               else
1019                 _rl_clear_to_eol (lendiff);
1020             }
1021         }
1022     }
1023 }
1024
1025 /* Tell the update routines that we have moved onto a new (empty) line. */
1026 int
1027 rl_on_new_line ()
1028 {
1029   if (visible_line)
1030     visible_line[0] = '\0';
1031
1032   _rl_last_c_pos = _rl_last_v_pos = 0;
1033   _rl_vis_botlin = last_lmargin = 0;
1034   if (vis_lbreaks)
1035     vis_lbreaks[0] = vis_lbreaks[1] = 0;
1036   visible_wrap_offset = 0;
1037   return 0;
1038 }
1039
1040 /* Actually update the display, period. */
1041 int
1042 rl_forced_update_display ()
1043 {
1044   if (visible_line)
1045     {
1046       register char *temp = visible_line;
1047
1048       while (*temp)
1049         *temp++ = '\0';
1050     }
1051   rl_on_new_line ();
1052   forced_display++;
1053   (*rl_redisplay_function) ();
1054   return 0;
1055 }
1056
1057 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1058    DATA is the contents of the screen line of interest; i.e., where
1059    the movement is being done. */
1060 void
1061 _rl_move_cursor_relative (new, data)
1062      int new;
1063      char *data;
1064 {
1065   register int i;
1066
1067   /* If we don't have to do anything, then return. */
1068   if (_rl_last_c_pos == new) return;
1069
1070   /* It may be faster to output a CR, and then move forwards instead
1071      of moving backwards. */
1072   /* i == current physical cursor position. */
1073   i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
1074   if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
1075       (_rl_term_autowrap && i == screenwidth))
1076     {
1077 #if defined (__MSDOS__)
1078       putc ('\r', rl_outstream);
1079 #else
1080       tputs (term_cr, 1, _rl_output_character_function);
1081 #endif /* !__MSDOS__ */
1082       _rl_last_c_pos = 0;
1083     }
1084
1085   if (_rl_last_c_pos < new)
1086     {
1087       /* Move the cursor forward.  We do it by printing the command
1088          to move the cursor forward if there is one, else print that
1089          portion of the output buffer again.  Which is cheaper? */
1090
1091       /* The above comment is left here for posterity.  It is faster
1092          to print one character (non-control) than to print a control
1093          sequence telling the terminal to move forward one character.
1094          That kind of control is for people who don't know what the
1095          data is underneath the cursor. */
1096 #if defined (HACK_TERMCAP_MOTION)
1097       extern char *term_forward_char;
1098
1099       if (term_forward_char)
1100         for (i = _rl_last_c_pos; i < new; i++)
1101           tputs (term_forward_char, 1, _rl_output_character_function);
1102       else
1103         for (i = _rl_last_c_pos; i < new; i++)
1104           putc (data[i], rl_outstream);
1105 #else
1106       for (i = _rl_last_c_pos; i < new; i++)
1107         putc (data[i], rl_outstream);
1108 #endif /* HACK_TERMCAP_MOTION */
1109     }
1110   else if (_rl_last_c_pos > new)
1111     _rl_backspace (_rl_last_c_pos - new);
1112   _rl_last_c_pos = new;
1113 }
1114
1115 /* PWP: move the cursor up or down. */
1116 void
1117 _rl_move_vert (to)
1118      int to;
1119 {
1120   register int delta, i;
1121
1122   if (_rl_last_v_pos == to || to > screenheight)
1123     return;
1124
1125 #if defined (__GO32__)
1126   {
1127     int row, col;
1128
1129     ScreenGetCursor (&row, &col);
1130     ScreenSetCursor ((row + to - _rl_last_v_pos), col);
1131   }
1132 #else /* !__GO32__ */
1133
1134   if ((delta = to - _rl_last_v_pos) > 0)
1135     {
1136       for (i = 0; i < delta; i++)
1137         putc ('\n', rl_outstream);
1138       tputs (term_cr, 1, _rl_output_character_function);
1139       _rl_last_c_pos = 0;
1140     }
1141   else
1142     {                   /* delta < 0 */
1143       if (term_up && *term_up)
1144         for (i = 0; i < -delta; i++)
1145           tputs (term_up, 1, _rl_output_character_function);
1146     }
1147 #endif /* !__GO32__ */
1148   _rl_last_v_pos = to;          /* Now TO is here */
1149 }
1150
1151 /* Physically print C on rl_outstream.  This is for functions which know
1152    how to optimize the display.  Return the number of characters output. */
1153 int
1154 rl_show_char (c)
1155      int c;
1156 {
1157   int n = 1;
1158   if (META_CHAR (c) && (_rl_output_meta_chars == 0))
1159     {
1160       fprintf (rl_outstream, "M-");
1161       n += 2;
1162       c = UNMETA (c);
1163     }
1164
1165 #if defined (DISPLAY_TABS)
1166   if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
1167 #else
1168   if (CTRL_CHAR (c) || c == RUBOUT)
1169 #endif /* !DISPLAY_TABS */
1170     {
1171       fprintf (rl_outstream, "C-");
1172       n += 2;
1173       c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
1174     }
1175
1176   putc (c, rl_outstream);
1177   fflush (rl_outstream);
1178   return n;
1179 }
1180
1181 int
1182 rl_character_len (c, pos)
1183      register int c, pos;
1184 {
1185   unsigned char uc;
1186
1187   uc = (unsigned char)c;
1188
1189   if (META_CHAR (uc))
1190     return ((_rl_output_meta_chars == 0) ? 4 : 1);
1191
1192   if (uc == '\t')
1193     {
1194 #if defined (DISPLAY_TABS)
1195       return (((pos | 7) + 1) - pos);
1196 #else
1197       return (2);
1198 #endif /* !DISPLAY_TABS */
1199     }
1200
1201   if (CTRL_CHAR (c) || c == RUBOUT)
1202     return (2);
1203
1204   return ((isprint (uc)) ? 1 : 2);
1205 }
1206
1207 /* How to print things in the "echo-area".  The prompt is treated as a
1208    mini-modeline. */
1209
1210 #if defined (USE_VARARGS)
1211 int
1212 #if defined (PREFER_STDARG)
1213 rl_message (const char *format, ...)
1214 #else
1215 rl_message (va_alist)
1216      va_dcl
1217 #endif
1218 {
1219   va_list args;
1220 #if defined (PREFER_VARARGS)
1221   char *format;
1222 #endif
1223
1224 #if defined (PREFER_STDARG)
1225   va_start (args, format);
1226 #else
1227   va_start (args);
1228   format = va_arg (args, char *);
1229 #endif
1230
1231   vsprintf (msg_buf, format, args);
1232   va_end (args);
1233
1234   rl_display_prompt = msg_buf;
1235   (*rl_redisplay_function) ();
1236   return 0;
1237 }
1238 #else /* !USE_VARARGS */
1239 int
1240 rl_message (format, arg1, arg2)
1241      char *format;
1242 {
1243   sprintf (msg_buf, format, arg1, arg2);
1244   rl_display_prompt = msg_buf;
1245   (*rl_redisplay_function) ();
1246   return 0;
1247 }
1248 #endif /* !USE_VARARGS */
1249
1250 /* How to clear things from the "echo-area". */
1251 int
1252 rl_clear_message ()
1253 {
1254   rl_display_prompt = rl_prompt;
1255   (*rl_redisplay_function) ();
1256   return 0;
1257 }
1258
1259 int
1260 rl_reset_line_state ()
1261 {
1262   rl_on_new_line ();
1263
1264   rl_display_prompt = rl_prompt ? rl_prompt : "";
1265   forced_display = 1;
1266   return 0;
1267 }
1268
1269 static char *saved_local_prompt;
1270 static char *saved_local_prefix;
1271 static int saved_last_invisible;
1272 static int saved_visible_length;
1273
1274 void
1275 rl_save_prompt ()
1276 {
1277   saved_local_prompt = local_prompt;
1278   saved_local_prefix = local_prompt_prefix;
1279   saved_last_invisible = last_invisible;
1280   saved_visible_length = visible_length;
1281
1282   local_prompt = local_prompt_prefix = (char *)0;
1283   last_invisible = visible_length = 0;
1284 }
1285
1286 void
1287 rl_restore_prompt ()
1288 {
1289   if (local_prompt)
1290     free (local_prompt);
1291   if (local_prompt_prefix)
1292     free (local_prompt_prefix);
1293
1294   local_prompt = saved_local_prompt;
1295   local_prompt_prefix = saved_local_prefix;
1296   last_invisible = saved_last_invisible;
1297   visible_length = saved_visible_length;
1298 }
1299
1300 char *
1301 _rl_make_prompt_for_search (pchar)
1302      int pchar;
1303 {
1304   int len;
1305   char *pmt;
1306
1307   rl_save_prompt ();
1308
1309   if (saved_local_prompt == 0)
1310     {
1311       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
1312       pmt = xmalloc (len + 2);
1313       if (len)
1314         strcpy (pmt, rl_prompt);
1315       pmt[len] = pchar;
1316       pmt[len+1] = '\0';
1317     }
1318   else
1319     {
1320       len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
1321       pmt = xmalloc (len + 2);
1322       if (len)
1323         strcpy (pmt, saved_local_prompt);
1324       pmt[len] = pchar;
1325       pmt[len+1] = '\0';
1326       local_prompt = savestring (pmt);
1327       last_invisible = saved_last_invisible;
1328       visible_length = saved_visible_length + 1;
1329     }
1330   return pmt;
1331 }
1332
1333 /* Quick redisplay hack when erasing characters at the end of the line. */
1334 void
1335 _rl_erase_at_end_of_line (l)
1336      int l;
1337 {
1338   register int i;
1339
1340   _rl_backspace (l);
1341   for (i = 0; i < l; i++)
1342     putc (' ', rl_outstream);
1343   _rl_backspace (l);
1344   for (i = 0; i < l; i++)
1345     visible_line[--_rl_last_c_pos] = '\0';
1346   rl_display_fixed++;
1347 }
1348
1349 /* Clear to the end of the line.  COUNT is the minimum
1350    number of character spaces to clear, */
1351 void
1352 _rl_clear_to_eol (count)
1353      int count;
1354 {
1355 #if !defined (__GO32__)
1356   if (term_clreol)
1357     tputs (term_clreol, 1, _rl_output_character_function);
1358   else if (count)
1359 #endif /* !__GO32__ */
1360     space_to_eol (count);
1361 }
1362
1363 /* Clear to the end of the line using spaces.  COUNT is the minimum
1364    number of character spaces to clear, */
1365 static void
1366 space_to_eol (count)
1367      int count;
1368 {
1369   register int i;
1370
1371   for (i = 0; i < count; i++)
1372    putc (' ', rl_outstream);
1373
1374   _rl_last_c_pos += count;
1375 }
1376
1377 void
1378 _rl_clear_screen ()
1379 {
1380 #if !defined (__GO32__)
1381   if (term_clrpag)
1382     tputs (term_clrpag, 1, _rl_output_character_function);
1383   else
1384 #endif /* !__GO32__ */
1385     crlf ();
1386 }
1387
1388 /* Insert COUNT characters from STRING to the output stream. */
1389 static void
1390 insert_some_chars (string, count)
1391      char *string;
1392      int count;
1393 {
1394 #if defined (__GO32__)
1395   int row, col, width;
1396   char *row_start;
1397
1398   ScreenGetCursor (&row, &col);
1399   width = ScreenCols ();
1400   row_start = ScreenPrimary + (row * width);
1401
1402   memcpy (row_start + col + count, row_start + col, width - col - count);
1403
1404   /* Place the text on the screen. */
1405   _rl_output_some_chars (string, count);
1406 #else /* !_GO32 */
1407
1408   /* If IC is defined, then we do not have to "enter" insert mode. */
1409   if (term_IC)
1410     {
1411       char *buffer;
1412       buffer = tgoto (term_IC, 0, count);
1413       tputs (buffer, 1, _rl_output_character_function);
1414       _rl_output_some_chars (string, count);
1415     }
1416   else
1417     {
1418       register int i;
1419
1420       /* If we have to turn on insert-mode, then do so. */
1421       if (term_im && *term_im)
1422         tputs (term_im, 1, _rl_output_character_function);
1423
1424       /* If there is a special command for inserting characters, then
1425          use that first to open up the space. */
1426       if (term_ic && *term_ic)
1427         {
1428           for (i = count; i--; )
1429             tputs (term_ic, 1, _rl_output_character_function);
1430         }
1431
1432       /* Print the text. */
1433       _rl_output_some_chars (string, count);
1434
1435       /* If there is a string to turn off insert mode, we had best use
1436          it now. */
1437       if (term_ei && *term_ei)
1438         tputs (term_ei, 1, _rl_output_character_function);
1439     }
1440 #endif /* !__GO32__ */
1441 }
1442
1443 /* Delete COUNT characters from the display line. */
1444 static void
1445 delete_chars (count)
1446      int count;
1447 {
1448 #if defined (__GO32__)
1449   int row, col, width;
1450   char *row_start;
1451
1452   ScreenGetCursor (&row, &col);
1453   width = ScreenCols ();
1454   row_start = ScreenPrimary + (row * width);
1455
1456   memcpy (row_start + col, row_start + col + count, width - col - count);
1457   memset (row_start + width - count, 0, count * 2);
1458 #else /* !_GO32 */
1459
1460   if (count > screenwidth)      /* XXX */
1461     return;
1462
1463   if (term_DC && *term_DC)
1464     {
1465       char *buffer;
1466       buffer = tgoto (term_DC, count, count);
1467       tputs (buffer, count, _rl_output_character_function);
1468     }
1469   else
1470     {
1471       if (term_dc && *term_dc)
1472         while (count--)
1473           tputs (term_dc, 1, _rl_output_character_function);
1474     }
1475 #endif /* !__GO32__ */
1476 }
1477
1478 void
1479 _rl_update_final ()
1480 {
1481   int full_lines;
1482
1483   full_lines = 0;
1484   /* If the cursor is the only thing on an otherwise-blank last line,
1485      compensate so we don't print an extra CRLF. */
1486   if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
1487         visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
1488     {
1489       _rl_vis_botlin--;
1490       full_lines = 1;
1491     }
1492   _rl_move_vert (_rl_vis_botlin);
1493   /* If we've wrapped lines, remove the final xterm line-wrap flag. */
1494   if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == screenwidth))
1495     {
1496       char *last_line;
1497       last_line = &visible_line[inv_lbreaks[_rl_vis_botlin]];
1498       _rl_move_cursor_relative (screenwidth - 1, last_line);
1499       _rl_clear_to_eol (0);
1500       putc (last_line[screenwidth - 1], rl_outstream);
1501     }
1502   _rl_vis_botlin = 0;
1503   crlf ();
1504   fflush (rl_outstream);
1505   rl_display_fixed++;
1506 }
1507
1508 /* Move to the start of the current line. */
1509 static void
1510 cr ()
1511 {
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     }
1521 }
1522
1523 /* Redisplay the current line after a SIGWINCH is received. */
1524 void
1525 _rl_redisplay_after_sigwinch ()
1526 {
1527   char *t, *oldp, *oldl, *oldlprefix;
1528
1529   /* Clear the current line and put the cursor at column 0.  Make sure
1530      the right thing happens if we have wrapped to a new screen line. */
1531   if (term_cr)
1532     {
1533 #if defined (__MSDOS__)
1534       putc ('\r', rl_outstream);
1535 #else
1536       tputs (term_cr, 1, _rl_output_character_function);
1537 #endif /* !__MSDOS__ */
1538       _rl_last_c_pos = 0;
1539 #if defined (__MSDOS__)
1540       space_to_eol (screenwidth);
1541       putc ('\r', rl_outstream);
1542 #else
1543       if (term_clreol)
1544         tputs (term_clreol, 1, _rl_output_character_function);
1545       else
1546         {
1547           space_to_eol (screenwidth);
1548           tputs (term_cr, 1, _rl_output_character_function);
1549         }
1550 #endif
1551       if (_rl_last_v_pos > 0)
1552         _rl_move_vert (0);
1553     }
1554   else
1555     crlf ();
1556
1557   /* Redraw only the last line of a multi-line prompt. */
1558   t = strrchr (rl_display_prompt, '\n');
1559   if (t)
1560     {
1561       oldp = rl_display_prompt;
1562       oldl = local_prompt;
1563       oldlprefix = local_prompt_prefix;
1564       rl_display_prompt = ++t;
1565       local_prompt = local_prompt_prefix = (char *)NULL;
1566       rl_forced_update_display ();
1567       rl_display_prompt = oldp;
1568       local_prompt = oldl;
1569       local_prompt_prefix = oldlprefix;
1570     }
1571   else
1572     rl_forced_update_display ();
1573 }
1574
1575 void
1576 _rl_clean_up_for_exit ()
1577 {
1578   if (readline_echoing_p)
1579     {
1580       _rl_move_vert (_rl_vis_botlin);
1581       _rl_vis_botlin = 0;
1582       fflush (rl_outstream);
1583       rl_restart_output (1, 0);
1584     }
1585 }
1586
1587 void
1588 _rl_erase_entire_line ()
1589 {
1590   cr ();
1591   _rl_clear_to_eol (0);
1592   cr ();
1593   fflush (rl_outstream);
1594 }