xkbprint.c revision 2f167a42
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
59static unsigned         outputFormat = WANT_DEFAULT;
60static const char *     wantLocale = "C";
61static char *           rootDir;
62static char *           inputFile;
63static char *           outputFile;
64static char *           outputFont = NULL;
65static char *           inDpyName;
66static char *           outDpyName;
67static Display *        inDpy;
68static Display *        outDpy;
69static XKBPrintArgs     args;
70static unsigned         warningLevel = 5;
71static Bool             synch;
72
73/***====================================================================***/
74
75static void
76Usage(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
127static Bool
128parseArgs(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
574static Display *
575GetDisplay(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
615int
616main(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