/*
  
Title:	MsgEd
  
File:	MakeMsg.c
  
Author:	Jim Nutt
	
Copr:	1988 by Jim Nutt
  
Description:
	
	routines to create new messages
  
Support Files:
  
	msged.h
  
*/

#include "msged.h"
#include <time.h>

#define TEXTLEN 128
#define INPLEN  60

static void show_attrib(void);
static int change_from(void);
static int change_attrib(void);
static int change_to(void);
static int change_dest(void);
static int change_orig(void);
static int change_subject(void);
static void clear_attributes(MSGHEADER * h);

static	char work[TEXTLEN];

int     do_lookup = FALSE;

void    createmsg(void);
int     editmsg(void);

void    createmsg()
{
        if (arealist[area].messages != 0)
                message.msgnum = ++arealist[area].last;
        else
                message.msgnum = arealist[area].first = arealist[area].last = 2;
	checkmem(messages = realloc(messages, arealist[area].last + 1));
	messages[message.msgnum] = TRUE;
	memset(&(message.header), 0, sizeof message.header);
        strncpy(message.header.from, username, sizeof(message.header.from));
        timestr(message.header.date);
        memset(&message.to,0, sizeof(message.to));
        memset(&message.from,0,sizeof(message.from));
        message.to.zone = message.from.zone = thisnode.zone;
	message.header.up = 0;
	message.header.reply = 0;
	clear_attributes(&message.header);
	clearbuffer();
        msgbuf.first = msgbuf.last = curline = NULL;
	message.from = thisnode;
        message.from.domain = NULL;
        message.to.domain = NULL;
	do_lookup = TRUE;
}

void    newmsg()
{
	int t;

	if (arealist[area].messages != 0)
		t = arealist[area].current;
	else
		t = 0;

        createmsg();
	editheader();
	switch (editmsg()) {

                case SAVE:
                        arealist[area].messages++;
			save(message);
			break;

                case ABORT:
                        messages[arealist[area].last--] = FALSE;
                        if (arealist[area].messages < 1) {
                                arealist[area].last = arealist[area].first = arealist[area].current = 0;
                                break;
                        }
			break;
	}

	if (t)
		arealist[area].current = t;
}

void    reply()
{
        char    msgto[sizeof(message.header.to)];
        char    subject[sizeof(message.header.subj)];
	int	link;
	ADDRESS tmp;
	MSGHEADER hlink;
	int	t = arealist[area].current;

        memcpy(msgto, message.header.from, sizeof(message.header.to));
        memcpy(subject, message.header.subj, sizeof(message.header.to));
	tmp = message.from;
	link = message.msgnum;

	createmsg();

	do_lookup = FALSE;
        memcpy(message.header.to, msgto, sizeof(message.header.to));
        memcpy(message.header.subj, subject, sizeof(message.header.to));
	message.to = tmp;

	editheader();

	message.header.reply = link;

	switch (editmsg()) {

		case SAVE:
			hlink = readheader(link);
			hlink.up = message.msgnum;
			writeheader(hlink,link);
                        arealist[area].messages++;
			save(message);
			break;

		case ABORT:
			messages[arealist[area].last--] = FALSE;
			break;
	}
	arealist[area].current = t;
}

