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.
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.
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.
26 ********************************************************/
27 /* $XFree86: xc/programs/xkbprint/xkbprint.c,v 3.10 2003/05/27 22:27:07 tsi Exp $ */
31 #include <X11/Xlocale.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>
44 #define DEBUG_VAR_NOT_LOCAL
45 #define DEBUG_VAR debugFlags
51 /***====================================================================***/
54 #define WANT_DEFAULT 0
55 #define WANT_PS_FILE 1
56 #define WANT_X_SERVER 2
58 #define INPUT_UNKNOWN 0
63 static char *fileTypeExt[] = {
70 static unsigned outputFormat= WANT_DEFAULT;
71 static char * wantLocale= "C";
72 static char * rootDir;
73 static char * inputFile;
74 static char * outputFile;
75 static char * outputFont= NULL;
76 static char * inDpyName,*outDpyName;
77 static Display * inDpy;
78 static Display * outDpy;
80 static Bool computeDflts= False;
82 static XKBPrintArgs args;
83 static unsigned warningLevel= 5;
86 /***====================================================================***/
89 Usage(int argc, char *argv[])
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");
96 fprintf(stderr,"-d [flags] Report debugging information\n");
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");
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");
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");
130 fprintf(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");
135 /***====================================================================***/
138 parseArgs(int argc, char *argv[])
145 args.scaleToFit= True;
146 args.wantColor= False;
147 args.wantSymbols= COMMON_SYMBOLS;
148 args.wantKeycodes= True;
149 args.wantDiffs= False;
151 args.label= LABEL_AUTO;
152 args.baseLabelGroup=0;
153 args.nLabelGroups= 1;
154 args.nTotalGroups= 0;
157 for (i=1;i<argc;i++) {
158 if ((argv[i][0]!='-')||(uStringEqual(argv[i],"-"))) {
159 if (inputFile==NULL) {
162 else if (outputFile==NULL) {
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]);
171 else if ((strcmp(argv[i],"-?")==0)||(strcmp(argv[i],"-help")==0)) {
175 else if (strcmp(argv[i],"-color")==0) {
176 args.wantColor= True;
179 else if (strcmp(argv[i],"-d")==0) {
180 if ((i>=(argc-1))||(!isdigit(argv[i+1][0]))) {
184 sscanf(argv[++i],"%i",&debugFlags);
186 uInformation("Setting debug flags to %d\n",debugFlags);
189 else if (strcmp(argv[i],"-dflts")==0) {
193 uWarning("Compute defaults not implemented yet\n");
195 else if (strcmp(argv[i],"-diffs")==0) {
196 args.wantDiffs= True;
198 else if (strcmp(argv[i],"-eps")==0) {
201 else if (strcmp(argv[i],"-fit")==0) {
202 args.scaleToFit= True;
204 else if (strcmp(argv[i],"-full")==0) {
205 args.scaleToFit= False;
207 else if (strcmp(argv[i],"-grid")==0) {
210 uWarning("Grid frequency not specified\n");
211 uAction("Trailing \"-grid\" option ignored\n");
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);
220 else if (strncmp(argv[i],"-I",2)==0) {
221 if (!XkbAddDirectoryToPath(&argv[i][2])) {
222 uAction("Exiting\n");
225 uInternalError("Includes not implemented yet\n");
228 else if (strcmp(argv[i],"-if")==0) {
230 uWarning("Internal Font name not specified\n");
231 uAction("Trailing \"-if\" option ignored\n");
233 else outputFont= argv[i];
235 else if (strcmp(argv[i],"-kc")==0) {
236 args.wantKeycodes= True;
238 else if (strcmp(argv[i],"-label")==0) {
240 uWarning("Label type not specified\n");
241 uAction("Trailing \"-label\" option ignored\n");
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;
252 uWarning("Unknown label type \"%s\" specified\n",argv[i]);
253 uAction("Ignored\n");
256 else if (strcmp(argv[i],"-lc")==0) {
258 uWarning("Locale not specified\n");
259 uAction("Trailing \"-lc\" option ignored\n");
261 else wantLocale= argv[i];
263 else if (strcmp(argv[i],"-lg")==0) {
266 uWarning("Label group not specified\n");
267 uAction("Trailing \"-lg\" option ignored\n");
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);
273 else args.baseLabelGroup= tmp-1;
275 else if (strcmp(argv[i],"-ll")==0) {
278 uWarning("Label level not specified\n");
279 uAction("Trailing \"-ll\" option ignored\n");
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);
285 else args.labelLevel= tmp-1;
287 else if (strcmp(argv[i],"-level1")==0)
289 else if (strcmp(argv[i],"-level2")==0)
291 else if (strcmp(argv[i],"-mono")==0) {
292 args.wantColor= False;
294 else if (strcmp(argv[i],"-n")==0) {
297 uWarning("Number of copies not specified\n");
298 uAction("Trailing \"-n\" option ignored\n");
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);
304 else args.copies= tmp;
306 else if (strcmp(argv[i],"-nokc")==0) {
307 args.wantKeycodes= False;
309 else if (strcmp(argv[i],"-nkg")==0) {
312 uWarning("Number of groups per key not specified\n");
313 uAction("Trailing \"-nkg\" option ignored\n");
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);
319 else args.nLabelGroups= tmp;
321 else if (strcmp(argv[i],"-npk")==0) {
324 uWarning("Number of keyboards per page not specified\n");
325 uAction("Trailing \"-npk\" option ignored\n");
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);
331 else args.nKBPerPage= tmp;
333 else if (strcmp(argv[i],"-ntg")==0) {
336 uWarning("Total number of groups not specified\n");
337 uAction("Trailing \"-ntg\" option ignored\n");
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);
343 else args.nTotalGroups= tmp;
345 else if (strcmp(argv[i],"-o")==0) {
347 uWarning("No output file specified\n");
348 uAction("Trailing \"-o\" option ignored\n");
350 else if (outputFile!=NULL) {
351 uWarning("Multiple output files specified\n");
352 uAction("Compiling %s, ignoring %s\n",outputFile,argv[i]);
354 else outputFile= argv[i];
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");
361 else if (rootDir!=NULL) {
362 uWarning("Multiple root directories specified\n");
363 uAction("Using %s, ignoring %s\n",rootDir,argv[i]);
365 else rootDir= &argv[i][2];
367 else if (strcmp(argv[i],"-pict")==0) {
369 uWarning("No level of pictographs specified\n");
370 uAction("Trailing \"-pict\" option ignored\n");
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]);
383 else if ((strcmp(argv[i],"-synch")==0)||(strcmp(argv[i],"-s")==0)) {
386 else if (strcmp(argv[i],"-w")==0) {
387 if ((i>=(argc-1))||(!isdigit(argv[i+1][0]))) {
392 if (sscanf(argv[++i],"%i",&itmp))
397 uError("Unknown flag \"%s\" on command line\n",argv[i]);
403 if (warningLevel>8) {
404 uWarning("Changing root directory to \"%s\"\n",rootDir);
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");
411 if (outputFont!=NULL) {
415 if (outputFile==NULL) {
416 outputFile= uAlloc(strlen(outputFont)+5);
417 sprintf(outputFile,"%s.pfa",outputFont);
419 else if (uStringEqual(outputFile,"-"))
423 file= fopen(outputFile,"w");
426 uError("Couldn't open \"%s\" to dump internal font \"%s\"\n",
427 outputFile,outputFont);
428 uAction("Exiting\n");
431 ok= DumpInternalFont(file,outputFont);
435 uWarning("No internal font to dump\n");
437 uAction("Removing \"%s\"\n",outputFile);
443 if (inputFile==NULL) {
444 uError("No input file specified\n");
448 else if (uStringEqual(inputFile,"-")) {
451 else if (strchr(inputFile,':')==NULL) {
452 int len= strlen(inputFile);
453 if ((len>4)&&(strcmp(&inputFile[len-4],".xkm")==0)) {
458 file= fopen(inputFile,"r");
463 fprintf(stderr,"Cannot open \"%s\" for reading\n",inputFile);
469 inDpyName= inputFile;
473 if (outputFormat==WANT_DEFAULT)
474 outputFormat= WANT_PS_FILE;
475 if ((outputFile==NULL)&&(inputFile!=NULL)&&uStringEqual(inputFile,"-")) {
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");
484 if (args.wantEPS) sprintf(outputFile,"stdin.eps");
485 else sprintf(outputFile,"stdin.ps");
487 else if ((outputFile==NULL)&&(inputFile!=NULL)) {
491 base= strrchr(inputFile,'/');
492 if (base==NULL) base= inputFile;
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");
502 ext= strrchr(base,'.');
504 if (args.wantEPS) sprintf(outputFile,"%s.eps",base);
505 else sprintf(outputFile,"%s.ps",base);
508 strcpy(outputFile,base);
509 if (args.wantEPS) strcpy(&outputFile[ext-base+1],"eps");
510 else strcpy(&outputFile[ext-base+1],"ps");
513 else if (outputFile==NULL) {
515 char *ch,*name,buf[128];
516 if (inDpyName[0]==':')
517 sprintf(name=buf,"server%s",inDpyName);
518 else name= inDpyName;
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");
527 strcpy(outputFile,name);
528 for (ch=outputFile;(*ch)!='\0';ch++) {
529 if (*ch==':') *ch= '-';
530 else if (*ch=='.') *ch= '_';
533 if (args.wantEPS) strcpy(ch,"eps");
534 else strcpy(ch,"ps");
536 else if (strchr(outputFile,':')!=NULL) {
537 outDpyName= outputFile;
539 outputFormat= WANT_X_SERVER;
540 uInternalError("Output to an X server not implemented yet\n");
547 GetDisplay(char *program, char *dpyName)
552 mjr= XkbMajorVersion;
553 mnr= XkbMinorVersion;
554 dpy= XkbOpenDisplay(dpyName,NULL,NULL,&mjr,&mnr,&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",
563 case XkbOD_ConnectionRefused:
564 uError("Cannot open display \"%s\"\n",dpyName);
566 case XkbOD_NonXkbServer:
567 uError("XKB extension not present on %s\n",dpyName);
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",
576 uInternalError("Unknown error %d from XkbOpenDisplay\n",error);
580 XSynchronize(dpy,True);
584 /***====================================================================***/
587 #define MAX_INCLUDE_OPTS 10
588 static char *includeOpt[MAX_INCLUDE_OPTS];
589 static int numIncludeOpts = 0;
593 main(int argc, char *argv[])
599 uSetEntryFile(NullString);
600 uSetDebugFile(NullString);
601 uSetErrorFile(NullString);
602 if (!parseArgs(argc,argv))
612 /* XkbInitIncludePath(); */
613 if (inputFile!=NULL) {
614 if (uStringEqual(inputFile,"-")) {
615 static char *in= "stdin";
620 file= fopen(inputFile,"r");
623 else if (inDpyName!=NULL) {
624 inDpy= GetDisplay(argv[0],inDpyName);
626 uAction("Exiting\n");
630 if (outDpyName!=NULL) {
631 uInternalError("Output to an X server not implemented yet\n");
632 outDpy= GetDisplay(argv[0],outDpyName);
634 uAction("Exiting\n");
638 if ((inDpy==NULL) && (outDpy==NULL)) {
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",
647 uAction("Exiting\n");
654 bzero((char *)&result,sizeof(result));
655 if ((result.xkb= XkbAllocKeyboard())==NULL) {
656 uFatalError("Cannot allocate keyboard description\n");
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");
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;
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");
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");
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);
698 ok= (ComputeKbdDefaults(result.xkb)==Success);
701 if (args.label==LABEL_AUTO)
702 args.label= LABEL_SYMBOLS;
705 fprintf(stderr,"Cannot open \"%s\" to read geometry\n",inputFile);
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");
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);
724 if (outputFile!=NULL) {
725 if (uStringEqual(outputFile,"-")) {
726 static char *of= "stdout";
731 out= fopen(outputFile,"w");
733 uError("Cannot open \"%s\" to write keyboard description\n",
735 uAction("Exiting\n");
740 switch (outputFormat) {
742 ok= GeometryToPostScript(out,&result,&args);
745 uInternalError("Output to X server not implemented yet\n");
748 uInternalError("Unknown output format %d\n",outputFormat);
749 uAction("No output file created\n");
754 uError("Error creating output file\n");
758 XCloseDisplay(inDpy);
761 XCloseDisplay(outDpy);