#ifndef lint
static char *SCCSid = "%W%	(NCSA)	%G%";
#endif
/*#define NEW_STUFF 	/* BYU - changed to "MacTCPdriver" for use in Make file. */
#define NEWSLC 
/*
*    maclook.c
*    User interface code for NCSA Telnet for the Macintosh
*	 by Gaige B. Paulsen
****************************************************************************
*                                                                          *
*      Uses	:															   *
*      TCP/IP kernel for NCSA Telnet                                       *
*      by Tim Krauskopf                                                    *
*	   with Macintosh code by Gaige B. Paulsen						 	   *
*                                                                          *
*      National Center for Supercomputing Applications                     *
*      152 Computing Applications Building                                 *
*      605 E. Springfield Ave.                                             *
*      Champaign, IL  61820                                                *
*                                                                          *
*                                                                          *
****************************************************************************
*
*   User interface for basic telnet with background file transfer
*   capabilities via FTP calls from host.
*
*	This, the Macintosh version also gives each session its own window,
*	provides advanced keyboard translation, Tek emulation, printing/copying
*	of text and graphics and the pasting of text into the active session.
*
*		Requires:
*	config.c- Aux. file for handling telnet documents
*	menu.c	- Aux. file for handling menu calls
*	event.c	- Aux. file for handling events
*	switch.c- Aux. file for handling swithcher  (the J word is in Event and here )
*/

/*
 *	Files for inclusion.
 */
#include	<stdio.h>
#include <string.h>
#include <stdlib.h>

#include	<Appletalk.h>
#include	<Controls.h>
#include	<CType.h>
#include	<Desk.h>
#include 	<Devices.h>
#include	<Dialogs.h>
#include	<Events.h>
#include	<Fonts.h>
#include	<FCntl.h>
#include	<Memory.h>
#include	<Menus.h>
#include	<Packages.h>
#include	<Files.h>
#include	<OSUtils.h>
#include	<Quickdraw.h>
#include	<Resources.h>
#include	<SegLoad.h>
#include 	<Strings.h>
#include	<TextEdit.h>
#include	<ToolUtils.h>
#include	<Types.h>
#include	<Windows.h>
#include	<OSEvents.h>
#include 	<Strings.h>

#include	"wind.h"
#include	"configrec.h"
#include	"hostform.h"
#include "event.h"
#include "croft.h"
#include "macutil.h"
#include "atalk.h"
#include "maclook.h"
#define PREFMASTER
#include	"prefs.h"

#include "whatami.h"
#include "rsmac.h"
#include "confile.h"
#include	"vsdata.h"
#include	"vskeys.h"
#include "vsinterf.h"
#include "vgtek.h"
#include "tekrgmac.h"
#include "rr.h"
#include "vr.h"
#include "vrrgmac.h" 
#include "user.h"
#include "util.h"
#include "netevent.h"
#include "config.h"
#include "environ.h"
#include "switch.h"
#include "menu.h"
#include "ser.h"				/* BYU 2.4.15 MPW */
#include "slip.h"				/* BYU 2.4.15 MPW */
#if 0							/* BYU 2.4.7 */
#include <MacTCPCommonTypes.h>
#include <AddressXlation.h>
#endif							/* BYU 2.4.7 */
#include "dnr.c"

#ifdef MPW
#include "mpw.h"
#endif MPW

/*
 *	Operation Governing Defines:
 */

#define	MaxSess		20		/* The maximum number of sessions */
#define	MaxGraph	30		/* Maximum number of graphics */


/*
 *	Emulation type defines
 */

#define VTEKTYPE 1
#define TEKTYPE 2
#define DUMBTYPE 3
#define RASTYPE 4


	#define SLC 3 
		#define SLC_NOSUPPORT	0
		#define SLC_CANTCHANGE	1
		#define SLC_VALUE		2
		#define SLC_DEFAULT		3
		#define SLC_LEVELBITS	3
		#define SLC_AWK			128
		#define SLC_SYNCH		1
		#define SLC_BRK			2
		#define SLC_IP			3
		#define SLC_AO			4
		#define SLC_AYT			5
		#define SLC_EOR			6
		#define SLC_ABORT		7
		#define SLC_EOF			8
		#define SLC_SUSP		9
		#define SLC_EC			10
		#define SLC_EL   		11
		#define SLC_EW   		12
		#define SLC_RP			13
		#define SLC_LNEXT		14
		#define SLC_XON			15
		#define SLC_XOFF		16
		#define SLC_FORW1		17
		#define SLC_FORW2		18

/*
 *	Service type defines
 */

/*
 *	Font Height and width constants
 */
#define Fheight 11
#define Fwidth 6
#define Fright 480

#define DefFONT 4
#define DefSIZE 9
/*
 *	Window constraints
 */

#define MAXWINDOWHEIGHT 18+Fheight*24
#define MAXWINDOWWIDTH  17+Fwidth*80+3

/*
 *	Resource Defines
 */


#define	FirstDLOG	1023
#define	AboutDLOG	256
#define	ConnAttDLOG	258
#define	ConnFalDLOG	303
#define BadMaskDLOG	330
#define BadIPDLOG	331

#define	GetParmDLOG	300
#define GetDefDLOG 1300     /* Config net for MacTCP version */
#define	GetParmIP	5		/* The IP number TE */
#define GetParmHOST	10		/* The Default Host TE */
#define	GetParmMASK	7		/* The Subnet Mask TE */
#define	GetParmStat	3		/* The Static IP RB */
#define	GetParmKDyn	4		/* The Dynamic IP RB */
#define	GetParmUseM	6		/* The Use Mask CB */
#define GetCaptureName 12	/* NCSA 2.5: Name of capture file */

#define	BadHostDLOG	301
#define	BadHostQuit	3		/* The Quit Button */
#define	BadHostCont	2		/* The Continue Button */


#define RESOLVERERROR 128
#define	GetDestDLOG	257
#define	GDdest		3		/* The Destination filed in GetDest dialog */

#define	XferCURS	290
#define	GINCURS		257
#define	DbugCURS	268
#define	POSCURS		256

#define	IPnumSTR	256
#define	HostSTR		257
#define	MaskSTR		258
#define FileSTR		1024		/* NCSA 2.5: name of capture file */
#define	FTPlogWIND	257

/*
 * Event Auxilliary Defines
 */



/*
 * ASCII character set defines
 */

#define ESC			0x1b	/* the escape character */
#define	BS			0x08	/* the backspace character */
#define DEL			0x7f	/* the delete character */
#define CR			0x0d	/* the carriage return character */
#define LF			0x0a	/* the line feed character */



#define EDcopy		4		/* Edit Menu: Copy */
#define EDpaste		5		/* Edit Menu: Paste */
#define EDcopyt		7		/* Edit Menu: Copy Table */
#define Edit	2
#define	Emul		3		/*	Emulation Menu's position */

#define GetStrRes(x)	(Str255 **)GetResource('STR ',(x));	/* NCSA 2.5 */


#ifdef OPTSDEBUG
char *telstates[]={
    "SE",
    "NOP",
    "DM",
    "BREAK",
    "IP",
    "ABORT",
    "AYT",
    "ERASE CHAR",
    "ERASE LINE",
    "GO AHEAD",
    "SB",
	"WILL",
	"WONT",
	"DO",
	"DONT"
};

char *teloptions[256]={
	"Binary",				/* 0 */
	"Echo",
	"Reconnection",
	"Supress Go Ahead",
	"Message Size Negotiation",
	"Status",				/* 5 */
	"Timing Mark",
	"Remote Controlled Trans and Echo",
	"Output Line Width",
	"Output Page Size",
	"Output Carriage-Return Disposition",	/* 10 */
	"Output Horizontal Tab Stops",
	"Output Horizontal Tab Disposition",
	"Output Formfeed Disposition",
	"Output Vertical Tabstops",
	"Output Vertical Tab Disposition",		/* 15 */
	"Output Linefeed Disposition",
	"Extended ASCII",
	"Logout",
	"Byte Macro",
	"Data Entry Terminal",					/* 20 */
	"SUPDUP",
	"SUPDUP Output",
	"Send Location",
	"Terminal Type",
	"End of Record",						/* 25 */
	"TACACS User Identification",
	"Output Marking",
	"Terminal Location Number",
	"3270 Regime",
	"X.3 PAD",								/* 30 */
	"Negotiate About Window Size",
	"Terminal Speed",
	"Toggle Flow Control",
	"Linemode",
	"X Display Location",					/* 35 */
	"36","37","38","39",
	"40","41","42","43","44","45","46","47","48","49",
	"50","51","52","53","54","55","56","57","58","59",
	"60","61","62","63","64","65","66","67","68","69",
	"70","71","72","73","74","75","76","77","78","79",
	"80","81","82","83","84","85","86","87","88","89",
	"90","91","92","93","94","95","96","97","98","99",
	"100","101","102","103","104","105","106","107","108","109",
	"110","111","112","113","114","115","116","117","118","119",
	"120","121","122","123","124","125","126","127","128","129",
	"130","131","132","133","134","135","136","137","138","139",
	"140","141","142","143","144","145","146","147","148","149",
	"150","151","152","153","154","155","156","157","158","159",
	"160","161","162","163","164","165","166","167","168","169",
	"170","171","172","173","174","175","176","177","178","179",
	"180","181","182","183","184","185","186","187","188","189",
	"190","191","192","193","194","195","196","197","198","199",
	"200","201","202","203","204","205","206","207","208","209",
	"210","211","212","213","214","215","216","217","218","219",
	"220","221","222","223","224","225","226","227","228","229",
	"230","231","232","233","234","235","236","237","238","239",
	"240","241","242","243","244","245","246","247","248","249",
	"250","251","252","253","254",
	"Extended Options List"		/* 255 */
};

char *LMoptions[]={
	"None",
	"SYNCH",
	"BREAK",
	"IP",
	"ABORT OUTPUT",
	"AYT",
	"EOR",
	"ABORT",
	"EOF",
	"SUSP",
	"EC",
	"EL",
	"EW",
	"RP",
	"LNEXT",
	"XON",
	"XOFF",
	"FORW1",
	"FORW2",
	"MCL",
	"MCR",
	"MCWL",
	"MCWR",
	"MCBOL",
	"MCEOL",
	"INSRT",
	"OVER",
	"ECR",
	"EWR",
	"EBOL",
	"EEOL"
};

char *LMflags[]={
	"NOSUPPORT",
	"CANTCHANGE",
	"VALUE",
	"DEFAULT"
};
#endif



#define MAXVG 20 /* maximum number of VG windows */

#ifdef SMTP			/* External Var for SMTP */
extern int smnum;
#endif

/*
 *	Type declarations for Globals
 */
Cursor
	*gincurs,		/* Cursor when in graphics input mode */
	*xfercurs,		/* Cursor when in transfer mode */
	*normcurs,		/* Cursor for non-transfer normal mode */
	*textcurs,		/* Cursor for text mode */
	*poscurs,		/* Cursor for positioning mode */
	*watchcurs,		/* Cursor for time-taking operations */
	*graphcurs;		/* Cursor for graphics windows */
Rect
	screenRect,		/* The whole screen */
	dragRect,		/* Where it is legal to drag ourselves */
	SizRect;		/* How big/small our windows can be */
Str255
	*defaultd,		/* Default host name */
	*dvs;			/* Default Volume/directory specification */

WindRec
	*screens,		/* Window Records (VS) for :	Current Sessions */
	ftplog,			/*								FTP Log			 */
	console;		/*								console Window   */

int
	SettingsFile=-1,/* The Resource Reference Number of the Settings file */
	neton	= 0,	/* Has the network been set up right? */
	ginon   = 0,	/* True if we are in GIN mode */
	xferon  = 0,	/* Is a transfer in progress */
	dynamic = 0,	/* not dynamic by default.... */
	userlevel=0,	/* The user privelege level... 0 allows reconfig on fly */
	numwindows=0,	/* Number of active window structures (note: not windows ) */
	scrn=0,			/* Currently active screen */
	graphs=0,		/* How many detached graphs do we have */
	oldgraph[MaxGraph],	/* Storage for old Graph numbers */
	debug=1,			/* Flag for debugging 1=active */
	done=0,			/* Are we done yet 0=not */
	net_okay,		/* BYU serial */
	KIP=0,			/* is KIP gateway present */
	ipn[4];			/* The real IP number */

long
	defmask,		/* The network mask as per defaults contingent on the IP */
	mynetmask;		/* The network mask as per user config */

unsigned char
	TermType[32],	/* Termtype to send */
	myipnum[4];		/* My IP number (internal) */
AddrBlock
	KIPserver;		/* KIP gateway address */

int *DirTree;
char *mungbuf;
short				/* BYU 2.4.7 - must match "extern" declaration in "menu.c". */
	cmask,			/* Are we using a custom mask */
	err;			/* Error variable */

OSErr io;

extern OSErr 					/* BYU 2.4.7 */
	OpenResolver(fileName);		/* BYU 2.4.7 */

extern int			/* BYU */
	RGMalloc();		/* BYU */

extern void 		/* BYU */
	init_mb_files(),/* BYU */
	AdjustMenus(),	/* BYU */
	VGalloc();		/* BYU */

extern MenuHandle	myMenus[];
#define COnext		1		/* Connection Menu: Next Session... */
#define Conn		5		/*	Connection Menu's position */

extern VSscrn *VSIw;

void DoTheMenuChecks();
/*
 *	Type declarations for functions
 */

int
	getWDnum();
char
	*strncpy(),
	*neterrstring();
Str255
	*getWDname();
pascal void
	VersionNumber(),
	OutlineItem(),
	ScrollProc();
pascal int
	modalProc();

GrafPtr
	RSgetwindow();

extern short 			/* BYU 2.4.15 */
	slip_connection;	/* BYU 2.4.15 */

extern int
	whichMenus,		/* Are we commanded or not ?*/
	HFS,			/* True if HFS is active/ false if not */
	EtherNet;		/* The all-powerful! */
extern
SysEnvRec
	theWorld;		/* The state of the machine address */
extern
char
	*VERSION;		/* Version Information */

#ifdef JOHN_DEERE
	int jdp;
#endif

void UItemAssign
  (
	DialogPtr dlog,
	int item,
	int (*proc)()
  ) /* sets the handler for a user item to the specified procedure. */
{
	Rect ibox;
	char **ihndl;
	short typ;

	GetDItem( dlog, item, &typ, &ihndl, &ibox);
	SetDItem( dlog, item,  typ, (Handle) proc, &ibox);
}

void HostIsAppl
  (
	void
  )
{
	Str255 fileName;
	short dumint;
	Handle dumlong;
	char *nnmm, *from;
	
	getappparms( &fileName, &dumint, &dumlong);
	nnmm = (char *) NewPtr( 64);
	if (nnmm ==NULL) {
		OtherError("Can't allocate space for","default config.tel name");
		quit();
		}
	from = &fileName;			/* Convert to a real format... */

	from = strncpy( nnmm,from, 63);			/* Strcpy sort of ... */
	nnmm[63]=0;
	Shostfile(nnmm);
}

/*
 *			T h e		M  A  I  N			P r o g r a m
 */

void initmac
  (
	void
  )
{
	char **userstring;
	EventRecord myEvent;
	int i;

	InitGraf(&qd.thePort);
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs(0L);
	InitCursor();

	/* MaxApplZone(); */
	MoreMasters();					/* I want memory, */
	MoreMasters();					/* Lots of Memory, */
	MoreMasters();					/* I want ApplHeap, and SysHeap, and more */
	MoreMasters();					/* Give me handles, and pointers...... */
	MoreMasters();
	MoreMasters();
	MoreMasters();

#ifndef REAL
	err=openresfile("ncsa.rsrc");	/* We don't want to RESedit too much */
#endif

	InquireEnvironment();

	for (i=1;i<12;i++)
		EventAvail( 0xffff, &myEvent);
	setupmenu( 0);				/* Temporarily default to old menus.... */

	screenRect = qd.screenBits.bounds;			/* well, they have to be set */
												/* somewhere, where else ? */
	SetRect(&dragRect, 4, 24, screenRect.right-4, screenRect.bottom-4);
	SetRect(&SizRect,	10*Fwidth+18,  3 *Fheight+18,
						80*Fwidth+18, 24 *Fheight+18);

	userstring =GetResource('NCSA',1);

	if (userstring !=0L) {
		userlevel= **userstring -'0';
		if (userlevel<0) userlevel=32767;
		if (userlevel>3) HostIsAppl();		/* Don't use config.tel <UAS> */
		}
}

/*
 * checkdebug - check to see if they clicked on a debug file
 */

int checkdebug
  (
	void
  )
{
	short i,mess,count;
	AppFile theFile;

	CountAppFiles(&mess,&count);
	if (mess==1) return(FALSE);
	if (count<1) return(FALSE);
	for(i=1;i<=count;i++) {
		GetAppFiles(i, &theFile);
		if (theFile.fType=='DBUG') {
			ClrAppFiles(i);
			return(TRUE);
			}
		if (theFile.fType=='TEXT') {
			char *nnmm, *from;
			ClrAppFiles(i);
			nnmm = (char *) NewPtr( 64);
			if (nnmm ==NULL) {
				OtherError("Can't allocate space for","default config.tel name");
				quit();
				}
			from = &theFile.fName;			/* Convert to a real format... */

			p2cstr(from);
			from = strncpy( nnmm,from, 63);			/* Strcpy sort of ... */
			nnmm[63]=0;
			Shostfile(nnmm);
			}
		}
	return(FALSE);
}

void putln									/* Put a C string on the console */
  (
	char *cp
  )
{
	int temp;

	if (!debug)
		return;

	temp=strlen(cp);
	if (temp>80) return;
	VSwrite(console.vs,cp,temp);
	VSwrite(console.vs,"\015\012",2);
}

/*
 *	initmcurs - Set up the mouse Cursors
 *		NOTE: debug tells if the bug or the pointer is to be used as dflt.
 */

void loadcursor
  (
	int CursorID,
	CursPtr *result
  )
  /* copies a specified cursor from a resource into a nonrelocatable block
	and returns a pointer to it in *result. */
  {
	CursHandle tempcurs;
	OSErr Err;

	*result = nil;
	do /* once */
	  {
		tempcurs = GetCursor(CursorID);
		Err = ResError();
		if (Err != noErr)
			break;
		(Ptr) *result = NewPtr(sizeof(Cursor));
		Err = MemError();
		if (Err != noErr)
			break;
		LoadResource((Handle) tempcurs); /* in case it was purged */
		Err = ResError();
		if (Err != noErr)
			break;
		BlockMove((Ptr) *tempcurs, (Ptr) *result, sizeof(Cursor));
	  }
	while (false);
	if (Err != noErr)
	  {
		if (*result != nil)
			DisposPtr((Ptr) *result);
		*result = &qd.arrow;
	  }
  } /* loadcursor */

void initmcurs
  (
	int debug
  ) /* initializes all the mouse cursors for later use */
  {
	loadcursor(watchCursor, &watchcurs);
	loadcursor(crossCursor, &graphcurs);
	loadcursor(POSCURS, &poscurs);
	loadcursor(iBeamCursor, &textcurs);
	loadcursor(GINCURS, &gincurs);
	loadcursor(XferCURS, &xfercurs);
	if (debug)
		loadcursor(DbugCURS, &normcurs);
	else
		normcurs = &qd.arrow;
	SetCursor(normcurs);
  }

/*
 * initconsole - initialize the  console window
 */

void initconsole
  (
	void
  )
{
	Rect pRect;

	SetRect(&pRect,15,287,15+MAXWINDOWWIDTH /*495,335 */, 287+MAXWINDOWHEIGHT);
	console.vs=RSnewwindow( &pRect, 50, 80, 24,
							"<console>", 1, DefFONT, DefSIZE, debug,0,0); /* NCSA 2.5 */
	console.wind = RSgetwindow( console.vs);

	VSwrite(ftplog.vs,"\033[24;0H",1);		/* Move to bottom of screen */

	console.active=0;console.port=0;
	console.termstate=VTEKTYPE;
	console.name="<console>";
}

/*
 * initftplog - initialize the FTP log window
 */

void initftplog
  (
	void
  )
{
	Rect prect;

	SetRect(&prect, 300,256,512,384);

	ftplog.vs=RSnewwindow( &prect, 50, 80, 24,
							"FTP Log", 1, DefFONT, DefSIZE,0,0,0); /* NCSA 2.5 */
	ftplog.wind = RSgetwindow( ftplog.vs);

	VSwrite(ftplog.vs,"\033[24;0H",7);		/* Move to bottom of screen */
	ftplog.active=0; 						/* Meaningless */
	ftplog.port=0;							/* As is this */
	ftplog.termstate=VTEKTYPE;
	ftplog.name="FTP Log";					/* And most of these */

}

/*
 *	initwd - Initialize the working directory pointers
 */

void initwd
  (
	void
  )
{
	extern int defaultv;

	defaultv=getWDnum();
	dvs=getWDname();
	VSwrite(console.vs,&(*dvs)[1],(int) (*dvs)[0]);
}

int ckhostfile
  (
	void
  )
{
	DialogPtr dtemp;
	char *from,*nnmm;
	Point where;
	SFReply sfr;
	SFTypeList	sfl;
	int temp=0;
	short item=0;
	Str255 *dir;


	dtemp=GetNewDialog( BadHostDLOG,(Ptr) 0L,(WindowPtr) -1L);
	while( item<1 || item>2 )
		ModalDialog((ModalFilterProcPtr) modalProc ,&item);
	DisposDialog(dtemp);

	if ( item==BadHostQuit ) return(-1);
	if ( item==BadHostCont ) return(-1);		/* changed, continue not allowed */

	where.h=100; where.v=100;
	sfl[0]='TEXT';					/* All TEXT files are Game */

	sfgetfile( pass(where), "Select Host File:", 0L,1,sfl,0L,&sfr);

	if (!sfr.good) {
		putln("got bad filename");	/* Possibly/Probably Cancel */
		return(-1);
		}

	setvol( 0L, sfr.vRefNum);		/* I like HFS, I like HFS, except when it is a pain */

	nnmm = (char *) NewPtr( 64);
	if (nnmm ==NULL) {
		OtherError("Can't allocate space for","modified config.tel name");
		quit();
		}
	from = &sfr.fName;			/* Convert to a real format... */

	p2cstr(from);
	dir = getWDname();
	(*dir)[++(*dir)[0]]='/';
	VSwrite( console.vs, &(*dir)[1], (int) (*dir)[0]);	/* Preview pathspec... */
	putln(from );						/* preview.... */

	from = strncpy( nnmm,from, 63);			/* Strcpy sort of ... */
	nnmm[63]=0;

	Shostfile(nnmm);

	return(0);
}

/*
 * initnet - init all of the network stuff...
 */

void initnet
  (
	int debug
  )
{
#pragma unused(debug)
	struct config conf;
	int error;

	error=Snetinit();

	if (error!=0 && error!=-2) {			/* if cant find hosts file, give em another */
		ShowAllErrors();
		if (ckhostfile()) {			/* BYU */
			quit();					/* BYU - shot, if that fails.... */
			return;					/* BYU */
			}						/* BYU */
		if (Snetinit()!=0) 	{		/* Ok, but only one more chance or we'll.... */
			HostIsAppl();
			ShowAllErrors();
	
			error=Snetinit();
			if (error!=0 && error!=-2) {
				ShowAllErrors();
				quit();	/* Squash 'em like a grape! */
				return;				/* BYU */
				}
			}
		}
	if (error == -2)
		reconfigNetwork(0);

	neton=1;
	TickCount();
	Sgetconfig(&conf);
	if (conf.comkeys)
		whichMenus=1;
	else
		whichMenus=0;
	strcpy(TermType,conf.termtype);
	switchMenus(whichMenus);

	if (conf.timesl>=0) JTime(conf.timesl);
	if (conf.textblock > 0)  
		setblocksize(conf.textblock);		/* network read-buffer size */
	else 
		setblocksize(120);

#ifdef SMTP
	setSMTP();						/* anyone wanna receive mail ? */
#endif

}

