12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127 |
- #include "stdinc.h"
- #include "dat.h"
- #include "fns.h"
- #include <draw.h>
- #include <event.h>
- /* --- tree.h */
- typedef struct Tree Tree;
- typedef struct Tnode Tnode;
- struct Tree
- {
- Tnode *root;
- Point offset;
- Image *clipr;
- };
- struct Tnode
- {
- Point offset;
- char *str;
- // char *(*strfn)(Tnode*);
- // uint (*draw)(Tnode*, Image*, Image*, Point);
- void (*expand)(Tnode*);
- void (*collapse)(Tnode*);
- uint expanded;
- Tnode **kid;
- int nkid;
- void *aux;
- };
- typedef struct Atree Atree;
- struct Atree
- {
- int resizefd;
- Tnode *root;
- };
- Atree *atreeinit(char*);
- /* --- visfossil.c */
- Tnode *initxheader(void);
- Tnode *initxcache(char *name);
- Tnode *initxsuper(void);
- Tnode *initxlocalroot(char *name, u32int addr);
- Tnode *initxentry(Entry);
- Tnode *initxsource(Entry, int);
- Tnode *initxentryblock(Block*, Entry*);
- Tnode *initxdatablock(Block*, uint);
- Tnode *initxroot(char *name, uchar[VtScoreSize]);
- int fd;
- Header h;
- Super super;
- VtSession *z;
- VtRoot vac;
- int showinactive;
- /*
- * dumbed down versions of fossil routines
- */
- char*
- bsStr(int state)
- {
- static char s[100];
- if(state == BsFree)
- return "Free";
- if(state == BsBad)
- return "Bad";
- sprint(s, "%x", state);
- if(!(state&BsAlloc))
- strcat(s, ",Free"); /* should not happen */
- if(state&BsVenti)
- strcat(s, ",Venti");
- if(state&BsClosed)
- strcat(s, ",Closed");
- return s;
- }
- char *bttab[] = {
- "BtData",
- "BtData+1",
- "BtData+2",
- "BtData+3",
- "BtData+4",
- "BtData+5",
- "BtData+6",
- "BtData+7",
- "BtDir",
- "BtDir+1",
- "BtDir+2",
- "BtDir+3",
- "BtDir+4",
- "BtDir+5",
- "BtDir+6",
- "BtDir+7",
- };
- char*
- btStr(int type)
- {
- if(type < nelem(bttab))
- return bttab[type];
- return "unknown";
- }
- #pragma varargck argpos stringnode 1
- Block*
- allocBlock(void)
- {
- Block *b;
- b = mallocz(sizeof(Block)+h.blockSize, 1);
- b->data = (void*)&b[1];
- return b;
- }
- void
- blockPut(Block *b)
- {
- free(b);
- }
- static u32int
- partStart(int part)
- {
- switch(part){
- default:
- assert(0);
- case PartSuper:
- return h.super;
- case PartLabel:
- return h.label;
- case PartData:
- return h.data;
- }
- }
- static u32int
- partEnd(int part)
- {
- switch(part){
- default:
- assert(0);
- case PartSuper:
- return h.super+1;
- case PartLabel:
- return h.data;
- case PartData:
- return h.end;
- }
- }
- Block*
- readBlock(int part, u32int addr)
- {
- u32int start, end;
- u64int offset;
- int n, nn;
- Block *b;
- uchar *buf;
- start = partStart(part);
- end = partEnd(part);
- if(addr >= end-start){
- werrstr("bad addr 0x%.8ux; wanted 0x%.8ux - 0x%.8ux", addr, start, end);
- return nil;
- }
- b = allocBlock();
- b->addr = addr;
- buf = b->data;
- offset = ((u64int)(addr+start))*h.blockSize;
- n = h.blockSize;
- while(n > 0){
- nn = pread(fd, buf, n, offset);
- if(nn < 0){
- blockPut(b);
- return nil;
- }
- if(nn == 0){
- werrstr("short read");
- blockPut(b);
- return nil;
- }
- n -= nn;
- offset += nn;
- buf += nn;
- }
- return b;
- }
- int vtType[BtMax] = {
- VtDataType, /* BtData | 0 */
- VtPointerType0, /* BtData | 1 */
- VtPointerType1, /* BtData | 2 */
- VtPointerType2, /* BtData | 3 */
- VtPointerType3, /* BtData | 4 */
- VtPointerType4, /* BtData | 5 */
- VtPointerType5, /* BtData | 6 */
- VtPointerType6, /* BtData | 7 */
- VtDirType, /* BtDir | 0 */
- VtPointerType0, /* BtDir | 1 */
- VtPointerType1, /* BtDir | 2 */
- VtPointerType2, /* BtDir | 3 */
- VtPointerType3, /* BtDir | 4 */
- VtPointerType4, /* BtDir | 5 */
- VtPointerType5, /* BtDir | 6 */
- VtPointerType6, /* BtDir | 7 */
- };
- Block*
- ventiBlock(uchar score[VtScoreSize], uint type)
- {
- int n;
- Block *b;
- b = allocBlock();
- memmove(b->score, score, VtScoreSize);
- b->addr = NilBlock;
- n = vtRead(z, b->score, vtType[type], b->data, h.blockSize);
- if(n < 0){
- fprint(2, "vtRead returns %d: %R\n", n);
- blockPut(b);
- return nil;
- }
- vtZeroExtend(vtType[type], b->data, n, h.blockSize);
- b->l.type = type;
- b->l.state = 0;
- b->l.tag = 0;
- b->l.epoch = 0;
- return b;
- }
- Block*
- dataBlock(uchar score[VtScoreSize], uint type, uint tag)
- {
- Block *b, *bl;
- int lpb;
- Label l;
- u32int addr;
- addr = globalToLocal(score);
- if(addr == NilBlock)
- return ventiBlock(score, type);
- lpb = h.blockSize/LabelSize;
- bl = readBlock(PartLabel, addr/lpb);
- if(bl == nil)
- return nil;
- if(!labelUnpack(&l, bl->data, addr%lpb)){
- werrstr("%R");
- blockPut(bl);
- return nil;
- }
- blockPut(bl);
- if(l.type != type){
- werrstr("type mismatch; got %d (%s) wanted %d (%s)",
- l.type, btStr(l.type), type, btStr(type));
- return nil;
- }
- if(tag && l.tag != tag){
- werrstr("tag mismatch; got 0x%.8ux wanted 0x%.8ux",
- l.tag, tag);
- return nil;
- }
- b = readBlock(PartData, addr);
- if(b == nil)
- return nil;
- b->l = l;
- return b;
- }
- Entry*
- copyEntry(Entry e)
- {
- Entry *p;
- p = mallocz(sizeof *p, 1);
- *p = e;
- return p;
- }
- MetaBlock*
- copyMetaBlock(MetaBlock mb)
- {
- MetaBlock *p;
- p = mallocz(sizeof mb, 1);
- *p = mb;
- return p;
- }
- /*
- * visualizer
- */
- #pragma varargck argpos stringnode 1
- Tnode*
- stringnode(char *fmt, ...)
- {
- va_list arg;
- Tnode *t;
- t = mallocz(sizeof(Tnode), 1);
- va_start(arg, fmt);
- t->str = vsmprint(fmt, arg);
- va_end(arg);
- t->nkid = -1;
- return t;
- }
- void
- xcacheexpand(Tnode *t)
- {
- if(t->nkid >= 0)
- return;
- t->nkid = 1;
- t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
- t->kid[0] = initxheader();
- }
- Tnode*
- initxcache(char *name)
- {
- Tnode *t;
- if((fd = open(name, OREAD)) < 0)
- sysfatal("cannot open %s: %r", name);
- t = stringnode("%s", name);
- t->expand = xcacheexpand;
- return t;
- }
- void
- xheaderexpand(Tnode *t)
- {
- if(t->nkid >= 0)
- return;
- t->nkid = 1;
- t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
- t->kid[0] = initxsuper();
- //t->kid[1] = initxlabel(h.label);
- //t->kid[2] = initxdata(h.data);
- }
- Tnode*
- initxheader(void)
- {
- u8int buf[HeaderSize];
- Tnode *t;
- if(pread(fd, buf, HeaderSize, HeaderOffset) < HeaderSize)
- return stringnode("error reading header: %r");
- if(!headerUnpack(&h, buf))
- return stringnode("error unpacking header: %R");
- t = stringnode("header "
- "version=%#ux (%d) "
- "blockSize=%#ux (%d) "
- "super=%#lux (%ld) "
- "label=%#lux (%ld) "
- "data=%#lux (%ld) "
- "end=%#lux (%ld)",
- h.version, h.version, h.blockSize, h.blockSize,
- h.super, h.super,
- h.label, h.label, h.data, h.data, h.end, h.end);
- t->expand = xheaderexpand;
- return t;
- }
- void
- xsuperexpand(Tnode *t)
- {
- if(t->nkid >= 0)
- return;
- t->nkid = 1;
- t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
- t->kid[0] = initxlocalroot("active", super.active);
- // t->kid[1] = initxlocalroot("next", super.next);
- // t->kid[2] = initxlocalroot("current", super.current);
- }
- Tnode*
- initxsuper(void)
- {
- Block *b;
- Tnode *t;
- b = readBlock(PartSuper, 0);
- if(b == nil)
- return stringnode("reading super: %r");
- if(!superUnpack(&super, b->data)){
- blockPut(b);
- return stringnode("unpacking super: %R");
- }
- blockPut(b);
- t = stringnode("super "
- "version=%#ux "
- "epoch=[%#ux,%#ux) "
- "qid=%#llux "
- "active=%#x "
- "next=%#x "
- "current=%#x "
- "last=%V "
- "name=%s",
- super.version, super.epochLow, super.epochHigh,
- super.qid, super.active, super.next, super.current,
- super.last, super.name);
- t->expand = xsuperexpand;
- return t;
- }
- void
- xvacrootexpand(Tnode *t)
- {
- if(t->nkid >= 0)
- return;
- t->nkid = 1;
- t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
- t->kid[0] = initxroot("root", vac.score);
- }
- Tnode*
- initxvacroot(uchar score[VtScoreSize])
- {
- Tnode *t;
- uchar buf[VtRootSize];
- int n;
- if((n = vtRead(z, score, VtRootType, buf, VtRootSize)) < 0)
- return stringnode("reading root %V: %R", score);
- if(!vtRootUnpack(&vac, buf))
- return stringnode("unpack %d-byte root: %R", n);
- h.blockSize = vac.blockSize;
- t = stringnode("vac version=%#ux name=%s type=%s blockSize=%ud score=%V prev=%V",
- vac.version, vac.name, vac.type, vac.blockSize, vac.score, vac.prev);
- t->expand = xvacrootexpand;
- return t;
- }
- Tnode*
- initxlabel(Label l)
- {
- return stringnode("label type=%s state=%s epoch=%#ux tag=%#ux",
- btStr(l.type), bsStr(l.state), l.epoch, l.tag);
- }
- typedef struct Xblock Xblock;
- struct Xblock
- {
- Tnode;
- Block *b;
- int (*gen)(void*, Block*, int, Tnode**);
- void *arg;
- int printlabel;
- };
- void
- xblockexpand(Tnode *tt)
- {
- int i, j;
- enum { Q = 32 };
- Xblock *t = (Xblock*)tt;
- Tnode *nn;
- if(t->nkid >= 0)
- return;
- j = 0;
- if(t->printlabel){
- t->kid = mallocz(Q*sizeof(t->kid[0]), 1);
- t->kid[0] = initxlabel(t->b->l);
- j = 1;
- }
- for(i=0;; i++){
- switch((*t->gen)(t->arg, t->b, i, &nn)){
- case -1:
- t->nkid = j;
- return;
- case 0:
- break;
- case 1:
- if(j%Q == 0)
- t->kid = realloc(t->kid, (j+Q)*sizeof(t->kid[0]));
- t->kid[j++] = nn;
- break;
- }
- }
- }
- int
- nilgen(void*, Block*, int, Tnode**)
- {
- return -1;
- }
- Tnode*
- initxblock(Block *b, char *s, int (*gen)(void*, Block*, int, Tnode**), void *arg)
- {
- Xblock *t;
- if(gen == nil)
- gen = nilgen;
- t = mallocz(sizeof(Xblock), 1);
- t->b = b;
- t->gen = gen;
- t->arg = arg;
- if(b->addr == NilBlock)
- t->str = smprint("Block %V: %s", b->score, s);
- else
- t->str = smprint("Block %#ux: %s", b->addr, s);
- t->printlabel = 1;
- t->nkid = -1;
- t->expand = xblockexpand;
- return t;
- }
- int
- xentrygen(void *v, Block *b, int o, Tnode **tp)
- {
- Entry e;
- Entry *ed;
- ed = v;
- if(o >= ed->dsize/VtEntrySize)
- return -1;
- entryUnpack(&e, b->data, o);
- if(!showinactive && !(e.flags & VtEntryActive))
- return 0;
- *tp = initxentry(e);
- return 1;
- }
- Tnode*
- initxentryblock(Block *b, Entry *ed)
- {
- return initxblock(b, "entry", xentrygen, ed);
- }
- typedef struct Xentry Xentry;
- struct Xentry
- {
- Tnode;
- Entry e;
- };
- void
- xentryexpand(Tnode *tt)
- {
- 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;
- }
- int
- ptrgen(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 int
- etype(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;
- }
- int
- xlocalrootgen(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);
- }
- int
- xvacrootgen(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;
- }
- int
- metaentrygen(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;
- }
- int
- metablockgen(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);
- }
- int
- parseScore(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;
- }
- int
- scoreFmt(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,
- };
- uint
- drawtext(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;
- }
- void
- drawnub(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)));
- }
- uint
- drawnode(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;
- }
- void
- drawtree(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;
- }
- void
- usage(void)
- {
- fprint(2, "usage: vtree /dev/sdC0/fossil\n");
- exits("usage");
- }
- Tree t;
- void
- eresized(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;
- void
- main(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;
- }
- }
- }
- }
|