diff options
Diffstat (limited to 'src/cmd/tweak.c')
-rw-r--r-- | src/cmd/tweak.c | 2058 |
1 files changed, 0 insertions, 2058 deletions
diff --git a/src/cmd/tweak.c b/src/cmd/tweak.c deleted file mode 100644 index c7e12878..00000000 --- a/src/cmd/tweak.c +++ /dev/null @@ -1,2058 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <cursor.h> -#include <event.h> -#include <bio.h> - -typedef struct Thing Thing; - -struct Thing -{ - Image *b; - Subfont *s; - char *name; /* file name */ - int face; /* is 48x48 face file or cursor file*/ - Rectangle r; /* drawing region */ - Rectangle tr; /* text region */ - Rectangle er; /* entire region */ - long c; /* character number in subfont */ - int mod; /* modified */ - int mag; /* magnification */ - Rune off; /* offset for subfont indices */ - Thing *parent; /* thing of which i'm an edit */ - Thing *next; -}; - -enum -{ - Border = 1, - Up = 1, - Down = 0, - Mag = 4, - Maxmag = 10, -}; - -enum -{ - NORMAL =0, - FACE =1, - CURSOR =2 -}; - -enum -{ - Mopen, - Mread, - Mwrite, - Mcopy, - Mchar, - Mpixels, - Mclose, - Mexit, -}; - -enum -{ - Blue = 54, -}; - -char *menu3str[] = { - "open", - "read", - "write", - "copy", - "char", - "pixels", - "close", - "exit", - 0, -}; - -Menu menu3 = { - menu3str -}; - -Cursor sweep0 = { - {-7, -7}, - {0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0}, - {0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, - 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, - 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00} -}; - -Cursor box = { - {-7, -7}, - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, - 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, - 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, - 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, - 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00} -}; - -Cursor sight = { - {-7, -7}, - {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF, - 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF, - 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,}, - {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84, - 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE, - 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, - 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,} -}; - -Cursor pixel = { - {-7, -7}, - {0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0xf8, 0x1f, - 0xf0, 0x0f, 0xe0, 0x07, 0xe0, 0x07, 0xfe, 0x7f, - 0xfe, 0x7f, 0xe0, 0x07, 0xe0, 0x07, 0xf0, 0x0f, - 0x78, 0x1f, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, }, - {0x00, 0x00, 0x0f, 0xf0, 0x31, 0x8c, 0x21, 0x84, - 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x40, 0x02, - 0x40, 0x02, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, - 0x21, 0x84, 0x31, 0x8c, 0x0f, 0xf0, 0x00, 0x00, } -}; - -Cursor busy = { - {-7, -7}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x8e, 0x1d, 0xc7, - 0xff, 0xe3, 0xff, 0xf3, 0xff, 0xff, 0x7f, 0xfe, - 0x3f, 0xf8, 0x17, 0xf0, 0x03, 0xe0, 0x00, 0x00,}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x82, - 0x04, 0x41, 0xff, 0xe1, 0x5f, 0xf1, 0x3f, 0xfe, - 0x17, 0xf0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00,} -}; - -Cursor skull = { - {-7,-7}, - {0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xe7, 0xe7, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0x1f, 0xf8, - 0x0f, 0xf0, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0xef, 0xf7, 0xc7, 0xe3, 0x00, 0x00, 0x00, 0x00,}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, - 0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0, - 0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27, - 0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} -}; - -Rectangle cntlr; /* control region */ -Rectangle editr; /* editing region */ -Rectangle textr; /* text region */ -Thing *thing; -Mouse mouse; -char hex[] = "0123456789abcdefABCDEF"; -jmp_buf err; -char *file; -int mag; -int but1val = 0; -int but2val = 255; -int invert = 0; -Image *values[256]; -Image *greyvalues[256]; -uchar data[8192]; - -Thing* tget(char*); -void mesg(char*, ...); -void drawthing(Thing*, int); -void xselect(void); -void menu(void); -void error(Display*, char*); -void buttons(int); -void drawall(void); -void tclose1(Thing*); - -void -main(int argc, char *argv[]) -{ - int i; - Event e; - Thing *t; - - mag = Mag; - if(initdraw(error, 0, "tweak") < 0){ - fprint(2, "tweak: initdraw failed: %r\n"); - exits("initdraw"); - } - for(i=0; i<256; i++){ - values[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, cmap2rgba(i)); - greyvalues[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, (i<<24)|(i<<16)|(i<<8)|0xFF); - if(values[i] == 0 || greyvalues[i] == 0) - drawerror(display, "can't allocate image"); - } - einit(Emouse|Ekeyboard); - eresized(0); - i = 1; - setjmp(err); - for(; i<argc; i++){ - file = argv[i]; - t = tget(argv[i]); - if(t) - drawthing(t, 1); - flushimage(display, 1); - } - file = 0; - setjmp(err); - for(;;) - switch(event(&e)){ - case Ekeyboard: - break; - case Emouse: - mouse = e.mouse; - if(mouse.buttons & 3){ - xselect(); - break; - } - if(mouse.buttons & 4) - menu(); - } -} - -int -xlog2(int n) -{ - int i; - - for(i=0; (1<<i) <= n; i++) - if((1<<i) == n) - return i; - fprint(2, "log2 %d = 0\n", n); - return 0; -} - -void -error(Display *d, char *s) -{ - USED(d); - - if(file) - mesg("can't read %s: %s: %r", file, s); - else - mesg("/dev/bitblt error: %s", s); - if(err[0]) - longjmp(err, 1); - exits(s); -} - -void -redraw(Thing *t) -{ - Thing *nt; - Point p; - - if(thing==0 || thing==t) - draw(screen, editr, display->white, nil, ZP); - if(thing == 0) - return; - if(thing != t){ - for(nt=thing; nt->next!=t; nt=nt->next) - ; - draw(screen, Rect(screen->r.min.x, nt->er.max.y, editr.max.x, editr.max.y), - display->white, nil, ZP); - } - for(nt=t; nt; nt=nt->next){ - drawthing(nt, 0); - if(nt->next == 0){ - p = Pt(editr.min.x, nt->er.max.y); - draw(screen, Rpt(p, editr.max), display->white, nil, ZP); - } - } - mesg(""); -} - -void -eresized(int new) -{ - if(new && getwindow(display, Refnone) < 0) - error(display, "can't reattach to window"); - cntlr = insetrect(screen->clipr, 1); - editr = cntlr; - textr = editr; - textr.min.y = textr.max.y - font->height; - cntlr.max.y = cntlr.min.y + font->height; - editr.min.y = cntlr.max.y+1; - editr.max.y = textr.min.y-1; - draw(screen, screen->clipr, display->white, nil, ZP); - draw(screen, Rect(editr.min.x, editr.max.y, editr.max.x+1, editr.max.y+1), display->black, nil, ZP); - replclipr(screen, 0, editr); - drawall(); -} - -void -mesgstr(Point p, int line, char *s) -{ - Rectangle c, r; - - r.min = p; - r.min.y += line*font->height; - r.max.y = r.min.y+font->height; - r.max.x = editr.max.x; - c = screen->clipr; - replclipr(screen, 0, r); - draw(screen, r, values[0xDD], nil, ZP); - r.min.x++; - string(screen, r.min, display->black, ZP, font, s); - replclipr(screen, 0, c); - flushimage(display, 1); -} - -void -mesg(char *fmt, ...) -{ - char buf[1024]; - va_list arg; - - va_start(arg, fmt); - vseprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - mesgstr(textr.min, 0, buf); -} - -void -tmesg(Thing *t, int line, char *fmt, ...) -{ - char buf[1024]; - va_list arg; - - va_start(arg, fmt); - vseprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - mesgstr(t->tr.min, line, buf); -} - - -void -scntl(char *l) -{ - sprint(l, "mag: %d but1: %d but2: %d invert-on-copy: %c", mag, but1val, but2val, "ny"[invert]); -} - -void -cntl(void) -{ - char buf[256]; - - scntl(buf); - mesgstr(cntlr.min, 0, buf); -} - -void -stext(Thing *t, char *l0, char *l1) -{ - Fontchar *fc; - char buf[256]; - - l1[0] = 0; - sprint(buf, "depth:%d r:%d %d %d %d ", - t->b->depth, t->b->r.min.x, t->b->r.min.y, - t->b->r.max.x, t->b->r.max.y); - if(t->parent) - sprint(buf+strlen(buf), "mag: %d ", t->mag); - sprint(l0, "%s file: %s", buf, t->name); - if(t->c >= 0){ - fc = &t->parent->s->info[t->c]; - sprint(l1, "c(hex): %x c(char): %C x: %d " - "top: %d bottom: %d left: %d width: %d iwidth: %d", - (int)(t->c+t->parent->off), (int)(t->c+t->parent->off), - fc->x, fc->top, fc->bottom, fc->left, - fc->width, Dx(t->b->r)); - }else if(t->s) - sprint(l1, "offset(hex): %ux n:%d height:%d ascent:%d", - t->off, t->s->n, t->s->height, t->s->ascent); -} - -void -text(Thing *t) -{ - char l0[256], l1[256]; - - stext(t, l0, l1); - tmesg(t, 0, l0); - if(l1[0]) - tmesg(t, 1, l1); -} - -void -drawall(void) -{ - Thing *t; - - cntl(); - for(t=thing; t; t=t->next) - drawthing(t, 0); -} - -int -value(Image *b, int x) -{ - int v, l, w; - uchar mask; - - w = b->depth; - if(w > 8){ - mesg("ldepth too large"); - return 0; - } - l = xlog2(w); - mask = (1<<w)-1; /* ones at right end of word */ - x -= b->r.min.x&~(7>>l); /* adjust x relative to first pixel */ - v = data[x>>(3-l)]; - v >>= ((7>>l)<<l) - ((x&(7>>l))<<l); /* pixel at right end of word */ - v &= mask; /* pixel at right end of word */ - return v; -} - -int -bvalue(int v, int d) -{ - v &= (1<<d)-1; - if(d > screen->depth) - v >>= d - screen->depth; - else - while(d < screen->depth && d < 8){ - v |= v << d; - d <<= 1; - } - if(v<0 || v>255){ - mesg("internal error: bad color"); - return Blue; - } - return v; -} - -void -drawthing(Thing *nt, int link) -{ - int n, nl, nf, i, x, y, sx, sy, fdx, dx, dy, v; - Thing *t; - Subfont *s; - Image *b, *col; - Point p, p1, p2; - - if(link){ - nt->next = 0; - if(thing == 0){ - thing = nt; - y = editr.min.y; - }else{ - for(t=thing; t->next; t=t->next) - ; - t->next = nt; - y = t->er.max.y; - } - }else{ - if(thing == nt) - y = editr.min.y; - else{ - for(t=thing; t->next!=nt; t=t->next) - ; - y = t->er.max.y; - } - } - s = nt->s; - b = nt->b; - nl = font->height; - if(s || nt->c>=0) - nl += font->height; - fdx = Dx(editr) - 2*Border; - dx = Dx(b->r); - dy = Dy(b->r); - if(nt->mag > 1){ - dx *= nt->mag; - dy *= nt->mag; - fdx -= fdx%nt->mag; - } - nf = 1 + dx/fdx; - nt->er.min.y = y; - nt->er.min.x = editr.min.x; - nt->er.max.x = nt->er.min.x + Border + dx + Border; - if(nt->er.max.x > editr.max.x) - nt->er.max.x = editr.max.x; - nt->er.max.y = nt->er.min.y + Border + nf*(dy+Border); - nt->r = insetrect(nt->er, Border); - nt->er.max.x = editr.max.x; - draw(screen, nt->er, display->white, nil, ZP); - for(i=0; i<nf; i++){ - p1 = Pt(nt->r.min.x-1, nt->r.min.y+i*(Border+dy)); - /* draw portion of bitmap */ - p = Pt(p1.x+1, p1.y); - if(nt->mag == 1) - draw(screen, Rect(p.x, p.y, p.x+fdx+Dx(b->r), p.y+Dy(b->r)), - b, nil, Pt(b->r.min.x+i*fdx, b->r.min.y)); - else{ - for(y=b->r.min.y; y<b->r.max.y; y++){ - sy = p.y+(y-b->r.min.y)*nt->mag; - if((n=unloadimage(b, Rect(b->r.min.x, y, b->r.max.x, y+1), data, sizeof data)) < 0) - fprint(2, "unloadimage: %r\n"); - for(x=b->r.min.x+i*(fdx/nt->mag); x<b->r.max.x; x++){ - sx = p.x+(x-i*(fdx/nt->mag)-b->r.min.x)*nt->mag; - if(sx >= nt->r.max.x) - break; - v = bvalue(value(b, x), b->depth); - if(v == 255) - continue; - if(b->chan == GREY8) - draw(screen, Rect(sx, sy, sx+nt->mag, sy+nt->mag), - greyvalues[v], nil, ZP); - else - draw(screen, Rect(sx, sy, sx+nt->mag, sy+nt->mag), - values[v], nil, ZP); - } - - } - } - /* line down left */ - if(i == 0) - col = display->black; - else - col = display->white; - draw(screen, Rect(p1.x, p1.y, p1.x+1, p1.y+dy+Border), col, nil, ZP); - /* line across top */ - draw(screen, Rect(p1.x, p1.y-1, nt->r.max.x+Border, p1.y), display->black, nil, ZP); - p2 = p1; - if(i == nf-1){ - p2.x += 1 + dx%fdx; - col = display->black; - }else{ - p2.x = nt->r.max.x; - col = display->white; - } - /* line down right */ - draw(screen, Rect(p2.x, p2.y, p2.x+1, p2.y+dy+Border), col, nil, ZP); - /* line across bottom */ - if(i == nf-1){ - p1.y += Border+dy; - draw(screen, Rect(p1.x, p1.y-1, p2.x,p1.y), display->black, nil, ZP); - } - } - nt->tr.min.x = editr.min.x; - nt->tr.max.x = editr.max.x; - nt->tr.min.y = nt->er.max.y + Border; - nt->tr.max.y = nt->tr.min.y + nl; - nt->er.max.y = nt->tr.max.y + Border; - text(nt); -} - -int -tohex(int c) -{ - if('0'<=c && c<='9') - return c - '0'; - if('a'<=c && c<='f') - return 10 + (c - 'a'); - if('A'<=c && c<='F') - return 10 + (c - 'A'); - return 0; -} - -Thing* -tget(char *file) -{ - int i, j, fd, face, x, y, c, chan; - Image *b; - Subfont *s; - Thing *t; - Dir *d; - jmp_buf oerr; - uchar buf[256]; - char *data; - - buf[0] = '\0'; - errstr((char*)buf, sizeof buf); /* flush pending error message */ - memmove(oerr, err, sizeof err); - d = nil; - if(setjmp(err)){ - Err: - free(d); - memmove(err, oerr, sizeof err); - return 0; - } - fd = open(file, OREAD); - if(fd < 0){ - mesg("can't open %s: %r", file); - goto Err; - } - d = dirfstat(fd); - if(d == nil){ - mesg("can't stat bitmap file %s: %r", file); - close(fd); - goto Err; - } - if(read(fd, buf, 11) != 11){ - mesg("can't read %s: %r", file); - close(fd); - goto Err; - } - seek(fd, 0, 0); - data = (char*)buf; - if(*data == '{') - data++; - if(memcmp(data, "0x", 2)==0 && data[4]==','){ - /* - * cursor file - */ - face = CURSOR; - s = 0; - data = malloc(d->length+1); - if(data == 0){ - mesg("can't malloc buffer: %r"); - close(fd); - goto Err; - } - data[d->length] = 0; - if(read(fd, data, d->length) != d->length){ - mesg("can't read cursor file %s: %r", file); - close(fd); - goto Err; - } - b = allocimage(display, Rect(0, 0, 16, 32), GREY1, 0, DNofill); - if(b == 0){ - mesg("image alloc failed file %s: %r", file); - free(data); - close(fd); - goto Err; - } - i = 0; - for(x=0;x<64; ){ - if((c=data[i]) == '\0') - goto ill; - if(c=='0' && data[i+1] == 'x'){ - i += 2; - continue; - } - if(strchr(hex, c)){ - buf[x++] = (tohex(c)<<4) | tohex(data[i+1]); - i += 2; - continue; - } - i++; - } - loadimage(b, Rect(0, 0, 16, 32), buf, sizeof buf); - free(data); - }else if(memcmp(buf, "0x", 2)==0){ - /* - * face file - */ - face = FACE; - s = 0; - data = malloc(d->length+1); - if(data == 0){ - mesg("can't malloc buffer: %r"); - close(fd); - goto Err; - } - data[d->length] = 0; - if(read(fd, data, d->length) != d->length){ - mesg("can't read bitmap file %s: %r", file); - close(fd); - goto Err; - } - for(y=0,i=0; i<d->length; i++) - if(data[i] == '\n') - y++; - if(y == 0){ - ill: - mesg("ill-formed face file %s", file); - close(fd); - free(data); - goto Err; - } - for(x=0,i=0; (c=data[i])!='\n'; ){ - if(c==',' || c==' ' || c=='\t'){ - i++; - continue; - } - if(c=='0' && data[i+1] == 'x'){ - i += 2; - continue; - } - if(strchr(hex, c)){ - x += 4; - i++; - continue; - } - goto ill; - } - if(x % y) - goto ill; - switch(x / y){ - default: - goto ill; - case 1: - chan = GREY1; - break; - case 2: - chan = GREY2; - break; - case 4: - chan = GREY4; - break; - case 8: - chan = CMAP8; - break; - } - b = allocimage(display, Rect(0, 0, y, y), chan, 0, -1); - if(b == 0){ - mesg("image alloc failed file %s: %r", file); - free(data); - close(fd); - goto Err; - } - i = 0; - for(j=0; j<y; j++){ - for(x=0; (c=data[i])!='\n'; ){ - if(c=='0' && data[i+1] == 'x'){ - i += 2; - continue; - } - if(strchr(hex, c)){ - buf[x++] = ~((tohex(c)<<4) | tohex(data[i+1])); - i += 2; - continue; - } - i++; - } - i++; - loadimage(b, Rect(0, j, y, j+1), buf, sizeof buf); - } - free(data); - }else{ - face = NORMAL; - s = 0; - b = readimage(display, fd, 0); - if(b == 0){ - mesg("can't read bitmap file %s: %r", file); - close(fd); - goto Err; - } - if(seek(fd, 0, 1) < d->length) - s = readsubfonti(display, file, fd, b, 0); - } - close(fd); - t = malloc(sizeof(Thing)); - if(t == 0){ - nomem: - mesg("malloc failed: %r"); - if(s) - freesubfont(s); - else - freeimage(b); - goto Err; - } - t->name = strdup(file); - if(t->name == 0){ - free(t); - goto nomem; - } - t->b = b; - t->s = s; - t->face = face; - t->mod = 0; - t->parent = 0; - t->c = -1; - t->mag = 1; - t->off = 0; - memmove(err, oerr, sizeof err); - return t; -} - -int -atline(int x, Point p, char *line, char *buf) -{ - char *s, *c, *word, *hit; - int w, wasblank; - Rune r; - - wasblank = 1; - hit = 0; - word = 0; - for(s=line; *s; s+=w){ - w = chartorune(&r, s); - x += runestringnwidth(font, &r, 1); - if(wasblank && r!=' ') - word = s; - wasblank = 0; - if(r == ' '){ - if(x >= p.x) - break; - wasblank = 1; - } - if(r == ':') - hit = word; - } - if(x < p.x) - return 0; - c = utfrune(hit, ':'); - strncpy(buf, hit, c-hit); - buf[c-hit] = 0; - return 1; -} - -int -attext(Thing *t, Point p, char *buf) -{ - char l0[256], l1[256]; - - if(!ptinrect(p, t->tr)) - return 0; - stext(t, l0, l1); - if(p.y < t->tr.min.y+font->height) - return atline(t->r.min.x, p, l0, buf); - else - return atline(t->r.min.x, p, l1, buf); -} - -int -type(char *buf, char *tag) -{ - Rune r; - char *p; - - esetcursor(&busy); - p = buf; - for(;;){ - *p = 0; - mesg("%s: %s", tag, buf); - r = ekbd(); - switch(r){ - case '\n': - mesg(""); - esetcursor(0); - return p-buf; - case 0x15: /* control-U */ - p = buf; - break; - case '\b': - if(p > buf) - --p; - break; - default: - p += runetochar(p, &r); - } - } - return 0; /* shut up compiler */ -} - -void -textedit(Thing *t, char *tag) -{ - char buf[256]; - char *s; - Image *b; - Subfont *f; - Fontchar *fc, *nfc; - Rectangle r; - ulong chan; - int i, ld, d, w, c, doredraw, fdx, x; - Thing *nt; - - buttons(Up); - if(type(buf, tag) == 0) - return; - if(strcmp(tag, "file") == 0){ - for(s=buf; *s; s++) - if(*s <= ' '){ - mesg("illegal file name"); - return; - } - if(strcmp(t->name, buf) != 0){ - if(t->parent) - t->parent->mod = 1; - else - t->mod = 1; - } - for(nt=thing; nt; nt=nt->next) - if(t==nt || t->parent==nt || nt->parent==t){ - free(nt->name); - nt->name = strdup(buf); - if(nt->name == 0){ - mesg("malloc failed: %r"); - return; - } - text(nt); - } - return; - } - if(strcmp(tag, "depth") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (d=atoi(buf))<0 || d>8 || xlog2(d)<0){ - mesg("illegal ldepth"); - return; - } - if(d == t->b->depth) - return; - if(t->parent) - t->parent->mod = 1; - else - t->mod = 1; - if(d == 8) - chan = CMAP8; - else - chan = CHAN1(CGrey, d); - for(nt=thing; nt; nt=nt->next){ - if(nt!=t && nt!=t->parent && nt->parent!=t) - continue; - b = allocimage(display, nt->b->r, chan, 0, 0); - if(b == 0){ - nobmem: - mesg("image alloc failed: %r"); - return; - } - draw(b, b->r, nt->b, nil, nt->b->r.min); - freeimage(nt->b); - nt->b = b; - if(nt->s){ - b = allocimage(display, nt->b->r, chan, 0, -1); - if(b == 0) - goto nobmem; - draw(b, b->r, nt->b, nil, nt->b->r.min); - f = allocsubfont(t->name, nt->s->n, nt->s->height, nt->s->ascent, nt->s->info, b); - if(f == 0){ - nofmem: - freeimage(b); - mesg("can't make subfont: %r"); - return; - } - nt->s->info = 0; /* prevent it being freed */ - nt->s->bits = 0; - freesubfont(nt->s); - nt->s = f; - } - drawthing(nt, 0); - } - return; - } - if(strcmp(tag, "mag") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<=0 || ld>Maxmag){ - mesg("illegal magnification"); - return; - } - if(t->mag == ld) - return; - t->mag = ld; - redraw(t); - return; - } - if(strcmp(tag, "r") == 0){ - if(t->s){ - mesg("can't change rectangle of subfont\n"); - return; - } - s = buf; - r.min.x = strtoul(s, &s, 0); - r.min.y = strtoul(s, &s, 0); - r.max.x = strtoul(s, &s, 0); - r.max.y = strtoul(s, &s, 0); - if(Dx(r)<=0 || Dy(r)<=0){ - mesg("illegal rectangle"); - return; - } - if(t->parent) - t = t->parent; - for(nt=thing; nt; nt=nt->next){ - if(nt->parent==t && !rectinrect(nt->b->r, r)) - tclose1(nt); - } - b = allocimage(display, r, t->b->chan, 0, 0); - if(b == 0) - goto nobmem; - draw(b, r, t->b, nil, r.min); - freeimage(t->b); - t->b = b; - b = allocimage(display, r, t->b->chan, 0, 0); - if(b == 0) - goto nobmem; - redraw(t); - t->mod = 1; - return; - } - if(strcmp(tag, "ascent") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0 || ld>t->s->height){ - mesg("illegal ascent"); - return; - } - if(t->s->ascent == ld) - return; - t->s->ascent = ld; - text(t); - t->mod = 1; - return; - } - if(strcmp(tag, "height") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){ - mesg("illegal height"); - return; - } - if(t->s->height == ld) - return; - t->s->height = ld; - text(t); - t->mod = 1; - return; - } - if(strcmp(tag, "left")==0 || strcmp(tag, "width") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){ - mesg("illegal value"); - return; - } - fc = &t->parent->s->info[t->c]; - if(strcmp(tag, "left")==0){ - if(fc->left == ld) - return; - fc->left = ld; - }else{ - if(fc->width == ld) - return; - fc->width = ld; - } - text(t); - t->parent->mod = 1; - return; - } - if(strcmp(tag, "offset(hex)") == 0){ - if(!strchr(hex, buf[0])){ - illoff: - mesg("illegal offset"); - return; - } - s = 0; - ld = strtoul(buf, &s, 16); - if(*s) - goto illoff; - t->off = ld; - text(t); - for(nt=thing; nt; nt=nt->next) - if(nt->parent == t) - text(nt); - return; - } - if(strcmp(tag, "n") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<=0){ - mesg("illegal n"); - return; - } - f = t->s; - if(w == f->n) - return; - doredraw = 0; - again: - for(nt=thing; nt; nt=nt->next) - if(nt->parent == t){ - doredraw = 1; - tclose1(nt); - goto again; - } - r = t->b->r; - if(w < f->n) - r.max.x = f->info[w].x; - b = allocimage(display, r, t->b->chan, 0, 0); - if(b == 0) - goto nobmem; - draw(b, b->r, t->b, nil, r.min); - fdx = Dx(editr) - 2*Border; - if(Dx(t->b->r)/fdx != Dx(b->r)/fdx) - doredraw = 1; - freeimage(t->b); - t->b = b; - b = allocimage(display, r, t->b->chan, 0, 0); - if(b == 0) - goto nobmem; - draw(b, b->r, t->b, nil, r.min); - nfc = malloc((w+1)*sizeof(Fontchar)); - if(nfc == 0){ - mesg("malloc failed"); - freeimage(b); - return; - } - fc = f->info; - for(i=0; i<=w && i<=f->n; i++) - nfc[i] = fc[i]; - if(w+1 < i) - memset(nfc+i, 0, ((w+1)-i)*sizeof(Fontchar)); - x = fc[f->n].x; - for(; i<=w; i++) - nfc[i].x = x; - f = allocsubfont(t->name, w, f->height, f->ascent, nfc, b); - if(f == 0) - goto nofmem; - t->s->bits = nil; /* don't free it */ - freesubfont(t->s); - f->info = nfc; - t->s = f; - if(doredraw) - redraw(thing); - else - drawthing(t, 0); - t->mod = 1; - return; - } - if(strcmp(tag, "iwidth") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<0){ - mesg("illegal iwidth"); - return; - } - w -= Dx(t->b->r); - if(w == 0) - return; - r = t->parent->b->r; - r.max.x += w; - c = t->c; - t = t->parent; - f = t->s; - b = allocimage(display, r, t->b->chan, 0, 0); - if(b == 0) - goto nobmem; - fc = &f->info[c]; - draw(b, Rect(b->r.min.x, b->r.min.y, - b->r.min.x+(fc[1].x-t->b->r.min.x), b->r.min.y+Dy(t->b->r)), - t->b, nil, t->b->r.min); - draw(b, Rect(fc[1].x+w, b->r.min.y, w+t->b->r.max.x, b->r.min.y+Dy(t->b->r)), - t->b, nil, Pt(fc[1].x, t->b->r.min.y)); - fdx = Dx(editr) - 2*Border; - doredraw = 0; - if(Dx(t->b->r)/fdx != Dx(b->r)/fdx) - doredraw = 1; - freeimage(t->b); - t->b = b; - b = allocimage(display, r, t->b->chan, 0, 0); - if(b == 0) - goto nobmem; - draw(b, b->r, t->b, nil, t->b->r.min); - fc = &f->info[c+1]; - for(i=c+1; i<=f->n; i++, fc++) - fc->x += w; - f = allocsubfont(t->name, f->n, f->height, f->ascent, - f->info, b); - if(f == 0) - goto nofmem; - /* t->s and f share info; free carefully */ - fc = f->info; - t->s->bits = nil; - t->s->info = 0; - freesubfont(t->s); - f->info = fc; - t->s = f; - if(doredraw) - redraw(t); - else - drawthing(t, 0); - /* redraw all affected chars */ - for(nt=thing; nt; nt=nt->next){ - if(nt->parent!=t || nt->c<c) - continue; - fc = &f->info[nt->c]; - r.min.x = fc[0].x; - r.min.y = nt->b->r.min.y; - r.max.x = fc[1].x; - r.max.y = nt->b->r.max.y; - b = allocimage(display, r, nt->b->chan, 0, 0); - if(b == 0) - goto nobmem; - draw(b, r, t->b, nil, r.min); - doredraw = 0; - if(Dx(nt->b->r)/fdx != Dx(b->r)/fdx) - doredraw = 1; - freeimage(nt->b); - nt->b = b; - if(c != nt->c) - text(nt); - else{ - if(doredraw) - redraw(nt); - else - drawthing(nt, 0); - } - } - t->mod = 1; - return; - } - mesg("cannot edit %s in file %s", tag, t->name); -} - -void -cntledit(char *tag) -{ - char buf[256]; - ulong l; - - buttons(Up); - if(type(buf, tag) == 0) - return; - if(strcmp(tag, "mag") == 0){ - if(buf[0]<'0' || '9'<buf[0] || (l=atoi(buf))<=0 || l>Maxmag){ - mesg("illegal magnification"); - return; - } - mag = l; - cntl(); - return; - } - if(strcmp(tag, "but1")==0 - || strcmp(tag, "but2")==0){ - if(buf[0]<'0' || '9'<buf[0] || (l=atoi(buf))<0 || l>255){ - mesg("illegal value"); - return; - } - if(strcmp(tag, "but1") == 0) - but1val = l; - else if(strcmp(tag, "but2") == 0) - but2val = l; - cntl(); - return; - } - if(strcmp(tag, "invert-on-copy")==0){ - if(buf[0]=='y' || buf[0]=='1') - invert = 1; - else if(buf[0]=='n' || buf[0]=='0') - invert = 0; - else{ - mesg("illegal value"); - return; - } - cntl(); - return; - } - mesg("cannot edit %s", tag); -} - -void -buttons(int ud) -{ - while((mouse.buttons==0) != ud) - mouse = emouse(); -} - -Point -screenpt(Thing *t, Point realp) -{ - int fdx, n; - Point p; - - fdx = Dx(editr)-2*Border; - if(t->mag > 1) - fdx -= fdx%t->mag; - p = mulpt(subpt(realp, t->b->r.min), t->mag); - if(fdx < Dx(t->b->r)*t->mag){ - n = p.x/fdx; - p.y += n * (Dy(t->b->r)*t->mag+Border); - p.x -= n * fdx; - } - p = addpt(p, t->r.min); - return p; -} - -Point -realpt(Thing *t, Point screenp) -{ - int fdx, n, dy; - Point p; - - fdx = (Dx(editr)-2*Border); - if(t->mag > 1) - fdx -= fdx%t->mag; - p.y = screenp.y-t->r.min.y; - p.x = 0; - if(fdx < Dx(t->b->r)*t->mag){ - dy = Dy(t->b->r)*t->mag+Border; - n = (p.y/dy); - p.x = n * fdx; - p.y -= n * dy; - } - p.x += screenp.x-t->r.min.x; - p = addpt(divpt(p, t->mag), t->b->r.min); - return p; -} - -int -sweep(int but, Rectangle *r) -{ - Thing *t; - Point p, q, lastq; - - esetcursor(&sweep0); - buttons(Down); - if(mouse.buttons != (1<<(but-1))){ - buttons(Up); - esetcursor(0); - return 0; - } - p = mouse.xy; - for(t=thing; t; t=t->next) - if(ptinrect(p, t->r)) - break; - if(t) - p = screenpt(t, realpt(t, p)); - r->min = p; - r->max = p; - esetcursor(&box); - lastq = ZP; - while(mouse.buttons == (1<<(but-1))){ - edrawgetrect(insetrect(*r, -Borderwidth), 1); - mouse = emouse(); - edrawgetrect(insetrect(*r, -Borderwidth), 0); - q = mouse.xy; - if(t) - q = screenpt(t, realpt(t, q)); - if(eqpt(q, lastq)) - continue; - *r = canonrect(Rpt(p, q)); - lastq = q; - } - esetcursor(0); - if(mouse.buttons){ - buttons(Up); - return 0; - } - return 1; -} - -void -openedit(Thing *t, Point pt, int c) -{ - int x, y; - Point p; - Rectangle r; - Rectangle br; - Fontchar *fc; - Thing *nt; - - if(t->b->depth > 8){ - mesg("image has depth %d; can't handle >8", t->b->depth); - return; - } - br = t->b->r; - if(t->s == 0){ - c = -1; - /* if big enough to bother, sweep box */ - if(Dx(br)<=16 && Dy(br)<=16) - r = br; - else{ - if(!sweep(1, &r)) - return; - r = rectaddpt(r, subpt(br.min, t->r.min)); - if(!rectclip(&r, br)) - return; - if(Dx(br) <= 8){ - r.min.x = br.min.x; - r.max.x = br.max.x; - }else if(Dx(r) < 4){ - toosmall: - mesg("rectangle too small"); - return; - } - if(Dy(br) <= 8){ - r.min.y = br.min.y; - r.max.y = br.max.y; - }else if(Dy(r) < 4) - goto toosmall; - } - }else if(c >= 0){ - fc = &t->s->info[c]; - r.min.x = fc[0].x; - r.min.y = br.min.y; - r.max.x = fc[1].x; - r.max.y = br.min.y + Dy(br); - }else{ - /* just point at character */ - fc = t->s->info; - p = addpt(pt, subpt(br.min, t->r.min)); - x = br.min.x; - y = br.min.y; - for(c=0; c<t->s->n; c++,fc++){ - again: - r.min.x = x; - r.min.y = y; - r.max.x = x + fc[1].x - fc[0].x; - r.max.y = y + Dy(br); - if(ptinrect(p, r)) - goto found; - if(r.max.x >= br.min.x+Dx(t->r)){ - x -= Dx(t->r); - y += t->s->height; - if(fc[1].x > fc[0].x) - goto again; - } - x += fc[1].x - fc[0].x; - } - return; - found: - r = br; - r.min.x = fc[0].x; - r.max.x = fc[1].x; - } - nt = malloc(sizeof(Thing)); - if(nt == 0){ - nomem: - mesg("can't allocate: %r"); - return; - } - memset(nt, 0, sizeof(Thing)); - nt->c = c; - nt->b = allocimage(display, r, t->b->chan, 0, DNofill); - if(nt->b == 0){ - free(nt); - goto nomem; - } - draw(nt->b, r, t->b, nil, r.min); - nt->name = strdup(t->name); - if(nt->name == 0){ - freeimage(nt->b); - free(nt); - goto nomem; - } - nt->parent = t; - nt->mag = mag; - drawthing(nt, 1); -} - -void -ckinfo(Thing *t, Rectangle mod) -{ - int i, j, k, top, bot, n, zero; - Fontchar *fc; - Rectangle r; - Image *b; - Thing *nt; - - if(t->parent) - t = t->parent; - if(t->s==0 || Dy(t->b->r)==0) - return; - b = 0; - /* check bounding boxes */ - fc = &t->s->info[0]; - r.min.y = t->b->r.min.y; - r.max.y = t->b->r.max.y; - for(i=0; i<t->s->n; i++, fc++){ - r.min.x = fc[0].x; - r.max.x = fc[1].x; - if(!rectXrect(mod, r)) - continue; - if(b==0 || Dx(b->r)<Dx(r)){ - if(b) - freeimage(b); - b = allocimage(display, rectsubpt(r, r.min), t->b->chan, 0, 0); - if(b == 0){ - mesg("can't alloc image"); - break; - } - } - draw(b, b->r, display->white, nil, ZP); - draw(b, b->r, t->b, nil, r.min); - top = 100000; - bot = 0; - n = 2+((Dx(r)/8)*t->b->depth); - for(j=0; j<b->r.max.y; j++){ - memset(data, 0, n); - unloadimage(b, Rect(b->r.min.x, j, b->r.max.x, j+1), data, sizeof data); - zero = 1; - for(k=0; k<n; k++) - if(data[k]){ - zero = 0; - break; - } - if(!zero){ - if(top > j) - top = j; - bot = j+1; - } - } - if(top > j) - top = 0; - if(top!=fc->top || bot!=fc->bottom){ - fc->top = top; - fc->bottom = bot; - for(nt=thing; nt; nt=nt->next) - if(nt->parent==t && nt->c==i) - text(nt); - } - } - if(b) - freeimage(b); -} - -void -twidpix(Thing *t, Point p, int set) -{ - Image *b, *v; - int c; - - b = t->b; - if(!ptinrect(p, b->r)) - return; - if(set) - c = but1val; - else - c = but2val; - if(b->chan == GREY8) - v = greyvalues[c]; - else - v = values[c]; - draw(b, Rect(p.x, p.y, p.x+1, p.y+1), v, nil, ZP); - p = screenpt(t, p); - draw(screen, Rect(p.x, p.y, p.x+t->mag, p.y+t->mag), v, nil, ZP); -} - -void -twiddle(Thing *t) -{ - int set; - Point p, lastp; - Image *b; - Thing *nt; - Rectangle mod; - - if(mouse.buttons!=1 && mouse.buttons!=2){ - buttons(Up); - return; - } - set = mouse.buttons==1; - b = t->b; - lastp = addpt(b->r.min, Pt(-1, -1)); - mod = Rpt(addpt(b->r.max, Pt(1, 1)), lastp); - while(mouse.buttons){ - p = realpt(t, mouse.xy); - if(!eqpt(p, lastp)){ - lastp = p; - if(ptinrect(p, b->r)){ - for(nt=thing; nt; nt=nt->next) - if(nt->parent==t->parent || nt==t->parent) - twidpix(nt, p, set); - if(t->parent) - t->parent->mod = 1; - else - t->mod = 1; - if(p.x < mod.min.x) - mod.min.x = p.x; - if(p.y < mod.min.y) - mod.min.y = p.y; - if(p.x >= mod.max.x) - mod.max.x = p.x+1; - if(p.y >= mod.max.y) - mod.max.y = p.y+1; - } - } - mouse = emouse(); - } - ckinfo(t, mod); -} - -void -xselect(void) -{ - Thing *t; - char line[128], buf[128]; - Point p; - - if(ptinrect(mouse.xy, cntlr)){ - scntl(line); - if(atline(cntlr.min.x, mouse.xy, line, buf)){ - if(mouse.buttons == 1) - cntledit(buf); - else - buttons(Up); - return; - } - return; - } - for(t=thing; t; t=t->next){ - if(attext(t, mouse.xy, buf)){ - if(mouse.buttons == 1) - textedit(t, buf); - else - buttons(Up); - return; - } - if(ptinrect(mouse.xy, t->r)){ - if(t->parent == 0){ - if(mouse.buttons == 1){ - p = mouse.xy; - buttons(Up); - openedit(t, p, -1); - }else - buttons(Up); - return; - } - twiddle(t); - return; - } - } -} - -void -twrite(Thing *t) -{ - int i, j, x, y, fd, ws, ld; - Biobuf buf; - Rectangle r; - - if(t->parent) - t = t->parent; - esetcursor(&busy); - fd = create(t->name, OWRITE, 0666); - if(fd < 0){ - mesg("can't write %s: %r", t->name); - return; - } - if(t->face && t->b->depth <= 4){ - r = t->b->r; - ld = xlog2(t->b->depth); - /* This heuristic reflects peculiarly different formats */ - ws = 4; - if(t->face == 2) /* cursor file */ - ws = 1; - else if(Dx(r)<32 || ld==0) - ws = 2; - Binit(&buf, fd, OWRITE); - if(t->face == CURSOR) - Bprint(&buf, "{"); - for(y=r.min.y; y<r.max.y; y++){ - unloadimage(t->b, Rect(r.min.x, y, r.max.x, y+1), data, sizeof data); - j = 0; - for(x=r.min.x; x<r.max.x; j+=ws,x+=ws*8>>ld){ - Bprint(&buf, "0x"); - for(i=0; i<ws; i++) - Bprint(&buf, "%.2x", data[i+j]); - Bprint(&buf, ", "); - } - if(t->face == CURSOR){ - switch(y){ - case 3: case 7: case 11: case 19: case 23: case 27: - Bprint(&buf, "\n "); - break; - case 15: - Bprint(&buf, "},\n{"); - break; - case 31: - Bprint(&buf, "}\n"); - break; - } - }else - Bprint(&buf, "\n"); - } - Bterm(&buf); - }else - if(writeimage(fd, t->b, 0)<0 || (t->s && writesubfont(fd, t->s)<0)){ - close(fd); - mesg("can't write %s: %r", t->name); - } - t->mod = 0; - close(fd); - mesg("wrote %s", t->name); -} - -void -tpixels(void) -{ - Thing *t; - Point p, lastp; - - esetcursor(&pixel); - for(;;){ - buttons(Down); - if(mouse.buttons != 4) - break; - for(t=thing; t; t=t->next){ - lastp = Pt(-1, -1); - if(ptinrect(mouse.xy, t->r)){ - while(ptinrect(mouse.xy, t->r) && mouse.buttons==4){ - p = realpt(t, mouse.xy); - if(!eqpt(p, lastp)){ - if(p.y != lastp.y) - unloadimage(t->b, Rect(t->b->r.min.x, p.y, t->b->r.max.x, p.y+1), data, sizeof data); - mesg("[%d,%d] = %d=0x%ux", p.x, p.y, value(t->b, p.x), value(t->b, p.x)); - lastp = p; - } - mouse = emouse(); - } - goto Continue; - } - } - mouse = emouse(); - Continue:; - } - buttons(Up); - esetcursor(0); -} - -void -tclose1(Thing *t) -{ - Thing *nt; - - if(t == thing) - thing = t->next; - else{ - for(nt=thing; nt->next!=t; nt=nt->next) - ; - nt->next = t->next; - } - do - for(nt=thing; nt; nt=nt->next) - if(nt->parent == t){ - tclose1(nt); - break; - } - while(nt); - if(t->s) - freesubfont(t->s); - else - freeimage(t->b); - free(t->name); - free(t); -} - -void -tclose(Thing *t) -{ - Thing *ct; - - if(t->mod){ - mesg("%s modified", t->name); - t->mod = 0; - return; - } - /* fiddle to save redrawing unmoved things */ - if(t == thing) - ct = 0; - else - for(ct=thing; ct; ct=ct->next) - if(ct->next==t || ct->next->parent==t) - break; - tclose1(t); - if(ct) - ct = ct->next; - else - ct = thing; - redraw(ct); -} - -void -tread(Thing *t) -{ - Thing *nt, *new; - Fontchar *i; - Rectangle r; - int nclosed; - - if(t->parent) - t = t->parent; - new = tget(t->name); - if(new == 0) - return; - nclosed = 0; - again: - for(nt=thing; nt; nt=nt->next) - if(nt->parent == t){ - if(!rectinrect(nt->b->r, new->b->r) - || new->b->depth!=nt->b->depth){ - closeit: - nclosed++; - nt->parent = 0; - tclose1(nt); - goto again; - } - if((t->s==0) != (new->s==0)) - goto closeit; - if((t->face==0) != (new->face==0)) - goto closeit; - if(t->s){ /* check same char */ - if(nt->c >= new->s->n) - goto closeit; - i = &new->s->info[nt->c]; - r.min.x = i[0].x; - r.max.x = i[1].x; - r.min.y = new->b->r.min.y; - r.max.y = new->b->r.max.y; - if(!eqrect(r, nt->b->r)) - goto closeit; - } - nt->parent = new; - draw(nt->b, nt->b->r, new->b, nil, nt->b->r.min); - } - new->next = t->next; - if(t == thing) - thing = new; - else{ - for(nt=thing; nt->next!=t; nt=nt->next) - ; - nt->next = new; - } - if(t->s) - freesubfont(t->s); - else - freeimage(t->b); - free(t->name); - free(t); - for(nt=thing; nt; nt=nt->next) - if(nt==new || nt->parent==new) - if(nclosed == 0) - drawthing(nt, 0); /* can draw in place */ - else{ - redraw(nt); /* must redraw all below */ - break; - } -} - -void -tchar(Thing *t) -{ - char buf[256], *p; - Rune r; - ulong c, d; - - if(t->s == 0){ - t = t->parent; - if(t==0 || t->s==0){ - mesg("not a subfont"); - return; - } - } - if(type(buf, "char (hex or character or hex-hex)") == 0) - return; - if(utflen(buf) == 1){ - chartorune(&r, buf); - c = r; - d = r; - }else{ - if(!strchr(hex, buf[0])){ - mesg("illegal hex character"); - return; - } - c = strtoul(buf, 0, 16); - d = c; - p = utfrune(buf, '-'); - if(p){ - d = strtoul(p+1, 0, 16); - if(d < c){ - mesg("invalid range"); - return; - } - } - } - c -= t->off; - d -= t->off; - while(c <= d){ - if(c<0 || c>=t->s->n){ - mesg("0x%lux not in font %s", c+t->off, t->name); - return; - } - openedit(t, Pt(0, 0), c); - c++; - } -} - -void -apply(void (*f)(Thing*)) -{ - Thing *t; - - esetcursor(&sight); - buttons(Down); - if(mouse.buttons == 4) - for(t=thing; t; t=t->next) - if(ptinrect(mouse.xy, t->er)){ - buttons(Up); - f(t); - break; - } - buttons(Up); - esetcursor(0); -} - -int -complement(Image *t) -{ - int i, n; - uchar *buf; - - n = Dy(t->r)*bytesperline(t->r, t->depth); - buf = malloc(n); - if(buf == 0) - return 0; - unloadimage(t, t->r, buf, n); - for(i=0; i<n; i++) - buf[i] = ~buf[i]; - loadimage(t, t->r, buf, n); - free(buf); - return 1; -} - -void -copy(void) -{ - Thing *st, *dt, *nt; - Rectangle sr, dr, fr; - Image *tmp; - Point p1, p2; - int but, up; - - if(!sweep(3, &sr)) - return; - for(st=thing; st; st=st->next) - if(rectXrect(sr, st->r)) - break; - if(st == 0) - return; - /* click gives full rectangle */ - if(Dx(sr)<4 && Dy(sr)<4) - sr = st->r; - rectclip(&sr, st->r); - p1 = realpt(st, sr.min); - p2 = realpt(st, Pt(sr.min.x, sr.max.y)); - up = 0; - if(p1.x != p2.x){ /* swept across a fold */ - onafold: - mesg("sweep spans a fold"); - goto Return; - } - p2 = realpt(st, sr.max); - sr.min = p1; - sr.max = p2; - fr.min = screenpt(st, sr.min); - fr.max = screenpt(st, sr.max); - p1 = subpt(p2, p1); /* diagonal */ - if(p1.x==0 || p1.y==0) - return; - border(screen, fr, -1, values[Blue], ZP); - esetcursor(&box); - for(; mouse.buttons==0; mouse=emouse()){ - for(dt=thing; dt; dt=dt->next) - if(ptinrect(mouse.xy, dt->er)) - break; - if(up) - edrawgetrect(insetrect(dr, -Borderwidth), 0); - up = 0; - if(dt == 0) - continue; - dr.max = screenpt(dt, realpt(dt, mouse.xy)); - dr.min = subpt(dr.max, mulpt(p1, dt->mag)); - if(!rectXrect(dr, dt->r)) - continue; - edrawgetrect(insetrect(dr, -Borderwidth), 1); - up = 1; - } - /* if up==1, we had a hit */ - esetcursor(0); - if(up) - edrawgetrect(insetrect(dr, -Borderwidth), 0); - but = mouse.buttons; - buttons(Up); - if(!up || but!=4) - goto Return; - dt = 0; - for(nt=thing; nt; nt=nt->next) - if(rectXrect(dr, nt->r)){ - if(dt){ - mesg("ambiguous sweep"); - return; - } - dt = nt; - } - if(dt == 0) - goto Return; - p1 = realpt(dt, dr.min); - p2 = realpt(dt, Pt(dr.min.x, dr.max.y)); - if(p1.x != p2.x) - goto onafold; - p2 = realpt(dt, dr.max); - dr.min = p1; - dr.max = p2; - - if(invert){ - tmp = allocimage(display, dr, dt->b->chan, 0, 255); - if(tmp == 0){ - nomem: - mesg("can't allocate temporary"); - goto Return; - } - draw(tmp, dr, st->b, nil, sr.min); - if(!complement(tmp)) - goto nomem; - draw(dt->b, dr, tmp, nil, dr.min); - freeimage(tmp); - }else - draw(dt->b, dr, st->b, nil, sr.min); - if(dt->parent){ - draw(dt->parent->b, dr, dt->b, nil, dr.min); - dt = dt->parent; - } - drawthing(dt, 0); - for(nt=thing; nt; nt=nt->next) - if(nt->parent==dt && rectXrect(dr, nt->b->r)){ - draw(nt->b, dr, dt->b, nil, dr.min); - drawthing(nt, 0); - } - ckinfo(dt, dr); - dt->mod = 1; - -Return: - /* clear blue box */ - drawthing(st, 0); -} - -void -menu(void) -{ - Thing *t; - char *mod; - int sel; - char buf[256]; - - sel = emenuhit(3, &mouse, &menu3); - switch(sel){ - case Mopen: - if(type(buf, "file")){ - t = tget(buf); - if(t) - drawthing(t, 1); - } - break; - case Mwrite: - apply(twrite); - break; - case Mread: - apply(tread); - break; - case Mchar: - apply(tchar); - break; - case Mcopy: - copy(); - break; - case Mpixels: - tpixels(); - break; - case Mclose: - apply(tclose); - break; - case Mexit: - mod = 0; - for(t=thing; t; t=t->next) - if(t->mod){ - mod = t->name; - t->mod = 0; - } - if(mod){ - mesg("%s modified", mod); - break; - } - esetcursor(&skull); - buttons(Down); - if(mouse.buttons == 4){ - buttons(Up); - exits(0); - } - buttons(Up); - esetcursor(0); - break; - } -} |