home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pub
/
win100
/
win19f.c
< prev
next >
Wrap
C/C++ Source or Header
|
2020-01-01
|
31KB
|
1,387 lines
/*
* Windows H19 Terminal Emulator Function Support Module
*
* Written by William S. Hall
* 3665 Benton Street, #66
* Santa Clara, CA 95051
*/
#define NOKANJI
#define NOATOM
#define NOMINMAX
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include "winasc.h"
#include "winh19.h"
#include "win19d.h"
#if defined(KERMIT)
#include "winkpf.h"
extern krmState;
#endif
/* ansi emulation manifests */
#define MAX_PARAM_LIST 32
#define BEGIN_ANSI_COMMAND 10
#define ANSI_INDIGIT 11
#define ANSI_ENDDIGIT 12
#define ANSI_MODE 13
#define ANSI_SET 14
#define ANSI_MODE_INDIGIT 15
#define ANSI_SET_INDIGIT 16
#define ANSI_MODE_ENDDIGIT 17
#define ANSI_SET_ENDDIGIT 18
/* ansi emulation local parameters */
static int ParamListIndex;
static int ANSIParam;
static int ANSIParamList[MAX_PARAM_LIST + 1];
static int NEAR InDigitTransition(BYTE ch, unsigned instate, unsigned endstate,
void (NEAR *action)(BYTE));
static void NEAR PositionRow(BYTE y);
static void NEAR PositionCol(BYTE x);
static void NEAR SwitchActiveWindow(HWND hWnd);
static void NEAR ProcessESCCommand(BYTE ch);
static void NEAR MoveStatWindow(short height);
static void NEAR ProcessBaudChange(int);
static void NEAR IdentifyTerm(void);
static void NEAR ReportCursorPosition(short line, short col);
static BOOL NEAR DoKeyTranslation(unsigned message, WORD *wparam);
static void NEAR DoANSICommand(int state, BYTE ch);
static void NEAR ANSISetCommand(BYTE ch);
static void NEAR ANSIModeCommand(BYTE ch);
static void NEAR PlaceInList(int val);
static void NEAR ANSICommand(BYTE ch);
static void NEAR DoHeathCommand(int state, BYTE ch);
static BOOL NEAR InNumpadSet(unsigned val);
static WORD NEAR EditToNumpadShort(unsigned val);
static WORD NEAR NumpadToEdit(unsigned val);
static WORD NEAR EditToNumpadLong(unsigned val);
/* special key handler when off-line */
void NEAR H19LocalKeyDown(WORD keycode)
{
switch (keycode) {
case VK_UP:
SendMessage(hWndActive,WH19_COMMAND,H19_MOVECURSORUP,1L);
break;
case VK_DOWN:
SendMessage(hWndActive,WH19_COMMAND,H19_MOVECURSORDOWN,1L);
break;
case VK_RIGHT:
SendMessage(hWndActive,WH19_COMMAND,H19_MOVECURSORRIGHT,1L);
break;
case VK_LEFT:
SendMessage(hWndActive,WH19_COMMAND,H19_MOVECURSORLEFT,1L);
break;
case VK_HOME:
CD.ICToggle = (CD.ICToggle ? FALSE : TRUE);
break;
case VK_END:
SendMessage(hWndActive, WH19_COMMAND, H19_INSERTLINE,1L);
break;
case VK_PRIOR:
SendMessage(hWndActive, WH19_COMMAND,H19_DELETECHAR,1L);
break;
case VK_NEXT:
SendMessage(hWndActive, WH19_COMMAND, H19_DELETELINE,1L);
break;
case VK_CLEAR:
SwitchActiveWindow(TW.hWnd);
SendMessage(hWndActive, WH19_COMMAND, H19_CURSORHOME,0L);
break;
case VK_F6:
if (GetKeyState(VK_SHIFT) & 0x8000)
SendMessage(hWndActive, WH19_COMMAND, H19_CLRSCREEN,0L);
else
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOENDOFSCREEN,0L);
break;
}
}
/* communications processor */
BOOL NEAR DoMessage()
{
MSG msg;
if (PeekMessage((LPMSG)&msg,NULL,0,0,PM_REMOVE)) {
if (msg.message == WM_QUIT)
exit((int)msg.wParam);
if (TranslateAccelerator(MW.hWnd,hAccel,(LPMSG)&msg) == 0) {
if (DoKeyTranslation(msg.message, &msg.wParam))
TranslateMessage((LPMSG)&msg);
DispatchMessage((LPMSG)&msg);
}
return TRUE;
}
return FALSE;
}
/* return TRUE if key is to be translated */
static BOOL NEAR DoKeyTranslation(unsigned message, WORD *wparam)
{
register unsigned shiftstate, numstate;
int retval = TRUE;
if ((message == WM_KEYDOWN) || (message == WM_KEYUP)) {
if (*wparam == VK_CANCEL)
return FALSE;
if (*wparam == VK_BACK) {
if (GetKeyState(VK_CONTROL) & 0x8000)
return FALSE;
return TRUE;
}
numstate = GetKeyState(VK_NUMLOCK);
shiftstate = (GetKeyState(VK_SHIFT) & 0x8000) >> 15;
if (CD.ShiftedKeypad) {
if (numstate | shiftstate) {
if (InNumpadSet(*wparam))
*wparam = NumpadToEdit(*wparam);
else
*wparam = EditToNumpadLong(*wparam);
}
else
*wparam = EditToNumpadShort(*wparam);
}
else {
if (!(numstate | shiftstate))
*wparam = EditToNumpadLong(*wparam);
else
*wparam = EditToNumpadShort(*wparam);
}
if (CD.AltKeypad)
if (InNumpadSet(*wparam))
retval = FALSE;
}
return retval;
}
/* support modules for key translation */
static BOOL NEAR InNumpadSet(unsigned val)
{
return(((val >= VK_NUMPAD0) && (val <= VK_NUMPAD9)) || (val == VK_DECIMAL));
}
static WORD NEAR NumpadToEdit(unsigned val)
{
switch (val) {
case VK_NUMPAD1:
val = VK_END;
break;
case VK_NUMPAD2:
val = VK_DOWN;
break;
case VK_NUMPAD3:
val = VK_NEXT;
break;
case VK_NUMPAD4:
val = VK_LEFT;
break;
case VK_NUMPAD5:
val = VK_CLEAR;
break;
case VK_NUMPAD6:
val = VK_RIGHT;
break;
case VK_NUMPAD7:
val = VK_HOME;
break;
case VK_NUMPAD8:
val = VK_UP;
break;
case VK_NUMPAD9:
val = VK_PRIOR;
break;
}
return val;
}
static WORD NEAR EditToNumpadShort(unsigned val)
{
switch (val) {
case VK_DELETE:
val = VK_DECIMAL;
break;
case VK_INSERT:
val = VK_NUMPAD0;
break;
}
return val;
}
static WORD NEAR EditToNumpadLong(unsigned val)
{
switch (val) {
case VK_DELETE:
val = VK_DECIMAL;
break;
case VK_INSERT:
val = VK_NUMPAD0;
break;
case VK_END:
val = VK_NUMPAD1;
break;
case VK_DOWN:
val = VK_NUMPAD2;
break;
case VK_NEXT:
val = VK_NUMPAD3;
break;
case VK_LEFT:
val = VK_NUMPAD4;
break;
case VK_CLEAR:
val = VK_NUMPAD5;
break;
case VK_RIGHT:
val = VK_NUMPAD6;
break;
case VK_HOME:
val = VK_NUMPAD7;
break;
case VK_UP:
val = VK_NUMPAD8;
break;
case VK_PRIOR:
val = VK_NUMPAD9;
break;
}
return val;
}
/* process string from comm port */
int NEAR H19StringInput(BYTE *str, short len)
{
register BYTE *ptr;
register short ctr;
short state;
BYTE ch;
int numrem;
while (len) {
if (state = CD.CommandState) {
ch = *str & 0x7f;
if (CD.ANSIMode)
DoANSICommand(state, ch);
else
DoHeathCommand(state, ch);
str++;
len -= 1;
}
else {
ctr = 0;
ptr = str;
while (len) {
if ((*ptr &= 0x7f) != ESC) {
ctr += 1;
ptr++;
len -= 1;
}
else {
ptr++;
len -= 1;
CD.CommandState = ESC_COMMAND;
break;
}
}
if (ctr) {
numrem = (int)SendMessage(hWndActive,WH19_STRINGINPUT,(WORD)ctr,
(LONG)(LPSTR)str);
if (numrem)
return(len + numrem);
}
str = ptr;
}
}
return (len);
}
/* start ansi processing */
static void NEAR DoANSICommand(int state, BYTE ch)
{
register int newstate;
if (ch == CAN)
newstate = NO_COMMAND;
else if (ch == ESC)
newstate = ESC_COMMAND;
else {
switch(state) {
case ESC_COMMAND:
switch (ch) {
case '[':
ParamListIndex = 0;
ANSIParam = 0;
ANSIParamList[0] = 0;
newstate = BEGIN_ANSI_COMMAND;
break;
case 'M':
SendMessage(hWndActive, WH19_COMMAND,
H19_REVERSELINEFEED,0L);
newstate = NO_COMMAND;
break;
case '=' : /* enter alternate keypad */
CD.AltKeypad = TRUE;
newstate = NO_COMMAND;
break;
case '>' : /* exit alternate keypad */
CD.AltKeypad = FALSE;
newstate = NO_COMMAND;
break;
default:
newstate = NO_COMMAND;
break;
}
break;
case BEGIN_ANSI_COMMAND:
switch(ch) {
case '?':
newstate = ANSI_MODE;
break;
case '>':
newstate = ANSI_SET;
break;
default:
newstate = InDigitTransition(ch, ANSI_INDIGIT,
ANSI_ENDDIGIT, ANSICommand);
break;
}
break;
case ANSI_INDIGIT:
case ANSI_ENDDIGIT:
newstate = InDigitTransition(ch, ANSI_INDIGIT,
ANSI_ENDDIGIT, ANSICommand);
break;
case ANSI_MODE:
case ANSI_MODE_INDIGIT:
case ANSI_MODE_ENDDIGIT:
newstate = InDigitTransition(ch, ANSI_MODE_INDIGIT,
ANSI_MODE_ENDDIGIT,ANSIModeCommand);
break;
case ANSI_SET:
case ANSI_SET_INDIGIT:
case ANSI_SET_ENDDIGIT:
newstate = InDigitTransition(ch, ANSI_SET_INDIGIT,
ANSI_SET_ENDDIGIT,ANSISetCommand);
break;
}
}
CD.CommandState = newstate;
}
/* support modules for ansi emulation */
static int NEAR InDigitTransition(BYTE ch, unsigned instate, unsigned endstate,
void (NEAR *action)(BYTE))
{
register int state;
if (isdigit(ch)) {
ANSIParam = 10 * ANSIParam + ch - '0';
state = instate;
}
else if (ch == ';') {
PlaceInList(ANSIParam);
state = endstate;
}
else {
PlaceInList(ANSIParam);
(*action)(ch);
state = NO_COMMAND;
}
return state;
}
static void NEAR ANSISetCommand(BYTE ch)
{
register int i;
if (ch == 'h')
for (i = 0; i < ParamListIndex; i++)
ProcessSetCommand(ANSIParamList[i]);
else if (ch == 'l')
for (i = 0; i < ParamListIndex; i++)
ProcessResetCommand(ANSIParamList[i]);
}
static void NEAR ANSIModeCommand(BYTE ch)
{
register int i;
if (ch == 'h') {
for (i = 0; i < ParamListIndex; i++) {
switch (ANSIParamList[i]) {
case 2:
CD.ANSIMode = FALSE;
return;
case 7:
CD.WrapAround = TRUE;
break;
}
}
}
else if (ch == 'l') {
for (i = 0; i < ParamListIndex; i++) {
switch (ANSIParamList[i]) {
case 7:
CD.WrapAround = FALSE;
break;
}
}
}
}
static void NEAR PlaceInList(int val)
{
if (ParamListIndex < MAX_PARAM_LIST)
ANSIParamList[ParamListIndex++] = val;
ANSIParam = 0;
}
static void NEAR ANSICommand(BYTE ch)
{
register int val1 = ANSIParamList[0];
register int val2 = ANSIParamList[1];
int i;
switch(ch) {
case 'A' : /* move cursor up */
if (val1 == 0)
val1 = 1;
SendMessage(hWndActive, WH19_COMMAND, H19_MOVECURSORUP,(LONG)val1);
break;
case 'B' : /* move cursor down */
if (val1 == 0)
val1 = 1;
SendMessage(hWndActive, WH19_COMMAND, H19_MOVECURSORDOWN,(LONG)val1);
break;
case 'C' :
if (val1 == 0)
val1 = 1;
SendMessage(hWndActive,WH19_COMMAND,H19_MOVECURSORRIGHT,(LONG)val1);
break;
case 'D' :
if (val1 == 0)
val1 = 1;
SendMessage(hWndActive,WH19_COMMAND,H19_MOVECURSORLEFT,(LONG)val1);
break;
case 'f':
case 'H':
switch(ParamListIndex) {
case 0:
PositionRow(0);
PositionCol(0);
break;
case 1:
if (val1 == 0)
val1 = 1;
PositionRow(LOBYTE(val1 - 1));
PositionCol(0);
break;
default:
if (val1 == 0)
val1 = 1;
if (val2 == 0)
val2 = 1;
PositionRow(LOBYTE(val1 - 1));
PositionCol(LOBYTE(val2 - 1));
break;
}
break;
case 'J':
if (ParamListIndex == 0)
SendMessage(hWndActive,WH19_COMMAND,H19_CLRTOENDOFSCREEN,0L);
else {
switch(val1) {
case 0:
SendMessage(hWndActive,WH19_COMMAND,H19_CLRTOENDOFSCREEN,0L);
break;
case 1:
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOTOPOFSCREEN,0L);
break;
case 2:
SendMessage(hWndActive, WH19_COMMAND, H19_CLRSCREEN,0L);
break;
}
}
break;
case 'K':
if (ParamListIndex == 0)
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOENDOFLINE,0L);
else {
switch(val1) {
case 0:
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOENDOFLINE,0L);
break;
case 1:
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOSTARTOFLINE,0L);
break;
case 2:
SendMessage(hWndActive, WH19_COMMAND, H19_ERASELINE,0L);
break;
}
}
break;
case 'L' : /* insert line */
if (val1 == 0)
val1 = 1;
SendMessage(hWndActive, WH19_COMMAND, H19_INSERTLINE,(LONG)val1);
break;
case 'M' : /* delete line */
if (val1 == 0)
val1 = 1;
SendMessage(hWndActive, WH19_COMMAND, H19_DELETELINE,(LONG)val1);
break;
case 'P' : /* delete char */
if (val1 == 0)
val1 = 1;
SendMessage(hWndActive, WH19_COMMAND,H19_DELETECHAR,(LONG)val1);
break;
case 'h' :
for (i = 0; i < ParamListIndex; i++) {
switch (ANSIParamList[i]) {
case 2:
CD.KeyboardDisabled = TRUE;
break;
case 4:
CD.ICToggle = TRUE;
break;
case 20:
CD.CRonLF = TRUE;
break;
}
}
break;
case 'l' :
for (i = 0; i < ParamListIndex; i++) {
switch (ANSIParamList[i]) {
case 2:
CD.KeyboardDisabled = FALSE;
break;
case 4:
CD.ICToggle = FALSE;
break;
case 20:
CD.CRonLF = FALSE;
break;
}
}
break;
case 'm':
for (i = 0; i < ParamListIndex; i++) {
switch (ANSIParamList[i]) {
case 0:
CD.InverseVideo = FALSE;
CD.CharAttribute = 0;
break;
case 7:
CD.InverseVideo = TRUE;
CD.CharAttribute = 0x80;
break;
case 10:
CD.GraphicsMode = TRUE;
break;
case 11:
CD.GraphicsMode = FALSE;
break;
}
}
break;
case 'n' :
switch(val1) {
case 6:
if (CD.LineState == IDM_ONLINE) {
short currow, curcol;
SendMessage(hWndActive, WH19_CURSORPOSITION,
H19_GETCURSOR,MAKELONG(&currow, &curcol));
ReportCursorPosition(currow,curcol);
}
}
break;
case 'p':
SendScreen(&TW);
break;
case 'q':
SendStatusLine(&SW);
break;
case 'r':
ProcessBaudChange(val1 - 1);
break;
case 's' :
SendMessage(hWndActive, WH19_CURSORPOSITION,H19_SAVECURSOR, 0L);
break;
case 'u' :
PositionRow((BYTE)CD.CurSaveRow);
PositionCol((BYTE)CD.CurSaveCol);
break;
case 'z':
ResetTerminal();
break;
}
}
/* Heath emulation modules */
static void NEAR DoHeathCommand(int state, BYTE ch)
{
if (ch == CAN)
CD.CommandState = NO_COMMAND;
else if (ch == ESC)
CD.CommandState = ESC_COMMAND;
else {
switch(state) {
case ESC_COMMAND:
ProcessESCCommand(ch);
break;
case YPOS_COMMAND:
PositionRow((BYTE)(ch - SP));
break;
case XPOS_COMMAND:
PositionCol((BYTE)(ch - SP));
break;
case SET_COMMAND:
ProcessSetCommand((int)(ch - '0'));
break;
case RESET_COMMAND:
ProcessResetCommand((int)(ch - '0'));
break;
case SETBAUD_COMMAND:
ProcessBaudChange((int)(ch - 'A'));
break;
}
}
}
static void NEAR PositionRow(BYTE y)
{
register short maxlines = TW.MaxLines;
CD.CommandState = XPOS_COMMAND;
if ((y >= 0) && (y < (BYTE)maxlines)) {
SwitchActiveWindow(TW.hWnd);
SendMessage(TW.hWnd,WH19_COMMAND,H19_POSITIONCURSORROW,(LONG)y);
}
else if (y == (BYTE)maxlines)
if (CD.StatOpen)
SwitchActiveWindow(SW.hWnd);
}
static void NEAR PositionCol(BYTE x)
{
register short cols = TW.MaxCols;
CD.CommandState = NO_COMMAND;
if ((x < 0) || (x >= (BYTE)cols))
x = (BYTE)(cols - 1);
SendMessage(hWndActive, WH19_COMMAND, H19_POSITIONCURSORCOL, (LONG)x);
}
static void NEAR SwitchActiveWindow(HWND hWnd)
{
if (hWndActive != hWnd) {
SendMessage(hWndActive, WH19_CARETFUNCTION, H19_DESTROYCARET,
(LONG)CD.OwnCaret);
hWndActive = hWnd;
SendMessage(hWndActive, WH19_CARETFUNCTION, H19_CREATECARET,
(LONG)CD.OwnCaret);
}
}
void ProcessSetCommand(int ch)
{
CD.CommandState = NO_COMMAND;
switch(ch) {
case 1 : /* enable status line */
if (!CD.StatOpen) {
CD.StatOpen = TRUE;
memset(SW.pVidBuffer, SP, TW.MaxCols);
MoveStatWindow(MW.Height);
InvalidateRect(SW.hWnd, (LPRECT)NULL, TRUE);
UpdateWindow(SW.hWnd);
if (hWndActive == SW.hWnd)
SendMessage(hWndActive,WH19_CARETFUNCTION,H19_SHOWCARET,0L);
SendMessage(hWndActive, WH19_COMMAND, H19_ADJUSTWINDOW,0L);
}
break;
case 2 : /* no key click */
CD.KeyClick = FALSE;
break;
case 3 : /* hold screen mode */
CD.HoldScreen = TRUE;
break;
case 4 : /* block cursor */
if (!CD.BlockCursor) {
CD.BlockCursor = TRUE;
SendMessage(hWndActive,WH19_CARETFUNCTION,H19_DESTROYCARET,
(LONG)CD.OwnCaret);
SendMessage(hWndActive,WH19_CARETFUNCTION,H19_CREATECARET,
(LONG)CD.OwnCaret);
}
break;
case 5 : /* cursor off */
SendMessage(hWndActive,WH19_CARETFUNCTION,H19_HIDECARET,0L);
CD.CursorOff = TRUE;
break;
case 6 : /* keypad shifted */
CD.ShiftedKeypad = TRUE;
break;
case 7 : /* alternate keypad */
CD.AltKeypad = TRUE;
break;
case 8 : /* auto lf on cr */
CD.LFonCR = TRUE;
break;
case 9 : /* auto cr on lf */
CD.CRonLF = TRUE;
break;
}
}
void ProcessResetCommand(int ch)
{
CD.CommandState = NO_COMMAND;
switch(ch) {
case 1 :
if (CD.StatOpen) {
CD.StatOpen = FALSE;
memset(SW.pVidBuffer, SP, TW.MaxCols);
InvalidateRect(SW.hWnd, (LPRECT)NULL, TRUE);
UpdateWindow(SW.hWnd);
MoveStatWindow(MW.Height);
if (hWndActive == SW.hWnd)
SendMessage(hWndActive,WH19_CARETFUNCTION,H19_HIDECARET,0L);
}
break;
case 2 : /* enable key click */
CD.KeyClick = TRUE;
break;
case 3 : /* exit hold screen mode */
CD.HoldScreen = FALSE;
break;
case 4 :
if (CD.BlockCursor) {
CD.BlockCursor = FALSE;
SendMessage(hWndActive, WH19_CARETFUNCTION,H19_DESTROYCARET,
(LONG)CD.OwnCaret);
SendMessage(hWndActive, WH19_CARETFUNCTION,H19_CREATECARET,
(LONG)CD.OwnCaret);
}
break;
case 5 : /* cursor on */
CD.CursorOff = FALSE;
SendMessage(hWndActive,WH19_CARETFUNCTION,H19_SHOWCARET,0L);
break;
case 6 : /* keypad unshifted */
CD.ShiftedKeypad = FALSE;
break;
case 7 : /* exit alternate keypad */
CD.AltKeypad = FALSE;
break;
case 8 : /* no auto lf on cr */
CD.LFonCR = FALSE;
break;
case 9 : /* no auto cr on lf */
CD.CRonLF = FALSE;
break;
}
}
static void NEAR ProcessESCCommand(BYTE ch)
{
CD.CommandState = NO_COMMAND;
switch(ch) {
case '#' : /* transmit page */
SendScreen(&TW);
break;
case '<' : /* enter ansi mode */
CD.ANSIMode = TRUE;
break;
case '=' : /* enter alternate keypad */
CD.AltKeypad = TRUE;
break;
case '>' : /* exit alternate keypad */
CD.AltKeypad = FALSE;
break;
case '@' : /* enter insert char mode */
CD.ICToggle = TRUE;
break;
case 'A' : /* move cursor up */
SendMessage(hWndActive, WH19_COMMAND, H19_MOVECURSORUP,1L);
break;
case 'B' : /* move cursor down */
SendMessage(hWndActive, WH19_COMMAND, H19_MOVECURSORDOWN,1L);
break;
case 'C' : /* move cursor right */
SendMessage(hWndActive, WH19_COMMAND, H19_MOVECURSORRIGHT,1L);
break;
case 'D' : /* move curosr left */
SendMessage(hWndActive, WH19_COMMAND, H19_MOVECURSORLEFT,1L);
break;
case 'E' : /* home and clear */
SendMessage(hWndActive, WH19_COMMAND, H19_CLRSCREEN,0L);
break;
case 'F' : /* enter graphics mode */
CD.GraphicsMode = TRUE;
break;
case 'G' : /* exit graphics mode */
CD.GraphicsMode = FALSE;
break;
case 'H' : /* home cursor */
SwitchActiveWindow(TW.hWnd);
SendMessage(hWndActive, WH19_COMMAND, H19_CURSORHOME,0L);
break;
case 'I' : /* reverse line feed */
SendMessage(hWndActive, WH19_COMMAND, H19_REVERSELINEFEED,0L);
break;
case 'J' : /* clear to end of screen */
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOENDOFSCREEN,0L);
break;
case 'K' : /* clear to end of line */
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOENDOFLINE,0L);
break;
case 'L' : /* insert line */
SendMessage(hWndActive, WH19_COMMAND, H19_INSERTLINE,1L);
break;
case 'M' : /* delete line */
SendMessage(hWndActive, WH19_COMMAND, H19_DELETELINE,1L);
break;
case 'N' : /* delete char */
SendMessage(hWndActive, WH19_COMMAND,H19_DELETECHAR,1L);
break;
case 'O' : /* exit insert char mode */
CD.ICToggle = FALSE;
break;
case 'Y' : /* position cursor */
CD.CommandState = YPOS_COMMAND;
break;
case 'Z' : /* identify as VT52 */
if (CD.LineState == IDM_ONLINE)
IdentifyTerm();
break;
case '[' : /* enter hold screen mode */
CD.HoldScreen = TRUE;
break;
case '\\' : /* exit hold screen mode */
CD.HoldScreen = FALSE;
break;
case ']' : /* transmit status line */
SendStatusLine(&SW);
break;
case 'b' : /* clear to screen top */
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOTOPOFSCREEN,0L);
break;
case 'j' : /* save cursor position */
SendMessage(hWndActive, WH19_CURSORPOSITION,H19_SAVECURSOR, 0L);
break;
case 'k' : /* set to saved position */
PositionRow((BYTE)CD.CurSaveRow);
PositionCol((BYTE)CD.CurSaveCol);
break;
case 'l' : /* erase entire line */
SendMessage(hWndActive, WH19_COMMAND, H19_ERASELINE,0L);
break;
case 'n' : /* report cursor position */
if (CD.LineState == IDM_ONLINE) {
short currow, curcol;
SendMessage(hWndActive, WH19_CURSORPOSITION,H19_GETCURSOR,
MAKELONG(&currow, &curcol));
ReportCursorPosition(currow,curcol);
}
break;
case 'o' : /* clear to start of line */
SendMessage(hWndActive, WH19_COMMAND, H19_CLRTOSTARTOFLINE,0L);
break;
case 'p' : /* enter inverse video */
CD.InverseVideo = TRUE;
CD.CharAttribute = 0x80;
break;
case 'q' : /* exit inverse video */
CD.CharAttribute = 0;
CD.InverseVideo = FALSE;
break;
case 'r' : /* set baud rate */
CD.CommandState = SETBAUD_COMMAND;
break;
case 't' : /* enter shifted keypad */
CD.ShiftedKeypad = TRUE;
break;
case 'u' : /* exit shifted keypad */
CD.ShiftedKeypad = FALSE;
break;
case 'v' : /* set wraparound */
CD.WrapAround = TRUE;
break;
case 'w': /* no wrap */
CD.WrapAround = FALSE;
break;
case 'x' : /* set command */
CD.CommandState = SET_COMMAND;
break;
case 'y' : /* reset command */
CD.CommandState = RESET_COMMAND;
break;
case 'z' : /* reset to power up conditions */
ResetTerminal();
break;
case '}' : /* disable keyboard */
CD.KeyboardDisabled = TRUE;
break;
case '{' : /* enable keyboard */
CD.KeyboardDisabled = FALSE;
break;
}
}
/* paint command */
void NEAR MainWndPaint(hWnd, hDC)
HWND hWnd;
HDC hDC;
{
register BOOL iconic = IsIconic(hWnd);
char *ptr;
RECT prect;
#if defined(KERMIT)
if (krmState)
krmShowTransferData(hWnd, hDC, iconic);
else
#endif
if (iconic) {
GetClientRect(hWnd, (LPRECT)&prect);
ptr = szWinTitle;
Rectangle(hDC,prect.left,prect.top,prect.right,prect.bottom);
prect.top += 1;
DrawText(hDC, (LPSTR)ptr,4,(LPRECT)&prect,
DT_CENTER | DT_NOCLIP | DT_EXTERNALLEADING);
prect.top = prect.bottom/2;
ptr += strlen(szWinTitle) - 5;
DrawText(hDC, (LPSTR)ptr,4,(LPRECT)&prect,
DT_CENTER | DT_NOCLIP);
}
}
/* called when a system key is activated */
long NEAR MainSysCommand(hWnd,message,wParam,lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
FARPROC fp;
switch (wParam) {
case IDM_ABOUT:
fp = MakeProcInstance((FARPROC)AboutBoxProc, hInst);
DialogBox(hInst, MAKEINTRESOURCE(DT_ABOUT),hWnd,fp);
FreeProcInstance(fp);
return TRUE;
default:
return(DefWindowProc(hWnd,message,wParam,lParam));
}
return (0L);
}
/* window has been resized */
void NEAR SizeWindow(width, height, code)
WORD width;
WORD height;
WORD code;
{
#if defined(KERMIT)
if (krmState)
krmAdjustHeight((short)width, (short)height);
#endif
switch (code) {
case SIZEICONIC:
break;
default:
MW.Height = height;
MW.Width = width;
MW.BottomTextLine = height / TW.CharHeight * TW.CharHeight -
TW.CharHeight;
MW.SCBottomTextLine = MW.SCTopTextLine + MW.BottomTextLine;
if (IsWindow(hWndActive))
SendMessage(hWndActive, WH19_CARETFUNCTION,H19_DESTROYCARET,
(LONG)CD.OwnCaret);
if (IsWindow(TW.hWnd)) {
MoveWindow(TW.hWnd,0,0,TW.Width,TW.Height,TRUE);
if (IsWindow(SW.hWnd))
MoveStatWindow(MW.Height);
}
if (IsWindow(hWndActive))
SendMessage(hWndActive, WH19_CARETFUNCTION,H19_CREATECARET,
(LONG)CD.OwnCaret);
break;
}
}
/* move status window */
static void NEAR MoveStatWindow(short height)
{
register short statpos = TW.Height;
register short statheight = TW.CharHeight;
CD.StatOverlayTerm = FALSE;
if ((statpos + statheight) > height) {
if (CD.StatOpen) {
statpos = MW.BottomTextLine;
statheight = MW.Height - MW.BottomTextLine;
CD.StatOverlayTerm = TRUE;
}
else {
statpos = MW.BottomTextLine + TW.CharHeight;
statheight = height - statpos;
}
}
MoveWindow(SW.hWnd,0,statpos,TW.Width,statheight,TRUE);
}
/* menu handler */
void NEAR WndCommand(hWnd, wparam, lparam)
HWND hWnd;
WORD wparam;
LONG lparam;
{
register HMENU hMenu = GetMenu(hWnd);
HCURSOR hCurOld;
FARPROC fp;
switch (wparam) {
case IDM_CLEARCOM:
FlushComm(cid,0);
FlushComm(cid,1);
EscapeCommFunction(cid,SETXON);
if (CD.LineState == IDM_ONLINE)
TransmitCommChar(cid, XON);
break;
case IDM_RESET:
ResetTerminal();
break;
case IDM_OFFLINE:
SetWindowLong(MW.hWnd, GWL_WNDPROC, (LONG)MainWndSubclassProc);
hCurOld = SetCursor(LoadCursor((HANDLE)NULL,IDC_WAIT));
SendMessage(hWndActive, WH19_CARETFUNCTION, H19_HIDECARET, 0L);
ChangeMenu(hMenu,IDM_OFFLINE,(LPSTR)szOnline,IDM_ONLINE,
MF_BYCOMMAND | MF_CHANGE);
DrawMenuBar(hWnd);
CD.LineState = IDM_ONLINE;
SendMessage(hWndActive, WH19_CARETFUNCTION, H19_SHOWCARET, 0L);
SetCursor(hCurOld);
break;
case IDM_ONLINE:
SetWindowLong(MW.hWnd, GWL_WNDPROC, (LONG)fpTerminal);
hCurOld = SetCursor(LoadCursor((HANDLE)NULL,IDC_WAIT));
SendMessage(hWndActive, WH19_CARETFUNCTION, H19_HIDECARET, 0L);
ChangeMenu(hMenu,IDM_ONLINE,(LPSTR)szOffline,IDM_OFFLINE,
MF_BYCOMMAND | MF_CHANGE);
DrawMenuBar(hWnd);
CD.LineState = IDM_OFFLINE;
SendMessage(hWndActive, WH19_CARETFUNCTION, H19_SHOWCARET, 0L);
SetCursor(hCurOld);
break;
case IDM_COMM:
fp = MakeProcInstance((FARPROC)SetCommParams, hInst);
DialogBox(hInst, MAKEINTRESOURCE(DT_COMM),hWnd,fp);
FreeProcInstance(fp);
break;
case IDM_TERM:
fp = MakeProcInstance((FARPROC)SetTermParams, hInst);
DialogBox(hInst, MAKEINTRESOURCE(DT_TERM),hWnd,fp);
FreeProcInstance(fp);
break;
case IDM_SPECIALKEYS:
fp = MakeProcInstance((FARPROC)SetStringParams, hInst);
DialogBox(hInst, MAKEINTRESOURCE(DT_STRING),hWnd,fp);
FreeProcInstance(fp);
break;
case IDM_COPY:
SendMessage(TW.hWnd, WH19_SLAPSCREEN, 0, 0L);
break;
case IDM_PASTE:
if (OpenClipboard(hWnd)) {
LPSTR lpClip, lpDest;
BYTE ch;
hClipData = GetClipboardData(CF_TEXT);
GB.lBufSize = GlobalSize(hClipData);
if (GB.hBuf == NULL) {
GB.hBuf = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
GB.lBufSize);
if (GB.hBuf != NULL) {
GB.lBufHead = GB.lBufTail = 0;
lpClip = GlobalLock(hClipData);
lpDest = GlobalLock(GB.hBuf);
while(ch = *lpClip++) {
if (ch != LF) {
*lpDest++ = ch;
GB.lBufTail += 1;
}
}
GlobalUnlock(hClipData);
GlobalUnlock(GB.hBuf);
}
}
CloseClipboard();
}
break;
#if defined(KERMIT)
default:
krmProcessKermitMenu(hWnd, wparam);
break;
#endif
}
}
/* communications processor */
void NEAR ProcessComm()
{
COMSTAT ComStatus;
int num;
register int retresult = 0;
register int result = 0;
static char Buffer[RXQUESIZE];
static int bufsize = 0;
if ((CD.LineState == IDM_ONLINE) && !CD.ScrollLock) {
if (bufsize == 0) {
GetCommError(cid, (COMSTAT FAR *)&ComStatus);
if (num = ComStatus.cbInQue) {
num = min(num, BUFSIZE);
if ((result = ReadComm(cid, (LPSTR)Buffer, num)) < 0) {
result = -result;
Buffer[result] = NUL;
}
}
}
else
result = bufsize;
#if defined(KERMIT)
if (krmState)
krmKermitDispatch(MW.hWnd, Buffer, result);
else
#endif
if (result) {
retresult = H19StringInput(Buffer, result);
if (retresult) {
bufsize = retresult;
memmove(Buffer, Buffer+result-retresult,retresult);
Buffer[bufsize] = 0;
}
else
bufsize = 0;
}
else if (GB.hBuf) {
BYTE FAR *tbuf;
LONG BufBytesRemaining;
int count;
BufBytesRemaining = GB.lBufTail - GB.lBufHead;
if (BufBytesRemaining > 0) {
tbuf = GlobalLock(GB.hBuf) + GB.lBufHead;
if (BufBytesRemaining > INT_MAX)
count = TW.MaxCols;
else
count = min(TW.MaxCols, (int)LOWORD(BufBytesRemaining));
WriteToPort(cid, tbuf, count);
GB.lBufHead += count;
BufBytesRemaining = GB.lBufTail - GB.lBufHead;
GlobalUnlock(GB.hBuf);
}
if (BufBytesRemaining <= 0)
GB.hBuf = GlobalFree(GB.hBuf);
}
}
}
/* write to comm port */
void NEAR WriteToPort(cid, buf, len)
short cid;
BYTE FAR *buf;
int len;
{
COMSTAT mystat;
register int room;
GetCommError(cid, (COMSTAT FAR *)&mystat);
room = TXQUESIZE - mystat.cbOutQue;
while (room < len) {
if (!DoMessage()) {
GetCommError(cid, (COMSTAT FAR *)&mystat);
room = TXQUESIZE - mystat.cbOutQue;
}
}
WriteComm(cid, (LPSTR)buf, len);
}
/* change baud rate */
static void NEAR ProcessBaudChange(int ch)
{
WORD rate;
CD.CommandState = NO_COMMAND;
if ((ch >= 0) && (ch < BAUDTABLESIZE)) {
CommData.BaudRate = rate = BaudRateTable[ch];
CommData.StopBits = ONESTOPBIT;
if (rate == 110)
CommData.StopBits = TWOSTOPBITS;
SetCommState((DCB FAR *)&CommData);
}
}
/* report vt52 */
static void NEAR IdentifyTerm()
{
BYTE outstr[5];
outstr[0] = ESC;
outstr[1] = '/';
outstr[2] = 'K';
WriteToPort(cid, (BYTE FAR *)outstr, 3);
}
/* report cursor position */
static void NEAR ReportCursorPosition(short line, short col)
{
BYTE outstr[20];
register BYTE *outstrptr = outstr;
*outstrptr++ = ESC;
if (CD.ANSIMode) {
*outstrptr++ = '[';
itoa(line+1, outstrptr,10);
outstrptr += strlen(outstrptr);
*outstrptr++ = ';';
itoa(col+1, outstrptr,10);
outstrptr += strlen(outstrptr);
*outstrptr++ = 'R';
}
else {
*outstrptr++ = 'Y';
*outstrptr++ = (BYTE)(SP + line);
*outstrptr++ = (BYTE)(SP + col);
}
*outstrptr = NUL;
WriteToPort(cid, (BYTE FAR *)outstr, strlen(outstr));
}