From 8cfd7df26dae31d608cd3ddac012f60904077d52 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Thu, 12 Oct 2000 05:34:36 +0000
Subject: [PATCH] Upgrade from XSDK v2.42 (16-bit only) to v3.01 (16-bit and
 32-bit)

---
 xtrn/sdk/xsdk.c     | 3694 +++++++++++++++++++++++--------------------
 xtrn/sdk/xsdk.h     |   93 +-
 xtrn/sdk/xsdkdefs.h |   95 +-
 xtrn/sdk/xsdkvars.c |   41 +-
 4 files changed, 2193 insertions(+), 1730 deletions(-)

diff --git a/xtrn/sdk/xsdk.c b/xtrn/sdk/xsdk.c
index 34ebaa8abb..97f6e1d794 100644
--- a/xtrn/sdk/xsdk.c
+++ b/xtrn/sdk/xsdk.c
@@ -1,31 +1,39 @@
-/* XSDK.C */
-
-/****************************************************************************/
-/*			Synchronet External Program Software Development Kit			*/
-/*							1995 Digital Dynamics							*/
-/****************************************************************************/
-
-/****************************************************************************/
-/* This source code file is public domain and may be modified, compiled 	*/
-/* distributed, or used in any way, in part or whole for any purposes		*/
-/* without the consent or notification of Digital Dynamics. 				*/
-/*																			*/
-/* We only request that you display to the user, at some point, in your 	*/
-/* program the character "XSDK" and the version number.                     */
-/* example: bprintf("XSDK v%s",xsdk_ver);                                   */
-/****************************************************************************/
-
-/****************************************************************************/
-/* The source code for two external programs developed by Digital Dynamics	*/
-/* using XSDK (Synchronet Blackjack [SBJ] and Synchronet BBS List [SBL])	*/
-/* are available to the public domain as examples of how to implement the	*/
-/* functions and variables included in this software development kit.		*/
-/****************************************************************************/
-
-/****************************************************/
-/* For use with Borland/Turbo C and C++ compilers.	*/
-/* Tabstop set to 4.								*/
-/****************************************************/
+/* xsdk.c */
+
+/* Synchronet External Program Software Development Kit	*/
+
+/* $Id$ */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
+ *																			*
+ * This library is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU Lesser General Public License		*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
+ *																			*
+ * Anonymous FTP access to the most recent released source is available at	*
+ * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
+ *																			*
+ * Anonymous CVS access to the development source and modification history	*
+ * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
+ *     (just hit return, no password is necessary)							*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout xtrn	*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * You are encouraged to submit any modifications (preferably in Unix diff	*
+ * format) via e-mail to mods@synchro.net									*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
 
 /***************************** Revision History *****************************\
 
@@ -185,12 +193,35 @@
 				left (similar to SBBS).
 			Users are now warned of their last 5 minutes available (like SBBS).
 	2.42
+			Added Microsoft/Borland 32-bit compiler compatibility
+			Added socket (Telnet) compatibility
+			Changed Ctrl-Minus (Insert key) to Ctrl-V
+			Changed Ctrl-V (Center text key) to Ctrl-L
+			Added support for telnet nodes (connection=0xffff)
+	3.00
+			Fixed problem with clear screen (form feed) in node messages.
+			checkline() now exits when the remote user disconnects on 32-bit 
+				programs. Use atexit() to add cleanup code.
+	3.01
+			Eliminated warnings in ctrl_a() when compiled with VC++ 6.0.
 
 \****************************************************************************/
 
+#ifdef _WIN32
+#include <windows.h>	// Sleep()
+#include <process.h>	// _beginthread()
+#include <winsock.h>	// socket stuff
+WSADATA WSAData;		// WinSock data
+#endif
+
 #include "xsdk.h"
 
-char *xsdk_ver="2.42";
+char *xsdk_ver="3.01"
+#ifdef _WIN32
+	"/Win32"
+#endif
+	;
+
 
 #ifdef __TURBOC__
 extern long timezone=0L;
@@ -203,14 +234,62 @@ short wherey(void);
 void clrscr(void);
 #endif  
 
+#ifdef _MSC_VER	  /* Microsoft C */
+
+#define sopen(f,o,s,p)	   _sopen(f,o,s,p)
+#define close(f)		   _close(f)
+#define SH_DENYNO		   _SH_DENYNO
+#define SH_DENYRW		   _SH_DENYRW
+
+#include <sys/locking.h>
+
+int lock(int file, long offset, int size) 
+{
+	int	i;
+	long	pos;
+   
+	pos=tell(file);
+	if(offset!=pos)
+		lseek(file, offset, SEEK_SET);
+	i=locking(file,LK_NBLCK,size);
+	if(offset!=pos)
+		lseek(file, pos, SEEK_SET);
+	return(i);
+}
+
+int unlock(int file, long offset, int size)
+{
+	int	i;
+	long	pos;
+   
+	pos=tell(file);
+	if(offset!=pos)
+		lseek(file, offset, SEEK_SET);
+	i=locking(file,LK_UNLCK,size);
+	if(offset!=pos)
+		lseek(file, pos, SEEK_SET);
+	return(i);
+}
+
+void clrscr(void)
+{
+}
+
+#endif /* _MSC_VER */
+
+#ifndef __16BIT__	/* Sockets */
+
+SOCKET			client_socket=INVALID_SOCKET;
+
+#endif
 
 /****************************************************************************/
 /* This allows users to abort the listing of text by using Ctrl-C           */
 /****************************************************************************/
 int cbreakh(void)	/* ctrl-break handler */
 {
-aborted=1;
-return(1);		/* 1 to continue, 0 to abort */
+	aborted=1;
+	return(1);		/* 1 to continue, 0 to abort */
 }
 
 /****************************************************************************/
@@ -222,11 +301,11 @@ int bprintf(char *fmt, ...)
 	char sbuf[1024];
 	int chcount;
 
-va_start(argptr,fmt);
-chcount=vsprintf(sbuf,fmt,argptr);
-va_end(argptr);
-bputs(sbuf);
-return(chcount);
+	va_start(argptr,fmt);
+	chcount=vsprintf(sbuf,fmt,argptr);
+	va_end(argptr);
+	bputs(sbuf);
+	return(chcount);
 }
 
 /****************************************************************************/
@@ -238,11 +317,11 @@ int rprintf(char *fmt, ...)
 	char sbuf[1024];
 	int chcount;
 
-va_start(argptr,fmt);
-chcount=vsprintf(sbuf,fmt,argptr);
-va_end(argptr);
-rputs(sbuf);
-return(chcount);
+	va_start(argptr,fmt);
+	chcount=vsprintf(sbuf,fmt,argptr);
+	va_end(argptr);
+	rputs(sbuf);
+	return(chcount);
 }
 
 /****************************************************************************/
@@ -252,14 +331,14 @@ void bputs(char *str)
 {
 	ulong l=0;
 
-while(str[l] && !aborted) {
-	if(str[l]==1) {				/* ctrl-a */
-		ctrl_a(str[++l]);		/* skip the ctrl-a */
-		if(str[l]=='Z')         /* Ctrl-AZ marks premature end of file */
-			break;
-		l++; }					/* skip the attribute code */
-	else
-		outchar(str[l++]); }
+	while(str[l] && !aborted) {
+		if(str[l]==1) {				/* ctrl-a */
+			ctrl_a(str[++l]);		/* skip the ctrl-a */
+			if(str[l]=='Z')         /* Ctrl-AZ marks premature end of file */
+				break;
+			l++; }					/* skip the attribute code */
+		else
+			outchar(str[l++]); }
 }
 
 /****************************************************************************/
@@ -271,8 +350,8 @@ void rputs(char *str)
 {
 	ulong l=0;
 
-while(str[l])
-	outchar(str[l++]);
+	while(str[l])
+		outchar(str[l++]);
 }
 
 /****************************************************************************/
@@ -283,18 +362,18 @@ int bstrlen(uchar *str)
 {
 	int i=0;
 
-while(*str) {
-	if(*str<SP) {	/* ctrl char */
-		if(*str==1) /* ctrl-A */
-			str++;
-		else if(*str!=CR && *str!=LF && *str!=FF)
-			i++; }
-	else
-		i++;
-	if(!(*str))
-		break;
-	str++; }
-return(i);
+	while(*str) {
+		if(*str<SP) {	/* ctrl char */
+			if(*str==1) /* ctrl-A */
+				str++;
+			else if(*str!=CR && *str!=LF && *str!=FF)
+				i++; }
+		else
+			i++;
+		if(!(*str))
+			break;
+		str++; }
+	return(i);
 }
 
 /****************************************************************************/
@@ -305,12 +384,47 @@ void center(char *str)
 {
 	 int i,j;
 
-j=bstrlen(str);
-for(i=0;i<(80-j)/2;i++)
-	outchar(SP);
-bputs(str);
+	j=bstrlen(str);
+	for(i=0;i<(80-j)/2;i++)
+		outchar(SP);
+	bputs(str);
 }
 
+#ifndef __16BIT__
+
+char	outbuf[5000];
+ulong	outbufbot=0;
+ulong	outbuftop=0;
+HANDLE	output_event;
+
+void output_thread(void* arg)
+{
+	int		i,len;
+	char	str[256];
+
+	while(client_socket!=INVALID_SOCKET) {
+		if(outbufbot==outbuftop) {
+			ResetEvent(output_event);
+			WaitForSingleObject(output_event,10000);
+			continue; }
+
+		if(outbuftop>outbufbot)
+			len=outbuftop-outbufbot;
+		else
+			len=sizeof(outbuf)-outbufbot;
+		i=send(client_socket,outbuf+outbufbot,len,0);
+		if(i!=len) {
+			sprintf(str,"!XSDK Error %d (%d) sending on socket %d\n"
+				,i,GetLastError(),client_socket);
+			OutputDebugString(str);
+		}
+		outbufbot+=len;
+		if(outbufbot>=sizeof(outbuf))
+			outbufbot=0;
+	}
+}
+#endif
+
 /****************************************************************************/
 /* Outputs one character to the screen. Handles, pause, saving and			*/
 /* restoring lines, etc.													*/
@@ -318,31 +432,51 @@ bputs(str);
 void outchar(char ch)
 {
 
-write(fileno(con_fp),&ch,1);
+#ifndef __16BIT__
+	ulong	top=outbuftop+1;
+
+	if(top==sizeof(outbuf))
+		top=0;
+	if(top!=outbufbot) {
+		outbuf[outbuftop++]=ch;
+		if(outbuftop==sizeof(outbuf))
+			outbuftop=0;
+		SetEvent(output_event);
+	}
+
+#endif
 
-if(ch==LF) {
-	lncntr++;
-	lbuflen=0;
-	tos=0; }
-else if(ch==FF) {
-	if(lncntr>1) {
+	write(fileno(con_fp),&ch,1);
+
+	if(ch==LF) {
+		lncntr++;
+		lbuflen=0;
+		tos=0; 
+	}
+	else if(ch==FF) {
+		if(lncntr>1) {
+			lncntr=0;
+			CRLF;
+			pause(); 
+		}
 		lncntr=0;
-		CRLF;
-		pause(); }
-	lncntr=0;
-	lbuflen=0;
-	tos=1; }
-else if(ch==BS) {
-	if(lbuflen)
-		lbuflen--; }
-else {
-	if(!lbuflen)
-		latr=curatr;
-	if(lbuflen>=LINE_BUFSIZE) lbuflen=0;
-	lbuf[lbuflen++]=ch; }
-if(lncntr==user_rows-1) {
-	lncntr=0;
-    pause(); }
+		lbuflen=0;
+		tos=1; 
+	}
+	else if(ch==BS) {
+		if(lbuflen)
+			lbuflen--; 
+	}
+	else {
+		if(!lbuflen)
+			latr=curatr;
+		if(lbuflen>=LINE_BUFSIZE) lbuflen=0;
+		lbuf[lbuflen++]=ch; 
+	}
+	if(lncntr==user_rows-1) {
+		lncntr=0;
+		pause(); 
+	}
 }
 
 /****************************************************************************/
