#include <windows.h>
#include <commdlg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "telnet.h"
#include "ini.h"
#include "auth.h"
extern char *encrypt_output;
extern char *decrypt_input;
extern char *cInvertedArray;
extern int bMouseDown;
extern int bSelection;
static SCREEN *ScreenList;
static HINSTANCE hInst;
static char szScreenClass[] = "ScreenWClass";
static char szScreenMenu[] = "ScreenMenu";
static char cursor_key[8][4] = {
"\x1B[D", "\x1B[A", "\x1B[C", "\x1B[B",
"\x1BOD", "\x1BOA", "\x1BOC", "\x1BOB",
};
void
ScreenInit(HINSTANCE hInstance)
{
BOOL b;
WNDCLASS wc;
hInst = hInstance;
ScreenList = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = ScreenWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(long);
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, "TERMINAL");
wc.hCursor = LoadCursor(NULL, IDC_IBEAM);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = szScreenMenu;
wc.lpszClassName = szScreenClass;
b = RegisterClass(&wc);
assert(b);
}
void
SetScreenInstance(HINSTANCE hInstance)
{
hInst = hInstance;
}
int
GetNewScreen(void)
{
SCREEN *pScr;
static int id = 0;
pScr = (SCREEN *) calloc(sizeof(SCREEN), 1);
if (pScr == NULL)
return(-1);
if (ScreenList == NULL) {
pScr->next = NULL;
pScr->prev = NULL;
}
else {
if (ScreenList->next == NULL) {
ScreenList->next = ScreenList;
ScreenList->prev = ScreenList;
}
pScr->next = ScreenList;
pScr->prev = ScreenList->prev;
ScreenList->prev->next = pScr;
ScreenList->prev = pScr;
}
ScreenList = pScr;
return(id++);
}
SCREENLINE *
ScreenNewLine(void)
{
SCREENLINE *pScrLine;
pScrLine = calloc(sizeof(SCREENLINE) + 2*MAX_LINE_WIDTH, 1);
if (pScrLine == NULL)
return (NULL);
pScrLine->text = &pScrLine->buffer[0];
pScrLine->attrib = &pScrLine->buffer[MAX_LINE_WIDTH];
return(pScrLine);
}
static void
MakeWindowTitle(char *host, int width, int height, char *title, int nchars)
{
char buf[128];
int hlen;
hlen = strlen(host);
title[0] = 0;
if (hlen + 1 > nchars)
return;
strcpy(title, host);
wsprintf(buf, " (%dh x %dw)", height, width);
if ((int) strlen(buf) + hlen + 1 > nchars)
return;
strcat(title, buf);
}
SCREEN *
InitNewScreen(CONFIG *Config)
{
TEXTMETRIC tm;
HMENU hMenu = NULL;
SCREEN *scr = NULL;
SCREENLINE *pScrLine;
SCREENLINE *pScrLineLast;
int id;
int idx = 0;
char title[128];
HDC hDC;
HFONT hFont;
id = GetNewScreen();
if (id == -1)
return(0);
scr = ScreenList;
assert(scr != NULL);
hMenu = LoadMenu(hInst, szScreenMenu);
assert(hMenu != NULL);
scr->title = Config->title;
MakeWindowTitle(Config->title, Config->width, Config->height,
title, sizeof(title));
scr->hwndTel = Config->hwndTel;
if (Config->backspace) {
CheckMenuItem(hMenu, IDM_BACKSPACE, MF_CHECKED);
CheckMenuItem(hMenu, IDM_DELETE, MF_UNCHECKED);
} else {
CheckMenuItem(hMenu, IDM_BACKSPACE, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_DELETE, MF_CHECKED);
}
hDC = GetDC(NULL);
assert(hDC != NULL);
scr->lf.lfPitchAndFamily = FIXED_PITCH;
GetPrivateProfileString(INI_FONT, "FaceName", "Courier", scr->lf.
lfFaceName, LF_FACESIZE, TELNET_INI);
scr->lf.lfHeight = (int) GetPrivateProfileInt(INI_FONT, "Height", 0, TELNET_INI);
scr->lf.lfWidth = (int) GetPrivateProfileInt(INI_FONT, "Width", 0, TELNET_INI);
scr->lf.lfPitchAndFamily = (BYTE) GetPrivateProfileInt(INI_FONT, "PitchAndFamily", 0, TELNET_INI);
scr->lf.lfCharSet = (BYTE) GetPrivateProfileInt(INI_FONT, "CharSet", 0, TELNET_INI);
scr->lf.lfEscapement = (BYTE) GetPrivateProfileInt(INI_FONT, "Escapement", 0, TELNET_INI);
scr->lf.lfQuality = PROOF_QUALITY;
scr->hSelectedFont = CreateFontIndirect((LPLOGFONT) &(scr->lf));
hFont = SelectObject(hDC, scr->hSelectedFont);
GetTextMetrics(hDC, (LPTEXTMETRIC) &tm);
SelectObject(hDC, hFont);
scr->cxChar = tm.tmAveCharWidth;
scr->cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(NULL, hDC);
scr->width = Config->width;
scr->height = Config->height;
scr->ID = id;
scr->x = 0;
scr->y = 0;
scr->Oldx = 0;
scr->Oldy = 0;
scr->attrib = 0;
scr->DECAWM = 1;
scr->bWrapPending = FALSE;
scr->top = 0;
scr->bottom = scr->height-1;
scr->parmptr = 0;
scr->escflg = 0;
scr->bAlert = FALSE;
scr->numlines = 0;
scr->maxlines = 150;
cInvertedArray = calloc(scr->width * scr->height, 1);
pScrLineLast = ScreenNewLine();
if (pScrLineLast == NULL)
return(NULL);
scr->screen_top = scr->buffer_top = pScrLineLast;
for (idx = 0; idx < scr->height - 1; idx++) {
pScrLine = ScreenNewLine();
if (pScrLine == NULL)
return(NULL);
pScrLine->prev = pScrLineLast;
pScrLineLast->next = pScrLine;
pScrLineLast = pScrLine;
}
scr->screen_bottom = scr->buffer_bottom = pScrLine;
scr->hWnd = CreateWindow(szScreenClass, title, WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
scr->cxChar * scr->width + FRAME_WIDTH,
scr->cyChar * scr->height + FRAME_HEIGHT,
NULL, hMenu, hInst, scr);
assert(scr->hWnd != NULL);
ShowWindow(scr->hWnd, SW_SHOW);
CreateCaret(scr->hWnd, NULL, scr->cxChar, 2);
SetCaretPos(scr->x*scr->cxChar, (scr->y+1) * scr->cyChar);
ShowCaret(scr->hWnd);
return(ScreenList);
}
void DeleteTopLine(
SCREEN *pScr)
{
assert(pScr->buffer_top != NULL);
pScr->buffer_top = pScr->buffer_top->next;
assert(pScr->buffer_top != NULL);
free(pScr->buffer_top->prev);
pScr->buffer_top->prev = NULL;
pScr->numlines--;
}
static void SetScreenScrollBar(
SCREEN *pScr)
{
if (pScr->numlines <= 0) {
SetScrollRange(pScr->hWnd, SB_VERT, 0, 100, FALSE);
SetScrollPos(pScr->hWnd, SB_VERT, 0, TRUE);
EnableScrollBar(pScr->hWnd, SB_VERT, ESB_DISABLE_BOTH);
}
else {
SetScrollRange(pScr->hWnd, SB_VERT, 0, pScr->numlines, FALSE);
SetScrollPos(pScr->hWnd, SB_VERT, pScr->numlines, TRUE);
EnableScrollBar(pScr->hWnd, SB_VERT, ESB_ENABLE_BOTH);
}
}
int ScreenScroll(
SCREEN *pScr)
{
SCREENLINE *pScrLine;
SCREENLINE *pPrev;
SCREENLINE *pNext;
SCREENLINE *pScrollTop;
SCREENLINE *pScrollBottom;
BOOL bFullScreen = TRUE;
HDC hDC;
RECT rc;
Edit_ClearSelection(pScr);
pScrollTop = GetScreenLineFromY(pScr, pScr->top);
pScrollBottom = GetScreenLineFromY(pScr, pScr->bottom);
if (pScrollTop != pScr->screen_top) {
bFullScreen = FALSE;
rc.left = 0;
rc.right = pScr->cxChar * pScr->width;
rc.top = pScr->cyChar * (pScr->top);
rc.bottom = pScr->cyChar * (pScr->bottom+1);
pNext = pScrollTop->next;
pPrev = pScrollTop->prev;
pPrev->next = pNext;
pNext->prev = pPrev;
pScrLine = pScrollTop;
ScreenClearLine(pScr, pScrLine);
}
else {
pScr->numlines++;
pScrLine = ScreenNewLine();
if (pScrLine == NULL)
return(0);
pScr->screen_top = pScrollTop->next;
}
if (pScrLine == NULL)
return(0);
pNext = pScrollBottom->next;
pScrollBottom->next = pScrLine;
pScrLine->next = pNext;
pScrLine->prev = pScrollBottom;
if (pNext != NULL)
pNext->prev = pScrLine;
if (pScrollBottom != pScr->screen_bottom) {
bFullScreen = FALSE;
rc.left = 0;
rc.right = pScr->cxChar * pScr->width;
rc.top = pScr->cyChar * pScr->top;
rc.bottom = pScr->cyChar * (pScr->bottom+1);
}
else {
if (pScr->screen_bottom == pScr->buffer_bottom)
pScr->buffer_bottom = pScrLine;
pScr->screen_bottom = pScrLine;
}
#if 0
CheckScreen(fpScr);
#endif
pScr->y++;
if (pScr->y > pScr->bottom)
pScr->y = pScr->bottom;
hDC = GetDC(pScr->hWnd);
assert(hDC != NULL);
if (bFullScreen)
ScrollDC(hDC, 0, -pScr->cyChar, NULL, NULL, NULL, NULL);
else
ScrollDC(hDC, 0, -pScr->cyChar, &rc, &rc, NULL, NULL);
PatBlt(hDC, 0, pScr->bottom * pScr->cyChar,
pScr->width * pScr->cxChar, pScr->cyChar, WHITENESS);
ReleaseDC(pScr->hWnd, hDC);
if (pScr->numlines == pScr->maxlines)
DeleteTopLine(pScr);
else
SetScreenScrollBar(pScr);
return(1);
}
int DrawTextScreen(
RECT rcInvalid,
SCREEN *pScr,
HDC hDC)
{
SCREENLINE *pScrLineTmp;
SCREENLINE *pScrLine;
int x = 0;
int y = 0;
int left = 0;
int right = 0;
int i;
int len;
char attrib;
#define YPOS (y*pScr->cyChar)
pScrLine = pScr->screen_top;
for (y = 0; y < pScr->height; y++) {
if (!pScrLine)
continue;
if (YPOS >= rcInvalid.top - pScr->cyChar &&
YPOS <= rcInvalid.bottom + pScr->cyChar) {
if (y < 0)
y = 0;
if (y >= pScr->height)
y = pScr->height - 1;
left = (rcInvalid.left / pScr->cxChar) - 1;
right = (rcInvalid.right / pScr->cxChar) + 1;
if (left < 0)
left = 0;
if (right > pScr->width - 1)
right = pScr->width - 1;
x = left;
while (x <= right) {
if (!pScrLine->text[x]) {
x++;
continue;
}
if (SCR_isrev(pScrLine->attrib[x])) {
SelectObject(hDC, pScr->hSelectedFont);
SetTextColor(hDC, RGB(255, 255, 255));
SetBkColor(hDC, RGB(0, 0, 0));
}
else if (SCR_isblnk(pScrLine->attrib[x])) {
SelectObject(hDC, pScr->hSelectedFont);
SetTextColor(hDC, RGB(255, 0, 0));
SetBkColor(hDC, RGB(255, 255, 255));
}
else if (SCR_isundl(pScrLine->attrib[x])) {
SetTextColor(hDC, RGB(255, 0, 0));
SetBkColor(hDC, RGB(255, 255, 255));
SelectObject(hDC, pScr->hSelectedULFont);
}
else {
SelectObject(hDC,pScr->hSelectedFont);
SetTextColor(hDC, RGB(0, 0, 0));
SetBkColor(hDC, RGB(255, 255, 255));
}
len = 1;
attrib = pScrLine->attrib[x];
for (i = x + 1; i <= right; i++) {
if (pScrLine->attrib[i] != attrib || !pScrLine->text[i])
break;
len++;
}
TextOut(hDC, x*pScr->cxChar, y*pScr->cyChar, &pScrLine->text[x], len);
x += len;
}
}
pScrLineTmp = pScrLine->next;
pScrLine = pScrLineTmp;
}
return(0);
}
static BOOL SetInternalScreenSize(
SCREEN *pScr,
int width,
int height)
{
RECT rc;
char *p;
int idx;
int n;
int newlines;
SCREENLINE *pNewLine;
SCREENLINE *pTopLine;
SCREENLINE *pBottomLine;
#if 0
int col;
int row;
int dydestbottom;
#endif
GetClientRect(pScr->hWnd, &rc);
width = (rc.right - rc.left) / pScr->cxChar;
height = (rc.bottom - rc.top) / pScr->cyChar;
if (pScr->height == height && pScr->width == width)
return(FALSE);
pScr->Oldx = 0;
pScr->Oldy = 0;
pScr->attrib = 0;
p = calloc(width * height, 1);
ScreenCursorOff(pScr);
#if 0
for (col = 0; col < width; col++) {
for (row = 0; row < height; row++) {
dydestbottom = height - 1 - row;
if (col < pScr->width && dydestbottom < pScr->height - 1)
p[row * width + col] =
cInvertedArray[(pScr->height - 1 - dydestbottom) * pScr->width + col];
}
}
#endif
free(cInvertedArray);
cInvertedArray = p;
pBottomLine = pScr->buffer_bottom;
newlines = height - (pScr->height + pScr->numlines);
if (newlines > 0) {
pScr->y += pScr->numlines;
pScr->numlines = 0;
for (idx = 0; idx < newlines; idx++) {
pNewLine = ScreenNewLine();
if (pNewLine == NULL)
return(FALSE);
pNewLine->prev = pBottomLine;
if (pBottomLine == NULL)
return(FALSE);
pBottomLine->next = pNewLine;
pBottomLine = pNewLine;
}
}
if (newlines < 0) {
pScr->y = (height - 1) - (pScr->bottom - pScr->y);
if (pScr->y < 0)
pScr->y = 0;
pScr->numlines = -newlines;
n = pScr->numlines - pScr->maxlines;
for (idx = 0; idx < n; idx++)
DeleteTopLine(pScr);
}
pScr->screen_bottom = pBottomLine;
pScr->buffer_bottom = pBottomLine;
pTopLine = pBottomLine;
for (idx = 1; idx < height; idx++) {
pTopLine = pTopLine->prev;
}
pScr->screen_top = pTopLine;
pScr->width = width;
pScr->height = height;
pScr->top = 0;
pScr->bottom = height - 1;
if (pScr->x >= width)
pScr->x = width - 1;
if (pScr->y >= height)
pScr->y = height - 1;
SetScreenScrollBar(pScr);
ScreenCursorOn(pScr);
return(TRUE);
}
static int ScreenAdjustUp(
SCREEN *pScr,
int n)
{
int idx;
SCREENLINE *pLine1;
SCREENLINE *pLine2;
for (idx = 0; idx < n; idx++) {
if (pScr->screen_top == pScr->buffer_top)
return(-idx);
pLine1 = pScr->screen_top->prev;
if (pLine1 == NULL)
return(-idx);
pLine2 = pScr->screen_bottom->prev;
if (pLine2 == NULL)
return(-idx);
pScr->screen_top = pLine1;
pScr->screen_bottom = pLine2;
}
return(idx);
}
static int ScreenAdjustDown(
SCREEN *pScr,
int n)
{
int idx;
SCREENLINE *pLine1;
SCREENLINE *pLine2;
for (idx = 0; idx < n; idx++) {
if (pScr->screen_bottom == pScr->buffer_bottom)
return(-idx);
pLine1 = pScr->screen_top->next;
if (pLine1 == NULL)
return(-idx);
pLine2 = pScr->screen_bottom->next;
if (pLine2 == NULL)
return(-idx);
pScr->screen_top = pLine1;
pScr->screen_bottom = pLine2;
}
return(idx);
}
long PASCAL ScreenWndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
MINMAXINFO *lpmmi;
SCREEN *pScr;
HMENU hMenu;
PAINTSTRUCT ps;
int x = 0;
int y = 0;
int ScrollPos;
int tmpScroll = 0;
int idx;
HDC hDC;
RECT rc;
char title[128];
static int bDoubleClick = FALSE;
switch (message) {
case WM_COMMAND:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
switch (wParam) {
case IDM_EXIT:
if (MessageBox(hWnd, "Terminate this connection?", "Telnet", MB_OKCANCEL) == IDOK) {
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
SendMessage(pScr->hwndTel, WM_MYSCREENCLOSE, 0, (LPARAM) pScr);
}
break;
case IDM_BACKSPACE:
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, IDM_BACKSPACE, MF_CHECKED);
CheckMenuItem(hMenu, IDM_DELETE, MF_UNCHECKED);
SendMessage(pScr->hwndTel, WM_MYSCREENCHANGEBKSP, VK_BACK, (LPARAM) pScr);
break;
case IDM_DELETE:
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, IDM_BACKSPACE, MF_UNCHECKED);
CheckMenuItem(hMenu, IDM_DELETE, MF_CHECKED);
SendMessage(pScr->hwndTel, WM_MYSCREENCHANGEBKSP, 0x7f, (LPARAM) pScr);
break;
case IDM_FONT:
ScreenCursorOff(pScr);
ProcessFontChange(hWnd);
ScreenCursorOn(pScr);
break;
case IDM_COPY:
Edit_Copy(hWnd);
hMenu=GetMenu(hWnd);
Edit_ClearSelection(pScr);
break;
case IDM_PASTE:
Edit_Paste(hWnd);
break;
case IDM_HELP_INDEX:
WinHelp(hWnd, HELP_FILE, HELP_INDEX, 0);
break;
case IDM_ABOUT:
#ifdef CYGNUS
#ifdef KRB4
strcpy(strTmp, " Kerberos 4 for Windows\n");
#endif
#ifdef KRB5
strcpy(strTmp, " KerbNet for Windows\n");
#endif
strcat(strTmp, "\n Version 1.00\n\n");
strcat(strTmp, " For support, contact:\n");
strcat(strTmp, " Cygnus Support - (415) 903-1400\n");
#else
strcpy(strTmp, " Kerberos 5 Telnet for Windows\n");
strcat(strTmp, " ALPHA SNAPSHOT 2\n\n");
#endif
if (encrypt_flag) {
strcat(strTmp, "\n[Encryption of output requested. State: ");
strcat(strTmp, (encrypt_output ? "encrypting]" : "INACTIVE]"));
strcat(strTmp, "\n[Decryption of input requested. State: ");
strcat(strTmp, (decrypt_input ? "decrypting]\n" : "INACTIVE]\n"));
}
MessageBox(NULL, strTmp, "Kerberos", MB_OK);
break;
#if defined(DEBUG)
case IDM_DEBUG:
CheckScreen(pScr);
break;
#endif
}
break;
case WM_NCCREATE:
pScr = (SCREEN *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
pScr->hWnd = hWnd;
SetWindowLong(hWnd, SCREEN_HANDLE, (LONG) pScr);
SetScrollRange(hWnd, SB_VERT, 0, 100, FALSE);
SetScrollPos(hWnd, SB_VERT, 0, TRUE);
EnableScrollBar(hWnd, SB_VERT, ESB_DISABLE_BOTH);
return(TRUE);
case WM_VSCROLL:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
ScreenCursorOff(pScr);
switch(wParam) {
case SB_LINEDOWN:
if (ScreenAdjustDown(pScr, 1) <= 0)
break;
hDC = GetDC(hWnd);
assert(hDC != NULL);
rc.left = 0;
rc.right = pScr->cxChar * pScr->width;
rc.top = 0;
rc.bottom = pScr->cyChar * (pScr->bottom + 1);
ScrollDC(hDC, 0, -pScr->cyChar, &rc, &rc, NULL, NULL);
ReleaseDC(hWnd, hDC);
rc.top = pScr->cyChar * pScr->bottom;
InvalidateRect(hWnd, &rc, TRUE);
ScrollPos = GetScrollPos(hWnd, SB_VERT);
SetScrollPos(hWnd, SB_VERT, ScrollPos + 1, TRUE);
UpdateWindow(hWnd);
break;
case SB_LINEUP:
if (ScreenAdjustUp(pScr, 1) <= 0)
break;
hDC = GetDC(hWnd);
assert(hDC != NULL);
rc.left = 0;
rc.right = pScr->cxChar * pScr->width;
rc.top = 0;
rc.bottom = pScr->cyChar * (pScr->bottom + 1);
ScrollDC(hDC, 0, pScr->cyChar, &rc, &rc, NULL, NULL);
ReleaseDC(hWnd, hDC);
rc.bottom = pScr->cyChar;
InvalidateRect(hWnd, &rc, TRUE);
ScrollPos = GetScrollPos(pScr->hWnd, SB_VERT);
SetScrollPos(hWnd,SB_VERT, ScrollPos - 1, TRUE);
UpdateWindow(hWnd);
break;
case SB_PAGEDOWN:
idx = abs(ScreenAdjustDown(pScr, pScr->height));
hDC = GetDC(hWnd);
assert(hDC != NULL);
rc.left = 0;
rc.right = pScr->cxChar * pScr->width;
rc.top = 0;
rc.bottom = pScr->cyChar * (pScr->bottom+1);
ScrollDC(hDC, 0, -idx * pScr->cyChar, &rc, &rc, NULL, NULL);
ReleaseDC(hWnd, hDC);
rc.top = pScr->cyChar * (pScr->bottom - idx + 1);
InvalidateRect(hWnd, &rc, TRUE);
ScrollPos=GetScrollPos(hWnd, SB_VERT);
SetScrollPos(hWnd, SB_VERT, ScrollPos + idx, TRUE);
break;
case SB_PAGEUP:
idx = abs(ScreenAdjustUp(pScr, pScr->height));
hDC = GetDC(hWnd);
assert(hDC != NULL);
rc.left = 0;
rc.right = pScr->cxChar * pScr->width;
rc.top = 0;
rc.bottom = pScr->cyChar * (pScr->bottom + 1);
ScrollDC(hDC, 0, idx * pScr->cyChar, &rc, &rc, NULL, NULL);
ReleaseDC(hWnd, hDC);
rc.bottom = idx * pScr->cyChar;
InvalidateRect(hWnd, &rc, TRUE);
ScrollPos=GetScrollPos(hWnd, SB_VERT);
SetScrollPos(hWnd, SB_VERT, ScrollPos - idx, TRUE);
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
ScrollPos = GetScrollPos(hWnd, SB_VERT);
tmpScroll = ScrollPos - LOWORD(lParam);
if (tmpScroll == 0)
break;
if (tmpScroll > 0)
ScreenAdjustUp(pScr, tmpScroll);
else
ScreenAdjustDown(pScr, -tmpScroll);
if (abs(tmpScroll) < pScr->height) {
hDC = GetDC(hWnd);
assert(hDC != NULL);
rc.left = 0;
rc.right = pScr->cxChar * pScr->width;
rc.top = 0;
rc.bottom = pScr->cyChar * (pScr->bottom + 1);
ScrollDC(hDC, 0, tmpScroll * pScr->cyChar, &rc, &rc, NULL, NULL);
ReleaseDC(hWnd, hDC);
if (tmpScroll > 0) {
rc.bottom = tmpScroll * pScr->cyChar;
InvalidateRect(hWnd, &rc, TRUE);
}
else {
rc.top = (pScr->bottom + tmpScroll + 1) * pScr->cyChar;
InvalidateRect(hWnd, &rc, TRUE);
}
}
else
InvalidateRect(hWnd, NULL, TRUE);
SetScrollPos(hWnd, SB_VERT, LOWORD(lParam), TRUE);
UpdateWindow(hWnd);
break;
}
ScreenCursorOn(pScr);
break;
case WM_KEYDOWN:
if (wParam == VK_INSERT) {
if (GetKeyState(VK_SHIFT) < 0)
PostMessage(hWnd, WM_COMMAND, IDM_PASTE, 0);
else if (GetKeyState(VK_CONTROL) < 0)
PostMessage(hWnd, WM_COMMAND, IDM_COPY, 0);
break;
}
if (wParam < VK_PRIOR || wParam > VK_DOWN)
break;
if (GetKeyState (VK_CONTROL) >= 0) {
if (wParam >= VK_LEFT && wParam <= VK_DOWN) {
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
wParam = wParam - VK_LEFT + (pScr->DECCKM ? 4 : 0);
SendMessage (pScr->hwndTel, WM_MYCURSORKEY,
strlen(cursor_key[wParam]),
(LPARAM) (char *) cursor_key[wParam]);
}
} else {
switch (wParam) {
case VK_PRIOR:
SendMessage(hWnd, WM_VSCROLL, SB_PAGEUP, 0);
break;
case VK_NEXT:
SendMessage(hWnd, WM_VSCROLL, SB_PAGEDOWN, 0);
break;
case VK_UP:
SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0);
break;
case VK_DOWN:
SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0);
break;
}
}
UpdateWindow(hWnd);
break;
case WM_CHAR:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
SendMessage(pScr->hwndTel, WM_MYSCREENCHAR, wParam, (LPARAM) pScr);
break;
case WM_INITMENU:
if (IsClipboardFormatAvailable(CF_TEXT))
EnableMenuItem((HMENU) wParam, IDM_PASTE, MF_ENABLED);
else
EnableMenuItem((HMENU) wParam, IDM_PASTE, MF_GRAYED);
if (bSelection)
EnableMenuItem((HMENU) wParam, IDM_COPY, MF_ENABLED);
else
EnableMenuItem((HMENU) wParam, IDM_COPY, MF_GRAYED);
break;
case WM_GETMINMAXINFO:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
if (pScr == NULL)
pScr = ScreenList;
lpmmi = (MINMAXINFO *) lParam;
if (FRAME_WIDTH + MAX_LINE_WIDTH * pScr->cxChar < lpmmi->ptMaxSize.x)
lpmmi->ptMaxSize.x = FRAME_WIDTH + MAX_LINE_WIDTH * pScr->cxChar;
lpmmi->ptMaxTrackSize.x = lpmmi->ptMaxSize.x;
lpmmi->ptMinTrackSize.x = FRAME_WIDTH + 20 * pScr->cxChar;
lpmmi->ptMinTrackSize.y = FRAME_HEIGHT + 4 * pScr->cyChar;
break;
case WM_LBUTTONDOWN:
if (bDoubleClick)
Edit_TripleClick(hWnd, lParam);
else
Edit_LbuttonDown(hWnd, lParam);
break;
case WM_LBUTTONUP:
Edit_LbuttonUp(hWnd, lParam);
break;
case WM_LBUTTONDBLCLK:
bDoubleClick = TRUE;
SetTimer(hWnd, TIMER_TRIPLECLICK, GetDoubleClickTime(), NULL);
Edit_LbuttonDblclk(hWnd, lParam);
break;
case WM_TIMER:
if (wParam == TIMER_TRIPLECLICK)
bDoubleClick = FALSE;
break;
case WM_RBUTTONUP:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
Edit_Copy(hWnd);
Edit_ClearSelection(pScr);
Edit_Paste(hWnd);
break;
case WM_MOUSEMOVE:
if (bMouseDown)
Edit_MouseMove(hWnd, lParam);
break;
case WM_RBUTTONDOWN:
#if 0
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
wsprintf(strTmp,"fp->x=%d fp->y=%d text=%s \r\n",
pScr->screen_top->x, pScr->screen_top->y, pScr->screen_top->text);
OutputDebugString(strTmp);
#endif
break;
case WM_PAINT:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
BeginPaint (hWnd, &ps);
SelectObject(ps.hdc, pScr->hSelectedFont);
if (pScr->screen_bottom != NULL)
DrawTextScreen(ps.rcPaint, pScr, ps.hdc);
else
OutputDebugString("screen_bottom is NULL.\r\n");
EndPaint(hWnd, &ps);
break;
case WM_CLOSE:
if (MessageBox(hWnd, "Terminate this connection?", "Telnet", MB_OKCANCEL) == IDOK) {
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
SendMessage(pScr->hwndTel, WM_MYSCREENCLOSE, 0, (LPARAM) pScr);
return (DefWindowProc(hWnd, message, wParam, lParam));
}
break;
case WM_DESTROY:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
if (pScr != NULL)
DeleteObject(pScr->hSelectedFont);
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_ACTIVATE:
if (wParam != WA_INACTIVE) {
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
if (pScr->bAlert) {
char strTitle[128];
int idx;
GetWindowText(hWnd, strTitle, sizeof(strTitle));
if (strTitle[0] == ALERT) {
idx = lstrlen(strTitle);
strTitle[idx - 2] = 0;
SetWindowText(hWnd, &strTitle[2]);
pScr->bAlert = FALSE;
}
}
}
return (DefWindowProc(hWnd, message, wParam, lParam));
case WM_SIZE:
if (wParam == SIZE_MINIMIZED)
break;
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
if (SetInternalScreenSize(pScr, LOWORD(lParam), HIWORD(lParam))) {
SendMessage(pScr->hwndTel, WM_MYSCREENSIZE, 0,
MAKELONG(pScr->width, pScr->height));
}
MakeWindowTitle(pScr->title, pScr->width, pScr->height,
title, sizeof(title));
SetWindowText(hWnd, title);
break;
case WM_SETFOCUS:
pScr = (SCREEN *) GetWindowLong(hWnd, SCREEN_HANDLE);
assert (pScr != NULL);
CreateCaret(hWnd, NULL, pScr->cxChar, 2);
ScreenCursorOn(pScr);
break;
case WM_KILLFOCUS:
DestroyCaret();
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
}
return(0);
}
void ScreenBell(
SCREEN *pScr)
{
char strTitle[128];
int idx;
MessageBeep(MB_ICONEXCLAMATION);
if (pScr->hWnd != GetActiveWindow()) {
FlashWindow(pScr->hWnd, TRUE);
if (!pScr->bAlert) {
strTitle[0] = ALERT;
strTitle[1] = SPACE;
GetWindowText(pScr->hWnd, &strTitle[2], sizeof(strTitle) - 2);
idx = lstrlen(strTitle);
strTitle[idx] = SPACE;
strTitle[idx+1] = ALERT;
strTitle[idx+2] = 0;
SetWindowText(pScr->hWnd, strTitle);
}
FlashWindow(pScr->hWnd, FALSE);
pScr->bAlert = TRUE;
}
}
void ScreenBackspace(SCREEN *pScr)
{
RECT rc;
pScr->bWrapPending = FALSE;
rc.left = pScr->x * pScr->cxChar;
rc.right = (pScr->x + 1) * pScr->cxChar;
rc.top = pScr->cyChar * pScr->y;
rc.bottom = pScr->cyChar * (pScr->y + 1);
InvalidateRect(pScr->hWnd, &rc, TRUE);
pScr->x--;
if (pScr->x < 0)
pScr->x = 0;
UpdateWindow(pScr->hWnd);
}
void ScreenTab(
SCREEN *pScr)
{
int num_spaces;
int idx;
SCREENLINE *pScrLine;
int iTest = 0;
HDC hDC;
num_spaces = TAB_SPACES - (pScr->x % TAB_SPACES);
if (pScr->x + num_spaces >= pScr->width)
num_spaces = pScr->width - pScr->x;
pScrLine = GetScreenLineFromY(pScr, pScr->y);
if (pScrLine == NULL)
return;
for (idx = 0; idx < num_spaces; idx++, pScr->x++) {
if (!pScrLine->text[pScr->x])
iTest=1;
if (iTest)
pScrLine->text[pScr->x] = SPACE;
}
hDC = GetDC(pScr->hWnd);
assert(hDC != NULL);
SelectObject(hDC, pScr->hSelectedFont);
TextOut(hDC, (pScr->x - num_spaces) * pScr->cxChar, pScr->y * pScr->cyChar,
pScrLine->text + pScr->x - num_spaces, num_spaces);
ReleaseDC(pScr->hWnd, hDC);
if (pScr->x >= pScr->width)
pScr->x = pScr->width - 1;
pScr->bWrapPending = FALSE;
}
void ScreenCarriageFeed(
SCREEN *pScr)
{
pScr->bWrapPending = FALSE;
pScr->x = 0;
}