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