2133 lines
68 KiB
C
2133 lines
68 KiB
C
/************************************************************
|
|
Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
|
|
|
|
Permission to use, copy, modify, and distribute this
|
|
software and its documentation for any purpose and without
|
|
fee is hereby granted, provided that the above copyright
|
|
notice appear in all copies and that both that copyright
|
|
notice and this permission notice appear in supporting
|
|
documentation, and that the name of Silicon Graphics not be
|
|
used in advertising or publicity pertaining to distribution
|
|
of the software without specific prior written permission.
|
|
Silicon Graphics makes no representation about the suitability
|
|
of this software for any purpose. It is provided "as is"
|
|
without any express or implied warranty.
|
|
|
|
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
|
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
|
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
|
|
THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
********************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#define XK_TECHNICAL
|
|
#define XK_PUBLISHING
|
|
#define XK_KATAKANA
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <X11/X.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/XKBlib.h>
|
|
#include <X11/extensions/XKBgeom.h>
|
|
#include <X11/extensions/XKM.h>
|
|
#include <X11/extensions/XKBfile.h>
|
|
#include <X11/keysym.h>
|
|
#include <X11/Xutil.h>
|
|
|
|
#if defined(sgi)
|
|
#include <malloc.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "utils.h"
|
|
#include "xkbprint.h"
|
|
#include "isokeys.h"
|
|
|
|
#define FONT_NONE -1
|
|
#define FONT_TEXT 0
|
|
#define FONT_LATIN1 1
|
|
#define FONT_SYMBOL 2
|
|
#define FONT_ISOCAPS 3
|
|
#define FONT_MOUSECAPS 4
|
|
|
|
typedef struct {
|
|
Display * dpy;
|
|
XkbDescPtr xkb;
|
|
XkbGeometryPtr geom;
|
|
int totalKB;
|
|
int kbPerPage;
|
|
int black;
|
|
int white;
|
|
int color;
|
|
int font;
|
|
int fontSize;
|
|
int nPages;
|
|
int x1, y1;
|
|
int x2, y2;
|
|
XKBPrintArgs * args;
|
|
} PSState;
|
|
|
|
#define G1L1 0
|
|
#define G1L2 1
|
|
#define G2L1 2
|
|
#define G2L2 3
|
|
#define CENTER 4
|
|
|
|
#define G1L1_MASK (1<<G1L1)
|
|
#define G1L2_MASK (1<<G1L2)
|
|
#define G2L1_MASK (1<<G2L1)
|
|
#define G2L2_MASK (1<<G2L2)
|
|
#define CENTER_MASK (1<<CENTER)
|
|
|
|
#define LABEL_MASK (0x1f)
|
|
#define GXL1_MASK (G1L1_MASK|G2L1_MASK)
|
|
#define GXL2_MASK (G1L2_MASK|G2L2_MASK)
|
|
#define G1LX_MASK (G1L1_MASK|G1L2_MASK)
|
|
#define G2LX_MASK (G2L1_MASK|G2L2_MASK)
|
|
#define GXLX_MASK (0x0f)
|
|
|
|
#define NLABELS 5
|
|
#define LABEL_LEN 30
|
|
|
|
#define SZ_AUTO 0
|
|
#define SZ_TINY 1
|
|
#define SZ_SMALL 2
|
|
#define SZ_MEDIUM 3
|
|
#define SZ_LARGE 4
|
|
#define SZ_XLARGE 5
|
|
|
|
typedef struct {
|
|
unsigned present;
|
|
Bool alpha[2];
|
|
char label[NLABELS][LABEL_LEN];
|
|
int font[NLABELS];
|
|
int size[NLABELS];
|
|
} KeyTop;
|
|
|
|
#define DFLT_LABEL_FONT "Helvetica-Narrow-Bold"
|
|
#define DFLT_LABEL_FONT_SIZE 10
|
|
|
|
/***====================================================================***/
|
|
|
|
typedef struct _PSFontDef {
|
|
const char *name;
|
|
const char **def;
|
|
} PSFontDef;
|
|
|
|
static PSFontDef internalFonts[] = {
|
|
{ "IsoKeyCaps", &IsoKeyCaps }
|
|
};
|
|
static int nInternalFonts = (sizeof(internalFonts) / sizeof(PSFontDef));
|
|
|
|
static void
|
|
ListInternalFonts(FILE *out, int first, int indent)
|
|
{
|
|
register int i, n, nThisLine;
|
|
|
|
for (n = 0; n < first; n++) {
|
|
putc(' ', out);
|
|
}
|
|
|
|
for (nThisLine = i = 0; i < nInternalFonts; i++) {
|
|
if (nThisLine == 4) {
|
|
fprintf(out, ",\n");
|
|
for (n = 0; n < indent; n++) {
|
|
putc(' ', out);
|
|
}
|
|
nThisLine = 0;
|
|
}
|
|
if (nThisLine == 0)
|
|
fprintf(out, "%s", internalFonts[i].name);
|
|
else
|
|
fprintf(out, ", %s", internalFonts[i].name);
|
|
nThisLine++;
|
|
}
|
|
if (nThisLine != 0)
|
|
fprintf(out, "\n");
|
|
return;
|
|
}
|
|
|
|
static Bool
|
|
PSIncludeFont(FILE *out, const char *font)
|
|
{
|
|
const char **pstr;
|
|
register int i;
|
|
|
|
pstr = NULL;
|
|
for (i = 0; (i < nInternalFonts) && (pstr == NULL); i++) {
|
|
if (uStringEqual(internalFonts[i].name, font))
|
|
pstr = internalFonts[i].def;
|
|
}
|
|
if (pstr != NULL) {
|
|
fprintf(out, "%%%%BeginFont: %s\n", font);
|
|
fprintf(out, "%s", *pstr);
|
|
fprintf(out, "%%%%EndFont\n");
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
Bool
|
|
DumpInternalFont(FILE *out, const char *fontName)
|
|
{
|
|
if (strcmp(fontName, "IsoKeyCaps") != 0) {
|
|
uError("No internal font named \"%s\"\n", fontName);
|
|
uAction("No font dumped\n");
|
|
fprintf(stderr, "Current internal fonts are: ");
|
|
ListInternalFonts(stderr, 0, 8);
|
|
return False;
|
|
}
|
|
PSIncludeFont(out, fontName);
|
|
return True;
|
|
}
|
|
|
|
/***====================================================================***/
|
|
|
|
static void
|
|
PSColorDef(FILE *out, PSState *state, XkbColorPtr color)
|
|
{
|
|
int tmp;
|
|
|
|
fprintf(out, "/C%03d ", color->pixel);
|
|
if (uStrCaseEqual(color->spec, "black")) {
|
|
state->black = color->pixel;
|
|
fprintf(out, "{ 0 setgray } def %% %s\n", color->spec);
|
|
}
|
|
else if (uStrCaseEqual(color->spec, "white")) {
|
|
state->white = color->pixel;
|
|
fprintf(out, "{ 1 setgray } def %% %s\n", color->spec);
|
|
}
|
|
else if ((sscanf(color->spec, "grey%d", &tmp) == 1) ||
|
|
(sscanf(color->spec, "gray%d", &tmp) == 1) ||
|
|
(sscanf(color->spec, "Grey%d", &tmp) == 1) ||
|
|
(sscanf(color->spec, "Gray%d", &tmp) == 1)) {
|
|
fprintf(out, "{ %f setgray } def %% %s\n",
|
|
1.0 - (((float) tmp) / 100.0), color->spec);
|
|
}
|
|
else if ((tmp = (uStrCaseEqual(color->spec, "red") * 100)) ||
|
|
(sscanf(color->spec, "red%d", &tmp) == 1)) {
|
|
fprintf(out, "{ %f 0 0 setrgbcolor } def %% %s\n",
|
|
(((float) tmp) / 100.0), color->spec);
|
|
}
|
|
else if ((tmp = (uStrCaseEqual(color->spec, "green") * 100)) ||
|
|
(sscanf(color->spec, "green%d", &tmp) == 1)) {
|
|
fprintf(out, "{ 0 %f 0 setrgbcolor } def %% %s\n",
|
|
(((float) tmp) / 100.0), color->spec);
|
|
}
|
|
else if ((tmp = (uStrCaseEqual(color->spec, "blue") * 100)) ||
|
|
(sscanf(color->spec, "blue%d", &tmp) == 1)) {
|
|
fprintf(out, "{ 0 0 %f setrgbcolor } def %% %s\n",
|
|
(((float) tmp) / 100.0), color->spec);
|
|
}
|
|
else
|
|
fprintf(out, "{ 0.9 setgray } def %% BOGUS! %s\n", color->spec);
|
|
}
|
|
|
|
static void
|
|
PSSetColor(FILE *out, PSState *state, int color)
|
|
{
|
|
if ((state->args->wantColor) && (state->color != color)) {
|
|
fprintf(out, "C%03d %% set color\n", color);
|
|
state->color = color;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSGSave(FILE *out, PSState *state)
|
|
{
|
|
fprintf(out, "gsave\n");
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSGRestore(FILE *out, PSState *state)
|
|
{
|
|
fprintf(out, "grestore\n");
|
|
state->color = -1;
|
|
state->font = FONT_NONE;
|
|
state->fontSize = -1;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSShapeDef(FILE *out, PSState *state, XkbShapePtr shape)
|
|
{
|
|
int o, p;
|
|
XkbOutlinePtr ol;
|
|
|
|
fprintf(out, "/%s {\n", XkbAtomGetString(state->dpy, shape->name));
|
|
fprintf(out, " gsave translate rotate /SOLID exch def\n");
|
|
for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
|
|
XkbPointPtr pt;
|
|
|
|
if ((shape->num_outlines > 1) && (ol == shape->approx))
|
|
continue;
|
|
pt = ol->points;
|
|
fprintf(out, "%% Outline %d\n", o + 1);
|
|
if (ol->num_points == 1) {
|
|
if (ol->corner_radius < 1) {
|
|
fprintf(out, " 0 0 moveto\n");
|
|
fprintf(out, " %3d 0 lineto\n", pt->x);
|
|
fprintf(out, " %3d %3d lineto\n", pt->x, pt->y);
|
|
fprintf(out, " 0 %3d lineto\n", pt->y);
|
|
fprintf(out, " 0 0 lineto\n");
|
|
fprintf(out, " SOLID { fill } { stroke } ifelse\n");
|
|
}
|
|
else {
|
|
fprintf(out, " mark\n");
|
|
fprintf(out, " %3d 0 moveto\n", ol->corner_radius);
|
|
fprintf(out, " %3d 0 %3d %3d %3d arcto\n", pt->x, pt->x,
|
|
pt->y, ol->corner_radius);
|
|
fprintf(out, " %3d %3d 0 %3d %3d arcto\n", pt->x, pt->y,
|
|
pt->y, ol->corner_radius);
|
|
fprintf(out, " 0 %3d 0 0 %3d arcto\n", pt->y,
|
|
ol->corner_radius);
|
|
fprintf(out, " 0 0 %3d 0 %3d arcto\n", pt->x,
|
|
ol->corner_radius);
|
|
fprintf(out, " SOLID { fill } { stroke } ifelse\n");
|
|
fprintf(out, " cleartomark\n");
|
|
}
|
|
}
|
|
else if (ol->num_points == 2) {
|
|
if (ol->corner_radius < 1) {
|
|
fprintf(out, " %3d %3d moveto\n", pt[0].x, pt[0].y);
|
|
fprintf(out, " %3d %3d lineto\n", pt[1].x, pt[0].y);
|
|
fprintf(out, " %3d %3d lineto\n", pt[1].x, pt[1].y);
|
|
fprintf(out, " %3d %3d lineto\n", pt[0].x, pt[1].y);
|
|
fprintf(out, " %3d %3d lineto\n", pt[0].x, pt[0].y);
|
|
fprintf(out, " SOLID { fill } { stroke } ifelse\n");
|
|
}
|
|
else {
|
|
fprintf(out, " mark\n");
|
|
fprintf(out, " %3d %3d moveto\n", pt[0].x + ol->corner_radius,
|
|
pt[0].y);
|
|
fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[0].y,
|
|
pt[1].x, pt[1].y, ol->corner_radius);
|
|
fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[1].y,
|
|
pt[0].x, pt[1].y, ol->corner_radius);
|
|
fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[1].y,
|
|
pt[0].x, pt[0].y, ol->corner_radius);
|
|
fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[0].y,
|
|
pt[1].x, pt[0].y, ol->corner_radius);
|
|
fprintf(out, " SOLID { fill } { stroke } ifelse\n");
|
|
fprintf(out, " cleartomark\n");
|
|
}
|
|
}
|
|
else {
|
|
if (ol->corner_radius < 1) {
|
|
fprintf(out, " %3d %3d moveto\n", pt->x, pt->y);
|
|
pt++;
|
|
for (p = 1; p < ol->num_points; p++, pt++) {
|
|
fprintf(out, " %3d %3d lineto\n", pt->x, pt->y);
|
|
}
|
|
if ((pt->x != ol->points[0].x) || (pt->y != ol->points[0].y))
|
|
fprintf(out, " closepath\n");
|
|
fprintf(out, " SOLID { fill } { stroke } ifelse\n");
|
|
}
|
|
else {
|
|
XkbPointPtr last;
|
|
|
|
last = &pt[ol->num_points - 1];
|
|
if ((last->x == pt->x) && (last->y == pt->y))
|
|
last--;
|
|
fprintf(out, " mark\n");
|
|
fprintf(out, " %% Determine tangent point of first corner\n");
|
|
fprintf(out, " %3d %3d moveto %d %d %d %d %d arcto\n",
|
|
last->x, last->y,
|
|
pt[0].x, pt[0].y, pt[1].x, pt[1].y, ol->corner_radius);
|
|
fprintf(out, " /TY exch def /TX exch def pop pop newpath\n");
|
|
fprintf(out, " %% Now draw the shape\n");
|
|
fprintf(out, " TX TY moveto\n");
|
|
for (p = 1; p < ol->num_points; p++) {
|
|
if (p < (ol->num_points - 1))
|
|
last = &pt[p + 1];
|
|
else
|
|
last = &pt[0];
|
|
fprintf(out, " %3d %3d %3d %3d %3d arcto\n",
|
|
pt[p].x, pt[p].y,
|
|
last->x, last->y, ol->corner_radius);
|
|
}
|
|
last = &pt[ol->num_points - 1];
|
|
if ((last->x != pt->x) || (last->y != pt->y)) {
|
|
fprintf(out, " %3d %3d %3d %3d %3d arcto\n",
|
|
pt[0].x, pt[0].y,
|
|
pt[1].x, pt[1].y, ol->corner_radius);
|
|
}
|
|
fprintf(out, " SOLID { fill } { stroke } ifelse\n");
|
|
fprintf(out, " cleartomark\n");
|
|
}
|
|
}
|
|
}
|
|
fprintf(out, " grestore\n");
|
|
fprintf(out, "} def\n");
|
|
return;
|
|
}
|
|
|
|
/***====================================================================***/
|
|
|
|
typedef struct {
|
|
char * foundry;
|
|
char * face;
|
|
char * weight;
|
|
char * slant;
|
|
char * setWidth;
|
|
char * variant;
|
|
int pixelSize;
|
|
int ptSize;
|
|
int resX;
|
|
int resY;
|
|
char * spacing;
|
|
int avgWidth;
|
|
char * encoding;
|
|
} FontStuff;
|
|
|
|
static void
|
|
ClearFontStuff(FontStuff *stuff)
|
|
{
|
|
if (stuff && stuff->foundry)
|
|
free(stuff->foundry);
|
|
bzero(stuff, sizeof(FontStuff));
|
|
return;
|
|
}
|
|
|
|
static Bool
|
|
CrackXLFDName(const char *name, FontStuff *stuff)
|
|
{
|
|
char *tmp;
|
|
|
|
if ((name == NULL) || (stuff == NULL))
|
|
return False;
|
|
if (name[0] == '-')
|
|
tmp = strdup(&name[1]);
|
|
else
|
|
tmp = strdup(name);
|
|
if (tmp == NULL)
|
|
return False;
|
|
stuff->foundry = tmp;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
stuff->face = tmp;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
stuff->weight = tmp;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
stuff->slant = tmp;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
stuff->setWidth = tmp;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
stuff->variant = tmp;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
if (*tmp == '*')
|
|
stuff->pixelSize = 0;
|
|
else if (sscanf(tmp, "%i", &stuff->pixelSize) != 1)
|
|
goto BAILOUT;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
if (*tmp == '*')
|
|
stuff->ptSize = 0;
|
|
else if (sscanf(tmp, "%i", &stuff->ptSize) != 1)
|
|
goto BAILOUT;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
if (*tmp == '*')
|
|
stuff->resX = 0;
|
|
else if (sscanf(tmp, "%i", &stuff->resX) != 1)
|
|
goto BAILOUT;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
if (*tmp == '*')
|
|
stuff->resY = 0;
|
|
else if (sscanf(tmp, "%i", &stuff->resY) != 1)
|
|
goto BAILOUT;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
stuff->spacing = tmp;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
if (*tmp == '*')
|
|
stuff->avgWidth = 0;
|
|
else if (sscanf(tmp, "%i", &stuff->avgWidth) != 1)
|
|
goto BAILOUT;
|
|
|
|
if ((tmp = strchr(tmp, '-')) == NULL)
|
|
goto BAILOUT;
|
|
else
|
|
*tmp++ = '\0';
|
|
stuff->encoding = tmp;
|
|
return True;
|
|
BAILOUT:
|
|
ClearFontStuff(stuff);
|
|
return False;
|
|
}
|
|
|
|
static void
|
|
PSSetUpForLatin1(FILE *out, PSState *state)
|
|
{
|
|
fprintf(out, "%s",
|
|
"save\n"
|
|
"/ISOLatin1Encoding where {pop save true}{false} ifelse\n"
|
|
"/ISOLatin1Encoding [\n"
|
|
" /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
|
|
" /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
|
|
" /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
|
|
" /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
|
|
" /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
|
|
" /.notdef /.notdef /space /exclam /quotedbl /numbersign\n"
|
|
" /dollar /percent /ampersand /quoteright /parenleft\n"
|
|
" /parenright /asterisk /plus /comma /minus /period\n"
|
|
" /slash /zero /one /two /three /four /five /six /seven\n"
|
|
" /eight /nine /colon /semicolon /less /equal /greater\n"
|
|
" /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M\n"
|
|
" /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n"
|
|
" /backslash /bracketright /asciicircum /underscore\n"
|
|
" /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m\n"
|
|
" /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft\n"
|
|
" /bar /braceright /asciitilde /guilsinglright /fraction\n"
|
|
" /florin /quotesingle /quotedblleft /guilsinglleft /fi\n"
|
|
" /fl /endash /dagger /daggerdbl /bullet /quotesinglbase\n"
|
|
" /quotedblbase /quotedblright /ellipsis /trademark\n"
|
|
" /perthousand /grave /scaron /circumflex /Scaron /tilde\n"
|
|
" /breve /zcaron /dotaccent /dotlessi /Zcaron /ring\n"
|
|
" /hungarumlaut /ogonek /caron /emdash /space /exclamdown\n"
|
|
" /cent /sterling /currency /yen /brokenbar /section\n"
|
|
" /dieresis /copyright /ordfeminine /guillemotleft\n"
|
|
" /logicalnot /hyphen /registered /macron /degree\n"
|
|
" /plusminus /twosuperior /threesuperior /acute /mu\n"
|
|
" /paragraph /periodcentered /cedilla /onesuperior\n"
|
|
" /ordmasculine /guillemotright /onequarter /onehalf\n"
|
|
" /threequarters /questiondown /Agrave /Aacute\n"
|
|
" /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
|
|
" /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute\n"
|
|
" /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute\n"
|
|
" /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n"
|
|
" /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n"
|
|
" /germandbls /agrave /aacute /acircumflex /atilde\n"
|
|
" /adieresis /aring /ae /ccedilla /egrave /eacute\n"
|
|
" /ecircumflex /edieresis /igrave /iacute /icircumflex\n"
|
|
" /idieresis /eth /ntilde /ograve /oacute /ocircumflex\n"
|
|
" /otilde /odieresis /divide /oslash /ugrave /uacute\n"
|
|
" /ucircumflex /udieresis /yacute /thorn /ydieresis\n"
|
|
"] def {restore} if\n"
|
|
"/reencodeISO-1 {\n"
|
|
" dup length dict begin\n"
|
|
" {1 index /FID ne {def}{pop pop} ifelse} forall\n"
|
|
" /Encoding ISOLatin1Encoding def\n"
|
|
" currentdict\n"
|
|
" end\n"
|
|
"} def\n"
|
|
);
|
|
}
|
|
|
|
static void
|
|
PSReencodeLatin1Font(FILE *out, const char *font)
|
|
{
|
|
fprintf(out, "/%s findfont reencodeISO-1\n", font);
|
|
fprintf(out, " /%s-8859-1 exch definefont pop\n", font);
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSSetUpFonts(FILE *out, const char *textFont, int size)
|
|
{
|
|
fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n",
|
|
FONT_TEXT, textFont);
|
|
fprintf(out, "/F%d { /%s-8859-1 findfont exch scalefont setfont } def\n",
|
|
FONT_LATIN1, textFont);
|
|
fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n",
|
|
FONT_SYMBOL, "Symbol");
|
|
fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n",
|
|
FONT_ISOCAPS, "IsoKeyCaps");
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSSetFont(FILE *out, PSState *state, int font, int size, int pts)
|
|
{
|
|
if ((state->font != font) || (state->fontSize != size)) {
|
|
fprintf(out, "%d %sF%d\n", size, (pts ? "pts " : ""), font);
|
|
state->font = font;
|
|
state->fontSize = size;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSProlog(FILE *out, PSState *state)
|
|
{
|
|
register int i;
|
|
|
|
if (!state->args->wantEPS) {
|
|
fprintf(out,
|
|
"%%!PS-Adobe-2.0\n"
|
|
"%%%%Creator: xkbprint\n");
|
|
if (state->geom->name != None)
|
|
fprintf(out, "%%%%Title: %s\n",
|
|
XkbAtomGetString(state->dpy, state->geom->name));
|
|
fprintf(out,
|
|
"%%%%BoundingBox: (atend)\n"
|
|
"%%%%Pages: 1\n"
|
|
"%%%%PageOrder: Ascend\n"
|
|
"%%%%DocumentFonts: (atend)\n"
|
|
"%%%%DocumentData: Clean7Bit\n"
|
|
"%%%%Orientation: Landscape\n"
|
|
"%%%%EndComments\n"
|
|
"%%%%BeginProlog\n"
|
|
"%% Resolution is 1/10mm -- need pt sizes for fonts\n"
|
|
"clippath pathbbox\n"
|
|
" /ury exch def /urx exch def\n"
|
|
" /llx exch def /lly exch def\n"
|
|
" newpath\n"
|
|
"/devwidth urx llx sub def\n"
|
|
"/devheight ury lly sub def\n");
|
|
}
|
|
else {
|
|
int w, h;
|
|
int pw, ph;
|
|
|
|
w = (((state->geom->width_mm * 72) / 254) * 11) / 10;
|
|
h = (((state->geom->height_mm * 72) / 254) * 11) / 10;
|
|
if (state->kbPerPage > 1)
|
|
h *= (state->kbPerPage + 1);
|
|
|
|
if (w <= h) {
|
|
pw = 7.5 * 72;
|
|
ph = 10 * 72;
|
|
}
|
|
else {
|
|
pw = 10 * 72;
|
|
ph = 7.5 * 72;
|
|
}
|
|
while ((w > pw) || (h > ph)) {
|
|
w = (w * 9) / 10;
|
|
h = (h * 9) / 10;
|
|
}
|
|
|
|
fprintf(out, "%%!PS-Adobe-2.0 EPSF-2.0\n");
|
|
fprintf(out, "%%%%BoundingBox: 0 0 %d %d\n", w, h);
|
|
fprintf(out, "%%%%Creator: xkbprint\n");
|
|
if (state->geom->name != None)
|
|
fprintf(out, "%%%%Title: %s\n",
|
|
XkbAtomGetString(state->dpy, state->geom->name));
|
|
fprintf(out, "%%%%Pages: 1\n");
|
|
fprintf(out, "%%%%EndComments\n");
|
|
fprintf(out, "%%%%BeginProlog\n");
|
|
fprintf(out, "/ury 0 def /urx 0 def\n");
|
|
fprintf(out, "/llx %d def /lly %d def\n", w, h);
|
|
fprintf(out, "/devwidth %d def /devheight %d def\n", w, h);
|
|
}
|
|
fprintf(out, "/kbdwidth %d def\n", state->geom->width_mm);
|
|
fprintf(out, "/kbdheight %d def\n", state->geom->height_mm);
|
|
fprintf(out, "%s",
|
|
"/pts { 254 mul 72 div } def\n"
|
|
"/mm10 { 72 mul 254 div } def\n"
|
|
"/landscape? {\n"
|
|
" devheight devwidth gt {\n"
|
|
" /pwidth devheight def /pheight devwidth def\n"
|
|
" 0 devheight translate\n"
|
|
" -90 rotate\n"
|
|
" } {\n"
|
|
" /pwidth devwidth def /pheight devheight def\n"
|
|
" } ifelse\n"
|
|
" 0 pheight translate\n"
|
|
" 1 -1 scale\n"
|
|
"} def\n"
|
|
"/centeroffset {\n"
|
|
" /S exch def\n"
|
|
" /HEIGHT exch def\n"
|
|
" /WIDTH exch def\n"
|
|
" S stringwidth /SH exch def /SW exch def\n"
|
|
" WIDTH SW sub 2 div\n"
|
|
" HEIGHT SH sub 2 div\n"
|
|
"} def\n");
|
|
PSSetUpForLatin1(out, state);
|
|
PSReencodeLatin1Font(out, DFLT_LABEL_FONT);
|
|
if (state->args->wantColor) {
|
|
XkbGeometryPtr geom = state->geom;
|
|
|
|
for (i = 0; i < geom->num_colors; i++) {
|
|
PSColorDef(out, state, &geom->colors[i]);
|
|
}
|
|
if (state->black < 0) {
|
|
XkbColorPtr color;
|
|
|
|
if (!(color = XkbAddGeomColor(geom, "black", geom->num_colors)))
|
|
uFatalError("Couldn't allocate black color!\n");
|
|
PSColorDef(out, state, color);
|
|
}
|
|
if (state->white < 0) {
|
|
XkbColorPtr color;
|
|
|
|
if (!(color = XkbAddGeomColor(geom, "white", geom->num_colors)))
|
|
uFatalError("Couldn't allocate white color!\n");
|
|
PSColorDef(out, state, color);
|
|
}
|
|
}
|
|
for (i = 0; i < state->geom->num_shapes; i++) {
|
|
PSShapeDef(out, state, &state->geom->shapes[i]);
|
|
}
|
|
if (state->args->label == LABEL_SYMBOLS) {
|
|
PSIncludeFont(out, "IsoKeyCaps");
|
|
}
|
|
PSSetUpFonts(out, DFLT_LABEL_FONT, DFLT_LABEL_FONT_SIZE);
|
|
fprintf(out, "%%%%EndProlog\n");
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSFileTrailer(FILE *out, PSState *state)
|
|
{
|
|
fprintf(out, "restore\n");
|
|
if (!state->args->wantEPS)
|
|
fprintf(out, "%%%%Trailer\n");
|
|
fprintf(out, "%%%%EOF\n");
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSPageSetup(FILE *out, PSState *state, Bool drawBorder)
|
|
{
|
|
XkbGeometryPtr geom;
|
|
|
|
geom = state->geom;
|
|
if (state->kbPerPage == 1) {
|
|
fprintf(out, "%%%%Page: %d %d\n", state->nPages + 1, state->nPages + 1);
|
|
fprintf(out, "%%%%BeginPageSetup\n");
|
|
}
|
|
else if ((state->nPages & 1) == 0) { /* even page */
|
|
int realPage;
|
|
|
|
realPage = state->nPages / 2 + 1;
|
|
fprintf(out, "%%%%Page: %d %d\n", realPage, realPage);
|
|
fprintf(out, "%%%%BeginPageSetup\n");
|
|
fprintf(out, "%% Keyboard %d\n", state->nPages + 1);
|
|
if (state->nPages == 0) {
|
|
fprintf(out,
|
|
"/realwidth devwidth def\n"
|
|
"/realheight devheight def\n"
|
|
"/devheight realheight 3 div def\n");
|
|
}
|
|
fprintf(out, "0 devheight dup 2 div add translate\n");
|
|
}
|
|
else {
|
|
fprintf(out, "%% Keyboard %d\n", state->nPages + 1);
|
|
}
|
|
fprintf(out, "save\n");
|
|
fprintf(out, "landscape?\n");
|
|
if (state->args->scaleToFit) {
|
|
fprintf(out,
|
|
"%% Scale keyboard to fit on the page\n"
|
|
"/kbdscale pwidth 72 sub kbdwidth div def\n"
|
|
"/kbdscalewidth kbdwidth kbdscale mul def\n"
|
|
"/kbdscaleheight kbdheight kbdscale mul def\n"
|
|
"/kbx 36 def\n"
|
|
"/kby pheight kbdscaleheight sub 2 div def\n");
|
|
PSGSave(out, state);
|
|
fprintf(out,
|
|
"kbx kby translate\n"
|
|
"kbdscale kbdscale scale\n");
|
|
}
|
|
else {
|
|
fprintf(out,
|
|
"%% Draw keyboard full size\n"
|
|
"/kbdscale 1 def\n"
|
|
"/kbdscalewidth kbdwidth mm10 def\n"
|
|
"/kbdscaleheight kbdheight mm10 def\n"
|
|
"/kbx pwidth kbdscalewidth sub 2 div def\n"
|
|
"/kby pheight kbdscaleheight sub 2 div def\n");
|
|
PSGSave(out, state);
|
|
fprintf(out,
|
|
"kbx kby translate\n"
|
|
"72 254 div dup scale\n");
|
|
}
|
|
if (drawBorder) {
|
|
if (state->args->wantColor) {
|
|
PSSetColor(out, state, geom->base_color->pixel);
|
|
fprintf(out, " 0 0 moveto\n");
|
|
fprintf(out, "%3d 0 lineto\n", geom->width_mm);
|
|
fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm);
|
|
fprintf(out, " 0 %3d lineto\n", geom->height_mm);
|
|
fprintf(out, "closepath fill\n");
|
|
}
|
|
PSSetColor(out, state, state->black);
|
|
fprintf(out, " 0 0 moveto\n");
|
|
fprintf(out, "%3d 0 lineto\n", geom->width_mm);
|
|
fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm);
|
|
fprintf(out, " 0 %3d lineto\n", geom->height_mm);
|
|
fprintf(out, "closepath stroke\n");
|
|
}
|
|
fprintf(out, "%%%%EndPageSetup\n");
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSPageTrailer(FILE *out, PSState *state)
|
|
{
|
|
char *name;
|
|
XkbDescPtr xkb;
|
|
XkbGeometryPtr geom;
|
|
XkbPropertyPtr prop;
|
|
int p, baseline;
|
|
|
|
xkb = state->xkb;
|
|
geom = state->geom;
|
|
if (state->args->grid > 0) {
|
|
fprintf(out, "%% Draw a %dmm grid\n", state->args->grid);
|
|
fprintf(out, "0 setlinewidth\n");
|
|
fprintf(out, "0.25 setgray\n");
|
|
fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->width_mm);
|
|
fprintf(out, " /GX exch def\n");
|
|
fprintf(out, " GX 0 moveto GX %d lineto stroke\n", geom->height_mm);
|
|
fprintf(out, "} for\n");
|
|
fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->height_mm);
|
|
fprintf(out, " /GY exch def\n");
|
|
fprintf(out, " 0 GY moveto %d GY lineto stroke\n", geom->width_mm);
|
|
fprintf(out, "} for\n");
|
|
}
|
|
PSGRestore(out, state);
|
|
name = NULL;
|
|
for (p = 0, prop = geom->properties; p < geom->num_properties; p++, prop++) {
|
|
if ((prop->value != NULL) && (uStrCaseEqual(prop->name, "description"))) {
|
|
name = prop->value;
|
|
break;
|
|
}
|
|
}
|
|
if ((!state->args->wantEPS) &&
|
|
((state->kbPerPage == 1) || ((state->nPages & 1) == 1) ||
|
|
(state->nPages == state->totalKB))) {
|
|
if ((name == NULL) && (geom->name != None))
|
|
name = XkbAtomGetString(state->dpy, geom->name);
|
|
|
|
baseline = 16;
|
|
if ((name != NULL) || (state->args->label == LABEL_SYMBOLS)) {
|
|
PSSetColor(out, state, state->black);
|
|
PSSetFont(out, state, FONT_LATIN1, 14, False);
|
|
}
|
|
if (state->args->label == LABEL_SYMBOLS) {
|
|
char buf[40], *lbuf;
|
|
const char *sName = NULL;
|
|
Atom sAtom;
|
|
|
|
if (state->args->nLabelGroups == 1)
|
|
snprintf(buf, sizeof(buf), "Group %d",
|
|
state->args->baseLabelGroup + 1);
|
|
else
|
|
snprintf(buf, sizeof(buf), "Groups %d-%d",
|
|
state->args->baseLabelGroup + 1,
|
|
state->args->baseLabelGroup +
|
|
state->args->nLabelGroups);
|
|
fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
|
|
buf);
|
|
fprintf(out, " kby kbdscaleheight add %d add\n", baseline);
|
|
fprintf(out, " moveto\n");
|
|
fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf);
|
|
baseline += 16;
|
|
|
|
if (xkb->names != NULL)
|
|
sAtom = xkb->names->symbols;
|
|
else
|
|
sAtom = None;
|
|
if (sAtom != None)
|
|
sName = XkbAtomGetString(state->dpy, sAtom);
|
|
if (sName == NULL)
|
|
sName = "(unknown)";
|
|
|
|
if (asprintf(&lbuf, "Layout: %s", sName) == -1) {
|
|
uFatalError("Can't allocate memory for string\n");
|
|
}
|
|
fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
|
|
lbuf);
|
|
fprintf(out, " kby kbdscaleheight add %d add\n", baseline);
|
|
fprintf(out, " moveto\n");
|
|
fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf);
|
|
baseline += 16;
|
|
free(lbuf);
|
|
}
|
|
if (name != NULL) {
|
|
fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
|
|
name);
|
|
fprintf(out, " kby kbdscaleheight add %d add\n", baseline);
|
|
fprintf(out, " moveto\n");
|
|
fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", name);
|
|
baseline += 16;
|
|
}
|
|
if (state->args->label == LABEL_KEYCODE) {
|
|
const char *sName = NULL;
|
|
char *lbuf;
|
|
Atom sAtom;
|
|
|
|
if (xkb->names != NULL)
|
|
sAtom = xkb->names->keycodes;
|
|
else
|
|
sAtom = None;
|
|
if (sAtom != None)
|
|
sName = XkbAtomGetString(state->dpy, sAtom);
|
|
if (sName == NULL)
|
|
sName = "(unknown)";
|
|
|
|
if (asprintf(&lbuf, "Keycodes: %s", sName) == -1) {
|
|
uFatalError("Can't allocate memory for string\n");
|
|
}
|
|
fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
|
|
lbuf);
|
|
fprintf(out, " kby kbdscaleheight add %d add\n", baseline);
|
|
fprintf(out, " moveto\n");
|
|
fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf);
|
|
baseline += 16;
|
|
free(lbuf);
|
|
}
|
|
if (state->args->copies > 1) {
|
|
for (p = 1; p < state->args->copies; p++)
|
|
fprintf(out, "copypage\n");
|
|
}
|
|
fprintf(out, "showpage\n");
|
|
fprintf(out, "restore\n");
|
|
fprintf(out, "%% Done with keyboard/page %d\n", state->nPages + 1);
|
|
}
|
|
else {
|
|
if ((!state->args->wantEPS) && (state->args->label == LABEL_SYMBOLS)) {
|
|
char buf[40];
|
|
|
|
baseline = 16;
|
|
PSSetColor(out, state, state->black);
|
|
PSSetFont(out, state, FONT_LATIN1, 14, False);
|
|
if (state->args->nLabelGroups == 1)
|
|
snprintf(buf, sizeof(buf), "Group %d",
|
|
state->args->baseLabelGroup + 1);
|
|
else
|
|
snprintf(buf, sizeof(buf), "Groups %d-%d",
|
|
state->args->baseLabelGroup + 1,
|
|
state->args->baseLabelGroup +
|
|
state->args->nLabelGroups + 1);
|
|
fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n",
|
|
buf);
|
|
fprintf(out, " kby kbdscaleheight add %d add\n", baseline);
|
|
fprintf(out, " moveto\n");
|
|
fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf);
|
|
baseline += 16;
|
|
}
|
|
fprintf(out, "restore\n");
|
|
fprintf(out, "%% Done with keyboard %d\n", state->nPages + 1);
|
|
fprintf(out, "0 devheight -1 mul translate %% next keyboard\n");
|
|
}
|
|
state->nPages++;
|
|
state->color = state->black;
|
|
state->font = -1;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSDoodad(FILE *out, PSState *state, XkbDoodadPtr doodad)
|
|
{
|
|
XkbDescPtr xkb;
|
|
const char *name, *dname;
|
|
int sz, leading;
|
|
|
|
xkb = state->xkb;
|
|
if (doodad->any.name != None)
|
|
dname = XkbAtomGetString(xkb->dpy, doodad->any.name);
|
|
else
|
|
dname = "NoName";
|
|
switch (doodad->any.type) {
|
|
case XkbOutlineDoodad:
|
|
case XkbSolidDoodad:
|
|
name = XkbAtomGetString(xkb->dpy,
|
|
XkbShapeDoodadShape(xkb->geom,
|
|
&doodad->shape)->name);
|
|
if (state->args->wantColor) {
|
|
PSSetColor(out, state, doodad->shape.color_ndx);
|
|
if (doodad->any.type != XkbOutlineDoodad) {
|
|
fprintf(out, "true %d %d %d %s %% Doodad %s\n",
|
|
doodad->shape.angle,
|
|
doodad->shape.left, doodad->shape.top, name, dname);
|
|
PSSetColor(out, state, state->black);
|
|
}
|
|
fprintf(out, "false %d %d %d %s %% Doodad %s\n",
|
|
doodad->shape.angle,
|
|
doodad->shape.left, doodad->shape.top, name, dname);
|
|
}
|
|
else {
|
|
fprintf(out, "false %d %d %d %s %% Doodad %s\n",
|
|
doodad->shape.angle,
|
|
doodad->shape.left, doodad->shape.top, name, dname);
|
|
}
|
|
break;
|
|
case XkbTextDoodad:
|
|
fprintf(out, "%% Doodad %s\n", dname);
|
|
PSSetColor(out, state, doodad->text.color_ndx);
|
|
PSGSave(out, state);
|
|
fprintf(out, "%d %d translate\n", doodad->text.left, doodad->text.top);
|
|
if (doodad->text.angle != 0)
|
|
fprintf(out, "%s rotate\n",
|
|
XkbGeomFPText(doodad->text.angle, XkbMessage));
|
|
sz = 14;
|
|
if (doodad->text.font) {
|
|
FontStuff stuff;
|
|
|
|
if (CrackXLFDName(doodad->text.font, &stuff)) {
|
|
if (stuff.ptSize > 0)
|
|
sz = stuff.ptSize / 10;
|
|
ClearFontStuff(&stuff);
|
|
}
|
|
}
|
|
PSSetFont(out, state, FONT_LATIN1, sz, True);
|
|
leading = (sz * 12) / 10;
|
|
if (strchr(doodad->text.text, '\n') == NULL) {
|
|
fprintf(out, "0 %d pts moveto 1 -1 scale\n", (leading * 8) / 10);
|
|
fprintf(out, "(%s) show\n", doodad->text.text);
|
|
}
|
|
else {
|
|
char *tmp, *buf, *end;
|
|
int offset = (leading * 8 / 10);
|
|
|
|
tmp = buf = strdup(doodad->text.text);
|
|
while (tmp != NULL) {
|
|
end = strchr(tmp, '\n');
|
|
if (end != NULL)
|
|
*end++ = '\0';
|
|
fprintf(out, "0 %d pts moveto 1 -1 scale\n", offset);
|
|
fprintf(out, "(%s) show 1 -1 scale\n", tmp);
|
|
offset += leading;
|
|
tmp = end;
|
|
}
|
|
free(buf);
|
|
}
|
|
PSGRestore(out, state);
|
|
break;
|
|
case XkbIndicatorDoodad:
|
|
name = XkbAtomGetString(xkb->dpy,
|
|
XkbIndicatorDoodadShape(xkb->geom,
|
|
&doodad->indicator)->
|
|
name);
|
|
if (state->args->wantColor) {
|
|
PSSetColor(out, state, doodad->indicator.off_color_ndx);
|
|
fprintf(out, "true 0 %d %d %s %% Doodad %s\n",
|
|
doodad->indicator.left, doodad->indicator.top, name, dname);
|
|
PSSetColor(out, state, state->black);
|
|
}
|
|
fprintf(out, "false 0 %d %d %s %% Doodad %s\n",
|
|
doodad->indicator.left, doodad->indicator.top, name, dname);
|
|
break;
|
|
case XkbLogoDoodad:
|
|
name = XkbAtomGetString(xkb->dpy,
|
|
XkbLogoDoodadShape(xkb->geom,
|
|
&doodad->logo)->name);
|
|
if (state->args->wantColor)
|
|
PSSetColor(out, state, doodad->shape.color_ndx);
|
|
fprintf(out, "false %d %d %d %s %% Doodad %s\n",
|
|
doodad->shape.angle,
|
|
doodad->shape.left, doodad->shape.top, name, dname);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/***====================================================================***/
|
|
|
|
static Bool
|
|
PSKeycapsSymbol(KeySym sym, unsigned char *buf,
|
|
int *font_rtrn, int *sz_rtrn, PSState *state)
|
|
{
|
|
if (state->args->wantSymbols == NO_SYMBOLS)
|
|
return False;
|
|
|
|
if (font_rtrn != NULL)
|
|
*font_rtrn = FONT_ISOCAPS;
|
|
if (sz_rtrn != NULL)
|
|
*sz_rtrn = SZ_LARGE;
|
|
buf[1] = '\0';
|
|
switch (sym) {
|
|
case XK_Shift_L:
|
|
case XK_Shift_R:
|
|
buf[0] = XKC_ISO_Shift;
|
|
return True;
|
|
case XK_Shift_Lock:
|
|
buf[0] = XKC_ISO_Shift_Lock;
|
|
return True;
|
|
case XK_ISO_Lock:
|
|
buf[0] = XKC_ISO_Caps_Lock;
|
|
return True;
|
|
case XK_BackSpace:
|
|
buf[0] = XKC_ISO_Backspace;
|
|
return True;
|
|
case XK_Return:
|
|
buf[0] = XKC_ISO_Return;
|
|
return True;
|
|
case XK_Up:
|
|
case XK_KP_Up:
|
|
buf[0] = XKC_ISO_Up;
|
|
return True;
|
|
case XK_Down:
|
|
case XK_KP_Down:
|
|
buf[0] = XKC_ISO_Down;
|
|
return True;
|
|
case XK_Left:
|
|
case XK_KP_Left:
|
|
buf[0] = XKC_ISO_Left;
|
|
return True;
|
|
case XK_Right:
|
|
case XK_KP_Right:
|
|
buf[0] = XKC_ISO_Right;
|
|
return True;
|
|
case XK_Tab:
|
|
buf[0] = XKC_ISO_Tab;
|
|
return True;
|
|
case XK_ISO_Left_Tab:
|
|
buf[0] = XKC_ISO_Left_Tab;
|
|
return True;
|
|
}
|
|
if (state->args->wantSymbols != ALL_SYMBOLS)
|
|
return False;
|
|
switch (sym) {
|
|
case XK_Caps_Lock:
|
|
buf[0] = XKC_ISO_Caps_Lock;
|
|
return True;
|
|
case XK_Num_Lock:
|
|
buf[0] = XKC_ISO_Num_Lock;
|
|
return True;
|
|
case XK_ISO_Level3_Shift:
|
|
buf[0] = XKC_ISO_Level3_Shift;
|
|
return True;
|
|
case XK_ISO_Level3_Lock:
|
|
buf[0] = XKC_ISO_Level3_Lock;
|
|
return True;
|
|
case XK_ISO_Next_Group:
|
|
case XK_ISO_Group_Shift:
|
|
buf[0] = XKC_ISO_Next_Group;
|
|
return True;
|
|
case XK_ISO_Next_Group_Lock:
|
|
buf[0] = XKC_ISO_Next_Group_Lock;
|
|
return True;
|
|
case XK_space:
|
|
buf[0] = XKC_ISO_Space;
|
|
return True;
|
|
case XK_nobreakspace:
|
|
buf[0] = XKC_ISO_No_Break_Space;
|
|
return True;
|
|
case XK_Insert:
|
|
buf[0] = XKC_ISO_Insert;
|
|
return True;
|
|
case XK_ISO_Continuous_Underline:
|
|
buf[0] = XKC_ISO_Continuous_Underline;
|
|
return True;
|
|
case XK_ISO_Discontinuous_Underline:
|
|
buf[0] = XKC_ISO_Discontinuous_Underline;
|
|
return True;
|
|
case XK_ISO_Emphasize:
|
|
buf[0] = XKC_ISO_Emphasize;
|
|
return True;
|
|
case XK_Multi_key:
|
|
buf[0] = XKC_ISO_Compose;
|
|
return True;
|
|
case XK_ISO_Center_Object:
|
|
buf[0] = XKC_ISO_Center_Object;
|
|
return True;
|
|
case XK_Delete:
|
|
buf[0] = XKC_ISO_Delete;
|
|
return True;
|
|
case XK_Clear:
|
|
buf[0] = XKC_ISO_Clear_Screen;
|
|
return True;
|
|
case XK_Scroll_Lock:
|
|
buf[0] = XKC_ISO_Scroll_Lock;
|
|
return True;
|
|
case XK_Help:
|
|
buf[0] = XKC_ISO_Help;
|
|
return True;
|
|
case XK_Print:
|
|
buf[0] = XKC_ISO_Print_Screen;
|
|
return True;
|
|
case XK_ISO_Enter:
|
|
buf[0] = XKC_ISO_Enter;
|
|
return True;
|
|
case XK_Alt_L:
|
|
case XK_Alt_R:
|
|
buf[0] = XKC_ISO_Alt;
|
|
return True;
|
|
case XK_Control_L:
|
|
case XK_Control_R:
|
|
buf[0] = XKC_ISO_Control;
|
|
return True;
|
|
case XK_Pause:
|
|
buf[0] = XKC_ISO_Pause;
|
|
return True;
|
|
case XK_Break:
|
|
buf[0] = XKC_ISO_Break;
|
|
return True;
|
|
case XK_Escape:
|
|
buf[0] = XKC_ISO_Escape;
|
|
return True;
|
|
case XK_Undo:
|
|
buf[0] = XKC_ISO_Undo;
|
|
return True;
|
|
case XK_ISO_Fast_Cursor_Up:
|
|
buf[0] = XKC_ISO_Fast_Cursor_Up;
|
|
return True;
|
|
case XK_ISO_Fast_Cursor_Down:
|
|
buf[0] = XKC_ISO_Fast_Cursor_Down;
|
|
return True;
|
|
case XK_ISO_Fast_Cursor_Left:
|
|
buf[0] = XKC_ISO_Fast_Cursor_Left;
|
|
return True;
|
|
case XK_ISO_Fast_Cursor_Right:
|
|
buf[0] = XKC_ISO_Fast_Cursor_Right;
|
|
return True;
|
|
case XK_Home:
|
|
buf[0] = XKC_ISO_Home;
|
|
return True;
|
|
case XK_End:
|
|
buf[0] = XKC_ISO_End;
|
|
return True;
|
|
case XK_Page_Up:
|
|
buf[0] = XKC_ISO_Page_Up;
|
|
return True;
|
|
case XK_Page_Down:
|
|
buf[0] = XKC_ISO_Page_Down;
|
|
return True;
|
|
case XK_ISO_Move_Line_Up:
|
|
buf[0] = XKC_ISO_Move_Line_Up;
|
|
return True;
|
|
case XK_ISO_Move_Line_Down:
|
|
buf[0] = XKC_ISO_Move_Line_Down;
|
|
return True;
|
|
case XK_ISO_Partial_Line_Up:
|
|
buf[0] = XKC_ISO_Partial_Line_Up;
|
|
return True;
|
|
case XK_ISO_Partial_Line_Down:
|
|
buf[0] = XKC_ISO_Partial_Line_Down;
|
|
return True;
|
|
case XK_ISO_Partial_Space_Left:
|
|
buf[0] = XKC_ISO_Partial_Space_Left;
|
|
return True;
|
|
case XK_ISO_Partial_Space_Right:
|
|
buf[0] = XKC_ISO_Partial_Space_Right;
|
|
return True;
|
|
case XK_ISO_Set_Margin_Left:
|
|
buf[0] = XKC_ISO_Set_Margin_Left;
|
|
return True;
|
|
case XK_ISO_Set_Margin_Right:
|
|
buf[0] = XKC_ISO_Set_Margin_Right;
|
|
return True;
|
|
case XK_ISO_Release_Margin_Left:
|
|
buf[0] = XKC_ISO_Release_Margin_Left;
|
|
return True;
|
|
case XK_ISO_Release_Margin_Right:
|
|
buf[0] = XKC_ISO_Release_Margin_Right;
|
|
return True;
|
|
case XK_ISO_Release_Both_Margins:
|
|
buf[0] = XKC_ISO_Release_Both_Margins;
|
|
return True;
|
|
case XK_ISO_Prev_Group:
|
|
buf[0] = XKC_ISO_Prev_Group;
|
|
return True;
|
|
case XK_ISO_Prev_Group_Lock:
|
|
buf[0] = XKC_ISO_Prev_Group_Lock;
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
static Bool
|
|
PSNonLatin1Symbol(KeySym sym, unsigned char *buf,
|
|
int *font_rtrn, int *sz_rtrn, PSState *state)
|
|
{
|
|
if (state->args->wantSymbols == NO_SYMBOLS)
|
|
return False;
|
|
|
|
if (font_rtrn != NULL)
|
|
*font_rtrn = FONT_TEXT;
|
|
if (sz_rtrn != NULL)
|
|
*sz_rtrn = SZ_LARGE;
|
|
buf[1] = '\0';
|
|
switch (sym) {
|
|
case XK_breve:
|
|
buf[0] = 0xC6;
|
|
return True;
|
|
case XK_abovedot:
|
|
buf[0] = 0xC7;
|
|
return True;
|
|
case XK_doubleacute:
|
|
buf[0] = 0xCD;
|
|
return True;
|
|
case XK_ogonek:
|
|
buf[0] = 0xCE;
|
|
return True;
|
|
case XK_caron:
|
|
buf[0] = 0xCF;
|
|
return True;
|
|
case XK_Lstroke:
|
|
buf[0] = 0xE8;
|
|
return True;
|
|
case XK_idotless:
|
|
buf[0] = 0xF5;
|
|
return True;
|
|
case XK_lstroke:
|
|
buf[0] = 0xF8;
|
|
return True;
|
|
}
|
|
if (font_rtrn != NULL)
|
|
*font_rtrn = FONT_SYMBOL;
|
|
if (sz_rtrn != NULL)
|
|
*sz_rtrn = SZ_MEDIUM;
|
|
if ((sym & (~0xffUL)) == 0x700) {
|
|
switch (sym) {
|
|
/* Greek symbol */
|
|
case XK_Greek_ALPHA:
|
|
buf[0] = 0x41;
|
|
return True;
|
|
case XK_Greek_BETA:
|
|
buf[0] = 0x42;
|
|
return True;
|
|
case XK_Greek_CHI:
|
|
buf[0] = 0x43;
|
|
return True;
|
|
case XK_Greek_DELTA:
|
|
buf[0] = 0x44;
|
|
return True;
|
|
case XK_Greek_EPSILON:
|
|
buf[0] = 0x45;
|
|
return True;
|
|
case XK_Greek_PHI:
|
|
buf[0] = 0x46;
|
|
return True;
|
|
case XK_Greek_GAMMA:
|
|
buf[0] = 0x47;
|
|
return True;
|
|
case XK_Greek_ETA:
|
|
buf[0] = 0x48;
|
|
return True;
|
|
case XK_Greek_IOTA:
|
|
buf[0] = 0x49;
|
|
return True;
|
|
case XK_Greek_KAPPA:
|
|
buf[0] = 0x4B;
|
|
return True;
|
|
case XK_Greek_LAMDA:
|
|
buf[0] = 0x4C;
|
|
return True;
|
|
case XK_Greek_MU:
|
|
buf[0] = 0x4D;
|
|
return True;
|
|
case XK_Greek_NU:
|
|
buf[0] = 0x4E;
|
|
return True;
|
|
case XK_Greek_OMICRON:
|
|
buf[0] = 0x4F;
|
|
return True;
|
|
case XK_Greek_PI:
|
|
buf[0] = 0x50;
|
|
return True;
|
|
case XK_Greek_THETA:
|
|
buf[0] = 0x51;
|
|
return True;
|
|
case XK_Greek_RHO:
|
|
buf[0] = 0x52;
|
|
return True;
|
|
case XK_Greek_SIGMA:
|
|
buf[0] = 0x53;
|
|
return True;
|
|
case XK_Greek_TAU:
|
|
buf[0] = 0x54;
|
|
return True;
|
|
case XK_Greek_UPSILON:
|
|
buf[0] = 0x55;
|
|
return True;
|
|
case XK_Greek_OMEGA:
|
|
buf[0] = 0x57;
|
|
return True;
|
|
case XK_Greek_XI:
|
|
buf[0] = 0x58;
|
|
return True;
|
|
case XK_Greek_PSI:
|
|
buf[0] = 0x59;
|
|
return True;
|
|
case XK_Greek_ZETA:
|
|
buf[0] = 0x5A;
|
|
return True;
|
|
|
|
case XK_Greek_alpha:
|
|
buf[0] = 0x61;
|
|
return True;
|
|
case XK_Greek_beta:
|
|
buf[0] = 0x62;
|
|
return True;
|
|
case XK_Greek_chi:
|
|
buf[0] = 0x63;
|
|
return True;
|
|
case XK_Greek_delta:
|
|
buf[0] = 0x64;
|
|
return True;
|
|
case XK_Greek_epsilon:
|
|
buf[0] = 0x65;
|
|
return True;
|
|
case XK_Greek_phi:
|
|
buf[0] = 0x66;
|
|
return True;
|
|
case XK_Greek_gamma:
|
|
buf[0] = 0x67;
|
|
return True;
|
|
case XK_Greek_eta:
|
|
buf[0] = 0x68;
|
|
return True;
|
|
case XK_Greek_iota:
|
|
buf[0] = 0x69;
|
|
return True;
|
|
case XK_Greek_kappa:
|
|
buf[0] = 0x6B;
|
|
return True;
|
|
case XK_Greek_lamda:
|
|
buf[0] = 0x6C;
|
|
return True;
|
|
case XK_Greek_mu:
|
|
buf[0] = 0x6D;
|
|
return True;
|
|
case XK_Greek_nu:
|
|
buf[0] = 0x6E;
|
|
return True;
|
|
case XK_Greek_omicron:
|
|
buf[0] = 0x6F;
|
|
return True;
|
|
case XK_Greek_pi:
|
|
buf[0] = 0x70;
|
|
return True;
|
|
case XK_Greek_theta:
|
|
buf[0] = 0x71;
|
|
return True;
|
|
case XK_Greek_rho:
|
|
buf[0] = 0x72;
|
|
return True;
|
|
case XK_Greek_sigma:
|
|
buf[0] = 0x73;
|
|
return True;
|
|
case XK_Greek_tau:
|
|
buf[0] = 0x74;
|
|
return True;
|
|
case XK_Greek_upsilon:
|
|
buf[0] = 0x75;
|
|
return True;
|
|
case XK_Greek_omega:
|
|
buf[0] = 0x77;
|
|
return True;
|
|
case XK_Greek_xi:
|
|
buf[0] = 0x78;
|
|
return True;
|
|
case XK_Greek_psi:
|
|
buf[0] = 0x79;
|
|
return True;
|
|
case XK_Greek_zeta:
|
|
buf[0] = 0x7A;
|
|
return True;
|
|
}
|
|
}
|
|
switch (sym) {
|
|
case XK_leftarrow:
|
|
buf[0] = 0xAC;
|
|
return True;
|
|
case XK_uparrow:
|
|
buf[0] = 0xAD;
|
|
return True;
|
|
case XK_rightarrow:
|
|
buf[0] = 0xAE;
|
|
return True;
|
|
case XK_downarrow:
|
|
buf[0] = 0xAF;
|
|
return True;
|
|
case XK_horizconnector:
|
|
buf[0] = 0xBE;
|
|
return True;
|
|
case XK_trademark:
|
|
buf[0] = 0xE4;
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
static KeySym
|
|
CheckSymbolAlias(KeySym sym, PSState *state)
|
|
{
|
|
if (XkbKSIsKeypad(sym)) {
|
|
if ((sym >= XK_KP_0) && (sym <= XK_KP_9))
|
|
sym = (sym - XK_KP_0) + XK_0;
|
|
else
|
|
switch (sym) {
|
|
case XK_KP_Space:
|
|
return XK_space;
|
|
case XK_KP_Tab:
|
|
return XK_Tab;
|
|
case XK_KP_Enter:
|
|
return XK_Return;
|
|
case XK_KP_F1:
|
|
return XK_F1;
|
|
case XK_KP_F2:
|
|
return XK_F2;
|
|
case XK_KP_F3:
|
|
return XK_F3;
|
|
case XK_KP_F4:
|
|
return XK_F4;
|
|
case XK_KP_Home:
|
|
return XK_Home;
|
|
case XK_KP_Left:
|
|
return XK_Left;
|
|
case XK_KP_Up:
|
|
return XK_Up;
|
|
case XK_KP_Right:
|
|
return XK_Right;
|
|
case XK_KP_Down:
|
|
return XK_Down;
|
|
case XK_KP_Page_Up:
|
|
return XK_Page_Up;
|
|
case XK_KP_Page_Down:
|
|
return XK_Page_Down;
|
|
case XK_KP_End:
|
|
return XK_End;
|
|
case XK_KP_Begin:
|
|
return XK_Begin;
|
|
case XK_KP_Insert:
|
|
return XK_Insert;
|
|
case XK_KP_Delete:
|
|
return XK_Delete;
|
|
case XK_KP_Equal:
|
|
return XK_equal;
|
|
case XK_KP_Multiply:
|
|
return XK_asterisk;
|
|
case XK_KP_Add:
|
|
return XK_plus;
|
|
case XK_KP_Subtract:
|
|
return XK_minus;
|
|
case XK_KP_Divide:
|
|
return XK_slash;
|
|
}
|
|
}
|
|
else if (XkbKSIsDeadKey(sym)) {
|
|
switch (sym) {
|
|
case XK_dead_grave:
|
|
sym = XK_grave;
|
|
break;
|
|
case XK_dead_acute:
|
|
sym = XK_acute;
|
|
break;
|
|
case XK_dead_circumflex:
|
|
sym = XK_asciicircum;
|
|
break;
|
|
case XK_dead_tilde:
|
|
sym = XK_asciitilde;
|
|
break;
|
|
case XK_dead_macron:
|
|
sym = XK_macron;
|
|
break;
|
|
case XK_dead_breve:
|
|
sym = XK_breve;
|
|
break;
|
|
case XK_dead_abovedot:
|
|
sym = XK_abovedot;
|
|
break;
|
|
case XK_dead_diaeresis:
|
|
sym = XK_diaeresis;
|
|
break;
|
|
case XK_dead_abovering:
|
|
sym = XK_degree;
|
|
break;
|
|
case XK_dead_doubleacute:
|
|
sym = XK_doubleacute;
|
|
break;
|
|
case XK_dead_caron:
|
|
sym = XK_caron;
|
|
break;
|
|
case XK_dead_cedilla:
|
|
sym = XK_cedilla;
|
|
break;
|
|
case XK_dead_ogonek:
|
|
sym = XK_ogonek;
|
|
break;
|
|
case XK_dead_iota:
|
|
sym = XK_Greek_iota;
|
|
break;
|
|
case XK_dead_voiced_sound:
|
|
sym = XK_voicedsound;
|
|
break;
|
|
case XK_dead_semivoiced_sound:
|
|
sym = XK_semivoicedsound;
|
|
break;
|
|
}
|
|
}
|
|
return sym;
|
|
}
|
|
|
|
static Bool
|
|
FindKeysymsByName(XkbDescPtr xkb, char *name, PSState *state, KeyTop *top)
|
|
{
|
|
static unsigned char buf[30];
|
|
int kc;
|
|
KeySym sym, *syms, topSyms[NLABELS];
|
|
int level, group;
|
|
int eG, nG, gI, l, g;
|
|
|
|
bzero(top, sizeof(KeyTop));
|
|
kc = XkbFindKeycodeByName(xkb, name, True);
|
|
if (state->args != NULL) {
|
|
level = state->args->labelLevel;
|
|
group = state->args->baseLabelGroup;
|
|
}
|
|
else
|
|
level = group = 0;
|
|
syms = XkbKeySymsPtr(xkb, kc);
|
|
eG = group;
|
|
nG = XkbKeyNumGroups(xkb, kc);
|
|
gI = XkbKeyGroupInfo(xkb, kc);
|
|
if ((state->args->wantDiffs) && (eG >= XkbKeyNumGroups(xkb, kc)))
|
|
return False; /* XXX was a return with no value */
|
|
if (nG == 0) {
|
|
return False;
|
|
}
|
|
else if (nG == 1) {
|
|
eG = 0;
|
|
}
|
|
else if (eG >= XkbKeyNumGroups(xkb, kc)) {
|
|
switch (XkbOutOfRangeGroupAction(gI)) {
|
|
default:
|
|
eG %= nG;
|
|
break;
|
|
case XkbClampIntoRange:
|
|
eG = nG - 1;
|
|
break;
|
|
case XkbRedirectIntoRange:
|
|
eG = XkbOutOfRangeGroupNumber(gI);
|
|
if (eG >= nG)
|
|
eG = 0;
|
|
break;
|
|
}
|
|
}
|
|
for (g = 0; g < state->args->nLabelGroups; g++) {
|
|
if ((eG + g) >= nG)
|
|
continue;
|
|
for (l = 0; l < 2; l++) {
|
|
int font, sz;
|
|
|
|
if (level + l >= XkbKeyGroupWidth(xkb, kc, (eG + g)))
|
|
continue;
|
|
sym = syms[((eG + g) * XkbKeyGroupsWidth(xkb, kc)) + (level + l)];
|
|
|
|
if (state->args->wantSymbols != NO_SYMBOLS)
|
|
sym = CheckSymbolAlias(sym, state);
|
|
topSyms[(g * 2) + l] = sym;
|
|
|
|
if (PSKeycapsSymbol(sym, buf, &font, &sz, state)) {
|
|
top->font[(g * 2) + l] = font;
|
|
top->size[(g * 2) + l] = sz;
|
|
}
|
|
else if (((sym & (~0xffUL)) == 0) && isprint(sym) && (!isspace(sym))) {
|
|
if (sym == '(')
|
|
snprintf((char *) buf, sizeof(buf), "\\(");
|
|
else if (sym == ')')
|
|
snprintf((char *) buf, sizeof(buf), "\\)");
|
|
else if (sym == '\\')
|
|
snprintf((char *) buf, sizeof(buf), "\\\\");
|
|
else
|
|
snprintf((char *) buf, sizeof(buf), "%c", (char) sym);
|
|
top->font[(g * 2) + l] = FONT_LATIN1;
|
|
top->size[(g * 2) + l] = SZ_MEDIUM;
|
|
switch (buf[0]) {
|
|
case '.':
|
|
case ':':
|
|
case ',':
|
|
case ';':
|
|
case '\'':
|
|
case '"':
|
|
case '`':
|
|
case '~':
|
|
case '^':
|
|
case 0250:
|
|
case 0270:
|
|
case 0267:
|
|
case 0260:
|
|
case 0252:
|
|
case 0272:
|
|
case 0271:
|
|
case 0262:
|
|
case 0263:
|
|
case 0264:
|
|
case 0255:
|
|
case 0254:
|
|
case 0257:
|
|
top->size[(g * 2) + l] = SZ_LARGE;
|
|
break;
|
|
}
|
|
}
|
|
else if (PSNonLatin1Symbol(sym, buf, &font, &sz, state)) {
|
|
top->font[(g * 2) + l] = font;
|
|
top->size[(g * 2) + l] = sz;
|
|
}
|
|
else {
|
|
char *tmp;
|
|
|
|
tmp = XKeysymToString(sym);
|
|
if (tmp != NULL)
|
|
strcpy((char *) buf, tmp);
|
|
else
|
|
snprintf((char *) buf, sizeof(buf), "(%ld)", sym);
|
|
top->font[(g * 2) + l] = FONT_LATIN1;
|
|
if (strlen((char *) buf) < 9)
|
|
top->size[(g * 2) + l] = SZ_SMALL;
|
|
else
|
|
top->size[(g * 2) + l] = SZ_TINY;
|
|
}
|
|
top->present |= (1 << ((g * 2) + l));
|
|
strncpy(top->label[(g * 2) + l], (char *) buf, LABEL_LEN - 1);
|
|
top->label[(g * 2) + l][LABEL_LEN - 1] = '\0';
|
|
}
|
|
if (((g == 0) && (top->present & G1LX_MASK) == G1LX_MASK) ||
|
|
((g == 1) && (top->present & G2LX_MASK) == G2LX_MASK)) {
|
|
KeySym lower, upper;
|
|
|
|
XConvertCase(topSyms[(g * 2)], &lower, &upper);
|
|
if ((topSyms[(g * 2)] == lower) && (topSyms[(g * 2) + 1] == upper)) {
|
|
top->alpha[g] = True;
|
|
}
|
|
}
|
|
}
|
|
return True;
|
|
}
|
|
|
|
static void
|
|
PSDrawLabel(FILE *out, const char *label, int x, int y, int w, int h)
|
|
{
|
|
fprintf(out, "%d %d (%s) centeroffset\n", w, h, label);
|
|
fprintf(out, "%d add exch\n", y);
|
|
fprintf(out, "%d add exch moveto\n", x);
|
|
fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", label);
|
|
return;
|
|
}
|
|
|
|
#define TOP_ROW 0
|
|
#define BOTTOM_ROW 1
|
|
#define CENTER_ROW 2
|
|
|
|
#define LEFT_COL 0
|
|
#define RIGHT_COL 1
|
|
#define CENTER_COL 2
|
|
|
|
static void
|
|
PSLabelKey(FILE *out, PSState *state, KeyTop *top, int x, int y,
|
|
XkbBoundsPtr bounds, int kc, int btm)
|
|
{
|
|
int w, h, i;
|
|
int row_y[3];
|
|
int col_x[3];
|
|
int row_h[3];
|
|
int col_w[3];
|
|
Bool present[NLABELS];
|
|
int sym_row[NLABELS];
|
|
int sym_col[NLABELS];
|
|
|
|
w = XkbBoundsWidth(bounds);
|
|
h = XkbBoundsHeight(bounds);
|
|
row_y[TOP_ROW] = y + bounds->y1 + (h / 10);
|
|
row_y[BOTTOM_ROW] = y + bounds->y1 + (h / 2) + (h / 10);
|
|
row_y[CENTER_ROW] = y + bounds->y1 + (h / 10);
|
|
row_h[TOP_ROW] = h / 2;
|
|
row_h[BOTTOM_ROW] = h / 2;
|
|
row_h[CENTER_ROW] = h;
|
|
|
|
col_x[LEFT_COL] = x + bounds->x1;
|
|
col_x[RIGHT_COL] = x + bounds->x1 + w / 2;
|
|
col_x[CENTER_COL] = x + bounds->x1;
|
|
col_w[LEFT_COL] = w / 2;
|
|
col_w[RIGHT_COL] = w / 2;
|
|
col_w[CENTER_COL] = w;
|
|
|
|
present[G1L1] = False;
|
|
sym_row[G1L1] = BOTTOM_ROW;
|
|
sym_col[G1L1] = LEFT_COL;
|
|
|
|
present[G1L2] = False;
|
|
sym_row[G1L2] = TOP_ROW;
|
|
sym_col[G1L2] = LEFT_COL;
|
|
|
|
present[G2L1] = False;
|
|
sym_row[G2L1] = BOTTOM_ROW;
|
|
sym_col[G2L1] = RIGHT_COL;
|
|
|
|
present[G2L2] = False;
|
|
sym_row[G2L2] = TOP_ROW;
|
|
sym_col[G2L2] = RIGHT_COL;
|
|
|
|
present[CENTER] = False;
|
|
sym_row[CENTER] = CENTER_ROW;
|
|
sym_col[CENTER] = CENTER_COL;
|
|
|
|
if (top->present & CENTER_MASK) {
|
|
present[CENTER] = True;
|
|
}
|
|
else
|
|
switch (top->present & GXLX_MASK) {
|
|
case G1L1_MASK:
|
|
present[G1L1] = True;
|
|
sym_row[G1L1] = CENTER_ROW;
|
|
sym_col[G1L1] = CENTER_COL;
|
|
break;
|
|
case G1LX_MASK:
|
|
present[G1L2] = True;
|
|
if (!top->alpha[0]) {
|
|
present[G1L1] = True;
|
|
if ((strlen(top->label[G1L1]) > 1) &&
|
|
(top->label[G1L1][0] != '\\'))
|
|
sym_col[G1L1] = CENTER_COL;
|
|
if ((strlen(top->label[G1L2]) > 1) &&
|
|
(top->label[G1L1][0] != '\\'))
|
|
sym_col[G1L2] = CENTER_COL;
|
|
}
|
|
break;
|
|
default:
|
|
if ((top->present & G1LX_MASK) == G1LX_MASK) {
|
|
present[G1L2] = True;
|
|
if (!top->alpha[0])
|
|
present[G1L1] = True;
|
|
}
|
|
else if ((top->present & G1LX_MASK) == G1L1_MASK) {
|
|
present[G1L1] = True;
|
|
}
|
|
else if ((top->present & G1LX_MASK) == G1L2_MASK) {
|
|
present[G1L2] = True;
|
|
}
|
|
if ((top->present & G2LX_MASK) == G2LX_MASK) {
|
|
present[G2L2] = True;
|
|
if (!top->alpha[1])
|
|
present[G2L1] = True;
|
|
}
|
|
else if ((top->present & G2LX_MASK) == G2L1_MASK) {
|
|
present[G2L1] = True;
|
|
}
|
|
else if ((top->present & G2LX_MASK) == G2L2_MASK) {
|
|
present[G2L2] = True;
|
|
}
|
|
break;
|
|
case 0:
|
|
return;
|
|
}
|
|
for (i = 0; i < NLABELS; i++) {
|
|
if (present[i]) {
|
|
int size;
|
|
|
|
if (top->size[i] == SZ_AUTO) {
|
|
size_t len = strlen(top->label[i]);
|
|
if (len == 1) {
|
|
if (top->font[i] == FONT_ISOCAPS)
|
|
size = 18;
|
|
else
|
|
size = 14;
|
|
}
|
|
else if (len < 10)
|
|
size = 12;
|
|
else
|
|
size = 10;
|
|
}
|
|
else if (top->size[i] == SZ_TINY)
|
|
size = 10;
|
|
else if (top->size[i] == SZ_SMALL)
|
|
size = 12;
|
|
else if (top->size[i] == SZ_LARGE)
|
|
size = 18;
|
|
else if (top->size[i] == SZ_XLARGE)
|
|
size = 24;
|
|
else
|
|
size = 14;
|
|
PSSetFont(out, state, top->font[i], size, True);
|
|
PSDrawLabel(out, top->label[i], col_x[sym_col[i]],
|
|
row_y[sym_row[i]], col_w[sym_col[i]],
|
|
row_h[sym_row[i]]);
|
|
}
|
|
}
|
|
if (state->args->wantKeycodes) {
|
|
char keycode[10];
|
|
|
|
snprintf(keycode, sizeof(keycode), "%d", kc);
|
|
PSSetFont(out, state, FONT_LATIN1, 8, True);
|
|
PSDrawLabel(out, keycode, x + bounds->x1, y + btm - 5, w, 0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void
|
|
PSSection(FILE *out, PSState *state, XkbSectionPtr section)
|
|
{
|
|
int r, offset;
|
|
XkbRowPtr row;
|
|
Display *dpy;
|
|
XkbDescPtr xkb;
|
|
|
|
xkb = state->xkb;
|
|
dpy = xkb->dpy;
|
|
fprintf(out, "%% Begin Section '%s'\n", (section->name != None ?
|
|
XkbAtomGetString(dpy, section-> name) : "NoName"));
|
|
PSGSave(out, state);
|
|
fprintf(out, "%d %d translate\n", section->left, section->top);
|
|
if (section->angle != 0)
|
|
fprintf(out, "%s rotate\n", XkbGeomFPText(section->angle, XkbMessage));
|
|
if (section->doodads) {
|
|
XkbDrawablePtr first, draw;
|
|
|
|
first = draw = XkbGetOrderedDrawables(NULL, section);
|
|
while (draw) {
|
|
if (draw->type == XkbDW_Section)
|
|
PSSection(out, state, draw->u.section);
|
|
else
|
|
PSDoodad(out, state, draw->u.doodad);
|
|
draw = draw->next;
|
|
}
|
|
XkbFreeOrderedDrawables(first);
|
|
}
|
|
for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
|
|
int k;
|
|
XkbKeyPtr key;
|
|
XkbShapePtr shape;
|
|
|
|
if (row->vertical)
|
|
offset = row->top;
|
|
else
|
|
offset = row->left;
|
|
fprintf(out, "%% Begin %s %d\n", row->vertical ? "column" : "row",
|
|
r + 1);
|
|
for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
|
|
shape = XkbKeyShape(xkb->geom, key);
|
|
offset += key->gap;
|
|
if (row->vertical) {
|
|
if (state->args->wantColor) {
|
|
if (key->color_ndx != state->white) {
|
|
PSSetColor(out, state, key->color_ndx);
|
|
fprintf(out, "true 0 %d %d %s %% %s\n",
|
|
row->left, offset,
|
|
XkbAtomGetString(dpy, shape->name),
|
|
XkbKeyNameText(key->name.name, XkbMessage));
|
|
}
|
|
PSSetColor(out, state, state->black);
|
|
}
|
|
fprintf(out, "false 0 %d %d %s %% %s\n", row->left, offset,
|
|
XkbAtomGetString(dpy, shape->name),
|
|
XkbKeyNameText(key->name.name, XkbMessage));
|
|
offset += shape->bounds.y2;
|
|
}
|
|
else {
|
|
if (state->args->wantColor) {
|
|
if (key->color_ndx != state->white) {
|
|
PSSetColor(out, state, key->color_ndx);
|
|
fprintf(out, "true 0 %d %d %s %% %s\n", offset,
|
|
row->top, XkbAtomGetString(dpy, shape->name),
|
|
XkbKeyNameText(key->name.name, XkbMessage));
|
|
}
|
|
PSSetColor(out, state, state->black);
|
|
}
|
|
fprintf(out, "false 0 %d %d %s %% %s\n", offset, row->top,
|
|
XkbAtomGetString(dpy, shape->name),
|
|
XkbKeyNameText(key->name.name, XkbMessage));
|
|
offset += shape->bounds.x2;
|
|
}
|
|
}
|
|
}
|
|
for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
|
|
int k, kc = 0;
|
|
XkbKeyPtr key;
|
|
XkbShapePtr shape;
|
|
XkbBoundsRec bounds;
|
|
|
|
if (state->args->label == LABEL_NONE)
|
|
break;
|
|
if (row->vertical)
|
|
offset = row->top;
|
|
else
|
|
offset = row->left;
|
|
fprintf(out, "%% Begin %s %d labels\n",
|
|
row->vertical ? "column" : "row", r + 1);
|
|
PSSetColor(out, state, xkb->geom->label_color->pixel);
|
|
PSSetFont(out, state, FONT_LATIN1, 12, True);
|
|
for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
|
|
char *name, *name2, buf[30], buf2[30];
|
|
int x, y;
|
|
KeyTop top;
|
|
|
|
shape = XkbKeyShape(xkb->geom, key);
|
|
XkbComputeShapeTop(shape, &bounds);
|
|
offset += key->gap;
|
|
name = name2 = NULL;
|
|
if (state->args->label == LABEL_SYMBOLS) {
|
|
if (!FindKeysymsByName(xkb, key->name.name, state, &top)) {
|
|
fprintf(out, "%% No label for %s\n",
|
|
XkbKeyNameText(key->name.name, XkbMessage));
|
|
}
|
|
}
|
|
else {
|
|
char *olKey;
|
|
|
|
if (section->num_overlays > 0)
|
|
olKey = XkbFindOverlayForKey(xkb->geom, section,
|
|
key->name.name);
|
|
else
|
|
olKey = NULL;
|
|
|
|
if (state->args->label == LABEL_KEYNAME) {
|
|
name = XkbKeyNameText(key->name.name, XkbMessage);
|
|
if (olKey)
|
|
name2 = XkbKeyNameText(olKey, XkbMessage);
|
|
}
|
|
else if (state->args->label == LABEL_KEYCODE) {
|
|
name = buf;
|
|
snprintf(name, sizeof(buf), "%d",
|
|
XkbFindKeycodeByName(xkb, key->name.name, True));
|
|
if (olKey) {
|
|
name2 = buf2;
|
|
snprintf(name2, sizeof(buf2), "%d",
|
|
XkbFindKeycodeByName(xkb, olKey, True));
|
|
}
|
|
}
|
|
bzero(&top, sizeof(KeyTop));
|
|
if (name2 != NULL) {
|
|
top.present |= G1LX_MASK;
|
|
strncpy(top.label[G1L1], name, LABEL_LEN - 1);
|
|
top.label[G1L1][LABEL_LEN - 1] = '\0';
|
|
strncpy(top.label[G1L2], name2, LABEL_LEN - 1);
|
|
top.label[G1L2][LABEL_LEN - 1] = '\0';
|
|
}
|
|
else if (name != NULL) {
|
|
top.present |= CENTER_MASK;
|
|
strncpy(top.label[CENTER], name, LABEL_LEN - 1);
|
|
top.label[CENTER][LABEL_LEN - 1] = '\0';
|
|
}
|
|
else {
|
|
fprintf(out, "%% No label for %s\n",
|
|
XkbKeyNameText(key->name.name, XkbMessage));
|
|
}
|
|
}
|
|
if (row->vertical) {
|
|
x = row->left;
|
|
y = offset;
|
|
offset += shape->bounds.y2;
|
|
}
|
|
else {
|
|
x = offset;
|
|
y = row->top;
|
|
offset += shape->bounds.x2;
|
|
}
|
|
name = key->name.name;
|
|
fprintf(out, "%% %s\n", XkbKeyNameText(name, XkbMessage));
|
|
if (state->args->wantKeycodes)
|
|
kc = XkbFindKeycodeByName(xkb, key->name.name, True);
|
|
PSLabelKey(out, state, &top, x, y, &bounds, kc, shape->bounds.y2);
|
|
}
|
|
}
|
|
PSGRestore(out, state);
|
|
return;
|
|
}
|
|
|
|
Bool
|
|
GeometryToPostScript(FILE *out, XkbFileInfo *pResult, XKBPrintArgs *args)
|
|
{
|
|
XkbDrawablePtr first, draw;
|
|
PSState state;
|
|
Bool dfltBorder;
|
|
int i;
|
|
|
|
if ((!pResult) || (!pResult->xkb) || (!pResult->xkb->geom))
|
|
return False;
|
|
state.xkb = pResult->xkb;
|
|
state.dpy = pResult->xkb->dpy;
|
|
state.geom = pResult->xkb->geom;
|
|
state.color = state.black = state.white = -1;
|
|
state.font = -1;
|
|
state.nPages = 0;
|
|
state.totalKB = 1;
|
|
state.kbPerPage = 1;
|
|
state.x1 = state.y1 = state.x2 = state.y2 = 0;
|
|
state.args = args;
|
|
|
|
if ((args->label == LABEL_SYMBOLS) && (pResult->xkb->ctrls)) {
|
|
if (args->nTotalGroups == 0)
|
|
state.totalKB =
|
|
pResult->xkb->ctrls->num_groups / args->nLabelGroups;
|
|
else
|
|
state.totalKB = args->nTotalGroups;
|
|
if (state.totalKB < 1)
|
|
state.totalKB = 1;
|
|
else if (state.totalKB > 1)
|
|
state.kbPerPage = 2;
|
|
}
|
|
if (args->nKBPerPage != 0)
|
|
state.kbPerPage = args->nKBPerPage;
|
|
|
|
PSProlog(out, &state);
|
|
first = XkbGetOrderedDrawables(state.geom, NULL);
|
|
|
|
for (draw = first, dfltBorder = True; draw != NULL; draw = draw->next) {
|
|
if ((draw->type != XkbDW_Section) &&
|
|
((draw->u.doodad->any.type == XkbOutlineDoodad) ||
|
|
(draw->u.doodad->any.type == XkbSolidDoodad))) {
|
|
char *name;
|
|
|
|
name = XkbAtomGetString(state.dpy, draw->u.doodad->any.name);
|
|
if ((name != NULL) && (uStrCaseEqual(name, "edges"))) {
|
|
dfltBorder = False;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < state.totalKB; i++) {
|
|
PSPageSetup(out, &state, dfltBorder);
|
|
for (draw = first; draw != NULL; draw = draw->next) {
|
|
if (draw->type == XkbDW_Section)
|
|
PSSection(out, &state, draw->u.section);
|
|
else {
|
|
PSDoodad(out, &state, draw->u.doodad);
|
|
}
|
|
}
|
|
PSPageTrailer(out, &state);
|
|
state.args->baseLabelGroup += state.args->nLabelGroups;
|
|
}
|
|
XkbFreeOrderedDrawables(first);
|
|
PSFileTrailer(out, &state);
|
|
return True;
|
|
}
|