[comp.sources.amiga] v89i186: vt100 - terminal emulator v2.9, Part09/09

page%swap@Sun.COM (Bob Page) (10/20/89)

Submitted-by: acs@pccuts.pcc.amdahl.com (Tony Sumrall)
Posting-number: Volume 89, Issue 186
Archive-name: comm/vt100r29.9

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	vt100.h
#	vt100.init
#	window.c
#	xmodem.c
# This is archive 9 of a 9-part kit.
# This archive created: Thu Oct 19 22:30:35 1989
echo "extracting vt100.h"
sed 's/^X//' << \SHAR_EOF > vt100.h
X/*********************************************************************
X *  a terminal program that has ascii and xmodem transfer capability
X *			:ts=8
X *
X *	v2.9 ACS - See change summary.
X *	v2.8a 880331 ACS - Update title to 2.8A.
X *	v2.7 870825 ACS - See README.
X *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
X *	v2.5 870214 DBW - more additions (see readme file)
X *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
X *	v2.3 861101 DBW - minor bug fixes
X *	v2.2 861012 DBW - more of the same
X *	v2.1 860915 DBW - new features (see README)
X *	     860823 DBW - Integrated and rewrote lots of code
X *	v2.0 860809 DBW	- Major release.. LOTS of changes
X *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
X *	v1.0 860712 DBW	- First version released
X *
X *  use esc to abort xmodem transfer
X *
X *  written by Michael Mounier
X *  new version by Dave Wecker 860621
X ********************************************************************/
X
X/********* major version (used for title of terminal window) *********/
X#define	VERSION	"VT100 (V2.9 ACS 891003) Terminal Window"
X
X/*********** ########  define the compiler type here ######## ********/
X#define	LATTICE	0
X#define MANX	1
X
X/*  compiler directives to fetch the necessary header files */
X#include <exec/types.h>
X#include <exec/exec.h>
X#include <intuition/intuition.h>
X#include <intuition/intuitionbase.h>
X#include <graphics/gfxbase.h>
X#include <graphics/gfx.h>
X#include <graphics/text.h>
X#include <graphics/regions.h>
X#include <graphics/copper.h>
X#include <graphics/gels.h>
X#include <devices/serial.h>
X#include <devices/keymap.h>
X#include <devices/inputevent.h>
X#include <devices/audio.h>
X#include <hardware/blit.h>
X
X			/* for Lattice you may have to change these with: */
X#include <stdio.h>	/* #include <lattice/stdio.h> and */
X#include <ctype.h>	/* #include <lattice/ctype.h>	 */
X
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <devices/timer.h>
X
X#if LATTICE
X#include <stdlib.h>
X#include <string.h>
X#include <proto/exec.h>
X#include <proto/graphics.h>
X#include <proto/intuition.h>
X#include <proto/dos.h>
X#include <proto/timer.h>
X#endif
X
X#if AREXX
X#include <rexx/rxslib.h>
X#include <rexx/storage.h>
X#endif /* AREXX */
X
X#if MANX
X#include <functions.h>
X#undef NULL
X#define   NULL   ((void *)0)
X#endif /* MANX */
X
X#define INTUITION_REV 1L
X#define GRAPHICS_REV  1L
X
X/* things for xmodem send and recieve */
X#define GOODREAD    0
X#define TIMEOUT	    1
X#define USERABORT   2
X#define SECSIZ   0x80
X#define TTIME_SHORT 5		/* number of seconds for short timeout */
X#define TTIME_LONG  50		/* number of seconds for long  timeout */
X#define TTIME_KERMIT 10		/* number of seconds for KERMIT timeout*/
X#define MAXLONGPKS 1000		/* Maximum long msgpkt size */
X#define BufSize  0x1080		/* Text buffer for XMODEM */
X#define ERRORMAX 10		/* Max errors before abort */
X#define RETRYMAX 10		/* Maximum retrys before abort */
X#define SOH      1		/* Start of sector char */
X#define EOT      4		/* end of transmission char */
X#define ACK      6		/* acknowledge sector transmission */
X#define NAK      21		/* error in transmission detected */
X
X#define FILEMAX 6	/* number of file menu items */
X#define MODEMAX 4	/* number of mode menu items */
X#define EXTMAX 10	/* number of external xfer pgms allowed */
X#define COMMAX 4	/* number of communication sub menus */
X#define RSMAX 5		/* speed menu items */
X#define PARMAX 5	/* parity items */
X#define XFMAX 4		/* transfer mode items */
X#define SCRIPTMAX 3	/* script menu items */
X#define UTILMAX 12	/* utility menu */
X#define MAXMENU 4	/* total number of menu entries */
X
X#define MAXGADSTR 80	/* Max size of prompts and inputs */
X
X#define FSF_REVERSE 256	/* fake font style to flag INVERSVID mode */
X
X#define FONTNAMESIZE	40
X#define FONTSUFFIX	".font"
X#define MAXFONTVARLEN	34	/* 40 minus sizeof(".font") */
X
Xextern char myfontname[];
X
X#define SERNAMESIZE	80
X
Xextern char mysername[];
X
X
X/*   Structure to hold the external xfer program names and command strings */
Xstruct ExternalXfer {
X    char *dispname;		/* Display name - shown on menu */
X    char *downname;		/* downcased name for cmd_short() */
X    char *send;			/* Command string to use for send */
X    char *receive;		/* Command string to use for receive */
X    char cmdkey;		/* Command key equivalent */
X};
X
Xextern struct ExternalXfer *(ExtXfer[EXTMAX]);	/* Defined in vt100.c */
Xextern int NumExts;				/* Number of ExtXfers */
X
X/* things for script support */
X
X#define GOTOLABEL   1
X#define	NEXTCOMMAND 0
X#define ONCOMMAND   2
X
X#define	WAIT_TIMER  2
X#define WAIT_STRING 1
X
X/* exe_cmd return values */
X#define CMDOK		0	/* Command OK				*/
X#define CMDWARN		5	/* Command issued WARNING msg		*/
X#define CMDNF		10	/* Command Not Found			*/
X#define CMDBS		11	/* Bad State (e.g. INIT only)		*/
X#define CMDFAIL		13	/* Command failed			*/
X
X/* things for 'beep' support */
X#define BEEPSIZE    10L
X#define BEEPFREQ    1000L
X#define COLORCLOCK  3579545L
X
X/* things for MENUPICK support */
X#define REDOFILE	1
X#define REDOCOMM	2
X#define REDOUTIL	4
X
Xextern struct	MsgPort *CreatePort();
X
Xextern int		CmdFromRexx;	/* Command came from the AREXX port	*/
X
X#if AREXX
Xextern struct RexxMsg *CreateRexxMsg();
Xextern STRPTR	*CreateArgstring();
Xextern struct MsgPort	*FromRexxPort;	/* Port we receive AREXX msgs on	*/
X
X#define HOSTNAMEROOT "VT100-"
X
X/*   Indices into rexxerrmsgs[] in init.c  */
X
X#define NORXLIB		1		/* No AREXX library		*/
X#define NORXPORT	2		/* No AREXX port		*/
X#define NORXMSG		3		/* Can't create AREXX message	*/
X#define NOHOSTMEM	4		/* Can't get memory for HostName*/
X#define HAVEVT100PORT	5		/* VT100 port already exists	*/
X#define NOPORTMEM	6		/* Can't get mem for a port	*/
X
Xextern char *rexxerrmsgs[];		/* in init.c			*/
Xextern int makerexxport();		/* in init.c			*/
X
Xextern char		*HostName;	/* Our host port name for AREXX		*/
Xextern char		*ForwardPortName; /* Port to which to forward data	*/
Xextern int		forwarding;	/* Flag to indicate if we should fwd	*/
X#endif /* AREXX */
X
X#if MANX
Xextern char	*malloc(),*strcpy(),*fgets();
X#endif /* MANX */
X
Xextern long	ftell();
X
Xextern int	multi;			/* flags multi file transfers */
Xextern int	server;
Xextern char     *bufr;			/* Buffer that XMODEM uses */
Xextern int	fd, timeout, ttime;
Xextern long	bytes_xferred;
Xextern char	MyDir[60];
Xextern BPTR	StartLock;
Xextern struct	IntuitionBase *IntuitionBase;
Xextern struct	GfxBase *GfxBase;
Xextern struct	Library *DiskfontBase;
X
X#if AREXX
Xextern struct RxsLib *RexxSysBase;
X#endif /* AREXX */
X
Xextern struct	TextAttr myattr;
Xextern struct	TextFont *myfont;
Xextern struct	NewScreen NewScreen;
Xextern struct	NewWindow NewWindow;
Xextern struct	NewWindow NewReqWindow;
Xextern struct	Screen *myscreen;
Xextern struct	Window *mywindow;
Xextern struct	Window *reqwindow;
Xextern struct	ViewPort *myviewport;
Xextern struct	RastPort *myrastport;
Xextern struct	IntuiMessage *NewMessage;
Xextern struct	Preferences  *Prefs;
Xextern char	InpBuf[80],UndoBuf[80],Prompt[80];
Xextern struct	StringInfo mystrinfo;
Xextern struct	Gadget     mystrgad;
Xextern struct	IntuiText  donetxt;
Xextern struct	Gadget	   mydonegad;
Xextern struct	IntuiText  mystrtxt;
Xextern struct	Requester  myrequest;
Xextern int	numreqs;
Xextern int	reqwinup;
Xextern struct	MenuItem FileItem[FILEMAX];
Xextern struct	IntuiText FileText[FILEMAX];
Xextern struct	MenuItem ModeItem[MODEMAX+EXTMAX];
Xextern struct	IntuiText ModeText[MODEMAX+EXTMAX];
Xextern struct	MenuItem CommItem[COMMAX];
Xextern struct	IntuiText CommText[COMMAX];
Xextern struct	MenuItem RSItem[RSMAX];
Xextern struct	IntuiText RSText[RSMAX];
Xextern struct	MenuItem ParItem[PARMAX];
Xextern struct	IntuiText ParText[PARMAX];
Xextern struct	MenuItem XFItem[XFMAX];
Xextern struct	IntuiText XFText[XFMAX];
Xextern struct	MenuItem ScriptItem[SCRIPTMAX];
Xextern struct	IntuiText ScriptText[SCRIPTMAX];
Xextern struct	MenuItem UtilItem[UTILMAX];
Xextern struct	IntuiText UtilText[UTILMAX];
Xextern struct	Menu menu[MAXMENU];
Xextern struct	timerequest Timer, Script_Timer;
Xextern struct	MsgPort *Timer_Port, *Script_Timer_Port;
Xextern struct	IOExtSer *Read_Request;
Xextern char	*rs_in;
Xextern struct	IOExtSer *Write_Request;
Xextern char	rs_out[2];
Xextern int	x,y,curmode;
Xextern int	Xsize, MINX,MAXX,Ysize,MINY,MAXY,BaseLine,top,bot,savx,savy;
Xextern int	savmode,nlmode,alt,savalt,a[2],sa[2];
Xextern int	inesc,inctrl,private,badseq,maxcol;
Xextern struct	IOAudio Audio_Request;
Xextern struct	MsgPort *Audio_Port;
Xextern UBYTE	*BeepWave;
Xextern UBYTE	Audio_AllocMap[4];
Xextern int	p_baud,p_screen,p_interlace,p_depth,p_buffer,p_wbcolors;
Xextern int	p_foreground,p_background,p_bold,p_cursor,p_lines,p_mode;
Xextern int	p_parity,p_volume,p_wrap,p_echo,p_keyapp,p_curapp,p_bs_del;
Xextern int	p_xbeep, p_xproto, p_convert,p_autochop, p_kmaxpack, p_unit;
Xextern int	p_fontsize, p_shared, p_mouse_up, p_mouse_down;
Xextern char	p_keyscript;
Xextern long	p_break;
Xextern char	*p_font, *p_device, *p_f[11],*p_F[10];
Xextern int	script_on;
Xextern int	script_wait;
Xextern int	doing_init;
X
X/* vt100.c */
Xextern int  do_send(),do_capture();
Xextern void cleanup();
Xextern ULONG handle_menupick();
Xextern void setserpar(), setserbaud(), setparams(), redoutil(), redofile(),
X	    redocomm();
X
X/* init.c */
Xextern void InitDevs(),InitFileItems(),InitCommItems(),
X	 InitScriptItems(),InitUtilItems(),InitMenu();
Xextern char *InitDefaults();
Xextern int maxrows;	/* number of scan lines available */
X
X/* window.c */
Xextern	void	swap_bs_del(),req(),emits(),emit(),emitbatch(),cursorflip();
Xextern	int	toasc();
Xextern void	ScrollInfoMsg(), InfoMsgNoScroll(), InfoMsg1Line(),
X		InfoMsg2Line();
X
X/* xmodem.c */
Xextern	void sendchar(),sendstring(),sendbreak(),multi_xfer(),
X	No_XON(),Do_XON();
Xextern	int  readchar(),XMODEM_Read_File(),XMODEM_Send_File();
X
X/* remote.c */
Xextern	void doremote(),doindex(),doctrl(),doesc(),doerase();
X
X/* kermit.c */
Xextern	int	doksend(), dokreceive();
Xextern	void	encode(), decode(), rpar(), spar(), saybye();
X
X/* script.c */
Xextern int	script_start(), chk_script(),
X		do_script_cmd();
Xextern char	*next_wrd(), *tostring();
Xextern int	exit_script(), do_ext();
X
X		/* init commands */
Xextern int	cmd_bkg(), cmd_bold(), cmd_buf(), cmd_cursor(), cmd_depth(),
X		cmd_device(), cmd_display(), cmd_fore(), cmd_font(),
X		cmd_fonts(), cmd_inter(), cmd_lines(), cmd_screen(),
X		cmd_unit(), cmd_volume(), cmd_wb(), cmd_null(),
X
X		/* script commands */
X		cmd_as(), cmd_beep(), cmd_cap(), cmd_cd(), cmd_delay(),
X		cmd_goto(), cmd_goto(), cmd_kb(), cmd_kg(), cmd_kr(),
X		cmd_ks(), cmd_msg(), cmd_on(), cmd_recf(), cmd_sb(),
X		cmd_send(), cmd_sendf(), cmd_wait(), cmd_xr(), cmd_xs(),
X
X		/* init and script commands */
X		cmd_ac(), cmd_appcur(), cmd_baud(), cmd_bt(), cmd_conv(),
X		cmd_echo(), cmd_exit(), cmd_ext(), cmd_fnc(), cmd_key(),
X		cmd_kmode(), cmd_kmaxpk(), cmd_mode(), cmd_mouse(),
X		cmd_numkey(), cmd_parity(), cmd_share(), cmd_short(),
X		cmd_swap(), cmd_wrap(), cmd_xbeep(), cmd_xproto();
X
X		/* rexx-only commands */
Xextern int	cmd_rx(), cmd_fwd();
X
X/* expand.c */
Xextern char **expand();
Xextern void set_dir(), free_expand();
SHAR_EOF
echo "extracting vt100.init"
sed 's/^X//' << \SHAR_EOF > vt100.init
X#   Setup 2 external protocols:
X# Zmodem with -Q (quit without waiting for a click in the close box) and
X# -I (take serial parameters from zmodem.init)
X	EXTERNAL	Zmodem "sz -QI @LOCAL" "rz -QI"
X# Ymodem with -B (use Ymodem instead of Zmodem), -Q and -I as above.
X	EXTERNAL	Ymodem "sz -BQI @LOCAL" "rz -BQI"
X# Select Zmodem as the default protocol.
X	XPROTO	Zmodem
SHAR_EOF
echo "extracting window.c"
sed 's/^X//' << \SHAR_EOF > window.c
X/****************************************************
X * vt100 emulator - window/keyboard support
X *		:ts=8
X *
X *	v2.9 ACS - See change summary.
X *	v2.7 870825 ACS - Provide an info/status window rather than using
X *			  req().  Better error handling.
X *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
X *	v2.5 870214 DBW - more additions (see readme file)
X *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
X *	v2.3 861101 DBW - minor bug fixes
X *	v2.2 861012 DBW - more of the same
X *	v2.1 860915 DBW - new features (see README)
X *	     860823 DBW - Integrated and rewrote lots of code
X *	v2.0 860809 DBW - Major rewrite
X *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
X *	v1.0 860712 DBW	- First version released
X *
X ****************************************************/
X
X#include "vt100.h"
X
Xstatic char *infkey[] = {	/* F-keys resulting from RawKeyConvert() */
X    "0~",  "1~",  "2~",  "3~",  "4~",  "5~",  "6~",  "7~",  "8~",  "9~",
X    "10~", "11~", "12~", "13~", "14~", "15~", "16~", "17~", "18~", "19~",
X    NULL};
X
X/* Cursor keys resulting from RawKeyConvert() and their output values */
Xstatic struct {
X    char *in;		/* in sequence */
X    char *out_curapp;	/* out sequence in p_curapp */
X    char *out;		/* out sequence !in p_curapp */
X} ckeys[] = {
X	"A",	"OA",	"[A",
X	"T",	"OA",	"[A",
X	"B",	"OB",	"[B",
X	"S",	"OB",	"[B",
X	"C",	"OC",	"[C",
X	" A~",	"OC",	"[C",
X	"D",	"OD",	"[D",
X	" @~",	"OD",	"[D",
X	NULL,	NULL,	NULL	};
X
X/*   Numeric keypad for A2000 and A500 have keys that the A1000 doesn't have.
X** Use them for the VT100 F-keys. */
Xstatic char npfkey[] = {
X    '(', 'P', ')', 'Q', '*', 'R', '/', 'S', 0, 0};
X
X/* Numeric keypad return values excluding HELP, '-' and ENTER */
Xstatic char keypad[] = {
X    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '\0'};
X/* Numeric keypad return values for HELP, - and ENTER */
Xstatic char speckeypad[] = {
X    '-',	'l',	'-',
X    '.',	'n',	'.',
X    '\015',	'M',	'\015',
X    '\0',	'\0',	'\0'	};
X
X/* For InfoMsg...may be changed by a NEWSIZE msg in vt100.c */
Xint reqminx,	/* Min value for x in reqwindow (pixels) */
X    reqmaxx,	/* Max value for x in reqwindow (pixels) */
X    reqmaxlen,	/* Max # chars in reqwindow */
X    reqminy,	/* Min value for y in reqwindow (scan lines) */	
X    reqmaxy,	/* Max value for y in reqwindow (scan lines) */
X    reqfudge;	/* Clear space between border and start of 1st char */
Xint reqy;	/* Current pixel location in reqwindow */
X
Xvoid ReqNewSize(), OpenReqWindow();
X
X/***************************************************
X *  function to swap the use of backspace and delete
X ***************************************************/
X
Xvoid swap_bs_del()
X{
X    if (p_bs_del)   p_bs_del = 0;
X    else	    p_bs_del = 1;
X}
X
X/*************************************************
X *  function to get file name (via a requestor)
X *************************************************/
Xvoid req(prmpt,name,getinp)
Xchar *prmpt,*name;
Xint  getinp;
X    {
X    ULONG class;
X#if MANX
X    USHORT RemoveGadget();
X#endif /* MANX */
X    int  lprmpt, lname;
X    struct IntuiMessage *Msg;
X
X    if(reqwinup == 0)
X	OpenReqWindow();
X    
X    if(!getinp) {
X    	InfoMsg2Line(prmpt, name);
X    	return;
X    }
X
X    lprmpt = strlen(prmpt);
X    lname = strlen(name);
X
X    /* Don't use strings longer than what we've provided space for. */
X    if(lprmpt > (MAXGADSTR-1)) {
X	emits("Prompt too long - truncated.\n");
X	lprmpt = MAXGADSTR-1;
X    }
X    if(lname > (MAXGADSTR-1)) {
X	emits("Name too long - truncated.\n");
X	lname = MAXGADSTR-1;
X    }
X
X    if (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X	class = Msg->Class;
X	ReplyMsg((struct Message *)Msg);
X	if(class == REQCLEAR)
X	    numreqs = 0;
X	if(class == NEWSIZE)
X	    ReqNewSize(reqwindow->Height, reqwindow->Width);
X    }
X
X    /* Make sure the prompt gets updated */
X    if (numreqs == 1 && strcmp(Prompt,prmpt) != 0) {
X	EndRequest(&myrequest,reqwindow);
X	do {
X		Wait(1L << reqwindow->UserPort->mp_SigBit);
X		while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X			class = Msg->Class;
X			ReplyMsg((struct Message *)Msg);
X			if(class == NEWSIZE)
X			    ReqNewSize(reqwindow->Height, reqwindow->Width);
X		}
X	} while (class != REQCLEAR);
X	numreqs = 0;
X	}
X
X    /* copy in a prompt and a default */
X    strncpy(Prompt,prmpt,lprmpt); Prompt[lprmpt] = '\0';
X    strncpy(InpBuf,name,lname); InpBuf[lname] = '\0';
X    mystrinfo.BufferPos = lname;
X
X    if (numreqs == 1) {		/* If there is a requester... reuse it */
X    	RefreshGadgets(&mystrgad, reqwindow, &myrequest);
X    	Delay(2L);
X    }
X    else {			/* otherwise create it */
X	while(numreqs != 1) {
X            if (Request(&myrequest, reqwindow) == 0) {
X		emits("ERROR - CAN'T CREATE REQUESTOR FOR:\n");
X		emits(Prompt); emit('\n'); emits(InpBuf); emit('\n');
X		return;
X	    }
X	    else numreqs = 1;
X
X	    do {
X		Wait(1L << reqwindow->UserPort->mp_SigBit);
X		while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X		    class = Msg->Class;
X		    ReplyMsg((struct Message *)Msg);
X		    if(class == REQCLEAR)
X			numreqs = 0;
X		    if(class == NEWSIZE)
X			ReqNewSize(reqwindow->Height, reqwindow->Width);
X		}
X	    } while (class != REQSET);
X	} /* end while numreqs != 0 */
X    } /* end else */
X
X    /* if we don't want input, we're done */
X    if (getinp == 0 || numreqs == 0) return;
X
X    if((reqwindow->Flags & WINDOWACTIVE) != WINDOWACTIVE) {
X    	WindowToFront(reqwindow);
X	ActivateWindow(reqwindow);
X	do {
X	    Wait(1L << reqwindow->UserPort->mp_SigBit);
X	    while(Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X		class = Msg->Class;
X		ReplyMsg((struct Message *)Msg);
X		if(class == NEWSIZE)
X		    ReqNewSize(reqwindow->Height, reqwindow->Width);
X	    }
X	} while (class != ACTIVEWINDOW);
X    }
X    
X    /* here is where we pre-select the gadget   */
X    if (!ActivateGadget(&mystrgad,reqwindow,&myrequest)) {
X
X	/* wait for his/her hands to get off the keyboard (Amiga-key) */
X	Delay(20L);
X	while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X	    ReplyMsg((struct Message *)Msg);
X	    if(class == NEWSIZE)
X		ReqNewSize(reqwindow->Height, reqwindow->Width);
X	}
X
X	/* try once more before giving up... */
X	ActivateGadget(&mystrgad,reqwindow,&myrequest);
X	}
X
X    /* wait for input to show up */
X    while (1) {
X	if ((NewMessage = (struct IntuiMessage *)
X		GetMsg(reqwindow->UserPort)) == FALSE) {
X	    Wait(1L<<reqwindow->UserPort->mp_SigBit);
X	    continue;
X	    }
X	class = NewMessage->Class;
X	ReplyMsg((struct Message *)NewMessage);
X
X	/* the requestor got terminated... yea!! */
X	if (class == REQCLEAR) break;
X
X	if(class == NEWSIZE)
X	    ReqNewSize(reqwindow->Height, reqwindow->Width);
X	    
X	/* maybe this is a menu item to handle */
X/*	if (class == MENUPICK) handle_menupick(class,code); */
X	}
X
X    /* all done, so return the result */
X    numreqs = 0;
X    strcpy(name,InpBuf);
X    if (reqwinup && ((reqwindow->Flags) & WINDOWACTIVE))
X	ActivateWindow(mywindow);
X    }
X
X/*************************************************
X*  function to print a string
X*************************************************/
Xvoid emits(string)
Xchar string[];
X    {
X    int i;
X    char c;
X
X    i=0;
X    while (string[i] != 0)
X	{
X	c=string[i];
X	if (c == 10) emit(13);
X	emit(c);
X	i += 1;
X	}
X    }
X
X/*************************************************
X*  function to output ascii chars to window
X*************************************************/
Xvoid emit(c)
Xchar c;
X    {
X    static char wrap_flag = 0;	/* are we at column 80? */
X
X    c &= 0x7F;
X    switch( c )
X	{
X	case '\t':
X	x += (Ysize * 8) - ((x-MINX) % (Ysize * 8));
X	break;
X
X	case 10:  /* lf */
X	doindex('D');
X	break;
X
X	case 13:  /* cr */
X	x = MINX;
X	break;
X
X	case 8:   /* backspace */
X	x -= Xsize;
X	if (x < MINX) x = MINX;
X	break;
X
X	case 12:     /* page */
X	x = MINX;
X	y = MINY;
X	SetAPen(mywindow->RPort,0L);
X	RectFill(mywindow->RPort,(long)MINX,
X	    (long)(MINY-BaseLine),(long)(MAXX+(Xsize-1)),(long)(MAXY+1));
X	SetAPen(mywindow->RPort,1L);
X	break;
X
X	case 7:     /* bell */
X	cmd_beep(0L);
X	break;
X
X	default:
X	if (c < ' ' || c > '~') break;
X	if (p_wrap && wrap_flag && x >= MAXX) {
X	    x = MINX;
X	    doindex('D');
X	    if (y > MAXY) {
X		y = MAXY;
X		ScrollRaster(mywindow->RPort,0L,(long)Ysize,(long)MINX,
X		    (long)(MINY-(BaseLine+1)),(long)(MAXX+(Xsize - 1)),
X		    (long)(MAXY+1));
X		}
X	    }
X	Move(mywindow->RPort,(long)x,(long)y);
X
X	if (curmode&FSF_BOLD) {
X	    if (p_depth > 1) {
X		SetAPen(mywindow->RPort,(long)(2+(1^p_screen)));
X		SetSoftStyle(mywindow->RPort,(long)curmode,253L);
X		}
X	    else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
X	    }
X	else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
X
X	if (curmode&FSF_REVERSE) {
X	    SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID));
X	    Text(mywindow->RPort,&c,1L);
X	    SetDrMd(mywindow->RPort,(long)JAM2);
X	    }
X	else Text(mywindow->RPort,&c,1L);
X
X	if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L);
X	x += Xsize;
X	} /* end of switch */
X
X    if (y > MAXY) {
X	y = MAXY;
X	x = MINX;
X	ScrollRaster(mywindow->RPort,0L,(long)Ysize,(long)MINX,
X	    (long)(MINY-(BaseLine+1)),(long)(MAXX+(Xsize - 1)),
X	    (long)(MAXY+1));
X	}
X    if (x > MAXX) {
X	wrap_flag = 1;
X	x = MAXX;
X	}
X    else wrap_flag = 0;
X    }
X
X/*************************************************
X*  function to output ascii chars to window (batched)
X*************************************************/
Xvoid emitbatch(la,lookahead)
Xint la;
Xchar *lookahead;
X    {
X    int i;
X
X    Move(mywindow->RPort,(long)x,(long)y);
X    i = x / Xsize;
X    if (i+la >= maxcol) {
X	if (p_wrap == 0) la = maxcol - i;
X	else {
X	    lookahead[la] = 0;
X	    emits(lookahead);
X	    return;
X	    }
X	}
X    if (curmode&FSF_BOLD) {
X	if (p_depth > 1) {
X	    SetAPen(mywindow->RPort,(long)(2+(1^p_screen)));
X	    SetSoftStyle(mywindow->RPort,(long)curmode,253L);
X	    }
X	else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
X	}
X    else SetSoftStyle(mywindow->RPort,(long)curmode,255L);
X
X    if (curmode&FSF_REVERSE) {
X	SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID));
X	Text(mywindow->RPort,lookahead,(long)la);
X	SetDrMd(mywindow->RPort,(long)JAM2);
X	}
X    else Text(mywindow->RPort,lookahead,(long)la);
X    if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L);
X    x += (Xsize * la);
X    }
X
X/******************************
X* Manipulate cursor
X******************************/
Xvoid cursorflip()
X    {
X    SetDrMd(mywindow->RPort,(long)COMPLEMENT);
X    SetAPen(mywindow->RPort,3L);
X    RectFill(mywindow->RPort, (long)(x), (long)(y-BaseLine),
X	(long)(x+Xsize-1), (long)(y+(Ysize-BaseLine-1)));
X    SetAPen(mywindow->RPort,1L);
X    SetDrMd(mywindow->RPort,(long)JAM2);
X    }
X
X/************************************************
X*  function to take raw key data and convert it
X*  into ascii chars
X**************************************************/
Xint toasc(retstr, code, qual, maxlen, ia, local)
Xunsigned char *retstr;
Xunsigned int code,qual;
Xint local, maxlen;
XAPTR ia;
X{
X    unsigned int ctrl, alt, npad;
X    int i,
X	cmatch,
X	length = 0;	/* length of returned string */
X    unsigned char *p = retstr;
X    static struct InputEvent ievent = {NULL, IECLASS_RAWKEY,0,0,0};
X
X    *p = '\0';
X
X    if(code >= 0x5a && code <= 0x5d) {
X	/*   Appears to be one of the keys (, ), /, * on the newer keypads.
X	** Convert them to VT100 F1-F4 */
X	char t, *convert = "()*/";
X
X	t = convert[code - 0x5a];
X	for(i = 0; npfkey[i]; i++)
X	    if(t == npfkey[i]) {
X		strcpy(p, "\033O");
X		*(p+2) = npfkey[i+1];
X		*(p+3) = '\0';
X		length = 3;
X		break;
X	    }
X	if(*p) {
X	    sendstring(p);
X	    return length;
X	}
X    }
X
X    ctrl  = qual & IEQUALIFIER_CONTROL;
X    alt	  = qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT);
X    npad  = qual & IEQUALIFIER_NUMERICPAD;
X
X    ievent.ie_Qualifier = qual;
X
X    ievent.ie_Code = code;
X    /* get previous codes from location pointed to by IAddress
X     * this "magic" pointer is valid intil the IntiiMessage is
X     * replied
X     */
X    ievent.ie_position.ie_addr = ia;
X    length = RawKeyConvert(&ievent, retstr, (LONG)maxlen, NULL);
X    if(length == 0)
X	return length;
X
X    *(p+length) = '\0';	/* Null terminate the value */
X
X    if(npad && length == 1) { /* keypad (excluding HELP key)? */
X	register char t = *p;
X
X	if(t == '(' || t == ')' || t == '*' || t == '/') {
X	    for(i = 0; npfkey[i]; i++)
X		if(t == npfkey[i]) {
X		    strcpy(p, "\033O");
X		    *(p+2) = npfkey[i+1];
X		    *(p+3) = '\0';
X		    length = 3;
X		    break;
X		}
X	} else if((t >= '0') && (t <= '9')) {
X	    if(p_keyapp) {
X		strcpy(p, "\033O");
X		*(p+2) = keypad[t-'0'];
X		*(p+3) = '\0';
X		length = 3;
X	    } /* else *p is correct */
X	} else for(i = 0; speckeypad[i]; i += 3)
X	    if(speckeypad[i] == t) {
X		if(p_keyapp) {
X		    strcpy(p, "\033O");
X		    *(p+2) = speckeypad[i+1];
X		    length = 3;
X		} else
X		    *p = speckeypad[i+2];
X		break;
X	    }
X    } else if((length == 3) && (strcmp(p, "\233?~") == 0)) {
X	/* HELP key -- only gen something if in app keypad mode */
X	if(p_keyapp) {
X	    strcpy(p, "\033Om");
X	    length = 3;
X	} else {
X	    *p = '\0';
X	    length = 0;
X	}
X    } else if(length > 1 && retstr[0] == 0x9b) { /* cursor or F-keys? */
X	cmatch = 0;
X	for(i = 0; ckeys[i].in && !cmatch; i++) {
X	    if(p_curapp
X	      && strcmp((p+1), ckeys[i].in) == 0) {
X		strcpy((p+1), ckeys[i].out_curapp);
X		*p = 0x1b;
X		length = strlen(ckeys[i].out_curapp)+1;
X		cmatch = 1;
X	    } else if(strcmp((p+1), ckeys[i].in) == 0) {
X		strcpy((p+1), ckeys[i].out);
X		*p = 0x1b;
X		length = strlen(ckeys[i].out)+1;
X		cmatch = 1;
X	    }
X	}
X	if(!cmatch) { /* Not cursor, try F-keys */
X	    for(i = 0; infkey[i]; i++) {
X		if(strcmp((p+1), infkey[i]) == 0) {
X		    if(i > 9)
X			strcpy(p, p_F[i-10]);
X		    else strcpy(p, p_f[i]);
X		    if(!script_on && *p == p_keyscript) {
X			script_start(p+1);
X			*p = '\0';
X			length = 0;
X		    }
X		    length = strlen(p);
X		    break;
X		}
X	    }
X	}
X    } else if(ctrl && (length == 1)) {
X	/* Control key shortcuts? */
X	switch(*p) {
X	case '6':
X	    *p = 30;
X	    break;
X	case '2':
X	case ' ': /* @ done by RawKeyConvert? */
X	    if(!local)
X		*p = (alt ? 128 : 0);
X		break;
X	case '-':
X	case '?':
X	    *p = 31;
X		break;
X	}
X    } else if(alt && !local && length == 1)
X	*p |= 0x80; /* Add hi bit if ALT is the only modifier */
X    else if(p_bs_del && *p == 8    && length == 1)
X	*p = 0x7f;
X    else if(p_bs_del && *p == 0x7f && length == 1)
X	*p = 8;
X
X/*    if (ctrl) {   Are all of these taken care of?
X	if (c > '`' && c <= 127) c -= 96;
X	else if (c > '@' && c <= '_') c -= 64;
X	else if (c == '6') c = 30;
X	else if (c == '-' || c == '?') c = 31;
X    } */
X    for(i = 0; i < length; i++)
X	sendchar(*(p++));
X    return(length);
X}
X
Xvoid
XKillReq()
X{
X    struct IntuiMessage *Msg;
X    ULONG class;
X    
X    if(numreqs != 0) {
X	EndRequest(&myrequest,reqwindow);
X	do {
X		Wait(1L << reqwindow->UserPort->mp_SigBit);
X		while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X			class = Msg->Class;
X			ReplyMsg((struct Message *)Msg);
X		}
X	} while (class != REQCLEAR);
X	numreqs = 0;
X    }
X
X    if(reqwinup) {
X    	/* First, clear out all pending messages */
X	while (Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X	    class = Msg->Class;
X	    ReplyMsg((struct Message *)Msg);
X	}
X	NewReqWindow.LeftEdge = reqwindow->LeftEdge;	/* Remember ...	  */
X	NewReqWindow.TopEdge = reqwindow->TopEdge;	/* ...where...	  */
X	NewReqWindow.Width = reqwindow->Width;		/* ...the user... */
X	NewReqWindow.Height = reqwindow->Height;	/* ...put it.	  */
X	CloseWindow(reqwindow); /* Now we can close the window */
X	reqwinup = 0;
X    }
X}
X
Xvoid
XInfoMsg2Line(header, msg)
Xchar *header, *msg;
X{
X    ScrollInfoMsg(1);
X    InfoMsgNoScroll(header);
X    ScrollInfoMsg(1);
X    InfoMsgNoScroll(msg);
X    ScrollInfoMsg(1);
X}
X
Xvoid
XInfoMsg1Line(msg)
Xchar *msg;
X{
X    ScrollInfoMsg(1);
X    InfoMsgNoScroll(msg);
X    ScrollInfoMsg(1);
X}
X
X/*   Output the specified data to the "info" window  */
Xvoid
XScrollInfoMsg(lines)
Xint lines;
X{
X/*  ULONG class;
X    struct IntuiMessage *Msg; */
X    int pixels = lines * Ysize;
X    
X    if(!reqwinup)
X	OpenReqWindow();
X
X/*  if(Msg=(struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X	class = Msg->Class;
X	ReplyMsg(Msg);
X	if(class == NEWSIZE)
X	    ReqNewSize(reqwindow->Height, reqwindow->Width);
X    } */
X
X    if ( (reqy += pixels) > reqmaxy) {
X	reqy = reqmaxy;
X	if(pixels > 0)
X	    ScrollRaster(reqwindow->RPort, 0L, (LONG)pixels,
X		(LONG)reqminx,
X		(LONG)reqminy,
X		(LONG)(reqmaxx+(Xsize - 1)),
X		(LONG)(reqmaxy+(Ysize - 1)));
X/* Was:		(LONG)(wp->Width - wp->BorderRight),
X		(LONG)(wp->Height - wp->BorderBottom)); */
X    }
X}
X
Xvoid
XInfoMsgNoScroll(msg)
Xchar *msg;
X{
X    LONG msglen = strlen(msg);
X
X    ScrollInfoMsg(0);	/* Ensure that the msg will be visible */
X
X    if(msglen > reqmaxlen)
X	msglen = reqmaxlen;
X
X    /*  Position the pen at the baseline of the character (BaseLine scan
X    ** lines into it). */
X    Move(reqwindow->RPort, (LONG)reqminx, (LONG)(reqy+BaseLine));
X    Text(reqwindow->RPort, msg, msglen);
X}
X
Xvoid
XReqNewSize(height, width)
XSHORT height, width;
X{
X    register struct Window *wp = reqwindow;
X    int oldmaxy;
X
X    /*   Compute min and max for x and y coordinates.  Note that for y the
X    ** value is for the *top* of the character, not the baseline.  Text()
X    ** uses a baseline value and so it must be adjusted prior to the call.
X    ** When computing the max values, calculate them so that we will have
X    ** sufficient room for an entire character. */
X    oldmaxy = reqmaxy;
X    reqminy = wp->BorderTop + reqfudge;
X    reqmaxy = (((height - reqminy - wp->BorderBottom) / Ysize) * Ysize)
X		+ (reqminy-Ysize);
X    reqminx = wp->BorderLeft + reqfudge;
X    reqmaxx = (((width - reqminx - wp->BorderRight) / Xsize) * Xsize)
X		+ (reqminx-Xsize);
X    reqmaxlen = (reqmaxx+(Xsize-1)) / Xsize;
X    if(oldmaxy > reqmaxy) { /* Clean up the bottom of the window */
X	int temp = height - wp->BorderBottom - reqmaxy;
X	
X	ScrollRaster(wp->RPort, 0L, (LONG)temp,
X	(LONG)reqminx,
X	(LONG)reqmaxy,
X	(LONG)(width - wp->BorderRight),
X	(LONG)(height - wp->BorderBottom));
X    }
X}
X
Xvoid
XOpenReqWindow()
X{
X    struct IntuiMessage *Msg;
X    ULONG class;
X    void ReqNewSize();
X    static init = 1;
X    
X    if(init) {
X	myrequest.LeftEdge = (myrequest.LeftEdge * Xsize) + 5;
X	myrequest.TopEdge  = (myrequest.TopEdge  * Ysize) + 2;
X	myrequest.Width    = (myrequest.Width    * Ysize) + 4;
X	myrequest.Height   = (myrequest.Height   * Xsize) + 6;
X
X	mydonegad.LeftEdge = (mydonegad.LeftEdge * Xsize) + 2;
X	mydonegad.TopEdge  = (mydonegad.TopEdge  * Ysize) + 2;
X	mydonegad.Width    = ((strlen(donetxt.IText) + 1) * Xsize) + 0;
X	mydonegad.Height   = (mydonegad.Height   * Ysize) + 2;
X
X	mystrgad.LeftEdge  = (mystrgad.LeftEdge * Xsize) + 2;
X	mystrgad.TopEdge   = (mystrgad.TopEdge  * Ysize) + 4;
X	mystrgad.Width     = (mystrgad.Width    * Ysize) + 0;
X	mystrgad.Height    = (mystrgad.Height   * Xsize) + 2;
X
X	donetxt.LeftEdge   = (donetxt.LeftEdge  * Xsize) + 0;
X	donetxt.TopEdge    = (donetxt.TopEdge   * Ysize) + 0;
X
X	mystrtxt.LeftEdge  = (mystrtxt.LeftEdge  * Xsize) + 2;
X	mystrtxt.TopEdge   = (mystrtxt.TopEdge   * Ysize) + 2;
X
X	NewReqWindow.Width    = (NewReqWindow.Width    * Xsize) + 4 + 18;
X	NewReqWindow.LeftEdge = (NewReqWindow.LeftEdge * Xsize) + 2;
X	NewReqWindow.LeftEdge = NewWindow.LeftEdge + NewWindow.Width
X				- NewReqWindow.Width;
X
X	NewReqWindow.TopEdge  = (NewReqWindow.TopEdge  * Ysize) + 7;
X	NewReqWindow.Height   = (NewReqWindow.Height   * Ysize) + 11 + 2;
X
X	init = 0;
X    }
X
X    reqwindow = OpenWindow(&NewReqWindow);
X    do {
X	Wait(1L << reqwindow->UserPort->mp_SigBit);
X	while(Msg = (struct IntuiMessage *)GetMsg(reqwindow->UserPort)) {
X	    class = Msg->Class;
X	    ReplyMsg((struct Message *)Msg);
X	}
X    } while (class != ACTIVEWINDOW);
X    reqfudge = 0;	/* Leave 0 pixels/scan lines between border and char */
X    ReqNewSize(reqwindow->Height, reqwindow->Width);
X    reqy = reqminy;	/* Top of character set by ReqNewSize() */
X    reqwinup = 1;
X    if (reqwinup && ((reqwindow->Flags) & WINDOWACTIVE))
X	ActivateWindow(mywindow);
X}
SHAR_EOF
echo "extracting xmodem.c"
sed 's/^X//' << \SHAR_EOF > xmodem.c
X/*************************************************************
X * vt100 terminal emulator - XMODEM protocol support
X *			:ts=8
X *
X *	v2.9 ACS - multi_xfer() no longer looks for $ -- kermit does,
X *		   readchar() now infers ttime of 100,000 micros if ttime == 0
X *		   (for newkermit); readchar() doesn't output a TIMED OUT msg
X *		   (because of newkermit); speed up sendstring().
X *	v2.7 870825 ACS - Make multi_xfer() non-recursive; on non-ESC in
X *			  readchar() re-do the main window's title. 
X *	v2.6 870227 DBW - bug fixes for all the stuff in v2.5
X *	v2.5 870214 DBW - more additions (see readme file)
X *	v2.4 861214 DBW - lots of fixes/additions (see readme file)
X *	v2.3 861101 DBW - minor bug fixes
X *	v2.2 861012 DBW - more of the same
X *	v2.1 860915 DBW - new features (see README)
X *	     860901 ACS - Added Parity and Word Length and support code
X *	     860823 DBW - Integrated and rewrote lots of code
X *	     860815 Steve Drew: readchar inproved with real timeouts
X *	v2.0 860809 DBW - Major rewrite
X *	v1.1 860720 DBW	- Switches, 80 cols, colors, bug fixes
X *	v1.0 860712 DBW	- First version released
X *
X *************************************************************/
X
X#include "vt100.h"
X
Xint enablexon = TRUE;
X
Xextern struct IntuiText MyTitle;
X
Xstatic unsigned long parity_settings[4] = {
X    0x96696996,
X    0x69969669,
X    0x69969669,
X    0x96696996 };
X
X/* crctab calculated by Mark G. Mendel, Network Systems Corporation */
Xstatic unsigned short crctab[256] = {
X    0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
X    0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
X    0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
X    0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
X    0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
X    0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
X    0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
X    0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
X    0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
X    0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
X    0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
X    0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
X    0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
X    0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
X    0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
X    0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
X    0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
X    0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
X    0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
X    0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
X    0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
X    0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
X    0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
X    0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
X    0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
X    0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
X    0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
X    0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
X    0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
X    0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
X    0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
X    0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
X};
X
X/*
X * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. 
X *  NOTE: First srgument must be in range 0 to 255.
X *        Second argument is referenced twice.
X * 
X * Programmers may incorporate any or all code into their programs, 
X * giving proper credit within the source. Publication of the 
X * source routines is permitted so long as proper credit is given 
X * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, 
X * Omen Technology.
X */
X
X#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
X
X/************************************************************
X* Send a string (using sendchar below)
X************************************************************/
X
Xvoid sendstring(s)
Xregister char *s;
X{
X    char	data[20];
X    register char *cp = data;
X    int		i;
X    LONG	oldlength = Write_Request->IOSer.io_Length;
X    APTR	saveaddr =  Write_Request->IOSer.io_Data;
X
X    Write_Request->IOSer.io_Length = sizeof(data)-1;
X    Write_Request->IOSer.io_Data = (APTR) &(data[0]);
X
X    if (enablexon)
X	No_XON();
X
X    while(i = *(s++)) {
X	*(cp++) = addparity(i);
X	if( (cp - data) == sizeof(data)-1) {
X	    *cp = '\0';
X	    do
X		DoIO((struct IORequest *)Write_Request);
X	    while(Write_Request->IOSer.io_Error != 0);
X	    cp = data;
X	}
X    }
X    if(cp > data) {
X	*(cp++) = '\0';
X	Write_Request->IOSer.io_Length = strlen(data);
X	do
X	    DoIO((struct IORequest *)Write_Request);
X	while(Write_Request->IOSer.io_Error != 0);
X    }
X
X    Write_Request->IOSer.io_Length = oldlength;
X    Write_Request->IOSer.io_Data   = saveaddr;
X
X    if (enablexon)
X	No_XON();
X}
X
X/**************************************************************/
X/* send char and read char functions for the xmodem function */
X/************************************************************/
Xvoid sendchar(ch)
Xint ch;
X{
X    if (enablexon)
X	No_XON();
X
X    rs_out[0] = addparity(ch);
X
X    do {
X	DoIO((struct IORequest *)Write_Request);
X    } while(Write_Request->IOSer.io_Error != 0);
X
X    if (enablexon)
X	Do_XON();
X}
X
Xstatic int
Xaddparity(ch)
Xregister int ch;
X{
X    int		i, j, k;
X
X    if(p_parity > 0)
X	switch (p_parity) {
X	case 1: /* mark */
X	    ch = (ch & 0x7F) | 0x80;
X	    break;
X
X	case 2: /* space */
X	    ch &= 0x7F;
X	    break;
X
X	case 3:	/* even */
X	case 4: /* odd  */
X	    i = (ch >> 5) & 0x3;
X	    j = ch & 0x1F;
X	    k = ((parity_settings[i] >> j) & 0x1) << 7;
X	    if (p_parity == 3)			/* even parity */
X		ch = (ch & 0x7F) | k;
X	    else					/* odd parity */
X		ch = (ch & 0x7F) | (k ^ 0x80);
X	}
X    return(ch & 0xFF);
X}
X
X/* send a break to the host */
Xvoid sendbreak()
X{
X    AbortIO((struct IORequest *)Read_Request);
X    Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit);
X    WaitIO((struct IORequest *)Read_Request);
X    Read_Request->IOSer.io_Command = SDCMD_BREAK;
X    DoIO((struct IORequest *)Read_Request);
X    Read_Request->IOSer.io_Command = CMD_READ;
X    SendIO((struct IORequest *)Read_Request);
X}
X
Xint readchar()
X{
X    int rd,ch;
X    ULONG class, waitmask;
X    USHORT code;
X
X    if(ttime == 0)
X	Timer.tr_time.tv_micro = 100000;
X    else
X	Timer.tr_time.tv_micro = 0;
X    Timer.tr_time.tv_secs = ttime;
X    SendIO((struct IORequest *)&Timer.tr_node);
X
X    rd = FALSE;
X    waitmask = ((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
X		( 1L << mywindow->UserPort->mp_SigBit) |
X		( 1L << Timer_Port->mp_SigBit));
X    if(reqwinup)
X	waitmask |= (1L << reqwindow->UserPort->mp_SigBit);
X    while (rd == FALSE) {
X	Wait(waitmask);
X	if (CheckIO((struct IORequest *)Read_Request)) {
X	    WaitIO((struct IORequest *)Read_Request);
X	    ch=rs_in[0];
X	    rd = TRUE;
X	    SendIO((struct IORequest *)Read_Request);
X	}
X	if(reqwinup &&
X	  (NewMessage=(struct IntuiMessage *)GetMsg(reqwindow->UserPort))) {
X	    class = NewMessage->Class;
X	    ReplyMsg((struct Message *)NewMessage);
X	    if(class == NEWSIZE)
X		ReqNewSize(reqwindow->Height, reqwindow->Width);
X	}
X	if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
X	   class = NewMessage->Class;
X	   code = NewMessage->Code;
X	   ReplyMsg((struct Message *)NewMessage);
X	   if ((class == RAWKEY) && (code == 69)) {
X		if(!CheckIO((struct IORequest *)&Timer))
X		    AbortIO((struct IORequest *)&Timer);
X		Wait (1L << Timer_Port->mp_SigBit);
X		WaitIO((struct IORequest *)&Timer.tr_node);
X		InfoMsg1Line("ERROR: User aborted transfer");
X		timeout = USERABORT;
X		return('\0');
X	   }
X	   PrintIText(mywindow->RPort, &MyTitle, 0L, 0L);
X	}
X
X	if (rd == FALSE && CheckIO((struct IORequest *)&Timer)) {
X/*	    InfoMsg1Line("ERROR: Timeout waiting for character"); */
X	    timeout = TIMEOUT;
X	    return('\0');
X	}
X    } /* end while */
X    if(!CheckIO((struct IORequest *)&Timer))
X	AbortIO((struct IORequest *)&Timer);
X    Wait (1L << Timer_Port->mp_SigBit);
X    WaitIO((struct IORequest *)&Timer.tr_node);
X    timeout = GOODREAD;
X    return(ch & (p_parity == 0 ? 0xFF : 0x7F));
X}
X
Xvoid No_XON()
X{
X
X    /* turn off XON/XOFF processing */
X    enablexon = FALSE;
X    Write_Request->io_SerFlags |= SERF_XDISABLED;
X    Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
X    DoIO((struct IORequest *)Write_Request);
X    Write_Request->IOSer.io_Command = CMD_WRITE;
X}
X
Xvoid Do_XON()
X{
X    /* turn on XON/XOFF processing */
X    enablexon = TRUE;
X    Write_Request->io_SerFlags &= ~SERF_XDISABLED;
X    Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
X    DoIO((struct IORequest *)Write_Request);
X    Write_Request->IOSer.io_Command = CMD_WRITE;
X}
X
X/**************************************/
X/* xmodem send and recieve functions */
X/************************************/
X
Xint XMODEM_Read_File(file)
Xchar *file;
X{
X    int		firstchar, sectnum, sectcurr, sectcomp, errors, errorflag,
X		c, good_sect, nak_char, retval = FALSE;
X    unsigned int   checksum, j, bufptr;
X    unsigned short crc;
X    char	scrstr2[40];
X
X    bytes_xferred = 0L;
X    ttime = TTIME_SHORT;
X
X    if( (bufr = AllocMem((long)BufSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL) {
X	InfoMsg1Line("XMODEM: Can't get a buffer.");
X	return FALSE;
X    }
X
X    if ((fd = creat(file, 0)) < 0) {
X	InfoMsg2Line("XMODEM Can't Open File:",file);
X	goto exit;
X    } else
X	InfoMsg1Line("XMODEM Receive, <esc> in VT100 window to abort");
X
X    sectnum = errors = bufptr = firstchar = 0;
X    if(p_xproto == 2)
X	nak_char = 'C';
X    else
X	nak_char = NAK;
X    No_XON();
X    sendchar(nak_char);
X    while (firstchar != EOT && errors != ERRORMAX) {
X	errorflag = FALSE;
X
X	while( (firstchar = readchar()) != SOH && firstchar != EOT) {
X	    if (timeout != GOODREAD) {
X		if (timeout == USERABORT || errors++ == ERRORMAX)
X		    goto exit;
X	    }
X	    sendchar(nak_char);
X	}
X
X	if  (firstchar == SOH) {
X	    sprintf(scrstr2,"%s: Block: %4d Bytes: %d",
X		    p_xproto==2?"XmodemCRC":"Xmodem", sectnum, sectnum*SECSIZ);
X	    InfoMsgNoScroll(scrstr2);
X	    sectcurr = readchar();
X	    if (timeout != GOODREAD)
X		goto exit;
X	    sectcomp = readchar();
X	    if (timeout != GOODREAD)
X		goto exit;
X	    if ((sectcurr + sectcomp) == 255) {
X		if (sectcurr == ((sectnum + 1) & 0xff)) {
X		    checksum = 0; crc = 0;
X		    for (j = bufptr; j < (bufptr + SECSIZ); j++) {
X			bufr[j] = readchar();
X			if (timeout != GOODREAD)
X			    goto exit;
X			checksum = (checksum + bufr[j]) & 0xff;
X			crc = updcrc(((unsigned int)bufr[j] & 0xff),  crc);
X		    }
X		    c = readchar();
X		    if(timeout != GOODREAD) {
X		    	errorflag = TRUE;
X			if(timeout == USERABORT)
X			    goto exit;
X		    }
X		    if(p_xproto == 2) {
X			crc = updcrc(((unsigned int)c & 0xff), crc);
X			c = readchar();
X			if(timeout != GOODREAD) {
X			    errorflag = TRUE;
X			    if(timeout == USERABORT)
X				goto exit;
X			}
X			crc = updcrc(((unsigned int)c & 0xff), crc);
X			good_sect = (crc == 0);
X		    } else
X			good_sect = (checksum == c);
X		    if (!good_sect) {
X		    	errorflag = TRUE;
X			if(timeout == USERABORT)
X			    goto exit;
X		    } else {
X			errors = 0;
X/*			sprintf(scrstr2,"Block %4d verified",sectnum); */
X			sectnum++;
X			bufptr += SECSIZ;
X			bytes_xferred += SECSIZ;
X/*			InfoMsgNoScroll(scrstr2); */
X			if (bufptr == BufSize) {
X			    if (write(fd, bufr, BufSize-SECSIZ) == EOF) {
X				InfoMsg1Line("XMODEM: Error Writing File");
X				goto exit;
X			    }
X			    bufptr = SECSIZ;
X			    for (j = 0; j < SECSIZ; j++)
X				bufr[j] = bufr[(BufSize-SECSIZ)+j];
X			}
X			sendchar(ACK);
X		    }
X		} else {
X		    /* got a duplicate sector */
X		    if (sectcurr == (sectnum & 0xff)) {
X			/* wait until we time out for 5secs */
X			do {
X			    readchar();
X			} while (timeout == GOODREAD);
X			if (timeout == USERABORT)
X			    goto exit;
X			InfoMsg1Line("XMODEM: Received Duplicate Sector");
X			sendchar(ACK);
X		    }
X		    else errorflag = TRUE;
X		}
X	    } else errorflag = TRUE;
X	}
X	if (errorflag == TRUE) {
X	    errors++;
X	    InfoMsg1Line("XMODEM: Error");
X	    sendchar(nak_char);
X	}
X    }        /* end while */
X    if ((firstchar == EOT) && (errors < ERRORMAX)) {
X	sendchar(ACK);
X	if (bufptr) {
X	    if(p_autochop) {
X		/* use firstchar to remember the last char for chopping */
X		if((firstchar = bufr[--bufptr]) == 0 || firstchar == 0x1A)
X		    while (bufptr && bufr[--bufptr] == firstchar)
X			;
X		bufptr++;
X	    }
X	    write(fd, bufr, bufptr);
X	}
X	close(fd);
X	ScrollInfoMsg(1);
X	retval = TRUE;
X    }
Xexit:
X    Do_XON();
X    FreeMem(bufr, (long)BufSize);
X    bufr = NULL;
X    return retval;
X}
X
Xint XMODEM_Send_File(file)
Xchar *file;
X{
X    int		sectnum, bytes_to_send, size, attempts, c, use_crc = 0,
X		retval = FALSE;
X    unsigned	checksum, j, bufptr;
X    unsigned short crc;
X    char	scrstr2[40];
X
X    bytes_xferred = 0;
X    ttime = TTIME_LONG;
X
X    if( (bufr = AllocMem((long)BufSize, MEMF_PUBLIC|MEMF_CLEAR)) == NULL) {
X	InfoMsg1Line("XMODEM: Can't get a buffer.");
X	return FALSE;
X    }
X
X    if ((fd = open(file, 0)) < 0) {
X	InfoMsg1Line("XMODEM: Cannot Open Send File");
X	FreeMem(bufr, (long)BufSize);
X	bufr = NULL;
X	return FALSE;
X    } else
X	InfoMsg1Line("XMODEM Send, <esc> from VT100 window to abort");
X    attempts = 0;
X    sectnum = 1;
X    No_XON();
X    /* wait for sync char */
X    j=1;
X    while (((c = readchar()) != NAK) && (c != 'C') && (j++ < ERRORMAX))
X	if (timeout == USERABORT)
X	    goto bad_exit;
X
X    if (j >= (ERRORMAX)) {
X	InfoMsg1Line("XMODEM: Receiver not sending");
X	goto bad_exit;
X    }
X
X    if(c == 'C')
X	use_crc = 1;
X    while ((bytes_to_send = read(fd, bufr, BufSize)) &&
X	    attempts != RETRYMAX) {
X	if (bytes_to_send == EOF) {
X	    InfoMsg1Line("XMODEM: Error Reading File");
X	    goto bad_exit;
X	}
X
X	bufptr = 0;
X	while (bytes_to_send > 0 && attempts != RETRYMAX) {
X	    attempts = 0;
X	    sprintf(scrstr2,"%s: Sending Block: %4d Bytes: %d",
X		    use_crc?"XmodemCRC":"Xmodem", sectnum, sectnum*SECSIZ);
X	    size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
X	    bytes_to_send -= size;
X	    do {
X		InfoMsgNoScroll(scrstr2);
X		sendchar(SOH);
X		sendchar(sectnum);
X		sendchar(~sectnum);
X		checksum = 0; crc = 0;
X		for (j = bufptr; j < bufptr + size; j++) {
X		    sendchar(bufr[j]);		/* send buffer data */
X		    checksum += bufr[j];
X		    crc = updcrc(((unsigned int)bufr[j] & 0xff), crc);
X		}
X		if( size < SECSIZ ) {		/* check if we need to pad */
X		    c = bufr[j-1] ? 0 : 0x1A;	/* choose correct padding */
X		    j = SECSIZ - size;
X		    checksum += j * c;
X		    while ( j-- ) {
X			if(use_crc)
X			    crc = updcrc(c, crc);
X			sendchar(c);		/* send padding */
X		    }
X		}
X		if(use_crc) {
X		    crc = updcrc(0, updcrc(0, crc));
X		    sendchar(crc >> 8);
X		    sendchar(crc & 0xff);
X		} else
X		    sendchar(checksum);
X		attempts++;
X		c = readchar();
X		if (timeout == USERABORT) {
X		    InfoMsg1Line("XMODEM: ABORTED");
X		    goto bad_exit;
X		}
X	    } while ((c != ACK) && (attempts != RETRYMAX));
X	    bufptr += size;
X	    bytes_xferred += size;
X/*	    sprintf(scrstr2,"Sent    block %4d",sectnum);
X	    InfoMsgNoScroll(scrstr2); */
X	    sectnum++;
X	}
X    }
X    close(fd);
X    if (attempts == RETRYMAX) {
X	InfoMsg1Line("XMODEM: No Acknowledgment, ABORTING");
X	goto bad_exit;
X    } else {
X	attempts = 0;
X	do {
X	    sendchar(EOT);
X	    attempts++;
X	} while ((readchar() != ACK) &&
X		     (attempts != RETRYMAX) &&
X		     (timeout != USERABORT)) ;
X	if (attempts == RETRYMAX)
X	    InfoMsg1Line("XMODEM: No end of file");
X    }
X    ScrollInfoMsg(1);
X    retval = TRUE;
X
Xbad_exit:
X    Do_XON();
X    FreeMem(bufr, (long)BufSize);
X    bufr = NULL;
X    return retval;
X}
X
X/* allow for multi file xfers separated by commas under
X    kermit and XMODEM */
X
Xvoid multi_xfer(name,mode,do_send)
Xchar *name;
Xint (*mode)();
Xint do_send;
X    {
X    int done = 0;
X    int status;
X    char *p, *name_start;
X
X    timeout = USERABORT - 1;
X    for(p=name_start=name; !done && timeout != USERABORT; name_start=++p)
X	{
X	if (*(name_start+1) == '\0')
X	    return;
X
X	while(*p == ' ') p++;
X	while(*p && *p != ',' && *p != ' ') p++;
X	if (*p == '\0') {
X	    done = TRUE;
X	    multi = 0;
X	}
X	else
X	    multi = 1;
X	*p = '\0';
X
X	status = ((*mode)(name_start, multi));
X	if (status == FALSE) close(fd);
X	}
X    server = 0;
X    multi = 0;
X    if(p_xbeep)
X	cmd_beep(0L);
X    }
X
SHAR_EOF
echo "End of archive 9 (of 9)"
# if you want to concatenate archives, remove anything after this line
exit