@@ -350,16 +484,19 @@ if(lncntr==user_rows-1) {
 /****************************************************************************/
 void pause(void)
 {
-	uchar tempattrs=curatr,*msg="\1_\1r\1h[Hit a key] ";
-	int i,j;
+	char	ch;
+	uchar	tempattrs=curatr,*msg="\1_\1r\1h[Hit a key] ";
+	int		i,j;
 
-lncntr=0;
-bputs(msg);
-j=bstrlen(msg);
-getkey(0);
-for(i=0;i<j;i++)
-	bputs("\b \b");
-attr(tempattrs);
+	lncntr=0;
+	bputs(msg);
+	j=bstrlen(msg);
+	ch=getkey(K_UPPER);
+	for(i=0;i<j;i++)
+		bputs("\b \b");
+	attr(tempattrs);
+	if(ch=='N' || ch=='Q')
+		aborted=1;
 }
 
 /****************************************************************************/
@@ -371,15 +508,17 @@ char yesno(char *str)
 {
 	char ch;
 
-bprintf("\1_\1b\1h%s (Y/n) ? \1w",str);
-while(1) {
-	ch=getkey(K_UPPER);
-	if(ch=='Y' || ch==CR) {
-		bputs("Yes\r\n");
-		return(1); }
-	if(ch=='N' || aborted) {
-		bputs("No\r\n");
-		return(0); } }
+	bprintf("\1_\1b\1h%s (Y/n) ? \1w",str);
+	while(1) {
+		ch=getkey(K_UPPER);
+		if(ch=='Y' || ch==CR) {
+			bputs("Yes\r\n");
+			return(1); }
+		if(ch=='N' || aborted) {
+			bputs("No\r\n");
+			return(0); 
+		} 
+	}
 }
 
 /****************************************************************************/
@@ -391,15 +530,17 @@ char noyes(char *str)
 {
 	char ch;
 
-bprintf("\1_\1b\1h%s (y/N) ? \1w",str);
-while(1) {
-	ch=getkey(K_UPPER);
-	if(ch=='N' || ch==CR || aborted) {
-		bputs("No\r\n");
-		return(1); }
-	if(ch=='Y') {
-		bputs("Yes\r\n");
-		return(0); } }
+	bprintf("\1_\1b\1h%s (y/N) ? \1w",str);
+	while(1) {
+		ch=getkey(K_UPPER);
+		if(ch=='N' || ch==CR || aborted) {
+			bputs("No\r\n");
+			return(1); }
+		if(ch=='Y') {
+			bputs("Yes\r\n");
+			return(0); 
+		} 
+	}
 }
 
 /****************************************************************************/
@@ -412,120 +553,140 @@ void mnemonics(char *str)
 {
 	long l;
 
-attr(mnelow);
-l=0L;
-while(str[l]) {
-	if(str[l]=='~' && str[l+1]) {
-		if(!(user_misc&ANSI))
-			outchar('(');
-		l++;
-		attr(mnehigh);
-		outchar(str[l]);
-		l++;
-		if(!(user_misc&ANSI))
-			outchar(')');
-		attr(mnelow); }
-	else
-		outchar(str[l++]); }
-attr(LIGHTGRAY);
+	attr(mnelow);
+	l=0L;
+	while(str[l]) {
+		if(str[l]=='~' && str[l+1]) {
+			if(!(user_misc&ANSI))
+				outchar('(');
+			l++;
+			attr(mnehigh);
+			outchar(str[l]);
+			l++;
+			if(!(user_misc&ANSI))
+				outchar(')');
+			attr(mnelow); 
+		}
+		else
+			outchar(str[l++]); 
+	}
+	attr(LIGHTGRAY);
 }
 
 /****************************************************************************/
 /* If a key has been pressed, the ASCII code is returned. If not, 0 is		*/
 /* returned. Ctrl-P and Ctrl-U are intercepted here.						*/
 /****************************************************************************/
-char inkey(int mode)
+char inkey(long mode)
 {
 	static in_ctrl_p;
 	uchar ch=0,hour,min,sec;
-	ushort tleft;
-	uint i;
+	long tleft;
+	int i=0;
 	time_t now;
 
-if(keybufbot!=keybuftop) {
-	ch=keybuf[keybufbot++];
-	if(keybufbot==KEY_BUFSIZE)
-		keybufbot=0; }
-else if(_bios_keybrd(1)) {
-	i=_bios_keybrd(0);
-	if(i&0xff)
-		ch=i&0xff;
-	else {					/* Local Alt or Function key hit */
-		i>>=8;
-		switch(i) {
-			case 0x47:	/* Home - Same as Ctrl-B */
-				return(2);	/* ctrl-b beginning of line */
-			case 0x4b:		/* Left Arrow - same as ctrl-] */
-				return(0x1d);
-			case 0x4d:		/* Right Arrow - same as ctrl-f */
-				return(6);
-			case 0x48:		/* Up arrow - same as ctrl-^ */
-				return(0x1e);
-			case 0x50:		/* Down arrow - same as CR */
-				return(CR);
-			case 0x4f:	  /* End	  - same as Ctrl-E */
-                return(5);  /* ctrl-e - end of line */
-			case 0x52:	/* Insert */
-				return(0x1f);	/* ctrl-minus - insert mode */
-			case 0x53:	/* Delete */
-                return(0x7f);   /* ctrl-bkspc - del cur char */
-			}
-		return(0); } }
+#ifndef __16BIT__
+	char	str[256];
+	ulong	cnt=0;
+
+	if(client_socket!=INVALID_SOCKET) {
+		i=ioctlsocket(client_socket,FIONREAD,&cnt);
+		if(i) {
+			sprintf(str,"!XSDK Error %d (%d) checking readcnt on socket %d\n"
+				,i,GetLastError(),client_socket);
+			OutputDebugString(str);
+		}
+	}
+
+	if(i==0 && cnt) 
+		recv(client_socket,&ch,1,0);
+	else
+#endif
 
-if(ch==0x10 || ch==0x1e) {	/* Ctrl-P or Ctrl-^ */
-	if(in_ctrl_p || !ctrl_dir[0])	/* keep from being recursive */
-		return(0);
-	in_ctrl_p=1;
-	SAVELINE;
-	CRLF;
-	nodemsg();
-	CRLF;
-	RESTORELINE;
-	lncntr=0;
-	in_ctrl_p=0;
-	return(0); }
+	if(keybufbot!=keybuftop) {
+		ch=keybuf[keybufbot++];
+		if(keybufbot==KEY_BUFSIZE)
+			keybufbot=0; }
+	else if(kbhit()) {
+		i=getch();
+		if(i==0 || i==0xE0) {			/* Local Alt or Function key hit */
+			i=getch();
+			switch(i) {
+				case 0x47:	/* Home - Same as Ctrl-B */
+					return(2);	/* ctrl-b beginning of line */
+				case 0x4b:		/* Left Arrow - same as ctrl-] */
+					return(0x1d);
+				case 0x4d:		/* Right Arrow - same as ctrl-f */
+					return(6);
+				case 0x48:		/* Up arrow - same as ctrl-^ */
+					return(0x1e);
+				case 0x50:		/* Down arrow - same as CR */
+					return(CR);
+				case 0x4f:	  /* End	  - same as Ctrl-E */
+					return(5);  /* ctrl-e - end of line */
+				case 0x52:	/* Insert */
+					return(0x1f);	/* ctrl-minus - insert mode */
+				case 0x53:	/* Delete */
+					return(0x7f);   /* ctrl-bkspc - del cur char */
+				}
+			return(0); } 
+		ch=i;
+	}
+
+	if(ch==0x10 || ch==0x1e) {	/* Ctrl-P or Ctrl-^ */
+		if(in_ctrl_p || !ctrl_dir[0])	/* keep from being recursive */
+			return(0);
+		in_ctrl_p=1;
+		SAVELINE;
+		CRLF;
+		nodemsg();
+		CRLF;
+		RESTORELINE;
+		lncntr=0;
+		in_ctrl_p=0;
+		return(0); }
 
-if(ch==20) { /* Ctrl-T Time left online */
-	SAVELINE;
-	attr(LIGHTGRAY);
-	now=time(NULL);
-	checktimeleft();
-	CRLF;
-	bprintf("\r\nStart     : %.24s",ctime(&starttime));
-	bprintf("\r\nNow       : %.24s",ctime(&now));
-	i=now-starttime;
-	hour=(i/60)/60;
-	min=(i/60)-(hour*60);
-	sec=i-((min+(hour*60))*60);
-	bprintf("\r\nTime Used : %02u:%02u:%02u",hour,min,sec);
-	tleft=timeleft-(now-starttime);
-	hour=(tleft/60)/60;
-	min=(tleft/60)-(hour*60);
-	sec=tleft-((min+(hour*60))*60);
-	bprintf("\r\nTime Left : %02u:%02u:%02u\r\n\r\n",hour,min,sec);
-	RESTORELINE;
-	lncntr=0;
-	return(0); }
+	if(ch==20) { /* Ctrl-T Time left online */
+		SAVELINE;
+		attr(LIGHTGRAY);
+		now=time(NULL);
+		checktimeleft();
+		CRLF;
+		bprintf("\r\nStart     : %.24s",ctime(&starttime));
+		bprintf("\r\nNow       : %.24s",ctime(&now));
+		i=now-starttime;
+		hour=(i/60)/60;
+		min=(i/60)-(hour*60);
+		sec=i-((min+(hour*60))*60);
+		bprintf("\r\nTime Used : %02u:%02u:%02u",hour,min,sec);
+		tleft=timeleft-(now-starttime);
+		hour=(tleft/60)/60;
+		min=(tleft/60)-(hour*60);
+		sec=tleft-((min+(hour*60))*60);
+		bprintf("\r\nTime Left : %02u:%02u:%02u\r\n\r\n",hour,min,sec);
+		RESTORELINE;
+		lncntr=0;
+		return(0); }
 
-if(ch==21) { /* Ctrl-U Users online */
-	if(!ctrl_dir[0])
-		return(0);
-	SAVELINE;
-	CRLF;
-	whos_online(1);
-	CRLF;
-	RESTORELINE;
-	lncntr=0;
-    return(0); }
+	if(ch==21) { /* Ctrl-U Users online */
+		if(!ctrl_dir[0])
+			return(0);
+		SAVELINE;
+		CRLF;
+		whos_online(1);
+		CRLF;
+		RESTORELINE;
+		lncntr=0;
+		return(0); }
 
-if(ch==3)
-	aborted=1;
-else if(aborted)
-	ch=3;
+	if(ch==3)
+		aborted=1;
+	else if(aborted)
+		ch=3;
 
-if(!ch && (!(mode&K_GETSTR) || mode&K_LOWPRIO|| node_misc&NM_LOWPRIO))
-	mswait(0);
-return(ch);
+	if(!ch && (!(mode&K_GETSTR) || mode&K_LOWPRIO|| node_misc&NM_LOWPRIO))
+		mswait(1);
+	return(ch);
 }
 
 /****************************************************************************/
@@ -533,45 +694,48 @@ return(ch);
 /* and hangs up if inactive for 4 minutes. Returns key hit, or uppercase of */
 /* key hit if mode&K_UPPER or key out of KEY BUFFER. Does not print key.	*/
 /****************************************************************************/
-char getkey(int mode)
+char getkey(long mode)
 {
-	char ch,warn=0;
-	ushort tleft;
-	time_t timeout,now;
-
-aborted=lncntr=0;
-timeout=time(NULL);
-do {
-	checkline();
-	ch=inkey(mode);
-	now=time(NULL);
-	if(ch) {
-		if(mode&K_NUMBER && isprint(ch) && !isdigit(ch))
-			continue;
-		if(mode&K_ALPHA && isprint(ch) && !isalpha(ch))
-			continue;
-		if(ch==LF) continue;
-		if(mode&K_UPPER)
-			return(toupper(ch));
-		return(ch); }
-	checktimeleft();
-
-	tleft=timeleft-(now-starttime);
-	if((tleft/60)<(5-timeleft_warn)) {	/* Running out of time warning */
-		timeleft_warn=5-(tleft/60);
-        SAVELINE;
-		bprintf("nh\r\n\7\r\nYou only have ri%unh minute%s "
-			"left.\r\n\r\n"
-			,((ushort)tleft/60)+1,(tleft/60) ? "s" : "");
-        RESTORELINE; }
-
-	if(now-timeout>=sec_warn && !warn)		/* Inactivity warning */
-		for(warn=0;warn<5;warn++)
-			outchar(7);
-	} while(now-timeout<sec_timeout);
-bputs("\r\nInactive too long.\r\n");
-exit(0);
-return(0);	/* never gets here, but makes compiler happy */
+	char	ch,warn=0;
+	long	tleft;
+	time_t	timeout,now;
+
+	aborted=lncntr=0;
+	timeout=time(NULL);
+	do {
+		checkline();
+		ch=inkey(mode);
+		now=time(NULL);
+		if(ch) {
+			if(mode&K_NUMBER && isprint(ch) && !isdigit(ch))
+				continue;
+			if(mode&K_ALPHA && isprint(ch) && !isalpha(ch))
+				continue;
+			if(ch==LF) continue;
+			if(mode&K_UPPER)
+				return(toupper(ch));
+			return(ch); 
+		}
+		checktimeleft();
+
+		tleft=timeleft-(now-starttime);
+		if((tleft/60)<(5-timeleft_warn)) {	/* Running out of time warning */
+			timeleft_warn=5-(tleft/60);
+			SAVELINE;
+			bprintf("\1n\1h\r\n\7\r\nYou only have \1r\1i%u\1n\1h minute%s "
+				"left.\r\n\r\n"
+				,((ushort)tleft/60)+1,(tleft/60) ? "s" : "");
+			RESTORELINE; 
+		}
+
+		if(now-timeout>=(time_t)sec_warn && !warn)		/* Inactivity warning */
+			for(warn=0;warn<5;warn++)
+				outchar(7);
+	} while(now-timeout<(time_t)sec_timeout);
+
+	bputs("\r\nInactive too long.\r\n");
+	exit(0);
+	return(0);	/* never gets here, but makes compiler happy */
 }
 
 /****************************************************************************/
@@ -579,7 +743,29 @@ return(0);	/* never gets here, but makes compiler happy */
 /****************************************************************************/
 void checkline(void)
 {
+#ifdef __16BIT__
 if(com_port && !((*msr)&DCD)) exit(0);
+#else
+	char	str[256];
+	char	ch;
+	int		i;
+	fd_set	socket_set;
+	struct timeval timeout;
+
+	FD_ZERO(&socket_set);
+	FD_SET(client_socket,&socket_set);
+	timeout.tv_sec=0;
+	timeout.tv_usec=100;
+
+	if((i=select(0,&socket_set,NULL,NULL,&timeout))>0) {
+		if((i=recv(client_socket,&ch,1,MSG_PEEK))!=1) {
+			sprintf(str,"!XSDK Error %d (%d) checking state of socket %d\n"
+				,i,GetLastError(),client_socket);
+			OutputDebugString(str);
+			exit(0);
+		}
+	}
+#endif
 }
 
 /****************************************************************************/
@@ -595,36 +781,42 @@ int getkeys(char *str,int max)
 	uchar ch,n=0;
 	int i=0;
 
-strupr(str);
-while(!aborted) {
-	ch=getkey(K_UPPER);
-	if(max && ch>0x7f)	/* extended ascii chars are digits to isdigit() */
-		continue;
-	if(ch && !n && (strchr(str,ch))) { 	/* return character if in string */
-		outchar(ch);
-		attr(LIGHTGRAY);
-		CRLF;
-		return(ch); }
-	if(ch==CR && max) {             /* return 0 if no number */
-		attr(LIGHTGRAY);
-		CRLF;
-		if(n)
-			return(i|0x8000);		/* return number plus high bit */
-		return(0); }
-	if(ch==BS && n) {
-		bputs("\b \b");
-		i/=10;
-		n--; }
-	else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
-		i*=10;
-		n++;
-		i+=ch&0xf;
-		outchar(ch);
-		if(i*10>max) {
+	strupr(str);
+	while(!aborted) {
+		ch=getkey(K_UPPER);
+		if(max && ch>0x7f)	/* extended ascii chars are digits to isdigit() */
+			continue;
+		if(ch && !n && (strchr(str,ch))) { 	/* return character if in string */
+			outchar(ch);
+			attr(LIGHTGRAY);
+			CRLF;
+			return(ch); 
+		}
+		if(ch==CR && max) {             /* return 0 if no number */
 			attr(LIGHTGRAY);
 			CRLF;
-			return(i|0x8000); } } }
-return(0);
+			if(n)
+				return(i|0x8000);		/* return number plus high bit */
+			return(0); 
+		}
+		if(ch==BS && n) {
+			bputs("\b \b");
+			i/=10;
+			n--; 
+		}
+		else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
+			i*=10;
+			n++;
+			i+=ch&0xf;
+			outchar(ch);
+			if(i*10>max) {
+				attr(LIGHTGRAY);
+				CRLF;
+				return(i|0x8000); 
+			} 
+		}	 
+	}
+	return(0);
 }
 
 /****************************************************************************/
@@ -635,33 +827,40 @@ int getnum(int max)
 	uchar ch,n=0;
 	int i=0;
 
-while(1) {
-	ch=getkey(K_UPPER);
-	if(ch>0x7f)
-		continue;
-	if(ch=='Q') {
-		outchar('Q');
-		CRLF;
-		return(-1); }
-	else if(ch==3) {		/* ctrl-c */
-		CRLF;
-		return(-1); }
-	else if(ch==CR) {
-		CRLF;
-		return(i); }
-	else if(ch==BS && n) {
-		bputs("\b \b");
-		i/=10;
-		n--; }
-	else if(isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
-		i*=10;
-		n++;
-		i+=ch&0xf;
-		outchar(ch);
-		if(i*10>max) {
+	while(1) {
+		ch=getkey(K_UPPER);
+		if(ch>0x7f)
+			continue;
+		if(ch=='Q') {
+			outchar('Q');
+			CRLF;
+			break;
+		}
+		else if(ch==3) {		/* ctrl-c */
 			CRLF;
-			return(i); } } }
-return(-1);
+			break;
+		}
+		else if(ch==CR) {
+			CRLF;
+			return(i);
+		}
+		else if(ch==BS && n) {
+			bputs("\b \b");
+			i/=10;
+			n--;
+		}
+		else if(isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) {
+			i*=10;
+			n++;
+			i+=ch&0xf;
+			outchar(ch);
+			if(i*10>max) {
+				CRLF;
+				return(i);
+			}
+		}
+	}
+	return(-1);
 }
 
 /****************************************************************************/
@@ -672,387 +871,450 @@ return(-1);
 /* a word, ^X backspaces a line, ^Gs, BSs, TABs are processed, LFs ignored. */
 /* ^N non-destructive BS, ^V center line. Valid keys are echoed.			*/
 /****************************************************************************/
