zsh-workers
 help / color / mirror / code / Atom feed
From: Roman Perepelitsa <roman.perepelitsa@gmail.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: PATCH: several bug fixes in countprompt
Date: Wed, 19 Jun 2019 12:22:13 +0200	[thread overview]
Message-ID: <CAN=4vMrT_CrkbCD7wsJnAwHSjLXgqHPusVzBuzD_Q8Oui3LN1g@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1138 bytes --]

This patch fixes 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 by hitting 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. Note that \u3050 has width 2.

    PROMPT="${(pl.40..\u3050.)}" zsh -df

Press ctrl-r or type ls<tab> 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<tab> to observe the effects of the bug.

On github: https://github.com/zsh-users/zsh/compare/master...romkatv:countprompt-fix.

I've only tested it on one terminal. Before I test it on a dozen of
different terminals, is there anything I'm missing? Anything I should
be on lookout for?

Roman.

[-- Attachment #2: countprompt-fix.patch --]
[-- Type: application/octet-stream, Size: 1740 bytes --]

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)

             reply	other threads:[~2019-06-19 10:23 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20190619102623epcas3p27d38284482c5631e0585059dc0b732a6@epcas3p2.samsung.com>
2019-06-19 10:22 ` Roman Perepelitsa [this message]
2019-06-19 10:56   ` Peter Stephenson
2019-06-19 14:44     ` Roman Perepelitsa
2019-06-19 14:52       ` Peter Stephenson
2019-06-19 14:58       ` Bart Schaefer
2019-06-19 15:09         ` Roman Perepelitsa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAN=4vMrT_CrkbCD7wsJnAwHSjLXgqHPusVzBuzD_Q8Oui3LN1g@mail.gmail.com' \
    --to=roman.perepelitsa@gmail.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).