summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-04-15 16:49:55 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-04-15 16:49:55 +0000
commit1875c12734938595033715a948f50b05b76bca3d (patch)
tree4b4bf3e48cddd2a8d5a3b187fde6772d424dfaa2
parentfe6d34f024a20d57741b500a91649fa7032cc509 (diff)
downloadzsh-1875c12734938595033715a948f50b05b76bca3d.tar.gz
zsh-1875c12734938595033715a948f50b05b76bca3d.zip
24819: fix transposing characters and sneaky combination generation
-rw-r--r--ChangeLog7
-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
5 files changed, 139 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index c71744d5e..c6a33a680 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-04-15 Peter Stephenson <pws@csr.com>
+
+ * : Src/Zle/zle.h, Src/Zle/zle_misc.c, Src/Zle/zle_move.c,
+ Src/Zle/zle_utils.c: need to fix up combining character aligment
+ in case of sneaky combination generation; fix transposing
+ characters.
+
2008-04-14 Peter Stephenson <pws@csr.com>
* 24816: Src/Zle/zle_hist.c, Src/Zle/zle_misc.c,
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);