Import readline 7.0 (patch 5)
[deliverable/binutils-gdb.git] / readline / display.c
1 /* display.c -- readline redisplay facility. */
2
3 /* Copyright (C) 1987-2015 Free Software Foundation, Inc.
4
5 This file is part of the GNU Readline Library (Readline), a library
6 for reading lines of text with interactive input and history editing.
7
8 Readline is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Readline is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Readline. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #define READLINE_LIBRARY
23
24 #if defined (HAVE_CONFIG_H)
25 # include <config.h>
26 #endif
27
28 #include <sys/types.h>
29
30 #if defined (HAVE_UNISTD_H)
31 # include <unistd.h>
32 #endif /* HAVE_UNISTD_H */
33
34 #include "posixstat.h"
35
36 #if defined (HAVE_STDLIB_H)
37 # include <stdlib.h>
38 #else
39 # include "ansi_stdlib.h"
40 #endif /* HAVE_STDLIB_H */
41
42 #include <stdio.h>
43
44 #ifdef __MSDOS__
45 # include <pc.h>
46 #endif
47
48 /* System-specific feature definitions and include files. */
49 #include "rldefs.h"
50 #include "rlmbutil.h"
51
52 /* Termcap library stuff. */
53 #include "tcap.h"
54
55 /* Some standard library routines. */
56 #include "readline.h"
57 #include "history.h"
58
59 #include "rlprivate.h"
60 #include "xmalloc.h"
61
62 #if !defined (strchr) && !defined (__STDC__)
63 extern char *strchr (), *strrchr ();
64 #endif /* !strchr && !__STDC__ */
65
66 static void update_line PARAMS((char *, char *, int, int, int, int));
67 static void space_to_eol PARAMS((int));
68 static void delete_chars PARAMS((int));
69 static void insert_some_chars PARAMS((char *, int, int));
70 static void open_some_spaces PARAMS((int));
71 static void cr PARAMS((void));
72 static void redraw_prompt PARAMS((char *));
73
74 /* Values for FLAGS */
75 #define PMT_MULTILINE 0x01
76
77 static char *expand_prompt PARAMS((char *, int, int *, int *, int *, int *));
78
79 /* State of visible and invisible lines. */
80 struct line_state
81 {
82 char *line;
83 int *lbreaks;
84 int lbsize;
85 #if defined (HANDLE_MULTIBYTE)
86 int wbsize;
87 int *wrapped_line;
88 #endif
89 };
90
91 /* The line display buffers. One is the line currently displayed on
92 the screen. The other is the line about to be displayed. */
93 static struct line_state line_state_array[2];
94 static struct line_state *line_state_visible = &line_state_array[0];
95 static struct line_state *line_state_invisible = &line_state_array[1];
96 static int line_structures_initialized = 0;
97
98 /* Backwards-compatible names. */
99 #define inv_lbreaks (line_state_invisible->lbreaks)
100 #define inv_lbsize (line_state_invisible->lbsize)
101 #define vis_lbreaks (line_state_visible->lbreaks)
102 #define vis_lbsize (line_state_visible->lbsize)
103
104 #define visible_line (line_state_visible->line)
105 #define invisible_line (line_state_invisible->line)
106
107 #if defined (HANDLE_MULTIBYTE)
108 static int _rl_col_width PARAMS((const char *, int, int, int));
109 #else
110 # define _rl_col_width(l, s, e, f) (((e) <= (s)) ? 0 : (e) - (s))
111 #endif
112
113 /* Heuristic used to decide whether it is faster to move from CUR to NEW
114 by backing up or outputting a carriage return and moving forward. CUR
115 and NEW are either both buffer positions or absolute screen positions. */
116 #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
117
118 /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
119 buffer index in others. This macro is used when deciding whether the
120 current cursor position is in the middle of a prompt string containing
121 invisible characters. XXX - might need to take `modmark' into account. */
122 /* XXX - only valid when tested against _rl_last_c_pos; buffer indices need
123 to use prompt_last_invisible directly. */
124 #define PROMPT_ENDING_INDEX \
125 ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
126
127
128 /* **************************************************************** */
129 /* */
130 /* Display stuff */
131 /* */
132 /* **************************************************************** */
133
134 /* This is the stuff that is hard for me. I never seem to write good
135 display routines in C. Let's see how I do this time. */
136
137 /* (PWP) Well... Good for a simple line updater, but totally ignores
138 the problems of input lines longer than the screen width.
139
140 update_line and the code that calls it makes a multiple line,
141 automatically wrapping line update. Careful attention needs
142 to be paid to the vertical position variables. */
143
144 /* Keep two buffers; one which reflects the current contents of the
145 screen, and the other to draw what we think the new contents should
146 be. Then compare the buffers, and make whatever changes to the
147 screen itself that we should. Finally, make the buffer that we
148 just drew into be the one which reflects the current contents of the
149 screen, and place the cursor where it belongs.
150
151 Commands that want to can fix the display themselves, and then let
152 this function know that the display has been fixed by setting the
153 RL_DISPLAY_FIXED variable. This is good for efficiency. */
154
155 /* Application-specific redisplay function. */
156 rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
157
158 /* Global variables declared here. */
159 /* What YOU turn on when you have handled all redisplay yourself. */
160 int rl_display_fixed = 0;
161
162 int _rl_suppress_redisplay = 0;
163 int _rl_want_redisplay = 0;
164
165 /* The stuff that gets printed out before the actual text of the line.
166 This is usually pointing to rl_prompt. */
167 char *rl_display_prompt = (char *)NULL;
168
169 /* Variables used to include the editing mode in the prompt. */
170 char *_rl_emacs_mode_str;
171 int _rl_emacs_modestr_len;
172
173 char *_rl_vi_ins_mode_str;
174 int _rl_vi_ins_modestr_len;
175
176 char *_rl_vi_cmd_mode_str;
177 int _rl_vi_cmd_modestr_len;
178
179 /* Pseudo-global variables declared here. */
180
181 /* The visible cursor position. If you print some text, adjust this. */
182 /* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
183 supporting multibyte characters, and an absolute cursor position when
184 in such a locale. This is an artifact of the donated multibyte support.
185 Care must be taken when modifying its value. */
186 int _rl_last_c_pos = 0;
187 int _rl_last_v_pos = 0;
188
189 static int cpos_adjusted;
190 static int cpos_buffer_position;
191 static int displaying_prompt_first_line;
192 static int prompt_multibyte_chars;
193
194 /* Number of lines currently on screen minus 1. */
195 int _rl_vis_botlin = 0;
196
197 static int _rl_inv_botlin = 0;
198
199 /* Variables used only in this file. */
200 /* The last left edge of text that was displayed. This is used when
201 doing horizontal scrolling. It shifts in thirds of a screenwidth. */
202 static int last_lmargin;
203
204 /* A buffer for `modeline' messages. */
205 static char *msg_buf = 0;
206 static int msg_bufsiz = 0;
207
208 /* Non-zero forces the redisplay even if we thought it was unnecessary. */
209 static int forced_display;
210
211 /* Default and initial buffer size. Can grow. */
212 static int line_size = 1024;
213
214 /* Variables to keep track of the expanded prompt string, which may
215 include invisible characters. */
216
217 static char *local_prompt, *local_prompt_prefix;
218 static int local_prompt_len;
219 static int prompt_visible_length, prompt_prefix_length;
220
221 /* The number of invisible characters in the line currently being
222 displayed on the screen. */
223 static int visible_wrap_offset;
224
225 /* The number of invisible characters in the prompt string. Static so it
226 can be shared between rl_redisplay and update_line */
227 static int wrap_offset;
228
229 /* The index of the last invisible character in the prompt string. */
230 static int prompt_last_invisible;
231
232 /* The length (buffer offset) of the first line of the last (possibly
233 multi-line) buffer displayed on the screen. */
234 static int visible_first_line_len;
235
236 /* Number of invisible characters on the first physical line of the prompt.
237 Only valid when the number of physical characters in the prompt exceeds
238 (or is equal to) _rl_screenwidth. */
239 static int prompt_invis_chars_first_line;
240
241 static int prompt_last_screen_line;
242
243 static int prompt_physical_chars;
244
245 /* set to a non-zero value by rl_redisplay if we are marking modified history
246 lines and the current line is so marked. */
247 static int modmark;
248
249 /* Variables to save and restore prompt and display information. */
250
251 /* These are getting numerous enough that it's time to create a struct. */
252
253 static char *saved_local_prompt;
254 static char *saved_local_prefix;
255 static int saved_last_invisible;
256 static int saved_visible_length;
257 static int saved_prefix_length;
258 static int saved_local_length;
259 static int saved_invis_chars_first_line;
260 static int saved_physical_chars;
261
262 /* Return a string indicating the editing mode, for use in the prompt. */
263
264 static char *
265 prompt_modestr (lenp)
266 int *lenp;
267 {
268 if (rl_editing_mode == emacs_mode)
269 {
270 if (lenp)
271 *lenp = _rl_emacs_mode_str ? _rl_emacs_modestr_len : RL_EMACS_MODESTR_DEFLEN;
272 return _rl_emacs_mode_str ? _rl_emacs_mode_str : RL_EMACS_MODESTR_DEFAULT;
273 }
274 else if (_rl_keymap == vi_insertion_keymap)
275 {
276 if (lenp)
277 *lenp = _rl_vi_ins_mode_str ? _rl_vi_ins_modestr_len : RL_VI_INS_MODESTR_DEFLEN;
278 return _rl_vi_ins_mode_str ? _rl_vi_ins_mode_str : RL_VI_INS_MODESTR_DEFAULT; /* vi insert mode */
279 }
280 else
281 {
282 if (lenp)
283 *lenp = _rl_vi_cmd_mode_str ? _rl_vi_cmd_modestr_len : RL_VI_CMD_MODESTR_DEFLEN;
284 return _rl_vi_cmd_mode_str ? _rl_vi_cmd_mode_str : RL_VI_CMD_MODESTR_DEFAULT; /* vi command mode */
285 }
286 }
287
288 /* Expand the prompt string S and return the number of visible
289 characters in *LP, if LP is not null. This is currently more-or-less
290 a placeholder for expansion. LIP, if non-null is a place to store the
291 index of the last invisible character in the returned string. NIFLP,
292 if non-zero, is a place to store the number of invisible characters in
293 the first prompt line. The previous are used as byte counts -- indexes
294 into a character buffer. */
295
296 /* Current implementation:
297 \001 (^A) start non-visible characters
298 \002 (^B) end non-visible characters
299 all characters except \001 and \002 (following a \001) are copied to
300 the returned string; all characters except those between \001 and
301 \002 are assumed to be `visible'. */
302
303 /* Possible values for FLAGS:
304 PMT_MULTILINE caller indicates that this is part of a multiline prompt
305 */
306
307 static char *
308 expand_prompt (pmt, flags, lp, lip, niflp, vlp)
309 char *pmt;
310 int flags;
311 int *lp, *lip, *niflp, *vlp;
312 {
313 char *r, *ret, *p, *igstart, *nprompt, *ms;
314 int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
315 int mlen;
316
317 /* We only expand the mode string for the last line of a multiline prompt
318 (a prompt with embedded newlines). */
319 ms = (((pmt == rl_prompt) ^ (flags & PMT_MULTILINE)) && _rl_show_mode_in_prompt) ? prompt_modestr (&mlen) : 0;
320 if (ms)
321 {
322 l = strlen (pmt);
323 nprompt = (char *)xmalloc (l + mlen + 1);
324 memcpy (nprompt, ms, mlen);
325 strcpy (nprompt + mlen, pmt);
326 }
327 else
328 nprompt = pmt;
329
330 /* Short-circuit if we can. */
331 if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (nprompt, RL_PROMPT_START_IGNORE) == 0)
332 {
333 r = (nprompt == pmt) ? savestring (pmt) : nprompt;
334
335 if (lp)
336 *lp = strlen (r);
337 if (lip)
338 *lip = 0;
339 if (niflp)
340 *niflp = 0;
341 if (vlp)
342 *vlp = lp ? *lp : strlen (r);
343 return r;
344 }
345
346 l = strlen (nprompt); /* XXX */
347 r = ret = (char *)xmalloc (l + 1);
348
349 rl = physchars = 0; /* mode string now part of nprompt */
350 invfl = 0; /* invisible chars in first line of prompt */
351 invflset = 0; /* we only want to set invfl once */
352 igstart = 0;
353
354 for (ignoring = last = ninvis = 0, p = nprompt; p && *p; p++)
355 {
356 /* This code strips the invisible character string markers
357 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
358 if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
359 {
360 ignoring = 1;
361 igstart = p;
362 continue;
363 }
364 else if (ignoring && *p == RL_PROMPT_END_IGNORE)
365 {
366 ignoring = 0;
367 if (p != (igstart + 1))
368 last = r - ret - 1;
369 continue;
370 }
371 else
372 {
373 #if defined (HANDLE_MULTIBYTE)
374 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
375 {
376 pind = p - nprompt;
377 ind = _rl_find_next_mbchar (nprompt, pind, 1, MB_FIND_NONZERO);
378 l = ind - pind;
379 while (l--)
380 *r++ = *p++;
381 if (!ignoring)
382 {
383 /* rl ends up being assigned to prompt_visible_length,
384 which is the number of characters in the buffer that
385 contribute to characters on the screen, which might
386 not be the same as the number of physical characters
387 on the screen in the presence of multibyte characters */
388 rl += ind - pind;
389 physchars += _rl_col_width (nprompt, pind, ind, 0);
390 }
391 else
392 ninvis += ind - pind;
393 p--; /* compensate for later increment */
394 }
395 else
396 #endif
397 {
398 *r++ = *p;
399 if (!ignoring)
400 {
401 rl++; /* visible length byte counter */
402 physchars++;
403 }
404 else
405 ninvis++; /* invisible chars byte counter */
406 }
407
408 if (invflset == 0 && rl >= _rl_screenwidth)
409 {
410 invfl = ninvis;
411 invflset = 1;
412 }
413 }
414 }
415
416 if (rl < _rl_screenwidth)
417 invfl = ninvis;
418
419 *r = '\0';
420 if (lp)
421 *lp = rl;
422 if (lip)
423 *lip = last;
424 if (niflp)
425 *niflp = invfl;
426 if (vlp)
427 *vlp = physchars;
428
429 if (nprompt != pmt)
430 free (nprompt);
431
432 return ret;
433 }
434
435 /* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
436 PMT and return the rest of PMT. */
437 char *
438 _rl_strip_prompt (pmt)
439 char *pmt;
440 {
441 char *ret;
442
443 ret = expand_prompt (pmt, 0, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
444 return ret;
445 }
446
447 void
448 _rl_reset_prompt ()
449 {
450 rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
451 }
452
453 /*
454 * Expand the prompt string into the various display components, if
455 * necessary.
456 *
457 * local_prompt = expanded last line of string in rl_display_prompt
458 * (portion after the final newline)
459 * local_prompt_prefix = portion before last newline of rl_display_prompt,
460 * expanded via expand_prompt
461 * prompt_visible_length = number of visible characters in local_prompt
462 * prompt_prefix_length = number of visible characters in local_prompt_prefix
463 *
464 * This function is called once per call to readline(). It may also be
465 * called arbitrarily to expand the primary prompt.
466 *
467 * The return value is the number of visible characters on the last line
468 * of the (possibly multi-line) prompt.
469 */
470 int
471 rl_expand_prompt (prompt)
472 char *prompt;
473 {
474 char *p, *t;
475 int c;
476
477 /* Clear out any saved values. */
478 FREE (local_prompt);
479 FREE (local_prompt_prefix);
480
481 local_prompt = local_prompt_prefix = (char *)0;
482 local_prompt_len = 0;
483 prompt_last_invisible = prompt_invis_chars_first_line = 0;
484 prompt_visible_length = prompt_physical_chars = 0;
485
486 if (prompt == 0 || *prompt == 0)
487 return (0);
488
489 p = strrchr (prompt, '\n');
490 if (p == 0)
491 {
492 /* The prompt is only one logical line, though it might wrap. */
493 local_prompt = expand_prompt (prompt, 0, &prompt_visible_length,
494 &prompt_last_invisible,
495 &prompt_invis_chars_first_line,
496 &prompt_physical_chars);
497 local_prompt_prefix = (char *)0;
498 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
499 return (prompt_visible_length);
500 }
501 else
502 {
503 /* The prompt spans multiple lines. */
504 t = ++p;
505 local_prompt = expand_prompt (p, PMT_MULTILINE,
506 &prompt_visible_length,
507 &prompt_last_invisible,
508 &prompt_invis_chars_first_line,
509 &prompt_physical_chars);
510 c = *t; *t = '\0';
511 /* The portion of the prompt string up to and including the
512 final newline is now null-terminated. */
513 local_prompt_prefix = expand_prompt (prompt, PMT_MULTILINE,
514 &prompt_prefix_length,
515 (int *)NULL,
516 (int *)NULL,
517 (int *)NULL);
518 *t = c;
519 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
520 return (prompt_prefix_length);
521 }
522 }
523
524 /* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
525 arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
526 and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
527 increased. If the lines have already been allocated, this ensures that
528 they can hold at least MINSIZE characters. */
529 static void
530 init_line_structures (minsize)
531 int minsize;
532 {
533 register int n;
534
535 if (minsize <= _rl_screenwidth) /* XXX - for gdb */
536 minsize = _rl_screenwidth + 1;
537
538 if (invisible_line == 0) /* initialize it */
539 {
540 if (line_size < minsize)
541 line_size = minsize;
542 visible_line = (char *)xmalloc (line_size);
543 invisible_line = (char *)xmalloc (line_size);
544 }
545 else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
546 {
547 line_size *= 2;
548 if (line_size < minsize)
549 line_size = minsize;
550 visible_line = (char *)xrealloc (visible_line, line_size);
551 invisible_line = (char *)xrealloc (invisible_line, line_size);
552 }
553
554 for (n = minsize; n < line_size; n++)
555 {
556 visible_line[n] = 0;
557 invisible_line[n] = 1;
558 }
559
560 if (vis_lbreaks == 0)
561 {
562 /* should be enough. */
563 inv_lbsize = vis_lbsize = 256;
564
565 #if defined (HANDLE_MULTIBYTE)
566 line_state_visible->wbsize = vis_lbsize;
567 line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
568
569 line_state_invisible->wbsize = inv_lbsize;
570 line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
571 #endif
572
573 inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
574 vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
575 inv_lbreaks[0] = vis_lbreaks[0] = 0;
576 }
577
578 line_structures_initialized = 1;
579 }
580
581 /* Basic redisplay algorithm. */
582 void
583 rl_redisplay ()
584 {
585 register int in, out, c, linenum, cursor_linenum;
586 register char *line;
587 int inv_botlin, lb_botlin, lb_linenum, o_cpos;
588 int newlines, lpos, temp, n0, num, prompt_lines_estimate;
589 char *prompt_this_line;
590 int mb_cur_max = MB_CUR_MAX;
591 #if defined (HANDLE_MULTIBYTE)
592 wchar_t wc;
593 size_t wc_bytes;
594 int wc_width;
595 mbstate_t ps;
596 int _rl_wrapped_multicolumn = 0;
597 #endif
598
599 if (_rl_echoing_p == 0)
600 return;
601
602 /* Block keyboard interrupts because this function manipulates global
603 data structures. */
604 _rl_block_sigint ();
605 RL_SETSTATE (RL_STATE_REDISPLAYING);
606
607 if (!rl_display_prompt)
608 rl_display_prompt = "";
609
610 if (line_structures_initialized == 0)
611 {
612 init_line_structures (0);
613 rl_on_new_line ();
614 }
615 else if (line_size <= _rl_screenwidth)
616 init_line_structures (_rl_screenwidth + 1);
617
618 /* Draw the line into the buffer. */
619 cpos_buffer_position = -1;
620
621 prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
622
623 line = invisible_line;
624 out = inv_botlin = 0;
625
626 /* Mark the line as modified or not. We only do this for history
627 lines. */
628 modmark = 0;
629 if (_rl_mark_modified_lines && current_history () && rl_undo_list)
630 {
631 line[out++] = '*';
632 line[out] = '\0';
633 modmark = 1;
634 }
635
636 /* If someone thought that the redisplay was handled, but the currently
637 visible line has a different modification state than the one about
638 to become visible, then correct the caller's misconception. */
639 if (visible_line[0] != invisible_line[0])
640 rl_display_fixed = 0;
641
642 /* If the prompt to be displayed is the `primary' readline prompt (the
643 one passed to readline()), use the values we have already expanded.
644 If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
645 number of non-visible characters in the prompt string. */
646 if (rl_display_prompt == rl_prompt || local_prompt)
647 {
648 if (local_prompt_prefix && forced_display)
649 _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
650
651 if (local_prompt_len > 0)
652 {
653 temp = local_prompt_len + out + 2;
654 if (temp >= line_size)
655 {
656 line_size = (temp + 1024) - (temp % 1024);
657 visible_line = (char *)xrealloc (visible_line, line_size);
658 line = invisible_line = (char *)xrealloc (invisible_line, line_size);
659 }
660 strncpy (line + out, local_prompt, local_prompt_len);
661 out += local_prompt_len;
662 }
663 line[out] = '\0';
664 wrap_offset = local_prompt_len - prompt_visible_length;
665 }
666 else
667 {
668 int pmtlen;
669 prompt_this_line = strrchr (rl_display_prompt, '\n');
670 if (!prompt_this_line)
671 prompt_this_line = rl_display_prompt;
672 else
673 {
674 prompt_this_line++;
675 pmtlen = prompt_this_line - rl_display_prompt; /* temp var */
676 if (forced_display)
677 {
678 _rl_output_some_chars (rl_display_prompt, pmtlen);
679 /* Make sure we are at column zero even after a newline,
680 regardless of the state of terminal output processing. */
681 if (pmtlen < 2 || prompt_this_line[-2] != '\r')
682 cr ();
683 }
684 }
685
686 prompt_physical_chars = pmtlen = strlen (prompt_this_line);
687 temp = pmtlen + out + 2;
688 if (temp >= line_size)
689 {
690 line_size = (temp + 1024) - (temp % 1024);
691 visible_line = (char *)xrealloc (visible_line, line_size);
692 line = invisible_line = (char *)xrealloc (invisible_line, line_size);
693 }
694 strncpy (line + out, prompt_this_line, pmtlen);
695 out += pmtlen;
696 line[out] = '\0';
697 wrap_offset = prompt_invis_chars_first_line = 0;
698 }
699
700 #define CHECK_INV_LBREAKS() \
701 do { \
702 if (newlines >= (inv_lbsize - 2)) \
703 { \
704 inv_lbsize *= 2; \
705 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
706 } \
707 } while (0)
708
709 #if defined (HANDLE_MULTIBYTE)
710 #define CHECK_LPOS() \
711 do { \
712 lpos++; \
713 if (lpos >= _rl_screenwidth) \
714 { \
715 if (newlines >= (inv_lbsize - 2)) \
716 { \
717 inv_lbsize *= 2; \
718 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
719 } \
720 inv_lbreaks[++newlines] = out; \
721 if (newlines >= (line_state_invisible->wbsize - 1)) \
722 { \
723 line_state_invisible->wbsize *= 2; \
724 line_state_invisible->wrapped_line = (int *)xrealloc (line_state_invisible->wrapped_line, line_state_invisible->wbsize * sizeof(int)); \
725 } \
726 line_state_invisible->wrapped_line[newlines] = _rl_wrapped_multicolumn; \
727 lpos = 0; \
728 } \
729 } while (0)
730 #else
731 #define CHECK_LPOS() \
732 do { \
733 lpos++; \
734 if (lpos >= _rl_screenwidth) \
735 { \
736 if (newlines >= (inv_lbsize - 2)) \
737 { \
738 inv_lbsize *= 2; \
739 inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
740 } \
741 inv_lbreaks[++newlines] = out; \
742 lpos = 0; \
743 } \
744 } while (0)
745 #endif
746
747 /* inv_lbreaks[i] is where line i starts in the buffer. */
748 inv_lbreaks[newlines = 0] = 0;
749 /* lpos is a physical cursor position, so it needs to be adjusted by the
750 number of invisible characters in the prompt, per line */
751 lpos = prompt_physical_chars + modmark;
752
753 #if defined (HANDLE_MULTIBYTE)
754 memset (line_state_invisible->wrapped_line, 0, line_state_invisible->wbsize * sizeof (int));
755 num = 0;
756 #endif
757
758 /* prompt_invis_chars_first_line is the number of invisible characters in
759 the first physical line of the prompt.
760 wrap_offset - prompt_invis_chars_first_line is the number of invis
761 chars on the second (or, more generally, last) line. */
762
763 /* This is zero-based, used to set the newlines */
764 prompt_lines_estimate = lpos / _rl_screenwidth;
765
766 /* what if lpos is already >= _rl_screenwidth before we start drawing the
767 contents of the command line? */
768 while (lpos >= _rl_screenwidth)
769 {
770 int z, p;
771 int nocorrect, wadjust;
772
773 nocorrect = 0;
774 /* Adjust depending on the invisible characters in the line. We use a
775 heuristic based on experience: invisible characters nearly always
776 appear in the first and last lines of the prompt */
777 wadjust = (newlines == 0)
778 ? prompt_invis_chars_first_line
779 : ((newlines == prompt_lines_estimate)
780 ? (wrap_offset - prompt_invis_chars_first_line)
781 : 0);
782
783 /* fix from Darin Johnson <darin@acuson.com> for prompt string with
784 invisible characters that is longer than the screen width. The
785 prompt_invis_chars_first_line variable could be made into an array
786 saying how many invisible characters there are per line, but that's
787 probably too much work for the benefit gained. How many people have
788 prompts that exceed two physical lines?
789 Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
790 #if defined (HANDLE_MULTIBYTE)
791 if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
792 {
793 nocorrect = 1;
794 n0 = num;
795 temp = local_prompt_len;
796 while (num < temp)
797 {
798 /* This has to take invisible characters in the prompt into
799 account. */
800 z = _rl_col_width (local_prompt, n0, num, 1) - wadjust;
801 if (z > _rl_screenwidth)
802 {
803 num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
804 break;
805 }
806 else if (z == _rl_screenwidth)
807 {
808 /* If we are in the middle or at the end of a multibyte
809 character, we want to move to the start, then find out
810 where it ends so we know where to insert the newline.
811 If this isn't a multibyte character, its the same as num++ */
812 p = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
813 num = _rl_find_next_mbchar (local_prompt, p, 1, MB_FIND_ANY);
814 break;
815 }
816 num++;
817 }
818 temp = num;
819 }
820 else
821 #endif /* !HANDLE_MULTIBYTE */
822 temp = ((newlines + 1) * _rl_screenwidth);
823
824 /* Now account for invisible characters in the current line. */
825 /* XXX - this assumes that the invisible characters may be split, but only
826 between the first and the last lines. */
827 if (nocorrect == 0)
828 temp += wadjust;
829
830 inv_lbreaks[++newlines] = temp;
831 #if defined (HANDLE_MULTIBYTE)
832 /* lpos is a physical cursor position, so it needs to take the invisible
833 characters into account. */
834 if (mb_cur_max > 1 && rl_byte_oriented == 0 && prompt_multibyte_chars > 0)
835 lpos -= _rl_col_width (local_prompt, n0, num, 1) - wadjust;
836 else
837 #endif
838 lpos -= _rl_screenwidth; /* all physical cursor positions */
839 }
840
841 prompt_last_screen_line = newlines;
842
843 /* Draw the rest of the line (after the prompt) into invisible_line, keeping
844 track of where the cursor is (cpos_buffer_position), the number of the line containing
845 the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
846 It maintains an array of line breaks for display (inv_lbreaks).
847 This handles expanding tabs for display and displaying meta characters. */
848 lb_linenum = 0;
849 #if defined (HANDLE_MULTIBYTE)
850 in = 0;
851 if (mb_cur_max > 1 && rl_byte_oriented == 0)
852 {
853 memset (&ps, 0, sizeof (mbstate_t));
854 /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
855 wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
856 }
857 else
858 wc_bytes = 1;
859 while (in < rl_end)
860 #else
861 for (in = 0; in < rl_end; in++)
862 #endif
863 {
864 c = (unsigned char)rl_line_buffer[in];
865
866 #if defined (HANDLE_MULTIBYTE)
867 if (mb_cur_max > 1 && rl_byte_oriented == 0)
868 {
869 if (MB_INVALIDCH (wc_bytes))
870 {
871 /* Byte sequence is invalid or shortened. Assume that the
872 first byte represents a character. */
873 wc_bytes = 1;
874 /* Assume that a character occupies a single column. */
875 wc_width = 1;
876 memset (&ps, 0, sizeof (mbstate_t));
877 }
878 else if (MB_NULLWCH (wc_bytes))
879 break; /* Found '\0' */
880 else
881 {
882 temp = WCWIDTH (wc);
883 wc_width = (temp >= 0) ? temp : 1;
884 }
885 }
886 #endif
887
888 if (out + 8 >= line_size) /* XXX - 8 for \t */
889 {
890 line_size *= 2;
891 visible_line = (char *)xrealloc (visible_line, line_size);
892 invisible_line = (char *)xrealloc (invisible_line, line_size);
893 line = invisible_line;
894 }
895
896 if (in == rl_point)
897 {
898 cpos_buffer_position = out;
899 lb_linenum = newlines;
900 }
901
902 #if defined (HANDLE_MULTIBYTE)
903 if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
904 #else
905 if (META_CHAR (c))
906 #endif
907 {
908 if (_rl_output_meta_chars == 0)
909 {
910 sprintf (line + out, "\\%o", c);
911
912 if (lpos + 4 >= _rl_screenwidth)
913 {
914 temp = _rl_screenwidth - lpos;
915 CHECK_INV_LBREAKS ();
916 inv_lbreaks[++newlines] = out + temp;
917 lpos = 4 - temp;
918 }
919 else
920 lpos += 4;
921
922 out += 4;
923 }
924 else
925 {
926 line[out++] = c;
927 CHECK_LPOS();
928 }
929 }
930 #if defined (DISPLAY_TABS)
931 else if (c == '\t')
932 {
933 register int newout;
934
935 #if 0
936 newout = (out | (int)7) + 1;
937 #else
938 newout = out + 8 - lpos % 8;
939 #endif
940 temp = newout - out;
941 if (lpos + temp >= _rl_screenwidth)
942 {
943 register int temp2;
944 temp2 = _rl_screenwidth - lpos;
945 CHECK_INV_LBREAKS ();
946 inv_lbreaks[++newlines] = out + temp2;
947 lpos = temp - temp2;
948 while (out < newout)
949 line[out++] = ' ';
950 }
951 else
952 {
953 while (out < newout)
954 line[out++] = ' ';
955 lpos += temp;
956 }
957 }
958 #endif
959 else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
960 {
961 line[out++] = '\0'; /* XXX - sentinel */
962 CHECK_INV_LBREAKS ();
963 inv_lbreaks[++newlines] = out;
964 lpos = 0;
965 }
966 else if (CTRL_CHAR (c) || c == RUBOUT)
967 {
968 line[out++] = '^';
969 CHECK_LPOS();
970 line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
971 CHECK_LPOS();
972 }
973 else
974 {
975 #if defined (HANDLE_MULTIBYTE)
976 if (mb_cur_max > 1 && rl_byte_oriented == 0)
977 {
978 register int i;
979
980 _rl_wrapped_multicolumn = 0;
981
982 if (_rl_screenwidth < lpos + wc_width)
983 for (i = lpos; i < _rl_screenwidth; i++)
984 {
985 /* The space will be removed in update_line() */
986 line[out++] = ' ';
987 _rl_wrapped_multicolumn++;
988 CHECK_LPOS();
989 }
990 if (in == rl_point)
991 {
992 cpos_buffer_position = out;
993 lb_linenum = newlines;
994 }
995 for (i = in; i < in+wc_bytes; i++)
996 line[out++] = rl_line_buffer[i];
997 for (i = 0; i < wc_width; i++)
998 CHECK_LPOS();
999 }
1000 else
1001 {
1002 line[out++] = c;
1003 CHECK_LPOS();
1004 }
1005 #else
1006 line[out++] = c;
1007 CHECK_LPOS();
1008 #endif
1009 }
1010
1011 #if defined (HANDLE_MULTIBYTE)
1012 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1013 {
1014 in += wc_bytes;
1015 /* XXX - what if wc_bytes ends up <= 0? check for MB_INVALIDCH */
1016 wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
1017 }
1018 else
1019 in++;
1020 #endif
1021
1022 }
1023 line[out] = '\0';
1024 if (cpos_buffer_position < 0)
1025 {
1026 cpos_buffer_position = out;
1027 lb_linenum = newlines;
1028 }
1029
1030 inv_botlin = lb_botlin = _rl_inv_botlin = newlines;
1031 CHECK_INV_LBREAKS ();
1032 inv_lbreaks[newlines+1] = out;
1033 cursor_linenum = lb_linenum;
1034
1035 /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
1036 CURSOR_LINENUM == line number where the cursor should be placed. */
1037
1038 /* PWP: now is when things get a bit hairy. The visible and invisible
1039 line buffers are really multiple lines, which would wrap every
1040 (screenwidth - 1) characters. Go through each in turn, finding
1041 the changed region and updating it. The line order is top to bottom. */
1042
1043 /* If we can move the cursor up and down, then use multiple lines,
1044 otherwise, let long lines display in a single terminal line, and
1045 horizontally scroll it. */
1046 displaying_prompt_first_line = 1;
1047 if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
1048 {
1049 int nleft, pos, changed_screen_line, tx;
1050
1051 if (!rl_display_fixed || forced_display)
1052 {
1053 forced_display = 0;
1054
1055 /* If we have more than a screenful of material to display, then
1056 only display a screenful. We should display the last screen,
1057 not the first. */
1058 if (out >= _rl_screenchars)
1059 {
1060 #if defined (HANDLE_MULTIBYTE)
1061 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1062 out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
1063 else
1064 #endif
1065 out = _rl_screenchars - 1;
1066 }
1067
1068 /* The first line is at character position 0 in the buffer. The
1069 second and subsequent lines start at inv_lbreaks[N], offset by
1070 OFFSET (which has already been calculated above). */
1071
1072 #define INVIS_FIRST() (prompt_physical_chars > _rl_screenwidth ? prompt_invis_chars_first_line : wrap_offset)
1073 #define WRAP_OFFSET(line, offset) ((line == 0) \
1074 ? (offset ? INVIS_FIRST() : 0) \
1075 : ((line == prompt_last_screen_line) ? wrap_offset-prompt_invis_chars_first_line : 0))
1076 #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
1077 #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
1078 #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
1079 #define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
1080 #define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
1081 #define INV_LINE(line) (invisible_line + inv_lbreaks[line])
1082
1083 #define OLD_CPOS_IN_PROMPT() (cpos_adjusted == 0 && \
1084 _rl_last_c_pos != o_cpos && \
1085 _rl_last_c_pos > wrap_offset && \
1086 o_cpos < prompt_last_invisible)
1087
1088 /* For each line in the buffer, do the updating display. */
1089 for (linenum = 0; linenum <= inv_botlin; linenum++)
1090 {
1091 /* This can lead us astray if we execute a program that changes
1092 the locale from a non-multibyte to a multibyte one. */
1093 o_cpos = _rl_last_c_pos;
1094 cpos_adjusted = 0;
1095 update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
1096 VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
1097
1098 /* update_line potentially changes _rl_last_c_pos, but doesn't
1099 take invisible characters into account, since _rl_last_c_pos
1100 is an absolute cursor position in a multibyte locale. See
1101 if compensating here is the right thing, or if we have to
1102 change update_line itself. There are several cases in which
1103 update_line adjusts _rl_last_c_pos itself (so it can pass
1104 _rl_move_cursor_relative accurate values); it communicates
1105 this back by setting cpos_adjusted. If we assume that
1106 _rl_last_c_pos is correct (an absolute cursor position) each
1107 time update_line is called, then we can assume in our
1108 calculations that o_cpos does not need to be adjusted by
1109 wrap_offset. */
1110 if (linenum == 0 && (mb_cur_max > 1 && rl_byte_oriented == 0) && OLD_CPOS_IN_PROMPT())
1111 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1112 else if (linenum == prompt_last_screen_line && prompt_physical_chars > _rl_screenwidth &&
1113 (mb_cur_max > 1 && rl_byte_oriented == 0) &&
1114 cpos_adjusted == 0 &&
1115 _rl_last_c_pos != o_cpos &&
1116 _rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
1117 _rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
1118
1119 /* If this is the line with the prompt, we might need to
1120 compensate for invisible characters in the new line. Do
1121 this only if there is not more than one new line (which
1122 implies that we completely overwrite the old visible line)
1123 and the new line is shorter than the old. Make sure we are
1124 at the end of the new line before clearing. */
1125 if (linenum == 0 &&
1126 inv_botlin == 0 && _rl_last_c_pos == out &&
1127 (wrap_offset > visible_wrap_offset) &&
1128 (_rl_last_c_pos < visible_first_line_len))
1129 {
1130 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1131 nleft = _rl_screenwidth - _rl_last_c_pos;
1132 else
1133 nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
1134 if (nleft)
1135 _rl_clear_to_eol (nleft);
1136 }
1137 #if 0
1138 /* This segment is intended to handle the case where the prompt
1139 has invisible characters on the second line and the new line
1140 to be displayed needs to clear the rest of the old characters
1141 out (e.g., when printing the i-search prompt). In general,
1142 the case of the new line being shorter than the old.
1143 Incomplete */
1144 else if (linenum == prompt_last_screen_line &&
1145 prompt_physical_chars > _rl_screenwidth &&
1146 wrap_offset != prompt_invis_chars_first_line &&
1147 _rl_last_c_pos == out &&
1148 #endif
1149
1150
1151 /* Since the new first line is now visible, save its length. */
1152 if (linenum == 0)
1153 visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
1154 }
1155
1156 /* We may have deleted some lines. If so, clear the left over
1157 blank ones at the bottom out. */
1158 if (_rl_vis_botlin > inv_botlin)
1159 {
1160 char *tt;
1161 for (; linenum <= _rl_vis_botlin; linenum++)
1162 {
1163 tt = VIS_CHARS (linenum);
1164 _rl_move_vert (linenum);
1165 _rl_move_cursor_relative (0, tt);
1166 _rl_clear_to_eol
1167 ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
1168 }
1169 }
1170 _rl_vis_botlin = inv_botlin;
1171
1172 /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
1173 different screen line during this redisplay. */
1174 changed_screen_line = _rl_last_v_pos != cursor_linenum;
1175 if (changed_screen_line)
1176 {
1177 _rl_move_vert (cursor_linenum);
1178 /* If we moved up to the line with the prompt using _rl_term_up,
1179 the physical cursor position on the screen stays the same,
1180 but the buffer position needs to be adjusted to account
1181 for invisible characters. */
1182 if ((mb_cur_max == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
1183 _rl_last_c_pos += wrap_offset;
1184 }
1185
1186 /* We have to reprint the prompt if it contains invisible
1187 characters, since it's not generally OK to just reprint
1188 the characters from the current cursor position. But we
1189 only need to reprint it if the cursor is before the last
1190 invisible character in the prompt string. */
1191 nleft = prompt_visible_length + wrap_offset;
1192 if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
1193 #if 0
1194 _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
1195 #else
1196 _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
1197 #endif
1198 {
1199 #if defined (__MSDOS__)
1200 putc ('\r', rl_outstream);
1201 #else
1202 if (_rl_term_cr)
1203 tputs (_rl_term_cr, 1, _rl_output_character_function);
1204 #endif
1205 if (modmark)
1206 _rl_output_some_chars ("*", 1);
1207
1208 _rl_output_some_chars (local_prompt, nleft);
1209 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1210 _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft, 1) - wrap_offset + modmark;
1211 else
1212 _rl_last_c_pos = nleft + modmark;
1213 }
1214
1215 /* Where on that line? And where does that line start
1216 in the buffer? */
1217 pos = inv_lbreaks[cursor_linenum];
1218 /* nleft == number of characters in the line buffer between the
1219 start of the line and the desired cursor position. */
1220 nleft = cpos_buffer_position - pos;
1221
1222 /* NLEFT is now a number of characters in a buffer. When in a
1223 multibyte locale, however, _rl_last_c_pos is an absolute cursor
1224 position that doesn't take invisible characters in the prompt
1225 into account. We use a fudge factor to compensate. */
1226
1227 /* Since _rl_backspace() doesn't know about invisible characters in the
1228 prompt, and there's no good way to tell it, we compensate for
1229 those characters here and call _rl_backspace() directly. */
1230 if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
1231 {
1232 /* TX == new physical cursor position in multibyte locale. */
1233 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1234 tx = _rl_col_width (&visible_line[pos], 0, nleft, 1) - visible_wrap_offset;
1235 else
1236 tx = nleft;
1237 if (tx >= 0 && _rl_last_c_pos > tx)
1238 {
1239 _rl_backspace (_rl_last_c_pos - tx); /* XXX */
1240 _rl_last_c_pos = tx;
1241 }
1242 }
1243
1244 /* We need to note that in a multibyte locale we are dealing with
1245 _rl_last_c_pos as an absolute cursor position, but moving to a
1246 point specified by a buffer position (NLEFT) that doesn't take
1247 invisible characters into account. */
1248 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1249 _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1250 else if (nleft != _rl_last_c_pos)
1251 _rl_move_cursor_relative (nleft, &invisible_line[pos]);
1252 }
1253 }
1254 else /* Do horizontal scrolling. */
1255 {
1256 #define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
1257 int lmargin, ndisp, nleft, phys_c_pos, t;
1258
1259 /* Always at top line. */
1260 _rl_last_v_pos = 0;
1261
1262 /* Compute where in the buffer the displayed line should start. This
1263 will be LMARGIN. */
1264
1265 /* The number of characters that will be displayed before the cursor. */
1266 ndisp = cpos_buffer_position - wrap_offset;
1267 nleft = prompt_visible_length + wrap_offset;
1268 /* Where the new cursor position will be on the screen. This can be
1269 longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
1270 phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
1271 t = _rl_screenwidth / 3;
1272
1273 /* If the number of characters had already exceeded the screenwidth,
1274 last_lmargin will be > 0. */
1275
1276 /* If the number of characters to be displayed is more than the screen
1277 width, compute the starting offset so that the cursor is about
1278 two-thirds of the way across the screen. */
1279 if (phys_c_pos > _rl_screenwidth - 2)
1280 {
1281 lmargin = cpos_buffer_position - (2 * t);
1282 if (lmargin < 0)
1283 lmargin = 0;
1284 /* If the left margin would be in the middle of a prompt with
1285 invisible characters, don't display the prompt at all. */
1286 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1287 lmargin = nleft;
1288 }
1289 else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
1290 lmargin = 0;
1291 else if (phys_c_pos < 1)
1292 {
1293 /* If we are moving back towards the beginning of the line and
1294 the last margin is no longer correct, compute a new one. */
1295 lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */
1296 if (wrap_offset && lmargin > 0 && lmargin < nleft)
1297 lmargin = nleft;
1298 }
1299 else
1300 lmargin = last_lmargin;
1301
1302 displaying_prompt_first_line = lmargin < nleft;
1303
1304 /* If the first character on the screen isn't the first character
1305 in the display line, indicate this with a special character. */
1306 if (lmargin > 0)
1307 line[lmargin] = '<';
1308
1309 /* If SCREENWIDTH characters starting at LMARGIN do not encompass
1310 the whole line, indicate that with a special character at the
1311 right edge of the screen. If LMARGIN is 0, we need to take the
1312 wrap offset into account. */
1313 t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
1314 if (t < out)
1315 line[t - 1] = '>';
1316
1317 if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
1318 {
1319 forced_display = 0;
1320 o_cpos = _rl_last_c_pos;
1321 cpos_adjusted = 0;
1322 update_line (&visible_line[last_lmargin],
1323 &invisible_line[lmargin],
1324 0,
1325 _rl_screenwidth + visible_wrap_offset,
1326 _rl_screenwidth + (lmargin ? 0 : wrap_offset),
1327 0);
1328
1329 if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1330 displaying_prompt_first_line && OLD_CPOS_IN_PROMPT())
1331 _rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
1332
1333 /* If the visible new line is shorter than the old, but the number
1334 of invisible characters is greater, and we are at the end of
1335 the new line, we need to clear to eol. */
1336 t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
1337 if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
1338 (_rl_last_c_pos == out) && displaying_prompt_first_line &&
1339 t < visible_first_line_len)
1340 {
1341 nleft = _rl_screenwidth - t;
1342 _rl_clear_to_eol (nleft);
1343 }
1344 visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
1345 if (visible_first_line_len > _rl_screenwidth)
1346 visible_first_line_len = _rl_screenwidth;
1347
1348 _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
1349 last_lmargin = lmargin;
1350 }
1351 }
1352 fflush (rl_outstream);
1353
1354 /* Swap visible and non-visible lines. */
1355 {
1356 struct line_state *vtemp = line_state_visible;
1357
1358 line_state_visible = line_state_invisible;
1359 line_state_invisible = vtemp;
1360
1361 rl_display_fixed = 0;
1362 /* If we are displaying on a single line, and last_lmargin is > 0, we
1363 are not displaying any invisible characters, so set visible_wrap_offset
1364 to 0. */
1365 if (_rl_horizontal_scroll_mode && last_lmargin)
1366 visible_wrap_offset = 0;
1367 else
1368 visible_wrap_offset = wrap_offset;
1369 }
1370
1371 RL_UNSETSTATE (RL_STATE_REDISPLAYING);
1372 _rl_release_sigint ();
1373 }
1374
1375 /* PWP: update_line() is based on finding the middle difference of each
1376 line on the screen; vis:
1377
1378 /old first difference
1379 /beginning of line | /old last same /old EOL
1380 v v v v
1381 old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
1382 new: eddie> Oh, my little buggy says to me, as lurgid as
1383 ^ ^ ^ ^
1384 \beginning of line | \new last same \new end of line
1385 \new first difference
1386
1387 All are character pointers for the sake of speed. Special cases for
1388 no differences, as well as for end of line additions must be handled.
1389
1390 Could be made even smarter, but this works well enough */
1391 static void
1392 update_line (old, new, current_line, omax, nmax, inv_botlin)
1393 register char *old, *new;
1394 int current_line, omax, nmax, inv_botlin;
1395 {
1396 register char *ofd, *ols, *oe, *nfd, *nls, *ne;
1397 int temp, lendiff, wsatend, od, nd, twidth, o_cpos;
1398 int current_invis_chars;
1399 int col_lendiff, col_temp;
1400 int bytes_to_insert;
1401 int mb_cur_max = MB_CUR_MAX;
1402 #if defined (HANDLE_MULTIBYTE)
1403 mbstate_t ps_new, ps_old;
1404 int new_offset, old_offset;
1405 #endif
1406
1407 /* If we're at the right edge of a terminal that supports xn, we're
1408 ready to wrap around, so do so. This fixes problems with knowing
1409 the exact cursor position and cut-and-paste with certain terminal
1410 emulators. In this calculation, TEMP is the physical screen
1411 position of the cursor. */
1412 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1413 temp = _rl_last_c_pos;
1414 else
1415 temp = _rl_last_c_pos - WRAP_OFFSET (_rl_last_v_pos, visible_wrap_offset);
1416 if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
1417 && _rl_last_v_pos == current_line - 1)
1418 {
1419 #if defined (HANDLE_MULTIBYTE)
1420 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1421 {
1422 wchar_t wc;
1423 mbstate_t ps;
1424 int tempwidth, bytes;
1425 size_t ret;
1426
1427 /* This fixes only double-column characters, but if the wrapped
1428 character consumes more than three columns, spaces will be
1429 inserted in the string buffer. */
1430 if (current_line < line_state_visible->wbsize && line_state_visible->wrapped_line[current_line] > 0)
1431 _rl_clear_to_eol (line_state_visible->wrapped_line[current_line]);
1432
1433 memset (&ps, 0, sizeof (mbstate_t));
1434 ret = mbrtowc (&wc, new, mb_cur_max, &ps);
1435 if (MB_INVALIDCH (ret))
1436 {
1437 tempwidth = 1;
1438 ret = 1;
1439 }
1440 else if (MB_NULLWCH (ret))
1441 tempwidth = 0;
1442 else
1443 tempwidth = WCWIDTH (wc);
1444
1445 if (tempwidth > 0)
1446 {
1447 int count, i;
1448 bytes = ret;
1449 for (count = 0; count < bytes; count++)
1450 putc (new[count], rl_outstream);
1451 _rl_last_c_pos = tempwidth;
1452 _rl_last_v_pos++;
1453 memset (&ps, 0, sizeof (mbstate_t));
1454 ret = mbrtowc (&wc, old, mb_cur_max, &ps);
1455 if (ret != 0 && bytes != 0)
1456 {
1457 if (MB_INVALIDCH (ret))
1458 ret = 1;
1459 memmove (old+bytes, old+ret, strlen (old+ret));
1460 memcpy (old, new, bytes);
1461 /* Fix up indices if we copy data from one line to another */
1462 omax += bytes - ret;
1463 for (i = current_line+1; i <= inv_botlin+1; i++)
1464 vis_lbreaks[i] += bytes - ret;
1465 }
1466 }
1467 else
1468 {
1469 putc (' ', rl_outstream);
1470 _rl_last_c_pos = 1;
1471 _rl_last_v_pos++;
1472 if (old[0] && new[0])
1473 old[0] = new[0];
1474 }
1475 }
1476 else
1477 #endif
1478 {
1479 if (new[0])
1480 putc (new[0], rl_outstream);
1481 else
1482 putc (' ', rl_outstream);
1483 _rl_last_c_pos = 1;
1484 _rl_last_v_pos++;
1485 if (old[0] && new[0])
1486 old[0] = new[0];
1487 }
1488 }
1489
1490
1491 /* Find first difference. */
1492 #if defined (HANDLE_MULTIBYTE)
1493 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1494 {
1495 /* See if the old line is a subset of the new line, so that the
1496 only change is adding characters. */
1497 temp = (omax < nmax) ? omax : nmax;
1498 if (memcmp (old, new, temp) == 0) /* adding at the end */
1499 {
1500 new_offset = old_offset = temp;
1501 ofd = old + temp;
1502 nfd = new + temp;
1503 }
1504 else
1505 {
1506 memset (&ps_new, 0, sizeof(mbstate_t));
1507 memset (&ps_old, 0, sizeof(mbstate_t));
1508
1509 if (omax == nmax && STREQN (new, old, omax))
1510 {
1511 old_offset = omax;
1512 new_offset = nmax;
1513 ofd = old + omax;
1514 nfd = new + nmax;
1515 }
1516 else
1517 {
1518 new_offset = old_offset = 0;
1519 for (ofd = old, nfd = new;
1520 (ofd - old < omax) && *ofd &&
1521 _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
1522 {
1523 old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
1524 new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
1525
1526 ofd = old + old_offset;
1527 nfd = new + new_offset;
1528 }
1529 }
1530 }
1531 }
1532 else
1533 #endif
1534 for (ofd = old, nfd = new;
1535 (ofd - old < omax) && *ofd && (*ofd == *nfd);
1536 ofd++, nfd++)
1537 ;
1538
1539 /* Move to the end of the screen line. ND and OD are used to keep track
1540 of the distance between ne and new and oe and old, respectively, to
1541 move a subtraction out of each loop. */
1542 for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
1543 for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
1544
1545 /* If no difference, continue to next line. */
1546 if (ofd == oe && nfd == ne)
1547 return;
1548
1549 #if defined (HANDLE_MULTIBYTE)
1550 if (mb_cur_max > 1 && rl_byte_oriented == 0 && _rl_utf8locale)
1551 {
1552 wchar_t wc;
1553 mbstate_t ps = { 0 };
1554 int t;
1555
1556 /* If the first character in the difference is a zero-width character,
1557 assume it's a combining character and back one up so the two base
1558 characters no longer compare equivalently. */
1559 t = mbrtowc (&wc, ofd, mb_cur_max, &ps);
1560 if (t > 0 && UNICODE_COMBINING_CHAR (wc) && WCWIDTH (wc) == 0)
1561 {
1562 old_offset = _rl_find_prev_mbchar (old, ofd - old, MB_FIND_ANY);
1563 new_offset = _rl_find_prev_mbchar (new, nfd - new, MB_FIND_ANY);
1564 ofd = old + old_offset; /* equal by definition */
1565 nfd = new + new_offset;
1566 }
1567 }
1568 #endif
1569
1570 wsatend = 1; /* flag for trailing whitespace */
1571
1572 #if defined (HANDLE_MULTIBYTE)
1573 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1574 {
1575 ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
1576 nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
1577
1578 while ((ols > ofd) && (nls > nfd))
1579 {
1580 memset (&ps_old, 0, sizeof (mbstate_t));
1581 memset (&ps_new, 0, sizeof (mbstate_t));
1582
1583 #if 0
1584 /* On advice from jir@yamato.ibm.com */
1585 _rl_adjust_point (old, ols - old, &ps_old);
1586 _rl_adjust_point (new, nls - new, &ps_new);
1587 #endif
1588
1589 if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
1590 break;
1591
1592 if (*ols == ' ')
1593 wsatend = 0;
1594
1595 ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
1596 nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
1597 }
1598 }
1599 else
1600 {
1601 #endif /* HANDLE_MULTIBYTE */
1602 ols = oe - 1; /* find last same */
1603 nls = ne - 1;
1604 while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
1605 {
1606 if (*ols != ' ')
1607 wsatend = 0;
1608 ols--;
1609 nls--;
1610 }
1611 #if defined (HANDLE_MULTIBYTE)
1612 }
1613 #endif
1614
1615 if (wsatend)
1616 {
1617 ols = oe;
1618 nls = ne;
1619 }
1620 #if defined (HANDLE_MULTIBYTE)
1621 /* This may not work for stateful encoding, but who cares? To handle
1622 stateful encoding properly, we have to scan each string from the
1623 beginning and compare. */
1624 else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
1625 #else
1626 else if (*ols != *nls)
1627 #endif
1628 {
1629 if (*ols) /* don't step past the NUL */
1630 {
1631 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1632 ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
1633 else
1634 ols++;
1635 }
1636 if (*nls)
1637 {
1638 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1639 nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
1640 else
1641 nls++;
1642 }
1643 }
1644
1645 /* count of invisible characters in the current invisible line. */
1646 current_invis_chars = W_OFFSET (current_line, wrap_offset);
1647 if (_rl_last_v_pos != current_line)
1648 {
1649 _rl_move_vert (current_line);
1650 /* We have moved up to a new screen line. This line may or may not have
1651 invisible characters on it, but we do our best to recalculate
1652 visible_wrap_offset based on what we know. */
1653 if (current_line == 0)
1654 visible_wrap_offset = prompt_invis_chars_first_line; /* XXX */
1655 if ((mb_cur_max == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
1656 _rl_last_c_pos += visible_wrap_offset;
1657 }
1658
1659 /* If this is the first line and there are invisible characters in the
1660 prompt string, and the prompt string has not changed, and the current
1661 cursor position is before the last invisible character in the prompt,
1662 and the index of the character to move to is past the end of the prompt
1663 string, then redraw the entire prompt string. We can only do this
1664 reliably if the terminal supports a `cr' capability.
1665
1666 This can also happen if the prompt string has changed, and the first
1667 difference in the line is in the middle of the prompt string, after a
1668 sequence of invisible characters (worst case) and before the end of
1669 the prompt. In this case, we have to redraw the entire prompt string
1670 so that the entire sequence of invisible characters is drawn. We need
1671 to handle the worst case, when the difference is after (or in the middle
1672 of) a sequence of invisible characters that changes the text color and
1673 before the sequence that restores the text color to normal. Then we have
1674 to make sure that the lines still differ -- if they don't, we can
1675 return immediately.
1676
1677 This is not an efficiency hack -- there is a problem with redrawing
1678 portions of the prompt string if they contain terminal escape
1679 sequences (like drawing the `unbold' sequence without a corresponding
1680 `bold') that manifests itself on certain terminals. */
1681
1682 lendiff = local_prompt_len;
1683 if (lendiff > nmax)
1684 lendiff = nmax;
1685 od = ofd - old; /* index of first difference in visible line */
1686 nd = nfd - new; /* nd, od are buffer indexes */
1687 if (current_line == 0 && !_rl_horizontal_scroll_mode &&
1688 _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
1689 (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) ||
1690 ((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX)))
1691 {
1692 #if defined (__MSDOS__)
1693 putc ('\r', rl_outstream);
1694 #else
1695 tputs (_rl_term_cr, 1, _rl_output_character_function);
1696 #endif
1697 if (modmark)
1698 _rl_output_some_chars ("*", 1);
1699 _rl_output_some_chars (local_prompt, lendiff);
1700 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1701 {
1702 /* We take wrap_offset into account here so we can pass correct
1703 information to _rl_move_cursor_relative. */
1704 _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff, 1) - wrap_offset + modmark;
1705 cpos_adjusted = 1;
1706 }
1707 else
1708 _rl_last_c_pos = lendiff + modmark;
1709
1710 /* Now if we have printed the prompt string because the first difference
1711 was within the prompt, see if we need to recompute where the lines
1712 differ. Check whether where we are now is past the last place where
1713 the old and new lines are the same and short-circuit now if we are. */
1714 if ((od <= prompt_last_invisible || nd <= prompt_last_invisible) &&
1715 omax == nmax &&
1716 lendiff > (ols-old) && lendiff > (nls-new))
1717 return;
1718
1719 /* XXX - we need to fix up our calculations if we are now past the
1720 old ofd/nfd and the prompt length (or line length) has changed.
1721 We punt on the problem and do a dumb update. We'd like to be able
1722 to just output the prompt from the beginning of the line up to the
1723 first difference, but you don't know the number of invisible
1724 characters in that case.
1725 This needs a lot of work to be efficient. */
1726 if ((od <= prompt_last_invisible || nd <= prompt_last_invisible))
1727 {
1728 nfd = new + lendiff; /* number of characters we output above */
1729 nd = lendiff;
1730
1731 /* Do a dumb update and return */
1732 temp = ne - nfd;
1733 if (temp > 0)
1734 {
1735 _rl_output_some_chars (nfd, temp);
1736 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1737 _rl_last_c_pos += _rl_col_width (new, nd, ne - new, 1);
1738 else
1739 _rl_last_c_pos += temp;
1740 }
1741 if (nmax < omax)
1742 goto clear_rest_of_line; /* XXX */
1743 else
1744 return;
1745 }
1746 }
1747
1748 o_cpos = _rl_last_c_pos;
1749
1750 /* When this function returns, _rl_last_c_pos is correct, and an absolute
1751 cursor position in multibyte mode, but a buffer index when not in a
1752 multibyte locale. */
1753 _rl_move_cursor_relative (od, old);
1754
1755 #if defined (HANDLE_MULTIBYTE)
1756 /* We need to indicate that the cursor position is correct in the presence of
1757 invisible characters in the prompt string. Let's see if setting this when
1758 we make sure we're at the end of the drawn prompt string works. */
1759 if (current_line == 0 && mb_cur_max > 1 && rl_byte_oriented == 0 &&
1760 (_rl_last_c_pos > 0 || o_cpos > 0) &&
1761 _rl_last_c_pos == prompt_physical_chars)
1762 cpos_adjusted = 1;
1763 #endif
1764
1765 /* if (len (new) > len (old))
1766 lendiff == difference in buffer (bytes)
1767 col_lendiff == difference on screen (columns)
1768 When not using multibyte characters, these are equal */
1769 lendiff = (nls - nfd) - (ols - ofd);
1770 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1771 col_lendiff = _rl_col_width (new, nfd - new, nls - new, 1) - _rl_col_width (old, ofd - old, ols - old, 1);
1772 else
1773 col_lendiff = lendiff;
1774
1775 /* If we are changing the number of invisible characters in a line, and
1776 the spot of first difference is before the end of the invisible chars,
1777 lendiff needs to be adjusted. */
1778 if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */
1779 current_invis_chars != visible_wrap_offset)
1780 {
1781 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1782 {
1783 lendiff += visible_wrap_offset - current_invis_chars;
1784 col_lendiff += visible_wrap_offset - current_invis_chars;
1785 }
1786 else
1787 {
1788 lendiff += visible_wrap_offset - current_invis_chars;
1789 col_lendiff = lendiff;
1790 }
1791 }
1792
1793 /* We use temp as a count of the number of bytes from the first difference
1794 to the end of the new line. col_temp is the corresponding number of
1795 screen columns. A `dumb' update moves to the spot of first difference
1796 and writes TEMP bytes. */
1797 /* Insert (diff (len (old), len (new)) ch. */
1798 temp = ne - nfd;
1799 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1800 col_temp = _rl_col_width (new, nfd - new, ne - new, 1);
1801 else
1802 col_temp = temp;
1803
1804 /* how many bytes from the new line buffer to write to the display */
1805 bytes_to_insert = nls - nfd;
1806
1807 /* col_lendiff > 0 if we are adding characters to the line */
1808 if (col_lendiff > 0) /* XXX - was lendiff */
1809 {
1810 /* Non-zero if we're increasing the number of lines. */
1811 int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
1812 /* If col_lendiff is > 0, implying that the new string takes up more
1813 screen real estate than the old, but lendiff is < 0, meaning that it
1814 takes fewer bytes, we need to just output the characters starting
1815 from the first difference. These will overwrite what is on the
1816 display, so there's no reason to do a smart update. This can really
1817 only happen in a multibyte environment. */
1818 if (lendiff < 0)
1819 {
1820 _rl_output_some_chars (nfd, temp);
1821 _rl_last_c_pos += col_temp; /* XXX - was _rl_col_width (nfd, 0, temp, 1); */
1822 /* If nfd begins before any invisible characters in the prompt,
1823 adjust _rl_last_c_pos to account for wrap_offset and set
1824 cpos_adjusted to let the caller know. */
1825 if (current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1826 {
1827 _rl_last_c_pos -= wrap_offset;
1828 cpos_adjusted = 1;
1829 }
1830 return;
1831 }
1832 /* Sometimes it is cheaper to print the characters rather than
1833 use the terminal's capabilities. If we're growing the number
1834 of lines, make sure we actually cause the new line to wrap
1835 around on auto-wrapping terminals. */
1836 else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
1837 {
1838 /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
1839 _rl_horizontal_scroll_mode == 1, inserting the characters with
1840 _rl_term_IC or _rl_term_ic will screw up the screen because of the
1841 invisible characters. We need to just draw them. */
1842 /* The same thing happens if we're trying to draw before the last
1843 invisible character in the prompt string or we're increasing the
1844 number of invisible characters in the line and we're not drawing
1845 the entire prompt string. */
1846 if (*ols && ((_rl_horizontal_scroll_mode &&
1847 _rl_last_c_pos == 0 &&
1848 lendiff > prompt_visible_length &&
1849 current_invis_chars > 0) == 0) &&
1850 (((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1851 current_line == 0 && wrap_offset &&
1852 ((nfd - new) <= prompt_last_invisible) &&
1853 (col_lendiff < prompt_visible_length)) == 0) &&
1854 (visible_wrap_offset >= current_invis_chars))
1855 {
1856 open_some_spaces (col_lendiff);
1857 _rl_output_some_chars (nfd, bytes_to_insert);
1858 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1859 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
1860 else
1861 _rl_last_c_pos += bytes_to_insert;
1862 }
1863 else if ((mb_cur_max == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
1864 {
1865 /* At the end of a line the characters do not have to
1866 be "inserted". They can just be placed on the screen. */
1867 _rl_output_some_chars (nfd, temp);
1868 _rl_last_c_pos += col_temp;
1869 return;
1870 }
1871 else /* just write from first difference to end of new line */
1872 {
1873 _rl_output_some_chars (nfd, temp);
1874 _rl_last_c_pos += col_temp;
1875 /* If nfd begins before the last invisible character in the
1876 prompt, adjust _rl_last_c_pos to account for wrap_offset
1877 and set cpos_adjusted to let the caller know. */
1878 if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1879 {
1880 _rl_last_c_pos -= wrap_offset;
1881 cpos_adjusted = 1;
1882 }
1883 return;
1884 }
1885
1886 if (bytes_to_insert > lendiff)
1887 {
1888 /* If nfd begins before the last invisible character in the
1889 prompt, adjust _rl_last_c_pos to account for wrap_offset
1890 and set cpos_adjusted to let the caller know. */
1891 if ((mb_cur_max > 1 && rl_byte_oriented == 0) && current_line == 0 && displaying_prompt_first_line && wrap_offset && ((nfd - new) <= prompt_last_invisible))
1892 {
1893 _rl_last_c_pos -= wrap_offset;
1894 cpos_adjusted = 1;
1895 }
1896 }
1897 }
1898 else
1899 {
1900 /* cannot insert chars, write to EOL */
1901 _rl_output_some_chars (nfd, temp);
1902 _rl_last_c_pos += col_temp;
1903 /* If we're in a multibyte locale and were before the last invisible
1904 char in the current line (which implies we just output some invisible
1905 characters) we need to adjust _rl_last_c_pos, since it represents
1906 a physical character position. */
1907 /* The current_line*rl_screenwidth+prompt_invis_chars_first_line is a
1908 crude attempt to compute how far into the new line buffer we are.
1909 It doesn't work well in the face of multibyte characters and needs
1910 to be rethought. XXX */
1911 if ((mb_cur_max > 1 && rl_byte_oriented == 0) &&
1912 current_line == prompt_last_screen_line && wrap_offset &&
1913 displaying_prompt_first_line &&
1914 wrap_offset != prompt_invis_chars_first_line &&
1915 ((nfd-new) < (prompt_last_invisible-(current_line*_rl_screenwidth+prompt_invis_chars_first_line))))
1916 {
1917 _rl_last_c_pos -= wrap_offset - prompt_invis_chars_first_line;
1918 cpos_adjusted = 1;
1919 }
1920 }
1921 }
1922 else /* Delete characters from line. */
1923 {
1924 /* If possible and inexpensive to use terminal deletion, then do so. */
1925 if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
1926 {
1927 /* If all we're doing is erasing the invisible characters in the
1928 prompt string, don't bother. It screws up the assumptions
1929 about what's on the screen. */
1930 if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
1931 displaying_prompt_first_line &&
1932 -lendiff == visible_wrap_offset)
1933 col_lendiff = 0;
1934
1935 /* If we have moved lmargin and we're shrinking the line, we've
1936 already moved the cursor to the first character of the new line,
1937 so deleting -col_lendiff characters will mess up the cursor
1938 position calculation */
1939 if (_rl_horizontal_scroll_mode && displaying_prompt_first_line == 0 &&
1940 col_lendiff && _rl_last_c_pos < -col_lendiff)
1941 col_lendiff = 0;
1942
1943 if (col_lendiff)
1944 delete_chars (-col_lendiff); /* delete (diff) characters */
1945
1946 /* Copy (new) chars to screen from first diff to last match,
1947 overwriting what is there. */
1948 if (bytes_to_insert > 0)
1949 {
1950 /* If nfd begins at the prompt, or before the invisible
1951 characters in the prompt, we need to adjust _rl_last_c_pos
1952 in a multibyte locale to account for the wrap offset and
1953 set cpos_adjusted accordingly. */
1954 _rl_output_some_chars (nfd, bytes_to_insert);
1955 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1956 {
1957 _rl_last_c_pos += _rl_col_width (nfd, 0, bytes_to_insert, 1);
1958 if (current_line == 0 && wrap_offset &&
1959 displaying_prompt_first_line &&
1960 _rl_last_c_pos > wrap_offset &&
1961 ((nfd - new) <= prompt_last_invisible))
1962 {
1963 _rl_last_c_pos -= wrap_offset;
1964 cpos_adjusted = 1;
1965 }
1966 }
1967 else
1968 _rl_last_c_pos += bytes_to_insert;
1969
1970 /* XXX - we only want to do this if we are at the end of the line
1971 so we move there with _rl_move_cursor_relative */
1972 if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
1973 {
1974 _rl_move_cursor_relative (ne-new, new);
1975 goto clear_rest_of_line;
1976 }
1977 }
1978 }
1979 /* Otherwise, print over the existing material. */
1980 else
1981 {
1982 if (temp > 0)
1983 {
1984 /* If nfd begins at the prompt, or before the invisible
1985 characters in the prompt, we need to adjust _rl_last_c_pos
1986 in a multibyte locale to account for the wrap offset and
1987 set cpos_adjusted accordingly. */
1988 _rl_output_some_chars (nfd, temp);
1989 _rl_last_c_pos += col_temp; /* XXX */
1990 if (mb_cur_max > 1 && rl_byte_oriented == 0)
1991 {
1992 if (current_line == 0 && wrap_offset &&
1993 displaying_prompt_first_line &&
1994 _rl_last_c_pos > wrap_offset &&
1995 ((nfd - new) <= prompt_last_invisible))
1996 {
1997 _rl_last_c_pos -= wrap_offset;
1998 cpos_adjusted = 1;
1999 }
2000 }
2001 }
2002 clear_rest_of_line:
2003 lendiff = (oe - old) - (ne - new);
2004 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2005 col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
2006 else
2007 col_lendiff = lendiff;
2008
2009 /* If we've already printed over the entire width of the screen,
2010 including the old material, then col_lendiff doesn't matter and
2011 space_to_eol will insert too many spaces. XXX - maybe we should
2012 adjust col_lendiff based on the difference between _rl_last_c_pos
2013 and _rl_screenwidth */
2014 if (col_lendiff && ((mb_cur_max == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
2015 {
2016 if (_rl_term_autowrap && current_line < inv_botlin)
2017 space_to_eol (col_lendiff);
2018 else
2019 _rl_clear_to_eol (col_lendiff);
2020 }
2021 }
2022 }
2023 }
2024
2025 /* Tell the update routines that we have moved onto a new (empty) line. */
2026 int
2027 rl_on_new_line ()
2028 {
2029 if (visible_line)
2030 visible_line[0] = '\0';
2031
2032 _rl_last_c_pos = _rl_last_v_pos = 0;
2033 _rl_vis_botlin = last_lmargin = 0;
2034 if (vis_lbreaks)
2035 vis_lbreaks[0] = vis_lbreaks[1] = 0;
2036 visible_wrap_offset = 0;
2037 return 0;
2038 }
2039
2040 /* Clear all screen lines occupied by the current readline line buffer
2041 (visible line) */
2042 int
2043 rl_clear_visible_line ()
2044 {
2045 int curr_line;
2046
2047 /* Make sure we move to column 0 so we clear the entire line */
2048 #if defined (__MSDOS__)
2049 putc ('\r', rl_outstream);
2050 #else
2051 tputs (_rl_term_cr, 1, _rl_output_character_function);
2052 #endif
2053 _rl_last_c_pos = 0;
2054
2055 /* Move to the last screen line of the current visible line */
2056 _rl_move_vert (_rl_vis_botlin);
2057
2058 /* And erase screen lines going up to line 0 (first visible line) */
2059 for (curr_line = _rl_last_v_pos; curr_line >= 0; curr_line--)
2060 {
2061 _rl_move_vert (curr_line);
2062 _rl_clear_to_eol (0);
2063 }
2064
2065 return 0;
2066 }
2067
2068 /* Tell the update routines that we have moved onto a new line with the
2069 prompt already displayed. Code originally from the version of readline
2070 distributed with CLISP. rl_expand_prompt must have already been called
2071 (explicitly or implicitly). This still doesn't work exactly right. */
2072 int
2073 rl_on_new_line_with_prompt ()
2074 {
2075 int prompt_size, i, l, real_screenwidth, newlines;
2076 char *prompt_last_line, *lprompt;
2077
2078 /* Initialize visible_line and invisible_line to ensure that they can hold
2079 the already-displayed prompt. */
2080 prompt_size = strlen (rl_prompt) + 1;
2081 init_line_structures (prompt_size);
2082
2083 /* Make sure the line structures hold the already-displayed prompt for
2084 redisplay. */
2085 lprompt = local_prompt ? local_prompt : rl_prompt;
2086 strcpy (visible_line, lprompt);
2087 strcpy (invisible_line, lprompt);
2088
2089 /* If the prompt contains newlines, take the last tail. */
2090 prompt_last_line = strrchr (rl_prompt, '\n');
2091 if (!prompt_last_line)
2092 prompt_last_line = rl_prompt;
2093
2094 l = strlen (prompt_last_line);
2095 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2096 _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */
2097 else
2098 _rl_last_c_pos = l;
2099
2100 /* Dissect prompt_last_line into screen lines. Note that here we have
2101 to use the real screenwidth. Readline's notion of screenwidth might be
2102 one less, see terminal.c. */
2103 real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
2104 _rl_last_v_pos = l / real_screenwidth;
2105 /* If the prompt length is a multiple of real_screenwidth, we don't know
2106 whether the cursor is at the end of the last line, or already at the
2107 beginning of the next line. Output a newline just to be safe. */
2108 if (l > 0 && (l % real_screenwidth) == 0)
2109 _rl_output_some_chars ("\n", 1);
2110 last_lmargin = 0;
2111
2112 newlines = 0; i = 0;
2113 while (i <= l)
2114 {
2115 _rl_vis_botlin = newlines;
2116 vis_lbreaks[newlines++] = i;
2117 i += real_screenwidth;
2118 }
2119 vis_lbreaks[newlines] = l;
2120 visible_wrap_offset = 0;
2121
2122 rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
2123
2124 return 0;
2125 }
2126
2127 /* Actually update the display, period. */
2128 int
2129 rl_forced_update_display ()
2130 {
2131 register char *temp;
2132
2133 if (visible_line)
2134 {
2135 temp = visible_line;
2136 while (*temp)
2137 *temp++ = '\0';
2138 }
2139 rl_on_new_line ();
2140 forced_display++;
2141 (*rl_redisplay_function) ();
2142 return 0;
2143 }
2144
2145 /* Redraw only the last line of a multi-line prompt. */
2146 void
2147 rl_redraw_prompt_last_line ()
2148 {
2149 char *t;
2150
2151 t = strrchr (rl_display_prompt, '\n');
2152 if (t)
2153 redraw_prompt (++t);
2154 else
2155 rl_forced_update_display ();
2156 }
2157
2158 /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
2159 (Well, when we don't have multibyte characters, _rl_last_c_pos is a
2160 buffer index.)
2161 DATA is the contents of the screen line of interest; i.e., where
2162 the movement is being done.
2163 DATA is always the visible line or the invisible line */
2164 void
2165 _rl_move_cursor_relative (new, data)
2166 int new;
2167 const char *data;
2168 {
2169 register int i;
2170 int woff; /* number of invisible chars on current line */
2171 int cpos, dpos; /* current and desired cursor positions */
2172 int adjust;
2173 int in_invisline;
2174 int mb_cur_max = MB_CUR_MAX;
2175
2176 woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
2177 cpos = _rl_last_c_pos;
2178
2179 if (cpos == 0 && cpos == new)
2180 return;
2181
2182 #if defined (HANDLE_MULTIBYTE)
2183 /* If we have multibyte characters, NEW is indexed by the buffer point in
2184 a multibyte string, but _rl_last_c_pos is the display position. In
2185 this case, NEW's display position is not obvious and must be
2186 calculated. We need to account for invisible characters in this line,
2187 as long as we are past them and they are counted by _rl_col_width. */
2188 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2189 {
2190 adjust = 1;
2191 /* Try to short-circuit common cases and eliminate a bunch of multibyte
2192 character function calls. */
2193 /* 1. prompt string */
2194 if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2195 {
2196 dpos = prompt_physical_chars;
2197 cpos_adjusted = 1;
2198 adjust = 0;
2199 }
2200 /* 2. prompt_string + line contents */
2201 else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2202 {
2203 dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2204 cpos_adjusted = 1;
2205 adjust = 0;
2206 }
2207 else
2208 dpos = _rl_col_width (data, 0, new, 1);
2209
2210 if (displaying_prompt_first_line == 0)
2211 adjust = 0;
2212
2213 /* yet another special case: printing the last line of a prompt with
2214 multibyte characters and invisible characters whose printable length
2215 exceeds the screen width with the last invisible character
2216 (prompt_last_invisible) in the last line. IN_INVISLINE is the
2217 offset of DATA in invisible_line */
2218 in_invisline = 0;
2219 if (data > invisible_line && data < invisible_line+inv_lbreaks[_rl_inv_botlin+1])
2220 in_invisline = data - invisible_line;
2221
2222 /* Use NEW when comparing against the last invisible character in the
2223 prompt string, since they're both buffer indices and DPOS is a
2224 desired display position. */
2225 /* NEW is relative to the current displayed line, while
2226 PROMPT_LAST_INVISIBLE is relative to the entire (wrapped) line.
2227 Need a way to reconcile these two variables by turning NEW into a
2228 buffer position relative to the start of the line */
2229 if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */
2230 (new+in_invisline > prompt_last_invisible) || /* invisible line */
2231 (prompt_physical_chars >= _rl_screenwidth && /* visible line */
2232 _rl_last_v_pos == prompt_last_screen_line &&
2233 wrap_offset >= woff && dpos >= woff &&
2234 new > (prompt_last_invisible-(vis_lbreaks[_rl_last_v_pos])-wrap_offset))))
2235 /* XXX last comparison might need to be >= */
2236 {
2237 dpos -= woff;
2238 /* Since this will be assigned to _rl_last_c_pos at the end (more
2239 precisely, _rl_last_c_pos == dpos when this function returns),
2240 let the caller know. */
2241 cpos_adjusted = 1;
2242 }
2243 }
2244 else
2245 #endif
2246 dpos = new;
2247
2248 /* If we don't have to do anything, then return. */
2249 if (cpos == dpos)
2250 return;
2251
2252 /* It may be faster to output a CR, and then move forwards instead
2253 of moving backwards. */
2254 /* i == current physical cursor position. */
2255 #if defined (HANDLE_MULTIBYTE)
2256 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2257 i = _rl_last_c_pos;
2258 else
2259 #endif
2260 i = _rl_last_c_pos - woff;
2261 if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
2262 (_rl_term_autowrap && i == _rl_screenwidth))
2263 {
2264 #if defined (__MSDOS__)
2265 putc ('\r', rl_outstream);
2266 #else
2267 tputs (_rl_term_cr, 1, _rl_output_character_function);
2268 #endif /* !__MSDOS__ */
2269 cpos = _rl_last_c_pos = 0;
2270 }
2271
2272 if (cpos < dpos)
2273 {
2274 /* Move the cursor forward. We do it by printing the command
2275 to move the cursor forward if there is one, else print that
2276 portion of the output buffer again. Which is cheaper? */
2277
2278 /* The above comment is left here for posterity. It is faster
2279 to print one character (non-control) than to print a control
2280 sequence telling the terminal to move forward one character.
2281 That kind of control is for people who don't know what the
2282 data is underneath the cursor. */
2283
2284 /* However, we need a handle on where the current display position is
2285 in the buffer for the immediately preceding comment to be true.
2286 In multibyte locales, we don't currently have that info available.
2287 Without it, we don't know where the data we have to display begins
2288 in the buffer and we have to go back to the beginning of the screen
2289 line. In this case, we can use the terminal sequence to move forward
2290 if it's available. */
2291 if (mb_cur_max > 1 && rl_byte_oriented == 0)
2292 {
2293 if (_rl_term_forward_char)
2294 {
2295 for (i = cpos; i < dpos; i++)
2296 tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2297 }
2298 else
2299 {
2300 tputs (_rl_term_cr, 1, _rl_output_character_function);
2301 for (i = 0; i < new; i++)
2302 putc (data[i], rl_outstream);
2303 }
2304 }
2305 else
2306 for (i = cpos; i < new; i++)
2307 putc (data[i], rl_outstream);
2308 }
2309
2310 #if defined (HANDLE_MULTIBYTE)
2311 /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2312 The byte length of the string is probably bigger than the column width
2313 of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2314 display point is less than _rl_last_c_pos. */
2315 #endif
2316 else if (cpos > dpos)
2317 _rl_backspace (cpos - dpos);
2318
2319 _rl_last_c_pos = dpos;
2320 }
2321
2322 /* PWP: move the cursor up or down. */
2323 void
2324 _rl_move_vert (to)
2325 int to;
2326 {
2327 register int delta, i;
2328
2329 if (_rl_last_v_pos == to || to > _rl_screenheight)
2330 return;
2331
2332 if ((delta = to - _rl_last_v_pos) > 0)
2333 {
2334 for (i = 0; i < delta; i++)
2335 putc ('\n', rl_outstream);
2336 #if defined (__MSDOS__)
2337 putc ('\r', rl_outstream);
2338 #else
2339 tputs (_rl_term_cr, 1, _rl_output_character_function);
2340 #endif
2341 _rl_last_c_pos = 0;
2342 }
2343 else
2344 { /* delta < 0 */
2345 #ifdef __DJGPP__
2346 int row, col;
2347
2348 fflush (rl_outstream);
2349 ScreenGetCursor (&row, &col);
2350 ScreenSetCursor (row + delta, col);
2351 i = -delta;
2352 #else
2353 if (_rl_term_up && *_rl_term_up)
2354 for (i = 0; i < -delta; i++)
2355 tputs (_rl_term_up, 1, _rl_output_character_function);
2356 #endif /* !__DJGPP__ */
2357 }
2358
2359 _rl_last_v_pos = to; /* Now TO is here */
2360 }
2361
2362 /* Physically print C on rl_outstream. This is for functions which know
2363 how to optimize the display. Return the number of characters output. */
2364 int
2365 rl_show_char (c)
2366 int c;
2367 {
2368 int n = 1;
2369 if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2370 {
2371 fprintf (rl_outstream, "M-");
2372 n += 2;
2373 c = UNMETA (c);
2374 }
2375
2376 #if defined (DISPLAY_TABS)
2377 if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
2378 #else
2379 if (CTRL_CHAR (c) || c == RUBOUT)
2380 #endif /* !DISPLAY_TABS */
2381 {
2382 fprintf (rl_outstream, "C-");
2383 n += 2;
2384 c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
2385 }
2386
2387 putc (c, rl_outstream);
2388 fflush (rl_outstream);
2389 return n;
2390 }
2391
2392 int
2393 rl_character_len (c, pos)
2394 register int c, pos;
2395 {
2396 unsigned char uc;
2397
2398 uc = (unsigned char)c;
2399
2400 if (META_CHAR (uc))
2401 return ((_rl_output_meta_chars == 0) ? 4 : 1);
2402
2403 if (uc == '\t')
2404 {
2405 #if defined (DISPLAY_TABS)
2406 return (((pos | 7) + 1) - pos);
2407 #else
2408 return (2);
2409 #endif /* !DISPLAY_TABS */
2410 }
2411
2412 if (CTRL_CHAR (c) || c == RUBOUT)
2413 return (2);
2414
2415 return ((ISPRINT (uc)) ? 1 : 2);
2416 }
2417 /* How to print things in the "echo-area". The prompt is treated as a
2418 mini-modeline. */
2419 static int msg_saved_prompt = 0;
2420
2421 #if defined (USE_VARARGS)
2422 int
2423 #if defined (PREFER_STDARG)
2424 rl_message (const char *format, ...)
2425 #else
2426 rl_message (va_alist)
2427 va_dcl
2428 #endif
2429 {
2430 va_list args;
2431 #if defined (PREFER_VARARGS)
2432 char *format;
2433 #endif
2434 #if defined (HAVE_VSNPRINTF)
2435 int bneed;
2436 #endif
2437
2438 #if defined (PREFER_STDARG)
2439 va_start (args, format);
2440 #else
2441 va_start (args);
2442 format = va_arg (args, char *);
2443 #endif
2444
2445 if (msg_buf == 0)
2446 msg_buf = xmalloc (msg_bufsiz = 128);
2447
2448 #if defined (HAVE_VSNPRINTF)
2449 bneed = vsnprintf (msg_buf, msg_bufsiz, format, args);
2450 if (bneed >= msg_bufsiz - 1)
2451 {
2452 msg_bufsiz = bneed + 1;
2453 msg_buf = xrealloc (msg_buf, msg_bufsiz);
2454 va_end (args);
2455
2456 #if defined (PREFER_STDARG)
2457 va_start (args, format);
2458 #else
2459 va_start (args);
2460 format = va_arg (args, char *);
2461 #endif
2462 vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2463 }
2464 #else
2465 vsprintf (msg_buf, format, args);
2466 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2467 #endif
2468 va_end (args);
2469
2470 if (saved_local_prompt == 0)
2471 {
2472 rl_save_prompt ();
2473 msg_saved_prompt = 1;
2474 }
2475 else if (local_prompt != saved_local_prompt)
2476 {
2477 FREE (local_prompt);
2478 FREE (local_prompt_prefix);
2479 local_prompt = (char *)NULL;
2480 }
2481 rl_display_prompt = msg_buf;
2482 local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
2483 &prompt_last_invisible,
2484 &prompt_invis_chars_first_line,
2485 &prompt_physical_chars);
2486 local_prompt_prefix = (char *)NULL;
2487 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2488 (*rl_redisplay_function) ();
2489
2490 return 0;
2491 }
2492 #else /* !USE_VARARGS */
2493 int
2494 rl_message (format, arg1, arg2)
2495 char *format;
2496 {
2497 if (msg_buf == 0)
2498 msg_buf = xmalloc (msg_bufsiz = 128);
2499
2500 sprintf (msg_buf, format, arg1, arg2);
2501 msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2502
2503 rl_display_prompt = msg_buf;
2504 if (saved_local_prompt == 0)
2505 {
2506 rl_save_prompt ();
2507 msg_saved_prompt = 1;
2508 }
2509 else if (local_prompt != saved_local_prompt)
2510 {
2511 FREE (local_prompt);
2512 FREE (local_prompt_prefix);
2513 local_prompt = (char *)NULL;
2514 }
2515 local_prompt = expand_prompt (msg_buf, 0, &prompt_visible_length,
2516 &prompt_last_invisible,
2517 &prompt_invis_chars_first_line,
2518 &prompt_physical_chars);
2519 local_prompt_prefix = (char *)NULL;
2520 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2521 (*rl_redisplay_function) ();
2522
2523 return 0;
2524 }
2525 #endif /* !USE_VARARGS */
2526
2527 /* How to clear things from the "echo-area". */
2528 int
2529 rl_clear_message ()
2530 {
2531 rl_display_prompt = rl_prompt;
2532 if (msg_saved_prompt)
2533 {
2534 rl_restore_prompt ();
2535 msg_saved_prompt = 0;
2536 }
2537 (*rl_redisplay_function) ();
2538 return 0;
2539 }
2540
2541 int
2542 rl_reset_line_state ()
2543 {
2544 rl_on_new_line ();
2545
2546 rl_display_prompt = rl_prompt ? rl_prompt : "";
2547 forced_display = 1;
2548 return 0;
2549 }
2550
2551 void
2552 rl_save_prompt ()
2553 {
2554 saved_local_prompt = local_prompt;
2555 saved_local_prefix = local_prompt_prefix;
2556 saved_prefix_length = prompt_prefix_length;
2557 saved_local_length = local_prompt_len;
2558 saved_last_invisible = prompt_last_invisible;
2559 saved_visible_length = prompt_visible_length;
2560 saved_invis_chars_first_line = prompt_invis_chars_first_line;
2561 saved_physical_chars = prompt_physical_chars;
2562
2563 local_prompt = local_prompt_prefix = (char *)0;
2564 local_prompt_len = 0;
2565 prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
2566 prompt_invis_chars_first_line = prompt_physical_chars = 0;
2567 }
2568
2569 void
2570 rl_restore_prompt ()
2571 {
2572 FREE (local_prompt);
2573 FREE (local_prompt_prefix);
2574
2575 local_prompt = saved_local_prompt;
2576 local_prompt_prefix = saved_local_prefix;
2577 local_prompt_len = saved_local_length;
2578 prompt_prefix_length = saved_prefix_length;
2579 prompt_last_invisible = saved_last_invisible;
2580 prompt_visible_length = saved_visible_length;
2581 prompt_invis_chars_first_line = saved_invis_chars_first_line;
2582 prompt_physical_chars = saved_physical_chars;
2583
2584 /* can test saved_local_prompt to see if prompt info has been saved. */
2585 saved_local_prompt = saved_local_prefix = (char *)0;
2586 saved_local_length = 0;
2587 saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2588 saved_invis_chars_first_line = saved_physical_chars = 0;
2589 }
2590
2591 char *
2592 _rl_make_prompt_for_search (pchar)
2593 int pchar;
2594 {
2595 int len;
2596 char *pmt, *p;
2597
2598 rl_save_prompt ();
2599
2600 /* We've saved the prompt, and can do anything with the various prompt
2601 strings we need before they're restored. We want the unexpanded
2602 portion of the prompt string after any final newline. */
2603 p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2604 if (p == 0)
2605 {
2606 len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
2607 pmt = (char *)xmalloc (len + 2);
2608 if (len)
2609 strcpy (pmt, rl_prompt);
2610 pmt[len] = pchar;
2611 pmt[len+1] = '\0';
2612 }
2613 else
2614 {
2615 p++;
2616 len = strlen (p);
2617 pmt = (char *)xmalloc (len + 2);
2618 if (len)
2619 strcpy (pmt, p);
2620 pmt[len] = pchar;
2621 pmt[len+1] = '\0';
2622 }
2623
2624 /* will be overwritten by expand_prompt, called from rl_message */
2625 prompt_physical_chars = saved_physical_chars + 1;
2626 return pmt;
2627 }
2628
2629 /* Quick redisplay hack when erasing characters at the end of the line. */
2630 void
2631 _rl_erase_at_end_of_line (l)
2632 int l;
2633 {
2634 register int i;
2635
2636 _rl_backspace (l);
2637 for (i = 0; i < l; i++)
2638 putc (' ', rl_outstream);
2639 _rl_backspace (l);
2640 for (i = 0; i < l; i++)
2641 visible_line[--_rl_last_c_pos] = '\0';
2642 rl_display_fixed++;
2643 }
2644
2645 /* Clear to the end of the line. COUNT is the minimum
2646 number of character spaces to clear, */
2647 void
2648 _rl_clear_to_eol (count)
2649 int count;
2650 {
2651 #ifndef __MSDOS__
2652 if (_rl_term_clreol)
2653 tputs (_rl_term_clreol, 1, _rl_output_character_function);
2654 else
2655 #endif
2656 if (count)
2657 space_to_eol (count);
2658 }
2659
2660 /* Clear to the end of the line using spaces. COUNT is the minimum
2661 number of character spaces to clear, */
2662 static void
2663 space_to_eol (count)
2664 int count;
2665 {
2666 register int i;
2667
2668 for (i = 0; i < count; i++)
2669 putc (' ', rl_outstream);
2670
2671 _rl_last_c_pos += count;
2672 }
2673
2674 void
2675 _rl_clear_screen ()
2676 {
2677 #ifndef __DJGPP__
2678 if (_rl_term_clrpag)
2679 tputs (_rl_term_clrpag, 1, _rl_output_character_function);
2680 else
2681 rl_crlf ();
2682 #else
2683 ScreenClear ();
2684 ScreenSetCursor (0, 0);
2685 #endif /* __DJGPP__ */
2686 }
2687
2688 /* Insert COUNT characters from STRING to the output stream at column COL. */
2689 static void
2690 insert_some_chars (string, count, col)
2691 char *string;
2692 int count, col;
2693 {
2694 open_some_spaces (col);
2695 _rl_output_some_chars (string, count);
2696 }
2697
2698 /* Insert COL spaces, keeping the cursor at the same position. We follow the
2699 ncurses documentation and use either im/ei with explicit spaces, or IC/ic
2700 by itself. We assume there will either be ei or we don't need to use it. */
2701 static void
2702 open_some_spaces (col)
2703 int col;
2704 {
2705 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
2706 char *buffer;
2707 register int i;
2708
2709 /* If IC is defined, then we do not have to "enter" insert mode. */
2710 if (_rl_term_IC)
2711 {
2712 buffer = tgoto (_rl_term_IC, 0, col);
2713 tputs (buffer, 1, _rl_output_character_function);
2714 }
2715 else if (_rl_term_im && *_rl_term_im)
2716 {
2717 tputs (_rl_term_im, 1, _rl_output_character_function);
2718 /* just output the desired number of spaces */
2719 for (i = col; i--; )
2720 _rl_output_character_function (' ');
2721 /* If there is a string to turn off insert mode, use it now. */
2722 if (_rl_term_ei && *_rl_term_ei)
2723 tputs (_rl_term_ei, 1, _rl_output_character_function);
2724 /* and move back the right number of spaces */
2725 _rl_backspace (col);
2726 }
2727 else if (_rl_term_ic && *_rl_term_ic)
2728 {
2729 /* If there is a special command for inserting characters, then
2730 use that first to open up the space. */
2731 for (i = col; i--; )
2732 tputs (_rl_term_ic, 1, _rl_output_character_function);
2733 }
2734 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
2735 }
2736
2737 /* Delete COUNT characters from the display line. */
2738 static void
2739 delete_chars (count)
2740 int count;
2741 {
2742 if (count > _rl_screenwidth) /* XXX */
2743 return;
2744
2745 #if !defined (__MSDOS__) && (!defined (__MINGW32__) || defined (NCURSES_VERSION))
2746 if (_rl_term_DC && *_rl_term_DC)
2747 {
2748 char *buffer;
2749 buffer = tgoto (_rl_term_DC, count, count);
2750 tputs (buffer, count, _rl_output_character_function);
2751 }
2752 else
2753 {
2754 if (_rl_term_dc && *_rl_term_dc)
2755 while (count--)
2756 tputs (_rl_term_dc, 1, _rl_output_character_function);
2757 }
2758 #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/
2759 }
2760
2761 void
2762 _rl_update_final ()
2763 {
2764 int full_lines;
2765
2766 full_lines = 0;
2767 /* If the cursor is the only thing on an otherwise-blank last line,
2768 compensate so we don't print an extra CRLF. */
2769 if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
2770 visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
2771 {
2772 _rl_vis_botlin--;
2773 full_lines = 1;
2774 }
2775 _rl_move_vert (_rl_vis_botlin);
2776 /* If we've wrapped lines, remove the final xterm line-wrap flag. */
2777 if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
2778 {
2779 char *last_line;
2780
2781 last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
2782 cpos_buffer_position = -1; /* don't know where we are in buffer */
2783 _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */
2784 _rl_clear_to_eol (0);
2785 putc (last_line[_rl_screenwidth - 1], rl_outstream);
2786 }
2787 _rl_vis_botlin = 0;
2788 rl_crlf ();
2789 fflush (rl_outstream);
2790 rl_display_fixed++;
2791 }
2792
2793 /* Move to the start of the current line. */
2794 static void
2795 cr ()
2796 {
2797 if (_rl_term_cr)
2798 {
2799 #if defined (__MSDOS__)
2800 putc ('\r', rl_outstream);
2801 #else
2802 tputs (_rl_term_cr, 1, _rl_output_character_function);
2803 #endif
2804 _rl_last_c_pos = 0;
2805 }
2806 }
2807
2808 /* Redraw the last line of a multi-line prompt that may possibly contain
2809 terminal escape sequences. Called with the cursor at column 0 of the
2810 line to draw the prompt on. */
2811 static void
2812 redraw_prompt (t)
2813 char *t;
2814 {
2815 char *oldp;
2816
2817 oldp = rl_display_prompt;
2818 rl_save_prompt ();
2819
2820 rl_display_prompt = t;
2821 local_prompt = expand_prompt (t, PMT_MULTILINE,
2822 &prompt_visible_length,
2823 &prompt_last_invisible,
2824 &prompt_invis_chars_first_line,
2825 &prompt_physical_chars);
2826 local_prompt_prefix = (char *)NULL;
2827 local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2828
2829 rl_forced_update_display ();
2830
2831 rl_display_prompt = oldp;
2832 rl_restore_prompt();
2833 }
2834
2835 /* Redisplay the current line after a SIGWINCH is received. */
2836 void
2837 _rl_redisplay_after_sigwinch ()
2838 {
2839 char *t;
2840
2841 /* Clear the last line (assuming that the screen size change will result in
2842 either more or fewer characters on that line only) and put the cursor at
2843 column 0. Make sure the right thing happens if we have wrapped to a new
2844 screen line. */
2845 if (_rl_term_cr)
2846 {
2847 _rl_move_vert (_rl_vis_botlin);
2848
2849 #if defined (__MSDOS__)
2850 putc ('\r', rl_outstream);
2851 #else
2852 tputs (_rl_term_cr, 1, _rl_output_character_function);
2853 #endif
2854 _rl_last_c_pos = 0;
2855 #if defined (__MSDOS__)
2856 space_to_eol (_rl_screenwidth);
2857 putc ('\r', rl_outstream);
2858 #else
2859 if (_rl_term_clreol)
2860 tputs (_rl_term_clreol, 1, _rl_output_character_function);
2861 else
2862 {
2863 space_to_eol (_rl_screenwidth);
2864 tputs (_rl_term_cr, 1, _rl_output_character_function);
2865 }
2866 #endif
2867 if (_rl_last_v_pos > 0)
2868 _rl_move_vert (0);
2869 }
2870 else
2871 rl_crlf ();
2872
2873 /* Redraw only the last line of a multi-line prompt. */
2874 t = strrchr (rl_display_prompt, '\n');
2875 if (t)
2876 redraw_prompt (++t);
2877 else
2878 rl_forced_update_display ();
2879 }
2880
2881 void
2882 _rl_clean_up_for_exit ()
2883 {
2884 if (_rl_echoing_p)
2885 {
2886 if (_rl_vis_botlin > 0) /* minor optimization plus bug fix */
2887 _rl_move_vert (_rl_vis_botlin);
2888 _rl_vis_botlin = 0;
2889 fflush (rl_outstream);
2890 rl_restart_output (1, 0);
2891 }
2892 }
2893
2894 void
2895 _rl_erase_entire_line ()
2896 {
2897 cr ();
2898 _rl_clear_to_eol (0);
2899 cr ();
2900 fflush (rl_outstream);
2901 }
2902
2903 void
2904 _rl_ttyflush ()
2905 {
2906 fflush (rl_outstream);
2907 }
2908
2909 /* return the `current display line' of the cursor -- the number of lines to
2910 move up to get to the first screen line of the current readline line. */
2911 int
2912 _rl_current_display_line ()
2913 {
2914 int ret, nleft;
2915
2916 /* Find out whether or not there might be invisible characters in the
2917 editing buffer. */
2918 if (rl_display_prompt == rl_prompt)
2919 nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
2920 else
2921 nleft = _rl_last_c_pos - _rl_screenwidth;
2922
2923 if (nleft > 0)
2924 ret = 1 + nleft / _rl_screenwidth;
2925 else
2926 ret = 0;
2927
2928 return ret;
2929 }
2930
2931 #if defined (HANDLE_MULTIBYTE)
2932 /* Calculate the number of screen columns occupied by STR from START to END.
2933 In the case of multibyte characters with stateful encoding, we have to
2934 scan from the beginning of the string to take the state into account. */
2935 static int
2936 _rl_col_width (str, start, end, flags)
2937 const char *str;
2938 int start, end, flags;
2939 {
2940 wchar_t wc;
2941 mbstate_t ps;
2942 int tmp, point, width, max;
2943
2944 if (end <= start)
2945 return 0;
2946 if (MB_CUR_MAX == 1 || rl_byte_oriented)
2947 /* this can happen in some cases where it's inconvenient to check */
2948 return (end - start);
2949
2950 memset (&ps, 0, sizeof (mbstate_t));
2951
2952 point = 0;
2953 max = end;
2954
2955 /* Try to short-circuit common cases. The adjustment to remove wrap_offset
2956 is done by the caller. */
2957 /* 1. prompt string */
2958 if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
2959 return (prompt_physical_chars + wrap_offset);
2960 /* 2. prompt string + line contents */
2961 else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
2962 {
2963 tmp = prompt_physical_chars + wrap_offset;
2964 /* XXX - try to call ourselves recursively with non-prompt portion */
2965 tmp += _rl_col_width (str, local_prompt_len, end, flags);
2966 return (tmp);
2967 }
2968
2969 while (point < start)
2970 {
2971 tmp = mbrlen (str + point, max, &ps);
2972 if (MB_INVALIDCH ((size_t)tmp))
2973 {
2974 /* In this case, the bytes are invalid or too short to compose a
2975 multibyte character, so we assume that the first byte represents
2976 a single character. */
2977 point++;
2978 max--;
2979
2980 /* Clear the state of the byte sequence, because in this case the
2981 effect of mbstate is undefined. */
2982 memset (&ps, 0, sizeof (mbstate_t));
2983 }
2984 else if (MB_NULLWCH (tmp))
2985 break; /* Found '\0' */
2986 else
2987 {
2988 point += tmp;
2989 max -= tmp;
2990 }
2991 }
2992
2993 /* If START is not a byte that starts a character, then POINT will be
2994 greater than START. In this case, assume that (POINT - START) gives
2995 a byte count that is the number of columns of difference. */
2996 width = point - start;
2997
2998 while (point < end)
2999 {
3000 tmp = mbrtowc (&wc, str + point, max, &ps);
3001 if (MB_INVALIDCH ((size_t)tmp))
3002 {
3003 /* In this case, the bytes are invalid or too short to compose a
3004 multibyte character, so we assume that the first byte represents
3005 a single character. */
3006 point++;
3007 max--;
3008
3009 /* and assume that the byte occupies a single column. */
3010 width++;
3011
3012 /* Clear the state of the byte sequence, because in this case the
3013 effect of mbstate is undefined. */
3014 memset (&ps, 0, sizeof (mbstate_t));
3015 }
3016 else if (MB_NULLWCH (tmp))
3017 break; /* Found '\0' */
3018 else
3019 {
3020 point += tmp;
3021 max -= tmp;
3022 tmp = WCWIDTH(wc);
3023 width += (tmp >= 0) ? tmp : 1;
3024 }
3025 }
3026
3027 width += point - end;
3028
3029 return width;
3030 }
3031 #endif /* HANDLE_MULTIBYTE */
This page took 0.090571 seconds and 5 git commands to generate.