From 1875c12734938595033715a948f50b05b76bca3d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 15 Apr 2008 16:49:55 +0000 Subject: 24819: fix transposing characters and sneaky combination generation --- ChangeLog | 7 ++++ Src/Zle/zle.h | 14 ++++++-- Src/Zle/zle_misc.c | 102 +++++++++++++++++++++++++++++++++++++++++----------- Src/Zle/zle_move.c | 46 +++++++++++++++++------- Src/Zle/zle_utils.c | 7 +++- 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 + + * : 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 * 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); -- cgit 1.4.1