jcs
/subtext
/amendments
/98
mail: Make menu work like others where just a letter does something
For menu options that require a message id, use a field input for that
    jcs made amendment 98 over 3 years ago
--- mail.c	Tue Apr 26 20:55:15 2022
+++ mail.c	Thu Apr 28 17:05:12 2022
@@ -58,6 +58,8 @@ void mail_delete(struct session *s, unsigned long idx)
 void mail_mark_unread(struct session *s, unsigned long idx);
 void mail_list(struct session *s, bool sent, unsigned long **mail_ids,
   size_t *nmsgs);
+short mail_get_message_id(struct session *s, size_t nmsgs, char *prompt,
+  short initial);
 
 void
 mail_free_message_strings(struct private_message *msg)
@@ -72,6 +74,38 @@ mail_free_message_strings(struct private_message *msg)
 	}
 }
 
+short
+mail_get_message_id(struct session *s, size_t nmsgs, char *prompt,
+  short initial)
+{
+	char *tmp;
+	char start_s[10] = { 0 };
+	short ret;
+
+	if (initial > -1)
+		snprintf(start_s, sizeof(start_s), "%d", initial);
+	
+get_id:
+	if (prompt)
+		session_printf(s, "{{B}}%s:{{/}} ", prompt);
+		
+	tmp = session_field_input(s, 5, 5, start_s, 0);
+	if (tmp == NULL)
+		return -1;
+	session_output(s, "\r\n", 2);
+	session_flush(s);
+	
+	if (sscanf(tmp, "%d", &ret) != 1 || ret < 1 || ret > nmsgs) {
+		session_printf(s, "{{B}}Invalid message ID{{/}} (^C to cancel)\r\n");
+		session_flush(s);
+		free(tmp);
+		goto get_id;
+	}
+	
+	free(tmp);
+	return ret;
+}
+
 void
 mail_menu(struct session *s)
 {
@@ -80,6 +114,7 @@ mail_menu(struct session *s)
 	bool done = false;
 	char *field;
 	unsigned long *mail_ids = NULL;
+	unsigned short c;
 	short ret;
 
 	if (!s->user) {
@@ -100,44 +135,69 @@ mail_menu(struct session *s)
 		session_output_template(s, "{{B}}Mail>{{/}} ");
 		session_flush(s);
 
-		field = session_field_input(s, 30, 30, NULL, 0);
-		if (field == NULL)
+get_menu_option:
+		c = session_input_char(s);
+		if (s->ending)
 			return;
-		session_output(s, "\r\n", 2);
+		if (c == '\r' || c == 0 || c > 255)
+			goto get_menu_option;
+			
+		session_printf(s, "%c\r\n", c);
 		session_flush(s);
-		
-		if (sscanf(field, "%[Cc] %s", &l, &arg) == 2)
+
+		switch (c) {
+		case 'c':
+		case 'C':
 			mail_compose(s, arg, NULL, NULL);
-		else if (sscanf(field, "%[Cc]", &l) == 1 && field[1] == '\0')
-			mail_compose(s, NULL, NULL, NULL);
-		else if (sscanf(field, "%[Dd] %ld%n", &l, &id, &count) == 2 &&
-		  field[count] == '\0')
-			mail_delete(s, id);
-		else if (sscanf(field, "%[Uu] %ld%n", &l, &id, &count) == 2 &&
-		  field[count] == '\0')
-			mail_mark_unread(s, id);
-		else if (sscanf(field, "%ld%n", &id, &count) == 1 &&
-		  field[count] == '\0') {
-			if (id < 1 || id > nmsgs) {
-				session_output_string(s, "Invalid message id\r\n");
-				session_flush(s);
-				continue;
-			}
-			mail_read(s, mail_ids[id - 1]);
-		}
-		else if (sscanf(field, "%[Ll]", &l) == 1 && field[1] == '\0')
+			break;
+		case 'd':
+		case 'D':
+			id = mail_get_message_id(s, nmsgs, "Message # to delete", -1);
+			if (id != -1)
+				mail_delete(s, id);
+			break;
+		case 'h':
+		case 'H':
+		case '?':
+			mail_help(s);
+			break;
+		case 'l':
+		case 'L':
 			mail_list(s, false, &mail_ids, &nmsgs);
-		else if (sscanf(field, "%[QqXx]", &l) == 1 && field[1] == '\0')
+			break;
+		case 'q':
+		case 'Q':
+		case 'x':
+		case 'X':
 			done = true;
-		else if (sscanf(field, "%[?Hh]", &l) == 1 && field[1] == '\0')
-			mail_help(s);
-		else if (field[0] != '\0') {
+			break;
+		case 'u':
+		case 'U':
+			id = mail_get_message_id(s, nmsgs, "Message # to mark unread",
+			  -1);
+			if (id != -1)
+				mail_mark_unread(s, id);
+			break;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			id = mail_get_message_id(s, nmsgs, "Message # to read",
+			  c - '0');
+			if (id != -1)
+				mail_read(s, mail_ids[id - 1]);
+			break;
+		default:
 			session_output_template(s,
 			  "Invalid option ({{B}}?{{/}} for help)\r\n");
 			session_flush(s);
 		}
-		
-		free(field);
 	}
 }