/********************************************************************
*
*
*  HCS II HOST Program
*
*    Version 3.62
*
*    February 4, 1999
*
*      Copyright (c) 1992-1999, Circuit Cellar Inc.
*
*
*  Version 3.62 -- February 4,1999 (jeff bachiochi) -- Y2K
*
*  Version 3.60 -- March 6, 1998
*								-- Fixed analog output display
*
*  Version 3.50 -- March 15, 1997
*								-- Final Answer MAN release
*
*  Version 3.05 -- November 3, 1996
*								-- Answer MAN support
*
*  Version 3.01 -- June 10, 1995
*								-- Fix log data dump
*								-- Fix vs_fillchar error on multiple program load
*
*  Version 3.00 -- March 16, 1995
*								-- Release version
*
*  Version 2.10 -- December 20, 1993
*								-- Release version
*
*  Version 2.00 -- March 3, 1993
*								-- Release version
*
*  Version 1.20 -- November 18, 1992
*								-- Increase timeout values for fast machines
*								-- Added MCIR support
*								-- Patched vs_locatecur error bug
*
*  Version 1.00 -- March 1992
*								-- Release version
*
*
*********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
#include <malloc.h>
#include <time.h>

#include "pro.h"
#include "xglobals.h"
#include "vs.h"
#include "colors.h"
#include "mouse.h"

#include "pcl4c.h"

#define true    1
#define false   0

#define bell    '\x07'
#define tab			'\x09'
#define cr      '\x0d'
#define esc     '\x1b'

#define alert   '!'
#define ack     '^'
#define reply   '$'
#define badver	'#'
#define toobig	'@'
#define clear   '\x00'
#define pause		'\x01'
#define update  '\x02'
#define newtime '\x05'
#define newevnt '\x06'
#define clrlog  '\x07'
#define logsize	'\x08'
#define dumplog '\x09'
#define setx10	'\x12'
#define setin		'\x15'
#define setout  '\x18'
#define setadc	'\x1b'
#define setdac	'\x1e'
#define setbit	'\x23'
#define netstr	'\x30'
#define vstr		'\x31'

#define curtime '\x80'
#define x10stat '\x81'
#define inpstat '\x82'
#define outstat '\x83'
#define adcstat '\x84'
#define dacstat '\x85'
#define modstat '\x86'
#define netstat '\x87'
#define msgdisp	'\x88'

#define Tics    36		/* 2 seconds */

unsigned int win[20];

time_t t1_start, t2_start;

int time1=false, time2=false, Port=0, mousepresent;

int fore[20] = { black,     yellow,     black,      white,     black,
								 black,     black,      black,      black,     black,
								 yellow,    lightgreen, lightgreen, black,     black,
								 yellow,    yellow,     black,      white};
int back[20] = { lightgray, magenta,    magenta,    black,     lightgray,
								 lightgray, lightgray,  lightgray,  lightgray, lightgray,
								 blue,      red,        red,        cyan,      green,
								 magenta,   magenta,    cyan,       black};

unsigned char modinit[40] = "AT&FLT&K3&Q5";

/* Array contains physical_x, physical_y, port_rows, port_columns, and hide
	 for windows 10-18 */

unsigned int scrn[9][5] = {49,  3,  3, 30, FALSE,
													 47,  9,  4, 32, FALSE,
													 47, 15,  4, 32, FALSE,
													 26,  5,  3, 17, FALSE,
														1,  4,  5, 22, FALSE,
													 27, 12,  4, 16, FALSE,
													 27, 19,  4, 16, FALSE,
													 47, 21,  3, 32, FALSE,
														2, 12, 12, 20, TRUE};

unsigned char box5[13] = { '\x0f','»','Ù','È','Í','º','Í','Í',
													 'Ä','Ä','Ä','Ç','¶' };

int network_mod[5] = {0,0,0,0,0};
int out_used[15]   = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
int in_used[15]    = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
int dac_used[15]   = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
int nb_used[15]    = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};

char house_used[16] = "                ";


int ErrorCheck(int Code) { /* Trap PCL error codes */
	if (Code < 0) {
		SioError(Code);
		SioDone(Port);
		exit(1);
	}
	return(0);
}


int AllocSeg(int Size)
{
	int Seg;
	char far *Ptr;

	/* allocate far heap */

	Ptr = (char far *) _fmalloc(Size+16);
	if (Ptr==NULL) return 0;

	/* SEG:0 points to buffer */

	Seg = (FP_SEG(Ptr) + 1) + (FP_OFF(Ptr)>>4);
	return Seg;
}


int bcd(int num)
{
	if (num>99) num = num - 100;
	return ((num / 10) * 16) + (num % 10);
}


void reset_HCS()
{
	SioPutc(Port, alert);
	SioPutc(Port, clear);
}


int SaveScreen()
{
	FILE *fp;
	int  i;

	if ((fp=fopen("host.cfg", "wb")) == NULL)
		return 1;

	for (i=10; i<19; i++) {
		fputc(wdw[win[i]]->physical_x,   fp);
		fputc(wdw[win[i]]->physical_y,   fp);
		fputc(wdw[win[i]]->port_rows,    fp);
		fputc(wdw[win[i]]->port_columns, fp);
		fputc(wdw[win[i]]->hide,         fp);
	}
	fputs(modinit, fp);

	fclose(fp);
	return 0;
}


void ReadScreen()
{
	FILE *fp;
	int  i, j;

	if ((fp=fopen("host.cfg", "rb")) == NULL)
		return;

	for (i=0; i<9; i++)
		for (j=0; j<5; j++)
			scrn[i][j] = fgetc(fp);

	fgets(modinit, 50, fp);

	fclose(fp);
}


void ClearWindows()
{
	int i;

	vs_locatecur(win[11],0,1,3);
	vs_clrtoend(win[11],0,fore[11],back[11]);

	vs_locatecur(win[12],0,1,3);
	vs_clrtoend(win[12],0,fore[12],back[12]);

	vs_locatecur(win[13],0,1,2);
	vs_clrtoend(win[13],0,fore[13],back[13]);

	vs_locatecur(win[14],0,1,3);
	vs_clrtoend(win[14],0,fore[14],back[14]);

	vs_locatecur(win[15],0,1,1);
	vs_clrtoend(win[15],0,fore[15],back[15]);

	vs_locatecur(win[16],0,1,1);
	vs_clrtoend(win[16],0,fore[16],back[16]);

	vs_locatecur(win[17],0,1,3);
	vs_clrtoend(win[17],0,fore[17],back[17]);

	vs_locatecur(win[18],0,1,1);
	vs_clrtoend(win[18],0,fore[18],back[18]);

	for (i=0; i<=4; i++)
		network_mod[i] = 0;

	for (i=0; i<=14; i++) {
		in_used[i]  = 99;
		out_used[i] = 99;
		dac_used[i] = 99;
		nb_used[i]  = 99;
	}
	strcpy(house_used, "                ");
}


int InitPort()
{
	int error;

	/* Set up transmit & receive buffer */
	SioRxBuf(Port,AllocSeg(2048),Size2048);
	/* Set port parmameters */
	SioParms(Port,NoParity,OneStopBit,WordLength8);
	/* Reset the port */
	error = SioReset(Port,Baud9600);
	if (!error) {
		SioRTS(Port, 'S');
		SioDTR(Port, 'S');
		/* Turn off flow control */
		SioFlow(Port, false);
	}
	return error;
}