-int getstr(char *strout, int maxlen, int mode)
+int getstr(char *strout, size_t maxlen, long mode)
 {
-	int i,l,x,z;	/* i=current position, l=length, j=printed chars */
+	size_t i,l,x,z;	/* i=current position, l=length, j=printed chars */
 					/* x&z=misc */
 	uchar ch,str1[256],str2[256],ins=0,atr;
 
-if(mode&K_LINE && user_misc&ANSI) {
-	attr(LIGHTGRAY|HIGH|(BLUE<<4));  /* white on blue */
-	for(i=0;i<maxlen;i++)
-		outchar(SP);
-	bprintf("\x1b[%dD",maxlen); }
-i=l=0;	/* i=total number of chars, j=number of printable chars */
-if(wordwrap[0]) {
-	strcpy(str1,wordwrap);
-	wordwrap[0]=0; }
-else str1[0]=0;
-if(mode&K_EDIT)
-	strcat(str1,strout);
-if(strlen(str1)>maxlen)
-	str1[maxlen]=0;
-atr=curatr;
-if(mode&K_AUTODEL && str1[0])
-	attr(BLUE|(LIGHTGRAY<<4));
-rputs(str1);
-if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && user_misc&ANSI)
-	bputs("\x1b[K");  /* destroy to eol */
-i=l=strlen(str1);
-
-if(mode&K_AUTODEL && str1[0]) {
-	ch=getkey(mode);
-    attr(atr);
-    if(isprint(ch) || ch==0x7f) {
-        for(i=0;i<l;i++)
-            bputs("\b \b");
-        i=l=0; }
-    else {
-        for(i=0;i<l;i++)
-            outchar(BS);
-        rputs(str1);
-        i=l; }
-	if(ch!=SP && ch!=TAB)
-        ungetkey(ch); }
-
-while((ch=getkey(mode|K_GETSTR))!=CR && !aborted) {
-	switch(ch) {
-		case 1:	/* Ctrl-A for ANSI */
-			if(!(mode&K_MSG) || i>maxlen-3)
-				break;
-            if(ins) {
-				if(l<maxlen)
-                    l++;
-				for(x=l;x>i;x--)
-					str1[x]=str1[x-1];
-				rprintf("%.*s",l-i,str1+i);
-				rprintf("\x1b[%dD",l-i);
-				if(i==maxlen-1)
-					ins=0; }
-			outchar(str1[i++]=1);
-			break;
-		case 2:	/* Ctrl-B Beginning of Line */
-			if(user_misc&ANSI && i) {
-				bprintf("\x1b[%dD",i);
-				i=0; }
-			break;
-		case 4:	/* Ctrl-D Delete word right */
-        	if(i<l) {
-				x=i;
-				while(x<l && str1[x]!=SP) {
-					outchar(SP);
-					x++; }
-				while(x<l && str1[x]==SP) {
-					outchar(SP);
-					x++; }
-				bprintf("\x1b[%dD",x-i);   /* move cursor back */
-				z=i;
-				while(z<l-(x-i))  {             /* move chars in string */
-					outchar(str1[z]=str1[z+(x-i)]);
-					z++; }
-				while(z<l) {					/* write over extra chars */
-					outchar(SP);
-					z++; }
-				bprintf("\x1b[%dD",z-i);
-				l-=x-i; }						/* l=new length */
-			break;
-		case 5:	/* Ctrl-E End of line */
-			if(user_misc&ANSI && i<l) {
-				bprintf("\x1b[%dC",l-i);  /* move cursor right one */
-				i=l; }
-			break;
-		case 6:	/* Ctrl-F move cursor forewards */
-			if(i<l && (user_misc&ANSI)) {
-				bputs("\x1b[C");   /* move cursor right one */
-				i++; }
-			break;
-		case 7:
-			if(!(mode&K_MSG))
-				break;
-             if(ins) {
-				if(l<maxlen)
-                    l++;
-				for(x=l;x>i;x--)
-					str1[x]=str1[x-1];
-				if(i==maxlen-1)
-					ins=0; }
-			 if(i<maxlen) {
-				str1[i++]=7;
-				outchar(7); }
-			 break;
-		case 14:	/* Ctrl-N Next word */
-			if(i<l && (user_misc&ANSI)) {
-				x=i;
-				while(str1[i]!=SP && i<l)
-					i++;
-				while(str1[i]==SP && i<l)
-					i++;
-				bprintf("\x1b[%dC",i-x); }
-			break;
-		case 0x1c:	  /* Ctrl-\ Previous word */
-			if(i && (user_misc&ANSI)) {
-				x=i;
-				while(str1[i-1]==SP && i)
-					i--;
-				while(str1[i-1]!=SP && i)
-					i--;
-				bprintf("\x1b[%dD",x-i); }
-			break;
-		case 18:	/* Ctrl-R Redraw Line */
-            redrwstr(str1,i,l,0);
-            break;
-		case TAB:
-			if(!(i%TABSIZE)) {
-            	if(ins) {
+	if(mode&K_LINE && user_misc&ANSI) {
+		attr(LIGHTGRAY|HIGH|(BLUE<<4));  /* white on blue */
+		for(i=0;i<maxlen;i++)
+			outchar(SP);
+		bprintf("\x1b[%dD",maxlen); 
+	}
+	i=l=0;	/* i=total number of chars, j=number of printable chars */
+	if(wordwrap[0]) {
+		strcpy(str1,wordwrap);
+		wordwrap[0]=0; 
+	}
+	else str1[0]=0;
+	if(mode&K_EDIT)
+		strcat(str1,strout);
+	if(strlen(str1)>maxlen)
+		str1[maxlen]=0;
+	atr=curatr;
+	if(mode&K_AUTODEL && str1[0])
+		attr(BLUE|(LIGHTGRAY<<4));
+	rputs(str1);
+	if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && user_misc&ANSI)
+		bputs("\x1b[K");  /* destroy to eol */
+	i=l=strlen(str1);
+
+	if(mode&K_AUTODEL && str1[0]) {
+		ch=getkey(mode);
+		attr(atr);
+		if(isprint(ch) || ch==0x7f) {
+			for(i=0;i<l;i++)
+				bputs("\b \b");
+			i=l=0; 
+		}
+		else {
+			for(i=0;i<l;i++)
+				outchar(BS);
+			rputs(str1);
+			i=l; 
+		}
+		if(ch!=SP && ch!=TAB)
+			ungetkey(ch); 
+	}
+
+	while((ch=getkey(mode|K_GETSTR))!=CR && !aborted) {
+		switch(ch) {
+			case 1:	/* Ctrl-A for ANSI */
+				if(!(mode&K_MSG) || i>maxlen-3)
+					break;
+				if(ins) {
 					if(l<maxlen)
-                        l++;
+						l++;
 					for(x=l;x>i;x--)
 						str1[x]=str1[x-1];
+					rprintf("%.*s",l-i,str1+i);
+					rprintf("\x1b[%dD",l-i);
 					if(i==maxlen-1)
-						ins=0; }
-				str1[i++]=SP;
-				outchar(SP); }
-			while(i<maxlen && i%TABSIZE) {
-            	if(ins) {
+						ins=0; 
+				}
+				outchar(str1[i++]=1);
+				break;
+			case 2:	/* Ctrl-B Beginning of Line */
+				if(user_misc&ANSI && i) {
+					bprintf("\x1b[%dD",i);
+					i=0; 
+				}
+				break;
+			case 4:	/* Ctrl-D Delete word right */
+        		if(i<l) {
+					x=i;
+					while(x<l && str1[x]!=SP) {
+						outchar(SP);
+						x++; 
+					}
+					while(x<l && str1[x]==SP) {
+						outchar(SP);
+						x++; 
+					}
+					bprintf("\x1b[%dD",x-i);   /* move cursor back */
+					z=i;
+					while(z<l-(x-i))  {             /* move chars in string */
+						outchar(str1[z]=str1[z+(x-i)]);
+						z++; 
+					}
+					while(z<l) {					/* write over extra chars */
+						outchar(SP);
+						z++; 
+					}
+					bprintf("\x1b[%dD",z-i);
+					l-=x-i; 						/* l=new length */
+				}
+				break;
+			case 5:	/* Ctrl-E End of line */
+				if(user_misc&ANSI && i<l) {
+					bprintf("\x1b[%dC",l-i);  /* move cursor right one */
+					i=l; 
+				}
+				break;
+			case 6:	/* Ctrl-F move cursor forewards */
+				if(i<l && (user_misc&ANSI)) {
+					bputs("\x1b[C");   /* move cursor right one */
+					i++; 
+				}
+				break;
+			case 7:
+				if(!(mode&K_MSG))
+					break;
+				 if(ins) {
 					if(l<maxlen)
-                        l++;
+						l++;
 					for(x=l;x>i;x--)
 						str1[x]=str1[x-1];
 					if(i==maxlen-1)
-						ins=0; }
-				str1[i++]=SP;
-				outchar(SP); }
-			if(ins)
+						ins=0; 
+				 }
+				 if(i<maxlen) {
+					str1[i++]=7;
+					outchar(7); 
+				 }
+				 break;
+			case 14:	/* Ctrl-N Next word */
+				if(i<l && (user_misc&ANSI)) {
+					x=i;
+					while(str1[i]!=SP && i<l)
+						i++;
+					while(str1[i]==SP && i<l)
+						i++;
+					bprintf("\x1b[%dC",i-x); 
+				}
+				break;
+			case 0x1c:	  /* Ctrl-\ Previous word */
+				if(i && (user_misc&ANSI)) {
+					x=i;
+					while(str1[i-1]==SP && i)
+						i--;
+					while(str1[i-1]!=SP && i)
+						i--;
+					bprintf("\x1b[%dD",x-i); 
+				}
+				break;
+			case 18:	/* Ctrl-R Redraw Line */
 				redrwstr(str1,i,l,0);
-			break;
-		case BS:
-			if(!i)
 				break;
-			i--;
-			l--;
-			if(i!=l) {				/* Deleting char in middle of line */
-				outchar(BS);
-				z=i;
-				while(z<l)	{		/* move the characters in the line */
-					outchar(str1[z]=str1[z+1]);
-					z++; }
-				outchar(SP);		/* write over the last char */
-				bprintf("\x1b[%dD",(l-i)+1); }
-			else
-				bputs("\b \b");
-			break;
-		case 22:	/* Ctrl-V 	Center line */
-			str1[l]=0;
-			l=bstrlen(str1);
-			for(x=0;x<(maxlen-l)/2;x++)
-				str2[x]=SP;
-			str2[x]=0;
-			strcat(str2,str1);
-			strcpy(strout,str2);
-			l=strlen(strout);
-			if(mode&K_MSG)
-				redrwstr(strout,i,l,K_MSG);
-			else {
-				while(i--)
-					bputs("\b");
-				bputs(strout);
-				if(mode&K_LINE)
-					attr(LIGHTGRAY); }
-			CRLF;
-			return(l);
-		case 23:	/* Ctrl-W   Delete word left */
-			if(i<l) {
-				x=i;							/* x=original offset */
-				while(i && str1[i-1]==SP) {
-					outchar(BS);
-					i--; }
-				while(i && str1[i-1]!=SP) {
+			case TAB:
+				if(!(i%TABSIZE)) {
+            		if(ins) {
+						if(l<maxlen)
+							l++;
+						for(x=l;x>i;x--)
+							str1[x]=str1[x-1];
+						if(i==maxlen-1)
+							ins=0; 
+					}
+					str1[i++]=SP;
+					outchar(SP); 
+				}
+				while(i<maxlen && i%TABSIZE) {
+            		if(ins) {
+						if(l<maxlen)
+							l++;
+						for(x=l;x>i;x--)
+							str1[x]=str1[x-1];
+						if(i==maxlen-1)
+							ins=0; 
+					}
+					str1[i++]=SP;
+					outchar(SP); 
+				}
+				if(ins)
+					redrwstr(str1,i,l,0);
+				break;
+			case BS:
+				if(!i)
+					break;
+				i--;
+				l--;
+				if(i!=l) {				/* Deleting char in middle of line */
 					outchar(BS);
-					i--; }
-				z=i;                            /* i=z=new offset */
-				while(z<l-(x-i))  {             /* move chars in string */
-					outchar(str1[z]=str1[z+(x-i)]);
-					z++; }
-				while(z<l) {					/* write over extra chars */
+					z=i;
+					while(z<l)	{		/* move the characters in the line */
+						outchar(str1[z]=str1[z+1]);
+						z++; 
+					}
+					outchar(SP);		/* write over the last char */
+					bprintf("\x1b[%dD",(l-i)+1); 
+				}
+				else
+					bputs("\b \b");
+				break;
+			case 12:	/* Ctrl-L 	Center line (used to be Ctrl-V) */
+				str1[l]=0;
+				l=bstrlen(str1);
+				for(x=0;x<(maxlen-l)/2;x++)
+					str2[x]=SP;
+				str2[x]=0;
+				strcat(str2,str1);
+				strcpy(strout,str2);
+				l=strlen(strout);
+				if(mode&K_MSG)
+					redrwstr(strout,i,l,K_MSG);
+				else {
+					while(i--)
+						bputs("\b");
+					bputs(strout);
+					if(mode&K_LINE)
+						attr(LIGHTGRAY); 
+				}
+				CRLF;
+				return(l);
+			case 23:	/* Ctrl-W   Delete word left */
+				if(i<l) {
+					x=i;							/* x=original offset */
+					while(i && str1[i-1]==SP) {
+						outchar(BS);
+						i--; 
+					}
+					while(i && str1[i-1]!=SP) {
+						outchar(BS);
+						i--; 
+					}
+					z=i;                            /* i=z=new offset */
+					while(z<l-(x-i))  {             /* move chars in string */
+						outchar(str1[z]=str1[z+(x-i)]);
+						z++; 
+					}
+					while(z<l) {					/* write over extra chars */
+						outchar(SP);
+						z++; 
+					}
+					bprintf("\x1b[%dD",z-i);        /* back to new x corridnant */
+					l-=x-i; 						/* l=new length */
+				}
+				else {
+            		while(i && str1[i-1]==SP) {
+						i--;
+						l--;
+						bputs("\b \b"); 
+					}
+					while(i && str1[i-1]!=SP) {
+						i--;
+						l--;
+						bputs("\b \b"); 
+					} 
+				}
+				break;
+			case 24:	/* Ctrl-X   Delete entire line */
+				while(i<l) {
 					outchar(SP);
-					z++; }
-				bprintf("\x1b[%dD",z-i);        /* back to new x corridnant */
-				l-=x-i; }						/* l=new length */
-			else {
-            	while(i && str1[i-1]==SP) {
-					i--;
-					l--;
-					bputs("\b \b"); }
-                while(i && str1[i-1]!=SP) {
-					i--;
+					i++; 
+				}
+				while(l) {
 					l--;
-					bputs("\b \b"); } }
-			break;
-		case 24:	/* Ctrl-X   Delete entire line */
-			while(i<l) {
-				outchar(SP);
-				i++; }
-			while(l) {
-				l--;
-				bputs("\b \b"); }
-			i=0;
-			break;
-		case 25:	/* Ctrl-Y	Delete to end of line */
-			if(user_misc&ANSI) {
-				bputs("\x1b[s\x1b[K\x1b[u");
-				l=i; }
-			break;
-		case 31:	/* Ctrl-Minus		Toggles Insert/Overwrite */
-			if(!(user_misc&ANSI))
+					bputs("\b \b"); 
+				}
+				i=0;
 				break;
-			if(ins) {
-				ins=0;
-				redrwstr(str1,i,l,0); }
-			else if(i<l) {
-				ins=1;
-				bprintf("\x1b[s\x1b[%dC",80-i);         /* save pos  */
-				z=curatr;								/* and got to EOL */
-                attr(z|BLINK|HIGH);
-				outchar('°');
-				attr(z);
-				bputs("\x1b[u"); }  /* restore pos */
-			break;
-		case 0x1d:	/* Ctrl-]  Reverse Cursor Movement */
-			if(i && (user_misc&ANSI)) {
-				bputs("\x1b[D");   /* move cursor left one */
-				i--; }
-			break;
-		case 0x7f:	/* Ctrl-BkSpc (DEL) Delete current char */
-			if(i==l)
+			case 25:	/* Ctrl-Y	Delete to end of line */
+				if(user_misc&ANSI) {
+					bputs("\x1b[s\x1b[K\x1b[u");
+					l=i; 
+				}
 				break;
-			l--;
-			z=i;
-			while(z<l)	{		/* move the characters in the line */
-				outchar(str1[z]=str1[z+1]);
-				z++; }
-			outchar(SP);		/* write over the last char */
-			bprintf("\x1b[%dD",(l-i)+1);
-            break;
-		case ESC:
-			if(!(user_misc&ANSI))
+			case 22:	/* Ctrl-V		Toggles Insert/Overwrite */
+				if(!(user_misc&ANSI))
+					break;
+				if(ins) {
+					ins=0;
+					redrwstr(str1,i,l,0); 
+				}
+				else if(i<l) {
+					ins=1;
+					bprintf("\x1b[s\x1b[%dC",80-i);         /* save pos  */
+					z=curatr;								/* and got to EOL */
+					attr(z|BLINK|HIGH);
+					outchar('°');
+					attr(z);
+					bputs("\x1b[u");   /* restore pos */
+				}
 				break;
-			if((ch=getkey(0x8000))!='[') {
-				ungetch(ch);
-				break; }
-			if((ch=getkey(0x8000))=='C') {
-				if(i<l) {
-					bputs("\x1b[C");   /* move cursor right one */
-					i++; } }
-			else if(ch=='D') {
-				if(i) {
+			case 0x1d:	/* Ctrl-]  Reverse Cursor Movement */
+				if(i && (user_misc&ANSI)) {
 					bputs("\x1b[D");   /* move cursor left one */
-					i--; } }
-			else {
-				while(isdigit(ch) || ch==';' || isalpha(ch)) {
-					if(isalpha(ch)) {
-						ch=getkey(0);
-						break; }
-					ch=getkey(0); }
-				ungetch(ch); }
-			break;
-		default:
-			if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) {
-				str1[i]=0;
-				if(ch==SP) {	/* don't wrap a space as last char */
-					strcpy(strout,str1);
-					if(stripattr(strout))
-						redrwstr(strout,i,l,K_MSG);
-					CRLF;
-					return(i); }
-				x=i-1;
-				z=1;
-				wordwrap[0]=ch;
-				while(str1[x]!=SP && x)
-					wordwrap[z++]=str1[x--];
-				if(x<(maxlen/2)) {
-					wordwrap[1]=0;	/* only wrap one character */
+					i--; 
+				}
+				break;
+			case 0x7f:	/* Ctrl-BkSpc (DEL) Delete current char */
+				if(i==l)
+					break;
+				l--;
+				z=i;
+				while(z<l)	{		/* move the characters in the line */
+					outchar(str1[z]=str1[z+1]);
+					z++; 
+				}
+				outchar(SP);		/* write over the last char */
+				bprintf("\x1b[%dD",(l-i)+1);
+				break;
+			case ESC:
+				if(!(user_misc&ANSI))
+					break;
+				if((ch=getkey(0x8000))!='[') {
+					ungetch(ch);
+					break; 
+				}
+				if((ch=getkey(0x8000))=='C') {
+					if(i<l) {
+						bputs("\x1b[C");   /* move cursor right one */
+						i++; 
+					} 
+				}
+				else if(ch=='D') {
+					if(i) {
+						bputs("\x1b[D");   /* move cursor left one */
+						i--; 
+					} 
+				}
+				else {
+					while(isdigit(ch) || ch==';' || isalpha(ch)) {
+						if(isalpha(ch)) {
+							ch=getkey(0);
+							break; 
+						}
+						ch=getkey(0); 
+					}
+					ungetch(ch); 
+				}
+				break;
+			default:
+				if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) {
+					str1[i]=0;
+					if(ch==SP) {	/* don't wrap a space as last char */
+						strcpy(strout,str1);
+						if(stripattr(strout))
+							redrwstr(strout,i,l,K_MSG);
+						CRLF;
+						return(i); 
+					}
+					x=i-1;
+					z=1;
+					wordwrap[0]=ch;
+					while(str1[x]!=SP && x)
+						wordwrap[z++]=str1[x--];
+					if(x<(maxlen/2)) {
+						wordwrap[1]=0;	/* only wrap one character */
+						strcpy(strout,str1);
+						if(stripattr(strout))
+							redrwstr(strout,i,l,K_MSG);
+						CRLF;
+						return(i); 
+					}
+					wordwrap[z]=0;
+					while(z--) {
+						i--;
+						bputs("\b \b"); 
+					}
+					strrev(wordwrap);
+					str1[x]=0;
 					strcpy(strout,str1);
 					if(stripattr(strout))
-						redrwstr(strout,i,l,K_MSG);
+						redrwstr(strout,i,x,mode);
 					CRLF;
-					return(i); }
-				wordwrap[z]=0;
-				while(z--) {
-					i--;
-					bputs("\b \b"); }
-				strrev(wordwrap);
-				str1[x]=0;
-				strcpy(strout,str1);
-				if(stripattr(strout))
-					redrwstr(strout,i,x,mode);
-				CRLF;
-				return(x); }
-			if(i<maxlen && ch>=SP) {
-				if(mode&K_UPRLWR)
-					if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-'
-						|| str1[i-1]=='.' || str1[i-1]=='_')))
-						ch=toupper(ch);
-					else
-						ch=tolower(ch);
-				if(ins) {
-					if(l<maxlen)	/* l<maxlen */
-                        l++;
-					for(x=l;x>i;x--)
-						str1[x]=str1[x-1];
-					rprintf("%.*s",l-i,str1+i);
-					rprintf("\x1b[%dD",l-i);
-					if(i==maxlen-1) {
-						bputs("  \b\b");
-						ins=0; } }
-				str1[i++]=ch;
-				outchar(ch); } }
-    if(i>l)
+					return(x); 
+				}
+				if(i<maxlen && ch>=SP) {
+					if(mode&K_UPRLWR)
+						if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-'
+							|| str1[i-1]=='.' || str1[i-1]=='_')))
+							ch=toupper(ch);
+						else
+							ch=tolower(ch);
+					if(ins) {
+						if(l<maxlen)	/* l<maxlen */
+							l++;
+						for(x=l;x>i;x--)
+							str1[x]=str1[x-1];
+						rprintf("%.*s",l-i,str1+i);
+						rprintf("\x1b[%dD",l-i);
+						if(i==maxlen-1) {
+							bputs("  \b\b");
+							ins=0; 
+						} 
+					}
+					str1[i++]=ch;
+					outchar(ch); 
+				} 
+			} /* switch */
+		if(i>l)
+			l=i;
+		if(mode&K_CHAT && !l)
+			return(0); 
+	}
+	if(i>l)
 		l=i;
-	if(mode&K_CHAT && !l)
-		return(0); }
-if(i>l)
-	l=i;
-str1[l]=0;
-if(!aborted) {
-    strcpy(strout,str1);
-    if(stripattr(strout) || ins)
-        redrwstr(strout,i,l,K_MSG); }
-else
-    l=0;
-if(mode&K_LINE) attr(LIGHTGRAY);
-if(!(mode&K_NOCRLF)) {
-	outchar(CR);
-	if(!(mode&K_MSG && aborted))
-		outchar(LF); }
-return(l);
+	str1[l]=0;
+	if(!aborted) {
+		strcpy(strout,str1);
+		if(stripattr(strout) || ins)
+			redrwstr(strout,i,l,K_MSG); 
+	}
+	else
+		l=0;
+	if(mode&K_LINE) attr(LIGHTGRAY);
+	if(!(mode&K_NOCRLF)) {
+		outchar(CR);
+		if(!(mode&K_MSG && aborted))
+			outchar(LF); 
+	}
+	return(l);
 }
 
 /****************************************************************************/
 /* Redraws str using i as current cursor position and l as length           */
 /****************************************************************************/
-void redrwstr(char *strin, int i, int l, char mode)
+void redrwstr(char *strin, int i, int l, long mode)
 {
 	char str[256],c;
 
-sprintf(str,"%-*.*s",l,l,strin);
-c=i;
-while(c--)
-	outchar(BS);
-if(mode&K_MSG)
-	bputs(str);
-else
-	rputs(str);
-if(user_misc&ANSI) {
-	bputs("\x1b[K");
-	if(i<l)
-		bprintf("\x1b[%dD",l-i); }
-else {
-	while(c<79)	{ /* clear to end of line */
-		outchar(SP);
-		c++; }
-	while(c>l) { /* back space to end of string */
+	sprintf(str,"%-*.*s",l,l,strin);
+	c=i;
+	while(c--)
 		outchar(BS);
-		c--; } }
+	if(mode&K_MSG)
+		bputs(str);
+	else
+		rputs(str);
+	if(user_misc&ANSI) {
+		bputs("\x1b[K");
+		if(i<l)
+			bprintf("\x1b[%dD",l-i); 
+	}
+	else {
+		while(c<79)	{ /* clear to end of line */
+			outchar(SP);
+			c++; 
+		}
+		while(c>l) { /* back space to end of string */
+			outchar(BS);
+			c--; 
+		} 
+	}
 }
 
 /****************************************************************************/
@@ -1064,130 +1326,133 @@ char stripattr(char *strin)
 	uchar str[81];
 	uchar a,c,d,e;
 
