Tuesday, 10 April 2012

The Importance of Questioning

One of the comments my about my last blog Design Patterns, The Emperor’s New Clothes and Catch 22 was that “one of the most valuable things these patterns offer is vocabulary. They give something a name.”, which is an important point that I think I missed. The idea is that once something has a name then it’s something you can easily communicate about. For example, it’s easier to say “I’ve used a Singleton” rather than “I’ve created this class where there’s only ever one instance and that instance is available to all other classes in the application”

I’ve often thought that naming in general is crucial to writing good software and that I'll definitely write a blog (or two) on the subject at some point. Suffice to say for now that when you see a method or class that’s badly named be brave, leap in and hit the right click, Refactor and Rename... menu options1, but remember, the trick is in finding the most meaningful name.


In reading my previous blog you may get the impression that I’m anti-patterns. This could not be further from the truth, whilst I’m anti-anti-patterns I am wholly pro-patterns, whether they’re straight forward Gang Of Four patterns, Martin Fowler’s Patterns of Enterprise Application Architecture or any other pattern, but I also think that the appropriate use of patterns is also important.

One of the points that should be made about the GOF patterns is that they can be ranked in terms of usefulness, importance and popularity. For example, virtually every developer knows about Singleton (is this because it's the simplest?) and, if you’ve used Spring, then you’ll have come across Strategy. If you don’t use Spring then I suspect that you’re more likely to know about the creational patterns: Abstract Factory, Factory Method and Builder. If you’ve done some JEE (aka J2EE) work then you’re bound to have seen Facade being used as the interface to an EJB2.

Also, you may use or have used Observer to inform bunches of objects about the change in state of one object, or used Template to define a skeletal algorithm, but there are those patterns that you don’t often find the need to use. Take Memento, most developers have come across this in the form of Serializable, but I can’t remember having to implement it myself except as an exercise in learning Memento and then there’s State Machine.

I first saw this pattern in 1989, a full five years before the GOF published their book. It was being used in a VT Terminal emulator written in ‘C’ on Windows 2.1 as part of a now defunct project called CityDesk produced by a defunct company call Apricot Computers. State Machine is very useful in parsing incoming byte streams a byte at a time and figuring out what actions to take and, just for posterity, there’s a chunk of the CityDesk code below: it isn’t pretty, it isn’t Java, it isn’t OO, but it is a State Machine and it does predate the GOF.


However, getting back on track... whilst State Machine is really useful for doing the kinds job described above, there are now more modern ways of processing byte streams, which in the case of Java are provided by SDK’s String, Streams and associated classes such as Pattern, Matcher etc. So, is State Machine becoming more obsolete or are there other really good uses for it?

To conclude this blog I think I should reiterate that I am pro-patterns: a pattern used in the appropriate place provides a very useful solution to a common problem, but I do think that they should be questioned from time to time. GOF patterns have been around a long time: can they be improved? Are they still as relevant today as they were when the book was written? Questioning things is an important skill, if you don’t question things then you’re likely to simply become a Cargo Cult Programmer.

You Really Don’t Want to See This

/*****************************************************************************/
/*                                                                           */
/* Program / Project Name      Vt320 Terminal Emulation Package              */
/*                                                                           */
/* Module Name                 Vt220.c                                       */
/*                                                                           */
/* Description     Much changed but still compatible version of the earlier  */
/*                 version of the Term220 file                               */
/*  Contains the Vt320/220/100/52 State machine functions                    */
/*                                                                           */
/* Procedures Included  EmulateVT100  CheckForEscSequence  VT100Cntl         */
/*  VT100Esc  VT100Private                                                   */
/*                                                                           */
/* Updates       None                                                        */
/*     MID 11.07.1989 2.00.02   Cursor up and down now checks       */
/*            for cursor movement beyond the     */
/*            screen bounds.         */
/*                       */
/* Va 2.00.05 4:35pm 14/7/89                                                 */
/* Mod to clear the Status line of data if in HostWrite mode                 */
/*                       */
/* Vb 2.00.01 9:40am 22/8/89  Mods around line 547 on EndRow resetting     */
/*                       */
/* Vb 2.00.01 10:20am 22/8/89                                               */
/*   - Mod to new line action so that if the scroll region is smaller than   */
/*   the screen then the cursor cannot LF past the bottom of the screen      */
/*                       */
/*****************************************************************************/

/************************************************************************
*
        EmulateVT220 - VT220 Emulator
*
*************************************************************************/



#include <windows.h>
#include <lcdcomms.h>
#include <lcdwcom.h>
#include <cdk.h>

#include <lcdprod.h>
#include <lcdctrl.h>
#include <sc_print.h>
#include <term.h>
#include <term320.h>
#include <Winstuff.h>
#include <lcdtiff.h>   
/* Imports for grafs */
#include <funcdecs.h>

#include
"term220.h"
#include "Scroll.h"

#include "externs.h"



VOID    EmulateVT100 (lpCharBuff, Cnt)
LPSTR   lpCharBuff;
int     Cnt;
{
#ifdef TERM320
  extern BOOL tWatch;
#endif
  extern BOOL DisplayControls;
  extern UTC utc;
   BYTE   c;

  
while (Cnt--)    /* For all the characters in the buffer loop around and sort them out */
  
{
       
c = *lpCharBuff++;  /* make c the next char to process */



      /* Allow the VT320 double height stuff to work
       * in the clearing screen bit
       */
     
if(DecDWLHoldOff)
      {
     
DWLReset(ScreenVars.CurrentRow,ScreenVars.EndRow);
         DecDWLHoldOff = FALSE;
     
}

   
if(utc.Mode != UTC_NORMAL)
       
ProcessTheMessage(c); /* call this if we're in Unit trust mode */
   
else
    
{

     
if(DisplayControls)    /* for control characters display every thing */
        
{
        
BufferCharacters(c);
        
continue;
        
}
   
if(PrintController(c))  /* sort out any printing we may be doing */
     
continue;


      
switch (c/*  Check for control characters  */
       
{
       
case NULL:    /*  11.07.1989  MID  2.00.02  */
         
break;    /* this is here to stop the output th the screen when print controller is on */
       
case 11:
       
case '\n':      /* NEWLINE */
       
AddToScrollScreen(ScreenVars.CurrentRow);    /* put the line in the scrolling screen region */
          
AddLineAutoPrint(c);    /* put this line in the file */
       
if (fCaptureLine)
           
CaptureLine ();
           
if (ScreenVars.CurrentRow == ScreenVars.ScrollBottom)
         {
           
//ScrollVEx (&ScreenImage[0][0],
             //      &AttributeMap[0][0],
             //    NULL,
             //      (LPSCREENVARS)&ScreenVars,
             //      hWndMain,
             //    ScreenVars.ScrollTop,
             //    ScreenVars.ScrollBottom,
             //    1,
               //      (BUTTONDATA FAR *)&bd,
             //    (LPFONTVARS)&FontVars);
           
ScrollVEx (
                  
hWndMain,
                 ScreenVars.ScrollTop,
                 ScreenVars.ScrollBottom,
                
1);

          DWLScroll
(ScreenVars.ScrollTop,ScreenVars.ScrollBottom,1);
        
}
       
else if(ScreenVars.CurrentRow < ScreenVars.EndRow/* RH 22/8/89 Vb 2.0.01 */
           
++ScreenVars.CurrentRow;

       
/*  IF SEQUENCE LNM IS ACTIVE MOVE CURSOR TO COL 0  */
       
if (fLFCR)
           
ScreenVars.CurrentCol = 0;
             faNewLine = FALSE;
         
break;

           
case '\07':     /* BELL */
         
MessageBeep (0);
       
break;

           
case '\r':      /* CARRIAGE RETURN */
       
ScreenVars.CurrentCol = 0;
        faNewLine = FALSE;
               
break;

           
case '\b':      /* BACKSPACE */
         
if (ScreenVars.CurrentCol)
         
--ScreenVars.CurrentCol;
               
break;

           
case '\t':      /* TAB */
           
if (ScreenVars.CurrentCol < ScreenVars.EndCol)
         {
           
for (++ScreenVars.CurrentCol; ScreenVars.CurrentCol <= ScreenVars.EndCol; ScreenVars.CurrentCol++)
             {
             
if (ScreenVars.TabStops[ScreenVars.CurrentCol])
               
break;
            
}
         }
               
break;

           
case 0x7f:      /* Ignore delete character */
         
if(bd.Terminal.TermOptions.MapBackSpaceToDel && ScreenVars.CurrentCol)
           
--ScreenVars.CurrentCol;
               
break;

       
case 5/* ENQ  */
        
if(tWatch)
          
SendDataBlock(bd.Data2,lstrlen(bd.Data2),FALSE);
            SendAnswerBack
();
       
break;

       
case SO: /* move G1 on to GL */
           
CurrentSet = &CharacterSet1;
           
break;

       
case SI:  /* move G0 into GL */
           
CurrentSet = &CharacterSet0;
           
break;

     
default:   /*  Check for Escape sequences  */
       
CheckForEscSequence (c);
           
break;
       
}
    }
    } 
}

/************************************************************************
*  This function checks for escape sequences. If one is found it is
   processed. If not then it is a normal character and is displayed.
*
*************************************************************************/

VOID CheckForEscSequence (c)

BYTE    c;

{
 
extern BOOL DecUKKeyBoard;
   extern BYTE PoundSign;

   
switch (State)
   {
       
case NORMAL:
       
/*  CHANGE STATE TO LOOK OF ESCAPE SEQUENCE IF ESCAPE RECEIVED  */
     
if (c == ESC)
           
State = ESCED;
                   
/* check for an 8 bit escape sequence */
       
else if(bd.Terminal.TermOptions.Bits87 && ((c >= 0x80)&&(c <= 0x9f)))
          {
       
State = ESCED;      /* c - 0x40 puts the char back into the correct range */
           
c -= (BYTE)0x40;
        CheckForEscSequence
(c)/* ie. 0x9b - 0x40 = 0x5b or'['. hence respond to an ESC [ call */
         
}
       
/*  NORMAL CHARACTER THEN PUT INTO SCREEN BUFFER  */
       
else if (c >= 32)
         {
           
if(DecUKKeyBoard && (c == PoundSign))
              
c = 0x9c;
           BufferCharacters
(c);
        
}
          
break;

   
case POSS_DECSTR:  /* a possible soft reset is on the way */
     
if(c == ESC)
        {
            
State = ESCED;
       
break;
       
}
     
else if((c == 'p') && (bd.Terminal.TermOptions.TermType != CDK_VT100))  
          
DecStr();
     
if(c != 'p')
       
State = SQU_ERROR;
     
else
         
State = NORMAL;
       
break;

       
case ESCED:
     
if(c == ESC)
        {
            
State = ESCED;
       
break;
       
}
     
else if (c == '(')
              
State = CHARSET_G0;
         
else if (c == ')')
              
State = CHARSET_G1;
         
else if (c == 'P')
          {
          
ClrParam();
           State = PARAMS;
           Pnum2 =
0;
         
}
       
else  /* CONTROL SEQUENCE INTRODUCER */
           
if (c == '[')
             {
             
ClrParam ();
              State = PARAMS;
            
}
       
else /* INTERMEDIATE CHARACTERS */
           
if (c > 0x20 && c <= 0x2f)
             
State = ESCSQU;
       
else if(c == ' '/* check for an ESC' ' input to switch mode */
       
State = CONTROLXMIT;
       
else if (c >= 0x30 && c <= 0x7e)
             
VT100Esc (c);
       
else
              
State = SQU_ERROR;
        
break;

     
case ESCSQU:
     
if(c == ESC)
        {
            
State = ESCED;
       
break;
       
}
     
else if (c >= 0x30 && c <= 0x7e)
             
VT100Esc (c);
           
break;

      
case PARAMS: /* PARAMETER CHARACTERS */      /*NEWBIT*/
         
if (Pnum == 0 && c >= 0x3c && c <= 0x3f)
             
fPrivate = TRUE;
         
else if (c == IMMED)
             
State = NORMAL;
       
else if ((c == '|')&&(Pnum2 < NO2PARAMS))
         {
         
FlagDCS = TRUE;
          Param2
[Pnum2++] = c;
        
}
       
else if ((FlagDCS == TRUE) && (c == 0x1b))
            
FlagDCS = FALSE;
          
else if((c == 0x22) && (Pnum2 < NO2PARAMS))
           
Param2[Pnum2] = c;
       
else if (c >= '0' && c <= '9')
             {
             
if (Pnum2 < NO2PARAMS)
             
Param2[Pnum2++] = c;
       
if(Pnum < NOPARAMS)
          {
              
Param[Pnum] *= 10;
                 Param
[Pnum] += (c - '0');
         
}
             }
           
else if (c == ';')
             {
              
if(++Pnum > (NOPARAMS - 1))
                    
State = NORMAL;
         
if(++Pnum2 < NO2PARAMS)
               
Param2[Pnum2] = c;
            
}
       
else if ((FlagDCS == TRUE)&&(Pnum2 < NO2PARAMS))
          
Param2[Pnum2++] = c;
       
else if(c == '$'/* a dollar sign for the status line Escape sequences */
       
State = STATUSLINE_ESCSEQ;
       
else if(c == '!')        
       
State = POSS_DECSTR;     /* a possible soft reset is on the way */
     
else if(c == ESC)
       
State = ESCED;      /* an unterminated esc sequence */
       
else
            
{
           
if (fPrivate || (c >= 0x70 && c <= 0x7e))
               
VT100Private (c);
               
else
                   
VT100Cntl (c);
               fPrivate = FALSE;
             
}
     
            
break;

     
case CHARSET_G1:
     
if(c == ESC)
        {
            
State = ESCED;
       
break;
       
}
       
else if (c == '0')
           
CharacterSet1 = TRUE;   /*  move Dec Graphics in to G1 */
     
else              /* this covers A and B */
           
CharacterSet1 = FALSE;  /*  ASCII into G1 */

         
State = NORMAL;
       
break;   

   
case CHARSET_G0:
     
if(c == ESC)
        {
            
State = ESCED;
       
break;
       
}
         
else if (c == '0')
           
CharacterSet0 = TRUE;   /*  Graphics  */
     
else              /* this covers A and B */
           
CharacterSet0 = FALSE;  /*  ASCII  */

         
State = NORMAL;
         
break;

   
case STATUSLINE_ESCSEQ:    /* act on a status line esacpe sequence */
     
if(c == ESC)
        {
            
State = ESCED;
       
break;
       
}
       
VT100Cntl(c);
       
break;
   
case CONTROLXMIT:  /* a possible change of control code bits is on the way */
     
if(c == ESC)
        {
            
State = ESCED;
       
break;
       
}
       
SelectTransmissionStyle(c);
       
break;
   
case SQU_ERROR:
     
if(c == ESC)
       
State = ESCED;
     
else if ((c >= '@') && (c < 0x7f))
       
State = NORMAL;
       
     
break;
   
default:
     
if(c == ESC)
            
State = ESCED;
     
else
             
State = NORMAL;
       
break;
   
}
}












/************************************************************************
*
        VT100Cntl - Check for VT100 Control escape sequences
*
*************************************************************************/

VOID    VT100Cntl (c)
BYTE    c;
{
#ifdef TERM320
   extern BOOL tWatch;
#endif
   
int    lines;



  State = NORMAL;
   
switch (c)
     {
       
/*
           INSERT PARAM[0] BLANK CHARS AT CURSOR POSITION
           WITH THE CHARACTER ATTRIBUTES SET TO NORMAL
        */
       
case ICH:  /* Vt200 and greater */
       
if(bd.Terminal.TermOptions.TermType != CDK_VT100)
          {
         
/*  INSERT AT LEAST 1 CHARACTER  */
         
if (Param[0] == 0)
           
Param[0] = 1;
          InsertCharacterEx
(&ScreenImage[0][0],
                 &AttributeMap
[0][0],
               NULL,
              
(LPSCREENVARS)&ScreenVars,
               Param
[0]);
         
}
       
break;

       
/*
            DELETE PARAM[0] CHARACTERS STARTING AT THE CURSOR POSITION
        */
       
case DCH:
       
/*  DELETE AT LEAST 1 CHARACTER  */
       
if (Param[0] == 0)
         
Param[0] = 1;
        DeleteCharacterEx
(&ScreenImage[0][0],
               &AttributeMap
[0][0],
             NULL,
            
(LPSCREENVARS)&ScreenVars,
             Param
[0]);
       
break;

       
/*
           INSERT PARAM[0] LINES
        */
       
case IL:
       
/*  INSERT AT LEAST 1 LINE  */
       
if (Param[0] == 0)
           
Param[0] = 1;

        InsertLineEx
(&ScreenImage[0][0],
                     &AttributeMap
[0][0],
            NULL,
           
(LPSCREENVARS)&ScreenVars,
            Param
[0]);
        SetCursorPosition
((LPSCREENVARS)&ScreenVars,
                    
(LPVTFLAGS)&VTFlags,
                   ScreenVars.CurrentRow,
                  
0,
                  
2);
       
break;

       
/*
            DELETE PARAM[0] LINES STARTING AT THE LINE WITH CURSOR
        */
   
case DL:
       
/*  DELETE AT LEAST 1 LINE  */
       
if (Param[0] == 0)
           
Param[0] = 1;

        DeleteLineEx
(&ScreenImage[0][0],
                  &AttributeMap
[0][0],
            NULL,
           
(LPSCREENVARS)&ScreenVars,
            Param
[0]);
        SetCursorPosition
((LPSCREENVARS)&ScreenVars,
                    
(LPVTFLAGS)&VTFlags,
                   ScreenVars.CurrentRow,
                  
0,
                  
2);
           
break;

   
case 0x5c: /* DECUDK   VT220 ONLY */
       
SetupFunctionKeys (Param2);
       
break;

       
/* CURSOR MOVEMENT */
       
case CUB:       /* LEFT */
       
if (ScreenVars.CurrentCol)
         {
           
if (Param[0] == 0)
         
Param[0] = 1;
       
if ((ScreenVars.CurrentCol - Param[0]) >= 0)
                 
ScreenVars.CurrentCol = ScreenVars.CurrentCol - Param[0];
       
else
           
ScreenVars.CurrentCol = 0;
        
}
           
break;

       
case CUF:       /* RIGHT */
       
if (ScreenVars.CurrentCol < ScreenVars.EndCol)
         {
           
if (Param[0] == 0)
         
Param[0] = 1;
       
if ((ScreenVars.CurrentCol + Param[0]) <= ScreenVars.EndCol)
                 
ScreenVars.CurrentCol = ScreenVars.CurrentCol + Param[0];
       
else
           
ScreenVars.CurrentCol = ScreenVars.EndCol;
        
}
           
break;

       
case CUU:       /* UP */
       
if(!bSLWrite)
          {
         
AddToScrollScreen(ScreenVars.CurrentRow);    /* put the line in the scrolling screen region */
         
if (fCaptureLine)
           
CaptureLine ();
            AddLineAutoPrint
(LF);    /* put this line in the file */
       
/****  MID 11.07.1989 2.00.02  */
         
if (ScreenVars.CurrentRow > ScreenVars.ScrollTop)
           {
             
if (Param[0] == 0)
             
Param[0] = 1;
              ScreenVars.CurrentRow = ScreenVars.CurrentRow - Param
[0];

           
if (ScreenVars.CurrentRow < ScreenVars.ScrollTop)
           
ScreenVars.CurrentRow = ScreenVars.ScrollTop;
          
}
          }
            
break;

       
case CUD:       /* DOWN */
       
if(!bSLWrite)
         {
         
AddToScrollScreen(ScreenVars.CurrentRow);    /* put the line in the scrolling screen region */
         
if (fCaptureLine)
           
CaptureLine ();
            AddLineAutoPrint
(LF);    /* put this line in the file */
       
/****  MID 11.07.1989 2.00.02  */
         
if (ScreenVars.CurrentRow < ScreenVars.ScrollBottom)
           {
               
if (Param[0] == 0)
             
Param[0] = 1;
                ScreenVars.CurrentRow = ScreenVars.CurrentRow + Param
[0];

           
if (ScreenVars.CurrentRow > ScreenVars.ScrollBottom)
           
ScreenVars.CurrentRow = ScreenVars.ScrollBottom;
          
}
          }
           
break;
       
case CUP:       /* CURSOR POSITION (HOME) */
       
case HVP:       /* HORIZONTAL & VERTICAL POSITION */
        /* RH Vb 2.00.01 Save the current value */
       
lines = ScreenVars.EndRow;    /* save the current end row in a convenient store */
       
if (fCaptureLine)
           
CaptureLine ();

            AddLineAutoPrint
(LF);    /* put this line in the file */
       
AddToScrollScreen(ScreenVars.CurrentRow);    /* put the line in the scrolling screen region */
       
if (Param[0] > 0)
           
--Param[0];
       
if (Param[1] > 0)
           
--Param[1];

       
/* if a VT320 term and in host write mode with the SL accessed then only the columns are affected */
       
if((bd.Terminal.TermOptions.TermType == CDK_VT320)&& bSLWrite)
       
ScreenVars.EndRow = Param[0] = LASTLINE;

        SetCursorPosition
((LPSCREENVARS)&ScreenVars,
                 
(LPVTFLAGS)&VTFlags,
                Param
[0],
                Param
[1],
               
2);
        faNewLine = FALSE;


       
/* RH Vb 2.00.01 added the ifdef */
       
ScreenVars.EndRow = lines;    /* reset the bottom row */
       
break;


   
case 'i':
       
switch (Param[0])
         {
         
case 0:    /*  PRINT SCREEN  */
              
ScreenPrint();
           
break;

       
case 5:    /*  ACTIVATE PRINTER CONTROLLER  Esc[5i */
           
DoPrintControl();
           
break;
        
}
       
break;

   
case 'h':
       
switch (Param[0])
         {
           
case 20: /* CAUSES LINE FEED TO DO A CR.  RETURN - CR & LF  */
               
fLFCR = TRUE;
           
break;

       
case 4/*  IRM  Insert mode  */ /*NEWBIT*/
               
VTFlags.WriteMode = TRUE; 
           
break;

       
case 12: /*  SRM  Local echo off  */
           
bd.Terminal.TermOptions.LocalEcho = FALSE;
           
break;
       
case 2/*  KAM  Lock keyboard  */
           
fKeyLock = TRUE;
           
break;
       
}
       
break;

   
case 'l'/* SWITCH ABOVE OFF */
       
switch (Param[0])
         {
           
case 20: /* LINE FEED TO JUST LF  */
               
fLFCR = FALSE;
         
break;

       
case 4/*  IRM  Replace mode  */
                 
VTFlags.WriteMode = FALSE; 
           
break;

       
case 12: /*  SRM  Local echo on  */
           
bd.Terminal.TermOptions.LocalEcho = TRUE;
           
break;

       
case 2/*  KAM  Unlock keyboard  */
           
fKeyLock = FALSE;
           
break;

        
}
       
break;

       
case ECH:  /* ERASE CHARACTER  VT220 ONLY */
       
if (Param[0] == 0)
            
Param[0] = 1;
     
       
if (Param[0] <= (BYTE)(((ScreenVars.EndCol + 1) - ScreenVars.CurrentCol)))
         
ClearEx (&ScreenImage[0][0],
                  &AttributeMap
[0][0],
                  NULL,
                  hWndMain,
                     
(LPSCREENVARS)&ScreenVars,
                 
(LPFONTVARS)&FontVars,
                  ScreenVars.CurrentRow,
                  ScreenVars.CurrentCol,
                  ScreenVars.CurrentRow,
                  ScreenVars.CurrentCol + Param
[0] - 1,
                  FALSE
);
       
else
        
{
         
Param[0] = Param[0] - ((ScreenVars.EndCol + 1) - ScreenVars.CurrentCol);
        lines = Param
[0] / (ScreenVars.EndCol + 1);
        Param
[0] = Param[0] - ((ScreenVars.EndCol + 1) * lines);
        ClearEx
(&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
               ScreenVars.CurrentRow,
               ScreenVars.CurrentCol,
               ScreenVars.CurrentRow + lines +
1,
               Param
[0],
               FALSE
);
        
}
       
break;

       
case ED:   /* DISPLAY */
     
if (Param[0] == 0/*  Erase from cursor to end of screen  */
    
{
       
ClearEx (&ScreenImage[0][0],
           &AttributeMap
[0][0],
           NULL,
           hWndMain,
              
(LPSCREENVARS)&ScreenVars,
          
(LPFONTVARS)&FontVars,
           ScreenVars.CurrentRow,
           ScreenVars.CurrentCol,
           ScreenVars.EndRow,
           ScreenVars.EndCol,
           FALSE
);
         DecDWLHoldOff = TRUE;  
    
}
     
else
      if
(Param[0] == 1/* Erase from screen start to cursor  */
    
{
       
ClearEx (&ScreenImage[0][0],
           &AttributeMap
[0][0],
           NULL,
           hWndMain,
              
(LPSCREENVARS)&ScreenVars,
          
(LPFONTVARS)&FontVars,
          
0,
          
0,
           ScreenVars.CurrentRow,
           ScreenVars.CurrentCol,
           FALSE
);
      DWLReset
(0,ScreenVars.CurrentRow);
    
}
     
else
      if
(Param[0] == 2/*  Erase all of screen  */
      
{
       
ClearEx (&ScreenImage[0][0],
           &AttributeMap
[0][0],
           NULL,
           hWndMain,
              
(LPSCREENVARS)&ScreenVars,
          
(LPFONTVARS)&FontVars,
          
0,
          
0,
           ScreenVars.EndRow,
           ScreenVars.EndCol,
           FALSE
);
      DWLReset
(0,ScreenVars.EndRow);
      
}
     
break;

       
case EL: /* LINE */
       
if (Param[0] == 0/*  Erase from cursor to EOL  */
         
ClearEx (&ScreenImage[0][0],
                 &AttributeMap
[0][0],
                 NULL,
                 hWndMain,
                    
(LPSCREENVARS)&ScreenVars,
                
(LPFONTVARS)&FontVars,
                 ScreenVars.CurrentRow,
                 ScreenVars.CurrentCol,
                 ScreenVars.CurrentRow,
                 ScreenVars.EndCol,
                 FALSE
);
       
else
        if
(Param[0] == 1/*  Erase from line start to cursor  */
         
ClearEx (&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
               ScreenVars.CurrentRow,
              
0,
               ScreenVars.CurrentRow,
               ScreenVars.CurrentCol,
               FALSE
);
       
else
        if
(Param[0] == 2/*  Erase whole line  */
         
ClearEx (&ScreenImage[0][0],
             &AttributeMap
[0][0],
             NULL,
             hWndMain,
                
(LPSCREENVARS)&ScreenVars,
            
(LPFONTVARS)&FontVars,
             ScreenVars.CurrentRow,
            
0,
             ScreenVars.CurrentRow,
             ScreenVars.EndCol,
             FALSE
);
       
break;
       
case TBC:       /* TABULATION CLEAR */
       
if (Param[0] == 0)
           
/*  CLEAR TAB STOP AT CURSOR POSITION  */
           
ClearTabStop ((LPSCREENVARS)&ScreenVars, ScreenVars.CurrentCol);
       
else if (Param[0] == 3)
         
/*  CLEAR ALL TAB STOPS  */
         
ClearTabStop ((LPSCREENVARS)&ScreenVars, -1);
       
       
break;

   
case DA:
       
if (Param[0] == 0)
         {
#ifdef TERM320
        
if(tWatch)
          
SendDataBlock(IdentifyString,16,FALSE);
#endif
        PutComm
(hWndMain,(LPSTR)IdentifyString, 16,(LPBUTTONDATA)&bd,(LPCOMMSVARS)&CommsVars,(BOOL FAR *)&fWaitingConnection);
        
}
       
break;

   

   
case DECSSDT:    /* if the status line is being talked to then switch it off */
       
SLReset();
        SetSLMode
()/* switch the status line mode */
       
break;

   
case DECSASD:
        SwitchStatusLine
();
       
break;

   
case SGR:       /* Select Graphic Rendition */
       
Sgr();
     
break;

   
default:
     
if((c < '@') || (c > 0x7e))
       
State = SQU_ERROR;
       
break;
  
}
}






/************************************************************************
*
        VT100Esc - Check for VT100 normal escape sequences
*
*************************************************************************/

VOID    VT100Esc (c)
BYTE    c;
{
#ifdef TERM320
   extern BOOL tWatch;
#endif
  
int i;


  State = NORMAL;

  
switch (c)
   {
       
case RIS:
        ResetTerminal
();
       
break;

       
case '=':
        VTFlags.fAppKeypad = TRUE;
           
break;

       
case '>':
        VTFlags.fAppKeypad = FALSE;
           
break;

       
case DECID:    /* Device attributes (WHAT ARE YOU) */
#ifdef TERM320
     
if(tWatch)
        
SendDataBlock(IdentifyString,16,FALSE);
#endif
        PutComm
(hWndMain,(LPSTR)IdentifyString, 16,(LPBUTTONDATA)&bd,(LPCOMMSVARS)&CommsVars,(BOOL FAR *)&fWaitingConnection);
        
break;

       
case IND:    /* CURSOR DOWN WITH SCROLL */
       
if (ScreenVars.CurrentRow < ScreenVars.ScrollBottom)
           
++ScreenVars.CurrentRow;
       
else
        if
(ScreenVars.CurrentRow == ScreenVars.ScrollBottom)
        {
           
//ScrollVEx (&ScreenImage[0][0],
          //     &AttributeMap[0][0],
          //     NULL,
          //     (LPSCREENVARS)&ScreenVars,
            //   hWndMain,
         //  ScreenVars.ScrollTop,
         //  ScreenVars.ScrollBottom,
         //  1,
            //   (BUTTONDATA FAR *)&bd,
        //   (LPFONTVARS)&FontVars);
           
ScrollVEx (
                  
hWndMain,
                 ScreenVars.ScrollTop,
                 ScreenVars.ScrollBottom,
                
1);

          DWLScroll
(ScreenVars.ScrollTop,ScreenVars.ScrollBottom,1);
       
}
           
break;

       
case RI:     /* CURSOR UP WITH SCROLL */
       
if (ScreenVars.CurrentRow > ScreenVars.ScrollTop)
           
--ScreenVars.CurrentRow;
       
else
        if
(ScreenVars.CurrentRow == ScreenVars.ScrollTop)
        {
       
//ScrollVEx (&ScreenImage[0][0],
          //       &AttributeMap[0][0],
          //       NULL,
         //    (LPSCREENVARS)&ScreenVars,
         //    hWndMain,
         //    ScreenVars.ScrollTop,
         //    ScreenVars.ScrollBottom,
         //    -1,
            //      (BUTTONDATA FAR *)&bd,
        //      (LPFONTVARS)&FontVars);
         
ScrollVEx (hWndMain,
                    ScreenVars.ScrollTop,
                    ScreenVars.ScrollBottom,
                    -
1);

         DWLScroll
(ScreenVars.ScrollTop,ScreenVars.ScrollBottom,-1);
        
}
           
break;

       
case NEL:    /* NEXT LINE WITH SCROLL */
       
if (ScreenVars.CurrentRow == ScreenVars.ScrollBottom)
        {
           
//ScrollVEx (&ScreenImage[0][0],
          //       &AttributeMap[0][0],
          //       NULL,
         //    (LPSCREENVARS)&ScreenVars,
           //       hWndMain,
         //    ScreenVars.ScrollTop,
         //    ScreenVars.ScrollBottom,
         //    1,
            //      (BUTTONDATA FAR *)&bd,
        //      (LPFONTVARS)&FontVars);
         
ScrollVEx(hWndMain,
                    ScreenVars.ScrollTop,
                   ScreenVars.ScrollBottom,
                  
1);


          DWLScroll
(ScreenVars.ScrollTop,ScreenVars.ScrollBottom,1);
      
}
       
else
           
++ScreenVars.CurrentRow;
        ScreenVars.CurrentCol =
0;
           
break;

   
case DECSC:
        DecSc
()/*NEWBIT*/
           
break;

       
case DECRC:
       
if(!CurSaveDone)    /* if not save was done then we use the default settings */
         
SaveCursor = DefaultCursor;

        CurSaveDone = FALSE;
        ScreenVars.CurrentCol = SaveCursor.Col;
        ScreenVars.CurrentRow = SaveCursor.Row;
        bd.Terminal.TermOptions.Autowrap = SaveCursor.Wrap;
        VTFlags.fOrigin = SaveCursor.Origin;
        VTFlags.SelectErasable = SaveCursor.SelectErase;
        CharacterSet0 = SaveCursor.Chars0;
        CharacterSet1 = SaveCursor.Chars1;
     
if(SaveCursor.CurrentSet)
       
CurrentSet = &CharacterSet1;
     
else
       
CurrentSet = &CharacterSet0;
        fBold = SaveCursor.Bold;
        fUnderscore = SaveCursor.Under;
        fBlink = SaveCursor.Blink;
        fReverse = SaveCursor.Reverse;
           
break;

       
case HTS:
        ScreenVars.TabStops
[ScreenVars.CurrentCol] = 1;
     
break;

   
case 'N':
   
case 'O':
        fOneNormal = TRUE;
       
break;

   
case 'Z':
#ifdef TERM320
     
if(tWatch)
        
SendDataBlock(IdentifyString,16,FALSE);
#endif
        PutComm
(hWndMain,(LPSTR)IdentifyString, 16,(LPBUTTONDATA)&bd,(LPCOMMSVARS)&CommsVars,(BOOL FAR *)&fWaitingConnection);
       
break;    
   
case DECSWL:    /* reset to a single width line */
       
DecDWL[ScreenVars.CurrentRow].LineUsed = FALSE;
      DecDWL
[ScreenVars.CurrentRow].LineType = ZERO;
         ScreenVars.LineUpdate
[ScreenVars.CurrentRow] = TRUE;
       
break;

   
case DECDHLTOP:
   
case DECDHLBOT:
   
case DECDWL:    /* set up for single height double width */
       
if(!DecDWL[ScreenVars.CurrentRow].LineUsed)
         
ClearEx (&ScreenImage[0][0],            /* clear the 2nd hlaf of the line */
                
&AttributeMap[0][0],
                 NULL,
                 hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
                
(LPFONTVARS)&FontVars,
                 ScreenVars.CurrentRow,
                 ScreenVars.EndCol/
2,
                 ScreenVars.CurrentRow,
                 ScreenVars.EndCol,
                 FALSE
);

         ScreenVars.LineUpdate
[ScreenVars.CurrentRow] = FALSE;
      DecDWL
[ScreenVars.CurrentRow].LineUsed = TRUE;
      DecDWL
[ScreenVars.CurrentRow].LineType = c;  /* the type of line */
        
break;
   
default:
     
if((c < '@') || (c > 0x7e))
         
State = SQU_ERROR;
       
break;
  
}
}







/************************************************************************
*
        VT100Private - Check for VT100 private sequences
*
*************************************************************************/

VOID    VT100Private (c)

BYTE    c;

{
   
extern     WORD fOldTermType;
    extern  BOOL ReverseScreen;
   
int    line,col;
    BYTE  forecolor,
         backcolor;
    LPBYTE tAttri;
    WORD  temp;

#define DECSCL   
0x70  /* 'p' Selects Terminal type */

#define VT100MODE  61   
#define VT200MODE  62  /* the two possible modes */

 
State = NORMAL;

   
switch (c)
     {
   
case DECSCL:      /* 'p' Terminal type set up */
       
if(Param[0] == VT100MODE/* 61 */
         
{
       
SelectTransmissionStyle('F');
          bd.Terminal.TermOptions.TermType = CDK_VT100;
         
}
       
else  /* this is 62 but assume any other numer gives us back a VT320 */
         

         
bd.Terminal.TermOptions.TermType = CDK_VT320;
           
if(Param[1] == (BYTE)1)
          
SelectTransmissionStyle('F');
           
else
          
SelectTransmissionStyle('G');
         
}
       
break;
           
   
case 'q': /* DECSCA SELECT CHARACTER ATTRIBUTES VT220 */
       
if(bd.Terminal.TermOptions.TermType != CDK_VT100)
          {
         
if((Param[0] == 0) || (Param[0] == 2))
             
VTFlags.SelectErasable = FALSE;
         
else /* if (Param[0] == 1) */
             
VTFlags.SelectErasable = TRUE;
         
}
       
break;

       
case ED: /* SELECTIVE DISPLAY ERASE VT220 */
       
if (Param[0] == 0/*  Erase from cursor to end of screen  */
         
ClearEx (&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
               ScreenVars.CurrentRow,
               ScreenVars.CurrentCol,
               ScreenVars.EndRow,
               ScreenVars.EndCol,
               TRUE
);
       
else
        if
(Param[0] == 1/* Erase from screen start to cursor  */
         
ClearEx (&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
              
0,
              
0,
               ScreenVars.CurrentRow,
               ScreenVars.CurrentCol -
1,
               TRUE
);
       
else
        if
(Param[0] == 2/*  Erase all of screen  */
         
ClearEx (&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
              
0,
              
0,
               ScreenVars.EndRow,
               ScreenVars.EndCol,
               TRUE
);
       
break;

       
case EL: /* SELECTIVE LINE ERASE VT220 */
       
if (Param[0] == 0/*  Erase from cursor to EOL  */
         
ClearEx (&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
               ScreenVars.CurrentRow,
               ScreenVars.CurrentCol,
               ScreenVars.CurrentRow,
               ScreenVars.EndCol,
               TRUE
);
       
else
        if
(Param[0] == 1/*  Erase from line start to cursor  */
         
ClearEx (&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
               ScreenVars.CurrentRow,
              
0,
               ScreenVars.CurrentRow,
               ScreenVars.CurrentCol,
               TRUE
);
       
else
        if
(Param[0] == 2/*  Erase whole line  */
         
ClearEx (&ScreenImage[0][0],
               &AttributeMap
[0][0],
               NULL,
               hWndMain,
                  
(LPSCREENVARS)&ScreenVars,
              
(LPFONTVARS)&FontVars,
               ScreenVars.CurrentRow,
              
0,
               ScreenVars.CurrentRow,
               ScreenVars.EndCol,
               TRUE
);
       
break;

       
case DECSTBM:
        NewScrollSet
(TRUE)/* SET Scrolling Region */
       
break;

       
case 'l':
       
case 'h':
       
case 'i':
           
switch (Param[0])
             {
               
case DECCKM:    /* APPLICATION / CURSOR MODES */
           
DecCkm(c);
           
break;
       
case DECANM:      /* VT52 Mode */
           
if (c == 'l')
              {
              
fOldTermType = bd.Terminal.TermOptions.TermType;
            bd.Terminal.TermOptions.TermType = CDK_VT52;
             
}
           
break;
       
case DECCOLM:     /* COLUMN */
           
if (!bd.Terminal.TermOptions.Cursor)
                      
HideCaret (NULL);
           
if((bd.Terminal.TermOptions.TermType == CDK_VT320)&&(bd.Terminal.TermOptions.StatusLine == CDK_HOSTWRITE))
              {
              
tEndRow = ScreenVars.EndRow;
              ScreenVars.EndRow = LASTLINE;
             
}

           
if (c == 'h')
             {
               
ChangeColMode (&ScreenImage[0][0],
                          &AttributeMap
[0][0],
                          NULL,
                     hWndMain,
                    
(LPFONTVARS)&FontVars,
                    
(LPSCREENVARS)&ScreenVars,
                    
(LPVTFLAGS)&VTFlags,
                     LASTCOL,
(LPBUTTONDATA)&bd);
           
if (VTFlags.fMaximized)    /* if we're maximized then add the scroll bar */
               
SetScrollBars (TRUE);

                ChangeVTFont
(hWndMain,AutoFontSelection((LPFONTSIZE)&FontSize[0],     /*  MID  29/06/1989  */
                
hWndMain,
                
(LPSCREENVARS)&ScreenVars,
                 FontVars.FontsLoaded
))

              InvalidateRect
(hWndMain,NULL,TRUE);
              
}
           
else
            if
(c == 'l')
             {
               
ChangeColMode (&ScreenImage[0][0],
                          &AttributeMap
[0][0],
                          NULL,
                     hWndMain,
                        
(LPFONTVARS)&FontVars,
                    
(LPSCREENVARS)&ScreenVars,
                    
(LPVTFLAGS)&VTFlags,
                     ID_80COL,
(LPBUTTONDATA)&bd);

           
if (VTFlags.fMaximized)    /* if we're maximized then remove the scroll bar */
               
SetScrollBars (FALSE);

                   ChangeVTFont
(hWndMain,AutoFontSelection((LPFONTSIZE)&FontSize[0],     /*  MID  29/06/1989  */
                
hWndMain,
                
(LPSCREENVARS)&ScreenVars,
                 FontVars.FontsLoaded
));

              InvalidateRect
(hWndMain,NULL,TRUE);
            
}

           
if((bd.Terminal.TermOptions.TermType == CDK_VT320)&&(bd.Terminal.TermOptions.StatusLine == CDK_HOSTWRITE))
           
ScreenVars.EndRow = tEndRow;

           
if(!bd.Terminal.TermOptions.Cursor && (GetFocus() == hWndMain))
              {
             
SetCaretPos (CaretXPos(), CaretYPos());
            ShowCaret
(NULL);
             
}
           
/* set Param array before resetting the scroll region */
           
Param[0] = 1;
            Param
[1] = 24/* default vals */
           
Pnum = 2;
            NewScrollSet
(TRUE);  
                  
break;
               
case DECSCNM:   /* SCREEN REVERSE / NORMAL */
           
if (c == 'i')
             
StartAutoPrint(DO_TITLE)/* Start the auto print mode */
           
else
            

           
if((!ReverseScreen && (c == 'h')) || (ReverseScreen && (c == 'l')))
              {
                    
ReverseScreenEx((LPSTR)bd.Data,(LPSTR)AttributeMap,(LPSCREENVARS)&ScreenVars);

                    
for (line = 0; line < LASTLINE; line++)
                       
if(!DecDWL[line].LineUsed)
                      
ScreenVars.LineUpdate[line] = TRUE;
                    
               
if(c == 'h')
                 
ReverseScreen = TRUE;     /* set up for soft terminal reset */
               
else
                 
ReverseScreen = FALSE;
           
}
              }
                 
break;

               
case DECOM:     /* ORIGIN */
           
DecOm(c);
                    
break;

                
case DECAWM:    /* AUTOWRAP */
              
DecAwm(c);
                    
break;

                
case DECTCEM:  /*  Hide and show cursor  */
           
DecTcem(c);
           
break;

                
case AUTOPRNOFF:  /* Auto Print Off */
           
if(c == 'i')
           
EndAutoPrint(DO_TITLE)/* End the auto print mode */
                    
break;

       
case DECPFF:  /*  MID  12/09/1988   FF after print screen  */
           
if (c == 'h')
               
VTFlags.fFormFeed = TRUE;
           
else
            if
(c == 'l')
               
VTFlags.fFormFeed = FALSE;
           
break;

       
case DECPEX:  /*  MID  12/09/1988   Print region  */
           
if (c == 'h')
               
VTFlags.fPrintExtent = FALSE;
           
else
            if
(c == 'l')
               
VTFlags.fPrintExtent = TRUE;
           
break;

            
}
     
break;
   
default:
     
if((c < '@') || (c > 0x7e))
       
State = SQU_ERROR;
     
break;
    
}
}


1In eclipse.

No comments: