blob: 47a7f327758a7fe0ca55dbd929184055aff0055d [file] [log] [blame]
rsc24c02862005-01-04 21:23:50 +00001#include <u.h>
2#include <libc.h>
3#include <draw.h>
rsc05a4d852007-03-26 20:55:26 +00004#include <thread.h>
rsc24c02862005-01-04 21:23:50 +00005#include <bio.h>
rsc05a4d852007-03-26 20:55:26 +00006#include <cursor.h>
rsc24c02862005-01-04 21:23:50 +00007#include "page.h"
8
9int resizing;
10int mknewwindow;
11int doabort;
12int chatty;
13int reverse = -1;
14int goodps = 1;
15int ppi = 100;
16int teegs = 0;
17int truetoboundingbox;
18int textbits=4, gfxbits=4;
rsc24c02862005-01-04 21:23:50 +000019int stdinfd;
20int truecolor;
21int imagemode;
rsc05a4d852007-03-26 20:55:26 +000022int notewatcher;
23int notegp;
24
25int
26watcher(void *v, char *x)
27{
28 USED(v);
29 if(strcmp(x, "die") != 0)
30 postnote(PNGROUP, notegp, x);
31 threadexitsall(0);
32 return 0;
33}
34
rsc5cd829d2007-04-03 12:50:49 +000035void
36watcherproc(void *v)
37{
38 threadnotify(watcher, 1);
39 for(;;)
40 sleep(1000);
41}
42
rsc05a4d852007-03-26 20:55:26 +000043int
44bell(void *u, char *x)
45{
46 if(x && strcmp(x, "hangup") == 0)
47 threadexitsall(0);
48
49 if(x && strstr(x, "die") == nil)
50 fprint(2, "postnote %d: %s\n", getpid(), x);
51
52 /* alarms come from the gs monitor */
53 if(x && strstr(x, "alarm")){
54 postnote(PNGROUP, getpid(), "die (gs error)");
55 postnote(PNPROC, notewatcher, "die (gs error)");
56 }
57
58 /* function mentions u so that it's in the stack trace */
59 if((u == nil || u != x) && doabort)
60 abort();
61
62/* fprint(2, "exiting %d\n", getpid()); */
63 wexits("note");
64 return 0;
65}
rsc24c02862005-01-04 21:23:50 +000066
67static int
68afmt(Fmt *fmt)
69{
70 char *s;
71
72 s = va_arg(fmt->args, char*);
73 if(s == nil || s[0] == '\0')
74 return fmtstrcpy(fmt, "");
75 else
76 return fmtprint(fmt, "%#q", s);
77}
78
79void
80usage(void)
81{
82 fprint(2, "usage: page [-biRrw] [-p ppi] file...\n");
rsc05a4d852007-03-26 20:55:26 +000083 wexits("usage");
rsc24c02862005-01-04 21:23:50 +000084}
85
86void
rsc05a4d852007-03-26 20:55:26 +000087threadmain(int argc, char **argv)
rsc24c02862005-01-04 21:23:50 +000088{
89 Document *doc;
90 Biobuf *b;
rsc05a4d852007-03-26 20:55:26 +000091 char *basename = argv[0];
rsc24c02862005-01-04 21:23:50 +000092 enum { Ninput = 16 };
93 uchar buf[Ninput+1];
94 int readstdin;
95
96 ARGBEGIN{
97 /* "temporary" debugging options */
98 case 'P':
99 goodps = 0;
100 break;
101 case 'v':
102 chatty++;
103 break;
104 case 'V':
105 teegs++;
106 break;
107 case 'a':
108 doabort++;
109 break;
110 case 'T':
111 textbits = atoi(EARGF(usage()));
112 gfxbits = atoi(EARGF(usage()));
113 break;
114
115 /* real options */
116 case 'R':
117 resizing = 1;
118 break;
119 case 'r':
120 reverse = 1;
121 break;
122 case 'p':
123 ppi = atoi(EARGF(usage()));
124 break;
125 case 'b':
126 truetoboundingbox = 1;
127 break;
128 case 'w':
rsc05a4d852007-03-26 20:55:26 +0000129 fprint(2, "%s: -w has only the effect of -R X11 systems\n", basename);
rsc24c02862005-01-04 21:23:50 +0000130 resizing = 1;
131 break;
132 case 'i':
133 imagemode = 1;
134 break;
135 default:
136 usage();
137 }ARGEND;
138
rsc05a4d852007-03-26 20:55:26 +0000139 notegp = getpid();
140
rsc5cd829d2007-04-03 12:50:49 +0000141 notewatcher = proccreate(watcherproc, NULL, 1024);
142 if(notewatcher == -1){
143 sysfatal("proccreate");
rsc05a4d852007-03-26 20:55:26 +0000144 threadexitsall(0);
rsc05a4d852007-03-26 20:55:26 +0000145 }
146
rsc24c02862005-01-04 21:23:50 +0000147 rfork(RFNOTEG);
rsc5cd829d2007-04-03 12:50:49 +0000148 threadnotify(bell, 1);
rsc24c02862005-01-04 21:23:50 +0000149
150 readstdin = 0;
151 if(imagemode == 0 && argc == 0){
152 readstdin = 1;
153 stdinfd = dup(0, -1);
154 close(0);
rsc05a4d852007-03-26 20:55:26 +0000155 open("/dev/tty", OREAD);
rsc24c02862005-01-04 21:23:50 +0000156 }
157
158 quotefmtinstall();
159 fmtinstall('a', afmt);
160
161 fmtinstall('R', Rfmt);
162 fmtinstall('P', Pfmt);
rsc05a4d852007-03-26 20:55:26 +0000163 /*
rsc17157e42006-03-20 02:25:59 +0000164 if(mknewwindow)
rsc05a4d852007-03-26 20:55:26 +0000165 newwin(); */
rsc24c02862005-01-04 21:23:50 +0000166
167 if(readstdin){
168 b = nil;
169 if(readn(stdinfd, buf, Ninput) != Ninput){
170 fprint(2, "page: short read reading %s\n", argv[0]);
171 wexits("read");
172 }
173 }else if(argc != 0){
174 if(!(b = Bopen(argv[0], OREAD))) {
175 fprint(2, "page: cannot open \"%s\"\n", argv[0]);
176 wexits("open");
177 }
178
179 if(Bread(b, buf, Ninput) != Ninput) {
180 fprint(2, "page: short read reading %s\n", argv[0]);
181 wexits("read");
182 }
183 }else
184 b = nil;
185
186 buf[Ninput] = '\0';
187 if(imagemode)
188 doc = initgfx(nil, 0, nil, nil, 0);
189 else if(strncmp((char*)buf, "%PDF-", 5) == 0)
190 doc = initpdf(b, argc, argv, buf, Ninput);
191 else if(strncmp((char*)buf, "\x04%!", 2) == 0)
192 doc = initps(b, argc, argv, buf, Ninput);
193 else if(buf[0] == '\x1B' && strstr((char*)buf, "@PJL"))
194 doc = initps(b, argc, argv, buf, Ninput);
195 else if(strncmp((char*)buf, "%!", 2) == 0)
196 doc = initps(b, argc, argv, buf, Ninput);
197 else if(strcmp((char*)buf, "\xF7\x02\x01\x83\x92\xC0\x1C;") == 0)
198 doc = initdvi(b, argc, argv, buf, Ninput);
199 else if(strncmp((char*)buf, "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1", 8) == 0)
200 doc = initmsdoc(b, argc, argv, buf, Ninput);
201 else if(strncmp((char*)buf, "x T ", 4) == 0)
202 doc = inittroff(b, argc, argv, buf, Ninput);
203 else {
204 if(ppi != 100) {
205 fprint(2, "page: you can't specify -p with graphic files\n");
206 wexits("-p and graphics");
207 }
208 doc = initgfx(b, argc, argv, buf, Ninput);
209 }
210
211 if(doc == nil) {
212 fprint(2, "page: error reading file: %r\n");
213 wexits("document init");
214 }
215
216 if(doc->npage < 1 && !imagemode) {
217 fprint(2, "page: no pages found?\n");
218 wexits("pagecount");
219 }
220
221 if(reverse == -1) /* neither cmdline nor ps reader set it */
222 reverse = 0;
223
224 if(initdraw(0, 0, "page") < 0){
225 fprint(2, "page: initdraw failed: %r\n");
226 wexits("initdraw");
227 }
228 truecolor = screen->depth > 8;
229 viewer(doc);
230 wexits(0);
231}
232
233void
234wexits(char *s)
235{
rsc05a4d852007-03-26 20:55:26 +0000236 if(s && *s && strcmp(s, "note") != 0 && mknewwindow)
237 sleep(10*1000);
238 postnote(PNPROC, notewatcher, "die");
239 postnote(PNGROUP, getpid(), "die");
240 threadexitsall(s);
rsc24c02862005-01-04 21:23:50 +0000241}