Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: PATCH: (large) initial support for combining characters in ZLE.



On Tue, 15 Apr 2008 15:58:54 +0200
"Mikael Magnusson" <mikachu@xxxxxxxxx> wrote:
> This is better, but I can still put the cursor between the a and the ~.
> >  > % zsh -f
> >  > % setopt combiningchars
> >  > % print -z $'\u0342'
> >  > the buffer should now contain an inverted <0342>, press left or ctrl-a
> >  > or whatever to go to the start of the line and press 'a'.
> But instead of pressing a, type a '!' and go left again and press 'a',
> then press ctrl-d. (or ctrl-t)

OK, so we need to fix things up right at the end after an operation in case
it generated some combinations a sneaky way.  Hence some more CCRIGHT()s.

> Another thing I noticed is that ctrl-t moves just the combining char,
> not the whole base+combiningchar, but that might already be on your
> todo as a subset of "fix widgets" :).

This should help with fixing the word stuff, when I get round to it...

I'm fed up with the names zle_misc.c and zle_utils.c.  I can never find
anything.

Index: Src/Zle/zle.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle.h,v
retrieving revision 1.37
diff -u -r1.37 zle.h
--- Src/Zle/zle.h	13 Apr 2008 16:58:42 -0000	1.37
+++ Src/Zle/zle.h	15 Apr 2008 16:42:04 -0000
@@ -75,14 +75,19 @@
 #define LASTFULLCHAR_T  ZLE_INT_T
 
 /* We may need to handle combining character alignment */
-#define CCLEFT()	alignmultiwordleft(1)
-#define CCRIGHT()	alignmultiwordright(1)
+#define CCLEFT()	alignmultiwordleft(&zlecs, 1)
+#define CCRIGHT()	alignmultiwordright(&zlecs, 1)
 /*
  * Increment or decrement the cursor position, skipping over
  * combining characters.
  */
 #define INCCS()		inccs()
 #define DECCS()		deccs()
+/*
+ * Same for any other position.
+ */
+#define INCPOS(pos)	incpos(&pos)
+#define DECPOS(pos)	decpos(&pos)
 
 #else  /* Not MULTIBYTE_SUPPORT: old single-byte code */
 
@@ -151,6 +156,11 @@
  */
 #define INCCS()		((void)(zlecs++))
 #define DECCS()		((void)(zlecs--))
+/*
+ * Same for any other position.
+ */
+#define INCPOS(pos)	((void)(pos++))
+#define DECPOS(pos)	((void)(pos--))
 
 #endif
 
Index: Src/Zle/zle_misc.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_misc.c,v
retrieving revision 1.46
diff -u -r1.46 zle_misc.c
--- Src/Zle/zle_misc.c	14 Apr 2008 14:57:54 -0000	1.46
+++ Src/Zle/zle_misc.c	15 Apr 2008 16:42:07 -0000
@@ -196,23 +196,66 @@
     return 0;
 }
 
+#ifdef MULTIBYTE_SUPPORT
+/*
+ * Transpose the chunk of the line from start to middle with
+ * that from middle to end.
+ */
+
+static void
+transpose_swap(int start, int middle, int end)
+{
+    int len1, len2;
+    ZLE_STRING_T first;
+
+    len1 = middle - start;
+    len2 = end - middle;
+
+    first = (ZLE_STRING_T)zalloc(len1 * ZLE_CHAR_SIZE);
+    ZS_memcpy(first, zleline + start, len1);
+    /* Move may be overlapping... */
+    ZS_memmove(zleline + start, zleline + middle, len2);
+    ZS_memcpy(zleline + start + len2, first, len1);
+    zfree(first, len1 * ZLE_CHAR_SIZE);
+}
+#endif
+
 /**/
 int
 gosmacstransposechars(UNUSED(char **args))
 {
-    int cc;
-
     if (zlecs < 2 || zleline[zlecs - 1] == '\n' || zleline[zlecs - 2] == '\n') {
-	if (zlecs == zlell || zleline[zlecs] == '\n' ||
-	    ((zlecs + 1 == zlell || zleline[zlecs + 1] == '\n') &&
-	     (!zlecs || zleline[zlecs - 1] == '\n'))) {
+	int twice = (zlecs == 0 || zleline[zlecs - 1] == '\n');
+
+	if (zlecs == zlell || zleline[zlecs] == '\n')
 	    return 1;
+
+	INCCS();
+	if (twice) {
+	    if (zlecs == zlell || zleline[zlecs] == '\n')
+		return 1;
+	    INCCS();
 	}
-	zlecs += (zlecs == 0 || zleline[zlecs - 1] == '\n') ? 2 : 1;
     }
-    cc = zleline[zlecs - 2];
-    zleline[zlecs - 2] = zleline[zlecs - 1];
-    zleline[zlecs - 1] = cc;
+#ifdef MULTIBYTE_SUPPORT
+    {
+	int start, middle;
+
+	middle = zlecs;
+	DECPOS(middle);
+
+	start = middle;
+	DECPOS(start);
+
+	transpose_swap(start, middle, zlecs);
+    }
+#else
+    {
+	ZLE_CHAR_T cc = zleline[zlecs - 2];
+	zleline[zlecs - 2] = zleline[zlecs - 1];
+	zleline[zlecs - 1] = cc;
+    }
+#endif
     return 0;
 }
 
@@ -220,7 +263,7 @@
 int
 transposechars(UNUSED(char **args))
 {
-    int cc, ct;
+    int ct;
     int n = zmult;
     int neg = n < 0;
 
@@ -231,26 +274,43 @@
 	    if (zlell == zlecs || zleline[zlecs] == '\n')
 		return 1;
 	    if (!neg)
-		zlecs++;
-	    ct++;
+		INCCS();
+	    INCPOS(ct);
 	}
 	if (neg) {
 	    if (zlecs && zleline[zlecs - 1] != '\n') {
-		zlecs--;
-		if (ct > 1 && zleline[ct - 2] != '\n')
-		    ct--;
+		DECCS();
+		if (ct > 1 && zleline[ct - 2] != '\n') {
+		    DECPOS(ct);
+		}
 	    }
 	} else {
 	    if (zlecs != zlell && zleline[zlecs] != '\n')
-		zlecs++;
+		INCCS();
+	}
+	if (ct == zlell || zleline[ct] == '\n') {
+	    DECPOS(ct);
 	}
-	if (ct == zlell || zleline[ct] == '\n')
-	    ct--;
 	if (ct < 1 || zleline[ct - 1] == '\n')
 	    return 1;
-	cc = zleline[ct - 1];
-	zleline[ct - 1] = zleline[ct];
-	zleline[ct] = cc;
+#ifdef MULTIBYTE_SUPPORT
+	{
+	    /*
+	     * We should keep any accents etc. on their original characters.
+	     */
+	    int start = ct, end = ct;
+	    DECPOS(start);
+	    INCPOS(end);
+
+	    transpose_swap(start, ct, end);
+	}
+#else
+	{
+	    ZLE_CHAR_T cc = zleline[ct - 1];
+	    zleline[ct - 1] = zleline[ct];
+	    zleline[ct] = cc;
+	}
+#endif
     }
     return 0;
 }
Index: Src/Zle/zle_move.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_move.c,v
retrieving revision 1.11
diff -u -r1.11 zle_move.c
--- Src/Zle/zle_move.c	13 Apr 2008 16:58:42 -0000	1.11
+++ Src/Zle/zle_move.c	15 Apr 2008 16:42:08 -0000
@@ -46,27 +46,27 @@
  */
 /**/
 int