void    quote()
{
	int     i;
	char	line[TEXTLEN];
	char	line2[TEXTLEN];
	char	origin[TEXTLEN];
	char	repdate[32];
	int	uucp = FALSE;
        char   *qs;
        char   *s;
        char   *l = NULL;
	LINE   *t;
	int	link;
	MSGHEADER hlink;
	int	tm = arealist[area].current;
	ADDRESS tmp;

        memset(&message.to,0, sizeof(message.to));
        memset(&message.from,0,sizeof(message.from));
        message.to.zone = message.from.zone = thisnode.zone;

	i = rm;
	rm -= (strlen(quotestr) + 5);
	qs = strdup(quotestr);

	readmsg(&message, message.msgnum);

	link = message.msgnum;
	memset(repdate,0,sizeof repdate);
	strncpy(repdate,message.header.date,sizeof(message.header.date));

	if (quotestyle == FIDONET) {
		if ((s = strchr(qs,'*')) != NULL) {
			l = message.header.from;
			while (isspace(*l) && ((l-message.header.from) < sizeof(message.header.from)))
				l++;
			if (l >= message.header.subj)
				*s = ' ';
			else
				*s = *l;
		}

		if ((s = strchr(qs,'^')) != NULL) {
			if (l == NULL)
				l = message.header.from;
			while (!isspace(*l) && ((l-message.header.from) < sizeof(message.header.from)))
				l++;
			while (isspace(*l) && ((l-message.header.from) < sizeof(message.header.from)))
				l++;
			if ((l-message.header.from) > sizeof(message.header.from))
				*s = ' ';
			else
				*s = *l;
		}
	}

	rm = i;

        memcpy(message.header.to, message.header.from,sizeof(message.header.to));

	message.to = message.from;
	message.from = thisnode;
	message.from.domain = NULL;

	message.msgnum = ++arealist[area].last;
	checkmem(messages = realloc(messages, arealist[area].last + 1));
        messages[message.msgnum] = TRUE;
        memset(message.header.from,0,sizeof(message.header.from));
        strncpy(message.header.from, username, sizeof(message.header.from));
	timestr(message.header.date);

	clear_attributes(&message.header);
	do_lookup = FALSE;

        message.header.reply = link;

	t = msgbuf.first;
	memset(line2,0,sizeof line2);
	memset(&tmp,0,sizeof tmp);
	memset(origin,0,sizeof origin);
	memset(work,0,sizeof work);
	strncpy(origin,message.header.to,sizeof message.header.to);


	while (t != NULL) {
		if (t->text != NULL) {
			if (quotestyle == FIDONET)
				sprintf(line, " %s %s", qs, t->text);
			else {
				sprintf(line, " %s%s",qs,t->text);
				if ((strncmp(" * Origin:",t->text,10) == 0) && !uucp) {
					strcpy(line2,t->text);

					if ((strchr(line2,'\n') == NULL) && (t->next != NULL))
						strcat(line2,t->next->text);

					if ((l = strrchr(line2,'(')) != NULL) {
						while (!isdigit(*l))
							l++;
						tmp = parsenode(l);
					}
					memset(line2,0,sizeof line2);
					if (tmp.net != 0) {
						strcat(origin," (");
						if (tmp.zone) {
							sprintf(work,"%d:",tmp.zone);
							strcat(origin,work);
						}
						sprintf(work,"%d/%d",tmp.net,tmp.node);
						strcat(origin,work);
						if (tmp.point) {
							sprintf(work,".%d",tmp.point);
							strcat(origin,work);
						}
						strcat(origin,")");
					}
				}
				else if (strncmp("\01UFGATE ",t->text,8) == 0)
					uucp = TRUE;
				else if (uucp && (strncmp("From: ",t->text,6) == 0)) {
					strcpy(origin,t->text+6);
					if (strchr(origin,'\n') != NULL)
						*strchr(origin,'\n') = '\0';
				}
				else if (uucp && (strncmp("Date: ",t->text,6) == 0)) {
					strcpy(repdate,t->text+6);
					if (strchr(repdate,'\n') != NULL)
						*strchr(repdate,'\n') = '\0';
				}
			}

			if (strchr(t->text, '\n') == NULL)
				strcat(line, "\n");

			free(t->text);
                        t->text = strdup(line);
                        assert(t->text);
		}
		t = t->next;
	}

	if ((quotestyle == USENET) && (!arealist[area].netmail)) {
		t = msgbuf.first;
		memset(line2,0,sizeof(line2));
		msgbuf.first = (LINE *) calloc(1,sizeof(LINE));

		if (uucp)
			sprintf(line2,"In an article of <%s>, %s writes:\n",repdate,origin);
		else
			sprintf(line2,"In a message of <%s>, %s writes:\n",repdate,origin);

		msgbuf.first->text = strdup(line2);
		msgbuf.first->next = (LINE *) calloc(1,sizeof(LINE));
		msgbuf.first->next->prev = msgbuf.first;
		msgbuf.first->next->text = strdup("\n");
		msgbuf.first->next->next = t;
		t->prev = msgbuf.first->next;
	}

	free(qs);

	editheader();

	switch (editmsg()) {

		case SAVE:
			hlink = readheader(link);
			hlink.up = message.msgnum;
			writeheader(hlink,link);
			arealist[area].messages++;
			save(message);
			break;

		case ABORT:
			messages[arealist[area].last--] = FALSE;
			break;
	}
	arealist[area].current = tm;
}

