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