/*
     ATP QWK MAIL READER FOR READING AND REPLYING TO QWK MAIL PACKETS.
     Copyright (C) 1992  Thomas McWilliams 
     Copyright (C) 1990  Rene Cougnenc
   
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 1, or (at your option)
     any later version.
     
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
     
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
read.c
*/

/* define prompts and ansi sequences for prompts */

#define	SRMPT  "%s [ %s ] > "  /* format string for simple prompt  */
#define PFROM  "      From: " 
#define PRTO   "        To: "
#define PSUBJ  "   Subject: "
#define PSECR  "  Security: "
#define PTAIL  "[  ]        "
#define A_BLINK  "\33[5m"
#define A_CLEAR  "\33[0m"
#define A_GREEN  "\33[32m"
#define A_HIGH   "\33[1m"
#define A_WHIT   "\33[37m"
#define LEFT35 "\33[35D"
#define RGHT25 "\33[25C"
#define LEFT57 "\33[57D"
#define RGHT54 "\33[54C"
#define PRTAIL "[ " RGHT25 " ]        " LEFT35 A_WHIT  
#define LRTAIL "[ " RGHT54 " ] " LEFT57 A_WHIT  

#define PRMT1  A_GREEN A_HIGH SRMPT
#define PRMT2  A_GREEN A_HIGH "%s [ " A_BLINK "%s" A_CLEAR A_GREEN A_HIGH " ] > "
#define PRMTFR A_GREEN PFROM PRTAIL   
#define PRMTTO A_GREEN PRTO  PRTAIL   
#define PRMTSB A_GREEN PSUBJ PRTAIL
#define PRMTSL A_GREEN PSUBJ LRTAIL
#define PRMTSC A_GREEN PSECR PRTAIL 

#define SRMTFR "      From: "
#define SRMTTO "        To: "
#define SRMTSB "   Subject: "
#define SRMTSC "  Security: " 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#ifndef unix
#ifdef WIN32
#include <malloc.h>
#include <direct.h>
#include <process.h>
#else
#include <alloc.h>
#include <dir.h>
#endif
#include <io.h>
#include <dos.h>
#endif
#include "system.h"
#include "ansi.h"
#include "makemail.h"
#include "qlib.h"
#include "reader.h"
#include "readlib.h"

#ifndef USESYSTEM   /* have tcgetattr() an tcsetattr() */
#include <termios.h> /* terminal stuff */
#include <sys/wait.h>
static struct termios savedterm ; 
#endif

/* global function declarations */

int main(int argc, char *argv[]);

/* static function declarations */

#ifndef USESYSTEM 
static void jert( int a ); /* catches signal SIGINT for unix */
#endif
static void Purge( void );
static void scruter( int mode ) ;
static int  FindActive( const int curconf );
static void showterms( void );
static void ReadShell(void);
static void togltag(void);
static void toglpcb(void);
static void Load(const char *name);
static void Read(const char *name);
static void chconf(const char *buf);
static void AutoJoin(void);
static void SaveMsg(const char *str);
static void Help(void);
static void Tag( char *line );
static int  ReadNext(const int mode);
static void PutHeader( int mode, struct fentry **sptr, int blen );
static void PrintHeader( FILE *fp);
static void Reply(const int mode, const char *line);
static int  AddReply(const char *fname, struct QmailRepType *Qmail);
static void ListConf(void);
static void GoToNum(const char *str);
static void WelcomeMsg( const char *mfile);
static void GetBbs(const char *name);
static void Check4LongSubj(void);
/* DTS removed static to separate out findtxt & findstr */
int  SeekNum(const char *str);
void Display(const int mode, struct fentry *bptr, int blen) ;
void getwinders( int dummy );

/*  end of static function declarations */

/* constant declarations */

#define TRUE 1
#define FALSE 0
#define NEXT 0
#define FIND 4
#define SCAN 8
#define QUICK 12
#define AGAIN 1
#define KILL 5
#define NUKE 9
#define PRIVATE 13
#define PREVIOUS 2
#define RPT_MASK 0x03 /* lower 2 bits used for display mode repeat constant */

/* global variables */

const char CONSPTR TagLine = NTAG ; /* PCBoard style tagline */
const char CONSPTR FidoTag = FTAG ; /* Fidonet style tagline */

#ifndef __MSDOS__
static pid_t Proc_ID ;  /* for unix */
#endif
char         CurTag[256];	/* Tag line chosen...                 */
char         UserTag[256];	/* Save run time defined tag-lines    */
char         OrigTag[256];  /* default tag from atprc config file */ 
static int   dflag = TRUE;	/* toggle for default and user defined tagline */

char            HomePath[MAXPATHS];	/* Home directory root of msg dirs    */
char            MailPath[MAXPATHS];	/* Where to look for new mail         */
char            ReplyPath[MAXPATHS];/* Where to put replies               */ 
char            WorkPath[MAXPATHS];	/* Where to archive/unarchive mail .  */
char            CurBoard[50];	    /* Name of the current board...       */
char 			Welcome[16] ;		/* Name of BBS welcome file			  */
char			News[16] ;			/* Name of BBS news file			  */
char 			GoodBye[16] ;		/* Name of BBS goodbye file			  */

/* variables used by line editor */
char           *luxptr ;         /* passed text to line editor for editing*/

/* variables set in configuration file */

int             ScrnLines = 25;/* default 25, changeable in config file */
int             ScrnCols  = 80;/* default 80, changeable in config file */
long			TruncNum	= 50L;/* default truncation file maintenance   */
int             SaveConf = -1 ;   /* save current conference */
long            RbufSize = MYBUF ;
size_t			RbufRecs = (( MYBUF + 127L ) / 128L ) ;
char            Editor[50];     /* Name of the standard text editor       */
char            Archiver[50];
char            UnArchiver[50];
char            qwklist[100];	/* command line for listing QWK packets */
char            bltlist[100];	/* command line for listing bulletins   */
char            speller[100];   /* command line for invoking speller    */  
int				autotag = TRUE; /* flag for random taglines             */
int             graphics = FALSE;/* flag for vt100 graphics mode        */
int             silent = FALSE; /* flag for no tty bell                 */
int             charset = CHR7BIT ;   /* which char set? 4 is dummy = undefnd.*/
int             fido = FALSE;	/* Flag for tagline style               */
int             ansi = TRUE ;	/* Flag true if ansi output is on       */
int             color = TRUE ;	/* Flag true if ansi output is on       */
int				pcbext = TRUE;/* Flag true to display long PCB subjs  */

/* variables used for reading, checking, writing, closing files */

struct MyIndex  Index;
FILE           *fidx = NULL, *fmsg = NULL;	/* Index File and msg file, globals */
int             FilesOpen = FALSE;	/* Flag if these files are open         */
int             FirstDone = FALSE;  /* Set if 1st message in conf is read   */
static int      newmail = TRUE;     /* used by AutoJoin()                   */
int             ActvCnt = 0;	/* tracks number of active conferences      */
int             CurConf;	    /* Number of current Conference...          */
long int        TotMsg;		    /* Number of messages in conf               */
byte           *rbuf =  NULL ;  /* Pointer to work buffer for messages      */
int             pmail = FALSE;	/* Flag indicates if personal mail waiting  */
int             ReplyExist = 0;	/* Flag 1 if there are replies to pack      */
static int      IsEmpty = TRUE;	/* Flag false if a BBS is loaded            */
int             HeadLetter = 1;	/* Flag 1 if automatic header is active     */
static int		caps = FALSE  ; /* Flag for reply ENTER mode                */
char			SubjBuf[100] ;	/* Long subject for PCBoard		            */
char			termtype[80] ;	/* TERM environ variable					*/

#ifdef UNIXCMDS
#define MAXCMDS  23     /* should equal count of the following array */
static const char CONSPTR cmds[MAXCMDS] = {"cd", "cp", "echo", "free", "ls", "ln", "lpr", "man", "sort", "sync",
		 "mkdir", "more", "mv", "pwd", "ps", "cwd", "rm", "rmdir", "set","cat", "less", "df", "du"
};
#else
#define MAXCMDS 16
static const char CONSPTR cmds[MAXCMDS] = { "del","dir","chkdsk","md","rd",
         "cd", "mem","more", "mkdir","set","print","rmdir","sort","copy", "xcopy","type" } ;
#endif

 /*----------------------------------------------------------------------*/
#ifndef USESYSTEM
static int reperror = FALSE ; /* error during replies Reply() */
static void       /* catch a signal in Reply() */
jert(int a) {
	signal(SIGINT, SIG_IGN);	
	kill( Proc_ID, SIGTERM);
	sleep(2);
	kill( Proc_ID, SIGKILL);
	ATPSETERM ; /* restore terminal parameters */
	reperror = TRUE ;
#ifndef HAVE_SETGET
	signal(SIGINT, SIG_DFL);
#else
	CLSCRN ();
	printf("caught signal: child process aborted\n\n");
	system("ls -altr /tmp"); /* list contents of /tmp directory */
	printf("\nplease clean your old files from /tmp directory\n\n");
	sleep(1);
#endif	
}
#endif

#ifdef TIOCGWINSZ
void
getwinders( int dummy ){

struct winsize siz ;

if( ioctl (STDIN_FILENO, TIOCGWINSZ, (char*) &siz ) < 0 ){
	printf("\nTIOCGWINSZ error getwinder()\n");
	sleep(3); return ;
} 
ScrnLines = siz.ws_row ;
ScrnCols  = siz.ws_col ;
}	
#endif 	

int
main(int argc, char *argv[])
{
	ATPGETERM ; /* save terminal parameters */
#ifndef __MSDOS__  
	Proc_ID = getpid();  /* for unix */
#endif
	luxptr = getenv("TERM");
 	strcpy(termtype, luxptr == NULL ? " " : luxptr ) ;
	if (strlen( getenv("PATH") ) > (size_t) MAXPATHS ){
		printf("PATH environment too long: %d\n", (size_t) MAXPATHS );
		exit(-1);
	} ;
	MakeHomePath();
	if ( ReadConfig() != OK )
		return (ERROR);
#ifdef TIOCGWINSZ
	signal( SIGWINCH, getwinders );
	getwinders(0); 
#endif	
		
	if ((ConfName = malloc ( sizeof(string16) * 2 )) == NULL)
	    return (ERROR);
	Clean();
	clear();
	bblack();
	Title();
	cyan();

	strcpy(CurBoard, txt[10]);     /* First default prompt....   */
	strcpy(ConfName[0], txt[9]);   /* "empty"                    */
	rl_initialize() ;
	if (fido)
		strcpy(CurTag, FidoTag);   /* setup the default TagLines */
	else
		strcpy(CurTag, TagLine);
	strcat(CurTag, OrigTag);
	if ((rbuf = (byte *) malloc (MYBUF)) == NULL) {
		printf("%s\n", txt[1]);	/* Not enough memory */
        	printf("%lu bytes\n", MYBUF );
		exit (0xFF);
	}
	if (argc == 2)
		GetBbs(argv[1]);
	if(autotag) 		
		ChooseTag();		
	printf("%s\n", CurTag);
	ReadShell();
	free (rbuf);
	if (FilesOpen) {
		fclose(fidx);
		fclose(fmsg);
	}
	free (ConfName);
	if( ConfNumbers != NULL) free(ConfNumbers);
	if( ConfActive  != NULL) free(ConfActive );
	clear(); fflush(stdout);
	ATPSETERM ; /* restore terminal parameters */
	Clean();
	return (OK);
}

