ref: 23dc7aaa3f6a42dc1b8f4a44f6ffefbe025e2979
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;