#include <ascii.h>
#include "fido.h"
#include "fidomem.h"
#include "proto.h"

/* Message area menu. */

void msg_menu() {
int msgnbr;		/* last message read */
int dir;		/* reading direction: 1 or -1 */
FLAG stats,ok;
FLAG kludge;		/* first time < or > is pressed */
int i,n,m;
char *s,opt;
char buff1[SS],buff2[SS];
char pattern[SF];	/* pattern for S)earch command */

/* Check the message area the caller defaults to; if its not valid
anymore, force them to area 1; if thats not valid, kick them out. */

	n= 0;				/* assume no good */
	mprintf(CM+8);			/* "wait..." */
	if (getmarea(caller.msg)) 
		if (allowed(&msgarea)) n= 1;

	if (! n) {			/* if no valid area, */
		for (i= 0; getmarea(i); i++) {
			if (allowed(&msgarea)) {
				n= 1;
				break;
			}
		}
	}
	if (! n) {
		mprintf(CM+153);		/* oops no areas! */
		lprintf(LM+38);
		return;
	}
	caller.msg= msgarea.number;		/* in case it changed */
	msgcount();				/* need to count */
	msgzap();				/* require a read first */

	dir= 1;					/* default == N)ext */
	msgnbr= findlmsg();
	stats= 0;				/* display stats first time */
	pattern[0]= NUL;			/* null pattern */
	kludge= 0;

	while (1) {
		caller.msg= msgarea.number;	/* keep it correct */
		if (! isargs()) {
			mcrlf();		/* override path */
			if (! stats) {
				stats= 1;
				mprintf(CM+155,*msg_total());
				mprintf(CM+156,*msg_highest());
				mprintf(CM+157,findlmsg());
				mcrlf();
			}
			if (*ovpath) mprintf(CM+21,ovpath);
			else {
				if (msgarea.number == fido.netmarea) 
					dsparea(CM+254,&msgarea,':');
				else dsparea(CM+255,&msgarea,':');
			}
			sprompt(fido.cmd.msg,FM+0,(dir > 0 ? 2 : 3)); /* (CM+158="MESSAGE SECTION") */

			if (uval(CLR_HLP,CLR_HLPS) == REGULAR) mcrlf();

			if (*msg_highest()) 		/* "Command, Message number 1-N " */
				mprintf(CM+161,*msg_highest(),msgnbr,(dir > 0 ? '+' : '-'));
			else mprintf(CM+160);		/* "no msgs yet" */
			mprintf(CM+103);		/* "(?=help): " */
		}
		s= getarg(FM+0);				/* ptr to first char, */

/* First check for the built-in commands and numbers; if thats what
was entered, execute it without the usual command parsing. All of these 
cause a message to be read. */

		ok= 1;					/* assume its special */
		n= -1;					/* assume no number */
		switch (tolower(*s)) {			/* check for special commands */
			case '0':			/* and plain numbers */
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				n= atoi(s);
				if (n > *msg_highest()) mprintf(CM+162);
				else rdmsg(n,0,&msgnbr);
				n= -1;
				kludge= 0;
				break;

			case '.':			/* same msg again */
				n= msgnbr;
				kludge= 0;
				break;

			case '-':			/* read reply-to */
				if (msg.reply) n= msg.reply;
				else n= -1;
				kludge= 0;
				break;

			case '+':			/* read reply */
				if (msg.up) n= msg.up;
				else n= -1;
				kludge= 0;
				break;

			case '<':			/* lowest message */
				msgnbr= 1;
				dir= 1;
				kludge= 1;		/* special case CR */
				break;

			case '>':			/* highest message */
				msgnbr= *msg_highest();
				dir= -1;
				kludge= 1;		/* special case next CR */
				break;

/* CR (which is end of line, and hence a NUL) means "repeat last N or P",
which means start at last-read + or - 1. In real life though, people
enter < or > meaning start at that end; the KLUDGE flag means dont do
the next/previous if the last cmd was < or > only. */

			case NUL:			/* repeat next/prev */
				if (kludge) n= msgnbr;	/* set by < or > */
				else {
					n= nxtmsg(msgnbr,dir);
					if (n == msgnbr) n= -1;	/* dont repeat last one */
				}
				kludge= 0;		/* its used now */
				break;

			default:
				ok= 0;			/* not a special cmd */
				kludge= 0;
				break;
		}

		if (ok) {				/* if it was a special cmd */
			if (n >= 0) rdmsg(n,dir,&msgnbr); /* read it */
			continue;
		}
		kludge= 0;				/* clear the kludge */

/* It is not a special command nor a number; check for commands. These
commands do not read a message, but mainly perform actions. */

		opt= tolower(s[1]);			/* second char, ie. 'rk' */
		i= is_cmd(*s,fido.cmd.msg);
		if (s[1] == '?') help(s,fido.cmd.msg,"message.hlp");
		else switch (i) {
			case 0: 
				mprintf(CM+36,*s);	/* "not a command" */
				cmdflush();
				break;

			case 1:
				help("",fido.cmd.msg,"message.hlp"); break;

			case 2:				/* read next msg */
				dir= 1;
				n= nxtmsg(msgnbr,dir);
				if (n != msgnbr) rdmsg(n,dir,&msgnbr);
				break;

			case 3:				/* read prev msg */
				dir= -1;
				n= nxtmsg(msgnbr,dir);
				if (n != msgnbr) rdmsg(n,dir,&msgnbr);
				break;

			case 4:				/* enter a msg */
				if (chk_ro()) break;	/* check read-only */
				msend(0,0); 
				mcrlf();
				break;

			case 5:				/* kill a msg */
				if (chk_ro()) break;	/* check read-only */
				msgkill(msgnbr);
				if (msgnbr > *msg_highest()) { /* correct */
					msgnbr= *msg_highest(); /* local msg nbr */
				}
				break;

			case 6:				/* find next msg to you */
				i= 0;			/* none found yet */
				m= msgnbr;		/* last msg read */
				n= nxtmsg(msgnbr,dir);	/* pick next ... */
				if (n == msgnbr) break;	/* reached the end */
				msgnbr= n;

				mprintf(CM+8);		/* "wait..." */
				while (n= fndmsg(msgnbr,dir)) {
					pollkbd();
					if (to_caller()) {
						typemsg(msgnbr= n);
						i= 1;
						break;

					} else closemsg();

					msgnbr= nxtmsg(n,dir);	/* pick next ... */
					if (msgnbr == n) break;	/* reached the end */
				} 
				if (! i) {
					mprintf(CM+163);		/* none found */
					msgnbr= m;
				}
				break;

			case 7:
				if (msgsel()) {		/* change areas, */
					msgnbr= findlmsg();
					dir= 1;		/* N)ext ... */
					stats= 0;
				}
				break;

			case 8:				/* reply to a msg */
				if (chk_ro()) break;	/* check read-only */
				if (msend(msgnbr,0) && (opt == 'k'))
					msgkill(msgnbr);
				break;

			case 9:				/* continuous read */
				mprintf(CM+83);		/* "Control-S ... strike any key..." */
				mconflush();
				cmdflush();
				i= mconin();
				mcrlf();
				if ((i == ETX) || (i == VT)) break;

				i= uval(CLR_LEN,CLR_LENS);	/* get "More?", */
				setuval(0,CLR_LEN,CLR_LENS);	/* clear it */
				while (n= fndmsg(msgnbr,dir)) {
					typemsg(n);
					setlmsg(n);
					mcrlf();
					msgnbr= nxtmsg(n,dir);
					if (n == msgnbr) break;
					if (abort) break;
				}
				setuval(i,CLR_LEN,CLR_LENS);	/* restore it */
				break;

			case 10:				/* list messages */
				m= msgnbr;			/* remember last read */
				if (! nxtmsg(msgnbr,0)) break;
				while (n= fndmsg(msgnbr,dir)) {
					closemsg();
					listhdr(&msg,n);
					mcrlf();

					msgnbr= nxtmsg(n,dir);
					if (n == msgnbr) break;
					if (abort) break;
				}
				msgnbr= m;
				break;

			case 11:			/* search for content */
				sprintf(buff1,CM+167);	/* "pattern to search for" */
				if (*pattern) {
					strcat(buff1,"["); /* possible default */
					strcat(buff1,pattern);
					strcat(buff1,"] ");
				}
				getfield(buff2,buff1,0,1,sizeof(pattern),1);
				cmdflush();		/* flush typeahead */
				if (*buff2) strcpy(pattern,buff2);
				if (! *pattern) break;

				mprintf(CM+8);		/* "wait..." */
				m= msgnbr;		/* orig. start number */
				if (kludge) n= msgnbr;	/* if < or > start here */
				else n= nxtmsg(msgnbr,dir); /* else next msg */
				if (msgnbr == n) break;	/* at the end */
				msgnbr= n;

				i= msgnbr;		/* where we started, */
				ok= 0;			/* no: no msgs found */
				while (n= fndmsg(msgnbr,dir)) {
					pollkbd();
					if (abort) break;

					if (inmsg(pattern)) {
						typemsg(n);	/* display it, */
						msgnbr= n;	/* just read this */
						ok= 1;		/* found one */
						break;

					} else closemsg();

					msgnbr= nxtmsg(n,dir);	/* next msg */
					if (msgnbr == n) break;	/* at the end */
				}
				if (! ok) {
					mprintf(CM+168);		/* "not found" */
					msgnbr= m;
				}
				break;

			case 12:			/* edit existing msg */
				if (chk_ro()) break;	/* check read-only */
				if (! fndmsg(msgnbr,0)) break;
				if ((uval(CLR_PRV,CLR_PRVS) < SYSOP) && !from_caller()) {
					mprintf(CM+169);	/* "not your message" */
					closemsg();
					break;
				}
				editmsg(msgnbr);
				break;

			case 13:
				setovpath();		/* path override */
				msgcount();		/* recount messages, */
				if (msgnbr > *msg_highest())
					msgnbr= *msg_highest();
				msgzap();
				break;

			case 14:
				textwrite(msgnbr);	/* write buffer */
				break;

			case 15:
				goodbye("");		/* logoff */
				break;

			case 16:			/* quit reading */
				return;
				break;
		}
	}
}

/* Write the current message out to the message buffer. */

static textwrite(msgnbr) 
unsigned msgnbr;
{
char buff[SS];
char fn[SS];				/* name of output file */
int n,i,f;
int width;				/* callers maximum screen width */
int count;
char word[SS];				/* word we build before output */
char c,lastc;				/* current and previous character */
int screen;				/* output width */
int lines;
FLAG skipline;				/* suppress ^A lines */

#define male (msgarea.number == fido.netmarea)

/* NOTE: Write to a file appends to the end; write to the buffer 
overwrites. */

	if (uval(CLR_PRV,CLR_PRVS) >= EXTRA) {
		getfield(fn,string(CM+13),0,3,SS,1);	/* "file to write to CR=buffer" */
		if (! *fn) goto from_buffer;		/* yuck, a GOTO */
		f= open(fn,2);				/* try to append */
		if (f != -1) {
			lseek(f,0L,2);			/* zip to EOF */
			mprintf(CM+170);

		} else f= creat(fn,2);			/* else create anew */
		if (f == -1) {
			stoupper(fn);
			mprintf(CM+151,fn);		/* "cant create filename" */
			lprintf(LM+39,fn);
			return;
		}

	} else {
from_buffer:	maketid(fn,"MSG.BUF");			/* default quote file */
		f= creat(fn,1);
		if (f == -1) {
			mprintf(CM+151,fn);		/* "buffer not working" */
			lprintf(LM+39,fn);		/* "cant create" */
			return;
		}
	}
	if (!fndmsg(msgnbr,0)) {
		close(f);
		return;					/* open message file */
	}
	strcpy(buff,"Original Message Date: "); strcat(buff,msg.date); 
	strcat(buff,"\r\n"); write(f,buff,strlen(buff));

	strcpy(buff,"From: "); strcat(buff,msg.from); 
	if (male) { strcat(buff," on "); strcat(buff,str_node(&msg_orig)); }
	strcat(buff,"\r\n"); write(f,buff,strlen(buff));

	strcpy(buff,"To: "); strcat(buff,msg.to); 
	if (male) { strcat(buff," on "); strcat(buff,str_node(&msg_dest)); }
	strcat(buff,"\r\n"); write(f,buff,strlen(buff));

	strcpy(buff,"Subj: "); strcat(buff,msg.subj); 
	strcat(buff,"\r\n"); write(f,buff,strlen(buff));

	lines= 4;					/* just wrote three */
	width= SS - sizeof("99: ");			/* set std. output width */
	lastc= screen= 0;
	skipline= 0;
	while (1) {					/* (keyboard abort) */
		word[i= 0]= NUL;			/* word is empty */
		while (i < sizeof(word)) {		/* word at a time */
			lastc= c;			/* remember last character */
			while (1) {
				count= read(msgfile,&c,1);/* read a character, */
				if (! count) break;	/* check EOF */

				switch (c) {
					case SUB: c= NUL; count= 0; break;
					case CR + 128: if (lastc == ' ') c= NUL;
						else c= ' '; break;
					case LF: c= NUL; break; /* LFs ignored */
				}
				if (c) break;		/* got a real one or CR */
			}
			if (count == 0) break;		/* end of file, word too */

/* The CR/SOH machine detects "IFNA Kludge" route lines and other nonsense
embedded in messages; this detects lines beginning with ^A and does not 
output them. */

			if (skipline) {			/* if machine is on, */
				if (c == CR) skipline= 0; /* CR turns it off, */
				continue;		/* eat characters */
			}
			skipline= (c == SOH) && (lastc == CR);
			if (skipline) continue;		/* check for new start */

			if (c == CR) break;		/* end of (the) wor(l)d */
			n= 1;				/* character repeat count */
			if (c == TAB) {			/* convert tabs */
				n= 8 - (screen % 8);	/* to spaces */
				c= ' ';			/* set the character, */
			}
			while (n--) word[i++]= c;	/* build the word */
			word[i]= NUL;			/* for output */
			if (c == ' ') break;
		}

/* Possibly suppress SEEN-BY lines if they occur at the start of the line */

		if (fbit(FBIT_SEENBY)) {		/* if suppressing SEEN-BYs */
			if ((fcomp(word,"SEEN-BY",7) == 0) && (screen == 0)) {
				skipline= 1;		/* dont output until */
				continue;		/* next CR */
			}
		}
		if (wordlen(word,screen) + screen > width) {
			write(f,"\215\n",2);		/* too long; wrap */
			screen= 0;			/* before typing word */
			++lines;
		}
		for (i= 0; word[i]; ++i) {		/* write it out */
			if ((word[i] < ' ') && (word[i] != CR)) {
				write(f,"^",1);		/* process control chars */
				word[i] |= '@';		/* here */
				write(f,&word[i],1);

			} else if (write(f,&word[i],1) != 1) {
				mprintf(CM+68);		/* "disk full" */
				lprintf(LM+16,fn);	/* "disk full filename" */
				break;
			}
		}
		screen += wordlen(word,screen);		/* size on screen */
		if (c == CR) {				/* if a hard CR, */
			write(f,"\r\n",2);		/* do a CR LF */
			screen= 0;
			++lines;
		}
		if (count == 0) break;			/* check EOF */
	}
	if (screen) write(f,"\r\n",2);			/* terminate last line */
	write(f,"\r\n",2);				/* add a blank line */
	close(f);
	closemsg();
	mprintf(CM+174,lines);
}

