xref: /plan9/sys/src/cmd/page/page.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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 newwindow;
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
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
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 void
59 main(int argc, char **argv)
60 {
61 	Document *doc;
62 	Biobuf *b;
63 	enum { Ninput = 16 };
64 	uchar buf[Ninput+1];
65 	int readstdin;
66 
67 	ARGBEGIN{
68 	/* "temporary" debugging options */
69 	case 'P':
70 		goodps = 0;
71 		break;
72 	case 'v':
73 		chatty++;
74 		break;
75 	case 'V':
76 		teegs++;
77 		break;
78 	case 'a':
79 		doabort++;
80 		break;
81 
82 	/* real options */
83 	case 'R':
84 		resizing = 1;
85 		break;
86 	case 'r':
87 		reverse = 1;
88 		break;
89 	case 'p':
90 		ppi = atoi(ARGF());
91 		break;
92 	case 'b':
93 		truetoboundingbox = 1;
94 		break;
95 	case 'w':
96 		newwindow = 1;
97 		resizing = 1;
98 		break;
99 	case 'i':
100 		imagemode = 1;
101 		break;
102 	default:
103 		fprint(2, "usage: page file...\n");
104 		wexits("usage");
105 	}ARGEND;
106 
107 	notegp = getpid();
108 
109 	switch(notewatcher = fork()){
110 	case -1:
111 		sysfatal("fork\n");
112 		exits(0);
113 	default:
114 		break;
115 	case 0:
116 		atnotify(watcher, 1);
117 		for(;;)
118 			sleep(1000);
119 		_exits(0);
120 	}
121 
122 	rfork(RFNOTEG);
123 	atnotify(bell, 1);
124 
125 	readstdin = 0;
126 	if(imagemode == 0 && argc == 0){
127 		readstdin = 1;
128 		stdinfd = dup(0, -1);
129 		close(0);
130 		open("/dev/cons", OREAD);
131 	}
132 
133 	fmtinstall('R', Rfmt);
134 	fmtinstall('P', Pfmt);
135 	if(newwindow)
136 		newwin();
137 
138 	if(readstdin){
139 		b = nil;
140 		if(readn(stdinfd, buf, Ninput) != Ninput){
141 			fprint(2, "page: short read reading %s\n", argv[0]);
142 			wexits("read");
143 		}
144 	}else if(argc != 0){
145 		if(!(b = Bopen(argv[0], OREAD))) {
146 			fprint(2, "page: cannot open \"%s\"\n", argv[0]);
147 			wexits("open");
148 		}
149 
150 		if(Bread(b, buf, Ninput) != Ninput) {
151 			fprint(2, "page: short read reading %s\n", argv[0]);
152 			wexits("read");
153 		}
154 	}else
155 		b = nil;
156 
157 	buf[Ninput] = '\0';
158 	if(imagemode)
159 		doc = initgfx(nil, 0, nil, nil, 0);
160 	else if(strncmp((char*)buf, "%PDF-", 5) == 0)
161 		doc = initpdf(b, argc, argv, buf, Ninput);
162 	else if(strncmp((char*)buf, "\x04%!", 2) == 0)
163 		doc = initps(b, argc, argv, buf, Ninput);
164 	else if(buf[0] == '\x1B' && strstr((char*)buf, "@PJL"))
165 		doc = initps(b, argc, argv, buf, Ninput);
166 	else if(strncmp((char*)buf, "%!", 2) == 0)
167 		doc = initps(b, argc, argv, buf, Ninput);
168 	else if(strcmp((char*)buf, "\xF7\x02\x01\x83\x92\xC0\x1C;") == 0)
169 		doc = initdvi(b, argc, argv, buf, Ninput);
170 	else if(strncmp((char*)buf, "x T ", 4) == 0)
171 		doc = inittroff(b, argc, argv, buf, Ninput);
172 	else {
173 		if(ppi != 100) {
174 			fprint(2, "page: you can't specify -p with graphic files\n");
175 			wexits("-p and graphics");
176 		}
177 		doc = initgfx(b, argc, argv, buf, Ninput);
178 	}
179 
180 	if(doc == nil) {
181 		fprint(2, "page: error reading file: %r\n");
182 		wexits("document init");
183 	}
184 
185 	if(doc->npage < 1 && !imagemode) {
186 		fprint(2, "page: no pages found?\n");
187 		wexits("pagecount");
188 	}
189 
190 	if(reverse == -1) /* neither cmdline nor ps reader set it */
191 		reverse = 0;
192 
193 	if(initdraw(0, 0, "page") < 0){
194 		fprint(2, "page: initdraw failed: %r\n");
195 		wexits("initdraw");
196 	}
197 	truecolor = screen->depth > 8;
198 	viewer(doc);
199 	wexits(0);
200 }
201 
202 void
203 wexits(char *s)
204 {
205 	if(s && *s && strcmp(s, "note") != 0 && newwindow)
206 		sleep(10*1000);
207 	postnote(PNPROC, notewatcher, "die");
208 	exits(s);
209 }
210