-alignmultiwordleft(int setpos)
+alignmultiwordleft(int *pos, int setpos)
 {
-    int loccs;
+    int loccs = *pos;
 
     /* generic nothing to do test */
-    if (!isset(COMBININGCHARS) || zlecs == zlell || zlecs == 0)
+    if (!isset(COMBININGCHARS) || loccs == zlell || loccs == 0)
 	return 0;
 
     /* need to be on zero-width punctuation character */
-    if (!iswpunct(zleline[zlecs]) || wcwidth(zleline[zlecs]) != 0)
+    if (!iswpunct(zleline[loccs]) || wcwidth(zleline[loccs]) != 0)
 	 return 0;
 
     /* yes, go left */
-    loccs = zlecs - 1;
+    loccs--;
 
     for (;;) {
 	/* second test here is paranoia */
 	if (iswalnum(zleline[loccs]) && wcwidth(zleline[loccs]) > 0) {
 	    /* found start position */
 	    if (setpos)
-		zlecs = loccs;
+		*pos = loccs;
 	    return 1;
 	} else if (!iswpunct(zleline[loccs]) ||
 		   wcwidth(zleline[loccs]) != 0) {
@@ -88,30 +88,31 @@
  */
 /**/
 int
-alignmultiwordright(int setpos)
+alignmultiwordright(int *pos, int setpos)
 {
     int loccs;
 
     /*
      * Are we on a suitable character?
      */
-    if (!alignmultiwordleft(0))
+    if (!alignmultiwordleft(pos, 0))
 	return 0;
 
     /* yes, go right */
-    loccs = zlecs + 1;
+    loccs = *pos + 1;
 
     while (loccs < zlell) {
 	/* Anything other than a combining char will do here */
 	if (!iswpunct(zleline[loccs]) || wcwidth(zleline[loccs]) != 0) {
 	    if (setpos)
-		zlecs = loccs;
+		*pos = loccs;
 	    return 1;
 	}
 	loccs++;
     }
 
-    zlecs = zlell;
+    if (setpos)
+	*pos = loccs;
     return 1;
 }
 
@@ -123,7 +124,7 @@
 inccs(void)
 {
     zlecs++;
-    alignmultiwordright(1);
+    alignmultiwordright(&zlecs, 1);
 }
 
 
@@ -134,7 +135,26 @@
 deccs(void)
 {
     zlecs--;
-    alignmultiwordleft(1);
+    alignmultiwordleft(&zlecs, 1);
+}
+
+/* Same utilities for general position */
+
+/**/
+mod_export void
+incpos(int *pos)
+{
+    (*pos)++;
+    alignmultiwordright(pos, 1);
+}
+
+
+/**/
+mod_export void
+decpos(int *pos)
+{
+    (*pos)--;
+    alignmultiwordleft(pos, 1);
 }
 #endif
 
Index: Src/Zle/zle_utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_utils.c,v
retrieving revision 1.47
diff -u -r1.47 zle_utils.c
--- Src/Zle/zle_utils.c	13 Apr 2008 16:58:44 -0000	1.47
+++ Src/Zle/zle_utils.c	15 Apr 2008 16:42:12 -0000
@@ -551,6 +551,7 @@
 
     cut(i, ct, flags);
     shiftchars(i, ct);
+    CCRIGHT();
 }
 
 /**/
@@ -569,6 +570,7 @@
 
     cut(i, ct, flags);
     shiftchars(i, ct);
+    CCRIGHT();
 }
 
 /**/
@@ -588,6 +590,7 @@
 	    DECCS();
 	shiftchars(zlecs, origcs - zlecs);
     }
+    CCRIGHT();
 }
 
 /**/
@@ -603,13 +606,14 @@
     } else {
 	int origcs = zlecs;
 	int n = ct;
-	DPUTS(zlemetaline != NULL, "backdel needs CUT_RAW when metafied");
+	DPUTS(zlemetaline != NULL, "foredel needs CUT_RAW when metafied");
 	while (n--)
 	    INCCS();
 	ct = zlecs - origcs;
 	zlecs = origcs;
 	shiftchars(zlecs, ct);
     }
+    CCRIGHT();
 }
 
 /**/
@@ -634,6 +638,7 @@
 	DECCS();
     else if (zlecs > zlell)
 	zlecs = zlell;
+    CCRIGHT();
 
     if (flags & ZSL_COPY)
 	free(scp);


-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



Messages sorted by: Reverse Date, Date, Thread, Author