void SetupScreen()
{
	scroll_bars_on = NO_BARS;
	thumbwheels_on = NO_BARS;
	method = DMA;
	active_attr = white + (black << 4);
	inactive_attr = lightgray + (black << 4);
	wn_hidecur();

	win[0] = wn_createw(physical_rows, physical_columns, 1,1,1,1,
						 physical_rows-2, physical_columns-2, FALSE, NONE,
						 NULL, NULL);
	vs_clrvs(win[0],0,white,black);
	vs_putcods(win[0],0,1,1,80,black,lightgray,red,lightgray,
	"  ~!  ~File  ~Command  ~Log  ~Window  ~Modem                                  HCS/SS");
	wn_openw(win[0]);

/*	scroll_bars_on = BOTH_BARS; */
	thumbwheels_on = BOTH_BARS;

	default_box = box5;

	win[11]= wn_createw(7,32,scrn[1][0],scrn[1][1],1,1,scrn[1][2],scrn[1][3],
											FALSE,HEAD_ON," Digital In ",NULL);
	vs_clrvs(win[11],0,fore[11],back[11]);
	vs_putscenter(win[11],0,
					"               111111 11112222",fore[11],back[11],1);
	vs_putscenter(win[11],0,
					"    01234567 89012345 67890123",fore[11],back[11],2);
	if (!scrn[1][4]) {
		wn_flybox(wdw[win[11]]->physical_x+
				wdw[win[11]]->port_columns/2,
				wdw[win[11]]->physical_y+
				wdw[win[11]]->port_rows/2,
				1,1,
				wdw[win[11]]->physical_x,
				wdw[win[11]]->physical_y,
				wdw[win[11]]->port_rows,
				wdw[win[11]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[11]);
	}


	win[12]= wn_createw(7,32,scrn[2][0],scrn[2][1],1,1,scrn[2][2],scrn[2][3],
											FALSE,HEAD_ON," Digital Out ",NULL);
	vs_clrvs(win[12],0,fore[12],back[12]);
	vs_putscenter(win[12],0,
					"               111111 11112222",fore[12],back[12],1);
	vs_putscenter(win[12],0,
					"    01234567 89012345 67890123",fore[12],back[12],2);
	if (!scrn[2][4]) {
		wn_flybox(wdw[win[12]]->physical_x+
				wdw[win[12]]->port_columns/2,
				wdw[win[12]]->physical_y+
				wdw[win[12]]->port_rows/2,
				1,1,
				wdw[win[12]]->physical_x,
				wdw[win[12]]->physical_y,
				wdw[win[12]]->port_rows,
				wdw[win[12]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[12]);
	}


	win[13]= wn_createw(8,17,scrn[3][0],scrn[3][1],1,1,scrn[3][2],scrn[3][3],
											FALSE,HEAD_ON," Network Mods ",NULL);
	vs_clrvs(win[13],0,fore[13],back[13]);
	vs_locatecur(win[13],0,9,1);
	vs_printf(win[13],0,fore[13],back[13],"01234567");
	if (!scrn[3][4]) {
		wn_flybox(wdw[win[13]]->physical_x+
				wdw[win[13]]->port_columns/2,
				wdw[win[13]]->physical_y+
				wdw[win[13]]->port_rows/2,
				1,1,
				wdw[win[13]]->physical_x,
				wdw[win[13]]->physical_y,
				wdw[win[13]]->port_rows,
				wdw[win[13]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[13]);
	}


	win[14]= wn_createw(18,22,scrn[4][0],scrn[4][1],1,1,scrn[4][2],scrn[4][3],
											FALSE,HEAD_ON," X-10 Mods ",NULL);
	vs_clrvs(win[14],0,fore[14],back[14]);
	vs_putscenter(win[14],0,"         1111111",fore[14],back[14],1);
	vs_putscenter(win[14],0,"1234567890123456",fore[14],back[14],2);
	if (!scrn[4][4]) {
		wn_flybox(wdw[win[14]]->physical_x+
				wdw[win[14]]->port_columns/2,
				wdw[win[14]]->physical_y+
				wdw[win[14]]->port_rows/2,
				1,1,
				wdw[win[14]]->physical_x,
				wdw[win[14]]->physical_y,
				wdw[win[14]]->port_rows,
				wdw[win[14]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[14]);
	}


	win[15]= wn_createw(30,16,scrn[5][0],scrn[5][1],1,1,scrn[5][2],scrn[5][3],
											FALSE,HEAD_ON," Analog In ",NULL);
	vs_clrvs(win[15],0,fore[15],back[15]);
	if (!scrn[5][4]) {
		wn_flybox(wdw[win[15]]->physical_x+
				wdw[win[15]]->port_columns/2,
				wdw[win[15]]->physical_y+
				wdw[win[15]]->port_rows/2,
				1,1,
				wdw[win[15]]->physical_x,
				wdw[win[15]]->physical_y,
				wdw[win[15]]->port_rows,
				wdw[win[15]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[15]);
	}


	win[16]= wn_createw(10,16,scrn[6][0],scrn[6][1],1,1,scrn[6][2],scrn[6][3],
											FALSE,HEAD_ON," Analog Out ",NULL);
	vs_clrvs(win[16],0,fore[16],back[16]);
	if (!scrn[6][4]) {
		wn_flybox(wdw[win[16]]->physical_x+
				wdw[win[16]]->port_columns/2,
				wdw[win[16]]->physical_y+
				wdw[win[16]]->port_rows/2,
				1,1,
				wdw[win[16]]->physical_x,
				wdw[win[16]]->physical_y,
				wdw[win[16]]->port_rows,
				wdw[win[16]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[16]);
	}


	win[17]= wn_createw(17,32,scrn[7][0],scrn[7][1],1,1,scrn[7][2],scrn[7][3],
											FALSE,HEAD_ON," Netbit ",NULL);
	vs_clrvs(win[17],0,fore[17],back[17]);
	vs_putscenter(win[17],0,
					"               111111 11112222",fore[17],back[17],1);
	vs_putscenter(win[17],0,
					"    01234567 89012345 67890123",fore[17],back[17],2);
	if (!scrn[7][4]) {
		wn_flybox(wdw[win[17]]->physical_x+
				wdw[win[17]]->port_columns/2,
				wdw[win[17]]->physical_y+
				wdw[win[17]]->port_rows/2,
				1,1,
				wdw[win[17]]->physical_x,
				wdw[win[17]]->physical_y,
				wdw[win[17]]->port_rows,
				wdw[win[17]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[17]);
	}


	win[18]= wn_createw(12,20,scrn[8][0],scrn[8][1],1,1,scrn[8][2],scrn[8][3],
											FALSE,HEAD_ON," Message ",NULL);
	vs_clrvs(win[18],0,fore[18],back[18]);
	if (!scrn[8][4]) {
		wn_flybox(wdw[win[18]]->physical_x+
				wdw[win[18]]->port_columns/2,
				wdw[win[18]]->physical_y+
				wdw[win[18]]->port_rows/2,
				1,1,
				wdw[win[18]]->physical_x,
				wdw[win[18]]->physical_y,
				wdw[win[18]]->port_rows,
				wdw[win[18]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[18]);
	}

	scroll_bars_on = NO_BARS;
	thumbwheels_on = NO_BARS;

	default_box = box0;

	win[10]= wn_createw(3,30,scrn[0][0],scrn[0][1],1,1,scrn[0][2],scrn[0][3],
											FALSE,HEAD_ON,NULL,NULL);
	vs_clrvs(win[10],0,fore[10],back[10]);
	if (!scrn[0][4]) {
		wn_flybox(wdw[win[10]]->physical_x+
				wdw[win[10]]->port_columns/2,
				wdw[win[10]]->physical_y+
				wdw[win[10]]->port_rows/2,
				1,1,
				wdw[win[10]]->physical_x,
				wdw[win[10]]->physical_y,
				wdw[win[10]]->port_rows,
				wdw[win[10]]->port_columns,
				28,40,box1,white,black);
		wn_openw(win[10]);
	}

	win[2] = wn_createw(6,40,20,6,1,1,6,40,FALSE,HEAD_ON,NULL,NULL);

	win[3] = wn_createw(6,40,20,12,1,1,6,40,FALSE,HEAD_ON,NULL,NULL);

	default_box = box1;

	win[4] = wn_createw(1,10,2,2,1,1,1,10,FALSE,HEAD_ON,NULL,NULL);
	vs_clrvs(win[4],0,fore[4],back[4]);
	vs_putcods(win[4],0,2,1,8,fore[4],back[4],red,back[4],"~About...");

	win[5] = wn_createw(2,6,5,2,1,1,2,6,FALSE,HEAD_ON,NULL,NULL);
	vs_clrvs(win[5],0,fore[5],back[5]);
	vs_putcods(win[5],0,2,1,4,fore[5],back[5],red,back[5],"~Load");
	vs_putcods(win[5],0,2,2,4,fore[5],back[5],red,back[5],"~Quit");

	win[6] = wn_createw(9,15,11,2,1,1,9,15,FALSE,HEAD_ON,NULL,NULL);
	vs_clrvs(win[6],0,fore[6],back[6]);
	vs_putcods(win[6],0,2,1,13,fore[6],back[6],red,back[6],"Set ~Time");
	vs_putcods(win[6],0,2,2,13,fore[6],back[6],red,back[6],"Set ~Input...");
	vs_putcods(win[6],0,2,3,13,fore[6],back[6],red,back[6],"Set ~Output...");
	vs_putcods(win[6],0,2,4,13,fore[6],back[6],red,back[6],"Set ~X-10...");
	vs_putcods(win[6],0,2,5,13,fore[6],back[6],red,back[6],"Set ~ADC...");
	vs_putcods(win[6],0,2,6,13,fore[6],back[6],red,back[6],"Set ~DAC...");
	vs_putcods(win[6],0,2,7,13,fore[6],back[6],red,back[6],"Set Net~bit...");
	vs_putcods(win[6],0,2,8,13,fore[6],back[6],red,back[6],"~Voice...");
	vs_putcods(win[6],0,2,9,13,fore[6],back[6],red,back[6],"~Network...");

	win[7] = wn_createw(3,7,20,2,1,1,3,7,FALSE,HEAD_ON,NULL,NULL);
	vs_clrvs(win[7],0,fore[7],back[7]);
	vs_putcods(win[7],0,2,1,5,fore[7],back[7],red,back[7],"~Clear");
	vs_putcods(win[7],0,2,2,5,fore[7],back[7],red,back[7],"~Size");
	vs_putcods(win[7],0,2,3,5,fore[7],back[7],red,back[7],"~Dump");

	win[8] = wn_createw(9,14,25,2,1,1,9,14,FALSE,HEAD_ON,NULL,NULL);
	vs_clrvs(win[8],0,fore[8],back[8]);
	vs_putcods(win[8],0,2,1,12,fore[8],back[8],red,back[8],"~Time");
	vs_putcods(win[8],0,2,2,12,fore[8],back[8],red,back[8],"~Digital In");
	vs_putcods(win[8],0,2,3,12,fore[8],back[8],red,back[8],"Digital ~Out");
	vs_putcods(win[8],0,2,4,12,fore[8],back[8],red,back[8],"~Network Mods");
	vs_putcods(win[8],0,2,5,12,fore[8],back[8],red,back[8],"~X-10 Mods");
	vs_putcods(win[8],0,2,6,12,fore[8],back[8],red,back[8],"~Analog In");
	vs_putcods(win[8],0,2,7,12,fore[8],back[8],red,back[8],"Analo~g Out");
	vs_putcods(win[8],0,2,8,12,fore[8],back[8],red,back[8],"Net~bits");
	vs_putcods(win[8],0,2,9,12,fore[8],back[8],red,back[8],"~Message");

	win[9] = wn_createw(3,9,33,2,1,1,3,9,FALSE,HEAD_ON,NULL,NULL);
	vs_clrvs(win[9],0,fore[9],back[9]);
	vs_putcods(win[9],0,2,1,7,fore[9],back[9],red,back[9],"~Init...");
	vs_putcods(win[9],0,2,2,7,fore[9],back[9],red,back[9],"~Dial...");
	vs_putcods(win[9],0,2,3,7,fore[9],back[9],red,back[9],"~Hangup");

	default_box = box0;

	win[1] = wn_createw(6,27,27,10,1,1,6,27,FALSE,HEAD_ON,NULL,NULL);
	wn_flybox(wdw[win[1]]->physical_x+
				wdw[win[1]]->port_columns/2,
				wdw[win[1]]->physical_y+
				wdw[win[1]]->port_rows/2,
				1,1,
				wdw[win[1]]->physical_x,
				wdw[win[1]]->physical_y,
				wdw[win[1]]->port_rows,
				wdw[win[1]]->port_columns,
				28,40,box1,white,black);
	vs_clrvs(win[1],0,fore[1],back[1]);
	vs_putscenter(win[1],0,"The Circuit Cellar",fore[1],back[1],1);
	vs_putscenter(win[1],0,"HCS/SpectraSense",fore[1],back[1],2);
	vs_putscenter(win[1],0,"Host Program Version 3.62",fore[1],back[1],4);
	vs_putscenter(win[1],0,"Copyright (c) 1992-1999",fore[1],back[1],5);
	vs_putscenter(win[1],0,"Circuit Cellar, Inc.",fore[1],back[1],6);
	wn_openw(win[1]);

	t1_start = time(NULL);
	time1 = true;
}


int FindActive(void)
{
	int current=1;

	while ((win[current] != active_wdw) && (current < 20))
		current++;

	return current;
}


void NextActive(void)
{
	int current=1, next;

	current = FindActive();

	if (current >= 20)
		return;

	next = current + 1;

	if ((next < 10) || (next > 18))
		next = 10;

	while (wdw[win[next]]->hide && next!=current) {
		next++;
		if (next > 18)
			next = 10;
	}
	wn_openw(win[next]);
}


void MoveActiveUp(void)
{
	int current;

	current = FindActive();
	wn_locatew(win[current],
						 wdw[win[current]]->physical_x,
						 wdw[win[current]]->physical_y - 1);
}


void MoveActiveDown(void)
{
	int current;

	current = FindActive();
	wn_locatew(win[current],
						 wdw[win[current]]->physical_x,
						 wdw[win[current]]->physical_y + 1);
}


void MoveActiveLeft(void)
{
	int current;

	current = FindActive();
	wn_locatew(win[current],
						 wdw[win[current]]->physical_x - 1,
						 wdw[win[current]]->physical_y);
}


void MoveActiveRight(void)
{
	int current;

	current = FindActive();
	wn_locatew(win[current],
						 wdw[win[current]]->physical_x + 1,
						 wdw[win[current]]->physical_y);
}


void SizeActiveUp(void)
{
	int current;

	current = FindActive();
	wn_sizet(win[current], wdw[win[current]]->last_tile, 0, -1);
}


void SizeActiveDown(void)
{
	int current;

	current = FindActive();
	wn_sizet(win[current], wdw[win[current]]->last_tile, 0, 1);
}


void SizeActiveLeft(void)
{
	int current;

	current = FindActive();
	wn_sizet(win[current], wdw[win[current]]->last_tile, -1, 0);
}


void SizeActiveRight(void)
{
	int current;

	current = FindActive();
	wn_sizet(win[current], wdw[win[current]]->last_tile, 1, 0);
}


void CloseActive(void)
{
	int current;

	current = FindActive();
	wn_closew(win[current]);
}


void DisplayInputs(void)
{
	int  s,i,b,err;
	int  icode,group,line,stat;

	icode = SioGetc(Port, Tics);
	if (icode < 0) return;
	group = (icode + 1) / 3;

	stat = SioGetc(Port, Tics);
	if (stat < 0) return;

	for (i=0; i<=8; i++) {
		if (in_used[i] == group) {
			line = i + 3;
			break;
		}
		if (in_used[i] == 99) {
			in_used[i] = group;
			line = i + 3;
			break;
		}
	}
	vs_locatecur(win[11],0,1,line);
	vs_printf(win[11],0,fore[11],back[11]," %03u:",group ? (group*24)-8:group);
	if (icode>1)
		vs_locatecur(win[11],0,(6+((icode+1)%3)*9),line);
	else
		vs_locatecur(win[11],0,(6+icode*9),line);
	s = stat;
	for (i=1; i<=8; i++, s = s >> 1)
		vs_printf(win[11],0,fore[11],back[11],(s & 0x0001) ? "1":"0");
}


void DisplayOutputs(void)
{
	int  s,i,b,err;
	int  ocode,group,line,stat;

	ocode = SioGetc(Port, Tics);
	if (ocode < 0) return;
	group = (ocode + 1) / 3;

	stat = SioGetc(Port, Tics);
	if (stat < 0) return;

	for (i=0; i<=8; i++) {
		if (out_used[i] == group) {
			line = i + 3;
			break;
		}
		if (out_used[i] == 99) {
			out_used[i] = group;
			line = i + 3;
			break;
		}
	}
	vs_locatecur(win[12],0,1,line);
	vs_printf(win[12],0,fore[12],back[12]," %03u:",group ? (group*24)-8:group);
	if (ocode>1)
		vs_locatecur(win[12],0,(6+((ocode+1)%3)*9),line);
	else
		vs_locatecur(win[12],0,(6+ocode*9),line);
	s = stat;
	for (i=1; i<=8; i++, s = s >> 1)
		vs_printf(win[12],0,fore[12],back[12],(s & 0x0001) ? "1":"0");
}


void DisplayADCs(void)
{
	int  group,start,i,j,err;
	int  stat[8];

	group = SioGetc(Port, Tics);
	start = group * 8;

	for (i=0; i<=7; i++) {
		stat[i] = (SioGetc(Port, Tics) + (SioGetc(Port, Tics) * 256)) % 9999;
		if (stat[i] < 0) return;
	}
	for (i=0; i<=3; i++) {
		if (group==13)
			vs_locatecur(win[15],0,1,i+5);
		else
			vs_locatecur(win[15],0,1,i+1);
		j = i * 2;
		vs_printf(win[15],0,fore[15],back[15]," %03i: %04i %04i",j+start,
					 stat[j],stat[j+1]);
	}
}


void DisplayDACs(void)
{
	int  group,start,i,j,err;
	int  line,stat[4];

	group = SioGetc(Port, Tics);
	start = group * 4;

	for (i=0; i<=1; i++) {
		stat[i] = (SioGetc(Port, Tics) + (SioGetc(Port, Tics) * 256)) % 9999;
		if (stat[i] < 0) return;
	}

	for (i=0; i<=8; i++) {
		if (dac_used[i] == group) {
			line = i + 1;
			break;
		}
		if (dac_used[i] == 99) {
			dac_used[i] = group;
			line = i + 1;
			break;
		}
	}
	vs_locatecur(win[16],0,1,line);
	vs_printf(win[16],0,fore[16],back[16]," %03i: %04i %04i",start,
					stat[0],stat[1]);
}


void DisplayModule(void)
{
	char house;
	int  s,i,line,ihouse,stat,err;

	ihouse = SioGetc(Port, Tics);
	if (ihouse < 0) return;
	house = (char) ihouse;

	stat = SioGetc(Port, Tics) + (SioGetc(Port, Tics) * 256);

	for (i=0; i<=15; i++) {
		if (house_used[i] == house) {
			line = i + 3;
			break;
		}
		if (house_used[i] == ' ') {
			house_used[i] = house;
			line = i + 3;
			break;
		}
	}
	vs_locatecur(win[14],0,2,line);
	vs_printf(win[14],0,fore[14],back[14],"%1c ",house);
	s = stat;
	for (i=1; i<=16; i++, s = s >> 1)
		vs_printf(win[14],0,fore[14],back[14],(s & 0x0001) ? "1":"0");
	vs_printf(win[14],0,fore[14],back[14]," %1c",house);
}


void DisplayNetwork(void)
{
	int  netmod,i,line,stat,err;

	netmod = SioGetc(Port, Tics);
	if (netmod < 0) return;

	stat = SioGetc(Port, Tics);
	if (stat < 0) return;

	for (i=0; i<=6; i++) {
		if (network_mod[i] == (netmod & 0xf0)) {
			line = i + 2;
			break;
		}
		if (network_mod[i] == 0) {
			network_mod[i] = netmod & 0xf0;
			line = i + 2;
			break;
		}
	}
	vs_locatecur(win[13],0,2,line);
	switch (netmod & 0xf0) {
		case 0x00: vs_printf(win[13],0,fore[13],back[13],"PL   : ");
					 break;
		case 0x10: vs_printf(win[13],0,fore[13],back[13],"MC/IR: ");
					 break;
		case 0x20: vs_printf(win[13],0,fore[13],back[13],"LCD  : ");
					 break;
		case 0x30: vs_printf(win[13],0,fore[13],back[13],"DIO  : ");
					 break;
		case 0x40: vs_printf(win[13],0,fore[13],back[13],"AMAN : ");
					 break;
		case 0x50: vs_printf(win[13],0,fore[13],back[13],"DIO+ : ");
					 break;
	}
	vs_locatecur(win[13],0,(netmod & 0x0f) + 9,line);

	if (stat == 1)
		vs_printf(win[13],0,fore[13],back[13],"*");
	else if (stat == 2)
		vs_printf(win[13],0,fore[13],back[13],"E");
	else
		vs_printf(win[13],0,fore[13],back[13],"-");
}


void DisplayNetbits(void)
{
	int  s,i,b,err;
	int  ncode,group,line,stat;

	ncode = SioGetc(Port, Tics);
	if (ncode < 0) return;
	group = ncode / 3;

	stat = SioGetc(Port, Tics);
	if (stat < 0) return;

	for (i=0; i<=14; i++) {
		if (nb_used[i] == group) {
			line = i + 3;
			break;
		}
		if (nb_used[i] == 99) {
			nb_used[i] = group;
			line = i + 3;
			break;
		}
	}
	vs_locatecur(win[17],0,1,line);
	vs_printf(win[17],0,fore[17],back[17]," %03u:",group*24);
	vs_locatecur(win[17],0,(6+(ncode%3)*9),line);
	s = stat;
	for (i=1; i<=8; i++, s = s >> 1)
		vs_printf(win[17],0,fore[17],back[17],(s & 0x0001) ? "1":"0");
}


void DisplayTime(void)
{
	int i, err, day_date[8];

	for (i=0; i<8; i++) {
		day_date[i] = SioGetc(Port, Tics);
		if (day_date[i] < 0) return;
	}

	vs_locatecur(win[10],0,3,2);
	vs_printf(win[10],0,fore[10],back[10],"%02X:%02X:%02X ",
				day_date[3], day_date[2], day_date[1]);
	switch (day_date[4] & 0x0f) {
		case 1: vs_printf(win[10],0,fore[10],back[10],"Sun, "); break;
		case 2: vs_printf(win[10],0,fore[10],back[10],"Mon, "); break;
		case 3: vs_printf(win[10],0,fore[10],back[10],"Tue, "); break;
		case 4: vs_printf(win[10],0,fore[10],back[10],"Wed, "); break;
		case 5: vs_printf(win[10],0,fore[10],back[10],"Thu, "); break;
		case 6: vs_printf(win[10],0,fore[10],back[10],"Fri, "); break;
		case 7: vs_printf(win[10],0,fore[10],back[10],"Sat, "); break;
	}
	switch (day_date[6]) {
		case 1 : vs_printf(win[10],0,fore[10],back[10],"Jan "); break;
		case 2 : vs_printf(win[10],0,fore[10],back[10],"Feb "); break;
		case 3 : vs_printf(win[10],0,fore[10],back[10],"Mar "); break;
		case 4 : vs_printf(win[10],0,fore[10],back[10],"Apr "); break;
		case 5 : vs_printf(win[10],0,fore[10],back[10],"May "); break;
		case 6 : vs_printf(win[10],0,fore[10],back[10],"Jun "); break;
		case 7 : vs_printf(win[10],0,fore[10],back[10],"Jul "); break;
		case 8 : vs_printf(win[10],0,fore[10],back[10],"Aug "); break;
		case 9 : vs_printf(win[10],0,fore[10],back[10],"Sep "); break;
		case 16: vs_printf(win[10],0,fore[10],back[10],"Oct "); break;
		case 17: vs_printf(win[10],0,fore[10],back[10],"Nov "); break;
		case 18: vs_printf(win[10],0,fore[10],back[10],"Dec "); break;
	}
	if ((day_date[7] & 0xff) > 98)
		vs_printf(win[10],0,fore[10],back[10],"%02X, 19%02X",
				day_date[5], day_date[7] & 0xff);
	else
		vs_printf(win[10],0,fore[10],back[10],"%02X, 20%02X",
				day_date[5], day_date[7] & 0xff);
}


void DisplayMessage(void)
{
	int ch;

	wn_openw(win[18]);
	while ((ch=SioGetc(Port, Tics)) != 0) {
		if (ch < 0) return;
		vs_printf(win[18],0,fore[18],back[18],"%1c",(char)ch);
	}
}


void Happy()
{
	sound(600);
	delay(200);
	sound(800);
	delay(200);
	nosound();
}

void Raz()
{
	sound(600);
	delay(200);
	sound(400);
	delay(200);
	nosound();
}


void NewEvents()
{
	FILE *fp;
	unsigned char old_inactive;
	char ch;
	int  c, count=0;

	vs_clrvs(win[2],0,fore[2],back[2]);
	vs_locatecur(win[2],0,2,1);
	vs_format(win[2],0,fore[2],back[2],
			"Loading new event program...");
	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[2]);
	inactive_attr = old_inactive;

	if ((fp=fopen("events.bin", "rb")) == NULL) {
		vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"EVENTS.BIN file not found!");
		Raz();
		t2_start = time(NULL);
		time2 = true;
		return;
	}

	SioPutc(Port, alert);
	SioPutc(Port, newevnt);
	while ((char) (c=SioGetc(Port, Tics)) != ack) {
		count++;
		if ((c < 0) || (count > 200)) {
			vs_format(win[2],0,fore[2],back[2],
					"\n\n Timeout on controller.  Try again.");
			Raz();
			t2_start = time(NULL);
			time2 = true;
			return;
		}
	}

	count = 0;
	while (!feof(fp)) {
		ch = getc(fp);
		SioPutc(Port, ch);
		count++;
		if (count>100) {
			vs_format(win[2],0,fore[2],back[2],".");
			count = 0;
		}
	}
	fclose(fp);

	ClearWindows();

	c = SioGetc(Port, Tics);
	if ((char)c == badver) {
		vs_format(win[2],0,fore[2],back[2],
				"\n Firmware and COMPILE versions\n don't match.  Recompile your code.");
		Raz();
		t2_start = time(NULL);
		time2 = true;
		return;
	}
	else if ((char)c == toobig) {
		vs_format(win[2],0,fore[2],back[2],
				"\n XPRESS program too big for\n available memory.");
		Raz();
		t2_start = time(NULL);
		time2 = true;
		return;
	}
	else if (((char)c != ack) || (c < 0)) {
		vs_format(win[2],0,fore[2],back[2],
				"\n Error sending events.  Try again.");
		Raz();
		t2_start = time(NULL);
		time2 = true;
		return;
	}

	vs_format(win[2],0,fore[2],back[2],
			"\n New events loaded.");
	Happy();
	t2_start = time(NULL);
	time2 = true;
}


void NewTime(void)
{
	struct tm *systime;
	time_t t;
	unsigned char old_inactive;
	int c, done = false, charcnt = 0, replyst = false;

	vs_clrvs(win[2],0,fore[2],back[2]);
	vs_puts(win[2],0,2,1,35,fore[2],back[2],
			"Updating time...");
	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[2]);
	inactive_attr = old_inactive;

	t = time(NULL);
	systime = localtime(&t);

	SioPutc(Port, alert);
	SioPutc(Port, newtime);

	SioPutc(Port, '\x00');					/* hundredths of sec */
	SioPutc(Port, (char)bcd(systime->tm_sec));
	SioPutc(Port, (char)bcd(systime->tm_min));
	SioPutc(Port, (char)bcd(systime->tm_hour));

	SioPutc(Port, (char)bcd(systime->tm_wday+1));
	SioPutc(Port, (char)bcd(systime->tm_mday));
	SioPutc(Port, (char)bcd(systime->tm_mon+1));
	SioPutc(Port, (char)bcd(systime->tm_year));

	while (!done) {
		c = SioGetc(Port, Tics);
		charcnt++;
		if ((c < 0) || (charcnt > 200)) {
			vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"Timeout on controller.  Try again.");
			Raz();
			t2_start = time(NULL);
			time2 = true;
			return;
		}
		if ((char)c == reply)
			replyst = true;
		else if (((char)c == newtime) && replyst)
			done = true;
		else
			replyst = false;
	}

	vs_puts(win[2],0,2,3,35,fore[2],back[2],
			"New time loaded.");
	Happy();
	t2_start = time(NULL);
	time2 = true;
}


void DumpLog()
{
	FILE *fp;
	unsigned char *dump, old_inactive;
	int  c, replyst=false, last=0, done=false;
	int  i=0, charcnt=0, count=0;

	vs_clrvs(win[2],0,fore[2],back[2]);
	vs_locatecur(win[2],0,2,1);
	vs_format(win[2],0,fore[2],back[2],
			"Dumping logged data to disk...");
	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[2]);
	inactive_attr = old_inactive;

	if ((fp=fopen("logdata.bin", "wb")) == NULL) {
		vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"Error opening LOGDATA.BIN file!");
		Raz();
		t2_start = time(NULL);
		time2 = true;
		return;
	}

	dump = malloc(32768);
	if (!dump) {
		vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"Error allocating memory!");
		Raz();
		t2_start = time(NULL);
		time2 = true;
		return;
	}

	SioPutc(Port, alert);
	SioPutc(Port, dumplog);

	while (!done) {
		c = SioGetc(Port, Tics);
		charcnt++;
		if ((c < 0) || (charcnt > 200)) {
			vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"Timeout on controller.  Try again.");
			Raz();
			t2_start = time(NULL);
			time2 = true;
			return;
		}
		if ((char)c == reply)
			replyst = true;
		else if (((char)c == dumplog) && replyst)
			done = true;
		else
			replyst = false;
	}

	done = false;

	while (!done) {
		c = SioGetc(Port, Tics);
		dump[i++] = (char) c;
		count++;
		if (count>255) {
			vs_format(win[2],0,fore[2],back[2],".");
			count = 0;
		}
		if (c==0xff) {
			last++;
			if (last>=3)
				done = true;
		}
		else
			last = 0;
		if (c < 0) {
			vs_puts(win[2],0,2,3,35,fore[2],back[2],
					"Timeout on controller.  Try again.");
			Raz();
			t2_start = time(NULL);
			time2 = true;
			return;
		}
	}

	if (fwrite(dump, (i-3), 1, fp) != 1) {
		vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"Error writing LOGDATA.BIN file!");
		Raz();
		t2_start = time(NULL);
		time2 = true;
		return;
	}

	fclose(fp);
	free(dump);

	vs_puts(win[2],0,2,3,35,fore[2],back[2],
			"Logged data saved.");
	Happy();
	t2_start = time(NULL);
	time2 = true;
}


