/*******************************\
* PCOM.C			*
* (C)1986-87, Patrick E. Hughes	*
\*******************************/

#include <exec/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <intuition/intuition.h>
#include <time.h>
#include "System.h"
#include "Defines.h"

/***********************\
* GLOBAL VARIABLE LIST	*
\***********************/

extern struct System System;

extern int Boards_Are_Active, Libraries_Are_Active;
extern int Bulletins_Are_Active, Mail_Is_Active;
extern int Whence_The_Logon;
extern struct User User;
extern long lseek();

static char Message_Buffer[2510] = {'\0'};

/********************/
int PCom()
{
int ch, stat, command_accepted;
char string[133];

if(Mail_Is_Active==0) { return(FAILURE); }

StatRollMessage("Private Mail");
PutStr("Private Mail\r\n");

return(Mail_Prompt(System.Mail_List));
}

/*********************/
static int Mail_Prompt(mh)
	struct Mail_Header *mh;
{
int ch, stat, command_accepted;
char string[133];

FOREVER
	{
	Check_Online_Status();
	PutStr("\r\nL>ist  R>ead  S>end  Q>uit\r\n");
	if(User.Sec_Status==255)
		{
		    PutStr("Sysop: $>Read D>elete\r\n");
		}
	PutStr("Private Mail Command: ? ");
	FOREVER
		{
		ch=ReadChar(120L);
		if(ch==TIMEOUT) { return(ch); }
		Check_Online_Status();
		switch(ch)
			{
			case 'd': /* deletions */
			case 'D':
				if(User.Sec_Status<255)
					{
					command_accepted=FAILURE;
					break;
					}
				stat=Mail_Delete_Frontend(mh);
				command_accepted=SUCCESS;
				break;
			case '$': /* SYSOP READ */
			case '4':
				if(User.Sec_Status<255)
					{
					command_accepted=FAILURE;
					break;
					}
				stat=Mail_Read_Frontend(mh);
				command_accepted=SUCCESS;
				break;
			case 's': /* SEND */
			case 'S':
				if(User.Sec_Status<mh->Write_Low ||
				   User.Sec_Status>mh->Write_High){
					command_accepted=FAILURE;
					break;
				}
				stat=Mail_Write(mh);
				if(stat==SUCCESS)
					{
					Append_Stat(STAT_LETTER);
					++User.Mail_Sent;
					}
				command_accepted=SUCCESS;
				break;
			case 'l': /* LIST */
			case 'L':
				stat=Mail_List(mh,User.Slot_Number);
				command_accepted=SUCCESS;
				break;
			case 'r': /* READ */
			case 'R':
				stat=Mail_Immediate(mh);
				command_accepted=SUCCESS;
				break;
			case 'Q': /* exit */
			case 'q':
				PutStr("Quit\r\n");
				return(SUCCESS);
				break;
			case '?':
			case '/':
				PutStr("Command Summary\r\n");
				strcpy(string,System.Location);
				strcat(string,"MailPrompt.Help");
				stat=MenuSend(string);
				command_accepted=SUCCESS;
				break;
			case '\000': /* FN-KEY HIT */
				command_accepted=SUCCESS;
				PutStr("\r\n");
				break;
			default:
				PurgeLine();
				command_accepted=FAILURE;
				break;
			}
		if(command_accepted==TIMEOUT) { return(TIMEOUT); }
		if(command_accepted==NO_CARRIER) { return(NO_CARRIER); }
		if(command_accepted==FAILURE) { continue; }
		break;
		}
	}
}