/*
 * Main Shell
 */

static void
ReadShell(void)
{
	char           prompt[80];
	char           *tmp = NULL ;
	char           *tmpbuf ;
	char           *ptr ;
	int            i ;
	
	if (( tmpbuf = (char *) malloc(MAXPATHS)) == NULL ){ /* local line buffer */
		printf("malloc() failed in read.c module ReadShell()\n\n");
		return;
	}

	while (1) {
topcat:
 		if(tmp != NULL) {
			free(tmp);
			tmp = NULL;
		}
		luxptr = NULL ;
		clear();
		if(ansi) {
		if (pmail && (CurConf == findCindex(PERS_CONF))) {
			sprintf(prompt, PRMT2, CurBoard, ConfName[CurConf]);
		} else {
			sprintf(prompt, PRMT1, CurBoard, ConfName[CurConf]);
		} 
		} else /* non-ansi */
			sprintf(prompt, SRMPT, CurBoard, ConfName[CurConf]);

		while ((tmp = readline(prompt,TRUE))==NULL) ;
		add_history(tmp);	
		clear();
		fflush(stdout);
		StripDel(tmp);
		StripLSpace(tmp);

		for (i = 0; i < MAXCMDS; i++) {	/* Internal shell commands */
			if (!strnicmp(tmp, cmds[i], strlen(cmds[i]))) {
				system(&tmp[0]);
                goto topcat ;  /* break from loop and take it from the top! */
			}
		}

		if(!strnicmp( tmp,"q!", 2)) tmp[1] = '\0' ;

		if (Numeric(tmp))
			GoToNum(tmp);

		else if (!strnicmp(tmp, "show ", 5))
			showterms();

		else if (!strnicmp(tmp, "aide", 4))
			Help();

		else if (!strnicmp(tmp, "cls", 3))
			CLSCRN ();

		else if (!strnicmp(tmp, "clean", 5))
			Purge();

		else if (!strnicmp(tmp, "conf", 4))
			ListConf();

		else if (!strnicmp(tmp, "date", 4))
			Date();

		else if (!strnicmp(tmp, "fido", 4))
			togltag();

		else if (!strnicmp(tmp, "find ", 5))
			(void) findtxt(tmp, FIND);

		else if (!strnicmp(tmp, "pcb", 3))
			toglpcb();
			
		else if (!strnicmp(tmp, "ts", 2))
			(void) findtxt(tmp, FIND);

		else if (!strnicmp(tmp, "help", 4))
			Help();

		else if (!stricmp(tmp, "last")){
			sprintf(prompt,"%ld",TotMsg);
			GoToNum(prompt);
		}

		else if (!stricmp(tmp, "next" ))
			(void) findtxt(tmp, NEXT);

		else if (!strnicmp(tmp, "scan", 4))
			scruter(SCAN);

		else if (!strnicmp(tmp, "qscan", 5))
			scruter(QUICK);

		else if (!strnicmp(tmp, "ql", 2))
			Qlist(qwklist);

		else if (!stricmp(tmp, "bl") || !stricmp(tmp, "blt") )
			Blist(bltlist);
#ifdef LISTDIR
		else if (!strnicmp(tmp, "al", 2))
			list_dir( "/foobar" );	
#endif
		else if (!strnicmp((char *) tmp, "graph", 4)) {	/* toggle autotag line selection */
			if (graphics){
				graphics = FALSE;
				printf(    "\n\t\t +------------------------------+\n");
				printf(      "\t\t |                              |\n");
				printf(      "\t\t |  vt100 graphics are now OFF  |\n");
				printf(      "\t\t |                              |\n");
				printf(      "\t\t +------------------------------+\n\n");
			}else{
				graphics = TRUE ;
				printf("\n\016\t\t lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk\n");
				printf(      "\t\t xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax\n");
				printf(      "\t\t xaa\017 vt100 graphics are now ON\016 ax\n");
				printf(      "\t\t xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax\n");
				printf(      "\t\t mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj\n\n\017");
			}
		}	
		else if (!strnicmp(tmp, "head", 4)) {
			blue();
			high();
			HeadLetter = HeadLetter ? 0 : 1;
			printf("%s ", txt[101]);	/* "Automatic H." */
			printf("%s\n", HeadLetter ? txt[85] : txt[86]);	/* "on" / "off"   */
			green();
			fflush(stdout);
		
		} else if (!strnicmp(tmp, "time", 4))
			Date();

		else if (!strnicmp(tmp, "welcome", 4))
			WelcomeMsg( Welcome );

		else if (!strnicmp(tmp, "hello", 5))
			WelcomeMsg( Welcome );

		else if (!strnicmp(tmp, "goodbye", 5))
			WelcomeMsg( GoodBye );
			
		else if (!strnicmp(tmp, "news", 4))
			WelcomeMsg( News );
			
		else if (!strnicmp(tmp, "file", 4)) 
			WelcomeMsg( NEWFILES );
				
		else if (!strnicmp(tmp, "door", 4)) 
			WelcomeMsg( DOORID );
				
		else if (!strnicmp(tmp, "blt-", 4)) 
			WelcomeMsg( tmp );

		else if (!strnicmp(tmp, "load", 4)) {
			if ((!IsEmpty) && ConfActive[CurConf])
				UpdateConf(UPDATE);
			Load(tmp);	/* Load new mail      */
		} else if (!strnicmp(tmp, "merde", 5))
			merde();/* Load new mail      */

		else if (!strnicmp(tmp, "rev", 3)) {
			if ((!IsEmpty) && ConfActive[CurConf])
				UpdateConf(UPDATE);	/* Save current conf pointer */
			Read(tmp);	/* read existing mail        */
		} else if (!strnicmp(tmp, "tag", 3))
			Tag(tmp);	/* change tagline     */

		else if (!stricmp(tmp,"reset")){
			UpdateConf(RESET);
		}
        else if ( tmp[0] == '\0' || tmp[1] == '\0' || tmp[1] == '\040' ){

            switch ( tmp[0] ) {

            case '!':
                if (tmp[1]) {  
                    system((char *) &tmp[1]);
                } else {
                    ptr = getenv( SHELL );
                    if (ptr)
                        system(ptr);
                }
                ATPSETERM ; /* reset terminal paramaters */
                break;

            case 'c':
            case 'C':
                if(CurConf == RCONF_IDX && FirstDone )
                        Reply(EDIT, tmp);
                break;

            case 'e':
            case 'E':
                if(CurConf == RCONF_IDX && tmp[1] == '\0' ) {
                    if (FirstDone)
                        Reply(EDIT, tmp);
                }
                else {
                    Reply(ENTER, tmp);
                }
                break;

            case 'j':
            case 'J':
               	chconf(tmp);
                break;

            case 's':
            case 'S':
                SaveMsg(tmp);
                break;
            default:
            break;
            }
        if( !tmp[1] || !tmp[0] )
	    switch( (int) tmp[0] ) {
            case '?':
		Help();
		break;

	    case 'a':
	    case 'A':
		if (FirstDone)
			Display(0, NULL, 0); 
		else
			ReadNext(NEXT);
		break;
#ifdef ATPDBG				
	    case 'i':
		printf("CurCon: %d   Index.LastRead: %d\n", CurConf, Index.LastRead);
		break;
#endif
	    case 'k':
		case 'K':
		ReadNext(KILL);
		break;

 	    case 'm':	 /* toggle ANSI mode on/off */
 	    case 'M':
 		ansi = ansi ? FALSE : TRUE ;
 		yellow();
 		high();
 		printf("%s %s .\n", txt[84], ansi ? txt[85] : txt[86]);
 		break;
 
	    case 'p':
	    case 'P':
		if(CurConf == RCONF_IDX)
		ReadNext(PRIVATE);
		break;			

	    case 'q':
	    case 'Q':
	    case 'g':
	    case 'G':
		if (!IsEmpty)
			UpdateConf(UPDATE);	/* Save current conf pointer */
		if (FilesOpen) {
			fclose(fidx);
			fclose(fmsg);
			FilesOpen = FALSE;
		}
		if (ReplyExist) {
			red();
			high();
			printf("%s\n%s %s.\n", txt[2], txt[3], CurBoard);	/* Warning, you have  */
			sprintf(prompt,"%s", txt[4]);	/* Replies,pack them ? */
			if (YesNo(YES,prompt))
			PackReply();
		}
		free(tmp);	
		free(tmpbuf);
		clear();
		return;

	   case 'n':
 	   case 'N':
		AutoJoin();
		break;

       	   case 'r':
       	   case 'R':
       	   	if (FirstDone && CurConf != RCONF_IDX)
            		Reply(REPLY, tmp);
            	break;

	case '+':
	case 0:
   		ReadNext(NEXT);
		break;

	case '-':
		ReadNext(PREVIOUS);
		break;
         }
      }
   }
}

static void
togltag(void)
{				/* switch tagline styles */
	fido = (fido ? FALSE : TRUE);
	Tag("tag \177");
}

static void
toglpcb(void)
{				/* switch support for PCBoard long subjects */
	pcbext = (pcbext ? FALSE : TRUE);
 	yellow();
 	high();
 	printf("%s %s .\n","PCBoard long subjects are", pcbext ? txt[85] : txt[86]);
}

static void
Load(const char *name)
{
	char            BbsName[50];
	char            tmp3[MAXPATHS];
	char            tmp2[MAXPATHS];
	char            tmp[MAXPATHS];
	char            OldDat[MAXPATHS];
	char            NewDat[MAXPATHS];
	char            prmbuf[80]; /* buffer for prompt passed to YesNo */
	struct stat     Oldst;
	struct stat     Newst;
	int             i;
#ifdef NONUM
	char           *tptr;
#endif 	
	tmp3[0]=0 ; tmp2[0]=0 ; tmp[0]=0 ;
	pmail = FALSE;		/* reset global flag to indicate no personal mail yet */
#ifdef ATPDBG
Oldst.st_mtime = Oldst.st_ctime = Oldst.st_atime = 0L ;
Newst.st_mtime = Newst.st_ctime = Newst.st_atime = 0L ;
#endif

	if (ReplyExist) {
		red();
		high();
		printf("%s\n%s %s.\n", txt[2], txt[3], CurBoard);	/* Warning, you have  */
		sprintf(prmbuf,"%s", txt[4]);	/* Replies,pack them ? */
		if (YesNo(YES,prmbuf))
			PackReply();
	}
	BbsName[0] = '\0';
	sscanf(name, "%s %s", tmp, BbsName);
	if (!BbsName[0]) {
		red();
		printf("%s  %s\n", txt[87], txt[88]);	/* "usage" " load.." */
		return;
	}
	printf("\n%s %s\n", txt[5], BbsName); /* "Loading" */ 

	if (strstr(BbsName, ".qw") == NULL)
		strcat(BbsName, ".qwk");

	sprintf(tmp, "%s%s", MailPath, BbsName);

/*
 * 	Now that we've used BbsName to id the packet file strip any
 * 	trailing digits so the board's subdir doesn't vary w/ packet #.
 */

	i = -1;
	while (BbsName[++i]);
	while (BbsName[--i] != '.');
	BbsName[i] = '\0';
#ifdef NONUM
	tptr = BbsName;
	if (!Numeric(tptr)) /* this code only for problems with Searchlight BBS */
		while (isdigit(BbsName[--i])) /* don't use it unless you need it.   */
			BbsName[i] = '\0';
#endif
	if (access(tmp, R_OK )) {
		red();
		printf("%s : %s\n", txt[6], tmp);	/* No mail found        */
		printf("%s\n", txt[7]);	/* Try the read command */
		return;
	}
	Clean();		/* Don't forget to clean work directory ! */
	yellow();
	high();
	printf("%s\n", txt[8]);	/* " Extracting Messages..." */
	green();
	fflush(stdout);
	GETWD (tmp3, MAXPATHS );	/* save current directory    */
	if ( ! CHPATH (WorkPath)) {	/* change to work directory  */
		sprintf(tmp2, "%s %s", UnArchiver, tmp);    /* build unzip command line  */
		system(tmp2);  /* execute unzip in work dir */
		CHPATH (tmp3);        /* restore current directory */
	} else {
		yellow();
		printf("Error: can't access workpath: %s\n", WorkPath);
		return ;
	}
	yellow();
	sprintf(tmp3, "%s%c%s", WorkPath, SEP, CNTRL_FILE);
	if (access(tmp3, F_OK )){
		printf("Error: can't find control file: %s\n", tmp3);
		return ;
	}
	sprintf(tmp2, "%s%s", HomePath, BbsName);	/* Access to a board subdir */
	if (access(tmp2, R_OK | W_OK ))
		my_mkdir(tmp2);

	sprintf(OldDat, "%s%s%c%s", HomePath, BbsName, SEP, CNTRL_FILE);
	sprintf(NewDat, "%s%c%s", WorkPath, SEP, CNTRL_FILE);
	if (access (OldDat, F_OK) == OK) {	/* If there exists an old control.dat */
		if( stat(OldDat, &Oldst) != OK ) {
			printf("Load() Can't stat OldDat\n");
			sleep(3);
		}
		if( stat(NewDat, &Newst) != OK ){
			printf("Load() Can't stat NewDat\n");
			sleep(3);
		}
#ifdef ATPDBG
		assert( Oldst.st_mtime > 0L ) ;
		assert( Newst.st_mtime > 0L ) ;
#endif
		if (Newst.st_mtime <= Oldst.st_mtime) {
			red();
			high();
			printf("%s\n%s.\n", txt[2], txt[11]);	/* "New packet older..." */
			sprintf(prmbuf , "%s...", txt[12]);	/* " Do you  want to.." */
			if (!YesNo(NO,prmbuf))
				return;
		}
	}
	strcpy(CurBoard, BbsName);
	MkIndex(WorkPath, tmp2);/* Create Index Files */
	Chk4Rep();
	Chk4Cnf(tmp2);  
	if (FilesOpen) {
		fclose(fidx);
		fclose(fmsg);
		FilesOpen = FALSE;
	}
	IsEmpty = FALSE;
	newmail = TRUE;
	caps = !fido ;
	if (pmail)
		CurConf = findCindex(PERS_CONF);
	else
		CurConf = FindActive(LastConf);
	if (CurConf < 0)
		CurConf = 0;
	GetConf(CurConf);
}


/*
 * Join a BBS without extracting new mail.
 */

static void
Read(const char *name)
{
	char            BbsName[50];
	char            tmp[MAXPATHS];
	if (ReplyExist) {
		red();
		printf("%s\n%s %s.\n", txt[2], txt[3], CurBoard);	/* Warning, you have  */
		sprintf(tmp,"%s", txt[4]);	/* Replies,pack them ? */
		if (YesNo(YES,tmp))
			PackReply();
		tmp[0] = '\0' ;
	}
	BbsName[0] = 0;
	sscanf(name, "%s %s", tmp, BbsName);
	if (!BbsName[0]) {
		red();
		printf("%s %s\n", txt[87], txt[89]);	/* "usage " "read..." */
		return;
	}
	printf("%s %s\n", txt[5], BbsName);	/* "Loading" */
	sprintf(tmp, "%s%s%c%s", HomePath, BbsName, SEP, CNTRL_FILE );
	if (access(tmp, F_OK )) {
		printf("%s : %s\n", txt[13], tmp);	/* "No bbs found " */
		return;
	}
	sprintf(tmp, "%s%s", HomePath, BbsName );
	if (ReadControl(tmp) != OK ) {
		printf("%s\n", txt[14]);	/* "Error in CONTROL.DAT." */
		return;
	}
	strcpy(CurBoard, BbsName);
	Chk4Rep();
	Chk4Cnf(tmp);
	if (FilesOpen) {
		fclose(fidx);
		fclose(fmsg);
		FilesOpen = FALSE;
	}
	ActvConf();		/* update boolean array of active/inactive flags */
	IsEmpty = FALSE;
	newmail = FALSE;
	caps = !fido ;
	CurConf = FindActive(LastConf);
	if (CurConf < 0)
		CurConf = 0;
	GetConf(CurConf);
}


/*
 * CHCONF : Change active conference.
 */
static void
chconf(const char *buf)
{
	char            Name[100];
	char            tmp[MAXPATHS];
	int             i ;
	unsigned int    m ;

	if (IsEmpty) {
		EmptyMsg();
		return;
	}
	Name[0] = 0;
	sscanf(buf, "%s %s", tmp, Name);
	if (!Name[0]) {
		red();
		printf("%s\n", txt[87]);	/* "Usage" */
		printf("\tj %s\n\t\t%s\n", txt[90], txt[91]);	/* "Conf #" "or" */
		printf("\tj %s\n", txt[92]);	/* "conf name" */
		printf("%s\n", txt[93]);	/* "type conf to list..." */
		return;
	}
	if (Numeric(Name)) {	/* a number is given */
		i = atoi(Name);
		if ((i = findCindex(i)) > -1)
			strcpy(Name, ConfName[i]);
	} else {		/* a name is given   */
		
		strcpy(tmp, strstr(buf, Name));
		strcpy( Name, tmp ) ;
		m = strlen(Name);
		for (i = 0; i <= LastConf; i++) {
			if (!stricmp(Name, ConfName[i]))
				break;
		}
		if( i > LastConf ) {		
			for (i = 0; i <= LastConf; i++) {
				if (!strnicmp(Name, ConfName[i], m))
					break;
			}	
		}
	}

	if (!stricmp(Name, "MAIN" ))
		i = 0;		/* Special case for "main board" */

	if (i > LastConf || i < 0) {
		printf("\n%s\n", txt[28]);	/* "Unknown conference" */
		return;
	}
	sprintf(tmp, "%s%s%c%d.cnf", HomePath, CurBoard, SEP, ConfNumbers[i]);
	if (access(tmp, F_OK )) {
		red();
		printf("%s : %s  %s\n", txt[6], tmp, ConfName[i]);	/* "No mail found" */
		return;
	}
	UpdateConf(UPDATE);		/* Save current conf pointer */
	if (GetConf(i) == ERROR)
		return;
	printf("\n ");
	blue(); 
	high();
	printf("*  %s %s %s. *", txt[29], ConfName[CurConf], txt[30]);
	green();
	printf("\n\n");
	/* "Conference " "joined" */
	clear();
	fflush(stdout);
}


/*
 * Loads next valid conferences.
 */
#define ILR Index.LastRead

static void
AutoJoin(void)
{
	char            tmp[MAXPATHS];
	int             i, j;

	if (IsEmpty) {
		EmptyMsg();
		return;
	}
	if (!ActvCnt) {
		chconf("j MAIN\n");
		return;
	}
	i = CurConf;
	j = ActvCnt ;
	while (j--) {
		i = FindActive(i);
		sprintf(tmp, "j %d\n", ConfNumbers[i]);
		chconf(tmp);
		if ( ILR < 0L || ILR != (TotMsg - 1) || !newmail ){
			return ;
		} 
		else 		
			printf("\t%s.\n", txt[31]);	/* "No new mail" */
	}
	newmail = FALSE;
	printf("\n");
}

#undef ILR

/*
 * Save current message in text file ( append mode ).
 */

static void
SaveMsg(const char *str)
{
	char            dummy[MAXPATHS];
	char            fname[MAXPATHS];
	byte           *ptr;
	FILE           *fp;
    unsigned long   i;
	int             apflag;

	if (IsEmpty) {
		EmptyMsg();
		return;
	}
	fname[0] = 0;
	sscanf(str, "%s %s", dummy, fname);
	if (!fname[0]) {
		high();
		yellow();
	ptr = (byte *) readline(txt[39],TRUE);
	clear(); fflush(stdout);
	fname[0] = '\0' ;
	if (ptr != NULL){
		strcpy(fname, (char *) ptr);
		free(ptr) ;
	}
	if (!fname[0]) {
			printf("%s.\n", txt[40]);	/* "Aborted" */
			return;
		}
	}
	apflag = access(fname, W_OK ) ? 1 : 0;

	if ((fp = fopen(fname, "a")) == NULL) {
		red();
		high();
		printf("%s %s\n", txt[51], fname);	/* "unable to open file" */
		return;
	}
	PrintHeader(fp);
	ptr = (byte *) (rbuf + sizeof(struct MsgHeaderType));
	i = 0;
	while (i < Index.Size) {
		if (*ptr != 0){
			if(charset == ISOLAT1 )
	  			fputc( codelu[  (unsigned) (*ptr) ] , fp) ;
			else if (charset == CHR7BIT)
			    fputc( code7bit[(unsigned) (*ptr) ] , fp) ;
			else
				fputc(*ptr, fp);
		}
		i++;
		ptr++;
	}

	fprintf(fp, "\n");

	blue();
	high();
	/* printf("Message %s",apflag ? "Saved in" : "Appended to"); */
	printf("%s %s", txt[41], apflag ? txt[42] : txt[43]);
	clear();
	cyan();
	printf(" %s\n", fname);
	fclose(fp);
}


/*
 * Help message.
 */

static void
Help(void)
{
	unsigned      i;

	white();
	high();
	printf("\n%s", hlp[1]);
	clear();
	printf("\n");
	for (i = 0; i < strlen(hlp[1]); i++)
		putchar('-');
	printf("\n");
	high();
	printf("\r\t q,g\t%s\n", hlp[2]);
	printf("\t k\t%s\n", hlp[3]);
	printf("\t !\t%s\n", hlp[4]);
	printf("\t +\t%s\n", hlp[5]);
	printf("\t -\t%s\n", hlp[6]);
	printf("\t a\t%s\n", hlp[7]);
	printf("\t e\t%s\n", hlp[8]);
	printf("\t j\t%s\n", hlp[9]);
	printf("\t n\t%s\n", hlp[11]);
	printf("\t r\t%s\n", hlp[12]);
	printf("\t s\t%s\n", hlp[13]);
	printf("\t find foobar\t%s\n",hlp[25]);
	printf("\t conf\t%s\n", hlp[14]);
	printf("\t clean\t%s\n", hlp[15]);
	printf("\t load\t%s\n", hlp[16]);
#ifdef ENGLISH
	printf("\t review\t%s\n", hlp[17]);
#else  /* francais */
	printf("\t revois\t%s\n", hlp[17]);
#endif
	printf("\t files\t%s\n", hlp[18]);
	printf("\t tag help\t%s\n", hlp[19]);
	printf("\t head\t%s\n", hlp[22]);
	printf("\t scan\t%s\n", hlp[24]);
	printf("\t qlist\t%s\n", hlp[23]);
	printf("\n");
}



/*
 * Change Reader Signature :-)
 */
static void
Tag( char *line)
{
	char            dummy[50];
	char            tmp[256];
	char            tmp2[256];
	int             i,j ;
	tmp2[0] = tmp[0] = 0;

	sscanf(line, "%s %s %s", dummy, tmp, tmp2);

 	if (tmp2[0] == 0 && (strnicmp((char *) tmp, "list", 4) == 0)) {	/* list taglines */
		sprintf(tmp2, "%s%s", HomePath, TAGFILE);
		printf("%s\n", tmp2 );
		if (!access(tmp2, R_OK )) {
			tmp[0] = 0 ;
			sprintf(tmp, "%s", HomePath);
			tagview(tmp, TAGFILE );
		}
		printf("\nDefault Tag : %s", OrigTag);
		printf("User defined: %s", UserTag);
		printf("\n");
		return;
	}
	if (tmp2[0] == 0 && Numeric((char *) tmp)) {	/* try to get a tagline from the list */
		i = atoi((char *) tmp);
		i = i < 0 ? -i : i;
		TagSeek( (unsigned) i);
		printf("Current Tag now set to:");
		printf("%s\n", CurTag);
		return;
	}
	if (tmp2[0] == 0 && tmp[0] == '?') {	/* Print current tag */
		printf("Current TagLine is:");
		printf("%s\n", CurTag);
		return;
	}
 	if (tmp2[0] == 0 && (strnicmp((char *) tmp, "rand", 4) == 0)) {	/* select tag at random  */
		ChooseTag();
		printf("Current Tag now set to:");
		printf("%s\n", CurTag);
		return;
	}
 	if ((tmp2[0] == 0 && (strnicmp((char *) tmp, "help", 4) == 0)) || line[3] == '\0') {	/* select tag help menu */
		white();
		high();
		printf("\n%s", taghlp[1]);
		clear();
		printf("\n");
		for (j = 0; j < (int) strlen(taghlp[1]); j++)
			putchar('-');
		printf("\n");
		high();
		printf("\t tag list\t%s\n", taghlp[2]);
		printf("\t tag ?   \t%s\n", taghlp[3]);
		printf("\t tag `n' \t%s\n", taghlp[4]);
		printf("\t tag random\t%s\n", taghlp[5]);
		printf("\t tag swap\t%s\n", taghlp[6]);
		printf("\t tag auto\t%s\n", taghlp[7]);
		printf("\t tag     \t%s\n", taghlp[8]);
		printf("\t tag help\t%s\n", taghlp[9]);
		printf("\t fido    \t%s\n", taghlp[10]);
		printf("\n");
		printf("Current TagLine is:");
		printf("%s\n", CurTag);
		return;
}
 	if (tmp2[0] == 0 && (strnicmp((char *) tmp, "auto", 4) == 0)) {	/* toggle autotag line selection */
		if (autotag){
			autotag = FALSE;
			printf("\nautotag is OFF\n\n");
		}else{
			autotag = TRUE ;
			printf("\nautotag is ON\n");
			ChooseTag();
			printf("Current Tag now set to:");
			printf("%s\n", CurTag);
		}
		return;
	}	
	if ((tmp2[0] == 0) && (strnicmp((char *) tmp, "swap", 4) == 0)){	/* restore standard tag */
		dflag = dflag ? FALSE : TRUE;
		if (fido)
			strcpy(CurTag, FidoTag);
		else
			strcpy(CurTag, TagLine);
		if (dflag)
			strcat(CurTag, OrigTag);
		else
			strcat(CurTag, UserTag);
		printf("Current Tag now set to:");
		printf("%s\n", CurTag);
		return;
	}
	if (!stricmp((char *) tmp, "fido")) {
		fido = (fido ? FALSE : TRUE);
		tmp[0] = '\177' ;
	}
	if (tmp[0] == '\177') {	/* toggle fido tag */
		strcpy((char *) tmp, (char *) CurTag);
		if (fido) {
			line = (char *) tmp + strlen(TagLine);	/* point to start of tag message */
			strcpy(CurTag, FidoTag);
		} else {
			line = (char *) tmp + strlen(FidoTag);
			strcpy(CurTag, TagLine);
		}
		strcat(CurTag, line);
		printf("Current Tag now set to:");
		printf("%s\n", CurTag);
		return;
	} 
	if (line[3] == '\040' ) {
		line += 4;	/* Change current tag to User defined Tag */
		strcpy(UserTag, line);
		strcat(UserTag, "\n");
		if (fido)
			strcpy(CurTag, FidoTag);
		else
			strcpy(CurTag, TagLine);
		strcat(CurTag, UserTag);
		dflag = FALSE;
		printf("Tag is now set to :");
		printf("%s\n", CurTag);
	}

}


/*
 * Print next, previous or current message.
 */

static int
ReadNext(const int mode)
{
	byte			tchar  ;
	long            here ;
    size_t          nrecs ;

    if( mode < NEXT || mode > PRIVATE )
		return(0) ;

	if (IsEmpty) {
		EmptyMsg();
		return (0);
	}
	if (!FilesOpen) {
		printf("%s \n", txt[44]);	/* no mail in conf */
		if (mode == SCAN || mode == QUICK )
			return (0);
		else
			AutoJoin();
		return (0);
	}
	/* if needed, seek to new record in conference index file */
	if ( (mode & (int) RPT_MASK) != 0 ) {
		here = ftell(fidx) - (long) ((mode & RPT_MASK) * sizeof(struct MyIndex));
		if (here < 0L) {
			printf("%s\n", txt[15]);	/* "First message !" */
			return (0);
		}
		if (fseek(fidx, here, SEEK_SET)) {
			printf("%s.\n", txt[16]);	/* "Seek error" */
			return (0);
		}
	}
	/* get new index information and check for end of conference */
	if (fread( &(Index.LastRead), 1, sizeof(struct MyIndex), fidx)
	    != sizeof(struct MyIndex)) {
		printf("%s\n", txt[17]);	/* "End of messages." */
		if (mode == SCAN || mode == FIND || mode == QUICK )
			return (0);
		else
			AutoJoin();
		return (0);
	}
	/* use new index information to seek to new message in msg file */
	if (fseek(fmsg, Index.Offset, SEEK_SET)) {
		printf("%s!\n", txt[16]);	/* "Seek Error" */
		return (0);
	}
	fread( &tchar, 1, 1, fmsg);	/* read status into variable */
    fseek( fmsg, Index.Offset, SEEK_SET);   /* re-seek           */

	if (mode == KILL || mode == NUKE ){
		tchar = tchar ^ 0x80 ; 		/* XOR status with 0x80      */
		if( mode == NUKE ) tchar = tchar | 0x80 ; 
		fwrite( &tchar,1, 1,fmsg);	/* write back new status     */
		fflush(fmsg);
		fseek(fmsg,Index.Offset, SEEK_SET); /* re-seek           */
	}
	if (mode == PRIVATE){
		tchar = ( tchar == 0x2A ) ? 0x20 : 0x2A ;	/* XOR status with 0x80      */
		fwrite( &tchar,1, 1,fmsg);	/* write back new status     */
		fflush(fmsg);
		fseek(fmsg,Index.Offset, SEEK_SET); /* re-seek           */
	}
	nrecs = (( Index.Size / 128 ) + 1 ) /* Msg + Head */ ;
	if ( mode == QUICK){
		fread( rbuf, 128, 1, fmsg );
		SubjBuf[0] = 0 ; 
		PutHeader(mode, NULL, 0);
	}
	else { 
		if ( nrecs > ( RbufSize / 128 ) )  /* try to reallocate buffer */
			if ( !reup( (unsigned long) (nrecs+1)*128L ))
				return(0) ;
    	if (fread((char *) rbuf, 128, nrecs, fmsg) != nrecs ) {
       		printf("%s? \n", txt[18]);  /* Read Error */
			return (0);
	}
	Display(mode, NULL, 0);
	}
 	return (1);
}


/*
 * Prints the Qmail message header pointed by buf .
 */

