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