From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18402 invoked from network); 19 Mar 2007 22:26:24 -0000 X-Spam-Checker-Version: SpamAssassin 3.1.8 (2007-02-13) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00,FORGED_RCVD_HELO autolearn=ham version=3.1.8 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 19 Mar 2007 22:26:24 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 68456 invoked from network); 19 Mar 2007 22:26:18 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 19 Mar 2007 22:26:18 -0000 Received: (qmail 23618 invoked by alias); 19 Mar 2007 22:26:16 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 23224 Received: (qmail 23608 invoked from network); 19 Mar 2007 22:26:15 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 19 Mar 2007 22:26:15 -0000 Received: (qmail 68114 invoked from network); 19 Mar 2007 22:26:15 -0000 Received: from mtaout01-winn.ispmail.ntl.com (81.103.221.47) by a.mx.sunsite.dk with SMTP; 19 Mar 2007 22:26:08 -0000 Received: from aamtaout01-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout01-winn.ispmail.ntl.com with ESMTP id <20070319222606.HMYM2951.mtaout01-winn.ispmail.ntl.com@aamtaout01-winn.ispmail.ntl.com>; Mon, 19 Mar 2007 22:26:06 +0000 Received: from pwslaptop.csr.com ([81.107.47.85]) by aamtaout01-winn.ispmail.ntl.com with SMTP id <20070319222605.OFEQ219.aamtaout01-winn.ispmail.ntl.com@pwslaptop.csr.com>; Mon, 19 Mar 2007 22:26:05 +0000 Date: Mon, 19 Mar 2007 22:25:46 +0000 From: Peter Stephenson To: zsh-workers@sunsite.dk, "David Durrleman" Subject: Re: zsh on short terminals Message-Id: <20070319222546.e69f669f.p.w.stephenson@ntlworld.com> In-Reply-To: <20070319131317.6851b5b2.pws@csr.com> References: <1bea19c20703142005t68ccbe91ie9572c97a865f561@mail.gmail.com> <20070319131317.6851b5b2.pws@csr.com> X-Mailer: Sylpheed version 2.2.10 (GTK+ 2.10.8; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Mon, 19 Mar 2007 13:13:17 +0000 Peter Stephenson wrote: > "David Durrleman" wrote: > > If I run a terminal with less than 3 lines (geometry 80x1 for > > example), then the first 17 chars of the prompt are not displayed > > Yes, it's a bug. > > This is a bit horrible. Zsh goes into a special mode when the terminal > height is less than 3, equivalent to single line mode---that's because it > can't fit the two extra lines the line editor normally expects to be there > as a minimum under the prompt. However, it looks like single line mode has > been allowed to lag behind the normal input mode and hasn't been fixed > for ages. I don't have time to rewrite it completely, so I'm not sure what > to do. Good news! I exaggerated wildly. Index: Src/Zle/zle_refresh.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_refresh.c,v retrieving revision 1.46 diff -u -r1.46 zle_refresh.c --- Src/Zle/zle_refresh.c 13 Jan 2006 17:46:09 -0000 1.46 +++ Src/Zle/zle_refresh.c 19 Mar 2007 22:22:56 -0000 @@ -227,7 +227,8 @@ vcs, vln, /* video cursor position column & line */ vmaxln, /* video maximum number of lines */ winw, winh, rwinh, /* window width & height */ - winpos; /* singlelinezle: line's position in window */ + winpos, /* singlelinezle: line's position in window */ + winprompt; /* singlelinezle: part of lprompt showing */ /**/ void @@ -242,7 +243,8 @@ else winh = (lines < 2) ? 24 : lines; rwinh = lines; /* keep the real number of lines */ - winpos = vln = vmaxln = 0; + vln = vmaxln = winprompt = 0; + winpos = -1; if (lwinw != winw || lwinh != winh) { if (nbuf) { for (ln = 0; ln != lwinh; ln++) { @@ -1443,21 +1445,12 @@ { REFRESH_STRING vbuf, vp, /* video buffer and pointer */ *qbuf, /* tmp */ - refreshop = *obuf; /* pointer to old video buffer */ + refreshop; /* pointer to old video buffer */ int t0, /* tmp */ vsiz, /* size of new video buffer */ - nvcs = 0; /* new video cursor column */ -#ifdef MULTIBYTE_SUPPORT - int eol = 0; /* has mbrtowc() returned -2? */ - /* - * converted lprompt and pointer: no WEOF hack here since - * we always output the full prompt and count its width. - */ - ZLE_STRING_T lpwbuf, lpwp; - char *lpptr, /* pointer into multibyte lprompt */ - *lpend; /* end of multibyte lprompt */ - mbstate_t mbs; /* shift state */ -#endif + nvcs = 0, /* new video cursor column */ + owinpos = winpos, /* previous window position */ + owinprompt = winprompt; /* previous winprompt */ nlnct = 1; /* generate the new line buffer completely */ @@ -1480,56 +1473,10 @@ tmpcs = 0; } - /* only use last part of prompt */ -#ifdef MULTIBYTE_SUPPORT - /* - * Convert the entire lprompt so that we know how to count - * characters. - */ - lpend = strchr(lpromptbuf, 0); - /* Worst case number of characters, not null-terminated */ - lpwp = lpwbuf = (ZLE_STRING_T)zalloc((lpend - lpromptbuf) - * sizeof(*lpwbuf)); - /* Reset shift state, maybe. */ - memset(&mbs, '\0', sizeof mbs); - for (lpptr = lpromptbuf; lpptr < lpend; ) { - size_t cnt = eol ? MB_INVALID : mbrtowc(lpwp, lpptr, lpend-lpptr, &mbs); - switch (cnt) { - case MB_INCOMPLETE: - eol = 1; - /* FALL THROUGH */ - case MB_INVALID: - memset(&mbs, '\0', sizeof mbs); - /* FALL THROUGH */ - case 0: - /* dunno, try to recover */ - lpptr++; - *lpwp++ = ZWC('?'); - break; - default: - /* successfully converted */ - lpptr += cnt; - lpwp++; - break; - } - } - if (lpwp - lpwbuf < lpromptw) { - /* Not enough characters for lpromptw. */ - ZR_memcpy(vbuf, lpwbuf, lpwp - lpwbuf); - vp = vbuf + (lpwp - lpwbuf); - while (vp < vbuf + lpromptw) - *vp++ = ZWC(' '); - } else { - ZR_memcpy(vbuf, lpwp - lpromptw, lpromptw); - vp = vbuf + lpromptw; - } - *vp = ZWC('\0'); - zfree(lpwbuf, lpromptw * sizeof(*lpwbuf)); -#else - memcpy(vbuf, strchr(lpromptbuf, 0) - lpromptw, lpromptw); - vbuf[lpromptw] = '\0'; + /* prompt is not directly copied into the video buffer */ + ZR_memset(vbuf, ZWC(' '), lpromptw); vp = vbuf + lpromptw; -#endif + *vp = ZWC('\0'); for (t0 = 0; t0 < tmpll; t0++) { if (tmpline[t0] == ZWC('\t')) { @@ -1561,6 +1508,8 @@ *vp = ZWC('\0'); /* determine which part of the new line buffer we want for the display */ + if (winpos == -1) + winpos = 0; if ((winpos && nvcs < winpos + 1) || (nvcs > winpos + winw - 2)) { if ((winpos = nvcs - ((winw - hasam) / 2)) < 0) winpos = 0; @@ -1575,10 +1524,71 @@ zfree(vbuf, vsiz * sizeof(*vbuf)); nvcs -= winpos; -/* display the `visable' portion of the line buffer */ - for (t0 = 0, vp = *nbuf;;) { - /* skip past all matching characters */ - for (; *vp && *vp == *refreshop; t0++, vp++, refreshop++) ; + if (winpos < lpromptw) { + /* skip start of buffer corresponding to prompt */ + winprompt = lpromptw - winpos; + } else { + /* don't */ + winprompt = 0; + } + if (winpos != owinpos && winprompt) { + char *pptr; + int skipping = 0, skipchars = winpos; + /* + * Need to output such part of the left prompt as fits. + * Skip the first winpos characters, outputting + * any characters marked with %{...%}. + */ + singmoveto(0); + MB_METACHARINIT(); + for (pptr = lpromptbuf; *pptr; ) { + if (*pptr == Inpar) { + skipping = 1; + pptr++; + } else if (*pptr == Outpar) { + skipping = 0; + pptr++; + } else { + convchar_t cc; + int mblen = MB_METACHARLENCONV(pptr, &cc); + if (skipping || skipchars == 0) + { + while (mblen) { +#ifdef MULTIBYTE_SUPPORT + if (cc == WEOF) + fputc('?', shout); + else +#endif + if (*pptr == Meta) { + mblen--; + fputc(*++pptr ^ 32, shout); + } else { + fputc(*pptr, shout); + } + pptr++; + mblen--; + } + } else { + skipchars--; + pptr += mblen; + } + } + } + vcs = winprompt; + } + +/* display the `visible' portion of the line buffer */ + t0 = winprompt; + vp = *nbuf + winprompt; + refreshop = *obuf + winprompt; + for (;;) { + /* + * Skip past all matching characters, but if there used + * to be a prompt here be careful since all manner of + * nastiness may be around. + */ + if (vp - *nbuf >= owinprompt) + for (; *vp && *vp == *refreshop; t0++, vp++, refreshop++) ; if (!*vp && !*refreshop) break; -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/