|
|
/* File: D:\WACKER\tdll\termutil.c (Created: 23-Dec-1993)
* * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 4 $ * $Date: 3/26/02 8:46a $ */ #include <windows.h>
#pragma hdrstop
//#define DEBUGSTR 1
#include <stdlib.h>
#include <limits.h>
#include "stdtyp.h"
#include "session.h"
#include "assert.h"
#include "timers.h"
#include "chars.h"
#include <emu\emu.h>
#include "term.h"
#include "term.hh"
#include "statusbr.h"
#include <term\res.h>
static int InMiddleofWideChar(ECHAR *pszRow, int iCol); //
// The following function is from code mofified slightly
// from MSDN for determining if you are currently running as a
// remote session (Terminal Service). REV: 10/03/2001
//
BOOL ValidateProductSuite ( LPSTR SuiteName );
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * termQuerySnapRect * * DESCRIPTION: * Returns the minimum rectangle that will encompass a full terminal. * * ARGUMENTS: * hhTerm - internal terminal handle. * prc - pointer to rect * * RETURNS: * void * */ void termQuerySnapRect(const HHTERM hhTerm, LPRECT prc) { prc->left = prc->top = 0;
prc->right = (hhTerm->iCols * hhTerm->xChar) + (2 * (hhTerm->xIndent + hhTerm->xBezel)) + (2 * GetSystemMetrics(SM_CXEDGE)) + GetSystemMetrics(SM_CXVSCROLL);
prc->bottom = ((hhTerm->iRows + 2) * hhTerm->yChar) + (2 * GetSystemMetrics(SM_CYEDGE)); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * MarkText * * DESCRIPTION: * Work horse routine that marks and unmarks text on the terminal screen. * It has two methods for marking, ABSOLUTE and XOR. ABSOLUTE sets the * range of cells given by ptBeg and ptEnd to the given setting (fMark) * while XOR will perform an exclusive or on the cell range. ABSOLUTE * is used to unmark cells mostly. * * ARGUMENTS: * HTERM hTerm - handle to a terminal * LPPOINT ptBeg - one end of the marking range * LPPOINT ptEnd - the other end of the marking range * BOOL fMark - new marking state of cells * SHORT fMarkingMethod - MARK_ABS or MARK_XOR * * * RETURNS: * VOID * */ void MarkText(const HHTERM hhTerm, const LPPOINT ptBeg, const LPPOINT ptEnd, const BOOL fMark, const int sMarkingMethod) { int iOffsetBeg, iOffsetEnd, sTermBeg, sTermEnd, i, j; RECT rc; long yBeg, yEnd;
//const int iMaxCells = hhTerm->iRows * TERM_COLS;
//
const int iMaxCells = MAX_EMUROWS * MAX_EMUCOLS;
//iOffsetBeg = ((ptBeg->y - 1) * TERM_COLS) + ptBeg->x;
//iOffsetEnd = ((ptEnd->y - 1) * TERM_COLS) + ptEnd->x;
//
iOffsetBeg = ((ptBeg->y - 1) * MAX_EMUCOLS) + ptBeg->x; iOffsetEnd = ((ptEnd->y - 1) * MAX_EMUCOLS) + ptEnd->x;
// Check if we moved enough to actually mark something.
if (iOffsetBeg == iOffsetEnd) return;
// Determine offsets for terminal area.
sTermBeg = min(max(iOffsetBeg, 0), iMaxCells); sTermEnd = min(max(iOffsetEnd, 0), iMaxCells);
// This routine use to reference the text and attribute buffers as
// a continous buffer. When switching over to pointer arrays, I
// introduced the [i/sCols][i%sCols] notation to keep from having
// to change the entire routine.
if (sTermBeg != sTermEnd) { //i = (min(sTermBeg, sTermEnd)
// + (hhTerm->iTopline * TERM_COLS)) % iMaxCells;
//
i = (min(sTermBeg, sTermEnd) + (hhTerm->iTopline * MAX_EMUCOLS)) % iMaxCells;
j = abs(sTermEnd - sTermBeg);
switch (sMarkingMethod) { case MARK_XOR: while (j-- > 0) { if (i >= iMaxCells) i = 0;
//hhTerm->fppstAttr[i/TERM_COLS][i%TERM_COLS].txtmrk
// ^= (unsigned)fMark;
//
hhTerm->fppstAttr[i/MAX_EMUCOLS][i%MAX_EMUCOLS].txtmrk ^= (unsigned)fMark;
i += 1; } break;
case MARK_ABS: while (j-- > 0) { if (i >= iMaxCells) i = 0;
//hhTerm->fppstAttr[i/TERM_COLS][i%TERM_COLS].txtmrk
// = (unsigned)fMark;
//
hhTerm->fppstAttr[i/MAX_EMUCOLS][i%MAX_EMUCOLS].txtmrk = (unsigned)fMark;
i += 1; } break;
default: assert(0); break; } }
TestForMarkingLock(hhTerm);
// Invalidate the rectangle covering the marked region
yBeg = min(ptBeg->y, ptEnd->y); yEnd = max(ptBeg->y, ptEnd->y);
rc.left = hhTerm->xIndent + (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel);
//rc.right = min((hhTerm->xChar * hhTerm->iCols) + hhTerm->xIndent +
// (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel), hhTerm->cx);
//
rc.right = min((hhTerm->xChar * MAX_EMUCOLS) + hhTerm->xIndent + (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel), hhTerm->cx); rc.top = (yBeg - hhTerm->iVScrlPos) * hhTerm->yChar; rc.bottom = (yEnd + 1 - hhTerm->iVScrlPos) * hhTerm->yChar;
InvalidateRect(hhTerm->hwnd, &rc, FALSE); return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * MarkTextAll * * DESCRIPTION: * Marks all of the text on the terminal screen and backscroll buffer. * * ARGUMENTS: * hhTerm - private terminal handle * * RETURNS: * void * */ void MarkTextAll(HHTERM hhTerm) { MarkText(hhTerm, &hhTerm->ptBeg, &hhTerm->ptEnd, FALSE, MARK_ABS);
hhTerm->ptBeg.x = 0; hhTerm->ptBeg.y = hhTerm->iVScrlMin;
//iEmuId = EmuQ(sessQueryEmuHdl(hhTerm->hSession)
hhTerm->ptEnd.x = hhTerm->iCols; hhTerm->ptEnd.y = hhTerm->iRows;
MarkText(hhTerm, &hhTerm->ptBeg, &hhTerm->ptEnd, TRUE, MARK_ABS); return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * UnmarkText * * DESCRIPTION: * Unmarks all text on the terminal screen * * ARGUMENTS: * hhTerm - private terminal handle * * RETURNS: * void * */ void UnmarkText(const HHTERM hhTerm) { MarkText(hhTerm, &hhTerm->ptBeg, &hhTerm->ptEnd, FALSE, MARK_ABS); hhTerm->ptBeg = hhTerm->ptEnd; TestForMarkingLock(hhTerm); return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * TestForMarkingLock * * DESCRIPTION: * Checks to seek if hTerm->fMarkingLock should be on or off. * * ARGUMENTS: * HTERM hTerm - handle to a terminal * * RETURNS: * VOID * */ void TestForMarkingLock(const HHTERM hhTerm) { hhTerm->fMarkingLock = (memcmp(&hhTerm->ptBeg, &hhTerm->ptEnd, sizeof(POINT)) == 0) ? FALSE : TRUE;
if (hhTerm->fMarkingLock) sessSetSuspend(hhTerm->hSession, SUSPEND_TERMINAL_MARKING);
else sessClearSuspend(hhTerm->hSession, SUSPEND_TERMINAL_MARKING);
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * PointInSelectionRange * * DESCRIPTION: * Tests if given point is within the range of the given beginning and * ending points. Note, pptBeg does not have to be less the pptEnd. * * ARGUMENTS: * const PPOINT ppt - point to test. * const PPOINT pptBeg - one end of the range. * const PPOINT pptEnd - other end of the range. * const int iCols - number of columns in current emulator. * * RETURNS: * TRUE if in range, else FALSE * */ BOOL PointInSelectionRange(const PPOINT ppt, const PPOINT pptBeg, const PPOINT pptEnd, const int iCols) { long l, lBeg, lEnd;
l = (ppt->y * iCols) + ppt->x; lBeg = (pptBeg->y * iCols) + pptBeg->x; lEnd = (pptEnd->y * iCols) + pptEnd->x;
if (l >= min(lBeg, lEnd) && l < max(lBeg, lEnd)) return TRUE;
return FALSE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * termTranslateKey * * DESCRIPTION: * Does the dirty work of translate accelator keys. * * ARGUMENTS: * HTERM hTerm - terminal handle. * HWND hwnd - terminal window handle. * USHORT usKey - key code from utilGetCharacter(). * * RETURNS: * TRUE if it processed char, else FALSE * */ BOOL termTranslateKey(const HHTERM hhTerm, const HWND hwnd, const KEY_T Key) { POINT ptTmp; INT x = 0; STEMUSET stEmuSet; BOOL fShiftKey, fScrlLk;
if (Key == 0) return TRUE;
fScrlLk = GetKeyState(VK_SCROLL) & 1; fShiftKey = (Key & SHIFT_KEY) ? TRUE : FALSE;
// Check to see if we use it.
switch (Key) { /* -------------- VK_HOME ------------- */
case VK_HOME | VIRTUAL_KEY: case VK_HOME | VIRTUAL_KEY | SHIFT_KEY: case VK_HOME | VIRTUAL_KEY | EXTENDED_KEY: case VK_HOME | VIRTUAL_KEY | EXTENDED_KEY | SHIFT_KEY: MoveSelectionCursor(hhTerm, hwnd, -hhTerm->iCols, 0, fShiftKey); break;
case VK_HOME | VIRTUAL_KEY | CTRL_KEY: case VK_HOME | VIRTUAL_KEY | CTRL_KEY | SHIFT_KEY: case VK_HOME | VIRTUAL_KEY | CTRL_KEY | EXTENDED_KEY: case VK_HOME | VIRTUAL_KEY | CTRL_KEY | EXTENDED_KEY | SHIFT_KEY: MoveSelectionCursor(hhTerm, hwnd, -hhTerm->iCols, hhTerm->iVScrlMin - hhTerm->iRows, fShiftKey); break;
case VK_HOME | VIRTUAL_KEY | ALT_KEY: case VK_HOME | VIRTUAL_KEY | ALT_KEY | SHIFT_KEY: case VK_HOME | VIRTUAL_KEY | ALT_KEY | SHIFT_KEY | CTRL_KEY: case VK_HOME | VIRTUAL_KEY | ALT_KEY | SHIFT_KEY | CTRL_KEY | EXTENDED_KEY: break;
/* -------------- VK_END ------------- */
case VK_END | VIRTUAL_KEY: case VK_END | VIRTUAL_KEY | SHIFT_KEY: case VK_END | VIRTUAL_KEY | EXTENDED_KEY: case VK_END | VIRTUAL_KEY | SHIFT_KEY | EXTENDED_KEY: MoveSelectionCursor(hhTerm, hwnd, hhTerm->iCols - hhTerm->ptEnd.x, 0, fShiftKey); break;
case VK_END | VIRTUAL_KEY | CTRL_KEY: case VK_END | VIRTUAL_KEY | CTRL_KEY | SHIFT_KEY: case VK_END | VIRTUAL_KEY | CTRL_KEY | EXTENDED_KEY: case VK_END | VIRTUAL_KEY | CTRL_KEY | SHIFT_KEY | EXTENDED_KEY: MoveSelectionCursor(hhTerm, hwnd, hhTerm->iCols, INT_MAX/2, fShiftKey); break;
/* -------------- VK_PRIOR & VK_NEXT ------------- */
case VK_PRIOR | VIRTUAL_KEY: case VK_NEXT | VIRTUAL_KEY: case VK_PRIOR | VIRTUAL_KEY | SHIFT_KEY: case VK_NEXT | VIRTUAL_KEY | SHIFT_KEY: case VK_PRIOR | VIRTUAL_KEY | EXTENDED_KEY: case VK_NEXT | VIRTUAL_KEY | EXTENDED_KEY: case VK_PRIOR | VIRTUAL_KEY | EXTENDED_KEY| SHIFT_KEY: case VK_NEXT | VIRTUAL_KEY | EXTENDED_KEY| SHIFT_KEY: ptTmp = hhTerm->ptEnd;
if (fShiftKey == 0) UnmarkText(hhTerm);
if (hhTerm->ptEnd.y < hhTerm->iVScrlPos || (hhTerm->ptEnd.y - hhTerm->iTermHite + 1) > hhTerm->iVScrlPos || !hhTerm->fLclCurOn) { x = 1; // means it is out of view.
}
SendMessage(hwnd, WM_VSCROLL, ((UCHAR)Key == VK_NEXT) ? SB_PAGEDOWN : SB_PAGEUP, 0);
if (x) { hhTerm->ptEnd.y = hhTerm->iVScrlPos;
if (hhTerm->fLclCurOn) SetLclCurPos(hhTerm, &hhTerm->ptEnd); }
else { if ((UCHAR)Key == VK_NEXT) { hhTerm->ptEnd.y += hhTerm->iTermHite; hhTerm->ptEnd.y = min(hhTerm->iRows, hhTerm->ptEnd.y); }
else { hhTerm->ptEnd.y -= hhTerm->iTermHite; hhTerm->ptEnd.y = max(hhTerm->iVScrlMin, hhTerm->ptEnd.y); }
if (hhTerm->fLclCurOn) SetLclCurPos(hhTerm, &hhTerm->ptEnd); }
if (!fShiftKey) hhTerm->ptBeg = hhTerm->ptEnd;
if (fShiftKey) MarkText(hhTerm, &ptTmp, &hhTerm->ptEnd, TRUE, MARK_XOR);
break;
case VK_PRIOR | VIRTUAL_KEY | CTRL_KEY: case VK_NEXT | VIRTUAL_KEY | CTRL_KEY: case VK_PRIOR | VIRTUAL_KEY | CTRL_KEY | EXTENDED_KEY: case VK_NEXT | VIRTUAL_KEY | CTRL_KEY | EXTENDED_KEY: UnmarkText(hhTerm);
SendMessage(hwnd, WM_HSCROLL, ((UCHAR)Key == VK_NEXT) ? SB_PAGEDOWN : SB_PAGEUP, 0);
break;
/* -------------- VK_UP ------------- */
case VK_UP | VIRTUAL_KEY: case VK_UP | VIRTUAL_KEY | SHIFT_KEY: case VK_UP | VIRTUAL_KEY | EXTENDED_KEY: case VK_UP | VIRTUAL_KEY | EXTENDED_KEY | SHIFT_KEY: MoveSelectionCursor(hhTerm, hwnd, 0, -1, fShiftKey); break;
/* -------------- VK_DOWN ------------- */
case VK_DOWN | VIRTUAL_KEY: case VK_DOWN | VIRTUAL_KEY | SHIFT_KEY: case VK_DOWN | VIRTUAL_KEY | EXTENDED_KEY: case VK_DOWN | VIRTUAL_KEY | EXTENDED_KEY | SHIFT_KEY: MoveSelectionCursor(hhTerm, hwnd, 0, 1, fShiftKey); break;
/* -------------- VK_LEFT ------------- */
case VK_LEFT | VIRTUAL_KEY: case VK_LEFT | VIRTUAL_KEY | SHIFT_KEY: case VK_LEFT | VIRTUAL_KEY | EXTENDED_KEY: case VK_LEFT | VIRTUAL_KEY | EXTENDED_KEY | SHIFT_KEY: MoveSelectionCursor(hhTerm, hwnd, -1, 0, fShiftKey); break;
/* -------------- VK_RIGHT ------------- */
case VK_RIGHT | VIRTUAL_KEY: case VK_RIGHT | VIRTUAL_KEY | SHIFT_KEY: case VK_RIGHT | VIRTUAL_KEY | EXTENDED_KEY: case VK_RIGHT | VIRTUAL_KEY | EXTENDED_KEY | SHIFT_KEY: MoveSelectionCursor(hhTerm, hwnd, 1, 0, fShiftKey); break;
/* -------------- VK_F4 ------------- */
case VK_F4 | CTRL_KEY | VIRTUAL_KEY: PostMessage(sessQueryHwnd(hhTerm->hSession), WM_CLOSE, 0, 0L); break;
/* -------------- VK_F8 ------------- */
case VK_F8 | VIRTUAL_KEY: if (fScrlLk || hhTerm->fMarkingLock) { hhTerm->fExtSelect = !hhTerm->fExtSelect; break; } return FALSE;
/* -------------- CTRL-C ------------- */
case 0x03: case VK_INSERT | VIRTUAL_KEY | CTRL_KEY: case VK_INSERT | VIRTUAL_KEY | CTRL_KEY | EXTENDED_KEY: if (fScrlLk || hhTerm->fMarkingLock) { PostMessage(sessQueryHwnd(hhTerm->hSession), WM_COMMAND, IDM_COPY, 0); break; }
return FALSE;
/* -------------- CTRL-V ------------- */
case 0x16: case VK_INSERT | VIRTUAL_KEY | SHIFT_KEY: case VK_INSERT | VIRTUAL_KEY | SHIFT_KEY | EXTENDED_KEY: if (emuQuerySettings(sessQueryEmuHdl(hhTerm->hSession), &stEmuSet) == 0 && stEmuSet.nTermKeys != EMU_KEYS_TERM) { PostMessage(sessQueryHwnd(hhTerm->hSession), WM_COMMAND, IDM_PASTE, 0);
break; }
return FALSE;
/* -------------- CTRL-X ------------- */ /* -------------- CTRL-Z ------------- */
case 0x18: case 0x1A: if (fScrlLk || hhTerm->fMarkingLock) return TRUE;
return FALSE;
/* -------------- Scroll Lock ------------- */
case VIRTUAL_KEY | VK_SCROLL: case VIRTUAL_KEY | SHIFT_KEY | VK_SCROLL: case VIRTUAL_KEY | ALT_KEY | VK_SCROLL: case VIRTUAL_KEY | ALT_KEY | SHIFT_KEY | VK_SCROLL: if (fScrlLk) sessSetSuspend(hhTerm->hSession, SUSPEND_SCRLCK); else sessClearSuspend(hhTerm->hSession, SUSPEND_SCRLCK);
PostMessage(sessQueryHwndStatusbar(hhTerm->hSession), SBR_NTFY_REFRESH, (WPARAM)SBR_SCRL_PART_NO, 0);
return TRUE;
/* -------------- Num Lock ------------- */
case VIRTUAL_KEY | EXTENDED_KEY | VK_NUMLOCK: case VIRTUAL_KEY | EXTENDED_KEY | SHIFT_KEY | VK_NUMLOCK: case VIRTUAL_KEY | EXTENDED_KEY | ALT_KEY | VK_NUMLOCK: case VIRTUAL_KEY | EXTENDED_KEY | ALT_KEY | SHIFT_KEY | VK_NUMLOCK: PostMessage(sessQueryHwndStatusbar(hhTerm->hSession), SBR_NTFY_REFRESH, (WPARAM)SBR_NUML_PART_NO, 0); return TRUE;
/* -------------- Caps Lock ------------- */
case VIRTUAL_KEY | VK_CAPITAL: case VIRTUAL_KEY | SHIFT_KEY | VK_CAPITAL: case VIRTUAL_KEY | ALT_KEY | VK_CAPITAL: case VIRTUAL_KEY | ALT_KEY | SHIFT_KEY | VK_CAPITAL: PostMessage(sessQueryHwndStatusbar(hhTerm->hSession), SBR_NTFY_REFRESH, (WPARAM)SBR_CAPL_PART_NO, 0); return TRUE;
/* -------------- Let it through based on scroll lock ------------- */
default: return fScrlLk; }
return TRUE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * MarkingTimerProc * * DESCRIPTION: * Multiplex timer callback routine used for text marking * * ARGUMENTS: * pvhWnd - terminal window. * lTime - contains time elapsed. * * RETURNS: * void * */ void CALLBACK MarkingTimerProc(void *pvhWnd, long lTime) { const HWND hwnd = (HWND)pvhWnd; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwnd, GWLP_USERDATA); MSG msg; POINT ptTemp;
if (hhTerm->fCapture == FALSE) return;
// This is TRUE if timer went off after we posted ourselves a message.
//
PeekMessage(&msg, hwnd, WM_TERM_SCRLMARK, WM_TERM_SCRLMARK, PM_REMOVE);
// Because mouse messages go in the system queue and don't get put in
// our application queue until its empty, we need to check.
//
if (PeekMessage(&msg, hwnd, WM_LBUTTONUP, WM_LBUTTONUP, PM_NOREMOVE) == TRUE) return;
// The scrolling routines set this whenever they actually perform
// a scroll. So we set it FALSE here. Then if any of the SendMessage()
// calls below actually scroll, we know to post a message back to
// ourselves to continue scrolling.
hhTerm->fScrolled = FALSE;
GetCursorPos(&ptTemp); MapWindowPoints(GetDesktopWindow(), hwnd, &ptTemp, 1);
/* -------------- We control the horizontal ------------- */
if (ptTemp.x > hhTerm->cx) SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, 0);
else if (ptTemp.x < 0) SendMessage(hwnd, WM_HSCROLL, SB_LINEUP, 0);
/* -------------- We control the vertical ------------- */
if (ptTemp.y > hhTerm->cy) SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
else if (ptTemp.y < 0) SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
// If we scrolled, post a message back to ourselves. Do this because
// the timer resolution is not short enough to produce a fast, smooth
// scrolling effect. Ideally, it would be better to drive this
// entirely from timer intervals, but its too slow compared to other
// apps.
if (hhTerm->fScrolled) { SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptTemp.x, ptTemp.y)); UpdateWindow(hwnd); //Sleep(10); // so we don't scroll too fast on fast machines.
PostMessage(hwnd, WM_TERM_SCRLMARK, 0, 0); }
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * termSetClrAttr * * DESCRIPTION: * Called as a result of the emulator notifying the terminal that * it's clear attribute has changed. This function calls the * appropriate emulator call to get the attribute and then * sets appropriate terminal variables. * * ARGUMENTS: * hhTerm - private terminal handle. * * RETURNS: * void * */ void termSetClrAttr(const HHTERM hhTerm) { HBRUSH hBrush; STATTR stAttr;
emuQueryClearAttr(sessQueryEmuHdl(hhTerm->hSession), &stAttr);
hhTerm->crTerm = hhTerm->pacrEmuColors[(stAttr.revvid) ? stAttr.txtclr : stAttr.bkclr];
if ((hBrush = CreateSolidBrush(hhTerm->crTerm)) == 0) return;
if (hhTerm->hbrushTerminal) DeleteObject(hhTerm->hbrushTerminal);
hhTerm->hbrushTerminal = hBrush; InvalidateRect(hhTerm->hwnd, 0, FALSE); return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * BlinkText * * DESCRIPTION: * Routine to toggle blinking-attribute cells on and off. * * ARGUMENTS: * HWND hwnd - terminal window handle. * * RETURNS: * VOID * */ void BlinkText(const HHTERM hhTerm) { int i, j, k; DWORD dwTime; RECT rc; BOOL fUpdate, fBlinks = FALSE; const int m = hhTerm->iRows; // for speed
const int n = hhTerm->iCols; // for speed
// hhTerm->iBlink is a tristate variable. If it is zero,
// there are no blink attributes in the image and we can exit
// immediately (this is an optimization). Otherwise, we toggle
// hhTerm->iBlink between -1 and 1, invalidate only those areas
// that have blinks, and paint.
if (hhTerm->iBlink == 0) return;
hhTerm->iBlink = (hhTerm->iBlink == -1) ? 1 : -1; dwTime = GetTickCount();
for (i = 0 ; i < m ; ++i) { const int r = (i + hhTerm->iTopline) % MAX_EMUROWS;
if (hhTerm->abBlink[r] == 0) continue;
// Don't let this routine gobble-up to much time. If we can't
// paint all the blinks, we can't paint all the blinks.
if ((GetTickCount() - dwTime) >= (DWORD)(hhTerm->uBlinkRate/2)) return;
for (j = 0, fUpdate = FALSE ; j < n ; ++j) { if (hhTerm->fppstAttr[r][j].blink) { for (k = j, j += 1 ; j < n ; ++j) { if (hhTerm->fppstAttr[r][j].blink == 0) break; }
rc.left = ((k - hhTerm->iHScrlPos) * hhTerm->xChar) + hhTerm->xIndent + hhTerm->xBezel; rc.right = rc.left + ((j - k) * hhTerm->xChar);
rc.top = (i + 1 - hhTerm->iVScrlPos) * hhTerm->yChar;
//rc.top = ((((i + m - hhTerm->iTopline) % m) + 1)
// - hhTerm->iVScrlPos) * hhTerm->yChar;
rc.bottom = rc.top + hhTerm->yChar;
//
// Currently we are blinking the text in the terminal
// emulator screen. If we don't want the text to blink
// when running in a Terminal Service session (Remote
// Desktop Connection) then uncomment the following
// line. REV: 10/4/2001
//
// if (!IsTerminalServicesEnabled()) // REMOVE:REV 10/4/2001
{ InvalidateRect(hhTerm->hwnd, &rc, FALSE); fUpdate = TRUE; } fBlinks = TRUE; } }
// Should draw here. Reason: if line 1 had a blinker and line 24
// had a blinker, we would have to repaint the whole terminal window
// since windows combines invalid regions.
if (fUpdate) UpdateWindow(hhTerm->hwnd);
hhTerm->abBlink[r] = (BYTE)fUpdate; }
if (fBlinks == FALSE) hhTerm->iBlink = 0;
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * RefreshTernWindow * * DESCRIPTION: * Calls the WM_SIZE code for terminal window * * ARGUMENTS: * hwnd - Terminal Window to refresh * * RETURNS: * void * */ void RefreshTermWindow(const HWND hwndTerm) { RECT rc; const HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwndTerm, GWLP_USERDATA);
if (hhTerm) // need to check validatity of handle. mrw:3/1/95
{ TP_WM_SIZE(hhTerm->hwnd, 0, 0, 0); // mrw:11/3/95
GetClientRect(hwndTerm, &rc); TP_WM_SIZE(hhTerm->hwnd, 0, rc.right, rc.bottom); InvalidateRect(hwndTerm, 0, FALSE); } return; }
//mpt:1-23-98 attempt to re-enable DBCS code
//#if 0
#ifndef CHAR_NARROW
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * termValidatePosition * * DESCRIPTION: * Checks the marking cursor position information in the HHTERM struct and * determines if it is valid by checking the underlying characters to see if * the cursor would split a double byte character. It optionally adjusts * the position to a valid position. * * ARGUMENTS: * hhTerm -- internal terminal data structure * nAdjustmentMode -- one of the following values: * VP_NO_ADJUSTMENT * VP_ADJUST_RIGHT * VP_ADJUST_LEFT * * RETURNS: * TRUE if the input values are OK, otherwise FALSE. Note that the adjust * parameter and any actions performed do not alter the return value. * */ BOOL termValidatePosition(const HHTERM hhTerm, const int nAdjustmentMode, POINT *pLocation) { BOOL bRet = TRUE;
if (pLocation->y <= 0) return TRUE; if ( hhTerm->fppstAttr[pLocation->y - 1][pLocation->x].wirt == TRUE ) { switch (nAdjustmentMode) { case VP_ADJUST_RIGHT: if ( pLocation->x < hhTerm->iCols ) { DbgOutStr("incrementing %d\r\n", pLocation->x, 0,0,0,0); pLocation->x++; bRet = FALSE; } break;
case VP_ADJUST_LEFT: if (pLocation->x > 0) { DbgOutStr("decrementing %d\r\n", pLocation->x, 0,0,0,0); pLocation->x--; bRet = FALSE; } break;
default: break; } } return bRet; } #endif // !CHAR_NARROW
#if 0 //DEADWOOD
BOOL bRet = TRUE; int bLeadByteSeen; int nOffset; LONG lIndx; LPTSTR pszStr = (LPTSTR)NULL;
/*
* This function just doesn't work correctly. The reason for that is * that I don't understand how the lines are organized and indexed in * the terminal. For now, this works OK if you just have a few lines * on the terminal screen for testing. Nothing in the backscroll. I * have no idea what other problems it has. * * DLW (17-Aug-1994) * * OK, I have made some attempt to get this stuff working correctly. * At least it doesn't seg anymore and seems to work most of the time. * I know that it still screws up when the scroll numbers are not just * right, so it is pretty obvious that it still is not what it should * be. So, it still needs to be checked by someone who knows what they * are doing (which leaves me out). * * DLW (18-Aug-1994) */
nOffset = 0; if (pLocation->y <= 0) { nOffset = hhTerm->iPhysicalBkRows + hhTerm->iNextBkLn + pLocation->y; nOffset %= hhTerm->iPhysicalBkRows;
pszStr = (LPTSTR)hhTerm->fplpstrBkTxt[nOffset]; } else if (pLocation->y > 0) { nOffset = pLocation->y - 1;
pszStr = (LPTSTR)hhTerm->fplpstrTxt[nOffset]; }
assert(pszStr);
if (pszStr == (LPTSTR)NULL) return FALSE;
/*
* We need to loop thru the string and check if the last character before * the specified character is a DBCS lead byte. If it is, we return FALSE * and perform any requested adjustment. */
bLeadByteSeen = FALSE; for (lIndx = 0; lIndx < pLocation->x; lIndx += 1) { if (bLeadByteSeen) { /* The rule is that a lead byte can NEVER follow a lead byte */ bLeadByteSeen = FALSE; } else { bLeadByteSeen = IsDBCSLeadByte(pszStr[lIndx]); } }
if (lIndx == pLocation->x) { bRet = !bLeadByteSeen; }
if (!bRet) { switch (nAdjustmentMode) { case VP_ADJUST_RIGHT: DbgOutStr("incrementing %d\r\n", pLocation->x, 0,0,0,0); /* TODO: range check this first */ pLocation->x += 1; break;
case VP_ADJUST_LEFT: DbgOutStr("decrementing %d\r\n", pLocation->x, 0,0,0,0); /* TODO: range check this first */ pLocation->x -= 1; break;
default: break; } } return bRet; } #endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * termGetLogFont * * DESCRIPTION: * This is here to handle a problem with calling send message in * the minitel load routines. * * ARGUMENTS: * hwndTerm - Terminal Window * * RETURNS: * 0=OK * * AUTHOR: mrw,2/21/95 * */ int termGetLogFont(const HWND hwndTerm, LPLOGFONT plf) { HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwndTerm, GWLP_USERDATA); assert(plf != 0);
if (hhTerm == 0) return -1; // mrw:6/15/95
*plf = hhTerm->lf; return 0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * termSetLogFont * * DESCRIPTION: * This is here to handle a problem with calling send message in * the minitel load routines. * * ARGUMENTS: * hwndTerm - Terminal Window * * RETURNS: * 0=OK * * AUTHOR: mrw,2/21/95 * */ int termSetLogFont(const HWND hwndTerm, LPLOGFONT plf) { HHTERM hhTerm = (HHTERM)GetWindowLongPtr(hwndTerm, GWLP_USERDATA); assert(plf != 0);
if (hhTerm == 0) // mrw,3/2/95
return -1;
hhTerm->lfHold = *plf; PostMessage(hwndTerm, WM_TERM_KLUDGE_FONT, 0, 0);
return 0; }
|