| #include <u.h> |
| #include <libc.h> |
| #include <draw.h> |
| #include <event.h> |
| #include <bio.h> |
| #include "page.h" |
| |
| int resizing; |
| int mknewwindow; |
| int doabort; |
| int chatty; |
| int reverse = -1; |
| int goodps = 1; |
| int ppi = 100; |
| int teegs = 0; |
| int truetoboundingbox; |
| int textbits=4, gfxbits=4; |
| int wctlfd = -1; |
| int stdinfd; |
| int truecolor; |
| int imagemode; |
| int notewatcher; |
| int notegp; |
| |
| int |
| watcher(void *v, char *x) |
| { |
| USED(v); |
| |
| if(strcmp(x, "die") != 0) |
| postnote(PNGROUP, notegp, x); |
| _exits(0); |
| return 0; |
| } |
| |
| int |
| bell(void *u, char *x) |
| { |
| if(x && strcmp(x, "hangup") == 0) |
| _exits(0); |
| |
| if(x && strstr(x, "die") == nil) |
| fprint(2, "postnote %d: %s\n", getpid(), x); |
| |
| /* alarms come from the gs monitor */ |
| if(x && strstr(x, "alarm")){ |
| postnote(PNGROUP, getpid(), "die (gs error)"); |
| postnote(PNPROC, notewatcher, "die (gs error)"); |
| } |
| |
| /* function mentions u so that it's in the stack trace */ |
| if((u == nil || u != x) && doabort) |
| abort(); |
| |
| /* fprint(2, "exiting %d\n", getpid()); */ |
| wexits("note"); |
| return 0; |
| } |
| |
| static int |
| afmt(Fmt *fmt) |
| { |
| char *s; |
| |
| s = va_arg(fmt->args, char*); |
| if(s == nil || s[0] == '\0') |
| return fmtstrcpy(fmt, ""); |
| else |
| return fmtprint(fmt, "%#q", s); |
| } |
| |
| void |
| usage(void) |
| { |
| fprint(2, "usage: page [-biRrw] [-p ppi] file...\n"); |
| exits("usage"); |
| } |
| |
| void |
| main(int argc, char **argv) |
| { |
| Document *doc; |
| Biobuf *b; |
| enum { Ninput = 16 }; |
| uchar buf[Ninput+1]; |
| int readstdin; |
| |
| ARGBEGIN{ |
| /* "temporary" debugging options */ |
| case 'P': |
| goodps = 0; |
| break; |
| case 'v': |
| chatty++; |
| break; |
| case 'V': |
| teegs++; |
| break; |
| case 'a': |
| doabort++; |
| break; |
| case 'T': |
| textbits = atoi(EARGF(usage())); |
| gfxbits = atoi(EARGF(usage())); |
| break; |
| |
| /* real options */ |
| case 'R': |
| resizing = 1; |
| break; |
| case 'r': |
| reverse = 1; |
| break; |
| case 'p': |
| ppi = atoi(EARGF(usage())); |
| break; |
| case 'b': |
| truetoboundingbox = 1; |
| break; |
| case 'w': |
| mknewwindow = 1; |
| resizing = 1; |
| break; |
| case 'i': |
| imagemode = 1; |
| break; |
| default: |
| usage(); |
| }ARGEND; |
| |
| notegp = getpid(); |
| |
| switch(notewatcher = fork()){ |
| case -1: |
| sysfatal("fork\n"); |
| exits(0); |
| default: |
| break; |
| case 0: |
| atnotify(watcher, 1); |
| for(;;) |
| sleep(1000); |
| _exits(0); |
| } |
| |
| rfork(RFNOTEG); |
| atnotify(bell, 1); |
| |
| readstdin = 0; |
| if(imagemode == 0 && argc == 0){ |
| readstdin = 1; |
| stdinfd = dup(0, -1); |
| close(0); |
| open("/dev/cons", OREAD); |
| } |
| |
| quotefmtinstall(); |
| fmtinstall('a', afmt); |
| |
| fmtinstall('R', Rfmt); |
| fmtinstall('P', Pfmt); |
| |
| if(readstdin){ |
| b = nil; |
| if(readn(stdinfd, buf, Ninput) != Ninput){ |
| fprint(2, "page: short read reading %s\n", argv[0]); |
| wexits("read"); |
| } |
| }else if(argc != 0){ |
| if(!(b = Bopen(argv[0], OREAD))) { |
| fprint(2, "page: cannot open \"%s\"\n", argv[0]); |
| wexits("open"); |
| } |
| |
| if(Bread(b, buf, Ninput) != Ninput) { |
| fprint(2, "page: short read reading %s\n", argv[0]); |
| wexits("read"); |
| } |
| }else |
| b = nil; |
| |
| buf[Ninput] = '\0'; |
| if(imagemode) |
| doc = initgfx(nil, 0, nil, nil, 0); |
| else if(strncmp((char*)buf, "%PDF-", 5) == 0) |
| doc = initpdf(b, argc, argv, buf, Ninput); |
| else if(strncmp((char*)buf, "\x04%!", 2) == 0) |
| doc = initps(b, argc, argv, buf, Ninput); |
| else if(buf[0] == '\x1B' && strstr((char*)buf, "@PJL")) |
| doc = initps(b, argc, argv, buf, Ninput); |
| else if(strncmp((char*)buf, "%!", 2) == 0) |
| doc = initps(b, argc, argv, buf, Ninput); |
| else if(strcmp((char*)buf, "\xF7\x02\x01\x83\x92\xC0\x1C;") == 0) |
| doc = initdvi(b, argc, argv, buf, Ninput); |
| else if(strncmp((char*)buf, "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1", 8) == 0) |
| doc = initmsdoc(b, argc, argv, buf, Ninput); |
| else if(strncmp((char*)buf, "x T ", 4) == 0) |
| doc = inittroff(b, argc, argv, buf, Ninput); |
| else { |
| if(ppi != 100) { |
| fprint(2, "page: you can't specify -p with graphic files\n"); |
| wexits("-p and graphics"); |
| } |
| doc = initgfx(b, argc, argv, buf, Ninput); |
| } |
| |
| if(doc == nil) { |
| fprint(2, "page: error reading file: %r\n"); |
| wexits("document init"); |
| } |
| |
| if(doc->npage < 1 && !imagemode) { |
| fprint(2, "page: no pages found?\n"); |
| wexits("pagecount"); |
| } |
| |
| if(reverse == -1) /* neither cmdline nor ps reader set it */ |
| reverse = 0; |
| |
| if(initdraw(0, 0, "page") < 0){ |
| fprint(2, "page: initdraw failed: %r\n"); |
| wexits("initdraw"); |
| } |
| truecolor = screen->depth > 8; |
| viewer(doc); |
| wexits(0); |
| } |
| |
| void |
| wexits(char *s) |
| { |
| if(s && *s && strcmp(s, "note") != 0 && mknewwindow) |
| sleep(10*1000); |
| postnote(PNPROC, notewatcher, "die"); |
| exits(s); |
| } |