/*****************************************************************
 * Articles/Notes, Misc. other functions overlay for Metal 1.10e
 *
 *	File: MEMISC.C
 *
 *	Copyright (c) 1984  Tim Gary
 *	     Delphi Data Systems
 *	     All Rights Reserved.
 *
 ******************************************************************
 *
 * 1.20a 11/11/84  Comments messages made more universal, and Goodbye
 *		  routine made to not display info if  G;N thing
 *		  typed.
 * 1.20a 11/07/84  Comments routine fixed for two CONSECUTIVE CR's
 *		  to stop.
 * 1.10e 11/01/84  Getrange now allows to read dead msgs.
 * 1.10e 10/29/84  Added chat(), cpm() and goodbye() to this overlay.
 *
 * 1.10c 10/12/84  Created from MEFEAT.C  4 parameters passed
 *		   to all of these routines.
 *
 ******************************************************************/

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


/**********************************************************
 * Overlay main program, dispatches to contained routines.
 **********************************************************/

ovmain(routine,p1,p2,p3,p4)
 int routine,p1,p2,p3,p4;
{
switch(routine)
	{
	case FEATURE:
		return feature(p1);
	case GETRANGE:
		return get_range(p1,p2,p3,p4);
	case OUTMSG:
		return out_msg(p1,p2);
	case CHAT:
		return chat(p1);
	case GOODBYE:
		return goodbye(p1);
	case GOCPM:
		return cpm(p1);
	default:
		send("\nUnknown routine called for.\n");
		break;
	}
} /* ovmain */


/******************************************************************
 * Articles function to list files in the Articles/Features ('A')
 * or Notes ('N') index file.  Index file has a fixed format of:
 *	chars 1-17  = filename/location of file (C format)
 *	chars 19-end of line = Description of file (displayed
 *			       in the index
 * Each line must have at least 19 chars in it.  A standard text
 * editor may be used to create the index file.  Each line is
 * the index for one file.  A line may NOT exceed 128 chars.
 * A maximum of 25 articles may be contained in the index files.
 * If the line begins with a ';', it is considered a comment line
 * and will be ignored..
 * If the line starts with a * then the line is printed during
 * the menu display.
 ******************************************************************/

feature(ch)
 char ch;
{
char in[25][18];	/* up to 25 files, 18 chars of length */
register char i,n,*tp,tot;
register FILE *indfile;

tot=0;

do {

if ( (indfile=open((ch=='A' ? FEATFILE : NOTEFILE),0)) == NULL)
	{
	printf("\nSorry, there are currently no %s posted.\n",
		ch=='A' ? "articles/features" : "notes");
	return;
	}

read(indfile,1);

if (!strloc) send(ch=='A' ? "\nFeatures/Articles:\n" : "\nNotes/Notices:\n");

for (i=0; i<25; ++i)
	{
YUCKO:	do fgets(buffer,indfile); while ( (tp=index(buffer,';'))!=0 && tp<(buffer+3) );
	if (*buffer=='\n') strcpy(buffer,buffer+1);	/* ignore LF's */
	if (*buffer=='*') { send("\n"); send(buffer+1); goto YUCKO; }
	if (strlen(buffer)<18) break;	/* see if at end yet */
	sscanf(buffer,"%18s",in[i]);
	sprintf(buffer,"\n%2d. %s",i+1,buffer+18);
	if (!strloc) if (send(buffer)==ERROR) break; /* allow contents abort */
	}
close(indfile);
if (i==0) return;
if (tot<i) tot=i;	/* tot=total # of items.. */

  sprintf(buffer,"\n\nSelect item number%s? ",user.parm.expert!=PON ?
	" (Enter RETURN to exit)" : "");
  ask(buffer,buffer,2,UPLOW);
  if (*buffer=='\0') return;
  n=atoi(buffer);
  if (n<=0 || n>tot) {
		   send("[Invalid item #]\nEnter the item number you wish to\
\nread, or type the RETURN key to\nreturn to the message system.\n");
		   continue;
		   }
  type(in[n-1]);	/* and type the file from where-ever it came from */
  } while (1);	/* just a loop forever */

}


/************************************
 * Get range function for read msgs *
 ************************************/

get_range(pmode,pfirst,plast,pinc)
 int *pmode,*pfirst,*plast,*pinc;
{
char *tp;
unsigned msgnum;
int bit;
register int sreq;	/* search request flag.. */

bit=0;

do {   /* silly do concept */

if (*pmode!='P')       /* new message read function has no options */
       {
       do {
	  sprintf(buffer,"\nRead message #(first=%u, Last=%u)? ",fmsg,lmsg);
	  ask(buffer,buffer,MAXLINE,UP);
	  if (*buffer=='?') read_help(*pmode | 128);
	  } while (*buffer=='?');
       } else  {	       /* if it is 'P' mode */
	       *buffer='N';    /* for new messages  */
	       *pmode='S';     /* selective read mode */
	       }
       if (*buffer=='K')
		{
		sprintf(buffer,"%s",buffer+1);
		bit=0x80;
		}

       sreq=msearch(buffer);   /* setup search if there is one */

       if (*buffer=='N') msgnum=user.lastread+1;
	  else {
	       if (isdigit(*buffer))
		       {
		       if ( ((msgnum=atoi(buffer))>lmsg) || (msgnum<0))
			       {
			       if (*buffer!='\0')
				       send("\n[Message out of range]\n");
			       strloc=0;    /* clear this global pointer */
			       return ERROR;
			       }
		       } else if (sreq) {      /* can have search alone  */
					msgnum=1;  /* and start at msg 1 */
					*buffer='+';
					}
				    else return ERROR;
	       } /* 'N' else test */

       if (*pmode=='S') *buffer='+';   /* Forward selective read */
       if (*pmode=='R') 	       /* Reverse selective read */
	       {
	       *buffer='-';
	       *pmode='S';
	       }
       if (msgnum==0) ++msgnum;        /* convert a zero to a one */

/* All options of modes are reduced by now, so start setting	 *
 * up values to be returned					 */

       if ( ( (tp=index(buffer,'+')) <buffer+7) && (tp!=0) ) *pinc=1;
	  else if ( ( (tp=index(buffer,'-'))<buffer+7) && (tp!=0) ) *pinc=-1;
	      else *pinc=0;

       for (*pfirst=0; msg[*pfirst].number<msgnum; ++(*pfirst));

       if (*pinc==-1) if (*pfirst!=0 && msg[*pfirst].number!=msgnum) *pfirst--;

       if (*pinc)
	       {
	       if (*pinc==1) *plast=mindex-1;
		 else *plast=0;
	       if (*pmode!='S' && user.parm.expert==POFF)
		       send("\nControl-O skips to the next message.\n");
	       }
	  else if (msg[*pfirst].number!=msgnum)
		       {
		       printf("\n[Message %u not found]\n",msgnum);
		       continue;
		       }
		       else *plast=*pfirst;

    break;	       /* I know.. wierd */

    } while (1);

(*pmode)|=bit;
return NULL;   /* done, ok */

} /* get_range */


/**********************************************
 * outputs message to printer 'P' or file 'W' *
 **********************************************/

