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