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