-e=strlen(strin);
-for(a=c=d=0;c<e;c++) {
-	if(strin[c]==1) {
-		a++;
-		switch(toupper(strin[c+1])) {
-			case '-':	/* clear 		*/
-			case '_':	/* clear		*/
-			case 'B':	/* blue 	fg 	*/
-			case 'C':	/* cyan 	fg 	*/
-			case 'G':	/* green	fg 	*/
-			case 'H':	/* high 	fg 	*/
-			case 'I':	/* blink 	   	*/
-			case 'K':	/* black 	fg 	*/
-			case 'L':	/* cls         	*/
-			case 'M':	/* magenta  fg 	*/
-			case 'N':	/* normal      	*/
-			case 'P':	/* pause       	*/
-			case 'Q':   /* pause reset  */
-			case 'R':	/* red      fg 	*/
-			case 'W':	/* white    fg 	*/
-			case 'Y':	/* yellow   fg 	*/
-			case '0':	/* black 	bg 	*/
-			case '1':	/* red   	bg 	*/
-			case '2':	/* green 	bg 	*/
-			case '3':   /* brown	bg 	*/
-			case '4':	/* blue  	bg 	*/
-			case '5':   /* magenta 	bg 	*/
-			case '6':	/* cyan    	bg 	*/
-			case '7':	/* white   	bg 	*/
-				break;
-			default:
-				c++;
-				continue; } }
-	str[d++]=strin[c]; }
-str[d]=0;
-strcpy(strin,str);
-return(a);
+	e=strlen(strin);
+	for(a=c=d=0;c<e;c++) {
+		if(strin[c]==1) {
+			a++;
+			switch(toupper(strin[c+1])) {
+				case '-':	/* clear 		*/
+				case '_':	/* clear		*/
+				case 'B':	/* blue 	fg 	*/
+				case 'C':	/* cyan 	fg 	*/
+				case 'G':	/* green	fg 	*/
+				case 'H':	/* high 	fg 	*/
+				case 'I':	/* blink 	   	*/
+				case 'K':	/* black 	fg 	*/
+				case 'L':	/* cls         	*/
+				case 'M':	/* magenta  fg 	*/
+				case 'N':	/* normal      	*/
+				case 'P':	/* pause       	*/
+				case 'Q':   /* pause reset  */
+				case 'R':	/* red      fg 	*/
+				case 'W':	/* white    fg 	*/
+				case 'Y':	/* yellow   fg 	*/
+				case '0':	/* black 	bg 	*/
+				case '1':	/* red   	bg 	*/
+				case '2':	/* green 	bg 	*/
+				case '3':   /* brown	bg 	*/
+				case '4':	/* blue  	bg 	*/
+				case '5':   /* magenta 	bg 	*/
+				case '6':	/* cyan    	bg 	*/
+				case '7':	/* white   	bg 	*/
+					break;
+				default:
+					c++;
+					continue; 
+			} 
+		}
+		str[d++]=strin[c]; 
+	}
+	str[d]=0;
+	strcpy(strin,str);
+	return(a);
 }
 
 /***************************************************************************/
 /* Changes local and remote text attributes accounting for monochrome      */
 /***************************************************************************/
-void attr(char atr)
+void attr(int atr)
 {
 
-if(!(user_misc&ANSI) || aborted)
-	return;
-if(!(user_misc&COLOR)) {  /* eliminate colors if user doesn't have them */
-	if(atr&LIGHTGRAY)		/* if any bits set, set all */
-		atr|=LIGHTGRAY;
-	if(atr&(LIGHTGRAY<<4))
-		atr|=(LIGHTGRAY<<4);
-	if(atr&LIGHTGRAY && atr&(LIGHTGRAY<<4))
-		atr&=~LIGHTGRAY; }	/* if background is solid, forground is black */
-if(curatr==atr) /* attribute hasn't changed. don't send codes */
-	return;
-
-if((!(atr&HIGH) && curatr&HIGH)	|| (!(atr&BLINK) && curatr&BLINK)
-	|| atr==LIGHTGRAY) {
-	bprintf("\x1b[0m");
-	curatr=LIGHTGRAY; }
-
-if(atr==LIGHTGRAY) {				 /* no attributes */
+	if(!(user_misc&ANSI) || aborted)
+		return;
+	if(!(user_misc&COLOR)) {  /* eliminate colors if user doesn't have them */
+		if(atr&LIGHTGRAY)		/* if any bits set, set all */
+			atr|=LIGHTGRAY;
+		if(atr&(LIGHTGRAY<<4))
+			atr|=(LIGHTGRAY<<4);
+		if(atr&LIGHTGRAY && atr&(LIGHTGRAY<<4))
+			atr&=~LIGHTGRAY; }	/* if background is solid, forground is black */
+	if(curatr==atr) /* attribute hasn't changed. don't send codes */
+		return;
+
+	if((!(atr&HIGH) && curatr&HIGH)	|| (!(atr&BLINK) && curatr&BLINK)
+		|| atr==LIGHTGRAY) {
+		bprintf("\x1b[0m");
+		curatr=LIGHTGRAY; }
+
+	if(atr==LIGHTGRAY) {				 /* no attributes */
+		curatr=atr;
+		return; }
+
+	if(atr&BLINK) {						/* special attributes */
+		if(!(curatr&BLINK))
+			bprintf("\x1b[5m"); }
+	if(atr&HIGH) {
+		if(!(curatr&HIGH))
+			bprintf("\x1b[1m"); }
+
+	if((atr&0x7)==BLACK) {				/* foreground colors */
+		if((curatr&0x7)!=BLACK)
+			bprintf("\x1b[30m"); }
+	else if((atr&0x7)==RED) {
+		if((curatr&0x7)!=RED)
+			bprintf("\x1b[31m"); }
+	else if((atr&0x7)==GREEN) {
+		if((curatr&0x7)!=GREEN)
+			bprintf("\x1b[32m"); }
+	else if((atr&0x7)==BROWN) {
+		if((curatr&0x7)!=BROWN)
+			bprintf("\x1b[33m"); }
+	else if((atr&0x7)==BLUE) {
+		if((curatr&0x7)!=BLUE)
+			bprintf("\x1b[34m"); }
+	else if((atr&0x7)==MAGENTA) {
+		if((curatr&0x7)!=MAGENTA)
+			bprintf("\x1b[35m"); }
+	else if((atr&0x7)==CYAN) {
+		if((curatr&0x7)!=CYAN)
+			bprintf("\x1b[36m"); }
+	else if((atr&0x7)==LIGHTGRAY) {
+		if((curatr&0x7)!=LIGHTGRAY)
+			bprintf("\x1b[37m"); }
+
+	if((atr&0x70)==(BLACK<<4)) {		/* background colors */
+		if((curatr&0x70)!=(BLACK<<4))
+			bprintf("\x1b[40m"); }
+	else if((atr&0x70)==(RED<<4)) {
+		if((curatr&0x70)!=(RED<<4))
+			bprintf("\x1b[41m"); }
+	else if((atr&0x70)==(GREEN<<4)) {
+		if((curatr&0x70)!=(GREEN<<4))
+			bprintf("\x1b[42m"); }
+	else if((atr&0x70)==(BROWN<<4)) {
+		if((curatr&0x70)!=(BROWN<<4))
+			bprintf("\x1b[43m"); }
+	else if((atr&0x70)==(BLUE<<4)) {
+		if((curatr&0x70)!=(BLUE<<4))
+			bprintf("\x1b[44m"); }
+	else if((atr&0x70)==(MAGENTA<<4)) {
+		if((curatr&0x70)!=(MAGENTA<<4))
+			bprintf("\x1b[45m"); }
+	else if((atr&0x70)==(CYAN<<4)) {
+		if((curatr&0x70)!=(CYAN<<4))
+			bprintf("\x1b[46m"); }
+	else if((atr&0x70)==(LIGHTGRAY<<4)) {
+		if((curatr&0x70)!=(LIGHTGRAY<<4))
+			bprintf("\x1b[47m"); }
+
 	curatr=atr;
-	return; }
-
-if(atr&BLINK) {						/* special attributes */
-	if(!(curatr&BLINK))
-		bprintf("\x1b[5m"); }
-if(atr&HIGH) {
-	if(!(curatr&HIGH))
-		bprintf("\x1b[1m"); }
-
-if((atr&0x7)==BLACK) {				/* foreground colors */
-	if((curatr&0x7)!=BLACK)
-		bprintf("\x1b[30m"); }
-else if((atr&0x7)==RED) {
-	if((curatr&0x7)!=RED)
-		bprintf("\x1b[31m"); }
-else if((atr&0x7)==GREEN) {
-	if((curatr&0x7)!=GREEN)
-		bprintf("\x1b[32m"); }
-else if((atr&0x7)==BROWN) {
-	if((curatr&0x7)!=BROWN)
-		bprintf("\x1b[33m"); }
-else if((atr&0x7)==BLUE) {
-	if((curatr&0x7)!=BLUE)
-		bprintf("\x1b[34m"); }
-else if((atr&0x7)==MAGENTA) {
-	if((curatr&0x7)!=MAGENTA)
-		bprintf("\x1b[35m"); }
-else if((atr&0x7)==CYAN) {
-	if((curatr&0x7)!=CYAN)
-		bprintf("\x1b[36m"); }
-else if((atr&0x7)==LIGHTGRAY) {
-	if((curatr&0x7)!=LIGHTGRAY)
-		bprintf("\x1b[37m"); }
-
-if((atr&0x70)==(BLACK<<4)) {		/* background colors */
-	if((curatr&0x70)!=(BLACK<<4))
-		bprintf("\x1b[40m"); }
-else if((atr&0x70)==(RED<<4)) {
-	if((curatr&0x70)!=(RED<<4))
-		bprintf("\x1b[41m"); }
-else if((atr&0x70)==(GREEN<<4)) {
-	if((curatr&0x70)!=(GREEN<<4))
-		bprintf("\x1b[42m"); }
-else if((atr&0x70)==(BROWN<<4)) {
-	if((curatr&0x70)!=(BROWN<<4))
-		bprintf("\x1b[43m"); }
-else if((atr&0x70)==(BLUE<<4)) {
-	if((curatr&0x70)!=(BLUE<<4))
-		bprintf("\x1b[44m"); }
-else if((atr&0x70)==(MAGENTA<<4)) {
-	if((curatr&0x70)!=(MAGENTA<<4))
-		bprintf("\x1b[45m"); }
-else if((atr&0x70)==(CYAN<<4)) {
-	if((curatr&0x70)!=(CYAN<<4))
-		bprintf("\x1b[46m"); }
-else if((atr&0x70)==(LIGHTGRAY<<4)) {
-	if((curatr&0x70)!=(LIGHTGRAY<<4))
-		bprintf("\x1b[47m"); }
-
-curatr=atr;
 }
 
 /****************************************************************************/
@@ -1195,22 +1460,20 @@ curatr=atr;
 /****************************************************************************/
 void cls(void)
 {
-	int i;
+	if(lncntr>1 && !tos) {
+		lncntr=0;
+		CRLF;
+		pause();
+		while(lncntr && !aborted)
+			pause(); }
 
-if(lncntr>1 && !tos) {
+	if(user_misc&ANSI)
+		bprintf("\x1b[2J");
+	else {
+		outchar(FF);
+		clrscr(); }
+	tos=1;
 	lncntr=0;
-	CRLF;
-	pause();
-	while(lncntr && !aborted)
-		pause(); }
-
-if(user_misc&ANSI)
-	bprintf("\x1b[2J");
-else {
-	outchar(FF);
-	clrscr(); }
-tos=1;
-lncntr=0;
 }
 
 #ifdef __WATCOMC__
@@ -1219,13 +1482,13 @@ short wherey(void)
 {
 	struct rccoord rc;
 
-rc=_gettextposition();
-return(rc.col);
+	rc=_gettextposition();
+	return(rc.col);
 }
 
 void clrscr(void)
 {
-_clearscreen(_GCLEARSCREEN);
+	_clearscreen(_GCLEARSCREEN);
 }
 
 #endif
@@ -1236,143 +1499,145 @@ _clearscreen(_GCLEARSCREEN);
 void ctrl_a(char x)
 {
 	char atr=curatr;
-	int i,j;
+	int i;
 
-if((uchar)x>=0x7f) {
-	if(user_misc&ANSI)
-		bprintf("\x1b[%uC",(uchar)x-0x7f);
-	else
-		for(i=0;i<(uchar)x-0x7f;i++)
-			outchar(SP);
-    return; }
-
-switch(toupper(x)) {
-	case '-':								/* turn off all attributes if */
-		if(atr&(HIGH|BLINK|(LIGHTGRAY<<4)))	/* high intensity, blink or */
-			attr(LIGHTGRAY);				/* background bits are set */
-		break;
-	case '_':								/* turn off all attributes if */
-		if(atr&(BLINK|(LIGHTGRAY<<4)))		/* blink or background is set */
-			attr(LIGHTGRAY);
-		break;
-	case ',':   /* Delay 1/10 sec */
-		mswait(100);
-		break;
-	case ';':   /* Delay 1/2 sec */
-		mswait(500);
-		break;
-	case '.':   /* Delay 2 secs */
-		mswait(2000);
-        break;
-	case 'P':	/* Pause */
-		pause();
-		break;
-	case 'Q':   /* Pause reset */
-		lncntr=0;
-		break;
-	case 'L':	/* CLS (form feed) */
-		cls();
-		break;
-	case '>':   /* CLREOL */
+	if((uchar)x>=0x7f) {
 		if(user_misc&ANSI)
-			bputs("\x1b[K");
-		else {
-			i=j=wherey();
-			while(i++<80)
+			bprintf("\x1b[%uC",(uchar)x-0x7f);
+		else
+			for(i=0;i<(uchar)x-0x7f;i++)
 				outchar(SP);
-			while(j++<80)
-				outchar(BS); }
-		break;
-	case '<':   /* Non-destructive backspace */
-		outchar(BS);
-		break;
-	case '[':   /* Carriage return */
-		outchar(CR);
-		break;
-	case ']':   /* Line feed */
-		outchar(LF);
-		break;
-	case 'A':   /* Ctrl-A */
-		outchar(1);
-        break;
-	case 'H': 	/* High intensity */
-		atr|=HIGH;
-		attr(atr);
-		break;
-	case 'I':	/* Blink */
-		atr|=BLINK;
-		attr(atr);
-		break;
-	case 'N': 	/* Normal */
-		attr(LIGHTGRAY);
-		break;
-	case 'R':
-		atr=(atr&0xf8)|RED;
-		attr(atr);
-		break;
-	case 'S':
-		nodesync();
-		break;
-	case 'G':
-		atr=(atr&0xf8)|GREEN;
-		attr(atr);
-		break;
-	case 'B':
-		atr=(atr&0xf8)|BLUE;
-		attr(atr);
-		break;
-    case 'W':	/* White */
-		atr=(atr&0xf8)|LIGHTGRAY;
-		attr(atr);
-		break;
-    case 'C':
-		atr=(atr&0xf8)|CYAN;
-		attr(atr);
-		break;
-	case 'M':
-		atr=(atr&0xf8)|MAGENTA;
-		attr(atr);
-		break;
-	case 'Y':
-		atr=(atr&0xf8)|BROWN;
-		attr(atr);
-		break;
-    case 'K':	/* Black */
-		atr=(atr&0xf8)|BLACK;
-		attr(atr);
-		break;
-    case '0':	/* Black Background */
-		atr=(atr&0x8f)|(BLACK<<4);
-		attr(atr);
-		break;
-	case '1':	/* Red Background */
-		atr=(atr&0x8f)|(RED<<4);
-		attr(atr);
-		break;
-	case '2':	/* Green Background */
-		atr=(atr&0x8f)|(GREEN<<4);
-		attr(atr);
-		break;
-	case '3':	/* Yellow Background */
-		atr=(atr&0x8f)|(BROWN<<4);
-		attr(atr);
-		break;
-	case '4':	/* Blue Background */
-		atr=(atr&0x8f)|(BLUE<<4);
-		attr(atr);
-		break;
-	case '5':	/* Magenta Background */
-		atr=(atr&0x8f)|(MAGENTA<<4);
-		attr(atr);
-		break;
-	case '6':	/* Cyan Background */
-		atr=(atr&0x8f)|(CYAN<<4);
-		attr(atr);
-		break;
-	case '7':	/* White Background */
-		atr=(atr&0x8f)|(LIGHTGRAY<<4);
-		attr(atr);
-		break; }
+		return; }
+
+	switch(toupper(x)) {
+		case '-':								/* turn off all attributes if */
+			if(atr&(HIGH|BLINK|(LIGHTGRAY<<4)))	/* high intensity, blink or */
+				attr(LIGHTGRAY);				/* background bits are set */
+			break;
+		case '_':								/* turn off all attributes if */
+			if(atr&(BLINK|(LIGHTGRAY<<4)))		/* blink or background is set */
+				attr(LIGHTGRAY);
+			break;
+		case ',':   /* Delay 1/10 sec */
+			mswait(100);
+			break;
+		case ';':   /* Delay 1/2 sec */
+			mswait(500);
+			break;
+		case '.':   /* Delay 2 secs */
+			mswait(2000);
+			break;
+		case 'P':	/* Pause */
+			pause();
+			break;
+		case 'Q':   /* Pause reset */
+			lncntr=0;
+			break;
+		case 'L':	/* CLS (form feed) */
+			cls();
+			break;
+		case '>':   /* CLREOL */
+			if(user_misc&ANSI)
+				bputs("\x1b[K");
+#if 0
+			else {
+				i=j=wherey();
+				while(i++<80)
+					outchar(SP);
+				while(j++<80)
+					outchar(BS); }
+#endif
+			break;
+		case '<':   /* Non-destructive backspace */
+			outchar(BS);
+			break;
+		case '[':   /* Carriage return */
+			outchar(CR);
+			break;
+		case ']':   /* Line feed */
+			outchar(LF);
+			break;
+		case 'A':   /* Ctrl-A */
+			outchar(1);
+			break;
+		case 'H': 	/* High intensity */
+			atr|=HIGH;
+			attr(atr);
+			break;
+		case 'I':	/* Blink */
+			atr|=BLINK;
+			attr(atr);
+			break;
+		case 'N': 	/* Normal */
+			attr(LIGHTGRAY);
+			break;
+		case 'R':
+			atr=(atr&0xf8)|RED;
+			attr(atr);
+			break;
+		case 'S':
+			nodesync();
+			break;
+		case 'G':
+			atr=(atr&0xf8)|GREEN;
+			attr(atr);
+			break;
+		case 'B':
+			atr=(atr&0xf8)|BLUE;
+			attr(atr);
+			break;
+		case 'W':	/* White */
+			atr=(atr&0xf8)|LIGHTGRAY;
+			attr(atr);
+			break;
+		case 'C':
+			atr=(atr&0xf8)|CYAN;
+			attr(atr);
+			break;
+		case 'M':
+			atr=(atr&0xf8)|MAGENTA;
+			attr(atr);
+			break;
+		case 'Y':
+			atr=(atr&0xf8)|BROWN;
+			attr(atr);
+			break;
+		case 'K':	/* Black */
+			atr=(atr&0xf8)|BLACK;
+			attr(atr);
+			break;
+		case '0':	/* Black Background */
+			atr=(atr&0x8f)|(uchar)(BLACK<<4);
+			attr(atr);
+			break;
+		case '1':	/* Red Background */
+			atr=(atr&0x8f)|(uchar)(RED<<4);
+			attr(atr);
+			break;
+		case '2':	/* Green Background */
+			atr=(atr&0x8f)|(uchar)(GREEN<<4);
+			attr(atr);
+			break;
+		case '3':	/* Yellow Background */
+			atr=(atr&0x8f)|(uchar)(BROWN<<4);
+			attr(atr);
+			break;
+		case '4':	/* Blue Background */
+			atr=(atr&0x8f)|(uchar)(BLUE<<4);
+			attr(atr);
+			break;
+		case '5':	/* Magenta Background */
+			atr=(atr&0x8f)|(uchar)(MAGENTA<<4);
+			attr(atr);
+			break;
+		case '6':	/* Cyan Background */
+			atr=(atr&0x8f)|(uchar)(CYAN<<4);
+			attr(atr);
+			break;
+		case '7':	/* White Background */
+			atr=(atr&0x8f)|(uchar)(LIGHTGRAY<<4);
+			attr(atr);
+			break; }
 }
 
 /****************************************************************************/
