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