main()
{
	DialogPtr dtemp;		/* Used for storage of the copyright dlog */


	DirTree = (int *)NewPtr(256*sizeof(int));
	mungbuf = (char *)NewPtr(1024);
	
	FlushEvents(everyEvent,0);
	initmac();				/* initialize Macintosh stuff */

	debug=checkdebug();		/* must return TRUE or FALSE */

	initmcurs(debug);		/* init the mouse cursor */
	SetCursor(watchcurs);

	if (RGMalloc()) {		/* BYU - save global space */
		short item;
		ParamText(0L, 0L, 0L, "\pInsufficient memory for TEK graphics");
		dtemp = GetNewDialog(302, (Ptr) 0L, (WindowPtr) -1L);
		ModalDialog(0L, &item);
		DisposDialog(dtemp);
		return;
	}						/* BYU */
	VGalloc();				/* BYU - save global space */
	VSinit(MaxSess+2);				/* initialize the Virtual Screen */
	
	screens = (WindRec *)NewPtr(MaxSess*sizeof(WindRec));

	initconsole();			/* allocate/initialize console screen */

/*	initEvents();			/* BYU 2.4.18 - Do Juggler stuff if necessary */

	dtemp=GetNewDialog(FirstDLOG,(Ptr) 0L,(WindowPtr) -1L);	/* opening dialog */
	UItemAssign( dtemp, 2, (int (*)()) VersionNumber);
	putln("past version number");
	DrawDialog(dtemp);				/* while we init everything */

	initftplog();			/* allocate/initialize ftp log screen */
	putln("past initftplog");
	VGinit();				/* initialize Virtual Graphics after VS so that */
							/* init messages can come on console screen */
	VRinit();
	MacRGinit();
	initwd();				/* init working/file transfer directory */


	net_okay = TRUE;		/* BYU serial - assume okay (necessary for initnet()). */
	initnet(debug);			/* initialize TK's network stuff */
	if (done || !neton)		/* BYU serial */
		net_okay = FALSE;	/* BYU serial */
	else					/* BYU serial */
		net_okay = TRUE;	/* BYU serial */

	done = FALSE;			/* BYU serial */

	init_serial();			/* BYU serial */
	initslip();				/* BYU 2.4.15 */

	init_mb_files();		/* BYU - initialize file id's to closed state */
					/* if initipnum() then FatalError("Can't run w/o IP number"); */
/*	initipnum( Button() && (userlevel==1)); */

											/* get the IP number (w/reconfigure) */
	SetCursor(normcurs);

	GetPrefs();				/* Load user preferences  (must be after initipnum) */
	initEvents();			/* BYU 2.4.18 - Must be after GetPrefs() */
	netgetip( myipnum);		/* Just in case it was RARPed */
	initswitch();			/* initialize switcher stuff if necessary */


	if (EtherNet == -99) {							/* BYU 2.4.16 */
		io = OpenResolver(NULL);					/* BYU 2.4.16 */

		if (io) {									/* BYU 2.4.16 */
			DialogPtr theErrDialog;					/* BYU 2.4.16 */
			short itemhit=0;						/* BYU 2.4.16 */

/* BYU serial - "Unable to open resolver" message. */
			theErrDialog = GetNewDialog(RESOLVERERROR,(Ptr)0L,(WindowPtr)-1L);	/* BYU 2.4.16 */
			DrawDialog(theErrDialog);									/* BYU 2.4.16 */
			while (!itemhit) 											/* BYU 2.4.16 */
				ModalDialog((ModalFilterProcPtr) modalProc,&itemhit);	/* BYU 2.4.16 */
			EtherNet = -100;											/* BYU 2.4.16 */
/*			quit();									/* BYU 2.4.16 */
		}											/* BYU 2.4.16 */
	}												/* BYU 2.4.16 */

/*	Ssetgates();					/* BYU serial - finishes IP inits */

	updateMenuChecks();
	DoTheMenuChecks();
	
	if (!checkCONF()) 				/* Configuration files? */
		DrawDialog(dtemp);			/* while we init everything */

	DisposDialog(dtemp);			/* Take it off.....all off......*/

#ifdef JOHN_DEERE
	jdp = netlisten( 2001,0);		/* BYU 2.4.15 */
#endif

	do {						/* BYU - Do this forever */
											/* Getting a tad bit small..... */

#ifdef SMTP
		rSMTPd();
#endif
		DoEvents();
		if (!done) DoModem();					/* BYU serial - watch serial port */
		if (!done && net_okay) DoNetEvents();	/* BYU serial - act like the postman */

	} while (!done);			/* BYU mod */
/*	quit();		/* BYU - TWIMC: this statement never used to execute */
}

putstr(cp)									/* Put an STR255 on the console */
char *cp;
{
	int temp;
	temp = cp[0];
	if (temp > 80)
		return;
	VSwrite(console.vs, &cp[1], temp);
	VSwrite(console.vs, "\015\012", 2);
}

vsput(c)									/* Put a single char on the console */
char c;
{
	VSwrite(console.vs,&c,1);
}

void ftpmess								/* Put a C string on the console */
  (
	char *cp
  )
{
	int temp;
	temp=strlen(cp);
	if (temp>80 || temp < 1) return;
	VSwrite(ftplog.vs,cp,temp);
}

int detachGraphics
  (
	int dnum
  )
{
	int i=0;

	while((i<numwindows) && (dnum!=screens[i].curgraph)) i++;
	if (i>=numwindows) return(-1);
	oldgraph[graphs++]=dnum;
	screens[i].curgraph=-1;
	screens[i].termstate=VTEKTYPE;
	screens[i].enabled=1;
	RGdetach(dnum);
	return(0);
}

int addport
  (
	ConfigRec *config
  )
{
	int i,cur,new, domlook=0,kk;
	char temp[43],*p,*rindex();
	long VSwhereis();
	struct machinfo *mp;
	DialogPtr dtemp;
	struct machinfo *Sgethost();

	SetCursor( watchcurs);					/* We may be here ARPTO seconds */

	paramtext( config->machine, 0L, 0L, "");
										/* No errors and this is the session */
	ptoc(config->machine);									
/*
*  check for port number tacked onto machine name.
*/
	if (!config->ftpwind)					/* is it an ftp window? */
		{
		p = rindex(config->machine, ' ');	/* look for space */
		if (p) {
			i = atoi(p);
			if (i > 0)
				config->port = i;			/* new port to try for */
			p = index(config->machine, ' ');
			if (p)
				*p = 0;						/* terminate string at first space */
			}
		}
/*	else config->port = 21;					/* BYU 2.4.20 - not needed, start at ftp port */
	
	new=0;								/* Spot for new conn # */

	mp = Sgethost( config->machine );

					/* Make the config record count for something..... */

	putln("got before configrec");
	if (!mp && (config->connectionType == 0))  {	/* BYU serial */
		new = Sdomain( config->machine);
		domlook=1;

		mp = Slooknum(new);				/* get machine record */
		putln("after looknum");
 		if (mp && config->port > 0) 
			mp->port = config->port;  	/* save port to use later */
		}
	else {

/* 
*  When it comes to the port number to try for, if our user asked for
*  a specific port number, make sure he gets it.  Otherwise take the 
*  config file's word for it. 
*/
		putln("inside else");
		if (config->ftpstate != 0) 		/* BYU mod */
			config->port = 21;			/* BYU mod */
		else							/* BYU mod */
		if (config->port == 23 && mp->port > 0)
			config->port = mp->port;		
		
		
		putln("before Snetopen");
		new = Snetopen( mp, config->port, config->connectionType);	/* BYU 2.4.15 */

		if (new < 0) { 												/* BYU 2.4.15 */

			if (config->connectionType == 0) {								/* BYU 2.4.15 */
				dtemp=GetNewDialog(ConnFalDLOG,(Ptr) 0L,(WindowPtr) -1L);	/* BYU 2.4.15 */
				DrawDialog( dtemp);											/* BYU 2.4.15 */
	
				Wait4Mouse();
				DisposDialog( dtemp);
			}

			updateCursor(1);							
			return(-1);
			} 

		}


	cur=numwindows;			/* Adjust # of windows and get this window's number */
	numwindows++;

	DoTheMenuChecks();

	screens[cur].lineAllow = config->lineAllow;
	screens[cur].eightbit = config->eightbit;		/* BYU 2.4.9 */
	screens[cur].forcesave = config->forcesave;		/* NCSA 2.5 */
	screens[cur].ftpwind = config->ftpwind;
	screens[cur].port=new;
	screens[cur].portNum = config->port;			/* NCSA */
	screens[cur].outlen=0;

	screens[cur].lmflag=0;
	for (kk=1; kk<19; kk++)
		(screens[cur]).slc[kk]=-1;
	screens[cur].slc[SLC_IP]=3;
	screens[cur].slc[SLC_EC]=127;
	screens[cur].slc[SLC_EL]=21;
	screens[cur].slc[SLC_EOF]=4;
	screens[cur].slc[SLC_ABORT]=3;
	screens[cur].slc[SLC_SUSP]=26; 
	

	screens[cur].vs=RSnewwindow( &config->window, config->scrollback, config->width, config->nlines,
								  config->name, config->vtwrap, config->font, config->fsize,
								  0, Prefs.dontclose, config->forcesave); /* NCSA 2.5 */
	screens[cur].wind=RSgetwindow( screens[cur].vs);

	sprintf(temp,"VS -%d- %lx (%d)",screens[cur].vs, VSwhereis(screens[cur].vs),
									config->scrollback);
	putln(temp);

	if (screens[cur].vs<0) {
		putln( "Couldn't open Virtual Screen");
		updateCursor(1);							/* Done stalling the user */
		return(-1);
		}

	screens[cur].maxscroll=config->scrollback;
#ifdef TESTING
	screens[cur].termstate=DUMBTYPE;
#else
	screens[cur].termstate=VTEKTYPE;
#endif TESTING
	screens[cur].naws =0;					/* NCSA - set default NAWS to zero */
	screens[cur].rows =config->nlines;		/* BYU 2.4.16 */
	screens[cur].bsdel=config->bsdel;
	screens[cur].name=config->name;
	screens[cur].machine=config->machine;
	screens[cur].crmap = config->crmap;
	screens[cur].tekclear= config->tekclear;
	screens[cur].ESscroll= config->clearsave;
	screens[cur].ESclear= TRUE;				/* BYU 2.4.8 - default Tek page clears screen */
	screens[cur].xfer=0;
	screens[cur].connectionType=config->connectionType;	/* BYU serial */
	screens[cur].ftpstate=config->ftpstate;	/* BYU */
	screens[cur].tektype = config->tektype;
	screens[cur].telstate=0;
	screens[cur].timing=0;
	screens[cur].curgraph=-1;			/* No graphics screen */
	screens[cur].echo=0;				/* I'm not echoing, are you? */
	screens[cur].ftpport = -1;			/* BYU - No additional FTP port opened yet */
	screens[cur].clientflags = 0;		/* BYU */
	if (config->ftpstate != 0) {		/* BYU */
	  screens[cur].termstate=DUMBTYPE;	/* BYU */
	  screens[cur].echo=1;				/* BYU - Echo for ftp */
	  screens[cur].halfdup = 1;			/* BYU */
	} else {							/* BYU */
	  screens[cur].termstate=VTEKTYPE;	/* BYU */
	  screens[cur].echo=0;				/* BYU - I'm not echoing, are you? */
	  screens[cur].halfdup = config->halfdup;	/* BYU */
	}									/* BYU */
	screens[cur].wrap = config->vtwrap;	/* wrap mode anyone? */
	screens[cur].kblen=0;				/* nothing in the buffer */
	screens[cur].enabled=1;				/* Gotta be enabled to start with */
	screens[cur].Ittype=0;
	screens[cur].Isga=0;				/* I suppress go ahead = no */
	screens[cur].Usga=0;				/* U suppress go ahead = no */
	screens[cur].corpse=0;
	screens[cur].width= config->width;
	if (screens[cur].connectionType != 0) {		/* BYU serial - if serial connection ... */
		screens[cur].TELstop = -1;				/* BYU serial - no stopping */
		screens[cur].TELgo = -1;				/* BYU serial - no going */
		screens[cur].TELip = -1;				/* BYU serial - no Interrupting the Process */
	} else {
		screens[cur].TELstop = config->TELstop;	/* BYU serial - ^s stops */
		screens[cur].TELgo = config->TELgo;		/* BYU serial - ^q gos */
		screens[cur].TELip = config->TELip;		/* BYU serial - ^c Interrupts the Process */
	}

	for (i=0;i<4;i++)
		if (RSsetcolor( screens[cur].vs, i, config->red[i],
										config->green[i],
										config->blue[i]))
			putln("Trouble setting the color");
		else putln("Color set...");

	if ((screens[cur].connectionType == 1) && !slip_connection) {		/* BYU 2.4.15 */
		addinmenu(cur, (Str255 *) screens[cur].name, (char) 0x13);		/* BYU serial */
    	screens[cur].active=0;											/* BYU serial */
    	RSshow( screens[cur].vs);			/* BYU serial */
    	SelectWindow(screens[cur].wind);	/* BYU serial */
    	screens[cur].Usga=1;				/* BYU serial */
    	changeport(scrn,cur);				/* BYU serial */
    	liveport(scrn);						/* BYU serial */
		}									/* BYU serial */
	else									/* BYU serial */

	if (domlook) {
		addinmenu(cur, (Str255 *) screens[cur].name, (char) 0x13);
		screens[cur].active = -1;
		}
	else {
		addinmenu(cur, (Str255 *) screens[cur].name, (char) 0xa5);
		screens[cur].active = 1;
		}

	VSscrolcontrol( screens[scrn].vs, -1, screens[scrn].ESscroll);
	updateCursor(1);							/* Done stalling the user */
/*	netgetip( myipnum);	*/			/* For Driver version, we must get our number */
	return(cur);
} /* addport */

