shithub: Nail

Download patch

ref: d765a836933a0ce07b1baaa0758be2f223dcaa3a
parent: 63b1407404f050c40ea37025e3bbcc21a69adf03
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Nov 17 16:01:29 EST 2020

mbox: redraw messages correctly after deletion

We were accidentally deleting one too many rows
when updating a message. There was also an edge
case when moving an empty dummy around.

--- a/mbox.c
+++ b/mbox.c
@@ -524,7 +524,7 @@
 static void
 removemesg(Mesg *m)
 {
-	Mesg *c, *p;
+	Mesg *c, *p, *pp;
 	int i, j;
 
 	/* remove child, preserving order */
@@ -536,7 +536,9 @@
 				j++;
 			p->child[j] = p->child[i];
 		}
-		p->nchild = j;
+		p->nchild--;
+		for(pp = p; pp != nil; pp = pp->parent)
+			pp->nsub--;
 	}
 
 	/* reparent children */
@@ -678,11 +680,27 @@
 		/* Bump whole thread up in list */
 		if(r->nsub > 0){
 			ln = mesglineno(r, nil);
-			nr = r->nsub;
+			nr = r->nsub-1;
 			if(!(r->state & Sdummy))
 				nr++;
-			fprint(mbox.addr, "%d,%d", ln, ln+nr);
-			write(mbox.data, "", 0);
+			/*
+			 * We can end up with an empty container
+			 * in an edge case.
+			 *
+			 * Imagine we have a dummy message with
+			 * a child, and that child gets deleted,
+			 * then a new message comes in replying
+			 * to that dummy.
+			 *
+			 * In this case, r->nsub == 1 due to the
+			 * newly added message, so nr=0.
+			 * in that case, skip the redraw, and
+			 * reinsert the dummy in the right place.
+			 */
+			if(nr > 0){
+				fprint(mbox.addr, "%d,%d", ln, ln+nr-1);
+				write(mbox.data, "", 0);
+			}
 			reinsert(r);
 		}
 		mbredraw(r, 1, 1);