void ClearLog(void)
{
	unsigned char old_inactive;
	int c, done = false, charcnt = 0;
	int replyst = false;

	vs_clrvs(win[2],0,fore[2],back[2]);
	vs_puts(win[2],0,2,1,35,fore[2],back[2],
			"Clearing log...");
	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[2]);
	inactive_attr = old_inactive;

	SioPutc(Port, alert);
	SioPutc(Port, clrlog);

	while (!done) {
		c = SioGetc(Port, Tics);
		charcnt++;
		if ((c < 0) || (charcnt > 200)) {
			vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"Timeout on controller.  Try again.");
			Raz();
			t2_start = time(NULL);
			time2 = true;
			return;
		}
		if ((char)c == reply)
			replyst = true;
		else if (((char)c == clrlog) && replyst)
			done = true;
		else
			replyst = false;
	}
	vs_puts(win[2],0,2,3,35,fore[2],back[2],
			"Log storage cleared.");
	Happy();
	t2_start = time(NULL);
	time2 = true;
}


void LogSize()
{
	unsigned char old_inactive;
	int  c, i, replyst=false, done=false, charcnt=0, size=0;

	vs_clrvs(win[2],0,fore[2],back[2]);
	vs_locatecur(win[2],0,1,1);
	vs_printf(win[2],0,fore[2],back[2]," Getting log size...");
	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[2]);
	inactive_attr = old_inactive;

	SioPutc(Port, alert);
	SioPutc(Port, logsize);

	while (!done) {
		c = SioGetc(Port, Tics);
		charcnt++;
		if ((c < 0) || (charcnt > 200)) {
			vs_puts(win[2],0,2,3,35,fore[2],back[2],
				"Timeout on controller.  Try again.");
			Raz();
			t2_start = time(NULL);
			time2 = true;
			return;
		}
		if ((char)c == reply)
			replyst = true;
		else if (((char)c == logsize) && replyst)
			done = true;
		else
			replyst = false;
	}

	for (i=0; i<2; i++) {
		c = SioGetc(Port, Tics);
		if (c < 0) {
			vs_puts(win[2],0,2,3,35,fore[2],back[2],
					"Timeout on controller.  Try again.");
			Raz();
			t2_start = time(NULL);
			time2 = true;
			return;
		}
		size = size + (i ? c*256 : c);
	}

	if (size == 1)
		vs_printf(win[2],0,fore[2],back[2],"\n\n Log size = %i entry",size);
	else
		vs_printf(win[2],0,fore[2],back[2],"\n\n Log size = %i entries",size);

	t2_start = time(NULL);
	time2 = true;
}


