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