ref: 4ac8bd4ae86f086d26012320b30ac04ce20e9c94
dir: /vcrop.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <event.h> #include <keyboard.h> Image *bg; Image *p; Image *n; char *menustr[] = { "crop", "undo", "save", "exit", 0 }; Menu menu = { menustr }; enum { Mcrop, Mundo, Msave, Mexit }; void eresized(int new) { if(new && getwindow(display, Refnone)<0) sysfatal("cannot reattach: %r"); draw(screen, screen->r, bg, nil, ZP); draw(screen, screen->r, n, nil, n->r.min); } void crop(Mouse *m) { Rectangle r; Image *i; r = egetrect(1, m); if(eqrect(r, ZR) || badrect(r)) return; i = allocimage(display, Rect(0,0,Dx(r),Dy(r)), screen->chan, 0, DNofill); if(i==nil) sysfatal("allocimage: %r"); draw(i, i->r, screen, nil, r.min); if(p) freeimage(p); p = n; n = i; eresized(0); } void save(Mouse *m) { char buf[255]; int i, fd; i = eenter("Save as:", buf, sizeof buf, m); if(i<0) return; fd = create(buf, OWRITE, 0644); if(fd<0) sysfatal("create: %r"); i = writeimage(fd, n, 0); if(i<0) sysfatal("writeimage: %r"); close(fd); } void undo(void) { if(p==nil) return; freeimage(n); n = p; p = nil; eresized(0); } void menu3hit(Mouse *m) { int i; i = emenuhit(3, m, &menu); switch(i){ case Mcrop: m->buttons = 1; crop(m); break; case Mundo: undo(); break; case Msave: save(m); break; case Mexit: exits(nil); } } void usage(char *n) { fprint(2, "usage: %s [image]\n", n); exits("usage"); } void main(int argc, char *argv[]) { Event ev; int e, fd; if(argc > 2) usage(argv[0]); fd = 0; if(argc==2){ fd = open(argv[1], OREAD); if(fd<0) sysfatal("open: %r"); } if(initdraw(nil, nil, "vcrop")<0) sysfatal("initdraw: %r"); einit(Emouse|Ekeyboard); bg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCFF); n = readimage(display, fd, 0); if(n==nil) sysfatal("readimage: %r"); close(fd); p = nil; eresized(0); for(;;){ e = event(&ev); switch(e){ case Emouse: if(ev.mouse.buttons==1) crop(&ev.mouse); else if(ev.mouse.buttons==4) menu3hit(&ev.mouse); break; case Ekeyboard: if(ev.kbdc==Kdel) exits(nil); break; } } }