home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / io / serial / tty.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  63KB  |  2,018 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples.
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved.
  6. *       This source code is only intended as a supplement to
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. //---------------------------------------------------------------------------
  13. //
  14. //  Module: tty.c
  15. //
  16. //  Purpose:
  17. //     The sample application demonstrates the usage of the COMM
  18. //     API.  It implements the new COMM API of Windows 3.1.
  19. //
  20. //     NOTE:  no escape sequences are translated, only
  21. //            the necessary control codes (LF, CR, BS, etc.)
  22. //
  23. //  Description of functions:
  24. //     Descriptions are contained in the function headers.
  25. //
  26. //---------------------------------------------------------------------------
  27. //
  28. //  Written by Microsoft Product Support Services, Windows Developer Support.
  29. //
  30. //---------------------------------------------------------------------------
  31.  
  32. #include "tty.h"
  33.  
  34. //---------------------------------------------------------------------------
  35. //  int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
  36. //                      LPSTR lpszCmdLine, int nCmdShow )
  37. //
  38. //  Description:
  39. //     This is the main window loop!
  40. //
  41. //  Parameters:
  42. //     As documented for all WinMain() functions.
  43. //
  44. //---------------------------------------------------------------------------
  45.  
  46. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  47.                     LPSTR lpszCmdLine, int nCmdShow )
  48. {
  49.    MSG   msg ;
  50.  
  51.    if (!hPrevInstance)
  52.       if (!InitApplication( hInstance ))
  53.          return ( FALSE ) ;
  54.  
  55.    if (NULL == (hTTYWnd = InitInstance( hInstance, nCmdShow )))
  56.       return ( FALSE ) ;
  57.  
  58.    while (GetMessage( &msg, NULL, 0, 0 ))
  59.    {
  60.       if (!TranslateAccelerator( hTTYWnd, ghAccel, &msg ))
  61.       {
  62.          TranslateMessage( &msg ) ;
  63.          DispatchMessage( &msg ) ;
  64.       }
  65.    }
  66.    return ( (int) msg.wParam ) ;
  67.  
  68. } // end of WinMain()
  69.  
  70. //---------------------------------------------------------------------------
  71. //  BOOL NEAR InitApplication( HANDLE hInstance )
  72. //
  73. //  Description:
  74. //     First time initialization stuff.  This registers information
  75. //     such as window classes.
  76. //
  77. //  Parameters:
  78. //     HANDLE hInstance
  79. //        Handle to this instance of the application.
  80. //
  81. //---------------------------------------------------------------------------
  82.  
  83. BOOL NEAR InitApplication( HANDLE hInstance )
  84. {
  85.    WNDCLASS  wndclass ;
  86.  
  87.    // register tty window class
  88.  
  89.    wndclass.style =         0 ;
  90.    wndclass.lpfnWndProc =   TTYWndProc ;
  91.    wndclass.cbClsExtra =    0 ;
  92.    wndclass.cbWndExtra =    TTYEXTRABYTES ;
  93.    wndclass.hInstance =     hInstance ;
  94.    wndclass.hIcon =         LoadIcon( hInstance, MAKEINTRESOURCE( TTYICON ) );
  95.    wndclass.hCursor =       LoadCursor( NULL, IDC_ARROW ) ;
  96.    wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
  97.    wndclass.lpszMenuName =  MAKEINTRESOURCE( TTYMENU ) ;
  98.    wndclass.lpszClassName = gszTTYClass ;
  99.  
  100.    return( RegisterClass( &wndclass ) ) ;
  101.  
  102. } // end of InitApplication()
  103.  
  104. //---------------------------------------------------------------------------
  105. //  HWND NEAR InitInstance( HANDLE hInstance, int nCmdShow )
  106. //
  107. //  Description:
  108. //     Initializes instance specific information.
  109. //
  110. //  Parameters:
  111. //     HANDLE hInstance
  112. //        Handle to instance
  113. //
  114. //     int nCmdShow
  115. //        How do we show the window?
  116. //
  117. //---------------------------------------------------------------------------
  118.  
  119. HWND NEAR InitInstance( HANDLE hInstance, int nCmdShow )
  120. {
  121.    HWND  hTTYWnd ;
  122.  
  123.    // load accelerators
  124.    ghAccel = LoadAccelerators( hInstance, MAKEINTRESOURCE( TTYACCEL ) ) ;
  125.  
  126.    // create the TTY window
  127.    hTTYWnd = CreateWindow( gszTTYClass, gszAppName,
  128.                            WS_OVERLAPPEDWINDOW,
  129.                            CW_USEDEFAULT, CW_USEDEFAULT,
  130.                            CW_USEDEFAULT, CW_USEDEFAULT,
  131.                            NULL, NULL, hInstance, NULL ) ;
  132.  
  133.    if (NULL == hTTYWnd)
  134.       return ( NULL ) ;
  135.  
  136.    ShowWindow( hTTYWnd, nCmdShow ) ;
  137.    UpdateWindow( hTTYWnd ) ;
  138.  
  139.    return ( hTTYWnd ) ;
  140.  
  141. } // end of InitInstance()
  142.  
  143. //---------------------------------------------------------------------------
  144. //  LRESULT FAR PASCAL TTYWndProc( HWND hWnd, UINT uMsg,
  145. //                                 WPARAM wParam, LPARAM lParam )
  146. //
  147. //  Description:
  148. //     This is the TTY Window Proc.  This handles ALL messages
  149. //     to the tty window.
  150. //
  151. //  Parameters:
  152. //     As documented for Window procedures.
  153. //
  154. //  Win-32 Porting Issues:
  155. //     - WM_HSCROLL and WM_VSCROLL packing is different under Win-32.
  156. //     - Needed LOWORD() of wParam for WM_CHAR messages.
  157. //
  158. //---------------------------------------------------------------------------
  159.  
  160. LRESULT FAR PASCAL TTYWndProc( HWND hWnd, UINT uMsg,
  161.                                WPARAM wParam, LPARAM lParam )
  162. {
  163.  
  164.    DWORD dwBlockSize=512;
  165.    char * szBuffer;
  166.  
  167.    switch (uMsg)
  168.    {
  169.  
  170.       case WM_CREATE:
  171.          return ( CreateTTYInfo( hWnd ) ) ;
  172.  
  173.       case WM_COMMAND:
  174.       {
  175.          switch ( LOWORD( wParam ) )
  176.          {
  177.             case IDM_CONNECT:
  178.                if (!OpenConnection( hWnd ))
  179.                   MessageBox( hWnd, "Connection failed.", gszAppName,
  180.                               MB_ICONEXCLAMATION ) ;
  181.                break ;
  182.  
  183.             case IDM_DISCONNECT:
  184.                KillTTYFocus( hWnd ) ;
  185.                CloseConnection( hWnd ) ;
  186.                break ;
  187.  
  188.             case IDM_SETTINGS:
  189.             {
  190.                NPTTYINFO  npTTYInfo ;
  191.  
  192.                if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  193.                   return ( FALSE ) ;
  194.                GoModalDialogBoxParam( GETHINST( hWnd ),
  195.                                       MAKEINTRESOURCE( SETTINGSDLGBOX ), hWnd,
  196.                                       (DLGPROC) SettingsDlgProc,
  197.                                       (LPARAM) (LPSTR) npTTYInfo ) ;
  198.  
  199.                // if fConnected, set new COM parameters
  200.  
  201.                if (CONNECTED( npTTYInfo ))
  202.                {
  203.                   if (!SetupConnection( hWnd ))
  204.                      MessageBox( hWnd, "Settings failed!", gszAppName,
  205.                                  MB_ICONEXCLAMATION ) ;
  206.                }
  207.             }
  208.             break ;
  209.  
  210.             case IDM_SENDBLOCK:
  211.                // This function is very useful to test how
  212.                // your comm application handles large blocks
  213.                // of data
  214.  
  215.                szBuffer = malloc(dwBlockSize);
  216.                memset(szBuffer, 'X', dwBlockSize);
  217.                WriteCommBlock( hWnd, szBuffer, dwBlockSize);
  218.                free(szBuffer);
  219.  
  220.                break;
  221.  
  222.             case IDM_ABOUT:
  223.                GoModalDialogBoxParam ( GETHINST( hWnd ),
  224.                                        MAKEINTRESOURCE( ABOUTDLGBOX ),
  225.                                        hWnd,
  226.                                        (DLGPROC) AboutDlgProc, 0L ) ;
  227.                break;
  228.  
  229.             case IDM_EXIT:
  230.                PostMessage( hWnd, WM_CLOSE, 0, 0L ) ;
  231.                break ;
  232.          }
  233.       }
  234.       break ;
  235.  
  236.       case WM_PAINT:
  237.          PaintTTY( hWnd ) ;
  238.          break ;
  239.  
  240.       case WM_SIZE:
  241.          SizeTTY( hWnd, HIWORD( lParam ), LOWORD( lParam ) ) ;
  242.          break ;
  243.  
  244.       case WM_HSCROLL:
  245.          ScrollTTYHorz( hWnd, LOWORD( wParam ), HIWORD( wParam ) ) ;
  246.          break ;
  247.  
  248.       case WM_VSCROLL:
  249.          ScrollTTYVert( hWnd, LOWORD( wParam ), HIWORD( wParam ) ) ;
  250.          break ;
  251.  
  252.       case WM_CHAR:
  253.          ProcessTTYCharacter( hWnd, LOBYTE( LOWORD( wParam ) ) ) ;
  254.          break ;
  255.  
  256.       case WM_SETFOCUS:
  257.          SetTTYFocus( hWnd ) ;
  258.          break ;
  259.  
  260.       case WM_KILLFOCUS:
  261.          KillTTYFocus( hWnd ) ;
  262.          break ;
  263.  
  264.       case WM_DESTROY:
  265.          DestroyTTYInfo( hWnd ) ;
  266.          PostQuitMessage( 0 ) ;
  267.          break ;
  268.  
  269.       case WM_CLOSE:
  270.          if (IDOK != MessageBox( hWnd, "OK to close window?", "TTY Sample",
  271.                                  MB_ICONQUESTION | MB_OKCANCEL ))
  272.             break ;
  273.  
  274.          // fall through
  275.  
  276.       default:
  277.          return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
  278.    }
  279.    return 0L ;
  280.  
  281. } // end of TTYWndProc()
  282.  
  283. //---------------------------------------------------------------------------
  284. //  LRESULT NEAR CreateTTYInfo( HWND hWnd )
  285. //
  286. //  Description:
  287. //     Creates the tty information structure and sets
  288. //     menu option availability.  Returns -1 if unsuccessful.
  289. //
  290. //  Parameters:
  291. //     HWND  hWnd
  292. //        Handle to main window.
  293. //
  294. //  Win-32 Porting Issues:
  295. //     - Needed to initialize TERMWND( npTTYInfo ) for secondary thread.
  296. //     - Needed to create/initialize overlapped structures used in reads &
  297. //       writes to COMM device.
  298. //
  299. //---------------------------------------------------------------------------
  300.  
  301. LRESULT NEAR CreateTTYInfo( HWND hWnd )
  302. {
  303.    HMENU       hMenu ;
  304.    NPTTYINFO   npTTYInfo ;
  305.  
  306.    if (NULL == (npTTYInfo =
  307.                    (NPTTYINFO) LocalAlloc( LPTR, sizeof( TTYINFO ) )))
  308.       return ( (LRESULT) -1 ) ;
  309.  
  310.    // initialize TTY info structure
  311.  
  312.    COMDEV( npTTYInfo )        = 0 ;
  313.    CONNECTED( npTTYInfo )     = FALSE ;
  314.    CURSORSTATE( npTTYInfo )   = CS_HIDE ;
  315.    LOCALECHO( npTTYInfo )     = FALSE ;
  316.    AUTOWRAP( npTTYInfo )      = TRUE ;
  317.    PORT( npTTYInfo )          = 1 ;
  318.    BAUDRATE( npTTYInfo )      = CBR_9600 ;
  319.    BYTESIZE( npTTYInfo )      = 8 ;
  320.    //FLOWCTRL( npTTYInfo )      = FC_RTSCTS ;
  321.    FLOWCTRL( npTTYInfo )      = FC_XONXOFF ;
  322.    PARITY( npTTYInfo )        = NOPARITY ;
  323.    STOPBITS( npTTYInfo )      = ONESTOPBIT ;
  324.    XONXOFF( npTTYInfo )       = FALSE ;
  325.    XSIZE( npTTYInfo )         = 0 ;
  326.    YSIZE( npTTYInfo )         = 0 ;
  327.    XSCROLL( npTTYInfo )       = 0 ;
  328.    YSCROLL( npTTYInfo )       = 0 ;
  329.    XOFFSET( npTTYInfo )       = 0 ;
  330.    YOFFSET( npTTYInfo )       = 0 ;
  331.    COLUMN( npTTYInfo )        = 0 ;
  332.    ROW( npTTYInfo )           = 0 ;
  333.    HTTYFONT( npTTYInfo )      = NULL ;
  334.    FGCOLOR( npTTYInfo )       = RGB( 0, 0, 0 ) ;
  335.    USECNRECEIVE( npTTYInfo )  = TRUE ;
  336.    DISPLAYERRORS( npTTYInfo ) = TRUE ;
  337.    WRITE_OS( npTTYInfo ).Offset = 0 ;
  338.    WRITE_OS( npTTYInfo ).OffsetHigh = 0 ;
  339.    READ_OS( npTTYInfo ).Offset = 0 ;
  340.    READ_OS( npTTYInfo ).OffsetHigh = 0 ;
  341.    TERMWND( npTTYInfo ) =       hWnd ;
  342.  
  343.    // create I/O event used for overlapped reads / writes
  344.  
  345.    READ_OS( npTTYInfo ).hEvent = CreateEvent( NULL,    // no security
  346.                                               TRUE,    // explicit reset req
  347.                                               FALSE,   // initial event reset
  348.                                               NULL ) ; // no name
  349.    if (READ_OS( npTTYInfo ).hEvent == NULL)
  350.    {
  351.       LocalFree( npTTYInfo ) ;
  352.       return ( -1 ) ;
  353.    }
  354.    WRITE_OS( npTTYInfo ).hEvent = CreateEvent( NULL,    // no security
  355.                                                TRUE,    // explicit reset req
  356.                                                FALSE,   // initial event reset
  357.                                                NULL ) ; // no name
  358.    if (NULL == WRITE_OS( npTTYInfo ).hEvent)
  359.    {
  360.       CloseHandle( READ_OS( npTTYInfo ).hEvent ) ;
  361.       LocalFree( npTTYInfo ) ;
  362.       return ( -1 ) ;
  363.    }
  364.  
  365.    // clear screen space
  366.  
  367.    _fmemset( SCREEN( npTTYInfo ), ' ', MAXROWS * MAXCOLS ) ;
  368.  
  369.    // setup default font information
  370.  
  371.    LFTTYFONT( npTTYInfo ).lfHeight =         9 ;
  372.    LFTTYFONT( npTTYInfo ).lfWidth =          0 ;
  373.    LFTTYFONT( npTTYInfo ).lfEscapement =     0 ;
  374.    LFTTYFONT( npTTYInfo ).lfOrientation =    0 ;
  375.    LFTTYFONT( npTTYInfo ).lfWeight =         0 ;
  376.    LFTTYFONT( npTTYInfo ).lfItalic =         0 ;
  377.    LFTTYFONT( npTTYInfo ).lfUnderline =      0 ;
  378.    LFTTYFONT( npTTYInfo ).lfStrikeOut =      0 ;
  379.    LFTTYFONT( npTTYInfo ).lfCharSet =        OEM_CHARSET ;
  380.    LFTTYFONT( npTTYInfo ).lfOutPrecision =   OUT_DEFAULT_PRECIS ;
  381.    LFTTYFONT( npTTYInfo ).lfClipPrecision =  CLIP_DEFAULT_PRECIS ;
  382.    LFTTYFONT( npTTYInfo ).lfQuality =        DEFAULT_QUALITY ;
  383.    LFTTYFONT( npTTYInfo ).lfPitchAndFamily = FIXED_PITCH | FF_MODERN ;
  384.    lstrcpy( LFTTYFONT( npTTYInfo ).lfFaceName, "FixedSys" ) ;
  385.  
  386.    // set TTYInfo handle before any further message processing.
  387.  
  388.    SETNPTTYINFO( hWnd, npTTYInfo ) ;
  389.  
  390.    // reset the character information, etc.
  391.  
  392.    ResetTTYScreen( hWnd, npTTYInfo ) ;
  393.  
  394.    hMenu = GetMenu( hWnd ) ;
  395.    EnableMenuItem( hMenu, IDM_DISCONNECT,
  396.                    MF_GRAYED | MF_DISABLED | MF_BYCOMMAND ) ;
  397.    EnableMenuItem( hMenu, IDM_CONNECT, MF_ENABLED | MF_BYCOMMAND ) ;
  398.  
  399.    return ( (LRESULT) TRUE ) ;
  400.  
  401. } // end of CreateTTYInfo()
  402.  
  403. //---------------------------------------------------------------------------
  404. //  BOOL NEAR DestroyTTYInfo( HWND hWnd )
  405. //
  406. //  Description:
  407. //     Destroys block associated with TTY window handle.
  408. //
  409. //  Parameters:
  410. //     HWND hWnd
  411. //        handle to TTY window
  412. //
  413. //  Win-32 Porting Issues:
  414. //     - Needed to clean up event objects created during initialization.
  415. //
  416. //---------------------------------------------------------------------------
  417.  
  418. BOOL NEAR DestroyTTYInfo( HWND hWnd )
  419. {
  420.    NPTTYINFO npTTYInfo ;
  421.  
  422.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  423.       return ( FALSE ) ;
  424.  
  425.    // force connection closed (if not already closed)
  426.  
  427.    if (CONNECTED( npTTYInfo ))
  428.       CloseConnection( hWnd ) ;
  429.  
  430.    // clean up event objects
  431.  
  432.    CloseHandle( READ_OS( npTTYInfo ).hEvent ) ;
  433.    CloseHandle( WRITE_OS( npTTYInfo ).hEvent ) ;
  434.    CloseHandle( POSTEVENT( npTTYInfo ) ) ;
  435.  
  436.    DeleteObject( HTTYFONT( npTTYInfo ) ) ;
  437.  
  438.    LocalFree( npTTYInfo ) ;
  439.    return ( TRUE ) ;
  440.  
  441. } // end of DestroyTTYInfo()
  442.  
  443. //---------------------------------------------------------------------------
  444. //  BOOL NEAR ResetTTYScreen( HWND hWnd, NPTTYINFO npTTYInfo )
  445. //
  446. //  Description:
  447. //     Resets the TTY character information and causes the
  448. //     screen to resize to update the scroll information.
  449. //
  450. //  Parameters:
  451. //     NPTTYINFO  npTTYInfo
  452. //        pointer to TTY info structure
  453. //
  454. //---------------------------------------------------------------------------
  455.  
  456. BOOL NEAR ResetTTYScreen( HWND hWnd, NPTTYINFO npTTYInfo )
  457. {
  458.    HDC         hDC ;
  459.    TEXTMETRIC  tm ;
  460.    RECT        rcWindow ;
  461.  
  462.    if (NULL == npTTYInfo)
  463.       return ( FALSE ) ;
  464.  
  465.    if (NULL != HTTYFONT( npTTYInfo ))
  466.       DeleteObject( HTTYFONT( npTTYInfo ) ) ;
  467.  
  468.    HTTYFONT( npTTYInfo ) = CreateFontIndirect( &LFTTYFONT( npTTYInfo ) ) ;
  469.  
  470.    hDC = GetDC( hWnd ) ;
  471.    SelectObject( hDC, HTTYFONT( npTTYInfo ) ) ;
  472.    GetTextMetrics( hDC, &tm ) ;
  473.    ReleaseDC( hWnd, hDC ) ;
  474.  
  475.    XCHAR( npTTYInfo ) = tm.tmAveCharWidth  ;
  476.    YCHAR( npTTYInfo ) = tm.tmHeight + tm.tmExternalLeading ;
  477.  
  478.    // a slimy hack to force the scroll position, region to
  479.    // be recalculated based on the new character sizes
  480.  
  481.    GetWindowRect( hWnd, &rcWindow ) ;
  482.    SendMessage( hWnd, WM_SIZE, SIZENORMAL,
  483.                 (LPARAM) MAKELONG( rcWindow.right - rcWindow.left,
  484.                                    rcWindow.bottom - rcWindow.top ) ) ;
  485.  
  486.    return ( TRUE ) ;
  487.  
  488. } // end of ResetTTYScreen()
  489.  
  490. //---------------------------------------------------------------------------
  491. //  BOOL NEAR PaintTTY( HWND hWnd )
  492. //
  493. //  Description:
  494. //     Paints the rectangle determined by the paint struct of
  495. //     the DC.
  496. //
  497. //  Parameters:
  498. //     HWND hWnd
  499. //        handle to TTY window (as always)
  500. //
  501. //---------------------------------------------------------------------------
  502.  
  503. BOOL NEAR PaintTTY( HWND hWnd )
  504. {
  505.    int          nRow, nCol, nEndRow, nEndCol, nCount, nHorzPos, nVertPos ;
  506.    HDC          hDC ;
  507.    HFONT        hOldFont ;
  508.    NPTTYINFO    npTTYInfo ;
  509.    PAINTSTRUCT  ps ;
  510.    RECT         rect ;
  511.  
  512.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  513.       return ( FALSE ) ;
  514.  
  515.    hDC = BeginPaint( hWnd, &ps ) ;
  516.    hOldFont = SelectObject( hDC, HTTYFONT( npTTYInfo ) ) ;
  517.    SetTextColor( hDC, FGCOLOR( npTTYInfo ) ) ;
  518.    SetBkColor( hDC, GetSysColor( COLOR_WINDOW ) ) ;
  519.    rect = ps.rcPaint ;
  520.    nRow =
  521.       min( MAXROWS - 1,
  522.            max( 0, (rect.top + YOFFSET( npTTYInfo )) / YCHAR( npTTYInfo ) ) ) ;
  523.    nEndRow =
  524.       min( MAXROWS - 1,
  525.            ((rect.bottom + YOFFSET( npTTYInfo ) - 1) / YCHAR( npTTYInfo ) ) ) ;
  526.    nCol =
  527.       min( MAXCOLS - 1,
  528.            max( 0, (rect.left + XOFFSET( npTTYInfo )) / XCHAR( npTTYInfo ) ) ) ;
  529.    nEndCol =
  530.       min( MAXCOLS - 1,
  531.            ((rect.right + XOFFSET( npTTYInfo ) - 1) / XCHAR( npTTYInfo ) ) ) ;
  532.    nCount = nEndCol - nCol + 1 ;
  533.    for (; nRow <= nEndRow; nRow++)
  534.    {
  535.       nVertPos = (nRow * YCHAR( npTTYInfo )) - YOFFSET( npTTYInfo ) ;
  536.       nHorzPos = (nCol * XCHAR( npTTYInfo )) - XOFFSET( npTTYInfo ) ;
  537.       rect.top = nVertPos ;
  538.       rect.bottom = nVertPos + YCHAR( npTTYInfo ) ;
  539.       rect.left = nHorzPos ;
  540.       rect.right = nHorzPos + XCHAR( npTTYInfo ) * nCount ;
  541.       SetBkMode( hDC, OPAQUE ) ;
  542.       ExtTextOut( hDC, nHorzPos, nVertPos, ETO_OPAQUE | ETO_CLIPPED, &rect,
  543.                   (LPSTR)( SCREEN( npTTYInfo ) + nRow * MAXCOLS + nCol ),
  544.                   nCount, NULL ) ;
  545.    }
  546.    SelectObject( hDC, hOldFont ) ;
  547.    EndPaint( hWnd, &ps ) ;
  548.    MoveTTYCursor( hWnd ) ;
  549.    return ( TRUE ) ;
  550.  
  551. } // end of PaintTTY()
  552.  
  553. //---------------------------------------------------------------------------
  554. //  BOOL NEAR SizeTTY( HWND hWnd, WORD wVertSize, WORD wHorzSize )
  555. //
  556. //  Description:
  557. //     Sizes TTY and sets up scrolling regions.
  558. //
  559. //  Parameters:
  560. //     HWND hWnd
  561. //        handle to TTY window
  562. //
  563. //     WORD wVertSize
  564. //        new vertical size
  565. //
  566. //     WORD wHorzSize
  567. //        new horizontal size
  568. //
  569. //---------------------------------------------------------------------------
  570.  
  571. BOOL NEAR SizeTTY( HWND hWnd, WORD wVertSize, WORD wHorzSize )
  572. {
  573.    int        nScrollAmt ;
  574.    NPTTYINFO  npTTYInfo ;
  575.  
  576.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  577.       return ( FALSE ) ;
  578.  
  579.    YSIZE( npTTYInfo ) = (int) wVertSize ;
  580.    YSCROLL( npTTYInfo ) = max( 0, (MAXROWS * YCHAR( npTTYInfo )) -
  581.                                YSIZE( npTTYInfo ) ) ;
  582.    nScrollAmt = min( YSCROLL( npTTYInfo ), YOFFSET( npTTYInfo ) ) -
  583.                      YOFFSET( npTTYInfo ) ;
  584.    ScrollWindow( hWnd, 0, -nScrollAmt, NULL, NULL ) ;
  585.  
  586.    YOFFSET( npTTYInfo ) = YOFFSET( npTTYInfo ) + nScrollAmt ;
  587.    SetScrollPos( hWnd, SB_VERT, YOFFSET( npTTYInfo ), FALSE ) ;
  588.    SetScrollRange( hWnd, SB_VERT, 0, YSCROLL( npTTYInfo ), TRUE ) ;
  589.  
  590.    XSIZE( npTTYInfo ) = (int) wHorzSize ;
  591.    XSCROLL( npTTYInfo ) = max( 0, (MAXCOLS * XCHAR( npTTYInfo )) -
  592.                                 XSIZE( npTTYInfo ) ) ;
  593.    nScrollAmt = min( XSCROLL( npTTYInfo ), XOFFSET( npTTYInfo )) -
  594.                      XOFFSET( npTTYInfo ) ;
  595.    ScrollWindow( hWnd, 0, -nScrollAmt, NULL, NULL ) ;
  596.    XOFFSET( npTTYInfo ) = XOFFSET( npTTYInfo ) + nScrollAmt ;
  597.    SetScrollPos( hWnd, SB_HORZ, XOFFSET( npTTYInfo ), FALSE ) ;
  598.    SetScrollRange( hWnd, SB_HORZ, 0, XSCROLL( npTTYInfo ), TRUE ) ;
  599.  
  600.    InvalidateRect( hWnd, NULL, TRUE ) ;
  601.  
  602.    return ( TRUE ) ;
  603.  
  604. } // end of SizeTTY()
  605.  
  606. //---------------------------------------------------------------------------
  607. //  BOOL NEAR ScrollTTYVert( HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
  608. //
  609. //  Description:
  610. //     Scrolls TTY window vertically.
  611. //
  612. //  Parameters:
  613. //     HWND hWnd
  614. //        handle to TTY window
  615. //
  616. //     WORD wScrollCmd
  617. //        type of scrolling we're doing
  618. //
  619. //     WORD wScrollPos
  620. //        scroll position
  621. //
  622. //---------------------------------------------------------------------------
  623.  
  624. BOOL NEAR ScrollTTYVert( HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
  625. {
  626.    int        nScrollAmt ;
  627.    NPTTYINFO  npTTYInfo ;
  628.  
  629.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  630.       return ( FALSE ) ;
  631.  
  632.    switch (wScrollCmd)
  633.    {
  634.       case SB_TOP:
  635.          nScrollAmt = -YOFFSET( npTTYInfo ) ;
  636.          break ;
  637.  
  638.       case SB_BOTTOM:
  639.          nScrollAmt = YSCROLL( npTTYInfo ) - YOFFSET( npTTYInfo ) ;
  640.          break ;
  641.  
  642.       case SB_PAGEUP:
  643.          nScrollAmt = -YSIZE( npTTYInfo ) ;
  644.          break ;
  645.  
  646.       case SB_PAGEDOWN:
  647.          nScrollAmt = YSIZE( npTTYInfo ) ;
  648.          break ;
  649.  
  650.       case SB_LINEUP:
  651.          nScrollAmt = -YCHAR( npTTYInfo ) ;
  652.          break ;
  653.  
  654.       case SB_LINEDOWN:
  655.          nScrollAmt = YCHAR( npTTYInfo ) ;
  656.          break ;
  657.  
  658.       case SB_THUMBPOSITION:
  659.          nScrollAmt = wScrollPos - YOFFSET( npTTYInfo ) ;
  660.          break ;
  661.  
  662.       default:
  663.          return ( FALSE ) ;
  664.    }
  665.    if ((YOFFSET( npTTYInfo ) + nScrollAmt) > YSCROLL( npTTYInfo ))
  666.       nScrollAmt = YSCROLL( npTTYInfo ) - YOFFSET( npTTYInfo ) ;
  667.    if ((YOFFSET( npTTYInfo ) + nScrollAmt) < 0)
  668.       nScrollAmt = -YOFFSET( npTTYInfo ) ;
  669.    ScrollWindow( hWnd, 0, -nScrollAmt, NULL, NULL ) ;
  670.    YOFFSET( npTTYInfo ) = YOFFSET( npTTYInfo ) + nScrollAmt ;
  671.    SetScrollPos( hWnd, SB_VERT, YOFFSET( npTTYInfo ), TRUE ) ;
  672.  
  673.    return ( TRUE ) ;
  674.  
  675. } // end of ScrollTTYVert()
  676.  
  677. //---------------------------------------------------------------------------
  678. //  BOOL NEAR ScrollTTYHorz( HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
  679. //
  680. //  Description:
  681. //     Scrolls TTY window horizontally.
  682. //
  683. //  Parameters:
  684. //     HWND hWnd
  685. //        handle to TTY window
  686. //
  687. //     WORD wScrollCmd
  688. //        type of scrolling we're doing
  689. //
  690. //     WORD wScrollPos
  691. //        scroll position
  692. //
  693. //---------------------------------------------------------------------------
  694.  
  695. BOOL NEAR ScrollTTYHorz( HWND hWnd, WORD wScrollCmd, WORD wScrollPos )
  696. {
  697.    int        nScrollAmt ;
  698.    NPTTYINFO  npTTYInfo ;
  699.  
  700.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  701.       return ( FALSE ) ;
  702.  
  703.    switch (wScrollCmd)
  704.    {
  705.       case SB_TOP:
  706.          nScrollAmt = -XOFFSET( npTTYInfo ) ;
  707.          break ;
  708.  
  709.       case SB_BOTTOM:
  710.          nScrollAmt = XSCROLL( npTTYInfo ) - XOFFSET( npTTYInfo ) ;
  711.          break ;
  712.  
  713.       case SB_PAGEUP:
  714.          nScrollAmt = -XSIZE( npTTYInfo ) ;
  715.          break ;
  716.  
  717.       case SB_PAGEDOWN:
  718.          nScrollAmt = XSIZE( npTTYInfo ) ;
  719.          break ;
  720.  
  721.       case SB_LINEUP:
  722.          nScrollAmt = -XCHAR( npTTYInfo ) ;
  723.          break ;
  724.  
  725.       case SB_LINEDOWN:
  726.          nScrollAmt = XCHAR( npTTYInfo ) ;
  727.          break ;
  728.  
  729.       case SB_THUMBPOSITION:
  730.          nScrollAmt = wScrollPos - XOFFSET( npTTYInfo ) ;
  731.          break ;
  732.  
  733.       default:
  734.          return ( FALSE ) ;
  735.    }
  736.    if ((XOFFSET( npTTYInfo ) + nScrollAmt) > XSCROLL( npTTYInfo ))
  737.       nScrollAmt = XSCROLL( npTTYInfo ) - XOFFSET( npTTYInfo ) ;
  738.    if ((XOFFSET( npTTYInfo ) + nScrollAmt) < 0)
  739.       nScrollAmt = -XOFFSET( npTTYInfo ) ;
  740.    ScrollWindow( hWnd, -nScrollAmt, 0, NULL, NULL ) ;
  741.    XOFFSET( npTTYInfo ) = XOFFSET( npTTYInfo ) + nScrollAmt ;
  742.    SetScrollPos( hWnd, SB_HORZ, XOFFSET( npTTYInfo ), TRUE ) ;
  743.  
  744.    return ( TRUE ) ;
  745.  
  746. } // end of ScrollTTYHorz()
  747.  
  748. //---------------------------------------------------------------------------
  749. //  BOOL NEAR SetTTYFocus( HWND hWnd )
  750. //
  751. //  Description:
  752. //     Sets the focus to the TTY window also creates caret.
  753. //
  754. //  Parameters:
  755. //     HWND hWnd
  756. //        handle to TTY window
  757. //
  758. //---------------------------------------------------------------------------
  759.  
  760. BOOL NEAR SetTTYFocus( HWND hWnd )
  761. {
  762.    NPTTYINFO  npTTYInfo ;
  763.  
  764.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  765.       return ( FALSE ) ;
  766.  
  767.    if (CONNECTED( npTTYInfo ) && (CURSORSTATE( npTTYInfo ) != CS_SHOW))
  768.    {
  769.       CreateCaret( hWnd, NULL, XCHAR( npTTYInfo ), YCHAR( npTTYInfo ) ) ;
  770.       ShowCaret( hWnd ) ;
  771.       CURSORSTATE( npTTYInfo ) = CS_SHOW ;
  772.    }
  773.    MoveTTYCursor( hWnd ) ;
  774.    return ( TRUE ) ;
  775.  
  776. } // end of SetTTYFocus()
  777.  
  778. //---------------------------------------------------------------------------
  779. //  BOOL NEAR KillTTYFocus( HWND hWnd )
  780. //
  781. //  Description:
  782. //     Kills TTY focus and destroys the caret.
  783. //
  784. //  Parameters:
  785. //     HWND hWnd
  786. //        handle to TTY window
  787. //
  788. //---------------------------------------------------------------------------
  789.  
  790. BOOL NEAR KillTTYFocus( HWND hWnd )
  791. {
  792.    NPTTYINFO  npTTYInfo ;
  793.  
  794.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  795.       return ( FALSE ) ;
  796.  
  797.    if (CONNECTED( npTTYInfo ) && (CURSORSTATE( npTTYInfo ) != CS_HIDE))
  798.    {
  799.       HideCaret( hWnd ) ;
  800.       DestroyCaret() ;
  801.       CURSORSTATE( npTTYInfo ) = CS_HIDE ;
  802.    }
  803.    return ( TRUE ) ;
  804.  
  805. } // end of KillTTYFocus()
  806.  
  807. //---------------------------------------------------------------------------
  808. //  BOOL NEAR MoveTTYCursor( HWND hWnd )
  809. //
  810. //  Description:
  811. //     Moves caret to current position.
  812. //
  813. //  Parameters:
  814. //     HWND hWnd
  815. //        handle to TTY window
  816. //
  817. //---------------------------------------------------------------------------
  818.  
  819. BOOL NEAR MoveTTYCursor( HWND hWnd )
  820. {
  821.    NPTTYINFO  npTTYInfo ;
  822.  
  823.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  824.       return ( FALSE ) ;
  825.  
  826.    if (CONNECTED( npTTYInfo ) && (CURSORSTATE( npTTYInfo ) & CS_SHOW))
  827.       SetCaretPos( (COLUMN( npTTYInfo ) * XCHAR( npTTYInfo )) -
  828.                    XOFFSET( npTTYInfo ),
  829.                    (ROW( npTTYInfo ) * YCHAR( npTTYInfo )) -
  830.                    YOFFSET( npTTYInfo ) ) ;
  831.  
  832.    return ( TRUE ) ;
  833.  
  834. } // end of MoveTTYCursor()
  835.  
  836. //---------------------------------------------------------------------------
  837. //  BOOL NEAR ProcessTTYCharacter( HWND hWnd, BYTE bOut )
  838. //
  839. //  Description:
  840. //     This simply writes a character to the port and echos it
  841. //     to the TTY screen if fLocalEcho is set.  Some minor
  842. //     keyboard mapping could be performed here.
  843. //
  844. //  Parameters:
  845. //     HWND hWnd
  846. //        handle to TTY window
  847. //
  848. //     BYTE bOut
  849. //        byte from keyboard
  850. //
  851. //---------------------------------------------------------------------------
  852.  
  853. BOOL NEAR ProcessTTYCharacter( HWND hWnd, BYTE bOut )
  854. {
  855.    NPTTYINFO  npTTYInfo ;
  856.  
  857.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  858.       return ( FALSE ) ;
  859.  
  860.    if (!CONNECTED( npTTYInfo ))
  861.       return ( FALSE ) ;
  862.  
  863.    // a robust app would take appropriate steps if WriteCommBlock failed
  864.    WriteCommBlock( hWnd, &bOut, 1 ) ;
  865.    if (LOCALECHO( npTTYInfo ))
  866.       WriteTTYBlock( hWnd, &bOut, 1 ) ;
  867.  
  868.    return ( TRUE ) ;
  869.  
  870. } // end of ProcessTTYCharacter()
  871.  
  872. //---------------------------------------------------------------------------
  873. //  BOOL NEAR OpenConnection( HWND hWnd )
  874. //
  875. //  Description:
  876. //     Opens communication port specified in the TTYINFO struct.
  877. //     It also sets the CommState and notifies the window via
  878. //     the fConnected flag in the TTYINFO struct.
  879. //
  880. //  Parameters:
  881. //     HWND hWnd
  882. //        handle to TTY window
  883. //
  884. //  Win-32 Porting Issues:
  885. //     - OpenComm() is not supported under Win-32.  Use CreateFile()
  886. //       and setup for OVERLAPPED_IO.
  887. //     - Win-32 has specific communication timeout parameters.
  888. //     - Created the secondary thread for event notification.
  889. //
  890. //---------------------------------------------------------------------------
  891.  
  892. BOOL NEAR OpenConnection( HWND hWnd )
  893. {
  894.    char       szPort[ 15 ], szTemp[ 10 ] ;
  895.    BOOL       fRetVal ;
  896.    HCURSOR    hOldCursor, hWaitCursor ;
  897.    HMENU      hMenu ;
  898.    NPTTYINFO  npTTYInfo ;
  899.  
  900.    HANDLE        hCommWatchThread ;
  901.    DWORD         dwThreadID ;
  902.    COMMTIMEOUTS  CommTimeOuts ;
  903.  
  904.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  905.       return ( FALSE ) ;
  906.  
  907.    // show the hourglass cursor
  908.    hWaitCursor = LoadCursor( NULL, IDC_WAIT ) ;
  909.    hOldCursor = SetCursor( hWaitCursor ) ;
  910.  
  911.    // load the COM prefix string and append port number
  912.  
  913.    LoadString( GETHINST( hWnd ), IDS_COMPREFIX, szTemp, sizeof( szTemp ) ) ;
  914.    wsprintf( szPort, "%s%d", (LPSTR) szTemp, PORT( npTTYInfo ) ) ;
  915.  
  916.    // open COMM device
  917.  
  918.    if ((COMDEV( npTTYInfo ) =
  919.       CreateFile( szPort, GENERIC_READ | GENERIC_WRITE,
  920.                   0,                    // exclusive access
  921.                   NULL,                 // no security attrs
  922.                   OPEN_EXISTING,
  923.                   FILE_ATTRIBUTE_NORMAL |
  924.                   FILE_FLAG_OVERLAPPED, // overlapped I/O
  925.                   NULL )) == (HANDLE) -1 )
  926.       return ( FALSE ) ;
  927.    else
  928.    {
  929.       // get any early notifications
  930.  
  931.       SetCommMask( COMDEV( npTTYInfo ), EV_RXCHAR ) ;
  932.  
  933.       // setup device buffers
  934.  
  935.       SetupComm( COMDEV( npTTYInfo ), 4096, 4096 ) ;
  936.  
  937.       // purge any information in the buffer
  938.  
  939.       PurgeComm( COMDEV( npTTYInfo ), PURGE_TXABORT | PURGE_RXABORT |
  940.                                       PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
  941.  
  942.       // set up for overlapped I/O
  943.  
  944.       CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
  945.       CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
  946.       CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
  947.       // CBR_9600 is approximately 1byte/ms. For our purposes, allow
  948.       // double the expected time per character for a fudge factor.
  949.       CommTimeOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600/BAUDRATE( npTTYInfo ) ;
  950.       CommTimeOuts.WriteTotalTimeoutConstant = 0 ;
  951.       SetCommTimeouts( COMDEV( npTTYInfo ), &CommTimeOuts ) ;
  952.    }
  953.  
  954.    fRetVal = SetupConnection( hWnd ) ;
  955.  
  956.    if (fRetVal)
  957.    {
  958.       CONNECTED( npTTYInfo ) = TRUE ;
  959.  
  960.       // Create a secondary thread
  961.       // to watch for an event.
  962.  
  963.       if (NULL == (hCommWatchThread =
  964.                       CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
  965.                                     0,
  966.                                     (LPTHREAD_START_ROUTINE) CommWatchProc,
  967.                                     (LPVOID) npTTYInfo,
  968.                                     0, &dwThreadID )))
  969.       {
  970.          CONNECTED( npTTYInfo ) = FALSE ;
  971.          CloseHandle( COMDEV( npTTYInfo ) ) ;
  972.          fRetVal = FALSE ;
  973.       }
  974.       else
  975.       {
  976.          THREADID( npTTYInfo ) = dwThreadID ;
  977.          HTHREAD( npTTYInfo ) = hCommWatchThread ;
  978.  
  979.          // assert DTR
  980.  
  981.          EscapeCommFunction( COMDEV( npTTYInfo ), SETDTR ) ;
  982.  
  983.          SetTTYFocus( hWnd ) ;
  984.  
  985.          hMenu = GetMenu( hWnd ) ;
  986.          EnableMenuItem( hMenu, IDM_DISCONNECT,
  987.                         MF_ENABLED | MF_BYCOMMAND ) ;
  988.          EnableMenuItem( hMenu, IDM_CONNECT,
  989.                         MF_GRAYED | MF_DISABLED | MF_BYCOMMAND ) ;
  990.  
  991.       }
  992.    }
  993.    else
  994.    {
  995.       CONNECTED( npTTYInfo ) = FALSE ;
  996.       CloseHandle( COMDEV( npTTYInfo ) ) ;
  997.    }
  998.  
  999.    // restore cursor
  1000.  
  1001.    SetCursor( hOldCursor ) ;
  1002.  
  1003.    return ( fRetVal ) ;
  1004.  
  1005. } // end of OpenConnection()
  1006.  
  1007. //---------------------------------------------------------------------------
  1008. //  BOOL NEAR SetupConnection( HWND hWnd )
  1009. //
  1010. //  Description:
  1011. //     This routines sets up the DCB based on settings in the
  1012. //     TTY info structure and performs a SetCommState().
  1013. //
  1014. //  Parameters:
  1015. //     HWND hWnd
  1016. //        handle to TTY window
  1017. //
  1018. //  Win-32 Porting Issues:
  1019. //     - Win-32 requires a slightly different processing of the DCB.
  1020. //       Changes were made for configuration of the hardware handshaking
  1021. //       lines.
  1022. //
  1023. //---------------------------------------------------------------------------
  1024.  
  1025. BOOL NEAR SetupConnection( HWND hWnd )
  1026. {
  1027.    BOOL       fRetVal ;
  1028.    BYTE       bSet ;
  1029.    DCB        dcb ;
  1030.    NPTTYINFO  npTTYInfo ;
  1031.  
  1032.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  1033.       return ( FALSE ) ;
  1034.  
  1035.    dcb.DCBlength = sizeof( DCB ) ;
  1036.  
  1037.    GetCommState( COMDEV( npTTYInfo ), &dcb ) ;
  1038.  
  1039.    dcb.BaudRate = BAUDRATE( npTTYInfo ) ;
  1040.    dcb.ByteSize = BYTESIZE( npTTYInfo ) ;
  1041.    dcb.Parity = PARITY( npTTYInfo ) ;
  1042.    dcb.StopBits = STOPBITS( npTTYInfo ) ;
  1043.  
  1044.    // setup hardware flow control
  1045.  
  1046.    bSet = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_DTRDSR) != 0) ;
  1047.    dcb.fOutxDsrFlow = bSet ;
  1048.    if (bSet)
  1049.       dcb.fDtrControl = DTR_CONTROL_HANDSHAKE ;
  1050.    else
  1051.       dcb.fDtrControl = DTR_CONTROL_ENABLE ;
  1052.  
  1053.    bSet = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_RTSCTS) != 0) ;
  1054.     dcb.fOutxCtsFlow = bSet ;
  1055.    if (bSet)
  1056.       dcb.fRtsControl = RTS_CONTROL_HANDSHAKE ;
  1057.    else
  1058.       dcb.fRtsControl = RTS_CONTROL_ENABLE ;
  1059.  
  1060.    // setup software flow control
  1061.  
  1062.    bSet = (BYTE) ((FLOWCTRL( npTTYInfo ) & FC_XONXOFF) != 0) ;
  1063.  
  1064.    dcb.fInX = dcb.fOutX = bSet ;
  1065.    dcb.XonChar = ASCII_XON ;
  1066.    dcb.XoffChar = ASCII_XOFF ;
  1067.    dcb.XonLim = 100 ;
  1068.    dcb.XoffLim = 100 ;
  1069.  
  1070.    // other various settings
  1071.  
  1072.    dcb.fBinary = TRUE ;
  1073.    dcb.fParity = TRUE ;
  1074.  
  1075.    fRetVal = SetCommState( COMDEV( npTTYInfo ), &dcb ) ;
  1076.  
  1077.    return ( fRetVal ) ;
  1078.  
  1079. } // end of SetupConnection()
  1080.  
  1081. //---------------------------------------------------------------------------
  1082. //  BOOL NEAR CloseConnection( HWND hWnd )
  1083. //
  1084. //  Description:
  1085. //     Closes the connection to the port.  Resets the connect flag
  1086. //     in the TTYINFO struct.
  1087. //
  1088. //  Parameters:
  1089. //     HWND hWnd
  1090. //        handle to TTY window
  1091. //
  1092. //  Win-32 Porting Issues:
  1093. //     - Needed to stop secondary thread.  SetCommMask() will signal the
  1094. //       WaitCommEvent() event and the thread will halt when the
  1095. //       CONNECTED() flag is clear.
  1096. //     - Use new PurgeComm() API to clear communications driver before
  1097. //       closing device.
  1098. //
  1099. //---------------------------------------------------------------------------
  1100.  
  1101. BOOL NEAR CloseConnection( HWND hWnd )
  1102. {
  1103.    HMENU      hMenu ;
  1104.    NPTTYINFO  npTTYInfo ;
  1105.  
  1106.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  1107.       return ( FALSE ) ;
  1108.  
  1109.    // set connected flag to FALSE
  1110.  
  1111.    CONNECTED( npTTYInfo ) = FALSE ;
  1112.  
  1113.    // disable event notification and wait for thread
  1114.    // to halt
  1115.  
  1116.    SetCommMask( COMDEV( npTTYInfo ), 0 ) ;
  1117.  
  1118.    // block until thread has been halted
  1119.  
  1120.    while(THREADID(npTTYInfo) != 0);
  1121.  
  1122.    // kill the focus
  1123.  
  1124.    KillTTYFocus( hWnd ) ;
  1125.  
  1126.    // drop DTR
  1127.  
  1128.    EscapeCommFunction( COMDEV( npTTYInfo ), CLRDTR ) ;
  1129.  
  1130.    // purge any outstanding reads/writes and close device handle
  1131.  
  1132.    PurgeComm( COMDEV( npTTYInfo ), PURGE_TXABORT | PURGE_RXABORT |
  1133.                                    PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
  1134.    CloseHandle( COMDEV( npTTYInfo ) ) ;
  1135.  
  1136.    // change the selectable items in the menu
  1137.  
  1138.    hMenu = GetMenu( hWnd ) ;
  1139.    EnableMenuItem( hMenu, IDM_DISCONNECT,
  1140.                    MF_GRAYED | MF_DISABLED | MF_BYCOMMAND ) ;
  1141.    EnableMenuItem( hMenu, IDM_CONNECT,
  1142.                    MF_ENABLED | MF_BYCOMMAND ) ;
  1143.  
  1144.    return ( TRUE ) ;
  1145.  
  1146. } // end of CloseConnection()
  1147.  
  1148. //---------------------------------------------------------------------------
  1149. //  int NEAR ReadCommBlock( HWND hWnd, LPSTR lpszBlock, int nMaxLength )
  1150. //
  1151. //  Description:
  1152. //     Reads a block from the COM port and stuffs it into
  1153. //     the provided buffer.
  1154. //
  1155. //  Parameters:
  1156. //     HWND hWnd
  1157. //        handle to TTY window
  1158. //
  1159. //     LPSTR lpszBlock
  1160. //        block used for storage
  1161. //
  1162. //     int nMaxLength
  1163. //        max length of block to read
  1164. //
  1165. //  Win-32 Porting Issues:
  1166. //     - ReadComm() has been replaced by ReadFile() in Win-32.
  1167. //     - Overlapped I/O has been implemented.
  1168. //
  1169. //---------------------------------------------------------------------------
  1170.  
  1171. int NEAR ReadCommBlock( HWND hWnd, LPSTR lpszBlock, int nMaxLength )
  1172. {
  1173.    BOOL       fReadStat ;
  1174.    COMSTAT    ComStat ;
  1175.    DWORD      dwErrorFlags;
  1176.    DWORD      dwLength;
  1177.    DWORD      dwError;
  1178.    char       szError[ 10 ] ;
  1179.    NPTTYINFO  npTTYInfo ;
  1180.  
  1181.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  1182.       return ( FALSE ) ;
  1183.  
  1184.    // only try to read number of bytes in queue
  1185.    ClearCommError( COMDEV( npTTYInfo ), &dwErrorFlags, &ComStat ) ;
  1186.    dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
  1187.  
  1188.    if (dwLength > 0)
  1189.    {
  1190.       fReadStat = ReadFile( COMDEV( npTTYInfo ), lpszBlock,
  1191.                             dwLength, &dwLength, &READ_OS( npTTYInfo ) ) ;
  1192.       if (!fReadStat)
  1193.       {
  1194.          if (GetLastError() == ERROR_IO_PENDING)
  1195.          {
  1196.             OutputDebugString("\n\rIO Pending");
  1197.             // We have to wait for read to complete.
  1198.             // This function will timeout according to the
  1199.             // CommTimeOuts.ReadTotalTimeoutConstant variable
  1200.             // Every time it times out, check for port errors
  1201.             while(!GetOverlappedResult( COMDEV( npTTYInfo ),
  1202.                &READ_OS( npTTYInfo ), &dwLength, TRUE ))
  1203.             {
  1204.                dwError = GetLastError();
  1205.                if(dwError == ERROR_IO_INCOMPLETE)
  1206.                   // normal result if not finished
  1207.                   continue;
  1208.                else
  1209.                {
  1210.                   // an error occurred, try to recover
  1211.                   wsprintf( szError, "<CE-%u>", dwError ) ;
  1212.                   WriteTTYBlock( hWnd, szError, lstrlen( szError ) ) ;
  1213.                   ClearCommError( COMDEV( npTTYInfo ), &dwErrorFlags, &ComStat ) ;
  1214.                   if ((dwErrorFlags > 0) && DISPLAYERRORS( npTTYInfo ))
  1215.                   {
  1216.                       wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
  1217.                       WriteTTYBlock( hWnd, szError, lstrlen( szError ) ) ;
  1218.                   }
  1219.                   break;
  1220.                }
  1221.  
  1222.             }
  1223.  
  1224.           }
  1225.          else
  1226.          {
  1227.             // some other error occurred
  1228.             dwLength = 0 ;
  1229.             ClearCommError( COMDEV( npTTYInfo ), &dwErrorFlags, &ComStat ) ;
  1230.             if ((dwErrorFlags > 0) && DISPLAYERRORS( npTTYInfo ))
  1231.             {
  1232.                 wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
  1233.                 WriteTTYBlock( hWnd, szError, lstrlen( szError ) ) ;
  1234.             }
  1235.          }
  1236.       }
  1237.    }
  1238.  
  1239.    return ( dwLength ) ;
  1240.  
  1241. } // end of ReadCommBlock()
  1242.  
  1243. //---------------------------------------------------------------------------
  1244. //  BOOL NEAR WriteCommBlock( HWND hWnd, BYTE *pByte )
  1245. //
  1246. //  Description:
  1247. //     Writes a block of data to the COM port specified in the associated
  1248. //     TTY info structure.
  1249. //
  1250. //  Parameters:
  1251. //     HWND hWnd
  1252. //        handle to TTY window
  1253. //
  1254. //     BYTE *pByte
  1255. //        pointer to data to write to port
  1256. //
  1257. //  Win-32 Porting Issues:
  1258. //     - WriteComm() has been replaced by WriteFile() in Win-32.
  1259. //     - Overlapped I/O has been implemented.
  1260. //
  1261. //---------------------------------------------------------------------------
  1262.  
  1263. BOOL NEAR WriteCommBlock( HWND hWnd, LPSTR lpByte , DWORD dwBytesToWrite)
  1264. {
  1265.  
  1266.    BOOL        fWriteStat ;
  1267.    DWORD       dwBytesWritten ;
  1268.    NPTTYINFO   npTTYInfo ;
  1269.    DWORD       dwErrorFlags;
  1270.    DWORD       dwError;
  1271.    DWORD       dwBytesSent=0;
  1272.    COMSTAT     ComStat;
  1273.    char        szError[ 128 ] ;
  1274.  
  1275.  
  1276.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  1277.       return ( FALSE ) ;
  1278.  
  1279.    fWriteStat = WriteFile( COMDEV( npTTYInfo ), lpByte, dwBytesToWrite,
  1280.                            &dwBytesWritten, &WRITE_OS( npTTYInfo ) ) ;
  1281.  
  1282.    // Note that normally the code will not execute the following
  1283.    // because the driver caches write operations. Small I/O requests
  1284.    // (up to several thousand bytes) will normally be accepted
  1285.    // immediately and WriteFile will return true even though an
  1286.    // overlapped operation was specified
  1287.  
  1288.    if (!fWriteStat)
  1289.    {
  1290.       if(GetLastError() == ERROR_IO_PENDING)
  1291.       {
  1292.          // We should wait for the completion of the write operation
  1293.          // so we know if it worked or not
  1294.  
  1295.          // This is only one way to do this. It might be beneficial to
  1296.          // place the write operation in a separate thread
  1297.          // so that blocking on completion will not negatively
  1298.          // affect the responsiveness of the UI
  1299.  
  1300.          // If the write takes too long to complete, this
  1301.          // function will timeout according to the
  1302.          // CommTimeOuts.WriteTotalTimeoutMultiplier variable.
  1303.          // This code logs the timeout but does not retry
  1304.          // the write.
  1305.  
  1306.          while(!GetOverlappedResult( COMDEV( npTTYInfo ),
  1307.             &WRITE_OS( npTTYInfo ), &dwBytesWritten, TRUE ))
  1308.          {
  1309.             dwError = GetLastError();
  1310.             if(dwError == ERROR_IO_INCOMPLETE)
  1311.             {
  1312.                // normal result if not finished
  1313.                dwBytesSent += dwBytesWritten;
  1314.                continue;
  1315.             }
  1316.             else
  1317.             {
  1318.                // an error occurred, try to recover
  1319.                wsprintf( szError, "<CE-%u>", dwError ) ;
  1320.                WriteTTYBlock( hWnd, szError, lstrlen( szError ) ) ;
  1321.                ClearCommError( COMDEV( npTTYInfo ), &dwErrorFlags, &ComStat ) ;
  1322.                if ((dwErrorFlags > 0) && DISPLAYERRORS( npTTYInfo ))
  1323.                {
  1324.                   wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
  1325.                   WriteTTYBlock( hWnd, szError, lstrlen( szError ) ) ;
  1326.                }
  1327.                break;
  1328.             }
  1329.          }
  1330.  
  1331.          dwBytesSent += dwBytesWritten;
  1332.  
  1333.          if( dwBytesSent != dwBytesToWrite )
  1334.              wsprintf(szError,"\nProbable Write Timeout: Total of %ld bytes sent", dwBytesSent);
  1335.          else
  1336.              wsprintf(szError,"\n%ld bytes written", dwBytesSent);
  1337.  
  1338.          OutputDebugString(szError);
  1339.  
  1340.       }
  1341.       else
  1342.       {
  1343.          // some other error occurred
  1344.          ClearCommError( COMDEV( npTTYInfo ), &dwErrorFlags, &ComStat ) ;
  1345.          if ((dwErrorFlags > 0) && DISPLAYERRORS( npTTYInfo ))
  1346.          {
  1347.             wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
  1348.             WriteTTYBlock( hWnd, szError, lstrlen( szError ) ) ;
  1349.          }
  1350.          return ( FALSE );
  1351.       }
  1352.    }
  1353.    return ( TRUE ) ;
  1354.  
  1355. } // end of WriteCommBlock()
  1356.  
  1357. //---------------------------------------------------------------------------
  1358. //  BOOL NEAR WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength )
  1359. //
  1360. //  Description:
  1361. //     Writes block to TTY screen.  Nothing fancy - just
  1362. //     straight TTY.
  1363. // gl
  1364. //  Parameters:
  1365. //     HWND hWnd
  1366. //        handle to TTY window
  1367. //
  1368. //     LPSTR lpBlock
  1369. //        far pointer to block of data
  1370. //
  1371. //     int nLength
  1372. //        length of block
  1373. //
  1374. //---------------------------------------------------------------------------
  1375.  
  1376. BOOL NEAR WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength )
  1377. {
  1378.    int        i ;
  1379.    NPTTYINFO  npTTYInfo ;
  1380.    RECT       rect ;
  1381.  
  1382.    if (NULL == (npTTYInfo = GETNPTTYINFO( hWnd )))
  1383.       return ( FALSE ) ;
  1384.  
  1385.    for (i = 0 ; i < nLength; i++)
  1386.    {
  1387.       switch (lpBlock[ i ])
  1388.       {
  1389.          case ASCII_BEL:
  1390.             // Bell
  1391.             MessageBeep( 0 ) ;
  1392.             break ;
  1393.  
  1394.          case ASCII_BS:
  1395.             // Backspace
  1396.             if (COLUMN( npTTYInfo ) > 0)
  1397.                COLUMN( npTTYInfo ) -- ;
  1398.             MoveTTYCursor( hWnd ) ;
  1399.             break ;
  1400.  
  1401.          case ASCII_CR:
  1402.             // Carriage return
  1403.             COLUMN( npTTYInfo ) = 0 ;
  1404.             MoveTTYCursor( hWnd ) ;
  1405.             if (!NEWLINE( npTTYInfo ))
  1406.                break;
  1407.  
  1408.             // fall through
  1409.  
  1410.          case ASCII_LF:
  1411.             // Line feed
  1412.             if (ROW( npTTYInfo )++ == MAXROWS - 1)
  1413.             {
  1414.                _fmemmove( (LPSTR) (SCREEN( npTTYInfo )),
  1415.                           (LPSTR) (SCREEN( npTTYInfo ) + MAXCOLS),
  1416.                           (MAXROWS - 1) * MAXCOLS ) ;
  1417.                _fmemset( (LPSTR) (SCREEN( npTTYInfo ) + (MAXROWS - 1) * MAXCOLS),
  1418.                          ' ', MAXCOLS ) ;
  1419.                InvalidateRect( hWnd, NULL, FALSE ) ;
  1420.                ROW( npTTYInfo )-- ;
  1421.             }
  1422.             MoveTTYCursor( hWnd ) ;
  1423.             break ;
  1424.  
  1425.          default:
  1426.             *(SCREEN( npTTYInfo ) + ROW( npTTYInfo ) * MAXCOLS +
  1427.                 COLUMN( npTTYInfo )) = lpBlock[ i ] ;
  1428.             rect.left = (COLUMN( npTTYInfo ) * XCHAR( npTTYInfo )) -
  1429.                         XOFFSET( npTTYInfo ) ;
  1430.             rect.right = rect.left + XCHAR( npTTYInfo ) ;
  1431.             rect.top = (ROW( npTTYInfo ) * YCHAR( npTTYInfo )) -
  1432.                        YOFFSET( npTTYInfo ) ;
  1433.             rect.bottom = rect.top + YCHAR( npTTYInfo ) ;
  1434.             InvalidateRect( hWnd, &rect, FALSE ) ;
  1435.  
  1436.             // Line wrap
  1437.             if (COLUMN( npTTYInfo ) < MAXCOLS - 1)
  1438.                COLUMN( npTTYInfo )++ ;
  1439.             else if (AUTOWRAP( npTTYInfo ))
  1440.                WriteTTYBlock( hWnd, "\r\n", 2 ) ;
  1441.             break;
  1442.       }
  1443.    }
  1444.    return ( TRUE ) ;
  1445.  
  1446. } // end of WriteTTYBlock()
  1447.  
  1448. //---------------------------------------------------------------------------
  1449. //  VOID NEAR GoModalDialogBoxParam( HINSTANCE hInstance,
  1450. //                                   LPCSTR lpszTemplate, HWND hWnd,
  1451. //                                   DLGPROC lpDlgProc, LPARAM lParam )
  1452. //
  1453. //  Description:
  1454. //     It is a simple utility function that simply performs the
  1455. //     MPI and invokes the dialog box with a DWORD paramter.
  1456. //
  1457. //  Parameters:
  1458. //     similar to that of DialogBoxParam() with the exception
  1459. //     that the lpDlgProc is not a procedure instance
  1460. //
  1461. //---------------------------------------------------------------------------
  1462.  
  1463. VOID NEAR GoModalDialogBoxParam( HINSTANCE hInstance, LPCSTR lpszTemplate,
  1464.                                  HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam )
  1465. {
  1466.    DLGPROC  lpProcInstance ;
  1467.  
  1468.    lpProcInstance = (DLGPROC) MakeProcInstance( (FARPROC) lpDlgProc,
  1469.                                                 hInstance ) ;
  1470.    DialogBoxParam( hInstance, lpszTemplate, hWnd, lpProcInstance, lParam ) ;
  1471.    FreeProcInstance( (FARPROC) lpProcInstance ) ;
  1472.  
  1473. } // end of GoModalDialogBoxParam()
  1474.  
  1475. //---------------------------------------------------------------------------
  1476. //  BOOL FAR PASCAL AboutDlgProc( HWND hDlg, UINT uMsg,
  1477. //                                WPARAM wParam, LPARAM lParam )
  1478. //
  1479. //  Description:
  1480. //     Simulates the Windows System Dialog Box.
  1481. //
  1482. //  Parameters:
  1483. //     Same as standard dialog procedures.
  1484. //
  1485. //---------------------------------------------------------------------------
  1486.  
  1487. BOOL FAR PASCAL AboutDlgProc( HWND hDlg, UINT uMsg,
  1488.                               WPARAM wParam, LPARAM lParam )
  1489. {
  1490.    switch (uMsg)
  1491.    {
  1492.       case WM_INITDIALOG:
  1493.       {
  1494.          char         szBuffer[ MAXLEN_TEMPSTR ], szTemp[ MAXLEN_TEMPSTR ];
  1495.          WORD         wRevision, wVersion ;
  1496.  
  1497. #ifdef ABOUTDLG_USEBITMAP
  1498.          // if we are using the bitmap, hide the icon
  1499.  
  1500.          ShowWindow( GetDlgItem( hDlg, IDD_ABOUTICON ), SW_HIDE ) ;
  1501. #endif
  1502.          // sets up the version number for Windows
  1503.  
  1504.          wVersion = LOWORD( GetVersion() ) ;
  1505.          wRevision = HIBYTE( wVersion ) ;
  1506.          wVersion = LOBYTE( wVersion ) ;
  1507.  
  1508.          GetDlgItemText( hDlg, IDD_TITLELINE, szTemp, sizeof( szTemp ) ) ;
  1509.          wsprintf( szBuffer, szTemp, wVersion, wRevision ) ;
  1510.          SetDlgItemText( hDlg, IDD_TITLELINE, szBuffer ) ;
  1511.  
  1512.          // sets up version number for TTY
  1513.  
  1514.          GetDlgItemText( hDlg, IDD_VERSION, szTemp, sizeof( szTemp ) ) ;
  1515.          wsprintf( szBuffer, szTemp, VER_MAJOR, VER_MINOR, VER_BUILD ) ;
  1516.          SetDlgItemText( hDlg, IDD_VERSION, (LPSTR) szBuffer ) ;
  1517.  
  1518.          // get by-line
  1519.  
  1520.          LoadString( GETHINST( hDlg ), IDS_BYLINE, szBuffer,
  1521.                      sizeof( szBuffer ) ) ;
  1522.          SetDlgItemText( hDlg, IDD_BYLINE, szBuffer ) ;
  1523.  
  1524.          SetDlgItemText( hDlg, IDD_WINDOWSMODE, "NT Mode" ) ;
  1525.  
  1526.       }
  1527.       return ( TRUE ) ;
  1528.  
  1529. #ifdef ABOUTDLG_USEBITMAP
  1530.       // used to paint the bitmap
  1531.  
  1532.       case WM_PAINT:
  1533.       {
  1534.          HBITMAP      hBitMap ;
  1535.          HDC          hDC, hMemDC ;
  1536.          PAINTSTRUCT  ps ;
  1537.  
  1538.          // load bitmap and display it
  1539.  
  1540.          hDC = BeginPaint( hDlg, &ps ) ;
  1541.          if (NULL != (hMemDC = CreateCompatibleDC( hDC )))
  1542.          {
  1543.             hBitMap = LoadBitmap( GETHINST( hDlg ),
  1544.                                   MAKEINTRESOURCE( TTYBITMAP ) ) ;
  1545.             hBitMap = SelectObject( hMemDC, hBitMap ) ;
  1546.             BitBlt( hDC, 10, 10, 64, 64, hMemDC, 0, 0, SRCCOPY ) ;
  1547.             DeleteObject( SelectObject( hMemDC, hBitMap ) ) ;
  1548.             DeleteDC( hMemDC ) ;
  1549.          }
  1550.          EndPaint( hDlg, &ps ) ;
  1551.       }
  1552.       break ;
  1553. #endif
  1554.  
  1555.       case WM_COMMAND:
  1556.          if (LOWORD( wParam ) == IDD_OK)
  1557.          {
  1558.             EndDialog( hDlg, TRUE ) ;
  1559.             return ( TRUE ) ;
  1560.          }
  1561.          break;
  1562.    }
  1563.    return ( FALSE ) ;
  1564.  
  1565. } // end of AboutDlgProc()
  1566.  
  1567. //---------------------------------------------------------------------------
  1568. //  VOID NEAR FillComboBox( HINSTANCE hInstance, HWND hCtrlWnd, int nIDString,
  1569. //                          WORD NEAR *npTable, WORD wTableLen,
  1570. //                          WORD wCurrentSetting )
  1571. //
  1572. //  Description:
  1573. //     Fills the given combo box with strings from the resource
  1574. //     table starting at nIDString.  Associated items are
  1575. //     added from given table.  The combo box is notified of
  1576. //     the current setting.
  1577. //
  1578. //  Parameters:
  1579. //     HINSTANCE hInstance
  1580. //        handle to application instance
  1581. //
  1582. //     HWND hCtrlWnd
  1583. //        handle to combo box control
  1584. //
  1585. //     int nIDString
  1586. //        first resource string id
  1587. //
  1588. //     DWORD NEAR *npTable
  1589. //        near point to table of associated values
  1590. //
  1591. //     WORD wTableLen
  1592. //        length of table
  1593. //
  1594. //     DWORD dwCurrentSetting
  1595. //        current setting (for combo box selection)
  1596. //
  1597. //---------------------------------------------------------------------------
  1598.  
  1599. VOID NEAR FillComboBox( HINSTANCE hInstance, HWND hCtrlWnd, int nIDString,
  1600.                         DWORD NEAR *npTable, WORD wTableLen,
  1601.                         DWORD dwCurrentSetting )
  1602. {
  1603.    char  szBuffer[ MAXLEN_TEMPSTR ] ;
  1604.    WORD  wCount, wPosition ;
  1605.  
  1606.    for (wCount = 0; wCount < wTableLen; wCount++)
  1607.    {
  1608.       // load the string from the string resources and
  1609.       // add it to the combo box
  1610.  
  1611.       LoadString( hInstance, nIDString + wCount, szBuffer, sizeof( szBuffer ) ) ;
  1612.       wPosition = LOWORD( SendMessage( hCtrlWnd, CB_ADDSTRING, 0,
  1613.                                        (LPARAM) (LPSTR) szBuffer ) ) ;
  1614.  
  1615.       // use item data to store the actual table value
  1616.  
  1617.       SendMessage( hCtrlWnd, CB_SETITEMDATA, (WPARAM) wPosition,
  1618.                    (LPARAM) *(npTable + wCount) ) ;
  1619.  
  1620.       // if this is our current setting, select it
  1621.  
  1622.       if (*(npTable + wCount) == dwCurrentSetting)
  1623.          SendMessage( hCtrlWnd, CB_SETCURSEL, (WPARAM) wPosition, 0L ) ;
  1624.    }
  1625.  
  1626. } // end of FillComboBox()
  1627.  
  1628. //---------------------------------------------------------------------------
  1629. //  BOOL NEAR SettingsDlgInit( HWND hDlg )
  1630. //
  1631. //  Description:
  1632. //     Puts current settings into dialog box (via CheckRadioButton() etc.)
  1633. //
  1634. //  Parameters:
  1635. //     HWND hDlg
  1636. //        handle to dialog box
  1637. //
  1638. //  Win-32 Porting Issues:
  1639. //     - Constants require DWORD arrays for baud rate table, etc.
  1640. //     - There is no "MAXCOM" function in Win-32.  Number of COM ports
  1641. //       is assumed to be 4.
  1642. //
  1643. //---------------------------------------------------------------------------
  1644.  
  1645. BOOL NEAR SettingsDlgInit( HWND hDlg )
  1646. {
  1647.    char       szBuffer[ MAXLEN_TEMPSTR ], szTemp[ MAXLEN_TEMPSTR ] ;
  1648.    NPTTYINFO  npTTYInfo ;
  1649.    WORD       wCount, wMaxCOM, wPosition ;
  1650.  
  1651.    if (NULL == (npTTYInfo = (NPTTYINFO) GET_PROP( hDlg, ATOM_TTYINFO )))
  1652.       return ( FALSE ) ;
  1653.  
  1654.    wMaxCOM = MAXPORTS ;
  1655.  
  1656.    // load the COM prefix from resources
  1657.  
  1658.    LoadString( GETHINST( hDlg ), IDS_COMPREFIX, szTemp, sizeof( szTemp ) ) ;
  1659.  
  1660.    // fill port combo box and make initial selection
  1661.  
  1662.    for (wCount = 0; wCount < wMaxCOM; wCount++)
  1663.    {
  1664.       wsprintf( szBuffer, "%s%d", (LPSTR) szTemp, wCount + 1 ) ;
  1665.       SendDlgItemMessage( hDlg, IDD_PORTCB, CB_ADDSTRING, 0,
  1666.                           (LPARAM) (LPSTR) szBuffer ) ;
  1667.    }
  1668.  
  1669.    SendDlgItemMessage( hDlg, IDD_PORTCB, CB_SETCURSEL,
  1670.                        (WPARAM) (PORT( npTTYInfo ) - 1), 0L ) ;
  1671.  
  1672.    // disable COM port combo box if connection has already been
  1673.    // established (e.g. OpenComm() already successful)
  1674.  
  1675.    EnableWindow( GetDlgItem( hDlg, IDD_PORTCB ), !CONNECTED( npTTYInfo ) ) ;
  1676.  
  1677.    // fill baud combo box and make initial selection
  1678.  
  1679.    FillComboBox( GETHINST( hDlg ), GetDlgItem( hDlg, IDD_BAUDCB ),
  1680.                  IDS_BAUD110, BaudTable,
  1681.                  sizeof( BaudTable ) / sizeof( BaudTable[ 0 ] ),
  1682.                  BAUDRATE( npTTYInfo ) ) ;
  1683.  
  1684.    // fill data bits combo box and make initial selection
  1685.  
  1686.    for (wCount = 5; wCount < 9; wCount++)
  1687.    {
  1688.       wsprintf( szBuffer, "%d", wCount ) ;
  1689.       wPosition = LOWORD( SendDlgItemMessage( hDlg, IDD_DATABITSCB,
  1690.                                               CB_ADDSTRING, 0,
  1691.                                               (LPARAM) (LPSTR) szBuffer ) ) ;
  1692.  
  1693.       // if current selection, tell the combo box
  1694.  
  1695.       if (wCount == BYTESIZE( npTTYInfo ))
  1696.          SendDlgItemMessage( hDlg, IDD_DATABITSCB, CB_SETCURSEL,
  1697.                              (WPARAM) wPosition, 0L ) ;
  1698.    }
  1699.  
  1700.    // fill parity combo box and make initial selection
  1701.  
  1702.    FillComboBox( GETHINST( hDlg ), GetDlgItem( hDlg, IDD_PARITYCB ),
  1703.                  IDS_PARITYNONE, ParityTable,
  1704.                  sizeof( ParityTable ) / sizeof( ParityTable[ 0 ] ),
  1705.                  PARITY( npTTYInfo ) ) ;
  1706.  
  1707.    // fill stop bits combo box and make initial selection
  1708.  
  1709.    FillComboBox( GETHINST( hDlg ), GetDlgItem( hDlg, IDD_STOPBITSCB ),
  1710.                  IDS_ONESTOPBIT, StopBitsTable,
  1711.                  sizeof( StopBitsTable ) / sizeof ( StopBitsTable ),
  1712.                  STOPBITS( npTTYInfo ) ) ;
  1713.  
  1714.    // initalize the flow control settings
  1715.  
  1716.    CheckDlgButton( hDlg, IDD_DTRDSR,
  1717.                    (FLOWCTRL( npTTYInfo ) & FC_DTRDSR) > 0 ) ;
  1718.    CheckDlgButton( hDlg, IDD_RTSCTS,
  1719.                    (FLOWCTRL( npTTYInfo ) & FC_RTSCTS) > 0 ) ;
  1720.    CheckDlgButton( hDlg, IDD_XONXOFF,
  1721.                    (FLOWCTRL( npTTYInfo ) & FC_XONXOFF) > 0 ) ;
  1722.  
  1723.    // other TTY settings
  1724.  
  1725.    CheckDlgButton( hDlg, IDD_AUTOWRAP, AUTOWRAP( npTTYInfo ) ) ;
  1726.    CheckDlgButton( hDlg, IDD_NEWLINE, NEWLINE( npTTYInfo ) ) ;
  1727.    CheckDlgButton( hDlg, IDD_LOCALECHO, LOCALECHO( npTTYInfo ) ) ;
  1728.  
  1729.    // control options
  1730.  
  1731.    // "Use CN_RECEIVE" is not valid under Win-32
  1732.  
  1733.    EnableWindow( GetDlgItem( hDlg, IDD_USECNRECEIVE ), FALSE ) ;
  1734.  
  1735.    CheckDlgButton( hDlg, IDD_DISPLAYERRORS, DISPLAYERRORS( npTTYInfo ) ) ;
  1736.  
  1737.    return ( TRUE ) ;
  1738.  
  1739. } // end of SettingsDlgInit()
  1740.  
  1741. //---------------------------------------------------------------------------
  1742. //  BOOL NEAR SelectTTYFont( HWND hDlg )
  1743. //
  1744. //  Description:
  1745. //     Selects the current font for the TTY screen.
  1746. //     Uses the Common Dialog ChooseFont() API.
  1747. //
  1748. //  Parameters:
  1749. //     HWND hDlg
  1750. //        handle to settings dialog
  1751. //
  1752. //---------------------------------------------------------------------------
  1753.  
  1754. BOOL NEAR SelectTTYFont( HWND hDlg )
  1755. {
  1756.    CHOOSEFONT  cfTTYFont ;
  1757.    NPTTYINFO   npTTYInfo ;
  1758.  
  1759.    if (NULL == (npTTYInfo = (NPTTYINFO) GET_PROP( hDlg, ATOM_TTYINFO )))
  1760.       return ( FALSE ) ;
  1761.  
  1762.    cfTTYFont.lStructSize    = sizeof( CHOOSEFONT ) ;
  1763.    cfTTYFont.hwndOwner      = hDlg ;
  1764.    cfTTYFont.hDC            = NULL ;
  1765.    cfTTYFont.rgbColors      = FGCOLOR( npTTYInfo ) ;
  1766.    cfTTYFont.lpLogFont      = &LFTTYFONT( npTTYInfo ) ;
  1767.    cfTTYFont.Flags          = CF_SCREENFONTS | CF_FIXEDPITCHONLY |
  1768.                               CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ;
  1769.    cfTTYFont.lCustData      = 0 ;
  1770.    cfTTYFont.lpfnHook       = NULL ;
  1771.    cfTTYFont.lpTemplateName = NULL ;
  1772.    cfTTYFont.hInstance      = GETHINST( hDlg ) ;
  1773.  
  1774.    if (ChooseFont( &cfTTYFont ))
  1775.    {
  1776.      FGCOLOR( npTTYInfo ) = cfTTYFont.rgbColors ;
  1777.      ResetTTYScreen( GetParent( hDlg ), npTTYInfo ) ;
  1778.    }
  1779.  
  1780.    return ( TRUE ) ;
  1781.  
  1782. } // end of SelectTTYFont()
  1783.  
  1784. //---------------------------------------------------------------------------
  1785. //  BOOL NEAR SettingsDlgTerm( HWND hDlg )
  1786. //
  1787. //  Description:
  1788. //     Puts dialog contents into TTY info structure.
  1789. //
  1790. //  Parameters:
  1791. //     HWND hDlg
  1792. //        handle to settings dialog
  1793. //
  1794. //  Win-32 Porting Issues:
  1795. //     - Baud rate requires DWORD values.
  1796. //
  1797. //---------------------------------------------------------------------------
  1798.  
  1799. BOOL NEAR SettingsDlgTerm( HWND hDlg )
  1800. {
  1801.    NPTTYINFO  npTTYInfo ;
  1802.    WORD       wSelection ;
  1803.  
  1804.    if (NULL == (npTTYInfo = (NPTTYINFO) GET_PROP( hDlg, ATOM_TTYINFO )))
  1805.       return ( FALSE ) ;
  1806.  
  1807.    // get port selection
  1808.  
  1809.    PORT( npTTYInfo ) =
  1810.       LOBYTE( LOWORD( SendDlgItemMessage( hDlg, IDD_PORTCB,
  1811.                                           CB_GETCURSEL,
  1812.                                           0, 0L ) ) + 1 ) ;
  1813.    // get baud rate selection
  1814.  
  1815.    wSelection =
  1816.       LOWORD( SendDlgItemMessage( hDlg, IDD_BAUDCB, CB_GETCURSEL,
  1817.                                   0, 0L ) ) ;
  1818.    BAUDRATE( npTTYInfo ) =
  1819.       SendDlgItemMessage( hDlg, IDD_BAUDCB, CB_GETITEMDATA,
  1820.                           (WPARAM) wSelection, 0L ) ;
  1821.  
  1822.    // get data bits selection
  1823.  
  1824.    BYTESIZE( npTTYInfo ) =
  1825.       LOBYTE( LOWORD( SendDlgItemMessage( hDlg, IDD_DATABITSCB,
  1826.                                           CB_GETCURSEL,
  1827.                                           0, 0L ) ) + 5 ) ;
  1828.  
  1829.    // get parity selection
  1830.  
  1831.    wSelection =
  1832.       LOWORD( SendDlgItemMessage( hDlg, IDD_PARITYCB, CB_GETCURSEL,
  1833.                                   0, 0L ) ) ;
  1834.    PARITY( npTTYInfo ) =
  1835.       LOBYTE( LOWORD( SendDlgItemMessage( hDlg, IDD_PARITYCB,
  1836.                                           CB_GETITEMDATA,
  1837.                                           (WPARAM) wSelection,
  1838.                                           0L ) ) ) ;
  1839.  
  1840.    // get stop bits selection
  1841.  
  1842.    wSelection =
  1843.       LOWORD( SendDlgItemMessage( hDlg, IDD_STOPBITSCB, CB_GETCURSEL,
  1844.                                   0, 0L ) ) ;
  1845.    STOPBITS( npTTYInfo ) =
  1846.       LOBYTE( LOWORD( SendDlgItemMessage( hDlg, IDD_STOPBITSCB,
  1847.                                           CB_GETITEMDATA,
  1848.                                           (WPARAM) wSelection, 0L ) ) ) ;
  1849.  
  1850.    // get flow control settings
  1851.  
  1852.    FLOWCTRL( npTTYInfo ) = 0 ;
  1853.    if (IsDlgButtonChecked( hDlg, IDD_DTRDSR ))
  1854.       FLOWCTRL( npTTYInfo ) |= FC_DTRDSR ;
  1855.    if (IsDlgButtonChecked( hDlg, IDD_RTSCTS ))
  1856.       FLOWCTRL( npTTYInfo ) |= FC_RTSCTS ;
  1857.    if (IsDlgButtonChecked( hDlg, IDD_XONXOFF ))
  1858.       FLOWCTRL( npTTYInfo ) |= FC_XONXOFF ;
  1859.  
  1860.    // get other various settings
  1861.  
  1862.    AUTOWRAP( npTTYInfo ) = IsDlgButtonChecked( hDlg, IDD_AUTOWRAP ) ;
  1863.    NEWLINE( npTTYInfo ) = IsDlgButtonChecked( hDlg, IDD_NEWLINE ) ;
  1864.    LOCALECHO( npTTYInfo ) = IsDlgButtonChecked( hDlg, IDD_LOCALECHO ) ;
  1865.  
  1866.    // control options
  1867.  
  1868.    USECNRECEIVE( npTTYInfo ) = IsDlgButtonChecked( hDlg, IDD_USECNRECEIVE ) ;
  1869.    DISPLAYERRORS( npTTYInfo ) = IsDlgButtonChecked( hDlg, IDD_DISPLAYERRORS ) ;
  1870.  
  1871.    return ( TRUE ) ;
  1872.  
  1873. } // end of SettingsDlgTerm()
  1874.  
  1875. //---------------------------------------------------------------------------
  1876. //  BOOL FAR PASCAL SettingsDlgProc( HWND hDlg, UINT uMsg,
  1877. //                                   WPARAM wParam, LPARAM lParam )
  1878. //
  1879. //  Description:
  1880. //     This handles all of the user preference settings for
  1881. //     the TTY.
  1882. //
  1883. //  Parameters:
  1884. //     same as all dialog procedures
  1885. //
  1886. //  Win-32 Porting Issues:
  1887. //     - npTTYInfo is a DWORD in Win-32.
  1888. //
  1889. //---------------------------------------------------------------------------
  1890.  
  1891. BOOL FAR PASCAL SettingsDlgProc( HWND hDlg, UINT uMsg,
  1892.                                  WPARAM wParam, LPARAM lParam )
  1893. {
  1894.    switch (uMsg)
  1895.    {
  1896.       case WM_INITDIALOG:
  1897.       {
  1898.          NPTTYINFO  npTTYInfo ;
  1899.  
  1900.          // get & save pointer to TTY info structure
  1901.  
  1902.          npTTYInfo = (NPTTYINFO) lParam ;
  1903.  
  1904.          SET_PROP( hDlg, ATOM_TTYINFO, (HANDLE) npTTYInfo ) ;
  1905.  
  1906.          return ( SettingsDlgInit( hDlg ) ) ;
  1907.       }
  1908.  
  1909.       case WM_COMMAND:
  1910.          switch ( LOWORD( wParam ))
  1911.          {
  1912.             case IDD_FONT:
  1913.                return ( SelectTTYFont( hDlg ) ) ;
  1914.  
  1915.             case IDD_OK:
  1916.                // Copy stuff into structure
  1917.                SettingsDlgTerm( hDlg ) ;
  1918.                EndDialog( hDlg, TRUE ) ;
  1919.                return ( TRUE ) ;
  1920.  
  1921.             case IDD_CANCEL:
  1922.                // Just end
  1923.                EndDialog( hDlg, TRUE ) ;
  1924.                return ( TRUE ) ;
  1925.          }
  1926.          break;
  1927.  
  1928.       case WM_DESTROY:
  1929.          REMOVE_PROP( hDlg, ATOM_TTYINFO ) ;
  1930.          break ;
  1931.    }
  1932.    return ( FALSE ) ;
  1933.  
  1934. } // end of SettingsDlgProc()
  1935.  
  1936. //************************************************************************
  1937. //  DWORD FAR PASCAL CommWatchProc( LPSTR lpData )
  1938. //
  1939. //  Description:
  1940. //     A secondary thread that will watch for COMM events.
  1941. //
  1942. //  Parameters:
  1943. //     LPSTR lpData
  1944. //        32-bit pointer argument
  1945. //
  1946. //  Win-32 Porting Issues:
  1947. //     - Added this thread to watch the communications device and
  1948. //       post notifications to the associated window.
  1949. //
  1950. //************************************************************************
  1951.  
  1952. DWORD FAR PASCAL CommWatchProc( LPSTR lpData )
  1953. {
  1954.    DWORD       dwEvtMask ;
  1955.    NPTTYINFO   npTTYInfo = (NPTTYINFO) lpData ;
  1956.    OVERLAPPED  os ;
  1957.     int        nLength ;
  1958.    BYTE       abIn[ MAXBLOCK + 1] ;
  1959.  
  1960.    memset( &os, 0, sizeof( OVERLAPPED ) ) ;
  1961.  
  1962.    // create I/O event used for overlapped read
  1963.  
  1964.    os.hEvent = CreateEvent( NULL,    // no security
  1965.                             TRUE,    // explicit reset req
  1966.                             FALSE,   // initial event reset
  1967.                             NULL ) ; // no name
  1968.    if (os.hEvent == NULL)
  1969.    {
  1970.       MessageBox( NULL, "Failed to create event for thread!", "TTY Error!",
  1971.                   MB_ICONEXCLAMATION | MB_OK ) ;
  1972.       return ( FALSE ) ;
  1973.    }
  1974.  
  1975.    if (!SetCommMask( COMDEV( npTTYInfo ), EV_RXCHAR ))
  1976.       return ( FALSE ) ;
  1977.  
  1978.    while ( CONNECTED( npTTYInfo ) )
  1979.    {
  1980.       dwEvtMask = 0 ;
  1981.  
  1982.       WaitCommEvent( COMDEV( npTTYInfo ), &dwEvtMask, NULL );
  1983.  
  1984.       if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
  1985.       {
  1986.          do
  1987.          {
  1988.             if (nLength = ReadCommBlock( hTTYWnd, (LPSTR) abIn, MAXBLOCK ))
  1989.             {
  1990.                WriteTTYBlock( hTTYWnd, (LPSTR) abIn, nLength ) ;
  1991.  
  1992.                // force a paint
  1993.  
  1994.                UpdateWindow( hTTYWnd ) ;
  1995.             }
  1996.          }
  1997.          while ( nLength > 0 ) ;
  1998.       }
  1999.    }
  2000.  
  2001.    // get rid of event handle
  2002.  
  2003.    CloseHandle( os.hEvent ) ;
  2004.  
  2005.    // clear information in structure (kind of a "we're done flag")
  2006.  
  2007.    THREADID( npTTYInfo ) = 0 ;
  2008.    HTHREAD( npTTYInfo ) = NULL ;
  2009.  
  2010.    return( TRUE ) ;
  2011.  
  2012. } // end of CommWatchProc()
  2013.  
  2014.  
  2015. //---------------------------------------------------------------------------
  2016. //  End of File: tty.c
  2017. //---------------------------------------------------------------------------
  2018.