www.pudn.com > vim53src.zip > farsi.c


/* vi:set ts=8 sts=4 sw=4: 
 * 
 * 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. 
 */ 
 
/* 
 * farsi.c: functions for Farsi language 
 * 
 * Included by main.c, when FKMAP is defined. 
 */ 
 
static int toF_Xor_X_ __ARGS((int c)); 
static int F_is_TyE __ARGS((int c)); 
static int F_is_TyC_TyD __ARGS((int c)); 
static int F_is_TyB_TyC_TyD __ARGS((int src, int offset)); 
static int toF_TyB __ARGS((int c)); 
static void put_curr_and_l_to_X __ARGS((int c)); 
static void put_and_redo __ARGS((int c)); 
static void chg_c_toX_orX __ARGS((void)); 
static void chg_c_to_X_orX_ __ARGS((void)); 
static void chg_c_to_X_or_X __ARGS((void)); 
static void chg_l_to_X_orX_ __ARGS((void)); 
static void chg_l_toXor_X __ARGS((void)); 
static void chg_r_to_Xor_X_ __ARGS((void)); 
static int toF_leading __ARGS((int c)); 
static int toF_Rjoin __ARGS((int c)); 
static int canF_Ljoin __ARGS((int c)); 
static int canF_Rjoin __ARGS((int c)); 
static int F_isterm __ARGS((int c)); 
static int toF_ending __ARGS((int c)); 
static void lrswapbuf __ARGS((char_u *buf, int len)); 
 
/* 
** Convert the given Farsi character into a _X or _X_ type 
*/ 
    static int 
toF_Xor_X_(c) 
    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 < 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 . 
*/ 
    int 
toF_TyA(c) 
    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(src, offset) 
    int	    src,    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(c) 
    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(c) 
    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(c) 
    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; 
} 
 
/* 
** Overwrite the current redo and cursor characters + left adjust 
*/ 
    static void 
