/******************************************************************************
 *	Metal Enter (send) message routine.
 *
 *	File name: MESEND.C  version 1.20a
 *
 *			Copyright (c) 1984 Tim Gary
 *			    Delphi Data Systems
 *			    All rights reserved.
 *
 *
 *	This module contains the message entry routine (enter, reply, etc)
 *
 *****************************************************************************
 *
 * 1.20a 11/07/84  Subject confirmation on reply.
 * 1.20a 11/04/84  Apply stuff added, private msg to sysop.
 * 1.10e 11/02/84  Fixed for new get/put counters.
 * 1.10e 10/30/84  Added privmsgs counter.
 * 1.10b 10/02/84  Cosmetics (deleted extra spaces).
 * 1.10a  9/28/84  Edit bug looked into.
 * 1.10a  9/27/84  More cosmetic fixes.
 * 1.10a  9/14/84  Added simplistic line edit of message text...
 * 1.10a  9/01/84  Routine taken from MS.C for overlay metal.
 *
 * 1.01a  7/14/84  Message editing bugs fixed (delete line.. movmem changed).
 *		   Added subject truncation notice on message entry.
 * 1.01a  6/30/84  Cleaned up more functions.
 * 1.01a  6/26/84  Cleaned up a few functions, and added MULTI_USER stuff.
 * 1.01a  6/10/84  Fixed to work with Aztec C 1.06. Started Multi-user stuff.
 *
 * 1.0b	  4/13/84  Modified for upper/lower case names, and added check for
 *		maximum messages allowed (killed and active ones).
 *
 * 1.0a	  3/16/84  Fixed reply bug.
 *
 * 1.0	  1/20/84  New format of Message file headers.
 * p3.0	 12/14/83  pre-release version 3.0 mods for MCONFIG..
 *
 *****************************************************************************/

#include "xpm.h"
#include "hmh.h"
#include "hmconfg.h"
#include "ctype.h"

static char *lp[MAXMLINES];	/* array of pointers to msg text lines */

/************************************************************************** 
 * enter a message, or reply to a message... mode=0 to enter, -1 to reply *
 *	or msg # to reply without asking for #.. (ie for read/reply)	  *
 **************************************************************************
 * if func=0, then reply or enter, if func=1 then APPLY command, private
 *    message to sysop.
 */