/* Find the specified message, searching in the specified direction (1 == up,
-1 == down, 0 == dont search). Returns the message number just read or 0 if
none was found. */

fndmsg(msgnbr,dir)
int msgnbr,dir;
{
int n;

	if (! msgnbr) ++msgnbr;			/* first time callers get 0 */

	while (1) {
		if (n= findmsg(msgnbr,dir)) {
			if (uval(CLR_PRV,CLR_PRVS) >= SYSOP) {
				break;					/* sysop can always read */
			}

			if (msgarea.number == fido.netmarea) {		/* FidoNet msg */
				if (!is_us(&msg_dest) && !is_us(&msg_orig)) {
					closemsg();			/* (IN TRANSIT) */
					msgnbr= nxtmsg(n,dir);		/* pick next */
					if (msgnbr != n) continue;
					else {				/* reached the end */
						n= 0;			/* dont display it */
						break;
					}
				}

			}
			if (msg.attr & MSGPRIVATE) {
				if (!to_caller() && !from_caller()) {
					closemsg();
					*msg.from= NUL;			/* blank out the */
					*msg.to= NUL;			/* last msg so we cant */
					*msg.subj= NUL;			/* so reply to (PRIVATE) */
					msg.attr= 0;
					if (dir == 0) {			/* wierd case */
						mprintf(CM+175);	/* "PRIVATE message" */
						return(0);		/* avoid msg below */
					}
					msgnbr= nxtmsg(n,dir);		/* (PRIVATE) */
					if (msgnbr != n) continue;
					else {
						n= 0;			/* dont display it */
						break;
					}
				}
			}
		}
		break;
	}
	if (!n && !dir) mprintf(CM+176,msgnbr);			/* "there is no msg N" */
	return(n);
}

