1 /*
2
3 Copyright 1988, 1989, 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 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35
36 #include <X11/X.h>
37 #include <X11/Xlib.h>
38 #include "Xlibint.h"
39 #include "Xlcint.h"
40 #include "XlcPubI.h"
41 #include "Ximint.h"
42 #include <X11/Xutil.h>
43 #include <X11/Xmd.h>
44 #define XK_LATIN1
45 #define XK_PUBLISHING
46 #include <X11/keysym.h>
47 #include <X11/extensions/XKBproto.h>
48 #include "XKBlibint.h"
49 #include <X11/Xlocale.h>
50 #include <ctype.h>
51 #include <X11/Xos.h>
52
53 #ifdef __sgi_not_xconsortium
54 #define XKB_EXTEND_LOOKUP_STRING
55 #endif
56
57 static int
_XkbHandleSpecialSym(KeySym keysym,char * buffer,int nbytes,int * extra_rtrn)58 _XkbHandleSpecialSym(KeySym keysym, char *buffer, int nbytes, int *extra_rtrn)
59 {
60
61 /* try to convert to Latin-1, handling ctrl */
62 if (!(((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) ||
63 (keysym == XK_Return) || (keysym == XK_Escape) ||
64 (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) ||
65 (keysym == XK_KP_Enter) ||
66 ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) ||
67 (keysym == XK_KP_Equal) || (keysym == XK_Delete)))
68 return 0;
69
70 if (nbytes < 1) {
71 if (extra_rtrn)
72 *extra_rtrn = 1;
73 return 0;
74 }
75 /* if X keysym, convert to ascii by grabbing low 7 bits */
76 if (keysym == XK_KP_Space)
77 buffer[0] = XK_space & 0x7F; /* patch encoding botch */
78 else if (keysym == XK_hyphen)
79 buffer[0] = (char) (XK_minus & 0xFF); /* map to equiv character */
80 else
81 buffer[0] = (char) (keysym & 0x7F);
82 return 1;
83 }
84
85 /*ARGSUSED*/
86 static int
_XkbKSToKnownSet(XPointer priv,KeySym keysym,char * buffer,int nbytes,int * extra_rtrn)87 _XkbKSToKnownSet(XPointer priv,
88 KeySym keysym,
89 char *buffer,
90 int nbytes,
91 int *extra_rtrn)
92 {
93 char tbuf[8], *buf;
94
95 if (extra_rtrn)
96 *extra_rtrn = 0;
97
98 /* convert "dead" diacriticals for dumb applications */
99 if ((keysym & 0xffffff00) == 0xfe00) {
100 switch (keysym) {
101 case XK_dead_grave: keysym = XK_grave; break;
102 case XK_dead_acute: keysym = XK_acute; break;
103 case XK_dead_circumflex: keysym = XK_asciicircum; break;
104 case XK_dead_tilde: keysym = XK_asciitilde; break;
105 case XK_dead_macron: keysym = XK_macron; break;
106 case XK_dead_breve: keysym = XK_breve; break;
107 case XK_dead_abovedot: keysym = XK_abovedot; break;
108 case XK_dead_diaeresis: keysym = XK_diaeresis; break;
109 case XK_dead_abovering: keysym = XK_degree; break;
110 case XK_dead_doubleacute: keysym = XK_doubleacute; break;
111 case XK_dead_caron: keysym = XK_caron; break;
112 case XK_dead_cedilla: keysym = XK_cedilla; break;
113 case XK_dead_ogonek: keysym = XK_ogonek; break;
114 case XK_dead_iota: keysym = XK_Greek_iota; break;
115 #ifdef XK_KATAKANA
116 case XK_dead_voiced_sound: keysym = XK_voicedsound; break;
117 case XK_dead_semivoiced_sound: keysym = XK_semivoicedsound; break;
118 #endif
119 }
120 }
121
122 if (nbytes < 1)
123 buf = tbuf;
124 else
125 buf = buffer;
126
127 if ((keysym & 0xffffff00) == 0xff00) {
128 return _XkbHandleSpecialSym(keysym, buf, nbytes, extra_rtrn);
129 }
130 return _XimGetCharCode(priv, keysym, (unsigned char *) buf, nbytes);
131 }
132
133 typedef struct _XkbToKS {
134 unsigned prefix;
135 char *map;
136 } XkbToKS;
137
138 /*ARGSUSED*/
139 static KeySym
_XkbKnownSetToKS(XPointer priv,char * buffer,int nbytes,Status * status)140 _XkbKnownSetToKS(XPointer priv, char *buffer, int nbytes, Status *status)
141 {
142 if (nbytes != 1)
143 return NoSymbol;
144 if (((buffer[0] & 0x80) == 0) && (buffer[0] >= 32))
145 return buffer[0];
146 else if ((buffer[0] & 0x7f) >= 32) {
147 XkbToKS *map = (XkbToKS *) priv;
148
149 if (map) {
150 if (map->map)
151 return map->prefix | map->map[buffer[0] & 0x7f];
152 else
153 return map->prefix | buffer[0];
154 }
155 return buffer[0];
156 }
157 return NoSymbol;
158 }
159
160 static KeySym
__XkbDefaultToUpper(KeySym sym)161 __XkbDefaultToUpper(KeySym sym)
162 {
163 KeySym lower, upper;
164
165 XConvertCase(sym, &lower, &upper);
166 return upper;
167 }
168
169 #ifdef XKB_EXTEND_LOOKUP_STRING
170 static int
Strcmp(char * str1,char * str2)171 Strcmp(char *str1, char *str2)
172 {
173 char str[256];
174 char c, *s;
175
176 /*
177 * unchecked strings from the environment can end up here, so check
178 * the length before copying.
179 */
180 if (strlen(str1) >= sizeof(str)) /* almost certain it's a mismatch */
181 return 1;
182
183 for (s = str; (c = *str1++);) {
184 if (isupper(c))
185 c = tolower(c);
186 *s++ = c;
187 }
188 *s = '\0';
189 return (strcmp(str, str2));
190 }
191 #endif
192
193 int
_XkbGetConverters(const char * encoding_name,XkbConverters * cvt_rtrn)194 _XkbGetConverters(const char *encoding_name, XkbConverters * cvt_rtrn)
195 {
196 if (!cvt_rtrn)
197 return 0;
198
199 cvt_rtrn->KSToMB = _XkbKSToKnownSet;
200 cvt_rtrn->KSToMBPriv = _XimGetLocaleCode(encoding_name);
201 cvt_rtrn->MBToKS = _XkbKnownSetToKS;
202 cvt_rtrn->MBToKSPriv = NULL;
203 cvt_rtrn->KSToUpper = __XkbDefaultToUpper;
204 return 1;
205 }
206
207 /***====================================================================***/
208
209 /*
210 * The function _XkbGetCharset seems to be missnamed as what it seems to
211 * be used for is to determine the encoding-name for the locale. ???
212 */
213
214 #ifdef XKB_EXTEND_LOOKUP_STRING
215
216 /*
217 * XKB_EXTEND_LOOKUP_STRING is not used by the SI. It is used by various
218 * X Consortium/X Project Team members, so we leave it in the source as
219 * an simplify integration by these companies.
220 */
221
222 #define CHARSET_FILE "/usr/lib/X11/input/charsets"
223 static char *_XkbKnownLanguages =
224 "c=ascii:da,de,en,es,fr,is,it,nl,no,pt,sv=iso8859-1:hu,pl,cs=iso8859-2:"
225 "eo=iso8859-3:sp=iso8859-5:ar,ara=iso8859-6:el=iso8859-7:he=iso8859-8:"
226 "tr=iso8859-9:lt,lv=iso8859-13:et,fi=iso8859-15:ru=koi8-r:uk=koi8-u:"
227 "th,th_TH,th_TH.iso8859-11=iso8859-11:th_TH.TIS620=tis620:hy=armscii-8:"
228 "vi=tcvn-5712:ka=georgian-academy:be,bg=microsoft-cp1251";
229
230 char *
_XkbGetCharset(void)231 _XkbGetCharset(void)
232 {
233 /*
234 * PAGE USAGE TUNING: explicitly initialize to move these to data
235 * instead of bss
236 */
237 static char buf[100] = { 0 };
238 char lang[256];
239 char *start, *tmp, *end, *next, *set;
240 char *country, *charset;
241 char *locale;
242
243 tmp = getenv("_XKB_CHARSET");
244 if (tmp)
245 return tmp;
246 locale = setlocale(LC_CTYPE, NULL);
247
248 if (locale == NULL)
249 return NULL;
250
251 if (strlen(locale) >= sizeof(lang))
252 return NULL;
253
254 for (tmp = lang; *tmp = *locale++; tmp++) {
255 if (isupper(*tmp))
256 *tmp = tolower(*tmp);
257 }
258 country = strchr(lang, '_');
259 if (country) {
260 *country++ = '\0';
261 charset = strchr(country, '.');
262 if (charset)
263 *charset++ = '\0';
264 if (charset) {
265 strncpy(buf, charset, 99);
266 buf[99] = '\0';
267 return buf;
268 }
269 }
270 else {
271 charset = NULL;
272 }
273
274 if ((tmp = getenv("_XKB_LOCALE_CHARSETS")) != NULL) {
275 start = _XkbAlloc(strlen(tmp) + 1);
276 strcpy(start, tmp);
277 tmp = start;
278 }
279 else {
280 struct stat sbuf;
281 FILE *file;
282 #ifndef __UNIXOS2__
283 char *cf = CHARSET_FILE;
284 #else
285 char *cf = __XOS2RedirRoot(CHARSET_FILE);
286 #endif
287
288 #ifndef S_ISREG
289 # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
290 #endif
291
292 if ((stat(cf, &sbuf) == 0) && S_ISREG(sbuf.st_mode) &&
293 (file = fopen(cf, "r"))) {
294 tmp = _XkbAlloc(sbuf.st_size + 1);
295 if (tmp != NULL) {
296 sbuf.st_size = (long) fread(tmp, 1, sbuf.st_size, file);
297 tmp[sbuf.st_size] = '\0';
298 }
299 fclose(file);
300 }
301 }
302
303 if (tmp == NULL) {
304 tmp = _XkbAlloc(strlen(_XkbKnownLanguages) + 1);
305 if (!tmp)
306 return NULL;
307 strcpy(tmp, _XkbKnownLanguages);
308 }
309 start = tmp;
310 do {
311 if ((set = strchr(tmp, '=')) == NULL)
312 break;
313 *set++ = '\0';
314 if ((next = strchr(set, ':')) != NULL)
315 *next++ = '\0';
316 while (tmp && *tmp) {
317 if ((end = strchr(tmp, ',')) != NULL)
318 *end++ = '\0';
319 if (Strcmp(tmp, lang) == 0) {
320 strncpy(buf, set, 100);
321 buf[99] = '\0';
322 Xfree(start);
323 return buf;
324 }
325 tmp = end;
326 }
327 tmp = next;
328 } while (tmp && *tmp);
329 Xfree(start);
330 return NULL;
331 }
332 #else
333 char *
_XkbGetCharset(void)334 _XkbGetCharset(void)
335 {
336 char *tmp;
337 XLCd lcd;
338
339 tmp = getenv("_XKB_CHARSET");
340 if (tmp)
341 return tmp;
342
343 lcd = _XlcCurrentLC();
344 if (lcd)
345 return XLC_PUBLIC(lcd, encoding_name);
346
347 return NULL;
348 }
349 #endif
350