changeset 10745:265268ea1adc v8.0.0262

patch 8.0.0262: Farsi support is barely tested commit https://github.com/vim/vim/commit/ddf662a1c86ef0b4bd0c55c5f0aa192ebd6d9a5e Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jan 29 17:59:12 2017 +0100 patch 8.0.0262: Farsi support is barely tested Problem: Farsi support is barely tested. Solution: Add more tests for Farsi. Clean up the code.
author Christian Brabandt <cb@256bit.org>
date Sun, 29 Jan 2017 18:00:05 +0100
parents f49773e0c392
children 38124880481d
files src/edit.c src/farsi.c src/testdir/test_farsi.vim src/version.c
diffstat 4 files changed, 312 insertions(+), 308 deletions(-) [+]
line wrap: on
line diff
--- a/src/edit.c
+++ b/src/edit.c
@@ -6166,6 +6166,9 @@ insertchar(
 		&& (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
 #endif
 		&& i < INPUT_BUFLEN
+# ifdef FEAT_FKMAP
+		&& !(p_fkmap && KeyTyped) /* Farsi mode mapping moves cursor */
+# endif
 		&& (textwidth == 0
 		    || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
 		&& !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1])))
@@ -6174,10 +6177,6 @@ insertchar(
 	    c = vgetc();
 	    if (p_hkmap && KeyTyped)
 		c = hkmap(c);		    /* Hebrew mode mapping */
-# ifdef FEAT_FKMAP
-	    if (p_fkmap && KeyTyped)
-		c = fkmap(c);		    /* Farsi mode mapping */
-# endif
 	    buf[i++] = c;
 #else
 	    buf[i++] = vgetc();
--- a/src/farsi.c
+++ b/src/farsi.c
@@ -15,30 +15,11 @@
 
 #if defined(FEAT_FKMAP) || defined(PROTO)
 
-static int toF_Xor_X_(int c);
-static int F_is_TyE(int c);
-static int F_is_TyC_TyD(int c);
 static int F_is_TyB_TyC_TyD(int src, int offset);
-static int toF_TyB(int c);
-static void put_curr_and_l_to_X(int c);
-static void put_and_redo(int c);
-static void chg_c_toX_orX(void);
-static void chg_c_to_X_orX_(void);
-static void chg_c_to_X_or_X(void);
-static void chg_l_to_X_orX_(void);
-static void chg_l_toXor_X(void);
-static void chg_r_to_Xor_X_(void);
-static int toF_leading(int c);
-static int toF_Rjoin(int c);
-static int canF_Ljoin(int c);
-static int canF_Rjoin(int c);
-static int F_isterm(int c);
-static int toF_ending(int c);
-static void lrswapbuf(char_u *buf, int len);
 
 /*
  * Convert the given Farsi character into a _X or _X_ type
-*/
+ */
     static int
 toF_Xor_X_(int c)
 {
@@ -105,7 +86,7 @@ toF_Xor_X_(int c)
 
 /*
  * Convert the given Farsi character into Farsi capital character.
-*/
+ */
     static int
 toF_TyA(int c)
 {
@@ -156,7 +137,7 @@ toF_TyA(int c)
  * Is the character under the cursor+offset in the given buffer a join type.
  * That is a character that is combined with the others.
  * Note: the offset is used only for command line buffer.
-*/
+ */
     static int
 F_is_TyB_TyC_TyD(int src, int offset)
 {
@@ -207,7 +188,7 @@ F_is_TyB_TyC_TyD(int src, int offset)
 
 /*
  * Is the Farsi character one of the terminating only type.
-*/
+ */
     static int
 F_is_TyE(int c)
 {
@@ -230,7 +211,7 @@ F_is_TyE(int c)
 
 /*
  * Is the Farsi character one of the none leading type.
-*/
+ */
     static int
 F_is_TyC_TyD(int c)
 {
@@ -254,7 +235,7 @@ F_is_TyC_TyD(int c)
 
 /*
  * Convert a none leading Farsi char into a leading type.
-*/
+ */
     static int
 toF_TyB(int c)
 {
@@ -275,9 +256,18 @@ toF_TyB(int c)
     return c;
 }
 
+
+    static void
+put_and_redo(int c)
+{
+    pchar_cursor(c);
+    AppendCharToRedobuff(K_BS);
+    AppendCharToRedobuff(c);
+}
+
 /*
  * Overwrite the current redo and cursor characters + left adjust.
-*/
+ */
     static void
 put_curr_and_l_to_X(int c)
 {
@@ -312,17 +302,9 @@ put_curr_and_l_to_X(int c)
     put_and_redo(c);
 }
 
-    static void
-put_and_redo(int c)
-{
-    pchar_cursor(c);
-    AppendCharToRedobuff(K_BS);
-    AppendCharToRedobuff(c);
-}
-
 /*
  * Change the char. under the cursor to a X_ or X type
-*/
+ */
     static void
 chg_c_toX_orX(void)
 {
@@ -446,8 +428,7 @@ chg_c_toX_orX(void)
 
 /*
  * Change the char. under the cursor to a _X_ or X_ type
-*/
-
+ */
     static void
 chg_c_to_X_orX_(void)
 {
@@ -498,9 +479,9 @@ chg_c_to_X_orX_(void)
 
 /*
  * Change the char. under the cursor to a _X_ or _X type
-*/
+ */
     static void
-chg_c_to_X_or_X (void)
+chg_c_to_X_or_X(void)
 {
     int	tempc;
 
@@ -529,7 +510,7 @@ chg_c_to_X_or_X (void)
 
 /*
  * Change the character left to the cursor to a _X_ or X_ type
-*/
+ */
     static void
 chg_l_to_X_orX_(void)
 {
@@ -597,10 +578,9 @@ chg_l_to_X_orX_(void)
 
 /*
  * Change the character left to the cursor to a X or _X type
-*/
-
+ */
     static void
-chg_l_toXor_X (void)
+chg_l_toXor_X(void)
 {
     int	tempc;
 
@@ -666,8 +646,7 @@ chg_l_toXor_X (void)
 
 /*
  * Change the character right to the cursor to a _X or _X_ type
-*/
-
+ */
     static void
 chg_r_to_Xor_X_(void)
 {
@@ -691,48 +670,50 @@ chg_r_to_Xor_X_(void)
 
 /*
  * Map Farsi keyboard when in fkmap mode.
-*/
-
+ */
     int
 fkmap(int c)
 {
     int		tempc;
-    static int	revins;
+    int		insert_mode = (State & INSERT);
+    static int	revins = 0;
 
     if (IS_SPECIAL(c))
 	return c;
 
-    if (VIM_ISDIGIT(c) || ((c == '.' || c == '+' || c == '-' ||
-	c == '^' || c == '%' || c == '#' || c == '=')  && revins))
+    if (insert_mode)
     {
-	if (!revins)
+	if (VIM_ISDIGIT(c) || ((c == '.' || c == '+' || c == '-' ||
+	    c == '^' || c == '%' || c == '#' || c == '=') && revins))
 	{
-	    if (curwin->w_cursor.col)
+	    /* Numbers are entered left-to-right. */
+	    if (!revins)
 	    {
-		if (!p_ri)
-		    dec_cursor();
+		if (curwin->w_cursor.col)
+		{
+		    if (!p_ri)
+			dec_cursor();
 
-		chg_c_toX_orX ();
-		chg_l_toXor_X ();
+		    chg_c_toX_orX ();
+		    chg_l_toXor_X ();
 
-		if (!p_ri)
-		    inc_cursor();
+		    if (!p_ri)
+			inc_cursor();
+		}
 	    }
-	}
 
-	arrow_used = TRUE;
-	(void)stop_arrow();
+	    arrow_used = TRUE;
+	    (void)stop_arrow();
 
-	if (!curwin->w_p_rl && revins)
-	    inc_cursor();
+	    if (!curwin->w_p_rl && revins)
+		inc_cursor();
 
-	++revins;
-	p_ri=1;
-    }
-    else
-    {
-	if (revins)
+	    ++revins;
+	    p_ri = 1;
+	}
+	else if (revins)
 	{
+	    /* Stop entering number. */
 	    arrow_used = TRUE;
 	    (void)stop_arrow();
 
@@ -773,14 +754,14 @@ fkmap(int c)
     if (!revins)
     {
 	if (curwin->w_p_rl)
-	    p_ri=0;
+	    p_ri = 0;
 	if (!curwin->w_p_rl)
-	    p_ri=1;
+	    p_ri = 1;
     }
 
-    if ((c < 0x100) && (isalpha(c) || c == '&' ||   c == '^' ||	c == ';' ||
+    if ((c < 0x100) && (isalpha(c) || c == '&' || c == '^' ||	c == ';' ||
 			    c == '\''||	c == ',' || c == '[' ||
-			    c == ']' ||	c == '{' || c == '}'	))
+			    c == ']' ||	c == '{' || c == '}'))
 	chg_r_to_Xor_X_();
 
     tempc = 0;
@@ -844,13 +825,12 @@ fkmap(int c)
 	case  NL:
 	case  TAB:
 
-	    if (p_ri && c == NL && curwin->w_cursor.col)
+	    if (p_ri && c == NL && curwin->w_cursor.col && insert_mode)
 	    {
 		/*
 		 * If the char before the cursor is _X_ or X_ do not change
 		 * the one under the cursor with X type.
-		*/
-
+		 */
 		dec_cursor();
 
 		if (F_isalpha(gchar_cursor()))
@@ -920,215 +900,219 @@ fkmap(int c)
 		}
 		break;
 	    }
-	    if (!p_ri)
-		dec_cursor();
 
-	    switch ((tempc = gchar_cursor()))
+	    if (insert_mode)
 	    {
-		case _BE:
-		case _PE:
-		case _TE:
-		case _SE:
-		case _JIM:
-		case _CHE:
-		case _HE_J:
-		case _XE:
-		case _SIN:
-		case _SHIN:
-		case _SAD:
-		case _ZAD:
-		case _FE:
-		case _GHAF:
-		case _KAF:
-		case _KAF_H:
-		case _GAF:
-		case _LAM:
-		case _MIM:
-		case _NOON:
-		case _HE:
-		case _HE_:
-		case _TA:
-		case _ZA:
-			put_curr_and_l_to_X(toF_TyA(tempc));
-			break;
-		case _AYN:
-		case _AYN_:
+		if (!p_ri)
+		    dec_cursor();
 
-			if (!p_ri)
-			    if (!curwin->w_cursor.col)
-			    {
-				put_curr_and_l_to_X(AYN);
-				break;
-			    }
-
-			if (p_ri)
-			    inc_cursor();
-			else
-			    dec_cursor();
+		switch ((tempc = gchar_cursor()))
+		{
+		    case _BE:
+		    case _PE:
+		    case _TE:
+		    case _SE:
+		    case _JIM:
+		    case _CHE:
+		    case _HE_J:
+		    case _XE:
+		    case _SIN:
+		    case _SHIN:
+		    case _SAD:
+		    case _ZAD:
+		    case _FE:
+		    case _GHAF:
+		    case _KAF:
+		    case _KAF_H:
+		    case _GAF:
+		    case _LAM:
+		    case _MIM:
+		    case _NOON:
+		    case _HE:
+		    case _HE_:
+		    case _TA:
+		    case _ZA:
+			    put_curr_and_l_to_X(toF_TyA(tempc));
+			    break;
+		    case _AYN:
+		    case _AYN_:
 
-			if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
-			    tempc = AYN_;
-			else
-			    tempc = AYN;
+			    if (!p_ri)
+				if (!curwin->w_cursor.col)
+				{
+				    put_curr_and_l_to_X(AYN);
+				    break;
+				}
 
-			if (p_ri)
-			    dec_cursor();
-			else
-			    inc_cursor();
+			    if (p_ri)
+				inc_cursor();
+			    else
+				dec_cursor();
 
-			put_curr_and_l_to_X(tempc);
+			    if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+				tempc = AYN_;
+			    else
+				tempc = AYN;
+
+			    if (p_ri)
+				dec_cursor();
+			    else
+				inc_cursor();
 
-			break;
-		case _GHAYN:
-		case _GHAYN_:
+			    put_curr_and_l_to_X(tempc);
+
+			    break;
+		    case _GHAYN:
+		    case _GHAYN_:
 
-			if (!p_ri)
-			    if (!curwin->w_cursor.col)
-			    {
-				put_curr_and_l_to_X(GHAYN);
-				break;
-			    }
+			    if (!p_ri)
+				if (!curwin->w_cursor.col)
+				{
+				    put_curr_and_l_to_X(GHAYN);
+				    break;
+				}
 
-			if (p_ri)
-			    inc_cursor();
-			else
-			    dec_cursor();
+			    if (p_ri)
+				inc_cursor();
+			    else
+				dec_cursor();
 
-			if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
-			    tempc = GHAYN_;
-			else
-			    tempc = GHAYN;
+			    if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+				tempc = GHAYN_;
+			    else
+				tempc = GHAYN;
 
-			if (p_ri)
-			    dec_cursor();
-			else
-			    inc_cursor();
+			    if (p_ri)
+				dec_cursor();
+			    else
+				inc_cursor();
 
-			put_curr_and_l_to_X(tempc);
-			break;
-		case _YE:
-		case _IE:
-		case _YEE:
-			if (!p_ri)
-			    if (!curwin->w_cursor.col)
-			    {
-				put_curr_and_l_to_X((tempc == _YE ? YE :
-					    (tempc == _IE ? IE : YEE)));
-				break;
-			    }
+			    put_curr_and_l_to_X(tempc);
+			    break;
+		    case _YE:
+		    case _IE:
+		    case _YEE:
+			    if (!p_ri)
+				if (!curwin->w_cursor.col)
+				{
+				    put_curr_and_l_to_X((tempc == _YE ? YE :
+						(tempc == _IE ? IE : YEE)));
+				    break;
+				}
 
-			if (p_ri)
-			    inc_cursor();
-			else
-			    dec_cursor();
+			    if (p_ri)
+				inc_cursor();
+			    else
+				dec_cursor();
 
-			if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
-				tempc = (tempc == _YE ? YE_ :
-				    (tempc == _IE ? IE_ : YEE_));
-			else
-				tempc = (tempc == _YE ? YE :
-				    (tempc == _IE ? IE : YEE));
+			    if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+				    tempc = (tempc == _YE ? YE_ :
+					(tempc == _IE ? IE_ : YEE_));
+			    else
+				    tempc = (tempc == _YE ? YE :
+					(tempc == _IE ? IE : YEE));
 
-			if (p_ri)
-			    dec_cursor();
-			else
-			    inc_cursor();
+			    if (p_ri)
+				dec_cursor();
+			    else
+				inc_cursor();
 
-			put_curr_and_l_to_X(tempc);
-			break;
+			    put_curr_and_l_to_X(tempc);
+			    break;
 		}
 
 		if (!p_ri)
 		    inc_cursor();
+	    }
 
-		tempc = 0;
+	    tempc = 0;
 
-		switch (c)
-		{
-		    case '0':	return FARSI_0;
-		    case '1':	return FARSI_1;
-		    case '2':	return FARSI_2;
-		    case '3':	return FARSI_3;
-		    case '4':	return FARSI_4;
-		    case '5':	return FARSI_5;
-		    case '6':	return FARSI_6;
-		    case '7':	return FARSI_7;
-		    case '8':	return FARSI_8;
-		    case '9':	return FARSI_9;
-		    case 'B':	return F_PSP;
-		    case 'E':	return JAZR_N;
-		    case 'F':	return ALEF_D_H;
-		    case 'H':	return ALEF_A;
-		    case 'I':	return TASH;
-		    case 'K':	return F_LQUOT;
-		    case 'L':	return F_RQUOT;
-		    case 'M':	return HAMZE;
-		    case 'O':	return '[';
-		    case 'P':	return ']';
-		    case 'Q':	return OO;
-		    case 'R':	return MAD_N;
-		    case 'T':	return OW;
-		    case 'U':	return MAD;
-		    case 'W':	return OW_OW;
-		    case 'Y':	return JAZR;
-		    case '`':	return F_PCN;
-		    case '!':	return F_EXCL;
-		    case '@':	return F_COMMA;
-		    case '#':	return F_DIVIDE;
-		    case '$':	return F_CURRENCY;
-		    case '%':	return F_PERCENT;
-		    case '^':	return F_MUL;
-		    case '&':	return F_BCOMMA;
-		    case '*':	return F_STAR;
-		    case '(':	return F_LPARENT;
-		    case ')':	return F_RPARENT;
-		    case '-':	return F_MINUS;
-		    case '_':	return F_UNDERLINE;
-		    case '=':	return F_EQUALS;
-		    case '+':	return F_PLUS;
-		    case '\\':	return F_BSLASH;
-		    case '|':	return F_PIPE;
-		    case ':':	return F_DCOLON;
-		    case '"':	return F_SEMICOLON;
-		    case '.':	return F_PERIOD;
-		    case '/':	return F_SLASH;
-		    case '<':	return F_LESS;
-		    case '>':	return F_GREATER;
-		    case '?':	return F_QUESTION;
-		    case ' ':	return F_BLANK;
-		}
-		break;
+	    switch (c)
+	    {
+		case '0':	return FARSI_0;
+		case '1':	return FARSI_1;
+		case '2':	return FARSI_2;
+		case '3':	return FARSI_3;
+		case '4':	return FARSI_4;
+		case '5':	return FARSI_5;
+		case '6':	return FARSI_6;
+		case '7':	return FARSI_7;
+		case '8':	return FARSI_8;
+		case '9':	return FARSI_9;
+		case 'B':	return F_PSP;
+		case 'E':	return JAZR_N;
+		case 'F':	return ALEF_D_H;
+		case 'H':	return ALEF_A;
+		case 'I':	return TASH;
+		case 'K':	return F_LQUOT;
+		case 'L':	return F_RQUOT;
+		case 'M':	return HAMZE;
+		case 'O':	return '[';
+		case 'P':	return ']';
+		case 'Q':	return OO;
+		case 'R':	return MAD_N;
+		case 'T':	return OW;
+		case 'U':	return MAD;
+		case 'W':	return OW_OW;
+		case 'Y':	return JAZR;
+		case '`':	return F_PCN;
+		case '!':	return F_EXCL;
+		case '@':	return F_COMMA;
+		case '#':	return F_DIVIDE;
+		case '$':	return F_CURRENCY;
+		case '%':	return F_PERCENT;
+		case '^':	return F_MUL;
+		case '&':	return F_BCOMMA;
+		case '*':	return F_STAR;
+		case '(':	return F_LPARENT;
+		case ')':	return F_RPARENT;
+		case '-':	return F_MINUS;
+		case '_':	return F_UNDERLINE;
+		case '=':	return F_EQUALS;
+		case '+':	return F_PLUS;
+		case '\\':	return F_BSLASH;
+		case '|':	return F_PIPE;
+		case ':':	return F_DCOLON;
+		case '"':	return F_SEMICOLON;
+		case '.':	return F_PERIOD;
+		case '/':	return F_SLASH;
+		case '<':	return F_LESS;
+		case '>':	return F_GREATER;
+		case '?':	return F_QUESTION;
+		case ' ':	return F_BLANK;
+	    }
+	    break;
 
 	case 'a':
-		tempc = _SHIN;
-		break;
+	    tempc = _SHIN;
+	    break;
 	case 'A':
-		tempc = WAW_H;
-		break;
+	    tempc = WAW_H;
+	    break;
 	case 'b':
-		tempc = ZAL;
-		break;
+	    tempc = ZAL;
+	    break;
 	case 'c':
-		tempc = ZE;
-		break;
+	    tempc = ZE;
+	    break;
 	case 'C':
-		tempc = JE;
-		break;
+	    tempc = JE;
+	    break;
 	case 'd':
-		tempc = _YE;
-		break;
+	    tempc = _YE;
+	    break;
 	case 'D':
-		tempc = _YEE;
-		break;
+	    tempc = _YEE;
+	    break;
 	case 'e':
-		tempc = _SE;
-		break;
+	    tempc = _SE;
+	    break;
 	case 'f':
-		tempc = _BE;
-		break;
+	    tempc = _BE;
+	    break;
 	case 'g':
-		tempc = _LAM;
-		break;
+	    tempc = _LAM;
+	    break;
 	case 'G':
 	    if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
 	    {
@@ -1230,7 +1214,7 @@ fkmap(int c)
 		inc_cursor();
 	    break;
 	case 'j':
-		tempc = _TE;
+	    tempc = _TE;
 	    break;
 	case 'J':
 	    if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
@@ -1260,73 +1244,73 @@ fkmap(int c)
 
 	    return tempc;
 	case 'k':
-		tempc = _NOON;
+	    tempc = _NOON;
 	    break;
 	case 'l':
-		tempc = _MIM;
+	    tempc = _MIM;
 	    break;
 	case 'm':
-		tempc = _PE;
+	    tempc = _PE;
 	    break;
 	case 'n':
 	case 'N':
-		tempc = DAL;
+	    tempc = DAL;
 	    break;
 	case 'o':
-		tempc = _XE;
+	    tempc = _XE;
 	    break;
 	case 'p':
-		tempc = _HE_J;
+	    tempc = _HE_J;
 	    break;
 	case 'q':
-		tempc = _ZAD;
+	    tempc = _ZAD;
 	    break;
 	case 'r':
-		tempc = _GHAF;
+	    tempc = _GHAF;
 	    break;
 	case 's':
-		tempc = _SIN;
+	    tempc = _SIN;
 	    break;
 	case 'S':
-		tempc = _IE;
+	    tempc = _IE;
 	    break;
 	case 't':
-		tempc = _FE;
+	    tempc = _FE;
 	    break;
 	case 'u':
-		if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
-		{
-		    if (!p_ri && !F_is_TyE(tempc))
-			chg_c_to_X_orX_ ();
-		    if (p_ri)
-			chg_c_to_X_or_X ();
+	    if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
+	    {
+		if (!p_ri && !F_is_TyE(tempc))
+		    chg_c_to_X_orX_ ();
+		if (p_ri)
+		    chg_c_to_X_or_X ();
 
-		}
+	    }
 
-		if (!p_ri && !curwin->w_cursor.col)
-		    return _AYN;
+	    if (!p_ri && !curwin->w_cursor.col)
+		return _AYN;
 
-		if (!p_ri)
-		    dec_cursor();
+	    if (!p_ri)
+		dec_cursor();
 
-		if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
-		    tempc = _AYN_;
-		else
-		    tempc = _AYN;
+	    if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
+		tempc = _AYN_;
+	    else
+		tempc = _AYN;
 
-		if (!p_ri)
-		    inc_cursor();
+	    if (!p_ri)
+		inc_cursor();
 	    break;
 	case 'v':
 	case 'V':
-		tempc = RE;
+	    tempc = RE;
 	    break;
 	case 'w':
-		tempc = _SAD;
+	    tempc = _SAD;
 	    break;
 	case 'x':
 	case 'X':
-		tempc = _TA;
+	    tempc = _TA;
 	    break;
 	case 'y':
 	    if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
@@ -1354,36 +1338,36 @@ fkmap(int c)
 
 	    break;
 	case 'z':
-		tempc = _ZA;
+	    tempc = _ZA;
 	    break;
 	case 'Z':
-		tempc = _KAF_H;
+	    tempc = _KAF_H;
 	    break;
 	case ';':
-		tempc = _KAF;
+	    tempc = _KAF;
 	    break;
 	case '\'':
-		tempc = _GAF;
+	    tempc = _GAF;
 	    break;
 	case ',':
-		tempc = WAW;
+	    tempc = WAW;
 	    break;
 	case '[':
-		tempc = _JIM;
+	    tempc = _JIM;
 	    break;
 	case ']':
-		tempc = _CHE;
+	    tempc = _CHE;
 	    break;
     }
 
-    if ((F_isalpha(tempc) || F_isdigit(tempc)))
+    if (F_isalpha(tempc) || F_isdigit(tempc))
     {
-	if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
+	if (!curwin->w_cursor.col && STRLEN(ml_get_curline()))
 	{
 	    if (!p_ri && !F_is_TyE(tempc))
-		chg_c_to_X_orX_ ();
+		chg_c_to_X_orX_();
 	    if (p_ri)
-		chg_c_to_X_or_X ();
+		chg_c_to_X_or_X();
 	}
 
 	if (curwin->w_cursor.col)
@@ -1392,9 +1376,9 @@ fkmap(int c)
 		dec_cursor();
 
 	    if (F_is_TyE(tempc))
-		chg_l_toXor_X ();
+		chg_l_toXor_X();
 	    else
-		chg_l_to_X_orX_ ();
+		chg_l_to_X_orX_();
 
 	    if (!p_ri)
 		inc_cursor();
@@ -1407,7 +1391,7 @@ fkmap(int c)
 
 /*
  * Convert a none leading Farsi char into a leading type.
-*/
+ */
     static int
 toF_leading(int c)
 {
@@ -1461,7 +1445,7 @@ toF_leading(int c)
 
 /*
  * Convert a given Farsi char into right joining type.
-*/
+ */
     static int
 toF_Rjoin(int c)
 {
@@ -1517,7 +1501,7 @@ toF_Rjoin(int c)
 
 /*
  * Can a given Farsi character join via its left edj.
-*/
+ */
     static int
 canF_Ljoin(int c)
 {
@@ -1591,7 +1575,7 @@ canF_Ljoin(int c)
 
 /*
  * Can a given Farsi character join via its right edj.
-*/
+ */
     static int
 canF_Rjoin(int c)
 {
@@ -1619,7 +1603,7 @@ canF_Rjoin(int c)
 
 /*
  * is a given Farsi character a terminating type.
-*/
+ */
     static int
 F_isterm(int c)
 {
@@ -1646,7 +1630,7 @@ F_isterm(int c)
 
 /*
  * Convert the given Farsi character into a ending type .
-*/
+ */
     static int
 toF_ending(int c)
 {
@@ -1691,7 +1675,7 @@ toF_ending(int c)
 
 /*
  * Convert the Farsi 3342 standard into Farsi VIM.
-*/
+ */
     static void
 conv_to_pvim(void)
 {
--- a/src/testdir/test_farsi.vim
+++ b/src/testdir/test_farsi.vim
@@ -1,4 +1,5 @@
 " Simplistic testing of Farsi mode.
+" Note: must be edited with latin1 encoding.
 
 if !has('farsi')
   finish
@@ -82,3 +83,21 @@ func Test_farsi_map()
   set noaltkeymap
   bwipe!
 endfunc
+
+func Test_input_farsi()
+  new
+  setlocal rightleft fkmap
+  " numbers switch input direction
+  call feedkeys("aabc0123456789.+-^%#=xyz\<Esc>", 'tx')
+  call assert_equal("\x8cÌν®¥ª­«¦¹¸·¶µ´³²±°Ô\x93Õ", getline('.'))
+
+  " all non-number special chars
+  call feedkeys("aB E F H I K L M O P Q R T U W Y ` !  @ # $ % ^ & * () - _ = + \\ | : \" .  / < > ? \<Esc>", 'tx')
+  call assert_equal("\x8cÌν®¥ª­«¦¹¸·¶µ´³²±°Ô\x93Õ¡ ô ú À ö æ ç Â [ ] ÷ ó ò ð õ ñ ¢ £  § ® ¤ ¥ ª ¬ è ¨© ­ é ½ « ë ê º » ¦  ¯ ¾ ¼ ¿ ", getline('.'))
+
+  " all letter chars
+  call feedkeys("aa A b c C d D e f g G h i j J k l m n N o p q r s S t u v V w x X y z Z ; \ , [ ] \<Esc>", 'tx')
+  call assert_equal("\x8cÌν®¥ª­«¦¹¸·¶µ´³²±°Ô\x93Õ¡ ô ú À ö æ ç Â [ ] ÷ ó ò ð õ ñ ¢ £  § ® ¤ ¥ ª ¬ è ¨© ­ é ½ « ë ê º » ¦  ¯ ¾ ¼ ¿ Ñ ù Ì Î Ï á þ Æ Ã Ü ø Á à Å ü Þ Ý Ä Ë Ë Ê É Ó Ù Ð û Ø Ö Í Í Ò Ô Ô × Õ ý Ú  ß Ç È ", getline('.'))
+
+  bwipe!
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    262,
+/**/
     261,
 /**/
     260,