/********************/
static int Mail_Read(mh,from,to)
	struct Mail_Header *mh;
	int from,to;
{
struct Mail_Data *bd;
int ch, number, stat, fd, count;
long seekstat, lslot, lsize;
char filename[133], string[81], *timestr;

--from;
--to;

/* OPEN THE DATA FILE */
strcpy(filename,mh->Location);
strcat(filename,"Mail.Data");
fd=open(filename,O_RDONLY);
if(fd==(-1))
	{
	PutStr("File error\r\n");
	PutStr(filename);
	PutStr(" cannot be accessed\r\n\r\n");
	return(SUCCESS);
	}

for(number=from;number<=to;++number)
	{
	bd=mh->Start_of_Data;
	bd+=number;

	/* SKIP IF EMPTY OR SEEK TO FILE POSITION */
	if(bd->Slot==0) { goto Skippy; }
	seekstat=lseek(fd,(long)(bd->Slot-1)*2500L,0);
	if(seekstat!=(long)(bd->Slot-1)*2500L)
		{
		sprintf(string,"Letter [%hu] seek error\r\n",number+1);
		PutStr(string);
		goto ReadSkip;
		}

	/* READ MESSAGE INTO BUFFER */
	stat=read(fd,Message_Buffer,2500);
	if(stat!=2500)
		{
		sprintf(string,"Letter [%hu] read error\r\n",number+1);
		PutStr(string);
		continue;
		}

	/* SEND THE MESSAGE ITSELF */
Skippy:	stat=Send_Mail(mh,bd,Message_Buffer,number+1);
	if(stat==TIMEOUT || stat==NO_CARRIER)
		{
		close(fd);
		return(stat);
		}

	/* BETWEEN MESSAGE PROMPT */
ReadSkip:
	stat=Between_Mail_Prompt(mh,bd,Message_Buffer,number+1);
	if(stat==TIMEOUT || stat==NO_CARRIER) { return(stat); }
	if(stat==0) { break; } /* QUIT */
	if(stat==1) { continue; } /* CONTINUE */
	if(stat==2) { --number; continue; } /* AGAIN */
	}

close(fd);
return(SUCCESS);
}

/***********************/
static int Send_Mail(mh,bd,msg,number)
	struct Mail_Header *mh;
	struct Mail_Data *bd;
	char msg[];
	int number;
{
int count, ch, more;
char stat, *ptr, *timestr, output[133], string[81];

/* IF IT'S DELETED */
if(bd->Slot==0)
	{
	sprintf(string,"\r\nLetter Number: [%hu] ",number);
	PutStr(string);
	PutStr("has been deleted\r\n");
	goto SendMark1;
	}

/* SEND OUT HEADER INFO */
sprintf(string,"\r\nLetter Number: [%hu]\r\n",number);
PutStr(string);
if(strlen(bd->Title)>0)
	{
	sprintf(string,"Subject: %s\r\n",bd->Title);
	PutStr(string);
	}

sprintf(string," Author: %s [%hu]\r\n",bd->Author,bd->From_Code);
PutStr(string);
sprintf(string,"Address: %s [%hu]\r\n",bd->Recipient,bd->To_Code);
PutStr(string);

timestr=ctime(&bd->Time);
timestr[strlen(timestr)-1]='\0';
sprintf(string,"  Time: %s\r\n\r\n",timestr);
PutStr(string);

for(count=0,more=5;;)
	{
	ptr=&msg[count];
	for(;msg[count]!='\n' && msg[count]!='\0';++count) { ; }
	if(msg[count]=='\0') { break; }
	msg[count]='\0';
	strcpy(output,ptr);
	strcat(output,"\r\n");
	PutStr(output);
	msg[count]='\n';
	++count;++more;
	if(more>=22)
		{
		more=0;
		PutStr("More..");
		ch=ReadChar(120L);
		if(ch==TIMEOUT || ch==NO_CARRIER) { return(ch); }
		if(ch=='Q' || ch=='q' || ch=='N' || ch=='n')
			{
			PutStr("\b\b\b\b\b\b      \b\b\b\b\b\b\r\n");
			return(SUCCESS);
			}
		PutStr("\b\b\b\b\b\b      \b\b\b\b\b\b");
		}
	/* CHECK FOR INPUT && CARRIER */
	Check_Online_Status();
	if(CheckInput())
		{
		stat=ReadChar(120L);
		switch(stat)
			{
			case '\023': /* ^S Pause */
			case 'S':
			case 's':
			case 'P':
			case 'p':
			case ' ':
				PurgeLine();
				stat=ReadChar(120L);
			    if(stat==TIMEOUT||stat==NO_CARRIER){return(stat);}
				break;
			case '\033': /* ESC Abort */
			case '\003': /* ^C */
			case '\020': /* ^P */
			case '\031': /* ^Y */
			case 'Q':
			case 'q':
			case 'X':
			case 'x':
				PutStr("\r\nAbort\r\n");
				goto SendMark1;
				break;
			default:
				PurgeLine();
				break;
			}
		}
	}
strcpy(output,ptr);
strcat(output,"\r\n");
PutStr(output);

SendMark1:
Check_Online_Status();

return(SUCCESS);
}

