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