ref: 3362539850d86c68b403202d113c67f2cd858fca
dir: /page-del/
diff 855cf4326f5a07d7142c2d8918f5fa856d912b85 uncommitted --- a//sys/src/cmd/page.c +++ b//sys/src/cmd/page.c @@ -74,6 +74,7 @@ Czerox, Cwrite, Cext, + Cdel, Cdummy2, Cquit, }; @@ -98,6 +99,7 @@ [Czerox] "zerox", 'z', 0, 0, [Cwrite] "write", 'w', 0, 0, [Cext] "ext", 'x', 0, 0, + [Cdel] "del", 'd', 0, 0, [Cdummy2] "", 0, 0, 0, [Cquit] "quit", 'q', Kdel, Keof, }; @@ -134,6 +136,7 @@ void showpage(Page *); void drawpage(Page *); Point pagesize(Page *); +void drawlock(int); Page* addpage(Page *up, char *name, int (*popen)(Page *), void *pdata, int fd) @@ -986,6 +989,54 @@ } } +/* page entries are never freed, there's no point + * and would break everything */ +Page* +delpage(Page *p) +{ + Page *t, *q; + + if(p == nil) + return nil; + /* to remove(2) subpages in documents makes no sense, and just + * removing a subentry doesn't seem like a feature worth the bother */ + if(p->up != root) + return p; + if(p->fd >= 0) + close(p->fd); + p->fd = -1; + if(remove(p->name) < 0){ + fprint(2, "remove %s: %r", p->name); + return p; + } + qlock(&pagelock); + for(t = p->down; t != nil && t->up != root; t = q){ + qlock(t); + drawlock(0); + unloadpage(t); + drawlock(1); + free(t->name); + free(t->data); + t->name = t->data = nil; + q = nextpage(t); + qunlock(t); + } + drawlock(0); + unloadpage(p); + drawlock(1); + free(p->name); + free(p->data); + p->name = p->data = nil; + if(root->down != p){ + t = prevpage(p); + t->next = p->next; + }else + root->down = p->next; + qunlock(&pagelock); + qunlock(p); + return p->next != nil ? p->next : t; +} + /* * A draw operation that touches only the area contained in bot but not in top. * mp and sp get aligned with bot.min. @@ -1461,6 +1512,7 @@ char buf[NPATH], *s; Point o; int fd; + Page *p; switch(i){ case Corigsize: @@ -1545,6 +1597,17 @@ break; case Csnarf: writeaddr(current, "/dev/snarf"); + break; + case Cdel: + if(current == nil || !canqlock(current)) + break; + if((p = delpage(current)) == current) + break; + current = p; + if(current == nil) + break; + forward = 1; + showpage(current); break; case Cnext: forward = 1;