static void
PutHeader(int mode, struct fentry **sptr, int blen)
{
	struct MsgHeaderType Header;
	byte  statu  ;
	int i ;
	byte *pntr , findbuf[256] ;
	struct fentry **dum1, *dum2 = NULL, *dum3 ;

	dum1 = ( sptr == NULL )? &dum2 : sptr; /* don't dereference null pointer */

	memcpy ( &Header.Status, rbuf, sizeof(struct MsgHeaderType) );
	pntr =  (byte *) Header.MsgDate ;
  	 
	if ( charset == ISOLAT1 ){
    	for( i=0 ; i<88 ; i++ , pntr++ ) /* translate header info */
	       *pntr = codelu[ ( unsigned ) *pntr  ] ;
	}
	else if ( charset == CHR7BIT ){
    	for( i=0 ; i<88 ; i++ , pntr++ ) /* translate header info */
		   *pntr = code7bit[ (unsigned) *pntr  ] ;		
	}

	/* check for lowercase letters in to/from fields */
	caps = TRUE ;
	pntr =  (byte *) (Header.ForWhom) ;
	for( i=0 ; i<50 ; i++ )
		if( pntr[i] >= 'a' && pntr[i] <= 'z' )
			caps = FALSE ;

	/* First line */
if(mode==SCAN){
	high();
	green();
	printf("\n%s", txt[19]);/* " From :" */
	yellow();
	*dum1 = hprint( rbuf,(unsigned) (21+25) , 25, sptr, blen); /* print Author */ 
	/*nprint(Header.Author, 25);*/ 
	magenta();
	printf(" : %s", ConfName[findCindex(readCnum((byte *) &(Header.BinConfN)))]);
	
	/* Second line */
	green();
	printf("\n%s", txt[20]);/* "To:" */
	red();
	if (!strnicmp(User1Name, (char *) (Header.ForWhom), strlen(User1Name))||
	   (!strnicmp(User2Name, (char *) (Header.ForWhom), strlen(User2Name)))) 
		blink();
	*dum1 = hprint( rbuf,(unsigned) 21, 25, sptr, blen); /* print ForWhom */ 
	/*nprint(Header.ForWhom, 25);*/

	clear();
	green();
	high();
	printf(" : %s", txt[23]);	/* "Number" */
	red();
	nprint(Header.NumMsg, 7);
	green();
	printf(" %s", txt[24]);	/* " Ref # " */
	yellow();
	nprint(Header.RefMsg, 7);

	green();
	printf("\n%s", txt[22]);/* "date:" */
	red();
	nprint(Header.MsgDate, 8);
	green();
	printf("%s", txt[26]);	/* "time:" */
	red();
	nprint(Header.MsgTime, 5);
	clear();
	printf("    : ");
	blue();
	printf("Index  : %ld/%ld", Index.MsgNum + 1, TotMsg);	/* 0 based, print 1 based. */
	statu = Header.Status ;
	if (statu == '+' || statu == '*' || statu >= 0x80) {
		red();
		printf("\t");
		high();
		blink();
		if (statu >= 0x80 )
			printf(" %s%c", txt[105], BELL);	/* "KILLED MESSAGE" */
		else			
			printf(" %s%c", txt[27], BELL);	/* "PRIVATE MESSAGE" */
	}
	clear();
	green();
	printf("\n");

	printf("%s", txt[21]);/* "Subject" */
	cyan();
	if( SubjBuf[0] == 0)  
		*dum1 = hprint(rbuf,(unsigned) (21+50), 25, sptr, blen); /* print Subject */
	else {  /* find string in long subject buffer */
		findbuf[0] = 0 ; dum1 = &dum2 ; dum2 = NULL ;
		if( sptr != NULL && blen ){
			if( (*sptr)->findpt != NULL ){
				memcpy( findbuf, (*sptr)->findpt, (unsigned) blen); 
				findbuf[blen] = '\0' ; 
				iso2dosup( findbuf );	
				findstr( (byte *) SubjBuf, findbuf, &dum2 ) ;
			} 
		}
		hprint( (byte *) SubjBuf,(unsigned) 0, strlen(SubjBuf), &dum2, blen); /* print Subject */
		while( dum2 != NULL ) {  /* free linked list */
				dum3 = dum2->fnext ;
				free( dum2 );
				dum2 = dum3 ;
		}
	}
	cyan();
	printf("\n\n");
} else { /* QUICK scan */
  		high();
 		yellow();
 		nprint(Header.Author, 25);
 		red();
 		if (!strnicmp(UserName, (char *) (Header.ForWhom), strlen(UserName))
		    && (CurConf != PCONF_IDX )) 
 			{
 			blink();
 			/* printf("%c",7); no way! don't ring bell */
 			}
 		nprint(Header.ForWhom, 25);
		clear();
 		red();
 		nprint(Header.Subject, 25);
 		blue();
 		printf("%ld", Index.MsgNum + 1);	/* 0 based, print 1 based. */
		statu = Header.Status ;
	if (statu == '+' || statu == '*' || statu >= 0x80) {
		red();
		high();
		blink();
		if (statu >= 0x80 )
 			printf("%c\n", 'K'); /* "KILLED MESSAGE" */
		else			
 			printf("%c\n", 'P'); /* "PRIVATE MESSAGE" */
	} else
 		printf("\n");
 		clear();
 		cyan();
        }
 }
  

/*
 * Prints the Qmail message header in file fp.
 */

static void
PrintHeader(FILE * fp)
{
	struct MsgHeaderType Header;
	const char CONSPTR Space = "\t\t";
	int i ;
	byte *pntr ;

	memcpy ( &Header.Status, rbuf, sizeof(struct MsgHeaderType) );
	pntr =  (byte *) Header.MsgDate ;

	if ( charset == ISOLAT1 ){
    	for( i=0 ; i<88 ; i++ , pntr++ ) /* translate header info */
	       *pntr = codelu[ ( unsigned ) *pntr  ] ;
	}
	else if ( charset == CHR7BIT ){
    	for( i=0 ; i<88 ; i++ , pntr++ ) /* translate header info */
		   *pntr = code7bit[ (unsigned) *pntr  ] ;		
	}
	
	
   /* First line */
	fprintf(fp, "\n%s", txt[19]);	/* "from:" */
	nfprint(fp, Header.Author, 25);
	fprintf(fp, Space);
	fprintf(fp, "%s", txt[23]);	/* "number:" */
	nfprint(fp, Header.NumMsg, 7);

	/* Second line */
	fprintf(fp, "\n%s", txt[20]);	/* "to :" */
	nfprint(fp, Header.ForWhom, 25);
	fprintf(fp, Space);
	fprintf(fp, "%s", txt[24]);	/* "ref#" */
	nfprint(fp, Header.RefMsg, 7);

	fprintf(fp, "\n%s", txt[21]);	/* "subj." */
	nfprint(fp, Header.Subject, 25);
	fprintf(fp, Space);
	fprintf(fp, "%s", txt[25]);	/* "Conf : " */
	fprintf(fp, "%s", (char *) (ConfName[findCindex(readCnum((byte *) &(Header.BinConfN)))]));
	fprintf(fp, "\n%s", txt[22]);	/* "date :" */
	nfprint(fp, Header.MsgDate, 8);
	fprintf(fp, "%s", txt[26]);	/* "time:" */
	nfprint(fp, Header.MsgTime, 5);
	fprintf(fp, "\t[%ld/%ld]", Index.MsgNum + 1, TotMsg);	/* 0 based, print 1 based. */
	if (Header.Status == '+' || Header.Status == '*') {
		fprintf(fp, "\t\t");
		fprintf(fp, "  %s\n", txt[27]);	/* "PRIVATE MESSAGE" */
	}
	fprintf(fp, "\n\n");
}

/*
 * Reply to current message or enter a message
 * -------------------------------------------
 */

#define NulConf -1
#define unsave(x,y,z) ( x = y , y = z )