@@ -1385,19 +1650,19 @@ int nopen(char *str, int access)
 	char count=0;
 	int file,share;
 
-if(access&SH_DENYNO) share=SH_DENYNO;
-else if(access==O_RDONLY) share=SH_DENYWR;
-else share=SH_DENYRW;
-while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
-	&& errno==EACCES && count++<LOOP_NOPEN)
-	if(count>10)
-		mswait(50);
-if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN)
-	bprintf("\r\nNOPEN COLLISION - File: %s Count: %d\r\n"
-		,str,count);
-if(file==-1 && errno==EACCES)
-	bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
-return(file);
+	if(access&SH_DENYNO) share=SH_DENYNO;
+	else if(access==O_RDONLY) share=SH_DENYWR;
+	else share=SH_DENYRW;
+	while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
+		&& errno==EACCES && count++<LOOP_NOPEN)
+		if(count>10)
+			mswait(50);
+	if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN)
+		bprintf("\r\nNOPEN COLLISION - File: %s Count: %d\r\n"
+			,str,count);
+	if(file==-1 && errno==EACCES)
+		bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
+	return(file);
 }
 
 /****************************************************************************/
@@ -1411,8 +1676,8 @@ void initdata(void)
 	int i;
 	FILE *stream;
 
-#if defined(__TURBOC__) || defined(__SC__)	/* Borland or Symantec */
-	ctrlbrk(cbreakh);
+#ifdef _WINSOCKAPI_
+    WSAStartup(MAKEWORD(1,1), &WSAData);
 #endif
 
 #ifdef __WATCOMC__
@@ -1428,257 +1693,292 @@ void initdata(void)
 	con_fp=stderr;
 #endif
 
-if(setmode(fileno(con_fp),O_BINARY)==-1) {	 /* eliminate LF expansion */
-	printf("Can't set console output to BINARY\n");
-	exit(1); }
-
-sprintf(str,"%sXTRN.DAT",node_dir);
-if((stream=fopen(str,"rt"))==NULL) {
-	printf("Can't open %s\r\n",str);
-	exit(1); }
-fgets(str,81,stream);			/* username */
-sprintf(user_name,"%.25s",str);
-truncsp(user_name);
-fgets(str,81,stream);			/* system name */
-sprintf(sys_name,"%.40s",str);
-truncsp(sys_name);
-fgets(str,81,stream);			/* system operator */
-sprintf(sys_op,"%.40s",str);
-truncsp(sys_op);
-fgets(str,81,stream);			/* system guru */
-sprintf(sys_guru,"%.40s",str);
-truncsp(sys_guru);
-
-fgets(str,81,stream);			/* ctrl dir */
-str[50]=0;
-if(str[0]=='.')
-	sprintf(ctrl_dir,"%s%s",node_dir,str);
-else
-	strcpy(ctrl_dir,str);
-truncsp(ctrl_dir);
-if(_fullpath(str,ctrl_dir,50))
-	strcpy(ctrl_dir,str);
-backslash(ctrl_dir);
-
-fgets(str,81,stream);			/* data dir */
-if(str[0]=='.')
-	sprintf(data_dir,"%s%s",node_dir,str);
-else
-	sprintf(data_dir,"%.40s",str);
-truncsp(data_dir);
-if(_fullpath(str,data_dir,50))
-	strcpy(data_dir,str);
-backslash(data_dir);
-
-fgets(str,81,stream);			/* total nodes */
-sys_nodes=atoi(str);
-fgets(str,81,stream);			/* current node */
-node_num=atoi(str);
-fgets(str,81,stream);			/* time left */
-timeleft=atoi(str);
-fgets(str,81,stream);			/* ANSI? (Yes, Mono, or No) */
-user_misc=0;
-if(str[0]=='Y')
-	user_misc|=(ANSI|COLOR);
-else if(str[0]=='M')
-	user_misc|=ANSI;
-fgets(str,81,stream);			/* screen lines */
-user_rows=atoi(str);
-fgets(str,81,stream);			/* credits */
-user_cdt=atol(str);
-fgets(str,81,stream);			/* level */
-user_level=atoi(str);
-fgets(str,81,stream);			/* was transfer level, left for compat. */
-fgets(str,81,stream);			/* birthdate */
-truncsp(str);
-sprintf(user_birth,"%.8s",str);
-fgets(str,81,stream);			/* sex */
-user_sex=str[0];
-fgets(str,81,stream);			/* user number */
-user_number=atoi(str);
-fgets(str,81,stream);			/* user phone number */
-sprintf(user_phone,"%.12s",str);
-truncsp(user_phone);
-fgets(str,81,stream);			/* com port (0 if local or no modem) */
-com_port=atoi(str);
-fgets(str,81,stream);			/* com (UART) irq */
-com_irq=atoi(str);
-fgets(str,81,stream);			/* com (UART) base address in hex */
-truncsp(str);
-com_base=(uint)ahtoul(str);
-fgets(str,81,stream);			/* com rate */
-com_rate=(ulong)atol(str);
-fgets(str,81,stream);			/* hardware flow control (Y/N) */
-if(toupper(str[0])=='Y')
-	mdm_misc|=MDM_FLOWCTRL;
-fgets(str,81,stream);			/* locked DTE rate (Y/N) */
-if(toupper(str[0])=='Y')
-	mdm_misc|=MDM_STAYHIGH;
-fgets(str,81,stream);			/* modem initialization string */
-sprintf(mdm_init,"%.63s",str);
-truncsp(mdm_init);
-fgets(str,81,stream);			/* modem special init string */
-sprintf(mdm_spec,"%.63s",str);
-truncsp(mdm_spec);
-fgets(str,81,stream);			/* modem terminal mode string */
-sprintf(mdm_term,"%.63s",str);
-truncsp(mdm_term);
-fgets(str,81,stream);			/* modem dial string */
-sprintf(mdm_dial,"%.63s",str);
-truncsp(mdm_dial);
-fgets(str,81,stream);			/* modem off-hook string */
-sprintf(mdm_offh,"%.63s",str);
-truncsp(mdm_offh);
-fgets(str,81,stream);			/* modem answer string */
-sprintf(mdm_answ,"%.63s",str);
-truncsp(mdm_answ);
-fgets(str,81,stream);			/* memory address of modem status register */
-msr=(uint far *)atol(str);
-if(!fgets(str,81,stream))		/* total number of external programs */
-	total_xtrns=0;
-else
-	total_xtrns=atoi(str);
-if(total_xtrns && (xtrn=(char **)MALLOC(sizeof(char *)*total_xtrns))==NULL) {
-	printf("Allocation error 1: %u\r\n",sizeof(char *)*total_xtrns);
-	exit(1); }
-for(i=0;i<total_xtrns;i++) {
-	fgets(str,81,stream);
-	truncsp(str);
-	if((xtrn[i]=(char *)MALLOC(strlen(str)+1))==NULL) {
-		printf("Allocation error 2 (%u): %u\r\n",i,strlen(str)+1);
+#ifdef __16BIT__
+
+#if defined(__TURBOC__) || defined(__SC__)	/* Borland or Symantec */
+	ctrlbrk(cbreakh);
+#endif
+
+	if(setmode(fileno(con_fp),O_BINARY)==-1) {	 /* eliminate LF expansion */
+		printf("Can't set console output to BINARY\n");
+		exit(1); }
+#endif
+
+	sprintf(str,"%sXTRN.DAT",node_dir);
+	if((stream=fopen(str,"rt"))==NULL) {
+		printf("Can't open %s\r\n",str);
 		exit(1); }
-	strcpy(xtrn[i],str); }
-fgets(str,81,stream);			/* user's main flags */
-sprintf(user_flags1,"%.26s",str);
-fgets(str,81,stream);			/* user's xfer flags */
-sprintf(user_flags2,"%.26s",str);
-fgets(str,81,stream);			/* user's exemptions */
-sprintf(user_exempt,"%.26s",str);
-fgets(str,81,stream);			/* user's restrictions */
-sprintf(user_rest,"%.26s",str);
-fgets(str,81,stream);			/* user's expiration date */
-truncsp(str);
-user_expire=ahtoul(str);
-str[0]=0;
-fgets(str,81,stream);			/* user's address */
-sprintf(user_address,"%.30s",str);
-truncsp(user_address);
-fgets(str,81,stream);			/* user's location (city, state) */
-sprintf(user_location,"%.30s",str);
-truncsp(user_location);
-fgets(str,81,stream);			/* user's zip/postal code */
-sprintf(user_zipcode,"%.10s",str);
-truncsp(user_zipcode);
-str[0]=0;
-fgets(str,81,stream);
-sprintf(user_flags3,"%.26s",str);
-fgets(str,81,stream);
-sprintf(user_flags4,"%.26s",str);
-if(fgets(str,81,stream))		/* Time-slice API type */
-	mswtyp=ahtoul(str);
-str[0]=0;
-fgets(str,81,stream);
-truncsp(str);
-sprintf(user_realname,"%.25s",str);
-str[0]=0;
-fgets(str,81,stream);
-user_dce=atol(str);
-
-str[0]=0;
-fgets(str,81,stream);			/* exec dir */
-if(!str[0])
-	sprintf(exec_dir,"%s..\\EXEC\\",ctrl_dir);
-else {
+	fgets(str,81,stream);			/* username */
+	sprintf(user_name,"%.25s",str);
+	truncsp(user_name);
+	fgets(str,81,stream);			/* system name */
+	sprintf(sys_name,"%.40s",str);
+	truncsp(sys_name);
+	fgets(str,81,stream);			/* system operator */
+	sprintf(sys_op,"%.40s",str);
+	truncsp(sys_op);
+	fgets(str,81,stream);			/* system guru */
+	sprintf(sys_guru,"%.40s",str);
+	truncsp(sys_guru);
+
+	fgets(str,81,stream);			/* ctrl dir */
+	str[50]=0;
 	if(str[0]=='.')
-		sprintf(exec_dir,"%s%s",node_dir,str);
+		sprintf(ctrl_dir,"%s%s",node_dir,str);
 	else
-		sprintf(exec_dir,"%.50s",str); }
-truncsp(exec_dir);
-if(_fullpath(str,exec_dir,50))
-	strcpy(exec_dir,str);
-backslash(exec_dir);
-
-str[0]=0;
-fgets(str,81,stream);			/* text dir */
-if(!str[0])
-	sprintf(text_dir,"%s..\\TEXT\\",ctrl_dir);
-else {
+		strcpy(ctrl_dir,str);
+	truncsp(ctrl_dir);
+	if(_fullpath(str,ctrl_dir,50))
+		strcpy(ctrl_dir,str);
+	backslash(ctrl_dir);
+
+	fgets(str,81,stream);			/* data dir */
 	if(str[0]=='.')
-		sprintf(text_dir,"%s%s",node_dir,str);
+		sprintf(data_dir,"%s%s",node_dir,str);
 	else
-		sprintf(text_dir,"%.50s",str); }
-truncsp(text_dir);
-if(_fullpath(str,text_dir,50))
-	strcpy(text_dir,str);
-backslash(text_dir);
-
-str[0]=0;
-fgets(str,81,stream);			/* temp dir */
-if(!str[0])
-	sprintf(temp_dir,"%sTEMP\\",node_dir);
-else {
-	if(str[0]!='\\' && str[1]!=':')
-		sprintf(temp_dir,"%s%s",node_dir,str);
+		sprintf(data_dir,"%.40s",str);
+	truncsp(data_dir);
+	if(_fullpath(str,data_dir,50))
+		strcpy(data_dir,str);
+	backslash(data_dir);
+
+	fgets(str,81,stream);			/* total nodes */
+	sys_nodes=atoi(str);
+	fgets(str,81,stream);			/* current node */
+	node_num=atoi(str);
+	fgets(str,81,stream);			/* time left */
+	timeleft=atoi(str);
+	fgets(str,81,stream);			/* ANSI? (Yes, Mono, or No) */
+	user_misc=0;
+	if(str[0]=='Y')
+		user_misc|=(ANSI|COLOR);
+	else if(str[0]=='M')
+		user_misc|=ANSI;
+	fgets(str,81,stream);			/* screen lines */
+	user_rows=atoi(str);
+	fgets(str,81,stream);			/* credits */
+	user_cdt=atol(str);
+	fgets(str,81,stream);			/* level */
+	user_level=atoi(str);
+	fgets(str,81,stream);			/* was transfer level, left for compat. */
+	fgets(str,81,stream);			/* birthdate */
+	truncsp(str);
+	sprintf(user_birth,"%.8s",str);
+	fgets(str,81,stream);			/* sex */
+	user_sex=str[0];
+	fgets(str,81,stream);			/* user number */
+	user_number=atoi(str);
+	fgets(str,81,stream);			/* user phone number */
+	sprintf(user_phone,"%.12s",str);
+	truncsp(user_phone);
+	fgets(str,81,stream);			/* com port (0 if local or no modem) */
+	com_port=atoi(str);
+	fgets(str,81,stream);			/* com (UART) irq */
+	com_irq=atoi(str);
+	fgets(str,81,stream);			/* com (UART) base address in hex */
+	truncsp(str);
+	com_base=(uint)ahtoul(str);
+	fgets(str,81,stream);			/* com rate */
+	com_rate=(ulong)atol(str);
+	fgets(str,81,stream);			/* hardware flow control (Y/N) */
+	if(toupper(str[0])=='Y')
+		mdm_misc|=MDM_FLOWCTRL;
+	fgets(str,81,stream);			/* locked DTE rate (Y/N) */
+	if(toupper(str[0])=='Y')
+		mdm_misc|=MDM_STAYHIGH;
+	fgets(str,81,stream);			/* modem initialization string */
+	sprintf(mdm_init,"%.63s",str);
+	truncsp(mdm_init);
+	fgets(str,81,stream);			/* modem special init string */
+	sprintf(mdm_spec,"%.63s",str);
+	truncsp(mdm_spec);
+	fgets(str,81,stream);			/* modem terminal mode string */
+	sprintf(mdm_term,"%.63s",str);
+	truncsp(mdm_term);
+	fgets(str,81,stream);			/* modem dial string */
+	sprintf(mdm_dial,"%.63s",str);
+	truncsp(mdm_dial);
+	fgets(str,81,stream);			/* modem off-hook string */
+	sprintf(mdm_offh,"%.63s",str);
+	truncsp(mdm_offh);
+	fgets(str,81,stream);			/* modem answer string */
+	sprintf(mdm_answ,"%.63s",str);
+	truncsp(mdm_answ);
+	fgets(str,81,stream);			/* memory address of modem status register */
+	msr=(uint FAR16 *)atol(str);
+	if(!fgets(str,81,stream))		/* total number of external programs */
+		total_xtrns=0;
 	else
-		sprintf(temp_dir,"%.50s",str); }
-truncsp(temp_dir);
-if(_fullpath(str,temp_dir,50))
-	strcpy(temp_dir,str);
-backslash(temp_dir);
-
-str[0]=0;
-fgets(str,81,stream);
-sprintf(sys_id,"%.8s",str);
-
-str[0]=0;
-fgets(str,81,stream);
-truncsp(str);
-if(str[0])
-	node_misc=(uint)ahtoul(str);
-else
-	node_misc=NM_LOWPRIO;
-
-fclose(stream);
-
-sprintf(str,"%sINTRSBBS.DAT",node_dir);     /* Shrank to run! */
-if(fexist(str)) {
-	if((stream=fopen(str,"rt"))==NULL) {
-		printf("Can't open %s\n",str);
+		total_xtrns=atoi(str);
+	if(total_xtrns && (xtrn=(char **)MALLOC(sizeof(char *)*total_xtrns))==NULL) {
+		printf("Allocation error 1: %u\r\n",sizeof(char *)*total_xtrns);
 		exit(1); }
-	fgets(tmp,81,stream);					/* so get MSR address from file */
-	msr=(uint far *)atol(tmp);
+	for(i=0;i<(int)total_xtrns;i++) {
+		fgets(str,81,stream);
+		truncsp(str);
+		if((xtrn[i]=(char *)MALLOC(strlen(str)+1))==NULL) {
+			printf("Allocation error 2 (%u): %u\r\n",i,strlen(str)+1);
+			exit(1); }
+		strcpy(xtrn[i],str); }
+	fgets(str,81,stream);			/* user's main flags */
+	sprintf(user_flags1,"%.26s",str);
+	fgets(str,81,stream);			/* user's xfer flags */
+	sprintf(user_flags2,"%.26s",str);
+	fgets(str,81,stream);			/* user's exemptions */
+	sprintf(user_exempt,"%.26s",str);
+	fgets(str,81,stream);			/* user's restrictions */
+	sprintf(user_rest,"%.26s",str);
+	fgets(str,81,stream);			/* user's expiration date */
+	truncsp(str);
+	user_expire=ahtoul(str);
+	str[0]=0;
+	fgets(str,81,stream);			/* user's address */
+	sprintf(user_address,"%.30s",str);
+	truncsp(user_address);
+	fgets(str,81,stream);			/* user's location (city, state) */
+	sprintf(user_location,"%.30s",str);
+	truncsp(user_location);
+	fgets(str,81,stream);			/* user's zip/postal code */
+	sprintf(user_zipcode,"%.10s",str);
+	truncsp(user_zipcode);
+	str[0]=0;
+	fgets(str,81,stream);
+	sprintf(user_flags3,"%.26s",str);
+	fgets(str,81,stream);
+	sprintf(user_flags4,"%.26s",str);
+	if(fgets(str,81,stream))		/* Time-slice API type */
+#ifdef __16BIT__ 
+		mswtyp=ahtoul(str);
+#else
+		;
+#endif
+	str[0]=0;
+	fgets(str,81,stream);
+	truncsp(str);
+	sprintf(user_realname,"%.25s",str);
+	str[0]=0;
+	fgets(str,81,stream);
+	user_dce=atol(str);
+
+	str[0]=0;
+	fgets(str,81,stream);			/* exec dir */
+	if(!str[0])
+		sprintf(exec_dir,"%s..\\EXEC\\",ctrl_dir);
+	else {
+		if(str[0]=='.')
+			sprintf(exec_dir,"%s%s",node_dir,str);
+		else
+			sprintf(exec_dir,"%.50s",str); }
+	truncsp(exec_dir);
+	if(_fullpath(str,exec_dir,50))
+		strcpy(exec_dir,str);
+	backslash(exec_dir);
+
+	str[0]=0;
+	fgets(str,81,stream);			/* text dir */
+	if(!str[0])
+		sprintf(text_dir,"%s..\\TEXT\\",ctrl_dir);
+	else {
+		if(str[0]=='.')
+			sprintf(text_dir,"%s%s",node_dir,str);
+		else
+			sprintf(text_dir,"%.50s",str); }
+	truncsp(text_dir);
+	if(_fullpath(str,text_dir,50))
+		strcpy(text_dir,str);
+	backslash(text_dir);
+
+	str[0]=0;
+	fgets(str,81,stream);			/* temp dir */
+	if(!str[0])
+		sprintf(temp_dir,"%sTEMP\\",node_dir);
+	else {
+		if(str[0]!='\\' && str[1]!=':')
+			sprintf(temp_dir,"%s%s",node_dir,str);
+		else
+			sprintf(temp_dir,"%.50s",str); }
+	truncsp(temp_dir);
+	if(_fullpath(str,temp_dir,50))
+		strcpy(temp_dir,str);
+	backslash(temp_dir);
+
+	str[0]=0;
+	fgets(str,81,stream);
+	sprintf(sys_id,"%.8s",str);
+
+	str[0]=0;
+	fgets(str,81,stream);
+	truncsp(str);
+	if(str[0])
+		node_misc=(uint)ahtoul(str);
+	else
+		node_misc=NM_LOWPRIO;
+
+#ifndef __16BIT__
+	str[0]=0;
+	fgets(str,81,stream);
+	client_socket=atoi(str);
+#endif
+
 	fclose(stream);
-	remove(str); }
-
-starttime=time(NULL);			/* initialize start time stamp */
-wordwrap[0]=0;					/* set wordwrap to null */
-attr(LIGHTGRAY);				/* initialize color and curatr to plain */
-mnehigh=LIGHTGRAY|HIGH; 		/* mnemonics highlight color */
-mnelow=GREEN;					/* mnemonics normal text color */
-sec_warn=180;					/* seconds till inactivity warning */
-sec_timeout=300;				/* seconds till inactivity timeout */
-tos=lncntr=0;					/* init topofscreen and linecounter to 0 */
-lastnodemsg=0;					/* Last node to send message to */
-aborted=0;                      /* Ctrl-C hit flag */
-sysop_level=90; 				/* Minimum level to be considered sysop */
-timeleft_warn=0;				/* Running out of time warning */
-
-sprintf(str,"%s%s",ctrl_dir,"NODE.DAB");
-if((nodefile=sopen(str,O_BINARY|O_RDWR,SH_DENYNO))==-1) {
-	bprintf("\r\n\7Error opening %s\r\n",str);
-	exit(1); }
-
-sprintf(str,"%sUSER\\NAME.DAT",data_dir);
-if((i=nopen(str,O_RDONLY))==-1) {
-	printf("\r\n\7Error opening %s\r\n",str);
-	exit(1); }
-memset(str,0,30);
-read(i,str,26);
-close(i);
-if(str[25]==CR) 	/* Version 1b */
-	name_len=25;
-else				/* Version 1a */
-	name_len=30;
+
+	sprintf(str,"%sINTRSBBS.DAT",node_dir);     /* Shrank to run! */
+	if(fexist(str)) {
+		if((stream=fopen(str,"rt"))==NULL) {
+			printf("Can't open %s\n",str);
+			exit(1); }
+		fgets(tmp,81,stream);					/* so get MSR address from file */
+		msr=(uint FAR16 *)atol(tmp);
+		fclose(stream);
+		remove(str); }
+
+	starttime=time(NULL);			/* initialize start time stamp */
+	wordwrap[0]=0;					/* set wordwrap to null */
+	attr(LIGHTGRAY);				/* initialize color and curatr to plain */
+	mnehigh=LIGHTGRAY|HIGH; 		/* mnemonics highlight color */
+	mnelow=GREEN;					/* mnemonics normal text color */
+	sec_warn=180;					/* seconds till inactivity warning */
+	sec_timeout=300;				/* seconds till inactivity timeout */
+	tos=lncntr=0;					/* init topofscreen and linecounter to 0 */
+	lastnodemsg=0;					/* Last node to send message to */
+	aborted=0;                      /* Ctrl-C hit flag */
+	sysop_level=90; 				/* Minimum level to be considered sysop */
+	timeleft_warn=0;				/* Running out of time warning */
+
+	sprintf(str,"%s%s",ctrl_dir,"NODE.DAB");
+	if((nodefile=sopen(str,O_BINARY|O_RDWR,SH_DENYNO,S_IREAD))==-1) {
+		bprintf("\r\n\7Error opening %s\r\n",str);
+		exit(1); }
+
+	sprintf(str,"%sUSER\\NAME.DAT",data_dir);
+	if((i=nopen(str,O_RDONLY))==-1) {
+		printf("\r\n\7Error opening %s\r\n",str);
+		exit(1); }
+	memset(str,0,30);
+	read(i,str,26);
+	close(i);
+	if(str[25]==CR) 	/* Version 1b */
+		name_len=25;
+	else				/* Version 1a */
+		name_len=30;
+
+#ifndef __16BIT__
+	if(client_socket!=INVALID_SOCKET) {
+		output_event=CreateEvent(
+						 NULL	// pointer to security attributes
+						,TRUE	// flag for manual-reset event
+						,FALSE	// flag for initial state
+						,NULL	// pointer to event-object name
+						);
+		if(output_event==NULL) {
+			printf("\r\n\7Error %d creating output_event\r\n",GetLastError());
+			exit(1);
+		}
+
+		_beginthread(output_thread,0,NULL);
+	}
+#endif
+
 }
 
 /****************************************************************************/
@@ -1690,19 +1990,19 @@ void get_term(void)
 	char str[128],ch;
 	int i;
 
-bputs("\r\x1b[!_\x1b[0t_\r        \r");
-mswait(500);
-for(i=0;i<120;i++) {
-	ch=inkey(0);
-	if(!ch)
-		break;
-	mswait(1);
-	str[i]=ch; }
-str[i]=0;
-if(strstr(str,"RIPSCRIP"))
-	user_misc|=RIP;
-if(strstr(str,"DC-TERM"))
-	user_misc|=WIP;
+	bputs("\r\x1b[!_\x1b[0t_\r        \r");
+	mswait(500);
+	for(i=0;i<120;i++) {
+		ch=inkey(0);
+		if(!ch)
+			break;
+		mswait(1);
+		str[i]=ch; }
+	str[i]=0;
+	if(strstr(str,"RIPSCRIP"))
+		user_misc|=RIP;
+	if(strstr(str,"DC-TERM"))
+		user_misc|=WIP;
 }
 
 /****************************************************************************/
