XKBCvt.c 9.37 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*

Copyright 1988, 1989, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.

*/

29
30
31
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <X11/X.h>
#include <X11/Xlib.h>
#include "Xlibint.h"
#include "Xlcint.h"
#include "XlcPubI.h"
Egbert Eich's avatar
Egbert Eich committed
41
#include "Ximint.h"
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <X11/Xutil.h>
#include <X11/Xmd.h>
#define XK_LATIN1
#define XK_PUBLISHING
#include <X11/keysym.h>
#include <X11/extensions/XKBproto.h>
#include "XKBlibint.h"
#include <X11/Xlocale.h>
#include <ctype.h>
#include <X11/Xos.h>

#ifdef __sgi_not_xconsortium
#define	XKB_EXTEND_LOOKUP_STRING
#endif

57
static int
58
59
60
61
_XkbHandleSpecialSym(KeySym keysym, char *buffer, int nbytes, int *extra_rtrn)
{
    /* try to convert to Latin-1, handling ctrl */
    if (!(((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) ||
62
63
64
65
66
67
68
69
70
71
72
          (keysym == XK_Return) || (keysym == XK_Escape) ||
          (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) ||
          (keysym == XK_KP_Enter) ||
          ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) ||
          (keysym == XK_KP_Equal) || (keysym == XK_Delete)))
        return 0;

    if (nbytes < 1) {
        if (extra_rtrn)
            *extra_rtrn = 1;
        return 0;
73
74
75
    }
    /* if X keysym, convert to ascii by grabbing low 7 bits */
    if (keysym == XK_KP_Space)
76
77
78
        buffer[0] = XK_space & 0x7F;            /* patch encoding botch */
    else
        buffer[0] = (char) (keysym & 0x7F);
79
80
81
82
    return 1;
}

/*ARGSUSED*/
83
static int
84
85
86
87
88
_XkbKSToKnownSet(XPointer priv,
                 KeySym keysym,
                 char *buffer,
                 int nbytes,
                 int *extra_rtrn)
89
{
90
    char tbuf[8], *buf;
91
92

    if (extra_rtrn)
93
        *extra_rtrn = 0;
94
95

    /* convert "dead" diacriticals for dumb applications */
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    if ((keysym & 0xffffff00) == 0xfe00) {
        switch (keysym) {
        case XK_dead_grave:            keysym = XK_grave; break;
        case XK_dead_acute:            keysym = XK_acute; break;
        case XK_dead_circumflex:       keysym = XK_asciicircum; break;
        case XK_dead_tilde:            keysym = XK_asciitilde; break;
        case XK_dead_macron:           keysym = XK_macron; break;
        case XK_dead_breve:            keysym = XK_breve; break;
        case XK_dead_abovedot:         keysym = XK_abovedot; break;
        case XK_dead_diaeresis:        keysym = XK_diaeresis; break;
        case XK_dead_abovering:        keysym = XK_degree; break;
        case XK_dead_doubleacute:      keysym = XK_doubleacute; break;
        case XK_dead_caron:            keysym = XK_caron; break;
        case XK_dead_cedilla:          keysym = XK_cedilla; break;
        case XK_dead_ogonek:           keysym = XK_ogonek; break;
        case XK_dead_iota:             keysym = XK_Greek_iota; break;
112
#ifdef XK_KATAKANA
113
114
        case XK_dead_voiced_sound:     keysym = XK_voicedsound; break;
        case XK_dead_semivoiced_sound: keysym = XK_semivoicedsound; break;
115
#endif
116
        }
117
118
    }

119
120
121
122
    if (nbytes < 1)
        buf = tbuf;
    else
        buf = buffer;
123

124
125
    if ((keysym & 0xffffff00) == 0xff00) {
        return _XkbHandleSpecialSym(keysym, buf, nbytes, extra_rtrn);
126
    }
127
    return _XimGetCharCode(priv, keysym, (unsigned char *) buf, nbytes);
128
129
130
}

