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 *
XSetLocaleModifiers(const char * modifiers)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
XSupportsLocale(void)97 XSupportsLocale(void)
98 {
99     return _XlcCurrentLC() != (XLCd)NULL;
100 }
101 
_XlcValidModSyntax(const char * mods,const char * const * valid_mods)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 *
_XlcDefaultMapModifiers(XLCd lcd,const char * user_mods,const char * prog_mods)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 = (int) strlen(prog_mods) + 1;
145     if (user_mods)
146 	i = (int) ((size_t) 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
_XlcRemoveLoader(XLCdLoadProc proc)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
_XlcAddLoader(XLCdLoadProc proc,XlcPosition position)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
_XOpenLC(char * name)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
_XCloseLC(XLCd lcd)320 _XCloseLC(
321     XLCd lcd)
322 {
323     (void) lcd;
324 }
325 
326 /*
327  * Get the XLCd for the current locale
328  */
329 
330 XLCd
_XlcCurrentLC(void)331 _XlcCurrentLC(void)
332 {
333     return _XOpenLC(NULL);
334 }
335 
336 XrmMethods
_XrmInitParseInfo(XPointer * state)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
XmbTextPropertyToTextList(Display * dpy,const XTextProperty * text_prop,char *** list_ret,int * count_ret)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
XwcTextPropertyToTextList(Display * dpy,const XTextProperty * text_prop,wchar_t *** list_ret,int * count_ret)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
Xutf8TextPropertyToTextList(Display * dpy,const XTextProperty * text_prop,char *** list_ret,int * count_ret)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
XmbTextListToTextProperty(Display * dpy,char ** list,int count,XICCEncodingStyle style,XTextProperty * text_prop)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
XwcTextListToTextProperty(Display * dpy,wchar_t ** list,int count,XICCEncodingStyle style,XTextProperty * text_prop)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
Xutf8TextListToTextProperty(Display * dpy,char ** list,int count,XICCEncodingStyle style,XTextProperty * text_prop)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
XwcFreeStringList(wchar_t ** list)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 *
XDefaultString(void)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
_XlcCopyFromArg(char * src,char * dst,int size)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
_XlcCopyToArg(char * src,char ** dst,int size)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
_XlcCountVaList(va_list var,int * count_ret)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
_XlcVaToArgList(va_list var,int count,XlcArgList * args_ret)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
_XlcCompileResourceList(XlcResourceList resources,int num_resources)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 *
_XlcGetValues(XPointer base,XlcResourceList resources,int num_resources,XlcArgList args,int num_args,unsigned long mask)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 *
_XlcSetValues(XPointer base,XlcResourceList resources,int num_resources,XlcArgList args,int num_args,unsigned long mask)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