10e20ee16Smrg/************************************************************
20e20ee16Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
30e20ee16Smrg
40e20ee16Smrg Permission to use, copy, modify, and distribute this
50e20ee16Smrg software and its documentation for any purpose and without
60e20ee16Smrg fee is hereby granted, provided that the above copyright
70e20ee16Smrg notice appear in all copies and that both that copyright
80e20ee16Smrg notice and this permission notice appear in supporting
92f167a42Smrg documentation, and that the name of Silicon Graphics not be
102f167a42Smrg used in advertising or publicity pertaining to distribution
110e20ee16Smrg of the software without specific prior written permission.
122f167a42Smrg Silicon Graphics makes no representation about the suitability
130e20ee16Smrg of this software for any purpose. It is provided "as is"
140e20ee16Smrg without any express or implied warranty.
152f167a42Smrg
162f167a42Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
172f167a42Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
180e20ee16Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
192f167a42Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
202f167a42Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
212f167a42Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
220e20ee16Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
230e20ee16Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
240e20ee16Smrg
250e20ee16Smrg ********************************************************/
262f167a42Smrg
272f167a42Smrg#ifdef HAVE_CONFIG_H
282f167a42Smrg#include "config.h"
292f167a42Smrg#endif
300e20ee16Smrg
310e20ee16Smrg#include <stdio.h>
320e20ee16Smrg#include <ctype.h>
330e20ee16Smrg#include <X11/Xlocale.h>
340e20ee16Smrg#include <X11/X.h>
350e20ee16Smrg#include <X11/Xlib.h>
360e20ee16Smrg#include <X11/XKBlib.h>
370e20ee16Smrg#include <X11/extensions/XKBgeom.h>
380e20ee16Smrg#include <X11/extensions/XKM.h>
390e20ee16Smrg#include <X11/extensions/XKBfile.h>
400e20ee16Smrg#include <X11/keysym.h>
410e20ee16Smrg
420e20ee16Smrg
430e20ee16Smrg#include <stdlib.h>
440e20ee16Smrg
450e20ee16Smrg#include "utils.h"
460e20ee16Smrg#include "xkbprint.h"
470e20ee16Smrg
480e20ee16Smrg/***====================================================================***/
490e20ee16Smrg
500e20ee16Smrg
510e20ee16Smrg#define	WANT_DEFAULT	0
520e20ee16Smrg#define	WANT_PS_FILE	1
530e20ee16Smrg#define	WANT_X_SERVER	2
540e20ee16Smrg
550e20ee16Smrg
562f167a42Smrgstatic unsigned         outputFormat = WANT_DEFAULT;
572f167a42Smrgstatic const char *     wantLocale = "C";
582f167a42Smrgstatic char *           rootDir;
592f167a42Smrgstatic char *           inputFile;
602f167a42Smrgstatic char *           outputFile;
612f167a42Smrgstatic char *           outputFont = NULL;
622f167a42Smrgstatic char *           inDpyName;
632f167a42Smrgstatic char *           outDpyName;
642f167a42Smrgstatic Display *        inDpy;
652f167a42Smrgstatic Display *        outDpy;
662f167a42Smrgstatic XKBPrintArgs     args;
672f167a42Smrgstatic unsigned         warningLevel = 5;
682f167a42Smrgstatic Bool             synch;
690e20ee16Smrg
700e20ee16Smrg/***====================================================================***/
710e20ee16Smrg
720e20ee16Smrgstatic void
730e20ee16SmrgUsage(int argc, char *argv[])
740e20ee16Smrg{
752f167a42Smrg    fprintf(stderr, "Usage: %s [options] input-file [ output-file ]\n%s",
762f167a42Smrg            argv[0],
772f167a42Smrg            "Legal options:\n"
782f167a42Smrg            "-?,-help      Print this message\n"
792f167a42Smrg            "-color        Use colors from geometry\n"
800e20ee16Smrg#ifdef DEBUG
812f167a42Smrg            "-d [flags]    Report debugging information\n"
820e20ee16Smrg#endif
832f167a42Smrg            "-dflts        Compute defaults for missing components\n"
842f167a42Smrg            "-diffs        Only show explicit key definitions\n"
852f167a42Smrg            "-eps          Generate an EPS file\n"
862f167a42Smrg            "-fit          Fit keyboard image on page (default)\n"
872f167a42Smrg            "-full         Print keyboard image full sized\n"
882f167a42Smrg            "-grid <n>     Print a grid with <n> mm resolution\n"
892f167a42Smrg            "-if <name>    Specifies the name of an internal font to dump\n"
900e20ee16Smrg#ifdef DEBUG
912f167a42Smrg            "-I[<dir>]     Specifies a top level directory\n"
922f167a42Smrg            "              for include directives.  You can\n"
932f167a42Smrg            "              specify multiple directories.\n"
940e20ee16Smrg#endif
952f167a42Smrg            "-kc           Also print keycodes, if possible\n"
962f167a42Smrg            "-label <what> Specifies the label to be drawn on keys\n"
972f167a42Smrg            "              Legal values for <what> are:\n"
982f167a42Smrg            "                  none,name,code,symbols\n"
992f167a42Smrg            "-lc <locale>  Use <locale> for fonts and symbols\n"
1002f167a42Smrg            "-level1       Use level 1 PostScript (default)\n"
1012f167a42Smrg            "-level2       Use level 2 PostScript\n"
1022f167a42Smrg            "-lg <num>     Use keyboard group <num> to print labels\n"
1032f167a42Smrg            "-ll <num>     Use shift level <num> to print labels\n"
1042f167a42Smrg            "-mono         Ignore colors from geometry (default)\n"
1052f167a42Smrg            "-n <num>      Print <num> copies (default 1)\n"
1062f167a42Smrg            "-nkg <num>    Number of groups to print on each key\n"
1072f167a42Smrg            "-nokc         Don't print keycodes, even if possible\n"
1082f167a42Smrg            "-npk <num>    Number of keyboards to print on each page\n"
1092f167a42Smrg            "-ntg <num>    Total number of groups to print\n"
1102f167a42Smrg            "-o <file>     Specifies output file name\n"
1112f167a42Smrg            "-R[<DIR>]     Specifies the root directory for relative\n"
1122f167a42Smrg            "              path names\n"
1132f167a42Smrg            "-pict <what>  Specifies use of pictographs instead of\n"
1142f167a42Smrg            "              keysym names where available, <what> can\n"
1152f167a42Smrg            "              be \"all\", \"none\" or \"common\" (default)\n"
1162f167a42Smrg            "-synch        Force synchronization\n"
1172f167a42Smrg            "-version      Print program version\n"
1182f167a42Smrg            "-w <lvl>      Set warning level (0=none, 10=all)\n"
1192f167a42Smrg        );
1200e20ee16Smrg}
1210e20ee16Smrg
1220e20ee16Smrg/***====================================================================***/
1230e20ee16Smrg
1240e20ee16Smrgstatic Bool
1250e20ee16SmrgparseArgs(int argc, char *argv[])
1260e20ee16Smrg{
1278b648e79Smrg    args = (XKBPrintArgs) {
1288b648e79Smrg        .copies = 1,
1298b648e79Smrg        .grid = 0,
1308b648e79Smrg        .level1 = True,
1318b648e79Smrg        .scaleToFit = True,
1328b648e79Smrg        .wantColor = False,
1338b648e79Smrg        .wantSymbols = COMMON_SYMBOLS,
1348b648e79Smrg        .wantKeycodes = True,
1358b648e79Smrg        .wantDiffs = False,
1368b648e79Smrg        .wantEPS = False,
1378b648e79Smrg        .label = LABEL_AUTO,
1388b648e79Smrg        .baseLabelGroup = 0,
1398b648e79Smrg        .nLabelGroups = 1,
1408b648e79Smrg        .nTotalGroups = 0,
1418b648e79Smrg        .nKBPerPage = 0,
1428b648e79Smrg        .labelLevel = 0
1438b648e79Smrg    };
1448b648e79Smrg    for (int i = 1; i < argc; i++) {
1452f167a42Smrg        if ((argv[i][0] != '-') || (uStringEqual(argv[i], "-"))) {
1462f167a42Smrg            if (inputFile == NULL) {
1472f167a42Smrg                inputFile = argv[i];
1482f167a42Smrg            }
1492f167a42Smrg            else if (outputFile == NULL) {
1502f167a42Smrg                outputFile = argv[i];
1512f167a42Smrg            }
1522f167a42Smrg            else {
1532f167a42Smrg                uWarning("Too many file names on command line\n");
1542f167a42Smrg                uAction("Compiling %s, writing to %s, ignoring %s\n",
1552f167a42Smrg                        inputFile, outputFile, argv[i]);
1562f167a42Smrg            }
1572f167a42Smrg        }
1582f167a42Smrg        else if ((strcmp(argv[i], "-?") == 0) ||
1592f167a42Smrg                 (strcmp(argv[i], "-help") == 0)) {
1602f167a42Smrg            Usage(argc, argv);
1612f167a42Smrg            exit(0);
1622f167a42Smrg        }
1632f167a42Smrg        else if (strcmp(argv[i], "-color") == 0) {
1642f167a42Smrg            args.wantColor = True;
1652f167a42Smrg        }
1660e20ee16Smrg#ifdef DEBUG
1672f167a42Smrg        else if (strcmp(argv[i], "-d") == 0) {
1682f167a42Smrg            if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0]))) {
1692f167a42Smrg                debugFlags = 1;
1702f167a42Smrg            }
1712f167a42Smrg            else {
1722f167a42Smrg                sscanf(argv[++i], "%i", &debugFlags);
1732f167a42Smrg            }
1742f167a42Smrg            uInformation("Setting debug flags to %d\n", debugFlags);
1752f167a42Smrg        }
1760e20ee16Smrg#endif
1772f167a42Smrg        else if (strcmp(argv[i], "-dflts") == 0) {
1782f167a42Smrg            uWarning("Compute defaults not implemented yet\n");
1792f167a42Smrg        }
1802f167a42Smrg        else if (strcmp(argv[i], "-diffs") == 0) {
1812f167a42Smrg            args.wantDiffs = True;
1822f167a42Smrg        }
1832f167a42Smrg        else if (strcmp(argv[i], "-eps") == 0) {
1842f167a42Smrg            args.wantEPS = True;
1852f167a42Smrg        }
1862f167a42Smrg        else if (strcmp(argv[i], "-fit") == 0) {
1872f167a42Smrg            args.scaleToFit = True;
1882f167a42Smrg        }
1892f167a42Smrg        else if (strcmp(argv[i], "-full") == 0) {
1902f167a42Smrg            args.scaleToFit = False;
1912f167a42Smrg        }
1922f167a42Smrg        else if (strcmp(argv[i], "-grid") == 0) {
1932f167a42Smrg            int tmp;
1942f167a42Smrg
1952f167a42Smrg            if (++i >= argc) {
1962f167a42Smrg                uWarning("Grid frequency not specified\n");
1972f167a42Smrg                uAction("Trailing \"-grid\" option ignored\n");
1982f167a42Smrg            }
1992f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1)) {
2002f167a42Smrg                uWarning("Grid frequency must be an integer > zero\n");
2012f167a42Smrg                uAction("Illegal frequency %d ignored\n", tmp);
2022f167a42Smrg            }
2032f167a42Smrg            else
2042f167a42Smrg                args.grid = tmp;
2052f167a42Smrg        }
2062f167a42Smrg        else if (strcmp(argv[i], "-if") == 0) {
2072f167a42Smrg            if (++i >= argc) {
2082f167a42Smrg                uWarning("Internal Font name not specified\n");
2092f167a42Smrg                uAction("Trailing \"-if\" option ignored\n");
2102f167a42Smrg            }
2112f167a42Smrg            else
2122f167a42Smrg                outputFont = argv[i];
2132f167a42Smrg        }
2142f167a42Smrg        else if (strcmp(argv[i], "-kc") == 0) {
2152f167a42Smrg            args.wantKeycodes = True;
2162f167a42Smrg        }
2172f167a42Smrg        else if (strcmp(argv[i], "-label") == 0) {
2182f167a42Smrg            if (++i >= argc) {
2192f167a42Smrg                uWarning("Label type not specified\n");
2202f167a42Smrg                uAction("Trailing \"-label\" option ignored\n");
2212f167a42Smrg            }
2222f167a42Smrg            else if (uStrCaseEqual(argv[i], "none"))
2232f167a42Smrg                args.label = LABEL_NONE;
2242f167a42Smrg            else if (uStrCaseEqual(argv[i], "name"))
2252f167a42Smrg                args.label = LABEL_KEYNAME;
2262f167a42Smrg            else if (uStrCaseEqual(argv[i], "code"))
2272f167a42Smrg                args.label = LABEL_KEYCODE;
2282f167a42Smrg            else if (uStrCaseEqual(argv[i], "symbols"))
2292f167a42Smrg                args.label = LABEL_SYMBOLS;
2302f167a42Smrg            else {
2312f167a42Smrg                uWarning("Unknown label type \"%s\" specified\n", argv[i]);
2322f167a42Smrg                uAction("Ignored\n");
2332f167a42Smrg            }
2342f167a42Smrg        }
2352f167a42Smrg        else if (strcmp(argv[i], "-lc") == 0) {
2362f167a42Smrg            if (++i >= argc) {
2372f167a42Smrg                uWarning("Locale not specified\n");
2382f167a42Smrg                uAction("Trailing \"-lc\" option ignored\n");
2392f167a42Smrg            }
2402f167a42Smrg            else
2412f167a42Smrg                wantLocale = argv[i];
2422f167a42Smrg        }
2432f167a42Smrg        else if (strcmp(argv[i], "-lg") == 0) {
2442f167a42Smrg            int tmp;
2452f167a42Smrg
2462f167a42Smrg            if (++i >= argc) {
2472f167a42Smrg                uWarning("Label group not specified\n");
2482f167a42Smrg                uAction("Trailing \"-lg\" option ignored\n");
2492f167a42Smrg            }
2502f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
2512f167a42Smrg                     (tmp > 4)) {
2522f167a42Smrg                uWarning("Label group must be an integer in the range 1..4\n");
2532f167a42Smrg                uAction("Illegal group %d ignored\n", tmp);
2542f167a42Smrg            }
2552f167a42Smrg            else
2562f167a42Smrg                args.baseLabelGroup = tmp - 1;
2572f167a42Smrg        }
2582f167a42Smrg        else if (strcmp(argv[i], "-ll") == 0) {
2592f167a42Smrg            int tmp;
2602f167a42Smrg
2612f167a42Smrg            if (++i >= argc) {
2622f167a42Smrg                uWarning("Label level not specified\n");
2632f167a42Smrg                uAction("Trailing \"-ll\" option ignored\n");
2642f167a42Smrg            }
2652f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
2662f167a42Smrg                     (tmp > 255)) {
2672f167a42Smrg                uWarning("Label level must be in the range 1..255\n");
2682f167a42Smrg                uAction("Illegal level %d ignored\n", tmp);
2692f167a42Smrg            }
2702f167a42Smrg            else
2712f167a42Smrg                args.labelLevel = tmp - 1;
2722f167a42Smrg        }
2732f167a42Smrg        else if (strcmp(argv[i], "-level1") == 0)
2742f167a42Smrg            args.level1 = True;
2752f167a42Smrg        else if (strcmp(argv[i], "-level2") == 0)
2762f167a42Smrg            args.level1 = False;
2772f167a42Smrg        else if (strcmp(argv[i], "-mono") == 0) {
2782f167a42Smrg            args.wantColor = False;
2792f167a42Smrg        }
2802f167a42Smrg        else if (strcmp(argv[i], "-n") == 0) {
2812f167a42Smrg            int tmp;
2822f167a42Smrg
2832f167a42Smrg            if (++i >= argc) {
2842f167a42Smrg                uWarning("Number of copies not specified\n");
2852f167a42Smrg                uAction("Trailing \"-n\" option ignored\n");
2862f167a42Smrg            }
2872f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1)) {
2882f167a42Smrg                uWarning("Number of copies must be an integer > zero\n");
2892f167a42Smrg                uAction("Illegal count %d ignored\n", tmp);
2902f167a42Smrg            }
2912f167a42Smrg            else
2922f167a42Smrg                args.copies = tmp;
2932f167a42Smrg        }
2942f167a42Smrg        else if (strcmp(argv[i], "-nokc") == 0) {
2952f167a42Smrg            args.wantKeycodes = False;
2962f167a42Smrg        }
2972f167a42Smrg        else if (strcmp(argv[i], "-nkg") == 0) {
2982f167a42Smrg            int tmp;
2992f167a42Smrg
3002f167a42Smrg            if (++i >= argc) {
3012f167a42Smrg                uWarning("Number of groups per key not specified\n");
3022f167a42Smrg                uAction("Trailing \"-nkg\" option ignored\n");
3032f167a42Smrg            }
3042f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
3052f167a42Smrg                     (tmp > 2)) {
3062f167a42Smrg                uWarning("Groups per key must be in the range 1..2\n");
3072f167a42Smrg                uAction("Illegal number of groups %d ignored\n", tmp);
3082f167a42Smrg            }
3092f167a42Smrg            else
3102f167a42Smrg                args.nLabelGroups = tmp;
3112f167a42Smrg        }
3122f167a42Smrg        else if (strcmp(argv[i], "-npk") == 0) {
3132f167a42Smrg            int tmp;
3142f167a42Smrg
3152f167a42Smrg            if (++i >= argc) {
3162f167a42Smrg                uWarning("Number of keyboards per page not specified\n");
3172f167a42Smrg                uAction("Trailing \"-npk\" option ignored\n");
3182f167a42Smrg            }
3192f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
3202f167a42Smrg                     (tmp > 2)) {
3212f167a42Smrg                uWarning("Keyboards per page must be in the range 1..2\n");
3222f167a42Smrg                uAction("Illegal number of keyboards %d ignored\n", tmp);
3232f167a42Smrg            }
3242f167a42Smrg            else
3252f167a42Smrg                args.nKBPerPage = tmp;
3262f167a42Smrg        }
3272f167a42Smrg        else if (strcmp(argv[i], "-ntg") == 0) {
3282f167a42Smrg            int tmp;
3292f167a42Smrg
3302f167a42Smrg            if (++i >= argc) {
3312f167a42Smrg                uWarning("Total number of groups not specified\n");
3322f167a42Smrg                uAction("Trailing \"-ntg\" option ignored\n");
3332f167a42Smrg            }
3342f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
3352f167a42Smrg                     (tmp > 4)) {
3362f167a42Smrg                uWarning("Total number of groups must be in the range 1..4\n");
3372f167a42Smrg                uAction("Illegal number of groups %d ignored\n", tmp);
3382f167a42Smrg            }
3392f167a42Smrg            else
3402f167a42Smrg                args.nTotalGroups = tmp;
3412f167a42Smrg        }
3422f167a42Smrg        else if (strcmp(argv[i], "-o") == 0) {
3432f167a42Smrg            if (++i >= argc) {
3442f167a42Smrg                uWarning("No output file specified\n");
3452f167a42Smrg                uAction("Trailing \"-o\" option ignored\n");
3462f167a42Smrg            }
3472f167a42Smrg            else if (outputFile != NULL) {
3482f167a42Smrg                uWarning("Multiple output files specified\n");
3492f167a42Smrg                uAction("Compiling %s, ignoring %s\n", outputFile, argv[i]);
3502f167a42Smrg            }
3512f167a42Smrg            else
3522f167a42Smrg                outputFile = argv[i];
3532f167a42Smrg        }
3542f167a42Smrg        else if (strncmp(argv[i], "-R", 2) == 0) {
3552f167a42Smrg            if (argv[i][2] == '\0') {
3562f167a42Smrg                uWarning("No root directory specified\n");
3572f167a42Smrg                uAction("Ignoring -R option\n");
3582f167a42Smrg            }
3592f167a42Smrg            else if (rootDir != NULL) {
3602f167a42Smrg                uWarning("Multiple root directories specified\n");
3612f167a42Smrg                uAction("Using %s, ignoring %s\n", rootDir, argv[i]);
3622f167a42Smrg            }
3632f167a42Smrg            else
3642f167a42Smrg                rootDir = &argv[i][2];
3652f167a42Smrg        }
3662f167a42Smrg        else if (strcmp(argv[i], "-pict") == 0) {
3672f167a42Smrg            if (++i >= argc) {
3682f167a42Smrg                uWarning("No level of pictographs specified\n");
3692f167a42Smrg                uAction("Trailing \"-pict\" option ignored\n");
3702f167a42Smrg            }
3712f167a42Smrg            else if (strcmp(argv[i], "none") == 0)
3722f167a42Smrg                args.wantSymbols = NO_SYMBOLS;
3732f167a42Smrg            else if (strcmp(argv[i], "common") == 0)
3742f167a42Smrg                args.wantSymbols = COMMON_SYMBOLS;
3752f167a42Smrg            else if (strcmp(argv[i], "all") == 0)
3762f167a42Smrg                args.wantSymbols = ALL_SYMBOLS;
3772f167a42Smrg            else if (outputFile != NULL) {
3782f167a42Smrg                uWarning("Unknown pictograph level specified\n");
3792f167a42Smrg                uAction("Ignoring illegal value %s\n", argv[i]);
3802f167a42Smrg            }
3812f167a42Smrg        }
3822f167a42Smrg        else if ((strcmp(argv[i], "-synch") == 0) ||
3832f167a42Smrg                 (strcmp(argv[i], "-s") == 0)) {
3842f167a42Smrg            synch = True;
3852f167a42Smrg        }
3862f167a42Smrg        else if (strcmp(argv[i], "-version") == 0) {
3872f167a42Smrg            puts(PACKAGE_STRING);
3882f167a42Smrg            exit(0);
3892f167a42Smrg        }
3902f167a42Smrg        else if (strcmp(argv[i], "-w") == 0) {
3912f167a42Smrg            if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0]))) {
3922f167a42Smrg                warningLevel = 0;
3932f167a42Smrg            }
3942f167a42Smrg            else {
3952f167a42Smrg                int itmp;
3962f167a42Smrg
3972f167a42Smrg                if (sscanf(argv[++i], "%i", &itmp))
3982f167a42Smrg                    warningLevel = itmp;
3992f167a42Smrg            }
4002f167a42Smrg        }
4012f167a42Smrg        else {
4022f167a42Smrg            uError("Unknown flag \"%s\" on command line\n", argv[i]);
4032f167a42Smrg            Usage(argc, argv);
4042f167a42Smrg            return False;
4052f167a42Smrg        }
4060e20ee16Smrg    }
4070e20ee16Smrg    if (rootDir) {
4082f167a42Smrg        if (warningLevel > 8) {
4092f167a42Smrg            uWarning("Changing root directory to \"%s\"\n", rootDir);
4102f167a42Smrg        }
4112f167a42Smrg        if ((chdir(rootDir) < 0) && (warningLevel > 0)) {
4122f167a42Smrg            uWarning("Couldn't change root directory to \"%s\"\n", rootDir);
4132f167a42Smrg            uAction("Root directory (-R) option ignored\n");
4142f167a42Smrg        }
4150e20ee16Smrg    }
4162f167a42Smrg    if (outputFont != NULL) {
4172f167a42Smrg        Bool ok;
4182f167a42Smrg        FILE *file = NULL;
4192f167a42Smrg
4202f167a42Smrg        if (outputFile == NULL) {
4212f167a42Smrg            asprintf(&outputFile, "%s.pfa", outputFont);
4222f167a42Smrg        }
4232f167a42Smrg        else if (uStringEqual(outputFile, "-"))
4242f167a42Smrg            file = stdout;
4252f167a42Smrg
4262f167a42Smrg        if (file == NULL)
4272f167a42Smrg            file = fopen(outputFile, "w");
4282f167a42Smrg
4292f167a42Smrg        if (!file) {
4302f167a42Smrg            uError("Couldn't open \"%s\" to dump internal font \"%s\"\n",
4312f167a42Smrg                   outputFile, outputFont);
4322f167a42Smrg            uAction("Exiting\n");
4332f167a42Smrg            exit(1);
4342f167a42Smrg        }
4352f167a42Smrg        ok = DumpInternalFont(file, outputFont);
4362f167a42Smrg        if (file != stdout)
4372f167a42Smrg            fclose(file);
4382f167a42Smrg        if (!ok) {
4392f167a42Smrg            uWarning("No internal font to dump\n");
4402f167a42Smrg            if (file != stdout) {
4412f167a42Smrg                uAction("Removing \"%s\"\n", outputFile);
4422f167a42Smrg                unlink(outputFile);
4432f167a42Smrg            }
4442f167a42Smrg        }
4452f167a42Smrg        exit((ok != 0));
4460e20ee16Smrg    }
4472f167a42Smrg    if (inputFile == NULL) {
4482f167a42Smrg        uError("No input file specified\n");
4492f167a42Smrg        Usage(argc, argv);
4502f167a42Smrg        return False;
4510e20ee16Smrg    }
4522f167a42Smrg    else if (uStringEqual(inputFile, "-")) {
4532f167a42Smrg        /* Nothing */
4540e20ee16Smrg    }
4552f167a42Smrg    else if (strchr(inputFile, ':') == NULL) {
4562f167a42Smrg        size_t len = strlen(inputFile);
4572f167a42Smrg
4582f167a42Smrg        if ((len > 4) && (strcmp(&inputFile[len - 4], ".xkm") == 0)) {
4592f167a42Smrg            /* Nothing */
4602f167a42Smrg        }
4612f167a42Smrg        else {
4622f167a42Smrg            FILE *file;
4632f167a42Smrg
4642f167a42Smrg            file = fopen(inputFile, "r");
4652f167a42Smrg            if (file) {
4662f167a42Smrg                fclose(file);
4672f167a42Smrg            }
4682f167a42Smrg            else {
4692f167a42Smrg                fprintf(stderr, "Cannot open \"%s\" for reading\n", inputFile);
4702f167a42Smrg                return False;
4712f167a42Smrg            }
4722f167a42Smrg        }
4730e20ee16Smrg    }
4740e20ee16Smrg    else {
4752f167a42Smrg        inDpyName = inputFile;
4762f167a42Smrg        inputFile = NULL;
4770e20ee16Smrg    }
4780e20ee16Smrg
4792f167a42Smrg    if (outputFormat == WANT_DEFAULT)
4802f167a42Smrg        outputFormat = WANT_PS_FILE;
4812f167a42Smrg    if ((outputFile == NULL) && (inputFile != NULL) &&
4822f167a42Smrg        uStringEqual(inputFile, "-")) {
4832f167a42Smrg        size_t len;
4842f167a42Smrg
4852f167a42Smrg        len = strlen("stdin.eps") + 2;
4862f167a42Smrg        outputFile = calloc(len, sizeof(char));
4872f167a42Smrg
4882f167a42Smrg        if (outputFile == NULL) {
4892f167a42Smrg            uInternalError("Cannot allocate space for output file name\n");
4902f167a42Smrg            uAction("Exiting\n");
4912f167a42Smrg            exit(1);
4922f167a42Smrg        }
4932f167a42Smrg        if (args.wantEPS)
4942f167a42Smrg            snprintf(outputFile, len, "stdin.eps");
4952f167a42Smrg        else
4962f167a42Smrg            snprintf(outputFile, len, "stdin.ps");
4970e20ee16Smrg    }
4982f167a42Smrg    else if ((outputFile == NULL) && (inputFile != NULL)) {
4992f167a42Smrg        size_t len;
5002f167a42Smrg        char *base, *ext;
5012f167a42Smrg
5022f167a42Smrg        base = strrchr(inputFile, '/');
5032f167a42Smrg        if (base == NULL)
5042f167a42Smrg            base = inputFile;
5052f167a42Smrg        else
5062f167a42Smrg            base++;
5072f167a42Smrg
5082f167a42Smrg        len = strlen(base) + strlen("eps") + 2;
5092f167a42Smrg        outputFile = calloc(len, sizeof(char));
5102f167a42Smrg
5112f167a42Smrg        if (outputFile == NULL) {
5122f167a42Smrg            uInternalError("Cannot allocate space for output file name\n");
5132f167a42Smrg            uAction("Exiting\n");
5142f167a42Smrg            exit(1);
5152f167a42Smrg        }
5162f167a42Smrg        ext = strrchr(base, '.');
5172f167a42Smrg        if (ext == NULL) {
5182f167a42Smrg            if (args.wantEPS)
5192f167a42Smrg                snprintf(outputFile, len, "%s.eps", base);
5202f167a42Smrg            else
5212f167a42Smrg                snprintf(outputFile, len, "%s.ps", base);
5222f167a42Smrg        }
5232f167a42Smrg        else {
5242f167a42Smrg            strcpy(outputFile, base);
5252f167a42Smrg            if (args.wantEPS)
5262f167a42Smrg                strcpy(&outputFile[ext - base + 1], "eps");
5272f167a42Smrg            else
5282f167a42Smrg                strcpy(&outputFile[ext - base + 1], "ps");
5292f167a42Smrg        }
5300e20ee16Smrg    }
5312f167a42Smrg    else if (outputFile == NULL) {
5322f167a42Smrg        size_t len;
5332f167a42Smrg        char *ch, *name, buf[128];
5342f167a42Smrg
5352f167a42Smrg        if (inDpyName[0] == ':')
5362f167a42Smrg            snprintf(name = buf, sizeof(buf), "server%s", inDpyName);
5372f167a42Smrg        else
5382f167a42Smrg            name = inDpyName;
5392f167a42Smrg
5402f167a42Smrg        len = strlen(name) + strlen("eps") + 2;
5412f167a42Smrg        outputFile = calloc(len, sizeof(char));
5422f167a42Smrg
5432f167a42Smrg        if (outputFile == NULL) {
5442f167a42Smrg            uInternalError("Cannot allocate space for output file name\n");
5452f167a42Smrg            uAction("Exiting\n");
5462f167a42Smrg            exit(1);
5472f167a42Smrg        }
5482f167a42Smrg        strcpy(outputFile, name);
5492f167a42Smrg        for (ch = outputFile; (*ch) != '\0'; ch++) {
5502f167a42Smrg            if (*ch == ':')
5512f167a42Smrg                *ch = '-';
5522f167a42Smrg            else if (*ch == '.')
5532f167a42Smrg                *ch = '_';
5542f167a42Smrg        }
5552f167a42Smrg        *ch++ = '.';
5562f167a42Smrg        if (args.wantEPS)
5572f167a42Smrg            strcpy(ch, "eps");
5582f167a42Smrg        else
5592f167a42Smrg            strcpy(ch, "ps");
5600e20ee16Smrg    }
5612f167a42Smrg    else if (strchr(outputFile, ':') != NULL) {
5622f167a42Smrg        outDpyName = outputFile;
5632f167a42Smrg        outputFile = NULL;
5642f167a42Smrg        outputFormat = WANT_X_SERVER;
5652f167a42Smrg        uInternalError("Output to an X server not implemented yet\n");
5662f167a42Smrg        return False;
5670e20ee16Smrg    }
5680e20ee16Smrg    return True;
5690e20ee16Smrg}
5700e20ee16Smrg
5710e20ee16Smrgstatic Display *
5720e20ee16SmrgGetDisplay(char *program, char *dpyName)
5730e20ee16Smrg{
5742f167a42Smrg    int mjr, mnr, error;
5752f167a42Smrg    Display *dpy;
5762f167a42Smrg
5772f167a42Smrg    mjr = XkbMajorVersion;
5782f167a42Smrg    mnr = XkbMinorVersion;
5792f167a42Smrg    dpy = XkbOpenDisplay(dpyName, NULL, NULL, &mjr, &mnr, &error);
5802f167a42Smrg    if (dpy == NULL) {
5812f167a42Smrg        switch (error) {
5822f167a42Smrg        case XkbOD_BadLibraryVersion:
5832f167a42Smrg            uInformation("%s was compiled with XKB version %d.%02d\n",
5842f167a42Smrg                         program, XkbMajorVersion, XkbMinorVersion);
5852f167a42Smrg            uError("X library supports incompatible version %d.%02d\n",
5862f167a42Smrg                   mjr, mnr);
5872f167a42Smrg            break;
5882f167a42Smrg        case XkbOD_ConnectionRefused:
5892f167a42Smrg            uError("Cannot open display \"%s\"\n", dpyName);
5902f167a42Smrg            break;
5912f167a42Smrg        case XkbOD_NonXkbServer:
5922f167a42Smrg            uError("XKB extension not present on %s\n", dpyName);
5932f167a42Smrg            break;
5942f167a42Smrg        case XkbOD_BadServerVersion:
5952f167a42Smrg            uInformation("%s was compiled with XKB version %d.%02d\n",
5962f167a42Smrg                         program, XkbMajorVersion, XkbMinorVersion);
5972f167a42Smrg            uError("Server %s uses incompatible version %d.%02d\n",
5982f167a42Smrg                   dpyName, mjr, mnr);
5992f167a42Smrg            break;
6002f167a42Smrg        default:
6012f167a42Smrg            uInternalError("Unknown error %d from XkbOpenDisplay\n", error);
6022f167a42Smrg        }
6030e20ee16Smrg    }
6040e20ee16Smrg    else if (synch)
6052f167a42Smrg        XSynchronize(dpy, True);
6060e20ee16Smrg    return dpy;
6070e20ee16Smrg}
6080e20ee16Smrg
6090e20ee16Smrg/***====================================================================***/
6100e20ee16Smrg
6110e20ee16Smrg
6120e20ee16Smrgint
6130e20ee16Smrgmain(int argc, char *argv[])
6140e20ee16Smrg{
6152f167a42Smrg    FILE *file;
6162f167a42Smrg    int ok;
6172f167a42Smrg    XkbFileInfo result;
6180e20ee16Smrg
6190e20ee16Smrg    uSetErrorFile(NullString);
6202f167a42Smrg    if (!parseArgs(argc, argv))
6212f167a42Smrg        exit(1);
6222f167a42Smrg    file = NULL;
6230e20ee16Smrg    XkbInitAtoms(NULL);
6240e20ee16Smrg/*     XkbInitIncludePath(); */
6252f167a42Smrg    if (inputFile != NULL) {
6262f167a42Smrg        if (uStringEqual(inputFile, "-")) {
6272f167a42Smrg            static char in[] = "stdin";
6282f167a42Smrg
6292f167a42Smrg            file = stdin;
6302f167a42Smrg            inputFile = in;
6312f167a42Smrg        }
6322f167a42Smrg        else {
6332f167a42Smrg            file = fopen(inputFile, "r");
6342f167a42Smrg        }
6350e20ee16Smrg    }
6362f167a42Smrg    else if (inDpyName != NULL) {
6372f167a42Smrg        inDpy = GetDisplay(argv[0], inDpyName);
6382f167a42Smrg        if (!inDpy) {
6392f167a42Smrg            uAction("Exiting\n");
6402f167a42Smrg            exit(1);
6412f167a42Smrg        }
6420e20ee16Smrg    }
6432f167a42Smrg    if (outDpyName != NULL) {
6442f167a42Smrg        uInternalError("Output to an X server not implemented yet\n");
6452f167a42Smrg        outDpy = GetDisplay(argv[0], outDpyName);
6462f167a42Smrg        if (!outDpy) {
6472f167a42Smrg            uAction("Exiting\n");
6482f167a42Smrg            exit(1);
6492f167a42Smrg        }
6500e20ee16Smrg    }
6512f167a42Smrg    if ((inDpy == NULL) && (outDpy == NULL)) {
6522f167a42Smrg        int mjr, mnr;
6532f167a42Smrg
6542f167a42Smrg        mjr = XkbMajorVersion;
6552f167a42Smrg        mnr = XkbMinorVersion;
6562f167a42Smrg        if (!XkbLibraryVersion(&mjr, &mnr)) {
6572f167a42Smrg            uInformation("%s was compiled with XKB version %d.%02d\n",
6582f167a42Smrg                         argv[0], XkbMajorVersion, XkbMinorVersion);
6592f167a42Smrg            uError("X library supports incompatible version %d.%02d\n",
6602f167a42Smrg                   mjr, mnr);
6612f167a42Smrg            uAction("Exiting\n");
6622f167a42Smrg            exit(1);
6632f167a42Smrg        }
6640e20ee16Smrg    }
6652f167a42Smrg    ok = True;
6660e20ee16Smrg    if (file) {
6672f167a42Smrg        unsigned tmp;
6682f167a42Smrg
6692f167a42Smrg        bzero((char *) &result, sizeof(result));
6702f167a42Smrg        if ((result.xkb = XkbAllocKeyboard()) == NULL) {
6712f167a42Smrg            uFatalError("Cannot allocate keyboard description\n");
6722f167a42Smrg            /* NOTREACHED */
6732f167a42Smrg        }
6742f167a42Smrg        tmp = XkmReadFile(file, XkmGeometryMask, XkmKeymapLegal, &result);
6752f167a42Smrg        if ((tmp & XkmGeometryMask) != 0) {
6762f167a42Smrg            uError("Couldn't read geometry from XKM file \"%s\"\n", inputFile);
6772f167a42Smrg            uAction("Exiting\n");
6782f167a42Smrg            ok = False;
6792f167a42Smrg        }
6802f167a42Smrg        if ((tmp & XkmKeyNamesMask) != 0)
6812f167a42Smrg            args.wantKeycodes = False;
6822f167a42Smrg        if (args.label == LABEL_AUTO) {
6832f167a42Smrg            if (result.defined & XkmSymbolsMask)
6842f167a42Smrg                args.label = LABEL_SYMBOLS;
6852f167a42Smrg            else if (result.defined & XkmKeyNamesMask)
6862f167a42Smrg                args.label = LABEL_KEYCODE;
6872f167a42Smrg            else
6882f167a42Smrg                args.label = LABEL_KEYNAME;
6892f167a42Smrg        }
6902f167a42Smrg        else if ((args.label == LABEL_KEYCODE) &&
6912f167a42Smrg                 ((tmp & XkmKeyNamesMask) != 0)) {
6922f167a42Smrg            uError("XKM file \"%s\" doesn't have keycodes\n", inputFile);
6932f167a42Smrg            uAction("Cannot label keys as requested. Exiting\n");
6942f167a42Smrg            ok = False;
6952f167a42Smrg        }
6962f167a42Smrg        else if ((args.label == LABEL_SYMBOLS) && ((tmp & XkmSymbolsMask) != 0)) {
6972f167a42Smrg            uError("XKM file \"%s\" doesn't have symbols\n", inputFile);
6982f167a42Smrg            uAction("Cannot label keys as requested. Exiting\n");
6992f167a42Smrg            ok = False;
7002f167a42Smrg        }
7010e20ee16Smrg    }
7022f167a42Smrg    else if (inDpy != NULL) {
7032f167a42Smrg        bzero((char *) &result, sizeof(result));
7042f167a42Smrg        result.type = XkmKeymapFile;
7052f167a42Smrg        result.xkb = XkbGetMap(inDpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
7062f167a42Smrg        if (result.xkb == NULL)
7072f167a42Smrg            uWarning("Cannot load keyboard description\n");
7082f167a42Smrg        if (XkbGetNames(inDpy, XkbAllNamesMask, result.xkb) != Success)
7092f167a42Smrg            uWarning("Cannot load names\n");
7102f167a42Smrg        if (XkbGetGeometry(inDpy, result.xkb) != Success) {
7112f167a42Smrg            uFatalError("Cannot load geometry for %s\n", inDpyName);
7122f167a42Smrg        }
7132f167a42Smrg        if (args.label == LABEL_AUTO)
7142f167a42Smrg            args.label = LABEL_SYMBOLS;
7150e20ee16Smrg    }
7160e20ee16Smrg    else {
7172f167a42Smrg        fprintf(stderr, "Cannot open \"%s\" to read geometry\n", inputFile);
7182f167a42Smrg        ok = 0;
7190e20ee16Smrg    }
7200e20ee16Smrg    if (ok) {
7212f167a42Smrg        FILE *out = NULL;
7222f167a42Smrg
7232f167a42Smrg        if (setlocale(LC_ALL, (wantLocale)) == NULL) {
7242f167a42Smrg            if (wantLocale != NULL) {
7252f167a42Smrg                uWarning("Couldn't change to locale %s\n", wantLocale);
7262f167a42Smrg                uAction("Using \"C\" locale, instead\n");
7272f167a42Smrg            }
7282f167a42Smrg        }
7292f167a42Smrg        /* need C numerics so decimal point doesn't get screwed up */
7302f167a42Smrg        setlocale(LC_NUMERIC, "C");
7312f167a42Smrg        if ((inDpy != outDpy) &&
7322f167a42Smrg            (XkbChangeKbdDisplay(outDpy, &result) != Success)) {
7332f167a42Smrg            uInternalError("Error converting keyboard display from %s to %s\n",
7342f167a42Smrg                           inDpyName, outDpyName);
7352f167a42Smrg            exit(1);
7362f167a42Smrg        }
7372f167a42Smrg        if (outputFile != NULL) {
7382f167a42Smrg            if (uStringEqual(outputFile, "-")) {
7392f167a42Smrg                static char of[] = "stdout";
7402f167a42Smrg
7412f167a42Smrg                out = stdout;
7422f167a42Smrg                outputFile = of;
7432f167a42Smrg            }
7442f167a42Smrg            else {
7452f167a42Smrg                out = fopen(outputFile, "w");
7462f167a42Smrg                if (out == NULL) {
7472f167a42Smrg                    uError("Cannot open \"%s\" to write keyboard description\n",
7482f167a42Smrg                           outputFile);
7492f167a42Smrg                    uAction("Exiting\n");
7502f167a42Smrg                    exit(1);
7512f167a42Smrg                }
7522f167a42Smrg            }
7532f167a42Smrg        }
7542f167a42Smrg        switch (outputFormat) {
7552f167a42Smrg        case WANT_PS_FILE:
7562f167a42Smrg            ok = GeometryToPostScript(out, &result, &args);
7572f167a42Smrg            break;
7582f167a42Smrg        case WANT_X_SERVER:
7592f167a42Smrg            uInternalError("Output to X server not implemented yet\n");
7602f167a42Smrg            break;
7612f167a42Smrg        default:
7622f167a42Smrg            uInternalError("Unknown output format %d\n", outputFormat);
7632f167a42Smrg            uAction("No output file created\n");
7642f167a42Smrg            ok = False;
7652f167a42Smrg            break;
7662f167a42Smrg        }
7672f167a42Smrg        if (!ok) {
7682f167a42Smrg            uError("Error creating output file\n");
7692f167a42Smrg        }
7700e20ee16Smrg    }
7712f167a42Smrg    if (inDpy)
7722f167a42Smrg        XCloseDisplay(inDpy);
7732f167a42Smrg    inDpy = NULL;
7740e20ee16Smrg    if (outDpy)
7752f167a42Smrg        XCloseDisplay(outDpy);
7762f167a42Smrg    return (ok == 0);
7770e20ee16Smrg}
778