static void
Reply(const int mode, const char *line)
{
	int             i , lowcase ;
	unsigned int    j ;
	char           *intmp ;
	char            fname[MAXPATHS];
	char            tmp[MAXPATHS];
	char            dummy[MAXPATHS];
	int             reedit = FALSE;
	struct MsgHeaderType *Header;
	struct QmailRepType Qmail;
#ifdef USESYSTEM
	char			cmd[MAXPATHS]; /* non-unix needs this */
#else
	pid_t 			npid ; /* used by wait() */	
#endif	
	if (IsEmpty) {
		EmptyMsg();
		return;
	}
	SaveConf = CurConf;

	if (mode == ENTER) {
		if ((sscanf(line, "%s %s", dummy, tmp)) == 2) {
			if (Numeric(tmp)) {   /* find proper index for conference */
				i = atoi(tmp);
				i = findCindex(i);
			} else {/* not numeric */
				if (!strnicmp(tmp, "MAIN", 4))
					i = 0;
				else {   /* search for match in conf list */
					j = strlen(tmp);
					for (i = 0; i <= LastConf; i++)
						if (!strnicmp(tmp, ConfName[i], j))
							break;
				}
			}
			if (i < 0 || i > LastConf) {/* index not found in previous step */
				printf("\n%s\n", txt[28]);	/* Unknown Conference */
				unsave( CurConf, SaveConf, NulConf ) ;
				return;
			}
			CurConf = i;   /* update Current conf. for our purposes */
		}
		if (CurConf == PCONF_IDX || CurConf == RCONF_IDX ) {
			unsave( CurConf, SaveConf, NulConf ) ;
			return;
		}
	    if (CurConf != SaveConf)		
			printf("\n%s %d  %s %s\n", txt[29], ConfNumbers[CurConf],
		       ConfName[CurConf], txt[30]);
	}
	Header = (struct MsgHeaderType *) rbuf;
	if ( (SaveConf >= (RCONF_IDX)) && mode != ENTER ) /* get actual conf. from header */
		CurConf = findCindex(readCnum((byte *) & (Header->BinConfN)));

	if ( (intmp = tempnam( WorkPath, "re" ))!= NULL) /* Temporary file */
		strcpy ( fname, intmp );
	else 		
		sprintf(fname, "%s%c%s", WorkPath, SEP, "reply.tmp" );	

l_edit:			/* this is where we go if we need to re-edit msg. */

	ResetHeader(&Qmail);
	printf("\n");

/* get who the message is from */
morefr:
  	green();
	strcpy (dummy , UserName) ;
	luxptr = dummy ;
	if (mode == EDIT){
		scpy(dummy, (char *) (Header->Author), 25);
	}		
	if (strcmp( luxptr, User1Name))
		add_history(User1Name);
	lowcase = fido  ;	 /* True or False boolean valued */
	if (mode == REPLY ){
		lowcase = FALSE ;
		intmp = (char *) Header->ForWhom ; 
		for ( i=0 ; i < 25 ; i++)
			if ( intmp[i] >= 'a' && intmp[i] <= 'z' )
				lowcase = TRUE ;
	}
	if ( mode == ENTER )
		lowcase = !caps ;
	if (!lowcase ) /* PCBoard likes uppercase to/from field */
		strupr(luxptr);
    while ((intmp = readline( (ansi ? PRMTFR : SRMTFR) ,TRUE))==NULL) ;
	strcpy(tmp, intmp);
	add_history(intmp);
	free(intmp);
	luxptr = NULL  ;
	StripDel(tmp);
	if (strlen(tmp) > (unsigned) 25) {
			red();
			printf("%s", txt[34]);	/* "Entry too long ! 25 chars max */
			green();
			printf("\n");
			goto morefr;
	}
	if(tmp[0])
	 	str2mem((char *) Qmail.Author, tmp); /* Right name in the from field */
  	else {	
		blue();
		printf("%s.", txt[33]);	/* "message aborted" */
		green();
		printf("\n");
		unsave( CurConf, SaveConf, NulConf ) ;
		return;
	}
	
/* get who the message is being sent to */
moreto:
	green();
  	luxptr = dummy ;
	if(mode == EDIT)
		scpy(dummy, (char *) (Header->ForWhom), 25);
	else if ( mode != ENTER )
		scpy(dummy, (char *) (Header->Author), 25);
    else
		strcpy(dummy, "All");
	if ( !fido || ( caps && (mode == ENTER) )) /* PCBoard likes uppercase to/from field */
		strupr(luxptr);
    while (( intmp = readline( (ansi ? PRMTTO : SRMTTO) ,TRUE))==NULL) ;
	if ( !fido || ( caps && (mode == ENTER) )) /* PCBoard likes uppercase to/from field */
		strupr(intmp);
	strcpy(tmp, intmp);
	add_history(intmp);
	free(intmp);
	luxptr = NULL  ;
	StripDel(tmp);
	if (strlen(tmp) > (unsigned) 25) {
			red();
			printf("%s", txt[34]);	/* "Entry too long ! 25 chars max */
			green();
			printf("\n");
			goto moreto;
	}
	if (!stricmp(tmp, "N") || !tmp[0] ) {
			blue();
			printf("%s.", txt[33]);	/* "message aborted" */
			green();
			printf("\n");
			unsave( CurConf, SaveConf, NulConf ) ;
			return;
	}
	str2mem((char *) (Qmail.ForWhom), (char *) tmp);

/* get subject of message */
	green();
	if (mode != ENTER ) {
			SubjBuf[0] = 0 ;
			if( PCBLONG )
				Check4LongSubj();	
			if( !SubjBuf[0] ) 
				scpy( SubjBuf , (char *) (Header->Subject), 25);
			luxptr = SubjBuf ;
	}
	if( ansi )
    	while (( intmp = readline( (PCBLONG ? PRMTSL : PRMTSB), TRUE))==NULL) ;
	else
    	while (( intmp = readline( SRMTSB , TRUE))==NULL) ;
	strcpy(tmp, intmp); 
	add_history(intmp);
	free(intmp) ;
	luxptr = NULL; /* remember that this is global so re-initialize ! */ 
	StripDel(tmp);

  	if (!stricmp(tmp, "N") || !tmp[0] ) {
		blue();
		printf("%s.", txt[33]);	/* "message aborted" */
		green();
		printf("\n");
		unsave( CurConf, SaveConf, NulConf ) ;
		return;
	}
	if (strlen(tmp) > (unsigned) 60) /* length of long subject line */
		tmp[60] = 0 ;
	if (strlen(tmp) > (unsigned) 25){/* make sure that it fits header field */
		strcpy ( SubjBuf, tmp ); 
		tmp[25] = 0 ;
	}
	else
		SubjBuf[0] = 0 ; /* don't use long subject if length <= 25 */
	str2mem((char *) Qmail.Subject, (char *) tmp);

/* get security of message */		
moresec:
	green();
 	if ((mode != ENTER)&&( Header->Status == '+' || Header->Status == '*')) {
			luxptr =  "Receiver Only (private)" ;
			add_history("None (public)");
	} else {
			luxptr = "None (public)";
			add_history("Receiver Only (private)") ;
	}		
    while (( intmp = readline( (ansi ? PRMTSC : SRMTSC),TRUE))==NULL) ;
	strcpy(tmp, intmp);
	add_history(intmp);
	free(intmp);
	luxptr = NULL  ;
	StripDel(tmp); StripLSpace(tmp);
	if (tmp[0]) {
		strupr(tmp);
		if (strlen(tmp) > (unsigned) 25) {
			red();
			printf("%s", txt[35]);	/* "Too long! R=...etc..." */
			green();
			printf("\n");
			goto moresec;
		}
		if (tmp[0] == 'R'/* || !strnicmp(tmp,"priv", 4) */ ) 
			Qmail.Status = (char) 0x2A ;
		else	
			Qmail.Status = (char) 0x20 ;
  	} else {	
		blue();
		printf("%s.", txt[33]);	/* "message aborted" */
		green();
		printf("\n");
		unsave( CurConf, SaveConf, NulConf ) ;
		return;
	}
	
	sprintf(dummy, "%-7d", ConfNumbers[CurConf]);
	str2mem((char *) Qmail.ConfNum, dummy);	/* Msg goes to the current conference */

	if( mode == EDIT && SaveConf == RCONF_IDX )
		scpy(dummy, (char *) (Header->RefMsg), 7);
	else if ( mode  != ENTER )
		scpy(dummy, (char *) (Header->NumMsg), 7);
	
	str2mem((char *) Qmail.RefMsg, (mode == ENTER) ? "" : dummy );

	if (mode == REPLY && reedit == FALSE)
		QuoteMsg(fname);/* Quote original message... */
	else if (mode == EDIT && reedit == FALSE)
		StripTag(fname);

	white();
	printf("\n%s\n", txt[38]);/* "calling editor" */
	
#ifndef USESYSTEM   /* use fork() instead of system() is preferred */
	reperror = FALSE ;
	signal(SIGINT, jert );

    if( (Proc_ID = fork()) == 0 ){
		execlp( Editor, Editor, fname, NULL );
		exit(-1);
	}
	if( Proc_ID > 0 ){
		wmore1:
				npid = wait( &i ) ;
				if ( npid != Proc_ID ) goto wmore1;
				if ( reperror ) ATPABRTRP ;
	}
	else
		ATPABRTRP ;
#else
	sprintf(cmd,"%s %s", Editor, fname);
    system (cmd) ;
#endif
	
	ATPSETERM ; /* reset terminal attributes */

/* Here is where we ask if we want to save message */

  /* Here is where we ask if spelling needs checking */

if(speller[0]){
   	while (( intmp = readline("Check spelling [Y/n] ?",TRUE))==NULL ) ;
	StripDel(intmp);
	intmp[0] = tolower( intmp[0] );
    if( intmp[0] != 'n' ){
#ifndef USESYSTEM
    	if( (Proc_ID = fork()) == 0 ){
			execlp( speller, speller, fname, NULL );
			exit(-1);
		}
		if( Proc_ID > 0 ){
		wmore2:
				npid = wait( &i ) ;
				if ( npid != Proc_ID ) goto wmore2;
				if ( reperror ) ATPABRTRP ;
				CLSCRN ();
		}
		else
			ATPABRTRP ;
	}
	signal(SIGINT, SIG_DFL);
#else
		sprintf(cmd,"%s %s", speller, fname);
		system(cmd);
	}
#endif	
	ATPSETERM ; /* restore terminal parameters */
	free( intmp );
} /* end of spelling code */

	tmp[0] = (char) 0 ;
	for( ; ; ) {
		CLSCRN (); printf("\n");
		if (tmp[0] != 't') 
			strcpy( tmp, "tag ?");
		Tag( tmp );
		printf("Fido style tagline is %s.\n\n", fido ? "ON" : "OFF");
		printf("select:\n\t`Save' to save reply.\n");
		printf("\t`Edit' to re-edit reply.\n");
		printf("\t`Fido' to toggle tagline style and save reply.\n");
		printf("\t`Tag' allows you to change tagline (see ATP man page)\n");
		printf("\t`Abort' to cancel reply.\n\n");
		while (( intmp = readline ("Choose: Save, Edit, Fido, Tag, Abort  [Save] ? ",TRUE))==NULL) ;
		strcpy (tmp,intmp); free(intmp); 
		StripDel(tmp); StripLSpace(tmp);
		tmp[0] = tolower(tmp[0]);
		if( !tmp[0] || tmp[0] == 's' || tmp[0] == 'f' || tmp[0] == 'a' || tmp[0] == 'e' )
			break ;    
	}  							/* end of for(;;) loop */
	if (tmp[0] == 'e') {
		reedit = TRUE;
		goto l_edit;			/* re-edit message */
	}						
	if (tmp[0] == 'a') {
		printf("\n\n%s\n", txt[33]); /* abort message */
		unlink(fname);
		unsave( CurConf, SaveConf, NulConf ) ;
		return;
	}
	if (tmp[0] == 'f') {
			togltag();
	}
	if (!fido)		/* adjust header for fido or not */
		for (i = 0; i < 50; i++)
			Qmail.ForWhom[i] = toupper(Qmail.ForWhom[i]);

	if ( AddReply(fname, (struct QmailRepType *) &(Qmail.Status)) ){ 
		if (autotag)
			ChooseTag();
		if (SaveConf==RCONF_IDX){
			CurConf = RCONF_IDX ;
			if (mode == EDIT)
				ReadNext(NUKE);
			TotMsg++;
			sprintf(dummy,"%ld",TotMsg);
			GoToNum (dummy);
		}
	}
#ifndef USESYSTEM
abrtreps:
	reperror = FALSE ;
	signal(SIGINT, SIG_DFL);
#endif	
	unsave( CurConf, SaveConf, NulConf ) ;
	return ;
}

/*
 * Add the reply to a Qmail reply.msg file.
 */
static int 
AddReply(const char *fname, struct QmailRepType * Qmail)
{
	if( ! OpenRepFile(ADDREP) )
		return FALSE ;
	if (KodeMessage(fname, Qmail))
		return FALSE ;
	ReplyExist = TRUE ;
	return TRUE ;
}




/*
 * LIST CONF : Prints conferences numbers,names, and status.
 */