void SetInput()
{
	unsigned char old_inactive;
	char state, buffer[5];
	int innum, abort = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Enter input number (0-255): ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
	sscanf(buffer,"%i",&innum);
	if ((innum<0) || (innum>255)) {
		vs_printf(win[3],0,fore[3],back[3],"\nInvalid input number.\n");
		delay(1000);
		abort = true;
	}
	if (!abort) {
		vs_printf(win[3],0,fore[3],back[3],"\nEnter new state (0/1/T): ");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%c",&state);
		if ((state!='0') && (state!='1') && (toupper(state)!='T')) {
			vs_printf(win[3],0,fore[3],back[3],"\nInvalid state.\n");
			delay(1000);
			abort = true;
		}
	}
	if (!abort) {
		SioPutc(Port, alert);
		SioPutc(Port, setin);
		SioPutc(Port, (char) innum);
		switch (toupper(state)) {
			case '0':	SioPutc(Port, '\x00');
								break;
			case '1':	SioPutc(Port, '\x01');
								break;
			case 'T':	SioPutc(Port, '\x02');
								break;
		}
	}
	wn_hidecur();
	wn_closew(win[3]);
}


void SetOutput()
{
	unsigned char old_inactive;
	char buffer[5];
	int outnum, state, abort = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Enter output number (0-255): ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
	sscanf(buffer,"%i",&outnum);
	if ((outnum<0) || (outnum>255)) {
		vs_printf(win[3],0,fore[3],back[3],"\nInvalid output number.\n");
		delay(1000);
		abort = true;
	}
	if (!abort) {
		vs_printf(win[3],0,fore[3],back[3],"\nEnter new state (0/1): ");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%i",&state);
		if ((state!=0) && (state!=1)) {
			vs_printf(win[3],0,fore[3],back[3],"\nInvalid state.\n");
			delay(1000);
			abort = true;
		}
	}
	if (!abort) {
		SioPutc(Port, alert);
		SioPutc(Port, setout);
		SioPutc(Port, (char) outnum);
		SioPutc(Port, (char) state);
	}
	wn_hidecur();
	wn_closew(win[3]);
}