void    change()
{
	messages[message.msgnum] = TRUE;
	message.header.sent = 0;
	timestr(message.header.date);

	message.header.sent = 0;
	message.header.forward = 0;
	message.header.orphan = 0;
	message.header.xx2 = 0;
	message.header.rcpt = 0;
	message.header.areq = 0;
	do_lookup = FALSE;

	editheader();

	switch (editmsg()) {

		case SAVE:
			writemsg(message, message.msgnum);
			arealist[area].current = message.msgnum;
			break;

		case ABORT:
			break;
	}
}

void    show_attrib()
{
        gotoxy(9, 5);
	if (message.header.private)
		intense(ON);
        bputs("Privileged ");
	intense(OFF);
	if (message.header.crash)
		intense(ON);
	bputs("Crash ");
	intense(OFF);
	if (message.header.attached)
		intense(ON);
	bputs("Attach ");
	intense(OFF);
	if (message.header.freq)
		intense(ON);
	bputs("Request ");
	intense(OFF);
	if (message.header.ureq)
		intense(ON);
	bputs("Update ");
	intense(OFF);
	if (message.header.killsent)
		intense(ON);
	bputs("Kill/sent ");
	intense(OFF);
	if (message.header.hold)
		intense(ON);
	bputs("Hold");
	intense(OFF);
	gotoxy(1, 5);
	bputs("Attrib: ");
}

int     change_attrib()
{
	int     ch;

	intense(ON);
        gotoxy(1, 5);
        video_update();
	bputs("Attrib: ");
	intense(OFF);
	ch = getkey();
	if (toupper((ch & 0xff)) == 'P')
		message.header.private ^= 1;
	if (toupper((ch & 0xff)) == 'C')
		message.header.crash ^= 1;
	if (toupper((ch & 0xff)) == 'A')
		message.header.attached ^= 1;
	if (toupper((ch & 0xff)) == 'U')
		message.header.ureq ^= 1;
	if (toupper((ch & 0xff)) == 'R')
		message.header.freq ^= 1;
	if (toupper((ch & 0xff)) == 'K')
		message.header.killsent ^= 1;
	if (toupper((ch & 0xff)) == 'H')
		message.header.hold ^= 1;
	return (ch);
}

int     change_from()
{
	int     ch;

	intense(ON);
	gotoxy(1, 2);
	bputs("From:   ");
        intense(OFF);
        clreol();
        ch = bgets(message.header.from, sizeof(message.header.from));
	gotoxy(1, 2);
	bputs("From:   ");
	return (ch);
}

int     change_orig()
{
	int     ch;
        char    tmp[INPLEN];

	gotoxy(9 + strlen(message.header.from), 2);
	intense(ON);
	bputs(" of ");
	intense(OFF);
	sprintf(tmp, "%d:%d/%d.%d",
		message.from.zone, message.from.net,
		message.from.node, message.from.point);

	if (message.from.domain != NULL) {
		strcat(tmp,"@");
                strcat(tmp,message.from.domain);
	}
	
        ch = bgets(tmp, INPLEN);
        message.from = parsenode(tmp);
	gotoxy(9 + strlen(message.header.from), 2);
	bputs(" of ");
	return (ch);
}

int     change_to()
{
	int	ch;
        char    tmp[sizeof(message.header.to)];

	intense(ON);
	gotoxy(1, 3);
	bputs("To:     ");
	intense(OFF);
	clreol();
        memset(tmp,0,sizeof(tmp));
        strncpy(tmp,message.header.to,sizeof(message.header.to));
        ch = bgets(message.header.to, sizeof(message.header.to));
	do_lookup = !(strcmpl(tmp,message.header.to) == 0);
	gotoxy(1, 3);
	bputs("To:     ");
        if ((arealist[area].netmail) && do_lookup) {
                message.to = lookup(message.header.to,fidolist);
		if ((message.to.net == 0) && (userlist != NULL))
                        message.to = lookup(message.header.to,userlist);
        }
	return (ch);
}

