xkbprint.c revision 2f167a42
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#if defined(sgi)
430e20ee16Smrg#include <malloc.h>
440e20ee16Smrg#endif
450e20ee16Smrg
460e20ee16Smrg#include <stdlib.h>
470e20ee16Smrg
480e20ee16Smrg#include "utils.h"
490e20ee16Smrg#include "xkbprint.h"
500e20ee16Smrg
510e20ee16Smrg/***====================================================================***/
520e20ee16Smrg
530e20ee16Smrg
540e20ee16Smrg#define	WANT_DEFAULT	0
550e20ee16Smrg#define	WANT_PS_FILE	1
560e20ee16Smrg#define	WANT_X_SERVER	2
570e20ee16Smrg
580e20ee16Smrg
592f167a42Smrgstatic unsigned         outputFormat = WANT_DEFAULT;
602f167a42Smrgstatic const char *     wantLocale = "C";
612f167a42Smrgstatic char *           rootDir;
622f167a42Smrgstatic char *           inputFile;
632f167a42Smrgstatic char *           outputFile;
642f167a42Smrgstatic char *           outputFont = NULL;
652f167a42Smrgstatic char *           inDpyName;
662f167a42Smrgstatic char *           outDpyName;
672f167a42Smrgstatic Display *        inDpy;
682f167a42Smrgstatic Display *        outDpy;
692f167a42Smrgstatic XKBPrintArgs     args;
702f167a42Smrgstatic unsigned         warningLevel = 5;
712f167a42Smrgstatic Bool             synch;
720e20ee16Smrg
730e20ee16Smrg/***====================================================================***/
740e20ee16Smrg
750e20ee16Smrgstatic void
760e20ee16SmrgUsage(int argc, char *argv[])
770e20ee16Smrg{
782f167a42Smrg    fprintf(stderr, "Usage: %s [options] input-file [ output-file ]\n%s",
792f167a42Smrg            argv[0],
802f167a42Smrg            "Legal options:\n"
812f167a42Smrg            "-?,-help      Print this message\n"
822f167a42Smrg            "-color        Use colors from geometry\n"
830e20ee16Smrg#ifdef DEBUG
842f167a42Smrg            "-d [flags]    Report debugging information\n"
850e20ee16Smrg#endif
862f167a42Smrg            "-dflts        Compute defaults for missing components\n"
872f167a42Smrg            "-diffs        Only show explicit key definitions\n"
882f167a42Smrg            "-eps          Generate an EPS file\n"
892f167a42Smrg            "-fit          Fit keyboard image on page (default)\n"
902f167a42Smrg            "-full         Print keyboard image full sized\n"
912f167a42Smrg            "-grid <n>     Print a grid with <n> mm resolution\n"
922f167a42Smrg            "-if <name>    Specifies the name of an internal font to dump\n"
930e20ee16Smrg#ifdef DEBUG
942f167a42Smrg            "-I[<dir>]     Specifies a top level directory\n"
952f167a42Smrg            "              for include directives.  You can\n"
962f167a42Smrg            "              specify multiple directories.\n"
970e20ee16Smrg#endif
982f167a42Smrg            "-kc           Also print keycodes, if possible\n"
992f167a42Smrg            "-label <what> Specifies the label to be drawn on keys\n"
1002f167a42Smrg            "              Legal values for <what> are:\n"
1012f167a42Smrg            "                  none,name,code,symbols\n"
1022f167a42Smrg            "-lc <locale>  Use <locale> for fonts and symbols\n"
1032f167a42Smrg            "-level1       Use level 1 PostScript (default)\n"
1042f167a42Smrg            "-level2       Use level 2 PostScript\n"
1052f167a42Smrg            "-lg <num>     Use keyboard group <num> to print labels\n"
1062f167a42Smrg            "-ll <num>     Use shift level <num> to print labels\n"
1072f167a42Smrg            "-mono         Ignore colors from geometry (default)\n"
1082f167a42Smrg            "-n <num>      Print <num> copies (default 1)\n"
1092f167a42Smrg            "-nkg <num>    Number of groups to print on each key\n"
1102f167a42Smrg            "-nokc         Don't print keycodes, even if possible\n"
1112f167a42Smrg            "-npk <num>    Number of keyboards to print on each page\n"
1122f167a42Smrg            "-ntg <num>    Total number of groups to print\n"
1132f167a42Smrg            "-o <file>     Specifies output file name\n"
1142f167a42Smrg            "-R[<DIR>]     Specifies the root directory for relative\n"
1152f167a42Smrg            "              path names\n"
1162f167a42Smrg            "-pict <what>  Specifies use of pictographs instead of\n"
1172f167a42Smrg            "              keysym names where available, <what> can\n"
1182f167a42Smrg            "              be \"all\", \"none\" or \"common\" (default)\n"
1192f167a42Smrg            "-synch        Force synchronization\n"
1202f167a42Smrg            "-version      Print program version\n"
1212f167a42Smrg            "-w <lvl>      Set warning level (0=none, 10=all)\n"
1222f167a42Smrg        );
1230e20ee16Smrg}
1240e20ee16Smrg
1250e20ee16Smrg/***====================================================================***/
1260e20ee16Smrg
1270e20ee16Smrgstatic Bool
1280e20ee16SmrgparseArgs(int argc, char *argv[])
1290e20ee16Smrg{
1302f167a42Smrg    register int i;
1312f167a42Smrg
1322f167a42Smrg    args.copies = 1;
1332f167a42Smrg    args.grid = 0;
1342f167a42Smrg    args.level1 = True;
1352f167a42Smrg    args.scaleToFit = True;
1362f167a42Smrg    args.wantColor = False;
1372f167a42Smrg    args.wantSymbols = COMMON_SYMBOLS;
1382f167a42Smrg    args.wantKeycodes = True;
1392f167a42Smrg    args.wantDiffs = False;
1402f167a42Smrg    args.wantEPS = False;
1412f167a42Smrg    args.label = LABEL_AUTO;
1422f167a42Smrg    args.baseLabelGroup = 0;
1432f167a42Smrg    args.nLabelGroups = 1;
1442f167a42Smrg    args.nTotalGroups = 0;
1452f167a42Smrg    args.nKBPerPage = 0;
1462f167a42Smrg    args.labelLevel = 0;
1472f167a42Smrg    for (i = 1; i < argc; i++) {
1482f167a42Smrg        if ((argv[i][0] != '-') || (uStringEqual(argv[i], "-"))) {
1492f167a42Smrg            if (inputFile == NULL) {
1502f167a42Smrg                inputFile = argv[i];
1512f167a42Smrg            }
1522f167a42Smrg            else if (outputFile == NULL) {
1532f167a42Smrg                outputFile = argv[i];
1542f167a42Smrg            }
1552f167a42Smrg            else {
1562f167a42Smrg                uWarning("Too many file names on command line\n");
1572f167a42Smrg                uAction("Compiling %s, writing to %s, ignoring %s\n",
1582f167a42Smrg                        inputFile, outputFile, argv[i]);
1592f167a42Smrg            }
1602f167a42Smrg        }
1612f167a42Smrg        else if ((strcmp(argv[i], "-?") == 0) ||
1622f167a42Smrg                 (strcmp(argv[i], "-help") == 0)) {
1632f167a42Smrg            Usage(argc, argv);
1642f167a42Smrg            exit(0);
1652f167a42Smrg        }
1662f167a42Smrg        else if (strcmp(argv[i], "-color") == 0) {
1672f167a42Smrg            args.wantColor = True;
1682f167a42Smrg        }
1690e20ee16Smrg#ifdef DEBUG
1702f167a42Smrg        else if (strcmp(argv[i], "-d") == 0) {
1712f167a42Smrg            if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0]))) {
1722f167a42Smrg                debugFlags = 1;
1732f167a42Smrg            }
1742f167a42Smrg            else {
1752f167a42Smrg                sscanf(argv[++i], "%i", &debugFlags);
1762f167a42Smrg            }
1772f167a42Smrg            uInformation("Setting debug flags to %d\n", debugFlags);
1782f167a42Smrg        }
1790e20ee16Smrg#endif
1802f167a42Smrg        else if (strcmp(argv[i], "-dflts") == 0) {
1812f167a42Smrg            uWarning("Compute defaults not implemented yet\n");
1822f167a42Smrg        }
1832f167a42Smrg        else if (strcmp(argv[i], "-diffs") == 0) {
1842f167a42Smrg            args.wantDiffs = True;
1852f167a42Smrg        }
1862f167a42Smrg        else if (strcmp(argv[i], "-eps") == 0) {
1872f167a42Smrg            args.wantEPS = True;
1882f167a42Smrg        }
1892f167a42Smrg        else if (strcmp(argv[i], "-fit") == 0) {
1902f167a42Smrg            args.scaleToFit = True;
1912f167a42Smrg        }
1922f167a42Smrg        else if (strcmp(argv[i], "-full") == 0) {
1932f167a42Smrg            args.scaleToFit = False;
1942f167a42Smrg        }
1952f167a42Smrg        else if (strcmp(argv[i], "-grid") == 0) {
1962f167a42Smrg            int tmp;
1972f167a42Smrg
1982f167a42Smrg            if (++i >= argc) {
1992f167a42Smrg                uWarning("Grid frequency not specified\n");
2002f167a42Smrg                uAction("Trailing \"-grid\" option ignored\n");
2012f167a42Smrg            }
2022f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1)) {
2032f167a42Smrg                uWarning("Grid frequency must be an integer > zero\n");
2042f167a42Smrg                uAction("Illegal frequency %d ignored\n", tmp);
2052f167a42Smrg            }
2062f167a42Smrg            else
2072f167a42Smrg                args.grid = tmp;
2082f167a42Smrg        }
2092f167a42Smrg        else if (strcmp(argv[i], "-if") == 0) {
2102f167a42Smrg            if (++i >= argc) {
2112f167a42Smrg                uWarning("Internal Font name not specified\n");
2122f167a42Smrg                uAction("Trailing \"-if\" option ignored\n");
2132f167a42Smrg            }
2142f167a42Smrg            else
2152f167a42Smrg                outputFont = argv[i];
2162f167a42Smrg        }
2172f167a42Smrg        else if (strcmp(argv[i], "-kc") == 0) {
2182f167a42Smrg            args.wantKeycodes = True;
2192f167a42Smrg        }
2202f167a42Smrg        else if (strcmp(argv[i], "-label") == 0) {
2212f167a42Smrg            if (++i >= argc) {
2222f167a42Smrg                uWarning("Label type not specified\n");
2232f167a42Smrg                uAction("Trailing \"-label\" option ignored\n");
2242f167a42Smrg            }
2252f167a42Smrg            else if (uStrCaseEqual(argv[i], "none"))
2262f167a42Smrg                args.label = LABEL_NONE;
2272f167a42Smrg            else if (uStrCaseEqual(argv[i], "name"))
2282f167a42Smrg                args.label = LABEL_KEYNAME;
2292f167a42Smrg            else if (uStrCaseEqual(argv[i], "code"))
2302f167a42Smrg                args.label = LABEL_KEYCODE;
2312f167a42Smrg            else if (uStrCaseEqual(argv[i], "symbols"))
2322f167a42Smrg                args.label = LABEL_SYMBOLS;
2332f167a42Smrg            else {
2342f167a42Smrg                uWarning("Unknown label type \"%s\" specified\n", argv[i]);
2352f167a42Smrg                uAction("Ignored\n");
2362f167a42Smrg            }
2372f167a42Smrg        }
2382f167a42Smrg        else if (strcmp(argv[i], "-lc") == 0) {
2392f167a42Smrg            if (++i >= argc) {
2402f167a42Smrg                uWarning("Locale not specified\n");
2412f167a42Smrg                uAction("Trailing \"-lc\" option ignored\n");
2422f167a42Smrg            }
2432f167a42Smrg            else
2442f167a42Smrg                wantLocale = argv[i];
2452f167a42Smrg        }
2462f167a42Smrg        else if (strcmp(argv[i], "-lg") == 0) {
2472f167a42Smrg            int tmp;
2482f167a42Smrg
2492f167a42Smrg            if (++i >= argc) {
2502f167a42Smrg                uWarning("Label group not specified\n");
2512f167a42Smrg                uAction("Trailing \"-lg\" option ignored\n");
2522f167a42Smrg            }
2532f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
2542f167a42Smrg                     (tmp > 4)) {
2552f167a42Smrg                uWarning("Label group must be an integer in the range 1..4\n");
2562f167a42Smrg                uAction("Illegal group %d ignored\n", tmp);
2572f167a42Smrg            }
2582f167a42Smrg            else
2592f167a42Smrg                args.baseLabelGroup = tmp - 1;
2602f167a42Smrg        }
2612f167a42Smrg        else if (strcmp(argv[i], "-ll") == 0) {
2622f167a42Smrg            int tmp;
2632f167a42Smrg
2642f167a42Smrg            if (++i >= argc) {
2652f167a42Smrg                uWarning("Label level not specified\n");
2662f167a42Smrg                uAction("Trailing \"-ll\" option ignored\n");
2672f167a42Smrg            }
2682f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
2692f167a42Smrg                     (tmp > 255)) {
2702f167a42Smrg                uWarning("Label level must be in the range 1..255\n");
2712f167a42Smrg                uAction("Illegal level %d ignored\n", tmp);
2722f167a42Smrg            }
2732f167a42Smrg            else
2742f167a42Smrg                args.labelLevel = tmp - 1;
2752f167a42Smrg        }
2762f167a42Smrg        else if (strcmp(argv[i], "-level1") == 0)
2772f167a42Smrg            args.level1 = True;
2782f167a42Smrg        else if (strcmp(argv[i], "-level2") == 0)
2792f167a42Smrg            args.level1 = False;
2802f167a42Smrg        else if (strcmp(argv[i], "-mono") == 0) {
2812f167a42Smrg            args.wantColor = False;
2822f167a42Smrg        }
2832f167a42Smrg        else if (strcmp(argv[i], "-n") == 0) {
2842f167a42Smrg            int tmp;
2852f167a42Smrg
2862f167a42Smrg            if (++i >= argc) {
2872f167a42Smrg                uWarning("Number of copies not specified\n");
2882f167a42Smrg                uAction("Trailing \"-n\" option ignored\n");
2892f167a42Smrg            }
2902f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1)) {
2912f167a42Smrg                uWarning("Number of copies must be an integer > zero\n");
2922f167a42Smrg                uAction("Illegal count %d ignored\n", tmp);
2932f167a42Smrg            }
2942f167a42Smrg            else
2952f167a42Smrg                args.copies = tmp;
2962f167a42Smrg        }
2972f167a42Smrg        else if (strcmp(argv[i], "-nokc") == 0) {
2982f167a42Smrg            args.wantKeycodes = False;
2992f167a42Smrg        }
3002f167a42Smrg        else if (strcmp(argv[i], "-nkg") == 0) {
3012f167a42Smrg            int tmp;
3022f167a42Smrg
3032f167a42Smrg            if (++i >= argc) {
3042f167a42Smrg                uWarning("Number of groups per key not specified\n");
3052f167a42Smrg                uAction("Trailing \"-nkg\" option ignored\n");
3062f167a42Smrg            }
3072f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
3082f167a42Smrg                     (tmp > 2)) {
3092f167a42Smrg                uWarning("Groups per key must be in the range 1..2\n");
3102f167a42Smrg                uAction("Illegal number of groups %d ignored\n", tmp);
3112f167a42Smrg            }
3122f167a42Smrg            else
3132f167a42Smrg                args.nLabelGroups = tmp;
3142f167a42Smrg        }
3152f167a42Smrg        else if (strcmp(argv[i], "-npk") == 0) {
3162f167a42Smrg            int tmp;
3172f167a42Smrg
3182f167a42Smrg            if (++i >= argc) {
3192f167a42Smrg                uWarning("Number of keyboards per page not specified\n");
3202f167a42Smrg                uAction("Trailing \"-npk\" option ignored\n");
3212f167a42Smrg            }
3222f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
3232f167a42Smrg                     (tmp > 2)) {
3242f167a42Smrg                uWarning("Keyboards per page must be in the range 1..2\n");
3252f167a42Smrg                uAction("Illegal number of keyboards %d ignored\n", tmp);
3262f167a42Smrg            }
3272f167a42Smrg            else
3282f167a42Smrg                args.nKBPerPage = tmp;
3292f167a42Smrg        }
3302f167a42Smrg        else if (strcmp(argv[i], "-ntg") == 0) {
3312f167a42Smrg            int tmp;
3322f167a42Smrg
3332f167a42Smrg            if (++i >= argc) {
3342f167a42Smrg                uWarning("Total number of groups not specified\n");
3352f167a42Smrg                uAction("Trailing \"-ntg\" option ignored\n");
3362f167a42Smrg            }
3372f167a42Smrg            else if ((sscanf(argv[i], "%i", &tmp) != 1) || (tmp < 1) ||
3382f167a42Smrg                     (tmp > 4)) {
3392f167a42Smrg                uWarning("Total number of groups must be in the range 1..4\n");
3402f167a42Smrg                uAction("Illegal number of groups %d ignored\n", tmp);
3412f167a42Smrg            }
3422f167a42Smrg            else
3432f167a42Smrg                args.nTotalGroups = tmp;
3442f167a42Smrg        }
3452f167a42Smrg        else if (strcmp(argv[i], "-o") == 0) {
3462f167a42Smrg            if (++i >= argc) {
3472f167a42Smrg                uWarning("No output file specified\n");
3482f167a42Smrg                uAction("Trailing \"-o\" option ignored\n");
3492f167a42Smrg            }
3502f167a42Smrg            else if (outputFile != NULL) {
3512f167a42Smrg                uWarning("Multiple output files specified\n");
3522f167a42Smrg                uAction("Compiling %s, ignoring %s\n", outputFile, argv[i]);
3532f167a42Smrg            }
3542f167a42Smrg            else
3552f167a42Smrg                outputFile = argv[i];
3562f167a42Smrg        }
3572f167a42Smrg        else if (strncmp(argv[i], "-R", 2) == 0) {
3582f167a42Smrg            if (argv[i][2] == '\0') {
3592f167a42Smrg                uWarning("No root directory specified\n");
3602f167a42Smrg                uAction("Ignoring -R option\n");
3612f167a42Smrg            }
3622f167a42Smrg            else if (rootDir != NULL) {
3632f167a42Smrg                uWarning("Multiple root directories specified\n");
3642f167a42Smrg                uAction("Using %s, ignoring %s\n", rootDir, argv[i]);
3652f167a42Smrg            }
3662f167a42Smrg            else
3672f167a42Smrg                rootDir = &argv[i][2];
3682f167a42Smrg        }
3692f167a42Smrg        else if (strcmp(argv[i], "-pict") == 0) {
3702f167a42Smrg            if (++i >= argc) {
3712f167a42Smrg                uWarning("No level of pictographs specified\n");
3722f167a42Smrg                uAction("Trailing \"-pict\" option ignored\n");
3732f167a42Smrg            }
3742f167a42Smrg            else if (strcmp(argv[i], "none") == 0)
3752f167a42Smrg                args.wantSymbols = NO_SYMBOLS;
3762f167a42Smrg            else if (strcmp(argv[i], "common") == 0)
3772f167a42Smrg                args.wantSymbols = COMMON_SYMBOLS;
3782f167a42Smrg            else if (strcmp(argv[i], "all") == 0)
3792f167a42Smrg                args.wantSymbols = ALL_SYMBOLS;
3802f167a42Smrg            else if (outputFile != NULL) {
3812f167a42Smrg                uWarning("Unknown pictograph level specified\n");
3822f167a42Smrg                uAction("Ignoring illegal value %s\n", argv[i]);
3832f167a42Smrg            }
3842f167a42Smrg        }
3852f167a42Smrg        else if ((strcmp(argv[i], "-synch") == 0) ||
3862f167a42Smrg                 (strcmp(argv[i], "-s") == 0)) {
3872f167a42Smrg            synch = True;
3882f167a42Smrg        }
3892f167a42Smrg        else if (strcmp(argv[i], "-version") == 0) {
3902f167a42Smrg            puts(PACKAGE_STRING);
3912f167a42Smrg            exit(0);
3922f167a42Smrg        }
3932f167a42Smrg        else if (strcmp(argv[i], "-w") == 0) {
3942f167a42Smrg            if ((i >= (argc - 1)) || (!isdigit(argv[i + 1][0]))) {
3952f167a42Smrg                warningLevel = 0;
3962f167a42Smrg            }
3972f167a42Smrg            else {
3982f167a42Smrg                int itmp;
3992f167a42Smrg
4002f167a42Smrg                if (sscanf(argv[++i], "%i", &itmp))
4012f167a42Smrg                    warningLevel = itmp;
4022f167a42Smrg            }
4032f167a42Smrg        }
4042f167a42Smrg        else {
4052f167a42Smrg            uError("Unknown flag \"%s\" on command line\n", argv[i]);
4062f167a42Smrg            Usage(argc, argv);
4072f167a42Smrg            return False;
4082f167a42Smrg        }
4090e20ee16Smrg    }
4100e20ee16Smrg    if (rootDir) {
4112f167a42Smrg        if (warningLevel > 8) {
4122f167a42Smrg            uWarning("Changing root directory to \"%s\"\n", rootDir);
4132f167a42Smrg        }
4142f167a42Smrg        if ((chdir(rootDir) < 0) && (warningLevel > 0)) {
4152f167a42Smrg            uWarning("Couldn't change root directory to \"%s\"\n", rootDir);
4162f167a42Smrg            uAction("Root directory (-R) option ignored\n");
4172f167a42Smrg        }
4180e20ee16Smrg    }
4192f167a42Smrg    if (outputFont != NULL) {
4202f167a42Smrg        Bool ok;
4212f167a42Smrg        FILE *file = NULL;
4222f167a42Smrg
4232f167a42Smrg        if (outputFile == NULL) {
4242f167a42Smrg            asprintf(&outputFile, "%s.pfa", outputFont);
4252f167a42Smrg        }
4262f167a42Smrg        else if (uStringEqual(outputFile, "-"))
4272f167a42Smrg            file = stdout;
4282f167a42Smrg
4292f167a42Smrg        if (file == NULL)
4302f167a42Smrg            file = fopen(outputFile, "w");
4312f167a42Smrg
4322f167a42Smrg        if (!file) {
4332f167a42Smrg            uError("Couldn't open \"%s\" to dump internal font \"%s\"\n",
4342f167a42Smrg                   outputFile, outputFont);
4352f167a42Smrg            uAction("Exiting\n");
4362f167a42Smrg            exit(1);
4372f167a42Smrg        }
4382f167a42Smrg        ok = DumpInternalFont(file, outputFont);
4392f167a42Smrg        if (file != stdout)
4402f167a42Smrg            fclose(file);
4412f167a42Smrg        if (!ok) {
4422f167a42Smrg            uWarning("No internal font to dump\n");
4432f167a42Smrg            if (file != stdout) {
4442f167a42Smrg                uAction("Removing \"%s\"\n", outputFile);
4452f167a42Smrg                unlink(outputFile);
4462f167a42Smrg            }
4472f167a42Smrg        }
4482f167a42Smrg        exit((ok != 0));
4490e20ee16Smrg    }
4502f167a42Smrg    if (inputFile == NULL) {
4512f167a42Smrg        uError("No input file specified\n");
4522f167a42Smrg        Usage(argc, argv);
4532f167a42Smrg        return False;
4540e20ee16Smrg    }
4552f167a42Smrg    else if (uStringEqual(inputFile, "-")) {
4562f167a42Smrg        /* Nothing */
4570e20ee16Smrg    }
4582f167a42Smrg    else if (strchr(inputFile, ':') == NULL) {
4592f167a42Smrg        size_t len = strlen(inputFile);
4602f167a42Smrg
4612f167a42Smrg        if ((len > 4) && (strcmp(&inputFile[len - 4], ".xkm") == 0)) {
4622f167a42Smrg            /* Nothing */
4632f167a42Smrg        }
4642f167a42Smrg        else {
4652f167a42Smrg            FILE *file;
4662f167a42Smrg
4672f167a42Smrg            file = fopen(inputFile, "r");
4682f167a42Smrg            if (file) {
4692f167a42Smrg                fclose(file);
4702f167a42Smrg            }
4712f167a42Smrg            else {
4722f167a42Smrg                fprintf(stderr, "Cannot open \"%s\" for reading\n", inputFile);
4732f167a42Smrg                return False;
4742f167a42Smrg            }
4752f167a42Smrg        }
4760e20ee16Smrg    }
4770e20ee16Smrg    else {
4782f167a42Smrg        inDpyName = inputFile;
4792f167a42Smrg        inputFile = NULL;
4800e20ee16Smrg    }
4810e20ee16Smrg
4822f167a42Smrg    if (outputFormat == WANT_DEFAULT)
4832f167a42Smrg        outputFormat = WANT_PS_FILE;
4842f167a42Smrg    if ((outputFile == NULL) && (inputFile != NULL) &&
4852f167a42Smrg        uStringEqual(inputFile, "-")) {
4862f167a42Smrg        size_t len;
4872f167a42Smrg
4882f167a42Smrg        len = strlen("stdin.eps") + 2;
4892f167a42Smrg        outputFile = calloc(len, sizeof(char));
4902f167a42Smrg
4912f167a42Smrg        if (outputFile == NULL) {
4922f167a42Smrg            uInternalError("Cannot allocate space for output file name\n");
4932f167a42Smrg            uAction("Exiting\n");
4942f167a42Smrg            exit(1);
4952f167a42Smrg        }
4962f167a42Smrg        if (args.wantEPS)
4972f167a42Smrg            snprintf(outputFile, len, "stdin.eps");
4982f167a42Smrg        else
4992f167a42Smrg            snprintf(outputFile, len, "stdin.ps");
5000e20ee16Smrg    }
5012f167a42Smrg    else if ((outputFile == NULL) && (inputFile != NULL)) {
5022f167a42Smrg        size_t len;
5032f167a42Smrg        char *base, *ext;
5042f167a42Smrg
5052f167a42Smrg        base = strrchr(inputFile, '/');
5062f167a42Smrg        if (base == NULL)
5072f167a42Smrg            base = inputFile;
5082f167a42Smrg        else
5092f167a42Smrg            base++;
5102f167a42Smrg
5112f167a42Smrg        len = strlen(base) + strlen("eps") + 2;
5122f167a42Smrg        outputFile = calloc(len, sizeof(char));
5132f167a42Smrg
5142f167a42Smrg        if (outputFile == NULL) {
5152f167a42Smrg            uInternalError("Cannot allocate space for output file name\n");
5162f167a42Smrg            uAction("Exiting\n");
5172f167a42Smrg            exit(1);
5182f167a42Smrg        }
5192f167a42Smrg        ext = strrchr(base, '.');
5202f167a42Smrg        if (ext == NULL) {
5212f167a42Smrg            if (args.wantEPS)
5222f167a42Smrg                snprintf(outputFile, len, "%s.eps", base);
5232f167a42Smrg            else
5242f167a42Smrg                snprintf(outputFile, len, "%s.ps", base);
5252f167a42Smrg        }
5262f167a42Smrg        else {
5272f167a42Smrg            strcpy(outputFile, base);
5282f167a42Smrg            if (args.wantEPS)
5292f167a42Smrg                strcpy(&outputFile[ext - base + 1], "eps");
5302f167a42Smrg            else
5312f167a42Smrg                strcpy(&outputFile[ext - base + 1], "ps");
5322f167a42Smrg        }
5330e20ee16Smrg    }
5342f167a42Smrg    else if (outputFile == NULL) {
5352f167a42Smrg        size_t len;
5362f167a42Smrg        char *ch, *name, buf[128];
5372f167a42Smrg
5382f167a42Smrg        if (inDpyName[0] == ':')
5392f167a42Smrg            snprintf(name = buf, sizeof(buf), "server%s", inDpyName);
5402f167a42Smrg        else
5412f167a42Smrg            name = inDpyName;
5422f167a42Smrg
5432f167a42Smrg        len = strlen(name) + strlen("eps") + 2;
5442f167a42Smrg        outputFile = calloc(len, sizeof(char));
5452f167a42Smrg
5462f167a42Smrg        if (outputFile == NULL) {
5472f167a42Smrg            uInternalError("Cannot allocate space for output file name\n");
5482f167a42Smrg            uAction("Exiting\n");
5492f167a42Smrg            exit(1);
5502f167a42Smrg        }
5512f167a42Smrg        strcpy(outputFile, name);
5522f167a42Smrg        for (ch = outputFile; (*ch) != '\0'; ch++) {
5532f167a42Smrg            if (*ch == ':')
5542f167a42Smrg                *ch = '-';
5552f167a42Smrg            else if (*ch == '.')
5562f167a42Smrg                *ch = '_';
5572f167a42Smrg        }
5582f167a42Smrg        *ch++ = '.';
5592f167a42Smrg        if (args.wantEPS)
5602f167a42Smrg            strcpy(ch, "eps");
5612f167a42Smrg        else
5622f167a42Smrg            strcpy(ch, "ps");
5630e20ee16Smrg    }
5642f167a42Smrg    else if (strchr(outputFile, ':') != NULL) {
5652f167a42Smrg        outDpyName = outputFile;
5662f167a42Smrg        outputFile = NULL;
5672f167a42Smrg        outputFormat = WANT_X_SERVER;
5682f167a42Smrg        uInternalError("Output to an X server not implemented yet\n");
5692f167a42Smrg        return False;
5700e20ee16Smrg    }
5710e20ee16Smrg    return True;
5720e20ee16Smrg}
5730e20ee16Smrg
5740e20ee16Smrgstatic Display *
5750e20ee16SmrgGetDisplay(char *program, char *dpyName)
5760e20ee16Smrg{
5772f167a42Smrg    int mjr, mnr, error;
5782f167a42Smrg    Display *dpy;
5792f167a42Smrg
5802f167a42Smrg    mjr = XkbMajorVersion;
5812f167a42Smrg    mnr = XkbMinorVersion;
5822f167a42Smrg    dpy = XkbOpenDisplay(dpyName, NULL, NULL, &mjr, &mnr, &error);
5832f167a42Smrg    if (dpy == NULL) {
5842f167a42Smrg        switch (error) {
5852f167a42Smrg        case XkbOD_BadLibraryVersion:
5862f167a42Smrg            uInformation("%s was compiled with XKB version %d.%02d\n",
5872f167a42Smrg                         program, XkbMajorVersion, XkbMinorVersion);
5882f167a42Smrg            uError("X library supports incompatible version %d.%02d\n",
5892f167a42Smrg                   mjr, mnr);
5902f167a42Smrg            break;
5912f167a42Smrg        case XkbOD_ConnectionRefused:
5922f167a42Smrg            uError("Cannot open display \"%s\"\n", dpyName);
5932f167a42Smrg            break;
5942f167a42Smrg        case XkbOD_NonXkbServer:
5952f167a42Smrg            uError("XKB extension not present on %s\n", dpyName);
5962f167a42Smrg            break;
5972f167a42Smrg        case XkbOD_BadServerVersion:
5982f167a42Smrg            uInformation("%s was compiled with XKB version %d.%02d\n",
5992f167a42Smrg                         program, XkbMajorVersion, XkbMinorVersion);
6002f167a42Smrg            uError("Server %s uses incompatible version %d.%02d\n",
6012f167a42Smrg                   dpyName, mjr, mnr);
6022f167a42Smrg            break;
6032f167a42Smrg        default:
6042f167a42Smrg            uInternalError("Unknown error %d from XkbOpenDisplay\n", error);
6052f167a42Smrg        }
6060e20ee16Smrg    }
6070e20ee16Smrg    else if (synch)
6082f167a42Smrg        XSynchronize(dpy, True);
6090e20ee16Smrg    return dpy;
6100e20ee16Smrg}
6110e20ee16Smrg
6120e20ee16Smrg/***====================================================================***/
6130e20ee16Smrg
6140e20ee16Smrg
6150e20ee16Smrgint
6160e20ee16Smrgmain(int argc, char *argv[])
6170e20ee16Smrg{
6182f167a42Smrg    FILE *file;
6192f167a42Smrg    int ok;
6202f167a42Smrg    XkbFileInfo result;
6210e20ee16Smrg
6220e20ee16Smrg    uSetErrorFile(NullString);
6232f167a42Smrg    if (!parseArgs(argc, argv))
6242f167a42Smrg        exit(1);
6250e20ee16Smrg#ifdef DEBUG
6260e20ee16Smrg#ifdef sgi
6272f167a42Smrg    if (debugFlags & 0x4)
6282f167a42Smrg        mallopt(M_DEBUG, 1);
6290e20ee16Smrg#endif
6300e20ee16Smrg#endif
6312f167a42Smrg    file = NULL;
6320e20ee16Smrg    XkbInitAtoms(NULL);
6330e20ee16Smrg/*     XkbInitIncludePath(); */
6342f167a42Smrg    if (inputFile != NULL) {
6352f167a42Smrg        if (uStringEqual(inputFile, "-")) {
6362f167a42Smrg            static char in[] = "stdin";
6372f167a42Smrg
6382f167a42Smrg            file = stdin;
6392f167a42Smrg            inputFile = in;
6402f167a42Smrg        }
6412f167a42Smrg        else {
6422f167a42Smrg            file = fopen(inputFile, "r");
6432f167a42Smrg        }
6440e20ee16Smrg    }
6452f167a42Smrg    else if (inDpyName != NULL) {
6462f167a42Smrg        inDpy = GetDisplay(argv[0], inDpyName);
6472f167a42Smrg        if (!inDpy) {
6482f167a42Smrg            uAction("Exiting\n");
6492f167a42Smrg            exit(1);
6502f167a42Smrg        }
6510e20ee16Smrg    }
6522f167a42Smrg    if (outDpyName != NULL) {
6532f167a42Smrg        uInternalError("Output to an X server not implemented yet\n");
6542f167a42Smrg        outDpy = GetDisplay(argv[0], outDpyName);
6552f167a42Smrg        if (!outDpy) {
6562f167a42Smrg            uAction("Exiting\n");
6572f167a42Smrg            exit(1);
6582f167a42Smrg        }
6590e20ee16Smrg    }
6602f167a42Smrg    if ((inDpy == NULL) && (outDpy == NULL)) {
6612f167a42Smrg        int mjr, mnr;
6622f167a42Smrg
6632f167a42Smrg        mjr = XkbMajorVersion;
6642f167a42Smrg        mnr = XkbMinorVersion;
6652f167a42Smrg        if (!XkbLibraryVersion(&mjr, &mnr)) {
6662f167a42Smrg            uInformation("%s was compiled with XKB version %d.%02d\n",
6672f167a42Smrg                         argv[0], XkbMajorVersion, XkbMinorVersion);
6682f167a42Smrg            uError("X library supports incompatible version %d.%02d\n",
6692f167a42Smrg                   mjr, mnr);
6702f167a42Smrg            uAction("Exiting\n");
6712f167a42Smrg            exit(1);
6722f167a42Smrg        }
6730e20ee16Smrg    }
6742f167a42Smrg    ok = True;
6750e20ee16Smrg    if (file) {
6762f167a42Smrg        unsigned tmp;
6772f167a42Smrg
6782f167a42Smrg        bzero((char *) &result, sizeof(result));
6792f167a42Smrg        if ((result.xkb = XkbAllocKeyboard()) == NULL) {
6802f167a42Smrg            uFatalError("Cannot allocate keyboard description\n");
6812f167a42Smrg            /* NOTREACHED */
6822f167a42Smrg        }
6832f167a42Smrg        tmp = XkmReadFile(file, XkmGeometryMask, XkmKeymapLegal, &result);
6842f167a42Smrg        if ((tmp & XkmGeometryMask) != 0) {
6852f167a42Smrg            uError("Couldn't read geometry from XKM file \"%s\"\n", inputFile);
6862f167a42Smrg            uAction("Exiting\n");
6872f167a42Smrg            ok = False;
6882f167a42Smrg        }
6892f167a42Smrg        if ((tmp & XkmKeyNamesMask) != 0)
6902f167a42Smrg            args.wantKeycodes = False;
6912f167a42Smrg        if (args.label == LABEL_AUTO) {
6922f167a42Smrg            if (result.defined & XkmSymbolsMask)
6932f167a42Smrg                args.label = LABEL_SYMBOLS;
6942f167a42Smrg            else if (result.defined & XkmKeyNamesMask)
6952f167a42Smrg                args.label = LABEL_KEYCODE;
6962f167a42Smrg            else
6972f167a42Smrg                args.label = LABEL_KEYNAME;
6982f167a42Smrg        }
6992f167a42Smrg        else if ((args.label == LABEL_KEYCODE) &&
7002f167a42Smrg                 ((tmp & XkmKeyNamesMask) != 0)) {
7012f167a42Smrg            uError("XKM file \"%s\" doesn't have keycodes\n", inputFile);
7022f167a42Smrg            uAction("Cannot label keys as requested. Exiting\n");
7032f167a42Smrg            ok = False;
7042f167a42Smrg        }
7052f167a42Smrg        else if ((args.label == LABEL_SYMBOLS) && ((tmp & XkmSymbolsMask) != 0)) {
7062f167a42Smrg            uError("XKM file \"%s\" doesn't have symbols\n", inputFile);
7072f167a42Smrg            uAction("Cannot label keys as requested. Exiting\n");
7082f167a42Smrg            ok = False;
7092f167a42Smrg        }
7100e20ee16Smrg    }
7112f167a42Smrg    else if (inDpy != NULL) {
7122f167a42Smrg        bzero((char *) &result, sizeof(result));
7132f167a42Smrg        result.type = XkmKeymapFile;
7142f167a42Smrg        result.xkb = XkbGetMap(inDpy, XkbAllMapComponentsMask, XkbUseCoreKbd);
7152f167a42Smrg        if (result.xkb == NULL)
7162f167a42Smrg            uWarning("Cannot load keyboard description\n");
7172f167a42Smrg        if (XkbGetNames(inDpy, XkbAllNamesMask, result.xkb) != Success)
7182f167a42Smrg            uWarning("Cannot load names\n");
7192f167a42Smrg        if (XkbGetGeometry(inDpy, result.xkb) != Success) {
7202f167a42Smrg            uFatalError("Cannot load geometry for %s\n", inDpyName);
7212f167a42Smrg        }
7222f167a42Smrg        if (args.label == LABEL_AUTO)
7232f167a42Smrg            args.label = LABEL_SYMBOLS;
7240e20ee16Smrg    }
7250e20ee16Smrg    else {
7262f167a42Smrg        fprintf(stderr, "Cannot open \"%s\" to read geometry\n", inputFile);
7272f167a42Smrg        ok = 0;
7280e20ee16Smrg    }
7290e20ee16Smrg    if (ok) {
7302f167a42Smrg        FILE *out = NULL;
7312f167a42Smrg
7322f167a42Smrg        if (setlocale(LC_ALL, (wantLocale)) == NULL) {
7332f167a42Smrg            if (wantLocale != NULL) {
7342f167a42Smrg                uWarning("Couldn't change to locale %s\n", wantLocale);
7352f167a42Smrg                uAction("Using \"C\" locale, instead\n");
7362f167a42Smrg            }
7372f167a42Smrg        }
7382f167a42Smrg        /* need C numerics so decimal point doesn't get screwed up */
7392f167a42Smrg        setlocale(LC_NUMERIC, "C");
7402f167a42Smrg        if ((inDpy != outDpy) &&
7412f167a42Smrg            (XkbChangeKbdDisplay(outDpy, &result) != Success)) {
7422f167a42Smrg            uInternalError("Error converting keyboard display from %s to %s\n",
7432f167a42Smrg                           inDpyName, outDpyName);
7442f167a42Smrg            exit(1);
7452f167a42Smrg        }
7462f167a42Smrg        if (outputFile != NULL) {
7472f167a42Smrg            if (uStringEqual(outputFile, "-")) {
7482f167a42Smrg                static char of[] = "stdout";
7492f167a42Smrg
7502f167a42Smrg                out = stdout;
7512f167a42Smrg                outputFile = of;
7522f167a42Smrg            }
7532f167a42Smrg            else {
7542f167a42Smrg                out = fopen(outputFile, "w");
7552f167a42Smrg                if (out == NULL) {
7562f167a42Smrg                    uError("Cannot open \"%s\" to write keyboard description\n",
7572f167a42Smrg                           outputFile);
7582f167a42Smrg                    uAction("Exiting\n");
7592f167a42Smrg                    exit(1);
7602f167a42Smrg                }
7612f167a42Smrg            }
7622f167a42Smrg        }
7632f167a42Smrg        switch (outputFormat) {
7642f167a42Smrg        case WANT_PS_FILE:
7652f167a42Smrg            ok = GeometryToPostScript(out, &result, &args);
7662f167a42Smrg            break;
7672f167a42Smrg        case WANT_X_SERVER:
7682f167a42Smrg            uInternalError("Output to X server not implemented yet\n");
7692f167a42Smrg            break;
7702f167a42Smrg        default:
7712f167a42Smrg            uInternalError("Unknown output format %d\n", outputFormat);
7722f167a42Smrg            uAction("No output file created\n");
7732f167a42Smrg            ok = False;
7742f167a42Smrg            break;
7752f167a42Smrg        }
7762f167a42Smrg        if (!ok) {
7772f167a42Smrg            uError("Error creating output file\n");
7782f167a42Smrg        }
7790e20ee16Smrg    }
7802f167a42Smrg    if (inDpy)
7812f167a42Smrg        XCloseDisplay(inDpy);
7822f167a42Smrg    inDpy = NULL;
7830e20ee16Smrg    if (outDpy)
7842f167a42Smrg        XCloseDisplay(outDpy);
7852f167a42Smrg    return (ok == 0);
7860e20ee16Smrg}
787