Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / xkbfmisc.c
CommitLineData
a09e091a
JB
1/************************************************************
2 Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <ctype.h>
33#include <stdlib.h>
34
35#include <X11/Xos.h>
36#include <X11/Xfuncs.h>
37#include <X11/extensions/XKMformat.h>
38
39#include <X11/X.h>
40#include <X11/keysym.h>
41#include <X11/Xproto.h>
42#include "misc.h"
43#include "inputstr.h"
44#include "dix.h"
45#include "xkbstr.h"
46#define XKBSRV_NEED_FILE_FUNCS 1
47#include <xkbsrv.h>
48#include "xkbgeom.h"
49#include "xkb.h"
50
51unsigned
52_XkbKSCheckCase(KeySym ks)
53{
54 unsigned set, rtrn;
55
56 set = (ks & (~0xff)) >> 8;
57 rtrn = 0;
58 switch (set) {
59 case 0: /* latin 1 */
60 if (((ks >= XK_A) && (ks <= XK_Z)) ||
61 ((ks >= XK_Agrave) && (ks <= XK_THORN) && (ks != XK_multiply))) {
62 rtrn |= _XkbKSUpper;
63 }
64 if (((ks >= XK_a) && (ks <= XK_z)) ||
65 ((ks >= XK_ssharp) && (ks <= XK_ydiaeresis) &&
66 (ks != XK_division))) {
67 rtrn |= _XkbKSLower;
68 }
69 break;
70 case 1: /* latin 2 */
71 if (((ks >= XK_Aogonek) && (ks <= XK_Zabovedot) && (ks != XK_breve)) ||
72 ((ks >= XK_Racute) && (ks <= XK_Tcedilla))) {
73 rtrn |= _XkbKSUpper;
74 }
75 if (((ks >= XK_aogonek) && (ks <= XK_zabovedot) && (ks != XK_ogonek) &&
76 (ks != XK_caron) && (ks != XK_doubleacute)) || ((ks >= XK_racute)
77 && (ks <=
78 XK_tcedilla)))
79 {
80 rtrn |= _XkbKSLower;
81 }
82 break;
83 case 2: /* latin 3 */
84 if (((ks >= XK_Hstroke) && (ks <= XK_Jcircumflex)) ||
85 ((ks >= XK_Cabovedot) && (ks <= XK_Scircumflex))) {
86 rtrn |= _XkbKSUpper;
87 }
88 if (((ks >= XK_hstroke) && (ks <= XK_jcircumflex)) ||
89 ((ks >= XK_cabovedot) && (ks <= XK_scircumflex))) {
90 rtrn |= _XkbKSLower;
91 }
92 break;
93 case 3: /* latin 4 */
94 if (((ks >= XK_Rcedilla) && (ks <= XK_Tslash)) ||
95 (ks == XK_ENG) || ((ks >= XK_Amacron) && (ks <= XK_Umacron))) {
96 rtrn |= _XkbKSUpper;
97 }
98 if ((ks == XK_kra) ||
99 ((ks >= XK_rcedilla) && (ks <= XK_tslash)) ||
100 (ks == XK_eng) || ((ks >= XK_amacron) && (ks <= XK_umacron))) {
101 rtrn |= _XkbKSLower;
102 }
103 break;
104 case 18: /* latin 8 */
105 if ((ks == XK_Wcircumflex) ||
106 (ks == XK_Ycircumflex) ||
107 (ks == XK_Babovedot) ||
108 (ks == XK_Dabovedot) ||
109 (ks == XK_Fabovedot) ||
110 (ks == XK_Mabovedot) ||
111 (ks == XK_Pabovedot) ||
112 (ks == XK_Sabovedot) ||
113 (ks == XK_Tabovedot) ||
114 (ks == XK_Wgrave) ||
115 (ks == XK_Wacute) || (ks == XK_Wdiaeresis) || (ks == XK_Ygrave)) {
116 rtrn |= _XkbKSUpper;
117 }
118 if ((ks == XK_wcircumflex) ||
119 (ks == XK_ycircumflex) ||
120 (ks == XK_babovedot) ||
121 (ks == XK_dabovedot) ||
122 (ks == XK_fabovedot) ||
123 (ks == XK_mabovedot) ||
124 (ks == XK_pabovedot) ||
125 (ks == XK_sabovedot) ||
126 (ks == XK_tabovedot) ||
127 (ks == XK_wgrave) ||
128 (ks == XK_wacute) || (ks == XK_wdiaeresis) || (ks == XK_ygrave)) {
129 rtrn |= _XkbKSLower;
130 }
131 break;
132 case 19: /* latin 9 */
133 if ((ks == XK_OE) || (ks == XK_Ydiaeresis)) {
134 rtrn |= _XkbKSUpper;
135 }
136 if (ks == XK_oe) {
137 rtrn |= _XkbKSLower;
138 }
139 break;
140 }
141 return rtrn;
142}
143
144/***===================================================================***/
145
146static Bool
147XkbWriteSectionFromName(FILE * file, const char *sectionName, const char *name)
148{
149 fprintf(file, " xkb_%-20s { include \"%s\" };\n", sectionName, name);
150 return TRUE;
151}
152
153#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%')))
154#define COMPLETE(n) ((n)&&(!NEED_DESC(n)))
155
156/* ARGSUSED */
157static void
158_AddIncl(FILE * file,
159 XkbDescPtr xkb,
160 Bool topLevel, Bool showImplicit, int index, void *priv)
161{
162 if ((priv) && (strcmp((char *) priv, "%") != 0))
163 fprintf(file, " include \"%s\"\n", (char *) priv);
164 return;
165}
166
167Bool
168XkbWriteXKBKeymapForNames(FILE * file,
169 XkbComponentNamesPtr names,
170 XkbDescPtr xkb, unsigned want, unsigned need)
171{
172 const char *tmp;
173 unsigned complete;
174 XkbNamesPtr old_names;
175 int multi_section;
176 unsigned wantNames, wantConfig, wantDflts;
177
178 complete = 0;
179 if (COMPLETE(names->keycodes))
180 complete |= XkmKeyNamesMask;
181 if (COMPLETE(names->types))
182 complete |= XkmTypesMask;
183 if (COMPLETE(names->compat))
184 complete |= XkmCompatMapMask;
185 if (COMPLETE(names->symbols))
186 complete |= XkmSymbolsMask;
187 if (COMPLETE(names->geometry))
188 complete |= XkmGeometryMask;
189 want |= (complete | need);
190 if (want & XkmSymbolsMask)
191 want |= XkmKeyNamesMask | XkmTypesMask;
192
193 if (want == 0)
194 return FALSE;
195
196 if (xkb) {
197 old_names = xkb->names;
198
199 xkb->defined = 0;
200 /* Wow would it ever be neat if we didn't need this noise. */
201 if (xkb->names && xkb->names->keys)
202 xkb->defined |= XkmKeyNamesMask;
203 if (xkb->map && xkb->map->types)
204 xkb->defined |= XkmTypesMask;
205 if (xkb->compat)
206 xkb->defined |= XkmCompatMapMask;
207 if (xkb->map && xkb->map->num_syms)
208 xkb->defined |= XkmSymbolsMask;
209 if (xkb->indicators)
210 xkb->defined |= XkmIndicatorsMask;
211 if (xkb->geom)
212 xkb->defined |= XkmGeometryMask;
213 }
214 else {
215 old_names = NULL;
216 }
217
218 wantConfig = want & (~complete);
219 if (xkb != NULL) {
220 if (wantConfig & XkmTypesMask) {
221 if ((!xkb->map) || (xkb->map->num_types < XkbNumRequiredTypes))
222 wantConfig &= ~XkmTypesMask;
223 }
224 if (wantConfig & XkmCompatMapMask) {
225 if ((!xkb->compat) || (xkb->compat->num_si < 1))
226 wantConfig &= ~XkmCompatMapMask;
227 }
228 if (wantConfig & XkmSymbolsMask) {
229 if ((!xkb->map) || (!xkb->map->key_sym_map))
230 wantConfig &= ~XkmSymbolsMask;
231 }
232 if (wantConfig & XkmIndicatorsMask) {
233 if (!xkb->indicators)
234 wantConfig &= ~XkmIndicatorsMask;
235 }
236 if (wantConfig & XkmKeyNamesMask) {
237 if ((!xkb->names) || (!xkb->names->keys))
238 wantConfig &= ~XkmKeyNamesMask;
239 }
240 if ((wantConfig & XkmGeometryMask) && (!xkb->geom))
241 wantConfig &= ~XkmGeometryMask;
242 }
243 else {
244 wantConfig = 0;
245 }
246 complete |= wantConfig;
247
248 wantDflts = 0;
249 wantNames = want & (~complete);
250 if ((xkb != NULL) && (old_names != NULL)) {
251 if (wantNames & XkmTypesMask) {
252 if (old_names->types != None) {
253 tmp = NameForAtom(old_names->types);
254 names->types = Xstrdup(tmp);
255 }
256 else {
257 wantDflts |= XkmTypesMask;
258 }
259 complete |= XkmTypesMask;
260 }
261 if (wantNames & XkmCompatMapMask) {
262 if (old_names->compat != None) {
263 tmp = NameForAtom(old_names->compat);
264 names->compat = Xstrdup(tmp);
265 }
266 else
267 wantDflts |= XkmCompatMapMask;
268 complete |= XkmCompatMapMask;
269 }
270 if (wantNames & XkmSymbolsMask) {
271 if (old_names->symbols == None)
272 return FALSE;
273 tmp = NameForAtom(old_names->symbols);
274 names->symbols = Xstrdup(tmp);
275 complete |= XkmSymbolsMask;
276 }
277 if (wantNames & XkmKeyNamesMask) {
278 if (old_names->keycodes != None) {
279 tmp = NameForAtom(old_names->keycodes);
280 names->keycodes = Xstrdup(tmp);
281 }
282 else
283 wantDflts |= XkmKeyNamesMask;
284 complete |= XkmKeyNamesMask;
285 }
286 if (wantNames & XkmGeometryMask) {
287 if (old_names->geometry == None)
288 return FALSE;
289 tmp = NameForAtom(old_names->geometry);
290 names->geometry = Xstrdup(tmp);
291 complete |= XkmGeometryMask;
292 wantNames &= ~XkmGeometryMask;
293 }
294 }
295 if (complete & XkmCompatMapMask)
296 complete |= XkmIndicatorsMask | XkmVirtualModsMask;
297 else if (complete & (XkmSymbolsMask | XkmTypesMask))
298 complete |= XkmVirtualModsMask;
299 if (need & (~complete))
300 return FALSE;
301 if ((complete & XkmSymbolsMask) &&
302 ((XkmKeyNamesMask | XkmTypesMask) & (~complete)))
303 return FALSE;
304
305 multi_section = 1;
306 if (((complete & XkmKeymapRequired) == XkmKeymapRequired) &&
307 ((complete & (~XkmKeymapLegal)) == 0)) {
308 fprintf(file, "xkb_keymap \"default\" {\n");
309 }
310 else if (((complete & XkmSemanticsRequired) == XkmSemanticsRequired) &&
311 ((complete & (~XkmSemanticsLegal)) == 0)) {
312 fprintf(file, "xkb_semantics \"default\" {\n");
313 }
314 else if (((complete & XkmLayoutRequired) == XkmLayoutRequired) &&
315 ((complete & (~XkmLayoutLegal)) == 0)) {
316 fprintf(file, "xkb_layout \"default\" {\n");
317 }
318 else if (XkmSingleSection(complete & (~XkmVirtualModsMask))) {
319 multi_section = 0;
320 }
321 else {
322 return FALSE;
323 }
324
325 wantNames = complete & (~(wantConfig | wantDflts));
326 if (wantConfig & XkmKeyNamesMask)
327 XkbWriteXKBKeycodes(file, xkb, FALSE, FALSE, _AddIncl, names->keycodes);
328 else if (wantDflts & XkmKeyNamesMask)
329 fprintf(stderr, "Default symbols not implemented yet!\n");
330 else if (wantNames & XkmKeyNamesMask)
331 XkbWriteSectionFromName(file, "keycodes", names->keycodes);
332
333 if (wantConfig & XkmTypesMask)
334 XkbWriteXKBKeyTypes(file, xkb, FALSE, FALSE, _AddIncl, names->types);
335 else if (wantDflts & XkmTypesMask)
336 fprintf(stderr, "Default types not implemented yet!\n");
337 else if (wantNames & XkmTypesMask)
338 XkbWriteSectionFromName(file, "types", names->types);
339
340 if (wantConfig & XkmCompatMapMask)
341 XkbWriteXKBCompatMap(file, xkb, FALSE, FALSE, _AddIncl, names->compat);
342 else if (wantDflts & XkmCompatMapMask)
343 fprintf(stderr, "Default interps not implemented yet!\n");
344 else if (wantNames & XkmCompatMapMask)
345 XkbWriteSectionFromName(file, "compatibility", names->compat);
346
347 if (wantConfig & XkmSymbolsMask)
348 XkbWriteXKBSymbols(file, xkb, FALSE, FALSE, _AddIncl, names->symbols);
349 else if (wantNames & XkmSymbolsMask)
350 XkbWriteSectionFromName(file, "symbols", names->symbols);
351
352 if (wantConfig & XkmGeometryMask)
353 XkbWriteXKBGeometry(file, xkb, FALSE, FALSE, _AddIncl, names->geometry);
354 else if (wantNames & XkmGeometryMask)
355 XkbWriteSectionFromName(file, "geometry", names->geometry);
356
357 if (multi_section)
358 fprintf(file, "};\n");
359 return TRUE;
360}
361
362/***====================================================================***/
363
364int
365XkbFindKeycodeByName(XkbDescPtr xkb, char *name, Bool use_aliases)
366{
367 register int i;
368
369 if ((!xkb) || (!xkb->names) || (!xkb->names->keys))
370 return 0;
371 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
372 if (strncmp(xkb->names->keys[i].name, name, XkbKeyNameLength) == 0)
373 return i;
374 }
375 if (!use_aliases)
376 return 0;
377 if (xkb->geom && xkb->geom->key_aliases) {
378 XkbKeyAliasPtr a;
379
380 a = xkb->geom->key_aliases;
381 for (i = 0; i < xkb->geom->num_key_aliases; i++, a++) {
382 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
383 return XkbFindKeycodeByName(xkb, a->real, FALSE);
384 }
385 }
386 if (xkb->names && xkb->names->key_aliases) {
387 XkbKeyAliasPtr a;
388
389 a = xkb->names->key_aliases;
390 for (i = 0; i < xkb->names->num_key_aliases; i++, a++) {
391 if (strncmp(name, a->alias, XkbKeyNameLength) == 0)
392 return XkbFindKeycodeByName(xkb, a->real, FALSE);
393 }
394 }
395 return 0;
396}
397
398unsigned
399XkbConvertGetByNameComponents(Bool toXkm, unsigned orig)
400{
401 unsigned rtrn;
402
403 rtrn = 0;
404 if (toXkm) {
405 if (orig & XkbGBN_TypesMask)
406 rtrn |= XkmTypesMask;
407 if (orig & XkbGBN_CompatMapMask)
408 rtrn |= XkmCompatMapMask;
409 if (orig & XkbGBN_SymbolsMask)
410 rtrn |= XkmSymbolsMask;
411 if (orig & XkbGBN_IndicatorMapMask)
412 rtrn |= XkmIndicatorsMask;
413 if (orig & XkbGBN_KeyNamesMask)
414 rtrn |= XkmKeyNamesMask;
415 if (orig & XkbGBN_GeometryMask)
416 rtrn |= XkmGeometryMask;
417 }
418 else {
419 if (orig & XkmTypesMask)
420 rtrn |= XkbGBN_TypesMask;
421 if (orig & XkmCompatMapMask)
422 rtrn |= XkbGBN_CompatMapMask;
423 if (orig & XkmSymbolsMask)
424 rtrn |= XkbGBN_SymbolsMask;
425 if (orig & XkmIndicatorsMask)
426 rtrn |= XkbGBN_IndicatorMapMask;
427 if (orig & XkmKeyNamesMask)
428 rtrn |= XkbGBN_KeyNamesMask;
429 if (orig & XkmGeometryMask)
430 rtrn |= XkbGBN_GeometryMask;
431 if (orig != 0)
432 rtrn |= XkbGBN_OtherNamesMask;
433 }
434 return rtrn;
435}
436
437/***====================================================================***/
438
439#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/'))
440
441Bool
442XkbNameMatchesPattern(char *name, char *ptrn)
443{
444 while (ptrn[0] != '\0') {
445 if (name[0] == '\0') {
446 if (ptrn[0] == '*') {
447 ptrn++;
448 continue;
449 }
450 return FALSE;
451 }
452 if (ptrn[0] == '?') {
453 if (UNMATCHABLE(name[0]))
454 return FALSE;
455 }
456 else if (ptrn[0] == '*') {
457 if ((!UNMATCHABLE(name[0])) &&
458 XkbNameMatchesPattern(name + 1, ptrn))
459 return TRUE;
460 return XkbNameMatchesPattern(name, ptrn + 1);
461 }
462 else if (ptrn[0] != name[0])
463 return FALSE;
464 name++;
465 ptrn++;
466 }
467 /* if we get here, the pattern is exhausted (-:just like me:-) */
468 return name[0] == '\0';
469}