|
|
/* File: D:\WACKER7\emu\emu.c (Created: 08-Dec-1993)
* * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 11 $ * $Date: 7/08/02 6:32p $ */
#include <windows.h>
#pragma hdrstop
#include <tdll\stdtyp.h>
#include <tdll\tdll.h>
#include <tdll\assert.h>
#include <tdll\mc.h>
#include <tdll\com.h>
#include <tdll\cloop.h>
#include <tdll\capture.h>
#include <tdll\session.h>
#include <tdll\load_res.h>
#include <tdll\globals.h>
#include <tdll\print.h>
#include <tdll\statusbr.h>
#include <tdll\htchar.h>
#include <search.h>
#include <tdll\update.h>
#include <term\res.h>
#include "emu.h"
#include "emu.hh"
#include "emuid.h"
#if defined(INCL_VTUTF8)
extern BOOL DoUTF8; #endif
static int FFstrlen(const BYTE *); int _cdecl KeyCmp(const void *, const void *);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * char_pn * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ void char_pn(const HHEMU hhEmu) /* interpret a character as a numeric param */ { if (hhEmu->emu_code < ETEXT(' ')) hhEmu->emu_code = ETEXT(' ');
hhEmu->selector[hhEmu->selector_cnt] = hhEmu->num_param[hhEmu->num_param_cnt] = hhEmu->emu_code - ETEXT(' ') + 1;
hhEmu->num_param[++hhEmu->num_param_cnt] = 0;
hhEmu->selector[++hhEmu->selector_cnt] = 0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * commanderror * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ void commanderror(const HHEMU hhEmu) { hhEmu->state = 0; ANSI_Pn_Clr(hhEmu); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuAutoDetectLoad * * DESCRIPTION: * if auto dection is on, loads the given emulator ID and sets auto * detection off. * * ARGUMENTS: * hhEmu - private emulator handle * EmuID - id of emulator to load * * RETURNS: * void * */ void emuAutoDetectLoad(const HHEMU hhEmu, const int nEmuID) { if (hhEmu->stUserSettings.nEmuId != EMU_AUTO) return;
if (hhEmu->stUserSettings.nEmuId != nEmuID) { emuLock((HEMU)hhEmu); hhEmu->stUserSettings.nAutoAttempts = 0; #ifdef INCL_USER_DEFINED_BACKSPACE_AND_TELNET_TERMINAL_ID
// Load the default telnet terminal id for this emulator. - cab:11/18/96
//
emuQueryDefaultTelnetId(nEmuID, hhEmu->stUserSettings.acTelnetId, EMU_MAX_TELNETID); #endif
emuUnlock((HEMU)hhEmu);
emuLoad((HEMU)hhEmu, nEmuID); } return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuStdGraphic * * DESCRIPTION: * This function is called to display the normal range of characters * for the emulators. It handles insertion modes, end of line wrapping, * and cursor positioning. * * ARGUMENTS: * * RETURNS: * */ void emuStdGraphic(const HHEMU hhEmu) { ECHAR ccode; ECHAR echBuf[10]; int iCharsToMove;
int iRow = hhEmu->emu_currow; int iCol = hhEmu->emu_curcol;
ECHAR *tp = hhEmu->emu_apText[hhEmu->emu_imgrow]; PSTATTR ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
ccode = hhEmu->emu_code;
// Is the emulator in insert mode?
//
if (hhEmu->mode_IRM == SET) { iCharsToMove = hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - iCol;
if (iCharsToMove + iCol >= hhEmu->emu_maxcol) iCharsToMove -= 1;
if (iCharsToMove > 0) { memmove(&tp[iCol+1], &tp[iCol], (unsigned)iCharsToMove * sizeof(ECHAR)); memmove(&ap[iCol+1], &ap[iCol], (unsigned)iCharsToMove * sizeof(ECHAR)); hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = min(hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + 1, hhEmu->emu_maxcol - 1); } }
// Our competetor's are eating the NULL's. DOS ANSI doesn't.
// For now we'll try it their way... - mrw
//
if (ccode == (ECHAR)0) return;
// Place the character and the current attribute into the image.
//
if ((hhEmu->stUserSettings.nEmuId == EMU_VT100) && ccode < sizeof(hhEmu->dspchar)) ccode = hhEmu->dspchar[ccode];
tp[iCol] = ccode; ap[iCol] = hhEmu->emu_charattr;
#if !defined(CHAR_NARROW)
if ((hhEmu->stUserSettings.nEmuId == EMU_AUTO) || (hhEmu->stUserSettings.nEmuId == EMU_ANSIW)) { // Process Double Byte Characters
//
if (QueryCLoopMBCSState(sessQueryCLoopHdl(hhEmu->hSession))) { if (isDBCSChar(ccode)) { int iColPrev = iCol;
ap[iCol].wilf = 1; ap[iCol].wirt = 0;
// Update the end of row index if necessary.
//
if (iCol > hhEmu->emu_aiEnd[hhEmu->emu_imgrow]) hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = iCol;
// Update the image.
//
updateChar(sessQueryUpdateHdl(hhEmu->hSession), iRow, iCol, hhEmu->mode_IRM ? hhEmu->emu_maxcol : hhEmu->emu_aiEnd[hhEmu->emu_imgrow]);
iCol = min(iCol+1, hhEmu->emu_maxcol);
tp[iCol] = ccode; ap[iCol] = ap[iColPrev]; ap[iCol].wilf = 0; ap[iCol].wirt = 1; } }
#if 0
//mpt:1-23-98 handles the case when an incoming character
// (single or double byte) overwrites the first half of
// a double byte character
if ( iCol < hhEmu->emu_maxcol ) { //if we orphaned a right half of a dbcs char
if (hhEmu->emu_apAttr[iRow][iCol + 1].wirt == TRUE) { //slide characters and attribs to left
iCharsToMove = hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - iCol + 1; if (iCol + 2 < hhEmu->emu_maxcol && iCharsToMove > 0) { memmove(&tp[iCol + 1], &tp[iCol + 2], (unsigned)iCharsToMove * sizeof(ECHAR));
memmove(&ap[iCol + 1], &ap[iCol + 2], (unsigned)iCharsToMove * sizeof(ECHAR)); } //move end of row since we removed a character
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] -= 1;
//update the image
updateChar(sessQueryUpdateHdl(hhEmu->hSession), hhEmu->emu_imgrow, hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + 1, hhEmu->mode_IRM ? hhEmu->emu_maxcol : hhEmu->emu_aiEnd[hhEmu->emu_imgrow] + 1);
} } #endif
} #endif //CHAR_NARROW
// Update the end of row index if necessary.
//
if (iCol > hhEmu->emu_aiEnd[hhEmu->emu_imgrow]) hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = iCol;
// Update the image.
//
updateChar(sessQueryUpdateHdl(hhEmu->hSession), iRow, iCol, hhEmu->mode_IRM ? hhEmu->emu_maxcol : hhEmu->emu_aiEnd[hhEmu->emu_imgrow]);
// Move the position of the cursor ahead of the last character
// displayed, checking for end of line wrap.
//
iCol++; if (iCol > hhEmu->emu_maxcol) { if (hhEmu->mode_AWM) { // This code was added, but not enabled because we did not
// want to introduce this without proper testing. If line
// wrap on capture to printer not working is reported as a
// bug, enable this code.
#if 0
printEchoChar(hhEmu->hPrintEcho, ETEXT('\r')); printEchoChar(hhEmu->hPrintEcho, ETEXT('\n')); #endif
printEchoString(hhEmu->hPrintEcho, tp, emuRowLen(hhEmu, iRow)); CnvrtMBCStoECHAR(echBuf, sizeof(echBuf), TEXT("\r\n"), StrCharGetByteCount(TEXT("\r\n")));
printEchoString(hhEmu->hPrintEcho, echBuf, sizeof(ECHAR) * 2);
CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession), CF_CAP_LINES, tp, emuRowLen(hhEmu, iRow));
if (iRow == hhEmu->bottom_margin) (*hhEmu->emu_scroll)(hhEmu, 1, TRUE); else iRow += 1;
iCol = 0; } else { iCol = hhEmu->emu_maxcol; } }
// Finally, set the cursor position. This wil reset emu_currow
// and emu_curcol.
//
(*hhEmu->emu_setcurpos)(hhEmu, iRow, iCol); return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emu_cleartabs * * DESCRIPTION: * Clears one or all tab stops. * * ARGUMENTS: * selector -- 0 clears tab at current cursor position * -- 3 clears all tabs in current line * * RETURNS: * nothing */ void emu_cleartabs(const HHEMU hhEmu, int selecter) { int col;
switch (selecter) { case 0: hhEmu->tab_stop[hhEmu->emu_curcol] = FALSE; break;
case 3: for (col = 0; col <= hhEmu->emu_maxcol; ++col) hhEmu->tab_stop[col] = FALSE; break;
default: commanderror(hhEmu); break; }
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuSendKeyString * * DESCRIPTION: * Sends the specified string. * * ARGUMENTS: * hhEmu - The internal emulator handle. * nIndex - Position of key in keytable array. * pstKeyTbl - Address of key strings table.
* * RETURNS: * nothing */ void emuSendKeyString(const HHEMU hhEmu, const nIndex, const PSTKEYTABLE pstKeyTbl) { ECHAR str[80]; PSTKEY pstKey; TCHAR *pszTemp; memset(str, ETEXT('\0'), sizeof(str));
assert(nIndex >= 0 && nIndex < pstKeyTbl->iMaxKeys);
pstKey = pstKeyTbl->pstKeys + nIndex;
pszTemp = pstKey->fPointer ? pstKey->u.pachKeyStr : pstKey->u.achKeyStr; CnvrtMBCStoECHAR(str, sizeof(str), pszTemp, StrCharGetByteCount(pszTemp));
emuSendString(hhEmu, str, pstKey->uLen); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuSendString * * DESCRIPTION: * Sends the specified string. * * ARGUMENTS: * str -- address of string * strlen -- length of string * * RETURNS: * nothing */ void emuSendString(const HHEMU hhEmu, ECHAR *str, int nLen) { TCHAR *pchMBCS = NULL; TCHAR *pchTemp = NULL; unsigned long ulSize = 0; unsigned int i = 0; unsigned long ulDestSize = nLen + 1;
// This probably allocates way to many bytes, but if the incomming
// string is all MBC's we are safe.
pchMBCS = malloc((unsigned long)ulDestSize * sizeof(TCHAR)); if (pchMBCS == NULL) { assert(FALSE); return; } TCHAR_Fill(pchMBCS, TEXT('\0'), nLen + 1);
#if defined(INCL_VTUTF8)
if (!DoUTF8) { ulSize = (unsigned long)CnvrtECHARtoMBCS(pchMBCS, (unsigned long)ulDestSize * sizeof(TCHAR), str, (unsigned long)nLen * sizeof(ECHAR)); } else { while (nLen > (int)ulSize) { pchMBCS[ulSize++] = (str[ulSize] & 0x00FF); } } #else
ulSize = (unsigned long)CnvrtECHARtoMBCS(pchMBCS, (unsigned long)ulDestSize * sizeof(TCHAR), str, (unsigned long)nLen * sizeof(ECHAR)); #endif
//
// Make sure the string is NULL terminated. REV: 07/23/2001
//
pchMBCS[ulDestSize - 1] = TEXT('\0'); pchTemp = pchMBCS; ulSize = StrCharGetStrLength(pchTemp);
#if 0 //DEADWOOD:jkh, 12/12/1996
// Some systems mistake something like ESC 0 D if the codes
// are sent in separate packets. This now sends such sequences
// in a single socket write which should usually put them in
// the same packet (though it doesn't guarantee to do so.
// Loop through the # of bytes in the string
for (i = 0 ; i < ulSize ; ++i) CLoopCharOut(sessQueryCLoopHdl(hhEmu->hSession), *pchTemp++); #endif
CLoopBufrOut(sessQueryCLoopHdl(hhEmu->hSession), pchTemp, ulSize);
free(pchMBCS); pchMBCS = NULL; return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emu_reverse_image * * DESCRIPTION: * Reverses the foreground and background colors for the entire virtual * image. * * ARGUMENTS: * none * * RETURNS: * nothing */ void emu_reverse_image(const HHEMU hhEmu) { int nRow, nCol; STATTR stOldAttr; PSTATTR pstAttr;
// Set reverse screen mode for both clear and character attributes.
//
hhEmu->attrState[CSCLEAR_STATE].revvid = !hhEmu->attrState[CSCLEAR_STATE].revvid;
hhEmu->emu_clearattr_sav = hhEmu->emu_clearattr = hhEmu->attrState[CSCLEAR_STATE];
hhEmu->attrState[CS_STATE].revvid = !hhEmu->attrState[CS_STATE].revvid;
hhEmu->emu_charattr = hhEmu->attrState[CS_STATE];
for (nRow = 0; nRow < (hhEmu->emu_maxrow+1); nRow++) { pstAttr = hhEmu->emu_apAttr[nRow];
for (nCol = 0 ; nCol <= hhEmu->emu_maxcol ; ++nCol, ++pstAttr) { stOldAttr = *pstAttr; pstAttr->txtclr = stOldAttr.bkclr; pstAttr->bkclr = stOldAttr.txtclr; } }
updateLine(sessQueryUpdateHdl(hhEmu->hSession), 0, hhEmu->emu_maxrow); NotifyClient(hhEmu->hSession, EVENT_EMU_CLRATTR, 0); return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emu_is25lines * * DESCRIPTION: * Tells the calling function if the emulator is using the 25th line. * * ARGUMENTS: * none * * RETURNS: * TRUE if the emulator is using the 25th line */ int emu_is25lines(const HHEMU hhEmu) { return (hhEmu->mode_25enab ? TRUE : FALSE); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emu_kbdlocked * * DESCRIPTION: * Replacement kbdin that ignores all keys passed to it. * * ARGUMENTS: * key -- key to process * * RETURNS: * nothing */ /* ARGSUSED */ int emu_kbdlocked(const HHEMU hhEmu, int key, const int fTest) { return -1; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * nothing * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ /* ARGSUSED */ void nothing(const HHEMU hhEmu) { return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuKbdKeyLookup * * DESCRIPTION: * Main keyboard translation routine for all emulators. Note, this * routine will not lookup keys unless the iUseTermKeys flag is set. * * ARGUMENTS: * UINT key - lower byte is char or virtual key, upper byte has flags * * RETURNS: * Index if translated, else minus one. * */ int emuKbdKeyLookup(const HHEMU hhEmu, const int uKey, const PSTKEYTABLE pstKeyTbl) { PSTKEY pstKey;
if (hhEmu->stUserSettings.nTermKeys == EMU_KEYS_ACCEL) return -1;
pstKey = bsearch(&uKey, pstKeyTbl->pstKeys, (unsigned)pstKeyTbl->iMaxKeys, sizeof(KEY), KeyCmp);
if (pstKey) return (int)(pstKey - pstKeyTbl->pstKeys);
return -1; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuKeyTableLoad * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ /* ARGSUSED */ int emuKeyTableLoad(const HHEMU hhEmu, const KEYTBLSTORAGE pstKeySource[], const int nNumKeys, PSTKEYTABLE const pstKeyTbl) { int l; int nLoop = 0; PSTKEY pstKeys;
if (nNumKeys == 0) return FALSE;
emuKeyTableFree(pstKeyTbl); // free previous instance
if ((pstKeyTbl->pstKeys = malloc((unsigned)(nNumKeys * (int)sizeof(KEY)))) == 0) { assert(0); return FALSE; }
memset(pstKeyTbl->pstKeys, 0, (unsigned)(nNumKeys * (int)sizeof(KEY)));
if (pstKeyTbl->pstKeys) { for (pstKeys = pstKeyTbl->pstKeys; nLoop < nNumKeys ; pstKeys++, nLoop++) { pstKeys->key = pstKeySource[nLoop].KeyCode;
l = FFstrlen(pstKeySource[nLoop].achKeyStr);
if ( l <= (int)sizeof(LPTSTR) ) { pstKeys->fPointer = FALSE;
// Because of the goofy resource compiler, it was
// necessary to define a "\xff" in the resource data,
// when what we really wanted was a "\x00\xff". So,
// now we determine when this case occurs, and load the
// \x00 value manually. Note that there is an additional
// test for this below when determining the length of the
// the data.
//
if (l != 0) { MemCopy(pstKeys->u.achKeyStr, pstKeySource[nLoop].achKeyStr, (unsigned)l); }
else { pstKeys->u.achKeyStr[0] = '\x00'; } } else { pstKeys->fPointer = TRUE; pstKeys->u.pachKeyStr = malloc((unsigned)(l+1));
if (!pstKeys->u.pachKeyStr) { emuKeyTableFree(pstKeyTbl); break; }
MemCopy(pstKeys->u.pachKeyStr, pstKeySource[nLoop].achKeyStr, (unsigned)l); }
// Here's the special case test, again.
//
if (l !=0 ) pstKeys->uLen = (int)l; else pstKeys->uLen = 1;
pstKeyTbl->iMaxKeys += 1; } }
if (pstKeyTbl->iMaxKeys) { qsort(pstKeyTbl->pstKeys, (unsigned)pstKeyTbl->iMaxKeys, sizeof(KEY), KeyCmp); }
return (int)pstKeyTbl->iMaxKeys; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuKeyTableFree * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ void emuKeyTableFree(PSTKEYTABLE const pstKeyTbl) { int i;
for (i = 0 ; i < pstKeyTbl->iMaxKeys ; i++) { if (pstKeyTbl->pstKeys[i].fPointer) { free(pstKeyTbl->pstKeys[i].u.pachKeyStr); pstKeyTbl->pstKeys[i].u.pachKeyStr = NULL; } }
pstKeyTbl->iMaxKeys = 0;
if (pstKeyTbl->pstKeys) { free(pstKeyTbl->pstKeys); pstKeyTbl->pstKeys = (KEY *)0; }
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * FFstrlen * * DESCRIPTION: * Local version of strlen that uses '\ff' as a string terminator * * ARGUMENTS: * CHAR FAR *s - '\ff' terminated string. * * RETURNS: * length * */ static int FFstrlen(const BYTE *s) { int i = 0;
while (*s++ != 0xFF) i += 1;
return i; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* KeyCmp * * DESCRIPTION: Compare function for qsort. * * ARGUMENTS: * * RETURNS: * */ int _cdecl KeyCmp(PSTKEY pstKey1, PSTKEY pstKey2) { if (pstKey1->key > pstKey2->key) return 1;
if (pstKey1->key < pstKey2->key) return -1;
return 0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* emuInstallStateTable * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ void emuInstallStateTable(const HHEMU hhEmu, struct trans_entry const *e, int size) { struct state_entry *state_pntr = 0; int nStateCnt = 0; int nTransCnt = 0;
while (size--) { if (e->next_state == NEW_STATE) /* start a new state */ { assert(nStateCnt < MAX_STATE); hhEmu->state_tbl[nStateCnt].first_trans = &hhEmu->trans_tbl[nTransCnt]; state_pntr = &hhEmu->state_tbl[nStateCnt++]; state_pntr->number_trans = 0; } else /* add a transition */ { assert(nTransCnt < MAX_TRANSITION); assert(state_pntr); if (state_pntr) { ++state_pntr->number_trans; } hhEmu->trans_tbl[nTransCnt++] = *e; } ++e; } }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuCreateTextAttrBufs * * DESCRIPTION: * This one took a while to decipher but here is the bottom line. * emu_maxrow and emu_maxcol refer to the last row and column from * offset 0 (ZERO)! The emulator image has 2 (two) more columns for the * the stuff unknown to me at the present time. This function wants * the total number of rows and columns, so emu_maxrow = 23 means the * the argument nRows is 24. * * ARGUMENTS: * * RETURNS: * */ int emuCreateTextAttrBufs(const HEMU hEmu, const size_t nRows, size_t nCols) { const HHEMU hhEmu = (HHEMU)hEmu; register size_t i, ndx; PSTATTR pstAttr;
if (hhEmu == NULL) { return FALSE; }
if (hhEmu->emu_apText && hhEmu->emu_apAttr && hhEmu->emu_aiEnd) return (TRUE); else emuDestroyTextAttrBufs(hEmu);
nCols += 2; // Emulators need two extra columns.
// Allocate the text buffer.
//
if ((hhEmu->emu_apText = (ECHAR **)calloc(nRows, sizeof(ECHAR *))) == 0) { assert(FALSE); return FALSE; }
for (i = 0 ; i < nRows ; ++i) { if ((hhEmu->emu_apText[i] = (ECHAR *)calloc(nCols, sizeof(ECHAR))) == 0) { assert(FALSE); emuDestroyTextAttrBufs(hEmu); return FALSE; }
ECHAR_Fill(hhEmu->emu_apText[i], EMU_BLANK_CHAR, nCols); }
// Allocate the array to hold the rightmost character column number
// for each row.
//
if ((hhEmu->emu_aiEnd = (int *)calloc(nRows, sizeof(int))) == 0) { assert(FALSE); emuDestroyTextAttrBufs(hEmu); return FALSE; }
for (ndx = 0; ndx < nRows; ++ndx) hhEmu->emu_aiEnd[ndx] = EMU_BLANK_LINE;
// Allocate the attribute buffer.
//
if ((hhEmu->emu_apAttr = (PSTATTR *)calloc(nRows, sizeof(LPTSTR))) == 0) { assert(FALSE); emuDestroyTextAttrBufs(hEmu); return FALSE; }
for (i = 0 ; i < nRows ; ++i) { if ((hhEmu->emu_apAttr[i] = calloc(nCols, sizeof(STATTR))) == 0) { assert(FALSE); emuDestroyTextAttrBufs(hEmu); return FALSE; }
for (ndx = 0, pstAttr = hhEmu->emu_apAttr[i] ; ndx < nCols ; ++ndx) pstAttr[ndx] = hhEmu->emu_clearattr; }
return TRUE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuDestroyTextAttrBufs * * DESCRIPTION: * Destroys any allocated buffers for text and attributes. * * ARGUMENTS: * void * * RETURNS: * void * */ void emuDestroyTextAttrBufs(const HEMU hEmu) { const HHEMU hhEmu = (HHEMU)hEmu; register int i;
if (hEmu == NULL || hhEmu == NULL) { return; }
if (hhEmu->emu_apText) { //
// Fixed memory leak hhEmu->emu_maxrow != MAX_EMUROWS
// MAX_EMUROWS was what was allocated. REV: 12/20/2000
//
for (i = 0 ; i < MAX_EMUROWS ; ++i) { if (hhEmu->emu_apText[i]) { free(hhEmu->emu_apText[i]); hhEmu->emu_apText[i] = NULL; } if (hhEmu->emu_apAttr[i]) { free(hhEmu->emu_apAttr[i]); hhEmu->emu_apAttr[i] = NULL; } }
free(hhEmu->emu_apText); hhEmu->emu_apText = 0;
free(hhEmu->emu_apAttr); hhEmu->emu_apAttr = 0; }
if (hhEmu->emu_aiEnd) { free(hhEmu->emu_aiEnd); hhEmu->emu_aiEnd = 0; }
if (hhEmu->emu_apAttr) { for (i = 0 ; i <= hhEmu->emu_maxrow ; ++i) { if (hhEmu->emu_apAttr[i]) { free(hhEmu->emu_apAttr[i]); hhEmu->emu_apAttr[i] = NULL; } }
free(hhEmu->emu_apAttr); hhEmu->emu_apAttr = 0; }
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * emuCreateNameTable * * DESCRIPTION: * Loads the Emulator Names into a table * * ARGUMENTS: * HHEMU hhEmu - Emulator Handle * * RETURNS: * Success/Failure * */ int emuCreateNameTable(const HHEMU hhEmu) { int iLen, idx, iRet; TCHAR achText[256];
iRet = TRUE;
emuLock((HEMU)hhEmu);
if (hhEmu->pstNameTable) { free(hhEmu->pstNameTable); hhEmu->pstNameTable = NULL; }
if ((hhEmu->pstNameTable = malloc(sizeof(STEMUNAMETABLE) * NBR_EMULATORS)) == 0) { assert(FALSE); iRet = FALSE; goto LoadExit; }
// Load the emulator name table. It simply contains the name and id of
// all of the supported emulators.
//
// EMU_AUTO
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_AUTO, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx = 0; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_AUTO;
// EMU_ANSI
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_ANSI, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_ANSI;
// EMU_ANSIW
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_ANSIW, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_ANSIW;
// EMU_MIMI
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_MINI, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_MINI;
// EMU_VIEW
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VIEW, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VIEW;
// EMU_TTY
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_TTY, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_TTY;
// EMU_VT100
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT100, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VT100;
// EMU_VT52
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT52, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VT52;
// EMU_VT100J
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT100J, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VT100J;
#if defined(INCL_VT220)
// EMU_VT220
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT220, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VT220; #endif
#if defined(INCL_VT320)
// EMU_VT320
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT320, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VT320; #endif
#if defined(INCL_VT100PLUS)
// EMU_VT100+
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VT100PLUS, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN(hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VTUTF8; #endif
#if defined(INCL_VTUTF8)
// EMU_VTUTF8
//
iLen = LoadString(glblQueryDllHinst(), IDS_EMUNAME_VTUTF8, achText, sizeof(achText) / sizeof(TCHAR));
if (iLen >= EMU_MAX_NAMELEN) { assert(FALSE); iRet = FALSE; goto LoadExit; }
idx++; StrCharCopyN (hhEmu->pstNameTable[idx].acName, achText, EMU_MAX_NAMELEN); hhEmu->pstNameTable[idx].nEmuId = EMU_VTUTF8; #endif
LoadExit:
emuUnlock((HEMU)hhEmu); return(iRet);
}
/* end of emu.c */
|