2 * zle_refresh.c - screen update
4 * This file is part of zsh, the Z shell.
6 * Copyright (c) 1992-1997 Paul Falstad
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
15 * In no event shall Paul Falstad or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Paul Falstad and the Zsh Development Group have been advised of
19 * the possibility of such damage.
21 * Paul Falstad and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose. The software
24 * provided hereunder is on an "as is" basis, and Paul Falstad and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
32 #ifdef MULTIBYTE_SUPPORT
34 * Handling for glyphs that contain more than one wide character,
35 * if ZLE_COMBINING_CHARS is set. Each glyph is one character with
36 * non-zero width followed by an arbitrary (but typically small)
37 * number of characters that have zero width (combining characters).
39 * The allocated size for each array is given by ?mw_size; nmw_ind
40 * is the next free element, i.e. nmwbuf[nmw_ind] will be the next
41 * element to be written (we never insert into omwbuf). We initialise
42 * nmw_ind to 1 to avoid the index stored in the character looking like a
43 * NULL. This wastees a word but it's safer than messing with pointers.
45 * The layout of the buffer is as a string of entries that consist of multiple
46 * elements of the allocated array with no boundary (the code keeps track of
47 * where each entry starts). Note distinction between (logical) entries and
48 * (array) elements. Each entry consists of an element giving the total
49 * number of wide characters for the entry (there are N+1 wide characters,
50 * where N >= 1 is the number of trailing zero width characters), followed by
54 *omwbuf
= NULL
, /* old multiword glyph buffer */
55 *nmwbuf
= NULL
; /* new multiword glyph buffer */
59 * Compare if two characters are equal.
61 #ifdef MULTIBYTE_SUPPORT
63 * We may need to compare values in multiword arrays. As the arrays are
64 * different for the old and new video arrays, it is vital that the comparison
65 * always be done in the correct order: an element of the old video array,
66 * followed by an element of the new one. In this case, having ascertained
67 * that both elements are multiword (because they have the some attributes),
68 * we do the character comparison in two stages: first we check that the
69 * lengths are the same, then we check that the characters stored are the
70 * same. This ensures we can't read past the end of either array. If either
71 * character is a constant, then TXT_MULTIWORD_MASK is guaranteed not to be
72 * set and this doesn't matter.
74 #define ZR_equal(oldzr, newzr) \
75 ((oldzr).atr == (newzr).atr && \
76 (((oldzr).atr & TXT_MULTIWORD_MASK) ? \
77 (omwbuf[(oldzr).chr] == nmwbuf[(newzr).chr] && \
78 !memcmp(omwbuf + (oldzr).chr + 1, nmwbuf + (newzr).chr + 1, \
79 omwbuf[(oldzr).chr] * sizeof(*omwbuf))) : \
80 (oldzr).chr == (newzr).chr))
82 #define ZR_equal(zr1, zr2) ((zr1).chr == (zr2).chr && (zr1).atr == (zr2).atr)
86 ZR_memset(REFRESH_ELEMENT
*dst
, REFRESH_ELEMENT rc
, int len
)
92 #define ZR_memcpy(d, s, l) memcpy((d), (s), (l)*sizeof(REFRESH_ELEMENT))
95 ZR_strcpy(REFRESH_ELEMENT
*dst
, const REFRESH_ELEMENT
*src
)
97 while ((*dst
++ = *src
++).chr
!= ZWC('\0'))
102 ZR_strlen(const REFRESH_ELEMENT
*wstr
)
106 while (wstr
++->chr
!= ZWC('\0'))
113 * Simplified strcmp: we don't need the sign, just whether
114 * the strings and their attributes are equal.
116 * In the multibyte case, the two elements must be in the order
117 * element from old video array, element from new video array.
120 ZR_strncmp(const REFRESH_ELEMENT
*oldwstr
, const REFRESH_ELEMENT
*newwstr
,
124 if ((!(oldwstr
->atr
& TXT_MULTIWORD_MASK
) && !oldwstr
->chr
) ||
125 (!(newwstr
->atr
& TXT_MULTIWORD_MASK
) && !newwstr
->chr
))
126 return !ZR_equal(*oldwstr
, *newwstr
);
127 if (!ZR_equal(*oldwstr
, *newwstr
))
136 #include "zle_refresh.pro"
141 * These are always output from the start, except in the special
142 * case where we are sure each character in the prompt corresponds
143 * to a character on screen.
147 char *lpromptbuf
, *rpromptbuf
;
149 /* Text attributes after displaying prompts */
152 unsigned pmpt_attr
, rpmpt_attr
;
154 /* number of lines displayed */
157 mod_export
int nlnct
;
159 /* Most lines of the buffer we've shown at once with the current list *
160 * showing. == 0 if there is no list. == -1 if a new list has just *
161 * been put on the screen. == -2 if zrefresh() needs to put up a new *
165 mod_export
int showinglist
;
167 /* > 0 if a completion list is displayed below the prompt,
168 * < 0 if a list is displayed above the prompt. */
171 mod_export
int listshown
;
173 /* Length of last list displayed (if it is below the prompt). */
176 mod_export
int lastlistlen
;
178 /* Non-zero if ALWAYS_LAST_PROMPT has been used, meaning that the *
179 * screen below the buffer display should not be cleared by *
180 * zrefresh(), but should be by trashzle(). */
183 mod_export
int clearflag
;
185 /* Non-zero if zrefresh() should clear the list below the prompt. */
188 mod_export
int clearlist
;
190 /* Zle in trashed state - updates may be subtly altered */
196 * Information used by PREDISPLAY and POSTDISPLAY parameters which
197 * add non-editable text to that being displayed.
200 ZLE_STRING_T predisplay
, postdisplay
;
202 int predisplaylen
, postdisplaylen
;
206 * Attributes used by default on the command line, and
207 * attributes for highlighting special (unprintable) characters
208 * displayed on screen.
211 static int default_atr_on
, special_atr_on
;
213 /* Flags for the region_highlight structure */
215 /* Offsets include predisplay */
220 * Attributes used for highlighting regions.
223 struct region_highlight
{
224 /* Attributes turned on in the region */
226 /* Start of the region */
229 * End of the region: position of the first character not highlighted
230 * (the same system as for point and mark).
234 * Any of the flags defined above.
239 * Array of region highlights, no special termination.
240 * The first element (0) always describes the region between
241 * point and mark. Any other elements are set by the user
242 * via the parameter region_highlight.
244 struct region_highlight
*region_highlights
;
246 * Count of special uses of region highlighting, which account
247 * for the first few elements of region_highlights.
248 * 0: region between point and mark
251 #define N_SPECIAL_HIGHLIGHTS (2)
253 * Number of elements in region_highlights.
254 * This includes the special elements above.
256 int n_region_highlights
;
259 * Flag that highlighting of the region is active.
265 /* cost of last update */
269 # define SELECT_ADD_COST(X) (cost += X)
270 # define zputc(a) (zwcputc(a, NULL), cost++)
271 # define zwrite(a, b) (zwcwrite((a), (b)), \
272 cost += ((b) * ZLE_CHAR_SIZE))
274 # define SELECT_ADD_COST(X)
275 # define zputc(a) zwcputc(a, NULL)
276 # define zwrite(a, b) zwcwrite((a), (b))
279 static const REFRESH_ELEMENT zr_cr
= { ZWC('\r'), 0 };
280 static const REFRESH_ELEMENT zr_dt
= { ZWC('.'), 0 };
281 static const REFRESH_ELEMENT zr_nl
= { ZWC('\n'), 0 };
282 static const REFRESH_ELEMENT zr_sp
= { ZWC(' '), 0 };
283 static const REFRESH_ELEMENT zr_ht
= { ZWC('\t'), 0 };
284 static const REFRESH_ELEMENT zr_zr
= { ZWC('\0'), 0 };
287 * Constant arrays to be copied into place: these are memcpy'd,
288 * so don't have terminating NULLs.
290 static const REFRESH_ELEMENT zr_end_ellipsis
[] = {
299 #define ZR_END_ELLIPSIS_SIZE \
300 ((int)(sizeof(zr_end_ellipsis)/sizeof(zr_end_ellipsis[0])))
302 static const REFRESH_ELEMENT zr_mid_ellipsis1
[] = {
310 #define ZR_MID_ELLIPSIS1_SIZE \
311 ((int)(sizeof(zr_mid_ellipsis1)/sizeof(zr_mid_ellipsis1[0])))
313 static const REFRESH_ELEMENT zr_mid_ellipsis2
[] = {
317 #define ZR_MID_ELLIPSIS2_SIZE \
318 ((int)(sizeof(zr_mid_ellipsis2)/sizeof(zr_mid_ellipsis2[0])))
320 static const REFRESH_ELEMENT zr_start_ellipsis
[] = {
327 #define ZR_START_ELLIPSIS_SIZE \
328 ((int)(sizeof(zr_start_ellipsis)/sizeof(zr_start_ellipsis[0])))
331 * Parse the variable zle_highlight to decide how to highlight characters
332 * and regions. Set defaults for anything not explicitly covered.
337 zle_set_highlight(void)
339 char **atrs
= getaparam("zle_highlight");
340 int special_atr_on_set
= 0;
341 int region_atr_on_set
= 0;
342 int isearch_atr_on_set
= 0;
343 struct region_highlight
*rhp
;
345 special_atr_on
= default_atr_on
= 0;
346 if (!region_highlights
) {
347 region_highlights
= (struct region_highlight
*)
348 zshcalloc(N_SPECIAL_HIGHLIGHTS
*sizeof(struct region_highlight
));
349 n_region_highlights
= N_SPECIAL_HIGHLIGHTS
;
351 for (rhp
= region_highlights
;
352 rhp
< region_highlights
+ N_SPECIAL_HIGHLIGHTS
;
359 for (; *atrs
; atrs
++) {
360 if (!strcmp(*atrs
, "none")) {
361 /* reset attributes for consistency... usually unnecessary */
362 special_atr_on
= default_atr_on
= 0;
363 special_atr_on_set
= region_atr_on_set
=
364 isearch_atr_on_set
= 1;
365 } else if (strpfx("default:", *atrs
)) {
366 match_highlight(*atrs
+ 8, &default_atr_on
);
367 } else if (strpfx("special:", *atrs
)) {
368 match_highlight(*atrs
+ 8, &special_atr_on
);
369 special_atr_on_set
= 1;
370 } else if (strpfx("region:", *atrs
)) {
371 match_highlight(*atrs
+ 7, ®ion_highlights
->atr
);
372 region_atr_on_set
= 1;
373 } else if (strpfx("isearch:", *atrs
)) {
374 match_highlight(*atrs
+ 8, &(region_highlights
[1].atr
));
375 isearch_atr_on_set
= 1;
381 if (!special_atr_on_set
)
382 special_atr_on
= TXTSTANDOUT
;
383 if (!region_atr_on_set
)
384 region_highlights
->atr
= TXTSTANDOUT
;
385 if (!isearch_atr_on_set
)
386 region_highlights
[1].atr
= TXTUNDERLINE
;
388 allocate_colour_buffer();
394 zle_free_highlight(void)
396 free_colour_buffer();
400 * Interface to the region_highlight ZLE parameter.
401 * Converts betwen a format like "P32 42 underline,bold" to
402 * the format in the region_highlights variable. Note that
403 * the region_highlights variable stores the internal (point/mark)
404 * region in element zero.
409 get_region_highlight(UNUSED(Param pm
))
411 int arrsize
= n_region_highlights
;
412 char **retarr
, **arrp
;
413 struct region_highlight
*rhp
;
415 /* region_highlights may not have been set yet */
417 arrsize
-= N_SPECIAL_HIGHLIGHTS
;
418 arrp
= retarr
= (char **)zhalloc((arrsize
+1)*sizeof(char *));
420 /* ignore special highlighting */
421 for (rhp
= region_highlights
+ N_SPECIAL_HIGHLIGHTS
;
424 char digbuf1
[DIGBUFSIZE
], digbuf2
[DIGBUFSIZE
];
425 int atrlen
= 0, alloclen
;
427 sprintf(digbuf1
, "%d", rhp
->start
);
428 sprintf(digbuf2
, "%d", rhp
->end
);
430 atrlen
= output_highlight(rhp
->atr
, NULL
);
431 alloclen
= atrlen
+ strlen(digbuf1
) + strlen(digbuf2
) +
432 3; /* 2 spaces, 1 0 */
433 if (rhp
->flags
& ZRH_PREDISPLAY
)
434 alloclen
+= 2; /* "P " */
435 *arrp
= (char *)zhalloc(alloclen
* sizeof(char));
437 * On input we allow a space after the flags.
438 * I haven't put a space here because I think it's
439 * marginally easier to have the output always split
440 * into three words, and then check the first to
441 * see if there are flags. However, it's arguable.
443 sprintf(*arrp
, "%s%s %s ",
444 (rhp
->flags
& ZRH_PREDISPLAY
) ? "P" : "",
446 (void)output_highlight(rhp
->atr
, *arrp
+ strlen(*arrp
));
454 * The parameter system requires the pm argument, but this
455 * may be NULL if called directly.
460 set_region_highlight(UNUSED(Param pm
), char **aval
)
463 struct region_highlight
*rhp
;
465 len
= aval
? arrlen(aval
) : 0;
466 if (n_region_highlights
!= len
+ N_SPECIAL_HIGHLIGHTS
) {
467 /* no null termination, but include special highlighting at start */
468 n_region_highlights
= len
+ N_SPECIAL_HIGHLIGHTS
;
469 region_highlights
= (struct region_highlight
*)
470 zrealloc(region_highlights
,
471 sizeof(struct region_highlight
) * n_region_highlights
);
477 for (rhp
= region_highlights
+ N_SPECIAL_HIGHLIGHTS
;
480 char *strp
, *oldstrp
;
483 if (*oldstrp
== 'P') {
484 rhp
->flags
= ZRH_PREDISPLAY
;
489 while (inblank(*oldstrp
))
492 rhp
->start
= (int)zstrtol(oldstrp
, &strp
, 10);
496 while (inblank(*strp
))
500 rhp
->end
= (int)zstrtol(strp
, &strp
, 10);
504 while (inblank(*strp
))
507 match_highlight(strp
, &rhp
->atr
);
514 unset_region_highlight(Param pm
, int exp
)
517 set_region_highlight(pm
, NULL
);
523 /* The last attributes that were on. */
527 * Clear the last attributes that we set: used when we're going
528 * to be outputting stuff that shouldn't show up as text.
531 clearattributes(void)
534 settextattributes(TXT_ATTR_OFF_FROM_ON(lastatr
));
540 * Output a termcap capability, clearing any text attributes so
541 * as not to mess up the display.
552 * Output the character. This must come from the new video
553 * buffer, nbuf, since we access the multiword buffer nmwbuf
556 * curatrp may be NULL, otherwise points to an integer specifying
557 * what attributes were turned on for a character output immediately
558 * before, in order to optimise output of attribute changes.
563 zwcputc(const REFRESH_ELEMENT
*c
, int *curatrp
)
566 * Safety: turn attributes off if last heard of turned on.
567 * This differs from *curatrp, which is an optimisation for
568 * writing lots of stuff at once.
570 #ifdef MULTIBYTE_SUPPORT
573 VARARR(char, mbtmp
, MB_CUR_MAX
+ 1);
576 if (lastatr
& ~c
->atr
) {
577 /* Stuff on we don't want, turn it off */
578 settextattributes(TXT_ATTR_OFF_FROM_ON(lastatr
& ~c
->atr
));
583 * Don't output "on" attributes in a string of characters with
584 * the same attributes. Be careful in case a different colour
587 if ((c
->atr
& TXT_ATTR_ON_MASK
) &&
589 ((*curatrp
& TXT_ATTR_ON_VALUES_MASK
) !=
590 (c
->atr
& TXT_ATTR_ON_VALUES_MASK
)))) {
591 /* Record just the control flags we might need to turn off... */
592 lastatr
= c
->atr
& TXT_ATTR_ON_MASK
;
593 /* ...but set including the values for colour attributes */
594 settextattributes(c
->atr
& TXT_ATTR_ON_VALUES_MASK
);
597 #ifdef MULTIBYTE_SUPPORT
598 if (c
->atr
& TXT_MULTIWORD_MASK
) {
599 /* Multiword glyph stored in nmwbuf */
600 int nchars
= nmwbuf
[c
->chr
];
601 REFRESH_CHAR
*wcptr
= nmwbuf
+ c
->chr
+ 1;
603 memset(&mbstate
, 0, sizeof(mbstate_t));
605 if ((i
= wcrtomb(mbtmp
, (wchar_t)*wcptr
++, &mbstate
)) > 0)
606 fwrite(mbtmp
, i
, 1, shout
);
608 } else if (c
->chr
!= WEOF
) {
609 memset(&mbstate
, 0, sizeof(mbstate_t));
610 if ((i
= wcrtomb(mbtmp
, (wchar_t)c
->chr
, &mbstate
)) > 0)
611 fwrite(mbtmp
, i
, 1, shout
);
614 fputc(c
->chr
, shout
);
618 * Always output "off" attributes since we only turn off at
619 * the end of a chunk of highlighted text.
621 if (c
->atr
& TXT_ATTR_OFF_MASK
) {
622 settextattributes(c
->atr
& TXT_ATTR_OFF_MASK
);
623 lastatr
&= ~((c
->atr
& TXT_ATTR_OFF_MASK
) >> TXT_ATTR_OFF_ON_SHIFT
);
627 * Remember the current attributes: those that are turned
628 * on, less those that are turned off again. Include
629 * colour attributes here in case the colour changes to
630 * another non-default one.
632 *curatrp
= (c
->atr
& TXT_ATTR_ON_VALUES_MASK
) &
633 ~((c
->atr
& TXT_ATTR_OFF_MASK
) >> TXT_ATTR_OFF_ON_SHIFT
);
638 zwcwrite(const REFRESH_STRING s
, size_t i
)
643 for (j
= 0; j
< i
; j
++)
644 zwcputc(s
+ j
, &curatr
);
645 return i
; /* TODO something better for error indication */
648 /* Oct/Nov 94: <mason> some code savagely redesigned to fix several bugs -
649 refreshline() & tc_rightcurs() majorly rewritten; zrefresh() fixed -
650 I've put my fingers into just about every routine in here -
651 any queries about updates to mason@primenet.com.au */
653 static REFRESH_STRING
654 *nbuf
= NULL
, /* new video buffer line-by-line array */
655 *obuf
= NULL
; /* old video buffer line-by-line array */
656 static int more_start
, /* more text before start of screen? */
657 more_end
, /* more stuff after end of screen? */
658 olnct
, /* previous number of lines */
659 ovln
, /* previous video cursor position line */
660 lpromptw
, rpromptw
, /* prompt widths on screen */
661 lpromptwof
, /* left prompt width with real end position */
662 lprompth
, /* lines taken up by the prompt */
663 rprompth
, /* right prompt height */
664 vcs
, vln
, /* video cursor position column & line */
665 vmaxln
, /* video maximum number of lines */
666 winw
, winh
, rwinh
, /* window width & height */
667 winpos
, /* singlelinezle: line's position in window */
668 winprompt
, /* singlelinezle: part of lprompt showing */
669 winw_alloc
= -1, /* allocated window width */
670 winh_alloc
= -1; /* allocates window height */
671 #ifdef MULTIBYTE_SUPPORT
673 omw_size
, /* allocated size of omwbuf */
674 nmw_size
, /* allocated size of nmwbuf */
675 nmw_ind
; /* next insert point in nmw_ind */
679 * Number of words to allocate in one go for the multiword buffers.
681 #define DEF_MWBUF_ALLOC (32)
688 for (ln
= 0; ln
!= winh_alloc
; ln
++) {
689 zfree(nbuf
[ln
], (winw_alloc
+ 2) * sizeof(**nbuf
));
690 zfree(obuf
[ln
], (winw_alloc
+ 2) * sizeof(**obuf
));
694 #ifdef MULTIBYTE_SUPPORT
695 zfree(nmwbuf
, nmw_size
* sizeof(*nmwbuf
));
696 zfree(omwbuf
, omw_size
* sizeof(*omwbuf
));
697 omw_size
= nmw_size
= 0;
711 winw
= columns
; /* terminal width */
712 if (termflags
& TERM_SHORT
)
715 winh
= (lines
< 2) ? 24 : lines
;
716 rwinh
= lines
; /* keep the real number of lines */
717 vln
= vmaxln
= winprompt
= 0;
719 if (winw_alloc
!= winw
|| winh_alloc
!= winh
) {
721 nbuf
= (REFRESH_STRING
*)zshcalloc((winh
+ 1) * sizeof(*nbuf
));
722 obuf
= (REFRESH_STRING
*)zshcalloc((winh
+ 1) * sizeof(*obuf
));
723 nbuf
[0] = (REFRESH_STRING
)zalloc((winw
+ 2) * sizeof(**nbuf
));
724 obuf
[0] = (REFRESH_STRING
)zalloc((winw
+ 2) * sizeof(**obuf
));
726 #ifdef MULTIBYTE_SUPPORT
727 nmw_size
= DEF_MWBUF_ALLOC
;
729 nmwbuf
= (REFRESH_CHAR
*)zalloc(nmw_size
* sizeof(*nmwbuf
));
731 omw_size
= DEF_MWBUF_ALLOC
;
732 omwbuf
= (REFRESH_CHAR
*)zalloc(omw_size
* sizeof(*omwbuf
));
738 for (ln
= 0; ln
!= winh
+ 1; ln
++) {
750 * countprompt() now correctly handles multibyte input.
752 countprompt(lpromptbuf
, &lpromptwof
, &lprompth
, 1);
753 countprompt(rpromptbuf
, &rpromptw
, &rprompth
, 0);
754 if (lpromptwof
!= winw
)
755 lpromptw
= lpromptwof
;
762 ZR_memset(nbuf
[0], zr_sp
, lpromptw
);
763 ZR_memset(obuf
[0], zr_sp
, lpromptw
);
764 nbuf
[0][lpromptw
] = obuf
[0][lpromptw
] = zr_zr
;
775 * Nov 96: <mason> changed to single line scroll
780 scrollwindow(int tline
)
786 for (t0
= tline
; t0
< winh
- 1; t0
++)
787 nbuf
[t0
] = nbuf
[t0
+ 1];
795 * Parameters in zrefresh used for communicating with next-line functions.
798 int canscroll
; /* number of lines we are allowed to scroll */
799 int ln
; /* current line we're working on */
800 int more_status
; /* more stuff in status line */
801 int nvcs
; /* video cursor column */
802 int nvln
; /* video cursor line */
803 int tosln
; /* tmp in statusline stuff */
804 REFRESH_STRING s
; /* pointer into the video buffer */
805 REFRESH_STRING sen
; /* pointer to end of the video buffer (eol) */
807 typedef struct rparams
*Rparams
;
809 static int cleareol
, /* clear to end-of-line (if can't cleareod) */
810 clearf
, /* alwayslastprompt used immediately before */
811 put_rpmpt
, /* whether we should display right-prompt */
812 oput_rpmpt
, /* whether displayed right-prompt last time */
813 oxtabs
, /* oxtabs - tabs expand to spaces if set */
814 numscrolls
, onumscrolls
;
817 * Go to the next line in the main display area. Return 1 if we should abort
818 * processing the line loop at this point, else 0.
820 * If wrapped is non-zero, text wrapped, so output newline.
821 * Otherwise, text not wrapped, so output null.
824 nextline(Rparams rpms
, int wrapped
)
826 nbuf
[rpms
->ln
][winw
+1] = wrapped
? zr_nl
: zr_zr
;
828 if (rpms
->ln
!= winh
- 1)
831 if (!rpms
->canscroll
) {
832 if (rpms
->nvln
!= -1 && rpms
->nvln
!= winh
- 1
833 && (numscrolls
!= onumscrolls
- 1
834 || rpms
->nvln
<= winh
/ 2))
837 rpms
->canscroll
= winh
/ 2;
841 if (rpms
->nvln
!= -1)
845 nbuf
[rpms
->ln
] = (REFRESH_STRING
)zalloc((winw
+ 2) * sizeof(**nbuf
));
846 rpms
->s
= nbuf
[rpms
->ln
];
847 rpms
->sen
= rpms
->s
+ winw
;
854 * Go to the next line in the status area.
857 snextline(Rparams rpms
)
860 if (rpms
->ln
!= winh
- 1)
863 if (rpms
->tosln
> rpms
->ln
) {
865 if (rpms
->nvln
> 1) {
870 } else if (rpms
->tosln
> 2 && rpms
->nvln
> 1) {
872 if (rpms
->tosln
<= rpms
->nvln
) {
876 scrollwindow(rpms
->tosln
);
880 rpms
->more_status
= 1;
881 scrollwindow(rpms
->tosln
+ 1);
884 nbuf
[rpms
->ln
] = (REFRESH_STRING
)zalloc((winw
+ 2) * sizeof(**nbuf
));
885 rpms
->s
= nbuf
[rpms
->ln
];
886 rpms
->sen
= rpms
->s
+ winw
;
892 settextattributes(int atr
)
894 if (txtchangeisset(atr
, TXTNOBOLDFACE
))
895 tsetcap(TCALLATTRSOFF
, 0);
896 if (txtchangeisset(atr
, TXTNOSTANDOUT
))
897 tsetcap(TCSTANDOUTEND
, 0);
898 if (txtchangeisset(atr
, TXTNOUNDERLINE
))
899 tsetcap(TCUNDERLINEEND
, 0);
900 if (txtchangeisset(atr
, TXTBOLDFACE
))
901 tsetcap(TCBOLDFACEBEG
, 0);
902 if (txtchangeisset(atr
, TXTSTANDOUT
))
903 tsetcap(TCSTANDOUTBEG
, 0);
904 if (txtchangeisset(atr
, TXTUNDERLINE
))
905 tsetcap(TCUNDERLINEBEG
, 0);
906 if (txtchangeisset(atr
, TXTFGCOLOUR
|TXTNOFGCOLOUR
))
907 set_colour_attribute(atr
, COL_SEQ_FG
, 0);
908 if (txtchangeisset(atr
, TXTBGCOLOUR
|TXTNOBGCOLOUR
))
909 set_colour_attribute(atr
, COL_SEQ_BG
, 0);
912 #ifdef MULTIBYTE_SUPPORT
914 * Add a multiword glyph at the screen location base.
915 * tptr points to the source and there are ichars characters.
918 addmultiword(REFRESH_ELEMENT
*base
, ZLE_STRING_T tptr
, int ichars
)
920 /* Number of characters needed in buffer incl. count */
921 int iadd
= ichars
+ 1, icnt
;
922 REFRESH_CHAR
*nmwptr
;
923 base
->atr
|= TXT_MULTIWORD_MASK
;
924 /* check allocation */
925 if (nmw_ind
+ iadd
> nmw_size
) {
926 /* need more space in buffer */
927 int mw_more
= (iadd
> DEF_MWBUF_ALLOC
) ? iadd
:
929 nmwbuf
= (REFRESH_CHAR
*)
930 zrealloc(nmwbuf
, (nmw_size
+= mw_more
) *
933 /* make buffer entry: count, then characters */
934 nmwptr
= nmwbuf
+ nmw_ind
;
936 for (icnt
= 0; icnt
< ichars
; icnt
++)
937 *nmwptr
++ = tptr
[icnt
];
938 /* save index and update */
939 base
->chr
= (wint_t)nmw_ind
;
946 * Swap the old and new video buffers, plus any associated multiword
947 * buffers. The new buffer becomes the old one; the new new buffer
948 * will be filled with the command line next time.
953 REFRESH_STRING
*qbuf
;
954 #ifdef MULTIBYTE_SUPPORT
955 REFRESH_CHAR
*qmwbuf
;
963 #ifdef MULTIBYTE_SUPPORT
964 /* likewise multiword buffers */
982 static int inlist
; /* avoiding recursion */
983 int iln
; /* current line as index in loops */
984 int t0
= -1; /* tmp */
985 ZLE_STRING_T tmpline
, /* line with added pre/post text */
986 t
, /* pointer into the real buffer */
987 scs
, /* pointer to cursor position in real buffer */
988 u
; /* pointer for status line stuff */
989 int tmpcs
, tmpll
; /* ditto cursor position and line length */
990 int tmppos
; /* t - tmpline */
991 int tmpalloced
; /* flag to free tmpline when finished */
992 int remetafy
; /* flag that zle line is metafied */
993 int txtchange
; /* attributes set after prompts */
995 #ifdef MULTIBYTE_SUPPORT
996 int width
; /* width of wide character */
1000 /* If this is called from listmatches() (indirectly via trashzle()), and *
1001 * that was called from the end of zrefresh(), then we don't need to do *
1002 * anything. All this `inlist' code is actually unnecessary, but it *
1003 * improves speed a little in a common case. */
1008 * zrefresh() is called from all over the place, so we can't
1009 * be sure if the line is metafied for completion or not.
1011 if (zlemetaline
!= NULL
) {
1018 if (predisplaylen
|| postdisplaylen
) {
1019 /* There is extra text to display at the start or end of the line */
1020 tmpline
= zalloc((zlell
+ predisplaylen
+ postdisplaylen
)*sizeof(*tmpline
));
1022 ZS_memcpy(tmpline
, predisplay
, predisplaylen
);
1024 ZS_memcpy(tmpline
+predisplaylen
, zleline
, zlell
);
1026 ZS_memcpy(tmpline
+predisplaylen
+zlell
, postdisplay
,
1029 tmpcs
= zlecs
+ predisplaylen
;
1030 tmpll
= predisplaylen
+ zlell
+ postdisplaylen
;
1039 /* this will create region_highlights if it's still NULL */
1040 zle_set_highlight();
1042 /* check for region between point ($CURSOR) and mark ($MARK) */
1043 if (region_active
) {
1044 if (zlecs
<= mark
) {
1045 region_highlights
->start
= zlecs
;
1046 region_highlights
->end
= mark
;
1048 region_highlights
->start
= mark
;
1049 region_highlights
->end
= zlecs
;
1052 region_highlights
->start
= region_highlights
->end
= -1;
1054 /* check for isearch string to highlight */
1055 if (isearch_active
) {
1056 region_highlights
[1].start
= isearch_startpos
;
1057 region_highlights
[1].end
= isearch_endpos
;
1059 region_highlights
[1].start
= region_highlights
[1].end
= -1;
1062 if (clearlist
&& listshown
> 0) {
1063 if (tccan(TCCLEAREOD
)) {
1064 int ovln
= vln
, ovcs
= vcs
;
1065 REFRESH_STRING nb
= nbuf
[vln
];
1067 nbuf
[vln
] = obuf
[vln
];
1069 tcoutclear(TCCLEAREOD
);
1078 listshown
= lastlistlen
= 0;
1079 if (showinglist
!= -2)
1085 cost
= 0; /* reset */
1088 /* Nov 96: <mason> I haven't checked how complete this is. sgtty stuff may
1090 #if defined(SGTABTYPE)
1091 oxtabs
= ((SGTTYFLAG
& SGTABTYPE
) == SGTABTYPE
);
1096 cleareol
= 0; /* unset */
1097 more_start
= more_end
= 0; /* unset */
1098 if (isset(SINGLELINEZLE
) || lines
< 3
1099 || (termflags
& (TERM_NOUP
| TERM_BAD
| TERM_UNKNOWN
)))
1100 termflags
|= TERM_SHORT
;
1102 termflags
&= ~TERM_SHORT
;
1109 t0
= olnct
; /* this is to clear extra lines even when */
1110 winchanged
= 0; /* the terminal cannot TCCLEAREOD */
1114 /* we probably should only have explicitly set attributes */
1115 tsetcap(TCALLATTRSOFF
, 0);
1116 tsetcap(TCSTANDOUTEND
, 0);
1117 tsetcap(TCUNDERLINEEND
, 0);
1118 /* cheat on attribute unset */
1119 txtunset(TXTBOLDFACE
|TXTSTANDOUT
|TXTUNDERLINE
);
1121 if (trashedzle
&& !clearflag
)
1124 resetneeded
= 0; /* unset */
1125 oput_rpmpt
= 0; /* no right-prompt currently on screen */
1128 if (tccan(TCCLEAREOD
))
1129 tcoutclear(TCCLEAREOD
);
1131 cleareol
= 1; /* request: clear to end of line */
1136 olnct
= (t0
< winh
) ? t0
: winh
;
1137 if (termflags
& TERM_SHORT
)
1139 else if (!clearflag
&& lpromptbuf
[0]) {
1140 zputs(lpromptbuf
, shout
);
1141 if (lpromptwof
== winw
)
1142 zputs("\n", shout
); /* works with both hasam and !hasam */
1144 txtchange
= pmpt_attr
;
1145 settextattributes(txtchange
);
1150 moveto(0, lpromptw
);
1154 } else if (winw
!= columns
|| rwinh
!= lines
)
1157 /* now winw equals columns and winh equals lines
1158 width comparisons can be made with winw, height comparisons with winh */
1160 if (termflags
& TERM_SHORT
) {
1161 singlerefresh(tmpline
, tmpll
, tmpcs
);
1167 fprintf(stderr
, "BUG: negative cursor position\n");
1172 scs
= tmpline
+ tmpcs
;
1175 /* first, we generate the video line buffers so we know what to put on
1176 the screen - also determine final cursor position (nvln, nvcs) */
1178 /* Deemed necessary by PWS 1995/05/15 due to kill-line problems */
1180 *nbuf
= (REFRESH_STRING
)zalloc((winw
+ 2) * sizeof(**nbuf
));
1182 memset(&rpms
, 0, sizeof(rpms
));
1185 rpms
.s
= nbuf
[rpms
.ln
= 0] + lpromptw
;
1186 rpms
.sen
= *nbuf
+ winw
;
1187 for (t
= tmpline
, tmppos
= 0; tmppos
< tmpll
; t
++, tmppos
++) {
1188 int base_atr_on
= default_atr_on
, base_atr_off
= 0, ireg
;
1189 int all_atr_on
, all_atr_off
;
1190 struct region_highlight
*rhp
;
1192 * Calculate attribute based on region.
1194 for (ireg
= 0, rhp
= region_highlights
;
1195 ireg
< n_region_highlights
;
1198 if (rhp
->flags
& ZRH_PREDISPLAY
)
1199 offset
= 0; /* include predisplay in start end */
1201 offset
= predisplaylen
; /* increment over it */
1202 if (rhp
->start
+ offset
<= tmppos
&&
1203 tmppos
< rhp
->end
+ offset
) {
1204 if (rhp
->atr
& (TXTFGCOLOUR
|TXTBGCOLOUR
)) {
1205 /* override colour with later entry */
1206 base_atr_on
= (base_atr_on
& ~TXT_ATTR_ON_VALUES_MASK
) |
1209 /* no colour set yet */
1210 base_atr_on
|= rhp
->atr
;
1212 if (tmppos
== rhp
->end
+ offset
- 1 ||
1213 tmppos
== tmpll
- 1)
1214 base_atr_off
|= TXT_ATTR_OFF_FROM_ON(rhp
->atr
);
1217 if (special_atr_on
& (TXTFGCOLOUR
|TXTBGCOLOUR
)) {
1218 /* keep colours from special attributes */
1219 all_atr_on
= special_atr_on
|
1220 (base_atr_on
& ~TXT_ATTR_COLOUR_ON_MASK
);
1222 /* keep colours from standard attributes */
1223 all_atr_on
= special_atr_on
| base_atr_on
;
1225 all_atr_off
= TXT_ATTR_OFF_FROM_ON(all_atr_on
);
1227 if (t
== scs
) /* if cursor is here, remember it */
1228 rpms
.nvcs
= rpms
.s
- nbuf
[rpms
.nvln
= rpms
.ln
];
1230 if (*t
== ZWC('\n')){ /* newline */
1231 /* text not wrapped */
1232 if (nextline(&rpms
, 0))
1234 } else if (*t
== ZWC('\t')) { /* tab */
1235 t0
= rpms
.s
- nbuf
[rpms
.ln
];
1236 if ((t0
| 7) + 1 >= winw
) {
1238 if (nextline(&rpms
, 1))
1242 rpms
.s
->chr
= ZWC(' ');
1243 rpms
.s
->atr
= base_atr_on
;
1245 } while ((++t0
) & 7);
1246 rpms
.s
[-1].atr
|= base_atr_off
;
1249 #ifdef MULTIBYTE_SUPPORT
1250 else if (iswprint(*t
) && (width
= WCWIDTH(*t
)) > 0) {
1252 if (width
> rpms
.sen
- rpms
.s
) {
1255 * Too wide to fit. Insert spaces to end of current line.
1258 rpms
.s
->chr
= ZWC(' ');
1261 rpms
.s
->atr
= all_atr_on
;
1263 } while (rpms
.s
< rpms
.sen
);
1265 rpms
.s
[-1].atr
|= all_atr_off
;
1266 if (nextline(&rpms
, 1))
1269 /* Update cursor to this point */
1270 rpms
.nvcs
= rpms
.s
- nbuf
[rpms
.nvln
= rpms
.ln
];
1273 if (isset(COMBININGCHARS
) && IS_BASECHAR(*t
)) {
1275 * Look for combining characters.
1277 for (ichars
= 1; tmppos
+ ichars
< tmpll
; ichars
++) {
1278 if (!IS_COMBINING(t
[ichars
]))
1283 if (width
> rpms
.sen
- rpms
.s
|| width
== 0) {
1285 * The screen width is too small to fit even one
1288 rpms
.s
->chr
= ZWC('?');
1289 rpms
.s
->atr
= all_atr_on
| all_atr_off
;
1292 /* We can fit it without reaching the end of the line. */
1294 * As we don't actually output the WEOF, we attach
1295 * any off attributes to the character itself.
1297 rpms
.s
->atr
= base_atr_on
| base_atr_off
;
1300 * Glyph includes combining characters.
1301 * Write these into the multiword buffer and put
1302 * the index into the value at the screen location.
1304 addmultiword(rpms
.s
, t
, ichars
);
1306 /* Single wide character */
1310 while (--width
> 0) {
1312 /* Not used, but be consistent... */
1313 rpms
.s
->atr
= base_atr_on
| base_atr_off
;
1318 /* allow for normal increment */
1319 tmppos
+= ichars
- 1;
1324 else if (ZC_icntrl(*t
)
1325 #ifdef MULTIBYTE_SUPPORT
1326 && (unsigned)*t
<= 0xffU
1328 ) { /* other control character */
1329 rpms
.s
->chr
= ZWC('^');
1330 rpms
.s
->atr
= all_atr_on
;
1332 if (rpms
.s
== rpms
.sen
) {
1334 rpms
.s
[-1].atr
|= all_atr_off
;
1335 if (nextline(&rpms
, 1))
1338 rpms
.s
->chr
= (((unsigned int)*t
& ~0x80u
) > 31) ?
1339 ZWC('?') : (*t
| ZWC('@'));
1340 rpms
.s
->atr
= all_atr_on
| all_atr_off
;
1343 #ifdef MULTIBYTE_SUPPORT
1346 * Not printable or zero width.
1347 * Resort to hackery.
1350 char *dispptr
= dispchars
;
1354 if ((unsigned)*t
> 0xffffU
) {
1355 sprintf(dispchars
, "<%.08x>", (unsigned)*t
);
1357 sprintf(dispchars
, "<%.04x>", (unsigned)*t
);
1360 if (mbtowc(&wc
, dispptr
, 1) == 1 /* paranoia */)
1365 rpms
.s
->atr
= all_atr_on
;
1367 if (rpms
.s
== rpms
.sen
) {
1370 rpms
.s
[-1].atr
|= all_atr_off
;
1373 if (nextline(&rpms
, 1))
1380 rpms
.s
[-1].atr
|= all_atr_off
;
1381 if (*dispptr
) /* nextline said stop processing */
1385 else { /* normal character */
1387 rpms
.s
->atr
= base_atr_on
| base_atr_off
;
1391 if (rpms
.s
== rpms
.sen
) {
1393 if (nextline(&rpms
, 1))
1398 /* if we're really on the next line, don't fake it; do everything properly */
1400 (rpms
.nvcs
= rpms
.s
- (nbuf
[rpms
.nvln
= rpms
.ln
])) == winw
) {
1402 (void)nextline(&rpms
, 1);
1408 if (t
!= tmpline
+ tmpll
)
1412 int outll
, outsz
, all_atr_on
, all_atr_off
;
1413 char *statusdup
= ztrdup(statusline
);
1414 ZLE_STRING_T outputline
=
1415 stringaszleline(statusdup
, 0, &outll
, &outsz
, NULL
);
1417 all_atr_on
= special_atr_on
;
1418 all_atr_off
= TXT_ATTR_OFF_FROM_ON(all_atr_on
);
1420 rpms
.tosln
= rpms
.ln
+ 1;
1421 nbuf
[rpms
.ln
][winw
+ 1] = zr_zr
; /* text not wrapped */
1424 for (; u
< outputline
+ outll
; u
++) {
1425 #ifdef MULTIBYTE_SUPPORT
1427 int width
= WCWIDTH(*u
);
1428 /* Handle wide characters as above */
1429 if (width
> rpms
.sen
- rpms
.s
) {
1432 } while (rpms
.s
< rpms
.sen
);
1433 nbuf
[rpms
.ln
][winw
+ 1] = zr_nl
;
1436 if (width
> rpms
.sen
- rpms
.s
) {
1437 rpms
.s
->chr
= ZWC('?');
1438 rpms
.s
->atr
= all_atr_on
| all_atr_off
;
1444 while (--width
> 0) {
1453 if (ZC_icntrl(*u
)) { /* simplified processing in the status line */
1454 rpms
.s
->chr
= ZWC('^');
1455 rpms
.s
->atr
= all_atr_on
;
1457 if (rpms
.s
== rpms
.sen
) {
1458 nbuf
[rpms
.ln
][winw
+ 1] = zr_nl
;/* text wrapped */
1461 rpms
.s
->chr
= (((unsigned int)*u
& ~0x80u
) > 31)
1462 ? ZWC('?') : (*u
| ZWC('@'));
1463 rpms
.s
->atr
= all_atr_on
| all_atr_off
;
1470 if (rpms
.s
== rpms
.sen
) {
1471 nbuf
[rpms
.ln
][winw
+ 1] = zr_nl
; /* text wrapped */
1475 if (rpms
.s
== rpms
.sen
) {
1477 * I suppose we don't modify nbuf[rpms.ln][winw+1] here
1478 * since we're right at the end?
1482 zfree(outputline
, outsz
);
1487 /* insert <.... at end of last line if there is more text past end of screen */
1489 #ifdef MULTIBYTE_SUPPORT
1490 int extra_ellipsis
= 0;
1494 rpms
.s
= nbuf
[rpms
.tosln
- 1];
1495 rpms
.sen
= rpms
.s
+ winw
- 7;
1496 for (; rpms
.s
< rpms
.sen
; rpms
.s
++) {
1497 if (rpms
.s
->chr
== ZWC('\0')) {
1498 ZR_memset(rpms
.s
, zr_sp
, rpms
.sen
- rpms
.s
);
1499 /* make sure we don't trigger the WEOF test */
1500 rpms
.sen
->chr
= ZWC('\0');
1504 /* rpms.s is no longer needed */
1505 #ifdef MULTIBYTE_SUPPORT
1507 * Ensure we don't start overwriting in the middle of a wide
1510 while(rpms
.sen
> nbuf
[rpms
.tosln
- 1] && rpms
.sen
->chr
== WEOF
) {
1515 ZR_memcpy(rpms
.sen
, zr_end_ellipsis
, ZR_END_ELLIPSIS_SIZE
);
1516 #ifdef MULTIBYTE_SUPPORT
1517 /* Extend to the end if we backed off for a wide character */
1518 if (extra_ellipsis
) {
1519 rpms
.sen
+= ZR_END_ELLIPSIS_SIZE
;
1520 ZR_memset(rpms
.sen
, zr_dt
, extra_ellipsis
);
1523 nbuf
[rpms
.tosln
- 1][winw
] = nbuf
[rpms
.tosln
- 1][winw
+ 1] = zr_zr
;
1526 /* insert <....> at end of first status line if status is too big */
1527 if (rpms
.more_status
) {
1528 #ifdef MULTIBYTE_SUPPORT
1529 int extra_ellipsis
= 0;
1531 rpms
.s
= nbuf
[rpms
.tosln
];
1532 rpms
.sen
= rpms
.s
+ winw
- 8;
1533 for (; rpms
.s
< rpms
.sen
; rpms
.s
++) {
1534 if (rpms
.s
->chr
== ZWC('\0')) {
1535 ZR_memset(rpms
.s
, zr_sp
, rpms
.sen
- rpms
.s
);
1539 /* rpms.s is no longer needed */
1540 #ifdef MULTIBYTE_SUPPORT
1542 * Ensure we don't start overwriting in the middle of a wide
1545 while(rpms
.sen
> nbuf
[rpms
.tosln
- 1] && rpms
.sen
->chr
== WEOF
) {
1550 ZR_memcpy(rpms
.sen
, zr_mid_ellipsis1
, ZR_MID_ELLIPSIS1_SIZE
);
1551 rpms
.sen
+= ZR_MID_ELLIPSIS1_SIZE
;
1552 #ifdef MULTIBYTE_SUPPORT
1553 /* Extend if we backed off for a wide character */
1554 if (extra_ellipsis
) {
1555 ZR_memset(rpms
.sen
, zr_dt
, extra_ellipsis
);
1556 rpms
.sen
+= extra_ellipsis
;
1559 ZR_memcpy(rpms
.sen
, zr_mid_ellipsis2
, ZR_MID_ELLIPSIS2_SIZE
);
1560 nbuf
[rpms
.tosln
][winw
] = nbuf
[rpms
.tosln
][winw
+ 1] = zr_zr
;
1563 nlnct
= rpms
.ln
+ 1;
1564 for (iln
= nlnct
; iln
< winh
; iln
++) {
1565 zfree(nbuf
[iln
], (winw
+ 2) * sizeof(**nbuf
));
1569 /* determine whether the right-prompt exists and can fit on the screen */
1571 if (trashedzle
&& opts
[TRANSIENTRPROMPT
])
1574 put_rpmpt
= rprompth
== 1 && rpromptbuf
[0] &&
1575 !strchr(rpromptbuf
, '\t') &&
1576 (int)ZR_strlen(nbuf
[0]) + rpromptw
< winw
- 1;
1578 /* insert >.... on first line if there is more text before start of screen */
1579 ZR_memset(nbuf
[0], zr_sp
, lpromptw
);
1580 t0
= winw
- lpromptw
;
1581 t0
= t0
> ZR_START_ELLIPSIS_SIZE
? ZR_START_ELLIPSIS_SIZE
: t0
;
1582 ZR_memcpy(nbuf
[0] + lpromptw
, zr_start_ellipsis
, t0
);
1583 ZR_memset(nbuf
[0] + lpromptw
+ t0
, zr_sp
, winw
- t0
- lpromptw
);
1584 nbuf
[0][winw
] = nbuf
[0][winw
+ 1] = zr_zr
;
1587 for (iln
= 0; iln
< nlnct
; iln
++) {
1588 /* if we have more lines than last time, clear the newly-used lines */
1592 /* if old line and new line are different,
1593 see if we can insert/delete a line to speed up update */
1595 if (!clearf
&& iln
> 0 && iln
< olnct
- 1 &&
1596 !(hasam
&& vcs
== winw
) &&
1597 nbuf
[iln
] && obuf
[iln
] &&
1598 ZR_strncmp(obuf
[iln
], nbuf
[iln
], 16)) {
1599 if (tccan(TCDELLINE
) && obuf
[iln
+ 1] &&
1600 obuf
[iln
+ 1][0].chr
&& nbuf
[iln
] &&
1601 !ZR_strncmp(obuf
[iln
+ 1], nbuf
[iln
], 16)) {
1604 zfree(obuf
[iln
], (winw
+ 2) * sizeof(**obuf
));
1605 for (t0
= iln
; t0
!= olnct
; t0
++)
1606 obuf
[t0
] = obuf
[t0
+ 1];
1607 obuf
[--olnct
] = NULL
;
1609 /* don't try to insert a line if olnct = vmaxln (vmaxln is the number
1610 of lines that have been displayed by this routine) so that we don't
1611 go off the end of the screen. */
1613 else if (tccan(TCINSLINE
) && olnct
< vmaxln
&& nbuf
[iln
+ 1] &&
1614 obuf
[iln
] && !ZR_strncmp(obuf
[iln
], nbuf
[iln
+ 1], 16)) {
1617 for (t0
= olnct
; t0
!= iln
; t0
--)
1618 obuf
[t0
] = obuf
[t0
- 1];
1624 /* update the single line */
1627 /* output the right-prompt if appropriate */
1628 if (put_rpmpt
&& !iln
&& !oput_rpmpt
) {
1631 moveto(0, winw
- 1 - rpromptw
);
1632 zputs(rpromptbuf
, shout
);
1634 /* reset character attributes to that set by the main prompt */
1635 txtchange
= pmpt_attr
;
1637 * Keep attributes that have actually changed,
1638 * which are ones off in rpmpt_attr and on in
1639 * pmpt_attr, and vice versa.
1641 attrchange
= txtchange
&
1642 (TXT_ATTR_OFF_FROM_ON(rpmpt_attr
) |
1643 TXT_ATTR_ON_FROM_OFF(rpmpt_attr
));
1645 * Careful in case the colour changed.
1647 if (txtchangeisset(txtchange
, TXTFGCOLOUR
) &&
1648 (!txtchangeisset(rpmpt_attr
, TXTFGCOLOUR
) ||
1649 ((txtchange
^ rpmpt_attr
) & TXT_ATTR_FG_COL_MASK
)))
1652 txtchange
& (TXTFGCOLOUR
| TXT_ATTR_FG_COL_MASK
);
1654 if (txtchangeisset(txtchange
, TXTBGCOLOUR
) &&
1655 (!txtchangeisset(rpmpt_attr
, TXTBGCOLOUR
) ||
1656 ((txtchange
^ rpmpt_attr
) & TXT_ATTR_BG_COL_MASK
)))
1659 txtchange
& (TXTBGCOLOUR
| TXT_ATTR_BG_COL_MASK
);
1662 * Now feed these changes into the usual function,
1666 settextattributes(attrchange
);
1670 /* if old buffer had extra lines, set them to be cleared and refresh them
1673 if (olnct
> nlnct
) {
1675 for (iln
= nlnct
; iln
< olnct
; iln
++)
1679 /* reset character attributes */
1680 if (clearf
&& postedit
) {
1681 if ((txtchange
= pmpt_attr
? pmpt_attr
: rpmpt_attr
))
1682 settextattributes(txtchange
);
1685 oput_rpmpt
= put_rpmpt
;
1687 /* move to the new cursor position */
1688 moveto(rpms
.nvln
, rpms
.nvcs
);
1690 /* swap old and new buffers - better than freeing/allocating every time */
1693 /* store current values so we can use them next time */
1696 onumscrolls
= numscrolls
;
1700 fflush(shout
); /* make sure everything is written out */
1703 zfree(tmpline
, tmpll
* sizeof(*tmpline
));
1705 zle_free_highlight();
1707 /* if we have a new list showing, note it; if part of the list has been
1708 overwritten, redisplay it. We have to metafy line back before calling
1710 if (showinglist
== -2 || (showinglist
> 0 && showinglist
< nlnct
)) {
1720 if (showinglist
== -1)
1721 showinglist
= nlnct
;
1727 #define tcinscost(X) (tccan(TCMULTINS) ? tclen[TCMULTINS] : (X)*tclen[TCINS])
1728 #define tcdelcost(X) (tccan(TCMULTDEL) ? tclen[TCMULTDEL] : (X)*tclen[TCDEL])
1729 #define tc_delchars(X) (void) tcmultout(TCDEL, TCMULTDEL, (X))
1730 #define tc_inschars(X) (void) tcmultout(TCINS, TCMULTINS, (X))
1731 #define tc_upcurs(X) (void) tcmultout(TCUP, TCMULTUP, (X))
1732 #define tc_leftcurs(X) (void) tcmultout(TCLEFT, TCMULTLEFT, (X))
1735 * Once again, in the multibyte case the arguments must be in the
1736 * order: element of old video array, element of new video array.
1739 wpfxlen(const REFRESH_ELEMENT
*olds
, const REFRESH_ELEMENT
*news
)
1743 while (olds
->chr
&& ZR_equal(*olds
, *news
))
1744 olds
++, news
++, i
++;
1748 /* refresh one line, using whatever speed-up tricks are provided by the tty */
1754 REFRESH_STRING nl
, ol
, p1
; /* line buffer pointers */
1755 int ccs
= 0, /* temporary count for cursor position */
1756 char_ins
= 0, /* number of characters inserted/deleted */
1757 col_cleareol
, /* clear to end-of-line from this column */
1759 ins_last
, /* insert pushed last character off line */
1760 nllen
, ollen
, /* new and old line buffer lengths */
1761 rnllen
; /* real new line buffer length */
1765 rnllen
= nllen
= nl
? ZR_strlen(nl
) : 0;
1768 ollen
= ZR_strlen(ol
);
1771 static REFRESH_ELEMENT nullchr
= { ZWC('\0'), 0 };
1776 /* optimisation: can easily happen for clearing old lines. If the terminal has
1777 the capability, then this is the easiest way to skip unnecessary stuff */
1778 if (cleareol
&& !nllen
&& !(hasam
&& ln
< nlnct
- 1)
1779 && tccan(TCCLEAREOL
)) {
1781 tcoutclear(TCCLEAREOL
);
1785 /* 1: pad out the new buffer with spaces to contain _all_ of the characters
1786 which need to be written. do this now to allow some pre-processing */
1788 if (cleareol
/* request to clear to end of line */
1789 || (!nllen
&& (ln
!= 0 || !put_rpmpt
)) /* no line buffer given */
1790 || (ln
== 0 && (put_rpmpt
!= oput_rpmpt
))) { /* prompt changed */
1791 p1
= zhalloc((winw
+ 2) * sizeof(*p1
));
1793 ZR_memcpy(p1
, nl
, nllen
);
1794 ZR_memset(p1
+ nllen
, zr_sp
, winw
- nllen
);
1797 p1
[winw
+ 1] = zr_zr
;
1799 p1
[winw
+ 1] = nl
[winw
+ 1];
1801 ZR_memcpy(nl
, p1
, winw
+ 2); /* next time obuf will be up-to-date */
1803 nl
= p1
; /* don't keep the padding for prompt line */
1805 } else if (ollen
> nllen
) { /* make new line at least as long as old */
1806 p1
= zhalloc((ollen
+ 1) * sizeof(*p1
));
1807 ZR_memcpy(p1
, nl
, nllen
);
1808 ZR_memset(p1
+ nllen
, zr_sp
, ollen
- nllen
);
1814 /* 2: see if we can clear to end-of-line, and if it's faster, work out where
1815 to do it from - we can normally only do so if there's no right-prompt.
1816 With automatic margins, we shouldn't do it if there is another line, in
1817 case it messes up cut and paste. */
1819 if (hasam
&& ln
< nlnct
- 1 && rnllen
== winw
)
1820 col_cleareol
= -2; /* clearing eol would be evil so don't */
1823 if (tccan(TCCLEAREOL
) && (nllen
== winw
|| put_rpmpt
!= oput_rpmpt
)) {
1824 for (i
= nllen
; i
&& ZR_equal(zr_sp
, nl
[i
- 1]); i
--)
1826 for (j
= ollen
; j
&& ZR_equal(ol
[j
- 1], zr_sp
); j
--)
1828 if ((j
> i
+ tclen
[TCCLEAREOL
]) /* new buf has enough spaces */
1829 || (nllen
== winw
&& ZR_equal(zr_sp
, nl
[winw
- 1])))
1834 /* 2b: first a new trick for automargin niceness - good for cut and paste */
1836 if (hasam
&& vcs
== winw
) {
1837 if (nbuf
[vln
] && nbuf
[vln
][vcs
+ 1].chr
== ZWC('\n')) {
1839 if (nbuf
[vln
] && nbuf
[vln
]->chr
) {
1842 zputc(&zr_sp
); /* I don't think this should happen */
1843 if (ln
== vln
) { /* better safe than sorry */
1848 } /* else hmmm... I wonder what happened */
1856 /* 2c: if we're on the first line, start checking at the end of the prompt;
1857 we shouldn't be doing anything within the prompt */
1859 if (ln
== 0 && lpromptw
) {
1863 ol
+= (i
> j
? j
: i
); /* if ol is too short, point it to '\0' */
1867 #ifdef MULTIBYTE_SUPPORT
1869 * Realign to a real character after any jiggery pokery at
1870 * the start of the line.
1872 while (nl
->chr
== WEOF
) {
1879 /* 3: main display loop - write out the buffer using whatever tricks we can */
1884 #ifdef MULTIBYTE_SUPPORT
1885 if ((!nl
->chr
|| nl
->chr
!= WEOF
) && (!ol
->chr
|| ol
->chr
!= WEOF
)) {
1887 if (nl
->chr
&& ol
->chr
&& ZR_equal(ol
[1], nl
[1])) {
1888 /* skip only if second chars match */
1889 #ifdef MULTIBYTE_SUPPORT
1892 /* skip past all matching characters */
1893 for (; nl
->chr
&& ZR_equal(*ol
, *nl
); nl
++, ol
++, ccs
++)
1895 #ifdef MULTIBYTE_SUPPORT
1896 /* Make sure ol and nl are pointing to real characters */
1897 while ((nl
->chr
== WEOF
|| ol
->chr
== WEOF
) && ccs
> ccs_was
) {
1906 if (ccs
== winw
&& hasam
&& char_ins
> 0 && ins_last
1908 nl
--; /* we can assume we can go back here */
1909 moveto(ln
, winw
- 1);
1912 return; /* write last character in line */
1914 if ((char_ins
<= 0) || (ccs
>= winw
)) /* written everything */
1916 if (tccan(TCCLEAREOL
) && (char_ins
>= tclen
[TCCLEAREOL
])
1917 && col_cleareol
!= -2)
1918 /* we've got junk on the right yet to clear */
1919 col_cleareol
= 0; /* force a clear to end of line */
1922 moveto(ln
, ccs
); /* move to where we do all output from */
1924 /* if we can finish quickly, do so */
1925 if ((col_cleareol
>= 0) && (ccs
>= col_cleareol
)) {
1926 tcoutclear(TCCLEAREOL
);
1930 /* we've written out the new but yet to clear rubbish due to inserts */
1932 i
= (winw
- ccs
< char_ins
) ? (winw
- ccs
) : char_ins
;
1933 if (tccan(TCDEL
) && (tcdelcost(i
) <= i
+ 1))
1943 /* if we've reached the end of the old buffer, then there are few tricks
1944 we can do, so we just dump out what we must and clear if we can */
1946 i
= (col_cleareol
>= 0) ? col_cleareol
: nllen
;
1950 * This shouldn't be necessary, but it's better
1951 * than a crash if there's a bug somewhere else,
1952 * so report in debug mode.
1954 DPUTS(1, "BUG: badly calculated old line width in refresh");
1959 if (col_cleareol
>= 0)
1960 tcoutclear(TCCLEAREOL
);
1964 /* inserting & deleting chars: we can if there's no right-prompt */
1965 if ((ln
|| !put_rpmpt
|| !oput_rpmpt
)
1966 #ifdef MULTIBYTE_SUPPORT
1967 && ol
->chr
!= WEOF
&& nl
->chr
!= WEOF
1969 && nl
[1].chr
&& ol
[1].chr
&& !ZR_equal(ol
[1], nl
[1])) {
1971 /* deleting characters - see if we can find a match series that
1972 makes it cheaper to delete intermediate characters
1973 eg. oldline: hifoobar \ hopefully cheaper here to delete two
1974 newline: foobar / characters, then we have six matches */
1977 for (i
= 1; ol
[i
].chr
; i
++)
1978 if (tcdelcost(i
) < wpfxlen(ol
+ i
, nl
)) {
1980 * Some terminals will output the current
1981 * attributes into cells added at the end by
1982 * deletions, so turn off text attributes.
1991 #ifdef MULTIBYTE_SUPPORT
1992 while (ol
->chr
== WEOF
) {
2003 /* inserting characters - characters pushed off the right should be
2004 annihilated, but we don't do this if we're on the last line lest
2005 undesired scrolling occurs due to `illegal' characters on screen */
2007 if (tccan(TCINS
) && (vln
!= lines
- 1)) { /* not on last line */
2008 for (i
= 1; nl
[i
].chr
; i
++)
2009 if (tcinscost(i
) < wpfxlen(ol
, nl
+ i
)) {
2013 #ifdef MULTIBYTE_SUPPORT
2014 while (nl
->chr
== WEOF
) {
2021 /* if we've pushed off the right, truncate oldline */
2022 for (i
= 0; ol
[i
].chr
&& i
< winw
- ccs
; i
++);
2023 #ifdef MULTIBYTE_SUPPORT
2024 while (ol
[i
].chr
== WEOF
)
2027 if (i
>= winw
- ccs
) {
2038 #ifdef MULTIBYTE_SUPPORT
2041 /* we can't do any fancy tricks, so just dump the single character
2042 and keep on trying */
2043 #ifdef MULTIBYTE_SUPPORT
2045 * in case we were tidying up a funny-width character when we
2046 * reached the end of the new line...
2053 * If an attribute was on here but isn't any more,
2054 * output the sequence to turn it off.
2056 now_off
= ol
->atr
& ~nl
->atr
& TXT_ATTR_ON_MASK
;
2058 settextattributes(TXT_ATTR_OFF_FROM_ON(now_off
));
2063 #ifdef MULTIBYTE_SUPPORT
2065 * Make sure we always overwrite the complete width of
2066 * a character that was there before.
2068 } while ((ol
->chr
== WEOF
&& nl
->chr
) ||
2069 (nl
->chr
== WEOF
&& ol
->chr
));
2074 /* move the cursor to line ln (relative to the prompt line),
2075 absolute column cl; update vln, vcs - video line and column */
2079 moveto(int ln
, int cl
)
2081 const REFRESH_ELEMENT
*rep
;
2089 if ((vln
< nlnct
) && nbuf
[vln
] && nbuf
[vln
]->chr
)
2095 if ((vln
< olnct
) && obuf
[vln
] && obuf
[vln
]->chr
)
2100 if (ln
== vln
&& cl
== vcs
)
2105 tc_upcurs(vln
- ln
);
2108 /* move down; if we might go off the end of the screen, use newlines
2109 instead of TCDOWN */
2112 if (vln
< vmaxln
- 1) {
2113 if (ln
> vmaxln
- 1) {
2114 if (tc_downcurs(vmaxln
- 1 - vln
))
2118 if (tc_downcurs(ln
- vln
))
2124 zputc(&zr_cr
), vcs
= 0; /* safety precaution */
2137 tcmultout(int cap
, int multcap
, int ct
)
2139 if (tccan(multcap
) && (!tccan(cap
) || tclen
[multcap
] <= tclen
[cap
] * ct
)) {
2140 tcoutarg(multcap
, ct
);
2142 } else if (tccan(cap
)) {
2150 /* ct: number of characters to move across */
2153 tc_rightcurs(int ct
)
2155 int cl
, /* ``desired'' absolute horizontal position */
2156 i
= vcs
, /* cursor position after initial movements */
2162 /* do a multright if we can - it's the most reliable */
2163 if (tccan(TCMULTRIGHT
)) {
2164 tcoutarg(TCMULTRIGHT
, ct
);
2168 /* do an absolute horizontal position if we can */
2169 if (tccan(TCHORIZPOS
)) {
2170 tcoutarg(TCHORIZPOS
, cl
);
2174 /* XXX: should really check "it" in termcap and use / and % */
2175 /* try tabs if tabs are non destructive and multright is not possible */
2176 if (!oxtabs
&& tccan(TCNEXTTAB
) && ((vcs
| 7) < cl
)) {
2179 for ( ; i
+ 8 <= cl
; i
+= 8)
2181 if ((ct
= cl
- i
) == 0) /* number of chars still to move across */
2185 /* otherwise _carefully_ write the contents of the video buffer.
2186 if we're anywhere in the prompt, goto the left column and write the whole
2189 If strlen(lpromptbuf) == lpromptw, we can cheat and output
2190 the appropriate chunk of the string. This test relies on the
2191 fact that any funny business will always make the length of
2192 the string larger than the printing width, so if they're the same
2193 we have only ASCII characters or a single-byte extension of ASCII.
2194 Unfortunately this trick won't work if there are potentially
2195 characters occupying more than one column. We could flag that
2196 this has happened (since it's not that common to have characters
2197 wider than one column), but for now it's easier not to use the
2198 trick if we are using WCWIDTH() on the prompt. It's not that
2199 common to be editing in the middle of the prompt anyway, I would
2202 if (vln
== 0 && i
< lpromptw
&& !(termflags
& TERM_SHORT
)) {
2203 #ifndef MULTIBYTE_SUPPORT
2204 if ((int)strlen(lpromptbuf
) == lpromptw
)
2205 fputs(lpromptbuf
+ i
, shout
);
2208 if (tccan(TCRIGHT
) && (tclen
[TCRIGHT
] * ct
<= ztrlen(lpromptbuf
)))
2209 /* it is cheaper to send TCRIGHT than reprint the whole prompt */
2210 for (ct
= lpromptw
- i
; ct
--; )
2215 tc_upcurs(lprompth
- 1);
2216 zputs(lpromptbuf
, shout
);
2217 if (lpromptwof
== winw
)
2218 zputs("\n", shout
); /* works with both hasam and !hasam */
2225 for (j
= 0, t
= nbuf
[vln
]; t
->chr
&& (j
< i
); j
++, t
++);
2227 for ( ; t
->chr
&& ct
; ct
--, t
++)
2231 zputc(&zr_sp
); /* not my fault your terminal can't go right */
2240 if (ct
&& !tcmultout(TCDOWN
, TCMULTDOWN
, ct
)) {
2243 zputc(&zr_cr
), ret
= -1;
2252 tputs(tcstr
[cap
], 1, putshout
);
2253 SELECT_ADD_COST(tclen
[cap
]);
2258 tcoutarg(int cap
, int arg
)
2262 result
= tgoto(tcstr
[cap
], arg
, arg
);
2263 tputs(result
, 1, putshout
);
2264 SELECT_ADD_COST(strlen(result
));
2269 clearscreen(UNUSED(char **args
))
2271 tcoutclear(TCCLEARSCREEN
);
2279 redisplay(UNUSED(char **args
))
2282 zputc(&zr_cr
); /* extra care */
2283 tc_upcurs(lprompth
- 1);
2290 * Show as much of the line buffer as we can in single line mode.
2291 * TBD: all termcap effects are turned off in this mode, so
2292 * there's no point in using character attributes. We should
2293 * decide what we're going to do and either remove the handling
2294 * from here or enable it in tsetcap().
2299 singlerefresh(ZLE_STRING_T tmpline
, int tmpll
, int tmpcs
)
2301 REFRESH_STRING vbuf
, vp
, /* video buffer and pointer */
2302 refreshop
; /* pointer to old video buffer */
2304 vsiz
, /* size of new video buffer */
2305 nvcs
= 0, /* new video cursor column */
2306 owinpos
= winpos
, /* previous window position */
2307 owinprompt
= winprompt
; /* previous winprompt */
2308 #ifdef MULTIBYTE_SUPPORT
2309 int width
; /* width of multibyte character */
2313 /* generate the new line buffer completely */
2314 for (vsiz
= 1 + lpromptw
, t0
= 0; t0
!= tmpll
; t0
++) {
2315 if (tmpline
[t0
] == ZWC('\t'))
2316 vsiz
= (vsiz
| 7) + 2;
2317 #ifdef MULTIBYTE_SUPPORT
2318 else if (iswprint(tmpline
[t0
]) && (width
= WCWIDTH(tmpline
[t0
]) > 0)) {
2320 if (isset(COMBININGCHARS
) && IS_BASECHAR(tmpline
[t0
])) {
2321 while (t0
< tmpll
-1 && IS_COMBINING(tmpline
[t0
+1]))
2326 else if (ZC_icntrl(tmpline
[t0
])
2327 #ifdef MULTIBYTE_SUPPORT
2328 && (unsigned)tmpline
[t0
] <= 0xffU
2332 #ifdef MULTIBYTE_SUPPORT
2340 vbuf
= (REFRESH_STRING
)zalloc(vsiz
* sizeof(*vbuf
));
2344 fprintf(stderr
, "BUG: negative cursor position\n");
2350 /* prompt is not directly copied into the video buffer */
2351 ZR_memset(vbuf
, zr_sp
, lpromptw
);
2352 vp
= vbuf
+ lpromptw
;
2355 for (t0
= 0; t0
< tmpll
; t0
++) {
2356 int base_atr_on
= 0, base_atr_off
= 0, ireg
;
2357 int all_atr_on
, all_atr_off
;
2358 struct region_highlight
*rhp
;
2360 * Calculate attribute based on region.
2362 for (ireg
= 0, rhp
= region_highlights
;
2363 ireg
< n_region_highlights
;
2366 if (rhp
->flags
& ZRH_PREDISPLAY
)
2367 offset
= 0; /* include predisplay in start end */
2369 offset
= predisplaylen
; /* increment over it */
2370 if (rhp
->start
+ offset
<= t0
&&
2371 t0
< rhp
->end
+ offset
) {
2372 if (base_atr_on
& (TXTFGCOLOUR
|TXTBGCOLOUR
)) {
2373 /* keep colour already set */
2374 base_atr_on
|= rhp
->atr
& ~TXT_ATTR_COLOUR_ON_MASK
;
2376 /* no colour set yet */
2377 base_atr_on
|= rhp
->atr
;
2379 if (t0
== rhp
->end
+ offset
- 1 ||
2381 base_atr_off
|= TXT_ATTR_OFF_FROM_ON(rhp
->atr
);
2384 if (special_atr_on
& (TXTFGCOLOUR
|TXTBGCOLOUR
)) {
2385 /* keep colours from special attributes */
2386 all_atr_on
= special_atr_on
|
2387 (base_atr_on
& ~TXT_ATTR_COLOUR_ON_MASK
);
2389 /* keep colours from standard attributes */
2390 all_atr_on
= special_atr_on
| base_atr_on
;
2392 all_atr_off
= TXT_ATTR_OFF_FROM_ON(all_atr_on
);
2394 if (tmpline
[t0
] == ZWC('\t')) {
2395 REFRESH_ELEMENT sp
= zr_sp
;
2396 sp
.atr
= base_atr_on
;
2397 for (*vp
++ = zr_sp
; (vp
- vbuf
) & 7; )
2399 vp
[-1].atr
|= base_atr_off
;
2400 } else if (tmpline
[t0
] == ZWC('\n')) {
2401 vp
->chr
= ZWC('\\');
2402 vp
->atr
= all_atr_on
;
2405 vp
->atr
= all_atr_on
| all_atr_off
;
2407 #ifdef MULTIBYTE_SUPPORT
2408 } else if (iswprint(tmpline
[t0
]) &&
2409 (width
= WCWIDTH(tmpline
[t0
])) > 0) {
2411 if (isset(COMBININGCHARS
) && IS_BASECHAR(tmpline
[t0
])) {
2413 * Look for combining characters.
2415 for (ichars
= 1; t0
+ ichars
< tmpll
; ichars
++) {
2416 if (!IS_COMBINING(tmpline
[t0
+ichars
]))
2421 vp
->atr
= base_atr_on
| base_atr_off
;
2423 addmultiword(vp
, tmpline
+t0
, ichars
);
2425 vp
->chr
= tmpline
[t0
];
2427 while (--width
> 0) {
2429 vp
->atr
= base_atr_on
| base_atr_off
;
2434 } else if (ZC_icntrl(tmpline
[t0
])
2435 #ifdef MULTIBYTE_SUPPORT
2436 && (unsigned)tmpline
[t0
] <= 0xffU
2439 ZLE_INT_T t
= tmpline
[++t0
];
2442 vp
->atr
= all_atr_on
;
2444 vp
->chr
= (((unsigned int)t
& ~0x80u
) > 31) ?
2445 ZWC('?') : (t
| ZWC('@'));
2446 vp
->atr
= all_atr_on
| all_atr_off
;
2449 #ifdef MULTIBYTE_SUPPORT
2452 char *dispptr
= dispchars
;
2456 if ((unsigned)tmpline
[t0
] > 0xffffU
) {
2457 sprintf(dispchars
, "<%.08x>", (unsigned)tmpline
[t0
]);
2459 sprintf(dispchars
, "<%.04x>", (unsigned)tmpline
[t0
]);
2462 if (mbtowc(&wc
, dispptr
, 1) == 1 /* paranoia */) {
2466 vp
->atr
= all_atr_on
;
2472 vp
[-1].atr
|= all_atr_off
;
2476 vp
->chr
= tmpline
[t0
];
2477 vp
->atr
= base_atr_on
| base_atr_off
;
2482 nvcs
= vp
- vbuf
- 1;
2488 /* determine which part of the new line buffer we want for the display */
2491 if ((winpos
&& nvcs
< winpos
+ 1) || (nvcs
> winpos
+ winw
- 2)) {
2492 if ((winpos
= nvcs
- ((winw
- hasam
) / 2)) < 0)
2496 vbuf
[winpos
].chr
= ZWC('<'); /* line continues to the left */
2497 vbuf
[winpos
].atr
= 0;
2499 if ((int)ZR_strlen(vbuf
+ winpos
) > (winw
- hasam
)) {
2500 vbuf
[winpos
+ winw
- hasam
- 1].chr
= ZWC('>'); /* line continues to right */
2501 vbuf
[winpos
+ winw
- hasam
- 1].atr
= 0;
2502 vbuf
[winpos
+ winw
- hasam
] = zr_zr
;
2504 ZR_strcpy(nbuf
[0], vbuf
+ winpos
);
2505 zfree(vbuf
, vsiz
* sizeof(*vbuf
));
2508 if (winpos
< lpromptw
) {
2509 /* skip start of buffer corresponding to prompt */
2510 winprompt
= lpromptw
- winpos
;
2515 if (winpos
!= owinpos
&& winprompt
) {
2517 int skipping
= 0, skipchars
= winpos
;
2519 * Need to output such part of the left prompt as fits.
2520 * Skip the first winpos characters, outputting
2521 * any characters marked with %{...%}.
2525 for (pptr
= lpromptbuf
; *pptr
; ) {
2526 if (*pptr
== Inpar
) {
2529 } else if (*pptr
== Outpar
) {
2534 int mblen
= MB_METACHARLENCONV(pptr
, &cc
);
2535 if (skipping
|| skipchars
== 0)
2538 #ifdef MULTIBYTE_SUPPORT
2543 if (*pptr
== Meta
) {
2545 fputc(*++pptr
^ 32, shout
);
2547 fputc(*pptr
, shout
);
2561 /* display the `visible' portion of the line buffer */
2563 vp
= *nbuf
+ winprompt
;
2564 refreshop
= *obuf
+ winprompt
;
2567 * Skip past all matching characters, but if there used
2568 * to be a prompt here be careful since all manner of
2569 * nastiness may be around.
2571 if (vp
- *nbuf
>= owinprompt
)
2572 for (; vp
->chr
&& ZR_equal(*refreshop
, *vp
);
2573 t0
++, vp
++, refreshop
++)
2576 if (!vp
->chr
&& !refreshop
->chr
)
2579 singmoveto(t0
); /* move to where we do all output from */
2581 if (!refreshop
->chr
) {
2582 if ((t0
= ZR_strlen(vp
)))
2588 if (tccan(TCCLEAREOL
))
2589 tcoutclear(TCCLEAREOL
);
2591 for (; refreshop
++->chr
; vcs
++)
2599 /* move to the new cursor position */
2612 /* choose cheapest movements for ttys without multiple movement capabilities -
2613 do this now because it's easier (to code) */
2615 if ((!tccan(TCMULTLEFT
) || pos
== 0) && (pos
<= vcs
/ 2)) {
2621 tc_leftcurs(vcs
- pos
);
2623 tc_rightcurs(pos
- vcs
);
2628 /* Provided for loading the module in a modular fashion */
2632 zle_refresh_boot(void)
2636 /* Provided for unloading the module in a modular fashion */
2640 zle_refresh_finish(void)
2644 if (region_highlights
)
2645 zfree(region_highlights
,
2646 sizeof(struct region_highlight
) * n_region_highlights
);