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