Import GNU Readline 8.1
[deliverable/binutils-gdb.git] / readline / readline / display.c
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 *
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 *
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 *
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
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
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
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
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 */
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
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
710 invis_nul (int *outp)
711 {
712 invis_addc (outp, '\0', 0);
713 *outp -= 1;
714 }
715
716 static void
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
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
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 lpos = prompt_physical_chars + modmark;
936
937 #if defined (HANDLE_MULTIBYTE)
938 memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
939 num = 0;
940 #endif
941
942 /* prompt_invis_chars_first_line is the number of invisible characters (bytes)
943 in the first physical line of the prompt.
944 wrap_offset - prompt_invis_chars_first_line is usually the number of
945 invis chars on the second (or, more generally, last) line. */
946
947 /* This is zero-based, used to set the newlines */
948 prompt_lines_estimate = lpos / _rl_screenwidth;
949
950 /* what if lpos is already >= _rl_screenwidth before we start drawing the
951 contents of the command line? */
952 if (lpos >= _rl_screenwidth)
953 {
954 temp = 0;
955
956 /* first copy the linebreaks array we computed in expand_prompt */
957 while (local_prompt_newlines[newlines+1] != -1)
958 {
959 temp = local_prompt_newlines[newlines+1];
960 inv_lbreaks[++newlines] = temp;
961 }
962
963 /* Now set lpos from the last newline */
964 if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
965 lpos = _rl_col_width (local_prompt, temp, local_prompt_len, 1) - (wrap_offset - prompt_invis_chars_first_line);
966 else
967 lpos -= (_rl_screenwidth * newlines);
968 }
969
970 prompt_last_screen_line = newlines;
971
972 /* Draw the rest of the line (after the prompt) into invisible_line, keeping
973 track of where the cursor is (cpos_buffer_position), the number of the
974 line containing the cursor (lb_linenum), the last line number (lb_botlin
975 and inv_botlin).
976 It maintains an array of line breaks for display (inv_lbreaks).
977 This handles expanding tabs for display and displaying meta characters. */
978 lb_linenum = 0;
979 #if defined (HANDLE_MULTIBYTE)
980 in = 0;
981 if (mb_cur_max > 1 && rl_byte_oriented == 0)
982 {
983 memset (&ps, 0, sizeof (mbstate_t));
984 if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[0]))
985 {
986 wc = (wchar_t)rl_line_buffer[0];
987 wc_bytes = 1;
988 }
989 else
990 wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
991 }
992 else
993 wc_bytes = 1;
994 while (in < rl_end)
995 #else
996 for (in = 0; in < rl_end; in++)
997 #endif
998 {
999 if (in == hl_begin)
1000 cur_face = FACE_STANDOUT;
1001 else if (in == hl_end)
1002 cur_face = FACE_NORMAL;
1003
1004 c = (unsigned char)rl_line_buffer[in];
1005
1006 #if defined (HANDLE_MULTIBYTE)
1007 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1008 {
1009 if (MB_INVALIDCH (wc_bytes))
1010 {
1011 /* Byte sequence is invalid or shortened. Assume that the
1012 first byte represents a character. */
1013 wc_bytes = 1;
1014 /* Assume that a character occupies a single column. */
1015 wc_width = 1;
1016 memset (&ps, 0, sizeof (mbstate_t));
1017 }
1018 else if (MB_NULLWCH (wc_bytes))
1019 break; /* Found '\0' */
1020 else
1021 {
1022 temp = WCWIDTH (wc);
1023 wc_width = (temp >= 0) ? temp : 1;
1024 }
1025 }
1026 #endif
1027
1028 if (in == rl_point)
1029 {
1030 cpos_buffer_position = out;
1031 lb_linenum = newlines;
1032 }
1033
1034 #if defined (HANDLE_MULTIBYTE)
1035 if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
1036 #else
1037 if (META_CHAR (c))
1038 #endif
1039 {
1040 if (_rl_output_meta_chars == 0)
1041 {
1042 char obuf[5];
1043 int olen;
1044
1045 olen = sprintf (obuf, "\\%o", c);
1046
1047 if (lpos + olen >= _rl_screenwidth)
1048 {
1049 temp = _rl_screenwidth - lpos;
1050 CHECK_INV_LBREAKS ();
1051 inv_lbreaks[++newlines] = out + temp;
1052 #if defined (HANDLE_MULTIBYTE)
1053 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1054 #endif
1055 lpos = olen - temp;
1056 }
1057 else
1058 lpos += olen;
1059
1060 for (temp = 0; temp < olen; temp++)
1061 {
1062 invis_addc (&out, obuf[temp], cur_face);
1063 CHECK_LPOS ();
1064 }
1065 }
1066 else
1067 {
1068 invis_addc (&out, c, cur_face);
1069 CHECK_LPOS();
1070 }
1071 }
1072 #if defined (DISPLAY_TABS)
1073 else if (c == '\t')
1074 {
1075 register int newout;
1076
1077 newout = out + 8 - lpos % 8;
1078 temp = newout - out;
1079 if (lpos + temp >= _rl_screenwidth)
1080 {
1081 register int temp2;
1082 temp2 = _rl_screenwidth - lpos;
1083 CHECK_INV_LBREAKS ();
1084 inv_lbreaks[++newlines] = out + temp2;
1085 #if defined (HANDLE_MULTIBYTE)
1086 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1087 #endif
1088 lpos = temp - temp2;
1089 while (out < newout)
1090 invis_addc (&out, ' ', cur_face);
1091 }
1092 else
1093 {
1094 while (out < newout)
1095 invis_addc (&out, ' ', cur_face);
1096 lpos += temp;
1097 }
1098 }
1099 #endif
1100 else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1101 {
1102 invis_addc (&out, '\0', cur_face);
1103 CHECK_INV_LBREAKS ();
1104 inv_lbreaks[++newlines] = out;
1105 #if defined (HANDLE_MULTIBYTE)
1106 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn;
1107 #endif
1108 lpos = 0;
1109 }
1110 else if (CTRL_CHAR (c) || c == RUBOUT)
1111 {
1112 invis_addc (&out, '^', cur_face);
1113 CHECK_LPOS();
1114 invis_addc (&out, CTRL_CHAR (c) ? UNCTRL (c) : '?', cur_face);
1115 CHECK_LPOS();
1116 }
1117 else
1118 {
1119 #if defined (HANDLE_MULTIBYTE)
1120 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1121 {
1122 register int i;
1123
1124 _rl_wrapped_multicolumn = 0;
1125
1126 if (_rl_screenwidth < lpos + wc_width)
1127 for (i = lpos; i < _rl_screenwidth; i++)
1128 {
1129 /* The space will be removed in update_line() */
1130 invis_addc (&out, ' ', cur_face);
1131 _rl_wrapped_multicolumn++;
1132 CHECK_LPOS();
1133 }
1134 if (in == rl_point)
1135 {
1136 cpos_buffer_position = out;
1137 lb_linenum = newlines;
1138 }
1139 for (i = in; i < in+wc_bytes; i++)
1140 invis_addc (&out, rl_line_buffer[i], cur_face);
1141 for (i = 0; i < wc_width; i++)
1142 CHECK_LPOS();
1143 }
1144 else
1145 {
1146 invis_addc (&out, c, cur_face);
1147 CHECK_LPOS();
1148 }
1149 #else
1150 invis_addc (&out, c, cur_face);
1151 CHECK_LPOS();
1152 #endif
1153 }
1154
1155 #if defined (HANDLE_MULTIBYTE)
1156 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1157 {
1158 in += wc_bytes;
1159 if (_rl_utf8locale && UTF8_SINGLEBYTE(rl_line_buffer[in]))
1160 {
1161 wc = (wchar_t)rl_line_buffer[in];
1162 wc_bytes = 1;
1163 memset (&ps, 0, sizeof (mbstate_t)); /* re-init state */
1164 }
1165 else
1166 wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
1167 }
1168 else
1169 in++;
1170 #endif
1171 }
1172 invis_nul (&out);
1173 line_totbytes = out;
1174 if (cpos_buffer_position < 0)
1175 {
1176 cpos_buffer_position = out;
1177 lb_linenum = newlines;
1178 }
1179
1180 /* If we are switching from one line to multiple wrapped lines, we don't
1181 want to do a dumb update (or we want to make it smarter). */
1182 if (_rl_quick_redisplay && newlines > 0)
1183 _rl_quick_redisplay = 0;
1184
1185 inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
1186 CHECK_INV_LBREAKS ();
1187 inv_lbreaks[newlines+1] = out;
1188 #if defined (HANDLE_MULTIBYTE)
1189 /* This should be 0 anyway */
1190 line_state_invisible->wrapped_line[newlines+1] = _rl_wrapped_multicolumn;
1191 #endif
1192 cursor_linenum = lb_linenum;
1193
1194 /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
1195 CURSOR_LINENUM == line number where the cursor should be placed. */
1196
1197 /* PWP: now is when things get a bit hairy. The visible and invisible
1198 line buffers are really multiple lines, which would wrap every
1199 (screenwidth - 1) characters. Go through each in turn, finding
1200 the changed region and updating it. The line order is top to bottom. */
1201
1202 /* If we can move the cursor up and down, then use multiple lines,
1203 otherwise, let long lines display in a single terminal line, and
1204 horizontally scroll it. */
1205 displaying_prompt_first_line = 1;
1206 if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1207 {
1208 int nleft, pos, changed_screen_line, tx;
1209
1210 if (!rl_display_fixed || forced_display)
1211 {
1212 forced_display = 0;
1213
1214 /* If we have more than a screenful of material to display, then
1215 only display a screenful. We should display the last screen,
1216 not the first. */
1217 if (out >= _rl_screenchars)
1218 {
1219 #if defined (HANDLE_MULTIBYTE)
1220 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1221 out = _rl_find_prev_mbchar (invisible_line, _rl_screenchars, MB_FIND_ANY);
1222 else
1223 #endif
1224 out = _rl_screenchars - 1;
1225 }
1226
1227 /* The first line is at character position 0 in the buffer. The
1228 second and subsequent lines start at inv_lbreaks[N], offset by
1229 OFFSET (which has already been calculated above). */
1230
1231 #define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
1232 #define WRAP_OFFSET(line, offset) ((line == 0) \
1233 ? (offset ? INVIS_FIRST() : 0) \
1234 : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
1235 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
1236 #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
1237 #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
1238 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
1239 #define VIS_FACE(line) (vis_face + vis_lbreaks[line])
1240 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
1241 #define VIS_LINE_FACE(line) ((line) > _rl_vis_botlin) ? "" : VIS_FACE(line)
1242 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
1243 #define INV_LINE_FACE(line) (inv_face + inv_lbreaks[line])
1244
1245 #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
1246 _rl_last_c_pos != o_cpos && \
1247 _rl_last_c_pos > wrap_offset && \
1248 o_cpos < prompt_last_invisible)
1249
1250
1251 /* We don't want to highlight anything that's going to be off the top
1252 of the display; if the current line takes up more than an entire
1253 screen, just mark the lines that won't be displayed as having a
1254 `normal' face.
1255 It's imperfect, but better than display corruption. */
1256 if (rl_mark_active_p () && inv_botlin > _rl_screenheight)
1257 {
1258 int extra;
1259
1260 extra = inv_botlin - _rl_screenheight;
1261 for (linenum = 0; linenum <= extra; linenum++)
1262 norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
1263 }
1264
1265 /* For each line in the buffer, do the updating display. */
1266 for (linenum = 0; linenum <= inv_botlin; linenum++)
1267 {
1268 /* This can lead us astray if we execute a program that changes
1269 the locale from a non-multibyte to a multibyte one. */
1270 o_cpos = _rl_last_c_pos;
1271 cpos_adjusted = 0;
1272 update_line (VIS_LINE(linenum), VIS_LINE_FACE(linenum),
1273 INV_LINE(linenum), INV_LINE_FACE(linenum),
1274 linenum,
1275 VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
1276
1277 /* update_line potentially changes _rl_last_c_pos, but doesn't
1278 take invisible characters into account, since _rl_last_c_pos
1279 is an absolute cursor position in a multibyte locale. We
1280 choose to (mostly) compensate for that here, rather than
1281 change update_line itself. There are several cases in which
1282 update_line adjusts _rl_last_c_pos itself (so it can pass
1283 _rl_move_cursor_relative accurate values); it communicates
1284 this back by setting cpos_adjusted. If we assume that
1285 _rl_last_c_pos is correct (an absolute cursor position) each
1286 time update_line is called, then we can assume in our
1287 calculations that o_cpos does not need to be adjusted by
1288 wrap_offset. */
1289 if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
1290 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1291 else if (cpos_adjusted == 0 &&
1292 linenum == prompt_last_screen_line &&
1293 prompt_physical_chars > _rl_screenwidth &&
1294 (mb_cur_max > 1 && rl_byte_oriented == 0) &&
1295 _rl_last_c_pos != o_cpos &&
1296 _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line)) /* XXX - rethink this last one */
1297 /* This assumes that all the invisible characters are split
1298 between the first and last lines of the prompt, if the
1299 prompt consumes more than two lines. It's usually right */
1300 /* XXX - not sure this is ever executed */
1301 _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
1302
1303 /* If this is the line with the prompt, we might need to
1304 compensate for invisible characters in the new line. Do
1305 this only if there is not more than one new line (which
1306 implies that we completely overwrite the old visible line)
1307 and the new line is shorter than the old. Make sure we are
1308 at the end of the new line before clearing. */
1309 if (linenum == 0 &&
1310 inv_botlin == 0 && _rl_last_c_pos == out &&
1311 (wrap_offset > visible_wrap_offset) &&
1312 (_rl_last_c_pos < visible_first_line_len))
1313 {
1314 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1315 nleft = _rl_screenwidth - _rl_last_c_pos;
1316 else
1317 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1318 if (nleft)
1319 _rl_clear_to_eol (nleft);
1320 }
1321 #if 0
1322 /* This segment is intended to handle the case where the old
1323 visible prompt has invisible characters and the new line
1324 to be displayed needs to clear the rest of the old characters
1325 out (e.g., when printing the i-search prompt): in general,
1326 the case of the new line being shorter than the old. We need
1327 to be at the end of the new line and the old line needs to be
1328 longer than the current cursor position. It's not perfect,
1329 since it uses the byte length of the first line, but this will
1330 at worst result in some extra clear-to-end-of-lines. We can't
1331 use the prompt length variables because they may not
1332 correspond to the visible line (see printing the i-search
1333 prompt above). The tests for differing numbers of invisible
1334 characters may not matter and can probably be removed. */
1335 else if (linenum == 0 &&
1336 linenum == prompt_last_screen_line &&
1337 _rl_last_c_pos == out &&
1338 _rl_last_c_pos < visible_first_line_len &&
1339 visible_wrap_offset &&
1340 visible_wrap_offset != wrap_offset)
1341 {
1342 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1343 nleft = _rl_screenwidth - _rl_last_c_pos;
1344 else
1345 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1346 if (nleft)
1347 _rl_clear_to_eol (nleft);
1348 }
1349 #endif
1350
1351 /* Since the new first line is now visible, save its length. */
1352 if (linenum == 0)
1353 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
1354 }
1355
1356 /* We may have deleted some lines. If so, clear the left over
1357 blank ones at the bottom out. */
1358 if (_rl_vis_botlin > inv_botlin)
1359 {
1360 char *tt;
1361 for (; linenum <= _rl_vis_botlin; linenum++)
1362 {
1363 tt = VIS_CHARS (linenum);
1364 _rl_move_vert (linenum);
1365 _rl_move_cursor_relative (0, tt, VIS_FACE(linenum));
1366 _rl_clear_to_eol
1367 ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
1368 }
1369 }
1370 _rl_vis_botlin = inv_botlin;
1371
1372 /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
1373 different screen line during this redisplay. */
1374 changed_screen_line = _rl_last_v_pos != cursor_linenum;
1375 if (changed_screen_line)
1376 {
1377 _rl_move_vert (cursor_linenum);
1378 /* If we moved up to the line with the prompt using _rl_term_up,
1379 the physical cursor position on the screen stays the same,
1380 but the buffer position needs to be adjusted to account
1381 for invisible characters. */
1382 if ((mb_cur_max == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
1383 _rl_last_c_pos += wrap_offset;
1384 }
1385
1386 /* Now we move the cursor to where it needs to be. First, make
1387 sure we are on the correct line (cursor_linenum). */
1388
1389 /* We have to reprint the prompt if it contains invisible
1390 characters, since it's not generally OK to just reprint
1391 the characters from the current cursor position. But we
1392 only need to reprint it if the cursor is before the last
1393 invisible character in the prompt string. */
1394 /* XXX - why not use local_prompt_len? */
1395 nleft = prompt_visible_length + wrap_offset;
1396 if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1397 _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1398 {
1399 _rl_cr ();
1400 if (modmark)
1401 _rl_output_some_chars ("*", 1);
1402
1403 _rl_output_some_chars (local_prompt, nleft);
1404 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1405 _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
1406 else
1407 _rl_last_c_pos = nleft + modmark;
1408 }
1409
1410 /* Where on that line? And where does that line start
1411 in the buffer? */
1412 pos = inv_lbreaks[cursor_linenum];
1413 /* nleft == number of characters (bytes) in the line buffer between
1414 the start of the line and the desired cursor position. */
1415 nleft = cpos_buffer_position - pos;
1416
1417 /* NLEFT is now a number of characters in a buffer. When in a
1418 multibyte locale, however, _rl_last_c_pos is an absolute cursor
1419 position that doesn't take invisible characters in the prompt
1420 into account. We use a fudge factor to compensate. */
1421
1422 /* Since _rl_backspace() doesn't know about invisible characters in
1423 the prompt, and there's no good way to tell it, we compensate for
1424 those characters here and call _rl_backspace() directly if
1425 necessary */
1426 if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
1427 {
1428 /* TX == new physical cursor position in multibyte locale. */
1429 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1430 tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
1431 else
1432 tx = nleft;
1433 if (tx >= 0 && _rl_last_c_pos > tx)
1434 {
1435 _rl_backspace (_rl_last_c_pos - tx); /* XXX */
1436 _rl_last_c_pos = tx;
1437 }
1438 }
1439
1440 /* We need to note that in a multibyte locale we are dealing with
1441 _rl_last_c_pos as an absolute cursor position, but moving to a
1442 point specified by a buffer position (NLEFT) that doesn't take
1443 invisible characters into account. */
1444 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1445 _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1446 else if (nleft != _rl_last_c_pos)
1447 _rl_move_cursor_relative (nleft, &invisible_line[pos], &inv_face[pos]);
1448 }
1449 }
1450 else /* Do horizontal scrolling. Much simpler */
1451 {
1452 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
1453 int lmargin, ndisp, nleft, phys_c_pos, t;
1454
1455 /* Always at top line. */
1456 _rl_last_v_pos = 0;
1457
1458 /* Compute where in the buffer the displayed line should start. This
1459 will be LMARGIN. */
1460
1461 /* The number of characters that will be displayed before the cursor. */
1462 ndisp = cpos_buffer_position - wrap_offset;
1463 nleft = prompt_visible_length + wrap_offset;
1464 /* Where the new cursor position will be on the screen. This can be
1465 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1466 phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
1467 t = _rl_screenwidth / 3;
1468
1469 /* If the number of characters had already exceeded the screenwidth,
1470 last_lmargin will be > 0. */
1471
1472 /* If the number of characters to be displayed is more than the screen
1473 width, compute the starting offset so that the cursor is about
1474 two-thirds of the way across the screen. */
1475 if (phys_c_pos > _rl_screenwidth - 2)
1476 {
1477 lmargin = cpos_buffer_position - (2 * t);
1478 if (lmargin < 0)
1479 lmargin = 0;
1480 /* If the left margin would be in the middle of a prompt with
1481 invisible characters, don't display the prompt at all. */
1482 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1483 lmargin = nleft;
1484 }
1485 else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
1486 lmargin = 0;
1487 else if (phys_c_pos < 1)
1488 {
1489 /* If we are moving back towards the beginning of the line and
1490 the last margin is no longer correct, compute a new one. */
1491 lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */
1492 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1493 lmargin = nleft;
1494 }
1495 else
1496 lmargin = last_lmargin;
1497
1498 displaying_prompt_first_line = lmargin < nleft;
1499
1500 /* If the first character on the screen isn't the first character
1501 in the display line, indicate this with a special character. */
1502 if (lmargin > 0)
1503 invisible_line[lmargin] = '<';
1504
1505 /* If SCREENWIDTH characters starting at LMARGIN do not encompass
1506 the whole line, indicate that with a special character at the
1507 right edge of the screen. If LMARGIN is 0, we need to take the
1508 wrap offset into account. */
1509 t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1510 if (t > 0 && t < out)
1511 invisible_line[t - 1] = '>';
1512
1513 if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
1514 {
1515 forced_display = 0;
1516 o_cpos = _rl_last_c_pos;
1517 cpos_adjusted = 0;
1518 update_line (&visible_line[last_lmargin], &vis_face[last_lmargin],
1519 &invisible_line[lmargin], &inv_face[lmargin],
1520 0,
1521 _rl_screenwidth + visible_wrap_offset,
1522 _rl_screenwidth + (lmargin ? 0 : wrap_offset),
1523 0);
1524
1525 if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1526 displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
1527 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1528
1529 /* If the visible new line is shorter than the old, but the number
1530 of invisible characters is greater, and we are at the end of
1531 the new line, we need to clear to eol. */
1532 t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
1533 if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
1534 (_rl_last_c_pos == out) && displaying_prompt_first_line &&
1535 t < visible_first_line_len)
1536 {
1537 nleft = _rl_screenwidth - t;
1538 _rl_clear_to_eol (nleft);
1539 }
1540 visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
1541 if (visible_first_line_len > _rl_screenwidth)
1542 visible_first_line_len = _rl_screenwidth;
1543
1544 _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin], &inv_face[lmargin]);
1545 last_lmargin = lmargin;
1546 }
1547 }
1548 fflush (rl_outstream);
1549
1550 /* Swap visible and non-visible lines. */
1551 {
1552 struct line_state *vtemp = line_state_visible;
1553
1554 line_state_visible = line_state_invisible;
1555 line_state_invisible = vtemp;
1556
1557 rl_display_fixed = 0;
1558 /* If we are displaying on a single line, and last_lmargin is > 0, we
1559 are not displaying any invisible characters, so set visible_wrap_offset
1560 to 0. */
1561 if (_rl_horizontal_scroll_mode && last_lmargin)
1562 visible_wrap_offset = 0;
1563 else
1564 visible_wrap_offset = wrap_offset;
1565
1566 _rl_quick_redisplay = 0;
1567 }
1568
1569 RL_UNSETSTATE (RL_STATE_REDISPLAYING);
1570 _rl_release_sigint ();
1571 }
1572
1573 static void
1574 putc_face (int c, int face, char *cur_face)
1575 {
1576 char cf;
1577 cf = *cur_face;
1578 if (cf != face)
1579 {
1580 if (cf != FACE_NORMAL && cf != FACE_STANDOUT)
1581 return;
1582 if (face != FACE_NORMAL && face != FACE_STANDOUT)
1583 return;
1584 if (face == FACE_STANDOUT && cf == FACE_NORMAL)
1585 _rl_standout_on ();
1586 if (face == FACE_NORMAL && cf == FACE_STANDOUT)
1587 _rl_standout_off ();
1588 *cur_face = face;
1589 }
1590 if (c != EOF)
1591 putc (c, rl_outstream);
1592 }
1593
1594 static void
1595 puts_face (const char *str, const char *face, int n)
1596 {
1597 int i;
1598 char cur_face;
1599
1600 for (cur_face = FACE_NORMAL, i = 0; i < n; i++)
1601 putc_face (str[i], face[i], &cur_face);
1602 putc_face (EOF, FACE_NORMAL, &cur_face);
1603 }
1604
1605 static void
1606 norm_face (char *face, int n)
1607 {
1608 memset (face, FACE_NORMAL, n);
1609 }
1610
1611 #define ADJUST_CPOS(x) do { _rl_last_c_pos -= (x) ; cpos_adjusted = 1; } while (0)
1612
1613 /* PWP: update_line() is based on finding the middle difference of each
1614 line on the screen; vis:
1615
1616 /old first difference
1617 /beginning of line | /old last same /old EOL
1618 v v v v
1619 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1620 new: eddie> Oh, my little buggy says to me, as lurgid as
1621 ^ ^ ^ ^
1622 \beginning of line | \new last same \new end of line
1623 \new first difference
1624
1625 All are character pointers for the sake of speed. Special cases for
1626 no differences, as well as for end of line additions must be handled.
1627
1628 Could be made even smarter, but this works well enough */
1629 static void
1630 update_line (char *old, char *old_face, char *new, char *new_face, int current_line, int omax, int nmax, int inv_botlin)
1631 {
1632 char *ofd, *ols, *oe, *nfd, *nls, *ne;
1633 char *ofdf, *nfdf, *olsf, *nlsf;
1634 int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
1635 int current_invis_chars;
1636 int col_lendiff, col_temp;
1637 int bytes_to_insert;
1638 int mb_cur_max = MB_CUR_MAX;
1639 #if defined (HANDLE_MULTIBYTE)
1640 mbstate_t ps_new, ps_old;
1641 int new_offset, old_offset;
1642 #endif
1643
1644 /* If we're at the right edge of a terminal that supports xn, we're
1645 ready to wrap around, so do so. This fixes problems with knowing
1646 the exact cursor position and cut-and-paste with certain terminal
1647 emulators. In this calculation, TEMP is the physical screen
1648 position of the cursor. */
1649 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1650 temp = _rl_last_c_pos;
1651 else
1652 temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
1653 if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1654 && _rl_last_v_pos == current_line - 1)
1655 {
1656 /* We're going to wrap around by writing the first character of NEW to
1657 the screen and dealing with changes to what's visible by modifying
1658 OLD to match it. Complicated by the presence of multi-width
1659 characters at the end of the line or beginning of the new one. */
1660 /* old is always somewhere in visible_line; new is always somewhere in
1661 invisible_line. These should always be null-terminated. */
1662 #if defined (HANDLE_MULTIBYTE)
1663 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1664 {
1665 wchar_t wc;
1666 mbstate_t ps;
1667 int oldwidth, newwidth;
1668 int oldbytes, newbytes;
1669 size_t ret;
1670
1671 /* This fixes only double-column characters, but if the wrapped
1672 character consumes more than three columns, spaces will be
1673 inserted in the string buffer. */
1674 /* XXX remember that we are working on the invisible line right now;
1675 we don't swap visible and invisible until just before rl_redisplay
1676 returns */
1677 /* This will remove the extra placeholder space we added with
1678 _rl_wrapped_multicolumn */
1679 if (current_line < line_state_invisible->wbsize && line_state_invisible->wrapped_line[current_line] > 0)
1680 _rl_clear_to_eol (line_state_invisible->wrapped_line[current_line]);
1681
1682 /* 1. how many screen positions does first char in old consume? */
1683 memset (&ps, 0, sizeof (mbstate_t));
1684 ret = mbrtowc (&wc, old, mb_cur_max, &ps);
1685 oldbytes = ret;
1686 if (MB_INVALIDCH (ret))
1687 {
1688 oldwidth = 1;
1689 oldbytes = 1;
1690 }
1691 else if (MB_NULLWCH (ret))
1692 oldwidth = 0;
1693 else
1694 oldwidth = WCWIDTH (wc);
1695 if (oldwidth < 0)
1696 oldwidth = 1;
1697
1698 /* 2. how many screen positions does the first char in new consume? */
1699 memset (&ps, 0, sizeof (mbstate_t));
1700 ret = mbrtowc (&wc, new, mb_cur_max, &ps);
1701 newbytes = ret;
1702 if (MB_INVALIDCH (ret))
1703 {
1704 newwidth = 1;
1705 newbytes = 1;
1706 }
1707 else if (MB_NULLWCH (ret))
1708 newwidth = 0;
1709 else
1710 newwidth = WCWIDTH (wc);
1711 if (newwidth < 0)
1712 newwidth = 1;
1713
1714 /* 3. if the new width is less than the old width, we need to keep
1715 going in new until we have consumed at least that many screen
1716 positions, and figure out how many bytes that will take */
1717 while (newbytes < nmax && newwidth < oldwidth)
1718 {
1719 int t;
1720
1721 ret = mbrtowc (&wc, new+newbytes, mb_cur_max, &ps);
1722 if (MB_INVALIDCH (ret))
1723 {
1724 newwidth += 1;
1725 newbytes += 1;
1726 }
1727 else if (MB_NULLWCH (ret))
1728 break;
1729 else
1730 {
1731 t = WCWIDTH (wc);
1732 newwidth += (t >= 0) ? t : 1;
1733 newbytes += ret;
1734 }
1735 }
1736 /* 4. If the new width is more than the old width, keep going in old
1737 until we have consumed exactly that many screen positions, and
1738 figure out how many bytes that will take. This is an optimization */
1739 while (oldbytes < omax && oldwidth < newwidth)
1740 {
1741 int t;
1742
1743 ret = mbrtowc (&wc, old+oldbytes, mb_cur_max, &ps);
1744 if (MB_INVALIDCH (ret))
1745 {
1746 oldwidth += 1;
1747 oldbytes += 1;
1748 }
1749 else if (MB_NULLWCH (ret))
1750 break;
1751 else
1752 {
1753 t = WCWIDTH (wc);
1754 oldwidth += (t >= 0) ? t : 1;
1755 oldbytes += ret;
1756 }
1757 }
1758 /* 5. write the first newbytes of new, which takes newwidth. This is
1759 where the screen wrapping takes place, and we are now writing
1760 characters onto the new line. We need to fix up old so it
1761 accurately reflects what is on the screen after the
1762 _rl_output_some_chars below. */
1763 if (newwidth > 0)
1764 {
1765 int count, i, j;
1766 char *optr;
1767
1768 puts_face (new, new_face, newbytes);
1769 _rl_last_c_pos = newwidth;
1770 _rl_last_v_pos++;
1771
1772 /* 5a. If the number of screen positions doesn't match, punt
1773 and do a dumb update.
1774 5b. If the number of bytes is greater in the new line than
1775 the old, do a dumb update, because there is no guarantee we
1776 can extend the old line enough to fit the new bytes. */
1777 if (newwidth != oldwidth || newbytes > oldbytes)
1778 {
1779 oe = old + omax;
1780 ne = new + nmax;
1781 nd = newbytes;
1782 nfd = new + nd;
1783 ofdf = old_face + oldbytes;
1784 nfdf = new_face + newbytes;
1785
1786 goto dumb_update;
1787 }
1788 if (oldbytes != 0 && newbytes != 0)
1789 {
1790 /* We have written as many bytes from new as we need to
1791 consume the first character of old. Fix up `old' so it
1792 reflects the new screen contents. We use +1 in the
1793 memmove call to copy the trailing NUL. */
1794 /* (strlen(old+oldbytes) == (omax - oldbytes - 1)) */
1795
1796 /* Don't bother trying to fit the bytes if the number of bytes
1797 doesn't change. */
1798 if (oldbytes != newbytes)
1799 {
1800 memmove (old+newbytes, old+oldbytes, strlen (old+oldbytes) + 1);
1801 memmove (old_face+newbytes, old_face+oldbytes, strlen (old+oldbytes) + 1);
1802 }
1803 memcpy (old, new, newbytes);
1804 memcpy (old_face, new_face, newbytes);
1805 j = newbytes - oldbytes;
1806 omax += j;
1807 /* Fix up indices if we copy data from one line to another */
1808 for (i = current_line+1; j != 0 && i <= inv_botlin+1 && i <=_rl_vis_botlin+1; i++)
1809 vis_lbreaks[i] += j;
1810 }
1811 }
1812 else
1813 {
1814 putc (' ', rl_outstream);
1815 _rl_last_c_pos = 1;
1816 _rl_last_v_pos++;
1817 if (old[0] && new[0])
1818 {
1819 old[0] = new[0];
1820 old_face[0] = new_face[0];
1821 }
1822 }
1823 }
1824 else
1825 #endif
1826 {
1827 if (new[0])
1828 puts_face (new, new_face, 1);
1829 else
1830 putc (' ', rl_outstream);
1831 _rl_last_c_pos = 1;
1832 _rl_last_v_pos++;
1833 if (old[0] && new[0])
1834 {
1835 old[0] = new[0];
1836 old_face[0] = new_face[0];
1837 }
1838 }
1839 }
1840
1841 /* We know that we are dealing with a single screen line here */
1842 if (_rl_quick_redisplay)
1843 {
1844 nfd = new;
1845 nfdf = new_face;
1846 ofd = old;
1847 ofdf = old_face;
1848 for (od = 0, oe = ofd; od < omax && *oe; oe++, od++);
1849 for (nd = 0, ne = nfd; nd < nmax && *ne; ne++, nd++);
1850 od = nd = 0;
1851 _rl_move_cursor_relative (0, old, old_face);
1852
1853 bytes_to_insert = ne - nfd;
1854 if (bytes_to_insert < local_prompt_len) /* ??? */
1855 goto dumb_update;
1856
1857 /* output the prompt, output the line contents, clear the rest */
1858 _rl_output_some_chars (nfd, local_prompt_len);
1859 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1860 _rl_last_c_pos = prompt_physical_chars;
1861 else
1862 _rl_last_c_pos = local_prompt_len;
1863
1864 bytes_to_insert -= local_prompt_len;
1865 if (bytes_to_insert > 0)
1866 {
1867 puts_face (new+local_prompt_len, nfdf+local_prompt_len, bytes_to_insert);
1868 if (mb_cur_max > 1 && rl_byte_oriented)
1869 _rl_last_c_pos += _rl_col_width (new, local_prompt_len, ne-new, 1);
1870 else
1871 _rl_last_c_pos += bytes_to_insert;
1872 }
1873
1874 /* See comments at dumb_update: for an explanation of this heuristic */
1875 if (nmax < omax)
1876 goto clear_rest_of_line;
1877 else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
1878 goto clear_rest_of_line;
1879 else
1880 return;
1881 }
1882
1883 /* Find first difference. */
1884 #if defined (HANDLE_MULTIBYTE)
1885 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1886 {
1887 /* See if the old line is a subset of the new line, so that the
1888 only change is adding characters. */
1889 temp = (omax < nmax) ? omax : nmax;
1890 if (memcmp (old, new, temp) == 0 && memcmp (old_face, new_face, temp) == 0)
1891 {
1892 new_offset = old_offset = temp; /* adding at the end */
1893 ofd = old + temp;
1894 ofdf = old_face + temp;
1895 nfd = new + temp;
1896 nfdf = new_face + temp;
1897 }
1898 else
1899 {
1900 memset (&ps_new, 0, sizeof(mbstate_t));
1901 memset (&ps_old, 0, sizeof(mbstate_t));
1902
1903 /* Are the old and new lines the same? */
1904 if (omax == nmax && memcmp (new, old, omax) == 0 && memcmp (new_face, old_face, omax) == 0)
1905 {
1906 old_offset = omax;
1907 new_offset = nmax;
1908 ofd = old + omax;
1909 ofdf = old_face + omax;
1910 nfd = new + nmax;
1911 nfdf = new_face + nmax;
1912 }
1913 else
1914 {
1915 /* Go through the line from the beginning and find the first
1916 difference. We assume that faces change at (possibly multi-
1917 byte) character boundaries. */
1918 new_offset = old_offset = 0;
1919 for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
1920 (ofd - old < omax) && *ofd &&
1921 _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new) &&
1922 *ofdf == *nfdf; )
1923 {
1924 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1925 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1926
1927 ofd = old + old_offset;
1928 ofdf = old_face + old_offset;
1929 nfd = new + new_offset;
1930 nfdf = new_face + new_offset;
1931 }
1932 }
1933 }
1934 }
1935 else
1936 #endif
1937 for (ofd = old, ofdf = old_face, nfd = new, nfdf = new_face;
1938 (ofd - old < omax) && *ofd && (*ofd == *nfd) && (*ofdf == *nfdf);
1939 ofd++, nfd++, ofdf++, nfdf++)
1940 ;
1941
1942 /* Move to the end of the screen line. ND and OD are used to keep track
1943 of the distance between ne and new and oe and old, respectively, to
1944 move a subtraction out of each loop. */
1945 for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1946 for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1947
1948 /* If no difference, continue to next line. */
1949 if (ofd == oe && nfd == ne)
1950 return;
1951
1952 #if defined (HANDLE_MULTIBYTE)
1953 if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
1954 {
1955 wchar_t wc;
1956 mbstate_t ps = { 0 };
1957 int t;
1958
1959 /* If the first character in the difference is a zero-width character,
1960 assume it's a combining character and back one up so the two base
1961 characters no longer compare equivalently. */
1962 t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
1963 if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
1964 {
1965 old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
1966 new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
1967 ofd = old + old_offset; /* equal by definition */
1968 ofdf = old_face + old_offset;
1969 nfd = new + new_offset;
1970 nfdf = new_face + new_offset;
1971 }
1972 }
1973 #endif
1974
1975 wsatend = 1; /* flag for trailing whitespace */
1976
1977 #if defined (HANDLE_MULTIBYTE)
1978 /* Find the last character that is the same between the two lines. This
1979 bounds the region that needs to change. */
1980 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1981 {
1982 ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1983 olsf = old_face + (ols - old);
1984 nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1985 nlsf = new_face + (nls - new);
1986
1987 while ((ols > ofd) && (nls > nfd))
1988 {
1989 memset (&ps_old, 0, sizeof (mbstate_t));
1990 memset (&ps_new, 0, sizeof (mbstate_t));
1991
1992 if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0 ||
1993 *olsf != *nlsf)
1994 break;
1995
1996 if (*ols == ' ')
1997 wsatend = 0;
1998
1999 ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
2000 olsf = old_face + (ols - old);
2001 nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
2002 nlsf = new_face + (nls - new);
2003 }
2004 }
2005 else
2006 {
2007 #endif /* HANDLE_MULTIBYTE */
2008 ols = oe - 1; /* find last same */
2009 olsf = old_face + (ols - old);
2010 nls = ne - 1;
2011 nlsf = new_face + (nls - new);
2012 while ((ols > ofd) && (nls > nfd) && (*ols == *nls) && (*olsf == *nlsf))
2013 {
2014 if (*ols != ' ')
2015 wsatend = 0;
2016 ols--; olsf--;
2017 nls--; nlsf--;
2018 }
2019 #if defined (HANDLE_MULTIBYTE)
2020 }
2021 #endif
2022
2023 if (wsatend)
2024 {
2025 ols = oe;
2026 olsf = old_face + (ols - old);
2027 nls = ne;
2028 nlsf = new_face + (nls - new);
2029 }
2030 #if defined (HANDLE_MULTIBYTE)
2031 /* This may not work for stateful encoding, but who cares? To handle
2032 stateful encoding properly, we have to scan each string from the
2033 beginning and compare. */
2034 else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0 || *olsf != *nlsf)
2035 #else
2036 else if (*ols != *nls || *olsf != *nlsf)
2037 #endif
2038 {
2039 if (*ols) /* don't step past the NUL */
2040 {
2041 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2042 ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
2043 else
2044 ols++;
2045 }
2046 if (*nls)
2047 {
2048 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2049 nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
2050 else
2051 nls++;
2052 }
2053 olsf = old_face + (ols - old);
2054 nlsf = new_face + (nls - new);
2055 }
2056
2057 /* count of invisible characters in the current invisible line. */
2058 current_invis_chars = W_OFFSET (current_line, wrap_offset);
2059 if (_rl_last_v_pos != current_line)
2060 {
2061 _rl_move_vert (current_line);
2062 /* We have moved up to a new screen line. This line may or may not have
2063 invisible characters on it, but we do our best to recalculate
2064 visible_wrap_offset based on what we know. */
2065 if (current_line == 0)
2066 visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */
2067 #if 0 /* XXX - not yet */
2068 else if (current_line == prompt_last_screen_line && wrap_offset > prompt_invis_chars_first_line)
2069 visible_wrap_offset = wrap_offset - prompt_invis_chars_first_line
2070 #endif
2071 if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
2072 _rl_last_c_pos += visible_wrap_offset;
2073 }
2074
2075 /* If this is the first line and there are invisible characters in the
2076 prompt string, and the prompt string has not changed, and the current
2077 cursor position is before the last invisible character in the prompt,
2078 and the index of the character to move to is past the end of the prompt
2079 string, then redraw the entire prompt string. We can only do this
2080 reliably if the terminal supports a `cr' capability.
2081
2082 This can also happen if the prompt string has changed, and the first
2083 difference in the line is in the middle of the prompt string, after a
2084 sequence of invisible characters (worst case) and before the end of
2085 the prompt. In this case, we have to redraw the entire prompt string
2086 so that the entire sequence of invisible characters is drawn. We need
2087 to handle the worst case, when the difference is after (or in the middle
2088 of) a sequence of invisible characters that changes the text color and
2089 before the sequence that restores the text color to normal. Then we have
2090 to make sure that the lines still differ -- if they don't, we can
2091 return immediately.
2092
2093 This is not an efficiency hack -- there is a problem with redrawing
2094 portions of the prompt string if they contain terminal escape
2095 sequences (like drawing the `unbold' sequence without a corresponding
2096 `bold') that manifests itself on certain terminals. */
2097
2098 lendiff = local_prompt_len;
2099 if (lendiff > nmax)
2100 lendiff = nmax;
2101 od = ofd - old; /* index of first difference in visible line */
2102 nd = nfd - new; /* nd, od are buffer indexes */
2103 if (current_line == 0 && !_rl_horizontal_scroll_mode &&
2104 _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
2105 (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
2106 ((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
2107 {
2108 _rl_cr ();
2109 if (modmark)
2110 _rl_output_some_chars ("*", 1);
2111 _rl_output_some_chars (local_prompt, lendiff);
2112 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2113 {
2114 /* If we just output the entire prompt string we can take advantage
2115 of knowing the number of physical characters in the prompt. If
2116 the prompt wraps lines (lendiff clamped at nmax), we can't. */
2117 if (lendiff == local_prompt_len)
2118 _rl_last_c_pos = prompt_physical_chars + modmark;
2119 else
2120 /* We take wrap_offset into account here so we can pass correct
2121 information to _rl_move_cursor_relative. */
2122 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
2123 cpos_adjusted = 1;
2124 }
2125 else
2126 _rl_last_c_pos = lendiff + modmark;
2127
2128 /* Now if we have printed the prompt string because the first difference
2129 was within the prompt, see if we need to recompute where the lines
2130 differ. Check whether where we are now is past the last place where
2131 the old and new lines are the same and short-circuit now if we are. */
2132 if ((od <= prompt_last_invisible || nd <= prompt_last_invisible) &&
2133 omax == nmax &&
2134 lendiff > (ols-old) && lendiff > (nls-new))
2135 return;
2136
2137 /* XXX - we need to fix up our calculations if we are now past the
2138 old ofd/nfd and the prompt length (or line length) has changed.
2139 We punt on the problem and do a dumb update. We'd like to be able
2140 to just output the prompt from the beginning of the line up to the
2141 first difference, but you don't know the number of invisible
2142 characters in that case.
2143 This needs a lot of work to be efficient, but it usually doesn't matter. */
2144 if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
2145 {
2146 nfd = new + lendiff; /* number of characters we output above */
2147 nfdf = new_face + lendiff;
2148 nd = lendiff;
2149
2150 /* Do a dumb update and return */
2151 dumb_update:
2152 temp = ne - nfd;
2153 if (temp > 0)
2154 {
2155 puts_face (nfd, nfdf, temp);
2156 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2157 {
2158 _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
2159 /* Need to adjust here based on wrap_offset. Guess that if
2160 this is the line containing the last line of the prompt
2161 we need to adjust by
2162 wrap_offset-prompt_invis_chars_first_line
2163 on the assumption that this is the number of invisible
2164 characters in the last line of the prompt. */
2165 if (wrap_offset > prompt_invis_chars_first_line &&
2166 current_line == prompt_last_screen_line &&
2167 prompt_physical_chars > _rl_screenwidth &&
2168 _rl_horizontal_scroll_mode == 0)
2169 ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
2170
2171 /* If we just output a new line including the prompt, and
2172 the prompt includes invisible characters, we need to
2173 account for them in the _rl_last_c_pos calculation, since
2174 _rl_col_width does not. This happens when other code does
2175 a goto dumb_update; */
2176 else if (current_line == 0 &&
2177 nfd == new &&
2178 prompt_invis_chars_first_line &&
2179 local_prompt_len <= temp &&
2180 wrap_offset >= prompt_invis_chars_first_line &&
2181 _rl_horizontal_scroll_mode == 0)
2182 ADJUST_CPOS (prompt_invis_chars_first_line);
2183 }
2184 else
2185 _rl_last_c_pos += temp;
2186 }
2187 /* This is a useful heuristic, but what we really want is to clear
2188 if the new number of visible screen characters is less than the
2189 old number of visible screen characters. If the prompt has changed,
2190 we don't really have enough information about the visible line to
2191 know for sure, so we use another heuristic calclulation below. */
2192 if (nmax < omax)
2193 goto clear_rest_of_line; /* XXX */
2194 else if ((nmax - W_OFFSET(current_line, wrap_offset)) < (omax - W_OFFSET (current_line, visible_wrap_offset)))
2195 goto clear_rest_of_line;
2196 else
2197 return;
2198 }
2199 }
2200
2201 o_cpos = _rl_last_c_pos;
2202
2203 /* When this function returns, _rl_last_c_pos is correct, and an absolute
2204 cursor position in multibyte mode, but a buffer index when not in a
2205 multibyte locale. */
2206 _rl_move_cursor_relative (od, old, old_face);
2207
2208 #if defined (HANDLE_MULTIBYTE)
2209 /* We need to indicate that the cursor position is correct in the presence of
2210 invisible characters in the prompt string. Let's see if setting this when
2211 we make sure we're at the end of the drawn prompt string works. */
2212 if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
2213 (_rl_last_c_pos > 0 || o_cpos > 0) &&
2214 _rl_last_c_pos == prompt_physical_chars)
2215 cpos_adjusted = 1;
2216 #endif
2217
2218 /* if (len (new) > len (old))
2219 lendiff == difference in buffer (bytes)
2220 col_lendiff == difference on screen (columns)
2221 When not using multibyte characters, these are equal */
2222 lendiff = (nls - nfd) - (ols - ofd);
2223 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2224 {
2225 int newchars, newwidth, newind;
2226 int oldchars, oldwidth, oldind;
2227
2228 newchars = nls - new;
2229 oldchars = ols - old;
2230
2231 /* If we can do it, try to adjust nls and ols so that nls-new will
2232 contain the entire new prompt string. That way we can use
2233 prompt_physical_chars and not have to recompute column widths.
2234 _rl_col_width adds wrap_offset and expects the caller to compensate,
2235 which we do below, so we do the same thing if we don't call
2236 _rl_col_width.
2237 We don't have to compare, since we know the characters are the same.
2238 The check of differing numbers of invisible chars may be extraneous.
2239 XXX - experimental */
2240 if (current_line == 0 && nfd == new && newchars > prompt_last_invisible &&
2241 newchars <= local_prompt_len &&
2242 local_prompt_len <= nmax &&
2243 current_invis_chars != visible_wrap_offset)
2244 {
2245 while (newchars < nmax && oldchars < omax && newchars < local_prompt_len)
2246 {
2247 #if defined (HANDLE_MULTIBYTE)
2248 newind = _rl_find_next_mbchar (new, newchars, 1, MB_FIND_NONZERO);
2249 oldind = _rl_find_next_mbchar (old, oldchars, 1, MB_FIND_NONZERO);
2250
2251 nls += newind - newchars;
2252 ols += oldind - oldchars;
2253
2254 newchars = newind;
2255 oldchars = oldind;
2256 #else
2257 nls++; ols++;
2258 newchars++; oldchars++;
2259 #endif
2260 }
2261 newwidth = (newchars == local_prompt_len) ? prompt_physical_chars + wrap_offset
2262 : _rl_col_width (new, 0, nls - new, 1);
2263 /* if we changed nls and ols, we need to recompute lendiff */
2264 lendiff = (nls - nfd) - (ols - ofd);
2265
2266 nlsf = new_face + (nls - new);
2267 olsf = old_face + (ols - old);
2268 }
2269 else
2270 newwidth = _rl_col_width (new, nfd - new, nls - new, 1);
2271
2272 oldwidth = _rl_col_width (old, ofd - old, ols - old, 1);
2273
2274 col_lendiff = newwidth - oldwidth;
2275 }
2276 else
2277 col_lendiff = lendiff;
2278
2279 /* col_lendiff uses _rl_col_width(), which doesn't know about whether or not
2280 the multibyte characters it counts are invisible, so unless we're printing
2281 the entire prompt string (in which case we can use prompt_physical_chars)
2282 the count is short by the number of bytes in the invisible multibyte
2283 characters - the number of multibyte characters.
2284
2285 We don't have a good way to solve this without moving to something like
2286 a bitmap that indicates which characters are visible and which are
2287 invisible. We fix it up (imperfectly) in the caller and by trying to use
2288 the entire prompt string wherever we can. */
2289
2290 /* If we are changing the number of invisible characters in a line, and
2291 the spot of first difference is before the end of the invisible chars,
2292 lendiff needs to be adjusted. */
2293 if (current_line == 0 && current_invis_chars != visible_wrap_offset)
2294 {
2295 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2296 {
2297 lendiff += visible_wrap_offset - current_invis_chars;
2298 col_lendiff += visible_wrap_offset - current_invis_chars;
2299 }
2300 else
2301 {
2302 lendiff += visible_wrap_offset - current_invis_chars;
2303 col_lendiff = lendiff;
2304 }
2305 }
2306
2307 /* We use temp as a count of the number of bytes from the first difference
2308 to the end of the new line. col_temp is the corresponding number of
2309 screen columns. A `dumb' update moves to the spot of first difference
2310 and writes TEMP bytes. */
2311 /* Insert (diff (len (old), len (new)) ch. */
2312 temp = ne - nfd;
2313 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2314 col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
2315 else
2316 col_temp = temp;
2317
2318 /* how many bytes from the new line buffer to write to the display */
2319 bytes_to_insert = nls - nfd;
2320
2321 /* col_lendiff > 0 if we are adding characters to the line */
2322 if (col_lendiff > 0) /* XXX - was lendiff */
2323 {
2324 /* Non-zero if we're increasing the number of lines. */
2325 int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
2326
2327 /* If col_lendiff is > 0, implying that the new string takes up more
2328 screen real estate than the old, but lendiff is < 0, meaning that it
2329 takes fewer bytes, we need to just output the characters starting
2330 from the first difference. These will overwrite what is on the
2331 display, so there's no reason to do a smart update. This can really
2332 only happen in a multibyte environment. */
2333 if (lendiff < 0)
2334 {
2335 puts_face (nfd, nfdf, temp);
2336 _rl_last_c_pos += col_temp;
2337 /* If nfd begins before any invisible characters in the prompt,
2338 adjust _rl_last_c_pos to account for wrap_offset and set
2339 cpos_adjusted to let the caller know. */
2340 if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2341 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2342 return;
2343 }
2344 /* Sometimes it is cheaper to print the characters rather than
2345 use the terminal's capabilities. If we're growing the number
2346 of lines, make sure we actually cause the new line to wrap
2347 around on auto-wrapping terminals. */
2348 else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
2349 {
2350 /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
2351 _rl_horizontal_scroll_mode == 1, inserting the characters with
2352 _rl_term_IC or _rl_term_ic will screw up the screen because of the
2353 invisible characters. We need to just draw them. */
2354 /* The same thing happens if we're trying to draw before the last
2355 invisible character in the prompt string or we're increasing the
2356 number of invisible characters in the line and we're not drawing
2357 the entire prompt string. */
2358 if (*ols && ((_rl_horizontal_scroll_mode &&
2359 _rl_last_c_pos == 0 &&
2360 lendiff > prompt_visible_length &&
2361 current_invis_chars > 0) == 0) &&
2362 (((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2363 current_line == 0 && wrap_offset &&
2364 ((nfd - new) <= prompt_last_invisible) &&
2365 (col_lendiff < prompt_visible_length)) == 0) &&
2366 (visible_wrap_offset >= current_invis_chars))
2367 {
2368 open_some_spaces (col_lendiff);
2369 puts_face (nfd, nfdf, bytes_to_insert);
2370 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2371 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2372 else
2373 _rl_last_c_pos += bytes_to_insert;
2374 }
2375 else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
2376 {
2377 /* At the end of a line the characters do not have to
2378 be "inserted". They can just be placed on the screen. */
2379 puts_face (nfd, nfdf, temp);
2380 _rl_last_c_pos += col_temp;
2381 return;
2382 }
2383 else /* just write from first difference to end of new line */
2384 {
2385 puts_face (nfd, nfdf, temp);
2386 _rl_last_c_pos += col_temp;
2387 /* If nfd begins before the last invisible character in the
2388 prompt, adjust _rl_last_c_pos to account for wrap_offset
2389 and set cpos_adjusted to let the caller know. */
2390 if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2391 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2392 return;
2393 }
2394
2395 if (bytes_to_insert > lendiff)
2396 {
2397 /* If nfd begins before the last invisible character in the
2398 prompt, adjust _rl_last_c_pos to account for wrap_offset
2399 and set cpos_adjusted to let the caller know. */
2400 if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
2401 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2402 }
2403 }
2404 else
2405 {
2406 /* cannot insert chars, write to EOL */
2407 puts_face (nfd, nfdf, temp);
2408 _rl_last_c_pos += col_temp;
2409 /* If we're in a multibyte locale and were before the last invisible
2410 char in the current line (which implies we just output some invisible
2411 characters) we need to adjust _rl_last_c_pos, since it represents
2412 a physical character position. */
2413 /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a
2414 crude attempt to compute how far into the new line buffer we are.
2415 It doesn't work well in the face of multibyte characters and needs
2416 to be rethought. XXX */
2417 if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
2418 current_line == prompt_last_screen_line && wrap_offset &&
2419 displaying_prompt_first_line &&
2420 wrap_offset != prompt_invis_chars_first_line &&
2421 ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
2422 ADJUST_CPOS (wrap_offset - prompt_invis_chars_first_line);
2423
2424 /* XXX - what happens if wrap_offset == prompt_invis_chars_first_line
2425 and we are drawing the first line (current_line == 0)? We should
2426 adjust by _rl_last_c_pos -= prompt_invis_chars_first_line */
2427 }
2428 }
2429 else /* Delete characters from line. */
2430 {
2431 /* If possible and inexpensive to use terminal deletion, then do so. */
2432 if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
2433 {
2434 /* If all we're doing is erasing the invisible characters in the
2435 prompt string, don't bother. It screws up the assumptions
2436 about what's on the screen. */
2437 if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
2438 displaying_prompt_first_line &&
2439 -lendiff == visible_wrap_offset)
2440 col_lendiff = 0;
2441
2442 /* If we have moved lmargin and we're shrinking the line, we've
2443 already moved the cursor to the first character of the new line,
2444 so deleting -col_lendiff characters will mess up the cursor
2445 position calculation */
2446 if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
2447 col_lendiff && _rl_last_c_pos < -col_lendiff)
2448 col_lendiff = 0;
2449
2450 if (col_lendiff)
2451 delete_chars (-col_lendiff); /* delete (diff) characters */
2452
2453 /* Copy (new) chars to screen from first diff to last match,
2454 overwriting what is there. */
2455 if (bytes_to_insert > 0)
2456 {
2457 /* If nfd begins at the prompt, or before the invisible
2458 characters in the prompt, we need to adjust _rl_last_c_pos
2459 in a multibyte locale to account for the wrap offset and
2460 set cpos_adjusted accordingly. */
2461 puts_face (nfd, nfdf, bytes_to_insert);
2462 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2463 {
2464 /* This still doesn't take into account whether or not the
2465 characters that this counts are invisible. */
2466 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
2467 if (current_line == 0 && wrap_offset &&
2468 displaying_prompt_first_line &&
2469 prompt_invis_chars_first_line &&
2470 _rl_last_c_pos >= prompt_invis_chars_first_line &&
2471 ((nfd - new) <= prompt_last_invisible))
2472 ADJUST_CPOS (prompt_invis_chars_first_line);
2473
2474 #if 1
2475 #ifdef HANDLE_MULTIBYTE
2476 /* If we write a non-space into the last screen column,
2477 remove the note that we added a space to compensate for
2478 a multibyte double-width character that didn't fit, since
2479 it's only valid for what was previously there. */
2480 /* XXX - watch this */
2481 if (_rl_last_c_pos == _rl_screenwidth &&
2482 line_state_invisible->wrapped_line[current_line+1] &&
2483 nfd[bytes_to_insert-1] != ' ')
2484 line_state_invisible->wrapped_line[current_line+1] = 0;
2485 #endif
2486 #endif
2487 }
2488 else
2489 _rl_last_c_pos += bytes_to_insert;
2490
2491 /* XXX - we only want to do this if we are at the end of the line
2492 so we move there with _rl_move_cursor_relative */
2493 if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
2494 {
2495 _rl_move_cursor_relative (ne-new, new, new_face);
2496 goto clear_rest_of_line;
2497 }
2498 }
2499 }
2500 /* Otherwise, print over the existing material. */
2501 else
2502 {
2503 if (temp > 0)
2504 {
2505 /* If nfd begins at the prompt, or before the invisible
2506 characters in the prompt, we need to adjust _rl_last_c_pos
2507 in a multibyte locale to account for the wrap offset and
2508 set cpos_adjusted accordingly. */
2509 puts_face (nfd, nfdf, temp);
2510 _rl_last_c_pos += col_temp; /* XXX */
2511 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2512 {
2513 if (current_line == 0 && wrap_offset &&
2514 displaying_prompt_first_line &&
2515 _rl_last_c_pos > wrap_offset &&
2516 ((nfd - new) <= prompt_last_invisible))
2517 ADJUST_CPOS (wrap_offset); /* XXX - prompt_invis_chars_first_line? */
2518 }
2519 }
2520 clear_rest_of_line:
2521 lendiff = (oe - old) - (ne - new);
2522 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2523 col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
2524 else
2525 col_lendiff = lendiff;
2526
2527 /* If we've already printed over the entire width of the screen,
2528 including the old material, then col_lendiff doesn't matter and
2529 space_to_eol will insert too many spaces. XXX - maybe we should
2530 adjust col_lendiff based on the difference between _rl_last_c_pos
2531 and _rl_screenwidth */
2532 if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
2533 {
2534 if (_rl_term_autowrap && current_line < inv_botlin)
2535 space_to_eol (col_lendiff);
2536 else
2537 _rl_clear_to_eol (col_lendiff);
2538 }
2539 }
2540 }
2541 }
2542
2543 /* Tell the update routines that we have moved onto a new (empty) line. */
2544 int
2545 rl_on_new_line (void)
2546 {
2547 if (visible_line)
2548 visible_line[0] = '\0';
2549
2550 _rl_last_c_pos = _rl_last_v_pos = 0;
2551 _rl_vis_botlin = last_lmargin = 0;
2552 if (vis_lbreaks)
2553 vis_lbreaks[0] = vis_lbreaks[1] = 0;
2554 visible_wrap_offset = 0;
2555 return 0;
2556 }
2557
2558 /* Clear all screen lines occupied by the current readline line buffer
2559 (visible line) */
2560 int
2561 rl_clear_visible_line (void)
2562 {
2563 int curr_line;
2564
2565 /* Make sure we move to column 0 so we clear the entire line */
2566 _rl_cr ();
2567 _rl_last_c_pos = 0;
2568
2569 /* Move to the last screen line of the current visible line */
2570 _rl_move_vert (_rl_vis_botlin);
2571
2572 /* And erase screen lines going up to line 0 (first visible line) */
2573 for (curr_line = _rl_last_v_pos; curr_line >= 0; curr_line--)
2574 {
2575 _rl_move_vert (curr_line);
2576 _rl_clear_to_eol (0);
2577 }
2578
2579 return 0;
2580 }
2581
2582 /* Tell the update routines that we have moved onto a new line with the
2583 prompt already displayed. Code originally from the version of readline
2584 distributed with CLISP. rl_expand_prompt must have already been called
2585 (explicitly or implicitly). This still doesn't work exactly right; it
2586 should use expand_prompt() */
2587 int
2588 rl_on_new_line_with_prompt (void)
2589 {
2590 int prompt_size, i, l, real_screenwidth, newlines;
2591 char *prompt_last_line, *lprompt;
2592
2593 /* Initialize visible_line and invisible_line to ensure that they can hold
2594 the already-displayed prompt. */
2595 prompt_size = strlen (rl_prompt) + 1;
2596 init_line_structures (prompt_size);
2597
2598 /* Make sure the line structures hold the already-displayed prompt for
2599 redisplay. */
2600 lprompt = local_prompt ? local_prompt : rl_prompt;
2601 strcpy (visible_line, lprompt);
2602 strcpy (invisible_line, lprompt);
2603
2604 /* If the prompt contains newlines, take the last tail. */
2605 prompt_last_line = strrchr (rl_prompt, '\n');
2606 if (!prompt_last_line)
2607 prompt_last_line = rl_prompt;
2608
2609 l = strlen (prompt_last_line);
2610 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2611 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */
2612 else
2613 _rl_last_c_pos = l;
2614
2615 /* Dissect prompt_last_line into screen lines. Note that here we have
2616 to use the real screenwidth. Readline's notion of screenwidth might be
2617 one less, see terminal.c. */
2618 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
2619 _rl_last_v_pos = l / real_screenwidth;
2620 /* If the prompt length is a multiple of real_screenwidth, we don't know
2621 whether the cursor is at the end of the last line, or already at the
2622 beginning of the next line. Output a newline just to be safe. */
2623 if (l > 0 && (l % real_screenwidth) == 0)
2624 _rl_output_some_chars ("\n", 1);
2625 last_lmargin = 0;
2626
2627 newlines = 0; i = 0;
2628 while (i <= l)
2629 {
2630 _rl_vis_botlin = newlines;
2631 vis_lbreaks[newlines++] = i;
2632 i += real_screenwidth;
2633 }
2634 vis_lbreaks[newlines] = l;
2635 visible_wrap_offset = 0;
2636
2637 rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
2638
2639 return 0;
2640 }
2641
2642 /* Actually update the display, period. */
2643 int
2644 rl_forced_update_display (void)
2645 {
2646 register char *temp;
2647
2648 if (visible_line)
2649 {
2650 temp = visible_line;
2651 while (*temp)
2652 *temp++ = '\0';
2653 }
2654 rl_on_new_line ();
2655 forced_display++;
2656 (*rl_redisplay_function) ();
2657 return 0;
2658 }
2659
2660 /* Redraw only the last line of a multi-line prompt. */
2661 void
2662 rl_redraw_prompt_last_line (void)
2663 {
2664 char *t;
2665
2666 t = strrchr (rl_display_prompt, '\n');
2667 if (t)
2668 redraw_prompt (++t);
2669 else
2670 rl_forced_update_display ();
2671 }
2672
2673 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
2674 (Well, when we don't have multibyte characters, _rl_last_c_pos is a
2675 buffer index.)
2676 DATA is the contents of the screen line of interest; i.e., where
2677 the movement is being done.
2678 DATA is always the visible line or the invisible line */
2679 static void
2680 _rl_move_cursor_relative (int new, const char *data, const char *dataf)
2681 {
2682 register int i;
2683 int woff; /* number of invisible chars on current line */
2684 int cpos, dpos; /* current and desired cursor positions */
2685 int adjust;
2686 int in_invisline;
2687 int mb_cur_max = MB_CUR_MAX;
2688
2689 woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
2690 cpos = _rl_last_c_pos;
2691
2692 if (cpos == 0 && cpos == new)
2693 return;
2694
2695 #if defined (HANDLE_MULTIBYTE)
2696 /* If we have multibyte characters, NEW is indexed by the buffer point in
2697 a multibyte string, but _rl_last_c_pos is the display position. In
2698 this case, NEW's display position is not obvious and must be
2699 calculated. We need to account for invisible characters in this line,
2700 as long as we are past them and they are counted by _rl_col_width. */
2701 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2702 {
2703 adjust = 1;
2704 /* Try to short-circuit common cases and eliminate a bunch of multibyte
2705 character function calls. */
2706 /* 1. prompt string */
2707 if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2708 {
2709 dpos = prompt_physical_chars;
2710 cpos_adjusted = 1;
2711 adjust = 0;
2712 }
2713 /* 2. prompt_string + line contents */
2714 else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2715 {
2716 dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2717 cpos_adjusted = 1;
2718 adjust = 0;
2719 }
2720 else
2721 dpos = _rl_col_width (data, 0, new, 1);
2722
2723 if (displaying_prompt_first_line == 0)
2724 adjust = 0;
2725
2726 /* yet another special case: printing the last line of a prompt with
2727 multibyte characters and invisible characters whose printable length
2728 exceeds the screen width with the last invisible character
2729 (prompt_last_invisible) in the last line. IN_INVISLINE is the
2730 offset of DATA in invisible_line */
2731 in_invisline = 0;
2732 if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
2733 in_invisline = data - invisible_line;
2734
2735 /* Use NEW when comparing against the last invisible character in the
2736 prompt string, since they're both buffer indices and DPOS is a
2737 desired display position. */
2738 /* NEW is relative to the current displayed line, while
2739 PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line.
2740 Need a way to reconcile these two variables by turning NEW into a
2741 buffer position relative to the start of the line */
2742 if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */
2743 (new+in_invisline > prompt_last_invisible) || /* invisible line */
2744 (prompt_physical_chars >= _rl_screenwidth && /* visible line */
2745 _rl_last_v_pos == prompt_last_screen_line &&
2746 wrap_offset >= woff && dpos >= woff &&
2747 new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset))))
2748 /* XXX last comparison might need to be >= */
2749 {
2750 dpos -= woff;
2751 /* Since this will be assigned to _rl_last_c_pos at the end (more
2752 precisely, _rl_last_c_pos == dpos when this function returns),
2753 let the caller know. */
2754 cpos_adjusted = 1;
2755 }
2756 }
2757 else
2758 #endif
2759 dpos = new;
2760
2761 /* If we don't have to do anything, then return. */
2762 if (cpos == dpos)
2763 return;
2764
2765 /* It may be faster to output a CR, and then move forwards instead
2766 of moving backwards. */
2767 /* i == current physical cursor position. */
2768 #if defined (HANDLE_MULTIBYTE)
2769 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2770 i = _rl_last_c_pos;
2771 else
2772 #endif
2773 i = _rl_last_c_pos - woff;
2774 if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
2775 (_rl_term_autowrap && i == _rl_screenwidth))
2776 {
2777 _rl_cr ();
2778 cpos = _rl_last_c_pos = 0;
2779 }
2780
2781 if (cpos < dpos)
2782 {
2783 /* Move the cursor forward. We do it by printing the command
2784 to move the cursor forward if there is one, else print that
2785 portion of the output buffer again. Which is cheaper? */
2786
2787 /* The above comment is left here for posterity. It is faster
2788 to print one character (non-control) than to print a control
2789 sequence telling the terminal to move forward one character.
2790 That kind of control is for people who don't know what the
2791 data is underneath the cursor. */
2792
2793 /* However, we need a handle on where the current display position is
2794 in the buffer for the immediately preceding comment to be true.
2795 In multibyte locales, we don't currently have that info available.
2796 Without it, we don't know where the data we have to display begins
2797 in the buffer and we have to go back to the beginning of the screen
2798 line. In this case, we can use the terminal sequence to move forward
2799 if it's available. */
2800 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2801 {
2802 if (_rl_term_forward_char)
2803 {
2804 for (i = cpos; i < dpos; i++)
2805 tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2806 }
2807 else
2808 {
2809 _rl_cr ();
2810 puts_face (data, dataf, new);
2811 }
2812 }
2813 else
2814 puts_face (data + cpos, dataf + cpos, new - cpos);
2815 }
2816
2817 #if defined (HANDLE_MULTIBYTE)
2818 /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2819 The byte length of the string is probably bigger than the column width
2820 of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2821 display point is less than _rl_last_c_pos. */
2822 #endif
2823 else if (cpos > dpos)
2824 _rl_backspace (cpos - dpos);
2825
2826 _rl_last_c_pos = dpos;
2827 }
2828
2829 /* PWP: move the cursor up or down. */
2830 void
2831 _rl_move_vert (int to)
2832 {
2833 register int delta, i;
2834
2835 if (_rl_last_v_pos == to || to > _rl_screenheight)
2836 return;
2837
2838 if ((delta = to - _rl_last_v_pos) > 0)
2839 {
2840 for (i = 0; i < delta; i++)
2841 putc ('\n', rl_outstream);
2842 _rl_cr ();
2843 _rl_last_c_pos = 0;
2844 }
2845 else
2846 { /* delta < 0 */
2847 #ifdef __DJGPP__
2848 int row, col;
2849
2850 fflush (rl_outstream);
2851 ScreenGetCursor (&row, &col);
2852 ScreenSetCursor (row + delta, col);
2853 i = -delta;
2854 #else
2855 if (_rl_term_up && *_rl_term_up)
2856 for (i = 0; i < -delta; i++)
2857 tputs (_rl_term_up, 1, _rl_output_character_function);
2858 #endif /* !__DJGPP__ */
2859 }
2860
2861 _rl_last_v_pos = to; /* Now TO is here */
2862 }
2863
2864 /* Physically print C on rl_outstream. This is for functions which know
2865 how to optimize the display. Return the number of characters output. */
2866 int
2867 rl_show_char (int c)
2868 {
2869 int n = 1;
2870 if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2871 {
2872 fprintf (rl_outstream, "M-");
2873 n += 2;
2874 c = UNMETA (c);
2875 }
2876
2877 #if defined (DISPLAY_TABS)
2878 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
2879 #else
2880 if (CTRL_CHAR (c) || c == RUBOUT)
2881 #endif /* !DISPLAY_TABS */
2882 {
2883 fprintf (rl_outstream, "C-");
2884 n += 2;
2885 c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
2886 }
2887
2888 putc (c, rl_outstream);
2889 fflush (rl_outstream);
2890 return n;
2891 }
2892
2893 int
2894 rl_character_len (int c, int pos)
2895 {
2896 unsigned char uc;
2897
2898 uc = (unsigned char)c;
2899
2900 if (META_CHAR (uc))
2901 return ((_rl_output_meta_chars == 0) ? 4 : 1);
2902
2903 if (uc == '\t')
2904 {
2905 #if defined (DISPLAY_TABS)
2906 return (((pos | 7) + 1) - pos);
2907 #else
2908 return (2);
2909 #endif /* !DISPLAY_TABS */
2910 }
2911
2912 if (CTRL_CHAR (c) || c == RUBOUT)
2913 return (2);
2914
2915 return ((ISPRINT (uc)) ? 1 : 2);
2916 }
2917 /* How to print things in the "echo-area". The prompt is treated as a
2918 mini-modeline. */
2919 static int msg_saved_prompt = 0;
2920
2921 #if defined (USE_VARARGS)
2922 int
2923 #if defined (PREFER_STDARG)
2924 rl_message (const char *format, ...)
2925 #else
2926 rl_message (va_alist)
2927 va_dcl
2928 #endif
2929 {
2930 va_list args;
2931 #if defined (PREFER_VARARGS)
2932 char *format;
2933 #endif
2934 #if defined (HAVE_VSNPRINTF)
2935 int bneed;
2936 #endif
2937
2938 #if defined (PREFER_STDARG)
2939 va_start (args, format);
2940 #else
2941 va_start (args);
2942 format = va_arg (args, char *);
2943 #endif
2944
2945 if (msg_buf == 0)
2946 msg_buf = xmalloc (msg_bufsiz = 128);
2947
2948 #if defined (HAVE_VSNPRINTF)
2949 bneed = vsnprintf (msg_buf, msg_bufsiz, format, args);
2950 if (bneed >= msg_bufsiz - 1)
2951 {
2952 msg_bufsiz = bneed + 1;
2953 msg_buf = xrealloc (msg_buf, msg_bufsiz);
2954 va_end (args);
2955
2956 #if defined (PREFER_STDARG)
2957 va_start (args, format);
2958 #else
2959 va_start (args);
2960 format = va_arg (args, char *);
2961 #endif
2962 vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2963 }
2964 #else
2965 vsprintf (msg_buf, format, args);
2966 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2967 #endif
2968 va_end (args);
2969
2970 if (saved_local_prompt == 0)
2971 {
2972 rl_save_prompt ();
2973 msg_saved_prompt = 1;
2974 }
2975 else if (local_prompt != saved_local_prompt)
2976 {
2977 FREE (local_prompt);
2978 FREE (local_prompt_prefix);
2979 local_prompt = (char *)NULL;
2980 }
2981 rl_display_prompt = msg_buf;
2982 local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
2983 &prompt_last_invisible,
2984 &prompt_invis_chars_first_line,
2985 &prompt_physical_chars);
2986 local_prompt_prefix = (char *)NULL;
2987 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2988 (*rl_redisplay_function) ();
2989
2990 return 0;
2991 }
2992 #else /* !USE_VARARGS */
2993 int
2994 rl_message (format, arg1, arg2)
2995 char *format;
2996 {
2997 if (msg_buf == 0)
2998 msg_buf = xmalloc (msg_bufsiz = 128);
2999
3000 sprintf (msg_buf, format, arg1, arg2);
3001 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
3002
3003 rl_display_prompt = msg_buf;
3004 if (saved_local_prompt == 0)
3005 {
3006 rl_save_prompt ();
3007 msg_saved_prompt = 1;
3008 }
3009 else if (local_prompt != saved_local_prompt)
3010 {
3011 FREE (local_prompt);
3012 FREE (local_prompt_prefix);
3013 local_prompt = (char *)NULL;
3014 }
3015 local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
3016 &prompt_last_invisible,
3017 &prompt_invis_chars_first_line,
3018 &prompt_physical_chars);
3019 local_prompt_prefix = (char *)NULL;
3020 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
3021 (*rl_redisplay_function) ();
3022
3023 return 0;
3024 }
3025 #endif /* !USE_VARARGS */
3026
3027 /* How to clear things from the "echo-area". */
3028 int
3029 rl_clear_message (void)
3030 {
3031 rl_display_prompt = rl_prompt;
3032 if (msg_saved_prompt)
3033 {
3034 rl_restore_prompt ();
3035 msg_saved_prompt = 0;
3036 }
3037 (*rl_redisplay_function) ();
3038 return 0;
3039 }
3040
3041 int
3042 rl_reset_line_state (void)
3043 {
3044 rl_on_new_line ();
3045
3046 rl_display_prompt = rl_prompt ? rl_prompt : "";
3047 forced_display = 1;
3048 return 0;
3049 }
3050
3051 /* Save all of the variables associated with the prompt and its display. Most
3052 of the complexity is dealing with the invisible characters in the prompt
3053 string and where they are. There are enough of these that I should consider
3054 a struct. */
3055 void
3056 rl_save_prompt (void)
3057 {
3058 saved_local_prompt = local_prompt;
3059 saved_local_prefix = local_prompt_prefix;
3060 saved_prefix_length = prompt_prefix_length;
3061 saved_local_length = local_prompt_len;
3062 saved_last_invisible = prompt_last_invisible;
3063 saved_visible_length = prompt_visible_length;
3064 saved_invis_chars_first_line = prompt_invis_chars_first_line;
3065 saved_physical_chars = prompt_physical_chars;
3066 saved_local_prompt_newlines = local_prompt_newlines;
3067
3068 local_prompt = local_prompt_prefix = (char *)0;
3069 local_prompt_len = 0;
3070 local_prompt_newlines = (int *)0;
3071
3072 prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
3073 prompt_invis_chars_first_line = prompt_physical_chars = 0;
3074 }
3075
3076 void
3077 rl_restore_prompt (void)
3078 {
3079 FREE (local_prompt);
3080 FREE (local_prompt_prefix);
3081 FREE (local_prompt_newlines);
3082
3083 local_prompt = saved_local_prompt;
3084 local_prompt_prefix = saved_local_prefix;
3085 local_prompt_len = saved_local_length;
3086 local_prompt_newlines = saved_local_prompt_newlines;
3087
3088 prompt_prefix_length = saved_prefix_length;
3089 prompt_last_invisible = saved_last_invisible;
3090 prompt_visible_length = saved_visible_length;
3091 prompt_invis_chars_first_line = saved_invis_chars_first_line;
3092 prompt_physical_chars = saved_physical_chars;
3093
3094 /* can test saved_local_prompt to see if prompt info has been saved. */
3095 saved_local_prompt = saved_local_prefix = (char *)0;
3096 saved_local_length = 0;
3097 saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
3098 saved_invis_chars_first_line = saved_physical_chars = 0;
3099 saved_local_prompt_newlines = 0;
3100 }
3101
3102 char *
3103 _rl_make_prompt_for_search (int pchar)
3104 {
3105 int len;
3106 char *pmt, *p;
3107
3108 rl_save_prompt ();
3109
3110 /* We've saved the prompt, and can do anything with the various prompt
3111 strings we need before they're restored. We want the unexpanded
3112 portion of the prompt string after any final newline. */
3113 p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
3114 if (p == 0)
3115 {
3116 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
3117 pmt = (char *)xmalloc (len + 2);
3118 if (len)
3119 strcpy (pmt, rl_prompt);
3120 pmt[len] = pchar;
3121 pmt[len+1] = '\0';
3122 }
3123 else
3124 {
3125 p++;
3126 len = strlen (p);
3127 pmt = (char *)xmalloc (len + 2);
3128 if (len)
3129 strcpy (pmt, p);
3130 pmt[len] = pchar;
3131 pmt[len+1] = '\0';
3132 }
3133
3134 /* will be overwritten by expand_prompt, called from rl_message */
3135 prompt_physical_chars = saved_physical_chars + 1;
3136 return pmt;
3137 }
3138
3139 /* Quick redisplay hack when erasing characters at the end of the line. */
3140 void
3141 _rl_erase_at_end_of_line (int l)
3142 {
3143 register int i;
3144
3145 _rl_backspace (l);
3146 for (i = 0; i < l; i++)
3147 putc (' ', rl_outstream);
3148 _rl_backspace (l);
3149 for (i = 0; i < l; i++)
3150 visible_line[--_rl_last_c_pos] = '\0';
3151 rl_display_fixed++;
3152 }
3153
3154 /* Clear to the end of the line. COUNT is the minimum
3155 number of character spaces to clear, but we use a terminal escape
3156 sequence if available. */
3157 void
3158 _rl_clear_to_eol (int count)
3159 {
3160 #ifndef __MSDOS__
3161 if (_rl_term_clreol)
3162 tputs (_rl_term_clreol, 1, _rl_output_character_function);
3163 else
3164 #endif
3165 if (count)
3166 space_to_eol (count);
3167 }
3168
3169 /* Clear to the end of the line using spaces. COUNT is the minimum
3170 number of character spaces to clear, */
3171 static void
3172 space_to_eol (int count)
3173 {
3174 register int i;
3175
3176 for (i = 0; i < count; i++)
3177 putc (' ', rl_outstream);
3178
3179 _rl_last_c_pos += count;
3180 }
3181
3182 void
3183 _rl_clear_screen (int clrscr)
3184 {
3185 #if defined (__DJGPP__)
3186 ScreenClear ();
3187 ScreenSetCursor (0, 0);
3188 #else
3189 if (_rl_term_clrpag)
3190 {
3191 tputs (_rl_term_clrpag, 1, _rl_output_character_function);
3192 if (clrscr && _rl_term_clrscroll)
3193 tputs (_rl_term_clrscroll, 1, _rl_output_character_function);
3194 }
3195 else
3196 rl_crlf ();
3197 #endif /* __DJGPP__ */
3198 }
3199
3200 /* Insert COUNT characters from STRING to the output stream at column COL. */
3201 static void
3202 insert_some_chars (char *string, int count, int col)
3203 {
3204 open_some_spaces (col);
3205 _rl_output_some_chars (string, count);
3206 }
3207
3208 /* Insert COL spaces, keeping the cursor at the same position. We follow the
3209 ncurses documentation and use either im/ei with explicit spaces, or IC/ic
3210 by itself. We assume there will either be ei or we don't need to use it. */
3211 static void
3212 open_some_spaces (int col)
3213 {
3214 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
3215 char *buffer;
3216 register int i;
3217
3218 /* If IC is defined, then we do not have to "enter" insert mode. */
3219 if (_rl_term_IC)
3220 {
3221 buffer = tgoto (_rl_term_IC, 0, col);
3222 tputs (buffer, 1, _rl_output_character_function);
3223 }
3224 else if (_rl_term_im && *_rl_term_im)
3225 {
3226 tputs (_rl_term_im, 1, _rl_output_character_function);
3227 /* just output the desired number of spaces */
3228 for (i = col; i--; )
3229 _rl_output_character_function (' ');
3230 /* If there is a string to turn off insert mode, use it now. */
3231 if (_rl_term_ei && *_rl_term_ei)
3232 tputs (_rl_term_ei, 1, _rl_output_character_function);
3233 /* and move back the right number of spaces */
3234 _rl_backspace (col);
3235 }
3236 else if (_rl_term_ic && *_rl_term_ic)
3237 {
3238 /* If there is a special command for inserting characters, then
3239 use that first to open up the space. */
3240 for (i = col; i--; )
3241 tputs (_rl_term_ic, 1, _rl_output_character_function);
3242 }
3243 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
3244 }
3245
3246 /* Delete COUNT characters from the display line. */
3247 static void
3248 delete_chars (int count)
3249 {
3250 if (count > _rl_screenwidth) /* XXX */
3251 return;
3252
3253 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
3254 if (_rl_term_DC && *_rl_term_DC)
3255 {
3256 char *buffer;
3257 buffer = tgoto (_rl_term_DC, count, count);
3258 tputs (buffer, count, _rl_output_character_function);
3259 }
3260 else
3261 {
3262 if (_rl_term_dc && *_rl_term_dc)
3263 while (count--)
3264 tputs (_rl_term_dc, 1, _rl_output_character_function);
3265 }
3266 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
3267 }
3268
3269 void
3270 _rl_update_final (void)
3271 {
3272 int full_lines, woff, botline_length;
3273
3274 if (line_structures_initialized == 0)
3275 return;
3276
3277 full_lines = 0;
3278 /* If the cursor is the only thing on an otherwise-blank last line,
3279 compensate so we don't print an extra CRLF. */
3280 if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
3281 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
3282 {
3283 _rl_vis_botlin--;
3284 full_lines = 1;
3285 }
3286 _rl_move_vert (_rl_vis_botlin);
3287 woff = W_OFFSET(_rl_vis_botlin, wrap_offset);
3288 botline_length = VIS_LLEN(_rl_vis_botlin) - woff;
3289 /* If we've wrapped lines, remove the final xterm line-wrap flag. */
3290 if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth)
3291 {
3292 char *last_line, *last_face;
3293
3294 /* LAST_LINE includes invisible characters, so if you want to get the
3295 last character of the first line, you have to take WOFF into account.
3296 This needs to be done for both calls to _rl_move_cursor_relative,
3297 which takes a buffer position as the first argument, and any direct
3298 subscripts of LAST_LINE. */
3299 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
3300 last_face = &vis_face[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */
3301 cpos_buffer_position = -1; /* don't know where we are in buffer */
3302 _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line, last_face); /* XXX */
3303 _rl_clear_to_eol (0);
3304 puts_face (&last_line[_rl_screenwidth - 1 + woff],
3305 &last_face[_rl_screenwidth - 1 + woff], 1);
3306 }
3307 _rl_vis_botlin = 0;
3308 if (botline_length > 0 || _rl_last_c_pos > 0)
3309 rl_crlf ();
3310 fflush (rl_outstream);
3311 rl_display_fixed++;
3312 }
3313
3314 /* Move to the start of the current line. */
3315 static void
3316 cr (void)
3317 {
3318 _rl_cr ();
3319 _rl_last_c_pos = 0;
3320 }
3321
3322 /* Redraw the last line of a multi-line prompt that may possibly contain
3323 terminal escape sequences. Called with the cursor at column 0 of the
3324 line to draw the prompt on. */
3325 static void
3326 redraw_prompt (char *t)
3327 {
3328 char *oldp;
3329
3330 oldp = rl_display_prompt;
3331 rl_save_prompt ();
3332
3333 rl_display_prompt = t;
3334 local_prompt = expand_prompt (t, PMT_MULTILINE,
3335 &prompt_visible_length,
3336 &prompt_last_invisible,
3337 &prompt_invis_chars_first_line,
3338 &prompt_physical_chars);
3339 local_prompt_prefix = (char *)NULL;
3340 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
3341
3342 rl_forced_update_display ();
3343
3344 rl_display_prompt = oldp;
3345 rl_restore_prompt();
3346 }
3347
3348 /* Redisplay the current line after a SIGWINCH is received. */
3349 void
3350 _rl_redisplay_after_sigwinch (void)
3351 {
3352 char *t;
3353
3354 /* Clear the last line (assuming that the screen size change will result in
3355 either more or fewer characters on that line only) and put the cursor at
3356 column 0. Make sure the right thing happens if we have wrapped to a new
3357 screen line. */
3358 if (_rl_term_cr)
3359 {
3360 _rl_move_vert (_rl_vis_botlin);
3361
3362 _rl_cr ();
3363 _rl_last_c_pos = 0;
3364
3365 #if !defined (__MSDOS__)
3366 if (_rl_term_clreol)
3367 tputs (_rl_term_clreol, 1, _rl_output_character_function);
3368 else
3369 #endif
3370 {
3371 space_to_eol (_rl_screenwidth);
3372 _rl_cr ();
3373 }
3374
3375 if (_rl_last_v_pos > 0)
3376 _rl_move_vert (0);
3377 }
3378 else
3379 rl_crlf ();
3380
3381 /* Redraw only the last line of a multi-line prompt. */
3382 t = strrchr (rl_display_prompt, '\n');
3383 if (t)
3384 redraw_prompt (++t);
3385 else
3386 rl_forced_update_display ();
3387 }
3388
3389 void
3390 _rl_clean_up_for_exit (void)
3391 {
3392 if (_rl_echoing_p)
3393 {
3394 if (_rl_vis_botlin > 0) /* minor optimization plus bug fix */
3395 _rl_move_vert (_rl_vis_botlin);
3396 _rl_vis_botlin = 0;
3397 fflush (rl_outstream);
3398 rl_restart_output (1, 0);
3399 }
3400 }
3401
3402 void
3403 _rl_erase_entire_line (void)
3404 {
3405 cr ();
3406 _rl_clear_to_eol (0);
3407 cr ();
3408 fflush (rl_outstream);
3409 }
3410
3411 void
3412 _rl_ttyflush (void)
3413 {
3414 fflush (rl_outstream);
3415 }
3416
3417 /* return the `current display line' of the cursor -- the number of lines to
3418 move up to get to the first screen line of the current readline line. */
3419 int
3420 _rl_current_display_line (void)
3421 {
3422 int ret, nleft;
3423
3424 /* Find out whether or not there might be invisible characters in the
3425 editing buffer. */
3426 if (rl_display_prompt == rl_prompt)
3427 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
3428 else
3429 nleft = _rl_last_c_pos - _rl_screenwidth;
3430
3431 if (nleft > 0)
3432 ret = 1 + nleft / _rl_screenwidth;
3433 else
3434 ret = 0;
3435
3436 return ret;
3437 }
3438
3439 void
3440 _rl_refresh_line (void)
3441 {
3442 rl_clear_visible_line ();
3443 rl_redraw_prompt_last_line ();
3444 rl_keep_mark_active ();
3445 }
3446
3447 #if defined (HANDLE_MULTIBYTE)
3448 /* Calculate the number of screen columns occupied by STR from START to END.
3449 In the case of multibyte characters with stateful encoding, we have to
3450 scan from the beginning of the string to take the state into account. */
3451 static int
3452 _rl_col_width (const char *str, int start, int end, int flags)
3453 {
3454 wchar_t wc;
3455 mbstate_t ps;
3456 int tmp, point, width, max;
3457
3458 if (end <= start)
3459 return 0;
3460 if (MB_CUR_MAX == 1 || rl_byte_oriented)
3461 /* this can happen in some cases where it's inconvenient to check */
3462 return (end - start);
3463
3464 memset (&ps, 0, sizeof (mbstate_t));
3465
3466 point = 0;
3467 max = end;
3468
3469 /* Try to short-circuit common cases. The adjustment to remove wrap_offset
3470 is done by the caller. */
3471 /* 1. prompt string */
3472 if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
3473 return (prompt_physical_chars + wrap_offset);
3474 /* 2. prompt string + line contents */
3475 else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
3476 {
3477 tmp = prompt_physical_chars + wrap_offset;
3478 /* XXX - try to call ourselves recursively with non-prompt portion */
3479 tmp += _rl_col_width (str, local_prompt_len, end, flags);
3480 return (tmp);
3481 }
3482
3483 while (point < start)
3484 {
3485 if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3486 {
3487 memset (&ps, 0, sizeof (mbstate_t));
3488 tmp = 1;
3489 }
3490 else
3491 tmp = mbrlen (str + point, max, &ps);
3492 if (MB_INVALIDCH ((size_t)tmp))
3493 {
3494 /* In this case, the bytes are invalid or too short to compose a
3495 multibyte character, so we assume that the first byte represents
3496 a single character. */
3497 point++;
3498 max--;
3499
3500 /* Clear the state of the byte sequence, because in this case the
3501 effect of mbstate is undefined. */
3502 memset (&ps, 0, sizeof (mbstate_t));
3503 }
3504 else if (MB_NULLWCH (tmp))
3505 break; /* Found '\0' */
3506 else
3507 {
3508 point += tmp;
3509 max -= tmp;
3510 }
3511 }
3512
3513 /* If START is not a byte that starts a character, then POINT will be
3514 greater than START. In this case, assume that (POINT - START) gives
3515 a byte count that is the number of columns of difference. */
3516 width = point - start;
3517
3518 while (point < end)
3519 {
3520 if (_rl_utf8locale && UTF8_SINGLEBYTE(str[point]))
3521 {
3522 tmp = 1;
3523 wc = (wchar_t) str[point];
3524 }
3525 else
3526 tmp = mbrtowc (&wc, str + point, max, &ps);
3527 if (MB_INVALIDCH ((size_t)tmp))
3528 {
3529 /* In this case, the bytes are invalid or too short to compose a
3530 multibyte character, so we assume that the first byte represents
3531 a single character. */
3532 point++;
3533 max--;
3534
3535 /* and assume that the byte occupies a single column. */
3536 width++;
3537
3538 /* Clear the state of the byte sequence, because in this case the
3539 effect of mbstate is undefined. */
3540 memset (&ps, 0, sizeof (mbstate_t));
3541 }
3542 else if (MB_NULLWCH (tmp))
3543 break; /* Found '\0' */
3544 else
3545 {
3546 point += tmp;
3547 max -= tmp;
3548 tmp = WCWIDTH(wc);
3549 width += (tmp >= 0) ? tmp : 1;
3550 }
3551 }
3552
3553 width += point - end;
3554
3555 return width;
3556 }
3557 #endif /* HANDLE_MULTIBYTE */
This page took 0.106252 seconds and 4 git commands to generate.