typedef struct _XkbToKS {
131
132
    unsigned prefix;
    char *map;
133
134
135
136
} XkbToKS;

/*ARGSUSED*/
static KeySym
137
_XkbKnownSetToKS(XPointer priv, char *buffer, int nbytes, Status *status)
138
{
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    if (nbytes != 1)
        return NoSymbol;
    if (((buffer[0] & 0x80) == 0) && (buffer[0] >= 32))
        return buffer[0];
    else if ((buffer[0] & 0x7f) >= 32) {
        XkbToKS *map = (XkbToKS *) priv;

        if (map) {
            if (map->map)
                return map->prefix | map->map[buffer[0] & 0x7f];
            else
                return map->prefix | buffer[0];
        }
        return buffer[0];
153
154
155
156
157
158
159
    }
    return NoSymbol;
}

static KeySym
__XkbDefaultToUpper(KeySym sym)
{
160
    KeySym lower, upper;
161
162
163
164
165

    XConvertCase(sym, &lower, &upper);
    return upper;
}

Egbert Eich's avatar
Egbert Eich committed
166
#ifdef XKB_EXTEND_LOOKUP_STRING
167
168
169
170
171
172
static int
Strcmp(char *str1, char *str2)
{
    char str[256];
    char c, *s;

Egbert Eich's avatar
Egbert Eich committed
173
174
175
176
    /*
     * unchecked strings from the environment can end up here, so check
     * the length before copying.
     */
177
178
    if (strlen(str1) >= sizeof(str))    /* almost certain it's a mismatch */
        return 1;
179

180
181
182
183
    for (s = str; (c = *str1++);) {
        if (isupper(c))
            c = tolower(c);
        *s++ = c;
184
185
186
187
    }
    *s = '\0';
    return (strcmp(str, str2));
}
Egbert Eich's avatar
Egbert Eich committed
188
#endif
189

190
int
191
_XkbGetConverters(const char *encoding_name, XkbConverters * cvt_rtrn)
192
{
193
194
    if (!cvt_rtrn)
        return 0;
Egbert Eich's avatar
Egbert Eich committed
195
196
197
198
199
200

    cvt_rtrn->KSToMB = _XkbKSToKnownSet;
    cvt_rtrn->KSToMBPriv = _XimGetLocaleCode(encoding_name);
    cvt_rtrn->MBToKS = _XkbKnownSetToKS;
    cvt_rtrn->MBToKSPriv = NULL;
    cvt_rtrn->KSToUpper = __XkbDefaultToUpper;
201
202
203
204
205
    return 1;
}

/***====================================================================***/

206
/*
207
208
209
210
211
212
 * The function _XkbGetCharset seems to be missnamed as what it seems to
 * be used for is to determine the encoding-name for the locale. ???
 */

#ifdef XKB_EXTEND_LOOKUP_STRING

213
/*
214
215
216
217
218
219
 * XKB_EXTEND_LOOKUP_STRING is not used by the SI. It is used by various
 * X Consortium/X Project Team members, so we leave it in the source as
 * an simplify integration by these companies.
 */

#define	CHARSET_FILE	"/usr/lib/X11/input/charsets"
220
221
222
223
224
225
226
227
static char *_XkbKnownLanguages =
    "c=ascii:da,de,en,es,fr,is,it,nl,no,pt,sv=iso8859-1:hu,pl,cs=iso8859-2:"
    "eo=iso8859-3:sp=iso8859-5:ar,ara=iso8859-6:el=iso8859-7:he=iso8859-8:"
    "tr=iso8859-9:lt,lv=iso8859-13:et,fi=iso8859-15:ru=koi8-r:uk=koi8-u:"
    "th,th_TH,th_TH.iso8859-11=iso8859-11:th_TH.TIS620=tis620:hy=armscii-8:"
    "vi=tcvn-5712:ka=georgian-academy:be,bg=microsoft-cp1251";