/* Find and display the specified message; returns the same as
fndmsg(), except updates 'justread' with the current message number, if 
found. */

rdmsg(msgnbr,dir,justread)
int msgnbr,dir,*justread;
{
int n;
	n= fndmsg(msgnbr,dir);			/* find one, */
	if (n) {				/* if found, */
		*justread= n;
		typemsg(n);			/* type it, etc */
		setlmsg(n);
	}
	return(n);
}
/* Return true if the passed string is contained anywhere in the
message header. */

inmsg(pat)
char *pat;
{
char thing[SS];
char *match;		/* dummy for stcpm() */

	stolower(pat);				/* check in lower case */

	strcpy(thing,msg.to);			/* local copy of object, */
	stolower(thing);			/* lower case for check, */
	if (stcpm(thing,pat,&match)) 		/* check it, */
		return(1);

	strcpy(thing,msg.from);
	stolower(thing);
	if (stcpm(thing,pat,&match)) 
		return(1);

	strcpy(thing,msg.subj);
	stolower(thing);
	if (stcpm(thing,pat,&match))
		return(1);
	return(0);
}
/* Change the default directory. If no arg entered, display DIR.bbs in each
active directory. Get the directory number. */

static msgsel() {
int saved,n,i;
char buff[SS],*cp;

	saved= msgarea.number;				/* remember which area */

	n= -1;						/* no area selected (yet) */
	if (isargs()) {					/* if input follows, */
		n= atoi(getarg(FM+0)) - 1;		/* and a number, */
		if (!getmarea(n)) n= -1;		/* check validity */
		else if (!allowed(&msgarea)) n= -1;	/* and access */
	}

/* Number is not pre-selected. Display the list or the msginfo file. */

	if (n == -1) if (!dispbbs("msginfo.bbs")) {
		mprintf(CM+177);			/* "Message Areas:" */
		abort= 0;
		for (i= 0; getmarea(i); i++) {
			if (abort) break;
			if (! allowed(&msgarea)) continue;
			if (msgarea.number == fido.netmarea) 
				dsparea(0,&msgarea,')'); /* list each one, */
			else dsparea(0,&msgarea,')');
		}
		if (i == 0) return(0);			/* oops, no areas ... */
	}

/* Now input and verify an area selection. */

	while (1) {
		if (n >= 0) if (getmarea(n)) {		/* if a valid choice, */
			if (allowed(&msgarea)) break;	/* take it as is */
		}
		cp= getarg(CM+178,saved + 1);		/* no, or bad number */
		if (!*cp) n= saved;			/* if blank no change, */
		else n= atoi(cp) - 1;			/* else get number, */
	}
	if (msgarea.number != saved) {			/* if a different area, */
		mprintf(CM+8);
		msgcount();				/* count the messages, */
		msgzap();
	}
	return(saved != msgarea.number);
}

/* Type the contents of the open message file, then close it. Abort 
if ^C typed. Increment the number of times read field. */

static typemsg(msgnbr)
int msgnbr;
{
int i;

	listhdr(&msg,msgnbr);			/* display the header, */
	mcrlf();				/* a blank line */
	dumptext(msgfile);			/* msg contents */

	i= 0;					/* 1 == need to update msg hdr */
	if (! from_caller()) {			/* if not the author */
		++msg.times;			/*   read once more, */
		++i;
	}
	if (to_caller()) {			/* if addressee */
		msg.attr |= MSGREAD;		/* mark as read */
		++i;
	}
	if (i) wrtmsg();			/* update it, */
	else closemsg();			/* or just close it */
}

/* Generate the next message number, check it. */

static nxtmsg(n,dir)
int n,dir;
{
	n += dir;
	if (! n) ++n;				/* first time callers first time */
	if (n < 1) {
		mprintf(CM+179);			/* "lowest message" */
		n= 1;

	} else if (n > *msg_highest()) {
		mprintf(CM+180);			/* "highest message" */
		n= *msg_highest();
	}
	return(n);
}

/* Kill message #N, fixing replies, and recovering credit if this message
was unsent and from this caller. */

static msgkill(msgnbr)
int msgnbr;
{
int reply,up,thisn;

	if (findmsg(msgnbr,0)) {
		closemsg();
		if (to_caller() || from_caller() || (uval(CLR_PRV,CLR_PRVS) >= EXTRA)) {
			up= msg.up;
			reply= msg.reply;		/* get pointers, */
			killmsg(msgnbr);		/* delete msg, */
			setlmsg();			/* adj. caller recd */
			msg.reply= 0;			/* (in case not found) */

/* If this message was FROM the caller, and it was not sent, lower the
debit by the cost of the message. */

			if (from_caller() && ((msg.cost > 0) && (msg.cost <= caller.debit)) ) {
				if (msg.attr & MSGSENT) {
					mprintf(CM+181);	/* "already sent, no credit" */
				} else {
					caller.debit-= msg.cost;
					mprintf(CM+182,bucks_str(msg.cost));
				}
			}

/* Now fix the reply pointers. If this msg had a reply, change the reply to
point to the deleted msgs reply number. (If 0, no reply) */

			if (up) {			/* if it had a reply, */
				if (thisn= findmsg(up,0)) { /* and correct #, */
					if (msg.reply == msgnbr) {
						if (reply == thisn) msg.reply= 0;
						else msg.reply= reply;
						wrtmsg();

					} else closemsg();
				}
			}

/* If this msg was a reply, then change the replied to's msg up pointer to
point to the ext in the chain. (If 0, then no chain.) */

			if (reply) {
				if (thisn= findmsg(reply,0)) {
					if (msg.up == msgnbr) {
						if (up == thisn) msg.up= 0;
						else msg.up= up;
						wrtmsg();

					} else closemsg();
				}
			}
			mprintf(CM+183,msgnbr);		/* "msg N deleted" */
		} else {
			mprintf(CM+169);			/* "not your message!" */
		}
	} else mprintf(CM+176,msgnbr);			/* "there is no msg N" */
}
/* List the header of the message. */

