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