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.
 
 
 
 
 
 

1816 lines
44 KiB

/* File: D:\WACKER\emu\vt100.c (Created: 08-Dec-1993)
*
* Copyright 1994, 1998 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 11 $
* $Date: 3/04/02 12:00p $
*/
#include <windows.h>
#pragma hdrstop
#include <tdll\stdtyp.h>
#include <tdll\tdll.h>
#include <tdll\htchar.h>
#include <tdll\session.h>
#include <tdll\chars.h>
#include <tdll\com.h>
#include <tdll\cloop.h>
#include <tdll\assert.h>
#include <tdll\print.h>
#include <tdll\capture.h>
#include <tdll\update.h>
#include <tdll\backscrl.h>
#include <tdll\mc.h>
#include "emu.h"
#include "emu.hh"
#include "emudec.hh"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* emuDecGraphic
*
* 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 emuDecGraphic(const HHEMU hhEmu)
{
ECHAR ccode = hhEmu->emu_code;
ECHAR aechBuf[10];
int iCharsToMove;
int fDecColHold = FALSE;
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];
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
// Initialize a test flag. This is used for a special case when
// emulating a VT100 (and maybe other DEC emulators) and the
// current column position is the maximum. When a character is placed
// at emu_maxcol, instead of advancing the cursor to column 0 of the
// next line, it is instead placed under that last character. When the
// next character arrives, it is placed at column 0 on the next line, and
// then the cursor is advanced as expected.
//
// Special DEC test.
//
if (hhEmu->mode_AWM && iCol == hhEmu->emu_maxcol)
{
if (pstPRI->fDecColHold)
{
fDecColHold = FALSE;
CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
CF_CAP_LINES,
tp,
emuRowLen(hhEmu, hhEmu->emu_imgrow));
printEchoString(hhEmu->hPrintEcho,
tp,
emuRowLen(hhEmu, hhEmu->emu_imgrow));
CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
StrCharGetByteCount(TEXT("\r\n")));
printEchoString(hhEmu->hPrintEcho,
aechBuf,
sizeof(ECHAR) * 2);
if (iRow == hhEmu->bottom_margin)
(*hhEmu->emu_scroll)(hhEmu, 1, TRUE);
else
++iRow;
iCol = 0;
(*hhEmu->emu_setcurpos)(hhEmu, iRow, iCol);
tp = hhEmu->emu_apText[hhEmu->emu_imgrow];
ap = hhEmu->emu_apAttr[hhEmu->emu_imgrow];
}
else
{
iCol = hhEmu->emu_maxcol;
fDecColHold = TRUE;
}
}
// Is the emulator in insert mode?
//
if (hhEmu->mode_IRM == SET)
{
iCharsToMove = (hhEmu->emu_aiEnd[hhEmu->emu_imgrow] - iCol + 1);
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) ||
(hhEmu->stUserSettings.nEmuId == EMU_VT220) ||
(hhEmu->stUserSettings.nEmuId == EMU_VT320) ||
(hhEmu->stUserSettings.nEmuId == EMU_VT100PLUS) ||
(hhEmu->stUserSettings.nEmuId == EMU_VTUTF8)) &&
ccode < sizeof(hhEmu->dspchar))
ccode = hhEmu->dspchar[ccode];
tp[iCol] = ccode;
ap[iCol] = hhEmu->emu_charattr;
// Check for double high, double wide processing.
//
if (pstPRI->aiLineAttr[hhEmu->emu_imgrow] != NO_LINE_ATTR)
{
int iColPrev = iCol;
ap[iCol].dblwilf = 1;
ap[iCol].dblwirt = 0;
ap[iCol].dblhihi = (pstPRI->aiLineAttr[hhEmu->emu_imgrow] == DBL_WIDE_HI) ? 1 : 0;
ap[iCol].dblhilo = (pstPRI->aiLineAttr[hhEmu->emu_imgrow] == DBL_WIDE_LO) ? 1 : 0;
iCol = min(iCol+1, hhEmu->emu_maxcol);
tp[iCol] = ccode;
ap[iCol] = ap[iColPrev];
ap[iCol].dblwilf = 0;
ap[iCol].dblwirt = 1;
}
#ifndef CHAR_NARROW
// Process Double Byte Characters
//
if (QueryCLoopMBCSState(sessQueryCLoopHdl(hhEmu->hSession)))
{
if (isDBCSChar(ccode))
{
int iColPrev = iCol;
ap[iCol].wilf = 1;
ap[iCol].wirt = 0;
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));
}
//blank out character at end of line
tp[hhEmu->emu_aiEnd[hhEmu->emu_imgrow]] = 32;
ap[hhEmu->emu_aiEnd[hhEmu->emu_imgrow]].wirt = 0;
//move end of row since we removed a character
hhEmu->emu_aiEnd[hhEmu->emu_imgrow]--;
//update the image
updateChar(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->emu_imgrow,
hhEmu->emu_aiEnd[hhEmu->emu_imgrow],
hhEmu->mode_IRM ?
hhEmu->emu_maxcol :
hhEmu->emu_aiEnd[hhEmu->emu_imgrow]);
}
}
#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,
hhEmu->emu_curcol,
hhEmu->mode_IRM ? hhEmu->emu_maxcol : iCol);
// Move the position of the cursor ahead of the last character
// displayed, checking for end of line wrap.
//
iCol += 1;
// Finally, set the cursor position. This wil reset emu_currow
// and emu_curcol.
//
(*hhEmu->emu_setcurpos)(hhEmu, iRow, iCol);
// Whenever we call setcurpos, it resets pstPRI->fDecColHold so
// don't set till after we postion cursor.
//
pstPRI->fDecColHold = fDecColHold;
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* ANSI_DA
*
* DESCRIPTION:
* Sends the device attribute (DA) report to the host.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void ANSI_DA(const HHEMU hhEmu)
{
int fOldValue;
ECHAR ech[15];
CnvrtMBCStoECHAR(ech, sizeof(ech), TEXT("\033[?1;2c"),
StrCharGetByteCount(TEXT("\033[?1;2c")));
fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
emuSendString(hhEmu, ech, (int)StrCharGetEcharByteCount(ech));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt100_savecursor
*
* DESCRIPTION:
* Saves the current cursor postion; and, it also
* saves display attributes, character set, wrap mode, and origin mode.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*
* NOTES:
* This function contains Auto Detect code.
*/
void vt100_savecursor(const HHEMU hhEmu)
{
ECHAR sel;
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
sel = hhEmu->emu_code;
if (sel == ETEXT('7')) /* save cursor & attributes */
{
(*hhEmu->emu_getcurpos)(hhEmu, &pstPRI->sv_row, &pstPRI->sv_col);
pstPRI->sv_state = hhEmu->iCurAttrState;
pstPRI->sv_attr = hhEmu->attrState[hhEmu->iCurAttrState];
vt_charset_save(hhEmu);
pstPRI->sv_AWM = hhEmu->mode_AWM;
pstPRI->sv_DECOM = hhEmu->mode_DECOM;
pstPRI->sv_protectmode = hhEmu->mode_protect;
pstPRI->fAttrsSaved = TRUE;
}
else if (sel == ETEXT('8')) /* restore cursor and attr. */
{
(*hhEmu->emu_setcurpos)(hhEmu, pstPRI->sv_row, pstPRI->sv_col);
//if (pstPRI->sv_col == hhEmu->emu_maxcol)
// hhEmu->emu_curcol = pstPRI->sv_col; /* in order to wrap on next char */
if (pstPRI->fAttrsSaved)
{
hhEmu->iCurAttrState = pstPRI->sv_state;
hhEmu->attrState[hhEmu->iCurAttrState] = pstPRI->sv_attr;
hhEmu->emu_charattr = hhEmu->attrState[hhEmu->iCurAttrState];
}
vt_charset_restore(hhEmu);
hhEmu->mode_AWM = pstPRI->sv_AWM;
hhEmu->mode_DECOM = pstPRI->sv_DECOM;
hhEmu->mode_protect = pstPRI->sv_protectmode;
}
else /* clear saved conditions */
{
pstPRI->sv_row = pstPRI->sv_col = 0;
pstPRI->sv_state = hhEmu->iCurAttrState;
pstPRI->sv_AWM = pstPRI->sv_DECOM = RESET;
pstPRI->sv_protectmode = FALSE;
pstPRI->fAttrsSaved = FALSE;
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt100_answerback
*
* DESCRIPTION:
* Sends the answerback message defined on the menus.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt100_answerback(const HHEMU hhEmu)
{
int fOldValue;
TCHAR *sp;
ECHAR *pech = NULL;
sp = hhEmu->acAnswerback;
// If there is nothing to send, there is nothing to send
if (StrCharGetStrLength(sp) == 0)
return;
pech = malloc((unsigned int)StrCharGetByteCount(sp));
if (pech == NULL)
{
assert(FALSE);
return;
}
CnvrtMBCStoECHAR(pech, StrCharGetByteCount(sp), sp, StrCharGetByteCount(sp));
/* to not get recursive answerback's in half duplex */
fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
emuSendString(hhEmu, pech, (int)StrCharGetEcharByteCount(pech));
free(pech);
pech = NULL;
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt100_hostreset
*
* DESCRIPTION:
* Calls vt100_reset() when told to reset by the host.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt100_hostreset(const HHEMU hhEmu)
{
vt100_reset(hhEmu, TRUE);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt100_reset
*
* DESCRIPTION:
* Resets the emulator.
*
* ARGUMENTS:
* host_request -- TRUE when told to reset by the host.
*
* RETURNS:
* nothing
*/
int vt100_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_DECPEX = hhEmu->mode_DECSCNM = hhEmu->mode_25enab =
hhEmu->mode_protect = hhEmu->mode_block =
hhEmu->mode_local = RESET;
hhEmu->mode_SRM = hhEmu->mode_DECTCEM = SET;
hhEmu->mode_AWM = hhEmu->stUserSettings.fWrapLines;
vt_charset_init(hhEmu);
if (host_request)
{
ANSI_Pn_Clr(hhEmu);
ANSI_SGR(hhEmu);
ANSI_RIS(hhEmu);
}
hhEmu->emu_code = ETEXT('>');
vt_alt_kpmode(hhEmu);
if (hhEmu->stUserSettings.nEmuId == EMU_ANSI ||
hhEmu->stUserSettings.nEmuId == EMU_AUTO)
hhEmu->emu_kbdin = ansi_kbdin;
else
hhEmu->emu_kbdin = vt100_kbdin;
hhEmu->mode_AWM = RESET;
hhEmu->stUserSettings.fWrapLines = RESET;
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt100_report
*
* DESCRIPTION:
* Sends the current terminal parameters specified by the DECREQTPARM.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt100_report(const HHEMU hhEmu)
{
int sol, i = 0, xspeed = 0;
TCHAR str[20];
TCHAR tempstr[4];
ECHAR ech[20];
int fOldValue;
TCHAR *sp;
long lBaud;
int nDataBits, nParity;
HCOM hCom;
static int baudrates[] = {50, 75, 110, 135, 150, 200, 300, 600, 1200,
1800, 2000, 2400, 2600, 4800, 9600, 19200};
sol = hhEmu->num_param[0];
if (sol != 0 && sol != 1)
return;
wsprintf(str, TEXT("\x01B[%s;"),
sol == 0 ? (LPTSTR)TEXT("2") : (LPTSTR)TEXT("3"));
hCom = sessQueryComHdl(hhEmu->hSession);
ComGetBaud(hCom, &lBaud);
ComGetDataBits(hCom, &nDataBits);
ComGetParity(hCom, &nParity);
// Parity
//
if (nParity == 0) // None
StrCharCat(str, TEXT("1;"));
else if (nParity == 1) // Odd
StrCharCat(str, TEXT("4;"));
else // Even
StrCharCat(str, TEXT("5;"));
// Data bits
//
nDataBits == 8 ? StrCharCat(str, TEXT("1;")) : StrCharCat(str, TEXT("2;"));
while (xspeed < 120)
{
if ((long)baudrates[i] >= lBaud)
break;
i++;
xspeed += 8;
}
// Recieving speed
//
wsprintf(tempstr, "%d", xspeed);
StrCharCat(str, tempstr);
// Sending speed
//
StrCharCat(str, TEXT(";"));
StrCharCat(str, tempstr);
// Bit rate multiplier ; Flags
//
StrCharCat(str, TEXT(";1;0x"));
sp = str;
CnvrtMBCStoECHAR(ech, sizeof(ech), sp, StrCharGetByteCount(sp));
/* to not get recursive vt100_report's if half duplex */
fOldValue = CLoopGetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), FALSE);
emuSendString(hhEmu, ech, (int)StrCharGetEcharByteCount(ech));
CLoopSetLocalEcho(sessQueryCLoopHdl(hhEmu->hSession), fOldValue);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt100_kbdin
*
* DESCRIPTION:
* Processes local keyboard keys for the VT100 emulator.
* Note: mode_DECKPAM is TRUE or SET when in DEC KeyPad Aplication Mode.
* Removed key processing 1/3/92. Will replace with something resonable
* later - mrw.
*
* ARGUMENTS:
* key -- key to process
*
* RETURNS:
* nothing
*/
int vt100_kbdin(const HHEMU hhEmu, int key, const int fTest)
{
int index = 0;
/* -------------- 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;
}
/* -------------- Mapped PF1-PF4 keys ------------- */
#if 0 // mrw:11/3/95 - removed because we can't control num-lock
// in Win95
else if (hhEmu->stUserSettings.fMapPFkeys &&
(index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl4)) != -1)
{
if (!fTest)
emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl4);
}
#endif
/* -------------- Cursor Key Mode ------------- */
else if (hhEmu->mode_DECCKM == SET &&
(index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl3)) != -1)
{
if (!fTest)
emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl3);
}
/* -------------- Keypad Application Mode ------------- */
else if (hhEmu->mode_DECKPAM &&
(index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl2)) != -1)
{
if (!fTest)
emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl2);
}
/* -------------- Normal keys ------------- */
else if ((index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl)) != -1)
{
if (!fTest)
emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl);
}
else
{
index = std_kbdin(hhEmu, key, fTest);
}
return index;
}
#if FALSE // Never used in HyperTerminal.
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* fakevt_kbdin
*
* DESCRIPTION:
* Processes local keyboard keys for the WANG, IBM3278 & RENX3278 emulators.
*
* ARGUMENTS:
* key -- key to process
*
* RETURNS:
* nothing
*/
int fakevt_kbdin(const HHEMU hhEmu, int key, const int fTest)
{
int index;
/* -------------- 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;
}
if ((index = emuKbdKeyLookup(hhEmu, key, &hhEmu->stEmuKeyTbl)) != -1)
{
if (!fTest)
emuSendKeyString(hhEmu, index, &hhEmu->stEmuKeyTbl);
}
else
{
index = std_kbdin(hhEmu, key, fTest);
}
return index;
}
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* vt100PrintCommands
*
* DESCRIPTION:
* Processes VT100 printing commands.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void vt100PrintCommands(const HHEMU hhEmu)
{
int line;
int from;
int to;
ECHAR sel;
ECHAR aechBuf[10];
sel = (ECHAR)hhEmu->selector[0];
switch (sel)
{
// Auto print on.
//
case ETEXT(0xF5):
hhEmu->print_echo = TRUE;
printSetStatus(hhEmu->hPrintEcho, TRUE);
break;
// Auto print off.
//
case ETEXT(0xF4):
hhEmu->print_echo = FALSE;
printSetStatus(hhEmu->hPrintEcho, FALSE);
printEchoClose(hhEmu->hPrintEcho);
break;
// Print screen.
//
case ETEXT(0x00):
if (hhEmu->mode_DECPEX == RESET)
from = hhEmu->top_margin, to = hhEmu->bottom_margin;
else
from = 0, to = EMU_DEFAULT_MAXROW;
for (line = from; line <= to; ++line)
printEchoLine(hhEmu->hPrintHost,
hhEmu->emu_apText[row_index(hhEmu, line)],
emuRowLen(hhEmu, row_index(hhEmu, line)));
if (hhEmu->mode_DECPFF == SET) /* print form feed */
{
CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("0x0C"),
StrCharGetByteCount(TEXT("0x0C")));
printEchoLine(hhEmu->hPrintHost, aechBuf, sizeof(ECHAR));
}
break;
// Print Cursor line.
//
case ETEXT(0xF1):
printEchoLine(hhEmu->hPrintEcho,
hhEmu->emu_apText[row_index(hhEmu,
hhEmu->emu_currow)],
emuRowLen(hhEmu,
row_index(hhEmu, hhEmu->emu_currow)));
break;
// Enter printer controller mode. State is hard coded for now...
// Bad news.
//
case ETEXT(0x05):
hhEmu->state = 6;
printSetStatus(hhEmu->hPrintHost, TRUE);
break;
// Exit printer controller mode. This is seen when not in
// controller mode.
//
case ETEXT(0x04):
break;
default:
break;
}
}
void vt100_prnc(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
ECHAR aechBuf[10];
size_t size;
*pstPRI->pntr++ = hhEmu->emu_code;
*pstPRI->pntr = 0;
++pstPRI->len_s;
CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\033[4i"),
StrCharGetByteCount(TEXT("\033[4i")));
size = (size_t)StrCharGetByteCount(TEXT("\033[4i"));
if ((pstPRI->len_s >= 4) && (memcmp(pstPRI->pntr - 4, aechBuf, size) == 0))
{
/* received termination string, wrap it up */
#if defined(INCL_PRINT_PASSTHROUGH)
if( !hhEmu->stUserSettings.fPrintRaw)
{
printEchoRaw(hhEmu->hPrintHost, pstPRI->storage, pstPRI->len_s - ((*(pstPRI->pntr - 3) == (TCHAR)TEXT('\233')) ? 3 : 4));
}
else
#endif
{
emuPrintChars(hhEmu, pstPRI->storage, pstPRI->len_s - ((*(pstPRI->pntr - 3) == (TCHAR)TEXT('\233')) ? 3 : 4));
printEchoChar(hhEmu->hPrintHost, ETEXT('\n'));
}
pstPRI->pntr = pstPRI->storage;
pstPRI->len_s = 0;
hhEmu->state = 0; /* drop out of this routine */
// Finish-up print job
DbgOutStr("print-control off\r\n", 0, 0, 0, 0, 0);
printEchoClose(hhEmu->hPrintHost);
return;
}
/* haven't received termination sequence yet, is storage filled? */
if (pstPRI->len_s >= (int)(sizeof(pstPRI->storage) - 1))
{
/* copy most of string to print buffer */
#if defined(INCL_PRINT_PASSTHROUGH)
if( !hhEmu->stUserSettings.fPrintRaw )
{
printEchoRaw(hhEmu->hPrintHost, pstPRI->storage, pstPRI->len_s - 4);
}
else
#endif
{
emuPrintChars(hhEmu, pstPRI->storage, pstPRI->len_s - 4);\
}
/* move end of string to beginning of storage */
memmove(pstPRI->storage, &pstPRI->storage[pstPRI->len_s - 4], 4 * sizeof(ECHAR));
pstPRI->pntr = pstPRI->storage + 4;
pstPRI->len_s = 4;
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*/
void emuSetDoubleAttr(const HHEMU hhEmu)
{
switch(hhEmu->emu_code)
{
// Double width, double height, top half.
//
case '3':
emuSetDoubleAttrRow(hhEmu, DBL_WIDE_HI);
break;
// Double width double height, bottom half.
//
case '4':
emuSetDoubleAttrRow(hhEmu, DBL_WIDE_LO);
break;
// Single width single height.
//
case '5':
emuSetSingleAttrRow(hhEmu);
break;
// Double width, single height.
//
case '6':
emuSetDoubleAttrRow(hhEmu, DBL_WIDE_SINGLE_HEIGHT);
break;
default:
break;
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*/
void emuSetSingleAttrRow(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int iOldRow,
iOldCol,
iImgRow;
// Determine the image row.
//
iImgRow = row_index(hhEmu, hhEmu->emu_currow);
// If the current line attribute is the same as the one we're
// being asked to change to, get out-a-town.
//
if (pstPRI->aiLineAttr[iImgRow] == NO_LINE_ATTR)
return;
// Get the current cursor position.
//
std_getcurpos(hhEmu, &iOldRow, &iOldCol);
// Convert the current row.
//
emuFromDblToSingle(hhEmu);
// Update the line.
//
updateLine(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->emu_currow,
hhEmu->emu_currow);
// Put the cursor back to where it was, or at the new rightmost
// margin, whichever is less.
//
iOldCol = iOldCol / 2;
iOldCol = min(iOldCol, hhEmu->emu_maxcol);
std_setcurpos(hhEmu, iOldRow, iOldCol);
// Finally, update this rows line attribute value.
//
pstPRI->aiLineAttr[iImgRow] = NO_LINE_ATTR;
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*/
void emuSetDoubleAttrRow(const HHEMU hhEmu, const int iLineAttr)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int iChar,
iImgRow,
iOldRow,
iOldCol,
iUpperAttr,
iLowerAttr;
// Determine the image row.
//
iImgRow = row_index(hhEmu, hhEmu->emu_currow);
// If the current line attribute is the same as the one we're
// being asked to change to, get out-a-town.
//
if (pstPRI->aiLineAttr[iImgRow] == iLineAttr)
return;
// Get the current cursor position.
//
std_getcurpos(hhEmu, &iOldRow, &iOldCol);
// If the current line attribute is anything but NO_LINE_ATTR, call
// a routine that will first put the row back into that state. That
// is, this routine converts FROM a standard line INTO a double wide
// line.
//
if (pstPRI->aiLineAttr[iImgRow] != NO_LINE_ATTR)
{
emuFromDblToSingle(hhEmu);
iOldCol = iOldCol / 2;
}
// Start a shell game!
//
iChar = (hhEmu->emu_maxcol+1) / 2;
// Remember that both of the following values will be zero in the
// case of processing a DBL_WIDE_SINGLE_HEIGHT request.
//
iUpperAttr = (iLineAttr == DBL_WIDE_HI) ? 1 : 0;
iLowerAttr = (iLineAttr == DBL_WIDE_LO) ? 1 : 0;
while (iChar >= 0)
{
hhEmu->emu_apText[iImgRow][(iChar * 2) + 1] = hhEmu->emu_apText[iImgRow][iChar];
hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblwirt = 1;
hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblwilf = 0;
hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblhihi = (unsigned)iUpperAttr;
hhEmu->emu_apAttr[iImgRow][(iChar * 2) + 1].dblhilo = (unsigned)iLowerAttr;
hhEmu->emu_apText[iImgRow][(iChar * 2)] = hhEmu->emu_apText[iImgRow][iChar];
hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblwirt = 0;
hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblwilf = 1;
hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblhihi = (unsigned)iUpperAttr;
hhEmu->emu_apAttr[iImgRow][(iChar * 2)].dblhilo = (unsigned)iLowerAttr;
iChar--;
}
// Null terminate the new text image.
//
hhEmu->emu_apText[iImgRow][hhEmu->emu_maxcol + 1] = ETEXT('\0');
// Update the line.
//
updateLine(sessQueryUpdateHdl(hhEmu->hSession),
hhEmu->emu_currow,
hhEmu->emu_currow);
// Put the cursor back to where it was, or at the new rightmost
// margin, whichever is less.
//
iOldCol = iOldCol * 2;
iOldCol = min(iOldCol, hhEmu->emu_maxcol);
std_setcurpos(hhEmu, iOldRow, iOldCol);
// Finally, update this rows line attribute value.
//
pstPRI->aiLineAttr[iImgRow] = iLineAttr;
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* emuFromDblToSingle
*
* DESCRIPTION:
* Note that this is a utility function and does not update the emulator
* image. The calling function should do this.
*
* ARGUMENTS:
*
* RETURNS:
*
*/
void emuFromDblToSingle(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
register int i;
int iSource,
iDest,
iLastCol,
iImgRow;
// Determine the image row.
//
iImgRow = row_index(hhEmu, hhEmu->emu_currow);
// If the current line attribute is the same as the one we're
// being asked to change to, get out-a-town.
//
if (pstPRI->aiLineAttr[iImgRow] == NO_LINE_ATTR)
return;
// A new shell game.
//
iSource = 0;
iDest = 0;
iLastCol = (hhEmu->emu_maxcol+1) / 2;
// TODO: JCM - in two location below, the text buffer is set to
// spaces, instead of nulls. Figure out why this is the case. We
// should be able to set these to nulls.
while (iSource <= hhEmu->emu_maxcol)
{
if (hhEmu->emu_apText[iImgRow][iSource] == ETEXT('\0')) // TODO 1:
hhEmu->emu_apText[iImgRow][iDest] = ETEXT(' ');
else
hhEmu->emu_apText[iImgRow][iDest] =
hhEmu->emu_apText[iImgRow][iSource];
hhEmu->emu_apAttr[iImgRow][iDest].dblwirt = 0;
hhEmu->emu_apAttr[iImgRow][iDest].dblwilf = 0;
hhEmu->emu_apAttr[iImgRow][iDest].dblhihi = 0;
hhEmu->emu_apAttr[iImgRow][iDest].dblhilo = 0;
iSource += 2;
iDest += 1;
}
for (i = iLastCol; i < MAX_EMUCOLS ; ++i)
{
hhEmu->emu_apText[iImgRow][i] = ETEXT(' '); // TODO 2:
hhEmu->emu_apAttr[iImgRow][i] = hhEmu->emu_clearattr;
/*
hhEmu->emu_apAttr[iImgRow][i].dblwirt = 0;
hhEmu->emu_apAttr[iImgRow][i].dblwilf = 0;
hhEmu->emu_apAttr[iImgRow][i].dblhihi = 0;
hhEmu->emu_apAttr[iImgRow][i].dblhilo = 0;
*/
}
pstPRI->aiLineAttr[iImgRow] = NO_LINE_ATTR;
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
*
* DESCRIPTION:
*
* ARGUMENTS:
*
* RETURNS:
*
*/
void emuDecTab(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int col;
col = hhEmu->emu_curcol;
while (col <= hhEmu->emu_maxcol)
{
if (hhEmu->tab_stop[++col])
{
break;
}
}
if (pstPRI->aiLineAttr[hhEmu->emu_imgrow] != NO_LINE_ATTR)
col = (col * 2) - 1;
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, col);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecCUF
*
* DESCRIPTION:
* Moves the cursor forward the specified number of characters, but stops
* at the last character in the current line.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecCUF(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int nchars, col;
nchars = hhEmu->num_param[hhEmu->num_param_cnt];
if (nchars < 1)
nchars = 1;
if (pstPRI->aiLineAttr[hhEmu->emu_imgrow])
nchars = (nchars * 2);
col = hhEmu->emu_curcol;
col += nchars;
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, col);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecCUP
*
* DESCRIPTION:
* Positions the cursor at the specified row and column. The row & column
* numbering start at 1. If origin mode is on, the positioning is relative
* to the home of the scrolling region.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecCUP(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int row, col;
row = hhEmu->num_param[0];
col = hhEmu->num_param_cnt > 0 ? hhEmu->num_param[1] : 0;
if (pstPRI->aiLineAttr[row_index(hhEmu, row)] != NO_LINE_ATTR)
col = (col * 2) - 1;
if (row <= 1)
row = 1;
if (col <= 1)
col = 1;
if (hhEmu->mode_DECOM) /* VT100 Origin mode - position rel to margin */
{
row += hhEmu->top_margin;
if (row > hhEmu->bottom_margin + 1)
row = hhEmu->bottom_margin + 1;
}
else /* Position is one-based from upper left */
{
if (row > hhEmu->emu_maxrow + 1)
row = hhEmu->emu_maxrow + 1;
}
if (col > hhEmu->emu_maxcol + 1)
col = hhEmu->emu_maxcol + 1;
(*hhEmu->emu_setcurpos)(hhEmu, row - 1, col - 1); /* ANSI is one-based, HA zero-based */
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecCUB
*
* DESCRIPTION: Moves the cursor backwards (to the left) the specified number
* of characters, but stops at the 1st character in the current
* line. The vt emus need a special function to handle the
* virtual column beyond the edge of the screen.
*
* ARGUMENTS: none
*
* RETURNS: nothing
*/
void emuDecCUB(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int nchars;
nchars = hhEmu->num_param[hhEmu->num_param_cnt];
if (nchars < 1)
nchars = 1;
if (pstPRI->aiLineAttr[hhEmu->emu_imgrow])
nchars = (nchars * 2);
(*hhEmu->emu_setcurpos)(hhEmu,
hhEmu->emu_currow,
hhEmu->emu_curcol - nchars);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecED
*
* DESCRIPTION:
* Erases some or all of the virtual screen image and corresponding
* real screen.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecED(const HHEMU hhEmu)
{
int selector = hhEmu->selector[0];
switch (selector)
{
case 0: /* cursor to end of screen */
case 0x0F:
case 0xF0:
(*hhEmu->emu_clearscreen)(hhEmu, 0);
break;
case 1: /* start of screen to cursor */
case 0xF1:
(*hhEmu->emu_clearscreen)(hhEmu, 1);
break;
case 2: /* Entire screen */
case 0xF2:
(*hhEmu->emu_clearscreen)(hhEmu, 2);
break;
default:
commanderror(hhEmu);
break;
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecUnload
*
* DESCRIPTION:
* Unloads current emulator by freeing used memory.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuVT100Unload(const HHEMU hhEmu)
{
PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
assert(hhEmu);
if (pstPRI)
{
if (pstPRI->aiLineAttr)
{
free(pstPRI->aiLineAttr);
pstPRI->aiLineAttr = 0;
}
free(hhEmu->pvPrivate);
hhEmu->pvPrivate = 0;
}
//
// Make sure to free the key tables that were created when the emulator
// was loaded, otherwise there is a memory leak. REV: 05/09/2001
//
emuKeyTableFree(&hhEmu->stEmuKeyTbl);
emuKeyTableFree(&hhEmu->stEmuKeyTbl2);
emuKeyTableFree(&hhEmu->stEmuKeyTbl3);
emuKeyTableFree(&hhEmu->stEmuKeyTbl4);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecIND
*
* DESCRIPTION:
* Moves cursor down 1 line and scrolls 1 line if necessary. IND stands
* for index.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecIND(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int fSourceIsDbl, fDestIsDbl;
int iCol;
// If we're at the bottom line, scroll.
//
if (hhEmu->emu_currow == hhEmu->bottom_margin)
{
(*hhEmu->emu_scroll)(hhEmu, 1, TRUE);
return;
}
fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
? FALSE : TRUE;
fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow + 1)] == NO_LINE_ATTR)
? FALSE : TRUE;
iCol = hhEmu->emu_curcol;
// If both source and dest are the same, regardless of size, go
// ahead and make the move. It only matters if they're different.
//
if (fSourceIsDbl == fDestIsDbl) // Both the same
iCol = iCol;
else if (fSourceIsDbl) // Source is double, dest is single.
iCol = iCol / 2;
else // Source is singel, dest is double.
iCol = iCol * 2;
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow + 1, iCol);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecRI
*
* DESCRIPTION:
* Moves cursor up 1 line and scrolls 1 line if necessary.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecRI(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int fSourceIsDbl, fDestIsDbl;
int iCol;
// If we're at the bottom line, scroll.
//
if (hhEmu->emu_currow == hhEmu->top_margin)
{
(*hhEmu->emu_scroll)(hhEmu, 1, FALSE);
return;
}
fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
? FALSE : TRUE;
fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow - 1)] == NO_LINE_ATTR)
? FALSE : TRUE;
iCol = hhEmu->emu_curcol;
// If both source and dest are the same, regardless of size, go
// ahead and make the move. It only matters if they're different.
//
if (fSourceIsDbl == fDestIsDbl) // Both the same
iCol = iCol;
else if (fSourceIsDbl) // Source is double, dest is single.
iCol = iCol / 2;
else // Source is singel, dest is double.
iCol = iCol * 2;
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow - 1, iCol);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecCUU
*
* DESCRIPTION: Moves the cursor up the specified number of lines, but stops
* at the top of the scrolling region. The column is constant.
* If above the scrolling region, it stops at the top of the
* screen.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecCUU(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int nlines,
row,
fSourceIsDbl,
fDestIsDbl,
iCol;
nlines = hhEmu->num_param[hhEmu->num_param_cnt];
if (nlines < 1)
nlines = 1;
row = hhEmu->emu_currow;
row -= nlines;
fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
? FALSE : TRUE;
fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow - nlines)] == NO_LINE_ATTR)
? FALSE : TRUE;
iCol = hhEmu->emu_curcol;
// The following code adjusts the column value for double wide
// characters.
//
if (fSourceIsDbl == fDestIsDbl) // Both the same
iCol = iCol;
else if (fSourceIsDbl) // Source is double, dest is single.
iCol = iCol / 2;
else // Source is singel, dest is double.
iCol = iCol * 2;
if (row < hhEmu->top_margin && (hhEmu->emu_currow >= hhEmu->top_margin || hhEmu->emu_currow < 0))
row = hhEmu->top_margin;
(*hhEmu->emu_setcurpos)(hhEmu, row, iCol);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecCUD
*
* DESCRIPTION: Moves the cursor down the specified number of lines, but stops
* at the bottom of the scrolling region. The column is constant.
* If below the scrolling region, it stops at the bottom of the
* screen.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void emuDecCUD(const HHEMU hhEmu)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int nlines,
row,
fSourceIsDbl,
fDestIsDbl,
iCol;
nlines = hhEmu->num_param[hhEmu->num_param_cnt];
if (nlines < 1)
nlines = 1;
row = hhEmu->emu_currow;
row += nlines;
fSourceIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)] == NO_LINE_ATTR)
? FALSE : TRUE;
fDestIsDbl = (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow + nlines)] == NO_LINE_ATTR)
? FALSE : TRUE;
iCol = hhEmu->emu_curcol;
// The following code adjusts the column value for double wide
// characters.
//
if (fSourceIsDbl == fDestIsDbl) // Both the same
iCol = iCol;
else if (fSourceIsDbl) // Source is double, dest is single.
iCol = iCol / 2;
else // Source is singel, dest is double.
iCol = iCol * 2;
if (row > hhEmu->bottom_margin &&
(hhEmu->emu_currow <= hhEmu->bottom_margin || hhEmu->emu_currow > hhEmu->emu_maxrow))
row = hhEmu->bottom_margin;
(*hhEmu->emu_setcurpos)(hhEmu, row, iCol);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecSetCurPos
*
* DESCRIPTION:
* Moves the cursor to the specified position on the virtual screen.
* If the cursor is beyond the end of existing text, the virtual screen
* line is filled out with spaces. If the cursor is beyond the edges of
* the video display, the video cursor is placed as close as possible
* to the desired position as the cursor display is changed.
*
* ARGUMENTS:
*
* RETURNS:
* nothing
*/
void emuDecSetCurPos(const HHEMU hhEmu, const int iRow, const int iCol)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int iTempCol;
int i;
// If we move the cursor, we need to clear the pstPRI->fDecHoldFlag;
//
pstPRI->fDecColHold = FALSE;
hhEmu->emu_currow = max(min(iRow, hhEmu->emu_maxrow), 0);
hhEmu->emu_curcol = max(min(iCol, hhEmu->emu_maxcol), 0);
iTempCol = hhEmu->emu_curcol;
// If the row is a double wide character row, don't ever let the
// cursor land on an odd column number. If it's there now, back
// it up one.
//
i = row_index(hhEmu, hhEmu->emu_currow);
if (pstPRI->aiLineAttr[i])
{
if (iTempCol % 2 == 1)
{
iTempCol -= 1;
}
}
updateCursorPos(sessQueryUpdateHdl(hhEmu->hSession), iRow, iTempCol);
hhEmu->emu_imgrow = row_index(hhEmu, hhEmu->emu_currow);
return;
#if 0
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
int iTempCol;
hhEmu->emu_currow = max(min(iRow, hhEmu->emu_maxrow), 0);
hhEmu->emu_curcol = max(min(iCol, hhEmu->emu_maxcol), 0);
iTempCol = hhEmu->emu_curcol;
// Do range checking for DEC emulation. This prevents the cursor
// from being displayed in the 81st position, which is a valid
// internal location, but is not a valid display column.
//
if (hhEmu->emu_curcol == hhEmu->emu_maxcol &&
(hhEmu->stUserSettings.nEmuId == EMU_VT100 ||
hhEmu->stUserSettings.nEmuId == EMU_VT100J))
{
iTempCol -= 1;
}
// If the row is a double wide character row, don't ever let the
// cursor land on an odd column number. If it's there now, back
// it up one.
//
if (pstPRI->aiLineAttr[row_index(hhEmu, hhEmu->emu_currow)])
{
if (iTempCol % 2 == 1)
{
iTempCol -= 1;
}
}
updateCursorPos(sessQueryUpdateHdl(hhEmu->hSession), iRow, iTempCol);
hhEmu->emu_imgrow = row_index(hhEmu, hhEmu->emu_currow);
return;
#endif
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* emuDecClearScreen
*
* DESCRIPTION:
* Erases some or all of the virtual screen image.
*
* ARGUMENTS:
* select -- 0 to erase from cursor to end of screen
* -- 1 to erase from start of screen to cursor
* -- 2 to erase entire screen
*
* RETURNS:
* nothing
*/
void emuDecClearScreen(const HHEMU hhEmu, const int nClearSelect)
{
const PSTDECPRIVATE pstPRI = (PSTDECPRIVATE)hhEmu->pvPrivate;
ECHAR aechBuf[10];
register int r;
int trow, tcol;
PSTATTR pstAttr;
BOOL fSave;
trow = hhEmu->emu_currow;
tcol = hhEmu->emu_curcol;
switch (nClearSelect)
{
/* cursor to end of screen */
case 0:
fSave = (hhEmu->emu_currow == 0 &&
hhEmu->emu_curcol == 0) ? TRUE : FALSE;
for (r = hhEmu->emu_currow + (fSave ? 0 : 1) ; r < MAX_EMUROWS; ++r)
{
if (fSave)
{
backscrlAdd(sessQueryBackscrlHdl(hhEmu->hSession),
hhEmu->emu_apText[row_index(hhEmu, r)],
hhEmu->emu_maxcol+1);
CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
CF_CAP_SCREENS,
hhEmu->emu_apText[row_index(hhEmu, r)],
emuRowLen(hhEmu, row_index(hhEmu, r)));
printEchoScreen(hhEmu->hPrintEcho,
hhEmu->emu_apText[row_index(hhEmu, r)],
emuRowLen(hhEmu, row_index(hhEmu, r)));
CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
StrCharGetByteCount(TEXT("\r\n")));
printEchoScreen(hhEmu->hPrintEcho,
aechBuf,
sizeof(ECHAR) * 2);
}
clear_imgrow(hhEmu, r);
pstPRI->aiLineAttr[row_index(hhEmu, r)] = NO_LINE_ATTR;
}
// Clear the partial row now.
//
ECHAR_Fill(hhEmu->emu_apText[row_index(hhEmu, hhEmu->emu_currow)] +
hhEmu->emu_curcol,
EMU_BLANK_CHAR,
(size_t)(MAX_EMUCOLS - hhEmu->emu_curcol + 1));
if (hhEmu->emu_curcol <= hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = hhEmu->emu_curcol - 1;
pstAttr = hhEmu->emu_apAttr[row_index(hhEmu, hhEmu->emu_currow)];
for (r = hhEmu->emu_curcol ; r < MAX_EMUCOLS ; ++r)
pstAttr[r] = hhEmu->emu_clearattr;
// Tell the video image what to do. Use the emuDispRgnScrollUp() call
// instead of RgnClear so edges of terminal get painted if
// clear attribute changes.
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;
/* start of screen to cursor */
case 1:
for (r = 0; r < hhEmu->emu_currow; ++r)
{
clear_imgrow(hhEmu, r);
pstPRI->aiLineAttr[row_index(hhEmu, r)] = NO_LINE_ATTR;
}
ECHAR_Fill(hhEmu->emu_apText[row_index(hhEmu, hhEmu->emu_currow)],
EMU_BLANK_CHAR,
(size_t)(hhEmu->emu_curcol + 1));
if (hhEmu->emu_curcol >= hhEmu->emu_aiEnd[hhEmu->emu_imgrow])
hhEmu->emu_aiEnd[hhEmu->emu_imgrow] = EMU_BLANK_LINE;
pstAttr = hhEmu->emu_apAttr[row_index(hhEmu, hhEmu->emu_currow)];
for (r = 0 ; r <= hhEmu->emu_curcol ; ++r)
pstAttr[r] = hhEmu->emu_clearattr;
(*hhEmu->emu_setcurpos)(hhEmu, hhEmu->emu_currow, hhEmu->emu_curcol);
updateLine(sessQueryUpdateHdl(hhEmu->hSession), 0, hhEmu->emu_currow);
break;
/* Entire screen */
case 2:
for (r = 0; r < MAX_EMUROWS; ++r)
{
backscrlAdd(sessQueryBackscrlHdl(hhEmu->hSession),
hhEmu->emu_apText[row_index(hhEmu, r)],
hhEmu->emu_maxcol+1);
CaptureLine(sessQueryCaptureFileHdl(hhEmu->hSession),
CF_CAP_SCREENS,
hhEmu->emu_apText[row_index(hhEmu, r)],
emuRowLen(hhEmu, row_index(hhEmu, r)));
printEchoScreen(hhEmu->hPrintEcho,
hhEmu->emu_apText[row_index(hhEmu, r)],
emuRowLen(hhEmu, row_index(hhEmu, r)));
CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT("\r\n"),
StrCharGetByteCount(TEXT("\r\n")));
printEchoScreen(hhEmu->hPrintEcho,
aechBuf,
sizeof(ECHAR) * 2);
clear_imgrow(hhEmu, r);
pstPRI->aiLineAttr[r] = NO_LINE_ATTR;
}
updateScroll(sessQueryUpdateHdl(hhEmu->hSession),
0,
hhEmu->emu_maxrow,
hhEmu->emu_maxrow + 1,
hhEmu->emu_imgtop,
TRUE);
// 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);
}
/* end of vt100.c */