Revision
17
Author
emsmith
Date
2006-08-18 11:12:11 -0700 (Fri, 18 Aug 2006)

Log Message

Ansi escape codes for colors on cmd.exe - exe and source code

Modified Paths

Added Paths

Diff

Added: library/trunk/lib/test/ansi.cpp (16 => 17)


--- library/trunk/lib/test/ansi.cpp	2006-08-15 17:27:10 UTC (rev 16)
+++ library/trunk/lib/test/ansi.cpp	2006-08-18 18:12:11 UTC (rev 17)
@@ -0,0 +1,374 @@
+/* Found at http://home.tiscali.dk/8x305617/provide/ansi.html */
+#include <condefs.h>
+#include <conio.h>
+#include <cstdio>
+#include <cctype>
+#include <string>
+#include <vector>
+#pragma hdrstop
+#include <io.h>
+#include <fcntl.h>
+using namespace std;
+
+/*
+        Borland C++ Builder 4.0 source code (console mode program).
+
+        Could probably compile on other
+        Win32 compilers with small changes.
+*/
+
+
+char const documentation[] =
+  "ANSI.EXE: An ANSI escape sequence filter for Win32 console mode.\n"
+  "\n"
+  "Redirect any program generating ANSI escape sequences through ANSI.EXE\n"
+  "using filtering:\n"
+  "	OtherProgram.exe ...other program arguments... | ansi\n"
+  "\n"
+  "and ANSI.EXE will translate the embedded escape sequences into the\n"
+  "appropriate colours, cursor movements etc.\n"
+  "\n"
+  "Keyboard redefinition not supported.\n"
+  "\n"
+  "Freeware.  Further information:\n"
+  "\t<URL:http://home13.inet.tele.dk/ajm/provide/ansi.html>\n"
+  "\n"
+  "regards,\n"
+  "Anders Munch, andersjm@post.tele.dk, June 18 2000\n"
+  ;
+
+
+
+
+//---------------------------------------------------------------------------
+static void ConvertAnsiToScreen();
+
+#pragma argsused
+int main(int argc, char* argv[])
+{
+  if(argc > 1)
+  {
+    fprintf(stderr, "%s", documentation);
+  }
+  else
+  {
+    setmode(fileno(stdin), O_BINARY);
+
+    ConvertAnsiToScreen();
+  }
+  return 0;
+}
+
+static int nextchar = EOF;
+std::string unechoed;
+
+inline unsigned char current()
+{ return static_cast<unsigned char>(nextchar); }
+inline bool atend()
+{ return nextchar == EOF || nextchar == '\032'; }
+
+static void advance()
+{
+    if(nextchar != EOF)
+	unechoed.push_back(current());
+    nextchar = getchar();
+}
+static void consume_current()
+{
+    nextchar = EOF;
+}
+static void flush()
+{
+    cputs(unechoed.c_str());
+    unechoed.clear();
+}
+static void newline()
+{
+    cputs("\r\n");
+}
+static void consume_previous() { unechoed.clear(); }
+
+static long ReadInteger()
+{
+    int val = 0;
+    while(isdigit(current()))
+    {
+	val = val * 10 + (current()-'0');
+	advance();
+    }
+    return val;
+}
+
+static int translate_colour(int ansic)
+{
+    switch(ansic)
+    {
+    default: /* impossible */;
+    case 0: return BLACK;
+    case 1: return RED;
+    case 2: return GREEN;
+    case 3: return YELLOW;
+    case 4: return BLUE;
+    case 5: return MAGENTA;
+    case 6: return CYAN;
+    case 7: return WHITE;
+    }
+}
+static void UNKNOWN_ANSI(unsigned char cmd, vector<long> const& params)
+{
+    cprintf("\r\nUNSUPPORTED ANSI COMMAND '%c', %d PARAMETERS\r\n",
+	    cmd, (int)params.size());
+}
+
+
+static void InterpretAnsiCommand(
+    unsigned char command,
+    bool equals_sign,
+    vector<long>& parameters)
+/*
+  Called for input on the form:
+     ESC [ P1;P2;....;PN c      (equals_sign == false)
+  or ESC [ = P1;P2;....;PN c    (equals_sign == true)
+
+  c is a single alphabetic letter, stored in 'command'.
+
+  P1..PN are integer parameters, stored in 'params':
+  	N==params.size().
+	Omitted (empty string) numbers are identified by EOF in 'params'.
+
+  Commands with string parameters will _not_ reach this point.
+
+  Wrt. illegal parameters and unsupported commands: some are diagnosed with
+  and error message (through UNKNOWN_ANSI).  Others are silently ignored.
+*/
+
+{
+    static int saved_x = 1, saved_y = 1;
+    struct text_info ti;
+    size_t paramcount = parameters.size();
+
+    gettextinfo(&ti);
+
+    if(command == 'm')
+    {
+	int attribute = ti.attribute;
+	vector<long>::iterator it;
+	for(it=parameters.begin(); it!= parameters.end(); ++it)
+	{
+	    int a = *it;
+
+	    if(a >= 30 && a <= 37)
+		attribute = (attribute & 0xF0) | translate_colour(a-30);
+	    else if(a >= 40 && a <= 47)
+		attribute = (attribute & 0x8F)
+		    | ((translate_colour(a-40) & 0x07) << 4);
+	    else if(a == 5)
+		attribute |= 0x80;
+	    else if(a == 0)
+		attribute = ti.normattr;
+	    else if(a == 1)
+		attribute |= 0x08;
+	    else if(a == 7)
+		attribute = ((attribute & 0x70) >> 4)
+		    | ((attribute & 0x07) << 4)
+		    | (attribute & 0x80);
+	    else if(a == 8)
+		attribute = 0;
+	}
+
+	textattr(attribute);
+
+    }
+
+    else if(paramcount == 0)
+    {
+	switch(command)
+	{
+	case 's':
+	{
+	    saved_x = ti.curx;
+	    saved_y = ti.cury;
+	}
+	break;
+
+	case 'u':
+	{
+	    gotoxy(saved_x, saved_y);
+	}
+	break;
+
+	case 'K':
+	{
+	    clreol();
+	}
+	break;
+
+	default: UNKNOWN_ANSI(command, parameters);
+	}
+    }
+
+    else if(paramcount == 1)
+    {
+	switch(command)
+	{
+	case 'J':
+	{
+	    /* assume parameters.size()==1, parameters[0]==2 */
+	    clrscr();
+	}
+	break;
+
+	case 'A':
+	{
+	    gotoxy(ti.curx, max(1L, ti.cury-parameters[0]));
+	}
+	break;
+
+	case 'B':
+	{
+	    gotoxy(ti.curx, ti.cury+parameters[0]);
+	}
+	break;
+
+	case 'C':
+	{
+	    gotoxy(ti.curx+parameters[0], ti.cury);
+	}
+	break;
+
+	case 'D':
+	{
+	    gotoxy(max(1L, ti.curx-parameters[0]), ti.cury);
+	}
+	break;
+
+	case 'h':
+	{
+	    if(equals_sign)
+	    {
+		int req = EOF;
+		const int DENIED = EOF;
+		const int NOT_IMPLEMENTED = EOF;
+		switch(parameters[0])
+		{
+		case 0: req = BW40; break;
+		case 1: req = C40; break;
+		case 2: req = BW80; break;
+		case 3: req = C80; break;
+		case 4: req = DENIED; break;
+		case 5: req = DENIED; break;
+		case 6: req = DENIED; break;
+		case 7: req = NOT_IMPLEMENTED; break;
+		}
+
+		if(req != EOF)
+		    textmode(req);
+	    }
+	}
+	break;
+
+	default: UNKNOWN_ANSI(command, parameters);
+	}
+    }
+
+    else if(paramcount == 2)
+    {
+	switch(command)
+	{
+	case 'H': case 'f':
+	{
+	    int row = parameters[0];
+	    if(row == EOF) row = 1;
+	    int col = parameters[1];
+	    if(col == EOF) col = 1;
+
+	    gotoxy(col, row);
+	}
+	break;
+	default: UNKNOWN_ANSI(command, parameters);
+	}
+    }
+}
+
+
+static void ConvertAnsiToScreen()
+/*
+  Input parser.  
+
+  Reads standard input (encapsulated by rule-based functions
+  advance(), current(), atend() etc.  
+
+  When an ANSI escape sequences is met, InterpretAnsiCommand is called 
+  to figure out what to do with it. 
+
+*/
+{
+    advance();
+    while(! atend())
+    {
+        switch(current())
+        {
+        case '\033':
+        {
+	    advance();
+
+	    if(! atend() && current() == '[')
+	    {
+		bool equals_sign;
+                advance();
+
+		if(! atend() && current() == '=')
+		{
+		    equals_sign = true; advance();
+		}
+		else equals_sign = false;
+
+                vector<long> parameters;
+                if(!atend() && (isdigit(current()) || current()==';'))
+                {
+		    if(current() == ';')
+			parameters.push_back(EOF);
+		    else
+			parameters.push_back(ReadInteger());
+
+		    while(!atend() && current()==';')
+		    {
+                        advance();
+                        if(!atend() && isdigit(current()))
+			    parameters.push_back(ReadInteger());
+                        else
+			    parameters.push_back(EOF);
+		    }
+                }
+
+                if(!atend() && isalpha(current()))
+                {
+		    char command = current();
+		    consume_previous(); consume_current(); flush();
+		    InterpretAnsiCommand(command, equals_sign, parameters);
+		    advance();
+                }
+	    }
+        }
+        break;
+
+        case '\n':
+        {
+	    consume_current();
+	    flush(); newline();
+
+	    advance();
+        }
+        break;
+
+        default:
+        {
+	    advance();
+        }
+        break;
+        }
+
+        flush();
+    }
+
+}
Property changes on: library/trunk/lib/test/ansi.cpp
___________________________________________________________________
Name: tsvn:logminsize
   + 15

