📄 view.c
字号:
{ Xentry *t = (Xentry*)tt; if(t->nkid >= 0) return; t->nkid = 1; t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1); t->kid[0] = initxsource(t->e, 1);}Tnode*initxentry(Entry e){ Xentry *t; t = mallocz(sizeof *t, 1); t->nkid = -1; t->str = smprint("Entry gen=%#ux psize=%d dsize=%d depth=%d flags=%#ux size=%lld score=%V", e.gen, e.psize, e.dsize, e.depth, e.flags, e.size, e.score); if(e.flags & VtEntryLocal) t->str = smprint("%s archive=%d snap=%d tag=%#ux", t->str, e.archive, e.snap, e.tag); t->expand = xentryexpand; t->e = e; return t; }intptrgen(void *v, Block *b, int o, Tnode **tp){ Entry *ed; Entry e; ed = v; if(o >= ed->psize/VtScoreSize) return -1; e = *ed; e.depth--; memmove(e.score, b->data+o*VtScoreSize, VtScoreSize); if(memcmp(e.score, vtZeroScore, VtScoreSize) == 0) return 0; *tp = initxsource(e, 0); return 1;}static intetype(int flags, int depth){ uint t; if(flags&VtEntryDir) t = BtDir; else t = BtData; return t+depth;}Tnode*initxsource(Entry e, int dowrap){ Block *b; Tnode *t, *tt; b = dataBlock(e.score, etype(e.flags, e.depth), e.tag); if(b == nil) return stringnode("dataBlock: %r"); if((e.flags & VtEntryActive) == 0) return stringnode("inactive Entry"); if(e.depth == 0){ if(e.flags & VtEntryDir) tt = initxentryblock(b, copyEntry(e)); else tt = initxdatablock(b, e.dsize); }else{ tt = initxblock(b, smprint("%s+%d pointer", (e.flags & VtEntryDir) ? "BtDir" : "BtData", e.depth), ptrgen, copyEntry(e)); } /* * wrap the contents of the Source in a Source node, * just so it's closer to what you see in the code. */ if(dowrap){ t = stringnode("Source"); t->nkid = 1; t->kid = mallocz(sizeof(Tnode*)*1, 1); t->kid[0] = tt; tt = t; } return tt;}intxlocalrootgen(void*, Block *b, int o, Tnode **tp){ Entry e; if(o >= 1) return -1; entryUnpack(&e, b->data, o); *tp = initxentry(e); return 1;}Tnode*initxlocalroot(char *name, u32int addr){ uchar score[VtScoreSize]; Block *b; localToGlobal(addr, score); b = dataBlock(score, BtDir, RootTag); if(b == nil) return stringnode("read data block %#ux: %R", addr); return initxblock(b, smprint("'%s' fs root", name), xlocalrootgen, nil);}intxvacrootgen(void*, Block *b, int o, Tnode **tp){ Entry e; if(o >= 3) return -1; entryUnpack(&e, b->data, o); *tp = initxentry(e); return 1;}Tnode*initxroot(char *name, uchar score[VtScoreSize]){ Block *b; b = dataBlock(score, BtDir, RootTag); if(b == nil) return stringnode("read data block %V: %R", score); return initxblock(b, smprint("'%s' fs root", name), xvacrootgen, nil);}Tnode*initxdirentry(MetaEntry *me){ DirEntry dir; Tnode *t; if(!deUnpack(&dir, me)) return stringnode("deUnpack: %R"); t = stringnode("dirEntry elem=%s size=%llud data=%#lux/%#lux meta=%#lux/%#lux", dir.elem, dir.size, dir.entry, dir.gen, dir.mentry, dir.mgen); t->nkid = 1; t->kid = mallocz(sizeof(t->kid[0])*1, 1); t->kid[0] = stringnode( "qid=%#llux\n" "uid=%s gid=%s mid=%s\n" "mtime=%lud mcount=%lud ctime=%lud atime=%lud\n" "mode=%luo\n" "plan9 %d p9path %#llux p9version %lud\n" "qidSpace %d offset %#llux max %#llux", dir.qid, dir.uid, dir.gid, dir.mid, dir.mtime, dir.mcount, dir.ctime, dir.atime, dir.mode, dir.plan9, dir.p9path, dir.p9version, dir.qidSpace, dir.qidOffset, dir.qidMax); return t;}intmetaentrygen(void *v, Block*, int o, Tnode **tp){ Tnode *t; MetaBlock *mb; MetaEntry me; mb = v; if(o >= mb->nindex) return -1; meUnpack(&me, mb, o); t = stringnode("MetaEntry %d bytes", mb->size); t->kid = mallocz(sizeof(t->kid[0])*1, 1); t->kid[0] = initxdirentry(&me); t->nkid = 1; *tp = t; return 1;}intmetablockgen(void *v, Block *b, int o, Tnode **tp){ Xblock *t; MetaBlock *mb; if(o >= 1) return -1; /* hack: reuse initxblock as a generic iterator */ mb = v; t = (Xblock*)initxblock(b, "", metaentrygen, mb); t->str = smprint("MetaBlock %d/%d space used, %d add'l free %d/%d table used%s", mb->size, mb->maxsize, mb->free, mb->nindex, mb->maxindex, mb->botch ? " [BOTCH]" : ""); t->printlabel = 0; *tp = t; return 1;}/* * attempt to guess at the type of data in the block. * it could just be data from a file, but we're hoping it's MetaBlocks. */Tnode*initxdatablock(Block *b, uint n){ MetaBlock mb; if(n > h.blockSize) n = h.blockSize; if(mbUnpack(&mb, b->data, n)) return initxblock(b, "metadata", metablockgen, copyMetaBlock(mb)); return initxblock(b, "data", nil, nil);}intparseScore(uchar *score, char *buf, int n){ int i, c; memset(score, 0, VtScoreSize); if(n < VtScoreSize*2) return 0; for(i=0; i<VtScoreSize*2; i++){ if(buf[i] >= '0' && buf[i] <= '9') c = buf[i] - '0'; else if(buf[i] >= 'a' && buf[i] <= 'f') c = buf[i] - 'a' + 10; else if(buf[i] >= 'A' && buf[i] <= 'F') c = buf[i] - 'A' + 10; else{ return 0; } if((i & 1) == 0) c <<= 4; score[i>>1] |= c; } return 1;}intscoreFmt(Fmt *f){ uchar *v; int i; u32int addr; v = va_arg(f->args, uchar*); if(v == nil){ fmtprint(f, "*"); }else if((addr = globalToLocal(v)) != NilBlock) fmtprint(f, "0x%.8ux", addr); else{ for(i = 0; i < VtScoreSize; i++) fmtprint(f, "%2.2ux", v[i]); } return 0;}Atree*atreeinit(char *arg){ Atree *a; uchar score[VtScoreSize]; vtAttach(); fmtinstall('V', scoreFmt); fmtinstall('R', vtErrFmt); z = vtDial(nil, 1); if(z == nil) fprint(2, "warning: cannot dial venti: %R\n"); if(!vtConnect(z, 0)){ fprint(2, "warning: cannot connect to venti: %R\n"); z = nil; } a = mallocz(sizeof(Atree), 1); if(strncmp(arg, "vac:", 4) == 0){ if(!parseScore(score, arg+4, strlen(arg+4))){ fprint(2, "cannot parse score\n"); return nil; } a->root = initxvacroot(score); }else a->root = initxcache(arg); a->resizefd = -1; return a;}/* --- tree.c */enum{ Nubwidth = 11, Nubheight = 11, Linewidth = Nubwidth*2+4,};uintdrawtext(char *s, Image *m, Image *clipr, Point o){ char *t, *nt, *e; uint dy; if(s == nil) s = "???"; dy = 0; for(t=s; t&&*t; t=nt){ if(nt = strchr(t, '\n')){ e = nt; nt++; }else e = t+strlen(t); _string(m, Pt(o.x, o.y+dy), display->black, ZP, display->defaultfont, t, nil, e-t, clipr->clipr, nil, ZP, SoverD); dy += display->defaultfont->height; } return dy;}voiddrawnub(Image *m, Image *clipr, Point o, Tnode *t){ clipr = nil; if(t->nkid == 0) return; if(t->nkid == -1 && t->expand == nil) return; o.y += (display->defaultfont->height-Nubheight)/2; draw(m, rectaddpt(Rect(0,0,1,Nubheight), o), display->black, clipr, ZP); draw(m, rectaddpt(Rect(0,0,Nubwidth,1), o), display->black, clipr, o); draw(m, rectaddpt(Rect(Nubwidth-1,0,Nubwidth,Nubheight), o), display->black, clipr, addpt(o, Pt(Nubwidth-1, 0))); draw(m, rectaddpt(Rect(0, Nubheight-1, Nubwidth, Nubheight), o), display->black, clipr, addpt(o, Pt(0, Nubheight-1))); draw(m, rectaddpt(Rect(0, Nubheight/2, Nubwidth, Nubheight/2+1), o), display->black, clipr, addpt(o, Pt(0, Nubheight/2))); if(!t->expanded) draw(m, rectaddpt(Rect(Nubwidth/2, 0, Nubwidth/2+1, Nubheight), o), display->black, clipr, addpt(o, Pt(Nubwidth/2, 0)));}uintdrawnode(Tnode *t, Image *m, Image *clipr, Point o){ int i; char *fs, *s; uint dy; Point oo; if(t == nil) return 0; t->offset = o; oo = Pt(o.x+Nubwidth+2, o.y);// if(t->draw)// dy = (*t->draw)(t, m, clipr, oo);// else{ fs = nil; if(t->str) s = t->str; // else if(t->strfn) // fs = s = (*t->strfn)(t); else s = "???"; dy = drawtext(s, m, clipr, oo); free(fs);// } if(t->expanded){ if(t->nkid == -1 && t->expand) (*t->expand)(t); oo = Pt(o.x+Nubwidth+(Linewidth-Nubwidth)/2, o.y+dy); for(i=0; i<t->nkid; i++) oo.y += drawnode(t->kid[i], m, clipr, oo); dy = oo.y - o.y; } drawnub(m, clipr, o, t); return dy;}voiddrawtree(Tree *t, Image *m, Rectangle r){ Point p; draw(m, r, display->white, nil, ZP); replclipr(t->clipr, 1, r); p = addpt(t->offset, r.min); drawnode(t->root, m, t->clipr, p);}Tnode*findnode(Tnode *t, Point p){ int i; Tnode *tt; if(ptinrect(p, rectaddpt(Rect(0,0,Nubwidth, Nubheight), t->offset))) return t; if(!t->expanded) return nil; for(i=0; i<t->nkid; i++) if(tt = findnode(t->kid[i], p)) return tt; return nil;}voidusage(void){ fprint(2, "usage: vtree /dev/sdC0/fossil\n"); exits("usage");}Tree t;voideresized(int new){ Rectangle r; r = screen->r; if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window"); drawtree(&t, screen, screen->r);}enum{ Left = 1<<0, Middle = 1<<1, Right = 1<<2, MMenu = 2,};char *items[] = { "exit", 0 };enum { IExit, };Menu menu;voidmain(int argc, char **argv){ int n; char *dir; Event e; Point op, p; Tnode *tn; Mouse m; int Eready; Atree *fs; ARGBEGIN{ case 'a': showinactive = 1; break; default: usage(); }ARGEND switch(argc){ default: usage(); case 1: dir = argv[0]; break; } fs = atreeinit(dir); initdraw(0, "/lib/font/bit/lucidasans/unicode.8.font", "tree"); t.root = fs->root; t.offset = ZP; t.clipr = allocimage(display, Rect(0,0,1,1), GREY1, 1, DOpaque); eresized(0); flushimage(display, 1); einit(Emouse); menu.item = items; menu.gen = 0; menu.lasthit = 0; if(fs->resizefd > 0){ Eready = 1<<3; estart(Eready, fs->resizefd, 1); }else Eready = 0; for(;;){ switch(n=eread(Emouse|Eready, &e)){ default: if(Eready && n==Eready) eresized(0); break; case Emouse: m = e.mouse; switch(m.buttons){ case Left: op = t.offset; p = m.xy; do { t.offset = addpt(t.offset, subpt(m.xy, p)); p = m.xy; eresized(0); m = emouse(); }while(m.buttons == Left); if(m.buttons){ t.offset = op; eresized(0); } break; case Middle: n = emenuhit(MMenu, &m, &menu); if(n == -1) break; switch(n){ case IExit: exits(nil); } break; case Right: do m = emouse(); while(m.buttons == Right); if(m.buttons) break; tn = findnode(t.root, m.xy); if(tn){ tn->expanded = !tn->expanded; eresized(0); } break; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -