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