xref: /vim-8.2.3635/src/arabic.c (revision 94688b8a)
1 /* vi:set ts=8 sts=4 sw=4 noet:
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  * arabic.c: functions for Arabic language
12  *
13  * Author: Nadim Shaikli & Isam Bayazidi
14  */
15 
16 #include "vim.h"
17 
18 #if defined(FEAT_ARABIC) || defined(PROTO)
19 
20 static int  A_firstc_laa(int c1, int c);
21 static int  A_is_harakat(int c);
22 static int  A_is_iso(int c);
23 static int  A_is_formb(int c);
24 static int  A_is_ok(int c);
25 static int  A_is_valid(int c);
26 static int  A_is_special(int c);
27 
28 
29 /*
30  * Returns True if c is an ISO-8859-6 shaped ARABIC letter (user entered)
31  */
32     static int
33 A_is_a(int cur_c)
34 {
35     switch (cur_c)
36     {
37 	case a_HAMZA:
38 	case a_ALEF_MADDA:
39 	case a_ALEF_HAMZA_ABOVE:
40 	case a_WAW_HAMZA:
41 	case a_ALEF_HAMZA_BELOW:
42 	case a_YEH_HAMZA:
43 	case a_ALEF:
44 	case a_BEH:
45 	case a_TEH_MARBUTA:
46 	case a_TEH:
47 	case a_THEH:
48 	case a_JEEM:
49 	case a_HAH:
50 	case a_KHAH:
51 	case a_DAL:
52 	case a_THAL:
53 	case a_REH:
54 	case a_ZAIN:
55 	case a_SEEN:
56 	case a_SHEEN:
57 	case a_SAD:
58 	case a_DAD:
59 	case a_TAH:
60 	case a_ZAH:
61 	case a_AIN:
62 	case a_GHAIN:
63 	case a_TATWEEL:
64 	case a_FEH:
65 	case a_QAF:
66 	case a_KAF:
67 	case a_LAM:
68 	case a_MEEM:
69 	case a_NOON:
70 	case a_HEH:
71 	case a_WAW:
72 	case a_ALEF_MAKSURA:
73 	case a_YEH:
74 	    return TRUE;
75     }
76 
77     return FALSE;
78 }
79 
80 
81 /*
82  * Returns True if c is an Isolated Form-B ARABIC letter
83  */
84     static int
85 A_is_s(int cur_c)
86 {
87     switch (cur_c)
88     {
89 	case a_s_HAMZA:
90 	case a_s_ALEF_MADDA:
91 	case a_s_ALEF_HAMZA_ABOVE:
92 	case a_s_WAW_HAMZA:
93 	case a_s_ALEF_HAMZA_BELOW:
94 	case a_s_YEH_HAMZA:
95 	case a_s_ALEF:
96 	case a_s_BEH:
97 	case a_s_TEH_MARBUTA:
98 	case a_s_TEH:
99 	case a_s_THEH:
100 	case a_s_JEEM:
101 	case a_s_HAH:
102 	case a_s_KHAH:
103 	case a_s_DAL:
104 	case a_s_THAL:
105 	case a_s_REH:
106 	case a_s_ZAIN:
107 	case a_s_SEEN:
108 	case a_s_SHEEN:
109 	case a_s_SAD:
110 	case a_s_DAD:
111 	case a_s_TAH:
112 	case a_s_ZAH:
113 	case a_s_AIN:
114 	case a_s_GHAIN:
115 	case a_s_FEH:
116 	case a_s_QAF:
117 	case a_s_KAF:
118 	case a_s_LAM:
119 	case a_s_MEEM:
120 	case a_s_NOON:
121 	case a_s_HEH:
122 	case a_s_WAW:
123 	case a_s_ALEF_MAKSURA:
124 	case a_s_YEH:
125 	    return TRUE;
126     }
127 
128     return FALSE;
129 }
130 
131 
132 /*
133  * Returns True if c is a Final shape of an ARABIC letter
134  */
135     static int
136 A_is_f(int cur_c)
137 {
138     switch (cur_c)
139     {
140 	case a_f_ALEF_MADDA:
141 	case a_f_ALEF_HAMZA_ABOVE:
142 	case a_f_WAW_HAMZA:
143 	case a_f_ALEF_HAMZA_BELOW:
144 	case a_f_YEH_HAMZA:
145 	case a_f_ALEF:
146 	case a_f_BEH:
147 	case a_f_TEH_MARBUTA:
148 	case a_f_TEH:
149 	case a_f_THEH:
150 	case a_f_JEEM:
151 	case a_f_HAH:
152 	case a_f_KHAH:
153 	case a_f_DAL:
154 	case a_f_THAL:
155 	case a_f_REH:
156 	case a_f_ZAIN:
157 	case a_f_SEEN:
158 	case a_f_SHEEN:
159 	case a_f_SAD:
160 	case a_f_DAD:
161 	case a_f_TAH:
162 	case a_f_ZAH:
163 	case a_f_AIN:
164 	case a_f_GHAIN:
165 	case a_f_FEH:
166 	case a_f_QAF:
167 	case a_f_KAF:
168 	case a_f_LAM:
169 	case a_f_MEEM:
170 	case a_f_NOON:
171 	case a_f_HEH:
172 	case a_f_WAW:
173 	case a_f_ALEF_MAKSURA:
174 	case a_f_YEH:
175 	case a_f_LAM_ALEF_MADDA_ABOVE:
176 	case a_f_LAM_ALEF_HAMZA_ABOVE:
177 	case a_f_LAM_ALEF_HAMZA_BELOW:
178 	case a_f_LAM_ALEF:
179 	    return TRUE;
180     }
181     return FALSE;
182 }
183 
184 
185 /*
186  * Change shape - from ISO-8859-6/Isolated to Form-B Isolated
187  */
188     static int
189 chg_c_a2s(int cur_c)
190 {
191     switch (cur_c)
192     {
193 	case a_HAMZA: return a_s_HAMZA;
194 	case a_ALEF_MADDA: return a_s_ALEF_MADDA;
195 	case a_ALEF_HAMZA_ABOVE: return a_s_ALEF_HAMZA_ABOVE;
196 	case a_WAW_HAMZA: return a_s_WAW_HAMZA;
197 	case a_ALEF_HAMZA_BELOW: return a_s_ALEF_HAMZA_BELOW;
198 	case a_YEH_HAMZA: return a_s_YEH_HAMZA;
199 	case a_ALEF: return a_s_ALEF;
200 	case a_TEH_MARBUTA: return a_s_TEH_MARBUTA;
201 	case a_DAL: return a_s_DAL;
202 	case a_THAL: return a_s_THAL;
203 	case a_REH: return a_s_REH;
204 	case a_ZAIN: return a_s_ZAIN;
205 	case a_TATWEEL: return cur_c;	/* exceptions */
206 	case a_WAW: return a_s_WAW;
207 	case a_ALEF_MAKSURA: return a_s_ALEF_MAKSURA;
208 	case a_BEH: return a_s_BEH;
209 	case a_TEH: return a_s_TEH;
210 	case a_THEH: return a_s_THEH;
211 	case a_JEEM: return a_s_JEEM;
212 	case a_HAH: return a_s_HAH;
213 	case a_KHAH: return a_s_KHAH;
214 	case a_SEEN: return a_s_SEEN;
215 	case a_SHEEN: return a_s_SHEEN;
216 	case a_SAD: return a_s_SAD;
217 	case a_DAD: return a_s_DAD;
218 	case a_TAH: return a_s_TAH;
219 	case a_ZAH: return a_s_ZAH;
220 	case a_AIN: return a_s_AIN;
221 	case a_GHAIN: return a_s_GHAIN;
222 	case a_FEH: return a_s_FEH;
223 	case a_QAF: return a_s_QAF;
224 	case a_KAF: return a_s_KAF;
225 	case a_LAM: return a_s_LAM;
226 	case a_MEEM: return a_s_MEEM;
227 	case a_NOON: return a_s_NOON;
228 	case a_HEH: return a_s_HEH;
229 	case a_YEH: return a_s_YEH;
230     }
231     return 0;
232 }
233 
234 
235 /*
236  * Change shape - from ISO-8859-6/Isolated to Initial
237  */
238     static int
239 chg_c_a2i(int cur_c)
240 {
241     switch (cur_c)
242     {
243 	case a_YEH_HAMZA: return a_i_YEH_HAMZA;
244 	case a_HAMZA:			/* exceptions */
245 	    return a_s_HAMZA;
246 	case a_ALEF_MADDA:		/* exceptions */
247 	    return a_s_ALEF_MADDA;
248 	case a_ALEF_HAMZA_ABOVE:	/* exceptions */
249 	    return a_s_ALEF_HAMZA_ABOVE;
250 	case a_WAW_HAMZA:		/* exceptions */
251 	    return a_s_WAW_HAMZA;
252 	case a_ALEF_HAMZA_BELOW:	/* exceptions */
253 	    return a_s_ALEF_HAMZA_BELOW;
254 	case a_ALEF:			/* exceptions */
255 	    return a_s_ALEF;
256 	case a_TEH_MARBUTA:		/* exceptions */
257 	    return a_s_TEH_MARBUTA;
258 	case a_DAL:			/* exceptions */
259 	    return a_s_DAL;
260 	case a_THAL:			/* exceptions */
261 	    return a_s_THAL;
262 	case a_REH:			/* exceptions */
263 	    return a_s_REH;
264 	case a_ZAIN:			/* exceptions */
265 	    return a_s_ZAIN;
266 	case a_TATWEEL:			/* exceptions */
267 	    return cur_c;
268 	case a_WAW:			/* exceptions */
269 	    return a_s_WAW;
270 	case a_ALEF_MAKSURA:		/* exceptions */
271 	    return a_s_ALEF_MAKSURA;
272 	case a_BEH: return a_i_BEH;
273 	case a_TEH: return a_i_TEH;
274 	case a_THEH: return a_i_THEH;
275 	case a_JEEM: return a_i_JEEM;
276 	case a_HAH: return a_i_HAH;
277 	case a_KHAH: return a_i_KHAH;
278 	case a_SEEN: return a_i_SEEN;
279 	case a_SHEEN: return a_i_SHEEN;
280 	case a_SAD: return a_i_SAD;
281 	case a_DAD: return a_i_DAD;
282 	case a_TAH: return a_i_TAH;
283 	case a_ZAH: return a_i_ZAH;
284 	case a_AIN: return a_i_AIN;
285 	case a_GHAIN: return a_i_GHAIN;
286 	case a_FEH: return a_i_FEH;
287 	case a_QAF: return a_i_QAF;
288 	case a_KAF: return a_i_KAF;
289 	case a_LAM: return a_i_LAM;
290 	case a_MEEM: return a_i_MEEM;
291 	case a_NOON: return a_i_NOON;
292 	case a_HEH: return a_i_HEH;
293 	case a_YEH: return a_i_YEH;
294     }
295     return 0;
296 }
297 
298 
299 /*
300  * Change shape - from ISO-8859-6/Isolated to Medial
301  */
302     static int
303 chg_c_a2m(int cur_c)
304 {
305     switch (cur_c)
306     {
307 	case a_HAMZA: return a_s_HAMZA;	/* exception */
308 	case a_ALEF_MADDA: return a_f_ALEF_MADDA;	/* exception */
309 	case a_ALEF_HAMZA_ABOVE: return a_f_ALEF_HAMZA_ABOVE;	/* exception */
310 	case a_WAW_HAMZA: return a_f_WAW_HAMZA;	/* exception */
311 	case a_ALEF_HAMZA_BELOW: return a_f_ALEF_HAMZA_BELOW;	/* exception */
312 	case a_YEH_HAMZA: return a_m_YEH_HAMZA;
313 	case a_ALEF: return a_f_ALEF;	/* exception */
314 	case a_BEH: return a_m_BEH;
315 	case a_TEH_MARBUTA: return a_f_TEH_MARBUTA;	/* exception */
316 	case a_TEH: return a_m_TEH;
317 	case a_THEH: return a_m_THEH;
318 	case a_JEEM: return a_m_JEEM;
319 	case a_HAH: return a_m_HAH;
320 	case a_KHAH: return a_m_KHAH;
321 	case a_DAL: return a_f_DAL;	/* exception */
322 	case a_THAL: return a_f_THAL;	/* exception */
323 	case a_REH: return a_f_REH;	/* exception */
324 	case a_ZAIN: return a_f_ZAIN;	/* exception */
325 	case a_SEEN: return a_m_SEEN;
326 	case a_SHEEN: return a_m_SHEEN;
327 	case a_SAD: return a_m_SAD;
328 	case a_DAD: return a_m_DAD;
329 	case a_TAH: return a_m_TAH;
330 	case a_ZAH: return a_m_ZAH;
331 	case a_AIN: return a_m_AIN;
332 	case a_GHAIN: return a_m_GHAIN;
333 	case a_TATWEEL: return cur_c;	/* exception */
334 	case a_FEH: return a_m_FEH;
335 	case a_QAF: return a_m_QAF;
336 	case a_KAF: return a_m_KAF;
337 	case a_LAM: return a_m_LAM;
338 	case a_MEEM: return a_m_MEEM;
339 	case a_NOON: return a_m_NOON;
340 	case a_HEH: return a_m_HEH;
341 	case a_WAW: return a_f_WAW;	/* exception */
342 	case a_ALEF_MAKSURA: return a_f_ALEF_MAKSURA;	/* exception */
343 	case a_YEH: return a_m_YEH;
344     }
345     return 0;
346 }
347 
348 
349 /*
350  * Change shape - from ISO-8859-6/Isolated to final
351  */
352     static int
353 chg_c_a2f(int cur_c)
354 {
355     /* NOTE: these encodings need to be accounted for
356      * a_f_ALEF_MADDA;
357      * a_f_ALEF_HAMZA_ABOVE;
358      * a_f_ALEF_HAMZA_BELOW;
359      * a_f_LAM_ALEF_MADDA_ABOVE;
360      * a_f_LAM_ALEF_HAMZA_ABOVE;
361      * a_f_LAM_ALEF_HAMZA_BELOW;
362      */
363     switch (cur_c)
364     {
365 	case a_HAMZA: return a_s_HAMZA;	/* exception */
366 	case a_ALEF_MADDA: return a_f_ALEF_MADDA;
367 	case a_ALEF_HAMZA_ABOVE: return a_f_ALEF_HAMZA_ABOVE;
368 	case a_WAW_HAMZA: return a_f_WAW_HAMZA;
369 	case a_ALEF_HAMZA_BELOW: return a_f_ALEF_HAMZA_BELOW;
370 	case a_YEH_HAMZA: return a_f_YEH_HAMZA;
371 	case a_ALEF: return a_f_ALEF;
372 	case a_BEH: return a_f_BEH;
373 	case a_TEH_MARBUTA: return a_f_TEH_MARBUTA;
374 	case a_TEH: return a_f_TEH;
375 	case a_THEH: return a_f_THEH;
376 	case a_JEEM: return a_f_JEEM;
377 	case a_HAH: return a_f_HAH;
378 	case a_KHAH: return a_f_KHAH;
379 	case a_DAL: return a_f_DAL;
380 	case a_THAL: return a_f_THAL;
381 	case a_REH: return a_f_REH;
382 	case a_ZAIN: return a_f_ZAIN;
383 	case a_SEEN: return a_f_SEEN;
384 	case a_SHEEN: return a_f_SHEEN;
385 	case a_SAD: return a_f_SAD;
386 	case a_DAD: return a_f_DAD;
387 	case a_TAH: return a_f_TAH;
388 	case a_ZAH: return a_f_ZAH;
389 	case a_AIN: return a_f_AIN;
390 	case a_GHAIN: return a_f_GHAIN;
391 	case a_TATWEEL:	return cur_c;	/* exception */
392 	case a_FEH: return a_f_FEH;
393 	case a_QAF: return a_f_QAF;
394 	case a_KAF: return a_f_KAF;
395 	case a_LAM: return a_f_LAM;
396 	case a_MEEM: return a_f_MEEM;
397 	case a_NOON: return a_f_NOON;
398 	case a_HEH: return a_f_HEH;
399 	case a_WAW: return a_f_WAW;
400 	case a_ALEF_MAKSURA: return a_f_ALEF_MAKSURA;
401 	case a_YEH: return a_f_YEH;
402     }
403     return 0;
404 }
405 
406 
407 /*
408  * Change shape - from Initial to Medial
409  * This code is unreachable, because for the relevant characters ARABIC_CHAR()
410  * is FALSE;
411  */
412 #if 0
413     static int
414 chg_c_i2m(int cur_c)
415 {
416     switch (cur_c)
417     {
418 	case a_i_YEH_HAMZA: return a_m_YEH_HAMZA;
419 	case a_i_BEH: return a_m_BEH;
420 	case a_i_TEH: return a_m_TEH;
421 	case a_i_THEH: return a_m_THEH;
422 	case a_i_JEEM: return a_m_JEEM;
423 	case a_i_HAH: return a_m_HAH;
424 	case a_i_KHAH: return a_m_KHAH;
425 	case a_i_SEEN: return a_m_SEEN;
426 	case a_i_SHEEN: return a_m_SHEEN;
427 	case a_i_SAD: return a_m_SAD;
428 	case a_i_DAD: return a_m_DAD;
429 	case a_i_TAH: return a_m_TAH;
430 	case a_i_ZAH: return a_m_ZAH;
431 	case a_i_AIN: return a_m_AIN;
432 	case a_i_GHAIN: return a_m_GHAIN;
433 	case a_i_FEH: return a_m_FEH;
434 	case a_i_QAF: return a_m_QAF;
435 	case a_i_KAF: return a_m_KAF;
436 	case a_i_LAM: return a_m_LAM;
437 	case a_i_MEEM: return a_m_MEEM;
438 	case a_i_NOON: return a_m_NOON;
439 	case a_i_HEH: return a_m_HEH;
440 	case a_i_YEH: return a_m_YEH;
441     }
442     return 0;
443 }
444 #endif
445 
446 
447 /*
448  * Change shape - from Final to Medial
449  */
450     static int
451 chg_c_f2m(int cur_c)
452 {
453     switch (cur_c)
454     {
455 	/* NOTE: these encodings are multi-positional, no ?
456 	 * case a_f_ALEF_MADDA:
457 	 * case a_f_ALEF_HAMZA_ABOVE:
458 	 * case a_f_ALEF_HAMZA_BELOW:
459 	 */
460 	case a_f_YEH_HAMZA: return a_m_YEH_HAMZA;
461 	case a_f_WAW_HAMZA:		/* exceptions */
462 	case a_f_ALEF:
463 	case a_f_TEH_MARBUTA:
464 	case a_f_DAL:
465 	case a_f_THAL:
466 	case a_f_REH:
467 	case a_f_ZAIN:
468 	case a_f_WAW:
469 	case a_f_ALEF_MAKSURA:
470 		return cur_c;
471 	case a_f_BEH: return a_m_BEH;
472 	case a_f_TEH: return a_m_TEH;
473 	case a_f_THEH: return a_m_THEH;
474 	case a_f_JEEM: return a_m_JEEM;
475 	case a_f_HAH: return a_m_HAH;
476 	case a_f_KHAH: return a_m_KHAH;
477 	case a_f_SEEN: return a_m_SEEN;
478 	case a_f_SHEEN: return a_m_SHEEN;
479 	case a_f_SAD: return a_m_SAD;
480 	case a_f_DAD: return a_m_DAD;
481 	case a_f_TAH: return a_m_TAH;
482 	case a_f_ZAH: return a_m_ZAH;
483 	case a_f_AIN: return a_m_AIN;
484 	case a_f_GHAIN: return a_m_GHAIN;
485 	case a_f_FEH: return a_m_FEH;
486 	case a_f_QAF: return a_m_QAF;
487 	case a_f_KAF: return a_m_KAF;
488 	case a_f_LAM: return a_m_LAM;
489 	case a_f_MEEM: return a_m_MEEM;
490 	case a_f_NOON: return a_m_NOON;
491 	case a_f_HEH: return a_m_HEH;
492 	case a_f_YEH: return a_m_YEH;
493 
494 	/* NOTE: these encodings are multi-positional, no ?
495 	 * case a_f_LAM_ALEF_MADDA_ABOVE:
496 	 * case a_f_LAM_ALEF_HAMZA_ABOVE:
497 	 * case a_f_LAM_ALEF_HAMZA_BELOW:
498 	 * case a_f_LAM_ALEF:
499 	 */
500     }
501     return 0;
502 }
503 
504 
505 /*
506  * Change shape - from Combination (2 char) to an Isolated
507  */
508     static int
509 chg_c_laa2i(int hid_c)
510 {
511     switch (hid_c)
512     {
513 	case a_ALEF_MADDA: return a_s_LAM_ALEF_MADDA_ABOVE;
514 	case a_ALEF_HAMZA_ABOVE: return a_s_LAM_ALEF_HAMZA_ABOVE;
515 	case a_ALEF_HAMZA_BELOW: return a_s_LAM_ALEF_HAMZA_BELOW;
516 	case a_ALEF: return a_s_LAM_ALEF;
517     }
518     return 0;
519 }
520 
521 
522 /*
523  * Change shape - from Combination-Isolated to Final
524  */
525     static int
526 chg_c_laa2f(int hid_c)
527 {
528     switch (hid_c)
529     {
530 	case a_ALEF_MADDA: return a_f_LAM_ALEF_MADDA_ABOVE;
531 	case a_ALEF_HAMZA_ABOVE: return a_f_LAM_ALEF_HAMZA_ABOVE;
532 	case a_ALEF_HAMZA_BELOW: return a_f_LAM_ALEF_HAMZA_BELOW;
533 	case a_ALEF: return a_f_LAM_ALEF;
534     }
535     return 0;
536 }
537 
538 /*
539  * Do "half-shaping" on character "c".  Return zero if no shaping.
540  */
541     static int
542 half_shape(int c)
543 {
544     if (A_is_a(c))
545 	return chg_c_a2i(c);
546     if (A_is_valid(c) && A_is_f(c))
547 	return chg_c_f2m(c);
548     return 0;
549 }
550 
551 /*
552  * Do Arabic shaping on character "c".  Returns the shaped character.
553  * out:    "ccp" points to the first byte of the character to be shaped.
554  * in/out: "c1p" points to the first composing char for "c".
555  * in:     "prev_c"  is the previous character (not shaped)
556  * in:     "prev_c1" is the first composing char for the previous char
557  *		     (not shaped)
558  * in:     "next_c"  is the next character (not shaped).
559  */
560     int
561 arabic_shape(
562     int		c,
563     int		*ccp,
564     int		*c1p,
565     int		prev_c,
566     int		prev_c1,
567     int		next_c)
568 {
569     int		curr_c;
570     int		shape_c;
571     int		curr_laa;
572     int		prev_laa;
573 
574     /* Deal only with Arabic character, pass back all others */
575     if (!A_is_ok(c))
576 	return c;
577 
578     /* half-shape current and previous character */
579     shape_c = half_shape(prev_c);
580 
581     /* Save away current character */
582     curr_c = c;
583 
584     curr_laa = A_firstc_laa(c, *c1p);
585     prev_laa = A_firstc_laa(prev_c, prev_c1);
586 
587     if (curr_laa)
588     {
589 	if (A_is_valid(prev_c) && !A_is_f(shape_c)
590 					 && !A_is_s(shape_c) && !prev_laa)
591 	    curr_c = chg_c_laa2f(curr_laa);
592 	else
593 	    curr_c = chg_c_laa2i(curr_laa);
594 
595 	/* Remove the composing character */
596 	*c1p = 0;
597     }
598     else if (!A_is_valid(prev_c) && A_is_valid(next_c))
599 	curr_c = chg_c_a2i(c);
600     else if (!shape_c || A_is_f(shape_c) || A_is_s(shape_c) || prev_laa)
601 	curr_c = A_is_valid(next_c) ? chg_c_a2i(c) : chg_c_a2s(c);
602     else if (A_is_valid(next_c))
603 #if 0
604 	curr_c = A_is_iso(c) ? chg_c_a2m(c) : chg_c_i2m(c);
605 #else
606 	curr_c = A_is_iso(c) ? chg_c_a2m(c) : 0;
607 #endif
608     else if (A_is_valid(prev_c))
609 	curr_c = chg_c_a2f(c);
610     else
611 	curr_c = chg_c_a2s(c);
612 
613     /* Sanity check -- curr_c should, in the future, never be 0.
614      * We should, in the future, insert a fatal error here. */
615     if (curr_c == NUL)
616 	curr_c = c;
617 
618     if (curr_c != c && ccp != NULL)
619     {
620 	char_u buf[MB_MAXBYTES + 1];
621 
622 	/* Update the first byte of the character. */
623 	(*mb_char2bytes)(curr_c, buf);
624 	*ccp = buf[0];
625     }
626 
627     /* Return the shaped character */
628     return curr_c;
629 }
630 
631 
632 /*
633  * A_firstc_laa returns first character of LAA combination if it exists
634  */
635     static int
636 A_firstc_laa(
637     int c,	/* base character */
638     int c1)	/* first composing character */
639 {
640     if (c1 != NUL && c == a_LAM && !A_is_harakat(c1))
641 	return c1;
642     return 0;
643 }
644 
645 
646 /*
647  * A_is_harakat returns TRUE if 'c' is an Arabic Harakat character
648  *		(harakat/tanween)
649  */
650     static int
651 A_is_harakat(int c)
652 {
653     return (c >= a_FATHATAN && c <= a_SUKUN);
654 }
655 
656 
657 /*
658  * A_is_iso returns TRUE if 'c' is an Arabic ISO-8859-6 character
659  *		(alphabet/number/punctuation)
660  */
661     static int
662 A_is_iso(int c)
663 {
664     return ((c >= a_HAMZA && c <= a_GHAIN)
665 	    || (c >= a_TATWEEL && c <= a_HAMZA_BELOW)
666 	    || c == a_MINI_ALEF);
667 }
668 
669 
670 /*
671  * A_is_formb returns TRUE if 'c' is an Arabic 10646-1 FormB character
672  *		(alphabet/number/punctuation)
673  */
674     static int
675 A_is_formb(int c)
676 {
677     return ((c >= a_s_FATHATAN && c <= a_s_DAMMATAN)
678 	    || c == a_s_KASRATAN
679 	    || (c >= a_s_FATHA && c <= a_f_LAM_ALEF)
680 	    || c == a_BYTE_ORDER_MARK);
681 }
682 
683 
684 /*
685  * A_is_ok returns TRUE if 'c' is an Arabic 10646 (8859-6 or Form-B)
686  */
687     static int
688 A_is_ok(int c)
689 {
690     return (A_is_iso(c) || A_is_formb(c));
691 }
692 
693 
694 /*
695  * A_is_valid returns TRUE if 'c' is an Arabic 10646 (8859-6 or Form-B)
696  *		with some exceptions/exclusions
697  */
698     static int
699 A_is_valid(int c)
700 {
701     return (A_is_ok(c) && !A_is_special(c));
702 }
703 
704 
705 /*
706  * A_is_special returns TRUE if 'c' is not a special Arabic character.
707  *		Specials don't adhere to most of the rules.
708  */
709     static int
710 A_is_special(int c)
711 {
712     return (c == a_HAMZA || c == a_s_HAMZA);
713 }
714 
715 #endif /* FEAT_ARABIC */
716