xref: /plan9/sys/src/cmd/page/page.c (revision 14cc0f535177405a84c5b73603a98e5db6674719)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <event.h>
5 #include <bio.h>
6 #include "page.h"
7 
8 int resizing;
9 int mknewwindow;
10 int doabort;
11 int chatty;
12 int reverse = -1;
13 int goodps = 1;
14 int ppi = 100;
15 int teegs = 0;
16 int truetoboundingbox;
17 int textbits=4, gfxbits=4;
18 int wctlfd = -1;
19 int stdinfd;
20 int truecolor;
21 int imagemode;
22 int notewatcher;
23 int notegp;
24 
25 int
watcher(void *,char * x)26 watcher(void*, char *x)
27 {
28 	if(strcmp(x, "die") != 0)
29 		postnote(PNGROUP, notegp, x);
30 	_exits(0);
31 	return 0;
32 }
33 
34 int
bell(void * u,char * x)35 bell(void *u, char *x)
36 {
37 	if(x && strcmp(x, "hangup") == 0)
38 		_exits(0);
39 
40 	if(x && strstr(x, "die") == nil)
41 		fprint(2, "postnote %d: %s\n", getpid(), x);
42 
43 	/* alarms come from the gs monitor */
44 	if(x && strstr(x, "alarm")){
45 		postnote(PNGROUP, getpid(), "die (gs error)");
46 		postnote(PNPROC, notewatcher, "die (gs error)");
47 	}
48 
49 	/* function mentions u so that it's in the stack trace */
50 	if((u == nil || u != x) && doabort)
51 		abort();
52 
53 /*	fprint(2, "exiting %d\n", getpid()); */
54 	wexits("note");
55 	return 0;
56 }
57 
58 static int
afmt(Fmt * fmt)59 afmt(Fmt *fmt)
60 {
61 	char *s;
62 
63 	s = va_arg(fmt->args, char*);
64 	if(s == nil || s[0] == '\0')
65 		return fmtstrcpy(fmt, "");
66 	else
67 		return fmtprint(fmt, "%#q", s);
68 }
69 
70 void
usage(void)71 usage(void)
72 {
73 	fprint(2, "usage: page [-biRrw] [-p ppi] file...\n");
74 	exits("usage");
75 }
76 
77 void
main(int argc,char ** argv)78 main(int argc, char **argv)
79 {
80 	Document *doc;
81 	Biobuf *b;
82 	enum { Ninput = 16 };
83 	uchar buf[Ninput+1];
84 	int readstdin;
85 
86 	ARGBEGIN{
87 	/* "temporary" debugging options */
88 	case 'P':
89 		goodps = 0;
90 		break;
91 	case 'v':
92 		chatty++;
93 		break;
94 	case 'V':
95 		teegs++;
96 		break;
97 	case 'a':
98 		doabort++;
99 		break;
100 	case 'T':
101 		textbits = atoi(EARGF(usage()));
102 		gfxbits = atoi(EARGF(usage()));
103 		break;
104 
105 	/* real options */
106 	case 'R':
107 		resizing = 1;
108 		break;
109 	case 'r':
110 		reverse = 1;
111 		break;
112 	case 'p':
113 		ppi = atoi(EARGF(usage()));
114 		break;
115 	case 'b':
116 		truetoboundingbox = 1;
117 		break;
118 	case 'w':
119 		mknewwindow = 1;
120 		resizing = 1;
121 		break;
122 	case 'i':
123 		imagemode = 1;
124 		break;
125 	default:
126 		usage();
127 	}ARGEND;
128 
129 	notegp = getpid();
130 
131 	switch(notewatcher = fork()){
132 	case -1:
133 		sysfatal("fork");
134 		exits(0);
135 	default:
136 		break;
137 	case 0:
138 		atnotify(watcher, 1);
139 		for(;;)
140 			sleep(1000);
141 		/* not reached */
142 	}
143 
144 	rfork(RFNOTEG);
145 	atnotify(bell, 1);
146 
147 	readstdin = 0;
148 	if(imagemode == 0 && argc == 0){
149 		readstdin = 1;
150 		stdinfd = dup(0, -1);
151 		close(0);
152 		open("/dev/cons", OREAD);
153 	}
154 
155 	quotefmtinstall();
156 	fmtinstall('a', afmt);
157 
158 	fmtinstall('R', Rfmt);
159 	fmtinstall('P', Pfmt);
160 	if(mknewwindow)
161 		newwin();
162 
163 	if(readstdin){
164 		b = nil;
165 		if(readn(stdinfd, buf, Ninput) != Ninput){
166 			fprint(2, "page: short read reading %s\n", argv[0]);
167 			wexits("read");
168 		}
169 	}else if(argc != 0){
170 		if(!(b = Bopen(argv[0], OREAD))) {
171 			fprint(2, "page: cannot open \"%s\"\n", argv[0]);
172 			wexits("open");
173 		}
174 
175 		if(Bread(b, buf, Ninput) != Ninput) {
176 			fprint(2, "page: short read reading %s\n", argv[0]);
177 			wexits("read");
178 		}
179 	}else
180 		b = nil;
181 
182 	buf[Ninput] = '\0';
183 	if(imagemode)
184 		doc = initgfx(nil, 0, nil, nil, 0);
185 	else if(strncmp((char*)buf, "%PDF-", 5) == 0)
186 		doc = initpdf(b, argc, argv, buf, Ninput);
187 	else if(strncmp((char*)buf, "\x04%!", 2) == 0)
188 		doc = initps(b, argc, argv, buf, Ninput);
189 	else if(buf[0] == '\x1B' && strstr((char*)buf, "@PJL"))
190 		doc = initps(b, argc, argv, buf, Ninput);
191 	else if(strncmp((char*)buf, "%!", 2) == 0)
192 		doc = initps(b, argc, argv, buf, Ninput);
193 	else if(strcmp((char*)buf, "\xF7\x02\x01\x83\x92\xC0\x1C;") == 0)
194 		doc = initdvi(b, argc, argv, buf, Ninput);
195 	else if(strncmp((char*)buf, "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1", 8) == 0)
196 		doc = initmsdoc(b, argc, argv, buf, Ninput);
197 	else if(strncmp((char*)buf, "x T ", 4) == 0)
198 		doc = inittroff(b, argc, argv, buf, Ninput);
199 	else {
200 		if(ppi != 100) {
201 			fprint(2, "page: you can't specify -p with graphic files\n");
202 			wexits("-p and graphics");
203 		}
204 		doc = initgfx(b, argc, argv, buf, Ninput);
205 	}
206 
207 	if(doc == nil) {
208 		fprint(2, "page: error reading file: %r\n");
209 		wexits("document init");
210 	}
211 
212 	if(doc->npage < 1 && !imagemode) {
213 		fprint(2, "page: no pages found?\n");
214 		wexits("pagecount");
215 	}
216 
217 	if(reverse == -1) /* neither cmdline nor ps reader set it */
218 		reverse = 0;
219 
220 	if(initdraw(0, 0, "page") < 0){
221 		fprint(2, "page: initdraw failed: %r\n");
222 		wexits("initdraw");
223 	}
224 	display->locking = 1;
225 
226 	truecolor = screen->depth > 8;
227 	viewer(doc);
228 	wexits(0);
229 }
230 
231 void
wexits(char * s)232 wexits(char *s)
233 {
234 	if(s && *s && strcmp(s, "note") != 0 && mknewwindow)
235 		sleep(10*1000);
236 	postnote(PNPROC, notewatcher, "die");
237 	exits(s);
238 }
239