This commit was manufactured by cvs2svn to create branch 'FSF'.
[external/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
23 #include <stdio.h>
24 #include <sys/types.h>
25
26 /* System-specific feature definitions and include files. */
27 #include "rldefs.h"
28
29 /* Some standard library routines. */
30 #include "readline.h"
31 #include "history.h"
32
33 #if !defined (strrchr)
34 extern char *strrchr ();
35 #endif /* !strchr */
36
37 /* Global and pseudo-global variables and functions
38    imported from readline.c. */
39 extern char *rl_prompt;
40 extern int readline_echoing_p;
41 extern char *term_clreol, *term_im, *term_ic,  *term_ei, *term_DC;
42 /* Termcap variables. */
43 extern char *term_up, *term_dc, *term_cr, *term_IC;
44 extern int screenheight, screenwidth, terminal_can_insert;
45
46 extern void _rl_output_some_chars ();
47 extern void _rl_output_character_function ();
48
49 extern int _rl_convert_meta_chars_to_ascii;
50 extern int _rl_horizontal_scroll_mode;
51 extern int _rl_mark_modified_lines;
52 extern int _rl_prefer_visible_bell;
53
54 /* Pseudo-global functions (local to the readline library) exported
55    by this file. */
56 void _rl_move_cursor_relative (), _rl_output_some_chars ();
57 void _rl_move_vert ();
58
59 static void update_line (), clear_to_eol ();
60 static void delete_chars (), insert_some_chars ();
61
62 extern char *xmalloc (), *xrealloc ();
63
64 /* **************************************************************** */
65 /*                                                                  */
66 /*                      Display stuff                               */
67 /*                                                                  */
68 /* **************************************************************** */
69
70 /* This is the stuff that is hard for me.  I never seem to write good
71    display routines in C.  Let's see how I do this time. */
72
73 /* (PWP) Well... Good for a simple line updater, but totally ignores
74    the problems of input lines longer than the screen width.
75
76    update_line and the code that calls it makes a multiple line,
77    automatically wrapping line update.  Carefull attention needs
78    to be paid to the vertical position variables.
79
80    handling of terminals with autowrap on (incl. DEC braindamage)
81    could be improved a bit.  Right now I just cheat and decrement
82    screenwidth by one. */
83
84 /* Keep two buffers; one which reflects the current contents of the
85    screen, and the other to draw what we think the new contents should
86    be.  Then compare the buffers, and make whatever changes to the
87    screen itself that we should.  Finally, make the buffer that we
88    just drew into be the one which reflects the current contents of the
89    screen, and place the cursor where it belongs.
90
91    Commands that want to can fix the display themselves, and then let
92    this function know that the display has been fixed by setting the
93    RL_DISPLAY_FIXED variable.  This is good for efficiency. */
94
95 /* What YOU turn on when you have handled all redisplay yourself. */
96 int rl_display_fixed = 0;
97
98 /* The stuff that gets printed out before the actual text of the line.
99    This is usually pointing to rl_prompt. */
100 char *rl_display_prompt = (char *)NULL;
101
102 /* Pseudo-global variables declared here. */
103 /* The visible cursor position.  If you print some text, adjust this. */
104 int _rl_last_c_pos = 0;
105 int _rl_last_v_pos = 0;
106
107 /* Number of lines currently on screen minus 1. */
108 int _rl_vis_botlin = 0;
109
110 /* Variables used only in this file. */
111 /* The last left edge of text that was displayed.  This is used when
112    doing horizontal scrolling.  It shifts in thirds of a screenwidth. */
113 static int last_lmargin = 0;
114
115 /* The line display buffers.  One is the line currently displayed on
116    the screen.  The other is the line about to be displayed. */
117 static char *visible_line = (char *)NULL;
118 static char *invisible_line = (char *)NULL;
119
120 /* A buffer for `modeline' messages. */
121 static char msg_buf[128];
122
123 /* Non-zero forces the redisplay even if we thought it was unnecessary. */
124 static int forced_display = 0;
125
126 /* Default and initial buffer size.  Can grow. */
127 static int line_size = 1024;
128
129 /* Basic redisplay algorithm. */
130 rl_redisplay ()
131 {
132   register int in, out, c, linenum;
133   register char *line = invisible_line;
134   char *prompt_this_line;
135   int c_pos = 0;
136   int inv_botlin = 0;           /* Number of lines in newly drawn buffer. */
137
138   if (!readline_echoing_p)
139     return;
140
141   if (!rl_display_prompt)
142     rl_display_prompt = "";
143
144   if (!invisible_line)
145     {
146       visible_line = (char *)xmalloc (line_size);
147       invisible_line = (char *)xmalloc (line_size);
148       line = invisible_line;
149       for (in = 0; in < line_size; in++)
150         {
151           visible_line[in] = 0;
152           invisible_line[in] = 1;
153         }
154       rl_on_new_line ();
155     }
156
157   /* Draw the line into the buffer. */
158   c_pos = -1;
159
160   /* Mark the line as modified or not.  We only do this for history
161      lines. */
162   out = 0;
163   if (_rl_mark_modified_lines && current_history () && rl_undo_list)
164     {
165       line[out++] = '*';
166       line[out] = '\0';
167     }
168
169   /* If someone thought that the redisplay was handled, but the currently
170      visible line has a different modification state than the one about
171      to become visible, then correct the caller's misconception. */
172   if (visible_line[0] != invisible_line[0])
173     rl_display_fixed = 0;
174
175   prompt_this_line = strrchr (rl_display_prompt, '\n');
176   if (!prompt_this_line)
177     prompt_this_line = rl_display_prompt;
178   else
179     {
180       prompt_this_line++;
181       if (forced_display)
182         _rl_output_some_chars
183           (rl_display_prompt, prompt_this_line - rl_display_prompt);
184     }
185
186   strncpy (line + out,  prompt_this_line, strlen (prompt_this_line));
187   out += strlen (prompt_this_line);
188   line[out] = '\0';
189
190   for (in = 0; in < rl_end; in++)
191     {
192       c = (unsigned char)rl_line_buffer[in];
193
194       if (out + 8 >= line_size)         /* XXX - 8 for \t */
195         {
196           line_size *= 2;
197           visible_line = (char *)xrealloc (visible_line, line_size);
198           invisible_line = (char *)xrealloc (invisible_line, line_size);
199           line = invisible_line;
200         }
201
202       if (in == rl_point)
203         c_pos = out;
204
205       if (META_CHAR (c))
206         {
207           if (_rl_convert_meta_chars_to_ascii)
208             {
209               sprintf (line + out, "\\%o", c);
210               out += 4;
211             }
212           else
213             line[out++] = c;      
214         }
215 #define DISPLAY_TABS
216 #if defined (DISPLAY_TABS)
217       else if (c == '\t')
218         {
219           register int newout = (out | (int)7) + 1;
220           while (out < newout)
221             line[out++] = ' ';
222         }
223 #endif
224       else if (c < ' ')
225         {
226           line[out++] = '^';
227           line[out++] = UNCTRL (c);     /* XXX was c ^ 0x40 */
228         }
229       else if (c == 127)
230         {
231           line[out++] = '^';
232           line[out++] = '?';
233         }
234       else
235         line[out++] = c;
236     }
237   line[out] = '\0';
238   if (c_pos < 0)
239     c_pos = out;
240
241   /* PWP: now is when things get a bit hairy.  The visible and invisible
242      line buffers are really multiple lines, which would wrap every
243      (screenwidth - 1) characters.  Go through each in turn, finding
244      the changed region and updating it.  The line order is top to bottom. */
245
246   /* If we can move the cursor up and down, then use multiple lines,
247      otherwise, let long lines display in a single terminal line, and
248      horizontally scroll it. */
249
250   if (!_rl_horizontal_scroll_mode && term_up && *term_up)
251     {
252       int total_screen_chars = (screenwidth * screenheight);
253
254       if (!rl_display_fixed || forced_display)
255         {
256           forced_display = 0;
257
258           /* If we have more than a screenful of material to display, then
259              only display a screenful.  We should display the last screen,
260              not the first.  I'll fix this in a minute. */
261           if (out >= total_screen_chars)
262             out = total_screen_chars - 1;
263
264           /* Number of screen lines to display. */
265           inv_botlin = out / screenwidth;
266
267           /* For each line in the buffer, do the updating display. */
268           for (linenum = 0; linenum <= inv_botlin; linenum++)
269             update_line (linenum > _rl_vis_botlin ? ""
270                          : &visible_line[linenum * screenwidth],
271                          &invisible_line[linenum * screenwidth],
272                          linenum);
273
274           /* We may have deleted some lines.  If so, clear the left over
275              blank ones at the bottom out. */
276           if (_rl_vis_botlin > inv_botlin)
277             {
278               char *tt;
279               for (; linenum <= _rl_vis_botlin; linenum++)
280                 {
281                   tt = &visible_line[linenum * screenwidth];
282                   _rl_move_vert (linenum);
283                   _rl_move_cursor_relative (0, tt);
284                   clear_to_eol
285                     ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth);
286                 }
287             }
288           _rl_vis_botlin = inv_botlin;
289
290           /* Move the cursor where it should be. */
291           _rl_move_vert (c_pos / screenwidth);
292           _rl_move_cursor_relative (c_pos % screenwidth,
293                                 &invisible_line[(c_pos / screenwidth) * screenwidth]);
294         }
295     }
296   else                          /* Do horizontal scrolling. */
297     {
298       int lmargin;
299
300       /* Always at top line. */
301       _rl_last_v_pos = 0;
302
303       /* If the display position of the cursor would be off the edge
304          of the screen, start the display of this line at an offset that
305          leaves the cursor on the screen. */
306       if (c_pos - last_lmargin > screenwidth - 2)
307         lmargin = (c_pos / (screenwidth / 3) - 2) * (screenwidth / 3);
308       else if (c_pos - last_lmargin < 1)
309         lmargin = ((c_pos - 1) / (screenwidth / 3)) * (screenwidth / 3);
310       else
311         lmargin = last_lmargin;
312
313       /* If the first character on the screen isn't the first character
314          in the display line, indicate this with a special character. */
315       if (lmargin > 0)
316         line[lmargin] = '<';
317
318       if (lmargin + screenwidth < out)
319         line[lmargin + screenwidth - 1] = '>';
320
321       if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
322         {
323           forced_display = 0;
324           update_line (&visible_line[last_lmargin],
325                        &invisible_line[lmargin], 0);
326
327           _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
328           last_lmargin = lmargin;
329         }
330     }
331   fflush (rl_outstream);
332
333   /* Swap visible and non-visible lines. */
334   {
335     char *temp = visible_line;
336     visible_line = invisible_line;
337     invisible_line = temp;
338     rl_display_fixed = 0;
339   }
340 }
341
342 /* PWP: update_line() is based on finding the middle difference of each
343    line on the screen; vis:
344
345                              /old first difference
346         /beginning of line   |              /old last same       /old EOL
347         v                    v              v                    v
348 old:    eddie> Oh, my little gruntle-buggy is to me, as lurgid as
349 new:    eddie> Oh, my little buggy says to me, as lurgid as
350         ^                    ^        ^                    ^
351         \beginning of line   |        \new last same       \new end of line
352                              \new first difference
353
354    All are character pointers for the sake of speed.  Special cases for
355    no differences, as well as for end of line additions must be handeled.
356
357    Could be made even smarter, but this works well enough */
358 static void
359 update_line (old, new, current_line)
360      register char *old, *new;
361      int current_line;
362 {
363   register char *ofd, *ols, *oe, *nfd, *nls, *ne;
364   int lendiff, wsatend;
365
366   /* Find first difference. */
367   for (ofd = old, nfd = new;
368        (ofd - old < screenwidth) && *ofd && (*ofd == *nfd);
369        ofd++, nfd++)
370     ;
371
372   /* Move to the end of the screen line. */
373   for (oe = ofd; ((oe - old) < screenwidth) && *oe; oe++);
374   for (ne = nfd; ((ne - new) < screenwidth) && *ne; ne++);
375
376   /* If no difference, continue to next line. */
377   if (ofd == oe && nfd == ne)
378     return;
379
380   wsatend = 1;                  /* flag for trailing whitespace */
381   ols = oe - 1;                 /* find last same */
382   nls = ne - 1;
383   while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
384     {
385       if (*ols != ' ')
386         wsatend = 0;
387       ols--;
388       nls--;
389     }
390
391   if (wsatend)
392     {
393       ols = oe;
394       nls = ne;
395     }
396   else if (*ols != *nls)
397     {
398       if (*ols)                 /* don't step past the NUL */
399         ols++;
400       if (*nls)
401         nls++;
402     }
403
404   _rl_move_vert (current_line);
405   _rl_move_cursor_relative (ofd - old, old);
406
407   /* if (len (new) > len (old)) */
408   lendiff = (nls - nfd) - (ols - ofd);
409
410   /* Insert (diff (len (old), len (new)) ch. */
411   if (lendiff > 0)
412     {
413       if (terminal_can_insert)
414         {
415           /* Sometimes it is cheaper to print the characters rather than
416              use the terminal's capabilities. */
417           if ((2 * (ne - nfd)) < lendiff && !term_IC)
418             {
419               _rl_output_some_chars (nfd, (ne - nfd));
420               _rl_last_c_pos += (ne - nfd);
421             }
422           else
423             {
424               if (*ols)
425                 {
426                   insert_some_chars (nfd, lendiff);
427                   _rl_last_c_pos += lendiff;
428                 }
429               else
430                 {
431                   /* At the end of a line the characters do not have to
432                      be "inserted".  They can just be placed on the screen. */
433                   _rl_output_some_chars (nfd, lendiff);
434                   _rl_last_c_pos += lendiff;
435                 }
436               /* Copy (new) chars to screen from first diff to last match. */
437               if (((nls - nfd) - lendiff) > 0)
438                 {
439                   _rl_output_some_chars (&nfd[lendiff], ((nls - nfd) - lendiff));
440                   _rl_last_c_pos += ((nls - nfd) - lendiff);
441                 }
442             }
443         }
444       else
445         {               /* cannot insert chars, write to EOL */
446           _rl_output_some_chars (nfd, (ne - nfd));
447           _rl_last_c_pos += (ne - nfd);
448         }
449     }
450   else                          /* Delete characters from line. */
451     {
452       /* If possible and inexpensive to use terminal deletion, then do so. */
453       if (term_dc && (2 * (ne - nfd)) >= (-lendiff))
454         {
455           if (lendiff)
456             delete_chars (-lendiff); /* delete (diff) characters */
457
458           /* Copy (new) chars to screen from first diff to last match */
459           if ((nls - nfd) > 0)
460             {
461               _rl_output_some_chars (nfd, (nls - nfd));
462               _rl_last_c_pos += (nls - nfd);
463             }
464         }
465       /* Otherwise, print over the existing material. */
466       else
467         {
468           _rl_output_some_chars (nfd, (ne - nfd));
469           _rl_last_c_pos += (ne - nfd);
470           clear_to_eol ((oe - old) - (ne - new));
471         }
472     }
473 }
474
475 /* Tell the update routines that we have moved onto a new (empty) line. */
476 rl_on_new_line ()
477 {
478   if (visible_line)
479     visible_line[0] = '\0';
480
481   _rl_last_c_pos = _rl_last_v_pos = 0;
482   _rl_vis_botlin = last_lmargin = 0;
483 }
484
485 /* Actually update the display, period. */
486 rl_forced_update_display ()
487 {
488   if (visible_line)
489     {
490       register char *temp = visible_line;
491
492       while (*temp) *temp++ = '\0';
493     }
494   rl_on_new_line ();
495   forced_display++;
496   rl_redisplay ();
497 }
498
499 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
500    DATA is the contents of the screen line of interest; i.e., where
501    the movement is being done. */
502 void
503 _rl_move_cursor_relative (new, data)
504      int new;
505      char *data;
506 {
507   register int i;
508
509   /* It may be faster to output a CR, and then move forwards instead
510      of moving backwards. */
511   if (new + 1 < _rl_last_c_pos - new)
512     {
513 #ifdef __MSDOS__
514       putc('\r', rl_outstream);
515 #else
516       tputs (term_cr, 1, _rl_output_character_function);
517 #endif
518       _rl_last_c_pos = 0;
519     }
520
521   if (_rl_last_c_pos == new) return;
522
523   if (_rl_last_c_pos < new)
524     {
525       /* Move the cursor forward.  We do it by printing the command
526          to move the cursor forward if there is one, else print that
527          portion of the output buffer again.  Which is cheaper? */
528
529       /* The above comment is left here for posterity.  It is faster
530          to print one character (non-control) than to print a control
531          sequence telling the terminal to move forward one character.
532          That kind of control is for people who don't know what the
533          data is underneath the cursor. */
534 #if defined (HACK_TERMCAP_MOTION)
535       extern char *term_forward_char;
536
537       if (term_forward_char)
538         for (i = _rl_last_c_pos; i < new; i++)
539           tputs (term_forward_char, 1, _rl_output_character_function);
540       else
541         for (i = _rl_last_c_pos; i < new; i++)
542           putc (data[i], rl_outstream);
543 #else
544       for (i = _rl_last_c_pos; i < new; i++)
545         putc (data[i], rl_outstream);
546 #endif                          /* HACK_TERMCAP_MOTION */
547     }
548   else
549     backspace (_rl_last_c_pos - new);
550   _rl_last_c_pos = new;
551 }
552
553 /* PWP: move the cursor up or down. */
554 void
555 _rl_move_vert (to)
556      int to;
557 {
558   register int delta, i;
559
560   if (_rl_last_v_pos == to || to > screenheight)
561     return;
562
563 #ifdef __GO32__
564   {
565     int row, col;
566     ScreenGetCursor (&row, &col);
567     ScreenSetCursor ((row + to - _rl_last_v_pos), col);
568   }
569 #else /* __GO32__ */
570   if ((delta = to - _rl_last_v_pos) > 0)
571     {
572       for (i = 0; i < delta; i++)
573         putc ('\n', rl_outstream);
574       tputs (term_cr, 1, _rl_output_character_function);
575       _rl_last_c_pos = 0;
576     }
577   else
578     {                   /* delta < 0 */
579       if (term_up && *term_up)
580         for (i = 0; i < -delta; i++)
581           tputs (term_up, 1, _rl_output_character_function);
582     }
583 #endif /* !__GO32__ */
584   _rl_last_v_pos = to;          /* Now TO is here */
585 }
586
587 /* Physically print C on rl_outstream.  This is for functions which know
588    how to optimize the display. */
589 rl_show_char (c)
590      int c;
591 {
592   if (META_CHAR (c) && _rl_convert_meta_chars_to_ascii)
593     {
594       fprintf (rl_outstream, "M-");
595       c = UNMETA (c);
596     }
597
598 #if defined (DISPLAY_TABS)
599   if (c < 32 && c != '\t')
600 #else
601   if (c < 32)
602 #endif /* !DISPLAY_TABS */
603     {
604
605       c += 64;
606     }
607
608   putc (c, rl_outstream);
609   fflush (rl_outstream);
610 }
611
612 int
613 rl_character_len (c, pos)
614      register int c, pos;
615 {
616   if (META_CHAR (c))
617     return (_rl_convert_meta_chars_to_ascii ? 4 : 1);
618
619   if (c == '\t')
620     {
621 #if defined (DISPLAY_TABS)
622       return (((pos | (int)7) + 1) - pos);
623 #else
624       return (2);
625 #endif /* !DISPLAY_TABS */
626     }
627
628   if (isprint (c))
629     return (1);
630   else
631     return (2);
632 }
633
634 /* How to print things in the "echo-area".  The prompt is treated as a
635    mini-modeline. */
636
637 #if defined (HAVE_VARARGS_H)
638 rl_message (va_alist)
639      va_dcl
640 {
641   char *format;
642   va_list args;
643
644   va_start (args);
645   format = va_arg (args, char *);
646   vsprintf (msg_buf, format, args);
647   va_end (args);
648
649   rl_display_prompt = msg_buf;
650   rl_redisplay ();
651 }
652 #else /* !HAVE_VARARGS_H */
653 rl_message (format, arg1, arg2)
654      char *format;
655 {
656   sprintf (msg_buf, format, arg1, arg2);
657   rl_display_prompt = msg_buf;
658   rl_redisplay ();
659 }
660 #endif /* !HAVE_VARARGS_H */
661
662 /* How to clear things from the "echo-area". */
663 rl_clear_message ()
664 {
665   rl_display_prompt = rl_prompt;
666   rl_redisplay ();
667 }
668
669 rl_reset_line_state ()
670 {
671   rl_on_new_line ();
672
673   rl_display_prompt = rl_prompt ? rl_prompt : "";
674   forced_display = 1;
675 }
676
677 /* Quick redisplay hack when erasing characters at the end of the line. */
678 void
679 _rl_erase_at_end_of_line (l)
680      int l;
681 {
682   register int i;
683
684   backspace (l);
685   for (i = 0; i < l; i++)
686     putc (' ', rl_outstream);
687   backspace (l);
688   for (i = 0; i < l; i++)
689     visible_line[--_rl_last_c_pos] = '\0';
690   rl_display_fixed++;
691 }
692
693 /* Clear to the end of the line.  COUNT is the minimum
694    number of character spaces to clear, */
695 static void
696 clear_to_eol (count)
697      int count;
698 {
699 #ifndef __GO32__
700   if (term_clreol)
701     {
702       tputs (term_clreol, 1, _rl_output_character_function);
703     }
704   else
705 #endif /* !__GO32__ */
706     {
707       register int i;
708
709       /* Do one more character space. */
710       count++;
711
712       for (i = 0; i < count; i++)
713         putc (' ', rl_outstream);
714
715       backspace (count);
716     }
717 }
718 /* Insert COUNT characters from STRING to the output stream. */
719 static void
720 insert_some_chars (string, count)
721      char *string;
722      int count;
723 {
724 #ifdef __GO32__
725   int row, col, width;
726   char *row_start;
727
728   ScreenGetCursor (&row, &col);
729   width = ScreenCols ();
730   row_start = ScreenPrimary + (row * width);
731   memcpy (row_start + col + count, row_start + col, width - col - count);
732   /* Place the text on the screen. */
733   _rl_output_some_chars (string, count);
734 #else /* __GO32__ */
735   /* If IC is defined, then we do not have to "enter" insert mode. */
736   if (term_IC)
737     {
738       char *tgoto (), *buffer;
739       buffer = tgoto (term_IC, 0, count);
740       tputs (buffer, 1, _rl_output_character_function);
741       _rl_output_some_chars (string, count);
742     }
743   else
744     {
745       register int i;
746
747       /* If we have to turn on insert-mode, then do so. */
748       if (term_im && *term_im)
749         tputs (term_im, 1, _rl_output_character_function);
750
751       /* If there is a special command for inserting characters, then
752          use that first to open up the space. */
753       if (term_ic && *term_ic)
754         {
755           for (i = count; i--; )
756             tputs (term_ic, 1, _rl_output_character_function);
757         }
758
759       /* Print the text. */
760       _rl_output_some_chars (string, count);
761
762       /* If there is a string to turn off insert mode, we had best use
763          it now. */
764       if (term_ei && *term_ei)
765         tputs (term_ei, 1, _rl_output_character_function);
766     }
767 #endif /* __GO32__ */
768 }
769
770 /* Delete COUNT characters from the display line. */
771 static void
772 delete_chars (count)
773      int count;
774 {
775 #if defined (__GO32__)
776   int row, col, width;
777   char *row_start;
778
779   ScreenGetCursor (&row, &col);
780   width = ScreenCols ();
781   row_start = ScreenPrimary + (row * width);
782   memcpy (row_start + col, row_start + col + count, width - col - count);
783   memset (row_start + width - count, 0, count * 2);
784 #else /* !__GO32__ */
785   if (count > screenwidth)
786     return;
787
788   if (term_DC && *term_DC)
789     {
790       char *tgoto (), *buffer;
791       buffer = tgoto (term_DC, 0, count);
792       tputs (buffer, 1, _rl_output_character_function);
793     }
794   else
795     {
796       if (term_dc && *term_dc)
797         while (count--)
798           tputs (term_dc, 1, _rl_output_character_function);
799     }
800 #endif /* !__GO32__ */
801 }