int     change_dest()
{
	int     ch;
        char    tmp[INPLEN];

	gotoxy(9 + strlen(message.header.to), 3);
	intense(ON);
	bputs(" of ");
	intense(OFF);
	sprintf(tmp, "%d:%d/%d.%d",
		message.to.zone, message.to.net,
		message.to.node, message.to.point);
		
	if (message.to.domain != NULL) {
		strcat(tmp,"@");
		strcat(tmp,message.to.domain);
        }

	if (message.to.net == 0)
                memset(tmp,0,sizeof(tmp));

        ch = bgets(tmp, INPLEN);
	message.to = parsenode(tmp);
        if (message.to.domain != NULL) {
                message.from.domain = strdup(thisnode.domain);
                assert(message.from.domain);
        }
		
	gotoxy(9 + strlen(message.header.to), 3);
	bputs(" of ");
	return (ch);
}

int     change_subject()
{
	int     ch;

	intense(ON);
	gotoxy(1, 4);
	if ((message.header.attached) ||
	    (message.header.freq) ||
	    (message.header.ureq))
		bputs("Files:  ");
	else
		bputs("Subj:   ");
	intense(OFF);
        ch = bgets(message.header.subj, sizeof(message.header.subj));
	gotoxy(1, 4);
	if ((message.header.attached) ||
	    (message.header.freq))
		bputs("Files:  ");
	else
		bputs("Subj:   ");

	return (ch);
}

void    editheader()
{
	int     field = 2;
	int     ch = 0;

	cls();
	gotoxy(1, 2);
	bputs("From:   ");
	bputs(message.header.from);
	gotoxy(1, 3);
	bputs("To:     ");
	gotoxy(1, 4);
	if ((message.header.attached) || (message.header.freq) || (message.header.ureq))
		bputs("Files:  ");
	else
		bputs("Subj:   ");
	show_attrib();
	gotoxy(1, 6);
	bputs(
	      "______________________________________________________________________________"
		);
	gotoxy(1, 6);
	foreground(normback);
	background(normfore);
	bputs(arealist[area].description);
	foreground(normfore);
	background(normback);

	while (ch != DONE) {
		switch (field) {
		case 0:
			ch = change_from();
			break;
		case 1:
			ch = change_orig();
			break;
		case 2:
			ch = change_to();
			break;
		case 3:
			ch = change_dest();
			break;
		case 4:
			ch = change_subject();
			break;
		case 5:
			ch = change_attrib();
			show_attrib();
			break;
		}

		if (ch == UP) {

			field--;

			if (field < 0)
				field = 5;

			if ((field == 3) && !arealist[area].netmail)
				field = 2;

			if ((field == 1) && !arealist[area].netmail)
				field = 0;
		}

		if ((ch == DOWN) || (ch == ENTER)) {

			if ((field == 5) && (ch == ENTER))
				break;

			field++;

			if (field > 5)
				field = 0;

			if ((field == 3) && !arealist[area].netmail)
				field = 4;

			if ((field == 1) && !arealist[area].netmail)
				field = 2;

			continue;
		}
	}
	showheader(message);
}

