farsi.c
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:39k
源码类别:

编辑器/阅读器

开发平台:

DOS

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8. /*
  9.  * farsi.c: functions for Farsi language
  10.  *
  11.  * Included by main.c, when FKMAP is defined.
  12.  */
  13. static int toF_Xor_X_ __ARGS((int c));
  14. static int F_is_TyE __ARGS((int c));
  15. static int F_is_TyC_TyD __ARGS((int c));
  16. static int F_is_TyB_TyC_TyD __ARGS((int src, int offset));
  17. static int toF_TyB __ARGS((int c));
  18. static void put_curr_and_l_to_X __ARGS((int c));
  19. static void put_and_redo __ARGS((int c));
  20. static void chg_c_toX_orX __ARGS((void));
  21. static void chg_c_to_X_orX_ __ARGS((void));
  22. static void chg_c_to_X_or_X __ARGS((void));
  23. static void chg_l_to_X_orX_ __ARGS((void));
  24. static void chg_l_toXor_X __ARGS((void));
  25. static void chg_r_to_Xor_X_ __ARGS((void));
  26. static int toF_leading __ARGS((int c));
  27. static int toF_Rjoin __ARGS((int c));
  28. static int canF_Ljoin __ARGS((int c));
  29. static int canF_Rjoin __ARGS((int c));
  30. static int F_isterm __ARGS((int c));
  31. static int toF_ending __ARGS((int c));
  32. static void lrswapbuf __ARGS((char_u *buf, int len));
  33. /*
  34. ** Convert the given Farsi character into a _X or _X_ type
  35. */
  36.     static int
  37. toF_Xor_X_(c)
  38.     int c;
  39. {
  40.     int tempc;
  41.     switch (c)
  42.     {
  43. case BE:
  44. return _BE;
  45. case PE:
  46. return _PE;
  47. case TE:
  48. return _TE;
  49. case SE:
  50. return _SE;
  51. case JIM:
  52. return _JIM;
  53. case CHE:
  54. return _CHE;
  55. case HE_J:
  56. return _HE_J;
  57. case XE:
  58. return _XE;
  59. case SIN:
  60. return _SIN;
  61. case SHIN:
  62. return _SHIN;
  63. case SAD:
  64. return _SAD;
  65. case ZAD:
  66. return _ZAD;
  67. case AYN:
  68. return _AYN;
  69. case AYN_:
  70. return _AYN_;
  71. case GHAYN:
  72. return _GHAYN;
  73. case GHAYN_:
  74. return _GHAYN_;
  75. case FE:
  76. return _FE;
  77. case GHAF:
  78. return _GHAF;
  79. case KAF:
  80. return _KAF;
  81. case GAF:
  82. return _GAF;
  83. case LAM:
  84. return _LAM;
  85. case MIM:
  86. return _MIM;
  87. case NOON:
  88. return _NOON;
  89. case YE:
  90. case YE_:
  91. return _YE;
  92. case YEE:
  93. case YEE_:
  94. return _YEE;
  95. case IE:
  96. case IE_:
  97. return _IE;
  98. case F_HE:
  99. tempc = _HE;
  100. if (p_ri && (curwin->w_cursor.col+1 < STRLEN(ml_get_curline())))
  101. {
  102.     inc_cursor();
  103.     if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  104. tempc = _HE_;
  105.     dec_cursor();
  106. }
  107. if (!p_ri && STRLEN(ml_get_curline()))
  108. {
  109.     dec_cursor();
  110.     if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  111. tempc = _HE_;
  112.     inc_cursor();
  113. }
  114. return tempc;
  115.     }
  116.     return 0;
  117. }
  118. /*
  119. ** Convert the given Farsi character into Farsi capital character .
  120. */
  121.     int
  122. toF_TyA(c)
  123.     int c ;
  124. {
  125.     switch (c)
  126.     {
  127. case ALEF_:
  128. return ALEF;
  129. case ALEF_U_H_:
  130. return ALEF_U_H;
  131. case _BE:
  132. return BE;
  133. case _PE:
  134. return PE;
  135. case _TE:
  136. return TE;
  137. case _SE:
  138. return SE;
  139. case _JIM:
  140. return JIM;
  141. case _CHE:
  142. return CHE;
  143. case _HE_J:
  144. return HE_J;
  145. case _XE:
  146. return XE;
  147. case _SIN:
  148. return SIN;
  149. case _SHIN:
  150. return SHIN;
  151. case _SAD:
  152. return SAD;
  153. case _ZAD:
  154. return ZAD;
  155. case _AYN:
  156. case AYN_:
  157. case _AYN_:
  158. return AYN;
  159. case _GHAYN:
  160. case GHAYN_:
  161. case _GHAYN_:
  162. return GHAYN;
  163. case _FE:
  164. return FE;
  165. case _GHAF:
  166. return GHAF;
  167. /* I am not sure what it is !!!     case _KAF_H: */
  168. case _KAF:
  169. return KAF;
  170. case _GAF:
  171. return GAF;
  172. case _LAM:
  173. return LAM;
  174. case _MIM:
  175. return MIM;
  176. case _NOON:
  177. return NOON;
  178. case _YE:
  179. case YE_:
  180. return YE;
  181. case _YEE:
  182. case YEE_:
  183. return YEE;
  184. case TEE_:
  185. return TEE;
  186. case _IE:
  187. case IE_:
  188. return IE;
  189. case _HE:
  190. case _HE_:
  191. return F_HE;
  192.     }
  193.     return c;
  194. }
  195. /*
  196. ** Is the character under the cursor+offset in the given buffer a join type.
  197. ** That is a character that is combined with the others.
  198. ** Note: the offset is used only for command line buffer.
  199. */
  200.     static int
  201. F_is_TyB_TyC_TyD(src, offset)
  202.     int     src,    offset;
  203. {
  204. int c;
  205.     if ( src == SRC_EDT)
  206. c = gchar_cursor();
  207.     else
  208. c = cmd_gchar(AT_CURSOR+offset);
  209.     switch (c)
  210.     {
  211. case _LAM:
  212. case _BE:
  213. case _PE:
  214. case _TE:
  215. case _SE:
  216. case _JIM:
  217. case _CHE:
  218. case _HE_J:
  219. case _XE:
  220. case _SIN:
  221. case _SHIN:
  222. case _SAD:
  223. case _ZAD:
  224. case _TA:
  225. case _ZA:
  226. case _AYN:
  227. case _AYN_:
  228. case _GHAYN:
  229. case _GHAYN_:
  230. case _FE:
  231. case _GHAF:
  232. case _KAF:
  233. case _KAF_H:
  234. case _GAF:
  235. case _MIM:
  236. case _NOON:
  237. case _YE:
  238. case _YEE:
  239. case _IE:
  240. case _HE_:
  241. case _HE:
  242. return TRUE;
  243.     }
  244.     return FALSE;
  245. }
  246. /*
  247. ** Is the Farsi character one of the terminating only type.
  248. */
  249.     static int
  250. F_is_TyE(c)
  251.     int     c;
  252. {
  253.     switch (c)
  254.     {
  255. case ALEF_A:
  256. case ALEF_D_H:
  257. case DAL:
  258. case ZAL:
  259. case RE:
  260. case ZE:
  261. case JE:
  262. case WAW:
  263. case WAW_H:
  264. case HAMZE:
  265. return TRUE;
  266.     }
  267.     return FALSE;
  268. }
  269. /*
  270. ** Is the Farsi character one of the none leading type.
  271. */
  272.     static int
  273. F_is_TyC_TyD(c)
  274.     int     c;
  275. {
  276.     switch (c)
  277.     {
  278. case ALEF_:
  279. case ALEF_U_H_:
  280. case _AYN_:
  281. case AYN_:
  282. case _GHAYN_:
  283. case GHAYN_:
  284. case _HE_:
  285. case YE_:
  286. case IE_:
  287. case TEE_:
  288. case YEE_:
  289. return TRUE;
  290.     }
  291.     return FALSE;
  292. }
  293. /*
  294. ** Convert a none leading Farsi char into a leading type.
  295. */
  296.     static int
  297. toF_TyB(c)
  298.     int     c;
  299. {
  300.     switch (c)
  301.     {
  302. case ALEF_: return ALEF;
  303. case ALEF_U_H_:     return ALEF_U_H;
  304. case _AYN_: return _AYN;
  305. case AYN_: return AYN; /* exception - there are many of them */
  306. case _GHAYN_: return _GHAYN;
  307. case GHAYN_: return GHAYN; /* exception - there are many of them */
  308. case _HE_: return _HE;
  309. case YE_: return YE;
  310. case IE_: return IE;
  311. case TEE_: return TEE;
  312. case YEE_: return YEE;
  313.     }
  314.     return c;
  315. }
  316. /*
  317. ** Overwrite the current redo and cursor characters + left adjust
  318. */
  319.     static void
  320. put_curr_and_l_to_X(c)
  321.     int   c;
  322. {
  323.     int tempc;
  324.     if (curwin->w_p_rl && p_ri)
  325. return;
  326.     if ( (curwin->w_cursor.col < STRLEN(ml_get_curline())))
  327.     {
  328. if ((p_ri && curwin->w_cursor.col) || !p_ri)
  329. {
  330.     if (p_ri)
  331. dec_cursor();
  332.     else
  333. inc_cursor();
  334.     if (F_is_TyC_TyD((tempc = gchar_cursor())))
  335.     {
  336. pchar_cursor(toF_TyB(tempc));
  337. AppendCharToRedobuff(K_BS);
  338. AppendCharToRedobuff(tempc);
  339.     }
  340.     if (p_ri)
  341. inc_cursor();
  342.     else
  343. dec_cursor();
  344. }
  345.     }
  346.     put_and_redo(c);
  347. }
  348.     static void
  349. put_and_redo(c)
  350.     int c;
  351. {
  352.     pchar_cursor(c);
  353.     AppendCharToRedobuff(K_BS);
  354.     AppendCharToRedobuff(c);
  355. }
  356. /*
  357. ** Change the char. under the cursor to a X_ or X type
  358. */
  359.     static void
  360. chg_c_toX_orX()
  361. {
  362.     int tempc, curc;
  363.     switch ((curc = gchar_cursor()))
  364.     {
  365. case _BE:
  366. tempc = BE;
  367. break;
  368. case _PE:
  369. tempc = PE;
  370. break;
  371. case _TE:
  372. tempc = TE;
  373. break;
  374. case _SE:
  375. tempc = SE;
  376. break;
  377. case _JIM:
  378. tempc = JIM;
  379. break;
  380. case _CHE:
  381. tempc = CHE;
  382. break;
  383. case _HE_J:
  384. tempc = HE_J;
  385. break;
  386. case _XE:
  387. tempc = XE;
  388. break;
  389. case _SIN:
  390. tempc = SIN;
  391. break;
  392. case _SHIN:
  393. tempc = SHIN;
  394. break;
  395. case _SAD:
  396. tempc = SAD;
  397. break;
  398. case _ZAD:
  399. tempc = ZAD;
  400. break;
  401. case _FE:
  402. tempc = FE;
  403. break;
  404. case _GHAF:
  405. tempc = GHAF;
  406. break;
  407. case _KAF_H:
  408. case _KAF:
  409. tempc = KAF;
  410. break;
  411. case _GAF:
  412. tempc = GAF;
  413. break;
  414. case _AYN:
  415. tempc = AYN;
  416. break;
  417. case _AYN_:
  418. tempc = AYN_;
  419. break;
  420. case _GHAYN:
  421. tempc = GHAYN;
  422. break;
  423. case _GHAYN_:
  424. tempc = GHAYN_;
  425. break;
  426. case _LAM:
  427. tempc = LAM;
  428. break;
  429. case _MIM:
  430. tempc = MIM;
  431. break;
  432. case _NOON:
  433. tempc = NOON;
  434. break;
  435. case _HE:
  436. case _HE_:
  437. tempc = F_HE;
  438. break;
  439. case _YE:
  440. case _IE:
  441. case _YEE:
  442. if (p_ri)
  443. {
  444.     inc_cursor();
  445.     if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  446.     tempc = (curc == _YE ? YE_ :
  447.     (curc == _IE ? IE_ : YEE_));
  448.     else
  449.     tempc = (curc == _YE ? YE :
  450.     (curc == _IE ? IE : YEE));
  451.     dec_cursor();
  452. }
  453. else
  454. {
  455.     if (curwin->w_cursor.col)
  456.     {
  457. dec_cursor();
  458. if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  459. tempc = (curc == _YE ? YE_ :
  460. (curc == _IE ? IE_ : YEE_));
  461. else
  462. tempc = (curc == _YE ? YE :
  463. (curc == _IE ? IE : YEE));
  464. inc_cursor();
  465.     }
  466.     else
  467.     tempc = (curc == _YE ? YE :
  468.     (curc == _IE ? IE : YEE));
  469. }
  470. break;
  471. default:
  472. tempc = 0;
  473.     }
  474.     if (tempc)
  475. put_and_redo(tempc);
  476. }
  477. /*
  478. ** Change the char. under the cursor to a _X_ or X_ type
  479. */
  480.     static void
  481. chg_c_to_X_orX_()
  482. {
  483.     int tempc;
  484.     switch (gchar_cursor())
  485.     {
  486. case ALEF:
  487. tempc = ALEF_;
  488. break;
  489. case ALEF_U_H:
  490. tempc = ALEF_U_H_;
  491. break;
  492. case _AYN:
  493. tempc = _AYN_;
  494. break;
  495. case AYN:
  496. tempc = AYN_;
  497. break;
  498. case _GHAYN:
  499. tempc = _GHAYN_;
  500. break;
  501. case GHAYN:
  502. tempc = GHAYN_;
  503. break;
  504. case _HE:
  505. tempc = _HE_;
  506. break;
  507. case YE:
  508. tempc = YE_;
  509. break;
  510. case IE:
  511. tempc = IE_;
  512. break;
  513. case TEE:
  514. tempc = TEE_;
  515. break;
  516. case YEE:
  517. tempc = YEE_;
  518. break;
  519. default:
  520. tempc = 0;
  521.     }
  522.     if (tempc)
  523. put_and_redo(tempc);
  524. }
  525. /*
  526. ** Change the char. under the cursor to a _X_ or _X type
  527. */
  528.     static void
  529. chg_c_to_X_or_X ()
  530. {
  531.     int tempc;
  532.     tempc = gchar_cursor();
  533.     if (curwin->w_cursor.col+1 < STRLEN(ml_get_curline()))
  534.     {
  535. inc_cursor();
  536. if ((tempc == F_HE) && (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)))
  537. {
  538.     tempc = _HE_;
  539.     dec_cursor();
  540.     put_and_redo(tempc);
  541.     return;
  542. }
  543. dec_cursor();
  544.     }
  545.     if ((tempc = toF_Xor_X_(tempc)))
  546. put_and_redo(tempc);
  547. }
  548. /*
  549. ** Change the character left to the cursor to a _X_ or X_ type
  550. */
  551.     static void
  552. chg_l_to_X_orX_ ()
  553. {
  554.     int tempc;
  555.     if (!curwin->w_cursor.col &&
  556. (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
  557. return;
  558.     if (!curwin->w_cursor.col && p_ri)
  559. return;
  560.     if (p_ri)
  561. dec_cursor();
  562.     else
  563. inc_cursor();
  564.     switch (gchar_cursor())
  565.     {
  566. case ALEF:
  567. tempc = ALEF_;
  568. break;
  569. case ALEF_U_H:
  570. tempc = ALEF_U_H_;
  571. break;
  572. case _AYN:
  573. tempc = _AYN_;
  574. break;
  575. case AYN:
  576. tempc = AYN_;
  577. break;
  578. case _GHAYN:
  579. tempc = _GHAYN_;
  580. break;
  581. case GHAYN:
  582. tempc = GHAYN_;
  583. break;
  584. case _HE:
  585. tempc = _HE_;
  586. break;
  587. case YE:
  588. tempc = YE_;
  589. break;
  590. case IE:
  591. tempc = IE_;
  592. break;
  593. case TEE:
  594. tempc = TEE_;
  595. break;
  596. case YEE:
  597. tempc = YEE_;
  598. break;
  599. default:
  600. tempc = 0;
  601.     }
  602.     if (tempc)
  603. put_and_redo(tempc);
  604.     if (p_ri)
  605. inc_cursor();
  606.     else
  607. dec_cursor();
  608. }
  609. /*
  610. ** Change the charcter left to the cursor to a X or _X type
  611. */
  612.     static void
  613. chg_l_toXor_X ()
  614. {
  615.     int tempc;
  616.     if (!curwin->w_cursor.col &&
  617. (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
  618. return;
  619.     if (!curwin->w_cursor.col && p_ri)
  620. return;
  621.     if (p_ri)
  622. dec_cursor();
  623.     else
  624. inc_cursor();
  625.     switch (gchar_cursor())
  626.     {
  627. case ALEF_:
  628. tempc = ALEF;
  629. break;
  630. case ALEF_U_H_:
  631. tempc = ALEF_U_H;
  632. break;
  633. case _AYN_:
  634. tempc = _AYN;
  635. break;
  636. case AYN_:
  637. tempc = AYN;
  638. break;
  639. case _GHAYN_:
  640. tempc = _GHAYN;
  641. break;
  642. case GHAYN_:
  643. tempc = GHAYN;
  644. break;
  645. case _HE_:
  646. tempc = _HE;
  647. break;
  648. case YE_:
  649. tempc = YE;
  650. break;
  651. case IE_:
  652. tempc = IE;
  653. break;
  654. case TEE_:
  655. tempc = TEE;
  656. break;
  657. case YEE_:
  658. tempc = YEE;
  659. break;
  660. default:
  661. tempc = 0;
  662.     }
  663.     if (tempc)
  664. put_and_redo(tempc);
  665.     if (p_ri)
  666. inc_cursor();
  667.     else
  668. dec_cursor();
  669. }
  670. /*
  671. ** Change the charcter right to the cursor to a _X or _X_ type
  672. */
  673.     static void
  674. chg_r_to_Xor_X_()
  675. {
  676. int tempc, c;
  677.     if (curwin->w_cursor.col)
  678.     {
  679. if (!p_ri)
  680.     dec_cursor();
  681. tempc = gchar_cursor();
  682. if ((c = toF_Xor_X_(tempc)))
  683.     put_and_redo(c);
  684. if (!p_ri)
  685.     inc_cursor();
  686.     }
  687. }
  688. /*
  689. ** Map Farsi keyboard when in fkmap mode.
  690. */
  691.     int
  692. fkmap(c)
  693.     int c;
  694. {
  695.     int tempc;
  696.     static int revins;
  697.     if (vim_isdigit(c) || ((c == '.' || c == '+' || c == '-' ||
  698. c == '^' || c == '%' || c == '#' || c == '=')  && revins))
  699.     {
  700. if (!revins)
  701. {
  702.     if (curwin->w_cursor.col)
  703.     {
  704. if (!p_ri)
  705.     dec_cursor();
  706.     chg_c_toX_orX ();
  707.     chg_l_toXor_X ();
  708. if (!p_ri)
  709.     inc_cursor();
  710.     }
  711. }
  712. arrow_used = TRUE;
  713. stop_arrow();
  714. if (!curwin->w_p_rl && revins)
  715.     inc_cursor();
  716. ++revins;
  717. p_ri=1;
  718.     }
  719.     else
  720.     {
  721. if (revins)
  722. {
  723.     arrow_used = TRUE;
  724.     stop_arrow();
  725.     revins=0;
  726.     tempc = gchar_cursor();
  727.     if (curwin->w_p_rl)
  728.     {
  729. while ((F_isdigit(gchar_cursor())
  730.     || (gchar_cursor() == F_PERIOD
  731. || gchar_cursor() == F_PLUS
  732. || gchar_cursor() == F_MINUS
  733. || gchar_cursor() == F_MUL
  734. || gchar_cursor() == F_DIVIDE
  735. || gchar_cursor() == F_PERCENT
  736. || gchar_cursor() == F_EQUALS))
  737. && gchar_cursor()!= NUL)
  738.     ++curwin->w_cursor.col;
  739.     }
  740.     else
  741.     {
  742. if (curwin->w_cursor.col)
  743.     while ((F_isdigit(gchar_cursor())
  744.     || (gchar_cursor() == F_PERIOD
  745. || gchar_cursor() == F_PLUS
  746. || gchar_cursor() == F_MINUS
  747. || gchar_cursor() == F_MUL
  748. || gchar_cursor() == F_DIVIDE
  749. || gchar_cursor() == F_PERCENT
  750. || gchar_cursor() == F_EQUALS))
  751.     && --curwin->w_cursor.col);
  752. if (!F_isdigit(gchar_cursor()))
  753.     ++curwin->w_cursor.col;
  754.     }
  755. }
  756.     }
  757.     if (!revins)
  758.     {
  759. if (curwin->w_p_rl)
  760.     p_ri=0;
  761. if (!curwin->w_p_rl)
  762.     p_ri=1;
  763.     }
  764.     if ((c < 0x100) && (isalpha(c) || c == '&' ||   c == '^' || c == ';' ||
  765.     c == '''|| c == ',' || c == '[' ||
  766.     c == ']' || c == '{' || c == '}' ))
  767. chg_r_to_Xor_X_();
  768.     tempc = 0;
  769.     switch (c)
  770.     {
  771. case '`':
  772. case ' ':
  773. case '.':
  774. case '!':
  775. case '"':
  776. case '$':
  777. case '%':
  778. case '^':
  779. case '&':
  780. case '/':
  781. case '(':
  782. case ')':
  783. case '=':
  784. case '\':
  785. case '?':
  786. case '+':
  787. case '-':
  788. case '_':
  789. case '*':
  790. case ':':
  791. case '#':
  792. case '~':
  793. case '@':
  794. case '<':
  795. case '>':
  796. case '{':
  797. case '}':
  798. case '|':
  799. case '0':
  800. case '1':
  801. case '2':
  802. case '3':
  803. case '4':
  804. case '5':
  805. case '6':
  806. case '7':
  807. case '8':
  808. case '9':
  809. case 'B':
  810. case 'E':
  811. case 'F':
  812. case 'H':
  813. case 'I':
  814. case 'K':
  815. case 'L':
  816. case 'M':
  817. case 'O':
  818. case 'P':
  819. case 'Q':
  820. case 'R':
  821. case 'T':
  822. case 'U':
  823. case 'W':
  824. case 'Y':
  825. case  NL:
  826. case  TAB:
  827.     if (p_ri && c == NL && curwin->w_cursor.col)
  828.     {
  829. /*
  830. ** If the char before the cursor is _X_ or X_ do not change
  831. ** the one under the cursor with X type.
  832. */
  833. dec_cursor();
  834. if (F_isalpha(gchar_cursor()))
  835. {
  836.     inc_cursor();
  837.     return NL;
  838. }
  839. inc_cursor();
  840.     }
  841.     if (!p_ri)
  842.     if (!curwin->w_cursor.col)
  843.     {
  844. switch (c)
  845. {
  846.     case '0': return FARSI_0;
  847.     case '1': return FARSI_1;
  848.     case '2': return FARSI_2;
  849.     case '3': return FARSI_3;
  850.     case '4': return FARSI_4;
  851.     case '5': return FARSI_5;
  852.     case '6': return FARSI_6;
  853.     case '7': return FARSI_7;
  854.     case '8': return FARSI_8;
  855.     case '9': return FARSI_9;
  856.     case 'B': return F_PSP;
  857.     case 'E': return JAZR_N;
  858.     case 'F': return ALEF_D_H;
  859.     case 'H': return ALEF_A;
  860.     case 'I': return TASH;
  861.     case 'K': return F_LQUOT;
  862.     case 'L': return F_RQUOT;
  863.     case 'M': return HAMZE;
  864.     case 'O': return '[';
  865.     case 'P': return ']';
  866.     case 'Q': return OO;
  867.     case 'R': return MAD_N;
  868.     case 'T': return OW;
  869.     case 'U': return MAD;
  870.     case 'W': return OW_OW;
  871.     case 'Y': return JAZR;
  872.     case '`': return F_PCN;
  873.     case '!': return F_EXCL;
  874.     case '@': return F_COMMA;
  875.     case '#': return F_DIVIDE;
  876.     case '$': return F_CURRENCY;
  877.     case '%': return F_PERCENT;
  878.     case '^': return F_MUL;
  879.     case '&': return F_BCOMMA;
  880.     case '*': return F_STAR;
  881.     case '(': return F_LPARENT;
  882.     case ')': return F_RPARENT;
  883.     case '-': return F_MINUS;
  884.     case '_': return F_UNDERLINE;
  885.     case '=': return F_EQUALS;
  886.     case '+': return F_PLUS;
  887.     case '\': return F_BSLASH;
  888.     case '|': return F_PIPE;
  889.     case ':': return F_DCOLON;
  890.     case '"': return F_SEMICOLON;
  891.     case '.': return F_PERIOD;
  892.     case '/': return F_SLASH;
  893.     case '<': return F_LESS;
  894.     case '>': return F_GREATER;
  895.     case '?': return F_QUESTION;
  896.     case ' ': return F_BLANK;
  897. }
  898. break;
  899.     }
  900.     if (!p_ri)
  901. dec_cursor();
  902.     switch ((tempc = gchar_cursor()))
  903.     {
  904. case _BE:
  905. case _PE:
  906. case _TE:
  907. case _SE:
  908. case _JIM:
  909. case _CHE:
  910. case _HE_J:
  911. case _XE:
  912. case _SIN:
  913. case _SHIN:
  914. case _SAD:
  915. case _ZAD:
  916. case _FE:
  917. case _GHAF:
  918. case _KAF:
  919. case _KAF_H:
  920. case _GAF:
  921. case _LAM:
  922. case _MIM:
  923. case _NOON:
  924. case _HE:
  925. case _HE_:
  926. case _TA:
  927. case _ZA:
  928. put_curr_and_l_to_X(toF_TyA(tempc));
  929. break;
  930. case _AYN:
  931. case _AYN_:
  932. if (!p_ri)
  933.     if (!curwin->w_cursor.col)
  934.     {
  935. put_curr_and_l_to_X(AYN);
  936. break;
  937.     }
  938. if (p_ri)
  939.     inc_cursor();
  940. else
  941.     dec_cursor();
  942. if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  943.     tempc = AYN_;
  944. else
  945.     tempc = AYN;
  946. if (p_ri)
  947.     dec_cursor();
  948. else
  949.     inc_cursor();
  950. put_curr_and_l_to_X(tempc);
  951. break;
  952. case _GHAYN:
  953. case _GHAYN_:
  954. if (!p_ri)
  955.     if (!curwin->w_cursor.col)
  956.     {
  957. put_curr_and_l_to_X(GHAYN);
  958. break;
  959.     }
  960. if (p_ri)
  961.     inc_cursor();
  962. else
  963.     dec_cursor();
  964. if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  965.     tempc = GHAYN_;
  966. else
  967.     tempc = GHAYN;
  968. if (p_ri)
  969.     dec_cursor();
  970. else
  971.     inc_cursor();
  972. put_curr_and_l_to_X(tempc);
  973. break;
  974. case _YE:
  975. case _IE:
  976. case _YEE:
  977. if (!p_ri)
  978.     if (!curwin->w_cursor.col)
  979.     {
  980. put_curr_and_l_to_X((tempc == _YE ? YE :
  981.     (tempc == _IE ? IE : YEE)));
  982. break;
  983.     }
  984. if (p_ri)
  985.     inc_cursor();
  986. else
  987.     dec_cursor();
  988. if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  989. tempc = (tempc == _YE ? YE_ :
  990.     (tempc == _IE ? IE_ : YEE_));
  991. else
  992. tempc = (tempc == _YE ? YE :
  993.     (tempc == _IE ? IE : YEE));
  994. if (p_ri)
  995.     dec_cursor();
  996. else
  997.     inc_cursor();
  998. put_curr_and_l_to_X(tempc);
  999. break;
  1000. }
  1001. if (!p_ri)
  1002.     inc_cursor();
  1003. tempc = 0;
  1004. switch (c)
  1005. {
  1006.     case '0': return FARSI_0;
  1007.     case '1': return FARSI_1;
  1008.     case '2': return FARSI_2;
  1009.     case '3': return FARSI_3;
  1010.     case '4': return FARSI_4;
  1011.     case '5': return FARSI_5;
  1012.     case '6': return FARSI_6;
  1013.     case '7': return FARSI_7;
  1014.     case '8': return FARSI_8;
  1015.     case '9': return FARSI_9;
  1016.     case 'B': return F_PSP;
  1017.     case 'E': return JAZR_N;
  1018.     case 'F': return ALEF_D_H;
  1019.     case 'H': return ALEF_A;
  1020.     case 'I': return TASH;
  1021.     case 'K': return F_LQUOT;
  1022.     case 'L': return F_RQUOT;
  1023.     case 'M': return HAMZE;
  1024.     case 'O': return '[';
  1025.     case 'P': return ']';
  1026.     case 'Q': return OO;
  1027.     case 'R': return MAD_N;
  1028.     case 'T': return OW;
  1029.     case 'U': return MAD;
  1030.     case 'W': return OW_OW;
  1031.     case 'Y': return JAZR;
  1032.     case '`': return F_PCN;
  1033.     case '!': return F_EXCL;
  1034.     case '@': return F_COMMA;
  1035.     case '#': return F_DIVIDE;
  1036.     case '$': return F_CURRENCY;
  1037.     case '%': return F_PERCENT;
  1038.     case '^': return F_MUL;
  1039.     case '&': return F_BCOMMA;
  1040.     case '*': return F_STAR;
  1041.     case '(': return F_LPARENT;
  1042.     case ')': return F_RPARENT;
  1043.     case '-': return F_MINUS;
  1044.     case '_': return F_UNDERLINE;
  1045.     case '=': return F_EQUALS;
  1046.     case '+': return F_PLUS;
  1047.     case '\': return F_BSLASH;
  1048.     case '|': return F_PIPE;
  1049.     case ':': return F_DCOLON;
  1050.     case '"': return F_SEMICOLON;
  1051.     case '.': return F_PERIOD;
  1052.     case '/': return F_SLASH;
  1053.     case '<': return F_LESS;
  1054.     case '>': return F_GREATER;
  1055.     case '?': return F_QUESTION;
  1056.     case ' ': return F_BLANK;
  1057. }
  1058. break;
  1059. case 'a':
  1060. tempc = _SHIN;
  1061.     break;
  1062. case 'A':
  1063. tempc = WAW_H;
  1064.     break;
  1065. case 'b':
  1066. tempc = ZAL;
  1067.     break;
  1068. case 'c':
  1069. tempc = ZE;
  1070.     break;
  1071. case 'C':
  1072. tempc = JE;
  1073.     break;
  1074. case 'd':
  1075. tempc = _YE;
  1076.     break;
  1077. case 'D':
  1078. tempc = _YEE;
  1079.     break;
  1080. case 'e':
  1081. tempc = _SE;
  1082.     break;
  1083. case 'f':
  1084. tempc = _BE;
  1085.     break;
  1086. case 'g':
  1087. tempc = _LAM;
  1088.     break;
  1089. case 'G':
  1090.     if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1091. {
  1092. if (gchar_cursor() == _LAM)
  1093.     chg_c_toX_orX ();
  1094. else
  1095.     if (p_ri)
  1096. chg_c_to_X_or_X ();
  1097.     }
  1098.     if (!p_ri)
  1099. if (!curwin->w_cursor.col)
  1100.     return ALEF_U_H;
  1101.     if (!p_ri)
  1102. dec_cursor();
  1103.     if (gchar_cursor() == _LAM)
  1104.     {
  1105. chg_c_toX_orX ();
  1106. chg_l_toXor_X ();
  1107.     tempc = ALEF_U_H;
  1108.     }
  1109.     else
  1110. if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1111. {
  1112. tempc = ALEF_U_H_;
  1113.     chg_l_toXor_X ();
  1114. }
  1115. else
  1116. tempc = ALEF_U_H;
  1117.     if (!p_ri)
  1118. inc_cursor();
  1119.     return tempc;
  1120. case 'h':
  1121.     if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1122. {
  1123. if (p_ri)
  1124.     chg_c_to_X_or_X ();
  1125.     }
  1126.     if (!p_ri)
  1127. if (!curwin->w_cursor.col)
  1128.     return ALEF;
  1129.     if (!p_ri)
  1130. dec_cursor();
  1131.     if (gchar_cursor() == _LAM)
  1132.     {
  1133. chg_l_toXor_X();
  1134. del_char(FALSE);
  1135. AppendCharToRedobuff(K_BS);
  1136. if (!p_ri)
  1137.     dec_cursor();
  1138.     tempc = LA;
  1139.     }
  1140.     else
  1141.     {
  1142. if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1143. {
  1144. tempc = ALEF_;
  1145.     chg_l_toXor_X ();
  1146. }
  1147. else
  1148. tempc = ALEF;
  1149.     }
  1150.     if (!p_ri)
  1151. inc_cursor();
  1152.     return tempc;
  1153. case 'i':
  1154.     if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1155. {
  1156. if (!p_ri && !F_is_TyE(tempc))
  1157.     chg_c_to_X_orX_ ();
  1158. if (p_ri)
  1159.     chg_c_to_X_or_X ();
  1160.     }
  1161.     if (!p_ri && !curwin->w_cursor.col)
  1162. return _HE;
  1163.     if (!p_ri)
  1164. dec_cursor();
  1165.     if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1166.     tempc = _HE_;
  1167.     else
  1168.     tempc = _HE;
  1169.     if (!p_ri)
  1170. inc_cursor();
  1171.     break;
  1172. case 'j':
  1173. tempc = _TE;
  1174.     break;
  1175. case 'J':
  1176.     if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1177. {
  1178. if (p_ri)
  1179.     chg_c_to_X_or_X ();
  1180.     }
  1181.     if (!p_ri)
  1182. if (!curwin->w_cursor.col)
  1183.     return TEE;
  1184.     if (!p_ri)
  1185. dec_cursor();
  1186.     if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1187.     {
  1188.     tempc = TEE_;
  1189. chg_l_toXor_X ();
  1190.     }
  1191.     else
  1192. tempc = TEE;
  1193.     if (!p_ri)
  1194. inc_cursor();
  1195.     return tempc;
  1196. case 'k':
  1197. tempc = _NOON;
  1198.     break;
  1199. case 'l':
  1200. tempc = _MIM;
  1201.     break;
  1202. case 'm':
  1203. tempc = _PE;
  1204.     break;
  1205. case 'n':
  1206. case 'N':
  1207. tempc = DAL;
  1208.     break;
  1209. case 'o':
  1210. tempc = _XE;
  1211.     break;
  1212. case 'p':
  1213. tempc = _HE_J;
  1214.     break;
  1215. case 'q':
  1216. tempc = _ZAD;
  1217.     break;
  1218. case 'r':
  1219. tempc = _GHAF;
  1220.     break;
  1221. case 's':
  1222. tempc = _SIN;
  1223.     break;
  1224. case 'S':
  1225. tempc = _IE;
  1226.     break;
  1227. case 't':
  1228. tempc = _FE;
  1229.     break;
  1230. case 'u':
  1231. if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1232. {
  1233.     if (!p_ri && !F_is_TyE(tempc))
  1234. chg_c_to_X_orX_ ();
  1235.     if (p_ri)
  1236. chg_c_to_X_or_X ();
  1237. }
  1238. if (!p_ri && !curwin->w_cursor.col)
  1239.     return _AYN;
  1240. if (!p_ri)
  1241.     dec_cursor();
  1242. if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1243.     tempc = _AYN_;
  1244. else
  1245.     tempc = _AYN;
  1246. if (!p_ri)
  1247.     inc_cursor();
  1248.     break;
  1249. case 'v':
  1250. case 'V':
  1251. tempc = RE;
  1252.     break;
  1253. case 'w':
  1254. tempc = _SAD;
  1255.     break;
  1256. case 'x':
  1257. case 'X':
  1258. tempc = _TA;
  1259.     break;
  1260. case 'y':
  1261.     if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1262. {
  1263. if (!p_ri && !F_is_TyE(tempc))
  1264.     chg_c_to_X_orX_ ();
  1265. if (p_ri)
  1266.     chg_c_to_X_or_X ();
  1267.     }
  1268.     if (!p_ri && !curwin->w_cursor.col)
  1269. return _GHAYN;
  1270.     if (!p_ri)
  1271. dec_cursor();
  1272.     if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1273. tempc = _GHAYN_;
  1274.     else
  1275. tempc = _GHAYN;
  1276.     if (!p_ri)
  1277. inc_cursor();
  1278.     break;
  1279. case 'z':
  1280. tempc = _ZA;
  1281.     break;
  1282. case 'Z':
  1283. tempc = _KAF_H;
  1284.     break;
  1285. case ';':
  1286. tempc = _KAF;
  1287.     break;
  1288. case ''':
  1289. tempc = _GAF;
  1290.     break;
  1291. case ',':
  1292. tempc = WAW;
  1293.     break;
  1294. case '[':
  1295. tempc = _JIM;
  1296.     break;
  1297. case ']':
  1298. tempc = _CHE;
  1299.     break;
  1300.     }
  1301.     if ((F_isalpha(tempc) || F_isdigit(tempc)))
  1302.     {
  1303. if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1304.     {
  1305.     if (!p_ri && !F_is_TyE(tempc))
  1306. chg_c_to_X_orX_ ();
  1307.     if (p_ri)
  1308. chg_c_to_X_or_X ();
  1309. }
  1310. if (curwin->w_cursor.col)
  1311. {
  1312.     if (!p_ri)
  1313. dec_cursor();
  1314.     if (F_is_TyE(tempc))
  1315. chg_l_toXor_X ();
  1316.     else
  1317. chg_l_to_X_orX_ ();
  1318.     if (!p_ri)
  1319. inc_cursor();
  1320. }
  1321.     }
  1322.     if (tempc)
  1323. return tempc;
  1324.     return c;
  1325. }
  1326. /*
  1327. ** Convert a none leading Farsi char into a leading type.
  1328. */
  1329.     static int
  1330. toF_leading(c)
  1331.     int     c;
  1332. {
  1333.     switch (c)
  1334.     {
  1335. case ALEF_: return ALEF;
  1336. case ALEF_U_H_:     return ALEF_U_H;
  1337. case BE:    return _BE;
  1338. case PE:    return _PE;
  1339. case TE:    return _TE;
  1340. case SE:    return _SE;
  1341. case JIM:   return _JIM;
  1342. case CHE:   return _CHE;
  1343. case HE_J:  return _HE_J;
  1344. case XE:    return _XE;
  1345. case SIN:   return _SIN;
  1346. case SHIN:  return _SHIN;
  1347. case SAD:   return _SAD;
  1348. case ZAD:   return _ZAD;
  1349. case AYN:
  1350. case AYN_:
  1351. case _AYN_: return _AYN;
  1352. case GHAYN:
  1353. case GHAYN_:
  1354. case _GHAYN_: return _GHAYN;
  1355. case FE:    return _FE;
  1356. case GHAF:  return _GHAF;
  1357. case KAF:   return _KAF;
  1358. case GAF:   return _GAF;
  1359. case LAM:   return _LAM;
  1360. case MIM:   return _MIM;
  1361. case NOON:  return _NOON;
  1362. case _HE_:
  1363. case F_HE: return _HE;
  1364. case YE:
  1365. case YE_: return _YE;
  1366. case IE_:
  1367. case IE: return _IE;
  1368. case YEE:
  1369. case YEE_: return _YEE;
  1370.     }
  1371.     return c;
  1372. }
  1373. /*
  1374. ** Convert a given Farsi char into right joining type.
  1375. */
  1376.     static int
  1377. toF_Rjoin(c)
  1378.     int     c;
  1379. {
  1380.     switch (c)
  1381.     {
  1382. case ALEF:  return ALEF_;
  1383. case ALEF_U_H: return ALEF_U_H_;
  1384. case BE:    return _BE;
  1385. case PE:    return _PE;
  1386. case TE:    return _TE;
  1387. case SE:    return _SE;
  1388. case JIM:   return _JIM;
  1389. case CHE:   return _CHE;
  1390. case HE_J:  return _HE_J;
  1391. case XE:    return _XE;
  1392. case SIN:   return _SIN;
  1393. case SHIN:  return _SHIN;
  1394. case SAD:   return _SAD;
  1395. case ZAD:   return _ZAD;
  1396. case AYN:
  1397. case AYN_:
  1398. case _AYN:  return _AYN_;
  1399. case GHAYN:
  1400. case GHAYN_:
  1401. case _GHAYN_: return _GHAYN_;
  1402. case FE:    return _FE;
  1403. case GHAF:  return _GHAF;
  1404. case KAF:   return _KAF;
  1405. case GAF:   return _GAF;
  1406. case LAM:   return _LAM;
  1407. case MIM:   return _MIM;
  1408. case NOON:  return _NOON;
  1409. case _HE:
  1410. case F_HE: return _HE_;
  1411. case YE:
  1412. case YE_: return _YE;
  1413. case IE_:
  1414. case IE: return _IE;
  1415. case TEE: return TEE_;
  1416. case YEE:
  1417. case YEE_: return _YEE;
  1418.     }
  1419.     return c;
  1420. }
  1421. /*
  1422. ** Can a given Farsi character join via its left edj.
  1423. */
  1424.     static int
  1425. canF_Ljoin(c)
  1426.     int c;
  1427. {
  1428.     switch (c)
  1429.     {
  1430. case _BE:
  1431. case BE:
  1432. case PE:
  1433. case _PE:
  1434. case TE:
  1435. case _TE:
  1436. case SE:
  1437. case _SE:
  1438. case JIM:
  1439. case _JIM:
  1440. case CHE:
  1441. case _CHE:
  1442. case HE_J:
  1443. case _HE_J:
  1444. case XE:
  1445. case _XE:
  1446. case SIN:
  1447. case _SIN:
  1448. case SHIN:
  1449. case _SHIN:
  1450. case SAD:
  1451. case _SAD:
  1452. case ZAD:
  1453. case _ZAD:
  1454. case _TA:
  1455. case _ZA:
  1456. case AYN:
  1457. case _AYN:
  1458. case _AYN_:
  1459. case AYN_:
  1460. case GHAYN:
  1461. case GHAYN_:
  1462. case _GHAYN_:
  1463. case _GHAYN:
  1464. case FE:
  1465. case _FE:
  1466. case GHAF:
  1467. case _GHAF:
  1468. case _KAF_H:
  1469. case KAF:
  1470. case _KAF:
  1471. case GAF:
  1472. case _GAF:
  1473. case LAM:
  1474. case _LAM:
  1475. case MIM:
  1476. case _MIM:
  1477. case NOON:
  1478. case _NOON:
  1479. case IE:
  1480. case _IE:
  1481. case IE_:
  1482. case YE:
  1483. case _YE:
  1484. case YE_:
  1485. case YEE:
  1486. case _YEE:
  1487. case YEE_:
  1488. case F_HE:
  1489. case _HE:
  1490. case _HE_:
  1491.     return TRUE;
  1492.     }
  1493.     return FALSE;
  1494. }
  1495. /*
  1496. ** Can a given Farsi character join via its right edj.
  1497. */
  1498.     static int
  1499. canF_Rjoin(c)
  1500.     int     c;
  1501. {
  1502.     switch (c)
  1503.     {
  1504. case ALEF:
  1505. case ALEF_:
  1506. case ALEF_U_H:
  1507. case ALEF_U_H_:
  1508. case DAL:
  1509. case ZAL:
  1510. case RE:
  1511. case JE:
  1512. case ZE:
  1513. case TEE:
  1514. case TEE_:
  1515. case WAW:
  1516. case WAW_H:
  1517.     return TRUE;
  1518.     }
  1519.     return canF_Ljoin(c);
  1520. }
  1521. /*
  1522. ** is a given Farsi character a terminating type.
  1523. */
  1524.     static int
  1525. F_isterm(c)
  1526.     int     c;
  1527. {
  1528.     switch (c)
  1529.     {
  1530. case ALEF:
  1531. case ALEF_:
  1532. case ALEF_U_H:
  1533. case ALEF_U_H_:
  1534. case DAL:
  1535. case ZAL:
  1536. case RE:
  1537. case JE:
  1538. case ZE:
  1539. case WAW:
  1540. case WAW_H:
  1541. case TEE:
  1542. case TEE_:
  1543.     return TRUE;
  1544.     }
  1545.     return FALSE;
  1546. }
  1547. /*
  1548. ** Convert the given Farsi character into a ending type .
  1549. */
  1550.     static int
  1551. toF_ending(c)
  1552.     int     c;
  1553. {
  1554.     switch (c)
  1555.     {
  1556. case _BE:
  1557. return BE;
  1558. case _PE:
  1559. return PE;
  1560. case _TE:
  1561. return TE;
  1562. case _SE:
  1563. return SE;
  1564. case _JIM:
  1565. return JIM;
  1566. case _CHE:
  1567. return CHE;
  1568. case _HE_J:
  1569. return HE_J;
  1570. case _XE:
  1571. return XE;
  1572. case _SIN:
  1573. return SIN;
  1574. case _SHIN:
  1575. return SHIN;
  1576. case _SAD:
  1577. return SAD;
  1578. case _ZAD:
  1579. return ZAD;
  1580. case _AYN:
  1581. return AYN;
  1582. case _AYN_:
  1583. return AYN_;
  1584. case _GHAYN:
  1585. return GHAYN;
  1586. case _GHAYN_:
  1587. return GHAYN_;
  1588. case _FE:
  1589. return FE;
  1590. case _GHAF:
  1591. return GHAF;
  1592. case _KAF_H:
  1593. case _KAF:
  1594. return KAF;
  1595. case _GAF:
  1596. return GAF;
  1597. case _LAM:
  1598. return LAM;
  1599. case _MIM:
  1600. return MIM;
  1601. case _NOON:
  1602. return NOON;
  1603. case _YE:
  1604. return YE_;
  1605. case YE_:
  1606. return YE;
  1607. case _YEE:
  1608. return YEE_;
  1609. case YEE_:
  1610. return YEE;
  1611. case TEE:
  1612. return TEE_;
  1613. case _IE:
  1614. return IE_;
  1615. case IE_:
  1616. return IE;
  1617. case _HE:
  1618. case _HE_:
  1619. return F_HE;
  1620.     }
  1621.     return c;
  1622. }
  1623. /*
  1624. ** Convert the Farsi 3342 standard into Farsi VIM.
  1625. */
  1626.     void
  1627. conv_to_pvim()
  1628. {
  1629. char_u *ptr;
  1630. int lnum, llen, i;
  1631.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  1632.     {
  1633. ptr = ml_get((linenr_t)lnum);
  1634. llen = STRLEN(ptr);
  1635. for ( i = 0; i < llen-1; i++)
  1636. {
  1637.     if (canF_Ljoin(ptr[i]) && canF_Rjoin(ptr[i+1]))
  1638.     {
  1639. ptr[i] = toF_leading(ptr[i]);
  1640. ++i;
  1641. while(canF_Rjoin(ptr[i]) && (i < llen))
  1642. {
  1643.     ptr[i] = toF_Rjoin(ptr[i]);
  1644.     if (F_isterm(ptr[i]) || !F_isalpha(ptr[i]))
  1645. break;
  1646.     ++i;
  1647. }
  1648. if (!F_isalpha(ptr[i]) || !canF_Rjoin(ptr[i]))
  1649.     ptr[i-1] = toF_ending(ptr[i-1]);
  1650.     }
  1651.     else
  1652. ptr[i] = toF_TyA(ptr[i]);
  1653. }
  1654.     }
  1655.     /*
  1656.     ** Following lines contains Farsi encoded character.
  1657.     */
  1658.     do_cmdline((char_u *)"%s/202231/232/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE);
  1659.     do_cmdline((char_u *)"%s/201231/370334/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE);
  1660.     update_screen(CLEAR);
  1661.     MSG_ATTR(farsi_text_1, hl_attr(HLF_S));
  1662. }
  1663. /*
  1664. ** Convert the Farsi VIM into Farsi 3342 standad.
  1665. */
  1666.     void
  1667. conv_to_pstd()
  1668. {
  1669. char_u *ptr;
  1670. int lnum, llen, i;
  1671.     /*
  1672.     ** Following line contains Farsi encoded character.
  1673.     */
  1674.     do_cmdline((char_u *)"%s/232/202231/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE);
  1675.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  1676.     {
  1677. ptr = ml_get((linenr_t)lnum);
  1678. llen = STRLEN(ptr);
  1679. for ( i = 0; i < llen; i++)
  1680. {
  1681.     ptr[i] = toF_TyA(ptr[i]);
  1682. }
  1683.     }
  1684.     update_screen(CLEAR);
  1685.     MSG_ATTR(farsi_text_2, hl_attr(HLF_S));
  1686. }
  1687. /*
  1688.  * left-right swap the characters in buf[len].
  1689.  */
  1690.     static void
  1691. lrswapbuf(buf, len)
  1692.     char_u *buf;
  1693.     int len;
  1694. {
  1695.     char_u *s, *e;
  1696.     int c;
  1697.     s = buf;
  1698.     e = buf + len - 1;
  1699.     while (e > s)
  1700.     {
  1701. c = *s;
  1702. *s = *e;
  1703. *e = c;
  1704. ++s;
  1705. --e;
  1706.     }
  1707. }
  1708. /*
  1709.  * swap all the characters in reverse direction
  1710.  */
  1711.     char_u *
  1712. lrswap(ibuf)
  1713.     char_u *ibuf;
  1714. {
  1715.     if (ibuf != NULL && *ibuf != NUL)
  1716. lrswapbuf(ibuf, (int)STRLEN(ibuf));
  1717.     return ibuf;
  1718. }
  1719. /*
  1720.  * swap all the Farsi characters in reverse direction
  1721.  */
  1722.     char_u *
  1723. lrFswap(cmdbuf, len)
  1724.     char_u *cmdbuf;
  1725.     int len;
  1726. {
  1727.     int i, cnt;
  1728.     if (cmdbuf == NULL)
  1729. return cmdbuf;
  1730.     if (len == 0 && (len = STRLEN(cmdbuf)) == 0)
  1731. return cmdbuf;
  1732.     for (i = 0; i < len; i++)
  1733.     {
  1734. for (cnt = 0; i + cnt < len
  1735. && (F_isalpha(cmdbuf[i + cnt])
  1736.     || F_isdigit(cmdbuf[i + cnt])
  1737.     || cmdbuf[i + cnt] == ' '); ++cnt)
  1738.     ;
  1739. lrswapbuf(cmdbuf + i, cnt);
  1740. i += cnt;
  1741.     }
  1742.     return cmdbuf;
  1743. }
  1744. /*
  1745.  * Reverse the characters in the seach path and substitude section accordingly
  1746.  */
  1747.     char_u *
  1748. lrF_sub(ibuf)
  1749.     char_u *ibuf;
  1750. {
  1751.     char_u *p, *ep;
  1752.     int i, cnt;
  1753.     p = ibuf;
  1754.     /* Find the boundry of the search path */
  1755.     while ((p = vim_strchr(++p, '/')) && p[-1] == '\')
  1756. ;
  1757.     if (p == NULL)
  1758. return ibuf;
  1759.     /* Reverse the Farsi characters in the search path. */
  1760.     lrFswap(ibuf, (int)(p-ibuf));
  1761.     /* Now find the boundry of the substitute section */
  1762.     if ((ep = (char_u *)strrchr((char *)++p, '/')))
  1763. cnt = ep - p;
  1764.     else
  1765. cnt = STRLEN(p);
  1766.     /* Reverse the characters in the substitute section and take care of '' */
  1767.     for (i = 0; i < cnt-1; i++)
  1768. if (p[i] == '\')
  1769. {
  1770.     p[i] = p[i+1] ;
  1771.     p[++i] = '\';
  1772. }
  1773.     lrswapbuf(p, cnt);
  1774.     return ibuf;
  1775. }
  1776. /*
  1777.  * Map Farsi keyboard when in cmd_fkmap mode.
  1778.  */
  1779.     int
  1780. cmdl_fkmap(c)
  1781.     int c;
  1782. {
  1783. int tempc;
  1784.     switch (c)
  1785.     {
  1786. case '0':
  1787. case '1':
  1788. case '2':
  1789. case '3':
  1790. case '4':
  1791. case '5':
  1792. case '6':
  1793. case '7':
  1794. case '8':
  1795. case '9':
  1796. case '`':
  1797. case ' ':
  1798. case '.':
  1799. case '!':
  1800. case '"':
  1801. case '$':
  1802. case '%':
  1803. case '^':
  1804. case '&':
  1805. case '/':
  1806. case '(':
  1807. case ')':
  1808. case '=':
  1809. case '\':
  1810. case '?':
  1811. case '+':
  1812. case '-':
  1813. case '_':
  1814. case '*':
  1815. case ':':
  1816. case '#':
  1817. case '~':
  1818. case '@':
  1819. case '<':
  1820. case '>':
  1821. case '{':
  1822. case '}':
  1823. case '|':
  1824. case 'B':
  1825. case 'E':
  1826. case 'F':
  1827. case 'H':
  1828. case 'I':
  1829. case 'K':
  1830. case 'L':
  1831. case 'M':
  1832. case 'O':
  1833. case 'P':
  1834. case 'Q':
  1835. case 'R':
  1836. case 'T':
  1837. case 'U':
  1838. case 'W':
  1839. case 'Y':
  1840. case  NL:
  1841. case  TAB:
  1842.        switch ((tempc = cmd_gchar(AT_CURSOR)))
  1843.        {
  1844.     case _BE:
  1845.     case _PE:
  1846.     case _TE:
  1847.     case _SE:
  1848.     case _JIM:
  1849.     case _CHE:
  1850.     case _HE_J:
  1851.     case _XE:
  1852.     case _SIN:
  1853.     case _SHIN:
  1854.     case _SAD:
  1855.     case _ZAD:
  1856.     case _AYN:
  1857.     case _GHAYN:
  1858.     case _FE:
  1859.     case _GHAF:
  1860.     case _KAF:
  1861.     case _GAF:
  1862.     case _LAM:
  1863.     case _MIM:
  1864.     case _NOON:
  1865.     case _HE:
  1866.     case _HE_:
  1867. cmd_pchar(toF_TyA(tempc), AT_CURSOR);
  1868. break;
  1869.     case _AYN_:
  1870. cmd_pchar(AYN_, AT_CURSOR);
  1871. break;
  1872.     case _GHAYN_:
  1873. cmd_pchar(GHAYN_, AT_CURSOR);
  1874. break;
  1875.     case _IE:
  1876. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  1877.     cmd_pchar(IE_, AT_CURSOR);
  1878. else
  1879.     cmd_pchar(IE, AT_CURSOR);
  1880. break;
  1881.     case _YEE:
  1882. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  1883.     cmd_pchar(YEE_, AT_CURSOR);
  1884. else
  1885.     cmd_pchar(YEE, AT_CURSOR);
  1886. break;
  1887.     case _YE:
  1888. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  1889.     cmd_pchar(YE_, AT_CURSOR);
  1890. else
  1891.     cmd_pchar(YE, AT_CURSOR);
  1892.     }
  1893.     switch (c)
  1894.     {
  1895. case '0':   return FARSI_0;
  1896. case '1':   return FARSI_1;
  1897. case '2':   return FARSI_2;
  1898. case '3':   return FARSI_3;
  1899. case '4':   return FARSI_4;
  1900. case '5':   return FARSI_5;
  1901. case '6':   return FARSI_6;
  1902. case '7':   return FARSI_7;
  1903. case '8':   return FARSI_8;
  1904. case '9':   return FARSI_9;
  1905. case 'B':   return F_PSP;
  1906. case 'E':   return JAZR_N;
  1907. case 'F':   return ALEF_D_H;
  1908. case 'H':   return ALEF_A;
  1909. case 'I':   return TASH;
  1910. case 'K':   return F_LQUOT;
  1911. case 'L':   return F_RQUOT;
  1912. case 'M':   return HAMZE;
  1913. case 'O':   return '[';
  1914. case 'P':   return ']';
  1915. case 'Q':   return OO;
  1916. case 'R':   return MAD_N;
  1917. case 'T':   return OW;
  1918. case 'U':   return MAD;
  1919. case 'W':   return OW_OW;
  1920. case 'Y':   return JAZR;
  1921. case '`':   return F_PCN;
  1922. case '!':   return F_EXCL;
  1923. case '@':   return F_COMMA;
  1924. case '#':   return F_DIVIDE;
  1925. case '$':   return F_CURRENCY;
  1926. case '%':   return F_PERCENT;
  1927. case '^':   return F_MUL;
  1928. case '&':   return F_BCOMMA;
  1929. case '*':   return F_STAR;
  1930. case '(':   return F_LPARENT;
  1931. case ')':   return F_RPARENT;
  1932. case '-':   return F_MINUS;
  1933. case '_':   return F_UNDERLINE;
  1934. case '=':   return F_EQUALS;
  1935. case '+':   return F_PLUS;
  1936. case '\':  return F_BSLASH;
  1937. case '|':   return F_PIPE;
  1938. case ':':   return F_DCOLON;
  1939. case '"':   return F_SEMICOLON;
  1940. case '.':   return F_PERIOD;
  1941. case '/':   return F_SLASH;
  1942. case '<':   return F_LESS;
  1943. case '>':   return F_GREATER;
  1944. case '?':   return F_QUESTION;
  1945. case ' ':   return F_BLANK;
  1946.     }
  1947.     break;
  1948. case 'a':   return _SHIN;
  1949. case 'A':   return WAW_H;
  1950. case 'b':   return ZAL;
  1951. case 'c':   return ZE;
  1952. case 'C':   return JE;
  1953. case 'd':   return _YE;
  1954. case 'D':   return _YEE;
  1955. case 'e':   return _SE;
  1956. case 'f':   return _BE;
  1957. case 'g':   return _LAM;
  1958. case 'G':
  1959.     if (cmd_gchar(AT_CURSOR) == _LAM )
  1960. {
  1961.     cmd_pchar(LAM, AT_CURSOR);
  1962.     return ALEF_U_H;
  1963. }
  1964. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  1965. return ALEF_U_H_;
  1966. else
  1967. return ALEF_U_H;
  1968. case 'h':
  1969.     if (cmd_gchar(AT_CURSOR) == _LAM )
  1970. {
  1971.     cmd_pchar(LA, AT_CURSOR);
  1972.     redrawcmdline();
  1973.     return K_IGNORE;
  1974. }
  1975. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  1976. return ALEF_;
  1977. else
  1978. return ALEF;
  1979. case 'i':
  1980. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  1981. return _HE_;
  1982. else
  1983. return _HE;
  1984. case 'j':   return _TE;
  1985. case 'J':
  1986. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  1987. return TEE_;
  1988. else
  1989. return TEE;
  1990. case 'k':   return _NOON;
  1991. case 'l':   return _MIM;
  1992. case 'm':   return _PE;
  1993. case 'n':
  1994. case 'N':   return DAL;
  1995. case 'o':   return _XE;
  1996. case 'p':   return _HE_J;
  1997. case 'q':   return _ZAD;
  1998. case 'r':   return _GHAF;
  1999. case 's':   return _SIN;
  2000. case 'S':   return _IE;
  2001. case 't':   return _FE;
  2002. case 'u':
  2003. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2004. return _AYN_;
  2005. else
  2006. return _AYN;
  2007. case 'v':
  2008. case 'V':   return RE;
  2009. case 'w':   return _SAD;
  2010. case 'x':
  2011. case 'X':   return _TA;
  2012. case 'y':
  2013. if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2014. return _GHAYN_;
  2015. else
  2016. return _GHAYN;
  2017. case 'z':
  2018. case 'Z':   return _ZA;
  2019. case ';':   return _KAF;
  2020. case ''':  return _GAF;
  2021. case ',':   return WAW;
  2022. case '[':   return _JIM;
  2023. case ']':   return _CHE;
  2024. }
  2025. return c;
  2026. }
  2027. /*
  2028.  * F_isalpha returns TRUE if 'c' is a Farsi alphabet
  2029.  */
  2030.     int
  2031. F_isalpha(c)
  2032.     int c;
  2033. {
  2034.     return (( c >= TEE_ && c <= _YE) ||
  2035. ( c >= ALEF_A && c <= YE) ||
  2036. ( c >= _IE && c <= YE_));
  2037. }
  2038. /*
  2039.  * F_isdigit returns TRUE if 'c' is a Farsi digit
  2040.  */
  2041.     int
  2042. F_isdigit(c)
  2043.     int     c;
  2044. {
  2045.     return (( c >= FARSI_0 && c <= FARSI_9 ));
  2046. }
  2047. /*
  2048.  * F_ischar returns TRUE if 'c' is a Farsi character.
  2049.  */
  2050.     int
  2051. F_ischar(c)
  2052.     int     c;
  2053. {
  2054.     return (( c >= TEE_ && c <= YE_));
  2055. }
  2056.     void
  2057. farsi_fkey(c)
  2058.     int     c;
  2059. {
  2060.     if (c == K_F8)
  2061.     {
  2062. if (p_altkeymap)
  2063. {
  2064.     if (curwin->w_p_pers & W_R_L)
  2065.     {
  2066. p_fkmap=0;
  2067. do_cmdline((char_u *)"set norl", NULL, NULL, DOCMD_NOWAIT);
  2068. MSG("");
  2069.     }
  2070.     else
  2071.     {
  2072. p_fkmap=1;
  2073. do_cmdline((char_u *)"set rl", NULL, NULL, DOCMD_NOWAIT);
  2074. MSG("");
  2075.     }
  2076.     curwin->w_p_pers = curwin->w_p_pers ^ W_R_L;
  2077. }
  2078.     }
  2079.     if (c == K_F9)
  2080.     {
  2081. if (p_altkeymap && curwin->w_p_rl)
  2082. {
  2083.     curwin->w_p_pers = curwin->w_p_pers ^ W_CONV;
  2084.     if (curwin->w_p_pers & W_CONV)
  2085. conv_to_pvim();
  2086.     else
  2087. conv_to_pstd();
  2088. }
  2089.     }
  2090. }