static void
ListConf(void)
{

#define pers -2
#define reps -1

 	unsigned		line ;
	int             i=0 ;
	char            tmp[MAXPATHS];

	if (IsEmpty) {
		EmptyMsg();
		return;
	}
	CLSCRN ();
	magenta();
	high();
	printf("\r%s %s\n", txt[78], BoardName);	/* "Liste des conf. sur" */
	clear();
	red();
	printf("\r");
	for (i = 0; i < (int) (strlen(txt[78]) + strlen(BoardName) + 1); i++)
		putchar('-');
	putchar('\n');

	for (i = pers, line = 0; i < RCONF_IDX ; i++) {
		line++;
		if (line > ScrnLines - 5) {
			line = 0;
			printf("\n");
			if (!more(YES))
				break;
			cyan();
		}
		if (i ==  pers ) {	/* List personal conference first */
			if (pmail)
				blink();
			i = PCONF_IDX ;
		}
		if (i == reps )     /* List reply conference next */
			i = RCONF_IDX ;	

		sprintf(tmp, "%s%s%c%d.cnf", HomePath, CurBoard, SEP, ConfNumbers[i]);
		red();
		high();
		printf("\n\t\t%4d ", ConfNumbers[i]);
		clear();
		blue();
		printf("......... ");
		magenta();
		if ( (i == PCONF_IDX)  && pmail)
			blink();
		high();
		printf("%-15s ", ConfName[i]);
		clear();
		blue();
		printf("......... ");
		if ( (i == PCONF_IDX)  && pmail)
			blink();
		green();	
		high();
		if (access(tmp, F_OK )) {
			printf("%s", txt[79]);	/* "Inactive" */
		} else {
			magenta();
			printf("%s", txt[80]);	/* "active" */
		}
		if( i == PCONF_IDX ){
			clear();
			i = pers  ;
		}
		else if (i == RCONF_IDX ) 
			i = reps  ;
	}
	clear();
	printf("\n\n");
#undef reps
#undef pers
}


/*
 * Goes to the msg number represented by the string. and print it.
 * ( Internal count, not BBS numbers ! )
 */

static void
GoToNum(const char *str){
	if( SeekNum( str ))
		Display(0, NULL, 0);
}

/*
 * Seek to specific message number
 *
 */

int
SeekNum(const char *str)
{
	long int        nb;
	size_t			nrecs ; /* number of records to read */

	if (IsEmpty) {
		EmptyMsg();
		return(0);
	}
	nb = atol(str);
	nb = nb - 1 ;
	if (nb < 0 || nb >= TotMsg) {
		red();
		high();
		printf("%s\n", txt[81]);	/* "Number out of range ! " */
		printf("%s ", txt[82]);	/* "Valid msgs are" */
		magenta();
		printf("1 ");
		red();
		printf("%s ", txt[83]);	/* "to" */
		magenta();
		printf("%ld\n", TotMsg);
		return(0);
	}
    if (fseek(fidx, ( nb * (long) sizeof(struct MyIndex)), SEEK_SET)) {
		printf("%s !\n", txt[16]);	/* "seek error" */
		return(0);
    }
    if (fread(&Index.LastRead, sizeof(struct MyIndex), 1, fidx) != (size_t) 1 ) {
		printf("%s\n", txt[17]);	/* "End of messages " */
		return(0);
	}
	rewind(fmsg);
    if (fseek(fmsg, Index.Offset, SEEK_SET)) {
        printf("%s !\n", txt[16]);
        return(0);
	}
    nrecs = ( (Index.Size / 128 ) + 1 ) ; /* same as (Index.Size+128)/128) */
    if ( nrecs > ( RbufSize / 128 ) ) 
     	if ( !reup( (unsigned long) (nrecs+1)*128L ))
			return(0) ;
	if ((fread((char *) rbuf, 128, nrecs , fmsg)) != nrecs ) {
  		printf("%s ? \n", txt[18]);	/* "read error" */
		return(0);
	}
	rbuf[ (Index.Size)+128 ] = '\0' ; /* terminate buffer like a string */
	FirstDone = TRUE ; /* signal that there is a full buffer */
	return(1); /* good seek */

}


/*
 * DISPLAY : Prints the current message,stored in memory.
 */

void
Display(const int mode, struct fentry *bptr, int blen)
{
	
	unsigned long   i = 0 ;
	int             QuotedColor, vidon = FALSE ;
	int             line = 0, count = 0 , bufct = 0 , spc_ct = 0 ;
	byte           *ptr, *pt;
   	byte           *linbuf ; 

	if (IsEmpty) {
		EmptyMsg();
		return;
	}
	if( mode != SCAN )
		CLSCRN ();
	SubjBuf[0] = 0 ;
	if( PCBLONG ) 
		Check4LongSubj() ;
	PutHeader(SCAN, &bptr, blen);
	if( mode == SCAN ) return  ;
	if (( linbuf = (byte *) malloc(800)) == NULL ){ /* local line buffer */
		printf("malloc() failed in read.c module Display()\n\n");
		return;
	}
	cyan();
    ptr =  rbuf + Index.Size + 127  ;  /* strip off trailing junk */
	while( *ptr == '\0' || *ptr == '\040' || *ptr == '\n' ) {
		*ptr = '\0' ;
	     ptr-- ;
	}
	*(++ptr) = '\n' ;
	
	ptr =  (rbuf + sizeof(struct MsgHeaderType));
	i = 0;
	if( PCBLONG && SubjBuf[0] ){
		while( *ptr++ != 0x0a ) i++ ; /* skip subject line */
	}
	QuotedColor = 0;
	line = 5 ; /* offset by six for header */
	pt = linbuf ;
	*pt = 0;

	while (i < Index.Size) {
		if( *ptr == 0 || ( silent && *ptr == 7 ) ) {
			i++, ptr++;
			continue ;
		}
		if ( count == ScrnCols ){ /* Security for long lines */
			line++ ;
		    count = 0 ;
			if( *ptr == '\n' )
				ptr++, i++ ; /* skip it, it'll wrap anyway */
		}
		if( bufct > 770 ) *ptr = '\n' ; /* blow long line saftey valve */
		/* DTS added the following 2 if's for reversing found strings */
		
		if( bptr != NULL && blen > 0 ) /* re-synch pointers */
			while( bptr != NULL && (((char *) ptr) > (bptr->findpt + blen)))
			{
				bptr = bptr->fnext ;   
			}    
		if( bptr != NULL && blen > 0 ){
			if ( ptr == (byte *) bptr->findpt )	/* Beginning of the found string */
				if ( ansi )  /* highlight found string */
				{
					*pt++ = 27;	/* Escape */
					*pt++ = '['; *pt++ = '7'; *pt++ = 'm'; bufct += 4 ;
					vidon = TRUE ;
				} else { /* non-ansi */
					*pt++ = '}', *pt++ = '*' ; bufct += 2 ;
				}
				
			if ( ptr == (byte *) (bptr->findpt + blen) )/* End of the found string */
				if ( ansi )  /* turn off highlighting */
				{
					*pt++ = 27;	/* Escape */
					*pt++ = '['; 
#ifdef VT220
 				/* If NOT an xterm, use vt220 stuff */
					if ( stricmp(termtype,"xterm") )
					{
						*pt++ = '2' ; *pt++ = '7' ; bufct += 2 ; 
					}
#endif
					*pt++ = 'm'; bufct += 3 ;
					bptr = bptr->fnext ;
					vidon = FALSE ;
				} else {   /* non-ansi */
					*pt++ = '*', *pt++ = '{', bufct += 2  ;
				}
			}

		if (*ptr == '\n') {    /* Display a total line          */
			count = bufct = 0;
			*pt = 0;
			line++;
			pt = linbuf ;
			if (IsQuoted('>', pt) ) {	/* Process colors on quoted line */
				while (*pt != '>')
					putchar(*pt++);
				QuotedColor = 1;
				red();	/* Quote char in red... */
				putchar(*pt++);
				green();	/* Quoted line in green.. */
				puts((char *) pt);
				cyan();
			} else {
				if (QuotedColor) {
					cyan();
					QuotedColor = 0;
				}
				puts((char *) linbuf);
			}
			pt = linbuf ;
		} else if ( *ptr == '\t' ) { /* expand tabs */
			/* calculate number of spaces to pad */
			spc_ct = 8 - ( count % 8 ) ;
			/* do housekeeping, track various counts */
			count += spc_ct ; bufct += spc_ct ;
			if( count > ScrnCols ) {
				count -= ScrnCols ;
				line++ ;
			}
			/* fill output buffer with expanded tab */
			while ( spc_ct ){
				*pt = (byte) 0x20 ;
				pt++ , spc_ct-- ;
			}
		} else if (*ptr) {	/* Non 0 chars */
			if(charset != CHRDOS ){
				if ( graphics && vtspecial(*ptr) ){ /* use vt100 graphics codes */
	       				*pt++ =  '\016';
		   				*pt++ =  codevt[ (unsigned) (*ptr) ]  ;
	       				*pt   =  '\017'; bufct+=2 ;
				}
				else if (charset == ISOLAT1 ) 
					*pt = codelu[   (unsigned) (*ptr) ]; /* use iso lookup table */
   		        else  /* use 7 bit character set */
					*pt = code7bit[ (unsigned) (*ptr) ]; 
			} 
			else
				*pt = *ptr ;
			pt++;
			count++;	/* Security for line length ... */
			bufct++;
		}
		i++;
		ptr++;
		if( *ptr ==  0 ) continue ;
		if (line > (ScrnLines - 3) ) {
			line = 0;
         	if (mode == KILL || mode == NUKE || mode == PRIVATE || i >= Index.Size )
				break;	
			if (!more(YES)){
				break;
			}
			cyan();
		}
	} /* end while */
	free(linbuf);
	FirstDone = TRUE;
	if( line && line < (ScrnLines - 2) )
		printf("\n"); 
#ifdef VT220
	if ( vidon && stricmp(termtype,"xterm") )
	{
		printf("\033[27m"); 
	}
	else
#endif
	if( vidon ) printf("\033[m");
	fflush(stdout); /* fail safe cancel of highlighting */
} 

/*
 * WelcomeMsg : Displays the welcome file.
 */

static void
WelcomeMsg(const char *mfile)
{
	char            tmp[MAXPATHS];

	if (IsEmpty) {
		EmptyMsg();
		return ;	
	}
	sprintf(tmp, "%s%s%c%s", HomePath, CurBoard, SEP, mfile );
	if ( *mfile != 0 && !access(tmp, R_OK ) ) {
		sprintf(tmp, "%s%s", HomePath, CurBoard);
		view(tmp, mfile );
	} else {
		printf("%s %s\n", txt[67], tmp);	/* "No file" */
	}
}

