📄 tweak.c
字号:
#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[] = { [Mopen] "open", [Mread] "read", [Mwrite] "write", [Mcopy] "copy", [Mchar] "char", [Mpixels] "pixels", [Mclose] "close", [Mexit] "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 select(void);void menu(void);void error(Display*, char*);void buttons(int);void drawall(void);void tclose1(Thing*);voidmain(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){ select(); break; } if(mouse.buttons & 4) menu(); }}voiderror(Display*, char *s){ 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);}voidredraw(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("");}voideresized(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();}voidmesgstr(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);}voidmesg(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);}voidtmesg(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);}voidscntl(char *l){ sprint(l, "mag: %d but1: %d but2: %d invert-on-copy: %c", mag, but1val, but2val, "ny"[invert]);}voidcntl(void){ char buf[256]; scntl(buf); mesgstr(cntlr.min, 0, buf);}voidstext(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);}voidtext(Thing *t){ char l0[256], l1[256]; stext(t, l0, l1); tmesg(t, 0, l0); if(l1[0]) tmesg(t, 1, l1);}voiddrawall(void){ Thing *t; cntl(); for(t=thing; t; t=t->next) drawthing(t, 0);}intvalue(Image *b, int x){ int v, l, w; uchar mask; w = b->depth; if(w > 8){ mesg("ldepth too large"); return 0; } l = log2[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;}intbvalue(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;}voiddrawthing(Thing *nt, int link){ int 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; unloadimage(b, Rect(b->r.min.x, y, b->r.max.x, y+1), data, sizeof data); 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);}inttohex(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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -