summary refs log tree commit diff
path: root/Src/Zle
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle')
-rw-r--r--Src/Zle/zle.h14
-rw-r--r--Src/Zle/zle_misc.c102
-rw-r--r--Src/Zle/zle_move.c46
-rw-r--r--Src/Zle/zle_utils.c7
4 files changed, 132 insertions, 37 deletions
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index 40230e784..bed5888cb 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -75,14 +75,19 @@ typedef wint_t   ZLE_INT_T;
 #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 @@ static inline int ZS_strncmp(ZLE_STRING_T s1, ZLE_STRING_T s2, size_t l)
  */
 #define INCCS()		((void)(zlecs++))
 #define DECCS()		((void)(zlecs--))
+/*
+ * Same for any other position.
+ */
+#define INCPOS(pos)	((void)(pos++))
+#define DECPOS(pos)	((void)(pos--))
 
 #endif
 
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index fb03ee149..db2d4acce 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -196,23 +196,66 @@ backwardkillline(char **args)
     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 @@ gosmacstransposechars(UNUSED(char **args))
 int
 transposechars(UNUSED(char **args))
 {
-    int cc, ct;
+    int ct;
     int n = zmult;
     int neg = n < 0;
 
@@ -231,26 +274,43 @@ transposechars(UNUSED(char **args))
 	    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;
 }
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index eef009390..4568e2696 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -46,27 +46,27 @@ static int vimarkcs[27], vimarkline[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 @@ alignmultiwordleft(int setpos)
  */
 /**/
 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 @@ mod_export void
 inccs(void)
 {
     zlecs++;
-    alignmultiwordright(1);
+    alignmultiwordright(&zlecs, 1);
 }
 
 
@@ -134,7 +135,26 @@ mod_export void
 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
 
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index cd8e2b26c..7d29bd649 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -551,6 +551,7 @@ backkill(int ct, int flags)
 
     cut(i, ct, flags);
     shiftchars(i, ct);
+    CCRIGHT();
 }
 
 /**/
@@ -569,6 +570,7 @@ forekill(int ct, int flags)
 
     cut(i, ct, flags);
     shiftchars(i, ct);
+    CCRIGHT();
 }
 
 /**/
@@ -588,6 +590,7 @@ backdel(int ct, int flags)
 	    DECCS();
 	shiftchars(zlecs, origcs - zlecs);
     }
+    CCRIGHT();
 }
 
 /**/
@@ -603,13 +606,14 @@ foredel(int ct, int flags)
     } 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 @@ setline(char *s, int flags)
 	DECCS();
     else if (zlecs > zlell)
 	zlecs = zlell;
+    CCRIGHT();
 
     if (flags & ZSL_COPY)
 	free(scp);