lcDefConv.c revision 818534a1
11.1Sriastrad/* 21.1Sriastrad * Copyright 1992, 1993 by TOSHIBA Corp. 31.1Sriastrad * 41.1Sriastrad * Permission to use, copy, modify, and distribute this software and its 51.1Sriastrad * documentation for any purpose and without fee is hereby granted, provided 61.1Sriastrad * that the above copyright notice appear in all copies and that both that 71.1Sriastrad * copyright notice and this permission notice appear in supporting 81.1Sriastrad * documentation, and that the name of TOSHIBA not be used in advertising 91.1Sriastrad * or publicity pertaining to distribution of the software without specific, 101.1Sriastrad * written prior permission. TOSHIBA make no representations about the 111.1Sriastrad * suitability of this software for any purpose. It is provided "as is" 121.1Sriastrad * without express or implied warranty. 131.1Sriastrad * 141.1Sriastrad * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 151.1Sriastrad * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 161.1Sriastrad * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 171.1Sriastrad * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 181.1Sriastrad * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 191.1Sriastrad * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 201.1Sriastrad * SOFTWARE. 211.1Sriastrad * 221.1Sriastrad * Author: Katsuhisa Yano TOSHIBA Corp. 231.1Sriastrad * mopi@osa.ilab.toshiba.co.jp 241.1Sriastrad */ 251.1Sriastrad/* 261.1Sriastrad * 2000 271.1Sriastrad * Modifier: Ivan Pascal The XFree86 Project 281.1Sriastrad */ 291.1Sriastrad 301.1Sriastrad/* 311.1Sriastrad * The default locale loader. 321.1Sriastrad * Supports: one byte per char (iso8859 like) locales. 331.1Sriastrad * How: converts bytes to wide characters in a 1:1 manner. 341.1Sriastrad * Platforms: all systems. 351.1Sriastrad */ 361.1Sriastrad 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#if !defined(Lynx_22) && !defined(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 = (const char *) *from; 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 while (*from_left && *to_left) { 161 (*from_left)--; 162 if (state->MBtoWC (state, src++, dst)) { 163 dst++; 164 (*to_left)--; 165 } else { 166 unconv++; 167 } 168 } 169 *from = (XPointer) src; 170 *to = (XPointer) dst; 171 return unconv; 172} 173 174static int 175def_wcstombs( 176 XlcConv conv, 177 XPointer *from, 178 int *from_left, 179 XPointer *to, 180 int *to_left, 181 XPointer *args, 182 int num_args) 183{ 184 const wchar_t *src = (const wchar_t *) * from; 185 char *dst = (char *) *to; 186 State state = (State) conv->state; 187 char ch[MB_LEN_MAX]; 188 int unconv = 0; 189 190 if (from == NULL || *from == NULL) 191 return 0; 192 193 while (*from_left && *to_left) { 194 (*from_left)--; 195 if (state->WCtoMB (state, *src++, ch)) { 196 *dst++ = *ch; 197 (*to_left)--; 198 } else { 199 unconv++; 200 } 201 } 202 *from = (XPointer) src; 203 *to = (XPointer) dst; 204 return unconv; 205} 206 207static int 208mbstostr( 209 XlcConv conv, 210 XPointer *from, 211 int *from_left, 212 XPointer *to, 213 int *to_left, 214 XPointer *args, 215 int num_args) 216{ 217 const char *src = (const char *) *from; 218 char *dst = (char *) *to; 219 CodeSet codeset; 220 State state = (State) conv->state; 221 char ch; 222 int unconv = 0; 223 224 if (from == NULL || *from == NULL) 225 return 0; 226 227 while (*from_left && *to_left) { 228 ch = *src++; 229 (*from_left)--; 230 231 codeset = (ch & GR) ? state->GR_codeset : state->GL_codeset; 232 if (codeset && codeset->string_encoding) { 233 *dst++ = ch; 234 (*to_left)--; 235 } else { 236 unconv++; 237 } 238 } 239 *from = (XPointer) src; 240 *to = (XPointer) dst; 241 return unconv; 242} 243 244static int 245wcstostr( 246 XlcConv conv, 247 XPointer *from, 248 int *from_left, 249 XPointer *to, 250 int *to_left, 251 XPointer *args, 252 int num_args) 253{ 254 const wchar_t *src = (const wchar_t *) *from; 255 char *dst = (char *) *to; 256 CodeSet codeset; 257 State state = (State) conv->state; 258 char ch[MB_LEN_MAX]; 259 int unconv = 0; 260 261 if (from == NULL || *from == NULL) 262 return 0; 263 264 while (*from_left && *to_left) { 265 (*from_left)--; 266 if (state->WCtoMB (state, *src++, ch)) { 267 codeset = (*ch & GR) ? state->GR_codeset : state->GL_codeset; 268 if (codeset && codeset->string_encoding) { 269 *dst++ = *ch; 270 (*to_left)--; 271 } else { 272 unconv++; 273 } 274 } else { 275 unconv++; 276 } 277 } 278 *from = (XPointer) src; 279 *to = (XPointer) dst; 280 return unconv; 281} 282 283static int 284mbstocs( 285 XlcConv conv, 286 XPointer *from, 287 int *from_left, 288 XPointer *to, 289 int *to_left, 290 XPointer *args, 291 int num_args) 292{ 293 const char *src = (const char *) *from; 294 char *dst = (char *) *to; 295 int length; 296 State state = (State) conv->state; 297 char cur_side; 298 int unconv = 0; 299 300 if (from == NULL || *from == NULL) 301 return 0; 302 303 length = min(*from_left, *to_left); 304 305 cur_side = *src & GR; 306 while (length) { 307 if ((char) (*src & GR) != cur_side) 308 break; 309 *dst++ = *src++; 310 length--; 311 } 312 313 if (num_args > 0) { 314 XlcCharSet charset = get_charset(state, cur_side); 315 if (charset) { 316 *((XlcCharSet *) args[0]) = charset; 317 } else { 318 dst = *to; 319 unconv = -1; 320 } 321 } 322 *from_left -= src - (char *) *from; 323 *to_left -= dst - (char *) *to; 324 *from = (XPointer) src; 325 *to = (XPointer) dst; 326 return unconv; 327} 328 329static int 330wcstocs( 331 XlcConv conv, 332 XPointer *from, 333 int *from_left, 334 XPointer *to, 335 int *to_left, 336 XPointer *args, 337 int num_args) 338{ 339 const wchar_t *src = (const wchar_t *) * from; 340 char *dst = (char *) *to; 341 State state = (State) conv->state; 342 char cur_side = 0, ch[MB_LEN_MAX]; 343 int unconv = 0; 344 Bool found = False; 345 346 if (from == NULL || *from == NULL) 347 return 0; 348 349 while (*from_left) { 350 if ((found = state->WCtoMB (state, *src, ch))) 351 break; 352 unconv++; 353 src++; 354 (*from_left)--; 355 } 356 357 if (found) { 358 cur_side = *ch & GR; 359 while (*from_left && *to_left) { 360 (*from_left)--; 361 if (state->WCtoMB (state, *src++, ch)) { 362 if ((char) (*ch & GR) != cur_side) { 363 src--; 364 (*from_left)++; 365 break; 366 } else { 367 *dst++ = *ch; 368 (*to_left)--; 369 } 370 } else { 371 unconv++; 372 } 373 } 374 } else { 375 unconv++; 376 } 377 378 if (num_args > 0) { 379 XlcCharSet charset = get_charset(state, cur_side); 380 if (charset) { 381 *((XlcCharSet *) args[0]) = charset; 382 } else { 383 unconv = -1; 384 } 385 } 386 *from = (XPointer) src; 387 *to = (XPointer) dst; 388 return unconv; 389} 390 391static int 392cstombs( 393 XlcConv conv, 394 XPointer *from, 395 int *from_left, 396 XPointer *to, 397 int *to_left, 398 XPointer *args, 399 int num_args) 400{ 401 const char *src = (const char *) *from; 402 char *dst = (char *) *to; 403 CodeSet codeset; 404 XlcCharSet charset; 405 State state = (State) conv->state; 406 unsigned char cur_side = 0; 407 int i; 408 Bool found = False; 409 410 if (from == NULL || *from == NULL) 411 return 0; 412 413 if (num_args > 0) { 414 charset = (XlcCharSet) args[0]; 415 if (charset == NULL) 416 return -1; 417 } else { 418 return -1; 419 } 420 421 if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) { 422 codeset = state->GL_codeset; 423 if (codeset) { 424 for (i = 0; i < codeset->num_charsets; i++) 425 if (charset == codeset->charset_list[i]) { 426 found = True; 427 cur_side = 0; 428 break; 429 } 430 } 431 } 432 if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) { 433 codeset = state->GR_codeset; 434 if (codeset) { 435 for (i = 0; i < codeset->num_charsets; i++) 436 if (charset == codeset->charset_list[i]) { 437 found = True; 438 cur_side = GR; 439 break; 440 } 441 } 442 } 443 if (found) { 444 int length = min(*from_left, *to_left); 445 while (length) { 446 *dst++ = *src++ | cur_side; 447 length--; 448 } 449 } else { 450 return -1; 451 } 452 453 *from_left -= src - (char *) *from; 454 *to_left -= dst - (char *) *to; 455 *from = (XPointer) src; 456 *to = (XPointer) dst; 457 return 0; 458} 459 460static int 461cstowcs( 462 XlcConv conv, 463 XPointer *from, 464 int *from_left, 465 XPointer *to, 466 int *to_left, 467 XPointer *args, 468 int num_args) 469{ 470 const char *src = (const char *) *from; 471 wchar_t *dst = (wchar_t *) * to; 472 CodeSet codeset; 473 XlcCharSet charset; 474 State state = (State) conv->state; 475 Bool found = False; 476 int i, unconv = 0; 477 unsigned char cur_side = 0; 478 479 if (from == NULL || *from == NULL) 480 return 0; 481 482 if (num_args > 0) { 483 charset = (XlcCharSet) args[0]; 484 if (charset == NULL) 485 return -1; 486 } else { 487 return -1; 488 } 489 490 if ((charset->side == XlcGL) || (charset->side == XlcGLGR)) { 491 codeset = state->GL_codeset; 492 if (codeset) { 493 for (i = 0; i < codeset->num_charsets; i++) 494 if (charset == codeset->charset_list[i]) { 495 found = True; 496 cur_side = 0; 497 break; 498 } 499 } 500 } 501 if (!found && ((charset->side == XlcGR) || (charset->side == XlcGLGR))) { 502 codeset = state->GR_codeset; 503 if (codeset) { 504 for (i = 0; i < codeset->num_charsets; i++) 505 if (charset == codeset->charset_list[i]) { 506 found = True; 507 cur_side = GR; 508 break; 509 } 510 } 511 } 512 if (found) { 513 char ch; 514 while (*from_left && *to_left) { 515 ch = *src++ | cur_side; 516 (*from_left)--; 517 if (state->MBtoWC (state, &ch, dst)) { 518 dst++; 519 (*to_left)--; 520 } else { 521 unconv++; 522 } 523 } 524 } else { 525 return -1; 526 } 527 *from = (XPointer) src; 528 *to = (XPointer) dst; 529 return unconv; 530} 531 532static int 533strtombs( 534 XlcConv conv, 535 XPointer *from, 536 int *from_left, 537 XPointer *to, 538 int *to_left, 539 XPointer *args, 540 int num_args) 541{ 542 const char *src = (const char *) *from; 543 char *dst = (char *) *to; 544 int length; 545 546 if (from == NULL || *from == NULL) 547 return 0; 548 549 length = min(*from_left, *to_left); 550 while (length) { 551 *dst++ = *src++; 552 length--; 553 } 554 555 *from_left -= src - (char *) *from; 556 *to_left -= dst - (char *) *to; 557 *from = (XPointer) src; 558 *to = (XPointer) dst; 559 return 0; 560} 561 562static void 563close_converter( 564 XlcConv conv) 565{ 566 if (conv->state) 567 Xfree(conv->state); 568 569 Xfree(conv); 570} 571 572static XlcConv 573create_conv( 574 XLCd lcd, 575 XlcConvMethods methods) 576{ 577 XlcConv conv; 578 State state; 579 580 conv = Xcalloc(1, sizeof(XlcConvRec)); 581 if (conv == NULL) 582 return (XlcConv) NULL; 583 584 state = Xmalloc(sizeof(StateRec)); 585 if (state == NULL) { 586 close_converter(conv); 587 return (XlcConv) NULL; 588 } 589 state->GL_codeset = XLC_GENERIC(lcd, initial_state_GL); 590 state->GR_codeset = XLC_GENERIC(lcd, initial_state_GR); 591 state->wc_mask = (1 << XLC_GENERIC(lcd, wc_shift_bits)) - 1; 592 state->wc_encode_mask = XLC_GENERIC(lcd, wc_encode_mask); 593 594#ifdef STDCVT 595 if (XLC_GENERIC(lcd, use_stdc_env) == True) 596 state->MBtoWC = &MBtoWCstd; 597 else 598#endif 599 state->MBtoWC = &MBtoWCdef; 600 601#ifdef STDCVT 602 if (XLC_GENERIC(lcd, use_stdc_env) == True) 603 state->WCtoMB = &WCtoMBstd; 604 else 605#endif 606 state->WCtoMB = &WCtoMBdef; 607 608 conv->methods = methods; 609 conv->state = (XPointer) state; 610 611 return conv; 612} 613 614static XlcConvMethodsRec mbstowcs_methods = { 615 close_converter, 616 def_mbstowcs, 617 NULL 618}; 619 620static XlcConv 621open_mbstowcs( 622 XLCd from_lcd, 623 const char *from_type, 624 XLCd to_lcd, 625 const char *to_type) 626{ 627 return create_conv(from_lcd, &mbstowcs_methods); 628} 629 630static XlcConvMethodsRec mbstostr_methods = { 631 close_converter, 632 mbstostr, 633 NULL 634}; 635 636static XlcConv 637open_mbstostr( 638 XLCd from_lcd, 639 const char *from_type, 640 XLCd to_lcd, 641 const char *to_type) 642{ 643 return create_conv(from_lcd, &mbstostr_methods); 644} 645 646static XlcConvMethodsRec mbstocs_methods = { 647 close_converter, 648 mbstocs, 649 NULL 650}; 651 652static XlcConv 653open_mbstocs( 654 XLCd from_lcd, 655 const char *from_type, 656 XLCd to_lcd, 657 const char *to_type) 658{ 659 return create_conv(from_lcd, &mbstocs_methods); 660} 661 662static XlcConvMethodsRec wcstombs_methods = { 663 close_converter, 664 def_wcstombs, 665 NULL 666}; 667 668static XlcConv 669open_wcstombs( 670 XLCd from_lcd, 671 const char *from_type, 672 XLCd to_lcd, 673 const char *to_type) 674{ 675 return create_conv(from_lcd, &wcstombs_methods); 676} 677 678static XlcConvMethodsRec wcstostr_methods = { 679 close_converter, 680 wcstostr, 681 NULL 682}; 683 684static XlcConv 685open_wcstostr( 686 XLCd from_lcd, 687 const char *from_type, 688 XLCd to_lcd, 689 const char *to_type) 690{ 691 return create_conv(from_lcd, &wcstostr_methods); 692} 693 694static XlcConvMethodsRec wcstocs_methods = { 695 close_converter, 696 wcstocs, 697 NULL 698}; 699 700static XlcConv 701open_wcstocs( 702 XLCd from_lcd, 703 const char *from_type, 704 XLCd to_lcd, 705 const char *to_type) 706{ 707 return create_conv(from_lcd, &wcstocs_methods); 708} 709 710static XlcConvMethodsRec strtombs_methods = { 711 close_converter, 712 strtombs, 713 NULL 714}; 715 716static XlcConv 717open_strtombs( 718 XLCd from_lcd, 719 const char *from_type, 720 XLCd to_lcd, 721 const char *to_type) 722{ 723 return create_conv(from_lcd, &strtombs_methods); 724} 725 726static XlcConvMethodsRec cstombs_methods = { 727 close_converter, 728 cstombs, 729 NULL 730}; 731 732static XlcConv 733open_cstombs( 734 XLCd from_lcd, 735 const char *from_type, 736 XLCd to_lcd, 737 const char *to_type) 738{ 739 return create_conv(from_lcd, &cstombs_methods); 740} 741 742static XlcConvMethodsRec cstowcs_methods = { 743 close_converter, 744 cstowcs, 745 NULL 746}; 747 748static XlcConv 749open_cstowcs( 750 XLCd from_lcd, 751 const char *from_type, 752 XLCd to_lcd, 753 const char *to_type) 754{ 755 return create_conv(from_lcd, &cstowcs_methods); 756} 757 758XLCd 759_XlcDefaultLoader( 760 const char *name) 761{ 762 XLCd lcd; 763 764 lcd = _XlcCreateLC(name, _XlcGenericMethods); 765 if (lcd == NULL) 766 return lcd; 767 768 if (XLC_PUBLIC(lcd, mb_cur_max) != 1){ 769 _XlcDestroyLC(lcd); 770 return (XLCd) NULL; 771 } 772 773 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar, open_mbstowcs); 774 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNString, open_mbstostr); 775 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs); 776 _XlcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbstocs); 777 778 _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte, open_wcstombs); 779 _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNString, open_wcstostr); 780 _XlcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs); 781 782 _XlcSetConverter(lcd, XlcNString, lcd, XlcNMultiByte, open_strtombs); 783 _XlcSetConverter(lcd, XlcNString, lcd, XlcNWideChar, open_mbstowcs); 784 785 _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs); 786 _XlcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs); 787 788 _XlcAddUtf8Converters(lcd); 789 790 return lcd; 791} 792