void destroyport
  (
	int wind
  )
{
	int i,
		callNoWindow=0;


	SetCursor( watchcurs);					/* We may be here a while */

	if (!screens[wind].corpse) {
		if (screens[wind].curgraph>-1)
			detachGraphics( screens[wind].curgraph);	/* Detach the Tek screen */
		if (screens[wind].outlen>0) {
			screens[wind].outlen=0;						/* Kill the remaining send*/
			HUnlock( screens[wind].outhand);			/*  buffer */
			HPurge ( screens[wind].outhand);
			}
		}


	/* Get rid of the names.  We don't need them anymore */
	
	DisposPtr(screens[wind].machine);
	DisposPtr(screens[wind].name);



	if (FrontWindow() == screens[wind].wind)
		callNoWindow=1;

	RSkillwindow( screens[wind].vs);
	screens[wind].active=-5;
	for (i=wind;i<numwindows-1;i++) {
		screens[i]=screens[i+1];		/* Bump all of the pointers */
		}
	if (scrn>wind) scrn--;				/* Adjust for deleting a lower #ered screen */

	numwindows--;						/* There are now fewer windows */
	extractmenu( wind);					/* remove from the menu bar */

	DoTheMenuChecks();

/* BYU 2.4.11 - the call to "NoWindow()" changes "myfrontwindow", 
                which is used by "updateCursor()", so we reversed 
                the order of the following two lines.  This was 
                causing the Mac the hang sometimes. */
	if (callNoWindow) NoWindow();	/* BYU 2.4.11 - Update cursor stuff if front window */
	updateCursor(1);				/* BYU 2.4.11 - Done stalling the user */

} /* destroyport */

void removeport
  (
	int wind
  )
{
	SetCursor( watchcurs);					/* We may be here a while */

	if (screens[wind].curgraph>-1)
		detachGraphics( screens[wind].curgraph);	/* Detach the Tek screen */
	if (screens[wind].outlen>0) {
				screens[wind].outlen=0;				/* Kill the remaining send*/
				HUnlock( screens[wind].outhand);	/*  buffer */
				HPurge ( screens[wind].outhand);
				}
	if (!Prefs.dontclose)
		destroyport(wind);
	else {
		char temp[255];
		sprintf(temp, "(%s)",screens[wind].name);
		setwtitle( screens[wind].wind, temp);

		screens[wind].corpse=1;
		screens[wind].port = 32700;
		screens[wind].active=-5;

		}
	updateCursor(1);							/* Done stalling the user */
} /* removeport */

int findbyWind						/* Find screen index by Window */
  (
	GrafPtr wn
  )
{
	int i=0;

	while((i<numwindows) && (wn!=screens[i].wind)) i++;
	if (i>=numwindows) return(-1);
	return(i);
}

int findbyVS						/* Find screen index by VS Number */
  (
	int vs
  )
{
	int i=0;

	while((i<numwindows) && (vs!=screens[i].vs)) i++;
	if (i>=numwindows) return(-1);
	return(i);
}

int isEightBit(int vs) {			/* BYU 2.4.12 */
	int i = findbyVS(vs);			/* BYU 2.4.12 */
	if (i>=numwindows) return(0);	/* BYU 2.4.12 */
	return(screens[i].eightbit);	/* BYU 2.4.12 */
}									/* BYU 2.4.12 */

void ERR				/* Error routine for BKGR/ICMP/etc....*/
  (
	int num
  )
{
	char temp[80],*dummy;

	dummy=strncpy( &temp[1],neterrstring(num),78);
	temp[79]='\0';						/* Compensate for error in strncopy */
	temp[0]= (unsigned char)strlen(&temp[1]);
	paramtext(0L,0L,0L,&temp[1]);			/* Load the error record field */
	putln( &temp[1]);
}

void xferstart					/* Called at start of FTP */
  (
	void
  )
{
	xferon=1;
	updateCursor(1);
}

void xferdone					/* Called at end of FTP */
  (
	void
  )
{
	xferon=0;
	updateCursor(1);
}

void setgraphcurs					/* Called at start of gin */
  (
	void
  )
{
	putln("Graphics INput mode entered");
	ginon=1;
	updateCursor(1);
}

void unsetgraphcurs					/* Called at start of gin */
  (
	void
  )
{
	ginon=0;
	updateCursor(1);
}

int decodeIPnum
  (
	char *s,
	unsigned char *myipnum
  )
{
	int i, node, hi, low;
	char temp[50];

	for (i=0; i<4; i++) myipnum[i]=0;
	i=0;
	
	if (!EtherNet)
		getATaddress( &hi, &low, &node);

	while((*s) && (i<4) ) {
		switch( *s) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				myipnum[i]= myipnum[i] *10 + (*s-'0');
				break;
			case '.':
				i++;
				break;
			case 'H':
			case 'h':
				myipnum[i]=hi;
				break;
			case 'L':
			case 'l':
				myipnum[i]=low;
				break;
			case 'N':
			case 'n':
				myipnum[i]=node;
				break;
			default:
				break;
			}
		s++;
		}
	
	sprintf( temp," IPNUM= %d.%d.%d.%d", (int) myipnum[0], (int) myipnum[1], (int) myipnum[2],
									 	(int) myipnum[3]);
	putln(temp);
	
	if (i<3) return( 1);
		else return( 0);
}

/*	CheckConfig (dynamic, dIP, useMask, dMask)
 *
 *		checks the configuration described by IP and Mask strings.  If it is OK,
 *			it returns (0).  If it is bad, it displays a message and returns (1)
 */
int CheckConfig
  (
	int dynamic,
	Handle dIP,
	int useMask,
	Handle dMask
  )
{
	DialogPtr dtemp;
	char temp[256];
	short item;
	int error=0;
	long ltemp;

	if (!dynamic) {				/* Check IP NUmber if appropriate */
		GetIText( dIP, temp);
		temp[temp[0] + 1]=0;			/* be safe for the wonderful sscanf */
	
		if (decodeIPnum(&temp[1], (unsigned char *) &ltemp)) {
			error=1;

			dtemp=GetNewDialog( BadIPDLOG,(Ptr) 0L,(WindowPtr) -1L);
			ModalDialog((ModalFilterProcPtr) modalProc, &item);
			DisposDialog(dtemp);
			}
		}

	if (useMask) {				/* Check Subnet Mask if appropriate */
		GetIText( dMask, temp);
		temp[temp[0] + 1] = 0;			/* be safe for the wonderful sscanf */

		if (temp[0]!=8 || (sscanf(&temp[1], "%lx", &ltemp)!=1) ) {
			error=1;

			dtemp=GetNewDialog( BadMaskDLOG,(Ptr) 0L,(WindowPtr) -1L);
			ModalDialog((ModalFilterProcPtr) modalProc, &item);
			DisposDialog(dtemp);
			}
		}
	return(error);
}

/*
 * PromptIP - this is one HUGE procedure, but I have not come up with an easy way
 *	to break it down.  It allows you to change all of the network parameters....
 */

