home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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);
- }