2025-04-27 07:49:33 -04:00

799 lines
30 KiB
C

/* File: cloop.c (created 12/27/93, JKH)
*
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 2 $
* $Date: 3/16/01 4:28p $
*/
#include <windows.h>
#pragma hdrstop
#include <tdll\features.h>
// #define DEBUGSTR
#include <tdll\stdtyp.h>
#include <tdll\session.h>
#include <tdll\globals.h>
#include <tdll\timers.h>
#include <tdll\com.h>
#include <tdll\xfer_msc.h>
#include <emu\emu.h>
#if defined(CHARACTER_TRANSLATION)
#include <tdll\translat.hh>
#endif
#if defined(INCL_VTUTF8)
#include <emu\emu.hh>
#include <tdll\htchar.h>
#endif
#include "cloop.h"
#include "cloop.hh"
#include "tchar.h"
#include <tdll\assert.h>
#if defined(INCL_VTUTF8)
BOOL DoUTF8 = FALSE;
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: CLoop
*
* DESCRIPTION:
* This function comprises the 'engine' of the engine thread. Its action
* is controlled by a series of control bits that are set and cleared
* by calls to CLoopRcvControl and CLoopControl
*
* ARGUMENTS:
* pstCLoop -- Handle returned from CLoopCreateHandle
*
* RETURNS:
* nothing
*/
DWORD WINAPI CLoop(LPVOID pvData) {
ST_CLOOP * const pstCLoop = (ST_CLOOP *)pvData;
HCOM hCom;
int nRcvCount;
TCHAR chData = (TCHAR)0;
ECHAR echData = (ECHAR)0;
HSESSION hSession;
HEMU hEmu;
KEY_T keyOut;
ST_FCHAIN *pstCurrent;
CHAINFUNC pfChainFunc;
int fValidChar;
#if defined(CHARACTER_TRANSLATION)
HHTRANSLATE hTrans;
#endif
int nCount;
int nIndx;
CHAR chBuffer[32]; /* Yes, it is supposed to be a CHAR */
int mc;
#if defined(INCL_VTUTF8)
HHEMU hhEmu;
UCHAR UTF8Buffer[32*3]; // Each UTF-8 character can be 3 characters in length.
WCHAR UNICODEBuffer[32];
TCHAR DBCSBuffer[32];
memset(UTF8Buffer, 0, sizeof(UTF8Buffer));
memset(UNICODEBuffer, 0, sizeof(UNICODEBuffer));
memset(DBCSBuffer, 0, sizeof(DBCSBuffer));
#endif // INCL_VTUTF8
DBGOUT_NORMAL("In CLoop(%lX)\r\n", pstCLoop,0,0,0,0);
assert(pstCLoop);
EnterCriticalSection(&pstCLoop->csect);
hSession = pstCLoop->hSession;
hCom = pstCLoop->hCom;
hEmu = pstCLoop->hEmu;
#if defined(CHARACTER_TRANSLATION)
hTrans = (HHTRANSLATE)sessQueryTranslateHdl(pstCLoop->hSession);
#endif
assert(hSession);
assert(hCom);
assert(hEmu);
DBGOUT_NORMAL("CLoop got critical section\r\n", 0,0,0,0,0);
while (!bittest(pstCLoop->afControl, CLOOP_TERMINATE)) {
DWORD dwRet;
// Normally, this CLoop function owns the critical section
// controlling the CLoop data. We give it up at least once each
// time through the loop to give other threads a change to call
// control functions.
LeaveCriticalSection(&pstCLoop->csect);
// Block if there is nothing to do
DBGOUT_YIELD("W+ ", 0,0,0,0,0);
dwRet = WaitForMultipleObjects(DIM(pstCLoop->ahEvents),
pstCLoop->ahEvents, FALSE, INFINITE);
DBGOUT_YIELD("W(0x%x)", dwRet,0,0,0,0);
EnterCriticalSection(&pstCLoop->csect);
DBGOUT_YIELD(": ", 0,0,0,0,0);
// See if a transfer has been initiated
if (bittest(pstCLoop->afControl, CLOOP_TRANSFER_READY)) {
DBGOUT_NORMAL("CLoop calling xfer\r\n", 0,0,0,0,0);
LeaveCriticalSection(&pstCLoop->csect);
xfrDoTransfer(sessQueryXferHdl(hSession));
DBGOUT_NORMAL("CLoop back from xfer\r\n", 0,0,0,0,0);
EnterCriticalSection(&pstCLoop->csect);
CLoopControl((HCLOOP)pstCLoop, CLOOP_CLEAR, CLOOP_TRANSFER_READY);
}
// If there is input waiting and we are not blocked from receiving
if (!pstCLoop->afRcvBlocked) {
// Give priority to receiving over sending since normally
// we will receive more data than we send (CR becomes CR LF)
// and since we have more control over the send rate
// TODO: implement priority setting by adjusting rcv count
for (nRcvCount = 10; nRcvCount--; ) {
fValidChar = FALSE;
if (mComRcvChar(hCom, &chData)) {
DBGOUT_NORMAL("Recieved Char\r\n", 0,0,0,0,0);
// Check for force to 7-bit ASCII
if (pstCLoop->stWorkSettings.fASCII7) {
chData &= 0x7F;
}
nCount = 0;
#if defined(INCL_VTUTF8)
//
// Do the UTF-8 conversions here if this is a VT-UTF8
// emulator.
//
hhEmu = (HHEMU)hEmu;
if (hhEmu != NULL &&
hhEmu->stUserSettings.nEmuId == EMU_VTUTF8) {
int iUTF8BufferLength = sizeof(UTF8Buffer);
int iUNICODEBufferLength = sizeof(UNICODEBuffer);
int iDBCSBufferLength = sizeof(DBCSBuffer);
DoUTF8 = TRUE;
if (TranslateUTF8ToDBCS(chData,
UTF8Buffer,
iUTF8BufferLength,
UNICODEBuffer,
iUNICODEBufferLength,
DBCSBuffer,
iDBCSBufferLength) == TRUE) {
//
// Now copy the DBCS buffer back into the chBuffer
// character array that is used later.
//
StrCharCopyN(chBuffer, DBCSBuffer,
sizeof(chBuffer));
nCount = StrCharGetByteCount(chBuffer);
//
// NULL out the Existing buffer.
//
memset(UTF8Buffer, 0, sizeof(UTF8Buffer));
memset(UNICODEBuffer, 0, sizeof(UNICODEBuffer));
memset(DBCSBuffer, 0, sizeof(DBCSBuffer));
} else {
nCount = -1;
}
}
if (hhEmu != NULL &&
hhEmu->stUserSettings.nEmuId != EMU_VTUTF8) {
DoUTF8 = FALSE;
#endif //INCL_VTUTF8
if ( nCount >= 0 ) {
#if defined(CHARACTER_TRANSLATION)
LeaveCriticalSection(&pstCLoop->csect);
hTrans->pfnIn(hTrans->pDllHandle,
chData,
&nCount,
sizeof(chBuffer),
chBuffer);
EnterCriticalSection(&pstCLoop->csect);
#else
chBuffer[0] = chData;
nCount = 1;
#endif
}
#if defined(INCL_VTUTF8)
}
#endif
for (nIndx = 0; nIndx < nCount; nIndx++) {
if (pstCLoop->fDoMBCS
#if defined(INCL_VTUTF8)
&&
(hhEmu != NULL &&
hhEmu->stUserSettings.nEmuId != EMU_VTUTF8)) {
#else
) {
#endif
if (pstCLoop->cLeadByte) {
chData = 0;
echData = chBuffer[nIndx] & 0xFF;
// There must be a macro for this somewhere
echData |= (ECHAR)(pstCLoop->cLeadByte << 8);
pstCLoop->cLeadByte = 0;
fValidChar = TRUE;
} else {
if (IsDBCSLeadByte(chBuffer[nIndx])) {
pstCLoop->cLeadByte = chBuffer[nIndx];
} else {
echData = chBuffer[nIndx] & 0xFF;
fValidChar = TRUE;
}
}
} // if (fDoMBCS)
else {
echData = ETEXT(chBuffer[nIndx]);
fValidChar = TRUE;
#if defined(INCL_VTUTF8)
if (hhEmu != NULL && hhEmu->stUserSettings.nEmuId == EMU_VTUTF8) {
memcpy(&echData, &chBuffer[nIndx], sizeof(ECHAR));
fValidChar = TRUE;
mc = 0;
nIndx +=1;
}
#endif
} // else (fDoMBCS)
if (fValidChar) {
#if FALSE
// Moved up above 11-Jan-95 DLW
// Check for force to 7-bit ASCII
if (pstCLoop->stWorkSettings.fASCII7)
echData &= 0x7F;
#endif
// Character translation/stripping
//*if ((chData = pstCLoop->panFltrIn[chData]) == -1)
//* continue;
// walk remote input function chain if it exists
if (pstCLoop->fRmtChain) {
pstCLoop->pstRmtChainNext =
pstCLoop->pstRmtChain;
while (pstCLoop->pstRmtChainNext) {
pstCurrent = pstCLoop->pstRmtChainNext;
pstCLoop->pstRmtChainNext =
pstCurrent->pstNext;
pfChainFunc = pstCurrent->pfFunc;
LeaveCriticalSection(&pstCLoop->csect);
mc = (*pfChainFunc)(chData,
pstCurrent->pvUserData);
EnterCriticalSection(&pstCLoop->csect);
if ( mc == CLOOP_DISCARD )
break;
}
}
if ( mc != CLOOP_DISCARD ) {
pstCLoop->fDataReceived = TRUE;
CLoopCharIn(pstCLoop, echData);
}
if (pstCLoop->afRcvBlocked) {
/*
* This is necessary because a script may be
* checking input and then stopping after it
* finds what it is looking for. If the loop
* count is still possitive, the remaining
* characters will "slip thru" before this
* loop terminates.
* This won't break in any obvious way, so be
* careful to preserve this feature if this
* loop is rewritten.
*
* TODO: when scripts are added, make sure this
* works correctly with character translation.
*/
// Receiving has been blocked,
// make sure any received
// data gets displayed.
LeaveCriticalSection(&pstCLoop->csect);
emuComDone(hEmu);
EnterCriticalSection(&pstCLoop->csect);
break;
}
}
}
//
// Clear the temporary input character buffer.
// as the buffer has been copied into echData.
// REV: 03/06/2001
//
memset(chBuffer, 0, sizeof(chBuffer));
} else {
CLoopRcvControl((HCLOOP)pstCLoop, CLOOP_SUSPEND,
CLOOP_RB_NODATA);
if (pstCLoop->fDataReceived) {
// Notify emulator that there is a pause in the
// stream of received data
LeaveCriticalSection(&pstCLoop->csect);
emuComDone(hEmu);
EnterCriticalSection(&pstCLoop->csect);
// If we had a delay timer already running, kill it
if (pstCLoop->htimerRcvDelay)
TimerDestroy(&pstCLoop->htimerRcvDelay);
// The stream of incoming data has stopped, set a
// timer so we can tell if it stops long enough to
// do cursor tracking etc.
if (TimerCreate(sessQueryTimerMux(pstCLoop->hSession),
&pstCLoop->htimerRcvDelay,
CLOOP_TRACKING_DELAY,
/* pstCLoop->pfRcvDelay, */
CLoopRcvDelayProc,
(void *)pstCLoop) != TIMER_OK) {
pstCLoop->htimerRcvDelay = (HTIMER)0;
assert(FALSE);
}
pstCLoop->fDataReceived = FALSE;
}
break;
}
}
}
// Check for outgoing data.
if (!pstCLoop->afSndBlocked) {
// (Taken verbatim from HA5G, by JMH 03-22-96):
// This change was added to fix a deadlock problem. While sending
// and receiving data simultaneously at high speed, it was
// possible for us to issue a handshake stop at the same time
// we would receive one from the host. Our code would wait
// in the ComSendBufr call and stop processing. Because of this,
// we would not be processing incoming data so we would never
// clear the handshake stop we had issued to the other end. If
// the other end was caught in the same state -- deadlock.
// This test slows our text transmission down. We should
// redesgin our transmission model to fix this. jkh, 1/19/95
// if (CLoopGetNextOutput(pstCLoop, &keyOut)) DEADWOOD:jmh 03-22-96
if (ComSndBufrBusy(hCom) == COM_BUSY) {
// UNDO:REV 03/01/2001 I believe this is where the problem with slow text file transfer is occurring!
//
//We need to unlock cloop around this sleep so that calls to
// emuKbdIn and emuDataIn, because may call the com
// thread, which may be stuck waiting to access cloop.
//
LeaveCriticalSection(&pstCLoop->csect);
Sleep(10); // jkh 04/29/1998 don't peg CPU
/*
* This is necessary because a script may be
* checking input and then stopping after it
* finds what it is looking for. If the loop
* count is still possitive, the remaining
* characters will "slip thru" before this
* loop terminates.
* This won't break in any obvious way, so be
* careful to preserve this feature if this
* loop is rewritten.
*
* TODO: when scripts are added, make sure this
* works correctly with character translation.
*/
// Receiving has been blocked,
// make sure any received
// data gets displayed.
// REV: 03/05/2001 Make sure the COM driver knows we're done.
//emuComDone(hEmu);
EnterCriticalSection(&pstCLoop->csect);
} else if (CLoopGetNextOutput(pstCLoop, &keyOut)) {
// Check for tab expansion
//DbgOutStr("C", 0,0,0,0,0);
if (keyOut == TEXT('\t') &&
pstCLoop->stWorkSettings.fExpandTabsOut &&
pstCLoop->stWorkSettings.nTabSizeOut) {
//* int i;
//* POINT pt;
//* mEmuGetCursorPos(
//* mGetEmulatorHdl(pstCLoop->hSession),
//* &pt);
//* i = pstCLoop->stWorkSettings.usTabSizeOut -
//* ((pt.x + 1) % pstCLoop->stWorkSettings.usTabSizeOut);
//* while (i-- > 0)
//* (VOID)mEmuKbdIn(hEmu, (KEY_T)TEXT(' '), FALSE);
}
else {
//jmh 03-22-96 We need to unlock cloop around calls to
// emuKbdIn and emuDataIn, because they call the com
// thread, which may be stuck waiting to access cloop.
//
LeaveCriticalSection(&pstCLoop->csect);
emuKbdIn(hEmu, keyOut, FALSE);
EnterCriticalSection(&pstCLoop->csect);
}
if (keyOut == TEXT('\r')) {
if (pstCLoop->stWorkSettings.fLineWait) {
CLoopSndControl((HCLOOP)pstCLoop, CLOOP_SUSPEND,
CLOOP_SB_LINEWAIT);
}
if (pstCLoop->stWorkSettings.fSendCRLF) {
//DEADWOOD:jkh 8/18/97
// Can't use CLoopSend here because the '\n' is placed
// behind any other codes waiting in the output queue.
// This caused all LF codes in a text file send to be
// sent AFTER the whole file, rather than after each CR
// CLoopSend((HCLOOP) pstCLoop, TEXT("\n"), 1, 0);
LeaveCriticalSection(&pstCLoop->csect);
emuKbdIn(hEmu, (KEY_T)'\n', FALSE);
EnterCriticalSection(&pstCLoop->csect);
#if 0 //DEADWOOD: RDE 20AUG98 MPT Fixed a local echo problem down in
// CloopCharIn which then caused an extra linefeed
// to be displayed on the local terminal.
if (pstCLoop->stWorkSettings.fLocalEcho &&
!pstCLoop->fSuppressDsp) {
//jmh 03-22-96 We need to unlock cloop around calls to
// emuKbdIn and emuDataIn, because they call the com
// thread, which may be stuck waiting to access cloop.
//
LeaveCriticalSection(&pstCLoop->csect);
emuDataIn(hEmu, TEXT('\n'));
emuComDone(hEmu);
EnterCriticalSection(&pstCLoop->csect);
}
#endif
}
if (pstCLoop->stWorkSettings.nLineDelay) {
if (TimerCreate(
sessQueryTimerMux(pstCLoop->hSession),
&pstCLoop->htimerCharDelay,
pstCLoop->stWorkSettings.nLineDelay,
pstCLoop->pfCharDelay,
(void *)pstCLoop) == TIMER_OK)
CLoopSndControl((HCLOOP)pstCLoop, CLOOP_SUSPEND,
CLOOP_SB_DELAY);
}
} else {
if (pstCLoop->stWorkSettings.nCharDelay) {
if (TimerCreate(
sessQueryTimerMux(pstCLoop->hSession),
&pstCLoop->htimerCharDelay,
pstCLoop->stWorkSettings.nCharDelay,
pstCLoop->pfCharDelay,
(void *)pstCLoop) == TIMER_OK)
CLoopSndControl((HCLOOP)pstCLoop, CLOOP_SUSPEND,
CLOOP_SB_DELAY);
}
}
//* if (pstCLoop->lpLearn)
//* {
//* CLearnSendChar(pstCLoop->lpLearn, (METACHAR)keyOut);
//* }
}
}
// Make sure any buffered output waiting gets sent.
//* ComSendPush(pstCLoop->hCom);
}
DBGOUT_NORMAL("Leaving CLoop(%lX)\r\n", pstCLoop,0,0,0,0);
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: CLoopCharIn
*
* DESCRIPTION:
* Does rec eive processing for characters received from the remote system
*
* ARGUMENTS:
* pstCLoop -- Handle returned from CLoopCreateHandle
* mc -- Character to be processed.
*
* RETURNS:
* nothing
*/
void CLoopCharIn(ST_CLOOP *pstCLoop, ECHAR chIn) {
// Check for echoplex
if (pstCLoop->stWorkSettings.fEchoplex) {
//mpt:1-27-98 converting echars to tchar was converting
// the character to a single byte. Consequently,
// echoing of a dbcs character was only echoing
// the second byte of the character.
if ( (pstCLoop->fDoMBCS) && (chIn > 255) ) {
//send first byte
ComSendCharNow(pstCLoop->hCom, (TCHAR) (chIn >> 8));
//send second byte
ComSendCharNow(pstCLoop->hCom, (TCHAR) (chIn & 0xFF));
} else {
ComSendCharNow(pstCLoop->hCom, (TCHAR) chIn);
}
if (chIn == ETEXT('\r')) {
ComSendCharNow(pstCLoop->hCom, TEXT('\n'));
}
}
if (pstCLoop->stWorkSettings.fLineWait &&
chIn == pstCLoop->stWorkSettings.chWaitChar)
CLoopSndControl((HCLOOP)pstCLoop, CLOOP_RESUME, CLOOP_SB_LINEWAIT);
// Display character in normal or image mode
if (!pstCLoop->fSuppressDsp) {
// DbgOutStr("Dsp %02X (%c)\r\n", chIn, chIn, 0,0,0);
emuDataIn(pstCLoop->hEmu, chIn);
if (chIn == ETEXT('\r') && pstCLoop->stWorkSettings.fAddLF)
emuDataIn(pstCLoop->hEmu, ETEXT('\n'));
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* CLoopCharOut
*
* DESCRIPTION:
* Called to send a character out the port with processing by the CLoop
* routines. Note that this differs from CLoopSend.
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
void CLoopCharOut(HCLOOP hCLoop, TCHAR chOut) {
ST_CLOOP * const pstCLoop = (ST_CLOOP *)hCLoop;
int fCharValid = FALSE;
ECHAR echOut = (ECHAR)0;
#if defined(INCL_VTUTF8)
int nUTF8Count;
int nUTF8Index;
HHEMU hhEmu = (HHEMU)pstCLoop->hSession;
CHAR chUTF8Buffer[32]; /* Yes, it is supposed to be a CHAR */
#endif // INCL_VTUTF8
#if defined(CHARACTER_TRANSLATION)
HHTRANSLATE hTrans;
int nCount;
int nIndx;
CHAR chBuffer[32]; /* Yes, it is supposed to be a CHAR */
hTrans = (HHTRANSLATE)sessQueryTranslateHdl(pstCLoop->hSession);
(*hTrans->pfnOut)(hTrans->pDllHandle,
chOut,
&nCount,
sizeof(chBuffer),
chBuffer);
for (nIndx = 0; nIndx < nCount; nIndx += 1) {
chOut = chBuffer[nIndx];
#endif //CHARACTER_TRANSLATION
#if defined(INCL_VTUTF8)
if (hhEmu != NULL && hhEmu->stUserSettings.nEmuId == EMU_VTUTF8) {
UCHAR UTF8Buffer[32*3]; // Each UTF-8 character can be 3 characters in length.
WCHAR UNICODEBuffer[32];
TCHAR DBCSBuffer[32];
int iUTF8BufferLength = sizeof(UTF8Buffer);
int iUNICODEBufferLength = sizeof(UNICODEBuffer);
int iDBCSBufferLength = sizeof(DBCSBuffer);
memset(UTF8Buffer, 0, sizeof(UTF8Buffer));
memset(UNICODEBuffer, 0, sizeof(UNICODEBuffer));
memset(DBCSBuffer, 0, sizeof(DBCSBuffer));
#if 0 // TODO:REV 03/16/2001 Add the code to convert the character to UTF-8 format here.
if (TranslateDBCSToUTF8(DBCSBuffer,
iDBCSBufferLength,
UNICODEBuffer,
iUNICODEBufferLength,
UTF8Buffer,
iUTF8BufferLength) == TRUE) {
//
// Now copy the DBCS buffer back into the chBuffer
// character array that is used later.
//
StrCharCopyN(chUTF8Buffer, UTF8Buffer,
sizeof(chUTF8Buffer));
nUTF8Count = StrCharGetByteCount(chUTF8Buffer);
//
// NULL out the Existing buffer.
//
memset(UTF8Buffer, 0, sizeof(UTF8Buffer));
memset(UNICODEBuffer, 0, sizeof(UNICODEBuffer));
memset(DBCSBuffer, 0, sizeof(DBCSBuffer));
} else
#endif
{
nUTF8Index = 0;
nUTF8Count = 1;
chUTF8Buffer[0] = chOut;
}
} else {
nUTF8Index = 0;
nUTF8Count = 1;
chUTF8Buffer[0] = chOut;
}
for (nUTF8Index = 0; nUTF8Index < nUTF8Count; nUTF8Index++) {
chOut = chUTF8Buffer[nUTF8Index];
#endif
ComSendCharNow(pstCLoop->hCom, chOut);
if (pstCLoop->stWorkSettings.fLocalEcho &&
!pstCLoop->fSuppressDsp) {
if (pstCLoop->fDoMBCS) {
if (pstCLoop->cLocalEchoLeadByte) {
echOut = chOut & 0xFF;
echOut |= (ECHAR)(pstCLoop->cLocalEchoLeadByte << 8);
pstCLoop->cLocalEchoLeadByte = 0;
fCharValid = TRUE;
} else {
if (IsDBCSLeadByte(chOut)) {
pstCLoop->cLocalEchoLeadByte = chOut;
} else {
echOut = chOut & 0xFF;
fCharValid = TRUE;
}
}
} else {
echOut = (ECHAR)chOut;
fCharValid = TRUE;
}
if (fCharValid) {
emuDataIn(pstCLoop->hEmu, echOut);
emuComDone(pstCLoop->hEmu);
}
}
#if defined(CHARACTER_TRANSLATION)
}
#endif
#if defined(INCL_VTUTF8)
}
#endif
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* CLoopBufrOut
*
* DESCRIPTION:
* Called to send a buffer of characters out the port with processing by the CLoop
* routines. Note that this differs from CLoopSend.
*
* ARGUMENTS:
*
*
* RETURNS:
* void
*
*/
void CLoopBufrOut(HCLOOP hCLoop, TCHAR *pchOut, int nLen) {
ST_CLOOP * const pstCLoop = (ST_CLOOP *)hCLoop;
int fCharValid = FALSE;
while (nLen--) {
ComSendChar(pstCLoop->hCom, *pchOut); // place chars in comsend buffer
if (pstCLoop->stWorkSettings.fLocalEcho &&
!pstCLoop->fSuppressDsp) {
if (pstCLoop->fDoMBCS) {
if (pstCLoop->cLocalEchoLeadByte != 0) {
*pchOut |= (TCHAR)(pstCLoop->cLocalEchoLeadByte << 8);
pstCLoop->cLocalEchoLeadByte = 0;
fCharValid = TRUE;
} else {
if (IsDBCSLeadByte(*pchOut)) {
pstCLoop->cLocalEchoLeadByte = *pchOut;
} else {
fCharValid = TRUE;
}
}
} else {
fCharValid = TRUE;
}
if (fCharValid) {
emuDataIn(pstCLoop->hEmu, *pchOut);
emuComDone(pstCLoop->hEmu);
}
}
++pchOut;
}
ComSendPush(pstCLoop->hCom);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: CLoopRcvDelayProc
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
/* ARGSUSED */
void CALLBACK CLoopRcvDelayProc(void *pvData, long lSince) {
// This timer was set the last time data input stopped. If no data
// has been received since, notify the display routines so they can
// do cursor tracking or whatever silly thing it is they do.
ST_CLOOP *pstCLoop = (ST_CLOOP *)pvData;
EnterCriticalSection(&pstCLoop->csect);
if (!pstCLoop->fDataReceived) {
emuTrackingNotify(pstCLoop->hEmu);
}
TimerDestroy(&pstCLoop->htimerRcvDelay);
(void)&lSince; // avoid compiler warnings
LeaveCriticalSection(&pstCLoop->csect);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: CLoopCharDelayProc
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
/* ARGSUSED */
void CALLBACK CLoopCharDelayProc(void *pvData, long lSince) {
ST_CLOOP *pstCLoop = (ST_CLOOP *)pvData;
EnterCriticalSection(&pstCLoop->csect);
TimerDestroy(&pstCLoop->htimerCharDelay);
CLoopSndControl((HCLOOP)pstCLoop, CLOOP_RESUME, CLOOP_SB_DELAY);
LeaveCriticalSection(&pstCLoop->csect);
(void)&lSince; // avoid compiler warnings
}