more files
This commit is contained in:
parent
173302913e
commit
61f5c35c94
37 changed files with 5947 additions and 1 deletions
|
|
@ -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|troff|pic|tbl'
|
||||
BUGGERED='CVS|faces|factotum|mailfs|scat|upas|vac|venti|lex|vncv|grap|eqn|troff|postscript|pic|tbl'
|
||||
DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"`
|
||||
|
||||
<$PLAN9/src/mkdirs
|
||||
|
|
|
|||
257
src/cmd/postscript/common/bbox.c
Normal file
257
src/cmd/postscript/common/bbox.c
Normal file
|
|
@ -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 comments */
|
||||
#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 transformation
|
||||
* 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?) the box a bit */
|
||||
|
||||
{
|
||||
|
||||
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,(int)bbox.urx, (int)bbox.ury);
|
||||
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 */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
127
src/cmd/postscript/common/comments.h
Normal file
127
src/cmd/postscript/common/comments.h
Normal file
|
|
@ -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 newline
|
||||
* stand on their own. Truly overkill on Adobe's part and mine for including them
|
||||
* 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 used
|
||||
* 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:"
|
||||
|
||||
264
src/cmd/postscript/common/common.c
Normal file
264
src/cmd/postscript/common/common.c
Normal file
|
|
@ -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 print */
|
||||
|
||||
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, stringvpos);
|
||||
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, errorstrings[errtype]);
|
||||
va_start(arg, fmt);
|
||||
vfprint(2, fmt, arg);
|
||||
va_end(arg);
|
||||
if (errtype == FATAL)
|
||||
exits("fatal error");
|
||||
}
|
||||
43
src/cmd/postscript/common/common.h
Normal file
43
src/cmd/postscript/common/common.h
Normal file
|
|
@ -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 *);
|
||||
40
src/cmd/postscript/common/ext.h
Normal file
40
src/cmd/postscript/common/ext.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
*
|
||||
* External varibles - most are in glob.c.
|
||||
*
|
||||
*/
|
||||
|
||||
extern char **argv; /* global so everyone can use them */
|
||||
extern int argc;
|
||||
|
||||
extern int x_stat; /* program exit status */
|
||||
extern int debug; /* debug flag */
|
||||
extern int ignore; /* what we do with FATAL errors */
|
||||
|
||||
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 programs */
|
||||
extern char *fontencoding; /* text font encoding scheme */
|
||||
|
||||
extern int dobbox; /* enable BoundingBox stuff if TRUE */
|
||||
extern double pageheight; /* only for BoundingBox calculations! */
|
||||
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();
|
||||
*/
|
||||
65
src/cmd/postscript/common/gen.h
Normal file
65
src/cmd/postscript/common/gen.h
Normal file
|
|
@ -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 get
|
||||
* 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))
|
||||
|
||||
56
src/cmd/postscript/common/getopt.c
Normal file
56
src/cmd/postscript/common/getopt.c
Normal file
|
|
@ -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], str, chr);}
|
||||
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;
|
||||
}
|
||||
29
src/cmd/postscript/common/glob.c
Normal file
29
src/cmd/postscript/common/glob.c
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
*
|
||||
* Global varibles - for PostScript translators.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "gen.h"
|
||||
|
||||
char **argv; /* global so everyone can use them */
|
||||
int argc;
|
||||
|
||||
int x_stat = 0; /* program exit status */
|
||||
int debug = OFF; /* debug flag */
|
||||
int ignore = OFF; /* what we do with FATAL errors */
|
||||
|
||||
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 programs */
|
||||
char *fontencoding = NULL; /* text font encoding scheme */
|
||||
|
||||
int dobbox = FALSE; /* enable BoundingBox stuff if TRUE */
|
||||
double pageheight = PAGEHEIGHT; /* only for BoundingBox calculations! */
|
||||
double pagewidth = PAGEWIDTH;
|
||||
|
||||
int reading = UTFENCODING; /* input */
|
||||
int writing = WRITING; /* and output encoding */
|
||||
|
||||
230
src/cmd/postscript/common/misc.c
Normal file
230
src/cmd/postscript/common/misc.c
Normal file
|
|
@ -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 */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
23
src/cmd/postscript/common/mkfile
Normal file
23
src/cmd/postscript/common/mkfile
Normal file
|
|
@ -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
|
||||
32
src/cmd/postscript/common/path.h
Normal file
32
src/cmd/postscript/common/path.h
Normal file
|
|
@ -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"
|
||||
|
||||
119
src/cmd/postscript/common/request.c
Normal file
119
src/cmd/postscript/common/request.c
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
*
|
||||
* Things used to handle special requests (eg. manual feed) globally or on a per
|
||||
* page basis. Requests are passed through to the translator using the -R option.
|
||||
* 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 applied
|
||||
* to the global environment. In all other cases it applies only to the selected
|
||||
* page. If a file is given, page must be supplied, and the lookup is in that file
|
||||
* 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 request */
|
||||
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", or
|
||||
* "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 this page */
|
||||
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 */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
22
src/cmd/postscript/common/request.h
Normal file
22
src/cmd/postscript/common/request.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
*
|
||||
* Things used to handle special PostScript requests (like manual feed) globally
|
||||
* or on a per page basis. All the translators I've supplied accept the -R option
|
||||
* that can be used to insert special PostScript code before the global setup is
|
||||
* done, or at the start of named pages. The argument to the -R option is a string
|
||||
* 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 applies
|
||||
* 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;
|
||||
|
||||
142
src/cmd/postscript/common/rune.c
Normal file
142
src/cmd/postscript/common/rune.c
Normal file
|
|
@ -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 1111 */
|
||||
Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
|
||||
Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 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;
|
||||
}
|
||||
19
src/cmd/postscript/common/rune.h
Normal file
19
src/cmd/postscript/common/rune.h
Normal file
|
|
@ -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 utf sequence (<) */
|
||||
Runeself = 0x80, /* rune and utf sequences are the same (<) */
|
||||
Runeerror = 0x80, /* decoding error in utf */
|
||||
};
|
||||
#endif
|
||||
27
src/cmd/postscript/common/tempnam.c
Normal file
27
src/cmd/postscript/common/tempnam.c
Normal file
|
|
@ -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
|
||||
11
src/cmd/postscript/download/README
Normal file
11
src/cmd/postscript/download/README
Normal file
|
|
@ -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).
|
||||
|
||||
545
src/cmd/postscript/download/download.c
Normal file
545
src/cmd/postscript/download/download.c
Normal file
|
|
@ -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 request
|
||||
* 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 copies
|
||||
* 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 (including the map
|
||||
* % table) in *hostfontdir seems like the
|
||||
* % 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 font.
|
||||
*
|
||||
* 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 should
|
||||
* 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 comments */
|
||||
#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 copying stdin */
|
||||
char *hostfontdir = HOSTDIR; /* host resident directory */
|
||||
char *mapname = "map"; /* map table - usually in *hostfontdir */
|
||||
char *suffix = ""; /* appended to the map table pathname */
|
||||
Map *map = NULL; /* device font map table */
|
||||
char *stringspace = NULL; /* for storing font and file strings */
|
||||
int next = 0; /* next free slot in map[] */
|
||||
|
||||
char *residentfonts = NULL; /* list of printer resident fonts */
|
||||
char *printer = NULL; /* printer name - only for Unix 4.0 lp */
|
||||
|
||||
char buf[2048]; /* input file line buffer */
|
||||
char *comment = DOCUMENTFONTS; /* look for this comment */
|
||||
int atend = FALSE; /* TRUE only if a comment says so */
|
||||
|
||||
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 options */
|
||||
readmap(); /* read the font map table */
|
||||
readresident(); /* and the optional resident font list */
|
||||
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 scan */
|
||||
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 begins
|
||||
* 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 comments */
|
||||
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 marks
|
||||
* 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 get
|
||||
* here and there aren't any arguments left, or if '-' is one of the input files
|
||||
* 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].file)+2)) == NULL )
|
||||
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 stdin.
|
||||
*
|
||||
*/
|
||||
|
||||
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 */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
14
src/cmd/postscript/download/download.h
Normal file
14
src/cmd/postscript/download/download.h
Normal file
|
|
@ -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 font */
|
||||
char *file; /* means copy this unix file */
|
||||
int downloaded; /* TRUE after *file is downloaded */
|
||||
} Map;
|
||||
|
||||
Map *allocate();
|
||||
|
||||
25
src/cmd/postscript/download/mkfile
Normal file
25
src/cmd/postscript/download/mkfile
Normal file
|
|
@ -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
|
||||
25
src/cmd/postscript/mkfile
Normal file
25
src/cmd/postscript/mkfile
Normal file
|
|
@ -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
|
||||
156
src/cmd/postscript/tr2post/Bgetfield.c
Normal file
156
src/cmd/postscript/tr2post/Bgetfield.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
458
src/cmd/postscript/tr2post/chartab.c
Normal file
458
src/cmd/postscript/tr2post/chartab.c
Normal file
|
|
@ -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 mount into postions 0-%d\n",
|
||||
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!\n", fontpos);
|
||||
|
||||
curtrofffontid = findtfn(fontmtab[fontpos], 1);
|
||||
if (debug) Bprint(Bstderr, "settrfont()-> curtrofffontid=%d\n", curtrofffontid);
|
||||
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, fontmtab[i]);
|
||||
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, there are only %d fonts\n",
|
||||
psftid, pfnamcnt);
|
||||
|
||||
endstring();
|
||||
if (pageon()) {
|
||||
Bprint(Bstdout, "%d /%s f\n", fontsize, pfnafontmtab[psftid].str);
|
||||
if ( fontheight != 0 || fontslant != 0 )
|
||||
Bprint(Bstdout, "%d %d changefont\n", fontslant, (fontheight != 0) ? fontheight : fontsize);
|
||||
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), "findpfn():pfnafontmtab");
|
||||
if (tp == 0)
|
||||
return(-2);
|
||||
pfnafontmtab = (struct pfnament *)tp;
|
||||
i = strlen(fontname);
|
||||
pfnafontmtab[pfnamcnt].str = galloc(0, i+1, "findpfn():pfnafontmtab[].str");
|
||||
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"; /* "/sys/lib/postscript/troff/"; */
|
||||
char troffmetricdirname[] = "#9/sys/lib/troff/font"; /* "/sys/lib/troff/font/devutf/"; */
|
||||
|
||||
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, trindex);
|
||||
filename=galloc(filename, strlen(postroffdirname)+1+strlen(fontname)+1, "readpsfontdesc: cannot allocate memory\n");
|
||||
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", filename, line);
|
||||
} else if (rv < 0) break;
|
||||
if ((rv=Bgetfield(Bfd, 'd', &end, 0)) == 0) {
|
||||
errorflg = 1;
|
||||
error(WARNING, "file %s:%d illegal end value\n", filename, line);
|
||||
} else if (rv < 0) break;
|
||||
if ((rv=Bgetfield(Bfd, 'd', &offset, 0)) < 0) {
|
||||
errorflg = 1;
|
||||
error(WARNING, "file %s:%d illegal offset value\n", filename, line);
|
||||
}
|
||||
if ((rv=Bgetfield(Bfd, 's', psfontnam, 128)) == 0) {
|
||||
errorflg = 1;
|
||||
error(WARNING, "file %s:%d illegal fontname value\n", filename, line);
|
||||
} 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 cross 256 glyph block boundary\n");
|
||||
errorflg = 1;
|
||||
break;
|
||||
}
|
||||
tp = &(troffontab[trindex]);
|
||||
tp->psfmap = galloc(tp->psfmap, ++(tp->psfmapsize)*sizeof(struct psfent), "readpsfontdesc():psfmap");
|
||||
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", start);
|
||||
Bprint(Bstderr, "\tpsfmap->end=0x%x\n", end);
|
||||
Bprint(Bstderr, "\tpsfmap->offset=0x%x\n", offset);
|
||||
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 + offset - startchar;
|
||||
}
|
||||
*/
|
||||
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, trindex);
|
||||
filename=galloc(filename, strlen(troffmetricdirname)+4+strlen(devname)+1+strlen(fontname)+1, "readtroffmetric():filename");
|
||||
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, line);
|
||||
} 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", filename, line);
|
||||
} 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", filename, line);
|
||||
} 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", filename, line);
|
||||
} else if (rv < 0) break;
|
||||
troffontab[trindex].spacewidth = ntoken;
|
||||
thisfont = RUNEGETGROUP(' ');
|
||||
thischar = RUNEGETCHAR(' ');
|
||||
for (cp = &(troffontab[trindex].charent[thisfont][thischar]); *cp != 0; cp = &((*cp)->next))
|
||||
if ((*cp)->name)
|
||||
if (strcmp((*cp)->name, " ") == 0)
|
||||
break;
|
||||
|
||||
if (*cp == 0) *cp = galloc(0, sizeof(struct charent), "readtroffmetric: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> rv=%d\n", filename, line, troffchar, rv);
|
||||
} 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 characters info */
|
||||
if ((rv=Bgetfield(Bfd, 'r', "e, 0)) == 0) {
|
||||
errorflg = 1;
|
||||
error(WARNING, "file %s:%d illegal width or quote token <0x%x> rv=%d\n", filename, line, quote, rv);
|
||||
} 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> rv=%d\n", filename, line, troffchar, rv);
|
||||
} 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> rv=%d\n", filename, line, troffchar, rv);
|
||||
} else if (rv < 0) break;
|
||||
if ((rv=Bgetfield(Bfd, 'd', &charnum, 0)) == 0) {
|
||||
errorflg = 1;
|
||||
error(WARNING, "file %s:%d illegal character number token <0x%x> rv=%d\n", filename, line, troffchar, rv);
|
||||
} 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",stoken, width, flag, charnum, str);
|
||||
}
|
||||
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]); *cp != 0; cp = &((*cp)->next))
|
||||
if ((*cp)->name) {
|
||||
if (debug) Bprint(Bstderr, "installing <%s>, found <%s>\n", stoken, (*cp)->name);
|
||||
if (strcmp((*cp)->name, stoken) == 0)
|
||||
break;
|
||||
}
|
||||
if (*cp == 0) *cp = galloc(0, sizeof(struct charent), "readtroffmetric:charent");
|
||||
(*cp)->postfontid = RUNEGETGROUP(charnum);
|
||||
(*cp)->postcharid = RUNEGETCHAR(charnum);
|
||||
(*cp)->troffcharwidth = width;
|
||||
(*cp)->name = galloc(0, strlen(stoken)+1, "readtroffmetric: char name");
|
||||
(*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 pscharid=0x%x thisfont=0x%x thischar=0x%x\n",
|
||||
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, insflg);
|
||||
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, botch!\n",
|
||||
i, troffontab[i].trfontid);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(troffontab[i].trfontid, fontname) == 0)
|
||||
return(i);
|
||||
}
|
||||
if (insflg) {
|
||||
tp = (struct troffont *)galloc(troffontab, sizeof(struct troffont)*(troffontcnt+1), "findtfn: struct troffont:");
|
||||
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 fields to 0 */
|
||||
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;
|
||||
}
|
||||
100
src/cmd/postscript/tr2post/conv.c
Normal file
100
src/cmd/postscript/tr2post/conv.c
Normal file
|
|
@ -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 current font */
|
||||
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' follows) */
|
||||
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");
|
||||
}
|
||||
178
src/cmd/postscript/tr2post/devcntl.c
Normal file
178
src/cmd/postscript/tr2post/devcntl.c
Normal file
|
|
@ -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, "PictureInclusion", sizeof("PictureInclusion")-1) == 0) {
|
||||
picture(inp, str);
|
||||
} else if (strncmp(str, "InlinePicture", sizeof("InlinePicture")-1) == 0) {
|
||||
error(FATAL, "InlinePicture not implemented yet.\n");
|
||||
/* inlinepic(inp, buf); */
|
||||
} else if (strncmp(str, "BeginPath", sizeof("BeginPath")-1) == 0) {
|
||||
beginpath(buf, FALSE);
|
||||
} else if (strncmp(str, "DrawPath", sizeof("DrawPath")-1) == 0) {
|
||||
drawpath(buf, FALSE);
|
||||
} else if (strncmp(str, "BeginObject", sizeof("BeginObject")-1) == 0) {
|
||||
beginpath(buf, TRUE);
|
||||
} else if (strncmp(str, "EndObject", sizeof("EndObject")-1) == 0) {
|
||||
drawpath(buf, TRUE);
|
||||
} else if (strncmp(str, "NewBaseline", sizeof("NewBaseline")-1) == 0) {
|
||||
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(str, "PostScript", sizeof("PostScript")-1) == 0) {
|
||||
if(pageon()) {
|
||||
endstring();
|
||||
Bprint(Bstdout, "%s\n", buf);
|
||||
}
|
||||
} else if (strncmp(str, "ExportPS", sizeof("ExportPS")-1) == 0) { /* dangerous!! */
|
||||
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", str, buf);
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
while ((c = Bgetc(inp)) != '\n' && c != Beof);
|
||||
inputlineno++;
|
||||
}
|
||||
|
||||
342
src/cmd/postscript/tr2post/draw.c
Normal file
342
src/cmd/postscript/tr2post/draw.c
Normal file
|
|
@ -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 pieces together */
|
||||
|
||||
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 to
|
||||
* 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], 0)<=0)
|
||||
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], x[i+1], y[i+1], x[i+2], y[i+2]);
|
||||
/* if (dobbox == TRUE) { /* could be better */
|
||||
/* cover((double)(x[i] + x[i+1])/2,(double)-(y[i] + y[i+1])/2);
|
||||
/* cover((double)x[i+1], (double)-y[i+1]);
|
||||
/* cover((double)(x[i+1] + x[i+2])/2, (double)-(y[i+1] + y[i+2])/2);
|
||||
/* }
|
||||
*/
|
||||
}
|
||||
|
||||
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)<=0 || Bgetfield(Bp, 'r', &i, 0)<=0)
|
||||
error(FATAL, "draw line function, destination coordinates not found.\n");
|
||||
|
||||
endstring();
|
||||
if (pageon())
|
||||
Bprint(Bstdout, "%d %d %d %d Dl\n", hpos, vpos, hpos+x1, vpos+y1);
|
||||
hpos += x1;
|
||||
vpos += y1;
|
||||
break;
|
||||
case 'c':
|
||||
if (Bgetfield(Bp, 'd', &d1, 0)<=0)
|
||||
error(FATAL, "draw circle function, diameter coordinates not found.\n");
|
||||
|
||||
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)<=0)
|
||||
error(FATAL, "draw ellipse function, diameter coordinates not found.\n");
|
||||
|
||||
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)<=0 || Bgetfield(Bp, 'd', &x2, 0)<=0 || Bgetfield(Bp, 'd', &y2, 0)<=0)
|
||||
error(FATAL, "draw arc function, coordinates not found.\n");
|
||||
|
||||
endstring();
|
||||
if (pageon())
|
||||
Bprint(Bstdout, "%d %d %d %d %d %d Da\n", hpos, vpos, x1, y1, x2, y2);
|
||||
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 used
|
||||
* 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 with
|
||||
* 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 defined
|
||||
* in *drawfile skip the newpath and stroke, until after the next "x X DrawPath"
|
||||
* 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 the
|
||||
* end of the path started by the last "x X BeginPath" command and uses whatever
|
||||
* 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 their
|
||||
* default behavior in which each drawing command is treated as an isolated path.
|
||||
* The new version (called after "x X DrawPath") has copy set to FALSE, and calls
|
||||
* 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. The
|
||||
* comments in parsebuf() describe what's handled.
|
||||
*
|
||||
* In the early version a path was started with "x X BeginObject" and ended with
|
||||
* "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 done a gsave */
|
||||
|
||||
/*
|
||||
*
|
||||
* Simple minded attempt at parsing the string that followed an "x X DrawPath"
|
||||
* command. Everything not recognized here is simply ignored - there's absolutely
|
||||
* 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 stroking the
|
||||
* 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 discarded.
|
||||
* The "stroke", "fill", and "wfill" force out appropriate PostScript code and are
|
||||
* followed by a grestore. In otherwords changes to the grahics state (eg. a gray
|
||||
* level or color) are reset to default values immediately after the stroke, fill,
|
||||
* or wfill tokens. For now "fill" gets invokes PostScript's eofill operator and
|
||||
* "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" (for
|
||||
* setting the gray level), "color" (for selecting a known color from the colordict
|
||||
* dictionary defined in *colorfile), and "line" (for setting the line width). All
|
||||
* three tokens can be extended since strncmp() makes the comparison. For example
|
||||
* the strings "line" and "linewidth" accomplish the same thing. Colors are named
|
||||
* (eg. "red"), but must be appropriately defined in *colorfile. For now all three
|
||||
* 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, with
|
||||
* 0 for black and 1 for white.
|
||||
*
|
||||
* To pass straight PostScript through enclose the appropriate commands in double
|
||||
* quotes. Straight PostScript is only bracketed by the outermost gsave/grestore
|
||||
* 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\ngrestore\n");
|
||||
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 setlinewidth\n", p);
|
||||
}
|
||||
} 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");
|
||||
|
||||
}
|
||||
36
src/cmd/postscript/tr2post/mkfile
Normal file
36
src/cmd/postscript/tr2post/mkfile
Normal file
|
|
@ -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
|
||||
295
src/cmd/postscript/tr2post/pictures.c
Normal file
295
src/cmd/postscript/tr2post/pictures.c
Normal file
|
|
@ -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-processor
|
||||
* 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 number
|
||||
* of bytes in the picture, which begins immediately on the next line. When dpost
|
||||
* encounters the InlinePicture device control command inlinepic() is called and
|
||||
* that routine appends the string name and the integer size to a temporary file
|
||||
* (fp_pic) and then adds the next size bytes read from the current input file to
|
||||
* file fp_pic. All in-line pictures are saved in fp_pic and located later using
|
||||
* the name string and picture file size that separate pictures saved in fp_pic.
|
||||
*
|
||||
* 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 there
|
||||
* 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, expressed
|
||||
* 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 recommended
|
||||
* approach! Perhaps the most important problem is that troff output, with in-line
|
||||
* 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 hwo[] */
|
||||
char units; /* scale indicator for frame dimensions */
|
||||
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 that
|
||||
* 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, width,
|
||||
* 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 control
|
||||
* 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, width */
|
||||
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 center */
|
||||
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 dimensions */
|
||||
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], frame[0], adjx, adjy, -rot);
|
||||
/* 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 accumulated
|
||||
* any in-line pictures fp_pic won't be NULL and we'll look there first. If *path
|
||||
* is found in *fp_pic we create another temp file, open it for update, unlink it,
|
||||
* 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 just
|
||||
* 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_pic */
|
||||
Biobuf *bfp;
|
||||
Biobuf *Bfp; /* and pointer for the new temp file */
|
||||
|
||||
|
||||
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 name");
|
||||
if ( (bfp = Bopen(pictmpname, ORDWR)) == NULL )
|
||||
error(FATAL, "can't open %s", pictmpname);
|
||||
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 pictures
|
||||
* grabbed from the input file are saved in the same temp file. Each is preceeded
|
||||
* by a one line header that includes the original picture file pathname and the
|
||||
* 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", ipictmpname);
|
||||
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 to
|
||||
* *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);
|
||||
}
|
||||
191
src/cmd/postscript/tr2post/ps_include.c
Normal file
191
src/cmd/postscript/tr2post/ps_include.c
Normal file
|
|
@ -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 appear
|
||||
* 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 just
|
||||
* indent comments a space, which turns DSC comments into non-DSC comments
|
||||
* and has no effect on binary encodings, which are whitespace-blind.
|
||||
*/
|
||||
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 whole
|
||||
* file is scanned, the special ps_include PostScript definitions are copied to
|
||||
* *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 when non zero */
|
||||
int foundpbox = 0; /* found the page bounding box */
|
||||
int nglobal = 0; /* number of global defs so far */
|
||||
int maxglobal = 0; /* and the number we've got room for */
|
||||
Section prolog, page, trailer; /* prologue, page, and trailer offsets */
|
||||
Section *global; /* offsets for all global definitions */
|
||||
double llx, lly; /* lower left and */
|
||||
double urx, ury; /* upper right corners - default coords */
|
||||
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("%%EndDocumentSetup"))
|
||||
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;
|
||||
}
|
||||
66
src/cmd/postscript/tr2post/ps_include.h
Normal file
66
src/cmd/postscript/tr2post/ps_include.h
Normal file
|
|
@ -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
|
||||
};
|
||||
139
src/cmd/postscript/tr2post/readDESC.c
Normal file
139
src/cmd/postscript/tr2post/readDESC.c
Normal file
|
|
@ -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(FONTDIR)
|
||||
+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, "readdesc:");
|
||||
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 number of fonts in mount table.\n");
|
||||
return(FALSE);
|
||||
}
|
||||
fontmnt = atoi(token) + 1;
|
||||
fontmtab = galloc(fontmtab, fontmnt*sizeof(char *), "readdesc:");
|
||||
|
||||
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 resolution.\n");
|
||||
return(FALSE);
|
||||
}
|
||||
devres = atoi(token);
|
||||
if (debug) Bprint(Bstderr, "res %d\n", devres);
|
||||
break;
|
||||
case 5:
|
||||
/* I don't really care about horizontal motion resolution */
|
||||
if (debug) Bprint(Bstderr, "ignoring horizontal resolution\n");
|
||||
break;
|
||||
case 6:
|
||||
/* I don't really care about vertical motion resolution */
|
||||
if (debug) Bprint(Bstderr, "ignoring vertical resolution\n");
|
||||
break;
|
||||
case 7:
|
||||
/* unitwidth is the font size at which the character widths are 1:1 */
|
||||
if (!isdigit(*token)) {
|
||||
error(WARNING, "readdesc: expecting unitwidth.\n");
|
||||
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 characters */
|
||||
if (debug) Bprint(Bstderr, "ignoring special character <%s>\n", token);
|
||||
break;
|
||||
default:
|
||||
if (*token == '#')
|
||||
Brdline(Bfd, '\n');
|
||||
else
|
||||
error(WARNING, "unknown token %s in DESC file.\n", token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Bterm(Bfd);
|
||||
}
|
||||
1238
src/cmd/postscript/tr2post/shell.lib
Normal file
1238
src/cmd/postscript/tr2post/shell.lib
Normal file
File diff suppressed because it is too large
Load diff
218
src/cmd/postscript/tr2post/tr2post.c
Normal file
218
src/cmd/postscript/tr2post/tr2post.c
Normal file
|
|
@ -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", aspectratio);
|
||||
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", magnification);
|
||||
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 argument string\n");
|
||||
exits("malloc");
|
||||
}
|
||||
strncpy(passthrough, t, i);
|
||||
break;
|
||||
default: /* don't know what to do for ch */
|
||||
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.\n");
|
||||
exits("write");
|
||||
}
|
||||
tot += i;
|
||||
}
|
||||
if (debug) Bprint(Bstderr, "copied %d bytes to final output i=%d\n", tot, i);
|
||||
if (i < 0) {
|
||||
Bprint(Bstderr, "read error on copying from temp file.\n");
|
||||
exits("read");
|
||||
}
|
||||
finish();
|
||||
|
||||
exits("");
|
||||
}
|
||||
103
src/cmd/postscript/tr2post/tr2post.h
Normal file
103
src/cmd/postscript/tr2post/tr2post.h
Normal file
|
|
@ -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);
|
||||
47
src/cmd/postscript/tr2post/utfmap
Normal file
47
src/cmd/postscript/tr2post/utfmap
Normal file
|
|
@ -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
|
||||
264
src/cmd/postscript/tr2post/utils.c
Normal file
264
src/cmd/postscript/tr2post/utils.c
Normal file
|
|
@ -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 font */
|
||||
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", troffontcnt, curtrofffontid);
|
||||
Bflush(Bstderr);
|
||||
exits("");
|
||||
}
|
||||
if (delta == troffontab[curtrofffontid].spacewidth*fontsize/10 && isinstring()) {
|
||||
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\n", x, expecthmot);
|
||||
}
|
||||
}
|
||||
}
|
||||
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(rune)]); *cp != 0; cp = &((*cp)->next)) {
|
||||
if ((*cp)->name) {
|
||||
if (debug) Bprint(Bstderr, "looking for <%s>, have <%s> in font %s\n", stoken, (*cp)->name, troffontab[trfid].trfontid);
|
||||
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 mounted font table index */
|
||||
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", troffontab[fontid].trfontid);
|
||||
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 next font */
|
||||
for (mi=0; mi<fontmnt; mi++) {
|
||||
if (troffontab[fontid].trfontid==0) error(WARNING, "glyphout:troffontab[%d].trfontid=0x%x, botch!\n",
|
||||
fontid, troffontab[fontid].trfontid);
|
||||
if (fontmtab[mi]==0) {
|
||||
if (debug) fprint(2, "fontmtab[%d]=0x%x, fontmnt=%d\n", mi, fontmtab[mi], fontmnt);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])==0) break;
|
||||
}
|
||||
if (mi==fontmnt) error(FATAL, "current troff font is not mounted, botch!\n");
|
||||
for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
|
||||
if (fontmtab[i]==0) {
|
||||
if (debug) fprint(2, "fontmtab[%d]=0x%x, fontmnt=%d\n", i, fontmtab[i], fontmnt);
|
||||
continue;
|
||||
}
|
||||
fontid = findtfn(fontmtab[i], TRUE);
|
||||
if (debug) fprint(2, " looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
|
||||
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 special character */
|
||||
if (mi != 1) {
|
||||
fontid = findtfn(fontmtab[1], TRUE);;
|
||||
if (debug) fprint(2, " looking through font at position 1: trying %s\n", troffontab[fontid].trfontid);
|
||||
cp = findglyph(fontid, rune, stoken);
|
||||
if (*cp != 0) goto foundit;
|
||||
}
|
||||
}
|
||||
|
||||
if (*cp == 0) {
|
||||
error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,
|
||||
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, fontmtab[i]);
|
||||
continue;
|
||||
}
|
||||
fontid = findtfn(fontmtab[i], TRUE);
|
||||
if (debug) fprint(2, " looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
|
||||
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 font %s\n", rune, stoken,
|
||||
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=0x%x troffcharwidth=%d\n",
|
||||
rune, rune, (*cp)->postfontid, (*cp)->postcharid, (*cp)->troffcharwidth);
|
||||
}
|
||||
|
||||
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 defined.\n", rune);
|
||||
|
||||
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, clean up for postscript */
|
||||
wid = chartorune(&r, (*cp)->name);
|
||||
if(' '<r && r<0x7F)
|
||||
Bprint(Bstdout, "%d build_%s\n", (*cp)->troffcharwidth, (*cp)->name);
|
||||
else{
|
||||
if((*cp)->name[wid] != 0)
|
||||
error(FATAL, "character <%s> badly named\n", (*cp)->name);
|
||||
Bprint(Bstdout, "%d build_X%.4x\n", (*cp)->troffcharwidth, r);
|
||||
}
|
||||
|
||||
/* stash charent pointer in a list so that we can print these character definitions
|
||||
* 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, sizeof(struct charent *) * ++build_char_cnt,
|
||||
"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)].str);
|
||||
}
|
||||
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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue