psgeom.c revision e6bced22
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#define	XK_TECHNICAL
320e20ee16Smrg#define	XK_PUBLISHING
330e20ee16Smrg#define	XK_KATAKANA
340e20ee16Smrg#include <stdio.h>
350e20ee16Smrg#include <ctype.h>
360e20ee16Smrg#include <X11/X.h>
370e20ee16Smrg#include <X11/Xlib.h>
380e20ee16Smrg#include <X11/XKBlib.h>
390e20ee16Smrg#include <X11/extensions/XKBgeom.h>
400e20ee16Smrg#include <X11/extensions/XKM.h>
410e20ee16Smrg#include <X11/extensions/XKBfile.h>
420e20ee16Smrg#include <X11/keysym.h>
430e20ee16Smrg#include <X11/Xutil.h>
440e20ee16Smrg
450e20ee16Smrg#if defined(sgi)
460e20ee16Smrg#include <malloc.h>
470e20ee16Smrg#endif
480e20ee16Smrg
490e20ee16Smrg#include <stdlib.h>
500e20ee16Smrg
510e20ee16Smrg#include "utils.h"
520e20ee16Smrg#include "xkbprint.h"
530e20ee16Smrg#include "isokeys.h"
540e20ee16Smrg
550e20ee16Smrg#define	FONT_NONE	-1
560e20ee16Smrg#define	FONT_TEXT	0
570e20ee16Smrg#define	FONT_LATIN1	1
580e20ee16Smrg#define	FONT_SYMBOL	2
590e20ee16Smrg#define	FONT_ISOCAPS	3
600e20ee16Smrg#define	FONT_MOUSECAPS	4
610e20ee16Smrg
620e20ee16Smrgtypedef struct {
632f167a42Smrg    Display *           dpy;
642f167a42Smrg    XkbDescPtr          xkb;
652f167a42Smrg    XkbGeometryPtr      geom;
662f167a42Smrg    int                 totalKB;
672f167a42Smrg    int                 kbPerPage;
682f167a42Smrg    int                 black;
692f167a42Smrg    int                 white;
702f167a42Smrg    int                 color;
712f167a42Smrg    int                 font;
722f167a42Smrg    int                 fontSize;
732f167a42Smrg    int                 nPages;
742f167a42Smrg    int                 x1, y1;
752f167a42Smrg    int                 x2, y2;
762f167a42Smrg    XKBPrintArgs *      args;
770e20ee16Smrg} PSState;
780e20ee16Smrg
790e20ee16Smrg#define	G1L1		0
800e20ee16Smrg#define	G1L2		1
810e20ee16Smrg#define	G2L1		2
820e20ee16Smrg#define	G2L2		3
830e20ee16Smrg#define	CENTER		4
840e20ee16Smrg
850e20ee16Smrg#define	G1L1_MASK	(1<<G1L1)
860e20ee16Smrg#define	G1L2_MASK	(1<<G1L2)
870e20ee16Smrg#define	G2L1_MASK	(1<<G2L1)
880e20ee16Smrg#define	G2L2_MASK	(1<<G2L2)
890e20ee16Smrg#define	CENTER_MASK	(1<<CENTER)
900e20ee16Smrg
910e20ee16Smrg#define	LABEL_MASK	(0x1f)
920e20ee16Smrg#define	GXL1_MASK	(G1L1_MASK|G2L1_MASK)
930e20ee16Smrg#define	GXL2_MASK	(G1L2_MASK|G2L2_MASK)
940e20ee16Smrg#define	G1LX_MASK	(G1L1_MASK|G1L2_MASK)
950e20ee16Smrg#define	G2LX_MASK	(G2L1_MASK|G2L2_MASK)
960e20ee16Smrg#define	GXLX_MASK	(0x0f)
970e20ee16Smrg
980e20ee16Smrg#define	NLABELS		5
990e20ee16Smrg#define	LABEL_LEN	30
1000e20ee16Smrg
1010e20ee16Smrg#define	SZ_AUTO		0
1020e20ee16Smrg#define	SZ_TINY		1
1030e20ee16Smrg#define	SZ_SMALL	2
1040e20ee16Smrg#define	SZ_MEDIUM	3
1050e20ee16Smrg#define	SZ_LARGE	4
1060e20ee16Smrg#define	SZ_XLARGE	5
1070e20ee16Smrg
1080e20ee16Smrgtypedef struct {
1092f167a42Smrg    unsigned    present;
1102f167a42Smrg    Bool        alpha[2];
1112f167a42Smrg    char        label[NLABELS][LABEL_LEN];
1122f167a42Smrg    int         font[NLABELS];
1132f167a42Smrg    int         size[NLABELS];
1140e20ee16Smrg} KeyTop;
1150e20ee16Smrg
1160e20ee16Smrg#define	DFLT_LABEL_FONT "Helvetica-Narrow-Bold"
1170e20ee16Smrg#define DFLT_LABEL_FONT_SIZE 10
1180e20ee16Smrg
1190e20ee16Smrg/***====================================================================***/
1200e20ee16Smrg
1210e20ee16Smrgtypedef struct _PSFontDef {
1222f167a42Smrg    const char *name;
1232f167a42Smrg    const char **def;
1240e20ee16Smrg} PSFontDef;
1250e20ee16Smrg
1260e20ee16Smrgstatic PSFontDef internalFonts[] = {
1272f167a42Smrg    { "IsoKeyCaps", &IsoKeyCaps }
1280e20ee16Smrg};
1292f167a42Smrgstatic int nInternalFonts = (sizeof(internalFonts) / sizeof(PSFontDef));
1300e20ee16Smrg
1310e20ee16Smrgstatic void
1320e20ee16SmrgListInternalFonts(FILE *out, int first, int indent)
1330e20ee16Smrg{
1342f167a42Smrg    register int i, n, nThisLine;
1350e20ee16Smrg
1362f167a42Smrg    for (n = 0; n < first; n++) {
1372f167a42Smrg        putc(' ', out);
1380e20ee16Smrg    }
1390e20ee16Smrg
1402f167a42Smrg    for (nThisLine = i = 0; i < nInternalFonts; i++) {
1412f167a42Smrg        if (nThisLine == 4) {
1422f167a42Smrg            fprintf(out, ",\n");
1432f167a42Smrg            for (n = 0; n < indent; n++) {
1442f167a42Smrg                putc(' ', out);
1452f167a42Smrg            }
1462f167a42Smrg            nThisLine = 0;
1472f167a42Smrg        }
1482f167a42Smrg        if (nThisLine == 0)
1492f167a42Smrg            fprintf(out, "%s", internalFonts[i].name);
1502f167a42Smrg        else
1512f167a42Smrg            fprintf(out, ", %s", internalFonts[i].name);
1522f167a42Smrg        nThisLine++;
1530e20ee16Smrg    }
1542f167a42Smrg    if (nThisLine != 0)
1552f167a42Smrg        fprintf(out, "\n");
1560e20ee16Smrg    return;
1570e20ee16Smrg}
1580e20ee16Smrg
1590e20ee16Smrgstatic Bool
1602f167a42SmrgPSIncludeFont(FILE *out, const char *font)
1610e20ee16Smrg{
1622f167a42Smrg    const char **pstr;
1632f167a42Smrg    register int i;
1640e20ee16Smrg
1652f167a42Smrg    pstr = NULL;
1662f167a42Smrg    for (i = 0; (i < nInternalFonts) && (pstr == NULL); i++) {
1672f167a42Smrg        if (uStringEqual(internalFonts[i].name, font))
1682f167a42Smrg            pstr = internalFonts[i].def;
1690e20ee16Smrg    }
1702f167a42Smrg    if (pstr != NULL) {
1712f167a42Smrg        fprintf(out, "%%%%BeginFont: %s\n", font);
1722f167a42Smrg        fprintf(out, "%s", *pstr);
1732f167a42Smrg        fprintf(out, "%%%%EndFont\n");
1742f167a42Smrg        return True;
1750e20ee16Smrg    }
1760e20ee16Smrg    return False;
1770e20ee16Smrg}
1780e20ee16Smrg
1790e20ee16SmrgBool
1802f167a42SmrgDumpInternalFont(FILE *out, const char *fontName)
1810e20ee16Smrg{
1822f167a42Smrg    if (strcmp(fontName, "IsoKeyCaps") != 0) {
1832f167a42Smrg        uError("No internal font named \"%s\"\n", fontName);
1842f167a42Smrg        uAction("No font dumped\n");
1852f167a42Smrg        fprintf(stderr, "Current internal fonts are: ");
1862f167a42Smrg        ListInternalFonts(stderr, 0, 8);
1872f167a42Smrg        return False;
1880e20ee16Smrg    }
1892f167a42Smrg    PSIncludeFont(out, fontName);
1900e20ee16Smrg    return True;
1910e20ee16Smrg}
1920e20ee16Smrg
1930e20ee16Smrg/***====================================================================***/
1940e20ee16Smrg
1950e20ee16Smrgstatic void
1960e20ee16SmrgPSColorDef(FILE *out, PSState *state, XkbColorPtr color)
1970e20ee16Smrg{
1982f167a42Smrg    int tmp;
1990e20ee16Smrg
2002f167a42Smrg    fprintf(out, "/C%03d ", color->pixel);
2012f167a42Smrg    if (uStrCaseEqual(color->spec, "black")) {
2022f167a42Smrg        state->black = color->pixel;
2032f167a42Smrg        fprintf(out, "{ 0 setgray } def      %% %s\n", color->spec);
2040e20ee16Smrg    }
2052f167a42Smrg    else if (uStrCaseEqual(color->spec, "white")) {
2062f167a42Smrg        state->white = color->pixel;
2072f167a42Smrg        fprintf(out, "{ 1 setgray } def      %% %s\n", color->spec);
2080e20ee16Smrg    }
2092f167a42Smrg    else if ((sscanf(color->spec, "grey%d", &tmp) == 1) ||
2102f167a42Smrg             (sscanf(color->spec, "gray%d", &tmp) == 1) ||
2112f167a42Smrg             (sscanf(color->spec, "Grey%d", &tmp) == 1) ||
2122f167a42Smrg             (sscanf(color->spec, "Gray%d", &tmp) == 1)) {
2132f167a42Smrg        fprintf(out, "{ %f setgray } def	    %% %s\n",
2142f167a42Smrg                1.0 - (((float) tmp) / 100.0), color->spec);
2150e20ee16Smrg    }
2162f167a42Smrg    else if ((tmp = (uStrCaseEqual(color->spec, "red") * 100)) ||
2172f167a42Smrg             (sscanf(color->spec, "red%d", &tmp) == 1)) {
2182f167a42Smrg        fprintf(out, "{ %f 0 0 setrgbcolor } def %% %s\n",
2192f167a42Smrg                (((float) tmp) / 100.0), color->spec);
2200e20ee16Smrg    }
2212f167a42Smrg    else if ((tmp = (uStrCaseEqual(color->spec, "green") * 100)) ||
2222f167a42Smrg             (sscanf(color->spec, "green%d", &tmp) == 1)) {
2232f167a42Smrg        fprintf(out, "{ 0 %f 0 setrgbcolor } def %% %s\n",
2242f167a42Smrg                (((float) tmp) / 100.0), color->spec);
2250e20ee16Smrg    }
2262f167a42Smrg    else if ((tmp = (uStrCaseEqual(color->spec, "blue") * 100)) ||
2272f167a42Smrg             (sscanf(color->spec, "blue%d", &tmp) == 1)) {
2282f167a42Smrg        fprintf(out, "{ 0 0 %f setrgbcolor } def %% %s\n",
2292f167a42Smrg                (((float) tmp) / 100.0), color->spec);
2300e20ee16Smrg    }
2312f167a42Smrg    else
2322f167a42Smrg        fprintf(out, "{ 0.9 setgray       } def %% BOGUS! %s\n", color->spec);
2330e20ee16Smrg}
2340e20ee16Smrg
2350e20ee16Smrgstatic void
2362f167a42SmrgPSSetColor(FILE *out, PSState *state, int color)
2370e20ee16Smrg{
2382f167a42Smrg    if ((state->args->wantColor) && (state->color != color)) {
2392f167a42Smrg        fprintf(out, "C%03d %% set color\n", color);
2402f167a42Smrg        state->color = color;
2410e20ee16Smrg    }
2420e20ee16Smrg    return;
2430e20ee16Smrg}
2440e20ee16Smrg
2450e20ee16Smrgstatic void
2460e20ee16SmrgPSGSave(FILE *out, PSState *state)
2470e20ee16Smrg{
2482f167a42Smrg    fprintf(out, "gsave\n");
2490e20ee16Smrg    return;
2500e20ee16Smrg}
2510e20ee16Smrg
2520e20ee16Smrgstatic void
2530e20ee16SmrgPSGRestore(FILE *out, PSState *state)
2540e20ee16Smrg{
2552f167a42Smrg    fprintf(out, "grestore\n");
2562f167a42Smrg    state->color = -1;
2572f167a42Smrg    state->font = FONT_NONE;
2582f167a42Smrg    state->fontSize = -1;
2590e20ee16Smrg    return;
2600e20ee16Smrg}
2610e20ee16Smrg
2620e20ee16Smrgstatic void
2630e20ee16SmrgPSShapeDef(FILE *out, PSState *state, XkbShapePtr shape)
2640e20ee16Smrg{
2652f167a42Smrg    int o, p;
2662f167a42Smrg    XkbOutlinePtr ol;
2672f167a42Smrg
268e6bced22Smrg    {
269e6bced22Smrg        char *a = XkbAtomGetString(state->dpy, shape->name);
270e6bced22Smrg        fprintf(out, "/%s {\n", a);
271e6bced22Smrg        XFree(a);
272e6bced22Smrg    }
2732f167a42Smrg    fprintf(out, "	gsave translate rotate /SOLID exch def\n");
2742f167a42Smrg    for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
2752f167a42Smrg        XkbPointPtr pt;
2762f167a42Smrg
2772f167a42Smrg        if ((shape->num_outlines > 1) && (ol == shape->approx))
2782f167a42Smrg            continue;
2792f167a42Smrg        pt = ol->points;
2802f167a42Smrg        fprintf(out, "%%	Outline %d\n", o + 1);
2812f167a42Smrg        if (ol->num_points == 1) {
2822f167a42Smrg            if (ol->corner_radius < 1) {
2832f167a42Smrg                fprintf(out, "	  0   0 moveto\n");
2842f167a42Smrg                fprintf(out, "	%3d   0 lineto\n", pt->x);
2852f167a42Smrg                fprintf(out, "	%3d %3d lineto\n", pt->x, pt->y);
2862f167a42Smrg                fprintf(out, "	  0 %3d lineto\n", pt->y);
2872f167a42Smrg                fprintf(out, "	  0   0 lineto\n");
2882f167a42Smrg                fprintf(out, "	SOLID { fill } { stroke } ifelse\n");
2892f167a42Smrg            }
2902f167a42Smrg            else {
2912f167a42Smrg                fprintf(out, "	mark\n");
2922f167a42Smrg                fprintf(out, "	%3d   0 moveto\n", ol->corner_radius);
2932f167a42Smrg                fprintf(out, "	%3d   0 %3d %3d %3d arcto\n", pt->x, pt->x,
2942f167a42Smrg                        pt->y, ol->corner_radius);
2952f167a42Smrg                fprintf(out, "	%3d %3d   0 %3d %3d arcto\n", pt->x, pt->y,
2962f167a42Smrg                        pt->y, ol->corner_radius);
2972f167a42Smrg                fprintf(out, "	  0 %3d   0   0 %3d arcto\n", pt->y,
2982f167a42Smrg                        ol->corner_radius);
2992f167a42Smrg                fprintf(out, "     0   0 %3d   0 %3d arcto\n", pt->x,
3002f167a42Smrg                        ol->corner_radius);
3012f167a42Smrg                fprintf(out, "	SOLID { fill } { stroke } ifelse\n");
3022f167a42Smrg                fprintf(out, "	cleartomark\n");
3032f167a42Smrg            }
3042f167a42Smrg        }
3052f167a42Smrg        else if (ol->num_points == 2) {
3062f167a42Smrg            if (ol->corner_radius < 1) {
3072f167a42Smrg                fprintf(out, "	%3d %3d moveto\n", pt[0].x, pt[0].y);
3082f167a42Smrg                fprintf(out, "	%3d %3d lineto\n", pt[1].x, pt[0].y);
3092f167a42Smrg                fprintf(out, "	%3d %3d lineto\n", pt[1].x, pt[1].y);
3102f167a42Smrg                fprintf(out, "	%3d %3d lineto\n", pt[0].x, pt[1].y);
3112f167a42Smrg                fprintf(out, "	%3d %3d lineto\n", pt[0].x, pt[0].y);
3122f167a42Smrg                fprintf(out, "	SOLID { fill } { stroke } ifelse\n");
3132f167a42Smrg            }
3142f167a42Smrg            else {
3152f167a42Smrg                fprintf(out, "	mark\n");
3162f167a42Smrg                fprintf(out, "	%3d %3d moveto\n", pt[0].x + ol->corner_radius,
3172f167a42Smrg                        pt[0].y);
3182f167a42Smrg                fprintf(out, "	%3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[0].y,
3192f167a42Smrg                        pt[1].x, pt[1].y, ol->corner_radius);
3202f167a42Smrg                fprintf(out, "	%3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[1].y,
3212f167a42Smrg                        pt[0].x, pt[1].y, ol->corner_radius);
3222f167a42Smrg                fprintf(out, "	%3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[1].y,
3232f167a42Smrg                        pt[0].x, pt[0].y, ol->corner_radius);
3242f167a42Smrg                fprintf(out, "   %3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[0].y,
3252f167a42Smrg                        pt[1].x, pt[0].y, ol->corner_radius);
3262f167a42Smrg                fprintf(out, "	SOLID { fill } { stroke } ifelse\n");
3272f167a42Smrg                fprintf(out, "	cleartomark\n");
3282f167a42Smrg            }
3292f167a42Smrg        }
3302f167a42Smrg        else {
3312f167a42Smrg            if (ol->corner_radius < 1) {
3322f167a42Smrg                fprintf(out, "	%3d %3d moveto\n", pt->x, pt->y);
3332f167a42Smrg                pt++;
3342f167a42Smrg                for (p = 1; p < ol->num_points; p++, pt++) {
3352f167a42Smrg                    fprintf(out, "	%3d %3d lineto\n", pt->x, pt->y);
3362f167a42Smrg                }
3372f167a42Smrg                if ((pt->x != ol->points[0].x) || (pt->y != ol->points[0].y))
3382f167a42Smrg                    fprintf(out, "	closepath\n");
3392f167a42Smrg                fprintf(out, "	SOLID { fill } { stroke } ifelse\n");
3402f167a42Smrg            }
3412f167a42Smrg            else {
3422f167a42Smrg                XkbPointPtr last;
3432f167a42Smrg
3442f167a42Smrg                last = &pt[ol->num_points - 1];
3452f167a42Smrg                if ((last->x == pt->x) && (last->y == pt->y))
3462f167a42Smrg                    last--;
3472f167a42Smrg                fprintf(out, "	mark\n");
3482f167a42Smrg                fprintf(out, "	%% Determine tangent point of first corner\n");
3492f167a42Smrg                fprintf(out, "	%3d %3d moveto %d %d %d %d %d arcto\n",
3502f167a42Smrg                        last->x, last->y,
3512f167a42Smrg                        pt[0].x, pt[0].y, pt[1].x, pt[1].y, ol->corner_radius);
3522f167a42Smrg                fprintf(out, "	/TY exch def /TX exch def pop pop newpath\n");
3532f167a42Smrg                fprintf(out, "	%% Now draw the shape\n");
3542f167a42Smrg                fprintf(out, "	TX TY moveto\n");
3552f167a42Smrg                for (p = 1; p < ol->num_points; p++) {
3562f167a42Smrg                    if (p < (ol->num_points - 1))
3572f167a42Smrg                        last = &pt[p + 1];
3582f167a42Smrg                    else
3592f167a42Smrg                        last = &pt[0];
3602f167a42Smrg                    fprintf(out, "	%3d %3d %3d %3d %3d arcto\n",
3612f167a42Smrg                            pt[p].x, pt[p].y,
3622f167a42Smrg                            last->x, last->y, ol->corner_radius);
3632f167a42Smrg                }
3642f167a42Smrg                last = &pt[ol->num_points - 1];
3652f167a42Smrg                if ((last->x != pt->x) || (last->y != pt->y)) {
3662f167a42Smrg                    fprintf(out, "	%3d %3d %3d %3d %3d arcto\n",
3672f167a42Smrg                            pt[0].x, pt[0].y,
3682f167a42Smrg                            pt[1].x, pt[1].y, ol->corner_radius);
3692f167a42Smrg                }
3702f167a42Smrg                fprintf(out, "	SOLID { fill } { stroke } ifelse\n");
3712f167a42Smrg                fprintf(out, "	cleartomark\n");
3722f167a42Smrg            }
3732f167a42Smrg        }
3740e20ee16Smrg    }
3752f167a42Smrg    fprintf(out, "	grestore\n");
3762f167a42Smrg    fprintf(out, "} def\n");
3770e20ee16Smrg    return;
3780e20ee16Smrg}
3790e20ee16Smrg
3800e20ee16Smrg/***====================================================================***/
3810e20ee16Smrg
3822f167a42Smrgtypedef struct {
3832f167a42Smrg    char *      foundry;
3842f167a42Smrg    char *      face;
3852f167a42Smrg    char *      weight;
3862f167a42Smrg    char *      slant;
3872f167a42Smrg    char *      setWidth;
3882f167a42Smrg    char *      variant;
3892f167a42Smrg    int         pixelSize;
3902f167a42Smrg    int         ptSize;
3912f167a42Smrg    int         resX;
3922f167a42Smrg    int         resY;
3932f167a42Smrg    char *      spacing;
3942f167a42Smrg    int         avgWidth;
3952f167a42Smrg    char *      encoding;
3960e20ee16Smrg} FontStuff;
3970e20ee16Smrg
3980e20ee16Smrgstatic void
3990e20ee16SmrgClearFontStuff(FontStuff *stuff)
4000e20ee16Smrg{
4010e20ee16Smrg    if (stuff && stuff->foundry)
4022f167a42Smrg        free(stuff->foundry);
4032f167a42Smrg    bzero(stuff, sizeof(FontStuff));
4040e20ee16Smrg    return;
4050e20ee16Smrg}
4060e20ee16Smrg
4070e20ee16Smrgstatic Bool
4082f167a42SmrgCrackXLFDName(const char *name, FontStuff *stuff)
4090e20ee16Smrg{
4102f167a42Smrg    char *tmp;
4112f167a42Smrg
4122f167a42Smrg    if ((name == NULL) || (stuff == NULL))
4132f167a42Smrg        return False;
4142f167a42Smrg    if (name[0] == '-')
4152f167a42Smrg        tmp = strdup(&name[1]);
4162f167a42Smrg    else
4172f167a42Smrg        tmp = strdup(name);
4182f167a42Smrg    if (tmp == NULL)
4192f167a42Smrg        return False;
4202f167a42Smrg    stuff->foundry = tmp;
4212f167a42Smrg
4222f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4232f167a42Smrg        goto BAILOUT;
4242f167a42Smrg    else
4252f167a42Smrg        *tmp++ = '\0';
4262f167a42Smrg    stuff->face = tmp;
4272f167a42Smrg
4282f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4292f167a42Smrg        goto BAILOUT;
4302f167a42Smrg    else
4312f167a42Smrg        *tmp++ = '\0';
4322f167a42Smrg    stuff->weight = tmp;
4332f167a42Smrg
4342f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4352f167a42Smrg        goto BAILOUT;
4362f167a42Smrg    else
4372f167a42Smrg        *tmp++ = '\0';
4382f167a42Smrg    stuff->slant = tmp;
4392f167a42Smrg
4402f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4412f167a42Smrg        goto BAILOUT;
4422f167a42Smrg    else
4432f167a42Smrg        *tmp++ = '\0';
4442f167a42Smrg    stuff->setWidth = tmp;
4452f167a42Smrg
4462f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4472f167a42Smrg        goto BAILOUT;
4482f167a42Smrg    else
4492f167a42Smrg        *tmp++ = '\0';
4502f167a42Smrg    stuff->variant = tmp;
4512f167a42Smrg
4522f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4532f167a42Smrg        goto BAILOUT;
4542f167a42Smrg    else
4552f167a42Smrg        *tmp++ = '\0';
4562f167a42Smrg    if (*tmp == '*')
4572f167a42Smrg        stuff->pixelSize = 0;
4582f167a42Smrg    else if (sscanf(tmp, "%i", &stuff->pixelSize) != 1)
4592f167a42Smrg        goto BAILOUT;
4602f167a42Smrg
4612f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4622f167a42Smrg        goto BAILOUT;
4632f167a42Smrg    else
4642f167a42Smrg        *tmp++ = '\0';
4652f167a42Smrg    if (*tmp == '*')
4662f167a42Smrg        stuff->ptSize = 0;
4672f167a42Smrg    else if (sscanf(tmp, "%i", &stuff->ptSize) != 1)
4682f167a42Smrg        goto BAILOUT;
4692f167a42Smrg
4702f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4712f167a42Smrg        goto BAILOUT;
4722f167a42Smrg    else
4732f167a42Smrg        *tmp++ = '\0';
4742f167a42Smrg    if (*tmp == '*')
4752f167a42Smrg        stuff->resX = 0;
4762f167a42Smrg    else if (sscanf(tmp, "%i", &stuff->resX) != 1)
4772f167a42Smrg        goto BAILOUT;
4782f167a42Smrg
4792f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4802f167a42Smrg        goto BAILOUT;
4812f167a42Smrg    else
4822f167a42Smrg        *tmp++ = '\0';
4832f167a42Smrg    if (*tmp == '*')
4842f167a42Smrg        stuff->resY = 0;
4852f167a42Smrg    else if (sscanf(tmp, "%i", &stuff->resY) != 1)
4862f167a42Smrg        goto BAILOUT;
4872f167a42Smrg
4882f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4892f167a42Smrg        goto BAILOUT;
4902f167a42Smrg    else
4912f167a42Smrg        *tmp++ = '\0';
4922f167a42Smrg    stuff->spacing = tmp;
4932f167a42Smrg
4942f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
4952f167a42Smrg        goto BAILOUT;
4962f167a42Smrg    else
4972f167a42Smrg        *tmp++ = '\0';
4982f167a42Smrg    if (*tmp == '*')
4992f167a42Smrg        stuff->avgWidth = 0;
5002f167a42Smrg    else if (sscanf(tmp, "%i", &stuff->avgWidth) != 1)
5012f167a42Smrg        goto BAILOUT;
5022f167a42Smrg
5032f167a42Smrg    if ((tmp = strchr(tmp, '-')) == NULL)
5042f167a42Smrg        goto BAILOUT;
5052f167a42Smrg    else
5062f167a42Smrg        *tmp++ = '\0';
5072f167a42Smrg    stuff->encoding = tmp;
5080e20ee16Smrg    return True;
5092f167a42Smrg BAILOUT:
5100e20ee16Smrg    ClearFontStuff(stuff);
5110e20ee16Smrg    return False;
5120e20ee16Smrg}
5130e20ee16Smrg
5140e20ee16Smrgstatic void
5150e20ee16SmrgPSSetUpForLatin1(FILE *out, PSState *state)
5160e20ee16Smrg{
5172f167a42Smrg    fprintf(out, "%s",
5182f167a42Smrg            "save\n"
5192f167a42Smrg            "/ISOLatin1Encoding where {pop save true}{false} ifelse\n"
5202f167a42Smrg            "/ISOLatin1Encoding [\n"
5212f167a42Smrg            "   /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
5222f167a42Smrg            "   /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
5232f167a42Smrg            "   /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
5242f167a42Smrg            "   /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
5252f167a42Smrg            "   /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
5262f167a42Smrg            "   /.notdef /.notdef /space /exclam /quotedbl /numbersign\n"
5272f167a42Smrg            "   /dollar /percent /ampersand /quoteright /parenleft\n"
5282f167a42Smrg            "   /parenright /asterisk /plus /comma /minus /period\n"
5292f167a42Smrg            "   /slash /zero /one /two /three /four /five /six /seven\n"
5302f167a42Smrg            "   /eight /nine /colon /semicolon /less /equal /greater\n"
5312f167a42Smrg            "   /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M\n"
5322f167a42Smrg            "   /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n"
5332f167a42Smrg            "   /backslash /bracketright /asciicircum /underscore\n"
5342f167a42Smrg            "   /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m\n"
5352f167a42Smrg            "   /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft\n"
5362f167a42Smrg            "   /bar /braceright /asciitilde /guilsinglright /fraction\n"
5372f167a42Smrg            "   /florin /quotesingle /quotedblleft /guilsinglleft /fi\n"
5382f167a42Smrg            "   /fl /endash /dagger /daggerdbl /bullet /quotesinglbase\n"
5392f167a42Smrg            "   /quotedblbase /quotedblright /ellipsis /trademark\n"
5402f167a42Smrg            "   /perthousand /grave /scaron /circumflex /Scaron /tilde\n"
5412f167a42Smrg            "   /breve /zcaron /dotaccent /dotlessi /Zcaron /ring\n"
5422f167a42Smrg            "   /hungarumlaut /ogonek /caron /emdash /space /exclamdown\n"
5432f167a42Smrg            "   /cent /sterling /currency /yen /brokenbar /section\n"
5442f167a42Smrg            "   /dieresis /copyright /ordfeminine /guillemotleft\n"
5452f167a42Smrg            "   /logicalnot /hyphen /registered /macron /degree\n"
5462f167a42Smrg            "   /plusminus /twosuperior /threesuperior /acute /mu\n"
5472f167a42Smrg            "   /paragraph /periodcentered /cedilla /onesuperior\n"
5482f167a42Smrg            "   /ordmasculine /guillemotright /onequarter /onehalf\n"
5492f167a42Smrg            "   /threequarters /questiondown /Agrave /Aacute\n"
5502f167a42Smrg            "   /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
5512f167a42Smrg            "   /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute\n"
5522f167a42Smrg            "   /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute\n"
5532f167a42Smrg            "   /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n"
5542f167a42Smrg            "   /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n"
5552f167a42Smrg            "   /germandbls /agrave /aacute /acircumflex /atilde\n"
5562f167a42Smrg            "   /adieresis /aring /ae /ccedilla /egrave /eacute\n"
5572f167a42Smrg            "   /ecircumflex /edieresis /igrave /iacute /icircumflex\n"
5582f167a42Smrg            "   /idieresis /eth /ntilde /ograve /oacute /ocircumflex\n"
5592f167a42Smrg            "   /otilde /odieresis /divide /oslash /ugrave /uacute\n"
5602f167a42Smrg            "   /ucircumflex /udieresis /yacute /thorn /ydieresis\n"
5612f167a42Smrg            "] def {restore} if\n"
5622f167a42Smrg            "/reencodeISO-1 {\n"
5632f167a42Smrg            "    dup length dict begin\n"
5642f167a42Smrg            "        {1 index /FID ne {def}{pop pop} ifelse} forall\n"
5652f167a42Smrg            "        /Encoding ISOLatin1Encoding def\n"
5662f167a42Smrg            "        currentdict\n"
5672f167a42Smrg            "    end\n"
5682f167a42Smrg            "} def\n"
5692f167a42Smrg        );
5700e20ee16Smrg}
5710e20ee16Smrg
5720e20ee16Smrgstatic void
5732f167a42SmrgPSReencodeLatin1Font(FILE *out, const char *font)
5740e20ee16Smrg{
5752f167a42Smrg    fprintf(out, "/%s findfont reencodeISO-1\n", font);
5762f167a42Smrg    fprintf(out, "	/%s-8859-1 exch definefont pop\n", font);
5770e20ee16Smrg    return;
5780e20ee16Smrg}
5790e20ee16Smrg
5800e20ee16Smrgstatic void
5812f167a42SmrgPSSetUpFonts(FILE *out, const char *textFont, int size)
5820e20ee16Smrg{
5832f167a42Smrg    fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n",
5842f167a42Smrg            FONT_TEXT, textFont);
5852f167a42Smrg    fprintf(out, "/F%d { /%s-8859-1 findfont exch scalefont setfont } def\n",
5862f167a42Smrg            FONT_LATIN1, textFont);
5872f167a42Smrg    fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n",
5882f167a42Smrg            FONT_SYMBOL, "Symbol");
5892f167a42Smrg    fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n",
5902f167a42Smrg            FONT_ISOCAPS, "IsoKeyCaps");
5910e20ee16Smrg    return;
5920e20ee16Smrg}
5930e20ee16Smrg
5940e20ee16Smrgstatic void
5950e20ee16SmrgPSSetFont(FILE *out, PSState *state, int font, int size, int pts)
5960e20ee16Smrg{
5972f167a42Smrg    if ((state->font != font) || (state->fontSize != size)) {
5982f167a42Smrg        fprintf(out, "%d %sF%d\n", size, (pts ? "pts " : ""), font);
5992f167a42Smrg        state->font = font;
6002f167a42Smrg        state->fontSize = size;
6010e20ee16Smrg    }
6020e20ee16Smrg    return;
6030e20ee16Smrg}
6040e20ee16Smrg
6050e20ee16Smrgstatic void
6060e20ee16SmrgPSProlog(FILE *out, PSState *state)
6070e20ee16Smrg{
6082f167a42Smrg    register int i;
6090e20ee16Smrg
6100e20ee16Smrg    if (!state->args->wantEPS) {
6112f167a42Smrg        fprintf(out,
6122f167a42Smrg                "%%!PS-Adobe-2.0\n"
6132f167a42Smrg                "%%%%Creator: xkbprint\n");
614e6bced22Smrg        if (state->geom->name != None) {
615e6bced22Smrg            char *a = XkbAtomGetString(state->dpy, state->geom->name);
616e6bced22Smrg            fprintf(out, "%%%%Title: %s\n", a);
617e6bced22Smrg            XFree(a);
618e6bced22Smrg        }
6192f167a42Smrg        fprintf(out,
6202f167a42Smrg                "%%%%BoundingBox: (atend)\n"
6212f167a42Smrg                "%%%%Pages: 1\n"
6222f167a42Smrg                "%%%%PageOrder: Ascend\n"
6232f167a42Smrg                "%%%%DocumentFonts: (atend)\n"
6242f167a42Smrg                "%%%%DocumentData: Clean7Bit\n"
6252f167a42Smrg                "%%%%Orientation: Landscape\n"
6262f167a42Smrg                "%%%%EndComments\n"
6272f167a42Smrg                "%%%%BeginProlog\n"
6282f167a42Smrg                "%% Resolution is 1/10mm -- need pt sizes for fonts\n"
6292f167a42Smrg                "clippath pathbbox\n"
6302f167a42Smrg                "    /ury exch def /urx exch def\n"
6312f167a42Smrg                "    /llx exch def /lly exch def\n"
6322f167a42Smrg                "    newpath\n"
6332f167a42Smrg                "/devwidth  urx llx sub def\n"
6342f167a42Smrg                "/devheight ury lly sub def\n");
6350e20ee16Smrg    }
6360e20ee16Smrg    else {
6372f167a42Smrg        int w, h;
6382f167a42Smrg        int pw, ph;
6392f167a42Smrg
6402f167a42Smrg        w = (((state->geom->width_mm * 72) / 254) * 11) / 10;
6412f167a42Smrg        h = (((state->geom->height_mm * 72) / 254) * 11) / 10;
6422f167a42Smrg        if (state->kbPerPage > 1)
6432f167a42Smrg            h *= (state->kbPerPage + 1);
6442f167a42Smrg
6452f167a42Smrg        if (w <= h) {
6462f167a42Smrg            pw = 7.5 * 72;
6472f167a42Smrg            ph = 10 * 72;
6482f167a42Smrg        }
6492f167a42Smrg        else {
6502f167a42Smrg            pw = 10 * 72;
6512f167a42Smrg            ph = 7.5 * 72;
6522f167a42Smrg        }
6532f167a42Smrg        while ((w > pw) || (h > ph)) {
6542f167a42Smrg            w = (w * 9) / 10;
6552f167a42Smrg            h = (h * 9) / 10;
6562f167a42Smrg        }
6572f167a42Smrg
6582f167a42Smrg        fprintf(out, "%%!PS-Adobe-2.0 EPSF-2.0\n");
6592f167a42Smrg        fprintf(out, "%%%%BoundingBox: 0 0 %d %d\n", w, h);
6602f167a42Smrg        fprintf(out, "%%%%Creator: xkbprint\n");
661e6bced22Smrg        if (state->geom->name != None) {
662e6bced22Smrg            char *a = XkbAtomGetString(state->dpy, state->geom->name);
663e6bced22Smrg            fprintf(out, "%%%%Title: %s\n", a);
664e6bced22Smrg            XFree(a);
665e6bced22Smrg        }
6662f167a42Smrg        fprintf(out, "%%%%Pages: 1\n");
6672f167a42Smrg        fprintf(out, "%%%%EndComments\n");
6682f167a42Smrg        fprintf(out, "%%%%BeginProlog\n");
6692f167a42Smrg        fprintf(out, "/ury 0 def /urx 0 def\n");
6702f167a42Smrg        fprintf(out, "/llx %d def /lly %d def\n", w, h);
6712f167a42Smrg        fprintf(out, "/devwidth %d def /devheight %d def\n", w, h);
6720e20ee16Smrg    }
6732f167a42Smrg    fprintf(out, "/kbdwidth %d def\n", state->geom->width_mm);
6742f167a42Smrg    fprintf(out, "/kbdheight %d def\n", state->geom->height_mm);
6752f167a42Smrg    fprintf(out, "%s",
6762f167a42Smrg            "/pts { 254 mul 72 div } def\n"
6772f167a42Smrg            "/mm10 { 72 mul 254 div } def\n"
6782f167a42Smrg            "/landscape? {\n"
6792f167a42Smrg            "	devheight devwidth gt {\n"
6802f167a42Smrg            "		/pwidth devheight def /pheight devwidth def\n"
6812f167a42Smrg            "		0 devheight translate\n"
6822f167a42Smrg            "		-90 rotate\n"
6832f167a42Smrg            "	} {\n"
6842f167a42Smrg            "		/pwidth devwidth def /pheight devheight def\n"
6852f167a42Smrg            "	} ifelse\n"
6862f167a42Smrg            "	0 pheight translate\n"
6872f167a42Smrg            "	1 -1 scale\n"
6882f167a42Smrg            "} def\n"
6892f167a42Smrg            "/centeroffset {\n"
6902f167a42Smrg            "    /S     exch def\n"
6912f167a42Smrg            "    /HEIGHT exch def\n"
6922f167a42Smrg            "    /WIDTH exch def\n"
6932f167a42Smrg            "    S stringwidth /SH exch def /SW exch def\n"
6942f167a42Smrg            "    WIDTH SW sub 2 div\n"
6952f167a42Smrg            "    HEIGHT SH sub 2 div\n"
6962f167a42Smrg            "} def\n");
6972f167a42Smrg    PSSetUpForLatin1(out, state);
6982f167a42Smrg    PSReencodeLatin1Font(out, DFLT_LABEL_FONT);
6990e20ee16Smrg    if (state->args->wantColor) {
7002f167a42Smrg        XkbGeometryPtr geom = state->geom;
7012f167a42Smrg
7022f167a42Smrg        for (i = 0; i < geom->num_colors; i++) {
7032f167a42Smrg            PSColorDef(out, state, &geom->colors[i]);
7042f167a42Smrg        }
7052f167a42Smrg        if (state->black < 0) {
7062f167a42Smrg            XkbColorPtr color;
7072f167a42Smrg
7082f167a42Smrg            if (!(color = XkbAddGeomColor(geom, "black", geom->num_colors)))
7092f167a42Smrg                uFatalError("Couldn't allocate black color!\n");
7102f167a42Smrg            PSColorDef(out, state, color);
7112f167a42Smrg        }
7122f167a42Smrg        if (state->white < 0) {
7132f167a42Smrg            XkbColorPtr color;
7142f167a42Smrg
7152f167a42Smrg            if (!(color = XkbAddGeomColor(geom, "white", geom->num_colors)))
7162f167a42Smrg                uFatalError("Couldn't allocate white color!\n");
7172f167a42Smrg            PSColorDef(out, state, color);
7182f167a42Smrg        }
7190e20ee16Smrg    }
7202f167a42Smrg    for (i = 0; i < state->geom->num_shapes; i++) {
7212f167a42Smrg        PSShapeDef(out, state, &state->geom->shapes[i]);
7220e20ee16Smrg    }
7232f167a42Smrg    if (state->args->label == LABEL_SYMBOLS) {
7242f167a42Smrg        PSIncludeFont(out, "IsoKeyCaps");
7250e20ee16Smrg    }
7262f167a42Smrg    PSSetUpFonts(out, DFLT_LABEL_FONT, DFLT_LABEL_FONT_SIZE);
7272f167a42Smrg    fprintf(out, "%%%%EndProlog\n");
7280e20ee16Smrg    return;
7290e20ee16Smrg}
7300e20ee16Smrg
7310e20ee16Smrgstatic void
7320e20ee16SmrgPSFileTrailer(FILE *out, PSState *state)
7330e20ee16Smrg{
7342f167a42Smrg    fprintf(out, "restore\n");
7350e20ee16Smrg    if (!state->args->wantEPS)
7362f167a42Smrg        fprintf(out, "%%%%Trailer\n");
7372f167a42Smrg    fprintf(out, "%%%%EOF\n");
7380e20ee16Smrg    return;
7390e20ee16Smrg}
7400e20ee16Smrg
7410e20ee16Smrgstatic void
7420e20ee16SmrgPSPageSetup(FILE *out, PSState *state, Bool drawBorder)
7430e20ee16Smrg{
7442f167a42Smrg    XkbGeometryPtr geom;
7450e20ee16Smrg
7462f167a42Smrg    geom = state->geom;
7472f167a42Smrg    if (state->kbPerPage == 1) {
7482f167a42Smrg        fprintf(out, "%%%%Page: %d %d\n", state->nPages + 1, state->nPages + 1);
7492f167a42Smrg        fprintf(out, "%%%%BeginPageSetup\n");
7500e20ee16Smrg    }
7512f167a42Smrg    else if ((state->nPages & 1) == 0) {        /* even page */
7522f167a42Smrg        int realPage;
7532f167a42Smrg
7542f167a42Smrg        realPage = state->nPages / 2 + 1;
7552f167a42Smrg        fprintf(out, "%%%%Page: %d %d\n", realPage, realPage);
7562f167a42Smrg        fprintf(out, "%%%%BeginPageSetup\n");
7572f167a42Smrg        fprintf(out, "%% Keyboard %d\n", state->nPages + 1);
7582f167a42Smrg        if (state->nPages == 0) {
7592f167a42Smrg            fprintf(out,
7602f167a42Smrg                    "/realwidth devwidth def\n"
7612f167a42Smrg                    "/realheight devheight def\n"
7622f167a42Smrg                    "/devheight realheight 3 div def\n");
7632f167a42Smrg        }
7642f167a42Smrg        fprintf(out, "0 devheight dup 2 div add translate\n");
7650e20ee16Smrg    }
7662f167a42Smrg    else {
7672f167a42Smrg        fprintf(out, "%% Keyboard %d\n", state->nPages + 1);
7680e20ee16Smrg    }
7692f167a42Smrg    fprintf(out, "save\n");
7702f167a42Smrg    fprintf(out, "landscape?\n");
7710e20ee16Smrg    if (state->args->scaleToFit) {
7722f167a42Smrg        fprintf(out,
7732f167a42Smrg                "%% Scale keyboard to fit on the page\n"
7742f167a42Smrg                "/kbdscale pwidth 72 sub kbdwidth div def\n"
7752f167a42Smrg                "/kbdscalewidth kbdwidth kbdscale mul def\n"
7762f167a42Smrg                "/kbdscaleheight kbdheight kbdscale mul def\n"
7772f167a42Smrg                "/kbx 36 def\n"
7782f167a42Smrg                "/kby pheight kbdscaleheight sub 2 div def\n");
7792f167a42Smrg        PSGSave(out, state);
7802f167a42Smrg        fprintf(out,
7812f167a42Smrg                "kbx kby translate\n"
7822f167a42Smrg                "kbdscale kbdscale scale\n");
7830e20ee16Smrg    }
7840e20ee16Smrg    else {
7852f167a42Smrg        fprintf(out,
7862f167a42Smrg                "%% Draw keyboard full size\n"
7872f167a42Smrg                "/kbdscale 1 def\n"
7882f167a42Smrg                "/kbdscalewidth kbdwidth mm10 def\n"
7892f167a42Smrg                "/kbdscaleheight kbdheight mm10 def\n"
7902f167a42Smrg                "/kbx pwidth kbdscalewidth sub 2 div def\n"
7912f167a42Smrg                "/kby pheight kbdscaleheight sub 2 div def\n");
7922f167a42Smrg        PSGSave(out, state);
7932f167a42Smrg        fprintf(out,
7942f167a42Smrg                "kbx kby translate\n"
7952f167a42Smrg                "72 254 div dup scale\n");
7960e20ee16Smrg    }
7970e20ee16Smrg    if (drawBorder) {
7982f167a42Smrg        if (state->args->wantColor) {
7992f167a42Smrg            PSSetColor(out, state, geom->base_color->pixel);
8002f167a42Smrg            fprintf(out, "  0   0 moveto\n");
8012f167a42Smrg            fprintf(out, "%3d   0 lineto\n", geom->width_mm);
8022f167a42Smrg            fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm);
8032f167a42Smrg            fprintf(out, "  0 %3d lineto\n", geom->height_mm);
8042f167a42Smrg            fprintf(out, "closepath fill\n");
8052f167a42Smrg        }
8062f167a42Smrg        PSSetColor(out, state, state->black);
8072f167a42Smrg        fprintf(out, "  0   0 moveto\n");
8082f167a42Smrg        fprintf(out, "%3d   0 lineto\n", geom->width_mm);
8092f167a42Smrg        fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm);
8102f167a42Smrg        fprintf(out, "  0 %3d lineto\n", geom->height_mm);
8112f167a42Smrg        fprintf(out, "closepath stroke\n");
8120e20ee16Smrg    }
8132f167a42Smrg    fprintf(out, "%%%%EndPageSetup\n");
8140e20ee16Smrg    return;
8150e20ee16Smrg}
8160e20ee16Smrg
8170e20ee16Smrgstatic void
8180e20ee16SmrgPSPageTrailer(FILE *out, PSState *state)
8190e20ee16Smrg{
8202f167a42Smrg    char *name;
8212f167a42Smrg    XkbDescPtr xkb;
8222f167a42Smrg    XkbGeometryPtr geom;
8232f167a42Smrg    XkbPropertyPtr prop;
8242f167a42Smrg    int p, baseline;
8252f167a42Smrg
8262f167a42Smrg    xkb = state->xkb;
8272f167a42Smrg    geom = state->geom;
8282f167a42Smrg    if (state->args->grid > 0) {
8292f167a42Smrg        fprintf(out, "%% Draw a %dmm grid\n", state->args->grid);
8302f167a42Smrg        fprintf(out, "0 setlinewidth\n");
8312f167a42Smrg        fprintf(out, "0.25 setgray\n");
8322f167a42Smrg        fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->width_mm);
8332f167a42Smrg        fprintf(out, "    /GX exch def\n");
8342f167a42Smrg        fprintf(out, "    GX 0 moveto GX %d lineto stroke\n", geom->height_mm);
8352f167a42Smrg        fprintf(out, "} for\n");
8362f167a42Smrg        fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->height_mm);
8372f167a42Smrg        fprintf(out, "    /GY exch def\n");
8382f167a42Smrg        fprintf(out, "    0 GY moveto %d GY lineto stroke\n", geom->width_mm);
8392f167a42Smrg        fprintf(out, "} for\n");
8400e20ee16Smrg    }
8412f167a42Smrg    PSGRestore(out, state);
8422f167a42Smrg    name = NULL;
8432f167a42Smrg    for (p = 0, prop = geom->properties; p < geom->num_properties; p++, prop++) {
8442f167a42Smrg        if ((prop->value != NULL) && (uStrCaseEqual(prop->name, "description"))) {
8452f167a42Smrg            name = prop->value;
8462f167a42Smrg            break;
8472f167a42Smrg        }
8480e20ee16Smrg    }
8492f167a42Smrg    if ((!state->args->wantEPS) &&
8502f167a42Smrg        ((state->kbPerPage == 1) || ((state->nPages & 1) == 1) ||
8512f167a42Smrg         (state->nPages == state->totalKB))) {
852e6bced22Smrg        char *a1 = NULL;
853e6bced22Smrg
8542f167a42Smrg        if ((name == NULL) && (geom->name != None))
855e6bced22Smrg            name = a1 = XkbAtomGetString(state->dpy, geom->name);
8562f167a42Smrg
8572f167a42Smrg        baseline = 16;
8582f167a42Smrg        if ((name != NULL) || (state->args->label == LABEL_SYMBOLS)) {
8592f167a42Smrg            PSSetColor(out, state, state->black);
8602f167a42Smrg            PSSetFont(out, state, FONT_LATIN1, 14, False);
8612f167a42Smrg        }
8622f167a42Smrg        if (state->args->label == LABEL_SYMBOLS) {
8632f167a42Smrg            char buf[40], *lbuf;
8642f167a42Smrg            const char *sName = NULL;
865e6bced22Smrg            char *a2 = NULL;
8662f167a42Smrg            Atom sAtom;
8672f167a42Smrg
8682f167a42Smrg            if (state->args->nLabelGroups == 1)
8692f167a42Smrg                snprintf(buf, sizeof(buf), "Group %d",
8702f167a42Smrg                         state->args->baseLabelGroup + 1);
8712f167a42Smrg            else
8722f167a42Smrg                snprintf(buf, sizeof(buf), "Groups %d-%d",
8732f167a42Smrg                         state->args->baseLabelGroup + 1,
8742f167a42Smrg                         state->args->baseLabelGroup +
8752f167a42Smrg                         state->args->nLabelGroups);
8762f167a42Smrg            fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
8772f167a42Smrg                    buf);
8782f167a42Smrg            fprintf(out, "    kby kbdscaleheight add %d add\n", baseline);
8792f167a42Smrg            fprintf(out, "    moveto\n");
8802f167a42Smrg            fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf);
8812f167a42Smrg            baseline += 16;
8822f167a42Smrg
8832f167a42Smrg            if (xkb->names != NULL)
8842f167a42Smrg                sAtom = xkb->names->symbols;
8852f167a42Smrg            else
8862f167a42Smrg                sAtom = None;
8872f167a42Smrg            if (sAtom != None)
888e6bced22Smrg                sName = a2 = XkbAtomGetString(state->dpy, sAtom);
8892f167a42Smrg            if (sName == NULL)
8902f167a42Smrg                sName = "(unknown)";
8912f167a42Smrg
8922f167a42Smrg            if (asprintf(&lbuf, "Layout: %s", sName) == -1) {
8932f167a42Smrg                uFatalError("Can't allocate memory for string\n");
8942f167a42Smrg            }
8952f167a42Smrg            fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
8962f167a42Smrg                    lbuf);
8972f167a42Smrg            fprintf(out, "    kby kbdscaleheight add %d add\n", baseline);
8982f167a42Smrg            fprintf(out, "    moveto\n");
8992f167a42Smrg            fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf);
9002f167a42Smrg            baseline += 16;
9012f167a42Smrg            free(lbuf);
902e6bced22Smrg            XFree(a2);
9032f167a42Smrg        }
9042f167a42Smrg        if (name != NULL) {
9052f167a42Smrg            fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
9062f167a42Smrg                    name);
9072f167a42Smrg            fprintf(out, "    kby kbdscaleheight add %d add\n", baseline);
9082f167a42Smrg            fprintf(out, "    moveto\n");
9092f167a42Smrg            fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", name);
9102f167a42Smrg            baseline += 16;
911e6bced22Smrg            name = NULL;
912e6bced22Smrg            XFree(a1);
9132f167a42Smrg        }
9142f167a42Smrg        if (state->args->label == LABEL_KEYCODE) {
9152f167a42Smrg            const char *sName = NULL;
9162f167a42Smrg            char *lbuf;
917e6bced22Smrg            char *a3 = NULL;
9182f167a42Smrg            Atom sAtom;
9192f167a42Smrg
9202f167a42Smrg            if (xkb->names != NULL)
9212f167a42Smrg                sAtom = xkb->names->keycodes;
9222f167a42Smrg            else
9232f167a42Smrg                sAtom = None;
9242f167a42Smrg            if (sAtom != None)
925e6bced22Smrg                sName = a3 = XkbAtomGetString(state->dpy, sAtom);
9262f167a42Smrg            if (sName == NULL)
9272f167a42Smrg                sName = "(unknown)";
9282f167a42Smrg
9292f167a42Smrg            if (asprintf(&lbuf, "Keycodes: %s", sName) == -1) {
9302f167a42Smrg                uFatalError("Can't allocate memory for string\n");
9312f167a42Smrg            }
9322f167a42Smrg            fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
9332f167a42Smrg                    lbuf);
9342f167a42Smrg            fprintf(out, "    kby kbdscaleheight add %d add\n", baseline);
9352f167a42Smrg            fprintf(out, "    moveto\n");
9362f167a42Smrg            fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf);
9372f167a42Smrg            baseline += 16;
9382f167a42Smrg            free(lbuf);
939e6bced22Smrg            XFree(a3);
9402f167a42Smrg        }
9412f167a42Smrg        if (state->args->copies > 1) {
9422f167a42Smrg            for (p = 1; p < state->args->copies; p++)
9432f167a42Smrg                fprintf(out, "copypage\n");
9442f167a42Smrg        }
9452f167a42Smrg        fprintf(out, "showpage\n");
9462f167a42Smrg        fprintf(out, "restore\n");
9472f167a42Smrg        fprintf(out, "%% Done with keyboard/page %d\n", state->nPages + 1);
9480e20ee16Smrg    }
9490e20ee16Smrg    else {
9502f167a42Smrg        if ((!state->args->wantEPS) && (state->args->label == LABEL_SYMBOLS)) {
9512f167a42Smrg            char buf[40];
9522f167a42Smrg
9532f167a42Smrg            baseline = 16;
9542f167a42Smrg            PSSetColor(out, state, state->black);
9552f167a42Smrg            PSSetFont(out, state, FONT_LATIN1, 14, False);
9562f167a42Smrg            if (state->args->nLabelGroups == 1)
9572f167a42Smrg                snprintf(buf, sizeof(buf), "Group %d",
9582f167a42Smrg                         state->args->baseLabelGroup + 1);
9592f167a42Smrg            else
9602f167a42Smrg                snprintf(buf, sizeof(buf), "Groups %d-%d",
9612f167a42Smrg                         state->args->baseLabelGroup + 1,
9622f167a42Smrg                         state->args->baseLabelGroup +
9632f167a42Smrg                         state->args->nLabelGroups + 1);
9642f167a42Smrg            fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
9652f167a42Smrg                    buf);
9662f167a42Smrg            fprintf(out, "    kby kbdscaleheight add %d add\n", baseline);
9672f167a42Smrg            fprintf(out, "    moveto\n");
9682f167a42Smrg            fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf);
9692f167a42Smrg            baseline += 16;
9702f167a42Smrg        }
9712f167a42Smrg        fprintf(out, "restore\n");
9722f167a42Smrg        fprintf(out, "%% Done with keyboard %d\n", state->nPages + 1);
9732f167a42Smrg        fprintf(out, "0 devheight -1 mul translate %% next keyboard\n");
9740e20ee16Smrg    }
9750e20ee16Smrg    state->nPages++;
9762f167a42Smrg    state->color = state->black;
9772f167a42Smrg    state->font = -1;
9780e20ee16Smrg    return;
9790e20ee16Smrg}
9800e20ee16Smrg
9810e20ee16Smrgstatic void
9820e20ee16SmrgPSDoodad(FILE *out, PSState *state, XkbDoodadPtr doodad)
9830e20ee16Smrg{
9842f167a42Smrg    XkbDescPtr xkb;
9852f167a42Smrg    const char *name, *dname;
986e6bced22Smrg    char *a1 = NULL, *a2 = NULL;
9872f167a42Smrg    int sz, leading;
9882f167a42Smrg
9892f167a42Smrg    xkb = state->xkb;
9902f167a42Smrg    if (doodad->any.name != None)
991e6bced22Smrg        dname = a1 = XkbAtomGetString(xkb->dpy, doodad->any.name);
9922f167a42Smrg    else
9932f167a42Smrg        dname = "NoName";
9940e20ee16Smrg    switch (doodad->any.type) {
9952f167a42Smrg    case XkbOutlineDoodad:
9962f167a42Smrg    case XkbSolidDoodad:
997e6bced22Smrg        name = a2 = XkbAtomGetString(xkb->dpy,
9982f167a42Smrg                                XkbShapeDoodadShape(xkb->geom,
9992f167a42Smrg                                                    &doodad->shape)->name);
10002f167a42Smrg        if (state->args->wantColor) {
10012f167a42Smrg            PSSetColor(out, state, doodad->shape.color_ndx);
10022f167a42Smrg            if (doodad->any.type != XkbOutlineDoodad) {
10032f167a42Smrg                fprintf(out, "true %d %d %d %s %% Doodad %s\n",
10042f167a42Smrg                        doodad->shape.angle,
10052f167a42Smrg                        doodad->shape.left, doodad->shape.top, name, dname);
10062f167a42Smrg                PSSetColor(out, state, state->black);
10072f167a42Smrg            }
10082f167a42Smrg            fprintf(out, "false %d %d %d %s %% Doodad %s\n",
10092f167a42Smrg                    doodad->shape.angle,
10102f167a42Smrg                    doodad->shape.left, doodad->shape.top, name, dname);
10112f167a42Smrg        }
10122f167a42Smrg        else {
10132f167a42Smrg            fprintf(out, "false %d %d %d %s %% Doodad %s\n",
10142f167a42Smrg                    doodad->shape.angle,
10152f167a42Smrg                    doodad->shape.left, doodad->shape.top, name, dname);
10162f167a42Smrg        }
1017e6bced22Smrg        name = NULL;
1018e6bced22Smrg        XFree(a2);
10192f167a42Smrg        break;
10202f167a42Smrg    case XkbTextDoodad:
10212f167a42Smrg        fprintf(out, "%% Doodad %s\n", dname);
10222f167a42Smrg        PSSetColor(out, state, doodad->text.color_ndx);
10232f167a42Smrg        PSGSave(out, state);
10242f167a42Smrg        fprintf(out, "%d %d translate\n", doodad->text.left, doodad->text.top);
10252f167a42Smrg        if (doodad->text.angle != 0)
10262f167a42Smrg            fprintf(out, "%s rotate\n",
10272f167a42Smrg                    XkbGeomFPText(doodad->text.angle, XkbMessage));
10282f167a42Smrg        sz = 14;
10292f167a42Smrg        if (doodad->text.font) {
10302f167a42Smrg            FontStuff stuff;
10312f167a42Smrg
10322f167a42Smrg            if (CrackXLFDName(doodad->text.font, &stuff)) {
10332f167a42Smrg                if (stuff.ptSize > 0)
10342f167a42Smrg                    sz = stuff.ptSize / 10;
10352f167a42Smrg                ClearFontStuff(&stuff);
10362f167a42Smrg            }
10372f167a42Smrg        }
10382f167a42Smrg        PSSetFont(out, state, FONT_LATIN1, sz, True);
10392f167a42Smrg        leading = (sz * 12) / 10;
10402f167a42Smrg        if (strchr(doodad->text.text, '\n') == NULL) {
10412f167a42Smrg            fprintf(out, "0 %d pts moveto 1 -1 scale\n", (leading * 8) / 10);
10422f167a42Smrg            fprintf(out, "(%s) show\n", doodad->text.text);
10432f167a42Smrg        }
10442f167a42Smrg        else {
10452f167a42Smrg            char *tmp, *buf, *end;
10462f167a42Smrg            int offset = (leading * 8 / 10);
10472f167a42Smrg
10482f167a42Smrg            tmp = buf = strdup(doodad->text.text);
10492f167a42Smrg            while (tmp != NULL) {
10502f167a42Smrg                end = strchr(tmp, '\n');
10512f167a42Smrg                if (end != NULL)
10522f167a42Smrg                    *end++ = '\0';
10532f167a42Smrg                fprintf(out, "0 %d pts moveto 1 -1 scale\n", offset);
10542f167a42Smrg                fprintf(out, "(%s) show 1 -1 scale\n", tmp);
10552f167a42Smrg                offset += leading;
10562f167a42Smrg                tmp = end;
10572f167a42Smrg            }
10582f167a42Smrg            free(buf);
10592f167a42Smrg        }
10602f167a42Smrg        PSGRestore(out, state);
10612f167a42Smrg        break;
10622f167a42Smrg    case XkbIndicatorDoodad:
1063e6bced22Smrg        name = a2 = XkbAtomGetString(xkb->dpy,
10642f167a42Smrg                                XkbIndicatorDoodadShape(xkb->geom,
10652f167a42Smrg                                                        &doodad->indicator)->
10662f167a42Smrg                                name);
10672f167a42Smrg        if (state->args->wantColor) {
10682f167a42Smrg            PSSetColor(out, state, doodad->indicator.off_color_ndx);
10692f167a42Smrg            fprintf(out, "true 0 %d %d %s %% Doodad %s\n",
10702f167a42Smrg                    doodad->indicator.left, doodad->indicator.top, name, dname);
10712f167a42Smrg            PSSetColor(out, state, state->black);
10722f167a42Smrg        }
10732f167a42Smrg        fprintf(out, "false 0 %d %d %s %% Doodad %s\n",
10742f167a42Smrg                doodad->indicator.left, doodad->indicator.top, name, dname);
1075e6bced22Smrg        name = NULL;
1076e6bced22Smrg        XFree(a2);
10772f167a42Smrg        break;
10782f167a42Smrg    case XkbLogoDoodad:
1079e6bced22Smrg        name = a2 = XkbAtomGetString(xkb->dpy,
10802f167a42Smrg                                XkbLogoDoodadShape(xkb->geom,
10812f167a42Smrg                                                   &doodad->logo)->name);
10822f167a42Smrg        if (state->args->wantColor)
10832f167a42Smrg            PSSetColor(out, state, doodad->shape.color_ndx);
10842f167a42Smrg        fprintf(out, "false %d %d %d %s %% Doodad %s\n",
10852f167a42Smrg                doodad->shape.angle,
10862f167a42Smrg                doodad->shape.left, doodad->shape.top, name, dname);
1087e6bced22Smrg        name = NULL;
1088e6bced22Smrg        XFree(a2);
10892f167a42Smrg        break;
10900e20ee16Smrg    }
1091e6bced22Smrg    XFree(a1);
10920e20ee16Smrg    return;
10930e20ee16Smrg}
10940e20ee16Smrg
10950e20ee16Smrg/***====================================================================***/
10960e20ee16Smrg
10970e20ee16Smrgstatic Bool
10982f167a42SmrgPSKeycapsSymbol(KeySym sym, unsigned char *buf,
10992f167a42Smrg                int *font_rtrn, int *sz_rtrn, PSState *state)
11000e20ee16Smrg{
11012f167a42Smrg    if (state->args->wantSymbols == NO_SYMBOLS)
11022f167a42Smrg        return False;
11032f167a42Smrg
11042f167a42Smrg    if (font_rtrn != NULL)
11052f167a42Smrg        *font_rtrn = FONT_ISOCAPS;
11062f167a42Smrg    if (sz_rtrn != NULL)
11072f167a42Smrg        *sz_rtrn = SZ_LARGE;
11082f167a42Smrg    buf[1] = '\0';
11090e20ee16Smrg    switch (sym) {
11102f167a42Smrg    case XK_Shift_L:
11112f167a42Smrg    case XK_Shift_R:
11122f167a42Smrg        buf[0] = XKC_ISO_Shift;
11132f167a42Smrg        return True;
11142f167a42Smrg    case XK_Shift_Lock:
11152f167a42Smrg        buf[0] = XKC_ISO_Shift_Lock;
11162f167a42Smrg        return True;
11172f167a42Smrg    case XK_ISO_Lock:
11182f167a42Smrg        buf[0] = XKC_ISO_Caps_Lock;
11192f167a42Smrg        return True;
11202f167a42Smrg    case XK_BackSpace:
11212f167a42Smrg        buf[0] = XKC_ISO_Backspace;
11222f167a42Smrg        return True;
11232f167a42Smrg    case XK_Return:
11242f167a42Smrg        buf[0] = XKC_ISO_Return;
11252f167a42Smrg        return True;
11262f167a42Smrg    case XK_Up:
11272f167a42Smrg    case XK_KP_Up:
11282f167a42Smrg        buf[0] = XKC_ISO_Up;
11292f167a42Smrg        return True;
11302f167a42Smrg    case XK_Down:
11312f167a42Smrg    case XK_KP_Down:
11322f167a42Smrg        buf[0] = XKC_ISO_Down;
11332f167a42Smrg        return True;
11342f167a42Smrg    case XK_Left:
11352f167a42Smrg    case XK_KP_Left:
11362f167a42Smrg        buf[0] = XKC_ISO_Left;
11372f167a42Smrg        return True;
11382f167a42Smrg    case XK_Right:
11392f167a42Smrg    case XK_KP_Right:
11402f167a42Smrg        buf[0] = XKC_ISO_Right;
11412f167a42Smrg        return True;
11422f167a42Smrg    case XK_Tab:
11432f167a42Smrg        buf[0] = XKC_ISO_Tab;
11442f167a42Smrg        return True;
11452f167a42Smrg    case XK_ISO_Left_Tab:
11462f167a42Smrg        buf[0] = XKC_ISO_Left_Tab;
11472f167a42Smrg        return True;
11480e20ee16Smrg    }
11492f167a42Smrg    if (state->args->wantSymbols != ALL_SYMBOLS)
11502f167a42Smrg        return False;
11510e20ee16Smrg    switch (sym) {
11522f167a42Smrg    case XK_Caps_Lock:
11532f167a42Smrg        buf[0] = XKC_ISO_Caps_Lock;
11542f167a42Smrg        return True;
11552f167a42Smrg    case XK_Num_Lock:
11562f167a42Smrg        buf[0] = XKC_ISO_Num_Lock;
11572f167a42Smrg        return True;
11582f167a42Smrg    case XK_ISO_Level3_Shift:
11592f167a42Smrg        buf[0] = XKC_ISO_Level3_Shift;
11602f167a42Smrg        return True;
11612f167a42Smrg    case XK_ISO_Level3_Lock:
11622f167a42Smrg        buf[0] = XKC_ISO_Level3_Lock;
11632f167a42Smrg        return True;
11642f167a42Smrg    case XK_ISO_Next_Group:
11652f167a42Smrg    case XK_ISO_Group_Shift:
11662f167a42Smrg        buf[0] = XKC_ISO_Next_Group;
11672f167a42Smrg        return True;
11682f167a42Smrg    case XK_ISO_Next_Group_Lock:
11692f167a42Smrg        buf[0] = XKC_ISO_Next_Group_Lock;
11702f167a42Smrg        return True;
11712f167a42Smrg    case XK_space:
11722f167a42Smrg        buf[0] = XKC_ISO_Space;
11732f167a42Smrg        return True;
11742f167a42Smrg    case XK_nobreakspace:
11752f167a42Smrg        buf[0] = XKC_ISO_No_Break_Space;
11762f167a42Smrg        return True;
11772f167a42Smrg    case XK_Insert:
11782f167a42Smrg        buf[0] = XKC_ISO_Insert;
11792f167a42Smrg        return True;
11802f167a42Smrg    case XK_ISO_Continuous_Underline:
11812f167a42Smrg        buf[0] = XKC_ISO_Continuous_Underline;
11822f167a42Smrg        return True;
11832f167a42Smrg    case XK_ISO_Discontinuous_Underline:
11842f167a42Smrg        buf[0] = XKC_ISO_Discontinuous_Underline;
11852f167a42Smrg        return True;
11862f167a42Smrg    case XK_ISO_Emphasize:
11872f167a42Smrg        buf[0] = XKC_ISO_Emphasize;
11882f167a42Smrg        return True;
11892f167a42Smrg    case XK_Multi_key:
11902f167a42Smrg        buf[0] = XKC_ISO_Compose;
11912f167a42Smrg        return True;
11922f167a42Smrg    case XK_ISO_Center_Object:
11932f167a42Smrg        buf[0] = XKC_ISO_Center_Object;
11942f167a42Smrg        return True;
11952f167a42Smrg    case XK_Delete:
11962f167a42Smrg        buf[0] = XKC_ISO_Delete;
11972f167a42Smrg        return True;
11982f167a42Smrg    case XK_Clear:
11992f167a42Smrg        buf[0] = XKC_ISO_Clear_Screen;
12002f167a42Smrg        return True;
12012f167a42Smrg    case XK_Scroll_Lock:
12022f167a42Smrg        buf[0] = XKC_ISO_Scroll_Lock;
12032f167a42Smrg        return True;
12042f167a42Smrg    case XK_Help:
12052f167a42Smrg        buf[0] = XKC_ISO_Help;
12062f167a42Smrg        return True;
12072f167a42Smrg    case XK_Print:
12082f167a42Smrg        buf[0] = XKC_ISO_Print_Screen;
12092f167a42Smrg        return True;
12102f167a42Smrg    case XK_ISO_Enter:
12112f167a42Smrg        buf[0] = XKC_ISO_Enter;
12122f167a42Smrg        return True;
12132f167a42Smrg    case XK_Alt_L:
12142f167a42Smrg    case XK_Alt_R:
12152f167a42Smrg        buf[0] = XKC_ISO_Alt;
12162f167a42Smrg        return True;
12172f167a42Smrg    case XK_Control_L:
12182f167a42Smrg    case XK_Control_R:
12192f167a42Smrg        buf[0] = XKC_ISO_Control;
12202f167a42Smrg        return True;
12212f167a42Smrg    case XK_Pause:
12222f167a42Smrg        buf[0] = XKC_ISO_Pause;
12232f167a42Smrg        return True;
12242f167a42Smrg    case XK_Break:
12252f167a42Smrg        buf[0] = XKC_ISO_Break;
12262f167a42Smrg        return True;
12272f167a42Smrg    case XK_Escape:
12282f167a42Smrg        buf[0] = XKC_ISO_Escape;
12292f167a42Smrg        return True;
12302f167a42Smrg    case XK_Undo:
12312f167a42Smrg        buf[0] = XKC_ISO_Undo;
12322f167a42Smrg        return True;
12332f167a42Smrg    case XK_ISO_Fast_Cursor_Up:
12342f167a42Smrg        buf[0] = XKC_ISO_Fast_Cursor_Up;
12352f167a42Smrg        return True;
12362f167a42Smrg    case XK_ISO_Fast_Cursor_Down:
12372f167a42Smrg        buf[0] = XKC_ISO_Fast_Cursor_Down;
12382f167a42Smrg        return True;
12392f167a42Smrg    case XK_ISO_Fast_Cursor_Left:
12402f167a42Smrg        buf[0] = XKC_ISO_Fast_Cursor_Left;
12412f167a42Smrg        return True;
12422f167a42Smrg    case XK_ISO_Fast_Cursor_Right:
12432f167a42Smrg        buf[0] = XKC_ISO_Fast_Cursor_Right;
12442f167a42Smrg        return True;
12452f167a42Smrg    case XK_Home:
12462f167a42Smrg        buf[0] = XKC_ISO_Home;
12472f167a42Smrg        return True;
12482f167a42Smrg    case XK_End:
12492f167a42Smrg        buf[0] = XKC_ISO_End;
12502f167a42Smrg        return True;
12512f167a42Smrg    case XK_Page_Up:
12522f167a42Smrg        buf[0] = XKC_ISO_Page_Up;
12532f167a42Smrg        return True;
12542f167a42Smrg    case XK_Page_Down:
12552f167a42Smrg        buf[0] = XKC_ISO_Page_Down;
12562f167a42Smrg        return True;
12572f167a42Smrg    case XK_ISO_Move_Line_Up:
12582f167a42Smrg        buf[0] = XKC_ISO_Move_Line_Up;
12592f167a42Smrg        return True;
12602f167a42Smrg    case XK_ISO_Move_Line_Down:
12612f167a42Smrg        buf[0] = XKC_ISO_Move_Line_Down;
12622f167a42Smrg        return True;
12632f167a42Smrg    case XK_ISO_Partial_Line_Up:
12642f167a42Smrg        buf[0] = XKC_ISO_Partial_Line_Up;
12652f167a42Smrg        return True;
12662f167a42Smrg    case XK_ISO_Partial_Line_Down:
12672f167a42Smrg        buf[0] = XKC_ISO_Partial_Line_Down;
12682f167a42Smrg        return True;
12692f167a42Smrg    case XK_ISO_Partial_Space_Left:
12702f167a42Smrg        buf[0] = XKC_ISO_Partial_Space_Left;
12712f167a42Smrg        return True;
12722f167a42Smrg    case XK_ISO_Partial_Space_Right:
12732f167a42Smrg        buf[0] = XKC_ISO_Partial_Space_Right;
12742f167a42Smrg        return True;
12752f167a42Smrg    case XK_ISO_Set_Margin_Left:
12762f167a42Smrg        buf[0] = XKC_ISO_Set_Margin_Left;
12772f167a42Smrg        return True;
12782f167a42Smrg    case XK_ISO_Set_Margin_Right:
12792f167a42Smrg        buf[0] = XKC_ISO_Set_Margin_Right;
12802f167a42Smrg        return True;
12812f167a42Smrg    case XK_ISO_Release_Margin_Left:
12822f167a42Smrg        buf[0] = XKC_ISO_Release_Margin_Left;
12832f167a42Smrg        return True;
12842f167a42Smrg    case XK_ISO_Release_Margin_Right:
12852f167a42Smrg        buf[0] = XKC_ISO_Release_Margin_Right;
12862f167a42Smrg        return True;
12872f167a42Smrg    case XK_ISO_Release_Both_Margins:
12882f167a42Smrg        buf[0] = XKC_ISO_Release_Both_Margins;
12892f167a42Smrg        return True;
12902f167a42Smrg    case XK_ISO_Prev_Group:
12912f167a42Smrg        buf[0] = XKC_ISO_Prev_Group;
12922f167a42Smrg        return True;
12932f167a42Smrg    case XK_ISO_Prev_Group_Lock:
12942f167a42Smrg        buf[0] = XKC_ISO_Prev_Group_Lock;
12952f167a42Smrg        return True;
12960e20ee16Smrg    }
12970e20ee16Smrg    return False;
12980e20ee16Smrg}
12990e20ee16Smrg
13000e20ee16Smrgstatic Bool
13010e20ee16SmrgPSNonLatin1Symbol(KeySym sym, unsigned char *buf,
13022f167a42Smrg                  int *font_rtrn, int *sz_rtrn, PSState *state)
13030e20ee16Smrg{
13042f167a42Smrg    if (state->args->wantSymbols == NO_SYMBOLS)
13052f167a42Smrg        return False;
13062f167a42Smrg
13072f167a42Smrg    if (font_rtrn != NULL)
13082f167a42Smrg        *font_rtrn = FONT_TEXT;
13092f167a42Smrg    if (sz_rtrn != NULL)
13102f167a42Smrg        *sz_rtrn = SZ_LARGE;
13112f167a42Smrg    buf[1] = '\0';
13120e20ee16Smrg    switch (sym) {
13132f167a42Smrg    case XK_breve:
13142f167a42Smrg        buf[0] = 0xC6;
13152f167a42Smrg        return True;
13162f167a42Smrg    case XK_abovedot:
13172f167a42Smrg        buf[0] = 0xC7;
13182f167a42Smrg        return True;
13192f167a42Smrg    case XK_doubleacute:
13202f167a42Smrg        buf[0] = 0xCD;
13212f167a42Smrg        return True;
13222f167a42Smrg    case XK_ogonek:
13232f167a42Smrg        buf[0] = 0xCE;
13242f167a42Smrg        return True;
13252f167a42Smrg    case XK_caron:
13262f167a42Smrg        buf[0] = 0xCF;
13272f167a42Smrg        return True;
13282f167a42Smrg    case XK_Lstroke:
13292f167a42Smrg        buf[0] = 0xE8;
13302f167a42Smrg        return True;
13312f167a42Smrg    case XK_idotless:
13322f167a42Smrg        buf[0] = 0xF5;
13332f167a42Smrg        return True;
13342f167a42Smrg    case XK_lstroke:
13352f167a42Smrg        buf[0] = 0xF8;
13362f167a42Smrg        return True;
13370e20ee16Smrg    }
13382f167a42Smrg    if (font_rtrn != NULL)
13392f167a42Smrg        *font_rtrn = FONT_SYMBOL;
13402f167a42Smrg    if (sz_rtrn != NULL)
13412f167a42Smrg        *sz_rtrn = SZ_MEDIUM;
13422f167a42Smrg    if ((sym & (~0xffUL)) == 0x700) {
13432f167a42Smrg        switch (sym) {
13442f167a42Smrg            /* Greek symbol */
13452f167a42Smrg        case XK_Greek_ALPHA:
13462f167a42Smrg            buf[0] = 0x41;
13472f167a42Smrg            return True;
13482f167a42Smrg        case XK_Greek_BETA:
13492f167a42Smrg            buf[0] = 0x42;
13502f167a42Smrg            return True;
13512f167a42Smrg        case XK_Greek_CHI:
13522f167a42Smrg            buf[0] = 0x43;
13532f167a42Smrg            return True;
13542f167a42Smrg        case XK_Greek_DELTA:
13552f167a42Smrg            buf[0] = 0x44;
13562f167a42Smrg            return True;
13572f167a42Smrg        case XK_Greek_EPSILON:
13582f167a42Smrg            buf[0] = 0x45;
13592f167a42Smrg            return True;
13602f167a42Smrg        case XK_Greek_PHI:
13612f167a42Smrg            buf[0] = 0x46;
13622f167a42Smrg            return True;
13632f167a42Smrg        case XK_Greek_GAMMA:
13642f167a42Smrg            buf[0] = 0x47;
13652f167a42Smrg            return True;
13662f167a42Smrg        case XK_Greek_ETA:
13672f167a42Smrg            buf[0] = 0x48;
13682f167a42Smrg            return True;
13692f167a42Smrg        case XK_Greek_IOTA:
13702f167a42Smrg            buf[0] = 0x49;
13712f167a42Smrg            return True;
13722f167a42Smrg        case XK_Greek_KAPPA:
13732f167a42Smrg            buf[0] = 0x4B;
13742f167a42Smrg            return True;
13752f167a42Smrg        case XK_Greek_LAMDA:
13762f167a42Smrg            buf[0] = 0x4C;
13772f167a42Smrg            return True;
13782f167a42Smrg        case XK_Greek_MU:
13792f167a42Smrg            buf[0] = 0x4D;
13802f167a42Smrg            return True;
13812f167a42Smrg        case XK_Greek_NU:
13822f167a42Smrg            buf[0] = 0x4E;
13832f167a42Smrg            return True;
13842f167a42Smrg        case XK_Greek_OMICRON:
13852f167a42Smrg            buf[0] = 0x4F;
13862f167a42Smrg            return True;
13872f167a42Smrg        case XK_Greek_PI:
13882f167a42Smrg            buf[0] = 0x50;
13892f167a42Smrg            return True;
13902f167a42Smrg        case XK_Greek_THETA:
13912f167a42Smrg            buf[0] = 0x51;
13922f167a42Smrg            return True;
13932f167a42Smrg        case XK_Greek_RHO:
13942f167a42Smrg            buf[0] = 0x52;
13952f167a42Smrg            return True;
13962f167a42Smrg        case XK_Greek_SIGMA:
13972f167a42Smrg            buf[0] = 0x53;
13982f167a42Smrg            return True;
13992f167a42Smrg        case XK_Greek_TAU:
14002f167a42Smrg            buf[0] = 0x54;
14012f167a42Smrg            return True;
14022f167a42Smrg        case XK_Greek_UPSILON:
14032f167a42Smrg            buf[0] = 0x55;
14042f167a42Smrg            return True;
14052f167a42Smrg        case XK_Greek_OMEGA:
14062f167a42Smrg            buf[0] = 0x57;
14072f167a42Smrg            return True;
14082f167a42Smrg        case XK_Greek_XI:
14092f167a42Smrg            buf[0] = 0x58;
14102f167a42Smrg            return True;
14112f167a42Smrg        case XK_Greek_PSI:
14122f167a42Smrg            buf[0] = 0x59;
14132f167a42Smrg            return True;
14142f167a42Smrg        case XK_Greek_ZETA:
14152f167a42Smrg            buf[0] = 0x5A;
14162f167a42Smrg            return True;
14172f167a42Smrg
14182f167a42Smrg        case XK_Greek_alpha:
14192f167a42Smrg            buf[0] = 0x61;
14202f167a42Smrg            return True;
14212f167a42Smrg        case XK_Greek_beta:
14222f167a42Smrg            buf[0] = 0x62;
14232f167a42Smrg            return True;
14242f167a42Smrg        case XK_Greek_chi:
14252f167a42Smrg            buf[0] = 0x63;
14262f167a42Smrg            return True;
14272f167a42Smrg        case XK_Greek_delta:
14282f167a42Smrg            buf[0] = 0x64;
14292f167a42Smrg            return True;
14302f167a42Smrg        case XK_Greek_epsilon:
14312f167a42Smrg            buf[0] = 0x65;
14322f167a42Smrg            return True;
14332f167a42Smrg        case XK_Greek_phi:
14342f167a42Smrg            buf[0] = 0x66;
14352f167a42Smrg            return True;
14362f167a42Smrg        case XK_Greek_gamma:
14372f167a42Smrg            buf[0] = 0x67;
14382f167a42Smrg            return True;
14392f167a42Smrg        case XK_Greek_eta:
14402f167a42Smrg            buf[0] = 0x68;
14412f167a42Smrg            return True;
14422f167a42Smrg        case XK_Greek_iota:
14432f167a42Smrg            buf[0] = 0x69;
14442f167a42Smrg            return True;
14452f167a42Smrg        case XK_Greek_kappa:
14462f167a42Smrg            buf[0] = 0x6B;
14472f167a42Smrg            return True;
14482f167a42Smrg        case XK_Greek_lamda:
14492f167a42Smrg            buf[0] = 0x6C;
14502f167a42Smrg            return True;
14512f167a42Smrg        case XK_Greek_mu:
14522f167a42Smrg            buf[0] = 0x6D;
14532f167a42Smrg            return True;
14542f167a42Smrg        case XK_Greek_nu:
14552f167a42Smrg            buf[0] = 0x6E;
14562f167a42Smrg            return True;
14572f167a42Smrg        case XK_Greek_omicron:
14582f167a42Smrg            buf[0] = 0x6F;
14592f167a42Smrg            return True;
14602f167a42Smrg        case XK_Greek_pi:
14612f167a42Smrg            buf[0] = 0x70;
14622f167a42Smrg            return True;
14632f167a42Smrg        case XK_Greek_theta:
14642f167a42Smrg            buf[0] = 0x71;
14652f167a42Smrg            return True;
14662f167a42Smrg        case XK_Greek_rho:
14672f167a42Smrg            buf[0] = 0x72;
14682f167a42Smrg            return True;
14692f167a42Smrg        case XK_Greek_sigma:
14702f167a42Smrg            buf[0] = 0x73;
14712f167a42Smrg            return True;
14722f167a42Smrg        case XK_Greek_tau:
14732f167a42Smrg            buf[0] = 0x74;
14742f167a42Smrg            return True;
14752f167a42Smrg        case XK_Greek_upsilon:
14762f167a42Smrg            buf[0] = 0x75;
14772f167a42Smrg            return True;
14782f167a42Smrg        case XK_Greek_omega:
14792f167a42Smrg            buf[0] = 0x77;
14802f167a42Smrg            return True;
14812f167a42Smrg        case XK_Greek_xi:
14822f167a42Smrg            buf[0] = 0x78;
14832f167a42Smrg            return True;
14842f167a42Smrg        case XK_Greek_psi:
14852f167a42Smrg            buf[0] = 0x79;
14862f167a42Smrg            return True;
14872f167a42Smrg        case XK_Greek_zeta:
14882f167a42Smrg            buf[0] = 0x7A;
14892f167a42Smrg            return True;
14902f167a42Smrg        }
14910e20ee16Smrg    }
14920e20ee16Smrg    switch (sym) {
14932f167a42Smrg    case XK_leftarrow:
14942f167a42Smrg        buf[0] = 0xAC;
14952f167a42Smrg        return True;
14962f167a42Smrg    case XK_uparrow:
14972f167a42Smrg        buf[0] = 0xAD;
14982f167a42Smrg        return True;
14992f167a42Smrg    case XK_rightarrow:
15002f167a42Smrg        buf[0] = 0xAE;
15012f167a42Smrg        return True;
15022f167a42Smrg    case XK_downarrow:
15032f167a42Smrg        buf[0] = 0xAF;
15042f167a42Smrg        return True;
15052f167a42Smrg    case XK_horizconnector:
15062f167a42Smrg        buf[0] = 0xBE;
15072f167a42Smrg        return True;
15082f167a42Smrg    case XK_trademark:
15092f167a42Smrg        buf[0] = 0xE4;
15102f167a42Smrg        return True;
15110e20ee16Smrg    }
15120e20ee16Smrg    return False;
15130e20ee16Smrg}
15140e20ee16Smrg
15150e20ee16Smrgstatic KeySym
15160e20ee16SmrgCheckSymbolAlias(KeySym sym, PSState *state)
15170e20ee16Smrg{
15180e20ee16Smrg    if (XkbKSIsKeypad(sym)) {
15192f167a42Smrg        if ((sym >= XK_KP_0) && (sym <= XK_KP_9))
15202f167a42Smrg            sym = (sym - XK_KP_0) + XK_0;
15212f167a42Smrg        else
15222f167a42Smrg            switch (sym) {
15232f167a42Smrg            case XK_KP_Space:
15242f167a42Smrg                return XK_space;
15252f167a42Smrg            case XK_KP_Tab:
15262f167a42Smrg                return XK_Tab;
15272f167a42Smrg            case XK_KP_Enter:
15282f167a42Smrg                return XK_Return;
15292f167a42Smrg            case XK_KP_F1:
15302f167a42Smrg                return XK_F1;
15312f167a42Smrg            case XK_KP_F2:
15322f167a42Smrg                return XK_F2;
15332f167a42Smrg            case XK_KP_F3:
15342f167a42Smrg                return XK_F3;
15352f167a42Smrg            case XK_KP_F4:
15362f167a42Smrg                return XK_F4;
15372f167a42Smrg            case XK_KP_Home:
15382f167a42Smrg                return XK_Home;
15392f167a42Smrg            case XK_KP_Left:
15402f167a42Smrg                return XK_Left;
15412f167a42Smrg            case XK_KP_Up:
15422f167a42Smrg                return XK_Up;
15432f167a42Smrg            case XK_KP_Right:
15442f167a42Smrg                return XK_Right;
15452f167a42Smrg            case XK_KP_Down:
15462f167a42Smrg                return XK_Down;
15472f167a42Smrg            case XK_KP_Page_Up:
15482f167a42Smrg                return XK_Page_Up;
15492f167a42Smrg            case XK_KP_Page_Down:
15502f167a42Smrg                return XK_Page_Down;
15512f167a42Smrg            case XK_KP_End:
15522f167a42Smrg                return XK_End;
15532f167a42Smrg            case XK_KP_Begin:
15542f167a42Smrg                return XK_Begin;
15552f167a42Smrg            case XK_KP_Insert:
15562f167a42Smrg                return XK_Insert;
15572f167a42Smrg            case XK_KP_Delete:
15582f167a42Smrg                return XK_Delete;
15592f167a42Smrg            case XK_KP_Equal:
15602f167a42Smrg                return XK_equal;
15612f167a42Smrg            case XK_KP_Multiply:
15622f167a42Smrg                return XK_asterisk;
15632f167a42Smrg            case XK_KP_Add:
15642f167a42Smrg                return XK_plus;
15652f167a42Smrg            case XK_KP_Subtract:
15662f167a42Smrg                return XK_minus;
15672f167a42Smrg            case XK_KP_Divide:
15682f167a42Smrg                return XK_slash;
15692f167a42Smrg            }
15700e20ee16Smrg    }
15710e20ee16Smrg    else if (XkbKSIsDeadKey(sym)) {
15722f167a42Smrg        switch (sym) {
15732f167a42Smrg        case XK_dead_grave:
15742f167a42Smrg            sym = XK_grave;
15752f167a42Smrg            break;
15762f167a42Smrg        case XK_dead_acute:
15772f167a42Smrg            sym = XK_acute;
15782f167a42Smrg            break;
15792f167a42Smrg        case XK_dead_circumflex:
15802f167a42Smrg            sym = XK_asciicircum;
15812f167a42Smrg            break;
15822f167a42Smrg        case XK_dead_tilde:
15832f167a42Smrg            sym = XK_asciitilde;
15842f167a42Smrg            break;
15852f167a42Smrg        case XK_dead_macron:
15862f167a42Smrg            sym = XK_macron;
15872f167a42Smrg            break;
15882f167a42Smrg        case XK_dead_breve:
15892f167a42Smrg            sym = XK_breve;
15902f167a42Smrg            break;
15912f167a42Smrg        case XK_dead_abovedot:
15922f167a42Smrg            sym = XK_abovedot;
15932f167a42Smrg            break;
15942f167a42Smrg        case XK_dead_diaeresis:
15952f167a42Smrg            sym = XK_diaeresis;
15962f167a42Smrg            break;
15972f167a42Smrg        case XK_dead_abovering:
15982f167a42Smrg            sym = XK_degree;
15992f167a42Smrg            break;
16002f167a42Smrg        case XK_dead_doubleacute:
16012f167a42Smrg            sym = XK_doubleacute;
16022f167a42Smrg            break;
16032f167a42Smrg        case XK_dead_caron:
16042f167a42Smrg            sym = XK_caron;
16052f167a42Smrg            break;
16062f167a42Smrg        case XK_dead_cedilla:
16072f167a42Smrg            sym = XK_cedilla;
16082f167a42Smrg            break;
16092f167a42Smrg        case XK_dead_ogonek:
16102f167a42Smrg            sym = XK_ogonek;
16112f167a42Smrg            break;
16122f167a42Smrg        case XK_dead_iota:
16132f167a42Smrg            sym = XK_Greek_iota;
16142f167a42Smrg            break;
16152f167a42Smrg        case XK_dead_voiced_sound:
16162f167a42Smrg            sym = XK_voicedsound;
16172f167a42Smrg            break;
16182f167a42Smrg        case XK_dead_semivoiced_sound:
16192f167a42Smrg            sym = XK_semivoicedsound;
16202f167a42Smrg            break;
16212f167a42Smrg        }
16220e20ee16Smrg    }
16230e20ee16Smrg    return sym;
16240e20ee16Smrg}
16250e20ee16Smrg
16260e20ee16Smrgstatic Bool
16270e20ee16SmrgFindKeysymsByName(XkbDescPtr xkb, char *name, PSState *state, KeyTop *top)
16280e20ee16Smrg{
16292f167a42Smrg    static unsigned char buf[30];
16302f167a42Smrg    int kc;
16312f167a42Smrg    KeySym sym, *syms, topSyms[NLABELS];
16322f167a42Smrg    int level, group;
16332f167a42Smrg    int eG, nG, gI, l, g;
16342f167a42Smrg
16352f167a42Smrg    bzero(top, sizeof(KeyTop));
16362f167a42Smrg    kc = XkbFindKeycodeByName(xkb, name, True);
16372f167a42Smrg    if (state->args != NULL) {
16382f167a42Smrg        level = state->args->labelLevel;
16392f167a42Smrg        group = state->args->baseLabelGroup;
16400e20ee16Smrg    }
16412f167a42Smrg    else
16422f167a42Smrg        level = group = 0;
16432f167a42Smrg    syms = XkbKeySymsPtr(xkb, kc);
16442f167a42Smrg    eG = group;
16452f167a42Smrg    nG = XkbKeyNumGroups(xkb, kc);
16462f167a42Smrg    gI = XkbKeyGroupInfo(xkb, kc);
16472f167a42Smrg    if ((state->args->wantDiffs) && (eG >= XkbKeyNumGroups(xkb, kc)))
16482f167a42Smrg        return False;           /* XXX was a return with no value */
16492f167a42Smrg    if (nG == 0) {
16502f167a42Smrg        return False;
16510e20ee16Smrg    }
16522f167a42Smrg    else if (nG == 1) {
16532f167a42Smrg        eG = 0;
16540e20ee16Smrg    }
16552f167a42Smrg    else if (eG >= XkbKeyNumGroups(xkb, kc)) {
16562f167a42Smrg        switch (XkbOutOfRangeGroupAction(gI)) {
16572f167a42Smrg        default:
16582f167a42Smrg            eG %= nG;
16592f167a42Smrg            break;
16602f167a42Smrg        case XkbClampIntoRange:
16612f167a42Smrg            eG = nG - 1;
16622f167a42Smrg            break;
16632f167a42Smrg        case XkbRedirectIntoRange:
16642f167a42Smrg            eG = XkbOutOfRangeGroupNumber(gI);
16652f167a42Smrg            if (eG >= nG)
16662f167a42Smrg                eG = 0;
16672f167a42Smrg            break;
16682f167a42Smrg        }
16690e20ee16Smrg    }
16702f167a42Smrg    for (g = 0; g < state->args->nLabelGroups; g++) {
16712f167a42Smrg        if ((eG + g) >= nG)
16722f167a42Smrg            continue;
16732f167a42Smrg        for (l = 0; l < 2; l++) {
16742f167a42Smrg            int font, sz;
16752f167a42Smrg
16762f167a42Smrg            if (level + l >= XkbKeyGroupWidth(xkb, kc, (eG + g)))
16772f167a42Smrg                continue;
16782f167a42Smrg            sym = syms[((eG + g) * XkbKeyGroupsWidth(xkb, kc)) + (level + l)];
16792f167a42Smrg
16802f167a42Smrg            if (state->args->wantSymbols != NO_SYMBOLS)
16812f167a42Smrg                sym = CheckSymbolAlias(sym, state);
16822f167a42Smrg            topSyms[(g * 2) + l] = sym;
16832f167a42Smrg
16842f167a42Smrg            if (PSKeycapsSymbol(sym, buf, &font, &sz, state)) {
16852f167a42Smrg                top->font[(g * 2) + l] = font;
16862f167a42Smrg                top->size[(g * 2) + l] = sz;
16872f167a42Smrg            }
16882f167a42Smrg            else if (((sym & (~0xffUL)) == 0) && isprint(sym) && (!isspace(sym))) {
16892f167a42Smrg                if (sym == '(')
16902f167a42Smrg                    snprintf((char *) buf, sizeof(buf), "\\(");
16912f167a42Smrg                else if (sym == ')')
16922f167a42Smrg                    snprintf((char *) buf, sizeof(buf), "\\)");
16932f167a42Smrg                else if (sym == '\\')
16942f167a42Smrg                    snprintf((char *) buf, sizeof(buf), "\\\\");
16952f167a42Smrg                else
16962f167a42Smrg                    snprintf((char *) buf, sizeof(buf), "%c", (char) sym);
16972f167a42Smrg                top->font[(g * 2) + l] = FONT_LATIN1;
16982f167a42Smrg                top->size[(g * 2) + l] = SZ_MEDIUM;
16992f167a42Smrg                switch (buf[0]) {
17002f167a42Smrg                case '.':
17012f167a42Smrg                case ':':
17022f167a42Smrg                case ',':
17032f167a42Smrg                case ';':
17042f167a42Smrg                case '\'':
17052f167a42Smrg                case '"':
17062f167a42Smrg                case '`':
17072f167a42Smrg                case '~':
17082f167a42Smrg                case '^':
17092f167a42Smrg                case 0250:
17102f167a42Smrg                case 0270:
17112f167a42Smrg                case 0267:
17122f167a42Smrg                case 0260:
17132f167a42Smrg                case 0252:
17142f167a42Smrg                case 0272:
17152f167a42Smrg                case 0271:
17162f167a42Smrg                case 0262:
17172f167a42Smrg                case 0263:
17182f167a42Smrg                case 0264:
17192f167a42Smrg                case 0255:
17202f167a42Smrg                case 0254:
17212f167a42Smrg                case 0257:
17222f167a42Smrg                    top->size[(g * 2) + l] = SZ_LARGE;
17232f167a42Smrg                    break;
17242f167a42Smrg                }
17252f167a42Smrg            }
17262f167a42Smrg            else if (PSNonLatin1Symbol(sym, buf, &font, &sz, state)) {
17272f167a42Smrg                top->font[(g * 2) + l] = font;
17282f167a42Smrg                top->size[(g * 2) + l] = sz;
17292f167a42Smrg            }
17302f167a42Smrg            else {
17312f167a42Smrg                char *tmp;
17322f167a42Smrg
17332f167a42Smrg                tmp = XKeysymToString(sym);
17342f167a42Smrg                if (tmp != NULL)
17352f167a42Smrg                    strcpy((char *) buf, tmp);
17362f167a42Smrg                else
17372f167a42Smrg                    snprintf((char *) buf, sizeof(buf), "(%ld)", sym);
17382f167a42Smrg                top->font[(g * 2) + l] = FONT_LATIN1;
17392f167a42Smrg                if (strlen((char *) buf) < 9)
17402f167a42Smrg                    top->size[(g * 2) + l] = SZ_SMALL;
17412f167a42Smrg                else
17422f167a42Smrg                    top->size[(g * 2) + l] = SZ_TINY;
17432f167a42Smrg            }
17442f167a42Smrg            top->present |= (1 << ((g * 2) + l));
17452f167a42Smrg            strncpy(top->label[(g * 2) + l], (char *) buf, LABEL_LEN - 1);
17462f167a42Smrg            top->label[(g * 2) + l][LABEL_LEN - 1] = '\0';
17472f167a42Smrg        }
17482f167a42Smrg        if (((g == 0) && (top->present & G1LX_MASK) == G1LX_MASK) ||
17492f167a42Smrg            ((g == 1) && (top->present & G2LX_MASK) == G2LX_MASK)) {
17502f167a42Smrg            KeySym lower, upper;
17512f167a42Smrg
17522f167a42Smrg            XConvertCase(topSyms[(g * 2)], &lower, &upper);
17532f167a42Smrg            if ((topSyms[(g * 2)] == lower) && (topSyms[(g * 2) + 1] == upper)) {
17542f167a42Smrg                top->alpha[g] = True;
17552f167a42Smrg            }
17562f167a42Smrg        }
17570e20ee16Smrg    }
17580e20ee16Smrg    return True;
17590e20ee16Smrg}
17600e20ee16Smrg
17610e20ee16Smrgstatic void
17622f167a42SmrgPSDrawLabel(FILE *out, const char *label, int x, int y, int w, int h)
17630e20ee16Smrg{
17642f167a42Smrg    fprintf(out, "%d %d (%s) centeroffset\n", w, h, label);
17652f167a42Smrg    fprintf(out, "%d add exch\n", y);
17662f167a42Smrg    fprintf(out, "%d add exch moveto\n", x);
17672f167a42Smrg    fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", label);
17680e20ee16Smrg    return;
17690e20ee16Smrg}
17700e20ee16Smrg
17710e20ee16Smrg#define	TOP_ROW		0
17720e20ee16Smrg#define	BOTTOM_ROW	1
17730e20ee16Smrg#define	CENTER_ROW	2
17740e20ee16Smrg
17750e20ee16Smrg#define	LEFT_COL	0
17760e20ee16Smrg#define	RIGHT_COL	1
17770e20ee16Smrg#define	CENTER_COL	2
17780e20ee16Smrg
17790e20ee16Smrgstatic void
17800e20ee16SmrgPSLabelKey(FILE *out, PSState *state, KeyTop *top, int x, int y,
17812f167a42Smrg           XkbBoundsPtr bounds, int kc, int btm)
17820e20ee16Smrg{
17832f167a42Smrg    int w, h, i;
17842f167a42Smrg    int row_y[3];
17852f167a42Smrg    int col_x[3];
17862f167a42Smrg    int row_h[3];
17872f167a42Smrg    int col_w[3];
17882f167a42Smrg    Bool present[NLABELS];
17892f167a42Smrg    int sym_row[NLABELS];
17902f167a42Smrg    int sym_col[NLABELS];
17912f167a42Smrg
17922f167a42Smrg    w = XkbBoundsWidth(bounds);
17932f167a42Smrg    h = XkbBoundsHeight(bounds);
17942f167a42Smrg    row_y[TOP_ROW] = y + bounds->y1 + (h / 10);
17952f167a42Smrg    row_y[BOTTOM_ROW] = y + bounds->y1 + (h / 2) + (h / 10);
17962f167a42Smrg    row_y[CENTER_ROW] = y + bounds->y1 + (h / 10);
17972f167a42Smrg    row_h[TOP_ROW] = h / 2;
17982f167a42Smrg    row_h[BOTTOM_ROW] = h / 2;
17992f167a42Smrg    row_h[CENTER_ROW] = h;
18002f167a42Smrg
18012f167a42Smrg    col_x[LEFT_COL] = x + bounds->x1;
18022f167a42Smrg    col_x[RIGHT_COL] = x + bounds->x1 + w / 2;
18032f167a42Smrg    col_x[CENTER_COL] = x + bounds->x1;
18042f167a42Smrg    col_w[LEFT_COL] = w / 2;
18052f167a42Smrg    col_w[RIGHT_COL] = w / 2;
18062f167a42Smrg    col_w[CENTER_COL] = w;
18072f167a42Smrg
18082f167a42Smrg    present[G1L1] = False;
18092f167a42Smrg    sym_row[G1L1] = BOTTOM_ROW;
18102f167a42Smrg    sym_col[G1L1] = LEFT_COL;
18112f167a42Smrg
18122f167a42Smrg    present[G1L2] = False;
18132f167a42Smrg    sym_row[G1L2] = TOP_ROW;
18142f167a42Smrg    sym_col[G1L2] = LEFT_COL;
18152f167a42Smrg
18162f167a42Smrg    present[G2L1] = False;
18172f167a42Smrg    sym_row[G2L1] = BOTTOM_ROW;
18182f167a42Smrg    sym_col[G2L1] = RIGHT_COL;
18192f167a42Smrg
18202f167a42Smrg    present[G2L2] = False;
18212f167a42Smrg    sym_row[G2L2] = TOP_ROW;
18222f167a42Smrg    sym_col[G2L2] = RIGHT_COL;
18232f167a42Smrg
18242f167a42Smrg    present[CENTER] = False;
18252f167a42Smrg    sym_row[CENTER] = CENTER_ROW;
18262f167a42Smrg    sym_col[CENTER] = CENTER_COL;
18272f167a42Smrg
18282f167a42Smrg    if (top->present & CENTER_MASK) {
18292f167a42Smrg        present[CENTER] = True;
18300e20ee16Smrg    }
18312f167a42Smrg    else
18322f167a42Smrg        switch (top->present & GXLX_MASK) {
18332f167a42Smrg        case G1L1_MASK:
18342f167a42Smrg            present[G1L1] = True;
18352f167a42Smrg            sym_row[G1L1] = CENTER_ROW;
18362f167a42Smrg            sym_col[G1L1] = CENTER_COL;
18372f167a42Smrg            break;
18382f167a42Smrg        case G1LX_MASK:
18392f167a42Smrg            present[G1L2] = True;
18402f167a42Smrg            if (!top->alpha[0]) {
18412f167a42Smrg                present[G1L1] = True;
18422f167a42Smrg                if ((strlen(top->label[G1L1]) > 1) &&
18432f167a42Smrg                    (top->label[G1L1][0] != '\\'))
18442f167a42Smrg                    sym_col[G1L1] = CENTER_COL;
18452f167a42Smrg                if ((strlen(top->label[G1L2]) > 1) &&
18462f167a42Smrg                    (top->label[G1L1][0] != '\\'))
18472f167a42Smrg                    sym_col[G1L2] = CENTER_COL;
18482f167a42Smrg            }
18492f167a42Smrg            break;
18502f167a42Smrg        default:
18512f167a42Smrg            if ((top->present & G1LX_MASK) == G1LX_MASK) {
18522f167a42Smrg                present[G1L2] = True;
18532f167a42Smrg                if (!top->alpha[0])
18542f167a42Smrg                    present[G1L1] = True;
18552f167a42Smrg            }
18562f167a42Smrg            else if ((top->present & G1LX_MASK) == G1L1_MASK) {
18572f167a42Smrg                present[G1L1] = True;
18582f167a42Smrg            }
18592f167a42Smrg            else if ((top->present & G1LX_MASK) == G1L2_MASK) {
18602f167a42Smrg                present[G1L2] = True;
18612f167a42Smrg            }
18622f167a42Smrg            if ((top->present & G2LX_MASK) == G2LX_MASK) {
18632f167a42Smrg                present[G2L2] = True;
18642f167a42Smrg                if (!top->alpha[1])
18652f167a42Smrg                    present[G2L1] = True;
18662f167a42Smrg            }
18672f167a42Smrg            else if ((top->present & G2LX_MASK) == G2L1_MASK) {
18682f167a42Smrg                present[G2L1] = True;
18692f167a42Smrg            }
18702f167a42Smrg            else if ((top->present & G2LX_MASK) == G2L2_MASK) {
18712f167a42Smrg                present[G2L2] = True;
18722f167a42Smrg            }
18732f167a42Smrg            break;
18742f167a42Smrg        case 0:
18752f167a42Smrg            return;
18762f167a42Smrg        }
18772f167a42Smrg    for (i = 0; i < NLABELS; i++) {
18782f167a42Smrg        if (present[i]) {
18792f167a42Smrg            int size;
18802f167a42Smrg
18812f167a42Smrg            if (top->size[i] == SZ_AUTO) {
18822f167a42Smrg                size_t len = strlen(top->label[i]);
18832f167a42Smrg                if (len == 1) {
18842f167a42Smrg                    if (top->font[i] == FONT_ISOCAPS)
18852f167a42Smrg                        size = 18;
18862f167a42Smrg                    else
18872f167a42Smrg                        size = 14;
18882f167a42Smrg                }
18892f167a42Smrg                else if (len < 10)
18902f167a42Smrg                    size = 12;
18912f167a42Smrg                else
18922f167a42Smrg                    size = 10;
18932f167a42Smrg            }
18942f167a42Smrg            else if (top->size[i] == SZ_TINY)
18952f167a42Smrg                size = 10;
18962f167a42Smrg            else if (top->size[i] == SZ_SMALL)
18972f167a42Smrg                size = 12;
18982f167a42Smrg            else if (top->size[i] == SZ_LARGE)
18992f167a42Smrg                size = 18;
19002f167a42Smrg            else if (top->size[i] == SZ_XLARGE)
19012f167a42Smrg                size = 24;
19022f167a42Smrg            else
19032f167a42Smrg                size = 14;
19042f167a42Smrg            PSSetFont(out, state, top->font[i], size, True);
19052f167a42Smrg            PSDrawLabel(out, top->label[i], col_x[sym_col[i]],
19062f167a42Smrg                        row_y[sym_row[i]], col_w[sym_col[i]],
19072f167a42Smrg                        row_h[sym_row[i]]);
19082f167a42Smrg        }
19090e20ee16Smrg    }
19100e20ee16Smrg    if (state->args->wantKeycodes) {
19112f167a42Smrg        char keycode[10];
19122f167a42Smrg
19132f167a42Smrg        snprintf(keycode, sizeof(keycode), "%d", kc);
19142f167a42Smrg        PSSetFont(out, state, FONT_LATIN1, 8, True);
19152f167a42Smrg        PSDrawLabel(out, keycode, x + bounds->x1, y + btm - 5, w, 0);
19160e20ee16Smrg    }
19170e20ee16Smrg    return;
19180e20ee16Smrg}
19190e20ee16Smrg
19200e20ee16Smrgstatic void
19210e20ee16SmrgPSSection(FILE *out, PSState *state, XkbSectionPtr section)
19220e20ee16Smrg{
19232f167a42Smrg    int r, offset;
19242f167a42Smrg    XkbRowPtr row;
19252f167a42Smrg    Display *dpy;
19262f167a42Smrg    XkbDescPtr xkb;
19272f167a42Smrg
19282f167a42Smrg    xkb = state->xkb;
19292f167a42Smrg    dpy = xkb->dpy;
1930e6bced22Smrg    {
1931e6bced22Smrg        const char *section_name;
1932e6bced22Smrg        char *atom_name = NULL;
1933e6bced22Smrg
1934e6bced22Smrg        if (section->name != None)
1935e6bced22Smrg            section_name = atom_name = XkbAtomGetString(dpy, section->name);
1936e6bced22Smrg        else
1937e6bced22Smrg            section_name = "NoName";
1938e6bced22Smrg        fprintf(out, "%% Begin Section '%s'\n", section_name);
1939e6bced22Smrg        XFree(atom_name);
1940e6bced22Smrg    }
19412f167a42Smrg    PSGSave(out, state);
19422f167a42Smrg    fprintf(out, "%d %d translate\n", section->left, section->top);
19432f167a42Smrg    if (section->angle != 0)
19442f167a42Smrg        fprintf(out, "%s rotate\n", XkbGeomFPText(section->angle, XkbMessage));
19450e20ee16Smrg    if (section->doodads) {
19462f167a42Smrg        XkbDrawablePtr first, draw;
19472f167a42Smrg
19482f167a42Smrg        first = draw = XkbGetOrderedDrawables(NULL, section);
19492f167a42Smrg        while (draw) {
19502f167a42Smrg            if (draw->type == XkbDW_Section)
19512f167a42Smrg                PSSection(out, state, draw->u.section);
19522f167a42Smrg            else
19532f167a42Smrg                PSDoodad(out, state, draw->u.doodad);
19542f167a42Smrg            draw = draw->next;
19552f167a42Smrg        }
19562f167a42Smrg        XkbFreeOrderedDrawables(first);
19570e20ee16Smrg    }
19582f167a42Smrg    for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
19592f167a42Smrg        int k;
19602f167a42Smrg        XkbKeyPtr key;
19612f167a42Smrg
19622f167a42Smrg        if (row->vertical)
19632f167a42Smrg            offset = row->top;
19642f167a42Smrg        else
19652f167a42Smrg            offset = row->left;
19662f167a42Smrg        fprintf(out, "%% Begin %s %d\n", row->vertical ? "column" : "row",
19672f167a42Smrg                r + 1);
19682f167a42Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
1969e6bced22Smrg            XkbShapePtr shape = XkbKeyShape(xkb->geom, key);
1970e6bced22Smrg            char *shape_name  = XkbAtomGetString(dpy, shape->name);
1971e6bced22Smrg
19722f167a42Smrg            offset += key->gap;
19732f167a42Smrg            if (row->vertical) {
19742f167a42Smrg                if (state->args->wantColor) {
19752f167a42Smrg                    if (key->color_ndx != state->white) {
19762f167a42Smrg                        PSSetColor(out, state, key->color_ndx);
19772f167a42Smrg                        fprintf(out, "true 0 %d %d %s %% %s\n",
1978e6bced22Smrg                                row->left, offset, shape_name,
19792f167a42Smrg                                XkbKeyNameText(key->name.name, XkbMessage));
19802f167a42Smrg                    }
19812f167a42Smrg                    PSSetColor(out, state, state->black);
19822f167a42Smrg                }
19832f167a42Smrg                fprintf(out, "false 0 %d %d %s %% %s\n", row->left, offset,
1984e6bced22Smrg                        shape_name,
19852f167a42Smrg                        XkbKeyNameText(key->name.name, XkbMessage));
19862f167a42Smrg                offset += shape->bounds.y2;
19872f167a42Smrg            }
19882f167a42Smrg            else {
19892f167a42Smrg                if (state->args->wantColor) {
19902f167a42Smrg                    if (key->color_ndx != state->white) {
19912f167a42Smrg                        PSSetColor(out, state, key->color_ndx);
19922f167a42Smrg                        fprintf(out, "true 0 %d %d %s %% %s\n", offset,
1993e6bced22Smrg                                row->top, shape_name,
19942f167a42Smrg                                XkbKeyNameText(key->name.name, XkbMessage));
19952f167a42Smrg                    }
19962f167a42Smrg                    PSSetColor(out, state, state->black);
19972f167a42Smrg                }
19982f167a42Smrg                fprintf(out, "false 0 %d %d %s %% %s\n", offset, row->top,
1999e6bced22Smrg                        shape_name,
20002f167a42Smrg                        XkbKeyNameText(key->name.name, XkbMessage));
20012f167a42Smrg                offset += shape->bounds.x2;
20022f167a42Smrg            }
2003e6bced22Smrg            XFree(shape_name);
20042f167a42Smrg        }
20050e20ee16Smrg    }
20062f167a42Smrg    for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
20072f167a42Smrg        int k, kc = 0;
20082f167a42Smrg        XkbKeyPtr key;
20092f167a42Smrg        XkbShapePtr shape;
20102f167a42Smrg        XkbBoundsRec bounds;
20112f167a42Smrg
20122f167a42Smrg        if (state->args->label == LABEL_NONE)
20132f167a42Smrg            break;
20142f167a42Smrg        if (row->vertical)
20152f167a42Smrg            offset = row->top;
20162f167a42Smrg        else
20172f167a42Smrg            offset = row->left;
20182f167a42Smrg        fprintf(out, "%% Begin %s %d labels\n",
20192f167a42Smrg                row->vertical ? "column" : "row", r + 1);
20202f167a42Smrg        PSSetColor(out, state, xkb->geom->label_color->pixel);
20212f167a42Smrg        PSSetFont(out, state, FONT_LATIN1, 12, True);
20222f167a42Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
20232f167a42Smrg            char *name, *name2, buf[30], buf2[30];
20242f167a42Smrg            int x, y;
20252f167a42Smrg            KeyTop top;
20262f167a42Smrg
20272f167a42Smrg            shape = XkbKeyShape(xkb->geom, key);
20282f167a42Smrg            XkbComputeShapeTop(shape, &bounds);
20292f167a42Smrg            offset += key->gap;
20302f167a42Smrg            name = name2 = NULL;
20312f167a42Smrg            if (state->args->label == LABEL_SYMBOLS) {
20322f167a42Smrg                if (!FindKeysymsByName(xkb, key->name.name, state, &top)) {
20332f167a42Smrg                    fprintf(out, "%% No label for %s\n",
20342f167a42Smrg                            XkbKeyNameText(key->name.name, XkbMessage));
20352f167a42Smrg                }
20362f167a42Smrg            }
20372f167a42Smrg            else {
20382f167a42Smrg                char *olKey;
20392f167a42Smrg
20402f167a42Smrg                if (section->num_overlays > 0)
20412f167a42Smrg                    olKey = XkbFindOverlayForKey(xkb->geom, section,
20422f167a42Smrg                                                 key->name.name);
20432f167a42Smrg                else
20442f167a42Smrg                    olKey = NULL;
20452f167a42Smrg
20462f167a42Smrg                if (state->args->label == LABEL_KEYNAME) {
20472f167a42Smrg                    name = XkbKeyNameText(key->name.name, XkbMessage);
20482f167a42Smrg                    if (olKey)
20492f167a42Smrg                        name2 = XkbKeyNameText(olKey, XkbMessage);
20502f167a42Smrg                }
20512f167a42Smrg                else if (state->args->label == LABEL_KEYCODE) {
20522f167a42Smrg                    name = buf;
20532f167a42Smrg                    snprintf(name, sizeof(buf), "%d",
20542f167a42Smrg                            XkbFindKeycodeByName(xkb, key->name.name, True));
20552f167a42Smrg                    if (olKey) {
20562f167a42Smrg                        name2 = buf2;
20572f167a42Smrg                        snprintf(name2, sizeof(buf2), "%d",
20582f167a42Smrg                                 XkbFindKeycodeByName(xkb, olKey, True));
20592f167a42Smrg                    }
20602f167a42Smrg                }
20612f167a42Smrg                bzero(&top, sizeof(KeyTop));
20622f167a42Smrg                if (name2 != NULL) {
20632f167a42Smrg                    top.present |= G1LX_MASK;
20642f167a42Smrg                    strncpy(top.label[G1L1], name, LABEL_LEN - 1);
20652f167a42Smrg                    top.label[G1L1][LABEL_LEN - 1] = '\0';
20662f167a42Smrg                    strncpy(top.label[G1L2], name2, LABEL_LEN - 1);
20672f167a42Smrg                    top.label[G1L2][LABEL_LEN - 1] = '\0';
20682f167a42Smrg                }
20692f167a42Smrg                else if (name != NULL) {
20702f167a42Smrg                    top.present |= CENTER_MASK;
20712f167a42Smrg                    strncpy(top.label[CENTER], name, LABEL_LEN - 1);
20722f167a42Smrg                    top.label[CENTER][LABEL_LEN - 1] = '\0';
20732f167a42Smrg                }
20742f167a42Smrg                else {
20752f167a42Smrg                    fprintf(out, "%% No label for %s\n",
20762f167a42Smrg                            XkbKeyNameText(key->name.name, XkbMessage));
20772f167a42Smrg                }
20782f167a42Smrg            }
20792f167a42Smrg            if (row->vertical) {
20802f167a42Smrg                x = row->left;
20812f167a42Smrg                y = offset;
20822f167a42Smrg                offset += shape->bounds.y2;
20832f167a42Smrg            }
20842f167a42Smrg            else {
20852f167a42Smrg                x = offset;
20862f167a42Smrg                y = row->top;
20872f167a42Smrg                offset += shape->bounds.x2;
20882f167a42Smrg            }
20892f167a42Smrg            name = key->name.name;
20902f167a42Smrg            fprintf(out, "%% %s\n", XkbKeyNameText(name, XkbMessage));
20912f167a42Smrg            if (state->args->wantKeycodes)
20922f167a42Smrg                kc = XkbFindKeycodeByName(xkb, key->name.name, True);
20932f167a42Smrg            PSLabelKey(out, state, &top, x, y, &bounds, kc, shape->bounds.y2);
20942f167a42Smrg        }
20950e20ee16Smrg    }
20962f167a42Smrg    PSGRestore(out, state);
20970e20ee16Smrg    return;
20980e20ee16Smrg}
20990e20ee16Smrg
21000e20ee16SmrgBool
21010e20ee16SmrgGeometryToPostScript(FILE *out, XkbFileInfo *pResult, XKBPrintArgs *args)
21020e20ee16Smrg{
21032f167a42Smrg    XkbDrawablePtr first, draw;
21042f167a42Smrg    PSState state;
21052f167a42Smrg    Bool dfltBorder;
21062f167a42Smrg    int i;
21072f167a42Smrg
21082f167a42Smrg    if ((!pResult) || (!pResult->xkb) || (!pResult->xkb->geom))
21092f167a42Smrg        return False;
21102f167a42Smrg    state.xkb = pResult->xkb;
21112f167a42Smrg    state.dpy = pResult->xkb->dpy;
21122f167a42Smrg    state.geom = pResult->xkb->geom;
21132f167a42Smrg    state.color = state.black = state.white = -1;
21142f167a42Smrg    state.font = -1;
21152f167a42Smrg    state.nPages = 0;
21162f167a42Smrg    state.totalKB = 1;
21172f167a42Smrg    state.kbPerPage = 1;
21182f167a42Smrg    state.x1 = state.y1 = state.x2 = state.y2 = 0;
21192f167a42Smrg    state.args = args;
21202f167a42Smrg
21212f167a42Smrg    if ((args->label == LABEL_SYMBOLS) && (pResult->xkb->ctrls)) {
21222f167a42Smrg        if (args->nTotalGroups == 0)
21232f167a42Smrg            state.totalKB =
21242f167a42Smrg                pResult->xkb->ctrls->num_groups / args->nLabelGroups;
21252f167a42Smrg        else
21262f167a42Smrg            state.totalKB = args->nTotalGroups;
21272f167a42Smrg        if (state.totalKB < 1)
21282f167a42Smrg            state.totalKB = 1;
21292f167a42Smrg        else if (state.totalKB > 1)
21302f167a42Smrg            state.kbPerPage = 2;
21310e20ee16Smrg    }
21322f167a42Smrg    if (args->nKBPerPage != 0)
21332f167a42Smrg        state.kbPerPage = args->nKBPerPage;
21342f167a42Smrg
21352f167a42Smrg    PSProlog(out, &state);
21362f167a42Smrg    first = XkbGetOrderedDrawables(state.geom, NULL);
21372f167a42Smrg
21382f167a42Smrg    for (draw = first, dfltBorder = True; draw != NULL; draw = draw->next) {
21392f167a42Smrg        if ((draw->type != XkbDW_Section) &&
21402f167a42Smrg            ((draw->u.doodad->any.type == XkbOutlineDoodad) ||
21412f167a42Smrg             (draw->u.doodad->any.type == XkbSolidDoodad))) {
21422f167a42Smrg            char *name;
21432f167a42Smrg
21442f167a42Smrg            name = XkbAtomGetString(state.dpy, draw->u.doodad->any.name);
21452f167a42Smrg            if ((name != NULL) && (uStrCaseEqual(name, "edges"))) {
21462f167a42Smrg                dfltBorder = False;
2147e6bced22Smrg                XFree(name);
21482f167a42Smrg                break;
21492f167a42Smrg            }
2150e6bced22Smrg            XFree(name);
21512f167a42Smrg        }
21520e20ee16Smrg    }
21532f167a42Smrg    for (i = 0; i < state.totalKB; i++) {
21542f167a42Smrg        PSPageSetup(out, &state, dfltBorder);
21552f167a42Smrg        for (draw = first; draw != NULL; draw = draw->next) {
21562f167a42Smrg            if (draw->type == XkbDW_Section)
21572f167a42Smrg                PSSection(out, &state, draw->u.section);
21582f167a42Smrg            else {
21592f167a42Smrg                PSDoodad(out, &state, draw->u.doodad);
21602f167a42Smrg            }
21612f167a42Smrg        }
21622f167a42Smrg        PSPageTrailer(out, &state);
21632f167a42Smrg        state.args->baseLabelGroup += state.args->nLabelGroups;
21640e20ee16Smrg    }
21650e20ee16Smrg    XkbFreeOrderedDrawables(first);
21662f167a42Smrg    PSFileTrailer(out, &state);
21670e20ee16Smrg    return True;
21680e20ee16Smrg}
2169