put_curr_and_l_to_X(c) 
    int		  c; 
{ 
    int	tempc; 
 
    if (curwin->w_p_rl && p_ri) 
	return; 
 
    if ( (curwin->w_cursor.col < 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); 
} 
 
    static void 
put_and_redo(c) 
    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() 
{ 
    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_() 
{ 
    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 () 
{ 
    int	tempc; 
 
    tempc = gchar_cursor(); 
 
    if (curwin->w_cursor.col+1 < 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))) 
	put_and_redo(tempc); 
} 
 
/* 
** Change the character left to the cursor to a _X_ or X_ type 
*/ 
    static void 
chg_l_to_X_orX_ () 
{ 
    int	tempc; 
 
    if (!curwin->w_cursor.col && 
	(curwin->w_cursor.col+1 == 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 charcter left to the cursor to a X or _X type 
*/ 
 
    static void 
chg_l_toXor_X () 
{ 
    int	tempc; 
 
    if (!curwin->w_cursor.col && 
	(curwin->w_cursor.col+1 == 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 charcter right to the cursor to a _X or _X_ type 
*/ 
 
    static void 
chg_r_to_Xor_X_() 
{ 
int tempc, c; 
 
    if (curwin->w_cursor.col) 
    { 
	if (!p_ri) 
	    dec_cursor(); 
 
	tempc = gchar_cursor(); 
 
	if ((c = toF_Xor_X_(tempc))) 
	    put_and_redo(c); 
 
	if (!p_ri) 
	    inc_cursor(); 
 
    } 
} 
 
/* 
** Map Farsi keyboard when in fkmap mode. 
*/ 
 
    int 
fkmap(c) 
    int c; 
{ 
    int		tempc; 
    static int	revins; 
 
    if (vim_isdigit(c) || ((c == '.' || c == '+' || c == '-' || 
	c == '^' || c == '%' || c == '#' || c == '=')  && revins)) 
    { 
	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; 
	stop_arrow(); 
 
	if (!curwin->w_p_rl && revins) 
	    inc_cursor(); 
 
	++revins; 
	p_ri=1; 
    } 
    else 
    { 
	if (revins) 
	{ 
	    arrow_used = TRUE; 
	    stop_arrow(); 
 
	    revins=0; 
	    tempc = gchar_cursor(); 
	    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) 
	    { 
		/* 
		** 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) 
	    if (!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 (!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(c) 
    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(c) 
    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(c) 
    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(c) 
    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(c) 
    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(c) 
    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. 
*/ 
    void 
conv_to_pvim() 
{ 
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 = 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(canF_Rjoin(ptr[i]) && (i < llen)) 
		{ 
		    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((char_u *)"%s/\202\231/\232/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE); 
    do_cmdline((char_u *)"%s/\201\231/\370\334/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE); 
 
    update_screen(CLEAR); 
    MSG_ATTR(farsi_text_1, hl_attr(HLF_S)); 
} 
 
/* 
** Convert the Farsi VIM into Farsi 3342 standad. 
*/ 
    void 
conv_to_pstd() 
{ 
char_u *ptr; 
int lnum, llen, i; 
 
    /* 
    ** Following line contains Farsi encoded character. 
    */ 
 
    do_cmdline((char_u *)"%s/\232/\202\231/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE); 
 
    for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) 
    { 
	ptr = ml_get((linenr_t)lnum); 
 
	llen = STRLEN(ptr); 
 
	for ( i = 0; i < llen; i++) 
	{ 
	    ptr[i] = toF_TyA(ptr[i]); 
 
	} 
    } 
 
    update_screen(CLEAR); 
    MSG_ATTR(farsi_text_2, hl_attr(HLF_S)); 
} 
 
/* 
 * left-right swap the characters in buf[len]. 
 */ 
    static void 
lrswapbuf(buf, len) 
    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(ibuf) 
    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(cmdbuf, len) 
    char_u	*cmdbuf; 
    int		len; 
{ 
    int		i, cnt; 
 
    if (cmdbuf == NULL) 
	return cmdbuf; 
 
    if (len == 0 && (len = 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 seach path and substitude section accordingly 
 */ 
    char_u * 
lrF_sub(ibuf) 
    char_u	*ibuf; 
{ 
    char_u	*p, *ep; 
    int		i, cnt; 
 
    p = ibuf; 
 
    /* Find the boundry of the search path */ 
    while ((p = vim_strchr(++p, '/')) && p[-1] == '\\') 
	; 
 
    if (p == NULL) 
	return ibuf; 
 
    /* Reverse the Farsi characters in the search path. */ 
    lrFswap(ibuf, (int)(p-ibuf)); 
 
    /* Now find the boundry of the substitute section */ 
    if ((ep = (char_u *)strrchr((char *)++p, '/'))) 
	cnt = ep - p; 
    else 
	cnt = 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(c) 
    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(c) 
    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(c) 
    int	    c; 
{ 
    return (( c >= FARSI_0 && c <= FARSI_9 )); 
} 
 
/* 
 * F_ischar returns TRUE if 'c' is a Farsi character. 
 */ 
    int 
F_ischar(c) 
    int	    c; 
{ 
    return (( c >= TEE_ && c <= YE_)); 
} 
 
    void 
farsi_fkey(c) 
    int	    c; 
{ 
    if (c == K_F8) 
    { 
	if (p_altkeymap) 
	{ 
	    if (curwin->w_p_pers & W_R_L) 
	    { 
		p_fkmap=0; 
		do_cmdline((char_u *)"set norl", NULL, NULL, DOCMD_NOWAIT); 
		MSG(""); 
	    } 
	    else 
	    { 
		p_fkmap=1; 
		do_cmdline((char_u *)"set rl", NULL, NULL, DOCMD_NOWAIT); 
		MSG(""); 
	    } 
 
	    curwin->w_p_pers = curwin->w_p_pers ^ W_R_L; 
	} 
    } 
 
    if (c == K_F9) 
    { 
	if (p_altkeymap && curwin->w_p_rl) 
	{ 
	    curwin->w_p_pers = curwin->w_p_pers ^ W_CONV; 
	    if (curwin->w_p_pers & W_CONV) 
		conv_to_pvim(); 
	    else 
		conv_to_pstd(); 
	} 
    } 
}