lcWrap.c revision 258a0ebe
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#include "reallocarray.h" 70 71#ifdef XTHREADS 72LockInfoPtr _Xi18n_lock; 73#endif 74 75char * 76XSetLocaleModifiers( 77 const char *modifiers) 78{ 79 XLCd lcd = _XlcCurrentLC(); 80 char *user_mods; 81 char *mapped_mods; 82 83 if (!lcd) 84 return (char *) NULL; 85 if (!modifiers) 86 return lcd->core->modifiers; 87 user_mods = getenv("XMODIFIERS"); 88 mapped_mods = (*lcd->methods->map_modifiers) (lcd, user_mods, modifiers); 89 if (mapped_mods) { 90 Xfree(lcd->core->modifiers); 91 lcd->core->modifiers = mapped_mods; 92 } 93 return mapped_mods; 94} 95 96Bool 97XSupportsLocale(void) 98{ 99 return _XlcCurrentLC() != (XLCd)NULL; 100} 101 102Bool _XlcValidModSyntax( 103 const char * mods, 104 const char * const *valid_mods) 105{ 106 int i; 107 const char * const *ptr; 108 109 while (mods && (*mods == '@')) { 110 mods++; 111 if (*mods == '@') 112 break; 113 for (ptr = valid_mods; *ptr; ptr++) { 114 i = strlen(*ptr); 115 if (strncmp(mods, *ptr, i) || ((mods[i] != '=') 116#ifdef WIN32 117 && (mods[i] != '#') 118#endif 119 )) 120 continue; 121 mods = strchr(mods+i+1, '@'); 122 break; 123 } 124 } 125 return !mods || !*mods; 126} 127 128static const char *im_valid[] = {"im", (const char *)NULL}; 129 130/*ARGSUSED*/ 131char * 132_XlcDefaultMapModifiers( 133 XLCd lcd, 134 const char *user_mods, 135 const char *prog_mods) 136{ 137 int i; 138 char *mods; 139 140 if (!_XlcValidModSyntax(prog_mods, im_valid)) 141 return (char *)NULL; 142 if (!_XlcValidModSyntax(user_mods, im_valid)) 143 return (char *)NULL; 144 i = strlen(prog_mods) + 1; 145 if (user_mods) 146 i += strlen(user_mods); 147 mods = Xmalloc(i); 148 if (mods) { 149 strcpy(mods, prog_mods); 150 if (user_mods) 151 strcat(mods, user_mods); 152#ifdef WIN32 153 { 154 char *s; 155 for (s = mods; (s = strchr(s, '@')); s++) { 156 for (s++; *s && *s != '='; s++) { 157 if (*s == '#') { 158 *s = '='; 159 break; 160 } 161 } 162 } 163 } 164#endif 165 } 166 return mods; 167} 168 169typedef struct _XLCdListRec { 170 struct _XLCdListRec *next; 171 XLCd lcd; 172 int ref_count; 173} XLCdListRec, *XLCdList; 174 175static XLCdList lcd_list = NULL; 176 177typedef struct _XlcLoaderListRec { 178 struct _XlcLoaderListRec *next; 179 XLCdLoadProc proc; 180} XlcLoaderListRec, *XlcLoaderList; 181 182static XlcLoaderList loader_list = NULL; 183 184void 185_XlcRemoveLoader( 186 XLCdLoadProc proc) 187{ 188 XlcLoaderList loader, prev; 189 190 if (loader_list == NULL) 191 return; 192 193 prev = loader = loader_list; 194 if (loader->proc == proc) { 195 loader_list = loader->next; 196 Xfree(loader); 197 return; 198 } 199 200 while ((loader = loader->next)) { 201 if (loader->proc == proc) { 202 prev->next = loader->next; 203 Xfree(loader); 204 return; 205 } 206 prev = loader; 207 } 208 209 return; 210} 211 212Bool 213_XlcAddLoader( 214 XLCdLoadProc proc, 215 XlcPosition position) 216{ 217 XlcLoaderList loader, last; 218 219 _XlcRemoveLoader(proc); /* remove old loader, if exist */ 220 221 loader = Xmalloc(sizeof(XlcLoaderListRec)); 222 if (loader == NULL) 223 return False; 224 225 loader->proc = proc; 226 227 if (loader_list == NULL) 228 position = XlcHead; 229 230 if (position == XlcHead) { 231 loader->next = loader_list; 232 loader_list = loader; 233 } else { 234 last = loader_list; 235 while (last->next) 236 last = last->next; 237 238 loader->next = NULL; 239 last->next = loader; 240 } 241 242 return True; 243} 244 245XLCd 246_XOpenLC( 247 char *name) 248{ 249 XLCd lcd; 250 XlcLoaderList loader; 251 XLCdList cur; 252#if !defined(X_LOCALE) 253 int len; 254 char sinamebuf[256]; 255 char* siname = sinamebuf; 256#endif 257 258 if (name == NULL) { 259 name = setlocale (LC_CTYPE, (char *)NULL); 260#if !defined(X_LOCALE) 261 /* 262 * _XlMapOSLocaleName will return the same string or a substring 263 * of name, so strlen(name) is okay 264 */ 265 if ((len = strlen(name)) >= sizeof sinamebuf) { 266 siname = Xmalloc (len + 1); 267 if (siname == NULL) 268 return NULL; 269 } 270 name = _XlcMapOSLocaleName(name, siname); 271#endif 272 } 273 274 _XLockMutex(_Xi18n_lock); 275 276 /* 277 * search for needed lcd, if found return it 278 */ 279 for (cur = lcd_list; cur; cur = cur->next) { 280 if (!strcmp (cur->lcd->core->name, name)) { 281 lcd = cur->lcd; 282 cur->ref_count++; 283 goto found; 284 } 285 } 286 287 if (!loader_list) 288 _XlcInitLoader(); 289 290 /* 291 * not there, so try to get and add to list 292 */ 293 for (loader = loader_list; loader; loader = loader->next) { 294 lcd = (*loader->proc)(name); 295 if (lcd) { 296 cur = Xmalloc (sizeof(XLCdListRec)); 297 if (cur) { 298 cur->lcd = lcd; 299 cur->ref_count = 1; 300 cur->next = lcd_list; 301 lcd_list = cur; 302 } else { 303 (*lcd->methods->close)(lcd); 304 lcd = (XLCd) NULL; 305 } 306 goto found; 307 } 308 } 309 310 lcd = NULL; 311 312found: 313 _XUnlockMutex(_Xi18n_lock); 314 315#if !defined(X_LOCALE) 316 if (siname != sinamebuf) Xfree(siname); 317#endif 318 319 return lcd; 320} 321 322void 323_XCloseLC( 324 XLCd lcd) 325{ 326 XLCdList cur, *prev; 327 328 for (prev = &lcd_list; (cur = *prev); prev = &cur->next) { 329 if (cur->lcd == lcd) { 330 if (--cur->ref_count < 1) { 331 _XlcDestroyLC(lcd); 332 *prev = cur->next; 333 Xfree(cur); 334 } 335 break; 336 } 337 } 338 339 if(loader_list) { 340 _XlcDeInitLoader(); 341 loader_list = NULL; 342 } 343} 344 345/* 346 * Get the XLCd for the current locale 347 */ 348 349XLCd 350_XlcCurrentLC(void) 351{ 352 XLCd lcd; 353 static XLCd last_lcd = NULL; 354 355 lcd = _XOpenLC((char *) NULL); 356 357 if (last_lcd) 358 _XCloseLC(last_lcd); 359 360 last_lcd = lcd; 361 362 return lcd; 363} 364 365XrmMethods 366_XrmInitParseInfo( 367 XPointer *state) 368{ 369 XLCd lcd = _XOpenLC((char *) NULL); 370 371 if (lcd == (XLCd) NULL) 372 return (XrmMethods) NULL; 373 374 return (*lcd->methods->init_parse_info)(lcd, state); 375} 376 377int 378XmbTextPropertyToTextList( 379 Display *dpy, 380 const XTextProperty *text_prop, 381 char ***list_ret, 382 int *count_ret) 383{ 384 XLCd lcd = _XlcCurrentLC(); 385 386 if (lcd == NULL) 387 return XLocaleNotSupported; 388 389 return (*lcd->methods->mb_text_prop_to_list)(lcd, dpy, text_prop, list_ret, 390 count_ret); 391} 392 393int 394XwcTextPropertyToTextList( 395 Display *dpy, 396 const XTextProperty *text_prop, 397 wchar_t ***list_ret, 398 int *count_ret) 399{ 400 XLCd lcd = _XlcCurrentLC(); 401 402 if (lcd == NULL) 403 return XLocaleNotSupported; 404 405 return (*lcd->methods->wc_text_prop_to_list)(lcd, dpy, text_prop, list_ret, 406 count_ret); 407} 408 409int 410Xutf8TextPropertyToTextList( 411 Display *dpy, 412 const XTextProperty *text_prop, 413 char ***list_ret, 414 int *count_ret) 415{ 416 XLCd lcd = _XlcCurrentLC(); 417 418 if (lcd == NULL) 419 return XLocaleNotSupported; 420 421 return (*lcd->methods->utf8_text_prop_to_list)(lcd, dpy, text_prop, 422 list_ret, count_ret); 423} 424 425int 426XmbTextListToTextProperty( 427 Display *dpy, 428 char **list, 429 int count, 430 XICCEncodingStyle style, 431 XTextProperty *text_prop) 432{ 433 XLCd lcd = _XlcCurrentLC(); 434 435 if (lcd == NULL) 436 return XLocaleNotSupported; 437 438 return (*lcd->methods->mb_text_list_to_prop)(lcd, dpy, list, count, style, 439 text_prop); 440} 441 442int 443XwcTextListToTextProperty( 444 Display *dpy, 445 wchar_t **list, 446 int count, 447 XICCEncodingStyle style, 448 XTextProperty *text_prop) 449{ 450 XLCd lcd = _XlcCurrentLC(); 451 452 if (lcd == NULL) 453 return XLocaleNotSupported; 454 455 return (*lcd->methods->wc_text_list_to_prop)(lcd, dpy, list, count, style, 456 text_prop); 457} 458 459int 460Xutf8TextListToTextProperty( 461 Display *dpy, 462 char **list, 463 int count, 464 XICCEncodingStyle style, 465 XTextProperty *text_prop) 466{ 467 XLCd lcd = _XlcCurrentLC(); 468 469 if (lcd == NULL) 470 return XLocaleNotSupported; 471 472 return (*lcd->methods->utf8_text_list_to_prop)(lcd, dpy, list, count, 473 style, text_prop); 474} 475 476void 477XwcFreeStringList( 478 wchar_t **list) 479{ 480 XLCd lcd = _XlcCurrentLC(); 481 482 if (lcd == NULL) 483 return; 484 485 (*lcd->methods->wc_free_string_list)(lcd, list); 486} 487 488const char * 489XDefaultString(void) 490{ 491 XLCd lcd = _XlcCurrentLC(); 492 493 if (lcd == NULL) 494 return (char *) NULL; 495 496 return (*lcd->methods->default_string)(lcd); 497} 498 499void 500_XlcCopyFromArg( 501 char *src, 502 char *dst, 503 int size) 504{ 505 if (size == sizeof(long)) 506 *((long *) dst) = (long) src; 507#ifdef LONG64 508 else if (size == sizeof(int)) 509 *((int *) dst) = (int)(long) src; 510#endif 511 else if (size == sizeof(short)) 512 *((short *) dst) = (short)(long) src; 513 else if (size == sizeof(char)) 514 *((char *) dst) = (char)(long) src; 515 else if (size == sizeof(XPointer)) 516 *((XPointer *) dst) = (XPointer) src; 517 else if (size > sizeof(XPointer)) 518 memcpy(dst, (char *) src, size); 519 else 520 memcpy(dst, (char *) &src, size); 521} 522 523void 524_XlcCopyToArg( 525 char *src, 526 char **dst, 527 int size) 528{ 529 /* FIXME: 530 On Big Endian machines, this behaves differently than _XCopyToArg. */ 531 if (size == sizeof(long)) 532 *((long *) *dst) = *((long *) src); 533#ifdef LONG64 534 else if (size == sizeof(int)) 535 *((int *) *dst) = *((int *) src); 536#endif 537 else if (size == sizeof(short)) 538 *((short *) *dst) = *((short *) src); 539 else if (size == sizeof(char)) 540 *((char *) *dst) = *((char *) src); 541 else if (size == sizeof(XPointer)) 542 *((XPointer *) *dst) = *((XPointer *) src); 543 else 544 memcpy(*dst, src, size); 545} 546 547void 548_XlcCountVaList( 549 va_list var, 550 int *count_ret) 551{ 552 int count; 553 554 for (count = 0; va_arg(var, char *); count++) 555 (void)va_arg(var, XPointer); 556 557 *count_ret = count; 558} 559 560void 561_XlcVaToArgList( 562 va_list var, 563 int count, 564 XlcArgList *args_ret) 565{ 566 XlcArgList args; 567 568 *args_ret = args = Xmallocarray(count, sizeof(XlcArg)); 569 if (args == (XlcArgList) NULL) 570 return; 571 572 for ( ; count-- > 0; args++) { 573 args->name = va_arg(var, char *); 574 args->value = va_arg(var, XPointer); 575 } 576} 577 578void 579_XlcCompileResourceList( 580 XlcResourceList resources, 581 int num_resources) 582{ 583 for ( ; num_resources-- > 0; resources++) 584 resources->xrm_name = XrmPermStringToQuark(resources->name); 585} 586 587char * 588_XlcGetValues( 589 XPointer base, 590 XlcResourceList resources, 591 int num_resources, 592 XlcArgList args, 593 int num_args, 594 unsigned long mask) 595{ 596 XlcResourceList res; 597 XrmQuark xrm_name; 598 int count; 599 600 for ( ; num_args-- > 0; args++) { 601 res = resources; 602 count = num_resources; 603 xrm_name = XrmPermStringToQuark(args->name); 604 605 for ( ; count-- > 0; res++) { 606 if (xrm_name == res->xrm_name && (mask & res->mask)) { 607 _XlcCopyToArg(base + res->offset, &args->value, res->size); 608 break; 609 } 610 } 611 612 if (count < 0) 613 return args->name; 614 } 615 616 return NULL; 617} 618 619char * 620_XlcSetValues( 621 XPointer base, 622 XlcResourceList resources, 623 int num_resources, 624 XlcArgList args, 625 int num_args, 626 unsigned long mask) 627{ 628 XlcResourceList res; 629 XrmQuark xrm_name; 630 int count; 631 632 for ( ; num_args-- > 0; args++) { 633 res = resources; 634 count = num_resources; 635 xrm_name = XrmPermStringToQuark(args->name); 636 637 for ( ; count-- > 0; res++) { 638 if (xrm_name == res->xrm_name && (mask & res->mask)) { 639 _XlcCopyFromArg(args->value, base + res->offset, res->size); 640 break; 641 } 642 } 643 644 if (count < 0) 645 return args->name; 646 } 647 648 return NULL; 649} 650