/***********************/
static int Store_Mail(mh,dh,msg)
	struct Mail_Header *mh;
	struct Mail_Data *dh;	/* containing title-author-etc info */
	char msg[];
{
struct Mail_Data *copy;
char string[133];
int fd, stat, count;
long seekstat, lsize, lslot;

stat=Find_Open_Slot(mh,dh);
if(stat==FAILURE)
	{
	PutStr("Space can not be found\r\n");
	PutStr("Your letter was not saved\r\n");
	return(FAILURE);
	}

strcpy(string,mh->Location);
strcat(string,"Mail.Data");
fd=open(string,O_WRONLY);
if(fd==(-1))
	{
	PutStr("File ");
	PutStr(string);
	PutStr(" open error.\r\nYour letter was not saved\r\n");
	return(FAILURE);
	}

/* SEEK TO FILE POSITION */
seekstat=lseek(fd,(long)(dh->Slot-1)*2500L,0);
if(seekstat!=(long)(dh->Slot-1)*2500L)
	{
	PutStr("File ");
	PutStr(string);
	PutStr(" seek error.\r\nYour letter was not saved\r\n");
	return(FAILURE);
	}

stat=write(fd,msg,2500);
if(stat!=2500)
	{
	PutStr("File ");
	PutStr(string);
	PutStr(" write error.\r\nYour letter was not saved\r\n");
	close(fd);
	return(FAILURE);
	}

stat=close(fd);
if(stat==(-1))
	{
	PutStr("File ");
	PutStr(string);
	PutStr(" close error.\r\nYour letter was not saved\r\n");
	close(fd);
	return(FAILURE);
	}

copy=mh->Start_of_Data;
copy+=dh->Slot-1;     /* for mail, there is a 1:1 correspondence between */
++mh->Highest_Letter; /* Slot and Data position */
dh->Time=time(NULL);
*copy=*dh;

return(Flush_Keys(mh));
}

/*********************/
static int Find_Open_Slot(mh,dh)
	struct Mail_Header *mh;
	struct Mail_Data *dh;
{
int slot, the_search, y;
struct Mail_Data *data;
char str[81];

if(mh->Highest_Post==mh->Maximum) { return(FAILURE); }

for(slot=1;slot<=mh->Maximum;++slot)
	{
	data=mh->Start_of_Data;
	data+=(slot-1);
	if(data->Slot==0)
		{
		dh->Slot=slot;
		return(SUCCESS);
		}
	}

return(FAILURE);
}

/**********************/
static int Flush_Keys(mh)
	struct Mail_Header *mh;
{
char string[133];
int fd, stat;

strcpy(string,mh->Location);
strcat(string,"Mail.Keys");
fd=open(string,O_WRONLY);
if(fd==(-1))
	{
	PutStr("File ");
	PutStr(string);
	PutStr(" can not be opened, possible corrupt data\r\n");
	return(FAILURE);
	}

stat=write(fd,mh->Start_of_Data,mh->Maximum*sizeof(struct Mail_Data));
if(stat!=mh->Maximum*sizeof(struct Mail_Data))
	{
	PutStr("File ");
	PutStr(string);
	PutStr(" can not be written, possible corrupt data\r\n");
	close(fd);
	return(FAILURE);
	}

stat=close(fd);
if(stat==(-1))
	{
	PutStr("File ");
	PutStr(string);
	PutStr(" can not be closed, possible corrupt data\r\n");
	return(FAILURE);
	}

return(SUCCESS);
}

/****************************/
static int Mail_Read_Frontend(mh)
	struct Mail_Header *mh;
{
int from, to, stat;
char string[81], holder[6];

if(mh->Highest_Letter==0)
	{
	PutStr("Sysop Read Letters\r\n");
	PutStr("There are no letters to read\r\n");
	return(SUCCESS);
	}

PutStr("\r\nSysop Read Letters\r\n");

Read_Front1:
Check_Online_Status();
sprintf(string,"\r\nRead from [1,%d]? ",mh->Maximum);
PutStr(string);
stat=LineInput("",string,5,120L);
if(stat==TIMEOUT) { return(stat); }
from=atoi(string);
if(from==0) { return(SUCCESS); }
if(from>mh->Maximum)
	{
    sprintf(string,"Too high. %d is the highest letter\r\n",mh->Maximum);
	PutStr(string);
	goto Read_Front1;
	}
Read_Front2:
Check_Online_Status();
sprintf(string,"  Read to [%d,%d]? ",from,mh->Maximum);
PutStr(string);
stat=LineInput("",string,5,120L);
if(stat==TIMEOUT) { return(stat); }
to=atoi(string);
if(to==0) { goto Read_Front1; }
if(to>mh->Maximum)
	{
    sprintf(string,"Too high. %d is the highest letter\r\n",mh->Maximum);
	PutStr(string);
	goto Read_Front2;
	}
if(to<from)
	{
	sprintf(string,"Too low. %d is the lowest\r\n",from);
	PutStr(string);
	goto Read_Front2;
	}

return(Mail_Read(mh,from,to));
}

/****************************/
static int Mail_Immediate(mh)
	struct Mail_Header *mh;
{
int from, stat;
char string[81], holder[6];
struct Mail_Data *data;

if(Mail_Count(mh,User.Slot_Number)==0)
	{
	PutStr("Read\r\n");
	PutStr("There are no letters for you\r\n");
	return(SUCCESS);
	}

PutStr("Read\r\n");

FOREVER
	{
	Check_Online_Status();
	Mail_List(mh,User.Slot_Number);
	sprintf(string,"\r\nNumber to read? ");
	PutStr(string);
	stat=LineInput("",string,5,120L);
	if(stat==TIMEOUT) { return(stat); }
	from=atoi(string);
	if(from<=0) { return(SUCCESS); }
	if(from>mh->Maximum)
		{
		PutStr("Too high\r\n");
		continue;
		}

	data=mh->Start_of_Data;
	data+=(from-1);
	if(data->To_Code!=User.Slot_Number)
		{
		PutStr("Not YOUR letter!\r\n");
		continue;
		}

	stat=Mail_Read(mh,from,from);
	if(stat!=SUCCESS) { return(stat); }
	Check_Online_Status();
	}
}

/****************************/
static int Mail_Delete_Frontend(mh)
	struct Mail_Header *mh;
{
int from, to, stat;
char string[81], holder[6];

if(mh->Highest_Letter==0)
	{
	PutStr("Delete Letters\r\n");
	PutStr("There are no letters to delete\r\n");
	return(SUCCESS);
	}

PutStr("\r\nDelete Letters\r\n");

Delete_Front1:
Check_Online_Status();
sprintf(string,"\r\nDelete FROM [1,%d]? ",mh->Maximum);
PutStr(string);
stat=LineInput("",string,5,120L);
if(stat==TIMEOUT) { return(stat); }
from=atoi(string);
if(from==0) { return(SUCCESS); }
if(from>mh->Maximum)
	{
    sprintf(string,"Too high. %d is the highest letter\r\n",mh->Maximum);
	PutStr(string);
	goto Delete_Front1;
	}
Delete_Front2:
Check_Online_Status();
sprintf(string,"  Delete TO [%d,%d]? ",from,mh->Maximum);
PutStr(string);
stat=LineInput("",string,5,120L);
if(stat==TIMEOUT) { return(stat); }
to=atoi(string);
if(to==0) { goto Delete_Front1; }
if(to>mh->Maximum)
	{
    sprintf(string,"Too high. %d is the highest letter\r\n",mh->Maximum);
	PutStr(string);
	goto Delete_Front2;
	}
if(to<from)
	{
	sprintf(string,"Too low. %d is the lowest\r\n",from);
	PutStr(string);
	goto Delete_Front2;
	}

return(Mail_Delete(mh,from,to));
}

/********************/
static int Between_Mail_Prompt(mh,bd,buf,number)
	struct Mail_Header *mh;
	struct Mail_Data *bd;
	char *buf;
	int number;
{
int ch, stat, command_accepted;
char str[133];

FOREVER
	{
	Check_Online_Status();
	PutStr("\r\nA>gain  N>ext  D>elete  R>eply  Q>uit\r\n");
	if(User.Sec_Status==255)
		{
		PutStr("E>xtract\r\n");
		}
	sprintf(str,"Letter Option? ");
	PutStr(str);
	FOREVER
		{
		ch=ReadChar(120L);
		if(ch==TIMEOUT) { return(ch); }
		Check_Online_Status();
		switch(ch)
			{
			case 'A': /* AGAIN */
			case 'a':
				PutStr("\r\n");
				return(2); /* 2 := read again */
				break;
			case 'C': /* CONTINUE */
			case 'c':
			case 'N': /* NEXT */
			case 'n':
			case '\r':
				PutStr("\r\n");
				Mail_Maybe_Delete(mh,number);
				return(1); /* 1 := onward */
				break;
			case 'D': /* DELETE */
			case 'd':
				PutStr("Delete\r\n");
				Mail_Delete(mh,number,number);
				if(number>mh->Maximum) { return(0); }
				return(1);
				break;
			case 'E': /* EXTRACT */
			case 'e':
				if(User.Sec_Status<255){
					command_accepted=FAILURE;
					break;
				}
				PutStr("Extract\r\n");
				stat=Mail_Extract(mh,bd,buf,number);
				command_accepted=SUCCESS;
				break;
			case 'R': /* REPLY */
			case 'r':
				stat=Mail_Private_Reply(mh,bd);
				if(stat==SUCCESS)
					{
					Mail_Maybe_Delete(mh,number);
					}
				return(1);
				break;
			case 'Q': /* QUIT */
			case 'q':
				PutStr("Quit\r\n");
				Mail_Maybe_Delete(mh,number);
				return(0); /* 0 := stop */
				break;
			case '?': /* HELP */
			case '/':
				PutStr("Command summary\r\n");
				strcpy(str,System.Location);
				strcat(str,"BetweenMail.Help");
				MenuSend(str);
				command_accepted=SUCCESS;
				break;
			case '\000': /* FN-KEY HIT */
				command_accepted=SUCCESS;
				PutStr("\r\n");
				break;
			default:
				PurgeLine();
				command_accepted=FAILURE;
				break;
			}
		if(command_accepted==FAILURE) { continue; }
		Check_Online_Status();
		break;
		}
	}
}

/********************/
static int Mail_Extract(mh,dh,buf,number)
	struct Mail_Header *mh;
	struct Mail_Data *dh;
	char *buf;
	int number;
{
int fd, stat, count;
char filename[133], final[133], string[81], *timestr;

PutStr("Extract\r\n");
sprintf(filename,"%s%s.%d",System.Location,"Letter",number);
Extract_Mark1:
Check_Online_Status();
PutStr("\r\nFile to save= ");
stat=LineInput(filename,final,132,120L);
if(stat==TIMEOUT) { return(TIMEOUT); }
if(stat==NO_CARRIER) { return(NO_CARRIER); }
if(stat==0) { PutStr("Abandoned\r\n"); return(SUCCESS); }

fd=open(final,O_WRONLY+O_CREAT+O_EXCL+O_APPEND);
if(fd==(-1))
	{
	PutStr(final);
	PutStr(" won't open. Try another,\r\nor a blank line to abandon\r\n");
	goto Extract_Mark1;
	}

/* SEND OUT HEADER INFO */
sprintf(string,"\nLetter Number: %hu\n",number);
write(fd,string,strlen(string));
if(strlen(dh->Title)>0)
	{
	sprintf(string,"Subject: %s\n",dh->Title);
	write(fd,string,strlen(string));
	}

sprintf(string," Author: %s [%hu]\n",dh->Author,dh->From_Code);
write(fd,string,strlen(string));
sprintf(string,"Sent To: %s [%hu]\n",dh->Recipient,dh->To_Code);
write(fd,string,strlen(string));
timestr=ctime(&dh->Time);
timestr[strlen(timestr)-1]='\0';
sprintf(string,"  Time: %s\n\n",timestr);
write(fd,string,strlen(string));

for(count=0;buf[count]!='\0';++count) { ; }
stat=write(fd,buf,count);
if(stat!=count) { PutStr("Error while writing\r\n"); }
stat=write(fd,"\n\n",2);
if(stat!=2) { PutStr("Error while writing\r\n"); }
stat=close(fd);
if(stat==EOF) { PutStr("Error while closing\r\n"); }

return(SUCCESS);
}

/********************/
static int Mail_Delete(mh,from,to)
	struct Mail_Header *mh;
	int from,to;
{
struct Mail_Data *dh, *dhsource, *dhreplace;
int count, offset;

--from;
--to;

/* SET THE NEW HIGH MESSAGE */
mh->Highest_Letter-=((to-from)+1);

/* THEN MARK THE RANGE AS DELETED */
for(count=from;count<=to;++count)
	{
	dh=mh->Start_of_Data;
	dh+=count;
	dh->Slot=0;
	dh->From_Code=0;
	dh->To_Code=0;
	}

return(Flush_Keys(mh));
}

/********************/
static int Mail_Write(mh)
	struct Mail_Header *mh;
{
static struct Mail_Data *data, the_struct;
int x, stat, msg_length, number;
struct User hoozer;
char str[133];

WriteMark1:
PutStr("Send A Letter\r\n\r\n");
data=&the_struct;

/* VERIFY FREE SPACE */
if(mh->Highest_Letter==mh->Maximum)
	{
	PutStr("There is no space for another letter\r\n");
	return(FAILURE);
	}

/* INPUT AND VERIFY TARGET ACCOUNT */
PutStr("\r\nEnter Account Number (or Name) to send to? ");
stat=LineInput("",str,31,120L);
if(stat<0) { return(stat); }
Check_Online_Status();
number=atoi(str);
if(number==0)
	{
	if((stat==1 && (toupper(str[0])=='Q' || str[0]=='@')) || stat==0)
		{
		PutStr("Quit\r\n");
		return(SUCCESS);
		}
	if(stat==1 && str[0]=='?')
		{
		strcpy(str,System.Location);
		strcat(str,"Patterns.Help");
		MenuSend(str);
		goto WriteMark1;
		}
	stat=Mail_By_Name(mh,str);
	if(stat<0 || stat=='@') { return(stat); }
	goto WriteMark1;
	}

if(number>System.User_Defaults.Maximum)
	{
	PutStr("Invalid account number\r\n");
	goto WriteMark1;
	}
	
Load_Account(number,&hoozer);
if(hoozer.Slot_Number==0)
	{
	PutStr("That account is deleted or unused\r\n");
	goto WriteMark1;
	}
sprintf(str,"Writing to %s [%u]\r\n\r\n",hoozer.Name,number);
PutStr(str);

PutStr("A single 'Q' to quit\r\n");
PutStr("Enter A Subject: ");
stat=LineInput("",data->Title,30,120L);
if(stat==TIMEOUT || stat==NO_CARRIER) { return(stat); }
if(stat==1 && toupper(data->Title[0])=='Q')
	{
	PutStr("Cancel that letter\r\n");
	goto WriteMark1;
	}

if(User.Sec_Status<255)
	{
	strcpy(data->Author,User.Name);
	}
else
	{
	PutStr("Name to use: ");
	stat=LineInput(User.Name,data->Author,30,120L);
	if(stat==TIMEOUT || stat==NO_CARRIER) { return(stat); }
	}

Check_Online_Status();
msg_length=Edit(Message_Buffer,2500,100,0);

if(msg_length==TIMEOUT || msg_length==NO_CARRIER) { return(msg_length); }
if(msg_length<0) { return(FAILURE); }

PutStr("Hold, saving your letter\r\n");
data->From_Code=User.Slot_Number;
data->To_Code=number;
strcpy(data->Recipient,hoozer.Name);
return(Store_Mail(mh,data,Message_Buffer));
}

/********************/
static int Mail_Private_Reply(mh,dh)
	struct Mail_Header *mh;
	struct Mail_Data *dh;
{
static struct Mail_Data *data, the_struct;
int x, stat, msg_length;
struct User hoozer;

PutStr("Reply\r\n");

/* VERIFY FREE SPACE */
if(mh->Highest_Letter==mh->Maximum)
	{
	PutStr("There is no space for another letter\r\n");
	return(FAILURE);
	}

data=&the_struct;

PutStr("\r\nA single 'Q' will quit\r\n");
PutStr("Enter the Subject: ");
stat=LineInput(mh->Title,data->Title,30,120L);
if(stat==TIMEOUT || stat==NO_CARRIER) { return(stat); }
if(stat==1 && toupper(data->Title[0])=='Q')
	{
	PutStr("Quit, do not write\r\n");
	return(FAILURE);
	}

if(User.Sec_Status<255)
	{
	strcpy(data->Author,User.Name);
	}
else
	{
	PutStr("Name to use: ");
	stat=LineInput(User.Name,data->Author,30,120L);
	if(stat==TIMEOUT || stat==NO_CARRIER) { return(stat); }
	}

/* VERIFY THAT THE TARGET ACCOUNT STILL EXISTS */
if(dh->From_Code<=System.User_Defaults.Maximum)
	{
	Load_Account(dh->From_Code,&hoozer);
	}
else
	{
	hoozer.Slot_Number=0;
	}
if(hoozer.Slot_Number==0)
	{
	PutStr("That account has been deleted\r\n");
	return(FAILURE);
	}

Check_Online_Status();
msg_length=Edit(Message_Buffer,2500,100,0);

if(msg_length==TIMEOUT || msg_length==NO_CARRIER) { return(msg_length); }
if(msg_length<0) { return(FAILURE); }

data->To_Code=dh->From_Code;
data->From_Code=User.Slot_Number;
strcpy(data->Recipient,dh->Author);
PutStr("Hold, storing your letter\r\n");
return(Store_Mail(mh,data,Message_Buffer));
}

/****************************/
int Mail_Count(mh,who)
	struct Mail_Header *mh;
	int who;
{
struct Mail_Data *dh;
int count, flag;

if(Mail_Is_Active==0) { return(FAILURE); }

for(flag=0,count=0;count<mh->Maximum;++count)
	{
	dh=mh->Start_of_Data;
	dh+=count;
	if(dh->To_Code==who && dh->Slot!=0) { ++flag; }
	}

return(flag);
}

/****************************/
int Mail_List(mh,who)
	struct Mail_Header *mh;
	int who;
{
struct Mail_Data *dh;
int count, flag;
char str[133];

if(Mail_Is_Active==0) { return(FAILURE); }

PutStr("\r\n");
for(flag=0,count=0;count<mh->Maximum;++count)
	{
	dh=mh->Start_of_Data;
	dh+=count;
	if(dh->To_Code==who && dh->Slot!=0)
		{
		++flag;
		sprintf(str,"Ltr # [%u] from %s\r\n",count+1,dh->Author);
		PutStr(str);
		}
	}

return(SUCCESS);
}

