Blame


1 24c02865 2005-01-04 devnull /*
2 24c02865 2005-01-04 devnull * ps.c
3 24c02865 2005-01-04 devnull *
4 24c02865 2005-01-04 devnull * provide postscript file reading support for page
5 24c02865 2005-01-04 devnull */
6 24c02865 2005-01-04 devnull
7 24c02865 2005-01-04 devnull #include <u.h>
8 24c02865 2005-01-04 devnull #include <libc.h>
9 24c02865 2005-01-04 devnull #include <draw.h>
10 17157e4a 2006-03-20 devnull #include <cursor.h>
11 24c02865 2005-01-04 devnull #include <event.h>
12 24c02865 2005-01-04 devnull #include <bio.h>
13 24c02865 2005-01-04 devnull #include <ctype.h>
14 24c02865 2005-01-04 devnull #include "page.h"
15 24c02865 2005-01-04 devnull
16 24c02865 2005-01-04 devnull typedef struct PSInfo PSInfo;
17 24c02865 2005-01-04 devnull typedef struct Page Page;
18 24c02865 2005-01-04 devnull
19 24c02865 2005-01-04 devnull struct Page {
20 24c02865 2005-01-04 devnull char *name;
21 24c02865 2005-01-04 devnull int offset; /* offset of page beginning within file */
22 24c02865 2005-01-04 devnull };
23 24c02865 2005-01-04 devnull
24 24c02865 2005-01-04 devnull struct PSInfo {
25 24c02865 2005-01-04 devnull GSInfo gs;
26 24c02865 2005-01-04 devnull Rectangle bbox; /* default bounding box */
27 24c02865 2005-01-04 devnull Page *page;
28 24c02865 2005-01-04 devnull int npage;
29 24c02865 2005-01-04 devnull int clueless; /* don't know where page boundaries are */
30 24c02865 2005-01-04 devnull long psoff; /* location of %! in file */
31 24c02865 2005-01-04 devnull char ctm[256];
32 24c02865 2005-01-04 devnull };
33 24c02865 2005-01-04 devnull
34 24c02865 2005-01-04 devnull static int pswritepage(Document *d, int fd, int page);
35 24c02865 2005-01-04 devnull static Image* psdrawpage(Document *d, int page);
36 24c02865 2005-01-04 devnull static char* pspagename(Document*, int);
37 24c02865 2005-01-04 devnull
38 24c02865 2005-01-04 devnull #define R(r) (r).min.x, (r).min.y, (r).max.x, (r).max.y
39 24c02865 2005-01-04 devnull Rectangle
40 24c02865 2005-01-04 devnull rdbbox(char *p)
41 24c02865 2005-01-04 devnull {
42 24c02865 2005-01-04 devnull Rectangle r;
43 24c02865 2005-01-04 devnull int a;
44 24c02865 2005-01-04 devnull char *f[4];
45 24c02865 2005-01-04 devnull while(*p == ':' || *p == ' ' || *p == '\t')
46 24c02865 2005-01-04 devnull p++;
47 24c02865 2005-01-04 devnull if(tokenize(p, f, 4) != 4)
48 24c02865 2005-01-04 devnull return Rect(0,0,0,0);
49 24c02865 2005-01-04 devnull r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3]));
50 24c02865 2005-01-04 devnull r = canonrect(r);
51 24c02865 2005-01-04 devnull if(Dx(r) <= 0 || Dy(r) <= 0)
52 24c02865 2005-01-04 devnull return Rect(0,0,0,0);
53 24c02865 2005-01-04 devnull
54 24c02865 2005-01-04 devnull if(truetoboundingbox)
55 24c02865 2005-01-04 devnull return r;
56 24c02865 2005-01-04 devnull
57 24c02865 2005-01-04 devnull /* initdraw not called yet, can't use %R */
58 24c02865 2005-01-04 devnull if(chatty) fprint(2, "[%d %d %d %d] -> ", R(r));
59 24c02865 2005-01-04 devnull /*
60 24c02865 2005-01-04 devnull * attempt to sniff out A4, 8½×11, others
61 24c02865 2005-01-04 devnull * A4 is 596×842
62 24c02865 2005-01-04 devnull * 8½×11 is 612×792
63 24c02865 2005-01-04 devnull */
64 24c02865 2005-01-04 devnull
65 24c02865 2005-01-04 devnull a = Dx(r)*Dy(r);
66 24c02865 2005-01-04 devnull if(a < 300*300){ /* really small, probably supposed to be */
67 24c02865 2005-01-04 devnull /* empty */
68 24c02865 2005-01-04 devnull } else if(Dx(r) <= 596 && r.max.x <= 596 && Dy(r) > 792 && Dy(r) <= 842 && r.max.y <= 842) /* A4 */
69 24c02865 2005-01-04 devnull r = Rect(0, 0, 596, 842);
70 24c02865 2005-01-04 devnull else { /* cast up to 8½×11 */
71 24c02865 2005-01-04 devnull if(Dx(r) <= 612 && r.max.x <= 612){
72 24c02865 2005-01-04 devnull r.min.x = 0;
73 24c02865 2005-01-04 devnull r.max.x = 612;
74 24c02865 2005-01-04 devnull }
75 24c02865 2005-01-04 devnull if(Dy(r) <= 792 && r.max.y <= 792){
76 24c02865 2005-01-04 devnull r.min.y = 0;
77 24c02865 2005-01-04 devnull r.max.y = 792;
78 24c02865 2005-01-04 devnull }
79 24c02865 2005-01-04 devnull }
80 24c02865 2005-01-04 devnull if(chatty) fprint(2, "[%d %d %d %d]\n", R(r));
81 24c02865 2005-01-04 devnull return r;
82 24c02865 2005-01-04 devnull }
83 24c02865 2005-01-04 devnull
84 24c02865 2005-01-04 devnull #define RECT(X) X.min.x, X.min.y, X.max.x, X.max.y
85 24c02865 2005-01-04 devnull
86 24c02865 2005-01-04 devnull int
87 24c02865 2005-01-04 devnull prefix(char *x, char *y)
88 24c02865 2005-01-04 devnull {
89 24c02865 2005-01-04 devnull return strncmp(x, y, strlen(y)) == 0;
90 24c02865 2005-01-04 devnull }
91 24c02865 2005-01-04 devnull
92 24c02865 2005-01-04 devnull /*
93 24c02865 2005-01-04 devnull * document ps is really being printed as n-up pages.
94 24c02865 2005-01-04 devnull * we need to treat every n pages as 1.
95 24c02865 2005-01-04 devnull */
96 24c02865 2005-01-04 devnull void
97 24c02865 2005-01-04 devnull repaginate(PSInfo *ps, int n)
98 24c02865 2005-01-04 devnull {
99 24c02865 2005-01-04 devnull int i, np, onp;
100 24c02865 2005-01-04 devnull Page *page;
101 24c02865 2005-01-04 devnull
102 24c02865 2005-01-04 devnull page = ps->page;
103 24c02865 2005-01-04 devnull onp = ps->npage;
104 24c02865 2005-01-04 devnull np = (ps->npage+n-1)/n;
105 24c02865 2005-01-04 devnull
106 24c02865 2005-01-04 devnull if(chatty) {
107 24c02865 2005-01-04 devnull for(i=0; i<=onp+1; i++)
108 24c02865 2005-01-04 devnull print("page %d: %d\n", i, page[i].offset);
109 24c02865 2005-01-04 devnull }
110 24c02865 2005-01-04 devnull
111 24c02865 2005-01-04 devnull for(i=0; i<np; i++)
112 24c02865 2005-01-04 devnull page[i] = page[n*i];
113 24c02865 2005-01-04 devnull
114 24c02865 2005-01-04 devnull /* trailer */
115 24c02865 2005-01-04 devnull page[np] = page[onp];
116 24c02865 2005-01-04 devnull
117 24c02865 2005-01-04 devnull /* EOF */
118 24c02865 2005-01-04 devnull page[np+1] = page[onp+1];
119 24c02865 2005-01-04 devnull
120 24c02865 2005-01-04 devnull ps->npage = np;
121 24c02865 2005-01-04 devnull
122 24c02865 2005-01-04 devnull if(chatty) {
123 24c02865 2005-01-04 devnull for(i=0; i<=np+1; i++)
124 24c02865 2005-01-04 devnull print("page %d: %d\n", i, page[i].offset);
125 24c02865 2005-01-04 devnull }
126 24c02865 2005-01-04 devnull
127 24c02865 2005-01-04 devnull }
128 24c02865 2005-01-04 devnull
129 24c02865 2005-01-04 devnull Document*
130 24c02865 2005-01-04 devnull initps(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
131 24c02865 2005-01-04 devnull {
132 24c02865 2005-01-04 devnull Document *d;
133 24c02865 2005-01-04 devnull PSInfo *ps;
134 24c02865 2005-01-04 devnull char *p;
135 24c02865 2005-01-04 devnull char *q, *r;
136 24c02865 2005-01-04 devnull char eol;
137 24c02865 2005-01-04 devnull char *nargv[1];
138 24c02865 2005-01-04 devnull char fdbuf[20];
139 24c02865 2005-01-04 devnull char tmp[32];
140 24c02865 2005-01-04 devnull int fd;
141 24c02865 2005-01-04 devnull int i;
142 24c02865 2005-01-04 devnull int incomments;
143 24c02865 2005-01-04 devnull int cantranslate;
144 24c02865 2005-01-04 devnull int trailer=0;
145 24c02865 2005-01-04 devnull int nesting=0;
146 24c02865 2005-01-04 devnull int dumb=0;
147 24c02865 2005-01-04 devnull int landscape=0;
148 24c02865 2005-01-04 devnull long psoff;
149 24c02865 2005-01-04 devnull long npage, mpage;
150 24c02865 2005-01-04 devnull Page *page;
151 24c02865 2005-01-04 devnull Rectangle bbox = Rect(0,0,0,0);
152 24c02865 2005-01-04 devnull
153 24c02865 2005-01-04 devnull if(argc > 1) {
154 24c02865 2005-01-04 devnull fprint(2, "can only view one ps file at a time\n");
155 24c02865 2005-01-04 devnull return nil;
156 24c02865 2005-01-04 devnull }
157 24c02865 2005-01-04 devnull
158 24c02865 2005-01-04 devnull fprint(2, "reading through postscript...\n");
159 24c02865 2005-01-04 devnull if(b == nil){ /* standard input; spool to disk (ouch) */
160 24c02865 2005-01-04 devnull fd = spooltodisk(buf, nbuf, nil);
161 24c02865 2005-01-04 devnull sprint(fdbuf, "/fd/%d", fd);
162 24c02865 2005-01-04 devnull b = Bopen(fdbuf, OREAD);
163 24c02865 2005-01-04 devnull if(b == nil){
164 24c02865 2005-01-04 devnull fprint(2, "cannot open disk spool file\n");
165 24c02865 2005-01-04 devnull wexits("Bopen temp");
166 24c02865 2005-01-04 devnull }
167 24c02865 2005-01-04 devnull nargv[0] = fdbuf;
168 24c02865 2005-01-04 devnull argv = nargv;
169 24c02865 2005-01-04 devnull }
170 24c02865 2005-01-04 devnull
171 24c02865 2005-01-04 devnull /* find %!, perhaps after PCL nonsense */
172 24c02865 2005-01-04 devnull Bseek(b, 0, 0);
173 24c02865 2005-01-04 devnull psoff = 0;
174 24c02865 2005-01-04 devnull eol = 0;
175 24c02865 2005-01-04 devnull for(i=0; i<16; i++){
176 24c02865 2005-01-04 devnull psoff = Boffset(b);
177 24c02865 2005-01-04 devnull if(!(p = Brdline(b, eol='\n')) && !(p = Brdline(b, eol='\r'))) {
178 24c02865 2005-01-04 devnull fprint(2, "cannot find end of first line\n");
179 24c02865 2005-01-04 devnull wexits("initps");
180 24c02865 2005-01-04 devnull }
181 24c02865 2005-01-04 devnull if(p[0]=='\x1B')
182 24c02865 2005-01-04 devnull p++, psoff++;
183 24c02865 2005-01-04 devnull if(p[0] == '%' && p[1] == '!')
184 24c02865 2005-01-04 devnull break;
185 24c02865 2005-01-04 devnull }
186 24c02865 2005-01-04 devnull if(i == 16){
187 24c02865 2005-01-04 devnull werrstr("not ps");
188 24c02865 2005-01-04 devnull return nil;
189 24c02865 2005-01-04 devnull }
190 24c02865 2005-01-04 devnull
191 24c02865 2005-01-04 devnull /* page counting */
192 24c02865 2005-01-04 devnull npage = 0;
193 24c02865 2005-01-04 devnull mpage = 16;
194 24c02865 2005-01-04 devnull page = emalloc(mpage*sizeof(*page));
195 24c02865 2005-01-04 devnull memset(page, 0, mpage*sizeof(*page));
196 24c02865 2005-01-04 devnull
197 24c02865 2005-01-04 devnull cantranslate = goodps;
198 24c02865 2005-01-04 devnull incomments = 1;
199 24c02865 2005-01-04 devnull Keepreading:
200 24c02865 2005-01-04 devnull while(p = Brdline(b, eol)) {
201 24c02865 2005-01-04 devnull if(p[0] == '%')
202 24c02865 2005-01-04 devnull if(chatty) fprint(2, "ps %.*s\n", utfnlen(p, Blinelen(b)-1), p);
203 24c02865 2005-01-04 devnull if(npage == mpage) {
204 24c02865 2005-01-04 devnull mpage *= 2;
205 24c02865 2005-01-04 devnull page = erealloc(page, mpage*sizeof(*page));
206 24c02865 2005-01-04 devnull memset(&page[npage], 0, npage*sizeof(*page));
207 24c02865 2005-01-04 devnull }
208 24c02865 2005-01-04 devnull
209 24c02865 2005-01-04 devnull if(p[0] != '%' || p[1] != '%')
210 24c02865 2005-01-04 devnull continue;
211 24c02865 2005-01-04 devnull
212 24c02865 2005-01-04 devnull if(prefix(p, "%%BeginDocument")) {
213 24c02865 2005-01-04 devnull nesting++;
214 24c02865 2005-01-04 devnull continue;
215 24c02865 2005-01-04 devnull }
216 24c02865 2005-01-04 devnull if(nesting > 0 && prefix(p, "%%EndDocument")) {
217 24c02865 2005-01-04 devnull nesting--;
218 24c02865 2005-01-04 devnull continue;
219 24c02865 2005-01-04 devnull }
220 24c02865 2005-01-04 devnull if(nesting)
221 24c02865 2005-01-04 devnull continue;
222 24c02865 2005-01-04 devnull
223 24c02865 2005-01-04 devnull if(prefix(p, "%%EndComment")) {
224 24c02865 2005-01-04 devnull incomments = 0;
225 24c02865 2005-01-04 devnull continue;
226 24c02865 2005-01-04 devnull }
227 24c02865 2005-01-04 devnull if(reverse == -1 && prefix(p, "%%PageOrder")) {
228 24c02865 2005-01-04 devnull /* glean whether we should reverse the viewing order */
229 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = 0;
230 24c02865 2005-01-04 devnull if(strstr(p, "Ascend"))
231 24c02865 2005-01-04 devnull reverse = 0;
232 24c02865 2005-01-04 devnull else if(strstr(p, "Descend"))
233 24c02865 2005-01-04 devnull reverse = 1;
234 24c02865 2005-01-04 devnull else if(strstr(p, "Special"))
235 24c02865 2005-01-04 devnull dumb = 1;
236 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = '\n';
237 24c02865 2005-01-04 devnull continue;
238 24c02865 2005-01-04 devnull } else if(prefix(p, "%%Trailer")) {
239 24c02865 2005-01-04 devnull incomments = 1;
240 24c02865 2005-01-04 devnull page[npage].offset = Boffset(b)-Blinelen(b);
241 24c02865 2005-01-04 devnull trailer = 1;
242 24c02865 2005-01-04 devnull continue;
243 24c02865 2005-01-04 devnull } else if(incomments && prefix(p, "%%Orientation")) {
244 24c02865 2005-01-04 devnull if(strstr(p, "Landscape"))
245 24c02865 2005-01-04 devnull landscape = 1;
246 24c02865 2005-01-04 devnull } else if(incomments && Dx(bbox)==0 && prefix(p, q="%%BoundingBox")) {
247 24c02865 2005-01-04 devnull bbox = rdbbox(p+strlen(q)+1);
248 24c02865 2005-01-04 devnull if(chatty)
249 24c02865 2005-01-04 devnull /* can't use %R because haven't initdraw() */
250 24c02865 2005-01-04 devnull fprint(2, "document bbox [%d %d %d %d]\n",
251 24c02865 2005-01-04 devnull RECT(bbox));
252 24c02865 2005-01-04 devnull continue;
253 24c02865 2005-01-04 devnull }
254 24c02865 2005-01-04 devnull
255 24c02865 2005-01-04 devnull /*
256 24c02865 2005-01-04 devnull * If they use the initgraphics command, we can't play our translation tricks.
257 24c02865 2005-01-04 devnull */
258 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = 0;
259 24c02865 2005-01-04 devnull if((q=strstr(p, "initgraphics")) && ((r=strchr(p, '%'))==nil || r > q))
260 24c02865 2005-01-04 devnull cantranslate = 0;
261 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = eol;
262 24c02865 2005-01-04 devnull
263 24c02865 2005-01-04 devnull if(!prefix(p, "%%Page:"))
264 24c02865 2005-01-04 devnull continue;
265 24c02865 2005-01-04 devnull
266 24c02865 2005-01-04 devnull /*
267 24c02865 2005-01-04 devnull * figure out of the %%Page: line contains a page number
268 24c02865 2005-01-04 devnull * or some other page description to use in the menu bar.
269 24c02865 2005-01-04 devnull *
270 24c02865 2005-01-04 devnull * lines look like %%Page: x y or %%Page: x
271 24c02865 2005-01-04 devnull * we prefer just x, and will generate our
272 24c02865 2005-01-04 devnull * own if necessary.
273 24c02865 2005-01-04 devnull */
274 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = 0;
275 24c02865 2005-01-04 devnull if(chatty) fprint(2, "page %s\n", p);
276 24c02865 2005-01-04 devnull r = p+7;
277 24c02865 2005-01-04 devnull while(*r == ' ' || *r == '\t')
278 24c02865 2005-01-04 devnull r++;
279 24c02865 2005-01-04 devnull q = r;
280 24c02865 2005-01-04 devnull while(*q && *q != ' ' && *q != '\t')
281 24c02865 2005-01-04 devnull q++;
282 24c02865 2005-01-04 devnull free(page[npage].name);
283 24c02865 2005-01-04 devnull if(*r) {
284 24c02865 2005-01-04 devnull if(*r == '"' && *q == '"')
285 24c02865 2005-01-04 devnull r++, q--;
286 24c02865 2005-01-04 devnull if(*q)
287 24c02865 2005-01-04 devnull *q = 0;
288 24c02865 2005-01-04 devnull page[npage].name = estrdup(r);
289 24c02865 2005-01-04 devnull *q = 'x';
290 24c02865 2005-01-04 devnull } else {
291 24c02865 2005-01-04 devnull snprint(tmp, sizeof tmp, "p %ld", npage+1);
292 24c02865 2005-01-04 devnull page[npage].name = estrdup(tmp);
293 24c02865 2005-01-04 devnull }
294 24c02865 2005-01-04 devnull
295 24c02865 2005-01-04 devnull /*
296 24c02865 2005-01-04 devnull * store the offset info for later viewing
297 24c02865 2005-01-04 devnull */
298 24c02865 2005-01-04 devnull trailer = 0;
299 24c02865 2005-01-04 devnull p[Blinelen(b)-1] = eol;
300 24c02865 2005-01-04 devnull page[npage++].offset = Boffset(b)-Blinelen(b);
301 24c02865 2005-01-04 devnull }
302 24c02865 2005-01-04 devnull if(Blinelen(b) > 0){
303 24c02865 2005-01-04 devnull fprint(2, "page: linelen %d\n", Blinelen(b));
304 24c02865 2005-01-04 devnull Bseek(b, Blinelen(b), 1);
305 24c02865 2005-01-04 devnull goto Keepreading;
306 24c02865 2005-01-04 devnull }
307 24c02865 2005-01-04 devnull
308 24c02865 2005-01-04 devnull if(Dx(bbox) == 0 || Dy(bbox) == 0)
309 24c02865 2005-01-04 devnull bbox = Rect(0,0,612,792); /* 8½×11 */
310 24c02865 2005-01-04 devnull /*
311 24c02865 2005-01-04 devnull * if we didn't find any pages, assume the document
312 24c02865 2005-01-04 devnull * is one big page
313 24c02865 2005-01-04 devnull */
314 24c02865 2005-01-04 devnull if(npage == 0) {
315 24c02865 2005-01-04 devnull dumb = 1;
316 24c02865 2005-01-04 devnull if(chatty) fprint(2, "don't know where pages are\n");
317 24c02865 2005-01-04 devnull reverse = 0;
318 24c02865 2005-01-04 devnull goodps = 0;
319 24c02865 2005-01-04 devnull trailer = 0;
320 24c02865 2005-01-04 devnull page[npage].name = "p 1";
321 24c02865 2005-01-04 devnull page[npage++].offset = 0;
322 24c02865 2005-01-04 devnull }
323 24c02865 2005-01-04 devnull
324 24c02865 2005-01-04 devnull if(npage+2 > mpage) {
325 24c02865 2005-01-04 devnull mpage += 2;
326 24c02865 2005-01-04 devnull page = erealloc(page, mpage*sizeof(*page));
327 24c02865 2005-01-04 devnull memset(&page[mpage-2], 0, 2*sizeof(*page));
328 24c02865 2005-01-04 devnull }
329 24c02865 2005-01-04 devnull
330 24c02865 2005-01-04 devnull if(!trailer)
331 24c02865 2005-01-04 devnull page[npage].offset = Boffset(b);
332 24c02865 2005-01-04 devnull
333 24c02865 2005-01-04 devnull Bseek(b, 0, 2); /* EOF */
334 24c02865 2005-01-04 devnull page[npage+1].offset = Boffset(b);
335 24c02865 2005-01-04 devnull
336 24c02865 2005-01-04 devnull d = emalloc(sizeof(*d));
337 24c02865 2005-01-04 devnull ps = emalloc(sizeof(*ps));
338 24c02865 2005-01-04 devnull ps->page = page;
339 24c02865 2005-01-04 devnull ps->npage = npage;
340 24c02865 2005-01-04 devnull ps->bbox = bbox;
341 24c02865 2005-01-04 devnull ps->psoff = psoff;
342 24c02865 2005-01-04 devnull
343 24c02865 2005-01-04 devnull d->extra = ps;
344 24c02865 2005-01-04 devnull d->npage = ps->npage;
345 24c02865 2005-01-04 devnull d->b = b;
346 24c02865 2005-01-04 devnull d->drawpage = psdrawpage;
347 24c02865 2005-01-04 devnull d->pagename = pspagename;
348 24c02865 2005-01-04 devnull
349 24c02865 2005-01-04 devnull d->fwdonly = ps->clueless = dumb;
350 24c02865 2005-01-04 devnull d->docname = argv[0];
351 24c02865 2005-01-04 devnull
352 17157e4a 2006-03-20 devnull if(spawngs(&ps->gs, "-dSAFER") < 0)
353 24c02865 2005-01-04 devnull return nil;
354 24c02865 2005-01-04 devnull
355 24c02865 2005-01-04 devnull if(!cantranslate)
356 24c02865 2005-01-04 devnull bbox.min = ZP;
357 24c02865 2005-01-04 devnull setdim(&ps->gs, bbox, ppi, landscape);
358 24c02865 2005-01-04 devnull
359 24c02865 2005-01-04 devnull if(goodps){
360 24c02865 2005-01-04 devnull /*
361 24c02865 2005-01-04 devnull * We want to only send the page (i.e. not header and trailer) information
362 24c02865 2005-01-04 devnull * for each page, so initialize the device by sending the header now.
363 24c02865 2005-01-04 devnull */
364 24c02865 2005-01-04 devnull pswritepage(d, ps->gs.gsfd, -1);
365 24c02865 2005-01-04 devnull waitgs(&ps->gs);
366 24c02865 2005-01-04 devnull }
367 24c02865 2005-01-04 devnull
368 24c02865 2005-01-04 devnull if(dumb) {
369 24c02865 2005-01-04 devnull fprint(ps->gs.gsfd, "(%s) run\n", argv[0]);
370 24c02865 2005-01-04 devnull fprint(ps->gs.gsfd, "(/fd/3) (w) file dup (THIS IS NOT A PLAN9 BITMAP 01234567890123456789012345678901234567890123456789\\n) writestring flushfile\n");
371 24c02865 2005-01-04 devnull }
372 24c02865 2005-01-04 devnull
373 24c02865 2005-01-04 devnull ps->bbox = bbox;
374 24c02865 2005-01-04 devnull
375 24c02865 2005-01-04 devnull return d;
376 24c02865 2005-01-04 devnull }
377 24c02865 2005-01-04 devnull
378 24c02865 2005-01-04 devnull static int
379 24c02865 2005-01-04 devnull pswritepage(Document *d, int fd, int page)
380 24c02865 2005-01-04 devnull {
381 24c02865 2005-01-04 devnull Biobuf *b = d->b;
382 24c02865 2005-01-04 devnull PSInfo *ps = d->extra;
383 24c02865 2005-01-04 devnull int t, n, i;
384 24c02865 2005-01-04 devnull long begin, end;
385 24c02865 2005-01-04 devnull char buf[8192];
386 24c02865 2005-01-04 devnull
387 24c02865 2005-01-04 devnull if(page == -1)
388 24c02865 2005-01-04 devnull begin = ps->psoff;
389 24c02865 2005-01-04 devnull else
390 24c02865 2005-01-04 devnull begin = ps->page[page].offset;
391 24c02865 2005-01-04 devnull
392 24c02865 2005-01-04 devnull end = ps->page[page+1].offset;
393 24c02865 2005-01-04 devnull
394 24c02865 2005-01-04 devnull if(chatty) {
395 24c02865 2005-01-04 devnull fprint(2, "writepage(%d)... from #%ld to #%ld...\n",
396 24c02865 2005-01-04 devnull page, begin, end);
397 24c02865 2005-01-04 devnull }
398 24c02865 2005-01-04 devnull Bseek(b, begin, 0);
399 24c02865 2005-01-04 devnull
400 24c02865 2005-01-04 devnull t = end-begin;
401 24c02865 2005-01-04 devnull n = sizeof(buf);
402 24c02865 2005-01-04 devnull if(n > t) n = t;
403 24c02865 2005-01-04 devnull while(t > 0 && (i=Bread(b, buf, n)) > 0) {
404 24c02865 2005-01-04 devnull if(write(fd, buf, i) != i)
405 24c02865 2005-01-04 devnull return -1;
406 24c02865 2005-01-04 devnull t -= i;
407 24c02865 2005-01-04 devnull if(n > t)
408 24c02865 2005-01-04 devnull n = t;
409 24c02865 2005-01-04 devnull }
410 24c02865 2005-01-04 devnull return end-begin;
411 24c02865 2005-01-04 devnull }
412 24c02865 2005-01-04 devnull
413 24c02865 2005-01-04 devnull static Image*
414 24c02865 2005-01-04 devnull psdrawpage(Document *d, int page)
415 24c02865 2005-01-04 devnull {
416 24c02865 2005-01-04 devnull PSInfo *ps = d->extra;
417 24c02865 2005-01-04 devnull Image *im;
418 24c02865 2005-01-04 devnull
419 24c02865 2005-01-04 devnull if(ps->clueless)
420 24c02865 2005-01-04 devnull return readimage(display, ps->gs.gsdfd, 0);
421 24c02865 2005-01-04 devnull
422 24c02865 2005-01-04 devnull waitgs(&ps->gs);
423 24c02865 2005-01-04 devnull
424 24c02865 2005-01-04 devnull if(goodps)
425 24c02865 2005-01-04 devnull pswritepage(d, ps->gs.gsfd, page);
426 24c02865 2005-01-04 devnull else {
427 24c02865 2005-01-04 devnull pswritepage(d, ps->gs.gsfd, -1);
428 24c02865 2005-01-04 devnull pswritepage(d, ps->gs.gsfd, page);
429 24c02865 2005-01-04 devnull pswritepage(d, ps->gs.gsfd, d->npage);
430 24c02865 2005-01-04 devnull }
431 24c02865 2005-01-04 devnull /*
432 24c02865 2005-01-04 devnull * If last line terminator is \r, gs will read ahead to check for \n
433 24c02865 2005-01-04 devnull * so send one to avoid deadlock.
434 24c02865 2005-01-04 devnull */
435 24c02865 2005-01-04 devnull write(ps->gs.gsfd, "\n", 1);
436 24c02865 2005-01-04 devnull im = readimage(display, ps->gs.gsdfd, 0);
437 24c02865 2005-01-04 devnull if(im == nil) {
438 24c02865 2005-01-04 devnull fprint(2, "fatal: readimage error %r\n");
439 24c02865 2005-01-04 devnull wexits("readimage");
440 24c02865 2005-01-04 devnull }
441 24c02865 2005-01-04 devnull waitgs(&ps->gs);
442 24c02865 2005-01-04 devnull
443 24c02865 2005-01-04 devnull return im;
444 24c02865 2005-01-04 devnull }
445 24c02865 2005-01-04 devnull
446 24c02865 2005-01-04 devnull static char*
447 24c02865 2005-01-04 devnull pspagename(Document *d, int page)
448 24c02865 2005-01-04 devnull {
449 24c02865 2005-01-04 devnull PSInfo *ps = (PSInfo *) d->extra;
450 24c02865 2005-01-04 devnull return ps->page[page].name;
451 24c02865 2005-01-04 devnull }