updated for version 7.3.284
Problem:    The str2special() function doesn't handle multi-byte characters
            properly.
Solution:   Recognize multi-byte characters. (partly by Vladimir Vichniakov)
diff --git a/src/getchar.c b/src/getchar.c
index 697eb31..16bf65a 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -3964,7 +3964,17 @@
     if (*mp->m_str == NUL)
 	msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
     else
-	msg_outtrans_special(mp->m_str, FALSE);
+    {
+	/* Remove escaping of CSI, because "m_str" is in a format to be used
+	 * as typeahead. */
+	char_u *s = vim_strsave(mp->m_str);
+	if (s != NULL)
+	{
+	    vim_unescape_csi(s);
+	    msg_outtrans_special(s, FALSE);
+	    vim_free(s);
+	}
+    }
 #ifdef FEAT_EVAL
     if (p_verbose > 0)
 	last_set_msg(mp->m_script_ID);
diff --git a/src/message.c b/src/message.c
index 89248b4..76bf69d 100644
--- a/src/message.c
+++ b/src/message.c
@@ -1547,16 +1547,27 @@
 	if (IS_SPECIAL(c) || modifiers)	/* special key */
 	    special = TRUE;
     }
-    *sp = str + 1;
 
 #ifdef FEAT_MBYTE
-    /* For multi-byte characters check for an illegal byte. */
-    if (has_mbyte && MB_BYTE2LEN(*str) > (*mb_ptr2len)(str))
+    if (has_mbyte && !IS_SPECIAL(c))
     {
-	transchar_nonprint(buf, c);
-	return buf;
+        int len = (*mb_ptr2len)(str);
+
+	/* For multi-byte characters check for an illegal byte. */
+	if (has_mbyte && MB_BYTE2LEN(*str) > len)
+	{
+	    transchar_nonprint(buf, c);
+	    *sp = str + 1;
+	    return buf;
+	}
+        /* Since 'special' is TRUE the multi-byte character 'c' will be
+         * processed by get_special_key_name() */
+        c = (*mb_ptr2char)(str);
+        *sp = str + len;
     }
+    else
 #endif
+	*sp = str + 1;
 
     /* Make unprintable characters in <> form, also <M-Space> and <Tab>.
      * Use <Space> only for lhs of a mapping. */
diff --git a/src/misc2.c b/src/misc2.c
index f91a64a..dbcd653 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -2754,6 +2754,7 @@
     int		bit;
     int		key;
     unsigned long n;
+    int		l;
 
     src = *srcp;
     if (src[0] != '<')
@@ -2766,8 +2767,17 @@
 	if (*bp == '-')
 	{
 	    last_dash = bp;
-	    if (bp[1] != NUL && bp[2] == '>')
-		++bp;	/* anything accepted, like <C-?> */
+	    if (bp[1] != NUL)
+	    {
+#ifdef FEAT_MBYTE
+		if (has_mbyte)
+		    l = mb_ptr2len(bp + 1);
+		else
+#endif
+		    l = 1;
+		if (bp[l + 1] == '>')
+		    bp += l;	/* anything accepted, like <C-?> */
+	    }
 	}
 	if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
 	    bp += 3;	/* skip t_xx, xx may be '-' or '>' */
@@ -2777,15 +2787,6 @@
     {
 	end_of_name = bp + 1;
 
-	if (STRNICMP(src + 1, "char-", 5) == 0 && VIM_ISDIGIT(src[6]))
-	{
-	    /* <Char-123> or <Char-033> or <Char-0x33> */
-	    vim_str2nr(src + 6, NULL, NULL, TRUE, TRUE, NULL, &n);
-	    *modp = 0;
-	    *srcp = end_of_name;
-	    return (int)n;
-	}
-
 	/* Which modifiers are given? */
 	modifiers = 0x0;
 	for (bp = src + 1; bp < last_dash; bp++)
@@ -2804,11 +2805,27 @@
 	 */
 	if (bp >= last_dash)
 	{
+	    if (STRNICMP(last_dash + 1, "char-", 5) == 0
+						 && VIM_ISDIGIT(last_dash[6]))
+	    {
+		/* <Char-123> or <Char-033> or <Char-0x33> */
+		vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n);
+		*modp = modifiers;
+		*srcp = end_of_name;
+		return (int)n;
+	    }
+
 	    /*
 	     * Modifier with single letter, or special key name.
 	     */
-	    if (modifiers != 0 && last_dash[2] == '>')
-		key = last_dash[1];
+#ifdef FEAT_MBYTE
+	    if (has_mbyte)
+		l = mb_ptr2len(last_dash + 1);
+	    else
+#endif
+		l = 1;
+	    if (modifiers != 0 && last_dash[l + 1] == '>')
+		key = PTR2CHAR(last_dash + 1);
 	    else
 	    {
 		key = get_special_key_code(last_dash + 1);
diff --git a/src/version.c b/src/version.c
index b5fe5aa..650e99f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -710,6 +710,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    284,
+/**/
     283,
 /**/
     282,