Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi-byte characters in prompt(chars) causes in-line editing to fail #78

Open
Tux opened this issue Jul 27, 2023 · 2 comments
Open

multi-byte characters in prompt(chars) causes in-line editing to fail #78

Tux opened this issue Jul 27, 2023 · 2 comments

Comments

@Tux
Copy link

Tux commented Jul 27, 2023

% set prompt='%# '
% set promptchars='>#'
> echo $prompt
%#
> ecgo $x

Correct > echo $x [y|n|E|a]? edit
> ecgo $x

The cursor is now after the x, as expected. Left arrow, home, etc all work as expected

> set promptchars="\U1F427#"
\

Not what I hoped for

\ set promptchars="🐧#"
🐧

Ahhhhh, beautiful :)

🐧 ecgo $x

Correct > echo $x [y|n|E|a]? edit
🐧 ecgo $x

The cursor is now after the x where it is expected, but using left-arrow will move the cursor 5 positions to the right instead. Now pressing the Home key puts the cursor on the x instead of on the e.
FWIW the same happens without using special characters in promptchars:

% set promptchars=">#"
> set prompt="🐧 "
🐧 ecgo $x

etc, same behavior.

My goal was to use "🐧䷡" on my devel box, where the U1f427 \N{PENGUIN} was for user "tux" and U04de1 \N{HEXAGRAM FOR GREAT POWER} was for user "root"

@Tux
Copy link
Author

Tux commented Jul 28, 2023

90% is debugging. Look at the change around line 1155

diff --git a/ed.refresh.c b/ed.refresh.c
index 183050e0..8b22a128 100644
--- a/ed.refresh.c
+++ b/ed.refresh.c
@@ -33,6 +33,7 @@
 #include "ed.h"
 /* #define DEBUG_UPDATE */
 /* #define DEBUG_REFRESH */
+/* #define DEBUG_REFCURSOR */
 /* #define DEBUG_LITERAL */
 
 /* refresh.c -- refresh the current set of lines on the screen */
@@ -1139,6 +1140,10 @@ cpy_pad_spaces(Char *dst, Char *src, int width)
 static void
 CalcPosition(int w, int th, int *h, int *v)
 {
+#ifdef DEBUG_REFCURSOR
+    int is = NLSCLASS_ILLEGAL_SIZE (w);
+    reprintf ("CP:%d W: %2d/%d, H: %d, V: %d, th: %d\r\n", __LINE__, w, is, *h, *v, th);
+#endif
     switch(w) {
 	case NLSCLASS_NL:
 	    *h = 0;
@@ -1155,6 +1160,8 @@ CalcPosition(int w, int th, int *h, int *v)
 	    *h += 4;
 	    break;
 	case NLSCLASS_ILLEGAL2:
+	    *h += NLSCLASS_ILLEGAL_SIZE(w);
+	    break;
 	case NLSCLASS_ILLEGAL3:
 	case NLSCLASS_ILLEGAL4:
 	case NLSCLASS_ILLEGAL5:
@@ -1163,23 +1170,33 @@ CalcPosition(int w, int th, int *h, int *v)
 	default:
 	    *h += w;
     }
+#ifdef DEBUG_REFCURSOR
+    reprintf ("cP:%d W: %2d/%d, H: %d, V: %d, th: %d\r\n", __LINE__, w, is, *h, *v, th);
+#endif
     if (*h >= th) {		/* check, extra long tabs picked up here also */
 	*h -= th;
 	(*v)++;
     }
+#ifdef DEBUG_REFCURSOR
+    reprintf ("cP:%d W: %2d/%d, H: %d, V: %d, th: %d\r\n", __LINE__, w, is, *h, *v, th);
+#endif
 }
 
 void
 RefCursor(void)
 {				/* only move to new cursor pos */
     Char *cp;
-    int w, h, th, v;
+    int w, h, th, v, pl;
 
     /* first we must find where the cursor is... */
     h = 0;
     v = 0;
     th = TermH;			/* optimize for speed */
 
+    /* Prompt length in bytes and in characters */
+    for (cp = Prompt; *cp; cp++);
+    pl = cp - Prompt;
+
     for (cp = Prompt; cp != NULL && *cp; ) {	/* do prompt */
 	if (*cp & LITERAL) {
 	    cp++;
@@ -1189,12 +1206,18 @@ RefCursor(void)
 	cp++;
 	CalcPosition(w, th, &h, &v);
     }
+#ifdef DEBUG_REFCURSOR
+    reprintf ("RC:%d '%s'/%d => H: %d, V: %d, th: %d, W: %d\r\n", __LINE__, Prompt, pl, h, v, th, w);
+#endif
 
     for (cp = InputBuf; cp < Cursor;) {	/* do input buffer to Cursor */
 	w = NLSClassify(*cp & CHAR, cp == InputBuf, 0);
 	cp++;
 	CalcPosition(w, th, &h, &v);
     }
+#ifdef DEBUG_REFCURSOR
+    reprintf ("RC:%d '%s'/%d => H: %d, V: %d, th: %d, W: %d\r\n", __LINE__, Prompt, pl, h, v, th, w);
+#endif
 
     /* now go there */
     MoveToLine(v);

Fixed the problem. Does that seem reasonable? What would break? Are there any tests I should run?

@Tux
Copy link
Author

Tux commented Jul 28, 2023

Tux/tcsh@899eefb if you want to cherry-pick. I can turn it into a PR, but I guess it does not meet your standards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant