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