1 /* display.c -- readline redisplay facility. */
2
3 /* Copyright (C) 1987-2020 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 putc_face PARAMS((int, int, char *));
67 static void puts_face PARAMS((const char *, const char *, int));
68 static void norm_face PARAMS((char *, int));
69
70 static void update_line PARAMS((char *, char *, char *, char *, int, int, int, int));
71 static void space_to_eol PARAMS((int));
72 static void delete_chars PARAMS((int));
73 static void insert_some_chars PARAMS((char *, int, int));
74 static void open_some_spaces PARAMS((int));
75 static void cr PARAMS((void));
76 static void redraw_prompt PARAMS((char *));
77 static void _rl_move_cursor_relative PARAMS((int, const char *, const char *));
78
79 /* Values for FLAGS */
80 #define PMT_MULTILINE 0x01
81
82 static char *expand_prompt PARAMS((char *, int, int *, int *, int *, int *));
83
84 #define DEFAULT_LINE_BUFFER_SIZE 1024
85
86 /* State of visible and invisible lines. */
87 struct line_state
88 {
89 char *line;
90 char *lface;
91 int *lbreaks;
92 int lbsize;
93 #if defined (HANDLE_MULTIBYTE)
94 int wbsize;
95 int *wrapped_line;
96 #endif
97 };
98
99 /* The line display buffers. One is the line currently displayed on
100 the screen. The other is the line about to be displayed. */
101 static struct line_state line_state_array[2];
102 static struct line_state *line_state_visible = &line_state_array[0];
103 static struct line_state *line_state_invisible = &line_state_array[1];
104 static int line_structures_initialized = 0;
105
106 /* Backwards-compatible names. */
107 #define inv_lbreaks (line_state_invisible->lbreaks)
108 #define inv_lbsize (line_state_invisible->lbsize)
109 #define vis_lbreaks (line_state_visible->lbreaks)
110 #define vis_lbsize (line_state_visible->lbsize)
111
112 #define visible_line (line_state_visible->line)
113 #define vis_face (line_state_visible->lface)
114 #define invisible_line (line_state_invisible->line)
115 #define inv_face (line_state_invisible->lface)
116
117 #if defined (HANDLE_MULTIBYTE)
118 static int _rl_col_width PARAMS((const char *, int, int, int));
119 #else
120 # define _rl_col_width(l, s, e, f) (((e) <= (s)) ? 0 : (e) - (s))
121 #endif
122
123 /* Heuristic used to decide whether it is faster to move from CUR to NEW
124 by backing up or outputting a carriage return and moving forward. CUR
125 and NEW are either both buffer positions or absolute screen positions. */
126 #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
127
128 /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
129 buffer index in others. This macro is used when deciding whether the
130 current cursor position is in the middle of a prompt string containing
131 invisible characters. XXX - might need to take `modmark' into account. */
132 /* XXX - only valid when tested against _rl_last_c_pos; buffer indices need
133 to use prompt_last_invisible directly. */
134 #define PROMPT_ENDING_INDEX \
135 ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
136
137 #define FACE_NORMAL '0'
138 #define FACE_STANDOUT '1'
139 #define FACE_INVALID ((char)1)
140
141 /* **************************************************************** */
142 /* */
143 /* Display stuff */
144 /* */
145 /* **************************************************************** */
146
147 /* This is the stuff that is hard for me. I never seem to write good
148 display routines in C. Let's see how I do this time. */
149
150 /* (PWP) Well... Good for a simple line updater, but totally ignores
151 the problems of input lines longer than the screen width.
152
153 update_line and the code that calls it makes a multiple line,
154 automatically wrapping line update. Careful attention needs
155 to be paid to the vertical position variables. */
156
157 /* Keep two buffers; one which reflects the current contents of the
158 screen, and the other to draw what we think the new contents should
159 be. Then compare the buffers, and make whatever changes to the
160 screen itself that we should. Finally, make the buffer that we
161 just drew into be the one which reflects the current contents of the
162 screen, and place the cursor where it belongs.
163
164 Commands that want to can fix the display themselves, and then let
165 this function know that the display has been fixed by setting the
166 RL_DISPLAY_FIXED variable. This is good for efficiency. */
167
168 /* Application-specific redisplay function. */
169 rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
170
171 /* Global variables declared here. */
172 /* What YOU turn on when you have handled all redisplay yourself. */
173 int rl_display_fixed = 0;
174
175 /* The stuff that gets printed out before the actual text of the line.
176 This is usually pointing to rl_prompt. */
177 char *rl_display_prompt = (char *)NULL;
178
179 /* Variables used to include the editing mode in the prompt. */
180 char *_rl_emacs_mode_str;
181 int _rl_emacs_modestr_len;
182
183 char *_rl_vi_ins_mode_str;
184 int _rl_vi_ins_modestr_len;
185
186 char *_rl_vi_cmd_mode_str;
187 int _rl_vi_cmd_modestr_len;
188
189 /* Pseudo-global variables declared here. */
190
191 /* Hints for other parts of readline to give to the display engine. */
192 int _rl_suppress_redisplay = 0;
193 int _rl_want_redisplay = 0;
194
195 /* The visible cursor position. If you print some text, adjust this. */
196 /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
197 supporting multibyte characters, and an absolute cursor position when
198 in such a locale. This is an artifact of the donated multibyte support.
199 Care must be taken when modifying its value. */
200 int _rl_last_c_pos = 0;
201 int _rl_last_v_pos = 0;
202
203 /* Number of physical lines consumed by the current line buffer currently
204 on screen minus 1. */
205 int _rl_vis_botlin = 0;
206
207 static int _rl_quick_redisplay = 0;
208
209 /* This is a hint update_line gives to rl_redisplay that it has adjusted the
210 value of _rl_last_c_pos *and* taken the presence of any invisible chars in
211 the prompt into account. rl_redisplay notes this and does not do the
212 adjustment itself. */
213 static int cpos_adjusted;
214
215 /* The index into the line buffer corresponding to the cursor position */
216 static int cpos_buffer_position;
217
218 /* A flag to note when we're displaying the first line of the prompt */
219 static int displaying_prompt_first_line;
220 /* The number of multibyte characters in the prompt, if any */
221 static int prompt_multibyte_chars;
222
223 static int _rl_inv_botlin = 0;
224
225 /* Variables used only in this file. */
226 /* The last left edge of text that was displayed. This is used when
227 doing horizontal scrolling. It shifts in thirds of a screenwidth. */
228 static int last_lmargin;
229
230 /* A buffer for `modeline' messages. */
231 static char *msg_buf = 0;
232 static int msg_bufsiz = 0;
233
234 /* Non-zero forces the redisplay even if we thought it was unnecessary. */
235 static int forced_display;
236
237 /* Default and initial buffer size. Can grow. */
238 static int line_size = 0;
239
240 /* Set to a non-zero value if horizontal scrolling has been enabled
241 automatically because the terminal was resized to height 1. */
242 static int horizontal_scrolling_autoset = 0; /* explicit initialization */
243
244 /* Variables to keep track of the expanded prompt string, which may
245 include invisible characters. */
246
247 static char *local_prompt, *local_prompt_prefix;
248 static int local_prompt_len;
249 static int prompt_prefix_length;
250 /* Number of chars in the buffer that contribute to visible chars on the screen.
251 This might be different from the number of physical chars in the presence
252 of multibyte characters */
253 static int prompt_visible_length;
254
255 /* The number of invisible characters in the line currently being
256 displayed on the screen. */
257 static int visible_wrap_offset;
258
259 /* The number of invisible characters in the prompt string. Static so it
260 can be shared between rl_redisplay and update_line */
261 static int wrap_offset;
262
263 /* The index of the last invisible character in the prompt string. */
264 static int prompt_last_invisible;
265
266 /* The length (buffer offset) of the first line of the last (possibly
267 multi-line) buffer displayed on the screen. */
268 static int visible_first_line_len;
269
270 /* Number of invisible characters on the first physical line of the prompt.
271 Only valid when the number of physical characters in the prompt exceeds
272 (or is equal to) _rl_screenwidth. */
273 static int prompt_invis_chars_first_line;
274
275 static int prompt_last_screen_line;
276
277 static int prompt_physical_chars;
278
279 /* An array of indexes into the prompt string where we will break physical
280 screen lines. It's easier to compute in expand_prompt and use later in
281 rl_redisplay instead of having rl_redisplay try to guess about invisible
282 characters in the prompt or use heuristics about where they are. */
283 static int *local_prompt_newlines;
284
285 /* set to a non-zero value by rl_redisplay if we are marking modified history
286 lines and the current line is so marked. */
287 static int modmark;
288
289 static int line_totbytes;
290
291 /* Variables to save and restore prompt and display information. */
292
293 /* These are getting numerous enough that it's time to create a struct. */
294
295 static char *saved_local_prompt;
296 static char *saved_local_prefix;
297 static int *saved_local_prompt_newlines;
298
299 static int saved_last_invisible;
300 static int saved_visible_length;
301 static int saved_prefix_length;
302 static int saved_local_length;
303 static int saved_invis_chars_first_line;
304 static int saved_physical_chars;
305
306 /* Return a string indicating the editing mode, for use in the prompt. */
307
308 static char *
prompt_modestr(int * lenp)309 prompt_modestr (int *lenp)
310 {
311 if (rl_editing_mode == emacs_mode)
312 {
313 if (lenp)
314 *lenp = _rl_emacs_mode_str ? _rl_emacs_modestr_len : RL_EMACS_MODESTR_DEFLEN;
315 return _rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT;
316 }
317 else if (_rl_keymap == vi_insertion_keymap)
318 {
319 if (lenp)
320 *lenp = _rl_vi_ins_mode_str ? _rl_vi_ins_modestr_len : RL_VI_INS_MODESTR_DEFLEN;
321 return _rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT; /* vi insert mode */
322 }
323 else
324 {
325 if (lenp)
326 *lenp = _rl_vi_cmd_mode_str ? _rl_vi_cmd_modestr_len : RL_VI_CMD_MODESTR_DEFLEN;
327 return _rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT; /* vi command mode */
328 }
329 }
330
331 /* Expand the prompt string S and return the number of visible
332 characters in *LP, if LP is not null. This is currently more-or-less
333 a placeholder for expansion. LIP, if non-null is a place to store the
334 index of the last invisible character in the returned string. NIFLP,
335 if non-zero, is a place to store the number of invisible characters in
336 the first prompt line. The previous are used as byte counts -- indexes
337 into a character buffer. *VLP gets the number of physical characters in
338 the expanded prompt (visible length) */
339
340 /* Current implementation:
341 \001 (^A) start non-visible characters
342 \002 (^B) end non-visible characters
343 all characters except \001 and \002 (following a \001) are copied to
344 the returned string; all characters except those between \001 and
345 \002 are assumed to be `visible'. */
346
347 /* Possible values for FLAGS:
348 PMT_MULTILINE caller indicates that this is part of a multiline prompt
349 */
350
351 /* This approximates the number of lines the prompt will take when displayed */
352 #define APPROX_DIV(n, d) (((n) < (d)) ? 1 : ((n) / (d)) + 1)
353
354 static char *
expand_prompt(char * pmt,int flags,int * lp,int * lip,int * niflp,int * vlp)355 expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
356 {
357 char *r, *ret, *p, *igstart, *nprompt, *ms;
358 int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
359 int mlen, newlines, newlines_guess, bound;
360 int mb_cur_max;
361
362 /* We only expand the mode string for the last line of a multiline prompt
363 (a prompt with embedded newlines). */
364 ms = (((pmt == rl_prompt) ^ (flags & PMT_MULTILINE)) && _rl_show_mode_in_prompt) ? prompt_modestr (&mlen) : 0;
365 if (ms)
366 {
367 l = strlen (pmt);
368 nprompt = (char *)xmalloc (l + mlen + 1);
369 memcpy (nprompt, ms, mlen);
370 strcpy (nprompt + mlen, pmt);
371 }
372 else
373 nprompt = pmt;
374
375 mb_cur_max = MB_CUR_MAX;
376
377 if (_rl_screenwidth == 0)
378 _rl_get_screen_size (0, 0); /* avoid division by zero */
379
380 /* Short-circuit if we can. We can do this if we are treating the prompt as
381 a sequence of bytes and there are no invisible characters in the prompt
382 to deal with. Since we populate local_prompt_newlines, we have to run
383 through the rest of the function if this prompt looks like it's going to
384 be longer than one screen line. */
385 if ((mb_cur_max <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0)
386 {
387 l = strlen (nprompt);
388 if (l < (_rl_screenwidth > 0 ? _rl_screenwidth : 80))
389 {
390 r = (nprompt == pmt) ? savestring (pmt) : nprompt;
391 if (lp)
392 *lp = l;
393 if (lip)
394 *lip = 0;
395 if (niflp)
396 *niflp = 0;
397 if (vlp)
398 *vlp = l;
399
400 local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * 2);
401 local_prompt_newlines[0] = 0;
402 local_prompt_newlines[1] = -1;
403
404 return r;
405 }
406 }
407
408 l = strlen (nprompt); /* XXX */
409 r = ret = (char *)xmalloc (l + 1);
410
411 /* Guess at how many screen lines the prompt will take to size the array that
412 keeps track of where the line wraps happen */
413 newlines_guess = (_rl_screenwidth > 0) ? APPROX_DIV(l, _rl_screenwidth) : APPROX_DIV(l, 80);
414 local_prompt_newlines = (int *) xrealloc (local_prompt_newlines, sizeof (int) * (newlines_guess + 1));
415 local_prompt_newlines[newlines = 0] = 0;
416 for (rl = 1; rl <= newlines_guess; rl++)
417 local_prompt_newlines[rl] = -1;
418
419 rl = physchars = 0; /* mode string now part of nprompt */
420 invfl = 0; /* invisible chars in first line of prompt */
421 invflset = 0; /* we only want to set invfl once */
422 igstart = 0; /* we're not ignoring any characters yet */
423
424 for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++)
425 {
426 /* This code strips the invisible character string markers
427 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
428 if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
429 {
430 ignoring = 1;
431 igstart = p;
432 continue;
433 }
434 else if (ignoring && *p == RL_PROMPT_END_IGNORE)
435 {
436 ignoring = 0;
437 if (p != (igstart + 1))
438 last = r - ret - 1;
439 continue;
440 }
441 else
442 {
443 #if defined (HANDLE_MULTIBYTE)
444 if (mb_cur_max > 1 && rl_byte_oriented == 0)
445 {
446 pind = p - nprompt;
447 ind = _rl_find_next_mbchar (nprompt, pind, 1, MB_FIND_NONZERO);
448 l = ind - pind;
449 while (l--)
450 *r++ = *p++;
451 if (!ignoring)
452 {
453 /* rl ends up being assigned to prompt_visible_length,
454 which is the number of characters in the buffer that
455 contribute to characters on the screen, which might
456 not be the same as the number of physical characters
457 on the screen in the presence of multibyte characters */
458 rl += ind - pind;
459 physchars += _rl_col_width (nprompt, pind, ind, 0);
460 }
461 else
462 ninvis += ind - pind;
463 p--; /* compensate for later increment */
464 }
465 else
466 #endif
467 {
468 *r++ = *p;
469 if (!ignoring)
470 {
471 rl++; /* visible length byte counter */
472 physchars++;
473 }
474 else
475 ninvis++; /* invisible chars byte counter */
476 }
477
478 if (invflset == 0 && physchars >= _rl_screenwidth)
479 {
480 invfl = ninvis;
481 invflset = 1;
482 }
483
484 if (physchars >= (bound = (newlines + 1) * _rl_screenwidth) && local_prompt_newlines[newlines+1] == -1)
485 {
486 int new;
487 if (physchars > bound) /* should rarely happen */
488 {
489 #if defined (HANDLE_MULTIBYTE)
490 *r = '\0'; /* need null-termination for strlen */
491 if (mb_cur_max > 1 && rl_byte_oriented == 0)
492 new = _rl_find_prev_mbchar (ret, r - ret, MB_FIND_ANY);
493 else
494 #endif
495 new = r - ret - (physchars - bound); /* XXX */
496 }
497 else
498 new = r - ret;
499 local_prompt_newlines[++newlines] = new;
500 }
501 }
502 }
503
504 if (rl < _rl_screenwidth)
505 invfl = ninvis;
506
507 *r = '\0';
508 if (lp)
509 *lp = rl;
510 if (lip)
511 *lip = last;
512 if (niflp)
513 *niflp = invfl;
514 if (vlp)
515 *vlp = physchars;
516
517 if (nprompt != pmt)
518 free (nprompt);
519
520 return ret;
521 }
522
523 /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
524 PMT and return the rest of PMT. */
525 char *
_rl_strip_prompt(char * pmt)526 _rl_strip_prompt (char *pmt)
527 {
528 char *ret;
529
530 ret = expand_prompt (pmt, 0, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
531 return ret;
532 }
533
534 void
_rl_reset_prompt(void)535 _rl_reset_prompt (void)
536 {
537 rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
538 }
539
540 /*
541 * Expand the prompt string into the various display components, if
542 * necessary.
543 *
544 * local_prompt = expanded last line of string in rl_display_prompt
545 * (portion after the final newline)
546 * local_prompt_prefix = portion before last newline of rl_display_prompt,
547 * expanded via expand_prompt
548 * prompt_visible_length = number of visible characters in local_prompt
549 * prompt_prefix_length = number of visible characters in local_prompt_prefix
550 *
551 * It also tries to keep track of the number of invisible characters in the
552 * prompt string, and where they are.
553 *
554 * This function is called once per call to readline(). It may also be
555 * called arbitrarily to expand the primary prompt.
556 *
557 * The return value is the number of visible characters on the last line
558 * of the (possibly multi-line) prompt. In this case, multi-line means
559 * there are embedded newlines in the prompt string itself, not that the
560 * number of physical characters exceeds the screen width and the prompt
561 * wraps.
562 */
563 int
rl_expand_prompt(char * prompt)564 rl_expand_prompt (char *prompt)
565 {
566 char *p, *t;
567 int c;
568
569 /* Clear out any saved values. */
570 FREE (local_prompt);
571 FREE (local_prompt_prefix);
572
573 local_prompt = local_prompt_prefix = (char *)0;
574 local_prompt_len = 0;
575 prompt_last_invisible = prompt_invis_chars_first_line = 0;
576 prompt_visible_length = prompt_physical_chars = 0;
577
578 if (prompt == 0 || *prompt == 0)
579 return (0);
580
581 p = strrchr (prompt, '\n');
582 if (p == 0)
583 {
584 /* The prompt is only one logical line, though it might wrap. */
585 local_prompt = expand_prompt (prompt, 0, &prompt_visible_length,
586 &prompt_last_invisible,
587 &prompt_invis_chars_first_line,
588 &prompt_physical_chars);
589 local_prompt_prefix = (char *)0;
590 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
591 return (prompt_visible_length);
592 }
593 else
594 {
595 /* The prompt spans multiple lines. */
596 t = ++p;
597 c = *t; *t = '\0';
598 /* The portion of the prompt string up to and including the
599 final newline is now null-terminated. */
600 local_prompt_prefix = expand_prompt (prompt, PMT_MULTILINE,
601 &prompt_prefix_length,
602 (int *)NULL,
603 (int *)NULL,
604 (int *)NULL);
605 *t = c;
606
607 local_prompt = expand_prompt (p, PMT_MULTILINE,
608 &prompt_visible_length,
609 &prompt_last_invisible,
610 &prompt_invis_chars_first_line,
611 &prompt_physical_chars);
612 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
613 return (prompt_prefix_length);
614 }
615 }
616
617 /* Allocate the various line structures, making sure they can hold MINSIZE
618 bytes. If the existing line size can accommodate MINSIZE bytes, don't do
619 anything. */
620 static void
realloc_line(int minsize)621 realloc_line (int minsize)
622 {
623 int minimum_size;
624 int newsize, delta;
625
626 minimum_size = DEFAULT_LINE_BUFFER_SIZE;
627 if (minsize < minimum_size)
628 minsize = minimum_size;
629 if (minsize <= _rl_screenwidth) /* XXX - for gdb */
630 minsize = _rl_screenwidth + 1;
631 if (line_size >= minsize)
632 return;
633
634 newsize = minimum_size;
635 while (newsize < minsize)
636 newsize *= 2;
637
638 visible_line = (char *)xrealloc (visible_line, newsize);
639 vis_face = (char *)xrealloc (vis_face, newsize);
640
641 invisible_line = (char *)xrealloc (invisible_line, newsize);
642 inv_face = (char *)xrealloc (inv_face, newsize);
643
644 delta = newsize - line_size;
645 memset (visible_line + line_size, 0, delta);
646 memset (vis_face + line_size, FACE_NORMAL, delta);
647 memset (invisible_line + line_size, 1, delta);
648 memset (inv_face + line_size, FACE_INVALID, delta);
649
650 line_size = newsize;
651 }
652
653 /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
654 arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
655 and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
656 increased. If the lines have already been allocated, this ensures that
657 they can hold at least MINSIZE characters. */
658 static void
init_line_structures(int minsize)659 init_line_structures (int minsize)
660 {
661 if (invisible_line == 0) /* initialize it */
662 {
663 if (line_size > minsize)
664 minsize = line_size;
665 }
666 realloc_line (minsize);
667
668 if (vis_lbreaks == 0)
669 {
670 /* should be enough. */
671 inv_lbsize = vis_lbsize = 256;
672
673 #if defined (HANDLE_MULTIBYTE)
674 line_state_visible->wbsize = vis_lbsize;
675 line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
676
677 line_state_invisible->wbsize = inv_lbsize;
678 line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
679 #endif
680
681 inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
682 vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
683 inv_lbreaks[0] = vis_lbreaks[0] = 0;
684 }
685
686 line_structures_initialized = 1;
687 }
688
689 /* Convenience functions to add chars to the invisible line that update the
690 face information at the same time. */
691 static void /* XXX - change this */
invis_addc(int * outp,char c,char face)692 invis_addc (int *outp, char c, char face)
693 {
694 realloc_line (*outp + 1);
695 invisible_line[*outp] = c;
696 inv_face[*outp] = face;
697 *outp += 1;
698 }
699
700 static void
invis_adds(int * outp,const char * str,int n,char face)701 invis_adds (int *outp, const char *str, int n, char face)
702 {
703 int i;
704
705 for (i = 0; i < n; i++)
706 invis_addc (outp, str[i], face);
707 }
708
709 static void
invis_nul(int * outp)710 invis_nul (int *outp)
711 {
712 invis_addc (outp, '\0', 0);
713 *outp -= 1;
714 }
715
716 static void
set_active_region(int * beg,int * end)717 set_active_region (int *beg, int *end)
718 {
719 if (rl_point >= 0 && rl_point <= rl_end && rl_mark >= 0 && rl_mark <= rl_end)
720 {
721 *beg = (rl_mark < rl_point) ? rl_mark : rl_point;
722 *end = (rl_mark < rl_point) ? rl_point : rl_mark;
723 }
724 }
725
726 /* Do whatever tests are necessary and tell update_line that it can do a
727 quick, dumb redisplay on the assumption that there are so many
728 differences between the old and new lines that it would be a waste to
729 compute all the differences.
730 Right now, it just sets _rl_quick_redisplay if the current visible line
731 is a single line (so we don't have to move vertically or mess with line
732 wrapping). */
733 void
_rl_optimize_redisplay(void)734 _rl_optimize_redisplay (void)
735 {
736 if (_rl_vis_botlin == 0)
737 _rl_quick_redisplay = 1;
738 }
739
740 /* Basic redisplay algorithm. See comments inline. */
741 void
rl_redisplay(void)742 rl_redisplay (void)
743 {
744 int in, out, c, linenum, cursor_linenum;
745 int inv_botlin, lb_botlin, lb_linenum, o_cpos;
746 int newlines, lpos, temp, n0, num, prompt_lines_estimate;
747 char *prompt_this_line;
748 char cur_face;
749 int hl_begin, hl_end;
750 int mb_cur_max = MB_CUR_MAX;
751 #if defined (HANDLE_MULTIBYTE)
752 wchar_t wc;
753 size_t wc_bytes;
754 int wc_width;
755 mbstate_t ps;
756 int _rl_wrapped_multicolumn = 0;
757 #endif
758
759 if (_rl_echoing_p == 0)
760 return;
761
762 /* Block keyboard interrupts because this function manipulates global
763 data structures. */
764 _rl_block_sigint ();
765 RL_SETSTATE (RL_STATE_REDISPLAYING);
766
767 cur_face = FACE_NORMAL;
768 /* Can turn this into an array for multiple highlighted objects in addition
769 to the region */
770 hl_begin = hl_end = -1;
771
772 if (rl_mark_active_p ())
773 set_active_region (&hl_begin, &hl_end);
774
775 if (!rl_display_prompt)
776 rl_display_prompt = "";
777
778 if (line_structures_initialized == 0)
779 {
780 init_line_structures (0);
781 rl_on_new_line ();
782 }
783 else if (line_size <= _rl_screenwidth)
784 init_line_structures (_rl_screenwidth + 1);
785
786 /* Enable horizontal scrolling automatically for terminals of height 1
787 where wrapping lines doesn't work. Disable it as soon as the terminal
788 height is increased again if it was automatically enabled. */
789 if (_rl_screenheight <= 1)
790 {
791 if (_rl_horizontal_scroll_mode == 0)
792 horizontal_scrolling_autoset = 1;
793 _rl_horizontal_scroll_mode = 1;
794 }
795 else if (horizontal_scrolling_autoset)
796 _rl_horizontal_scroll_mode = 0;
797
798 /* Draw the line into the buffer. */
799 cpos_buffer_position = -1;
800
801 prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
802
803 out = inv_botlin = 0;
804
805 /* Mark the line as modified or not. We only do this for history
806 lines. */
807 modmark = 0;
808 if (_rl_mark_modified_lines && current_history () && rl_undo_list)
809 {
810 invis_addc (&out, '*', cur_face);
811 invis_nul (&out);
812 modmark = 1;
813 }
814
815 /* If someone thought that the redisplay was handled, but the currently
816 visible line has a different modification state than the one about
817 to become visible, then correct the caller's misconception. */
818 if (visible_line[0] != invisible_line[0])
819 rl_display_fixed = 0;
820
821 /* If the prompt to be displayed is the `primary' readline prompt (the
822 one passed to readline()), use the values we have already expanded.
823 If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
824 number of non-visible characters (bytes) in the prompt string. */
825 /* This is where we output the characters in the prompt before the last
826 newline, if any. If there aren't any embedded newlines, we don't
827 write anything. Copy the last line of the prompt string into the line in
828 any case */
829 if (rl_display_prompt == rl_prompt || local_prompt)
830 {
831 if (local_prompt_prefix && forced_display)
832 _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
833
834 if (local_prompt_len > 0)
835 invis_adds (&out, local_prompt, local_prompt_len, cur_face);
836 invis_nul (&out);
837 wrap_offset = local_prompt_len - prompt_visible_length;
838 }
839 else
840 {
841 int pmtlen;
842 prompt_this_line = strrchr (rl_display_prompt, '\n');
843 if (!prompt_this_line)
844 prompt_this_line = rl_display_prompt;
845 else
846 {
847 prompt_this_line++;
848 pmtlen = prompt_this_line - rl_display_prompt; /* temp var */
849 if (forced_display)
850 {
851 _rl_output_some_chars (rl_display_prompt, pmtlen);
852 /* Make sure we are at column zero even after a newline,
853 regardless of the state of terminal output processing. */
854 if (pmtlen < 2 || prompt_this_line[-2] != '\r')
855 cr ();
856 }
857 }
858
859 prompt_physical_chars = pmtlen = strlen (prompt_this_line); /* XXX */
860 invis_adds (&out, prompt_this_line, pmtlen, cur_face);
861 invis_nul (&out);
862 wrap_offset = prompt_invis_chars_first_line = 0;
863 }
864
865 #if defined (HANDLE_MULTIBYTE)
866 #define CHECK_INV_LBREAKS() \
867 do { \
868 if (newlines >= (inv_lbsize - 2)) \
869 { \
870 inv_lbsize *= 2; \
871 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
872 } \
873 if (newlines >= (line_state_invisible->wbsize - 2)) \
874 { \
875 line_state_invisible->wbsize *= 2; \
876 line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
877 } \
878 } while (0)
879 #else
880 #define CHECK_INV_LBREAKS() \
881 do { \
882 if (newlines >= (inv_lbsize - 2)) \
883 { \
884 inv_lbsize *= 2; \
885 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
886 } \
887 } while (0)
888 #endif /* !HANDLE_MULTIBYTE */
889
890 #if defined (HANDLE_MULTIBYTE)
891 #define CHECK_LPOS() \
892 do { \
893 lpos++; \
894 if (lpos >= _rl_screenwidth) \
895 { \
896 if (newlines >= (inv_lbsize - 2)) \
897 { \
898 inv_lbsize *= 2; \
899 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
900 } \
901 inv_lbreaks[++newlines] = out; \
902 if (newlines >= (line_state_invisible->wbsize - 2)) \
903 { \
904 line_state_invisible->wbsize *= 2; \
905 line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
906 } \
907 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
908 lpos = 0; \
909 } \
910 } while (0)
911 #else
912 #define CHECK_LPOS() \
913 do { \
914 lpos++; \
915 if (lpos >= _rl_screenwidth) \
916 { \
917 if (newlines >= (inv_lbsize - 2)) \
918 { \
919 inv_lbsize *= 2; \
920 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
921 } \
922 inv_lbreaks[++newlines] = out; \
923 lpos = 0; \
924 } \
925 } while (0)
926 #endif
927
928 /* inv_lbreaks[i] is where line i starts in the buffer. */
929 inv_lbreaks[newlines = 0] = 0;
930 /* lpos is a physical cursor position, so it needs to be adjusted by the
931 number of invisible characters in the prompt, per line. We compute
932 the line breaks in the prompt string in expand_prompt, taking invisible
933 characters into account, and if lpos exceeds the screen width, we copy
934 the data in the loop below. */
935 if (local_prompt)
936 lpos = prompt_physical_chars + modmark;
937 else
938 lpos = 0;
939
940 #if defined (HANDLE_MULTIBYTE)
941 memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
942 num = 0;
943 #endif
944
945 /* prompt_invis_chars_first_line is the number of invisible characters (bytes)
946 in the first physical line of the prompt.
947 wrap_offset - prompt_invis_chars_first_line is usually the number of
948 invis chars on the second (or, more generally, last) line. */
949
950 /* This is zero-based, used to set the newlines */
951 prompt_lines_estimate = lpos / _rl_screenwidth;
952
953 /* what if lpos is already >= _rl_screenwidth before we start drawing the
954 contents of the command line? */
955 if (lpos >= _rl_screenwidth)
956 {
957 temp = 0;
958
959 /* first copy the linebreaks array we computed in expand_prompt */
960 while (local_prompt_newlines[newlines+1] != -1)
961 {
962 temp = local_prompt_newlines[newlines+1];
963 inv_lbreaks[++newlines] = temp;
964 }
965
966 /* Now set lpos from the last newline */
967 if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
968 lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
969 else
970 lpos -= (_rl_screenwidth * newlines);
971 }
972
973 prompt_last_screen_line = newlines;
974
975 /* Draw the rest of the line (after the prompt) into invisible_line, keeping
976 track of where the cursor is (cpos_buffer_position), the number of the
977 line containing the cursor (lb_linenum), the last line number (lb_botlin
978 and inv_botlin).
979 It maintains an array of line breaks for display (inv_lbreaks).
980 This handles expanding tabs for display and displaying meta characters. */
981 lb_linenum = 0;
982 #if defined (HANDLE_MULTIBYTE)
983 in = 0;
984 if (mb_cur_max > 1 && rl_byte_oriented == 0)
985 {
986 memset (&ps, 0, sizeof (mbstate_t));
987 if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[0]))
988 {
989 wc = (wchar_t)rl_line_buffer[0];
990 wc_bytes = 1;
991 }
992 else
993 wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
994 }
995 else
996 wc_bytes = 1;
997 while (in < rl_end)
998 #else
999 for (in = 0; in < rl_end; in++)
1000 #endif
1001 {
1002 if (in == hl_begin)
1003 cur_face = FACE_STANDOUT;
1004 else if (in == hl_end)
1005 cur_face = FACE_NORMAL;
1006
1007 c = (unsigned char)rl_line_buffer[in];
1008
1009 #if defined (HANDLE_MULTIBYTE)
1010 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1011 {
1012 if (MB_INVALIDCH (wc_bytes))
1013 {
1014 /* Byte sequence is invalid or shortened. Assume that the
1015 first byte represents a character. */
1016 wc_bytes = 1;
1017 /* Assume that a character occupies a single column. */
1018 wc_width = 1;
1019 memset (&ps, 0, sizeof (mbstate_t));
1020 }
1021 else if (MB_NULLWCH (wc_bytes))
1022 break; /* Found '\0' */
1023 else
1024 {
1025 temp = WCWIDTH (wc);
1026 wc_width = (temp >= 0) ? temp : 1;
1027 }
1028 }
1029 #endif
1030
1031 if (in == rl_point)
1032 {
1033 cpos_buffer_position = out;
1034 lb_linenum = newlines;
1035 }
1036
1037 #if defined (HANDLE_MULTIBYTE)
1038 if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
1039 #else
1040 if (META_CHAR (c))
1041 #endif
1042 {
1043 if (_rl_output_meta_chars == 0)
1044 {
1045 char obuf[5];
1046 int olen;
1047
1048 olen = sprintf (obuf, "\\%o", c);
1049
1050 if (lpos + olen >= _rl_screenwidth)
1051 {
1052 temp = _rl_screenwidth - lpos;
1053 CHECK_INV_LBREAKS ();
1054 inv_lbreaks[++newlines] = out + temp;
1055 #if defined (HANDLE_MULTIBYTE)
1056 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1057 #endif
1058 lpos = olen - temp;
1059 }
1060 else
1061 lpos += olen;
1062
1063 for (temp = 0; temp < olen; temp++)
1064 {
1065 invis_addc (&out, obuf[temp], cur_face);
1066 CHECK_LPOS ();
1067 }
1068 }
1069 else
1070 {
1071 invis_addc (&out, c, cur_face);
1072 CHECK_LPOS();
1073 }
1074 }
1075 #if defined (DISPLAY_TABS)
1076 else if (c == '\t')
1077 {
1078 register int newout;
1079
1080 newout = out + 8 - lpos % 8;
1081 temp = newout - out;
1082 if (lpos + temp >= _rl_screenwidth)
1083 {
1084 register int temp2;
1085 temp2 = _rl_screenwidth - lpos;
1086 CHECK_INV_LBREAKS ();
1087 inv_lbreaks[++newlines] = out + temp2;
1088 #if defined (HANDLE_MULTIBYTE)
1089 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1090 #endif
1091 lpos = temp - temp2;
1092 while (out < newout)
1093 invis_addc (&out, ' ', cur_face);
1094 }
1095 else
1096 {
1097 while (out < newout)
1098 invis_addc (&out, ' ', cur_face);
1099 lpos += temp;
1100 }
1101 }
1102 #endif
1103 else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1104 {
1105 invis_addc (&out, '\0', cur_face);
1106 CHECK_INV_LBREAKS ();
1107 inv_lbreaks[++newlines] = out;
1108 #if defined (HANDLE_MULTIBYTE)
1109 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1110 #endif
1111 lpos = 0;
1112 }
1113 else if (CTRL_CHAR (c) || c == RUBOUT)
1114 {
1115 invis_addc (&out, '^', cur_face);
1116 CHECK_LPOS();
1117 invis_addc (&out, CTRL_CHAR (c) ? UNCTRL (c) : '?', cur_face);
1118 CHECK_LPOS();
1119 }
1120 else
1121 {
1122 #if defined (HANDLE_MULTIBYTE)
1123 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1124 {
1125 register int i;
1126
1127 _rl_wrapped_multicolumn = 0;
1128
1129 if (_rl_screenwidth < lpos + wc_width)
1130 for (i = lpos; i < _rl_screenwidth; i++)
1131 {
1132 /* The space will be removed in update_line() */
1133 invis_addc (&out, ' ', cur_face);
1134 _rl_wrapped_multicolumn++;
1135 CHECK_LPOS();
1136 }
1137 if (in == rl_point)
1138 {
1139 cpos_buffer_position = out;
1140 lb_linenum = newlines;
1141 }
1142 for (i = in; i < in+wc_bytes; i++)
1143 invis_addc (&out, rl_line_buffer[i], cur_face);
1144 for (i = 0; i < wc_width; i++)
1145 CHECK_LPOS();
1146 }
1147 else
1148 {
1149 invis_addc (&out, c, cur_face);
1150 CHECK_LPOS();
1151 }
1152 #else
1153 invis_addc (&out, c, cur_face);
1154 CHECK_LPOS();
1155 #endif
1156 }
1157
1158 #if defined (HANDLE_MULTIBYTE)
1159 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1160 {
1161 in += wc_bytes;
1162 if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[in]))
1163 {
1164 wc = (wchar_t)rl_line_buffer[in];
1165 wc_bytes = 1;
1166 memset (&ps, 0, sizeof (mbstate_t)); /* re-init state */
1167 }
1168 else
1169 wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
1170 }
1171 else
1172 in++;
1173 #endif
1174 }
1175 invis_nul (&out);
1176 line_totbytes = out;
1177 if (cpos_buffer_position < 0)
1178 {
1179 cpos_buffer_position = out;
1180 lb_linenum = newlines;
1181 }
1182
1183 /* If we are switching from one line to multiple wrapped lines, we don't
1184 want to do a dumb update (or we want to make it smarter). */
1185 if (_rl_quick_redisplay && newlines > 0)
1186 _rl_quick_redisplay = 0;
1187
1188 inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
1189 CHECK_INV_LBREAKS ();
1190 inv_lbreaks[newlines+1] = out;
1191 #if defined (HANDLE_MULTIBYTE)
1192 /* This should be 0 anyway */
1193 line_state_invisible->wrapped_line[newlines+1] = _rl_wrapped_multicolumn;
1194 #endif
1195 cursor_linenum = lb_linenum;
1196
1197 /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
1198 CURSOR_LINENUM == line number where the cursor should be placed. */
1199
1200 /* PWP: now is when things get a bit hairy. The visible and invisible
1201 line buffers are really multiple lines, which would wrap every
1202 (screenwidth - 1) characters. Go through each in turn, finding
1203 the changed region and updating it. The line order is top to bottom. */
1204
1205 /* If we can move the cursor up and down, then use multiple lines,
1206 otherwise, let long lines display in a single terminal line, and
1207 horizontally scroll it. */
1208 displaying_prompt_first_line = 1;
1209 if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1210 {
1211 int nleft, pos, changed_screen_line, tx;
1212
1213 if (!rl_display_fixed || forced_display)
1214 {
1215 forced_display = 0;
1216
1217 /* If we have more than a screenful of material to display, then
1218 only display a screenful. We should display the last screen,
1219 not the first. */
1220 if (out >= _rl_screenchars)
1221 {
1222 #if defined (HANDLE_MULTIBYTE)
1223 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1224 out = _rl_find_prev_mbchar (invisible_line, _rl_screenchars, MB_FIND_ANY);
1225 else
1226 #endif
1227 out = _rl_screenchars - 1;
1228 }
1229
1230 /* The first line is at character position 0 in the buffer. The
1231 second and subsequent lines start at inv_lbreaks[N], offset by
1232 OFFSET (which has already been calculated above). */
1233
1234 #define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
1235 #define WRAP_OFFSET(line, offset) ((line == 0) \
1236 ? (offset ? INVIS_FIRST() : 0) \
1237 : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
1238 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
1239 #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
1240 #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
1241 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
1242 #define VIS_FACE(line) (vis_face + vis_lbreaks[line])
1243 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
1244 #define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
1245 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
1246 #define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
1247
1248 #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
1249 _rl_last_c_pos != o_cpos && \
1250 _rl_last_c_pos > wrap_offset && \
1251 o_cpos < prompt_last_invisible)
1252
1253
1254 /* We don't want to highlight anything that's going to be off the top
1255 of the display; if the current line takes up more than an entire
1256 screen, just mark the lines that won't be displayed as having a
1257 `normal' face.
1258 It's imperfect, but better than display corruption. */
1259 if (rl_mark_active_p () && inv_botlin > _rl_screenheight)
1260 {
1261 int extra;
1262
1263 extra = inv_botlin - _rl_screenheight;
1264 for (linenum = 0; linenum <= extra; linenum++)
1265 norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
1266 }
1267
1268 /* For each line in the buffer, do the updating display. */
1269 for (linenum = 0; linenum <= inv_botlin; linenum++)
1270 {
1271 /* This can lead us astray if we execute a program that changes
1272 the locale from a non-multibyte to a multibyte one. */
1273 o_cpos = _rl_last_c_pos;
1274 cpos_adjusted = 0;
1275 update_line (VIS_LINE(linenum), VIS_LINE_FACE(linenum),
1276 INV_LINE(linenum), INV_LINE_FACE(linenum),
1277 linenum,
1278 VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
1279
1280 /* update_line potentially changes _rl_last_c_pos, but doesn't
1281 take invisible characters into account, since _rl_last_c_pos
1282 is an absolute cursor position in a multibyte locale. We
1283 choose to (mostly) compensate for that here, rather than
1284 change update_line itself. There are several cases in which
1285 update_line adjusts _rl_last_c_pos itself (so it can pass
1286 _rl_move_cursor_relative accurate values); it communicates
1287 this back by setting cpos_adjusted. If we assume that
1288 _rl_last_c_pos is correct (an absolute cursor position) each
1289 time update_line is called, then we can assume in our
1290 calculations that o_cpos does not need to be adjusted by
1291 wrap_offset. */
1292 if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
1293 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1294 else if (cpos_adjusted == 0 &&
1295 linenum == prompt_last_screen_line &&
1296 prompt_physical_chars > _rl_screenwidth &&
1297 (mb_cur_max > 1 && rl_byte_oriented == 0) &&
1298 _rl_last_c_pos != o_cpos &&
1299 _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line)) /* XXX - rethink this last one */
1300 /* This assumes that all the invisible characters are split
1301 between the first and last lines of the prompt, if the
1302 prompt consumes more than two lines. It's usually right */
1303 /* XXX - not sure this is ever executed */
1304 _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
1305
1306 /* If this is the line with the prompt, we might need to
1307 compensate for invisible characters in the new line. Do
1308 this only if there is not more than one new line (which
1309 implies that we completely overwrite the old visible line)
1310 and the new line is shorter than the old. Make sure we are
1311 at the end of the new line before clearing. */
1312 if (linenum == 0 &&
1313 inv_botlin == 0 && _rl_last_c_pos == out &&
1314 (wrap_offset > visible_wrap_offset) &&
1315 (_rl_last_c_pos < visible_first_line_len))
1316 {
1317 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1318 nleft = _rl_screenwidth - _rl_last_c_pos;
1319 else
1320 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1321 if (nleft)
1322 _rl_clear_to_eol (nleft);
1323 }
1324 #if 0
1325 /* This segment is intended to handle the case where the old
1326 visible prompt has invisible characters and the new line
1327 to be displayed needs to clear the rest of the old characters
1328 out (e.g., when printing the i-search prompt): in general,
1329 the case of the new line being shorter than the old. We need
1330 to be at the end of the new line and the old line needs to be
1331 longer than the current cursor position. It's not perfect,
1332 since it uses the byte length of the first line, but this will
1333 at worst result in some extra clear-to-end-of-lines. We can't
1334 use the prompt length variables because they may not
1335 correspond to the visible line (see printing the i-search
1336 prompt above). The tests for differing numbers of invisible
1337 characters may not matter and can probably be removed. */
1338 else if (linenum == 0 &&
1339 linenum == prompt_last_screen_line &&
1340 _rl_last_c_pos == out &&
1341 _rl_last_c_pos < visible_first_line_len &&
1342 visible_wrap_offset &&
1343 visible_wrap_offset != wrap_offset)
1344 {
1345 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1346 nleft = _rl_screenwidth - _rl_last_c_pos;
1347 else
1348 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1349 if (nleft)
1350 _rl_clear_to_eol (nleft);
1351 }
1352 #endif
1353
1354 /* Since the new first line is now visible, save its length. */
1355 if (linenum == 0)
1356 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
1357 }
1358
1359 /* We may have deleted some lines. If so, clear the left over
1360 blank ones at the bottom out. */
1361 if (_rl_vis_botlin > inv_botlin)
1362 {
1363 char *tt;
1364 for (; linenum <= _rl_vis_botlin; linenum++)
1365 {
1366 tt = VIS_CHARS (linenum);
1367 _rl_move_vert (linenum);
1368 _rl_move_cursor_relative (0, tt, VIS_FACE(linenum));
1369 _rl_clear_to_eol
1370 ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
1371 }
1372 }
1373 _rl_vis_botlin = inv_botlin;
1374
1375 /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
1376 different screen line during this redisplay. */
1377 changed_screen_line = _rl_last_v_pos != cursor_linenum;
1378 if (changed_screen_line)
1379 {
1380 _rl_move_vert (cursor_linenum);
1381 /* If we moved up to the line with the prompt using _rl_term_up,
1382 the physical cursor position on the screen stays the same,
1383 but the buffer position needs to be adjusted to account
1384 for invisible characters. */
1385 if ((mb_cur_max == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
1386 _rl_last_c_pos += wrap_offset;
1387 }
1388
1389 /* Now we move the cursor to where it needs to be. First, make
1390 sure we are on the correct line (cursor_linenum). */
1391
1392 /* We have to reprint the prompt if it contains invisible
1393 characters, since it's not generally OK to just reprint
1394 the characters from the current cursor position. But we
1395 only need to reprint it if the cursor is before the last
1396 invisible character in the prompt string. */
1397 /* XXX - why not use local_prompt_len? */
1398 nleft = prompt_visible_length + wrap_offset;
1399 if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1400 _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1401 {
1402 _rl_cr ();
1403 if (modmark)
1404 _rl_output_some_chars ("*", 1);
1405
1406 _rl_output_some_chars (local_prompt, nleft);
1407 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1408 _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
1409 else
1410 _rl_last_c_pos = nleft + modmark;
1411 }
1412
1413 /* Where on that line? And where does that line start
1414 in the buffer? */
1415 pos = inv_lbreaks[cursor_linenum];
1416 /* nleft == number of characters (bytes) in the line buffer between
1417 the start of the line and the desired cursor position. */
1418 nleft = cpos_buffer_position - pos;
1419
1420 /* NLEFT is now a number of characters in a buffer. When in a
1421 multibyte locale, however, _rl_last_c_pos is an absolute cursor
1422 position that doesn't take invisible characters in the prompt
1423 into account. We use a fudge factor to compensate. */
1424
1425 /* Since _rl_backspace() doesn't know about invisible characters in
1426 the prompt, and there's no good way to tell it, we compensate for
1427 those characters here and call _rl_backspace() directly if
1428 necessary */
1429 if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
1430 {
1431 /* TX == new physical cursor position in multibyte locale. */
1432 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1433 tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
1434 else
1435 tx = nleft;
1436 if (tx >= 0 && _rl_last_c_pos > tx)
1437 {
1438 _rl_backspace (_rl_last_c_pos - tx); /* XXX */
1439 _rl_last_c_pos = tx;
1440 }
1441 }
1442
1443 /* We need to note that in a multibyte locale we are dealing with
1444 _rl_last_c_pos as an absolute cursor position, but moving to a
1445 point specified by a buffer position (NLEFT) that doesn't take
1446 invisible characters into account. */
1447 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1448 _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1449 else if (nleft != _rl_last_c_pos)
1450 _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1451 }
1452 }
1453 else /* Do horizontal scrolling. Much simpler */
1454 {
1455 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
1456 int lmargin, ndisp, nleft, phys_c_pos, t;
1457
1458 /* Always at top line. */
1459 _rl_last_v_pos = 0;
1460
1461 /* Compute where in the buffer the displayed line should start. This
1462 will be LMARGIN. */
1463
1464 /* The number of characters that will be displayed before the cursor. */
1465 ndisp = cpos_buffer_position - wrap_offset;
1466 nleft = prompt_visible_length + wrap_offset;
1467 /* Where the new cursor position will be on the screen. This can be
1468 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1469 phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
1470 t = _rl_screenwidth / 3;
1471
1472 /* If the number of characters had already exceeded the screenwidth,
1473 last_lmargin will be > 0. */
1474
1475 /* If the number of characters to be displayed is more than the screen
1476 width, compute the starting offset so that the cursor is about
1477 two-thirds of the way across the screen. */
1478 if (phys_c_pos > _rl_screenwidth - 2)
1479 {
1480 lmargin = cpos_buffer_position - (2 * t);
1481 if (lmargin < 0)
1482 lmargin = 0;
1483 /* If the left margin would be in the middle of a prompt with
1484 invisible characters, don't display the prompt at all. */
1485 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1486 lmargin = nleft;
1487 }
1488 else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
1489 lmargin = 0;
1490 else if (phys_c_pos < 1)
1491 {
1492 /* If we are moving back towards the beginning of the line and
1493 the last margin is no longer correct, compute a new one. */
1494 lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */
1495 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1496 lmargin = nleft;
1497 }
1498 else
1499 lmargin = last_lmargin;
1500
1501 displaying_prompt_first_line = lmargin < nleft;
1502
1503 /* If the first character on the screen isn't the first character
1504 in the display line, indicate this with a special character. */
1505 if (lmargin > 0)
1506 invisible_line[lmargin] = '<';
1507
1508 /* If SCREENWIDTH characters starting at LMARGIN do not encompass
1509 the whole line, indicate that with a special character at the
1510 right edge of the screen. If LMARGIN is 0, we need to take the
1511 wrap offset into account. */
1512 t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1513 if (t > 0 && t < out)
1514 invisible_line[t - 1] = '>';
1515
1516 if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
1517 {
1518 forced_display = 0;
1519 o_cpos = _rl_last_c_pos;
1520 cpos_adjusted = 0;
1521 update_line (&visible_line[last_lmargin], &vis_face[last_lmargin],
1522 &invisible_line[lmargin], &inv_face[lmargin],
1523 0,
1524 _rl_screenwidth + visible_wrap_offset,
1525 _rl_screenwidth + (lmargin ? 0 : wrap_offset),
1526 0);
1527
1528 if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1529 displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
1530 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1531
1532 /* If the visible new line is shorter than the old, but the number
1533 of invisible characters is greater, and we are at the end of
1534 the new line, we need to clear to eol. */
1535 t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
1536 if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
1537 (_rl_last_c_pos == out) && displaying_prompt_first_line &&
1538 t < visible_first_line_len)
1539 {
1540 nleft = _rl_screenwidth - t;
1541 _rl_clear_to_eol (nleft);
1542 }
1543 visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
1544 if (visible_first_line_len > _rl_screenwidth)
1545 visible_first_line_len = _rl_screenwidth;
1546
1547 _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin], &inv_face[lmargin]);
1548 last_lmargin = lmargin;
1549 }
1550 }
1551 fflush (rl_outstream);
1552
1553 /* Swap visible and non-visible lines. */
1554 {
1555 struct line_state *vtemp = line_state_visible;
1556
1557 line_state_visible = line_state_invisible;
1558 line_state_invisible = vtemp;
1559
1560 rl_display_fixed = 0;
1561 /* If we are displaying on a single line, and last_lmargin is > 0, we
1562 are not displaying any invisible characters, so set visible_wrap_offset
1563 to 0. */
1564 if (_rl_horizontal_scroll_mode && last_lmargin)
1565 visible_wrap_offset = 0;
1566 else
1567 visible_wrap_offset = wrap_offset;
1568
1569 _rl_quick_redisplay = 0;
1570 }
1571
1572 RL_UNSETSTATE (RL_STATE_REDISPLAYING);
1573 _rl_release_sigint ();
1574 }
1575
1576 static void
putc_face(int c,int face,char * cur_face)1577 putc_face (int c, int face, char *cur_face)
1578 {
1579 char cf;
1580 cf = *cur_face;
1581 if (cf != face)
1582 {
1583 if (cf != FACE_NORMAL && cf != FACE_STANDOUT)
1584 return;
1585 if (face != FACE_NORMAL && face != FACE_STANDOUT)
1586 return;
1587 if (face == FACE_STANDOUT && cf == FACE_NORMAL)
1588 _rl_standout_on ();
1589 if (face == FACE_NORMAL && cf == FACE_STANDOUT)
1590 _rl_standout_off ();
1591 *cur_face = face;
1592 }
1593 if (c != EOF)
1594 putc (c, rl_outstream);
1595 }
1596
1597 static void
puts_face(const char * str,const char * face,int n)1598 puts_face (const char *str, const char *face, int n)
1599 {
1600 int i;
1601 char cur_face;
1602
1603 for (cur_face = FACE_NORMAL, i = 0; i < n; i++)
1604 putc_face (str[i], face[i], &cur_face);
1605 putc_face (EOF, FACE_NORMAL, &cur_face);
1606 }
1607
1608 static void
norm_face(char * face,int n)1609 norm_face (char *face, int n)
1610 {
1611 memset (face, FACE_NORMAL, n);
1612 }
1613
1614 #define ADJUST_CPOS(x) do { _rl_last_c_pos -= (x) ; cpos_adjusted = 1; } while (0)
1615
1616 /* PWP: update_line() is based on finding the middle difference of each
1617 line on the screen; vis:
1618
1619 /old first difference
1620 /beginning of line | /old last same /old EOL
1621 v v v v
1622 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1623 new: eddie> Oh, my little buggy says to me, as lurgid as
1624 ^ ^ ^ ^
1625 \beginning of line | \new last same \new end of line
1626 \new first difference
1627
1628 All are character pointers for the sake of speed. Special cases for
1629 no differences, as well as for end of line additions must be handled.
1630
1631 Could be made even smarter, but this works well enough */
1632 static void
update_line(char * old,char * old_face,char * new,char * new_face,int current_line,int omax,int nmax,int inv_botlin)1633 update_line (char *old, char *old_face, char *new, char *new_face, int current_line, int omax, int nmax, int inv_botlin)
1634 {
1635 char *ofd, *ols, *oe, *nfd, *nls, *ne;
1636 char *ofdf, *nfdf, *olsf, *nlsf;
1637 int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
1638 int current_invis_chars;
1639 int col_lendiff, col_temp;
1640 int bytes_to_insert;
1641 int mb_cur_max = MB_CUR_MAX;
1642 #if defined (HANDLE_MULTIBYTE)
1643 mbstate_t ps_new, ps_old;
1644 int new_offset, old_offset;
1645 #endif
1646
1647 /* If we're at the right edge of a terminal that supports xn, we're
1648 ready to wrap around, so do so. This fixes problems with knowing
1649 the exact cursor position and cut-and-paste with certain terminal
1650 emulators. In this calculation, TEMP is the physical screen
1651 position of the cursor. */
1652 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1653 temp = _rl_last_c_pos;
1654 else
1655 temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
1656 if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1657 && _rl_last_v_pos == current_line - 1)
1658 {
1659 /* We're going to wrap around by writing the first character of NEW to
1660 the screen and dealing with changes to what's visible by modifying
1661 OLD to match it. Complicated by the presence of multi-width
1662 characters at the end of the line or beginning of the new one. */
1663 /* old is always somewhere in visible_line; new is always somewhere in
1664 invisible_line. These should always be null-terminated. */
1665 #if defined (HANDLE_MULTIBYTE)
1666 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1667 {
1668 wchar_t wc;
1669 mbstate_t ps;
1670 int oldwidth, newwidth;
1671 int oldbytes, newbytes;
1672 size_t ret;
1673
1674 /* This fixes only double-column characters, but if the wrapped
1675 character consumes more than three columns, spaces will be
1676 inserted in the string buffer. */
1677 /* XXX remember that we are working on the invisible line right now;
1678 we don't swap visible and invisible until just before rl_redisplay
1679 returns */
1680 /* This will remove the extra placeholder space we added with
1681 _rl_wrapped_multicolumn */
1682 if (current_line < line_state_invisible->wbsize && line_state_invisible->wrapped_line[current_line] > 0)
1683 _rl_clear_to_eol (line_state_invisible->wrapped_line[current_line]);
1684
1685 /* 1. how many screen positions does first char in old consume? */
1686 memset (&ps, 0, sizeof (mbstate_t));
1687 ret = mbrtowc (&wc, old, mb_cur_max, &ps);
1688 oldbytes = ret;
1689 if (MB_INVALIDCH (ret))
1690 {
1691 oldwidth = 1;
1692 oldbytes = 1;
1693 }
1694 else if (MB_NULLWCH (ret))
1695 oldwidth = 0;
1696 else
1697 oldwidth = WCWIDTH (wc);
1698 if (oldwidth < 0)
1699 oldwidth = 1;
1700
1701 /* 2. how many screen positions does the first char in new consume? */
1702 memset (&ps, 0, sizeof (mbstate_t));
1703 ret = mbrtowc (&wc, new, mb_cur_max, &ps);
1704 newbytes = ret;
1705 if (MB_INVALIDCH (ret))
1706 {
1707 newwidth = 1;
1708 newbytes = 1;
1709 }
1710 else if (MB_NULLWCH (ret))
1711 newwidth = 0;
1712 else
1713 newwidth = WCWIDTH (wc);
1714 if (newwidth < 0)
1715 newwidth = 1;
1716
1717 /* 3. if the new width is less than the old width, we need to keep
1718 going in new until we have consumed at least that many screen
1719 positions, and figure out how many bytes that will take */
1720 while (newbytes < nmax && newwidth < oldwidth)
1721 {
1722 int t;
1723
1724 ret = mbrtowc (&wc, new+newbytes, mb_cur_max, &ps);
1725 if (MB_INVALIDCH (ret))
1726 {
1727 newwidth += 1;
1728 newbytes += 1;
1729 }
1730 else if (MB_NULLWCH (ret))
1731 break;
1732 else
1733 {
1734 t = WCWIDTH (wc);
1735 newwidth += (t >= 0) ? t : 1;
1736 newbytes += ret;
1737 }
1738 }
1739 /* 4. If the new width is more than the old width, keep going in old
1740 until we have consumed exactly that many screen positions, and
1741 figure out how many bytes that will take. This is an optimization */
1742 while (oldbytes < omax && oldwidth < newwidth)
1743 {
1744 int t;
1745
1746 ret = mbrtowc (&wc, old+oldbytes, mb_cur_max, &ps);
1747 if (MB_INVALIDCH (ret))
1748 {
1749 oldwidth += 1;
1750 oldbytes += 1;
1751 }
1752 else if (MB_NULLWCH (ret))
1753 break;
1754 else
1755 {
1756 t = WCWIDTH (wc);
1757 oldwidth += (t >= 0) ? t : 1;
1758 oldbytes += ret;
1759 }
1760 }
1761 /* 5. write the first newbytes of new, which takes newwidth. This is
1762 where the screen wrapping takes place, and we are now writing
1763 characters onto the new line. We need to fix up old so it
1764 accurately reflects what is on the screen after the
1765 _rl_output_some_chars below. */
1766 if (newwidth > 0)
1767 {
1768 int count, i, j;
1769 char *optr;
1770
1771 puts_face (new, new_face, newbytes);
1772 _rl_last_c_pos = newwidth;
1773 _rl_last_v_pos++;
1774
1775 /* 5a. If the number of screen positions doesn't match, punt
1776 and do a dumb update.
1777 5b. If the number of bytes is greater in the new line than
1778 the old, do a dumb update, because there is no guarantee we
1779 can extend the old line enough to fit the new bytes. */
1780 if (newwidth != oldwidth || newbytes > oldbytes)
1781 {
1782 oe = old + omax;
1783 ne = new + nmax;
1784 nd = newbytes;
1785 nfd = new + nd;
1786 ofdf = old_face + oldbytes;
1787 nfdf = new_face + newbytes;
1788
1789 goto dumb_update;
1790 }
1791 if (oldbytes != 0 && newbytes != 0)
1792 {
1793 /* We have written as many bytes from new as we need to
1794 consume the first character of old. Fix up `old' so it
1795 reflects the new screen contents. We use +1 in the
1796 memmove call to copy the trailing NUL. */
1797 /* (strlen(old+oldbytes) == (omax - oldbytes - 1)) */
1798
1799 /* Don't bother trying to fit the bytes if the number of bytes
1800 doesn't change. */
1801 if (oldbytes != newbytes)
1802 {
1803 memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
1804 memmove (old_face+newbytes, old_face+oldbytes, strlen (old+oldbytes) + 1);
1805 }
1806 memcpy (old, new, newbytes);
1807 memcpy (old_face, new_face, newbytes);
1808 j = newbytes - oldbytes;
1809 omax += j;
1810 /* Fix up indices if we copy data from one line to another */
1811 for (i = current_line+1; j != 0 && i <= inv_botlin+1 && i <=_rl_vis_botlin+1; i++)
1812 vis_lbreaks[i] += j;
1813 }
1814 }
1815 else
1816 {
1817 putc (' ', rl_outstream);
1818 _rl_last_c_pos = 1;
1819 _rl_last_v_pos++;
1820 if (old[0] && new[0])
1821 {
1822 old[0] = new[0];
1823 old_face[0] = new_face[0];
1824 }
1825 }
1826 }
1827 else
1828 #endif
1829 {
1830 if (new[0])
1831 puts_face (new, new_face, 1);
1832 else
1833 putc (' ', rl_outstream);
1834 _rl_last_c_pos = 1;
1835 _rl_last_v_pos++;
1836 if (old[0] && new[0])
1837 {
1838 old[0] = new[0];
1839 old_face[0] = new_face[0];
1840 }
1841 }
1842 }
1843
1844 /* We know that we are dealing with a single screen line here */
1845 if (_rl_quick_redisplay)
1846 {
1847 nfd = new;
1848 nfdf = new_face;
1849 ofd = old;
1850 ofdf = old_face;
1851 for (od = 0, oe = ofd; od < omax && *oe; oe++, od++);
1852 for (nd = 0, ne = nfd; nd < nmax && *ne; ne++, nd++);
1853 od = nd = 0;
1854 _rl_move_cursor_relative (0, old, old_face);
1855
1856 bytes_to_insert = ne - nfd;
1857 if (bytes_to_insert < local_prompt_len) /* ??? */
1858 goto dumb_update;
1859
1860 /* output the prompt, output the line contents, clear the rest */
1861 _rl_output_some_chars (nfd, local_prompt_len);
1862 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1863 _rl_last_c_pos = prompt_physical_chars;
1864 else
1865 _rl_last_c_pos = local_prompt_len;
1866
1867 bytes_to_insert -= local_prompt_len;
1868 if (bytes_to_insert > 0)
1869 {
1870 puts_face (new+local_prompt_len, nfdf+local_prompt_len, bytes_to_insert);
1871 if (mb_cur_max > 1 && rl_byte_oriented)
1872 _rl_last_c_pos += _rl_col_width (new, local_prompt_len, ne-new, 1);
1873 else
1874 _rl_last_c_pos += bytes_to_insert;
1875 }
1876
1877 /* See comments at dumb_update: for an explanation of this heuristic */
1878 if (nmax < omax)
1879 goto clear_rest_of_line;
1880 else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
1881 goto clear_rest_of_line;
1882 else
1883 return;
1884 }
1885
1886 /* Find first difference. */
1887 #if defined (HANDLE_MULTIBYTE)
1888 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1889 {
1890 /* See if the old line is a subset of the new line, so that the
1891 only change is adding characters. */
1892 temp = (omax < nmax) ? omax : nmax;
1893 if (memcmp (old, new, temp) == 0 && memcmp (old_face, new_face, temp) == 0)
1894 {
1895 new_offset = old_offset = temp; /* adding at the end */
1896 ofd = old + temp;
1897 ofdf = old_face + temp;
1898 nfd = new + temp;
1899 nfdf = new_face + temp;
1900 }
1901 else
1902 {
1903 memset (&ps_new, 0, sizeof(mbstate_t));
1904 memset (&ps_old, 0, sizeof(mbstate_t));
1905
1906 /* Are the old and new lines the same? */
1907 if (omax == nmax && memcmp (new, old, omax) == 0 && memcmp (new_face, old_face, omax) == 0)
1908 {
1909 old_offset = omax;
1910 new_offset = nmax;
1911 ofd = old + omax;
1912 ofdf = old_face + omax;
1913 nfd = new + nmax;
1914 nfdf = new_face + nmax;
1915 }
1916 else
1917 {
1918 /* Go through the line from the beginning and find the first
1919 difference. We assume that faces change at (possibly multi-
1920 byte) character boundaries. */
1921 new_offset = old_offset = 0;
1922 for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
1923 (ofd - old < omax) && *ofd &&
1924 _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new) &&
1925 *ofdf == *nfdf; )
1926 {
1927 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1928 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1929
1930 ofd = old + old_offset;
1931 ofdf = old_face + old_offset;
1932 nfd = new + new_offset;
1933 nfdf = new_face + new_offset;
1934 }
1935 }
1936 }
1937 }
1938 else
1939 #endif
1940 for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
1941 (ofd - old < omax) && *ofd && (*ofd == *nfd) && (*ofdf == *nfdf);
1942 ofd++, nfd++, ofdf++, nfdf++)
1943 ;
1944
1945 /* Move to the end of the screen line. ND and OD are used to keep track
1946 of the distance between ne and new and oe and old, respectively, to
1947 move a subtraction out of each loop. */
1948 for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1949 for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1950
1951 /* If no difference, continue to next line. */
1952 if (ofd == oe && nfd == ne)
1953 return;
1954
1955 #if defined (HANDLE_MULTIBYTE)
1956 if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
1957 {
1958 wchar_t wc;
1959 mbstate_t ps = { 0 };
1960 int t;
1961
1962 /* If the first character in the difference is a zero-width character,
1963 assume it's a combining character and back one up so the two base
1964 characters no longer compare equivalently. */
1965 t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
1966 if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
1967 {
1968 old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
1969 new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
1970 ofd = old + old_offset; /* equal by definition */
1971 ofdf = old_face + old_offset;
1972 nfd = new + new_offset;
1973 nfdf = new_face + new_offset;
1974 }
1975 }
1976 #endif
1977
1978 wsatend = 1; /* flag for trailing whitespace */
1979
1980 #if defined (HANDLE_MULTIBYTE)
1981 /* Find the last character that is the same between the two lines. This
1982 bounds the region that needs to change. */
1983 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1984 {
1985 ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1986 olsf = old_face + (ols - old);
1987 nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1988 nlsf = new_face + (nls - new);
1989
1990 while ((ols > ofd) && (nls > nfd))
1991 {
1992 memset (&ps_old, 0, sizeof (mbstate_t));
1993 memset (&ps_new, 0, sizeof (mbstate_t));
1994
1995 if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0 ||
1996 *olsf != *nlsf)
1997 break;
1998
1999 if (*ols == ' ')
2000 wsatend = 0;
2001
2002 ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
2003 olsf = old_face + (ols - old);
2004 nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
2005 nlsf = new_face + (nls - new);
2006 }
2007 }
2008 else
2009 {
2010 #endif /* HANDLE_MULTIBYTE */
2011 ols = oe - 1; /* find last same */
2012 olsf = old_face + (ols - old);
2013 nls = ne - 1;
2014 nlsf = new_face + (nls - new);
2015 while ((ols > ofd) && (nls > nfd) && (*ols == *nls) && (*olsf == *nlsf))
2016 {
2017 if (*ols != ' ')
2018 wsatend = 0;
2019 ols--; olsf--;
2020 nls--; nlsf--;
2021 }
2022 #if defined (HANDLE_MULTIBYTE)
2023 }
2024 #endif
2025
2026 if (wsatend)
2027 {
2028 ols = oe;
2029 olsf = old_face + (ols - old);
2030 nls = ne;
2031 nlsf = new_face + (nls - new);
2032 }
2033 #if defined (HANDLE_MULTIBYTE)
2034 /* This may not work for stateful encoding, but who cares? To handle
2035 stateful encoding properly, we have to scan each string from the
2036 beginning and compare. */
2037 else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0 || *olsf != *nlsf)
2038 #else
2039 else if (*ols != *nls || *olsf != *nlsf)
2040 #endif
2041 {
2042 if (*ols) /* don't step past the NUL */
2043 {
2044 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2045 ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
2046 else
2047 ols++;
2048 }
2049 if (*nls)
2050 {
2051 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2052 nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
2053 else
2054 nls++;
2055 }
2056 olsf = old_face + (ols - old);
2057 nlsf = new_face + (nls - new);
2058 }
2059
2060 /* count of invisible characters in the current invisible line. */
2061 current_invis_chars = W_OFFSET (current_line, wrap_offset);
2062 if (_rl_last_v_pos != current_line)
2063 {
2064 _rl_move_vert (current_line);
2065 /* We have moved up to a new screen line. This line may or may not have
2066 invisible characters on it, but we do our best to recalculate
2067 visible_wrap_offset based on what we know. */
2068 if (current_line == 0)
2069 visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */
2070 #if 0 /* XXX - not yet */
2071 else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
2072 visible_wrap_offset = wrap_offset - prompt_invis_chars_first_line
2073 #endif
2074 if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
2075 _rl_last_c_pos += visible_wrap_offset;
2076 }
2077
2078 /* If this is the first line and there are invisible characters in the
2079 prompt string, and the prompt string has not changed, and the current
2080 cursor position is before the last invisible character in the prompt,
2081 and the index of the character to move to is past the end of the prompt
2082 string, then redraw the entire prompt string. We can only do this
2083 reliably if the terminal supports a `cr' capability.
2084
2085 This can also happen if the prompt string has changed, and the first
2086 difference in the line is in the middle of the prompt string, after a
2087 sequence of invisible characters (worst case) and before the end of
2088 the prompt. In this case, we have to redraw the entire prompt string
2089 so that the entire sequence of invisible characters is drawn. We need
2090 to handle the worst case, when the difference is after (or in the middle
2091 of) a sequence of invisible characters that changes the text color and
2092 before the sequence that restores the text color to normal. Then we have
2093 to make sure that the lines still differ -- if they don't, we can
2094 return immediately.
2095
2096 This is not an efficiency hack -- there is a problem with redrawing
2097 portions of the prompt string if they contain terminal escape
2098 sequences (like drawing the `unbold' sequence without a corresponding
2099 `bold') that manifests itself on certain terminals. */
2100
2101 lendiff = local_prompt_len;
2102 if (lendiff > nmax)
2103 lendiff = nmax;
2104 od = ofd - old; /* index of first difference in visible line */
2105 nd = nfd - new; /* nd, od are buffer indexes */
2106 if (current_line == 0 && !_rl_horizontal_scroll_mode &&
2107 _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
2108 (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
2109 ((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
2110 {
2111 _rl_cr ();
2112 if (modmark)
2113 _rl_output_some_chars ("*", 1);
2114 _rl_output_some_chars (local_prompt, lendiff);
2115 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2116 {
2117 /* If we just output the entire prompt string we can take advantage
2118 of knowing the number of physical characters in the prompt. If
2119 the prompt wraps lines (lendiff clamped at nmax), we can't. */
2120 if (lendiff == local_prompt_len)
2121 _rl_last_c_pos = prompt_physical_chars + modmark;
2122 else
2123 /* We take wrap_offset into account here so we can pass correct
2124 information to _rl_move_cursor_relative. */
2125 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
2126 cpos_adjusted = 1;
2127 }
2128 else
2129 _rl_last_c_pos = lendiff + modmark;
2130
2131 /* Now if we have printed the prompt string because the first difference
2132 was within the prompt, see if we need to recompute where the lines
2133 differ. Check whether where we are now is past the last place where
2134 the old and new lines are the same and short-circuit now if we are. */
2135 if ((od <= prompt_last_invisible || nd <= prompt_last_invisible) &&
2136 omax == nmax &&
2137 lendiff > (ols-old) && lendiff > (nls-new))
2138 return;
2139
2140 /* XXX - we need to fix up our calculations if we are now past the
2141 old ofd/nfd and the prompt length (or line length) has changed.
2142 We punt on the problem and do a dumb update. We'd like to be able
2143 to just output the prompt from the beginning of the line up to the
2144 first difference, but you don't know the number of invisible
2145 characters in that case.
2146 This needs a lot of work to be efficient, but it usually doesn't matter. */
2147 if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
2148 {
2149 nfd = new + lendiff; /* number of characters we output above */
2150 nfdf = new_face + lendiff;
2151 nd = lendiff;
2152
2153 /* Do a dumb update and return */
2154 dumb_update:
2155 temp = ne - nfd;
2156 if (temp > 0)
2157 {
2158 puts_face (nfd, nfdf, temp);
2159 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2160 {
2161 _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
2162 /* Need to adjust here based on wrap_offset. Guess that if
2163 this is the line containing the last line of the prompt
2164 we need to adjust by
2165 wrap_offset-prompt_invis_chars_first_line
2166 on the assumption that this is the number of invisible
2167 characters in the last line of the prompt. */
2168 if (wrap_offset > prompt_invis_chars_first_line &&
2169 current_line == prompt_last_screen_line &&
2170 prompt_physical_chars > _rl_screenwidth &&
2171 _rl_horizontal_scroll_mode == 0)
2172 ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
2173
2174 /* If we just output a new line including the prompt, and
2175 the prompt includes invisible characters, we need to
2176 account for them in the _rl_last_c_pos calculation, since
2177 _rl_col_width does not. This happens when other code does
2178 a goto dumb_update; */
2179 else if (current_line == 0 &&
2180 nfd == new &&
2181 prompt_invis_chars_first_line &&
2182 local_prompt_len <= temp &&
2183 wrap_offset >= prompt_invis_chars_first_line &&
2184 _rl_horizontal_scroll_mode == 0)
2185 ADJUST_CPOS (prompt_invis_chars_first_line);
2186 }
2187 else
2188 _rl_last_c_pos += temp;
2189 }
2190 /* This is a useful heuristic, but what we really want is to clear
2191 if the new number of visible screen characters is less than the
2192 old number of visible screen characters. If the prompt has changed,
2193 we don't really have enough information about the visible line to
2194 know for sure, so we use another heuristic calclulation below. */
2195 if (nmax < omax)
2196 goto clear_rest_of_line; /* XXX */
2197 else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
2198 goto clear_rest_of_line;
2199 else
2200 return;
2201 }
2202 }
2203
2204 o_cpos = _rl_last_c_pos;
2205
2206 /* When this function returns, _rl_last_c_pos is correct, and an absolute
2207 cursor position in multibyte mode, but a buffer index when not in a
2208 multibyte locale. */
2209 _rl_move_cursor_relative (od, old, old_face);
2210
2211 #if defined (HANDLE_MULTIBYTE)
2212 /* We need to indicate that the cursor position is correct in the presence of
2213 invisible characters in the prompt string. Let's see if setting this when
2214 we make sure we're at the end of the drawn prompt string works. */
2215 if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
2216 (_rl_last_c_pos > 0 || o_cpos > 0) &&
2217 _rl_last_c_pos == prompt_physical_chars)
2218 cpos_adjusted = 1;
2219 #endif
2220
2221 /* if (len (new) > len (old))
2222 lendiff == difference in buffer (bytes)
2223 col_lendiff == difference on screen (columns)
2224 When not using multibyte characters, these are equal */
2225 lendiff = (nls - nfd) - (ols - ofd);
2226 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2227 {
2228 int newchars, newwidth, newind;
2229 int oldchars, oldwidth, oldind;
2230
2231 newchars = nls - new;
2232 oldchars = ols - old;
2233
2234 /* If we can do it, try to adjust nls and ols so that nls-new will
2235 contain the entire new prompt string. That way we can use
2236 prompt_physical_chars and not have to recompute column widths.
2237 _rl_col_width adds wrap_offset and expects the caller to compensate,
2238 which we do below, so we do the same thing if we don't call
2239 _rl_col_width.
2240 We don't have to compare, since we know the characters are the same.
2241 The check of differing numbers of invisible chars may be extraneous.
2242 XXX - experimental */
2243 if (current_line == 0 && nfd == new && newchars > prompt_last_invisible &&
2244 newchars <= local_prompt_len &&
2245 local_prompt_len <= nmax &&
2246 current_invis_chars != visible_wrap_offset)
2247 {
2248 while (newchars < nmax && oldchars < omax && newchars < local_prompt_len)
2249 {
2250 #if defined (HANDLE_MULTIBYTE)
2251 newind = _rl_find_next_mbchar (new, newchars, 1, MB_FIND_NONZERO);
2252 oldind = _rl_find_next_mbchar (old, oldchars, 1, MB_FIND_NONZERO);
2253
2254 nls += newind - newchars;
2255 ols += oldind - oldchars;
2256
2257 newchars = newind;
2258 oldchars = oldind;
2259 #else
2260 nls++; ols++;
2261 newchars++; oldchars++;
2262 #endif
2263 }
2264 newwidth = (newchars == local_prompt_len) ? prompt_physical_chars + wrap_offset
2265 : _rl_col_width (new, 0, nls - new, 1);
2266 /* if we changed nls and ols, we need to recompute lendiff */
2267 lendiff = (nls - nfd) - (ols - ofd);
2268
2269 nlsf = new_face + (nls - new);
2270 olsf = old_face + (ols - old);
2271 }
2272 else
2273 newwidth = _rl_col_width (new, nfd - new, nls - new, 1);
2274
2275 oldwidth = _rl_col_width (old, ofd - old, ols - old, 1);
2276
2277 col_lendiff = newwidth - oldwidth;
2278 }
2279 else
2280 col_lendiff = lendiff;
2281
2282 /* col_lendiff uses _rl_col_width(), which doesn't know about whether or not
2283 the multibyte characters it counts are invisible, so unless we're printing
2284 the entire prompt string (in which case we can use prompt_physical_chars)
2285 the count is short by the number of bytes in the invisible multibyte
2286 characters - the number of multibyte characters.
2287
2288 We don't have a good way to solve this without moving to something like
2289 a bitmap that indicates which characters are visible and which are
2290 invisible. We fix it up (imperfectly) in the caller and by trying to use
2291 the entire prompt string wherever we can. */
2292
2293 /* If we are changing the number of invisible characters in a line, and
2294 the spot of first difference is before the end of the invisible chars,
2295 lendiff needs to be adjusted. */
2296 if (current_line == 0 && current_invis_chars != visible_wrap_offset)
2297 {
2298 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2299 {
2300 lendiff += visible_wrap_offset - current_invis_chars;
2301 col_lendiff += visible_wrap_offset - current_invis_chars;
2302 }
2303 else
2304 {
2305 lendiff += visible_wrap_offset - current_invis_chars;
2306 col_lendiff = lendiff;
2307 }
2308 }
2309
2310 /* We use temp as a count of the number of bytes from the first difference
2311 to the end of the new line. col_temp is the corresponding number of
2312 screen columns. A `dumb' update moves to the spot of first difference
2313 and writes TEMP bytes. */
2314 /* Insert (diff (len (old), len (new)) ch. */
2315 temp = ne - nfd;
2316 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2317 col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
2318 else
2319 col_temp = temp;
2320
2321 /* how many bytes from the new line buffer to write to the display */
2322 bytes_to_insert = nls - nfd;
2323
2324 /* col_lendiff > 0 if we are adding characters to the line */
2325 if (col_lendiff > 0) /* XXX - was lendiff */
2326 {
2327 /* Non-zero if we're increasing the number of lines. */
2328 int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
2329
2330 /* If col_lendiff is > 0, implying that the new string takes up more
2331 screen real estate than the old, but lendiff is < 0, meaning that it
2332 takes fewer bytes, we need to just output the characters starting
2333 from the first difference. These will overwrite what is on the
2334 display, so there's no reason to do a smart update. This can really
2335 only happen in a multibyte environment. */
2336 if (lendiff < 0)
2337 {
2338 puts_face (nfd, nfdf, temp);
2339 _rl_last_c_pos += col_temp;
2340 /* If nfd begins before any invisible characters in the prompt,
2341 adjust _rl_last_c_pos to account for wrap_offset and set
2342 cpos_adjusted to let the caller know. */
2343 if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2344 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2345 return;
2346 }
2347 /* Sometimes it is cheaper to print the characters rather than
2348 use the terminal's capabilities. If we're growing the number
2349 of lines, make sure we actually cause the new line to wrap
2350 around on auto-wrapping terminals. */
2351 else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
2352 {
2353 /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
2354 _rl_horizontal_scroll_mode == 1, inserting the characters with
2355 _rl_term_IC or _rl_term_ic will screw up the screen because of the
2356 invisible characters. We need to just draw them. */
2357 /* The same thing happens if we're trying to draw before the last
2358 invisible character in the prompt string or we're increasing the
2359 number of invisible characters in the line and we're not drawing
2360 the entire prompt string. */
2361 if (*ols && ((_rl_horizontal_scroll_mode &&
2362 _rl_last_c_pos == 0 &&
2363 lendiff > prompt_visible_length &&
2364 current_invis_chars > 0) == 0) &&
2365 (((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2366 current_line == 0 && wrap_offset &&
2367 ((nfd - new) <= prompt_last_invisible) &&
2368 (col_lendiff < prompt_visible_length)) == 0) &&
2369 (visible_wrap_offset >= current_invis_chars))
2370 {
2371 open_some_spaces (col_lendiff);
2372 puts_face (nfd, nfdf, bytes_to_insert);
2373 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2374 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2375 else
2376 _rl_last_c_pos += bytes_to_insert;
2377 }
2378 else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
2379 {
2380 /* At the end of a line the characters do not have to
2381 be "inserted". They can just be placed on the screen. */
2382 puts_face (nfd, nfdf, temp);
2383 _rl_last_c_pos += col_temp;
2384 return;
2385 }
2386 else /* just write from first difference to end of new line */
2387 {
2388 puts_face (nfd, nfdf, temp);
2389 _rl_last_c_pos += col_temp;
2390 /* If nfd begins before the last invisible character in the
2391 prompt, adjust _rl_last_c_pos to account for wrap_offset
2392 and set cpos_adjusted to let the caller know. */
2393 if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2394 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2395 return;
2396 }
2397
2398 if (bytes_to_insert > lendiff)
2399 {
2400 /* If nfd begins before the last invisible character in the
2401 prompt, adjust _rl_last_c_pos to account for wrap_offset
2402 and set cpos_adjusted to let the caller know. */
2403 if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2404 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2405 }
2406 }
2407 else
2408 {
2409 /* cannot insert chars, write to EOL */
2410 puts_face (nfd, nfdf, temp);
2411 _rl_last_c_pos += col_temp;
2412 /* If we're in a multibyte locale and were before the last invisible
2413 char in the current line (which implies we just output some invisible
2414 characters) we need to adjust _rl_last_c_pos, since it represents
2415 a physical character position. */
2416 /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a
2417 crude attempt to compute how far into the new line buffer we are.
2418 It doesn't work well in the face of multibyte characters and needs
2419 to be rethought. XXX */
2420 if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2421 current_line == prompt_last_screen_line && wrap_offset &&
2422 displaying_prompt_first_line &&
2423 wrap_offset != prompt_invis_chars_first_line &&
2424 ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
2425 ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
2426
2427 /* XXX - what happens if wrap_offset == prompt_invis_chars_first_line
2428 and we are drawing the first line (current_line == 0)? We should
2429 adjust by _rl_last_c_pos -= prompt_invis_chars_first_line */
2430 }
2431 }
2432 else /* Delete characters from line. */
2433 {
2434 /* If possible and inexpensive to use terminal deletion, then do so. */
2435 if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
2436 {
2437 /* If all we're doing is erasing the invisible characters in the
2438 prompt string, don't bother. It screws up the assumptions
2439 about what's on the screen. */
2440 if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
2441 displaying_prompt_first_line &&
2442 -lendiff == visible_wrap_offset)
2443 col_lendiff = 0;
2444
2445 /* If we have moved lmargin and we're shrinking the line, we've
2446 already moved the cursor to the first character of the new line,
2447 so deleting -col_lendiff characters will mess up the cursor
2448 position calculation */
2449 if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
2450 col_lendiff && _rl_last_c_pos < -col_lendiff)
2451 col_lendiff = 0;
2452
2453 if (col_lendiff)
2454 delete_chars (-col_lendiff); /* delete (diff) characters */
2455
2456 /* Copy (new) chars to screen from first diff to last match,
2457 overwriting what is there. */
2458 if (bytes_to_insert > 0)
2459 {
2460 /* If nfd begins at the prompt, or before the invisible
2461 characters in the prompt, we need to adjust _rl_last_c_pos
2462 in a multibyte locale to account for the wrap offset and
2463 set cpos_adjusted accordingly. */
2464 puts_face (nfd, nfdf, bytes_to_insert);
2465 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2466 {
2467 /* This still doesn't take into account whether or not the
2468 characters that this counts are invisible. */
2469 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2470 if (current_line == 0 && wrap_offset &&
2471 displaying_prompt_first_line &&
2472 prompt_invis_chars_first_line &&
2473 _rl_last_c_pos >= prompt_invis_chars_first_line &&
2474 ((nfd - new) <= prompt_last_invisible))
2475 ADJUST_CPOS (prompt_invis_chars_first_line);
2476
2477 #if 1
2478 #ifdef HANDLE_MULTIBYTE
2479 /* If we write a non-space into the last screen column,
2480 remove the note that we added a space to compensate for
2481 a multibyte double-width character that didn't fit, since
2482 it's only valid for what was previously there. */
2483 /* XXX - watch this */
2484 if (_rl_last_c_pos == _rl_screenwidth &&
2485 line_state_invisible->wrapped_line[current_line+1] &&
2486 nfd[bytes_to_insert-1] != ' ')
2487 line_state_invisible->wrapped_line[current_line+1] = 0;
2488 #endif
2489 #endif
2490 }
2491 else
2492 _rl_last_c_pos += bytes_to_insert;
2493
2494 /* XXX - we only want to do this if we are at the end of the line
2495 so we move there with _rl_move_cursor_relative */
2496 if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
2497 {
2498 _rl_move_cursor_relative (ne-new, new, new_face);
2499 goto clear_rest_of_line;
2500 }
2501 }
2502 }
2503 /* Otherwise, print over the existing material. */
2504 else
2505 {
2506 if (temp > 0)
2507 {
2508 /* If nfd begins at the prompt, or before the invisible
2509 characters in the prompt, we need to adjust _rl_last_c_pos
2510 in a multibyte locale to account for the wrap offset and
2511 set cpos_adjusted accordingly. */
2512 puts_face (nfd, nfdf, temp);
2513 _rl_last_c_pos += col_temp; /* XXX */
2514 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2515 {
2516 if (current_line == 0 && wrap_offset &&
2517 displaying_prompt_first_line &&
2518 _rl_last_c_pos > wrap_offset &&
2519 ((nfd - new) <= prompt_last_invisible))
2520 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2521 }
2522 }
2523 clear_rest_of_line:
2524 lendiff = (oe - old) - (ne - new);
2525 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2526 col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
2527 else
2528 col_lendiff = lendiff;
2529
2530 /* If we've already printed over the entire width of the screen,
2531 including the old material, then col_lendiff doesn't matter and
2532 space_to_eol will insert too many spaces. XXX - maybe we should
2533 adjust col_lendiff based on the difference between _rl_last_c_pos
2534 and _rl_screenwidth */
2535 if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
2536 {
2537 if (_rl_term_autowrap && current_line < inv_botlin)
2538 space_to_eol (col_lendiff);
2539 else
2540 _rl_clear_to_eol (col_lendiff);
2541 }
2542 }
2543 }
2544 }
2545
2546 /* Tell the update routines that we have moved onto a new (empty) line. */
2547 int
rl_on_new_line(void)2548 rl_on_new_line (void)
2549 {
2550 if (visible_line)
2551 visible_line[0] = '\0';
2552
2553 _rl_last_c_pos = _rl_last_v_pos = 0;
2554 _rl_vis_botlin = last_lmargin = 0;
2555 if (vis_lbreaks)
2556 vis_lbreaks[0] = vis_lbreaks[1] = 0;
2557 visible_wrap_offset = 0;
2558 return 0;
2559 }
2560
2561 /* Clear all screen lines occupied by the current readline line buffer
2562 (visible line) */
2563 int
rl_clear_visible_line(void)2564 rl_clear_visible_line (void)
2565 {
2566 int curr_line;
2567
2568 /* Make sure we move to column 0 so we clear the entire line */
2569 _rl_cr ();
2570 _rl_last_c_pos = 0;
2571
2572 /* Move to the last screen line of the current visible line */
2573 _rl_move_vert (_rl_vis_botlin);
2574
2575 /* And erase screen lines going up to line 0 (first visible line) */
2576 for (curr_line = _rl_last_v_pos; curr_line >= 0; curr_line--)
2577 {
2578 _rl_move_vert (curr_line);
2579 _rl_clear_to_eol (0);
2580 }
2581
2582 return 0;
2583 }
2584
2585 /* Tell the update routines that we have moved onto a new line with the
2586 prompt already displayed. Code originally from the version of readline
2587 distributed with CLISP. rl_expand_prompt must have already been called
2588 (explicitly or implicitly). This still doesn't work exactly right; it
2589 should use expand_prompt() */
2590 int
rl_on_new_line_with_prompt(void)2591 rl_on_new_line_with_prompt (void)
2592 {
2593 int prompt_size, i, l, real_screenwidth, newlines;
2594 char *prompt_last_line, *lprompt;
2595
2596 /* Initialize visible_line and invisible_line to ensure that they can hold
2597 the already-displayed prompt. */
2598 prompt_size = strlen (rl_prompt) + 1;
2599 init_line_structures (prompt_size);
2600
2601 /* Make sure the line structures hold the already-displayed prompt for
2602 redisplay. */
2603 lprompt = local_prompt ? local_prompt : rl_prompt;
2604 strcpy (visible_line, lprompt);
2605 strcpy (invisible_line, lprompt);
2606
2607 /* If the prompt contains newlines, take the last tail. */
2608 prompt_last_line = strrchr (rl_prompt, '\n');
2609 if (!prompt_last_line)
2610 prompt_last_line = rl_prompt;
2611
2612 l = strlen (prompt_last_line);
2613 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2614 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */
2615 else
2616 _rl_last_c_pos = l;
2617
2618 /* Dissect prompt_last_line into screen lines. Note that here we have
2619 to use the real screenwidth. Readline's notion of screenwidth might be
2620 one less, see terminal.c. */
2621 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
2622 _rl_last_v_pos = l / real_screenwidth;
2623 /* If the prompt length is a multiple of real_screenwidth, we don't know
2624 whether the cursor is at the end of the last line, or already at the
2625 beginning of the next line. Output a newline just to be safe. */
2626 if (l > 0 && (l % real_screenwidth) == 0)
2627 _rl_output_some_chars ("\n", 1);
2628 last_lmargin = 0;
2629
2630 newlines = 0; i = 0;
2631 while (i <= l)
2632 {
2633 _rl_vis_botlin = newlines;
2634 vis_lbreaks[newlines++] = i;
2635 i += real_screenwidth;
2636 }
2637 vis_lbreaks[newlines] = l;
2638 visible_wrap_offset = 0;
2639
2640 rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
2641
2642 return 0;
2643 }
2644
2645 /* Actually update the display, period. */
2646 int
rl_forced_update_display(void)2647 rl_forced_update_display (void)
2648 {
2649 register char *temp;
2650
2651 if (visible_line)
2652 {
2653 temp = visible_line;
2654 while (*temp)
2655 *temp++ = '\0';
2656 }
2657 rl_on_new_line ();
2658 forced_display++;
2659 (*rl_redisplay_function) ();
2660 return 0;
2661 }
2662
2663 /* Redraw only the last line of a multi-line prompt. */
2664 void
rl_redraw_prompt_last_line(void)2665 rl_redraw_prompt_last_line (void)
2666 {
2667 char *t;
2668
2669 t = strrchr (rl_display_prompt, '\n');
2670 if (t)
2671 redraw_prompt (++t);
2672 else
2673 rl_forced_update_display ();
2674 }
2675
2676 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
2677 (Well, when we don't have multibyte characters, _rl_last_c_pos is a
2678 buffer index.)
2679 DATA is the contents of the screen line of interest; i.e., where
2680 the movement is being done.
2681 DATA is always the visible line or the invisible line */
2682 static void
_rl_move_cursor_relative(int new,const char * data,const char * dataf)2683 _rl_move_cursor_relative (int new, const char *data, const char *dataf)
2684 {
2685 register int i;
2686 int woff; /* number of invisible chars on current line */
2687 int cpos, dpos; /* current and desired cursor positions */
2688 int adjust;
2689 int in_invisline;
2690 int mb_cur_max = MB_CUR_MAX;
2691
2692 woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
2693 cpos = _rl_last_c_pos;
2694
2695 if (cpos == 0 && cpos == new)
2696 return;
2697
2698 #if defined (HANDLE_MULTIBYTE)
2699 /* If we have multibyte characters, NEW is indexed by the buffer point in
2700 a multibyte string, but _rl_last_c_pos is the display position. In
2701 this case, NEW's display position is not obvious and must be
2702 calculated. We need to account for invisible characters in this line,
2703 as long as we are past them and they are counted by _rl_col_width. */
2704 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2705 {
2706 adjust = 1;
2707 /* Try to short-circuit common cases and eliminate a bunch of multibyte
2708 character function calls. */
2709 /* 1. prompt string */
2710 if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2711 {
2712 dpos = prompt_physical_chars;
2713 cpos_adjusted = 1;
2714 adjust = 0;
2715 }
2716 /* 2. prompt_string + line contents */
2717 else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2718 {
2719 dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2720 cpos_adjusted = 1;
2721 adjust = 0;
2722 }
2723 else
2724 dpos = _rl_col_width (data, 0, new, 1);
2725
2726 if (displaying_prompt_first_line == 0)
2727 adjust = 0;
2728
2729 /* yet another special case: printing the last line of a prompt with
2730 multibyte characters and invisible characters whose printable length
2731 exceeds the screen width with the last invisible character
2732 (prompt_last_invisible) in the last line. IN_INVISLINE is the
2733 offset of DATA in invisible_line */
2734 in_invisline = 0;
2735 if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
2736 in_invisline = data - invisible_line;
2737
2738 /* Use NEW when comparing against the last invisible character in the
2739 prompt string, since they're both buffer indices and DPOS is a
2740 desired display position. */
2741 /* NEW is relative to the current displayed line, while
2742 PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line.
2743 Need a way to reconcile these two variables by turning NEW into a
2744 buffer position relative to the start of the line */
2745 if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */
2746 (new+in_invisline > prompt_last_invisible) || /* invisible line */
2747 (prompt_physical_chars >= _rl_screenwidth && /* visible line */
2748 _rl_last_v_pos == prompt_last_screen_line &&
2749 wrap_offset >= woff && dpos >= woff &&
2750 new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset))))
2751 /* XXX last comparison might need to be >= */
2752 {
2753 dpos -= woff;
2754 /* Since this will be assigned to _rl_last_c_pos at the end (more
2755 precisely, _rl_last_c_pos == dpos when this function returns),
2756 let the caller know. */
2757 cpos_adjusted = 1;
2758 }
2759 }
2760 else
2761 #endif
2762 dpos = new;
2763
2764 /* If we don't have to do anything, then return. */
2765 if (cpos == dpos)
2766 return;
2767
2768 /* It may be faster to output a CR, and then move forwards instead
2769 of moving backwards. */
2770 /* i == current physical cursor position. */
2771 #if defined (HANDLE_MULTIBYTE)
2772 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2773 i = _rl_last_c_pos;
2774 else
2775 #endif
2776 i = _rl_last_c_pos - woff;
2777 if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
2778 (_rl_term_autowrap && i == _rl_screenwidth))
2779 {
2780 _rl_cr ();
2781 cpos = _rl_last_c_pos = 0;
2782 }
2783
2784 if (cpos < dpos)
2785 {
2786 /* Move the cursor forward. We do it by printing the command
2787 to move the cursor forward if there is one, else print that
2788 portion of the output buffer again. Which is cheaper? */
2789
2790 /* The above comment is left here for posterity. It is faster
2791 to print one character (non-control) than to print a control
2792 sequence telling the terminal to move forward one character.
2793 That kind of control is for people who don't know what the
2794 data is underneath the cursor. */
2795
2796 /* However, we need a handle on where the current display position is
2797 in the buffer for the immediately preceding comment to be true.
2798 In multibyte locales, we don't currently have that info available.
2799 Without it, we don't know where the data we have to display begins
2800 in the buffer and we have to go back to the beginning of the screen
2801 line. In this case, we can use the terminal sequence to move forward
2802 if it's available. */
2803 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2804 {
2805 if (_rl_term_forward_char)
2806 {
2807 for (i = cpos; i < dpos; i++)
2808 tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2809 }
2810 else
2811 {
2812 _rl_cr ();
2813 puts_face (data, dataf, new);
2814 }
2815 }
2816 else
2817 puts_face (data + cpos, dataf + cpos, new - cpos);
2818 }
2819
2820 #if defined (HANDLE_MULTIBYTE)
2821 /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2822 The byte length of the string is probably bigger than the column width
2823 of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2824 display point is less than _rl_last_c_pos. */
2825 #endif
2826 else if (cpos > dpos)
2827 _rl_backspace (cpos - dpos);
2828
2829 _rl_last_c_pos = dpos;
2830 }
2831
2832 /* PWP: move the cursor up or down. */
2833 void
_rl_move_vert(int to)2834 _rl_move_vert (int to)
2835 {
2836 register int delta, i;
2837
2838 if (_rl_last_v_pos == to || to > _rl_screenheight)
2839 return;
2840
2841 if ((delta = to - _rl_last_v_pos) > 0)
2842 {
2843 for (i = 0; i < delta; i++)
2844 putc ('\n', rl_outstream);
2845 _rl_cr ();
2846 _rl_last_c_pos = 0;
2847 }
2848 else
2849 { /* delta < 0 */
2850 #ifdef __DJGPP__
2851 int row, col;
2852
2853 fflush (rl_outstream);
2854 ScreenGetCursor (&row, &col);
2855 ScreenSetCursor (row + delta, col);
2856 i = -delta;
2857 #else
2858 if (_rl_term_up && *_rl_term_up)
2859 for (i = 0; i < -delta; i++)
2860 tputs (_rl_term_up, 1, _rl_output_character_function);
2861 #endif /* !__DJGPP__ */
2862 }
2863
2864 _rl_last_v_pos = to; /* Now TO is here */
2865 }
2866
2867 /* Physically print C on rl_outstream. This is for functions which know
2868 how to optimize the display. Return the number of characters output. */
2869 int
rl_show_char(int c)2870 rl_show_char (int c)
2871 {
2872 int n = 1;
2873 if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2874 {
2875 fprintf (rl_outstream, "M-");
2876 n += 2;
2877 c = UNMETA (c);
2878 }
2879
2880 #if defined (DISPLAY_TABS)
2881 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
2882 #else
2883 if (CTRL_CHAR (c) || c == RUBOUT)
2884 #endif /* !DISPLAY_TABS */
2885 {
2886 fprintf (rl_outstream, "C-");
2887 n += 2;
2888 c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
2889 }
2890
2891 putc (c, rl_outstream);
2892 fflush (rl_outstream);
2893 return n;
2894 }
2895
2896 int
rl_character_len(int c,int pos)2897 rl_character_len (int c, int pos)
2898 {
2899 unsigned char uc;
2900
2901 uc = (unsigned char)c;
2902
2903 if (META_CHAR (uc))
2904 return ((_rl_output_meta_chars == 0) ? 4 : 1);
2905
2906 if (uc == '\t')
2907 {
2908 #if defined (DISPLAY_TABS)
2909 return (((pos | 7) + 1) - pos);
2910 #else
2911 return (2);
2912 #endif /* !DISPLAY_TABS */
2913 }
2914
2915 if (CTRL_CHAR (c) || c == RUBOUT)
2916 return (2);
2917
2918 return ((ISPRINT (uc)) ? 1 : 2);
2919 }
2920 /* How to print things in the "echo-area". The prompt is treated as a
2921 mini-modeline. */
2922 static int msg_saved_prompt = 0;
2923
2924 #if defined (USE_VARARGS)
2925 int
2926 #if defined (PREFER_STDARG)
rl_message(const char * format,...)2927 rl_message (const char *format, ...)
2928 #else
2929 rl_message (va_alist)
2930 va_dcl
2931 #endif
2932 {
2933 va_list args;
2934 #if defined (PREFER_VARARGS)
2935 char *format;
2936 #endif
2937 #if defined (HAVE_VSNPRINTF)
2938 int bneed;
2939 #endif
2940
2941 #if defined (PREFER_STDARG)
2942 va_start (args, format);
2943 #else
2944 va_start (args);
2945 format = va_arg (args, char *);
2946 #endif
2947
2948 if (msg_buf == 0)
2949 msg_buf = xmalloc (msg_bufsiz = 128);
2950
2951 #if defined (HAVE_VSNPRINTF)
2952 bneed = vsnprintf (msg_buf, msg_bufsiz, format, args);
2953 if (bneed >= msg_bufsiz - 1)
2954 {
2955 msg_bufsiz = bneed + 1;
2956 msg_buf = xrealloc (msg_buf, msg_bufsiz);
2957 va_end (args);
2958
2959 #if defined (PREFER_STDARG)
2960 va_start (args, format);
2961 #else
2962 va_start (args);
2963 format = va_arg (args, char *);
2964 #endif
2965 vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2966 }
2967 #else
2968 vsprintf (msg_buf, format, args);
2969 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2970 #endif
2971 va_end (args);
2972
2973 if (saved_local_prompt == 0)
2974 {
2975 rl_save_prompt ();
2976 msg_saved_prompt = 1;
2977 }
2978 else if (local_prompt != saved_local_prompt)
2979 {
2980 FREE (local_prompt);
2981 FREE (local_prompt_prefix);
2982 local_prompt = (char *)NULL;
2983 }
2984 rl_display_prompt = msg_buf;
2985 local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
2986 &prompt_last_invisible,
2987 &prompt_invis_chars_first_line,
2988 &prompt_physical_chars);
2989 local_prompt_prefix = (char *)NULL;
2990 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2991 (*rl_redisplay_function) ();
2992
2993 return 0;
2994 }
2995 #else /* !USE_VARARGS */
2996 int
rl_message(format,arg1,arg2)2997 rl_message (format, arg1, arg2)
2998 char *format;
2999 {
3000 if (msg_buf == 0)
3001 msg_buf = xmalloc (msg_bufsiz = 128);
3002
3003 sprintf (msg_buf, format, arg1, arg2);
3004 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
3005
3006 rl_display_prompt = msg_buf;
3007 if (saved_local_prompt == 0)
3008 {
3009 rl_save_prompt ();
3010 msg_saved_prompt = 1;
3011 }
3012 else if (local_prompt != saved_local_prompt)
3013 {
3014 FREE (local_prompt);
3015 FREE (local_prompt_prefix);
3016 local_prompt = (char *)NULL;
3017 }
3018 local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
3019 &prompt_last_invisible,
3020 &prompt_invis_chars_first_line,
3021 &prompt_physical_chars);
3022 local_prompt_prefix = (char *)NULL;
3023 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
3024 (*rl_redisplay_function) ();
3025
3026 return 0;
3027 }
3028 #endif /* !USE_VARARGS */
3029
3030 /* How to clear things from the "echo-area". */
3031 int
rl_clear_message(void)3032 rl_clear_message (void)
3033 {
3034 rl_display_prompt = rl_prompt;
3035 if (msg_saved_prompt)
3036 {
3037 rl_restore_prompt ();
3038 msg_saved_prompt = 0;
3039 }
3040 (*rl_redisplay_function) ();
3041 return 0;
3042 }
3043
3044 int
rl_reset_line_state(void)3045 rl_reset_line_state (void)
3046 {
3047 rl_on_new_line ();
3048
3049 rl_display_prompt = rl_prompt ? rl_prompt : "";
3050 forced_display = 1;
3051 return 0;
3052 }
3053
3054 /* Save all of the variables associated with the prompt and its display. Most
3055 of the complexity is dealing with the invisible characters in the prompt
3056 string and where they are. There are enough of these that I should consider
3057 a struct. */
3058 void
rl_save_prompt(void)3059 rl_save_prompt (void)
3060 {
3061 saved_local_prompt = local_prompt;
3062 saved_local_prefix = local_prompt_prefix;
3063 saved_prefix_length = prompt_prefix_length;
3064 saved_local_length = local_prompt_len;
3065 saved_last_invisible = prompt_last_invisible;
3066 saved_visible_length = prompt_visible_length;
3067 saved_invis_chars_first_line = prompt_invis_chars_first_line;
3068 saved_physical_chars = prompt_physical_chars;
3069 saved_local_prompt_newlines = local_prompt_newlines;
3070
3071 local_prompt = local_prompt_prefix = (char *)0;
3072 local_prompt_len = 0;
3073 local_prompt_newlines = (int *)0;
3074
3075 prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
3076 prompt_invis_chars_first_line = prompt_physical_chars = 0;
3077 }
3078
3079 void
rl_restore_prompt(void)3080 rl_restore_prompt (void)
3081 {
3082 FREE (local_prompt);
3083 FREE (local_prompt_prefix);
3084 FREE (local_prompt_newlines);
3085
3086 local_prompt = saved_local_prompt;
3087 local_prompt_prefix = saved_local_prefix;
3088 local_prompt_len = saved_local_length;
3089 local_prompt_newlines = saved_local_prompt_newlines;
3090
3091 prompt_prefix_length = saved_prefix_length;
3092 prompt_last_invisible = saved_last_invisible;
3093 prompt_visible_length = saved_visible_length;
3094 prompt_invis_chars_first_line = saved_invis_chars_first_line;
3095 prompt_physical_chars = saved_physical_chars;
3096
3097 /* can test saved_local_prompt to see if prompt info has been saved. */
3098 saved_local_prompt = saved_local_prefix = (char *)0;
3099 saved_local_length = 0;
3100 saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
3101 saved_invis_chars_first_line = saved_physical_chars = 0;
3102 saved_local_prompt_newlines = 0;
3103 }
3104
3105 char *
_rl_make_prompt_for_search(int pchar)3106 _rl_make_prompt_for_search (int pchar)
3107 {
3108 int len;
3109 char *pmt, *p;
3110
3111 rl_save_prompt ();
3112
3113 /* We've saved the prompt, and can do anything with the various prompt
3114 strings we need before they're restored. We want the unexpanded
3115 portion of the prompt string after any final newline. */
3116 p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
3117 if (p == 0)
3118 {
3119 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
3120 pmt = (char *)xmalloc (len + 2);
3121 if (len)
3122 strcpy (pmt, rl_prompt);
3123 pmt[len] = pchar;
3124 pmt[len+1] = '\0';
3125 }
3126 else
3127 {
3128 p++;
3129 len = strlen (p);
3130 pmt = (char *)xmalloc (len + 2);
3131 if (len)
3132 strcpy (pmt, p);
3133 pmt[len] = pchar;
3134 pmt[len+1] = '\0';
3135 }
3136
3137 /* will be overwritten by expand_prompt, called from rl_message */
3138 prompt_physical_chars = saved_physical_chars + 1;
3139 return pmt;
3140 }
3141
3142 /* Quick redisplay hack when erasing characters at the end of the line. */
3143 void
_rl_erase_at_end_of_line(int l)3144 _rl_erase_at_end_of_line (int l)
3145 {
3146 register int i;
3147
3148 _rl_backspace (l);
3149 for (i = 0; i < l; i++)
3150 putc (' ', rl_outstream);
3151 _rl_backspace (l);
3152 for (i = 0; i < l; i++)
3153 visible_line[--_rl_last_c_pos] = '\0';
3154 rl_display_fixed++;
3155 }
3156
3157 /* Clear to the end of the line. COUNT is the minimum
3158 number of character spaces to clear, but we use a terminal escape
3159 sequence if available. */
3160 void
_rl_clear_to_eol(int count)3161 _rl_clear_to_eol (int count)
3162 {
3163 #ifndef __MSDOS__
3164 if (_rl_term_clreol)
3165 tputs (_rl_term_clreol, 1, _rl_output_character_function);
3166 else
3167 #endif
3168 if (count)
3169 space_to_eol (count);
3170 }
3171
3172 /* Clear to the end of the line using spaces. COUNT is the minimum
3173 number of character spaces to clear, */
3174 static void
space_to_eol(int count)3175 space_to_eol (int count)
3176 {
3177 register int i;
3178
3179 for (i = 0; i < count; i++)
3180 putc (' ', rl_outstream);
3181
3182 _rl_last_c_pos += count;
3183 }
3184
3185 void
_rl_clear_screen(int clrscr)3186 _rl_clear_screen (int clrscr)
3187 {
3188 #if defined (__DJGPP__)
3189 ScreenClear ();
3190 ScreenSetCursor (0, 0);
3191 #else
3192 if (_rl_term_clrpag)
3193 {
3194 tputs (_rl_term_clrpag, 1, _rl_output_character_function);
3195 if (clrscr && _rl_term_clrscroll)
3196 tputs (_rl_term_clrscroll, 1, _rl_output_character_function);
3197 }
3198 else
3199 rl_crlf ();
3200 #endif /* __DJGPP__ */
3201 }
3202
3203 /* Insert COUNT characters from STRING to the output stream at column COL. */
3204 static void
insert_some_chars(char * string,int count,int col)3205 insert_some_chars (char *string, int count, int col)
3206 {
3207 open_some_spaces (col);
3208 _rl_output_some_chars (string, count);
3209 }
3210
3211 /* Insert COL spaces, keeping the cursor at the same position. We follow the
3212 ncurses documentation and use either im/ei with explicit spaces, or IC/ic
3213 by itself. We assume there will either be ei or we don't need to use it. */
3214 static void
open_some_spaces(int col)3215 open_some_spaces (int col)
3216 {
3217 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
3218 char *buffer;
3219 register int i;
3220
3221 /* If IC is defined, then we do not have to "enter" insert mode. */
3222 if (_rl_term_IC)
3223 {
3224 buffer = tgoto (_rl_term_IC, 0, col);
3225 tputs (buffer, 1, _rl_output_character_function);
3226 }
3227 else if (_rl_term_im && *_rl_term_im)
3228 {
3229 tputs (_rl_term_im, 1, _rl_output_character_function);
3230 /* just output the desired number of spaces */
3231 for (i = col; i--; )
3232 _rl_output_character_function (' ');
3233 /* If there is a string to turn off insert mode, use it now. */
3234 if (_rl_term_ei && *_rl_term_ei)
3235 tputs (_rl_term_ei, 1, _rl_output_character_function);
3236 /* and move back the right number of spaces */
3237 _rl_backspace (col);
3238 }
3239 else if (_rl_term_ic && *_rl_term_ic)
3240 {
3241 /* If there is a special command for inserting characters, then
3242 use that first to open up the space. */
3243 for (i = col; i--; )
3244 tputs (_rl_term_ic, 1, _rl_output_character_function);
3245 }
3246 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
3247 }
3248
3249 /* Delete COUNT characters from the display line. */
3250 static void
delete_chars(int count)3251 delete_chars (int count)
3252 {
3253 if (count > _rl_screenwidth) /* XXX */
3254 return;
3255
3256 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
3257 if (_rl_term_DC && *_rl_term_DC)
3258 {
3259 char *buffer;
3260 buffer = tgoto (_rl_term_DC, count, count);
3261 tputs (buffer, count, _rl_output_character_function);
3262 }
3263 else
3264 {
3265 if (_rl_term_dc && *_rl_term_dc)
3266 while (count--)
3267 tputs (_rl_term_dc, 1, _rl_output_character_function);
3268 }
3269 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
3270 }
3271
3272 void
_rl_update_final(void)3273 _rl_update_final (void)
3274 {
3275 int full_lines, woff, botline_length;
3276
3277 if (line_structures_initialized == 0)
3278 return;
3279
3280 full_lines = 0;
3281 /* If the cursor is the only thing on an otherwise-blank last line,
3282 compensate so we don't print an extra CRLF. */
3283 if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
3284 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
3285 {
3286 _rl_vis_botlin--;
3287 full_lines = 1;
3288 }
3289 _rl_move_vert (_rl_vis_botlin);
3290 woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
3291 botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
3292 /* If we've wrapped lines, remove the final xterm line-wrap flag. */
3293 if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
3294 {
3295 char *last_line, *last_face;
3296
3297 /* LAST_LINE includes invisible characters, so if you want to get the
3298 last character of the first line, you have to take WOFF into account.
3299 This needs to be done for both calls to _rl_move_cursor_relative,
3300 which takes a buffer position as the first argument, and any direct
3301 subscripts of LAST_LINE. */
3302 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
3303 last_face = &vis_face[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
3304 cpos_buffer_position = -1; /* don't know where we are in buffer */
3305 _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line, last_face); /* XXX */
3306 _rl_clear_to_eol (0);
3307 puts_face (&last_line[_rl_screenwidth - 1 + woff],
3308 &last_face[_rl_screenwidth - 1 + woff], 1);
3309 }
3310 _rl_vis_botlin = 0;
3311 if (botline_length > 0 || _rl_last_c_pos > 0)
3312 rl_crlf ();
3313 fflush (rl_outstream);
3314 rl_display_fixed++;
3315 }
3316
3317 /* Move to the start of the current line. */
3318 static void
cr(void)3319 cr (void)
3320 {
3321 _rl_cr ();
3322 _rl_last_c_pos = 0;
3323 }
3324
3325 /* Redraw the last line of a multi-line prompt that may possibly contain
3326 terminal escape sequences. Called with the cursor at column 0 of the
3327 line to draw the prompt on. */
3328 static void
redraw_prompt(char * t)3329 redraw_prompt (char *t)
3330 {
3331 char *oldp;
3332
3333 oldp = rl_display_prompt;
3334 rl_save_prompt ();
3335
3336 rl_display_prompt = t;
3337 local_prompt = expand_prompt (t, PMT_MULTILINE,
3338 &prompt_visible_length,
3339 &prompt_last_invisible,
3340 &prompt_invis_chars_first_line,
3341 &prompt_physical_chars);
3342 local_prompt_prefix = (char *)NULL;
3343 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
3344
3345 rl_forced_update_display ();
3346
3347 rl_display_prompt = oldp;
3348 rl_restore_prompt();
3349 }
3350
3351 /* Redisplay the current line after a SIGWINCH is received. */
3352 void
_rl_redisplay_after_sigwinch(void)3353 _rl_redisplay_after_sigwinch (void)
3354 {
3355 char *t;
3356
3357 /* Clear the last line (assuming that the screen size change will result in
3358 either more or fewer characters on that line only) and put the cursor at
3359 column 0. Make sure the right thing happens if we have wrapped to a new
3360 screen line. */
3361 if (_rl_term_cr)
3362 {
3363 _rl_move_vert (_rl_vis_botlin);
3364
3365 _rl_cr ();
3366 _rl_last_c_pos = 0;
3367
3368 #if !defined (__MSDOS__)
3369 if (_rl_term_clreol)
3370 tputs (_rl_term_clreol, 1, _rl_output_character_function);
3371 else
3372 #endif
3373 {
3374 space_to_eol (_rl_screenwidth);
3375 _rl_cr ();
3376 }
3377
3378 if (_rl_last_v_pos > 0)
3379 _rl_move_vert (0);
3380 }
3381 else
3382 rl_crlf ();
3383
3384 /* Redraw only the last line of a multi-line prompt. */
3385 t = strrchr (rl_display_prompt, '\n');
3386 if (t)
3387 redraw_prompt (++t);
3388 else
3389 rl_forced_update_display ();
3390 }
3391
3392 void
_rl_clean_up_for_exit(void)3393 _rl_clean_up_for_exit (void)
3394 {
3395 if (_rl_echoing_p)
3396 {
3397 if (_rl_vis_botlin > 0) /* minor optimization plus bug fix */
3398 _rl_move_vert (_rl_vis_botlin);
3399 _rl_vis_botlin = 0;
3400 fflush (rl_outstream);
3401 rl_restart_output (1, 0);
3402 }
3403 }
3404
3405 void
_rl_erase_entire_line(void)3406 _rl_erase_entire_line (void)
3407 {
3408 cr ();
3409 _rl_clear_to_eol (0);
3410 cr ();
3411 fflush (rl_outstream);
3412 }
3413
3414 void
_rl_ttyflush(void)3415 _rl_ttyflush (void)
3416 {
3417 fflush (rl_outstream);
3418 }
3419
3420 /* return the `current display line' of the cursor -- the number of lines to
3421 move up to get to the first screen line of the current readline line. */
3422 int
_rl_current_display_line(void)3423 _rl_current_display_line (void)
3424 {
3425 int ret, nleft;
3426
3427 /* Find out whether or not there might be invisible characters in the
3428 editing buffer. */
3429 if (rl_display_prompt == rl_prompt)
3430 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
3431 else
3432 nleft = _rl_last_c_pos - _rl_screenwidth;
3433
3434 if (nleft > 0)
3435 ret = 1 + nleft / _rl_screenwidth;
3436 else
3437 ret = 0;
3438
3439 return ret;
3440 }
3441
3442 void
_rl_refresh_line(void)3443 _rl_refresh_line (void)
3444 {
3445 rl_clear_visible_line ();
3446 rl_redraw_prompt_last_line ();
3447 rl_keep_mark_active ();
3448 }
3449
3450 #if defined (HANDLE_MULTIBYTE)
3451 /* Calculate the number of screen columns occupied by STR from START to END.
3452 In the case of multibyte characters with stateful encoding, we have to
3453 scan from the beginning of the string to take the state into account. */
3454 static int
_rl_col_width(const char * str,int start,int end,int flags)3455 _rl_col_width (const char *str, int start, int end, int flags)
3456 {
3457 wchar_t wc;
3458 mbstate_t ps;
3459 int tmp, point, width, max;
3460
3461 if (end <= start)
3462 return 0;
3463 if (MB_CUR_MAX == 1 || rl_byte_oriented)
3464 /* this can happen in some cases where it's inconvenient to check */
3465 return (end - start);
3466
3467 memset (&ps, 0, sizeof (mbstate_t));
3468
3469 point = 0;
3470 max = end;
3471
3472 /* Try to short-circuit common cases. The adjustment to remove wrap_offset
3473 is done by the caller. */
3474 /* 1. prompt string */
3475 if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
3476 return (prompt_physical_chars + wrap_offset);
3477 /* 2. prompt string + line contents */
3478 else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
3479 {
3480 tmp = prompt_physical_chars + wrap_offset;
3481 /* XXX - try to call ourselves recursively with non-prompt portion */
3482 tmp += _rl_col_width (str, local_prompt_len, end, flags);
3483 return (tmp);
3484 }
3485
3486 while (point < start)
3487 {
3488 if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3489 {
3490 memset (&ps, 0, sizeof (mbstate_t));
3491 tmp = 1;
3492 }
3493 else
3494 tmp = mbrlen (str + point, max, &ps);
3495 if (MB_INVALIDCH ((size_t)tmp))
3496 {
3497 /* In this case, the bytes are invalid or too short to compose a
3498 multibyte character, so we assume that the first byte represents
3499 a single character. */
3500 point++;
3501 max--;
3502
3503 /* Clear the state of the byte sequence, because in this case the
3504 effect of mbstate is undefined. */
3505 memset (&ps, 0, sizeof (mbstate_t));
3506 }
3507 else if (MB_NULLWCH (tmp))
3508 break; /* Found '\0' */
3509 else
3510 {
3511 point += tmp;
3512 max -= tmp;
3513 }
3514 }
3515
3516 /* If START is not a byte that starts a character, then POINT will be
3517 greater than START. In this case, assume that (POINT - START) gives
3518 a byte count that is the number of columns of difference. */
3519 width = point - start;
3520
3521 while (point < end)
3522 {
3523 if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3524 {
3525 tmp = 1;
3526 wc = (wchar_t) str[point];
3527 }
3528 else
3529 tmp = mbrtowc (&wc, str + point, max, &ps);
3530 if (MB_INVALIDCH ((size_t)tmp))
3531 {
3532 /* In this case, the bytes are invalid or too short to compose a
3533 multibyte character, so we assume that the first byte represents
3534 a single character. */
3535 point++;
3536 max--;
3537
3538 /* and assume that the byte occupies a single column. */
3539 width++;
3540
3541 /* Clear the state of the byte sequence, because in this case the
3542 effect of mbstate is undefined. */
3543 memset (&ps, 0, sizeof (mbstate_t));
3544 }
3545 else if (MB_NULLWCH (tmp))
3546 break; /* Found '\0' */
3547 else
3548 {
3549 point += tmp;
3550 max -= tmp;
3551 tmp = WCWIDTH(wc);
3552 width += (tmp >= 0) ? tmp : 1;
3553 }
3554 }
3555
3556 width += point - end;
3557
3558 return width;
3559 }
3560 #endif /* HANDLE_MULTIBYTE */
3561