/********************/
int Mail_Reply_To(mh,who)
	struct Mail_Header *mh;
	int who;
{
static struct Mail_Data *data, the_struct;
int x, stat, msg_length, number;
struct User hoozer;
char str[133];

if(Mail_Is_Active==0) { return(FAILURE); }

ReplyMark1:
data=&the_struct;

/* VERIFY FREE SPACE */
if(mh->Highest_Letter==mh->Maximum)
	{
	PutStr("There is no space for a private reply\r\n");
	return(FAILURE);
	}

/* VERIFY TARGET ACCOUNT */
if(who<=System.User_Defaults.Maximum && who>0)
	{
	stat=Load_Account(who,&hoozer);
	}
else
	{
	hoozer.Slot_Number=0;
	}
if(stat==FAILURE)
	{
	PutStr("That account has file problems\r\n");
	return(SUCCESS);
	}
if(hoozer.Slot_Number==0)
	{
	PutStr("That account is deleted or unused\r\n");
	return(SUCCESS);
	}
sprintf(str,"\r\nWriting to %s [%u]\r\n\r\n",hoozer.Name,who);
PutStr(str);

PutStr("\r\nEnter Subject: ");
stat=LineInput("",data->Title,30,120L);
if(stat<0) { return(stat); }
if(stat==0)
	{
	PutStr("Cancel that letter\r\n");
	return(SUCCESS);
	}

if(User.Sec_Status<255)
	{
	strcpy(data->Author,User.Name);
	}
else
	{
	PutStr("Name to use: ");
	stat=LineInput(User.Name,data->Author,30,120L);
	if(stat==TIMEOUT || stat==NO_CARRIER) { return(stat); }
	}

Check_Online_Status();
msg_length=Edit(Message_Buffer,2500,100,0);

if(msg_length==TIMEOUT || msg_length==NO_CARRIER) { return(msg_length); }
if(msg_length<0) { return(FAILURE); }

PutStr("\r\nHold, saving your letter\r\n");
data->From_Code=User.Slot_Number;
data->To_Code=who;
strcpy(data->Recipient,hoozer.Name);
return(Store_Mail(mh,data,Message_Buffer));
}

/****************************/
static int Mail_Maybe_Delete(mh,which)
	struct Mail_Header *mh;
	int which;
{
int stat, ch;

PutStr("\r\nDelete the original now? ");
FOREVER
	{
	ch=ReadChar(120L);
	if(toupper(ch)=='Y')
		{
		PutStr("Yes\r\n");
		PutStr("Hold, deleting\r\n");
		return(Mail_Delete(mh,which,which));
		}
	if(toupper(ch)=='N')
		{
		PutStr("No\r\n");
		return(FAILURE);
		}
	if(ch<0) { return(ch); }
	}
}

/************************************/
static int Mail_By_Name(mh,name)
	struct Mail_Header *mh;
	char *name;
{
struct User hoozer;
int slot, stat;
char s[81];

strcpy(s,name);

for(slot=1;slot<=System.User_Defaults.Maximum;++slot)
	{
	stat=Load_Account(slot,&hoozer);
	if(stat==FAILURE)
		{
		PutStr("File error reading an account\r\n");
		PutStr("Cannot continue the search\r\n");
		return(SUCCESS);
		}
	if(hoozer.Slot_Number==0)
		{
		;
		}
	else if(jive(hoozer.Name,s)==SUCCESS)
		{
		PutStr("\r\nSend Mail To > ");
		PutStr(hoozer.Name);
		PutStr(" ? ");
		stat=ReadChar(120L);
		if(stat<0) { return(stat); }
		switch(toupper(stat))
			{
			case 'Q':
			case '@':
				PutStr("Quit\r\n");
				return(FAILURE);
				break;
			case 'Y':
				return(Mail_Reply_To(mh,slot));
				break;
			}
		}
	SendChar('.');
	Check_Online_Status();
	if(CheckInput())
		{
		stat=ReadChar(120L);
		switch(stat)
			{
			case '\033': /* ESC Abort */
			case '\003': /* ^C */
			case '\020': /* ^P */
			case '\031': /* ^Y */
			case 'Q':
			case 'q':
			case 'X':
			case 'x':
				PutStr("\r\nAbort\r\n");
				goto ByNameMark1;
				break;
			default:
				PurgeLine();
				break;
			}
		}
	}
ByNameMark1:
PutStr("\r\nNo matching name selected\r\n");
return(FAILURE);
}
