ref: 368dd6ad29ac747ea16ec6b48617828912d7f3a0
dir: /page-del/
diff 9d43029ff984435111eff658308a44b4f3eee1cc uncommitted --- a//sys/src/cmd/page.c +++ b//sys/src/cmd/page.c @@ -74,7 +74,10 @@ Czerox, Cwrite, Cext, + Cpop, Cdummy2, + Cdelete, + Cdummy3, Cquit, }; @@ -98,7 +101,10 @@ [Czerox] "zerox", 'z', 0, 0, [Cwrite] "write", 'w', 0, 0, [Cext] "ext", 'x', 0, 0, + [Cpop] "pop", 'p', 0, 0, [Cdummy2] "", 0, 0, 0, + [Cdelete] "delete", 'D', 0, 0, + [Cdummy3] "", 0, 0, 0, [Cquit] "quit", 'q', Kdel, Keof, }; @@ -134,6 +140,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) @@ -987,6 +994,72 @@ } } +/* doesn't actually free the page entry or touch links to avoid breakage */ +Page* +freepage(Page *p, Page *prev) +{ + Page *next, *up; + + drawlock(0); + unloadpage(p); + drawlock(1); + if(p->fd >= 0) + close(p->fd); + p->fd = -1; + /* not touching p->data */ + free(p->name); + p->name = nil; + p->open = nil; + next = nextpage(p); + up = p->up; + if(up->down == p){ + if(up->tail != p) + up->down = next; + else + up->down = nil; + }else if(up->tail == p){ + up->tail = prev; + prev->next = nil; + }else + prev->next = next; + return next; +} + +Page* +poppage(Page *p, int del) +{ + Page *t, *prev, *next; + + if(p == nil) + return nil; + if(p == root) + return p; + if(del){ + if(!(access(p->name, OREAD) == 0 && remove(p->name) == 0 + || p->data != nil && access(p->data, OREAD) == 0 && remove(p->data) == 0)){ + fprint(2, "remove %s: %r", p->name); + return p; + } + } + qlock(&pagelock); + for(t = p->down, prev = p; t != nil && t->up != p->up; prev = t, t = next){ + qlock(t); + next = freepage(t, prev); + qunlock(t); + } + p->down = nil; + prev = prevpage(p); + next = freepage(p, prev); + qunlock(&pagelock); + qunlock(p); + if(next != nil){ + forward = 1; + return next; + } + forward = -1; + return prev; +} + /* * A draw operation that touches only the area contained in bot but not in top. * mp and sp get aligned with bot.min. @@ -1462,8 +1535,10 @@ { char buf[NPATH], *s; Point o; - int fd; + int fd, del; + Page *p; + del = 0; switch(i){ case Corigsize: pos = ZP; @@ -1547,6 +1622,25 @@ break; case Csnarf: writeaddr(current, "/dev/snarf"); + break; + case Cdelete: + del = 1; + /* wet floor */ + case Cpop: + if(current == nil || !canqlock(current)) + break; + if((p = poppage(current, del)) == current){ + qunlock(current); + break; + } + if((current = p) == nil){ + drawlock(0); + draw(screen, screen->r, paper, nil, ZP); + drawframe(screen->r); + drawlock(1); + break; + } + showpage(current); break; case Cnext: forward = 1;