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 460e20ee16Smrg#include <stdlib.h> 470e20ee16Smrg 480e20ee16Smrg#include "utils.h" 490e20ee16Smrg#include "xkbprint.h" 500e20ee16Smrg#include "isokeys.h" 510e20ee16Smrg 520e20ee16Smrg#define FONT_NONE -1 530e20ee16Smrg#define FONT_TEXT 0 540e20ee16Smrg#define FONT_LATIN1 1 550e20ee16Smrg#define FONT_SYMBOL 2 560e20ee16Smrg#define FONT_ISOCAPS 3 570e20ee16Smrg#define FONT_MOUSECAPS 4 580e20ee16Smrg 590e20ee16Smrgtypedef struct { 602f167a42Smrg Display * dpy; 612f167a42Smrg XkbDescPtr xkb; 622f167a42Smrg XkbGeometryPtr geom; 632f167a42Smrg int totalKB; 642f167a42Smrg int kbPerPage; 652f167a42Smrg int black; 662f167a42Smrg int white; 672f167a42Smrg int color; 682f167a42Smrg int font; 692f167a42Smrg int fontSize; 702f167a42Smrg int nPages; 712f167a42Smrg int x1, y1; 722f167a42Smrg int x2, y2; 732f167a42Smrg XKBPrintArgs * args; 740e20ee16Smrg} PSState; 750e20ee16Smrg 760e20ee16Smrg#define G1L1 0 770e20ee16Smrg#define G1L2 1 780e20ee16Smrg#define G2L1 2 790e20ee16Smrg#define G2L2 3 800e20ee16Smrg#define CENTER 4 810e20ee16Smrg 820e20ee16Smrg#define G1L1_MASK (1<<G1L1) 830e20ee16Smrg#define G1L2_MASK (1<<G1L2) 840e20ee16Smrg#define G2L1_MASK (1<<G2L1) 850e20ee16Smrg#define G2L2_MASK (1<<G2L2) 860e20ee16Smrg#define CENTER_MASK (1<<CENTER) 870e20ee16Smrg 880e20ee16Smrg#define LABEL_MASK (0x1f) 890e20ee16Smrg#define GXL1_MASK (G1L1_MASK|G2L1_MASK) 900e20ee16Smrg#define GXL2_MASK (G1L2_MASK|G2L2_MASK) 910e20ee16Smrg#define G1LX_MASK (G1L1_MASK|G1L2_MASK) 920e20ee16Smrg#define G2LX_MASK (G2L1_MASK|G2L2_MASK) 930e20ee16Smrg#define GXLX_MASK (0x0f) 940e20ee16Smrg 950e20ee16Smrg#define NLABELS 5 960e20ee16Smrg#define LABEL_LEN 30 970e20ee16Smrg 980e20ee16Smrg#define SZ_AUTO 0 990e20ee16Smrg#define SZ_TINY 1 1000e20ee16Smrg#define SZ_SMALL 2 1010e20ee16Smrg#define SZ_MEDIUM 3 1020e20ee16Smrg#define SZ_LARGE 4 1030e20ee16Smrg#define SZ_XLARGE 5 1040e20ee16Smrg 1050e20ee16Smrgtypedef struct { 1062f167a42Smrg unsigned present; 1072f167a42Smrg Bool alpha[2]; 1082f167a42Smrg char label[NLABELS][LABEL_LEN]; 1092f167a42Smrg int font[NLABELS]; 1102f167a42Smrg int size[NLABELS]; 1110e20ee16Smrg} KeyTop; 1120e20ee16Smrg 1130e20ee16Smrg#define DFLT_LABEL_FONT "Helvetica-Narrow-Bold" 1140e20ee16Smrg#define DFLT_LABEL_FONT_SIZE 10 1150e20ee16Smrg 1160e20ee16Smrg/***====================================================================***/ 1170e20ee16Smrg 1180e20ee16Smrgtypedef struct _PSFontDef { 1192f167a42Smrg const char *name; 1202f167a42Smrg const char **def; 1210e20ee16Smrg} PSFontDef; 1220e20ee16Smrg 1230e20ee16Smrgstatic PSFontDef internalFonts[] = { 1242f167a42Smrg { "IsoKeyCaps", &IsoKeyCaps } 1250e20ee16Smrg}; 1262f167a42Smrgstatic int nInternalFonts = (sizeof(internalFonts) / sizeof(PSFontDef)); 1270e20ee16Smrg 1280e20ee16Smrgstatic void 1290e20ee16SmrgListInternalFonts(FILE *out, int first, int indent) 1300e20ee16Smrg{ 1318b648e79Smrg register int i, nThisLine; 1320e20ee16Smrg 1338b648e79Smrg for (int n = 0; n < first; n++) { 1342f167a42Smrg putc(' ', out); 1350e20ee16Smrg } 1360e20ee16Smrg 1372f167a42Smrg for (nThisLine = i = 0; i < nInternalFonts; i++) { 1382f167a42Smrg if (nThisLine == 4) { 1392f167a42Smrg fprintf(out, ",\n"); 1408b648e79Smrg for (int n = 0; n < indent; n++) { 1412f167a42Smrg putc(' ', out); 1422f167a42Smrg } 1432f167a42Smrg nThisLine = 0; 1442f167a42Smrg } 1452f167a42Smrg if (nThisLine == 0) 1462f167a42Smrg fprintf(out, "%s", internalFonts[i].name); 1472f167a42Smrg else 1482f167a42Smrg fprintf(out, ", %s", internalFonts[i].name); 1492f167a42Smrg nThisLine++; 1500e20ee16Smrg } 1512f167a42Smrg if (nThisLine != 0) 1522f167a42Smrg fprintf(out, "\n"); 1530e20ee16Smrg return; 1540e20ee16Smrg} 1550e20ee16Smrg 1560e20ee16Smrgstatic Bool 1572f167a42SmrgPSIncludeFont(FILE *out, const char *font) 1580e20ee16Smrg{ 1592f167a42Smrg const char **pstr; 1600e20ee16Smrg 1612f167a42Smrg pstr = NULL; 1628b648e79Smrg for (int i = 0; (i < nInternalFonts) && (pstr == NULL); i++) { 1632f167a42Smrg if (uStringEqual(internalFonts[i].name, font)) 1642f167a42Smrg pstr = internalFonts[i].def; 1650e20ee16Smrg } 1662f167a42Smrg if (pstr != NULL) { 1672f167a42Smrg fprintf(out, "%%%%BeginFont: %s\n", font); 1682f167a42Smrg fprintf(out, "%s", *pstr); 1692f167a42Smrg fprintf(out, "%%%%EndFont\n"); 1702f167a42Smrg return True; 1710e20ee16Smrg } 1720e20ee16Smrg return False; 1730e20ee16Smrg} 1740e20ee16Smrg 1750e20ee16SmrgBool 1762f167a42SmrgDumpInternalFont(FILE *out, const char *fontName) 1770e20ee16Smrg{ 1782f167a42Smrg if (strcmp(fontName, "IsoKeyCaps") != 0) { 1792f167a42Smrg uError("No internal font named \"%s\"\n", fontName); 1802f167a42Smrg uAction("No font dumped\n"); 1812f167a42Smrg fprintf(stderr, "Current internal fonts are: "); 1822f167a42Smrg ListInternalFonts(stderr, 0, 8); 1832f167a42Smrg return False; 1840e20ee16Smrg } 1852f167a42Smrg PSIncludeFont(out, fontName); 1860e20ee16Smrg return True; 1870e20ee16Smrg} 1880e20ee16Smrg 1890e20ee16Smrg/***====================================================================***/ 1900e20ee16Smrg 1910e20ee16Smrgstatic void 1920e20ee16SmrgPSColorDef(FILE *out, PSState *state, XkbColorPtr color) 1930e20ee16Smrg{ 1942f167a42Smrg int tmp; 1950e20ee16Smrg 1962f167a42Smrg fprintf(out, "/C%03d ", color->pixel); 1972f167a42Smrg if (uStrCaseEqual(color->spec, "black")) { 1982f167a42Smrg state->black = color->pixel; 1992f167a42Smrg fprintf(out, "{ 0 setgray } def %% %s\n", color->spec); 2000e20ee16Smrg } 2012f167a42Smrg else if (uStrCaseEqual(color->spec, "white")) { 2022f167a42Smrg state->white = color->pixel; 2032f167a42Smrg fprintf(out, "{ 1 setgray } def %% %s\n", color->spec); 2040e20ee16Smrg } 2052f167a42Smrg else if ((sscanf(color->spec, "grey%d", &tmp) == 1) || 2062f167a42Smrg (sscanf(color->spec, "gray%d", &tmp) == 1) || 2072f167a42Smrg (sscanf(color->spec, "Grey%d", &tmp) == 1) || 2082f167a42Smrg (sscanf(color->spec, "Gray%d", &tmp) == 1)) { 2092f167a42Smrg fprintf(out, "{ %f setgray } def %% %s\n", 2102f167a42Smrg 1.0 - (((float) tmp) / 100.0), color->spec); 2110e20ee16Smrg } 2122f167a42Smrg else if ((tmp = (uStrCaseEqual(color->spec, "red") * 100)) || 2132f167a42Smrg (sscanf(color->spec, "red%d", &tmp) == 1)) { 2142f167a42Smrg fprintf(out, "{ %f 0 0 setrgbcolor } def %% %s\n", 2152f167a42Smrg (((float) tmp) / 100.0), color->spec); 2160e20ee16Smrg } 2172f167a42Smrg else if ((tmp = (uStrCaseEqual(color->spec, "green") * 100)) || 2182f167a42Smrg (sscanf(color->spec, "green%d", &tmp) == 1)) { 2192f167a42Smrg fprintf(out, "{ 0 %f 0 setrgbcolor } def %% %s\n", 2202f167a42Smrg (((float) tmp) / 100.0), color->spec); 2210e20ee16Smrg } 2222f167a42Smrg else if ((tmp = (uStrCaseEqual(color->spec, "blue") * 100)) || 2232f167a42Smrg (sscanf(color->spec, "blue%d", &tmp) == 1)) { 2242f167a42Smrg fprintf(out, "{ 0 0 %f setrgbcolor } def %% %s\n", 2252f167a42Smrg (((float) tmp) / 100.0), color->spec); 2260e20ee16Smrg } 2272f167a42Smrg else 2282f167a42Smrg fprintf(out, "{ 0.9 setgray } def %% BOGUS! %s\n", color->spec); 2290e20ee16Smrg} 2300e20ee16Smrg 2310e20ee16Smrgstatic void 2322f167a42SmrgPSSetColor(FILE *out, PSState *state, int color) 2330e20ee16Smrg{ 2342f167a42Smrg if ((state->args->wantColor) && (state->color != color)) { 2352f167a42Smrg fprintf(out, "C%03d %% set color\n", color); 2362f167a42Smrg state->color = color; 2370e20ee16Smrg } 2380e20ee16Smrg return; 2390e20ee16Smrg} 2400e20ee16Smrg 2410e20ee16Smrgstatic void 2420e20ee16SmrgPSGSave(FILE *out, PSState *state) 2430e20ee16Smrg{ 2442f167a42Smrg fprintf(out, "gsave\n"); 2450e20ee16Smrg return; 2460e20ee16Smrg} 2470e20ee16Smrg 2480e20ee16Smrgstatic void 2490e20ee16SmrgPSGRestore(FILE *out, PSState *state) 2500e20ee16Smrg{ 2512f167a42Smrg fprintf(out, "grestore\n"); 2522f167a42Smrg state->color = -1; 2532f167a42Smrg state->font = FONT_NONE; 2542f167a42Smrg state->fontSize = -1; 2550e20ee16Smrg return; 2560e20ee16Smrg} 2570e20ee16Smrg 2580e20ee16Smrgstatic void 2590e20ee16SmrgPSShapeDef(FILE *out, PSState *state, XkbShapePtr shape) 2600e20ee16Smrg{ 2618b648e79Smrg int o; 2622f167a42Smrg XkbOutlinePtr ol; 2632f167a42Smrg 264e6bced22Smrg { 265e6bced22Smrg char *a = XkbAtomGetString(state->dpy, shape->name); 266e6bced22Smrg fprintf(out, "/%s {\n", a); 267e6bced22Smrg XFree(a); 268e6bced22Smrg } 2692f167a42Smrg fprintf(out, " gsave translate rotate /SOLID exch def\n"); 2702f167a42Smrg for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) { 2712f167a42Smrg XkbPointPtr pt; 2722f167a42Smrg 2732f167a42Smrg if ((shape->num_outlines > 1) && (ol == shape->approx)) 2742f167a42Smrg continue; 2752f167a42Smrg pt = ol->points; 2762f167a42Smrg fprintf(out, "%% Outline %d\n", o + 1); 2772f167a42Smrg if (ol->num_points == 1) { 2782f167a42Smrg if (ol->corner_radius < 1) { 2792f167a42Smrg fprintf(out, " 0 0 moveto\n"); 2802f167a42Smrg fprintf(out, " %3d 0 lineto\n", pt->x); 2812f167a42Smrg fprintf(out, " %3d %3d lineto\n", pt->x, pt->y); 2822f167a42Smrg fprintf(out, " 0 %3d lineto\n", pt->y); 2832f167a42Smrg fprintf(out, " 0 0 lineto\n"); 2842f167a42Smrg fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 2852f167a42Smrg } 2862f167a42Smrg else { 2872f167a42Smrg fprintf(out, " mark\n"); 2882f167a42Smrg fprintf(out, " %3d 0 moveto\n", ol->corner_radius); 2892f167a42Smrg fprintf(out, " %3d 0 %3d %3d %3d arcto\n", pt->x, pt->x, 2902f167a42Smrg pt->y, ol->corner_radius); 2912f167a42Smrg fprintf(out, " %3d %3d 0 %3d %3d arcto\n", pt->x, pt->y, 2922f167a42Smrg pt->y, ol->corner_radius); 2932f167a42Smrg fprintf(out, " 0 %3d 0 0 %3d arcto\n", pt->y, 2942f167a42Smrg ol->corner_radius); 2952f167a42Smrg fprintf(out, " 0 0 %3d 0 %3d arcto\n", pt->x, 2962f167a42Smrg ol->corner_radius); 2972f167a42Smrg fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 2982f167a42Smrg fprintf(out, " cleartomark\n"); 2992f167a42Smrg } 3002f167a42Smrg } 3012f167a42Smrg else if (ol->num_points == 2) { 3022f167a42Smrg if (ol->corner_radius < 1) { 3032f167a42Smrg fprintf(out, " %3d %3d moveto\n", pt[0].x, pt[0].y); 3042f167a42Smrg fprintf(out, " %3d %3d lineto\n", pt[1].x, pt[0].y); 3052f167a42Smrg fprintf(out, " %3d %3d lineto\n", pt[1].x, pt[1].y); 3062f167a42Smrg fprintf(out, " %3d %3d lineto\n", pt[0].x, pt[1].y); 3072f167a42Smrg fprintf(out, " %3d %3d lineto\n", pt[0].x, pt[0].y); 3082f167a42Smrg fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 3092f167a42Smrg } 3102f167a42Smrg else { 3112f167a42Smrg fprintf(out, " mark\n"); 3122f167a42Smrg fprintf(out, " %3d %3d moveto\n", pt[0].x + ol->corner_radius, 3132f167a42Smrg pt[0].y); 3142f167a42Smrg fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[0].y, 3152f167a42Smrg pt[1].x, pt[1].y, ol->corner_radius); 3162f167a42Smrg fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[1].y, 3172f167a42Smrg pt[0].x, pt[1].y, ol->corner_radius); 3182f167a42Smrg fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[1].y, 3192f167a42Smrg pt[0].x, pt[0].y, ol->corner_radius); 3202f167a42Smrg fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[0].y, 3212f167a42Smrg pt[1].x, pt[0].y, ol->corner_radius); 3222f167a42Smrg fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 3232f167a42Smrg fprintf(out, " cleartomark\n"); 3242f167a42Smrg } 3252f167a42Smrg } 3262f167a42Smrg else { 3272f167a42Smrg if (ol->corner_radius < 1) { 3282f167a42Smrg fprintf(out, " %3d %3d moveto\n", pt->x, pt->y); 3292f167a42Smrg pt++; 3308b648e79Smrg for (int p = 1; p < ol->num_points; p++, pt++) { 3312f167a42Smrg fprintf(out, " %3d %3d lineto\n", pt->x, pt->y); 3322f167a42Smrg } 3332f167a42Smrg if ((pt->x != ol->points[0].x) || (pt->y != ol->points[0].y)) 3342f167a42Smrg fprintf(out, " closepath\n"); 3352f167a42Smrg fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 3362f167a42Smrg } 3372f167a42Smrg else { 3382f167a42Smrg XkbPointPtr last; 3392f167a42Smrg 3402f167a42Smrg last = &pt[ol->num_points - 1]; 3412f167a42Smrg if ((last->x == pt->x) && (last->y == pt->y)) 3422f167a42Smrg last--; 3432f167a42Smrg fprintf(out, " mark\n"); 3442f167a42Smrg fprintf(out, " %% Determine tangent point of first corner\n"); 3452f167a42Smrg fprintf(out, " %3d %3d moveto %d %d %d %d %d arcto\n", 3462f167a42Smrg last->x, last->y, 3472f167a42Smrg pt[0].x, pt[0].y, pt[1].x, pt[1].y, ol->corner_radius); 3482f167a42Smrg fprintf(out, " /TY exch def /TX exch def pop pop newpath\n"); 3492f167a42Smrg fprintf(out, " %% Now draw the shape\n"); 3502f167a42Smrg fprintf(out, " TX TY moveto\n"); 3518b648e79Smrg for (int p = 1; p < ol->num_points; p++) { 3522f167a42Smrg if (p < (ol->num_points - 1)) 3532f167a42Smrg last = &pt[p + 1]; 3542f167a42Smrg else 3552f167a42Smrg last = &pt[0]; 3562f167a42Smrg fprintf(out, " %3d %3d %3d %3d %3d arcto\n", 3572f167a42Smrg pt[p].x, pt[p].y, 3582f167a42Smrg last->x, last->y, ol->corner_radius); 3592f167a42Smrg } 3602f167a42Smrg last = &pt[ol->num_points - 1]; 3612f167a42Smrg if ((last->x != pt->x) || (last->y != pt->y)) { 3622f167a42Smrg fprintf(out, " %3d %3d %3d %3d %3d arcto\n", 3632f167a42Smrg pt[0].x, pt[0].y, 3642f167a42Smrg pt[1].x, pt[1].y, ol->corner_radius); 3652f167a42Smrg } 3662f167a42Smrg fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 3672f167a42Smrg fprintf(out, " cleartomark\n"); 3682f167a42Smrg } 3692f167a42Smrg } 3700e20ee16Smrg } 3712f167a42Smrg fprintf(out, " grestore\n"); 3722f167a42Smrg fprintf(out, "} def\n"); 3730e20ee16Smrg return; 3740e20ee16Smrg} 3750e20ee16Smrg 3760e20ee16Smrg/***====================================================================***/ 3770e20ee16Smrg 3782f167a42Smrgtypedef struct { 3792f167a42Smrg char * foundry; 3802f167a42Smrg char * face; 3812f167a42Smrg char * weight; 3822f167a42Smrg char * slant; 3832f167a42Smrg char * setWidth; 3842f167a42Smrg char * variant; 3852f167a42Smrg int pixelSize; 3862f167a42Smrg int ptSize; 3872f167a42Smrg int resX; 3882f167a42Smrg int resY; 3892f167a42Smrg char * spacing; 3902f167a42Smrg int avgWidth; 3912f167a42Smrg char * encoding; 3920e20ee16Smrg} FontStuff; 3930e20ee16Smrg 3940e20ee16Smrgstatic void 3950e20ee16SmrgClearFontStuff(FontStuff *stuff) 3960e20ee16Smrg{ 3978b648e79Smrg if (stuff) { 3982f167a42Smrg free(stuff->foundry); 3998b648e79Smrg bzero(stuff, sizeof(FontStuff)); 4008b648e79Smrg } 4010e20ee16Smrg return; 4020e20ee16Smrg} 4030e20ee16Smrg 4040e20ee16Smrgstatic Bool 4052f167a42SmrgCrackXLFDName(const char *name, FontStuff *stuff) 4060e20ee16Smrg{ 4072f167a42Smrg char *tmp; 4082f167a42Smrg 4092f167a42Smrg if ((name == NULL) || (stuff == NULL)) 4102f167a42Smrg return False; 4112f167a42Smrg if (name[0] == '-') 4122f167a42Smrg tmp = strdup(&name[1]); 4132f167a42Smrg else 4142f167a42Smrg tmp = strdup(name); 4152f167a42Smrg if (tmp == NULL) 4162f167a42Smrg return False; 4172f167a42Smrg stuff->foundry = tmp; 4182f167a42Smrg 4192f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4202f167a42Smrg goto BAILOUT; 4212f167a42Smrg else 4222f167a42Smrg *tmp++ = '\0'; 4232f167a42Smrg stuff->face = tmp; 4242f167a42Smrg 4252f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4262f167a42Smrg goto BAILOUT; 4272f167a42Smrg else 4282f167a42Smrg *tmp++ = '\0'; 4292f167a42Smrg stuff->weight = tmp; 4302f167a42Smrg 4312f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4322f167a42Smrg goto BAILOUT; 4332f167a42Smrg else 4342f167a42Smrg *tmp++ = '\0'; 4352f167a42Smrg stuff->slant = tmp; 4362f167a42Smrg 4372f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4382f167a42Smrg goto BAILOUT; 4392f167a42Smrg else 4402f167a42Smrg *tmp++ = '\0'; 4412f167a42Smrg stuff->setWidth = tmp; 4422f167a42Smrg 4432f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4442f167a42Smrg goto BAILOUT; 4452f167a42Smrg else 4462f167a42Smrg *tmp++ = '\0'; 4472f167a42Smrg stuff->variant = tmp; 4482f167a42Smrg 4492f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4502f167a42Smrg goto BAILOUT; 4512f167a42Smrg else 4522f167a42Smrg *tmp++ = '\0'; 4532f167a42Smrg if (*tmp == '*') 4542f167a42Smrg stuff->pixelSize = 0; 4552f167a42Smrg else if (sscanf(tmp, "%i", &stuff->pixelSize) != 1) 4562f167a42Smrg goto BAILOUT; 4572f167a42Smrg 4582f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4592f167a42Smrg goto BAILOUT; 4602f167a42Smrg else 4612f167a42Smrg *tmp++ = '\0'; 4622f167a42Smrg if (*tmp == '*') 4632f167a42Smrg stuff->ptSize = 0; 4642f167a42Smrg else if (sscanf(tmp, "%i", &stuff->ptSize) != 1) 4652f167a42Smrg goto BAILOUT; 4662f167a42Smrg 4672f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4682f167a42Smrg goto BAILOUT; 4692f167a42Smrg else 4702f167a42Smrg *tmp++ = '\0'; 4712f167a42Smrg if (*tmp == '*') 4722f167a42Smrg stuff->resX = 0; 4732f167a42Smrg else if (sscanf(tmp, "%i", &stuff->resX) != 1) 4742f167a42Smrg goto BAILOUT; 4752f167a42Smrg 4762f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4772f167a42Smrg goto BAILOUT; 4782f167a42Smrg else 4792f167a42Smrg *tmp++ = '\0'; 4802f167a42Smrg if (*tmp == '*') 4812f167a42Smrg stuff->resY = 0; 4822f167a42Smrg else if (sscanf(tmp, "%i", &stuff->resY) != 1) 4832f167a42Smrg goto BAILOUT; 4842f167a42Smrg 4852f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4862f167a42Smrg goto BAILOUT; 4872f167a42Smrg else 4882f167a42Smrg *tmp++ = '\0'; 4892f167a42Smrg stuff->spacing = tmp; 4902f167a42Smrg 4912f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 4922f167a42Smrg goto BAILOUT; 4932f167a42Smrg else 4942f167a42Smrg *tmp++ = '\0'; 4952f167a42Smrg if (*tmp == '*') 4962f167a42Smrg stuff->avgWidth = 0; 4972f167a42Smrg else if (sscanf(tmp, "%i", &stuff->avgWidth) != 1) 4982f167a42Smrg goto BAILOUT; 4992f167a42Smrg 5002f167a42Smrg if ((tmp = strchr(tmp, '-')) == NULL) 5012f167a42Smrg goto BAILOUT; 5022f167a42Smrg else 5032f167a42Smrg *tmp++ = '\0'; 5042f167a42Smrg stuff->encoding = tmp; 5050e20ee16Smrg return True; 5062f167a42Smrg BAILOUT: 5070e20ee16Smrg ClearFontStuff(stuff); 5080e20ee16Smrg return False; 5090e20ee16Smrg} 5100e20ee16Smrg 5110e20ee16Smrgstatic void 5120e20ee16SmrgPSSetUpForLatin1(FILE *out, PSState *state) 5130e20ee16Smrg{ 5142f167a42Smrg fprintf(out, "%s", 5152f167a42Smrg "save\n" 5162f167a42Smrg "/ISOLatin1Encoding where {pop save true}{false} ifelse\n" 5172f167a42Smrg "/ISOLatin1Encoding [\n" 5182f167a42Smrg " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 5192f167a42Smrg " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 5202f167a42Smrg " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 5212f167a42Smrg " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 5222f167a42Smrg " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 5232f167a42Smrg " /.notdef /.notdef /space /exclam /quotedbl /numbersign\n" 5242f167a42Smrg " /dollar /percent /ampersand /quoteright /parenleft\n" 5252f167a42Smrg " /parenright /asterisk /plus /comma /minus /period\n" 5262f167a42Smrg " /slash /zero /one /two /three /four /five /six /seven\n" 5272f167a42Smrg " /eight /nine /colon /semicolon /less /equal /greater\n" 5282f167a42Smrg " /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M\n" 5292f167a42Smrg " /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n" 5302f167a42Smrg " /backslash /bracketright /asciicircum /underscore\n" 5312f167a42Smrg " /quoteleft /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 /braceleft\n" 5332f167a42Smrg " /bar /braceright /asciitilde /guilsinglright /fraction\n" 5342f167a42Smrg " /florin /quotesingle /quotedblleft /guilsinglleft /fi\n" 5352f167a42Smrg " /fl /endash /dagger /daggerdbl /bullet /quotesinglbase\n" 5362f167a42Smrg " /quotedblbase /quotedblright /ellipsis /trademark\n" 5372f167a42Smrg " /perthousand /grave /scaron /circumflex /Scaron /tilde\n" 5382f167a42Smrg " /breve /zcaron /dotaccent /dotlessi /Zcaron /ring\n" 5392f167a42Smrg " /hungarumlaut /ogonek /caron /emdash /space /exclamdown\n" 5402f167a42Smrg " /cent /sterling /currency /yen /brokenbar /section\n" 5412f167a42Smrg " /dieresis /copyright /ordfeminine /guillemotleft\n" 5422f167a42Smrg " /logicalnot /hyphen /registered /macron /degree\n" 5432f167a42Smrg " /plusminus /twosuperior /threesuperior /acute /mu\n" 5442f167a42Smrg " /paragraph /periodcentered /cedilla /onesuperior\n" 5452f167a42Smrg " /ordmasculine /guillemotright /onequarter /onehalf\n" 5462f167a42Smrg " /threequarters /questiondown /Agrave /Aacute\n" 5472f167a42Smrg " /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n" 5482f167a42Smrg " /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute\n" 5492f167a42Smrg " /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute\n" 5502f167a42Smrg " /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n" 5512f167a42Smrg " /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n" 5522f167a42Smrg " /germandbls /agrave /aacute /acircumflex /atilde\n" 5532f167a42Smrg " /adieresis /aring /ae /ccedilla /egrave /eacute\n" 5542f167a42Smrg " /ecircumflex /edieresis /igrave /iacute /icircumflex\n" 5552f167a42Smrg " /idieresis /eth /ntilde /ograve /oacute /ocircumflex\n" 5562f167a42Smrg " /otilde /odieresis /divide /oslash /ugrave /uacute\n" 5572f167a42Smrg " /ucircumflex /udieresis /yacute /thorn /ydieresis\n" 5582f167a42Smrg "] def {restore} if\n" 5592f167a42Smrg "/reencodeISO-1 {\n" 5602f167a42Smrg " dup length dict begin\n" 5612f167a42Smrg " {1 index /FID ne {def}{pop pop} ifelse} forall\n" 5622f167a42Smrg " /Encoding ISOLatin1Encoding def\n" 5632f167a42Smrg " currentdict\n" 5642f167a42Smrg " end\n" 5652f167a42Smrg "} def\n" 5662f167a42Smrg ); 5670e20ee16Smrg} 5680e20ee16Smrg 5690e20ee16Smrgstatic void 5702f167a42SmrgPSReencodeLatin1Font(FILE *out, const char *font) 5710e20ee16Smrg{ 5722f167a42Smrg fprintf(out, "/%s findfont reencodeISO-1\n", font); 5732f167a42Smrg fprintf(out, " /%s-8859-1 exch definefont pop\n", font); 5740e20ee16Smrg return; 5750e20ee16Smrg} 5760e20ee16Smrg 5770e20ee16Smrgstatic void 5782f167a42SmrgPSSetUpFonts(FILE *out, const char *textFont, int size) 5790e20ee16Smrg{ 5802f167a42Smrg fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n", 5812f167a42Smrg FONT_TEXT, textFont); 5822f167a42Smrg fprintf(out, "/F%d { /%s-8859-1 findfont exch scalefont setfont } def\n", 5832f167a42Smrg FONT_LATIN1, textFont); 5842f167a42Smrg fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n", 5852f167a42Smrg FONT_SYMBOL, "Symbol"); 5862f167a42Smrg fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n", 5872f167a42Smrg FONT_ISOCAPS, "IsoKeyCaps"); 5880e20ee16Smrg return; 5890e20ee16Smrg} 5900e20ee16Smrg 5910e20ee16Smrgstatic void 5920e20ee16SmrgPSSetFont(FILE *out, PSState *state, int font, int size, int pts) 5930e20ee16Smrg{ 5942f167a42Smrg if ((state->font != font) || (state->fontSize != size)) { 5952f167a42Smrg fprintf(out, "%d %sF%d\n", size, (pts ? "pts " : ""), font); 5962f167a42Smrg state->font = font; 5972f167a42Smrg state->fontSize = size; 5980e20ee16Smrg } 5990e20ee16Smrg return; 6000e20ee16Smrg} 6010e20ee16Smrg 6020e20ee16Smrgstatic void 6030e20ee16SmrgPSProlog(FILE *out, PSState *state) 6040e20ee16Smrg{ 6050e20ee16Smrg if (!state->args->wantEPS) { 6062f167a42Smrg fprintf(out, 6072f167a42Smrg "%%!PS-Adobe-2.0\n" 6082f167a42Smrg "%%%%Creator: xkbprint\n"); 609e6bced22Smrg if (state->geom->name != None) { 610e6bced22Smrg char *a = XkbAtomGetString(state->dpy, state->geom->name); 611e6bced22Smrg fprintf(out, "%%%%Title: %s\n", a); 612e6bced22Smrg XFree(a); 613e6bced22Smrg } 6142f167a42Smrg fprintf(out, 6152f167a42Smrg "%%%%BoundingBox: (atend)\n" 6162f167a42Smrg "%%%%Pages: 1\n" 6172f167a42Smrg "%%%%PageOrder: Ascend\n" 6182f167a42Smrg "%%%%DocumentFonts: (atend)\n" 6192f167a42Smrg "%%%%DocumentData: Clean7Bit\n" 6202f167a42Smrg "%%%%Orientation: Landscape\n" 6212f167a42Smrg "%%%%EndComments\n" 6222f167a42Smrg "%%%%BeginProlog\n" 6232f167a42Smrg "%% Resolution is 1/10mm -- need pt sizes for fonts\n" 6242f167a42Smrg "clippath pathbbox\n" 6252f167a42Smrg " /ury exch def /urx exch def\n" 6262f167a42Smrg " /llx exch def /lly exch def\n" 6272f167a42Smrg " newpath\n" 6282f167a42Smrg "/devwidth urx llx sub def\n" 6292f167a42Smrg "/devheight ury lly sub def\n"); 6300e20ee16Smrg } 6310e20ee16Smrg else { 6322f167a42Smrg int w, h; 6332f167a42Smrg int pw, ph; 6342f167a42Smrg 6352f167a42Smrg w = (((state->geom->width_mm * 72) / 254) * 11) / 10; 6362f167a42Smrg h = (((state->geom->height_mm * 72) / 254) * 11) / 10; 6372f167a42Smrg if (state->kbPerPage > 1) 6382f167a42Smrg h *= (state->kbPerPage + 1); 6392f167a42Smrg 6402f167a42Smrg if (w <= h) { 6412f167a42Smrg pw = 7.5 * 72; 6422f167a42Smrg ph = 10 * 72; 6432f167a42Smrg } 6442f167a42Smrg else { 6452f167a42Smrg pw = 10 * 72; 6462f167a42Smrg ph = 7.5 * 72; 6472f167a42Smrg } 6482f167a42Smrg while ((w > pw) || (h > ph)) { 6492f167a42Smrg w = (w * 9) / 10; 6502f167a42Smrg h = (h * 9) / 10; 6512f167a42Smrg } 6522f167a42Smrg 6532f167a42Smrg fprintf(out, "%%!PS-Adobe-2.0 EPSF-2.0\n"); 6542f167a42Smrg fprintf(out, "%%%%BoundingBox: 0 0 %d %d\n", w, h); 6552f167a42Smrg fprintf(out, "%%%%Creator: xkbprint\n"); 656e6bced22Smrg if (state->geom->name != None) { 657e6bced22Smrg char *a = XkbAtomGetString(state->dpy, state->geom->name); 658e6bced22Smrg fprintf(out, "%%%%Title: %s\n", a); 659e6bced22Smrg XFree(a); 660e6bced22Smrg } 6612f167a42Smrg fprintf(out, "%%%%Pages: 1\n"); 6622f167a42Smrg fprintf(out, "%%%%EndComments\n"); 6632f167a42Smrg fprintf(out, "%%%%BeginProlog\n"); 6642f167a42Smrg fprintf(out, "/ury 0 def /urx 0 def\n"); 6652f167a42Smrg fprintf(out, "/llx %d def /lly %d def\n", w, h); 6662f167a42Smrg fprintf(out, "/devwidth %d def /devheight %d def\n", w, h); 6670e20ee16Smrg } 6682f167a42Smrg fprintf(out, "/kbdwidth %d def\n", state->geom->width_mm); 6692f167a42Smrg fprintf(out, "/kbdheight %d def\n", state->geom->height_mm); 6702f167a42Smrg fprintf(out, "%s", 6712f167a42Smrg "/pts { 254 mul 72 div } def\n" 6722f167a42Smrg "/mm10 { 72 mul 254 div } def\n" 6732f167a42Smrg "/landscape? {\n" 6742f167a42Smrg " devheight devwidth gt {\n" 6752f167a42Smrg " /pwidth devheight def /pheight devwidth def\n" 6762f167a42Smrg " 0 devheight translate\n" 6772f167a42Smrg " -90 rotate\n" 6782f167a42Smrg " } {\n" 6792f167a42Smrg " /pwidth devwidth def /pheight devheight def\n" 6802f167a42Smrg " } ifelse\n" 6812f167a42Smrg " 0 pheight translate\n" 6822f167a42Smrg " 1 -1 scale\n" 6832f167a42Smrg "} def\n" 6842f167a42Smrg "/centeroffset {\n" 6852f167a42Smrg " /S exch def\n" 6862f167a42Smrg " /HEIGHT exch def\n" 6872f167a42Smrg " /WIDTH exch def\n" 6882f167a42Smrg " S stringwidth /SH exch def /SW exch def\n" 6892f167a42Smrg " WIDTH SW sub 2 div\n" 6902f167a42Smrg " HEIGHT SH sub 2 div\n" 6912f167a42Smrg "} def\n"); 6922f167a42Smrg PSSetUpForLatin1(out, state); 6932f167a42Smrg PSReencodeLatin1Font(out, DFLT_LABEL_FONT); 6940e20ee16Smrg if (state->args->wantColor) { 6952f167a42Smrg XkbGeometryPtr geom = state->geom; 6962f167a42Smrg 6978b648e79Smrg for (int i = 0; i < geom->num_colors; i++) { 6982f167a42Smrg PSColorDef(out, state, &geom->colors[i]); 6992f167a42Smrg } 7002f167a42Smrg if (state->black < 0) { 7012f167a42Smrg XkbColorPtr color; 7022f167a42Smrg 7032f167a42Smrg if (!(color = XkbAddGeomColor(geom, "black", geom->num_colors))) 7042f167a42Smrg uFatalError("Couldn't allocate black color!\n"); 7052f167a42Smrg PSColorDef(out, state, color); 7062f167a42Smrg } 7072f167a42Smrg if (state->white < 0) { 7082f167a42Smrg XkbColorPtr color; 7092f167a42Smrg 7102f167a42Smrg if (!(color = XkbAddGeomColor(geom, "white", geom->num_colors))) 7112f167a42Smrg uFatalError("Couldn't allocate white color!\n"); 7122f167a42Smrg PSColorDef(out, state, color); 7132f167a42Smrg } 7140e20ee16Smrg } 7158b648e79Smrg for (int i = 0; i < state->geom->num_shapes; i++) { 7162f167a42Smrg PSShapeDef(out, state, &state->geom->shapes[i]); 7170e20ee16Smrg } 7182f167a42Smrg if (state->args->label == LABEL_SYMBOLS) { 7192f167a42Smrg PSIncludeFont(out, "IsoKeyCaps"); 7200e20ee16Smrg } 7212f167a42Smrg PSSetUpFonts(out, DFLT_LABEL_FONT, DFLT_LABEL_FONT_SIZE); 7222f167a42Smrg fprintf(out, "%%%%EndProlog\n"); 7230e20ee16Smrg return; 7240e20ee16Smrg} 7250e20ee16Smrg 7260e20ee16Smrgstatic void 7270e20ee16SmrgPSFileTrailer(FILE *out, PSState *state) 7280e20ee16Smrg{ 7292f167a42Smrg fprintf(out, "restore\n"); 7300e20ee16Smrg if (!state->args->wantEPS) 7312f167a42Smrg fprintf(out, "%%%%Trailer\n"); 7322f167a42Smrg fprintf(out, "%%%%EOF\n"); 7330e20ee16Smrg return; 7340e20ee16Smrg} 7350e20ee16Smrg 7360e20ee16Smrgstatic void 7370e20ee16SmrgPSPageSetup(FILE *out, PSState *state, Bool drawBorder) 7380e20ee16Smrg{ 7392f167a42Smrg XkbGeometryPtr geom; 7400e20ee16Smrg 7412f167a42Smrg geom = state->geom; 7422f167a42Smrg if (state->kbPerPage == 1) { 7432f167a42Smrg fprintf(out, "%%%%Page: %d %d\n", state->nPages + 1, state->nPages + 1); 7442f167a42Smrg fprintf(out, "%%%%BeginPageSetup\n"); 7450e20ee16Smrg } 7462f167a42Smrg else if ((state->nPages & 1) == 0) { /* even page */ 7472f167a42Smrg int realPage; 7482f167a42Smrg 7492f167a42Smrg realPage = state->nPages / 2 + 1; 7502f167a42Smrg fprintf(out, "%%%%Page: %d %d\n", realPage, realPage); 7512f167a42Smrg fprintf(out, "%%%%BeginPageSetup\n"); 7522f167a42Smrg fprintf(out, "%% Keyboard %d\n", state->nPages + 1); 7532f167a42Smrg if (state->nPages == 0) { 7542f167a42Smrg fprintf(out, 7552f167a42Smrg "/realwidth devwidth def\n" 7562f167a42Smrg "/realheight devheight def\n" 7572f167a42Smrg "/devheight realheight 3 div def\n"); 7582f167a42Smrg } 7592f167a42Smrg fprintf(out, "0 devheight dup 2 div add translate\n"); 7600e20ee16Smrg } 7612f167a42Smrg else { 7622f167a42Smrg fprintf(out, "%% Keyboard %d\n", state->nPages + 1); 7630e20ee16Smrg } 7642f167a42Smrg fprintf(out, "save\n"); 7652f167a42Smrg fprintf(out, "landscape?\n"); 7660e20ee16Smrg if (state->args->scaleToFit) { 7672f167a42Smrg fprintf(out, 7682f167a42Smrg "%% Scale keyboard to fit on the page\n" 7692f167a42Smrg "/kbdscale pwidth 72 sub kbdwidth div def\n" 7702f167a42Smrg "/kbdscalewidth kbdwidth kbdscale mul def\n" 7712f167a42Smrg "/kbdscaleheight kbdheight kbdscale mul def\n" 7722f167a42Smrg "/kbx 36 def\n" 7732f167a42Smrg "/kby pheight kbdscaleheight sub 2 div def\n"); 7742f167a42Smrg PSGSave(out, state); 7752f167a42Smrg fprintf(out, 7762f167a42Smrg "kbx kby translate\n" 7772f167a42Smrg "kbdscale kbdscale scale\n"); 7780e20ee16Smrg } 7790e20ee16Smrg else { 7802f167a42Smrg fprintf(out, 7812f167a42Smrg "%% Draw keyboard full size\n" 7822f167a42Smrg "/kbdscale 1 def\n" 7832f167a42Smrg "/kbdscalewidth kbdwidth mm10 def\n" 7842f167a42Smrg "/kbdscaleheight kbdheight mm10 def\n" 7852f167a42Smrg "/kbx pwidth kbdscalewidth sub 2 div def\n" 7862f167a42Smrg "/kby pheight kbdscaleheight sub 2 div def\n"); 7872f167a42Smrg PSGSave(out, state); 7882f167a42Smrg fprintf(out, 7892f167a42Smrg "kbx kby translate\n" 7902f167a42Smrg "72 254 div dup scale\n"); 7910e20ee16Smrg } 7920e20ee16Smrg if (drawBorder) { 7932f167a42Smrg if (state->args->wantColor) { 7942f167a42Smrg PSSetColor(out, state, geom->base_color->pixel); 7952f167a42Smrg fprintf(out, " 0 0 moveto\n"); 7962f167a42Smrg fprintf(out, "%3d 0 lineto\n", geom->width_mm); 7972f167a42Smrg fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm); 7982f167a42Smrg fprintf(out, " 0 %3d lineto\n", geom->height_mm); 7992f167a42Smrg fprintf(out, "closepath fill\n"); 8002f167a42Smrg } 8012f167a42Smrg PSSetColor(out, state, state->black); 8022f167a42Smrg fprintf(out, " 0 0 moveto\n"); 8032f167a42Smrg fprintf(out, "%3d 0 lineto\n", geom->width_mm); 8042f167a42Smrg fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm); 8052f167a42Smrg fprintf(out, " 0 %3d lineto\n", geom->height_mm); 8062f167a42Smrg fprintf(out, "closepath stroke\n"); 8070e20ee16Smrg } 8082f167a42Smrg fprintf(out, "%%%%EndPageSetup\n"); 8090e20ee16Smrg return; 8100e20ee16Smrg} 8110e20ee16Smrg 8120e20ee16Smrgstatic void 8130e20ee16SmrgPSPageTrailer(FILE *out, PSState *state) 8140e20ee16Smrg{ 8152f167a42Smrg char *name; 8162f167a42Smrg XkbDescPtr xkb; 8172f167a42Smrg XkbGeometryPtr geom; 8182f167a42Smrg XkbPropertyPtr prop; 8192f167a42Smrg int p, baseline; 8202f167a42Smrg 8212f167a42Smrg xkb = state->xkb; 8222f167a42Smrg geom = state->geom; 8232f167a42Smrg if (state->args->grid > 0) { 8242f167a42Smrg fprintf(out, "%% Draw a %dmm grid\n", state->args->grid); 8252f167a42Smrg fprintf(out, "0 setlinewidth\n"); 8262f167a42Smrg fprintf(out, "0.25 setgray\n"); 8272f167a42Smrg fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->width_mm); 8282f167a42Smrg fprintf(out, " /GX exch def\n"); 8292f167a42Smrg fprintf(out, " GX 0 moveto GX %d lineto stroke\n", geom->height_mm); 8302f167a42Smrg fprintf(out, "} for\n"); 8312f167a42Smrg fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->height_mm); 8322f167a42Smrg fprintf(out, " /GY exch def\n"); 8332f167a42Smrg fprintf(out, " 0 GY moveto %d GY lineto stroke\n", geom->width_mm); 8342f167a42Smrg fprintf(out, "} for\n"); 8350e20ee16Smrg } 8362f167a42Smrg PSGRestore(out, state); 8372f167a42Smrg name = NULL; 8382f167a42Smrg for (p = 0, prop = geom->properties; p < geom->num_properties; p++, prop++) { 8392f167a42Smrg if ((prop->value != NULL) && (uStrCaseEqual(prop->name, "description"))) { 8402f167a42Smrg name = prop->value; 8412f167a42Smrg break; 8422f167a42Smrg } 8430e20ee16Smrg } 8442f167a42Smrg if ((!state->args->wantEPS) && 8452f167a42Smrg ((state->kbPerPage == 1) || ((state->nPages & 1) == 1) || 8462f167a42Smrg (state->nPages == state->totalKB))) { 847e6bced22Smrg char *a1 = NULL; 848e6bced22Smrg 8492f167a42Smrg if ((name == NULL) && (geom->name != None)) 850e6bced22Smrg name = a1 = XkbAtomGetString(state->dpy, geom->name); 8512f167a42Smrg 8522f167a42Smrg baseline = 16; 8532f167a42Smrg if ((name != NULL) || (state->args->label == LABEL_SYMBOLS)) { 8542f167a42Smrg PSSetColor(out, state, state->black); 8552f167a42Smrg PSSetFont(out, state, FONT_LATIN1, 14, False); 8562f167a42Smrg } 8572f167a42Smrg if (state->args->label == LABEL_SYMBOLS) { 8582f167a42Smrg char buf[40], *lbuf; 8592f167a42Smrg const char *sName = NULL; 860e6bced22Smrg char *a2 = NULL; 8612f167a42Smrg Atom sAtom; 8622f167a42Smrg 8632f167a42Smrg if (state->args->nLabelGroups == 1) 8642f167a42Smrg snprintf(buf, sizeof(buf), "Group %d", 8652f167a42Smrg state->args->baseLabelGroup + 1); 8662f167a42Smrg else 8672f167a42Smrg snprintf(buf, sizeof(buf), "Groups %d-%d", 8682f167a42Smrg state->args->baseLabelGroup + 1, 8692f167a42Smrg state->args->baseLabelGroup + 8702f167a42Smrg state->args->nLabelGroups); 8712f167a42Smrg fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 8722f167a42Smrg buf); 8732f167a42Smrg fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 8742f167a42Smrg fprintf(out, " moveto\n"); 8752f167a42Smrg fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf); 8762f167a42Smrg baseline += 16; 8772f167a42Smrg 8782f167a42Smrg if (xkb->names != NULL) 8792f167a42Smrg sAtom = xkb->names->symbols; 8802f167a42Smrg else 8812f167a42Smrg sAtom = None; 8822f167a42Smrg if (sAtom != None) 883e6bced22Smrg sName = a2 = XkbAtomGetString(state->dpy, sAtom); 8842f167a42Smrg if (sName == NULL) 8852f167a42Smrg sName = "(unknown)"; 8862f167a42Smrg 8872f167a42Smrg if (asprintf(&lbuf, "Layout: %s", sName) == -1) { 8882f167a42Smrg uFatalError("Can't allocate memory for string\n"); 8892f167a42Smrg } 8902f167a42Smrg fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 8912f167a42Smrg lbuf); 8922f167a42Smrg fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 8932f167a42Smrg fprintf(out, " moveto\n"); 8942f167a42Smrg fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf); 8952f167a42Smrg baseline += 16; 8962f167a42Smrg free(lbuf); 897e6bced22Smrg XFree(a2); 8982f167a42Smrg } 8992f167a42Smrg if (name != NULL) { 9002f167a42Smrg fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 9012f167a42Smrg name); 9022f167a42Smrg fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 9032f167a42Smrg fprintf(out, " moveto\n"); 9042f167a42Smrg fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", name); 9052f167a42Smrg baseline += 16; 906e6bced22Smrg name = NULL; 907e6bced22Smrg XFree(a1); 9082f167a42Smrg } 9092f167a42Smrg if (state->args->label == LABEL_KEYCODE) { 9102f167a42Smrg const char *sName = NULL; 9112f167a42Smrg char *lbuf; 912e6bced22Smrg char *a3 = NULL; 9132f167a42Smrg Atom sAtom; 9142f167a42Smrg 9152f167a42Smrg if (xkb->names != NULL) 9162f167a42Smrg sAtom = xkb->names->keycodes; 9172f167a42Smrg else 9182f167a42Smrg sAtom = None; 9192f167a42Smrg if (sAtom != None) 920e6bced22Smrg sName = a3 = XkbAtomGetString(state->dpy, sAtom); 9212f167a42Smrg if (sName == NULL) 9222f167a42Smrg sName = "(unknown)"; 9232f167a42Smrg 9242f167a42Smrg if (asprintf(&lbuf, "Keycodes: %s", sName) == -1) { 9252f167a42Smrg uFatalError("Can't allocate memory for string\n"); 9262f167a42Smrg } 9272f167a42Smrg fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 9282f167a42Smrg lbuf); 9292f167a42Smrg fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 9302f167a42Smrg fprintf(out, " moveto\n"); 9312f167a42Smrg fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf); 9322f167a42Smrg baseline += 16; 9332f167a42Smrg free(lbuf); 934e6bced22Smrg XFree(a3); 9352f167a42Smrg } 9362f167a42Smrg if (state->args->copies > 1) { 9372f167a42Smrg for (p = 1; p < state->args->copies; p++) 9382f167a42Smrg fprintf(out, "copypage\n"); 9392f167a42Smrg } 9402f167a42Smrg fprintf(out, "showpage\n"); 9412f167a42Smrg fprintf(out, "restore\n"); 9422f167a42Smrg fprintf(out, "%% Done with keyboard/page %d\n", state->nPages + 1); 9430e20ee16Smrg } 9440e20ee16Smrg else { 9452f167a42Smrg if ((!state->args->wantEPS) && (state->args->label == LABEL_SYMBOLS)) { 9462f167a42Smrg char buf[40]; 9472f167a42Smrg 9482f167a42Smrg baseline = 16; 9492f167a42Smrg PSSetColor(out, state, state->black); 9502f167a42Smrg PSSetFont(out, state, FONT_LATIN1, 14, False); 9512f167a42Smrg if (state->args->nLabelGroups == 1) 9522f167a42Smrg snprintf(buf, sizeof(buf), "Group %d", 9532f167a42Smrg state->args->baseLabelGroup + 1); 9542f167a42Smrg else 9552f167a42Smrg snprintf(buf, sizeof(buf), "Groups %d-%d", 9562f167a42Smrg state->args->baseLabelGroup + 1, 9572f167a42Smrg state->args->baseLabelGroup + 9582f167a42Smrg state->args->nLabelGroups + 1); 9592f167a42Smrg fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 9602f167a42Smrg buf); 9612f167a42Smrg fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 9622f167a42Smrg fprintf(out, " moveto\n"); 9632f167a42Smrg fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf); 9642f167a42Smrg baseline += 16; 9652f167a42Smrg } 9662f167a42Smrg fprintf(out, "restore\n"); 9672f167a42Smrg fprintf(out, "%% Done with keyboard %d\n", state->nPages + 1); 9682f167a42Smrg fprintf(out, "0 devheight -1 mul translate %% next keyboard\n"); 9690e20ee16Smrg } 9700e20ee16Smrg state->nPages++; 9712f167a42Smrg state->color = state->black; 9722f167a42Smrg state->font = -1; 9730e20ee16Smrg return; 9740e20ee16Smrg} 9750e20ee16Smrg 9760e20ee16Smrgstatic void 9770e20ee16SmrgPSDoodad(FILE *out, PSState *state, XkbDoodadPtr doodad) 9780e20ee16Smrg{ 9792f167a42Smrg XkbDescPtr xkb; 9802f167a42Smrg const char *name, *dname; 981e6bced22Smrg char *a1 = NULL, *a2 = NULL; 9822f167a42Smrg int sz, leading; 9832f167a42Smrg 9842f167a42Smrg xkb = state->xkb; 9852f167a42Smrg if (doodad->any.name != None) 986e6bced22Smrg dname = a1 = XkbAtomGetString(xkb->dpy, doodad->any.name); 9872f167a42Smrg else 9882f167a42Smrg dname = "NoName"; 9890e20ee16Smrg switch (doodad->any.type) { 9902f167a42Smrg case XkbOutlineDoodad: 9912f167a42Smrg case XkbSolidDoodad: 992e6bced22Smrg name = a2 = XkbAtomGetString(xkb->dpy, 9932f167a42Smrg XkbShapeDoodadShape(xkb->geom, 9942f167a42Smrg &doodad->shape)->name); 9952f167a42Smrg if (state->args->wantColor) { 9962f167a42Smrg PSSetColor(out, state, doodad->shape.color_ndx); 9972f167a42Smrg if (doodad->any.type != XkbOutlineDoodad) { 9982f167a42Smrg fprintf(out, "true %d %d %d %s %% Doodad %s\n", 9992f167a42Smrg doodad->shape.angle, 10002f167a42Smrg doodad->shape.left, doodad->shape.top, name, dname); 10012f167a42Smrg PSSetColor(out, state, state->black); 10022f167a42Smrg } 10032f167a42Smrg fprintf(out, "false %d %d %d %s %% Doodad %s\n", 10042f167a42Smrg doodad->shape.angle, 10052f167a42Smrg doodad->shape.left, doodad->shape.top, name, dname); 10062f167a42Smrg } 10072f167a42Smrg else { 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 } 1012e6bced22Smrg name = NULL; 1013e6bced22Smrg XFree(a2); 10142f167a42Smrg break; 10152f167a42Smrg case XkbTextDoodad: 10162f167a42Smrg fprintf(out, "%% Doodad %s\n", dname); 10172f167a42Smrg PSSetColor(out, state, doodad->text.color_ndx); 10182f167a42Smrg PSGSave(out, state); 10192f167a42Smrg fprintf(out, "%d %d translate\n", doodad->text.left, doodad->text.top); 10202f167a42Smrg if (doodad->text.angle != 0) 10212f167a42Smrg fprintf(out, "%s rotate\n", 10222f167a42Smrg XkbGeomFPText(doodad->text.angle, XkbMessage)); 10232f167a42Smrg sz = 14; 10242f167a42Smrg if (doodad->text.font) { 10252f167a42Smrg FontStuff stuff; 10262f167a42Smrg 10272f167a42Smrg if (CrackXLFDName(doodad->text.font, &stuff)) { 10282f167a42Smrg if (stuff.ptSize > 0) 10292f167a42Smrg sz = stuff.ptSize / 10; 10302f167a42Smrg ClearFontStuff(&stuff); 10312f167a42Smrg } 10322f167a42Smrg } 10332f167a42Smrg PSSetFont(out, state, FONT_LATIN1, sz, True); 10342f167a42Smrg leading = (sz * 12) / 10; 10352f167a42Smrg if (strchr(doodad->text.text, '\n') == NULL) { 10362f167a42Smrg fprintf(out, "0 %d pts moveto 1 -1 scale\n", (leading * 8) / 10); 10372f167a42Smrg fprintf(out, "(%s) show\n", doodad->text.text); 10382f167a42Smrg } 10392f167a42Smrg else { 10402f167a42Smrg char *tmp, *buf, *end; 10412f167a42Smrg int offset = (leading * 8 / 10); 10422f167a42Smrg 10432f167a42Smrg tmp = buf = strdup(doodad->text.text); 10442f167a42Smrg while (tmp != NULL) { 10452f167a42Smrg end = strchr(tmp, '\n'); 10462f167a42Smrg if (end != NULL) 10472f167a42Smrg *end++ = '\0'; 10482f167a42Smrg fprintf(out, "0 %d pts moveto 1 -1 scale\n", offset); 10492f167a42Smrg fprintf(out, "(%s) show 1 -1 scale\n", tmp); 10502f167a42Smrg offset += leading; 10512f167a42Smrg tmp = end; 10522f167a42Smrg } 10532f167a42Smrg free(buf); 10542f167a42Smrg } 10552f167a42Smrg PSGRestore(out, state); 10562f167a42Smrg break; 10572f167a42Smrg case XkbIndicatorDoodad: 1058e6bced22Smrg name = a2 = XkbAtomGetString(xkb->dpy, 10592f167a42Smrg XkbIndicatorDoodadShape(xkb->geom, 10602f167a42Smrg &doodad->indicator)-> 10612f167a42Smrg name); 10622f167a42Smrg if (state->args->wantColor) { 10632f167a42Smrg PSSetColor(out, state, doodad->indicator.off_color_ndx); 10642f167a42Smrg fprintf(out, "true 0 %d %d %s %% Doodad %s\n", 10652f167a42Smrg doodad->indicator.left, doodad->indicator.top, name, dname); 10662f167a42Smrg PSSetColor(out, state, state->black); 10672f167a42Smrg } 10682f167a42Smrg fprintf(out, "false 0 %d %d %s %% Doodad %s\n", 10692f167a42Smrg doodad->indicator.left, doodad->indicator.top, name, dname); 1070e6bced22Smrg name = NULL; 1071e6bced22Smrg XFree(a2); 10722f167a42Smrg break; 10732f167a42Smrg case XkbLogoDoodad: 1074e6bced22Smrg name = a2 = XkbAtomGetString(xkb->dpy, 10752f167a42Smrg XkbLogoDoodadShape(xkb->geom, 10762f167a42Smrg &doodad->logo)->name); 10772f167a42Smrg if (state->args->wantColor) 10782f167a42Smrg PSSetColor(out, state, doodad->shape.color_ndx); 10792f167a42Smrg fprintf(out, "false %d %d %d %s %% Doodad %s\n", 10802f167a42Smrg doodad->shape.angle, 10812f167a42Smrg doodad->shape.left, doodad->shape.top, name, dname); 1082e6bced22Smrg name = NULL; 1083e6bced22Smrg XFree(a2); 10842f167a42Smrg break; 10850e20ee16Smrg } 1086e6bced22Smrg XFree(a1); 10870e20ee16Smrg return; 10880e20ee16Smrg} 10890e20ee16Smrg 10900e20ee16Smrg/***====================================================================***/ 10910e20ee16Smrg 10920e20ee16Smrgstatic Bool 10932f167a42SmrgPSKeycapsSymbol(KeySym sym, unsigned char *buf, 10942f167a42Smrg int *font_rtrn, int *sz_rtrn, PSState *state) 10950e20ee16Smrg{ 10962f167a42Smrg if (state->args->wantSymbols == NO_SYMBOLS) 10972f167a42Smrg return False; 10982f167a42Smrg 10992f167a42Smrg if (font_rtrn != NULL) 11002f167a42Smrg *font_rtrn = FONT_ISOCAPS; 11012f167a42Smrg if (sz_rtrn != NULL) 11022f167a42Smrg *sz_rtrn = SZ_LARGE; 11032f167a42Smrg buf[1] = '\0'; 11040e20ee16Smrg switch (sym) { 11052f167a42Smrg case XK_Shift_L: 11062f167a42Smrg case XK_Shift_R: 11072f167a42Smrg buf[0] = XKC_ISO_Shift; 11082f167a42Smrg return True; 11092f167a42Smrg case XK_Shift_Lock: 11102f167a42Smrg buf[0] = XKC_ISO_Shift_Lock; 11112f167a42Smrg return True; 11122f167a42Smrg case XK_ISO_Lock: 11132f167a42Smrg buf[0] = XKC_ISO_Caps_Lock; 11142f167a42Smrg return True; 11152f167a42Smrg case XK_BackSpace: 11162f167a42Smrg buf[0] = XKC_ISO_Backspace; 11172f167a42Smrg return True; 11182f167a42Smrg case XK_Return: 11192f167a42Smrg buf[0] = XKC_ISO_Return; 11202f167a42Smrg return True; 11212f167a42Smrg case XK_Up: 11222f167a42Smrg case XK_KP_Up: 11232f167a42Smrg buf[0] = XKC_ISO_Up; 11242f167a42Smrg return True; 11252f167a42Smrg case XK_Down: 11262f167a42Smrg case XK_KP_Down: 11272f167a42Smrg buf[0] = XKC_ISO_Down; 11282f167a42Smrg return True; 11292f167a42Smrg case XK_Left: 11302f167a42Smrg case XK_KP_Left: 11312f167a42Smrg buf[0] = XKC_ISO_Left; 11322f167a42Smrg return True; 11332f167a42Smrg case XK_Right: 11342f167a42Smrg case XK_KP_Right: 11352f167a42Smrg buf[0] = XKC_ISO_Right; 11362f167a42Smrg return True; 11372f167a42Smrg case XK_Tab: 11382f167a42Smrg buf[0] = XKC_ISO_Tab; 11392f167a42Smrg return True; 11402f167a42Smrg case XK_ISO_Left_Tab: 11412f167a42Smrg buf[0] = XKC_ISO_Left_Tab; 11422f167a42Smrg return True; 11430e20ee16Smrg } 11442f167a42Smrg if (state->args->wantSymbols != ALL_SYMBOLS) 11452f167a42Smrg return False; 11460e20ee16Smrg switch (sym) { 11472f167a42Smrg case XK_Caps_Lock: 11482f167a42Smrg buf[0] = XKC_ISO_Caps_Lock; 11492f167a42Smrg return True; 11502f167a42Smrg case XK_Num_Lock: 11512f167a42Smrg buf[0] = XKC_ISO_Num_Lock; 11522f167a42Smrg return True; 11532f167a42Smrg case XK_ISO_Level3_Shift: 11542f167a42Smrg buf[0] = XKC_ISO_Level3_Shift; 11552f167a42Smrg return True; 11562f167a42Smrg case XK_ISO_Level3_Lock: 11572f167a42Smrg buf[0] = XKC_ISO_Level3_Lock; 11582f167a42Smrg return True; 11592f167a42Smrg case XK_ISO_Next_Group: 11602f167a42Smrg case XK_ISO_Group_Shift: 11612f167a42Smrg buf[0] = XKC_ISO_Next_Group; 11622f167a42Smrg return True; 11632f167a42Smrg case XK_ISO_Next_Group_Lock: 11642f167a42Smrg buf[0] = XKC_ISO_Next_Group_Lock; 11652f167a42Smrg return True; 11662f167a42Smrg case XK_space: 11672f167a42Smrg buf[0] = XKC_ISO_Space; 11682f167a42Smrg return True; 11692f167a42Smrg case XK_nobreakspace: 11702f167a42Smrg buf[0] = XKC_ISO_No_Break_Space; 11712f167a42Smrg return True; 11722f167a42Smrg case XK_Insert: 11732f167a42Smrg buf[0] = XKC_ISO_Insert; 11742f167a42Smrg return True; 11752f167a42Smrg case XK_ISO_Continuous_Underline: 11762f167a42Smrg buf[0] = XKC_ISO_Continuous_Underline; 11772f167a42Smrg return True; 11782f167a42Smrg case XK_ISO_Discontinuous_Underline: 11792f167a42Smrg buf[0] = XKC_ISO_Discontinuous_Underline; 11802f167a42Smrg return True; 11812f167a42Smrg case XK_ISO_Emphasize: 11822f167a42Smrg buf[0] = XKC_ISO_Emphasize; 11832f167a42Smrg return True; 11842f167a42Smrg case XK_Multi_key: 11852f167a42Smrg buf[0] = XKC_ISO_Compose; 11862f167a42Smrg return True; 11872f167a42Smrg case XK_ISO_Center_Object: 11882f167a42Smrg buf[0] = XKC_ISO_Center_Object; 11892f167a42Smrg return True; 11902f167a42Smrg case XK_Delete: 11912f167a42Smrg buf[0] = XKC_ISO_Delete; 11922f167a42Smrg return True; 11932f167a42Smrg case XK_Clear: 11942f167a42Smrg buf[0] = XKC_ISO_Clear_Screen; 11952f167a42Smrg return True; 11962f167a42Smrg case XK_Scroll_Lock: 11972f167a42Smrg buf[0] = XKC_ISO_Scroll_Lock; 11982f167a42Smrg return True; 11992f167a42Smrg case XK_Help: 12002f167a42Smrg buf[0] = XKC_ISO_Help; 12012f167a42Smrg return True; 12022f167a42Smrg case XK_Print: 12032f167a42Smrg buf[0] = XKC_ISO_Print_Screen; 12042f167a42Smrg return True; 12052f167a42Smrg case XK_ISO_Enter: 12062f167a42Smrg buf[0] = XKC_ISO_Enter; 12072f167a42Smrg return True; 12082f167a42Smrg case XK_Alt_L: 12092f167a42Smrg case XK_Alt_R: 12102f167a42Smrg buf[0] = XKC_ISO_Alt; 12112f167a42Smrg return True; 12122f167a42Smrg case XK_Control_L: 12132f167a42Smrg case XK_Control_R: 12142f167a42Smrg buf[0] = XKC_ISO_Control; 12152f167a42Smrg return True; 12162f167a42Smrg case XK_Pause: 12172f167a42Smrg buf[0] = XKC_ISO_Pause; 12182f167a42Smrg return True; 12192f167a42Smrg case XK_Break: 12202f167a42Smrg buf[0] = XKC_ISO_Break; 12212f167a42Smrg return True; 12222f167a42Smrg case XK_Escape: 12232f167a42Smrg buf[0] = XKC_ISO_Escape; 12242f167a42Smrg return True; 12252f167a42Smrg case XK_Undo: 12262f167a42Smrg buf[0] = XKC_ISO_Undo; 12272f167a42Smrg return True; 12282f167a42Smrg case XK_ISO_Fast_Cursor_Up: 12292f167a42Smrg buf[0] = XKC_ISO_Fast_Cursor_Up; 12302f167a42Smrg return True; 12312f167a42Smrg case XK_ISO_Fast_Cursor_Down: 12322f167a42Smrg buf[0] = XKC_ISO_Fast_Cursor_Down; 12332f167a42Smrg return True; 12342f167a42Smrg case XK_ISO_Fast_Cursor_Left: 12352f167a42Smrg buf[0] = XKC_ISO_Fast_Cursor_Left; 12362f167a42Smrg return True; 12372f167a42Smrg case XK_ISO_Fast_Cursor_Right: 12382f167a42Smrg buf[0] = XKC_ISO_Fast_Cursor_Right; 12392f167a42Smrg return True; 12402f167a42Smrg case XK_Home: 12412f167a42Smrg buf[0] = XKC_ISO_Home; 12422f167a42Smrg return True; 12432f167a42Smrg case XK_End: 12442f167a42Smrg buf[0] = XKC_ISO_End; 12452f167a42Smrg return True; 12462f167a42Smrg case XK_Page_Up: 12472f167a42Smrg buf[0] = XKC_ISO_Page_Up; 12482f167a42Smrg return True; 12492f167a42Smrg case XK_Page_Down: 12502f167a42Smrg buf[0] = XKC_ISO_Page_Down; 12512f167a42Smrg return True; 12522f167a42Smrg case XK_ISO_Move_Line_Up: 12532f167a42Smrg buf[0] = XKC_ISO_Move_Line_Up; 12542f167a42Smrg return True; 12552f167a42Smrg case XK_ISO_Move_Line_Down: 12562f167a42Smrg buf[0] = XKC_ISO_Move_Line_Down; 12572f167a42Smrg return True; 12582f167a42Smrg case XK_ISO_Partial_Line_Up: 12592f167a42Smrg buf[0] = XKC_ISO_Partial_Line_Up; 12602f167a42Smrg return True; 12612f167a42Smrg case XK_ISO_Partial_Line_Down: 12622f167a42Smrg buf[0] = XKC_ISO_Partial_Line_Down; 12632f167a42Smrg return True; 12642f167a42Smrg case XK_ISO_Partial_Space_Left: 12652f167a42Smrg buf[0] = XKC_ISO_Partial_Space_Left; 12662f167a42Smrg return True; 12672f167a42Smrg case XK_ISO_Partial_Space_Right: 12682f167a42Smrg buf[0] = XKC_ISO_Partial_Space_Right; 12692f167a42Smrg return True; 12702f167a42Smrg case XK_ISO_Set_Margin_Left: 12712f167a42Smrg buf[0] = XKC_ISO_Set_Margin_Left; 12722f167a42Smrg return True; 12732f167a42Smrg case XK_ISO_Set_Margin_Right: 12742f167a42Smrg buf[0] = XKC_ISO_Set_Margin_Right; 12752f167a42Smrg return True; 12762f167a42Smrg case XK_ISO_Release_Margin_Left: 12772f167a42Smrg buf[0] = XKC_ISO_Release_Margin_Left; 12782f167a42Smrg return True; 12792f167a42Smrg case XK_ISO_Release_Margin_Right: 12802f167a42Smrg buf[0] = XKC_ISO_Release_Margin_Right; 12812f167a42Smrg return True; 12822f167a42Smrg case XK_ISO_Release_Both_Margins: 12832f167a42Smrg buf[0] = XKC_ISO_Release_Both_Margins; 12842f167a42Smrg return True; 12852f167a42Smrg case XK_ISO_Prev_Group: 12862f167a42Smrg buf[0] = XKC_ISO_Prev_Group; 12872f167a42Smrg return True; 12882f167a42Smrg case XK_ISO_Prev_Group_Lock: 12892f167a42Smrg buf[0] = XKC_ISO_Prev_Group_Lock; 12902f167a42Smrg return True; 12910e20ee16Smrg } 12920e20ee16Smrg return False; 12930e20ee16Smrg} 12940e20ee16Smrg 12950e20ee16Smrgstatic Bool 12960e20ee16SmrgPSNonLatin1Symbol(KeySym sym, unsigned char *buf, 12972f167a42Smrg int *font_rtrn, int *sz_rtrn, PSState *state) 12980e20ee16Smrg{ 12992f167a42Smrg if (state->args->wantSymbols == NO_SYMBOLS) 13002f167a42Smrg return False; 13012f167a42Smrg 13022f167a42Smrg if (font_rtrn != NULL) 13032f167a42Smrg *font_rtrn = FONT_TEXT; 13042f167a42Smrg if (sz_rtrn != NULL) 13052f167a42Smrg *sz_rtrn = SZ_LARGE; 13062f167a42Smrg buf[1] = '\0'; 13070e20ee16Smrg switch (sym) { 13082f167a42Smrg case XK_breve: 13092f167a42Smrg buf[0] = 0xC6; 13102f167a42Smrg return True; 13112f167a42Smrg case XK_abovedot: 13122f167a42Smrg buf[0] = 0xC7; 13132f167a42Smrg return True; 13142f167a42Smrg case XK_doubleacute: 13152f167a42Smrg buf[0] = 0xCD; 13162f167a42Smrg return True; 13172f167a42Smrg case XK_ogonek: 13182f167a42Smrg buf[0] = 0xCE; 13192f167a42Smrg return True; 13202f167a42Smrg case XK_caron: 13212f167a42Smrg buf[0] = 0xCF; 13222f167a42Smrg return True; 13232f167a42Smrg case XK_Lstroke: 13242f167a42Smrg buf[0] = 0xE8; 13252f167a42Smrg return True; 13262f167a42Smrg case XK_idotless: 13272f167a42Smrg buf[0] = 0xF5; 13282f167a42Smrg return True; 13292f167a42Smrg case XK_lstroke: 13302f167a42Smrg buf[0] = 0xF8; 13312f167a42Smrg return True; 13320e20ee16Smrg } 13332f167a42Smrg if (font_rtrn != NULL) 13342f167a42Smrg *font_rtrn = FONT_SYMBOL; 13352f167a42Smrg if (sz_rtrn != NULL) 13362f167a42Smrg *sz_rtrn = SZ_MEDIUM; 13372f167a42Smrg if ((sym & (~0xffUL)) == 0x700) { 13382f167a42Smrg switch (sym) { 13392f167a42Smrg /* Greek symbol */ 13402f167a42Smrg case XK_Greek_ALPHA: 13412f167a42Smrg buf[0] = 0x41; 13422f167a42Smrg return True; 13432f167a42Smrg case XK_Greek_BETA: 13442f167a42Smrg buf[0] = 0x42; 13452f167a42Smrg return True; 13462f167a42Smrg case XK_Greek_CHI: 13472f167a42Smrg buf[0] = 0x43; 13482f167a42Smrg return True; 13492f167a42Smrg case XK_Greek_DELTA: 13502f167a42Smrg buf[0] = 0x44; 13512f167a42Smrg return True; 13522f167a42Smrg case XK_Greek_EPSILON: 13532f167a42Smrg buf[0] = 0x45; 13542f167a42Smrg return True; 13552f167a42Smrg case XK_Greek_PHI: 13562f167a42Smrg buf[0] = 0x46; 13572f167a42Smrg return True; 13582f167a42Smrg case XK_Greek_GAMMA: 13592f167a42Smrg buf[0] = 0x47; 13602f167a42Smrg return True; 13612f167a42Smrg case XK_Greek_ETA: 13622f167a42Smrg buf[0] = 0x48; 13632f167a42Smrg return True; 13642f167a42Smrg case XK_Greek_IOTA: 13652f167a42Smrg buf[0] = 0x49; 13662f167a42Smrg return True; 13672f167a42Smrg case XK_Greek_KAPPA: 13682f167a42Smrg buf[0] = 0x4B; 13692f167a42Smrg return True; 13702f167a42Smrg case XK_Greek_LAMDA: 13712f167a42Smrg buf[0] = 0x4C; 13722f167a42Smrg return True; 13732f167a42Smrg case XK_Greek_MU: 13742f167a42Smrg buf[0] = 0x4D; 13752f167a42Smrg return True; 13762f167a42Smrg case XK_Greek_NU: 13772f167a42Smrg buf[0] = 0x4E; 13782f167a42Smrg return True; 13792f167a42Smrg case XK_Greek_OMICRON: 13802f167a42Smrg buf[0] = 0x4F; 13812f167a42Smrg return True; 13822f167a42Smrg case XK_Greek_PI: 13832f167a42Smrg buf[0] = 0x50; 13842f167a42Smrg return True; 13852f167a42Smrg case XK_Greek_THETA: 13862f167a42Smrg buf[0] = 0x51; 13872f167a42Smrg return True; 13882f167a42Smrg case XK_Greek_RHO: 13892f167a42Smrg buf[0] = 0x52; 13902f167a42Smrg return True; 13912f167a42Smrg case XK_Greek_SIGMA: 13922f167a42Smrg buf[0] = 0x53; 13932f167a42Smrg return True; 13942f167a42Smrg case XK_Greek_TAU: 13952f167a42Smrg buf[0] = 0x54; 13962f167a42Smrg return True; 13972f167a42Smrg case XK_Greek_UPSILON: 13982f167a42Smrg buf[0] = 0x55; 13992f167a42Smrg return True; 14002f167a42Smrg case XK_Greek_OMEGA: 14012f167a42Smrg buf[0] = 0x57; 14022f167a42Smrg return True; 14032f167a42Smrg case XK_Greek_XI: 14042f167a42Smrg buf[0] = 0x58; 14052f167a42Smrg return True; 14062f167a42Smrg case XK_Greek_PSI: 14072f167a42Smrg buf[0] = 0x59; 14082f167a42Smrg return True; 14092f167a42Smrg case XK_Greek_ZETA: 14102f167a42Smrg buf[0] = 0x5A; 14112f167a42Smrg return True; 14122f167a42Smrg 14132f167a42Smrg case XK_Greek_alpha: 14142f167a42Smrg buf[0] = 0x61; 14152f167a42Smrg return True; 14162f167a42Smrg case XK_Greek_beta: 14172f167a42Smrg buf[0] = 0x62; 14182f167a42Smrg return True; 14192f167a42Smrg case XK_Greek_chi: 14202f167a42Smrg buf[0] = 0x63; 14212f167a42Smrg return True; 14222f167a42Smrg case XK_Greek_delta: 14232f167a42Smrg buf[0] = 0x64; 14242f167a42Smrg return True; 14252f167a42Smrg case XK_Greek_epsilon: 14262f167a42Smrg buf[0] = 0x65; 14272f167a42Smrg return True; 14282f167a42Smrg case XK_Greek_phi: 14292f167a42Smrg buf[0] = 0x66; 14302f167a42Smrg return True; 14312f167a42Smrg case XK_Greek_gamma: 14322f167a42Smrg buf[0] = 0x67; 14332f167a42Smrg return True; 14342f167a42Smrg case XK_Greek_eta: 14352f167a42Smrg buf[0] = 0x68; 14362f167a42Smrg return True; 14372f167a42Smrg case XK_Greek_iota: 14382f167a42Smrg buf[0] = 0x69; 14392f167a42Smrg return True; 14402f167a42Smrg case XK_Greek_kappa: 14412f167a42Smrg buf[0] = 0x6B; 14422f167a42Smrg return True; 14432f167a42Smrg case XK_Greek_lamda: 14442f167a42Smrg buf[0] = 0x6C; 14452f167a42Smrg return True; 14462f167a42Smrg case XK_Greek_mu: 14472f167a42Smrg buf[0] = 0x6D; 14482f167a42Smrg return True; 14492f167a42Smrg case XK_Greek_nu: 14502f167a42Smrg buf[0] = 0x6E; 14512f167a42Smrg return True; 14522f167a42Smrg case XK_Greek_omicron: 14532f167a42Smrg buf[0] = 0x6F; 14542f167a42Smrg return True; 14552f167a42Smrg case XK_Greek_pi: 14562f167a42Smrg buf[0] = 0x70; 14572f167a42Smrg return True; 14582f167a42Smrg case XK_Greek_theta: 14592f167a42Smrg buf[0] = 0x71; 14602f167a42Smrg return True; 14612f167a42Smrg case XK_Greek_rho: 14622f167a42Smrg buf[0] = 0x72; 14632f167a42Smrg return True; 14642f167a42Smrg case XK_Greek_sigma: 14652f167a42Smrg buf[0] = 0x73; 14662f167a42Smrg return True; 14672f167a42Smrg case XK_Greek_tau: 14682f167a42Smrg buf[0] = 0x74; 14692f167a42Smrg return True; 14702f167a42Smrg case XK_Greek_upsilon: 14712f167a42Smrg buf[0] = 0x75; 14722f167a42Smrg return True; 14732f167a42Smrg case XK_Greek_omega: 14742f167a42Smrg buf[0] = 0x77; 14752f167a42Smrg return True; 14762f167a42Smrg case XK_Greek_xi: 14772f167a42Smrg buf[0] = 0x78; 14782f167a42Smrg return True; 14792f167a42Smrg case XK_Greek_psi: 14802f167a42Smrg buf[0] = 0x79; 14812f167a42Smrg return True; 14822f167a42Smrg case XK_Greek_zeta: 14832f167a42Smrg buf[0] = 0x7A; 14842f167a42Smrg return True; 14852f167a42Smrg } 14860e20ee16Smrg } 14870e20ee16Smrg switch (sym) { 14882f167a42Smrg case XK_leftarrow: 14892f167a42Smrg buf[0] = 0xAC; 14902f167a42Smrg return True; 14912f167a42Smrg case XK_uparrow: 14922f167a42Smrg buf[0] = 0xAD; 14932f167a42Smrg return True; 14942f167a42Smrg case XK_rightarrow: 14952f167a42Smrg buf[0] = 0xAE; 14962f167a42Smrg return True; 14972f167a42Smrg case XK_downarrow: 14982f167a42Smrg buf[0] = 0xAF; 14992f167a42Smrg return True; 15002f167a42Smrg case XK_horizconnector: 15012f167a42Smrg buf[0] = 0xBE; 15022f167a42Smrg return True; 15032f167a42Smrg case XK_trademark: 15042f167a42Smrg buf[0] = 0xE4; 15052f167a42Smrg return True; 15060e20ee16Smrg } 15070e20ee16Smrg return False; 15080e20ee16Smrg} 15090e20ee16Smrg 15100e20ee16Smrgstatic KeySym 15110e20ee16SmrgCheckSymbolAlias(KeySym sym, PSState *state) 15120e20ee16Smrg{ 15130e20ee16Smrg if (XkbKSIsKeypad(sym)) { 15142f167a42Smrg if ((sym >= XK_KP_0) && (sym <= XK_KP_9)) 15152f167a42Smrg sym = (sym - XK_KP_0) + XK_0; 15162f167a42Smrg else 15172f167a42Smrg switch (sym) { 15182f167a42Smrg case XK_KP_Space: 15192f167a42Smrg return XK_space; 15202f167a42Smrg case XK_KP_Tab: 15212f167a42Smrg return XK_Tab; 15222f167a42Smrg case XK_KP_Enter: 15232f167a42Smrg return XK_Return; 15242f167a42Smrg case XK_KP_F1: 15252f167a42Smrg return XK_F1; 15262f167a42Smrg case XK_KP_F2: 15272f167a42Smrg return XK_F2; 15282f167a42Smrg case XK_KP_F3: 15292f167a42Smrg return XK_F3; 15302f167a42Smrg case XK_KP_F4: 15312f167a42Smrg return XK_F4; 15322f167a42Smrg case XK_KP_Home: 15332f167a42Smrg return XK_Home; 15342f167a42Smrg case XK_KP_Left: 15352f167a42Smrg return XK_Left; 15362f167a42Smrg case XK_KP_Up: 15372f167a42Smrg return XK_Up; 15382f167a42Smrg case XK_KP_Right: 15392f167a42Smrg return XK_Right; 15402f167a42Smrg case XK_KP_Down: 15412f167a42Smrg return XK_Down; 15422f167a42Smrg case XK_KP_Page_Up: 15432f167a42Smrg return XK_Page_Up; 15442f167a42Smrg case XK_KP_Page_Down: 15452f167a42Smrg return XK_Page_Down; 15462f167a42Smrg case XK_KP_End: 15472f167a42Smrg return XK_End; 15482f167a42Smrg case XK_KP_Begin: 15492f167a42Smrg return XK_Begin; 15502f167a42Smrg case XK_KP_Insert: 15512f167a42Smrg return XK_Insert; 15522f167a42Smrg case XK_KP_Delete: 15532f167a42Smrg return XK_Delete; 15542f167a42Smrg case XK_KP_Equal: 15552f167a42Smrg return XK_equal; 15562f167a42Smrg case XK_KP_Multiply: 15572f167a42Smrg return XK_asterisk; 15582f167a42Smrg case XK_KP_Add: 15592f167a42Smrg return XK_plus; 15602f167a42Smrg case XK_KP_Subtract: 15612f167a42Smrg return XK_minus; 15622f167a42Smrg case XK_KP_Divide: 15632f167a42Smrg return XK_slash; 15642f167a42Smrg } 15650e20ee16Smrg } 15660e20ee16Smrg else if (XkbKSIsDeadKey(sym)) { 15672f167a42Smrg switch (sym) { 15682f167a42Smrg case XK_dead_grave: 15692f167a42Smrg sym = XK_grave; 15702f167a42Smrg break; 15712f167a42Smrg case XK_dead_acute: 15722f167a42Smrg sym = XK_acute; 15732f167a42Smrg break; 15742f167a42Smrg case XK_dead_circumflex: 15752f167a42Smrg sym = XK_asciicircum; 15762f167a42Smrg break; 15772f167a42Smrg case XK_dead_tilde: 15782f167a42Smrg sym = XK_asciitilde; 15792f167a42Smrg break; 15802f167a42Smrg case XK_dead_macron: 15812f167a42Smrg sym = XK_macron; 15822f167a42Smrg break; 15832f167a42Smrg case XK_dead_breve: 15842f167a42Smrg sym = XK_breve; 15852f167a42Smrg break; 15862f167a42Smrg case XK_dead_abovedot: 15872f167a42Smrg sym = XK_abovedot; 15882f167a42Smrg break; 15892f167a42Smrg case XK_dead_diaeresis: 15902f167a42Smrg sym = XK_diaeresis; 15912f167a42Smrg break; 15922f167a42Smrg case XK_dead_abovering: 15932f167a42Smrg sym = XK_degree; 15942f167a42Smrg break; 15952f167a42Smrg case XK_dead_doubleacute: 15962f167a42Smrg sym = XK_doubleacute; 15972f167a42Smrg break; 15982f167a42Smrg case XK_dead_caron: 15992f167a42Smrg sym = XK_caron; 16002f167a42Smrg break; 16012f167a42Smrg case XK_dead_cedilla: 16022f167a42Smrg sym = XK_cedilla; 16032f167a42Smrg break; 16042f167a42Smrg case XK_dead_ogonek: 16052f167a42Smrg sym = XK_ogonek; 16062f167a42Smrg break; 16072f167a42Smrg case XK_dead_iota: 16082f167a42Smrg sym = XK_Greek_iota; 16092f167a42Smrg break; 16102f167a42Smrg case XK_dead_voiced_sound: 16112f167a42Smrg sym = XK_voicedsound; 16122f167a42Smrg break; 16132f167a42Smrg case XK_dead_semivoiced_sound: 16142f167a42Smrg sym = XK_semivoicedsound; 16152f167a42Smrg break; 16162f167a42Smrg } 16170e20ee16Smrg } 16180e20ee16Smrg return sym; 16190e20ee16Smrg} 16200e20ee16Smrg 16210e20ee16Smrgstatic Bool 16220e20ee16SmrgFindKeysymsByName(XkbDescPtr xkb, char *name, PSState *state, KeyTop *top) 16230e20ee16Smrg{ 16242f167a42Smrg static unsigned char buf[30]; 16252f167a42Smrg int kc; 16262f167a42Smrg KeySym sym, *syms, topSyms[NLABELS]; 16272f167a42Smrg int level, group; 16288b648e79Smrg int eG, nG, gI; 16292f167a42Smrg 16302f167a42Smrg bzero(top, sizeof(KeyTop)); 16312f167a42Smrg kc = XkbFindKeycodeByName(xkb, name, True); 16322f167a42Smrg if (state->args != NULL) { 16332f167a42Smrg level = state->args->labelLevel; 16342f167a42Smrg group = state->args->baseLabelGroup; 16350e20ee16Smrg } 16362f167a42Smrg else 16372f167a42Smrg level = group = 0; 16382f167a42Smrg syms = XkbKeySymsPtr(xkb, kc); 16392f167a42Smrg eG = group; 16402f167a42Smrg nG = XkbKeyNumGroups(xkb, kc); 16412f167a42Smrg gI = XkbKeyGroupInfo(xkb, kc); 16428b648e79Smrg if ((state->args != NULL) && (state->args->wantDiffs) && 16438b648e79Smrg (eG >= XkbKeyNumGroups(xkb, kc))) 16442f167a42Smrg return False; /* XXX was a return with no value */ 16452f167a42Smrg if (nG == 0) { 16462f167a42Smrg return False; 16470e20ee16Smrg } 16482f167a42Smrg else if (nG == 1) { 16492f167a42Smrg eG = 0; 16500e20ee16Smrg } 16512f167a42Smrg else if (eG >= XkbKeyNumGroups(xkb, kc)) { 16522f167a42Smrg switch (XkbOutOfRangeGroupAction(gI)) { 16532f167a42Smrg default: 16542f167a42Smrg eG %= nG; 16552f167a42Smrg break; 16562f167a42Smrg case XkbClampIntoRange: 16572f167a42Smrg eG = nG - 1; 16582f167a42Smrg break; 16592f167a42Smrg case XkbRedirectIntoRange: 16602f167a42Smrg eG = XkbOutOfRangeGroupNumber(gI); 16612f167a42Smrg if (eG >= nG) 16622f167a42Smrg eG = 0; 16632f167a42Smrg break; 16642f167a42Smrg } 16650e20ee16Smrg } 16668b648e79Smrg for (int g = 0; g < state->args->nLabelGroups; g++) { 16672f167a42Smrg if ((eG + g) >= nG) 16682f167a42Smrg continue; 16698b648e79Smrg for (int l = 0; l < 2; l++) { 16702f167a42Smrg int font, sz; 16712f167a42Smrg 16722f167a42Smrg if (level + l >= XkbKeyGroupWidth(xkb, kc, (eG + g))) 16732f167a42Smrg continue; 16742f167a42Smrg sym = syms[((eG + g) * XkbKeyGroupsWidth(xkb, kc)) + (level + l)]; 16752f167a42Smrg 16762f167a42Smrg if (state->args->wantSymbols != NO_SYMBOLS) 16772f167a42Smrg sym = CheckSymbolAlias(sym, state); 16782f167a42Smrg topSyms[(g * 2) + l] = sym; 16792f167a42Smrg 16802f167a42Smrg if (PSKeycapsSymbol(sym, buf, &font, &sz, state)) { 16812f167a42Smrg top->font[(g * 2) + l] = font; 16822f167a42Smrg top->size[(g * 2) + l] = sz; 16832f167a42Smrg } 16842f167a42Smrg else if (((sym & (~0xffUL)) == 0) && isprint(sym) && (!isspace(sym))) { 16852f167a42Smrg if (sym == '(') 16862f167a42Smrg snprintf((char *) buf, sizeof(buf), "\\("); 16872f167a42Smrg else if (sym == ')') 16882f167a42Smrg snprintf((char *) buf, sizeof(buf), "\\)"); 16892f167a42Smrg else if (sym == '\\') 16902f167a42Smrg snprintf((char *) buf, sizeof(buf), "\\\\"); 16912f167a42Smrg else 16922f167a42Smrg snprintf((char *) buf, sizeof(buf), "%c", (char) sym); 16932f167a42Smrg top->font[(g * 2) + l] = FONT_LATIN1; 16942f167a42Smrg top->size[(g * 2) + l] = SZ_MEDIUM; 16952f167a42Smrg switch (buf[0]) { 16962f167a42Smrg case '.': 16972f167a42Smrg case ':': 16982f167a42Smrg case ',': 16992f167a42Smrg case ';': 17002f167a42Smrg case '\'': 17012f167a42Smrg case '"': 17022f167a42Smrg case '`': 17032f167a42Smrg case '~': 17042f167a42Smrg case '^': 17052f167a42Smrg case 0250: 17062f167a42Smrg case 0270: 17072f167a42Smrg case 0267: 17082f167a42Smrg case 0260: 17092f167a42Smrg case 0252: 17102f167a42Smrg case 0272: 17112f167a42Smrg case 0271: 17122f167a42Smrg case 0262: 17132f167a42Smrg case 0263: 17142f167a42Smrg case 0264: 17152f167a42Smrg case 0255: 17162f167a42Smrg case 0254: 17172f167a42Smrg case 0257: 17182f167a42Smrg top->size[(g * 2) + l] = SZ_LARGE; 17192f167a42Smrg break; 17202f167a42Smrg } 17212f167a42Smrg } 17222f167a42Smrg else if (PSNonLatin1Symbol(sym, buf, &font, &sz, state)) { 17232f167a42Smrg top->font[(g * 2) + l] = font; 17242f167a42Smrg top->size[(g * 2) + l] = sz; 17252f167a42Smrg } 17262f167a42Smrg else { 17272f167a42Smrg char *tmp; 17282f167a42Smrg 17292f167a42Smrg tmp = XKeysymToString(sym); 17302f167a42Smrg if (tmp != NULL) 17312f167a42Smrg strcpy((char *) buf, tmp); 17322f167a42Smrg else 17332f167a42Smrg snprintf((char *) buf, sizeof(buf), "(%ld)", sym); 17342f167a42Smrg top->font[(g * 2) + l] = FONT_LATIN1; 17352f167a42Smrg if (strlen((char *) buf) < 9) 17362f167a42Smrg top->size[(g * 2) + l] = SZ_SMALL; 17372f167a42Smrg else 17382f167a42Smrg top->size[(g * 2) + l] = SZ_TINY; 17392f167a42Smrg } 17402f167a42Smrg top->present |= (1 << ((g * 2) + l)); 17412f167a42Smrg strncpy(top->label[(g * 2) + l], (char *) buf, LABEL_LEN - 1); 17422f167a42Smrg top->label[(g * 2) + l][LABEL_LEN - 1] = '\0'; 17432f167a42Smrg } 17442f167a42Smrg if (((g == 0) && (top->present & G1LX_MASK) == G1LX_MASK) || 17452f167a42Smrg ((g == 1) && (top->present & G2LX_MASK) == G2LX_MASK)) { 17462f167a42Smrg KeySym lower, upper; 17472f167a42Smrg 17482f167a42Smrg XConvertCase(topSyms[(g * 2)], &lower, &upper); 17492f167a42Smrg if ((topSyms[(g * 2)] == lower) && (topSyms[(g * 2) + 1] == upper)) { 17502f167a42Smrg top->alpha[g] = True; 17512f167a42Smrg } 17522f167a42Smrg } 17530e20ee16Smrg } 17540e20ee16Smrg return True; 17550e20ee16Smrg} 17560e20ee16Smrg 17570e20ee16Smrgstatic void 17582f167a42SmrgPSDrawLabel(FILE *out, const char *label, int x, int y, int w, int h) 17590e20ee16Smrg{ 17602f167a42Smrg fprintf(out, "%d %d (%s) centeroffset\n", w, h, label); 17612f167a42Smrg fprintf(out, "%d add exch\n", y); 17622f167a42Smrg fprintf(out, "%d add exch moveto\n", x); 17632f167a42Smrg fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", label); 17640e20ee16Smrg return; 17650e20ee16Smrg} 17660e20ee16Smrg 17670e20ee16Smrg#define TOP_ROW 0 17680e20ee16Smrg#define BOTTOM_ROW 1 17690e20ee16Smrg#define CENTER_ROW 2 17700e20ee16Smrg 17710e20ee16Smrg#define LEFT_COL 0 17720e20ee16Smrg#define RIGHT_COL 1 17730e20ee16Smrg#define CENTER_COL 2 17740e20ee16Smrg 17750e20ee16Smrgstatic void 17760e20ee16SmrgPSLabelKey(FILE *out, PSState *state, KeyTop *top, int x, int y, 17772f167a42Smrg XkbBoundsPtr bounds, int kc, int btm) 17780e20ee16Smrg{ 17798b648e79Smrg int w, h; 17802f167a42Smrg int row_y[3]; 17812f167a42Smrg int col_x[3]; 17822f167a42Smrg int row_h[3]; 17832f167a42Smrg int col_w[3]; 17842f167a42Smrg Bool present[NLABELS]; 17852f167a42Smrg int sym_row[NLABELS]; 17862f167a42Smrg int sym_col[NLABELS]; 17872f167a42Smrg 17882f167a42Smrg w = XkbBoundsWidth(bounds); 17892f167a42Smrg h = XkbBoundsHeight(bounds); 17902f167a42Smrg row_y[TOP_ROW] = y + bounds->y1 + (h / 10); 17912f167a42Smrg row_y[BOTTOM_ROW] = y + bounds->y1 + (h / 2) + (h / 10); 17922f167a42Smrg row_y[CENTER_ROW] = y + bounds->y1 + (h / 10); 17932f167a42Smrg row_h[TOP_ROW] = h / 2; 17942f167a42Smrg row_h[BOTTOM_ROW] = h / 2; 17952f167a42Smrg row_h[CENTER_ROW] = h; 17962f167a42Smrg 17972f167a42Smrg col_x[LEFT_COL] = x + bounds->x1; 17982f167a42Smrg col_x[RIGHT_COL] = x + bounds->x1 + w / 2; 17992f167a42Smrg col_x[CENTER_COL] = x + bounds->x1; 18002f167a42Smrg col_w[LEFT_COL] = w / 2; 18012f167a42Smrg col_w[RIGHT_COL] = w / 2; 18022f167a42Smrg col_w[CENTER_COL] = w; 18032f167a42Smrg 18042f167a42Smrg present[G1L1] = False; 18052f167a42Smrg sym_row[G1L1] = BOTTOM_ROW; 18062f167a42Smrg sym_col[G1L1] = LEFT_COL; 18072f167a42Smrg 18082f167a42Smrg present[G1L2] = False; 18092f167a42Smrg sym_row[G1L2] = TOP_ROW; 18102f167a42Smrg sym_col[G1L2] = LEFT_COL; 18112f167a42Smrg 18122f167a42Smrg present[G2L1] = False; 18132f167a42Smrg sym_row[G2L1] = BOTTOM_ROW; 18142f167a42Smrg sym_col[G2L1] = RIGHT_COL; 18152f167a42Smrg 18162f167a42Smrg present[G2L2] = False; 18172f167a42Smrg sym_row[G2L2] = TOP_ROW; 18182f167a42Smrg sym_col[G2L2] = RIGHT_COL; 18192f167a42Smrg 18202f167a42Smrg present[CENTER] = False; 18212f167a42Smrg sym_row[CENTER] = CENTER_ROW; 18222f167a42Smrg sym_col[CENTER] = CENTER_COL; 18232f167a42Smrg 18242f167a42Smrg if (top->present & CENTER_MASK) { 18252f167a42Smrg present[CENTER] = True; 18260e20ee16Smrg } 18272f167a42Smrg else 18282f167a42Smrg switch (top->present & GXLX_MASK) { 18292f167a42Smrg case G1L1_MASK: 18302f167a42Smrg present[G1L1] = True; 18312f167a42Smrg sym_row[G1L1] = CENTER_ROW; 18322f167a42Smrg sym_col[G1L1] = CENTER_COL; 18332f167a42Smrg break; 18342f167a42Smrg case G1LX_MASK: 18352f167a42Smrg present[G1L2] = True; 18362f167a42Smrg if (!top->alpha[0]) { 18372f167a42Smrg present[G1L1] = True; 18382f167a42Smrg if ((strlen(top->label[G1L1]) > 1) && 18392f167a42Smrg (top->label[G1L1][0] != '\\')) 18402f167a42Smrg sym_col[G1L1] = CENTER_COL; 18412f167a42Smrg if ((strlen(top->label[G1L2]) > 1) && 18422f167a42Smrg (top->label[G1L1][0] != '\\')) 18432f167a42Smrg sym_col[G1L2] = CENTER_COL; 18442f167a42Smrg } 18452f167a42Smrg break; 18462f167a42Smrg default: 18472f167a42Smrg if ((top->present & G1LX_MASK) == G1LX_MASK) { 18482f167a42Smrg present[G1L2] = True; 18492f167a42Smrg if (!top->alpha[0]) 18502f167a42Smrg present[G1L1] = True; 18512f167a42Smrg } 18522f167a42Smrg else if ((top->present & G1LX_MASK) == G1L1_MASK) { 18532f167a42Smrg present[G1L1] = True; 18542f167a42Smrg } 18552f167a42Smrg else if ((top->present & G1LX_MASK) == G1L2_MASK) { 18562f167a42Smrg present[G1L2] = True; 18572f167a42Smrg } 18582f167a42Smrg if ((top->present & G2LX_MASK) == G2LX_MASK) { 18592f167a42Smrg present[G2L2] = True; 18602f167a42Smrg if (!top->alpha[1]) 18612f167a42Smrg present[G2L1] = True; 18622f167a42Smrg } 18632f167a42Smrg else if ((top->present & G2LX_MASK) == G2L1_MASK) { 18642f167a42Smrg present[G2L1] = True; 18652f167a42Smrg } 18662f167a42Smrg else if ((top->present & G2LX_MASK) == G2L2_MASK) { 18672f167a42Smrg present[G2L2] = True; 18682f167a42Smrg } 18692f167a42Smrg break; 18702f167a42Smrg case 0: 18712f167a42Smrg return; 18722f167a42Smrg } 18738b648e79Smrg for (int i = 0; i < NLABELS; i++) { 18742f167a42Smrg if (present[i]) { 18752f167a42Smrg int size; 18762f167a42Smrg 18772f167a42Smrg if (top->size[i] == SZ_AUTO) { 18782f167a42Smrg size_t len = strlen(top->label[i]); 18792f167a42Smrg if (len == 1) { 18802f167a42Smrg if (top->font[i] == FONT_ISOCAPS) 18812f167a42Smrg size = 18; 18822f167a42Smrg else 18832f167a42Smrg size = 14; 18842f167a42Smrg } 18852f167a42Smrg else if (len < 10) 18862f167a42Smrg size = 12; 18872f167a42Smrg else 18882f167a42Smrg size = 10; 18892f167a42Smrg } 18902f167a42Smrg else if (top->size[i] == SZ_TINY) 18912f167a42Smrg size = 10; 18922f167a42Smrg else if (top->size[i] == SZ_SMALL) 18932f167a42Smrg size = 12; 18942f167a42Smrg else if (top->size[i] == SZ_LARGE) 18952f167a42Smrg size = 18; 18962f167a42Smrg else if (top->size[i] == SZ_XLARGE) 18972f167a42Smrg size = 24; 18982f167a42Smrg else 18992f167a42Smrg size = 14; 19002f167a42Smrg PSSetFont(out, state, top->font[i], size, True); 19012f167a42Smrg PSDrawLabel(out, top->label[i], col_x[sym_col[i]], 19022f167a42Smrg row_y[sym_row[i]], col_w[sym_col[i]], 19032f167a42Smrg row_h[sym_row[i]]); 19042f167a42Smrg } 19050e20ee16Smrg } 19060e20ee16Smrg if (state->args->wantKeycodes) { 19072f167a42Smrg char keycode[10]; 19082f167a42Smrg 19092f167a42Smrg snprintf(keycode, sizeof(keycode), "%d", kc); 19102f167a42Smrg PSSetFont(out, state, FONT_LATIN1, 8, True); 19112f167a42Smrg PSDrawLabel(out, keycode, x + bounds->x1, y + btm - 5, w, 0); 19120e20ee16Smrg } 19130e20ee16Smrg return; 19140e20ee16Smrg} 19150e20ee16Smrg 19160e20ee16Smrgstatic void 19170e20ee16SmrgPSSection(FILE *out, PSState *state, XkbSectionPtr section) 19180e20ee16Smrg{ 19192f167a42Smrg int r, offset; 19202f167a42Smrg XkbRowPtr row; 19212f167a42Smrg Display *dpy; 19222f167a42Smrg XkbDescPtr xkb; 19232f167a42Smrg 19242f167a42Smrg xkb = state->xkb; 19252f167a42Smrg dpy = xkb->dpy; 1926e6bced22Smrg { 1927e6bced22Smrg const char *section_name; 1928e6bced22Smrg char *atom_name = NULL; 1929e6bced22Smrg 1930e6bced22Smrg if (section->name != None) 1931e6bced22Smrg section_name = atom_name = XkbAtomGetString(dpy, section->name); 1932e6bced22Smrg else 1933e6bced22Smrg section_name = "NoName"; 1934e6bced22Smrg fprintf(out, "%% Begin Section '%s'\n", section_name); 1935e6bced22Smrg XFree(atom_name); 1936e6bced22Smrg } 19372f167a42Smrg PSGSave(out, state); 19382f167a42Smrg fprintf(out, "%d %d translate\n", section->left, section->top); 19392f167a42Smrg if (section->angle != 0) 19402f167a42Smrg fprintf(out, "%s rotate\n", XkbGeomFPText(section->angle, XkbMessage)); 19410e20ee16Smrg if (section->doodads) { 19422f167a42Smrg XkbDrawablePtr first, draw; 19432f167a42Smrg 19442f167a42Smrg first = draw = XkbGetOrderedDrawables(NULL, section); 19452f167a42Smrg while (draw) { 19462f167a42Smrg if (draw->type == XkbDW_Section) 19472f167a42Smrg PSSection(out, state, draw->u.section); 19482f167a42Smrg else 19492f167a42Smrg PSDoodad(out, state, draw->u.doodad); 19502f167a42Smrg draw = draw->next; 19512f167a42Smrg } 19522f167a42Smrg XkbFreeOrderedDrawables(first); 19530e20ee16Smrg } 19542f167a42Smrg for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 19552f167a42Smrg int k; 19562f167a42Smrg XkbKeyPtr key; 19572f167a42Smrg 19582f167a42Smrg if (row->vertical) 19592f167a42Smrg offset = row->top; 19602f167a42Smrg else 19612f167a42Smrg offset = row->left; 19622f167a42Smrg fprintf(out, "%% Begin %s %d\n", row->vertical ? "column" : "row", 19632f167a42Smrg r + 1); 19642f167a42Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 1965e6bced22Smrg XkbShapePtr shape = XkbKeyShape(xkb->geom, key); 1966e6bced22Smrg char *shape_name = XkbAtomGetString(dpy, shape->name); 1967e6bced22Smrg 19682f167a42Smrg offset += key->gap; 19692f167a42Smrg if (row->vertical) { 19702f167a42Smrg if (state->args->wantColor) { 19712f167a42Smrg if (key->color_ndx != state->white) { 19722f167a42Smrg PSSetColor(out, state, key->color_ndx); 19732f167a42Smrg fprintf(out, "true 0 %d %d %s %% %s\n", 1974e6bced22Smrg row->left, offset, shape_name, 19752f167a42Smrg XkbKeyNameText(key->name.name, XkbMessage)); 19762f167a42Smrg } 19772f167a42Smrg PSSetColor(out, state, state->black); 19782f167a42Smrg } 19792f167a42Smrg fprintf(out, "false 0 %d %d %s %% %s\n", row->left, offset, 1980e6bced22Smrg shape_name, 19812f167a42Smrg XkbKeyNameText(key->name.name, XkbMessage)); 19822f167a42Smrg offset += shape->bounds.y2; 19832f167a42Smrg } 19842f167a42Smrg else { 19852f167a42Smrg if (state->args->wantColor) { 19862f167a42Smrg if (key->color_ndx != state->white) { 19872f167a42Smrg PSSetColor(out, state, key->color_ndx); 19882f167a42Smrg fprintf(out, "true 0 %d %d %s %% %s\n", offset, 1989e6bced22Smrg row->top, shape_name, 19902f167a42Smrg XkbKeyNameText(key->name.name, XkbMessage)); 19912f167a42Smrg } 19922f167a42Smrg PSSetColor(out, state, state->black); 19932f167a42Smrg } 19942f167a42Smrg fprintf(out, "false 0 %d %d %s %% %s\n", offset, row->top, 1995e6bced22Smrg shape_name, 19962f167a42Smrg XkbKeyNameText(key->name.name, XkbMessage)); 19972f167a42Smrg offset += shape->bounds.x2; 19982f167a42Smrg } 1999e6bced22Smrg XFree(shape_name); 20002f167a42Smrg } 20010e20ee16Smrg } 20022f167a42Smrg for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 20032f167a42Smrg int k, kc = 0; 20042f167a42Smrg XkbKeyPtr key; 20052f167a42Smrg 20062f167a42Smrg if (state->args->label == LABEL_NONE) 20072f167a42Smrg break; 20082f167a42Smrg if (row->vertical) 20092f167a42Smrg offset = row->top; 20102f167a42Smrg else 20112f167a42Smrg offset = row->left; 20122f167a42Smrg fprintf(out, "%% Begin %s %d labels\n", 20132f167a42Smrg row->vertical ? "column" : "row", r + 1); 20142f167a42Smrg PSSetColor(out, state, xkb->geom->label_color->pixel); 20152f167a42Smrg PSSetFont(out, state, FONT_LATIN1, 12, True); 20162f167a42Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 20172f167a42Smrg char *name, *name2, buf[30], buf2[30]; 20182f167a42Smrg int x, y; 20192f167a42Smrg KeyTop top; 20208b648e79Smrg XkbShapePtr shape; 20218b648e79Smrg XkbBoundsRec bounds; 20222f167a42Smrg 20232f167a42Smrg shape = XkbKeyShape(xkb->geom, key); 20242f167a42Smrg XkbComputeShapeTop(shape, &bounds); 20252f167a42Smrg offset += key->gap; 20262f167a42Smrg name = name2 = NULL; 20272f167a42Smrg if (state->args->label == LABEL_SYMBOLS) { 20282f167a42Smrg if (!FindKeysymsByName(xkb, key->name.name, state, &top)) { 20292f167a42Smrg fprintf(out, "%% No label for %s\n", 20302f167a42Smrg XkbKeyNameText(key->name.name, XkbMessage)); 20312f167a42Smrg } 20322f167a42Smrg } 20332f167a42Smrg else { 20342f167a42Smrg char *olKey; 20352f167a42Smrg 20362f167a42Smrg if (section->num_overlays > 0) 20372f167a42Smrg olKey = XkbFindOverlayForKey(xkb->geom, section, 20382f167a42Smrg key->name.name); 20392f167a42Smrg else 20402f167a42Smrg olKey = NULL; 20412f167a42Smrg 20422f167a42Smrg if (state->args->label == LABEL_KEYNAME) { 20432f167a42Smrg name = XkbKeyNameText(key->name.name, XkbMessage); 20442f167a42Smrg if (olKey) 20452f167a42Smrg name2 = XkbKeyNameText(olKey, XkbMessage); 20462f167a42Smrg } 20472f167a42Smrg else if (state->args->label == LABEL_KEYCODE) { 20482f167a42Smrg name = buf; 20492f167a42Smrg snprintf(name, sizeof(buf), "%d", 20502f167a42Smrg XkbFindKeycodeByName(xkb, key->name.name, True)); 20512f167a42Smrg if (olKey) { 20522f167a42Smrg name2 = buf2; 20532f167a42Smrg snprintf(name2, sizeof(buf2), "%d", 20542f167a42Smrg XkbFindKeycodeByName(xkb, olKey, True)); 20552f167a42Smrg } 20562f167a42Smrg } 20572f167a42Smrg bzero(&top, sizeof(KeyTop)); 20582f167a42Smrg if (name2 != NULL) { 20592f167a42Smrg top.present |= G1LX_MASK; 20602f167a42Smrg strncpy(top.label[G1L1], name, LABEL_LEN - 1); 20612f167a42Smrg top.label[G1L1][LABEL_LEN - 1] = '\0'; 20622f167a42Smrg strncpy(top.label[G1L2], name2, LABEL_LEN - 1); 20632f167a42Smrg top.label[G1L2][LABEL_LEN - 1] = '\0'; 20642f167a42Smrg } 20652f167a42Smrg else if (name != NULL) { 20662f167a42Smrg top.present |= CENTER_MASK; 20672f167a42Smrg strncpy(top.label[CENTER], name, LABEL_LEN - 1); 20682f167a42Smrg top.label[CENTER][LABEL_LEN - 1] = '\0'; 20692f167a42Smrg } 20702f167a42Smrg else { 20712f167a42Smrg fprintf(out, "%% No label for %s\n", 20722f167a42Smrg XkbKeyNameText(key->name.name, XkbMessage)); 20732f167a42Smrg } 20742f167a42Smrg } 20752f167a42Smrg if (row->vertical) { 20762f167a42Smrg x = row->left; 20772f167a42Smrg y = offset; 20782f167a42Smrg offset += shape->bounds.y2; 20792f167a42Smrg } 20802f167a42Smrg else { 20812f167a42Smrg x = offset; 20822f167a42Smrg y = row->top; 20832f167a42Smrg offset += shape->bounds.x2; 20842f167a42Smrg } 20852f167a42Smrg name = key->name.name; 20862f167a42Smrg fprintf(out, "%% %s\n", XkbKeyNameText(name, XkbMessage)); 20872f167a42Smrg if (state->args->wantKeycodes) 20882f167a42Smrg kc = XkbFindKeycodeByName(xkb, key->name.name, True); 20892f167a42Smrg PSLabelKey(out, state, &top, x, y, &bounds, kc, shape->bounds.y2); 20902f167a42Smrg } 20910e20ee16Smrg } 20922f167a42Smrg PSGRestore(out, state); 20930e20ee16Smrg return; 20940e20ee16Smrg} 20950e20ee16Smrg 20960e20ee16SmrgBool 20970e20ee16SmrgGeometryToPostScript(FILE *out, XkbFileInfo *pResult, XKBPrintArgs *args) 20980e20ee16Smrg{ 20992f167a42Smrg XkbDrawablePtr first, draw; 21002f167a42Smrg PSState state; 21012f167a42Smrg Bool dfltBorder; 21022f167a42Smrg 21032f167a42Smrg if ((!pResult) || (!pResult->xkb) || (!pResult->xkb->geom)) 21042f167a42Smrg return False; 21058b648e79Smrg state = (PSState) { 21068b648e79Smrg .xkb = pResult->xkb, 21078b648e79Smrg .dpy = pResult->xkb->dpy, 21088b648e79Smrg .geom = pResult->xkb->geom, 21098b648e79Smrg .color = -1, 21108b648e79Smrg .black = -1, 21118b648e79Smrg .white = -1, 21128b648e79Smrg .font = -1, 21138b648e79Smrg .nPages = 0, 21148b648e79Smrg .totalKB = 1, 21158b648e79Smrg .kbPerPage = 1, 21168b648e79Smrg .x1 = 0, 21178b648e79Smrg .y1 = 0, 21188b648e79Smrg .x2 = 0, 21198b648e79Smrg .y2 = 0, 21208b648e79Smrg .args = args 21218b648e79Smrg }; 21222f167a42Smrg 21232f167a42Smrg if ((args->label == LABEL_SYMBOLS) && (pResult->xkb->ctrls)) { 21242f167a42Smrg if (args->nTotalGroups == 0) 21252f167a42Smrg state.totalKB = 21262f167a42Smrg pResult->xkb->ctrls->num_groups / args->nLabelGroups; 21272f167a42Smrg else 21282f167a42Smrg state.totalKB = args->nTotalGroups; 21292f167a42Smrg if (state.totalKB < 1) 21302f167a42Smrg state.totalKB = 1; 21312f167a42Smrg else if (state.totalKB > 1) 21322f167a42Smrg state.kbPerPage = 2; 21330e20ee16Smrg } 21342f167a42Smrg if (args->nKBPerPage != 0) 21352f167a42Smrg state.kbPerPage = args->nKBPerPage; 21362f167a42Smrg 21372f167a42Smrg PSProlog(out, &state); 21382f167a42Smrg first = XkbGetOrderedDrawables(state.geom, NULL); 21392f167a42Smrg 21402f167a42Smrg for (draw = first, dfltBorder = True; draw != NULL; draw = draw->next) { 21412f167a42Smrg if ((draw->type != XkbDW_Section) && 21422f167a42Smrg ((draw->u.doodad->any.type == XkbOutlineDoodad) || 21432f167a42Smrg (draw->u.doodad->any.type == XkbSolidDoodad))) { 21442f167a42Smrg char *name; 21452f167a42Smrg 21462f167a42Smrg name = XkbAtomGetString(state.dpy, draw->u.doodad->any.name); 21472f167a42Smrg if ((name != NULL) && (uStrCaseEqual(name, "edges"))) { 21482f167a42Smrg dfltBorder = False; 2149e6bced22Smrg XFree(name); 21502f167a42Smrg break; 21512f167a42Smrg } 2152e6bced22Smrg XFree(name); 21532f167a42Smrg } 21540e20ee16Smrg } 21558b648e79Smrg for (int i = 0; i < state.totalKB; i++) { 21562f167a42Smrg PSPageSetup(out, &state, dfltBorder); 21572f167a42Smrg for (draw = first; draw != NULL; draw = draw->next) { 21582f167a42Smrg if (draw->type == XkbDW_Section) 21592f167a42Smrg PSSection(out, &state, draw->u.section); 21602f167a42Smrg else { 21612f167a42Smrg PSDoodad(out, &state, draw->u.doodad); 21622f167a42Smrg } 21632f167a42Smrg } 21642f167a42Smrg PSPageTrailer(out, &state); 21652f167a42Smrg state.args->baseLabelGroup += state.args->nLabelGroups; 21660e20ee16Smrg } 21670e20ee16Smrg XkbFreeOrderedDrawables(first); 21682f167a42Smrg PSFileTrailer(out, &state); 21690e20ee16Smrg return True; 21700e20ee16Smrg} 2171