home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
progjorn
/
pj_7_1.arc
/
WINH19.C
< prev
next >
Wrap
Text File
|
1988-10-23
|
13KB
|
521 lines
/*
* Windows H19 emulator
*
* Written by William S. Hall
* 3665 Benton Street, #66
* Santa Clara, CA 95051
*
* Program entry module - extracts
*/
/* Windows entry point */
int FAR PASCAL WinMain(hInstance, hPrevInstance, lpszCmdLine, cmdShow)
HANDLE hInstance, hPrevInstance;
LPSTR lpszCmdLine;
short cmdShow;
{
/*
* Initialization
*/
if (!InitProgram(hInstance,hPrevInstance, lpszCmdLine, cmdShow))
return FALSE;
/*
* Message loop
*/
while (TRUE)
if (!DoMessage()) /* if message, process it */
ProcessComm(); /* if none, then take care of communications */
}
/*
* Main window procedure. If the terminal is off-line, then Windows calls
* this function whenever it has information for the main window.
* If we are on-line, then the subclass window procedure below is
* entered first. Any messages not processed there come here.
*/
long FAR PASCAL MainWndProc(hWnd,message,wParam,lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
PAINTSTRUCT ps;
BYTE ShortStr[2];
HMENU hMenu;
switch(message) {
/*
* This action is required when the clipboard chain changes.
*/
case WM_CHANGECBCHAIN:
if (wParam == hWndNext)
hWndNext = LOWORD(lParam);
SendMessage(hWndNext, message, wParam, lParam);
break;
/*
* Enable our 'paste' menu if there is textual data in clipboard.
*/
case WM_DRAWCLIPBOARD:
if (IsWindow(hWndNext))
SendMessage(hWndNext, message, wParam, lParam);
if (OpenClipboard(hWnd)) {
hClipData = GetClipboardData(CF_TEXT);
hMenu = GetMenu(hWnd);
if (hClipData != NULL)
EnableMenuItem(hMenu, IDM_PASTE, MF_ENABLED);
else
EnableMenuItem(hMenu, IDM_PASTE, MF_GRAYED);
CloseClipboard();
}
break;
/*
* Main window has been created. Do some initializations unique
* to this window.
*/
case WM_CREATE:
MainWndCreate(hWnd,lParam);
break;
/*
* The WM_KEYDOWN message gives us a way to process special keys
* such as those from the keypad or the function keys. If we
* get this message, then the terminal is off-line. Since we still
* want the keypad to perform correctly, i. e. up-arrow moves the
* cursor up, we call the local keydown routine to do the right thing.
*/
case WM_KEYDOWN:
if (!CD.KeyboardDisabled)
H19LocalKeyDown(wParam);
break;
/*
* A key down/up stroke has been translated to a printable character.
* Since we are off-line, we simply process it locally.
*/
case WM_CHAR:
if (!CD.KeyboardDisabled) {
ShortStr[0] = (BYTE)wParam;
H19StringInput(ShortStr,(short)1);
if (wParam == XON)
EscapeCommFunction(cid,SETXON);
}
break;
/*
* We can create the caret. Since the main window does not carry
* the text, the request is passed on to the currently active
* child, which may be the main window or the status line.
*/
case WM_SETFOCUS:
CD.OwnCaret = TRUE;
if (IsWindowEnabled(hWnd) && IsWindow(hWndActive)) {
SendMessage(hWndActive, WH19_CARETFUNCTION, H19_CREATECARET,
(LONG)CD.OwnCaret);
}
break;
/*
* We have lost input focus, so we must destroy the caret. The
* request is simply passed to the active child window.
*/
case WM_KILLFOCUS:
if (IsWindow(hWndActive)) {
SendMessage(hWndActive,WH19_CARETFUNCTION,H19_DESTROYCARET,
(LONG)CD.OwnCaret);
}
CD.OwnCaret = FALSE;
break;
/*
* A menu item or accelerator has been selected. Process it.
*/
case WM_COMMAND:
WndCommand(hWnd, wParam, lParam);
break;
/*
* The main window has moved. Recompute some parameters to help
* us locate the child terminal windows.
*/
case WM_MOVE:
MW.SCTopTextLine = HIWORD(lParam);
MW.SCBottomTextLine = MW.SCTopTextLine + MW.BottomTextLine;
break;
/*
* The main window has been resized. We must now move the child
* windows accordingly.
*/
case WM_SIZE:
SizeWindow(LOWORD(lParam), HIWORD(lParam), wParam);
break;
/*
* Close the comm port and get off the clipboard chain; exiting.
*/
case WM_CLOSE:
CloseCommPort(hWnd, &cid);
ChangeClipboardChain(hWnd, hWndNext);
DestroyWindow(hWnd);
break;
/*
* Windows is exiting; close the comm port.
*/
case WM_ENDSESSION:
if (wParam)
CloseCommPort(hWnd, &cid);
break;
/*
* Request to exit.
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
/*
* Clear main window if not iconic. Otherwise draw icon.
*/
case WM_PAINT:
BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
MainWndPaint(hWnd, ps.hdc);
EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
break;
/*
* We watch this message for the 'About' box command.
*/
case WM_SYSCOMMAND:
return((long)MainSysCommand(hWnd, message, wParam,lParam));
/*
* All messages we don't process go here.
*/
default:
return ((long)DefWindowProc(hWnd,message,wParam,lParam));
}
return(0L);
}
/*
* Subclass window procedure. This procedure is called first whenever
* the terminal is on-line. Any message not processed here must be
* returned to the main window procedure above.
*/
LONG FAR PASCAL MainWndSubclassProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
BYTE outstr[80];
int len = 0;
BOOL CheckForControl = FALSE;
switch(message) {
/*
* We are on-line and a printable character has been struck.
* Copy the character to a buffer. See below for call to
* write to the communications port.
*/
case WM_CHAR:
if (!CD.KeyboardDisabled)
outstr[len++] = (BYTE)wParam;
break;
/*
* We are on-line and a key-down code has been received. We
* use this message to process keypad and other special keys.
*/
case WM_KEYDOWN:
/* set comm break if CTRL-BREAK is down */
if (wParam == VK_CANCEL) {
if (CD.BreakFlag == -1)
CD.BreakFlag = SetCommBreak(cid);
break;
}
/*
* Use the scroll key to control scrolling or hold-screen mode.
*/
else if (wParam == VK_SCROLL) {
SetScrollState();
break;
}
if (!CD.KeyboardDisabled) {
switch(wParam) {
/*
* Translate CTRL-BKSP to a DELETE character.
*/
case VK_BACK:
if (GetKeyState(VK_CONTROL) & 0x8000)
outstr[len++] = DEL;
break;
/*
* For the rest of the keypad keys, put together a
* string (such as ESC A for up-arrow when in Heath
* mode or ESC [ A when it ANSI mode). In certain
* cases, if the control key is also down, then the
* string is not tranmitted as per H-19 behavior.
*/
default:
CheckForControl = OutputKeydown(outstr, &len, wParam);
break;
}
}
break;
/*
* All programmable function keys are in the resource accelerator
* table. Hence they generate WM_COMMAND messages.
* Since they have no effect unless on-line, we process them here.
*/
case WM_COMMAND:
if ((wParam >= IDM_F1) && (wParam <= IDM_CSF12)) {
if (!CD.KeyboardDisabled) {
char *tptr;
int sparam, index;
sparam = (wParam /100) * 100;
index = wParam - sparam;
switch (sparam) {
case IDM_F1: /* unshifted */
tptr = szFKey[index];
break;
case IDM_SF1: /* shifted */
tptr = szSFKey[index];
break;
case IDM_CF1: /* control */
tptr = szCFKey[index];
break;
case IDM_CSF1: /* control-shift */
tptr = szCSFKey[index];
break;
}
/*
* Read programmed action from win.ini.
*/
len = GetProfileString((LPSTR)szAppName,(LPSTR)tptr,
(LPSTR)"",(LPSTR)outstr,80);
/*
* Look for '\char' entries. Convert them to control chars.
*/
ScanForEscapes(outstr, &len);
break;
}
break;
}
/*
* All other WM_COMMAND messages are sent on to main wnd proc.
*/
return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
case WM_KEYUP:
/*
* if CTRL-BREAK key is released, then clear comm break.
*/
if (wParam == VK_CANCEL) {
ClearCommBreak(cid);
CD.BreakFlag = -1;
break;
}
/*
* Unprocessed messages go here.
*/
default:
return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
}
/*
* If CheckForControl is TRUE, then do not send string to comm
* port. Instead, return it to main window procedure where it
* can be processed as if off-line.
*/
if (CheckForControl)
if (GetKeyState(VK_CONTROL) & 0x8000)
return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
/*
* We have a string of positive length, so send it out.
*/
if (len) {
WriteToPort(cid, (BYTE FAR *)outstr, len);
/*
* Local echo, so send it back to ourselves as well.
*/
if (!CD.FullDuplex)
return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
}
return 0L;
}
/*
* This routine builds the appropriate string for the keypad keys.
TRUE is returned if the key is one which is not sent if the
control key is pressed.
*/
static BOOL NEAR OutputKeydown(BYTE str[], int *plen, WORD wparam)
{
BOOL result = FALSE;
int index;
BOOL shift, control;
/*
* If Heath mode, then prefix string with ESC. If ANSI, add '[' or
* other appropriate lead character.
*/
str[(*plen)++] = ESC;
if (CD.ANSIMode)
str[(*plen)++] = '[';
switch(wparam) {
case VK_UP: /* Up arrow */
str[(*plen)++] = 'A';
result = TRUE;
break;
case VK_DOWN: /* Down arrow */
str[(*plen)++] = 'B';
result = TRUE;
break;
case VK_RIGHT: /* Right arrow */
str[(*plen)++] = 'C';
result = TRUE;
break;
case VK_LEFT: /* Left arrow */
str[(*plen)++] = 'D';
result = TRUE;
break;
/*
* Home key. On H-19 this is toggle insert character.
*/
case VK_HOME:
if (CD.ANSIMode) {
str[(*plen)++] = '4';
if (CD.ICToggle)
str[(*plen)++] = 'l';
else
str[(*plen)++] = 'h';
}
else {
if (CD.ICToggle)
str[(*plen)++] = 'O';
else
str[(*plen)++] = '@';
}
result = TRUE;
break;
/*
* End key. On H-19, this is insert-line.
*/
case VK_END:
str[(*plen)++] = 'L';
result = TRUE;
break;
/*
* Pg Up key. On H-19, this is delete character.
*/
case VK_PRIOR:
if (CD.ANSIMode)
str[(*plen)++] = 'P';
else
str[(*plen)++] = 'N';
result = TRUE;
break;
/*
* Pg Dn key. On H-19, this is delete-line.
*/
case VK_NEXT:
str[(*plen)++] = 'M';
result = TRUE;
break;
/*
* '5' key. On H-19, this is the home key.
*/
case VK_CLEAR:
str[(*plen)++] = 'H';
result = TRUE;
break;
/*
* Function keys. F1 to F5 correspond on H-19. F6 acts as
* the erase key. F7, F8, and F9 are the blue, red, white
* keys, respectively.
*/
case VK_F1:
case VK_F2:
case VK_F3:
case VK_F4:
case VK_F5:
case VK_F7:
case VK_F8:
case VK_F9:
if (wparam >= VK_F7)
index = 'P' + wparam - VK_F7;
else
index = 'S' + wparam - VK_F1;
if (CD.ANSIMode)
str[*plen - 1] = 'O';
str[(*plen)++] = (BYTE)index;
break;
/*
* Erase key. Do different things if shifted or not.
*/
case VK_F6:
if (GetKeyState(VK_SHIFT) & 0x8000) {
if (CD.ANSIMode) {
str[(*plen)++] = '2';
str[(*plen)++] = 'J';
}
else
str[(*plen)++] = 'E';
}
else
str[(*plen)++] = 'J';
result = TRUE;
break;
/*
* If we get these keys, then we have to send out 3-character
* sequences if in Alternate keypad mode.
*/
case VK_NUMPAD0:
case VK_NUMPAD1:
case VK_NUMPAD2:
case VK_NUMPAD3:
case VK_NUMPAD4:
case VK_NUMPAD5:
case VK_NUMPAD6:
case VK_NUMPAD7:
case VK_NUMPAD8:
case VK_NUMPAD9:
case VK_DECIMAL:
if (CD.AltKeypad) {
if (CD.ANSIMode)
str[*plen - 1] = 'O';
else
str[(*plen)++] = '?';
if (wparam == VK_DECIMAL)
str[(*plen)++] = 'n';
else
str[(*plen)++] = (BYTE)('p' + (wparam - VK_NUMPAD0));
}
else
*plen = 0;
break;
default:
*plen = 0;
break;
}
return(result);
}