diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp
index 03819da5227f1972c5f1620763f48839201f6333..9a759c0791e65eaecd3ba2a3891e3f153ade3ceb 100644
--- a/src/sbbs3/con_out.cpp
+++ b/src/sbbs3/con_out.cpp
@@ -84,8 +84,8 @@ int sbbs_t::bputs(const char *str)
 	return(l);
 }
 
-/* Perform PETSCII terminal output translation */
-static unsigned char petscii(unsigned char ch)
+/* Perform PETSCII terminal output translation (from ASCII/CP437) */
+unsigned char cp437_to_petscii(unsigned char ch)
 {
 	if(isalpha(ch))
 		return ch ^ 0x20;	/* swap upper/lower case */
@@ -151,13 +151,92 @@ static unsigned char petscii(unsigned char ch)
 		case 207:
 		case 208:
 		case 193:		return '\xB1';
-
 	}
 	if(ch&0x80)
 		return exascii_to_ascii_char(ch);
 	return ch;
 }
 
+/* Perform PETSCII conversion to ANSI-BBS/CP437 */
+int sbbs_t::petscii_to_ansibbs(unsigned char ch)
+{
+	if((ch&0xe0) == 0xc0)	/* "Codes $60-$7F are, actually, copies of codes $C0-$DF" */
+		ch = 0x60 | (ch&0x1f);
+	if(isalpha(ch))
+		return outchar(ch ^ 0x20);	/* swap upper/lower case */
+	switch(ch) {
+		case '\r':					newline();		break;
+		case PETSCII_HOME:			cursor_home();	break;
+		case PETSCII_CLEAR:			return CLS;
+		case PETSCII_DELETE:		backspace();	break;
+		case PETSCII_LEFT:			cursor_left();	break;
+		case PETSCII_RIGHT:			cursor_right();	break;
+		case PETSCII_UP:			cursor_up();	break;
+		case PETSCII_DOWN:			cursor_down();	break;
+
+		case PETSCII_BRITPOUND:		return outchar((char)156);
+		case PETSCII_CHECKMARK:		return outchar((char)251);
+		case PETSCII_CHECKERBRD:
+		case PETSCII_LIGHTHASH:		return outchar((char)176);
+		case 0x7e:
+		case PETSCII_MEDIUMHASH:	return outchar((char)177);
+		case PETSCII_HEAVYHASH:		return outchar((char)178);
+		case PETSCII_SOLID:			return outchar((char)219);
+		case PETSCII_BOTTOMHALF:	return outchar((char)220);
+		case PETSCII_LEFTHALF:		return outchar((char)221);
+		case PETSCII_RIGHTHALF:		return outchar((char)222);
+		case PETSCII_TOPHALF:		return outchar((char)223);
+		case PETSCII_LWRLFTBOX:
+		case PETSCII_LWRRHTBOX:
+		case PETSCII_UPRRHTBOX:
+		case PETSCII_UPRLFTBOX:		return outchar((char)254);
+
+		/* Line drawing chars */
+		case 0x7D:
+		case PETSCII_VERTLINE:		return outchar((char)179);
+		case PETSCII_HORZLINE:		return outchar((char)196);
+		case 0x7B:
+		case PETSCII_CROSS:			return outchar((char)197);
+		case (uchar)'\xBD':			return outchar((char)217);
+		case (uchar)'\xB0':			return outchar((char)218);
+		case (uchar)'\xAE':			return outchar((char)191);
+		case (uchar)'\xAD':			return outchar((char)192);
+		case (uchar)'\xAB':			return outchar((char)195);
+		case (uchar)'\xB3':			return outchar((char)180);
+		case (uchar)'\xB2':			return outchar((char)194);
+		case (uchar)'\xB1':			return outchar((char)193);
+		case PETSCII_BLACK:			return attr(BLACK);
+		case PETSCII_WHITE:			return attr(WHITE);
+		case PETSCII_RED:			return attr(RED);
+		case PETSCII_GREEN:			return attr(GREEN);
+		case PETSCII_BLUE:			return attr(BLUE);
+		case PETSCII_ORANGE:		return attr(MAGENTA);
+		case PETSCII_BROWN:			return attr(BROWN);
+		case PETSCII_YELLOW:		return attr(YELLOW);
+		case PETSCII_CYAN:			return attr(LIGHTCYAN);
+		case PETSCII_LIGHTRED:		return attr(LIGHTRED);
+		case PETSCII_DARKGRAY:		return attr(DARKGRAY);
+		case PETSCII_MEDIUMGRAY:	return attr(CYAN);
+		case PETSCII_LIGHTGREEN:	return attr(LIGHTGREEN);
+		case PETSCII_LIGHTBLUE:		return attr(LIGHTBLUE);
+		case PETSCII_LIGHTGRAY:		return attr(LIGHTGRAY);
+		case PETSCII_PURPLE:		return attr(LIGHTMAGENTA);
+		case PETSCII_REVERSE_ON:	return attr((curatr&0x07) << 4);
+		case PETSCII_REVERSE_OFF:	return attr(curatr >> 4);
+		case PETSCII_FLASH_ON:		return attr(curatr | BLINK);
+		case PETSCII_FLASH_OFF:		return attr(curatr & ~BLINK);
+		default:					
+			if(ch&0x80)				return bprintf("#%3d", ch);
+			return outchar(ch);
+		case PETSCII_UPPERLOWER:
+		case PETSCII_UPPERGRFX:
+			/* Do nothing */
+			return 0;
+	}
+	return 0;
+}
+
+
 /****************************************************************************/
 /* Raw put string (remotely)												*/
 /* Performs Telnet IAC escaping												*/
