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:
Post a comment