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

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

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

# 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:
#	kermitproto.h
#	mouse.doc
#	newkermit.c
#	remote.c
#	rexx.c
#	script.c
# This is archive 7 of a 9-part kit.
# This archive created: Thu Oct 19 22:30:32 1989
echo "extracting kermitproto.h"
sed 's/^X//' << \SHAR_EOF > kermitproto.h
X/*
X * Include file for kermitproto.w.  You probably don't want to change
X * any of the following manifest constants.
X * this module.
X */
X#define MAXSP 2048	/* Maximum length packet to send		*/
X#define MAXRP 1024	/* Maximum length packet to receive		*/
X#define DRPSIZ 94	/* Default data size of received packet		*/
X#define DSPSIZ 94	/* Default data size of sent packet		*/
X#define MAXWS 1		/* Maximum window size for sliding windows	*/
X#define NULL 0L
X
X/*
X * The following defines change the names of some things as an example
X * of how you can interface kermitproto.w to your own code.
X *
X * WARNING WILL ROBINSON:  These are highly specific to the Amiga
X * terminal emulator program "VT100" by Dave Wecker et. al. and must
X * certainly change for your code.
X */
X
X#define parity p_parity		/* parity on?		*/
X#define text p_mode		/* Text or binary mode? */
X#define convert p_convert	/* Convert files to lower case? */
X#define urpsiz p_kmaxpack	/* Kermit maximum packet size */
X
SHAR_EOF
echo "extracting mouse.doc"
sed 's/^X//' << \SHAR_EOF > mouse.doc
X			Mousing around with VT100
X
XBy default, this version of VT100 sends the following sequence when
Xthe user presses the left (selection) button on the Amiga mouse:
X
X	<ESC> M (yes, a real capital M) <quals> <column> <line>
X
Xwhere column and line are bytes that represent the x, y coordinates of
Xthe mouse click (offset by 32; a click on (0, 0) results in sending
Xtwo space characters), and quals is like so:
X
X	bit 0	control key
X	bit 1	shift key
X	bit 2	meta (alt) key
X	bit 3	caps lock
X	bit 4	mouse down event
X	bit 5	mouse up event
X	bit 6	always on (making qual a printable value)
X
XFor example, clicking on column 1, row 1 results in the escape sequence
X
X	<ESC> M P <SPC> <SPC>
X
XIn the startup file and scripts, the command MOUSE accepts the following
Xfour parameters:
X
X	UP	send a mouse event only when user releases the select button
X	DOWN	send an event only when user presses the select button
X	BOTH	send both up- and downward clicks
X	OFF	don't send mouse clicks
X
X
XThe function key setup has been extended to handle "fm" (along with
X"f1", "f2", etc.) so you can specify the string preceeding mouse
Xevents.  For example,
X
X	F M	"^[Oz"
X
XIn a script or the startup file would rebind the "mouse" function key to
Xsend
X	<ESC> O z
SHAR_EOF
echo "extracting newkermit.c"
sed 's/^X//' << \SHAR_EOF > newkermit.c
X/*			:ts=8						*/
X
X/*
X * These are the new interfaces between vt100 and the new Kermit protocol
X * module.
X */
X
X#include "vt100.h"			/* Get defines and so on	*/
X/*
X * Here are the declarations for our communication with kermitproto.c
X */
X
Xextern int	cx, cz;			/* Abort flags			*/
X
Xextern char	start;			/* Start state for Kermit	*/
Xchar		*cmarg;			/* Command argument for server	*/ 
X
X/*
X * The below variables have to do with the status of the communcation
X * so far.  They should be maintained over in kermitproto.w so that
X * things like the number of bytes sent and the packet type can be
X * printed as status.
X */
Xstatic int	npackets,		/* Number of packets sent so far */
X		naks;			/* Number of naks		*/
X
X
Xstatic char message[80];		/* Message line to output	*/
X
X/*
X * Do Kermit sending.  This expands wild cards into local variables for
X * gnfile() below.
X */
X
Xstatic int nfiles, wild;
Xstatic char **lp, **list;
X
Xdoksend(file,more)
Xchar *file;
Xint more;
X{
X    char *p;
X
X    list = NULL;
X    p = file;
X    while(*p && *p != '*' && *p != '?') p++;
X    if (*p) {
X	wild = 1;
X	list = expand(file, &nfiles);
X	if (list == NULL) {
X	    InfoMsg1Line("KERMIT: No wild card match");
X	    return FALSE;
X	}
X    }
X    else {
X	nfiles = 1;
X	wild = 0;
X	list = (char **) malloc(sizeof(char *));
X	*list = (char *) malloc(strlen(file) + 1);
X	strcpy(*list, file);
X    }
X    lp = list;
X    start = 's';			/* Set start state to send	*/
X    npackets = naks = 0;
X    message[0] = '\0';
X    proto();				/* Call protocol		*/
X    if (wild == 1)
X	free_expand(list);
X    else {
X	free((void *) *list);
X	free((void *) list);
X    }
X    return TRUE;
X}
X
X/*
X * gnfile(s, n)  char *s; int n;
X *
X * Returns in string s the name of the next file for Kermit to process,
X * which can be up to n characters in length.  Returns a positive value
X * if there are more files, 0 if not.
X */
Xint
Xgnfile(s, n)
Xchar *s;
Xint n;
X{
X    if (--nfiles >= 0) {
X	strncpy(s, *lp, n);
X	lp++;
X	return 1;
X    } else
X	return 0;
X}
X
X/*
X * Do Kermit receiving.  The file and more arguments in this routine are
X * for Get'ting files when the remote machine is the server.
X */
Xdokreceive(file,more)
Xchar *file;
Xint more;
X{
X    naks = npackets = 0;
X    message[0] = '\0';			/* Initialize			*/
X    if (!server)
X	start = 'v';			/* Start state to receive	*/
X    else {
X	cmarg = file;			/* Files to get from remote	*/
X	start = 'r';			/* Start state to get		*/
X    }
X    proto();
X    return TRUE;
X}
X
X/* kermit_directory()--request a remote directory from a Kermit server.
X */
X
X#define tochar(c) ((c) + 32)
X
Xvoid
Xkermit_directory(dir)
Xchar *dir;
X{
X    char command[80];
X
X    strcpy(command, "D");		/* Generic directory command */
X    command[1] = tochar(strlen(dir));	/* Length of directory name */
X    strcpy(&command[2], dir);		/* The directory itself */
X    cmarg = command;
X    start = 'g';			/* Generic command start state */
X    naks = npackets = 0;
X    proto();
X}
X
X/*
X * saybye()--send a FINISH command to a remote Kermit server.  This is
X * in fact what the original VT100 saybye() does.  A true Kermit BYE
X * command would mean changing the "F" below to "L", and it would actually
X * log out the remote host as well as shut down the Kermit server.
X */
Xvoid
Xsaybye()
X{
X    static char bye_command[] = "F";
X
X    cmarg = &bye_command[0];
X    start = 'g';			/* Generic command start state	*/
X    naks = npackets = 0;
X    proto();
X    return /* TRUE */;
X}
X
X/*
X * ttinl(dest, max, eol, timelimit)
X *
X * Read up to max characters from serial port into the array pointed
X * to by dest.  Return value is the number of characters received.
X *    If eol is greater than 0, terminate read upon first
X * eol character received.  If timelimit is greater than 0, wait at
X * most timelimit seconds for the characters.  The array is null
X * terminated;  in addition, if we do see an eol, we overwrite it
X * with the NULL and the returned character count does not include it.
X * (This behavior is required by the code in the C Kermit book but is
X * not explicitly stated there.)
X *
X * This version is most unsatisfactory as it does I/O one character
X * at a time, but extensive changes in the rest of VT100 would be
X * needed in order to use a multi-character read.
X */
X
Xstatic int pushedser = -1;			/* pushed character	*/
X
Xint ttinl(dest, max, eol, timelimit)
Xchar *dest;
Xint max, eol, timelimit;
X{
X    int i;
X    void ttflui();
X
X    if (timelimit > 0)
X	ttime = timelimit;
X    else
X	ttime = 30;			/* Maximum timeout if not given	*/
X    for (i = 0; i < max; i++) {
X	dest[i] = readchar();
X	if (timeout != GOODREAD) {
X	    if (timeout == USERABORT) {	/* User abort requested		*/
X		if (cx == 1)
X		    start = 'a';	/* Second escape--abort mess	*/
X		else
X		    cx = cz = 1;	/* Set abort flags		*/
X		continue;		/* Continue receiving anyway	*/
X	    } else {
X		i = -1;			/* Some other error.		*/
X		break;
X	    }
X	}
X	if (eol > 0 && dest[i] == eol)
X	    break;
X	ttime = 2;			/* Intrapacket timeout		*/
X    }
X    if (i >= 0)
X	dest[i] = '\0';			/* Null terminate what we got	*/
X    else
X	dest[0] = '\0';
X    return i;				/* Return length or failure	*/
X}
X
X/*
X * ttol(out, n)
X *
X * Send n characters pointed to by out through the serial port using
X * current settings of word length, parity, and flow control. Return
X * 
X *
X * Here I bypass sendchar() and go direct to the low level.
X */
Xint
Xttol(out, n)
Xchar *out;
Xint n;
X{
X    int retval;
X
X    Write_Request->IOSer.io_Data = (APTR) out;
X    Write_Request->IOSer.io_Length = n;
X    Write_Request->IOSer.io_Command = CMD_WRITE;
X    SendIO((struct IORequest *)Write_Request);
X    retval = WaitIO((struct IORequest *)Write_Request);
X    /*
X     * Restore old values.
X     */
X    Write_Request->IOSer.io_Data = (APTR) rs_out;
X    Write_Request->IOSer.io_Length = 1;
X    if (retval != 0)
X	return -1;
X    else
X	return ((int)Write_Request->IOSer.io_Actual);
X}
X
X/*
X * ttflui()
X *
X * Remove any pending characters from the serial port.
X *
X * Even worse than ttinl() and ttol(), this reads characters with a minimal
X * timeout until there aren't any more.  Note that I also changed readchar()
X * in xmodem.c to check if ttime is 0, and if it is, to set its timeout to
X * 100,000 ticks (0.1 seconds).  I also removed the InfoMsg1Line call which
X * warned about timeouts so this would work.  Ideally, ttinl() should do
X * a single CMD_READ in ReadRequest, and ttflui() should AbortIO() it.
X */
Xvoid
Xttflui()
X{
X    int c;
X
X    ttime = 0;
X    do {
X	c = readchar();
X    } while (timeout == GOODREAD);
X}
X
Xvoid
Xsleep(seconds) int seconds;
X{
X    if (seconds > 0)
X	Delay(seconds*TICKS_PER_SECOND);
X}
X
X/*
X * Now here are tmsg() and tchar() for putting out warnings.  What I've done
X * is to use tchar()'s argument as a flag to put out whatever status we need.
X * tmsg()'s argument is put out as a message line.
X */
X
X/*
X * tchar(c)--put the single character c onto the user's screen as part
X * of Kermit's communication to said user.
X */
Xvoid
Xtchar(c)
Xchar c;
X{
X    char status[80];
X    void tmsg();
X
X    switch (c) {
X	case '.':
X	    npackets++;
X	    break;
X	case '%':
X	    naks++;
X	    break;
X	default:
X	    status[0] = c;
X	    status[1] = '\0';
X	    tmsg(status);			/* Output unknown chars */
X	    return;
X    }
X    sprintf(status, "Packets: %4d Retries: %4d", npackets, naks);
X    InfoMsgNoScroll(status);
X}
X
X/*
X * tmsg(s) char *s;--Put a message string onto the user's screen as part
X * of the communication from Kermit.
X *
X * I put out a message using InfoMsg.  We store it up until we get a newline,
X * then we scroll and put it out.
X */
X
Xvoid
Xtmsg(more_message)
Xchar *more_message;
X{
X    /*
X     * If new message won't fit, put out message so far and copy it.
X     * Otherwise, just catenate new message to old.
X     */
X    if (strlen(more_message) + strlen(message) < sizeof(message)) {
X	strcat(message,more_message);
X    } else {
X	InfoMsg1Line(message);
X	strcpy(message,more_message);
X    }
X}
X
X/*
X * tmsgl(s) char *s;--Put out a newline-terminated message to the user's
X * screen as part of Kermit communication.
X */
Xvoid
Xtmsgl(more_message)
Xchar *more_message;
X{
X    tmsg(more_message);
X    InfoMsg1Line(message);
X    message[0] = '\0';
X}
X
SHAR_EOF
echo "extracting remote.c"
sed 's/^X//' << \SHAR_EOF > remote.c
X/****************************************************
X * vt100 emulator - remote character interpretation
X *		:ts=8
X *
X *	V2.9 ACS - CAN was not cancelling a control sequence (thanks
X *		   to Bill Kinnersly.
X *	V2.8		  Insert/delete character (@/P) by John Wang
X *			  (jwang@ATRP.MEDIA.MIT.EDU)
X *	v2.7 870227 ACS - No changes to this routine.
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 860803 DRB - Rewrote the control sequence parser
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 int    p[10];
Xstatic int    numpar;
Xstatic char   escseq[40];
X
Xstatic void doalt(), doline();
X
X/************************************************
X*  function to handle remote characters
X*************************************************/
Xvoid doremote(c)
Xchar c;
X    {
X    if (c == 24) { inesc = -1; inctrl = -1; return; }
X    if (c == 27 || (inesc >= 0 && c >= ' ')) { doesc(c); return; }
X    if (inctrl >= 0 && c >= ' ') { doctrl(c); return; }
X    if (c == 10 || c == 11 || c == 12) {
X	if (nlmode) doindex('E'); else doindex('D');
X	return;
X	}
X    if (c == 13) {
X	if (!nlmode) emit(c);
X	return;
X	}
X    if (c == 15) { alt = 0; return; }
X    if (c == 14) { alt = 1; return; }
X    if (a[alt] && c > 94 && c < 127) { doalt(c); return; }
X    emit(c);
X    }
X
Xvoid doesc(c)
Xchar c;
X{
X    if (inesc < 0) { inesc = 0; return; }
X    if (c == 27 || c == 24) { inesc = -1; return; }
X    if (c < ' ' || c == 127) return;	  /* Ignore control chars */
X
X    /* Collect intermediates */
X    if (c < '0') {escseq[inesc++] = c; return; }
X
X    /* by process of elimination, we have a final character.
X       Put it in the buffer, and dispatch on the first character
X       in the buffer */
X
X    escseq[inesc] = c;
X    inesc = -1;				/* No longer collecting a sequence */
X    switch (escseq[0])			/* Dispatch on the first received */
X    {
X      case '[':				/* Control sequence introducer */
X	numpar = 0;			/* No parameters yet */
X	private = 0;			/* Not a private sequence (yet?) */
X	badseq = 0;			/* Good until proven bad */
X	p[0] = p[1] = 0;		/* But default the first parameter */
X	inctrl = 0;			/* We are in a control sequence */
X	return;				/* All done for now ... */
X
X      case 'D': case 'E': case 'M':	/* Some kind of index */
X	doindex (c);			/* Do the index */
X	return;				/* Return */
X
X      case '7':				/* Save cursor position */
X	savx = x; savy = y; savmode = curmode; savalt = alt;
X	sa[0] = a[0]; sa[1] = a[1];
X	return;
X
X      case '8':				/* Restore cursor position */
X	x = savx; y = savy; alt = savalt; curmode = savmode;
X	a[0] = sa[0]; a[1] = sa[1];
X	return;
X
X      case 'c':				/* Reset */
X	top = MINY; bot = MAXY; savx = MINX; savy = MINY;
X	curmode = FS_NORMAL; p_keyapp = 0; p_curapp = 0;
X	inesc = -1;
X	a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0;
X	redoutil();
X	emit(12);
X	return;
X
X      case '(':				/* Change character set */
X	if (c == '0' || c == '2') a[0] = 1; else a[0] = 0;
X	return;
X
X      case ')':				/* Change the other character set */
X	if (c == '0' || c == '2') a[1] = 1; else a[1] = 0;
X	return;
X
X      case '=':				/* set keypad application mode */
X	p_keyapp = 1;
X	redoutil();
X	return;
X
X      case '>':				/* reset application mode */
X	p_keyapp = 0;
X	redoutil();
X	return;
X
X      case 'Z':
X	sendchar(27); sendstring("[?1;7c"); return;
X
X      /* If we didn't match anything, we can just return, happy in the
X	 knowledge that we've at least eaten the whole sequence */
X
X    }					/* End of switch */
X    return;
X}
X
Xvoid doctrl(c)
Xchar c;
X{
X    int	    i;
X
X    if (c == 27 || c == 24) { inctrl = -1; return; }
X    if (c < ' ' || c == 127) return;		  /* Ignore control chars */
X
X    /* First, look for some parameter characters.  If the very first
X	parameter character isn't a digit, then we have a
X	private sequence */
X
X    if (c >= '0' && c < '@')
X    {
X	/* can't have parameters after intermediates */
X	if (inctrl > 0) {badseq++ ; return; }
X	switch (c)
X	{
X	  case '0': case '1': case '2': case '3': case '4':
X	  case '5': case '6': case '7': case '8': case '9':
X	    p[numpar] = p[numpar] * 10 + (c - '0');
X	    return;
X
X	  case ';':
X	    p[++numpar] = 0;		/* Start a new parameter */
X	    return;
X
X	  case '<': case '=': case '>': case '?': /* Can only mean private */
X
X	    /* Only allowed BEFORE parameters */
X	    if (inctrl == 0) private = c;
X	    return;
X
X	/* if we come here, it's a bad sequence */
X	}
X	badseq++;			/* Flag the bad sequence */
X    }
X
X    if (c < '0')			/* Intermediate character */
X    {
X	escseq[inctrl++] = c;		/* Save the intermediate character */
X	return;
X    }
X
X    /* if we get here, we have the final character.  Put it in the
X       escape sequence buffer, then dispatch the control sequence */
X
X    numpar++;				/* Reflect the real number of parameters */
X    escseq[inctrl++] = c;		/* Store the final character */
X    escseq[inctrl] = '\000';		/* Tie off the buffer */
X    inctrl = -1;			/* End of the control sequence scan */
X
X    /* Don't know how to do most private sequences right now,
X	so just punt them */
X
X    if ((private != 0 && private != '?') || badseq != 0) return;
X    if (private == '?' && escseq[0] != 'h' &&
X	escseq[0] != 'l') return;
X
X    switch (escseq[0])			/* Dispatch on first intermediate or final */
X    {
X      case 'A': if (p[0]<=0) p[0] = 1;
X		y -= Ysize*p[0]; if (y<top)  y = top;  return;
X      case 'B': if (p[0]<=0) p[0] = 1;
X		y += Ysize*p[0]; if (y>bot)  y = bot;  return;
X      case 'C': if (p[0]<=0) p[0] = 1;
X		x += Ysize*p[0]; if (x>MAXX) x = MAXX; return;
X      case 'D': if (p[0]<=0) p[0] = 1;
X		x -= Ysize*p[0]; if (x<MINX) x = MINX; return;
X
X      case 'H': case 'f':		/* Cursor position */
X	if (p[0] <= 0) p[0] = 1;
X	if (p[1] <= 0) p[1] = 1;
X	y = (--p[0]*Ysize)+MINY; x = (--p[1]*Ysize)+MINX;
X	if (y > MAXY) y = MAXY;
X	if (x > MAXX) x = MAXX;
X	if (y < MINY) y = MINY;
X	if (x < MINX) x = MINX;
X	return;
X
X      case 'L':				/* ANSI insert line */
X      case 'M':				/* ANSI delete line */
X	if (p[0] <= 0) p[0] = 1;
X	ScrollRaster(mywindow->RPort,
X	    0L, (long)((escseq[0] == 'M' ? Ysize : -Ysize) * p[0]),
X	    (long)MINX, (long)(y-BaseLine),
X	    (long)(MAXX+Xsize-1), (long)bot+Ysize-BaseLine-1 );
X	return;
X
X      case '@':				/* Insert characters */
X      case 'P':				/* Delete characters */
X	if (p[0] <= 0) p[0] = 1;
X	ScrollRaster(mywindow->RPort, 
X	   	(long) ((escseq[0] == 'P'? Ysize : -Ysize)) * p[0], 0L,
X		(long) x, (long)(y - BaseLine),
X		(long) MAXX+Xsize-1, (long)(y+Ysize-BaseLine-1) );
X	return;
X
X      case 'r':				/* Set scroll region */
X	if (p[0] <= 0) p[0] = 1;
X	if (p[1] <= 0) p[1] = p_lines;
X	top = (--p[0]*Ysize)+MINY; bot = (--p[1]*Ysize)+MINY;
X	if (top < MINY) top = MINY;
X	if (bot > MAXY) bot = MAXY;
X	if (top > bot) { top = MINY; bot = MAXY; }
X	x = MINX; y = MINY;
X	return;
X
X      case 'm':				/* Set graphic rendition */
X	for (i=0;i<numpar;i++) {
X	    if (p[i] < 0) p[i] = 0;
X	    switch (p[i]) {
X		case 0:
X		curmode  = FS_NORMAL;
X		break;
X
X		case 1:
X		curmode |= FSF_BOLD;
X		break;
X
X		case 4:
X		curmode |= FSF_UNDERLINED;
X		break;
X
X		case 5:
X		curmode |= FSF_ITALIC;
X		break;
X
X		default:
X		curmode |= FSF_REVERSE;
X		break;
X		}
X	    }
X	return;
X
X      case 'K':				/* Erase in line */
X	doerase();
X	return;
X
X      case 'J':				/* Erase in display */
X	if (p[0] < 0) p[0] = 0;
X	SetAPen(mywindow->RPort,0L);
X	if (p[0] == 0) {
X	    if (y < MAXY) RectFill(mywindow->RPort,
X		(long)MINX,(long)(y+(Ysize-BaseLine)),
X		(long)(MAXX+Xsize-1),
X		(long)(MAXY+(Ysize-BaseLine-1)));
X	    }
X	else if (p[0] == 1) {
X	    if (y > MINY) RectFill(mywindow->RPort,
X		(long)MINX,
X		(long)(MINY-BaseLine),
X		(long)(MAXX+Xsize-1),
X		(long)(y-BaseLine-1));
X	    }
X	else RectFill(mywindow->RPort,
X	    (long)MINX,
X	    (long)(MINY-BaseLine),
X	    (long)(MAXX+Xsize-1),
X	    (long)(MAXY+(Ysize-BaseLine-1)));
X	SetAPen(mywindow->RPort,1L);
X	doerase(); return;
X
X      case 'h':				/* Set parameter */
X	if (private == 0 && p[0] == 20)		nlmode = 1;
X	else if (private == '?') {
X	    if      (p[0] == 7)	p_wrap   = 1;
X	    else if (p[0] == 1)	p_curapp = 1;
X	    redoutil();
X	    }
X	return;
X
X      case 'l':				/* Reset parameter */
X	if (private == 0 && p[0] == 20)		nlmode = 0;
X	else if (private == '?') {
X	    if      (p[0] == 7)	p_wrap   = 0;
X	    else if (p[0] == 1) p_curapp = 0;
X	    redoutil();
X	    }
X	return;
X
X      case 'x':
X	sendchar(27); sendstring("[3;1;8;64;64;1;0x"); return;
X
X      case 'n':
X	if (p[0] == 6) {
X	    sendchar(27);
X	    sprintf(escseq,"[%d;%dR",((y-MINY)/Ysize)+1,((x-MINX)/Xsize)+1);
X	    sendstring(escseq); return;
X	    }
X	sendchar(27); sendstring("[0n"); return;
X
X      case 'c':
X	sendchar(27); sendstring("[?1;7c"); return;
X    }
X
X    /* Don't know how to do this one, so punt it */
X}
X
Xvoid doindex(c)
Xchar c;
X    {
X    if (c != 'M') {
X	if (c == 'E') x = MINX;
X	if (y > bot) if (y < MAXY) y += 8;
X	if (y == bot)
X	    ScrollRaster(mywindow->RPort,
X		0L, (long)Ysize,
X		(long)MINX, (long)(top-BaseLine),
X		(long)(MAXX+Xsize-1), (long)(bot+(Ysize-BaseLine-1)) );
X	if (y < bot) y += Ysize;
X	}
X    else {
X	if (y < top) if (y > MINY) y -= BaseLine;
X	if (y == top)
X	    ScrollRaster(mywindow->RPort,0L,
X		(long)-Ysize,
X		(long)MINX,
X		(long)(top-BaseLine),
X		(long)(MAXX+Xsize-1),
X		(long)(bot+(Ysize-BaseLine-1)));
X	if (y > top) y -= Ysize;
X	}
X    return;
X    }
X
Xstatic void
Xdoalt(c)
Xchar c;
X    {
X    int oldx,newx;
X    inesc = -1;
X    oldx = x; emit(' '); newx = x;
X    x = oldx;
X    SetAPen(mywindow->RPort,1L);
X    switch (c) {
X	case 'a':
X	doline(0,-BaseLine,Xsize,1);
X	break;
X
X	case 'j':
X	case 'm':
X	case 'v':   doline(Xsize/2,-BaseLine,Xsize/2,-(Ysize-BaseLine));
X	if      (c=='j')  doline(0,-(Ysize-BaseLine),Xsize/2,-(Ysize-BaseLine));
X	else if (c=='m')  doline(Xsize/2,-(Ysize-BaseLine),Xsize,-(Ysize-BaseLine));
X	else              doline(0,-(Ysize-BaseLine),Xsize,-(Ysize-BaseLine));
X	break;
X
X	case 'k':
X	case 'l':
X	case 'w': doline(Xsize/2,-(Ysize-BaseLine),Xsize/2,1);
X	if      (c=='k')  doline(0,-(Ysize-BaseLine),Xsize/2,-(Ysize-BaseLine));
X	else if (c=='l')  doline(Xsize/2,-(Ysize-BaseLine),Xsize,-(Ysize-BaseLine));
X	else              doline(0,-(Ysize-BaseLine),Xsize,-(Ysize-BaseLine));
X	break;
X
X	case 'n':
X	case 'q': doline(0,-(Ysize-BaseLine),Xsize,-(Ysize-BaseLine));
X	if      (c=='n')  doline(Xsize/2,-BaseLine,Xsize/2,Ysize-BaseLine);
X	break;
X
X	case 't':
X	case 'u':
X	case 'x':   doline(Xsize/2,-BaseLine,Xsize/2,1);
X	if      (c=='t')  doline(Xsize/2,-(Ysize-BaseLine),Xsize,-(Ysize-BaseLine));
X	else if (c=='u')  doline(0,-(Ysize-BaseLine),Xsize/2,-(Ysize-BaseLine));
X	break;
X	}
X    x = newx;
X}
X
Xstatic void
Xdoline(x1,y1,x2,y2) {
X    RectFill(mywindow->RPort,(long)(x+x1),(long)(y+y1),
X	(long)(x+x2),(long)(y+y2));
X}
X
Xvoid doerase()
X    {
X    if (p[0] < 0) p[0] = 0;
X    SetAPen(mywindow->RPort,0L);
X    if (p[0] == 0) RectFill(mywindow->RPort,
X	(long)x,
X	(long)(y-BaseLine),
X	(long)(MAXX+Xsize-1),
X	(long)(y+(Ysize-BaseLine-1)));
X    else if (p[0] == 1) RectFill(mywindow->RPort,
X	(long)MINX,
X	(long)(y-BaseLine),
X	(long)(x+Xsize-1),
X	(long)(y+(Ysize-BaseLine-1)));
X    else RectFill(mywindow->RPort,
X	(long)MINX,
X	(long)(y-BaseLine),
X	(long)(MAXX+Xsize-1),
X	(long)(y+(Ysize-BaseLine-1)));
X    SetAPen(mywindow->RPort,1L);
X    return;
X    }
X
SHAR_EOF
echo "extracting rexx.c"
sed 's/^X//' << \SHAR_EOF > rexx.c
X/*************************************************************
X * vt100 terminal emulator - AREXX support
X *				:ts=8
X *
X *	v2.9 ACS - New with this version.
X *
X *************************************************************/
X
X#ifdef AREXX
X
X#include "vt100.h"
X
Xint RexxReplies = 0;			/* # outstanding replies */
X
Xextern int doing_init;			/* in init.c		*/
X
Xextern char *extension;			/* in vt100.c		*/
X
X#define AREXXCOMMAND 2
X/*   Derived from:
X *
X *  REXX.C
X *
X *	(c) Copyright 1987 by Kim DeVaughn, All Rights Reserved
X *
X *  ARexx interface code, etc.
X *
X */
X
Xdo_rx(cmd, implied)
Xchar *cmd;
Xint implied;
X{
X    int	len, ret = 0;
X    char *p;
X    register struct RexxMsg *RexxMsg;
X    struct MsgPort *RexxPort;
X
X    if(cmd == NULL || *cmd == '\0')
X	return ret;
X
X    if(RexxSysBase == NULL) {
X        if((RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L)) == NULL)
X            return NORXLIB;
X        if( (ret = makerexxport()) != 0)
X	    return ret;
X    }
X
X    for(len = 0, p = cmd; *p != '\n' && *p != '\0'; p++, len++)
X	;
X
X    Forbid();
X    if((RexxPort = FindPort(RXSDIR))) {
X	if((RexxMsg = CreateRexxMsg(FromRexxPort, extension, HostName)) &&
X	   (ARG0(RexxMsg) = (STRPTR)CreateArgstring(cmd, (LONG)len)) ) {
X	    ARG1(RexxMsg) = (STRPTR)AREXXCOMMAND;
X	    RexxMsg->rm_Action = RXCOMM;
X	    PutMsg(RexxPort, (struct Message *)RexxMsg);
X	    RexxReplies++;
X	} else
X	    ret = NORXMSG;
X    } else
X	ret = NORXPORT;
X    Permit();
X    return ret;
X}
X
Xvoid
Xprocessrexxmsg(RexxMsg)
Xregister struct RexxMsg *RexxMsg;
X{
X    extern char *next_wrd();
X    register char *arg0 = NULL, *arg1 = NULL;
X    char *command = NULL,
X	 *message = NULL,
X	 *errmsg = "AREXX macro not found: ",
X	 *MacDone = "AREXX macro complete: ",
X	 *NoMem = "processrexxmsg: Can't allocate memory for message.";
X    int len = 0;
X
X    arg0 = (char *)ARG0(RexxMsg);
X    arg1 = (char *)ARG1(RexxMsg);
X    if(arg0 && *arg0)
X	command = next_wrd(arg0, &len);
X
X    if(RexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) {
X	/*   Got some kind of reply so we'll assume that the AREXX lib is
X	** available.  If it's a "command not found" then tell the user.  If
X	** it's a command FROM VT100 (marked by AREXXCOMMAND in ARG1) and we
X	** have no outstanding replies then it must mean that a previously
X	** issued AREXX command FROM VT100 has completed, tell the user.
X	** Otherwise, we can just toss the reply.
X	**/
X
X	if(--RexxReplies <= 0)
X	    RexxReplies = 0;
X
X	if(RexxMsg->rm_Result1 == 5 && RexxMsg->rm_Result2 == 1) {
X	    LONG memlen = strlen(errmsg) + len + 1;
X
X	    if(message = AllocMem(memlen, MEMF_PUBLIC | MEMF_CLEAR)) {
X		strcpy(message, errmsg);
X		strncat(message, command, len);
X		if(doing_init) {
X		    puts("Init:");
X		    puts(message);
X		} else
X		    InfoMsg2Line("Script:", message);
X		FreeMem(message, memlen);
X	    } else {
X		if(doing_init) {
X		    puts("Init:");
X		    puts(NoMem);
X		} else
X		    InfoMsg2Line("Script:", NoMem);
X	    }
X	}
X
X	if(arg1 == (char *)AREXXCOMMAND) {
X	    if(RexxReplies == 0 && command) {
X		LONG memlen = strlen(MacDone) + strlen(command) + 1;
X
X		if(message = AllocMem(memlen, MEMF_PUBLIC | MEMF_CLEAR)) {
X		    strcpy(message, MacDone);
X		    strcat(message, command);
X		    if(doing_init) {
X			puts("Init:");
X			puts(message);
X		    } else
X			InfoMsg1Line(message);
X		    FreeMem(message, memlen);
X		} else {
X		    if(doing_init) {
X			puts("Init:");
X			puts(NoMem);
X		    } else
X			InfoMsg2Line("Script:", NoMem);
X		}
X	    }
X	}
X
X	DeleteArgstring(arg0);
X	ARG0(RexxMsg) = NULL;
X	ARG1(RexxMsg) = NULL;
X	DeleteRexxMsg(RexxMsg);
X
X	return;
X    } else if(RexxMsg->rm_Action == RXCOMM) {
X	int ret;
X	LONG memlen = strlen(arg0) + 1;
X
X	CmdFromRexx = 1;	/* Tell everyone from whence it came */
X	command = AllocMem(memlen, MEMF_PUBLIC | MEMF_CLEAR);
X	strcpy(command, arg0);
X	next_wrd(command, &len);
X
X	RexxMsg->rm_Result1 = exe_cmd(command, len);
X	CmdFromRexx = 0;
X	FreeMem(command, memlen);
X    } else {
X	RexxMsg->rm_Result1 = 5;
X	RexxMsg->rm_Result2 = 1;
X    }
X    ReplyMsg((struct Message *)RexxMsg);
X}
X#endif /* AREXX */
SHAR_EOF
echo "extracting script.c"
sed 's/^X//' << \SHAR_EOF > script.c
X/*************************************************************
X * vt100 terminal emulator - Script file support
X *				:ts=8
X *
X *	v2.9 ACS - Add support for font size, external transfer program
X *		   support, new ASIS option to LACE cmd and AREXX support.
X *	v2.8a 880331 ACS - Allow comments on XPROTO and FONT.
X *	v2.7 870825 ACS - Wait for the reply from AbortIO().
X *			  Use the *InfoMsg*() routines in window.c.  Provide
X *			  for multiple script files on command line
X *			  (companion to the changes in init.c).  Add the
X *			  ability to set shortcuts from init file.
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 BAUD, PARITY and WORD commands & handling
X *	     860823 DBW - Integrated and rewrote lots of code
X *	     860815 Steve Drew: Initial version written of SCRIPT.C
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
X#define DNMAXLEN	9
X
Xextern struct MsgPort *mySerPort;	/* in vt100.c */
X
Xstruct COMMAND {
X    int (*func)();
X    char *cname;
X    int	minlen;
X    int	validfrom;
X};
X
X#define INIT		1
X#define SCRIPT		2
X#define NONREXX		4
X#define REXXONLY	8
X
Xstruct LABEL  {
X    struct LABEL *next;
X    char *name;
X    long pos;
X};
X
Xextern long atol();
X
X#if MANX
Xextern char *index();
X#endif	/* MANX */
X
X#if LATTICE
X#define index(a,b) stpchr(a,b)
X#endif	/* LATTICE */
X
Xstruct SHORT_CUTS {
X    char *cname;
X    char *pos;
X};
X    
X/*   Following variables are set up in init.c's InitDefaults.  They tell
X** us if there are any other script files listed on the command line so
X** that we can execute them when a prior script is done.  */
X
Xextern int script_files_todo;
Xextern char **script_files;
X
X/****************  globals  needed  ******************/
X
Xchar		on_string[20];	     /* string to match on for on cmd	 */
Xchar		wait_string[20];     /* string to match of for wait cmd  */
Xchar		golabel[20];	     /* label we are looking for in goto */
Xchar		on_cmd[20];	     /* command to execute when on matchs*/
Xint		onsize;		     /* size of on_string		 */
Xint		waitsize;	     /* size of wait_string		 */
Xint		onpos;		     /* position in on string for search */
Xint		waitpos;	     /* pos in wait_string for search	 */
Xint		on_match;	     /* flag set while doing on_cmd	 */
XFILE		*sf = NULL;	     /* file pointer for script file	 */
Xstruct LABEL	*lbase = NULL;	     /* will point to first label	 */
Xstruct LABEL	*labels;	     /* current label pointer		 */
Xchar		errmsg[80];	     /* Error msg from routines		 */
X#if AREXX
Xint		implied_rexx;	    /* cmd_rx() invoked as impled cmd	 */
X#endif /* AREXX */
X
X/************************ command table *********************************/
Xstatic struct COMMAND commands[] = {
Xcmd_appcur,	"appcursor",	3, INIT|SCRIPT,	/* turn app. cursor on/off	*/
Xcmd_as,		"ascii",	3, SCRIPT,	/* ascii send			*/
Xcmd_ac,		"autochop",	3, INIT|SCRIPT,	/* XMODEM autochop		*/
Xcmd_bkg,	"background",	3, INIT,	/* set background color		*/
Xcmd_baud,	"baud",		3, INIT|SCRIPT,	/* Set Baud Rate		*/
Xcmd_beep,	"beep",		3, SCRIPT,	/* Beep				*/
Xcmd_bold,	"bold",		3, INIT,	/* set bold color		*/
Xcmd_bt,		"breaktime",	3, INIT|SCRIPT,	/* Set Break Time		*/
Xcmd_buf,	"buffer",	3, INIT,	/* set buffer size		*/
Xcmd_cap,	"capture",	3, SCRIPT,	/* ascii capture on/off		*/
Xcmd_cd,		"cd",		2, SCRIPT,	/* change directory		*/
Xcmd_conv,	"convert",	4, INIT|SCRIPT,	/* convert fn to lowercase	*/
Xcmd_cursor,	"cursor",	3, INIT,	/* set cursor color		*/
Xcmd_delay,	"delay",	3, SCRIPT,	/* delay amount of seconds	*/
Xcmd_depth,	"depth",	3, INIT,	/* set screen depth		*/
Xcmd_device,	"device",	3, INIT,	/* set serial device name	*/
Xcmd_display,	"display",	3, SCRIPT,	/* Display data on screen	*/
Xcmd_echo,	"echo",		3, INIT|SCRIPT,	/* turn echo on or off		*/
Xcmd_exit,	"exit",		3, INIT|SCRIPT|NONREXX,	/* exit script file	*/
Xcmd_ext,	"external",	4, INIT|SCRIPT,	/* external xfer pgms		*/
Xcmd_fnc,	"f",		1, INIT|SCRIPT,	/* define function key		*/
Xcmd_font,	"font",		3, INIT,	/* set font			*/
Xcmd_fonts,	"fontsize",	5, INIT,	/* set fontsize			*/
Xcmd_fore,	"foreground",	3, INIT,	/* set foreground color		*/
X#if AREXX
Xcmd_fwd,	"forward",	3, REXXONLY,	/* forward data to rexx		*/
X#endif /* AREXX */
Xcmd_goto,	"goto",		3, SCRIPT|NONREXX,/* goto label			*/
Xcmd_inter,	"interlace",	3, INIT,	/* interlace ON/OFF		*/
Xcmd_kb,		"kb",		2, SCRIPT,	/* kermit bye (for server)	*/
Xcmd_key,	"keyscript",	3, INIT|SCRIPT,	/* keyscript character		*/
Xcmd_kg,		"kg",		2, SCRIPT,	/* kermit get file		*/
Xcmd_kmaxpk,	"kmaxpack",	8, INIT|SCRIPT,	/* Kermit maximum packet size	*/
Xcmd_kr,		"kr",		2, SCRIPT,	/* kermit receive file		*/
Xcmd_ks,		"ks",		2, SCRIPT,	/* kermit send file		*/
Xcmd_lines,	"lines",	3, INIT,	/* num lines			*/
Xcmd_mode,	"mode",		3, INIT|SCRIPT,	/* KERMIT transfer mode		*/
Xcmd_mouse,	"mouse",	3, INIT|SCRIPT,	/* Mouse control		*/
Xcmd_msg,	"msg",		3, SCRIPT,	/* Display a message		*/
Xcmd_numkey,	"numkey",	6, INIT|SCRIPT,	/* turn numeric kpad on/off	*/
Xcmd_on,		"on",		2, SCRIPT,	/* on a 'string' do a cmd	*/
Xcmd_parity,	"parity",	6, INIT|SCRIPT,	/* Set Parity			*/
Xcmd_recf,	"recfile",	4, SCRIPT,	/* receive a file from host	*/
Xcmd_rx,		"rx",		2, INIT|SCRIPT,	/* Specific invocation		*/
Xcmd_sb,		"sb",		2, SCRIPT,	/* Send a break			*/
Xcmd_screen,	"screen",	3, INIT,	/* Screen WB/CUST		*/
Xcmd_send,	"send",		4, SCRIPT,	/* send string to host		*/
Xcmd_sendf,	"sendfile",	5, SCRIPT,	/* send a file to host		*/
Xcmd_share,	"shareserial",	5, INIT|SCRIPT,	/* ShareSerial device		*/
Xcmd_short,	"shortcut",	3, INIT,	/* Set shortcuts		*/
Xcmd_swap,	"swap",		4, INIT|SCRIPT,	/* Swap BS and DEL		*/
Xcmd_unit,	"unit",		4, INIT,	/* Unit of serial.device to use */
Xcmd_volume,	"volume",	3, INIT,	/* set volume			*/
Xcmd_wait,	"wait",		4, SCRIPT|NONREXX, /* wait for a host string	*/
Xcmd_wb,		"wbcolors",	3, INIT,	/* use WB colors		*/
Xcmd_wrap,	"wrap",		4, INIT|SCRIPT,	/* turn wrap on or off		*/
Xcmd_xbeep,	"xbeep",	4, INIT|SCRIPT,	/* Beep at end of xfer		*/
Xcmd_xproto,	"xprotocol",	5, INIT|SCRIPT,	/* Xfer Protocol		*/
Xcmd_xr,		"xr",		2, SCRIPT,	/* xmodem receive file		*/
Xcmd_xs,		"xs",		2, SCRIPT,	/* xmodem send file		*/
Xcmd_null,	NULL,		0, 0 	/* mark the end of the list	*/
X};
X
Xchar *xprotos[] = {	/* Order *must* be same as corresponding p_xproto values */
X    "ascii", "xmodem", "xmodemcrc", "kermit" };
X
X/*   NB: The structures referenced in the structure may be found in
X** init.c */
Xextern struct filecmd {
X    char mo;	/* Mode			*/
X    char se;	/* Send			*/
X    char re;	/* Receive		*/
X    char kg;	/* Kermit Get		*/
X    char kb;	/* Kermit Bye		*/
X    char ca;	/* Capture or Capturing */
X    char nl;
X} filecmd_chars;
X
Xextern struct mode_cmd {
X    char as;	/* ascii mode		*/
X    char xm;	/* xmodem mode		*/
X    char xmc;	/* xmodem crc mode	*/
X    char ke;	/* kermit mode		*/
X    char nl;
X} modecmd_chars;
X
Xextern struct baducmd {
X    char b03;	/* 0300			*/
X    char b12;	/* 1200			*/
X    char b24;	/* 2400			*/
X    char b48;	/* 4800			*/
X    char b96;	/* 9600			*/
X    char bnl;
X} baudcmd_chars;
X
Xextern struct parcmd {
X    char no;	/* NOne			*/
X    char ma;	/* MArk			*/
X    char sp;	/* SPace		*/
X    char ev;	/* EVen			*/
X    char od;	/* ODd			*/
X    char nl;
X} parcmd_chars;
X
Xextern struct commcmd {
X    char nl0;	/* Baud Sub-Item	*/
X    char nl1;	/* Parity Sub-Item	*/
X    char nl2;	/* Xfer mode Sub-Item	*/
X    char sh;	/* Shared item		*/
X    char nl;
X} commcmd_chars;
X
Xextern struct modcmd {
X    char im;	/* IMage		*/
X    char tx;	/* TeXt			*/
X    char cn;	/* CoNvert		*/
X    char ac;	/* AutoChop		*/
X    char nl;
X} modcmd_chars;
X
Xextern struct scrcmd {
X    char em;	/* Execute Macro	*/
X    char ab;	/* Abort Macro		*/
X    char rx;	/* AREXX Macro		*/
X    char nl;
X} scrcmd_chars;
X
Xextern struct {
X    char sb;	/* Send Break	*/
X    char hu;	/* Hang Up	*/
X    char cd;	/* Change Dir	*/
X    char cs;	/* Clear Screen	*/
X    char ec;	/* ECho		*/
X    char wr;	/* WRap		*/
X    char nk;	/* Num Key	*/
X    char ac;	/* App Cur	*/
X    char bs;	/* BS<->DEL	*/
X    char xb;	/* Beep at end of Xfer	*/
X    char mu;	/* Mouse up events	*/
X    char md;	/* Mouse down events	*/
X    char nl;
X} utilcmd_chars;
X
Xstatic struct SHORT_CUTS shortkeys[] = {	/* Short-cut keys */
X	/* File items: */
X    "se", &(filecmd_chars.se),		/* Send file			*/
X    "re", &(filecmd_chars.re),		/* Receive file			*/
X    "kb", &(filecmd_chars.kb),		/* kermit bye (for server)	*/
X    "kg", &(filecmd_chars.kg),		/* kermit get (for server)	*/
X    "cap", &(filecmd_chars.ca),		/* Capture			*/
X	/* Mode items:	*/
X    "asc", &(modecmd_chars.as),		/* ascii mode			*/
X    "xmc", &(modecmd_chars.xmc),	/* xmodemcrc mode		*/
X    "xm", &(modecmd_chars.xm),		/* xmodem mode			*/
X    "ke", &(modecmd_chars.ke),		/* kermit mode			*/
X	/* Comm items:	*/
X    "share", &(commcmd_chars.sh),	/* Shared			*/
X    "300", &(baudcmd_chars.b03),	/* Set Baud Rate		*/
X    "1200", &(baudcmd_chars.b12),	/* Set Baud Rate		*/
X    "2400", &(baudcmd_chars.b24),	/* Set Baud Rate		*/
X    "4800", &(baudcmd_chars.b48),	/* Set Baud Rate		*/
X    "9600", &(baudcmd_chars.b96),	/* Set Baud Rate		*/
X    "none", &(parcmd_chars.no),		/* Set Parity			*/
X    "mark", &(parcmd_chars.ma),		/* Set Parity			*/
X    "space", &(parcmd_chars.sp),	/* Set Parity			*/
X    "even", &(parcmd_chars.ev),		/* Set Parity			*/
X    "odd", &(parcmd_chars.od),		/* Set Parity			*/
X    "image", &(modcmd_chars.im),	/* KERMIT transfer mode		*/
X    "text", &(modcmd_chars.tx),		/* KERMIT transfer mode		*/
X    "convert", &(modcmd_chars.cn),	/* KERMIT transfer mode		*/
X    "autochop", &(modcmd_chars.ac),	/* XMODEM autochop		*/
X	/* Script items:	*/
X    "execute", &(scrcmd_chars.em),	/* execute macro		*/
X    "abort", &(scrcmd_chars.ab),	/* abort macro			*/
X    "rx", &(scrcmd_chars.rx),		/* rexx macro			*/
X	/* Util items: */
X    "sb", &(utilcmd_chars.sb),		/* send break			*/
X    "hang", &(utilcmd_chars.hu),	/* hang up			*/
X    "cd", &(utilcmd_chars.cd),		/* change directory		*/
X    "clear", &(utilcmd_chars.cs),	/* clear screen			*/
X    "ech", &(utilcmd_chars.ec),		/* turn echo on or off		*/
X    "wrap", &(utilcmd_chars.wr),	/* turn wrap on or off		*/
X    "numkey", &(utilcmd_chars.nk),	/* turn numeric kpad on/off	*/
X    "app", &(utilcmd_chars.ac),		/* turn app. cursor on/off	*/
X    "con", &(utilcmd_chars.bs),		/* convert bs to del		*/
X    "swap", &(utilcmd_chars.bs),	/* Swap BS and DEL		*/
X    "xbeep", &(utilcmd_chars.xb),	/* Beep at end of xfer		*/
X    "mouseup", &(utilcmd_chars.mu),	/* Mouse up events		*/
X    "mousedn", &(utilcmd_chars.md),	/* Mouse dn events		*/
X    NULL, NULL
X};
X
Xstatic int cmd_from_script;		/* != 0 iff cmd from a script	*/
X
X
X/********************************************************************/
X/* checks char to see if match with on string or wait_string	    */
X/* if on string match oncmd gets executed imediately,		    */
X/* if wait_string match script_wait is set.			    */
X/********************************************************************/
X
Xchk_script(c)
Xchar c;
X{
X    if (on_string[0] != '\0') {
X	if (on_string[onpos] == c) {
X	    onpos++;
X	    if (onpos == onsize) {
X		on_match = TRUE;
X		do_script_cmd(ONCOMMAND);
X		on_match = FALSE;
X		on_string[0] = '\0';
X		on_cmd[0] = '\0';
X		onpos = 0;
X		return(0);
X	    }
X	}
X	else onpos = 0;
X    }
X    if (wait_string[0] != '\0') {
X       if (wait_string[waitpos] != c) {
X	    waitpos = 0;
X	    return(0);
X	}
X	waitpos++;
X	if (waitpos != waitsize) return(0);
X	wait_string[0] = '\0';
X	script_wait = FALSE;
X    }
X}
X
Xscript_start(file)
Xchar *file;
X{
X    char *sfile = NULL;
X
X    if (strlen(file) == 0 || *file == '#') return(0);
X    if ((sf = fopen(file, "r")) == NULL) {
X	    sfile = AllocMem((LONG)(strlen(file)+3), MEMF_PUBLIC|MEMF_CLEAR);
X	    strcpy(sfile, "S:");
X	    strcat(sfile, file);
X	    if((sf = fopen(sfile, "r")) == NULL) {
X		InfoMsg2Line("Can't open script file",file);
X		return(0);
X	    }
X    }
X    script_on = TRUE;
X    script_wait = FALSE;
X    wait_string[0] = '\0';
X    on_string[0] = '\0';
X    on_match = FALSE;
X    lbase = NULL;
X    if(sfile)
X	FreeMem(sfile, (LONG)strlen(file)+3);
X}
X
X/* return pointer to next word. set l to size of the word */
X
Xchar *next_wrd(s,l)
Xchar *s;
Xint *l;
X{
X    char *p;
X
X    while(*s && (*s == ' ' || *s == '\t')) s++;
X    p = s;
X    while(*s && (*s != ' ' && *s != '\t')) s++;
X    *l = s-p;
X    return(p);
X}
X
Xexe_cmd(p,l)
Xregister char *p;
Xint l;
X{
X    int i, l2, cmdrc = CMDOK;
X    register struct COMMAND *cmd;
X
X    /* downcase the command */
X    for (i=0; i<l; i++) p[i] |= ' ';
X
X    errmsg[0] = '\0';
X
X    /* now search for it */
X    for (cmd = commands; cmd->func != cmd_null; cmd++) {
X	int validfrom = cmd->validfrom;
X
X	if(*p != cmd->cname[0])
X	    continue;
X
X	l2 = strlen(cmd->cname);
X	if(l >= cmd->minlen && l <= l2
X	  && strncmp(p, cmd->cname, l) == 0) {
X	    if( (!doing_init && (validfrom == INIT))
X	    ||  (((validfrom & NONREXX)  == NONREXX)  &&  CmdFromRexx)
X	    ||  (((validfrom & REXXONLY) == REXXONLY) && !CmdFromRexx) )
X		return(CMDBS);
X
X	    cmd_from_script = 1;
X	    cmdrc = (*(cmd->func))(next_wrd(p+l, &l));
X	    cmd_from_script = 0;
X	    if(errmsg[0])
X		if(doing_init) {
X		    puts("Init:");
X		    puts(errmsg);
X		} else
X		    InfoMsg2Line("Script:", errmsg);
X	    return(cmdrc);
X	}
X    }
X#if AREXX
X    if(implied_rexx == 0 && RexxSysBase != NULL) {
X	implied_rexx = 1;
X	cmdrc = cmd_rx(p);
X	implied_rexx = 0;
X	return(cmdrc);
X    }
X#endif /* AREXX */
X
X    if (doing_init) {
X	puts("Init: unknown command:");
X	puts(p);
X    } else
X	InfoMsg2Line("Script - unknown command:",p);
X
X    return(CMDNF);
X}
X
Xstruct LABEL *find_label(lname)
Xchar *lname;
X{
X    struct LABEL *label;
X
X    label = lbase;
X    while(label != NULL) {
X	if (strcmp(label->name, lname) == 0) return (label);
X	label = label->next;
X    }
X    return(NULL);
X}
X
Xdo_script_cmd(stat)
Xint stat;
X{
X    int len,l;
X    char line[256];
X    char *p;
X
X    /* if ON command is matched and we were	*/
X    /* doing a DELAY then abort the delay timer,*/
X    /* except if on_cmd was just a SEND.	*/
X    if (stat == ONCOMMAND) {
X	strcpy(line,on_cmd);
X	p = next_wrd(line,&l);
X	if (*p != 's' && script_wait == WAIT_TIMER)  {
X	    if(!CheckIO((struct IORequest *)&Script_Timer))
X		AbortIO((struct IORequest *)&Script_Timer);
X	    Wait (1L << Script_Timer_Port->mp_SigBit);
X	    WaitIO((struct IORequest *)&Script_Timer);
X
X	    /* script will proceed after on command    */
X	    script_wait = FALSE;
X	}
X	exe_cmd(p,l);
X	return(0);
X    }
X    script_wait = FALSE;
X
X    if(CmdFromRexx)
X	return;
X
X    while(fgets(line,256,sf) != NULL) {
X       len = strlen(line);
X       line[--len] = '\0';
X       p = next_wrd(&line[0], &l);
X       if (*(p + l - 1) == ':') {		/* its a label */
X	   *(p + l - 1) = '\0';
X	   if (find_label(p) == NULL) {		/* it's a new label */
X		if (lbase == NULL)  {		/* it's the first label */
X		    labels = lbase = (struct LABEL *)
X			malloc(sizeof (struct LABEL));
X		}
X		else {
X		    labels->next = (struct LABEL *)
X			malloc(sizeof (struct LABEL));
X		    labels = labels->next;
X		}
X		labels->pos  = ftell(sf);
X		labels->name = malloc(l);
X		labels->next = NULL;
X		strcpy(labels->name, p);
X		if (stat == GOTOLABEL && strcmp(p, golabel) == 0)
X		      stat = NEXTCOMMAND;
X	    }
X	    p = next_wrd(p+l+1, &l);
X	}   /* end of it's a label */
X	if (stat == GOTOLABEL || *p == '#')
X	    continue;
X	if (*p)
X	    exe_cmd(p,l);
X	return(0);
X    }		    /* end of while */
X    if (stat == GOTOLABEL)
X	InfoMsg2Line("Script: label not found:",golabel);
X    exit_script();
X    if(script_files_todo > 0) {
X	script_files_todo--;
X	script_start(*(script_files++));
X    }
X}
X
Xexit_script()
X{
X    if (script_wait == WAIT_TIMER) {	/* timer not done yet */
X	if(!CheckIO((struct IORequest *)&Script_Timer))
X	    AbortIO((struct IORequest *)&Script_Timer); /* so abort it */
X	Wait (1L << Script_Timer_Port->mp_SigBit); /* Wait for the sig */
X	WaitIO((struct IORequest *)&Script_Timer); /* Get my reply back */
X    }
X    InfoMsg1Line("Script: terminated");
X    script_on = FALSE;
X    script_wait = TRUE;
X    on_match = FALSE;
X    wait_string[0] = '\0';
X    on_string[0] = '\0';
X    on_cmd[0] = '\0';
X    fclose(sf);
X    sf = NULL;
X    if (reqwinup && ((reqwindow->Flags) & WINDOWACTIVE))
X	ActivateWindow(mywindow);
X    return 0;
X}
X
X/* remove quotes terminate string & return pointer to start */
X
Xchar *tostring(ptr)
Xchar *ptr;
X{
X    register char *s1, *s2;
X
X    if(*ptr == '\0')
X	return ptr;
X
X    s1 = ptr;
X    if (*ptr == '"') {
X	while(*ptr++) {
X	    if(*ptr == '"')
X		if(*(ptr+1) == '"')
X		    ptr++;
X		else
X		    break;
X	}
X	/*   Only 2 ways out: encounter an single " or hit \0. */
X	if (*ptr == '"')
X	    *ptr = '\0';
X	ptr = s2 = ++s1;
X	while(*s2) {
X	    switch(*s2) {
X	    case '"':
X		if(*(s2+1) == '"')
X		    *s1++ = *s2++;
X		break;
X	    case '^':
X		if(*(s2+1) == '^')
X		    *s1++ = *s2++;
X		else
X		    *s1++ = ((*++s2) | ' ') - 96;
X		break;
X	    default:
X		*s1++ = *s2;
X		break;
X	    }
X	    s2++;
X	}
X	*s1 = '\0';
X	return(ptr);
X    }
X    if (*s1 == '^') {
X	*s1 = (*(s1+1)|' ')-96;
X	*(s1+1) = '\0';
X	return(s1);
X    }
X    *(s1+1) = '\0';
X    return(s1);
X}
X
X/***************************** SCRIPT COMMANDS ********************/
X
Xcmd_goto(lname)
Xchar *lname;
X{
X    struct LABEL *label;
X			    /* if on_cmd was a goto kill wait state */
X    if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; }
X    if ((label = find_label(lname)) == NULL) {	/* is it forward */
X	strcpy(golabel,lname);
X	do_script_cmd(GOTOLABEL);
X    }
X    else {
X	fseek(sf,(long)(label->pos),0);
X    }
X    return 0;
X}
X
Xcmd_send(str)
Xchar *str;
X{
X    register char *p = tostring(str);
X    int i, len = strlen(p);
X
X    if(p_echo)
X	for(i = 0; i < len; i++) {
X	    doremote(*p);
X	    sendchar(*(p++));
X	}
X    else
X	sendstring(p);
X    return 0;
X}
X
Xcmd_wait(str)
Xchar *str;
X{
X    int waitstrsize = sizeof(wait_string) - 1;
X
X    str = tostring(str);
X    strncpy(wait_string, str, waitstrsize);
X    wait_string[waitstrsize] = '\0';
X    waitsize = strlen(wait_string);
X    script_wait = WAIT_STRING;
X    return 0;
X}
X
Xcmd_on(str)
Xchar *str;
X{
X   char *p;
X
X    p = tostring(str);
X    if( (onsize = strlen(p)) == 0) {
X	on_string[0] = '\0';
X	on_cmd[0] = '\0';
X    } else {
X	int onstrsize = sizeof(on_string) - 1,
X	    oncmdsize = sizeof(on_cmd) - 1,
X	    len;
X
X	strncpy(on_string, p, onstrsize);
X	on_string[onstrsize] = '\0';
X	p = next_wrd(p+onsize+1, &len);
X	strncpy(on_cmd, p, oncmdsize);
X	on_cmd[oncmdsize] = '\0';
X    }
X    return 0;
X}
X
Xcmd_delay(seconds)
Xchar *seconds;
X{
X    script_wait = WAIT_TIMER;
X    Script_Timer.tr_time.tv_secs = atoi(seconds);
X    Script_Timer.tr_time.tv_micro = 0;
X    SendIO((struct IORequest *)&Script_Timer.tr_node);
X    return 0;
X}
X
Xcmd_exit(option)
Xchar *option;
X{
X    char *p;
X    int  l;
X
X    if (doing_init)
X	return 0;
X
X    if (*option) {
X	p = next_wrd(option,&l);
X	*(p+l) = '\000';
X	if  (strcmp(p,"vt100") == 0 || strcmp(p,"VT100") == 0)
X	    cleanup("Exit vt100 from script",0);
X	exit_script();
X	script_start(p);
X    }
X    else {
X	exit_script();
X	if(script_files_todo > 0) {
X	    script_files_todo--;
X	    script_start(*(script_files++));
X	}
X    }
X    return 0;
X}
X
Xcmd_ext(parms)
Xchar *parms;
X{
X    struct ExternalXfer *cexp;
X    int i, j, len, nxfer, ci_strcmp(), cmdrc = CMDOK;
X    char *p, temp[80], bound, *send, *dn;
X    unsigned long mem_type = MEMF_PUBLIC | MEMF_CLEAR;
X
X    parms = next_wrd(parms, &len);	/* Step to start of display name */
X    if(len <= 0) {	/* No next word...error */
X	strcpy(errmsg, "No display name for EXT command.");
X	return CMDFAIL;
X    }
X
X    dn = parms;		/* Remember start of display name		*/
X    parms += len;	/* Step to end of word				*/
X    *(parms++) = '\0';	/* Mark end of display name and step beyond it	*/
X    if(len > DNMAXLEN) {
X	*(dn+DNMAXLEN) = '\0';
X	sprintf(temp, "Display name more than %d chars, 1st %d used in EXT %s",
X		DNMAXLEN, DNMAXLEN, dn);
X	if(doing_init) {
X	    puts("Init:");
X	    puts(temp);
X	} else
X	    InfoMsg2Line("Script:", temp);
X	cmdrc = CMDWARN;
X    }
X
X    parms = next_wrd(parms, &len);	/* Step to start of SEND cmd */
X
X    /* Find a matching ExternalXfer structure based on display name */
X    for(i = 0; i < NumExts; i++) {
X	if(ci_strcmp(ExtXfer[i]->downname, dn) == 0)
X	    if(len > 0)	/* Replace this entry */
X		break;
X	    else {	/* remove this entry from the list */
X		struct ExternalXfer *p = ExtXfer[i];
X		FreeMem(p->dispname, (long)(strlen(p->dispname)+1));
X		FreeMem(p->downname, (long)(strlen(p->downname)+1));
X		FreeMem(p->send, (long)(strlen(p->send)+1));
X		FreeMem(p->receive, (long)(strlen(p->receive)+1));
X		FreeMem(p, (long)sizeof(struct ExternalXfer));
X		ExtXfer[i] = NULL;
X		for(j = i+1; j < NumExts; j++)
X		    ExtXfer[j-1] = ExtXfer[j];
X		NumExts--;
X		if(!doing_init)
X		    InitFileItems();
X		return;
X	    }
X    }
X    nxfer = i;			/* Remember index of match or where to put new... */
X    cexp = ExtXfer[nxfer];	/* ...and its location. */
X
X    bound = *(parms++);	/* Remember starting quote for SEND command and step over it */
X    if((p = index(parms, bound)) == NULL) {
X	sprintf(errmsg, "No ending quote for SEND cmd in EXT %s", dn);
X	return CMDFAIL;
X    }
X    *p = '\0';		/* Replace ending quote with NULL */
X    send = parms;	/* Remember start of SEND cmd... */
X    parms = ++p;	/* ...and step over the NULL */
X
X    parms = next_wrd(parms, &len);	/* Step to start of RECEIVE cmd */
X    if(len <= 0) {
X	sprintf(errmsg, "No RECEIVE command for EXT %s", dn);
X	return CMDFAIL;
X    }
X    bound = *(parms++);
X    if((p =index(parms, bound)) == NULL) {
X	sprintf(errmsg, "No ending quote for RECEIVE cmd in EXT %s", dn);
X	return CMDFAIL;
X    }
X    *p = '\0';
X
X    if(cexp) {	/* changing a current entry */
X	FreeMem(cexp->dispname, (long)(strlen(cexp->dispname)+1));
X	FreeMem(cexp->downname, (long)(strlen(cexp->downname)+1));
X	FreeMem(cexp->send, (long)(strlen(cexp->send)+1));
X	FreeMem(cexp->receive, (long)(strlen(cexp->receive)+1));
X	cexp->cmdkey = '\0';
X    } else if(nxfer >= EXTMAX) {
X	sprintf(errmsg, "EXT %s would add more than %d external protocols",
X		dn, EXTMAX);
X	return CMDFAIL;
X    } else {
X	cexp = (struct ExternalXfer *)
X		AllocMem((long)sizeof(struct ExternalXfer), mem_type);
X	ExtXfer[nxfer] = cexp;
X	NumExts++;
X    }
X
X    /* Initialize the new ExternalXfer entry.  Leave room in dispname for
X    ** a checkmark (2 character widths). */
X    len = strlen(dn);
X    cexp->dispname = (char *)AllocMem((long)len+3, mem_type);
X    strcpy(cexp->dispname, "  ");
X    strcat(cexp->dispname, dn);
X    cexp->downname = (char *)AllocMem((long)len+1, mem_type);
X    for(i = 0; i < len; i++)
X	cexp->downname[i] = dn[i] | ' ';
X    cexp->send = (char *)AllocMem((long)strlen(send)+1, mem_type);
X    strcpy(cexp->send, send);
X    cexp->receive = (char *)AllocMem((long)strlen(parms)+1, mem_type);
X    strcpy(cexp->receive, parms);
X
X    if(!doing_init)
X	InitFileItems();
X    return cmdrc;
X}
X
Xcmd_ks(file)
Xchar *file;
X{
X    char name[MAXGADSTR], *p;
X
X    if(file)
X	strcpy(name, file);
X    else
X	name[0] = '\0';
X
X    if(file == NULL || *file == '\0' || !cmd_from_script) {
X	req("Kermit Send:",name,1);
X	p = name;
X	if(file && !cmd_from_script)
X	    strcpy(file, name);
X    } else
X	p = file;
X    multi_xfer(p, doksend, 1);
X    return CMDOK;
X}
X
Xcmd_kr(file)
Xchar *file;
X{
X    char name[80];
X
X    name[0] = '\0';
X
X    multi_xfer(name, dokreceive, 0);
X    return CMDOK;
X}
X
Xcmd_kg(file)
Xchar *file;
X{
X    char name[MAXGADSTR], *p;
X
X    if(file)
X	strcpy(name, file);
X    else
X	name[0] = '\0';
X
X    server = TRUE;
X    if(file == NULL || *file == '\0' || !cmd_from_script) {
X	req("Kermit GET remote file(s):", name, 1);
X	p = name;
X	if(file && !cmd_from_script)
X	    strcpy(file, name);
X    } else
X	p = file;
X    multi_xfer(p, dokreceive, 0);
X    return CMDOK;
X}
X
Xcmd_kb()
X{
X    saybye();
X    return CMDOK;
X}
X
Xcmd_recf(file)
Xchar *file;
X{
X    int cmdrc = CMDOK;
X
X    switch(p_xproto) {
X    case 0:	/* Ascii */
X	do_capture(file);
X	break;
X    case 1:	/* Xmodem */
X    case 2:	/* XmodemCRC */
X	if(p_parity > 0) {
X	    InfoMsg1Line("Parity setting prevents XMODEM receive.");
X	    break;
X	}
X	cmd_xr(file);
X	break;
X    case 3:	/* Kermit */
X	cmd_kr(file);
X	break;
X    default:
X	if(p_xproto > MODEMAX + NumExts - 1)
X	    cmd_kr(file);
X	else
X	    cmdrc = do_ext(ExtXfer[p_xproto-MODEMAX],
X			   ExtXfer[p_xproto-MODEMAX]->receive,
X			   file);
X    }
X    return cmdrc;
X}
X
Xcmd_sendf(file)
Xchar *file;
X{
X    int cmdrc = CMDOK;
X
X    switch(p_xproto) {
X    case 0:	/* Ascii */
X	do_send(file);
X	break;
X    case 1:	/* Xmodem */
X    case 2:	/* XmodemCRC */
X	if(p_parity > 0) {
X	    InfoMsg1Line("Parity setting prevents XMODEM send.");
X	    cmdrc = CMDFAIL;
X	    break;
X	}
X	cmd_xs(file);
X	break;
X    case 3:	/* Kermit */
X	cmd_ks(file);
X	break;
X    default:
X	if(p_xproto > MODEMAX + NumExts - 1)
X	    cmd_ks(file);
X	else
X	    cmdrc = do_ext(ExtXfer[p_xproto-MODEMAX],
X			   ExtXfer[p_xproto-MODEMAX]->send,
X			   file);
X    }
X    return cmdrc;
X}
X
Xcmd_xs(file)
Xchar *file;
X{
X    char name[MAXGADSTR], *p;
X
X    if(file)
X	strcpy(name, file);
X    else
X	name[0] = '\0';
X
X    if(file == NULL || *file == '\0' || !cmd_from_script) {
X	req("Xmodem Send:",name,1);
X	p = name;
X	if(file && !cmd_from_script)
X	    strcpy(file, name);
X    } else
X	p = file;
X    multi_xfer(p, XMODEM_Send_File, 1);
X    return CMDOK;
X}
X
Xcmd_xr(file)
Xchar *file;
X{
X    char name[MAXGADSTR], *p;
X
X    if(file)
X	strcpy(name, file);
X    else
X	name[0] = '\0';
X
X    if(file == NULL || *file == '\0' || !cmd_from_script) {
X	req("Xmodem Receive:",name,1);
X	p = name;
X	if(file && !cmd_from_script)
X	    strcpy(file, name);
X    } else
X	p = file;
X    multi_xfer(p, XMODEM_Read_File, 1);
X    return CMDOK;
X}
X
Xcmd_cd(name)
Xchar *name;
X{
X    set_dir(name);
X    return CMDOK;
X}
X
Xcmd_sb(str)
Xchar *str;
X{
X    sendbreak();
X    return CMDOK;
X}
X
Xcmd_baud(rate)
Xchar *rate;
X{
X    int i = atoi(rate),
X	cmdrc = CMDOK;
X
X    switch( i ) {
X	case  300:
X	case 1200:
X	case 2400:
X	case 4800:
X	case 9600:
X	if (doing_init) p_baud = i;
X	else		setserbaud(i, TRUE);
X	break;
X
X	default:
X	strcpy(errmsg, "Invalid baud rate: ");
X	strcat(errmsg, rate);
X	cmdrc = CMDFAIL;
X	break;
X    }
X    return cmdrc;
X}
X
Xcmd_parity(par)
Xchar *par;
X{
X    int i;
X
X    switch( *par|' ' ) {
X	case 'n': i =  0; break;
X	case 'm': i =  1; break;
X	case 's': i =  2; break;
X	case 'e': i =  3; break;
X	case 'o': i =  4; break;
X
X	default:
X	strcpy(errmsg, "Init: invalid parity: ");
X	strcat(errmsg, par);
X	return CMDFAIL;
X    }
X    p_parity = i;
X    if (doing_init == 0)
X	redocomm();
X    return CMDOK;
X}
X
X#if AREXX
Xcmd_rx(cmd)
Xchar	*cmd;
X{
X    int	cmdrc = CMDOK,
X	ret = do_rx(cmd, implied_rexx);
X    char *msg = NULL;
X
X    errmsg[0] = '\0';
X    if(ret) {
X	cmdrc = CMDFAIL;
X	if(doing_init)
X	    printf("Init:\n%s\n", rexxerrmsgs[ret]);
X	else
X	    InfoMsg2Line("Script:", rexxerrmsgs[ret]);
X    }
X    return cmdrc;
X}
X#else
Xcmd_rx(cmd)
Xchar	*cmd;
X{
X    char *msg = "AREXX not compiled into this version.";
X
X    if(doing_init)
X	printf("Init:\n%s\n", msg);
X    else
X	InfoMsg2Line("Script:", msg);
X    return CMDFAIL;
X}
X#endif
X
Xcmd_bt(breaklength)
Xchar *breaklength;
X{
X    p_break = atol(breaklength);
X    if (doing_init)
X	return CMDOK;
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->io_BrkTime = Write_Request->io_BrkTime = p_break;
X    setparams();
X    return CMDOK;
X}
X
Xcmd_kmaxpk(pks)
Xchar *pks;
X{
X    int i = atoi(pks),
X	cmdrc = CMDOK;
X
X    if(i <= MAXLONGPKS)
X	p_kmaxpack = i;
X    else {
X	sprintf(errmsg, "Kermit packet size too big: %d", pks);
X	cmdrc = CMDFAIL;
X    }
X    return cmdrc;
X}
X
Xcmd_mode(tmode)
Xchar *tmode;
X{
X    switch (*tmode|' ') {
X	case 'i':
X	p_mode = 0;
X	break;
X
X	case 'c':
X	p_mode = 1;
X	break;
X
X	default:
X	strcpy(errmsg, "Init: invalid transfer mode: ");
X	strcat(errmsg, tmode);
X	return CMDFAIL;
X    }
X    if (doing_init == 0)
X	redocomm();
X    return CMDOK;
X}
X
Xcmd_as(file)
Xchar *file;
X{
X    do_send(file);
X    return CMDOK;
X}
X
Xcmd_cap(file)
Xchar *file;
X{
X    do_capture(file);
X    return CMDOK;
X}
X
Xcmd_beep(dummy)
Xchar	*dummy;
X{
X    if (p_volume == 0)
X	DisplayBeep(NULL);
X    else {
X	BeginIO((struct IORequest *)&Audio_Request);
X	WaitIO((struct IORequest *)&Audio_Request);
X    }
X    return CMDOK;
X}
X
Xvoid setvar(par,typ,var)
Xchar	*par;
Xint	typ,*var;
X{
X    int i;
X
X    switch (typ) {
X	case 0: /* ON/OFF or YES/NO */
X	case 1: /* not case */
X	if ((par[1]|' ') == 'n' || (par[0]|' ') == 'y') *var = 1-typ;
X	else						*var = typ;
X	break;
X
X	case 2: /* read hex number */
X	if (sscanf(par,"%x",&i) == 1) *var = i;
X
X	break;
X
X	case 3: /* read decimal number */
X	if (sscanf(par,"%d",&i) == 1) *var = i;
X	break;
X    }
X}
X
Xcmd_ac(par)
Xchar *par;
X{
X    setvar(par,0,&p_autochop);
X    if (doing_init == 0)
X	redoutil();
X    return CMDOK;
X}
X
Xcmd_echo(par)
Xchar	*par;
X{
X    setvar(par,0,&p_echo);
X    if (doing_init == 0)
X	redoutil();
X    return CMDOK;
X}
X
Xcmd_wrap(par)
Xchar	*par;
X{
X    setvar(par,0,&p_wrap);
X    if (doing_init == 0)
X	redoutil();
X    return CMDOK;
X}
X
Xcmd_share(parm)
Xchar *parm;
X{
X    int oldval = p_shared;
X
X    setvar(parm, 0, &p_shared);
X
X    if(Read_Request && (oldval ^ p_shared)) {
X	/* Port is going from shared->exclusive or vice-versa.  Close it and
X	** re-open */
X	if(!CheckIO((struct IORequest *)Read_Request))
X	    AbortIO((struct IORequest *)Read_Request);
X	Wait (1L <<mySerPort->mp_SigBit);
X	WaitIO((struct IORequest *)Read_Request);
X	CloseDevice((struct IORequest *)Read_Request);
X	if(p_shared)
X	    Read_Request->io_SerFlags |= SERF_SHARED;
X	else
X	    Read_Request->io_SerFlags &= (-1L ^ SERF_SHARED);
X	if(OpenDevice(mysername,(LONG)p_unit,(struct IORequest *)Read_Request,NULL))
X	    cleanup("Can't re-open Read device",0);
X	InitCommItems();
X	setparams();
X    }
X    return CMDOK;
X}
X
Xcmd_xbeep(par)
Xchar	*par;
X{
X    setvar(par,0,&p_xbeep);
X    if (doing_init == 0)
X	redoutil();
X    return CMDOK;
X}
X
Xcmd_xproto(par)
Xchar	*par;
X{
X    int i, len, save, cmdrc = CMDOK;
X
X    next_wrd(par, &len);
X
X    p_xproto = MODEMAX + 1;	/* Establish an out of bounds default */
X
X    if(len) {
X	par[len] = '\0';
X
X	/* downcase the parameter */
X	for(i = 0; i < len; i++) par[i] |= ' ';
X
X	for(i = 0; i < MODEMAX; i++)
X	    if(strcmp(par, &(*(xprotos[i]))) == 0) {
X		p_xproto = i;
X		break;
X	    }
X    }
X    if(p_xproto >= MODEMAX) {
X	/* Not a built-in protocol...check the defined external protocols */
X	p_xproto = 0;
X	if(len > DNMAXLEN) {
X	    save = *(par+DNMAXLEN);
X	    *(par+DNMAXLEN) = '\0';
X	}
X	for(i = 0; i < NumExts; i++) {
X	    if(strcmp(par, ExtXfer[i]->downname) == 0) {
X		p_xproto = MODEMAX + i;
X		break;
X	    }
X	}
X
X	if(p_xproto == 0) {
X	    p_xproto = MODEMAX - 1;
X	    if(len > DNMAXLEN)
X		*(par+DNMAXLEN) = save;
X	    sprintf(errmsg, "XPROTO beginning \"%.10s\" unknown, %s used",
X		    par, &(*(xprotos[p_xproto])));
X	    cmdrc = CMDFAIL;
X	}
X    }
X    if(!doing_init)
X	redofile();
X    return cmdrc;
X}
X
Xcmd_numkey(par)
Xchar	*par;
X{
X    setvar(par,1,&p_keyapp);
X    if (doing_init == 0)
X	redoutil();
X    return CMDOK;
X}
X
Xcmd_appcur(par)
Xchar	*par;
X{
X    setvar(par,0,&p_curapp);
X    if (doing_init == 0)
X	redoutil();
X    return CMDOK;
X}
X
Xcmd_swap(par)
Xchar	*par;
X{
X    setvar(par,0,&p_bs_del);
X    if (doing_init == 0)
X	redoutil();	/* Calls InitUtilItems which does swap_bs_del() */
X    else {
X    	swap_bs_del();	/* Setup keys[] properly... */
X    	swap_bs_del();	/* ...for new mode	    */
X    }
X    return CMDOK;
X}
X
Xcmd_bkg(par)
Xchar	*par;
X{
X    setvar(par,2,&p_background);
X    return CMDOK;
X}
X
Xcmd_bold(par)
Xchar	*par;
X{
X    setvar(par,2,&p_bold);
X    return CMDOK;
X}
X
Xcmd_buf(par)
Xchar	*par;
X{
X    setvar(par,3,&p_buffer);
X    return CMDOK;
X}
X
Xcmd_cursor(par)
Xchar	*par;
X{
X    setvar(par,2,&p_cursor);
X    return CMDOK;
X}
X
Xcmd_depth(par)
Xchar	*par;
X{
X    setvar(par,3,&p_depth);
X    return CMDOK;
X}
X
Xcmd_device(par)
Xchar	*par;
X{
X    int	len, cmdrc = CMDOK;
X    char	temp[80];
X
X    next_wrd(par, &len);
X    if(len > SERNAMESIZE) {
X	printf(temp, "Init:\nDevice parm too long, %s used", SERIALNAME);
X	strcpy(mysername, SERIALNAME);
X	cmdrc = CMDFAIL;
X    } else
X	strcpy(mysername, par);
X    return cmdrc;
X}
X
Xcmd_display(str)
Xchar	*str;
X{
X    register char *p;
X
X    for(p = tostring(str); *p; p++)
X	doremote(*p);
X
X    return CMDOK;
X}
X
Xcmd_fore(par)
Xchar	*par;
X{
X    setvar(par,2,&p_foreground);
X    return CMDOK;
X}
X
X#if AREXX
X/*   This routine *depends* on the fact that the FORWARD command is only
X** valid from AREXX.  It then assumes that it can open RXSNAME.
X**/
Xcmd_fwd(par)
Xchar *par;
X{
X    int i;
X
X    if(ForwardPortName != NULL) {
X	FreeMem(ForwardPortName, (LONG)strlen(ForwardPortName) + 1);
X	ForwardPortName = NULL;
X    }
X
X    forwarding = 0;
X
X    if(RexxSysBase == NULL) {
X	RexxSysBase = (struct RxsLib *)OpenLibrary(RXSNAME, 0L);
X	if( (i = makerexxport()) != 0) {
X	    strcpy(errmsg, rexxerrmsgs[i]);
X	    return CMDFAIL;
X	}
X    }
X
X    if(par && *par) {
X	if(ForwardPortName = AllocMem((LONG)strlen(par)+1,
X				MEMF_PUBLIC | MEMF_CLEAR)) {
X	    strcpy(ForwardPortName, par);
X	    forwarding = 1;
X	} else {
X	    strcpy(errmsg, "Can't allocate memory for an AREXX forward port");
X	    return CMDFAIL;
X	}
X    }
X
X    return CMDOK;
X}
X#else
Xcmd_fwd(par)
X{
X    return CMDFAIL;
X}
X#endif /* AREXX */
X
Xcmd_font(par)
Xchar	*par;
X{
X    char temp[80];
X    int  len, cmdrc = CMDOK;
X
X    next_wrd(par, &len);
X
X    temp[0] = '\0';
X
X    /*  myfontname has been initialized from p_font in InitDefaults() in
X    ** init.c */
X
X    if(!len) {
X	sprintf(temp, "Init:\nNo font specified, \"%s\" used", myfontname);
X	cmdrc = CMDWARN;
X    } else {
X	if(*par && len) {
X	    if(len < MAXFONTVARLEN) {
X	    	par[len] = '\0';
X		strcpy(myfontname, par);
X		strcat(myfontname,FONTSUFFIX);
X	    } else {
X		sprintf(temp, "Init:\nFont specification too long, \"%s\" used",
X			myfontname);
X		cmdrc = CMDWARN;
X	    }
X        }
X    }
X    myattr.ta_Name = (STRPTR)myfontname;
X    if(*temp)
X	puts(temp);
X    return cmdrc;
X}
X
Xcmd_fonts(par)
Xchar	*par;
X{
X    char temp[80];
X    int  len, size, cmdrc = CMDOK;
X
X    next_wrd(par, &len);
X
X    temp[0] = '\0';
X
X    /*  myfontname has been initialized from p_font in InitDefaults() in
X    ** init.c */
X
X    if(!len) {
X	strcpy(temp, "Init:\nNo font size specified, \"8\" used");
X	cmdrc = CMDWARN;
X    } else {
X	if(*par && len) {
X	    size = atoi(par);
X	    if(size > 0)
X		myattr.ta_YSize = size;
X	    else {
X	    	myattr.ta_YSize = 8;
X		sprintf(temp, "Init:\nFont size \"%s\" invalid, \"8\" used",
X			par);
X		cmdrc = CMDWARN;
X	    }
X        }
X    }
X    if(*temp)
X	puts(temp);
X    return cmdrc;
X}
X
Xcmd_inter(par)
Xchar	*par;
X{
X    if(strcmp(par, "asis") == 0)
X	p_interlace = 2;
X    else
X	setvar(par,0,&p_interlace);
X    return CMDOK;
X}
X
Xcmd_mouse(par)
Xchar *par;
X{
X    switch (par[0]|' ') {
X	case 'b':
X	    p_mouse_up = p_mouse_down = 1;		/* send both	*/
X	    break;
X
X	case 'o':
X	    p_mouse_up = p_mouse_down = 0;		/* mouse off	*/
X	    break;
X
X	case 'u':
X	    p_mouse_up = 1;				/* up only      */
X	    p_mouse_down = 0;
X	    break;
X
X	case 'd':					/* down only	*/
X	    p_mouse_down = 1;
X	    p_mouse_up = 0;
X	    break;
X	default:
X	    return CMDFAIL;
X    }
X    return CMDOK;
X}
X
Xcmd_msg(par)
Xchar *par;
X{
X    register char *p, *s;
X    int newline = 1;		/* Whether we need to scroll */
X
X    for(s = p = tostring(par); *p; p++) {
X	if(*p == '\n') {
X	    *p = '\0';
X	    InfoMsgNoScroll(s);
X	    ScrollInfoMsg(1);
X	    newline = 0;
X	    s = p + 1;
X	} else if(*p == '\r') {
X	    *p = '\0';
X	    InfoMsgNoScroll(s);
X	    newline = 0;
X	    s = p + 1;
X	} else
X	    newline = 1;
X    }
X    if(*s)
X	InfoMsgNoScroll(s);
X
X    if(newline)
X	ScrollInfoMsg(1);
X    return CMDOK;
X}
X
Xcmd_lines(par)
Xchar	*par;
X{
X    setvar(par,3,&p_lines);
X    return CMDOK;
X}
X
Xcmd_screen(par)
Xchar	*par;
X{
X    if ((par[0]|' ') == 'w') p_screen = 0;
X    else		     p_screen = 1;
X    return CMDOK;
X}
X
Xcmd_unit(par)
Xchar	*par;
X{
X    setvar(par, 3, &p_unit);
X    return CMDOK;
X}
X
Xcmd_wb(par)
Xchar	*par;
X{
X    setvar(par,0,&p_wbcolors);
X    return CMDOK;
X}
X
Xcmd_short(par)	/* Set keyboard shortcuts */
Xchar	*par;
X{
X    int	i, l, l2;
X    register char *p = par;
X    
X    /* downcase the next word */
X    for (i=0; p[i] && (p[i] != ' ') && (p[i] != '\t'); i++)
X	p[i] |= ' ';
X    l = i;
X    
X    /*   Find the command name.  If found set the shortcut key to the
X    ** user's value.  If no value then set the key to ' ' to indicate no
X    ** shortcut available. */
X    for(i = 0; shortkeys[i].cname != NULL; i++) {
X	l2 = strlen(shortkeys[i].cname);
X	if (l >= l2 && strncmp(p, shortkeys[i].cname, l2) == 0) {
X	    for( ; p[l] && ((p[l] == ' ') || (p[l] == '\t')) ; l++)
X		;
X	    if(p[l])
X		*(shortkeys[i].pos) = p[l];
X	    else
X		*(shortkeys[i].pos) = ' ';
X	    return CMDOK;
X	}
X    }
X
X    /* Not a "normal" item so try an ExternalXfer item */
X    p = next_wrd(par, &l);
X    if(l > 0) {
X	*(p+l) = '\0';
X	for(i = 0; i < NumExts; i++)
X	    if(strcmp(p, ExtXfer[i]->downname) == 0) {
X		p = next_wrd(p+l+1, &l);
X		if(l <= 0)
X		    break;
X		ExtXfer[i]->cmdkey = *p;
X		return CMDOK;
X	    }
X    }
X
X    sprintf(errmsg, "Unknown shortcut: %s", par);
X    return CMDFAIL;
X}
X
Xcmd_key(par)
Xchar	*par;
X{
X    int i;
X
X    if (sscanf(par,"%x",&i) == 1)
X	p_keyscript = (char)(i & 0x7f);
X    return CMDOK;
X}
X
Xcmd_volume(par)
Xchar	*par;
X{
X    setvar(par,3,&p_volume);
X    return CMDOK;
X}
X
Xcmd_conv(par)
Xchar	*par;
X{
X    setvar(par,0,&p_convert);
X    if (doing_init == 0)
X	redoutil();
X    return CMDOK;
X}
X
Xcmd_fnc(par)
Xchar	*par;
X{
X    char    *s;
X    int     l;
X    int     i = atoi(par);
X
X    s = par;
X    if (*s) s = next_wrd(s,&l);		/* skip key number */
X    if (*s) s = next_wrd(s+l+1,&l);	/* point at desired string */
X    if (*s) s = tostring(s);		/* convert the string */
X    if(*par == 'm') {	/* Mouse prefix */
X	p_f[10] = malloc(strlen(s) + 1);
X	strcpy(p_f[10], s);
X    } else if (*s && i > 0 && i < 21) {
X	if (i > 10) {
X	    p_F[i-11] = malloc(strlen(s)+1);
X	    strcpy(p_F[i-11],s);
X	}
X	else {
X	    p_f[i-1] = malloc(strlen(s)+1);
X	    strcpy(p_f[i-1],s);
X	}
X    }
X    return CMDOK;
X}
X
Xcmd_null(dummy)
Xchar *dummy;
X{
X    return CMDOK;
X}
X
X/* Case-insensitive strcmp() */
Xci_strcmp(p1, p2)
Xchar *p1, *p2;
X{
X    while( *p1 && ((*p1 | ' ') == (*p2 | ' ')) ) {
X	++p1;
X	++p2;
X    }
X    return(*p1 != *p2);
X}
X
Xdo_ext(exp, pgmname, file)
Xstruct ExternalXfer *exp;
Xchar *pgmname, *file;
X{
X    char *local = "@LOCAL",
X	 *remote = "@REMOTE",
X	 *command,
X	 localfn[MAXGADSTR],
X	 remotefn[MAXGADSTR],
X	 *p,
X	 *p1;
X    int len = 0,
X	locallen = strlen(local),
X	remotelen = strlen(remote);
X
X    if(file)
X	strcpy(localfn, file);
X    else
X	localfn[0] = '\0';
X    remotefn[0] = '\0';
X
X    /* Get the initial length of the command then go through the user's
X    ** command string looking for @LOCAL and @REMOTE.  When we encounter one of
X    ** these strings then, if we don't already have the appropriate filename,
X    ** we'll put up a requester asking for it.  Whether we put up the requester
X    ** or not we must still account for the length of the replacement filename
X    ** so that when we AllocMem() for the command we'll only get what we need.
X    */
X    len = strlen(pgmname) + 1;
X    for(p = pgmname; *p; p++) {
X	if(*p == '@')
X	    if(strncmp(p+1, local+1, locallen-1) == 0) {
X		if(!cmd_from_script || localfn[0] == '\0')
X		    req("Local file name:", localfn, 1);
X		if(!localfn[0])	/* No filename specified */
X		    return CMDFAIL;
X		if(file && !cmd_from_script)
X		    strcpy(file, localfn);
X		len += strlen(localfn);
X		len -= locallen;
X		p += locallen;
X	    } else if(strncmp(p+1, remote+1, remotelen-1) == 0) {
X		req("Remote file name:", remotefn, 1);
X		if(!remotefn[0])	/* No filename specified */
X		    return CMDFAIL;
X		len += strlen(remotefn);
X		len -= remotelen;
X		p += remotelen;
X	    }
X    }	/* for p = pgmname */
X
X    /* Allocate space for the command and copy the command string to it
X    ** replacing @LOCAL and @REMOTE with localfn and remotefn, respectively */
X    command = AllocMem((long)len, MEMF_PUBLIC | MEMF_CLEAR);
X    if(localfn[0] || remotefn[0]) {
X	for(p = pgmname, p1 = p; *p; p++) {
X	    if(strncmp(p, local, locallen) == 0) {
X		strncat(command, p1, p - p1);
X		strcat(command, localfn);
X		p += locallen;
X		p1 = p;
X	    } else if(strncmp(p, remote, remotelen) == 0) {
X		strncat(command, p1, p - p1);
X		strcat(command, remotefn);
X		p += remotelen;
X		p1 = p;
X	    }
X	}
X	strcat(command, p1);	/* Don't forget the tail of the command! */
X    } else strcpy(command, pgmname);
X
X    /* Close down VT100's use of the serial port */
X    if(!CheckIO((struct IORequest *)Read_Request))
X	AbortIO((struct IORequest *)Read_Request);
X    Wait (1L <<mySerPort->mp_SigBit);
X    WaitIO((struct IORequest *)Read_Request);
X    if(!p_shared)
X	CloseDevice((struct IORequest *)Read_Request);
X
X    Execute(command, 0L, 0L);	/* Invoke the external xfer pgm */
X    FreeMem(command, (long)len);
X    if(!p_shared && OpenDevice(mysername,(LONG)p_unit,(struct IORequest *)Read_Request,NULL))
X	cleanup("Can't re-open Read device",0);
X    setparams();
X    return CMDOK;
X}
SHAR_EOF
echo "End of archive 7 (of 9)"
# if you want to concatenate archives, remove anything after this line
exit