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