void    timestr(char *s)
{
        char buffer[21];
	static char *months[12] =
	{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

	struct tm *t;
	time_t  ltime;

	time(&ltime);
	t = localtime(&ltime);
        sprintf(buffer, "%02d %3s %2d %02d:%02d:%02d",
		t->tm_mday, months[t->tm_mon], t->tm_year,
                t->tm_hour, t->tm_min, t->tm_sec);

        strncpy(s,buffer,20);
}

static void clear_attributes(MSGHEADER * h)
{
        if (!arealist[area].echomail) {
                h->crash     = msgbits.crash;
                h->private   = msgbits.private;
                h->killsent  = msgbits.killsent;
                h->hold      = msgbits.hold;
        }
        else {
                h->crash     = 0;
                h->private   = 0;
                h->killsent  = 0;
                h->hold      = 0;
        }

        h->local     = msgbits.local;
        h->recvd     = msgbits.recvd;
        h->attached  = msgbits.attached;
        h->sent      = msgbits.sent;
        h->forward   = msgbits.forward;
        h->orphan    = msgbits.orphan;
        h->xx2       = msgbits.xx2;
        h->freq      = msgbits.freq;
        h->rreq      = msgbits.rreq;
        h->rcpt      = msgbits.rcpt;
        h->areq      = msgbits.areq;
        h->ureq      = msgbits.ureq;
}

void save(MSG message)

{
	LINE *l;
        char **name = NULL;
        ADDRESS *address = NULL;
        char buf[TEXTLEN];
        char o[TEXTLEN];
        char *a = NULL;
        char *s = NULL;
	int  i = 0;
        int  j = 0;

        /* initialize stuff */

        memset(buf,0,TEXTLEN);
        memset(o,0,TEXTLEN);

	/* check for a cc: */

	l = msgbuf.first;
	s = l->text;
	while (isspace(*s))
		s++;

	/* write the original message */

	messages[message.msgnum] = TRUE;
	writemsg(message,message.msgnum);
	arealist[area].current = message.msgnum;

	/* if no cc:, then return */

        strcpy(buf,s);
        strlwr(buf);

        if (strncmp(buf,"cc:",3) != 0)
                return;

        name = (char **) calloc(1, sizeof(char **));
        address = (ADDRESS *) calloc(1,sizeof(ADDRESS));

        sprintf(o," * Original to %s @ %d:%d/%d.%d",message.header.to,message.to.zone,message.to.net,message.to.node,message.to.point);
	if (message.to.domain != NULL) {
		strcat(o,">");
		strcat(o,message.to.domain);
	}

	strcat(o,"\n");

        /* build the address list */

        while ((l != NULL) && (l->text != NULL)) {
                if (tolower(*s) == 'c') s = strchr(s,' ');

                while (isspace(*s))
                        s++;

                memset(buf,0,TEXTLEN);
                strcpy(buf,s);

                a = strchr(buf,'\n');
                if (a != NULL)
                        *a = '\0';

                a = strrchr(buf,' ');

                if (a == NULL)
                        break;
                else
                        a++;

                if (isdigit(*a)) {
                        address[i] = parsenode(a);
                        *(a - 1) = '\0';
                }
                else {
                        address[i] = lookup(buf,fidolist);
			if ((address[i].net == 0) && (userlist != NULL))
                                address[i] = lookup(buf,userlist);
                }

                name[i] = strdup(buf);

                i++;

                if ((address = (ADDRESS *) realloc(address,sizeof(ADDRESS) * (i+1))) == NULL)
                        return;

                if ((name = (char **) realloc(name,sizeof(char **) * (i+1))) == NULL) {
                        free(address);
                        return;
                }
		l = l->next;
		s = l->text;
	}

        if ((l = (LINE *) calloc(1,sizeof(LINE))) == NULL) {
                free(name);
                free(address);
                return;
        }

        l->text = strdup("\n");
        assert(l->text);
	l->next = msgbuf.first;
	l->next->prev = l;
	l->prev = NULL;
	msgbuf.first = l;

        if ((l = (LINE *) calloc(1,sizeof(LINE))) == NULL) {
                free(name);
                free(address);
                return;
        }

        l->text = strdup(o);
        assert(l->text);
	l->next = msgbuf.first;
	l->next->prev = l;
	l->prev = NULL;
	msgbuf.first = l;

	for (j = 0; j < i; j++) {
		message.to = address[j];
                memset(message.header.to,0,sizeof(message.header.to));
                strncpy(message.header.to,name[j],sizeof(message.header.to));
                free(name[j]);
                arealist[area].current = message.msgnum = ++arealist[area].last;
                messages = realloc(messages,message.msgnum + 1);
                if (messages == NULL) {
                        free(name);
                        free(address);
                        return;
                }
                arealist[area].messages++;
		messages[message.msgnum] = TRUE;
		writemsg(message,message.msgnum);
        }

        arealist[area].current = arealist[area].last;
        readmsg(&message,arealist[area].current);
        free(name);
        free(address);
}
