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_CONFIG_H 28#include <config.h> 29#endif 30#include <stdio.h> 31#include <ctype.h> 32#include <stdlib.h> 33#include <X11/Xfuncs.h> 34#include <X11/Xlib.h> 35#include <X11/XKBlib.h> 36#include <X11/extensions/XKBgeom.h> 37 38#include "XKMformat.h" 39#include "XKBfileInt.h" 40 41typedef struct _XkmInfo { 42 unsigned short bound_vmods; 43 unsigned short named_vmods; 44 unsigned char num_bound; 45 unsigned char group_compat; 46 unsigned short num_group_compat; 47 unsigned short num_leds; 48 int total_vmodmaps; 49} XkmInfo; 50 51/***====================================================================***/ 52 53#define xkmPutCARD8(f,v) (putc(v,f),1) 54 55static int 56xkmPutCARD16(FILE *file, unsigned val) 57{ 58 CARD16 tmp = val; 59 60 fwrite(&tmp, 2, 1, file); 61 return 2; 62} 63 64static int 65xkmPutCARD32(FILE *file, unsigned long val) 66{ 67 CARD32 tmp = val; 68 69 fwrite(&tmp, 4, 1, file); 70 return 4; 71} 72 73static int 74xkmPutPadding(FILE *file, unsigned pad) 75{ 76 int i; 77 78 for (i = 0; i < pad; i++) { 79 putc('\0', file); 80 } 81 return pad; 82} 83 84static int 85xkmPutCountedBytes(FILE *file, char *ptr, unsigned count) 86{ 87 register int nOut; 88 register unsigned pad; 89 90 if (count == 0) 91 return xkmPutCARD32(file, (unsigned long) 0); 92 93 xkmPutCARD16(file, count); 94 nOut = fwrite(ptr, 1, count, file); 95 if (nOut < 0) 96 return 2; 97 nOut = count + 2; 98 pad = XkbPaddedSize(nOut) - nOut; 99 if (pad) 100 xkmPutPadding(file, pad); 101 return nOut + pad; 102} 103 104static unsigned 105xkmSizeCountedString(char *str) 106{ 107 if (str == NULL) 108 return 4; 109 return XkbPaddedSize(strlen(str) + 2); 110} 111 112static int 113xkmPutCountedString(FILE *file, char *str) 114{ 115 if (str == NULL) 116 return xkmPutCARD32(file, (unsigned long) 0); 117 return xkmPutCountedBytes(file, str, strlen(str)); 118} 119 120#define xkmSizeCountedAtomString(d,a) \ 121 xkmSizeCountedString(XkbAtomGetString((d),(a))) 122 123#define xkmPutCountedAtomString(d,f,a) \ 124 xkmPutCountedString((f),XkbAtomGetString((d),(a))) 125 126/***====================================================================***/ 127 128static unsigned 129SizeXKMVirtualMods(XkbFileInfo *result, XkmInfo *info, 130 xkmSectionInfo *toc, int *offset_inout) 131{ 132 Display *dpy; 133 XkbDescPtr xkb; 134 unsigned nBound, bound; 135 unsigned nNamed, named, szNames; 136 register unsigned i, bit; 137 138 xkb = result->xkb; 139 if ((!xkb) || (!xkb->names) || (!xkb->server)) { 140 _XkbLibError(_XkbErrMissingVMods, "SizeXKMVirtualMods", 0); 141 return 0; 142 } 143 dpy = xkb->dpy; 144 bound = named = 0; 145 for (i = nBound = nNamed = szNames = 0, bit = 1; i < XkbNumVirtualMods; 146 i++, bit <<= 1) { 147 if (xkb->server->vmods[i] != XkbNoModifierMask) { 148 bound |= bit; 149 nBound++; 150 } 151 if (xkb->names->vmods[i] != None) { 152 named |= bit; 153 szNames += xkmSizeCountedAtomString(dpy, xkb->names->vmods[i]); 154 nNamed++; 155 } 156 } 157 info->num_bound = nBound; 158 info->bound_vmods = bound; 159 info->named_vmods = named; 160 if ((nBound == 0) && (nNamed == 0)) 161 return 0; 162 toc->type = XkmVirtualModsIndex; 163 toc->format = MSBFirst; 164 toc->size = 4 + XkbPaddedSize(nBound) + szNames + SIZEOF(xkmSectionInfo); 165 toc->offset = *offset_inout; 166 (*offset_inout) += toc->size; 167 return 1; 168} 169 170static unsigned 171WriteXKMVirtualMods(FILE *file, XkbFileInfo *result, XkmInfo *info) 172{ 173 register unsigned int i, bit; 174 XkbDescPtr xkb; 175 Display *dpy; 176 unsigned size = 0; 177 178 xkb = result->xkb; 179 dpy = xkb->dpy; 180 size += xkmPutCARD16(file, info->bound_vmods); 181 size += xkmPutCARD16(file, info->named_vmods); 182 for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 183 if (info->bound_vmods & bit) 184 size += xkmPutCARD8(file, xkb->server->vmods[i]); 185 } 186 if ((i = XkbPaddedSize(info->num_bound) - info->num_bound) > 0) 187 size += xkmPutPadding(file, i); 188 for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 189 if (info->named_vmods & bit) { 190 register char *name; 191 192 name = XkbAtomGetString(dpy, xkb->names->vmods[i]); 193 size += xkmPutCountedString(file, name); 194 } 195 } 196 return size; 197} 198 199/***====================================================================***/ 200 201static unsigned 202SizeXKMKeycodes(XkbFileInfo *result, xkmSectionInfo *toc, int *offset_inout) 203{ 204 XkbDescPtr xkb; 205 Atom kcName; 206 int size = 0; 207 Display *dpy; 208 209 xkb = result->xkb; 210 if ((!xkb) || (!xkb->names) || (!xkb->names->keys)) { 211 _XkbLibError(_XkbErrMissingNames, "SizeXKMKeycodes", 0); 212 return 0; 213 } 214 dpy = xkb->dpy; 215 kcName = xkb->names->keycodes; 216 size += 4; /* min and max keycode */ 217 size += xkmSizeCountedAtomString(dpy, kcName); 218 size += XkbNumKeys(xkb) * sizeof(XkbKeyNameRec); 219 if (xkb->names->num_key_aliases > 0) { 220 if (xkb->names->key_aliases != NULL) 221 size += xkb->names->num_key_aliases * sizeof(XkbKeyAliasRec); 222 else 223 xkb->names->num_key_aliases = 0; 224 } 225 toc->type = XkmKeyNamesIndex; 226 toc->format = MSBFirst; 227 toc->size = size + SIZEOF(xkmSectionInfo); 228 toc->offset = (*offset_inout); 229 (*offset_inout) += toc->size; 230 return 1; 231} 232 233static unsigned 234WriteXKMKeycodes(FILE *file, XkbFileInfo *result) 235{ 236 XkbDescPtr xkb; 237 Atom kcName; 238 char *start; 239 Display *dpy; 240 unsigned tmp, size = 0; 241 242 xkb = result->xkb; 243 dpy = xkb->dpy; 244 kcName = xkb->names->keycodes; 245 start = xkb->names->keys[xkb->min_key_code].name; 246 247 size += xkmPutCountedString(file, XkbAtomGetString(dpy, kcName)); 248 size += xkmPutCARD8(file, xkb->min_key_code); 249 size += xkmPutCARD8(file, xkb->max_key_code); 250 size += xkmPutCARD8(file, xkb->names->num_key_aliases); 251 size += xkmPutPadding(file, 1); 252 tmp = fwrite(start, sizeof(XkbKeyNameRec), XkbNumKeys(xkb), file); 253 size += tmp * sizeof(XkbKeyNameRec); 254 if (xkb->names->num_key_aliases > 0) { 255 tmp = fwrite((char *) xkb->names->key_aliases, 256 sizeof(XkbKeyAliasRec), xkb->names->num_key_aliases, file); 257 size += tmp * sizeof(XkbKeyAliasRec); 258 } 259 return size; 260} 261 262/***====================================================================***/ 263 264static unsigned 265SizeXKMKeyTypes(XkbFileInfo *result, xkmSectionInfo *toc, int *offset_inout) 266{ 267 register unsigned i, n, size; 268 XkbKeyTypePtr type; 269 XkbDescPtr xkb; 270 Display *dpy; 271 char *name; 272 273 xkb = result->xkb; 274 if ((!xkb) || (!xkb->map) || (!xkb->map->types)) { 275 _XkbLibError(_XkbErrMissingTypes, "SizeXKBKeyTypes", 0); 276 return 0; 277 } 278 dpy = xkb->dpy; 279 if (xkb->map->num_types < XkbNumRequiredTypes) { 280 _XkbLibError(_XkbErrMissingReqTypes, "SizeXKBKeyTypes", 0); 281 return 0; 282 } 283 if (xkb->names) 284 name = XkbAtomGetString(dpy, xkb->names->types); 285 else 286 name = NULL; 287 size = xkmSizeCountedString(name); 288 size += 4; /* room for # of key types + padding */ 289 for (i = 0, type = xkb->map->types; i < xkb->map->num_types; i++, type++) { 290 size += SIZEOF(xkmKeyTypeDesc); 291 size += SIZEOF(xkmKTMapEntryDesc) * type->map_count; 292 size += xkmSizeCountedAtomString(dpy, type->name); 293 if (type->preserve) 294 size += SIZEOF(xkmModsDesc) * type->map_count; 295 if (type->level_names) { 296 Atom *names; 297 298 names = type->level_names; 299 for (n = 0; n < (unsigned) type->num_levels; n++) { 300 size += xkmSizeCountedAtomString(dpy, names[n]); 301 } 302 } 303 } 304 toc->type = XkmTypesIndex; 305 toc->format = MSBFirst; 306 toc->size = size + SIZEOF(xkmSectionInfo); 307 toc->offset = (*offset_inout); 308 (*offset_inout) += toc->size; 309 return 1; 310} 311 312static unsigned 313WriteXKMKeyTypes(FILE *file, XkbFileInfo *result) 314{ 315 register unsigned i, n; 316 XkbDescPtr xkb; 317 XkbKeyTypePtr type; 318 xkmKeyTypeDesc wire; 319 XkbKTMapEntryPtr entry; 320 xkmKTMapEntryDesc wire_entry; 321 Atom *names; 322 Display *dpy; 323 unsigned tmp, size = 0; 324 char *name; 325 326 xkb = result->xkb; 327 dpy = xkb->dpy; 328 if (xkb->names) 329 name = XkbAtomGetString(dpy, xkb->names->types); 330 else 331 name = NULL; 332 size += xkmPutCountedString(file, name); 333 size += xkmPutCARD16(file, xkb->map->num_types); 334 size += xkmPutPadding(file, 2); 335 type = xkb->map->types; 336 for (i = 0; i < xkb->map->num_types; i++, type++) { 337 wire.realMods = type->mods.real_mods; 338 wire.virtualMods = type->mods.vmods; 339 wire.numLevels = type->num_levels; 340 wire.nMapEntries = type->map_count; 341 wire.preserve = (type->preserve != NULL); 342 if (type->level_names != NULL) 343 wire.nLevelNames = type->num_levels; 344 else 345 wire.nLevelNames = 0; 346 tmp = fwrite(&wire, SIZEOF(xkmKeyTypeDesc), 1, file); 347 size += tmp * SIZEOF(xkmKeyTypeDesc); 348 for (n = 0, entry = type->map; n < type->map_count; n++, entry++) { 349 wire_entry.level = entry->level; 350 wire_entry.realMods = entry->mods.real_mods; 351 wire_entry.virtualMods = entry->mods.vmods; 352 tmp = fwrite(&wire_entry, SIZEOF(xkmKTMapEntryDesc), 1, file); 353 size += tmp * SIZEOF(xkmKTMapEntryDesc); 354 } 355 size += xkmPutCountedString(file, XkbAtomGetString(dpy, type->name)); 356 if (type->preserve) { 357 xkmModsDesc p_entry; 358 359 XkbModsPtr pre; 360 361 for (n = 0, pre = type->preserve; n < type->map_count; n++, pre++) { 362 p_entry.realMods = pre->real_mods; 363 p_entry.virtualMods = pre->vmods; 364 tmp = fwrite(&p_entry, SIZEOF(xkmModsDesc), 1, file); 365 size += tmp * SIZEOF(xkmModsDesc); 366 } 367 } 368 if (type->level_names != NULL) { 369 names = type->level_names; 370 for (n = 0; n < wire.nLevelNames; n++) { 371 size += 372 xkmPutCountedString(file, XkbAtomGetString(dpy, names[n])); 373 } 374 } 375 } 376 return size; 377} 378 379/***====================================================================***/ 380 381static unsigned 382SizeXKMCompatMap(XkbFileInfo *result, XkmInfo *info, 383 xkmSectionInfo *toc, int *offset_inout) 384{ 385 XkbDescPtr xkb; 386 char *name; 387 int size; 388 register int i; 389 unsigned groups, nGroups; 390 Display *dpy; 391 392 xkb = result->xkb; 393 if ((!xkb) || (!xkb->compat) || (!xkb->compat->sym_interpret)) { 394 _XkbLibError(_XkbErrMissingCompatMap, "SizeXKMCompatMap", 0); 395 return 0; 396 } 397 dpy = xkb->dpy; 398 if (xkb->names) 399 name = XkbAtomGetString(dpy, xkb->names->compat); 400 else 401 name = NULL; 402 403 for (i = groups = nGroups = 0; i < XkbNumKbdGroups; i++) { 404 if ((xkb->compat->groups[i].real_mods != 0) || 405 (xkb->compat->groups[i].vmods != 0)) { 406 groups |= (1 << i); 407 nGroups++; 408 } 409 } 410 info->group_compat = groups; 411 info->num_group_compat = nGroups; 412 size = 4; /* room for num_si and group_compat mask */ 413 size += xkmSizeCountedString(name); 414 size += (SIZEOF(xkmSymInterpretDesc) * xkb->compat->num_si); 415 size += (SIZEOF(xkmModsDesc) * nGroups); 416 toc->type = XkmCompatMapIndex; 417 toc->format = MSBFirst; 418 toc->size = size + SIZEOF(xkmSectionInfo); 419 toc->offset = (*offset_inout); 420 (*offset_inout) += toc->size; 421 return 1; 422} 423 424static unsigned 425WriteXKMCompatMap(FILE *file, XkbFileInfo *result, XkmInfo *info) 426{ 427 register unsigned i; 428 char *name; 429 XkbDescPtr xkb; 430 XkbSymInterpretPtr interp; 431 xkmSymInterpretDesc wire; 432 Display *dpy; 433 unsigned tmp, size = 0; 434 435 xkb = result->xkb; 436 dpy = xkb->dpy; 437 if (xkb->names) 438 name = XkbAtomGetString(dpy, xkb->names->compat); 439 else 440 name = NULL; 441 size += xkmPutCountedString(file, name); 442 size += xkmPutCARD16(file, xkb->compat->num_si); 443 size += xkmPutCARD8(file, info->group_compat); 444 size += xkmPutPadding(file, 1); 445 interp = xkb->compat->sym_interpret; 446 for (i = 0; i < xkb->compat->num_si; i++, interp++) { 447 wire.sym = interp->sym; 448 wire.mods = interp->mods; 449 wire.match = interp->match; 450 wire.virtualMod = interp->virtual_mod; 451 wire.flags = interp->flags; 452 wire.actionType = interp->act.type; 453 wire.actionData[0] = interp->act.data[0]; 454 wire.actionData[1] = interp->act.data[1]; 455 wire.actionData[2] = interp->act.data[2]; 456 wire.actionData[3] = interp->act.data[3]; 457 wire.actionData[4] = interp->act.data[4]; 458 wire.actionData[5] = interp->act.data[5]; 459 wire.actionData[6] = interp->act.data[6]; 460 tmp = fwrite(&wire, SIZEOF(xkmSymInterpretDesc), 1, file); 461 size += tmp * SIZEOF(xkmSymInterpretDesc); 462 } 463 if (info->group_compat) { 464 register unsigned bit; 465 466 xkmModsDesc modsWire; 467 468 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 469 if (info->group_compat & bit) { 470 modsWire.realMods = xkb->compat->groups[i].real_mods; 471 modsWire.virtualMods = xkb->compat->groups[i].vmods; 472 fwrite(&modsWire, SIZEOF(xkmModsDesc), 1, file); 473 size += SIZEOF(xkmModsDesc); 474 } 475 } 476 } 477 return size; 478} 479 480/***====================================================================***/ 481 482static unsigned 483SizeXKMSymbols(XkbFileInfo *result, XkmInfo *info, 484 xkmSectionInfo *toc, int *offset_inout) 485{ 486 Display *dpy; 487 XkbDescPtr xkb; 488 unsigned size; 489 register int i, nSyms; 490 char *name; 491 492 xkb = result->xkb; 493 if ((!xkb) || (!xkb->map) || ((!xkb->map->syms))) { 494 _XkbLibError(_XkbErrMissingSymbols, "SizeXKMSymbols", 0); 495 return 0; 496 } 497 dpy = xkb->dpy; 498 if (xkb->names && (xkb->names->symbols != None)) 499 name = XkbAtomGetString(dpy, xkb->names->symbols); 500 else 501 name = NULL; 502 size = xkmSizeCountedString(name); 503 size += 4; /* min and max keycode, group names mask */ 504 for (i = 0; i < XkbNumKbdGroups; i++) { 505 if (xkb->names->groups[i] != None) 506 size += xkmSizeCountedAtomString(dpy, xkb->names->groups[i]); 507 } 508 info->total_vmodmaps = 0; 509 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 510 nSyms = XkbKeyNumSyms(xkb, i); 511 size += SIZEOF(xkmKeySymMapDesc) + (nSyms * 4); 512 if (xkb->server) { 513 if (xkb->server->explicit[i] & XkbExplicitKeyTypesMask) { 514 register int g; 515 516 for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) { 517 if (xkb->server->explicit[i] & (1 << g)) { 518 XkbKeyTypePtr type; 519 char *name; 520 521 type = XkbKeyKeyType(xkb, i, g); 522 name = XkbAtomGetString(dpy, type->name); 523 if (name != NULL) 524 size += xkmSizeCountedString(name); 525 } 526 } 527 } 528 if (XkbKeyHasActions(xkb, i)) 529 size += nSyms * SIZEOF(xkmActionDesc); 530 if (xkb->server->behaviors[i].type != XkbKB_Default) 531 size += SIZEOF(xkmBehaviorDesc); 532 if (xkb->server->vmodmap && (xkb->server->vmodmap[i] != 0)) 533 info->total_vmodmaps++; 534 } 535 } 536 size += info->total_vmodmaps * SIZEOF(xkmVModMapDesc); 537 toc->type = XkmSymbolsIndex; 538 toc->format = MSBFirst; 539 toc->size = size + SIZEOF(xkmSectionInfo); 540 toc->offset = (*offset_inout); 541 (*offset_inout) += toc->size; 542 return 1; 543} 544 545static unsigned 546WriteXKMSymbols(FILE *file, XkbFileInfo *result, XkmInfo *info) 547{ 548 Display *dpy; 549 XkbDescPtr xkb; 550 register int i, n; 551 xkmKeySymMapDesc wireMap; 552 char *name; 553 unsigned tmp, size = 0; 554 555 xkb = result->xkb; 556 dpy = xkb->dpy; 557 if (xkb->names && (xkb->names->symbols != None)) 558 name = XkbAtomGetString(dpy, xkb->names->symbols); 559 else 560 name = NULL; 561 size += xkmPutCountedString(file, name); 562 for (tmp = i = 0; i < XkbNumKbdGroups; i++) { 563 if (xkb->names->groups[i] != None) 564 tmp |= (1 << i); 565 } 566 size += xkmPutCARD8(file, xkb->min_key_code); 567 size += xkmPutCARD8(file, xkb->max_key_code); 568 size += xkmPutCARD8(file, tmp); 569 size += xkmPutCARD8(file, info->total_vmodmaps); 570 for (i = 0, n = 1; i < XkbNumKbdGroups; i++, n <<= 1) { 571 if ((tmp & n) == 0) 572 continue; 573 size += xkmPutCountedAtomString(dpy, file, xkb->names->groups[i]); 574 } 575 for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) { 576 char *typeName[XkbNumKbdGroups]; 577 578 wireMap.width = XkbKeyGroupsWidth(xkb, i); 579 wireMap.num_groups = XkbKeyGroupInfo(xkb, i); 580 if (xkb->map && xkb->map->modmap) 581 wireMap.modifier_map = xkb->map->modmap[i]; 582 else 583 wireMap.modifier_map = 0; 584 wireMap.flags = 0; 585 bzero((char *) typeName, XkbNumKbdGroups * sizeof(char *)); 586 if (xkb->server) { 587 if (xkb->server->explicit[i] & XkbExplicitKeyTypesMask) { 588 register int g; 589 590 for (g = 0; g < XkbKeyNumGroups(xkb, i); g++) { 591 if (xkb->server->explicit[i] & (1 << g)) { 592 XkbKeyTypePtr type; 593 594 type = XkbKeyKeyType(xkb, i, g); 595 typeName[g] = XkbAtomGetString(dpy, type->name); 596 if (typeName[g] != NULL) 597 wireMap.flags |= (1 << g); 598 } 599 } 600 } 601 if (XkbKeyHasActions(xkb, i)) 602 wireMap.flags |= XkmKeyHasActions; 603 if (xkb->server->behaviors[i].type != XkbKB_Default) 604 wireMap.flags |= XkmKeyHasBehavior; 605 if ((xkb->server->explicit[i] & XkbExplicitAutoRepeatMask) && 606 (xkb->ctrls != NULL)) { 607 if (xkb->ctrls->per_key_repeat[(i / 8)] & (1 << (i % 8))) 608 wireMap.flags |= XkmRepeatingKey; 609 else 610 wireMap.flags |= XkmNonRepeatingKey; 611 } 612 } 613 tmp = fwrite(&wireMap, SIZEOF(xkmKeySymMapDesc), 1, file); 614 size += tmp * SIZEOF(xkmKeySymMapDesc); 615 if (xkb->server->explicit[i] & XkbExplicitKeyTypesMask) { 616 register int g; 617 618 for (g = 0; g < XkbNumKbdGroups; g++) { 619 if (typeName[g] != NULL) 620 size += xkmPutCountedString(file, typeName[g]); 621 } 622 } 623 if (XkbNumGroups(wireMap.num_groups) > 0) { 624 KeySym *sym; 625 626 sym = XkbKeySymsPtr(xkb, i); 627 for (n = XkbKeyNumSyms(xkb, i); n > 0; n--, sym++) { 628 size += xkmPutCARD32(file, (CARD32) *sym); 629 } 630 if (wireMap.flags & XkmKeyHasActions) { 631 XkbAction *act; 632 633 act = XkbKeyActionsPtr(xkb, i); 634 for (n = XkbKeyNumActions(xkb, i); n > 0; n--, act++) { 635 tmp = fwrite(act, SIZEOF(xkmActionDesc), 1, file); 636 size += tmp * SIZEOF(xkmActionDesc); 637 } 638 } 639 } 640 if (wireMap.flags & XkmKeyHasBehavior) { 641 xkmBehaviorDesc b; 642 643 b.type = xkb->server->behaviors[i].type; 644 b.data = xkb->server->behaviors[i].data; 645 tmp = fwrite(&b, SIZEOF(xkmBehaviorDesc), 1, file); 646 size += tmp * SIZEOF(xkmBehaviorDesc); 647 } 648 } 649 if (info->total_vmodmaps > 0) { 650 xkmVModMapDesc v; 651 652 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 653 if (xkb->server->vmodmap[i] != 0) { 654 v.key = i; 655 v.vmods = xkb->server->vmodmap[i]; 656 tmp = fwrite(&v, SIZEOF(xkmVModMapDesc), 1, file); 657 size += tmp * SIZEOF(xkmVModMapDesc); 658 } 659 } 660 } 661 return size; 662} 663 664/***====================================================================***/ 665 666static unsigned 667SizeXKMIndicators(XkbFileInfo *result, XkmInfo *info, 668 xkmSectionInfo *toc, int *offset_inout) 669{ 670 Display *dpy; 671 XkbDescPtr xkb; 672 unsigned size; 673 register unsigned i, nLEDs; 674 675 xkb = result->xkb; 676 if ((xkb == NULL) || (xkb->indicators == NULL)) { 677/* _XkbLibError(_XkbErrMissingIndicators,"SizeXKMIndicators",0);*/ 678 return 0; 679 } 680 dpy = xkb->dpy; 681 nLEDs = 0; 682 size = 8; /* number of indicator maps/physical indicators */ 683 if (xkb->indicators != NULL) { 684 for (i = 0; i < XkbNumIndicators; i++) { 685 XkbIndicatorMapPtr map = &xkb->indicators->maps[i]; 686 687 if ((map->flags != 0) || (map->which_groups != 0) || 688 (map->groups != 0) || (map->which_mods != 0) || 689 (map->mods.real_mods != 0) || (map->mods.vmods != 0) || 690 (map->ctrls != 0) || 691 (xkb->names && (xkb->names->indicators[i] != None))) { 692 char *name; 693 694 if (xkb->names && xkb->names->indicators[i] != None) { 695 name = XkbAtomGetString(dpy, xkb->names->indicators[i]); 696 } 697 else 698 name = NULL; 699 size += xkmSizeCountedString(name); 700 size += SIZEOF(xkmIndicatorMapDesc); 701 nLEDs++; 702 } 703 } 704 } 705 info->num_leds = nLEDs; 706 toc->type = XkmIndicatorsIndex; 707 toc->format = MSBFirst; 708 toc->size = size + SIZEOF(xkmSectionInfo); 709 toc->offset = (*offset_inout); 710 (*offset_inout) += toc->size; 711 return 1; 712} 713 714static unsigned 715WriteXKMIndicators(FILE *file, XkbFileInfo *result, XkmInfo *info) 716{ 717 Display *dpy; 718 XkbDescPtr xkb; 719 register unsigned i; 720 xkmIndicatorMapDesc wire; 721 unsigned tmp, size = 0; 722 723 xkb = result->xkb; 724 dpy = xkb->dpy; 725 size += xkmPutCARD8(file, info->num_leds); 726 size += xkmPutPadding(file, 3); 727 size += xkmPutCARD32(file, xkb->indicators->phys_indicators); 728 if (xkb->indicators != NULL) { 729 for (i = 0; i < XkbNumIndicators; i++) { 730 XkbIndicatorMapPtr map = &xkb->indicators->maps[i]; 731 732 if ((map->flags != 0) || (map->which_groups != 0) || 733 (map->groups != 0) || (map->which_mods != 0) || 734 (map->mods.real_mods != 0) || (map->mods.vmods != 0) || 735 (map->ctrls != 0) || (xkb->names && 736 (xkb->names->indicators[i] != None))) { 737 char *name; 738 739 if (xkb->names && xkb->names->indicators[i] != None) { 740 name = XkbAtomGetString(dpy, xkb->names->indicators[i]); 741 } 742 else 743 name = NULL; 744 size += xkmPutCountedString(file, name); 745 wire.indicator = i + 1; 746 wire.flags = map->flags; 747 wire.which_mods = map->which_mods; 748 wire.real_mods = map->mods.real_mods; 749 wire.vmods = map->mods.vmods; 750 wire.which_groups = map->which_groups; 751 wire.groups = map->groups; 752 wire.ctrls = map->ctrls; 753 tmp = fwrite(&wire, SIZEOF(xkmIndicatorMapDesc), 1, file); 754 size += tmp * SIZEOF(xkmIndicatorMapDesc); 755 } 756 } 757 } 758 return size; 759} 760 761/***====================================================================***/ 762 763static unsigned 764SizeXKMGeomDoodad(XkbFileInfo *result, XkbDoodadPtr doodad) 765{ 766 unsigned size; 767 768 size = SIZEOF(xkmAnyDoodadDesc); 769 size += xkmSizeCountedAtomString(result->xkb->dpy, doodad->any.name); 770 if (doodad->any.type == XkbTextDoodad) { 771 size += xkmSizeCountedString(doodad->text.text); 772 size += xkmSizeCountedString(doodad->text.font); 773 } 774 else if (doodad->any.type == XkbLogoDoodad) { 775 size += xkmSizeCountedString(doodad->logo.logo_name); 776 } 777 return size; 778} 779 780static unsigned 781SizeXKMGeomSection(XkbFileInfo *result, XkbSectionPtr section) 782{ 783 register int i; 784 unsigned size; 785 786 size = SIZEOF(xkmSectionDesc); 787 size += xkmSizeCountedAtomString(result->xkb->dpy, section->name); 788 if (section->rows) { 789 XkbRowPtr row; 790 791 for (row = section->rows, i = 0; i < section->num_rows; i++, row++) { 792 size += SIZEOF(xkmRowDesc); 793 size += row->num_keys * SIZEOF(xkmKeyDesc); 794 } 795 } 796 if (section->doodads) { 797 XkbDoodadPtr doodad; 798 799 for (doodad = section->doodads, i = 0; i < section->num_doodads; 800 i++, doodad++) { 801 size += SizeXKMGeomDoodad(result, doodad); 802 } 803 } 804 if (section->overlays) { 805 XkbOverlayPtr ol; 806 807 for (ol = section->overlays, i = 0; i < section->num_overlays; 808 i++, ol++) { 809 register int r; 810 XkbOverlayRowPtr row; 811 812 size += xkmSizeCountedAtomString(result->xkb->dpy, ol->name); 813 size += SIZEOF(xkmOverlayDesc); 814 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 815 size += SIZEOF(xkmOverlayRowDesc); 816 size += row->num_keys * SIZEOF(xkmOverlayKeyDesc); 817 } 818 } 819 } 820 return size; 821} 822 823static unsigned 824SizeXKMGeometry(XkbFileInfo *result, xkmSectionInfo *toc, int *offset_inout) 825{ 826 register int i; 827 Display *dpy; 828 XkbDescPtr xkb; 829 XkbGeometryPtr geom; 830 unsigned size; 831 832 xkb = result->xkb; 833 if ((!xkb) || (!xkb->geom)) 834 return 0; 835 dpy = xkb->dpy; 836 geom = xkb->geom; 837 size = xkmSizeCountedAtomString(dpy, geom->name); 838 size += SIZEOF(xkmGeometryDesc); 839 size += xkmSizeCountedString(geom->label_font); 840 if (geom->properties) { 841 XkbPropertyPtr prop; 842 843 for (i = 0, prop = geom->properties; i < geom->num_properties; 844 i++, prop++) { 845 size += xkmSizeCountedString(prop->name); 846 size += xkmSizeCountedString(prop->value); 847 } 848 } 849 if (geom->colors) { 850 XkbColorPtr color; 851 852 for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 853 size += xkmSizeCountedString(color->spec); 854 } 855 } 856 if (geom->shapes) { 857 XkbShapePtr shape; 858 859 for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 860 register int n; 861 register XkbOutlinePtr ol; 862 863 size += xkmSizeCountedAtomString(dpy, shape->name); 864 size += SIZEOF(xkmShapeDesc); 865 for (n = 0, ol = shape->outlines; n < shape->num_outlines; 866 n++, ol++) { 867 size += SIZEOF(xkmOutlineDesc); 868 size += ol->num_points * SIZEOF(xkmPointDesc); 869 } 870 } 871 } 872 if (geom->sections) { 873 XkbSectionPtr section; 874 875 for (i = 0, section = geom->sections; i < geom->num_sections; 876 i++, section++) { 877 size += SizeXKMGeomSection(result, section); 878 } 879 } 880 if (geom->doodads) { 881 XkbDoodadPtr doodad; 882 883 for (i = 0, doodad = geom->doodads; i < geom->num_doodads; 884 i++, doodad++) { 885 size += SizeXKMGeomDoodad(result, doodad); 886 } 887 } 888 if (geom->key_aliases) { 889 size += geom->num_key_aliases * (XkbKeyNameLength * 2); 890 } 891 toc->type = XkmGeometryIndex; 892 toc->format = MSBFirst; 893 toc->size = size + SIZEOF(xkmSectionInfo); 894 toc->offset = (*offset_inout); 895 (*offset_inout) += toc->size; 896 return 1; 897} 898 899static unsigned 900WriteXKMGeomDoodad(FILE *file, XkbFileInfo *result, XkbDoodadPtr doodad) 901{ 902 Display *dpy; 903 XkbDescPtr xkb; 904 xkmDoodadDesc doodadWire; 905 unsigned tmp, size = 0; 906 907 xkb = result->xkb; 908 dpy = xkb->dpy; 909 bzero((char *) &doodadWire, sizeof(doodadWire)); 910 doodadWire.any.type = doodad->any.type; 911 doodadWire.any.priority = doodad->any.priority; 912 doodadWire.any.top = doodad->any.top; 913 doodadWire.any.left = doodad->any.left; 914 switch (doodad->any.type) { 915 case XkbOutlineDoodad: 916 case XkbSolidDoodad: 917 doodadWire.shape.angle = doodad->shape.angle; 918 doodadWire.shape.color_ndx = doodad->shape.color_ndx; 919 doodadWire.shape.shape_ndx = doodad->shape.shape_ndx; 920 break; 921 case XkbTextDoodad: 922 doodadWire.text.angle = doodad->text.angle; 923 doodadWire.text.width = doodad->text.width; 924 doodadWire.text.height = doodad->text.height; 925 doodadWire.text.color_ndx = doodad->text.color_ndx; 926 break; 927 case XkbIndicatorDoodad: 928 doodadWire.indicator.shape_ndx = doodad->indicator.shape_ndx; 929 doodadWire.indicator.on_color_ndx = doodad->indicator.on_color_ndx; 930 doodadWire.indicator.off_color_ndx = doodad->indicator.off_color_ndx; 931 break; 932 case XkbLogoDoodad: 933 doodadWire.logo.angle = doodad->logo.angle; 934 doodadWire.logo.color_ndx = doodad->logo.color_ndx; 935 doodadWire.logo.shape_ndx = doodad->logo.shape_ndx; 936 break; 937 default: 938 _XkbLibError(_XkbErrIllegalDoodad, "WriteXKMGeomDoodad", 939 doodad->any.type); 940 return 0; 941 } 942 size += xkmPutCountedAtomString(dpy, file, doodad->any.name); 943 tmp = fwrite(&doodadWire, SIZEOF(xkmDoodadDesc), 1, file); 944 size += tmp * SIZEOF(xkmDoodadDesc); 945 if (doodad->any.type == XkbTextDoodad) { 946 size += xkmPutCountedString(file, doodad->text.text); 947 size += xkmPutCountedString(file, doodad->text.font); 948 } 949 else if (doodad->any.type == XkbLogoDoodad) { 950 size += xkmPutCountedString(file, doodad->logo.logo_name); 951 } 952 return size; 953} 954 955static unsigned 956WriteXKMGeomOverlay(FILE *file, XkbFileInfo *result, XkbOverlayPtr ol) 957{ 958 register int r, k; 959 Display *dpy; 960 XkbDescPtr xkb; 961 XkbOverlayRowPtr row; 962 xkmOverlayDesc olWire; 963 xkmOverlayRowDesc rowWire; 964 xkmOverlayKeyDesc keyWire; 965 unsigned tmp, size = 0; 966 967 xkb = result->xkb; 968 dpy = xkb->dpy; 969 bzero((char *) &olWire, sizeof(olWire)); 970 bzero((char *) &rowWire, sizeof(rowWire)); 971 bzero((char *) &keyWire, sizeof(keyWire)); 972 size += xkmPutCountedAtomString(dpy, file, ol->name); 973 olWire.num_rows = ol->num_rows; 974 tmp = fwrite(&olWire, SIZEOF(xkmOverlayDesc), 1, file); 975 size += tmp * SIZEOF(xkmOverlayDesc); 976 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 977 XkbOverlayKeyPtr key; 978 979 rowWire.row_under = row->row_under; 980 rowWire.num_keys = row->num_keys; 981 tmp = fwrite(&rowWire, SIZEOF(xkmOverlayRowDesc), 1, file); 982 size += tmp * SIZEOF(xkmOverlayRowDesc); 983 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 984 memcpy(keyWire.over, key->over.name, XkbKeyNameLength); 985 memcpy(keyWire.under, key->under.name, XkbKeyNameLength); 986 tmp = fwrite(&keyWire, SIZEOF(xkmOverlayKeyDesc), 1, file); 987 size += tmp * SIZEOF(xkmOverlayKeyDesc); 988 } 989 } 990 return size; 991} 992 993static unsigned 994WriteXKMGeomSection(FILE *file, XkbFileInfo *result, XkbSectionPtr section) 995{ 996 register int i; 997 Display *dpy; 998 XkbDescPtr xkb; 999 xkmSectionDesc sectionWire; 1000 unsigned tmp, size = 0; 1001 1002 xkb = result->xkb; 1003 dpy = xkb->dpy; 1004 size += xkmPutCountedAtomString(dpy, file, section->name); 1005 sectionWire.top = section->top; 1006 sectionWire.left = section->left; 1007 sectionWire.width = section->width; 1008 sectionWire.height = section->height; 1009 sectionWire.angle = section->angle; 1010 sectionWire.priority = section->priority; 1011 sectionWire.num_rows = section->num_rows; 1012 sectionWire.num_doodads = section->num_doodads; 1013 sectionWire.num_overlays = section->num_overlays; 1014 tmp = fwrite(§ionWire, SIZEOF(xkmSectionDesc), 1, file); 1015 size += tmp * SIZEOF(xkmSectionDesc); 1016 if (section->rows) { 1017 register unsigned k; 1018 XkbRowPtr row; 1019 xkmRowDesc rowWire; 1020 XkbKeyPtr key; 1021 xkmKeyDesc keyWire; 1022 1023 for (i = 0, row = section->rows; i < section->num_rows; i++, row++) { 1024 rowWire.top = row->top; 1025 rowWire.left = row->left; 1026 rowWire.num_keys = row->num_keys; 1027 rowWire.vertical = row->vertical; 1028 tmp = fwrite(&rowWire, SIZEOF(xkmRowDesc), 1, file); 1029 size += tmp * SIZEOF(xkmRowDesc); 1030 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 1031 memcpy(keyWire.name, key->name.name, XkbKeyNameLength); 1032 keyWire.gap = key->gap; 1033 keyWire.shape_ndx = key->shape_ndx; 1034 keyWire.color_ndx = key->color_ndx; 1035 tmp = fwrite(&keyWire, SIZEOF(xkmKeyDesc), 1, file); 1036 size += tmp * SIZEOF(xkmKeyDesc); 1037 } 1038 } 1039 } 1040 if (section->doodads) { 1041 XkbDoodadPtr doodad; 1042 1043 for (i = 0, doodad = section->doodads; i < section->num_doodads; 1044 i++, doodad++) { 1045 size += WriteXKMGeomDoodad(file, result, doodad); 1046 } 1047 } 1048 if (section->overlays) { 1049 XkbOverlayPtr ol; 1050 1051 for (i = 0, ol = section->overlays; i < section->num_overlays; 1052 i++, ol++) { 1053 size += WriteXKMGeomOverlay(file, result, ol); 1054 } 1055 } 1056 return size; 1057} 1058 1059static unsigned 1060WriteXKMGeometry(FILE *file, XkbFileInfo *result) 1061{ 1062 register int i; 1063 Display *dpy; 1064 XkbDescPtr xkb; 1065 XkbGeometryPtr geom; 1066 xkmGeometryDesc wire; 1067 unsigned tmp, size = 0; 1068 1069 xkb = result->xkb; 1070 if ((!xkb) || (!xkb->geom)) 1071 return 0; 1072 dpy = xkb->dpy; 1073 geom = xkb->geom; 1074 wire.width_mm = geom->width_mm; 1075 wire.height_mm = geom->height_mm; 1076 wire.base_color_ndx = XkbGeomColorIndex(geom, geom->base_color); 1077 wire.label_color_ndx = XkbGeomColorIndex(geom, geom->label_color); 1078 wire.num_properties = geom->num_properties; 1079 wire.num_colors = geom->num_colors; 1080 wire.num_shapes = geom->num_shapes; 1081 wire.num_sections = geom->num_sections; 1082 wire.num_doodads = geom->num_doodads; 1083 wire.num_key_aliases = geom->num_key_aliases; 1084 size += xkmPutCountedAtomString(dpy, file, geom->name); 1085 tmp = fwrite(&wire, SIZEOF(xkmGeometryDesc), 1, file); 1086 size += tmp * SIZEOF(xkmGeometryDesc); 1087 size += xkmPutCountedString(file, geom->label_font); 1088 if (geom->properties) { 1089 XkbPropertyPtr prop; 1090 1091 for (i = 0, prop = geom->properties; i < geom->num_properties; 1092 i++, prop++) { 1093 size += xkmPutCountedString(file, prop->name); 1094 size += xkmPutCountedString(file, prop->value); 1095 } 1096 } 1097 if (geom->colors) { 1098 XkbColorPtr color; 1099 1100 for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 1101 size += xkmPutCountedString(file, color->spec); 1102 } 1103 } 1104 if (geom->shapes) { 1105 XkbShapePtr shape; 1106 xkmShapeDesc shapeWire; 1107 1108 for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 1109 register int n; 1110 XkbOutlinePtr ol; 1111 xkmOutlineDesc olWire; 1112 1113 bzero((char *) &shapeWire, sizeof(xkmShapeDesc)); 1114 size += xkmPutCountedAtomString(dpy, file, shape->name); 1115 shapeWire.num_outlines = shape->num_outlines; 1116 if (shape->primary != NULL) 1117 shapeWire.primary_ndx = XkbOutlineIndex(shape, shape->primary); 1118 else 1119 shapeWire.primary_ndx = XkbNoShape; 1120 if (shape->approx != NULL) 1121 shapeWire.approx_ndx = XkbOutlineIndex(shape, shape->approx); 1122 else 1123 shapeWire.approx_ndx = XkbNoShape; 1124 tmp = fwrite(&shapeWire, SIZEOF(xkmShapeDesc), 1, file); 1125 size += tmp * SIZEOF(xkmShapeDesc); 1126 for (n = 0, ol = shape->outlines; n < shape->num_outlines; 1127 n++, ol++) { 1128 register int p; 1129 XkbPointPtr pt; 1130 xkmPointDesc ptWire; 1131 1132 olWire.num_points = ol->num_points; 1133 olWire.corner_radius = ol->corner_radius; 1134 tmp = fwrite(&olWire, SIZEOF(xkmOutlineDesc), 1, file); 1135 size += tmp * SIZEOF(xkmOutlineDesc); 1136 for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) { 1137 ptWire.x = pt->x; 1138 ptWire.y = pt->y; 1139 tmp = fwrite(&ptWire, SIZEOF(xkmPointDesc), 1, file); 1140 size += tmp * SIZEOF(xkmPointDesc); 1141 } 1142 } 1143 } 1144 } 1145 if (geom->sections) { 1146 XkbSectionPtr section; 1147 1148 for (i = 0, section = geom->sections; i < geom->num_sections; 1149 i++, section++) { 1150 size += WriteXKMGeomSection(file, result, section); 1151 } 1152 } 1153 if (geom->doodads) { 1154 XkbDoodadPtr doodad; 1155 1156 for (i = 0, doodad = geom->doodads; i < geom->num_doodads; 1157 i++, doodad++) { 1158 size += WriteXKMGeomDoodad(file, result, doodad); 1159 } 1160 } 1161 if (geom->key_aliases) { 1162 tmp = 1163 fwrite(geom->key_aliases, 2 * XkbKeyNameLength, 1164 geom->num_key_aliases, file); 1165 size += tmp * (2 * XkbKeyNameLength); 1166 } 1167 return size; 1168} 1169 1170/***====================================================================***/ 1171 1172/*ARGSUSED*/ 1173static int 1174GetXKMKeyNamesTOC(XkbFileInfo *result, XkmInfo *info, 1175 int max_toc, xkmSectionInfo *toc_rtrn) 1176{ 1177 int num_toc; 1178 int total_size; 1179 1180 total_size = num_toc = 0; 1181 if (SizeXKMKeycodes(result, &toc_rtrn[num_toc], &total_size)) 1182 num_toc++; 1183 if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size)) 1184 num_toc++; 1185 return num_toc; 1186} 1187 1188/*ARGSUSED*/ 1189static int 1190GetXKMTypesTOC(XkbFileInfo *result, XkmInfo *info, 1191 int max_toc, xkmSectionInfo *toc_rtrn) 1192{ 1193 int num_toc; 1194 int total_size; 1195 1196 total_size = num_toc = 0; 1197 if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size)) 1198 num_toc++; 1199 if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size)) 1200 num_toc++; 1201 return num_toc; 1202} 1203 1204/*ARGSUSED*/ 1205static int 1206GetXKMCompatMapTOC(XkbFileInfo *result, XkmInfo *info, 1207 int max_toc, xkmSectionInfo *toc_rtrn) 1208{ 1209 int num_toc; 1210 int total_size; 1211 1212 total_size = num_toc = 0; 1213 if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size)) 1214 num_toc++; 1215 if (SizeXKMCompatMap(result, info, &toc_rtrn[num_toc], &total_size)) 1216 num_toc++; 1217 if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size)) 1218 num_toc++; 1219 return num_toc; 1220} 1221 1222/*ARGSUSED*/ 1223static int 1224GetXKMSemanticsTOC(XkbFileInfo *result, XkmInfo *info, 1225 int max_toc, xkmSectionInfo *toc_rtrn) 1226{ 1227 int num_toc; 1228 int total_size; 1229 1230 total_size = num_toc = 0; 1231 if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size)) 1232 num_toc++; 1233 if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size)) 1234 num_toc++; 1235 if (SizeXKMCompatMap(result, info, &toc_rtrn[num_toc], &total_size)) 1236 num_toc++; 1237 if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size)) 1238 num_toc++; 1239 return num_toc; 1240} 1241 1242/*ARGSUSED*/ 1243static int 1244GetXKMLayoutTOC(XkbFileInfo *result, XkmInfo *info, 1245 int max_toc, xkmSectionInfo *toc_rtrn) 1246{ 1247 int num_toc; 1248 int total_size; 1249 1250 total_size = num_toc = 0; 1251 if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size)) 1252 num_toc++; 1253 if (SizeXKMKeycodes(result, &toc_rtrn[num_toc], &total_size)) 1254 num_toc++; 1255 if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size)) 1256 num_toc++; 1257 if (SizeXKMSymbols(result, info, &toc_rtrn[num_toc], &total_size)) 1258 num_toc++; 1259 if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size)) 1260 num_toc++; 1261 if (SizeXKMGeometry(result, &toc_rtrn[num_toc], &total_size)) 1262 num_toc++; 1263 return num_toc; 1264} 1265 1266/*ARGSUSED*/ 1267static int 1268GetXKMKeymapTOC(XkbFileInfo *result, XkmInfo *info, 1269 int max_toc, xkmSectionInfo *toc_rtrn) 1270{ 1271 int num_toc; 1272 int total_size; 1273 1274 total_size = num_toc = 0; 1275 if (SizeXKMVirtualMods(result, info, &toc_rtrn[num_toc], &total_size)) 1276 num_toc++; 1277 if (SizeXKMKeycodes(result, &toc_rtrn[num_toc], &total_size)) 1278 num_toc++; 1279 if (SizeXKMKeyTypes(result, &toc_rtrn[num_toc], &total_size)) 1280 num_toc++; 1281 if (SizeXKMCompatMap(result, info, &toc_rtrn[num_toc], &total_size)) 1282 num_toc++; 1283 if (SizeXKMSymbols(result, info, &toc_rtrn[num_toc], &total_size)) 1284 num_toc++; 1285 if (SizeXKMIndicators(result, info, &toc_rtrn[num_toc], &total_size)) 1286 num_toc++; 1287 if (SizeXKMGeometry(result, &toc_rtrn[num_toc], &total_size)) 1288 num_toc++; 1289 return num_toc; 1290} 1291 1292/*ARGSUSED*/ 1293static int 1294GetXKMGeometryTOC(XkbFileInfo *result, XkmInfo *info, 1295 int max_toc, xkmSectionInfo *toc_rtrn) 1296{ 1297 int num_toc; 1298 int total_size; 1299 1300 total_size = num_toc = 0; 1301 if (SizeXKMGeometry(result, &toc_rtrn[num_toc], &total_size)) 1302 num_toc++; 1303 return num_toc; 1304} 1305 1306static Bool 1307WriteXKMFile(FILE *file, XkbFileInfo *result, 1308 int num_toc, xkmSectionInfo *toc, XkmInfo *info) 1309{ 1310 register int i; 1311 unsigned tmp, size, total = 0; 1312 1313 for (i = 0; i < num_toc; i++) { 1314 tmp = fwrite(&toc[i], SIZEOF(xkmSectionInfo), 1, file); 1315 total += tmp * SIZEOF(xkmSectionInfo); 1316 switch (toc[i].type) { 1317 case XkmTypesIndex: 1318 size = WriteXKMKeyTypes(file, result); 1319 break; 1320 case XkmCompatMapIndex: 1321 size = WriteXKMCompatMap(file, result, info); 1322 break; 1323 case XkmSymbolsIndex: 1324 size = WriteXKMSymbols(file, result, info); 1325 break; 1326 case XkmIndicatorsIndex: 1327 size = WriteXKMIndicators(file, result, info); 1328 break; 1329 case XkmKeyNamesIndex: 1330 size = WriteXKMKeycodes(file, result); 1331 break; 1332 case XkmGeometryIndex: 1333 size = WriteXKMGeometry(file, result); 1334 break; 1335 case XkmVirtualModsIndex: 1336 size = WriteXKMVirtualMods(file, result, info); 1337 break; 1338 default: 1339 _XkbLibError(_XkbErrIllegalTOCType, "WriteXKMFile", toc[i].type); 1340 return False; 1341 } 1342 size += SIZEOF(xkmSectionInfo); 1343 if (size != toc[i].size) { 1344 _XkbLibError(_XkbErrBadLength, 1345 XkbConfigText(toc[i].type, XkbMessage), 1346 size - toc[i].size); 1347 return False; 1348 } 1349 } 1350 return True; 1351} 1352 1353 1354#define MAX_TOC 16 1355 1356Bool 1357XkbWriteXKMFile(FILE *out, XkbFileInfo *result) 1358{ 1359 Bool ok; 1360 XkbDescPtr xkb; 1361 XkmInfo info; 1362 int size_toc, i; 1363 unsigned hdr, present; 1364 xkmFileInfo fileInfo; 1365 xkmSectionInfo toc[MAX_TOC]; 1366 1367 int (*getTOC) (XkbFileInfo * /* result */ , 1368 XkmInfo * /* info */ , 1369 int /* max_to */ , 1370 xkmSectionInfo * /* toc_rtrn */ 1371 ); 1372 1373 switch (result->type) { 1374 case XkmKeyNamesIndex: 1375 getTOC = GetXKMKeyNamesTOC; 1376 break; 1377 case XkmTypesIndex: 1378 getTOC = GetXKMTypesTOC; 1379 break; 1380 case XkmCompatMapIndex: 1381 getTOC = GetXKMCompatMapTOC; 1382 break; 1383 case XkmSemanticsFile: 1384 getTOC = GetXKMSemanticsTOC; 1385 break; 1386 case XkmLayoutFile: 1387 getTOC = GetXKMLayoutTOC; 1388 break; 1389 case XkmKeymapFile: 1390 getTOC = GetXKMKeymapTOC; 1391 break; 1392 case XkmGeometryFile: 1393 case XkmGeometryIndex: 1394 getTOC = GetXKMGeometryTOC; 1395 break; 1396 default: 1397 _XkbLibError(_XkbErrIllegalContents, 1398 XkbConfigText(result->type, XkbMessage), 0); 1399 return False; 1400 } 1401 xkb = result->xkb; 1402 1403 bzero((char *) &info, sizeof(XkmInfo)); 1404 size_toc = (*getTOC) (result, &info, MAX_TOC, toc); 1405 if (size_toc < 1) { 1406 _XkbLibError(_XkbErrEmptyFile, "XkbWriteXKMFile", 0); 1407 return False; 1408 } 1409 if (out == NULL) { 1410 _XkbLibError(_XkbErrFileCannotOpen, "XkbWriteXKMFile", 0); 1411 return False; 1412 } 1413 for (i = present = 0; i < size_toc; i++) { 1414 toc[i].offset += 4 + SIZEOF(xkmFileInfo); 1415 toc[i].offset += (size_toc * SIZEOF(xkmSectionInfo)); 1416 if (toc[i].type <= XkmLastIndex) { 1417 present |= (1 << toc[i].type); 1418 } 1419#ifdef DEBUG 1420 else { 1421 fprintf(stderr, "Illegal section type %d\n", toc[i].type); 1422 fprintf(stderr, "Ignored\n"); 1423 } 1424#endif 1425 } 1426 hdr = (('x' << 24) | ('k' << 16) | ('m' << 8) | XkmFileVersion); 1427 xkmPutCARD32(out, (unsigned long) hdr); 1428 fileInfo.type = result->type; 1429 fileInfo.min_kc = xkb->min_key_code; 1430 fileInfo.max_kc = xkb->max_key_code; 1431 fileInfo.num_toc = size_toc; 1432 fileInfo.present = present; 1433 fileInfo.pad = 0; 1434 fwrite(&fileInfo, SIZEOF(xkmFileInfo), 1, out); 1435 fwrite(toc, SIZEOF(xkmSectionInfo), size_toc, out); 1436 ok = WriteXKMFile(out, result, size_toc, toc, &info); 1437 return ok; 1438} 1439