@@ -176,9 +255,9 @@ int sbbs_t::rputs(const char *str, size_t len)
 	for(l=0;l<len && online;l++) {
 		if(str[l]==(char)TELNET_IAC && !(telnet_mode&TELNET_MODE_OFF))
 			outcom(TELNET_IAC);	/* Must escape Telnet IAC char (255) */
-		char ch = str[l];
+		uchar ch = str[l];
 		if(term&PETSCII)
-			ch = petscii(ch);
+			ch = cp437_to_petscii(ch);
 		if(outcom(ch)!=0)
 			break;
 		if(lbuflen<LINE_BUFSIZE)
@@ -257,7 +336,7 @@ long sbbs_t::term_supports(long cmp_flags)
 /* Performs column counting, line counting, and auto-pausing				*/
 /* Performs saveline buffering (for restoreline)							*/
 /****************************************************************************/
-void sbbs_t::outchar(char ch)
+int sbbs_t::outchar(char ch)
 {
 	/*
 	 * outchar_esc values:
@@ -271,7 +350,7 @@ void sbbs_t::outchar(char ch)
      */
 
 	if(console&CON_ECHO_OFF)
-		return;
+		return 0;
 	if(ch==ESC && outchar_esc < 4)
 		outchar_esc=1;
 	else if(outchar_esc==1) {
@@ -349,7 +428,7 @@ void sbbs_t::outchar(char ch)
 			if(ch==(char)TELNET_IAC && !(telnet_mode&TELNET_MODE_OFF))
 				outcom(TELNET_IAC);	/* Must escape Telnet IAC char (255) */
 			if(term&PETSCII) {
-				char pet = petscii(ch);
+				uchar pet = cp437_to_petscii(ch);
 				if(pet == PETSCII_SOLID)
 					outcom(PETSCII_REVERSE_ON);
 				outcom(pet);
@@ -404,6 +483,7 @@ void sbbs_t::outchar(char ch)
 		lncntr=0;
 		pause();
 	}
+	return 0;
 }
 
 void sbbs_t::center(char *instr)
@@ -803,7 +883,7 @@ void sbbs_t::ctrl_a(char x)
 /****************************************************************************/
 /* Sends terminal control codes to change remote terminal colors/attributes */
 /****************************************************************************/
-void sbbs_t::attr(int atr)
+int sbbs_t::attr(int atr)
 {
 	char	str[16];
 	int		newatr = atr;
@@ -873,6 +953,7 @@ void sbbs_t::attr(int atr)
 	else if(term&ANSI)
 		rputs(ansi(newatr,curatr,str));
 	curatr=newatr;
+	return 0;
 }
 
 /****************************************************************************/
diff --git a/src/sbbs3/download.cpp b/src/sbbs3/download.cpp
index fa64c0fd33de5dade812756c0f35f73703934d2b..cf6fd1ba3d7186dcb806bb4acf2e86e932e39a57 100644
--- a/src/sbbs3/download.cpp
+++ b/src/sbbs3/download.cpp
@@ -226,12 +226,12 @@ int sbbs_t::protocol(prot_t* prot, enum XFER_TYPE type
 	/* enable telnet binary transmission in both directions */
 	request_telnet_opt(TELNET_DO,TELNET_BINARY_TX);
 	request_telnet_opt(TELNET_WILL,TELNET_BINARY_TX);
-	ex_mode=0;
+	ex_mode = EX_BIN;
 	if(prot->misc&PROT_NATIVE)
 		ex_mode|=EX_NATIVE;
 #ifdef __unix__		/* file xfer progs must use stdio on Unix */
 	if(!(prot->misc&PROT_SOCKET))
-		ex_mode|=(EX_STDIO|EX_BIN);
+		ex_mode|=EX_STDIO;
 #endif
 
 	i=external(cmdline,ex_mode,p);
diff --git a/src/sbbs3/prntfile.cpp b/src/sbbs3/prntfile.cpp
index 28c7a2089394b9b6f9dbc33895ea4b537ed8a72b..d0fa16543e4eb0c58907b3e385914ba044270f5a 100644
--- a/src/sbbs3/prntfile.cpp
+++ b/src/sbbs3/prntfile.cpp
@@ -43,32 +43,29 @@
 /* for pauses, aborts and ANSI. 'str' is the path of the file to print      */
 /* Called from functions menu and text_sec                                  */
 /****************************************************************************/
-bool sbbs_t::printfile(char *str, long mode)
+bool sbbs_t::printfile(const char* fname, long mode)
 {
 	char* buf;
+	char fpath[MAX_PATH+1];
 	char* p;
 	int file;
-	BOOL wip=FALSE,rip=FALSE,html=FALSE;
+	BOOL rip=FALSE;
 	long l,length,savcon=console;
 	FILE *stream;
 
-	p=strrchr(str,'.');
+	SAFECOPY(fpath, fname);
+	fexistcase(fpath);
+	p=getfext(fpath);
 	if(p!=NULL) {
-		if(stricmp(p,".wip")==0) {
-			wip=TRUE;
-			mode|=P_NOPAUSE;
-		}
-		else if(stricmp(p,".rip")==0) {
+		if(stricmp(p,".rip")==0) {
 			rip=TRUE;
 			mode|=P_NOPAUSE;
-		}
-		else if(stricmp(p,".html")==0)  {
-			html=TRUE;
-			mode|=(P_HTML|P_NOPAUSE);
+		} else if(stricmp(p, ".seq") == 0) {
+			mode |= P_PETSCII;
 		}
 	}
 
-	if(mode&P_NOABORT || wip || rip || html) {
+	if(mode&P_NOABORT || rip) {
 		if(online==ON_REMOTE && console&CON_R_ECHO) {
 			rioctl(IOCM|ABORT);
 			rioctl(IOCS|ABORT); 
@@ -76,17 +73,16 @@ bool sbbs_t::printfile(char *str, long mode)
 		sys_status&=~SS_ABORT; 
 	}
 
-	if(!(mode&P_NOCRLF) && !tos && !wip && !rip && !html) {
+	if(!(mode&P_NOCRLF) && !tos && !rip) {
 		CRLF;
 	}
 
-	fexistcase(str);
-	if((stream=fnopen(&file,str,O_RDONLY|O_DENYNONE))==NULL) {
+	if((stream=fnopen(&file,fpath,O_RDONLY|O_DENYNONE))==NULL) {
 		if(!(mode&P_NOERROR)) {
 			lprintf(LOG_NOTICE,"!Error %d (%s) opening: %s"
-				,errno,strerror(errno),str);
+				,errno,strerror(errno),fpath);
 			bputs(text[FileNotFound]);
-			if(SYSOP) bputs(str);
+			if(SYSOP) bputs(fpath);
 			CRLF;
 		}
 		return false; 
@@ -95,25 +91,25 @@ bool sbbs_t::printfile(char *str, long mode)
 	length=(long)filelength(file);
 	if(length<0) {
 		fclose(stream);
-		errormsg(WHERE,ERR_CHK,str,length);
+		errormsg(WHERE,ERR_CHK,fpath,length);
 		return false;
 	}
 	if((buf=(char*)malloc(length+1L))==NULL) {
 		fclose(stream);
-		errormsg(WHERE,ERR_ALLOC,str,length+1L);
+		errormsg(WHERE,ERR_ALLOC,fpath,length+1L);
 		return false; 
 	}
 	l=lread(file,buf,length);
 	fclose(stream);
 	if(l!=length)
-		errormsg(WHERE,ERR_READ,str,length);
+		errormsg(WHERE,ERR_READ,fpath,length);
 	else {
 		buf[l]=0;
 		putmsg(buf,mode);
 	}
 	free(buf); 
 
-	if((mode&P_NOABORT || wip || rip || html) && online==ON_REMOTE) {
+	if((mode&P_NOABORT || rip) && online==ON_REMOTE) {
 		SYNC;
 		rioctl(IOSM|ABORT); 
 	}
@@ -123,13 +119,16 @@ bool sbbs_t::printfile(char *str, long mode)
 	return true;
 }
 
-bool sbbs_t::printtail(char *str, int lines, long mode)
+bool sbbs_t::printtail(const char* fname, int lines, long mode)
 {
 	char*	buf;
+	char	fpath[MAX_PATH+1];
 	char*	p;
 	int		file,cur=0;
 	long	length,l;
 
+	SAFECOPY(fpath, fname);
+	fexistcase(fpath);
 	if(mode&P_NOABORT) {
 		if(online==ON_REMOTE) {
 			rioctl(IOCM|ABORT);
@@ -140,13 +139,12 @@ bool sbbs_t::printtail(char *str, int lines, long mode)
 	if(!tos) {
 		CRLF; 
 	}
-	fexistcase(str);
-	if((file=nopen(str,O_RDONLY|O_DENYNONE))==-1) {
+	if((file=nopen(fpath,O_RDONLY|O_DENYNONE))==-1) {
 		if(!(mode&P_NOERROR)) {
 			lprintf(LOG_NOTICE,"!Error %d (%s) opening: %s"
-				,errno,strerror(errno),str);
+				,errno,strerror(errno),fpath);
 			bputs(text[FileNotFound]);
-			if(SYSOP) bputs(str);
+			if(SYSOP) bputs(fpath);
 			CRLF;
 		}
 		return false; 
@@ -154,18 +152,18 @@ bool sbbs_t::printtail(char *str, int lines, long mode)
 	length=(long)filelength(file);
 	if(length<0) {
 		close(file);
-		errormsg(WHERE,ERR_CHK,str,length);
+		errormsg(WHERE,ERR_CHK,fpath,length);
 		return false;
 	}
 	if((buf=(char*)malloc(length+1L))==NULL) {
 		close(file);
-		errormsg(WHERE,ERR_ALLOC,str,length+1L);
+		errormsg(WHERE,ERR_ALLOC,fpath,length+1L);
 		return false; 
 	}
 	l=lread(file,buf,length);
 	close(file);
 	if(l!=length)
-		errormsg(WHERE,ERR_READ,str,length);
+		errormsg(WHERE,ERR_READ,fpath,length);
 	else {
 		buf[l]=0;
 		p=(buf+l)-1;
diff --git a/src/sbbs3/putmsg.cpp b/src/sbbs3/putmsg.cpp
index f69853861baaabab931b2cbd9963c01110b05534..9905a847dc8db0566dcd09e6d89665277780f11d 100644
--- a/src/sbbs3/putmsg.cpp
+++ b/src/sbbs3/putmsg.cpp
@@ -64,18 +64,17 @@ char sbbs_t::putmsg(const char *buf, long mode)
 		attr(LIGHTGRAY);
 	if(mode&P_NOPAUSE)
 		sys_status|=SS_PAUSEOFF;
-	if(mode&P_HTML)
-		putcom("\x02\x02");
+	long term = term_supports();
 	if(!(mode&P_NOATCODES) && memcmp(str, "@WRAPOFF@", 9) == 0) {
 		mode &= ~P_WORDWRAP;
 		l += 9;
 	}
 	if(mode&P_WORDWRAP) {
-		char* term = NULL;
+		char* wrapoff = NULL;
 		if(!(mode&P_NOATCODES)) {
-			term = strstr((char*)str+l, "@WRAPOFF@");
-			if(term != NULL)
-				*term = 0;
+			wrapoff = strstr((char*)str+l, "@WRAPOFF@");
+			if(wrapoff != NULL)
+				*wrapoff = 0;
 		}
 		char *wrapped;
 		if((wrapped=::wordwrap((char*)str+l, cols-1, 79, /* handle_quotes: */TRUE)) == NULL)
@@ -85,7 +84,7 @@ char sbbs_t::putmsg(const char *buf, long mode)
 			putmsg(wrapped, mode&(~P_WORDWRAP));
 			free(wrapped);
 			l=strlen(str);
-			if(term != NULL)
+			if(wrapoff != NULL)
 				l += 9;	// Skip "<NUL>WRAPOFF@"
 		}
 	}
@@ -143,7 +142,7 @@ char sbbs_t::putmsg(const char *buf, long mode)
 			l+=4; 
 		}
 		else if(cfg.sys_misc&SM_RENEGADE && str[l]=='|' && isdigit((unsigned char)str[l+1])
-			&& isdigit((unsigned char)str[l+2]) && !(useron.misc&(RIP|WIP))) {
+			&& isdigit((unsigned char)str[l+2]) && !(useron.misc&RIP)) {
 			sprintf(tmp2,"%.2s",str+l+1);
 			i=atoi(tmp2);
 			if(i>=16) { 				/* setting background */
@@ -158,7 +157,7 @@ char sbbs_t::putmsg(const char *buf, long mode)
 			l+=3;	/* Skip |xx */
 		}	
 		else if(cfg.sys_misc&SM_CELERITY && str[l]=='|' && isalpha((unsigned char)str[l+1])
-			&& !(useron.misc&(RIP|WIP))) {
+			&& !(useron.misc&RIP)) {
 			switch(str[l+1]) {
 				case 'k':
 					attr((curatr&0xf0)|BLACK);
@@ -270,10 +269,8 @@ char sbbs_t::putmsg(const char *buf, long mode)
 					continue; 
 				} 
 			}
-			if(str[l]=='!' && str[l+1]=='|' && useron.misc&(RIP|WIP)) /* RIP */
+			if(str[l]=='!' && str[l+1]=='|' && useron.misc&RIP) /* RIP */
 				lncntr=0;				/* so defeat pause */
-			if(str[l]==ESC && str[l+1]=='$')    /* WIP command */
-				lncntr=0;
 			if(str[l]=='@' && !(mode&P_NOATCODES)) {
 				if(memcmp(str+l, "@EOF@", 5) == 0)
 					break;
@@ -310,19 +307,6 @@ char sbbs_t::putmsg(const char *buf, long mode)
 					break;
 				}
 
-				/* In HTML mode, defer PAUSE and MORE to end and suppress message */
-				if(mode&P_HTML) {
-					if(!memcmp(str+l,"@MORE@",6)) {
-						defered_pause=TRUE;
-						l+=6;
-						continue;
-					}
-					if(!memcmp(str+l,"@PAUSE@",7)) {
-						defered_pause=TRUE;
-						l+=7;
-						continue;
-					}
-				}
 				i=show_atcode((char *)str+l);	/* returns 0 if not valid @ code */
 				l+=i;					/* i is length of code string */
 				if((sys_status&SS_ABORT) && !lines_printed)	/* Aborted at (auto) pause prompt (e.g. due to CLS)? */
@@ -332,18 +316,16 @@ char sbbs_t::putmsg(const char *buf, long mode)
 			}
 			if(mode&P_CPM_EOF && str[l]==CTRL_Z)
 				break;
-			outchar(str[l]);
-#if 0
-				if(!(mode&P_HTML) && !exatr && !outchar_esc && lncntr && lbuflen && cols && ++col==cols)
-					lncntr++;
+			if(mode&P_PETSCII) {
+				if(term&PETSCII)
+					outcom(str[l]);
 				else
-					col=0;
-#endif
+					petscii_to_ansibbs(str[l]);
+			} else
+				outchar(str[l]);
 			l++; 
 		} 
 	}
-	if(mode&P_HTML)
-		putcom("\x02");
 	if(!(mode&P_SAVEATR)) {
 		console=orgcon;
 		attr(tmpatr); 
@@ -353,10 +335,7 @@ char sbbs_t::putmsg(const char *buf, long mode)
 
 	/* Handle defered pauses */
 	if(defered_pause) {
-		if(mode&P_HTML)
-			getkey(0);
-		else
-			pause();
+		pause();
 	}
 
 	ret=str[l];
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index ae5bed7d72f7a31bf388671e6d93af94e4d54840..3cb8220e3c956ea1be3e7eebc435d7aa94915025 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -703,7 +703,7 @@ public:
 #endif
 	;
 	void	backspace(void);				/* Output a destructive backspace via outchar */
-	void	outchar(char ch);				/* Output a char - check echo and emu.  */
+	int		outchar(char ch);				/* Output a char - check echo and emu.  */
 	void	center(char *str);
 	void	clearline(void);
 	void	cleartoeol(void);
@@ -721,6 +721,9 @@ public:
 	void	progress(const char* str, int count, int total, int interval=1);
 	bool	saveline(void);
 	bool	restoreline(void);
+	int		petscii_to_ansibbs(unsigned char);
+	int		attr(int);				/* Change text color/attributes */
+	void	ctrl_a(char);			/* Performs Ctrl-Ax attribute changes */
 
 	/* getstr.cpp */
 	size_t	getstr_offset;
@@ -744,8 +747,8 @@ public:
 	char	handle_ctrlkey(char ch, long mode=0);
 
 	/* prntfile.cpp */
-	bool	printfile(char *str, long mode);
-	bool	printtail(char *str, int lines, long mode);
+	bool	printfile(const char* fname, long mode);
+	bool	printtail(const char* fname, int lines, long mode);
 	bool	menu(const char *code, long mode = 0);
 	bool	menu_exists(const char *code, const char* ext=NULL, char* realpath=NULL);
 
@@ -755,8 +758,6 @@ public:
 	long	mselect(const char *title, str_list_t list, unsigned max_selections, const char* item_fmt, const char* selected_str, const char* unselected_str, const char* prompt_fmt);
 
 	void	redrwstr(char *strin, int i, int l, long mode);
-	void	attr(int atr);				/* Change local and remote text attributes */
-	void	ctrl_a(char x);			/* Peforms the Ctrl-Ax attribute changes */
 
 	/* atcodes.cpp */
 	int		show_atcode(const char *code);
@@ -1175,6 +1176,9 @@ extern "C" {
 	/* qwk.cpp */
 	DLLEXPORT int		qwk_route(scfg_t*, const char *inaddr, char *fulladdr, size_t maxlen);
 
+	/* con_out.cpp */
+	unsigned char		cp437_to_petscii(unsigned char);
+
 #ifdef JAVASCRIPT
 
 	typedef struct {
diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h
index d335adaec31635d9f9816feaec7373cfb32785bf..d138ae36ea28cbb992c16604c09a75a63c450c4e 100644
--- a/src/sbbs3/sbbsdefs.h
+++ b/src/sbbs3/sbbsdefs.h
@@ -754,6 +754,7 @@ typedef enum {						/* Values for xtrn_t.event				*/
 #define P_CPM_EOF	(1<<8)		/* Ignore Ctrl-Z chars (CPM End-of-File)	*/
 #define	P_TRUNCATE	(1<<9)		/* Truncate (don't display) long lines		*/
 #define P_NOERROR	(1<<10)		/* Don't report error if file doesn't exist	*/
+#define P_PETSCII	(1<<11)		/* Message is native PETSCII				*/
 
 								/* Bits in 'mode' for listfiles             */
 #define FL_ULTIME   (1<<0)		/* List files by upload time                */
diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp
index 356a8a32b226345e0d20a630aed9504ed710fceb..5d64c46a78cf7c1bc2657ff91b1b459050ce62b9 100644
--- a/src/sbbs3/xtrn.cpp
+++ b/src/sbbs3/xtrn.cpp
@@ -255,6 +255,13 @@ BYTE* telnet_expand(BYTE* inbuf, ulong inlen, BYTE* outbuf, ulong& newlen)
     return(outbuf);
 }
 
+static void petscii_convert(BYTE* buf, ulong len)
+{
+    for(ulong i=0; i<len; i++) {
+		buf[i] = cp437_to_petscii(buf[i]);
+	}
+}
+
 static bool native_executable(scfg_t* cfg, const char* cmdline, long mode)
 {
 	char*	p;
@@ -929,6 +936,8 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 						lprintf(LOG_ERR,"output buffer overflow");
 						rd=RingBufFree(&outbuf);
 					}
+					if(!(mode&EX_BIN) && term_supports(PETSCII))
+						petscii_convert(bp, rd);
 					RingBufWrite(&outbuf, bp, rd);
 				}
 			} else {	// Windows 9x
@@ -996,6 +1005,8 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 						lprintf(LOG_ERR,"output buffer overflow");
 						rd=RingBufFree(&outbuf);
 					}
+					if(!(mode&EX_BIN) && term_supports(PETSCII))
+						petscii_convert(bp, rd);
 					RingBufWrite(&outbuf, bp, rd);
 				}
 			}
@@ -1928,18 +1939,21 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
 				}
 				else
    	       			bp=telnet_expand(buf, rd, output_buf, output_len);
-			} else if ((mode & EX_STDIO) != EX_STDIO) {
-				/* LF to CRLF expansion */
-				bp=lf_expand(buf, rd, output_buf, output_len);
-			} else if(mode&EX_WWIV) {
-                bp=wwiv_expand(buf, rd, wwiv_buf, output_len, useron.misc, wwiv_flag);
-				if(output_len > sizeof(wwiv_buf))
-					lprintf(LOG_ERR, "WWIV_BUF OVERRUN");
 			} else {
-				bp=buf;
-				output_len=rd;
+				if ((mode & EX_STDIO) != EX_STDIO) {
+					/* LF to CRLF expansion */
+					bp=lf_expand(buf, rd, output_buf, output_len);
+				} else if(mode&EX_WWIV) {
+					bp=wwiv_expand(buf, rd, wwiv_buf, output_len, useron.misc, wwiv_flag);
+					if(output_len > sizeof(wwiv_buf))
+						lprintf(LOG_ERR, "WWIV_BUF OVERRUN");
+				} else {
+					bp=buf;
+					output_len=rd;
+				}
+				if (term_supports(PETSCII))
+					petscii_convert(bp, output_len);
 			}
-
 			/* Did expansion overrun the output buffer? */
 			if(output_len>sizeof(output_buf)) {
 				lprintf(LOG_ERR,"OUTPUT_BUF OVERRUN");
diff --git a/src/xpdev/petdefs.h b/src/xpdev/petdefs.h
index 1f57d23301008cca2a4dba2332ff060542b34131..c25ec650c65b67460e45d0f3bd2631ec88844105 100644
--- a/src/xpdev/petdefs.h
+++ b/src/xpdev/petdefs.h
@@ -76,28 +76,28 @@ enum petscii_char {
 	/* Symbols (which don't align with ASCII) */
 	PETSCII_BRITPOUND	= 92,
 	/* Graphic chars */
-	PETSCII_LIGHTHASH	= '\xA6',
-	PETSCII_MEDIUMHASH	= '\xDE',
-	PETSCII_HEAVYHASH	= '\xA9',
-	PETSCII_SOLID		= '\xA0',	// Actually inversed solid (empty)
-	PETSCII_LEFTHALF	= '\xA1',
-	PETSCII_RIGHTHALF	= '\xB6',	// Not quite a full half
-	PETSCII_TOPHALF		= '\xB8',	// Not quite a full half
-	PETSCII_BOTTOMHALF	= '\xA2',
-	PETSCII_CHECKMARK	= '\xBA',
-	PETSCII_CROSS		= '\xDB',
-	PETSCII_HORZLINE	= '\xC0',
-	PETSCII_VERTLINE	= '\xDD',
-	PETSCII_LWRRHTBOX	= '\xAC',
-	PETSCII_LWRLFTBOX	= '\xBB',
-	PETSCII_UPRRHTBOX	= '\xBC',
-	PETSCII_UPRLFTBOX	= '\xBE',
-	PETSCII_CHECKERBRD	= '\xBF',
+	PETSCII_LIGHTHASH	= 0xA6,
+	PETSCII_MEDIUMHASH	= 0xDE,
+	PETSCII_HEAVYHASH	= 0xA9,
+	PETSCII_SOLID		= 0xA0,	// Actually inversed solid (empty)
+	PETSCII_LEFTHALF	= 0xA1,
+	PETSCII_RIGHTHALF	= 0xB6,	// Not quite a full half
+	PETSCII_TOPHALF		= 0xB8,	// Not quite a full half
+	PETSCII_BOTTOMHALF	= 0xA2,
+	PETSCII_CHECKMARK	= 0xBA,
+	PETSCII_CROSS		= 0xDB,
+	PETSCII_HORZLINE	= 0xC0,
+	PETSCII_VERTLINE	= 0xDD,
+	PETSCII_LWRRHTBOX	= 0xAC,
+	PETSCII_LWRLFTBOX	= 0xBB,
+	PETSCII_UPRRHTBOX	= 0xBC,
+	PETSCII_UPRLFTBOX	= 0xBE,
+	PETSCII_CHECKERBRD	= 0xBF,
 	/* Replacement chars (missing ASCII chars) */
-	PETSCII_BACKSLASH	= '/',		// the 109 graphics char is an 'M' in shifted/text mode :-(
-	PETSCII_BACKTICK	= '\xAD',	// a graphics char actually
-	PETSCII_TILDE		= '\xA8',	// a graphics char actually
-	PETSCII_UNDERSCORE	= '\xA4',	// a graphics char actually
+	PETSCII_BACKSLASH	= '/',	// the 109 graphics char is an 'M' in shifted/text mode :-(
+	PETSCII_BACKTICK	= 0xAD,	// a graphics char actually
+	PETSCII_TILDE		= 0xA8,	// a graphics char actually
+	PETSCII_UNDERSCORE	= 0xA4,	// a graphics char actually
 };
 
 #endif /* Don't add anything after this line */
\ No newline at end of file