Hi Bram!

On Di, 09 Jun 2015, Bram Moolenaar wrote:

> Christian Brabandt wrote:
> 
> > > > Bram,
> > > > There are still two open issues with langmaps. One is issue 297
> > > > (https://code.google.com/p/vim/issues/detail?id=297), the other one is
> > > > this one
> > > > (https://groups.google.com/d/msg/vim_dev/5D1WSL2gj-A/OgCBNZQEHNEJ)
> > > > 
> > > > I have checked the problem and I think the problem is, that mappings
> > > > won't be resolved after a multibyte characters have been read. This is
> > > > caused, by the fact that vgetorpeek() that resolves mappings, doesn't
> > > > know about multibyte chars, since those are only known in the higher
> > > > level vgetc() function. But after applying the langmap there, Vim
> > > > won't check, if the input needs to be resolved for mappings.
> > > > 
> > > > Therefore I changed vgetc() function to resolve langmaps after the
> > > > multibyte chars have been read correctly and once this changed the
> > > > input character and a mapping for that character exists, put that
> > > > character again into the typeahead buffer and run vgetorpeek() again.
> > > > 
> > > > Attached patch includes 2 tests, that are taken from the above issues
> > > > and demonstrate the problem.
> > > 
> > > I think this is not right.  LANGMAP_ADJUST() is already called inside
> > > vgetorpeek().  After your change it would also be called on the result.
> > 
> > Isn't that, what is happening currently anyhow? LANGMAP_ADJUST() is 
> > called inside vgetorpeek() and again in normal.c after safe_vgetc()
> 
> Hmm, it's slightly differently.  Inside vgetorpeek() LANGMAP_ADJUST() is
> only used to check for a matching mapping.  It's not used to actually
> change the returned character.  The LANGMAP_ADJUST() in normal.c does
> the actual translation.
> 
> So the problem in vgetorpeek() is that LANGMAP_ADJUST() is only applied
> to a byte, not a character.  Your change to call LANGMAP_ADJUST() in
> vgetc() does cause a double translation.  That can be avoided by
> returning the original character, but it doesn't handle multi-character
> mappings.
> 
> I don't think there is a simple solution, would need to apply
> LANGMAP_ADJUST() in vgetorpeek() on every character before checking for
> a mapping, but not actually returning the adjusted character when no
> mapping matches.

It's tricky, as one can't call vgetorpeek() recursively to receive the 
next characters. Here is a patch, that seems to work and that does not 
seem to brake the other tests. So that is good.

However, I don't know, from where to get characters from. I am not sure, 
if one needs to check the stuffbuf or other buffers to check for another 
char. Currently, this gets characters from the user and from the 
scriptfile (that I discovered from the non-working test ;))

I would appreciate some feedback especially if I need to get characters 
from other places as well or if there needs to be checked some more.

Best,
Christian
-- 
Die Zukunft der Sprache ist die Formel.
                -- C. W. Ceram (eig. Kurt W Marek)

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/getchar.c b/src/getchar.c
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1998,6 +1998,7 @@ vgetorpeek(advance)
 #endif
     int		old_wcol, old_wrow;
     int		wait_tb_len;
+    int		keylen_mb_off = 0;	/* keylen adjustment for multibyte chars */
 
     /*
      * This function doesn't work very well when called recursively.  This may
@@ -2141,14 +2142,52 @@ vgetorpeek(advance)
 			    )
 		    {
 #ifdef FEAT_LANGMAP
+			int k = 1;
+
 			if (c1 == K_SPECIAL)
 			    nolmaplen = 2;
 			else
 			{
+#ifdef FEAT_MBYTE
+			    char_u  buf[MB_MAXBYTES + 1];
+			    int	j;
+
+			    if (has_mbyte && (k = MB_BYTE2LEN_CHECK(c1)) > 1)
+			    {
+				if (typebuf.tb_len == 1)
+				{
+				    /* get some more chars */
+				    j = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len,
+				    typebuf.tb_buflen - typebuf.tb_off - typebuf.tb_len - 1,
+					0, typebuf.tb_change_cnt);
+				    typebuf.tb_len += j;
+				}
+
+				if (typebuf.tb_len > 1)
+				{
+				    buf[0] = c1;
+				    for (j=1; j < k; ++j)
+					buf[j] = typebuf.tb_buf[typebuf.tb_off + j];
+				}
+				/* need to remember, that we have to remove more bytes */
+				keylen_mb_off = k - 1;
+				k = c1;
+				c1 = (*mb_ptr2char)(buf);
+			    }
+#endif
 			    LANGMAP_ADJUST(c1, (State & INSERT) == 0);
