Dev (Back & Front)ARTIGO

A importância do questionamento

Um dos meus comentários sobre um artigo que escrevi – Emperor’s New Clothes e Catch 22 (inglês) – foi que “uma das coisas mais valiosas que esses padrões oferecem é o vocabulário. Eles dão nome a algo.”, o que é um ponto importante que acho que deixei passar. A ideia é que, uma vez algo possui um nome,  você pode comunicar facilmente sobre esse algo. Por exemplo, é mais fácil dizer “Eu usei um Singleton” em vez de “Eu criei esta classe, onde há sempre apenas uma instância e essa instância está disponível para todas as outras classes no aplicativo”.

Sempre pensei que a nomeação, em geral, é crucial para escrever um bom software e que eu definitivamente vou escrever um artigo (ou dois) sobre o assunto algum dia. Por enquanto, basta dizer que, quando você vê um método ou uma classe que está mal nomeada, seja corajoso: corra e aperte o botão direito, Refatorar e renomear… Menu Opções, mas lembre-se: o truque consiste em encontrar o nome mais significativo.

Lendo artigo que citei acima, você pode ter a impressão de que sou contra padrões. Isso não pode estar mais distante da verdade, já que ao mesmo tempo que sou muito anti-anti-padrões, eu sou totalmente a favor deles, se eles forem exatamente de acordo com os padrões “Gang Of Four”, “Martin Fowler’s Patterns of Enterprise Application Architecture” ou qualquer outro padrão, mas eu ainda penso que o uso correto de padrões é também muito importante.

Uma das observações que deveriam ser feitas a respeito dos padrões GOF é que eles podem ser ranqueados em termos de utilidade, importância e popularidade. Por exemplo, praticamente todo desenvolvedor conhece Singleton (talvez por ele ser o mais simples?) e, caso já tenha usado o Spring, então você já se deparou com Strategy. Se você não usa Spring, então suspeito que é mais provável que você conheça os padrões de criação: Abstract Factory, Factory Method e Builder. Se você já fez algum trabalho JEE (conhecido como J2EE), então com certeza você já viu Facade sendo usado como interface para um EJB2.

Além disso, você pode usar ou ter usado Observer para informar um grupo de objetos sobre a mudança de estado de um, ou usado Template para definir um algoritmo estrutural, mas há aqueles padrões que você não costuma achar a necessidade de usar. Pegue o Memento, a maioria dos desenvolvedores já se deparou com isso na forma de Serializable, mas não me lembro de ter que implementar isso sozinho, exceto como um exercício de aprendizagem de Memento e então existe a State Machine.

Vi esse padrão pela primeira vez em 1989, cinco anos antes de o GOF ter publicado seu livro. Ele estava sendo usado em um emulador de terminal VT escrito em “C” no Windows 2.1 como parte de um projeto já extinto chamado CityDesk, produzido por uma empresa extinta chamada Apricot Computers. State Machine é muito útil na análise de fluxos de bytes de entrada, um byte de cada vez, para descobrir que ações tomar e, apenas para a posteridade, há uma parte do código CityDesk abaixo: não é bonito, não é Java, não é OO, mas é uma State Machine e que é anterior a GOF.

No entanto, voltando aos trilho… Enquanto State Machine é realmente útil para fazer os tipos de trabalho descritos acima, agora existem maneiras mais modernas de processamento de fluxos de bytes, que no caso do Java são fornecidos pela String do SDK, Streams e classes associadas como Pattern Matcher e etc. Então, State Machine está se tornando mais obsoleta ou existem bons outros usos para ela?

Para concluir este artigo, acho que devo reiterar que sou pró-padrões: um padrão utilizado no lugar apropriado fornece uma solução muito útil para um problema comum, mas acho que eles devem ser questionados de tempos em tempos. Padrões GOF têm estado por aí por muito tempo: eles podem ser melhorados? Eles ainda são tão relevantes hoje como eram quando o livro foi escrito? Questionar coisas é uma habilidade importante, se você não o fizer, então é provável que você se torne um programador Cargo Cult.

Você realmente não quer ver isto:

/*****************************************************************************/
/* */
/* 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;
}
}

?

Texto original disponível em http://www.captaindebug.com/2012/04/importance-of-questioning-design.html

Trabalha na empresa Bet365 desde 2012. É um programador e desenvolvedor Java com certificado em Sun, com considerável experiência em todos os aspectos do ciclo de desenvolvimento em ambientes financeiros. Seus recentes projetos incluem o uso de Java, Spring e Oracle.

Ver perfil