updated for version 7.2-109
diff --git a/src/edit.c b/src/edit.c
index 24f1496..b998f8d 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -7703,9 +7703,7 @@
*/
++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 */
@@ -7714,9 +7712,7 @@
add_to_showcmd_c(literally);
#endif
regname = plain_vgetc();
-#ifdef FEAT_LANGMAP
LANGMAP_ADJUST(regname, TRUE);
-#endif
}
--no_mapping;
diff --git a/src/macros.h b/src/macros.h
index f223099..afe3572 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -127,15 +127,31 @@
#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.
+ * 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.
*/
-# define LANGMAP_ADJUST(c, condition) do { \
- if (*p_langmap && (condition) && !KeyStuffed && (c) >= 0 && (c) < 256) \
- c = langmap_mapchar[c]; \
+# 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
/*
diff --git a/src/normal.c b/src/normal.c
index 30678a4..3241330 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -651,10 +651,7 @@
* Get the command character from the user.
*/
c = safe_vgetc();
-
-#ifdef FEAT_LANGMAP
LANGMAP_ADJUST(c, TRUE);
-#endif
#ifdef FEAT_VISUAL
/*
@@ -744,9 +741,7 @@
}
++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)
{
@@ -769,9 +764,7 @@
++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
@@ -959,9 +952,7 @@
* "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
@@ -1062,10 +1053,8 @@
}
#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)
@@ -4630,9 +4619,7 @@
++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
@@ -4988,9 +4975,7 @@
++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
diff --git a/src/option.c b/src/option.c
index bd12b8b..87497ea 100644
--- a/src/option.c
+++ b/src/option.c
@@ -10153,25 +10153,110 @@
#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).
+ * 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));
/*
- * 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.
+ * 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++) /* we init with a-one-to one map */
- langmap_mapchar[i] = 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,7 +10270,10 @@
char_u *p2;
int from, to;
- langmap_init(); /* back to one-to-one map first */
+#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,7 +10323,13 @@
transchar(from));
return;
}
- langmap_mapchar[from & 255] = to;
+
+#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);
diff --git a/src/proto/option.pro b/src/proto/option.pro
index bb50ef1..39ee7be 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -44,6 +44,7 @@
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));
diff --git a/src/version.c b/src/version.c
index 7a83788..f5f53a5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -677,6 +677,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 109,
+/**/
108,
/**/
107,
diff --git a/src/window.c b/src/window.c
index b360f54..2c14e50 100644
--- a/src/window.c
+++ b/src/window.c
@@ -594,9 +594,7 @@
++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