@@ -1712,10 +2012,10 @@ void truncsp(uchar *str)
 {
 	char c;
 
-str[strcspn(str,"\t")]=0;
-c=strlen(str);
-while(c && (uchar)str[c-1]<=SP) c--;
-str[c]=0;
+	str[strcspn(str,"\t")]=0;
+	c=strlen(str);
+	while(c && (uchar)str[c-1]<=SP) c--;
+	str[c]=0;
 }
 
 /****************************************************************************/
@@ -1725,9 +2025,10 @@ void backslash(char *str)
 {
     int i;
 
-i=strlen(str);
-if(i && str[i-1]!='\\') {
-    str[i]='\\'; str[i+1]=0; }
+	i=strlen(str);
+	if(i && str[i-1]!='\\') {
+		str[i]='\\'; str[i+1]=0; 
+	}
 }
 
 
@@ -1738,9 +2039,9 @@ if(i && str[i-1]!='\\') {
 /****************************************************************************/
 void checktimeleft(void)
 {
-if(!SYSOP && !strchr(user_exempt,'T') && time(NULL)-starttime>timeleft) {
-	bputs("\1_\n\1r\1hTime's up.\n");
-	exit(0);  }
+	if(!SYSOP && !strchr(user_exempt,'T') && time(NULL)-starttime>timeleft) {
+		bputs("\1_\n\1r\1hTime's up.\n");
+		exit(0);  }
 }
 
 /****************************************************************************/
@@ -1753,23 +2054,23 @@ void printfile(char *str)
 	int file;
 	ulong length;
 
-strupr(str);
-if(!tos)
-	CRLF;
-if((file=nopen(str,O_RDONLY))==-1) {
-	bprintf("File not Found: %s\r\n",str);
-	return; }
-length=filelength(file);
-if((buf=MALLOC(length+1L))==NULL) {
+	strupr(str);
+	if(!tos)
+		CRLF;
+	if((file=nopen(str,O_RDONLY))==-1) {
+		bprintf("File not Found: %s\r\n",str);
+		return; }
+	length=filelength(file);
+	if((buf=MALLOC(length+1L))==NULL) {
+		close(file);
+		bprintf("\7\r\nPRINTFILE: Error allocating %lu bytes of memory for %s.\r\n"
+			,length+1L,str);
+		return; }
+	buf[read(file,buf,length)]=0;
 	close(file);
-	bprintf("\7\r\nPRINTFILE: Error allocating %lu bytes of memory for %s.\r\n"
-		,length+1L,str);
-	return; }
-buf[read(file,buf,length)]=0;
-close(file);
-bputs(buf);
-aborted=0;
-FREE(buf);
+	bputs(buf);
+	aborted=0;
+	FREE(buf);
 }
 
 /****************************************************************************/
@@ -1782,29 +2083,29 @@ char *username(uint usernumber)
 	char	str[128];
 	int 	i,file;
 
-strcpy(name,"UNKNOWN USER");
-if(!data_dir[0])
-	return(name);
-if(!usernumber) {
-	bputs("\7username: called with zero usernumber\r\n");
-	return(name); }
-sprintf(str,"%sUSER\\NAME.DAT",data_dir);
-if((file=nopen(str,O_RDONLY))==-1) {
-	bprintf("\7username: couldn't open %s\r\n",str);
-	return(name); }
-if(filelength(file)<(long)(usernumber-1)*((long)name_len+2L)) {
+	strcpy(name,"UNKNOWN USER");
+	if(!data_dir[0])
+		return(name);
+	if(!usernumber) {
+		bputs("\7username: called with zero usernumber\r\n");
+		return(name); }
+	sprintf(str,"%sUSER\\NAME.DAT",data_dir);
+	if((file=nopen(str,O_RDONLY))==-1) {
+		bprintf("\7username: couldn't open %s\r\n",str);
+		return(name); }
+	if(filelength(file)<(long)(usernumber-1)*((long)name_len+2L)) {
+		close(file);
+		return(name); }
+	lseek(file,(long)(usernumber-1)*((long)name_len+2L),SEEK_SET);
+	read(file,name,25);
 	close(file);
-	return(name); }
-lseek(file,(long)(usernumber-1)*((long)name_len+2L),SEEK_SET);
-read(file,name,25);
-close(file);
-for(i=0;i<25;i++)
-	if(name[i]==3)
-		break;
-name[i]=0;
-if(!name[0])
-	strcpy(name,"DELETED USER");
-return(name);
+	for(i=0;i<25;i++)
+		if(name[i]==3)
+			break;
+	name[i]=0;
+	if(!name[0])
+		strcpy(name,"DELETED USER");
+	return(name);
 }
 
 /****************************************************************************/
@@ -1817,24 +2118,24 @@ uint usernumber(char *username)
 	int i,file;
 	FILE *stream;
 
-if(!data_dir[0])
+	if(!data_dir[0])
+		return(0);
+	sprintf(str,"%sUSER\\NAME.DAT",data_dir);
+	if((file=nopen(str,O_RDONLY))==-1 || (stream=fdopen(file,"rb"))==NULL) {
+		if(file!=-1)
+			close(file);
+		bprintf("\7usernumber: couldn't open %s\r\n",str);
+		return(0); }
+	for(i=1;!feof(stream);i++) {
+		if(!fread(str,27,1,stream))
+			break;
+		str[25]=0;
+		truncsp(str);	/* chop of trailing EOTs and spaces */
+		if(!stricmp(str,username)) {
+			fclose(stream);
+			return(i); } }
+	fclose(stream);
 	return(0);
-sprintf(str,"%sUSER\\NAME.DAT",data_dir);
-if((file=nopen(str,O_RDONLY))==-1 || (stream=fdopen(file,"rb"))==NULL) {
-	if(file!=-1)
-		close(file);
-	bprintf("\7usernumber: couldn't open %s\r\n",str);
-	return(0); }
-for(i=1;!feof(stream);i++) {
-	if(!fread(str,27,1,stream))
-		break;
-	str[25]=0;
-	truncsp(str);	/* chop of trailing EOTs and spaces */
-	if(!stricmp(str,username)) {
-		fclose(stream);
-		return(i); } }
-fclose(stream);
-return(0);
 }
 
 
@@ -1845,17 +2146,33 @@ return(0);
 /****************************************************************************/
 char fexist(char *filespec)
 {
-#ifdef __SC__	/* Symantec */
-if(findfirst(filespec,0)==NULL)
-	return(0);
-return(1);
-#else			/* Not Symantec */
-	struct ffblk f;
+#if defined(_MSC_VER)	/* Microsoft */
+
+	long	handle;
+    struct _finddata_t f;
 
-if(findfirst(filespec,&f,0)==NULL)
+	if((handle=_findfirst(filespec,&f))==-1)
+		return(FALSE);
+	_findclose(handle);
+	if(f.attrib&_A_SUBDIR)
+		return(FALSE);
+	return(TRUE);
+
+#elif defined(__SC__)	/* Symantec */
+
+	if(findfirst(filespec,0)==NULL)
+		return(0);
 	return(1);
-return(0);
-#endif			/* !__SC__ */
+
+#else					/* Borland/Watcom */
+
+	struct ffblk f;
+
+	if(findfirst(filespec,&f,0)==NULL)
+		return(1);
+	return(0);
+
+#endif
 }
 
 /****************************************************************************/
@@ -1864,25 +2181,37 @@ return(0);
 /****************************************************************************/
 long flength(char *filespec)
 {
-#ifdef __SC__		/* Symantec */
+#if defined(_MSC_VER)	/* Microsoft */
+
+	long	handle;
+    struct _finddata_t f;
+
+	if((handle=_findfirst(filespec,&f))==-1)
+		return(-1L);
+	_findclose(handle);
+	return(f.size);
+
+#elif defined(__SC__)	/* Symantec */
+
 	struct FILE *f;
 
-if((f=findfirst(filespec,0))==NULL)
-	return(-1);
-return(f->size);
+	if((f=findfirst(filespec,0))==NULL)
+		return(-1);
+	return(f->size);
 
-#else				/* Not Symantec */
+#else					/* Borland/Watcom */
 
 	struct ffblk f;
 
-if(findfirst(filespec,&f,0)==NULL)
+	if(findfirst(filespec,&f,0)==NULL)
 #ifdef __TURBOC__	/* Borland */
-	return(f.ff_fsize);
+		return(f.ff_fsize);
 #else				/* Other (Watcom) */
-	return(f.size);
+		return(f.size);
 #endif
-return(-1L);
-#endif				/* !__SC__ */
+	return(-1L);
+
+#endif				
 }
 
 /****************************************************************************/
@@ -1894,15 +2223,15 @@ char *ultoac(ulong l, char *string)
 	char str[81];
 	char i,j,k;
 
-ultoa(l,str,10);
-i=strlen(str)-1;
-j=i/3+1+i;
-string[j--]=0;
-for(k=1;i>-1;k++) {
-	string[j--]=str[i--];
-	if(j>0 && !(k%3))
-		string[j--]=','; }
-return(string);
+	ultoa(l,str,10);
+	i=strlen(str)-1;
+	j=i/3+1+i;
+	string[j--]=0;
+	for(k=1;i>-1;k++) {
+		string[j--]=str[i--];
+		if(j>0 && !(k%3))
+			string[j--]=','; }
+	return(string);
 }
 
 /****************************************************************************/
@@ -1912,9 +2241,9 @@ ulong ahtoul(char *str)
 {
 	ulong l,val=0;
 
-while((l=(*str++)|0x20)!=0x20)
-	val=(l&0xf)+(l>>6&1)*9+val*16;
-return(val);
+	while((l=(*str++)|0x20)!=0x20)
+		val=(l&0xf)+(l>>6&1)*9+val*16;
+	return(val);
 }
 
 /****************************************************************************/
@@ -1922,25 +2251,24 @@ return(val);
 /* from NODE.DAB															*/
 /* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
 /****************************************************************************/
-void getnodedat(uchar number, node_t *node, char lockit)
+void getnodedat(int number, node_t *node, char lockit)
 {
-	char str[256];
 	int count=0;
 
-if(nodefile<0)
-	return;
-number--;	/* make zero based */
-while(count<LOOP_NODEDAB) {
-	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-	if(lockit
-		&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
-		count++;
-		continue; }
-	if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
-		break;
-	count++; }
-if(count==LOOP_NODEDAB)
-	bprintf("\7Error unlocking and reading NODE.DAB\r\n");
+	if(nodefile<0)
+		return;
+	number--;	/* make zero based */
+	while(count<LOOP_NODEDAB) {
+		lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
+		if(lockit
+			&& lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
+			count++;
+			continue; }
+		if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
+			break;
+		count++; }
+	if(count==LOOP_NODEDAB)
+		bprintf("\7Error unlocking and reading NODE.DAB\r\n");
 }
 
 /****************************************************************************/
@@ -1948,20 +2276,17 @@ if(count==LOOP_NODEDAB)
 /* getnodedat(num,&node,1); must have been called before calling this func  */
 /*          NOTE: ------^   the indicates the node record has been locked   */
 /****************************************************************************/
-void putnodedat(uchar number, node_t node)
+void putnodedat(int number, node_t node)
 {
-	char str[256];
-	int count;
-
-if(nodefile<0)
-	return;
-number--;	/* make zero based */
-lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
-if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
+	if(nodefile<0)
+		return;
+	number--;	/* make zero based */
+	lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
+	if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
+		unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
+		bprintf("\7Error writing NODE.DAB for node %u\r\n",number+1);
+		return; }
 	unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
-	bprintf("\7Error writing NODE.DAB for node %u\r\n",number+1);
-	return; }
-unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
 }
 
 /****************************************************************************/
@@ -1971,221 +2296,225 @@ void nodesync(void)
 {
 	node_t node;
 
-if(!ctrl_dir[0])
-	return;
-getnodedat(node_num,&node,0);
+	if(!ctrl_dir[0])
+		return;
+	getnodedat(node_num,&node,0);
 
-if(node.misc&NODE_MSGW)
-	getsmsg(user_number);		/* getsmsg clears MSGW flag */
+	if(node.misc&NODE_MSGW)
+		getsmsg(user_number);		/* getsmsg clears MSGW flag */
 
-if(node.misc&NODE_NMSG) 		/* getnmsg clears NMSG flag */
-	getnmsg();
+	if(node.misc&NODE_NMSG) 		/* getnmsg clears NMSG flag */
+		getnmsg();
 
-if(node.misc&NODE_INTR)
-	exit(0);
+	if(node.misc&NODE_INTR)
+		exit(0);
 
 }
 
 /****************************************************************************/
 /* Displays the information for node number 'number' contained in 'node'    */
 /****************************************************************************/
