lcWrap.c revision 258a0ebe
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 = strlen(*ptr);
115	    if (strncmp(mods, *ptr, 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    int 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    int ref_count;
173} XLCdListRec, *XLCdList;
174
175static XLCdList lcd_list = NULL;
176
177typedef struct _XlcLoaderListRec {
178    struct _XlcLoaderListRec *next;
179    XLCdLoadProc proc;
180} XlcLoaderListRec, *XlcLoaderList;
181
182static XlcLoaderList loader_list = NULL;
183
184void
185_XlcRemoveLoader(
186    XLCdLoadProc proc)
187{
188    XlcLoaderList loader, prev;
189
190    if (loader_list == NULL)
191	return;
192
193    prev = loader = loader_list;
194    if (loader->proc == proc) {
195	loader_list = loader->next;
196	Xfree(loader);
197	return;
198    }
199
200    while ((loader = loader->next)) {
201	if (loader->proc == proc) {
202	    prev->next = loader->next;
203	    Xfree(loader);
204	    return;
205	}
206	prev = loader;
207    }
208
209    return;
210}
211
212Bool
213_XlcAddLoader(
214    XLCdLoadProc proc,
215    XlcPosition position)
216{
217    XlcLoaderList loader, last;
218
219    _XlcRemoveLoader(proc);		/* remove old loader, if exist */
220
221    loader = Xmalloc(sizeof(XlcLoaderListRec));
222    if (loader == NULL)
223	return False;
224
225    loader->proc = proc;
226
227    if (loader_list == NULL)
228	position = XlcHead;
229
230    if (position == XlcHead) {
231	loader->next = loader_list;
232	loader_list = loader;
233    } else {
234	last = loader_list;
235	while (last->next)
236	    last = last->next;
237
238	loader->next = NULL;
239	last->next = loader;
240    }
241
242    return True;
243}
244
245XLCd
246_XOpenLC(
247    char *name)
248{
249    XLCd lcd;
250    XlcLoaderList loader;
251    XLCdList cur;
252#if !defined(X_LOCALE)
253    int len;
254    char sinamebuf[256];
255    char* siname = sinamebuf;
256#endif
257
258    if (name == NULL) {
259	name = setlocale (LC_CTYPE, (char *)NULL);
260#if !defined(X_LOCALE)
261        /*
262         * _XlMapOSLocaleName will return the same string or a substring
263         * of name, so strlen(name) is okay
264         */
265        if ((len = strlen(name)) >= sizeof sinamebuf) {
266            siname = Xmalloc (len + 1);
267            if (siname == NULL)
268                return NULL;
269        }
270        name = _XlcMapOSLocaleName(name, siname);
271#endif
272    }
273
274    _XLockMutex(_Xi18n_lock);
275
276    /*
277     * search for needed lcd, if found return it
278     */
279    for (cur = lcd_list; cur; cur = cur->next) {
280	if (!strcmp (cur->lcd->core->name, name)) {
281	    lcd = cur->lcd;
282	    cur->ref_count++;
283	    goto found;
284	}
285    }
286
287    if (!loader_list)
288	_XlcInitLoader();
289
290    /*
291     * not there, so try to get and add to list
292     */
293    for (loader = loader_list; loader; loader = loader->next) {
294	lcd = (*loader->proc)(name);
295	if (lcd) {
296	    cur = Xmalloc (sizeof(XLCdListRec));
297	    if (cur) {
298		cur->lcd = lcd;
299		cur->ref_count = 1;
300		cur->next = lcd_list;
301		lcd_list = cur;
302	    } else {
303		(*lcd->methods->close)(lcd);
304		lcd = (XLCd) NULL;
305	    }
306	    goto found;
307	}
308    }
309
310    lcd = NULL;
311
312found:
313    _XUnlockMutex(_Xi18n_lock);
314
315#if !defined(X_LOCALE)
316    if (siname != sinamebuf) Xfree(siname);
317#endif
318
319    return lcd;
320}
321
322void
323_XCloseLC(
324    XLCd lcd)
325{
326    XLCdList cur, *prev;
327
328    for (prev = &lcd_list; (cur = *prev); prev = &cur->next) {
329	if (cur->lcd == lcd) {
330	    if (--cur->ref_count < 1) {
331		_XlcDestroyLC(lcd);
332		*prev = cur->next;
333		Xfree(cur);
334	    }
335	    break;
336	}
337    }
338
339    if(loader_list) {
340	_XlcDeInitLoader();
341	loader_list = NULL;
342    }
343}
344
345/*
346 * Get the XLCd for the current locale
347 */
348
349XLCd
350_XlcCurrentLC(void)
351{
352    XLCd lcd;
353    static XLCd last_lcd = NULL;
354
355    lcd = _XOpenLC((char *) NULL);
356
357    if (last_lcd)
358	_XCloseLC(last_lcd);
359
360    last_lcd = lcd;
361
362    return lcd;
363}
364
365XrmMethods
366_XrmInitParseInfo(
367    XPointer *state)
368{
369    XLCd lcd = _XOpenLC((char *) NULL);
370
371    if (lcd == (XLCd) NULL)
372	return (XrmMethods) NULL;
373
374    return (*lcd->methods->init_parse_info)(lcd, state);
375}
376
377int
378XmbTextPropertyToTextList(
379    Display *dpy,
380    const XTextProperty *text_prop,
381    char ***list_ret,
382    int *count_ret)
383{
384    XLCd lcd = _XlcCurrentLC();
385
386    if (lcd == NULL)
387	return XLocaleNotSupported;
388
389    return (*lcd->methods->mb_text_prop_to_list)(lcd, dpy, text_prop, list_ret,
390						 count_ret);
391}
392
393int
394XwcTextPropertyToTextList(
395    Display *dpy,
396    const XTextProperty *text_prop,
397    wchar_t ***list_ret,
398    int *count_ret)
399{
400    XLCd lcd = _XlcCurrentLC();
401
402    if (lcd == NULL)
403	return XLocaleNotSupported;
404
405    return (*lcd->methods->wc_text_prop_to_list)(lcd, dpy, text_prop, list_ret,
406						 count_ret);
407}
408
409int
410Xutf8TextPropertyToTextList(
411    Display *dpy,
412    const XTextProperty *text_prop,
413    char ***list_ret,
414    int *count_ret)
415{
416    XLCd lcd = _XlcCurrentLC();
417
418    if (lcd == NULL)
419	return XLocaleNotSupported;
420
421    return (*lcd->methods->utf8_text_prop_to_list)(lcd, dpy, text_prop,
422						   list_ret, count_ret);
423}
424
425int
426XmbTextListToTextProperty(
427    Display *dpy,
428    char **list,
429    int count,
430    XICCEncodingStyle style,
431    XTextProperty *text_prop)
432{
433    XLCd lcd = _XlcCurrentLC();
434
435    if (lcd == NULL)
436	return XLocaleNotSupported;
437
438    return (*lcd->methods->mb_text_list_to_prop)(lcd, dpy, list, count, style,
439						 text_prop);
440}
441
442int
443XwcTextListToTextProperty(
444    Display *dpy,
445    wchar_t **list,
446    int count,
447    XICCEncodingStyle style,
448    XTextProperty *text_prop)
449{
450    XLCd lcd = _XlcCurrentLC();
451
452    if (lcd == NULL)
453	return XLocaleNotSupported;
454
455    return (*lcd->methods->wc_text_list_to_prop)(lcd, dpy, list, count, style,
456						 text_prop);
457}
458
459int
460Xutf8TextListToTextProperty(
461    Display *dpy,
462    char **list,
463    int count,
464    XICCEncodingStyle style,
465    XTextProperty *text_prop)
466{
467    XLCd lcd = _XlcCurrentLC();
468
469    if (lcd == NULL)
470	return XLocaleNotSupported;
471
472    return (*lcd->methods->utf8_text_list_to_prop)(lcd, dpy, list, count,
473						   style, text_prop);
474}
475
476void
477XwcFreeStringList(
478    wchar_t **list)
479{
480    XLCd lcd = _XlcCurrentLC();
481
482    if (lcd == NULL)
483	return;
484
485    (*lcd->methods->wc_free_string_list)(lcd, list);
486}
487
488const char *
489XDefaultString(void)
490{
491    XLCd lcd = _XlcCurrentLC();
492
493    if (lcd == NULL)
494	return (char *) NULL;
495
496    return (*lcd->methods->default_string)(lcd);
497}
498
499void
500_XlcCopyFromArg(
501    char *src,
502    char *dst,
503    int size)
504{
505    if (size == sizeof(long))
506	*((long *) dst) = (long) src;
507#ifdef LONG64
508    else if (size == sizeof(int))
509	*((int *) dst) = (int)(long) src;
510#endif
511    else if (size == sizeof(short))
512	*((short *) dst) = (short)(long) src;
513    else if (size == sizeof(char))
514	*((char *) dst) = (char)(long) src;
515    else if (size == sizeof(XPointer))
516	*((XPointer *) dst) = (XPointer) src;
517    else if (size > sizeof(XPointer))
518	memcpy(dst, (char *) src, size);
519    else
520	memcpy(dst, (char *) &src, size);
521}
522
523void
524_XlcCopyToArg(
525    char *src,
526    char **dst,
527    int size)
528{
529    /* FIXME:
530       On Big Endian machines, this behaves differently than _XCopyToArg. */
531    if (size == sizeof(long))
532	*((long *) *dst) = *((long *) src);
533#ifdef LONG64
534    else if (size == sizeof(int))
535	*((int *) *dst) = *((int *) src);
536#endif
537    else if (size == sizeof(short))
538	*((short *) *dst) = *((short *) src);
539    else if (size == sizeof(char))
540	*((char *) *dst) = *((char *) src);
541    else if (size == sizeof(XPointer))
542	*((XPointer *) *dst) = *((XPointer *) src);
543    else
544	memcpy(*dst, src, size);
545}
546
547void
548_XlcCountVaList(
549    va_list var,
550    int *count_ret)
551{
552    int count;
553
554    for (count = 0; va_arg(var, char *); count++)
555	(void)va_arg(var, XPointer);
556
557    *count_ret = count;
558}
559
560void
561_XlcVaToArgList(
562    va_list var,
563    int count,
564    XlcArgList *args_ret)
565{
566    XlcArgList args;
567
568    *args_ret = args = Xmallocarray(count, sizeof(XlcArg));
569    if (args == (XlcArgList) NULL)
570	return;
571
572    for ( ; count-- > 0; args++) {
573	args->name = va_arg(var, char *);
574	args->value = va_arg(var, XPointer);
575    }
576}
577
578void
579_XlcCompileResourceList(
580    XlcResourceList resources,
581    int num_resources)
582{
583    for ( ; num_resources-- > 0; resources++)
584	resources->xrm_name = XrmPermStringToQuark(resources->name);
585}
586
587char *
588_XlcGetValues(
589    XPointer base,
590    XlcResourceList resources,
591    int num_resources,
592    XlcArgList args,
593    int num_args,
594    unsigned long mask)
595{
596    XlcResourceList res;
597    XrmQuark xrm_name;
598    int count;
599
600    for ( ; num_args-- > 0; args++) {
601	res = resources;
602	count = num_resources;
603	xrm_name = XrmPermStringToQuark(args->name);
604
605	for ( ; count-- > 0; res++) {
606	    if (xrm_name == res->xrm_name && (mask & res->mask)) {
607		    _XlcCopyToArg(base + res->offset, &args->value, res->size);
608		break;
609	    }
610	}
611
612	if (count < 0)
613	    return args->name;
614    }
615
616    return NULL;
617}
618
619char *
620_XlcSetValues(
621    XPointer base,
622    XlcResourceList resources,
623    int num_resources,
624    XlcArgList args,
625    int num_args,
626    unsigned long mask)
627{
628    XlcResourceList res;
629    XrmQuark xrm_name;
630    int count;
631
632    for ( ; num_args-- > 0; args++) {
633	res = resources;
634	count = num_resources;
635	xrm_name = XrmPermStringToQuark(args->name);
636
637	for ( ; count-- > 0; res++) {
638	    if (xrm_name == res->xrm_name && (mask & res->mask)) {
639		_XlcCopyFromArg(args->value, base + res->offset, res->size);
640		break;
641	    }
642	}
643
644	if (count < 0)
645	    return args->name;
646    }
647
648    return NULL;
649}
650