lcWrap.c revision 0f8248bf
1/* 2 3Copyright 1991, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28/* 29 * Copyright 1991 by the Open Software Foundation 30 * Copyright 1993 by the TOSHIBA Corp. 31 * 32 * Permission to use, copy, modify, distribute, and sell this software and its 33 * documentation for any purpose is hereby granted without fee, provided that 34 * the above copyright notice appear in all copies and that both that 35 * copyright notice and this permission notice appear in supporting 36 * documentation, and that the names of Open Software Foundation and TOSHIBA 37 * not be used in advertising or publicity pertaining to distribution of the 38 * software without specific, written prior permission. Open Software 39 * Foundation and TOSHIBA make no representations about the suitability of this 40 * software for any purpose. It is provided "as is" without express or 41 * implied warranty. 42 * 43 * OPEN SOFTWARE FOUNDATION AND TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO 44 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 45 * FITNESS, IN NO EVENT SHALL OPEN SOFTWARE FOUNDATIONN OR TOSHIBA BE 46 * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 47 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 48 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 49 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 50 * 51 * M. Collins OSF 52 * 53 * Katsuhisa Yano TOSHIBA Corp. 54 */ 55 56#ifdef HAVE_CONFIG_H 57#include <config.h> 58#endif 59#include <stdlib.h> 60#include "Xlibint.h" 61#include "Xlcint.h" 62#include <X11/Xlocale.h> 63#include <X11/Xos.h> 64#ifdef WIN32 65#undef close 66#endif 67#include <X11/Xutil.h> 68#include "XlcPubI.h" 69 70#ifdef XTHREADS 71LockInfoPtr _Xi18n_lock; 72#endif 73 74char * 75XSetLocaleModifiers( 76 const char *modifiers) 77{ 78 XLCd lcd = _XlcCurrentLC(); 79 char *user_mods; 80 char *mapped_mods; 81 82 if (!lcd) 83 return (char *) NULL; 84 if (!modifiers) 85 return lcd->core->modifiers; 86 user_mods = getenv("XMODIFIERS"); 87 mapped_mods = (*lcd->methods->map_modifiers) (lcd, user_mods, modifiers); 88 if (mapped_mods) { 89 Xfree(lcd->core->modifiers); 90 lcd->core->modifiers = mapped_mods; 91 } 92 return mapped_mods; 93} 94 95Bool 96XSupportsLocale(void) 97{ 98 return _XlcCurrentLC() != (XLCd)NULL; 99} 100 101Bool _XlcValidModSyntax( 102 const char * mods, 103 const char * const *valid_mods) 104{ 105 int i; 106 const char * const *ptr; 107 108 while (mods && (*mods == '@')) { 109 mods++; 110 if (*mods == '@') 111 break; 112 for (ptr = valid_mods; *ptr; ptr++) { 113 i = strlen(*ptr); 114 if (strncmp(mods, *ptr, i) || ((mods[i] != '=') 115#ifdef WIN32 116 && (mods[i] != '#') 117#endif 118 )) 119 continue; 120 mods = strchr(mods+i+1, '@'); 121 break; 122 } 123 } 124 return !mods || !*mods; 125} 126 127static const char *im_valid[] = {"im", (const char *)NULL}; 128 129/*ARGSUSED*/ 130char * 131_XlcDefaultMapModifiers( 132 XLCd lcd, 133 const char *user_mods, 134 const char *prog_mods) 135{ 136 int i; 137 char *mods; 138 139 if (!_XlcValidModSyntax(prog_mods, im_valid)) 140 return (char *)NULL; 141 if (!_XlcValidModSyntax(user_mods, im_valid)) 142 return (char *)NULL; 143 i = strlen(prog_mods) + 1; 144 if (user_mods) 145 i += strlen(user_mods); 146 mods = Xmalloc(i); 147 if (mods) { 148 strcpy(mods, prog_mods); 149 if (user_mods) 150 strcat(mods, user_mods); 151#ifdef WIN32 152 { 153 char *s; 154 for (s = mods; (s = strchr(s, '@')); s++) { 155 for (s++; *s && *s != '='; s++) { 156 if (*s == '#') { 157 *s = '='; 158 break; 159 } 160 } 161 } 162 } 163#endif 164 } 165 return mods; 166} 167 168typedef struct _XLCdListRec { 169 struct _XLCdListRec *next; 170 XLCd lcd; 171 int ref_count; 172} XLCdListRec, *XLCdList; 173 174static XLCdList lcd_list = NULL; 175 176typedef struct _XlcLoaderListRec { 177 struct _XlcLoaderListRec *next; 178 XLCdLoadProc proc; 179} XlcLoaderListRec, *XlcLoaderList; 180 181static XlcLoaderList loader_list = NULL; 182 183void 184_XlcRemoveLoader( 185 XLCdLoadProc proc) 186{ 187 XlcLoaderList loader, prev; 188 189 if (loader_list == NULL) 190 return; 191 192 prev = loader = loader_list; 193 if (loader->proc == proc) { 194 loader_list = loader->next; 195 Xfree(loader); 196 return; 197 } 198 199 while ((loader = loader->next)) { 200 if (loader->proc == proc) { 201 prev->next = loader->next; 202 Xfree(loader); 203 return; 204 } 205 prev = loader; 206 } 207 208 return; 209} 210 211Bool 212_XlcAddLoader( 213 XLCdLoadProc proc, 214 XlcPosition position) 215{ 216 XlcLoaderList loader, last; 217 218 _XlcRemoveLoader(proc); /* remove old loader, if exist */ 219 220 loader = Xmalloc(sizeof(XlcLoaderListRec)); 221 if (loader == NULL) 222 return False; 223 224 loader->proc = proc; 225 226 if (loader_list == NULL) 227 position = XlcHead; 228 229 if (position == XlcHead) { 230 loader->next = loader_list; 231 loader_list = loader; 232 } else { 233 last = loader_list; 234 while (last->next) 235 last = last->next; 236 237 loader->next = NULL; 238 last->next = loader; 239 } 240 241 return True; 242} 243 244XLCd 245_XOpenLC( 246 char *name) 247{ 248 XLCd lcd; 249 XlcLoaderList loader; 250 XLCdList cur; 251#if !defined(X_LOCALE) 252 int len; 253 char sinamebuf[256]; 254 char* siname = sinamebuf; 255#endif 256 257 if (name == NULL) { 258 name = setlocale (LC_CTYPE, (char *)NULL); 259#if !defined(X_LOCALE) 260 /* 261 * _XlMapOSLocaleName will return the same string or a substring 262 * of name, so strlen(name) is okay 263 */ 264 if ((len = strlen(name)) >= sizeof sinamebuf) { 265 siname = Xmalloc (len + 1); 266 if (siname == NULL) 267 return NULL; 268 } 269 name = _XlcMapOSLocaleName(name, siname); 270#endif 271 } 272 273 _XLockMutex(_Xi18n_lock); 274 275 /* 276 * search for needed lcd, if found return it 277 */ 278 for (cur = lcd_list; cur; cur = cur->next) { 279 if (!strcmp (cur->lcd->core->name, name)) { 280 lcd = cur->lcd; 281 cur->ref_count++; 282 goto found; 283 } 284 } 285 286 if (!loader_list) 287 _XlcInitLoader(); 288 289 /* 290 * not there, so try to get and add to list 291 */ 292 for (loader = loader_list; loader; loader = loader->next) { 293 lcd = (*loader->proc)(name); 294 if (lcd) { 295 cur = Xmalloc (sizeof(XLCdListRec)); 296 if (cur) { 297 cur->lcd = lcd; 298 cur->ref_count = 1; 299 cur->next = lcd_list; 300 lcd_list = cur; 301 } else { 302 (*lcd->methods->close)(lcd); 303 lcd = (XLCd) NULL; 304 } 305 goto found; 306 } 307 } 308 309 lcd = NULL; 310 311found: 312 _XUnlockMutex(_Xi18n_lock); 313 314#if !defined(X_LOCALE) 315 if (siname != sinamebuf) Xfree(siname); 316#endif 317 318 return lcd; 319} 320 321void 322_XCloseLC( 323 XLCd lcd) 324{ 325 XLCdList cur, *prev; 326 327 for (prev = &lcd_list; (cur = *prev); prev = &cur->next) { 328 if (cur->lcd == lcd) { 329 if (--cur->ref_count < 1) { 330 (*lcd->methods->close)(lcd); 331 *prev = cur->next; 332 Xfree(cur); 333 } 334 break; 335 } 336 } 337 338 if(loader_list) { 339 _XlcDeInitLoader(); 340 loader_list = NULL; 341 } 342} 343 344/* 345 * Get the XLCd for the current locale 346 */ 347 348XLCd 349_XlcCurrentLC(void) 350{ 351 XLCd lcd; 352 static XLCd last_lcd = NULL; 353 354 lcd = _XOpenLC((char *) NULL); 355 356 if (last_lcd) 357 _XCloseLC(last_lcd); 358 359 last_lcd = lcd; 360 361 return lcd; 362} 363 364XrmMethods 365_XrmInitParseInfo( 366 XPointer *state) 367{ 368 XLCd lcd = _XOpenLC((char *) NULL); 369 370 if (lcd == (XLCd) NULL) 371 return (XrmMethods) NULL; 372 373 return (*lcd->methods->init_parse_info)(lcd, state); 374} 375 376int 377XmbTextPropertyToTextList( 378 Display *dpy, 379 const XTextProperty *text_prop, 380 char ***list_ret, 381 int *count_ret) 382{ 383 XLCd lcd = _XlcCurrentLC(); 384 385 if (lcd == NULL) 386 return XLocaleNotSupported; 387 388 return (*lcd->methods->mb_text_prop_to_list)(lcd, dpy, text_prop, list_ret, 389 count_ret); 390} 391 392int 393XwcTextPropertyToTextList( 394 Display *dpy, 395 const XTextProperty *text_prop, 396 wchar_t ***list_ret, 397 int *count_ret) 398{ 399 XLCd lcd = _XlcCurrentLC(); 400 401 if (lcd == NULL) 402 return XLocaleNotSupported; 403 404 return (*lcd->methods->wc_text_prop_to_list)(lcd, dpy, text_prop, list_ret, 405 count_ret); 406} 407 408int 409Xutf8TextPropertyToTextList( 410 Display *dpy, 411 const XTextProperty *text_prop, 412 char ***list_ret, 413 int *count_ret) 414{ 415 XLCd lcd = _XlcCurrentLC(); 416 417 if (lcd == NULL) 418 return XLocaleNotSupported; 419 420 return (*lcd->methods->utf8_text_prop_to_list)(lcd, dpy, text_prop, 421 list_ret, count_ret); 422} 423 424int 425XmbTextListToTextProperty( 426 Display *dpy, 427 char **list, 428 int count, 429 XICCEncodingStyle style, 430 XTextProperty *text_prop) 431{ 432 XLCd lcd = _XlcCurrentLC(); 433 434 if (lcd == NULL) 435 return XLocaleNotSupported; 436 437 return (*lcd->methods->mb_text_list_to_prop)(lcd, dpy, list, count, style, 438 text_prop); 439} 440 441int 442XwcTextListToTextProperty( 443 Display *dpy, 444 wchar_t **list, 445 int count, 446 XICCEncodingStyle style, 447 XTextProperty *text_prop) 448{ 449 XLCd lcd = _XlcCurrentLC(); 450 451 if (lcd == NULL) 452 return XLocaleNotSupported; 453 454 return (*lcd->methods->wc_text_list_to_prop)(lcd, dpy, list, count, style, 455 text_prop); 456} 457 458int 459Xutf8TextListToTextProperty( 460 Display *dpy, 461 char **list, 462 int count, 463 XICCEncodingStyle style, 464 XTextProperty *text_prop) 465{ 466 XLCd lcd = _XlcCurrentLC(); 467 468 if (lcd == NULL) 469 return XLocaleNotSupported; 470 471 return (*lcd->methods->utf8_text_list_to_prop)(lcd, dpy, list, count, 472 style, text_prop); 473} 474 475void 476XwcFreeStringList( 477 wchar_t **list) 478{ 479 XLCd lcd = _XlcCurrentLC(); 480 481 if (lcd == NULL) 482 return; 483 484 (*lcd->methods->wc_free_string_list)(lcd, list); 485} 486 487const char * 488XDefaultString(void) 489{ 490 XLCd lcd = _XlcCurrentLC(); 491 492 if (lcd == NULL) 493 return (char *) NULL; 494 495 return (*lcd->methods->default_string)(lcd); 496} 497 498void 499_XlcCopyFromArg( 500 char *src, 501 char *dst, 502 int size) 503{ 504 if (size == sizeof(long)) 505 *((long *) dst) = (long) src; 506#ifdef LONG64 507 else if (size == sizeof(int)) 508 *((int *) dst) = (int)(long) src; 509#endif 510 else if (size == sizeof(short)) 511 *((short *) dst) = (short)(long) src; 512 else if (size == sizeof(char)) 513 *((char *) dst) = (char)(long) src; 514 else if (size == sizeof(XPointer)) 515 *((XPointer *) dst) = (XPointer) src; 516 else if (size > sizeof(XPointer)) 517 memcpy(dst, (char *) src, size); 518 else 519 memcpy(dst, (char *) &src, size); 520} 521 522void 523_XlcCopyToArg( 524 char *src, 525 char **dst, 526 int size) 527{ 528 /* FIXME: 529 On Big Endian machines, this behaves differently than _XCopyToArg. */ 530 if (size == sizeof(long)) 531 *((long *) *dst) = *((long *) src); 532#ifdef LONG64 533 else if (size == sizeof(int)) 534 *((int *) *dst) = *((int *) src); 535#endif 536 else if (size == sizeof(short)) 537 *((short *) *dst) = *((short *) src); 538 else if (size == sizeof(char)) 539 *((char *) *dst) = *((char *) src); 540 else if (size == sizeof(XPointer)) 541 *((XPointer *) *dst) = *((XPointer *) src); 542 else 543 memcpy(*dst, src, size); 544} 545 546void 547_XlcCountVaList( 548 va_list var, 549 int *count_ret) 550{ 551 int count; 552 553 for (count = 0; va_arg(var, char *); count++) 554 (void)va_arg(var, XPointer); 555 556 *count_ret = count; 557} 558 559void 560_XlcVaToArgList( 561 va_list var, 562 int count, 563 XlcArgList *args_ret) 564{ 565 XlcArgList args; 566 567 *args_ret = args = Xmalloc(sizeof(XlcArg) * count); 568 if (args == (XlcArgList) NULL) 569 return; 570 571 for ( ; count-- > 0; args++) { 572 args->name = va_arg(var, char *); 573 args->value = va_arg(var, XPointer); 574 } 575} 576 577void 578_XlcCompileResourceList( 579 XlcResourceList resources, 580 int num_resources) 581{ 582 for ( ; num_resources-- > 0; resources++) 583 resources->xrm_name = XrmPermStringToQuark(resources->name); 584} 585 586char * 587_XlcGetValues( 588 XPointer base, 589 XlcResourceList resources, 590 int num_resources, 591 XlcArgList args, 592 int num_args, 593 unsigned long mask) 594{ 595 XlcResourceList res; 596 XrmQuark xrm_name; 597 int count; 598 599 for ( ; num_args-- > 0; args++) { 600 res = resources; 601 count = num_resources; 602 xrm_name = XrmPermStringToQuark(args->name); 603 604 for ( ; count-- > 0; res++) { 605 if (xrm_name == res->xrm_name && (mask & res->mask)) { 606 _XlcCopyToArg(base + res->offset, &args->value, res->size); 607 break; 608 } 609 } 610 611 if (count < 0) 612 return args->name; 613 } 614 615 return NULL; 616} 617 618char * 619_XlcSetValues( 620 XPointer base, 621 XlcResourceList resources, 622 int num_resources, 623 XlcArgList args, 624 int num_args, 625 unsigned long mask) 626{ 627 XlcResourceList res; 628 XrmQuark xrm_name; 629 int count; 630 631 for ( ; num_args-- > 0; args++) { 632 res = resources; 633 count = num_resources; 634 xrm_name = XrmPermStringToQuark(args->name); 635 636 for ( ; count-- > 0; res++) { 637 if (xrm_name == res->xrm_name && (mask & res->mask)) { 638 _XlcCopyFromArg(args->value, base + res->offset, res->size); 639 break; 640 } 641 } 642 643 if (count < 0) 644 return args->name; 645 } 646 647 return NULL; 648} 649