tmore files - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 61f5c35c9465f0702739b41249a664d409f0482c | |
parent 173302913ebce353eadcbb12d71c3759cbe79e34 | |
Author: rsc <devnull@localhost> | |
Date: Sat, 15 May 2004 23:55:53 +0000 | |
more files | |
Diffstat: | |
M src/cmd/mkfile | 2 +- | |
A src/cmd/postscript/common/bbox.c | 257 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/comments… | 127 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/common.c | 264 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/common.h | 43 ++++++++++++++++++++++++++++++ | |
A src/cmd/postscript/common/ext.h | 40 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/gen.h | 65 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/getopt.c | 56 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/glob.c | 29 +++++++++++++++++++++++++++++ | |
A src/cmd/postscript/common/misc.c | 230 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/mkfile | 23 +++++++++++++++++++++++ | |
A src/cmd/postscript/common/path.h | 32 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/request.c | 119 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/request.h | 22 ++++++++++++++++++++++ | |
A src/cmd/postscript/common/rune.c | 142 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/common/rune.h | 19 +++++++++++++++++++ | |
A src/cmd/postscript/common/tempnam.c | 27 +++++++++++++++++++++++++++ | |
A src/cmd/postscript/download/README | 11 +++++++++++ | |
A src/cmd/postscript/download/downlo… | 545 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/download/downlo… | 14 ++++++++++++++ | |
A src/cmd/postscript/download/mkfile | 25 +++++++++++++++++++++++++ | |
A src/cmd/postscript/mkfile | 25 +++++++++++++++++++++++++ | |
A src/cmd/postscript/tr2post/Bgetfie… | 156 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/chartab… | 458 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/conv.c | 100 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/devcntl… | 178 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/draw.c | 342 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/mkfile | 36 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/picture… | 295 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/ps_incl… | 191 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/ps_incl… | 66 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/readDES… | 139 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/shell.l… | 1238 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/tr2post… | 218 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/tr2post… | 103 +++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/utfmap | 47 +++++++++++++++++++++++++++++… | |
A src/cmd/postscript/tr2post/utils.c | 264 +++++++++++++++++++++++++++++… | |
37 files changed, 5947 insertions(+), 1 deletion(-) | |
--- | |
diff --git a/src/cmd/mkfile b/src/cmd/mkfile | |
t@@ -5,7 +5,7 @@ SHORTLIB=sec fs mux regexp9 thread bio 9 | |
<$PLAN9/src/mkmany | |
-BUGGERED='CVS|faces|factotum|mailfs|scat|upas|vac|venti|lex|vncv|grap|eqn|trof… | |
+BUGGERED='CVS|faces|factotum|mailfs|scat|upas|vac|venti|lex|vncv|grap|eqn|trof… | |
DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"` | |
<$PLAN9/src/mkdirs | |
diff --git a/src/cmd/postscript/common/bbox.c b/src/cmd/postscript/common/bbox.c | |
t@@ -0,0 +1,257 @@ | |
+/* | |
+ * | |
+ * Boundingbox code for PostScript translators. The boundingbox for each page | |
+ * is accumulated in bbox - the one for the whole document goes in docbbox. A | |
+ * call to writebbox() puts out an appropriate comment, updates docbbox, and | |
+ * resets bbox for the next page. The assumption made at the end of writebbox() | |
+ * is that we're really printing the current page only if output is now going | |
+ * to stdout - a valid assumption for all supplied translators. Needs the math | |
+ * library. | |
+ * | |
+ */ | |
+ | |
+#include <stdio.h> | |
+#include <ctype.h> | |
+#include <sys/types.h> | |
+#include <fcntl.h> | |
+#include <math.h> | |
+ | |
+#include "comments.h" /* PostScript file structuring co… | |
+#include "gen.h" /* a few general purpose definitions */ | |
+#include "ext.h" /* external variable declarations */ | |
+ | |
+typedef struct bbox { | |
+ int set; | |
+ double llx, lly; | |
+ double urx, ury; | |
+} Bbox; | |
+ | |
+Bbox bbox = {FALSE, 0.0, 0.0, 0.0, 0.0}; | |
+Bbox docbbox = {FALSE, 0.0, 0.0, 0.0, 0.0}; | |
+ | |
+double ctm[6] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; | |
+double matrix1[6], matrix2[6]; | |
+ | |
+/*****************************************************************************/ | |
+ | |
+cover(x, y) | |
+ | |
+ double x, y; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Adds point (x, y) to bbox. Coordinates are in user space - the transformati… | |
+ * to default coordinates happens in writebbox(). | |
+ * | |
+ */ | |
+ | |
+ if ( bbox.set == FALSE ) { | |
+ bbox.llx = bbox.urx = x; | |
+ bbox.lly = bbox.ury = y; | |
+ bbox.set = TRUE; | |
+ } else { | |
+ if ( x < bbox.llx ) | |
+ bbox.llx = x; | |
+ if ( y < bbox.lly ) | |
+ bbox.lly = y; | |
+ if ( x > bbox.urx ) | |
+ bbox.urx = x; | |
+ if ( y > bbox.ury ) | |
+ bbox.ury = y; | |
+ } /* End else */ | |
+ | |
+} /* End of cover */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+writebbox(fp, keyword, slop) | |
+ | |
+ FILE *fp; /* the comment is written here */ | |
+ char *keyword; /* the boundingbox comment string */ | |
+ int slop; /* expand (or contract?) t… | |
+ | |
+{ | |
+ | |
+ Bbox ubbox; /* user space bounding box */ | |
+ double x, y; | |
+ | |
+/* | |
+ * | |
+ * Transforms the numbers in the bbox[] using ctm[], adjusts the corners a bit | |
+ * (depending on slop) and then writes comment. If *keyword is BoundingBox use | |
+ * whatever's been saved in docbbox, otherwise assume the comment is just for | |
+ * the current page. | |
+ * | |
+ */ | |
+ | |
+ if ( strcmp(keyword, BOUNDINGBOX) == 0 ) | |
+ bbox = docbbox; | |
+ | |
+ if ( bbox.set == TRUE ) { | |
+ ubbox = bbox; | |
+ bbox.set = FALSE; /* so cover() works properly */ | |
+ x = ctm[0] * ubbox.llx + ctm[2] * ubbox.lly + ctm[4]; | |
+ y = ctm[1] * ubbox.llx + ctm[3] * ubbox.lly + ctm[5]; | |
+ cover(x, y); | |
+ x = ctm[0] * ubbox.llx + ctm[2] * ubbox.ury + ctm[4]; | |
+ y = ctm[1] * ubbox.llx + ctm[3] * ubbox.ury + ctm[5]; | |
+ cover(x, y); | |
+ x = ctm[0] * ubbox.urx + ctm[2] * ubbox.ury + ctm[4]; | |
+ y = ctm[1] * ubbox.urx + ctm[3] * ubbox.ury + ctm[5]; | |
+ cover(x, y); | |
+ x = ctm[0] * ubbox.urx + ctm[2] * ubbox.lly + ctm[4]; | |
+ y = ctm[1] * ubbox.urx + ctm[3] * ubbox.lly + ctm[5]; | |
+ cover(x, y); | |
+ bbox.llx -= slop + 0.5; | |
+ bbox.lly -= slop + 0.5; | |
+ bbox.urx += slop + 0.5; | |
+ bbox.ury += slop + 0.5; | |
+ fprintf(fp, "%s %d %d %d %d\n", keyword, (int)bbox.llx, (int)bbox.lly,… | |
+ bbox = ubbox; | |
+ } /* End if */ | |
+ | |
+ resetbbox((fp == stdout) ? TRUE : FALSE); | |
+ | |
+} /* End of writebbox */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+resetbbox(output) | |
+ | |
+ int output; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Adds bbox to docbbox and resets bbox for the next page. Only update docbbox | |
+ * if we really did output on the last page. | |
+ * | |
+ */ | |
+ | |
+ if ( docbbox.set == TRUE ) { | |
+ cover(docbbox.llx, docbbox.lly); | |
+ cover(docbbox.urx, docbbox.ury); | |
+ } /* End if */ | |
+ | |
+ if ( output == TRUE ) { | |
+ docbbox = bbox; | |
+ docbbox.set = TRUE; | |
+ } /* End if */ | |
+ | |
+ bbox.set = FALSE; | |
+ | |
+} /* End of resetbbox */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+scale(sx, sy) | |
+ | |
+ double sx, sy; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Scales the default matrix. | |
+ * | |
+ */ | |
+ | |
+ matrix1[0] = sx; | |
+ matrix1[1] = 0; | |
+ matrix1[2] = 0; | |
+ matrix1[3] = sy; | |
+ matrix1[4] = 0; | |
+ matrix1[5] = 0; | |
+ | |
+ concat(matrix1); | |
+ | |
+} /* End of scale */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+translate(tx, ty) | |
+ | |
+ double tx, ty; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Translates the default matrix. | |
+ * | |
+ */ | |
+ | |
+ matrix1[0] = 1.0; | |
+ matrix1[1] = 0.0; | |
+ matrix1[2] = 0.0; | |
+ matrix1[3] = 1.0; | |
+ matrix1[4] = tx; | |
+ matrix1[5] = ty; | |
+ | |
+ concat(matrix1); | |
+ | |
+} /* End of translate */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+rotate(angle) | |
+ | |
+ double angle; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Rotates by angle degrees. | |
+ * | |
+ */ | |
+ | |
+ angle *= 3.1416 / 180; | |
+ | |
+ matrix1[0] = matrix1[3] = cos(angle); | |
+ matrix1[1] = sin(angle); | |
+ matrix1[2] = -matrix1[1]; | |
+ matrix1[4] = 0.0; | |
+ matrix1[5] = 0.0; | |
+ | |
+ concat(matrix1); | |
+ | |
+} /* End of rotate */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+concat(m1) | |
+ | |
+ double m1[]; | |
+ | |
+{ | |
+ | |
+ double m2[6]; | |
+ | |
+/* | |
+ * | |
+ * Replaces the ctm[] by the result of the matrix multiplication m1[] x ctm[]. | |
+ * | |
+ */ | |
+ | |
+ m2[0] = ctm[0]; | |
+ m2[1] = ctm[1]; | |
+ m2[2] = ctm[2]; | |
+ m2[3] = ctm[3]; | |
+ m2[4] = ctm[4]; | |
+ m2[5] = ctm[5]; | |
+ | |
+ ctm[0] = m1[0] * m2[0] + m1[1] * m2[2]; | |
+ ctm[1] = m1[0] * m2[1] + m1[1] * m2[3]; | |
+ ctm[2] = m1[2] * m2[0] + m1[3] * m2[2]; | |
+ ctm[3] = m1[2] * m2[1] + m1[3] * m2[3]; | |
+ ctm[4] = m1[4] * m2[0] + m1[5] * m2[2] + m2[4]; | |
+ ctm[5] = m1[4] * m2[1] + m1[5] * m2[3] + m2[5]; | |
+ | |
+} /* End of concat */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
diff --git a/src/cmd/postscript/common/comments.h b/src/cmd/postscript/common/c… | |
t@@ -0,0 +1,127 @@ | |
+/* | |
+ * | |
+ * Currently defined file structuring comments from Adobe - plus a few others. | |
+ * Ones that end with a colon expect arguments, while those ending with a newl… | |
+ * stand on their own. Truly overkill on Adobe's part and mine for including t… | |
+ * all! | |
+ * | |
+ * All PostScript files should begin with a header that starts with one of the | |
+ * following comments. | |
+ * | |
+ */ | |
+ | |
+#define NONCONFORMING "%!PS\n" | |
+#define MINCONFORMING "%!PS-Adobe-\n" | |
+#define OLDCONFORMING "%!PS-Adobe-1.0\n" | |
+ | |
+#define CONFORMING "%!PS-Adobe-2.0\n" | |
+#define CONFORMINGEPS "%!PS-Adobe-2.0 EPS\n" | |
+#define CONFORMINGQUERY "%!PS-Adobe-2.0 Query\n" | |
+#define CONFORMINGEXITSERVER "%!PS-Adobe-2.0 ExitServer\n" | |
+ | |
+/* | |
+ * | |
+ * Header comments - immediately follow the appropriate document classification | |
+ * comment. | |
+ * | |
+ */ | |
+ | |
+#define TITLE "%%Title:" | |
+#define CREATOR "%%Creator:" | |
+#define CREATIONDATE "%%CreationDate:" | |
+#define FOR "%%For:" | |
+#define ROUTING "%%Routing:" | |
+#define BOUNDINGBOX "%%BoundingBox:" | |
+#define PAGES "%%Pages:" | |
+#define REQUIREMENTS "%%Requirements:" | |
+ | |
+#define DOCUMENTFONTS "%%DocumentFonts:" | |
+#define DOCUMENTNEEDEDFONTS "%%DocumentNeededFonts:" | |
+#define DOCUMENTSUPPLIEDFONTS "%%DocumentSuppliedFonts:" | |
+#define DOCUMENTNEEDEDPROCSETS "%%DocumentNeededProcSets:" | |
+#define DOCUMENTSUPPLIEDPROCSETS "%%DocumentSuppliedProcSets:" | |
+#define DOCUMENTNEEDEDFILES "%%DocumentNeededFiles:" | |
+#define DOCUMENTSUPPLIEDFILES "%%DocumentSuppliedFiles:" | |
+#define DOCUMENTPAPERSIZES "%%DocumentPaperSizes:" | |
+#define DOCUMENTPAPERFORMS "%%DocumentPaperForms:" | |
+#define DOCUMENTPAPERCOLORS "%%DocumentPaperColors:" | |
+#define DOCUMENTPAPERWEIGHTS "%%DocumentPaperWeights:" | |
+#define DOCUMENTPRINTERREQUIRED "%%DocumentPrinterREquired:" | |
+#define ENDCOMMENTS "%%EndComments\n" | |
+#define ENDPROLOG "%%EndProlog\n" | |
+ | |
+/* | |
+ * | |
+ * Body comments - can appear anywhere in a document. | |
+ * | |
+ */ | |
+ | |
+#define BEGINSETUP "%%BeginSetup\n" | |
+#define ENDSETUP "%%EndSetup\n" | |
+#define BEGINDOCUMENT "%%BeginDocument:" | |
+#define ENDDOCUMENT "%%EndDocument\n" | |
+#define BEGINFILE "%%BeginFile:" | |
+#define ENDFILE "%%EndFile\n" | |
+#define BEGINPROCSET "%%BeginProcSet:" | |
+#define ENDPROCSET "%%EndProcSet\n" | |
+#define BEGINBINARY "%%BeginBinary:" | |
+#define ENDBINARY "%%EndBinary\n" | |
+#define BEGINPAPERSIZE "%%BeginePaperSize:" | |
+#define ENDPAPERSIZE "%%EndPaperSize\n" | |
+#define BEGINFEATURE "%%BeginFeature:" | |
+#define ENDFEATURE "%%EndFeature\n" | |
+#define BEGINEXITSERVER "%%BeginExitServer:" | |
+#define ENDEXITSERVER "%%EndExitServer\n" | |
+#define TRAILER "%%Trailer\n" | |
+ | |
+/* | |
+ * | |
+ * Page level comments - usually will occur once per page. | |
+ * | |
+ */ | |
+ | |
+#define PAGE "%%Page:" | |
+#define PAGEFONTS "%%PageFonts:" | |
+#define PAGEFILES "%%PageFiles:" | |
+#define PAGEBOUNDINGBOX "%%PageBoundingBox:" | |
+#define BEGINPAGESETUP "%%BeginPageSetup\n" | |
+#define BEGINOBJECT "%%BeginObject:" | |
+#define ENDOBJECT "%%EndObject\n" | |
+ | |
+/* | |
+ * | |
+ * Resource requirements - again can appear anywhere in a document. | |
+ * | |
+ */ | |
+ | |
+#define INCLUDEFONT "%%IncludeFont:" | |
+#define INCLUDEPROCSET "%%IncludeProcSet:" | |
+#define INCLUDEFILE "%%IncludeFile:" | |
+#define EXECUTEFILE "%%ExecuteFile:" | |
+#define CHANGEFONT "%%ChangeFont:" | |
+#define PAPERFORM "%%PaparForm:" | |
+#define PAPERCOLOR "%%PaperColor:" | |
+#define PAPERWEIGHT "%%PaperWeight:" | |
+#define PAPERSIZE "%%PaperSize:" | |
+#define FEATURE "%%Feature:" | |
+#define ENDOFFILE "%%EOF\n" | |
+ | |
+#define CONTINUECOMMENT "%%+" | |
+#define ATEND "(atend)" | |
+ | |
+/* | |
+ * | |
+ * Some non-standard document comments. Global definitions are occasionally us… | |
+ * in dpost and are marked by BEGINGLOBAL and ENDGLOBAL. The resulting document | |
+ * violates page independence, but can easily be converted to a conforming file | |
+ * using a utililty program. | |
+ * | |
+ */ | |
+ | |
+#define BEGINSCRIPT "%%BeginScript\n" | |
+#define BEGINGLOBAL "%%BeginGlobal\n" | |
+#define ENDGLOBAL "%%EndGlobal\n" | |
+#define ENDPAGE "%%EndPage:" | |
+#define FORMSPERPAGE "%%FormsPerPage:" | |
+#define VERSION "%%Version:" | |
+ | |
diff --git a/src/cmd/postscript/common/common.c b/src/cmd/postscript/common/com… | |
t@@ -0,0 +1,264 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <ctype.h> | |
+#include "common.h" | |
+#include "comments.h" | |
+#include "path.h" | |
+ | |
+struct strtab charcode[FONTSIZE] = { | |
+ {4, "\\000"}, {4, "\\001"}, {4, "\\002"}, {4, "\\003"}, | |
+ {4, "\\004"}, {4, "\\005"}, {4, "\\006"}, {4, "\\007"}, | |
+ {4, "\\010"}, {4, "\\011"}, {4, "\\012"}, {4, "\\013"}, | |
+ {4, "\\014"}, {4, "\\015"}, {4, "\\016"}, {4, "\\017"}, | |
+ {4, "\\020"}, {4, "\\021"}, {4, "\\022"}, {4, "\\023"}, | |
+ {4, "\\024"}, {4, "\\025"}, {4, "\\026"}, {4, "\\027"}, | |
+ {4, "\\030"}, {4, "\\031"}, {4, "\\032"}, {4, "\\033"}, | |
+ {4, "\\034"}, {4, "\\035"}, {4, "\\036"}, {4, "\\037"}, | |
+ {1, " "}, {1, "!"}, {1, "\""}, {1, "#"}, | |
+ {1, "$"}, {1, "%"}, {1, "&"}, {1, "'"}, | |
+ {2, "\\("}, {2, "\\)"}, {1, "*"}, {1, "+"}, | |
+ {1, ","}, {1, "-"}, {1, "."}, {1, "/"}, | |
+ {1, "0"}, {1, "1"}, {1, "2"}, {1, "3"}, | |
+ {1, "4"}, {1, "5"}, {1, "6"}, {1, "7"}, | |
+ {1, "8"}, {1, "9"}, {1, ":"}, {1, ";"}, | |
+ {1, "<"}, {1, "="}, {1, ">"}, {1, "?"}, | |
+ {1, "@"}, {1, "A"}, {1, "B"}, {1, "C"}, | |
+ {1, "D"}, {1, "E"}, {1, "F"}, {1, "G"}, | |
+ {1, "H"}, {1, "I"}, {1, "J"}, {1, "K"}, | |
+ {1, "L"}, {1, "M"}, {1, "N"}, {1, "O"}, | |
+ {1, "P"}, {1, "Q"}, {1, "R"}, {1, "S"}, | |
+ {1, "T"}, {1, "U"}, {1, "V"}, {1, "W"}, | |
+ {1, "X"}, {1, "Y"}, {1, "Z"}, {1, "["}, | |
+ {2, "\\\\"}, {1, "]"}, {1, "^"}, {1, "_"}, | |
+ {1, "`"}, {1, "a"}, {1, "b"}, {1, "c"}, | |
+ {1, "d"}, {1, "e"}, {1, "f"}, {1, "g"}, | |
+ {1, "h"}, {1, "i"}, {1, "j"}, {1, "k"}, | |
+ {1, "l"}, {1, "m"}, {1, "n"}, {1, "o"}, | |
+ {1, "p"}, {1, "q"}, {1, "r"}, {1, "s"}, | |
+ {1, "t"}, {1, "u"}, {1, "v"}, {1, "w"}, | |
+ {1, "x"}, {1, "y"}, {1, "z"}, {1, "{"}, | |
+ {1, "|"}, {1, "}"}, {1, "~"}, {4, "\\177"}, | |
+ {4, "\\200"}, {4, "\\201"}, {4, "\\202"}, {4, "\\203"}, | |
+ {4, "\\204"}, {4, "\\205"}, {4, "\\206"}, {4, "\\207"}, | |
+ {4, "\\210"}, {4, "\\211"}, {4, "\\212"}, {4, "\\213"}, | |
+ {4, "\\214"}, {4, "\\215"}, {4, "\\216"}, {4, "\\217"}, | |
+ {4, "\\220"}, {4, "\\221"}, {4, "\\222"}, {4, "\\223"}, | |
+ {4, "\\224"}, {4, "\\225"}, {4, "\\226"}, {4, "\\227"}, | |
+ {4, "\\230"}, {4, "\\231"}, {4, "\\232"}, {4, "\\233"}, | |
+ {4, "\\234"}, {4, "\\235"}, {4, "\\236"}, {4, "\\237"}, | |
+ {4, "\\240"}, {4, "\\241"}, {4, "\\242"}, {4, "\\243"}, | |
+ {4, "\\244"}, {4, "\\245"}, {4, "\\246"}, {4, "\\247"}, | |
+ {4, "\\250"}, {4, "\\251"}, {4, "\\252"}, {4, "\\253"}, | |
+ {4, "\\254"}, {4, "\\255"}, {4, "\\256"}, {4, "\\257"}, | |
+ {4, "\\260"}, {4, "\\261"}, {4, "\\262"}, {4, "\\263"}, | |
+ {4, "\\264"}, {4, "\\265"}, {4, "\\266"}, {4, "\\267"}, | |
+ {4, "\\270"}, {4, "\\271"}, {4, "\\272"}, {4, "\\273"}, | |
+ {4, "\\274"}, {4, "\\275"}, {4, "\\276"}, {4, "\\277"}, | |
+ {4, "\\300"}, {4, "\\301"}, {4, "\\302"}, {4, "\\303"}, | |
+ {4, "\\304"}, {4, "\\305"}, {4, "\\306"}, {4, "\\307"}, | |
+ {4, "\\310"}, {4, "\\311"}, {4, "\\312"}, {4, "\\313"}, | |
+ {4, "\\314"}, {4, "\\315"}, {4, "\\316"}, {4, "\\317"}, | |
+ {4, "\\320"}, {4, "\\321"}, {4, "\\322"}, {4, "\\323"}, | |
+ {4, "\\324"}, {4, "\\325"}, {4, "\\326"}, {4, "\\327"}, | |
+ {4, "\\330"}, {4, "\\331"}, {4, "\\332"}, {4, "\\333"}, | |
+ {4, "\\334"}, {4, "\\335"}, {4, "\\336"}, {4, "\\337"}, | |
+ {4, "\\340"}, {4, "\\341"}, {4, "\\342"}, {4, "\\343"}, | |
+ {4, "\\344"}, {4, "\\345"}, {4, "\\346"}, {4, "\\347"}, | |
+ {4, "\\350"}, {4, "\\351"}, {4, "\\352"}, {4, "\\353"}, | |
+ {4, "\\354"}, {4, "\\355"}, {4, "\\356"}, {4, "\\357"}, | |
+ {4, "\\360"}, {4, "\\361"}, {4, "\\362"}, {4, "\\363"}, | |
+ {4, "\\364"}, {4, "\\365"}, {4, "\\366"}, {4, "\\367"}, | |
+ {4, "\\370"}, {4, "\\371"}, {4, "\\372"}, {4, "\\373"}, | |
+ {4, "\\374"}, {4, "\\375"}, {4, "\\376"}, {4, "\\377"} | |
+}; | |
+ | |
+static BOOLEAN in_string = FALSE; | |
+int char_no = 0; | |
+int line_no = 0; | |
+int page_no = 0; /* page number in a document */ | |
+int pages_printed = 0; | |
+static int pplistmaxsize=0; | |
+ | |
+static unsigned char *pplist=0; /* bitmap list for storing pages to pri… | |
+ | |
+void | |
+pagelist(char *list) { | |
+ char c; | |
+ int n, m; | |
+ int state, start; | |
+ | |
+ if (list == 0) return; | |
+ state = 1; | |
+ start = 0; | |
+ while ((c=*list) != '\0') { | |
+ n = 0; | |
+ while (isdigit(c)) { | |
+ n = n * 10 + c - '0'; | |
+ c = *++list; | |
+ } | |
+ switch (state) { | |
+ case 1: | |
+ start = n; | |
+ case 2: | |
+ if (n/8+1 > pplistmaxsize) { | |
+ pplistmaxsize = n/8+1; | |
+ pplist = galloc(pplist, n/8+1, "page list"); | |
+ } | |
+ for (m=start; m<=n; m++) | |
+ pplist[m/8] |= 1<<(m%8); | |
+ break; | |
+ } | |
+ switch (c) { | |
+ case '-': | |
+ state = 2; | |
+ list++; | |
+ break; | |
+ case ',': | |
+ state = 1; | |
+ list++; | |
+ break; | |
+ case '\0': | |
+ break; | |
+ } | |
+ } | |
+} | |
+ | |
+BOOLEAN | |
+pageon(void) { | |
+ extern BOOLEAN debug; | |
+ static BOOLEAN privdebug = FALSE; | |
+ | |
+ if (pplist == 0 && page_no != 0) { | |
+ if (privdebug && !debug) { | |
+ privdebug = FALSE; | |
+ debug = TRUE; | |
+ } | |
+ return(TRUE); /* no page list, print all pages */ | |
+ } | |
+ if (page_no/8 < pplistmaxsize && (pplist[page_no/8] & 1<<(page_no%8)))… | |
+ if (privdebug && !debug) { | |
+ privdebug = FALSE; | |
+ debug = TRUE; | |
+ } | |
+ return(TRUE); | |
+ } else { | |
+ if (!privdebug && debug) { | |
+ privdebug = TRUE; | |
+ debug = FALSE; | |
+ } | |
+ return(FALSE); | |
+ } | |
+} | |
+ | |
+static int stringhpos, stringvpos; | |
+ | |
+void | |
+startstring(void) { | |
+ if (!in_string) { | |
+ stringhpos = hpos; | |
+ stringvpos = vpos; | |
+ if (pageon()) Bprint(Bstdout, "("); | |
+ in_string = 1; | |
+ } | |
+} | |
+ | |
+void | |
+endstring(void) { | |
+ if (in_string) { | |
+ if (pageon()) Bprint(Bstdout, ") %d %d w\n", stringhpos, strin… | |
+ in_string = 0; | |
+ } | |
+} | |
+ | |
+BOOLEAN | |
+isinstring(void) { | |
+ return(in_string); | |
+} | |
+ | |
+void | |
+startpage(void) { | |
+ ++char_no; | |
+ ++line_no; | |
+ ++page_no; | |
+ if (pageon()) { | |
+ ++pages_printed; | |
+ Bprint(Bstdout, "%s %d %d\n", PAGE, page_no, pages_printed); | |
+ Bprint(Bstdout, "/saveobj save def\n"); | |
+ Bprint(Bstdout, "mark\n"); | |
+ Bprint(Bstdout, "%d pagesetup\n", pages_printed); | |
+ } | |
+} | |
+ | |
+void | |
+endpage(void) { | |
+ endstring(); | |
+ curpostfontid = -1; | |
+ line_no = 0; | |
+ char_no = 0; | |
+ if (pageon()) { | |
+ Bprint(Bstdout, "cleartomark\n"); | |
+ Bprint(Bstdout, "showpage\n"); | |
+ Bprint(Bstdout, "saveobj restore\n"); | |
+ Bprint(Bstdout, "%s %d %d\n", ENDPAGE, page_no, pages_printed); | |
+ } | |
+} | |
+ | |
+/* This was taken from postprint */ | |
+ | |
+int | |
+cat(char *filename) { | |
+ Biobuf *bfile; | |
+ Biobuf *Bfile; | |
+ int n; | |
+ static char buf[Bsize]; | |
+ | |
+ if ((bfile = Bopen(unsharp(filename), OREAD)) == 0) { | |
+ return(1); | |
+ } | |
+ Bfile = bfile; | |
+ while ((n=Bread(Bfile, buf, Bsize)) > 0) { | |
+ if (Bwrite(Bstdout, buf, n) != n) | |
+ break; | |
+ } | |
+ Bterm(Bfile); | |
+ if (n != 0) { | |
+ return(1); | |
+ } | |
+ return(0); | |
+} | |
+extern int debug; | |
+void * | |
+galloc(void *ptr, int size, char *perstr) { | |
+ void *x; | |
+ | |
+ if ((x=realloc(ptr, size)) == 0) { | |
+ perror(perstr); | |
+ exits("malloc"); | |
+ } | |
+ return(x); | |
+} | |
+ | |
+static char *errorstrings[] = { | |
+ {""}, /* NONE */ | |
+ {"WARNING"}, | |
+ {"FATAL"} | |
+}; | |
+ | |
+char *programname; | |
+char *inputfilename = "<stdin>"; | |
+int inputlineno; | |
+ | |
+void | |
+error(int errtype, char *fmt, ...) { | |
+ va_list arg; | |
+ | |
+ Bflush(Bstdout); | |
+ Bflush(Bstderr); | |
+ fprint(2, "%s: %s:%d :%s: ", programname, inputfilename, inputlineno, … | |
+ va_start(arg, fmt); | |
+ vfprint(2, fmt, arg); | |
+ va_end(arg); | |
+ if (errtype == FATAL) | |
+ exits("fatal error"); | |
+} | |
diff --git a/src/cmd/postscript/common/common.h b/src/cmd/postscript/common/com… | |
t@@ -0,0 +1,43 @@ | |
+#define NONE 0 | |
+#define WARNING 1 | |
+#define FATAL 2 | |
+ | |
+#define RUNEGETGROUP(a) ((a>>8)&0xff) | |
+#define RUNEGETCHAR(a) (a&0xff) | |
+ | |
+typedef int BOOLEAN; | |
+ | |
+#define TRUE 1 | |
+#define FALSE 0 | |
+ | |
+#define NUMOFONTS 0x100 | |
+#define FONTSIZE 0x100 | |
+ | |
+extern char *programname; | |
+extern char *inputfilename; | |
+extern int inputlineno; | |
+ | |
+extern int page_no; | |
+extern int pages_printed; | |
+extern int curpostfontid; | |
+extern int hpos, vpos; | |
+ | |
+extern Biobuf *Bstdout, *Bstderr; | |
+ | |
+struct strtab { | |
+ int size; | |
+ char *str; | |
+ int used; | |
+}; | |
+ | |
+extern struct strtab charcode[]; | |
+BOOLEAN pageon(void); | |
+void startstring(void); | |
+void endstring(void); | |
+BOOLEAN isinstring(void); | |
+void startpage(void); | |
+void endpage(void); | |
+int cat(char *); | |
+int Bgetfield(Biobuf *, int, void *, int); | |
+void *galloc(void *, int, char *); | |
+void pagelist(char *); | |
diff --git a/src/cmd/postscript/common/ext.h b/src/cmd/postscript/common/ext.h | |
t@@ -0,0 +1,40 @@ | |
+/* | |
+ * | |
+ * External varibles - most are in glob.c. | |
+ * | |
+ */ | |
+ | |
+extern char **argv; /* global so everyone can us… | |
+extern int argc; | |
+ | |
+extern int x_stat; /* program exit status */ | |
+extern int debug; /* debug flag */ | |
+extern int ignore; /* what we do with FATAL erro… | |
+ | |
+extern long lineno; /* line number */ | |
+extern long position; /* byte position */ | |
+extern char *prog_name; /* and program name - for errors… | |
+extern char *temp_file; /* temporary file - for some pro… | |
+extern char *fontencoding; /* text font encoding scheme … | |
+ | |
+extern int dobbox; /* enable BoundingBox stuff i… | |
+extern double pageheight; /* only for BoundingBox calcul… | |
+extern double pagewidth; | |
+ | |
+extern int reading; /* input */ | |
+extern int writing; /* and output encoding */ | |
+ | |
+extern char *optarg; /* for getopt() */ | |
+extern int optind; | |
+ | |
+extern void interrupt(); | |
+//extern char *tempnam(char*,char*); | |
+/* | |
+ * extern char *malloc(); | |
+ * extern char *calloc(); | |
+ * extern char *strtok(); | |
+ * extern long ftell(); | |
+ * extern double atof(); | |
+ * extern double sqrt(); | |
+ * extern double atan2(); | |
+ */ | |
diff --git a/src/cmd/postscript/common/gen.h b/src/cmd/postscript/common/gen.h | |
t@@ -0,0 +1,65 @@ | |
+/* | |
+ * | |
+ * A few definitions that shouldn't have to change. Used by most programs in | |
+ * this package. | |
+ * | |
+ */ | |
+ | |
+#define PROGRAMVERSION "3.3.2" | |
+ | |
+#define NON_FATAL 0 | |
+#define FATAL 1 | |
+#define USER_FATAL 2 | |
+ | |
+#define OFF 0 | |
+#define ON 1 | |
+ | |
+#define FALSE 0 | |
+#define TRUE 1 | |
+ | |
+#define BYTE 8 | |
+#define BMASK 0377 | |
+ | |
+#define POINTS 72.3 | |
+ | |
+#ifndef PI | |
+#define PI 3.141592654 | |
+#endif | |
+ | |
+#define ONEBYTE 0 | |
+#define UTFENCODING 1 | |
+ | |
+#define READING ONEBYTE | |
+#define WRITING ONEBYTE | |
+ | |
+/* | |
+ * | |
+ * DOROUND controls whether some translators include file ROUNDPAGE (path.h) | |
+ * after the prologue. Used to round page dimensions obtained from the clippath | |
+ * to know paper sizes. Enabled by setting DOROUND to TRUE (or 1). | |
+ * | |
+ */ | |
+ | |
+#define DOROUND TRUE | |
+ | |
+/* | |
+ * | |
+ * Default resolution and the height and width of a page (in case we need to g… | |
+ * to upper left corner) - only used in BoundingBox calculations!! | |
+ * | |
+ */ | |
+ | |
+#define DEFAULT_RES 72 | |
+#define PAGEHEIGHT 11.0 * DEFAULT_RES | |
+#define PAGEWIDTH 8.5 * DEFAULT_RES | |
+ | |
+/* | |
+ * | |
+ * Simple macros. | |
+ * | |
+ */ | |
+ | |
+#define ABS(A) ((A) >= 0 ? (A) : -(A)) | |
+#define MIN(A, B) ((A) < (B) ? (A) : (B)) | |
+#define MAX(A, B) ((A) > (B) ? (A) : (B)) | |
+ | |
diff --git a/src/cmd/postscript/common/getopt.c b/src/cmd/postscript/common/get… | |
t@@ -0,0 +1,56 @@ | |
+#ifndef _POSIX_SOURCE | |
+#include <u.h> | |
+#include <libc.h> | |
+#endif | |
+#include <stdio.h> | |
+#define ERR(str, chr) if(opterr){fprintf(stderr, "%s%s%c\n", argv[0], st… | |
+int opterr = 1; | |
+int optind = 1; | |
+int optopt; | |
+char *optarg; | |
+char *strchr(); | |
+ | |
+int | |
+getopt (argc, argv, opts) | |
+char **argv, *opts; | |
+{ | |
+ static int sp = 1; | |
+ register c; | |
+ register char *cp; | |
+ | |
+ if (sp == 1) | |
+ if (optind >= argc || | |
+ argv[optind][0] != '-' || argv[optind][1] == '\0') | |
+ return EOF; | |
+ else if (strcmp(argv[optind], "--") == NULL) { | |
+ optind++; | |
+ return EOF; | |
+ } | |
+ optopt = c = argv[optind][sp]; | |
+ if (c == ':' || (cp=strchr(opts, c)) == NULL) { | |
+ ERR (": illegal option -- ", c); | |
+ if (argv[optind][++sp] == '\0') { | |
+ optind++; | |
+ sp = 1; | |
+ } | |
+ return '?'; | |
+ } | |
+ if (*++cp == ':') { | |
+ if (argv[optind][sp+1] != '\0') | |
+ optarg = &argv[optind++][sp+1]; | |
+ else if (++optind >= argc) { | |
+ ERR (": option requires an argument -- ", c); | |
+ sp = 1; | |
+ return '?'; | |
+ } else | |
+ optarg = argv[optind++]; | |
+ sp = 1; | |
+ } else { | |
+ if (argv[optind][++sp] == '\0') { | |
+ sp = 1; | |
+ optind++; | |
+ } | |
+ optarg = NULL; | |
+ } | |
+ return c; | |
+} | |
diff --git a/src/cmd/postscript/common/glob.c b/src/cmd/postscript/common/glob.c | |
t@@ -0,0 +1,29 @@ | |
+/* | |
+ * | |
+ * Global varibles - for PostScript translators. | |
+ * | |
+ */ | |
+ | |
+#include <stdio.h> | |
+#include "gen.h" | |
+ | |
+char **argv; /* global so everyone can u… | |
+int argc; | |
+ | |
+int x_stat = 0; /* program exit status */ | |
+int debug = OFF; /* debug flag */ | |
+int ignore = OFF; /* what we do with FATAL error… | |
+ | |
+long lineno = 0; /* line number */ | |
+long position = 0; /* byte position */ | |
+char *prog_name = ""; /* and program name - for errors */ | |
+char *temp_file = NULL; /* temporary file - for some pro… | |
+char *fontencoding = NULL; /* text font encoding scheme … | |
+ | |
+int dobbox = FALSE; /* enable BoundingBox stuff … | |
+double pageheight = PAGEHEIGHT; /* only for BoundingBox calculat… | |
+double pagewidth = PAGEWIDTH; | |
+ | |
+int reading = UTFENCODING; /* input */ | |
+int writing = WRITING; /* and output encoding */ | |
+ | |
diff --git a/src/cmd/postscript/common/misc.c b/src/cmd/postscript/common/misc.c | |
t@@ -0,0 +1,230 @@ | |
+/* | |
+ * | |
+ * General purpose routines. | |
+ * | |
+ */ | |
+ | |
+#include <stdio.h> | |
+#include <ctype.h> | |
+#include <sys/types.h> | |
+#include <fcntl.h> | |
+ | |
+#include "gen.h" | |
+#include "ext.h" | |
+#include "path.h" | |
+ | |
+int nolist = 0; /* number of specified ranges */ | |
+int olist[50]; /* processing range pairs */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+out_list(str) | |
+ | |
+ char *str; | |
+ | |
+{ | |
+ | |
+ int start, stop; | |
+ | |
+/* | |
+ * | |
+ * Grab page ranges from str, save them in olist[], and update the nolist | |
+ * count. Range syntax matches nroff/troff syntax. | |
+ * | |
+ */ | |
+ | |
+ while ( *str && nolist < sizeof(olist) - 2 ) { | |
+ start = stop = str_convert(&str, 0); | |
+ | |
+ if ( *str == '-' && *str++ ) | |
+ stop = str_convert(&str, 9999); | |
+ | |
+ if ( start > stop ) | |
+ error(FATAL, "illegal range %d-%d", start, stop); | |
+ | |
+ olist[nolist++] = start; | |
+ olist[nolist++] = stop; | |
+ | |
+ if ( *str != '\0' ) str++; | |
+ } /* End while */ | |
+ | |
+ olist[nolist] = 0; | |
+ | |
+} /* End of out_list */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+in_olist(num) | |
+ | |
+ int num; | |
+ | |
+{ | |
+ | |
+ int i; | |
+ | |
+/* | |
+ * | |
+ * Return ON if num is in the current page range list. Print everything if | |
+ * there's no list. | |
+ * | |
+ */ | |
+ if ( nolist == 0 ) | |
+ return(ON); | |
+ | |
+ for ( i = 0; i < nolist; i += 2 ) | |
+ if ( num >= olist[i] && num <= olist[i+1] ) | |
+ return(ON); | |
+ | |
+ return(OFF); | |
+ | |
+} /* End of in_olist */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+setencoding(name) | |
+ | |
+ char *name; | |
+ | |
+{ | |
+ | |
+ char path[150]; | |
+ | |
+/* | |
+ * | |
+ * Include the font encoding file selected by name. It's a full pathname if | |
+ * it begins with /, otherwise append suffix ".enc" and look for the file in | |
+ * ENCODINGDIR. Missing files are silently ignored. | |
+ * | |
+ */ | |
+ | |
+ if ( name == NULL ) | |
+ name = "Default"; | |
+ | |
+ if ( *name == '/' ) | |
+ strcpy(path, name); | |
+ else sprintf(path, "%s/%s.enc", ENCODINGDIR, name); | |
+ | |
+ if ( cat(path) == TRUE ) | |
+ writing = strncmp(name, "UTF", 3) == 0; | |
+ | |
+} /* End of setencoding */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+cat(file) | |
+ | |
+ char *file; | |
+ | |
+{ | |
+ | |
+ int fd_in; | |
+ int fd_out; | |
+ char buf[512]; | |
+ int count; | |
+ | |
+/* | |
+ * | |
+ * Copy *file to stdout. Return FALSE is there was a problem. | |
+ * | |
+ */ | |
+ | |
+ fflush(stdout); | |
+ | |
+ if ( (fd_in = open(file, O_RDONLY)) == -1 ) | |
+ return(FALSE); | |
+ | |
+ fd_out = fileno(stdout); | |
+ while ( (count = read(fd_in, buf, sizeof(buf))) > 0 ) | |
+ write(fd_out, buf, count); | |
+ | |
+ close(fd_in); | |
+ | |
+ return(TRUE); | |
+ | |
+} /* End of cat */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+str_convert(str, err) | |
+ | |
+ char **str; | |
+ int err; | |
+ | |
+{ | |
+ | |
+ int i; | |
+ | |
+/* | |
+ * | |
+ * Grab the next integer from **str and return its value or err if *str | |
+ * isn't an integer. *str is modified after each digit is read. | |
+ * | |
+ */ | |
+ | |
+ if ( ! isdigit(**str) ) | |
+ return(err); | |
+ | |
+ for ( i = 0; isdigit(**str); *str += 1 ) | |
+ i = 10 * i + **str - '0'; | |
+ | |
+ return(i); | |
+ | |
+} /* End of str_convert */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+error(kind, mesg, a1, a2, a3) | |
+ | |
+ int kind; | |
+ char *mesg; | |
+ unsigned a1, a2, a3; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Print an error message and quit if kind is FATAL. | |
+ * | |
+ */ | |
+ | |
+ if ( mesg != NULL && *mesg != '\0' ) { | |
+ fprintf(stderr, "%s: ", prog_name); | |
+ fprintf(stderr, mesg, a1, a2, a3); | |
+ if ( lineno > 0 ) | |
+ fprintf(stderr, " (line %d)", lineno); | |
+ if ( position > 0 ) | |
+ fprintf(stderr, " (near byte %d)", position); | |
+ putc('\n', stderr); | |
+ } /* End if */ | |
+ | |
+ if ( kind == FATAL && ignore == OFF ) { | |
+ if ( temp_file != NULL ) | |
+ unlink(temp_file); | |
+ exit(x_stat | 01); | |
+ } /* End if */ | |
+ | |
+} /* End of error */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+void interrupt(sig) | |
+ | |
+ int sig; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Signal handler for translators. | |
+ * | |
+ */ | |
+ | |
+ if ( temp_file != NULL ) | |
+ unlink(temp_file); | |
+ | |
+ exit(1); | |
+ | |
+} /* End of interrupt */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
diff --git a/src/cmd/postscript/common/mkfile b/src/cmd/postscript/common/mkfile | |
t@@ -0,0 +1,23 @@ | |
+<$PLAN9/src/mkhdr | |
+ | |
+<../config | |
+ | |
+LIB=com.a | |
+OFILES=bbox.$O\ | |
+ glob.$O\ | |
+ misc.$O\ | |
+ request.$O\ | |
+ rune.$O\ | |
+ tempnam.$O\ | |
+ getopt.$O\ | |
+ | |
+HFILES=comments.h\ | |
+ gen.h\ | |
+ ext.h\ | |
+ request.h\ | |
+ path.h\ | |
+ rune.h\ | |
+ | |
+<$PLAN9/src/mklib | |
+ | |
+CFLAGS=-c -D$SYSTEM -D_POSIX_SOURCE | |
diff --git a/src/cmd/postscript/common/path.h b/src/cmd/postscript/common/path.h | |
t@@ -0,0 +1,32 @@ | |
+/* | |
+ * | |
+ * pathname definitions for important files and directories. | |
+ * | |
+ */ | |
+ | |
+#define DPOST "#9/sys/lib/postscript/prologues/dpost.ps" | |
+#define POSTBGI "#9/sys/lib/postscript/prologues/postbgi.ps" | |
+#define POSTDAISY "#9/sys/lib/postscript/prologues/postdaisy.ps" | |
+#define POSTDMD "#9/sys/lib/postscript/prologues/postdmd.ps" | |
+#define POSTMD "#9/sys/lib/postscript/prologues/postmd.ps" | |
+#define POSTPLOT "#9/sys/lib/postscript/prologues/postplot.ps" | |
+#define POSTPRINT "#9/sys/lib/postscript/prologues/postprint.ps" | |
+#define POSTNPRINT "#9/sys/lib/postscript/prologues/postnprint.ps" | |
+#define POSTTEK "#9/sys/lib/postscript/prologues/posttek.ps" | |
+#define POSTGIF "#9/sys/lib/postscript/prologues/postgif.ps" | |
+ | |
+#define BASELINE "#9/sys/lib/postscript/prologues/baseline.ps" | |
+#define COLOR "#9/sys/lib/postscript/prologues/color.ps" | |
+#define DRAW "#9/sys/lib/postscript/prologues/draw.ps" | |
+#define FORMFILE "#9/sys/lib/postscript/prologues/forms.ps" | |
+#define SHADEFILE "#9/sys/lib/postscript/prologues/shade.ps" | |
+#define KERNING "#9/sys/lib/postscript/prologues/kerning.ps" | |
+#define REQUESTFILE "#9/sys/lib/postscript/prologues/ps.requests" | |
+#define ROUNDPAGE "#9/sys/lib/postscript/prologues/roundpage.ps" | |
+ | |
+#define ENCODINGDIR "#9/sys/lib/postscript/prologues" | |
+#define HOSTDIR "#9/sys/lib/postscript/font" | |
+#define FONTDIR "#9/sys/lib/troff/font" | |
+#define POSTLIBDIR "#9/sys/lib/postscript/prologues" | |
+#define TEMPDIR "/tmp" | |
+ | |
diff --git a/src/cmd/postscript/common/request.c b/src/cmd/postscript/common/re… | |
t@@ -0,0 +1,119 @@ | |
+/* | |
+ * | |
+ * Things used to handle special requests (eg. manual feed) globally or on a p… | |
+ * page basis. Requests are passed through to the translator using the -R opti… | |
+ * The argument to -R can be "request", "request:page", or "request:page:file". | |
+ * If page is omitted (as in the first form) or set to 0 request will be appli… | |
+ * to the global environment. In all other cases it applies only to the select… | |
+ * page. If a file is given, page must be supplied, and the lookup is in that … | |
+ * rather than *requestfile. | |
+ * | |
+ */ | |
+ | |
+#include <stdio.h> | |
+ | |
+#include "gen.h" /* general purpose definitions */ | |
+#include "request.h" /* a few special definitions */ | |
+#include "path.h" /* for the default request file */ | |
+ | |
+Request request[MAXREQUEST]; /* next page or global requ… | |
+int nextreq = 0; /* goes in request[nextreq] */ | |
+char *requestfile = REQUESTFILE; /* default lookup file */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+saverequest(want) | |
+ | |
+ char *want; /* grab code for this stuff */ | |
+ | |
+{ | |
+ | |
+ char *page; /* and save it for this page */ | |
+ char *strtok(); | |
+ | |
+/* | |
+ * | |
+ * Save the request until we get to appropriate page - don't even bother with | |
+ * the lookup right now. Format of *want string is "request", "request:page", … | |
+ * "request:page:file", and we assume we can change the string here as needed. | |
+ * If page is omitted or given as 0 the request will be done globally. If *want | |
+ * includes a file, request and page must also be given, and in that case *file | |
+ * will be used for the lookup. | |
+ * | |
+ */ | |
+ | |
+ if ( nextreq < MAXREQUEST ) { | |
+ request[nextreq].want = strtok(want, ": "); | |
+ if ( (page = strtok(NULL, ": ")) == NULL ) | |
+ request[nextreq].page = 0; | |
+ else request[nextreq].page = atoi(page); | |
+ if ( (request[nextreq].file = strtok(NULL, ": ")) == NULL ) | |
+ request[nextreq].file = requestfile; | |
+ nextreq++; | |
+ } else error(NON_FATAL, "too many requests - ignoring %s", want); | |
+ | |
+} /* End of saverequest */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+writerequest(page, fp_out) | |
+ | |
+ int page; /* write everything for th… | |
+ FILE *fp_out; /* to this file */ | |
+ | |
+{ | |
+ | |
+ int i; /* loop index */ | |
+ | |
+/* | |
+ * | |
+ * Writes out all the requests that have been saved for page. Page 0 refers to | |
+ * the global environment and is done during initial setup. | |
+ * | |
+ */ | |
+ | |
+ for ( i = 0; i < nextreq; i++ ) | |
+ if ( request[i].page == page ) | |
+ dumprequest(request[i].want, request[i].file, fp_out); | |
+ | |
+} /* End of writerequest */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+dumprequest(want, file, fp_out) | |
+ | |
+ char *want; /* look for this string */ | |
+ char *file; /* in this file */ | |
+ FILE *fp_out; /* and write the value out here */ | |
+ | |
+{ | |
+ | |
+ char buf[100]; /* line buffer for reading *file */ | |
+ FILE *fp_in; | |
+ | |
+/* | |
+ * | |
+ * Looks for *want in the request file and if it's found the associated value | |
+ * is copied to the output file. Keywords (ie. the *want strings) begin an @ in | |
+ * the first column of file, while the values (ie. the stuff that's copied to | |
+ * the output file) starts on the next line and extends to the next keyword or | |
+ * to the end of file. | |
+ * | |
+ */ | |
+ | |
+ if ( (fp_in = fopen(file, "r")) != NULL ) { | |
+ while ( fgets(buf, sizeof(buf), fp_in) != NULL ) | |
+ if ( buf[0] == '@' && strncmp(want, &buf[1], strlen(want)) == 0 ) | |
+ while ( fgets(buf, sizeof(buf), fp_in) != NULL ) | |
+ if ( buf[0] == '#' || buf[0] == '%' ) | |
+ continue; | |
+ else if ( buf[0] != '@' ) | |
+ fprintf(fp_out, "%s", buf); | |
+ else break; | |
+ fclose(fp_in); | |
+ } /* End if */ | |
+ | |
+} /* End of dumprequest */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
diff --git a/src/cmd/postscript/common/request.h b/src/cmd/postscript/common/re… | |
t@@ -0,0 +1,22 @@ | |
+/* | |
+ * | |
+ * Things used to handle special PostScript requests (like manual feed) global… | |
+ * or on a per page basis. All the translators I've supplied accept the -R opt… | |
+ * that can be used to insert special PostScript code before the global setup … | |
+ * done, or at the start of named pages. The argument to the -R option is a st… | |
+ * that can be "request", "request:page", or "request:page:file". If page isn't | |
+ * given (as in the first form) or if it's 0 in the last two, the request appl… | |
+ * to the global environment, otherwise request holds only for the named page. | |
+ * If a file name is given a page number must be supplied, and in that case the | |
+ * request will be looked up in that file. | |
+ * | |
+ */ | |
+ | |
+#define MAXREQUEST 30 | |
+ | |
+typedef struct { | |
+ char *want; | |
+ int page; | |
+ char *file; | |
+} Request; | |
+ | |
diff --git a/src/cmd/postscript/common/rune.c b/src/cmd/postscript/common/rune.c | |
t@@ -0,0 +1,142 @@ | |
+#include "rune.h" | |
+ | |
+enum | |
+{ | |
+ Bit1 = 7, | |
+ Bitx = 6, | |
+ Bit2 = 5, | |
+ Bit3 = 4, | |
+ Bit4 = 3, | |
+ | |
+ T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ | |
+ Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ | |
+ T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ | |
+ T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ | |
+ T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ | |
+ | |
+ Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 … | |
+ Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 … | |
+ Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 … | |
+ | |
+ Maskx = (1<<Bitx)-1, /* 0011 1111 */ | |
+ Testx = Maskx ^ 0xFF, /* 1100 0000 */ | |
+ | |
+ Bad = Runeerror, | |
+}; | |
+ | |
+int | |
+chartorune(Rune *rune, char *str) | |
+{ | |
+ int c, c1, c2; | |
+ long l; | |
+ | |
+ /* | |
+ * one character sequence | |
+ * 00000-0007F => T1 | |
+ */ | |
+ c = *(unsigned char*)str; | |
+ if(c < Tx) { | |
+ *rune = c; | |
+ return 1; | |
+ } | |
+ | |
+ /* | |
+ * two character sequence | |
+ * 0080-07FF => T2 Tx | |
+ */ | |
+ c1 = *(unsigned char*)(str+1) ^ Tx; | |
+ if(c1 & Testx) | |
+ goto bad; | |
+ if(c < T3) { | |
+ if(c < T2) | |
+ goto bad; | |
+ l = ((c << Bitx) | c1) & Rune2; | |
+ if(l <= Rune1) | |
+ goto bad; | |
+ *rune = l; | |
+ return 2; | |
+ } | |
+ | |
+ /* | |
+ * three character sequence | |
+ * 0800-FFFF => T3 Tx Tx | |
+ */ | |
+ c2 = *(unsigned char*)(str+2) ^ Tx; | |
+ if(c2 & Testx) | |
+ goto bad; | |
+ if(c < T4) { | |
+ l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; | |
+ if(l <= Rune2) | |
+ goto bad; | |
+ *rune = l; | |
+ return 3; | |
+ } | |
+ | |
+ /* | |
+ * bad decoding | |
+ */ | |
+bad: | |
+ *rune = Bad; | |
+ return 1; | |
+} | |
+ | |
+int | |
+runetochar(char *str, Rune *rune) | |
+{ | |
+ long c; | |
+ | |
+ /* | |
+ * one character sequence | |
+ * 00000-0007F => 00-7F | |
+ */ | |
+ c = *rune; | |
+ if(c <= Rune1) { | |
+ str[0] = c; | |
+ return 1; | |
+ } | |
+ | |
+ /* | |
+ * two character sequence | |
+ * 0080-07FF => T2 Tx | |
+ */ | |
+ if(c <= Rune2) { | |
+ str[0] = T2 | (c >> 1*Bitx); | |
+ str[1] = Tx | (c & Maskx); | |
+ return 2; | |
+ } | |
+ | |
+ /* | |
+ * three character sequence | |
+ * 0800-FFFF => T3 Tx Tx | |
+ */ | |
+ str[0] = T3 | (c >> 2*Bitx); | |
+ str[1] = Tx | ((c >> 1*Bitx) & Maskx); | |
+ str[2] = Tx | (c & Maskx); | |
+ return 3; | |
+} | |
+ | |
+int | |
+runelen(long c) | |
+{ | |
+ Rune rune; | |
+ char str[10]; | |
+ | |
+ rune = c; | |
+ return runetochar(str, &rune); | |
+} | |
+ | |
+int | |
+fullrune(char *str, int n) | |
+{ | |
+ int c; | |
+ | |
+ if(n > 0) { | |
+ c = *(unsigned char*)str; | |
+ if(c < Tx) | |
+ return 1; | |
+ if(n > 1) | |
+ if(c < T3 || n > 2) | |
+ return 1; | |
+ } | |
+ return 0; | |
+} | |
diff --git a/src/cmd/postscript/common/rune.h b/src/cmd/postscript/common/rune.h | |
t@@ -0,0 +1,19 @@ | |
+/* | |
+ * | |
+ * Rune declarations - for supporting UTF encoding. | |
+ * | |
+ */ | |
+ | |
+#define RUNELIB 1 | |
+ | |
+#ifdef RUNELIB | |
+typedef unsigned short Rune; | |
+ | |
+enum | |
+{ | |
+ UTFmax = 3, /* maximum bytes per rune */ | |
+ Runesync = 0x80, /* cannot represent part of a u… | |
+ Runeself = 0x80, /* rune and utf sequences are t… | |
+ Runeerror = 0x80, /* decoding error in utf */ | |
+}; | |
+#endif | |
diff --git a/src/cmd/postscript/common/tempnam.c b/src/cmd/postscript/common/te… | |
t@@ -0,0 +1,27 @@ | |
+#include <stdio.h> | |
+#include <errno.h> | |
+ | |
+#if defined(V9) || defined(BSD4_2) || defined(plan9) | |
+char *tempnam(char *dir, char *pfx) { | |
+ int pid; | |
+ unsigned int len; | |
+ char *tnm, *malloc(); | |
+ static int seq = 0; | |
+ | |
+ pid = getpid(); | |
+ len = strlen(dir) + strlen(pfx) + 10; | |
+ if ((tnm = malloc(len)) != NULL) { | |
+ sprintf(tnm, "%s", dir); | |
+ if (access(tnm, 7) == -1) | |
+ return(NULL); | |
+ do { | |
+ sprintf(tnm, "%s/%s%d%d", dir, pfx, pid, seq++); | |
+ errno = 0; | |
+ if (access(tnm, 7) == -1) | |
+ if (errno == ENOENT) | |
+ return(tnm); | |
+ } while (1); | |
+ } | |
+ return(tnm); | |
+} | |
+#endif | |
diff --git a/src/cmd/postscript/download/README b/src/cmd/postscript/download/R… | |
t@@ -0,0 +1,11 @@ | |
+ | |
+A simple program that scans PostScript files for %%DocumentFonts: | |
+comments and prepends requested host resident font files to the | |
+input. Written for Unix 4.0 lp. | |
+ | |
+Downloaded fonts are the ones named in the %%DocumentFonts: comment | |
+and listed in a special map file (which can be selected using the | |
+-m option). See example.map and comments in download.c for examples | |
+of map files. By default map files and font files are in *hostfontdir. | |
+It's initialized using HOSTDIR (file ../common/path.h). | |
+ | |
diff --git a/src/cmd/postscript/download/download.c b/src/cmd/postscript/downlo… | |
t@@ -0,0 +1,545 @@ | |
+/* | |
+ * | |
+ * download - host resident font downloader | |
+ * | |
+ * Prepends host resident fonts to PostScript input files. The program assumes | |
+ * the input files are part of a single PostScript job and that requested fonts | |
+ * can be downloaded at the start of each input file. Downloaded fonts are the | |
+ * ones named in a %%DocumentFonts: comment and listed in a special map table. | |
+ * Map table pathnames (supplied using the -m option) that begin with a / are | |
+ * taken as is. Otherwise the final pathname is built using *hostfontdir (-H | |
+ * option), *mapname (-m option), and *suffix. | |
+ * | |
+ * The map table consists of fontname-filename pairs, separated by white space. | |
+ * Comments are introduced by % (as in PostScript) and extend to the end of the | |
+ * current line. The only fonts that can be downloaded are the ones listed in | |
+ * the active map table that point the program to a readable Unix file. A requ… | |
+ * for an unlisted font or inaccessible file is ignored. All font requests are | |
+ * ignored if the map table can't be read. In that case the program simply cop… | |
+ * the input files to stdout. | |
+ * | |
+ * An example (but not one to follow) of what can be in a map table is, | |
+ * | |
+ * % | |
+ * % Map requests for Bookman-Light to file *hostfontdir/KR | |
+ * % | |
+ * | |
+ * Bookman-Light KR % Keeping everything (inclu… | |
+ * % table) in *hostfontdir seems like … | |
+ * % cleanest approach. | |
+ * | |
+ * % | |
+ * % Map Palatino-Roman to file *hostfontdir/palatino/Roman | |
+ * % | |
+ * Palatino-Roman palatino/Roman | |
+ * | |
+ * % Map ZapfDingbats to file /usr/lib/host/dingbats | |
+ * | |
+ * ZapfDingbats /usr/lib/host/dingbats | |
+ * | |
+ * Once again, file names that begin with a / are taken as is. All others have | |
+ * *hostfontdir/ prepended to the file string associated with a particular fon… | |
+ * | |
+ * Map table can be associated with a printer model (e.g. a LaserWriter), a | |
+ * printer destination, or whatever - the choice is up to an administrator. | |
+ * By destination may be best if your spooler is running several private | |
+ * printers. Host resident fonts are usually purchased under a license that | |
+ * restricts their use to a limited number of printers. A font licensed for | |
+ * a single printer should only be used on that printer. | |
+ * | |
+ * Was written quickly, so there's much room for improvement. Undoubtedly shou… | |
+ * be a more general program (e.g. scan for other comments). | |
+ * | |
+ */ | |
+ | |
+#include <stdio.h> | |
+#include <signal.h> | |
+#include <sys/types.h> | |
+#include <fcntl.h> | |
+#include <sys/stat.h> | |
+#include <string.h> | |
+ | |
+#include "comments.h" /* PostScript file structuring co… | |
+#include "gen.h" /* general purpose definitions */ | |
+#include "path.h" /* for temporary directory */ | |
+#include "ext.h" /* external variable declarations */ | |
+#include "download.h" /* a few special definitions */ | |
+ | |
+char *temp_dir = TEMPDIR; /* temp directory - for copyin… | |
+char *hostfontdir = HOSTDIR; /* host resident directory … | |
+char *mapname = "map"; /* map table - usually in *hostfo… | |
+char *suffix = ""; /* appended to the map table … | |
+Map *map = NULL; /* device font map table */ | |
+char *stringspace = NULL; /* for storing font and file s… | |
+int next = 0; /* next free slot in map[] */ | |
+ | |
+char *residentfonts = NULL; /* list of printer resident … | |
+char *printer = NULL; /* printer name - only for Unix 4.… | |
+ | |
+char buf[2048]; /* input file line buffer */ | |
+char *comment = DOCUMENTFONTS; /* look for this comment */ | |
+int atend = FALSE; /* TRUE only if a comment say… | |
+ | |
+FILE *fp_in; /* next input file */ | |
+FILE *fp_temp = NULL; /* for copying stdin */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+main(agc, agv) | |
+ | |
+ int agc; | |
+ char *agv[]; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Host resident font downloader. The input files are assumed to be part of a | |
+ * single PostScript job. | |
+ * | |
+ */ | |
+ | |
+ fp_in = stdin; | |
+ | |
+ argc = agc; /* other routines may want them… | |
+ argv = agv; | |
+ | |
+ prog_name = argv[0]; /* just for error messages */ | |
+ | |
+ init_signals(); /* sets up interrupt handling */ | |
+ options(); /* first get command line option… | |
+ readmap(); /* read the font map table */ | |
+ readresident(); /* and the optional resident font l… | |
+ arguments(); /* then process non-option arguments */ | |
+ done(); /* and clean things up */ | |
+ exit(x_stat); /* not much could be wrong */ | |
+ | |
+} /* End of main */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+init_signals() | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Makes sure we handle interrupts properly. | |
+ * | |
+ */ | |
+ | |
+ if ( signal(SIGINT, interrupt) == SIG_IGN ) { | |
+ signal(SIGINT, SIG_IGN); | |
+ signal(SIGQUIT, SIG_IGN); | |
+ signal(SIGHUP, SIG_IGN); | |
+ } else { | |
+ signal(SIGHUP, interrupt); | |
+ signal(SIGQUIT, interrupt); | |
+ } /* End else */ | |
+ | |
+ signal(SIGTERM, interrupt); | |
+ | |
+} /* End of init_signals */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+options() | |
+ | |
+{ | |
+ | |
+ int ch; /* return value from getopt(… | |
+ char *optnames = "c:fm:p:r:H:T:DI"; | |
+ | |
+ extern char *optarg; /* used by getopt() */ | |
+ extern int optind; | |
+ | |
+/* | |
+ * | |
+ * Reads and processes the command line options. | |
+ * | |
+ */ | |
+ | |
+ while ( (ch = getopt(argc, argv, optnames)) != EOF ) { | |
+ switch ( ch ) { | |
+ case 'c': /* look for this comment */ | |
+ comment = optarg; | |
+ break; | |
+ | |
+ case 'f': /* force a complete input file sc… | |
+ atend = TRUE; | |
+ break; | |
+ | |
+ case 'm': /* printer map table name */ | |
+ mapname = optarg; | |
+ break; | |
+ | |
+ case 'p': /* printer name - for Unix 4.0 lp… | |
+ printer = optarg; | |
+ break; | |
+ | |
+ case 'r': /* resident font list */ | |
+ residentfonts = optarg; | |
+ break; | |
+ | |
+ case 'H': /* host resident font directory */ | |
+ hostfontdir = optarg; | |
+ break; | |
+ | |
+ case 'T': /* temporary file directory */ | |
+ temp_dir = optarg; | |
+ break; | |
+ | |
+ case 'D': /* debug flag */ | |
+ debug = ON; | |
+ break; | |
+ | |
+ case 'I': /* ignore FATAL errors */ | |
+ ignore = ON; | |
+ break; | |
+ | |
+ case '?': /* don't understand the option */ | |
+ error(FATAL, ""); | |
+ break; | |
+ | |
+ default: /* don't know what to do for ch */ | |
+ error(FATAL, "missing case for option %c\n", ch); | |
+ break; | |
+ } /* End switch */ | |
+ } /* End while */ | |
+ | |
+ argc -= optind; /* get ready for non-option args */ | |
+ argv += optind; | |
+ | |
+} /* End of options */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+readmap() | |
+ | |
+{ | |
+ | |
+ char *path; | |
+ char *ptr; | |
+ int fd; | |
+ struct stat sbuf; | |
+ | |
+/* | |
+ * | |
+ * Initializes the map table by reading an ASCII mapping file. If mapname begi… | |
+ * with a / it's the map table. Otherwise hostfontdir, mapname, and suffix are | |
+ * combined to build the final pathname. If we can open the file we read it all | |
+ * into memory, erase comments, and separate the font and file name pairs. When | |
+ * we leave next points to the next free slot in the map[] array. If it's zero | |
+ * nothing was in the file or we couldn't open it. | |
+ * | |
+ */ | |
+ | |
+ if ( hostfontdir == NULL || mapname == NULL ) | |
+ return; | |
+ | |
+ if ( *mapname != '/' ) { | |
+ if ( (path = (char *)malloc(strlen(hostfontdir) + strlen(mapname) + | |
+ strlen(suffix) + 2)) == NULL ) | |
+ error(FATAL, "no memory"); | |
+ sprintf(path, "%s/%s%s", hostfontdir, mapname, suffix); | |
+ } else path = mapname; | |
+ | |
+ if ( (fd = open(unsharp(path), 0)) != -1 ) { | |
+ if ( fstat(fd, &sbuf) == -1 ) | |
+ error(FATAL, "can't fstat %s", path); | |
+ if ( (stringspace = (char *)malloc(sbuf.st_size + 2)) == NULL ) | |
+ error(FATAL, "no memory"); | |
+ if ( read(fd, stringspace, sbuf.st_size) == -1 ) | |
+ error(FATAL, "can't read %s", path); | |
+ close(fd); | |
+ | |
+ stringspace[sbuf.st_size] = '\n'; /* just to be safe */ | |
+ stringspace[sbuf.st_size+1] = '\0'; | |
+ for ( ptr = stringspace; *ptr != '\0'; ptr++ ) /* erase comment… | |
+ if ( *ptr == '%' ) | |
+ for ( ; *ptr != '\n' ; ptr++ ) | |
+ *ptr = ' '; | |
+ | |
+ for ( ptr = stringspace; ; next++ ) { | |
+ if ( (next % 50) == 0 ) | |
+ map = allocate(map, next+50); | |
+ map[next].downloaded = FALSE; | |
+ map[next].font = strtok(ptr, " \t\n"); | |
+ map[next].file = strtok(ptr = NULL, " \t\n"); | |
+ if ( map[next].font == NULL ) | |
+ break; | |
+ if ( map[next].file == NULL ) | |
+ error(FATAL, "map table format error - check %s", path); | |
+ } /* End for */ | |
+ } /* End if */ | |
+ | |
+} /* End of readmap */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+readresident() | |
+ | |
+{ | |
+ | |
+ FILE *fp; | |
+ char *path; | |
+ int ch; | |
+ int n; | |
+ | |
+/* | |
+ * | |
+ * Reads a file that lists the resident fonts for a particular printer and mar… | |
+ * each font as already downloaded. Nothing's done if the file can't be read or | |
+ * there's no mapping file. Comments, as in the map file, begin with a % and | |
+ * extend to the end of the line. Added for Unix 4.0 lp. | |
+ * | |
+ */ | |
+ | |
+ if ( next == 0 || (printer == NULL && residentfonts == NULL) ) | |
+ return; | |
+ | |
+ if ( printer != NULL ) { /* use Unix 4.0 lp pathnames */ | |
+ sprintf(buf, "%s/printers/%s", HOSTDIR, printer); | |
+ path = buf; | |
+ } else path = residentfonts; | |
+ | |
+ if ( (fp = fopen(unsharp(path), "r")) != NULL ) { | |
+ while ( fscanf(fp, "%s", buf) != EOF ) | |
+ if ( buf[0] == '%' ) | |
+ while ( (ch = getc(fp)) != EOF && ch != '\n' ) ; | |
+ else if ( (n = lookup(buf)) < next ) | |
+ map[n].downloaded = TRUE; | |
+ fclose(fp); | |
+ } /* End if */ | |
+ | |
+} /* End of readresident */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+arguments() | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Makes sure all the non-option command line arguments are processed. If we g… | |
+ * here and there aren't any arguments left, or if '-' is one of the input fil… | |
+ * we'll translate stdin. Assumes input files are part of a single PostScript | |
+ * job and fonts can be downloaded at the start of each file. | |
+ * | |
+ */ | |
+ | |
+ if ( argc < 1 ) | |
+ download(); | |
+ else { | |
+ while ( argc > 0 ) { | |
+ fp_temp = NULL; | |
+ if ( strcmp(*argv, "-") == 0 ) | |
+ fp_in = stdin; | |
+ else if ( (fp_in = fopen(unsharp(*argv), "r")) == NULL ) | |
+ error(FATAL, "can't open %s", *argv); | |
+ download(); | |
+ if ( fp_in != stdin ) | |
+ fclose(fp_in); | |
+ if ( fp_temp != NULL ) | |
+ fclose(fp_temp); | |
+ argc--; | |
+ argv++; | |
+ } /* End while */ | |
+ } /* End else */ | |
+ | |
+} /* End of arguments */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+done() | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Clean things up before we quit. | |
+ * | |
+ */ | |
+ | |
+ if ( temp_file != NULL ) | |
+ unlink(temp_file); | |
+ | |
+} /* End of done */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+download() | |
+ | |
+{ | |
+ | |
+ int infontlist = FALSE; | |
+ | |
+/* | |
+ * | |
+ * If next is zero the map table is empty and all we do is copy the input file | |
+ * to stdout. Otherwise we read the input file looking for %%DocumentFonts: or | |
+ * continuation comments, add any accessible fonts to the output file, and then | |
+ * append the input file. When reading stdin we append lines to fp_temp and | |
+ * recover them when we're ready to copy the input file. fp_temp will often | |
+ * only contain part of stdin - if there's no %%DocumentFonts: (atend) comment | |
+ * we stop reading fp_in after the header. | |
+ * | |
+ */ | |
+ | |
+ if ( next > 0 ) { | |
+ if ( fp_in == stdin ) { | |
+ if ( (temp_file = tempnam(temp_dir, "post")) == NULL ) | |
+ error(FATAL, "can't generate temp file name"); | |
+ if ( (fp_temp = fopen(temp_file, "w+r")) == NULL ) | |
+ error(FATAL, "can't open %s", temp_file); | |
+ unlink(temp_file); | |
+ } /* End if */ | |
+ | |
+ while ( fgets(buf, sizeof(buf), fp_in) != NULL ) { | |
+ if ( fp_temp != NULL ) | |
+ fprintf(fp_temp, "%s", buf); | |
+ if ( buf[0] != '%' || buf[1] != '%' ) { | |
+ if ( (buf[0] != '%' || buf[1] != '!') && atend == FALSE ) | |
+ break; | |
+ infontlist = FALSE; | |
+ } else if ( strncmp(buf, comment, strlen(comment)) == 0 ) { | |
+ copyfonts(buf); | |
+ infontlist = TRUE; | |
+ } else if ( buf[2] == '+' && infontlist == TRUE ) | |
+ copyfonts(buf); | |
+ else infontlist = FALSE; | |
+ } /* End while */ | |
+ } /* End if */ | |
+ | |
+ copyinput(); | |
+ | |
+} /* End of download */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+copyfonts(list) | |
+ | |
+ char *list; | |
+ | |
+{ | |
+ | |
+ char *font; | |
+ char *path; | |
+ int n; | |
+ | |
+/* | |
+ * | |
+ * list points to a %%DocumentFonts: or continuation comment. What follows the | |
+ * the keyword will be a list of fonts separated by white space (or (atend)). | |
+ * Look for each font in the map table and if it's found copy the font file to | |
+ * stdout (once only). | |
+ * | |
+ */ | |
+ | |
+ strtok(list, " \n"); /* skip to the font list */ | |
+ | |
+ while ( (font = strtok(NULL, " \t\n")) != NULL ) { | |
+ if ( strcmp(font, ATEND) == 0 ) { | |
+ atend = TRUE; | |
+ break; | |
+ } /* End if */ | |
+ if ( (n = lookup(font)) < next ) { | |
+ if ( *map[n].file != '/' ) { | |
+ if ( (path = (char *)malloc(strlen(hostfontdir)+strlen(map[n].… | |
+ error(FATAL, "no memory"); | |
+ sprintf(path, "%s/%s", hostfontdir, map[n].file); | |
+ cat(unsharp(path)); | |
+ free(path); | |
+ } else cat(unsharp(map[n].file)); | |
+ map[n].downloaded = TRUE; | |
+ } /* End if */ | |
+ } /* End while */ | |
+ | |
+} /* End of copyfonts */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+copyinput() | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Copies the input file to stdout. If fp_temp isn't NULL seek to the start and | |
+ * add it to the output file - it's a partial (or complete) copy of stdin made | |
+ * by download(). Then copy fp_in, but only seek to the start if it's not stdi… | |
+ * | |
+ */ | |
+ | |
+ if ( fp_temp != NULL ) { | |
+ fseek(fp_temp, 0L, 0); | |
+ while ( fgets(buf, sizeof(buf), fp_temp) != NULL ) | |
+ printf("%s", buf); | |
+ } /* End if */ | |
+ | |
+ if ( fp_in != stdin ) | |
+ fseek(fp_in, 0L, 0); | |
+ | |
+ while ( fgets(buf, sizeof(buf), fp_in) != NULL ) | |
+ printf("%s", buf); | |
+ | |
+} /* End of copyinput */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+lookup(font) | |
+ | |
+ char *font; | |
+ | |
+{ | |
+ | |
+ int i; | |
+ | |
+/* | |
+ * | |
+ * Looks for *font in the map table. Return the map table index if found and | |
+ * not yet downloaded - otherwise return next. | |
+ * | |
+ */ | |
+ | |
+ for ( i = 0; i < next; i++ ) | |
+ if ( strcmp(font, map[i].font) == 0 ) { | |
+ if ( map[i].downloaded == TRUE ) | |
+ i = next; | |
+ break; | |
+ } /* End if */ | |
+ | |
+ return(i); | |
+ | |
+} /* End of lookup */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+Map *allocate(ptr, num) | |
+ | |
+ Map *ptr; | |
+ int num; | |
+ | |
+{ | |
+ | |
+/* | |
+ * | |
+ * Allocates space for num Map elements. Calls malloc() if ptr is NULL and | |
+ * realloc() otherwise. | |
+ * | |
+ */ | |
+ | |
+ if ( ptr == NULL ) | |
+ ptr = (Map *)malloc(num * sizeof(Map)); | |
+ else ptr = (Map *)realloc(ptr, num * sizeof(Map)); | |
+ | |
+ if ( ptr == NULL ) | |
+ error(FATAL, "no map memory"); | |
+ | |
+ return(ptr); | |
+ | |
+} /* End of allocate */ | |
+ | |
+/*****************************************************************************/ | |
+ | |
diff --git a/src/cmd/postscript/download/download.h b/src/cmd/postscript/downlo… | |
t@@ -0,0 +1,14 @@ | |
+/* | |
+ * | |
+ * The font data for a printer is saved in an array of the following type. | |
+ * | |
+ */ | |
+ | |
+typedef struct map { | |
+ char *font; /* a request for this PostScript fon… | |
+ char *file; /* means copy this unix file */ | |
+ int downloaded; /* TRUE after *file is downloaded */ | |
+} Map; | |
+ | |
+Map *allocate(); | |
+ | |
diff --git a/src/cmd/postscript/download/mkfile b/src/cmd/postscript/download/m… | |
t@@ -0,0 +1,25 @@ | |
+<$PLAN9/src/mkhdr | |
+ | |
+<../config | |
+TARG=psdownload | |
+ | |
+OFILES=download.$O | |
+ | |
+COMMONDIR=../common | |
+ | |
+HFILES=download.h\ | |
+ $COMMONDIR/comments.h\ | |
+ $COMMONDIR/gen.h\ | |
+ $COMMONDIR/path.h\ | |
+ $COMMONDIR/ext.h\ | |
+ | |
+LIB=$COMMONDIR/com.a | |
+BIN=$POSTBIN | |
+ | |
+<$PLAN9/src/mkone | |
+CFLAGS=-c -D$SYSTEM -D_POSIX_SOURCE -I$COMMONDIR | |
+ | |
+$LIB: | |
+ cd $COMMONDIR | |
+ mk install | |
+ mk clean | |
diff --git a/src/cmd/postscript/mkfile b/src/cmd/postscript/mkfile | |
t@@ -0,0 +1,25 @@ | |
+<$PLAN9/src/mkhdr | |
+ | |
+<config | |
+ | |
+DIRS=\ | |
+ common\ | |
+ tr2post\ | |
+ download\ | |
+# cropmarks\ | |
+# grabit\ | |
+# hardcopy\ | |
+# mpictures\ | |
+# postgif\ | |
+# postprint\ | |
+# postreverse\ | |
+# posttek\ | |
+# printfont\ | |
+# psencoding\ | |
+# psfiles\ | |
+# g3p9bit\ | |
+# p9bitpost\ | |
+# tcpostio\ | |
+# text2post\ | |
+ | |
+<$PLAN9/src/mkdirs | |
diff --git a/src/cmd/postscript/tr2post/Bgetfield.c b/src/cmd/postscript/tr2pos… | |
t@@ -0,0 +1,156 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include "../common/common.h" | |
+#include "tr2post.h" | |
+ | |
+#undef isspace | |
+#define isspace bisspace | |
+ | |
+int | |
+isspace(Rune r) | |
+{ | |
+ return(r==' ' || r=='\t' || r=='\n' || r == '\r' || r=='\f'); | |
+} | |
+ | |
+int | |
+Bskipws(Biobuf *bp) { | |
+ int r; | |
+ char c[UTFmax]; | |
+ int sindex = 0; | |
+ | |
+ /* skip over initial white space */ | |
+ do { | |
+ r = Bgetrune(bp); | |
+ if (r == '\n') inputlineno++; | |
+ sindex++; | |
+ } while (r>=0 && isspace(r)); | |
+ if (r<0) { | |
+ return(-1); | |
+ } else if (!isspace(r)) { | |
+ Bungetrune(bp); | |
+ --sindex; | |
+ } | |
+ return(sindex); | |
+} | |
+ | |
+int | |
+asc2dig(char c, int base) { | |
+ if (c >= '0' && c <= '9') | |
+ if (base == 8 && c > '7') return(-1); | |
+ else return(c - '0'); | |
+ | |
+ if (base == 16) | |
+ if (c >= 'a' && c <= 'f') return(10 + c - 'a'); | |
+ else if (c >= 'A' && c <= 'F') return(10 + c - 'A'); | |
+ | |
+ return(-1); | |
+} | |
+ | |
+/* get a string of type: "d" for decimal integer, "u" for unsigned, | |
+ * "s" for string", "c" for char, | |
+ * return the number of characters gotten for the field. If nothing | |
+ * was gotten and the end of file was reached, a negative value | |
+ * from the Bgetrune is returned. | |
+ */ | |
+ | |
+int | |
+Bgetfield(Biobuf *bp, int type, void *thing, int size) { | |
+ int r; | |
+ Rune R; | |
+ char c[UTFmax]; | |
+ int sindex = 0, i, j, n = 0; | |
+ int negate = 0; | |
+ int base = 10; | |
+ BOOLEAN bailout = FALSE; | |
+ int dig; | |
+ unsigned int u = 0; | |
+ | |
+ /* skip over initial white space */ | |
+ if (Bskipws(bp) < 0) | |
+ return(-1); | |
+ | |
+ switch (type) { | |
+ case 'd': | |
+ while (!bailout && (r = Bgetrune(bp))>=0) { | |
+ switch (sindex++) { | |
+ case 0: | |
+ switch (r) { | |
+ case '-': | |
+ negate = 1; | |
+ continue; | |
+ case '+': | |
+ continue; | |
+ case '0': | |
+ base = 8; | |
+ continue; | |
+ default: | |
+ break; | |
+ } | |
+ break; | |
+ case 1: | |
+ if ((r == 'x' || r == 'X') && base == 8) { | |
+ base = 16; | |
+ continue; | |
+ } | |
+ } | |
+ if ((dig = asc2dig(r, base)) == -1) bailout = TRUE; … | |
+ else n = dig + (n * base); | |
+ } | |
+ if (r < 0) return(-1); | |
+ *(int *)thing = (negate)?-n:n; | |
+ Bungetrune(bp); | |
+ break; | |
+ case 'u': | |
+ while (!bailout && (r = Bgetrune(bp))>=0) { | |
+ switch (sindex++) { | |
+ case 0: | |
+ if (*c == '0') { | |
+ base = 8; | |
+ continue; | |
+ } | |
+ break; | |
+ case 1: | |
+ if ((r == 'x' || r == 'X') && base == 8) { | |
+ base = 16; | |
+ continue; | |
+ } | |
+ } | |
+ if ((dig = asc2dig(r, base)) == -1) bailout = TRUE; … | |
+ else u = dig + (n * base); | |
+ } | |
+ *(int *)thing = u; | |
+ if (r < 0) return(-1); | |
+ Bungetrune(bp); | |
+ break; | |
+ case 's': | |
+ j = 0; | |
+ while ((size>j+UTFmax) && (r = Bgetrune(bp))>=0 && !isspace(r)… | |
+ R = r; | |
+ i = runetochar(&(((char *)thing)[j]), &R); | |
+ j += i; | |
+ sindex++; | |
+ } | |
+ ((char *)thing)[j++] = '\0'; | |
+ if (r < 0) return(-1); | |
+ Bungetrune(bp); | |
+ break; | |
+ case 'r': | |
+ if ((r = Bgetrune(bp))>=0) { | |
+ *(Rune *)thing = r; | |
+ sindex++; | |
+ return(sindex); | |
+ } | |
+ if (r <= 0) return(-1); | |
+ Bungetrune(bp); | |
+ break; | |
+ default: | |
+ return(-2); | |
+ } | |
+ if (r < 0 && sindex == 0) | |
+ return(r); | |
+ else if (bailout && sindex == 1) { | |
+ return(0); | |
+ } else | |
+ return(sindex); | |
+} | |
diff --git a/src/cmd/postscript/tr2post/chartab.c b/src/cmd/postscript/tr2post/… | |
t@@ -0,0 +1,458 @@ | |
+/* Unicode | PostScript | |
+ * start end | offset font name | |
+ * 0x0000 0x00ff 0x00 LucidaSansUnicode00 | |
+ */ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include "common.h" | |
+#include "tr2post.h" | |
+#include "comments.h" | |
+#include "path.h" | |
+ | |
+/* Postscript font names, e.g., `LucidaSansUnicode00' | |
+ * names may only be added because reference to the | |
+ * names is made by indexing into this table. | |
+ */ | |
+static struct pfnament *pfnafontmtab = 0; | |
+static int pfnamcnt = 0; | |
+int curpostfontid = -1; | |
+int curfontsize = -1; | |
+int curtrofffontid = -1; | |
+static int curfontpos = -1; | |
+static int fontheight = 0; | |
+static int fontslant = 0; | |
+ | |
+/* This is troffs mounted font table. It is an anachronism resulting | |
+ * from the design of the APS typesetter. fontmnt is the | |
+ * number of positions available. fontmnt is really 11, but | |
+ * should not be limited. | |
+ */ | |
+int fontmnt = 0; | |
+char **fontmtab; | |
+ | |
+struct troffont *troffontab = 0; | |
+ | |
+int troffontcnt = 0; | |
+ | |
+void | |
+mountfont(int pos, char *fontname) { | |
+ int i; | |
+ | |
+ if (debug) Bprint(Bstderr, "mountfont(%d, %s)\n", pos, fontname); | |
+ if (pos < 0 || pos >= fontmnt) | |
+ error(FATAL, "cannot mount a font at position %d,\n can only … | |
+ pos, fontmnt-1); | |
+ | |
+ i = strlen(fontname); | |
+ fontmtab[pos] = galloc(fontmtab[pos], i+1, "mountfont():fontmtab"); | |
+ strcpy(fontmtab[pos], fontname); | |
+ if (curfontpos == pos) curfontpos = -1; | |
+} | |
+ | |
+void | |
+settrfont(void) { | |
+ if (curfontpos == fontpos) return; | |
+ | |
+ if (fontmtab[fontpos] == 0) | |
+ error(FATAL, "Font at position %d was not initialized, botch!\… | |
+ | |
+ curtrofffontid = findtfn(fontmtab[fontpos], 1); | |
+ if (debug) Bprint(Bstderr, "settrfont()-> curtrofffontid=%d\n", curtro… | |
+ curfontpos = fontpos; | |
+ if (curtrofffontid < 0) { | |
+ int i; | |
+ | |
+ error(WARNING, "fontpos=%d\n", fontpos); | |
+ for (i=0; i<fontmnt; i++) | |
+ if (fontmtab[i] == 0) | |
+ error(WARNING, "fontmtab[%d]=0x0\n", i); | |
+ else | |
+ error(WARNING, "fontmtab[%d]=%s\n", i, fontmta… | |
+ exits("settrfont()"); | |
+ } | |
+} | |
+ | |
+void | |
+setpsfont(int psftid, int fontsize) { | |
+ if (psftid == curpostfontid && fontsize == curfontsize) return; | |
+ if (psftid >= pfnamcnt) | |
+ error(FATAL, "Postscript font index=%d used but not defined, t… | |
+ psftid, pfnamcnt); | |
+ | |
+ endstring(); | |
+ if (pageon()) { | |
+ Bprint(Bstdout, "%d /%s f\n", fontsize, pfnafontmtab[psftid].s… | |
+ if ( fontheight != 0 || fontslant != 0 ) | |
+ Bprint(Bstdout, "%d %d changefont\n", fontslant, (font… | |
+ pfnafontmtab[psftid].used = 1; | |
+ curpostfontid = psftid; | |
+ curfontsize = fontsize; | |
+ } | |
+} | |
+ | |
+/* find index of PostScript font name in table | |
+ * returns -1 if name is not in table | |
+ * If insflg is not zero | |
+ * and the name is not found in the table, insert it. | |
+ */ | |
+int | |
+findpfn(char *fontname, int insflg) { | |
+ char *tp; | |
+ int i; | |
+ | |
+ for (i=0; i<pfnamcnt; i++) { | |
+ if (strcmp(pfnafontmtab[i].str, fontname) == 0) | |
+ return(i); | |
+ } | |
+ if (insflg) { | |
+ tp = galloc(pfnafontmtab, sizeof(struct pfnament)*(pfnamcnt+1)… | |
+ if (tp == 0) | |
+ return(-2); | |
+ pfnafontmtab = (struct pfnament *)tp; | |
+ i = strlen(fontname); | |
+ pfnafontmtab[pfnamcnt].str = galloc(0, i+1, "findpfn():pfnafon… | |
+ strncpy(pfnafontmtab[pfnamcnt].str, fontname, i); | |
+ pfnafontmtab[pfnamcnt].str[i] = '\0'; | |
+ pfnafontmtab[pfnamcnt].used = 0; | |
+ return(pfnamcnt++); | |
+ } | |
+ return(-1); | |
+} | |
+ | |
+char postroffdirname[] = "#9/sys/lib/postscript/troff"; /* "/sy… | |
+char troffmetricdirname[] = "#9/sys/lib/troff/font"; /* "/sys/lib/troff… | |
+ | |
+int | |
+readpsfontdesc(char *fontname, int trindex) { | |
+ static char *filename = 0; | |
+ Biobuf *bfd; | |
+ Biobuf *Bfd; | |
+ int warn = 0, errorflg = 0, line =1, rv; | |
+ int start, end, offset; | |
+ int startfont, endfont, startchar, endchar, i, pfid; | |
+ char psfontnam[128]; | |
+ struct troffont *tp; | |
+ | |
+ if (debug) Bprint(Bstderr, "readpsfontdesc(%s,%d)\n", fontname, trinde… | |
+ filename=galloc(filename, strlen(postroffdirname)+1+strlen(fontname)+1… | |
+ sprint(filename, "%s/%s", postroffdirname, fontname); | |
+ | |
+ bfd = Bopen(unsharp(filename), OREAD); | |
+ if (bfd == 0) { | |
+ error(WARNING, "cannot open file %s\n", filename); | |
+ return(0); | |
+ } | |
+ Bfd = bfd; | |
+ | |
+ do { | |
+ offset = 0; | |
+ if ((rv=Bgetfield(Bfd, 'd', &start, 0)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal start value\n", fil… | |
+ } else if (rv < 0) break; | |
+ if ((rv=Bgetfield(Bfd, 'd', &end, 0)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal end value\n", filen… | |
+ } else if (rv < 0) break; | |
+ if ((rv=Bgetfield(Bfd, 'd', &offset, 0)) < 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal offset value\n", fi… | |
+ } | |
+ if ((rv=Bgetfield(Bfd, 's', psfontnam, 128)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal fontname value\n", … | |
+ } else if (rv < 0) break; | |
+ Brdline(Bfd, '\n'); | |
+ if (!errorflg) { | |
+ struct psfent *psfentp; | |
+ startfont = RUNEGETGROUP(start); | |
+ startchar = RUNEGETCHAR(start); | |
+ endfont = RUNEGETGROUP(end); | |
+ endchar = RUNEGETCHAR(end); | |
+ pfid = findpfn(psfontnam, 1); | |
+ if (startfont != endfont) { | |
+ error(WARNING, "font descriptions must not cro… | |
+ errorflg = 1; | |
+ break; | |
+ } | |
+ tp = &(troffontab[trindex]); | |
+ tp->psfmap = galloc(tp->psfmap, ++(tp->psfmapsize)*siz… | |
+ psfentp = &(tp->psfmap[tp->psfmapsize-1]); | |
+ psfentp->start = start; | |
+ psfentp->end = end; | |
+ psfentp->offset = offset; | |
+ psfentp->psftid = pfid; | |
+ if (debug) { | |
+ Bprint(Bstderr, "\tpsfmap->start=0x%x\n", star… | |
+ Bprint(Bstderr, "\tpsfmap->end=0x%x\n", end); | |
+ Bprint(Bstderr, "\tpsfmap->offset=0x%x\n", off… | |
+ Bprint(Bstderr, "\tpsfmap->pfid=0x%x\n", pfid); | |
+ } | |
+/* | |
+ for (i=startchar; i<=endchar; i++) { | |
+ tp->charent[startfont][i].postfontid = pfid; | |
+ tp->charent[startfont][i].postcharid = i + off… | |
+ } | |
+ */ | |
+ if (debug) { | |
+ Bprint(Bstderr, "%x %x ", start, end); | |
+ if (offset) Bprint(Bstderr, "%x ", offset); | |
+ Bprint(Bstderr, "%s\n", psfontnam); | |
+ } | |
+ line++; | |
+ } | |
+ } while(errorflg != 1); | |
+ Bterm(Bfd); | |
+ return(1); | |
+} | |
+ | |
+int | |
+readtroffmetric(char *fontname, int trindex) { | |
+ static char *filename = 0; | |
+ Biobuf *bfd; | |
+ Biobuf *Bfd; | |
+ int warn = 0, errorflg = 0, line =1, rv; | |
+ struct troffont *tp; | |
+ struct charent **cp; | |
+ char stoken[128], *str; | |
+ int ntoken; | |
+ Rune troffchar, quote; | |
+ int width, flag, charnum, thisfont, thischar; | |
+ BOOLEAN specharflag; | |
+ | |
+ if (debug) Bprint(Bstderr, "readtroffmetric(%s,%d)\n", fontname, trind… | |
+ filename=galloc(filename, strlen(troffmetricdirname)+4+strlen(devname)… | |
+ sprint(filename, "%s/dev%s/%s", troffmetricdirname, devname, fontname); | |
+ | |
+ bfd = Bopen(unsharp(filename), OREAD); | |
+ if (bfd == 0) { | |
+ error(WARNING, "cannot open file %s\n", filename); | |
+ return(0); | |
+ } | |
+ Bfd = bfd; | |
+ do { | |
+ /* deal with the few lines at the beginning of the | |
+ * troff font metric files. | |
+ */ | |
+ if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal token\n", filename,… | |
+ } else if (rv < 0) break; | |
+ if (debug) { | |
+ Bprint(Bstderr, "%s\n", stoken); | |
+ } | |
+ | |
+ if (strcmp(stoken, "name") == 0) { | |
+ if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal token\n", f… | |
+ } else if (rv < 0) break; | |
+ } else if (strcmp(stoken, "named") == 0) { | |
+ Brdline(Bfd, '\n'); | |
+ } else if (strcmp(stoken, "fontname") == 0) { | |
+ if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal token\n", f… | |
+ } else if (rv < 0) break; | |
+ } else if (strcmp(stoken, "spacewidth") == 0) { | |
+ if ((rv=Bgetfield(Bfd, 'd', &ntoken, 0)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal token\n", f… | |
+ } else if (rv < 0) break; | |
+ troffontab[trindex].spacewidth = ntoken; | |
+ thisfont = RUNEGETGROUP(' '); | |
+ thischar = RUNEGETCHAR(' '); | |
+ for (cp = &(troffontab[trindex].charent[thisfont][this… | |
+ if ((*cp)->name) | |
+ if (strcmp((*cp)->name, " ") == 0) | |
+ break; | |
+ | |
+ if (*cp == 0) *cp = galloc(0, sizeof(struct charent), … | |
+ (*cp)->postfontid = thisfont; | |
+ (*cp)->postcharid = thischar; | |
+ (*cp)->troffcharwidth = ntoken; | |
+ (*cp)->name = galloc(0, 2, "readtroffmetric: char name… | |
+ (*cp)->next = 0; | |
+ strcpy((*cp)->name, " "); | |
+ } else if (strcmp(stoken, "special") == 0) { | |
+ troffontab[trindex].special = TRUE; | |
+ } else if (strcmp(stoken, "charset") == 0) { | |
+ line++; | |
+ break; | |
+ } | |
+ if (!errorflg) { | |
+ line++; | |
+ } | |
+ } while(!errorflg && rv>=0); | |
+ while(!errorflg && rv>=0) { | |
+ if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal rune token <0x%x> r… | |
+ } else if (rv < 0) break; | |
+ if (utflen(stoken) > 1) specharflag = TRUE; | |
+ else specharflag = FALSE; | |
+ /* if this character is a quote we have to use the previous ch… | |
+ if ((rv=Bgetfield(Bfd, 'r', "e, 0)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal width or quote toke… | |
+ } else if (rv < 0) break; | |
+ if (quote == '"') { | |
+ /* need some code here */ | |
+ | |
+ goto flush; | |
+ } else { | |
+ Bungetrune(Bfd); | |
+ } | |
+ | |
+ if ((rv=Bgetfield(Bfd, 'd', &width, 0)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal width token <0x%x> … | |
+ } else if (rv < 0) break; | |
+ if ((rv=Bgetfield(Bfd, 'd', &flag, 0)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal flag token <0x%x> r… | |
+ } else if (rv < 0) break; | |
+ if ((rv=Bgetfield(Bfd, 'd', &charnum, 0)) == 0) { | |
+ errorflg = 1; | |
+ error(WARNING, "file %s:%d illegal character number to… | |
+ } else if (rv < 0) break; | |
+flush: | |
+ str = Brdline(Bfd, '\n'); | |
+ /* stash the crap from the end of the line for debugging */ | |
+ if (debug) { | |
+ if (str == 0) { | |
+ Bprint(Bstderr, "premature EOF\n"); | |
+ return(0); | |
+ } | |
+ str[Blinelen(Bfd)-1] = '\0'; | |
+ } | |
+ line++; | |
+ chartorune(&troffchar, stoken); | |
+ if (specharflag) { | |
+ if (debug) | |
+ Bprint(Bstderr, "%s %d %d 0x%x %s # special\n… | |
+ } | |
+ if (strcmp(stoken, "---") == 0) { | |
+ thisfont = RUNEGETGROUP(charnum); | |
+ thischar = RUNEGETCHAR(charnum); | |
+ stoken[0] = '\0'; | |
+ } else { | |
+ thisfont = RUNEGETGROUP(troffchar); | |
+ thischar = RUNEGETCHAR(troffchar); | |
+ } | |
+ for (cp = &(troffontab[trindex].charent[thisfont][thischar]); … | |
+ if ((*cp)->name) { | |
+ if (debug) Bprint(Bstderr, "installing <%s>, f… | |
+ if (strcmp((*cp)->name, stoken) == 0) | |
+ break; | |
+ } | |
+ if (*cp == 0) *cp = galloc(0, sizeof(struct charent), "readtro… | |
+ (*cp)->postfontid = RUNEGETGROUP(charnum); | |
+ (*cp)->postcharid = RUNEGETCHAR(charnum); | |
+ (*cp)->troffcharwidth = width; | |
+ (*cp)->name = galloc(0, strlen(stoken)+1, "readtroffmetric: ch… | |
+ (*cp)->next = 0; | |
+ strcpy((*cp)->name, stoken); | |
+ if (debug) { | |
+ if (specharflag) | |
+ Bprint(Bstderr, "%s", stoken); | |
+ else | |
+ Bputrune(Bstderr, troffchar); | |
+ Bprint(Bstderr, " %d %d 0x%x %s # psfontid=0x%x pscha… | |
+ width, flag, charnum, str, | |
+ (*cp)->postfontid, | |
+ (*cp)->postcharid, | |
+ thisfont, thischar); | |
+ } | |
+ } | |
+ Bterm(Bfd); | |
+ Bflush(Bstderr); | |
+ return(1); | |
+} | |
+ | |
+/* find index of troff font name in table | |
+ * returns -1 if name is not in table | |
+ * returns -2 if it cannot allocate memory | |
+ * returns -3 if there is a font mapping problem | |
+ * If insflg is not zero | |
+ * and the name is not found in the table, insert it. | |
+ */ | |
+int | |
+findtfn(char *fontname, BOOLEAN insflg) { | |
+ struct troffont *tp; | |
+ int i, j; | |
+ | |
+ if (debug) { | |
+ if (fontname==0) fprint(2, "findtfn(0x%x,%d)\n", fontname, ins… | |
+ else fprint(2, "findtfn(%s,%d)\n", fontname, insflg); | |
+ } | |
+ for (i=0; i<troffontcnt; i++) { | |
+ if (troffontab[i].trfontid==0) { | |
+ error(WARNING, "findtfn:troffontab[%d].trfontid=0x%x, … | |
+ i, troffontab[i].trfontid); | |
+ continue; | |
+ } | |
+ if (strcmp(troffontab[i].trfontid, fontname) == 0) | |
+ return(i); | |
+ } | |
+ if (insflg) { | |
+ tp = (struct troffont *)galloc(troffontab, sizeof(struct troff… | |
+ if (tp == 0) | |
+ return(-2); | |
+ troffontab = tp; | |
+ tp = &(troffontab[troffontcnt]); | |
+ i = strlen(fontname); | |
+ tp->trfontid = galloc(0, i+1, "findtfn: trfontid:"); | |
+ | |
+ /* initialize new troff font entry with name and numeric field… | |
+ strncpy(tp->trfontid, fontname, i); | |
+ tp->trfontid[i] = '\0'; | |
+ tp->special = FALSE; | |
+ tp->spacewidth = 0; | |
+ tp->psfmapsize = 0; | |
+ tp->psfmap = 0; | |
+ for (i=0; i<NUMOFONTS; i++) | |
+ for (j=0; j<FONTSIZE; j++) | |
+ tp->charent[i][j] = 0; | |
+ troffontcnt++; | |
+ if (!readtroffmetric(fontname, troffontcnt-1)) | |
+ return(-3); | |
+ if (!readpsfontdesc(fontname, troffontcnt-1)) | |
+ return(-3); | |
+ return(troffontcnt-1); | |
+ } | |
+ return(-1); | |
+} | |
+ | |
+void | |
+finish(void) { | |
+ int i; | |
+ | |
+ Bprint(Bstdout, "%s", TRAILER); | |
+ Bprint(Bstdout, "done\n"); | |
+ Bprint(Bstdout, "%s", DOCUMENTFONTS); | |
+ | |
+ for (i=0; i<pfnamcnt; i++) | |
+ if (pfnafontmtab[i].used) | |
+ Bprint(Bstdout, " %s", pfnafontmtab[i].str); | |
+ Bprint(Bstdout, "\n"); | |
+ | |
+ Bprint(Bstdout, "%s %d\n", PAGES, pages_printed); | |
+ | |
+} | |
+ | |
+/* Set slant to n degrees. Disable slanting if n is 0. */ | |
+void | |
+t_slant(int n) { | |
+ fontslant = n; | |
+ curpostfontid = -1; | |
+} | |
+ | |
+/* Set character height to n points. Disabled if n is 0 or the current size. */ | |
+ | |
+void | |
+t_charht(int n) { | |
+ fontheight = (n == fontsize) ? 0 : n; | |
+ curpostfontid = -1; | |
+} | |
diff --git a/src/cmd/postscript/tr2post/conv.c b/src/cmd/postscript/tr2post/con… | |
t@@ -0,0 +1,100 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include "../common/common.h" | |
+#include "tr2post.h" | |
+ | |
+void | |
+conv(Biobuf *Bp) { | |
+ long c, n; | |
+ int r; | |
+ char special[10]; | |
+ int save; | |
+ | |
+ inputlineno = 1; | |
+ if (debug) Bprint(Bstderr, "conv(Biobuf *Bp=0x%x)\n", Bp); | |
+ while ((r = Bgetrune(Bp)) >= 0) { | |
+/* Bprint(Bstderr, "r=<%c>,0x%x\n", r, r); */ | |
+/* Bflush(Bstderr); */ | |
+ switch (r) { | |
+ case 's': /* set point size */ | |
+ Bgetfield(Bp, 'd', &fontsize, 0); | |
+ break; | |
+ case 'f': /* set font to postion */ | |
+ Bgetfield(Bp, 'd', &fontpos, 0); | |
+ save = inputlineno; | |
+ settrfont(); | |
+ inputlineno = save; /* ugh */ | |
+ break; | |
+ case 'c': /* print rune */ | |
+ r = Bgetrune(Bp); | |
+ runeout(r); | |
+ break; | |
+ case 'C': /* print special character */ | |
+ Bgetfield(Bp, 's', special, 10); | |
+ specialout(special); | |
+ break; | |
+ case 'N': /* print character with numeric value from cu… | |
+ Bgetfield(Bp, 'd', &n, 0); | |
+ break; | |
+ case 'H': /* go to absolute horizontal position */ | |
+ Bgetfield(Bp, 'd', &n, 0); | |
+ hgoto(n); | |
+ break; | |
+ case 'V': /* go to absolute vertical position */ | |
+ Bgetfield(Bp, 'd', &n, 0); | |
+ vgoto(n); | |
+ break; | |
+ case 'h': /* go to relative horizontal position */ | |
+ Bgetfield(Bp, 'd', &n, 0); | |
+ hmot(n); | |
+ break; | |
+ case 'v': /* go to relative vertical position */ | |
+ Bgetfield(Bp, 'd', &n, 0); | |
+ vmot(n); | |
+ break; | |
+ case '0': case '1': case '2': case '3': case '4': | |
+ case '5': case '6': case '7': case '8': case '9': | |
+ /* move right nn units, then print character c… | |
+ n = (r - '0') * 10; | |
+ r = Bgetrune(Bp); | |
+ if (r < 0) | |
+ error(FATAL, "EOF or error reading input\n"); | |
+ else if (r < '0' || r > '9') | |
+ error(FATAL, "integer expected\n"); | |
+ n += r - '0'; | |
+ r = Bgetrune(Bp); | |
+ hmot(n); | |
+ runeout(r); | |
+ break; | |
+ case 'p': /* begin page */ | |
+ Bgetfield(Bp, 'd', &n, 0); | |
+ endpage(); | |
+ startpage(); | |
+ break; | |
+ case 'n': /* end of line (information only 'b a' follow… | |
+ Brdline(Bp, '\n'); /* toss rest of line */ | |
+ inputlineno++; | |
+ break; | |
+ case 'w': /* paddable word space (information only) */ | |
+ break; | |
+ case 'D': /* graphics function */ | |
+ draw(Bp); | |
+ break; | |
+ case 'x': /* device control functions */ | |
+ devcntl(Bp); | |
+ break; | |
+ case '#': /* comment */ | |
+ Brdline(Bp, '\n'); /* toss rest of line */ | |
+ case '\n': | |
+ inputlineno++; | |
+ break; | |
+ default: | |
+ error(WARNING, "unknown troff function <%c>\n", r); | |
+ break; | |
+ } | |
+ } | |
+ endpage(); | |
+ if (debug) Bprint(Bstderr, "r=0x%x\n", r); | |
+ if (debug) Bprint(Bstderr, "leaving conv\n"); | |
+} | |
diff --git a/src/cmd/postscript/tr2post/devcntl.c b/src/cmd/postscript/tr2post/… | |
t@@ -0,0 +1,178 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <stdio.h> | |
+#include "../common/common.h" | |
+#include "tr2post.h" | |
+ | |
+char devname[20] = { 'u', 't', 'f', '\0' }; | |
+int resolution; | |
+int minx, miny; | |
+ | |
+struct sjt { | |
+ char *str; | |
+ void (*func)(void *); | |
+}; | |
+ | |
+/* I won't need this if getfields can replace sscanf | |
+ | |
+extern void picture(Biobuf *); | |
+extern void notavail(char *); | |
+ | |
+void | |
+PSInclude(Biobuf *inp) { | |
+ char buf[256]; | |
+ | |
+ Bgetfield(inp, 's', buf, 256); | |
+ if(pageon()) { | |
+ endstring(); | |
+ Bprint(Bstdout, "%s\n", buf); | |
+ } | |
+} | |
+ | |
+struct sjt specialjumptable[] = { | |
+ {"PI", picture}, | |
+ {"PictureInclusion", picture}, | |
+ {"InlinePicture", NULL}, | |
+ {"BeginPath", NULL}, | |
+ {"DrawPath", NULL}, | |
+ {"BeginObject", NULL}, | |
+ {"EndObject", NULL}, | |
+ {"NewBaseline", NULL}, | |
+ {"DrawText", NULL}, | |
+ {"SetText", NULL}, | |
+ {"SetColor", NULL}, | |
+ {"INFO", NULL}, | |
+ {"PS", PSInclude}, | |
+ {"Postscript", PSInclude}, | |
+ {"ExportPS", notavail("ExportPS")}, | |
+ {NULL, NULL} | |
+}; | |
+*/ | |
+ | |
+void | |
+devcntl(Biobuf *inp) { | |
+ | |
+ char cmd[50], buf[256], str[MAXTOKENSIZE], *line; | |
+ int c, n, linelen; | |
+ | |
+/* | |
+ * | |
+ * Interpret device control commands, ignoring any we don't recognize. The | |
+ * "x X ..." commands are a device dependent collection generated by troff's | |
+ * \X'...' request. | |
+ * | |
+ */ | |
+ | |
+ Bgetfield(inp, 's', cmd, 50); | |
+ if (debug) Bprint(Bstderr, "devcntl(cmd=%s)\n", cmd); | |
+ switch (cmd[0]) { | |
+ case 'f': /* mount font in a position */ | |
+ Bgetfield(inp, 'd', &n, 0); | |
+ Bgetfield(inp, 's', str, 100); | |
+ mountfont(n, str); | |
+ break; | |
+ | |
+ case 'i': /* initialize */ | |
+ initialize(); | |
+ break; | |
+ | |
+ case 'p': /* pause */ | |
+ break; | |
+ | |
+ case 'r': /* resolution assumed when prepared */ | |
+ Bgetfield(inp, 'd', &resolution, 0); | |
+ Bgetfield(inp, 'd', &minx, 0); | |
+ Bgetfield(inp, 'd', &miny, 0); | |
+ break; | |
+ | |
+ case 's': /* stop */ | |
+ case 't': /* trailer */ | |
+ /* flushtext(); */ | |
+ break; | |
+ | |
+ case 'H': /* char height */ | |
+ Bgetfield(inp, 'd', &n, 0); | |
+ t_charht(n); | |
+ break; | |
+ | |
+ case 'S': /* slant */ | |
+ Bgetfield(inp, 'd', &n, 0); | |
+ t_slant(n); | |
+ break; | |
+ | |
+ case 'T': /* device name */ | |
+ Bgetfield(inp, 's', &devname, 16); | |
+ if (debug) Bprint(Bstderr, "devname=%s\n", devname); | |
+ break; | |
+ | |
+ case 'E': /* input encoding - not in troff yet … | |
+ Bgetfield(inp, 's', &str, 100); | |
+/* if ( strcmp(str, "UTF") == 0 ) | |
+ reading = UTFENCODING; | |
+ else reading = ONEBYTE; | |
+ */ | |
+ break; | |
+ | |
+ case 'X': /* copy through - from troff */ | |
+ if (Bgetfield(inp, 's', str, MAXTOKENSIZE-1) <= 0) | |
+ error(FATAL, "incomplete devcntl line\n"); | |
+ if ((line = Brdline(inp, '\n')) == 0) | |
+ error(FATAL, "incomplete devcntl line\n"); | |
+ strncpy(buf, line, Blinelen(inp)-1); | |
+ buf[Blinelen(inp)-1] = '\0'; | |
+ Bungetc(inp); | |
+ | |
+ if (strncmp(str, "PI", sizeof("PI")-1) == 0 || strncmp(str, "P… | |
+ picture(inp, str); | |
+ } else if (strncmp(str, "InlinePicture", sizeof("InlinePicture… | |
+ error(FATAL, "InlinePicture not implemented yet.\n"); | |
+/* inlinepic(inp, buf); */ | |
+ } else if (strncmp(str, "BeginPath", sizeof("BeginPath")-1) ==… | |
+ beginpath(buf, FALSE); | |
+ } else if (strncmp(str, "DrawPath", sizeof("DrawPath")-1) == 0… | |
+ drawpath(buf, FALSE); | |
+ } else if (strncmp(str, "BeginObject", sizeof("BeginObject")-1… | |
+ beginpath(buf, TRUE); | |
+ } else if (strncmp(str, "EndObject", sizeof("EndObject")-1) ==… | |
+ drawpath(buf, TRUE); | |
+ } else if (strncmp(str, "NewBaseline", sizeof("NewBaseline")-1… | |
+ error(FATAL, "NewBaseline not implemented yet.\n"); | |
+/* newbaseline(buf); */ | |
+ } else if (strncmp(str, "DrawText", sizeof("DrawText")-1) == 0… | |
+ error(FATAL, "DrawText not implemented yet.\n"); | |
+/* drawtext(buf); */ | |
+ } else if (strncmp(str, "SetText", sizeof("SetText")-1) == 0) { | |
+ error(FATAL, "SetText not implemented yet.\n"); | |
+/* settext(buf); */ | |
+ } else if (strncmp(str, "SetColor", sizeof("SetColor")-1) == 0… | |
+ error(FATAL, "SetColor not implemented yet.\n"); | |
+/* newcolor(buf); */ | |
+/* setcolor(); */ | |
+ } else if (strncmp(str, "INFO", sizeof("INFO")-1) == 0) { | |
+ error(FATAL, "INFO not implemented yet.\n"); | |
+/* flushtext(); */ | |
+/* Bprint(outp, "%%INFO%s", buf); */ | |
+ } else if (strncmp(str, "PS", sizeof("PS")-1) == 0 || strncmp(… | |
+ if(pageon()) { | |
+ endstring(); | |
+ Bprint(Bstdout, "%s\n", buf); | |
+ } | |
+ } else if (strncmp(str, "ExportPS", sizeof("ExportPS")-1) == 0… | |
+ error(FATAL, "ExportPS not implemented yet.\n"); | |
+/* if (Bfildes(outp) == 1) { */ | |
+/* restore(); */ | |
+/* Bprint(outp, "%s", buf); */ | |
+/* save(); */ | |
+/* } */ | |
+ } | |
+/* else | |
+ error(WARNING, "Unknown string <%s %s> after x X\n", s… | |
+*/ | |
+ | |
+ break; | |
+ } | |
+ while ((c = Bgetc(inp)) != '\n' && c != Beof); | |
+ inputlineno++; | |
+} | |
+ | |
diff --git a/src/cmd/postscript/tr2post/draw.c b/src/cmd/postscript/tr2post/dra… | |
t@@ -0,0 +1,342 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <ctype.h> | |
+#include "../common/common.h" | |
+#include "tr2post.h" | |
+ | |
+BOOLEAN drawflag = FALSE; | |
+BOOLEAN inpath = FALSE; /* TRUE if we're putting… | |
+ | |
+void | |
+cover(double x, double y) { | |
+} | |
+ | |
+void | |
+drawspline(Biobuf *Bp, int flag) { /* flag!=1 connect end points */ | |
+ int x[100], y[100]; | |
+ int i, N; | |
+/* | |
+ * | |
+ * Spline drawing routine for Postscript printers. The complicated stuff is | |
+ * handled by procedure Ds, which should be defined in the library file. I've | |
+ * seen wrong implementations of troff's spline drawing, so fo the record I'll | |
+ * write down the parametric equations and the necessary conversions to Bezier | |
+ * cubic splines (as used in Postscript). | |
+ * | |
+ * | |
+ * Parametric equation (x coordinate only): | |
+ * | |
+ * | |
+ * (x2 - 2 * x1 + x0) 2 (x0 + x1) | |
+ * x = ------------------ * t + (x1 - x0) * t + --------- | |
+ * 2 2 | |
+ * | |
+ * | |
+ * The coefficients in the Bezier cubic are, | |
+ * | |
+ * | |
+ * A = 0 | |
+ * B = (x2 - 2 * x1 + x0) / 2 | |
+ * C = x1 - x0 | |
+ * | |
+ * | |
+ * while the current point is, | |
+ * | |
+ * current-point = (x0 + x1) / 2 | |
+ * | |
+ * Using the relationships given in the Postscript manual (page 121) it's easy… | |
+ * see that the control points are given by, | |
+ * | |
+ * | |
+ * x0' = (x0 + 5 * x1) / 6 | |
+ * x1' = (x2 + 5 * x1) / 6 | |
+ * x2' = (x1 + x2) / 2 | |
+ * | |
+ * | |
+ * where the primed variables are the ones used by curveto. The calculations | |
+ * shown above are done in procedure Ds using the coordinates set up in both | |
+ * the x[] and y[] arrays. | |
+ * | |
+ * A simple test of whether your spline drawing is correct would be to use cip | |
+ * to draw a spline and some tangent lines at appropriate points and then print | |
+ * the file. | |
+ * | |
+ */ | |
+ | |
+ for (N=2; N<sizeof(x)/sizeof(x[0]); N++) | |
+ if (Bgetfield(Bp, 'd', &x[N], 0)<=0 || Bgetfield(Bp, 'd', &y[N… | |
+ break; | |
+ | |
+ x[0] = x[1] = hpos; | |
+ y[0] = y[1] = vpos; | |
+ | |
+ for (i = 1; i < N; i++) { | |
+ x[i+1] += x[i]; | |
+ y[i+1] += y[i]; | |
+ } | |
+ | |
+ x[N] = x[N-1]; | |
+ y[N] = y[N-1]; | |
+ | |
+ for (i = ((flag!=1)?0:1); i < ((flag!=1)?N-1:N-2); i++) { | |
+ endstring(); | |
+ if (pageon()) | |
+ Bprint(Bstdout, "%d %d %d %d %d %d Ds\n", x[i], y[i], … | |
+/* if (dobbox == TRUE) { /* could be better */ | |
+/* cover((double)(x[i] + x[i+1])/2,(double)-(y[i] +… | |
+/* cover((double)x[i+1], (double)-y[i+1]); | |
+/* cover((double)(x[i+1] + x[i+2])/2, (double)-(y[i… | |
+/* } | |
+ */ | |
+ } | |
+ | |
+ hpos = x[N]; /* where troff expects to be */ | |
+ vpos = y[N]; | |
+} | |
+ | |
+void | |
+draw(Biobuf *Bp) { | |
+ | |
+ int r, x1, y1, x2, y2, i; | |
+ int d1, d2; | |
+ | |
+ drawflag = TRUE; | |
+ r = Bgetrune(Bp); | |
+ switch(r) { | |
+ case 'l': | |
+ if (Bgetfield(Bp, 'd', &x1, 0)<=0 || Bgetfield(Bp, 'd', &y1, 0… | |
+ error(FATAL, "draw line function, destination coordina… | |
+ | |
+ endstring(); | |
+ if (pageon()) | |
+ Bprint(Bstdout, "%d %d %d %d Dl\n", hpos, vpos, hpos+x… | |
+ hpos += x1; | |
+ vpos += y1; | |
+ break; | |
+ case 'c': | |
+ if (Bgetfield(Bp, 'd', &d1, 0)<=0) | |
+ error(FATAL, "draw circle function, diameter coordinat… | |
+ | |
+ endstring(); | |
+ if (pageon()) | |
+ Bprint(Bstdout, "%d %d %d %d De\n", hpos, vpos, d1, d1… | |
+ hpos += d1; | |
+ break; | |
+ case 'e': | |
+ if (Bgetfield(Bp, 'd', &d1, 0)<=0 || Bgetfield(Bp, 'd', &d2, 0… | |
+ error(FATAL, "draw ellipse function, diameter coordina… | |
+ | |
+ endstring(); | |
+ if (pageon()) | |
+ Bprint(Bstdout, "%d %d %d %d De\n", hpos, vpos, d1, d2… | |
+ hpos += d1; | |
+ break; | |
+ case 'a': | |
+ if (Bgetfield(Bp, 'd', &x1, 0)<=0 || Bgetfield(Bp, 'd', &y1, 0… | |
+ error(FATAL, "draw arc function, coordinates not found… | |
+ | |
+ endstring(); | |
+ if (pageon()) | |
+ Bprint(Bstdout, "%d %d %d %d %d %d Da\n", hpos, vpos, … | |
+ hpos += x1 + x2; | |
+ vpos += y1 + y2; | |
+ break; | |
+ case 'q': | |
+ drawspline(Bp, 1); | |
+ break; | |
+ case '~': | |
+ drawspline(Bp, 2); | |
+ break; | |
+ default: | |
+ error(FATAL, "unknown draw function <%c>\n", r); | |
+ break; | |
+ } | |
+} | |
+ | |
+void | |
+beginpath(char *buf, int copy) { | |
+ | |
+/* | |
+ * Called from devcntrl() whenever an "x X BeginPath" command is read. It's us… | |
+ * to mark the start of a sequence of drawing commands that should be grouped | |
+ * together and treated as a single path. By default the drawing procedures in | |
+ * *drawfile treat each drawing command as a separate object, and usually start | |
+ * with a newpath (just as a precaution) and end with a stroke. The newpath and | |
+ * stroke isolate individual drawing commands and make it impossible to deal w… | |
+ * composite objects. "x X BeginPath" can be used to mark the start of drawing | |
+ * commands that should be grouped together and treated as a single object, and | |
+ * part of what's done here ensures that the PostScript drawing commands defin… | |
+ * in *drawfile skip the newpath and stroke, until after the next "x X DrawPat… | |
+ * command. At that point the path that's been built up can be manipulated in | |
+ * various ways (eg. filled and/or stroked with a different line width). | |
+ * | |
+ * Color selection is one of the options that's available in parsebuf(), | |
+ * so if we get here we add *colorfile to the output file before doing | |
+ * anything important. | |
+ * | |
+ */ | |
+ if (inpath == FALSE) { | |
+ endstring(); | |
+ /* getdraw(); */ | |
+ /* getcolor(); */ | |
+ Bprint(Bstdout, "gsave\n"); | |
+ Bprint(Bstdout, "newpath\n"); | |
+ Bprint(Bstdout, "%d %d m\n", hpos, vpos); | |
+ Bprint(Bstdout, "/inpath true def\n"); | |
+ if ( copy == TRUE ) | |
+ Bprint(Bstdout, "%s\n", buf); | |
+ inpath = TRUE; | |
+ } | |
+} | |
+ | |
+static void parsebuf(char*); | |
+ | |
+void | |
+drawpath(char *buf, int copy) { | |
+ | |
+/* | |
+ * | |
+ * Called from devcntrl() whenever an "x X DrawPath" command is read. It marks… | |
+ * end of the path started by the last "x X BeginPath" command and uses whatev… | |
+ * has been passed along in *buf to manipulate the path (eg. fill and/or stroke | |
+ * the path). Once that's been done the drawing procedures are restored to the… | |
+ * default behavior in which each drawing command is treated as an isolated pa… | |
+ * The new version (called after "x X DrawPath") has copy set to FALSE, and ca… | |
+ * parsebuf() to figure out what goes in the output file. It's a feeble attempt | |
+ * to free users and preprocessors (like pic) from having to know PostScript. … | |
+ * comments in parsebuf() describe what's handled. | |
+ * | |
+ * In the early version a path was started with "x X BeginObject" and ended wi… | |
+ * "x X EndObject". In both cases *buf was just copied to the output file, and | |
+ * was expected to be legitimate PostScript that manipulated the current path. | |
+ * The old escape sequence will be supported for a while (for Ravi), and always | |
+ * call this routine with copy set to TRUE. | |
+ * | |
+ * | |
+ */ | |
+ | |
+ if ( inpath == TRUE ) { | |
+ if ( copy == TRUE ) | |
+ Bprint(Bstdout, "%s\n", buf); | |
+ else | |
+ parsebuf(buf); | |
+ Bprint(Bstdout, "grestore\n"); | |
+ Bprint(Bstdout, "/inpath false def\n"); | |
+/* reset(); */ | |
+ inpath = FALSE; | |
+ } | |
+} | |
+ | |
+ | |
+/*****************************************************************************/ | |
+ | |
+static void | |
+parsebuf(char *buf) | |
+{ | |
+ char *p; /* usually the next token */ | |
+ char *q; | |
+ int gsavelevel = 0; /* non-zero if we've… | |
+ | |
+/* | |
+ * | |
+ * Simple minded attempt at parsing the string that followed an "x X DrawPath" | |
+ * command. Everything not recognized here is simply ignored - there's absolut… | |
+ * no error checking and what was originally in buf is clobbered by strtok(). | |
+ * A typical *buf might look like, | |
+ * | |
+ * gray .9 fill stroke | |
+ * | |
+ * to fill the current path with a gray level of .9 and follow that by strokin… | |
+ * outline of the path. Since unrecognized tokens are ignored the last example | |
+ * could also be written as, | |
+ * | |
+ * with gray .9 fill then stroke | |
+ * | |
+ * The "with" and "then" strings aren't recognized tokens and are simply disca… | |
+ * The "stroke", "fill", and "wfill" force out appropriate PostScript code and… | |
+ * followed by a grestore. In otherwords changes to the grahics state (eg. a g… | |
+ * level or color) are reset to default values immediately after the stroke, f… | |
+ * or wfill tokens. For now "fill" gets invokes PostScript's eofill operator a… | |
+ * "wfill" calls fill (ie. the operator that uses the non-zero winding rule). | |
+ * | |
+ * The tokens that cause temporary changes to the graphics state are "gray" (f… | |
+ * setting the gray level), "color" (for selecting a known color from the colo… | |
+ * dictionary defined in *colorfile), and "line" (for setting the line width).… | |
+ * three tokens can be extended since strncmp() makes the comparison. For exam… | |
+ * the strings "line" and "linewidth" accomplish the same thing. Colors are na… | |
+ * (eg. "red"), but must be appropriately defined in *colorfile. For now all t… | |
+ * tokens must be followed immediately by their single argument. The gray level | |
+ * (ie. the argument that follows "gray") should be a number between 0 and 1, … | |
+ * 0 for black and 1 for white. | |
+ * | |
+ * To pass straight PostScript through enclose the appropriate commands in dou… | |
+ * quotes. Straight PostScript is only bracketed by the outermost gsave/gresto… | |
+ * pair (ie. the one from the initial "x X BeginPath") although that's probably | |
+ * a mistake. Suspect I may have to change the double quote delimiters. | |
+ * | |
+ */ | |
+ | |
+ for( ; p != nil ; p = q ) { | |
+ if( q = strchr(p, ' ') ) { | |
+ *q++ = '\0'; | |
+ } | |
+ | |
+ if ( gsavelevel == 0 ) { | |
+ Bprint(Bstdout, "gsave\n"); | |
+ gsavelevel++; | |
+ } | |
+ if ( strcmp(p, "stroke") == 0 ) { | |
+ Bprint(Bstdout, "closepath stroke\ngrestore\n"); | |
+ gsavelevel--; | |
+ } else if ( strcmp(p, "openstroke") == 0 ) { | |
+ Bprint(Bstdout, "stroke\ngrestore\n"); | |
+ gsavelevel--; | |
+ } else if ( strcmp(p, "fill") == 0 ) { | |
+ Bprint(Bstdout, "eofill\ngrestore\n"); | |
+ gsavelevel--; | |
+ } else if ( strcmp(p, "wfill") == 0 ) { | |
+ Bprint(Bstdout, "fill\ngrestore\n"); | |
+ gsavelevel--; | |
+ } else if ( strcmp(p, "sfill") == 0 ) { | |
+ Bprint(Bstdout, "eofill\ngrestore\ngsave\nstroke\ngres… | |
+ gsavelevel--; | |
+ } else if ( strncmp(p, "gray", strlen("gray")) == 0 ) { | |
+ if( q ) { | |
+ p = q; | |
+ if ( q = strchr(p, ' ') ) | |
+ *q++ = '\0'; | |
+ Bprint(Bstdout, "%s setgray\n", p); | |
+ } | |
+ } else if ( strncmp(p, "color", strlen("color")) == 0 ) { | |
+ if( q ) { | |
+ p = q; | |
+ if ( q = strchr(p, ' ') ) | |
+ *q++ = '\0'; | |
+ Bprint(Bstdout, "/%s setcolor\n", p); | |
+ } | |
+ } else if ( strncmp(p, "line", strlen("line")) == 0 ) { | |
+ if( q ) { | |
+ p = q; | |
+ if ( q = strchr(p, ' ') ) | |
+ *q++ = '\0'; | |
+ Bprint(Bstdout, "%s resolution mul 2 div setli… | |
+ } | |
+ } else if ( strncmp(p, "reverse", strlen("reverse")) == 0 ) | |
+ Bprint(Bstdout, "reversepath\n"); | |
+ else if ( *p == '"' ) { | |
+ for ( ; gsavelevel > 0; gsavelevel-- ) | |
+ Bprint(Bstdout, "grestore\n"); | |
+ if ( q != nil ) | |
+ *--q = ' '; | |
+ if ( (q = strchr(p, '"')) != nil ) { | |
+ *q++ = '\0'; | |
+ Bprint(Bstdout, "%s\n", p); | |
+ } | |
+ } | |
+ } | |
+ | |
+ for ( ; gsavelevel > 0; gsavelevel-- ) | |
+ Bprint(Bstdout, "grestore\n"); | |
+ | |
+} | |
diff --git a/src/cmd/postscript/tr2post/mkfile b/src/cmd/postscript/tr2post/mkf… | |
t@@ -0,0 +1,36 @@ | |
+<$PLAN9/src/mkhdr | |
+ | |
+<../config | |
+ | |
+COMMONDIR=../common | |
+ | |
+SHORTLIB=bio 9 | |
+TARG=tr2post | |
+ | |
+OFILES=tr2post.$O\ | |
+ chartab.$O\ | |
+ Bgetfield.$O\ | |
+ conv.$O\ | |
+ utils.$O\ | |
+ devcntl.$O\ | |
+ draw.$O\ | |
+ readDESC.$O\ | |
+ ps_include.$O\ | |
+ pictures.$O\ | |
+ common.$O\ | |
+ | |
+HFILES=tr2post.h\ | |
+ ps_include.h\ | |
+ $COMMONDIR/common.h\ | |
+ $COMMONDIR/comments.h\ | |
+ $COMMONDIR/path.h\ | |
+ $COMMONDIR/ext.h\ | |
+ | |
+BIN=$POSTBIN | |
+ | |
+<$PLAN9/src/mkone | |
+ | |
+CFLAGS=$CFLAGS -c -D'PROGRAMVERSION="0.1"' -D'DOROUND=1' -I$COMMONDIR | |
+ | |
+%.$O: $COMMONDIR/%.c | |
+ $CC $CFLAGS $COMMONDIR/$stem.c | |
diff --git a/src/cmd/postscript/tr2post/pictures.c b/src/cmd/postscript/tr2post… | |
t@@ -0,0 +1,295 @@ | |
+/* | |
+ * | |
+ * PostScript picture inclusion routines. Support for managing in-line pictures | |
+ * has been added, and works in combination with the simple picpack pre-proces… | |
+ * that's supplied with this package. An in-line picture begins with a special | |
+ * device control command that looks like, | |
+ * | |
+ * x X InlinPicture name size | |
+ * | |
+ * where name is the pathname of the original picture file and size is the num… | |
+ * of bytes in the picture, which begins immediately on the next line. When dp… | |
+ * encounters the InlinePicture device control command inlinepic() is called a… | |
+ * that routine appends the string name and the integer size to a temporary fi… | |
+ * (fp_pic) and then adds the next size bytes read from the current input file… | |
+ * file fp_pic. All in-line pictures are saved in fp_pic and located later usi… | |
+ * the name string and picture file size that separate pictures saved in fp_pi… | |
+ * | |
+ * When a picture request (ie. an "x X PI" command) is encountered picopen() is | |
+ * called and it first looks for the picture file in fp_pic. If it's found the… | |
+ * the entire picture (ie. size bytes) is copied from fp_pic to a new temp file | |
+ * and that temp file is used as the picture file. If there's nothing in fp_pic | |
+ * or if the lookup failed the original route is taken. | |
+ * | |
+ * Support for in-line pictures is an attempt to address requirements, express… | |
+ * by several organizations, of being able to store a document as a single file | |
+ * (usually troff input) that can then be sent through dpost and ultimately to | |
+ * a PostScript printer. The mechanism may help some users, but the are obvious | |
+ * disadvantages to this approach, and the original mechanism is the recommend… | |
+ * approach! Perhaps the most important problem is that troff output, with in-… | |
+ * pictures included, doesn't fit the device independent language accepted by | |
+ * important post-processors (like proff) and that means you won't be able to | |
+ * reliably preview a packed file on your 5620 (or whatever). | |
+ * | |
+ */ | |
+ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <stdio.h> | |
+#include "ext.h" | |
+#include "common.h" | |
+#include "tr2post.h" | |
+/* PostScript file structuring comments */ | |
+#include "comments.h" | |
+/* general purpose definitions */ | |
+/* #include "gen.h" */ | |
+/* just for TEMPDIR definition */ | |
+#include "path.h" | |
+/* external variable declarations */ | |
+/* #include "ext.h" */ | |
+ | |
+Biobuf *bfp_pic = NULL; | |
+Biobuf *Bfp_pic; | |
+Biobuf *picopen(char *); | |
+ | |
+#define MAXGETFIELDS 16 | |
+char *fields[MAXGETFIELDS]; | |
+int nfields; | |
+ | |
+extern int devres, hpos, vpos; | |
+extern int picflag; | |
+ | |
+/*****************************************************************************/ | |
+ | |
+void | |
+picture(Biobuf *inp, char *buf) { | |
+ int poffset; /* page offset */ | |
+ int indent; /* indent */ | |
+ int length; /* line length */ | |
+ int totrap; /* distance to next trap */ | |
+ char name[100]; /* picture file and page string */ | |
+ char hwo[40], *p; /* height, width and offset strings */ | |
+ char flags[20]; /* miscellaneous stuff */ | |
+ int page = 1; /* page number pulled from name[] … | |
+ double frame[4]; /* height, width, y, and x offsets from… | |
+ char units; /* scale indicator for frame dimensi… | |
+ int whiteout = 0; /* white out the box? */ | |
+ int outline = 0; /* draw a box around the picture? */ | |
+ int scaleboth = 0; /* scale both dimensions? */ | |
+ double adjx = 0.5; /* left-right adjustment */ | |
+ double adjy = 0.5; /* top-bottom adjustment */ | |
+ double rot = 0; /* rotation in clockwise degrees */ | |
+ Biobuf *fp_in; /* for *name */ | |
+ int i; /* loop index */ | |
+ | |
+/* | |
+ * | |
+ * Called from devcntrl() after an 'x X PI' command is found. The syntax of th… | |
+ * command is: | |
+ * | |
+ * x X PI:args | |
+ * | |
+ * with args separated by colons and given by: | |
+ * | |
+ * poffset | |
+ * indent | |
+ * length | |
+ * totrap | |
+ * file[(page)] | |
+ * height[,width[,yoffset[,xoffset]]] | |
+ * [flags] | |
+ * | |
+ * poffset, indent, length, and totrap are given in machine units. height, wid… | |
+ * and offset refer to the picture frame in inches, unless they're followed by | |
+ * the u scale indicator. flags is a string that provides a little bit of cont… | |
+ * over the placement of the picture in the frame. Rotation of the picture, in | |
+ * clockwise degrees, is set by the a flag. If it's not followed by an angle | |
+ * the current rotation angle is incremented by 90 degrees, otherwise the angle | |
+ * is set by the number that immediately follows the a. | |
+ * | |
+ */ | |
+ | |
+ if (!picflag) /* skip it */ | |
+ return; | |
+ endstring(); | |
+ | |
+ flags[0] = '\0'; /* just to be safe */ | |
+ | |
+ nfields = getfields(buf, fields, MAXGETFIELDS, 0, ":\n"); | |
+ if (nfields < 6) { | |
+ error(WARNING, "too few arguments to specify picture"); | |
+ return; | |
+ } | |
+ poffset = atoi(fields[1]); | |
+ indent = atoi(fields[2]); | |
+ length = atoi(fields[3]); | |
+ totrap = atoi(fields[4]); | |
+ strncpy(name, fields[5], sizeof(name)); | |
+ strncpy(hwo, fields[6], sizeof(hwo)); | |
+ if (nfields >= 6) | |
+ strncpy(flags, fields[7], sizeof(flags)); | |
+ | |
+ nfields = getfields(buf, fields, MAXGETFIELDS, 0, "()"); | |
+ if (nfields == 2) { | |
+ strncpy(name, fields[0], sizeof(name)); | |
+ page = atoi(fields[1]); | |
+ } | |
+ | |
+ if ((fp_in = picopen(name)) == NULL) { | |
+ error(WARNING, "can't open picture file %s\n", name); | |
+ return; | |
+ } | |
+ | |
+ frame[0] = frame[1] = -1; /* default frame height, widt… | |
+ frame[2] = frame[3] = 0; /* and y and x offsets */ | |
+ | |
+ for (i = 0, p = hwo-1; i < 4 && p != NULL; i++, p = strchr(p, ',')) | |
+ if (sscanf(++p, "%lf%c", &frame[i], &units) == 2) | |
+ if (units == 'i' || units == ',' || units == '\0') | |
+ frame[i] *= devres; | |
+ | |
+ if (frame[0] <= 0) /* check what we got for height */ | |
+ frame[0] = totrap; | |
+ | |
+ if (frame[1] <= 0) /* and width - check too big?? */ | |
+ frame[1] = length - indent; | |
+ | |
+ frame[3] += poffset + indent; /* real x offset */ | |
+ | |
+ for (i = 0; flags[i]; i++) | |
+ switch (flags[i]) { | |
+ case 'c': adjx = adjy = 0.5; break; /* move to the cent… | |
+ case 'l': adjx = 0; break; /* left */ | |
+ case 'r': adjx = 1; break; /* right */ | |
+ case 't': adjy = 1; break; /* top */ | |
+ case 'b': adjy = 0; break; /* or bottom justify… | |
+ case 'o': outline = 1; break; /* outline the picture */ | |
+ case 'w': whiteout = 1; break; /* white out the box */ | |
+ case 's': scaleboth = 1; break; /* scale both dimension… | |
+ case 'a': if ( sscanf(&flags[i+1], "%lf", &rot) != 1 ) | |
+ rot += 90; | |
+ } | |
+ | |
+ /* restore(); */ | |
+ endstring(); | |
+ Bprint(Bstdout, "cleartomark\n"); | |
+ Bprint(Bstdout, "saveobj restore\n"); | |
+ | |
+ ps_include(fp_in, Bstdout, page, whiteout, outline, scaleboth, | |
+ frame[3]+frame[1]/2, -vpos-frame[2]-frame[0]/2, frame[1], fram… | |
+ /* save(); */ | |
+ Bprint(Bstdout, "/saveobj save def\n"); | |
+ Bprint(Bstdout, "mark\n"); | |
+ Bterm(fp_in); | |
+ | |
+} | |
+ | |
+/* | |
+ * | |
+ * Responsible for finding and opening the next picture file. If we've accumul… | |
+ * any in-line pictures fp_pic won't be NULL and we'll look there first. If *p… | |
+ * is found in *fp_pic we create another temp file, open it for update, unlink… | |
+ * copy in the picture, seek back to the start of the new temp file, and return | |
+ * the file pointer to the caller. If fp_pic is NULL or the lookup fails we ju… | |
+ * open file *path and return the resulting file pointer to the caller. | |
+ * | |
+ */ | |
+Biobuf * | |
+picopen(char *path) { | |
+/* char name[100]; /* pathnames */ | |
+/* long pos; /* current position */ | |
+/* long total; /* and sizes - from *fp_pi… | |
+ Biobuf *bfp; | |
+ Biobuf *Bfp; /* and pointer for the new temp fil… | |
+ | |
+ | |
+ if ((bfp = Bopen(path, OREAD)) == 0) | |
+ error(FATAL, "can't open %s\n", path); | |
+ Bfp = bfp; | |
+ return(Bfp); | |
+#ifdef UNDEF | |
+ if (Bfp_pic != NULL) { | |
+ Bseek(Bfp_pic, 0L, 0); | |
+ while (Bgetfield(Bfp_pic, 's', name, 99)>0 | |
+ && Bgetfield(Bfp_pic, 'd', &total, 0)>0) { | |
+ pos = Bseek(Bfp_pic, 0L, 1); | |
+ if (strcmp(path, name) == 0) { | |
+ if (tmpnam(pictmpname) == NULL) | |
+ error(FATAL, "can't generate temp file… | |
+ if ( (bfp = Bopen(pictmpname, ORDWR)) == NULL ) | |
+ error(FATAL, "can't open %s", pictmpna… | |
+ Bfp = bfp; | |
+ piccopy(Bfp_pic, Bfp, total); | |
+ Bseek(Bfp, 0L, 0); | |
+ return(Bfp); | |
+ } | |
+ Bseek(Bfp_pic, total+pos, 0); | |
+ } | |
+ } | |
+ if ((bfp = Bopen(path, OREAD)) == 0) | |
+ Bfp = 0; | |
+ else | |
+ Bfp = bfp; | |
+ return(Bfp); | |
+#endif | |
+} | |
+ | |
+/* | |
+ * | |
+ * Adds an in-line picture file to the end of temporary file *Bfp_pic. All pic… | |
+ * grabbed from the input file are saved in the same temp file. Each is precee… | |
+ * by a one line header that includes the original picture file pathname and t… | |
+ * size of the picture in bytes. The in-line picture file is opened for update, | |
+ * left open, and unlinked so it disappears when we do. | |
+ * | |
+ */ | |
+/* *fp; /* current input file */ | |
+/* *buf; /* whatever followed "x X InlinePicture… | |
+ | |
+#ifdef UNDEF | |
+void | |
+inlinepic(Biobuf *Bfp, char *buf) { | |
+ char name[100]; /* picture file pathname */ | |
+ long total; /* and size - both from *buf… | |
+ | |
+ | |
+ if (Bfp_pic == NULL ) { | |
+ tmpnam(pictmpname); | |
+ if ((bfp_pic = Bopen(pictmpname, ORDWR)) == 0) | |
+ error(FATAL, "can't open in-line picture file %s",… | |
+ unlink(pictmpname); | |
+ } | |
+ | |
+ if ( sscanf(buf, "%s %ld", name, &total) != 2 ) | |
+ error(FATAL, "in-line picture error"); | |
+ | |
+ fseek(Bfp_pic, 0L, 2); | |
+ fprintf(Bfp_pic, "%s %ld\n", name, total); | |
+ getc(fp); | |
+ fflush(fp_pic); | |
+ piccopy(fp, fp_pic, total); | |
+ ungetc('\n', fp); | |
+ | |
+} | |
+#endif | |
+ | |
+/* | |
+ * | |
+ * Copies total bytes from file fp_in to fp_out. Used to append picture files … | |
+ * *fp_pic and then copy them to yet another temporary file immediately before | |
+ * they're used (in picture()). | |
+ * | |
+ */ | |
+/* *fp_in; input */ | |
+/* *fp_out; and output file pointers */ | |
+/* total; number of bytes to be copied */ | |
+void | |
+piccopy(Biobuf *Bfp_in, Biobuf *Bfp_out, long total) { | |
+ long i; | |
+ | |
+ for (i = 0; i < total; i++) | |
+ if (Bputc(Bfp_out, Bgetc(Bfp_in)) < 0) | |
+ error(FATAL, "error copying in-line picture file"); | |
+ Bflush(Bfp_out); | |
+} | |
diff --git a/src/cmd/postscript/tr2post/ps_include.c b/src/cmd/postscript/tr2po… | |
t@@ -0,0 +1,191 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <stdio.h> | |
+#include "../common/common.h" | |
+#include "ps_include.h" | |
+ | |
+extern int curpostfontid; | |
+extern int curfontsize; | |
+ | |
+typedef struct {long start, end;} Section; | |
+static char *buf; | |
+ | |
+static void | |
+copy(Biobuf *fin, Biobuf *fout, Section *s) { | |
+ int cond; | |
+ if (s->end <= s->start) | |
+ return; | |
+ Bseek(fin, s->start, 0); | |
+ while (Bseek(fin, 0L, 1) < s->end && (buf=Brdline(fin, '\n')) != NULL){ | |
+ /* | |
+ * We have to be careful here, because % can legitimately appe… | |
+ * in Ascii85 encodings, and must not be elided. | |
+ * The goal here is to make any DSC comments impotent without | |
+ * actually changing the behavior of the Postscript. | |
+ * Since stripping ``comments'' breaks Ascii85, we can instead… | |
+ * indent comments a space, which turns DSC comments into non-… | |
+ * and has no effect on binary encodings, which are whitespace… | |
+ */ | |
+ if(buf[0] == '%') | |
+ Bputc(fout, ' '); | |
+ Bwrite(fout, buf, Blinelen(fin)); | |
+ } | |
+} | |
+ | |
+/* | |
+ * | |
+ * Reads a PostScript file (*fin), and uses structuring comments to locate the | |
+ * prologue, trailer, global definitions, and the requested page. After the wh… | |
+ * file is scanned, the special ps_include PostScript definitions are copied … | |
+ * *fout, followed by the prologue, global definitions, the requested page, and | |
+ * the trailer. Before returning the initial environment (saved in PS_head) is | |
+ * restored. | |
+ * | |
+ * By default we assume the picture is 8.5 by 11 inches, but the BoundingBox | |
+ * comment, if found, takes precedence. | |
+ * | |
+ */ | |
+/* *fin, *fout; /* input and output files */ | |
+/* page_no; /* physical page number from *fin */ | |
+/* whiteout; /* erase picture area */ | |
+/* outline; /* draw a box around it and */ | |
+/* scaleboth; /* scale both dimensions - if not zero */ | |
+/* cx, cy; /* center of the picture and */ | |
+/* sx, sy; /* its size - in current coordinates … | |
+/* ax, ay; /* left-right, up-down adjustment */ | |
+/* rot; /* rotation - in clockwise degrees */ | |
+ | |
+void | |
+ps_include(Biobuf *fin, Biobuf *fout, int page_no, int whiteout, | |
+ int outline, int scaleboth, double cx, double cy, double sx, double sy, | |
+ double ax, double ay, double rot) { | |
+ char **strp; | |
+ int foundpage = 0; /* found the page whe… | |
+ int foundpbox = 0; /* found the page bou… | |
+ int nglobal = 0; /* number of global def… | |
+ int maxglobal = 0; /* and the number we'… | |
+ Section prolog, page, trailer; /* prologue, page, and tr… | |
+ Section *global; /* offsets for all global defin… | |
+ double llx, lly; /* lower left and */ | |
+ double urx, ury; /* upper right corners - defaul… | |
+ double w = whiteout != 0; /* mostly for the var() macro … | |
+ double o = outline != 0; | |
+ double s = scaleboth != 0; | |
+ int i; /* loop index */ | |
+ | |
+#define has(word) (strncmp(buf, word, strlen(word)) == 0) | |
+#define grab(n) ((Section *)(nglobal \ | |
+ ? realloc((char *)global, n*sizeof(Section)) \ | |
+ : calloc(n, sizeof(Section)))) | |
+ | |
+ llx = lly = 0; /* default BoundingBox - 8.5x11 inches */ | |
+ urx = 72 * 8.5; | |
+ ury = 72 * 11.0; | |
+ | |
+ /* section boundaries and bounding box */ | |
+ | |
+ prolog.start = prolog.end = 0; | |
+ page.start = page.end = 0; | |
+ trailer.start = 0; | |
+ Bseek(fin, 0L, 0); | |
+ | |
+ while ((buf=Brdline(fin, '\n')) != NULL) { | |
+ buf[Blinelen(fin)-1] = '\0'; | |
+ if (!has("%%")) | |
+ continue; | |
+ else if (has("%%Page: ")) { | |
+ if (!foundpage) | |
+ page.start = Bseek(fin, 0L, 1); | |
+ sscanf(buf, "%*s %*s %d", &i); | |
+ if (i == page_no) | |
+ foundpage = 1; | |
+ else if (foundpage && page.end <= page.start) | |
+ page.end = Bseek(fin, 0L, 1); | |
+ } else if (has("%%EndPage: ")) { | |
+ sscanf(buf, "%*s %*s %d", &i); | |
+ if (i == page_no) { | |
+ foundpage = 1; | |
+ page.end = Bseek(fin, 0L, 1); | |
+ } | |
+ if (!foundpage) | |
+ page.start = Bseek(fin, 0L, 1); | |
+ } else if (has("%%PageBoundingBox: ")) { | |
+ if (i == page_no) { | |
+ foundpbox = 1; | |
+ sscanf(buf, "%*s %lf %lf %lf %lf", | |
+ &llx, &lly, &urx, &ury); | |
+ } | |
+ } else if (has("%%BoundingBox: ")) { | |
+ if (!foundpbox) | |
+ sscanf(buf,"%*s %lf %lf %lf %lf", | |
+ &llx, &lly, &urx, &ury); | |
+ } else if (has("%%EndProlog") || has("%%EndSetup") || has("%%E… | |
+ prolog.end = page.start = Bseek(fin, 0L, 1); | |
+ else if (has("%%Trailer")) | |
+ trailer.start = Bseek(fin, 0L, 1); | |
+ else if (has("%%BeginGlobal")) { | |
+ if (page.end <= page.start) { | |
+ if (nglobal >= maxglobal) { | |
+ maxglobal += 20; | |
+ global = grab(maxglobal); | |
+ } | |
+ global[nglobal].start = Bseek(fin, 0L, 1); | |
+ } | |
+ } else if (has("%%EndGlobal")) | |
+ if (page.end <= page.start) | |
+ global[nglobal++].end = Bseek(fin, 0L, 1); | |
+ } | |
+ Bseek(fin, 0L, 2); | |
+ if (trailer.start == 0) | |
+ trailer.start = Bseek(fin, 0L, 1); | |
+ trailer.end = Bseek(fin, 0L, 1); | |
+ | |
+ if (page.end <= page.start) | |
+ page.end = trailer.start; | |
+ | |
+/* | |
+fprint(2, "prolog=(%d,%d)\n", prolog.start, prolog.end); | |
+fprint(2, "page=(%d,%d)\n", page.start, page.end); | |
+for(i = 0; i < nglobal; i++) | |
+ fprint(2, "global[%d]=(%d,%d)\n", i, global[i].start, global[i].end); | |
+fprint(2, "trailer=(%d,%d)\n", trailer.start, trailer.end); | |
+*/ | |
+ | |
+ /* all output here */ | |
+ for (strp = PS_head; *strp != NULL; strp++) | |
+ Bwrite(fout, *strp, strlen(*strp)); | |
+ | |
+ Bprint(fout, "/llx %g def\n", llx); | |
+ Bprint(fout, "/lly %g def\n", lly); | |
+ Bprint(fout, "/urx %g def\n", urx); | |
+ Bprint(fout, "/ury %g def\n", ury); | |
+ Bprint(fout, "/w %g def\n", w); | |
+ Bprint(fout, "/o %g def\n", o); | |
+ Bprint(fout, "/s %g def\n", s); | |
+ Bprint(fout, "/cx %g def\n", cx); | |
+ Bprint(fout, "/cy %g def\n", cy); | |
+ Bprint(fout, "/sx %g def\n", sx); | |
+ Bprint(fout, "/sy %g def\n", sy); | |
+ Bprint(fout, "/ax %g def\n", ax); | |
+ Bprint(fout, "/ay %g def\n", ay); | |
+ Bprint(fout, "/rot %g def\n", rot); | |
+ | |
+ for (strp = PS_setup; *strp != NULL; strp++) | |
+ Bwrite(fout, *strp, strlen(*strp)); | |
+ | |
+ copy(fin, fout, &prolog); | |
+ for(i = 0; i < nglobal; i++) | |
+ copy(fin, fout, &global[i]); | |
+ copy(fin, fout, &page); | |
+ copy(fin, fout, &trailer); | |
+ for (strp = PS_tail; *strp != NULL; strp++) | |
+ Bwrite(fout, *strp, strlen(*strp)); | |
+ | |
+ if(nglobal) | |
+ free(global); | |
+ | |
+ /* force the program to reestablish its state */ | |
+ curpostfontid = -1; | |
+ curfontsize = -1; | |
+} | |
diff --git a/src/cmd/postscript/tr2post/ps_include.h b/src/cmd/postscript/tr2po… | |
t@@ -0,0 +1,66 @@ | |
+static char *PS_head[] = { | |
+ "%ps_include: begin\n", | |
+ "save\n", | |
+ "/ed {exch def} def\n", | |
+ "{} /showpage ed\n", | |
+ "{} /copypage ed\n", | |
+ "{} /erasepage ed\n", | |
+ "{} /letter ed\n", | |
+ "currentdict /findfont known systemdict /findfont known and {\n", | |
+ " /findfont systemdict /findfont get def\n", | |
+ "} if\n", | |
+ "36 dict dup /PS-include-dict-dw ed begin\n", | |
+ "/context ed\n", | |
+ "count array astore /o-stack ed\n", | |
+ "%ps_include: variables begin\n", | |
+ 0 | |
+}; | |
+ | |
+static char *PS_setup[] = { | |
+ "%ps_include: variables end\n", | |
+ "{llx lly urx ury} /bbox ed\n", | |
+ "{newpath 2 index exch 2 index exch dup 6 index exch\n", | |
+ " moveto 3 {lineto} repeat closepath} /boxpath ed\n", | |
+ "{dup mul exch dup mul add sqrt} /len ed\n", | |
+ "{2 copy gt {exch} if pop} /min ed\n", | |
+ "{2 copy lt {exch} if pop} /max ed\n", | |
+ "{transform round exch round exch A itransform} /nice ed\n", | |
+ "{6 array} /n ed\n", | |
+ "n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed\n… | |
+ "urx llx sub 0 A dtransform len /Sx ed\n", | |
+ "0 ury lly sub A dtransform len /Sy ed\n", | |
+ "llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed\n", | |
+ "rot dup sin abs /S ed cos abs /C ed\n", | |
+ "Sx S mul Sy C mul add /H ed\n", | |
+ "Sx C mul Sy S mul add /W ed\n", | |
+ "sy H div /Scaley ed\n", | |
+ "sx W div /Scalex ed\n", | |
+ "s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if\n", | |
+ "sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed\n", | |
+ "sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed\n", | |
+ "urx llx sub 0 A dtransform exch atan rot exch sub /rot ed\n", | |
+ "n currentmatrix initgraphics setmatrix\n", | |
+ "cx cy translate\n", | |
+ "Scalex Scaley scale\n", | |
+ "rot rotate\n", | |
+ "Cx neg Cy neg translate\n", | |
+ "A concat\n", | |
+ "bbox boxpath clip newpath\n", | |
+ "w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if\n", | |
+ "end\n", | |
+ "gsave\n", | |
+ "%ps_include: inclusion begin\n", | |
+ 0 | |
+}; | |
+ | |
+static char *PS_tail[] = { | |
+ "%ps_include: inclusion end\n", | |
+ "grestore\n", | |
+ "PS-include-dict-dw begin\n", | |
+ "o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice\n", | |
+ " initgraphics 0.1 setlinewidth boxpath stroke grestore} if\n", | |
+ "clear o-stack aload pop\n", | |
+ "context end restore\n", | |
+ "%ps_include: end\n", | |
+ 0 | |
+}; | |
diff --git a/src/cmd/postscript/tr2post/readDESC.c b/src/cmd/postscript/tr2post… | |
t@@ -0,0 +1,139 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <ctype.h> | |
+#include "common.h" | |
+#include "tr2post.h" | |
+#include "comments.h" | |
+#include "path.h" | |
+ | |
+char *printdesclang = 0; | |
+char *encoding = 0; | |
+int devres; | |
+int unitwidth; | |
+int nspechars = 0; | |
+struct charent spechars[MAXSPECHARS]; | |
+ | |
+#define NDESCTOKS 9 | |
+static char *desctoks[NDESCTOKS] = { | |
+ "PDL", | |
+ "Encoding", | |
+ "fonts", | |
+ "sizes", | |
+ "res", | |
+ "hor", | |
+ "vert", | |
+ "unitwidth", | |
+ "charset" | |
+}; | |
+ | |
+char *spechar[MAXSPECHARS]; | |
+ | |
+int | |
+hash(char *s, int l) { | |
+ unsigned i; | |
+ | |
+ for (i=0; *s; s++) | |
+ i = i*10 + *s; | |
+ return(i % l); | |
+} | |
+ | |
+BOOLEAN | |
+readDESC(void) { | |
+ char token[MAXTOKENSIZE]; | |
+ char *descnameformat = "%s/dev%s/DESC"; | |
+ char *descfilename = 0; | |
+ Biobuf *bfd; | |
+ Biobuf *Bfd; | |
+ int i, state = -1; | |
+ int fontindex = 0; | |
+ | |
+ if (debug) Bprint(Bstderr, "readDESC()\n"); | |
+ descfilename = galloc(descfilename, strlen(descnameformat)+strlen(FONT… | |
+ +strlen(devname)+1, "readdesc"); | |
+ sprint(descfilename, descnameformat, FONTDIR, devname); | |
+ if ((bfd = Bopen(unsharp(descfilename), OREAD)) == 0) { | |
+ error(WARNING, "cannot open file %s\n", descfilename); | |
+ return(0); | |
+ } | |
+ Bfd = bfd; | |
+ | |
+ while (Bgetfield(Bfd, 's', token, MAXTOKENSIZE) > 0) { | |
+ for (i=0; i<NDESCTOKS; i++) { | |
+ if (strcmp(desctoks[i], token) == 0) { | |
+ state = i; | |
+ break; | |
+ } | |
+ } | |
+ if (i<NDESCTOKS) continue; | |
+ switch (state) { | |
+ case 0: | |
+ printdesclang=galloc(printdesclang, strlen(token)+1, "… | |
+ strcpy(printdesclang, token); | |
+ if (debug) Bprint(Bstderr, "PDL %s\n", token); | |
+ break; | |
+ case 1: | |
+ encoding=galloc(encoding, strlen(token)+1, "readdesc:"… | |
+ strcpy(encoding, token); | |
+ if (debug) Bprint(Bstderr, "encoding %s\n", token); | |
+ break; | |
+ case 2: | |
+ if (fontmnt <=0) { | |
+ if (!isdigit(*token)) { | |
+ error(WARNING, "readdesc: expecting nu… | |
+ return(FALSE); | |
+ } | |
+ fontmnt = atoi(token) + 1; | |
+ fontmtab = galloc(fontmtab, fontmnt*sizeof(cha… | |
+ | |
+ for (i=0; i<fontmnt; i++) | |
+ fontmtab[i] = 0; | |
+ fontindex = 0; | |
+ } else { | |
+ mountfont(++fontindex, token); | |
+ findtfn(token, TRUE); | |
+ } | |
+ break; | |
+ case 3: | |
+ /* I don't really care about sizes */ | |
+ break; | |
+ case 4: | |
+ /* device resolution in dots per inch */ | |
+ if (!isdigit(*token)) { | |
+ error(WARNING, "readdesc: expecting device res… | |
+ return(FALSE); | |
+ } | |
+ devres = atoi(token); | |
+ if (debug) Bprint(Bstderr, "res %d\n", devres); | |
+ break; | |
+ case 5: | |
+ /* I don't really care about horizontal motion resolut… | |
+ if (debug) Bprint(Bstderr, "ignoring horizontal resolu… | |
+ break; | |
+ case 6: | |
+ /* I don't really care about vertical motion resolutio… | |
+ if (debug) Bprint(Bstderr, "ignoring vertical resoluti… | |
+ break; | |
+ case 7: | |
+ /* unitwidth is the font size at which the character w… | |
+ if (!isdigit(*token)) { | |
+ error(WARNING, "readdesc: expecting unitwidth.… | |
+ return(FALSE); | |
+ } | |
+ unitwidth = atoi(token); | |
+ if (debug) Bprint(Bstderr, "unitwidth %d\n", unitwidth… | |
+ break; | |
+ case 8: | |
+ /* I don't really care about this list of special char… | |
+ if (debug) Bprint(Bstderr, "ignoring special character… | |
+ break; | |
+ default: | |
+ if (*token == '#') | |
+ Brdline(Bfd, '\n'); | |
+ else | |
+ error(WARNING, "unknown token %s in DESC file.… | |
+ break; | |
+ } | |
+ } | |
+ Bterm(Bfd); | |
+} | |
diff --git a/src/cmd/postscript/tr2post/shell.lib b/src/cmd/postscript/tr2post/… | |
t@@ -0,0 +1,1238 @@ | |
+# | |
+# Shell library - for building devutf tables. | |
+# | |
+ | |
+RESOLUTION=720 | |
+UNITWIDTH=10 | |
+ | |
+OCTALESCAPES=${OCTALESCAPES:-160} # <= code means add \0ddd names | |
+DOWNLOADVECTOR=FALSE # TRUE can mean incomplete tables | |
+ | |
+# | |
+# BuiltinTables returns command lines that generate PostScript programs | |
+# for building a typesetter description file and font width tables for | |
+# a relatively standard collection of fonts. Use awk to select a command | |
+# line or modify an existing command to build a width table for a new | |
+# font. | |
+# | |
+ | |
+BuiltinTables() { | |
+ cat <<-'//End of BuiltinTables' | |
+ Proportional R Times-Roman | |
+ Proportional I Times-Italic | |
+ Proportional B Times-Bold | |
+ Proportional BI Times-BoldItalic | |
+ Proportional AB AvantGarde-Demi | |
+ Proportional AI AvantGarde-BookOblique | |
+ Proportional AR AvantGarde-Book | |
+ Proportional AX AvantGarde-DemiOblique | |
+ Proportional H Helvetica | |
+ Proportional HB Helvetica-Bold | |
+ Proportional HI Helvetica-Oblique | |
+ Proportional HX Helvetica-BoldOblique | |
+ Proportional Hb Helvetica-Narrow-Bold | |
+ Proportional Hi Helvetica-Narrow-Oblique | |
+ Proportional Hr Helvetica-Narrow | |
+ Proportional Hx Helvetica-Narrow-BoldOblique | |
+ Proportional KB Bookman-Demi | |
+ Proportional KI Bookman-LightItalic | |
+ Proportional KR Bookman-Light | |
+ Proportional KX Bookman-DemiItalic | |
+ Proportional NB NewCenturySchlbk-Bold | |
+ Proportional NI NewCenturySchlbk-Italic | |
+ Proportional NR NewCenturySchlbk-Roman | |
+ Proportional NX NewCenturySchlbk-BoldItalic | |
+ Proportional PA Palatino-Roman | |
+ Proportional PB Palatino-Bold | |
+ Proportional PI Palatino-Italic | |
+ Proportional PX Palatino-BoldItalic | |
+ Proportional ZI ZapfChancery-MediumItalic | |
+ FixedWidth C Courier | |
+ FixedWidth CB Courier-Bold | |
+ FixedWidth CI Courier-Oblique | |
+ FixedWidth CO Courier | |
+ FixedWidth CW Courier | |
+ FixedWidth CX Courier-BoldOblique | |
+ Dingbats ZD ZapfDingbats | |
+ Greek GR Symbol | |
+ Symbol S Symbol | |
+ Special S1 Times-Roman | |
+ Description DESC --- | |
+ //End of BuiltinTables | |
+} | |
+ | |
+# | |
+# AllTables prints the complete list of builtin font names. | |
+# | |
+ | |
+AllTables() { | |
+ BuiltinTables | awk '{print $2}' | |
+} | |
+ | |
+# | |
+# Charset functions generate keyword/value pairs (as PostScript objects) | |
+# that describe the character set available in a font. The keyword is a | |
+# PostScript string that represents troff's name for the character. The | |
+# value is usually the literal name (i.e. begins with a /) assigned to | |
+# the character in the PostScript font. The value can also be an integer | |
+# or a PostScript string. An integer value is used as an index in the | |
+# current font's Encoding array. A string value is returned to the host | |
+# unchanged when the entry for the character is constructed. Entries that | |
+# have (") as their value are synonyms for the preceeding character. | |
+# | |
+# The 18 characters missing from ROM resident fonts on older printers are | |
+# flagged with the PostScript comment "% missing". | |
+# | |
+ | |
+StandardCharset() { | |
+ cat <<-'//End of StandardCharset' | |
+ (!) /exclam | |
+ (") /quotedbl | |
+ (dq) (") % synonym | |
+ (#) /numbersign | |
+ ($) /dollar | |
+ (%) /percent | |
+ (&) /ampersand | |
+ (') /quoteright | |
+ (\() /parenleft | |
+ (\)) /parenright | |
+ (*) /asterisk | |
+ (+) /plus | |
+ (,) /comma | |
+ (-) /hyphen % changed from minus… | |
+ (.) /period | |
+ (/) /slash | |
+ (0) /zero | |
+ (1) /one | |
+ (2) /two | |
+ (3) /three | |
+ (4) /four | |
+ (5) /five | |
+ (6) /six | |
+ (7) /seven | |
+ (8) /eight | |
+ (9) /nine | |
+ (:) /colon | |
+ (;) /semicolon | |
+ (<) /less | |
+ (=) /equal | |
+ (>) /greater | |
+ (?) /question | |
+ (@) /at | |
+ (A) /A | |
+ (B) /B | |
+ (C) /C | |
+ (D) /D | |
+ (E) /E | |
+ (F) /F | |
+ (G) /G | |
+ (H) /H | |
+ (I) /I | |
+ (J) /J | |
+ (K) /K | |
+ (L) /L | |
+ (M) /M | |
+ (N) /N | |
+ (O) /O | |
+ (P) /P | |
+ (Q) /Q | |
+ (R) /R | |
+ (S) /S | |
+ (T) /T | |
+ (U) /U | |
+ (V) /V | |
+ (W) /W | |
+ (X) /X | |
+ (Y) /Y | |
+ (Z) /Z | |
+ ([) /bracketleft | |
+ (\\) /backslash | |
+ (bs) (") % synonym | |
+ (]) /bracketright | |
+ (^) /asciicircum | |
+ (_) /underscore | |
+ (`) /quoteleft | |
+ (a) /a | |
+ (b) /b | |
+ (c) /c | |
+ (d) /d | |
+ (e) /e | |
+ (f) /f | |
+ (g) /g | |
+ (h) /h | |
+ (i) /i | |
+ (j) /j | |
+ (k) /k | |
+ (l) /l | |
+ (m) /m | |
+ (n) /n | |
+ (o) /o | |
+ (p) /p | |
+ (q) /q | |
+ (r) /r | |
+ (s) /s | |
+ (t) /t | |
+ (u) /u | |
+ (v) /v | |
+ (w) /w | |
+ (x) /x | |
+ (y) /y | |
+ (z) /z | |
+ ({) /braceleft | |
+ (|) /bar | |
+ (}) /braceright | |
+ (~) /asciitilde | |
+ (\\`) /grave % devpost character | |
+ (ga) (") % synonym | |
+ (!!) /exclamdown | |
+ (c|) /cent | |
+ (ct) (") % devpost synonym | |
+ (L-) /sterling | |
+ (ps) (") % devpost synonym | |
+ (xo) /currency | |
+ (cr) (") % devpost synonym | |
+ (Y-) /yen | |
+ (yn) (") % devpost synonym | |
+ (||) /brokenbar % missing | |
+ (so) /section | |
+ (sc) (") % devpost synonym | |
+ ("") /dieresis | |
+ (:a) (") % devpost synonym | |
+ (co) /copyright | |
+ (a_) /ordfeminine | |
+ (<<) /guillemotleft | |
+ (-,) /logicalnot | |
+ (hy) /hyphen | |
+ (--) /minus | |
+ (ro) /registered | |
+ (rg) (") % devpost synonym | |
+ (-^) /macron | |
+ (-a) (") % devpost synonym | |
+ (0^) /degree % missing | |
+ (+-) /plusminus % missing | |
+ (2^) /twosuperior % missing | |
+ (3^) /threesuperior % missing | |
+ (\\') /acute | |
+ (aa) (") % devpost synonym | |
+ (/u) /mu % missing | |
+ (P!) /paragraph | |
+ (pg) (") % devpost synonym | |
+ (.^) /periodcentered | |
+ (,,) /cedilla | |
+ (,a) (") % devpost synonym | |
+ (1^) /onesuperior % missing | |
+ (o_) /ordmasculine | |
+ (>>) /guillemotright | |
+ (14) /onequarter % missing | |
+ (12) /onehalf % missing | |
+ (34) /threequarters % missing | |
+ (??) /questiondown | |
+ (A`) /Agrave | |
+ (A') /Aacute | |
+ (A^) /Acircumflex | |
+ (A~) /Atilde | |
+ (A") /Adieresis | |
+ (A*) /Aring | |
+ (AE) /AE | |
+ (C,) /Ccedilla | |
+ (E`) /Egrave | |
+ (E') /Eacute | |
+ (E^) /Ecircumflex | |
+ (E") /Edieresis | |
+ (I`) /Igrave | |
+ (I') /Iacute | |
+ (I^) /Icircumflex | |
+ (I") /Idieresis | |
+ (D-) /Eth % missing | |
+ (N~) /Ntilde | |
+ (O`) /Ograve | |
+ (O') /Oacute | |
+ (O^) /Ocircumflex | |
+ (O~) /Otilde | |
+ (O") /Odieresis | |
+ (xx) /multiply % missing | |
+ (O/) /Oslash | |
+ (U`) /Ugrave | |
+ (U') /Uacute | |
+ (U^) /Ucircumflex | |
+ (U") /Udieresis | |
+ (Y') /Yacute % missing | |
+ (TH) /Thorn % missing | |
+ (ss) /germandbls | |
+ (a`) /agrave | |
+ (a') /aacute | |
+ (a^) /acircumflex | |
+ (a~) /atilde | |
+ (a") /adieresis | |
+ (a*) /aring | |
+ (ae) /ae | |
+ (c,) /ccedilla | |
+ (e`) /egrave | |
+ (e') /eacute | |
+ (e^) /ecircumflex | |
+ (e") /edieresis | |
+ (i`) /igrave | |
+ (i') /iacute | |
+ (i^) /icircumflex | |
+ (i") /idieresis | |
+ (d-) /eth % missing | |
+ (n~) /ntilde | |
+ (o`) /ograve | |
+ (o') /oacute | |
+ (o^) /ocircumflex | |
+ (o~) /otilde | |
+ (o") /odieresis | |
+ (-:) /divide % missing | |
+ (o/) /oslash | |
+ (u`) /ugrave | |
+ (u') /uacute | |
+ (u^) /ucircumflex | |
+ (u") /udieresis | |
+ (y') /yacute % missing | |
+ (th) /thorn % missing | |
+ (y") /ydieresis | |
+ (^a) /circumflex % devpost accent | |
+ (~a) /tilde % devpost accent | |
+ (Ua) /breve % devpost accent | |
+ (.a) /dotaccent % devpost accent | |
+ (oa) /ring % devpost accent | |
+ ("a) /hungarumlaut % devpost accent | |
+ (Ca) /ogonek % devpost accent | |
+ (va) /caron % devpost accent | |
+ //End of StandardCharset | |
+} | |
+ | |
+# | |
+# DingbatsCharset guarantees changes in StandardCharset don't show up in ZD. | |
+# | |
+ | |
+DingbatsCharset() { | |
+ cat <<-'//End of DingbatsCharset' | |
+ (!) /exclam | |
+ (") /quotedbl | |
+ (#) /numbersign | |
+ ($) /dollar | |
+ (%) /percent | |
+ (&) /ampersand | |
+ (') /quoteright | |
+ (\() /parenleft | |
+ (\)) /parenright | |
+ (*) /asterisk | |
+ (+) /plus | |
+ (,) /comma | |
+ (-) /minus % also hyphen in devpost | |
+ (.) /period | |
+ (/) /slash | |
+ (0) /zero | |
+ (1) /one | |
+ (2) /two | |
+ (3) /three | |
+ (4) /four | |
+ (5) /five | |
+ (6) /six | |
+ (7) /seven | |
+ (8) /eight | |
+ (9) /nine | |
+ (:) /colon | |
+ (;) /semicolon | |
+ (<) /less | |
+ (=) /equal | |
+ (>) /greater | |
+ (?) /question | |
+ (@) /at | |
+ (A) /A | |
+ (B) /B | |
+ (C) /C | |
+ (D) /D | |
+ (E) /E | |
+ (F) /F | |
+ (G) /G | |
+ (H) /H | |
+ (I) /I | |
+ (J) /J | |
+ (K) /K | |
+ (L) /L | |
+ (M) /M | |
+ (N) /N | |
+ (O) /O | |
+ (P) /P | |
+ (Q) /Q | |
+ (R) /R | |
+ (S) /S | |
+ (T) /T | |
+ (U) /U | |
+ (V) /V | |
+ (W) /W | |
+ (X) /X | |
+ (Y) /Y | |
+ (Z) /Z | |
+ ([) /bracketleft | |
+ (\\) /backslash | |
+ (]) /bracketright | |
+ (^) /asciicircum | |
+ (_) /underscore | |
+ (`) /quoteleft | |
+ (a) /a | |
+ (b) /b | |
+ (c) /c | |
+ (d) /d | |
+ (e) /e | |
+ (f) /f | |
+ (g) /g | |
+ (h) /h | |
+ (i) /i | |
+ (j) /j | |
+ (k) /k | |
+ (l) /l | |
+ (m) /m | |
+ (n) /n | |
+ (o) /o | |
+ (p) /p | |
+ (q) /q | |
+ (r) /r | |
+ (s) /s | |
+ (t) /t | |
+ (u) /u | |
+ (v) /v | |
+ (w) /w | |
+ (x) /x | |
+ (y) /y | |
+ (z) /z | |
+ ({) /braceleft | |
+ (|) /bar | |
+ (}) /braceright | |
+ (~) /asciitilde | |
+ (\\`) /grave % devpost character | |
+ (!!) /exclamdown | |
+ (c|) /cent | |
+ (L-) /sterling | |
+ (xo) /currency | |
+ (Y-) /yen | |
+ (||) /brokenbar % missing | |
+ (so) /section | |
+ ("") /dieresis | |
+ (co) /copyright | |
+ (a_) /ordfeminine | |
+ (<<) /guillemotleft | |
+ (-,) /logicalnot | |
+ (hy) /hyphen | |
+ (ro) /registered | |
+ (-^) /macron | |
+ (0^) /degree % missing | |
+ (+-) /plusminus % missing | |
+ (2^) /twosuperior % missing | |
+ (3^) /threesuperior % missing | |
+ (\\') /acute | |
+ (/u) /mu % missing | |
+ (P!) /paragraph | |
+ (.^) /periodcentered | |
+ (,,) /cedilla | |
+ (1^) /onesuperior % missing | |
+ (o_) /ordmasculine | |
+ (>>) /guillemotright | |
+ (14) /onequarter % missing | |
+ (12) /onehalf % missing | |
+ (34) /threequarters % missing | |
+ (??) /questiondown | |
+ (A`) /Agrave | |
+ (A') /Aacute | |
+ (A^) /Acircumflex | |
+ (A~) /Atilde | |
+ (A") /Adieresis | |
+ (A*) /Aring | |
+ (AE) /AE | |
+ (C,) /Ccedilla | |
+ (E`) /Egrave | |
+ (E') /Eacute | |
+ (E^) /Ecircumflex | |
+ (E") /Edieresis | |
+ (I`) /Igrave | |
+ (I') /Iacute | |
+ (I^) /Icircumflex | |
+ (I") /Idieresis | |
+ (D-) /Eth % missing | |
+ (N~) /Ntilde | |
+ (O`) /Ograve | |
+ (O') /Oacute | |
+ (O^) /Ocircumflex | |
+ (O~) /Otilde | |
+ (O") /Odieresis | |
+ (xx) /multiply % missing | |
+ (O/) /Oslash | |
+ (U`) /Ugrave | |
+ (U') /Uacute | |
+ (U^) /Ucircumflex | |
+ (U") /Udieresis | |
+ (Y') /Yacute % missing | |
+ (TH) /Thorn % missing | |
+ (ss) /germandbls | |
+ (a`) /agrave | |
+ (a') /aacute | |
+ (a^) /acircumflex | |
+ (a~) /atilde | |
+ (a") /adieresis | |
+ (a*) /aring | |
+ (ae) /ae | |
+ (c,) /ccedilla | |
+ (e`) /egrave | |
+ (e') /eacute | |
+ (e^) /ecircumflex | |
+ (e") /edieresis | |
+ (i`) /igrave | |
+ (i') /iacute | |
+ (i^) /icircumflex | |
+ (i") /idieresis | |
+ (d-) /eth % missing | |
+ (n~) /ntilde | |
+ (o`) /ograve | |
+ (o') /oacute | |
+ (o^) /ocircumflex | |
+ (o~) /otilde | |
+ (o") /odieresis | |
+ (-:) /divide % missing | |
+ (o/) /oslash | |
+ (u`) /ugrave | |
+ (u') /uacute | |
+ (u^) /ucircumflex | |
+ (u") /udieresis | |
+ (y') /yacute % missing | |
+ (th) /thorn % missing | |
+ (y") /ydieresis | |
+ //End of DingbatsCharset | |
+} | |
+ | |
+SymbolCharset() { | |
+ cat <<-'//End of SymbolCharset' | |
+ (---) /exclam | |
+ (fa) /universal | |
+ (---) /numbersign | |
+ (te) /existential | |
+ (---) /percent | |
+ (---) /ampersand | |
+ (st) /suchthat | |
+ (---) /parenleft | |
+ (---) /parenright | |
+ (**) /asteriskmath | |
+ (pl) /plus | |
+ (---) /comma | |
+ (mi) /minus | |
+ (---) /period | |
+ (sl) /slash | |
+ (---) /zero | |
+ (---) /one | |
+ (---) /two | |
+ (---) /three | |
+ (---) /four | |
+ (---) /five | |
+ (---) /six | |
+ (---) /seven | |
+ (---) /eight | |
+ (---) /nine | |
+ (---) /colon | |
+ (---) /semicolon | |
+ (<) /less | |
+ (eq) /equal | |
+ (>) /greater | |
+ (---) /question | |
+ (cg) /congruent | |
+ (*A) /Alpha | |
+ (\244x) (") | |
+ (*B) /Beta | |
+ (\244y) (") | |
+ (*X) /Chi | |
+ (\244\257) (") | |
+ (*D) /Delta | |
+ (\244{) (") | |
+ (*E) /Epsilon | |
+ (\244|) (") | |
+ (*F) /Phi | |
+ (\244\256) (") | |
+ (*G) /Gamma | |
+ (\244z) (") | |
+ (*Y) /Eta | |
+ (\244~) (") | |
+ (*I) /Iota | |
+ (\244\241) (") | |
+ (---) /theta1 | |
+ (\244\331) (") | |
+ (*K) /Kappa | |
+ (\244\242) (") | |
+ (*L) /Lambda | |
+ (\244\243) (") | |
+ (*M) /Mu | |
+ (\244\244) (") | |
+ (*N) /Nu | |
+ (\244\245) (") | |
+ (*O) /Omicron | |
+ (\244\247) (") | |
+ (*P) /Pi | |
+ (\244\250) (") | |
+ (*H) /Theta | |
+ (\244\240) (") | |
+ (*R) /Rho | |
+ (\244\251) (") | |
+ (*S) /Sigma | |
+ (\244\253) (") | |
+ (*T) /Tau | |
+ (\244\254) (") | |
+ (*U) /Upsilon | |
+ (\244\255) (") | |
+ (ts) /sigma1 | |
+ (\244\312) (") | |
+ (*W) /Omega | |
+ (\244\261) (") | |
+ (*C) /Xi | |
+ (\244\246) (") | |
+ (*Q) /Psi | |
+ (\244\260) (") | |
+ (*Z) /Zeta | |
+ (\244}) (") | |
+ (---) /bracketleft | |
+ (tf) /therefore | |
+ (---) /bracketright | |
+ (pp) /perpendicular | |
+ (ul) /underscore | |
+ (_) (") % synonym | |
+ (rn) /radicalex | |
+ (*a) /alpha | |
+ (\244\271) (") | |
+ (*b) /beta | |
+ (\244\272) (") | |
+ (*x) /chi | |
+ (\244\317) (") | |
+ (*d) /delta | |
+ (\244\274) (") | |
+ (*e) /epsilon | |
+ (\244\275) (") | |
+ (*f) /phi | |
+ (\244\316) (") | |
+ (*g) /gamma | |
+ (\244\273) (") | |
+ (*y) /eta | |
+ (\244\277) (") | |
+ (*i) /iota | |
+ (\244\301) (") | |
+ (---) /phi1 | |
+ (\244\335) (") | |
+ (*k) /kappa | |
+ (\244\302) (") | |
+ (*l) /lambda | |
+ (\244\303) (") | |
+ (*m) /mu | |
+ (\244\304) (") | |
+ (*n) /nu | |
+ (\244\305) (") | |
+ (*o) /omicron | |
+ (\244\307) (") | |
+ (*p) /pi | |
+ (\244\310) (") | |
+ (*h) /theta | |
+ (\244\300) (") | |
+ (*r) /rho | |
+ (\244\311) (") | |
+ (*s) /sigma | |
+ (\244\313) (") | |
+ (*t) /tau | |
+ (\244\314) (") | |
+ (*u) /upsilon | |
+ (\244\315) (") | |
+ (---) /omega1 | |
+ (\244\336) (") | |
+ (*w) /omega | |
+ (\244\321) (") | |
+ (*c) /xi | |
+ (\244\306) (") | |
+ (*q) /psi | |
+ (\244\320) (") | |
+ (*z) /zeta | |
+ (\244\276) (") | |
+ (---) /braceleft | |
+ (or) /bar | |
+ (---) /braceright | |
+ (ap) /similar | |
+ (---) /Upsilon1 | |
+ (fm) /minute | |
+ (<=) /lessequal | |
+ (fr) /fraction % devpost charact… | |
+ (if) /infinity | |
+ (fn) /florin % devpost c… | |
+ (---) /club | |
+ (---) /diamond | |
+ (---) /heart | |
+ (---) /spade | |
+ (ab) /arrowboth | |
+ (<-) /arrowleft | |
+ (ua) /arrowup | |
+ (->) /arrowright | |
+ (da) /arrowdown | |
+ (de) /degree | |
+ (+-) /plusminus | |
+ (---) /second | |
+ (>=) /greaterequal | |
+ (mu) /multiply | |
+ (pt) /proportional | |
+ (pd) /partialdiff | |
+ (bu) /bullet | |
+ (di) /divide | |
+ (!=) /notequal | |
+ (==) /equivalence | |
+ (~~) /approxequal | |
+ (el) /ellipsis | |
+ (av) /arrowvertex | |
+ (ah) /arrowhorizex | |
+ (CR) /carriagereturn | |
+ (af) /aleph | |
+ (If) /Ifraktur | |
+ (Rf) /Rfraktur | |
+ (ws) /weierstrass | |
+ (Ox) /circlemultiply | |
+ (O+) /circleplus | |
+ (es) /emptyset | |
+ (ca) /intersection | |
+ (cu) /union | |
+ (sp) /propersuperset | |
+ (ip) /reflexsuperset | |
+ (!b) /notsubset | |
+ (sb) /propersubset | |
+ (ib) /reflexsubset | |
+ (mo) /element | |
+ (!m) /notelement | |
+ (an) /angle | |
+ (gr) /gradient | |
+ (rg) /registerserif | |
+ (co) /copyrightserif | |
+ (tm) /trademarkserif | |
+ (---) /product | |
+ (sr) /radical | |
+ (c.) /dotmath | |
+ (no) /logicalnot | |
+ (l&) /logicaland | |
+ (l|) /logicalor | |
+ (---) /arrowdblboth | |
+ (---) /arrowdblleft | |
+ (---) /arrowdblup | |
+ (---) /arrowdblright | |
+ (---) /arrowdbldown | |
+ (lz) /lozenge | |
+ (b<) /angleleft | |
+ (RG) /registersans | |
+ (CO) /copyrightsans | |
+ (TM) /trademarksans | |
+ (---) /summation | |
+ (LT) /parenlefttp | |
+ (br) /parenleftex | |
+ (LX) (") % synonym | |
+ (LB) /parenleftbt | |
+ (lc) /bracketlefttp | |
+ (lx) /bracketleftex | |
+ (lf) /bracketleftbt | |
+ (lt) /bracelefttp | |
+ (lk) /braceleftmid | |
+ (lb) /braceleftbt | |
+ (bv) /braceex | |
+ (|) (") % synonym | |
+ (b>) /angleright | |
+ (is) /integral | |
+ (---) /integraltp | |
+ (---) /integralex | |
+ (---) /integralbt | |
+ (RT) /parenrighttp | |
+ (RX) /parenrightex | |
+ (RB) /parenrightbt | |
+ (rc) /bracketrighttp | |
+ (rx) /bracketrightex | |
+ (rf) /bracketrightbt | |
+ (rt) /bracerighttp | |
+ (rk) /bracerightmid | |
+ (rb) /bracerightbt | |
+ (~=) (55 0 1) % charlib | |
+ //End of SymbolCharset | |
+} | |
+ | |
+SpecialCharset() { | |
+ cat <<-'//End of SpecialCharset' | |
+ (ru) /underscore | |
+ ('') /quotedblright % devpost character | |
+ (``) /quotedblleft % devpost character | |
+ (dg) /dagger % devpost character | |
+ (dd) /daggerdbl % devpost character | |
+ (en) /endash % devpost character | |
+ (\\-) (") % synonym | |
+ (em) /emdash | |
+% (ff) (60 2 1) % charlib | |
+% (Fi) (84 2 1) % charlib | |
+% (Fl) (84 2 1) % charlib | |
+ (14) (75 2 1) % charlib | |
+ (12) (75 2 1) % charlib | |
+ (34) (75 2 1) % charlib | |
+ (bx) (50 2 1) % charlib | |
+ (ob) (38 2 1) % charlib | |
+ (ci) (75 0 1) % charlib | |
+ (sq) (50 2 1) % charlib | |
+ (Sl) (50 2 1) % charlib | |
+ (L1) (110 1 1) % charlib | |
+ (LA) (110 1 1) % charlib | |
+ (LV) (110 3 1) % charlib | |
+ (LH) (210 1 1) % charlib | |
+ (lh) (100 0 1) % charlib | |
+ (rh) (100 0 1) % charlib | |
+ (lH) (100 0 1) % charlib | |
+ (rH) (100 0 1) % charlib | |
+ (PC) (220 2 1) % charlib | |
+ (DG) (185 2 1) % charlib | |
+ //End of SpecialCharset | |
+} | |
+ | |
+# | |
+# Latin1 ensures a font uses the ISOLatin1Encoding vector, although only | |
+# text fonts should be re-encoded. Downloading the Encoding vector doesn't | |
+# often make sense. No ISOLatin1Encoding array likely means ROM based fonts | |
+# on your printer are incomplete. Type 1 fonts with a full Latin1 character | |
+# set appeared sometime after Version 50.0. | |
+# | |
+ | |
+Latin1() { | |
+ if [ "$DOWNLOADVECTOR" = TRUE ]; then | |
+ cat <<-'//End of ISOLatin1Encoding' | |
+ /ISOLatin1Encoding [ | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /space | |
+ /exclam | |
+ /quotedbl | |
+ /numbersign | |
+ /dollar | |
+ /percent | |
+ /ampersand | |
+ /quoteright | |
+ /parenleft | |
+ /parenright | |
+ /asterisk | |
+ /plus | |
+ /comma | |
+ /minus | |
+ /period | |
+ /slash | |
+ /zero | |
+ /one | |
+ /two | |
+ /three | |
+ /four | |
+ /five | |
+ /six | |
+ /seven | |
+ /eight | |
+ /nine | |
+ /colon | |
+ /semicolon | |
+ /less | |
+ /equal | |
+ /greater | |
+ /question | |
+ /at | |
+ /A | |
+ /B | |
+ /C | |
+ /D | |
+ /E | |
+ /F | |
+ /G | |
+ /H | |
+ /I | |
+ /J | |
+ /K | |
+ /L | |
+ /M | |
+ /N | |
+ /O | |
+ /P | |
+ /Q | |
+ /R | |
+ /S | |
+ /T | |
+ /U | |
+ /V | |
+ /W | |
+ /X | |
+ /Y | |
+ /Z | |
+ /bracketleft | |
+ /backslash | |
+ /bracketright | |
+ /asciicircum | |
+ /underscore | |
+ /quoteleft | |
+ /a | |
+ /b | |
+ /c | |
+ /d | |
+ /e | |
+ /f | |
+ /g | |
+ /h | |
+ /i | |
+ /j | |
+ /k | |
+ /l | |
+ /m | |
+ /n | |
+ /o | |
+ /p | |
+ /q | |
+ /r | |
+ /s | |
+ /t | |
+ /u | |
+ /v | |
+ /w | |
+ /x | |
+ /y | |
+ /z | |
+ /braceleft | |
+ /bar | |
+ /braceright | |
+ /asciitilde | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /.notdef | |
+ /dotlessi | |
+ /grave | |
+ /acute | |
+ /circumflex | |
+ /tilde | |
+ /macron | |
+ /breve | |
+ /dotaccent | |
+ /dieresis | |
+ /.notdef | |
+ /ring | |
+ /cedilla | |
+ /.notdef | |
+ /hungarumlaut | |
+ /ogonek | |
+ /caron | |
+ /space | |
+ /exclamdown | |
+ /cent | |
+ /sterling | |
+ /currency | |
+ /yen | |
+ /brokenbar | |
+ /section | |
+ /dieresis | |
+ /copyright | |
+ /ordfeminine | |
+ /guillemotleft | |
+ /logicalnot | |
+ /hyphen | |
+ /registered | |
+ /macron | |
+ /degree | |
+ /plusminus | |
+ /twosuperior | |
+ /threesuperior | |
+ /acute | |
+ /mu | |
+ /paragraph | |
+ /periodcentered | |
+ /cedilla | |
+ /onesuperior | |
+ /ordmasculine | |
+ /guillemotright | |
+ /onequarter | |
+ /onehalf | |
+ /threequarters | |
+ /questiondown | |
+ /Agrave | |
+ /Aacute | |
+ /Acircumflex | |
+ /Atilde | |
+ /Adieresis | |
+ /Aring | |
+ /AE | |
+ /Ccedilla | |
+ /Egrave | |
+ /Eacute | |
+ /Ecircumflex | |
+ /Edieresis | |
+ /Igrave | |
+ /Iacute | |
+ /Icircumflex | |
+ /Idieresis | |
+ /Eth | |
+ /Ntilde | |
+ /Ograve | |
+ /Oacute | |
+ /Ocircumflex | |
+ /Otilde | |
+ /Odieresis | |
+ /multiply | |
+ /Oslash | |
+ /Ugrave | |
+ /Uacute | |
+ /Ucircumflex | |
+ /Udieresis | |
+ /Yacute | |
+ /Thorn | |
+ /germandbls | |
+ /agrave | |
+ /aacute | |
+ /acircumflex | |
+ /atilde | |
+ /adieresis | |
+ /aring | |
+ /ae | |
+ /ccedilla | |
+ /egrave | |
+ /eacute | |
+ /ecircumflex | |
+ /edieresis | |
+ /igrave | |
+ /iacute | |
+ /icircumflex | |
+ /idieresis | |
+ /eth | |
+ /ntilde | |
+ /ograve | |
+ /oacute | |
+ /ocircumflex | |
+ /otilde | |
+ /odieresis | |
+ /divide | |
+ /oslash | |
+ /ugrave | |
+ /uacute | |
+ /ucircumflex | |
+ /udieresis | |
+ /yacute | |
+ /thorn | |
+ /ydieresis | |
+ ] def | |
+ //End of ISOLatin1Encoding | |
+ fi | |
+ | |
+ echo "ISOLatin1Encoding /$1 ReEncode" | |
+} | |
+ | |
+# | |
+# Generating functions output PostScript programs that build font width | |
+# tables or a typesetter description file. Send the program to a printer | |
+# and the complete table will come back on the serial port. All write on | |
+# stdout and assume the prologue and other required PostScript files are | |
+# all available. | |
+# | |
+ | |
+Proportional() { | |
+ echo "/unitwidth $UNITWIDTH def" | |
+ echo "/resolution $RESOLUTION def" | |
+ echo "/octalescapes $OCTALESCAPES def" | |
+ echo "/charset [" | |
+ # Get <>_ and | from S. Use accents for ascii ^ and ~. | |
+ StandardCharset | awk ' | |
+ $1 == "(<)" && $2 == "/less" {$1 = "(---)"} | |
+ $1 == "(>)" && $2 == "/greater" {$1 = "(---)"} | |
+ $1 == "(_)" && $2 == "/underscore" {$1 = "(---)"} | |
+ $1 == "(|)" && $2 == "/bar" {$1 = "(---)"} | |
+ $1 == "(^)" && $2 == "/asciicircum" { | |
+ printf "(^)\t/circumflex\n" | |
+ $1 = "(---)" | |
+ } | |
+ $1 == "(~)" && $2 == "/asciitilde" { | |
+ printf "(~)\t/tilde\n" | |
+ $1 = "(---)" | |
+ } | |
+ {printf "%s\t%s\n", $1, $2} | |
+ ' | |
+ echo "] def" | |
+ | |
+ Latin1 $2 | |
+ echo "/$2 SelectFont" | |
+ echo "(opO) SetAscender" | |
+ | |
+ echo "(name $1\\\\n) Print" | |
+ echo "(fontname $2\\\\n) Print" | |
+ echo "/$1 NamedInPrologue" | |
+ echo "(spacewidth ) Print 32 GetWidth Print (\n) Print" | |
+ echo "(charset\\\\n) Print" | |
+ echo "BuildFontCharset" | |
+} | |
+ | |
+FixedWidth() { | |
+ echo "/unitwidth $UNITWIDTH def" | |
+ echo "/resolution $RESOLUTION def" | |
+ echo "/octalescapes $OCTALESCAPES def" | |
+ echo "/charset [" | |
+ StandardCharset | |
+ echo "] def" | |
+ | |
+ Latin1 $2 | |
+ echo "/$2 SelectFont" | |
+ echo "(opO) SetAscender" | |
+ | |
+ echo "(name $1\\\\n) Print" | |
+ echo "(fontname $2\\\\n) Print" | |
+ echo "/$1 NamedInPrologue" | |
+ echo "(spacewidth ) Print 32 GetWidth Print (\n) Print" | |
+ echo "(charset\\\\n) Print" | |
+ echo "BuildFontCharset" | |
+} | |
+ | |
+Dingbats() { | |
+ echo "/unitwidth $UNITWIDTH def" | |
+ echo "/resolution $RESOLUTION def" | |
+ echo "/octalescapes $OCTALESCAPES def" | |
+ echo "/charset [" | |
+ DingbatsCharset | awk '$1 != "(---)" && $2 ~ /^\/[a-zA-Z]/ { | |
+ printf "%s\tISOLatin1Encoding %s GetCode\n", $1, $2 | |
+ }' | |
+ echo "] def" | |
+ | |
+ echo "/$2 SelectFont" | |
+ echo "( ) SetAscender" | |
+ | |
+ echo "(name $1\\\\n) Print" | |
+ echo "(fontname $2\\\\n) Print" | |
+ echo "/$1 NamedInPrologue" | |
+ echo "(charset\\\\n) Print" | |
+ echo "BuildFontCharset" | |
+} | |
+ | |
+Greek() { | |
+ echo "/unitwidth $UNITWIDTH def" | |
+ echo "/resolution $RESOLUTION def" | |
+ echo "/charset [" | |
+ SymbolCharset | awk ' | |
+ BEGIN {hit = -1} | |
+ $1 ~ /\(\*[a-zA-Z]\)/ {print; hit = NR} | |
+ $2 == "(\")" && hit == NR-1 {print; hit = NR} | |
+ ' | |
+ echo "] def" | |
+ | |
+ echo "/$2 SelectFont" | |
+ echo "(orO) SetAscender" | |
+ | |
+ echo "(name $1\\\\n) Print" | |
+ echo "(fontname $2\\\\n) Print" | |
+ echo "/$1 NamedInPrologue" | |
+ echo "(spacewidth ) Print 32 GetWidth Print (\n) Print" | |
+ echo "(charset\\\\n) Print" | |
+ echo "BuildFontCharset" | |
+} | |
+ | |
+Symbol() { | |
+ echo "/unitwidth $UNITWIDTH def" | |
+ echo "/resolution $RESOLUTION def" | |
+ echo "/charset [" | |
+ SymbolCharset | |
+ echo "] def" | |
+ | |
+ echo "ChangeMetrics" | |
+ echo "/S SelectFont" | |
+ echo "(orO) SetAscender" | |
+ | |
+ echo "(name $1\\\\n) Print" | |
+ echo "(fontname $2\\\\n) Print" | |
+ echo "/$1 NamedInPrologue" | |
+ echo "(special\\\\n) Print" | |
+ echo "(charset\\\\n) Print" | |
+ echo "BuildFontCharset" | |
+} | |
+ | |
+Special() { | |
+ echo "/unitwidth $UNITWIDTH def" | |
+ echo "/resolution $RESOLUTION def" | |
+ echo "/charset [" | |
+ SpecialCharset | |
+ echo "] def" | |
+ | |
+ echo "ChangeMetrics" | |
+ echo "/S1 SelectFont" | |
+ | |
+ echo "(# Times-Roman special font\\\\n) Print" | |
+ echo "(name $1\\\\n) Print" | |
+ echo "(fontname $2\\\\n) Print" | |
+ echo "/$1 NamedInPrologue" | |
+ echo "(special\\\\n) Print" | |
+ echo "(charset\\\\n) Print" | |
+ echo "BuildFontCharset" | |
+} | |
+ | |
+# | |
+# The DESC file doesn't have to be built on a printer. It's only here for | |
+# consistency. | |
+# | |
+ | |
+Description() { | |
+ echo "/charset [" # awk - so the stack doesn't overflow | |
+ StandardCharset | awk '$1 !~ /\(\\[0-9]/ {print $1}' | |
+ SymbolCharset | awk '$1 !~ /\(\\[0-9]/ {print $1}' | |
+ SpecialCharset | awk '$1 !~ /\(\\[0-9]/ {print $1}' | |
+ echo "] def" | |
+ | |
+ cat <<-//DESC | |
+ (#Device Description - utf character set | |
+ | |
+ PDL PostScript | |
+ Encoding Latin1 | |
+ | |
+ fonts 10 R I B BI CW H HI HB S1 S | |
+ sizes 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
+ 23 24 25 26 27 28 29 30 31 32 33 34 35 36 38 40 42 44 46 | |
+ 48 50 52 54 56 58 60 64 68 72 78 84 90 96 100 105 110 115 | |
+ 120 125 130 135 140 145 150 155 160 0 | |
+ res $RESOLUTION | |
+ hor 1 | |
+ vert 1 | |
+ unitwidth $UNITWIDTH | |
+ | |
+ //DESC | |
+ echo "(charset\\\\n) Print" | |
+ echo "BuildDescCharset" | |
+ echo "(\\\\n) Print" | |
+} | |
+ | |
diff --git a/src/cmd/postscript/tr2post/tr2post.c b/src/cmd/postscript/tr2post/… | |
t@@ -0,0 +1,218 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include <stdio.h> | |
+#include "common.h" | |
+#include "tr2post.h" | |
+#include "comments.h" | |
+#include "path.h" | |
+ | |
+int formsperpage = 1; | |
+int picflag = 1; | |
+double aspectratio = 1.0; | |
+int copies = 1; | |
+int landscape = 0; | |
+double magnification = 1.0; | |
+int linesperpage = 66; | |
+int pointsize = 10; | |
+double xoffset = .25; | |
+double yoffset = .25; | |
+char *passthrough = 0; | |
+ | |
+Biobuf binp, *bstdout, bstderr; | |
+Biobuf *Bstdin, *Bstdout, *Bstderr; | |
+int debug = 0; | |
+ | |
+char tmpfilename[MAXTOKENSIZE]; | |
+char copybuf[BUFSIZ]; | |
+ | |
+ | |
+struct charent **build_char_list = 0; | |
+int build_char_cnt = 0; | |
+ | |
+void | |
+prologues(void) { | |
+ int i; | |
+ char charlibname[MAXTOKENSIZE]; | |
+ | |
+ Bprint(Bstdout, "%s", CONFORMING); | |
+ Bprint(Bstdout, "%s %s\n", VERSION, PROGRAMVERSION); | |
+ Bprint(Bstdout, "%s %s\n", DOCUMENTFONTS, ATEND); | |
+ Bprint(Bstdout, "%s %s\n", PAGES, ATEND); | |
+ Bprint(Bstdout, "%s", ENDCOMMENTS); | |
+ | |
+ if (cat(unsharp(DPOST))) { | |
+ Bprint(Bstderr, "can't read %s\n", DPOST); | |
+ exits("dpost prologue"); | |
+ } | |
+ | |
+ if (drawflag) { | |
+ if (cat(unsharp(DRAW))) { | |
+ Bprint(Bstderr, "can't read %s\n", DRAW); | |
+ exits("draw prologue"); | |
+ } | |
+ } | |
+ | |
+ if (DOROUND) | |
+ cat(unsharp(ROUNDPAGE)); | |
+ | |
+ Bprint(Bstdout, "%s", ENDPROLOG); | |
+ Bprint(Bstdout, "%s", BEGINSETUP); | |
+ Bprint(Bstdout, "mark\n"); | |
+ if (formsperpage > 1) { | |
+ Bprint(Bstdout, "%s %d\n", FORMSPERPAGE, formsperpage); | |
+ Bprint(Bstdout, "/formsperpage %d def\n", formsperpage); | |
+ } | |
+ if (aspectratio != 1) Bprint(Bstdout, "/aspectratio %g def\n", aspectr… | |
+ if (copies != 1) Bprint(Bstdout, "/#copies %d store\n", copies); | |
+ if (landscape) Bprint(Bstdout, "/landscape true def\n"); | |
+ if (magnification != 1) Bprint(Bstdout, "/magnification %g def\n", mag… | |
+ if (pointsize != 10) Bprint(Bstdout, "/pointsize %d def\n", pointsize); | |
+ if (xoffset != .25) Bprint(Bstdout, "/xoffset %g def\n", xoffset); | |
+ if (yoffset != .25) Bprint(Bstdout, "/yoffset %g def\n", yoffset); | |
+ cat(unsharp(ENCODINGDIR"/Latin1.enc")); | |
+ if (passthrough != 0) Bprint(Bstdout, "%s\n", passthrough); | |
+ | |
+ Bprint(Bstdout, "setup\n"); | |
+ if (formsperpage > 1) { | |
+ cat(unsharp(FORMFILE)); | |
+ Bprint(Bstdout, "%d setupforms \n", formsperpage); | |
+ } | |
+/* output Build character info from charlib if necessary. */ | |
+ | |
+ for (i=0; i<build_char_cnt; i++) { | |
+ sprint(charlibname, "%s/%s", CHARLIB, build_char_list[i]->name… | |
+ if (cat(unsharp(charlibname))) | |
+ Bprint(Bstderr, "cannot open %s\n", charlibname); | |
+ } | |
+ | |
+ Bprint(Bstdout, "%s", ENDSETUP); | |
+} | |
+ | |
+void | |
+cleanup(void) { | |
+ remove(tmpfilename); | |
+} | |
+ | |
+main(int argc, char *argv[]) { | |
+ Biobuf *binp; | |
+ Biobuf *Binp; | |
+ int i, tot, ifd; | |
+ char *t; | |
+ | |
+ programname = argv[0]; | |
+ if (Binit(&bstderr, 2, OWRITE) == Beof) { | |
+ exits("Binit"); | |
+ } | |
+ Bstderr = &bstderr; | |
+ | |
+ tmpnam(tmpfilename); | |
+ if ((bstdout=Bopen(tmpfilename, OWRITE)) == 0) { | |
+ Bprint(Bstderr, "cannot open temporary file %s\n", tmpfilename… | |
+ exits("Bopen"); | |
+ } | |
+ atexit(cleanup); | |
+ Bstdout = bstdout; | |
+ | |
+ ARGBEGIN{ | |
+ case 'a': /* aspect ratio */ | |
+ aspectratio = atof(ARGF()); | |
+ break; | |
+ case 'c': /* copies */ | |
+ copies = atoi(ARGF()); | |
+ break; | |
+ case 'd': | |
+ debug = 1; | |
+ break; | |
+ case 'm': /* magnification */ | |
+ magnification = atof(ARGF()); | |
+ break; | |
+ case 'n': /* forms per page */ | |
+ formsperpage = atoi(ARGF()); | |
+ break; | |
+ case 'o': /* output page list */ | |
+ pagelist(ARGF()); | |
+ break; | |
+ case 'p': /* landscape or portrait mode… | |
+ if ( ARGF()[0] == 'l' ) | |
+ landscape = 1; | |
+ else | |
+ landscape = 0; | |
+ break; | |
+ case 'x': /* shift things horizontally … | |
+ xoffset = atof(ARGF()); | |
+ break; | |
+ case 'y': /* and vertically on the page… | |
+ yoffset = atof(ARGF()); | |
+ break; | |
+ case 'P': /* PostScript pass through */ | |
+ t = ARGF(); | |
+ i = strlen(t) + 1; | |
+ passthrough = malloc(i); | |
+ if (passthrough == 0) { | |
+ Bprint(Bstderr, "cannot allocate memory for ar… | |
+ exits("malloc"); | |
+ } | |
+ strncpy(passthrough, t, i); | |
+ break; | |
+ default: /* don't know what to do for c… | |
+ Bprint(Bstderr, "unknown option %C\n", ARGC()); | |
+ break; | |
+ }ARGEND; | |
+ readDESC(); | |
+ if (argc == 0) { | |
+ if ((binp = (Biobuf *)malloc(sizeof(Biobuf))) < (Biobuf *)0) { | |
+ Bprint(Bstderr, "malloc failed.\n"); | |
+ exits("malloc"); | |
+ } | |
+ if (Binit(binp, 0, OREAD) == Beof) { | |
+ Bprint(Bstderr, "Binit of <stdin> failed.\n"); | |
+ exits("Binit"); | |
+ } | |
+ Binp = binp; | |
+ if (debug) Bprint(Bstderr, "using standard input\n"); | |
+ conv(Binp); | |
+ Bterm(Binp); | |
+ } | |
+ for (i=0; i<argc; i++) { | |
+ if ((binp=Bopen(argv[i], OREAD)) == 0) { | |
+ Bprint(Bstderr, "cannot open file %s\n", argv[i]); | |
+ continue; | |
+ } | |
+ Binp = binp; | |
+ inputfilename = argv[i]; | |
+ conv(Binp); | |
+ Bterm(Binp); | |
+ } | |
+ Bterm(Bstdout); | |
+ | |
+ if ((ifd=open(tmpfilename, OREAD)) < 0) { | |
+ Bprint(Bstderr, "open of %s failed.\n", tmpfilename); | |
+ exits("open"); | |
+ } | |
+ | |
+ bstdout = galloc(0, sizeof(Biobuf), "bstdout"); | |
+ if (Binit(bstdout, 1, OWRITE) == Beof) { | |
+ Bprint(Bstderr, "Binit of <stdout> failed.\n"); | |
+ exits("Binit"); | |
+ } | |
+ Bstdout = bstdout; | |
+ prologues(); | |
+ Bflush(Bstdout); | |
+ tot = 0; i = 0; | |
+ while ((i=read(ifd, copybuf, BUFSIZ)) > 0) { | |
+ if (write(1, copybuf, i) != i) { | |
+ Bprint(Bstderr, "write error on copying from temp file… | |
+ exits("write"); | |
+ } | |
+ tot += i; | |
+ } | |
+ if (debug) Bprint(Bstderr, "copied %d bytes to final output i=%d\n", t… | |
+ if (i < 0) { | |
+ Bprint(Bstderr, "read error on copying from temp file.\n"); | |
+ exits("read"); | |
+ } | |
+ finish(); | |
+ | |
+ exits(""); | |
+} | |
diff --git a/src/cmd/postscript/tr2post/tr2post.h b/src/cmd/postscript/tr2post/… | |
t@@ -0,0 +1,103 @@ | |
+#define MAXSPECHARS 512 | |
+#define MAXTOKENSIZE 128 | |
+#define CHARLIB "#9/sys/lib/troff/font/devutf/charlib" | |
+ | |
+extern int debug; | |
+extern int fontsize; | |
+extern int fontpos; | |
+extern int resolution; /* device resolution, goobies per inch */ | |
+extern int minx; /* minimum x motion */ | |
+extern int miny; /* minimum y motion */ | |
+extern char devname[]; | |
+extern int devres; | |
+extern int unitwidth; | |
+extern char *printdesclang; | |
+extern char *encoding; | |
+extern int fontmnt; | |
+extern char **fontmtab; | |
+ | |
+extern int curtrofffontid; /* index into trofftab of current troff font… | |
+extern int troffontcnt; | |
+ | |
+extern BOOLEAN drawflag; | |
+ | |
+struct specname { | |
+ char *str; | |
+ struct specname *next; | |
+}; | |
+ | |
+/* character entries for special characters (those pointed | |
+ * to by multiple character names, e.g. \(mu for multiply. | |
+ */ | |
+struct charent { | |
+ char postfontid; /* index into pfnamtab */ | |
+ char postcharid; /* e.g., 0x00 */ | |
+ short troffcharwidth; | |
+ char *name; | |
+ struct charent *next; | |
+}; | |
+ | |
+extern struct charent **build_char_list; | |
+extern int build_char_cnt; | |
+ | |
+struct pfnament { | |
+ char *str; | |
+ int used; | |
+}; | |
+ | |
+/* these entries map troff character code ranges to | |
+ * postscript font and character ranges. | |
+ */ | |
+struct psfent { | |
+ int start; | |
+ int end; | |
+ int offset; | |
+ int psftid; | |
+}; | |
+ | |
+struct troffont { | |
+ char *trfontid; /* the common troff font name e.g., `R'… | |
+ BOOLEAN special; /* flag says this is a special font. */ | |
+ int spacewidth; | |
+ int psfmapsize; | |
+ struct psfent *psfmap; | |
+ struct charent *charent[NUMOFONTS][FONTSIZE]; | |
+}; | |
+ | |
+extern struct troffont *troffontab; | |
+extern struct charent spechars[]; | |
+ | |
+/** prototypes **/ | |
+void initialize(void); | |
+void mountfont(int, char*); | |
+int findtfn(char *, int); | |
+void runeout(Rune); | |
+void specialout(char *); | |
+long nametorune(char *); | |
+void conv(Biobuf *); | |
+void hgoto(int); | |
+void vgoto(int); | |
+void hmot(int); | |
+void vmot(int); | |
+void draw(Biobuf *); | |
+void devcntl(Biobuf *); | |
+void notavail(char *); | |
+void error(int, char *, ...); | |
+void loadfont(int, char *); | |
+void flushtext(void); | |
+void t_charht(int); | |
+void t_slant(int); | |
+void startstring(void); | |
+void endstring(void); | |
+BOOLEAN pageon(void); | |
+void setpsfont(int, int); | |
+void settrfont(void); | |
+int hash(char *, int); | |
+BOOLEAN readDESC(void); | |
+void finish(void); | |
+void ps_include(Biobuf *, Biobuf *, int, int, | |
+ int, int, double, double, double, double, | |
+ double, double, double); | |
+void picture(Biobuf *, char *); | |
+void beginpath(char*, int); | |
+void drawpath(char*, int); | |
diff --git a/src/cmd/postscript/tr2post/utfmap b/src/cmd/postscript/tr2post/utf… | |
t@@ -0,0 +1,47 @@ | |
+¡ !! ¢ c$ £ l$ ¤ g$ | |
+¥ y$ ¦ || § SS ¨ "" | |
+© cO ª sa « << ¬ no | |
+ -- ® rO ¯ __ ° de | |
+± +- ² s2 ³ s3 ´ '' | |
+µ mi ¶ pg · .. ¸ ,, | |
+¹ s1 º s0 » >> ¼ 14 | |
+½ 12 ¾ 34 ¿ ?? À `A | |
+Á 'A Â ^A Ã ~A Ä "A | |
+Å oA Æ AE Ç ,C È `E | |
+É 'E Ê ^E Ë "E Ì `I | |
+Í 'I Î ^I Ï "I Ð D- | |
+Ñ ~N Ò `O Ó 'O Ô ^O | |
+Õ ~O Ö "O × mu Ø /O | |
+Ù `U Ú 'U Û ^U Ü "U | |
+Ý 'Y Þ |P ß ss à `a | |
+á 'a â ^a ã ~a ä "a | |
+å oa æ ae ç ,c è `e | |
+é 'e ê ^e ë "e ì `i | |
+í 'i î ^i ï "i ð d- | |
+ñ ~n ò `o ó 'o ô ^o | |
+õ ~o ö "o ÷ -: ø /o | |
+ù `u ú 'u û ^u ü "u | |
+ý 'y þ |p ÿ "y α *a | |
+β *b γ *g δ *d ε *e | |
+ζ *z η *y θ *h ι *i | |
+κ *k λ *l *m μ ν *n | |
+ξ *c ο *o π *p ρ *r | |
+ς ts σ *s τ *t υ *u | |
+φ *f χ *x ψ *q ω *w | |
+Α *A Β *B Γ *G Δ *D | |
+Ε *E Ζ *Z Η *Y Θ *H | |
+Ι *I Κ *K Λ *L Μ *M | |
+Ν *N Ξ *C Ο *O Π *P | |
+Ρ *R Σ *S Τ *T Υ *U | |
+Φ *F Χ *X Ψ *Q Ω *W | |
+← <- ↑ ua → -> ↓ da | |
+↔ ab ∀ fa ∃ te ∂ pd | |
+∅ es ∆ *D ∇ gr ∉ !m | |
+∍ st ∗ ** ∙ bu √ sr | |
+∝ pt ∞ if ∠ an ∧ l& | |
+∨ l| ∩ ca ∪ cu ∫ is | |
+∴ tf ≃ ~= ≅ cg ≈ ~~ | |
+≠ != ≡ == ≦ <= ≧ >= | |
+⊂ sb ⊃ sp ⊄ !b ⊆ ib | |
+⊇ ip ⊕ O+ ⊖ O- ⊗ Ox | |
+⊢ tu ⊨ Tu ⋄ lz ⋯ el | |
diff --git a/src/cmd/postscript/tr2post/utils.c b/src/cmd/postscript/tr2post/ut… | |
t@@ -0,0 +1,264 @@ | |
+#include <u.h> | |
+#include <libc.h> | |
+#include <bio.h> | |
+#include "../common/common.h" | |
+#include "tr2post.h" | |
+ | |
+int hpos = 0, vpos = 0; | |
+int fontsize, fontpos; | |
+ | |
+#define MAXSTR 128 | |
+int trindex; /* index into trofftab of current troff fo… | |
+static int expecthmot = 0; | |
+ | |
+void | |
+initialize(void) { | |
+} | |
+ | |
+void | |
+hgoto(int x) { | |
+ hpos = x; | |
+ if (pageon()) { | |
+ endstring(); | |
+/* Bprint(Bstdout, "%d %d m\n", hpos, vpos); */ | |
+ } | |
+} | |
+ | |
+void | |
+vgoto(int y) { | |
+ vpos = y; | |
+ if (pageon()) { | |
+ endstring(); | |
+/* Bprint(Bstdout, "%d %d m\n", hpos, vpos); */ | |
+ } | |
+} | |
+ | |
+void | |
+hmot(int x) { | |
+ int delta; | |
+ | |
+ if ((x<expecthmot-1) || (x>expecthmot+1)) { | |
+ delta = x - expecthmot; | |
+ if (curtrofffontid <0 || curtrofffontid >= troffontcnt) { | |
+ Bprint(Bstderr, "troffontcnt=%d curtrofffontid=%d\n", … | |
+ Bflush(Bstderr); | |
+ exits(""); | |
+ } | |
+ if (delta == troffontab[curtrofffontid].spacewidth*fontsize/10… | |
+ if (pageon()) runeout(' '); | |
+ } else { | |
+ if (pageon()) { | |
+ endstring(); | |
+ /* Bprint(Bstdout, " %d 0 rmoveto ", delta); */ | |
+/* Bprint(Bstdout, " %d %d m ", hpos+x, vpos); … | |
+ if (debug) Bprint(Bstderr, "x=%d expecthmot=%d… | |
+ } | |
+ } | |
+ } | |
+ hpos += x; | |
+ expecthmot = 0; | |
+} | |
+ | |
+void | |
+vmot(int y) { | |
+ endstring(); | |
+/* Bprint(Bstdout, " 0 %d rmoveto ", -y); */ | |
+ vpos += y; | |
+} | |
+ | |
+struct charent ** | |
+findglyph(int trfid, Rune rune, char *stoken) { | |
+ struct charent **cp; | |
+ | |
+ for (cp = &(troffontab[trfid].charent[RUNEGETGROUP(rune)][RUNEGETCHAR(… | |
+ if ((*cp)->name) { | |
+ if (debug) Bprint(Bstderr, "looking for <%s>, have <%s… | |
+ if (strcmp((*cp)->name, stoken) == 0) | |
+ break; | |
+ } | |
+ } | |
+ return(cp); | |
+} | |
+ | |
+/* output glyph. Use first rune to look up character (hash) | |
+ * then use stoken UTF string to find correct glyph in linked | |
+ * list of glyphs in bucket. | |
+ */ | |
+void | |
+glyphout(Rune rune, char *stoken, BOOLEAN specialflag) { | |
+ struct charent **cp; | |
+ struct troffont *tfp; | |
+ struct psfent *psfp; | |
+ int i, t; | |
+ int fontid; /* this is the troff font table index, not the moun… | |
+ int mi, fi, wid; | |
+ Rune r; | |
+ | |
+ settrfont(); | |
+ | |
+ /* check current font for the character, special or not */ | |
+ fontid = curtrofffontid; | |
+if (debug) fprint(2, " looking through current font: trying %s\n", trof… | |
+ cp = findglyph(fontid, rune, stoken); | |
+ if (*cp != 0) goto foundit; | |
+ | |
+ if (specialflag) { | |
+ if (expecthmot) hmot(0); | |
+ | |
+ /* check special fonts for the special character */ | |
+ /* cycle through the (troff) mounted fonts starting at the nex… | |
+ for (mi=0; mi<fontmnt; mi++) { | |
+ if (troffontab[fontid].trfontid==0) error(WARNING, "gl… | |
+ fontid, troffontab[fontid].trfontid); | |
+ if (fontmtab[mi]==0) { | |
+ if (debug) fprint(2, "fontmtab[%d]=0x%x, fontm… | |
+ continue; | |
+ } | |
+ if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])=… | |
+ } | |
+ if (mi==fontmnt) error(FATAL, "current troff font is not mount… | |
+ for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) { | |
+ if (fontmtab[i]==0) { | |
+ if (debug) fprint(2, "fontmtab[%d]=0x%x, fontm… | |
+ continue; | |
+ } | |
+ fontid = findtfn(fontmtab[i], TRUE); | |
+if (debug) fprint(2, " looking through special fonts: trying %s\n", tro… | |
+ if (troffontab[fontid].special) { | |
+ cp = findglyph(fontid, rune, stoken); | |
+ if (*cp != 0) goto foundit; | |
+ } | |
+ } | |
+ | |
+ /* check font 1 (if current font is not font 1) for the specia… | |
+ if (mi != 1) { | |
+ fontid = findtfn(fontmtab[1], TRUE);; | |
+if (debug) fprint(2, " looking through font at position 1: trying %s\n"… | |
+ cp = findglyph(fontid, rune, stoken); | |
+ if (*cp != 0) goto foundit; | |
+ } | |
+ } | |
+ | |
+ if (*cp == 0) { | |
+ error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff… | |
+ troffontab[curtrofffontid].trfontid); | |
+ expecthmot = 0; | |
+ } | |
+ | |
+ /* use the peter face in lieu of the character that we couldn't find */ | |
+ rune = 'p'; stoken = "pw"; | |
+ for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) { | |
+ if (fontmtab[i]==0) { | |
+ if (debug) fprint(2, "fontmtab[%d]=0x%x\n", i, fontmta… | |
+ continue; | |
+ } | |
+ fontid = findtfn(fontmtab[i], TRUE); | |
+if (debug) fprint(2, " looking through special fonts: trying %s\n", tro… | |
+ if (troffontab[fontid].special) { | |
+ cp = findglyph(fontid, rune, stoken); | |
+ if (*cp != 0) goto foundit; | |
+ } | |
+ } | |
+ | |
+ if (*cp == 0) { | |
+ error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff… | |
+ troffontab[curtrofffontid].trfontid); | |
+ expecthmot = 0; | |
+ return; | |
+ } | |
+ | |
+foundit: | |
+ t = (((*cp)->postfontid&0xff)<<8) | ((*cp)->postcharid&0xff); | |
+ if (debug) { | |
+ Bprint(Bstderr, "runeout(0x%x)<%C> postfontid=0x%x postcharid=… | |
+ rune, rune, (*cp)->postfontid, (*cp)->postcharid, (*cp… | |
+ } | |
+ | |
+ tfp = &(troffontab[fontid]); | |
+ for (i=0; i<tfp->psfmapsize; i++) { | |
+ psfp = &(tfp->psfmap[i]); | |
+ if(t>=psfp->start && t<=psfp->end) break; | |
+ } | |
+ if (i >= tfp->psfmapsize) | |
+ error(FATAL, "character <0x%x> does not have a Postscript font… | |
+ | |
+ setpsfont(psfp->psftid, fontsize); | |
+ | |
+ if (t == 0x0001) { /* character is in charlib */ | |
+ endstring(); | |
+ if (pageon()) { | |
+ struct charent *tcp; | |
+ | |
+ Bprint(Bstdout, "%d %d m ", hpos, vpos); | |
+ /* if char is unicode character rather than name, clea… | |
+ wid = chartorune(&r, (*cp)->name); | |
+ if(' '<r && r<0x7F) | |
+ Bprint(Bstdout, "%d build_%s\n", (*cp)->troffc… | |
+ else{ | |
+ if((*cp)->name[wid] != 0) | |
+ error(FATAL, "character <%s> badly nam… | |
+ Bprint(Bstdout, "%d build_X%.4x\n", (*cp)->tro… | |
+ } | |
+ | |
+ /* stash charent pointer in a list so that we can prin… | |
+ * in the prologue. | |
+ */ | |
+ for (i=0; i<build_char_cnt; i++) | |
+ if (*cp == build_char_list[i]) break; | |
+ if (i == build_char_cnt) { | |
+ build_char_list = galloc(build_char_list, size… | |
+ "build_char_list"); | |
+ build_char_list[build_char_cnt-1] = *cp; | |
+ } | |
+ } | |
+ expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth; | |
+ } else if (isinstring() || rune != ' ') { | |
+ startstring(); | |
+ if (pageon()) { | |
+ if (rune == ' ') | |
+ Bprint(Bstdout, " "); | |
+ else | |
+ Bprint(Bstdout, "%s", charcode[RUNEGETCHAR(t)]… | |
+ } | |
+ expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth; | |
+ } | |
+} | |
+ | |
+/* runeout puts a symbol into a string (queue) to be output. | |
+ * It also has to keep track of the current and last symbol | |
+ * output to check that the spacing is correct by default | |
+ * or needs to be adjusted with a spacing operation. | |
+ */ | |
+ | |
+void | |
+runeout(Rune rune) { | |
+ char stoken[UTFmax+1]; | |
+ int i; | |
+ | |
+ i = runetochar(stoken, &rune); | |
+ stoken[i] = '\0'; | |
+ glyphout(rune, stoken, TRUE); | |
+} | |
+ | |
+void | |
+specialout(char *stoken) { | |
+ Rune rune; | |
+ int i; | |
+ | |
+ i = chartorune(&rune, stoken); | |
+ glyphout(rune, stoken, TRUE); | |
+} | |
+ | |
+void | |
+graphfunc(Biobuf *bp) { | |
+} | |
+ | |
+long | |
+nametorune(char *name) { | |
+ return(0); | |
+} | |
+ | |
+void | |
+notavail(char *msg) { | |
+ Bprint(Bstderr, "%s is not available at this time.\n", msg); | |
+} |