commit 05a4d855f167ae2d0d2c0ba0e386d933172b71ea from: rsc date: Mon Mar 26 20:55:26 2007 UTC add page (Kris Maglione) commit - 6c4c5c5b959ec8a2e85510bdf85339582f638f36 commit + 05a4d855f167ae2d0d2c0ba0e386d933172b71ea blob - a09de6689b2fdbbfe8bafef92e8889acb6123aee blob + befccc32b975c549bda6627a4a2355012d6133a4 --- src/cmd/mkfile +++ src/cmd/mkfile @@ -4,7 +4,7 @@ TARG=`ls *.[cy] *.lx | egrep -v "\.tab\.c$|^x\." | sed <$PLAN9/src/mkmany -BUGGERED='CVS|faces|factotum|lp|ip|mailfs|page|scat|upas|vncv|mnihongo|mpm|index|u9fs|secstore' +BUGGERED='CVS|faces|factotum|lp|ip|mailfs|scat|upas|vncv|mnihongo|mpm|index|u9fs|secstore' DIRS=lex `ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"|egrep -v '^lex$'` <$PLAN9/src/mkdirs blob - 319cfb68f62fdea12f42676ebe57bd7a5d1beafd blob + 415db0384e2ff80873e5f4c6adc26cdeb50d87f7 --- src/cmd/page/filter.c +++ src/cmd/page/filter.c @@ -1,9 +1,9 @@ #include #include #include -#include -#include +#include #include +#include #include "page.h" Document* @@ -24,7 +24,7 @@ initfilt(Biobuf *b, int argc, char **argv, uchar *buf, if(docopy){ if(pipe(p) < 0){ fprint(2, "pipe fails: %r\n"); - exits("Epipe"); + threadexits("Epipe"); } }else{ p[0] = open("/dev/null", ORDWR); @@ -35,27 +35,29 @@ initfilt(Biobuf *b, int argc, char **argv, uchar *buf, switch(fork()){ case -1: fprint(2, "fork fails: %r\n"); - exits("Efork"); + threadexits("Efork"); default: - close(p[1]); + close(p[0]); if(docopy){ - write(p[0], buf, nbuf); + write(p[1], buf, nbuf); if(b) while((n = Bread(b, xbuf, sizeof xbuf)) > 0) - write(p[0], xbuf, n); + write(p[1], xbuf, n); else while((n = read(stdinfd, xbuf, sizeof xbuf)) > 0) - write(p[0], xbuf, n); + write(p[1], xbuf, n); } - close(p[0]); + close(p[1]); waitpid(); break; case 0: - close(p[0]); - dup(p[1], 0); + close(p[1]); + dup(p[0], 0); dup(ofd, 1); /* stderr shines through */ - execl("/bin/rc", "rc", "-c", cmd, nil); + if(chatty) + fprint(2, "Execing '%s'\n", cmd); + execlp("rc", "rc", "-c", cmd, nil); break; } @@ -81,7 +83,7 @@ initdvi(Biobuf *b, int argc, char **argv, uchar *buf, */ if(b == nil){ /* standard input; spool to disk (ouch) */ fd = spooltodisk(buf, nbuf, &name); - sprint(fdbuf, "/fd/%d", fd); + sprint(fdbuf, "/dev/fd/%d", fd); b = Bopen(fdbuf, OREAD); if(b == nil){ fprint(2, "cannot open disk spool file\n"); blob - 9ce6f74c937fad14f88e4ac7ff44ebff141d0340 blob + e8b40d038c31804c24e0526f25cc48506f06cd7c --- src/cmd/page/gfx.c +++ src/cmd/page/gfx.c @@ -5,14 +5,13 @@ #include #include #include -#include -#include +#include #include +#include #include "page.h" typedef struct Convert Convert; typedef struct GfxInfo GfxInfo; -typedef struct Graphic Graphic; struct Convert { char *name; @@ -24,29 +23,6 @@ struct GfxInfo { Graphic *g; }; -struct Graphic { - int type; - char *name; - uchar *buf; /* if stdin */ - int nbuf; -}; - -enum { - Ipic, - Itiff, - Ijpeg, - Igif, - Iinferno, - Ifax, - Icvt2pic, - Iplan9bm, - Iccittg4, - Ippm, - Ipng, - Iyuv, - Ibmp -}; - /* * N.B. These commands need to read stdin if %a is replaced * with an empty string. @@ -65,15 +41,14 @@ Convert cvt[] = { [Iccittg4] { "ccitt-g4", "cat %a|rx nslocum /usr/lib/ocr/bin/bcp -M|fb/pcp -tcompressed -l0" }, [Ipng] { "png", "png -9 %a", "png -t9 %a" }, [Iyuv] { "yuv", "yuv -9 %a", "yuv -t9 %a" }, -[Ibmp] { "bmp", "bmp -9 %a", "bmp -t9 %a" } +[Ibmp] { "bmp", "bmp -9 %a", "bmp -t9 %a" }, }; -static Image* convert(Graphic*); static Image* gfxdrawpage(Document *d, int page); static char* gfxpagename(Document*, int); -static int spawnrc(char*, uchar*, int); -static void waitrc(void); -static int spawnpost(int); +static int spawnrc(char*, Graphic*); +//static void waitrc(void); +//static int spawnpost(int); static int addpage(Document*, char*); static int rmpage(Document*, int); static int genaddpage(Document*, char*, uchar*, int); @@ -202,12 +177,12 @@ genaddpage(Document *doc, char *name, uchar *buf, int else g->type = Icvt2pic; - if(name) + if(name){ g->name = estrdup(name); - else{ + g->fd = -1; + }else{ g->name = estrdup("stdin"); /* so it can be freed */ - g->buf = buf; - g->nbuf = nbuf; + g->fd = stdinpipe(buf, nbuf); } if(chatty) fprint(2, "classified \"%s\" as \"%s\"\n", g->name, cvt[g->type].name); @@ -244,7 +219,7 @@ rmpage(Document *doc, int n) } -static Image* +Image* convert(Graphic *g) { int fd; @@ -253,25 +228,24 @@ convert(Graphic *g) char *name, buf[1000]; Image *im; int rcspawned = 0; - Waitmsg *w; c = cvt[g->type]; if(c.cmd == nil) { if(chatty) fprint(2, "no conversion for bitmap \"%s\"...\n", g->name); - if(g->buf == nil){ /* not stdin */ + if(g->fd < 0){ /* not stdin */ fd = open(g->name, OREAD); if(fd < 0) { fprint(2, "cannot open file: %r\n"); wexits("open"); } }else - fd = stdinpipe(g->buf, g->nbuf); + fd = g->fd; } else { cmd = c.cmd; if(truecolor && c.truecmd) cmd = c.truecmd; - if(g->buf != nil) /* is stdin */ + if(g->fd >= 0) /* is pipe */ name = ""; else name = g->name; @@ -281,7 +255,7 @@ convert(Graphic *g) } snprint(buf, sizeof buf, cmd, name); if(chatty) fprint(2, "using \"%s\" to convert \"%s\"...\n", buf, g->name); - fd = spawnrc(buf, g->buf, g->nbuf); + fd = spawnrc(buf, g); rcspawned++; if(fd < 0) { fprint(2, "cannot spawn converter: %r\n"); @@ -293,43 +267,31 @@ convert(Graphic *g) if(im == nil) { fprint(2, "warning: couldn't read image: %r\n"); } - close(fd); - /* for some reason rx doesn't work well with wait */ - /* for some reason 3to1 exits on success with a non-null status of |3to1 */ - if(rcspawned && g->type != Iccittg4) { - if((w=wait())!=nil && w->msg[0] && !strstr(w->msg, "3to1")) - fprint(2, "slave wait error: %s\n", w->msg); - free(w); - } + close(fd); return im; } static int -spawnrc(char *cmd, uchar *stdinbuf, int nstdinbuf) +spawnrc(char *cmd, Graphic *g) { int pfd[2]; - int pid; + int fd[3]; if(chatty) fprint(2, "spawning(%s)...", cmd); if(pipe(pfd) < 0) return -1; - if((pid = fork()) < 0) + + if(g->fd > 0) + fd[0] = dup(g->fd, -1); + else + fd[0] = open("/dev/null", OREAD); + fd[1] = pfd[1]; + fd[2] = dup(2, -1); + + if(threadspawnl(fd, "rc", "rc", "-c", cmd, nil) == -1) return -1; - if(pid == 0) { - close(pfd[1]); - if(stdinbuf) - dup(stdinpipe(stdinbuf, nstdinbuf), 0); - else - dup(open("/dev/null", OREAD), 0); - dup(pfd[0], 1); - /*dup(pfd[0], 2); */ - execl("/bin/rc", "rc", "-c", cmd, nil); - wexits("exec"); - } - close(pfd[0]); - return pfd[1]; + return pfd[0]; } - blob - fd7337ec81d64f42f4c1ad3ebbc1574ab0d3aab0 blob + 8c0e1b59f6ec29847f7c7bdb404029c5064ebf9f --- src/cmd/page/gs.c +++ src/cmd/page/gs.c @@ -7,9 +7,9 @@ #include #include #include -#include -#include +#include #include +#include #include "page.h" static int gspid; /* globals for atexit */ @@ -37,87 +37,41 @@ killgs(void) postnote(PNPROC, gspid, "die yankee pig dog"); } -int -spawnwriter(GSInfo *g, Biobuf *b) +void +spawnreader(void *cp) { - char buf[4096]; - int n; - int fd; + int n, fd, pfd[2]; + char buf[1024]; - switch(fork()){ - case -1: return -1; - case 0: break; - default: return 0; - } + recv(cp, &fd); - Bseek(b, 0, 0); - fd = g->gsfd; - while((n = Bread(b, buf, sizeof buf)) > 0) - write(fd, buf, n); - fprint(fd, "(/fd/3) (w) file dup (THIS IS NOT AN INFERNO BITMAP\\n) writestring flushfile\n"); - _exits(0); - return -1; -} + if(pipe(pfd)<0) + wexits("pipe failed"); -int -spawnreader(int fd) -{ - int n, pfd[2]; - char buf[1024]; + send(cp, &pfd[1]); - if(pipe(pfd)<0) - return -1; - switch(fork()){ - case -1: - return -1; - case 0: - break; - default: - close(pfd[0]); - return pfd[1]; + while((n=read(pfd[0], buf, sizeof buf)) > 0) { + write(1, buf, n); + write(fd, buf, n); } - close(pfd[1]); - switch(fork()){ - case -1: - wexits("fork failed"); - case 0: - while((n=read(fd, buf, sizeof buf)) > 0) { - write(1, buf, n); - write(pfd[0], buf, n); - } - break; - default: - while((n=read(pfd[0], buf, sizeof buf)) > 0) { - write(1, buf, n); - write(fd, buf, n); - } - break; - } - postnote(PNGROUP, getpid(), "i'm die-ing"); - _exits(0); - return -1; + close(pfd[0]); + threadexits(0); } void -spawnmonitor(int fd) +spawnmonitor(void *cp) { char buf[4096]; char *xbuf; + int fd; int n; int out; int first; - switch(rfork(RFFDG|RFNOTEG|RFPROC)){ - case -1: - default: - return; + recv(cp, &fd); - case 0: - break; - } - - out = open("/dev/cons", OWRITE); + out = open("/dev/tty", OWRITE); if(out < 0) out = 2; @@ -131,17 +85,19 @@ spawnmonitor(int fd) write(out, xbuf, n); alarm(500); } - _exits(0); + threadexits(0); } int spawngs(GSInfo *g, char *safer) { + Channel *cp; char *args[16]; char tb[32], gb[32]; int i, nargs; int devnull; - int stdinout[2]; + int stdinp[2]; + int stdoutp[2]; int dataout[2]; int errout[2]; @@ -153,15 +109,15 @@ spawngs(GSInfo *g, char *safer) * gs output written to fd 1 (i.e. ouptut gs generates on error) is fed to errout. * gs data output is written to fd 3, which is dataout. */ - if(pipe(stdinout) < 0 || pipe(dataout)<0 || pipe(errout)<0) + if(pipe(stdinp)<0 || pipe(stdoutp)<0 || pipe(dataout)<0 || pipe(errout)<0) return -1; nargs = 0; args[nargs++] = "gs"; args[nargs++] = "-dNOPAUSE"; - args[nargs++] = safer; - args[nargs++] = "-sDEVICE=plan9"; - args[nargs++] = "-sOutputFile=/fd/3"; + args[nargs++] = "-dDELAYSAFER"; + args[nargs++] = "-sDEVICE=bmp16m"; + args[nargs++] = "-sOutputFile=/dev/fd/3"; args[nargs++] = "-dQUIET"; args[nargs++] = "-r100"; sprint(tb, "-dTextAlphaBits=%d", textbits); @@ -175,9 +131,10 @@ spawngs(GSInfo *g, char *safer) gspid = fork(); if(gspid == 0) { - close(stdinout[1]); - close(dataout[1]); - close(errout[1]); + close(stdinp[1]); + close(stdoutp[0]); + close(dataout[0]); + close(errout[0]); /* * Horrible problem: we want to dup fd's 0-4 below, @@ -189,36 +146,49 @@ spawngs(GSInfo *g, char *safer) while((devnull = open("/dev/null", ORDWR)) < 5) ; - stdinout[0] = dup(stdinout[0], -1); - errout[0] = dup(errout[0], -1); - dataout[0] = dup(dataout[0], -1); + stdinp[0] = dup(stdinp[0], -1); + stdoutp[1] = dup(stdoutp[1], -1); + errout[1] = dup(errout[1], -1); + dataout[1] = dup(dataout[1], -1); - dup(stdinout[0], 0); - dup(errout[0], 1); - dup(devnull, 2); /* never anything useful */ - dup(dataout[0], 3); - dup(stdinout[0], 4); + dup(stdinp[0], 0); + dup(errout[1], 1); + dup(errout[1], devnull); /* never anything useful */ + dup(dataout[1], 3); + dup(stdoutp[1], 4); for(i=5; i<20; i++) close(i); - exec("/bin/gs", args); + execvp("gs", args); wexits("exec"); } - close(stdinout[0]); - close(errout[0]); - close(dataout[0]); + close(stdinp[0]); + close(stdoutp[1]); + close(errout[1]); + close(dataout[1]); atexit(killgs); - if(teegs) - stdinout[1] = spawnreader(stdinout[1]); + cp = chancreate(sizeof(int), 0); + if(teegs) { + proccreate(spawnreader, cp, mainstacksize); + send(cp, &stdoutp[0]); + recv(cp, &stdoutp[0]); + } - gsfd = g->gsfd = stdinout[1]; - g->gsdfd = dataout[1]; + gsfd = g->gsfd = stdinp[1]; g->gspid = gspid; + g->g.fd = dataout[0]; + g->g.name = "gs pipe"; + g->g.type = Ibmp; - spawnmonitor(errout[1]); - Binit(&g->gsrd, g->gsfd, OREAD); + proccreate(spawnmonitor, cp, mainstacksize); + send(cp, &errout[0]); + chanfree(cp); - gscmd(g, "/PAGEOUT (/fd/4) (w) file def\n"); + Binit(&g->gsrd, stdoutp[0], OREAD); + + gscmd(g, "/PAGEOUT (/dev/fd/4) (w) file def\n"); + if(!strcmp(safer, "-dSAFER")) + gscmd(g, ".setsafe\n"); gscmd(g, "/PAGE== { PAGEOUT exch write==only PAGEOUT (\\n) writestring PAGEOUT flushfile } def\n"); waitgs(g); @@ -269,11 +239,14 @@ setdim(GSInfo *gs, Rectangle bbox, int ppi, int landsc if(!Dx(bbox)) bbox = Rect(0, 0, 612, 792); /* 8½×11 */ - if(landscape) - pbox = Rect(bbox.min.y, bbox.min.x, bbox.max.y, bbox.max.x); - else + switch(landscape){ + case 0: pbox = bbox; - + break; + default: + pbox = Rect(bbox.min.y, bbox.min.x, bbox.max.y, bbox.max.x); + break; + } gscmd(gs, "/PageSize [%d %d]\n", Dx(pbox), Dy(pbox)); gscmd(gs, "/Margins [%d %d]\n", -pbox.min.x, -pbox.min.y); gscmd(gs, "currentdevice putdeviceprops pop\n"); @@ -305,10 +278,10 @@ waitgs(GSInfo *gs) uchar buf[1024]; int n; -/* gscmd(gs, "(\\n**bstack\\n) print flush\n"); */ -/* gscmd(gs, "stack flush\n"); */ -/* gscmd(gs, "(**estack\\n) print flush\n"); */ - gscmd(gs, "(\\n/*GO.SYSIN DD\\n) PAGE==\n"); */ +// gscmd(gs, "(\\n**bstack\\n) print flush\n"); +// gscmd(gs, "stack flush\n"); +// gscmd(gs, "(**estack\\n) print flush\n"); + gscmd(gs, "(\\n//GO.SYSIN DD\\n) PAGE==\n"); alarm(300*1000); for(;;) { blob - 0c4163ad001791e7c0c595976ad14d494efba6ee blob + bcd02a8d2d57461d16e1cbc424fc2daf2d295b4c --- src/cmd/page/mkfile +++ src/cmd/page/mkfile @@ -14,8 +14,18 @@ OFILES=\ util.$O\ view.$O\ +LIB=$PLAN9/lib/libdraw.a + +UPDATE=\ + mkfile\ + ${OFILES:%.$O=%.c}\ + pdfprolog.ps\ + $HFILES\ + <$PLAN9/src/mkone +BIN=$PLAN9/bin + pdfprolog.c: pdfprolog.ps cat pdfprolog.ps | sed 's/.*/"&\\n"/g' >pdfprolog.c blob - 9f6816e23f6b7c9e18521d8f422ca0550aec3c67 blob + 96563c3d1663fb7ff179681f39344fa4df6c8533 --- src/cmd/page/nrotate.c +++ src/cmd/page/nrotate.c @@ -15,15 +15,15 @@ #include #include #include +#include #include -#include #include "page.h" int ndraw = 0; enum { Xaxis, - Yaxis + Yaxis, }; static void reverse(Image*, Image*, int); @@ -229,7 +229,7 @@ swapadjacent(Image *img, Image *tmp, int axis, int img /* * r0 is the lower rectangle, while r1 is the upper one. */ - draw(tmp, tmp->r, img, nil + draw(tmp, tmp->r, img, nil, } void blob - 4c76e03316c0139b1aba8da82a50ec685504238b blob + 52c6eee3599bb5e6a246a68912d29b4cc12f9b22 --- src/cmd/page/page.c +++ src/cmd/page/page.c @@ -1,9 +1,10 @@ #include #include #include -#include -#include +#include +#include #include +#include #include "page.h" int resizing; @@ -16,11 +17,46 @@ 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); + threadexitsall(0); + return 0; +} + +int +bell(void *u, char *x) +{ + if(x && strcmp(x, "hangup") == 0) + threadexitsall(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) { @@ -37,14 +73,15 @@ void usage(void) { fprint(2, "usage: page [-biRrw] [-p ppi] file...\n"); - exits("usage"); + wexits("usage"); } void -main(int argc, char **argv) +threadmain(int argc, char **argv) { Document *doc; Biobuf *b; + char *basename = argv[0]; enum { Ninput = 16 }; uchar buf[Ninput+1]; int readstdin; @@ -82,7 +119,7 @@ main(int argc, char **argv) truetoboundingbox = 1; break; case 'w': - mknewwindow = 1; + fprint(2, "%s: -w has only the effect of -R X11 systems\n", basename); resizing = 1; break; case 'i': @@ -92,14 +129,30 @@ main(int argc, char **argv) usage(); }ARGEND; + notegp = getpid(); + + switch(notewatcher = fork()){ + case -1: + sysfatal("fork\n"); + threadexitsall(0); + default: + break; + case 0: + atnotify(watcher, 1); + for(;;) + sleep(1000); + /* not reached */ + } + rfork(RFNOTEG); + atnotify(bell, 1); readstdin = 0; if(imagemode == 0 && argc == 0){ readstdin = 1; stdinfd = dup(0, -1); close(0); - open("/dev/cons", OREAD); + open("/dev/tty", OREAD); } quotefmtinstall(); @@ -107,8 +160,9 @@ main(int argc, char **argv) fmtinstall('R', Rfmt); fmtinstall('P', Pfmt); + /* if(mknewwindow) - newwin(); + newwin(); */ if(readstdin){ b = nil; @@ -179,5 +233,9 @@ main(int argc, char **argv) void wexits(char *s) { - exits(s); + if(s && *s && strcmp(s, "note") != 0 && mknewwindow) + sleep(10*1000); + postnote(PNPROC, notewatcher, "die"); + postnote(PNGROUP, getpid(), "die"); + threadexitsall(s); } blob - be54e3867f9c0d88b66cd3e01472f903ec3ae5e0 blob + 7e6c526eb1b4d54353876983c54b5f7846a3d36e --- src/cmd/page/page.h +++ src/cmd/page/page.h @@ -1,3 +1,5 @@ +#undef pipe + typedef struct Document Document; struct Document { @@ -12,6 +14,31 @@ struct Document { void *extra; }; +typedef struct Graphic Graphic; + +struct Graphic { + int type; + int fd; + char *name; +}; + +enum { + Ipic, + Itiff, + Ijpeg, + Igif, + Iinferno, + Ifax, + Icvt2pic, + Iplan9bm, + Iccittg4, + Ippm, + Ipng, + Iyuv, + Ibmp, +}; + + void *emalloc(int); void *erealloc(void*, int); char *estrdup(char*); @@ -48,10 +75,10 @@ Image *resample(Image*, Image*); /* ghostscript interface shared by ps, pdf */ typedef struct GSInfo GSInfo; struct GSInfo { + Graphic g; int gsfd; Biobuf gsrd; int gspid; - int gsdfd; int ppi; }; void waitgs(GSInfo*); @@ -70,6 +97,7 @@ void wexits(char*); Image* xallocimage(Display*, Rectangle, ulong, int, ulong); int bell(void*, char*); int opentemp(char *template); +Image* convert(Graphic *g); extern int stdinfd; extern int truecolor; blob - d723ad8c56800289a78fa0fd45ec93eb39beb98b blob + 77c888522e45175291de991236f3d27d51423c91 --- src/cmd/page/pdf.c +++ src/cmd/page/pdf.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include "page.h" @@ -66,7 +66,7 @@ initpdf(Biobuf *b, int argc, char **argv, uchar *buf, fprint(2, "reading through pdf...\n"); if(b == nil){ /* standard input; spool to disk (ouch) */ fd = spooltodisk(buf, nbuf, &fn); - sprint(fdbuf, "/fd/%d", fd); + sprint(fdbuf, "/dev/fd/%d", fd); b = Bopen(fdbuf, OREAD); if(b == nil){ fprint(2, "cannot open disk spool file\n"); @@ -122,7 +122,7 @@ initpdf(Biobuf *b, int argc, char **argv, uchar *buf, pdf->pagebbox = emalloc(sizeof(Rectangle)*npage); for(i=0; igs, "%d pdfgetpage\n", i+1); - pdf->pagebbox[i] = pdfbbox(pdf); + pdf->pagebbox[i] = pdfbbox(&pdf->gs); if(Dx(pdf->pagebbox[i]) <= 0) pdf->pagebbox[i] = bbox; } @@ -136,7 +136,7 @@ pdfdrawpage(Document *doc, int page) Image *im; gscmd(&pdf->gs, "%d DoPDFPage\n", page+1); - im = readimage(display, pdf->gs.gsdfd, 0); + im = convert(&pdf->gs.g); if(im == nil) { fprint(2, "fatal: readimage error %r\n"); wexits("readimage"); blob - 8493e6d2ad7e09b69d6fef6eb583031b12399402 blob + de51c062ac92faa62e7054789c5833571fd4ea20 --- src/cmd/page/pdfprolog.c +++ src/cmd/page/pdfprolog.c @@ -2,28 +2,19 @@ "/Page# 0 def\n" "/PDFSave null def\n" "/DSCPageCount 0 def\n" -"/DoPDFPage {dup /Page# exch store pdfgetpage mypdfshowpage } def\n" +"/DoPDFPage {dup /Page# exch store pdfgetpage pdfshowpage } def\n" "\n" "/pdfshowpage_mysetpage { % pdfshowpage_mysetpage \n" " dup /CropBox pget {\n" " boxrect\n" " 2 array astore /PageSize exch 4 2 roll\n" -" neg exch neg exch 2 array astore /PageOffset exch\n" +" 4 index /Rotate pget {\n" +" dup 0 lt {360 add} if 90 idiv {exch neg} repeat\n" +" } if\n" +" exch neg exch 2 array astore /PageOffset exch\n" " << 5 1 roll >> setpagedevice\n" " } if\n" "} bind def\n" "\n" -"/mypdfshowpage % pdfshowpage -\n" -" { dup /Page exch store\n" -" pdfshowpage_init \n" -" pdfshowpage_setpage \n" -" pdfshowpage_mysetpage\n" -" save /PDFSave exch store\n" -" (before exec) VMDEBUG\n" -" pdfshowpage_finish\n" -" (after exec) VMDEBUG\n" -" PDFSave restore\n" -" } bind def\n" -"\n" "GS_PDF_ProcSet begin\n" "pdfdict begin\n" blob - c4c31c923a94314567f8e1f1ea977858bbcbd3ce blob + 681e0587a709e20412700a85bd7378e79d161536 --- src/cmd/page/pdfprolog.ps +++ src/cmd/page/pdfprolog.ps @@ -2,28 +2,19 @@ /Page# 0 def /PDFSave null def /DSCPageCount 0 def -/DoPDFPage {dup /Page# exch store pdfgetpage mypdfshowpage } def +/DoPDFPage {dup /Page# exch store pdfgetpage pdfshowpage } def /pdfshowpage_mysetpage { % pdfshowpage_mysetpage dup /CropBox pget { boxrect 2 array astore /PageSize exch 4 2 roll - neg exch neg exch 2 array astore /PageOffset exch + 4 index /Rotate pget { + dup 0 lt {360 add} if 90 idiv {exch neg} repeat + } if + exch neg exch 2 array astore /PageOffset exch << 5 1 roll >> setpagedevice } if } bind def -/mypdfshowpage % pdfshowpage - - { dup /Page exch store - pdfshowpage_init - pdfshowpage_setpage - pdfshowpage_mysetpage - save /PDFSave exch store - (before exec) VMDEBUG - pdfshowpage_finish - (after exec) VMDEBUG - PDFSave restore - } bind def - GS_PDF_ProcSet begin pdfdict begin blob - cc6f3c513f9c5054cfafafa7c621685bdeec54d6 blob + 4b678dc383958f71bbab5d5d63878639ccb93fd5 --- src/cmd/page/ps.c +++ src/cmd/page/ps.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include "page.h" @@ -158,7 +158,7 @@ initps(Biobuf *b, int argc, char **argv, uchar *buf, i fprint(2, "reading through postscript...\n"); if(b == nil){ /* standard input; spool to disk (ouch) */ fd = spooltodisk(buf, nbuf, nil); - sprint(fdbuf, "/fd/%d", fd); + sprint(fdbuf, "/dev/fd/%d", fd); b = Bopen(fdbuf, OREAD); if(b == nil){ fprint(2, "cannot open disk spool file\n"); @@ -367,7 +367,7 @@ Keepreading: if(dumb) { fprint(ps->gs.gsfd, "(%s) run\n", argv[0]); - fprint(ps->gs.gsfd, "(/fd/3) (w) file dup (THIS IS NOT A PLAN9 BITMAP 01234567890123456789012345678901234567890123456789\\n) writestring flushfile\n"); + fprint(ps->gs.gsfd, "(/dev/fd/3) (w) file dup (THIS IS NOT A PLAN9 BITMAP 01234567890123456789012345678901234567890123456789\\n) writestring flushfile\n"); } ps->bbox = bbox; @@ -417,7 +417,7 @@ psdrawpage(Document *d, int page) Image *im; if(ps->clueless) - return readimage(display, ps->gs.gsdfd, 0); + return convert(&ps->gs.g); waitgs(&ps->gs); @@ -433,7 +433,7 @@ psdrawpage(Document *d, int page) * so send one to avoid deadlock. */ write(ps->gs.gsfd, "\n", 1); - im = readimage(display, ps->gs.gsdfd, 0); + im = convert(&ps->gs.g); if(im == nil) { fprint(2, "fatal: readimage error %r\n"); wexits("readimage"); blob - fc13059bf22d7933eaa170e00c30621ad3814cac blob + 4808734813f2d0331008b816be7f3ab29271a210 --- src/cmd/page/rotate.c +++ src/cmd/page/rotate.c @@ -15,14 +15,14 @@ #include #include #include +#include #include -#include #include "page.h" int ndraw = 0; enum { Xaxis = 0, - Yaxis = 1 + Yaxis = 1, }; Image *mtmp; @@ -55,7 +55,6 @@ moveup(Image *im, Image *tmp, int a, int b, int c, int drawop(tmp, tmp->r, im, nil, im->r.min, S); switch(axis){ - default: case Xaxis: range = Rect(a, im->r.min.y, c, im->r.max.y); dr0 = range; @@ -67,6 +66,7 @@ moveup(Image *im, Image *tmp, int a, int b, int c, int p1 = Pt(a, im->r.min.y); break; case Yaxis: + default: range = Rect(im->r.min.x, a, im->r.max.x, c); dr0 = range; dr0.max.y = dr0.min.y+(c-b); @@ -90,7 +90,6 @@ interlace(Image *im, Image *tmp, int axis, int n, Imag r0 = im->r; r1 = im->r; switch(axis) { - default: case Xaxis: r0.max.x = n; r1.min.x = n; @@ -98,6 +97,7 @@ interlace(Image *im, Image *tmp, int axis, int n, Imag p1 = (Point){-gran, 0}; break; case Yaxis: + default: r0.max.y = n; r1.min.y = n; p0 = (Point){0, gran}; @@ -132,12 +132,12 @@ interlace(Image *im, Image *tmp, int axis, int n, Imag int nextmask(Image *mask, int axis, int maskdim) { - Point delta; + Point o; - delta = axis==Xaxis ? Pt(maskdim,0) : Pt(0,maskdim); + o = axis==Xaxis ? Pt(maskdim,0) : Pt(0,maskdim); drawop(mtmp, mtmp->r, mask, nil, mask->r.min, S); - gendrawop(mask, mask->r, mtmp, delta, mtmp, divpt(delta,-2), S); -/* writefile("mask", mask, maskdim/2); */ + gendrawop(mask, mask->r, mtmp, o, mtmp, divpt(o,-2), S); +// writefile("mask", mask, maskdim/2); return maskdim/2; } @@ -153,13 +153,13 @@ shuffle(Image *im, Image *tmp, int axis, int n, Image nn = n - left; interlace(im, tmp, axis, nn, mask, gran); -/* writefile("interlace", im, gran); */ +// writefile("interlace", im, gran); gran = nextmask(mask, axis, gran); shuffle(im, tmp, axis, n, mask, gran, nn); -/* writefile("shuffle", im, gran); */ +// writefile("shuffle", im, gran); moveup(im, tmp, lastnn, nn, n, axis); -/* writefile("move", im, gran); */ +// writefile("move", im, gran); } void @@ -198,7 +198,7 @@ rot180(Image *im) } rmask.max.x = gran; drawop(mask, rmask, display->opaque, nil, ZP, S); -/* writefile("mask", mask, gran); */ +// writefile("mask", mask, gran); shuffle(im, tmp, Xaxis, Dx(im->r), mask, gran, 0); freeimage(mask); freeimage(mtmp); @@ -309,11 +309,11 @@ i0(double x) } double -kaiser(double x, double tau, double alpha) +kaiser(double x, double t, double a) { - if(fabs(x) > tau) + if(fabs(x) > t) return 0.; - return i0(alpha*sqrt(1-(x*x/(tau*tau))))/i0(alpha); + return i0(a*sqrt(1-(x*x/(t*t))))/i0(a); } blob - 2669df84689bd26ec905b8a622fe639be18af716 blob + 1f6fdeffddae8ed83822daf6aa8b50b7833e9b34 --- src/cmd/page/util.c +++ src/cmd/page/util.c @@ -1,9 +1,9 @@ #include #include #include -#include -#include +#include #include +#include #include "page.h" void* @@ -41,30 +41,6 @@ estrdup(char *s) return t; } -int -opentemp(char *template) -{ - int fd, i; - char *p; - - p = estrdup(template); - fd = -1; - for(i=0; i<10; i++){ - mktemp(p); - if(access(p, 0) < 0 && (fd=create(p, ORDWR|ORCLOSE, 0400)) >= 0) - break; - strcpy(p, template); - } - if(fd < 0){ - fprint(2, "couldn't make temporary file\n"); - wexits("Ecreat"); - } - strcpy(template, p); - free(p); - - return fd; -} - /* * spool standard input to /tmp. * we've already read the initial in bytes into ibuf. @@ -96,37 +72,54 @@ spooltodisk(uchar *ibuf, int in, char **name) return fd; } +typedef struct StdinArg StdinArg; + +struct StdinArg { + Channel *cp; + uchar *ibuf; + int in; +}; + /* * spool standard input into a pipe. * we've already ready the first in bytes into ibuf */ -int -stdinpipe(uchar *ibuf, int in) +static void +_stdinpipe(void *a) { uchar buf[8192]; - int n; + StdinArg *arg; int p[2]; + int n; + + arg = a; + if(pipe(p) < 0){ fprint(2, "pipe fails: %r\n"); wexits("pipe"); } - switch(rfork(RFPROC|RFFDG)){ - case -1: - fprint(2, "fork fails: %r\n"); - wexits("fork"); - default: - close(p[1]); - return p[0]; - case 0: - break; - } + send(arg->cp, &p[0]); - close(p[0]); - write(p[1], ibuf, in); + write(p[1], arg->ibuf, arg->in); while((n = read(stdinfd, buf, sizeof buf)) > 0) write(p[1], buf, n); + + close(p[1]); + threadexits(0); +} - _exits(0); - return -1; /* not reached */ +int +stdinpipe(uchar *ibuf, int in) { + StdinArg arg; + int fd; + + arg.ibuf = ibuf; + arg.in = in; + arg.cp = chancreate(sizeof(int), 0); + proccreate(_stdinpipe, &arg, mainstacksize); + recv(arg.cp, &fd); + chanfree(arg.cp); + + return fd; } blob - 1cdb254144026a863b5a0b3394c4108b97d8f128 blob + ab409cc7920702da8cd8f8f2f26cbbfcfba9fc3f --- src/cmd/page/view.c +++ src/cmd/page/view.c @@ -4,17 +4,19 @@ #include #include +#include <9pclient.h> #include #include -#include -#include +#include +#include +#include #include #include #include -#include #include "page.h" Document *doc; +Mousectl *mc; Image *im; int page; int angle = 0; @@ -26,6 +28,7 @@ Point ul; /* the upper left corner of the image is a Point pclip(Point, Rectangle); Rectangle mkrange(Rectangle screenr, Rectangle imr); void redraw(Image*); +void plumbproc(void*); Cursor reading={ {-1, -1}, @@ -56,20 +59,13 @@ enum { Middle = 2, Right = 4, - RMenu = 3 + RMenu = 3, }; void unhide(void) { - static int wctl = -1; - - if(wctl < 0) - wctl = open("/dev/wctl", OWRITE); - if(wctl < 0) - return; - - write(wctl, "unhide", 6); + USED(nil); } int @@ -126,7 +122,7 @@ showpage(int page, Menu *m) else m->lasthit = reverse ? doc->npage-1-page : page; - esetcursor(&reading); + setcursor(mc, &reading); freeimage(im); if((page < 0 || page >= doc->npage) && !doc->fwdonly){ im = nil; @@ -169,7 +165,7 @@ showpage(int page, Menu *m) break; } - esetcursor(nil); + setcursor(mc, nil); if(showbottom){ ul.y = screen->r.max.y - Dy(im->r); showbottom = 0; @@ -186,7 +182,7 @@ writebitmap(void) char name[64+30]; static char result[200]; char *p, *q; - int fd; + int fd = -1; if(im == nil) return "no image"; @@ -209,18 +205,18 @@ writebitmap(void) snprint(name, sizeof(name)-1, "%s.%d.bit", q, page+1); if(access(name, 0) >= 0) { strcat(name, "XXXX"); - mktemp(name); + fd = mkstemp(name); } - if(access(name, 0) >= 0) + if(fd < 0) return "couldn't think of a name for bitmap"; } else { strcpy(name, "bitXXXX"); - mktemp(name); - if(access(name, 0) >= 0) + mkstemp(name); + if(fd < 0) return "couldn't think of a name for bitmap"; } - if((fd = create(name, OWRITE, 0666)) < 0) { + if(fd < 0) { snprint(result, sizeof result, "cannot create %s: %r", name); return result; } @@ -265,7 +261,7 @@ enum{ Del, Write, Empty3, - Exit + Exit, }; void @@ -273,11 +269,14 @@ viewer(Document *dd) { int i, fd, n, oldpage; int nxt; + Channel *cp; Menu menu, midmenu; Mouse m; - Event e; + Keyboardctl *kc; Point dxy, oxy, xy0; + Rune run; Rectangle r; + int size[2]; Image *tmp; static char *fwditems[] = { "this page", "next page", "exit", 0 }; static char *miditems[] = { @@ -299,16 +298,44 @@ viewer(Document *dd) 0 }; char *s; - enum { Eplumb = 4 }; + enum { + CMouse, + CResize, + CKeyboard, + CPlumb, + CN + }; + Alt alts[CN+1]; Plumbmsg *pm; + cp = chancreate(sizeof pm, 0); + assert(cp); + doc = dd; /* save global for menuhit */ ul = screen->r.min; - einit(Emouse|Ekeyboard); - if(doc->addpage != nil) - eplumb(Eplumb, "image"); + mc = initmouse(nil, screen); + kc = initkeyboard(nil); + alts[CMouse].c = mc->c; + alts[CMouse].v = &m; + alts[CMouse].op = CHANRCV; + alts[CResize].c = mc->resizec; + alts[CResize].v = &size; + alts[CResize].op = CHANRCV; + alts[CKeyboard].c = kc->c; + alts[CKeyboard].v = &run; + alts[CKeyboard].op = CHANRCV; + alts[CPlumb].c = cp; + alts[CPlumb].v = ± + alts[CPlumb].op = CHANNOP; + alts[CN].op = CHANEND; - esetcursor(&reading); + /* XXX: Event */ + if(doc->addpage != nil) { + alts[CPlumb].op = CHANRCV; + proccreate(plumbproc, cp, 16384); + } + + setcursor(mc, &reading); r.min = ZP; /* @@ -336,7 +363,7 @@ viewer(Document *dd) midmenu.lasthit = Next; showpage(page, &menu); - esetcursor(nil); + setcursor(mc, nil); nxt = 0; for(;;) { @@ -345,14 +372,14 @@ viewer(Document *dd) * a fair amount. we don't care about doc->npage anymore, and * all that can be done is select the next page. */ - switch(eread(Emouse|Ekeyboard|Eplumb, &e)){ - case Ekeyboard: - if(e.kbdc <= 0xFF && isdigit(e.kbdc)) { - nxt = nxt*10+e.kbdc-'0'; - break; - } else if(e.kbdc != '\n') + switch(alt(alts)) { + case CKeyboard: + if(run <= 0xFF && isdigit(run)) { + nxt = nxt*10+run-'0'; + break; + } else if(run != '\n') nxt = 0; - switch(e.kbdc) { + switch(run) { case 'r': /* reverse page order */ if(doc->fwdonly) break; @@ -372,12 +399,12 @@ viewer(Document *dd) } break; case 'w': /* write bitmap of current screen */ - esetcursor(&reading); + setcursor(mc, &reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); - esetcursor(nil); + setcursor(mc, nil); flushimage(display, 1); break; case 'd': /* remove image from working set */ @@ -397,9 +424,9 @@ viewer(Document *dd) case 'u': if(im==nil) break; - esetcursor(&reading); + setcursor(mc, &reading); rot180(im); - esetcursor(nil); + setcursor(mc, nil); angle = (angle+180) % 360; redraw(screen); flushimage(display, 1); @@ -470,15 +497,14 @@ viewer(Document *dd) } break; default: - esetcursor(&query); + setcursor(mc, &query); sleep(1000); - esetcursor(nil); + setcursor(mc, nil); break; } break; - case Emouse: - m = e.mouse; + case CMouse: switch(m.buttons){ case Left: oxy = m.xy; @@ -487,7 +513,7 @@ viewer(Document *dd) dxy = subpt(m.xy, oxy); oxy = m.xy; translate(dxy); - m = emouse(); + recv(mc->c, &m); } while(m.buttons == Left); if(m.buttons) { dxy = subpt(xy0, oxy); @@ -499,7 +525,7 @@ viewer(Document *dd) if(doc->npage == 0) break; - n = emenuhit(Middle, &m, &midmenu); + n = menuhit(Middle, mc, &midmenu, nil); if(n == -1) break; switch(n){ @@ -543,7 +569,7 @@ viewer(Document *dd) double delta; Rectangle r; - r = egetrect(Middle, &m); + r = getrect(Middle, mc); if((rectclip(&r, rectaddpt(im->r, ul)) == 0) || Dx(r) == 0 || Dy(r) == 0) break; @@ -553,7 +579,7 @@ viewer(Document *dd) else delta = (double)Dy(im->r)/(double)Dy(r); - esetcursor(&reading); + setcursor(mc, &reading); tmp = xallocimage(display, Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)), im->chan, 0, DBlack); @@ -564,7 +590,7 @@ viewer(Document *dd) resample(im, tmp); freeimage(im); im = tmp; - esetcursor(nil); + setcursor(mc, nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); @@ -580,7 +606,7 @@ viewer(Document *dd) delta = (double)Dy(screen->r)/(double)Dy(im->r); r = Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)); - esetcursor(&reading); + setcursor(mc, &reading); tmp = xallocimage(display, r, im->chan, 0, DBlack); if(tmp == nil) { fprint(2, "out of memory during fit: %r\n"); @@ -589,16 +615,16 @@ viewer(Document *dd) resample(im, tmp); freeimage(im); im = tmp; - esetcursor(nil); + setcursor(mc, nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Rot: /* rotate 90 */ - esetcursor(&reading); + setcursor(mc, &reading); im = rot90(im); - esetcursor(nil); + setcursor(mc, nil); angle = (angle+90) % 360; redraw(screen); flushimage(display, 1); @@ -606,9 +632,9 @@ viewer(Document *dd) case Upside: /* upside-down */ if(im==nil) break; - esetcursor(&reading); + setcursor(mc, &reading); rot180(im); - esetcursor(nil); + setcursor(mc, nil); angle = (angle+180) % 360; redraw(screen); flushimage(display, 1); @@ -628,12 +654,12 @@ viewer(Document *dd) } break; case Write: /* write */ - esetcursor(&reading); + setcursor(mc, &reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); - esetcursor(nil); + setcursor(mc, nil); flushimage(display, 1); break; case Del: /* delete */ @@ -663,7 +689,7 @@ viewer(Document *dd) break; oldpage = page; - n = emenuhit(RMenu, &m, &menu); + n = menuhit(RMenu, mc, &menu, nil); if(n == -1) break; @@ -691,9 +717,15 @@ viewer(Document *dd) break; } break; - - case Eplumb: - pm = e.v; + case CResize: + r = screen->r; + if(getwindow(display, Refnone) < 0) + fprint(2,"can't reattach to window"); + ul = addpt(ul, subpt(screen->r.min, r.min)); + redraw(screen); + flushimage(display, 1); + break; + case CPlumb: if(pm->ndata <= 0){ plumbfree(pm); break; @@ -866,18 +898,7 @@ redraw(Image *screen) } } border(screen, r, -4000, gray, ZP); -/* flushimage(display, 0); */ -} - -void -eresized(int new) -{ - Rectangle r; - r = screen->r; - if(new && getwindow(display, Refnone) < 0) - fprint(2,"can't reattach to window"); - ul = addpt(ul, subpt(screen->r.min, r.min)); - redraw(screen); +// flushimage(display, 0); } /* clip p to be in r */ @@ -909,21 +930,17 @@ resize(int dx, int dy) static Rectangle sr; Rectangle r, or; - dx += 2*Borderwidth; - dy += 2*Borderwidth; - if(wctlfd < 0){ - wctlfd = open("/dev/wctl", OWRITE); - if(wctlfd < 0) - return; + r = screen->r; + if(Dx(sr)*Dy(sr) == 0) { + sr = screenrect(); + /* Start with the size of the first image */ + r.max.x = r.min.x; + r.max.y = r.min.y; } - r = insetrect(screen->r, -Borderwidth); if(Dx(r) >= dx && Dy(r) >= dy) return; - if(Dx(sr)*Dy(sr) == 0) - sr = screenrect(); - or = r; r.max.x = max(r.min.x+dx, r.max.x); @@ -950,8 +967,7 @@ resize(int dx, int dy) if(Dx(r) == Dx(or) && Dy(r) == Dy(or)) return; - fprint(wctlfd, "resize -minx %d -miny %d -maxx %d -maxy %d\n", - r.min.x, r.min.y, r.max.x, r.max.y); + drawresizewindow(r); } /* @@ -966,129 +982,73 @@ xallocimage(Display *d, Rectangle r, ulong chan, int r return allocimage(d, r, chan, repl, val); } -/* all code below this line should be in the library, but is stolen from colors instead */ -static char* -rdenv(char *name) -{ - char *v; - int fd, size; - - fd = open(name, OREAD); - if(fd < 0) - return 0; - size = seek(fd, 0, 2); - v = malloc(size+1); - if(v == 0){ - fprint(2, "page: can't malloc: %r\n"); - wexits("no mem"); - } - seek(fd, 0, 0); - read(fd, v, size); - v[size] = 0; - close(fd); - return v; -} - void -newwin(void) +plumbproc(void *c) { - char *srv, *mntsrv; - char spec[100]; - int srvfd, cons, pid; + Channel *cp; + CFid *fd; - switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){ - case -1: - fprint(2, "page: can't fork: %r\n"); - wexits("no fork"); - case 0: - break; - default: - wexits(0); + cp = c; + fd = plumbopenfid("image", OREAD|OCEXEC); + if(fd == nil) { + fprint(2, "Cannot connect to the plumber"); + threadexits("plumber"); } - - srv = rdenv("/env/wsys"); - if(srv == 0){ - mntsrv = rdenv("/mnt/term/env/wsys"); - if(mntsrv == 0){ - fprint(2, "page: can't find $wsys\n"); - wexits("srv"); - } - srv = malloc(strlen(mntsrv)+10); - sprint(srv, "/mnt/term%s", mntsrv); - free(mntsrv); - pid = 0; /* can't send notes to remote processes! */ - }else - pid = getpid(); - srvfd = open(srv, ORDWR); - free(srv); - if(srvfd == -1){ - fprint(2, "page: can't open %s: %r\n", srv); - wexits("no srv"); + for(;;) { + send(cp, plumbrecvfid(fd)); } - sprint(spec, "new -pid %d", pid); - if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){ - fprint(2, "page: can't mount /mnt/wsys: %r (spec=%s)\n", spec); - wexits("no mount"); - } - close(srvfd); - unmount("/mnt/acme", "/dev"); - bind("/mnt/wsys", "/dev", MBEFORE); - cons = open("/dev/cons", OREAD); - if(cons==-1){ - NoCons: - fprint(2, "page: can't open /dev/cons: %r"); - wexits("no cons"); - } - dup(cons, 0); - close(cons); - cons = open("/dev/cons", OWRITE); - if(cons==-1) - goto NoCons; - dup(cons, 1); - dup(cons, 2); - close(cons); -/* wctlfd = open("/dev/wctl", OWRITE); */ } +/* XXX: This function is ugly and hacky. There may be a better way... or not */ Rectangle screenrect(void) { - int fd; - char buf[12*5]; + int fd[3], pfd[2]; + int n, w, h; + char buf[64]; + char *p, *pr; - fd = open("/dev/screen", OREAD); - if(fd == -1) - fd=open("/mnt/term/dev/screen", OREAD); - if(fd == -1){ - fprint(2, "page: can't open /dev/screen: %r\n"); - wexits("window read"); - } - if(read(fd, buf, sizeof buf) != sizeof buf){ - fprint(2, "page: can't read /dev/screen: %r\n"); - wexits("screen read"); - } - close(fd); - return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48)); + if(pipe(pfd) < 0) + wexits("pipe failed"); + + fd[0] = open("/dev/null", OREAD); + fd[1] = pfd[1]; + fd[2] = dup(2, -1); + if(threadspawnl(fd, "rc", "rc", "-c", "xdpyinfo | grep 'dimensions:'", nil) == -1) + wexits("threadspawnl failed"); + + if((n = read(pfd[0], buf, 63)) <= 0) + wexits("read xdpyinfo failed"); + close(fd[0]); + + buf[n] = '\0'; + for(p = buf; *p; p++) + if(*p >= '0' && *p <= '9') break; + if(*p == '\0') + wexits("xdpyinfo parse failed"); + + w = strtoul(p, &pr, 10); + if(p == pr || *pr == '\0' || *(++pr) == '\0') + wexits("xdpyinfo parse failed"); + h = strtoul(pr, &p, 10); + if(p == pr) + wexits("xdpyinfo parse failed"); + + return Rect(0, 0, w, h); } void zerox(void) { int pfd[2]; + int fd[3]; pipe(pfd); - switch(rfork(RFFDG|RFPROC)) { - case -1: - wexits("cannot fork in zerox: %r"); - case 0: - dup(pfd[1], 0); - close(pfd[0]); - execl("/bin/page", "page", "-w", nil); - wexits("cannot exec in zerox: %r\n"); - default: - close(pfd[1]); - writeimage(pfd[0], im, 0); - close(pfd[0]); - break; - } + fd[0] = pfd[0]; + fd[1] = dup(1, -1); + fd[2] = dup(2, -1); + threadspawnl(fd, "page", "page", "-R", nil); + + writeimage(pfd[1], im, 0); + close(pfd[1]); }