📄 view.c
字号:
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); freeimage(im); im = 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); freeimage(im); im = tmp; esetcursor(nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Rot: /* rotate 90 */ esetcursor(&reading); im = rot90(im); esetcursor(nil); angle = (angle+90) % 360; redraw(screen); flushimage(display, 1); break; case Upside: /* upside-down */ if(im==nil) break; esetcursor(&reading); rot180(im); esetcursor(nil); angle = (angle+180) % 360; redraw(screen); flushimage(display, 1); 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; n = emenuhit(RMenu, &m, &menu); 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(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 voidgendrawdiff(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 voiddrawdiff(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 voidtranslate(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);}voidredraw(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); }voideresized(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 */Pointpclip(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. */voidresize(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;}voidnewwin(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); free(srv); if(srvfd == -1){ fprint(2, "page: can't open %s: %r\n", srv); wexits("no 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);}Rectanglescreenrect(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));}voidzerox(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; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -