lcWrap.c revision 07fb9b8f
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 = (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
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    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
169typedef struct _XLCdListRec {
170    struct _XLCdListRec *next;
171    XLCd lcd;
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 = (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
309found:
310    _XUnlockMutex(_Xi18n_lock);
311
312#if !defined(X_LOCALE)
313    if (siname != sinamebuf) Xfree(siname);
314#endif
315
316    return lcd;
317}
318
319void
320_XCloseLC(
321    XLCd lcd)
322{
323    (void) lcd;
324}
325
326/*
327 * Get the XLCd for the current locale
328 */
329
330XLCd
331_XlcCurrentLC(void)
332{
333    return _XOpenLC(NULL);
334}
335
336XrmMethods
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
348int
349XmbTextPropertyToTextList(
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
364int
365XwcTextPropertyToTextList(
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
380int
381Xutf8TextPropertyToTextList(
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
396int
397XmbTextListToTextProperty(
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
413int
414XwcTextListToTextProperty(
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
430int
431Xutf8TextListToTextProperty(
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
447void
448XwcFreeStringList(
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
459const char *
460XDefaultString(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
470void
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
494void
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
518void
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
531void
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
549void
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
558char *
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
590char *
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