void SetADC()
{
	unsigned char old_inactive;
	char state, buffer[5];
	int adcnum, value, abort = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Enter ADC number (0-135): ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
	sscanf(buffer,"%i",&adcnum);
	if ((adcnum<0) || (adcnum>135)) {
		vs_printf(win[3],0,fore[3],back[3],"\nInvalid ADC number.\n");
		delay(1000);
		abort = true;
	}
	if (!abort) {
		vs_printf(win[3],0,fore[3],back[3],"\nEnter new value (0-4095/T): ");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%c",&state);
		if (toupper(state)!='T') {
			sscanf(buffer,"%i",&value);
			if ((value<0) || (value>4095)) {
				vs_printf(win[3],0,fore[3],back[3],"\nInvalid value.\n");
				delay(1000);
				abort = true;
			}
		}
		else
			value = 4096;
	}
	if (!abort) {
		SioPutc(Port, alert);
		SioPutc(Port, setadc);
		SioPutc(Port, (char) adcnum);
		SioPutc(Port, (char) (value%256));
		SioPutc(Port, (char) (value/256));
	}
	wn_hidecur();
	wn_closew(win[3]);
}


void SetDAC()
{
	unsigned char old_inactive;
	char buffer[5];
	int dacnum, value, abort = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Enter DAC number (0-31): ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
	sscanf(buffer,"%i",&dacnum);
	if ((dacnum<0) || (dacnum>31)) {
		vs_printf(win[3],0,fore[3],back[3],"\nInvalid DAC number.\n");
		delay(1000);
		abort = true;
	}
	if (!abort) {
		vs_printf(win[3],0,fore[3],back[3],"\nEnter new value (0-4095): ");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%i",&value);
		if ((value<0) || (value>4095)) {
			vs_printf(win[3],0,fore[3],back[3],"\nInvalid value.\n");
			delay(1000);
			abort = true;
		}
	}
	if (!abort) {
		SioPutc(Port, alert);
		SioPutc(Port, setdac);
		SioPutc(Port, (char) dacnum);
		SioPutc(Port, (char) (value%256));
		SioPutc(Port, (char) (value/256));
	}
	wn_hidecur();
	wn_closew(win[3]);
}


void SetX10()
{
	unsigned char old_inactive;
	char buffer[5], house;
	int module, func, count = 2, abort = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Enter house code (A-P): ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
	sscanf(buffer,"%c",&house);
	if ((toupper(house)<'A') || (toupper(house)>'P')) {
		vs_printf(win[3],0,fore[3],back[3],"\nInvalid house code.\n");
		delay(1000);
		abort = true;
	}
	if (!abort) {
		vs_printf(win[3],0,fore[3],back[3],"Enter module number (1-16): ");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%i",&module);
		if ((module<1) || (module>16)) {
			vs_printf(win[3],0,fore[3],back[3],"\nInvalid number.\n");
			delay(1000);
			abort = true;
		}
	}
	if (!abort) {
		vs_printf(win[3],0,fore[3],back[3],"1=AllUnitsOff, 2=AllLightsOn");
		vs_printf(win[3],0,fore[3],back[3],"\n3=On, 4=Off, 5=Dim, 6=Bright");
		vs_printf(win[3],0,fore[3],back[3],"\nEnter function code (1-6): ");
		wn_showcur();
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%i",&func);
		if ((func<1) || (func>6)) {
			vs_printf(win[3],0,fore[3],back[3],"\nInvalid code.\n");
			delay(1000);
			abort = true;
		}
	}
	if (!abort && func>=5) {
		vs_printf(win[3],0,fore[3],back[3],"Enter number of steps (1-31): ");
		wn_showcur();
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%i",&count);
		if ((count<1) || (count>31)) {
			vs_printf(win[3],0,fore[3],back[3],"\nInvalid number.\n");
			delay(1000);
			abort = true;
		}
	}
	if (!abort) {
		SioPutc(Port, alert);
		SioPutc(Port, setx10);
		SioPutc(Port, (char) (((toupper(house)-'A')<<4) + (module-1)));
		SioPutc(Port, (char) (func-1));
		SioPutc(Port, (char) count);
	}
	wn_hidecur();
	wn_closew(win[3]);
}


