diff --git a/src/sbbs3/ansiterm.cpp b/src/sbbs3/ansiterm.cpp
index b24bb2913961de261b8bdf3b58ac9d1d71db95d5..6964d68c321ded3801e5e26dcbfbe8dbe352ea96 100644
--- a/src/sbbs3/ansiterm.cpp
+++ b/src/sbbs3/ansiterm.cpp
@@ -97,6 +97,102 @@ const char *sbbs_t::ansi(int atr)
 	return("-Invalid use of ansi()-");
 }
 
+/* insure str is at least 14 bytes in size! */
+char* sbbs_t::ansi(int atr, int curatr, char* str)
+{
+	if(!term_supports(COLOR)) {  /* eliminate colors if user doesn't have them */
+		if(atr&LIGHTGRAY)       /* if any foreground bits set, set all */
+			atr|=LIGHTGRAY;
+		if(atr&BG_LIGHTGRAY)  /* if any background bits set, set all */
+			atr|=BG_LIGHTGRAY;
+		if(atr&LIGHTGRAY && atr&BG_LIGHTGRAY)
+			atr&=~LIGHTGRAY;    /* if background is solid, foreground is black */
+		if(!atr)
+			atr|=LIGHTGRAY;		/* don't allow black on black */
+	}
+	if(curatr==atr) { /* text hasn't changed. no sequence needed */
+		*str=0;
+		return str;
+	}
+
+	strcpy(str,"\033[");
+	if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK)
+		|| atr==LIGHTGRAY) {
+		strcat(str,"0;");
+		curatr=LIGHTGRAY;
+	}
+	if(atr&BLINK) {                     /* special attributes */
+		if(!(curatr&BLINK))
+			strcat(str,"5;");
+	}
+	if(atr&HIGH) {
+		if(!(curatr&HIGH))
+			strcat(str,"1;"); 
+	}
+	if((atr&0x07) != (curatr&0x07)) {
+		switch(atr&0x07) {
+			case BLACK:
+				strcat(str,"30;");
+				break;
+			case RED:
+				strcat(str,"31;");
+				break;
+			case GREEN:
+				strcat(str,"32;");
+				break;
+			case BROWN:
+				strcat(str,"33;");
+				break;
+			case BLUE:
+				strcat(str,"34;");
+				break;
+			case MAGENTA:
+				strcat(str,"35;");
+				break;
+			case CYAN:
+				strcat(str,"36;");
+				break;
+			case LIGHTGRAY:
+				strcat(str,"37;");
+				break;
+		}
+	}
+	if((atr&0x70) != (curatr&0x70)) {
+		switch(atr&0x70) {
+			/* The BG_BLACK macro is 0x200, so isn't in the mask */
+			case 0 /* BG_BLACK */:	
+				strcat(str,"40;");
+				break;
+			case BG_RED:
+				strcat(str,"41;");
+				break;
+			case BG_GREEN:
+				strcat(str,"42;");
+				break;
+			case BG_BROWN:
+				strcat(str,"43;");
+				break;
+			case BG_BLUE:
+				strcat(str,"44;");
+				break;
+			case BG_MAGENTA:
+				strcat(str,"45;");
+				break;
+			case BG_CYAN:
+				strcat(str,"46;");
+				break;
+			case BG_LIGHTGRAY:
+				strcat(str,"47;");
+				break;
+		}
+	}
+	if(strlen(str)==2)	/* Convert <ESC>[ to blank */
+		*str=0;
+	else
+		str[strlen(str)-1]='m';
+	return str;
+}
+
 void sbbs_t::ansi_getlines()
 {
 	if(sys_status&SS_USERON && useron.misc&ANSI && !useron.rows /* Auto-detect rows */
diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp
index 1cd7475594f7356f2ef020824564b63efcd29c00..50db0690e669e9966c4e3b725286da5e61ea8561 100644
--- a/src/sbbs3/con_out.cpp
+++ b/src/sbbs3/con_out.cpp
@@ -575,181 +575,7 @@ void sbbs_t::attr(int atr)
 
 	if(!term_supports(ANSI))
 		return;
-	if(!term_supports(COLOR)) {  /* eliminate colors if user doesn't have them */
-		if(atr&LIGHTGRAY)       /* if any foreground bits set, set all */
-			atr|=LIGHTGRAY;
-		if(atr&BG_LIGHTGRAY)  /* if any background bits set, set all */
-			atr|=BG_LIGHTGRAY;
-		if(atr&LIGHTGRAY && atr&BG_LIGHTGRAY)
-			atr&=~LIGHTGRAY;    /* if background is solid, foreground is black */
-		if(!atr)
-			atr|=LIGHTGRAY;		/* don't allow black on black */
-	}
-	if(curatr==atr) /* text hasn't changed. don't send codes */
-		return;
-
-#if 1
-	strcpy(str,"\033[");
-	if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK)
-		|| atr==LIGHTGRAY) {
-		strcat(str,"0;");
-		curatr=LIGHTGRAY;
-	}
-	if(atr&BLINK) {                     /* special attributes */
-		if(!(curatr&BLINK))
-			strcat(str,"5;");
-	}
-	if(atr&HIGH) {
-		if(!(curatr&HIGH))
-			strcat(str,"1;"); 
-	}
-	if((atr&0x07) != (curatr&0x07)) {
-		switch(atr&0x07) {
-			case BLACK:
-				strcat(str,"30;");
-				break;
-			case RED:
-				strcat(str,"31;");
-				break;
-			case GREEN:
-				strcat(str,"32;");
-				break;
-			case BROWN:
-				strcat(str,"33;");
-				break;
-			case BLUE:
-				strcat(str,"34;");
-				break;
-			case MAGENTA:
-				strcat(str,"35;");
-				break;
-			case CYAN:
-				strcat(str,"36;");
-				break;
-			case LIGHTGRAY:
-				strcat(str,"37;");
-				break;
-		}
-	}
-	if((atr&0x70) != (curatr&0x70)) {
-		switch(atr&0x70) {
-			/* The BG_BLACK macro is 0x200, so isn't in the mask */
-			case 0 /* BG_BLACK */:	
-				strcat(str,"40;");
-				break;
-			case BG_RED:
-				strcat(str,"41;");
-				break;
-			case BG_GREEN:
-				strcat(str,"42;");
-				break;
-			case BG_BROWN:
-				strcat(str,"43;");
-				break;
-			case BG_BLUE:
-				strcat(str,"44;");
-				break;
-			case BG_MAGENTA:
-				strcat(str,"45;");
-				break;
-			case BG_CYAN:
-				strcat(str,"46;");
-				break;
-			case BG_LIGHTGRAY:
-				strcat(str,"47;");
-				break;
-		}
-	}
-	if(strlen(str)==2)
-		return;
-	str[strlen(str)-1]='m';
-	rputs(str);
-#else
-	if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK)
-		|| atr==LIGHTGRAY) {
-		rputs(ansi(ANSI_NORMAL));
-		curatr=LIGHTGRAY; 
-	}
-
-	if(atr==LIGHTGRAY)                  /* no attributes */
-		return;
-
-	if(atr&BLINK) {                     /* special attributes */
-		if(!(curatr&BLINK))
-			rputs(ansi(BLINK)); 
-	}
-	if(atr&HIGH) {
-		if(!(curatr&HIGH))
-			rputs(ansi(HIGH)); 
-	}
-
-	if((atr&0x7)==BLACK) {              /* foreground colors */
-		if((curatr&0x7)!=BLACK)
-			rputs(ansi(BLACK)); 
-	}
-	else if((atr&0x7)==RED) {
-		if((curatr&0x7)!=RED)
-			rputs(ansi(RED)); 
-	}
-	else if((atr&0x7)==GREEN) {
-		if((curatr&0x7)!=GREEN)
-			rputs(ansi(GREEN)); 
-	}
-	else if((atr&0x7)==BROWN) {
-		if((curatr&0x7)!=BROWN)
-			rputs(ansi(BROWN)); 
-	}
-	else if((atr&0x7)==BLUE) {
-		if((curatr&0x7)!=BLUE)
-			rputs(ansi(BLUE)); 
-	}
-	else if((atr&0x7)==MAGENTA) {
-		if((curatr&0x7)!=MAGENTA)
-			rputs(ansi(MAGENTA)); 
-	}
-	else if((atr&0x7)==CYAN) {
-		if((curatr&0x7)!=CYAN)
-			rputs(ansi(CYAN)); 
-	}
-	else if((atr&0x7)==LIGHTGRAY) {
-		if((curatr&0x7)!=LIGHTGRAY)
-			rputs(ansi(LIGHTGRAY)); 
-	}
-
-	if((atr&0x70)==0) {        /* background colors */
-		if((curatr&0x70)!=0)
-			rputs(ansi(BG_BLACK)); 
-	}
-	else if((atr&0x70)==BG_RED) {
-		if((curatr&0x70)!=BG_RED)
-			rputs(ansi(BG_RED)); 
-	}
-	else if((atr&0x70)==BG_GREEN) {
-		if((curatr&0x70)!=BG_GREEN)
-			rputs(ansi(BG_GREEN)); 
-	}
-	else if((atr&0x70)==BG_BROWN) {
-		if((curatr&0x70)!=BG_BROWN)
-			rputs(ansi(BG_BROWN)); 
-	}
-	else if((atr&0x70)==BG_BLUE) {
-		if((curatr&0x70)!=BG_BLUE)
-			rputs(ansi(BG_BLUE)); 
-	}
-	else if((atr&0x70)==BG_MAGENTA) {
-		if((curatr&0x70)!=BG_MAGENTA)
-			rputs(ansi(BG_MAGENTA)); 
-	}
-	else if((atr&0x70)==BG_CYAN) {
-		if((curatr&0x70)!=BG_CYAN)
-			rputs(ansi(BG_CYAN)); 
-	}
-	else if((atr&0x70)==BG_LIGHTGRAY) {
-		if((curatr&0x70)!=BG_LIGHTGRAY)
-			rputs(ansi(BG_LIGHTGRAY)); 
-	}
-#endif
-
+	rputs(ansi(atr,curatr,str,sizeof(str)-1));
 	curatr=atr;
 }
 
diff --git a/src/sbbs3/js_console.cpp b/src/sbbs3/js_console.cpp
index aa8db0308aa31f41471f066effc2329ee5fa1840..8ced6d4cf3c2d6a755be22ad5d3b1f1c93598e45 100644
--- a/src/sbbs3/js_console.cpp
+++ b/src/sbbs3/js_console.cpp
@@ -1151,8 +1151,17 @@ js_ansi(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
 	if(argc)
 		JS_ValueToInt32(cx,argv[0],&attr);
-	if((js_str=JS_NewStringCopyZ(cx,sbbs->ansi(attr)))==NULL)
-		return(JS_FALSE);
+	if(argc>1) {
+		int32	curattr=0;
+		char	buf[16];
+
+		JS_ValueToInt32(cx,argv[0],&curattr);
+		if((js_str=JS_NewStringCopyZ(cx,sbbs->ansi(attr,curattr,buf)))==NULL)
+			return(JS_FALSE);
+	} else {
+		if((js_str=JS_NewStringCopyZ(cx,sbbs->ansi(attr)))==NULL)
+			return(JS_FALSE);
+	}
 
 	*rval = STRING_TO_JSVAL(js_str);
     return(JS_TRUE);
@@ -1558,8 +1567,10 @@ static jsSyncMethodSpec js_console_functions[] = {
 	,JSDOCSTR("restore last output line")
 	,310
 	},		
-	{"ansi",			js_ansi,			1, JSTYPE_STRING,	JSDOCSTR("attribute_number")
-	,JSDOCSTR("returns ANSI encoding of specified <i>attribute_number</i>")
+	{"ansi",			js_ansi,			1, JSTYPE_STRING,	JSDOCSTR("attribute [,current_attribute]")
+	,JSDOCSTR("returns ANSI sequence required to generate specified terminal <i>attribute</i> "
+	"(e.g. <tt>YELLOW|HIGH|BG_BLUE</tt>), "
+	"if <i>current_attribute</i> is specified, an optimized ANSI sequence may be returned")
 	,310
 	},		
 	{"ansi_save",		js_pushxy,			0, JSTYPE_ALIAS	},
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 5e261c971a3389343b308f91237cd0b4717eea2f..96eb9853d09d3b6350bdd3c5386e1c665319a650 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -379,7 +379,8 @@ public:
 	uint	sysvar_li;
 
     /* ansi_term.cpp */
-	const char *	ansi(int atr);			/* Returns ansi escape sequence for atr */
+	const char*	ansi(int atr);			/* Returns ansi escape sequence for atr */
+	char*	ansi(int atr, int curatr, char* str);
     bool	ansi_gotoxy(int x, int y);
 	bool	ansi_getxy(int* x, int* y);
 	bool	ansi_save(void);