mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-07-06 19:28:56 +00:00
Show system date in status bar. Code cleanup.
This commit is contained in:
parent
aecf9496ec
commit
9c19434397
174
apps/email.c
174
apps/email.c
@ -29,6 +29,28 @@
|
|||||||
#define SCROLLBACK 25*80 // How many bytes to go back when paging up
|
#define SCROLLBACK 25*80 // How many bytes to go back when paging up
|
||||||
#define READSZ 1024 // Size of buffer for copying files
|
#define READSZ 1024 // Size of buffer for copying files
|
||||||
|
|
||||||
|
#define BELL 0x07
|
||||||
|
#define BACKSPACE 0x08
|
||||||
|
#define INVERSE 0x0f
|
||||||
|
#define RETURN 0x0d
|
||||||
|
#define NORMAL 0x0e
|
||||||
|
#define CURDOWN 0x0a
|
||||||
|
#define HOME 0x19
|
||||||
|
#define CLRLINE 0x1a
|
||||||
|
#define DELETE 0x7f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Represents a date and time
|
||||||
|
*/
|
||||||
|
struct datetime {
|
||||||
|
unsigned int year;
|
||||||
|
unsigned char month;
|
||||||
|
unsigned char day;
|
||||||
|
unsigned char hour;
|
||||||
|
unsigned char minute;
|
||||||
|
unsigned char ispd25format;
|
||||||
|
unsigned char nodatetime;
|
||||||
|
};
|
||||||
|
|
||||||
char filename[80];
|
char filename[80];
|
||||||
char userentry[80];
|
char userentry[80];
|
||||||
@ -51,9 +73,9 @@ static unsigned char buf[READSZ];
|
|||||||
*/
|
*/
|
||||||
void goto_prompt_row(void) {
|
void goto_prompt_row(void) {
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
putchar(0x19); // HOME
|
putchar(HOME);
|
||||||
for (i = 0; i < PROMPT_ROW - 1; ++i)
|
for (i = 0; i < PROMPT_ROW - 1; ++i)
|
||||||
putchar(0x0a); // CURSOR DOWN
|
putchar(CURDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -64,7 +86,7 @@ void error(uint8_t fatal, const char *fmt, ...) {
|
|||||||
va_list v;
|
va_list v;
|
||||||
if (fatal) {
|
if (fatal) {
|
||||||
clrscr();
|
clrscr();
|
||||||
printf("\n\n%cFATAL ERROR:%c\n\n", 0x0f, 0x0e);
|
printf("\n\n%cFATAL ERROR:%c\n\n", INVERSE, NORMAL);
|
||||||
va_start(v, fmt);
|
va_start(v, fmt);
|
||||||
vprintf(fmt, v);
|
vprintf(fmt, v);
|
||||||
va_end(v);
|
va_end(v);
|
||||||
@ -73,13 +95,13 @@ void error(uint8_t fatal, const char *fmt, ...) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
||||||
goto_prompt_row();
|
goto_prompt_row();
|
||||||
putchar(0x1a); // CLEAR LINE
|
putchar(CLRLINE);
|
||||||
va_start(v, fmt);
|
va_start(v, fmt);
|
||||||
vprintf(fmt, v);
|
vprintf(fmt, v);
|
||||||
va_end(v);
|
va_end(v);
|
||||||
printf(" - [Press Any Key]");
|
printf(" - [Press Any Key]");
|
||||||
cgetc();
|
cgetc();
|
||||||
putchar(0x1a); // CLEAR LINE
|
putchar(CLRLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +111,7 @@ void error(uint8_t fatal, const char *fmt, ...) {
|
|||||||
void spinner(void) {
|
void spinner(void) {
|
||||||
static char chars[] = "|/-\\";
|
static char chars[] = "|/-\\";
|
||||||
static uint8_t i = 0;
|
static uint8_t i = 0;
|
||||||
putchar(0x08); // BACKSPACE
|
putchar(BACKSPACE);
|
||||||
putchar(chars[(i++) % 4]);
|
putchar(chars[(i++) % 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +133,52 @@ void readconfigfile(void) {
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void readdatetime(unsigned char time[4], struct datetime *dt) {
|
||||||
|
unsigned int d = time[0] + 256U * time[1];
|
||||||
|
unsigned int t = time[2] + 256U * time[3];
|
||||||
|
if ((d == 0) && (t == 0)) {
|
||||||
|
dt->nodatetime = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dt->nodatetime = 0;
|
||||||
|
if (!(t & 0xe000)) {
|
||||||
|
/* ProDOS 1.0 to 2.4.2 date format */
|
||||||
|
dt->year = (d & 0xfe00) >> 9;
|
||||||
|
dt->month = (d & 0x01e0) >> 5;
|
||||||
|
dt->day = d & 0x001f;
|
||||||
|
dt->hour = (t & 0x1f00) >> 8;
|
||||||
|
dt->minute = t & 0x003f;
|
||||||
|
dt->ispd25format = 0;
|
||||||
|
if (dt->year < 40) /* See ProDOS-8 Tech Note 48 */
|
||||||
|
dt->year += 2000;
|
||||||
|
else
|
||||||
|
dt->year += 1900;
|
||||||
|
} else {
|
||||||
|
/* ProDOS 2.5.0+ */
|
||||||
|
dt->year = t & 0x0fff;
|
||||||
|
dt->month = ((t & 0xf000) >> 12) - 1;
|
||||||
|
dt->day = (d & 0xf800) >> 11;
|
||||||
|
dt->hour = (d & 0x07c0) >> 6;
|
||||||
|
dt->minute = d & 0x003f;
|
||||||
|
dt->ispd25format = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printdatetime(struct datetime *dt) {
|
||||||
|
if (dt->nodatetime)
|
||||||
|
fputs("????-??-?? ??:??", stdout);
|
||||||
|
else {
|
||||||
|
printf("%04d-%02d-%02d %02d:%02d",
|
||||||
|
dt->year, dt->month, dt->day, dt->hour, dt->minute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printsystemdate(void) {
|
||||||
|
struct datetime dt;
|
||||||
|
readdatetime((unsigned char*)(0xbf90), &dt);
|
||||||
|
printdatetime(&dt);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free linked list rooted at headers
|
* Free linked list rooted at headers
|
||||||
*/
|
*/
|
||||||
@ -203,7 +271,7 @@ void printfield(char *s, uint8_t start, uint8_t end) {
|
|||||||
* Print one line summary of email headers for one message
|
* Print one line summary of email headers for one message
|
||||||
*/
|
*/
|
||||||
void print_one_email_summary(struct emailhdrs *h, uint8_t inverse) {
|
void print_one_email_summary(struct emailhdrs *h, uint8_t inverse) {
|
||||||
putchar(inverse ? 0xf : 0xe); // INVERSE or NORMAL
|
putchar(inverse ? INVERSE : NORMAL);
|
||||||
putchar(h->tag == 'T' ? 'T' : ' ');
|
putchar(h->tag == 'T' ? 'T' : ' ');
|
||||||
switch(h->status) {
|
switch(h->status) {
|
||||||
case 'N':
|
case 'N':
|
||||||
@ -224,7 +292,7 @@ void print_one_email_summary(struct emailhdrs *h, uint8_t inverse) {
|
|||||||
putchar('|');
|
putchar('|');
|
||||||
printfield(h->subject, 0, 39);
|
printfield(h->subject, 0, 39);
|
||||||
//putchar('\r');
|
//putchar('\r');
|
||||||
putchar(0xe); // NORMAL
|
putchar(NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -240,16 +308,24 @@ struct emailhdrs *get_headers(uint16_t n) {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print status bar at the top
|
||||||
|
*/
|
||||||
void status_bar(void) {
|
void status_bar(void) {
|
||||||
putchar(0x19); // HOME
|
putchar(HOME);
|
||||||
|
putchar(INVERSE);
|
||||||
|
fputs(" ", stdout);
|
||||||
|
printsystemdate();
|
||||||
|
putchar(HOME);
|
||||||
if (num_msgs == 0)
|
if (num_msgs == 0)
|
||||||
printf("%c%s [%s] No messages%c",
|
printf("%c%s [%s] No messages ", INVERSE, PROGNAME, curr_mbox);
|
||||||
0x0f, PROGNAME, curr_mbox, 0x0e);
|
|
||||||
else
|
else
|
||||||
printf("%c%s [%s] %u messages, %u new, %u tagged. Displaying %u-%u%c",
|
printf("%c[%s] %u msgs, %u new, %u tagged. Showing %u-%u. ",
|
||||||
0x0f, PROGNAME, curr_mbox, total_msgs, total_new, total_tag, first_msg,
|
INVERSE, curr_mbox, total_msgs, total_new, total_tag, first_msg,
|
||||||
first_msg + num_msgs - 1, 0x0e);
|
first_msg + num_msgs - 1);
|
||||||
printf("\n\n");
|
putchar(NORMAL);
|
||||||
|
putchar(CURDOWN);
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -265,11 +341,11 @@ void email_summary(void) {
|
|||||||
++i;
|
++i;
|
||||||
h = h->next;
|
h = h->next;
|
||||||
}
|
}
|
||||||
putchar(0x19); // HOME
|
putchar(HOME);
|
||||||
for (i = 0; i < MENU_ROW - 1; ++i)
|
for (i = 0; i < MENU_ROW - 1; ++i)
|
||||||
putchar(0x0a); // CURSOR DOWN
|
putchar(CURDOWN);
|
||||||
printf("%cUp/K Prev | SPC/RET Read | A)rchive | C)opy | M)ove | D)el | U)ndel | P)urge %c", 0x0f, 0x0e);
|
printf("%cUp/K Prev | SPC/RET Read | A)rchive | C)opy | M)ove | D)el | U)ndel | P)urge %c", INVERSE, NORMAL);
|
||||||
printf("%cDn/J Next | S)witch mbox | N)ew mbox| T)ag | W)rite | R)eply | F)wd | Q)uit %c", 0x0f, 0x0e);
|
printf("%cDn/J Next | S)witch mbox | N)ew mbox| T)ag | W)rite | R)eply | F)wd | Q)uit %c", INVERSE, NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -279,9 +355,9 @@ void email_summary_for(uint16_t n) {
|
|||||||
struct emailhdrs *h = headers;
|
struct emailhdrs *h = headers;
|
||||||
uint16_t j;
|
uint16_t j;
|
||||||
h = get_headers(n);
|
h = get_headers(n);
|
||||||
putchar(0x19); // HOME
|
putchar(HOME);
|
||||||
for (j = 0; j < n + 1; ++j)
|
for (j = 0; j < n + 1; ++j)
|
||||||
putchar(0x0a); // CURSOR DOWN
|
putchar(CURDOWN);
|
||||||
print_one_email_summary(h, (n == selection));
|
print_one_email_summary(h, (n == selection));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,9 +411,9 @@ restart:
|
|||||||
}
|
}
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
if ((*p) == 22) { // Use the CURSOR ROW location
|
if ((*p) == 22) { // Use the CURSOR ROW location
|
||||||
putchar(0x0f); // INVERSE
|
putchar(INVERSE);
|
||||||
printf("[%05lu] SPACE continue reading | B)ack | T)op | H)drs | Q)uit", pos);
|
printf("[%05lu] SPACE continue reading | B)ack | T)op | H)drs | Q)uit", pos);
|
||||||
putchar(0x0e); // NORMAL
|
putchar(NORMAL);
|
||||||
retry1:
|
retry1:
|
||||||
c = cgetc();
|
c = cgetc();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -371,15 +447,15 @@ retry1:
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
putchar(7); // BELL
|
putchar(BELL);
|
||||||
goto retry1;
|
goto retry1;
|
||||||
}
|
}
|
||||||
clrscr();
|
clrscr();
|
||||||
}
|
}
|
||||||
} else if (eof) {
|
} else if (eof) {
|
||||||
putchar(0x0f); // INVERSE
|
putchar(INVERSE);
|
||||||
printf("[%05lu] *** END *** | B)ack | T)op | H)drs | Q)uit", pos);
|
printf("[%05lu] *** END *** | B)ack | T)op | H)drs | Q)uit", pos);
|
||||||
putchar(0x0e); // NORMAL
|
putchar(NORMAL);
|
||||||
retry2:
|
retry2:
|
||||||
c = cgetc();
|
c = cgetc();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -411,7 +487,7 @@ retry2:
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
putchar(7); // BELL
|
putchar(BELL);
|
||||||
goto retry2;
|
goto retry2;
|
||||||
}
|
}
|
||||||
clrscr();
|
clrscr();
|
||||||
@ -475,6 +551,9 @@ void new_mailbox(char *mbox) {
|
|||||||
void switch_mailbox(char *mbox) {
|
void switch_mailbox(char *mbox) {
|
||||||
char prev_mbox[80];
|
char prev_mbox[80];
|
||||||
uint8_t err;
|
uint8_t err;
|
||||||
|
// Treat '.' as shortcut for INBOX
|
||||||
|
if (!strcmp(mbox, "."))
|
||||||
|
strcpy(mbox, "INBOX");
|
||||||
strcpy(prev_mbox, curr_mbox);
|
strcpy(prev_mbox, curr_mbox);
|
||||||
strcpy(curr_mbox, mbox);
|
strcpy(curr_mbox, mbox);
|
||||||
first_msg = 1;
|
first_msg = 1;
|
||||||
@ -523,7 +602,7 @@ void purge_deleted(void) {
|
|||||||
error(ERR_NONFATAL, "Can't delete %s", filename);
|
error(ERR_NONFATAL, "Can't delete %s", filename);
|
||||||
}
|
}
|
||||||
goto_prompt_row();
|
goto_prompt_row();
|
||||||
putchar(0x1a); // CLEAR LINE
|
putchar(CLRLINE);
|
||||||
printf("%u msgs deleted", ++delcount);
|
printf("%u msgs deleted", ++delcount);
|
||||||
} else {
|
} else {
|
||||||
l = fwrite(h, 1, EMAILHDRS_SZ_ON_DISK, fp2);
|
l = fwrite(h, 1, EMAILHDRS_SZ_ON_DISK, fp2);
|
||||||
@ -732,9 +811,9 @@ void copy_to_mailbox(struct emailhdrs *h, uint16_t idx,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putchar(0x08); // Erase spinner
|
putchar(BACKSPACE);
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
putchar(0x08);
|
putchar(BACKSPACE);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
fclose(fp2);
|
fclose(fp2);
|
||||||
@ -788,13 +867,13 @@ char prompt_okay(char *msg) {
|
|||||||
c = cgetc();
|
c = cgetc();
|
||||||
if ((c == 'y') || (c == 'Y') || (c == 'n') || (c == 'N'))
|
if ((c == 'y') || (c == 'Y') || (c == 'n') || (c == 'N'))
|
||||||
break;
|
break;
|
||||||
putchar(7); // BELL
|
putchar(BELL);
|
||||||
}
|
}
|
||||||
if ((c == 'y') || (c == 'Y'))
|
if ((c == 'y') || (c == 'Y'))
|
||||||
c = 1;
|
c = 1;
|
||||||
else
|
else
|
||||||
c = 0;
|
c = 0;
|
||||||
putchar(0x1a); // CLEAR LINE
|
putchar(CLRLINE);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,7 +922,7 @@ uint8_t copy_to_mailbox_tagged(char *mbox, uint8_t delete) {
|
|||||||
if (h->tag == 'T') {
|
if (h->tag == 'T') {
|
||||||
h->tag = ' '; // Don't want it tagged in the destination
|
h->tag = ' '; // Don't want it tagged in the destination
|
||||||
goto_prompt_row();
|
goto_prompt_row();
|
||||||
putchar(0x1a); // CLEAR LINE
|
putchar(CLRLINE);
|
||||||
printf("%u/%u:", ++tagcount, total_tag);
|
printf("%u/%u:", ++tagcount, total_tag);
|
||||||
copy_to_mailbox(h, count, mbox, delete, ' ');
|
copy_to_mailbox(h, count, mbox, delete, ' ');
|
||||||
}
|
}
|
||||||
@ -859,6 +938,7 @@ err:
|
|||||||
* Returns number of chars read.
|
* Returns number of chars read.
|
||||||
* prompt - Message to display before > prompt
|
* prompt - Message to display before > prompt
|
||||||
* is_file - if 1, restrict chars to those allowed in ProDOS filename
|
* is_file - if 1, restrict chars to those allowed in ProDOS filename
|
||||||
|
* Returns number of chars read
|
||||||
*/
|
*/
|
||||||
uint8_t prompt_for_name(char *prompt, uint8_t is_file) {
|
uint8_t prompt_for_name(char *prompt, uint8_t is_file) {
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
@ -868,22 +948,22 @@ uint8_t prompt_for_name(char *prompt, uint8_t is_file) {
|
|||||||
i = 0;
|
i = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
c = cgetc();
|
c = cgetc();
|
||||||
if (is_file && !isalnum(c) && (c != 0x0d) && (c != 0x08) && (c != 0x7f) && (c != '.')) {
|
if (is_file && !isalnum(c) && (c != RETURN) && (c != BACKSPACE) && (c != DELETE) && (c != '.')) {
|
||||||
putchar(7); // BELL
|
putchar(BELL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0x0d: // RETURN KEY
|
case RETURN:
|
||||||
goto done;
|
goto done;
|
||||||
case 0x08: // BACKSPACE
|
case BACKSPACE:
|
||||||
case 0x7f: // DELETE
|
case DELETE:
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
putchar(0x08);
|
putchar(BACKSPACE);
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
putchar(0x08);
|
putchar(BACKSPACE);
|
||||||
--i;
|
--i;
|
||||||
} else
|
} else
|
||||||
putchar(7); // BELL
|
putchar(BELL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
putchar(c);
|
putchar(c);
|
||||||
@ -894,7 +974,7 @@ uint8_t prompt_for_name(char *prompt, uint8_t is_file) {
|
|||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
userentry[i] = '\0';
|
userentry[i] = '\0';
|
||||||
putchar(0x1a); // CLEAR LINE
|
putchar(CLRLINE);
|
||||||
goto_prompt_row();
|
goto_prompt_row();
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -921,11 +1001,13 @@ void create_blank_outgoing() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "From: %s\n", cfg_emailaddr);
|
fprintf(fp, "From: %s\n", cfg_emailaddr);
|
||||||
|
prompt_for_name("To", 0);
|
||||||
|
if (strlen(userentry) == 0)
|
||||||
|
return;
|
||||||
|
fprintf(fp, "To: %s\n", userentry);
|
||||||
prompt_for_name("Subject", 0);
|
prompt_for_name("Subject", 0);
|
||||||
fprintf(fp, "Subject: %s\n", userentry);
|
fprintf(fp, "Subject: %s\n", userentry);
|
||||||
fprintf(fp, "Date: TODO: put date in here!!\n"); // TODO
|
fprintf(fp, "Date: TODO: put date in here!!\n"); // TODO
|
||||||
prompt_for_name("To", 0);
|
|
||||||
fprintf(fp, "To: %s\n", userentry);
|
|
||||||
prompt_for_name("cc", 0);
|
prompt_for_name("cc", 0);
|
||||||
fprintf(fp, "cc: %s\n\n", userentry);
|
fprintf(fp, "cc: %s\n\n", userentry);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -991,7 +1073,7 @@ void keyboard_hdlr(void) {
|
|||||||
email_summary();
|
email_summary();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0d: // RETURN KEY
|
case RETURN:
|
||||||
case ' ':
|
case ' ':
|
||||||
h = get_headers(selection);
|
h = get_headers(selection);
|
||||||
if (h) {
|
if (h) {
|
||||||
@ -1073,7 +1155,7 @@ void keyboard_hdlr(void) {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
//printf("[%02x]", c);
|
//printf("[%02x]", c);
|
||||||
putchar(7); // BELL
|
putchar(BELL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user