static listhdr(m,n)
struct _msg *m;
int n;
{
#define male (msgarea.number == fido.netmarea)

	mprintf(0,"#%-3u %s [%u] ",n,m-> date,m-> times);
	if (m-> attr & MSGPRIVATE) mprintf(CM+245);
	if (m-> attr & MSGSENT) mprintf(CM+246);
	if (m-> attr & MSGREAD) mprintf(CM+247);
	if (m-> attr & MSGFILE) mprintf(CM+248);
	if (m-> attr & MSGFREQ) mprintf(CM+249);

	if (male) {
		if ((!is_us(&msg_orig) && !is_us(&msg_dest))
		    || (msg.attr & MSGFWD))
			mprintf(CM+250);
	}
	if (m-> attr & MSGORPHAN) mprintf(CM+251);
	if (m-> attr & MSGKILL) mprintf(CM+252);
	if (male) mputs(bucks_str(m-> cost));
	mcrlf();

	mprintf(CM+184,m-> from);		/* From: */
	if (male) {
		mprintf(0,", %s",str_node(&msg_orig));
		if (! is_us(&msg_orig)) {
			if (find_ndat(&msg_orig) != -1)
				mprintf(0,", %s, %s",ndat.name,ndat.city);
		}
	}
	mcrlf();
	
	mprintf(CM+185,m-> to);
	if (male) {
		mprintf(0,", %s",str_node(&msg_dest));
		if (! is_us(&msg_dest)) {
			if (find_ndat(&msg_dest) != -1)
				mprintf(0,", %s, %s",ndat.name,ndat.city);
		}
	}
	mcrlf();

	if (m-> reply) mprintf(CM+186,m-> reply);
	if (m-> up) mprintf(CM+187,m-> up);
	if (m-> reply || m-> up) mcrlf();

	if (m-> attr & (MSGFILE | MSGFREQ)) mprintf(CM+188,m-> subj);
	else mprintf(CM+189,m-> subj);
}

