📄 tweak.c
字号:
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);}voidckinfo(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);}voidtwidpix(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);}voidtwiddle(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);}voidselect(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; } }}voidtwrite(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 = log2[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);}voidtpixels(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);}voidtclose1(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);}voidtclose(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);}voidtread(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; }}voidtchar(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++; }}voidapply(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);}intcomplement(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;}voidcopy(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);}voidmenu(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; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -