]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/display.c
Bash-4.3 patch 11
[thirdparty/bash.git] / lib / readline / display.c
CommitLineData
726f6388
JA
1/* display.c -- readline redisplay facility. */
2
ac50fbac 3/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
726f6388 4
3185942a
JA
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
3185942a
JA
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
3185942a
JA
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
3185942a
JA
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
ac50fbac
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));
ac50fbac 70static void open_some_spaces PARAMS((int));
f73dda09 71static void cr PARAMS((void));
ccc6cda3 72
3185942a
JA
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];
90static int line_structures_initialized = 0;
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)
0001803f 102static int _rl_col_width PARAMS((const char *, int, int, int));
7117c2d2 103#else
0001803f 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
0628567a
JA
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
0628567a
JA
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
3185942a 115 invisible characters. XXX - might need to take `modmark' into account. */
0628567a
JA
116#define PROMPT_ENDING_INDEX \
117 ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
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;
95732b49 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. */
95732b49 162
726f6388 163/* The visible cursor position. If you print some text, adjust this. */
95732b49
JA
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
95732b49 171static int cpos_adjusted;
0628567a 172static int cpos_buffer_position;
ac50fbac 173static int displaying_prompt_first_line;
3185942a 174static int prompt_multibyte_chars;
95732b49 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. */
ac50fbac
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;
0628567a 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
b80f6443
JA
223static int prompt_physical_chars;
224
3185942a
JA
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
95732b49
JA
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;
0628567a 238static int saved_local_length;
95732b49
JA
239static int saved_invis_chars_first_line;
240static int saved_physical_chars;
241
ac50fbac
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
b80f6443
JA
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 *
b80f6443 270expand_prompt (pmt, lp, lip, niflp, vlp)
726f6388 271 char *pmt;
b80f6443 272 int *lp, *lip, *niflp, *vlp;
726f6388 273{
0628567a 274 char *r, *ret, *p, *igstart;
eb873671 275 int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
726f6388
JA
276
277 /* Short-circuit if we can. */
b80f6443 278 if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
726f6388 279 {
ac50fbac
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);
b80f6443
JA
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);
ac50fbac
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 */
eb873671 312 invflset = 0; /* we only want to set invfl once */
28ef6c31 313
0628567a 314 igstart = 0;
ac50fbac 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 */
0628567a 319 if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
726f6388 320 {
0628567a
JA
321 ignoring = 1;
322 igstart = p;
726f6388
JA
323 continue;
324 }
325 else if (ignoring && *p == RL_PROMPT_END_IGNORE)
326 {
327 ignoring = 0;
0628567a 328 if (p != (igstart + 1))
95732b49 329 last = r - ret - 1;
726f6388
JA
330 continue;
331 }
332 else
333 {
b80f6443
JA
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)
eb873671 343 {
3185942a
JA
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 */
eb873671 349 rl += ind - pind;
0001803f 350 physchars += _rl_col_width (pmt, pind, ind, 0);
eb873671 351 }
b80f6443
JA
352 else
353 ninvis += ind - pind;
354 p--; /* compensate for later increment */
355 }
28ef6c31 356 else
b80f6443
JA
357#endif
358 {
359 *r++ = *p;
360 if (!ignoring)
eb873671
JA
361 {
362 rl++; /* visible length byte counter */
363 physchars++;
364 }
b80f6443
JA
365 else
366 ninvis++; /* invisible chars byte counter */
367 }
368
eb873671
JA
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;
b80f6443
JA
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
b80f6443 400 ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
bb70624e
JA
401 return ret;
402}
403
ac50fbac
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;
0628567a 439 local_prompt_len = 0;
95732b49
JA
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,
b80f6443
JA
452 &prompt_invis_chars_first_line,
453 &prompt_physical_chars);
726f6388 454 local_prompt_prefix = (char *)0;
0628567a 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,
f1be666c 464 &prompt_invis_chars_first_line,
eb873671 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,
f1be666c 471 (int *)NULL,
eb873671 472 (int *)NULL);
726f6388 473 *t = c;
0628567a 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;
3185942a 516
7117c2d2 517#if defined (HANDLE_MULTIBYTE)
3185942a
JA
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
3185942a
JA
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 }
3185942a
JA
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;
0628567a 539 int inv_botlin, lb_botlin, lb_linenum, o_cpos;
3185942a 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
3185942a 550 if (_rl_echoing_p == 0)
726f6388
JA
551 return;
552
3185942a
JA
553 /* Block keyboard interrupts because this function manipulates global
554 data structures. */
555 _rl_block_sigint ();
89a92869 556 RL_SETSTATE (RL_STATE_REDISPLAYING);
3185942a 557
726f6388
JA
558 if (!rl_display_prompt)
559 rl_display_prompt = "";
560
3185942a 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. */
0628567a 568 cpos_buffer_position = -1;
726f6388 569
3185942a
JA
570 prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
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. */
b80f6443 577 modmark = 0;
726f6388
JA
578 if (_rl_mark_modified_lines && current_history () && rl_undo_list)
579 {
580 line[out++] = '*';
581 line[out] = '\0';
b80f6443 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
0628567a 600 if (local_prompt_len > 0)
ccc6cda3 601 {
0628567a 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 }
0628567a
JA
609 strncpy (line + out, local_prompt, local_prompt_len);
610 out += local_prompt_len;
ccc6cda3 611 }
726f6388 612 line[out] = '\0';
0628567a 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
b80f6443 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; \
3185942a
JA
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;
b80f6443 698 lpos = prompt_physical_chars + modmark;
b80f6443 699
7117c2d2 700#if defined (HANDLE_MULTIBYTE)
3185942a 701 memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
eb873671 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
3185942a
JA
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 {
0628567a 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
b80f6443
JA
723 prompts that exceed two physical lines?
724 Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
eb873671 725#if defined (HANDLE_MULTIBYTE)
3185942a 726 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
eb873671 727 {
0628567a
JA
728 n0 = num;
729 temp = local_prompt_len;
730 while (num < temp)
eb873671 731 {
0001803f 732 z = _rl_col_width (local_prompt, n0, num, 1);
0628567a
JA
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++;
eb873671 741 }
0628567a 742 temp = num;
eb873671 743 }
0628567a 744 else
eb873671 745#endif /* !HANDLE_MULTIBYTE */
0628567a
JA
746 temp = ((newlines + 1) * _rl_screenwidth);
747
748 /* Now account for invisible characters in the current line. */
3185942a
JA
749 /* XXX - this assumes that the invisible characters may be split, but only
750 between the first and the last lines. */
ac50fbac
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;
eb873671 755#if defined (HANDLE_MULTIBYTE)
3185942a 756 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
0001803f 757 lpos -= _rl_col_width (local_prompt, n0, num, 1);
0628567a 758 else
eb873671 759#endif
0628567a 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
0628567a 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));
0001803f 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 {
b80f6443 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 }
b80f6443 800 else if (MB_NULLWCH (wc_bytes))
7117c2d2
JA
801 break; /* Found '\0' */
802 else
803 {
ac50fbac 804 temp = WCWIDTH (wc);
b80f6443 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 {
0628567a 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 {
0628567a 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;
0001803f 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';
0628567a 946 if (cpos_buffer_position < 0)
ccc6cda3 947 {
0628567a 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
0628567a 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. */
ac50fbac 968 displaying_prompt_first_line = 1;
28ef6c31 969 if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
726f6388 970 {
95732b49 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
f1be666c
JA
992#define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
993#define WRAP_OFFSET(line, offset) ((line == 0) \
994 ? (offset ? INVIS_FIRST() : 0) \
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
0001803f
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 {
0628567a
JA
1011 /* This can lead us astray if we execute a program that changes
1012 the locale from a non-multibyte to a multibyte one. */
95732b49
JA
1013 o_cpos = _rl_last_c_pos;
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
95732b49
JA
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
3185942a 1022 change update_line itself. There are several cases in which
95732b49
JA
1023 update_line adjusts _rl_last_c_pos itself (so it can pass
1024 _rl_move_cursor_relative accurate values); it communicates
0628567a
JA
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. */
0001803f 1030 if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
f1be666c
JA
1031 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
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 &&
1036 _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
1037 _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
95732b49 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 {
95732b49
JA
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 }
3185942a
JA
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. */
95732b49 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 &&
0628567a
JA
1113#if 0
1114 _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
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
3185942a
JA
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)
0001803f 1130 _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
7117c2d2 1131 else
3185942a 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
0628567a
JA
1139 start of the line and the desired cursor position. */
1140 nleft = cpos_buffer_position - pos;
726f6388 1141
95732b49
JA
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. */
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 {
0628567a 1152 /* TX == new physical cursor position in multibyte locale. */
7117c2d2 1153 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
0001803f 1154 tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
7117c2d2 1155 else
95732b49 1156 tx = nleft;
f1be666c 1157 if (tx >= 0 && _rl_last_c_pos > tx)
95732b49
JA
1158 {
1159 _rl_backspace (_rl_last_c_pos - tx); /* XXX */
1160 _rl_last_c_pos = tx;
1161 }
726f6388
JA
1162 }
1163
95732b49
JA
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. */
0628567a 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. */
0628567a 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 {
0628567a 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. */
0628567a 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
ac50fbac
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
89a92869 1237 if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
726f6388
JA
1238 {
1239 forced_display = 0;
89a92869
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
ac50fbac
CR
1249 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
1250 displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
0001803f 1251 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
89a92869 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) &&
ac50fbac 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
0628567a 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 {
3185942a 1276 struct line_state *vtemp = line_state_visible;
bb70624e 1277
3185942a
JA
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 }
3185942a 1290
89a92869 1291 RL_UNSETSTATE (RL_STATE_REDISPLAYING);
3185942a 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;
f1be666c 1317 int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
ccc6cda3 1318 int current_invis_chars;
7117c2d2 1319 int col_lendiff, col_temp;
ac50fbac 1320 int bytes_to_insert;
7117c2d2
JA
1321#if defined (HANDLE_MULTIBYTE)
1322 mbstate_t ps_new, ps_old;
0628567a 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. */
95732b49
JA
1331 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1332 temp = _rl_last_c_pos;
1333 else
f1be666c 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
ac50fbac 1347 character consumes more than three columns, spaces will be
7117c2d2 1348 inserted in the string buffer. */
3185942a
JA
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);
b80f6443 1354 if (MB_INVALIDCH (ret))
7117c2d2
JA
1355 {
1356 tempwidth = 1;
1357 ret = 1;
1358 }
b80f6443 1359 else if (MB_NULLWCH (ret))
7117c2d2
JA
1360 tempwidth = 0;
1361 else
ac50fbac 1362 tempwidth = WCWIDTH (wc);
7117c2d2
JA
1363
1364 if (tempwidth > 0)
1365 {
0001803f 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 {
b80f6443 1376 if (MB_INVALIDCH (ret))
0001803f
CR
1377 ret = 1;
1378 memmove (old+bytes, old+ret, strlen (old+ret));
7117c2d2 1379 memcpy (old, new, bytes);
0001803f
CR
1380 /* Fix up indices if we copy data from one line to another */
1381 omax += bytes - ret;
ac50fbac 1382 for (i = current_line+1; i <= inv_botlin+1; i++)
0001803f 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);
95732b49 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 {
b80f6443
JA
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;
3185942a 1417 if (memcmp (old, new, temp) == 0) /* adding at the end */
7117c2d2 1418 {
ac50fbac 1419 new_offset = old_offset = temp;
b80f6443
JA
1420 ofd = old + temp;
1421 nfd = new + temp;
1422 }
1423 else
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))
1429 {
ac50fbac
CR
1430 old_offset = omax;
1431 new_offset = nmax;
b80f6443
JA
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);
ac50fbac 1444
b80f6443
JA
1445 ofd = old + old_offset;
1446 nfd = new + new_offset;
1447 }
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
ac50fbac
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);
ac50fbac 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
b80f6443
JA
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);
b80f6443 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);
95732b49 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
0628567a 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 &&
0628567a 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
3185942a
JA
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)
95732b49
JA
1600 {
1601 /* We take wrap_offset into account here so we can pass correct
1602 information to _rl_move_cursor_relative. */
0001803f 1603 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
95732b49
JA
1604 cpos_adjusted = 1;
1605 }
7117c2d2 1606 else
3185942a 1607 _rl_last_c_pos = lendiff + modmark;
726f6388
JA
1608 }
1609
f1be666c
JA
1610 o_cpos = _rl_last_c_pos;
1611
0628567a 1612 /* When this function returns, _rl_last_c_pos is correct, and an absolute
ac50fbac 1613 cursor position in multibyte mode, but a buffer index when not in a
0628567a 1614 multibyte locale. */
ccc6cda3 1615 _rl_move_cursor_relative (od, old);
ac50fbac 1616
0628567a
JA
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. */
3185942a 1621 if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 &&
f1be666c
JA
1622 (_rl_last_c_pos > 0 || o_cpos > 0) &&
1623 _rl_last_c_pos == prompt_physical_chars)
0628567a 1624 cpos_adjusted = 1;
0628567a 1625#endif
726f6388 1626
7117c2d2 1627 /* if (len (new) > len (old))
ac50fbac
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)
0001803f 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. */
1640 if (current_line == 0 && !_rl_horizontal_scroll_mode &&
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
ac50fbac
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)
0001803f 1662 col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
7117c2d2
JA
1663 else
1664 col_temp = temp;
1665
ac50fbac
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;
f1be666c
JA
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);
ac50fbac 1683 _rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
f1be666c
JA
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. */
ac50fbac 1687 if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
f1be666c
JA
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. */
f1be666c 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. */
3185942a
JA
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 {
ac50fbac
CR
1718 open_some_spaces (col_lendiff);
1719 _rl_output_some_chars (nfd, bytes_to_insert);
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;
3185942a 1724 }
95732b49 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. */
ac50fbac
CR
1729 _rl_output_some_chars (nfd, temp);
1730 _rl_last_c_pos += col_temp;
1731 return;
726f6388 1732 }
ac50fbac 1733 else /* just write from first difference to end of new line */
ccc6cda3 1734 {
ccc6cda3 1735 _rl_output_some_chars (nfd, temp);
7117c2d2 1736 _rl_last_c_pos += col_temp;
3185942a
JA
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. */
ac50fbac 1740 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
f1be666c
JA
1741 {
1742 _rl_last_c_pos -= wrap_offset;
1743 cpos_adjusted = 1;
1744 }
ccc6cda3
JA
1745 return;
1746 }
ac50fbac
CR
1747
1748 if (bytes_to_insert > lendiff)
726f6388 1749 {
3185942a
JA
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. */
ac50fbac 1753 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
3185942a
JA
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;
95732b49
JA
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
1767 characters) we need to adjust _rl_last_c_pos, since it represents
1768 a physical character position. */
3185942a
JA
1769 if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
1770 current_line == prompt_last_screen_line && wrap_offset &&
ac50fbac 1771 displaying_prompt_first_line &&
3185942a
JA
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 &&
ac50fbac 1789 displaying_prompt_first_line &&
726f6388 1790 -lendiff == visible_wrap_offset)
7117c2d2 1791 col_lendiff = 0;
726f6388 1792
ac50fbac
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
ac50fbac
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 {
f1be666c
JA
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. */
ac50fbac 1812 _rl_output_some_chars (nfd, bytes_to_insert);
f1be666c
JA
1813 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1814 {
ac50fbac
CR
1815 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
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))
f1be666c
JA
1820 {
1821 _rl_last_c_pos -= wrap_offset;
1822 cpos_adjusted = 1;
1823 }
1824 }
3185942a 1825 else
ac50fbac
CR
1826 _rl_last_c_pos += bytes_to_insert;
1827
1828 if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
1829 goto clear_rest_of_line;
726f6388
JA
1830 }
1831 }
1832 /* Otherwise, print over the existing material. */
1833 else
1834 {
1835 if (temp > 0)
1836 {
f1be666c
JA
1837 /* If nfd begins at the prompt, or before the invisible
1838 characters in the prompt, we need to adjust _rl_last_c_pos
1839 in a multibyte locale to account for the wrap offset and
1840 set cpos_adjusted accordingly. */
726f6388 1841 _rl_output_some_chars (nfd, temp);
95732b49 1842 _rl_last_c_pos += col_temp; /* XXX */
f1be666c
JA
1843 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1844 {
ac50fbac
CR
1845 if (current_line == 0 && wrap_offset &&
1846 displaying_prompt_first_line &&
1847 _rl_last_c_pos > wrap_offset &&
1848 ((nfd - new) <= prompt_last_invisible))
f1be666c
JA
1849 {
1850 _rl_last_c_pos -= wrap_offset;
1851 cpos_adjusted = 1;
1852 }
1853 }
726f6388 1854 }
ac50fbac 1855clear_rest_of_line:
726f6388 1856 lendiff = (oe - old) - (ne - new);
7117c2d2 1857 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
0001803f 1858 col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
7117c2d2
JA
1859 else
1860 col_lendiff = lendiff;
1861
3185942a
JA
1862 /* If we've already printed over the entire width of the screen,
1863 including the old material, then col_lendiff doesn't matter and
1864 space_to_eol will insert too many spaces. XXX - maybe we should
1865 adjust col_lendiff based on the difference between _rl_last_c_pos
1866 and _rl_screenwidth */
89a92869 1867 if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
b72432fd
JA
1868 {
1869 if (_rl_term_autowrap && current_line < inv_botlin)
7117c2d2 1870 space_to_eol (col_lendiff);
b72432fd 1871 else
7117c2d2 1872 _rl_clear_to_eol (col_lendiff);
b72432fd 1873 }
726f6388
JA
1874 }
1875 }
1876}
1877
1878/* Tell the update routines that we have moved onto a new (empty) line. */
ccc6cda3 1879int
726f6388
JA
1880rl_on_new_line ()
1881{
1882 if (visible_line)
1883 visible_line[0] = '\0';
1884
1885 _rl_last_c_pos = _rl_last_v_pos = 0;
1886 _rl_vis_botlin = last_lmargin = 0;
ccc6cda3
JA
1887 if (vis_lbreaks)
1888 vis_lbreaks[0] = vis_lbreaks[1] = 0;
1889 visible_wrap_offset = 0;
726f6388
JA
1890 return 0;
1891}
1892
bb70624e
JA
1893/* Tell the update routines that we have moved onto a new line with the
1894 prompt already displayed. Code originally from the version of readline
b80f6443
JA
1895 distributed with CLISP. rl_expand_prompt must have already been called
1896 (explicitly or implicitly). This still doesn't work exactly right. */
bb70624e
JA
1897int
1898rl_on_new_line_with_prompt ()
1899{
1900 int prompt_size, i, l, real_screenwidth, newlines;
b80f6443 1901 char *prompt_last_line, *lprompt;
bb70624e
JA
1902
1903 /* Initialize visible_line and invisible_line to ensure that they can hold
1904 the already-displayed prompt. */
1905 prompt_size = strlen (rl_prompt) + 1;
1906 init_line_structures (prompt_size);
1907
1908 /* Make sure the line structures hold the already-displayed prompt for
1909 redisplay. */
b80f6443
JA
1910 lprompt = local_prompt ? local_prompt : rl_prompt;
1911 strcpy (visible_line, lprompt);
1912 strcpy (invisible_line, lprompt);
bb70624e
JA
1913
1914 /* If the prompt contains newlines, take the last tail. */
1915 prompt_last_line = strrchr (rl_prompt, '\n');
1916 if (!prompt_last_line)
1917 prompt_last_line = rl_prompt;
1918
1919 l = strlen (prompt_last_line);
7117c2d2 1920 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
0001803f 1921 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */
7117c2d2
JA
1922 else
1923 _rl_last_c_pos = l;
bb70624e
JA
1924
1925 /* Dissect prompt_last_line into screen lines. Note that here we have
1926 to use the real screenwidth. Readline's notion of screenwidth might be
1927 one less, see terminal.c. */
28ef6c31 1928 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
bb70624e
JA
1929 _rl_last_v_pos = l / real_screenwidth;
1930 /* If the prompt length is a multiple of real_screenwidth, we don't know
1931 whether the cursor is at the end of the last line, or already at the
1932 beginning of the next line. Output a newline just to be safe. */
1933 if (l > 0 && (l % real_screenwidth) == 0)
1934 _rl_output_some_chars ("\n", 1);
1935 last_lmargin = 0;
1936
1937 newlines = 0; i = 0;
1938 while (i <= l)
1939 {
1940 _rl_vis_botlin = newlines;
1941 vis_lbreaks[newlines++] = i;
1942 i += real_screenwidth;
1943 }
1944 vis_lbreaks[newlines] = l;
1945 visible_wrap_offset = 0;
1946
b80f6443
JA
1947 rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
1948
bb70624e
JA
1949 return 0;
1950}
1951
726f6388 1952/* Actually update the display, period. */
ccc6cda3 1953int
726f6388
JA
1954rl_forced_update_display ()
1955{
0628567a
JA
1956 register char *temp;
1957
726f6388
JA
1958 if (visible_line)
1959 {
0628567a 1960 temp = visible_line;
ccc6cda3 1961 while (*temp)
b72432fd 1962 *temp++ = '\0';
726f6388
JA
1963 }
1964 rl_on_new_line ();
1965 forced_display++;
ccc6cda3 1966 (*rl_redisplay_function) ();
726f6388
JA
1967 return 0;
1968}
1969
1970/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
95732b49
JA
1971 (Well, when we don't have multibyte characters, _rl_last_c_pos is a
1972 buffer index.)
726f6388
JA
1973 DATA is the contents of the screen line of interest; i.e., where
1974 the movement is being done. */
1975void
1976_rl_move_cursor_relative (new, data)
1977 int new;
28ef6c31 1978 const char *data;
726f6388
JA
1979{
1980 register int i;
95732b49
JA
1981 int woff; /* number of invisible chars on current line */
1982 int cpos, dpos; /* current and desired cursor positions */
0001803f 1983 int adjust;
726f6388 1984
f1be666c 1985 woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
95732b49 1986 cpos = _rl_last_c_pos;
89a92869
CR
1987
1988 if (cpos == 0 && cpos == new)
1989 return;
1990
7117c2d2
JA
1991#if defined (HANDLE_MULTIBYTE)
1992 /* If we have multibyte characters, NEW is indexed by the buffer point in
1993 a multibyte string, but _rl_last_c_pos is the display position. In
b80f6443 1994 this case, NEW's display position is not obvious and must be
95732b49
JA
1995 calculated. We need to account for invisible characters in this line,
1996 as long as we are past them and they are counted by _rl_col_width. */
1997 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
b80f6443 1998 {
0001803f
CR
1999 adjust = 1;
2000 /* Try to short-circuit common cases and eliminate a bunch of multibyte
2001 character function calls. */
2002 /* 1. prompt string */
2003 if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2004 {
2005 dpos = prompt_physical_chars;
2006 cpos_adjusted = 1;
2007 adjust = 0;
2008 }
2009 /* 2. prompt_string + line contents */
2010 else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2011 {
2012 dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2013 cpos_adjusted = 1;
2014 adjust = 0;
2015 }
2016 else
2017 dpos = _rl_col_width (data, 0, new, 1);
2018
ac50fbac
CR
2019 if (displaying_prompt_first_line == 0)
2020 adjust = 0;
2021
f1be666c
JA
2022 /* Use NEW when comparing against the last invisible character in the
2023 prompt string, since they're both buffer indices and DPOS is a
2024 desired display position. */
0001803f 2025 if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */
89a92869 2026 (prompt_physical_chars >= _rl_screenwidth &&
f1be666c 2027 _rl_last_v_pos == prompt_last_screen_line &&
89a92869 2028 wrap_offset >= woff && dpos >= woff &&
0001803f 2029 new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset))))
3185942a 2030 /* XXX last comparison might need to be >= */
0628567a
JA
2031 {
2032 dpos -= woff;
2033 /* Since this will be assigned to _rl_last_c_pos at the end (more
2034 precisely, _rl_last_c_pos == dpos when this function returns),
2035 let the caller know. */
2036 cpos_adjusted = 1;
2037 }
b80f6443 2038 }
95732b49 2039 else
7117c2d2 2040#endif
95732b49
JA
2041 dpos = new;
2042
2043 /* If we don't have to do anything, then return. */
2044 if (cpos == dpos)
2045 return;
726f6388
JA
2046
2047 /* It may be faster to output a CR, and then move forwards instead
2048 of moving backwards. */
2049 /* i == current physical cursor position. */
95732b49
JA
2050#if defined (HANDLE_MULTIBYTE)
2051 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2052 i = _rl_last_c_pos;
2053 else
2054#endif
2055 i = _rl_last_c_pos - woff;
0628567a 2056 if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
28ef6c31 2057 (_rl_term_autowrap && i == _rl_screenwidth))
726f6388
JA
2058 {
2059#if defined (__MSDOS__)
2060 putc ('\r', rl_outstream);
2061#else
28ef6c31 2062 tputs (_rl_term_cr, 1, _rl_output_character_function);
726f6388 2063#endif /* !__MSDOS__ */
95732b49 2064 cpos = _rl_last_c_pos = 0;
726f6388
JA
2065 }
2066
95732b49 2067 if (cpos < dpos)
726f6388
JA
2068 {
2069 /* Move the cursor forward. We do it by printing the command
2070 to move the cursor forward if there is one, else print that
2071 portion of the output buffer again. Which is cheaper? */
2072
2073 /* The above comment is left here for posterity. It is faster
2074 to print one character (non-control) than to print a control
2075 sequence telling the terminal to move forward one character.
2076 That kind of control is for people who don't know what the
2077 data is underneath the cursor. */
0628567a
JA
2078
2079 /* However, we need a handle on where the current display position is
2080 in the buffer for the immediately preceding comment to be true.
2081 In multibyte locales, we don't currently have that info available.
2082 Without it, we don't know where the data we have to display begins
2083 in the buffer and we have to go back to the beginning of the screen
2084 line. In this case, we can use the terminal sequence to move forward
2085 if it's available. */
7117c2d2
JA
2086 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2087 {
0628567a
JA
2088 if (_rl_term_forward_char)
2089 {
2090 for (i = cpos; i < dpos; i++)
2091 tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2092 }
2093 else
2094 {
2095 tputs (_rl_term_cr, 1, _rl_output_character_function);
2096 for (i = 0; i < new; i++)
2097 putc (data[i], rl_outstream);
2098 }
7117c2d2 2099 }
726f6388 2100 else
95732b49 2101 for (i = cpos; i < new; i++)
726f6388 2102 putc (data[i], rl_outstream);
726f6388 2103 }
95732b49 2104
7117c2d2
JA
2105#if defined (HANDLE_MULTIBYTE)
2106 /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2107 The byte length of the string is probably bigger than the column width
2108 of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2109 display point is less than _rl_last_c_pos. */
7117c2d2 2110#endif
95732b49
JA
2111 else if (cpos > dpos)
2112 _rl_backspace (cpos - dpos);
7117c2d2 2113
95732b49 2114 _rl_last_c_pos = dpos;
726f6388
JA
2115}
2116
2117/* PWP: move the cursor up or down. */
2118void
2119_rl_move_vert (to)
2120 int to;
2121{
2122 register int delta, i;
2123
28ef6c31 2124 if (_rl_last_v_pos == to || to > _rl_screenheight)
726f6388
JA
2125 return;
2126
726f6388
JA
2127 if ((delta = to - _rl_last_v_pos) > 0)
2128 {
2129 for (i = 0; i < delta; i++)
2130 putc ('\n', rl_outstream);
bb70624e
JA
2131#if defined (__MSDOS__)
2132 putc ('\r', rl_outstream);
2133#else
28ef6c31 2134 tputs (_rl_term_cr, 1, _rl_output_character_function);
bb70624e 2135#endif
726f6388
JA
2136 _rl_last_c_pos = 0;
2137 }
2138 else
2139 { /* delta < 0 */
ac50fbac
CR
2140#ifdef __DJGPP__
2141 int row, col;
2142
2143 fflush (rl_outstream);
2144 ScreenGetCursor (&row, &col);
2145 ScreenSetCursor (row + delta, col);
2146 i = -delta;
2147#else
28ef6c31 2148 if (_rl_term_up && *_rl_term_up)
726f6388 2149 for (i = 0; i < -delta; i++)
28ef6c31 2150 tputs (_rl_term_up, 1, _rl_output_character_function);
ac50fbac 2151#endif /* !__DJGPP__ */
726f6388 2152 }
bb70624e 2153
726f6388
JA
2154 _rl_last_v_pos = to; /* Now TO is here */
2155}
2156
2157/* Physically print C on rl_outstream. This is for functions which know
2158 how to optimize the display. Return the number of characters output. */
ccc6cda3 2159int
726f6388
JA
2160rl_show_char (c)
2161 int c;
2162{
2163 int n = 1;
2164 if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2165 {
2166 fprintf (rl_outstream, "M-");
2167 n += 2;
2168 c = UNMETA (c);
2169 }
2170
2171#if defined (DISPLAY_TABS)
ccc6cda3 2172 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
726f6388 2173#else
ccc6cda3 2174 if (CTRL_CHAR (c) || c == RUBOUT)
726f6388
JA
2175#endif /* !DISPLAY_TABS */
2176 {
2177 fprintf (rl_outstream, "C-");
2178 n += 2;
ccc6cda3 2179 c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
726f6388
JA
2180 }
2181
2182 putc (c, rl_outstream);
2183 fflush (rl_outstream);
2184 return n;
2185}
2186
2187int
2188rl_character_len (c, pos)
2189 register int c, pos;
2190{
2191 unsigned char uc;
2192
2193 uc = (unsigned char)c;
2194
2195 if (META_CHAR (uc))
2196 return ((_rl_output_meta_chars == 0) ? 4 : 1);
2197
2198 if (uc == '\t')
2199 {
2200#if defined (DISPLAY_TABS)
2201 return (((pos | 7) + 1) - pos);
2202#else
2203 return (2);
2204#endif /* !DISPLAY_TABS */
2205 }
2206
ccc6cda3
JA
2207 if (CTRL_CHAR (c) || c == RUBOUT)
2208 return (2);
2209
f73dda09 2210 return ((ISPRINT (uc)) ? 1 : 2);
726f6388 2211}
726f6388
JA
2212/* How to print things in the "echo-area". The prompt is treated as a
2213 mini-modeline. */
95732b49 2214static int msg_saved_prompt = 0;
726f6388 2215
ccc6cda3
JA
2216#if defined (USE_VARARGS)
2217int
2218#if defined (PREFER_STDARG)
2219rl_message (const char *format, ...)
2220#else
726f6388
JA
2221rl_message (va_alist)
2222 va_dcl
ccc6cda3 2223#endif
726f6388 2224{
726f6388 2225 va_list args;
ccc6cda3
JA
2226#if defined (PREFER_VARARGS)
2227 char *format;
2228#endif
ac50fbac
CR
2229#if defined (HAVE_VSNPRINTF)
2230 int bneed;
2231#endif
726f6388 2232
ccc6cda3
JA
2233#if defined (PREFER_STDARG)
2234 va_start (args, format);
2235#else
726f6388
JA
2236 va_start (args);
2237 format = va_arg (args, char *);
ccc6cda3
JA
2238#endif
2239
ac50fbac
CR
2240 if (msg_buf == 0)
2241 msg_buf = xmalloc (msg_bufsiz = 128);
2242
f73dda09 2243#if defined (HAVE_VSNPRINTF)
ac50fbac
CR
2244 bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2245 if (bneed >= msg_bufsiz - 1)
2246 {
2247 msg_bufsiz = bneed + 1;
2248 msg_buf = xrealloc (msg_buf, msg_bufsiz);
2249 va_end (args);
2250
2251#if defined (PREFER_STDARG)
2252 va_start (args, format);
2253#else
2254 va_start (args);
2255 format = va_arg (args, char *);
2256#endif
2257 vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2258 }
f73dda09 2259#else
726f6388 2260 vsprintf (msg_buf, format, args);
ac50fbac 2261 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
f73dda09 2262#endif
726f6388
JA
2263 va_end (args);
2264
95732b49
JA
2265 if (saved_local_prompt == 0)
2266 {
2267 rl_save_prompt ();
2268 msg_saved_prompt = 1;
2269 }
ac50fbac
CR
2270 else if (local_prompt != saved_local_prompt)
2271 {
2272 FREE (local_prompt);
2273 FREE (local_prompt_prefix);
2274 local_prompt = (char *)NULL;
2275 }
726f6388 2276 rl_display_prompt = msg_buf;
95732b49
JA
2277 local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2278 &prompt_last_invisible,
2279 &prompt_invis_chars_first_line,
2280 &prompt_physical_chars);
2281 local_prompt_prefix = (char *)NULL;
0628567a 2282 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
ccc6cda3 2283 (*rl_redisplay_function) ();
95732b49 2284
726f6388
JA
2285 return 0;
2286}
ccc6cda3
JA
2287#else /* !USE_VARARGS */
2288int
726f6388
JA
2289rl_message (format, arg1, arg2)
2290 char *format;
2291{
ac50fbac
CR
2292 if (msg_buf == 0)
2293 msg_buf = xmalloc (msg_bufsiz = 128);
2294
726f6388 2295 sprintf (msg_buf, format, arg1, arg2);
ac50fbac 2296 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
95732b49 2297
726f6388 2298 rl_display_prompt = msg_buf;
95732b49
JA
2299 if (saved_local_prompt == 0)
2300 {
2301 rl_save_prompt ();
2302 msg_saved_prompt = 1;
2303 }
ac50fbac
CR
2304 else if (local_prompt != saved_local_prompt)
2305 {
2306 FREE (local_prompt);
2307 FREE (local_prompt_prefix);
2308 local_prompt = (char *)NULL;
2309 }
95732b49
JA
2310 local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2311 &prompt_last_invisible,
2312 &prompt_invis_chars_first_line,
2313 &prompt_physical_chars);
2314 local_prompt_prefix = (char *)NULL;
0628567a 2315 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
ccc6cda3 2316 (*rl_redisplay_function) ();
95732b49 2317
726f6388
JA
2318 return 0;
2319}
ccc6cda3 2320#endif /* !USE_VARARGS */
726f6388
JA
2321
2322/* How to clear things from the "echo-area". */
ccc6cda3 2323int
726f6388
JA
2324rl_clear_message ()
2325{
2326 rl_display_prompt = rl_prompt;
95732b49
JA
2327 if (msg_saved_prompt)
2328 {
2329 rl_restore_prompt ();
2330 msg_saved_prompt = 0;
2331 }
ccc6cda3 2332 (*rl_redisplay_function) ();
726f6388
JA
2333 return 0;
2334}
2335
ccc6cda3 2336int
726f6388
JA
2337rl_reset_line_state ()
2338{
2339 rl_on_new_line ();
2340
2341 rl_display_prompt = rl_prompt ? rl_prompt : "";
2342 forced_display = 1;
2343 return 0;
2344}
2345
ccc6cda3 2346void
b72432fd 2347rl_save_prompt ()
ccc6cda3
JA
2348{
2349 saved_local_prompt = local_prompt;
2350 saved_local_prefix = local_prompt_prefix;
95732b49 2351 saved_prefix_length = prompt_prefix_length;
0628567a 2352 saved_local_length = local_prompt_len;
28ef6c31
JA
2353 saved_last_invisible = prompt_last_invisible;
2354 saved_visible_length = prompt_visible_length;
b80f6443
JA
2355 saved_invis_chars_first_line = prompt_invis_chars_first_line;
2356 saved_physical_chars = prompt_physical_chars;
ccc6cda3
JA
2357
2358 local_prompt = local_prompt_prefix = (char *)0;
0628567a 2359 local_prompt_len = 0;
95732b49 2360 prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
b80f6443 2361 prompt_invis_chars_first_line = prompt_physical_chars = 0;
ccc6cda3
JA
2362}
2363
2364void
b72432fd 2365rl_restore_prompt ()
ccc6cda3 2366{
28ef6c31
JA
2367 FREE (local_prompt);
2368 FREE (local_prompt_prefix);
ccc6cda3
JA
2369
2370 local_prompt = saved_local_prompt;
2371 local_prompt_prefix = saved_local_prefix;
0628567a 2372 local_prompt_len = saved_local_length;
95732b49 2373 prompt_prefix_length = saved_prefix_length;
28ef6c31
JA
2374 prompt_last_invisible = saved_last_invisible;
2375 prompt_visible_length = saved_visible_length;
b80f6443
JA
2376 prompt_invis_chars_first_line = saved_invis_chars_first_line;
2377 prompt_physical_chars = saved_physical_chars;
95732b49
JA
2378
2379 /* can test saved_local_prompt to see if prompt info has been saved. */
2380 saved_local_prompt = saved_local_prefix = (char *)0;
0628567a 2381 saved_local_length = 0;
95732b49
JA
2382 saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2383 saved_invis_chars_first_line = saved_physical_chars = 0;
ccc6cda3
JA
2384}
2385
2386char *
2387_rl_make_prompt_for_search (pchar)
2388 int pchar;
2389{
2390 int len;
0628567a 2391 char *pmt, *p;
ccc6cda3 2392
b72432fd 2393 rl_save_prompt ();
ccc6cda3 2394
0628567a
JA
2395 /* We've saved the prompt, and can do anything with the various prompt
2396 strings we need before they're restored. We want the unexpanded
2397 portion of the prompt string after any final newline. */
2398 p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2399 if (p == 0)
ccc6cda3
JA
2400 {
2401 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
f73dda09 2402 pmt = (char *)xmalloc (len + 2);
ccc6cda3 2403 if (len)
b72432fd 2404 strcpy (pmt, rl_prompt);
ccc6cda3
JA
2405 pmt[len] = pchar;
2406 pmt[len+1] = '\0';
2407 }
2408 else
2409 {
0628567a
JA
2410 p++;
2411 len = strlen (p);
f73dda09 2412 pmt = (char *)xmalloc (len + 2);
ccc6cda3 2413 if (len)
0628567a 2414 strcpy (pmt, p);
ccc6cda3
JA
2415 pmt[len] = pchar;
2416 pmt[len+1] = '\0';
0628567a 2417 }
b80f6443 2418
0628567a 2419 /* will be overwritten by expand_prompt, called from rl_message */
95732b49 2420 prompt_physical_chars = saved_physical_chars + 1;
ccc6cda3
JA
2421 return pmt;
2422}
2423
726f6388
JA
2424/* Quick redisplay hack when erasing characters at the end of the line. */
2425void
2426_rl_erase_at_end_of_line (l)
2427 int l;
2428{
2429 register int i;
2430
ccc6cda3 2431 _rl_backspace (l);
726f6388
JA
2432 for (i = 0; i < l; i++)
2433 putc (' ', rl_outstream);
ccc6cda3 2434 _rl_backspace (l);
726f6388
JA
2435 for (i = 0; i < l; i++)
2436 visible_line[--_rl_last_c_pos] = '\0';
2437 rl_display_fixed++;
2438}
2439
2440/* Clear to the end of the line. COUNT is the minimum
2441 number of character spaces to clear, */
d166f048
JA
2442void
2443_rl_clear_to_eol (count)
726f6388
JA
2444 int count;
2445{
ac50fbac 2446#ifndef __MSDOS__
28ef6c31
JA
2447 if (_rl_term_clreol)
2448 tputs (_rl_term_clreol, 1, _rl_output_character_function);
ac50fbac
CR
2449 else
2450#endif
2451 if (count)
2452 space_to_eol (count);
726f6388
JA
2453}
2454
2455/* Clear to the end of the line using spaces. COUNT is the minimum
2456 number of character spaces to clear, */
2457static void
2458space_to_eol (count)
2459 int count;
2460{
2461 register int i;
2462
2463 for (i = 0; i < count; i++)
2464 putc (' ', rl_outstream);
2465
2466 _rl_last_c_pos += count;
2467}
2468
d166f048
JA
2469void
2470_rl_clear_screen ()
2471{
ac50fbac 2472#ifndef __DJGPP__
28ef6c31
JA
2473 if (_rl_term_clrpag)
2474 tputs (_rl_term_clrpag, 1, _rl_output_character_function);
d166f048 2475 else
28ef6c31 2476 rl_crlf ();
ac50fbac
CR
2477#else
2478 ScreenClear ();
2479 ScreenSetCursor (0, 0);
2480#endif /* __DJGPP__ */
d166f048
JA
2481}
2482
7117c2d2 2483/* Insert COUNT characters from STRING to the output stream at column COL. */
726f6388 2484static void
7117c2d2 2485insert_some_chars (string, count, col)
726f6388 2486 char *string;
7117c2d2 2487 int count, col;
726f6388 2488{
ac50fbac 2489 open_some_spaces (col);
95732b49 2490 _rl_output_some_chars (string, count);
ac50fbac
CR
2491}
2492
2493/* Insert COL spaces, keeping the cursor at the same position. We follow the
2494 ncurses documentation and use either im/ei with explicit spaces, or IC/ic
2495 by itself. We assume there will either be ei or we don't need to use it. */
2496static void
2497open_some_spaces (col)
2498 int col;
2499{
2500#if !defined (__MSDOS__) && !defined (__MINGW32__)
2501 char *buffer;
2502 register int i;
7117c2d2 2503
726f6388 2504 /* If IC is defined, then we do not have to "enter" insert mode. */
28ef6c31 2505 if (_rl_term_IC)
726f6388 2506 {
7117c2d2 2507 buffer = tgoto (_rl_term_IC, 0, col);
726f6388 2508 tputs (buffer, 1, _rl_output_character_function);
726f6388 2509 }
ac50fbac 2510 else if (_rl_term_im && *_rl_term_im)
726f6388 2511 {
ac50fbac
CR
2512 tputs (_rl_term_im, 1, _rl_output_character_function);
2513 /* just output the desired number of spaces */
2514 for (i = col; i--; )
2515 _rl_output_character_function (' ');
2516 /* If there is a string to turn off insert mode, use it now. */
28ef6c31
JA
2517 if (_rl_term_ei && *_rl_term_ei)
2518 tputs (_rl_term_ei, 1, _rl_output_character_function);
ac50fbac
CR
2519 /* and move back the right number of spaces */
2520 _rl_backspace (col);
2521 }
2522 else if (_rl_term_ic && *_rl_term_ic)
2523 {
2524 /* If there is a special command for inserting characters, then
2525 use that first to open up the space. */
2526 for (i = col; i--; )
2527 tputs (_rl_term_ic, 1, _rl_output_character_function);
726f6388 2528 }
ac50fbac 2529#endif /* !__MSDOS__ && !__MINGW32__ */
726f6388
JA
2530}
2531
2532/* Delete COUNT characters from the display line. */
2533static void
2534delete_chars (count)
2535 int count;
2536{
28ef6c31 2537 if (count > _rl_screenwidth) /* XXX */
726f6388
JA
2538 return;
2539
95732b49 2540#if !defined (__MSDOS__) && !defined (__MINGW32__)
28ef6c31 2541 if (_rl_term_DC && *_rl_term_DC)
726f6388 2542 {
ccc6cda3 2543 char *buffer;
28ef6c31 2544 buffer = tgoto (_rl_term_DC, count, count);
726f6388
JA
2545 tputs (buffer, count, _rl_output_character_function);
2546 }
2547 else
2548 {
28ef6c31 2549 if (_rl_term_dc && *_rl_term_dc)
726f6388 2550 while (count--)
28ef6c31 2551 tputs (_rl_term_dc, 1, _rl_output_character_function);
726f6388 2552 }
95732b49 2553#endif /* !__MSDOS__ && !__MINGW32__ */
726f6388
JA
2554}
2555
2556void
2557_rl_update_final ()
2558{
2559 int full_lines;
2560
2561 full_lines = 0;
ccc6cda3
JA
2562 /* If the cursor is the only thing on an otherwise-blank last line,
2563 compensate so we don't print an extra CRLF. */
2564 if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
d166f048 2565 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
726f6388
JA
2566 {
2567 _rl_vis_botlin--;
2568 full_lines = 1;
2569 }
2570 _rl_move_vert (_rl_vis_botlin);
ccc6cda3 2571 /* If we've wrapped lines, remove the final xterm line-wrap flag. */
28ef6c31 2572 if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
726f6388 2573 {
726f6388 2574 char *last_line;
7117c2d2 2575
bb70624e 2576 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
0628567a
JA
2577 cpos_buffer_position = -1; /* don't know where we are in buffer */
2578 _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */
d166f048 2579 _rl_clear_to_eol (0);
28ef6c31 2580 putc (last_line[_rl_screenwidth - 1], rl_outstream);
726f6388
JA
2581 }
2582 _rl_vis_botlin = 0;
28ef6c31 2583 rl_crlf ();
726f6388
JA
2584 fflush (rl_outstream);
2585 rl_display_fixed++;
2586}
2587
2588/* Move to the start of the current line. */
2589static void
2590cr ()
2591{
28ef6c31 2592 if (_rl_term_cr)
726f6388 2593 {
bb70624e
JA
2594#if defined (__MSDOS__)
2595 putc ('\r', rl_outstream);
2596#else
28ef6c31 2597 tputs (_rl_term_cr, 1, _rl_output_character_function);
bb70624e 2598#endif
726f6388
JA
2599 _rl_last_c_pos = 0;
2600 }
2601}
2602
bb70624e
JA
2603/* Redraw the last line of a multi-line prompt that may possibly contain
2604 terminal escape sequences. Called with the cursor at column 0 of the
2605 line to draw the prompt on. */
2606static void
2607redraw_prompt (t)
2608 char *t;
2609{
95732b49 2610 char *oldp;
bb70624e 2611
bb70624e 2612 oldp = rl_display_prompt;
95732b49 2613 rl_save_prompt ();
bb70624e
JA
2614
2615 rl_display_prompt = t;
28ef6c31
JA
2616 local_prompt = expand_prompt (t, &prompt_visible_length,
2617 &prompt_last_invisible,
b80f6443
JA
2618 &prompt_invis_chars_first_line,
2619 &prompt_physical_chars);
bb70624e 2620 local_prompt_prefix = (char *)NULL;
0628567a 2621 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
95732b49 2622
bb70624e
JA
2623 rl_forced_update_display ();
2624
2625 rl_display_prompt = oldp;
95732b49 2626 rl_restore_prompt();
bb70624e
JA
2627}
2628
726f6388
JA
2629/* Redisplay the current line after a SIGWINCH is received. */
2630void
2631_rl_redisplay_after_sigwinch ()
2632{
bb70624e 2633 char *t;
726f6388 2634
3185942a
JA
2635 /* Clear the last line (assuming that the screen size change will result in
2636 either more or fewer characters on that line only) and put the cursor at
2637 column 0. Make sure the right thing happens if we have wrapped to a new
2638 screen line. */
28ef6c31 2639 if (_rl_term_cr)
726f6388 2640 {
3185942a
JA
2641 _rl_move_vert (_rl_vis_botlin);
2642
bb70624e
JA
2643#if defined (__MSDOS__)
2644 putc ('\r', rl_outstream);
2645#else
28ef6c31 2646 tputs (_rl_term_cr, 1, _rl_output_character_function);
bb70624e 2647#endif
726f6388 2648 _rl_last_c_pos = 0;
bb70624e 2649#if defined (__MSDOS__)
28ef6c31 2650 space_to_eol (_rl_screenwidth);
bb70624e
JA
2651 putc ('\r', rl_outstream);
2652#else
28ef6c31
JA
2653 if (_rl_term_clreol)
2654 tputs (_rl_term_clreol, 1, _rl_output_character_function);
726f6388
JA
2655 else
2656 {
28ef6c31
JA
2657 space_to_eol (_rl_screenwidth);
2658 tputs (_rl_term_cr, 1, _rl_output_character_function);
726f6388 2659 }
bb70624e 2660#endif
726f6388
JA
2661 if (_rl_last_v_pos > 0)
2662 _rl_move_vert (0);
2663 }
2664 else
28ef6c31 2665 rl_crlf ();
726f6388
JA
2666
2667 /* Redraw only the last line of a multi-line prompt. */
2668 t = strrchr (rl_display_prompt, '\n');
2669 if (t)
bb70624e 2670 redraw_prompt (++t);
726f6388
JA
2671 else
2672 rl_forced_update_display ();
2673}
ccc6cda3
JA
2674
2675void
2676_rl_clean_up_for_exit ()
2677{
3185942a 2678 if (_rl_echoing_p)
ccc6cda3 2679 {
b7ec1810
CR
2680 if (_rl_vis_botlin > 0) /* minor optimization plus bug fix */
2681 _rl_move_vert (_rl_vis_botlin);
ccc6cda3
JA
2682 _rl_vis_botlin = 0;
2683 fflush (rl_outstream);
b72432fd 2684 rl_restart_output (1, 0);
ccc6cda3
JA
2685 }
2686}
b72432fd
JA
2687
2688void
2689_rl_erase_entire_line ()
2690{
2691 cr ();
2692 _rl_clear_to_eol (0);
2693 cr ();
2694 fflush (rl_outstream);
2695}
bb70624e
JA
2696
2697/* return the `current display line' of the cursor -- the number of lines to
2698 move up to get to the first screen line of the current readline line. */
2699int
2700_rl_current_display_line ()
2701{
2702 int ret, nleft;
2703
2704 /* Find out whether or not there might be invisible characters in the
2705 editing buffer. */
2706 if (rl_display_prompt == rl_prompt)
28ef6c31 2707 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
bb70624e 2708 else
28ef6c31 2709 nleft = _rl_last_c_pos - _rl_screenwidth;
bb70624e
JA
2710
2711 if (nleft > 0)
28ef6c31 2712 ret = 1 + nleft / _rl_screenwidth;
bb70624e
JA
2713 else
2714 ret = 0;
2715
2716 return ret;
2717}
7117c2d2
JA
2718
2719#if defined (HANDLE_MULTIBYTE)
2720/* Calculate the number of screen columns occupied by STR from START to END.
2721 In the case of multibyte characters with stateful encoding, we have to
2722 scan from the beginning of the string to take the state into account. */
2723static int
0001803f 2724_rl_col_width (str, start, end, flags)
b80f6443 2725 const char *str;
0001803f 2726 int start, end, flags;
7117c2d2
JA
2727{
2728 wchar_t wc;
0628567a 2729 mbstate_t ps;
7117c2d2
JA
2730 int tmp, point, width, max;
2731
2732 if (end <= start)
2733 return 0;
f1be666c 2734 if (MB_CUR_MAX == 1 || rl_byte_oriented)
ac50fbac 2735 /* this can happen in some cases where it's inconvenient to check */
f1be666c 2736 return (end - start);
7117c2d2 2737
0628567a
JA
2738 memset (&ps, 0, sizeof (mbstate_t));
2739
7117c2d2
JA
2740 point = 0;
2741 max = end;
2742
0001803f
CR
2743 /* Try to short-circuit common cases. The adjustment to remove wrap_offset
2744 is done by the caller. */
2745 /* 1. prompt string */
2746 if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
2747 return (prompt_physical_chars + wrap_offset);
2748 /* 2. prompt string + line contents */
2749 else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
2750 {
2751 tmp = prompt_physical_chars + wrap_offset;
2752 /* XXX - try to call ourselves recursively with non-prompt portion */
2753 tmp += _rl_col_width (str, local_prompt_len, end, flags);
2754 return (tmp);
2755 }
2756
7117c2d2
JA
2757 while (point < start)
2758 {
2759 tmp = mbrlen (str + point, max, &ps);
b80f6443 2760 if (MB_INVALIDCH ((size_t)tmp))
7117c2d2
JA
2761 {
2762 /* In this case, the bytes are invalid or too short to compose a
2763 multibyte character, so we assume that the first byte represents
2764 a single character. */
2765 point++;
2766 max--;
2767
2768 /* Clear the state of the byte sequence, because in this case the
2769 effect of mbstate is undefined. */
2770 memset (&ps, 0, sizeof (mbstate_t));
2771 }
b80f6443
JA
2772 else if (MB_NULLWCH (tmp))
2773 break; /* Found '\0' */
7117c2d2
JA
2774 else
2775 {
2776 point += tmp;
2777 max -= tmp;
2778 }
2779 }
2780
2781 /* If START is not a byte that starts a character, then POINT will be
2782 greater than START. In this case, assume that (POINT - START) gives
2783 a byte count that is the number of columns of difference. */
2784 width = point - start;
2785
2786 while (point < end)
2787 {
2788 tmp = mbrtowc (&wc, str + point, max, &ps);
b80f6443 2789 if (MB_INVALIDCH ((size_t)tmp))
7117c2d2
JA
2790 {
2791 /* In this case, the bytes are invalid or too short to compose a
2792 multibyte character, so we assume that the first byte represents
2793 a single character. */
2794 point++;
2795 max--;
2796
2797 /* and assume that the byte occupies a single column. */
2798 width++;
2799
2800 /* Clear the state of the byte sequence, because in this case the
2801 effect of mbstate is undefined. */
2802 memset (&ps, 0, sizeof (mbstate_t));
2803 }
b80f6443
JA
2804 else if (MB_NULLWCH (tmp))
2805 break; /* Found '\0' */
7117c2d2
JA
2806 else
2807 {
2808 point += tmp;
2809 max -= tmp;
ac50fbac 2810 tmp = WCWIDTH(wc);
7117c2d2
JA
2811 width += (tmp >= 0) ? tmp : 1;
2812 }
2813 }
2814
2815 width += point - end;
2816
2817 return width;
2818}
2819#endif /* HANDLE_MULTIBYTE */