void SetNetbit()
{
	unsigned char old_inactive;
	char buffer[5];
	int bitnum, state, abort = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Enter netbit number (0-319): ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
	sscanf(buffer,"%i",&bitnum);
	if ((bitnum<0) || (bitnum>319)) {
		vs_printf(win[3],0,fore[3],back[3],"\nInvalid netbit number.\n");
		delay(1000);
		abort = true;
	}
	if (!abort) {
		vs_printf(win[3],0,fore[3],back[3],"\nEnter new state (0/1): ");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],5);
		sscanf(buffer,"%i",&state);
		if ((state!=0) && (state!=1)) {
			vs_printf(win[3],0,fore[3],back[3],"\nInvalid state.\n");
			delay(1000);
			abort = true;
		}
	}
	if (!abort) {
		SioPutc(Port, alert);
		SioPutc(Port, setbit);
		SioPutc(Port, (char) (bitnum%256));
		SioPutc(Port, (char) (bitnum/256));
		SioPutc(Port, (char) state);
	}
	wn_hidecur();
	wn_closew(win[3]);
}


void NetString()
{
	unsigned char old_inactive;
	char buffer[80];
	int i = 0, done = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;

	while (!done) {
		i = 0;
		vs_clrvs(win[3],0,fore[3],back[3]);
		vs_locatecur(win[3],0,1,1);

		wn_showcur();
		vs_printf(win[3],0,fore[3],back[3],"Enter a network command string:\n");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],80);
		wn_hidecur();

		if (buffer[0]) {
			SioPutc(Port, alert);
			SioPutc(Port, netstr);
			while (buffer[i])
				SioPutc(Port, buffer[i++]);
			SioPutc(Port, '\x00');

			SioPutc(Port, alert);
			SioPutc(Port, pause);
		}
		else
			done = true;
	}
	wn_closew(win[3]);
}


void VoiceString()
{
	unsigned char old_inactive;
	char buffer[80];
	int i = 0, done = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;

	while (!done) {
		i = 0;
		vs_clrvs(win[3],0,fore[3],back[3]);
		vs_locatecur(win[3],0,1,1);
		wn_showcur();

		vs_printf(win[3],0,fore[3],back[3],"Enter a voice string:\n");
		vs_gets(win[3],0,true,buffer,fore[3],back[3],80);
		wn_hidecur();

		if (buffer[0]) {
			SioPutc(Port, alert);
			SioPutc(Port, vstr);
			while (buffer[i])
				SioPutc(Port, buffer[i++]);
			SioPutc(Port, '\x00');

			SioPutc(Port, alert);
			SioPutc(Port, pause);
		}
		else
			done = true;
	}
	wn_closew(win[3]);
}


void ModemOut(char str[])
{
	int	i=0;

	while (str[i]) {
		SioPutc(Port, str[i]);
		i++;
	}
}


void ModemIn(char str[],int timeout)
{
	int i=0, c=0;
	char ch;

	do {
		ch = SioGetc(Port, timeout*18);
		str[i++] = ch;
		if (ch == '\n')
			c++;
	}
	while ((ch > 0) && (c < 2));

	if (ch < 0) {
		i = 0;
		vs_printf(win[3],0,fore[3],back[3],"\nError communicating with modem.\n");
	}
	str[i] = '';
}


