1 /* 2 3 Copyright 1991, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from 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 72 LockInfoPtr _Xi18n_lock; 73 #endif 74 75 char * 76 XSetLocaleModifiers( 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 96 Bool 97 XSupportsLocale(void) 98 { 99 return _XlcCurrentLC() != (XLCd)NULL; 100 } 101 102 Bool _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 128 static const char *im_valid[] = {"im", (const char *)NULL}; 129 130 /*ARGSUSED*/ 131 char * 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 169 typedef struct _XLCdListRec { 170 struct _XLCdListRec *next; 171 XLCd lcd; 172 } XLCdListRec, *XLCdList; 173 174 static XLCdList lcd_list = NULL; 175 176 typedef struct _XlcLoaderListRec { 177 struct _XlcLoaderListRec *next; 178 XLCdLoadProc proc; 179 } XlcLoaderListRec, *XlcLoaderList; 180 181 static XlcLoaderList loader_list = NULL; 182 183 void 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 211 Bool 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 244 XLCd 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 309 found: 310 _XUnlockMutex(_Xi18n_lock); 311 312 #if !defined(X_LOCALE) 313 if (siname != sinamebuf) Xfree(siname); 314 #endif 315 316 return lcd; 317 } 318 319 void 320 _XCloseLC( 321 XLCd lcd) 322 { 323 (void) lcd; 324 } 325 326 /* 327 * Get the XLCd for the current locale 328 */ 329 330 XLCd 331 _XlcCurrentLC(void) 332 { 333 return _XOpenLC(NULL); 334 } 335 336 XrmMethods 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 348 int 349 XmbTextPropertyToTextList( 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 364 int 365 XwcTextPropertyToTextList( 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 380 int 381 Xutf8TextPropertyToTextList( 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 396 int 397 XmbTextListToTextProperty( 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 413 int 414 XwcTextListToTextProperty( 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 430 int 431 Xutf8TextListToTextProperty( 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 447 void 448 XwcFreeStringList( 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 459 const char * 460 XDefaultString(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 470 void 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 494 void 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 518 void 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 531 void 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 549 void 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 558 char * 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 590 char * 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