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