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