diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp
index 2cfaa77278754120105d17ab7653d365e935305d..1c2ed232e850608ca3a279e2f4d66d0bc1280434 100644
--- a/src/sbbs3/con_out.cpp
+++ b/src/sbbs3/con_out.cpp
@@ -566,57 +566,46 @@ const char* sbbs_t::term_charset(long term)
 /****************************************************************************/
 int sbbs_t::outchar(char ch)
 {
-	/*
-	 * outchar_esc values:
-	 * 0: No sequence
-	 * 1: ESC
-	 * 2: CSI
-	 * 3: Final byte
-     * 4: APS, DCS, PM, or OSC
-     * 5: SOS
-     * 6: ESC inside of SOS
-     */
-
 	if(console&CON_ECHO_OFF)
 		return 0;
-	if(ch==ESC && outchar_esc < 4)
-		outchar_esc=1;
-	else if(outchar_esc==1) {
-		if(ch=='[')
-			outchar_esc++;
-		else if(ch=='_' || ch=='P' || ch == '^' || ch == ']')
-			outchar_esc=4;
+	if(ch == ESC && outchar_esc < ansiState_string)
+		outchar_esc = ansiState_esc;
+	else if(outchar_esc == ansiState_esc) {
+		if(ch == '[')
+			outchar_esc = ansiState_csi;
+		else if(ch == '_' || ch == 'P' || ch == '^' || ch == ']')
+			outchar_esc = ansiState_string;
 		else if(ch=='X')
-			outchar_esc=5;
-		else if(ch >= 0x40 && ch <= 0x5f)
-			outchar_esc=3;
+			outchar_esc = ansiState_sos;
+		else if(ch >= '@' && ch <= '_')
+			outchar_esc = ansiState_final;
 		else
-			outchar_esc=0;
+			outchar_esc = ansiState_none;
 	}
-	else if(outchar_esc==2) {
-		if(ch>='@' && ch<='~')
-			outchar_esc++;
+	else if(outchar_esc == ansiState_csi) {
+		if(ch >= '@' && ch <= '~')
+			outchar_esc = ansiState_final;
 	}
-	else if(outchar_esc==4) {	// APS, DCS, PM, or OSC
+	else if(outchar_esc == ansiState_string) {	// APS, DCS, PM, or OSC
 		if (ch == ESC)
-			outchar_esc = 1;
-		if (!((ch >= 0x08 && ch <= 0x0d) || (ch >= 0x20 && ch <= 0x7e)))
-			outchar_esc = 0;
+			outchar_esc = ansiState_esc;
+		if (!((ch >= '\b' && ch <= '\r') || (ch >= ' ' && ch <= '~')))
+			outchar_esc = ansiState_none;
 	}
-	else if(outchar_esc==5) {	// SOS
+	else if(outchar_esc == ansiState_sos) {	// SOS
 		if (ch == ESC)
-			outchar_esc++;
+			outchar_esc = ansiState_sos_esc;
 	}
-	else if(outchar_esc==6) {	// ESC inside SOS
+	else if(outchar_esc == ansiState_sos_esc) {	// ESC inside SOS
 		if (ch == '\\')
-			outchar_esc = 1;
+			outchar_esc = ansiState_esc;
 		else if (ch == 'X')
-			outchar_esc = 0;
+			outchar_esc = ansiState_none;
 		else
-			outchar_esc = 5;
+			outchar_esc = ansiState_sos;
 	}
 	else
-		outchar_esc=0;
+		outchar_esc = ansiState_none;
 	long term = term_supports();
 	char utf8[UTF8_MAX_LEN + 1] = "";
 	if(!(term&PETSCII)) {
@@ -642,7 +631,7 @@ int sbbs_t::outchar(char ch)
 	if(!(console&CON_R_ECHO))
 		return 0;
 
-	if((console&CON_R_ECHOX) && (uchar)ch>=' ' && !outchar_esc) {
+	if((console&CON_R_ECHOX) && (uchar)ch>=' ' && outchar_esc == ansiState_none) {
 		ch=text[YNQP][3];
 		if(text[YNQP][2]==0 || ch==0) ch='X';
 	}
@@ -677,7 +666,7 @@ int sbbs_t::outchar(char ch)
 				outcom(ch);
 		}
 	}
-	if(!outchar_esc) {
+	if(outchar_esc == ansiState_none) {
 		/* Track cursor position locally */
 		switch(ch) {
 			case '\a':	// 7
@@ -718,8 +707,8 @@ int sbbs_t::outchar(char ch)
 				break;
 		}
 	}
-	if(outchar_esc==3)
-		outchar_esc=0;
+	if(outchar_esc == ansiState_final)
+		outchar_esc = ansiState_none;
 
 	if(lncntr==rows-1 && ((useron.misc&(UPAUSE^(console&CON_PAUSEOFF))) || sys_status&SS_PAUSEON)
 		&& !(sys_status&(SS_PAUSEOFF|SS_ABORT))) {
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index c0502bb5f0a154552777d41059a6b2bc6ce9bcde..499f6670ece3a5d1696d75e771e39c045fce78c5 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -3369,7 +3369,7 @@ sbbs_t::sbbs_t(ushort node_num, union xp_sockaddr *addr, size_t addr_len, const
 	pause_hotspot = NULL;
 	console = 0;
 	online = 0;
-	outchar_esc = 0;
+	outchar_esc = ansiState_none;
 	nodemsg_inside = 0;	/* allows single nest */
 	hotkey_inside = 0;	/* allows single nest */
 	event_time = 0;
diff --git a/src/sbbs3/putmsg.cpp b/src/sbbs3/putmsg.cpp
index ad8c67cb08835473f35fb054cdfa74821ff0e69f..62fd6b3a5709c903a0f2481d758b95f0ab17a914 100644
--- a/src/sbbs3/putmsg.cpp
+++ b/src/sbbs3/putmsg.cpp
@@ -193,10 +193,6 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob
 				l+=2;
 			}
 		}
-		else if((str[l]=='`' || str[l]=='�') && str[l+1]=='[') {
-			outchar(ESC); /* Convert `[ and �[ to ESC[ */
-			l++;
-		}
 		else if(!((*mode)&P_NOXATTRS)
 			&& (cfg.sys_misc&SM_PCBOARD) && str[l]=='@' && str[l+1]=='X'
 			&& isxdigit((unsigned char)str[l+2]) && isxdigit((unsigned char)str[l+3])) {
@@ -348,7 +344,7 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob
 			}
 
 			/* ansi escape sequence */
-			if(outchar_esc) {
+			if(outchar_esc >= ansiState_csi) {
 				if(str[l]=='A' || str[l]=='B' || str[l]=='H' || str[l]=='J'
 					|| str[l]=='f' || str[l]=='u')    /* ANSI anim */
 					lncntr=0;			/* so defeat pause */
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 7f78bc34adbfff44b5a777ffc2689e2f3ed05aa5..2139e8b94754af08dc601d343257f275887a9e25 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -348,7 +348,15 @@ public:
 
 	scfg_t	cfg;
 
-	int		outchar_esc;		   // track ANSI escape seq output
+	enum ansiState {
+		 ansiState_none		// No sequence
+		,ansiState_esc		// Escape
+		,ansiState_csi		// CSI
+		,ansiState_final	// Final byte
+		,ansiState_string	// APS, DCS, PM, or OSC
+		,ansiState_sos		// SOS
+		,ansiState_sos_esc	// ESC inside SOS
+	} outchar_esc;			// track ANSI escape seq output
 
 	int 	rioctl(ushort action); // remote i/o control
 	bool	rio_abortable;