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