xkbfmisc.c revision 4642e01f
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 38#include <X11/X.h> 39#define NEED_EVENTS 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{ 54unsigned 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_agrave)&&(ks<=XK_ydiaeresis))) { 66 rtrn|= _XkbKSLower; 67 } 68 break; 69 case 1: /* latin 2 */ 70 if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))|| 71 ((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) { 72 rtrn|= _XkbKSUpper; 73 } 74 if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))|| 75 ((ks>=XK_racute)&&(ks<=XK_tcedilla))) { 76 rtrn|= _XkbKSLower; 77 } 78 break; 79 case 2: /* latin 3 */ 80 if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))|| 81 ((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) { 82 rtrn|= _XkbKSUpper; 83 } 84 if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))|| 85 ((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) { 86 rtrn|= _XkbKSLower; 87 } 88 break; 89 case 3: /* latin 4 */ 90 if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))|| 91 (ks==XK_ENG)|| 92 ((ks>=XK_Amacron)&&(ks<=XK_Umacron))) { 93 rtrn|= _XkbKSUpper; 94 } 95 if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))|| 96 (ks==XK_eng)|| 97 ((ks>=XK_amacron)&&(ks<=XK_umacron))) { 98 rtrn|= _XkbKSLower; 99 } 100 break; 101 case 18: /* latin 8 */ 102 if ((ks==XK_Babovedot)|| 103 ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))|| 104 ((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))|| 105 (ks==XK_Mabovedot)|| 106 (ks==XK_Pabovedot)|| 107 (ks==XK_Sabovedot)|| 108 (ks==XK_Wdiaeresis)|| 109 ((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) { 110 rtrn|= _XkbKSUpper; 111 } 112 if ((ks==XK_babovedot)|| 113 (ks==XK_dabovedot)|| 114 (ks==XK_fabovedot)|| 115 (ks==XK_mabovedot)|| 116 ((ks>=XK_wgrave)&&(ks<=XK_wacute))|| 117 (ks==XK_ygrave)|| 118 ((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) { 119 rtrn|= _XkbKSLower; 120 } 121 break; 122 case 19: /* latin 9 */ 123 if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) { 124 rtrn|= _XkbKSUpper; 125 } 126 if (ks==XK_oe) { 127 rtrn|= _XkbKSLower; 128 } 129 break; 130 } 131 return rtrn; 132} 133 134/***===================================================================***/ 135 136static Bool 137XkbWriteSectionFromName(FILE *file,char *sectionName,char *name) 138{ 139 fprintf(file," xkb_%-20s { include \"%s\" };\n",sectionName,name); 140 return True; 141} 142 143#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%'))) 144#define COMPLETE(n) ((n)&&(!NEED_DESC(n))) 145 146/* ARGSUSED */ 147static void 148_AddIncl( FILE * file, 149 XkbDescPtr xkb, 150 Bool topLevel, 151 Bool showImplicit, 152 int index, 153 void * priv) 154{ 155 if ((priv)&&(strcmp((char *)priv,"%")!=0)) 156 fprintf(file," include \"%s\"\n",(char *)priv); 157 return; 158} 159 160Bool 161XkbWriteXKBKeymapForNames( FILE * file, 162 XkbComponentNamesPtr names, 163 XkbDescPtr xkb, 164 unsigned want, 165 unsigned need) 166{ 167char * name,*tmp; 168unsigned complete; 169XkbNamesPtr old_names; 170int multi_section; 171unsigned wantNames,wantConfig,wantDflts; 172 173 complete= 0; 174 if ((name=names->keymap)==NULL) name= "default"; 175 if (COMPLETE(names->keycodes)) complete|= XkmKeyNamesMask; 176 if (COMPLETE(names->types)) complete|= XkmTypesMask; 177 if (COMPLETE(names->compat)) complete|= XkmCompatMapMask; 178 if (COMPLETE(names->symbols)) complete|= XkmSymbolsMask; 179 if (COMPLETE(names->geometry)) complete|= XkmGeometryMask; 180 want|= (complete|need); 181 if (want&XkmSymbolsMask) 182 want|= XkmKeyNamesMask|XkmTypesMask; 183 184 if (want==0) 185 return False; 186 187 if (xkb) { 188 old_names = xkb->names; 189 190 xkb->defined = 0; 191 /* Wow would it ever be neat if we didn't need this noise. */ 192 if (xkb->names && xkb->names->keys) 193 xkb->defined |= XkmKeyNamesMask; 194 if (xkb->map && xkb->map->types) 195 xkb->defined |= XkmTypesMask; 196 if (xkb->compat) 197 xkb->defined |= XkmCompatMapMask; 198 if (xkb->map && xkb->map->num_syms) 199 xkb->defined |= XkmSymbolsMask; 200 if (xkb->indicators) 201 xkb->defined |= XkmIndicatorsMask; 202 if (xkb->geom) 203 xkb->defined |= XkmGeometryMask; 204 } 205 else { 206 old_names= NULL; 207 } 208 209 wantConfig= want&(~complete); 210 if (xkb!=NULL) { 211 if (wantConfig&XkmTypesMask) { 212 if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes)) 213 wantConfig&= ~XkmTypesMask; 214 } 215 if (wantConfig&XkmCompatMapMask) { 216 if ((!xkb->compat) || (xkb->compat->num_si<1)) 217 wantConfig&= ~XkmCompatMapMask; 218 } 219 if (wantConfig&XkmSymbolsMask) { 220 if ((!xkb->map) || (!xkb->map->key_sym_map)) 221 wantConfig&= ~XkmSymbolsMask; 222 } 223 if (wantConfig&XkmIndicatorsMask) { 224 if (!xkb->indicators) 225 wantConfig&= ~XkmIndicatorsMask; 226 } 227 if (wantConfig&XkmKeyNamesMask) { 228 if ((!xkb->names)||(!xkb->names->keys)) 229 wantConfig&= ~XkmKeyNamesMask; 230 } 231 if ((wantConfig&XkmGeometryMask)&&(!xkb->geom)) 232 wantConfig&= ~XkmGeometryMask; 233 } 234 else { 235 wantConfig= 0; 236 } 237 complete|= wantConfig; 238 239 wantDflts= 0; 240 wantNames= want&(~complete); 241 if ((xkb!=NULL) && (old_names!=NULL)) { 242 if (wantNames&XkmTypesMask) { 243 if (old_names->types!=None) { 244 tmp= XkbAtomGetString(old_names->types); 245 names->types= _XkbDupString(tmp); 246 } 247 else { 248 wantDflts|= XkmTypesMask; 249 } 250 complete|= XkmTypesMask; 251 } 252 if (wantNames&XkmCompatMapMask) { 253 if (old_names->compat!=None) { 254 tmp= XkbAtomGetString(old_names->compat); 255 names->compat= _XkbDupString(tmp); 256 } 257 else wantDflts|= XkmCompatMapMask; 258 complete|= XkmCompatMapMask; 259 } 260 if (wantNames&XkmSymbolsMask) { 261 if (old_names->symbols==None) 262 return False; 263 tmp= XkbAtomGetString(old_names->symbols); 264 names->symbols= _XkbDupString(tmp); 265 complete|= XkmSymbolsMask; 266 } 267 if (wantNames&XkmKeyNamesMask) { 268 if (old_names->keycodes!=None) { 269 tmp= XkbAtomGetString(old_names->keycodes); 270 names->keycodes= _XkbDupString(tmp); 271 } 272 else wantDflts|= XkmKeyNamesMask; 273 complete|= XkmKeyNamesMask; 274 } 275 if (wantNames&XkmGeometryMask) { 276 if (old_names->geometry==None) 277 return False; 278 tmp= XkbAtomGetString(old_names->geometry); 279 names->geometry= _XkbDupString(tmp); 280 complete|= XkmGeometryMask; 281 wantNames&= ~XkmGeometryMask; 282 } 283 } 284 if (complete&XkmCompatMapMask) 285 complete|= XkmIndicatorsMask|XkmVirtualModsMask; 286 else if (complete&(XkmSymbolsMask|XkmTypesMask)) 287 complete|= XkmVirtualModsMask; 288 if (need & (~complete)) 289 return False; 290 if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete))) 291 return False; 292 293 multi_section= 1; 294 if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&& 295 ((complete&(~XkmKeymapLegal))==0)) { 296 fprintf(file,"xkb_keymap \"%s\" {\n",name); 297 } 298 else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&& 299 ((complete&(~XkmSemanticsLegal))==0)) { 300 fprintf(file,"xkb_semantics \"%s\" {\n",name); 301 } 302 else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&& 303 ((complete&(~XkmLayoutLegal))==0)) { 304 fprintf(file,"xkb_layout \"%s\" {\n",name); 305 } 306 else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) { 307 multi_section= 0; 308 } 309 else { 310 return False; 311 } 312 313 wantNames= complete&(~(wantConfig|wantDflts)); 314 name= names->keycodes; 315 if (wantConfig&XkmKeyNamesMask) 316 XkbWriteXKBKeycodes(file,xkb,False,False,_AddIncl,name); 317 else if (wantDflts&XkmKeyNamesMask) 318 fprintf(stderr,"Default symbols not implemented yet!\n"); 319 else if (wantNames&XkmKeyNamesMask) 320 XkbWriteSectionFromName(file,"keycodes",name); 321 322 name= names->types; 323 if (wantConfig&XkmTypesMask) 324 XkbWriteXKBKeyTypes(file,xkb,False,False,_AddIncl,name); 325 else if (wantDflts&XkmTypesMask) 326 fprintf(stderr,"Default types not implemented yet!\n"); 327 else if (wantNames&XkmTypesMask) 328 XkbWriteSectionFromName(file,"types",name); 329 330 name= names->compat; 331 if (wantConfig&XkmCompatMapMask) 332 XkbWriteXKBCompatMap(file,xkb,False,False,_AddIncl,name); 333 else if (wantDflts&XkmCompatMapMask) 334 fprintf(stderr,"Default interps not implemented yet!\n"); 335 else if (wantNames&XkmCompatMapMask) 336 XkbWriteSectionFromName(file,"compatibility",name); 337 338 name= names->symbols; 339 if (wantConfig&XkmSymbolsMask) 340 XkbWriteXKBSymbols(file,xkb,False,False,_AddIncl,name); 341 else if (wantNames&XkmSymbolsMask) 342 XkbWriteSectionFromName(file,"symbols",name); 343 344 name= names->geometry; 345 if (wantConfig&XkmGeometryMask) 346 XkbWriteXKBGeometry(file,xkb,False,False,_AddIncl,name); 347 else if (wantNames&XkmGeometryMask) 348 XkbWriteSectionFromName(file,"geometry",name); 349 350 if (multi_section) 351 fprintf(file,"};\n"); 352 return True; 353} 354 355/***====================================================================***/ 356 357int 358XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases) 359{ 360register int i; 361 362 if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) 363 return 0; 364 for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 365 if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0) 366 return i; 367 } 368 if (!use_aliases) 369 return 0; 370 if (xkb->geom && xkb->geom->key_aliases) { 371 XkbKeyAliasPtr a; 372 a= xkb->geom->key_aliases; 373 for (i=0;i<xkb->geom->num_key_aliases;i++,a++) { 374 if (strncmp(name,a->alias,XkbKeyNameLength)==0) 375 return XkbFindKeycodeByName(xkb,a->real,False); 376 } 377 } 378 if (xkb->names && xkb->names->key_aliases) { 379 XkbKeyAliasPtr a; 380 a= xkb->names->key_aliases; 381 for (i=0;i<xkb->names->num_key_aliases;i++,a++) { 382 if (strncmp(name,a->alias,XkbKeyNameLength)==0) 383 return XkbFindKeycodeByName(xkb,a->real,False); 384 } 385 } 386 return 0; 387} 388 389 390unsigned 391XkbConvertGetByNameComponents(Bool toXkm,unsigned orig) 392{ 393unsigned rtrn; 394 395 rtrn= 0; 396 if (toXkm) { 397 if (orig&XkbGBN_TypesMask) rtrn|= XkmTypesMask; 398 if (orig&XkbGBN_CompatMapMask) rtrn|= XkmCompatMapMask; 399 if (orig&XkbGBN_SymbolsMask) rtrn|= XkmSymbolsMask; 400 if (orig&XkbGBN_IndicatorMapMask) rtrn|= XkmIndicatorsMask; 401 if (orig&XkbGBN_KeyNamesMask) rtrn|= XkmKeyNamesMask; 402 if (orig&XkbGBN_GeometryMask) rtrn|= XkmGeometryMask; 403 } 404 else { 405 if (orig&XkmTypesMask) rtrn|= XkbGBN_TypesMask; 406 if (orig&XkmCompatMapMask) rtrn|= XkbGBN_CompatMapMask; 407 if (orig&XkmSymbolsMask) rtrn|= XkbGBN_SymbolsMask; 408 if (orig&XkmIndicatorsMask) rtrn|= XkbGBN_IndicatorMapMask; 409 if (orig&XkmKeyNamesMask) rtrn|= XkbGBN_KeyNamesMask; 410 if (orig&XkmGeometryMask) rtrn|= XkbGBN_GeometryMask; 411 if (orig!=0) rtrn|= XkbGBN_OtherNamesMask; 412 } 413 return rtrn; 414} 415 416/* all latin-1 alphanumerics, plus parens, slash, minus, underscore and */ 417/* wildcards */ 418 419static unsigned char componentSpecLegal[] = { 420 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, 421 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, 422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 423 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 424}; 425 426void 427XkbEnsureSafeMapName(char *name) 428{ 429 if (name==NULL) 430 return; 431 while (*name!='\0') { 432 if ((componentSpecLegal[(*name)/8]&(1<<((*name)%8)))==0) 433 *name= '_'; 434 name++; 435 } 436 return; 437} 438 439/***====================================================================***/ 440 441#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/')) 442 443Bool 444XkbNameMatchesPattern(char *name,char *ptrn) 445{ 446 while (ptrn[0]!='\0') { 447 if (name[0]=='\0') { 448 if (ptrn[0]=='*') { 449 ptrn++; 450 continue; 451 } 452 return False; 453 } 454 if (ptrn[0]=='?') { 455 if (UNMATCHABLE(name[0])) 456 return False; 457 } 458 else if (ptrn[0]=='*') { 459 if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn)) 460 return True; 461 return XkbNameMatchesPattern(name,ptrn+1); 462 } 463 else if (ptrn[0]!=name[0]) 464 return False; 465 name++; 466 ptrn++; 467 } 468 /* if we get here, the pattern is exhausted (-:just like me:-) */ 469 return (name[0]=='\0'); 470} 471