psgeom.c revision e6bced22
1/************************************************************ 2 Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 3 4 Permission to use, copy, modify, and distribute this 5 software and its documentation for any purpose and without 6 fee is hereby granted, provided that the above copyright 7 notice appear in all copies and that both that copyright 8 notice and this permission notice appear in supporting 9 documentation, and that the name of Silicon Graphics not be 10 used in advertising or publicity pertaining to distribution 11 of the software without specific prior written permission. 12 Silicon Graphics makes no representation about the suitability 13 of this software for any purpose. It is provided "as is" 14 without any express or implied warranty. 15 16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25 ********************************************************/ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#define XK_TECHNICAL 32#define XK_PUBLISHING 33#define XK_KATAKANA 34#include <stdio.h> 35#include <ctype.h> 36#include <X11/X.h> 37#include <X11/Xlib.h> 38#include <X11/XKBlib.h> 39#include <X11/extensions/XKBgeom.h> 40#include <X11/extensions/XKM.h> 41#include <X11/extensions/XKBfile.h> 42#include <X11/keysym.h> 43#include <X11/Xutil.h> 44 45#if defined(sgi) 46#include <malloc.h> 47#endif 48 49#include <stdlib.h> 50 51#include "utils.h" 52#include "xkbprint.h" 53#include "isokeys.h" 54 55#define FONT_NONE -1 56#define FONT_TEXT 0 57#define FONT_LATIN1 1 58#define FONT_SYMBOL 2 59#define FONT_ISOCAPS 3 60#define FONT_MOUSECAPS 4 61 62typedef struct { 63 Display * dpy; 64 XkbDescPtr xkb; 65 XkbGeometryPtr geom; 66 int totalKB; 67 int kbPerPage; 68 int black; 69 int white; 70 int color; 71 int font; 72 int fontSize; 73 int nPages; 74 int x1, y1; 75 int x2, y2; 76 XKBPrintArgs * args; 77} PSState; 78 79#define G1L1 0 80#define G1L2 1 81#define G2L1 2 82#define G2L2 3 83#define CENTER 4 84 85#define G1L1_MASK (1<<G1L1) 86#define G1L2_MASK (1<<G1L2) 87#define G2L1_MASK (1<<G2L1) 88#define G2L2_MASK (1<<G2L2) 89#define CENTER_MASK (1<<CENTER) 90 91#define LABEL_MASK (0x1f) 92#define GXL1_MASK (G1L1_MASK|G2L1_MASK) 93#define GXL2_MASK (G1L2_MASK|G2L2_MASK) 94#define G1LX_MASK (G1L1_MASK|G1L2_MASK) 95#define G2LX_MASK (G2L1_MASK|G2L2_MASK) 96#define GXLX_MASK (0x0f) 97 98#define NLABELS 5 99#define LABEL_LEN 30 100 101#define SZ_AUTO 0 102#define SZ_TINY 1 103#define SZ_SMALL 2 104#define SZ_MEDIUM 3 105#define SZ_LARGE 4 106#define SZ_XLARGE 5 107 108typedef struct { 109 unsigned present; 110 Bool alpha[2]; 111 char label[NLABELS][LABEL_LEN]; 112 int font[NLABELS]; 113 int size[NLABELS]; 114} KeyTop; 115 116#define DFLT_LABEL_FONT "Helvetica-Narrow-Bold" 117#define DFLT_LABEL_FONT_SIZE 10 118 119/***====================================================================***/ 120 121typedef struct _PSFontDef { 122 const char *name; 123 const char **def; 124} PSFontDef; 125 126static PSFontDef internalFonts[] = { 127 { "IsoKeyCaps", &IsoKeyCaps } 128}; 129static int nInternalFonts = (sizeof(internalFonts) / sizeof(PSFontDef)); 130 131static void 132ListInternalFonts(FILE *out, int first, int indent) 133{ 134 register int i, n, nThisLine; 135 136 for (n = 0; n < first; n++) { 137 putc(' ', out); 138 } 139 140 for (nThisLine = i = 0; i < nInternalFonts; i++) { 141 if (nThisLine == 4) { 142 fprintf(out, ",\n"); 143 for (n = 0; n < indent; n++) { 144 putc(' ', out); 145 } 146 nThisLine = 0; 147 } 148 if (nThisLine == 0) 149 fprintf(out, "%s", internalFonts[i].name); 150 else 151 fprintf(out, ", %s", internalFonts[i].name); 152 nThisLine++; 153 } 154 if (nThisLine != 0) 155 fprintf(out, "\n"); 156 return; 157} 158 159static Bool 160PSIncludeFont(FILE *out, const char *font) 161{ 162 const char **pstr; 163 register int i; 164 165 pstr = NULL; 166 for (i = 0; (i < nInternalFonts) && (pstr == NULL); i++) { 167 if (uStringEqual(internalFonts[i].name, font)) 168 pstr = internalFonts[i].def; 169 } 170 if (pstr != NULL) { 171 fprintf(out, "%%%%BeginFont: %s\n", font); 172 fprintf(out, "%s", *pstr); 173 fprintf(out, "%%%%EndFont\n"); 174 return True; 175 } 176 return False; 177} 178 179Bool 180DumpInternalFont(FILE *out, const char *fontName) 181{ 182 if (strcmp(fontName, "IsoKeyCaps") != 0) { 183 uError("No internal font named \"%s\"\n", fontName); 184 uAction("No font dumped\n"); 185 fprintf(stderr, "Current internal fonts are: "); 186 ListInternalFonts(stderr, 0, 8); 187 return False; 188 } 189 PSIncludeFont(out, fontName); 190 return True; 191} 192 193/***====================================================================***/ 194 195static void 196PSColorDef(FILE *out, PSState *state, XkbColorPtr color) 197{ 198 int tmp; 199 200 fprintf(out, "/C%03d ", color->pixel); 201 if (uStrCaseEqual(color->spec, "black")) { 202 state->black = color->pixel; 203 fprintf(out, "{ 0 setgray } def %% %s\n", color->spec); 204 } 205 else if (uStrCaseEqual(color->spec, "white")) { 206 state->white = color->pixel; 207 fprintf(out, "{ 1 setgray } def %% %s\n", color->spec); 208 } 209 else if ((sscanf(color->spec, "grey%d", &tmp) == 1) || 210 (sscanf(color->spec, "gray%d", &tmp) == 1) || 211 (sscanf(color->spec, "Grey%d", &tmp) == 1) || 212 (sscanf(color->spec, "Gray%d", &tmp) == 1)) { 213 fprintf(out, "{ %f setgray } def %% %s\n", 214 1.0 - (((float) tmp) / 100.0), color->spec); 215 } 216 else if ((tmp = (uStrCaseEqual(color->spec, "red") * 100)) || 217 (sscanf(color->spec, "red%d", &tmp) == 1)) { 218 fprintf(out, "{ %f 0 0 setrgbcolor } def %% %s\n", 219 (((float) tmp) / 100.0), color->spec); 220 } 221 else if ((tmp = (uStrCaseEqual(color->spec, "green") * 100)) || 222 (sscanf(color->spec, "green%d", &tmp) == 1)) { 223 fprintf(out, "{ 0 %f 0 setrgbcolor } def %% %s\n", 224 (((float) tmp) / 100.0), color->spec); 225 } 226 else if ((tmp = (uStrCaseEqual(color->spec, "blue") * 100)) || 227 (sscanf(color->spec, "blue%d", &tmp) == 1)) { 228 fprintf(out, "{ 0 0 %f setrgbcolor } def %% %s\n", 229 (((float) tmp) / 100.0), color->spec); 230 } 231 else 232 fprintf(out, "{ 0.9 setgray } def %% BOGUS! %s\n", color->spec); 233} 234 235static void 236PSSetColor(FILE *out, PSState *state, int color) 237{ 238 if ((state->args->wantColor) && (state->color != color)) { 239 fprintf(out, "C%03d %% set color\n", color); 240 state->color = color; 241 } 242 return; 243} 244 245static void 246PSGSave(FILE *out, PSState *state) 247{ 248 fprintf(out, "gsave\n"); 249 return; 250} 251 252static void 253PSGRestore(FILE *out, PSState *state) 254{ 255 fprintf(out, "grestore\n"); 256 state->color = -1; 257 state->font = FONT_NONE; 258 state->fontSize = -1; 259 return; 260} 261 262static void 263PSShapeDef(FILE *out, PSState *state, XkbShapePtr shape) 264{ 265 int o, p; 266 XkbOutlinePtr ol; 267 268 { 269 char *a = XkbAtomGetString(state->dpy, shape->name); 270 fprintf(out, "/%s {\n", a); 271 XFree(a); 272 } 273 fprintf(out, " gsave translate rotate /SOLID exch def\n"); 274 for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) { 275 XkbPointPtr pt; 276 277 if ((shape->num_outlines > 1) && (ol == shape->approx)) 278 continue; 279 pt = ol->points; 280 fprintf(out, "%% Outline %d\n", o + 1); 281 if (ol->num_points == 1) { 282 if (ol->corner_radius < 1) { 283 fprintf(out, " 0 0 moveto\n"); 284 fprintf(out, " %3d 0 lineto\n", pt->x); 285 fprintf(out, " %3d %3d lineto\n", pt->x, pt->y); 286 fprintf(out, " 0 %3d lineto\n", pt->y); 287 fprintf(out, " 0 0 lineto\n"); 288 fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 289 } 290 else { 291 fprintf(out, " mark\n"); 292 fprintf(out, " %3d 0 moveto\n", ol->corner_radius); 293 fprintf(out, " %3d 0 %3d %3d %3d arcto\n", pt->x, pt->x, 294 pt->y, ol->corner_radius); 295 fprintf(out, " %3d %3d 0 %3d %3d arcto\n", pt->x, pt->y, 296 pt->y, ol->corner_radius); 297 fprintf(out, " 0 %3d 0 0 %3d arcto\n", pt->y, 298 ol->corner_radius); 299 fprintf(out, " 0 0 %3d 0 %3d arcto\n", pt->x, 300 ol->corner_radius); 301 fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 302 fprintf(out, " cleartomark\n"); 303 } 304 } 305 else if (ol->num_points == 2) { 306 if (ol->corner_radius < 1) { 307 fprintf(out, " %3d %3d moveto\n", pt[0].x, pt[0].y); 308 fprintf(out, " %3d %3d lineto\n", pt[1].x, pt[0].y); 309 fprintf(out, " %3d %3d lineto\n", pt[1].x, pt[1].y); 310 fprintf(out, " %3d %3d lineto\n", pt[0].x, pt[1].y); 311 fprintf(out, " %3d %3d lineto\n", pt[0].x, pt[0].y); 312 fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 313 } 314 else { 315 fprintf(out, " mark\n"); 316 fprintf(out, " %3d %3d moveto\n", pt[0].x + ol->corner_radius, 317 pt[0].y); 318 fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[0].y, 319 pt[1].x, pt[1].y, ol->corner_radius); 320 fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[1].x, pt[1].y, 321 pt[0].x, pt[1].y, ol->corner_radius); 322 fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[1].y, 323 pt[0].x, pt[0].y, ol->corner_radius); 324 fprintf(out, " %3d %3d %3d %3d %3d arcto\n", pt[0].x, pt[0].y, 325 pt[1].x, pt[0].y, ol->corner_radius); 326 fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 327 fprintf(out, " cleartomark\n"); 328 } 329 } 330 else { 331 if (ol->corner_radius < 1) { 332 fprintf(out, " %3d %3d moveto\n", pt->x, pt->y); 333 pt++; 334 for (p = 1; p < ol->num_points; p++, pt++) { 335 fprintf(out, " %3d %3d lineto\n", pt->x, pt->y); 336 } 337 if ((pt->x != ol->points[0].x) || (pt->y != ol->points[0].y)) 338 fprintf(out, " closepath\n"); 339 fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 340 } 341 else { 342 XkbPointPtr last; 343 344 last = &pt[ol->num_points - 1]; 345 if ((last->x == pt->x) && (last->y == pt->y)) 346 last--; 347 fprintf(out, " mark\n"); 348 fprintf(out, " %% Determine tangent point of first corner\n"); 349 fprintf(out, " %3d %3d moveto %d %d %d %d %d arcto\n", 350 last->x, last->y, 351 pt[0].x, pt[0].y, pt[1].x, pt[1].y, ol->corner_radius); 352 fprintf(out, " /TY exch def /TX exch def pop pop newpath\n"); 353 fprintf(out, " %% Now draw the shape\n"); 354 fprintf(out, " TX TY moveto\n"); 355 for (p = 1; p < ol->num_points; p++) { 356 if (p < (ol->num_points - 1)) 357 last = &pt[p + 1]; 358 else 359 last = &pt[0]; 360 fprintf(out, " %3d %3d %3d %3d %3d arcto\n", 361 pt[p].x, pt[p].y, 362 last->x, last->y, ol->corner_radius); 363 } 364 last = &pt[ol->num_points - 1]; 365 if ((last->x != pt->x) || (last->y != pt->y)) { 366 fprintf(out, " %3d %3d %3d %3d %3d arcto\n", 367 pt[0].x, pt[0].y, 368 pt[1].x, pt[1].y, ol->corner_radius); 369 } 370 fprintf(out, " SOLID { fill } { stroke } ifelse\n"); 371 fprintf(out, " cleartomark\n"); 372 } 373 } 374 } 375 fprintf(out, " grestore\n"); 376 fprintf(out, "} def\n"); 377 return; 378} 379 380/***====================================================================***/ 381 382typedef struct { 383 char * foundry; 384 char * face; 385 char * weight; 386 char * slant; 387 char * setWidth; 388 char * variant; 389 int pixelSize; 390 int ptSize; 391 int resX; 392 int resY; 393 char * spacing; 394 int avgWidth; 395 char * encoding; 396} FontStuff; 397 398static void 399ClearFontStuff(FontStuff *stuff) 400{ 401 if (stuff && stuff->foundry) 402 free(stuff->foundry); 403 bzero(stuff, sizeof(FontStuff)); 404 return; 405} 406 407static Bool 408CrackXLFDName(const char *name, FontStuff *stuff) 409{ 410 char *tmp; 411 412 if ((name == NULL) || (stuff == NULL)) 413 return False; 414 if (name[0] == '-') 415 tmp = strdup(&name[1]); 416 else 417 tmp = strdup(name); 418 if (tmp == NULL) 419 return False; 420 stuff->foundry = tmp; 421 422 if ((tmp = strchr(tmp, '-')) == NULL) 423 goto BAILOUT; 424 else 425 *tmp++ = '\0'; 426 stuff->face = tmp; 427 428 if ((tmp = strchr(tmp, '-')) == NULL) 429 goto BAILOUT; 430 else 431 *tmp++ = '\0'; 432 stuff->weight = tmp; 433 434 if ((tmp = strchr(tmp, '-')) == NULL) 435 goto BAILOUT; 436 else 437 *tmp++ = '\0'; 438 stuff->slant = tmp; 439 440 if ((tmp = strchr(tmp, '-')) == NULL) 441 goto BAILOUT; 442 else 443 *tmp++ = '\0'; 444 stuff->setWidth = tmp; 445 446 if ((tmp = strchr(tmp, '-')) == NULL) 447 goto BAILOUT; 448 else 449 *tmp++ = '\0'; 450 stuff->variant = tmp; 451 452 if ((tmp = strchr(tmp, '-')) == NULL) 453 goto BAILOUT; 454 else 455 *tmp++ = '\0'; 456 if (*tmp == '*') 457 stuff->pixelSize = 0; 458 else if (sscanf(tmp, "%i", &stuff->pixelSize) != 1) 459 goto BAILOUT; 460 461 if ((tmp = strchr(tmp, '-')) == NULL) 462 goto BAILOUT; 463 else 464 *tmp++ = '\0'; 465 if (*tmp == '*') 466 stuff->ptSize = 0; 467 else if (sscanf(tmp, "%i", &stuff->ptSize) != 1) 468 goto BAILOUT; 469 470 if ((tmp = strchr(tmp, '-')) == NULL) 471 goto BAILOUT; 472 else 473 *tmp++ = '\0'; 474 if (*tmp == '*') 475 stuff->resX = 0; 476 else if (sscanf(tmp, "%i", &stuff->resX) != 1) 477 goto BAILOUT; 478 479 if ((tmp = strchr(tmp, '-')) == NULL) 480 goto BAILOUT; 481 else 482 *tmp++ = '\0'; 483 if (*tmp == '*') 484 stuff->resY = 0; 485 else if (sscanf(tmp, "%i", &stuff->resY) != 1) 486 goto BAILOUT; 487 488 if ((tmp = strchr(tmp, '-')) == NULL) 489 goto BAILOUT; 490 else 491 *tmp++ = '\0'; 492 stuff->spacing = tmp; 493 494 if ((tmp = strchr(tmp, '-')) == NULL) 495 goto BAILOUT; 496 else 497 *tmp++ = '\0'; 498 if (*tmp == '*') 499 stuff->avgWidth = 0; 500 else if (sscanf(tmp, "%i", &stuff->avgWidth) != 1) 501 goto BAILOUT; 502 503 if ((tmp = strchr(tmp, '-')) == NULL) 504 goto BAILOUT; 505 else 506 *tmp++ = '\0'; 507 stuff->encoding = tmp; 508 return True; 509 BAILOUT: 510 ClearFontStuff(stuff); 511 return False; 512} 513 514static void 515PSSetUpForLatin1(FILE *out, PSState *state) 516{ 517 fprintf(out, "%s", 518 "save\n" 519 "/ISOLatin1Encoding where {pop save true}{false} ifelse\n" 520 "/ISOLatin1Encoding [\n" 521 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 522 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 523 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 524 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 525 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n" 526 " /.notdef /.notdef /space /exclam /quotedbl /numbersign\n" 527 " /dollar /percent /ampersand /quoteright /parenleft\n" 528 " /parenright /asterisk /plus /comma /minus /period\n" 529 " /slash /zero /one /two /three /four /five /six /seven\n" 530 " /eight /nine /colon /semicolon /less /equal /greater\n" 531 " /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M\n" 532 " /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft\n" 533 " /backslash /bracketright /asciicircum /underscore\n" 534 " /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m\n" 535 " /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft\n" 536 " /bar /braceright /asciitilde /guilsinglright /fraction\n" 537 " /florin /quotesingle /quotedblleft /guilsinglleft /fi\n" 538 " /fl /endash /dagger /daggerdbl /bullet /quotesinglbase\n" 539 " /quotedblbase /quotedblright /ellipsis /trademark\n" 540 " /perthousand /grave /scaron /circumflex /Scaron /tilde\n" 541 " /breve /zcaron /dotaccent /dotlessi /Zcaron /ring\n" 542 " /hungarumlaut /ogonek /caron /emdash /space /exclamdown\n" 543 " /cent /sterling /currency /yen /brokenbar /section\n" 544 " /dieresis /copyright /ordfeminine /guillemotleft\n" 545 " /logicalnot /hyphen /registered /macron /degree\n" 546 " /plusminus /twosuperior /threesuperior /acute /mu\n" 547 " /paragraph /periodcentered /cedilla /onesuperior\n" 548 " /ordmasculine /guillemotright /onequarter /onehalf\n" 549 " /threequarters /questiondown /Agrave /Aacute\n" 550 " /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n" 551 " /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute\n" 552 " /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute\n" 553 " /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n" 554 " /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n" 555 " /germandbls /agrave /aacute /acircumflex /atilde\n" 556 " /adieresis /aring /ae /ccedilla /egrave /eacute\n" 557 " /ecircumflex /edieresis /igrave /iacute /icircumflex\n" 558 " /idieresis /eth /ntilde /ograve /oacute /ocircumflex\n" 559 " /otilde /odieresis /divide /oslash /ugrave /uacute\n" 560 " /ucircumflex /udieresis /yacute /thorn /ydieresis\n" 561 "] def {restore} if\n" 562 "/reencodeISO-1 {\n" 563 " dup length dict begin\n" 564 " {1 index /FID ne {def}{pop pop} ifelse} forall\n" 565 " /Encoding ISOLatin1Encoding def\n" 566 " currentdict\n" 567 " end\n" 568 "} def\n" 569 ); 570} 571 572static void 573PSReencodeLatin1Font(FILE *out, const char *font) 574{ 575 fprintf(out, "/%s findfont reencodeISO-1\n", font); 576 fprintf(out, " /%s-8859-1 exch definefont pop\n", font); 577 return; 578} 579 580static void 581PSSetUpFonts(FILE *out, const char *textFont, int size) 582{ 583 fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n", 584 FONT_TEXT, textFont); 585 fprintf(out, "/F%d { /%s-8859-1 findfont exch scalefont setfont } def\n", 586 FONT_LATIN1, textFont); 587 fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n", 588 FONT_SYMBOL, "Symbol"); 589 fprintf(out, "/F%d { /%s findfont exch scalefont setfont } def\n", 590 FONT_ISOCAPS, "IsoKeyCaps"); 591 return; 592} 593 594static void 595PSSetFont(FILE *out, PSState *state, int font, int size, int pts) 596{ 597 if ((state->font != font) || (state->fontSize != size)) { 598 fprintf(out, "%d %sF%d\n", size, (pts ? "pts " : ""), font); 599 state->font = font; 600 state->fontSize = size; 601 } 602 return; 603} 604 605static void 606PSProlog(FILE *out, PSState *state) 607{ 608 register int i; 609 610 if (!state->args->wantEPS) { 611 fprintf(out, 612 "%%!PS-Adobe-2.0\n" 613 "%%%%Creator: xkbprint\n"); 614 if (state->geom->name != None) { 615 char *a = XkbAtomGetString(state->dpy, state->geom->name); 616 fprintf(out, "%%%%Title: %s\n", a); 617 XFree(a); 618 } 619 fprintf(out, 620 "%%%%BoundingBox: (atend)\n" 621 "%%%%Pages: 1\n" 622 "%%%%PageOrder: Ascend\n" 623 "%%%%DocumentFonts: (atend)\n" 624 "%%%%DocumentData: Clean7Bit\n" 625 "%%%%Orientation: Landscape\n" 626 "%%%%EndComments\n" 627 "%%%%BeginProlog\n" 628 "%% Resolution is 1/10mm -- need pt sizes for fonts\n" 629 "clippath pathbbox\n" 630 " /ury exch def /urx exch def\n" 631 " /llx exch def /lly exch def\n" 632 " newpath\n" 633 "/devwidth urx llx sub def\n" 634 "/devheight ury lly sub def\n"); 635 } 636 else { 637 int w, h; 638 int pw, ph; 639 640 w = (((state->geom->width_mm * 72) / 254) * 11) / 10; 641 h = (((state->geom->height_mm * 72) / 254) * 11) / 10; 642 if (state->kbPerPage > 1) 643 h *= (state->kbPerPage + 1); 644 645 if (w <= h) { 646 pw = 7.5 * 72; 647 ph = 10 * 72; 648 } 649 else { 650 pw = 10 * 72; 651 ph = 7.5 * 72; 652 } 653 while ((w > pw) || (h > ph)) { 654 w = (w * 9) / 10; 655 h = (h * 9) / 10; 656 } 657 658 fprintf(out, "%%!PS-Adobe-2.0 EPSF-2.0\n"); 659 fprintf(out, "%%%%BoundingBox: 0 0 %d %d\n", w, h); 660 fprintf(out, "%%%%Creator: xkbprint\n"); 661 if (state->geom->name != None) { 662 char *a = XkbAtomGetString(state->dpy, state->geom->name); 663 fprintf(out, "%%%%Title: %s\n", a); 664 XFree(a); 665 } 666 fprintf(out, "%%%%Pages: 1\n"); 667 fprintf(out, "%%%%EndComments\n"); 668 fprintf(out, "%%%%BeginProlog\n"); 669 fprintf(out, "/ury 0 def /urx 0 def\n"); 670 fprintf(out, "/llx %d def /lly %d def\n", w, h); 671 fprintf(out, "/devwidth %d def /devheight %d def\n", w, h); 672 } 673 fprintf(out, "/kbdwidth %d def\n", state->geom->width_mm); 674 fprintf(out, "/kbdheight %d def\n", state->geom->height_mm); 675 fprintf(out, "%s", 676 "/pts { 254 mul 72 div } def\n" 677 "/mm10 { 72 mul 254 div } def\n" 678 "/landscape? {\n" 679 " devheight devwidth gt {\n" 680 " /pwidth devheight def /pheight devwidth def\n" 681 " 0 devheight translate\n" 682 " -90 rotate\n" 683 " } {\n" 684 " /pwidth devwidth def /pheight devheight def\n" 685 " } ifelse\n" 686 " 0 pheight translate\n" 687 " 1 -1 scale\n" 688 "} def\n" 689 "/centeroffset {\n" 690 " /S exch def\n" 691 " /HEIGHT exch def\n" 692 " /WIDTH exch def\n" 693 " S stringwidth /SH exch def /SW exch def\n" 694 " WIDTH SW sub 2 div\n" 695 " HEIGHT SH sub 2 div\n" 696 "} def\n"); 697 PSSetUpForLatin1(out, state); 698 PSReencodeLatin1Font(out, DFLT_LABEL_FONT); 699 if (state->args->wantColor) { 700 XkbGeometryPtr geom = state->geom; 701 702 for (i = 0; i < geom->num_colors; i++) { 703 PSColorDef(out, state, &geom->colors[i]); 704 } 705 if (state->black < 0) { 706 XkbColorPtr color; 707 708 if (!(color = XkbAddGeomColor(geom, "black", geom->num_colors))) 709 uFatalError("Couldn't allocate black color!\n"); 710 PSColorDef(out, state, color); 711 } 712 if (state->white < 0) { 713 XkbColorPtr color; 714 715 if (!(color = XkbAddGeomColor(geom, "white", geom->num_colors))) 716 uFatalError("Couldn't allocate white color!\n"); 717 PSColorDef(out, state, color); 718 } 719 } 720 for (i = 0; i < state->geom->num_shapes; i++) { 721 PSShapeDef(out, state, &state->geom->shapes[i]); 722 } 723 if (state->args->label == LABEL_SYMBOLS) { 724 PSIncludeFont(out, "IsoKeyCaps"); 725 } 726 PSSetUpFonts(out, DFLT_LABEL_FONT, DFLT_LABEL_FONT_SIZE); 727 fprintf(out, "%%%%EndProlog\n"); 728 return; 729} 730 731static void 732PSFileTrailer(FILE *out, PSState *state) 733{ 734 fprintf(out, "restore\n"); 735 if (!state->args->wantEPS) 736 fprintf(out, "%%%%Trailer\n"); 737 fprintf(out, "%%%%EOF\n"); 738 return; 739} 740 741static void 742PSPageSetup(FILE *out, PSState *state, Bool drawBorder) 743{ 744 XkbGeometryPtr geom; 745 746 geom = state->geom; 747 if (state->kbPerPage == 1) { 748 fprintf(out, "%%%%Page: %d %d\n", state->nPages + 1, state->nPages + 1); 749 fprintf(out, "%%%%BeginPageSetup\n"); 750 } 751 else if ((state->nPages & 1) == 0) { /* even page */ 752 int realPage; 753 754 realPage = state->nPages / 2 + 1; 755 fprintf(out, "%%%%Page: %d %d\n", realPage, realPage); 756 fprintf(out, "%%%%BeginPageSetup\n"); 757 fprintf(out, "%% Keyboard %d\n", state->nPages + 1); 758 if (state->nPages == 0) { 759 fprintf(out, 760 "/realwidth devwidth def\n" 761 "/realheight devheight def\n" 762 "/devheight realheight 3 div def\n"); 763 } 764 fprintf(out, "0 devheight dup 2 div add translate\n"); 765 } 766 else { 767 fprintf(out, "%% Keyboard %d\n", state->nPages + 1); 768 } 769 fprintf(out, "save\n"); 770 fprintf(out, "landscape?\n"); 771 if (state->args->scaleToFit) { 772 fprintf(out, 773 "%% Scale keyboard to fit on the page\n" 774 "/kbdscale pwidth 72 sub kbdwidth div def\n" 775 "/kbdscalewidth kbdwidth kbdscale mul def\n" 776 "/kbdscaleheight kbdheight kbdscale mul def\n" 777 "/kbx 36 def\n" 778 "/kby pheight kbdscaleheight sub 2 div def\n"); 779 PSGSave(out, state); 780 fprintf(out, 781 "kbx kby translate\n" 782 "kbdscale kbdscale scale\n"); 783 } 784 else { 785 fprintf(out, 786 "%% Draw keyboard full size\n" 787 "/kbdscale 1 def\n" 788 "/kbdscalewidth kbdwidth mm10 def\n" 789 "/kbdscaleheight kbdheight mm10 def\n" 790 "/kbx pwidth kbdscalewidth sub 2 div def\n" 791 "/kby pheight kbdscaleheight sub 2 div def\n"); 792 PSGSave(out, state); 793 fprintf(out, 794 "kbx kby translate\n" 795 "72 254 div dup scale\n"); 796 } 797 if (drawBorder) { 798 if (state->args->wantColor) { 799 PSSetColor(out, state, geom->base_color->pixel); 800 fprintf(out, " 0 0 moveto\n"); 801 fprintf(out, "%3d 0 lineto\n", geom->width_mm); 802 fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm); 803 fprintf(out, " 0 %3d lineto\n", geom->height_mm); 804 fprintf(out, "closepath fill\n"); 805 } 806 PSSetColor(out, state, state->black); 807 fprintf(out, " 0 0 moveto\n"); 808 fprintf(out, "%3d 0 lineto\n", geom->width_mm); 809 fprintf(out, "%3d %3d lineto\n", geom->width_mm, geom->height_mm); 810 fprintf(out, " 0 %3d lineto\n", geom->height_mm); 811 fprintf(out, "closepath stroke\n"); 812 } 813 fprintf(out, "%%%%EndPageSetup\n"); 814 return; 815} 816 817static void 818PSPageTrailer(FILE *out, PSState *state) 819{ 820 char *name; 821 XkbDescPtr xkb; 822 XkbGeometryPtr geom; 823 XkbPropertyPtr prop; 824 int p, baseline; 825 826 xkb = state->xkb; 827 geom = state->geom; 828 if (state->args->grid > 0) { 829 fprintf(out, "%% Draw a %dmm grid\n", state->args->grid); 830 fprintf(out, "0 setlinewidth\n"); 831 fprintf(out, "0.25 setgray\n"); 832 fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->width_mm); 833 fprintf(out, " /GX exch def\n"); 834 fprintf(out, " GX 0 moveto GX %d lineto stroke\n", geom->height_mm); 835 fprintf(out, "} for\n"); 836 fprintf(out, " 0 %d %d {\n", state->args->grid * 10, geom->height_mm); 837 fprintf(out, " /GY exch def\n"); 838 fprintf(out, " 0 GY moveto %d GY lineto stroke\n", geom->width_mm); 839 fprintf(out, "} for\n"); 840 } 841 PSGRestore(out, state); 842 name = NULL; 843 for (p = 0, prop = geom->properties; p < geom->num_properties; p++, prop++) { 844 if ((prop->value != NULL) && (uStrCaseEqual(prop->name, "description"))) { 845 name = prop->value; 846 break; 847 } 848 } 849 if ((!state->args->wantEPS) && 850 ((state->kbPerPage == 1) || ((state->nPages & 1) == 1) || 851 (state->nPages == state->totalKB))) { 852 char *a1 = NULL; 853 854 if ((name == NULL) && (geom->name != None)) 855 name = a1 = XkbAtomGetString(state->dpy, geom->name); 856 857 baseline = 16; 858 if ((name != NULL) || (state->args->label == LABEL_SYMBOLS)) { 859 PSSetColor(out, state, state->black); 860 PSSetFont(out, state, FONT_LATIN1, 14, False); 861 } 862 if (state->args->label == LABEL_SYMBOLS) { 863 char buf[40], *lbuf; 864 const char *sName = NULL; 865 char *a2 = NULL; 866 Atom sAtom; 867 868 if (state->args->nLabelGroups == 1) 869 snprintf(buf, sizeof(buf), "Group %d", 870 state->args->baseLabelGroup + 1); 871 else 872 snprintf(buf, sizeof(buf), "Groups %d-%d", 873 state->args->baseLabelGroup + 1, 874 state->args->baseLabelGroup + 875 state->args->nLabelGroups); 876 fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 877 buf); 878 fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 879 fprintf(out, " moveto\n"); 880 fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf); 881 baseline += 16; 882 883 if (xkb->names != NULL) 884 sAtom = xkb->names->symbols; 885 else 886 sAtom = None; 887 if (sAtom != None) 888 sName = a2 = XkbAtomGetString(state->dpy, sAtom); 889 if (sName == NULL) 890 sName = "(unknown)"; 891 892 if (asprintf(&lbuf, "Layout: %s", sName) == -1) { 893 uFatalError("Can't allocate memory for string\n"); 894 } 895 fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 896 lbuf); 897 fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 898 fprintf(out, " moveto\n"); 899 fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf); 900 baseline += 16; 901 free(lbuf); 902 XFree(a2); 903 } 904 if (name != NULL) { 905 fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 906 name); 907 fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 908 fprintf(out, " moveto\n"); 909 fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", name); 910 baseline += 16; 911 name = NULL; 912 XFree(a1); 913 } 914 if (state->args->label == LABEL_KEYCODE) { 915 const char *sName = NULL; 916 char *lbuf; 917 char *a3 = NULL; 918 Atom sAtom; 919 920 if (xkb->names != NULL) 921 sAtom = xkb->names->keycodes; 922 else 923 sAtom = None; 924 if (sAtom != None) 925 sName = a3 = XkbAtomGetString(state->dpy, sAtom); 926 if (sName == NULL) 927 sName = "(unknown)"; 928 929 if (asprintf(&lbuf, "Keycodes: %s", sName) == -1) { 930 uFatalError("Can't allocate memory for string\n"); 931 } 932 fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 933 lbuf); 934 fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 935 fprintf(out, " moveto\n"); 936 fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", lbuf); 937 baseline += 16; 938 free(lbuf); 939 XFree(a3); 940 } 941 if (state->args->copies > 1) { 942 for (p = 1; p < state->args->copies; p++) 943 fprintf(out, "copypage\n"); 944 } 945 fprintf(out, "showpage\n"); 946 fprintf(out, "restore\n"); 947 fprintf(out, "%% Done with keyboard/page %d\n", state->nPages + 1); 948 } 949 else { 950 if ((!state->args->wantEPS) && (state->args->label == LABEL_SYMBOLS)) { 951 char buf[40]; 952 953 baseline = 16; 954 PSSetColor(out, state, state->black); 955 PSSetFont(out, state, FONT_LATIN1, 14, False); 956 if (state->args->nLabelGroups == 1) 957 snprintf(buf, sizeof(buf), "Group %d", 958 state->args->baseLabelGroup + 1); 959 else 960 snprintf(buf, sizeof(buf), "Groups %d-%d", 961 state->args->baseLabelGroup + 1, 962 state->args->baseLabelGroup + 963 state->args->nLabelGroups + 1); 964 fprintf(out, "kbx kbdscalewidth 0 (%s) centeroffset pop add\n", 965 buf); 966 fprintf(out, " kby kbdscaleheight add %d add\n", baseline); 967 fprintf(out, " moveto\n"); 968 fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", buf); 969 baseline += 16; 970 } 971 fprintf(out, "restore\n"); 972 fprintf(out, "%% Done with keyboard %d\n", state->nPages + 1); 973 fprintf(out, "0 devheight -1 mul translate %% next keyboard\n"); 974 } 975 state->nPages++; 976 state->color = state->black; 977 state->font = -1; 978 return; 979} 980 981static void 982PSDoodad(FILE *out, PSState *state, XkbDoodadPtr doodad) 983{ 984 XkbDescPtr xkb; 985 const char *name, *dname; 986 char *a1 = NULL, *a2 = NULL; 987 int sz, leading; 988 989 xkb = state->xkb; 990 if (doodad->any.name != None) 991 dname = a1 = XkbAtomGetString(xkb->dpy, doodad->any.name); 992 else 993 dname = "NoName"; 994 switch (doodad->any.type) { 995 case XkbOutlineDoodad: 996 case XkbSolidDoodad: 997 name = a2 = XkbAtomGetString(xkb->dpy, 998 XkbShapeDoodadShape(xkb->geom, 999 &doodad->shape)->name); 1000 if (state->args->wantColor) { 1001 PSSetColor(out, state, doodad->shape.color_ndx); 1002 if (doodad->any.type != XkbOutlineDoodad) { 1003 fprintf(out, "true %d %d %d %s %% Doodad %s\n", 1004 doodad->shape.angle, 1005 doodad->shape.left, doodad->shape.top, name, dname); 1006 PSSetColor(out, state, state->black); 1007 } 1008 fprintf(out, "false %d %d %d %s %% Doodad %s\n", 1009 doodad->shape.angle, 1010 doodad->shape.left, doodad->shape.top, name, dname); 1011 } 1012 else { 1013 fprintf(out, "false %d %d %d %s %% Doodad %s\n", 1014 doodad->shape.angle, 1015 doodad->shape.left, doodad->shape.top, name, dname); 1016 } 1017 name = NULL; 1018 XFree(a2); 1019 break; 1020 case XkbTextDoodad: 1021 fprintf(out, "%% Doodad %s\n", dname); 1022 PSSetColor(out, state, doodad->text.color_ndx); 1023 PSGSave(out, state); 1024 fprintf(out, "%d %d translate\n", doodad->text.left, doodad->text.top); 1025 if (doodad->text.angle != 0) 1026 fprintf(out, "%s rotate\n", 1027 XkbGeomFPText(doodad->text.angle, XkbMessage)); 1028 sz = 14; 1029 if (doodad->text.font) { 1030 FontStuff stuff; 1031 1032 if (CrackXLFDName(doodad->text.font, &stuff)) { 1033 if (stuff.ptSize > 0) 1034 sz = stuff.ptSize / 10; 1035 ClearFontStuff(&stuff); 1036 } 1037 } 1038 PSSetFont(out, state, FONT_LATIN1, sz, True); 1039 leading = (sz * 12) / 10; 1040 if (strchr(doodad->text.text, '\n') == NULL) { 1041 fprintf(out, "0 %d pts moveto 1 -1 scale\n", (leading * 8) / 10); 1042 fprintf(out, "(%s) show\n", doodad->text.text); 1043 } 1044 else { 1045 char *tmp, *buf, *end; 1046 int offset = (leading * 8 / 10); 1047 1048 tmp = buf = strdup(doodad->text.text); 1049 while (tmp != NULL) { 1050 end = strchr(tmp, '\n'); 1051 if (end != NULL) 1052 *end++ = '\0'; 1053 fprintf(out, "0 %d pts moveto 1 -1 scale\n", offset); 1054 fprintf(out, "(%s) show 1 -1 scale\n", tmp); 1055 offset += leading; 1056 tmp = end; 1057 } 1058 free(buf); 1059 } 1060 PSGRestore(out, state); 1061 break; 1062 case XkbIndicatorDoodad: 1063 name = a2 = XkbAtomGetString(xkb->dpy, 1064 XkbIndicatorDoodadShape(xkb->geom, 1065 &doodad->indicator)-> 1066 name); 1067 if (state->args->wantColor) { 1068 PSSetColor(out, state, doodad->indicator.off_color_ndx); 1069 fprintf(out, "true 0 %d %d %s %% Doodad %s\n", 1070 doodad->indicator.left, doodad->indicator.top, name, dname); 1071 PSSetColor(out, state, state->black); 1072 } 1073 fprintf(out, "false 0 %d %d %s %% Doodad %s\n", 1074 doodad->indicator.left, doodad->indicator.top, name, dname); 1075 name = NULL; 1076 XFree(a2); 1077 break; 1078 case XkbLogoDoodad: 1079 name = a2 = XkbAtomGetString(xkb->dpy, 1080 XkbLogoDoodadShape(xkb->geom, 1081 &doodad->logo)->name); 1082 if (state->args->wantColor) 1083 PSSetColor(out, state, doodad->shape.color_ndx); 1084 fprintf(out, "false %d %d %d %s %% Doodad %s\n", 1085 doodad->shape.angle, 1086 doodad->shape.left, doodad->shape.top, name, dname); 1087 name = NULL; 1088 XFree(a2); 1089 break; 1090 } 1091 XFree(a1); 1092 return; 1093} 1094 1095/***====================================================================***/ 1096 1097static Bool 1098PSKeycapsSymbol(KeySym sym, unsigned char *buf, 1099 int *font_rtrn, int *sz_rtrn, PSState *state) 1100{ 1101 if (state->args->wantSymbols == NO_SYMBOLS) 1102 return False; 1103 1104 if (font_rtrn != NULL) 1105 *font_rtrn = FONT_ISOCAPS; 1106 if (sz_rtrn != NULL) 1107 *sz_rtrn = SZ_LARGE; 1108 buf[1] = '\0'; 1109 switch (sym) { 1110 case XK_Shift_L: 1111 case XK_Shift_R: 1112 buf[0] = XKC_ISO_Shift; 1113 return True; 1114 case XK_Shift_Lock: 1115 buf[0] = XKC_ISO_Shift_Lock; 1116 return True; 1117 case XK_ISO_Lock: 1118 buf[0] = XKC_ISO_Caps_Lock; 1119 return True; 1120 case XK_BackSpace: 1121 buf[0] = XKC_ISO_Backspace; 1122 return True; 1123 case XK_Return: 1124 buf[0] = XKC_ISO_Return; 1125 return True; 1126 case XK_Up: 1127 case XK_KP_Up: 1128 buf[0] = XKC_ISO_Up; 1129 return True; 1130 case XK_Down: 1131 case XK_KP_Down: 1132 buf[0] = XKC_ISO_Down; 1133 return True; 1134 case XK_Left: 1135 case XK_KP_Left: 1136 buf[0] = XKC_ISO_Left; 1137 return True; 1138 case XK_Right: 1139 case XK_KP_Right: 1140 buf[0] = XKC_ISO_Right; 1141 return True; 1142 case XK_Tab: 1143 buf[0] = XKC_ISO_Tab; 1144 return True; 1145 case XK_ISO_Left_Tab: 1146 buf[0] = XKC_ISO_Left_Tab; 1147 return True; 1148 } 1149 if (state->args->wantSymbols != ALL_SYMBOLS) 1150 return False; 1151 switch (sym) { 1152 case XK_Caps_Lock: 1153 buf[0] = XKC_ISO_Caps_Lock; 1154 return True; 1155 case XK_Num_Lock: 1156 buf[0] = XKC_ISO_Num_Lock; 1157 return True; 1158 case XK_ISO_Level3_Shift: 1159 buf[0] = XKC_ISO_Level3_Shift; 1160 return True; 1161 case XK_ISO_Level3_Lock: 1162 buf[0] = XKC_ISO_Level3_Lock; 1163 return True; 1164 case XK_ISO_Next_Group: 1165 case XK_ISO_Group_Shift: 1166 buf[0] = XKC_ISO_Next_Group; 1167 return True; 1168 case XK_ISO_Next_Group_Lock: 1169 buf[0] = XKC_ISO_Next_Group_Lock; 1170 return True; 1171 case XK_space: 1172 buf[0] = XKC_ISO_Space; 1173 return True; 1174 case XK_nobreakspace: 1175 buf[0] = XKC_ISO_No_Break_Space; 1176 return True; 1177 case XK_Insert: 1178 buf[0] = XKC_ISO_Insert; 1179 return True; 1180 case XK_ISO_Continuous_Underline: 1181 buf[0] = XKC_ISO_Continuous_Underline; 1182 return True; 1183 case XK_ISO_Discontinuous_Underline: 1184 buf[0] = XKC_ISO_Discontinuous_Underline; 1185 return True; 1186 case XK_ISO_Emphasize: 1187 buf[0] = XKC_ISO_Emphasize; 1188 return True; 1189 case XK_Multi_key: 1190 buf[0] = XKC_ISO_Compose; 1191 return True; 1192 case XK_ISO_Center_Object: 1193 buf[0] = XKC_ISO_Center_Object; 1194 return True; 1195 case XK_Delete: 1196 buf[0] = XKC_ISO_Delete; 1197 return True; 1198 case XK_Clear: 1199 buf[0] = XKC_ISO_Clear_Screen; 1200 return True; 1201 case XK_Scroll_Lock: 1202 buf[0] = XKC_ISO_Scroll_Lock; 1203 return True; 1204 case XK_Help: 1205 buf[0] = XKC_ISO_Help; 1206 return True; 1207 case XK_Print: 1208 buf[0] = XKC_ISO_Print_Screen; 1209 return True; 1210 case XK_ISO_Enter: 1211 buf[0] = XKC_ISO_Enter; 1212 return True; 1213 case XK_Alt_L: 1214 case XK_Alt_R: 1215 buf[0] = XKC_ISO_Alt; 1216 return True; 1217 case XK_Control_L: 1218 case XK_Control_R: 1219 buf[0] = XKC_ISO_Control; 1220 return True; 1221 case XK_Pause: 1222 buf[0] = XKC_ISO_Pause; 1223 return True; 1224 case XK_Break: 1225 buf[0] = XKC_ISO_Break; 1226 return True; 1227 case XK_Escape: 1228 buf[0] = XKC_ISO_Escape; 1229 return True; 1230 case XK_Undo: 1231 buf[0] = XKC_ISO_Undo; 1232 return True; 1233 case XK_ISO_Fast_Cursor_Up: 1234 buf[0] = XKC_ISO_Fast_Cursor_Up; 1235 return True; 1236 case XK_ISO_Fast_Cursor_Down: 1237 buf[0] = XKC_ISO_Fast_Cursor_Down; 1238 return True; 1239 case XK_ISO_Fast_Cursor_Left: 1240 buf[0] = XKC_ISO_Fast_Cursor_Left; 1241 return True; 1242 case XK_ISO_Fast_Cursor_Right: 1243 buf[0] = XKC_ISO_Fast_Cursor_Right; 1244 return True; 1245 case XK_Home: 1246 buf[0] = XKC_ISO_Home; 1247 return True; 1248 case XK_End: 1249 buf[0] = XKC_ISO_End; 1250 return True; 1251 case XK_Page_Up: 1252 buf[0] = XKC_ISO_Page_Up; 1253 return True; 1254 case XK_Page_Down: 1255 buf[0] = XKC_ISO_Page_Down; 1256 return True; 1257 case XK_ISO_Move_Line_Up: 1258 buf[0] = XKC_ISO_Move_Line_Up; 1259 return True; 1260 case XK_ISO_Move_Line_Down: 1261 buf[0] = XKC_ISO_Move_Line_Down; 1262 return True; 1263 case XK_ISO_Partial_Line_Up: 1264 buf[0] = XKC_ISO_Partial_Line_Up; 1265 return True; 1266 case XK_ISO_Partial_Line_Down: 1267 buf[0] = XKC_ISO_Partial_Line_Down; 1268 return True; 1269 case XK_ISO_Partial_Space_Left: 1270 buf[0] = XKC_ISO_Partial_Space_Left; 1271 return True; 1272 case XK_ISO_Partial_Space_Right: 1273 buf[0] = XKC_ISO_Partial_Space_Right; 1274 return True; 1275 case XK_ISO_Set_Margin_Left: 1276 buf[0] = XKC_ISO_Set_Margin_Left; 1277 return True; 1278 case XK_ISO_Set_Margin_Right: 1279 buf[0] = XKC_ISO_Set_Margin_Right; 1280 return True; 1281 case XK_ISO_Release_Margin_Left: 1282 buf[0] = XKC_ISO_Release_Margin_Left; 1283 return True; 1284 case XK_ISO_Release_Margin_Right: 1285 buf[0] = XKC_ISO_Release_Margin_Right; 1286 return True; 1287 case XK_ISO_Release_Both_Margins: 1288 buf[0] = XKC_ISO_Release_Both_Margins; 1289 return True; 1290 case XK_ISO_Prev_Group: 1291 buf[0] = XKC_ISO_Prev_Group; 1292 return True; 1293 case XK_ISO_Prev_Group_Lock: 1294 buf[0] = XKC_ISO_Prev_Group_Lock; 1295 return True; 1296 } 1297 return False; 1298} 1299 1300static Bool 1301PSNonLatin1Symbol(KeySym sym, unsigned char *buf, 1302 int *font_rtrn, int *sz_rtrn, PSState *state) 1303{ 1304 if (state->args->wantSymbols == NO_SYMBOLS) 1305 return False; 1306 1307 if (font_rtrn != NULL) 1308 *font_rtrn = FONT_TEXT; 1309 if (sz_rtrn != NULL) 1310 *sz_rtrn = SZ_LARGE; 1311 buf[1] = '\0'; 1312 switch (sym) { 1313 case XK_breve: 1314 buf[0] = 0xC6; 1315 return True; 1316 case XK_abovedot: 1317 buf[0] = 0xC7; 1318 return True; 1319 case XK_doubleacute: 1320 buf[0] = 0xCD; 1321 return True; 1322 case XK_ogonek: 1323 buf[0] = 0xCE; 1324 return True; 1325 case XK_caron: 1326 buf[0] = 0xCF; 1327 return True; 1328 case XK_Lstroke: 1329 buf[0] = 0xE8; 1330 return True; 1331 case XK_idotless: 1332 buf[0] = 0xF5; 1333 return True; 1334 case XK_lstroke: 1335 buf[0] = 0xF8; 1336 return True; 1337 } 1338 if (font_rtrn != NULL) 1339 *font_rtrn = FONT_SYMBOL; 1340 if (sz_rtrn != NULL) 1341 *sz_rtrn = SZ_MEDIUM; 1342 if ((sym & (~0xffUL)) == 0x700) { 1343 switch (sym) { 1344 /* Greek symbol */ 1345 case XK_Greek_ALPHA: 1346 buf[0] = 0x41; 1347 return True; 1348 case XK_Greek_BETA: 1349 buf[0] = 0x42; 1350 return True; 1351 case XK_Greek_CHI: 1352 buf[0] = 0x43; 1353 return True; 1354 case XK_Greek_DELTA: 1355 buf[0] = 0x44; 1356 return True; 1357 case XK_Greek_EPSILON: 1358 buf[0] = 0x45; 1359 return True; 1360 case XK_Greek_PHI: 1361 buf[0] = 0x46; 1362 return True; 1363 case XK_Greek_GAMMA: 1364 buf[0] = 0x47; 1365 return True; 1366 case XK_Greek_ETA: 1367 buf[0] = 0x48; 1368 return True; 1369 case XK_Greek_IOTA: 1370 buf[0] = 0x49; 1371 return True; 1372 case XK_Greek_KAPPA: 1373 buf[0] = 0x4B; 1374 return True; 1375 case XK_Greek_LAMDA: 1376 buf[0] = 0x4C; 1377 return True; 1378 case XK_Greek_MU: 1379 buf[0] = 0x4D; 1380 return True; 1381 case XK_Greek_NU: 1382 buf[0] = 0x4E; 1383 return True; 1384 case XK_Greek_OMICRON: 1385 buf[0] = 0x4F; 1386 return True; 1387 case XK_Greek_PI: 1388 buf[0] = 0x50; 1389 return True; 1390 case XK_Greek_THETA: 1391 buf[0] = 0x51; 1392 return True; 1393 case XK_Greek_RHO: 1394 buf[0] = 0x52; 1395 return True; 1396 case XK_Greek_SIGMA: 1397 buf[0] = 0x53; 1398 return True; 1399 case XK_Greek_TAU: 1400 buf[0] = 0x54; 1401 return True; 1402 case XK_Greek_UPSILON: 1403 buf[0] = 0x55; 1404 return True; 1405 case XK_Greek_OMEGA: 1406 buf[0] = 0x57; 1407 return True; 1408 case XK_Greek_XI: 1409 buf[0] = 0x58; 1410 return True; 1411 case XK_Greek_PSI: 1412 buf[0] = 0x59; 1413 return True; 1414 case XK_Greek_ZETA: 1415 buf[0] = 0x5A; 1416 return True; 1417 1418 case XK_Greek_alpha: 1419 buf[0] = 0x61; 1420 return True; 1421 case XK_Greek_beta: 1422 buf[0] = 0x62; 1423 return True; 1424 case XK_Greek_chi: 1425 buf[0] = 0x63; 1426 return True; 1427 case XK_Greek_delta: 1428 buf[0] = 0x64; 1429 return True; 1430 case XK_Greek_epsilon: 1431 buf[0] = 0x65; 1432 return True; 1433 case XK_Greek_phi: 1434 buf[0] = 0x66; 1435 return True; 1436 case XK_Greek_gamma: 1437 buf[0] = 0x67; 1438 return True; 1439 case XK_Greek_eta: 1440 buf[0] = 0x68; 1441 return True; 1442 case XK_Greek_iota: 1443 buf[0] = 0x69; 1444 return True; 1445 case XK_Greek_kappa: 1446 buf[0] = 0x6B; 1447 return True; 1448 case XK_Greek_lamda: 1449 buf[0] = 0x6C; 1450 return True; 1451 case XK_Greek_mu: 1452 buf[0] = 0x6D; 1453 return True; 1454 case XK_Greek_nu: 1455 buf[0] = 0x6E; 1456 return True; 1457 case XK_Greek_omicron: 1458 buf[0] = 0x6F; 1459 return True; 1460 case XK_Greek_pi: 1461 buf[0] = 0x70; 1462 return True; 1463 case XK_Greek_theta: 1464 buf[0] = 0x71; 1465 return True; 1466 case XK_Greek_rho: 1467 buf[0] = 0x72; 1468 return True; 1469 case XK_Greek_sigma: 1470 buf[0] = 0x73; 1471 return True; 1472 case XK_Greek_tau: 1473 buf[0] = 0x74; 1474 return True; 1475 case XK_Greek_upsilon: 1476 buf[0] = 0x75; 1477 return True; 1478 case XK_Greek_omega: 1479 buf[0] = 0x77; 1480 return True; 1481 case XK_Greek_xi: 1482 buf[0] = 0x78; 1483 return True; 1484 case XK_Greek_psi: 1485 buf[0] = 0x79; 1486 return True; 1487 case XK_Greek_zeta: 1488 buf[0] = 0x7A; 1489 return True; 1490 } 1491 } 1492 switch (sym) { 1493 case XK_leftarrow: 1494 buf[0] = 0xAC; 1495 return True; 1496 case XK_uparrow: 1497 buf[0] = 0xAD; 1498 return True; 1499 case XK_rightarrow: 1500 buf[0] = 0xAE; 1501 return True; 1502 case XK_downarrow: 1503 buf[0] = 0xAF; 1504 return True; 1505 case XK_horizconnector: 1506 buf[0] = 0xBE; 1507 return True; 1508 case XK_trademark: 1509 buf[0] = 0xE4; 1510 return True; 1511 } 1512 return False; 1513} 1514 1515static KeySym 1516CheckSymbolAlias(KeySym sym, PSState *state) 1517{ 1518 if (XkbKSIsKeypad(sym)) { 1519 if ((sym >= XK_KP_0) && (sym <= XK_KP_9)) 1520 sym = (sym - XK_KP_0) + XK_0; 1521 else 1522 switch (sym) { 1523 case XK_KP_Space: 1524 return XK_space; 1525 case XK_KP_Tab: 1526 return XK_Tab; 1527 case XK_KP_Enter: 1528 return XK_Return; 1529 case XK_KP_F1: 1530 return XK_F1; 1531 case XK_KP_F2: 1532 return XK_F2; 1533 case XK_KP_F3: 1534 return XK_F3; 1535 case XK_KP_F4: 1536 return XK_F4; 1537 case XK_KP_Home: 1538 return XK_Home; 1539 case XK_KP_Left: 1540 return XK_Left; 1541 case XK_KP_Up: 1542 return XK_Up; 1543 case XK_KP_Right: 1544 return XK_Right; 1545 case XK_KP_Down: 1546 return XK_Down; 1547 case XK_KP_Page_Up: 1548 return XK_Page_Up; 1549 case XK_KP_Page_Down: 1550 return XK_Page_Down; 1551 case XK_KP_End: 1552 return XK_End; 1553 case XK_KP_Begin: 1554 return XK_Begin; 1555 case XK_KP_Insert: 1556 return XK_Insert; 1557 case XK_KP_Delete: 1558 return XK_Delete; 1559 case XK_KP_Equal: 1560 return XK_equal; 1561 case XK_KP_Multiply: 1562 return XK_asterisk; 1563 case XK_KP_Add: 1564 return XK_plus; 1565 case XK_KP_Subtract: 1566 return XK_minus; 1567 case XK_KP_Divide: 1568 return XK_slash; 1569 } 1570 } 1571 else if (XkbKSIsDeadKey(sym)) { 1572 switch (sym) { 1573 case XK_dead_grave: 1574 sym = XK_grave; 1575 break; 1576 case XK_dead_acute: 1577 sym = XK_acute; 1578 break; 1579 case XK_dead_circumflex: 1580 sym = XK_asciicircum; 1581 break; 1582 case XK_dead_tilde: 1583 sym = XK_asciitilde; 1584 break; 1585 case XK_dead_macron: 1586 sym = XK_macron; 1587 break; 1588 case XK_dead_breve: 1589 sym = XK_breve; 1590 break; 1591 case XK_dead_abovedot: 1592 sym = XK_abovedot; 1593 break; 1594 case XK_dead_diaeresis: 1595 sym = XK_diaeresis; 1596 break; 1597 case XK_dead_abovering: 1598 sym = XK_degree; 1599 break; 1600 case XK_dead_doubleacute: 1601 sym = XK_doubleacute; 1602 break; 1603 case XK_dead_caron: 1604 sym = XK_caron; 1605 break; 1606 case XK_dead_cedilla: 1607 sym = XK_cedilla; 1608 break; 1609 case XK_dead_ogonek: 1610 sym = XK_ogonek; 1611 break; 1612 case XK_dead_iota: 1613 sym = XK_Greek_iota; 1614 break; 1615 case XK_dead_voiced_sound: 1616 sym = XK_voicedsound; 1617 break; 1618 case XK_dead_semivoiced_sound: 1619 sym = XK_semivoicedsound; 1620 break; 1621 } 1622 } 1623 return sym; 1624} 1625 1626static Bool 1627FindKeysymsByName(XkbDescPtr xkb, char *name, PSState *state, KeyTop *top) 1628{ 1629 static unsigned char buf[30]; 1630 int kc; 1631 KeySym sym, *syms, topSyms[NLABELS]; 1632 int level, group; 1633 int eG, nG, gI, l, g; 1634 1635 bzero(top, sizeof(KeyTop)); 1636 kc = XkbFindKeycodeByName(xkb, name, True); 1637 if (state->args != NULL) { 1638 level = state->args->labelLevel; 1639 group = state->args->baseLabelGroup; 1640 } 1641 else 1642 level = group = 0; 1643 syms = XkbKeySymsPtr(xkb, kc); 1644 eG = group; 1645 nG = XkbKeyNumGroups(xkb, kc); 1646 gI = XkbKeyGroupInfo(xkb, kc); 1647 if ((state->args->wantDiffs) && (eG >= XkbKeyNumGroups(xkb, kc))) 1648 return False; /* XXX was a return with no value */ 1649 if (nG == 0) { 1650 return False; 1651 } 1652 else if (nG == 1) { 1653 eG = 0; 1654 } 1655 else if (eG >= XkbKeyNumGroups(xkb, kc)) { 1656 switch (XkbOutOfRangeGroupAction(gI)) { 1657 default: 1658 eG %= nG; 1659 break; 1660 case XkbClampIntoRange: 1661 eG = nG - 1; 1662 break; 1663 case XkbRedirectIntoRange: 1664 eG = XkbOutOfRangeGroupNumber(gI); 1665 if (eG >= nG) 1666 eG = 0; 1667 break; 1668 } 1669 } 1670 for (g = 0; g < state->args->nLabelGroups; g++) { 1671 if ((eG + g) >= nG) 1672 continue; 1673 for (l = 0; l < 2; l++) { 1674 int font, sz; 1675 1676 if (level + l >= XkbKeyGroupWidth(xkb, kc, (eG + g))) 1677 continue; 1678 sym = syms[((eG + g) * XkbKeyGroupsWidth(xkb, kc)) + (level + l)]; 1679 1680 if (state->args->wantSymbols != NO_SYMBOLS) 1681 sym = CheckSymbolAlias(sym, state); 1682 topSyms[(g * 2) + l] = sym; 1683 1684 if (PSKeycapsSymbol(sym, buf, &font, &sz, state)) { 1685 top->font[(g * 2) + l] = font; 1686 top->size[(g * 2) + l] = sz; 1687 } 1688 else if (((sym & (~0xffUL)) == 0) && isprint(sym) && (!isspace(sym))) { 1689 if (sym == '(') 1690 snprintf((char *) buf, sizeof(buf), "\\("); 1691 else if (sym == ')') 1692 snprintf((char *) buf, sizeof(buf), "\\)"); 1693 else if (sym == '\\') 1694 snprintf((char *) buf, sizeof(buf), "\\\\"); 1695 else 1696 snprintf((char *) buf, sizeof(buf), "%c", (char) sym); 1697 top->font[(g * 2) + l] = FONT_LATIN1; 1698 top->size[(g * 2) + l] = SZ_MEDIUM; 1699 switch (buf[0]) { 1700 case '.': 1701 case ':': 1702 case ',': 1703 case ';': 1704 case '\'': 1705 case '"': 1706 case '`': 1707 case '~': 1708 case '^': 1709 case 0250: 1710 case 0270: 1711 case 0267: 1712 case 0260: 1713 case 0252: 1714 case 0272: 1715 case 0271: 1716 case 0262: 1717 case 0263: 1718 case 0264: 1719 case 0255: 1720 case 0254: 1721 case 0257: 1722 top->size[(g * 2) + l] = SZ_LARGE; 1723 break; 1724 } 1725 } 1726 else if (PSNonLatin1Symbol(sym, buf, &font, &sz, state)) { 1727 top->font[(g * 2) + l] = font; 1728 top->size[(g * 2) + l] = sz; 1729 } 1730 else { 1731 char *tmp; 1732 1733 tmp = XKeysymToString(sym); 1734 if (tmp != NULL) 1735 strcpy((char *) buf, tmp); 1736 else 1737 snprintf((char *) buf, sizeof(buf), "(%ld)", sym); 1738 top->font[(g * 2) + l] = FONT_LATIN1; 1739 if (strlen((char *) buf) < 9) 1740 top->size[(g * 2) + l] = SZ_SMALL; 1741 else 1742 top->size[(g * 2) + l] = SZ_TINY; 1743 } 1744 top->present |= (1 << ((g * 2) + l)); 1745 strncpy(top->label[(g * 2) + l], (char *) buf, LABEL_LEN - 1); 1746 top->label[(g * 2) + l][LABEL_LEN - 1] = '\0'; 1747 } 1748 if (((g == 0) && (top->present & G1LX_MASK) == G1LX_MASK) || 1749 ((g == 1) && (top->present & G2LX_MASK) == G2LX_MASK)) { 1750 KeySym lower, upper; 1751 1752 XConvertCase(topSyms[(g * 2)], &lower, &upper); 1753 if ((topSyms[(g * 2)] == lower) && (topSyms[(g * 2) + 1] == upper)) { 1754 top->alpha[g] = True; 1755 } 1756 } 1757 } 1758 return True; 1759} 1760 1761static void 1762PSDrawLabel(FILE *out, const char *label, int x, int y, int w, int h) 1763{ 1764 fprintf(out, "%d %d (%s) centeroffset\n", w, h, label); 1765 fprintf(out, "%d add exch\n", y); 1766 fprintf(out, "%d add exch moveto\n", x); 1767 fprintf(out, "1 -1 scale (%s) show 1 -1 scale\n", label); 1768 return; 1769} 1770 1771#define TOP_ROW 0 1772#define BOTTOM_ROW 1 1773#define CENTER_ROW 2 1774 1775#define LEFT_COL 0 1776#define RIGHT_COL 1 1777#define CENTER_COL 2 1778 1779static void 1780PSLabelKey(FILE *out, PSState *state, KeyTop *top, int x, int y, 1781 XkbBoundsPtr bounds, int kc, int btm) 1782{ 1783 int w, h, i; 1784 int row_y[3]; 1785 int col_x[3]; 1786 int row_h[3]; 1787 int col_w[3]; 1788 Bool present[NLABELS]; 1789 int sym_row[NLABELS]; 1790 int sym_col[NLABELS]; 1791 1792 w = XkbBoundsWidth(bounds); 1793 h = XkbBoundsHeight(bounds); 1794 row_y[TOP_ROW] = y + bounds->y1 + (h / 10); 1795 row_y[BOTTOM_ROW] = y + bounds->y1 + (h / 2) + (h / 10); 1796 row_y[CENTER_ROW] = y + bounds->y1 + (h / 10); 1797 row_h[TOP_ROW] = h / 2; 1798 row_h[BOTTOM_ROW] = h / 2; 1799 row_h[CENTER_ROW] = h; 1800 1801 col_x[LEFT_COL] = x + bounds->x1; 1802 col_x[RIGHT_COL] = x + bounds->x1 + w / 2; 1803 col_x[CENTER_COL] = x + bounds->x1; 1804 col_w[LEFT_COL] = w / 2; 1805 col_w[RIGHT_COL] = w / 2; 1806 col_w[CENTER_COL] = w; 1807 1808 present[G1L1] = False; 1809 sym_row[G1L1] = BOTTOM_ROW; 1810 sym_col[G1L1] = LEFT_COL; 1811 1812 present[G1L2] = False; 1813 sym_row[G1L2] = TOP_ROW; 1814 sym_col[G1L2] = LEFT_COL; 1815 1816 present[G2L1] = False; 1817 sym_row[G2L1] = BOTTOM_ROW; 1818 sym_col[G2L1] = RIGHT_COL; 1819 1820 present[G2L2] = False; 1821 sym_row[G2L2] = TOP_ROW; 1822 sym_col[G2L2] = RIGHT_COL; 1823 1824 present[CENTER] = False; 1825 sym_row[CENTER] = CENTER_ROW; 1826 sym_col[CENTER] = CENTER_COL; 1827 1828 if (top->present & CENTER_MASK) { 1829 present[CENTER] = True; 1830 } 1831 else 1832 switch (top->present & GXLX_MASK) { 1833 case G1L1_MASK: 1834 present[G1L1] = True; 1835 sym_row[G1L1] = CENTER_ROW; 1836 sym_col[G1L1] = CENTER_COL; 1837 break; 1838 case G1LX_MASK: 1839 present[G1L2] = True; 1840 if (!top->alpha[0]) { 1841 present[G1L1] = True; 1842 if ((strlen(top->label[G1L1]) > 1) && 1843 (top->label[G1L1][0] != '\\')) 1844 sym_col[G1L1] = CENTER_COL; 1845 if ((strlen(top->label[G1L2]) > 1) && 1846 (top->label[G1L1][0] != '\\')) 1847 sym_col[G1L2] = CENTER_COL; 1848 } 1849 break; 1850 default: 1851 if ((top->present & G1LX_MASK) == G1LX_MASK) { 1852 present[G1L2] = True; 1853 if (!top->alpha[0]) 1854 present[G1L1] = True; 1855 } 1856 else if ((top->present & G1LX_MASK) == G1L1_MASK) { 1857 present[G1L1] = True; 1858 } 1859 else if ((top->present & G1LX_MASK) == G1L2_MASK) { 1860 present[G1L2] = True; 1861 } 1862 if ((top->present & G2LX_MASK) == G2LX_MASK) { 1863 present[G2L2] = True; 1864 if (!top->alpha[1]) 1865 present[G2L1] = True; 1866 } 1867 else if ((top->present & G2LX_MASK) == G2L1_MASK) { 1868 present[G2L1] = True; 1869 } 1870 else if ((top->present & G2LX_MASK) == G2L2_MASK) { 1871 present[G2L2] = True; 1872 } 1873 break; 1874 case 0: 1875 return; 1876 } 1877 for (i = 0; i < NLABELS; i++) { 1878 if (present[i]) { 1879 int size; 1880 1881 if (top->size[i] == SZ_AUTO) { 1882 size_t len = strlen(top->label[i]); 1883 if (len == 1) { 1884 if (top->font[i] == FONT_ISOCAPS) 1885 size = 18; 1886 else 1887 size = 14; 1888 } 1889 else if (len < 10) 1890 size = 12; 1891 else 1892 size = 10; 1893 } 1894 else if (top->size[i] == SZ_TINY) 1895 size = 10; 1896 else if (top->size[i] == SZ_SMALL) 1897 size = 12; 1898 else if (top->size[i] == SZ_LARGE) 1899 size = 18; 1900 else if (top->size[i] == SZ_XLARGE) 1901 size = 24; 1902 else 1903 size = 14; 1904 PSSetFont(out, state, top->font[i], size, True); 1905 PSDrawLabel(out, top->label[i], col_x[sym_col[i]], 1906 row_y[sym_row[i]], col_w[sym_col[i]], 1907 row_h[sym_row[i]]); 1908 } 1909 } 1910 if (state->args->wantKeycodes) { 1911 char keycode[10]; 1912 1913 snprintf(keycode, sizeof(keycode), "%d", kc); 1914 PSSetFont(out, state, FONT_LATIN1, 8, True); 1915 PSDrawLabel(out, keycode, x + bounds->x1, y + btm - 5, w, 0); 1916 } 1917 return; 1918} 1919 1920static void 1921PSSection(FILE *out, PSState *state, XkbSectionPtr section) 1922{ 1923 int r, offset; 1924 XkbRowPtr row; 1925 Display *dpy; 1926 XkbDescPtr xkb; 1927 1928 xkb = state->xkb; 1929 dpy = xkb->dpy; 1930 { 1931 const char *section_name; 1932 char *atom_name = NULL; 1933 1934 if (section->name != None) 1935 section_name = atom_name = XkbAtomGetString(dpy, section->name); 1936 else 1937 section_name = "NoName"; 1938 fprintf(out, "%% Begin Section '%s'\n", section_name); 1939 XFree(atom_name); 1940 } 1941 PSGSave(out, state); 1942 fprintf(out, "%d %d translate\n", section->left, section->top); 1943 if (section->angle != 0) 1944 fprintf(out, "%s rotate\n", XkbGeomFPText(section->angle, XkbMessage)); 1945 if (section->doodads) { 1946 XkbDrawablePtr first, draw; 1947 1948 first = draw = XkbGetOrderedDrawables(NULL, section); 1949 while (draw) { 1950 if (draw->type == XkbDW_Section) 1951 PSSection(out, state, draw->u.section); 1952 else 1953 PSDoodad(out, state, draw->u.doodad); 1954 draw = draw->next; 1955 } 1956 XkbFreeOrderedDrawables(first); 1957 } 1958 for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 1959 int k; 1960 XkbKeyPtr key; 1961 1962 if (row->vertical) 1963 offset = row->top; 1964 else 1965 offset = row->left; 1966 fprintf(out, "%% Begin %s %d\n", row->vertical ? "column" : "row", 1967 r + 1); 1968 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 1969 XkbShapePtr shape = XkbKeyShape(xkb->geom, key); 1970 char *shape_name = XkbAtomGetString(dpy, shape->name); 1971 1972 offset += key->gap; 1973 if (row->vertical) { 1974 if (state->args->wantColor) { 1975 if (key->color_ndx != state->white) { 1976 PSSetColor(out, state, key->color_ndx); 1977 fprintf(out, "true 0 %d %d %s %% %s\n", 1978 row->left, offset, shape_name, 1979 XkbKeyNameText(key->name.name, XkbMessage)); 1980 } 1981 PSSetColor(out, state, state->black); 1982 } 1983 fprintf(out, "false 0 %d %d %s %% %s\n", row->left, offset, 1984 shape_name, 1985 XkbKeyNameText(key->name.name, XkbMessage)); 1986 offset += shape->bounds.y2; 1987 } 1988 else { 1989 if (state->args->wantColor) { 1990 if (key->color_ndx != state->white) { 1991 PSSetColor(out, state, key->color_ndx); 1992 fprintf(out, "true 0 %d %d %s %% %s\n", offset, 1993 row->top, shape_name, 1994 XkbKeyNameText(key->name.name, XkbMessage)); 1995 } 1996 PSSetColor(out, state, state->black); 1997 } 1998 fprintf(out, "false 0 %d %d %s %% %s\n", offset, row->top, 1999 shape_name, 2000 XkbKeyNameText(key->name.name, XkbMessage)); 2001 offset += shape->bounds.x2; 2002 } 2003 XFree(shape_name); 2004 } 2005 } 2006 for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 2007 int k, kc = 0; 2008 XkbKeyPtr key; 2009 XkbShapePtr shape; 2010 XkbBoundsRec bounds; 2011 2012 if (state->args->label == LABEL_NONE) 2013 break; 2014 if (row->vertical) 2015 offset = row->top; 2016 else 2017 offset = row->left; 2018 fprintf(out, "%% Begin %s %d labels\n", 2019 row->vertical ? "column" : "row", r + 1); 2020 PSSetColor(out, state, xkb->geom->label_color->pixel); 2021 PSSetFont(out, state, FONT_LATIN1, 12, True); 2022 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 2023 char *name, *name2, buf[30], buf2[30]; 2024 int x, y; 2025 KeyTop top; 2026 2027 shape = XkbKeyShape(xkb->geom, key); 2028 XkbComputeShapeTop(shape, &bounds); 2029 offset += key->gap; 2030 name = name2 = NULL; 2031 if (state->args->label == LABEL_SYMBOLS) { 2032 if (!FindKeysymsByName(xkb, key->name.name, state, &top)) { 2033 fprintf(out, "%% No label for %s\n", 2034 XkbKeyNameText(key->name.name, XkbMessage)); 2035 } 2036 } 2037 else { 2038 char *olKey; 2039 2040 if (section->num_overlays > 0) 2041 olKey = XkbFindOverlayForKey(xkb->geom, section, 2042 key->name.name); 2043 else 2044 olKey = NULL; 2045 2046 if (state->args->label == LABEL_KEYNAME) { 2047 name = XkbKeyNameText(key->name.name, XkbMessage); 2048 if (olKey) 2049 name2 = XkbKeyNameText(olKey, XkbMessage); 2050 } 2051 else if (state->args->label == LABEL_KEYCODE) { 2052 name = buf; 2053 snprintf(name, sizeof(buf), "%d", 2054 XkbFindKeycodeByName(xkb, key->name.name, True)); 2055 if (olKey) { 2056 name2 = buf2; 2057 snprintf(name2, sizeof(buf2), "%d", 2058 XkbFindKeycodeByName(xkb, olKey, True)); 2059 } 2060 } 2061 bzero(&top, sizeof(KeyTop)); 2062 if (name2 != NULL) { 2063 top.present |= G1LX_MASK; 2064 strncpy(top.label[G1L1], name, LABEL_LEN - 1); 2065 top.label[G1L1][LABEL_LEN - 1] = '\0'; 2066 strncpy(top.label[G1L2], name2, LABEL_LEN - 1); 2067 top.label[G1L2][LABEL_LEN - 1] = '\0'; 2068 } 2069 else if (name != NULL) { 2070 top.present |= CENTER_MASK; 2071 strncpy(top.label[CENTER], name, LABEL_LEN - 1); 2072 top.label[CENTER][LABEL_LEN - 1] = '\0'; 2073 } 2074 else { 2075 fprintf(out, "%% No label for %s\n", 2076 XkbKeyNameText(key->name.name, XkbMessage)); 2077 } 2078 } 2079 if (row->vertical) { 2080 x = row->left; 2081 y = offset; 2082 offset += shape->bounds.y2; 2083 } 2084 else { 2085 x = offset; 2086 y = row->top; 2087 offset += shape->bounds.x2; 2088 } 2089 name = key->name.name; 2090 fprintf(out, "%% %s\n", XkbKeyNameText(name, XkbMessage)); 2091 if (state->args->wantKeycodes) 2092 kc = XkbFindKeycodeByName(xkb, key->name.name, True); 2093 PSLabelKey(out, state, &top, x, y, &bounds, kc, shape->bounds.y2); 2094 } 2095 } 2096 PSGRestore(out, state); 2097 return; 2098} 2099 2100Bool 2101GeometryToPostScript(FILE *out, XkbFileInfo *pResult, XKBPrintArgs *args) 2102{ 2103 XkbDrawablePtr first, draw; 2104 PSState state; 2105 Bool dfltBorder; 2106 int i; 2107 2108 if ((!pResult) || (!pResult->xkb) || (!pResult->xkb->geom)) 2109 return False; 2110 state.xkb = pResult->xkb; 2111 state.dpy = pResult->xkb->dpy; 2112 state.geom = pResult->xkb->geom; 2113 state.color = state.black = state.white = -1; 2114 state.font = -1; 2115 state.nPages = 0; 2116 state.totalKB = 1; 2117 state.kbPerPage = 1; 2118 state.x1 = state.y1 = state.x2 = state.y2 = 0; 2119 state.args = args; 2120 2121 if ((args->label == LABEL_SYMBOLS) && (pResult->xkb->ctrls)) { 2122 if (args->nTotalGroups == 0) 2123 state.totalKB = 2124 pResult->xkb->ctrls->num_groups / args->nLabelGroups; 2125 else 2126 state.totalKB = args->nTotalGroups; 2127 if (state.totalKB < 1) 2128 state.totalKB = 1; 2129 else if (state.totalKB > 1) 2130 state.kbPerPage = 2; 2131 } 2132 if (args->nKBPerPage != 0) 2133 state.kbPerPage = args->nKBPerPage; 2134 2135 PSProlog(out, &state); 2136 first = XkbGetOrderedDrawables(state.geom, NULL); 2137 2138 for (draw = first, dfltBorder = True; draw != NULL; draw = draw->next) { 2139 if ((draw->type != XkbDW_Section) && 2140 ((draw->u.doodad->any.type == XkbOutlineDoodad) || 2141 (draw->u.doodad->any.type == XkbSolidDoodad))) { 2142 char *name; 2143 2144 name = XkbAtomGetString(state.dpy, draw->u.doodad->any.name); 2145 if ((name != NULL) && (uStrCaseEqual(name, "edges"))) { 2146 dfltBorder = False; 2147 XFree(name); 2148 break; 2149 } 2150 XFree(name); 2151 } 2152 } 2153 for (i = 0; i < state.totalKB; i++) { 2154 PSPageSetup(out, &state, dfltBorder); 2155 for (draw = first; draw != NULL; draw = draw->next) { 2156 if (draw->type == XkbDW_Section) 2157 PSSection(out, &state, draw->u.section); 2158 else { 2159 PSDoodad(out, &state, draw->u.doodad); 2160 } 2161 } 2162 PSPageTrailer(out, &state); 2163 state.args->baseLabelGroup += state.args->nLabelGroups; 2164 } 2165 XkbFreeOrderedDrawables(first); 2166 PSFileTrailer(out, &state); 2167 return True; 2168} 2169