From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19796 invoked from network); 15 Apr 2008 16:47:10 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.4 (2008-01-01) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.4 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 15 Apr 2008 16:47:10 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 22619 invoked from network); 15 Apr 2008 16:47:03 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 15 Apr 2008 16:47:03 -0000 Received: (qmail 1630 invoked by alias); 15 Apr 2008 16:46:59 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 24819 Received: (qmail 1607 invoked from network); 15 Apr 2008 16:46:59 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 15 Apr 2008 16:46:59 -0000 Received: from cluster-g.mailcontrol.com (cluster-g.mailcontrol.com [85.115.41.190]) by bifrost.dotsrc.org (Postfix) with ESMTP id 091278043AC7 for ; Tue, 15 Apr 2008 18:46:53 +0200 (CEST) Received: from cameurexb01.EUROPE.ROOT.PRI ([62.189.241.200]) by rly05g.srv.mailcontrol.com (MailControl) with ESMTP id m3FGkfqM023891 for ; Tue, 15 Apr 2008 17:46:49 +0100 Received: from news01 ([10.103.143.38]) by cameurexb01.EUROPE.ROOT.PRI with Microsoft SMTPSVC(6.0.3790.3959); Tue, 15 Apr 2008 17:46:46 +0100 Date: Tue, 15 Apr 2008 17:46:45 +0100 From: Peter Stephenson To: "Zsh Hackers' List" Subject: Re: PATCH: (large) initial support for combining characters in ZLE. Message-ID: <20080415174645.0590d589@news01> In-Reply-To: <237967ef0804150658h1f8df5e5w422955fc6b92fe29@mail.gmail.com> References: <20080413175442.0e95a241@pws-pc> <237967ef0804140634l7e02ce6fofff7f3f3ec6c8d7c@mail.gmail.com> <20080414145425.566bcb92@news01> <237967ef0804150658h1f8df5e5w422955fc6b92fe29@mail.gmail.com> Organization: CSR X-Mailer: Claws Mail 3.3.1 (GTK+ 2.12.5; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 15 Apr 2008 16:46:46.0944 (UTC) FILETIME=[4B2EAA00:01C89F18] X-Scanned-By: MailControl A-08-00-05 (www.mailcontrol.com) on 10.71.0.115 X-Virus-Scanned: ClamAV 0.91.2/6781/Tue Apr 15 15:41:50 2008 on bifrost X-Virus-Status: Clean On Tue, 15 Apr 2008 15:58:54 +0200 "Mikael Magnusson" 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 Software Engineer CSR PLC, Churchill House, Cambridge Business Park, Cowley Road Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070