int PromptIP
  (
	int dynam
  )
{

#define GetStrRes(x)	(Str255 **)GetResource('STR ',x);

	DialogPtr dtemp;
	Str255 *ptemp,nstring;
	Str255 **hostR,**ipR, **maskR;
	Str255 **fileR, *ftemp;				/* NCSA 2.5: Capture session file */
	Rect dBox;
	Handle dynIP,statIP,useMask,dHand, dIP, dMask;
	int olddynam;
	int mask=0,terr,badconfig=1, enteredbad;
	short dItem;
	
	dtemp=GetNewDialog(GetParmDLOG,(Ptr) 0L,(WindowPtr) -1L); /* Get the dialog to use */

	UItemAssign( dtemp, 11, (int (*)()) OutlineItem);

	ipR=GetStrRes(IPnumSTR);				/* Was there an IP Number before */

	if (ipR!=0L) {							/* If So...*/
		GetDItem(dtemp,GetParmIP,&dItem,&dHand,&dBox);	/* Get the dialog item */
		HLock((Handle) ipR);							/* Lock the string in */

		SetIText(dHand, (Str255) *ipR);					/* Set the item's text to the old 1*/
		SelIText(dtemp,GetParmIP,0,32767);				/* And select it */
		HUnlock((Handle) ipR);							/* Unlock the string */
#ifdef OLDM
		RmveResource(ipR);					/* Remove the old rotting number */
#endif
		putln("Reading previous IP Resource");
		}
	else if (KIP) dynam=1;					/* Default to dynamic if KIP + no res */


	fileR=GetStrRes( FileSTR);				/* NCSA 2.5 */
	if (fileR!=0L) {						/* NCSA 2.5 */
		GetDItem(dtemp,GetCaptureName,&dItem,&dHand,&dBox);	/* NCSA 2.5 */
		HLock((Handle) fileR);					/* NCSA 2.5 */
												/* NCSA 2.5 */	
		SetIText(dHand, (Str255) *fileR);		/* NCSA 2.5 */
												/* NCSA 2.5 */	
		HUnlock((Handle) fileR);				/* NCSA 2.5 */
		putln("Reading previous Capture File Resource");	/* NCSA 2.5 */
		}										/* NCSA 2.5 */

	hostR=GetStrRes( HostSTR);		/* Was there a default host */
	if (hostR!=0L) {							/* If So...*/
		GetDItem(dtemp,GetParmHOST,&dItem,&dHand,&dBox);	/* Get the dialog item */
		HLock((Handle) hostR);					/* Lock the string in */

		SetIText(dHand, (Str255) *hostR);		/* Set the item's text to the old 1*/

		HUnlock((Handle) hostR);				/* Unlock the string */
		putln("Reading previous Default Dest. Resource");
		}

	maskR=GetStrRes( MaskSTR );
	if (maskR!=0L) {							/* If So...*/
		GetDItem(dtemp,GetParmMASK,&dItem,&dHand,&dBox);	/* Get the dialog item */
		HLock((Handle) maskR);						/* Lock the string in */

		SetIText(dHand, (Str255) *maskR);			/* Set the item's text to the old 1*/

		HUnlock((Handle) maskR);					/* Unlock the string */

		if ( mynetmask!=defmask ) mask=1;		/* Is the mask custom? */

		putln("Reading previous Mask Resource");
		}

	olddynam = dynam;

	dItem=0;
	GetDItem(dtemp,GetParmStat,&dItem,&statIP,&dBox);	/* Get the IP # handle */

	dItem=0;
	GetDItem(dtemp,GetParmKDyn,&dItem,&dynIP,&dBox);	/* Get the Dynam Handle */

	dItem=0;
	GetDItem(dtemp,GetParmUseM,&dItem,&useMask,&dBox);	/* Get the Mask Handle */

	dItem=0;
	GetDItem(dtemp,GetParmIP,&dItem,&dIP,&dBox);		/* Get the IP TE Handle */

	dItem=0;
	GetDItem(dtemp,GetParmMASK,&dItem,&dMask,&dBox);	/* Get the Mask TE Handle */

	if (!(KIP || EtherNet)) {
		HiliteControl((ControlHandle) dynIP,255);	/* Dont even think of dynam */
		dynam = 0;
		}

	SetCtlValue((ControlHandle) dynIP,dynam);				/* Set up the controls */

	SetCtlValue((ControlHandle) statIP, !dynam);			/* Kip/RARP can have dynamic */

	SetCtlValue((ControlHandle) useMask, mask);				/* No Mask to start */
#ifdef MAYBELATER
	enteredbad = CheckConfig( dynam, dIP, mask, dMask);
											/* We can't cancel if we have a bad start */
#else
#pragma unused(enteredbad)
#endif
	while( badconfig) {
		dItem=0;
		while((dItem> 2) || (dItem==0)) {		/* loop till done */
			ModalDialog((ModalFilterProcPtr) modalProc ,&dItem); /* Get an event */
			if (dItem==GetParmIP)  
					if (dynam) dItem = GetParmStat;
			if (dItem==GetParmStat) { dynam=0;					/* They want to tell me */
							SetCtlValue((ControlHandle) dynIP,dynam);
							SetCtlValue((ControlHandle) statIP, !dynam);
						}
			if (dItem==GetParmKDyn) { dynam=1;					/* I should figure it out */
							SetCtlValue((ControlHandle) dynIP,dynam);
							SetCtlValue((ControlHandle) statIP, !dynam);
						}
			if (dItem==GetParmMASK) 
					if (!mask) dItem=GetParmUseM;
			if (dItem==GetParmUseM) {mask=!mask;
							SetCtlValue((ControlHandle) useMask,mask);
						}
			}
	
		if (dItem == 1) {
			DisposDialog(dtemp);						/* Get rid of dialog */
			return(olddynam);
			}
		badconfig=CheckConfig( dynam, dIP, mask, dMask);
		}			/* End of While Badconfig */

	if (SettingsFile==-1) {
		DisposDialog(dtemp);
		return(dynam);
		}


	if (ipR ==0L) {
		putln("Making new IP number resource");
		ipR=(Str255 **)NewHandle(256L);		/* Get a temp handle */
		if (ipR==0L) putln("I can't get any space");
		addresource((Handle) ipR,'STR ',256,"IP Number");
		if ((terr=ResError())!=0) {
			sprintf(&nstring,"Error in addresource. (%d)",terr);
			putln(&nstring);
			}
		}

	HLock((Handle) ipR);					/* Lock it down */
	ptemp=*ipR;								/* a pointer for sanity*/

	GetIText(dIP, (Str255) ptemp);				/* Get the IP Number fm the TE */
	(*ptemp)[(*ptemp)[0] + 1] = 0;				/* be on the scanf safe side */

	if (dynam) (*ptemp)[0]=0;
	else 
		if (0==decodeIPnum( &(*ptemp)[1], myipnum) )
				putln("Got a successful IP Number");

	HUnlock((Handle) ipR);
	ChangedResource((Handle) ipR);
	UpdateResFile(HomeResFile((Handle) ipR));	/* now it is saved, process it*/

/******/


	if (fileR ==0L) {									/* NCSA 2.5 */
		putln("Making new Capture File resource");		/* NCSA 2.5 */
		fileR=(Str255 **)NewHandle(256L);				/* NCSA 2.5 */
		if (fileR==0L) putln("I can't get any space");	/* NCSA 2.5 */
		addresource((Handle) fileR,'STR ',FileSTR,"CaptureFile");	/* NCSA 2.5 */
		if ((terr=ResError())!=0) {								/* NCSA 2.5 */
			sprintf(&nstring,"Error in addresource. (%d)",terr);	/* NCSA 2.5 */
			putln(&nstring);									/* NCSA 2.5 */
			}											/* NCSA 2.5 */
		}												/* NCSA 2.5 */

	if (hostR ==0L) {
		putln("Making new Host resource");
		hostR=(Str255 **)NewHandle(256L);		/* Get a temp handle */
		if (hostR==0L) putln("I can't get any space");
		addresource((Handle) hostR,'STR ',257,"Default Host");
		if ((terr=ResError())!=0) {
			sprintf(&nstring,"Error in addresource. (%d)",terr);
			putln(&nstring);
			}
		}

	HLock((Handle) hostR);								/* Lock it down */
	ptemp=*hostR;								/* a pointer for sanity*/

	GetDItem(dtemp,GetParmHOST,&dItem,&dHand,&dBox);		/* Get the Default Host */
	GetIText(dHand, (Str255) ptemp);

	movmem( ptemp, defaultd,256);				/* Make a copy for later */
	p2cstr((StringPtr) defaultd);

	HUnlock((Handle) hostR);
	ChangedResource((Handle) hostR);
	UpdateResFile(HomeResFile((Handle) hostR));


	HLock((Handle) fileR);						/* NCSA 2.5 */
	ftemp=*fileR;								/* NCSA 2.5 */
	GetDItem(dtemp,GetCaptureName,&dItem,&dHand,&dBox);	/* NCSA 2.5 */
	GetIText(dHand, (Str255) ftemp);			/* NCSA 2.5 */
	HUnlock((Handle) fileR);					/* NCSA 2.5 */
	ChangedResource((Handle) fileR);			/* NCSA 2.5 */
	UpdateResFile(HomeResFile((Handle) fileR));	/* NCSA 2.5 */


/******/

	if ((maskR ==0L) || (GetHandleSize((Handle) maskR) < 9)) {		/* BYU 2.4.7 */
		maskR=(Str255 **)NewHandle(256L);		/* Get a temp handle */
		putln("Making new Mask resource");
		if (maskR==0L) putln("I can't get any space");
		addresource((Handle) maskR, 'STR ', MaskSTR, "Network Mask");
		if ((terr=ResError())!=0) {
			sprintf( &nstring, "Error in addresource. (%d)", terr);
			putln(&nstring);
			}
		}

	HLock((Handle)maskR);								/* Lock it down */
	ptemp=*maskR;								/* a pointer for sanity*/

	GetIText(dMask, (Str255) ptemp);				/* Get the Mask from the Dialog */

	if (mask) { putln("using custom mask");
				cmask=1;
				} else cmask=0;
	(*ptemp)[(*ptemp)[0] + 1] = '\0';			/* terminate for sscanf */
	
/* BYU 2.4.7 - We want the operator specified mask to take precedence 
   over any default settings.
*/
#if 1
	if ((*ptemp)[0] == 8) {									/* BYU 2.4.7 */
		sscanf((char *) ptemp + 1, "%lx", &mynetmask);		/* BYU 2.4.7 */
		cmask=1;											/* BYU 2.4.7 */
	} else {												/* BYU 2.4.7 */
#else
	if (( 1!=sscanf((char *) ptemp + 1, "%lx", &mynetmask))/* || (!mask)*/) {		/* BYU 2.4.7 */
#endif
		(*ptemp)[0] = 0;					/* Make it remain default */
		(*ptemp)[1] = ' ';
		putln( "Default mask used, saved mask cleared....");
		}

	HUnlock((Handle) maskR);
	ChangedResource((Handle) maskR);
	UpdateResFile(HomeResFile((Handle) maskR));
/******/

	DisposDialog(dtemp);						/* Get rid of dialog */

	return(dynam);								/* Return with the status of */
												/* Dynamic or Static IP */
  } /* PromptIP */

/*
 *	Get a dynamic IP Number..... this should be done only if you are Crofted
 */
int DynamIP
  (
	char *ipnum
  )
{
	if (!KIP) {
		putln("You can't use dynamic IP Numbers without Croft!!");
		return(-1);
		}
	putln("Obtaining a dynamic IP Number");

	if (KIPgetdynam(&KIPserver, (long *) ipnum) <0) {
		OtherError("Error obtaining dynamic IP #.","Dynamic addressing not available");
		putln("dynamic IP get failed ");
		return(-1);
		}

	return(0);
}

/*
 *	Register your IP Number..... this need be done only if you are Crofted
 */
int RegIP
  (
	char *ipnum
  )
{
#if 1															/* BYU 2.4.11 */
	if (EtherNet) {												/* BYU 2.4.11 */
		putln("You don't need to register on ethernet....");	/* BYU 2.4.11 */
#else															/* BYU 2.4.11 */
	if (!KIP) {
		putln("You don't need to register if you aren't using Croft....");
#endif															/* BYU 2.4.11 */
		return(0);
		}
	putln("Registering IP Number to the network");
	if (KIPregister(ipnum) <0) {
		putln("Registration failed!!");
		return(-1);
		}
	return(0);
}

void setnetconfigs
  (
	char *ipnum,
	long *netmask
  )
{
	char sbuf[80];
	sprintf(sbuf,"%lx is mask",*netmask);
	putln(sbuf);

	netsetip(ipnum);				/* Here is your number */

	netsetmask((unsigned char *) netmask); /* And your network type */
}

/*
 *	initipnum - Initialize the IP number, and check it and the other wonderful
 *		things associated (mask,ip #, def host). Button forces the PromptIP dialog.
 *
 *  Thanks to Ric Anderson from the University of Arizona for the setvol patches to
 *  make the system folder work right.
 */

int initipnum
  (
	int button
  )
{
	Str255 *tempp,**temph;
	int error=0,dynam=0;
	short refnum;
	long ns;
	char *myDir;
	short myVRef;
	WDPBRec theWD;
	OSErr 	err=0;
	
/*	strncpy (files_name, name, size);
	files_name[size] = 0; */



  /* look for an existing settings file. The usual search path
	for this will include the current folder and the system folder,
	unless they're on different volumes (see tech note 77). */

	myDir = (char *)NewPtr(255);
	setmydir(); /* first, try the application folder */
	SettingsFile=openrfperm("NCSA Telnet Settings",0,fsRdWrShPerm);	/* BYU - Open the Settings file shared. */
	if (SettingsFile == - 1)
	  {
		sysdir(); /* in case it's on a different volume */
		SettingsFile=openrfperm("NCSA Telnet Settings",0,fsRdWrShPerm);	/* BYU - Open the Settings file shared. */
	  } /* if */

	if (SettingsFile == - 1)
		{

		GetVol(myDir,&myVRef);	
		myDir[myDir[0]+2] = 0;		
		strcat(myDir,"System Folder:Preferences");
		myDir[myDir[0]+1] = ':';
		myDir[0] += (strlen("System Folder:Preferences")+1);
		

		putln("the dir is:");
		putln(myDir);

		theWD.ioCompletion = NULL;
		theWD.ioNamePtr = myDir;
		theWD.ioVRefNum = 0;
		theWD.ioWDDirID = 0;
		err = PBHSetVol (&theWD, false);
		SettingsFile=openrfperm("NCSA Telnet Settings",0,fsRdWrShPerm);	/* BYU - Open the Settings file shared. */
		
		}


	DisposPtr(myDir);
	if (SettingsFile == -1 )
	  {
	  /* no settings file anywhere -- create one in the system folder. */
	/*	sysdir(); */
		create("NCSA Telnet Settings", theWorld.sysVRefNum, 'NCSA', 'IPNO');
		createresfile("NCSA Telnet Settings");	/* Make a new one if it is not there .... */
		SettingsFile=openrfperm("NCSA Telnet Settings",0,fsRdWrShPerm);	/* BYU - Open the Settings file shared. */
	  } /* if */
	setmydir();		/* set back to default dir */
	
  /* Initialize the default host */
	if ((defaultd=(Str255 *)NewPtr(256)) ==0L) {
		putln("Oops, no memory at all");
		quit();
		} else
			(*defaultd)[0]=0;							/* Default to no host */

	temph=(Str255 **)GetResource('STR ',HostSTR);
	if (temph!=0L) {
		HLock((Handle) temph);							/* This remains locked */
		movmem( *temph, defaultd,256);
		p2cstr((StringPtr) defaultd);
		HUnlock((Handle) temph);
		} else									/* BYU serial - Use it .... */
			strcpy((char *) defaultd,"");		/* BYU serial - Default to no host */

	if (EtherNet == -99)			/* Return on Driver TCP */
		return(1);
		
	if (!EtherNet)
	  {
		OSErr err;
		err = OpenDriver("\p.MPP", &refnum);
		if (err == 0)
			putln("MPP AOk");
		else
		  {
			DialogPtr dtemp;
/*			short item;											/* BYU 2.4.15 */

			putln("MPP Bad");
		  /* following sequence is copied from atopen in atalk.c */
			if (err == -97 || err == -98)
				ParamText(0L, 0L, 0L,
					"\pYou forgot to turn on AppleTalk in the Chooser");
			else if (err == -192)
				ParamText(0L, 0L, 0L, "\pCouldnt find atpl resource");
			else
				ParamText(0L, 0L, 0L, "\pUnknown Error");
			dtemp = GetNewDialog(302, (Ptr) 0L, (WindowPtr) -1L);
#if 1															/* BYU 2.4.15 */
			DrawDialog(dtemp);									/* BYU 2.4.15 */
			WaitSeconds(5);										/* BYU 2.4.15 */
#else															/* BYU 2.4.15 */
			ModalDialog(0L, &item);
#endif															/* BYU 2.4.15 */
			DisposDialog(dtemp);
/*			quit();												/* BYU 2.4.15 */
		  }
	  /* Check if KIP is the Gateway if so load number */
		if ( KIPfindgate(&KIPserver)>0)
		  {
			putln("Croft Gateway is online!");		/* BYU */
			KIP=1;			/* we have a KIP Croft Gateway */
			KIPgetns(&KIPserver, &ns);
			if (ns !=0) Ssetns((unsigned char *) &ns);
		  }
	  }
	else
		KIP = 0;
  /* Initialize the IP Number */
	temph = (Str255 **)GetResource('STR ',IPnumSTR);
	if (temph!=0L) {
		HLock((Handle) temph);							/* lock for string ref. */
		tempp=*temph;

		(*tempp)[(*tempp)[0] + 1]=0;
		error=decodeIPnum(&(*tempp)[1], myipnum);

		if (error) {
			if (EtherNet) {					/* Dynamic if Ether and no IP Number */
				strncpy(myipnum,"RARP",4);
				dynam=1;
				error=0;
				}
			else if (KIP) {
				DynamIP(myipnum);			/* Dynamic if KIP and no IP number */
				dynam=1;
				error=0;
				}
			else  error=1;				/* Error  if !KIP and  "" ""	   */
			}
		HUnlock((Handle) temph);			/* Get rid of old number */
		}
	else error=1;							/* error set by lack of resource */

						/* Set up our default masking, given the IP number */

	if (userlevel >2) {
		if (!dynam) {
			if (!KIP) error=1;
			else {
				dynam=1;
				DynamIP(myipnum);
				}
			}
		}

	if (!(myipnum[0] & 0x80))
			defmask=0xff000000;						/* Class A */
		else if ( (myipnum[0] & 0xC0 )==0x80)
			defmask=0xffff0000;						/* Class B */
		else if ( (myipnum[0] & 0xC0 )==0xC0)
			defmask=0xffffff00;						/* Class C */

	temph=(Str255 **)GetResource('STR ',MaskSTR);	/* Get the current mask */
	if (temph!=0L) {
		HLock((Handle) temph);						/* Lock for string ref. */
		tempp=*temph;
		(*tempp)[(*tempp)[0] + 1] = '\0';			/* terminate for scanf */
		}
	cmask=1;
#if 1
	if (temph!=0L /*&& tempp[0] == 8*/) {				/* BYU 2.4.7 */
		sscanf((char *) tempp + 1,"%lx",&mynetmask);	/* BYU 2.4.7 */
	} else {											/* BYU 2.4.7 */
#else
	if (temph==0L || tempp[0] != 8 ||							/* BYU 2.4.7 */
		(1!=sscanf((char *) tempp + 1,"%lx",&mynetmask))) {		/* BYU 2.4.7 */
#endif
			mynetmask=defmask;					/* Default masks... */
			cmask=0;
			}

	if (temph!=0L) HUnlock((Handle) temph);		/* Ok, I admit this seq. has to go */

	if (error) putln("error is set");
	if (button) putln("button is set");

	dynamic = dynam;

	if ( (error || button) && userlevel<2) {
		putln("Prompting for IP Number");

		/* if (ResError()!=-192)
			ERRWarn(800);		Can't Load Existing Resource, out of space */

		if ( PromptIP( dynam)) {
			if (EtherNet)
				strncpy(myipnum,"RARP",4);
			else 
				DynamIP(myipnum);
			if (!(myipnum[0] & 0x80))
					defmask=0xff000000;						/* Class A */
				else if ( (myipnum[0] & 0xC0 )==0x80)
					defmask=0xffff0000;						/* Class B */
				else if ( (myipnum[0] & 0xC0 )==0xC0)
					defmask=0xffffff00;						/* Class C */

			if (!cmask) mynetmask=defmask;

			dynamic=1;
			}
		else dynamic=0;
		}
	else if (error) quit();

	setnetconfigs( myipnum,  &mynetmask);
	if (RegIP(myipnum))
		reconfigNetwork(1);
	return(0);
} /* initipnum */

/*
*  special dialog for the driver version.
*  This one only prompts for default host and nothing else.
*  Much of the appearance of the dialog is retained so that the user can switch
*  versions easily.
*/
int driverconf
  (
	void
  )
{
#define GetStrRes(x)	(Str255 **)GetResource('STR ',(x));

	DialogPtr dtemp;
	Str255 *ptemp;
	Str255 **hostR;
	Rect dBox;
	Handle dHand;
	int terr;
	short dItem;
	Str255 **fileR;					/* NCSA 2.5: handle to file name */
	Str255 *ftemp;					/* NCSA 2.5: pointer for sanity */
	
	dtemp=GetNewDialog( GetDefDLOG,(Ptr) 0L,(WindowPtr) -1L);	/* Bring on the box */


	hostR=GetStrRes( HostSTR);		/* Was there a default host */
	fileR=GetStrRes( FileSTR);		/* NCSA 2.5: get capture file name */


	if (fileR!=0L) {							/* NCSA 2.5: handle capture file */
		GetDItem(dtemp,8,&dItem,&dHand,&dBox);	/* NCSA 2.5: get the name */
		HLock((Handle) fileR);					/* NCSA 2.5 */
												/* NCSA 2.5 */
		SetIText(dHand, (Str255) *fileR);		/* NCSA 2.5 */
	/*	SelIText(dtemp,6,0,1000); */			/* NCSA 2.5 */
		HUnlock((Handle) fileR);				/* NCSA 2.5 */
		putln("Reading previous Default Dest. Resource");	/* NCSA 2.5 */
		}										/* NCSA 2.5 */


	if (hostR!=0L) {							/* If So...*/
		GetDItem(dtemp,6,&dItem,&dHand,&dBox);	/* Get the dialog item */
		HLock((Handle) hostR);					/* Lock the string in */

		SetIText(dHand, (Str255) *hostR);		/* Set the item's text to the old 1*/
		SelIText(dtemp,6,0,1000);
		HUnlock((Handle) hostR);				/* Unlock the string */
		putln("Reading previous Default Dest. Resource");
		}
	

	UItemAssign( dtemp, 7, (int (*)()) OutlineItem);
		
	dItem = 3;
	while (dItem> 2)     /* cancel == 1, OK == 2 */
		ModalDialog((ModalFilterProcPtr) modalProc, &dItem);

	if (SettingsFile==-1 || dItem == 2) {
		DisposDialog(dtemp);
		return(0);
		}
		
	if (hostR ==0L) {
		putln("Making new Host resource");
		hostR=(Str255 **)NewHandle(256L);		/* Get a temp handle */
		if (hostR==0L) putln("I can't get any space");
		addresource((Handle) hostR,'STR ',HostSTR,"Default Host");
		if ((terr=ResError())!=0) {
			putln("Error in addresource");
			}
		}


	if (fileR ==0L) {									/* NCSA 2.5 */
		putln("Making new Capture File resource");		/* NCSA 2.5 */
		fileR=(Str255 **)NewHandle(256L);				/* NCSA 2.5 */
		if (fileR==0L) putln("I can't get any space");	/* NCSA 2.5 */
		addresource((Handle) fileR,'STR ',FileSTR,"Capture File");	/* NCSA 2.5 */
		if ((terr=ResError())!=0) {						/* NCSA 2.5 */
			putln("Error in addresource");				/* NCSA 2.5	*/
			}											/* NCSA 2.5 */
		}												/* NCSA 2.5 */



	HLock((Handle) hostR);						/* Lock it down */
	ptemp=*hostR;								/* a pointer for sanity*/	
	GetDItem(dtemp,6,&dItem,&dHand,&dBox);		/* Get the Default Host */
	GetIText(dHand, (Str255) ptemp);
	movmem( ptemp, defaultd,256);				/* Make a copy for later */
	p2cstr((StringPtr) defaultd);		
	HUnlock((Handle) hostR);
	ChangedResource((Handle) hostR);
	UpdateResFile(HomeResFile((Handle) hostR));


	HLock((Handle) fileR);						/* NCSA 2.5 */
	ftemp=*fileR;								/* NCSA 2.5 */	
	GetDItem(dtemp,8,&dItem,&dHand,&dBox);		/* NCSA 2.5 */
	GetIText(dHand, (Str255) ftemp);			/* NCSA 2.5 */
	HUnlock((Handle) fileR);					/* NCSA 2.5 */
	ChangedResource((Handle) fileR);			/* NCSA 2.5 */
	UpdateResFile(HomeResFile((Handle) fileR));	/* NCSA 2.5 */


	DisposDialog( dtemp);

	return(1);
} /* driverconf */


/*********************************************************************/
/*  parse
*   look at the string which has just come in from outside and
*   check for special sequences that we are interested in.
*
*   Tries to pass through routine strings immediately, waiting for special
*   characters ESC and 255 to change modes.
*/

#define STNORM	0
#define EOF		236
#define	SE		240
#define	NOP		241
#define DM		242
#define BREAK	243
#define IP		244
#define AO		245
#define	AYT		246
#define	EC		247
#define EL		248
#define GA		249
#define	SB		250
#define WILLTEL 251
#define WONTTEL 252
#define DOTEL	253
#define DONTTEL 254
#define	IAC		255
#define	SEXECUTE			200
#define	NEGOTIATE			1
#define ESCFOUND 			5
#define IACFOUND 			6

#define BINARY 				0
#define ECHO				1
#define SGA					3
#define STATUS				5
#define TIMING				6
#define	TERMTYP				24
#define GS					29
#define NAWS				31
#define	TERMSPEED			32
#define REMOTEFLOW			33
#define LINEMODE 			34
	#define MODE 1
		#define EDIT     1
		#define TRAPSIG  2
		#define MODE_ACK 4


#define FORWARDMASK 2

#define	substate	tw->substat

void parse
  (
	struct WindRec *tw,
	unsigned char *st,
	int cnt
  )
{
	int i,temptw;
	unsigned char *mark,*orig;
	char parsedat[40];
	char mesg[50];
#ifdef OPTSDEBUG
	char munger[255]; 
#endif






	orig = st;				/* remember beginning point */
	mark = st + cnt;		/* set to end of input string */

/*
* raw mode for debugging, passes through escape sequences and other
* special characters as <27> symbols
*/
	if (tw->termstate == DUMBTYPE) {
		for (i=0; i < cnt; i++,st++)			/* put on screen raw */
			if (*st == 27 || *st > 126) {
				sprintf(parsedat,"<%d>",*st);
				VSwrite(tw->vs,parsedat,strlen(parsedat));	/* send to virtual screen */
			}
			else
				VSwrite(tw->vs,st,1);
	}
	else {

/*
*  traverse string, looking for any special characters which indicate that
*  we need to change modes.
*/
	while (st < mark) {

		switch (tw->telstate) {
			case GS:
			case ESCFOUND:
				if (tw->tektype != -1) {	/* NCSA 2.5: we'll allow the TEK */
				if ((*st == 12) || (tw->telstate == GS))	/* esc-FF */
				{
					if ((tw->termstate == VTEKTYPE) || (!tw->tekclear))
					{
						if (tw->termstate == VTEKTYPE)
							putln("Entering Tek mode");
						else if (tw->curgraph > -1)
							detachGraphics(tw->curgraph);
						if (tw->curgraph <=  -1)
						{
							temptw = VGnewwin(1,tw->vs);
							if (temptw > -1)
							{
								tw->curgraph = temptw;

								VGgiveinfo(temptw);
								RGattach(temptw,tw->vs,tw->name);
							}
							else
								tw->telstate = STNORM;
						}
						if (tw->telstate != STNORM)
							tw->termstate = TEKTYPE;
					}
					if (tw->telstate == GS)
					{
						st++;
						VGwrite(tw->curgraph,"\035",1);
					}
					else if (tw->telstate != STNORM)
						VGwrite(tw->curgraph,"\037\033\014",3);
					tw->telstate = STNORM;
					break;
				}
				}		/* NCSA 2.5 */
			
				if (*st == '^')				/* ESC- ^ */
				{
					tw->termstate = RASTYPE;
					tw->telstate = STNORM;
					VRwrite("\033^",2);		/* Put it through */
					orig = ++st;
					break;
				}
				
				if (tw->termstate == TEKTYPE)
					VGwrite(tw->curgraph,"\033",1);
				else if (tw->termstate  == RASTYPE)
					VRwrite("\033",1);
				else
					VSwrite(tw->vs,"\033",1);	/* send the missing ESC */
				tw->telstate = STNORM;
				break;
			case IACFOUND: 		/* telnet option negotiation */
				if (*st == 255) {		/* real data = 255 */
					st++;				/* real 255 will get sent */
					tw->telstate = STNORM;
					break;
				}
				if ( 239 < *st ) {
					tw->telstate = *st;		/* by what the option is */
					st++;
					break;
				}
				putln("Strange telnet option!");
				tw->telstate = STNORM;
				orig=st;
				break;

			case EOF:
#ifdef OPTSDEBUG
				sprintf(munger,"RECV: %s",telstates[tw->telstate - SE]);
				putln(munger); 
#endif
				orig=st;
				tw->telstate=STNORM;
				
				break;

			case EL:				/* thanx Quincey!!! */
			case EC:
			case AYT:
			case AO:
			case IP:
			case BREAK:
			case DM:
			case NOP:
			case SE:
#ifdef OPTSDEBUG
				sprintf(munger,"RECV: %s",telstates[tw->telstate - SE]);
				putln(munger); 
#endif
				tw->telstate = STNORM;
				orig=st;

			case GA:
				orig=st;
				tw->telstate = STNORM;
				break;
            case DOTEL:
#ifdef OPTSDEBUG
				sprintf(munger,"RECV: %s %s",telstates[tw->telstate-SE],teloptions[*st]);
				putln(munger); 
#endif

				switch( *st) {
					case  SGA:		/* Sure we'll supress GA */
						if (!tw->Isga)
							{
							tw->Isga=1;
							sprintf(parsedat,"%c%c%c",255,WILLTEL,*st);
							netpush(tw->port);
							netwrite(tw->port,parsedat,3);
							}
						tw->telstate = STNORM;
						orig = ++st;
						break;
					case TERMTYP:		/* And we'll even tell you about ourselves */
						if (!tw->Ittype)
							{
							tw->Ittype=1;
							sprintf(parsedat,"%c%c%c",255,WILLTEL,*st);
							netpush(tw->port);
							netwrite(tw->port,parsedat,3);
							}
						tw->telstate = STNORM;
						orig = ++st;
						break;

					case  NAWS:			/* NCSA: sure, I like changing the window size! */
						tw->naws =1;									/* NCSA: this session is now NAWS */
						sprintf(parsedat,"%c%c%c",255,WILLTEL,*st);		/* NCSA: reply, we will to NAWS */
						netpush(tw->port);								/* NCSA */
						netwrite(tw->port,parsedat,3);					/* NCSA: send it out */
#if 1
						sprintf(parsedat,"%c%c%c%c%c%c%c%c%c",IAC,SB,	/* BYU 2.4.16 */
							NAWS,(char)0,(unsigned char)tw->width,		/* BYU 2.4.16 */
							(char)0,(unsigned char)tw->rows,IAC,SE);	/* BYU 2.4.16 */
						netpush(tw->port);								/* BYU 2.4.16 */
						netwrite(tw->port,parsedat,9);					/* BYU 2.4.16 */
#endif
						tw->telstate = STNORM;							/* NCSA */
						orig = ++st;									/* NCSA */
						break;											/* NCSA */

					case LINEMODE:  /* Sure I'll do line mode... */
						if (tw->lineAllow) 
							{
							sprintf(parsedat,"%c%c%c",IAC,WILLTEL,*st++);
							putln("*** using linemode");
							
							netwrite(tw->port,parsedat,3);
							
							sprintf(parsedat,"%c%c%c%c",IAC,SB,LINEMODE,SLC);
							netwrite(tw->port,parsedat,4);
							putln("SENT: IAC SB LINEMODE SLC");
	
							for (i=1; i<19; i++){
								if (tw->slc[i]==-1)
									{
									sprintf(parsedat,"%c%c%c",i,SLC_NOSUPPORT,0);
#ifdef OPTSDEBUG
									sprintf(munger,"     %s NO_SUPPORT 0",LMoptions[i]);
#endif
									}
								else
									{
									sprintf(parsedat,"%c%c%c",i,SLC_CANTCHANGE,(char)tw->slc[i]);
#ifdef OPTSDEBUG
									sprintf(munger,"     %s CANTCHANGE %i",LMoptions[i],(int)tw->slc[i]);
#endif
									}
#ifdef OPTSDEBUG
								putln(munger);
#endif
								netwrite(tw->port,parsedat,3);
								}
	
							putln("SENT: IAC SE");
							sprintf(parsedat,"%c%c",IAC,SE);
							netwrite(tw->port,parsedat,2);
							}
							
						else 
							{
							sprintf(parsedat,"%c%c%c",IAC,WONTTEL,LINEMODE);
							netwrite(tw->port,parsedat,3);

							putln("*** linemode not allowed");
							}

						break;
					default:				/* But, we won't do .... */
                		sprintf(parsedat,"%c%c%c",255,WONTTEL,*st++);
						putln("didnt do option");
                		netwrite(tw->port,parsedat,3);  
						break;
					}
                tw->telstate = STNORM;
                orig = st;
                break;

            case DONTTEL:
#ifdef NOTNEEDED
				switch( *st) {
					case  3:		/* Sure we'll supress GA */
						if (!tw->Isga)
							break;
						tw->Isga=0;
						sprintf(parsedat,"%c%c%c",255,WONTTEL,*st++);
						netpush(tw->port);
						netwrite(tw->port,parsedat,3);
						break;
					case 24:		/* And we'll even tell you about ourselves */
						if (!tw->Ittype)
							break;
						tw->Ittype=0;
						sprintf(parsedat,"%c%c%c",255,WONTTEL,*st++);
						netpush(tw->port);
						netwrite(tw->port,parsedat,3);
						break;
					
					default: 
						st++; 	/* this data is garbage */
						break;
					}
#endif

#ifdef OPTSDEBUG
					sprintf(munger,"RECV: %s %s",telstates[tw->telstate-SE],teloptions[*st]);
					putln(munger); 
#endif
					tw->telstate = STNORM;
                	orig = ++st;
                break;

            case WILLTEL:
#ifdef OPTSDEBUG
				sprintf(munger,"SENT: %s %s",telstates[tw->telstate-SE],teloptions[*st]);
				putln(munger); 
#endif

                tw->telstate = STNORM;
                switch(*st++) {
                    case 1:             /* Echo on the other end*/
						if (!tw->echo)
							break;
						tw->echo = 0;	/* Ok, in that case they can echo... */
						changeport(scrn,scrn);
                        sprintf(parsedat,"%c%c%c",255,DOTEL,1);
						netpush(tw->port);
                        netwrite(tw->port,parsedat,3);  /* refuse it */
						break;
					case 3:				/* Supress GA */
						if (tw->Usga)
							break;
						tw->Usga = 1;	/* Go Ahead and supress GA */
                        sprintf(parsedat,"%c%c%c",255,DOTEL,3);
						netpush(tw->port);
                        netwrite(tw->port,parsedat,3);  /* refuse it */
						break;
					case TIMING:				/* Timing Mark */
						tw->timing = 0;
						break;
                    default:
                        sprintf(parsedat,"%c%c%c",255,DONTTEL,*(st-1));
                        netwrite(tw->port,parsedat,3);  /* refuse it */
                }
                orig = st;
                break;

            case WONTTEL:
#ifdef OPTSDEBUG
				sprintf(munger,"SENT: %s %s",telstates[tw->telstate-SE],teloptions[*st]);
				putln(munger); 
#endif
                tw->telstate = STNORM;
                switch(*st++) {         /* which option? */
                    case ECHO:             /* echo */
						if (tw->echo)
							break;
                        tw->echo = 1;	/* Ok, I will echo if I have to... */
						changeport(scrn,scrn);
                        sprintf(parsedat,"%c%c%c",IAC,DONTTEL,ECHO);
						netpush(tw->port);
                        netwrite(tw->port,parsedat,3);  /* refuse it */
                        break;
					case 3:
						if (!tw->Usga)
							break;
						tw->Usga = 0;
                        sprintf(parsedat,"%c%c%c",255,DONTTEL,*(st-1));
						netpush(tw->port);
                        netwrite(tw->port,parsedat,3);  /* refuse it */
						break;
					case TIMING:				/* Timing Mark */
						tw->timing = 0;
						break;
                    default:
                        break;
                }
                orig = st;
                break;

			case SB:
				tw->telstate = NEGOTIATE;
				orig=st;
				i = substate=0;				/* Defined for each */
				break;

			case NEGOTIATE:
				if (substate <200) {
					switch( *st) {
						case IAC:
							if (*(st+1) ==IAC) 
								{
								parsedat[i++]=*st++;
								parsedat[i++]=*st++;
								}
							else 
								{
								parsedat[i]='\0';
								substate=*st++;
								}							
							break;
						default:
							parsedat[i++]=*st++;
							break;
						}
					} else {
					switch( substate) {
						case IAC:
							substate=*st++;
							if (substate==SE) {
								switch( parsedat[0]) {
								case TERMTYP:
									if (parsedat[1]==1) {
										char s[50];


#ifdef OPTSDEBUG
										sprintf(munger,"RECV: SB TERMINAL-TYPE SEND\r\nSEND: SB TERMINAL-TYPE IS %s\r\n",TermType);
										putln(munger); 
#endif
										netpush(tw->port);
										netwrite(tw->port,"\377\372\030\000",4);
										netpush(tw->port);
										sprintf(s,"%s\377\360",TermType);
                        				netwrite(tw->port, s, strlen(s));
										}
									break;
/* this is the new line-mode stuff */

								
										case LINEMODE:
											switch(parsedat[1]){
												char s[50];

												case MODE:

													if ((parsedat[2] & EDIT) &&tw->lineAllow)
														tw->lmflag=1;
													/*else
														tw->lmflag=0; */
														
											
													sprintf(mesg,"value of tw->lmflag: %i",(int)tw->lmflag);
													putln(mesg);
													putln("SENT: IAC SB LINEMODE MODE");

													sprintf(s,"%c%c%c%c",IAC,SB,LINEMODE,MODE);
													netwrite(tw->port,s,4);
													sprintf(s,"%c%c%c",parsedat[2]|MODE_ACK,IAC,SE);
													netwrite(tw->port,s,3); 
#ifdef OPTSDEBUG
													sprintf(munger,"     %i IAC SE",(int)(parsedat[2]|MODE_ACK));
													putln(munger); 
#endif
													break;
												case DOTEL:
													netwrite(tw->port,"\377\372\042",3);
													sprintf(s,"%c\002\377\360",WONTTEL);
													netwrite(tw->port,s,strlen(s));
													break;

												case WILLTEL:
													netwrite(tw->port,"\377\372\042",3);
													sprintf(s,"%c\002\377\360",DONTTEL);
													netwrite(tw->port,s,strlen(s));
													break;


												case SLC:
#ifdef OPTSDEBUG
													sprintf(munger,"RECV: SB LINEMODE SLC");
													putln(munger);
#endif
													for(i=2;(parsedat[i]!='\0') && (parsedat[i]!=IAC); i+=3) 
														{
#ifdef OPTSDEBUG
														if(parsedat[i+1] & SLC_AWK)
															sprintf(munger,"     %s %s|AWK %d",LMoptions[parsedat[i]],LMflags[parsedat[i+1] & SLC_LEVELBITS],parsedat[i+2]);
														else
															sprintf(munger,"     %s %s %d",LMoptions[parsedat[i]],LMflags[parsedat[i+1] & SLC_LEVELBITS],parsedat[i+2]);
														putln(munger);
#endif
														if ((unsigned char)(parsedat[i+2])==IAC) i++;

														}	/* end for */
					
													/* First check to see if we need to reply */
													for (i=2;(parsedat[i]!='\0') && (parsedat[i]!=IAC); i+=3)
														{
														if (!(parsedat[i+1] & SLC_AWK)) break;
														if ((unsigned char)(parsedat[i+2])==IAC) i++;
														}
	
													/* if we do then send a reply */
													if ((parsedat[i]!=IAC) && (parsedat[i]!='\0'))
														{
														sprintf(s,"%c%c%c%c",IAC,SB,LINEMODE,SLC);
														netwrite(tw->port,s,4);
														putln("SENT: IAC SB LINEMODE SLC");
		

#ifdef NEWSLC
														for (i=2; (parsedat[i]!='\0') && (parsedat[i]!=IAC); i+=3)
															{
															if (!(parsedat[i+1] & SLC_AWK))		/* no response of ACK set */
																{
																if (parsedat[i+1] != SLC_NOSUPPORT)
																	{
																	sprintf(s,"%c%c%c",parsedat[i],SLC_NOSUPPORT,0);
#ifdef OPTSDEBUG
																	sprintf(munger,"     %s NOSUPPORT 0",LMoptions[parsedat[i]]);
#endif
																	}
																else		/* Acknowledge the No_Support case */
																	{
																	sprintf(s,"%c%c%c",parsedat[i],SLC_AWK|SLC_NOSUPPORT,(char)0);
#ifdef OPTSDEBUG
																	sprintf(munger,"     %s NOSUPPORT|AWK 0",LMoptions[parsedat[i]]);
#endif
																	}																
#ifdef OPTSDEBUG
																putln(munger);
#endif
																netwrite(tw->port,s,3);
																}
																if ((unsigned char)(parsedat[i+2])==IAC) i++;
															}

#else
														for (i=2; (parsedat[i]!='\0') && (parsedat[i]!=IAC); i+=3)
															{
															if (!(parsedat[i+1] & SLC_AWK))
																{
																if (tw->slc[parsedat[i]]==-1)
																	{
																	sprintf(s,"%c%c%c",i,SLC_NOSUPPORT,0);
#ifdef OPTSDEBUG
																	sprintf(munger,"     %s %s 0",LMoptions[i],LMflags[parsedat[i+1] & SLC_LEVELBITS]);
#endif
																	}
																else
																	{
																	sprintf(s,"%c%c%c",i,SLC_CANTCHANGE,(char)tw->slc[parsedat[i]]);
#ifdef OPTSDEBUG
																	sprintf(munger,"     %s %s 0",LMoptions[i],LMflags[parsedat[i+1] & SLC_LEVELBITS]);
#endif
																	}																
#ifdef OPTSDEBUG
																putln(munger);
#endif
																netwrite(tw->port,s,3);
																if (parsedat[i+2]==IAC) i++;
																}
															}
															
#endif
														sprintf(s,"%c%c",IAC,SE);
														netwrite(tw->port,s,2);
														}

												/* otherwise just exit */
													break;

												default:
													break;

												}
										break;

/* end of all the new line-mode shit */								
								
								
								default:
									break;
								}
							}
							orig=st;
							tw->telstate=STNORM;
							break;
						default:
							orig=st;
							tw->telstate=STNORM;
							break;
						}
					}

				break;
            default:
                tw->telstate = STNORM;
                break;
		}

/*
* quick scan of the remaining string, skip chars while they are
* uninteresting
*/
		if (tw->telstate == STNORM) {
/*
*  skip along as fast as possible until an interesting character is found
*/
			if (!tw->eightbit) {											/* BYU 2.4.10 */
				while (st < mark) {											/* BYU 2.4.10 */
					if (*st == IAC) 										/* BYU 2.4.10 */
						break;												/* BYU 2.4.10 */
					else {													/* BYU 2.4.10 */
						*st &= 0x7f; 										/* BYU 2.4.10 */
						if (*st == ESC  || *st == GS) 						/* BYU 2.4.10 */
							break;											/* BYU 2.4.10 */
						st++;												/* BYU 2.4.10 */
				}	}														/* BYU 2.4.10 */
			} else 															/* BYU 2.4.10 */
				while (st < mark && *st != ESC  && *st < 128 && *st != GS) 	/* BYU 2.4.10 */
					st++; 													/* BYU 2.4.10 */
/*
*  send the string where it belongs
*/
			if (!tw->timing) {
				if (tw->termstate == TEKTYPE) {
					int i;
					
					i = VGwrite( tw->curgraph,orig,  st-orig);
					if (i < (st - orig)) {
						detachGraphics(tw->curgraph);
						st = orig + i;
						putln("From Tek to VS");
						}
					}
				else if (tw->termstate == RASTYPE) {
					int i;
					
					i= VRwrite( orig, st-orig);
					if (i <(st-orig)) {
						tw->termstate = VTEKTYPE;
						st = orig +i;				/* Next char to parse */
						putln("From VR to VS");
						}
					}
				else 
					VSwrite( tw->vs,orig,st-orig);	/* send to virtual VT102 */
				}

			orig = st;				/* forget what we have sent already */

			if (st < mark)
			switch (*st) {
				case 255:			/* telnet IAC */
					tw->telstate = IACFOUND;
					st++;
					break;
				case GS:
					if (tw->telstate != GS)
					{
#if 0	/* BYU */
						putln("Hey, were here @ GS!!!");
#endif
						tw->telstate = GS;
					}
					else
						tw->telstate = STNORM;
					st++;
					break;
					
				case ESC:			/* ESCape code */
					if (st == mark-1 || *(st+1) == 12 || *(st+1) == '^' ) {
						tw->telstate = ESCFOUND;
					}
					st++;			/* strip or accept ESC char */

					break;
#ifdef WORKSOLD
				default:
					if (*st > 127) {
						putln("Strange char > 128!");
						(*st++)&=0x7f;	/* NVT Ascii says I can... */
				      if (st==mark) 	/*new addition */
         				 VSwrite(tw->vs,orig,1);
#endif
				default:
					if (*st++ > 127) {
/*						putln("Strange char > 128!");		/* BYU 2.4.10 */
					/*	(*st++)&=0x7f;*/	/* NVT Ascii says I can... */
				      if (st==mark) 	/*new addition */
         				 VSwrite(tw->vs,orig,1);


					}
					break;
			}

		}

	}  /* end while */
	}
} /* parse */

int VGalive
  (
	int dnum
  )
{
	int i;

	i=0;
	while((i<numwindows) && (dnum!=screens[i].curgraph)) i++;
	if (i<numwindows) {
		return(1);
		}
	else {
		i=0;
		while ((i<graphs) && (dnum!=oldgraph[i])) i++;
		if (i<graphs)
			return(1);
		}
	return(0);
}

void destroyGraphics
  (
	int dnum
  )
{
	int i;

	i=0;
	while((i<numwindows) && (dnum!=screens[i].curgraph)) i++;
	if (i<numwindows) {
		screens[i].curgraph=-1;
		screens[i].termstate=VTEKTYPE;
		screens[i].enabled=1;
		}
	else {
		i=0;
		while ((i<graphs) && (dnum!=oldgraph[i])) i++;
		while (i<(MaxGraph-1))
			oldgraph[i]=oldgraph[++i];			/* Bump everyone down one slot */
		graphs--;								/* One less graph to feed */
		}
	VGclose( dnum);
}

int isHFS
  (
	void
  )
{
	return
		HFS;
}

FindByVG(vg)
int vg;
{
	int i=0;

	while((i<numwindows) && (vg!=screens[i].curgraph)) i++;
	if (i>=numwindows) return(-1);
	return(i);
}

void TekEnable
  (
	int vg
  )
{
	int change;

	change=FindByVG( vg);
	if (change>=0)
		screens[change].enabled=1;
}

void TekDisable
  (
	int vg
  )
{
	int change;

	change=FindByVG( vg);
	if (change>=0)
		screens[change].enabled=0;
}

pascal void OutlineItem( dlog, itm)
DialogPtr dlog;
short itm;
{
	Rect ibox;
	char **ihndl;
	short typ;
	int item=itm;
	
	GetDItem( dlog, item, &typ, &ihndl, &ibox);
	PenSize( 3,3);
	InsetRect( &ibox, -4,-4);
	FrameRoundRect( &ibox, 16,16);
}

pascal void VersionNumber( dlog, itm)
DialogPtr dlog;
short itm;
{
	Rect ibox;
	char **ihndl;
	short typ;
	int item=itm;

	GetDItem( dlog, item, &typ, &ihndl, &ibox);
	TextFont( 3);
	TextSize( 9);
	MoveTo( ibox.left+((ibox.right-ibox.left)/2)-(stringwidth( VERSION)/2), ibox.bottom-2);
	drawstring( VERSION );
}


char *rindex(s,c)
	char *s,c;
	{
	char *p;
	
	p = NULL;
	
	while (*s) {
		if (*s == c)
			p = s;
		s++;
		}

	return(p);

}



void DoTheMenuChecks()
{
	short	active;
	short	windownum;
	
	if (numwindows>0)
		{
		EnableItem( myMenus[Conn],0);
		DrawMenuBar();
		}

	else 
		{
		DisableItem(myMenus[Conn],0);
		DrawMenuBar();
		}
		
	active =0;
	
	for (windownum=0;windownum<numwindows;windownum++)
		if (!screens[windownum].active) active++;
		
	if (active<2)	
		DisableItem(myMenus[Conn],COnext);
	else EnableItem(myMenus[Conn],COnext);

	if (!active)
		{
/*		DisableItem(myMenus[Edit],EDcopy);
		DisableItem(myMenus[Edit],EDcopyt); */
		DisableItem(myMenus[Edit],EDpaste);
		DisableItem(myMenus[Emul],0);
		DrawMenuBar();
		}
	else 
		{
/*		EnableItem(myMenus[Edit],EDcopy);
		EnableItem(myMenus[Edit],EDcopyt); */
		EnableItem(myMenus[Edit],EDpaste);
		EnableItem( myMenus[Emul],0);
		DrawMenuBar();
		}
				
}