To: vim-dev@vim.org Subject: Patch 7.2.109 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 7.2.109 Problem: 'langmap' does not work for multi-byte characters. Solution: Add a list of mapped multi-byte characters. (based on work by Konstantin Korikov, Agathoklis Hatzimanikas) Files: runtime/doc/options.txt, src/edit.c, src/getchar.c, src/macros.h, src/normal.c, src/option.c, src/proto/option.pro, src/window.c *** ../vim-7.2.108/runtime/doc/options.txt Fri Nov 28 10:59:57 2008 --- runtime/doc/options.txt Wed Feb 11 18:59:34 2009 *************** *** 4175,4183 **** be able to execute Normal mode commands. This is the opposite of the 'keymap' option, where characters are mapped in Insert mode. - This only works for 8-bit characters. The value of 'langmap' may be - specified with multi-byte characters (e.g., UTF-8), but only the lower - 8 bits of each character will be used. Example (for Greek, in UTF-8): *greek* > :set langmap=ΑA,ΒB,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ΝN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,ΥY,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,πp,qq,ρr,σs,τt,θu,ωv,ςw,χx,υy,ζz --- 4188,4193 ---- *** ../vim-7.2.108/src/edit.c Wed Feb 4 11:19:40 2009 --- src/edit.c Sat Feb 21 19:54:03 2009 *************** *** 7703,7711 **** */ ++no_mapping; regname = plain_vgetc(); - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(regname, TRUE); - #endif if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P) { /* Get a third key for literal register insertion */ --- 7703,7709 ---- *************** *** 7714,7722 **** add_to_showcmd_c(literally); #endif regname = plain_vgetc(); - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(regname, TRUE); - #endif } --no_mapping; --- 7712,7718 ---- *** ../vim-7.2.108/src/macros.h Wed Aug 15 20:41:07 2007 --- src/macros.h Sat Feb 21 19:55:38 2009 *************** *** 127,141 **** #ifdef FEAT_LANGMAP /* * Adjust chars in a language according to 'langmap' option. ! * NOTE that there is NO overhead if 'langmap' is not set; but even ! * when set we only have to do 2 ifs and an array lookup. * Don't apply 'langmap' if the character comes from the Stuff buffer. * The do-while is just to ignore a ';' after the macro. */ ! # define LANGMAP_ADJUST(c, condition) do { \ ! if (*p_langmap && (condition) && !KeyStuffed && (c) >= 0 && (c) < 256) \ ! c = langmap_mapchar[c]; \ } while (0) #endif /* --- 127,157 ---- #ifdef FEAT_LANGMAP /* * Adjust chars in a language according to 'langmap' option. ! * NOTE that there is no noticeable overhead if 'langmap' is not set. ! * When set the overhead for characters < 256 is small. * Don't apply 'langmap' if the character comes from the Stuff buffer. * The do-while is just to ignore a ';' after the macro. */ ! # ifdef FEAT_MBYTE ! # define LANGMAP_ADJUST(c, condition) \ ! do { \ ! if (*p_langmap && (condition) && !KeyStuffed && (c) >= 0) \ ! { \ ! if ((c) < 256) \ ! c = langmap_mapchar[c]; \ ! else \ ! c = langmap_adjust_mb(c); \ ! } \ } while (0) + # else + # define LANGMAP_ADJUST(c, condition) \ + do { \ + if (*p_langmap && (condition) && !KeyStuffed && (c) >= 0 && (c) < 256) \ + c = langmap_mapchar[c]; \ + } while (0) + # endif + #else + # define LANGMAP_ADJUST(c, condition) /* nop */ #endif /* *** ../vim-7.2.108/src/normal.c Wed Feb 4 11:45:28 2009 --- src/normal.c Sat Feb 21 19:55:17 2009 *************** *** 651,660 **** * Get the command character from the user. */ c = safe_vgetc(); - - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(c, TRUE); - #endif #ifdef FEAT_VISUAL /* --- 651,657 ---- *************** *** 744,752 **** } ++no_zero_mapping; /* don't map zero here */ c = plain_vgetc(); - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(c, TRUE); - #endif --no_zero_mapping; if (ctrl_w) { --- 741,747 ---- *************** *** 769,777 **** ++no_mapping; ++allow_keys; /* no mapping for nchar, but keys */ c = plain_vgetc(); /* get next character */ - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(c, TRUE); - #endif --no_mapping; --allow_keys; #ifdef FEAT_CMDL_INFO --- 764,770 ---- *************** *** 959,967 **** * "gr", "g'" and "g`". */ ca.nchar = plain_vgetc(); - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(ca.nchar, TRUE); - #endif #ifdef FEAT_CMDL_INFO need_flushbuf |= add_to_showcmd(ca.nchar); #endif --- 952,958 ---- *************** *** 1062,1071 **** } #endif - #ifdef FEAT_LANGMAP /* adjust chars > 127, except after "tTfFr" commands */ LANGMAP_ADJUST(*cp, !lang); - #endif #ifdef FEAT_RIGHTLEFT /* adjust Hebrew mapped char */ if (p_hkmap && lang && KeyTyped) --- 1053,1060 ---- *************** *** 4630,4638 **** ++no_mapping; ++allow_keys; /* no mapping for nchar, but allow key codes */ nchar = plain_vgetc(); - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(nchar, TRUE); - #endif --no_mapping; --allow_keys; #ifdef FEAT_CMDL_INFO --- 4619,4625 ---- *************** *** 4988,4996 **** ++no_mapping; ++allow_keys; /* no mapping for nchar, but allow key codes */ nchar = plain_vgetc(); - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(nchar, TRUE); - #endif --no_mapping; --allow_keys; #ifdef FEAT_CMDL_INFO --- 4975,4981 ---- *** ../vim-7.2.108/src/option.c Wed Feb 11 22:47:32 2009 --- src/option.c Sat Feb 21 19:46:13 2009 *************** *** 10153,10177 **** #ifdef FEAT_LANGMAP /* ! * Any character has an equivalent character. This is used for keyboards that ! * have a special language mode that sends characters above 128 (although ! * other characters can be translated too). */ /* ! * char_u langmap_mapchar[256]; ! * Normally maps each of the 128 upper chars to an <128 ascii char; used to ! * "translate" native lang chars in normal mode or some cases of ! * insert mode without having to tediously switch lang mode back&forth. */ static void langmap_init() { int i; ! for (i = 0; i < 256; i++) /* we init with a-one-to one map */ ! langmap_mapchar[i] = i; } /* --- 10153,10262 ---- #ifdef FEAT_LANGMAP /* ! * Any character has an equivalent 'langmap' character. This is used for ! * keyboards that have a special language mode that sends characters above ! * 128 (although other characters can be translated too). The "to" field is a ! * Vim command character. This avoids having to switch the keyboard back to ! * ASCII mode when leaving Insert mode. ! * ! * langmap_mapchar[] maps any of 256 chars to an ASCII char used for Vim ! * commands. ! * When FEAT_MBYTE is defined langmap_mapga.ga_data is a sorted table of ! * langmap_entry_T. This does the same as langmap_mapchar[] for characters >= ! * 256. ! */ ! # ifdef FEAT_MBYTE ! /* ! * With multi-byte support use growarray for 'langmap' chars >= 256 */ + typedef struct + { + int from; + int to; + } langmap_entry_T; + + static garray_T langmap_mapga; + static void langmap_set_entry __ARGS((int from, int to)); + + /* + * Search for an entry in "langmap_mapga" for "from". If found set the "to" + * field. If not found insert a new entry at the appropriate location. + */ + static void + langmap_set_entry(from, to) + int from; + int to; + { + langmap_entry_T *entries = (langmap_entry_T *)(langmap_mapga.ga_data); + int a = 0; + int b = langmap_mapga.ga_len; + + /* Do a binary search for an existing entry. */ + while (a != b) + { + int i = (a + b) / 2; + int d = entries[i].from - from; + + if (d == 0) + { + entries[i].to = to; + return; + } + if (d < 0) + a = i + 1; + else + b = i; + } + + if (ga_grow(&langmap_mapga, 1) != OK) + return; /* out of memory */ + + /* insert new entry at position "a" */ + entries = (langmap_entry_T *)(langmap_mapga.ga_data) + a; + mch_memmove(entries + 1, entries, + (langmap_mapga.ga_len - a) * sizeof(langmap_entry_T)); + ++langmap_mapga.ga_len; + entries[0].from = from; + entries[0].to = to; + } /* ! * Apply 'langmap' to multi-byte character "c" and return the result. */ + int + langmap_adjust_mb(c) + int c; + { + langmap_entry_T *entries = (langmap_entry_T *)(langmap_mapga.ga_data); + int a = 0; + int b = langmap_mapga.ga_len; + + while (a != b) + { + int i = (a + b) / 2; + int d = entries[i].from - c; + + if (d == 0) + return entries[i].to; /* found matching entry */ + if (d < 0) + a = i + 1; + else + b = i; + } + return c; /* no entry found, return "c" unmodified */ + } + # endif static void langmap_init() { int i; ! for (i = 0; i < 256; i++) ! langmap_mapchar[i] = i; /* we init with a one-to-one map */ ! # ifdef FEAT_MBYTE ! ga_init2(&langmap_mapga, sizeof(langmap_entry_T), 8); ! # endif } /* *************** *** 10185,10191 **** char_u *p2; int from, to; ! langmap_init(); /* back to one-to-one map first */ for (p = p_langmap; p[0] != NUL; ) { --- 10270,10279 ---- char_u *p2; int from, to; ! #ifdef FEAT_MBYTE ! ga_clear(&langmap_mapga); /* clear the previous map first */ ! #endif ! langmap_init(); /* back to one-to-one map */ for (p = p_langmap; p[0] != NUL; ) { *************** *** 10235,10241 **** transchar(from)); return; } ! langmap_mapchar[from & 255] = to; /* Advance to next pair */ mb_ptr_adv(p); --- 10323,10335 ---- transchar(from)); return; } ! ! #ifdef FEAT_MBYTE ! if (from >= 256) ! langmap_set_entry(from, to); ! else ! #endif ! langmap_mapchar[from & 255] = to; /* Advance to next pair */ mb_ptr_adv(p); *** ../vim-7.2.108/src/proto/option.pro Sat May 5 19:28:04 2007 --- src/proto/option.pro Wed Feb 11 21:21:05 2009 *************** *** 44,49 **** --- 44,50 ---- void set_context_in_set_cmd __ARGS((expand_T *xp, char_u *arg, int opt_flags)); int ExpandSettings __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file)); int ExpandOldSetting __ARGS((int *num_file, char_u ***file)); + int langmap_adjust_mb __ARGS((int c)); int has_format_option __ARGS((int x)); int shortmess __ARGS((int x)); void vimrc_found __ARGS((char_u *fname, char_u *envname)); *** ../vim-7.2.108/src/window.c Fri Nov 28 21:26:50 2008 --- src/window.c Sat Feb 21 19:55:25 2009 *************** *** 594,602 **** ++allow_keys; /* no mapping for xchar, but allow key codes */ if (xchar == NUL) xchar = plain_vgetc(); - #ifdef FEAT_LANGMAP LANGMAP_ADJUST(xchar, TRUE); - #endif --no_mapping; --allow_keys; #ifdef FEAT_CMDL_INFO --- 594,600 ---- *** ../vim-7.2.108/src/version.c Wed Feb 11 22:47:32 2009 --- src/version.c Sat Feb 21 19:34:28 2009 *************** *** 678,679 **** --- 678,681 ---- { /* Add new patch number below this line */ + /**/ + 109, /**/ -- hundred-and-one symptoms of being an internet addict: 99. The hum of a cooling fan and the click of keys is comforting to you. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ download, build and distribute -- http://www.A-A-P.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///