From 80aa807a61cf10ebf459ba8e06621a5ec33041dc Mon Sep 17 00:00:00 2001 From: romkatv Date: Wed, 19 Jun 2019 12:16:41 +0200 Subject: fix multiple bugs in countprompt 1. Height off by one in the presence of meta characters at the end of the line. The following prompt has height 2 but countprompt used to return 3. PROMPT="${(pl.$COLUMNS..-.)}%f"$'\n' You can observe the effects of the bug with esc-x followed by reset-prompt. 2. Width off by one when a line is broken in the middle of a wide character. Assuming COLUMNS=79, the following prompt has width 2 but countprompt used to return 0. PROMPT="${(pl.40..\u3050.)}" zsh -df Press ctrl-r or type ls to observe the effects of the bug. 3. Width off by 1-7 when a line is broken in the middle of a tab. Assuming COLUMNS=79, the following prompt has width 1 but countprompt used to return 0. PROMPT="${(pl.10..\t.)}" zsh -df Press Ctrl-R or type ls to observe the effects of the bug. --- Src/prompt.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'Src') diff --git a/Src/prompt.c b/Src/prompt.c index e8d50d161..7f4d7a70e 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -1075,10 +1075,9 @@ putstr(int d) mod_export void countprompt(char *str, int *wp, int *hp, int overf) { - int w = 0, h = 1, multi = 0; + int w = 0, h = 1, multi = 0, wcw = 0; int s = 1; #ifdef MULTIBYTE_SUPPORT - int wcw; char inchar; mbstate_t mbs; wchar_t wc; @@ -1092,10 +1091,23 @@ countprompt(char *str, int *wp, int *hp, int overf) * prompt and the line it terminates takes up exactly the width of the * terminal */ - if (w >= zterm_columns && overf >= 0 && !multi && *str != '\n') { - w = 0; + while (w > zterm_columns && overf >= 0 && !multi) { h++; + if (wcw) { + /* + * Wide characters don't get split off. They move to the + * next line if there is not enough space. + */ + w = wcw; + break; + } else { + /* + * Tabs overflow to the next line as if they were made of spaces. + */ + w -= zterm_columns; + } } + wcw = 0; /* * Input string should be metafied, so tokens in it should * be real tokens, even if there are multibyte characters. @@ -1176,12 +1188,19 @@ countprompt(char *str, int *wp, int *hp, int overf) * This isn't easy to handle generally; just assume there's no * output. */ - if(w >= zterm_columns && overf >= 0) { - if (!overf || w > zterm_columns) { - w = 0; - h++; + while (w > zterm_columns && overf >= 0) { + h++; + if (wcw) { + w = wcw; + break; + } else { + w -= zterm_columns; } } + if (w == zterm_columns && overf == 0) { + w = 0; + h++; + } if(wp) *wp = w; if(hp) -- cgit 1.4.1