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{ 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{ 167const char * tmp; 168unsigned complete; 169XkbNamesPtr old_names; 170int multi_section; 171unsigned wantNames,wantConfig,wantDflts; 172 173 complete= 0; 174 if (COMPLETE(names->keycodes)) complete|= XkmKeyNamesMask; 175 if (COMPLETE(names->types)) complete|= XkmTypesMask; 176 if (COMPLETE(names->compat)) complete|= XkmCompatMapMask; 177 if (COMPLETE(names->symbols)) complete|= XkmSymbolsMask; 178 if (COMPLETE(names->geometry)) complete|= XkmGeometryMask; 179 want|= (complete|need); 180 if (want&XkmSymbolsMask) 181 want|= XkmKeyNamesMask|XkmTypesMask; 182 183 if (want==0) 184 return FALSE; 185 186 if (xkb) { 187 old_names = xkb->names; 188 189 xkb->defined = 0; 190 /* Wow would it ever be neat if we didn't need this noise. */ 191 if (xkb->names && xkb->names->keys) 192 xkb->defined |= XkmKeyNamesMask; 193 if (xkb->map && xkb->map->types) 194 xkb->defined |= XkmTypesMask; 195 if (xkb->compat) 196 xkb->defined |= XkmCompatMapMask; 197 if (xkb->map && xkb->map->num_syms) 198 xkb->defined |= XkmSymbolsMask; 199 if (xkb->indicators) 200 xkb->defined |= XkmIndicatorsMask; 201 if (xkb->geom) 202 xkb->defined |= XkmGeometryMask; 203 } 204 else { 205 old_names= NULL; 206 } 207 208 wantConfig= want&(~complete); 209 if (xkb!=NULL) { 210 if (wantConfig&XkmTypesMask) { 211 if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes)) 212 wantConfig&= ~XkmTypesMask; 213 } 214 if (wantConfig&XkmCompatMapMask) { 215 if ((!xkb->compat) || (xkb->compat->num_si<1)) 216 wantConfig&= ~XkmCompatMapMask; 217 } 218 if (wantConfig&XkmSymbolsMask) { 219 if ((!xkb->map) || (!xkb->map->key_sym_map)) 220 wantConfig&= ~XkmSymbolsMask; 221 } 222 if (wantConfig&XkmIndicatorsMask) { 223 if (!xkb->indicators) 224 wantConfig&= ~XkmIndicatorsMask; 225 } 226 if (wantConfig&XkmKeyNamesMask) { 227 if ((!xkb->names)||(!xkb->names->keys)) 228 wantConfig&= ~XkmKeyNamesMask; 229 } 230 if ((wantConfig&XkmGeometryMask)&&(!xkb->geom)) 231 wantConfig&= ~XkmGeometryMask; 232 } 233 else { 234 wantConfig= 0; 235 } 236 complete|= wantConfig; 237 238 wantDflts= 0; 239 wantNames= want&(~complete); 240 if ((xkb!=NULL) && (old_names!=NULL)) { 241 if (wantNames&XkmTypesMask) { 242 if (old_names->types!=None) { 243 tmp= NameForAtom(old_names->types); 244 names->types= _XkbDupString(tmp); 245 } 246 else { 247 wantDflts|= XkmTypesMask; 248 } 249 complete|= XkmTypesMask; 250 } 251 if (wantNames&XkmCompatMapMask) { 252 if (old_names->compat!=None) { 253 tmp= NameForAtom(old_names->compat); 254 names->compat= _XkbDupString(tmp); 255 } 256 else wantDflts|= XkmCompatMapMask; 257 complete|= XkmCompatMapMask; 258 } 259 if (wantNames&XkmSymbolsMask) { 260 if (old_names->symbols==None) 261 return FALSE; 262 tmp= NameForAtom(old_names->symbols); 263 names->symbols= _XkbDupString(tmp); 264 complete|= XkmSymbolsMask; 265 } 266 if (wantNames&XkmKeyNamesMask) { 267 if (old_names->keycodes!=None) { 268 tmp= NameForAtom(old_names->keycodes); 269 names->keycodes= _XkbDupString(tmp); 270 } 271 else wantDflts|= XkmKeyNamesMask; 272 complete|= XkmKeyNamesMask; 273 } 274 if (wantNames&XkmGeometryMask) { 275 if (old_names->geometry==None) 276 return FALSE; 277 tmp= NameForAtom(old_names->geometry); 278 names->geometry= _XkbDupString(tmp); 279 complete|= XkmGeometryMask; 280 wantNames&= ~XkmGeometryMask; 281 } 282 } 283 if (complete&XkmCompatMapMask) 284 complete|= XkmIndicatorsMask|XkmVirtualModsMask; 285 else if (complete&(XkmSymbolsMask|XkmTypesMask)) 286 complete|= XkmVirtualModsMask; 287 if (need & (~complete)) 288 return FALSE; 289 if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete))) 290 return FALSE; 291 292 multi_section= 1; 293 if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&& 294 ((complete&(~XkmKeymapLegal))==0)) { 295 fprintf(file,"xkb_keymap \"default\" {\n"); 296 } 297 else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&& 298 ((complete&(~XkmSemanticsLegal))==0)) { 299 fprintf(file,"xkb_semantics \"default\" {\n"); 300 } 301 else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&& 302 ((complete&(~XkmLayoutLegal))==0)) { 303 fprintf(file,"xkb_layout \"default\" {\n"); 304 } 305 else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) { 306 multi_section= 0; 307 } 308 else { 309 return FALSE; 310 } 311 312 wantNames= complete&(~(wantConfig|wantDflts)); 313 if (wantConfig&XkmKeyNamesMask) 314 XkbWriteXKBKeycodes(file,xkb,FALSE,FALSE,_AddIncl,names->keycodes); 315 else if (wantDflts&XkmKeyNamesMask) 316 fprintf(stderr,"Default symbols not implemented yet!\n"); 317 else if (wantNames&XkmKeyNamesMask) 318 XkbWriteSectionFromName(file,"keycodes",names->keycodes); 319 320 if (wantConfig&XkmTypesMask) 321 XkbWriteXKBKeyTypes(file,xkb,FALSE,FALSE,_AddIncl,names->types); 322 else if (wantDflts&XkmTypesMask) 323 fprintf(stderr,"Default types not implemented yet!\n"); 324 else if (wantNames&XkmTypesMask) 325 XkbWriteSectionFromName(file,"types",names->types); 326 327 if (wantConfig&XkmCompatMapMask) 328 XkbWriteXKBCompatMap(file,xkb,FALSE,FALSE,_AddIncl,names->compat); 329 else if (wantDflts&XkmCompatMapMask) 330 fprintf(stderr,"Default interps not implemented yet!\n"); 331 else if (wantNames&XkmCompatMapMask) 332 XkbWriteSectionFromName(file,"compatibility",names->compat); 333 334 if (wantConfig&XkmSymbolsMask) 335 XkbWriteXKBSymbols(file,xkb,FALSE,FALSE,_AddIncl,names->symbols); 336 else if (wantNames&XkmSymbolsMask) 337 XkbWriteSectionFromName(file,"symbols",names->symbols); 338 339 if (wantConfig&XkmGeometryMask) 340 XkbWriteXKBGeometry(file,xkb,FALSE,FALSE,_AddIncl,names->geometry); 341 else if (wantNames&XkmGeometryMask) 342 XkbWriteSectionFromName(file,"geometry",names->geometry); 343 344 if (multi_section) 345 fprintf(file,"};\n"); 346 return TRUE; 347} 348 349/***====================================================================***/ 350 351int 352XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases) 353{ 354register int i; 355 356 if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) 357 return 0; 358 for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { 359 if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0) 360 return i; 361 } 362 if (!use_aliases) 363 return 0; 364 if (xkb->geom && xkb->geom->key_aliases) { 365 XkbKeyAliasPtr a; 366 a= xkb->geom->key_aliases; 367 for (i=0;i<xkb->geom->num_key_aliases;i++,a++) { 368 if (strncmp(name,a->alias,XkbKeyNameLength)==0) 369 return XkbFindKeycodeByName(xkb,a->real,FALSE); 370 } 371 } 372 if (xkb->names && xkb->names->key_aliases) { 373 XkbKeyAliasPtr a; 374 a= xkb->names->key_aliases; 375 for (i=0;i<xkb->names->num_key_aliases;i++,a++) { 376 if (strncmp(name,a->alias,XkbKeyNameLength)==0) 377 return XkbFindKeycodeByName(xkb,a->real,FALSE); 378 } 379 } 380 return 0; 381} 382 383 384unsigned 385XkbConvertGetByNameComponents(Bool toXkm,unsigned orig) 386{ 387unsigned rtrn; 388 389 rtrn= 0; 390 if (toXkm) { 391 if (orig&XkbGBN_TypesMask) rtrn|= XkmTypesMask; 392 if (orig&XkbGBN_CompatMapMask) rtrn|= XkmCompatMapMask; 393 if (orig&XkbGBN_SymbolsMask) rtrn|= XkmSymbolsMask; 394 if (orig&XkbGBN_IndicatorMapMask) rtrn|= XkmIndicatorsMask; 395 if (orig&XkbGBN_KeyNamesMask) rtrn|= XkmKeyNamesMask; 396 if (orig&XkbGBN_GeometryMask) rtrn|= XkmGeometryMask; 397 } 398 else { 399 if (orig&XkmTypesMask) rtrn|= XkbGBN_TypesMask; 400 if (orig&XkmCompatMapMask) rtrn|= XkbGBN_CompatMapMask; 401 if (orig&XkmSymbolsMask) rtrn|= XkbGBN_SymbolsMask; 402 if (orig&XkmIndicatorsMask) rtrn|= XkbGBN_IndicatorMapMask; 403 if (orig&XkmKeyNamesMask) rtrn|= XkbGBN_KeyNamesMask; 404 if (orig&XkmGeometryMask) rtrn|= XkbGBN_GeometryMask; 405 if (orig!=0) rtrn|= XkbGBN_OtherNamesMask; 406 } 407 return rtrn; 408} 409 410/***====================================================================***/ 411 412#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/')) 413 414Bool 415XkbNameMatchesPattern(char *name,char *ptrn) 416{ 417 while (ptrn[0]!='\0') { 418 if (name[0]=='\0') { 419 if (ptrn[0]=='*') { 420 ptrn++; 421 continue; 422 } 423 return FALSE; 424 } 425 if (ptrn[0]=='?') { 426 if (UNMATCHABLE(name[0])) 427 return FALSE; 428 } 429 else if (ptrn[0]=='*') { 430 if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn)) 431 return TRUE; 432 return XkbNameMatchesPattern(name,ptrn+1); 433 } 434 else if (ptrn[0]!=name[0]) 435 return FALSE; 436 name++; 437 ptrn++; 438 } 439 /* if we get here, the pattern is exhausted (-:just like me:-) */ 440 return name[0]=='\0'; 441} 442