shithub: Nail

Download patch

ref: d50f1886ac392bb53226bcdee649cad221a05e73
parent: 3dfdd6d6c595da74ac627548a9f7e939ab039ab7
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Jan 27 11:23:18 EST 2021

nail: fix reordering on deletion

When deleting the root of a thread with multiple
children, we need to replace it with a dummy so
that the ordering stays intact.

--- a/mbox.c
+++ b/mbox.c
@@ -382,7 +382,7 @@
 	}
 	p = lookupid(m->inreplyto);
 	if(p == nil)
-		p = placeholder(m->inreplyto, m->time, ins);
+		p = placeholder(m->inreplyto, m->time);
 	if(!addchild(p, m, d))
 		m->state |= Stoplev;
 	return m;
@@ -649,32 +649,26 @@
 }
 
 static void
-removemesg(Mesg *m)
+relinkmsg(Mesg *p, Mesg *m)
 {
-	Mesg *c, *p, *pp;
+	Mesg *c, *pp;
 	int i, j;
 
 	/* remove child, preserving order */
 	j = 0;
-	p = m->parent;
-	if(p != nil){
-		for(i = 0; p && i < p->nchild; i++){
-			if(p->child[i] != m)
-				p->child[j++] = p->child[i];
-		}
-		p->nchild = j;
-		for(pp = p; pp != nil; pp = pp->parent)
-			pp->nsub--;
+	for(i = 0; p && i < p->nchild; i++){
+		if(p->child[i] != m)
+			p->child[j++] = p->child[i];
 	}
+	p->nchild = j;
+	for(pp = p; pp != nil; pp = pp->parent)
+		pp->nsub -= m->nsub + 1;
 
 	/* reparent children */
 	for(i = 0; i < m->nchild; i++){
 		c = m->child[i];
 		c->parent = nil;
-		if(p != nil)
-			addchild(p, c, 1);
-		else
-			c->state |= Stoplev;
+		addchild(p, c, c->nsub + 1);
 	}
 }
 
@@ -683,7 +677,7 @@
 {
 	int i, j, ln, fd;
 	char *path;
-	Mesg *m;
+	Mesg *m, *p;
 
 	i = 0;
 	path = estrjoin(maildir, "/ctl", nil);
@@ -703,14 +697,20 @@
 		if(m->flags & Ftodel)
 			fprint(fd, "delete %s %d", mailbox, atoi(m->name));
 
-		removemesg(m);
+		p = m->parent;
 		removeid(m);
+		if(p == nil && m->nsub != 0){
+			p = placeholder(m->messageid, m->time);
+			p->nsub = m->nsub + 1;
+			mbox.mesg[i] = p;
+		}
+		if(p != nil)
+			relinkmsg(p, m);
 		for(j = 0; j < m->nchild; j++)
 			mbredraw(m->child[j], 1, 1);
 		memmove(&mbox.mesg[i], &mbox.mesg[i+1], (mbox.nmesg - i)*sizeof(Mesg*));
 		mbox.nmesg--;
-		mesgfree(m);
-	}
+ 	}
 	close(fd);
 	fprint(mbox.ctl, "clean\n");
 }