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