diff options
Diffstat (limited to '')
-rw-r--r-- | src/farsi.c | 2179 |
1 files changed, 2179 insertions, 0 deletions
diff --git a/src/farsi.c b/src/farsi.c new file mode 100644 index 0000000..48dd991 --- /dev/null +++ b/src/farsi.c @@ -0,0 +1,2179 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * farsi.c: functions for Farsi language + */ + +#include "vim.h" + +#if defined(FEAT_FKMAP) || defined(PROTO) + +static int F_is_TyB_TyC_TyD(int src, int offset); + +/* + * Convert the given Farsi character into a _X or _X_ type + */ + static int +toF_Xor_X_(int c) +{ + int tempc; + + switch (c) + { + case BE: return _BE; + case PE: return _PE; + case TE: return _TE; + case SE: return _SE; + case JIM: return _JIM; + case CHE: return _CHE; + case HE_J: return _HE_J; + case XE: return _XE; + case SIN: return _SIN; + case SHIN: return _SHIN; + case SAD: return _SAD; + case ZAD: return _ZAD; + case AYN: return _AYN; + case AYN_: return _AYN_; + case GHAYN: return _GHAYN; + case GHAYN_: return _GHAYN_; + case FE: return _FE; + case GHAF: return _GHAF; + case KAF: return _KAF; + case GAF: return _GAF; + case LAM: return _LAM; + case MIM: return _MIM; + case NOON: return _NOON; + case YE: + case YE_: return _YE; + case YEE: + case YEE_: return _YEE; + case IE: + case IE_: return _IE; + case F_HE: + tempc = _HE; + + if (p_ri && (curwin->w_cursor.col + 1 + < (colnr_T)STRLEN(ml_get_curline()))) + { + inc_cursor(); + + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = _HE_; + + dec_cursor(); + } + if (!p_ri && STRLEN(ml_get_curline())) + { + dec_cursor(); + + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = _HE_; + + inc_cursor(); + } + + return tempc; + } + return 0; +} + +/* + * Convert the given Farsi character into Farsi capital character. + */ + static int +toF_TyA(int c) +{ + switch (c) + { + case ALEF_: return ALEF; + case ALEF_U_H_: return ALEF_U_H; + case _BE: return BE; + case _PE: return PE; + case _TE: return TE; + case _SE: return SE; + case _JIM: return JIM; + case _CHE: return CHE; + case _HE_J: return HE_J; + case _XE: return XE; + case _SIN: return SIN; + case _SHIN: return SHIN; + case _SAD: return SAD; + case _ZAD: return ZAD; + case _AYN: + case AYN_: + case _AYN_: return AYN; + case _GHAYN: + case GHAYN_: + case _GHAYN_: return GHAYN; + case _FE: return FE; + case _GHAF: return GHAF; + /* I am not sure what it is !!! case _KAF_H: */ + case _KAF: return KAF; + case _GAF: return GAF; + case _LAM: return LAM; + case _MIM: return MIM; + case _NOON: return NOON; + case _YE: + case YE_: return YE; + case _YEE: + case YEE_: return YEE; + case TEE_: return TEE; + case _IE: + case IE_: return IE; + case _HE: + case _HE_: return F_HE; + } + return 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) +{ + int c; + + if (src == SRC_EDT) + c = gchar_cursor(); + else + c = cmd_gchar(AT_CURSOR+offset); + + switch (c) + { + case _LAM: + 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 _TA: + case _ZA: + case _AYN: + case _AYN_: + case _GHAYN: + case _GHAYN_: + case _FE: + case _GHAF: + case _KAF: + case _KAF_H: + case _GAF: + case _MIM: + case _NOON: + case _YE: + case _YEE: + case _IE: + case _HE_: + case _HE: + return TRUE; + } + return FALSE; +} + +/* + * Is the Farsi character one of the terminating only type. + */ + static int +F_is_TyE(int c) +{ + switch (c) + { + case ALEF_A: + case ALEF_D_H: + case DAL: + case ZAL: + case RE: + case ZE: + case JE: + case WAW: + case WAW_H: + case HAMZE: + return TRUE; + } + return FALSE; +} + +/* + * Is the Farsi character one of the none leading type. + */ + static int +F_is_TyC_TyD(int c) +{ + switch (c) + { + case ALEF_: + case ALEF_U_H_: + case _AYN_: + case AYN_: + case _GHAYN_: + case GHAYN_: + case _HE_: + case YE_: + case IE_: + case TEE_: + case YEE_: + return TRUE; + } + return FALSE; +} + +/* + * Convert a none leading Farsi char into a leading type. + */ + static int +toF_TyB(int c) +{ + switch (c) + { + case ALEF_: return ALEF; + case ALEF_U_H_: return ALEF_U_H; + case _AYN_: return _AYN; + case AYN_: return AYN; /* exception - there are many of them */ + case _GHAYN_: return _GHAYN; + case GHAYN_: return GHAYN; /* exception - there are many of them */ + case _HE_: return _HE; + case YE_: return YE; + case IE_: return IE; + case TEE_: return TEE; + case YEE_: return YEE; + } + 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) +{ + int tempc; + + if (curwin->w_p_rl && p_ri) + return; + + if ((curwin->w_cursor.col < (colnr_T)STRLEN(ml_get_curline()))) + { + if ((p_ri && curwin->w_cursor.col) || !p_ri) + { + if (p_ri) + dec_cursor(); + else + inc_cursor(); + + if (F_is_TyC_TyD((tempc = gchar_cursor()))) + { + pchar_cursor(toF_TyB(tempc)); + AppendCharToRedobuff(K_BS); + AppendCharToRedobuff(tempc); + } + + if (p_ri) + inc_cursor(); + else + dec_cursor(); + } + } + + put_and_redo(c); +} + +/* + * Change the char. under the cursor to a X_ or X type + */ + static void +chg_c_toX_orX(void) +{ + int tempc, curc; + + switch ((curc = gchar_cursor())) + { + case _BE: + tempc = BE; + break; + case _PE: + tempc = PE; + break; + case _TE: + tempc = TE; + break; + case _SE: + tempc = SE; + break; + case _JIM: + tempc = JIM; + break; + case _CHE: + tempc = CHE; + break; + case _HE_J: + tempc = HE_J; + break; + case _XE: + tempc = XE; + break; + case _SIN: + tempc = SIN; + break; + case _SHIN: + tempc = SHIN; + break; + case _SAD: + tempc = SAD; + break; + case _ZAD: + tempc = ZAD; + break; + case _FE: + tempc = FE; + break; + case _GHAF: + tempc = GHAF; + break; + case _KAF_H: + case _KAF: + tempc = KAF; + break; + case _GAF: + tempc = GAF; + break; + case _AYN: + tempc = AYN; + break; + case _AYN_: + tempc = AYN_; + break; + case _GHAYN: + tempc = GHAYN; + break; + case _GHAYN_: + tempc = GHAYN_; + break; + case _LAM: + tempc = LAM; + break; + case _MIM: + tempc = MIM; + break; + case _NOON: + tempc = NOON; + break; + case _HE: + case _HE_: + tempc = F_HE; + break; + case _YE: + case _IE: + case _YEE: + if (p_ri) + { + inc_cursor(); + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = (curc == _YE ? YE_ : + (curc == _IE ? IE_ : YEE_)); + else + tempc = (curc == _YE ? YE : + (curc == _IE ? IE : YEE)); + dec_cursor(); + } + else + { + if (curwin->w_cursor.col) + { + dec_cursor(); + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = (curc == _YE ? YE_ : + (curc == _IE ? IE_ : YEE_)); + else + tempc = (curc == _YE ? YE : + (curc == _IE ? IE : YEE)); + inc_cursor(); + } + else + tempc = (curc == _YE ? YE : + (curc == _IE ? IE : YEE)); + } + break; + default: + tempc = 0; + } + + if (tempc) + put_and_redo(tempc); +} + +/* + * Change the char. under the cursor to a _X_ or X_ type + */ + static void +chg_c_to_X_orX_(void) +{ + int tempc; + + switch (gchar_cursor()) + { + case ALEF: + tempc = ALEF_; + break; + case ALEF_U_H: + tempc = ALEF_U_H_; + break; + case _AYN: + tempc = _AYN_; + break; + case AYN: + tempc = AYN_; + break; + case _GHAYN: + tempc = _GHAYN_; + break; + case GHAYN: + tempc = GHAYN_; + break; + case _HE: + tempc = _HE_; + break; + case YE: + tempc = YE_; + break; + case IE: + tempc = IE_; + break; + case TEE: + tempc = TEE_; + break; + case YEE: + tempc = YEE_; + break; + default: + tempc = 0; + } + + if (tempc) + put_and_redo(tempc); +} + +/* + * Change the char. under the cursor to a _X_ or _X type + */ + static void +chg_c_to_X_or_X(void) +{ + int tempc; + + tempc = gchar_cursor(); + + if (curwin->w_cursor.col + 1 < (colnr_T)STRLEN(ml_get_curline())) + { + inc_cursor(); + + if ((tempc == F_HE) && (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))) + { + tempc = _HE_; + + dec_cursor(); + + put_and_redo(tempc); + return; + } + + dec_cursor(); + } + + if ((tempc = toF_Xor_X_(tempc)) != 0) + put_and_redo(tempc); +} + +/* + * Change the character left to the cursor to a _X_ or X_ type + */ + static void +chg_l_to_X_orX_(void) +{ + int tempc; + + if (curwin->w_cursor.col != 0 && + (curwin->w_cursor.col + 1 == (colnr_T)STRLEN(ml_get_curline()))) + return; + + if (!curwin->w_cursor.col && p_ri) + return; + + if (p_ri) + dec_cursor(); + else + inc_cursor(); + + switch (gchar_cursor()) + { + case ALEF: + tempc = ALEF_; + break; + case ALEF_U_H: + tempc = ALEF_U_H_; + break; + case _AYN: + tempc = _AYN_; + break; + case AYN: + tempc = AYN_; + break; + case _GHAYN: + tempc = _GHAYN_; + break; + case GHAYN: + tempc = GHAYN_; + break; + case _HE: + tempc = _HE_; + break; + case YE: + tempc = YE_; + break; + case IE: + tempc = IE_; + break; + case TEE: + tempc = TEE_; + break; + case YEE: + tempc = YEE_; + break; + default: + tempc = 0; + } + + if (tempc) + put_and_redo(tempc); + + if (p_ri) + inc_cursor(); + else + dec_cursor(); +} + +/* + * Change the character left to the cursor to a X or _X type + */ + static void +chg_l_toXor_X(void) +{ + int tempc; + + if (curwin->w_cursor.col != 0 && + (curwin->w_cursor.col + 1 == (colnr_T)STRLEN(ml_get_curline()))) + return; + + if (!curwin->w_cursor.col && p_ri) + return; + + if (p_ri) + dec_cursor(); + else + inc_cursor(); + + switch (gchar_cursor()) + { + case ALEF_: + tempc = ALEF; + break; + case ALEF_U_H_: + tempc = ALEF_U_H; + break; + case _AYN_: + tempc = _AYN; + break; + case AYN_: + tempc = AYN; + break; + case _GHAYN_: + tempc = _GHAYN; + break; + case GHAYN_: + tempc = GHAYN; + break; + case _HE_: + tempc = _HE; + break; + case YE_: + tempc = YE; + break; + case IE_: + tempc = IE; + break; + case TEE_: + tempc = TEE; + break; + case YEE_: + tempc = YEE; + break; + default: + tempc = 0; + } + + if (tempc) + put_and_redo(tempc); + + if (p_ri) + inc_cursor(); + else + dec_cursor(); +} + +/* + * Change the character right to the cursor to a _X or _X_ type + */ + static void +chg_r_to_Xor_X_(void) +{ + int tempc, c; + + if (curwin->w_cursor.col) + { + if (!p_ri) + dec_cursor(); + + tempc = gchar_cursor(); + + if ((c = toF_Xor_X_(tempc)) != 0) + put_and_redo(c); + + if (!p_ri) + inc_cursor(); + + } +} + +/* + * Map Farsi keyboard when in fkmap mode. + */ + int +fkmap(int c) +{ + int tempc; + int insert_mode = (State & INSERT); + static int revins = 0; + + if (IS_SPECIAL(c)) + return c; + + if (insert_mode) + { + if (VIM_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(); + } + } + + arrow_used = TRUE; + (void)stop_arrow(); + + if (!curwin->w_p_rl && revins) + inc_cursor(); + + ++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) + 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 (!revins) + { + if (curwin->w_p_rl) + p_ri = 0; + if (!curwin->w_p_rl) + p_ri = 1; + } + + if ((c < 0x100) && (isalpha(c) || c == '&' || c == '^' || c == ';' || + c == '\''|| c == ',' || c == '[' || + c == ']' || c == '{' || c == '}')) + chg_r_to_Xor_X_(); + + tempc = 0; + + switch (c) + { + case '`': + case ' ': + case '.': + case '!': + case '"': + case '$': + case '%': + case '^': + case '&': + case '/': + case '(': + case ')': + case '=': + case '\\': + case '?': + case '+': + case '-': + case '_': + case '*': + case ':': + case '#': + case '~': + case '@': + case '<': + case '>': + case '{': + case '}': + case '|': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'B': + case 'E': + case 'F': + case 'H': + case 'I': + case 'K': + case 'L': + case 'M': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'T': + case 'U': + case 'W': + case 'Y': + case NL: + case TAB: + + 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())) + { + inc_cursor(); + return NL; + } + + inc_cursor(); + } + + if (!p_ri && !curwin->w_cursor.col) + { + 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; + } + + 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(tempc)); + 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 (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = AYN_; + else + tempc = AYN; + + if (p_ri) + dec_cursor(); + else + inc_cursor(); + + 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) + inc_cursor(); + else + dec_cursor(); + + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = GHAYN_; + else + tempc = GHAYN; + + 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; + } + + 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 (p_ri) + dec_cursor(); + else + inc_cursor(); + + put_curr_and_l_to_X(tempc); + break; + } + + if (!p_ri) + inc_cursor(); + } + + 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; + + case 'a': + tempc = _SHIN; + break; + case 'A': + tempc = WAW_H; + break; + case 'b': + tempc = ZAL; + break; + case 'c': + tempc = ZE; + break; + case 'C': + tempc = JE; + break; + case 'd': + tempc = _YE; + break; + case 'D': + tempc = _YEE; + break; + case 'e': + tempc = _SE; + break; + case 'f': + tempc = _BE; + break; + case 'g': + tempc = _LAM; + break; + case 'G': + if (!curwin->w_cursor.col && STRLEN(ml_get_curline())) + { + + if (gchar_cursor() == _LAM) + chg_c_toX_orX (); + else if (p_ri) + chg_c_to_X_or_X (); + } + + if (!p_ri) + if (!curwin->w_cursor.col) + return ALEF_U_H; + + if (!p_ri) + dec_cursor(); + + if (gchar_cursor() == _LAM) + { + chg_c_toX_orX (); + chg_l_toXor_X (); + tempc = ALEF_U_H; + } + else if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + { + tempc = ALEF_U_H_; + chg_l_toXor_X (); + } + else + tempc = ALEF_U_H; + + if (!p_ri) + inc_cursor(); + + return tempc; + case 'h': + if (!curwin->w_cursor.col && STRLEN(ml_get_curline())) + { + if (p_ri) + chg_c_to_X_or_X (); + + } + + if (!p_ri) + if (!curwin->w_cursor.col) + return ALEF; + + if (!p_ri) + dec_cursor(); + + if (gchar_cursor() == _LAM) + { + chg_l_toXor_X(); + del_char(FALSE); + AppendCharToRedobuff(K_BS); + + if (!p_ri) + dec_cursor(); + + tempc = LA; + } + else + { + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + { + tempc = ALEF_; + chg_l_toXor_X (); + } + else + tempc = ALEF; + } + + if (!p_ri) + inc_cursor(); + + return tempc; + case 'i': + 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 _HE; + + if (!p_ri) + dec_cursor(); + + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = _HE_; + else + tempc = _HE; + + if (!p_ri) + inc_cursor(); + break; + case 'j': + tempc = _TE; + break; + case 'J': + if (!curwin->w_cursor.col && STRLEN(ml_get_curline())) + { + if (p_ri) + chg_c_to_X_or_X (); + + } + + if (!p_ri) + if (!curwin->w_cursor.col) + return TEE; + + if (!p_ri) + dec_cursor(); + + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + { + tempc = TEE_; + chg_l_toXor_X (); + } + else + tempc = TEE; + + if (!p_ri) + inc_cursor(); + + return tempc; + case 'k': + tempc = _NOON; + break; + case 'l': + tempc = _MIM; + break; + case 'm': + tempc = _PE; + break; + case 'n': + case 'N': + tempc = DAL; + break; + case 'o': + tempc = _XE; + break; + case 'p': + tempc = _HE_J; + break; + case 'q': + tempc = _ZAD; + break; + case 'r': + tempc = _GHAF; + break; + case 's': + tempc = _SIN; + break; + case 'S': + tempc = _IE; + break; + case 't': + 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 (!p_ri && !curwin->w_cursor.col) + return _AYN; + + if (!p_ri) + dec_cursor(); + + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = _AYN_; + else + tempc = _AYN; + + if (!p_ri) + inc_cursor(); + break; + case 'v': + case 'V': + tempc = RE; + break; + case 'w': + tempc = _SAD; + break; + case 'x': + case 'X': + tempc = _TA; + break; + case 'y': + 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 _GHAYN; + + if (!p_ri) + dec_cursor(); + + if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)) + tempc = _GHAYN_; + else + tempc = _GHAYN; + + if (!p_ri) + inc_cursor(); + + break; + case 'z': + tempc = _ZA; + break; + case 'Z': + tempc = _KAF_H; + break; + case ';': + tempc = _KAF; + break; + case '\'': + tempc = _GAF; + break; + case ',': + tempc = WAW; + break; + case '[': + tempc = _JIM; + break; + case ']': + tempc = _CHE; + break; + } + + if (F_isalpha(tempc) || F_isdigit(tempc)) + { + 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) + { + if (!p_ri) + dec_cursor(); + + if (F_is_TyE(tempc)) + chg_l_toXor_X(); + else + chg_l_to_X_orX_(); + + if (!p_ri) + inc_cursor(); + } + } + if (tempc) + return tempc; + return c; +} + +/* + * Convert a none leading Farsi char into a leading type. + */ + static int +toF_leading(int c) +{ + switch (c) + { + case ALEF_: return ALEF; + case ALEF_U_H_: return ALEF_U_H; + case BE: return _BE; + case PE: return _PE; + case TE: return _TE; + case SE: return _SE; + case JIM: return _JIM; + case CHE: return _CHE; + case HE_J: return _HE_J; + case XE: return _XE; + case SIN: return _SIN; + case SHIN: return _SHIN; + case SAD: return _SAD; + case ZAD: return _ZAD; + + case AYN: + case AYN_: + case _AYN_: return _AYN; + + case GHAYN: + case GHAYN_: + case _GHAYN_: return _GHAYN; + + case FE: return _FE; + case GHAF: return _GHAF; + case KAF: return _KAF; + case GAF: return _GAF; + case LAM: return _LAM; + case MIM: return _MIM; + case NOON: return _NOON; + + case _HE_: + case F_HE: return _HE; + + case YE: + case YE_: return _YE; + + case IE_: + case IE: return _IE; + + case YEE: + case YEE_: return _YEE; + } + return c; +} + +/* + * Convert a given Farsi char into right joining type. + */ + static int +toF_Rjoin(int c) +{ + switch (c) + { + case ALEF: return ALEF_; + case ALEF_U_H: return ALEF_U_H_; + case BE: return _BE; + case PE: return _PE; + case TE: return _TE; + case SE: return _SE; + case JIM: return _JIM; + case CHE: return _CHE; + case HE_J: return _HE_J; + case XE: return _XE; + case SIN: return _SIN; + case SHIN: return _SHIN; + case SAD: return _SAD; + case ZAD: return _ZAD; + + case AYN: + case AYN_: + case _AYN: return _AYN_; + + case GHAYN: + case GHAYN_: + case _GHAYN_: return _GHAYN_; + + case FE: return _FE; + case GHAF: return _GHAF; + case KAF: return _KAF; + case GAF: return _GAF; + case LAM: return _LAM; + case MIM: return _MIM; + case NOON: return _NOON; + + case _HE: + case F_HE: return _HE_; + + case YE: + case YE_: return _YE; + + case IE_: + case IE: return _IE; + + case TEE: return TEE_; + + case YEE: + case YEE_: return _YEE; + } + return c; +} + +/* + * Can a given Farsi character join via its left edj. + */ + static int +canF_Ljoin(int c) +{ + switch (c) + { + case _BE: + case BE: + case PE: + case _PE: + case TE: + case _TE: + case SE: + case _SE: + case JIM: + case _JIM: + case CHE: + case _CHE: + case HE_J: + case _HE_J: + case XE: + case _XE: + case SIN: + case _SIN: + case SHIN: + case _SHIN: + case SAD: + case _SAD: + case ZAD: + case _ZAD: + case _TA: + case _ZA: + case AYN: + case _AYN: + case _AYN_: + case AYN_: + case GHAYN: + case GHAYN_: + case _GHAYN_: + case _GHAYN: + case FE: + case _FE: + case GHAF: + case _GHAF: + case _KAF_H: + case KAF: + case _KAF: + case GAF: + case _GAF: + case LAM: + case _LAM: + case MIM: + case _MIM: + case NOON: + case _NOON: + case IE: + case _IE: + case IE_: + case YE: + case _YE: + case YE_: + case YEE: + case _YEE: + case YEE_: + case F_HE: + case _HE: + case _HE_: + return TRUE; + } + return FALSE; +} + +/* + * Can a given Farsi character join via its right edj. + */ + static int +canF_Rjoin(int c) +{ + switch (c) + { + case ALEF: + case ALEF_: + case ALEF_U_H: + case ALEF_U_H_: + case DAL: + case ZAL: + case RE: + case JE: + case ZE: + case TEE: + case TEE_: + case WAW: + case WAW_H: + return TRUE; + } + + return canF_Ljoin(c); + +} + +/* + * is a given Farsi character a terminating type. + */ + static int +F_isterm(int c) +{ + switch (c) + { + case ALEF: + case ALEF_: + case ALEF_U_H: + case ALEF_U_H_: + case DAL: + case ZAL: + case RE: + case JE: + case ZE: + case WAW: + case WAW_H: + case TEE: + case TEE_: + return TRUE; + } + + return FALSE; +} + +/* + * Convert the given Farsi character into a ending type . + */ + static int +toF_ending(int c) +{ + switch (c) + { + case _BE: return BE; + case _PE: return PE; + case _TE: return TE; + case _SE: return SE; + case _JIM: return JIM; + case _CHE: return CHE; + case _HE_J: return HE_J; + case _XE: return XE; + case _SIN: return SIN; + case _SHIN: return SHIN; + case _SAD: return SAD; + case _ZAD: return ZAD; + case _AYN: return AYN; + case _AYN_: return AYN_; + case _GHAYN: return GHAYN; + case _GHAYN_: return GHAYN_; + case _FE: return FE; + case _GHAF: return GHAF; + case _KAF_H: + case _KAF: return KAF; + case _GAF: return GAF; + case _LAM: return LAM; + case _MIM: return MIM; + case _NOON: return NOON; + case _YE: return YE_; + case YE_: return YE; + case _YEE: return YEE_; + case YEE_: return YEE; + case TEE: return TEE_; + case _IE: return IE_; + case IE_: return IE; + case _HE: + case _HE_: return F_HE; + } + return c; +} + +/* + * Convert the Farsi 3342 standard into Farsi VIM. + */ + static void +conv_to_pvim(void) +{ + char_u *ptr; + int lnum, llen, i; + + for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) + { + ptr = ml_get((linenr_T)lnum); + + llen = (int)STRLEN(ptr); + + for (i = 0; i < llen-1; i++) + { + if (canF_Ljoin(ptr[i]) && canF_Rjoin(ptr[i+1])) + { + ptr[i] = toF_leading(ptr[i]); + ++i; + + while (i < llen && canF_Rjoin(ptr[i])) + { + ptr[i] = toF_Rjoin(ptr[i]); + if (F_isterm(ptr[i]) || !F_isalpha(ptr[i])) + break; + ++i; + } + if (!F_isalpha(ptr[i]) || !canF_Rjoin(ptr[i])) + ptr[i-1] = toF_ending(ptr[i-1]); + } + else + ptr[i] = toF_TyA(ptr[i]); + } + } + + /* + * Following lines contains Farsi encoded character. + */ + + do_cmdline_cmd((char_u *)"%s/\202\231/\232/ge"); + do_cmdline_cmd((char_u *)"%s/\201\231/\370\334/ge"); + + /* Assume the screen has been messed up: clear it and redraw. */ + redraw_later(CLEAR); + msg_attr(farsi_text_1, HL_ATTR(HLF_S)); +} + +/* + * Convert the Farsi VIM into Farsi 3342 standard. + */ + static void +conv_to_pstd(void) +{ + char_u *ptr; + int lnum, llen, i; + + /* + * Following line contains Farsi encoded character. + */ + do_cmdline_cmd((char_u *)"%s/\232/\202\231/ge"); + + for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) + { + ptr = ml_get((linenr_T)lnum); + llen = (int)STRLEN(ptr); + + for (i = 0; i < llen; i++) + ptr[i] = toF_TyA(ptr[i]); + } + + /* Assume the screen has been messed up: clear it and redraw. */ + redraw_later(CLEAR); + msg_attr(farsi_text_2, HL_ATTR(HLF_S)); +} + +/* + * left-right swap the characters in buf[len]. + */ + static void +lrswapbuf(char_u *buf, int len) +{ + char_u *s, *e; + int c; + + s = buf; + e = buf + len - 1; + + while (e > s) + { + c = *s; + *s = *e; + *e = c; + ++s; + --e; + } +} + +/* + * swap all the characters in reverse direction + */ + char_u * +lrswap(char_u *ibuf) +{ + if (ibuf != NULL && *ibuf != NUL) + lrswapbuf(ibuf, (int)STRLEN(ibuf)); + return ibuf; +} + +/* + * swap all the Farsi characters in reverse direction + */ + char_u * +lrFswap(char_u *cmdbuf, int len) +{ + int i, cnt; + + if (cmdbuf == NULL) + return cmdbuf; + + if (len == 0 && (len = (int)STRLEN(cmdbuf)) == 0) + return cmdbuf; + + for (i = 0; i < len; i++) + { + for (cnt = 0; i + cnt < len + && (F_isalpha(cmdbuf[i + cnt]) + || F_isdigit(cmdbuf[i + cnt]) + || cmdbuf[i + cnt] == ' '); ++cnt) + ; + + lrswapbuf(cmdbuf + i, cnt); + i += cnt; + } + return cmdbuf; +} + +/* + * Reverse the characters in the search path and substitute section + * accordingly. + * TODO: handle different separator characters. Use skip_regexp(). + */ + char_u * +lrF_sub(char_u *ibuf) +{ + char_u *p, *ep; + int i, cnt; + + p = ibuf; + + /* Find the boundary of the search path */ + while (((p = vim_strchr(p + 1, '/')) != NULL) && p[-1] == '\\') + ; + + if (p == NULL) + return ibuf; + + /* Reverse the Farsi characters in the search path. */ + lrFswap(ibuf, (int)(p-ibuf)); + + /* Now find the boundary of the substitute section */ + if ((ep = (char_u *)strrchr((char *)++p, '/')) != NULL) + cnt = (int)(ep - p); + else + cnt = (int)STRLEN(p); + + /* Reverse the characters in the substitute section and take care of '\' */ + for (i = 0; i < cnt-1; i++) + if (p[i] == '\\') + { + p[i] = p[i+1] ; + p[++i] = '\\'; + } + + lrswapbuf(p, cnt); + + return ibuf; +} + +/* + * Map Farsi keyboard when in cmd_fkmap mode. + */ + int +cmdl_fkmap(int c) +{ + int tempc; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '`': + case ' ': + case '.': + case '!': + case '"': + case '$': + case '%': + case '^': + case '&': + case '/': + case '(': + case ')': + case '=': + case '\\': + case '?': + case '+': + case '-': + case '_': + case '*': + case ':': + case '#': + case '~': + case '@': + case '<': + case '>': + case '{': + case '}': + case '|': + case 'B': + case 'E': + case 'F': + case 'H': + case 'I': + case 'K': + case 'L': + case 'M': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'T': + case 'U': + case 'W': + case 'Y': + case NL: + case TAB: + + switch ((tempc = cmd_gchar(AT_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 _AYN: + case _GHAYN: + case _FE: + case _GHAF: + case _KAF: + case _GAF: + case _LAM: + case _MIM: + case _NOON: + case _HE: + case _HE_: + cmd_pchar(toF_TyA(tempc), AT_CURSOR); + break; + case _AYN_: + cmd_pchar(AYN_, AT_CURSOR); + break; + case _GHAYN_: + cmd_pchar(GHAYN_, AT_CURSOR); + break; + case _IE: + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1)) + cmd_pchar(IE_, AT_CURSOR); + else + cmd_pchar(IE, AT_CURSOR); + break; + case _YEE: + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1)) + cmd_pchar(YEE_, AT_CURSOR); + else + cmd_pchar(YEE, AT_CURSOR); + break; + case _YE: + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1)) + cmd_pchar(YE_, AT_CURSOR); + else + cmd_pchar(YE, AT_CURSOR); + } + + 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': return _SHIN; + case 'A': return WAW_H; + case 'b': return ZAL; + case 'c': return ZE; + case 'C': return JE; + case 'd': return _YE; + case 'D': return _YEE; + case 'e': return _SE; + case 'f': return _BE; + case 'g': return _LAM; + case 'G': + if (cmd_gchar(AT_CURSOR) == _LAM) + { + cmd_pchar(LAM, AT_CURSOR); + return ALEF_U_H; + } + + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR)) + return ALEF_U_H_; + else + return ALEF_U_H; + case 'h': + if (cmd_gchar(AT_CURSOR) == _LAM) + { + cmd_pchar(LA, AT_CURSOR); + redrawcmdline(); + return K_IGNORE; + } + + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR)) + return ALEF_; + else + return ALEF; + case 'i': + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR)) + return _HE_; + else + return _HE; + case 'j': return _TE; + case 'J': + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR)) + return TEE_; + else + return TEE; + case 'k': return _NOON; + case 'l': return _MIM; + case 'm': return _PE; + case 'n': + case 'N': return DAL; + case 'o': return _XE; + case 'p': return _HE_J; + case 'q': return _ZAD; + case 'r': return _GHAF; + case 's': return _SIN; + case 'S': return _IE; + case 't': return _FE; + case 'u': + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR)) + return _AYN_; + else + return _AYN; + case 'v': + case 'V': return RE; + case 'w': return _SAD; + case 'x': + case 'X': return _TA; + case 'y': + if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR)) + return _GHAYN_; + else + return _GHAYN; + case 'z': + case 'Z': return _ZA; + case ';': return _KAF; + case '\'': return _GAF; + case ',': return WAW; + case '[': return _JIM; + case ']': return _CHE; + } + + return c; +} + +/* + * F_isalpha returns TRUE if 'c' is a Farsi alphabet + */ + int +F_isalpha(int c) +{ + return ((c >= TEE_ && c <= _YE) + || (c >= ALEF_A && c <= YE) + || (c >= _IE && c <= YE_)); +} + +/* + * F_isdigit returns TRUE if 'c' is a Farsi digit + */ + int +F_isdigit(int c) +{ + return (c >= FARSI_0 && c <= FARSI_9); +} + +/* + * F_ischar returns TRUE if 'c' is a Farsi character. + */ + int +F_ischar(int c) +{ + return (c >= TEE_ && c <= YE_); +} + + void +farsi_f8(cmdarg_T *cap UNUSED) +{ + if (p_altkeymap) + { + if (curwin->w_farsi & W_R_L) + { + p_fkmap = 0; + do_cmdline_cmd((char_u *)"set norl"); + msg(""); + } + else + { + p_fkmap = 1; + do_cmdline_cmd((char_u *)"set rl"); + msg(""); + } + + curwin->w_farsi = curwin->w_farsi ^ W_R_L; + } +} + + void +farsi_f9(cmdarg_T *cap UNUSED) +{ + if (p_altkeymap && curwin->w_p_rl) + { + curwin->w_farsi = curwin->w_farsi ^ W_CONV; + if (curwin->w_farsi & W_CONV) + conv_to_pvim(); + else + conv_to_pstd(); + } +} + +#endif /* FEAT_FKMAP */ |