1/* 2 * Copyright 1992, 1993 by TOSHIBA Corp. 3 * 4 * Permission to use, copy, modify, and distribute this software and its 5 * documentation for any purpose and without fee is hereby granted, provided 6 * that the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of TOSHIBA not be used in advertising 9 * or publicity pertaining to distribution of the software without specific, 10 * written prior permission. TOSHIBA make no representations about the 11 * suitability of this software for any purpose. It is provided "as is" 12 * without express or implied warranty. 13 * 14 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20 * SOFTWARE. 21 * 22 * Author: Katsuhisa Yano TOSHIBA Corp. 23 * mopi@osa.ilab.toshiba.co.jp 24 */ 25/* 26 * 2000 27 * Modifier: Ivan Pascal The XFree86 Project 28 */ 29 30/* 31 * The default locale loader. 32 * Supports: one byte per char (iso8859 like) locales. 33 * How: converts bytes to wide characters in a 1:1 manner. 34 * Platforms: all systems. 35 */ 36 37#ifdef HAVE_CONFIG_H 38#include <config.h> 39#endif 40#include "Xlibint.h" 41#include "XlcGeneric.h" 42 43#ifndef MB_LEN_MAX 44#define MB_LEN_MAX 6 45#endif 46 47#ifndef X_LOCALE 48#define STDCVT 49#endif 50 51#define GR 0x80 52#define GL 0x7f 53 54typedef struct _StateRec *State; 55typedef struct _StateRec { 56 CodeSet GL_codeset; 57 CodeSet GR_codeset; 58 wchar_t wc_mask; 59 wchar_t wc_encode_mask; 60 Bool (*MBtoWC) (State state, const char *ch, wchar_t *wc); 61 Bool (*WCtoMB) (State state, wchar_t wc, char *ch); 62} StateRec; 63 64static 65Bool MBtoWCdef( 66 State state, 67 const char *ch, 68 wchar_t *wc) 69{ 70 wchar_t wc_encoding; 71 CodeSet codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset; 72 if (!codeset) 73 return False; 74 wc_encoding = codeset->wc_encoding; 75 *wc = ((wchar_t) *ch & state->wc_mask) | wc_encoding; 76 return True; 77} 78 79#ifdef STDCVT 80static 81Bool MBtoWCstd( 82 State state, 83 const char *ch, 84 wchar_t *wc) 85{ 86 return (mbtowc(wc, ch, 1) == 1); 87} 88#endif 89 90static 91Bool WCtoMBdef( 92 State state, 93 wchar_t wc, 94 char *ch) 95{ 96 wchar_t wc_encoding = wc & state->wc_encode_mask; 97 CodeSet codeset; 98 99 codeset = state->GL_codeset; 100 if (codeset && (wc_encoding == codeset->wc_encoding)) { 101 *ch = wc & state->wc_mask; 102 return True; 103 } 104 codeset = state->GR_codeset; 105 if (codeset && (wc_encoding == codeset->wc_encoding)) { 106 *ch = (wc & state->wc_mask) | GR; 107 return True; 108 } 109 return False; 110} 111 112#ifdef STDCVT 113static 114Bool WCtoMBstd( 115 State state, 116 wchar_t wc, 117 char *ch) 118{ 119 return (wctomb(ch, wc) == 1); 120} 121#endif 122 123static 124XlcCharSet get_charset( 125 State state, 126 char side) 127{ 128 CodeSet codeset = side ? state->GR_codeset : state->GL_codeset; 129 if (codeset) { 130 int i; 131 XlcCharSet charset; 132 for (i = 0; i < codeset->num_charsets; i++) { 133 charset = codeset->charset_list[i]; 134 if (*charset->ct_sequence != '\0') 135 return charset; 136 } 137 return *(codeset->charset_list); 138 } 139 return (XlcCharSet) NULL; 140} 141 142static int 143def_mbstowcs( 144 XlcConv conv, 145 XPointer *from, 146 int *from_left, 147 XPointer *to, 148 int *to_left, 149 XPointer *args, 150 int num_args) 151{ 152 const char *src; 153 wchar_t *dst = (wchar_t *) *to; 154 State state = (State) conv->state; 155 int unconv = 0; 156 157 if (from == NULL || *from == NULL) 158 return 0; 159 160 src = (const char *) *from; 161 162 while (*from_left && *to_left) { 163 (*from_left)--; 164 if (state->MBtoWC (state, src++, dst)) { 165 dst++; 166 (*to_left)--; 167 } else { 168 unconv++; 169 } 170 } 171 *from = (XPointer) src; 172 *to = (XPointer) dst; 173 return unconv; 174} 175 176static int 177def_wcstombs( 178 XlcConv conv, 179 XPointer *from, 180 int *from_left, 181 XPointer *to, 182 int *to_left, 183 XPointer *args, 184 int num_args) 185{ 186 const wchar_t *src; 187 char *dst = (char *) *to; 188 State state = (State) conv->state; 189 char ch[MB_LEN_MAX]; 190 int unconv = 0; 191 192 if (from == NULL || *from == NULL) 193 return 0; 194 195 src = (const wchar_t *) *from; 196 197 while (*from_left && *to_left) { 198 (*from_left)--; 199 if (state->WCtoMB (state, *src++, ch)) { 200 *dst++ = *ch; 201 (*to_left)--; 202 } else { 203 unconv++; 204 } 205 } 206 *from = (XPointer) src; 207 *to = (XPointer) dst; 208 return unconv; 209} 210 211static int 212mbstostr( 213 XlcConv conv, 214 XPointer *from, 215 int *from_left, 216 XPointer *to, 217 int *to_left, 218 XPointer *args, 219 int num_args) 220{ 221 const char *src; 222 char *dst = (char *) *to; 223 CodeSet codeset; 224 State state = (State) conv->state; 225 char ch; 226 int unconv = 0; 227 228 if (from == NULL || *from == NULL) 229 return 0; 230 231 src = (const char *) *from; 232 233 while (*from_left && *to_left) { 234 ch = *src++; 235 (*from_left)--; 236 237 codeset = (ch & GR) ? state->GR_codeset : state->GL_codeset; 238 if (codeset && codeset->string_encoding) { 239 *dst++ = ch; 240 (*to_left)--; 241 } else { 242 unconv++; 243 } 244 } 245 *from = (XPointer) src; 246 *to = (XPointer) dst; 247 return unconv; 248} 249 250static int 251wcstostr( 252 XlcConv conv, 253 XPointer *from, 254 int *from_left, 255 XPointer *to, 256 int *to_left, 257 XPointer *args, 258 int num_args) 259{ 260 const wchar_t *src; 261 char *dst = (char *) *to; 262 CodeSet codeset; 263 State state = (State) conv->state; 264 char ch[MB_LEN_MAX]; 265 int unconv = 0; 266 267 if (from == NULL || *from == NULL) 268 return 0; 269 270 src = (const wchar_t *) *from; 271 272 while (*from_left && *to_left) { 273 (*from_left)--; 274 if (state->WCtoMB (state, *src++, ch)) { 275 codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset; 276 if (codeset && codeset->string_encoding) { 277 *dst++ = *ch; 278 (*to_left)--; 279 } else { 280 unconv++; 281 } 282 } else { 283 unconv++; 284 } 285 } 286 *from = (XPointer) src; 287 *to = (XPointer) dst; 288 return unconv; 289} 290 291static int 292mbstocs( 293 XlcConv conv, 294 XPointer *from, 295 int *from_left, 296 XPointer *to, 297 int *to_left, 298 XPointer *args, 299 int num_args) 300{ 301 const char *src; 302 char *dst = (char *) *to; 303 int length; 304 State state = (State) conv->state; 305 char cur_side; 306 int unconv = 0; 307 308 if (from == NULL || *from == NULL) 309 return 0; 310 311 src = (const char *) *from; 312 length = min(*from_left, *to_left); 313 314 cur_side = *src & GR; 315 while (length) { 316 if ((char) (*src & GR) != cur_side) 317 break; 318 *dst++ = *src++; 319 length--; 320 } 321 322 if (num_args > 0) { 323 XlcCharSet charset = get_charset(state, cur_side); 324 if (charset) { 325 *((XlcCharSet *) args[0]) = charset; 326 } else { 327 dst = *to; 328 unconv = -1; 329 } 330 } 331 *from_left -= src - (char *) *from; 332 *to_left -= dst - (char *) *to; 333 *from = (XPointer) src; 334 *to = (XPointer) dst; 335 return unconv; 336} 337 338static int 339wcstocs( 340 XlcConv conv, 341 XPointer *from, 342 int *from_left, 343 XPointer *to, 344 int *to_left, 345 XPointer *args, 346 int num_args) 347{ 348 const wchar_t *src; 349 char *dst = (char *) *to; 350 State state = (State) conv->state; 351 char cur_side = 0, ch[MB_LEN_MAX]; 352 int unconv = 0; 353 Bool found = False; 354 355 if (from == NULL || *from == NULL) 356 return 0; 357 358 src = (const wchar_t *) *from; 359 360 while (*from_left) { 361 if ((found = state->WCtoMB (state, *src, ch))) 362 break; 363 unconv++; 364 src++; 365 (*from_left)--; 366 } 367 368 if (found) { 369 cur_side = *ch & GR; 370 while (*from_left && *to_left) { 371 (*from_left)--; 372 if (state->WCtoMB (state, *src++, ch)) { 373 if ((char) (*ch & GR) != cur_side) { 374 src--; 375 (*from_left)++; 376 break; 377 } else { 378 *dst++ = *ch; 379 (*to_left)--; 380 } 381 } else { 382 unconv++; 383 } 384 } 385 } else { 386 unconv++; 387 } 388 389 if (num_args > 0) { 390 XlcCharSet charset = get_charset(state, cur_side); 391 if (charset) { 392 *((XlcCharSet *) args[0]) = charset; 393 } else { 394 unconv = -1; 395 } 396 } 397 *from = (XPointer) src; 398 *to = (XPointer) dst; 399 return unconv; 400} 401 402static int 403cstombs( 404 XlcConv conv, 405 XPointer *from, 406 int *from_left, 407 XPointer *to, 408 int *to_left, 409 XPointer *args, 410 int num_args) 411{ 412 const char *src; 413 char *dst = (char *) *to; 414 CodeSet codeset; 415 XlcCharSet charset; 416 State state = (State) conv->state; 417 unsigned char cur_side = 0; 418 int i; 419 Bool found = False; 420 421 if (from == NULL || *from == NULL) 422 return 0; 423 424 src = (const char *) *from; 425 426 if (num_args > 0) { 427 charset = (XlcCharSet) args[0]; 428 if (charset == NULL) 429 return -1; 430 } else { 431 return -1; 432 } 433 434 if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) { 435 codeset = state->GL_codeset; 436 if (codeset) { 437 for (i = 0; i < codeset->num_charsets; i++) 438 if (charset == codeset->charset_list[i]) { 439 found = True; 440 cur_side = 0; 441 break; 442 } 443 } 444 } 445 if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) { 446 codeset = state->GR_codeset; 447 if (codeset) { 448 for (i = 0; i < codeset->num_charsets; i++) 449 if (charset == codeset->charset_list[i]) { 450 found = True; 451 cur_side = GR; 452 break; 453 } 454 } 455 } 456 if (found) { 457 int length = min(*from_left, *to_left); 458 while (length) { 459 *dst++ = *src++ | cur_side; 460 length--; 461 } 462 } else { 463 return -1; 464 } 465 466 *from_left -= src - (char *) *from; 467 *to_left -= dst - (char *) *to; 468 *from = (XPointer) src; 469 *to = (XPointer) dst; 470 return 0; 471} 472 473static int 474cstowcs( 475 XlcConv conv, 476 XPointer *from, 477 int *from_left, 478 XPointer *to, 479 int *to_left, 480 XPointer *args, 481 int num_args) 482{ 483 const char *src; 484 wchar_t *dst = (wchar_t *) *to; 485 CodeSet codeset; 486 XlcCharSet charset; 487 State state = (State) conv->state; 488 Bool found = False; 489 int i, unconv = 0; 490 unsigned char cur_side = 0; 491 492 if (from == NULL || *from == NULL) 493 return 0; 494 495 src = (const char *) *from; 496 497 if (num_args > 0) { 498 charset = (XlcCharSet) args[0]; 499 if (charset == NULL) 500 return -1; 501 } else { 502 return -1; 503 } 504 505 if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) { 506 codeset = state->GL_codeset; 507 if (codeset) { 508 for (i = 0; i < codeset->num_charsets; i++) 509 if (charset == codeset->charset_list[i]) { 510 found = True; 511 cur_side = 0; 512 break; 513 } 514 } 515 } 516 if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) { 517 codeset = state->GR_codeset; 518 if (codeset) { 519 for (i = 0; i < codeset->num_charsets; i++) 520 if (charset == codeset->charset_list[i]) { 521 found = True; 522 cur_side = GR; 523 break; 524 } 525 } 526 } 527 if (found) { 528 char ch; 529 while (*from_left && *to_left) { 530 ch = *src++ | cur_side; 531 (*from_left)--; 532 if (state->MBtoWC (state, &ch, dst)) { 533 dst++; 534 (*to_left)--; 535 } else { 536 unconv++; 537 } 538 } 539 } else { 540 return -1; 541 } 542 *from = (XPointer) src; 543 *to = (XPointer) dst; 544 return unconv; 545} 546 547static int 548strtombs( 549 XlcConv conv, 550 XPointer *from, 551 int *from_left, 552 XPointer *to, 553 int *to_left, 554 XPointer *args, 555 int num_args) 556{ 557 const char *src; 558 char *dst = (char *) *to; 559 int length; 560 561 if (from == NULL || *from == NULL) 562 return 0; 563 564 src = (const char *) *from; 565 length = min(*from_left, *to_left); 566 while (length) { 567 *dst++ = *src++; 568 length--; 569 } 570 571 *from_left -= src - (char *) *from; 572 *to_left -= dst - (char *) *to; 573 *from = (XPointer) src; 574 *to = (XPointer) dst; 575 return 0; 576} 577 578static void 579close_converter( 580 XlcConv conv) 581{ 582 583 Xfree(conv->state); 584 Xfree(conv); 585} 586 587static XlcConv 588create_conv( 589 XLCd lcd, 590 XlcConvMethods methods) 591{ 592 XlcConv conv; 593 State state; 594 595 conv = Xcalloc(1, sizeof(XlcConvRec)); 596 if (conv == NULL) 597 return (XlcConv) NULL; 598 599 state = Xmalloc(sizeof(StateRec)); 600 if (state == NULL) { 601 close_converter(conv); 602 return (XlcConv) NULL; 603 } 604 state->GL_codeset = XLC_GENERIC(lcd, initial_state_GL); 605 state->GR_codeset = XLC_GENERIC(lcd, initial_state_GR); 606 state->wc_mask = (1 << XLC_GENERIC(lcd, wc_shift_bits)) - 1; 607 state->wc_encode_mask = XLC_GENERIC(lcd, wc_encode_mask); 608 609#ifdef STDCVT 610 if (XLC_GENERIC(lcd, use_stdc_env) == True) 611 state->MBtoWC = &MBtoWCstd; 612 else 613#endif 614 state->MBtoWC = &MBtoWCdef; 615 616#ifdef STDCVT 617 if (XLC_GENERIC(lcd, use_stdc_env) == True) 618 state->WCtoMB = &WCtoMBstd; 619 else 620#endif 621 state->WCtoMB = &WCtoMBdef; 622 623 conv->methods = methods; 624 conv->state = (XPointer) state; 625 626 return conv; 627} 628 629static XlcConvMethodsRec mbstowcs_methods = { 630 close_converter, 631 def_mbstowcs, 632 NULL 633}; 634 635static XlcConv 636open_mbstowcs( 637 XLCd from_lcd, 638 const char *from_type, 639 XLCd to_lcd, 640 const char *to_type) 641{ 642 return create_conv(from_lcd, &mbstowcs_methods); 643} 644 645static XlcConvMethodsRec mbstostr_methods = { 646 close_converter, 647 mbstostr, 648 NULL 649}; 650 651static XlcConv 652open_mbstostr( 653 XLCd from_lcd, 654 const char *from_type, 655 XLCd to_lcd, 656 const char *to_type) 657{ 658 return create_conv(from_lcd, &mbstostr_methods); 659} 660 661static XlcConvMethodsRec mbstocs_methods = { 662 close_converter, 663 mbstocs, 664 NULL 665}; 666 667static XlcConv 668open_mbstocs( 669 XLCd from_lcd, 670 const char *from_type, 671 XLCd to_lcd, 672 const char *to_type) 673{ 674 return create_conv(from_lcd, &mbstocs_methods); 675} 676 677static XlcConvMethodsRec wcstombs_methods = { 678 close_converter, 679 def_wcstombs, 680 NULL 681}; 682 683static XlcConv 684open_wcstombs( 685 XLCd from_lcd, 686 const char *from_type, 687 XLCd to_lcd, 688 const char *to_type) 689{ 690 return create_conv(from_lcd, &wcstombs_methods); 691} 692 693static XlcConvMethodsRec wcstostr_methods = { 694 close_converter, 695 wcstostr, 696 NULL 697}; 698 699static XlcConv 700open_wcstostr( 701 XLCd from_lcd, 702 const char *from_type, 703 XLCd to_lcd, 704 const char *to_type) 705{ 706 return create_conv(from_lcd, &wcstostr_methods); 707} 708 709static XlcConvMethodsRec wcstocs_methods = { 710 close_converter, 711 wcstocs, 712 NULL 713}; 714 715static XlcConv 716open_wcstocs( 717 XLCd from_lcd, 718 const char *from_type, 719 XLCd to_lcd, 720 const char *to_type) 721{ 722 return create_conv(from_lcd, &wcstocs_methods); 723} 724 725static XlcConvMethodsRec strtombs_methods = { 726 close_converter, 727 strtombs, 728 NULL 729}; 730 731static XlcConv 732open_strtombs( 733 XLCd from_lcd, 734 const char *from_type, 735 XLCd to_lcd, 736 const char *to_type) 737{ 738 return create_conv(from_lcd, &strtombs_methods); 739} 740 741static XlcConvMethodsRec cstombs_methods = { 742 close_converter, 743 cstombs, 744 NULL 745}; 746 747static XlcConv 748open_cstombs( 749 XLCd from_lcd, 750 const char *from_type, 751 XLCd to_lcd, 752 const char *to_type) 753{ 754 return create_conv(from_lcd, &cstombs_methods); 755} 756 757static XlcConvMethodsRec cstowcs_methods = { 758 close_converter, 759 cstowcs, 760 NULL 761}; 762 763static XlcConv 764open_cstowcs( 765 XLCd from_lcd, 766 const char *from_type, 767 XLCd to_lcd, 768 const char *to_type) 769{ 770 return create_conv(from_lcd, &cstowcs_methods); 771} 772 773XLCd 774_XlcDefaultLoader( 775 const char *name) 776{ 777 XLCd lcd; 778 779 lcd = _XlcCreateLC(name, _XlcGenericMethods); 780 if (lcd == NULL) 781 return lcd; 782 783 if (XLC_PUBLIC(lcd, mb_cur_max) != 1){ 784 _XlcDestroyLC(lcd); 785 return (XLCd) NULL; 786 } 787 788 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs); 789 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_mbstostr); 790 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs); 791 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbstocs); 792 793 _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs); 794 _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr); 795 _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs); 796 797 _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_strtombs); 798 _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_mbstowcs); 799 800 _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs); 801 _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs); 802 803 _XlcAddUtf8Converters(lcd); 804 805 return lcd; 806} 807