Added: library/trunk/lib/test/ansi.exe


(Binary files differ)
Property changes on: library/trunk/lib/test/ansi.exe ___________________________________________________________________ Name: tsvn:logminsize + 15 Name: svn:mime-type + application/octet-stream

Modified: library/trunk/lib/test/run.bat (16 => 17)


--- library/trunk/lib/test/run.bat	2006-08-15 17:27:10 UTC (rev 16)
+++ library/trunk/lib/test/run.bat	2006-08-18 18:12:11 UTC (rev 17)
@@ -26,7 +26,7 @@
 IF %PHP_BIN%  == "" GOTO ERROR1
 IF %PHP_INI%  == "" GOTO ERROR2
 
-%PHP_BIN% -c %PHP_INI% run.php %1 %2 %3 %4
+%PHP_BIN% -c %PHP_INI% run.php %1 %2 %3 %4 | ansi.exe
 GOTO END
 
 :ERROR1

Modified: library/trunk/lib/test/run.sh (16 => 17)


--- library/trunk/lib/test/run.sh	2006-08-15 17:27:10 UTC (rev 16)
+++ library/trunk/lib/test/run.sh	2006-08-18 18:12:11 UTC (rev 17)
@@ -15,7 +15,7 @@
 # * @category     config
 # */
 
-# path to php cli
+# path to php cli binary
 # example - /usr/bin/php
 php_bin=