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