ovmain(func,mode)
 int func;		/* definition required, but variable not used */
 unsigned mode;
{
char *ptr,temp[81],*reserve;	/* reserve=reserved alloc block for files */
int a,b;
register int loop,line;

if (O.user_types[user.type].postmsg==NO && func!=1)
	{
      send("You may not enter a message until the system operator approves it.\
\nLeave comments to the sysop if you would like this ability.\n");
	return;
	}

if ((totalmsgs>=O.MAXTOTMSGS) || (msgcount>=O.MAXMSGS))
	{
	send("\nSorry, the message base is full.\nPlease try to leave your message at a later time.");
	return;
	}


if (mode==0)	/* regular msg entry */
	{
	if (func!=1)
		{
		ask("Who to (RETURN for all) ?",
			message.receiver,FNAMELEN+LNAMELEN+1,UPLOW);
		capstr(message.receiver);
		if (message.receiver[0]=='\0') strcpy(message.receiver,"ALL USERS");
		}
	   else {
		strcpy(message.receiver,"Sysop");
		send("To: Sysop\n");
		}
	if (get_topic(message.topic)==ERROR) return;
       }
       else
	{	/* reply to message */
	if ((int)mode==-1)	/* regular reply command.. */
	 	{
	 	ask("Reply to what message ? ",temp,6,UP);
	 	if (!isdigit(*temp)) return; /* not alpha, return to command */
		mode=atoi(temp);	/* convert to number */
		if (!mode) return;	/* invalid message #=0 */
		messages=open(MESSAGES,F_RD | F_UNLOCK);
			/* the following assumes open file */
		}
	/* both regular and read/reply use the following */
	/* mode=message number replying to */
	/* file must be open before...  from read, or whatever.. */
	a=getindex(mode);	/* get index into msg array, of msg mode */
	if (a==ERROR)
		{
		close(messages);
		send("\n[Message not found]\n");
		return;
		}
	setarec(messages,msg[a].seek);	/* seek to message replying to */
	read(messages,0);	/* get the header */
	movmem(bufloc(messages),&message,128);	/* get stuff into structure */

	sprintf(message.receiver,"%s %s",message.fsend,message.lsend);
	send("\nTo: "); send(message.receiver); putchar('\n');
	send("Subject: "); send(message.topic);
	close(messages);	/* close the file */
	send("\n[Is the subject ok (y/n)? ] ");
	if (tolower(getd())=='n')
		{
		send("[no]\n");
		if (get_topic(message.topic)==ERROR) return;
		}
	   else	send("[yes]\n");
	if (message.status==DEADMSG) mode=0;	/* make rest of stuff nonrep */
	}	/* end of initial reply stuff all the rest of entermsg is
	      as it was, except to end where pointers are setup to the reply */

if (func==1)
	{
	send("\nMessage will be Private.\n");
	message.status=PRIVMSG;
	}
 else
  do {
   message.status=NORMMSG;	/* default to normal message */
   send("(Private/Normal) ?");
   getl(buffer,UP);
   *buffer=tolower(*buffer);
   if (*buffer=='p') message.status=PRIVMSG;		/* private msg */
     else if (*buffer=='?')
		{
		send("\nTo make the message readable only by the person\n\
it is addressed to, enter P for private.\n\n\
Anything else will make the message public (normal).\n\n");
		continue;	/* and ask again */
		}
     else if (*buffer!='n') send("[Normal assumed]\n");
   break;	/* what, you say???  yeh, yeh.. see the continue above?? */
   } while (1);

 if (user.parm.expert==POFF)		 /* not expert.. tell him what to do */
	{
	sprintf(buffer,
"\nEnter message text following each line number.\
\nTo edit or end, hit RETURN alone on a line.\
\nUp to %d characters (letters/numbers) on a line,\
\nand %d lines maximum.\n",O.MAXMSGLINE,O.MLINES);
	send(buffer);
	}

reserve=malloc(2*(sizeof(FILE))+10);	/* make sure there's room for files */

/********************************/
/* Lines may be up to MAXMSGLINE long, and up to MLINES lines	*/
/*   can be entered... limitted by avaliable memory only! 	*/
/********************************/
/* Main loop	*/
/****************/

 for (line=1; line<=O.MLINES; line++)
	{
  cont:	printf("%2d: ",line);
	getl(buffer,UPLOW+MSGLINE);	/* get line up to MAXLINE long */
	if (*buffer=='\0') break;	/* return alone. get enter command */
	if (save_line(line,buffer)==ERROR) break;
	/* above allocs space, and puts line there if room.. ERROR==no room */
	}
 do	{
	if (user.parm.expert==POFF)
		{
		send("\n(A)bort,  (C)ontinue, (D)elete, (E)dit,\n(I)nsert, (L)ist, (R)eplace, (S)ave");
		if (user.status==SYSOP) send("\n(F)ile read");
		send(" :: Select");
	   }
	   else
		if (user.status!=SYSOP) send("\nA,C,D,E,I,L,R,S");
		   else send("\nA,C,D,E,I,L,R,S,F");
	sepstr=' ';
	ask(" ? ",temp,10,UP);
	sepstr='\0';
	switch (*temp)
		{
	case '?':
	       send("(A)bort message entry         (C)ontinue entering message\
\n(D)elete line of the message  (E)dit message text\
\n(I)nsert a line of text       (L)ist the message\
\n(R)eplace line with new one   (S)ave the message");
		if (user.status==SYSOP) send("\n(F)ile transfer to message text\n");
		break;
	case 'A':
		for (loop=0; loop<line-1; loop++) free(lp[loop]);
		free(reserve);
		return;
	case 'C':
		goto cont;	/* yuk!!!!!!!!!!!!! */
	case 'D':
		line=del_line(line);
		break;
	case 'E':
		edit_line(line);
		break;
	case 'F':
		if (user.status==SYSOP) line=read_file(line);
		break;
	case 'I':
		line=ins_line(line);
		break;
	case 'L':
		for (loop=1; (loop<line) && (!breakkey()); loop++)
			printf("\n%2d  %s",loop,lp[loop-1]);
		putchar('\n');
		break;
	case 'R':
		rep_line(line);
		break;
	case 'S':
		if (line<=1) {
			send("\n[No message text]\n");
			*temp='\0';
			}
		break;		/* another save check later... */
 		}	/* end switch */
	} while (*temp!='S');	/* get command while not save command */

free(reserve);	/* put space back in memory queue */

#ifdef MULTI_USER

while ((counters=open(COUNTERS,F_RD))==NULL)	/* wait for counters */
	{
	unsigned t;
	send("\nQueued.");
	for (t=0; t<30000; t++);	/* delay a bit */
	}
rename(COUNTERS,"$$$met$$.$$$");
close(counters);
mu_update();		/* see if anything happened.. */

#endif /* multi user */

printf("\n[Saving message #%u]",nextmsg);

/* get new time/date if RTC defined */

if (O.RTC!=NOCLOCK) readclock();

/* if reply.. do reply stuff.. */

msg[mindex].reply=msg[mindex].parent=0;	/* clear parent/reply */

if (mode!=0)	/* if reply... */
	{
	a=getindex(mode);	/* get index into array / find last msg  */
	while ((a!=ERROR) && msg[a].reply!=0) a=getindex(msg[a].reply);

	/* a=last message in reply list, so this is where we need to update */

   if (a!=ERROR)
	  {
	  msg[mindex].parent=msg[a].number;	/* put parent msg in place */
	  msg[a].reply=nextmsg;			/* new reply in list */
	  updatemsg(a);	/* update message/summary files acordingly */
	  }	/* ok to reply */

	}  /* reply check */


/* add to message file */

	messages=open(MESSAGES,F_RW | F_UNLOCK);	/* r/w open */
	summary=open(SUMMARY,F_RW | F_UNLOCK);		/* speed reasons.. */
	toeof(messages);		/* seek to end of file */
	message.seek=getrec(messages);	/* get the current cp/m record # */
	message.number=nextmsg;		/* setup structure to be written */
	message.parent=msg[mindex].parent;
	message.reply=msg[mindex].reply;
	strcpy(message.fsend,user.first);
	strcpy(message.lsend,user.last);
	message.lines=line-1;
	strcpy(message.date,date);
	strcpy(message.time,time);
	movmem(&message,bufloc(messages),128);	/* copy structure to buffer */

	write(messages,1);

/* deal with summary file */
	movmem(bufloc(messages),bufloc(summary),128);	/* copy msg buffer */

	for (loop=1; loop<line; loop++)
		{
		fputs(lp[loop-1],messages);	/* write the line */
		putc('\n',messages);		/* why not...	  */
		free(lp[loop-1]);	/* free up memory */
		}
	putc('\n',messages);
	if (getbuf(messages)) write(messages,0);	/* flush buffer */
	close(messages);

	toeof(summary);		/* compute file size.. set rr to eof */
 	write(summary,0);

	setarec(summary,0);
	sprintf(bufloc(summary),"%5u\n",++msgcount);
	write(summary,0);
	close(summary);

	msg[mindex].number=nextmsg++;		/* update number */
	msg[mindex++].seek=message.seek;	/* seek location */
	lmsg=nextmsg-1;				/* last msg #  	 */
	++totalmsgs;				/* total active+killed msgs */
	if (message.status==PRIVMSG) ++privmsgs;	/* # private msgs */

/* write new counters.. */
	pcounters(0);

#ifdef MULTI_USER
    unlink("$$$met$$.$$$");
#endif

}	/* enter command */


