shithub: mongrel

Download patch

ref: 76d2ed0cda44c790a068ca9b8bce5bee2fce5334
parent: 371fe66160a278041a25c39162a4bbcd4e0cc333
author: phil9 <telephil9@gmail.com>
date: Fri Feb 4 14:48:58 EST 2022

preserve selection when adding or removing mails

	selection and scroll offset were reset to 0 for no particularly good reasons.
	We now maintain the selection and only switch if the currently selected mail is deleted.

	Also fix a potential double free when mails are deleted.

--- a/a.h
+++ b/a.h
@@ -66,9 +66,9 @@
 Mailbox* loadmbox(char *name);
 void mesgloadbody(Message*);
 int mesgmarkseen(Mailbox*, Message*);
-void mboxadd(Mailbox *mbox, char *path);
-int  mboxmod(Mailbox *mbox, char *path);
-void mboxdel(Mailbox *mbox, char *path);
+int mboxadd(Mailbox *mbox, char *path);
+int mboxmod(Mailbox *mbox, char *path);
+int mboxdel(Mailbox *mbox, char *path);
 void mesgdel(Mailbox *mbox, Message *m);
 void seemailproc(void *v);
 
@@ -83,7 +83,8 @@
 void indexdraw(void);
 void indexmouse(Mouse);
 void indexkey(Rune);
-void indexresetsel(void);
+void indexadded(int);
+void indexremoved(int);
 void indexswitch(Mailbox*);
 
 /* pager */
--- a/index.c
+++ b/index.c
@@ -59,17 +59,38 @@
 static int sel;
 static int lineh;
 
+Message*
+messageat(int index)
+{
+	index = mbox->count - index - 1;
+	return mbox->list->elts[index];
+}
+
 void
-indexresetsel(void)
+indexadded(int index)
 {
-	sel = 0;
-	offset = 0;
+	index = mbox->count - index - 1;
+	if(sel <= index)
+		++sel;
 }
 
 void
+indexremoved(int index)
+{
+	index = mbox->count - index - 1;
+	if(sel >= index){
+		--sel;
+		if(sel < 0)
+			sel = 0;
+		sendp(selc, messageat(sel));
+	}
+}
+
+void
 indexswitch(Mailbox *mb)
 {
-	indexresetsel();
+	sel = 0;
+	offset = 0;
 	mbox = mb;
 }
 
@@ -84,13 +105,6 @@
 	n = mbox->list->nelts;
 	if(offset + n%nlines >= n)
 		offset = n - n%nlines;
-}
-
-Message*
-messageat(int index)
-{
-	index = mbox->count - index - 1;
-	return mbox->list->elts[index];
 }
 
 Rectangle
--- a/main.c
+++ b/main.c
@@ -137,21 +137,22 @@
 	s = e.path;
 	switch(e.type){
 		case Enew:
-			mboxadd(mb, s);
+			i = mboxadd(mb, s);
 			if(mb==mbox){
-				indexresetsel();
+				indexadded(i);
 				redraw();
 			}
 			break;
 		case Edelete:
-			mboxdel(mb, s);
+			i = mboxdel(mb, s);
 			if(mb==mbox){
-				indexresetsel();
+				indexremoved(i);
 				redraw();
 			}
 			break;
 		case Emodify:
-			if(mboxmod(mb, s) && mb==mbox)
+			i = mboxmod(mb, s);
+			if(i >= 0 && mb==mbox)
 				redraw();
 			break;
 	}
--- a/mbox.c
+++ b/mbox.c
@@ -119,7 +119,7 @@
 	else
 		m->flags = readflags(path);
 	if(n >= 20 && f[19] != nil && strlen(f[19]) > 0)
-		m->sender = f[19];
+		m->sender = strdup(f[19]);
 	else
 		m->sender = strdup(m->from);
 	m->time = time(nil);
@@ -220,7 +220,7 @@
 	return mb;
 }
 
-void
+int
 mboxadd(Mailbox *mbox, char *path)
 {
 	Message *m;
@@ -230,7 +230,7 @@
 	for(i = 0; i < mbox->list->nelts; i++){
 		m = mbox->list->elts[i];
 		if(m->id == id)
-			return;
+			return -1;
 	}
 	m = loadmessage(path);
 	m->id = id;
@@ -238,6 +238,7 @@
 		++mbox->unseen;
 	mladd(mbox->list, m);
 	++mbox->count;
+	return mbox->count - 1;
 }
 
 int
@@ -254,7 +255,7 @@
 	}
 	if(m==nil){
 		fprint(2, "could not find mail '%s'\n", path);
-		return 0;
+		return -1;
 	}
 	f = readflags(path);
 	if(m->flags != f){
@@ -263,12 +264,12 @@
 		else if((m->flags & Fseen) == 0 && (f & Fseen) != 0)
 			--mbox->unseen;
 		m->flags = f;
-		return 1;
+		return i;
 	}
-	return 0;
+	return -1;
 }
 
-void
+int
 mboxdel(Mailbox *mbox, char *path)
 {
 	Message *m;
@@ -278,6 +279,8 @@
 	for(i = 0; i < mbox->list->nelts; i++){
 		m = mbox->list->elts[i];
 		if(strcmp(path, m->path)==0){
+			if((m->flags & Fseen) == 0)
+				--mbox->unseen;
 			mldel(mbox->list, i);
 			free(m->path);
 			free(m->info);
@@ -284,13 +287,13 @@
 			free(m->sender);
 			free(m);
 			--mbox->count;
-			return;
+			return i;
 		}
 	}
 	if(m==nil){
 		fprint(2, "could not find mail '%s'\n", path);
-		return;
 	}
+	return -1;
 }
 
 void