/* Return true if this message is TO this caller. */

static to_caller() {
char buff[SS],name[SS];

	strproc(name,caller.name,99);		/* format callers name */
	strproc(buff,msg.to,99);		/* fixed format TO */
	return(same(name,buff));		/* string compare blah blah */
}

/* Return true if this message is FROM this caller. */

static from_caller() {
char buff[SS],name[SS];

	strproc(name,caller.name,99);		/* format callers name */
	strproc(buff,msg.from,99);		/* make fixed format */
	return(same(name,buff));		/* string compare blah blah */
}

/* Return the next message to be read; if it was saved, this will be
the last msg read. */

static findlmsg()
{
int i,n;

	n= 0;
	for (i= 0; i < MAXLREAD; i++) {
		if (caller.lastmsg[i].area == msgarea.number) {
			n= caller.lastmsg[i].msg;
			break;
		}
	}
	if (n > *msg_highest()) n= *msg_highest();
	return(n);
}

/* Save the highest message number read in the current message area. There
is a (SM+all) fixed number of slots to save msg areas, and probably many msg
areas. If the msg area is not in the table, delete the oldest entry
and add this one. If the current msg number is higher than the one in 
there, it is saved. */

static setlmsg(n)
int n;
{
int i,m;

	m= -1;					/* remember first free slot */

/* Look for the desired area # in the table; also remember the first unused slot
in case we dont find the one we want. */

	for (i= 0; i < MAXLREAD; i++) {	
		if ((caller.lastmsg[i].area == 255) && (m == -1)) m= i;
		if (caller.lastmsg[i].area == msgarea.number) break;
	}

	if (i >= MAXLREAD) {			/* if area not found */
		if (m == -1) m= 0;		/* (bug prevention) */
		i= m;				/* slot to use this time */
		if (++m >= MAXLREAD) m= 0;	/* turn next slot into */
		caller.lastmsg[m].area= 255;	/* free slot */
		caller.lastmsg[m].msg= 0;
	} 

	caller.lastmsg[i].area= msgarea.number;	/* set area number */

	if (n > caller.lastmsg[i].msg) caller.lastmsg[i].msg= n;
	if (caller.lastmsg[i].msg > *msg_highest())
		caller.lastmsg[i].msg= *msg_highest();
}

/* Check if this area is read-only; if so, complain and return non-zero. */

static int chk_ro() {

	if (*ovpath ||				/* O)verride path set, */
	    (uval(CLR_PRV,CLR_PRVS) >= EXTRA) ||/* high caller priv, */
	    !(msgarea.flags & AREA_RO)) 	/* or not O=ReadOnly, */
		return(0);			/* not read-only */

	mprintf(CM+106);			/* "area is read-only" */
	return(1);
}