get_topic(s)
 char *s;
{
char temp[81];

about:	ask("Subject ?",temp,80,UPLOW);
	if (strlen(temp)>TOPICLEN)	/* tell him it's too long.. */
		{
		temp[TOPICLEN]='\0';	/* truncate topic */
		printf("\nSubject truncated to: %s\n",temp);
		ask("Is this ok (y/n)? ",temp+TOPICLEN+2,2,UP);
		if (temp[TOPICLEN+2]=='N') goto about;	/* ask topic again */
		if (temp[TOPICLEN+2]!='Y') send("[Yes assumed]\n");
		}	/* I'm sick of slandering goto, in certain
			   cases, it makes life much easier... */
	strcpy(message.topic,temp);
	if (message.topic[0]=='\0') return ERROR; /* return hit? yep->return */
return NULL;
}


/********************************************************
 * save line pointed to by buf, in message buffer..	*
 ********************************************************/

save_line(line,buf)
 register int line;
 register char *buf;
{
if ((lp[line-1]=malloc(strlen(buf)+2))==0)	/* try to get space */
	{
	send("\n[Message buffer full!! Line not entered]\n\
[Please save message, and continue in a new one]\n");
	return ERROR;		/* and exit to enter command mode */
	}
strcpy(lp[line-1],buf);	/* setup line pointer for later use */
return NULL;
}


/*****************************************
 * read in a message from a regular file *
 *****************************************/