-void printnodedat(uchar number, node_t node)
+void printnodedat(int number, node_t node)
 {
 	char hour,mer[3],tmp[256];
 	int i;
 
-attr(LIGHTGRAY|HIGH);
-bprintf("Node %2d: ",number);
-attr(GREEN);
-switch(node.status) {
-    case NODE_WFC:
-        bputs("Waiting for call");
-        break;
-    case NODE_OFFLINE:
-        bputs("Offline");
-        break;
-    case NODE_NETTING:
-        bputs("Networking");
-        break;
-    case NODE_LOGON:
-        bputs("At logon prompt");
-        break;
-    case NODE_EVENT_WAITING:
-        bputs("Waiting for all nodes to become inactive");
-        break;
-    case NODE_EVENT_LIMBO:
-        bprintf("Waiting for node %d to finish external event",node.aux);
-        break;
-    case NODE_EVENT_RUNNING:
-        bputs("Running external event");
-        break;
-    case NODE_NEWUSER:
-		attr(GREEN|HIGH);
-        bputs("New user");
-		attr(GREEN);
-        bputs(" applying for access ");
-        if(!node.connection)
-            bputs("Locally");
-        else
-            bprintf("at %ubps",node.connection);
-        break;
-    case NODE_QUIET:
-        if(!SYSOP) {
-            bputs("Waiting for call");
-            break; }
-    case NODE_INUSE:
-		attr(GREEN|HIGH);
-        if(node.misc&NODE_ANON && !SYSOP)
-            bputs("UNKNOWN USER");
-        else
-			bputs(username(node.useron));
-		attr(GREEN);
-        bputs(" ");
-        switch(node.action) {
-            case NODE_MAIN:
-                bputs("at main menu");
-                break;
-            case NODE_RMSG:
-                bputs("reading messages");
-                break;
-            case NODE_RMAL:
-                bputs("reading mail");
-                break;
-            case NODE_RSML:
-                bputs("reading sent mail");
-                break;
-            case NODE_RTXT:
-                bputs("reading text files");
-                break;
-            case NODE_PMSG:
-                bputs("posting message");
-                break;
-            case NODE_SMAL:
-                bputs("sending mail");
-                break;
-            case NODE_AMSG:
-                bputs("posting auto-message");
-                break;
-            case NODE_XTRN:
-                if(!node.aux)
-                    bputs("at external program menu");
-                else {
-					bputs("running ");
-					i=node.aux-1;
-					if(i>=total_xtrns || !xtrn[i][0])
-						bputs("external program");
+	attr(LIGHTGRAY|HIGH);
+	bprintf("Node %2d: ",number);
+	attr(GREEN);
+	switch(node.status) {
+		case NODE_WFC:
+			bputs("Waiting for call");
+			break;
+		case NODE_OFFLINE:
+			bputs("Offline");
+			break;
+		case NODE_NETTING:
+			bputs("Networking");
+			break;
+		case NODE_LOGON:
+			bputs("At logon prompt");
+			break;
+		case NODE_EVENT_WAITING:
+			bputs("Waiting for all nodes to become inactive");
+			break;
+		case NODE_EVENT_LIMBO:
+			bprintf("Waiting for node %d to finish external event",node.aux);
+			break;
+		case NODE_EVENT_RUNNING:
+			bputs("Running external event");
+			break;
+		case NODE_NEWUSER:
+			attr(GREEN|HIGH);
+			bputs("New user");
+			attr(GREEN);
+			bputs(" applying for access ");
+			if(!node.connection)
+				bputs("Locally");
+			else if(node.connection==0xffff)
+				bprintf("via telnet");
+			else
+				bprintf("at %ubps",node.connection);
+			break;
+		case NODE_QUIET:
+			if(!SYSOP) {
+				bputs("Waiting for call");
+				break; }
+		case NODE_INUSE:
+			attr(GREEN|HIGH);
+			if(node.misc&NODE_ANON && !SYSOP)
+				bputs("UNKNOWN USER");
+			else
+				bputs(username(node.useron));
+			attr(GREEN);
+			bputs(" ");
+			switch(node.action) {
+				case NODE_MAIN:
+					bputs("at main menu");
+					break;
+				case NODE_RMSG:
+					bputs("reading messages");
+					break;
+				case NODE_RMAL:
+					bputs("reading mail");
+					break;
+				case NODE_RSML:
+					bputs("reading sent mail");
+					break;
+				case NODE_RTXT:
+					bputs("reading text files");
+					break;
+				case NODE_PMSG:
+					bputs("posting message");
+					break;
+				case NODE_SMAL:
+					bputs("sending mail");
+					break;
+				case NODE_AMSG:
+					bputs("posting auto-message");
+					break;
+				case NODE_XTRN:
+					if(!node.aux)
+						bputs("at external program menu");
+					else {
+						bputs("running ");
+						i=node.aux-1;
+						if(i>=(int)total_xtrns || i<0 || !xtrn[i][0])
+							bputs("external program");
+						else
+							bputs(xtrn[i]); }
+					break;
+				case NODE_DFLT:
+					bputs("changing defaults");
+					break;
+				case NODE_XFER:
+					bputs("at transfer menu");
+					break;
+				case NODE_RFSD:
+					bprintf("retrieving from device #%d",node.aux);
+					break;
+				case NODE_DLNG:
+					bprintf("downloading");
+					break;
+				case NODE_ULNG:
+					bputs("uploading");
+					break;
+				case NODE_BXFR:
+					bputs("transferring bidirectional");
+					break;
+				case NODE_LFIL:
+					bputs("listing files");
+					break;
+				case NODE_LOGN:
+					bputs("logging on");
+					break;
+				case NODE_LCHT:
+					bprintf("in local chat with %s",sys_op);
+					break;
+				case NODE_MCHT:
+					if(node.aux) {
+						bprintf("in multinode chat channel %d",node.aux&0xff);
+						if(node.aux&0x1f00)  /* password */
+							outchar('*'); }
 					else
-						bputs(xtrn[i]); }
-                break;
-            case NODE_DFLT:
-                bputs("changing defaults");
-                break;
-            case NODE_XFER:
-                bputs("at transfer menu");
-                break;
-			case NODE_RFSD:
-				bprintf("retrieving from device #%d",node.aux);
-                break;
-            case NODE_DLNG:
-                bprintf("downloading");
-                break;
-            case NODE_ULNG:
-                bputs("uploading");
-                break;
-            case NODE_BXFR:
-				bputs("transferring bidirectional");
-                break;
-            case NODE_LFIL:
-                bputs("listing files");
-                break;
-            case NODE_LOGN:
-                bputs("logging on");
-                break;
-            case NODE_LCHT:
-                bprintf("in local chat with %s",sys_op);
-                break;
-            case NODE_MCHT:
-                if(node.aux) {
-                    bprintf("in multinode chat channel %d",node.aux&0xff);
-					if(node.aux&0x1f00)  /* password */
-						outchar('*'); }
-                else
-                    bputs("in multinode global chat channel");
-                break;
-			case NODE_PAGE:
-				bprintf("paging node %u for private chat",node.aux);
-				break;
-			case NODE_PCHT:
-				bprintf("in private chat with node %u",node.aux);
-				break;
-            case NODE_GCHT:
-                bprintf("chatting with %s",sys_guru);
-                break;
-            case NODE_CHAT:
-                bputs("in chat section");
-                break;
-            case NODE_TQWK:
-                bputs("transferring QWK packet");
-                break;
-            case NODE_SYSP:
-                bputs("performing sysop activities");
-                break;
-            default:
-                bputs(itoa(node.action,tmp,10));
-                break;  }
-        if(!node.connection)
-            bputs(" locally");
-        else
-            bprintf(" at %ubps",node.connection);
-        if(node.action==NODE_DLNG) {
-            if((node.aux/60)>12) {
-                hour=(node.aux/60)-12;
-                strcpy(mer,"pm"); }
-            else {
-                if((node.aux/60)==0)    /* 12 midnite */
-                    hour=12;
-                else hour=node.aux/60;
-                strcpy(mer,"am"); }
-            bprintf(" ETA %02d:%02d %s"
-				,hour,node.aux%60,mer); }
-        break; }
-i=NODE_LOCK;
-if(node.status==NODE_INUSE || SYSOP)
-	i|=NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG;
-if(node.misc&i) {
-    bputs(" (");
-	if(node.misc&(i&NODE_AOFF))
-		outchar('A');
-    if(node.misc&NODE_LOCK)
-		outchar('L');
-	if(node.misc&(i&(NODE_MSGW|NODE_NMSG)))
-		outchar('M');
-	if(node.misc&(i&NODE_POFF))
-		outchar('P');
-	outchar(')'); }
-if(SYSOP && ((node.misc
-    &(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
-    || node.status==NODE_QUIET)) {
-    bputs(" [");
-    if(node.misc&NODE_ANON)
-		outchar('A');
-    if(node.misc&NODE_INTR)
-		outchar('I');
-    if(node.misc&NODE_RRUN)
-		outchar('R');
-    if(node.misc&NODE_UDAT)
-		outchar('U');
-    if(node.status==NODE_QUIET)
-		outchar('Q');
-    if(node.misc&NODE_EVENT)
-		outchar('E');
-    if(node.misc&NODE_DOWN)
-		outchar('D');
-	outchar(']'); }
-if(node.errors && SYSOP) {
-	attr(RED|HIGH|BLINK);
-    bprintf(" %d error%c",node.errors, node.errors>1 ? 's' : '\0' ); }
-CRLF;
+						bputs("in multinode global chat channel");
+					break;
+				case NODE_PAGE:
+					bprintf("paging node %u for private chat",node.aux);
+					break;
+				case NODE_PCHT:
+					bprintf("in private chat with node %u",node.aux);
+					break;
+				case NODE_GCHT:
+					bprintf("chatting with %s",sys_guru);
+					break;
+				case NODE_CHAT:
+					bputs("in chat section");
+					break;
+				case NODE_TQWK:
+					bputs("transferring QWK packet");
+					break;
+				case NODE_SYSP:
+					bputs("performing sysop activities");
+					break;
+				default:
+					bputs(itoa(node.action,tmp,10));
+					break;  }
+			if(!node.connection)
+				bputs(" locally");
+			else if(node.connection==0xffff)
+				bprintf(" via telnet");
+			else
+				bprintf(" at %ubps",node.connection);
+			if(node.action==NODE_DLNG) {
+				if((node.aux/60)>12) {
+					hour=(node.aux/60)-12;
+					strcpy(mer,"pm"); }
+				else {
+					if((node.aux/60)==0)    /* 12 midnite */
+						hour=12;
+					else hour=node.aux/60;
+					strcpy(mer,"am"); }
+				bprintf(" ETA %02d:%02d %s"
+					,hour,node.aux%60,mer); }
+			break; }
+	i=NODE_LOCK;
+	if(node.status==NODE_INUSE || SYSOP)
+		i|=NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG;
+	if(node.misc&i) {
+		bputs(" (");
+		if(node.misc&(i&NODE_AOFF))
+			outchar('A');
+		if(node.misc&NODE_LOCK)
+			outchar('L');
+		if(node.misc&(i&(NODE_MSGW|NODE_NMSG)))
+			outchar('M');
+		if(node.misc&(i&NODE_POFF))
+			outchar('P');
+		outchar(')'); }
+	if(SYSOP && ((node.misc
+		&(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
+		|| node.status==NODE_QUIET)) {
+		bputs(" [");
+		if(node.misc&NODE_ANON)
+			outchar('A');
+		if(node.misc&NODE_INTR)
+			outchar('I');
+		if(node.misc&NODE_RRUN)
+			outchar('R');
+		if(node.misc&NODE_UDAT)
+			outchar('U');
+		if(node.status==NODE_QUIET)
+			outchar('Q');
+		if(node.misc&NODE_EVENT)
+			outchar('E');
+		if(node.misc&NODE_DOWN)
+			outchar('D');
+		outchar(']'); }
+	if(node.errors && SYSOP) {
+		attr(RED|HIGH|BLINK);
+		bprintf(" %d error%c",node.errors, node.errors>1 ? 's' : '\0' ); }
+	CRLF;
 }
 
 /****************************************************************************/
@@ -2199,36 +2528,36 @@ void getsmsg(int usernumber)
 	long length;
 	node_t node;
 
-if(!data_dir[0])
-	return;
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
-if(flength(str)<1L) {
-	return; }
-if((file=nopen(str,O_RDWR))==-1) {
-	bprintf("\7Error opening %s for read/write access\r\n",str);
-	return; }
-length=filelength(file);
-if((buf=MALLOC(length+1))==NULL) {
-	close(file);
-	bprintf("\7Error allocating %u bytes of memory for %s\r\n",length+1,str);
-	return; }
-if(read(file,buf,length)!=length) {
+	if(!data_dir[0])
+		return;
+	sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
+	if(flength(str)<1L) {
+		return; }
+	if((file=nopen(str,O_RDWR))==-1) {
+		bprintf("\7Error opening %s for read/write access\r\n",str);
+		return; }
+	length=filelength(file);
+	if((buf=MALLOC(length+1))==NULL) {
+		close(file);
+		bprintf("\7Error allocating %u bytes of memory for %s\r\n",length+1,str);
+		return; }
+	if(read(file,buf,length)!=length) {
+		close(file);
+		FREE(buf);
+		bprintf("\7Error reading %u bytes from %s\r\n",length,str);
+		return; }
+	chsize(file,0L);
 	close(file);
+	buf[length]=0;
+	getnodedat(node_num,&node,0);
+	if(node.action==NODE_MAIN || node.action==NODE_XFER) {
+		CRLF; }
+	if(node.misc&NODE_MSGW) {
+		getnodedat(node_num,&node,1);
+		node.misc&=~NODE_MSGW;
+		putnodedat(node_num,node); }
+	bputs(buf);
 	FREE(buf);
-	bprintf("\7Error reading %u bytes from %s\r\n",length,str);
-	return; }
-chsize(file,0L);
-close(file);
-buf[length]=0;
-getnodedat(node_num,&node,0);
-if(node.action==NODE_MAIN || node.action==NODE_XFER) {
-	CRLF; }
-if(node.misc&NODE_MSGW) {
-	getnodedat(node_num,&node,1);
-	node.misc&=~NODE_MSGW;
-	putnodedat(node_num,node); }
-bputs(buf);
-FREE(buf);
 }
 
 /****************************************************************************/
@@ -2240,26 +2569,26 @@ void putsmsg(int usernumber, char *strin)
 	int file,i;
     node_t node;
 
-if(!data_dir[0])
-	return;
-sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	bprintf("\7Error opening/creating %s for creat/append access\r\n",str);
-	return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
+	if(!data_dir[0])
+		return;
+	sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber);
+	if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
+		bprintf("\7Error opening/creating %s for creat/append access\r\n",str);
+		return; }
+	i=strlen(strin);
+	if(write(file,strin,i)!=i) {
+		close(file);
+		bprintf("\7Error writing %u bytes to %s\r\n",i,str);
+		return; }
 	close(file);
-	bprintf("\7Error writing %u bytes to %s\r\n",i,str);
-	return; }
-close(file);
-for(i=1;i<=sys_nodes;i++) {		/* flag node if user on that msg waiting */
-	getnodedat(i,&node,0);
-	if(node.useron==usernumber
-		&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
-		&& !(node.misc&NODE_MSGW)) {
-		getnodedat(i,&node,1);
-		node.misc|=NODE_MSGW;
-        putnodedat(i,node); } }
+	for(i=1;i<=sys_nodes;i++) {		/* flag node if user on that msg waiting */
+		getnodedat(i,&node,0);
+		if(node.useron==(ushort)usernumber
+			&& (node.status==NODE_INUSE || node.status==NODE_QUIET)
+			&& !(node.misc&NODE_MSGW)) {
+			getnodedat(i,&node,1);
+			node.misc|=NODE_MSGW;
+			putnodedat(i,node); } }
 }
 
 /****************************************************************************/
@@ -2272,34 +2601,34 @@ void getnmsg(void)
 	long length;
 	node_t thisnode;
 
-if(!data_dir[0])
-	return;
-getnodedat(node_num,&thisnode,1);
-thisnode.misc&=~NODE_NMSG;			/* clear the NMSG flag */
-putnodedat(node_num,thisnode);
-
-sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,node_num);
-if(flength(str)<1L) {
-	return; }
-if((file=nopen(str,O_RDWR))==-1) {
-	printf("Couldn't open %s for read/write\r\n",str);
-	return; }
-length=filelength(file);
-if((buf=MALLOC(length+1))==NULL) {
-	close(file);
-	printf("Couldn't allocate %lu bytes for %s\r\n",length+1,str);
-	return; }
-if(read(file,buf,length)!=length) {
+	if(!data_dir[0])
+		return;
+	getnodedat(node_num,&thisnode,1);
+	thisnode.misc&=~NODE_NMSG;			/* clear the NMSG flag */
+	putnodedat(node_num,thisnode);
+
+	sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,node_num);
+	if(flength(str)<1L) {
+		return; }
+	if((file=nopen(str,O_RDWR))==-1) {
+		printf("Couldn't open %s for read/write\r\n",str);
+		return; }
+	length=filelength(file);
+	if((buf=MALLOC(length+1))==NULL) {
+		close(file);
+		printf("Couldn't allocate %lu bytes for %s\r\n",length+1,str);
+		return; }
+	if(read(file,buf,length)!=length) {
+		close(file);
+		FREE(buf);
+		printf("Couldn't read %lu bytes from %s\r\n",length,str);
+		return; }
+	chsize(file,0L);
 	close(file);
+	buf[length]=0;
+
+	bputs(buf);
 	FREE(buf);
-	printf("Couldn't read %lu bytes from %s\r\n",length,str);
-	return; }
-chsize(file,0L);
-close(file);
-buf[length]=0;
-
-bputs(buf);
-FREE(buf);
 }
 
 /****************************************************************************/
@@ -2311,24 +2640,24 @@ void putnmsg(int num, char *strin)
 	int file,i;
     node_t node;
 
-if(!data_dir[0])
-	return;
-sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,num);
-if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
-	printf("Couldn't open %s for append\r\n",str);
-	return; }
-i=strlen(strin);
-if(write(file,strin,i)!=i) {
+	if(!data_dir[0])
+		return;
+	sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,num);
+	if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
+		printf("Couldn't open %s for append\r\n",str);
+		return; }
+	i=strlen(strin);
+	if(write(file,strin,i)!=i) {
+		close(file);
+		printf("Error writing %u bytes to %s\r\n",i,str);
+		return; }
 	close(file);
-	printf("Error writing %u bytes to %s\r\n",i,str);
-	return; }
-close(file);
-getnodedat(num,&node,0);
-if((node.status==NODE_INUSE || node.status==NODE_QUIET)
-	&& !(node.misc&NODE_NMSG)) {
-	getnodedat(num,&node,1);
-	node.misc|=NODE_NMSG;
-	putnodedat(num,node); }
+	getnodedat(num,&node,0);
+	if((node.status==NODE_INUSE || node.status==NODE_QUIET)
+		&& !(node.misc&NODE_NMSG)) {
+		getnodedat(num,&node,1);
+		node.misc|=NODE_NMSG;
+		putnodedat(num,node); }
 }
 
 /****************************************************************************/
