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