/*
 * GETBBS : Called by main() with argv[1]. Looks for a new QWK packet, if
 * older than message base, just  loads the base.
 */

static void
GetBbs(const char *name)
{
	char			*tpt;
	char            tmp[MAXPATHS];
	char            packet[MAXPATHS];
	char            base[MAXPATHS];
	struct stat     Oldst;
	struct stat     Newst;

#ifdef ATPDBG
	Oldst.st_mtime = Oldst.st_ctime = Oldst.st_atime = 0L ;
	Newst.st_mtime = Newst.st_ctime = Newst.st_atime = 0L ;
#endif
	strcpy(tmp, name);
	if (strstr(name, ".qw") == NULL)
		strcat(tmp, ".qwk");
			
	sprintf(packet, "%s%s", MailPath, tmp);

	if (access(packet, R_OK )) {/* No new mail found */
		printf("%s\n", txt[31]);	/* "no new mail" */
		Read(name);
		return;
	}
	strcpy( packet, tmp);	
	if( (tpt = strrchr( packet, '.' )) != NULL )
		*tpt = 0 ;

	sprintf(base, "%s%s%c%s", HomePath, packet, SEP, CNTRL_FILE);
	if (access(base, F_OK )) {
		printf("\n%s. ", txt[45]);	/* New BBS in this base. */
		sprintf(tmp, "load %s", name);
		Load(tmp);
		return;
	}
	sprintf(packet, "%s%s", MailPath, tmp);
	if( stat(packet, &Newst) != 0 ) {
		printf("GetBbs() Can't stat packet\n");
		sleep(3);
	}
	if( stat(base, &Oldst) != 0 ){
		printf("GetBbs() Can't stat base\n");
		sleep(3);
	}
#ifdef ATPDBG
	assert( Oldst.st_mtime > 0L ) ;
	assert( Newst.st_mtime > 0L ) ;
#endif	
	if (Newst.st_mtime <= Oldst.st_mtime) {
		printf("\n");
		blue();
		high();
		printf("%s. %s.", txt[46], txt[47]); /* mail older than last update */
		green();
		fflush(stdout);
		printf("\n");
		sprintf(tmp, "Read %s", name);
		Read(tmp);
		return;
	}
	sprintf(tmp, "Load %s", name);
	Load(tmp); 
}


static void
Purge(void)
{
	int             i; 
	long            c_len, i_len, trunc_siz, num_msgs = 0L, avg_siz = 0L ;
	char            tmp[80];
	char            cnf[MAXPATHS];
	char            idx[MAXPATHS];
	char			*ntmp ;
	struct stat     st ;
	
	if (IsEmpty) {
		EmptyMsg();
		return;
	}
	if (ConfActive[CurConf])
		UpdateConf(UPDATE);	/* Save current conf pointer */
	trunc_siz = TruncNum  ;
	magenta();
	high();			/* Selective erasing of conferences. */
	printf("\n%s\n", txt[102]);	/* Effacement sélectif des conférences */
	clear();
	red();
	printf("----------------------------------------\n");

	for (i = 0; i <= LastConf; i++) {
		sprintf(cnf, "%s%s%c%d.cnf", HomePath, CurBoard, SEP, ConfNumbers[i]);
		sprintf(idx, "%s%s%c%d.idx", HomePath, CurBoard, SEP, ConfNumbers[i]);

		if (stat(cnf, &st) == -1) 
			continue;	/* No such file */
		else 
			c_len = st.st_size;

		if (stat(idx, &st) == -1) 
			continue;	/* No such file */
		else 
			i_len = st.st_size;
		num_msgs = i_len / sizeof (struct MyIndex);
		avg_siz  = (((c_len * 10) / num_msgs) + 5) / 10;
		/* here we could attempt to rebuild index if num_msgs == 0 */
		/* not implemented yet */

/* onemore: */
		green();
		high();
		printf("\nConf. %d [ ", ConfNumbers[i]);
		yellow();
		printf("%s", ConfName[i]);
		green();
		printf(" ] takes ");
		yellow();
		printf("%ld Kbytes\n", (c_len + 512) >> 10);
		green();
	    {
		printf ("\n     Index length = %ld bytes\n", i_len );
		printf ("     Data length = %ld bytes\n", c_len);
		printf ("     Number of messages = %ld \n", num_msgs);
		printf ("     Average size = %ld bytes\n\n", avg_siz);
	    }
		printf(" (D)elete (C)lean (T)runcate (N)ext (S)top : ");

		fget(tmp, 5, stdin);
		strupr(tmp);

		switch ((int) tmp[0]) {
		case 'N':
			break;

		case 'S':
			if (!ConfActive[CurConf])
				AutoJoin();
			return;

		case 'D':
		case 'C':
		case 'T':
			if (i == CurConf) {
				Index.LastRead = 0L;
				Index.MsgNum = 0L;
				TotMsg = 0L;
				if (FilesOpen) {
					fclose(fidx);
					fclose(fmsg);
					FilesOpen = FALSE;
					FirstDone = FALSE;
				}
			}
			if(  tmp[0] == 'D' ) { 
				ConfActive[i] = FALSE;
				if (unlink(cnf) == ERROR ) {
					printf("Unable to remove file %s\n", cnf);
					ConfActive[i] = TRUE ; 
				} else if (unlink(idx) == ERROR) {
					printf("Unable to remove file %s\n", idx);
				} ;
			 	
				if (i == findCindex(PERS_CONF))
					pmail = FALSE;
				blue();
				printf("Conference %d is now empty.", ConfNumbers[i]);
				green();
				printf("\n\n");
				ActvCnt--;	/* one less active conference */
			} else {
				if( tmp[0] == 'T' ){
					sprintf( tmp, "%ld", trunc_siz);
					luxptr = tmp ;		
					for( ; ; ) {
						ntmp = readline("enter truncation count: ", TRUE); 
						if( Numeric(ntmp) ) 
							break ;
						free(ntmp); 
					}
					trunc_siz = atol( ntmp );
					free( ntmp );
					printf("--\n");
				}
				clip( cnf, tmp[0], trunc_siz ); /* purge and/or truncate conference */ 
				if ( (stat(cnf, &st) == -1) || st.st_size == 0 ) { 
					ConfActive[i] = FALSE;
					ActvCnt-- ;
					if (i == findCindex(PERS_CONF))
						pmail = FALSE;
				} else if (i == CurConf && GetConf(i) != OK ){  /* reopen conference */
					printf("Error in purge() can't reopen conference\n");
				}
			}
			break;

		default:
			break;
		}
	}
	ActvConf();  /* update array of active conferences */
	ReplyExist = ConfActive[RCONF_IDX] ;
	if (!ConfActive[CurConf])
		AutoJoin();
}

/*
 * scan through the message headers 
 */

static void 
scruter(int mode)
{
	int             i, m;
	long            msgnumb ;
	char            seeker[100] ;

	msgnumb = Index.MsgNum ;
	if( mode == SCAN )
		m = ScrnLines / 6;
	else
		m = ScrnLines - 1 ;	
	do {
		CLSCRN ();
		for (i = 0; i < m; i++)
			if (!ReadNext(mode))
				goto lscrut ; /* break out of nested loops */
			else
				msgnumb = Index.MsgNum ; /* save current message number */ 
	} while (more(YES));
lscrut:
	if( msgnumb >= 0L ){ /* fill msg buffer from current message */
		sprintf( seeker, "%ld", msgnumb ? msgnumb : msgnumb + 1L );
		if( SeekNum( seeker ) && msgnumb == 0L ) /* fill message buffer with last message */
			fseek( fidx, 0L, SEEK_SET );	
	}
	return ;
}

/*
 * Search array for next active conference, wrapping around 
 * to start if need be.
 */

static int
FindActive(const int curcon)
{
	int             i;
	for (i = curcon + 1; i <= LastConf; i++) {
		if (ConfActive[i])
			return (i);
	}
	for (i = 0; i <= curcon; i++) {
		if (ConfActive[i])
			return (i);
	}
	return (-1);
}

static void 
showterms(void){
	int i = 0;	
	while( terms[i] != NULL && i < 50 ){
		printf("%s\n",terms[i]) ;
		i++;
	}

}

#define SUBLEN 72
static void
Check4LongSubj(void)
{
		char *tptr, *sptr, tmpc ;
		int ct = 0 ;
		
/* check first line of message for @SUBJECT (ignore white space) */

		tptr = (char *) (rbuf + 128) ;
		while ( ct++ < SUBLEN ) 
		{
				if( *tptr == '*' || *tptr == (char) 9 || *tptr == 0x20 || ((byte)*tptr) == 0xff ) {
					tptr++ ; 
					continue ; /* strip leading white space */
				}
				else if ( *tptr != '@' )
					break ;
				else
				{
					tptr++ ;
					SubjBuf[0] = 0 ;		
					if ( !strncmp( (char *) tptr, "SUBJECT:", (size_t) 8 )){ 
						sptr = tptr + 8 ;
						if ( sptr[60] == 'N' && sptr[61] == '\n' ) {
							memcpy( SubjBuf, sptr, 60 );
						} else {
							while( *tptr != 0x0a && ct++ < SUBLEN ) tptr++; 
							if( sptr[61] == 'N' ){ 
								sptr[62] = 0 ;
								ShiftLeft( tptr, 1) ;
								strcpy( SubjBuf, sptr) ; 
								sptr[61] = sptr[62] = '\n' ;
							} else {
								tmpc = *tptr ;
								*tptr = 0 ;
								strcpy( SubjBuf, sptr ) ;
								*tptr = tmpc ;	
							}
						}
						SubjBuf[60] = '\0' ;
						sptr = SubjBuf ;
						while( *sptr ) sptr++ ;
						sptr-- ;
						while( *sptr == 0x20 ) *sptr-- = 0 ;
					}
				}
				break ;
		}
}

#ifdef LISTDIR 
#include "editline/editline.h"
extern char *Screen ;
extern SIZE_T  ScreenSize ;

static void
list_dir( char *path )
{
    char	**av;
    int		ac = 5 ;

    ac = rl_list_possib((char *)path, (char ***)&av);
    if (ac) {
    ScreenSize = SCREEN_INC;
    Screen = NEW(char, ScreenSize);
	columns(ac, av);
	TTYflush();
	DISPOSE(Screen);
	sleep(3);
	while (--ac >= 0)
	    free(av[ac]);
	free(av);
    }
}
#endif
