Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1693 lines
44 KiB

/* File: \wacker\emu\vt220.c (Created: 28-Jan-1998)
*
* Copyright 1998 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 8 $
* $Date: 5/09/01 4:48p $
*/
#include <windows.h>
#pragma hdrstop
#include <tdll\stdtyp.h>
#include <tdll\tdll.h>
#include <tdll\htchar.h>
#include <tdll\session.h>
#include <tdll\cloop.h>
#include <tdll\assert.h>
#include <tdll\print.h>
#include <tdll\update.h>
#include <tdll\capture.h>
#include <tdll\backscrl.h>
#include <tdll\chars.h>
#include <tdll\mc.h>
#include "emu.h"
#include "emu.hh"
#include "emudec.hh"
#if defined(INCL_VT220)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220_hostreset
*
* DESCRIPTION:
* Calls vt220_reset() when told by the host to reset.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt220_hostreset(const HHEMU hhEmu)
{
vt220_reset(hhEmu, TRUE);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220_reset
*
* DESCRIPTION:
* Calls vt220_reset() when told by the host to reset.
*
* ARGUMENTS:
* host_request -- TRUE if told by host to reset
*
* RETURNS:
* nothing
*/
int vt220_reset(const HHEMU hhEmu, const int host_request)
{
hhEmu->mode_KAM = hhEmu->mode_IRM = hhEmu->mode_VEM =
hhEmu->mode_HEM = hhEmu->mode_LNM = hhEmu->mode_DECCKM =
hhEmu->mode_DECOM = hhEmu->mode_DECCOLM = hhEmu->mode_DECPFF =
// hhEmu->mode_DECSCNM = hhEmu->mode_25enab = hhEmu->mode_blank =
hhEmu->mode_DECSCNM = hhEmu->mode_25enab =
hhEmu->mode_block = hhEmu->mode_local = RESET;
hhEmu->mode_SRM = hhEmu->mode_DECPEX = hhEmu->mode_DECTCEM = SET;
hhEmu->mode_AWM = TRUE;
// hhEmu->mode_protect = hhEmu->vt220_protectmode = FALSE;
hhEmu->mode_protect = FALSE;
if (host_request)
{
ANSI_RIS(hhEmu);
hhEmu->mode_AWM = RESET;
}
hhEmu->fUse8BitCodes = FALSE;
hhEmu->mode_vt220 = TRUE;
hhEmu->mode_vt320 = FALSE;
if (hhEmu->nEmuLoaded == EMU_VT320)
{
hhEmu->mode_vt320 = TRUE;
}
vt_charset_init(hhEmu);
hhEmu->emu_code = '>';
vt_alt_kpmode(hhEmu);
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220_softreset
*
* DESCRIPTION:
* Does a soft reset.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt220_softreset(const HHEMU hhEmu)
{
hhEmu->mode_KAM = hhEmu->mode_IRM = hhEmu->mode_DECCKM =
hhEmu->mode_DECOM = hhEmu->mode_DECKPAM = RESET;
hhEmu->mode_AWM = RESET;
DEC_STBM(hhEmu, 0,0);
ANSI_Pn_Clr(hhEmu);
ANSI_SGR(hhEmu);
hhEmu->emu_code = 0;
vt100_savecursor(hhEmu);
vt_charset_init(hhEmu);
hhEmu->emu_code = '>';
vt_alt_kpmode(hhEmu);
hhEmu->mode_protect = FALSE;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220mode_reset
*
* DESCRIPTION:
* Sets the VT220 emulator to the proper conditions when switching
* from vt100 mode.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt220mode_reset(const HHEMU hhEmu)
{
hhEmu->mode_KAM = hhEmu->mode_IRM = hhEmu->mode_VEM =
hhEmu->mode_HEM = hhEmu->mode_DECCKM = hhEmu->mode_DECOM =
hhEmu->mode_25enab = hhEmu->mode_AWM = RESET;
hhEmu->mode_DECPEX = hhEmu-> mode_DECTCEM = SET;
hhEmu->fUse8BitCodes = FALSE;
hhEmu->mode_vt220 = TRUE;
hhEmu->mode_vt320 = FALSE;
vt_charset_init(hhEmu);
hhEmu->emu_code = '>';
vt_alt_kpmode(hhEmu);
DEC_STBM(hhEmu, 0, hhEmu->emu_maxrow + 1);
hhEmu->emu_code = 0;
vt100_savecursor(hhEmu);
hhEmu->mode_protect = FALSE;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220_DA
*
* DESCRIPTION:
* Sends the primary device attribute (DA) information to the host.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt220_DA(const HHEMU hhEmu)
{
int fOldValue;
char achStr[50];
ECHAR ech[50];
//if (emuProjSuppressEmuReporting(hhEmu))
// return;
// Build the 7-bit or 8-bit response.
//
if (hhEmu->fUse8BitCodes)
{
achStr[0] = '\x9B';
achStr[1] = '\x00';
}
else
{
achStr[0] = '\x1B';
achStr[1] = '[';
achStr[2] = '\x00';
}
// Add the VT220 or VT320 part of the response.
//
if (hhEmu->mode_vt320)
StrCharCat(achStr, TEXT("?63"));
else
StrCharCat(achStr, TEXT("?62"));
// Add the rest of the respnse and send the result.
//
StrCharCat(achStr, TEXT(";1;2;6;8;9;14c"));
CnvrtMBCStoECHAR(ech, sizeof(ech), achStr,
StrCharGetByteCount(achStr));
fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
emuSendString(hhEmu, ech, (int)StrCharGetEcharByteCount(ech));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220_2ndDA
*
* DESCRIPTION:
* Sends the secondary device attribute (DA) information to the host.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt220_2ndDA(const HHEMU hhEmu)
{
int fOldValue;
char achStr[50];
ECHAR ech[50];
// Build the 7-bit or 8-bit response.
//
if (hhEmu->fUse8BitCodes)
{
achStr[0] = '\x9B';
achStr[1] = '\x00';
}
else
{
achStr[0] = '\x1B';
achStr[1] = '[';
achStr[2] = '\x00';
}
// Add the VT220 or VT320 part of the response.
//
if (hhEmu->mode_vt320)
{
StrCharCat(achStr, TEXT(">24;14;0c"));
}
else
{
StrCharCat(achStr, TEXT(">1;23;0c"));
}
CnvrtMBCStoECHAR(ech, sizeof(ech), achStr,
StrCharGetByteCount(achStr));
fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
emuSendString(hhEmu, ech, (int)StrCharGetEcharByteCount(ech));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* emuDecClearUDK
*
* DESCRIPTION:
* This function clears (frees) all of the user defined key sequences
* that may have been previously stored.
*
* ARGUMENTS:
* HHEMU hhEmu - The internal emulator handle.
*
* NOTES:
* This function is called in response to the following escape sequence.
* Esc Pc;Pl |
*
* RETURNS:
* void
*
* AUTHOR: John Masters, 05-Sep-1995
*/
void emuDecClearUDK(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
PSTEMUKEYDATA pstKey = pstPRI->pstUDK;
int idx;
// Set a flag that identifies the locked or unlocked status of the
// UDK's that will be set after the definition of the keys has
// completed.
//
if (hhEmu->selector[1] == 1)
pstPRI->fUnlockedUDK = 1; // Keys are unlocked after definition.
else
pstPRI->fUnlockedUDK = 0; // Keys are locked after definition.
// This function is called in response to an escape sequence that tells
// the emulator to either clear each key sequence when a new one is
// defined, or to clear all of the key sequences before any are defined.
//
// emuDecStoreUDK always clears the current sequence before assigning
// a new one. So, this function will clear all of the keys only
// if that's what we were asked to do. If the first selector is Zero,
// then we will go ahead and clear all of the User Defined Keys.
//
if (hhEmu->selector[0] != 0)
return;
// Cycle through the user defined key table and free
// any memory that may have been allocated for sequences.
//
if (pstKey)
{
for (idx = 0; idx < MAX_UDK_KEYS; idx++, pstKey++)
{
if (pstKey->iSequenceLen != 0)
{
free(pstKey->pSequence);
pstKey->iSequenceLen = 0;
}
}
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecDefineUDK
*
* DESCRIPTION:
* Redefines the string output by a key.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecDefineUDK(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
TCHAR acAscii[16] = { TEXT('0'), TEXT('1'), TEXT('2'), TEXT('3'),
TEXT('4'), TEXT('5'), TEXT('6'), TEXT('7'),
TEXT('8'), TEXT('9'), TEXT('A'), TEXT('B'),
TEXT('C'), TEXT('D'), TEXT('E'), TEXT('F') };
unsigned int aiHex[16] = { 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F };
int idx;
ECHAR emuCode;
emuCode = hhEmu->emu_code;
switch(pstPRI->iUDKState)
{
case(KEY_NUMBER_NEXT):
TCHAR_Fill(pstPRI->acUDKSequence,
0, sizeof(pstPRI->acUDKSequence) / sizeof(TCHAR));
pstPRI->iUDKSequenceLen = 0;
pstPRI->chUDKAssignment = 0;
pstPRI->iUDKState = KEY_DIGIT2_NEXT;
if (IN_RANGE(emuCode,TEXT('1'),TEXT('3')))
{
for (idx = 0; idx < 16; idx++)
{
if (emuCode == acAscii[idx])
break;
}
pstPRI->chUDKAssignment = (TCHAR)(aiHex[idx] << 4);
}
else
{
goto UDKexit;
}
break;
case(KEY_DIGIT2_NEXT):
if (isdigit(emuCode))
{
for (idx = 0; idx < 16; idx++)
{
if (emuCode == acAscii[idx])
break;
}
pstPRI->chUDKAssignment += (TCHAR)aiHex[idx];
// The key to which the following sequence will be assigned
// has been identified. Lookup that key in a table and
// store an index that corresponds to the key table index.
// See the initialization function for the emulator for
// further clarification.
//
for (idx = 0; idx < MAX_UDK_KEYS; idx++)
{
if (pstPRI->chUDKAssignment == pstPRI->pacUDKSelectors[idx])
break;
}
// Process a possible error.
//
if (idx >= MAX_UDK_KEYS)
{
goto UDKexit;
}
// When the sequence is saved in the key table,
// this index will be used to identify which
// key in that table will get the user defined sequence.
//
pstPRI->iUDKTableIndex = idx;
pstPRI->iUDKState = SLASH_NEXT;
}
else
{
goto UDKexit;
}
break;
case (SLASH_NEXT):
if (emuCode == TEXT('/'))
{
pstPRI->iUDKState = CHAR_DIGIT1_NEXT;
}
else
{
goto UDKexit;
}
break;
case (CHAR_DIGIT1_NEXT):
switch(emuCode)
{
case(TEXT(';')):
case 0x9C:
if (emuDecStoreUDK(hhEmu) != 0)
goto UDKexit;
if (emuCode == TEXT('\x9C'))
goto UDKexit;
pstPRI->iUDKState = KEY_NUMBER_NEXT;
break;
case(TEXT('\x1B')):
pstPRI->iUDKState = ESC_SEEN;
break;
default:
if (!isxdigit(emuCode))
{
goto UDKexit;
}
// Collect the first half of the key comming in.
//
for (idx = 0; idx < 16; idx++)
{
if (emuCode == acAscii[idx])
break;
}
pstPRI->chUDKAssignment = 0;
pstPRI->chUDKAssignment = (TCHAR)(aiHex[idx] << 4);
pstPRI->iUDKState = CHAR_DIGIT2_NEXT;
break;
}
break;
case(CHAR_DIGIT2_NEXT):
if (!isxdigit(emuCode))
{
goto UDKexit;
}
// This is the second half of the key comming in.
//
for (idx = 0; idx < 16; idx++)
{
if (emuCode == acAscii[idx])
break;
}
pstPRI->chUDKAssignment += (TCHAR)aiHex[idx];
if (pstPRI->chUDKAssignment >= 127)
{
goto UDKexit;
}
pstPRI->acUDKSequence[pstPRI->iUDKSequenceLen] =
pstPRI->chUDKAssignment;
pstPRI->iUDKSequenceLen += 1;
pstPRI->iUDKState = CHAR_DIGIT1_NEXT;
break;
case(ESC_SEEN):
if ((emuCode = TEXT('\\')) == 0)
{
goto UDKexit;
}
if (emuDecStoreUDK(hhEmu) != 0)
{
assert(FALSE);
}
// We have completed defining the user defined key sequences.
// A flag set in emuDecClearUDK was set to identify the locked
// or unlocked status of the sequences after their definition.
// Promote that setting up to the variable used by the user
// interface.
//
hhEmu->fAllowUserKeys = pstPRI->fUnlockedUDK;
goto UDKexit;
default:
goto UDKexit;
}
// Returning from here allows the state table to pass control
// back to this function, where the internal state (pstPRI->iUDKState)
// will be used to control flow through the case statement above.
//
return;
UDKexit:
// The sequence is complete or we're dropping out because of
// an error.
//
// Initialize the UDK state and the emulators state.
//
pstPRI->iUDKState = KEY_NUMBER_NEXT;
hhEmu->state = 0;
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* emuDecStoreUDK
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
* Author: John Masters
*
*/
int emuDecStoreUDK(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
PSTEMUKEYDATA pstKey = pstPRI->pstUDK + pstPRI->iUDKTableIndex;
// There may be a user settings that disables user defined keys.
// If this feature in not enabled, get outta town.
//
if (!hhEmu->fAllowUserKeys)
{
return(0);
}
// First, free a previously allocated key for this entry, if
// necessary.
//
if (pstKey->iSequenceLen != 0)
{
free(pstKey->pSequence);
pstKey->iSequenceLen = 0;
}
// Now allocate the space for the key sequence.
//
pstKey->pSequence = malloc( sizeof(TCHAR) *
(unsigned int)pstPRI->iUDKSequenceLen);
if (pstKey->pSequence == 0)
{
assert(FALSE);
return(-1);
}
// Now, copy the previously collected sequence into the key table
// and initialize the length variable.
//
MemCopy(pstKey->pSequence,
pstPRI->acUDKSequence,
(unsigned int)pstPRI->iUDKSequenceLen);
pstKey->iSequenceLen = (unsigned int)pstPRI->iUDKSequenceLen;
return(0);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220_level
*
* DESCRIPTION:
* Sets the compatibility level of the VT220.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt220_level(const HHEMU hhEmu)
{
int term, level;
term = hhEmu->num_param[0];
level = hhEmu->num_param_cnt > 0 ? hhEmu->num_param[1] : 0;
if (level < 1)
level = 0;
if (term == 61)
{
if (hhEmu->mode_vt220)
vt100_init(hhEmu);
}
else if (term == 62 || term == 63)
{
if (!hhEmu->mode_vt220)
vt220_init(hhEmu); /* sets mode_vt220 & mode_vt320 */
if (level == 1)
hhEmu->fUse8BitCodes = FALSE;
if (level == 0 || level == 2)
hhEmu->fUse8BitCodes = TRUE;
if (term == 62 && hhEmu->mode_vt320)
hhEmu->mode_vt320 = FALSE;
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt220_protmode
*
* DESCRIPTION:
* Sets up and clears protect mode -- called selective erase on vt220.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt220_protmode(const HHEMU hhEmu)
{
hhEmu->mode_protect = (hhEmu->num_param[0] == 1);
hhEmu->emu_charattr.protect = (unsigned int)hhEmu->mode_protect;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* emuDecKeyboardIn
*
* DESCRIPTION:
* This function processes the keyboard keys for all the DEC terminal
* emulators.
*
* Please note that both emuSendKeyString, and emuDecSendKeyString are
* used in this function. emuDecSendKeyString is a function that will
* convert the 8-bit sequence from the key table to a 7-bit value, if
* necessary.
*
* Keys Used to Emulate a DEC Terminal's PF1-PF4 Keys
*
* The keys normally used in HyperACCESS to emulate a DEC terminal's
* PF1-PF4 keys are F1-F4. Some people, however, prefer to use the
* keys at the top of the PC's numeric keypad (Num Lock, /, *, -),
* because these keys' physical location matches that of a DEC
* terminal's PF1-PF4 keys. If you prefer using these keys, select
* the "PF1-PF4 mapped to top row of keypad" checkbox in the
* terminal settings dialog for the DEC terminal you are using.
*
* When "PF1-PF4 mapped to top row of keypad" is checked ...
*
* The keys at the top of the keypad act as PF1-PF4, and F1-F4
* revert to performing functions defined by the operating system.
* For example, F1 displays help, and Num Lock sends the character
* sequence that the DEC terminal associates with PF1. The operating
* system will also sense that Num Lock has been pressed, and toggle
* the keyboard's Num Lock state. The Num Lock state, however, has
* no effect on the behavior of the DEC terminal emulator when
* PF1-PF4 are mapped to the top row of the keypad.
*
* When "PF1-PF4 mapped to top row of keypad" is NOT checked...
*
* F1-F4 act as PF1-PF4, and the keys at the top of the keypad (Num
* Lock, /, *, -) perform their normal functions. For example, F1
* sends the character sequence that the DEC terminal associates
* with PF1, and Num Lock toggles the keyboard's Num Lock state.
* When Num Lock is on, your PC's keypad (except the top row)
* emulates the numeric keypad of a DEC terminal. When Num Lock is
* off, your keypad's arrow keys emulate a DEC terminal's arrow
* keys. (If your keyboard has a separate set of arrow keys, that
* set will always emulate a DEC terminal's arrow keys, regardless
* Num Lock's state.)
*
* ARGUMENTS:
* HHEMU hhEmu - The Internal emulator handle.
* int Key - The key to process.
* int fTest - Are we testing, or processing the key.
*
* RETURNS:
* This function returns the index of the table in which the key was
* found.
*
* AUTHOR: John Masters, 12-Sep-1995
*/
int emuDecKeyboardIn(const HHEMU hhEmu, int Key, const int fTest)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int index;
int fNumlock;
int fMovedPfKeys;
int fSearchKeypad;
int fCursorKeyMode;
int fKeypadNumeric;
int fKeypadApplication;
int fSearchUDK;
if (!fTest)
{
#if 0
DbgOutStr("VT100_KBDIN", 0, 0, 0, 0, 0);
DbgOutStr("Key: Char :0x%x", hKey.VKchar, 0, 0, 0, 0);
DbgOutStr(" Virtual :%d", hKey.Virtual, 0, 0, 0, 0);
DbgOutStr(" Ctrl :%d", hKey.Ctrl, 0, 0, 0, 0);
DbgOutStr(" Alt :%d", hKey.Alt, 0, 0, 0, 0);
DbgOutStr(" Shift :%d", hKey.Shift, 0, 0, 0, 0);
DbgOutStr(" Extended :%d", hKey.Extended, 0, 0, 0, 0);
#endif
}
// Initialize some locals. The keypad is either in Numeric Mode,
// or Application Mode. So, the first two locals below are mutually
// exclusive variables. They have been defined only to improve
// readability in this code.
//
fKeypadApplication = hhEmu->mode_DECKPAM;
fKeypadNumeric = !fKeypadApplication;
//fMovedPfKeys = hhEmu->stUserSettings.fMapPFkeys;
fMovedPfKeys = FALSE;
fNumlock = QUERY_NUMLOCK();
fSearchKeypad = (fMovedPfKeys || fNumlock);
fCursorKeyMode = (hhEmu->mode_DECCKM == SET) &&
(hhEmu->nEmuLoaded != EMU_VT52);
fSearchUDK = hhEmu->fAllowUserKeys &&
((hhEmu->nEmuLoaded == EMU_VT220) ||
(hhEmu->nEmuLoaded == EMU_VT320));
assert(fKeypadApplication != fKeypadNumeric);
/* -------------- Check Backspace & Delete keys ------------- */
if (hhEmu->stUserSettings.fReverseDelBk && ((Key == VK_BACKSPACE) ||
(Key == DELETE_KEY) || (Key == DELETE_KEY_EXT)))
{
Key = (Key == VK_BACKSPACE) ? DELETE_KEY : VK_BACKSPACE;
}
// F1 thru F4 from either function keys on the top of the keyboard,
// or from the function key pad on the left. (They have not been
// mapped to the top row of the numeric keypad).
//
if (!fMovedPfKeys && (index = emuDecKbdKeyLookup(hhEmu,
Key, pstPRI->pstcEmuKeyTbl1, pstPRI->iKeyTable1Entries)) != -1)
{
if (!fTest)
emuDecSendKeyString(hhEmu, index,
pstPRI->pstcEmuKeyTbl1, pstPRI->iKeyTable1Entries);
}
// F1 thru F4, if they have been mapped to the top row of the
// numeric keypad (Numlock, /, *, -).
//
else if (fMovedPfKeys && (index = emuDecKbdKeyLookup(hhEmu,
Key, pstPRI->pstcEmuKeyTbl2, pstPRI->iKeyTable2Entries)) != -1)
{
if (!fTest)
emuDecSendKeyString(hhEmu, index,
pstPRI->pstcEmuKeyTbl2, pstPRI->iKeyTable2Entries);
}
#if FALSE // HT doesn't know the state of the numlock.
// Keypad Numeric Mode.
//
else if (fSearchKeypad && fKeypadNumeric &&
(index = emuDecKbdKeyLookup(hhEmu, Key, pstPRI->pstcEmuKeyTbl3,
pstPRI->iKeyTable3Entries)) != -1)
{
if (!fTest)
emuDecSendKeyString(hhEmu, index,
pstPRI->pstcEmuKeyTbl3, pstPRI->iKeyTable3Entries);
}
#endif
// Keypad Application Mode.
//
else if (fSearchKeypad && fKeypadApplication &&
(index = emuDecKbdKeyLookup(hhEmu, Key, pstPRI->pstcEmuKeyTbl4,
pstPRI->iKeyTable4Entries)) != -1)
{
if (!fTest)
emuDecSendKeyString(hhEmu, index,
pstPRI->pstcEmuKeyTbl4, pstPRI->iKeyTable4Entries);
}
// Cursor Key Mode.
//
else if (fCursorKeyMode &&
(index = emuDecKbdKeyLookup(hhEmu, Key, pstPRI->pstcEmuKeyTbl5,
pstPRI->iKeyTable5Entries)) != -1)
{
if (!fTest)
emuDecSendKeyString(hhEmu, index,
pstPRI->pstcEmuKeyTbl5, pstPRI->iKeyTable5Entries);
}
// User defined keys.
//
else if (fSearchUDK &&
(index = emuDecKbdKeyLookup(hhEmu, Key, pstPRI->pstUDK,
pstPRI->iUDKTableEntries)) != -1)
{
if (!fTest)
emuDecSendKeyString(hhEmu, index, pstPRI->pstUDK,
pstPRI->iUDKTableEntries);
}
// Standard keys.
//
else if ((index = emuDecKbdKeyLookup(hhEmu, Key,
pstPRI->pstcEmuKeyTbl6, pstPRI->iKeyTable6Entries)) != -1)
{
if (!fTest)
{
emuDecSendKeyString(hhEmu, index,
pstPRI->pstcEmuKeyTbl6, pstPRI->iKeyTable6Entries);
}
}
// Standard characters.
//
else
{
//DbgOutStr("VT100Kbdin calling std_kbdin", 0, 0, 0, 0, 0);
index = std_kbdin(hhEmu, Key, fTest);
}
return index;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* emuDecKbdKeyLookup
*
* DESCRIPTION:
* Main keyboard translation routine for all emulators. Note, this
* routine will not lookup keys unless the iUseTermKeys flag is set.
*
* ARGUMENTS:
* HHEMU hhEmu - Internal emulator handle
* UINT key - lower byte is char or virtual key, upper byte has flags
*
* RETURNS:
* Index if translated, else minus one.
*
*/
int emuDecKbdKeyLookup(const HHEMU hhEmu,
const KEYDEF Key,
PSTCEMUKEYDATA pstKeyTbl,
const int iMaxEntries)
{
PSTCEMUKEYDATA pstKey = pstKeyTbl;
int idx,
iRet;
// There is no need to look for the key if the user has
// the terminal set up for accelerator keys.
//
if (hhEmu->stUserSettings.nTermKeys == EMU_KEYS_ACCEL)
{
return -1;
}
// Do a linear search through the supplied table for the given
// key. Once it is found, return that index, or return (-1) if
// the key is not located.
//
iRet = (-1);
// The VT220 and VT320 key tables have user defined key tables
// that have empty sequence entries in them, unless they have been
// defined by the host. So, if they're empty, we're not going to
// report them as keys that have been found.
//
for (idx = 0; idx < iMaxEntries; idx++, pstKey++)
{
if (pstKey->Key == Key && pstKey->iSequenceLen != 0)
{
iRet = idx;
break;
}
}
return iRet;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecSendKeyString
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
* nothing
*/
void emuDecSendKeyString(const HHEMU hhEmu, const int iIndex,
PSTCEMUKEYDATA pstcKeyTbl, const int iMaxEntries)
{
PSTCEMUKEYDATA pstKeyData = pstcKeyTbl + iIndex;
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
const int fUDK = (pstcKeyTbl == pstPRI->pstUDK) ? 1 : 0;
int iLen;
unsigned int iLeadByte;
TCHAR * pchLeadChar = NULL;
ECHAR str[80];
if (pstcKeyTbl == 0)
{
assert(FALSE);
return;
}
ECHAR_Fill(str, TEXT('\0'), sizeof(str)/sizeof(ECHAR));
// If we are processing VT52 or VT100 keys, call the standard
// send string function. The VT100 doesn't switch between 7 and 8
// bit controls.
//
if (hhEmu->nEmuLoaded == EMU_VT100 || hhEmu->nEmuLoaded == EMU_VT52)
{
emuVT220SendKeyString(hhEmu, iIndex, pstcKeyTbl, iMaxEntries);
return;
}
// 7-bit controls don't apply to the user defined sequences.
// Also, because empty key sequences are defined in the User Defined
// Key Table, it is possible that the key sequence value is NULL. So,
// we'll process the User Defined Key here, checking the sequence
// before we try to operate on it.
//
if (fUDK)
{
if (pstKeyData->pSequence)
{
emuVT220SendKeyString(hhEmu, iIndex, pstcKeyTbl, iMaxEntries);
}
return;
}
// If we are are sending 8 bit codes, process the key directly
// from the key table, as usual.
//
if (hhEmu->fUse8BitCodes)
{
emuVT220SendKeyString(hhEmu, iIndex, pstcKeyTbl, iMaxEntries);
return;
}
// If we are processing 7 bit codes, the first character in the
// sequence defined in the key table will be replaced with its 7-bit
// value, sometimes.
//
iLeadByte = *(pstKeyData->pSequence);
switch(iLeadByte)
{
case 0x84:
// Send Esc - D
//
pchLeadChar = TEXT("\x1B\x44\x00");
break;
case 0x8F:
// Send Esc - O
//
pchLeadChar = TEXT("\x1B\x4F\x00");
break;
case 0x9B:
// Send Esc - [
//
pchLeadChar = TEXT("\x1B\x5B\x00");
break;
default:
// Send sequence as defined in the key table.
//
pchLeadChar = TEXT("\x00");
break;
}
// If we are sending a 7-bit version of the sequence, it gets sent out
// in two pieces, otherwise send the sequence as it is defined
// in the key table.
//
if (*pchLeadChar)
{
CnvrtMBCStoECHAR(str, sizeof(str), pchLeadChar,
StrCharGetByteCount(pchLeadChar));
iLen = StrCharGetEcharByteCount(str);
CnvrtMBCStoECHAR(&str[iLen], sizeof(str) - iLen,
pstKeyData->pSequence + 1,
StrCharGetByteCount(pstKeyData->pSequence + 1));
emuSendString(hhEmu, str, StrCharGetEcharByteCount(str));
}
else
{
emuVT220SendKeyString(hhEmu, iIndex, pstcKeyTbl, iMaxEntries);
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION:
* emuVT220SendKeyString
*
* DESCRIPTION:
* Sends the specified string.
*
* This is a VT220 specific replacement for emuSendKeyString in emu.c. It's
* the emuSendKeyString from \shared\emulator\emu.c.
*
* ARGUMENTS:
* hhEmu - The internal emulator handle.
* nIndex - Position of key in keytable array.
* pstKeyTbl - Address of key strings table.
*
* RETURNS:
* nothing
*
*/
void emuVT220SendKeyString(const HHEMU hhEmu,
const int iIndex,
PSTCEMUKEYDATA pstcKeyTbl,
const int iMaxEntries)
{
ECHAR str[80];
PSTCEMUKEYDATA pstKeyData = pstcKeyTbl + iIndex;
memset(str, 0, sizeof(str));
if (iIndex < 0 || iIndex >= iMaxEntries)
{
assert(FALSE);
return;
}
pstKeyData = pstcKeyTbl + iIndex;
#if defined(_DEBUG)
DbgOutStr("%s", pstcKeyTbl[iIndex].pszKeyName, 0, 0, 0, 0);
#endif
if (pstKeyData->iSequenceLen > 0)
{
CnvrtMBCStoECHAR(str, sizeof(str), pstKeyData->pSequence,
StrCharGetByteCount(pstKeyData->pSequence));
emuSendString(hhEmu, str, StrCharGetEcharByteCount(str));
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecEL
*
* DESCRIPTION:
* Erase In Line (EL). This control function erases characters from
* part or all of the current line. When you erase complete lines, they
* become single height and single width, with all character attributes
* cleared.
*
* Selective Erase in Display (SED). This control function lets you
* erase some or all of the erasable characters in the display. DECSED
* cam only erase characters defined as erasable by the DECSCA control
* function. A selective erase is controled by the DEC_private flag
* in the emulator handle. This is dealt with in the lower level
* function that does the actual erasing.
*
* ARGUMENTS:
* hhEmu - The internal emulator handle.
*
* RETURNS:
* nothing
*/
void emuDecEL(const HHEMU hhEmu)
{
int iClearType;
switch (hhEmu->selector[0])
{
case 0:
case 0x0F:
case 0xF0:
if (hhEmu->emu_curcol == 0)
iClearType = CLEAR_ENTIRE_LINE;
else
iClearType = CLEAR_CURSOR_TO_LINE_END;
break;
case 1:
case 0xF1:
iClearType = CLEAR_LINE_START_TO_CURSOR;
break;
case 2:
case 0xF2:
iClearType = CLEAR_ENTIRE_LINE;
break;
default:
commanderror(hhEmu);
return;
}
emuDecClearLine(hhEmu, iClearType);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION:
* emuDecClearLine
*
* DESCRIPTION:
* Erases some or all of the virtual screen image.
*
* ARGUMENTS:
* HHEMU hhEmu - The internal emulator handle.
*
* int iClearSelect - CLEAR_CURSOR_TO_LINE_END 0
* - CLEAR_LINE_START_TO_CURSOR 1
* - CLEAR_ENTIRE_LINE 2
*
*
* RETURNS:
* nothing
*
*/
void emuDecClearLine(const HHEMU hhEmu, const int iClearSelect)
{
register int iCurrentImgRow, iCol;
ECHAR * pechText = 0;
PSTATTR pstCell = 0;
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
iCurrentImgRow = row_index(hhEmu, hhEmu->emu_currow);
pstCell = hhEmu->emu_apAttr[iCurrentImgRow];
pechText = hhEmu->emu_apText[iCurrentImgRow];
switch (iClearSelect)
{
case CLEAR_CURSOR_TO_LINE_END:
// Clear the current line from the current cursor position
// through the end of the user's maximum screen width.
//
for(iCol = hhEmu->emu_curcol; iCol <= hhEmu->emu_maxcol; iCol++)
{
// If we're in DEC private mode and the character is
// protected, don't do anything with it.
//
if (hhEmu->DEC_private && pstCell[iCol].protect)
{
continue;
}
// OK, clear the character and it's attribute at this column
// location.
//
pechText[iCol] = (ECHAR)EMU_BLANK_CHAR;
pstCell[iCol] = hhEmu->emu_clearattr;
}
// Adjust the array that contains the column number of the last
// character in this row.
//
if (hhEmu->emu_curcol <= hhEmu->emu_aiEnd[iCurrentImgRow])
{
hhEmu->emu_aiEnd[iCurrentImgRow] = max(hhEmu->emu_curcol - 1, 0);
}
break;
case CLEAR_LINE_START_TO_CURSOR:
// Clear the range from the beginning of the line, through the
// current cursor position.
//
for(iCol = 0; iCol <= hhEmu->emu_curcol; iCol++)
{
// If we're in DEC private mode and the character is
// protected, don't do anything with it.
//
if (hhEmu->DEC_private && pstCell[iCol].protect)
{
continue;
}
// OK, clear the character and it's attribute at this column
// location.
//
pechText[iCol] = (ECHAR)EMU_BLANK_CHAR;
pstCell[iCol] = hhEmu->emu_clearattr;
}
// Adjust the array value that contains the column number
// of the last character in this row.
//
if (hhEmu->emu_curcol >= hhEmu->emu_aiEnd[iCurrentImgRow])
{
hhEmu->emu_aiEnd[iCurrentImgRow] = EMU_BLANK_LINE;
}
break;
case CLEAR_ENTIRE_LINE:
// The entire line needs to be cleared, but we only want
// to put the user defined size of the emulator into the
// backscroll buffer.
//
backscrlAdd(sessQueryBackscrlHdl(hhEmu->hSession),
pechText, hhEmu->emu_maxcol + 1);
if (hhEmu->DEC_private)
emuDecClearImageRowSelective(hhEmu, hhEmu->emu_currow);
else
clear_imgrow(hhEmu, hhEmu->emu_currow);
pstPRI->aiLineAttr[iCurrentImgRow] = NO_LINE_ATTR;
break;
default:
commanderror(hhEmu);
}
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, hhEmu->emu_curcol);
// Added a global to save the clear attribute at the time of
// notification. This is necessary since the message is posted
// and a race condition can develop.
//
hhEmu->emu_clearattr_sav = hhEmu->emu_clearattr;
updateLine(sessQueryUpdateHdl(hhEmu->hSession), 0, hhEmu->emu_currow);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuVT220ED
*
* DESCRIPTION:
* Erase In Display (ED). This control function erases characters from
* part or all of the display. When you erase complete lines, they
* become single height and single width, with all character attributes
* cleared.
*
* Selective Erase in Display (SED). This control function lets you
* erase some or all of the erasable characters in the display. DECSED
* cam only erase characters defined as erasable by the DECSCA control
* function. A selective erase is controled by the DEC_private flag
* in the emulator handle. This is dealt with in the lower level
* function that does the actual erasing.
*
* ARGUMENTS:
* hhEmu - The internal emulator handle.
*
* RETURNS:
* nothing
*/
void emuVT220ED(const HHEMU hhEmu)
{
int iClearType;
switch (hhEmu->selector[0])
{
case 0:
case 0x0F:
case 0xF0:
if (hhEmu->emu_currow == 0 && hhEmu->emu_curcol == 0)
iClearType = CLEAR_ENTIRE_SCREEN;
else
iClearType = CLEAR_CURSOR_TO_SCREEN_END;
break;
case 1:
case 0xF1:
iClearType = CLEAR_SCREEN_START_TO_CURSOR;
break;
case 2:
case 0xF2:
iClearType = CLEAR_ENTIRE_SCREEN;
break;
default:
commanderror(hhEmu);
return;
}
emuDecEraseScreen(hhEmu, iClearType);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION:
* emuDecEraseScreen
*
* DESCRIPTION:
* Erases some or all of the virtual screen image.
*
* ARGUMENTS:
* HHEMU hhEmu - The internal emulator handle.
*
* int iClearSelect - CLEAR_CURSOR_TO_SCREEN_END 0
* - CLEAR_SCREEN_START_TO_CURSOR 1
* - CLEAR_ENTIRE_SCREEN 2
*
*
* RETURNS:
* nothing
*
*/
void emuDecEraseScreen(const HHEMU hhEmu, const int iClearSelect)
{
register int iRow;
int trow,
iStartRow, iEndRow,
tcol,
iVirtualRow,
iLineLen;
ECHAR aechBuf[10];
ECHAR * pechText = 0;
PSTATTR pstCell = 0;
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
trow = hhEmu->emu_currow;
tcol = hhEmu->emu_curcol;
switch (iClearSelect)
{
case CLEAR_CURSOR_TO_SCREEN_END:
// Note that the calling function (emuDecED) changes iClearSelect
// to CLEAR_ENTIRE_SCREEN if CLEAR_CURSOR_TO_SCREEN_END was
// issued with a current cursor position at (0,0). Clearing
// the entire screen pushes the screen image into the backscroll
// buffer, the capture file, and to the printer. Anything less
// than that simply gets cleared from the display. Now...
// Clear the range from one line below the current cursor position
// through the end of the user's maximum screen size.
//
for (iRow = hhEmu->emu_currow + 1; iRow <= hhEmu->emu_maxrow; iRow++)
{
if (hhEmu->DEC_private)
emuDecClearImageRowSelective(hhEmu, iRow);
else
clear_imgrow(hhEmu, iRow);
}
// Now clear the characters and attributes from the partial
// row that the cursor was on.
//
emuDecClearLine(hhEmu, CLEAR_CURSOR_TO_LINE_END);
// Identify the range of line attributes that need to be cleared,
// and clear them.
//
if (hhEmu->emu_curcol == 0)
iStartRow = hhEmu->emu_currow;
else
iStartRow = hhEmu->emu_currow + 1;
iStartRow = min(iStartRow, hhEmu->emu_maxrow);
iEndRow = hhEmu->emu_maxrow;
if (iStartRow >= 0)
{
for(iRow = iStartRow; iRow <= iEndRow; iRow++)
pstPRI->aiLineAttr[iRow] = NO_LINE_ATTR;
}
// Finally, update the image.
//
updateScroll(sessQueryUpdateHdl(hhEmu->hSession),
0,
hhEmu->emu_maxrow,
hhEmu->emu_maxrow + 1,
hhEmu->emu_imgtop,
TRUE);
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, hhEmu->emu_curcol);
// Added a global to save the clear attribute at the time of
// notification. This is necessary since the message is posted
// and a race condition can develop.
//
hhEmu->emu_clearattr_sav = hhEmu->emu_clearattr;
NotifyClient(hhEmu->hSession, EVENT_EMU_CLRATTR, 0);
break;
case CLEAR_SCREEN_START_TO_CURSOR:
// Clear the range from the first row, to one row above the
// current cursor position.
//
for (iRow = 0; iRow < hhEmu->emu_currow; iRow++)
{
if (hhEmu->DEC_private)
emuDecClearImageRowSelective(hhEmu, iRow);
else
clear_imgrow(hhEmu, iRow);
}
// Now clear the partial (current) row.
//
emuDecClearLine(hhEmu, CLEAR_LINE_START_TO_CURSOR);
// Identify the range of line attributes that need to be cleared,
// and clear them.
//
iStartRow = 0;
if (hhEmu->emu_curcol == hhEmu->emu_maxcol)
iEndRow = hhEmu->emu_currow;
else
iEndRow = hhEmu->emu_currow - 1;
iEndRow = max(iEndRow, 0);
if (iStartRow >= 0)
{
for(iRow = iStartRow; iRow <= iEndRow; iRow++)
pstPRI->aiLineAttr[iRow] = NO_LINE_ATTR;
}
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, hhEmu->emu_curcol);
updateLine(sessQueryUpdateHdl(hhEmu->hSession), 0, hhEmu->emu_currow);
break;
case CLEAR_ENTIRE_SCREEN:
// The entire buffer needs to be cleared, but we only want
// to put the user defined size of the emualtor into the
// backscroll buffer, capture file and print file.
//
for (iRow = 0; iRow < MAX_EMUROWS; iRow++)
{
if (iRow <= hhEmu->emu_maxrow)
{
iVirtualRow = row_index(hhEmu, iRow);
iLineLen = emuRowLen(hhEmu, iVirtualRow);
pechText = hhEmu->emu_apText[iVirtualRow];
backscrlAdd(sessQueryBackscrlHdl(hhEmu->hSession),
pechText, iLineLen);
CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
CF_CAP_SCREENS, pechText, iLineLen);
printEchoScreen(hhEmu->hPrintEcho, pechText, iVirtualRow);
CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
StrCharGetByteCount(TEXT("\r\n")));
printEchoScreen(hhEmu->hPrintEcho, aechBuf, sizeof(ECHAR) * 2);
if (hhEmu->DEC_private)
emuDecClearImageRowSelective(hhEmu, iRow);
else
clear_imgrow(hhEmu, iRow);
}
else
{
clear_imgrow(hhEmu, iRow);
}
pstPRI->aiLineAttr[iRow] = NO_LINE_ATTR;
}
// Scroll the imgae.
//
updateScroll(sessQueryUpdateHdl(hhEmu->hSession),
0,
hhEmu->emu_maxrow,
hhEmu->emu_maxrow + 1,
hhEmu->emu_imgtop,
TRUE);
// Added a global to save the clear attribute at the time of
// notification. This is necessary since the message is posted
// and a race condition can develop.
hhEmu->emu_clearattr_sav = hhEmu->emu_clearattr;
NotifyClient(hhEmu->hSession, EVENT_EMU_CLRATTR, 0);
break;
default:
commanderror(hhEmu);
}
(*hhEmu->emu_setcurpos)(hhEmu, trow, tcol);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* emuDecClearImageRowSelective
*
* DESCRIPTION:
* This function clears the characters and attributes from the supplied
* row, taking into account the protected bit in the character
* attributes. It only clears those characters that are NOT protected.
*
* ARGUMENTS:
* HHEMU hhEmu - The internal emulator handle.
*
* int iRow - The row to clear.
*
* RETURNS:
* nothing
*/
void emuDecClearImageRowSelective(const HHEMU hhEmu, const int iImageRow)
{
register int i, iRow;
ECHAR *pechText = 0;
PSTATTR pstCell = 0;
iRow = row_index(hhEmu, iImageRow);
pstCell = hhEmu->emu_apAttr[iRow];
pechText = hhEmu->emu_apText[iRow];
// Clear only the characters (and attributes) of the non-protected
// characters.
//
for (i = 0; i < MAX_EMUCOLS; i++)
{
if ( pstCell[i].protect == 0 )
{
pstCell[i] = hhEmu->emu_clearattr;
pechText[i] = EMU_BLANK_CHAR;
}
if (pechText[i] != EMU_BLANK_CHAR)
hhEmu->emu_aiEnd[iRow] = i;
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecUnload
*
* DESCRIPTION:
* Unloads current emulator by freeing used memory.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecUnload(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
PSTEMUKEYDATA pstKey = pstPRI->pstUDK;
int idx;
if (pstPRI)
{
// Clear the line attribute array.
//
if (pstPRI->aiLineAttr)
{
free(pstPRI->aiLineAttr);
pstPRI->aiLineAttr = 0;
}
// Cycle through the user defined key table and free
// any memory that may have been allocated for sequences.
//
if (pstKey)
{
for (idx = 0; idx < MAX_UDK_KEYS; idx++, pstKey++)
{
if (pstKey->iSequenceLen != 0)
{
free(pstKey->pSequence);
pstKey->iSequenceLen = 0;
}
}
}
free(pstPRI);
//pstPRI = NULL; //mpt:12-21-98 cannot modify a const object
hhEmu->pvPrivate = NULL;
}
return;
}
#endif // INCL_VT220
/* end of VT220.C */