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