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