1/************************************************************ 2 Copyright (c) 1994 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#elif defined(HAVE_CONFIG_H) 30#include <config.h> 31#endif 32 33#include <stdio.h> 34#include <ctype.h> 35#include <stdlib.h> 36#include <X11/Xfuncs.h> 37 38 39#include <X11/Xlib.h> 40#include <X11/XKBlib.h> 41#include <X11/extensions/XKBgeom.h> 42 43#include "XKMformat.h" 44#include "XKBfileInt.h" 45 46 47#define VMOD_HIDE_VALUE 0 48#define VMOD_SHOW_VALUE 1 49#define VMOD_COMMENT_VALUE 2 50 51static Bool 52WriteXKBVModDecl(FILE *file, Display *dpy, XkbDescPtr xkb, int showValue) 53{ 54 register int i, nMods; 55 Atom *vmodNames; 56 57 if (xkb == NULL) 58 return False; 59 if (xkb->names != NULL) 60 vmodNames = xkb->names->vmods; 61 else 62 vmodNames = NULL; 63 64 for (i = nMods = 0; i < XkbNumVirtualMods; i++) { 65 if ((vmodNames != NULL) && (vmodNames[i] != None)) { 66 if (nMods == 0) 67 fprintf(file, " virtual_modifiers "); 68 else 69 fprintf(file, ","); 70 fprintf(file, "%s", XkbAtomText(dpy, vmodNames[i], XkbXKBFile)); 71 if ((showValue != VMOD_HIDE_VALUE) && 72 (xkb->server) && (xkb->server->vmods[i] != XkbNoModifierMask)) { 73 if (showValue == VMOD_COMMENT_VALUE) { 74 fprintf(file, "/* = %s */", 75 XkbModMaskText(xkb->server->vmods[i], XkbXKBFile)); 76 } 77 else { 78 fprintf(file, "= %s", 79 XkbModMaskText(xkb->server->vmods[i], XkbXKBFile)); 80 } 81 } 82 nMods++; 83 } 84 } 85 if (nMods > 0) 86 fprintf(file, ";\n\n"); 87 return True; 88} 89 90/***====================================================================***/ 91 92static Bool 93WriteXKBAction(FILE *file, XkbFileInfo *result, XkbAnyAction *action) 94{ 95 XkbDescPtr xkb; 96 Display *dpy; 97 98 xkb = result->xkb; 99 dpy = xkb->dpy; 100 fprintf(file, "%s", 101 XkbActionText(dpy, xkb, (XkbAction *) action, XkbXKBFile)); 102 return True; 103} 104 105/***====================================================================***/ 106 107Bool 108XkbWriteXKBKeycodes(FILE * file, 109 XkbFileInfo * result, 110 Bool topLevel, 111 Bool showImplicit, 112 XkbFileAddOnFunc addOn, 113 void * priv) 114{ 115 Atom kcName; 116 register unsigned i; 117 XkbDescPtr xkb; 118 Display *dpy; 119 const char *alternate; 120 121 xkb = result->xkb; 122 if ((!xkb) || (!xkb->names) || (!xkb->names->keys)) { 123 _XkbLibError(_XkbErrMissingNames, "XkbWriteXKBKeycodes", 0); 124 return False; 125 } 126 dpy = xkb->dpy; 127 kcName = xkb->names->keycodes; 128 if (kcName != None) 129 fprintf(file, "xkb_keycodes \"%s\" {\n", 130 XkbAtomText(dpy, kcName, XkbXKBFile)); 131 else 132 fprintf(file, "xkb_keycodes {\n"); 133 fprintf(file, " minimum = %d;\n", xkb->min_key_code); 134 fprintf(file, " maximum = %d;\n", xkb->max_key_code); 135 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 136 if (xkb->names->keys[i].name[0] != '\0') { 137 if (XkbFindKeycodeByName(xkb, xkb->names->keys[i].name, True) != i) 138 alternate = "alternate "; 139 else 140 alternate = ""; 141 fprintf(file, " %s%6s = %d;\n", alternate, 142 XkbKeyNameText(xkb->names->keys[i].name, XkbXKBFile), i); 143 } 144 } 145 if (xkb->indicators != NULL) { 146 for (i = 0; i < XkbNumIndicators; i++) { 147 const char *type; 148 149 if (xkb->indicators->phys_indicators & (1 << i)) 150 type = " "; 151 else 152 type = " virtual "; 153 if (xkb->names->indicators[i] != None) { 154 fprintf(file, "%sindicator %d = \"%s\";\n", type, i + 1, 155 XkbAtomText(dpy, xkb->names->indicators[i], 156 XkbXKBFile)); 157 } 158 } 159 } 160 if (xkb->names->key_aliases != NULL) { 161 XkbKeyAliasPtr pAl; 162 163 pAl = xkb->names->key_aliases; 164 for (i = 0; i < xkb->names->num_key_aliases; i++, pAl++) { 165 fprintf(file, " alias %6s = %6s;\n", 166 XkbKeyNameText(pAl->alias, XkbXKBFile), 167 XkbKeyNameText(pAl->real, XkbXKBFile)); 168 } 169 } 170 if (addOn) 171 (*addOn) (file, result, topLevel, showImplicit, XkmKeyNamesIndex, priv); 172 fprintf(file, "};\n\n"); 173 return True; 174} 175 176Bool 177XkbWriteXKBKeyTypes(FILE * file, 178 XkbFileInfo * result, 179 Bool topLevel, 180 Bool showImplicit, 181 XkbFileAddOnFunc addOn, 182 void * priv) 183{ 184 Display *dpy; 185 register unsigned i, n; 186 XkbKeyTypePtr type; 187 XkbKTMapEntryPtr entry; 188 XkbDescPtr xkb; 189 190 xkb = result->xkb; 191 if ((!xkb) || (!xkb->map) || (!xkb->map->types)) { 192 _XkbLibError(_XkbErrMissingTypes, "XkbWriteXKBKeyTypes", 0); 193 return False; 194 } 195 dpy = xkb->dpy; 196 if (xkb->map->num_types < XkbNumRequiredTypes) { 197 _XkbLibError(_XkbErrMissingReqTypes, "XkbWriteXKBKeyTypes", 0); 198 return 0; 199 } 200 if ((xkb->names == NULL) || (xkb->names->types == None)) 201 fprintf(file, "xkb_types {\n\n"); 202 else 203 fprintf(file, "xkb_types \"%s\" {\n\n", 204 XkbAtomText(dpy, xkb->names->types, XkbXKBFile)); 205 WriteXKBVModDecl(file, dpy, xkb, 206 (showImplicit ? VMOD_COMMENT_VALUE : VMOD_HIDE_VALUE)); 207 208 type = xkb->map->types; 209 for (i = 0; i < xkb->map->num_types; i++, type++) { 210 fprintf(file, " type \"%s\" {\n", 211 XkbAtomText(dpy, type->name, XkbXKBFile)); 212 fprintf(file, " modifiers= %s;\n", 213 XkbVModMaskText(dpy, xkb, type->mods.real_mods, 214 type->mods.vmods, XkbXKBFile)); 215 entry = type->map; 216 for (n = 0; n < type->map_count; n++, entry++) { 217 char *str; 218 219 str = 220 XkbVModMaskText(dpy, xkb, entry->mods.real_mods, 221 entry->mods.vmods, XkbXKBFile); 222 fprintf(file, " map[%s]= Level%d;\n", str, entry->level + 1); 223 if ((type->preserve) && ((type->preserve[n].real_mods) || 224 (type->preserve[n].vmods))) { 225 fprintf(file, " preserve[%s]= ", str); 226 fprintf(file, "%s;\n", XkbVModMaskText(dpy, xkb, 227 type->preserve[n]. 228 real_mods, 229 type->preserve[n].vmods, 230 XkbXKBFile)); 231 } 232 } 233 if (type->level_names != NULL) { 234 Atom *name = type->level_names; 235 236 for (n = 0; n < type->num_levels; n++, name++) { 237 if ((*name) == None) 238 continue; 239 fprintf(file, " level_name[Level%d]= \"%s\";\n", n + 1, 240 XkbAtomText(dpy, *name, XkbXKBFile)); 241 } 242 } 243 fprintf(file, " };\n"); 244 } 245 if (addOn) 246 (*addOn) (file, result, topLevel, showImplicit, XkmTypesIndex, priv); 247 fprintf(file, "};\n\n"); 248 return True; 249} 250 251static Bool 252WriteXKBIndicatorMap(FILE * file, 253 XkbFileInfo * result, 254 Atom name, 255 XkbIndicatorMapPtr led, 256 XkbFileAddOnFunc addOn, 257 void * priv) 258{ 259 XkbDescPtr xkb; 260 char *tmp; 261 262 xkb = result->xkb; 263 tmp = XkbAtomGetString(xkb->dpy, name); 264 fprintf(file, " indicator \"%s\" {\n", tmp); 265 _XkbFree(tmp); 266 if (led->flags & XkbIM_NoExplicit) 267 fprintf(file, " !allowExplicit;\n"); 268 if (led->flags & XkbIM_LEDDrivesKB) 269 fprintf(file, " indicatorDrivesKeyboard;\n"); 270 if (led->which_groups != 0) { 271 if (led->which_groups != XkbIM_UseEffective) { 272 fprintf(file, " whichGroupState= %s;\n", 273 XkbIMWhichStateMaskText(led->which_groups, XkbXKBFile)); 274 } 275 fprintf(file, " groups= 0x%02x;\n", led->groups); 276 } 277 if (led->which_mods != 0) { 278 if (led->which_mods != XkbIM_UseEffective) { 279 fprintf(file, " whichModState= %s;\n", 280 XkbIMWhichStateMaskText(led->which_mods, XkbXKBFile)); 281 } 282 fprintf(file, " modifiers= %s;\n", 283 XkbVModMaskText(xkb->dpy, xkb, 284 led->mods.real_mods, led->mods.vmods, 285 XkbXKBFile)); 286 } 287 if (led->ctrls != 0) { 288 fprintf(file, " controls= %s;\n", 289 XkbControlsMaskText(led->ctrls, XkbXKBFile)); 290 } 291 if (addOn) 292 (*addOn) (file, result, False, True, XkmIndicatorsIndex, priv); 293 fprintf(file, " };\n"); 294 return True; 295} 296 297Bool 298XkbWriteXKBCompatMap(FILE * file, 299 XkbFileInfo * result, 300 Bool topLevel, 301 Bool showImplicit, 302 XkbFileAddOnFunc addOn, 303 void * priv) 304{ 305 Display * dpy; 306 register unsigned i; 307 XkbSymInterpretPtr interp; 308 XkbDescPtr xkb; 309 310 xkb = result->xkb; 311 if ((!xkb) || (!xkb->compat) || (!xkb->compat->sym_interpret)) { 312 _XkbLibError(_XkbErrMissingCompatMap, "XkbWriteXKBCompatMap", 0); 313 return False; 314 } 315 dpy = xkb->dpy; 316 if ((xkb->names == NULL) || (xkb->names->compat == None)) 317 fprintf(file, "xkb_compatibility {\n\n"); 318 else 319 fprintf(file, "xkb_compatibility \"%s\" {\n\n", 320 XkbAtomText(dpy, xkb->names->compat, XkbXKBFile)); 321 WriteXKBVModDecl(file, dpy, xkb, 322 (showImplicit ? VMOD_COMMENT_VALUE : VMOD_HIDE_VALUE)); 323 324 fprintf(file, " interpret.useModMapMods= AnyLevel;\n"); 325 fprintf(file, " interpret.repeat= False;\n"); 326 fprintf(file, " interpret.locking= False;\n"); 327 interp = xkb->compat->sym_interpret; 328 for (i = 0; i < xkb->compat->num_si; i++, interp++) { 329 fprintf(file, " interpret %s+%s(%s) {\n", 330 ((interp->sym == NoSymbol) ? "Any" : 331 XkbKeysymText(interp->sym, XkbXKBFile)), 332 XkbSIMatchText(interp->match, XkbXKBFile), 333 XkbModMaskText(interp->mods, XkbXKBFile)); 334 if (interp->virtual_mod != XkbNoModifier) { 335 fprintf(file, " virtualModifier= %s;\n", 336 XkbVModIndexText(dpy, xkb, interp->virtual_mod, 337 XkbXKBFile)); 338 } 339 if (interp->match & XkbSI_LevelOneOnly) 340 fprintf(file, " useModMapMods=level1;\n"); 341 if (interp->flags & XkbSI_LockingKey) 342 fprintf(file, " locking= True;\n"); 343 if (interp->flags & XkbSI_AutoRepeat) 344 fprintf(file, " repeat= True;\n"); 345 fprintf(file, " action= "); 346 WriteXKBAction(file, result, &interp->act); 347 fprintf(file, ";\n"); 348 fprintf(file, " };\n"); 349 } 350 for (i = 0; i < XkbNumKbdGroups; i++) { 351 XkbModsPtr gc; 352 353 gc = &xkb->compat->groups[i]; 354 if ((gc->real_mods == 0) && (gc->vmods == 0)) 355 continue; 356 fprintf(file, " group %d = %s;\n", i + 1, 357 XkbVModMaskText(xkb->dpy, xkb, gc->real_mods, gc->vmods, 358 XkbXKBFile)); 359 } 360 if (xkb->indicators) { 361 for (i = 0; i < XkbNumIndicators; i++) { 362 XkbIndicatorMapPtr map = &xkb->indicators->maps[i]; 363 364 if ((map->flags != 0) || (map->which_groups != 0) || 365 (map->groups != 0) || (map->which_mods != 0) || 366 (map->mods.real_mods != 0) || (map->mods.vmods != 0) || 367 (map->ctrls != 0)) { 368 WriteXKBIndicatorMap(file, result, xkb->names->indicators[i], 369 map, addOn, priv); 370 } 371 } 372 } 373 if (addOn) 374 (*addOn) (file, result, topLevel, showImplicit, XkmCompatMapIndex, 375 priv); 376 fprintf(file, "};\n\n"); 377 return True; 378} 379 380Bool 381XkbWriteXKBSymbols(FILE * file, 382 XkbFileInfo * result, 383 Bool topLevel, 384 Bool showImplicit, 385 XkbFileAddOnFunc addOn, 386 void * priv) 387{ 388 Display *dpy; 389 register unsigned i, tmp; 390 XkbDescPtr xkb; 391 XkbClientMapPtr map; 392 XkbServerMapPtr srv; 393 Bool showActions; 394 395 xkb = result->xkb; 396 397 if ((!xkb) || (!xkb->map) || (!xkb->map->syms) || (!xkb->map->key_sym_map)) { 398 _XkbLibError(_XkbErrMissingSymbols, "XkbWriteXKBSymbols", 0); 399 return False; 400 } 401 if ((!xkb->names) || (!xkb->names->keys)) { 402 _XkbLibError(_XkbErrMissingNames, "XkbWriteXKBSymbols", 0); 403 return False; 404 } 405 406 map = xkb->map; 407 srv = xkb->server; 408 dpy = xkb->dpy; 409 410 if ((xkb->names == NULL) || (xkb->names->symbols == None)) 411 fprintf(file, "xkb_symbols {\n\n"); 412 else 413 fprintf(file, "xkb_symbols \"%s\" {\n\n", 414 XkbAtomText(dpy, xkb->names->symbols, XkbXKBFile)); 415 for (tmp = i = 0; i < XkbNumKbdGroups; i++) { 416 if (xkb->names->groups[i] != None) { 417 fprintf(file, " name[group%d]=\"%s\";\n", i + 1, 418 XkbAtomText(dpy, xkb->names->groups[i], XkbXKBFile)); 419 tmp++; 420 } 421 } 422 if (tmp > 0) 423 fprintf(file, "\n"); 424 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 425 Bool simple; 426 427 if ((int) XkbKeyNumSyms(xkb, i) < 1) 428 continue; 429 if (XkbFindKeycodeByName(xkb, xkb->names->keys[i].name, True) != i) 430 continue; 431 simple = True; 432 fprintf(file, " key %6s {", 433 XkbKeyNameText(xkb->names->keys[i].name, XkbXKBFile)); 434 if (srv->explicit) { 435 if (((srv->explicit[i] & XkbExplicitKeyTypesMask) != 0) || 436 (showImplicit)) { 437 int typeNdx, g; 438 Bool multi; 439 const char *comment = " "; 440 441 if ((srv->explicit[i] & XkbExplicitKeyTypesMask) == 0) 442 comment = "//"; 443 multi = False; 444 typeNdx = XkbKeyKeyTypeIndex(xkb, i, 0); 445 for (g = 1; (g < XkbKeyNumGroups(xkb, i)) && (!multi); g++) { 446 if (XkbKeyKeyTypeIndex(xkb, i, g) != typeNdx) 447 multi = True; 448 } 449 if (multi) { 450 for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) { 451 typeNdx = XkbKeyKeyTypeIndex(xkb, i, g); 452 if (srv->explicit[i] & (1 << g)) { 453 fprintf(file, "\n%s type[group%d]= \"%s\",", 454 comment, g + 1, 455 XkbAtomText(dpy, map->types[typeNdx].name, 456 XkbXKBFile)); 457 } 458 else if (showImplicit) { 459 fprintf(file, "\n// type[group%d]= \"%s\",", 460 g + 1, 461 XkbAtomText(dpy, map->types[typeNdx].name, 462 XkbXKBFile)); 463 } 464 } 465 } 466 else { 467 fprintf(file, "\n%s type= \"%s\",", comment, 468 XkbAtomText(dpy, map->types[typeNdx].name, 469 XkbXKBFile)); 470 } 471 simple = False; 472 } 473 if (((srv->explicit[i] & XkbExplicitAutoRepeatMask) != 0) && 474 (xkb->ctrls != NULL)) { 475 if (xkb->ctrls->per_key_repeat[i / 8] & (1 << (i % 8))) 476 fprintf(file, "\n repeat= Yes,"); 477 else 478 fprintf(file, "\n repeat= No,"); 479 simple = False; 480 } 481 if ((xkb->server != NULL) && (xkb->server->vmodmap != NULL) && 482 (xkb->server->vmodmap[i] != 0)) { 483 if ((srv->explicit[i] & XkbExplicitVModMapMask) != 0) { 484 fprintf(file, "\n virtualMods= %s,", 485 XkbVModMaskText(dpy, xkb, 0, 486 xkb->server->vmodmap[i], 487 XkbXKBFile)); 488 } 489 else if (showImplicit) { 490 fprintf(file, "\n// virtualMods= %s,", 491 XkbVModMaskText(dpy, xkb, 0, 492 xkb->server->vmodmap[i], 493 XkbXKBFile)); 494 } 495 } 496 } 497 switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb, i))) { 498 case XkbClampIntoRange: 499 fprintf(file, "\n groupsClamp,"); 500 break; 501 case XkbRedirectIntoRange: 502 fprintf(file, "\n groupsRedirect= Group%d,", 503 XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb, i)) + 1); 504 break; 505 } 506 if (srv->behaviors != NULL) { 507 unsigned type; 508 509 type = srv->behaviors[i].type & XkbKB_OpMask; 510 511 if (type != XkbKB_Default) { 512 simple = False; 513 fprintf(file, "\n %s,", 514 XkbBehaviorText(xkb, &srv->behaviors[i], XkbXKBFile)); 515 } 516 } 517 if ((srv->explicit == NULL) || showImplicit || 518 ((srv->explicit[i] & XkbExplicitInterpretMask) != 0)) 519 showActions = XkbKeyHasActions(xkb, i); 520 else 521 showActions = False; 522 523 if (((unsigned) XkbKeyNumGroups(xkb, i) > 1) || showActions) 524 simple = False; 525 if (simple) { 526 KeySym *syms; 527 unsigned s; 528 529 syms = XkbKeySymsPtr(xkb, i); 530 fprintf(file, " [ "); 531 for (s = 0; s < XkbKeyGroupWidth(xkb, i, XkbGroup1Index); s++) { 532 if (s != 0) 533 fprintf(file, ", "); 534 fprintf(file, "%15s", XkbKeysymText(*syms++, XkbXKBFile)); 535 } 536 fprintf(file, " ] };\n"); 537 } 538 else { 539 unsigned g, s; 540 KeySym *syms; 541 XkbAction *acts; 542 543 syms = XkbKeySymsPtr(xkb, i); 544 acts = XkbKeyActionsPtr(xkb, i); 545 for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) { 546 if (g != 0) 547 fprintf(file, ","); 548 fprintf(file, "\n symbols[Group%d]= [ ", g + 1); 549 for (s = 0; s < XkbKeyGroupWidth(xkb, i, g); s++) { 550 if (s != 0) 551 fprintf(file, ", "); 552 fprintf(file, "%15s", XkbKeysymText(syms[s], XkbXKBFile)); 553 } 554 fprintf(file, " ]"); 555 syms += XkbKeyGroupsWidth(xkb, i); 556 if (showActions) { 557 fprintf(file, ",\n actions[Group%d]= [ ", g + 1); 558 for (s = 0; s < XkbKeyGroupWidth(xkb, i, g); s++) { 559 if (s != 0) 560 fprintf(file, ", "); 561 WriteXKBAction(file, result, 562 (XkbAnyAction *) & acts[s]); 563 } 564 fprintf(file, " ]"); 565 acts += XkbKeyGroupsWidth(xkb, i); 566 } 567 } 568 fprintf(file, "\n };\n"); 569 } 570 } 571 if (map && map->modmap) { 572 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 573 if (map->modmap[i] != 0) { 574 register int n, bit; 575 576 for (bit = 1, n = 0; n < XkbNumModifiers; n++, bit <<= 1) { 577 if (map->modmap[i] & bit) { 578 char buf[5]; 579 580 memcpy(buf, xkb->names->keys[i].name, 4); 581 buf[4] = '\0'; 582 fprintf(file, " modifier_map %s { <%s> };\n", 583 XkbModIndexText(n, XkbXKBFile), buf); 584 } 585 } 586 } 587 } 588 } 589 if (addOn) 590 (*addOn) (file, result, topLevel, showImplicit, XkmSymbolsIndex, priv); 591 fprintf(file, "};\n\n"); 592 return True; 593} 594 595static Bool 596WriteXKBOutline(FILE * file, 597 XkbShapePtr shape, 598 XkbOutlinePtr outline, 599 int lastRadius, 600 int first, 601 int indent) 602{ 603 register int i; 604 XkbPointPtr pt; 605 char *iStr; 606 607 fprintf(file, "%s", iStr = XkbIndentText(first)); 608 if (first != indent) 609 iStr = XkbIndentText(indent); 610 if (outline->corner_radius != lastRadius) { 611 fprintf(file, "corner= %s,", 612 XkbGeomFPText(outline->corner_radius, XkbMessage)); 613 if (shape != NULL) { 614 fprintf(file, "\n%s", iStr); 615 } 616 } 617 if (shape) { 618 if (outline == shape->approx) 619 fprintf(file, "approx= "); 620 else if (outline == shape->primary) 621 fprintf(file, "primary= "); 622 } 623 fprintf(file, "{"); 624 for (pt = outline->points, i = 0; i < outline->num_points; i++, pt++) { 625 if (i == 0) 626 fprintf(file, " "); 627 else if ((i % 4) == 0) 628 fprintf(file, ",\n%s ", iStr); 629 else 630 fprintf(file, ", "); 631 fprintf(file, "[ %3s, %3s ]", XkbGeomFPText(pt->x, XkbXKBFile), 632 XkbGeomFPText(pt->y, XkbXKBFile)); 633 } 634 fprintf(file, " }"); 635 return True; 636} 637 638static Bool 639WriteXKBDoodad(FILE * file, 640 Display * dpy, 641 unsigned indent, 642 XkbGeometryPtr geom, 643 XkbDoodadPtr doodad) 644{ 645 register char *i_str; 646 XkbShapePtr shape; 647 XkbColorPtr color; 648 649 i_str = XkbIndentText(indent); 650 fprintf(file, "%s%s \"%s\" {\n", i_str, 651 XkbDoodadTypeText(doodad->any.type, XkbMessage), 652 XkbAtomText(dpy, doodad->any.name, XkbMessage)); 653 fprintf(file, "%s top= %s;\n", i_str, 654 XkbGeomFPText(doodad->any.top, XkbXKBFile)); 655 fprintf(file, "%s left= %s;\n", i_str, 656 XkbGeomFPText(doodad->any.left, XkbXKBFile)); 657 fprintf(file, "%s priority= %d;\n", i_str, doodad->any.priority); 658 switch (doodad->any.type) { 659 case XkbOutlineDoodad: 660 case XkbSolidDoodad: 661 if (doodad->shape.angle != 0) { 662 fprintf(file, "%s angle= %s;\n", i_str, 663 XkbGeomFPText(doodad->shape.angle, XkbXKBFile)); 664 } 665 if (doodad->shape.color_ndx != 0) { 666 fprintf(file, "%s color= \"%s\";\n", i_str, 667 XkbShapeDoodadColor(geom, &doodad->shape)->spec); 668 } 669 shape = XkbShapeDoodadShape(geom, &doodad->shape); 670 fprintf(file, "%s shape= \"%s\";\n", i_str, 671 XkbAtomText(dpy, shape->name, XkbXKBFile)); 672 break; 673 case XkbTextDoodad: 674 if (doodad->text.angle != 0) { 675 fprintf(file, "%s angle= %s;\n", i_str, 676 XkbGeomFPText(doodad->text.angle, XkbXKBFile)); 677 } 678 if (doodad->text.width != 0) { 679 fprintf(file, "%s width= %s;\n", i_str, 680 XkbGeomFPText(doodad->text.width, XkbXKBFile)); 681 682 } 683 if (doodad->text.height != 0) { 684 fprintf(file, "%s height= %s;\n", i_str, 685 XkbGeomFPText(doodad->text.height, XkbXKBFile)); 686 687 } 688 if (doodad->text.color_ndx != 0) { 689 color = XkbTextDoodadColor(geom, &doodad->text); 690 fprintf(file, "%s color= \"%s\";\n", i_str, 691 XkbStringText(color->spec, XkbXKBFile)); 692 } 693 fprintf(file, "%s XFont= \"%s\";\n", i_str, 694 XkbStringText(doodad->text.font, XkbXKBFile)); 695 fprintf(file, "%s text= \"%s\";\n", i_str, 696 XkbStringText(doodad->text.text, XkbXKBFile)); 697 break; 698 case XkbIndicatorDoodad: 699 shape = XkbIndicatorDoodadShape(geom, &doodad->indicator); 700 color = XkbIndicatorDoodadOnColor(geom, &doodad->indicator); 701 fprintf(file, "%s onColor= \"%s\";\n", i_str, 702 XkbStringText(color->spec, XkbXKBFile)); 703 color = XkbIndicatorDoodadOffColor(geom, &doodad->indicator); 704 fprintf(file, "%s offColor= \"%s\";\n", i_str, 705 XkbStringText(color->spec, XkbXKBFile)); 706 fprintf(file, "%s shape= \"%s\";\n", i_str, 707 XkbAtomText(dpy, shape->name, XkbXKBFile)); 708 break; 709 case XkbLogoDoodad: 710 fprintf(file, "%s logoName= \"%s\";\n", i_str, 711 XkbStringText(doodad->logo.logo_name, XkbXKBFile)); 712 if (doodad->shape.angle != 0) { 713 fprintf(file, "%s angle= %s;\n", i_str, 714 XkbGeomFPText(doodad->logo.angle, XkbXKBFile)); 715 } 716 if (doodad->shape.color_ndx != 0) { 717 fprintf(file, "%s color= \"%s\";\n", i_str, 718 XkbLogoDoodadColor(geom, &doodad->logo)->spec); 719 } 720 shape = XkbLogoDoodadShape(geom, &doodad->logo); 721 fprintf(file, "%s shape= \"%s\";\n", i_str, 722 XkbAtomText(dpy, shape->name, XkbXKBFile)); 723 break; 724 } 725 fprintf(file, "%s};\n", i_str); 726 return True; 727} 728 729/*ARGSUSED*/ 730static Bool 731WriteXKBOverlay(FILE * file, 732 Display * dpy, 733 unsigned indent, 734 XkbGeometryPtr geom, 735 XkbOverlayPtr ol) 736{ 737 register char *i_str; 738 int r, k, nOut; 739 XkbOverlayRowPtr row; 740 XkbOverlayKeyPtr key; 741 742 i_str = XkbIndentText(indent); 743 if (ol->name != None) { 744 fprintf(file, "%soverlay \"%s\" {\n", i_str, 745 XkbAtomText(dpy, ol->name, XkbMessage)); 746 } 747 else 748 fprintf(file, "%soverlay {\n", i_str); 749 for (nOut = r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 750 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 751 char *over, *under; 752 753 over = XkbKeyNameText(key->over.name, XkbXKBFile); 754 under = XkbKeyNameText(key->under.name, XkbXKBFile); 755 if (nOut == 0) 756 fprintf(file, "%s %6s=%6s", i_str, under, over); 757 else if ((nOut % 4) == 0) 758 fprintf(file, ",\n%s %6s=%6s", i_str, under, over); 759 else 760 fprintf(file, ", %6s=%6s", under, over); 761 nOut++; 762 } 763 } 764 fprintf(file, "\n%s};\n", i_str); 765 return True; 766} 767 768static Bool 769WriteXKBSection(FILE * file, 770 Display * dpy, 771 XkbSectionPtr s, 772 XkbGeometryPtr geom) 773{ 774 register int i; 775 XkbRowPtr row; 776 int dfltKeyColor = 0; 777 778 fprintf(file, " section \"%s\" {\n", 779 XkbAtomText(dpy, s->name, XkbXKBFile)); 780 if (s->rows && (s->rows->num_keys > 0)) { 781 dfltKeyColor = s->rows->keys[0].color_ndx; 782 fprintf(file, " key.color= \"%s\";\n", 783 XkbStringText(geom->colors[dfltKeyColor].spec, XkbXKBFile)); 784 } 785 fprintf(file, " priority= %d;\n", s->priority); 786 fprintf(file, " top= %s;\n", 787 XkbGeomFPText(s->top, XkbXKBFile)); 788 fprintf(file, " left= %s;\n", 789 XkbGeomFPText(s->left, XkbXKBFile)); 790 fprintf(file, " width= %s;\n", 791 XkbGeomFPText(s->width, XkbXKBFile)); 792 fprintf(file, " height= %s;\n", 793 XkbGeomFPText(s->height, XkbXKBFile)); 794 if (s->angle != 0) { 795 fprintf(file, " angle= %s;\n", 796 XkbGeomFPText(s->angle, XkbXKBFile)); 797 } 798 for (i = 0, row = s->rows; row && i < s->num_rows; i++, row++) { 799 fprintf(file, " row {\n"); 800 fprintf(file, " top= %s;\n", 801 XkbGeomFPText(row->top, XkbXKBFile)); 802 fprintf(file, " left= %s;\n", 803 XkbGeomFPText(row->left, XkbXKBFile)); 804 if (row->vertical) 805 fprintf(file, " vertical;\n"); 806 if (row->num_keys > 0) { 807 register int k; 808 register XkbKeyPtr key; 809 int forceNL = 0; 810 int nThisLine = 0; 811 812 fprintf(file, " keys {\n"); 813 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 814 XkbShapePtr shape; 815 816 if (key->color_ndx != dfltKeyColor) 817 forceNL = 1; 818 if (k == 0) { 819 fprintf(file, " "); 820 nThisLine = 0; 821 } 822 else if (((nThisLine % 2) == 1) || (forceNL)) { 823 fprintf(file, ",\n "); 824 forceNL = nThisLine = 0; 825 } 826 else { 827 fprintf(file, ", "); 828 nThisLine++; 829 } 830 shape = XkbKeyShape(geom, key); 831 fprintf(file, "{ %6s, \"%s\", %3s", 832 XkbKeyNameText(key->name.name, XkbXKBFile), 833 XkbAtomText(dpy, shape->name, XkbXKBFile), 834 XkbGeomFPText(key->gap, XkbXKBFile)); 835 if (key->color_ndx != dfltKeyColor) { 836 fprintf(file, ", color=\"%s\"", 837 XkbKeyColor(geom, key)->spec); 838 forceNL = 1; 839 } 840 fprintf(file, " }"); 841 } 842 fprintf(file, "\n };\n"); 843 } 844 fprintf(file, " };\n"); 845 } 846 if (s->doodads != NULL) { 847 XkbDoodadPtr doodad; 848 849 for (i = 0, doodad = s->doodads; i < s->num_doodads; i++, doodad++) { 850 WriteXKBDoodad(file, dpy, 8, geom, doodad); 851 } 852 } 853 if (s->overlays != NULL) { 854 XkbOverlayPtr ol; 855 856 for (i = 0, ol = s->overlays; i < s->num_overlays; i++, ol++) { 857 WriteXKBOverlay(file, dpy, 8, geom, ol); 858 } 859 } 860 fprintf(file, " }; // End of \"%s\" section\n\n", 861 XkbAtomText(dpy, s->name, XkbXKBFile)); 862 return True; 863} 864 865Bool 866XkbWriteXKBGeometry(FILE * file, 867 XkbFileInfo * result, 868 Bool topLevel, 869 Bool showImplicit, 870 XkbFileAddOnFunc addOn, 871 void * priv) 872{ 873 Display *dpy; 874 register unsigned i, n; 875 XkbDescPtr xkb; 876 XkbGeometryPtr geom; 877 878 xkb = result->xkb; 879 if ((!xkb) || (!xkb->geom)) { 880 _XkbLibError(_XkbErrMissingGeometry, "XkbWriteXKBGeometry", 0); 881 return False; 882 } 883 dpy = xkb->dpy; 884 geom = xkb->geom; 885 if (geom->name == None) 886 fprintf(file, "xkb_geometry {\n\n"); 887 else 888 fprintf(file, "xkb_geometry \"%s\" {\n\n", 889 XkbAtomText(dpy, geom->name, XkbXKBFile)); 890 fprintf(file, " width= %s;\n", 891 XkbGeomFPText(geom->width_mm, XkbXKBFile)); 892 fprintf(file, " height= %s;\n\n", 893 XkbGeomFPText(geom->height_mm, XkbXKBFile)); 894 895 if (geom->key_aliases != NULL) { 896 XkbKeyAliasPtr pAl; 897 898 pAl = geom->key_aliases; 899 for (i = 0; i < geom->num_key_aliases; i++, pAl++) { 900 fprintf(file, " alias %6s = %6s;\n", 901 XkbKeyNameText(pAl->alias, XkbXKBFile), 902 XkbKeyNameText(pAl->real, XkbXKBFile)); 903 } 904 fprintf(file, "\n"); 905 } 906 907 if (geom->base_color != NULL) 908 fprintf(file, " baseColor= \"%s\";\n", 909 XkbStringText(geom->base_color->spec, XkbXKBFile)); 910 if (geom->label_color != NULL) 911 fprintf(file, " labelColor= \"%s\";\n", 912 XkbStringText(geom->label_color->spec, XkbXKBFile)); 913 if (geom->label_font != NULL) 914 fprintf(file, " xfont= \"%s\";\n", 915 XkbStringText(geom->label_font, XkbXKBFile)); 916 if ((geom->num_colors > 0) && (showImplicit)) { 917 XkbColorPtr color; 918 919 for (color = geom->colors, i = 0; i < geom->num_colors; i++, color++) { 920 fprintf(file, "// color[%d]= \"%s\"\n", i, 921 XkbStringText(color->spec, XkbXKBFile)); 922 } 923 fprintf(file, "\n"); 924 } 925 if (geom->num_properties > 0) { 926 XkbPropertyPtr prop; 927 928 for (prop = geom->properties, i = 0; i < geom->num_properties; 929 i++, prop++) { 930 fprintf(file, " %s= \"%s\";\n", prop->name, 931 XkbStringText(prop->value, XkbXKBFile)); 932 } 933 fprintf(file, "\n"); 934 } 935 if (geom->num_shapes > 0) { 936 XkbShapePtr shape; 937 XkbOutlinePtr outline; 938 int lastR; 939 940 for (shape = geom->shapes, i = 0; i < geom->num_shapes; i++, shape++) { 941 lastR = 0; 942 fprintf(file, " shape \"%s\" {", 943 XkbAtomText(dpy, shape->name, XkbXKBFile)); 944 outline = shape->outlines; 945 if (shape->num_outlines > 1) { 946 for (n = 0; n < shape->num_outlines; n++, outline++) { 947 if (n == 0) 948 fprintf(file, "\n"); 949 else 950 fprintf(file, ",\n"); 951 WriteXKBOutline(file, shape, outline, lastR, 8, 8); 952 lastR = outline->corner_radius; 953 } 954 fprintf(file, "\n };\n"); 955 } 956 else { 957 WriteXKBOutline(file, NULL, outline, lastR, 1, 8); 958 fprintf(file, " };\n"); 959 } 960 } 961 } 962 if (geom->num_sections > 0) { 963 XkbSectionPtr section; 964 965 for (section = geom->sections, i = 0; i < geom->num_sections; 966 i++, section++) { 967 WriteXKBSection(file, dpy, section, geom); 968 } 969 } 970 if (geom->num_doodads > 0) { 971 XkbDoodadPtr doodad; 972 973 for (i = 0, doodad = geom->doodads; i < geom->num_doodads; 974 i++, doodad++) { 975 WriteXKBDoodad(file, dpy, 4, geom, doodad); 976 } 977 } 978 if (addOn) 979 (*addOn) (file, result, topLevel, showImplicit, XkmGeometryIndex, priv); 980 fprintf(file, "};\n\n"); 981 return True; 982} 983 984/*ARGSUSED*/ 985Bool 986XkbWriteXKBSemantics(FILE * file, 987 XkbFileInfo * result, 988 Bool topLevel, 989 Bool showImplicit, 990 XkbFileAddOnFunc addOn, 991 void * priv) 992{ 993 Bool ok; 994 995 fprintf(file, "xkb_semantics {\n"); 996 ok = XkbWriteXKBKeyTypes(file, result, False, False, addOn, priv); 997 ok = ok && XkbWriteXKBCompatMap(file, result, False, False, addOn, priv); 998 fprintf(file, "};\n"); 999 return ok; 1000} 1001 1002/*ARGSUSED*/ 1003Bool 1004XkbWriteXKBLayout(FILE * file, 1005 XkbFileInfo * result, 1006 Bool topLevel, 1007 Bool showImplicit, 1008 XkbFileAddOnFunc addOn, 1009 void * priv) 1010{ 1011 Bool ok; 1012 XkbDescPtr xkb; 1013 1014 xkb = result->xkb; 1015 fprintf(file, "xkb_layout {\n"); 1016 ok = XkbWriteXKBKeycodes(file, result, False, showImplicit, addOn, priv); 1017 ok = ok && 1018 XkbWriteXKBKeyTypes(file, result, False, showImplicit, addOn, priv); 1019 ok = ok && 1020 XkbWriteXKBSymbols(file, result, False, showImplicit, addOn, priv); 1021 if (xkb->geom) 1022 ok = ok && 1023 XkbWriteXKBGeometry(file, result, False, showImplicit, addOn, priv); 1024 fprintf(file, "};\n"); 1025 return ok; 1026} 1027 1028/*ARGSUSED*/ 1029Bool 1030XkbWriteXKBKeymap(FILE * file, 1031 XkbFileInfo * result, 1032 Bool topLevel, 1033 Bool showImplicit, 1034 XkbFileAddOnFunc addOn, 1035 void * priv) 1036{ 1037 Bool ok; 1038 XkbDescPtr xkb; 1039 1040 xkb = result->xkb; 1041 fprintf(file, "xkb_keymap {\n"); 1042 ok = XkbWriteXKBKeycodes(file, result, False, showImplicit, addOn, priv); 1043 ok = ok && 1044 XkbWriteXKBKeyTypes(file, result, False, showImplicit, addOn, priv); 1045 ok = ok && 1046 XkbWriteXKBCompatMap(file, result, False, showImplicit, addOn, priv); 1047 ok = ok && 1048 XkbWriteXKBSymbols(file, result, False, showImplicit, addOn, priv); 1049 if (xkb->geom) 1050 ok = ok && 1051 XkbWriteXKBGeometry(file, result, False, showImplicit, addOn, priv); 1052 fprintf(file, "};\n"); 1053 return ok; 1054} 1055 1056Bool 1057XkbWriteXKBFile(FILE * out, 1058 XkbFileInfo * result, 1059 Bool showImplicit, 1060 XkbFileAddOnFunc addOn, 1061 void * priv) 1062{ 1063 Bool ok = False; 1064 1065 Bool (*func) (FILE * /* file */ , 1066 XkbFileInfo * /* result */ , 1067 Bool /* topLevel */ , 1068 Bool /* showImplicit */ , 1069 XkbFileAddOnFunc /* addOn */ , 1070 void * /* priv */ 1071 ) = NULL; 1072 1073 switch (result->type) { 1074 case XkmSemanticsFile: 1075 func = XkbWriteXKBSemantics; 1076 break; 1077 case XkmLayoutFile: 1078 func = XkbWriteXKBLayout; 1079 break; 1080 case XkmKeymapFile: 1081 func = XkbWriteXKBKeymap; 1082 break; 1083 case XkmTypesIndex: 1084 func = XkbWriteXKBKeyTypes; 1085 break; 1086 case XkmCompatMapIndex: 1087 func = XkbWriteXKBCompatMap; 1088 break; 1089 case XkmSymbolsIndex: 1090 func = XkbWriteXKBSymbols; 1091 break; 1092 case XkmKeyNamesIndex: 1093 func = XkbWriteXKBKeycodes; 1094 break; 1095 case XkmGeometryFile: 1096 case XkmGeometryIndex: 1097 func = XkbWriteXKBGeometry; 1098 break; 1099 case XkmVirtualModsIndex: 1100 case XkmIndicatorsIndex: 1101 _XkbLibError(_XkbErrBadImplementation, 1102 XkbConfigText(result->type, XkbMessage), 0); 1103 return False; 1104 } 1105 if (out == NULL) { 1106 _XkbLibError(_XkbErrFileCannotOpen, "XkbWriteXkbFile", 0); 1107 ok = False; 1108 } 1109 else if (func) { 1110 ok = (*func) (out, result, True, showImplicit, addOn, priv); 1111 } 1112 return ok; 1113} 1114