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