Annotation of embedaddon/readline/display.c, revision 1.1.1.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.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:
1.1.1.2 ! misho 1828: /* XXX - we only want to do this if we are at the end of the line
! 1829: so we move there with _rl_move_cursor_relative */
1.1 misho 1830: if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
1.1.1.2 ! misho 1831: {
! 1832: _rl_move_cursor_relative (ne-new, new);
! 1833: goto clear_rest_of_line;
! 1834: }
1.1 misho 1835: }
1836: }
1837: /* Otherwise, print over the existing material. */
1838: else
1839: {
1840: if (temp > 0)
1841: {
1842: /* If nfd begins at the prompt, or before the invisible
1843: characters in the prompt, we need to adjust _rl_last_c_pos
1844: in a multibyte locale to account for the wrap offset and
1845: set cpos_adjusted accordingly. */
1846: _rl_output_some_chars (nfd, temp);
1847: _rl_last_c_pos += col_temp; /* XXX */
1848: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1849: {
1850: if (current_line == 0 && wrap_offset &&
1851: displaying_prompt_first_line &&
1852: _rl_last_c_pos > wrap_offset &&
1853: ((nfd - new) <= prompt_last_invisible))
1854: {
1855: _rl_last_c_pos -= wrap_offset;
1856: cpos_adjusted = 1;
1857: }
1858: }
1859: }
1860: clear_rest_of_line:
1861: lendiff = (oe - old) - (ne - new);
1862: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1863: col_lendiff = _rl_col_width (old, 0, oe - old, 1) - _rl_col_width (new, 0, ne - new, 1);
1864: else
1865: col_lendiff = lendiff;
1866:
1867: /* If we've already printed over the entire width of the screen,
1868: including the old material, then col_lendiff doesn't matter and
1869: space_to_eol will insert too many spaces. XXX - maybe we should
1870: adjust col_lendiff based on the difference between _rl_last_c_pos
1871: and _rl_screenwidth */
1872: if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
1873: {
1874: if (_rl_term_autowrap && current_line < inv_botlin)
1875: space_to_eol (col_lendiff);
1876: else
1877: _rl_clear_to_eol (col_lendiff);
1878: }
1879: }
1880: }
1881: }
1882:
1883: /* Tell the update routines that we have moved onto a new (empty) line. */
1884: int
1885: rl_on_new_line ()
1886: {
1887: if (visible_line)
1888: visible_line[0] = '\0';
1889:
1890: _rl_last_c_pos = _rl_last_v_pos = 0;
1891: _rl_vis_botlin = last_lmargin = 0;
1892: if (vis_lbreaks)
1893: vis_lbreaks[0] = vis_lbreaks[1] = 0;
1894: visible_wrap_offset = 0;
1895: return 0;
1896: }
1897:
1898: /* Tell the update routines that we have moved onto a new line with the
1899: prompt already displayed. Code originally from the version of readline
1900: distributed with CLISP. rl_expand_prompt must have already been called
1901: (explicitly or implicitly). This still doesn't work exactly right. */
1902: int
1903: rl_on_new_line_with_prompt ()
1904: {
1905: int prompt_size, i, l, real_screenwidth, newlines;
1906: char *prompt_last_line, *lprompt;
1907:
1908: /* Initialize visible_line and invisible_line to ensure that they can hold
1909: the already-displayed prompt. */
1910: prompt_size = strlen (rl_prompt) + 1;
1911: init_line_structures (prompt_size);
1912:
1913: /* Make sure the line structures hold the already-displayed prompt for
1914: redisplay. */
1915: lprompt = local_prompt ? local_prompt : rl_prompt;
1916: strcpy (visible_line, lprompt);
1917: strcpy (invisible_line, lprompt);
1918:
1919: /* If the prompt contains newlines, take the last tail. */
1920: prompt_last_line = strrchr (rl_prompt, '\n');
1921: if (!prompt_last_line)
1922: prompt_last_line = rl_prompt;
1923:
1924: l = strlen (prompt_last_line);
1925: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1926: _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l, 1); /* XXX */
1927: else
1928: _rl_last_c_pos = l;
1929:
1930: /* Dissect prompt_last_line into screen lines. Note that here we have
1931: to use the real screenwidth. Readline's notion of screenwidth might be
1932: one less, see terminal.c. */
1933: real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
1934: _rl_last_v_pos = l / real_screenwidth;
1935: /* If the prompt length is a multiple of real_screenwidth, we don't know
1936: whether the cursor is at the end of the last line, or already at the
1937: beginning of the next line. Output a newline just to be safe. */
1938: if (l > 0 && (l % real_screenwidth) == 0)
1939: _rl_output_some_chars ("\n", 1);
1940: last_lmargin = 0;
1941:
1942: newlines = 0; i = 0;
1943: while (i <= l)
1944: {
1945: _rl_vis_botlin = newlines;
1946: vis_lbreaks[newlines++] = i;
1947: i += real_screenwidth;
1948: }
1949: vis_lbreaks[newlines] = l;
1950: visible_wrap_offset = 0;
1951:
1952: rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
1953:
1954: return 0;
1955: }
1956:
1957: /* Actually update the display, period. */
1958: int
1959: rl_forced_update_display ()
1960: {
1961: register char *temp;
1962:
1963: if (visible_line)
1964: {
1965: temp = visible_line;
1966: while (*temp)
1967: *temp++ = '\0';
1968: }
1969: rl_on_new_line ();
1970: forced_display++;
1971: (*rl_redisplay_function) ();
1972: return 0;
1973: }
1974:
1975: /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
1976: (Well, when we don't have multibyte characters, _rl_last_c_pos is a
1977: buffer index.)
1978: DATA is the contents of the screen line of interest; i.e., where
1979: the movement is being done. */
1980: void
1981: _rl_move_cursor_relative (new, data)
1982: int new;
1983: const char *data;
1984: {
1985: register int i;
1986: int woff; /* number of invisible chars on current line */
1987: int cpos, dpos; /* current and desired cursor positions */
1988: int adjust;
1989:
1990: woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
1991: cpos = _rl_last_c_pos;
1992:
1993: if (cpos == 0 && cpos == new)
1994: return;
1995:
1996: #if defined (HANDLE_MULTIBYTE)
1997: /* If we have multibyte characters, NEW is indexed by the buffer point in
1998: a multibyte string, but _rl_last_c_pos is the display position. In
1999: this case, NEW's display position is not obvious and must be
2000: calculated. We need to account for invisible characters in this line,
2001: as long as we are past them and they are counted by _rl_col_width. */
2002: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2003: {
2004: adjust = 1;
2005: /* Try to short-circuit common cases and eliminate a bunch of multibyte
2006: character function calls. */
2007: /* 1. prompt string */
2008: if (new == local_prompt_len && memcmp (data, local_prompt, new) == 0)
2009: {
2010: dpos = prompt_physical_chars;
2011: cpos_adjusted = 1;
2012: adjust = 0;
2013: }
2014: /* 2. prompt_string + line contents */
2015: else if (new > local_prompt_len && local_prompt && memcmp (data, local_prompt, local_prompt_len) == 0)
2016: {
2017: dpos = prompt_physical_chars + _rl_col_width (data, local_prompt_len, new, 1);
2018: cpos_adjusted = 1;
2019: adjust = 0;
2020: }
2021: else
2022: dpos = _rl_col_width (data, 0, new, 1);
2023:
2024: if (displaying_prompt_first_line == 0)
2025: adjust = 0;
2026:
2027: /* Use NEW when comparing against the last invisible character in the
2028: prompt string, since they're both buffer indices and DPOS is a
2029: desired display position. */
2030: if (adjust && ((new > prompt_last_invisible) || /* XXX - don't use woff here */
2031: (prompt_physical_chars >= _rl_screenwidth &&
2032: _rl_last_v_pos == prompt_last_screen_line &&
2033: wrap_offset >= woff && dpos >= woff &&
2034: new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset))))
2035: /* XXX last comparison might need to be >= */
2036: {
2037: dpos -= woff;
2038: /* Since this will be assigned to _rl_last_c_pos at the end (more
2039: precisely, _rl_last_c_pos == dpos when this function returns),
2040: let the caller know. */
2041: cpos_adjusted = 1;
2042: }
2043: }
2044: else
2045: #endif
2046: dpos = new;
2047:
2048: /* If we don't have to do anything, then return. */
2049: if (cpos == dpos)
2050: return;
2051:
2052: /* It may be faster to output a CR, and then move forwards instead
2053: of moving backwards. */
2054: /* i == current physical cursor position. */
2055: #if defined (HANDLE_MULTIBYTE)
2056: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2057: i = _rl_last_c_pos;
2058: else
2059: #endif
2060: i = _rl_last_c_pos - woff;
2061: if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
2062: (_rl_term_autowrap && i == _rl_screenwidth))
2063: {
2064: #if defined (__MSDOS__)
2065: putc ('\r', rl_outstream);
2066: #else
2067: tputs (_rl_term_cr, 1, _rl_output_character_function);
2068: #endif /* !__MSDOS__ */
2069: cpos = _rl_last_c_pos = 0;
2070: }
2071:
2072: if (cpos < dpos)
2073: {
2074: /* Move the cursor forward. We do it by printing the command
2075: to move the cursor forward if there is one, else print that
2076: portion of the output buffer again. Which is cheaper? */
2077:
2078: /* The above comment is left here for posterity. It is faster
2079: to print one character (non-control) than to print a control
2080: sequence telling the terminal to move forward one character.
2081: That kind of control is for people who don't know what the
2082: data is underneath the cursor. */
2083:
2084: /* However, we need a handle on where the current display position is
2085: in the buffer for the immediately preceding comment to be true.
2086: In multibyte locales, we don't currently have that info available.
2087: Without it, we don't know where the data we have to display begins
2088: in the buffer and we have to go back to the beginning of the screen
2089: line. In this case, we can use the terminal sequence to move forward
2090: if it's available. */
2091: if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2092: {
2093: if (_rl_term_forward_char)
2094: {
2095: for (i = cpos; i < dpos; i++)
2096: tputs (_rl_term_forward_char, 1, _rl_output_character_function);
2097: }
2098: else
2099: {
2100: tputs (_rl_term_cr, 1, _rl_output_character_function);
2101: for (i = 0; i < new; i++)
2102: putc (data[i], rl_outstream);
2103: }
2104: }
2105: else
2106: for (i = cpos; i < new; i++)
2107: putc (data[i], rl_outstream);
2108: }
2109:
2110: #if defined (HANDLE_MULTIBYTE)
2111: /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
2112: The byte length of the string is probably bigger than the column width
2113: of the string, which means that if NEW == _rl_last_c_pos, then NEW's
2114: display point is less than _rl_last_c_pos. */
2115: #endif
2116: else if (cpos > dpos)
2117: _rl_backspace (cpos - dpos);
2118:
2119: _rl_last_c_pos = dpos;
2120: }
2121:
2122: /* PWP: move the cursor up or down. */
2123: void
2124: _rl_move_vert (to)
2125: int to;
2126: {
2127: register int delta, i;
2128:
2129: if (_rl_last_v_pos == to || to > _rl_screenheight)
2130: return;
2131:
2132: if ((delta = to - _rl_last_v_pos) > 0)
2133: {
2134: for (i = 0; i < delta; i++)
2135: putc ('\n', rl_outstream);
2136: #if defined (__MSDOS__)
2137: putc ('\r', rl_outstream);
2138: #else
2139: tputs (_rl_term_cr, 1, _rl_output_character_function);
2140: #endif
2141: _rl_last_c_pos = 0;
2142: }
2143: else
2144: { /* delta < 0 */
2145: #ifdef __DJGPP__
2146: int row, col;
2147:
2148: fflush (rl_outstream);
2149: ScreenGetCursor (&row, &col);
2150: ScreenSetCursor (row + delta, col);
2151: i = -delta;
2152: #else
2153: if (_rl_term_up && *_rl_term_up)
2154: for (i = 0; i < -delta; i++)
2155: tputs (_rl_term_up, 1, _rl_output_character_function);
2156: #endif /* !__DJGPP__ */
2157: }
2158:
2159: _rl_last_v_pos = to; /* Now TO is here */
2160: }
2161:
2162: /* Physically print C on rl_outstream. This is for functions which know
2163: how to optimize the display. Return the number of characters output. */
2164: int
2165: rl_show_char (c)
2166: int c;
2167: {
2168: int n = 1;
2169: if (META_CHAR (c) && (_rl_output_meta_chars == 0))
2170: {
2171: fprintf (rl_outstream, "M-");
2172: n += 2;
2173: c = UNMETA (c);
2174: }
2175:
2176: #if defined (DISPLAY_TABS)
2177: if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
2178: #else
2179: if (CTRL_CHAR (c) || c == RUBOUT)
2180: #endif /* !DISPLAY_TABS */
2181: {
2182: fprintf (rl_outstream, "C-");
2183: n += 2;
2184: c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
2185: }
2186:
2187: putc (c, rl_outstream);
2188: fflush (rl_outstream);
2189: return n;
2190: }
2191:
2192: int
2193: rl_character_len (c, pos)
2194: register int c, pos;
2195: {
2196: unsigned char uc;
2197:
2198: uc = (unsigned char)c;
2199:
2200: if (META_CHAR (uc))
2201: return ((_rl_output_meta_chars == 0) ? 4 : 1);
2202:
2203: if (uc == '\t')
2204: {
2205: #if defined (DISPLAY_TABS)
2206: return (((pos | 7) + 1) - pos);
2207: #else
2208: return (2);
2209: #endif /* !DISPLAY_TABS */
2210: }
2211:
2212: if (CTRL_CHAR (c) || c == RUBOUT)
2213: return (2);
2214:
2215: return ((ISPRINT (uc)) ? 1 : 2);
2216: }
2217: /* How to print things in the "echo-area". The prompt is treated as a
2218: mini-modeline. */
2219: static int msg_saved_prompt = 0;
2220:
2221: #if defined (USE_VARARGS)
2222: int
2223: #if defined (PREFER_STDARG)
2224: rl_message (const char *format, ...)
2225: #else
2226: rl_message (va_alist)
2227: va_dcl
2228: #endif
2229: {
2230: va_list args;
2231: #if defined (PREFER_VARARGS)
2232: char *format;
2233: #endif
2234: #if defined (HAVE_VSNPRINTF)
2235: int bneed;
2236: #endif
2237:
2238: #if defined (PREFER_STDARG)
2239: va_start (args, format);
2240: #else
2241: va_start (args);
2242: format = va_arg (args, char *);
2243: #endif
2244:
2245: if (msg_buf == 0)
2246: msg_buf = xmalloc (msg_bufsiz = 128);
2247:
2248: #if defined (HAVE_VSNPRINTF)
2249: bneed = vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2250: if (bneed >= msg_bufsiz - 1)
2251: {
2252: msg_bufsiz = bneed + 1;
2253: msg_buf = xrealloc (msg_buf, msg_bufsiz);
2254: va_end (args);
2255:
2256: #if defined (PREFER_STDARG)
2257: va_start (args, format);
2258: #else
2259: va_start (args);
2260: format = va_arg (args, char *);
2261: #endif
2262: vsnprintf (msg_buf, msg_bufsiz - 1, format, args);
2263: }
2264: #else
2265: vsprintf (msg_buf, format, args);
2266: msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2267: #endif
2268: va_end (args);
2269:
2270: if (saved_local_prompt == 0)
2271: {
2272: rl_save_prompt ();
2273: msg_saved_prompt = 1;
2274: }
2275: else if (local_prompt != saved_local_prompt)
2276: {
2277: FREE (local_prompt);
2278: FREE (local_prompt_prefix);
2279: local_prompt = (char *)NULL;
2280: }
2281: rl_display_prompt = msg_buf;
2282: local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2283: &prompt_last_invisible,
2284: &prompt_invis_chars_first_line,
2285: &prompt_physical_chars);
2286: local_prompt_prefix = (char *)NULL;
2287: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2288: (*rl_redisplay_function) ();
2289:
2290: return 0;
2291: }
2292: #else /* !USE_VARARGS */
2293: int
2294: rl_message (format, arg1, arg2)
2295: char *format;
2296: {
2297: if (msg_buf == 0)
2298: msg_buf = xmalloc (msg_bufsiz = 128);
2299:
2300: sprintf (msg_buf, format, arg1, arg2);
2301: msg_buf[msg_bufsiz - 1] = '\0'; /* overflow? */
2302:
2303: rl_display_prompt = msg_buf;
2304: if (saved_local_prompt == 0)
2305: {
2306: rl_save_prompt ();
2307: msg_saved_prompt = 1;
2308: }
2309: else if (local_prompt != saved_local_prompt)
2310: {
2311: FREE (local_prompt);
2312: FREE (local_prompt_prefix);
2313: local_prompt = (char *)NULL;
2314: }
2315: local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
2316: &prompt_last_invisible,
2317: &prompt_invis_chars_first_line,
2318: &prompt_physical_chars);
2319: local_prompt_prefix = (char *)NULL;
2320: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2321: (*rl_redisplay_function) ();
2322:
2323: return 0;
2324: }
2325: #endif /* !USE_VARARGS */
2326:
2327: /* How to clear things from the "echo-area". */
2328: int
2329: rl_clear_message ()
2330: {
2331: rl_display_prompt = rl_prompt;
2332: if (msg_saved_prompt)
2333: {
2334: rl_restore_prompt ();
2335: msg_saved_prompt = 0;
2336: }
2337: (*rl_redisplay_function) ();
2338: return 0;
2339: }
2340:
2341: int
2342: rl_reset_line_state ()
2343: {
2344: rl_on_new_line ();
2345:
2346: rl_display_prompt = rl_prompt ? rl_prompt : "";
2347: forced_display = 1;
2348: return 0;
2349: }
2350:
2351: void
2352: rl_save_prompt ()
2353: {
2354: saved_local_prompt = local_prompt;
2355: saved_local_prefix = local_prompt_prefix;
2356: saved_prefix_length = prompt_prefix_length;
2357: saved_local_length = local_prompt_len;
2358: saved_last_invisible = prompt_last_invisible;
2359: saved_visible_length = prompt_visible_length;
2360: saved_invis_chars_first_line = prompt_invis_chars_first_line;
2361: saved_physical_chars = prompt_physical_chars;
2362:
2363: local_prompt = local_prompt_prefix = (char *)0;
2364: local_prompt_len = 0;
2365: prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
2366: prompt_invis_chars_first_line = prompt_physical_chars = 0;
2367: }
2368:
2369: void
2370: rl_restore_prompt ()
2371: {
2372: FREE (local_prompt);
2373: FREE (local_prompt_prefix);
2374:
2375: local_prompt = saved_local_prompt;
2376: local_prompt_prefix = saved_local_prefix;
2377: local_prompt_len = saved_local_length;
2378: prompt_prefix_length = saved_prefix_length;
2379: prompt_last_invisible = saved_last_invisible;
2380: prompt_visible_length = saved_visible_length;
2381: prompt_invis_chars_first_line = saved_invis_chars_first_line;
2382: prompt_physical_chars = saved_physical_chars;
2383:
2384: /* can test saved_local_prompt to see if prompt info has been saved. */
2385: saved_local_prompt = saved_local_prefix = (char *)0;
2386: saved_local_length = 0;
2387: saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
2388: saved_invis_chars_first_line = saved_physical_chars = 0;
2389: }
2390:
2391: char *
2392: _rl_make_prompt_for_search (pchar)
2393: int pchar;
2394: {
2395: int len;
2396: char *pmt, *p;
2397:
2398: rl_save_prompt ();
2399:
2400: /* We've saved the prompt, and can do anything with the various prompt
2401: strings we need before they're restored. We want the unexpanded
2402: portion of the prompt string after any final newline. */
2403: p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
2404: if (p == 0)
2405: {
2406: len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
2407: pmt = (char *)xmalloc (len + 2);
2408: if (len)
2409: strcpy (pmt, rl_prompt);
2410: pmt[len] = pchar;
2411: pmt[len+1] = '\0';
2412: }
2413: else
2414: {
2415: p++;
2416: len = strlen (p);
2417: pmt = (char *)xmalloc (len + 2);
2418: if (len)
2419: strcpy (pmt, p);
2420: pmt[len] = pchar;
2421: pmt[len+1] = '\0';
2422: }
2423:
2424: /* will be overwritten by expand_prompt, called from rl_message */
2425: prompt_physical_chars = saved_physical_chars + 1;
2426: return pmt;
2427: }
2428:
2429: /* Quick redisplay hack when erasing characters at the end of the line. */
2430: void
2431: _rl_erase_at_end_of_line (l)
2432: int l;
2433: {
2434: register int i;
2435:
2436: _rl_backspace (l);
2437: for (i = 0; i < l; i++)
2438: putc (' ', rl_outstream);
2439: _rl_backspace (l);
2440: for (i = 0; i < l; i++)
2441: visible_line[--_rl_last_c_pos] = '\0';
2442: rl_display_fixed++;
2443: }
2444:
2445: /* Clear to the end of the line. COUNT is the minimum
2446: number of character spaces to clear, */
2447: void
2448: _rl_clear_to_eol (count)
2449: int count;
2450: {
2451: #ifndef __MSDOS__
2452: if (_rl_term_clreol)
2453: tputs (_rl_term_clreol, 1, _rl_output_character_function);
2454: else
2455: #endif
2456: if (count)
2457: space_to_eol (count);
2458: }
2459:
2460: /* Clear to the end of the line using spaces. COUNT is the minimum
2461: number of character spaces to clear, */
2462: static void
2463: space_to_eol (count)
2464: int count;
2465: {
2466: register int i;
2467:
2468: for (i = 0; i < count; i++)
2469: putc (' ', rl_outstream);
2470:
2471: _rl_last_c_pos += count;
2472: }
2473:
2474: void
2475: _rl_clear_screen ()
2476: {
2477: #ifndef __DJGPP__
2478: if (_rl_term_clrpag)
2479: tputs (_rl_term_clrpag, 1, _rl_output_character_function);
2480: else
2481: rl_crlf ();
2482: #else
2483: ScreenClear ();
2484: ScreenSetCursor (0, 0);
2485: #endif /* __DJGPP__ */
2486: }
2487:
2488: /* Insert COUNT characters from STRING to the output stream at column COL. */
2489: static void
2490: insert_some_chars (string, count, col)
2491: char *string;
2492: int count, col;
2493: {
2494: open_some_spaces (col);
2495: _rl_output_some_chars (string, count);
2496: }
2497:
2498: /* Insert COL spaces, keeping the cursor at the same position. We follow the
2499: ncurses documentation and use either im/ei with explicit spaces, or IC/ic
2500: by itself. We assume there will either be ei or we don't need to use it. */
2501: static void
2502: open_some_spaces (col)
2503: int col;
2504: {
2505: #if !defined (__MSDOS__) && !defined (__MINGW32__)
2506: char *buffer;
2507: register int i;
2508:
2509: /* If IC is defined, then we do not have to "enter" insert mode. */
2510: if (_rl_term_IC)
2511: {
2512: buffer = tgoto (_rl_term_IC, 0, col);
2513: tputs (buffer, 1, _rl_output_character_function);
2514: }
2515: else if (_rl_term_im && *_rl_term_im)
2516: {
2517: tputs (_rl_term_im, 1, _rl_output_character_function);
2518: /* just output the desired number of spaces */
2519: for (i = col; i--; )
2520: _rl_output_character_function (' ');
2521: /* If there is a string to turn off insert mode, use it now. */
2522: if (_rl_term_ei && *_rl_term_ei)
2523: tputs (_rl_term_ei, 1, _rl_output_character_function);
2524: /* and move back the right number of spaces */
2525: _rl_backspace (col);
2526: }
2527: else if (_rl_term_ic && *_rl_term_ic)
2528: {
2529: /* If there is a special command for inserting characters, then
2530: use that first to open up the space. */
2531: for (i = col; i--; )
2532: tputs (_rl_term_ic, 1, _rl_output_character_function);
2533: }
2534: #endif /* !__MSDOS__ && !__MINGW32__ */
2535: }
2536:
2537: /* Delete COUNT characters from the display line. */
2538: static void
2539: delete_chars (count)
2540: int count;
2541: {
2542: if (count > _rl_screenwidth) /* XXX */
2543: return;
2544:
2545: #if !defined (__MSDOS__) && !defined (__MINGW32__)
2546: if (_rl_term_DC && *_rl_term_DC)
2547: {
2548: char *buffer;
2549: buffer = tgoto (_rl_term_DC, count, count);
2550: tputs (buffer, count, _rl_output_character_function);
2551: }
2552: else
2553: {
2554: if (_rl_term_dc && *_rl_term_dc)
2555: while (count--)
2556: tputs (_rl_term_dc, 1, _rl_output_character_function);
2557: }
2558: #endif /* !__MSDOS__ && !__MINGW32__ */
2559: }
2560:
2561: void
2562: _rl_update_final ()
2563: {
2564: int full_lines;
2565:
2566: full_lines = 0;
2567: /* If the cursor is the only thing on an otherwise-blank last line,
2568: compensate so we don't print an extra CRLF. */
2569: if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
2570: visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
2571: {
2572: _rl_vis_botlin--;
2573: full_lines = 1;
2574: }
2575: _rl_move_vert (_rl_vis_botlin);
2576: /* If we've wrapped lines, remove the final xterm line-wrap flag. */
2577: if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
2578: {
2579: char *last_line;
2580:
2581: last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
2582: cpos_buffer_position = -1; /* don't know where we are in buffer */
2583: _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */
2584: _rl_clear_to_eol (0);
2585: putc (last_line[_rl_screenwidth - 1], rl_outstream);
2586: }
2587: _rl_vis_botlin = 0;
2588: rl_crlf ();
2589: fflush (rl_outstream);
2590: rl_display_fixed++;
2591: }
2592:
2593: /* Move to the start of the current line. */
2594: static void
2595: cr ()
2596: {
2597: if (_rl_term_cr)
2598: {
2599: #if defined (__MSDOS__)
2600: putc ('\r', rl_outstream);
2601: #else
2602: tputs (_rl_term_cr, 1, _rl_output_character_function);
2603: #endif
2604: _rl_last_c_pos = 0;
2605: }
2606: }
2607:
2608: /* Redraw the last line of a multi-line prompt that may possibly contain
2609: terminal escape sequences. Called with the cursor at column 0 of the
2610: line to draw the prompt on. */
2611: static void
2612: redraw_prompt (t)
2613: char *t;
2614: {
2615: char *oldp;
2616:
2617: oldp = rl_display_prompt;
2618: rl_save_prompt ();
2619:
2620: rl_display_prompt = t;
2621: local_prompt = expand_prompt (t, &prompt_visible_length,
2622: &prompt_last_invisible,
2623: &prompt_invis_chars_first_line,
2624: &prompt_physical_chars);
2625: local_prompt_prefix = (char *)NULL;
2626: local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
2627:
2628: rl_forced_update_display ();
2629:
2630: rl_display_prompt = oldp;
2631: rl_restore_prompt();
2632: }
2633:
2634: /* Redisplay the current line after a SIGWINCH is received. */
2635: void
2636: _rl_redisplay_after_sigwinch ()
2637: {
2638: char *t;
2639:
2640: /* Clear the last line (assuming that the screen size change will result in
2641: either more or fewer characters on that line only) and put the cursor at
2642: column 0. Make sure the right thing happens if we have wrapped to a new
2643: screen line. */
2644: if (_rl_term_cr)
2645: {
2646: _rl_move_vert (_rl_vis_botlin);
2647:
2648: #if defined (__MSDOS__)
2649: putc ('\r', rl_outstream);
2650: #else
2651: tputs (_rl_term_cr, 1, _rl_output_character_function);
2652: #endif
2653: _rl_last_c_pos = 0;
2654: #if defined (__MSDOS__)
2655: space_to_eol (_rl_screenwidth);
2656: putc ('\r', rl_outstream);
2657: #else
2658: if (_rl_term_clreol)
2659: tputs (_rl_term_clreol, 1, _rl_output_character_function);
2660: else
2661: {
2662: space_to_eol (_rl_screenwidth);
2663: tputs (_rl_term_cr, 1, _rl_output_character_function);
2664: }
2665: #endif
2666: if (_rl_last_v_pos > 0)
2667: _rl_move_vert (0);
2668: }
2669: else
2670: rl_crlf ();
2671:
2672: /* Redraw only the last line of a multi-line prompt. */
2673: t = strrchr (rl_display_prompt, '\n');
2674: if (t)
2675: redraw_prompt (++t);
2676: else
2677: rl_forced_update_display ();
2678: }
2679:
2680: void
2681: _rl_clean_up_for_exit ()
2682: {
2683: if (_rl_echoing_p)
2684: {
1.1.1.2 ! misho 2685: if (_rl_vis_botlin > 0) /* minor optimization plus bug fix */
! 2686: _rl_move_vert (_rl_vis_botlin);
1.1 misho 2687: _rl_vis_botlin = 0;
2688: fflush (rl_outstream);
2689: rl_restart_output (1, 0);
2690: }
2691: }
2692:
2693: void
2694: _rl_erase_entire_line ()
2695: {
2696: cr ();
2697: _rl_clear_to_eol (0);
2698: cr ();
2699: fflush (rl_outstream);
2700: }
2701:
2702: /* return the `current display line' of the cursor -- the number of lines to
2703: move up to get to the first screen line of the current readline line. */
2704: int
2705: _rl_current_display_line ()
2706: {
2707: int ret, nleft;
2708:
2709: /* Find out whether or not there might be invisible characters in the
2710: editing buffer. */
2711: if (rl_display_prompt == rl_prompt)
2712: nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
2713: else
2714: nleft = _rl_last_c_pos - _rl_screenwidth;
2715:
2716: if (nleft > 0)
2717: ret = 1 + nleft / _rl_screenwidth;
2718: else
2719: ret = 0;
2720:
2721: return ret;
2722: }
2723:
2724: #if defined (HANDLE_MULTIBYTE)
2725: /* Calculate the number of screen columns occupied by STR from START to END.
2726: In the case of multibyte characters with stateful encoding, we have to
2727: scan from the beginning of the string to take the state into account. */
2728: static int
2729: _rl_col_width (str, start, end, flags)
2730: const char *str;
2731: int start, end, flags;
2732: {
2733: wchar_t wc;
2734: mbstate_t ps;
2735: int tmp, point, width, max;
2736:
2737: if (end <= start)
2738: return 0;
2739: if (MB_CUR_MAX == 1 || rl_byte_oriented)
2740: /* this can happen in some cases where it's inconvenient to check */
2741: return (end - start);
2742:
2743: memset (&ps, 0, sizeof (mbstate_t));
2744:
2745: point = 0;
2746: max = end;
2747:
2748: /* Try to short-circuit common cases. The adjustment to remove wrap_offset
2749: is done by the caller. */
2750: /* 1. prompt string */
2751: if (flags && start == 0 && end == local_prompt_len && memcmp (str, local_prompt, local_prompt_len) == 0)
2752: return (prompt_physical_chars + wrap_offset);
2753: /* 2. prompt string + line contents */
2754: else if (flags && start == 0 && local_prompt_len > 0 && end > local_prompt_len && local_prompt && memcmp (str, local_prompt, local_prompt_len) == 0)
2755: {
2756: tmp = prompt_physical_chars + wrap_offset;
2757: /* XXX - try to call ourselves recursively with non-prompt portion */
2758: tmp += _rl_col_width (str, local_prompt_len, end, flags);
2759: return (tmp);
2760: }
2761:
2762: while (point < start)
2763: {
2764: tmp = mbrlen (str + point, max, &ps);
2765: if (MB_INVALIDCH ((size_t)tmp))
2766: {
2767: /* In this case, the bytes are invalid or too short to compose a
2768: multibyte character, so we assume that the first byte represents
2769: a single character. */
2770: point++;
2771: max--;
2772:
2773: /* Clear the state of the byte sequence, because in this case the
2774: effect of mbstate is undefined. */
2775: memset (&ps, 0, sizeof (mbstate_t));
2776: }
2777: else if (MB_NULLWCH (tmp))
2778: break; /* Found '\0' */
2779: else
2780: {
2781: point += tmp;
2782: max -= tmp;
2783: }
2784: }
2785:
2786: /* If START is not a byte that starts a character, then POINT will be
2787: greater than START. In this case, assume that (POINT - START) gives
2788: a byte count that is the number of columns of difference. */
2789: width = point - start;
2790:
2791: while (point < end)
2792: {
2793: tmp = mbrtowc (&wc, str + point, max, &ps);
2794: if (MB_INVALIDCH ((size_t)tmp))
2795: {
2796: /* In this case, the bytes are invalid or too short to compose a
2797: multibyte character, so we assume that the first byte represents
2798: a single character. */
2799: point++;
2800: max--;
2801:
2802: /* and assume that the byte occupies a single column. */
2803: width++;
2804:
2805: /* Clear the state of the byte sequence, because in this case the
2806: effect of mbstate is undefined. */
2807: memset (&ps, 0, sizeof (mbstate_t));
2808: }
2809: else if (MB_NULLWCH (tmp))
2810: break; /* Found '\0' */
2811: else
2812: {
2813: point += tmp;
2814: max -= tmp;
2815: tmp = WCWIDTH(wc);
2816: width += (tmp >= 0) ? tmp : 1;
2817: }
2818: }
2819:
2820: width += point - end;
2821:
2822: return width;
2823: }
2824: #endif /* HANDLE_MULTIBYTE */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>