Home | History | Annotate | Line # | Download | only in xlibi18n
      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