1 /************************************************************
2  Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
3 
4  Permission to use, copy, modify, and distribute this
5  software and its documentation for any purpose and without
6  fee is hereby granted, provided that the above copyright
7  notice appear in all copies and that both that copyright
8  notice and this permission notice appear in supporting
9  documentation, and that the name of Silicon Graphics not be
10  used in advertising or publicity pertaining to distribution
11  of the software without specific prior written permission.
12  Silicon Graphics makes no representation about the suitability
13  of this software for any purpose. It is provided "as is"
14  without any express or implied warranty.
15 
16  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 
25  ********************************************************/
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <X11/Xlocale.h>
34 #include <X11/X.h>
35 #include <X11/Xlib.h>
36 #include <X11/XKBlib.h>
37 #include <X11/extensions/XKBgeom.h>
38 #include <X11/extensions/XKM.h>
39 #include <X11/extensions/XKBfile.h>
40 #include <X11/keysym.h>
41 
42 #if defined(sgi)
43 #include <malloc.h>
44 #endif
45 
46 #include <stdlib.h>
47 
48 #include "utils.h"
49 #include "xkbprint.h"
50 
51 /***====================================================================***/
52 
53 
54 #define	WANT_DEFAULT	0
55 #define	WANT_PS_FILE	1
56 #define	WANT_X_SERVER	2
57 
58 
59 static unsigned         outputFormat = WANT_DEFAULT;
60 static const char *     wantLocale = "C";
61 static char *           rootDir;
62 static char *           inputFile;
63 static char *           outputFile;
64 static char *           outputFont = NULL;
65 static char *           inDpyName;
66 static char *           outDpyName;
67 static Display *        inDpy;
68 static Display *        outDpy;
69 static XKBPrintArgs     args;
70 static unsigned         warningLevel = 5;
71 static Bool             synch;
72 
73 /***====================================================================***/
74 
75 static void
Usage(int argc,char * argv[])76 Usage(int argc, char *argv[])
77 {
78     fprintf(stderr, "Usage: %s [options] input-file [ output-file ]\n%s",
79             argv[0],
80             "Legal options:\n"
81             "-?,-help      Print this message\n"
82             "-color        Use colors from geometry\n"
83 #ifdef DEBUG
84             "-d [flags]    Report debugging information\n"
85 #endif
86             "-dflts        Compute defaults for missing components\n"
87             "-diffs        Only show explicit key definitions\n"
88             "-eps          Generate an EPS file\n"
89             "-fit          Fit keyboard image on page (default)\n"
90             "-full         Print keyboard image full sized\n"
91             "-grid <n>     Print a grid with <n> mm resolution\n"
92             "-if <name>    Specifies the name of an internal font to dump\n"
93 #ifdef DEBUG
94             "-I[<dir>]     Specifies a top level directory\n"
95             "              for include directives.  You can\n"
96             "              specify multiple directories.\n"
97 #endif
98             "-kc           Also print keycodes, if possible\n"
99             "-label <what> Specifies the label to be drawn on keys\n"
100             "              Legal values for <what> are:\n"
101             "                  none,name,code,symbols\n"
102             "-lc <locale>  Use <locale> for fonts and symbols\n"
103             "-level1       Use level 1 PostScript (default)\n"
104             "-level2       Use level 2 PostScript\n"
105             "-lg <num>     Use keyboard group <num> to print labels\n"
106             "-ll <num>     Use shift level <num> to print labels\n"
107             "-mono         Ignore colors from geometry (default)\n"
108             "-n <num>      Print <num> copies (default 1)\n"
109             "-nkg <num>    Number of groups to print on each key\n"
110             "-nokc         Don't print keycodes, even if possible\n"
111             "-npk <num>    Number of keyboards to print on each page\n"
112             "-ntg <num>    Total number of groups to print\n"
113             "-o <file>     Specifies output file name\n"
114             "-R[<DIR>]     Specifies the root directory for relative\n"
115             "              path names\n"
116             "-pict <what>  Specifies use of pictographs instead of\n"
117             "              keysym names where available, <what> can\n"
118             "              be \"all\", \"none\" or \"common\" (default)\n"
119             "-synch        Force synchronization\n"
120             "-version      Print program version\n"
121             "-w <lvl>      Set warning level (0=none, 10=all)\n"
122         );
123 }
124 
125 /***====================================================================***/
126 
127 static Bool
parseArgs(int argc,char * argv[])128 parseArgs(int argc, char *argv[])
129 {
130     register int i;
131 
132     args.copies = 1;
133     args.grid = 0;
134     args.level1 = True;
135     args.scaleToFit = True;
136     args.wantColor = False;
137     args.wantSymbols = COMMON_SYMBOLS;
138     args.wantKeycodes = True;
139     args.wantDiffs = False;
140     args.wantEPS = False;
141     args.label = LABEL_AUTO;
142     args.baseLabelGroup = 0;
143     args.nLabelGroups = 1;
144     args.nTotalGroups = 0;
145     args.nKBPerPage = 0;
146     args.labelLevel = 0;
147     for (i = 1; i < argc; i++) {
148         if ((argv[i][0] != '-') || (uStringEqual(argv[i], "-"))) {
149             if (inputFile == NULL) {
150                 inputFile = argv[i];
151             }
152             else if (outputFile == NULL) {
153                 outputFile = argv[i];
154             }
155             else {
156                 uWarning("Too many file names on command line\n");
157                 uAction("Compiling %s, writing to %s, ignoring %s\n",
158                         inputFile, outputFile, argv[i]);
159             }
160         }
161         else if ((strcmp(argv[i], "-?") == 0) ||
162                  (strcmp(argv[i], "-help") == 0)) {
163             Usage(argc, argv);
164             exit(0);
165         }
166         else if (strcmp(argv[i], "-color") == 0) {
167             args.wantColor = True;
168         }
169 #ifdef DEBUG
170         else if (strcmp(argv[i], "-d") == 0) {
171             if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0]))) {
172                 debugFlags = 1;
173             }
174             else {
175                 sscanf(argv[++i], "%i", &debugFlags);
176             }
177             uInformation("Setting debug flags to %d\n", debugFlags);
178         }
179 #endif
180         else if (strcmp(argv[i], "-dflts") == 0) {
181             uWarning("Compute defaults not implemented yet\n");
182         }
183         else if (strcmp(argv[i], "-diffs") == 0) {
184             args.wantDiffs = True;
185         }
186         else if (strcmp(argv[i], "-eps") == 0) {
187             args.wantEPS = True;
188         }
189         else if (strcmp(argv[i], "-fit") == 0) {
190             args.scaleToFit = True;
191         }
192         else if (strcmp(argv[i], "-full") == 0) {
193             args.scaleToFit = False;
194         }
195         else if (strcmp(argv[i], "-grid") == 0) {
196             int tmp;
197 
198             if (++i >= argc) {
199                 uWarning("Grid frequency not specified\n");
200                 uAction("Trailing \"-grid\" option ignored\n");
201             }
202             else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1)) {
203                 uWarning("Grid frequency must be an integer > zero\n");
204                 uAction("Illegal frequency %d ignored\n", tmp);
205             }
206             else
207                 args.grid = tmp;
208         }
209         else if (strcmp(argv[i], "-if") == 0) {
210             if (++i >= argc) {
211                 uWarning("Internal Font name not specified\n");
212                 uAction("Trailing \"-if\" option ignored\n");
213             }
214             else
215                 outputFont = argv[i];
216         }
217         else if (strcmp(argv[i], "-kc") == 0) {
218             args.wantKeycodes = True;
219         }
220         else if (strcmp(argv[i], "-label") == 0) {
221             if (++i >= argc) {
222                 uWarning("Label type not specified\n");
223                 uAction("Trailing \"-label\" option ignored\n");
224             }
225             else if (uStrCaseEqual(argv[i], "none"))
226                 args.label = LABEL_NONE;
227             else if (uStrCaseEqual(argv[i], "name"))
228                 args.label = LABEL_KEYNAME;
229             else if (uStrCaseEqual(argv[i], "code"))
230                 args.label = LABEL_KEYCODE;
231             else if (uStrCaseEqual(argv[i], "symbols"))
232                 args.label = LABEL_SYMBOLS;
233             else {
234                 uWarning("Unknown label type \"%s\" specified\n", argv[i]);
235                 uAction("Ignored\n");
236             }
237         }
238         else if (strcmp(argv[i], "-lc") == 0) {
239             if (++i >= argc) {
240                 uWarning("Locale not specified\n");
241                 uAction("Trailing \"-lc\" option ignored\n");
242             }
243             else
244                 wantLocale = argv[i];
245         }
246         else if (strcmp(argv[i], "-lg") == 0) {
247             int tmp;
248 
249             if (++i >= argc) {
250                 uWarning("Label group not specified\n");
251                 uAction("Trailing \"-lg\" option ignored\n");
252             }
253             else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
254                      (tmp > 4)) {
255                 uWarning("Label group must be an integer in the range 1..4\n");
256                 uAction("Illegal group %d ignored\n", tmp);
257             }
258             else
259                 args.baseLabelGroup = tmp - 1;
260         }
261         else if (strcmp(argv[i], "-ll") == 0) {
262             int tmp;
263 
264             if (++i >= argc) {
265                 uWarning("Label level not specified\n");
266                 uAction("Trailing \"-ll\" option ignored\n");
267             }
268             else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
269                      (tmp > 255)) {
270                 uWarning("Label level must be in the range 1..255\n");
271                 uAction("Illegal level %d ignored\n", tmp);
272             }
273             else
274                 args.labelLevel = tmp - 1;
275         }
276         else if (strcmp(argv[i], "-level1") == 0)
277             args.level1 = True;
278         else if (strcmp(argv[i], "-level2") == 0)
279             args.level1 = False;
280         else if (strcmp(argv[i], "-mono") == 0) {
281             args.wantColor = False;
282         }
283         else if (strcmp(argv[i], "-n") == 0) {
284             int tmp;
285 
286             if (++i >= argc) {
287                 uWarning("Number of copies not specified\n");
288                 uAction("Trailing \"-n\" option ignored\n");
289             }
290             else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1)) {
291                 uWarning("Number of copies must be an integer > zero\n");
292                 uAction("Illegal count %d ignored\n", tmp);
293             }
294             else
295                 args.copies = tmp;
296         }
297         else if (strcmp(argv[i], "-nokc") == 0) {
298             args.wantKeycodes = False;
299         }
300         else if (strcmp(argv[i], "-nkg") == 0) {
301             int tmp;
302 
303             if (++i >= argc) {
304                 uWarning("Number of groups per key not specified\n");
305                 uAction("Trailing \"-nkg\" option ignored\n");
306             }
307             else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
308                      (tmp > 2)) {
309                 uWarning("Groups per key must be in the range 1..2\n");
310                 uAction("Illegal number of groups %d ignored\n", tmp);
311             }
312             else
313                 args.nLabelGroups = tmp;
314         }
315         else if (strcmp(argv[i], "-npk") == 0) {
316             int tmp;
317 
318             if (++i >= argc) {
319                 uWarning("Number of keyboards per page not specified\n");
320                 uAction("Trailing \"-npk\" option ignored\n");
321             }
322             else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
323                      (tmp > 2)) {
324                 uWarning("Keyboards per page must be in the range 1..2\n");
325                 uAction("Illegal number of keyboards %d ignored\n", tmp);
326             }
327             else
328                 args.nKBPerPage = tmp;
329         }
330         else if (strcmp(argv[i], "-ntg") == 0) {
331             int tmp;
332 
333             if (++i >= argc) {
334                 uWarning("Total number of groups not specified\n");
335                 uAction("Trailing \"-ntg\" option ignored\n");
336             }
337             else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
338                      (tmp > 4)) {
339                 uWarning("Total number of groups must be in the range 1..4\n");
340                 uAction("Illegal number of groups %d ignored\n", tmp);
341             }
342             else
343                 args.nTotalGroups = tmp;
344         }
345         else if (strcmp(argv[i], "-o") == 0) {
346             if (++i >= argc) {
347                 uWarning("No output file specified\n");
348                 uAction("Trailing \"-o\" option ignored\n");
349             }
350             else if (outputFile != NULL) {
351                 uWarning("Multiple output files specified\n");
352                 uAction("Compiling %s, ignoring %s\n", outputFile, argv[i]);
353             }
354             else
355                 outputFile = argv[i];
356         }
357         else if (strncmp(argv[i], "-R", 2) == 0) {
358             if (argv[i][2] == '\0') {
359                 uWarning("No root directory specified\n");
360                 uAction("Ignoring -R option\n");
361             }
362             else if (rootDir != NULL) {
363                 uWarning("Multiple root directories specified\n");
364                 uAction("Using %s, ignoring %s\n", rootDir, argv[i]);
365             }
366             else
367                 rootDir = &argv[i][2];
368         }
369         else if (strcmp(argv[i], "-pict") == 0) {
370             if (++i >= argc) {
371                 uWarning("No level of pictographs specified\n");
372                 uAction("Trailing \"-pict\" option ignored\n");
373             }
374             else if (strcmp(argv[i], "none") == 0)
375                 args.wantSymbols = NO_SYMBOLS;
376             else if (strcmp(argv[i], "common") == 0)
377                 args.wantSymbols = COMMON_SYMBOLS;
378             else if (strcmp(argv[i], "all") == 0)
379                 args.wantSymbols = ALL_SYMBOLS;
380             else if (outputFile != NULL) {
381                 uWarning("Unknown pictograph level specified\n");
382                 uAction("Ignoring illegal value %s\n", argv[i]);
383             }
384         }
385         else if ((strcmp(argv[i], "-synch") == 0) ||
386                  (strcmp(argv[i], "-s") == 0)) {
387             synch = True;
388         }
389         else if (strcmp(argv[i], "-version") == 0) {
390             puts(PACKAGE_STRING);
391             exit(0);
392         }
393         else if (strcmp(argv[i], "-w") == 0) {
394             if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0]))) {
395                 warningLevel = 0;
396             }
397             else {
398                 int itmp;
399 
400                 if (sscanf(argv[++i], "%i", &itmp))
401                     warningLevel = itmp;
402             }
403         }
404         else {
405             uError("Unknown flag \"%s\" on command line\n", argv[i]);
406             Usage(argc, argv);
407             return False;
408         }
409     }
410     if (rootDir) {
411         if (warningLevel > 8) {
412             uWarning("Changing root directory to \"%s\"\n", rootDir);
413         }
414         if ((chdir(rootDir) < 0) && (warningLevel > 0)) {
415             uWarning("Couldn't change root directory to \"%s\"\n", rootDir);
416             uAction("Root directory (-R) option ignored\n");
417         }
418     }
419     if (outputFont != NULL) {
420         Bool ok;
421         FILE *file = NULL;
422 
423         if (outputFile == NULL) {
424             asprintf(&outputFile, "%s.pfa", outputFont);
425         }
426         else if (uStringEqual(outputFile, "-"))
427             file = stdout;
428 
429         if (file == NULL)
430             file = fopen(outputFile, "w");
431 
432         if (!file) {
433             uError("Couldn't open \"%s\" to dump internal font \"%s\"\n",
434                    outputFile, outputFont);
435             uAction("Exiting\n");
436             exit(1);
437         }
438         ok = DumpInternalFont(file, outputFont);
439         if (file != stdout)
440             fclose(file);
441         if (!ok) {
442             uWarning("No internal font to dump\n");
443             if (file != stdout) {
444                 uAction("Removing \"%s\"\n", outputFile);
445                 unlink(outputFile);
446             }
447         }
448         exit((ok != 0));
449     }
450     if (inputFile == NULL) {
451         uError("No input file specified\n");
452         Usage(argc, argv);
453         return False;
454     }
455     else if (uStringEqual(inputFile, "-")) {
456         /* Nothing */
457     }
458     else if (strchr(inputFile, ':') == NULL) {
459         size_t len = strlen(inputFile);
460 
461         if ((len > 4) && (strcmp(&inputFile[len - 4], ".xkm") == 0)) {
462             /* Nothing */
463         }
464         else {
465             FILE *file;
466 
467             file = fopen(inputFile, "r");
468             if (file) {
469                 fclose(file);
470             }
471             else {
472                 fprintf(stderr, "Cannot open \"%s\" for reading\n", inputFile);
473                 return False;
474             }
475         }
476     }
477     else {
478         inDpyName = inputFile;
479         inputFile = NULL;
480     }
481 
482     if (outputFormat == WANT_DEFAULT)
483         outputFormat = WANT_PS_FILE;
484     if ((outputFile == NULL) && (inputFile != NULL) &&
485         uStringEqual(inputFile, "-")) {
486         size_t len;
487 
488         len = strlen("stdin.eps") + 2;
489         outputFile = calloc(len, sizeof(char));
490 
491         if (outputFile == NULL) {
492             uInternalError("Cannot allocate space for output file name\n");
493             uAction("Exiting\n");
494             exit(1);
495         }
496         if (args.wantEPS)
497             snprintf(outputFile, len, "stdin.eps");
498         else
499             snprintf(outputFile, len, "stdin.ps");
500     }
501     else if ((outputFile == NULL) && (inputFile != NULL)) {
502         size_t len;
503         char *base, *ext;
504 
505         base = strrchr(inputFile, '/');
506         if (base == NULL)
507             base = inputFile;
508         else
509             base++;
510 
511         len = strlen(base) + strlen("eps") + 2;
512         outputFile = calloc(len, sizeof(char));
513 
514         if (outputFile == NULL) {
515             uInternalError("Cannot allocate space for output file name\n");
516             uAction("Exiting\n");
517             exit(1);
518         }
519         ext = strrchr(base, '.');
520         if (ext == NULL) {
521             if (args.wantEPS)
522                 snprintf(outputFile, len, "%s.eps", base);
523             else
524                 snprintf(outputFile, len, "%s.ps", base);
525         }
526         else {
527             strcpy(outputFile, base);
528             if (args.wantEPS)
529                 strcpy(&outputFile[ext - base + 1], "eps");
530             else
531                 strcpy(&outputFile[ext - base + 1], "ps");
532         }
533     }
534     else if (outputFile == NULL) {
535         size_t len;
536         char *ch, *name, buf[128];
537 
538         if (inDpyName[0] == ':')
539             snprintf(name = buf, sizeof(buf), "server%s", inDpyName);
540         else
541             name = inDpyName;
542 
543         len = strlen(name) + strlen("eps") + 2;
544         outputFile = calloc(len, sizeof(char));
545 
546         if (outputFile == NULL) {
547             uInternalError("Cannot allocate space for output file name\n");
548             uAction("Exiting\n");
549             exit(1);
550         }
551         strcpy(outputFile, name);
552         for (ch = outputFile; (*ch) != '\0'; ch++) {
553             if (*ch == ':')
554                 *ch = '-';
555             else if (*ch == '.')
556                 *ch = '_';
557         }
558         *ch++ = '.';
559         if (args.wantEPS)
560             strcpy(ch, "eps");
561         else
562             strcpy(ch, "ps");
563     }
564     else if (strchr(outputFile, ':') != NULL) {
565         outDpyName = outputFile;
566         outputFile = NULL;
567         outputFormat = WANT_X_SERVER;
568         uInternalError("Output to an X server not implemented yet\n");
569         return False;
570     }
571     return True;
572 }
573 
574 static Display *
GetDisplay(char * program,char * dpyName)575 GetDisplay(char *program, char *dpyName)
576 {
577     int mjr, mnr, error;
578     Display *dpy;
579 
580     mjr = XkbMajorVersion;
581     mnr = XkbMinorVersion;
582     dpy = XkbOpenDisplay(dpyName, NULL, NULL, &mjr, &mnr, &error);
583     if (dpy == NULL) {
584         switch (error) {
585         case XkbOD_BadLibraryVersion:
586             uInformation("%s was compiled with XKB version %d.%02d\n",
587                          program, XkbMajorVersion, XkbMinorVersion);
588             uError("X library supports incompatible version %d.%02d\n",
589                    mjr, mnr);
590             break;
591         case XkbOD_ConnectionRefused:
592             uError("Cannot open display \"%s\"\n", dpyName);
593             break;
594         case XkbOD_NonXkbServer:
595             uError("XKB extension not present on %s\n", dpyName);
596             break;
597         case XkbOD_BadServerVersion:
598             uInformation("%s was compiled with XKB version %d.%02d\n",
599                          program, XkbMajorVersion, XkbMinorVersion);
600             uError("Server %s uses incompatible version %d.%02d\n",
601                    dpyName, mjr, mnr);
602             break;
603         default:
604             uInternalError("Unknown error %d from XkbOpenDisplay\n", error);
605         }
606     }
607     else if (synch)
608         XSynchronize(dpy, True);
609     return dpy;
610 }
611 
612 /***====================================================================***/
613 
614 
615 int
main(int argc,char * argv[])616 main(int argc, char *argv[])
617 {
618     FILE *file;
619     int ok;
620     XkbFileInfo result;
621 
622     uSetErrorFile(NullString);
623     if (!parseArgs(argc, argv))
624         exit(1);
625 #ifdef DEBUG
626 #ifdef sgi
627     if (debugFlags & 0x4)
628         mallopt(M_DEBUG, 1);
629 #endif
630 #endif
631     file = NULL;
632     XkbInitAtoms(NULL);
633 /*     XkbInitIncludePath(); */
634     if (inputFile != NULL) {
635         if (uStringEqual(inputFile, "-")) {
636             static char in[] = "stdin";
637 
638             file = stdin;
639             inputFile = in;
640         }
641         else {
642             file = fopen(inputFile, "r");
643         }
644     }
645     else if (inDpyName != NULL) {
646         inDpy = GetDisplay(argv[0], inDpyName);
647         if (!inDpy) {
648             uAction("Exiting\n");
649             exit(1);
650         }
651     }
652     if (outDpyName != NULL) {
653         uInternalError("Output to an X server not implemented yet\n");
654         outDpy = GetDisplay(argv[0], outDpyName);
655         if (!outDpy) {
656             uAction("Exiting\n");
657             exit(1);
658         }
659     }
660     if ((inDpy == NULL) && (outDpy == NULL)) {
661         int mjr, mnr;
662 
663         mjr = XkbMajorVersion;
664         mnr = XkbMinorVersion;
665         if (!XkbLibraryVersion(&mjr, &mnr)) {
666             uInformation("%s was compiled with XKB version %d.%02d\n",
667                          argv[0], XkbMajorVersion, XkbMinorVersion);
668             uError("X library supports incompatible version %d.%02d\n",
669                    mjr, mnr);
670             uAction("Exiting\n");
671             exit(1);
672         }
673     }
674     ok = True;
675     if (file) {
676         unsigned tmp;
677 
678         bzero((char *) &result, sizeof(result));
679         if ((result.xkb = XkbAllocKeyboard()) == NULL) {
680             uFatalError("Cannot allocate keyboard description\n");
681             /* NOTREACHED */
682         }
683         tmp = XkmReadFile(file, XkmGeometryMask, XkmKeymapLegal, &result);
684         if ((tmp & XkmGeometryMask) != 0) {
685             uError("Couldn't read geometry from XKM file \"%s\"\n", inputFile);
686             uAction("Exiting\n");
687             ok = False;
688         }
689         if ((tmp & XkmKeyNamesMask) != 0)
690             args.wantKeycodes = False;
691         if (args.label == LABEL_AUTO) {
692             if (result.defined & XkmSymbolsMask)
693                 args.label = LABEL_SYMBOLS;
694             else if (result.defined & XkmKeyNamesMask)
695                 args.label = LABEL_KEYCODE;
696             else
697                 args.label = LABEL_KEYNAME;
698         }
699         else if ((args.label == LABEL_KEYCODE) &&
700                  ((tmp & XkmKeyNamesMask) != 0)) {
701             uError("XKM file \"%s\" doesn't have keycodes\n", inputFile);
702             uAction("Cannot label keys as requested. Exiting\n");
703             ok = False;
704         }
705         else if ((args.label == LABEL_SYMBOLS) && ((tmp & XkmSymbolsMask) != 0)) {
706             uError("XKM file \"%s\" doesn't have symbols\n", inputFile);
707             uAction("Cannot label keys as requested. Exiting\n");
708             ok = False;
709         }
710     }
711     else if (inDpy != NULL) {
712         bzero((char *) &result, sizeof(result));
713         result.type = XkmKeymapFile;
714         result.xkb = XkbGetMap(inDpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
715         if (result.xkb == NULL)
716             uWarning("Cannot load keyboard description\n");
717         if (XkbGetNames(inDpy, XkbAllNamesMask, result.xkb) != Success)
718             uWarning("Cannot load names\n");
719         if (XkbGetGeometry(inDpy, result.xkb) != Success) {
720             uFatalError("Cannot load geometry for %s\n", inDpyName);
721         }
722         if (args.label == LABEL_AUTO)
723             args.label = LABEL_SYMBOLS;
724     }
725     else {
726         fprintf(stderr, "Cannot open \"%s\" to read geometry\n", inputFile);
727         ok = 0;
728     }
729     if (ok) {
730         FILE *out = NULL;
731 
732         if (setlocale(LC_ALL, (wantLocale)) == NULL) {
733             if (wantLocale != NULL) {
734                 uWarning("Couldn't change to locale %s\n", wantLocale);
735                 uAction("Using \"C\" locale, instead\n");
736             }
737         }
738         /* need C numerics so decimal point doesn't get screwed up */
739         setlocale(LC_NUMERIC, "C");
740         if ((inDpy != outDpy) &&
741             (XkbChangeKbdDisplay(outDpy, &result) != Success)) {
742             uInternalError("Error converting keyboard display from %s to %s\n",
743                            inDpyName, outDpyName);
744             exit(1);
745         }
746         if (outputFile != NULL) {
747             if (uStringEqual(outputFile, "-")) {
748                 static char of[] = "stdout";
749 
750                 out = stdout;
751                 outputFile = of;
752             }
753             else {
754                 out = fopen(outputFile, "w");
755                 if (out == NULL) {
756                     uError("Cannot open \"%s\" to write keyboard description\n",
757                            outputFile);
758                     uAction("Exiting\n");
759                     exit(1);
760                 }
761             }
762         }
763         switch (outputFormat) {
764         case WANT_PS_FILE:
765             ok = GeometryToPostScript(out, &result, &args);
766             break;
767         case WANT_X_SERVER:
768             uInternalError("Output to X server not implemented yet\n");
769             break;
770         default:
771             uInternalError("Unknown output format %d\n", outputFormat);
772             uAction("No output file created\n");
773             ok = False;
774             break;
775         }
776         if (!ok) {
777             uError("Error creating output file\n");
778         }
779     }
780     if (inDpy)
781         XCloseDisplay(inDpy);
782     inDpy = NULL;
783     if (outDpy)
784         XCloseDisplay(outDpy);
785     return (ok == 0);
786 }
787