out_msg(place,lns)
 int place;
 register int lns;
{
register int line_count;
unsigned save_seek;
int ret_flag;

if (place=='P')		/* printer output */
	{
	send("print]\n\n");	/* next line '=' is on purpose */
	if (ret_flag=yes_no("Print CURRENT message (y/n)?"))
		{
		read(messages,1);	/* next record */
		get_header(2,buffer);
		print(buffer);
		for (line_count=0; line_count<lns; line_count++)
			{
			fgets(buffer,messages);
			print(buffer);
			print("\r");
			}
		} /* ok.. */
	} 	/* printer output */
/* otherwise, it's to a file.. get name, etc.. */
   else
	{
	char file[MAXLINE+1];
	FILE *fd;
	send("write]\n\n");	/* Next line '=' on purpose */
	if (ret_flag=yes_no("Write CURRENT message to disk file (y/n)?"))
		{
		send("Write message to what file (uu/d:file.nam)? ");
		getl(file,UP);
		if (*file=='\0')
			{
			strcpy(file,"14/a:message.log");
			send("[File 14/A:MESSAGE.LOG assumed]\n");
			}
		save_seek=getrec(messages);
		close(messages);
		reset_disk(0);		/* for cp/m independence later */
		messages=open(MESSAGES,0);
		setarec(messages,save_seek);
		read(messages,1);
		if (fd=open(file,1))
			{
			toeof(fd);	/* go to end to check if exists */
			if (getrec(fd)!=0)
				{
				send("\n[File Exists!]\n");
				if (ret_flag=yes_no("[Append to existing file? ]"))
					{
					setrrec(fd,-1);	/* backup rec */
					read(fd,0);
					while(gchar(fd)!=26);	/* test eof */
					setbuf(fd,getbuf(fd)-1);/* backup 1 */
					}
				   else if (ret_flag=yes_no("[Delete existing file? ]"))
						{
						close(fd);
						unlink(file);
						fd=open(file,1);
						}
					  else {
						send("[Aborting message write]\n");
						close(fd);
						return NO;
						}
				}

			get_header(2,buffer);
			fputs(buffer,fd);
			for (line_count=0; line_count<lns; line_count++)
				{
				fgets(buffer,messages);
				fputs(buffer,fd);
				send(buffer);
				}
			fputs("\r\n\032",fd);	/* cr/lf and eof */
			write(fd,0);	/* finish up (make sure all written) */
			close(fd);
			}
			else send("\n[Unable to open file]\n");
		} /* y/n */
	} /* output to file */
putchar('\n');
return ret_flag;
}


/**********************
 * Comments help info *
 **********************/

comm_help()
{
static char *c_text[] = {
	"\nYou may leave a private comment to Sysop now.\n",
	"\nAn answer other than Yes or No will abort the",
	"\ncurrent command.\n",
	"\nRemember:  If you expect a reply to a question,",
	"\nit is much better to Enter a message to the Sysop,",
	"\n('E' command) instead of leaving comments here!\n",
	0 };
if (!strloc) dis_text(c_text);
}


/************************************
 * Ask user if he wishes to leave comments to sysop
 ************************************/

askcomments(str)
 char *str;
{
register FILE *comments;
int cr_flag=FALSE;

if (user.parm.expert!=PON) comm_help();

do	{
   if (!str) ask("\nLeave private comments to the Sysop (y/n)? ",buffer,2,UP);
     else ask(str,buffer,2,UP);
   if (*buffer=='?') comm_help();
	}
	while (*buffer=='?');	/* while he's still confused.. */

if (*buffer=='Y')
   {		/* enter comments now */

	send("\nEnter comments.\n*** Type 2 RETURNs ALONE at the prompts to save comments ***\n");
	send("WAIT for the prompt after each line.\n");

/* DON'T CHANGE FORMAT OF NEXT LINE, MIGHT BE READ FOR REPLY TO COMMENTS */
	sprintf(buffer,"\r\nFrom user %-5u stat='%c': %s %s on %s%s%s\r\n",
		user.number,user.status,user.first,user.last,date,
		(O.RTC ? " at " : ""), (O.RTC ? time : "") );

if (!O.PRTLOG)		/* if no printer log, use file stuff */
	{
	comments=open(COMMENTS,F_RW | F_LOCK);
	toeof(comments);	/* go to end of file */
	fputs(buffer,comments);
	}
   else
	print(buffer);	/* output string to printer */

do	{
	ask("->",buffer,79,UPLOW);
	if (!O.PRTLOG)
		{
		fputs(buffer,comments);
		putc('\n',comments);
		}
		else
		  { print(buffer); print("\r\n"); } /* send to lineprinter */
	if (*buffer=='\0')
		{
		if (!cr_flag) cr_flag=TRUE;
		   else break;
		}
	   else cr_flag=FALSE;
	}
	 while (1);

if (!O.PRTLOG)
	{
	while (!eobuf(comments)) putc('\0',comments); /* fill rest with null*/
	write(comments,0);      /* last minute cleanup */
	close(comments);
	}

   }
   else if (*buffer!='N')
		{
		send("\n[Returning..]\n");
		return ERROR;	/* didn't want to leave */
		}

return NULL;
}



