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
51 static Bool
WriteXKBVModDecl(FILE * file,Display * dpy,XkbDescPtr xkb,int showValue)52 WriteXKBVModDecl(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
92 static Bool
WriteXKBAction(FILE * file,XkbFileInfo * result,XkbAnyAction * action)93 WriteXKBAction(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
107 Bool
XkbWriteXKBKeycodes(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)108 XkbWriteXKBKeycodes(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
176 Bool
XkbWriteXKBKeyTypes(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)177 XkbWriteXKBKeyTypes(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
251 static Bool
WriteXKBIndicatorMap(FILE * file,XkbFileInfo * result,Atom name,XkbIndicatorMapPtr led,XkbFileAddOnFunc addOn,void * priv)252 WriteXKBIndicatorMap(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
297 Bool
XkbWriteXKBCompatMap(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)298 XkbWriteXKBCompatMap(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
380 Bool
XkbWriteXKBSymbols(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)381 XkbWriteXKBSymbols(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
595 static Bool
WriteXKBOutline(FILE * file,XkbShapePtr shape,XkbOutlinePtr outline,int lastRadius,int first,int indent)596 WriteXKBOutline(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
638 static Bool
WriteXKBDoodad(FILE * file,Display * dpy,unsigned indent,XkbGeometryPtr geom,XkbDoodadPtr doodad)639 WriteXKBDoodad(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*/
730 static Bool
WriteXKBOverlay(FILE * file,Display * dpy,unsigned indent,XkbGeometryPtr geom,XkbOverlayPtr ol)731 WriteXKBOverlay(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
768 static Bool
WriteXKBSection(FILE * file,Display * dpy,XkbSectionPtr s,XkbGeometryPtr geom)769 WriteXKBSection(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
865 Bool
XkbWriteXKBGeometry(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)866 XkbWriteXKBGeometry(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*/
985 Bool
XkbWriteXKBSemantics(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)986 XkbWriteXKBSemantics(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*/
1003 Bool
XkbWriteXKBLayout(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)1004 XkbWriteXKBLayout(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*/
1029 Bool
XkbWriteXKBKeymap(FILE * file,XkbFileInfo * result,Bool topLevel,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)1030 XkbWriteXKBKeymap(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
1056 Bool
XkbWriteXKBFile(FILE * out,XkbFileInfo * result,Bool showImplicit,XkbFileAddOnFunc addOn,void * priv)1057 XkbWriteXKBFile(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