summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@centraldogma>2011-09-15 20:59:31 +0200
committercinap_lenrek <cinap_lenrek@centraldogma>2011-09-15 20:59:31 +0200
commitd9657f82748a397eed451a4cfd0bbc6f19551488 (patch)
tree920beb374f6476d81df66188119254acc0db7197 /sys/src
parentd02a0b77666d94bc97bbf0412b3cbefeff12c462 (diff)
replaceing page with npage
Diffstat (limited to 'sys/src')
-rw-r--r--sys/src/cmd/page.c (renamed from sys/src/cmd/npage.c)36
-rw-r--r--sys/src/cmd/page/cache.c187
-rw-r--r--sys/src/cmd/page/filter.c107
-rw-r--r--sys/src/cmd/page/gfx.c332
-rw-r--r--sys/src/cmd/page/gs.c342
-rw-r--r--sys/src/cmd/page/mkfile36
-rw-r--r--sys/src/cmd/page/nrotate.c277
-rw-r--r--sys/src/cmd/page/page.c238
-rw-r--r--sys/src/cmd/page/page.h85
-rw-r--r--sys/src/cmd/page/pdf.c153
-rw-r--r--sys/src/cmd/page/pdfprolog.ps20
-rw-r--r--sys/src/cmd/page/ps.c450
-rw-r--r--sys/src/cmd/page/rotate.c500
-rw-r--r--sys/src/cmd/page/util.c131
-rw-r--r--sys/src/cmd/page/view.c1073
15 files changed, 36 insertions, 3931 deletions
diff --git a/sys/src/cmd/npage.c b/sys/src/cmd/page.c
index 5bd1653c0..a0751a5eb 100644
--- a/sys/src/cmd/npage.c
+++ b/sys/src/cmd/page.c
@@ -873,6 +873,26 @@ translate(Page *p, Point d)
}
Page*
+findpage(char *name)
+{
+ Page *p;
+ int n;
+
+ n = strlen(name);
+ /* look in current document first */
+ if(current && current->up){
+ for(p = current->up->down; p; p = p->next)
+ if(cistrncmp(p->label, name, n) == 0)
+ return p;
+ }
+ /* look everywhere */
+ for(p = root->down; p; p = nextpage(p))
+ if(cistrncmp(p->label, name, n) == 0)
+ return p;
+ return nil;
+}
+
+Page*
pageat(int i)
{
Page *p;
@@ -1006,6 +1026,7 @@ void
main(int argc, char *argv[])
{
enum { Eplumb = 4 };
+ char jump[32];
Plumbmsg *pm;
Point o;
Mouse m;
@@ -1061,6 +1082,7 @@ main(int argc, char *argv[])
for(; *argv; argv++)
addpage(root, shortname(*argv), popenfile, strdup(*argv), -1);
+ jump[0] = 0;
for(;;){
i=event(&e);
switch(i){
@@ -1183,6 +1205,8 @@ main(int argc, char *argv[])
qunlock(current);
if(prevpage(current))
pos.y = 0;
+ case '-':
+ case Kbs:
case Kleft:
showpage(prevpage(current));
break;
@@ -1201,10 +1225,22 @@ main(int argc, char *argv[])
qunlock(current);
if(nextpage(current))
pos.y = 0;
+ case '\n':
+ if(jump[0]){
+ showpage(findpage(jump));
+ jump[0] = 0;
+ break;
+ }
case ' ':
case Kright:
showpage(nextpage(current));
break;
+ default:
+ i = strlen(jump);
+ if(i+1 < sizeof(jump)){
+ jump[i] = e.kbdc;
+ jump[i+1] = 0;
+ }
}
break;
case Eplumb:
diff --git a/sys/src/cmd/page/cache.c b/sys/src/cmd/page/cache.c
deleted file mode 100644
index 376a075ed..000000000
--- a/sys/src/cmd/page/cache.c
+++ /dev/null
@@ -1,187 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <cursor.h>
-#include <event.h>
-#include <bio.h>
-#include <plumb.h>
-#include <ctype.h>
-#include <keyboard.h>
-#include "page.h"
-
-typedef struct Cached Cached;
-struct Cached
-{
- Document *doc;
- int page;
- int angle;
- Image *im;
-};
-
-static Cached cache[5];
-
-static Image*
-questionmark(void)
-{
- static Image *im;
-
- if(im)
- return im;
- im = xallocimage(display, Rect(0,0,50,50), GREY1, 1, DBlack);
- if(im == nil)
- return nil;
- string(im, ZP, display->white, ZP, display->defaultfont, "?");
- return im;
-}
-
-void
-cacheflush(void)
-{
- int i;
- Cached *c;
-
- for(i=0; i<nelem(cache); i++){
- c = &cache[i];
- if(c->im)
- freeimage(c->im);
- c->im = nil;
- c->doc = nil;
- }
-}
-
-static Image*
-_cachedpage(Document *doc, int angle, int page, char *ra)
-{
- int i;
- Cached *c, old;
- Image *im, *tmp;
- static int lastpage = -1;
-
- if((page < 0 || page >= doc->npage) && !doc->fwdonly)
- return nil;
-
-Again:
- for(i=0; i<nelem(cache); i++){
- c = &cache[i];
- if(c->doc == doc && c->angle == angle && c->page == page){
- if(chatty) fprint(2, "cache%s hit %d\n", ra, page);
- goto Found;
- }
- if(c->doc == nil)
- break;
- }
-
- if(i >= nelem(cache))
- i = nelem(cache)-1;
- c = &cache[i];
- if(c->im)
- freeimage(c->im);
- c->im = nil;
- c->doc = nil;
- c->page = -1;
-
- if(chatty) fprint(2, "cache%s load %d\n", ra, page);
- im = doc->drawpage(doc, page);
- if(im == nil){
- if(doc->fwdonly) /* end of file */
- wexits(0);
- im = questionmark();
- if(im == nil){
- Flush:
- if(i > 0){
- cacheflush();
- goto Again;
- }
- fprint(2, "out of memory: %r\n");
- wexits("memory");
- }
- return im;
- }
-
- if(im->r.min.x != 0 || im->r.min.y != 0){
- /* translate to 0,0 */
- tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill);
- if(tmp == nil){
- freeimage(im);
- goto Flush;
- }
- drawop(tmp, tmp->r, im, nil, im->r.min, S);
- freeimage(im);
- im = tmp;
- }
-
- switch(angle){
- case 90:
- im = rot90(im);
- break;
- case 180:
- rot180(im);
- break;
- case 270:
- im = rot270(im);
- break;
- }
- if(im == nil)
- goto Flush;
-
- c->doc = doc;
- c->page = page;
- c->angle = angle;
- c->im = im;
-
-Found:
- if(chatty) fprint(2, "cache%s mtf %d @%d:", ra, c->page, i);
- old = *c;
- memmove(cache+1, cache, (c-cache)*sizeof cache[0]);
- cache[0] = old;
- if(chatty){
- for(i=0; i<nelem(cache); i++)
- fprint(2, " %d", cache[i].page);
- fprint(2, "\n");
- }
- if(chatty) fprint(2, "cache%s return %d %p\n", ra, old.page, old.im);
- return old.im;
-}
-
-Image*
-cachedpage(Document *doc, int angle, int page)
-{
- static int lastpage = -1;
- static int rabusy;
- Image *im;
- int ra;
-
- if(doc->npage < 1)
- return display->white;
-
- im = _cachedpage(doc, angle, page, "");
- if(im == nil)
- return nil;
-
- /* readahead */
- ra = -1;
- if(!rabusy){
- if(page == lastpage+1)
- ra = page+1;
- else if(page == lastpage-1)
- ra = page-1;
- }
- lastpage = page;
- if(ra >= 0){
- rabusy = 1;
- switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
- case -1:
- rabusy = 0;
- break;
- case 0:
- lockdisplay(display);
- _cachedpage(doc, angle, ra, "-ra");
- rabusy = 0;
- unlockdisplay(display);
- _exits(nil);
- default:
- break;
- }
- }
- return im;
-}
diff --git a/sys/src/cmd/page/filter.c b/sys/src/cmd/page/filter.c
deleted file mode 100644
index 07c3df2b2..000000000
--- a/sys/src/cmd/page/filter.c
+++ /dev/null
@@ -1,107 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-#include <bio.h>
-#include "page.h"
-
-Document*
-initfilt(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf, char *type, char *cmd, int docopy)
-{
- int ofd;
- int p[2];
- char xbuf[8192];
- int n;
-
- if(argc > 1) {
- fprint(2, "can only view one %s file at a time\n", type);
- return nil;
- }
-
- fprint(2, "converting from %s to postscript...\n", type);
-
- if(docopy){
- if(pipe(p) < 0){
- fprint(2, "pipe fails: %r\n");
- exits("Epipe");
- }
- }else{
- p[0] = open("/dev/null", ORDWR);
- p[1] = open("/dev/null", ORDWR);
- }
-
- ofd = opentemp("/tmp/pagecvtXXXXXXXXX");
- switch(fork()){
- case -1:
- fprint(2, "fork fails: %r\n");
- exits("Efork");
- default:
- close(p[1]);
- if(docopy){
- write(p[0], buf, nbuf);
- if(b)
- while((n = Bread(b, xbuf, sizeof xbuf)) > 0)
- write(p[0], xbuf, n);
- else
- while((n = read(stdinfd, xbuf, sizeof xbuf)) > 0)
- write(p[0], xbuf, n);
- }
- close(p[0]);
- waitpid();
- break;
- case 0:
- close(p[0]);
- dup(p[1], 0);
- dup(ofd, 1);
- /* stderr shines through */
- execl("/bin/rc", "rc", "-c", cmd, nil);
- break;
- }
-
- if(b)
- Bterm(b);
- seek(ofd, 0, 0);
- b = emalloc(sizeof(Biobuf));
- Binit(b, ofd, OREAD);
-
- return initps(b, argc, argv, nil, 0);
-}
-
-Document*
-initdvi(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
-{
- int fd;
- char *name;
- char cmd[256];
- char fdbuf[20];
-
- /*
- * Stupid DVIPS won't take standard input.
- */
- if(b == nil){ /* standard input; spool to disk (ouch) */
- fd = spooltodisk(buf, nbuf, &name);
- sprint(fdbuf, "/fd/%d", fd);
- b = Bopen(fdbuf, OREAD);
- if(b == nil){
- fprint(2, "cannot open disk spool file\n");
- wexits("Bopen temp");
- }
- argv = &name;
- argc = 1;
- }
-
- snprint(cmd, sizeof cmd, "dvips -Pps -r0 -q1 -f1 '%s'", argv[0]);
- return initfilt(b, argc, argv, buf, nbuf, "dvi", cmd, 0);
-}
-
-Document*
-inittroff(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
-{
- return initfilt(b, argc, argv, buf, nbuf, "troff", "lp -dstdout", 1);
-}
-
-Document*
-initmsdoc(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
-{
- return initfilt(b, argc, argv, buf, nbuf, "microsoft office", "doc2ps", 1);
-}
diff --git a/sys/src/cmd/page/gfx.c b/sys/src/cmd/page/gfx.c
deleted file mode 100644
index 57ebc746b..000000000
--- a/sys/src/cmd/page/gfx.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * graphics file reading for page
- */
-
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-#include <bio.h>
-#include "page.h"
-
-typedef struct Convert Convert;
-typedef struct GfxInfo GfxInfo;
-typedef struct Graphic Graphic;
-
-struct Convert {
- char *name;
- char *cmd;
- char *truecmd; /* cmd for true color */
-};
-
-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.
- */
-Convert cvt[] = {
-[Ipic] { "plan9", "fb/3to1 rgbv %a |fb/pcp -tplan9" },
-[Itiff] { "tiff", "fb/tiff2pic %a | fb/3to1 rgbv | fb/pcp -tplan9" },
-[Iplan9bm] { "plan9bm", nil },
-[Ijpeg] { "jpeg", "jpg -9 %a", "jpg -t9 %a" },
-[Igif] { "gif", "gif -9 %a", "gif -t9 %a" },
-[Iinferno] { "inferno", nil },
-[Ifax] { "fax", "aux/g3p9bit -g %a" },
-[Icvt2pic] { "unknown", "fb/cvt2pic %a |fb/3to1 rgbv" },
-[Ippm] { "ppm", "ppm -9 %a", "ppm -t9 %a" },
-/* ``temporary'' hack for hobby */
-[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" },
-};
-
-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 addpage(Document*, char*);
-static int rmpage(Document*, int);
-static int genaddpage(Document*, char*, uchar*, int);
-
-static char*
-gfxpagename(Document *doc, int page)
-{
- GfxInfo *gfx = doc->extra;
- return gfx->g[page].name;
-}
-
-static Image*
-gfxdrawpage(Document *doc, int page)
-{
- GfxInfo *gfx = doc->extra;
- return convert(gfx->g+page);
-}
-
-Document*
-initgfx(Biobuf*, int argc, char **argv, uchar *buf, int nbuf)
-{
- GfxInfo *gfx;
- Document *doc;
- int i;
-
- doc = emalloc(sizeof(*doc));
- gfx = emalloc(sizeof(*gfx));
- gfx->g = nil;
-
- doc->npage = 0;
- doc->drawpage = gfxdrawpage;
- doc->pagename = gfxpagename;
- doc->addpage = addpage;
- doc->rmpage = rmpage;
- doc->extra = gfx;
- doc->fwdonly = 0;
-
- fprint(2, "reading through graphics...\n");
- if(argc==0 && buf)
- genaddpage(doc, nil, buf, nbuf);
- else{
- for(i=0; i<argc; i++)
- if(addpage(doc, argv[i]) < 0)
- fprint(2, "warning: not including %s: %r\n", argv[i]);
- }
-
- return doc;
-}
-
-static int
-genaddpage(Document *doc, char *name, uchar *buf, int nbuf)
-{
- Graphic *g;
- GfxInfo *gfx;
- Biobuf *b;
- uchar xbuf[32];
- int i, l;
-
- l = 0;
- gfx = doc->extra;
-
- assert((name == nil) ^ (buf == nil));
- assert(name != nil || doc->npage == 0);
-
- for(i=0; i<doc->npage; i++)
- if(strcmp(gfx->g[i].name, name) == 0)
- return i;
-
- if(name){
- l = strlen(name);
- if((b = Bopen(name, OREAD)) == nil) {
- werrstr("Bopen: %r");
- return -1;
- }
-
- if(Bread(b, xbuf, sizeof xbuf) != sizeof xbuf) {
- werrstr("short read: %r");
- return -1;
- }
- Bterm(b);
- buf = xbuf;
- nbuf = sizeof xbuf;
- }
-
-
- gfx->g = erealloc(gfx->g, (doc->npage+1)*(sizeof(*gfx->g)));
- g = &gfx->g[doc->npage];
-
- memset(g, 0, sizeof *g);
- if(memcmp(buf, "GIF", 3) == 0)
- g->type = Igif;
- else if(memcmp(buf, "\111\111\052\000", 4) == 0)
- g->type = Itiff;
- else if(memcmp(buf, "\115\115\000\052", 4) == 0)
- g->type = Itiff;
- else if(memcmp(buf, "\377\330\377", 3) == 0)
- g->type = Ijpeg;
- else if(memcmp(buf, "\211PNG\r\n\032\n", 3) == 0)
- g->type = Ipng;
- else if(memcmp(buf, "compressed\n", 11) == 0)
- g->type = Iinferno;
- else if(memcmp(buf, "\0PC Research, Inc", 17) == 0)
- g->type = Ifax;
- else if(memcmp(buf, "TYPE=ccitt-g31", 14) == 0)
- g->type = Ifax;
- else if(memcmp(buf, "II*", 3) == 0)
- g->type = Ifax;
- else if(memcmp(buf, "TYPE=ccitt-g4", 13) == 0)
- g->type = Iccittg4;
- else if(memcmp(buf, "TYPE=", 5) == 0)
- g->type = Ipic;
- else if(buf[0] == 'P' && '0' <= buf[1] && buf[1] <= '9')
- g->type = Ippm;
- else if(memcmp(buf, "BM", 2) == 0)
- g->type = Ibmp;
- else if(memcmp(buf, " ", 10) == 0 &&
- '0' <= buf[10] && buf[10] <= '9' &&
- buf[11] == ' ')
- g->type = Iplan9bm;
- else if(strtochan((char*)buf) != 0)
- g->type = Iplan9bm;
- else if (l > 4 && strcmp(name + l -4, ".yuv") == 0)
- g->type = Iyuv;
- else
- g->type = Icvt2pic;
-
- if(name)
- g->name = estrdup(name);
- else{
- g->name = estrdup("stdin"); /* so it can be freed */
- g->buf = buf;
- g->nbuf = nbuf;
- }
-
- if(chatty) fprint(2, "classified \"%s\" as \"%s\"\n", g->name, cvt[g->type].name);
- return doc->npage++;
-}
-
-static int
-addpage(Document *doc, char *name)
-{
- return genaddpage(doc, name, nil, 0);
-}
-
-static int
-rmpage(Document *doc, int n)
-{
- int i;
- GfxInfo *gfx;
-
- if(n < 0 || n >= doc->npage)
- return -1;
-
- gfx = doc->extra;
- doc->npage--;
- free(gfx->g[n].name);
-
- for(i=n; i<doc->npage; i++)
- gfx->g[i] = gfx->g[i+1];
-
- if(n < doc->npage)
- return n;
- if(n == 0)
- return 0;
- return n-1;
-}
-
-
-static Image*
-convert(Graphic *g)
-{
- int fd;
- Convert c;
- char *cmd;
- 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 */
- fd = open(g->name, OREAD);
- if(fd < 0) {
- fprint(2, "cannot open file: %r\n");
- wexits("open");
- }
- }else
- fd = stdinpipe(g->buf, g->nbuf);
- } else {
- cmd = c.cmd;
- if(truecolor && c.truecmd)
- cmd = c.truecmd;
-
- if(g->buf != nil) /* is stdin */
- name = "";
- else
- name = g->name;
- if(strlen(cmd)+strlen(name) > sizeof buf) {
- fprint(2, "command too long\n");
- wexits("convert");
- }
- 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);
- rcspawned++;
- if(fd < 0) {
- fprint(2, "cannot spawn converter: %r\n");
- wexits("convert");
- }
- }
-
- im = readimage(display, fd, 0);
- 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);
- }
- return im;
-}
-
-static int
-spawnrc(char *cmd, uchar *stdinbuf, int nstdinbuf)
-{
- int pfd[2];
- int pid;
-
- if(chatty) fprint(2, "spawning(%s)...", cmd);
-
- if(pipe(pfd) < 0)
- return -1;
- if((pid = fork()) < 0)
- 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];
-}
-
diff --git a/sys/src/cmd/page/gs.c b/sys/src/cmd/page/gs.c
deleted file mode 100644
index 3ff04685b..000000000
--- a/sys/src/cmd/page/gs.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * gs interface for page.
- * ps.c and pdf.c both use these routines.
- * a caveat: if you run more than one gs, only the last
- * one gets killed by killgs
- */
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-#include <bio.h>
-#include "page.h"
-
-static int gspid; /* globals for atexit */
-static int gsfd;
-static void killgs(void);
-
-static void
-killgs(void)
-{
- char tmpfile[100];
-
- close(gsfd);
- postnote(PNGROUP, getpid(), "die");
-
- /*
- * from ghostscript's use.txt:
- * ``Ghostscript currently doesn't do a very good job of deleting temporary
- * files when it exits; you may have to delete them manually from time to
- * time.''
- */
- sprint(tmpfile, "/tmp/gs_%.5da", (gspid+300000)%100000);
- if(chatty) fprint(2, "remove %s...\n", tmpfile);
- remove(tmpfile);
- sleep(100);
- postnote(PNPROC, gspid, "die yankee pig dog");
-}
-
-int
-spawnwriter(GSInfo *g, Biobuf *b)
-{
- char buf[4096];
- int n;
- int fd;
-
- switch(fork()){
- case -1: return -1;
- case 0: break;
- default: return 0;
- }
-
- 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;
-}
-
-int
-spawnreader(int fd)
-{
- int n, pfd[2];
- char buf[1024];
-
- if(pipe(pfd)<0)
- return -1;
- switch(fork()){
- case -1:
- return -1;
- case 0:
- break;
- default:
- close(pfd[0]);
- return pfd[1];
- }
-
- 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;
-}
-
-void
-spawnmonitor(int fd)
-{
- char buf[4096];
- char *xbuf;
- int n;
- int out;
- int first;
-
- switch(rfork(RFFDG|RFNOTEG|RFPROC)){
- case -1:
- default:
- return;
-
- case 0:
- break;
- }
-
- out = open("/dev/cons", OWRITE);
- if(out < 0)
- out = 2;
-
- xbuf = buf; /* for ease of acid */
- first = 1;
- while((n = read(fd, xbuf, sizeof buf)) > 0){
- if(first){
- first = 0;
- fprint(2, "Ghostscript Error:\n");
- }
- write(out, xbuf, n);
- alarm(500);
- }
- _exits(0);
-}
-
-int
-spawngs(GSInfo *g, char *safer)
-{
- char *args[16];
- char tb[32], gb[32];
- int i, nargs;
- int devnull;
- int stdinout[2];
- int dataout[2];
- int errout[2];
-
- /*
- * spawn gs
- *
- * gs's standard input is fed from stdinout.
- * gs output written to fd-2 (i.e. output we generate intentionally) is fed to stdinout.
- * 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)
- return -1;
-
- nargs = 0;
- args[nargs++] = "gs";
- args[nargs++] = "-dNOPAUSE";
- args[nargs++] = safer;
- args[nargs++] = "-sDEVICE=plan9";
- args[nargs++] = "-sOutputFile=/fd/3";
- args[nargs++] = "-dQUIET";
- args[nargs++] = "-r100";
- sprint(tb, "-dTextAlphaBits=%d", textbits);
- sprint(gb, "-dGraphicsAlphaBits=%d", gfxbits);
- if(textbits)
- args[nargs++] = tb;
- if(gfxbits)
- args[nargs++] = gb;
- args[nargs++] = "-";
- args[nargs] = nil;
-
- gspid = fork();
- if(gspid == 0) {
- close(stdinout[1]);
- close(dataout[1]);
- close(errout[1]);
-
- /*
- * Horrible problem: we want to dup fd's 0-4 below,
- * but some of the source fd's might have those small numbers.
- * So we need to reallocate those. In order to not step on
- * anything else, we'll dup the fd's to higher ones using
- * dup(x, -1), but we need to use up the lower ones first.
- */
- 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);
-
- dup(stdinout[0], 0);
- dup(errout[0], 1);
- dup(devnull, 2); /* never anything useful */
- dup(dataout[0], 3);
- dup(stdinout[0], 4);
- for(i=5; i<20; i++)
- close(i);
- exec("/bin/gs", args);
- wexits("exec");
- }
- close(stdinout[0]);
- close(errout[0]);
- close(dataout[0]);
- atexit(killgs);
-
- if(teegs)
- stdinout[1] = spawnreader(stdinout[1]);
-
- gsfd = g->gsfd = stdinout[1];
- g->gsdfd = dataout[1];
- g->gspid = gspid;
-
- spawnmonitor(errout[1]);
- Binit(&g->gsrd, g->gsfd, OREAD);
-
- gscmd(g, "/PAGEOUT (/fd/4) (w) file def\n");
- gscmd(g, "/PAGE== { PAGEOUT exch write==only PAGEOUT (\\n) writestring PAGEOUT flushfile } def\n");
- waitgs(g);
-
- return 0;
-}
-
-int
-gscmd(GSInfo *gs, char *fmt, ...)
-{
- char buf[1024];
- int n;
-
- va_list v;
- va_start(v, fmt);
- n = vseprint(buf, buf+sizeof buf, fmt, v) - buf;
- if(n <= 0)
- return n;
-
- if(chatty) {
- fprint(2, "cmd: ");
- write(2, buf, n);
- }
-
- if(write(gs->gsfd, buf, n) != 0)
- return -1;
-
- return n;
-}
-
-/*
- * set the dimensions of the bitmap we expect to get back from GS.
- */
-void
-setdim(GSInfo *gs, Rectangle bbox, int ppi, int landscape)
-{
- Rectangle pbox;
-
- if(chatty)
- fprint(2, "setdim: bbox=%R\n", bbox);
-
- if(ppi)
- gs->ppi = ppi;
-
- gscmd(gs, "mark\n");
- if(ppi)
- gscmd(gs, "/HWResolution [%d %d]\n", ppi, ppi);
-
- if(!Dx(bbox))
- bbox = Rect(0, 0, 612, 792); /* 8½×11 */
-
- switch(landscape){
- case 0:
- pbox = bbox;
- break;
- case 1:
- 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");
- gscmd(gs, "/#copies 1 store\n");
-
- if(!eqpt(bbox.min, ZP))
- gscmd(gs, "%d %d translate\n", -bbox.min.x, -bbox.min.y);
-
- switch(landscape){
- case 0:
- break;
- case 1:
- gscmd(gs, "%d 0 translate\n", Dy(bbox));
- gscmd(gs, "90 rotate\n");
- break;
- }
-
- waitgs(gs);
-}
-
-void
-waitgs(GSInfo *gs)
-{
- /* we figure out that gs is done by telling it to
- * print something and waiting until it does.
- */
- char *p;
- Biobuf *b = &gs->gsrd;
- 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");
-
- alarm(300*1000);
- for(;;) {
- p = Brdline(b, '\n');
- if(p == nil) {
- n = Bbuffered(b);
- if(n <= 0)
- break;
- if(n > sizeof buf)
- n = sizeof buf;
- Bread(b, buf, n);
- continue;
- }
- p[Blinelen(b)-1] = 0;
- if(chatty) fprint(2, "p: ");
- if(chatty) write(2, p, Blinelen(b)-1);
- if(chatty) fprint(2, "\n");
- if(strstr(p, "Error:")) {
- alarm(0);
- fprint(2, "ghostscript error: %s\n", p);
- wexits("gs error");
- }
-
- if(strstr(p, "//GO.SYSIN DD")) {
- break;
- }
- }
- alarm(0);
-}
diff --git a/sys/src/cmd/page/mkfile b/sys/src/cmd/page/mkfile
deleted file mode 100644
index cbb8c9756..000000000
--- a/sys/src/cmd/page/mkfile
+++ /dev/null
@@ -1,36 +0,0 @@
-</$objtype/mkfile
-
-TARG=page
-
-HFILES=page.h
-OFILES=\
- cache.$O\
- filter.$O\
- gfx.$O\
- gs.$O\
- page.$O\
- pdf.$O\
- ps.$O\
- rotate.$O\
- util.$O\
- view.$O\
-
-LIB=/$objtype/lib/libdraw.a
-
-UPDATE=\
- mkfile\
- ${OFILES:%.$O=%.c}\
- pdfprolog.ps\
- $HFILES\
- /sys/man/1/page\
- /386/bin/page\
-
-</sys/src/cmd/mkone
-
-BIN=/$objtype/bin
-
-pdfprolog.c: pdfprolog.ps
- cat pdfprolog.ps | sed 's/.*/"&\\n"/g' >pdfprolog.c
-
-pdf.$O: pdfprolog.c
-
diff --git a/sys/src/cmd/page/nrotate.c b/sys/src/cmd/page/nrotate.c
deleted file mode 100644
index 2225ec3f1..000000000
--- a/sys/src/cmd/page/nrotate.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Rotate an image 180° in O(log Dx + log Dy)
- * draw calls, using an extra buffer the same size
- * as the image.
- *
- * The basic concept is that you can invert an array by
- * inverting the top half, inverting the bottom half, and
- * then swapping them.
- *
- * This is usually overkill, but it speeds up slow remote
- * connections quite a bit.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <draw.h>
-#include <event.h>
-#include "page.h"
-
-int ndraw = 0;
-
-enum {
- Xaxis,
- Yaxis,
-};
-
-static void reverse(Image*, Image*, int);
-static void shuffle(Image*, Image*, int, int, Image*, int, int);
-static void writefile(char *name, Image *im, int gran);
-static void halvemaskdim(Image*);
-static void swapranges(Image*, Image*, int, int, int, int);
-
-/*
- * Rotate the image 180° by reflecting first
- * along the X axis, and then along the Y axis.
- */
-void
-rot180(Image *img)
-{
- Image *tmp;
-
- tmp = xallocimage(display, img->r, img->chan, 0, DNofill);
- if(tmp == nil)
- return;
-
- reverse(img, tmp, Xaxis);
- reverse(img, tmp, Yaxis);
-
- freeimage(tmp);
-}
-
-Image *mtmp;
-
-static void
-reverse(Image *img, Image *tmp, int axis)
-{
- Image *mask;
- Rectangle r;
- int i, d;
-
- /*
- * We start by swapping large chunks at a time.
- * The chunk size should be the largest power of
- * two that fits in the dimension.
- */
- d = axis==Xaxis ? Dx(img) : Dy(img);
- for(i = 1; i*2 <= d; i *= 2)
- ;
-
- r = axis==Xaxis ? Rect(0,0, i,100) : Rect(0,0, 100,i);
- mask = xallocimage(display, r, GREY1, 1, DTransparent);
- mtmp = xallocimage(display, r, GREY1, 1, DTransparent);
-
- /*
- * Now color the bottom (or left) half of the mask opaque.
- */
- if(axis==Xaxis)
- r.max.x /= 2;
- else
- r.max.y /= 2;
-
- draw(mask, r, display->opaque, nil, ZP);
- writefile("mask", mask, i);
-
- /*
- * Shuffle will recur, shuffling the pieces as necessary
- * and making the mask a finer and finer grating.
- */
- shuffle(img, tmp, axis, d, mask, i, 0);
-
- freeimage(mask);
-}
-
-/*
- * Shuffle the image by swapping pieces of size maskdim.
- */
-static void
-shuffle(Image *img, Image *tmp, int axis, int imgdim, Image *mask, int maskdim)
-{
- int slop;
-
- if(maskdim == 0)
- return;
-
- /*
- * Figure out how much will be left over that needs to be
- * shifted specially to the bottom.
- */
- slop = imgdim % maskdim;
-
- /*
- * Swap adjacent grating lines as per mask.
- */
- swapadjacent(img, tmp, axis, imgdim - slop, mask, maskdim);
-
- /*
- * Calculate the mask with gratings half as wide and recur.
- */
- halvemaskdim(mask, maskdim, axis);
- writefile("mask", mask, maskdim/2);
-
- shuffle(img, tmp, axis, imgdim, mask, maskdim/2);
-
- /*
- * Move the slop down to the bottom of the image.
- */
- swapranges(img, tmp, 0, imgdim-slop, imgdim, axis);
- moveup(im, tmp, lastnn, nn, n, axis);
-}
-
-/*
- * Halve the grating period in the mask.
- * The grating currently looks like
- * ####____####____####____####____
- * where #### is opacity.
- *
- * We want
- * ##__##__##__##__##__##__##__##__
- * which is achieved by shifting the mask
- * and drawing on itself through itself.
- * Draw doesn't actually allow this, so
- * we have to copy it first.
- *
- * ####____####____####____####____ (dst)
- * + ____####____####____####____#### (src)
- * in __####____####____####____####__ (mask)
- * ===========================================
- * ##__##__##__##__##__##__##__##__
- */
-static void
-halvemaskdim(Image *m, int maskdim, int axis)
-{
- Point δ;
-
- δ = axis==Xaxis ? Pt(maskdim,0) : Pt(0,maskdim);
- draw(mtmp, mtmp->r, mask, nil, mask->r.min);
- gendraw(mask, mask->r, mtmp, δ, mtmp, divpt(δ,2));
- writefile("mask", mask, maskdim/2);
-}
-
-/*
- * Swap the regions [a,b] and [b,c]
- */
-static void
-swapranges(Image *img, Image *tmp, int a, int b, int c, int axis)
-{
- Rectangle r;
- Point δ;
-
- if(a == b || b == c)
- return;
-
- writefile("swap", img, 0);
- draw(tmp, tmp->r, im, nil, im->r.min);
-
- /* [a,a+(c-b)] gets [b,c] */
- r = img->r;
- if(axis==Xaxis){
- δ = Pt(1,0);
- r.min.x = img->r.min.x + a;
- r.max.x = img->r.min.x + a + (c-b);
- }else{
- δ = Pt(0,1);
- r.min.y = img->r.min.y + a;
- r.max.y = img->r.min.y + a + (c-b);
- }
- draw(img, r, tmp, nil, addpt(tmp->r.min, mulpt(δ, b)));
-
- /* [a+(c-b), c] gets [a,b] */
- r = img->r;
- if(axis==Xaxis){
- r.min.x = img->r.min.x + a + (c-b);
- r.max.x = img->r.min.x + c;
- }else{
- r.min.y = img->r.min.y + a + (c-b);
- r.max.y = img->r.min.y + c;
- }
- draw(img, r, tmp, nil, addpt(tmp->r.min, mulpt(δ, a)));
- writefile("swap", img, 1);
-}
-
-/*
- * Swap adjacent regions as specified by the grating.
- * We do this by copying the image through the mask twice,
- * once aligned with the grading and once 180° out of phase.
- */
-static void
-swapadjacent(Image *img, Image *tmp, int axis, int imgdim, Image *mask, int maskdim)
-{
- Point δ;
- Rectangle r0, r1;
-
- δ = axis==Xaxis ? Pt(1,0) : Pt(0,1);
-
- r0 = img->r;
- r1 = img->r;
- switch(axis){
- case Xaxis:
- r0.max.x = imgdim;
- r1.min.x = imgdim;
- break;
- case Yaxis:
- r0.max.y = imgdim;
- r1.min.y = imgdim;
- }
-
- /*
- * r0 is the lower rectangle, while r1 is the upper one.
- */
- draw(tmp, tmp->r, img, nil,
-}
-
-void
-interlace(Image *im, Image *tmp, int axis, int n, Image *mask, int gran)
-{
- Point p0, p1;
- Rectangle r0, r1;
-
- r0 = im->r;
- r1 = im->r;
- switch(axis) {
- case Xaxis:
- r0.max.x = n;
- r1.min.x = n;
- p0 = (Point){gran, 0};
- p1 = (Point){-gran, 0};
- break;
- case Yaxis:
- r0.max.y = n;
- r1.min.y = n;
- p0 = (Point){0, gran};
- p1 = (Point){0, -gran};
- break;
- }
-
- draw(tmp, im->r, im, display->black, im->r.min);
- gendraw(im, r0, tmp, p0, mask, mask->r.min);
- gendraw(im, r0, tmp, p1, mask, p1);
-}
-
-
-static void
-writefile(char *name, Image *im, int gran)
-{
- static int c = 100;
- int fd;
- char buf[200];
-
- snprint(buf, sizeof buf, "%d%s%d", c++, name, gran);
- fd = create(buf, OWRITE, 0666);
- if(fd < 0)
- return;
- writeimage(fd, im, 0);
- close(fd);
-}
-
diff --git a/sys/src/cmd/page/page.c b/sys/src/cmd/page/page.c
deleted file mode 100644
index 85e55586c..000000000
--- a/sys/src/cmd/page/page.c
+++ /dev/null
@@ -1,238 +0,0 @@
-#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*, char *x)
-{
- 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");
- exits(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);
- }
-
- quotefmtinstall();
- fmtinstall('a', afmt);
-
- fmtinstall('R', Rfmt);
- fmtinstall('P', Pfmt);
- if(mknewwindow)
- newwin();
-
- 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");
- }
- display->locking = 1;
-
- 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);
-}
diff --git a/sys/src/cmd/page/page.h b/sys/src/cmd/page/page.h
deleted file mode 100644
index ac66df6b1..000000000
--- a/sys/src/cmd/page/page.h
+++ /dev/null
@@ -1,85 +0,0 @@
-typedef struct Document Document;
-
-struct Document {
- char *docname;
- int npage;
- int fwdonly;
- char* (*pagename)(Document*, int);
- Image* (*drawpage)(Document*, int);
- int (*addpage)(Document*, char*);
- int (*rmpage)(Document*, int);
- Biobuf *b;
- void *extra;
-};
-
-void *emalloc(int);
-void *erealloc(void*, int);
-char *estrdup(char*);
-int spawncmd(char*, char **, int, int, int);
-
-int spooltodisk(uchar*, int, char**);
-int stdinpipe(uchar*, int);
-Document *initps(Biobuf*, int, char**, uchar*, int);
-Document *initpdf(Biobuf*, int, char**, uchar*, int);
-Document *initgfx(Biobuf*, int, char**, uchar*, int);
-Document *inittroff(Biobuf*, int, char**, uchar*, int);
-Document *initdvi(Biobuf*, int, char**, uchar*, int);
-Document *initmsdoc(Biobuf*, int, char**, uchar*, int);
-
-void viewer(Document*);
-extern Cursor reading;
-extern int chatty;
-extern int goodps;
-extern int textbits, gfxbits;
-extern int reverse;
-extern int clean;
-extern int ppi;
-extern int teegs;
-extern int truetoboundingbox;
-extern int wctlfd;
-extern int resizing;
-extern int mknewwindow;
-
-void rot180(Image*);
-Image *rot90(Image*);
-Image *rot270(Image*);
-Image *resample(Image*, Image*);
-
-/* ghostscript interface shared by ps, pdf */
-typedef struct GSInfo GSInfo;
-struct GSInfo {
- int gsfd;
- Biobuf gsrd;
- int gspid;
- int gsdfd;
- int ppi;
-};
-void waitgs(GSInfo*);
-int gscmd(GSInfo*, char*, ...);
-int spawngs(GSInfo*, char*);
-void setdim(GSInfo*, Rectangle, int, int);
-int spawnwriter(GSInfo*, Biobuf*);
-Rectangle screenrect(void);
-void newwin(void);
-void zerox(void);
-Rectangle winrect(void);
-void resize(int, int);
-int max(int, int);
-int min(int, int);
-void wexits(char*);
-Image* xallocimage(Display*, Rectangle, ulong, int, ulong);
-int bell(void*, char*);
-int opentemp(char *template);
-Image* cachedpage(Document*, int, int);
-void cacheflush(void);
-
-extern int stdinfd;
-extern int truecolor;
-
-/* BUG BUG BUG BUG BUG: cannot use new draw operations in drawterm,
- * or in vncs, and there is a bug in the kernel for copying images
- * from cpu memory -> video memory (memmove is not being used).
- * until all that is settled, ignore the draw operators.
- */
-#define drawop(a,b,c,d,e,f) draw(a,b,c,d,e)
-#define gendrawop(a,b,c,d,e,f,g) gendraw(a,b,c,d,e,f)
diff --git a/sys/src/cmd/page/pdf.c b/sys/src/cmd/page/pdf.c
deleted file mode 100644
index 5261eab59..000000000
--- a/sys/src/cmd/page/pdf.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * pdf.c
- *
- * pdf file support for page
- */
-
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-#include <bio.h>
-#include "page.h"
-
-typedef struct PDFInfo PDFInfo;
-struct PDFInfo {
- GSInfo;
- Rectangle *pagebbox;
-};
-
-static Image* pdfdrawpage(Document *d, int page);
-static char* pdfpagename(Document*, int);
-
-char *pdfprolog =
-#include "pdfprolog.c"
- ;
-
-Rectangle
-pdfbbox(GSInfo *gs)
-{
- char *p;
- char *f[4];
- Rectangle r;
-
- r = Rect(0,0,0,0);
- waitgs(gs);
- gscmd(gs, "/CropBox knownoget {} {[0 0 0 0]} ifelse PAGE==\n");
- p = Brdline(&gs->gsrd, '\n');
- p[Blinelen(&gs->gsrd)-1] ='\0';
- if(p[0] != '[')
- return r;
- if(tokenize(p+1, f, 4) != 4)
- return r;
- r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3]));
- waitgs(gs);
- return r;
-}
-
-Document*
-initpdf(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
-{
- Document *d;
- PDFInfo *pdf;
- char *p;
- char *fn;
- char fdbuf[20];
- int fd;
- int i, npage;
- Rectangle bbox;
-
- if(argc > 1) {
- fprint(2, "can only view one pdf file at a time\n");
- return nil;
- }
-
- 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);
- b = Bopen(fdbuf, OREAD);
- if(b == nil){
- fprint(2, "cannot open disk spool file\n");
- wexits("Bopen temp");
- }
- }else
- fn = argv[0];
-
- /* sanity check */
- Bseek(b, 0, 0);
- if(!(p = Brdline(b, '\n')) && !(p = Brdline(b, '\r'))) {
- fprint(2, "cannot find end of first line\n");
- wexits("initps");
- }
- if(strncmp(p, "%PDF-", 5) != 0) {
- werrstr("not pdf");
- return nil;
- }
-
- /* setup structures so one free suffices */
- p = emalloc(sizeof(*d) + sizeof(*pdf));
- d = (Document*) p;
- p += sizeof(*d);
- pdf = (PDFInfo*) p;
-
- d->extra = pdf;
- d->b = b;
- d->drawpage = pdfdrawpage;
- d->pagename = pdfpagename;
- d->fwdonly = 0;
-
- if(spawngs(pdf, "-dDELAYSAFER") < 0)
- return nil;
-
- gscmd(pdf, "%s", pdfprolog);
- waitgs(pdf);
-
- setdim(pdf, Rect(0,0,0,0), ppi, 0);
- gscmd(pdf, "(%s) (r) file { DELAYSAFER { .setsafe } if } stopped pop pdfopen begin\n", fn);
- gscmd(pdf, "pdfpagecount PAGE==\n");
- p = Brdline(&pdf->gsrd, '\n');
- npage = atoi(p);
- if(npage < 1) {
- fprint(2, "no pages?\n");
- return nil;
- }
- d->npage = npage;
- d->docname = argv[0];
-
- gscmd(pdf, "Trailer\n");
- bbox = pdfbbox(pdf);
-
- pdf->pagebbox = emalloc(sizeof(Rectangle)*npage);
- for(i=0; i<npage; i++) {
- gscmd(pdf, "%d pdfgetpage\n", i+1);
- pdf->pagebbox[i] = pdfbbox(pdf);
- if(Dx(pdf->pagebbox[i]) <= 0)
- pdf->pagebbox[i] = bbox;
- }
- return d;
-}
-
-static Image*
-pdfdrawpage(Document *doc, int page)
-{
- PDFInfo *pdf = doc->extra;
- Image *im;
-
- gscmd(pdf, "%d DoPDFPage\n", page+1);
- im = readimage(display, pdf->gsdfd, 0);
- if(im == nil) {
- fprint(2, "fatal: readimage error %r\n");
- wexits("readimage");
- }
- waitgs(pdf);
- return im;
-}
-
-static char*
-pdfpagename(Document*, int page)
-{
- static char str[15];
- sprint(str, "p %d", page+1);
- return str;
-}
diff --git a/sys/src/cmd/page/pdfprolog.ps b/sys/src/cmd/page/pdfprolog.ps
deleted file mode 100644
index 681e0587a..000000000
--- a/sys/src/cmd/page/pdfprolog.ps
+++ /dev/null
@@ -1,20 +0,0 @@
-/Page null def
-/Page# 0 def
-/PDFSave null def
-/DSCPageCount 0 def
-/DoPDFPage {dup /Page# exch store pdfgetpage pdfshowpage } def
-
-/pdfshowpage_mysetpage { % <pagedict> pdfshowpage_mysetpage <pagedict>
- dup /CropBox pget {
- boxrect
- 2 array astore /PageSize exch 4 2 roll
- 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
-
-GS_PDF_ProcSet begin
-pdfdict begin
diff --git a/sys/src/cmd/page/ps.c b/sys/src/cmd/page/ps.c
deleted file mode 100644
index f1e4cbf93..000000000
--- a/sys/src/cmd/page/ps.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * ps.c
- *
- * provide postscript file reading support for page
- */
-
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-#include <bio.h>
-#include <ctype.h>
-#include "page.h"
-
-typedef struct PSInfo PSInfo;
-typedef struct Page Page;
-
-struct Page {
- char *name;
- int offset; /* offset of page beginning within file */
-};
-
-struct PSInfo {
- GSInfo;
- Rectangle bbox; /* default bounding box */
- Page *page;
- int npage;
- int clueless; /* don't know where page boundaries are */
- long psoff; /* location of %! in file */
- char ctm[256];
-};
-
-static int pswritepage(Document *d, int fd, int page);
-static Image* psdrawpage(Document *d, int page);
-static char* pspagename(Document*, int);
-
-#define R(r) (r).min.x, (r).min.y, (r).max.x, (r).max.y
-Rectangle
-rdbbox(char *p)
-{
- Rectangle r;
- int a;
- char *f[4];
- while(*p == ':' || *p == ' ' || *p == '\t')
- p++;
- if(tokenize(p, f, 4) != 4)
- return Rect(0,0,0,0);
- r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3]));
- r = canonrect(r);
- if(Dx(r) <= 0 || Dy(r) <= 0)
- return Rect(0,0,0,0);
-
- if(truetoboundingbox)
- return r;
-
- /* initdraw not called yet, can't use %R */
- if(chatty) fprint(2, "[%d %d %d %d] -> ", R(r));
- /*
- * attempt to sniff out A4, 8½×11, others
- * A4 is 596×842
- * 8½×11 is 612×792
- */
-
- a = Dx(r)*Dy(r);
- if(a < 300*300){ /* really small, probably supposed to be */
- /* empty */
- } else if(Dx(r) <= 596 && r.max.x <= 596 && Dy(r) > 792 && Dy(r) <= 842 && r.max.y <= 842) /* A4 */
- r = Rect(0, 0, 596, 842);
- else { /* cast up to 8½×11 */
- if(Dx(r) <= 612 && r.max.x <= 612){
- r.min.x = 0;
- r.max.x = 612;
- }
- if(Dy(r) <= 792 && r.max.y <= 792){
- r.min.y = 0;
- r.max.y = 792;
- }
- }
- if(chatty) fprint(2, "[%d %d %d %d]\n", R(r));
- return r;
-}
-
-#define RECT(X) X.min.x, X.min.y, X.max.x, X.max.y
-
-int
-prefix(char *x, char *y)
-{
- return strncmp(x, y, strlen(y)) == 0;
-}
-
-/*
- * document ps is really being printed as n-up pages.
- * we need to treat every n pages as 1.
- */
-void
-repaginate(PSInfo *ps, int n)
-{
- int i, np, onp;
- Page *page;
-
- page = ps->page;
- onp = ps->npage;
- np = (ps->npage+n-1)/n;
-
- if(chatty) {
- for(i=0; i<=onp+1; i++)
- print("page %d: %d\n", i, page[i].offset);
- }
-
- for(i=0; i<np; i++)
- page[i] = page[n*i];
-
- /* trailer */
- page[np] = page[onp];
-
- /* EOF */
- page[np+1] = page[onp+1];
-
- ps->npage = np;
-
- if(chatty) {
- for(i=0; i<=np+1; i++)
- print("page %d: %d\n", i, page[i].offset);
- }
-
-}
-
-Document*
-initps(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
-{
- Document *d;
- PSInfo *ps;
- char *p;
- char *q, *r;
- char eol;
- char *nargv[1];
- char fdbuf[20];
- char tmp[32];
- int fd;
- int i;
- int incomments;
- int cantranslate;
- int trailer=0;
- int nesting=0;
- int dumb=0;
- int landscape=0;
- long psoff;
- long npage, mpage;
- Page *page;
- Rectangle bbox = Rect(0,0,0,0);
-
- if(argc > 1) {
- fprint(2, "can only view one ps file at a time\n");
- return nil;
- }
-
- 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);
- b = Bopen(fdbuf, OREAD);
- if(b == nil){
- fprint(2, "cannot open disk spool file\n");
- wexits("Bopen temp");
- }
- nargv[0] = fdbuf;
- argv = nargv;
- }
-
- /* find %!, perhaps after PCL nonsense */
- Bseek(b, 0, 0);
- psoff = 0;
- eol = 0;
- for(i=0; i<16; i++){
- psoff = Boffset(b);
- if(!(p = Brdline(b, eol='\n')) && !(p = Brdline(b, eol='\r'))) {
- fprint(2, "cannot find end of first line\n");
- wexits("initps");
- }
- if(p[0]=='\x1B')
- p++, psoff++;
- if(p[0] == '%' && p[1] == '!')
- break;
- }
- if(i == 16){
- werrstr("not ps");
- return nil;
- }
-
- /* page counting */
- npage = 0;
- mpage = 16;
- page = emalloc(mpage*sizeof(*page));
- memset(page, 0, mpage*sizeof(*page));
-
- cantranslate = goodps;
- incomments = 1;
-Keepreading:
- while(p = Brdline(b, eol)) {
- if(p[0] == '%')
- if(chatty > 1) fprint(2, "ps %.*s\n", utfnlen(p, Blinelen(b)-1), p);
- if(npage == mpage) {
- mpage *= 2;
- page = erealloc(page, mpage*sizeof(*page));
- memset(&page[npage], 0, npage*sizeof(*page));
- }
-
- if(p[0] != '%' || p[1] != '%')
- continue;
-
- if(prefix(p, "%%BeginDocument")) {
- nesting++;
- continue;
- }
- if(nesting > 0 && prefix(p, "%%EndDocument")) {
- nesting--;
- continue;
- }
- if(nesting)
- continue;
-
- if(prefix(p, "%%EndComment")) {
- incomments = 0;
- continue;
- }
- if(reverse == -1 && prefix(p, "%%PageOrder")) {
- /* glean whether we should reverse the viewing order */
- p[Blinelen(b)-1] = 0;
- if(strstr(p, "Ascend"))
- reverse = 0;
- else if(strstr(p, "Descend"))
- reverse = 1;
- else if(strstr(p, "Special"))
- dumb = 1;
- p[Blinelen(b)-1] = '\n';
- continue;
- } else if(prefix(p, "%%Trailer")) {
- incomments = 1;
- page[npage].offset = Boffset(b)-Blinelen(b);
- trailer = 1;
- continue;
- } else if(incomments && prefix(p, "%%Orientation")) {
- if(strstr(p, "Landscape"))
- landscape = 1;
- } else if(incomments && Dx(bbox)==0 && prefix(p, q="%%BoundingBox")) {
- bbox = rdbbox(p+strlen(q)+1);
- if(chatty)
- /* can't use %R because haven't initdraw() */
- fprint(2, "document bbox [%d %d %d %d]\n",
- RECT(bbox));
- continue;
- }
-
- /*
- * If they use the initgraphics command, we can't play our translation tricks.
- */
- p[Blinelen(b)-1] = 0;
- if((q=strstr(p, "initgraphics")) && ((r=strchr(p, '%'))==nil || r > q))
- cantranslate = 0;
- p[Blinelen(b)-1] = eol;
-
- if(!prefix(p, "%%Page:"))
- continue;
-
- /*
- * figure out of the %%Page: line contains a page number
- * or some other page description to use in the menu bar.
- *
- * lines look like %%Page: x y or %%Page: x
- * we prefer just x, and will generate our
- * own if necessary.
- */
- p[Blinelen(b)-1] = 0;
- if(chatty) fprint(2, "page %s\n", p);
- r = p+7;
- while(*r == ' ' || *r == '\t')
- r++;
- q = r;
- while(*q && *q != ' ' && *q != '\t')
- q++;
- free(page[npage].name);
- if(*r) {
- if(*r == '"' && *q == '"')
- r++, q--;
- if(*q)
- *q = 0;
- page[npage].name = estrdup(r);
- *q = 'x';
- } else {
- snprint(tmp, sizeof tmp, "p %ld", npage+1);
- page[npage].name = estrdup(tmp);
- }
-
- /*
- * store the offset info for later viewing
- */
- trailer = 0;
- p[Blinelen(b)-1] = eol;
- page[npage++].offset = Boffset(b)-Blinelen(b);
- }
- if(Blinelen(b) > 0){
- fprint(2, "page: linelen %d\n", Blinelen(b));
- Bseek(b, Blinelen(b), 1);
- goto Keepreading;
- }
-
- if(Dx(bbox) == 0 || Dy(bbox) == 0)
- bbox = Rect(0,0,612,792); /* 8½×11 */
- /*
- * if we didn't find any pages, assume the document
- * is one big page
- */
- if(npage == 0) {
- dumb = 1;
- if(chatty) fprint(2, "don't know where pages are\n");
- reverse = 0;
- goodps = 0;
- trailer = 0;
- page[npage].name = "p 1";
- page[npage++].offset = 0;
- }
-
- if(npage+2 > mpage) {
- mpage += 2;
- page = erealloc(page, mpage*sizeof(*page));
- memset(&page[mpage-2], 0, 2*sizeof(*page));
- }
-
- if(!trailer)
- page[npage].offset = Boffset(b);
-
- Bseek(b, 0, 2); /* EOF */
- page[npage+1].offset = Boffset(b);
-
- d = emalloc(sizeof(*d));
- ps = emalloc(sizeof(*ps));
- ps->page = page;
- ps->npage = npage;
- ps->bbox = bbox;
- ps->psoff = psoff;
-
- d->extra = ps;
- d->npage = ps->npage;
- d->b = b;
- d->drawpage = psdrawpage;
- d->pagename = pspagename;
-
- d->fwdonly = ps->clueless = dumb;
- d->docname = argv[0];
-
- if(spawngs(ps, "-dSAFER") < 0)
- return nil;
-
- if(!cantranslate)
- bbox.min = ZP;
- setdim(ps, bbox, ppi, landscape);
-
- if(goodps){
- /*
- * We want to only send the page (i.e. not header and trailer) information
- * for each page, so initialize the device by sending the header now.
- */
- pswritepage(d, ps->gsfd, -1);
- waitgs(ps);
- }
-
- if(dumb) {
- fprint(ps->gsfd, "(%s) run\n", argv[0]);
- fprint(ps->gsfd, "(/fd/3) (w) file dup (THIS IS NOT A PLAN9 BITMAP 01234567890123456789012345678901234567890123456789\\n) writestring flushfile\n");
- }
-
- ps->bbox = bbox;
-
- return d;
-}
-
-static int
-pswritepage(Document *d, int fd, int page)
-{
- Biobuf *b = d->b;
- PSInfo *ps = d->extra;
- int t, n, i;
- long begin, end;
- char buf[8192];
-
- if(page == -1)
- begin = ps->psoff;
- else
- begin = ps->page[page].offset;
-
- end = ps->page[page+1].offset;
-
- if(chatty) {
- fprint(2, "writepage(%d)... from #%ld to #%ld...\n",
- page, begin, end);
- }
- Bseek(b, begin, 0);
-
- t = end-begin;
- n = sizeof(buf);
- if(n > t) n = t;
- while(t > 0 && (i=Bread(b, buf, n)) > 0) {
- if(write(fd, buf, i) != i)
- return -1;
- t -= i;
- if(n > t)
- n = t;
- }
- return end-begin;
-}
-
-static Image*
-psdrawpage(Document *d, int page)
-{
- PSInfo *ps = d->extra;
- Image *im;
-
- if(ps->clueless)
- return readimage(display, ps->gsdfd, 0);
-
- waitgs(ps);
-
- if(goodps)
- pswritepage(d, ps->gsfd, page);
- else {
- pswritepage(d, ps->gsfd, -1);
- pswritepage(d, ps->gsfd, page);
- pswritepage(d, ps->gsfd, d->npage);
- }
- /*
- * If last line terminator is \r, gs will read ahead to check for \n
- * so send one to avoid deadlock.
- */
- write(ps->gsfd, "\n", 1);
- im = readimage(display, ps->gsdfd, 0);
- if(im == nil) {
- fprint(2, "fatal: readimage error %r\n");
- wexits("readimage");
- }
- waitgs(ps);
-
- return im;
-}
-
-static char*
-pspagename(Document *d, int page)
-{
- PSInfo *ps = (PSInfo *) d->extra;
- return ps->page[page].name;
-}
diff --git a/sys/src/cmd/page/rotate.c b/sys/src/cmd/page/rotate.c
deleted file mode 100644
index 7f4083e8a..000000000
--- a/sys/src/cmd/page/rotate.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * rotate an image 180° in O(log Dx + log Dy) /dev/draw writes,
- * using an extra buffer same size as the image.
- *
- * the basic concept is that you can invert an array by inverting
- * the top half, inverting the bottom half, and then swapping them.
- * the code does this slightly backwards to ensure O(log n) runtime.
- * (If you do it wrong, you can get O(log² n) runtime.)
- *
- * This is usually overkill, but it speeds up slow remote
- * connections quite a bit.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <draw.h>
-#include <event.h>
-#include "page.h"
-
-int ndraw = 0;
-enum {
- Xaxis = 0,
- Yaxis = 1,
-};
-
-Image *mtmp;
-
-void
-writefile(char *name, Image *im, int gran)
-{
- static int c = 100;
- int fd;
- char buf[200];
-
- snprint(buf, sizeof buf, "%d%s%d", c++, name, gran);
- fd = create(buf, OWRITE, 0666);
- if(fd < 0)
- return;
- writeimage(fd, im, 0);
- close(fd);
-}
-
-void
-moveup(Image *im, Image *tmp, int a, int b, int c, int axis)
-{
- Rectangle range;
- Rectangle dr0, dr1;
- Point p0, p1;
-
- if(a == b || b == c)
- return;
-
- drawop(tmp, tmp->r, im, nil, im->r.min, S);
-
- switch(axis){
- case Xaxis:
- range = Rect(a, im->r.min.y, c, im->r.max.y);
- dr0 = range;
- dr0.max.x = dr0.min.x+(c-b);
- p0 = Pt(b, im->r.min.y);
-
- dr1 = range;
- dr1.min.x = dr1.max.x-(b-a);
- p1 = Pt(a, im->r.min.y);
- break;
- case Yaxis:
- range = Rect(im->r.min.x, a, im->r.max.x, c);
- dr0 = range;
- dr0.max.y = dr0.min.y+(c-b);
- p0 = Pt(im->r.min.x, b);
-
- dr1 = range;
- dr1.min.y = dr1.max.y-(b-a);
- p1 = Pt(im->r.min.x, a);
- break;
- }
- drawop(im, dr0, tmp, nil, p0, S);
- drawop(im, dr1, tmp, nil, p1, S);
-}
-
-void
-interlace(Image *im, Image *tmp, int axis, int n, Image *mask, int gran)
-{
- Point p0, p1;
- Rectangle r0, r1;
-
- r0 = im->r;
- r1 = im->r;
- switch(axis) {
- case Xaxis:
- r0.max.x = n;
- r1.min.x = n;
- p0 = (Point){gran, 0};
- p1 = (Point){-gran, 0};
- break;
- case Yaxis:
- r0.max.y = n;
- r1.min.y = n;
- p0 = (Point){0, gran};
- p1 = (Point){0, -gran};
- break;
- }
-
- drawop(tmp, im->r, im, display->opaque, im->r.min, S);
- gendrawop(im, r0, tmp, p0, mask, mask->r.min, S);
- gendrawop(im, r0, tmp, p1, mask, p1, S);
-}
-
-/*
- * Halve the grating period in the mask.
- * The grating currently looks like
- * ####____####____####____####____
- * where #### is opacity.
- *
- * We want
- * ##__##__##__##__##__##__##__##__
- * which is achieved by shifting the mask
- * and drawing on itself through itself.
- * Draw doesn't actually allow this, so
- * we have to copy it first.
- *
- * ####____####____####____####____ (dst)
- * + ____####____####____####____#### (src)
- * in __####____####____####____####__ (mask)
- * ===========================================
- * ##__##__##__##__##__##__##__##__
- */
-int
-nextmask(Image *mask, int axis, int maskdim)
-{
- Point δ;
-
- δ = axis==Xaxis ? Pt(maskdim,0) : Pt(0,maskdim);
- drawop(mtmp, mtmp->r, mask, nil, mask->r.min, S);
- gendrawop(mask, mask->r, mtmp, δ, mtmp, divpt(δ,-2), S);
-// writefile("mask", mask, maskdim/2);
- return maskdim/2;
-}
-
-void
-shuffle(Image *im, Image *tmp, int axis, int n, Image *mask, int gran,
- int lastnn)
-{
- int nn, left;
-
- if(gran == 0)
- return;
- left = n%(2*gran);
- nn = n - left;
-
- interlace(im, tmp, axis, nn, mask, gran);
-// writefile("interlace", im, gran);
-
- gran = nextmask(mask, axis, gran);
- shuffle(im, tmp, axis, n, mask, gran, nn);
-// writefile("shuffle", im, gran);
- moveup(im, tmp, lastnn, nn, n, axis);
-// writefile("move", im, gran);
-}
-
-void
-rot180(Image *im)
-{
- Image *tmp, *tmp0;
- Image *mask;
- Rectangle rmask;
- int gran;
-
- if(chantodepth(im->chan) < 8){
- /* this speeds things up dramatically; draw is too slow on sub-byte pixel sizes */
- tmp0 = xallocimage(display, im->r, CMAP8, 0, DNofill);
- drawop(tmp0, tmp0->r, im, nil, im->r.min, S);
- }else
- tmp0 = im;
-
- tmp = xallocimage(display, tmp0->r, tmp0->chan, 0, DNofill);
- if(tmp == nil){
- if(tmp0 != im)
- freeimage(tmp0);
- return;
- }
- for(gran=1; gran<Dx(im->r); gran *= 2)
- ;
- gran /= 4;
-
- rmask.min = ZP;
- rmask.max = (Point){2*gran, 100};
-
- mask = xallocimage(display, rmask, GREY1, 1, DTransparent);
- mtmp = xallocimage(display, rmask, GREY1, 1, DTransparent);
- if(mask == nil || mtmp == nil) {
- fprint(2, "out of memory during rot180: %r\n");
- wexits("memory");
- }
- rmask.max.x = gran;
- drawop(mask, rmask, display->opaque, nil, ZP, S);
-// writefile("mask", mask, gran);
- shuffle(im, tmp, Xaxis, Dx(im->r), mask, gran, 0);
- freeimage(mask);
- freeimage(mtmp);
-
- for(gran=1; gran<Dy(im->r); gran *= 2)
- ;
- gran /= 4;
- rmask.max = (Point){100, 2*gran};
- mask = xallocimage(display, rmask, GREY1, 1, DTransparent);
- mtmp = xallocimage(display, rmask, GREY1, 1, DTransparent);
- if(mask == nil || mtmp == nil) {
- fprint(2, "out of memory during rot180: %r\n");
- wexits("memory");
- }
- rmask.max.y = gran;
- drawop(mask, rmask, display->opaque, nil, ZP, S);
- shuffle(im, tmp, Yaxis, Dy(im->r), mask, gran, 0);
- freeimage(mask);
- freeimage(mtmp);
- freeimage(tmp);
- if(tmp0 != im)
- freeimage(tmp0);
-}
-
-/* rotates an image 90 degrees clockwise */
-Image *
-rot90(Image *im)
-{
- Image *tmp;
- int i, j, dx, dy;
-
- dx = Dx(im->r);
- dy = Dy(im->r);
- tmp = xallocimage(display, Rect(0, 0, dy, dx), im->chan, 0, DCyan);
- if(tmp == nil) {
- fprint(2, "out of memory during rot90: %r\n");
- wexits("memory");
- }
-
- for(j = 0; j < dx; j++) {
- for(i = 0; i < dy; i++) {
- drawop(tmp, Rect(i, j, i+1, j+1), im, nil, Pt(j, dy-(i+1)), S);
- }
- }
- freeimage(im);
-
- return(tmp);
-}
-
-/* rotates an image 270 degrees clockwise */
-Image *
-rot270(Image *im)
-{
- Image *tmp;
- int i, j, dx, dy;
-
- dx = Dx(im->r);
- dy = Dy(im->r);
- tmp = xallocimage(display, Rect(0, 0, dy, dx), im->chan, 0, DCyan);
- if(tmp == nil) {
- fprint(2, "out of memory during rot270: %r\n");
- wexits("memory");
- }
-
- for(i = 0; i < dy; i++) {
- for(j = 0; j < dx; j++) {
- drawop(tmp, Rect(i, j, i+1, j+1), im, nil, Pt(dx-(j+1), i), S);
- }
- }
- freeimage(im);
-
- return(tmp);
-}
-
-/* from resample.c -- resize from → to using interpolation */
-
-
-#define K2 7 /* from -.7 to +.7 inclusive, meaning .2 into each adjacent pixel */
-#define NK (2*K2+1)
-double K[NK];
-
-double
-fac(int L)
-{
- int i, f;
-
- f = 1;
- for(i=L; i>1; --i)
- f *= i;
- return f;
-}
-
-/*
- * i0(x) is the modified Bessel function, Σ (x/2)^2L / (L!)²
- * There are faster ways to calculate this, but we precompute
- * into a table so let's keep it simple.
- */
-double
-i0(double x)
-{
- double v;
- int L;
-
- v = 1.0;
- for(L=1; L<10; L++)
- v += pow(x/2., 2*L)/pow(fac(L), 2);
- return v;
-}
-
-double
-kaiser(double x, double τ, double α)
-{
- if(fabs(x) > τ)
- return 0.;
- return i0(α*sqrt(1-(x*x/(τ*τ))))/i0(α);
-}
-
-
-void
-resamplex(uchar *in, int off, int d, int inx, uchar *out, int outx)
-{
- int i, x, k;
- double X, xx, v, rat;
-
-
- rat = (double)inx/(double)outx;
- for(x=0; x<outx; x++){
- if(inx == outx){
- /* don't resample if size unchanged */
- out[off+x*d] = in[off+x*d];
- continue;
- }
- v = 0.0;
- X = x*rat;
- for(k=-K2; k<=K2; k++){
- xx = X + rat*k/10.;
- i = xx;
- if(i < 0)
- i = 0;
- if(i >= inx)
- i = inx-1;
- v += in[off+i*d] * K[K2+k];
- }
- out[off+x*d] = v;
- }
-}
-
-void
-resampley(uchar **in, int off, int iny, uchar **out, int outy)
-{
- int y, i, k;
- double Y, yy, v, rat;
-
- rat = (double)iny/(double)outy;
- for(y=0; y<outy; y++){
- if(iny == outy){
- /* don't resample if size unchanged */
- out[y][off] = in[y][off];
- continue;
- }
- v = 0.0;
- Y = y*rat;
- for(k=-K2; k<=K2; k++){
- yy = Y + rat*k/10.;
- i = yy;
- if(i < 0)
- i = 0;
- if(i >= iny)
- i = iny-1;
- v += in[i][off] * K[K2+k];
- }
- out[y][off] = v;
- }
-
-}
-
-Image*
-resample(Image *from, Image *to)
-{
- int i, j, bpl, nchan;
- uchar **oscan, **nscan;
- char tmp[20];
- int xsize, ysize;
- double v;
- Image *t1, *t2;
- ulong tchan;
-
- for(i=-K2; i<=K2; i++){
- K[K2+i] = kaiser(i/10., K2/10., 4.);
- }
-
- /* normalize */
- v = 0.0;
- for(i=0; i<NK; i++)
- v += K[i];
- for(i=0; i<NK; i++)
- K[i] /= v;
-
- switch(from->chan){
- case GREY8:
- case RGB24:
- case RGBA32:
- case ARGB32:
- case XRGB32:
- break;
-
- case CMAP8:
- case RGB15:
- case RGB16:
- tchan = RGB24;
- goto Convert;
-
- case GREY1:
- case GREY2:
- case GREY4:
- tchan = GREY8;
- Convert:
- /* use library to convert to byte-per-chan form, then convert back */
- t1 = xallocimage(display, Rect(0, 0, Dx(from->r), Dy(from->r)), tchan, 0, DNofill);
- if(t1 == nil) {
- fprint(2, "out of memory for temp image 1 in resample: %r\n");
- wexits("memory");
- }
- drawop(t1, t1->r, from, nil, ZP, S);
- t2 = xallocimage(display, to->r, tchan, 0, DNofill);
- if(t2 == nil) {
- fprint(2, "out of memory temp image 2 in resample: %r\n");
- wexits("memory");
- }
- resample(t1, t2);
- drawop(to, to->r, t2, nil, ZP, S);
- freeimage(t1);
- freeimage(t2);
- return to;
-
- default:
- sysfatal("can't handle channel type %s", chantostr(tmp, from->chan));
- }
-
- xsize = Dx(to->r);
- ysize = Dy(to->r);
- oscan = malloc(Dy(from->r)*sizeof(uchar*));
- nscan = malloc(max(ysize, Dy(from->r))*sizeof(uchar*));
- if(oscan == nil || nscan == nil)
- sysfatal("can't allocate: %r");
-
- /* unload original image into scan lines */
- bpl = bytesperline(from->r, from->depth);
- for(i=0; i<Dy(from->r); i++){
- oscan[i] = malloc(bpl);
- if(oscan[i] == nil)
- sysfatal("can't allocate: %r");
- j = unloadimage(from, Rect(from->r.min.x, from->r.min.y+i, from->r.max.x, from->r.min.y+i+1), oscan[i], bpl);
- if(j != bpl)
- sysfatal("unloadimage");
- }
-
- /* allocate scan lines for destination. we do y first, so need at least Dy(from->r) lines */
- bpl = bytesperline(Rect(0, 0, xsize, Dy(from->r)), from->depth);
- for(i=0; i<max(ysize, Dy(from->r)); i++){
- nscan[i] = malloc(bpl);
- if(nscan[i] == nil)
- sysfatal("can't allocate: %r");
- }
-
- /* resample in X */
- nchan = from->depth/8;
- for(i=0; i<Dy(from->r); i++){
- for(j=0; j<nchan; j++){
- if(j==0 && from->chan==XRGB32)
- continue;
- resamplex(oscan[i], j, nchan, Dx(from->r), nscan[i], xsize);
- }
- free(oscan[i]);
- oscan[i] = nscan[i];
- nscan[i] = malloc(bpl);
- if(nscan[i] == nil)
- sysfatal("can't allocate: %r");
- }
-
- /* resample in Y */
- for(i=0; i<xsize; i++)
- for(j=0; j<nchan; j++)
- resampley(oscan, nchan*i+j, Dy(from->r), nscan, ysize);
-
- /* pack data into destination */
- bpl = bytesperline(to->r, from->depth);
- for(i=0; i<ysize; i++){
- j = loadimage(to, Rect(0, i, xsize, i+1), nscan[i], bpl);
- if(j != bpl)
- sysfatal("loadimage: %r");
- }
-
- for(i=0; i<Dy(from->r); i++){
- free(oscan[i]);
- free(nscan[i]);
- }
- free(oscan);
- free(nscan);
-
- return to;
-}
diff --git a/sys/src/cmd/page/util.c b/sys/src/cmd/page/util.c
deleted file mode 100644
index 3c27f9c03..000000000
--- a/sys/src/cmd/page/util.c
+++ /dev/null
@@ -1,131 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-#include <bio.h>
-#include "page.h"
-
-void*
-emalloc(int sz)
-{
- void *v;
- v = malloc(sz);
- if(v == nil) {
- fprint(2, "out of memory allocating %d\n", sz);
- wexits("mem");
- }
- memset(v, 0, sz);
- return v;
-}
-
-void*
-erealloc(void *v, int sz)
-{
- v = realloc(v, sz);
- if(v == nil) {
- fprint(2, "out of memory allocating %d\n", sz);
- wexits("mem");
- }
- return v;
-}
-
-char*
-estrdup(char *s)
-{
- char *t;
- if((t = strdup(s)) == nil) {
- fprint(2, "out of memory in strdup(%.10s)\n", s);
- wexits("mem");
- }
- 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.
- */
-int
-spooltodisk(uchar *ibuf, int in, char **name)
-{
- uchar buf[8192];
- int fd, n;
- char temp[40];
-
- strcpy(temp, "/tmp/pagespoolXXXXXXXXX");
- fd = opentemp(temp);
- if(name)
- *name = estrdup(temp);
-
- if(write(fd, ibuf, in) != in){
- fprint(2, "error writing temporary file\n");
- wexits("write temp");
- }
-
- while((n = read(stdinfd, buf, sizeof buf)) > 0){
- if(write(fd, buf, n) != n){
- fprint(2, "error writing temporary file\n");
- wexits("write temp0");
- }
- }
- seek(fd, 0, 0);
- return fd;
-}
-
-/*
- * spool standard input into a pipe.
- * we've already ready the first in bytes into ibuf
- */
-int
-stdinpipe(uchar *ibuf, int in)
-{
- uchar buf[8192];
- int n;
- int p[2];
- if(pipe(p) < 0){
- fprint(2, "pipe fails: %r\n");
- wexits("pipe");
- }
-
- switch(rfork(RFMEM|RFPROC|RFFDG)){
- case -1:
- fprint(2, "fork fails: %r\n");
- wexits("fork");
- default:
- close(p[1]);
- return p[0];
- case 0:
- break;
- }
-
- close(p[0]);
- write(p[1], ibuf, in);
- while((n = read(stdinfd, buf, sizeof buf)) > 0)
- write(p[1], buf, n);
-
- _exits(0);
- return -1; /* not reached */
-}
diff --git a/sys/src/cmd/page/view.c b/sys/src/cmd/page/view.c
deleted file mode 100644
index 4a32916a9..000000000
--- a/sys/src/cmd/page/view.c
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*
- * the actual viewer that handles screen stuff
- */
-
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <cursor.h>
-#include <event.h>
-#include <bio.h>
-#include <plumb.h>
-#include <ctype.h>
-#include <keyboard.h>
-#include "page.h"
-
-Document *doc;
-Image *im;
-Image *tofree;
-int page;
-int angle = 0;
-int showbottom = 0; /* on the next showpage, move the image so the bottom is visible. */
-
-Rectangle ulrange; /* the upper left corner of the image must be in this rectangle */
-Point ul; /* the upper left corner of the image is at this point on the screen */
-
-Point pclip(Point, Rectangle);
-Rectangle mkrange(Rectangle screenr, Rectangle imr);
-void redraw(Image*);
-
-Cursor reading={
- {-1, -1},
- {0xff, 0x80, 0xff, 0x80, 0xff, 0x00, 0xfe, 0x00,
- 0xff, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xef, 0xe0,
- 0xc7, 0xf0, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0xc0,
- 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, },
- {0x00, 0x00, 0x7f, 0x00, 0x7e, 0x00, 0x7c, 0x00,
- 0x7e, 0x00, 0x7f, 0x00, 0x6f, 0x80, 0x47, 0xc0,
- 0x03, 0xe0, 0x01, 0xf0, 0x00, 0xe0, 0x00, 0x40,
- 0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
-};
-
-Cursor query = {
- {-7,-7},
- {0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe,
- 0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8,
- 0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0,
- 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, },
- {0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c,
- 0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0,
- 0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80,
- 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
-};
-
-enum {
- Left = 1,
- Middle = 2,
- Right = 4,
-
- RMenu = 3,
-};
-
-static void
-delayfreeimage(Image *m)
-{
- if(m == tofree)
- return;
- if(tofree)
- freeimage(tofree);
- tofree = m;
-}
-
-void
-unhide(void)
-{
- static int wctl = -1;
-
- if(wctl < 0)
- wctl = open("/dev/wctl", OWRITE);
- if(wctl < 0)
- return;
-
- write(wctl, "unhide", 6);
-}
-
-int
-max(int a, int b)
-{
- return a > b ? a : b;
-}
-
-int
-min(int a, int b)
-{
- return a < b ? a : b;
-}
-
-
-char*
-menugen(int n)
-{
- static char menustr[32];
- char *p;
- int len;
-
- if(n == doc->npage)
- return "exit";
- if(n > doc->npage)
- return nil;
-
- if(reverse)
- n = doc->npage-1-n;
-
- p = doc->pagename(doc, n);
- len = (sizeof menustr)-2;
-
- if(strlen(p) > len && strrchr(p, '/'))
- p = strrchr(p, '/')+1;
- if(strlen(p) > len)
- p = p+strlen(p)-len;
-
- strcpy(menustr+1, p);
- if(page == n)
- menustr[0] = '>';
- else
- menustr[0] = ' ';
- return menustr;
-}
-
-void
-showpage(int page, Menu *m)
-{
- if(doc->fwdonly)
- m->lasthit = 0; /* this page */
- else
- m->lasthit = reverse ? doc->npage-1-page : page;
-
- esetcursor(&reading);
- delayfreeimage(nil);
- im = cachedpage(doc, angle, page);
- if(im == nil)
- wexits(0);
- if(resizing)
- resize(Dx(im->r), Dy(im->r));
-
- esetcursor(nil);
- if(showbottom){
- ul.y = screen->r.max.y - Dy(im->r);
- showbottom = 0;
- }
-
- redraw(screen);
- flushimage(display, 1);
-}
-
-char*
-writebitmap(void)
-{
- char basename[64];
- char name[64+30];
- static char result[200];
- char *p, *q;
- int fd;
-
- if(im == nil)
- return "no image";
-
- memset(basename, 0, sizeof basename);
- if(doc->docname)
- strncpy(basename, doc->docname, sizeof(basename)-1);
- else if((p = menugen(page)) && p[0] != '\0')
- strncpy(basename, p+1, sizeof(basename)-1);
-
- if(basename[0]) {
- if(q = strrchr(basename, '/'))
- q++;
- else
- q = basename;
- if(p = strchr(q, '.'))
- *p = 0;
-
- memset(name, 0, sizeof name);
- snprint(name, sizeof(name)-1, "%s.%d.bit", q, page+1);
- if(access(name, 0) >= 0) {
- strcat(name, "XXXX");
- mktemp(name);
- }
- if(access(name, 0) >= 0)
- return "couldn't think of a name for bitmap";
- } else {
- strcpy(name, "bitXXXX");
- mktemp(name);
- if(access(name, 0) >= 0)
- return "couldn't think of a name for bitmap";
- }
-
- if((fd = create(name, OWRITE, 0666)) < 0) {
- snprint(result, sizeof result, "cannot create %s: %r", name);
- return result;
- }
-
- if(writeimage(fd, im, 0) < 0) {
- snprint(result, sizeof result, "cannot writeimage: %r");
- close(fd);
- return result;
- }
- close(fd);
-
- snprint(result, sizeof result, "wrote %s", name);
- return result;
-}
-
-static void translate(Point);
-
-static int
-showdata(Plumbmsg *msg)
-{
- char *s;
-
- s = plumblookup(msg->attr, "action");
- return s && strcmp(s, "showdata")==0;
-}
-
-static int
-plumbquit(Plumbmsg *msg)
-{
- char *s;
-
- s = plumblookup(msg->attr, "action");
- return s && strcmp(s, "quit")==0;
-}
-
-/* correspond to entries in miditems[] below,
- * changing one means you need to change
- */
-enum{
- Restore = 0,
- Zin,
- Fit,
- Rot,
- Upside,
- Empty1,
- Next,
- Prev,
- Zerox,
- Empty2,
- Reverse,
- Del,
- Write,
- Empty3,
- Exit,
-};
-
-void
-viewer(Document *dd)
-{
- int i, fd, n, oldpage;
- int nxt;
- Menu menu, midmenu;
- Mouse m;
- Event e;
- Point dxy, oxy, xy0;
- Rectangle r;
- Image *tmp;
- static char *fwditems[] = { "this page", "next page", "exit", 0 };
- static char *miditems[] = {
- "orig size",
- "zoom in",
- "fit window",
- "rotate 90",
- "upside down",
- "",
- "next",
- "prev",
- "zerox",
- "",
- "reverse",
- "discard",
- "write",
- "",
- "quit",
- 0
- };
- char *s;
- enum { Eplumb = 4 };
- Plumbmsg *pm;
-
- doc = dd; /* save global for menuhit */
- ul = screen->r.min;
- einit(Emouse|Ekeyboard);
- if(doc->addpage != nil)
- eplumb(Eplumb, "image");
-
- esetcursor(&reading);
- r.min = ZP;
-
- /*
- * im is a global pointer to the current image.
- * eventually, i think we will have a layer between
- * the display routines and the ps/pdf/whatever routines
- * to perhaps cache and handle images of different
- * sizes, etc.
- */
- im = 0;
- page = reverse ? doc->npage-1 : 0;
-
- if(doc->fwdonly) {
- menu.item = fwditems;
- menu.gen = 0;
- menu.lasthit = 0;
- } else {
- menu.item = 0;
- menu.gen = menugen;
- menu.lasthit = 0;
- }
-
- midmenu.item = miditems;
- midmenu.gen = 0;
- midmenu.lasthit = Next;
-
- showpage(page, &menu);
- esetcursor(nil);
-
- nxt = 0;
- for(;;) {
- /*
- * throughout, if doc->fwdonly is set, we restrict the functionality
- * a fair amount. we don't care about doc->npage anymore, and
- * all that can be done is select the next page.
- */
- unlockdisplay(display);
- i = eread(Emouse|Ekeyboard|Eplumb, &e);
- lockdisplay(display);
- switch(i){
- case Ekeyboard:
- if(e.kbdc <= 0xFF && isdigit(e.kbdc)) {
- nxt = nxt*10+e.kbdc-'0';
- break;
- } else if(e.kbdc != '\n')
- nxt = 0;
- switch(e.kbdc) {
- case 'r': /* reverse page order */
- if(doc->fwdonly)
- break;
- reverse = !reverse;
- menu.lasthit = doc->npage-1-menu.lasthit;
-
- /*
- * the theory is that if we are reversing the
- * document order and are on the first or last
- * page then we're just starting and really want
- * to view the other end. maybe the if
- * should be dropped and this should happen always.
- */
- if(page == 0 || page == doc->npage-1) {
- page = doc->npage-1-page;
- showpage(page, &menu);
- }
- break;
- case 'w': /* write bitmap of current screen */
- esetcursor(&reading);
- s = writebitmap();
- if(s)
- string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP,
- display->defaultfont, s);
- esetcursor(nil);
- flushimage(display, 1);
- break;
- case 'd': /* remove image from working set */
- if(doc->rmpage && page < doc->npage) {
- if(doc->rmpage(doc, page) >= 0) {
- if(doc->npage < 0)
- wexits(0);
- if(page >= doc->npage)
- page = doc->npage-1;
- showpage(page, &menu);
- }
- }
- break;
- case 'q':
- case 0x04: /* ctrl-d */
- wexits(0);
- case 'u':
- if(im==nil)
- break;
- angle = (angle+180) % 360;
- showpage(page, &menu);
- break;
- case '-':
- case '\b':
- case Kleft:
- if(page > 0 && !doc->fwdonly) {
- --page;
- showpage(page, &menu);
- }
- break;
- case '\n':
- if(nxt) {
- nxt--;
- if(nxt >= 0 && nxt < doc->npage && !doc->fwdonly)
- showpage(page=nxt, &menu);
- nxt = 0;
- break;
- }
- goto Gotonext;
- case Kright:
- case ' ':
- Gotonext:
- if(doc->npage && ++page >= doc->npage && !doc->fwdonly)
- wexits(0);
- showpage(page, &menu);
- break;
-
- /*
- * The upper y coordinate of the image is at ul.y in screen->r.
- * Panning up means moving the upper left corner down. If the
- * upper left corner is currently visible, we need to go back a page.
- */
- case Kup:
- if(screen->r.min.y <= ul.y && ul.y < screen->r.max.y){
- if(page > 0 && !doc->fwdonly){
- --page;
- showbottom = 1;
- showpage(page, &menu);
- }
- } else {
- i = Dy(screen->r)/2;
- if(i > 10)
- i -= 10;
- if(i+ul.y > screen->r.min.y)
- i = screen->r.min.y - ul.y;
- translate(Pt(0, i));
- }
- break;
-
- /*
- * If the lower y coordinate is on the screen, we go to the next page.
- * The lower y coordinate is at ul.y + Dy(im->r).
- */
- case Kdown:
- i = ul.y + Dy(im->r);
- if(screen->r.min.y <= i && i <= screen->r.max.y){
- ul.y = screen->r.min.y;
- goto Gotonext;
- } else {
- i = -Dy(screen->r)/2;
- if(i < -10)
- i += 10;
- if(i+ul.y+Dy(im->r) <= screen->r.max.y)
- i = screen->r.max.y - Dy(im->r) - ul.y - 1;
- translate(Pt(0, i));
- }
- break;
- default:
- esetcursor(&query);
- sleep(1000);
- esetcursor(nil);
- break;
- }
- break;
-
- case Emouse:
- m = e.mouse;
- switch(m.buttons){
- case Left:
- oxy = m.xy;
- xy0 = oxy;
- do {
- dxy = subpt(m.xy, oxy);
- oxy = m.xy;
- translate(dxy);
- unlockdisplay(display);
- m = emouse();
- lockdisplay(display);
- } while(m.buttons == Left);
- if(m.buttons) {
- dxy = subpt(xy0, oxy);
- translate(dxy);
- }
- break;
-
- case Middle:
- if(doc->npage == 0)
- break;
-
- unlockdisplay(display);
- n = emenuhit(Middle, &m, &midmenu);
- lockdisplay(display);
- if(n == -1)
- break;
- switch(n){
- case Next: /* next */
- if(reverse)
- page--;
- else
- page++;
- if(page < 0) {
- if(reverse) return;
- else page = 0;
- }
-
- if((page >= doc->npage) && !doc->fwdonly)
- return;
-
- showpage(page, &menu);
- nxt = 0;
- break;
- case Prev: /* prev */
- if(reverse)
- page++;
- else
- page--;
- if(page < 0) {
- if(reverse) return;
- else page = 0;
- }
-
- if((page >= doc->npage) && !doc->fwdonly && !reverse)
- return;
-
- showpage(page, &menu);
- nxt = 0;
- break;
- case Zerox: /* prev */
- zerox();
- break;
- case Zin: /* zoom in */
- {
- double delta;
- Rectangle r;
-
- r = egetrect(Middle, &m);
- if((rectclip(&r, rectaddpt(im->r, ul)) == 0) ||
- Dx(r) == 0 || Dy(r) == 0)
- break;
- /* use the smaller side to expand */
- if(Dx(r) < Dy(r))
- delta = (double)Dx(im->r)/(double)Dx(r);
- else
- delta = (double)Dy(im->r)/(double)Dy(r);
-
- esetcursor(&reading);
- tmp = xallocimage(display,
- Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)),
- im->chan, 0, DBlack);
- if(tmp == nil) {
- fprint(2, "out of memory during zoom: %r\n");
- wexits("memory");
- }
- resample(im, tmp);
- im = tmp;
- delayfreeimage(tmp);
- esetcursor(nil);
- ul = screen->r.min;
- redraw(screen);
- flushimage(display, 1);
- break;
- }
- case Fit: /* fit */
- {
- double delta;
- Rectangle r;
-
- delta = (double)Dx(screen->r)/(double)Dx(im->r);
- if((double)Dy(im->r)*delta > Dy(screen->r))
- 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);
- tmp = xallocimage(display, r, im->chan, 0, DBlack);
- if(tmp == nil) {
- fprint(2, "out of memory during fit: %r\n");
- wexits("memory");
- }
- resample(im, tmp);
- im = tmp;
- delayfreeimage(tmp);
- esetcursor(nil);
- ul = screen->r.min;
- redraw(screen);
- flushimage(display, 1);
- break;
- }
- case Rot: /* rotate 90 */
- angle = (angle+90) % 360;
- showpage(page, &menu);
- break;
- case Upside: /* upside-down */
- angle = (angle+180) % 360;
- showpage(page, &menu);
- break;
- case Restore: /* restore */
- showpage(page, &menu);
- break;
- case Reverse: /* reverse */
- if(doc->fwdonly)
- break;
- reverse = !reverse;
- menu.lasthit = doc->npage-1-menu.lasthit;
-
- if(page == 0 || page == doc->npage-1) {
- page = doc->npage-1-page;
- showpage(page, &menu);
- }
- break;
- case Write: /* write */
- esetcursor(&reading);
- s = writebitmap();
- if(s)
- string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP,
- display->defaultfont, s);
- esetcursor(nil);
- flushimage(display, 1);
- break;
- case Del: /* delete */
- if(doc->rmpage && page < doc->npage) {
- if(doc->rmpage(doc, page) >= 0) {
- if(doc->npage < 0)
- wexits(0);
- if(page >= doc->npage)
- page = doc->npage-1;
- showpage(page, &menu);
- }
- }
- break;
- case Exit: /* exit */
- return;
- case Empty1:
- case Empty2:
- case Empty3:
- break;
-
- };
-
-
-
- case Right:
- if(doc->npage == 0)
- break;
-
- oldpage = page;
- unlockdisplay(display);
- n = emenuhit(RMenu, &m, &menu);
- lockdisplay(display);
- if(n == -1)
- break;
-
- if(doc->fwdonly) {
- switch(n){
- case 0: /* this page */
- break;
- case 1: /* next page */
- showpage(++page, &menu);
- break;
- case 2: /* exit */
- return;
- }
- break;
- }
-
- if(n == doc->npage)
- return;
- else
- page = reverse ? doc->npage-1-n : n;
-
- if(oldpage != page)
- showpage(page, &menu);
- nxt = 0;
- break;
- }
- break;
-
- case Eplumb:
- pm = e.v;
- if(pm->ndata <= 0){
- plumbfree(pm);
- break;
- }
- if(plumbquit(pm))
- exits(nil);
- if(showdata(pm)) {
- s = estrdup("/tmp/pageplumbXXXXXXX");
- fd = opentemp(s);
- write(fd, pm->data, pm->ndata);
- /* lose fd reference on purpose; the file is open ORCLOSE */
- } else if(pm->data[0] == '/') {
- s = estrdup(pm->data);
- } else {
- s = emalloc(strlen(pm->wdir)+1+pm->ndata+1);
- sprint(s, "%s/%s", pm->wdir, pm->data);
- cleanname(s);
- }
- if((i = doc->addpage(doc, s)) >= 0) {
- page = i;
- unhide();
- showpage(page, &menu);
- }
- free(s);
- plumbfree(pm);
- break;
- }
- }
-}
-
-Image *gray;
-
-/*
- * A draw operation that touches only the area contained in bot but not in top.
- * mp and sp get aligned with bot.min.
- */
-static void
-gendrawdiff(Image *dst, Rectangle bot, Rectangle top,
- Image *src, Point sp, Image *mask, Point mp, int op)
-{
- Rectangle r;
- Point origin;
- Point delta;
-
- USED(op);
-
- if(Dx(bot)*Dy(bot) == 0)
- return;
-
- /* no points in bot - top */
- if(rectinrect(bot, top))
- return;
-
- /* bot - top ≡ bot */
- if(Dx(top)*Dy(top)==0 || rectXrect(bot, top)==0){
- gendrawop(dst, bot, src, sp, mask, mp, op);
- return;
- }
-
- origin = bot.min;
- /* split bot into rectangles that don't intersect top */
- /* left side */
- if(bot.min.x < top.min.x){
- r = Rect(bot.min.x, bot.min.y, top.min.x, bot.max.y);
- delta = subpt(r.min, origin);
- gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
- bot.min.x = top.min.x;
- }
-
- /* right side */
- if(bot.max.x > top.max.x){
- r = Rect(top.max.x, bot.min.y, bot.max.x, bot.max.y);
- delta = subpt(r.min, origin);
- gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
- bot.max.x = top.max.x;
- }
-
- /* top */
- if(bot.min.y < top.min.y){
- r = Rect(bot.min.x, bot.min.y, bot.max.x, top.min.y);
- delta = subpt(r.min, origin);
- gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
- bot.min.y = top.min.y;
- }
-
- /* bottom */
- if(bot.max.y > top.max.y){
- r = Rect(bot.min.x, top.max.y, bot.max.x, bot.max.y);
- delta = subpt(r.min, origin);
- gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
- bot.max.y = top.max.y;
- }
-}
-
-static void
-drawdiff(Image *dst, Rectangle bot, Rectangle top, Image *src, Image *mask, Point p, int op)
-{
- gendrawdiff(dst, bot, top, src, p, mask, p, op);
-}
-
-/*
- * Translate the image in the window by delta.
- */
-static void
-translate(Point delta)
-{
- Point u;
- Rectangle r, or;
-
- if(im == nil)
- return;
-
- u = pclip(addpt(ul, delta), ulrange);
- delta = subpt(u, ul);
- if(delta.x == 0 && delta.y == 0)
- return;
-
- /*
- * The upper left corner of the image is currently at ul.
- * We want to move it to u.
- */
- or = rectaddpt(Rpt(ZP, Pt(Dx(im->r), Dy(im->r))), ul);
- r = rectaddpt(or, delta);
-
- drawop(screen, r, screen, nil, ul, S);
- ul = u;
-
- /* fill in gray where image used to be but isn't. */
- drawdiff(screen, insetrect(or, -2), insetrect(r, -2), gray, nil, ZP, S);
-
- /* fill in black border */
- drawdiff(screen, insetrect(r, -2), r, display->black, nil, ZP, S);
-
- /* fill in image where it used to be off the screen. */
- if(rectclip(&or, screen->r))
- drawdiff(screen, r, rectaddpt(or, delta), im, nil, im->r.min, S);
- else
- drawop(screen, r, im, nil, im->r.min, S);
- flushimage(display, 1);
-}
-
-void
-redraw(Image *screen)
-{
- Rectangle r;
-
- if(im == nil)
- return;
-
- ulrange.max = screen->r.max;
- ulrange.min = subpt(screen->r.min, Pt(Dx(im->r), Dy(im->r)));
-
- ul = pclip(ul, ulrange);
- drawop(screen, screen->r, im, nil, subpt(im->r.min, subpt(ul, screen->r.min)), S);
-
- if(im->repl)
- return;
-
- /* fill in any outer edges */
- /* black border */
- r = rectaddpt(im->r, subpt(ul, im->r.min));
- border(screen, r, -2, display->black, ZP);
- r.min = subpt(r.min, Pt(2,2));
- r.max = addpt(r.max, Pt(2,2));
-
- /* gray for the rest */
- if(gray == nil) {
- gray = xallocimage(display, Rect(0,0,1,1), RGB24, 1, 0x888888FF);
- if(gray == nil) {
- fprint(2, "g out of memory: %r\n");
- wexits("mem");
- }
- }
- 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);
-}
-
-/* clip p to be in r */
-Point
-pclip(Point p, Rectangle r)
-{
- if(p.x < r.min.x)
- p.x = r.min.x;
- else if(p.x >= r.max.x)
- p.x = r.max.x-1;
-
- if(p.y < r.min.y)
- p.y = r.min.y;
- else if(p.y >= r.max.y)
- p.y = r.max.y-1;
-
- return p;
-}
-
-/*
- * resize is perhaps a misnomer.
- * this really just grows the window to be at least dx across
- * and dy high. if the window hits the bottom or right edge,
- * it is backed up until it hits the top or left edge.
- */
-void
-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 = 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);
- r.max.y = max(r.min.y+dy, r.max.y);
- if(r.max.x > sr.max.x){
- if(Dx(r) > Dx(sr)){
- r.min.x = 0;
- r.max.x = sr.max.x;
- }else
- r = rectaddpt(r, Pt(sr.max.x-r.max.x, 0));
- }
- if(r.max.y > sr.max.y){
- if(Dy(r) > Dy(sr)){
- r.min.y = 0;
- r.max.y = sr.max.y;
- }else
- r = rectaddpt(r, Pt(0, sr.max.y-r.max.y));
- }
-
- /*
- * Sometimes we can't actually grow the window big enough,
- * and resizing it to the same shape makes it flash.
- */
- 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);
-}
-
-/*
- * If we allocimage after a resize but before flushing the draw buffer,
- * we won't have seen the reshape event, and we won't have called
- * getwindow, and allocimage will fail. So we flushimage before every alloc.
- */
-Image*
-xallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val)
-{
- flushimage(display, 0);
- 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)
-{
- char *srv, *mntsrv;
- char spec[100];
- int srvfd, cons, pid;
-
- 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);
- }
-
- 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);
- if(srvfd == -1){
- fprint(2, "page: can't open %s: %r\n", srv);
- wexits("no srv");
- }
- free(srv);
- 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);
-}
-
-Rectangle
-screenrect(void)
-{
- int fd;
- char buf[12*5];
-
- 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));
-}
-
-void
-zerox(void)
-{
- int pfd[2];
-
- pipe(pfd);
- switch(rfork(RFFDG|RFREND|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;
- }
-}