@@ -2341,23 +2670,23 @@ int whos_online(char listself)
 	int i,j;
 	node_t node;
 
-if(!ctrl_dir[0])
-	return(0);
-CRLF;
-for(j=0,i=1;i<=sys_nodes;i++) {
-	getnodedat(i,&node,0);
-	if(i==node_num) {
-		if(listself)
+	if(!ctrl_dir[0])
+		return(0);
+	CRLF;
+	for(j=0,i=1;i<=sys_nodes;i++) {
+		getnodedat(i,&node,0);
+		if(i==node_num) {
+			if(listself)
+				printnodedat(i,node);
+			continue; }
+		if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
 			printnodedat(i,node);
-		continue; }
-	if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
-		printnodedat(i,node);
-		if(!lastnodemsg)
-			lastnodemsg=i;
-		j++; } }
-if(!j)
-	bputs("\1nNo other active nodes.\r\n");
-return(j);
+			if(!lastnodemsg)
+				lastnodemsg=i;
+			j++; } }
+	if(!j)
+		bputs("\1nNo other active nodes.\r\n");
+	return(j);
 }
 
 /****************************************************************************/
@@ -2365,71 +2694,72 @@ return(j);
 /****************************************************************************/
 void nodemsg(void)
 {
-	char	str[256],line[256],buf[512];
-	int 	i,j;
+	char	line[256],buf[512];
+	int 	i;
 	node_t	thisnode;
 	node_t 	node;
 
-if(!ctrl_dir[0])
-	return;
-if(strchr(user_rest,'C')) {
-	bputs("You cannot send messages.\r\n");
-	return; }
-getnodedat(node_num,&thisnode,0);
-wordwrap[0]=0;
-if(lastnodemsg) {
-	getnodedat(lastnodemsg,&node,0);
-	if(node.status!=NODE_INUSE)
-		lastnodemsg=0; }
-if(!whos_online(0))
-	return;
-bprintf("\r\nngNumber of node to send message to, whAngll, "
-	"or whQnguit [%u]: wh",lastnodemsg);
-i=getkeys("QA",sys_nodes);
-if(i==-1)
-	return;
-if(i&0x8000 || !i) {
-	if(!i)
-		i=lastnodemsg;
-	else {
-		i^=0x8000;
-		lastnodemsg=i; }
-	if(!i || i>sys_nodes)
+	if(!ctrl_dir[0])
 		return;
-	getnodedat(i,&node,0);
-	if(node.status!=NODE_INUSE && !SYSOP)
-		bprintf("\r\n_whNode %d is not in use.\r\n",i);
-	else if(i==node_num)
-		bputs("\r\nThere's no need to send a message to yourself.\r\n");
-	else if(node.misc&NODE_POFF && !SYSOP)
-		bprintf("\r\nrhiDon't bug %s.n\r\n"
-			,node.misc&NODE_ANON ? "UNKNOWN USER"
-			: username(node.useron));
-	else {
-		bputs("_yhMessage: ");
+	if(strchr(user_rest,'C')) {
+		bputs("You cannot send messages.\r\n");
+		return; }
+	getnodedat(node_num,&thisnode,0);
+	wordwrap[0]=0;
+	if(lastnodemsg) {
+		getnodedat(lastnodemsg,&node,0);
+		if(node.status!=NODE_INUSE)
+			lastnodemsg=0; }
+	if(!whos_online(0))
+		return;
+	bprintf("\r\n\1n\1gNumber of node to send message to, \1w\1hA\1n\1gll, "
+		"or \1w\1hQ\1n\1guit [%u]: \1w\1h",lastnodemsg);
+	i=getkeys("QA",sys_nodes);
+	if(i==-1)
+		return;
+	if(i&0x8000 || !i) {
+		if(!i)
+			i=lastnodemsg;
+		else {
+			i^=0x8000;
+			lastnodemsg=i; }
+		if(!i || i>sys_nodes)
+			return;
+		getnodedat(i,&node,0);
+		if(node.status!=NODE_INUSE && !SYSOP)
+			bprintf("\r\n\1_\1w\1hNode %d is not in use.\r\n",i);
+		else if(i==node_num)
+			bputs("\r\nThere's no need to send a message to yourself.\r\n");
+		else if(node.misc&NODE_POFF && !SYSOP)
+			bprintf("\r\n\1r\1h\1iDon't bug %s.\1n\r\n"
+				,node.misc&NODE_ANON ? "UNKNOWN USER"
+				: username(node.useron));
+		else {
+			bputs("\1_\1y\1hMessage: ");
+			if(!getstr(line,70,K_LINE))
+				return;
+			sprintf(buf
+				,"\7\1_\1w\1hNode %2d: \1g%s\1n\1g sent you a message:\r\n"
+				"\1w\1h\0014%s\1n\r\n"
+				,node_num
+				,thisnode.misc&NODE_ANON ? "UNKNOWN USER" : user_name,line);
+			putnmsg(i,buf); } }
+	else if(i=='A') {
+		bputs("\1_\1y\1hMessage: ");
 		if(!getstr(line,70,K_LINE))
 			return;
 		sprintf(buf
-			,"\7_whNode %2d: g%sng sent you a message:\r\nwh4%sn\r\n"
+			,"\7\1_\1w\1hNode %2d: \1g%s\1n\1g sent all nodes a message:\r\n"
+				"\1w\1h\0014%s\1n\r\n"
 			,node_num
 			,thisnode.misc&NODE_ANON ? "UNKNOWN USER" : user_name,line);
-		putnmsg(i,buf); } }
-else if(i=='A') {
-	bputs("_yhMessage: ");
-	if(!getstr(line,70,K_LINE))
-		return;
-	sprintf(buf
-		,"\7_whNode %2d: g%sng sent all nodes a message:\r\n"
-			"wh4%sn\r\n"
-		,node_num
-		,thisnode.misc&NODE_ANON ? "UNKNOWN USER" : user_name,line);
-	for(i=1;i<=sys_nodes;i++) {
-		if(i==node_num)
-			continue;
-		getnodedat(i,&node,0);
-		if((node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET))
-			&& (SYSOP || !(node.misc&NODE_POFF)))
-			putnmsg(i,buf); } }
+		for(i=1;i<=sys_nodes;i++) {
+			if(i==node_num)
+				continue;
+			getnodedat(i,&node,0);
+			if((node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET))
+				&& (SYSOP || !(node.misc&NODE_POFF)))
+				putnmsg(i,buf); } }
 
 }
 
@@ -2439,9 +2769,9 @@ else if(i=='A') {
 void ungetkey(char ch)
 {
 
-keybuf[keybuftop++]=ch;
-if(keybuftop==KEY_BUFSIZE)
-	keybuftop=0;
+	keybuf[keybuftop++]=ch;
+	if(keybuftop==KEY_BUFSIZE)
+		keybuftop=0;
 }
 
 #ifdef __SC__					/* Missing from Symantec RTL */
diff --git a/xtrn/sdk/xsdk.h b/xtrn/sdk/xsdk.h
index 592d24c1ca..20af4f8491 100644
--- a/xtrn/sdk/xsdk.h
+++ b/xtrn/sdk/xsdk.h
@@ -1,42 +1,54 @@
-/* XSDK.H */
+/* xsdk.h */
+
+/* Synchronet XSDK function prototypes */
+
+/* $Id$ */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
+ *																			*
+ * This library is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU Lesser General Public License		*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
+ *																			*
+ * Anonymous FTP access to the most recent released source is available at	*
+ * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
+ *																			*
+ * Anonymous CVS access to the development source and modification history	*
+ * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
+ *     (just hit return, no password is necessary)							*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout xtrn	*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * You are encouraged to submit any modifications (preferably in Unix diff	*
+ * format) via e-mail to mods@synchro.net									*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
+
 
 #ifndef _XSDK_H
 #define _XSDK_H
 
-/****************************************************************************/
-/*			Synchronet External Program Software Development Kit			*/
-/*							1993 Digital Dynamics							*/
-/****************************************************************************/
-
-/****************************************************************************/
-/* This source code file is public domain and may be modified, compiled 	*/
-/* distributed, or used in any way, in part or whole for any purposes		*/
-/* without the consent or notification of Digital Dynamics. 				*/
-/*																			*/
-/* We only request that you display to the user, at some point, in your 	*/
-/* program the character "XSDK" and the version number.                     */
-/* example: bprintf("XSDK v%s",xsdk_ver);                                   */
-/****************************************************************************/
-
-/****************************************************************************/
-/* The source code for two external programs developed by Digital Dynamics	*/
-/* using XSDK (Synchronet Blackjack [SBJ] and Synchronet BBS List [SBL])	*/
-/* are available to the public domain as examples of how to implement the	*/
-/* functions and variables included in this software development kit.		*/
-/****************************************************************************/
-
-
-/****************************************************/
-/* For use with Borland/Turbo C and C++ compilers.	*/
-/* Tabstop set to 4.								*/
-/****************************************************/
-
 /*********************************************/
 /* Standard Borland/Turbo C/C++ Header Files */
 /*********************************************/
 #include <io.h>
 #include <dos.h>
+#ifdef _WIN32
+#include <windows.h>
+#else
 #include <bios.h>
+#endif
 #include <time.h>
 #include <ctype.h>
 #include <stdio.h>
@@ -134,12 +146,12 @@ char noyes(char *str);
 	- If the local or remote user has struck a key, this function returns the
 	  key, otherwise it returns 0
 	- Does not wait for a keystroke */
-char inkey(int mode);
+char inkey(long mode);
 
 /* Get a Key
 	- Waits for the local or remote user to hit a valid key
 	- See K_* constants in XSDKDEFS.H for possible values of mode */
-char getkey(int mode);
+char getkey(long mode);
 
 /* Get One of these Keys or a Number
 	- Waits for the user to hit a valid key or if max is non-zero, then enter
@@ -159,7 +171,7 @@ int  getnum(int max);
 /* Change Attribute
 	- Sends ANSI escape sequences (if user supports ANSI) to change color
 	- Valid color bits are defined in INCLUDE\CONIO.H */
-void attr(char atr);
+void attr(int atr);
 
 /* Clear Screen
 	- Clears local and remote screen (using ANSI if appropriate)
@@ -196,11 +208,11 @@ void printfile(char *str);
 	- Waits for the user to enter a string
 	- maxlen is the maximum length of the string
 	- See K_* constants in XSDKDEFS.H for possible values of mode */
-int  getstr(char *str, int maxlen, int mode);
+int  getstr(char *str, size_t maxlen, long mode);
 
 /* Redraw String
 	- Redisplays a string, mainly called by getstr() */
-void redrwstr(char *strin, int i, int l, char mode);
+void redrwstr(char *strin, int i, int l, long mode);
 
 /* Strip Invalid Ctrl-A codes */
 char stripattr(char *strin);
@@ -224,16 +236,16 @@ char *ultoac(ulong l, char *string);
 ulong ahtoul(char *str);
 
 /* Display status of node */
-void printnodedat(uchar number, node_t node);
+void printnodedat(int number, node_t node);
 
 /* Checks to see if this node has been interrupted or any messages waiting */
 void nodesync(void);
 
 /* Writes the node information to disk */
-void putnodedat(uchar number, node_t node);
+void putnodedat(int number, node_t node);
 
 /* Reads the node information from disk */
-void getnodedat(uchar number, node_t *node, char lockit);
+void getnodedat(int number, node_t *node, char lockit);
 
 /* Writes a short message (telegram) for specified user number */
 void putsmsg(int usernumber, char *strin);
@@ -259,12 +271,19 @@ void ungetkey(char ch);
 /* Check to see if the user has hung-up */
 void checkline(void);
 
+#ifndef _WIN32
 /* Wait a specific number of milliseconds */
 void mswait(int ms);
+#endif
 
 /* Display a line (with ctrl-A codes) centered on the screen */
 void center(char *str);
 
+#ifdef _MSC_VER
+int lock(int file, long offset, int size);
+int unlock(int file, long offset, int size);
+#endif
+
 #ifdef __cplusplus
 	}
 #endif
diff --git a/xtrn/sdk/xsdkdefs.h b/xtrn/sdk/xsdkdefs.h
index 9f0cb632d2..188e76fc02 100644
--- a/xtrn/sdk/xsdkdefs.h
+++ b/xtrn/sdk/xsdkdefs.h
@@ -1,4 +1,39 @@
-/* XSDKDEFS.H */
+/* xsdkdefs.h */
+
+/* Synchronet XSDK constants, macros, and type definitions */
+
+/* $Id$ */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
+ *																			*
+ * This library is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU Lesser General Public License		*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
+ *																			*
+ * Anonymous FTP access to the most recent released source is available at	*
+ * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
+ *																			*
+ * Anonymous CVS access to the development source and modification history	*
+ * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
+ *     (just hit return, no password is necessary)							*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout xtrn	*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * You are encouraged to submit any modifications (preferably in Unix diff	*
+ * format) via e-mail to mods@synchro.net									*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
 
 #ifndef _XSDKDEFS_H
 #define _XSDKDEFS_H
@@ -6,6 +41,10 @@
 /**********/
 /* Macros */
 /**********/
+
+#ifdef _WIN32
+#define mswait	Sleep		/* Win32 equivalent */
+#endif
 									/* Control characters */
 #define STX 	0x02				/* Start of text			^B	*/
 #define ETX 	0x03				/* End of text				^C	*/
@@ -146,10 +185,8 @@ enum {								/* Node Action */
 #define NM_LOWPRIO	(1<<15) /* Always use low priority input			*/
 #define NM_7BITONLY (1L<<16) /* Except 7-bit input only (E71 terminals)  */
 
-#ifdef __WATCOMC__
-
-	#if !defined(__COLORS)
-	#define __COLORS
+#if !defined(__COLORS)
+#define __COLORS
 
 	enum COLORS {
 		BLACK,			/* dark colors */
@@ -169,9 +206,14 @@ enum {								/* Node Action */
 		YELLOW,
 		WHITE
 	};
-	#endif
+#endif
+
+#ifndef BLINK
+#define BLINK		128 /* blink bit */
+#endif
+
+#ifdef __WATCOMC__
 
-	#define BLINK		128 /* blink bit */
 
 	#define ffblk find_t
     #define findfirst(x,y,z) _dos_findfirst(x,z,y)
@@ -179,6 +221,27 @@ enum {								/* Node Action */
 	#pragma aux mswait "_*"
 #endif
 
+/* Windows Types */
+#ifndef BYTE
+#define BYTE	uchar
+#endif
+#ifndef WORD
+#define WORD	ushort
+#endif
+#ifndef DWORD
+#define DWORD	ulong
+#endif
+#ifndef BOOL
+#define BOOL	int
+#endif
+#ifndef TRUE
+#define TRUE	1
+#define FALSE	0
+#endif
+#ifndef HANDLE
+#define HANDLE	void*
+#endif
+
 /****************************************************************************/
 /* MALLOC/FREE Macros for various compilers and environments				*/
 /* MALLOC is used for allocations of 64k or less							*/
@@ -186,8 +249,13 @@ enum {								/* Node Action */
 /* LMALLOC is used for allocations of possibly larger than 64k				*/
 /* LFREE is used to free buffers allocated with LMALLOC 					*/
 /* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer 	*/
+/* FAR16 is used to create a far (32-bit) pointer in 16-bit compilers		*/
+/* HUGE16 is used to create a huge (32-bit) pointer in 16-bit compilers 	*/
 /****************************************************************************/
 #if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
+	#define __16BIT__
+	#define HUGE16 huge
+	#define FAR16 far
 	#if defined(__TURBOC__)
 		#define REALLOC(x,y) farrealloc(x,y)
 		#define LMALLOC(x) farmalloc(x)
@@ -208,6 +276,8 @@ enum {								/* Node Action */
 		#define FREE free
 	#endif
 #else		/* 32-bit Compiler or Small Memory Model */
+	#define HUGE16
+	#define FAR16
 	#define REALLOC realloc
 	#define LMALLOC malloc
 	#define MALLOC malloc
@@ -235,15 +305,24 @@ enum {								/* Node Action */
 /* Typedefs */
 /************/
 
+#ifdef _WIN32	/* necessary for compatibility with SBBS v2 */
+#pragma pack(push)
+#pragma pack(1)
+#endif
+
 typedef struct {						/* Node information kept in NODE.DAB */
 	uchar	status,						/* Current Status of Node */
 			errors,						/* Number of Critical Errors */
 			action;						/* Action User is doing on Node */
-	uint	useron,						/* User on Node */
+	ushort	useron,						/* User on Node */
 			connection,					/* Connection rate of Node */
 			misc,						/* Miscellaneous bits for node */
 			aux;						/* Auxillary word for node */
 	ulong	extaux;						/* Extended aux dword for node */
             } node_t;
 
+#ifdef _WIN32
+#pragma pack(pop)		/* original packing */
+#endif
+
 #endif	/* Don't add anything after this endif */
diff --git a/xtrn/sdk/xsdkvars.c b/xtrn/sdk/xsdkvars.c
index 68182bdf75..b041e61ef1 100644
--- a/xtrn/sdk/xsdkvars.c
+++ b/xtrn/sdk/xsdkvars.c
@@ -1,4 +1,39 @@
-/* XSDKVARS.C */
+/* xsdkvars.c */
+
+/* Synchronet XSDK global variables */
+
+/* $Id$ */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
+ *																			*
+ * This library is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU Lesser General Public License		*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
+ *																			*
+ * Anonymous FTP access to the most recent released source is available at	*
+ * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
+ *																			*
+ * Anonymous CVS access to the development source and modification history	*
+ * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
+ *     (just hit return, no password is necessary)							*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout xtrn	*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * You are encouraged to submit any modifications (preferably in Unix diff	*
+ * format) via e-mail to mods@synchro.net									*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
 
 #include <time.h>
 #include <stdio.h>
@@ -84,11 +119,11 @@ GLOBAL char     latr;           /* Starting attribute of line buffer */
 GLOBAL uint 	inDV;			/* DESQview version if running under DV */
 GLOBAL int		keybuftop,keybufbot;	/* Keyboard input buffer pointers */
 GLOBAL char     keybuf[KEY_BUFSIZE];    /* Keyboard input buffer */
-GLOBAL uint far *msr;			/* Last modem status register contents */
+GLOBAL uint FAR16 *msr;			/* Last modem status register contents */
 GLOBAL char 	**xtrn; 		/* List of external program names */
 GLOBAL uint 	total_xtrns;	/* Total number of external programs */
 GLOBAL uchar	lastnodemsg;	/* Last node to send a message to */
 GLOBAL uchar	name_len;		/* Length of name field in NAME.DAT */
 GLOBAL char 	aborted;		/* Aborted flag - if ctrl-c hit */
-GLOBAL uint 	sysop_level;	/* Sysop Level */
+GLOBAL char 	sysop_level;	/* Sysop Level */
 GLOBAL FILE 	*con_fp;		/* Console file pointer (stdout/stderr) */
-- 
GitLab