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