17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier * ps.c
37dd7cddfSDavid du Colombier *
47dd7cddfSDavid du Colombier * provide postscript file reading support for page
57dd7cddfSDavid du Colombier */
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier #include <u.h>
87dd7cddfSDavid du Colombier #include <libc.h>
97dd7cddfSDavid du Colombier #include <draw.h>
107dd7cddfSDavid du Colombier #include <event.h>
117dd7cddfSDavid du Colombier #include <bio.h>
127dd7cddfSDavid du Colombier #include <ctype.h>
137dd7cddfSDavid du Colombier #include "page.h"
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier typedef struct PSInfo PSInfo;
167dd7cddfSDavid du Colombier typedef struct Page Page;
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier struct Page {
199a747e4fSDavid du Colombier char *name;
207dd7cddfSDavid du Colombier int offset; /* offset of page beginning within file */
217dd7cddfSDavid du Colombier };
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier struct PSInfo {
247dd7cddfSDavid du Colombier GSInfo;
257dd7cddfSDavid du Colombier Rectangle bbox; /* default bounding box */
267dd7cddfSDavid du Colombier Page *page;
277dd7cddfSDavid du Colombier int npage;
287dd7cddfSDavid du Colombier int clueless; /* don't know where page boundaries are */
2980ee5cbfSDavid du Colombier long psoff; /* location of %! in file */
307dd7cddfSDavid du Colombier char ctm[256];
317dd7cddfSDavid du Colombier };
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier static int pswritepage(Document *d, int fd, int page);
347dd7cddfSDavid du Colombier static Image* psdrawpage(Document *d, int page);
357dd7cddfSDavid du Colombier static char* pspagename(Document*, int);
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier #define R(r) (r).min.x, (r).min.y, (r).max.x, (r).max.y
387dd7cddfSDavid du Colombier Rectangle
rdbbox(char * p)397dd7cddfSDavid du Colombier rdbbox(char *p)
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier Rectangle r;
427dd7cddfSDavid du Colombier int a;
437dd7cddfSDavid du Colombier char *f[4];
447dd7cddfSDavid du Colombier while(*p == ':' || *p == ' ' || *p == '\t')
457dd7cddfSDavid du Colombier p++;
467dd7cddfSDavid du Colombier if(tokenize(p, f, 4) != 4)
477dd7cddfSDavid du Colombier return Rect(0,0,0,0);
487dd7cddfSDavid du Colombier r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3]));
497dd7cddfSDavid du Colombier r = canonrect(r);
507dd7cddfSDavid du Colombier if(Dx(r) <= 0 || Dy(r) <= 0)
517dd7cddfSDavid du Colombier return Rect(0,0,0,0);
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier if(truetoboundingbox)
547dd7cddfSDavid du Colombier return r;
557dd7cddfSDavid du Colombier
567dd7cddfSDavid du Colombier /* initdraw not called yet, can't use %R */
577dd7cddfSDavid du Colombier if(chatty) fprint(2, "[%d %d %d %d] -> ", R(r));
587dd7cddfSDavid du Colombier /*
597dd7cddfSDavid du Colombier * attempt to sniff out A4, 8½×11, others
607dd7cddfSDavid du Colombier * A4 is 596×842
617dd7cddfSDavid du Colombier * 8½×11 is 612×792
627dd7cddfSDavid du Colombier */
637dd7cddfSDavid du Colombier
647dd7cddfSDavid du Colombier a = Dx(r)*Dy(r);
659a747e4fSDavid du Colombier if(a < 300*300){ /* really small, probably supposed to be */
669a747e4fSDavid du Colombier /* empty */
679a747e4fSDavid du Colombier } else if(Dx(r) <= 596 && r.max.x <= 596 && Dy(r) > 792 && Dy(r) <= 842 && r.max.y <= 842) /* A4 */
687dd7cddfSDavid du Colombier r = Rect(0, 0, 596, 842);
697dd7cddfSDavid du Colombier else { /* cast up to 8½×11 */
707dd7cddfSDavid du Colombier if(Dx(r) <= 612 && r.max.x <= 612){
717dd7cddfSDavid du Colombier r.min.x = 0;
727dd7cddfSDavid du Colombier r.max.x = 612;
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier if(Dy(r) <= 792 && r.max.y <= 792){
757dd7cddfSDavid du Colombier r.min.y = 0;
767dd7cddfSDavid du Colombier r.max.y = 792;
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier if(chatty) fprint(2, "[%d %d %d %d]\n", R(r));
807dd7cddfSDavid du Colombier return r;
817dd7cddfSDavid du Colombier }
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier #define RECT(X) X.min.x, X.min.y, X.max.x, X.max.y
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier int
prefix(char * x,char * y)867dd7cddfSDavid du Colombier prefix(char *x, char *y)
877dd7cddfSDavid du Colombier {
887dd7cddfSDavid du Colombier return strncmp(x, y, strlen(y)) == 0;
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier /*
927dd7cddfSDavid du Colombier * document ps is really being printed as n-up pages.
937dd7cddfSDavid du Colombier * we need to treat every n pages as 1.
947dd7cddfSDavid du Colombier */
957dd7cddfSDavid du Colombier void
repaginate(PSInfo * ps,int n)967dd7cddfSDavid du Colombier repaginate(PSInfo *ps, int n)
977dd7cddfSDavid du Colombier {
987dd7cddfSDavid du Colombier int i, np, onp;
997dd7cddfSDavid du Colombier Page *page;
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier page = ps->page;
1027dd7cddfSDavid du Colombier onp = ps->npage;
1037dd7cddfSDavid du Colombier np = (ps->npage+n-1)/n;
1047dd7cddfSDavid du Colombier
1057dd7cddfSDavid du Colombier if(chatty) {
1067dd7cddfSDavid du Colombier for(i=0; i<=onp+1; i++)
1077dd7cddfSDavid du Colombier print("page %d: %d\n", i, page[i].offset);
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier for(i=0; i<np; i++)
1117dd7cddfSDavid du Colombier page[i] = page[n*i];
1127dd7cddfSDavid du Colombier
1137dd7cddfSDavid du Colombier /* trailer */
1147dd7cddfSDavid du Colombier page[np] = page[onp];
1157dd7cddfSDavid du Colombier
1167dd7cddfSDavid du Colombier /* EOF */
1177dd7cddfSDavid du Colombier page[np+1] = page[onp+1];
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier ps->npage = np;
1207dd7cddfSDavid du Colombier
1217dd7cddfSDavid du Colombier if(chatty) {
1227dd7cddfSDavid du Colombier for(i=0; i<=np+1; i++)
1237dd7cddfSDavid du Colombier print("page %d: %d\n", i, page[i].offset);
1247dd7cddfSDavid du Colombier }
1257dd7cddfSDavid du Colombier
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier Document*
initps(Biobuf * b,int argc,char ** argv,uchar * buf,int nbuf)1297dd7cddfSDavid du Colombier initps(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
1307dd7cddfSDavid du Colombier {
1317dd7cddfSDavid du Colombier Document *d;
1327dd7cddfSDavid du Colombier PSInfo *ps;
1339a747e4fSDavid du Colombier char *p;
1347dd7cddfSDavid du Colombier char *q, *r;
1357dd7cddfSDavid du Colombier char eol;
1367dd7cddfSDavid du Colombier char *nargv[1];
1377dd7cddfSDavid du Colombier char fdbuf[20];
1389a747e4fSDavid du Colombier char tmp[32];
1397dd7cddfSDavid du Colombier int fd;
14080ee5cbfSDavid du Colombier int i;
1417dd7cddfSDavid du Colombier int incomments;
1427dd7cddfSDavid du Colombier int cantranslate;
1437dd7cddfSDavid du Colombier int trailer=0;
1447dd7cddfSDavid du Colombier int nesting=0;
1457dd7cddfSDavid du Colombier int dumb=0;
146d9306527SDavid du Colombier int landscape=0;
14780ee5cbfSDavid du Colombier long psoff;
1487dd7cddfSDavid du Colombier long npage, mpage;
1497dd7cddfSDavid du Colombier Page *page;
1507dd7cddfSDavid du Colombier Rectangle bbox = Rect(0,0,0,0);
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier if(argc > 1) {
1537dd7cddfSDavid du Colombier fprint(2, "can only view one ps file at a time\n");
1547dd7cddfSDavid du Colombier return nil;
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier fprint(2, "reading through postscript...\n");
1587dd7cddfSDavid du Colombier if(b == nil){ /* standard input; spool to disk (ouch) */
1597dd7cddfSDavid du Colombier fd = spooltodisk(buf, nbuf, nil);
1607dd7cddfSDavid du Colombier sprint(fdbuf, "/fd/%d", fd);
1617dd7cddfSDavid du Colombier b = Bopen(fdbuf, OREAD);
1627dd7cddfSDavid du Colombier if(b == nil){
1637dd7cddfSDavid du Colombier fprint(2, "cannot open disk spool file\n");
1647dd7cddfSDavid du Colombier wexits("Bopen temp");
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier nargv[0] = fdbuf;
1677dd7cddfSDavid du Colombier argv = nargv;
1687dd7cddfSDavid du Colombier }
1697dd7cddfSDavid du Colombier
17080ee5cbfSDavid du Colombier /* find %!, perhaps after PCL nonsense */
1717dd7cddfSDavid du Colombier Bseek(b, 0, 0);
17280ee5cbfSDavid du Colombier psoff = 0;
17380ee5cbfSDavid du Colombier eol = 0;
17480ee5cbfSDavid du Colombier for(i=0; i<16; i++){
17580ee5cbfSDavid du Colombier psoff = Boffset(b);
1767dd7cddfSDavid du Colombier if(!(p = Brdline(b, eol='\n')) && !(p = Brdline(b, eol='\r'))) {
1777dd7cddfSDavid du Colombier fprint(2, "cannot find end of first line\n");
1787dd7cddfSDavid du Colombier wexits("initps");
1797dd7cddfSDavid du Colombier }
18080ee5cbfSDavid du Colombier if(p[0]=='\x1B')
18180ee5cbfSDavid du Colombier p++, psoff++;
18280ee5cbfSDavid du Colombier if(p[0] == '%' && p[1] == '!')
18380ee5cbfSDavid du Colombier break;
18480ee5cbfSDavid du Colombier }
18580ee5cbfSDavid du Colombier if(i == 16){
1867dd7cddfSDavid du Colombier werrstr("not ps");
1877dd7cddfSDavid du Colombier return nil;
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier
1907dd7cddfSDavid du Colombier /* page counting */
1917dd7cddfSDavid du Colombier npage = 0;
1927dd7cddfSDavid du Colombier mpage = 16;
1937dd7cddfSDavid du Colombier page = emalloc(mpage*sizeof(*page));
1947dd7cddfSDavid du Colombier memset(page, 0, mpage*sizeof(*page));
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier cantranslate = goodps;
1977dd7cddfSDavid du Colombier incomments = 1;
1987dd7cddfSDavid du Colombier Keepreading:
1997dd7cddfSDavid du Colombier while(p = Brdline(b, eol)) {
2007dd7cddfSDavid du Colombier if(p[0] == '%')
201*493edcedSDavid du Colombier if(chatty > 1) fprint(2, "ps %.*s\n", utfnlen(p, Blinelen(b)-1), p);
2027dd7cddfSDavid du Colombier if(npage == mpage) {
2037dd7cddfSDavid du Colombier mpage *= 2;
2047dd7cddfSDavid du Colombier page = erealloc(page, mpage*sizeof(*page));
2057dd7cddfSDavid du Colombier memset(&page[npage], 0, npage*sizeof(*page));
2067dd7cddfSDavid du Colombier }
2077dd7cddfSDavid du Colombier
2087dd7cddfSDavid du Colombier if(p[0] != '%' || p[1] != '%')
2097dd7cddfSDavid du Colombier continue;
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier if(prefix(p, "%%BeginDocument")) {
2127dd7cddfSDavid du Colombier nesting++;
2137dd7cddfSDavid du Colombier continue;
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier if(nesting > 0 && prefix(p, "%%EndDocument")) {
2167dd7cddfSDavid du Colombier nesting--;
2177dd7cddfSDavid du Colombier continue;
2187dd7cddfSDavid du Colombier }
2197dd7cddfSDavid du Colombier if(nesting)
2207dd7cddfSDavid du Colombier continue;
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier if(prefix(p, "%%EndComment")) {
2237dd7cddfSDavid du Colombier incomments = 0;
2247dd7cddfSDavid du Colombier continue;
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier if(reverse == -1 && prefix(p, "%%PageOrder")) {
2277dd7cddfSDavid du Colombier /* glean whether we should reverse the viewing order */
2287dd7cddfSDavid du Colombier p[Blinelen(b)-1] = 0;
2297dd7cddfSDavid du Colombier if(strstr(p, "Ascend"))
2307dd7cddfSDavid du Colombier reverse = 0;
2317dd7cddfSDavid du Colombier else if(strstr(p, "Descend"))
2327dd7cddfSDavid du Colombier reverse = 1;
2337dd7cddfSDavid du Colombier else if(strstr(p, "Special"))
2347dd7cddfSDavid du Colombier dumb = 1;
2357dd7cddfSDavid du Colombier p[Blinelen(b)-1] = '\n';
2367dd7cddfSDavid du Colombier continue;
2377dd7cddfSDavid du Colombier } else if(prefix(p, "%%Trailer")) {
2387dd7cddfSDavid du Colombier incomments = 1;
2397dd7cddfSDavid du Colombier page[npage].offset = Boffset(b)-Blinelen(b);
2407dd7cddfSDavid du Colombier trailer = 1;
2417dd7cddfSDavid du Colombier continue;
242d9306527SDavid du Colombier } else if(incomments && prefix(p, "%%Orientation")) {
243d9306527SDavid du Colombier if(strstr(p, "Landscape"))
244d9306527SDavid du Colombier landscape = 1;
2457dd7cddfSDavid du Colombier } else if(incomments && Dx(bbox)==0 && prefix(p, q="%%BoundingBox")) {
2467dd7cddfSDavid du Colombier bbox = rdbbox(p+strlen(q)+1);
2477dd7cddfSDavid du Colombier if(chatty)
2487dd7cddfSDavid du Colombier /* can't use %R because haven't initdraw() */
2497dd7cddfSDavid du Colombier fprint(2, "document bbox [%d %d %d %d]\n",
2507dd7cddfSDavid du Colombier RECT(bbox));
2517dd7cddfSDavid du Colombier continue;
2527dd7cddfSDavid du Colombier }
2537dd7cddfSDavid du Colombier
2547dd7cddfSDavid du Colombier /*
2557dd7cddfSDavid du Colombier * If they use the initgraphics command, we can't play our translation tricks.
2567dd7cddfSDavid du Colombier */
2577dd7cddfSDavid du Colombier p[Blinelen(b)-1] = 0;
2587dd7cddfSDavid du Colombier if((q=strstr(p, "initgraphics")) && ((r=strchr(p, '%'))==nil || r > q))
2597dd7cddfSDavid du Colombier cantranslate = 0;
2607dd7cddfSDavid du Colombier p[Blinelen(b)-1] = eol;
2617dd7cddfSDavid du Colombier
2627dd7cddfSDavid du Colombier if(!prefix(p, "%%Page:"))
2637dd7cddfSDavid du Colombier continue;
2647dd7cddfSDavid du Colombier
2657dd7cddfSDavid du Colombier /*
2667dd7cddfSDavid du Colombier * figure out of the %%Page: line contains a page number
2677dd7cddfSDavid du Colombier * or some other page description to use in the menu bar.
2687dd7cddfSDavid du Colombier *
2697dd7cddfSDavid du Colombier * lines look like %%Page: x y or %%Page: x
2707dd7cddfSDavid du Colombier * we prefer just x, and will generate our
2717dd7cddfSDavid du Colombier * own if necessary.
2727dd7cddfSDavid du Colombier */
2737dd7cddfSDavid du Colombier p[Blinelen(b)-1] = 0;
2747dd7cddfSDavid du Colombier if(chatty) fprint(2, "page %s\n", p);
2757dd7cddfSDavid du Colombier r = p+7;
2767dd7cddfSDavid du Colombier while(*r == ' ' || *r == '\t')
2777dd7cddfSDavid du Colombier r++;
2787dd7cddfSDavid du Colombier q = r;
2797dd7cddfSDavid du Colombier while(*q && *q != ' ' && *q != '\t')
2807dd7cddfSDavid du Colombier q++;
2819a747e4fSDavid du Colombier free(page[npage].name);
2827dd7cddfSDavid du Colombier if(*r) {
2837dd7cddfSDavid du Colombier if(*r == '"' && *q == '"')
2847dd7cddfSDavid du Colombier r++, q--;
2857dd7cddfSDavid du Colombier if(*q)
2867dd7cddfSDavid du Colombier *q = 0;
2879a747e4fSDavid du Colombier page[npage].name = estrdup(r);
2887dd7cddfSDavid du Colombier *q = 'x';
2899a747e4fSDavid du Colombier } else {
2909a747e4fSDavid du Colombier snprint(tmp, sizeof tmp, "p %ld", npage+1);
2919a747e4fSDavid du Colombier page[npage].name = estrdup(tmp);
2929a747e4fSDavid du Colombier }
2937dd7cddfSDavid du Colombier
2947dd7cddfSDavid du Colombier /*
2957dd7cddfSDavid du Colombier * store the offset info for later viewing
2967dd7cddfSDavid du Colombier */
2977dd7cddfSDavid du Colombier trailer = 0;
2987dd7cddfSDavid du Colombier p[Blinelen(b)-1] = eol;
2997dd7cddfSDavid du Colombier page[npage++].offset = Boffset(b)-Blinelen(b);
3007dd7cddfSDavid du Colombier }
3017dd7cddfSDavid du Colombier if(Blinelen(b) > 0){
3027dd7cddfSDavid du Colombier fprint(2, "page: linelen %d\n", Blinelen(b));
3037dd7cddfSDavid du Colombier Bseek(b, Blinelen(b), 1);
3047dd7cddfSDavid du Colombier goto Keepreading;
3057dd7cddfSDavid du Colombier }
3067dd7cddfSDavid du Colombier
3077dd7cddfSDavid du Colombier if(Dx(bbox) == 0 || Dy(bbox) == 0)
3087dd7cddfSDavid du Colombier bbox = Rect(0,0,612,792); /* 8½×11 */
3097dd7cddfSDavid du Colombier /*
3107dd7cddfSDavid du Colombier * if we didn't find any pages, assume the document
3117dd7cddfSDavid du Colombier * is one big page
3127dd7cddfSDavid du Colombier */
3137dd7cddfSDavid du Colombier if(npage == 0) {
3147dd7cddfSDavid du Colombier dumb = 1;
3157dd7cddfSDavid du Colombier if(chatty) fprint(2, "don't know where pages are\n");
3167dd7cddfSDavid du Colombier reverse = 0;
3177dd7cddfSDavid du Colombier goodps = 0;
3187dd7cddfSDavid du Colombier trailer = 0;
3199a747e4fSDavid du Colombier page[npage].name = "p 1";
3207dd7cddfSDavid du Colombier page[npage++].offset = 0;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier
3237dd7cddfSDavid du Colombier if(npage+2 > mpage) {
3247dd7cddfSDavid du Colombier mpage += 2;
3257dd7cddfSDavid du Colombier page = erealloc(page, mpage*sizeof(*page));
3267dd7cddfSDavid du Colombier memset(&page[mpage-2], 0, 2*sizeof(*page));
3277dd7cddfSDavid du Colombier }
3287dd7cddfSDavid du Colombier
3297dd7cddfSDavid du Colombier if(!trailer)
3307dd7cddfSDavid du Colombier page[npage].offset = Boffset(b);
3317dd7cddfSDavid du Colombier
3327dd7cddfSDavid du Colombier Bseek(b, 0, 2); /* EOF */
3337dd7cddfSDavid du Colombier page[npage+1].offset = Boffset(b);
3347dd7cddfSDavid du Colombier
3357dd7cddfSDavid du Colombier d = emalloc(sizeof(*d));
3367dd7cddfSDavid du Colombier ps = emalloc(sizeof(*ps));
3377dd7cddfSDavid du Colombier ps->page = page;
3387dd7cddfSDavid du Colombier ps->npage = npage;
3397dd7cddfSDavid du Colombier ps->bbox = bbox;
34080ee5cbfSDavid du Colombier ps->psoff = psoff;
3417dd7cddfSDavid du Colombier
3427dd7cddfSDavid du Colombier d->extra = ps;
3437dd7cddfSDavid du Colombier d->npage = ps->npage;
3447dd7cddfSDavid du Colombier d->b = b;
3457dd7cddfSDavid du Colombier d->drawpage = psdrawpage;
3467dd7cddfSDavid du Colombier d->pagename = pspagename;
3477dd7cddfSDavid du Colombier
3487dd7cddfSDavid du Colombier d->fwdonly = ps->clueless = dumb;
3497dd7cddfSDavid du Colombier d->docname = argv[0];
3507dd7cddfSDavid du Colombier
351593dc095SDavid du Colombier if(spawngs(ps, "-dSAFER") < 0)
3527dd7cddfSDavid du Colombier return nil;
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier if(!cantranslate)
3557dd7cddfSDavid du Colombier bbox.min = ZP;
356d9306527SDavid du Colombier setdim(ps, bbox, ppi, landscape);
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier if(goodps){
3597dd7cddfSDavid du Colombier /*
3607dd7cddfSDavid du Colombier * We want to only send the page (i.e. not header and trailer) information
3617dd7cddfSDavid du Colombier * for each page, so initialize the device by sending the header now.
3627dd7cddfSDavid du Colombier */
3637dd7cddfSDavid du Colombier pswritepage(d, ps->gsfd, -1);
3647dd7cddfSDavid du Colombier waitgs(ps);
3657dd7cddfSDavid du Colombier }
3667dd7cddfSDavid du Colombier
3677dd7cddfSDavid du Colombier if(dumb) {
3687dd7cddfSDavid du Colombier fprint(ps->gsfd, "(%s) run\n", argv[0]);
36980ee5cbfSDavid du Colombier fprint(ps->gsfd, "(/fd/3) (w) file dup (THIS IS NOT A PLAN9 BITMAP 01234567890123456789012345678901234567890123456789\\n) writestring flushfile\n");
3707dd7cddfSDavid du Colombier }
3717dd7cddfSDavid du Colombier
3727dd7cddfSDavid du Colombier ps->bbox = bbox;
3737dd7cddfSDavid du Colombier
3747dd7cddfSDavid du Colombier return d;
3757dd7cddfSDavid du Colombier }
3767dd7cddfSDavid du Colombier
3777dd7cddfSDavid du Colombier static int
pswritepage(Document * d,int fd,int page)3787dd7cddfSDavid du Colombier pswritepage(Document *d, int fd, int page)
3797dd7cddfSDavid du Colombier {
3807dd7cddfSDavid du Colombier Biobuf *b = d->b;
3817dd7cddfSDavid du Colombier PSInfo *ps = d->extra;
3827dd7cddfSDavid du Colombier int t, n, i;
3837dd7cddfSDavid du Colombier long begin, end;
3847dd7cddfSDavid du Colombier char buf[8192];
3857dd7cddfSDavid du Colombier
3867dd7cddfSDavid du Colombier if(page == -1)
38780ee5cbfSDavid du Colombier begin = ps->psoff;
3887dd7cddfSDavid du Colombier else
3897dd7cddfSDavid du Colombier begin = ps->page[page].offset;
3907dd7cddfSDavid du Colombier
3917dd7cddfSDavid du Colombier end = ps->page[page+1].offset;
3927dd7cddfSDavid du Colombier
3937dd7cddfSDavid du Colombier if(chatty) {
3947dd7cddfSDavid du Colombier fprint(2, "writepage(%d)... from #%ld to #%ld...\n",
3957dd7cddfSDavid du Colombier page, begin, end);
3967dd7cddfSDavid du Colombier }
3977dd7cddfSDavid du Colombier Bseek(b, begin, 0);
3987dd7cddfSDavid du Colombier
3997dd7cddfSDavid du Colombier t = end-begin;
4007dd7cddfSDavid du Colombier n = sizeof(buf);
4017dd7cddfSDavid du Colombier if(n > t) n = t;
4027dd7cddfSDavid du Colombier while(t > 0 && (i=Bread(b, buf, n)) > 0) {
4037dd7cddfSDavid du Colombier if(write(fd, buf, i) != i)
4047dd7cddfSDavid du Colombier return -1;
4057dd7cddfSDavid du Colombier t -= i;
4067dd7cddfSDavid du Colombier if(n > t)
4077dd7cddfSDavid du Colombier n = t;
4087dd7cddfSDavid du Colombier }
4097dd7cddfSDavid du Colombier return end-begin;
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier
4127dd7cddfSDavid du Colombier static Image*
psdrawpage(Document * d,int page)4137dd7cddfSDavid du Colombier psdrawpage(Document *d, int page)
4147dd7cddfSDavid du Colombier {
4157dd7cddfSDavid du Colombier PSInfo *ps = d->extra;
4167dd7cddfSDavid du Colombier Image *im;
4177dd7cddfSDavid du Colombier
4187dd7cddfSDavid du Colombier if(ps->clueless)
4197dd7cddfSDavid du Colombier return readimage(display, ps->gsdfd, 0);
4207dd7cddfSDavid du Colombier
4217dd7cddfSDavid du Colombier waitgs(ps);
4227dd7cddfSDavid du Colombier
4237dd7cddfSDavid du Colombier if(goodps)
4247dd7cddfSDavid du Colombier pswritepage(d, ps->gsfd, page);
4257dd7cddfSDavid du Colombier else {
4267dd7cddfSDavid du Colombier pswritepage(d, ps->gsfd, -1);
4277dd7cddfSDavid du Colombier pswritepage(d, ps->gsfd, page);
4287dd7cddfSDavid du Colombier pswritepage(d, ps->gsfd, d->npage);
4297dd7cddfSDavid du Colombier }
4306b6b9ac8SDavid du Colombier /*
4316b6b9ac8SDavid du Colombier * If last line terminator is \r, gs will read ahead to check for \n
4326b6b9ac8SDavid du Colombier * so send one to avoid deadlock.
4336b6b9ac8SDavid du Colombier */
4346b6b9ac8SDavid du Colombier write(ps->gsfd, "\n", 1);
4357dd7cddfSDavid du Colombier im = readimage(display, ps->gsdfd, 0);
4367dd7cddfSDavid du Colombier if(im == nil) {
4377dd7cddfSDavid du Colombier fprint(2, "fatal: readimage error %r\n");
4387dd7cddfSDavid du Colombier wexits("readimage");
4397dd7cddfSDavid du Colombier }
4407dd7cddfSDavid du Colombier waitgs(ps);
4417dd7cddfSDavid du Colombier
4427dd7cddfSDavid du Colombier return im;
4437dd7cddfSDavid du Colombier }
4447dd7cddfSDavid du Colombier
4457dd7cddfSDavid du Colombier static char*
pspagename(Document * d,int page)4467dd7cddfSDavid du Colombier pspagename(Document *d, int page)
4477dd7cddfSDavid du Colombier {
4487dd7cddfSDavid du Colombier PSInfo *ps = (PSInfo *) d->extra;
4497dd7cddfSDavid du Colombier return ps->page[page].name;
4507dd7cddfSDavid du Colombier }
451