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