//--------------------------------------------------------------------------- // // Module: ttychic.c // // Purpose: // This sample application demonstrates the usage of the COMM // API. It implements the new Win32c API of Windows 95. // // This application demonstrates how to read data asynchronously // using the OVERLAPPED structure. // // NOTE: no escape sequences are translated, only // the necessary control codes (LF, CR, BS, etc.) // // Description of functions: // Descriptions are contained in the function headers. // //--------------------------------------------------------------------------- // // Written by Microsoft Product Support Services, Windows Developer Support. // Copyright (c) 1991 Microsoft Corporation. All Rights Reserved. // //--------------------------------------------------------------------------- #include "tty.h" HINSTANCE ghInst; //global instance handle, for now. HWND hTTYWnd ; //global window handle BOOL bReading; PTTYINFO pTTYInfo ; COMMCONFIG cc; DCB dcb; COMMTIMEOUTS to; COMMPROP cp; HANDLE hComm, hThread; LPCSTR lpszCommName = "COM2"; //global variable to define the serial // COM port you will be using DWORD ReadThread (LPDWORD lpdwParam1); void locProcessCommError (DWORD dwError); void locProcessBytes (LPBYTE buf, DWORD dwBytes); #if !defined(_WIN32) #include #endif // Windows NT defines APIENTRY, but 3.x doesn't #if !defined (APIENTRY) #define APIENTRY far pascal #endif // Windows 3.x uses a FARPROC for dialogs #if !defined(_WIN32) #define DLGPROC FARPROC #endif char szDebug[100]; // // FUNCTION: WinMain(HINSTANCE, HINSTANCE, LPSTR, int) // // PURPOSE: calls initialization function, processes message loop // // COMMENTS: // // Windows recognizes this function by name as the initial entry point // for the program. This function calls the application initialization // routine, if no other instance of the program is running, and always // calls the instance initialization routine. It then executes a // message retrieval and dispatch loop that is the top-level control // structure for the remainder of execution. The loop is terminated // when a WM_QUIT message is received, at which time this function // exits the application instance by returning the value passed by // PostQuitMessage(). // // If this function must abort before entering the message loop, it // returns the conventional value NULL. // int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { MSG msg; DWORD id; BOOL bOldState = FALSE; OutputDebugString ("TTY Demo Program\n"); // Other instances of app running? if (!hPrevInstance) { // Initialize shared things if (!InitApplication(hInstance)) { return (FALSE); // Exits if unable to initialize } } if (NULL == (hTTYWnd = InitInstance( hInstance, nCmdShow ))) return ( FALSE ) ; ghInst = hInstance; CreateTTYInfo( hTTYWnd ); if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hTTYWnd,GWL_PTTYINFO ))) return ( FALSE ) ; /* open COM port #2 for reading and writing */ if ((hComm=CreateFile (lpszCommName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,NULL)) == INVALID_HANDLE_VALUE) { /* handle error */ MessageBox (NULL, "Error opening COM port","",MB_OK); return FALSE; } /* end if (error creating read thread) */ /* get comm properties */ cp.wPacketLength = sizeof(COMMPROP); GetCommProperties (hComm, &cp); /* create the thread for reading bytes */ bReading = TRUE; if ((hThread=CreateThread (NULL /*def security */, 0 /* def stack size */, (LPTHREAD_START_ROUTINE)ReadThread, NULL /* param to pass to thread */, 0, &id)) == INVALID_HANDLE_VALUE) { /* handle error */ MessageBox (NULL, "Error creating READ thread","",MB_OK); CloseHandle (hComm); return FALSE; } /* end if (error creating read thread) */ while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator (msg.hwnd, ghAccel, &msg)) { TranslateMessage(&msg);// Translates virtual key codes DispatchMessage(&msg); // Dispatches message to window } } /* end while (not a quit message) */ /* kill the read thread */ bReading = FALSE; /* in case the thread is not running, resume it now */ ResumeThread (hThread); /* wait for thread to die... */ while (GetExitCodeThread(hThread, &id)) { if (id == STILL_ACTIVE) continue; else break; } /* end while (no error reading thread exit code) */ CloseHandle (hThread); /* close COM port */ CloseHandle (hComm); /* clean up */ DestroyTTYInfo( hTTYWnd ) ; // Returns the value from PostQuitMessage return (msg.wParam); // This will prevent 'unused formal parameter' warnings lpCmdLine; } //--------------------------------------------------------------------------- // BOOL NEAR InitApplication( HANDLE hInstance ) // // Description: // First time initialization stuff. This registers information // such as window classes. // // Parameters: // HANDLE hInstance // Handle to this instance of the application. // //--------------------------------------------------------------------------- BOOL NEAR InitApplication( HANDLE hInstance ) { WNDCLASS wndclass ; // register tty window class wndclass.style = 0 ; wndclass.lpfnWndProc = TTYWndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = sizeof( DWORD ) ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( TTYICON ) ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ; wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ; wndclass.lpszMenuName = MAKEINTRESOURCE( TTYMENU ) ; wndclass.lpszClassName = gszTTYClass ; return( RegisterClass( &wndclass ) ) ; } // end of InitApplication() //--------------------------------------------------------------------------- // HWND NEAR InitInstance( HANDLE hInstance, int nCmdShow ) // // Description: // Initializes instance specific information. // // Parameters: // HANDLE hInstance // Handle to instance // // int nCmdShow // How do we show the window? // //--------------------------------------------------------------------------- HWND NEAR InitInstance( HANDLE hInstance, int nCmdShow ) { HWND hTTYWnd ; // load accelerators ghAccel = LoadAccelerators( hInstance, MAKEINTRESOURCE( TTYACCEL ) ) ; // create the TTY window hTTYWnd = CreateWindow( gszTTYClass, gszAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ) ; if (NULL == hTTYWnd) return ( NULL ) ; ShowWindow( hTTYWnd, nCmdShow ) ; UpdateWindow( hTTYWnd ) ; return ( hTTYWnd ) ; } // end of InitInstance() //--------------------------------------------------------------------------- // LRESULT FAR PASCAL TTYWndProc( HWND hWnd, UINT uMsg, // WPARAM wParam, LPARAM lParam ) // // Description: // This is the TTY Window Proc. This handles ALL messages // to the tty window. // // Parameters: // As documented for Window procedures. // //--------------------------------------------------------------------------- LRESULT FAR PASCAL TTYWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { LONG lrc; switch (uMsg) { case WM_CREATE: break; case WM_COMMAND: { switch ((DWORD) wParam) { case ID_SETTINGS_CONFIGURE: /* get current port settings */ lrc = sizeof(COMMCONFIG); GetCommConfig (hComm, &cc, &lrc); /* display dialog to modify settings */ if (!CommConfigDialog(lpszCommName,hWnd, &cc)) break; /* write new settings */ if (!SetCommState (hComm, &cc.dcb)) break; break; case IDM_ABOUT: GoModalDialogBoxParam ( GETHINST( hWnd ), MAKEINTRESOURCE( ABOUTDLGBOX ), hWnd, AboutDlgProc, 0 ) ; break; case IDM_EXIT: PostMessage( hWnd, WM_CLOSE, 0, 0L ) ; break ; } } break ; case WM_PAINT: PaintTTY( hWnd ) ; break ; case WM_SIZE: SizeTTY( hWnd, HIWORD( lParam ), LOWORD( lParam ) ) ; break ; case WM_HSCROLL: ScrollTTYHorz( hWnd, (WORD) wParam, LOWORD( lParam ) ) ; break ; case WM_VSCROLL: ScrollTTYVert( hWnd, (WORD) wParam, LOWORD( lParam ) ) ; break ; case WM_CHAR: /* echo to local window if echo turned on */ if (LOCALECHO (pTTYInfo)) { WriteTTYBlock(hWnd, (LPBYTE)&wParam, 1 ); } /* write out the character to the COM Port */ if (!WriteFile(hComm, (LPBYTE)&wParam, 1, &lrc, NULL)) { /* handle error */ locProcessCommError(GetLastError ()); } /* end if (error reading bytes) */ break ; case WM_SETFOCUS: SetTTYFocus( hWnd ) ; break ; case WM_KILLFOCUS: KillTTYFocus( hWnd ) ; break ; case WM_DESTROY: PostQuitMessage( 0 ) ; break ; case WM_CLOSE: if (IDOK != MessageBox( hWnd, "OK to close window?", "TTY Sample", MB_ICONQUESTION | MB_OKCANCEL )) break ; // fall through default: return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ; } return 0L ; } // end of TTYWndProc() //--------------------------------------------------------------------------- // DWORD ReadThread(LPDWORD lpdwParam1) // // Description: // Thread dedicated to reading bytes from the COM port // // // Parameters: // LPDWORD lpdwParam1 // Thread data (not used) // //--------------------------------------------------------------------------- /* This is an example of the overlapped, signalled reading of bytes from a COM port */ /*Note the use of FALSE in the last flag to GetOverlappResult, telling the function to return immediately if all the bytes requested have not been read. The alternative code section, which is compiled out with #if 0, has the same flag set TRUE. In t his case, GetOverlappedResult will not return until all the bytes are read Also note that use of this code for interactive terminals will produce an annoying "blockyness" as Windows waits for 10 bytes at a time. This can be fixed by setting the number of bytes to read to merely 1. */ /* THIS CODE REQUIRES THAT THE COM PORT BE OPENED FOR OVERLAPPED I/O */ DWORD ReadThread (LPDWORD lpdwParam1) { BYTE inbuff[100]; DWORD nBytesRead, endtime, lrc; static OVERLAPPED o; /* the next two lines check to make sure that total timeouts are supported */ if (!cp.dwProvCapabilities & PCF_TOTALTIMEOUTS) return 1L; /* the next four lines set the total timeout interval */ memset (&to, 0, sizeof(to)); to.ReadTotalTimeoutMultiplier = 5; to.ReadTotalTimeoutConstant = 1000; SetCommTimeouts (hComm, &to); /* create a manual-reset event */ o.hEvent = CreateEvent (NULL, /* lpsa */ TRUE, /* manual reset */ FALSE, /* init state non sig */ NULL); /* read loop */ while (bReading) { /* try to read 10 bytes */ if (!ReadFile(hComm, inbuff, 10, &nBytesRead, &o)) { /* if there are not ten bytes waiting in read buffer, then ERROR_IO_PENDING is returned */ /* if ReadFile failed, the number of returned bytes not valid, so zero out and wait to get correct number from GetOverlappedResult */ nBytesRead = 0; if ((lrc=GetLastError()) == ERROR_IO_PENDING) { #if 0 if (GetOverlappedResult(hComm, &o, &nBytesRead, TRUE)) { if (nBytesRead) locProcessBytes(inbuff, nBytesRead); } else { locProcessCommError(GetLastError ()); } #endif #if 1 /* wait 1 second for the ten bytes */ endtime = GetTickCount() + 1000; /* wait for overlapped I/O to complete */ while (!GetOverlappedResult(hComm, &o, &nBytesRead, FALSE)) { /* do additional processing here - perhaps get and displatch messages to keep the menus alive */ /* .... */ /* make sure timeout has not expired */ if (GetTickCount() > endtime) { break; } } /* end while (I/O still pending) */ /* if I/O retrieved some bytes, then process bytes */ if (nBytesRead) { locProcessBytes(inbuff, nBytesRead); } #endif } else { /* handle error */ locProcessCommError(GetLastError ()); } } /* end if (error reading bytes) */ else { if (nBytesRead) locProcessBytes(inbuff, nBytesRead); } /* manually reset event */ ResetEvent (o.hEvent); } /* end while (reading bytes) */ /* clean out any pending bytes in the receive buffer */ PurgeComm(hComm, PURGE_RXCLEAR); return 0L; } /* end function (ReadThread) */ void locProcessCommError (DWORD dwError) { LONG lrc; COMSTAT cs; /* clear error */ ClearCommError (hComm, &lrc, &cs); } /* end function (locProcessCommError) */ void locProcessBytes (LPBYTE buf, DWORD dwBytes) { WriteTTYBlock(hTTYWnd, buf, dwBytes); } /* end function (locProcessBytes) */ //--------------------------------------------------------------------------- // LRESULT NEAR CreateTTYInfo( HWND hWnd ) // // Description: // Creates the tty information structure and sets // menu option availability. Returns -1 if unsuccessful. // // Parameters: // HWND hWnd // Handle to main window. // //--------------------------------------------------------------------------- LRESULT NEAR CreateTTYInfo( HWND hWnd ) { PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) LocalAlloc( LPTR, sizeof( TTYINFO ) ))) return ( (LRESULT) -1 ) ; // initialize TTY info structure COMDEV( pTTYInfo ) = 0 ; CONNECTED( pTTYInfo ) = FALSE ; CURSORSTATE( pTTYInfo ) = CS_HIDE ; LOCALECHO( pTTYInfo ) = TRUE ; AUTOWRAP( pTTYInfo ) = TRUE ; PORT( pTTYInfo ) = 1 ; BAUDRATE( pTTYInfo ) = CBR_9600 ; BYTESIZE( pTTYInfo ) = 8 ; FLOWCTRL( pTTYInfo ) = FC_RTSCTS ; PARITY( pTTYInfo ) = NOPARITY ; STOPBITS( pTTYInfo ) = ONESTOPBIT ; XONXOFF( pTTYInfo ) = FALSE ; XSIZE( pTTYInfo ) = 0 ; YSIZE( pTTYInfo ) = 0 ; XSCROLL( pTTYInfo ) = 0 ; YSCROLL( pTTYInfo ) = 0 ; XOFFSET( pTTYInfo ) = 0 ; YOFFSET( pTTYInfo ) = 0 ; COLUMN( pTTYInfo ) = 0 ; ROW( pTTYInfo ) = 0 ; HTTYFONT( pTTYInfo ) = NULL ; FGCOLOR( pTTYInfo ) = RGB( 0, 0, 0 ) ; USECNRECEIVE( pTTYInfo ) = TRUE ; DISPLAYERRORS( pTTYInfo ) = TRUE ; NEWLINE (pTTYInfo) = TRUE ; // clear screen space memset( SCREEN( pTTYInfo ), ' ', MAXROWS * MAXCOLS ) ; // setup default font information LFTTYFONT( pTTYInfo ).lfHeight = 12 ; LFTTYFONT( pTTYInfo ).lfWidth = 0 ; LFTTYFONT( pTTYInfo ).lfEscapement = 0 ; LFTTYFONT( pTTYInfo ).lfOrientation = 0 ; LFTTYFONT( pTTYInfo ).lfWeight = 0 ; LFTTYFONT( pTTYInfo ).lfItalic = 0 ; LFTTYFONT( pTTYInfo ).lfUnderline = 0 ; LFTTYFONT( pTTYInfo ).lfStrikeOut = 0 ; LFTTYFONT( pTTYInfo ).lfCharSet = OEM_CHARSET ; LFTTYFONT( pTTYInfo ).lfOutPrecision = OUT_DEFAULT_PRECIS ; LFTTYFONT( pTTYInfo ).lfClipPrecision = CLIP_DEFAULT_PRECIS ; LFTTYFONT( pTTYInfo ).lfQuality = DEFAULT_QUALITY ; LFTTYFONT( pTTYInfo ).lfPitchAndFamily = FIXED_PITCH | FF_MODERN ; LFTTYFONT( pTTYInfo ).lfFaceName[0] = 0; // set TTYInfo handle before any further message processing. SetWindowLong( hWnd, GWL_PTTYINFO, (WPARAM) pTTYInfo ) ; // reset the character information, etc. ResetTTYScreen( hWnd, pTTYInfo ) ; return ( (LRESULT) TRUE ) ; } // end of CreateTTYInfo() //--------------------------------------------------------------------------- // BOOL NEAR DestroyTTYInfo( HWND hWnd ) // // Description: // Destroys block associated with TTY window handle. // // Parameters: // HWND hWnd // handle to TTY window // //--------------------------------------------------------------------------- BOOL NEAR DestroyTTYInfo( HWND hWnd ) { PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; DeleteObject( HTTYFONT( pTTYInfo ) ) ; LocalFree( pTTYInfo ) ; return ( TRUE ) ; } // end of DestroyTTYInfo() //--------------------------------------------------------------------------- // BOOL NEAR ResetTTYScreen( HWND hWnd, PTTYINFO pTTYInfo ) // // Description: // Resets the TTY character information and causes the // screen to resize to update the scroll information. // // Parameters: // PTTYINFO pTTYInfo // pointer to TTY info structure // //--------------------------------------------------------------------------- BOOL NEAR ResetTTYScreen( HWND hWnd, PTTYINFO pTTYInfo ) { HDC hDC ; TEXTMETRIC tm ; RECT rcWindow ; if (NULL == pTTYInfo) return ( FALSE ) ; if (NULL != HTTYFONT( pTTYInfo )) DeleteObject( HTTYFONT( pTTYInfo ) ) ; HTTYFONT( pTTYInfo ) = CreateFontIndirect( &LFTTYFONT( pTTYInfo ) ) ; hDC = GetDC( hWnd ) ; SelectObject( hDC, HTTYFONT( pTTYInfo ) ) ; GetTextMetrics( hDC, &tm ) ; ReleaseDC( hWnd, hDC ) ; XCHAR( pTTYInfo ) = tm.tmAveCharWidth ; YCHAR( pTTYInfo ) = tm.tmHeight + tm.tmExternalLeading ; // a slimy hack to force the scroll position, region to // be recalculated based on the new character sizes GetWindowRect( hWnd, &rcWindow ) ; SendMessage( hWnd, WM_SIZE, SIZENORMAL, (LPARAM) MAKELONG( rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top ) ) ; return ( TRUE ) ; } // end of ResetTTYScreen() //--------------------------------------------------------------------------- // BOOL NEAR PaintTTY( HWND hWnd ) // // Description: // Paints the rectangle determined by the paint struct of // the DC. // // Parameters: // HWND hWnd // handle to TTY window (as always) // //--------------------------------------------------------------------------- BOOL NEAR PaintTTY( HWND hWnd ) { int nRow, nCol, nEndRow, nEndCol, nCount, nHorzPos, nVertPos ; HDC hDC ; HFONT hOldFont ; PTTYINFO pTTYInfo ; PAINTSTRUCT ps ; RECT rect ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; hDC = BeginPaint( hWnd, &ps ) ; hOldFont = SelectObject( hDC, HTTYFONT( pTTYInfo ) ) ; SetTextColor( hDC, FGCOLOR( pTTYInfo ) ) ; SetBkColor( hDC, GetSysColor( COLOR_WINDOW ) ) ; rect = ps.rcPaint ; nRow = min( MAXROWS - 1, max( 0, (rect.top + YOFFSET( pTTYInfo )) / YCHAR( pTTYInfo ) ) ) ; nEndRow = min( MAXROWS - 1, ((rect.bottom + YOFFSET( pTTYInfo ) - 1) / YCHAR( pTTYInfo ) ) ) ; nCol = min( MAXCOLS - 1, max( 0, (rect.left + XOFFSET( pTTYInfo )) / XCHAR( pTTYInfo ) ) ) ; nEndCol = min( MAXCOLS - 1, ((rect.right + XOFFSET( pTTYInfo ) - 1) / XCHAR( pTTYInfo ) ) ) ; nCount = nEndCol - nCol + 1 ; for (; nRow <= nEndRow; nRow++) { nVertPos = (nRow * YCHAR( pTTYInfo )) - YOFFSET( pTTYInfo ) ; nHorzPos = (nCol * XCHAR( pTTYInfo )) - XOFFSET( pTTYInfo ) ; rect.top = nVertPos ; rect.bottom = nVertPos + YCHAR( pTTYInfo ) ; rect.left = nHorzPos ; rect.right = nHorzPos + XCHAR( pTTYInfo ) * nCount ; SetBkMode( hDC, OPAQUE ) ; ExtTextOut( hDC, nHorzPos, nVertPos, ETO_OPAQUE | ETO_CLIPPED, &rect, (LPSTR)( SCREEN( pTTYInfo ) + nRow * MAXCOLS + nCol ), nCount, NULL ) ; } SelectObject( hDC, hOldFont ) ; EndPaint( hWnd, &ps ) ; MoveTTYCursor( hWnd ) ; return ( TRUE ) ; } // end of PaintTTY() //--------------------------------------------------------------------------- // BOOL NEAR SizeTTY( HWND hWnd, WORD wVertSize, WORD wHorzSize ) // // Description: // Sizes TTY and sets up scrolling regions. // // Parameters: // HWND hWnd // handle to TTY window // // WORD wVertSize // new vertical size // // WORD wHorzSize // new horizontal size // //--------------------------------------------------------------------------- BOOL NEAR SizeTTY( HWND hWnd, WORD wVertSize, WORD wHorzSize ) { int nScrollAmt ; PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; YSIZE( pTTYInfo ) = (int) wVertSize ; YSCROLL( pTTYInfo ) = max( 0, (MAXROWS * YCHAR( pTTYInfo )) - YSIZE( pTTYInfo ) ) ; nScrollAmt = min( YSCROLL( pTTYInfo ), YOFFSET( pTTYInfo ) ) - YOFFSET( pTTYInfo ) ; ScrollWindow( hWnd, 0, -nScrollAmt, NULL, NULL ) ; YOFFSET( pTTYInfo ) = YOFFSET( pTTYInfo ) + nScrollAmt ; SetScrollPos( hWnd, SB_VERT, YOFFSET( pTTYInfo ), FALSE ) ; SetScrollRange( hWnd, SB_VERT, 0, YSCROLL( pTTYInfo ), TRUE ) ; XSIZE( pTTYInfo ) = (int) wHorzSize ; XSCROLL( pTTYInfo ) = max( 0, (MAXCOLS * XCHAR( pTTYInfo )) - XSIZE( pTTYInfo ) ) ; nScrollAmt = min( XSCROLL( pTTYInfo ), XOFFSET( pTTYInfo )) - XOFFSET( pTTYInfo ) ; ScrollWindow( hWnd, 0, -nScrollAmt, NULL, NULL ) ; XOFFSET( pTTYInfo ) = XOFFSET( pTTYInfo ) + nScrollAmt ; SetScrollPos( hWnd, SB_HORZ, XOFFSET( pTTYInfo ), FALSE ) ; SetScrollRange( hWnd, SB_HORZ, 0, XSCROLL( pTTYInfo ), TRUE ) ; InvalidateRect( hWnd, NULL, TRUE ) ; return ( TRUE ) ; } // end of SizeTTY() //--------------------------------------------------------------------------- // BOOL NEAR ScrollTTYVert( HWND hWnd, WORD wScrollCmd, WORD wScrollPos ) // // Description: // Scrolls TTY window vertically. // // Parameters: // HWND hWnd // handle to TTY window // // WORD wScrollCmd // type of scrolling we're doing // // WORD wScrollPos // scroll position // //--------------------------------------------------------------------------- BOOL NEAR ScrollTTYVert( HWND hWnd, WORD wScrollCmd, WORD wScrollPos ) { int nScrollAmt ; PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; switch (wScrollCmd) { case SB_TOP: nScrollAmt = -YOFFSET( pTTYInfo ) ; break ; case SB_BOTTOM: nScrollAmt = YSCROLL( pTTYInfo ) - YOFFSET( pTTYInfo ) ; break ; case SB_PAGEUP: nScrollAmt = -YSIZE( pTTYInfo ) ; break ; case SB_PAGEDOWN: nScrollAmt = YSIZE( pTTYInfo ) ; break ; case SB_LINEUP: nScrollAmt = -YCHAR( pTTYInfo ) ; break ; case SB_LINEDOWN: nScrollAmt = YCHAR( pTTYInfo ) ; break ; case SB_THUMBPOSITION: nScrollAmt = wScrollPos - YOFFSET( pTTYInfo ) ; break ; default: return ( FALSE ) ; } if ((YOFFSET( pTTYInfo ) + nScrollAmt) > YSCROLL( pTTYInfo )) nScrollAmt = YSCROLL( pTTYInfo ) - YOFFSET( pTTYInfo ) ; if ((YOFFSET( pTTYInfo ) + nScrollAmt) < 0) nScrollAmt = -YOFFSET( pTTYInfo ) ; ScrollWindow( hWnd, 0, -nScrollAmt, NULL, NULL ) ; YOFFSET( pTTYInfo ) = YOFFSET( pTTYInfo ) + nScrollAmt ; SetScrollPos( hWnd, SB_VERT, YOFFSET( pTTYInfo ), TRUE ) ; return ( TRUE ) ; } // end of ScrollTTYVert() //--------------------------------------------------------------------------- // BOOL NEAR ScrollTTYHorz( HWND hWnd, WORD wScrollCmd, WORD wScrollPos ) // // Description: // Scrolls TTY window horizontally. // // Parameters: // HWND hWnd // handle to TTY window // // WORD wScrollCmd // type of scrolling we're doing // // WORD wScrollPos // scroll position // //--------------------------------------------------------------------------- BOOL NEAR ScrollTTYHorz( HWND hWnd, WORD wScrollCmd, WORD wScrollPos ) { int nScrollAmt ; PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; switch (wScrollCmd) { case SB_TOP: nScrollAmt = -XOFFSET( pTTYInfo ) ; break ; case SB_BOTTOM: nScrollAmt = XSCROLL( pTTYInfo ) - XOFFSET( pTTYInfo ) ; break ; case SB_PAGEUP: nScrollAmt = -XSIZE( pTTYInfo ) ; break ; case SB_PAGEDOWN: nScrollAmt = XSIZE( pTTYInfo ) ; break ; case SB_LINEUP: nScrollAmt = -XCHAR( pTTYInfo ) ; break ; case SB_LINEDOWN: nScrollAmt = XCHAR( pTTYInfo ) ; break ; case SB_THUMBPOSITION: nScrollAmt = wScrollPos - XOFFSET( pTTYInfo ) ; break ; default: return ( FALSE ) ; } if ((XOFFSET( pTTYInfo ) + nScrollAmt) > XSCROLL( pTTYInfo )) nScrollAmt = XSCROLL( pTTYInfo ) - XOFFSET( pTTYInfo ) ; if ((XOFFSET( pTTYInfo ) + nScrollAmt) < 0) nScrollAmt = -XOFFSET( pTTYInfo ) ; ScrollWindow( hWnd, -nScrollAmt, 0, NULL, NULL ) ; XOFFSET( pTTYInfo ) = XOFFSET( pTTYInfo ) + nScrollAmt ; SetScrollPos( hWnd, SB_HORZ, XOFFSET( pTTYInfo ), TRUE ) ; return ( TRUE ) ; } // end of ScrollTTYHorz() //--------------------------------------------------------------------------- // BOOL NEAR SetTTYFocus( HWND hWnd ) // // Description: // Sets the focus to the TTY window also creates caret. // // Parameters: // HWND hWnd // handle to TTY window // //--------------------------------------------------------------------------- BOOL NEAR SetTTYFocus( HWND hWnd ) { PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; if (CURSORSTATE( pTTYInfo ) != CS_SHOW) { CreateCaret( hWnd, NULL, XCHAR( pTTYInfo ), YCHAR( pTTYInfo ) ) ; ShowCaret( hWnd ) ; CURSORSTATE( pTTYInfo ) = CS_SHOW ; } MoveTTYCursor( hWnd ) ; return ( TRUE ) ; } // end of SetTTYFocus() //--------------------------------------------------------------------------- // BOOL NEAR KillTTYFocus( HWND hWnd ) // // Description: // Kills TTY focus and destroys the caret. // // Parameters: // HWND hWnd // handle to TTY window // //--------------------------------------------------------------------------- BOOL NEAR KillTTYFocus( HWND hWnd ) { PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; if (CURSORSTATE( pTTYInfo ) != CS_HIDE) { HideCaret( hWnd ) ; DestroyCaret() ; CURSORSTATE( pTTYInfo ) = CS_HIDE ; } return ( TRUE ) ; } // end of KillTTYFocus() //--------------------------------------------------------------------------- // BOOL NEAR MoveTTYCursor( HWND hWnd ) // // Description: // Moves caret to current position. // // Parameters: // HWND hWnd // handle to TTY window // //--------------------------------------------------------------------------- BOOL NEAR MoveTTYCursor( HWND hWnd ) { PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; if (CURSORSTATE( pTTYInfo ) & CS_SHOW) SetCaretPos( (COLUMN( pTTYInfo ) * XCHAR( pTTYInfo )) - XOFFSET( pTTYInfo ), (ROW( pTTYInfo ) * YCHAR( pTTYInfo )) - YOFFSET( pTTYInfo ) ) ; return ( TRUE ) ; } // end of MoveTTYCursor() //--------------------------------------------------------------------------- // BOOL WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength ) // // Description: // Writes block to TTY screen. Nothing fancy - just // straight TTY. // // Parameters: // HWND hWnd // handle to TTY window // // LPSTR lpBlock // far pointer to block of data // // int nLength // length of block // //--------------------------------------------------------------------------- BOOL WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength ) { int i ; PTTYINFO pTTYInfo ; RECT rect ; if (NULL == (pTTYInfo = (PTTYINFO) GetWindowLong( hWnd, GWL_PTTYINFO ))) return ( FALSE ) ; for (i = 0 ; i < nLength; i++) { switch (lpBlock[ i ]) { case ASCII_BEL: // Bell MessageBeep( 0 ) ; break ; case ASCII_BS: // Backspace if (COLUMN( pTTYInfo ) > 0) COLUMN( pTTYInfo ) -- ; MoveTTYCursor( hWnd ) ; break ; case ASCII_CR: // Carriage return COLUMN( pTTYInfo ) = 0 ; MoveTTYCursor( hWnd ) ; if (!NEWLINE( pTTYInfo )) break; // fall through case ASCII_LF: // Line feed if (ROW( pTTYInfo )++ == MAXROWS - 1) { memmove( (LPSTR) (SCREEN( pTTYInfo )), (LPSTR) (SCREEN( pTTYInfo ) + MAXCOLS), (MAXROWS - 1) * MAXCOLS ) ; memset( (LPSTR) (SCREEN( pTTYInfo ) + (MAXROWS - 1) * MAXCOLS), ' ', MAXCOLS ) ; InvalidateRect( hWnd, NULL, FALSE ) ; ROW( pTTYInfo )-- ; } MoveTTYCursor( hWnd ) ; break ; default: *(SCREEN( pTTYInfo ) + ROW( pTTYInfo ) * MAXCOLS + COLUMN( pTTYInfo )) = lpBlock[ i ] ; rect.left = (COLUMN( pTTYInfo ) * XCHAR( pTTYInfo )) - XOFFSET( pTTYInfo ) ; rect.right = rect.left + XCHAR( pTTYInfo ) ; rect.top = (ROW( pTTYInfo ) * YCHAR( pTTYInfo )) - YOFFSET( pTTYInfo ) ; rect.bottom = rect.top + YCHAR( pTTYInfo ) ; InvalidateRect( hWnd, &rect, FALSE ) ; // Line wrap if (COLUMN( pTTYInfo ) < MAXCOLS - 1) COLUMN( pTTYInfo )++ ; else if (AUTOWRAP( pTTYInfo )) WriteTTYBlock( hWnd, "\r\n", 2 ) ; break; } } return ( TRUE ) ; } // end of WriteTTYBlock() //--------------------------------------------------------------------------- // VOID GoModalDialogBoxParam( HINSTANCE hInstance, // LPCSTR lpszTemplate, HWND hWnd, // DLGPROC lpDlgProc, LPARAM lParam ) // // Description: // It is a simple utility function that simply performs the // MPI and invokes the dialog box with a DWORD paramter. // // Parameters: // similar to that of DialogBoxParam() with the exception // that the lpDlgProc is not a procedure instance // //--------------------------------------------------------------------------- VOID GoModalDialogBoxParam( HINSTANCE hInstance, LPCSTR lpszTemplate, HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam ) { DLGPROC lpProcInstance ; lpProcInstance = (DLGPROC) MakeProcInstance( (FARPROC) lpDlgProc, hInstance ) ; DialogBoxParam( hInstance, lpszTemplate, hWnd, lpProcInstance, lParam ) ; FreeProcInstance( (FARPROC) lpProcInstance ) ; } // end of GoModalDialogBoxParam() //--------------------------------------------------------------------------- // BOOL FAR PASCAL AboutDlgProc( HWND hDlg, UINT uMsg, // WPARAM wParam, LPARAM lParam ) // // Description: // Simulates the Windows System Dialog Box. // // Parameters: // Same as standard dialog procedures. // //--------------------------------------------------------------------------- BOOL FAR PASCAL AboutDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { int idModeString ; char szBuffer[ MAXLEN_TEMPSTR ], szTemp[ MAXLEN_TEMPSTR ] ; DWORD dwFreeMemory; WORD wRevision, wVersion ; #ifdef ABOUTDLG_USEBITMAP // if we are using the bitmap, hide the icon ShowWindow( GetDlgItem( hDlg, IDD_ABOUTICON ), SW_HIDE ) ; #endif // sets up the version number for Windows wVersion = LOWORD( GetVersion() ) ; switch (HIBYTE( wVersion )) { case 10: wRevision = 1 ; break ; default: wRevision = 0 ; break; } wVersion &= 0xFF ; GetDlgItemText( hDlg, IDD_TITLELINE, szTemp, sizeof( szTemp ) ) ; wsprintf( szBuffer, szTemp, wVersion, wRevision ) ; SetDlgItemText( hDlg, IDD_TITLELINE, szBuffer ) ; // sets up version number for TTY GetDlgItemText( hDlg, IDD_VERSION, szTemp, sizeof( szTemp ) ) ; wsprintf( szBuffer, szTemp, VER_MAJOR, VER_MINOR, VER_BUILD ) ; SetDlgItemText( hDlg, IDD_VERSION, (LPSTR) szBuffer ) ; // get by-line LoadString( GETHINST( hDlg ), IDS_BYLINE, szBuffer, sizeof( szBuffer ) ) ; SetDlgItemText( hDlg, IDD_BYLINE, szBuffer ) ; LoadString( GETHINST( hDlg ), idModeString, szBuffer, sizeof( szBuffer ) ) ; SetDlgItemText( hDlg, IDD_WINDOWSMODE, szBuffer ) ; // get free memory information dwFreeMemory = GetFreeSpace( 0 ) / 1024L ; GetDlgItemText( hDlg, IDD_FREEMEM, szTemp, sizeof( szTemp ) ) ; wsprintf( szBuffer, szTemp, dwFreeMemory ) ; SetDlgItemText( hDlg, IDD_FREEMEM, (LPSTR) szBuffer ) ; } return ( TRUE ) ; #ifdef ABOUTDLG_USEBITMAP // used to paint the bitmap case WM_PAINT: { HBITMAP hBitMap ; HDC hDC, hMemDC ; PAINTSTRUCT ps ; // load bitmap and display it hDC = BeginPaint( hDlg, &ps ) ; if (NULL != (hMemDC = CreateCompatibleDC( hDC ))) { hBitMap = LoadBitmap( GETHINST( hDlg ), MAKEINTRESOURCE( TTYBITMAP ) ) ; hBitMap = SelectObject( hMemDC, hBitMap ) ; BitBlt( hDC, 10, 10, 64, 64, hMemDC, 0, 0, SRCCOPY ) ; DeleteObject( SelectObject( hMemDC, hBitMap ) ) ; DeleteDC( hMemDC ) ; } EndPaint( hDlg, &ps ) ; } break ; #endif case WM_COMMAND: if ((WORD) wParam == IDD_OK) { EndDialog( hDlg, TRUE ) ; return ( TRUE ) ; } break; } return ( FALSE ) ; } // end of AboutDlgProc() //--------------------------------------------------------------------------- // VOID FillComboBox( HINSTANCE hInstance, HWND hCtrlWnd, int nIDString, // DWORD *npTable, WORD wTableLen, // WORD wCurrentSetting ) // // Description: // Fills the given combo box with strings from the resource // table starting at nIDString. Associated items are // added from given table. The combo box is notified of // the current setting. // // Parameters: // HINSTANCE hInstance // handle to application instance // // HWND hCtrlWnd // handle to combo box control // // int nIDString // first resource string id // // WORD *npTable // near point to table of associated values // // WORD wTableLen // length of table // // WORD wCurrentSetting // current setting (for combo box selection) // //--------------------------------------------------------------------------- VOID FillComboBox( HINSTANCE hInstance, HWND hCtrlWnd, int nIDString, DWORD *npTable, WORD wTableLen, WORD wCurrentSetting ) { char szBuffer[ MAXLEN_TEMPSTR ] ; WORD wCount, wPosition ; for (wCount = 0; wCount < wTableLen; wCount++) { // load the string from the string resources and // add it to the combo box LoadString( hInstance, nIDString + wCount, szBuffer, sizeof( szBuffer ) ) ; wPosition = LOWORD( SendMessage( hCtrlWnd, CB_ADDSTRING, 0, (LPARAM) (LPSTR) szBuffer ) ) ; // use item data to store the actual table value SendMessage( hCtrlWnd, CB_SETITEMDATA, (WPARAM) wPosition, (LPARAM) (LONG) *(npTable + wCount) ) ; // if this is our current setting, select it if (*(npTable + wCount) == wCurrentSetting) SendMessage( hCtrlWnd, CB_SETCURSEL, (WPARAM) wPosition, 0 ) ; } } // end of FillComboBox() //--------------------------------------------------------------------------- // BOOL SelectTTYFont( HWND hDlg ) // // Description: // Selects the current font for the TTY screen. // Uses the Common Dialog ChooseFont() API. // // Parameters: // HWND hDlg // handle to settings dialog // //--------------------------------------------------------------------------- BOOL SelectTTYFont( HWND hDlg ) { CHOOSEFONT cfTTYFont ; PTTYINFO pTTYInfo ; if (NULL == (pTTYInfo = (PTTYINFO) GET_PROP( hDlg, ATOM_TTYINFO ))) return ( FALSE ) ; cfTTYFont.lStructSize = sizeof( CHOOSEFONT ) ; cfTTYFont.hwndOwner = hDlg ; cfTTYFont.hDC = NULL ; cfTTYFont.rgbColors = FGCOLOR( pTTYInfo ) ; cfTTYFont.lpLogFont = &LFTTYFONT( pTTYInfo ) ; cfTTYFont.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ; cfTTYFont.lCustData = 0 ; cfTTYFont.lpfnHook = NULL ; cfTTYFont.lpTemplateName = NULL ; cfTTYFont.hInstance = GETHINST( hDlg ) ; if (ChooseFont( &cfTTYFont )) { FGCOLOR( pTTYInfo ) = cfTTYFont.rgbColors ; ResetTTYScreen( GetParent( hDlg ), pTTYInfo ) ; } return ( TRUE ) ; } // end of SelectTTYFont() //--------------------------------------------------------------------------- // End of File: tty.c //---------------------------------------------------------------------------