char *
228
_XkbGetCharset(void)
229
230
231
232
233
234
235
{
    /*
     * PAGE USAGE TUNING: explicitly initialize to move these to data
     * instead of bss
     */
    static char buf[100] = { 0 };
    char lang[256];
236
237
    char *start, *tmp, *end, *next, *set;
    char *country, *charset;
238
239
    char *locale;

240
241
242
243
    tmp = getenv("_XKB_CHARSET");
    if (tmp)
        return tmp;
    locale = setlocale(LC_CTYPE, NULL);
244

245
246
    if (locale == NULL)
        return NULL;
247

Egbert Eich's avatar
Egbert Eich committed
248
    if (strlen(locale) >= sizeof(lang))
249
        return NULL;
Egbert Eich's avatar
Egbert Eich committed
250

251
    for (tmp = lang; *tmp = *locale++; tmp++) {
252
253
        if (isupper(*tmp))
            *tmp = tolower(*tmp);
254
    }
255
256
257
258
259
260
261
262
263
264
265
    country = strchr(lang, '_');
    if (country) {
        *country++ = '\0';
        charset = strchr(country, '.');
        if (charset)
            *charset++ = '\0';
        if (charset) {
            strncpy(buf, charset, 99);
            buf[99] = '\0';
            return buf;
        }
266
    }
267
    else {
268
        charset = NULL;
269
270
    }

271
272
273
274
275
276
277
278
    if ((tmp = getenv("_XKB_LOCALE_CHARSETS")) != NULL) {
        start = _XkbAlloc(strlen(tmp) + 1);
        strcpy(start, tmp);
        tmp = start;
    }
    else {
        struct stat sbuf;
        FILE *file;
Egbert Eich's avatar
Egbert Eich committed
279
#ifndef __UNIXOS2__
280
        char *cf = CHARSET_FILE;
Egbert Eich's avatar
Egbert Eich committed
281
282
283
#else
        char *cf = __XOS2RedirRoot(CHARSET_FILE);
#endif
284
285
286
287

#ifndef S_ISREG
# define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
#endif
288

289
290
291
292
293
294
295
296
297
        if ((stat(cf, &sbuf) == 0) && S_ISREG(sbuf.st_mode) &&
            (file = fopen(cf, "r"))) {
            tmp = _XkbAlloc(sbuf.st_size + 1);
            if (tmp != NULL) {
                sbuf.st_size = (long) fread(tmp, 1, sbuf.st_size, file);
                tmp[sbuf.st_size] = '\0';
            }
            fclose(file);
        }
298
299
    }

300
301
302
303
304
    if (tmp == NULL) {
        tmp = _XkbAlloc(strlen(_XkbKnownLanguages) + 1);
        if (!tmp)
            return NULL;
        strcpy(tmp, _XkbKnownLanguages);
305
306
307
    }
    start = tmp;
    do {
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
        if ((set = strchr(tmp, '=')) == NULL)
            break;
        *set++ = '\0';
        if ((next = strchr(set, ':')) != NULL)
            *next++ = '\0';
        while (tmp && *tmp) {
            if ((end = strchr(tmp, ',')) != NULL)
                *end++ = '\0';
            if (Strcmp(tmp, lang) == 0) {
                strncpy(buf, set, 100);
                buf[99] = '\0';
                Xfree(start);
                return buf;
            }
            tmp = end;
        }
        tmp = next;
    } while (tmp && *tmp);
326
327
328
329
    Xfree(start);
    return NULL;
}
#else
330
char *
331
_XkbGetCharset(void)
332
333
334
335
{
    char *tmp;
    XLCd lcd;

336
337
338
    tmp = getenv("_XKB_CHARSET");
    if (tmp)
        return tmp;
339
340

    lcd = _XlcCurrentLC();
341
342
    if (lcd)
        return XLC_PUBLIC(lcd, encoding_name);
343
344
345
346

    return NULL;
}
#endif