read_file(line)
 register int line;
{
char file[20];
register FILE *fd;
register int oline;
char *bp;
int i;

oline=line;	/* for ending output of # lines read */

ask("\nFile to copy to message text? ",file,19,UP);
if ((fd=open(file,0))!=NULL)	/* try to open file */
	{
	read(fd,1);	/* fgets needs initial read */
	while (line<=O.MLINES && i!=0x1a && i!=EOF)
		{
		bp=buffer;
		while (1) {
		   if ((i=getc(fd))==EOF) break;
		   if (i=='\r' || i==0x1a)
			break;
		   if (i!='\n') *bp++=i;
		   }
		*bp='\0';	/* terminate string */
		if (save_line(line,buffer)==ERROR) break;	/* no space */
		send("\n");	/* to allow ^s */
		printf("%2d: %s",line++,buffer);
		}
	printf("\n\n[%d lines read from %s]\n",line-oline,file);
	close(fd);
	}
	else send("[File NOT found]");

return line;
}


ins_line(cline)
 register int cline;
{
register char *ptr;
register int ln,loop;
char temp[11];

if (cline<O.MLINES)
	{
	ask("Insert before what line ?",temp,10,UP);
	putchar('\n');
	ln=atoi(temp);
	if ((ln>0) && (ln<=cline))
		{
		printf("%3d: ",ln);
		getl(buffer,UPLOW+MSGLINE);
		if ((ptr=malloc(strlen(buffer)+2))==0)
			{
			send("\n[Message buffer FULL, line not entered!]\n");
			return cline;
			}
		/* move line pos pointers up a line */
		for (loop=cline+2; loop>=ln; loop--)
			lp[loop]=lp[loop-1];

		lp[ln-1]=ptr;
		strcpy(ptr,buffer);	/* insert the line */
		cline++;	  /* one more line	*/
		}
		 else send("\n[Invalid line]");
	}
	else
	   {
	   sprintf(buffer,"\n[Max of %d lines!!]",O.MLINES);
	   send(buffer);
	   }

return cline;
} /* ins_line */



del_line(cline)
 register int cline;
{
register int ln	,i;
char temp[11];

ask("Delete which line ?",temp,10,UP);
putchar('\n');
ln=atoi(temp);
if ((ln>0) && (ln<cline))
	{
	free(lp[ln-1]);		/* unallocate the space */
	for (i=ln; i<=cline; i++) lp[i-1]=lp[i];
	cline--;				/* minus one line */
	}
  else send("\n[Line not found]");

return cline;
} /* del_line */


rep_line(cline)
 register int cline;
{
register int ln,tlen;
char temp[11];

ask("Replace which line? ",temp,10,UP);
ln=atoi(temp);
if ((ln>0) && (ln<cline))
	{
	printf("\nLine Was:\n%5d: %s\n",ln,lp[ln-1]);
	send("\nEnter new line, or Return if no change:\n");
	printf("%5d: ",ln);
	getl(buffer,UPLOW+MSGLINE);
	if (*buffer=='\0')		/* null line? */
		return;
	tlen=strlen(lp[ln-1]+2);	/* temp save */
	free(lp[ln-1]);
	save_line(ln,buffer);
	}
  else send("\n[Invalid line]");
} /* rep_line */


edit_line(cline)
 register int cline;
{
register int ln,tlen;
char *sptr;
char temp[129];

ask("Edit which line? ",temp,10,UP);
ln=atoi(temp);
if ((ln>0) && (ln<cline))
	{
	while (1) {
	   printf("\nLine Was:\n%5d: %s\n",ln,lp[ln-1]);
	   send("\nEnter old text to be removed: ");
	   getl(temp,UPLOW+MSGLINE);
	   if (*temp=='\0')		/* null line? */
		return;
	   sptr=sindex(temp,lp[ln-1]);	/* order important!! */
	   if (sptr) break;	/* string is there.. */
	     else send("\n[String not found!]\n");
	   }

	tlen=strlen(temp);
	strncpy(buffer,lp[ln-1],sptr-lp[ln-1]);
	buffer[sptr-lp[ln-1]]='\0';	/* make sure its terminated 9/28 */

	send("\nEnter new replacement text: ");
	getl(temp,UPLOW+MSGLINE);

	strcpy(&buffer[strlen(buffer)],temp);	/* fix new line up... */
	strcpy(&buffer[strlen(buffer)],sptr+tlen);

	if (strlen(buffer)>O.MAXMSGLINE)
		{
		send("\nNew line to long.  Edit aborted.\n");
		return;
		}

	printf("\n%3d: %s\n",ln,buffer);
	free(lp[ln-1]);
	save_line(ln,buffer);
	}
  else send("\n[Invalid line]");
} /* edit_line */


/* End of file */