void ModemInit(void)
{
	unsigned char old_inactive;
	char *buf, buffer[30], repbuf[50];

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Current string = %s\n",modinit);
	vs_printf(win[3],0,fore[3],back[3],"\nEnter new init string: ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],30);
	wn_hidecur();
	if (buffer[0])
		strcpy(modinit, buffer);
	else {
		vs_printf(win[3],0,fore[3],back[3],"Init string unchanged\n");
		delay(3000);
	}
	wn_closew(win[3]);
}


void Hangup()
{
	SioDTR(Port, 'C');
	delay(1000);
	SioDTR(Port, 'S');
}


void Dial(void)
{
	unsigned char old_inactive;
	char *buf, buffer[30], repbuf[50];

	old_inactive = inactive_attr;
	inactive_attr = black + (lightgray << 4);
	wn_openw(win[3]);
	inactive_attr = old_inactive;
	vs_clrvs(win[3],0,fore[3],back[3]);
	vs_locatecur(win[3],0,1,1);
	wn_showcur();

	vs_printf(win[3],0,fore[3],back[3],"Enter phone number: ");
	vs_gets(win[3],0,true,buffer,fore[3],back[3],30);
	wn_hidecur();
	if (buffer[0]) {
		vs_printf(win[3],0,fore[3],back[3],"Resetting modem...");
		SioDTR(Port, 'S');
		ModemOut("ATZ\r");
		ModemIn(repbuf,4);
		if (strstr(repbuf,"OK")) {
			ModemOut(modinit);
			ModemOut("\r");
			ModemIn(repbuf,2);
			if (strstr(repbuf,"OK")) {
				vs_printf(win[3],0,fore[3],back[3],"\nDialing %s...",buffer);
				ModemOut("ATD");
				ModemOut(buffer);
				ModemOut("\r");
				ModemIn(repbuf,60);
				buf = strstr(repbuf,"\r");
				vs_printf(win[3],0,fore[3],back[3],"%s",buf);
				if (strstr(repbuf,"CONNECT"))
					SioPutc(Port, cr);
				else
					Hangup();
			}
			else
				Hangup();
		}
		else
			Hangup();
	}
	else
		vs_printf(win[3],0,fore[3],back[3],"Aborting dial\n");
	delay(3000);
	wn_closew(win[3]);
}


void SpecialMenu()
{
	unsigned char old_active;
	unsigned int chx;
	int button, pressed, x, y;
	int done = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	vs_putcods(win[0],0,2,1,3,black,green,red,green," ~! ");
	old_active = active_attr;
	active_attr = black + (lightgray << 4);
	wn_openw(win[4]);
	active_attr = old_active;

	while (!done) {
		if (mousepresent) {
			button = 1;
			kb_mousepressed(&button, &pressed, &x, &y);

			x = (x/8) + 1;
			y = (y/8) + 1;

			if (pressed) {
				if ((y==3) && (x>3) && (x<12)) {
					wn_closew(win[4]);
					wn_openw(win[1]);
					t1_start = time(NULL);
					time1 = true;
				}
				done = true;
			}
		}
		if (kbhit()) {
			chx = kb_getxc();
			switch (chx >> 8) {
				case 0x1e:	wn_closew(win[4]);			/* A */
										wn_openw(win[1]);
										t1_start = time(NULL);
										time1 = true;
			}
			done = true;
		}
	}
	wn_closew(win[4]);
	vs_putcods(win[0],0,2,1,3,black,lightgray,red,lightgray," ~! ");

	SioPutc(Port, alert);
	SioPutc(Port, update);
}


int FileMenu()
{
	unsigned char old_active;
	unsigned int chx;
	int button, pressed, x, y;
	int done = false, quit = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	vs_putcods(win[0],0,5,1,6,black,green,red,green," ~File ");
	old_active = active_attr;
	active_attr = black + (lightgray << 4);
	wn_openw(win[5]);
	active_attr = old_active;

	while (!done) {
		if (mousepresent) {
			button = 1;
			kb_mousepressed(&button, &pressed, &x, &y);

			x = (x/8) + 1;
			y = (y/8) + 1;

			if (pressed) {
				if ((y==3) && (x>7) && (x<12))
					NewEvents();
				else if ((y==4) && (x>7) && (x<12))
					quit = true;
				done = true;
			}
		}
		if (kbhit()) {
			chx = kb_getxc();
			switch (chx >> 8) {
				case 0x26:	NewEvents();	/* L */
										break;
				case 0x10:	quit = true;	/* Q */
			}
			done = true;
		}
	}
	wn_closew(win[5]);
	vs_putcods(win[0],0,5,1,6,black,lightgray,red,lightgray," ~File ");

	SioPutc(Port, alert);
	SioPutc(Port, update);

	return(quit);
}


void CommandMenu()
{
	unsigned char old_active;
	unsigned int chx;
	int button, pressed, x, y;
	int done = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	vs_putcods(win[0],0,11,1,9,black,green,red,green," ~Command ");
	old_active = active_attr;
	active_attr = black + (lightgray << 4);
	wn_openw(win[6]);
	active_attr = old_active;

	while (!done) {
		if (mousepresent) {
			button = 1;
			kb_mousepressed(&button, &pressed, &x, &y);

			x = (x/8) + 1;
			y = (y/8) + 1;

			if (pressed) {
				if ((y==3) && (x>12) && (x<26))
					NewTime();
				else if ((y==4) && (x>12) && (x<26))
					SetInput();
				else if ((y==5) && (x>12) && (x<26))
					SetOutput();
				else if ((y==6) && (x>12) && (x<26))
					SetX10();
				else if ((y==7) && (x>12) && (x<26))
					SetADC();
				else if ((y==8) && (x>12) && (x<26))
					SetDAC();
				else if ((y==9) && (x>12) && (x<26))
					SetNetbit();
				else if ((y==10) && (x>12) && (x<26))
					VoiceString();
				else if ((y==11) && (x>12) && (x<26))
					NetString();
				done = true;
			}
		}
		if (kbhit()) {
			chx = kb_getxc();
			switch (chx >> 8) {
				case 0x14:	NewTime();			/* T */
										break;
				case 0x17:	SetInput();			/* I */
										break;
				case 0x18:	SetOutput();		/* O */
										break;
				case 0x2d:	SetX10();				/* X */
										break;
				case 0x1e:	SetADC();				/* A */
										break;
				case 0x20:	SetDAC();				/* D */
										break;
				case 0x30:	SetNetbit();		/* B */
										break;
				case 0x2f:	VoiceString();	/* V */
										break;
				case 0x31:	NetString();		/* N */
										break;
			}
			done = true;
		}
	}
	wn_closew(win[6]);
	vs_putcods(win[0],0,11,1,9,black,lightgray,red,lightgray," ~Command ");

	SioPutc(Port, alert);
	SioPutc(Port, update);
}


void LogMenu()
{
	unsigned char old_active;
	unsigned int chx;
	int button, pressed, x, y;
	int done = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	vs_putcods(win[0],0,20,1,5,black,green,red,green," ~Log ");
	old_active = active_attr;
	active_attr = black + (lightgray << 4);
	wn_openw(win[7]);
	active_attr = old_active;

	while (!done) {
		if (mousepresent) {
			button = 1;
			kb_mousepressed(&button, &pressed, &x, &y);

			x = (x/8) + 1;
			y = (y/8) + 1;

			if (pressed) {
				if ((y==3) && (x>21) && (x<27))
					ClearLog();
				else if ((y==4) && (x>21) && (x<27))
					LogSize();
				else if ((y==5) && (x>21) && (x<27))
					DumpLog();
				done = true;
			}
		}
		if (kbhit()) {
			chx = kb_getxc();
			switch (chx >> 8) {
				case 0x2e:	ClearLog();	/* C */
										break;
				case 0x1f:	LogSize();	/* S */
										break;
				case 0x20:	DumpLog();	/* D */
										break;
			}
			done = true;
		}
	}
	wn_closew(win[7]);
	vs_putcods(win[0],0,20,1,5,black,lightgray,red,lightgray," ~Log ");

	SioPutc(Port, alert);
	SioPutc(Port, update);
}


void WindowMenu()
{
	unsigned char old_active;
	unsigned int chx;
	int button, pressed, x, y;
	int done = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	vs_putcods(win[0],0,25,1,8,black,green,red,green," ~Window ");
	old_active = active_attr;
	active_attr = black + (lightgray << 4);
	wn_openw(win[8]);
	active_attr = old_active;

	while (!done) {
		if (mousepresent) {
			button = 1;
			kb_mousepressed(&button, &pressed, &x, &y);

			x = (x/8) + 1;
			y = (y/8) + 1;

			if (pressed) {
				if ((y==3) && (x>26) && (x<39))
					wn_openw(win[10]);
				else if ((y==4) && (x>26) && (x<39))
					wn_openw(win[11]);
				else if ((y==5) && (x>26) && (x<39))
					wn_openw(win[12]);
				else if ((y==6) && (x>26) && (x<39))
					wn_openw(win[13]);
				else if ((y==7) && (x>26) && (x<39))
					wn_openw(win[14]);
				else if ((y==8) && (x>26) && (x<39))
					wn_openw(win[15]);
				else if ((y==9) && (x>26) && (x<39))
					wn_openw(win[16]);
				else if ((y==10) && (x>26) && (x<39))
					wn_openw(win[17]);
				else if ((y==11) && (x>26) && (x<39))
					wn_openw(win[18]);
				done = true;
			}
		}
		if (kbhit()) {
			chx = kb_getxc();
			switch (chx >> 8) {
				case 0x14:	wn_openw(win[10]);	/* T */
										break;
				case 0x20:	wn_openw(win[11]);	/* D */
										break;
				case 0x18:	wn_openw(win[12]);	/* O */
										break;
				case 0x31:	wn_openw(win[13]);	/* N */
										break;
				case 0x2d:	wn_openw(win[14]);	/* X */
										break;
				case 0x1e:	wn_openw(win[15]);	/* A */
										break;
				case 0x22:	wn_openw(win[16]);	/* G */
										break;
				case 0x30:	wn_openw(win[17]);	/* B */
										break;
				case 0x32:	wn_openw(win[18]);	/* M */
										break;
			}
			done = true;
		}
	}
	wn_closew(win[8]);
	vs_putcods(win[0],0,25,1,8,black,lightgray,red,lightgray," ~Window ");

	SioPutc(Port, alert);
	SioPutc(Port, update);
}


void ModemMenu()
{
	unsigned char old_active;
	unsigned int chx;
	int button, pressed, x, y;
	int done = false;

	SioPutc(Port, alert);
	SioPutc(Port, pause);

	vs_putcods(win[0],0,33,1,7,black,green,red,green," ~Modem ");
	old_active = active_attr;
	active_attr = black + (lightgray << 4);
	wn_openw(win[9]);
	active_attr = old_active;

	while (!done) {
		if (mousepresent) {
			button = 1;
			kb_mousepressed(&button, &pressed, &x, &y);

			x = (x/8) + 1;
			y = (y/8) + 1;

			if (pressed) {
				if ((y==3) && (x>34) && (x<42))
					ModemInit();
				else if ((y==4) && (x>34) && (x<42))
					Dial();
				else if ((y==5) && (x>34) && (x<42))
					Hangup();
				done = true;
			}
		}
		if (kbhit()) {
			chx = kb_getxc();
			switch (chx >> 8) {
				case 0x17:	ModemInit();	/* I */
										break;
				case 0x20:	Dial();				/* D */
										break;
				case 0x23:	Hangup();			/* H */
										break;
			}
			done = true;
		}
	}
	wn_closew(win[9]);
	vs_putcods(win[0],0,33,1,7,black,lightgray,red,lightgray," ~Modem ");

	SioPutc(Port, alert);
	SioPutc(Port, update);
}


main(int argc, char *argv[])
{
	int error, i, c, done = false, help;
	int button, pressed, xm, ym, m1, m2, m3, m4;
	unsigned int rhandle, x, y, offset, chx, shift;

	wn_init();

	mousepresent = kb_ismouse();

	if (argc>1) {
		if (!stricmp(argv[1],"/COM1") || !stricmp(argv[2],"/COM1")) {
			Port = 0;
			help = false;
		}
		if (!stricmp(argv[1],"/COM2") || !stricmp(argv[2],"/COM2")) {
			Port = 1;
			help = false;
		}
		if (!stricmp(argv[1],"/COM3") || !stricmp(argv[2],"/COM3")) {
			Port = 2;
			help = false;
		}
		if (!stricmp(argv[1],"/COM4") || !stricmp(argv[2],"/COM4")) {
			Port = 3;
			help = false;
		}
		if (!stricmp(argv[1],"/M") || !stricmp(argv[2],"/M")) {
			for (i=0; i<16; i++) {
				ibm_fcolor_table[i] = 0;
				ibm_bcolor_table[i] = 7;
			}
			ibm_fcolor_table[15] = 15;
			ibm_fcolor_table[7]  = 7;
			ibm_bcolor_table[0]  = 0;
			help = false;
		}
		if (help) {
			printf("\nCircuit Cellar HCS/SpectraSense Host Program");
			printf("\n Version 3.60\n");
			printf("\nUsage: HOST {/COM1|/COM2|/COM3|/COM4} {/M}\n");
			printf("\nwhere: COM1 = serial port 1");
			printf("\n       COM2 = serial port 2");
			printf("\n       COM3 = serial port 3");
			printf("\n       COM4 = serial port 4");
			printf("\n       M    = monochrome display\n");
			return 1;
		}
	}

	if (mousepresent)
		kb_showmouse();

	clrscr();

	error = InitPort();
	if (error) {
		printf("\nError initializing serial port!\n");
		kb_hidemouse();
		SioDone(Port);
		return 1;
	}

	ReadScreen();
	SetupScreen();

	SioPutc(Port, cr);

	SioPutc(Port, alert);
	SioPutc(Port, update);

	while (kbhit()) getch();

	while (!done) {
		while (!kbhit() && !done) {
			if (time1)
				if (difftime(time(NULL), t1_start) >= 8) {
					time1 = false;
					wn_closew(win[1]);
				}
			if (time2)
				if (difftime(time(NULL), t2_start) >= 4) {
					time2 = false;
					wn_closew(win[2]);
				}
			if ((c=SioGetc(Port, 0)) >= 0)
				if ((char)c == reply)
					if ((c=SioGetc(Port, Tics)) >= 0)
						switch ((char) c) {
							case curtime: DisplayTime();
														break;
							case x10stat: DisplayModule();
														break;
							case inpstat: DisplayInputs();
														break;
							case outstat: DisplayOutputs();
														break;
							case adcstat: DisplayADCs();
														break;
							case dacstat: DisplayDACs();
														break;
							case modstat: DisplayNetwork();
														break;
							case netstat: DisplayNetbits();
														break;
							case msgdisp: DisplayMessage();
														break;
						}

			if (mousepresent) {

				/* Check for mouse click */

				button = 1;
				kb_mousepressed(&button, &pressed, &xm, &ym);

				/* Convert to screen coordinates */

				x = (xm/8) + 1;
				y = (ym/8) + 1;

				if (pressed && (wn_isonwdw(x, y, &rhandle)) && (rhandle == 0) &&
						(y == 1)) {

					/* Do menu bar */

					if (x<5)
						SpecialMenu();
					else if ((x>4) && (x<11))
						done = FileMenu();
					else if ((x>10) && (x<20))
						CommandMenu();
					else if ((x>19) && (x<25))
						LogMenu();
					else if ((x>24) && (x<33))
						WindowMenu();
					else if ((x>32) && (x<40))
						ModemMenu();
				}

				else if (pressed && (wn_isonwdw(x, y, &rhandle)) && (rhandle > 0)) {

					/* Bring window clicked to front */

					if (rhandle != last_wdw) {
						kb_hidemouse();
						wn_openw(rhandle);
						kb_showmouse();
					}

					/* If button pressed, check out where we are */

					m2 = 1;
					kb_mousestatus(&m2, &m3, &m4);
					if (m2) {

						/* Do window move */

						if (wn_isonubar(rhandle, x, y)) {
							m2 = 1;		/* Flag button as pressed */
							offset = x - wdw[rhandle]->physical_x;
							while (m2 == 1) {
								kb_mousestatus(&m2, &m3, &m4);
								x = (m3/8) + 1;
								y = (m4/8) + 1;
								if ((wdw[rhandle]->physical_x != (x-offset)) ||
										(wdw[rhandle]->physical_y != y)) {
									kb_hidemouse();
									wn_locatew(rhandle, (x-offset), y);
									kb_showmouse();
								}
							}
						}

						/* Do window size */

						else if (wn_isonlrc(rhandle, x, y)){
							m2 = 1;		/* Flag button as pressed */
							while (m2 == 1) {
								kb_mousestatus(&m2, &m3, &m4);
								x = (m3/8) + 1;
								y = (m4/8) + 1;
								if (((wdw[rhandle]->physical_x +
										wdw[rhandle]->port_columns + 1) != x) ||
										((wdw[rhandle]->physical_y +
										wdw[rhandle]->port_rows + 1) != y)) {
									kb_hidemouse();
									wn_sizet(rhandle,
										wdw[rhandle]->last_tile,
										x - wdw[rhandle]->physical_x
											- wdw[rhandle]->port_columns - 1,
										y - wdw[rhandle]->physical_y
											- wdw[rhandle]->port_rows - 1);
									kb_showmouse();
								}
							}
						}

						else if (wn_isonulc(rhandle, x, y))
							wn_closew(rhandle);

						/* Do the scroll bars in the same way */

						else if (wn_isonsbd(rhandle, 0, x, y)) {
							m2 = 1;
							while (m2 == 1) {
								kb_mousestatus(&m2, &m3, &m4);
								kb_hidemouse();
								wn_scrollvs(rhandle,0,0,1);
								kb_showmouse();
								wn_sync_tw_to_vs(rhandle, 0);
							}
						}

						else if (wn_isonsbr(rhandle, 0, x, y)) {
							m2 = 1;
							while (m2 == 1) {
								kb_mousestatus(&m2, &m3, &m4);
								kb_hidemouse();
								wn_scrollvs(rhandle,0,1,0);
								kb_showmouse();
								wn_sync_tw_to_vs(rhandle, 0);
							}
						}

						else if (wn_isonsbl(rhandle, 0, x, y)) {
							m2 = 1;
							while (m2 == 1) {
								kb_mousestatus(&m2, &m3, &m4);
								kb_hidemouse();
								wn_scrollvs(rhandle,0,-1,0);
								kb_showmouse();
								wn_sync_tw_to_vs(rhandle, 0);
							}
						}

						else if (wn_isonsbu(rhandle, 0, x, y)) {
							m2 = 1;
							while (m2 == 1) {
								kb_mousestatus(&m2, &m3, &m4);
								kb_hidemouse();
								wn_scrollvs(rhandle,0,0,-1);
								kb_showmouse();
								wn_sync_tw_to_vs(rhandle, 0);
							}
						}

						else if (wn_isonvtw(rhandle, 0, x, y)) {
							kb_mousestatus(&m2, &m3, &m4);
							while (m2 == 1) {
								y = m4/(200/physical_rows) + 1;
								y = y - (wdw[rhandle]->physical_y + 2);
								kb_hidemouse();
								wn_locatetwabs(rhandle, 0, -1, y);
								wn_sync_vs_to_tw(rhandle, 0);
								kb_showmouse();
								kb_mousestatus(&m2, &m3, &m4);
							}
						}
						else if (wn_isonhtw(rhandle, 0, x, y)) {
							kb_mousestatus(&m2, &m3, &m4);
							while (m2 == 1) {
								x = m3/(640/physical_columns) + 1;
								kb_hidemouse();
								x = x - (wdw[rhandle]->physical_x + 2);
								wn_locatetwabs(rhandle, 0, x, -1);
								wn_sync_vs_to_tw(rhandle, 0);
								kb_showmouse();
								kb_mousestatus(&m2, &m3, &m4);
							}
						}

						else if (wn_isonvrbar(rhandle, 0, x, y)) {
							y = y - (wdw[rhandle]->physical_y + 2);
							wn_locatetwabs(rhandle, 0, -1, y);
							wn_sync_vs_to_tw(rhandle, 0);
						}

						else if (wn_isonhbar(rhandle, 0, x, y)) {
							x = x - (wdw[rhandle]->physical_x + 2);
							wn_locatetwabs(rhandle, 0, x, -1);
							wn_sync_vs_to_tw(rhandle, 0);
						}
					}

					/* If it is a single-click, we've got different choices */
					else if (pressed) {

						/* If it is in a virtual screen move the screen's cursor */

						if (wn_isonvs(rhandle,0,&x,&y))
							vs_locatecur(rhandle,0,x,y);

						/* We handle single clicks on scroll bars in the same way */

						else if (wn_isonsbu(rhandle, 0, x, y))
							wn_scrollvs(rhandle,0,0,1);
						else if (wn_isonsbl(rhandle, 0, x, y))
							wn_scrollvs(rhandle,0,1,0);
						else if (wn_isonsbr(rhandle, 0, x, y))
							wn_scrollvs(rhandle,0,-1,0);
						else if (wn_isonsbd(rhandle, 0, x, y))
							wn_scrollvs(rhandle,0,0,-1);
						else if (wn_isonvrbar(rhandle, 0, x, y)) {
							y = y - (wdw[rhandle]->physical_y + 2);
							wn_locatetwabs(rhandle, 0, -1, y);
							wn_sync_vs_to_tw(rhandle, 0);
						}
						else if (wn_isonhbar(rhandle, 0, x, y)) {
							x = x - (wdw[rhandle]->physical_x + 2);
							wn_locatetwabs(rhandle, 0, x, -1);
							wn_sync_vs_to_tw(rhandle, 0);
						}
						else if (wn_isonurc(rhandle, x, y)) {
							kb_hidemouse();
							wn_zoomw();
							kb_showmouse();
						}
						else if (wn_isonulc(rhandle, x, y))
							wn_closew(rhandle);
					}
				}
			}
		}
		if (kbhit() && !done) {
			chx = kb_getxc();
			shift = kb_getshift();
			if (!(shift & 0x0003))
				switch (chx >> 8) {
					case 0x21:	done = FileMenu();			/* F */
											break;
					case 0x2e:	CommandMenu();					/* C */
											break;
					case 0x26:	LogMenu();							/* L */
											break;
					case 0x11:	WindowMenu();						/* W */
											break;
					case 0x32:	ModemMenu();						/* M */
											break;
					case 0x10:	done = true;						/* Q */
											break;
					case 0x1c:	SioPutc(Port, alert);		/* Enter */
											SioPutc(Port, update);
											break;
					case 0x0f:	NextActive();						/* Tab */
											break;
					case 0x53:	CloseActive();					/* Delete */
											break;
					case 0x48:	MoveActiveUp();					/* Up */
											break;
					case 0x50:	MoveActiveDown();				/* Down */
											break;
					case 0x4b:	MoveActiveLeft();				/* Left */
											break;
					case 0x4d:	MoveActiveRight();			/* Right */
											break;
					default:		sound(1000);
											delay(100);
											nosound();
				}
			else
				switch (chx >> 8) {
					case 0x02:	SpecialMenu();			/* ! */
											break;
					case 0x48:	SizeActiveUp();			/* ShUp */
											break;
					case 0x50:	SizeActiveDown();		/* ShDown */
											break;
					case 0x4b:	SizeActiveLeft();		/* ShLeft */
											break;
					case 0x4d:	SizeActiveRight();	/* ShRight */
											break;
				}
		}
	}
	SaveScreen();
	kb_hidemouse();
	wn_restorescr();
	v_gotoxy(oldx, oldy);
	v_curshape(oldb, olde);

	SioDone(Port);

	return 0;
}

