lcWrap.c revision 07fb9b8f
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 = (int) strlen(*ptr); 115 if (strncmp(mods, *ptr, (size_t) 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 size_t 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} 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 = (int) 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 goto found; 282 } 283 } 284 285 if (!loader_list) 286 _XlcInitLoader(); 287 288 /* 289 * not there, so try to get and add to list 290 */ 291 for (loader = loader_list; loader; loader = loader->next) { 292 lcd = (*loader->proc)(name); 293 if (lcd) { 294 cur = Xmalloc (sizeof(XLCdListRec)); 295 if (cur) { 296 cur->lcd = lcd; 297 cur->next = lcd_list; 298 lcd_list = cur; 299 } else { 300 (*lcd->methods->close)(lcd); 301 lcd = (XLCd) NULL; 302 } 303 goto found; 304 } 305 } 306 307 lcd = NULL; 308 309found: 310 _XUnlockMutex(_Xi18n_lock); 311 312#if !defined(X_LOCALE) 313 if (siname != sinamebuf) Xfree(siname); 314#endif 315 316 return lcd; 317} 318 319void 320_XCloseLC( 321 XLCd lcd) 322{ 323 (void) lcd; 324} 325 326/* 327 * Get the XLCd for the current locale 328 */ 329 330XLCd 331_XlcCurrentLC(void) 332{ 333 return _XOpenLC(NULL); 334} 335 336XrmMethods 337_XrmInitParseInfo( 338 XPointer *state) 339{ 340 XLCd lcd = _XOpenLC((char *) NULL); 341 342 if (lcd == (XLCd) NULL) 343 return (XrmMethods) NULL; 344 345 return (*lcd->methods->init_parse_info)(lcd, state); 346} 347 348int 349XmbTextPropertyToTextList( 350 Display *dpy, 351 const XTextProperty *text_prop, 352 char ***list_ret, 353 int *count_ret) 354{ 355 XLCd lcd = _XlcCurrentLC(); 356 357 if (lcd == NULL) 358 return XLocaleNotSupported; 359 360 return (*lcd->methods->mb_text_prop_to_list)(lcd, dpy, text_prop, list_ret, 361 count_ret); 362} 363 364int 365XwcTextPropertyToTextList( 366 Display *dpy, 367 const XTextProperty *text_prop, 368 wchar_t ***list_ret, 369 int *count_ret) 370{ 371 XLCd lcd = _XlcCurrentLC(); 372 373 if (lcd == NULL) 374 return XLocaleNotSupported; 375 376 return (*lcd->methods->wc_text_prop_to_list)(lcd, dpy, text_prop, list_ret, 377 count_ret); 378} 379 380int 381Xutf8TextPropertyToTextList( 382 Display *dpy, 383 const XTextProperty *text_prop, 384 char ***list_ret, 385 int *count_ret) 386{ 387 XLCd lcd = _XlcCurrentLC(); 388 389 if (lcd == NULL) 390 return XLocaleNotSupported; 391 392 return (*lcd->methods->utf8_text_prop_to_list)(lcd, dpy, text_prop, 393 list_ret, count_ret); 394} 395 396int 397XmbTextListToTextProperty( 398 Display *dpy, 399 char **list, 400 int count, 401 XICCEncodingStyle style, 402 XTextProperty *text_prop) 403{ 404 XLCd lcd = _XlcCurrentLC(); 405 406 if (lcd == NULL) 407 return XLocaleNotSupported; 408 409 return (*lcd->methods->mb_text_list_to_prop)(lcd, dpy, list, count, style, 410 text_prop); 411} 412 413int 414XwcTextListToTextProperty( 415 Display *dpy, 416 wchar_t **list, 417 int count, 418 XICCEncodingStyle style, 419 XTextProperty *text_prop) 420{ 421 XLCd lcd = _XlcCurrentLC(); 422 423 if (lcd == NULL) 424 return XLocaleNotSupported; 425 426 return (*lcd->methods->wc_text_list_to_prop)(lcd, dpy, list, count, style, 427 text_prop); 428} 429 430int 431Xutf8TextListToTextProperty( 432 Display *dpy, 433 char **list, 434 int count, 435 XICCEncodingStyle style, 436 XTextProperty *text_prop) 437{ 438 XLCd lcd = _XlcCurrentLC(); 439 440 if (lcd == NULL) 441 return XLocaleNotSupported; 442 443 return (*lcd->methods->utf8_text_list_to_prop)(lcd, dpy, list, count, 444 style, text_prop); 445} 446 447void 448XwcFreeStringList( 449 wchar_t **list) 450{ 451 XLCd lcd = _XlcCurrentLC(); 452 453 if (lcd == NULL) 454 return; 455 456 (*lcd->methods->wc_free_string_list)(lcd, list); 457} 458 459const char * 460XDefaultString(void) 461{ 462 XLCd lcd = _XlcCurrentLC(); 463 464 if (lcd == NULL) 465 return (char *) NULL; 466 467 return (*lcd->methods->default_string)(lcd); 468} 469 470void 471_XlcCopyFromArg( 472 char *src, 473 char *dst, 474 int size) 475{ 476 if (size == sizeof(long)) 477 *((long *) dst) = (long) src; 478#ifdef LONG64 479 else if (size == sizeof(int)) 480 *((int *) dst) = (int)(long) src; 481#endif 482 else if (size == sizeof(short)) 483 *((short *) dst) = (short)(long) src; 484 else if (size == sizeof(char)) 485 *((char *) dst) = (char)(long) src; 486 else if (size == sizeof(XPointer)) 487 *((XPointer *) dst) = (XPointer) src; 488 else if (size > sizeof(XPointer)) 489 memcpy(dst, (char *) src, (size_t) size); 490 else 491 memcpy(dst, (char *) &src, (size_t) size); 492} 493 494void 495_XlcCopyToArg( 496 char *src, 497 char **dst, 498 int size) 499{ 500 /* FIXME: 501 On Big Endian machines, this behaves differently than _XCopyToArg. */ 502 if (size == sizeof(long)) 503 *((long *) *dst) = *((long *) src); 504#ifdef LONG64 505 else if (size == sizeof(int)) 506 *((int *) *dst) = *((int *) src); 507#endif 508 else if (size == sizeof(short)) 509 *((short *) *dst) = *((short *) src); 510 else if (size == sizeof(char)) 511 *((char *) *dst) = *((char *) src); 512 else if (size == sizeof(XPointer)) 513 *((XPointer *) *dst) = *((XPointer *) src); 514 else 515 memcpy(*dst, src, (size_t) size); 516} 517 518void 519_XlcCountVaList( 520 va_list var, 521 int *count_ret) 522{ 523 int count; 524 525 for (count = 0; va_arg(var, char *); count++) 526 (void)va_arg(var, XPointer); 527 528 *count_ret = count; 529} 530 531void 532_XlcVaToArgList( 533 va_list var, 534 int count, 535 XlcArgList *args_ret) 536{ 537 XlcArgList args; 538 539 *args_ret = args = Xmallocarray(count, sizeof(XlcArg)); 540 if (args == (XlcArgList) NULL) 541 return; 542 543 for ( ; count-- > 0; args++) { 544 args->name = va_arg(var, char *); 545 args->value = va_arg(var, XPointer); 546 } 547} 548 549void 550_XlcCompileResourceList( 551 XlcResourceList resources, 552 int num_resources) 553{ 554 for ( ; num_resources-- > 0; resources++) 555 resources->xrm_name = XrmPermStringToQuark(resources->name); 556} 557 558char * 559_XlcGetValues( 560 XPointer base, 561 XlcResourceList resources, 562 int num_resources, 563 XlcArgList args, 564 int num_args, 565 unsigned long mask) 566{ 567 XlcResourceList res; 568 XrmQuark xrm_name; 569 int count; 570 571 for ( ; num_args-- > 0; args++) { 572 res = resources; 573 count = num_resources; 574 xrm_name = XrmPermStringToQuark(args->name); 575 576 for ( ; count-- > 0; res++) { 577 if (xrm_name == res->xrm_name && (mask & res->mask)) { 578 _XlcCopyToArg(base + res->offset, &args->value, res->size); 579 break; 580 } 581 } 582 583 if (count < 0) 584 return args->name; 585 } 586 587 return NULL; 588} 589 590char * 591_XlcSetValues( 592 XPointer base, 593 XlcResourceList resources, 594 int num_resources, 595 XlcArgList args, 596 int num_args, 597 unsigned long mask) 598{ 599 XlcResourceList res; 600 XrmQuark xrm_name; 601 int count; 602 603 for ( ; num_args-- > 0; args++) { 604 res = resources; 605 count = num_resources; 606 xrm_name = XrmPermStringToQuark(args->name); 607 608 for ( ; count-- > 0; res++) { 609 if (xrm_name == res->xrm_name && (mask & res->mask)) { 610 _XlcCopyFromArg(args->value, base + res->offset, res->size); 611 break; 612 } 613 } 614 615 if (count < 0) 616 return args->name; 617 } 618 619 return NULL; 620} 621