+			    if (c1 == k)
+				keylen_mb_off = 0;
 			    nolmaplen = 0;
 			}
 #endif
+#ifdef FEAT_LANGMAP
+			if (MAP_HASH(local_State, c1) > 255)
+			{
+			    c1 = k;
+			    keylen_mb_off = 0;
+			}
+#endif
 #ifdef FEAT_LOCALMAP
 			/* First try buffer-local mappings. */
 			mp = curbuf->b_maphash[MAP_HASH(local_State, c1)];
@@ -2192,7 +2231,7 @@ vgetorpeek(advance)
 				int	c2;
 #endif
 				/* find the match length of this mapping */
-				for (mlen = 1; mlen < typebuf.tb_len; ++mlen)
+				for (mlen = 1 + keylen_mb_off; mlen < typebuf.tb_len; ++mlen)
 				{
 #ifdef FEAT_LANGMAP
 				    c2 = typebuf.tb_buf[typebuf.tb_off + mlen];
@@ -2202,7 +2241,7 @@ vgetorpeek(advance)
 					nomap = 2;
 				    else
 					LANGMAP_ADJUST(c2, TRUE);
-				    if (mp->m_keys[mlen] != c2)
+				    if (mp->m_keys[mlen - keylen_mb_off] != c2)
 #else
 				    if (mp->m_keys[mlen] !=
 					typebuf.tb_buf[typebuf.tb_off + mlen])
@@ -2229,8 +2268,8 @@ vgetorpeek(advance)
 				 * - Full match: mlen == keylen
 				 * - Partly match: mlen == typebuf.tb_len
 				 */
-				keylen = mp->m_keylen;
-				if (mlen == keylen
+				keylen = mp->m_keylen + keylen_mb_off;
+				if (mlen  == keylen
 				     || (mlen == typebuf.tb_len
 						  && typebuf.tb_len < keylen))
 				{
diff --git a/src/testdir/test_mapping.in b/src/testdir/test_mapping.in
--- a/src/testdir/test_mapping.in
+++ b/src/testdir/test_mapping.in
@@ -35,7 +35,20 @@ o+
 :nnoremap . :call feedkeys(".", "in")<cr>
 :/^a b
 0qqdw.ifooqj0@q:unmap .
-
+:" langmap doesn't work with multibyte chars, that are mapped
+:set langmap=öS
+:nnoremap S s
+/^MATCH HERE /e
+ö: 
+:" langmap needs to allow for recursive mappings issue #297
+:nunmap S
+:set langmap=
+:set langmap=öc
+:nnoremap col :.put ='Resolved langmap and mapping'<cr>
+:/^# TEST 7/
+:" Needs feedkeys, test doesn't work with öol
+:call feedkeys("öol", 't')
+:nunmap S
 
 :/^test/,$w! test.out
 :qa!
@@ -43,6 +56,13 @@ ENDTEST
 
 test starts here:
 
+# TEST 5: let feedkeys insert chars at current position in mapping
 a b c d
 a b c d
 
+# TEST 6: Apply mapping to langmapped multibyte char
+MATCH HERE Do not replace.
+
+# TEST 7: Resolved langmaps need to be checked for mappings
+
+
diff --git a/src/testdir/test_mapping.ok b/src/testdir/test_mapping.ok
--- a/src/testdir/test_mapping.ok
+++ b/src/testdir/test_mapping.ok
@@ -1,7 +1,15 @@
 test starts here:
 
+# TEST 5: let feedkeys insert chars at current position in mapping
 fooc d
 fooc d
+
+# TEST 6: Apply mapping to langmapped multibyte char
+MATCH HERE: Do not replace.
+
+# TEST 7: Resolved langmaps need to be checked for mappings
+Resolved langmap and mapping
+
 vim
 TEST2: CTRL-C |<ctrl-c>A|
 

Raspunde prin e-mail lui