www.pudn.com > wsc4c30.zip > ANSI.C


/* 
**  ansi.c 
** 
**  ANSI terminal emulator 
** 
**  Interprets ANSI escape sequences. Think of the keyboard 
**  and terminal as an external device and ANSI.C as its 
**  interface. 
** 
**  This module uses PAINT.C as its interface to the actual 
**  screen. 
** 
**  FEATURE             SUPPORTED 
**  =======             ========= 
**  Cursor positioning  Yes 
**  Underlining         No 
**  Blinking, inverse   No 
**  Color               No 
** 
*/ 
 
#include "windows.h" 
#include "paint.h" 
#include "ascii.h" 
#include "wsc.h" 
 
extern HWND hMainWnd; 
 
#define SIZE 40 
 
static int  Initialized = 0; 
static int  Debug = 0; 
static int  SavedRow = 0; 
static int  SavedCol = 0; 
static char ReportBuffer[SIZE]; 
static int  ReportLeft = 0; 
static int  ReportRight = 0; 
static char ListBuf[SIZE];      /* escape sequence buffer */ 
static int  ListCnt  = 0;       /* # characters in ListBuf[] */ 
 
static char EscSequence[4] = {27,'[','A','\0'}; 
 
/* add char to escape sequence list */ 
 
static void Add2List(char C) 
{if(ListCnt='0')&&(c<='9')) return TRUE; 
 else return FALSE; 
} 
 
/* is character alphabetic ? */ 
 
static int IsAlpha(char c) 
{if((c>='a')&&(c<='z')) return TRUE; 
 if((c>='A')&&(c<='Z')) return TRUE; 
 return FALSE; 
} 
 
/* 
** returns numeric parameter, advancing 
** list index to next non-numeric digit 
*/ 
 
static int EatDigits(int *IndexPtr) 
{int  Value = 0; 
 char Char; 
 /* while characters in escape sequence list */ 
 while(*IndexPtr < ListCnt) 
   {Char = ListBuf[*IndexPtr]; 
    if(IsDigit(Char)) 
      {Value = 10*Value + (Char - '0'); 
       (*IndexPtr)++; 
      } 
    else break; 
   } 
 return Value; 
} 
 
/* 
** The Escape sequence buffer is ready to interpret when: 
**   1) Sequence starts with "ESC [" , and 
**   2) Sequence ends with a alphabetic character. 
*/ 
 
static void Interpret(void) 
{int i; 
 int Index;  /* index into ListBuf[] */ 
 int Value;  /* parameter value */ 
 int Row; 
 int Col; 
 if(Debug) 
   {DisplayChar('['); 
    for(i=0;iNROWS) Row = NROWS; 
         PaintSetRow(Row); 
        } 
      break; 
    case 'C':  /*** ESC [ * C ***/ 
      Value = EatDigits(&Index); 
      if(Value==0) Value = 1; 
      if(Index==ListCnt-1) 
        {/* move right 1 column */ 
         Col += Value; 
         if(Col>NCOLS) Col = NCOLS; 
         PaintSetCol(Col); 
        } 
      break; 
    case 'D':  /*** ESC [ * D ***/ 
      Value = EatDigits(&Index); 
      if(Value==0) Value = 1; 
      if(Index==ListCnt-1) 
        {/* move left 1 column */ 
         Col -= Value; 
         if(Col<0) Col = 0; 
         PaintSetCol(Col); 
        } 
      break; 
    case 'f':  /***  ESC [ * ; * f  ***/ 
    case 'H':  /***  ESC [ * ; * H  ***/ 
               /***  ESC [ = * H    ***/ 
      if(ListBuf[2]=='=') 
         {Index++; 
          Value = EatDigits(&Index); 
          break; 
         } 
      Row = EatDigits(&Index) - 1; 
      if(ListBuf[Index]==';') 
        {Index++; 
         Col = EatDigits(&Index) - 1; 
        } 
      if(Index==ListCnt-1) 
        {PaintSetRow(Row); 
         PaintSetCol(Col); 
        } 
      break; 
    case 'J':  /***  ESC [ 2 J  ***/ 
      if((ListBuf[2]=='2')&&(ListCnt==4)) 
         {/* erase display */ 
          PaintClearScreen(); 
          break; 
         } 
      break; 
    case 'K': /***  ESC [ 2 K  ***/ 
      if((ListBuf[2]=='2')&&(ListCnt==4)) 
        {/* erase to EOL */ 
         PaintClearEOL(); 
        } 
      break; 
    case 'n': /***  ESC [ 6 n  ***/ 
      if((ListBuf[2]=='6')&&(ListCnt==4)) 
         {/* output Cursor Position ReportBuffer (CPR) */ 
          Row = PaintGetRow(); 
          Col = PaintGetCol(); 
          /* save up position report */ 
          wsprintf((LPSTR)ReportBuffer,"%c[%d;%dR",ESC,Row+1,Col+1); 
          ReportLeft = 0; 
          ReportRight = lstrlen((LPSTR)ReportBuffer) - 1; 
          break; 
         } 
      break; 
    case 'u':  /***  ESC [ u  ***/ 
      if((ListBuf[2]=='u')&&(ListCnt==3)) 
        {/* restore saved cursor position */ 
         PaintSetRow(SavedRow); 
         PaintSetCol(SavedCol); 
        } 
      break; 
    case 's':  /***  ESC [ s  ***/ 
      if((ListBuf[2]=='S')&&(ListCnt==3)) 
        {/* save cursor position */ 
         SavedRow = PaintGetRow(); 
         SavedCol = PaintGetCol(); 
        } 
      break; 
    default: 
      /* sequence not recognized or not supported */ 
      break; 
   } /* end-switch */ 
 ClearList(); 
} 
 
/**********************/ 
/*                    */ 
/*  PUBLIC functions  */ 
/*                    */ 
/**********************/ 
 
/* set/clear Debug flag */ 
 
void AnsiDebug(int Flag) 
{Debug = Flag; 
} 
 
/* display character */ 
 
int AnsiPutc(char C) 
{/* initialized ? */ 
 if(!Initialized) 
    {ClearList(); 
     Initialized = 1; 
    } 
 /* process character C */ 
 if(C==ESC) 
    {/* start new escape sequence */ 
     ListCnt = 0; 
     Add2List(ESC); 
     return 0; 
    } 
 else 
    {/* escape sequence started ? */ 
     if(ListCnt==0) 
        {DisplayChar(C); 
         return 1; 
        } 
     else 
        {/* add to escape sequence */ 
         Add2List(C); 
         /* last char in ListBuf[] alphabetic ? */ 
         if(IsAlpha(ListBuf[ListCnt-1])) 
           {/* ready to interpret */ 
            if(ListBuf[1]=='[') Interpret(); 
            else ListCnt = 0; 
           } 
         return 0; 
        } 
    } 
} 
 
/* display (null terminated) string */ 
 
int AnsiPuts(LPSTR String) 
{int i; 
 int Len = lstrlen(String); 
 for(i=0;i