page.c 4.3 KB

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