xkbfmisc.c revision 35c4bbdf
11.6Ssimonb/************************************************************ 21.1Sjonathan Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 31.2Sjonathan 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} 470