/*******************
 * chat with sysop *
 *******************/

chat(mode)
 int mode;
{
register int a,cfast;
register char temp;
int col;		/* current column count for auto wrap */

if (mode)
	{		/* display user if no 25th status line */
	putchar('\n');
	if (!O.STATUSLINE) printf("%s %s is ",user.first,user.last);
	 else wustat("  [CHAT]");
	send("Yelling for Sysop  ");
	globalchar='\0';
	for (temp=0; temp<25; temp++)
		{
		send("\07 .\07 .\07 .");	/* bell */
		for (cfast=0; cfast<1000; cfast++)
			if (breakkey()) return;
			 else if ((a=globalchar)==0x1b)	/* ESC hit by sysop? */
				{
				wustat(0);	/* put back just user info */
				send("\nThe Sysop is available, please go ahead...\n");
				break;
				}
		send("\b\07\b\b\07\b\b\07");	/* backup most of the way */
		if (a==0x1b) break;	/* ESCAPE is Sysop's "I'm here" char */
		}
	if (!a)	
		{
      		send("\nThe Sysop is currently not available.\n");
		askcomments("Would you like to leave private comments to the System Operator? ");
		return;
		}
	} /* end mode check... if mode=0 then just start chat mode */
globalchar=0;	/* for next pass through */
send("\n** [^K to abort chat] **\n");

col=1;	/* first column */
while((cfast=getchar())!=11)		/* while not ^K */
	{
	if (cfast=='\r')
		{
		col=1;
		putchar('\n');
		}
	 else if (cfast=='\b' || cfast==0x7f)
		  {
		  --col;
		  send(" \b");
		  }
	  else {
	       if ( ( ++col>user.parm.width-7 &&
		     (isspace(cfast) || ispunct(cfast)) )
		  || (col>user.parm.width-1) )
			{
			col=1;
			send("\n");	/* force CRLF */
			}
		}
	}
putchar('\n');
}


/*******************
 * jump to CP/M... *
 *******************/

cpm(mode)
 register int mode;	/* if mode=1 then ask if leave comments */
{
if (O.user_types[user.type].maxuser==0)
	{ send("\nYou don't have access to the operating system."); return; }

if (mode==1)	
	if (askcomments(0)==ERROR) return;	/* didn't want to leave */

if (user.parm.expert!=PON) type(CPMINFO);	/* experts know this already */

*tout=O.user_types[user.type].timeout;
*maxuser=O.user_types[user.type].maxuser;
if (O.ZCPR) if (O.user_types[user.type].zcprflag==YES) *O.SECURELOC=255;

#ifndef MULTI_USER
 *(char *)0=0xc3;
#endif

sprintf(buffer,"\nYou have access thru user area %d.\n\n\
[Entering Operating System]",*maxuser);

send(buffer);
exit(0);		/* enter OS	*/
}


/*******************************
 * Leave the system
 *******************************/

goodbye(mode)
 register int mode;
{
if (mode==1)	/* if 'g' entered. else no comments */
	if (askcomments(0)==ERROR) return;	/* didn't want to leave */
send("\nMetal Message System\nCopyright (c) 1984 Tim Gary\nAll rights reserved.\n\n");

#ifndef MULTI_USER
  *(char *)0=0xcd;	/* to loggout with bye */
#endif

exit(0);		/* go to cpm and exit  */
}


/* EOF MEMISC.C */

