]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/readline/display.c
913e0da0cf8497cc454fb3ce937aef298ab7de9e
[thirdparty/bash.git] / lib / readline / display.c
1 /* display.c -- readline redisplay facility. */
2
3 /* Copyright (C) 1987-2013 Free Software Foundation, Inc.
4
5 This file is part of the GNU Readline Library (Readline), a library
6 for reading lines of text with interactive input and history editing.
7
8 Readline is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Readline is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Readline. If not, see <http://www.gnu.org/licenses/>.
20 */
21
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 #ifdef __MSDOS__
45 # include <pc.h>
46 #endif
47
48 /* System-specific feature definitions and include files. */
49 #include "rldefs.h"
50 #include "rlmbutil.h"
51
52 /* Termcap library stuff. */
53 #include "tcap.h"
54
55 /* Some standard library routines. */
56 #include "readline.h"
57 #include "history.h"
58
59 #include "rlprivate.h"
60 #include "xmalloc.h"
61
62 #if !defined (strchr) && !defined (__STDC__)
63 extern char *strchr (), *strrchr ();
64 #endif /* !strchr && !__STDC__ */
65
66 static void update_line PARAMS((char *, char *, int, int, int, int));
67 static void space_to_eol PARAMS((int));
68 static void delete_chars PARAMS((int));
69 static void insert_some_chars PARAMS((char *, int, int));
70 static void open_some_spaces PARAMS((int));
71 static void cr PARAMS((void));
72
73 /* State of visible and invisible lines. */
74 struct line_state
75 {
76 char *line;
77 int *lbreaks;
78 int lbsize;
79 #if defined (HANDLE_MULTIBYTE)
80 int *wrapped_line;
81 int wbsize;
82 #endif
83 };
84
85 /* The line display buffers. One is the line currently displayed on
86 the screen. The other is the line about to be displayed. */
87 static struct line_state line_state_array[2];
88 static struct line_state *line_state_visible = &line_state_array[0];
89 static struct line_state *line_state_invisible = &line_state_array[1];
90 static int line_structures_initialized = 0;
91
92 /* Backwards-compatible names. */
93 #define inv_lbreaks (line_state_invisible->lbreaks)
94 #define inv_lbsize (line_state_invisible->lbsize)
95 #define vis_lbreaks (line_state_visible->lbreaks)
96 #define vis_lbsize (line_state_visible->lbsize)
97
98 #define visible_line (line_state_visible->line)
99 #define invisible_line (line_state_invisible->line)
100
101 #if defined (HANDLE_MULTIBYTE)
102 static int _rl_col_width PARAMS((const char *, int, int, int));
103 #else
104 # define _rl_col_width(l, s, e, f) (((e) <= (s)) ? 0 : (e) - (s))
105 #endif
106
107 /* Heuristic used to decide whether it is faster to move from CUR to NEW
108 by backing up or outputting a carriage return and moving forward. CUR
109 and NEW are either both buffer positions or absolute screen positions. */
110 #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
111
112 /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
113 buffer index in others. This macro is used when deciding whether the
114 current cursor position is in the middle of a prompt string containing
115 invisible characters. XXX - might need to take `modmark' into account. */
116 #define PROMPT_ENDING_INDEX \
117 ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
118
119
120 /* **************************************************************** */
121 /* */
122 /* Display stuff */
123 /* */
124 /* **************************************************************** */
125
126 /* This is the stuff that is hard for me. I never seem to write good
127 display routines in C. Let's see how I do this time. */
128
129 /* (PWP) Well... Good for a simple line updater, but totally ignores
130 the problems of input lines longer than the screen width.
131
132 update_line and the code that calls it makes a multiple line,
133 automatically wrapping line update. Careful attention needs
134 to be paid to the vertical position variables. */
135
136 /* Keep two buffers; one which reflects the current contents of the
137 screen, and the other to draw what we think the new contents should
138 be. Then compare the buffers, and make whatever changes to the
139 screen itself that we should. Finally, make the buffer that we
140 just drew into be the one which reflects the current contents of the
141 screen, and place the cursor where it belongs.
142
143 Commands that want to can fix the display themselves, and then let
144 this function know that the display has been fixed by setting the
145 RL_DISPLAY_FIXED variable. This is good for efficiency. */
146
147 /* Application-specific redisplay function. */
148 rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
149
150 /* Global variables declared here. */
151 /* What YOU turn on when you have handled all redisplay yourself. */
152 int rl_display_fixed = 0;
153
154 int _rl_suppress_redisplay = 0;
155 int _rl_want_redisplay = 0;
156
157 /* The stuff that gets printed out before the actual text of the line.
158 This is usually pointing to rl_prompt. */
159 char *rl_display_prompt = (char *)NULL;
160
161 /* Pseudo-global variables declared here. */
162
163 /* The visible cursor position. If you print some text, adjust this. */
164 /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
165 supporting multibyte characters, and an absolute cursor position when
166 in such a locale. This is an artifact of the donated multibyte support.
167 Care must be taken when modifying its value. */
168 int _rl_last_c_pos = 0;
169 int _rl_last_v_pos = 0;
170
171 static int cpos_adjusted;
172 static int cpos_buffer_position;
173 static int displaying_prompt_first_line;
174 static int prompt_multibyte_chars;
175
176 /* Number of lines currently on screen minus 1. */
177 int _rl_vis_botlin = 0;
178
179 /* Variables used only in this file. */
180 /* The last left edge of text that was displayed. This is used when
181 doing horizontal scrolling. It shifts in thirds of a screenwidth. */
182 static int last_lmargin;
183
184 /* A buffer for `modeline' messages. */
185 static char *msg_buf = 0;
186 static int msg_bufsiz = 0;
187
188 /* Non-zero forces the redisplay even if we thought it was unnecessary. */
189 static int forced_display;
190
191 /* Default and initial buffer size. Can grow. */
192 static int line_size = 1024;
193
194 /* Variables to keep track of the expanded prompt string, which may
195 include invisible characters. */
196
197 static char *local_prompt, *local_prompt_prefix;
198 static int local_prompt_len;
199 static int prompt_visible_length, prompt_prefix_length;
200
201 /* The number of invisible characters in the line currently being
202 displayed on the screen. */
203 static int visible_wrap_offset;
204
205 /* The number of invisible characters in the prompt string. Static so it
206 can be shared between rl_redisplay and update_line */
207 static int wrap_offset;
208
209 /* The index of the last invisible character in the prompt string. */
210 static int prompt_last_invisible;
211
212 /* The length (buffer offset) of the first line of the last (possibly
213 multi-line) buffer displayed on the screen. */
214 static int visible_first_line_len;
215
216 /* Number of invisible characters on the first physical line of the prompt.
217 Only valid when the number of physical characters in the prompt exceeds
218 (or is equal to) _rl_screenwidth. */
219 static int prompt_invis_chars_first_line;
220
221 static int prompt_last_screen_line;
222
223 static int prompt_physical_chars;
224
225 /* set to a non-zero value by rl_redisplay if we are marking modified history
226 lines and the current line is so marked. */
227 static int modmark;
228
229 /* Variables to save and restore prompt and display information. */
230
231 /* These are getting numerous enough that it's time to create a struct. */
232
233 static char *saved_local_prompt;
234 static char *saved_local_prefix;
235 static int saved_last_invisible;
236 static int saved_visible_length;
237 static int saved_prefix_length;
238 static int saved_local_length;
239 static int saved_invis_chars_first_line;
240 static int saved_physical_chars;
241
242 /* Return a character indicating the editing mode, for use in the prompt. */
243 static int
244 prompt_modechar ()
245 {
246 if (rl_editing_mode == emacs_mode)
247 return '@';
248 else if (_rl_keymap == vi_insertion_keymap)
249 return '+'; /* vi insert mode */
250 else
251 return ':'; /* vi command mode */
252 }
253
254 /* Expand the prompt string S and return the number of visible
255 characters in *LP, if LP is not null. This is currently more-or-less
256 a placeholder for expansion. LIP, if non-null is a place to store the
257 index of the last invisible character in the returned string. NIFLP,
258 if non-zero, is a place to store the number of invisible characters in
259 the first prompt line. The previous are used as byte counts -- indexes
260 into a character buffer. */
261
262 /* Current implementation:
263 \001 (^A) start non-visible characters
264 \002 (^B) end non-visible characters
265 all characters except \001 and \002 (following a \001) are copied to
266 the returned string; all characters except those between \001 and
267 \002 are assumed to be `visible'. */
268
269 static char *
270 expand_prompt (pmt, lp, lip, niflp, vlp)
271 char *pmt;
272 int *lp, *lip, *niflp, *vlp;
273 {
274 char *r, *ret, *p, *igstart;
275 int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
276
277 /* Short-circuit if we can. */
278 if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
279 {
280 if (pmt == rl_prompt && _rl_show_mode_in_prompt)
281 {
282 l = strlen (pmt);
283 r = (char *)xmalloc (l + 2);
284 r[0] = prompt_modechar ();
285 strcpy (r + 1, pmt);
286 }
287 else
288 r = savestring (pmt);
289
290 if (lp)
291 *lp = strlen (r);
292 if (lip)
293 *lip = 0;
294 if (niflp)
295 *niflp = 0;
296 if (vlp)
297 *vlp = lp ? *lp : strlen (r);
298 return r;
299 }
300
301 l = strlen (pmt);
302 r = ret = (char *)xmalloc (l + 2);
303
304 rl = physchars = 0; /* move up here so mode show can set them */
305 if (pmt == rl_prompt && _rl_show_mode_in_prompt)
306 {
307 *r++ = prompt_modechar ();
308 rl = physchars = 1;
309 }
310
311 invfl = 0; /* invisible chars in first line of prompt */
312 invflset = 0; /* we only want to set invfl once */
313
314 igstart = 0;
315 for (ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
316 {
317 /* This code strips the invisible character string markers
318 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
319 if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
320 {
321 ignoring = 1;
322 igstart = p;
323 continue;
324 }
325 else if (ignoring && *p == RL_PROMPT_END_IGNORE)
326 {
327 ignoring = 0;
328 if (p != (igstart + 1))
329 last = r - ret - 1;
330 continue;
331 }
332 else
333 {
334 #if defined (HANDLE_MULTIBYTE)
335 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
336 {
337 pind = p - pmt;
338 ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
339 l = ind - pind;
340 while (l--)
341 *r++ = *p++;
342 if (!ignoring)
343 {
344 /* rl ends up being assigned to prompt_visible_length,
345 which is the number of characters in the buffer that
346 contribute to characters on the screen, which might
347 not be the same as the number of physical characters
348 on the screen in the presence of multibyte characters */
349 rl += ind - pind;
350 physchars += _rl_col_width (pmt, pind, ind, 0);
351 }
352 else
353 ninvis += ind - pind;
354 p--; /* compensate for later increment */
355 }
356 else
357 #endif
358 {
359 *r++ = *p;
360 if (!ignoring)
361 {
362 rl++; /* visible length byte counter */
363 physchars++;
364 }
365 else
366 ninvis++; /* invisible chars byte counter */
367 }
368
369 if (invflset == 0 && rl >= _rl_screenwidth)
370 {
371 invfl = ninvis;
372 invflset = 1;
373 }
374 }
375 }
376
377 if (rl < _rl_screenwidth)
378 invfl = ninvis;
379
380 *r = '\0';
381 if (lp)
382 *lp = rl;
383 if (lip)
384 *lip = last;
385 if (niflp)
386 *niflp = invfl;
387 if (vlp)
388 *vlp = physchars;
389 return ret;
390 }
391
392 /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
393 PMT and return the rest of PMT. */
394 char *
395 _rl_strip_prompt (pmt)
396 char *pmt;
397 {
398 char *ret;
399
400 ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
401 return ret;
402 }
403
404 void
405 _rl_reset_prompt ()
406 {
407 rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
408 }
409
410 /*
411 * Expand the prompt string into the various display components, if
412 * necessary.
413 *
414 * local_prompt = expanded last line of string in rl_display_prompt
415 * (portion after the final newline)
416 * local_prompt_prefix = portion before last newline of rl_display_prompt,
417 * expanded via expand_prompt
418 * prompt_visible_length = number of visible characters in local_prompt
419 * prompt_prefix_length = number of visible characters in local_prompt_prefix
420 *
421 * This function is called once per call to readline(). It may also be
422 * called arbitrarily to expand the primary prompt.
423 *
424 * The return value is the number of visible characters on the last line
425 * of the (possibly multi-line) prompt.
426 */
427 int
428 rl_expand_prompt (prompt)
429 char *prompt;
430 {
431 char *p, *t;
432 int c;
433
434 /* Clear out any saved values. */
435 FREE (local_prompt);
436 FREE (local_prompt_prefix);
437
438 local_prompt = local_prompt_prefix = (char *)0;
439 local_prompt_len = 0;
440 prompt_last_invisible = prompt_invis_chars_first_line = 0;
441 prompt_visible_length = prompt_physical_chars = 0;
442
443 if (prompt == 0 || *prompt == 0)
444 return (0);
445
446 p = strrchr (prompt, '\n');
447 if (!p)
448 {
449 /* The prompt is only one logical line, though it might wrap. */
450 local_prompt = expand_prompt (prompt, &prompt_visible_length,
451 &prompt_last_invisible,
452 &prompt_invis_chars_first_line,
453 &prompt_physical_chars);
454 local_prompt_prefix = (char *)0;
455 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
456 return (prompt_visible_length);
457 }
458 else
459 {
460 /* The prompt spans multiple lines. */
461 t = ++p;
462 local_prompt = expand_prompt (p, &prompt_visible_length,
463 &prompt_last_invisible,
464 &prompt_invis_chars_first_line,
465 &prompt_physical_chars);
466 c = *t; *t = '\0';
467 /* The portion of the prompt string up to and including the
468 final newline is now null-terminated. */
469 local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
470 (int *)NULL,
471 (int *)NULL,
472 (int *)NULL);
473 *t = c;
474 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
475 return (prompt_prefix_length);
476 }
477 }
478
479 /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
480 arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
481 and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
482 increased. If the lines have already been allocated, this ensures that
483 they can hold at least MINSIZE characters. */
484 static void
485 init_line_structures (minsize)
486 int minsize;
487 {
488 register int n;
489
490 if (invisible_line == 0) /* initialize it */
491 {
492 if (line_size < minsize)
493 line_size = minsize;
494 visible_line = (char *)xmalloc (line_size);
495 invisible_line = (char *)xmalloc (line_size);
496 }
497 else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
498 {
499 line_size *= 2;
500 if (line_size < minsize)
501 line_size = minsize;
502 visible_line = (char *)xrealloc (visible_line, line_size);
503 invisible_line = (char *)xrealloc (invisible_line, line_size);
504 }
505
506 for (n = minsize; n < line_size; n++)
507 {
508 visible_line[n] = 0;
509 invisible_line[n] = 1;
510 }
511
512 if (vis_lbreaks == 0)
513 {
514 /* should be enough. */
515 inv_lbsize = vis_lbsize = 256;
516
517 #if defined (HANDLE_MULTIBYTE)
518 line_state_visible->wbsize = vis_lbsize;
519 line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
520
521 line_state_invisible->wbsize = inv_lbsize;
522 line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
523 #endif
524
525 inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
526 vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
527 inv_lbreaks[0] = vis_lbreaks[0] = 0;
528 }
529
530 line_structures_initialized = 1;
531 }
532
533 /* Basic redisplay algorithm. */
534 void
535 rl_redisplay ()
536 {
537 register int in, out, c, linenum, cursor_linenum;
538 register char *line;
539 int inv_botlin, lb_botlin, lb_linenum, o_cpos;
540 int newlines, lpos, temp, n0, num, prompt_lines_estimate;
541 char *prompt_this_line;
542 #if defined (HANDLE_MULTIBYTE)
543 wchar_t wc;
544 size_t wc_bytes;
545 int wc_width;
546 mbstate_t ps;
547 int _rl_wrapped_multicolumn = 0;
548 #endif
549
550 if (_rl_echoing_p == 0)
551 return;
552
553 /* Block keyboard interrupts because this function manipulates global
554 data structures. */
555 _rl_block_sigint ();
556 RL_SETSTATE (RL_STATE_REDISPLAYING);
557
558 if (!rl_display_prompt)
559 rl_display_prompt = "";
560
561 if (line_structures_initialized == 0)
562 {
563 init_line_structures (0);
564 rl_on_new_line ();
565 }
566
567 /* Draw the line into the buffer. */
568 cpos_buffer_position = -1;
569
570 prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
571
572 line = invisible_line;
573 out = inv_botlin = 0;
574
575 /* Mark the line as modified or not. We only do this for history
576 lines. */
577 modmark = 0;
578 if (_rl_mark_modified_lines && current_history () && rl_undo_list)
579 {
580 line[out++] = '*';
581 line[out] = '\0';
582 modmark = 1;
583 }
584
585 /* If someone thought that the redisplay was handled, but the currently
586 visible line has a different modification state than the one about
587 to become visible, then correct the caller's misconception. */
588 if (visible_line[0] != invisible_line[0])
589 rl_display_fixed = 0;
590
591 /* If the prompt to be displayed is the `primary' readline prompt (the
592 one passed to readline()), use the values we have already expanded.
593 If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
594 number of non-visible characters in the prompt string. */
595 if (rl_display_prompt == rl_prompt || local_prompt)
596 {
597 if (local_prompt_prefix && forced_display)
598 _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
599
600 if (local_prompt_len > 0)
601 {
602 temp = local_prompt_len + out + 2;
603 if (temp >= line_size)
604 {
605 line_size = (temp + 1024) - (temp % 1024);
606 visible_line = (char *)xrealloc (visible_line, line_size);
607 line = invisible_line = (char *)xrealloc (invisible_line, line_size);
608 }
609 strncpy (line + out, local_prompt, local_prompt_len);
610 out += local_prompt_len;
611 }
612 line[out] = '\0';
613 wrap_offset = local_prompt_len - prompt_visible_length;
614 }
615 else
616 {
617 int pmtlen;
618 prompt_this_line = strrchr (rl_display_prompt, '\n');
619 if (!prompt_this_line)
620 prompt_this_line = rl_display_prompt;
621 else
622 {
623 prompt_this_line++;
624 pmtlen = prompt_this_line - rl_display_prompt; /* temp var */
625 if (forced_display)
626 {
627 _rl_output_some_chars (rl_display_prompt, pmtlen);
628 /* Make sure we are at column zero even after a newline,
629 regardless of the state of terminal output processing. */
630 if (pmtlen < 2 || prompt_this_line[-2] != '\r')
631 cr ();
632 }
633 }
634
635 prompt_physical_chars = pmtlen = strlen (prompt_this_line);
636 temp = pmtlen + out + 2;
637 if (temp >= line_size)
638 {
639 line_size = (temp + 1024) - (temp % 1024);
640 visible_line = (char *)xrealloc (visible_line, line_size);
641 line = invisible_line = (char *)xrealloc (invisible_line, line_size);
642 }
643 strncpy (line + out, prompt_this_line, pmtlen);
644 out += pmtlen;
645 line[out] = '\0';
646 wrap_offset = prompt_invis_chars_first_line = 0;
647 }
648
649 #define CHECK_INV_LBREAKS() \
650 do { \
651 if (newlines >= (inv_lbsize - 2)) \
652 { \
653 inv_lbsize *= 2; \
654 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
655 } \
656 } while (0)
657
658 #if defined (HANDLE_MULTIBYTE)
659 #define CHECK_LPOS() \
660 do { \
661 lpos++; \
662 if (lpos >= _rl_screenwidth) \
663 { \
664 if (newlines >= (inv_lbsize - 2)) \
665 { \
666 inv_lbsize *= 2; \
667 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
668 } \
669 inv_lbreaks[++newlines] = out; \
670 if (newlines >= (line_state_invisible->wbsize - 1)) \
671 { \
672 line_state_invisible->wbsize *= 2; \
673 line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
674 } \
675 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
676 lpos = 0; \
677 } \
678 } while (0)
679 #else
680 #define CHECK_LPOS() \
681 do { \
682 lpos++; \
683 if (lpos >= _rl_screenwidth) \
684 { \
685 if (newlines >= (inv_lbsize - 2)) \
686 { \
687 inv_lbsize *= 2; \
688 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
689 } \
690 inv_lbreaks[++newlines] = out; \
691 lpos = 0; \
692 } \
693 } while (0)
694 #endif
695
696 /* inv_lbreaks[i] is where line i starts in the buffer. */
697 inv_lbreaks[newlines = 0] = 0;
698 lpos = prompt_physical_chars + modmark;
699
700 #if defined (HANDLE_MULTIBYTE)
701 memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
702 num = 0;
703 #endif
704
705 /* prompt_invis_chars_first_line is the number of invisible characters in
706 the first physical line of the prompt.
707 wrap_offset - prompt_invis_chars_first_line is the number of invis
708 chars on the second (or, more generally, last) line. */
709
710 /* This is zero-based, used to set the newlines */
711 prompt_lines_estimate = lpos / _rl_screenwidth;
712
713 /* what if lpos is already >= _rl_screenwidth before we start drawing the
714 contents of the command line? */
715 while (lpos >= _rl_screenwidth)
716 {
717 int z;
718 /* fix from Darin Johnson <darin@acuson.com> for prompt string with
719 invisible characters that is longer than the screen width. The
720 prompt_invis_chars_first_line variable could be made into an array
721 saying how many invisible characters there are per line, but that's
722 probably too much work for the benefit gained. How many people have
723 prompts that exceed two physical lines?
724 Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
725 #if defined (HANDLE_MULTIBYTE)
726 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
727 {
728 n0 = num;
729 temp = local_prompt_len;
730 while (num < temp)
731 {
732 z = _rl_col_width (local_prompt, n0, num, 1);
733 if (z > _rl_screenwidth)
734 {
735 num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
736 break;
737 }
738 else if (z == _rl_screenwidth)
739 break;
740 num++;
741 }
742 temp = num;
743 }
744 else
745 #endif /* !HANDLE_MULTIBYTE */
746 temp = ((newlines + 1) * _rl_screenwidth);
747
748 /* Now account for invisible characters in the current line. */
749 /* XXX - this assumes that the invisible characters may be split, but only
750 between the first and the last lines. */
751 temp += (newlines == 0) ? prompt_invis_chars_first_line
752 : ((newlines == prompt_lines_estimate) ? wrap_offset : prompt_invis_chars_first_line);
753
754 inv_lbreaks[++newlines] = temp;
755 #if defined (HANDLE_MULTIBYTE)
756 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
757 lpos -= _rl_col_width (local_prompt, n0, num, 1);
758 else
759 #endif
760 lpos -= _rl_screenwidth;
761 }
762
763 prompt_last_screen_line = newlines;
764
765 /* Draw the rest of the line (after the prompt) into invisible_line, keeping
766 track of where the cursor is (cpos_buffer_position), the number of the line containing
767 the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
768 It maintains an array of line breaks for display (inv_lbreaks).
769 This handles expanding tabs for display and displaying meta characters. */
770 lb_linenum = 0;
771 #if defined (HANDLE_MULTIBYTE)
772 in = 0;
773 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
774 {
775 memset (&ps, 0, sizeof (mbstate_t));
776 /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
777 wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
778 }
779 else
780 wc_bytes = 1;
781 while (in < rl_end)
782 #else
783 for (in = 0; in < rl_end; in++)
784 #endif
785 {
786 c = (unsigned char)rl_line_buffer[in];
787
788 #if defined (HANDLE_MULTIBYTE)
789 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
790 {
791 if (MB_INVALIDCH (wc_bytes))
792 {
793 /* Byte sequence is invalid or shortened. Assume that the
794 first byte represents a character. */
795 wc_bytes = 1;
796 /* Assume that a character occupies a single column. */
797 wc_width = 1;
798 memset (&ps, 0, sizeof (mbstate_t));
799 }
800 else if (MB_NULLWCH (wc_bytes))
801 break; /* Found '\0' */
802 else
803 {
804 temp = WCWIDTH (wc);
805 wc_width = (temp >= 0) ? temp : 1;
806 }
807 }
808 #endif
809
810 if (out + 8 >= line_size) /* XXX - 8 for \t */
811 {
812 line_size *= 2;
813 visible_line = (char *)xrealloc (visible_line, line_size);
814 invisible_line = (char *)xrealloc (invisible_line, line_size);
815 line = invisible_line;
816 }
817
818 if (in == rl_point)
819 {
820 cpos_buffer_position = out;
821 lb_linenum = newlines;
822 }
823
824 #if defined (HANDLE_MULTIBYTE)
825 if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
826 #else
827 if (META_CHAR (c))
828 #endif
829 {
830 if (_rl_output_meta_chars == 0)
831 {
832 sprintf (line + out, "\\%o", c);
833
834 if (lpos + 4 >= _rl_screenwidth)
835 {
836 temp = _rl_screenwidth - lpos;
837 CHECK_INV_LBREAKS ();
838 inv_lbreaks[++newlines] = out + temp;
839 lpos = 4 - temp;
840 }
841 else
842 lpos += 4;
843
844 out += 4;
845 }
846 else
847 {
848 line[out++] = c;
849 CHECK_LPOS();
850 }
851 }
852 #if defined (DISPLAY_TABS)
853 else if (c == '\t')
854 {
855 register int newout;
856
857 #if 0
858 newout = (out | (int)7) + 1;
859 #else
860 newout = out + 8 - lpos % 8;
861 #endif
862 temp = newout - out;
863 if (lpos + temp >= _rl_screenwidth)
864 {
865 register int temp2;
866 temp2 = _rl_screenwidth - lpos;
867 CHECK_INV_LBREAKS ();
868 inv_lbreaks[++newlines] = out + temp2;
869 lpos = temp - temp2;
870 while (out < newout)
871 line[out++] = ' ';
872 }
873 else
874 {
875 while (out < newout)
876 line[out++] = ' ';
877 lpos += temp;
878 }
879 }
880 #endif
881 else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
882 {
883 line[out++] = '\0'; /* XXX - sentinel */
884 CHECK_INV_LBREAKS ();
885 inv_lbreaks[++newlines] = out;
886 lpos = 0;
887 }
888 else if (CTRL_CHAR (c) || c == RUBOUT)
889 {
890 line[out++] = '^';
891 CHECK_LPOS();
892 line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
893 CHECK_LPOS();
894 }
895 else
896 {
897 #if defined (HANDLE_MULTIBYTE)
898 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
899 {
900 register int i;
901
902 _rl_wrapped_multicolumn = 0;
903
904 if (_rl_screenwidth < lpos + wc_width)
905 for (i = lpos; i < _rl_screenwidth; i++)
906 {
907 /* The space will be removed in update_line() */
908 line[out++] = ' ';
909 _rl_wrapped_multicolumn++;
910 CHECK_LPOS();
911 }
912 if (in == rl_point)
913 {
914 cpos_buffer_position = out;
915 lb_linenum = newlines;
916 }
917 for (i = in; i < in+wc_bytes; i++)
918 line[out++] = rl_line_buffer[i];
919 for (i = 0; i < wc_width; i++)
920 CHECK_LPOS();
921 }
922 else
923 {
924 line[out++] = c;
925 CHECK_LPOS();
926 }
927 #else
928 line[out++] = c;
929 CHECK_LPOS();
930 #endif
931 }
932
933 #if defined (HANDLE_MULTIBYTE)
934 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
935 {
936 in += wc_bytes;
937 /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
938 wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
939 }
940 else
941 in++;
942 #endif
943
944 }
945 line[out] = '\0';
946 if (cpos_buffer_position < 0)
947 {
948 cpos_buffer_position = out;
949 lb_linenum = newlines;
950 }
951
952 inv_botlin = lb_botlin = newlines;
953 CHECK_INV_LBREAKS ();
954 inv_lbreaks[newlines+1] = out;
955 cursor_linenum = lb_linenum;
956
957 /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
958 CURSOR_LINENUM == line number where the cursor should be placed. */
959
960 /* PWP: now is when things get a bit hairy. The visible and invisible
961 line buffers are really multiple lines, which would wrap every
962 (screenwidth - 1) characters. Go through each in turn, finding
963 the changed region and updating it. The line order is top to bottom. */
964
965 /* If we can move the cursor up and down, then use multiple lines,
966 otherwise, let long lines display in a single terminal line, and
967 horizontally scroll it. */
968 displaying_prompt_first_line = 1;
969 if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
970 {
971 int nleft, pos, changed_screen_line, tx;
972
973 if (!rl_display_fixed || forced_display)
974 {
975 forced_display = 0;
976
977 /* If we have more than a screenful of material to display, then
978 only display a screenful. We should display the last screen,
979 not the first. */
980 if (out >= _rl_screenchars)
981 {
982 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
983 out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
984 else
985 out = _rl_screenchars - 1;
986 }
987
988 /* The first line is at character position 0 in the buffer. The
989 second and subsequent lines start at inv_lbreaks[N], offset by
990 OFFSET (which has already been calculated above). */
991
992 #define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
993 #define WRAP_OFFSET(line, offset) ((line == 0) \
994 ? (offset ? INVIS_FIRST() : 0) \
995 : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
996 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
997 #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
998 #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
999 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
1000 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
1001 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
1002
1003 #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
1004 _rl_last_c_pos != o_cpos && \
1005 _rl_last_c_pos > wrap_offset && \
1006 o_cpos < prompt_last_invisible)
1007
1008 /* For each line in the buffer, do the updating display. */
1009 for (linenum = 0; linenum <= inv_botlin; linenum++)
1010 {
1011 /* This can lead us astray if we execute a program that changes
1012 the locale from a non-multibyte to a multibyte one. */
1013 o_cpos = _rl_last_c_pos;
1014 cpos_adjusted = 0;
1015 update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
1016 VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
1017
1018 /* update_line potentially changes _rl_last_c_pos, but doesn't
1019 take invisible characters into account, since _rl_last_c_pos
1020 is an absolute cursor position in a multibyte locale. See
1021 if compensating here is the right thing, or if we have to
1022 change update_line itself. There are several cases in which
1023 update_line adjusts _rl_last_c_pos itself (so it can pass
1024 _rl_move_cursor_relative accurate values); it communicates
1025 this back by setting cpos_adjusted. If we assume that
1026 _rl_last_c_pos is correct (an absolute cursor position) each
1027 time update_line is called, then we can assume in our
1028 calculations that o_cpos does not need to be adjusted by
1029 wrap_offset. */
1030 if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
1031 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1032 else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
1033 (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
1034 cpos_adjusted == 0 &&
1035 _rl_last_c_pos != o_cpos &&
1036 _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
1037 _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
1038
1039 /* If this is the line with the prompt, we might need to
1040 compensate for invisible characters in the new line. Do
1041 this only if there is not more than one new line (which
1042 implies that we completely overwrite the old visible line)
1043 and the new line is shorter than the old. Make sure we are
1044 at the end of the new line before clearing. */
1045 if (linenum == 0 &&
1046 inv_botlin == 0 && _rl_last_c_pos == out &&
1047 (wrap_offset > visible_wrap_offset) &&
1048 (_rl_last_c_pos < visible_first_line_len))
1049 {
1050 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1051 nleft = _rl_screenwidth - _rl_last_c_pos;
1052 else
1053 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1054 if (nleft)
1055 _rl_clear_to_eol (nleft);
1056 }
1057 #if 0
1058 /* This segment is intended to handle the case where the prompt
1059 has invisible characters on the second line and the new line
1060 to be displayed needs to clear the rest of the old characters
1061 out (e.g., when printing the i-search prompt). In general,
1062 the case of the new line being shorter than the old.
1063 Incomplete */
1064 else if (linenum == prompt_last_screen_line &&
1065 prompt_physical_chars > _rl_screenwidth &&
1066 wrap_offset != prompt_invis_chars_first_line &&
1067 _rl_last_c_pos == out &&
1068 #endif
1069
1070
1071 /* Since the new first line is now visible, save its length. */
1072 if (linenum == 0)
1073 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
1074 }
1075
1076 /* We may have deleted some lines. If so, clear the left over
1077 blank ones at the bottom out. */
1078 if (_rl_vis_botlin > inv_botlin)
1079 {
1080 char *tt;
1081 for (; linenum <= _rl_vis_botlin; linenum++)
1082 {
1083 tt = VIS_CHARS (linenum);
1084 _rl_move_vert (linenum);
1085 _rl_move_cursor_relative (0, tt);
1086 _rl_clear_to_eol
1087 ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
1088 }
1089 }
1090 _rl_vis_botlin = inv_botlin;
1091
1092 /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
1093 different screen line during this redisplay. */
1094 changed_screen_line = _rl_last_v_pos != cursor_linenum;
1095 if (changed_screen_line)
1096 {
1097 _rl_move_vert (cursor_linenum);
1098 /* If we moved up to the line with the prompt using _rl_term_up,
1099 the physical cursor position on the screen stays the same,
1100 but the buffer position needs to be adjusted to account
1101 for invisible characters. */
1102 if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
1103 _rl_last_c_pos += wrap_offset;
1104 }
1105
1106 /* We have to reprint the prompt if it contains invisible
1107 characters, since it's not generally OK to just reprint
1108 the characters from the current cursor position. But we
1109 only need to reprint it if the cursor is before the last
1110 invisible character in the prompt string. */
1111 nleft = prompt_visible_length + wrap_offset;
1112 if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1113 #if 0
1114 _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
1115 #else
1116 _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1117 #endif
1118 {
1119 #if defined (__MSDOS__)
1120 putc ('\r', rl_outstream);
1121 #else
1122 if (_rl_term_cr)
1123 tputs (_rl_term_cr, 1, _rl_output_character_function);
1124 #endif
1125 if (modmark)
1126 _rl_output_some_chars ("*", 1);
1127
1128 _rl_output_some_chars (local_prompt, nleft);
1129 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1130 _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
1131 else
1132 _rl_last_c_pos = nleft + modmark;
1133 }
1134
1135 /* Where on that line? And where does that line start
1136 in the buffer? */
1137 pos = inv_lbreaks[cursor_linenum];
1138 /* nleft == number of characters in the line buffer between the
1139 start of the line and the desired cursor position. */
1140 nleft = cpos_buffer_position - pos;
1141
1142 /* NLEFT is now a number of characters in a buffer. When in a
1143 multibyte locale, however, _rl_last_c_pos is an absolute cursor
1144 position that doesn't take invisible characters in the prompt
1145 into account. We use a fudge factor to compensate. */
1146
1147 /* Since _rl_backspace() doesn't know about invisible characters in the
1148 prompt, and there's no good way to tell it, we compensate for
1149 those characters here and call _rl_backspace() directly. */
1150 if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
1151 {
1152 /* TX == new physical cursor position in multibyte locale. */
1153 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1154 tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
1155 else
1156 tx = nleft;
1157 if (tx >= 0 && _rl_last_c_pos > tx)
1158 {
1159 _rl_backspace (_rl_last_c_pos - tx); /* XXX */
1160 _rl_last_c_pos = tx;
1161 }
1162 }
1163
1164 /* We need to note that in a multibyte locale we are dealing with
1165 _rl_last_c_pos as an absolute cursor position, but moving to a
1166 point specified by a buffer position (NLEFT) that doesn't take
1167 invisible characters into account. */
1168 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1169 _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1170 else if (nleft != _rl_last_c_pos)
1171 _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1172 }
1173 }
1174 else /* Do horizontal scrolling. */
1175 {
1176 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
1177 int lmargin, ndisp, nleft, phys_c_pos, t;
1178
1179 /* Always at top line. */
1180 _rl_last_v_pos = 0;
1181
1182 /* Compute where in the buffer the displayed line should start. This
1183 will be LMARGIN. */
1184
1185 /* The number of characters that will be displayed before the cursor. */
1186 ndisp = cpos_buffer_position - wrap_offset;
1187 nleft = prompt_visible_length + wrap_offset;
1188 /* Where the new cursor position will be on the screen. This can be
1189 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1190 phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
1191 t = _rl_screenwidth / 3;
1192
1193 /* If the number of characters had already exceeded the screenwidth,
1194 last_lmargin will be > 0. */
1195
1196 /* If the number of characters to be displayed is more than the screen
1197 width, compute the starting offset so that the cursor is about
1198 two-thirds of the way across the screen. */
1199 if (phys_c_pos > _rl_screenwidth - 2)
1200 {
1201 lmargin = cpos_buffer_position - (2 * t);
1202 if (lmargin < 0)
1203 lmargin = 0;
1204 /* If the left margin would be in the middle of a prompt with
1205 invisible characters, don't display the prompt at all. */
1206 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1207 lmargin = nleft;
1208 }
1209 else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
1210 lmargin = 0;
1211 else if (phys_c_pos < 1)
1212 {
1213 /* If we are moving back towards the beginning of the line and
1214 the last margin is no longer correct, compute a new one. */
1215 lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */
1216 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1217 lmargin = nleft;
1218 }
1219 else
1220 lmargin = last_lmargin;
1221
1222 displaying_prompt_first_line = lmargin < nleft;
1223
1224 /* If the first character on the screen isn't the first character
1225 in the display line, indicate this with a special character. */
1226 if (lmargin > 0)
1227 line[lmargin] = '<';
1228
1229 /* If SCREENWIDTH characters starting at LMARGIN do not encompass
1230 the whole line, indicate that with a special character at the
1231 right edge of the screen. If LMARGIN is 0, we need to take the
1232 wrap offset into account. */
1233 t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1234 if (t < out)
1235 line[t - 1] = '>';
1236
1237 if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
1238 {
1239 forced_display = 0;
1240 o_cpos = _rl_last_c_pos;
1241 cpos_adjusted = 0;
1242 update_line (&visible_line[last_lmargin],
1243 &invisible_line[lmargin],
1244 0,
1245 _rl_screenwidth + visible_wrap_offset,
1246 _rl_screenwidth + (lmargin ? 0 : wrap_offset),
1247 0);
1248
1249 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
1250 displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
1251 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1252
1253 /* If the visible new line is shorter than the old, but the number
1254 of invisible characters is greater, and we are at the end of
1255 the new line, we need to clear to eol. */
1256 t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
1257 if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
1258 (_rl_last_c_pos == out) && displaying_prompt_first_line &&
1259 t < visible_first_line_len)
1260 {
1261 nleft = _rl_screenwidth - t;
1262 _rl_clear_to_eol (nleft);
1263 }
1264 visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
1265 if (visible_first_line_len > _rl_screenwidth)
1266 visible_first_line_len = _rl_screenwidth;
1267
1268 _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
1269 last_lmargin = lmargin;
1270 }
1271 }
1272 fflush (rl_outstream);
1273
1274 /* Swap visible and non-visible lines. */
1275 {
1276 struct line_state *vtemp = line_state_visible;
1277
1278 line_state_visible = line_state_invisible;
1279 line_state_invisible = vtemp;
1280
1281 rl_display_fixed = 0;
1282 /* If we are displaying on a single line, and last_lmargin is > 0, we
1283 are not displaying any invisible characters, so set visible_wrap_offset
1284 to 0. */
1285 if (_rl_horizontal_scroll_mode && last_lmargin)
1286 visible_wrap_offset = 0;
1287 else
1288 visible_wrap_offset = wrap_offset;
1289 }
1290
1291 RL_UNSETSTATE (RL_STATE_REDISPLAYING);
1292 _rl_release_sigint ();
1293 }
1294
1295 /* PWP: update_line() is based on finding the middle difference of each
1296 line on the screen; vis:
1297
1298 /old first difference
1299 /beginning of line | /old last same /old EOL
1300 v v v v
1301 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1302 new: eddie> Oh, my little buggy says to me, as lurgid as
1303 ^ ^ ^ ^
1304 \beginning of line | \new last same \new end of line
1305 \new first difference
1306
1307 All are character pointers for the sake of speed. Special cases for
1308 no differences, as well as for end of line additions must be handled.
1309
1310 Could be made even smarter, but this works well enough */
1311 static void
1312 update_line (old, new, current_line, omax, nmax, inv_botlin)
1313 register char *old, *new;
1314 int current_line, omax, nmax, inv_botlin;
1315 {
1316 register char *ofd, *ols, *oe, *nfd, *nls, *ne;
1317 int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
1318 int current_invis_chars;
1319 int col_lendiff, col_temp;
1320 int bytes_to_insert;
1321 #if defined (HANDLE_MULTIBYTE)
1322 mbstate_t ps_new, ps_old;
1323 int new_offset, old_offset;
1324 #endif
1325
1326 /* If we're at the right edge of a terminal that supports xn, we're
1327 ready to wrap around, so do so. This fixes problems with knowing
1328 the exact cursor position and cut-and-paste with certain terminal
1329 emulators. In this calculation, TEMP is the physical screen
1330 position of the cursor. */
1331 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1332 temp = _rl_last_c_pos;
1333 else
1334 temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
1335 if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1336 && _rl_last_v_pos == current_line - 1)
1337 {
1338 #if defined (HANDLE_MULTIBYTE)
1339 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1340 {
1341 wchar_t wc;
1342 mbstate_t ps;
1343 int tempwidth, bytes;
1344 size_t ret;
1345
1346 /* This fixes only double-column characters, but if the wrapped
1347 character consumes more than three columns, spaces will be
1348 inserted in the string buffer. */
1349 if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0)
1350 _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
1351
1352 memset (&ps, 0, sizeof (mbstate_t));
1353 ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
1354 if (MB_INVALIDCH (ret))
1355 {
1356 tempwidth = 1;
1357 ret = 1;
1358 }
1359 else if (MB_NULLWCH (ret))
1360 tempwidth = 0;
1361 else
1362 tempwidth = WCWIDTH (wc);
1363
1364 if (tempwidth > 0)
1365 {
1366 int count, i;
1367 bytes = ret;
1368 for (count = 0; count < bytes; count++)
1369 putc (new[count], rl_outstream);
1370 _rl_last_c_pos = tempwidth;
1371 _rl_last_v_pos++;
1372 memset (&ps, 0, sizeof (mbstate_t));
1373 ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
1374 if (ret != 0 && bytes != 0)
1375 {
1376 if (MB_INVALIDCH (ret))
1377 ret = 1;
1378 memmove (old+bytes, old+ret, strlen (old+ret));
1379 memcpy (old, new, bytes);
1380 /* Fix up indices if we copy data from one line to another */
1381 omax += bytes - ret;
1382 for (i = current_line+1; i <= inv_botlin+1; i++)
1383 vis_lbreaks[i] += bytes - ret;
1384 }
1385 }
1386 else
1387 {
1388 putc (' ', rl_outstream);
1389 _rl_last_c_pos = 1;
1390 _rl_last_v_pos++;
1391 if (old[0] && new[0])
1392 old[0] = new[0];
1393 }
1394 }
1395 else
1396 #endif
1397 {
1398 if (new[0])
1399 putc (new[0], rl_outstream);
1400 else
1401 putc (' ', rl_outstream);
1402 _rl_last_c_pos = 1;
1403 _rl_last_v_pos++;
1404 if (old[0] && new[0])
1405 old[0] = new[0];
1406 }
1407 }
1408
1409
1410 /* Find first difference. */
1411 #if defined (HANDLE_MULTIBYTE)
1412 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1413 {
1414 /* See if the old line is a subset of the new line, so that the
1415 only change is adding characters. */
1416 temp = (omax < nmax) ? omax : nmax;
1417 if (memcmp (old, new, temp) == 0) /* adding at the end */
1418 {
1419 new_offset = old_offset = temp;
1420 ofd = old + temp;
1421 nfd = new + temp;
1422 }
1423 else
1424 {
1425 memset (&ps_new, 0, sizeof(mbstate_t));
1426 memset (&ps_old, 0, sizeof(mbstate_t));
1427
1428 if (omax == nmax && STREQN (new, old, omax))
1429 {
1430 old_offset = omax;
1431 new_offset = nmax;
1432 ofd = old + omax;
1433 nfd = new + nmax;
1434 }
1435 else
1436 {
1437 new_offset = old_offset = 0;
1438 for (ofd = old, nfd = new;
1439 (ofd - old < omax) && *ofd &&
1440 _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
1441 {
1442 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1443 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1444
1445 ofd = old + old_offset;
1446 nfd = new + new_offset;
1447 }
1448 }
1449 }
1450 }
1451 else
1452 #endif
1453 for (ofd = old, nfd = new;
1454 (ofd - old < omax) && *ofd && (*ofd == *nfd);
1455 ofd++, nfd++)
1456 ;
1457
1458 /* Move to the end of the screen line. ND and OD are used to keep track
1459 of the distance between ne and new and oe and old, respectively, to
1460 move a subtraction out of each loop. */
1461 for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1462 for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1463
1464 /* If no difference, continue to next line. */
1465 if (ofd == oe && nfd == ne)
1466 return;
1467
1468 #if defined (HANDLE_MULTIBYTE)
1469 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
1470 {
1471 wchar_t wc;
1472 mbstate_t ps = { 0 };
1473 int t;
1474
1475 /* If the first character in the difference is a zero-width character,
1476 assume it's a combining character and back one up so the two base
1477 characters no longer compare equivalently. */
1478 t = mbrtowc (&wc, ofd, MB_CUR_MAX, &ps);
1479 if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
1480 {
1481 old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
1482 new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
1483 ofd = old + old_offset; /* equal by definition */
1484 nfd = new + new_offset;
1485 }
1486 }
1487 #endif
1488
1489 wsatend = 1; /* flag for trailing whitespace */
1490
1491 #if defined (HANDLE_MULTIBYTE)
1492 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1493 {
1494 ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1495 nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1496
1497 while ((ols > ofd) && (nls > nfd))
1498 {
1499 memset (&ps_old, 0, sizeof (mbstate_t));
1500 memset (&ps_new, 0, sizeof (mbstate_t));
1501
1502 #if 0
1503 /* On advice from jir@yamato.ibm.com */
1504 _rl_adjust_point (old, ols - old, &ps_old);
1505 _rl_adjust_point (new, nls - new, &ps_new);
1506 #endif
1507
1508 if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
1509 break;
1510
1511 if (*ols == ' ')
1512 wsatend = 0;
1513
1514 ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1515 nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1516 }
1517 }
1518 else
1519 {
1520 #endif /* HANDLE_MULTIBYTE */
1521 ols = oe - 1; /* find last same */
1522 nls = ne - 1;
1523 while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
1524 {
1525 if (*ols != ' ')
1526 wsatend = 0;
1527 ols--;
1528 nls--;
1529 }
1530 #if defined (HANDLE_MULTIBYTE)
1531 }
1532 #endif
1533
1534 if (wsatend)
1535 {
1536 ols = oe;
1537 nls = ne;
1538 }
1539 #if defined (HANDLE_MULTIBYTE)
1540 /* This may not work for stateful encoding, but who cares? To handle
1541 stateful encoding properly, we have to scan each string from the
1542 beginning and compare. */
1543 else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
1544 #else
1545 else if (*ols != *nls)
1546 #endif
1547 {
1548 if (*ols) /* don't step past the NUL */
1549 {
1550 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1551 ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
1552 else
1553 ols++;
1554 }
1555 if (*nls)
1556 {
1557 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1558 nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
1559 else
1560 nls++;
1561 }
1562 }
1563
1564 /* count of invisible characters in the current invisible line. */
1565 current_invis_chars = W_OFFSET (current_line, wrap_offset);
1566 if (_rl_last_v_pos != current_line)
1567 {
1568 _rl_move_vert (current_line);
1569 if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
1570 _rl_last_c_pos += visible_wrap_offset;
1571 }
1572
1573 /* If this is the first line and there are invisible characters in the
1574 prompt string, and the prompt string has not changed, and the current
1575 cursor position is before the last invisible character in the prompt,
1576 and the index of the character to move to is past the end of the prompt
1577 string, then redraw the entire prompt string. We can only do this
1578 reliably if the terminal supports a `cr' capability.
1579
1580 This is not an efficiency hack -- there is a problem with redrawing
1581 portions of the prompt string if they contain terminal escape
1582 sequences (like drawing the `unbold' sequence without a corresponding
1583 `bold') that manifests itself on certain terminals. */
1584
1585 lendiff = local_prompt_len;
1586 od = ofd - old; /* index of first difference in visible line */
1587 if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1588 _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1589 od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
1590 {
1591 #if defined (__MSDOS__)
1592 putc ('\r', rl_outstream);
1593 #else
1594 tputs (_rl_term_cr, 1, _rl_output_character_function);
1595 #endif
1596 if (modmark)
1597 _rl_output_some_chars ("*", 1);
1598 _rl_output_some_chars (local_prompt, lendiff);
1599 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1600 {
1601 /* We take wrap_offset into account here so we can pass correct
1602 information to _rl_move_cursor_relative. */
1603 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
1604 cpos_adjusted = 1;
1605 }
1606 else
1607 _rl_last_c_pos = lendiff + modmark;
1608 }
1609
1610 o_cpos = _rl_last_c_pos;
1611
1612 /* When this function returns, _rl_last_c_pos is correct, and an absolute
1613 cursor position in multibyte mode, but a buffer index when not in a
1614 multibyte locale. */
1615 _rl_move_cursor_relative (od, old);
1616
1617 #if defined (HANDLE_MULTIBYTE)
1618 /* We need to indicate that the cursor position is correct in the presence of
1619 invisible characters in the prompt string. Let's see if setting this when
1620 we make sure we're at the end of the drawn prompt string works. */
1621 if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
1622 (_rl_last_c_pos > 0 || o_cpos > 0) &&
1623 _rl_last_c_pos == prompt_physical_chars)
1624 cpos_adjusted = 1;
1625 #endif
1626
1627 /* if (len (new) > len (old))
1628 lendiff == difference in buffer (bytes)
1629 col_lendiff == difference on screen (columns)
1630 When not using multibyte characters, these are equal */
1631 lendiff = (nls - nfd) - (ols - ofd);
1632 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1633 col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
1634 else
1635 col_lendiff = lendiff;
1636
1637 /* If we are changing the number of invisible characters in a line, and
1638 the spot of first difference is before the end of the invisible chars,
1639 lendiff needs to be adjusted. */
1640 if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1641 current_invis_chars != visible_wrap_offset)
1642 {
1643 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1644 {
1645 lendiff += visible_wrap_offset - current_invis_chars;
1646 col_lendiff += visible_wrap_offset - current_invis_chars;
1647 }
1648 else
1649 {
1650 lendiff += visible_wrap_offset - current_invis_chars;
1651 col_lendiff = lendiff;
1652 }
1653 }
1654
1655 /* We use temp as a count of the number of bytes from the first difference
1656 to the end of the new line. col_temp is the corresponding number of
1657 screen columns. A `dumb' update moves to the spot of first difference
1658 and writes TEMP bytes. */
1659 /* Insert (diff (len (old), len (new)) ch. */
1660 temp = ne - nfd;
1661 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1662 col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
1663 else
1664 col_temp = temp;
1665
1666 /* how many bytes from the new line buffer to write to the display */
1667 bytes_to_insert = nls - nfd;
1668
1669 /* col_lendiff > 0 if we are adding characters to the line */
1670 if (col_lendiff > 0) /* XXX - was lendiff */
1671 {
1672 /* Non-zero if we're increasing the number of lines. */
1673 int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1674 /* If col_lendiff is > 0, implying that the new string takes up more
1675 screen real estate than the old, but lendiff is < 0, meaning that it
1676 takes fewer bytes, we need to just output the characters starting
1677 from the first difference. These will overwrite what is on the
1678 display, so there's no reason to do a smart update. This can really
1679 only happen in a multibyte environment. */
1680 if (lendiff < 0)
1681 {
1682 _rl_output_some_chars (nfd, temp);
1683 _rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
1684 /* If nfd begins before any invisible characters in the prompt,
1685 adjust _rl_last_c_pos to account for wrap_offset and set
1686 cpos_adjusted to let the caller know. */
1687 if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1688 {
1689 _rl_last_c_pos -= wrap_offset;
1690 cpos_adjusted = 1;
1691 }
1692 return;
1693 }
1694 /* Sometimes it is cheaper to print the characters rather than
1695 use the terminal's capabilities. If we're growing the number
1696 of lines, make sure we actually cause the new line to wrap
1697 around on auto-wrapping terminals. */
1698 else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
1699 {
1700 /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
1701 _rl_horizontal_scroll_mode == 1, inserting the characters with
1702 _rl_term_IC or _rl_term_ic will screw up the screen because of the
1703 invisible characters. We need to just draw them. */
1704 /* The same thing happens if we're trying to draw before the last
1705 invisible character in the prompt string or we're increasing the
1706 number of invisible characters in the line and we're not drawing
1707 the entire prompt string. */
1708 if (*ols && ((_rl_horizontal_scroll_mode &&
1709 _rl_last_c_pos == 0 &&
1710 lendiff > prompt_visible_length &&
1711 current_invis_chars > 0) == 0) &&
1712 (((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
1713 current_line == 0 && wrap_offset &&
1714 ((nfd - new) <= prompt_last_invisible) &&
1715 (col_lendiff < prompt_visible_length)) == 0) &&
1716 (visible_wrap_offset >= current_invis_chars))
1717 {
1718 open_some_spaces (col_lendiff);
1719 _rl_output_some_chars (nfd, bytes_to_insert);
1720 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1721 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
1722 else
1723 _rl_last_c_pos += bytes_to_insert;
1724 }
1725 else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
1726 {
1727 /* At the end of a line the characters do not have to
1728 be "inserted". They can just be placed on the screen. */
1729 _rl_output_some_chars (nfd, temp);
1730 _rl_last_c_pos += col_temp;
1731 return;
1732 }
1733 else /* just write from first difference to end of new line */
1734 {
1735 _rl_output_some_chars (nfd, temp);
1736 _rl_last_c_pos += col_temp;
1737 /* If nfd begins before the last invisible character in the
1738 prompt, adjust _rl_last_c_pos to account for wrap_offset
1739 and set cpos_adjusted to let the caller know. */
1740 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1741 {
1742 _rl_last_c_pos -= wrap_offset;
1743 cpos_adjusted = 1;
1744 }
1745 return;
1746 }
1747
1748 if (bytes_to_insert > lendiff)
1749 {
1750 /* If nfd begins before the last invisible character in the
1751 prompt, adjust _rl_last_c_pos to account for wrap_offset
1752 and set cpos_adjusted to let the caller know. */
1753 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1754 {
1755 _rl_last_c_pos -= wrap_offset;
1756 cpos_adjusted = 1;
1757 }
1758 }
1759 }
1760 else
1761 {
1762 /* cannot insert chars, write to EOL */
1763 _rl_output_some_chars (nfd, temp);
1764 _rl_last_c_pos += col_temp;
1765 /* If we're in a multibyte locale and were before the last invisible
1766 char in the current line (which implies we just output some invisible
1767 characters) we need to adjust _rl_last_c_pos, since it represents
1768 a physical character position. */
1769 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
1770 current_line == prompt_last_screen_line && wrap_offset &&
1771 displaying_prompt_first_line &&
1772 wrap_offset != prompt_invis_chars_first_line &&
1773 ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth))))
1774 {
1775 _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
1776 cpos_adjusted = 1;
1777 }
1778 }
1779 }
1780 else /* Delete characters from line. */
1781 {
1782 /* If possible and inexpensive to use terminal deletion, then do so. */
1783 if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
1784 {
1785 /* If all we're doing is erasing the invisible characters in the
1786 prompt string, don't bother. It screws up the assumptions
1787 about what's on the screen. */
1788 if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
1789 displaying_prompt_first_line &&
1790 -lendiff == visible_wrap_offset)
1791 col_lendiff = 0;
1792
1793 /* If we have moved lmargin and we're shrinking the line, we've
1794 already moved the cursor to the first character of the new line,
1795 so deleting -col_lendiff characters will mess up the cursor
1796 position calculation */
1797 if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
1798 col_lendiff && _rl_last_c_pos < -col_lendiff)
1799 col_lendiff = 0;
1800
1801 if (col_lendiff)
1802 delete_chars (-col_lendiff); /* delete (diff) characters */
1803
1804 /* Copy (new) chars to screen from first diff to last match,
1805 overwriting what is there. */
1806 if (bytes_to_insert > 0)
1807 {
1808 /* If nfd begins at the prompt, or before the invisible
1809 characters in the prompt, we need to adjust _rl_last_c_pos
1810 in a multibyte locale to account for the wrap offset and
1811 set cpos_adjusted accordingly. */
1812 _rl_output_some_chars (nfd, bytes_to_insert);
1813 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1814 {
1815 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
1816 if (current_line == 0 && wrap_offset &&
1817 displaying_prompt_first_line &&
1818 _rl_last_c_pos > wrap_offset &&
1819 ((nfd - new) <= prompt_last_invisible))
1820 {
1821 _rl_last_c_pos -= wrap_offset;
1822 cpos_adjusted = 1;
1823 }
1824 }
1825 else
1826 _rl_last_c_pos += bytes_to_insert;
1827
1828 if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
1829 goto clear_rest_of_line;
1830 }
1831 }
1832 /* Otherwise, print over the existing material. */
1833 else
1834 {
1835 if (temp > 0)
1836 {
1837 /* If nfd begins at the prompt, or before the invisible
1838 characters in the prompt, we need to adjust _rl_last_c_pos
1839 in a multibyte locale to account for the wrap offset and
1840 set cpos_adjusted accordingly. */
1841 _rl_output_some_chars (nfd, temp);
1842 _rl_last_c_pos += col_temp; /* XXX */
1843 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1844 {
1845 if (current_line == 0 && wrap_offset &&
1846 displaying_prompt_first_line &&
1847 _rl_last_c_pos > wrap_offset &&
1848 ((nfd - new) <= prompt_last_invisible))
1849 {
1850 _rl_last_c_pos -= wrap_offset;
1851 cpos_adjusted = 1;
1852 }
1853 }
1854 }
1855 clear_rest_of_line:
1856 lendiff = (oe - old) - (ne - new);
1857 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1858 col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
1859 else
1860 col_lendiff = lendiff;
1861
1862 /* If we've already printed over the entire width of the screen,
1863 including the old material, then col_lendiff doesn't matter and
1864 space_to_eol will insert too many spaces. XXX - maybe we should
1865 adjust col_lendiff based on the difference between _rl_last_c_pos
1866 and _rl_screenwidth */
1867 if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
1868 {
1869 if (_rl_term_autowrap && current_line < inv_botlin)
1870 space_to_eol (col_lendiff);
1871 else
1872 _rl_clear_to_eol (col_lendiff);
1873 }
1874 }
1875 }
1876 }
1877
1878 /* Tell the update routines that we have moved onto a new (empty) line. */
1879 int
1880 rl_on_new_line ()
1881 {
1882 if (visible_line)
1883 visible_line[0] = '\0';
1884
1885 _rl_last_c_pos = _rl_last_v_pos = 0;
1886 _rl_vis_botlin = last_lmargin = 0;
1887 if (vis_lbreaks)
1888 vis_lbreaks[0] = vis_lbreaks[1] = 0;
1889 visible_wrap_offset = 0;
1890 return 0;
1891 }
1892
1893 /* Tell the update routines that we have moved onto a new line with the
1894 prompt already displayed. Code originally from the version of readline
1895 distributed with CLISP. rl_expand_prompt must have already been called
1896 (explicitly or implicitly). This still doesn't work exactly right. */
1897 int
1898 rl_on_new_line_with_prompt ()
1899 {
1900 int prompt_size, i, l, real_screenwidth, newlines;
1901 char *prompt_last_line, *lprompt;
1902
1903 /* Initialize visible_line and invisible_line to ensure that they can hold
1904 the already-displayed prompt. */
1905 prompt_size = strlen (rl_prompt) + 1;
1906 init_line_structures (prompt_size);
1907
1908 /* Make sure the line structures hold the already-displayed prompt for
1909 redisplay. */
1910 lprompt = local_prompt ? local_prompt : rl_prompt;
1911 strcpy (visible_line, lprompt);
1912 strcpy (invisible_line, lprompt);
1913
1914 /* If the prompt contains newlines, take the last tail. */
1915 prompt_last_line = strrchr (rl_prompt, '\n');
1916 if (!prompt_last_line)
1917 prompt_last_line = rl_prompt;
1918
1919 l = strlen (prompt_last_line);
1920 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1921 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */
1922 else
1923 _rl_last_c_pos = l;
1924
1925 /* Dissect prompt_last_line into screen lines. Note that here we have
1926 to use the real screenwidth. Readline's notion of screenwidth might be
1927 one less, see terminal.c. */
1928 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
1929 _rl_last_v_pos = l / real_screenwidth;
1930 /* If the prompt length is a multiple of real_screenwidth, we don't know
1931 whether the cursor is at the end of the last line, or already at the
1932 beginning of the next line. Output a newline just to be safe. */
1933 if (l > 0 && (l % real_screenwidth) == 0)
1934 _rl_output_some_chars ("\n", 1);
1935 last_lmargin = 0;
1936
1937 newlines = 0; i = 0;
1938 while (i <= l)
1939 {
1940 _rl_vis_botlin = newlines;
1941 vis_lbreaks[newlines++] = i;
1942 i += real_screenwidth;
1943 }
1944 vis_lbreaks[newlines] = l;
1945 visible_wrap_offset = 0;
1946
1947 rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
1948
1949 return 0;
1950 }
1951
1952 /* Actually update the display, period. */
1953 int
1954 rl_forced_update_display ()
1955 {
1956 register char *temp;
1957
1958 if (visible_line)
1959 {
1960 temp = visible_line;
1961 while (*temp)
1962 *temp++ = '\0';
1963 }
1964 rl_on_new_line ();
1965 forced_display++;
1966 (*rl_redisplay_function) ();
1967 return 0;
1968 }
1969
1970 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1971 (Well, when we don't have multibyte characters, _rl_last_c_pos is a
1972 buffer index.)
1973 DATA is the contents of the screen line of interest; i.e., where
1974 the movement is being done. */
1975 void
1976 _rl_move_cursor_relative (new, data)
1977 int new;
1978 const char *data;
1979 {
1980 register int i;
1981 int woff; /* number of invisible chars on current line */
1982 int cpos, dpos; /* current and desired cursor positions */
1983 int adjust;
1984
1985 woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
1986 cpos = _rl_last_c_pos;
1987
1988 if (cpos == 0 && cpos == new)
1989 return;
1990
1991 #if defined (HANDLE_MULTIBYTE)
1992 /* If we have multibyte characters, NEW is indexed by the buffer point in
1993 a multibyte string, but _rl_last_c_pos is the display position. In
1994 this case, NEW's display position is not obvious and must be
1995 calculated. We need to account for invisible characters in this line,
1996 as long as we are past them and they are counted by _rl_col_width. */
1997 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1998 {
1999 adjust = 1;
2000 /* Try to short-circuit common cases and eliminate a bunch of multibyte
2001 character function calls. */
2002 /* 1. prompt string */
2003 if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2004 {
2005 dpos = prompt_physical_chars;
2006 cpos_adjusted = 1;
2007 adjust = 0;
2008 }
2009 /* 2. prompt_string + line contents */
2010 else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2011 {
2012 dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2013 cpos_adjusted = 1;
2014 adjust = 0;
2015 }
2016 else
2017 dpos = _rl_col_width (data, 0, new, 1);
2018
2019 if (displaying_prompt_first_line == 0)
2020 adjust = 0;
2021
2022 /* Use NEW when comparing against the last invisible character in the
2023 prompt string, since they're both buffer indices and DPOS is a
2024 desired display position. */
2025 if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */
2026 (prompt_physical_chars >= _rl_screenwidth &&
2027 _rl_last_v_pos == prompt_last_screen_line &&
2028 wrap_offset >= woff && dpos >= woff &&
2029 new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset))))
2030 /* XXX last comparison might need to be >= */
2031 {
2032 dpos -= woff;
2033 /* Since this will be assigned to _rl_last_c_pos at the end (more
2034 precisely, _rl_last_c_pos == dpos when this function returns),
2035 let the caller know. */
2036 cpos_adjusted = 1;
2037 }
2038 }
2039 else
2040 #endif
2041 dpos = new;
2042
2043 /* If we don't have to do anything, then return. */
2044 if (cpos == dpos)
2045 return;
2046
2047 /* It may be faster to output a CR, and then move forwards instead
2048 of moving backwards. */
2049 /* i == current physical cursor position. */
2050 #if defined (HANDLE_MULTIBYTE)
2051 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2052 i = _rl_last_c_pos;
2053 else
2054 #endif
2055 i = _rl_last_c_pos - woff;
2056 if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
2057 (_rl_term_autowrap && i == _rl_screenwidth))
2058 {
2059 #if defined (__MSDOS__)
2060 putc ('\r', rl_outstream);
2061 #else
2062 tputs (_rl_term_cr, 1, _rl_output_character_function);
2063 #endif /* !__MSDOS__ */
2064 cpos = _rl_last_c_pos = 0;
2065 }
2066
2067 if (cpos < dpos)
2068 {
2069 /* Move the cursor forward. We do it by printing the command
2070 to move the cursor forward if there is one, else print that
2071 portion of the output buffer again. Which is cheaper? */
2072
2073 /* The above comment is left here for posterity. It is faster
2074 to print one character (non-control) than to print a control
2075 sequence telling the terminal to move forward one character.
2076 That kind of control is for people who don't know what the
2077 data is underneath the cursor. */
2078
2079 /* However, we need a handle on where the current display position is
2080 in the buffer for the immediately preceding comment to be true.
2081 In multibyte locales, we don't currently have that info available.
2082 Without it, we don't know where the data we have to display begins
2083 in the buffer and we have to go back to the beginning of the screen
2084 line. In this case, we can use the terminal sequence to move forward
2085 if it's available. */
2086 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2087 {
2088 if (_rl_term_forward_char)
2089 {
2090 for (i = cpos; i < dpos; i++)
2091 tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2092 }
2093 else
2094 {
2095 tputs (_rl_term_cr, 1, _rl_output_character_function);
2096 for (i = 0; i < new; i++)
2097 putc (data[i], rl_outstream);
2098 }
2099 }
2100 else
2101 for (i = cpos; i < new; i++)
2102 putc (data[i], rl_outstream);
2103 }
2104
2105 #if defined (HANDLE_MULTIBYTE)
2106 /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2107 The byte length of the string is probably bigger than the column width
2108 of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2109 display point is less than _rl_last_c_pos. */
2110 #endif
2111 else if (cpos > dpos)
2112 _rl_backspace (cpos - dpos);
2113
2114 _rl_last_c_pos = dpos;
2115 }
2116
2117 /* PWP: move the cursor up or down. */
2118 void
2119 _rl_move_vert (to)
2120 int to;
2121 {
2122 register int delta, i;
2123
2124 if (_rl_last_v_pos == to || to > _rl_screenheight)
2125 return;
2126
2127 if ((delta = to - _rl_last_v_pos) > 0)
2128 {
2129 for (i = 0; i < delta; i++)
2130 putc ('\n', rl_outstream);
2131 #if defined (__MSDOS__)
2132 putc ('\r', rl_outstream);
2133 #else
2134 tputs (_rl_term_cr, 1, _rl_output_character_function);
2135 #endif
2136 _rl_last_c_pos = 0;
2137 }
2138 else
2139 { /* delta < 0 */
2140 #ifdef __DJGPP__
2141 int row, col;
2142
2143 fflush (rl_outstream);
2144 ScreenGetCursor (&row, &col);
2145 ScreenSetCursor (row + delta, col);
2146 i = -delta;
2147 #else
2148 if (_rl_term_up && *_rl_term_up)
2149 for (i = 0; i < -delta; i++)
2150 tputs (_rl_term_up, 1, _rl_output_character_function);
2151 #endif /* !__DJGPP__ */
2152 }
2153
2154 _rl_last_v_pos = to; /* Now TO is here */
2155 }
2156
2157 /* Physically print C on rl_outstream. This is for functions which know
2158 how to optimize the display. Return the number of characters output. */
2159 int
2160 rl_show_char (c)
2161 int c;
2162 {
2163 int n = 1;
2164 if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2165 {
2166 fprintf (rl_outstream, "M-");
2167 n += 2;
2168 c = UNMETA (c);
2169 }
2170
2171 #if defined (DISPLAY_TABS)
2172 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
2173 #else
2174 if (CTRL_CHAR (c) || c == RUBOUT)
2175 #endif /* !DISPLAY_TABS */
2176 {
2177 fprintf (rl_outstream, "C-");
2178 n += 2;
2179 c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
2180 }
2181
2182 putc (c, rl_outstream);
2183 fflush (rl_outstream);
2184 return n;
2185 }
2186
2187 int
2188 rl_character_len (c, pos)
2189 register int c, pos;
2190 {
2191 unsigned char uc;
2192
2193 uc = (unsigned char)c;
2194
2195 if (META_CHAR (uc))
2196 return ((_rl_output_meta_chars == 0) ? 4 : 1);
2197
2198 if (uc == '\t')
2199 {
2200 #if defined (DISPLAY_TABS)
2201 return (((pos | 7) + 1) - pos);
2202 #else
2203 return (2);
2204 #endif /* !DISPLAY_TABS */
2205 }
2206
2207 if (CTRL_CHAR (c) || c == RUBOUT)
2208 return (2);
2209
2210 return ((ISPRINT (uc)) ? 1 : 2);
2211 }
2212 /* How to print things in the "echo-area". The prompt is treated as a
2213 mini-modeline. */
2214 static int msg_saved_prompt = 0;
2215
2216 #if defined (USE_VARARGS)
2217 int
2218 #if defined (PREFER_STDARG)
2219 rl_message (const char *format, ...)
2220 #else
2221 rl_message (va_alist)
2222 va_dcl
2223 #endif
2224 {
2225 va_list args;
2226 #if defined (PREFER_VARARGS)
2227 char *format;
2228 #endif
2229 #if defined (HAVE_VSNPRINTF)
2230 int bneed;
2231 #endif
2232
2233 #if defined (PREFER_STDARG)
2234 va_start (args, format);
2235 #else
2236 va_start (args);
2237 format = va_arg (args, char *);
2238 #endif
2239
2240 if (msg_buf == 0)
2241 msg_buf = xmalloc (msg_bufsiz = 128);
2242
2243 #if defined (HAVE_VSNPRINTF)
2244 bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2245 if (bneed >= msg_bufsiz - 1)
2246 {
2247 msg_bufsiz = bneed + 1;
2248 msg_buf = xrealloc (msg_buf, msg_bufsiz);
2249 va_end (args);
2250
2251 #if defined (PREFER_STDARG)
2252 va_start (args, format);
2253 #else
2254 va_start (args);
2255 format = va_arg (args, char *);
2256 #endif
2257 vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2258 }
2259 #else
2260 vsprintf (msg_buf, format, args);
2261 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2262 #endif
2263 va_end (args);
2264
2265 if (saved_local_prompt == 0)
2266 {
2267 rl_save_prompt ();
2268 msg_saved_prompt = 1;
2269 }
2270 else if (local_prompt != saved_local_prompt)
2271 {
2272 FREE (local_prompt);
2273 FREE (local_prompt_prefix);
2274 local_prompt = (char *)NULL;
2275 }
2276 rl_display_prompt = msg_buf;
2277 local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2278 &prompt_last_invisible,
2279 &prompt_invis_chars_first_line,
2280 &prompt_physical_chars);
2281 local_prompt_prefix = (char *)NULL;
2282 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2283 (*rl_redisplay_function) ();
2284
2285 return 0;
2286 }
2287 #else /* !USE_VARARGS */
2288 int
2289 rl_message (format, arg1, arg2)
2290 char *format;
2291 {
2292 if (msg_buf == 0)
2293 msg_buf = xmalloc (msg_bufsiz = 128);
2294
2295 sprintf (msg_buf, format, arg1, arg2);
2296 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2297
2298 rl_display_prompt = msg_buf;
2299 if (saved_local_prompt == 0)
2300 {
2301 rl_save_prompt ();
2302 msg_saved_prompt = 1;
2303 }
2304 else if (local_prompt != saved_local_prompt)
2305 {
2306 FREE (local_prompt);
2307 FREE (local_prompt_prefix);
2308 local_prompt = (char *)NULL;
2309 }
2310 local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2311 &prompt_last_invisible,
2312 &prompt_invis_chars_first_line,
2313 &prompt_physical_chars);
2314 local_prompt_prefix = (char *)NULL;
2315 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2316 (*rl_redisplay_function) ();
2317
2318 return 0;
2319 }
2320 #endif /* !USE_VARARGS */
2321
2322 /* How to clear things from the "echo-area". */
2323 int
2324 rl_clear_message ()
2325 {
2326 rl_display_prompt = rl_prompt;
2327 if (msg_saved_prompt)
2328 {
2329 rl_restore_prompt ();
2330 msg_saved_prompt = 0;
2331 }
2332 (*rl_redisplay_function) ();
2333 return 0;
2334 }
2335
2336 int
2337 rl_reset_line_state ()
2338 {
2339 rl_on_new_line ();
2340
2341 rl_display_prompt = rl_prompt ? rl_prompt : "";
2342 forced_display = 1;
2343 return 0;
2344 }
2345
2346 void
2347 rl_save_prompt ()
2348 {
2349 saved_local_prompt = local_prompt;
2350 saved_local_prefix = local_prompt_prefix;
2351 saved_prefix_length = prompt_prefix_length;
2352 saved_local_length = local_prompt_len;
2353 saved_last_invisible = prompt_last_invisible;
2354 saved_visible_length = prompt_visible_length;
2355 saved_invis_chars_first_line = prompt_invis_chars_first_line;
2356 saved_physical_chars = prompt_physical_chars;
2357
2358 local_prompt = local_prompt_prefix = (char *)0;
2359 local_prompt_len = 0;
2360 prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
2361 prompt_invis_chars_first_line = prompt_physical_chars = 0;
2362 }
2363
2364 void
2365 rl_restore_prompt ()
2366 {
2367 FREE (local_prompt);
2368 FREE (local_prompt_prefix);
2369
2370 local_prompt = saved_local_prompt;
2371 local_prompt_prefix = saved_local_prefix;
2372 local_prompt_len = saved_local_length;
2373 prompt_prefix_length = saved_prefix_length;
2374 prompt_last_invisible = saved_last_invisible;
2375 prompt_visible_length = saved_visible_length;
2376 prompt_invis_chars_first_line = saved_invis_chars_first_line;
2377 prompt_physical_chars = saved_physical_chars;
2378
2379 /* can test saved_local_prompt to see if prompt info has been saved. */
2380 saved_local_prompt = saved_local_prefix = (char *)0;
2381 saved_local_length = 0;
2382 saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2383 saved_invis_chars_first_line = saved_physical_chars = 0;
2384 }
2385
2386 char *
2387 _rl_make_prompt_for_search (pchar)
2388 int pchar;
2389 {
2390 int len;
2391 char *pmt, *p;
2392
2393 rl_save_prompt ();
2394
2395 /* We've saved the prompt, and can do anything with the various prompt
2396 strings we need before they're restored. We want the unexpanded
2397 portion of the prompt string after any final newline. */
2398 p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2399 if (p == 0)
2400 {
2401 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
2402 pmt = (char *)xmalloc (len + 2);
2403 if (len)
2404 strcpy (pmt, rl_prompt);
2405 pmt[len] = pchar;
2406 pmt[len+1] = '\0';
2407 }
2408 else
2409 {
2410 p++;
2411 len = strlen (p);
2412 pmt = (char *)xmalloc (len + 2);
2413 if (len)
2414 strcpy (pmt, p);
2415 pmt[len] = pchar;
2416 pmt[len+1] = '\0';
2417 }
2418
2419 /* will be overwritten by expand_prompt, called from rl_message */
2420 prompt_physical_chars = saved_physical_chars + 1;
2421 return pmt;
2422 }
2423
2424 /* Quick redisplay hack when erasing characters at the end of the line. */
2425 void
2426 _rl_erase_at_end_of_line (l)
2427 int l;
2428 {
2429 register int i;
2430
2431 _rl_backspace (l);
2432 for (i = 0; i < l; i++)
2433 putc (' ', rl_outstream);
2434 _rl_backspace (l);
2435 for (i = 0; i < l; i++)
2436 visible_line[--_rl_last_c_pos] = '\0';
2437 rl_display_fixed++;
2438 }
2439
2440 /* Clear to the end of the line. COUNT is the minimum
2441 number of character spaces to clear, */
2442 void
2443 _rl_clear_to_eol (count)
2444 int count;
2445 {
2446 #ifndef __MSDOS__
2447 if (_rl_term_clreol)
2448 tputs (_rl_term_clreol, 1, _rl_output_character_function);
2449 else
2450 #endif
2451 if (count)
2452 space_to_eol (count);
2453 }
2454
2455 /* Clear to the end of the line using spaces. COUNT is the minimum
2456 number of character spaces to clear, */
2457 static void
2458 space_to_eol (count)
2459 int count;
2460 {
2461 register int i;
2462
2463 for (i = 0; i < count; i++)
2464 putc (' ', rl_outstream);
2465
2466 _rl_last_c_pos += count;
2467 }
2468
2469 void
2470 _rl_clear_screen ()
2471 {
2472 #ifndef __DJGPP__
2473 if (_rl_term_clrpag)
2474 tputs (_rl_term_clrpag, 1, _rl_output_character_function);
2475 else
2476 rl_crlf ();
2477 #else
2478 ScreenClear ();
2479 ScreenSetCursor (0, 0);
2480 #endif /* __DJGPP__ */
2481 }
2482
2483 /* Insert COUNT characters from STRING to the output stream at column COL. */
2484 static void
2485 insert_some_chars (string, count, col)
2486 char *string;
2487 int count, col;
2488 {
2489 open_some_spaces (col);
2490 _rl_output_some_chars (string, count);
2491 }
2492
2493 /* Insert COL spaces, keeping the cursor at the same position. We follow the
2494 ncurses documentation and use either im/ei with explicit spaces, or IC/ic
2495 by itself. We assume there will either be ei or we don't need to use it. */
2496 static void
2497 open_some_spaces (col)
2498 int col;
2499 {
2500 #if !defined (__MSDOS__) && !defined (__MINGW32__)
2501 char *buffer;
2502 register int i;
2503
2504 /* If IC is defined, then we do not have to "enter" insert mode. */
2505 if (_rl_term_IC)
2506 {
2507 buffer = tgoto (_rl_term_IC, 0, col);
2508 tputs (buffer, 1, _rl_output_character_function);
2509 }
2510 else if (_rl_term_im && *_rl_term_im)
2511 {
2512 tputs (_rl_term_im, 1, _rl_output_character_function);
2513 /* just output the desired number of spaces */
2514 for (i = col; i--; )
2515 _rl_output_character_function (' ');
2516 /* If there is a string to turn off insert mode, use it now. */
2517 if (_rl_term_ei && *_rl_term_ei)
2518 tputs (_rl_term_ei, 1, _rl_output_character_function);
2519 /* and move back the right number of spaces */
2520 _rl_backspace (col);
2521 }
2522 else if (_rl_term_ic && *_rl_term_ic)
2523 {
2524 /* If there is a special command for inserting characters, then
2525 use that first to open up the space. */
2526 for (i = col; i--; )
2527 tputs (_rl_term_ic, 1, _rl_output_character_function);
2528 }
2529 #endif /* !__MSDOS__ && !__MINGW32__ */
2530 }
2531
2532 /* Delete COUNT characters from the display line. */
2533 static void
2534 delete_chars (count)
2535 int count;
2536 {
2537 if (count > _rl_screenwidth) /* XXX */
2538 return;
2539
2540 #if !defined (__MSDOS__) && !defined (__MINGW32__)
2541 if (_rl_term_DC && *_rl_term_DC)
2542 {
2543 char *buffer;
2544 buffer = tgoto (_rl_term_DC, count, count);
2545 tputs (buffer, count, _rl_output_character_function);
2546 }
2547 else
2548 {
2549 if (_rl_term_dc && *_rl_term_dc)
2550 while (count--)
2551 tputs (_rl_term_dc, 1, _rl_output_character_function);
2552 }
2553 #endif /* !__MSDOS__ && !__MINGW32__ */
2554 }
2555
2556 void
2557 _rl_update_final ()
2558 {
2559 int full_lines;
2560
2561 full_lines = 0;
2562 /* If the cursor is the only thing on an otherwise-blank last line,
2563 compensate so we don't print an extra CRLF. */
2564 if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
2565 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
2566 {
2567 _rl_vis_botlin--;
2568 full_lines = 1;
2569 }
2570 _rl_move_vert (_rl_vis_botlin);
2571 /* If we've wrapped lines, remove the final xterm line-wrap flag. */
2572 if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
2573 {
2574 char *last_line;
2575
2576 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
2577 cpos_buffer_position = -1; /* don't know where we are in buffer */
2578 _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */
2579 _rl_clear_to_eol (0);
2580 putc (last_line[_rl_screenwidth - 1], rl_outstream);
2581 }
2582 _rl_vis_botlin = 0;
2583 rl_crlf ();
2584 fflush (rl_outstream);
2585 rl_display_fixed++;
2586 }
2587
2588 /* Move to the start of the current line. */
2589 static void
2590 cr ()
2591 {
2592 if (_rl_term_cr)
2593 {
2594 #if defined (__MSDOS__)
2595 putc ('\r', rl_outstream);
2596 #else
2597 tputs (_rl_term_cr, 1, _rl_output_character_function);
2598 #endif
2599 _rl_last_c_pos = 0;
2600 }
2601 }
2602
2603 /* Redraw the last line of a multi-line prompt that may possibly contain
2604 terminal escape sequences. Called with the cursor at column 0 of the
2605 line to draw the prompt on. */
2606 static void
2607 redraw_prompt (t)
2608 char *t;
2609 {
2610 char *oldp;
2611
2612 oldp = rl_display_prompt;
2613 rl_save_prompt ();
2614
2615 rl_display_prompt = t;
2616 local_prompt = expand_prompt (t, &prompt_visible_length,
2617 &prompt_last_invisible,
2618 &prompt_invis_chars_first_line,
2619 &prompt_physical_chars);
2620 local_prompt_prefix = (char *)NULL;
2621 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2622
2623 rl_forced_update_display ();
2624
2625 rl_display_prompt = oldp;
2626 rl_restore_prompt();
2627 }
2628
2629 /* Redisplay the current line after a SIGWINCH is received. */
2630 void
2631 _rl_redisplay_after_sigwinch ()
2632 {
2633 char *t;
2634
2635 /* Clear the last line (assuming that the screen size change will result in
2636 either more or fewer characters on that line only) and put the cursor at
2637 column 0. Make sure the right thing happens if we have wrapped to a new
2638 screen line. */
2639 if (_rl_term_cr)
2640 {
2641 _rl_move_vert (_rl_vis_botlin);
2642
2643 #if defined (__MSDOS__)
2644 putc ('\r', rl_outstream);
2645 #else
2646 tputs (_rl_term_cr, 1, _rl_output_character_function);
2647 #endif
2648 _rl_last_c_pos = 0;
2649 #if defined (__MSDOS__)
2650 space_to_eol (_rl_screenwidth);
2651 putc ('\r', rl_outstream);
2652 #else
2653 if (_rl_term_clreol)
2654 tputs (_rl_term_clreol, 1, _rl_output_character_function);
2655 else
2656 {
2657 space_to_eol (_rl_screenwidth);
2658 tputs (_rl_term_cr, 1, _rl_output_character_function);
2659 }
2660 #endif
2661 if (_rl_last_v_pos > 0)
2662 _rl_move_vert (0);
2663 }
2664 else
2665 rl_crlf ();
2666
2667 /* Redraw only the last line of a multi-line prompt. */
2668 t = strrchr (rl_display_prompt, '\n');
2669 if (t)
2670 redraw_prompt (++t);
2671 else
2672 rl_forced_update_display ();
2673 }
2674
2675 void
2676 _rl_clean_up_for_exit ()
2677 {
2678 if (_rl_echoing_p)
2679 {
2680 _rl_move_vert (_rl_vis_botlin);
2681 _rl_vis_botlin = 0;
2682 fflush (rl_outstream);
2683 rl_restart_output (1, 0);
2684 }
2685 }
2686
2687 void
2688 _rl_erase_entire_line ()
2689 {
2690 cr ();
2691 _rl_clear_to_eol (0);
2692 cr ();
2693 fflush (rl_outstream);
2694 }
2695
2696 /* return the `current display line' of the cursor -- the number of lines to
2697 move up to get to the first screen line of the current readline line. */
2698 int
2699 _rl_current_display_line ()
2700 {
2701 int ret, nleft;
2702
2703 /* Find out whether or not there might be invisible characters in the
2704 editing buffer. */
2705 if (rl_display_prompt == rl_prompt)
2706 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
2707 else
2708 nleft = _rl_last_c_pos - _rl_screenwidth;
2709
2710 if (nleft > 0)
2711 ret = 1 + nleft / _rl_screenwidth;
2712 else
2713 ret = 0;
2714
2715 return ret;
2716 }
2717
2718 #if defined (HANDLE_MULTIBYTE)
2719 /* Calculate the number of screen columns occupied by STR from START to END.
2720 In the case of multibyte characters with stateful encoding, we have to
2721 scan from the beginning of the string to take the state into account. */
2722 static int
2723 _rl_col_width (str, start, end, flags)
2724 const char *str;
2725 int start, end, flags;
2726 {
2727 wchar_t wc;
2728 mbstate_t ps;
2729 int tmp, point, width, max;
2730
2731 if (end <= start)
2732 return 0;
2733 if (MB_CUR_MAX == 1 || rl_byte_oriented)
2734 /* this can happen in some cases where it's inconvenient to check */
2735 return (end - start);
2736
2737 memset (&ps, 0, sizeof (mbstate_t));
2738
2739 point = 0;
2740 max = end;
2741
2742 /* Try to short-circuit common cases. The adjustment to remove wrap_offset
2743 is done by the caller. */
2744 /* 1. prompt string */
2745 if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
2746 return (prompt_physical_chars + wrap_offset);
2747 /* 2. prompt string + line contents */
2748 else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
2749 {
2750 tmp = prompt_physical_chars + wrap_offset;
2751 /* XXX - try to call ourselves recursively with non-prompt portion */
2752 tmp += _rl_col_width (str, local_prompt_len, end, flags);
2753 return (tmp);
2754 }
2755
2756 while (point < start)
2757 {
2758 tmp = mbrlen (str + point, max, &ps);
2759 if (MB_INVALIDCH ((size_t)tmp))
2760 {
2761 /* In this case, the bytes are invalid or too short to compose a
2762 multibyte character, so we assume that the first byte represents
2763 a single character. */
2764 point++;
2765 max--;
2766
2767 /* Clear the state of the byte sequence, because in this case the
2768 effect of mbstate is undefined. */
2769 memset (&ps, 0, sizeof (mbstate_t));
2770 }
2771 else if (MB_NULLWCH (tmp))
2772 break; /* Found '\0' */
2773 else
2774 {
2775 point += tmp;
2776 max -= tmp;
2777 }
2778 }
2779
2780 /* If START is not a byte that starts a character, then POINT will be
2781 greater than START. In this case, assume that (POINT - START) gives
2782 a byte count that is the number of columns of difference. */
2783 width = point - start;
2784
2785 while (point < end)
2786 {
2787 tmp = mbrtowc (&wc, str + point, max, &ps);
2788 if (MB_INVALIDCH ((size_t)tmp))
2789 {
2790 /* In this case, the bytes are invalid or too short to compose a
2791 multibyte character, so we assume that the first byte represents
2792 a single character. */
2793 point++;
2794 max--;
2795
2796 /* and assume that the byte occupies a single column. */
2797 width++;
2798
2799 /* Clear the state of the byte sequence, because in this case the
2800 effect of mbstate is undefined. */
2801 memset (&ps, 0, sizeof (mbstate_t));
2802 }
2803 else if (MB_NULLWCH (tmp))
2804 break; /* Found '\0' */
2805 else
2806 {
2807 point += tmp;
2808 max -= tmp;
2809 tmp = WCWIDTH(wc);
2810 width += (tmp >= 0) ? tmp : 1;
2811 }
2812 }
2813
2814 width += point - end;
2815
2816 return width;
2817 }
2818 #endif /* HANDLE_MULTIBYTE */