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