aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/edit.c39
-rw-r--r--src/nvim/farsi.c337
-rw-r--r--src/nvim/testdir/test_farsi.vim49
3 files changed, 240 insertions, 185 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 35bbe04ff0..cf4328fe0a 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -5241,28 +5241,27 @@ insertchar (
buf[0] = c;
i = 1;
- if (textwidth > 0)
+ if (textwidth > 0) {
virtcol = get_nolist_virtcol();
- /*
- * Stop the string when:
- * - no more chars available
- * - finding a special character (command key)
- * - buffer is full
- * - running into the 'textwidth' boundary
- * - need to check for abbreviation: A non-word char after a word-char
- */
- while ( (c = vpeekc()) != NUL
- && !ISSPECIAL(c)
- && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
- && i < INPUT_BUFLEN
- && (textwidth == 0
- || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
- && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1]))) {
+ }
+ // Stop the string when:
+ // - no more chars available
+ // - finding a special character (command key)
+ // - buffer is full
+ // - running into the 'textwidth' boundary
+ // - need to check for abbreviation: A non-word char after a word-char
+ while ((c = vpeekc()) != NUL
+ && !ISSPECIAL(c)
+ && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
+ && i < INPUT_BUFLEN
+ && !(p_fkmap && KeyTyped) // Farsi mode mapping moves cursor
+ && (textwidth == 0
+ || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
+ && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1]))) {
c = vgetc();
- if (p_hkmap && KeyTyped)
- c = hkmap(c); /* Hebrew mode mapping */
- if (p_fkmap && KeyTyped)
- c = fkmap(c); /* Farsi mode mapping */
+ if (p_hkmap && KeyTyped) {
+ c = hkmap(c); // Hebrew mode mapping
+ }
buf[i++] = c;
}
diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c
index 1053cb3ac2..5801a2d8fb 100644
--- a/src/nvim/farsi.c
+++ b/src/nvim/farsi.c
@@ -596,78 +596,83 @@ static void chg_r_to_Xor_X_(void)
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 (ascii_isdigit(c)
- || ((c == '.'
- || c == '+'
- || c == '-'
- || c == '^'
- || c == '%'
- || c == '#'
- || c == '=')
- && revins)) {
- if (!revins) {
- if (curwin->w_cursor.col) {
- if (!p_ri) {
- dec_cursor();
- }
+ if (insert_mode) {
+ if (ascii_isdigit(c)
+ || ((c == '.'
+ || c == '+'
+ || c == '-'
+ || c == '^'
+ || c == '%'
+ || c == '#'
+ || c == '=')
+ && revins)) {
+ // Numbers are entered left-to-right.
+ if (!revins) {
+ if (curwin->w_cursor.col) {
+ if (!p_ri) {
+ dec_cursor();
+ }
- chg_c_toX_orX();
- chg_l_toXor_X();
- if (!p_ri) {
- inc_cursor();
+ chg_c_toX_orX();
+ chg_l_toXor_X();
+ 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) {
- arrow_used = TRUE;
- (void)stop_arrow();
+ revins++;
+ p_ri = 1;
+ } else {
+ if (revins) {
+ // Stop entering number.
+ arrow_used = true;
+ (void)stop_arrow();
- revins = 0;
- if (curwin->w_p_rl) {
- while ((F_isdigit(gchar_cursor())
- || (gchar_cursor() == F_PERIOD
- || gchar_cursor() == F_PLUS
- || gchar_cursor() == F_MINUS
- || gchar_cursor() == F_MUL
- || gchar_cursor() == F_DIVIDE
- || gchar_cursor() == F_PERCENT
- || gchar_cursor() == F_EQUALS))
- && gchar_cursor() != NUL) {
- curwin->w_cursor.col++;
- }
- } else {
- if (curwin->w_cursor.col) {
+ revins = 0;
+ if (curwin->w_p_rl) {
while ((F_isdigit(gchar_cursor())
- || (gchar_cursor() == F_PERIOD
- || gchar_cursor() == F_PLUS
- || gchar_cursor() == F_MINUS
- || gchar_cursor() == F_MUL
- || gchar_cursor() == F_DIVIDE
- || gchar_cursor() == F_PERCENT
- || gchar_cursor() == F_EQUALS))
- && --curwin->w_cursor.col) {
+ || (gchar_cursor() == F_PERIOD
+ || gchar_cursor() == F_PLUS
+ || gchar_cursor() == F_MINUS
+ || gchar_cursor() == F_MUL
+ || gchar_cursor() == F_DIVIDE
+ || gchar_cursor() == F_PERCENT
+ || gchar_cursor() == F_EQUALS))
+ && gchar_cursor() != NUL) {
+ curwin->w_cursor.col++;
+ }
+ } else {
+ if (curwin->w_cursor.col) {
+ while ((F_isdigit(gchar_cursor())
+ || (gchar_cursor() == F_PERIOD
+ || gchar_cursor() == F_PLUS
+ || gchar_cursor() == F_MINUS
+ || gchar_cursor() == F_MUL
+ || gchar_cursor() == F_DIVIDE
+ || gchar_cursor() == F_PERCENT
+ || gchar_cursor() == F_EQUALS))
+ && --curwin->w_cursor.col) {
+ }
}
- }
- if (!F_isdigit(gchar_cursor())) {
- ++curwin->w_cursor.col;
+ if (!F_isdigit(gchar_cursor())) {
+ curwin->w_cursor.col++;
+ }
}
}
}
@@ -755,7 +760,7 @@ int fkmap(int c)
case 'Y':
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.
@@ -826,135 +831,137 @@ int fkmap(int c)
}
}
- if (!p_ri) {
- dec_cursor();
- }
+ if (insert_mode) {
+ if (!p_ri) {
+ 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((char_u)tempc));
- break;
+ 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((char_u)tempc));
+ break;
- case _AYN:
- case _AYN_:
- if (!p_ri) {
- if (!curwin->w_cursor.col) {
- put_curr_and_l_to_X(AYN);
- break;
+ case _AYN:
+ case _AYN_:
+ if (!p_ri) {
+ if (!curwin->w_cursor.col) {
+ put_curr_and_l_to_X(AYN);
+ 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 = AYN_;
- } else {
- tempc = AYN;
- }
+ if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) {
+ tempc = AYN_;
+ } else {
+ tempc = AYN;
+ }
- if (p_ri) {
- dec_cursor();
- } else {
- inc_cursor();
- }
+ if (p_ri) {
+ dec_cursor();
+ } else {
+ inc_cursor();
+ }
- put_curr_and_l_to_X((char_u)tempc);
- break;
+ put_curr_and_l_to_X((char_u)tempc);
+ break;
- case _GHAYN:
- case _GHAYN_:
+ 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((char_u)tempc);
- break;
+ put_curr_and_l_to_X((char_u)tempc);
+ break;
- case _YE:
- case _IE:
- case _YEE:
+ 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) {
+ 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((char_u)tempc);
- break;
- }
+ put_curr_and_l_to_X((char_u)tempc);
+ break;
+ }
- if (!p_ri) {
- inc_cursor();
+ if (!p_ri) {
+ inc_cursor();
+ }
}
tempc = 0;
diff --git a/src/nvim/testdir/test_farsi.vim b/src/nvim/testdir/test_farsi.vim
index e094191599..9ff2653af4 100644
--- a/src/nvim/testdir/test_farsi.vim
+++ b/src/nvim/testdir/test_farsi.vim
@@ -1,4 +1,5 @@
" Simplistic testing of Farsi mode.
+" Note: must be edited with latin1 encoding.
if !has('farsi') || has('nvim') " Not supported in Nvim. #6192
finish
@@ -82,3 +83,51 @@ 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 with spaces
+ call feedkeys("oB E F H I K L M O P Q R T U W Y ` ! @ # $ % ^ & * () - _ = + \\ | : \" . / < > ? \<Esc>", 'tx')
+ call assert_equal("¡ ô ú À ö æ ç Â [ ] ÷ ó ò ð õ ñ ¢ £  § ® ¤ ¥ ª ¬ è ¨© ­ é ½ « ë ê º » ¦  ¯ ¾ ¼ ¿ ", getline('.'))
+
+ " all non-number special chars without spaces
+ call feedkeys("oBEFHIKLMOPQRTUWY`!@#$%^&*()-_=+\\|:\"./<>?\<Esc>",'tx')
+ call assert_equal("¡ôúÀöæçÂ[]÷óòðõñ¢£§®¤¥ª¬è¨©­é½«ë꺻¦¯¾¼¿", getline('.'))
+
+ " all letter chars with spaces
+ call feedkeys("oa 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("Ñ ù Ì Î Ï á þ Æ Ã Ü ø Á à Å ü Þ Ý Ä Ë Ë Ê É Ó Ù Ð û Ø Ö Í Í Ò Ô Ô × Õ ý Ú  ß Ç È ", getline('.'))
+
+ " all letter chars without spaces
+ call feedkeys("oaAbcCdDefgGhijJklmnNopqrsStuvVwxXyzZ;\,[]\<Esc>", 'tx')
+ call assert_equal("\x8cùÌÎÏ\x9fî\x86\x83ÜøÁ\x9d\x85\x80\x9c\x9b\x84ËË\x8a\x89\x8e\x96\x8bì\x95\x90ÍÍ\x8dÔÔ\x93Õý\x97ß\x87\x88", getline('.'))
+
+ bwipe!
+endfunc
+
+func Test_command_line_farsi()
+ set allowrevins altkeymap
+
+ " letter characters with spaces
+ call feedkeys(":\"\<C-_>a 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 ; \\ , [ ]\<CR>", 'tx')
+ call assert_equal("\"\x88 Ç ß ë Ú Õ Õ × Ô Ô Ò Í Í Ö Ø û Ð Ù Ó É Ê Ë Ë Ä Ý Þ ü Å à Á ø Ü Ã Æ þ á Ï Î Ì ù Ñ", getreg(':'))
+
+ " letter characters without spaces
+ call feedkeys(":\"\<C-_>aAbcCdDefgGhijJklmnNopqrsStuvVwxXyzZ;\\,[]\<CR>", 'tx')
+ call assert_equal("\"\x88\x87ßëÚÕÕ\x93ÔÔ\x8dÍÍ\x90\x95ì\x8b\x96\x8e\x89\x8aËË\x84\x9b\x9c\x80\x85\x9dÁøÜ\x83\x86î\x9fÏÎÌù\x8c", getreg(':'))
+
+ " other characters with spaces
+ call feedkeys(":\"\<C-_>0 1 2 3 4 5 6 7 8 9 ` . ! \" $ % ^ & / () = \\ ? + - _ * : # ~ @ < > { } | B E F H I K L M O P Q R T U W Y\<CR>", 'tx')
+ call assert_equal("\"ñ õ ð ò ó ÷ ] [ Â ç æ ö À ú ô ¡ ê } { ¼ ¾ § ~ ® º è é ­ «  ¿ ë ½ ©¨ ¯ ¬ ª ¥ ¤ »  £  ¦ ¢ ¹ ¸ · ¶ µ ´ ³ ² ± °", getreg(':'))
+
+ " other characters without spaces
+ call feedkeys(":\"\<C-_>0123456789`.!\"$%^&/()=\\?+-_*:#~@<>{}|BEFHIKLMOPQRTUWY\<CR>", 'tx')
+ call assert_equal("\"ñõðòó÷][ÂçæöÀúô¡ê}{¼¾§~®ºèé­«¿ë½©¨¯¬ª¥¤»£¦¢¹¸·¶µ´³²±°", getreg(':'))
+
+ set noallowrevins noaltkeymap
+endfunc