summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoff Wing <gcw@users.sourceforge.net>2001-08-15 14:48:48 +0000
committerGeoff Wing <gcw@users.sourceforge.net>2001-08-15 14:48:48 +0000
commit2eda2a09212e220edf09c978d038d47de0e64267 (patch)
treefddcc4048783d8ad877a93799452b3704f1d3e27
parent71a6bbaebc0b10177ec73e4112ae6482d81d0334 (diff)
downloadzsh-2eda2a09212e220edf09c978d038d47de0e64267.tar.gz
zsh-2eda2a09212e220edf09c978d038d47de0e64267.zip
15621: display of status line was being mucked up; continuation
markers "<...." and "<....>" weren't being display properly
-rw-r--r--Src/Zle/zle_refresh.c309
1 files changed, 190 insertions, 119 deletions
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 4621b5124..a05b6634b 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -33,7 +33,7 @@
/* Expanded prompts */
/**/
-char *lpptbuf, *rpptbuf;
+char *lpromptbuf, *rpromptbuf;
/* Text attributes after displaying prompts */
@@ -43,22 +43,38 @@ unsigned pmpt_attr, rpmpt_attr;
/* number of lines displayed */
/**/
-int nlnct;
+mod_export int nlnct;
/* Most lines of the buffer we've shown at once with the current list *
* showing. == 0 if there is no list. == -1 if a new list has just *
- * been put on the screen. == -2 if refresh() needs to put up a new *
+ * been put on the screen. == -2 if zrefresh() needs to put up a new *
* list. */
/**/
-int showinglist;
+mod_export int showinglist;
+
+/* > 0 if a completion list is displayed below the prompt,
+ * < 0 if a list is displayed above the prompt. */
+
+/**/
+mod_export int listshown;
+
+/* Length of last list displayed (if it is below the prompt). */
+
+/**/
+mod_export int lastlistlen;
/* Non-zero if ALWAYS_LAST_PROMPT has been used, meaning that the *
* screen below the buffer display should not be cleared by *
- * refresh(), but should be by trashzle(). */
+ * zrefresh(), but should be by trashzle(). */
+
+/**/
+mod_export int clearflag;
+
+/* Non-zero if zrefresh() should clear the list below the prompt. */
/**/
-int clearflag;
+mod_export int clearlist;
#ifdef HAVE_SELECT
/* cost of last update */
@@ -75,19 +91,20 @@ int cost;
#endif
/* Oct/Nov 94: <mason> some code savagely redesigned to fix several bugs -
- refreshline() & tc_rightcurs() majorly rewritten; refresh() fixed -
+ refreshline() & tc_rightcurs() majorly rewritten; zrefresh() fixed -
I've put my fingers into just about every routine in here -
- any queries about updates to mason@werple.net.au */
+ any queries about updates to mason@primenet.com.au */
static char **nbuf = NULL, /* new video buffer line-by-line char array */
**obuf = NULL; /* old video buffer line-by-line char array */
static int more_start, /* more text before start of screen? */
more_end, /* more stuff after end of screen? */
- lppth, /* lines taken up by the prompt */
olnct, /* previous number of lines */
ovln, /* previous video cursor position line */
- pptw, rpw, /* prompt widths on screen */
- rppth, /* right prompt height */
+ lpromptw, rpromptw, /* prompt widths on screen */
+ lpromptwof, /* left prompt width with real end position */
+ lprompth, /* lines taken up by the prompt */
+ rprompth, /* right prompt height */
vcs, vln, /* video cursor position column & line */
vmaxln, /* video maximum number of lines */
winw, winh, rwinh, /* window width & height */
@@ -100,7 +117,6 @@ resetvideo(void)
int ln;
static int lwinw = -1, lwinh = -1; /* last window width & height */
- genprompts();
winw = columns; /* terminal width */
if (termflags & TERM_SHORT)
winh = 1;
@@ -132,13 +148,22 @@ resetvideo(void)
*obuf[ln] = '\0';
}
- if (pptw) {
- memset(nbuf[0], ' ', pptw);
- memset(obuf[0], ' ', pptw);
- nbuf[0][pptw] = obuf[0][pptw] = '\0';
+ countprompt(lpromptbuf, &lpromptwof, &lprompth, 1);
+ countprompt(rpromptbuf, &rpromptw, &rprompth, 0);
+ if (lpromptwof != winw)
+ lpromptw = lpromptwof;
+ else {
+ lpromptw = 0;
+ lprompth++;
+ }
+
+ if (lpromptw) {
+ memset(nbuf[0], ' ', lpromptw);
+ memset(obuf[0], ' ', lpromptw);
+ nbuf[0][lpromptw] = obuf[0][lpromptw] = '\0';
}
- vcs = pptw;
+ vcs = lpromptw;
olnct = nlnct = 0;
if (showinglist > 0)
showinglist = -2;
@@ -198,16 +223,25 @@ scrollwindow(int tline)
if (ln != winh - 1) \
ln++; \
else \
- if (tosln < 3) { \
+ if (tosln > ln) { \
+ tosln--; \
+ if (nvln > 1) { \
+ scrollwindow(0); \
+ nvln--; \
+ } else \
+ more_end = 1; \
+ } else if (tosln > 2 && nvln > 1) { \
+ tosln--; \
+ if (tosln <= nvln) { \
+ scrollwindow(0); \
+ nvln--; \
+ } else { \
+ scrollwindow(tosln); \
+ more_end = 1; \
+ } \
+ } else { \
more_status = 1; \
scrollwindow(tosln + 1); \
- } else if (tosln - 1 <= nvln) { \
- scrollwindow(0); \
- if (nvln) \
- nvln--, tosln--; \
- } else { \
- tosln--; \
- scrollwindow(tosln); \
} \
if (!nbuf[ln]) \
nbuf[ln] = (char *)zalloc(winw + 2); \
@@ -223,8 +257,8 @@ static int cleareol, /* clear to end-of-line (if can't cleareod) */
numscrolls, onumscrolls;
/**/
-void
-refresh(void)
+mod_export void
+zrefresh(void)
{
static int inlist; /* avoiding recursion */
int canscroll = 0, /* number of lines we are allowed to scroll */
@@ -240,19 +274,45 @@ refresh(void)
char **qbuf; /* tmp */
/* If this is called from listmatches() (indirectly via trashzle()), and *
- * that was called from the end of refresh(), then we don't need to do *
+ * that was called from the end of zrefresh(), then we don't need to do *
* anything. All this `inlist' code is actually unnecessary, but it *
* improves speed a little in a common case. */
if (inlist)
return;
+ if (clearlist && listshown > 0) {
+ if (tccan(TCCLEAREOD)) {
+ int ovln = vln, ovcs = vcs;
+ char *nb = nbuf[vln];
+
+ nbuf[vln] = obuf[vln];
+ moveto(nlnct, 0);
+ tcout(TCCLEAREOD);
+ moveto(ovln, ovcs);
+ nbuf[vln] = nb;
+ } else {
+ invalidatelist();
+ moveto(0, 0);
+ clearflag = 0;
+ resetneeded = 1;
+ }
+ listshown = lastlistlen = 0;
+ if (showinglist != -2)
+ showinglist = 0;
+ }
+ clearlist = 0;
+
#ifdef HAVE_SELECT
cost = 0; /* reset */
#endif
/* Nov 96: <mason> I haven't checked how complete this is. sgtty stuff may
or may not work */
+#if defined(SGTABTYPE)
oxtabs = ((SGTTYFLAG & SGTABTYPE) == SGTABTYPE);
+#else
+ oxtabs = 0;
+#endif
cleareol = 0; /* unset */
more_start = more_end = 0; /* unset */
@@ -263,12 +323,13 @@ refresh(void)
termflags &= ~TERM_SHORT;
if (resetneeded) {
onumscrolls = 0;
- setterm();
+ zsetterm();
#ifdef TIOCGWINSZ
if (winchanged) {
moveto(0, 0);
t0 = olnct; /* this is to clear extra lines even when */
winchanged = 0; /* the terminal cannot TCCLEAREOD */
+ listshown = 0;
}
#endif
resetvideo();
@@ -280,21 +341,27 @@ refresh(void)
tsetcap(TCSTANDOUTEND, 0);
tsetcap(TCUNDERLINEEND, 0);
- if (!clearflag)
+ if (!clearflag) {
if (tccan(TCCLEAREOD))
tcout(TCCLEAREOD);
else
cleareol = 1; /* request: clear to end of line */
+ if (listshown > 0)
+ listshown = 0;
+ }
if (t0 > -1)
olnct = t0;
if (termflags & TERM_SHORT)
vcs = 0;
- else if (!clearflag && lpptbuf[0])
- zputs(lpptbuf, shout);
+ else if (!clearflag && lpromptbuf[0]) {
+ zputs(lpromptbuf, shout);
+ if (lpromptwof == winw)
+ zputs("\n", shout); /* works with both hasam and !hasam */
+ }
if (clearflag) {
zputc('\r', shout);
vcs = 0;
- moveto(0, pptw);
+ moveto(0, lpromptw);
}
fflush(shout);
clearf = clearflag;
@@ -326,7 +393,7 @@ refresh(void)
if (!*nbuf)
*nbuf = (char *)zalloc(winw + 2);
- s = (unsigned char *)(nbuf[ln = 0] + pptw);
+ s = (unsigned char *)(nbuf[ln = 0] + lpromptw);
t = line;
sen = (unsigned char *)(*nbuf + winw);
for (; t < line+ll; t++) {
@@ -377,13 +444,6 @@ refresh(void)
if (statusline) {
tosln = ln + 1;
- if (ln == winh - 1) {
- if (nvln > 0) {
- scrollwindow(0);
- nvln--;
- }
- tosln--;
- }
nbuf[ln][winw + 1] = '\0'; /* text not wrapped */
snextline
t = (unsigned char *)statusline;
@@ -402,38 +462,59 @@ refresh(void)
snextline
}
}
+ if (s == sen)
+ snextline
}
+ *s = '\0';
/* insert <.... at end of last line if there is more text past end of screen */
if (more_end) {
if (!statusline)
tosln = winh;
- strncpy(nbuf[tosln - 1] + winw - 7, " <.... ", 7);
+ s = nbuf[tosln - 1];
+ sen = s + winw - 7;
+ for (; s < sen; s++) {
+ if (*s == '\0') {
+ for (; s < sen; )
+ *s++ = ' ';
+ break;
+ }
+ }
+ strncpy(sen, " <.... ", 7);
nbuf[tosln - 1][winw] = nbuf[tosln - 1][winw + 1] = '\0';
}
/* insert <....> at end of first status line if status is too big */
if (more_status) {
- strncpy(nbuf[tosln] + winw - 8, " <....> ", 8);
+ s = nbuf[tosln];
+ sen = s + winw - 8;
+ for (; s < sen; s++) {
+ if (*s == '\0') {
+ for (; s < sen; )
+ *s++ = ' ';
+ break;
+ }
+ }
+ strncpy(sen, " <....> ", 8);
nbuf[tosln][winw] = nbuf[tosln][winw + 1] = '\0';
}
- *s = '\0';
nlnct = ln + 1;
for (ln = nlnct; ln < winh; ln++)
zfree(nbuf[ln], winw + 2), nbuf[ln] = NULL;
/* determine whether the right-prompt exists and can fit on the screen */
if (!more_start)
- put_rpmpt = rppth == 1 && rpptbuf[0] && !strchr(rpptbuf, '\t') &&
- (int)strlen(nbuf[0]) + rpw < winw - 1;
+ put_rpmpt = rprompth == 1 && rpromptbuf[0] &&
+ !strchr(rpromptbuf, '\t') &&
+ (int)strlen(nbuf[0]) + rpromptw < winw - 1;
else {
/* insert >.... on first line if there is more text before start of screen */
- memset(nbuf[0], ' ', pptw);
- t0 = winw - pptw;
+ memset(nbuf[0], ' ', lpromptw);
+ t0 = winw - lpromptw;
t0 = t0 > 5 ? 5 : t0;
- strncpy(nbuf[0] + pptw, ">....", t0);
- memset(nbuf[0] + pptw + t0, ' ', winw - t0 - pptw);
+ strncpy(nbuf[0] + lpromptw, ">....", t0);
+ memset(nbuf[0] + lpromptw + t0, ' ', winw - t0 - lpromptw);
nbuf[0][winw] = nbuf[0][winw + 1] = '\0';
}
@@ -445,7 +526,7 @@ refresh(void)
/* if old line and new line are different,
see if we can insert/delete a line to speed up update */
- if (ln < olnct - 1 && !(hasam && vcs == winw) &&
+ if (ln > 0 && ln < olnct - 1 && !(hasam && vcs == winw) &&
nbuf[ln] && obuf[ln] &&
strncmp(nbuf[ln], obuf[ln], 16)) {
if (tccan(TCDELLINE) && obuf[ln + 1] && obuf[ln + 1][0] &&
@@ -477,8 +558,8 @@ refresh(void)
/* output the right-prompt if appropriate */
if (put_rpmpt && !ln && !oput_rpmpt) {
- moveto(0, winw - 1 - rpw);
- zputs(rpptbuf, shout);
+ moveto(0, winw - 1 - rpromptw);
+ zputs(rpromptbuf, shout);
vcs = winw - 1;
/* reset character attributes to that set by the main prompt */
txtchange = pmpt_attr;
@@ -547,7 +628,7 @@ individually */
inlist = 1;
listmatches();
inlist = 0;
- refresh();
+ zrefresh();
}
if (showinglist == -1)
showinglist = nlnct;
@@ -596,7 +677,7 @@ refreshline(int ln)
if (cleareol /* request to clear to end of line */
|| !nllen /* no line buffer given */
|| (ln == 0 && (put_rpmpt != oput_rpmpt))) { /* prompt changed */
- p1 = halloc(winw + 2);
+ p1 = zhalloc(winw + 2);
if (nllen)
strncpy(p1, nl, nllen);
memset(p1 + nllen, ' ', winw - nllen);
@@ -608,7 +689,7 @@ refreshline(int ln)
nl = p1; /* don't keep the padding for prompt line */
nllen = winw;
} else if (ollen > nllen) { /* make new line at least as long as old */
- p1 = halloc(ollen + 1);
+ p1 = zhalloc(ollen + 1);
strncpy(p1, nl, nllen);
memset(p1 + nllen, ' ', ollen - nllen);
p1[ollen] = '\0';
@@ -659,12 +740,12 @@ refreshline(int ln)
/* 2c: if we're on the first line, start checking at the end of the prompt;
we shouldn't be doing anything within the prompt */
- if (ln == 0 && pptw) {
- i = pptw - ccs;
+ if (ln == 0 && lpromptw) {
+ i = lpromptw - ccs;
j = strlen(ol);
nl += i;
ol += (i > j ? j : i); /* if ol is too short, point it to '\0' */
- ccs = pptw;
+ ccs = lpromptw;
}
/* 3: main display loop - write out the buffer using whatever tricks we can */
@@ -815,7 +896,7 @@ moveto(int ln, int cl)
instead of TCDOWN */
while (ln > vln) {
- if (vln < vmaxln - 1)
+ if (vln < vmaxln - 1) {
if (ln > vmaxln - 1) {
if (tc_downcurs(vmaxln - 1 - vln))
vcs = 0;
@@ -826,6 +907,7 @@ moveto(int ln, int cl)
vln = ln;
continue;
}
+ }
zputc('\r', shout), vcs = 0; /* safety precaution */
while (ln > vln) {
zputc('\n', shout);
@@ -833,24 +915,12 @@ moveto(int ln, int cl)
}
}
- if (cl == vcs)
- return;
-
-/* choose cheapest movements for ttys without multiple movement capabilities -
- do this now because it's easier (to code) */
- if (cl <= vcs / 2) {
- zputc('\r', shout);
- vcs = 0;
- }
- if (vcs < cl)
- tc_rightcurs(cl);
- else if (vcs > cl)
- tc_leftcurs(vcs - cl);
- vcs = cl;
+ if (cl != vcs)
+ singmoveto(cl);
}
/**/
-int
+mod_export int
tcmultout(int cap, int multcap, int ct)
{
if (tccan(multcap) && (!tccan(cap) || tclen[multcap] <= tclen[cap] * ct)) {
@@ -864,16 +934,17 @@ tcmultout(int cap, int multcap, int ct)
return 0;
}
+/* ct: number of characters to move across */
/**/
static void
-tc_rightcurs(int cl)
+tc_rightcurs(int ct)
{
- int ct, /* number of characters to move across */
+ int cl, /* ``desired'' absolute horizontal position */
i = vcs, /* cursor position after initial movements */
j;
char *t;
- ct = cl - vcs;
+ cl = ct + vcs;
/* do a multright if we can - it's the most reliable */
if (tccan(TCMULTRIGHT)) {
@@ -881,6 +952,13 @@ tc_rightcurs(int cl)
return;
}
+/* do an absolute horizontal position if we can */
+ if (tccan(TCHORIZPOS)) {
+ tcoutarg(TCHORIZPOS, cl);
+ return;
+ }
+
+/* XXX: should really check "it" in termcap and use / and % */
/* try tabs if tabs are non destructive and multright is not possible */
if (!oxtabs && tccan(TCNEXTTAB) && ((vcs | 7) < cl)) {
i = (vcs | 7) + 1;
@@ -893,21 +971,23 @@ tc_rightcurs(int cl)
/* otherwise _carefully_ write the contents of the video buffer.
if we're anywhere in the prompt, goto the left column and write the whole
- prompt out unless ztrlen(lpptbuf) == pptw : we can cheat then */
- if (vln == 0 && i < pptw) {
- if (strlen(lpptbuf) == pptw)
- fputs(lpptbuf + i, shout);
- else if (tccan(TCRIGHT) && (tclen[TCRIGHT] * ct <= ztrlen(lpptbuf)))
+ prompt out unless ztrlen(lpromptbuf) == lpromptw : we can cheat then */
+ if (vln == 0 && i < lpromptw && !(termflags & TERM_SHORT)) {
+ if (strlen(lpromptbuf) == lpromptw)
+ fputs(lpromptbuf + i, shout);
+ else if (tccan(TCRIGHT) && (tclen[TCRIGHT] * ct <= ztrlen(lpromptbuf)))
/* it is cheaper to send TCRIGHT than reprint the whole prompt */
- for (ct = pptw - i; ct--; )
+ for (ct = lpromptw - i; ct--; )
tcout(TCRIGHT);
else {
if (i != 0)
zputc('\r', shout);
- tc_upcurs(lppth - 1);
- zputs(lpptbuf, shout);
+ tc_upcurs(lprompth - 1);
+ zputs(lpromptbuf, shout);
+ if (lpromptwof == winw)
+ zputs("\n", shout); /* works with both hasam and !hasam */
}
- i = pptw;
+ i = lpromptw;
ct = cl - i;
}
@@ -936,7 +1016,7 @@ tc_downcurs(int ct)
}
/**/
-void
+mod_export void
tcout(int cap)
{
tputs(tcstr[cap], 1, putshout);
@@ -955,23 +1035,25 @@ tcoutarg(int cap, int arg)
}
/**/
-void
-clearscreen(void)
+mod_export int
+clearscreen(char **args)
{
tcout(TCCLEARSCREEN);
resetneeded = 1;
clearflag = 0;
+ return 0;
}
/**/
-void
-redisplay(void)
+mod_export int
+redisplay(char **args)
{
moveto(0, 0);
zputc('\r', shout); /* extra care */
- tc_upcurs(lppth - 1);
+ tc_upcurs(lprompth - 1);
resetneeded = 1;
clearflag = 0;
+ return 0;
}
/**/
@@ -987,7 +1069,7 @@ singlerefresh(void)
nlnct = 1;
/* generate the new line buffer completely */
- for (vsiz = 1 + pptw, t0 = 0; t0 != ll; t0++, vsiz++)
+ for (vsiz = 1 + lpromptw, t0 = 0; t0 != ll; t0++, vsiz++)
if (line[t0] == '\t')
vsiz = (vsiz | 7) + 1;
else if (icntrl(line[t0]))
@@ -1002,9 +1084,10 @@ singlerefresh(void)
cs = 0;
}
- memcpy(vbuf, strchr(lpptbuf, 0) - pptw, pptw); /* only use last part of prompt */
- vbuf[pptw] = '\0';
- vp = vbuf + pptw;
+ /* only use last part of prompt */
+ memcpy(vbuf, strchr(lpromptbuf, 0) - lpromptw, lpromptw);
+ vbuf[lpromptw] = '\0';
+ vp = vbuf + lpromptw;
for (t0 = 0; t0 != ll; t0++) {
if (line[t0] == '\t')
@@ -1086,31 +1169,19 @@ singmoveto(int pos)
{
if (pos == vcs)
return;
- if (pos <= vcs / 2) {
+
+/* choose cheapest movements for ttys without multiple movement capabilities -
+ do this now because it's easier (to code) */
+
+ if ((!tccan(TCMULTLEFT) || pos == 0) && (pos <= vcs / 2)) {
zputc('\r', shout);
vcs = 0;
}
- if (pos < vcs) {
- tc_leftcurs(vcs - pos);
- vcs = pos;
- }
- if (pos > vcs) {
- if (tcmultout(TCRIGHT, TCMULTRIGHT, pos - vcs))
- vcs = pos;
- else
- while (pos > vcs) {
- zputc(nbuf[0][vcs], shout);
- vcs++;
- }
- }
-}
-/* recheck size of prompts */
+ if (pos < vcs)
+ tc_leftcurs(vcs - pos);
+ else if (pos > vcs)
+ tc_rightcurs(pos - vcs);
-/**/
-static void
-genprompts(void)
-{
- countprompt(lpptbuf, &pptw, &lppth);
- countprompt(rpptbuf, &rpw, &rppth);
+ vcs = pos;
}