File:  [OS/2 SDKs] / pmsdk / samples / pmcomm / pmcomm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:28:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: pmsdk-1988, HEAD
Microsoft OS/2 SDK PM 08-08-1988

/*-----------------------------------------------------------
  PMCOMM.C -- PM Communications program.
  Created by Microsoft Corp., 1988
  -----------------------------------------------------------*/

#include <os2def.h>

#define  INCL_DOSDEVICES
#define  INCL_DOSPROCESS
#include <bsedos.h>    /* for threads       */

#define  INCL_WIN
#define  INCL_GPI
#include <pm.h>

#include <stdio.h>     /* for filelength () and sprintf */
#include <stdlib.h>    /* for min max */
#include <string.h>    /* for strcpy strcat */
#include "pmcomm.h"

#define MAXWIDTH     80  /* # characters wide. */
#define MAXLINES     20  /* # lines. */
#define BUFFERMAX    (MAXWIDTH * MAXLINES)
#define MAXFILESIZE  BUFFERMAX-1
#define WM_BLAST     (WM_USER+1)

#define FILLBUF(x,y) (cDisplayBuf[(y * MAXWIDTH)+x])

CHAR    szClassName [10] ;
CHAR    szTitleBar  [40] ;
CHAR    szINIFile   [20] ;
CHAR    szUnTitled  [14] ;

BYTE    bSaveXONChar;    /* from DCB structure */

char    cInBuffer[INBUFLENGTH]; /* comm input buffer                  */
char    cTempBuf[INBUFLENGTH];  /* temp buf from comm to display buf. */
char    cDisplayBuf[BUFFERMAX]; /* buffer to hold contents.           */
char    cCaptionBuf[40];        /* buffer for caption bar.            */
char    *pBlastString;
char    *pTempBuf;
char    *pTempPt;

char    *pStartLine[MAXLINES]; /* # of pointers to make     */
int     iLineLength[MAXLINES]; /* line length of each row   */
int     iMaxLines;
int     iMaxWidth;             /* used to see if you overflow line    */
SHORT   xCursor, yCursor;      /* cursor location for buffer & screen */
SHORT   xPause,  yPause;       /* save currsor position during pause  */
SHORT   xChar, yChar;          /* size of character for display       */

int     iBufPos;               /* current buffer position     */

HAB     hab ;
char    *pFile;              /* pointer to provided file    */
BOOL    bGotSettings;        /* do we have the settings?    */
BOOL    bSettingsChanged;    /* did the settings change?    */
BOOL    bTestOn;             /* flag to flip test on or off */
BOOL    bEchoOn;             /* flag to set echo  on or off */
BOOL    bPauseOn;            /* flag to set pause on or off */
BOOL    bCaptureOn;          /* flag to set capture on |off */
BOOL    bCommOpen;           /* flag to set if comm is open */
BOOL    bWordWrap;           /* flag to set word wrap       */
BOOL    bScroll;             /* if scroll occured skip paint*/
BOOL    bResult;
BOOL    bOverFlow;           /* flag for circular buffer    */
BOOL    bExitReadThread;     /* flag to exit ReadComm thread*/
int     i;                   /* global use of a temp int    */
int     iToFormat;           /* # of bytes formated         */

HWND    hGWnd ;              /* Global handle to window     */
HWND    hGMenuWnd ;          /* Global handle to menu       */
HWND    hWndFrame ;          /* Global handle to frame      */
HWND    hwndHscroll, hwndVscroll ;

USHORT  uCommHandle = NULL;  /* COM port file handle        */

USHORT  usRetCode,     /* return code, value not to be saved */
        uStatus,
        Result = TRUE;

USHORT  uTempParity, uTempStopBits, uTempDataBits;

char    cSaveFile[24];  /* string to hold capture file name */

struct CommRecord {
   USHORT uPortName,
          uBaudRate,
          uDataBits,
          uStopBits,
          uParity,
          uConnect,
          uDialType,
          uWaitTone,
          uWaitCarrier;
    char  cString[24];
  } CommSpec;

/* ------------ thread related variables -------------- */

LONG      lReadSemTrigger;
TID       idThread;
UCHAR     cReadThreadStack[4096];

/* ------------ Forward references & type checking -------- */

BOOL   ReadINIFile(char *);
void   InitBuffers(void);     /* Start the comm session */
BOOL   InitCommPort(void);    /* Initialise comm port   */
void   BuildCaption(int);     /* build caption bar with file name   */
void   CloseComm(void);       /* close modem connection & com port  */
void   GetLines(void);        /* Gets pointer to each line & length */
void   Error(int, int);       /* Display error message */
void   FAR PASCAL ReadCommThread();
void   WriteCommPort(USHORT); /* write char to comm port */
void   TestComm(void);        /* write char to comm port */
void   Dump();

MRESULT EXPENTRY PMCommWndProc (HWND, USHORT, MPARAM, MPARAM);

/* ===================== MAIN ========================== */
main (argc, argv)
int    argc ;
char   *argv [] ;
{
   HMQ      hmq ;
   HWND     hwndPMComm;
   QMSG     qmsg ;
   ULONG    flCreate;

   hab = WinInitialize (0);
   hmq = WinCreateMsgQueue (hab, 0);

   WinLoadString (hab, NULL, IDS_CLASS,   sizeof szClassName, szClassName);
   WinLoadString (hab, NULL, IDS_TITLE,   sizeof szTitleBar,  szTitleBar);
   WinLoadString (hab, NULL, IDS_INIFILE, sizeof szINIFile,   szINIFile);
   WinLoadString (hab, NULL, IDS_UNTITLED,sizeof szUnTitled,  szUnTitled);

   WinRegisterClass (hab, szClassName, PMCommWndProc, 0L, 0);

   flCreate = FCF_STANDARD | FCF_VERTSCROLL | FCF_HORZSCROLL;
   hWndFrame = WinCreateStdWindow (HWND_DESKTOP,
                            WS_VISIBLE | FS_ICON | FS_ACCELTABLE,
                            &flCreate, szClassName, szTitleBar,
                            0L, NULL, ID_RESOURCE, &hwndPMComm);

   hGMenuWnd = WinWindowFromID ( hWndFrame, FID_MENU);

   if (argc > 1)
      pFile = argv[1]; /* pass pointer to file */
   else
      pFile = NULL;
   
   bResult = ReadINIFile(pFile);

   while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
        WinDispatchMsg (hab, &qmsg);

   DosSuspendThread (idThread);

   WinDestroyWindow (hWndFrame);
   WinDestroyMsgQueue (hmq);
   WinTerminate (hab);
   return 0 ;
}


/* -----------------------------------------------
   ReadINIFile

   Read in a file if one is provided
    else try the default file.
   If it is provided then gather the comm settings.

   ----------------------------------------------- */
BOOL ReadINIFile(pFile)
char  *pFile;
{
  FILE    *fp ;
  USHORT  uBytesRead ;

  bGotSettings     = FALSE;
  bSettingsChanged = FALSE;

  if (pFile != NULL ) {  /* read file name that is provided */
    if ( (fp = fopen(pFile, "r")) == NULL) {
       WinMessageBox (HWND_DESKTOP, hGWnd, pFile, "File not found", NULL, MB_OK);
       BuildCaption( 2 ); /* untitled */
    }
  }
  else /* read default file settings */
       if ( (fp = fopen(szINIFile, "r")) == NULL) {
          BuildCaption( 2 ); /* untitled */
       }

  if (fp) {
     uBytesRead = fread( &CommSpec, 1, sizeof(CommSpec), fp );
     fclose(fp);
     if (uBytesRead == sizeof(CommSpec)) {
        bGotSettings = TRUE;
        BuildCaption( (pFile ? 1 : 0) );
     }
     else {
        WinMessageBox (HWND_DESKTOP, hGWnd, "Reading file.", NULL, NULL, MB_OK);
        return FALSE;
     }

     bResult = WinMessageBox (HWND_DESKTOP, hGWnd, "Do you wish to connect?",
                                                  "PM COMM", NULL, MB_YESNO);
     if (bResult == MBID_YES)
        WinPostMsg( hGWnd, WM_COMMAND, MPFROM2SHORT (IDM_START, 0), 0L );
  }
  return TRUE;

}


/* -------------------------------------------------- */
/*   This routine builds the caption bar.
 */
void BuildCaption(iCaptionType)
int  iCaptionType;
{

  /* always starts off "PM Terminal [ ] - " */
  strcpy(cCaptionBuf, szTitleBar);
  switch (iCaptionType) {
     case 0: 
             strcat( cCaptionBuf, szINIFile );  /* default file name  */
             break;
     case 1:
             strcat( cCaptionBuf, pFile );      /* provided file name */ 
             break;
     default:
             strcat( cCaptionBuf, szUnTitled ); /* untitled used      */
             break;
  }

  WinSetWindowText( WinQueryWindow (hGWnd, QW_PARENT, FALSE), cCaptionBuf );

}



/* -------------------------------------------------
      Set up everything for the comm session.
   ------------------------------------------------- */
void InitBuffers()
{
  int i;

  for ( i=0 ; i<BUFFERMAX ; i++ ) /* clear Display buffer */
     cDisplayBuf[i] = 0;

  pTempBuf = cTempBuf;
  for ( i=0 ; i<INBUFLENGTH ; i++ ) /* clear temp buffer */
     *pTempBuf++ = 0;

  for ( i=0 ; i<MAXLINES ; i++ )  /* set line lenghts to 0 */
     iLineLength[i] = 0;

  for ( i=0 ; i<MAXLINES ; i++ )  /* set ptr to each line  */
     pStartLine[i] = (&cDisplayBuf[0])+(i*MAXWIDTH);

  iMaxLines = 0;

  iBufPos = 0;           /* set current buffer position    */
  xCursor = 0;           /* set cursor  position           */
  yCursor = 0;

  bEchoOn    = FALSE;    /* see what you type.             */
  bScroll    = FALSE;    /* set scroll so paint will work  */
  bOverFlow  = FALSE;    /* clear buffer overflow          */
  bCaptureOn = FALSE;    /* capture input to a file.       */

  bPauseOn = FALSE;      /* allows you to pause a session  */

  /* hide scroll bars */
  WinSetParent(hwndHscroll, HWND_OBJECT, FALSE);
  WinSetParent(hwndVscroll, HWND_OBJECT, FALSE);

}


/* ------------------------------------------------- */
BOOL InitCommPort()    /* initialise com port */
{

  USHORT    ActionTaken;          /* action: returned by OS/2 */
  char      cPortName[5];         /* port name with appended com # */

  char   FlushData,      /* data returned by flush IOCTL function */
         FlushParm = FLUSH_CMDINFO; /* param to flush IOCTL function */

  struct LineChar {               /* line characteristics */
         BYTE   bDataBits;
         BYTE   bParity;
         BYTE   bStopBits;
  } sLineChar;

  struct DCB {                    /* device control block information */
         USHORT usWriteTimeout;
         USHORT usReadTimeout;
         BYTE   bFlags1;
         BYTE   bFlags2;
         BYTE   bFlags3;
         BYTE   bErrorReplacementChar;
         BYTE   bBreakReplacementChar;
         BYTE   bXONChar;
         BYTE   bXOFFChar;
  } sDCB;

  /* open the com port */
  sprintf( cPortName, "COM%d", CommSpec.uPortName );
  if ((usRetCode = DosOpen( cPortName, &uCommHandle, &ActionTaken,
                           0L, 0, 0x0001, 0x0042, 0L)) != 0) {
    Error(ERR_DOSOPEN, usRetCode);
    return FALSE;
  }
  /* set the baud rate */
  if ((usRetCode = DosDevIOCtl(0L, &(CommSpec.uBaudRate), 
                             SETBAUD, SERIAL, uCommHandle)) != 0) {
    Error(ERR_IOCTLSETBAUD, usRetCode);
    return FALSE;
  }

  /* set Data Bits, Stop Bits, Parity */

  sLineChar.bDataBits = (BYTE) CommSpec.uDataBits; 
  sLineChar.bParity   = (BYTE)(CommSpec.uParity ? 0 : 2); 
  sLineChar.bStopBits = (BYTE) CommSpec.uStopBits;

  if ((usRetCode = DosDevIOCtl(0L, &sLineChar, SETLINECHAR, 
                              SERIAL, uCommHandle)) != 0) {
    Error(ERR_IOCTLSETLINECHAR, usRetCode);
    return FALSE;
  }

  /* get device control block info */
  if ((usRetCode = DosDevIOCtl( &sDCB, 0L, GETDCB, SERIAL, 
                             uCommHandle)) != 0) {
    Error(ERR_IOCTLGETDCB, usRetCode);
    return FALSE;
  }

  bSaveXONChar = sDCB.bXONChar;

  sDCB.bFlags2 |= 0x03;    /* enable auto Xmit and recv flow control */
  sDCB.bFlags3 &= 0xf9;    /* clear read timeout flags */
  sDCB.bFlags3 |= 0x04;    /* set wait for something read timeout */
  sDCB.usReadTimeout = READTIMEOUT; /* set read timout value */

  /* set device control block info */
  if ((usRetCode = DosDevIOCtl(0L, (char *) &sDCB, SETDCB, SERIAL, 
                              uCommHandle)) != 0) {
    Error(ERR_IOCTLSETDCB, usRetCode);
    return FALSE;
  }

   /* flush transmit/receive queues */
   if ((usRetCode = DosDevIOCtl(&FlushData, &FlushParm, 
                               FLUSHINPUT, GENERIC, uCommHandle)) != 0) 
         Error(ERR_IOCTLFLUSHQUE, usRetCode);

   if ((usRetCode = DosDevIOCtl(&FlushData, &FlushParm, 
                               FLUSHOUTPUT, GENERIC, uCommHandle)) != 0) 
         Error(ERR_IOCTLFLUSHQUE, usRetCode);

  return TRUE;

}


/* -------------------------------------------------
   ReadCommPort
  
   This routine is executed by a thread. It loops continuously 
   waiting to receive data from the comm port and writing it out 
   to a tempoary buffer. The loop waits under three conditions: 
      1] The person selected the STOP menu item,
      2] The person selected the PAUSE menu item,
      3] The routine to display the characters in the current
             input queue is not finished.
   This thread terminates when the user exits the program.

   Suggestions/To do list:
     o Make a circular buffer to have DosRead into, cInBuffer.
     o Make another thread to take characters out of the
       cInBuffer, and format them correctly into the DisplayBuffer.
  ----------------------------------------------------*/

void FAR PASCAL ReadCommThread()
{
  USHORT  usNumBytes;   /* number of bytes actually read */
  PUSHORT pfCommErr;    /* pointer to variable to receive error */

  while ( !bExitReadThread ) {

     DosSemWait (&lReadSemTrigger, -1L); /* to allow for PAUSE */


     if (bTestOn) {
        if ((usRetCode = DosDevIOCtl( &pfCommErr, 0L, GETCOMERROR, 
                                     SERIAL, uCommHandle)) != 0)
           Error(ERR_IOCTLGETCOMERROR, usRetCode);
     }

     if ((usRetCode = DosRead(uCommHandle, cInBuffer, 1024, &usNumBytes)) != 0)
        Error(ERR_DOSREAD, usRetCode);

     if (usNumBytes) {
        DosSemSet (&lReadSemTrigger);
        if (bCaptureOn) {

           FILE    *fp ;

           if ((fp = fopen( "f:readcomm.dmp", "ab")) != NULL) {
              fwrite( cInBuffer, 1, usNumBytes, fp );
              fclose(fp);
           }
        }

        WinPostMsg( hGWnd, WM_BLAST, MPFROM2SHORT (0, usNumBytes), (MPARAM)0 );
        /* pTempBuf = cInBuffer; */ /* may cause timing problem w/ word wrap */
     }

   }   /* end while */
   DosExit(0,0);
}


/* ----------------------------------------------------
     Write one character at a time to the Comm Port.

     Suggestions/To do list:
        Make this a separate thread.  Put the characters in a 
        circular buffer and put the characters out when it's ready.  
  ----------------------------------------------------*/
void WriteCommPort(usCharOut)
USHORT  usCharOut;
{
   USHORT    uNumBytes;    /* number of bytes actually written */

   if ((usRetCode = DosWrite(uCommHandle, &usCharOut, 1, &uNumBytes )) != 0)
      Error(ERR_DOSWRITE, usRetCode);
}


/* ---------------------------------------------------- */
void CloseComm()
{

  FILE    *fp ;

  char   FlushData,      /* data returned by flush IOCTL function */
         FlushParm = FLUSH_CMDINFO; /* param to flush IOCTL function */
      
  if ( DosSemSet(&lReadSemTrigger) != 0)
    WinMessageBox ( HWND_DESKTOP, hGWnd,
                    "Setting Sem ReadSem." , NULL, NULL, MB_OK);

  /* flush transmit/receive queues */
  if ((usRetCode = DosDevIOCtl(&FlushData, &FlushParm, 
                              FLUSHINPUT, GENERIC, uCommHandle)) != 0) 
        Error(ERR_IOCTLFLUSHQUE, usRetCode);

  if ((usRetCode = DosDevIOCtl(&FlushData, &FlushParm, 
                              FLUSHOUTPUT, GENERIC, uCommHandle)) != 0) 
        Error(ERR_IOCTLFLUSHQUE, usRetCode);

  if ((usRetCode = DosClose(uCommHandle)) != 0)
     WinMessageBox ( HWND_DESKTOP, hGWnd,
                    "Closing Comm Port" , NULL, NULL, MB_OK);
  bCommOpen = FALSE;

  if ( bSettingsChanged ) {
     bResult = WinMessageBox (HWND_DESKTOP, hGWnd, "Do you wish to Save?",
                                "Settings changed.", NULL, MB_YESNO);
     if (bResult == MBID_YES) {
       if ((fp = fopen( (pFile ? pFile : szINIFile), "w")) != NULL) {
          fwrite( &CommSpec, 1, sizeof(CommSpec), fp );
          fclose(fp);
       }
     }
     bSettingsChanged = FALSE;
  }
}



/* ----------------------------------------------- */
MRESULT EXPENTRY AboutDlgProc (hDlg, msg, mp1, mp2)
HWND   hDlg ;
USHORT msg ;
MPARAM mp1 ;
MPARAM mp2 ;
{
  switch (msg) {
     case WM_COMMAND:

          switch (COMMANDMSG(&msg)->cmd) {
             case DID_OK:
             case DID_CANCEL:
                  WinDismissDlg (hDlg, TRUE);
                  break ;

             default:
                  break ;
          }
          break ;

     default:
          return WinDefDlgProc (hDlg, msg, mp1, mp2);
     }
  return FALSE ;
}


/* ----------------------------------------------- */
MRESULT EXPENTRY GetFileDlgProc (hDlg, msg, mp1, mp2)
HWND   hDlg ;
USHORT msg ;
MPARAM mp1 ;
MPARAM mp2 ;
{
  switch (msg) {
     case WM_COMMAND:

          switch (COMMANDMSG(&msg)->cmd) {
             case DID_OK:
                  WinQueryDlgItemText(  hDlg, DB_FILENAME, 24, cSaveFile );
                  bCaptureOn = TRUE;
                  WinDismissDlg (hDlg, TRUE);

             case DID_CANCEL:
                  WinDismissDlg (hDlg, FALSE);
                  break ;

             default:
                  break ;
            }
            break ;

     default:
            return WinDefDlgProc (hDlg, msg, mp1, mp2);
  }
  return FALSE ;
}


/* ----------------------------------------------- */
MRESULT EXPENTRY SettingsDlgProc (hDlg, msg, mp1, mp2)
HWND   hDlg ;
USHORT msg ;
MPARAM mp1 ;
MPARAM mp2 ;
{
  BOOL    fResult;

  switch (msg) {

     case WM_INITDLG:
         if (bGotSettings) {
            WinSetDlgItemShort( hDlg, DB_PORT,   CommSpec.uPortName, FALSE );
            WinSetDlgItemShort( hDlg, DB_BAUD,   CommSpec.uBaudRate, FALSE );
            WinSetDlgItemText(  hDlg, DB_STRING, CommSpec.cString );

            uTempParity   = CommSpec.uParity   + DB_PARITY;
            uTempStopBits = CommSpec.uStopBits + DB_STOPBITS;
            uTempDataBits = CommSpec.uDataBits + (DB_DATABITS-7);
         }
         else {      /* set the defaults */
             uTempParity   =  DB_PARITY+1;    /* odd is default */
             uTempStopBits =  DB_STOPBITS;    /* 1 is default */
             uTempDataBits =  DB_DATABITS+1;  /* 8 is default */
         }

         WinSendDlgItemMsg( hDlg, uTempParity, BM_SETCHECK,
                                  MPFROM2SHORT(TRUE, 0), 0L );
         WinSendDlgItemMsg( hDlg, uTempStopBits, BM_SETCHECK,
                                  MPFROM2SHORT(TRUE, 0), 0L );
         WinSendDlgItemMsg( hDlg, uTempDataBits, BM_SETCHECK,
                                  MPFROM2SHORT(TRUE, 0), 0L );
         break;

     case WM_CONTROL:

         if ( SHORT1FROMMP (mp1) >= DB_PARITY &&
              SHORT1FROMMP (mp1) <= DB_PARITY+2 )
            uTempParity = SHORT1FROMMP (mp1);

         if ( SHORT1FROMMP (mp1) >= DB_STOPBITS &&
              SHORT1FROMMP (mp1) <= DB_STOPBITS+2 )
            uTempStopBits = SHORT1FROMMP (mp1);

         if ( SHORT1FROMMP (mp1) >= DB_DATABITS &&
              SHORT1FROMMP (mp1) <= DB_DATABITS+1 )
            uTempDataBits = SHORT1FROMMP (mp1);

         break;

     case WM_COMMAND:

         switch (COMMANDMSG(&msg)->cmd) {
              case DID_OK:

        WinQueryDlgItemShort( hDlg, DB_PORT,   &CommSpec.uPortName, fResult);
        WinQueryDlgItemShort( hDlg, DB_BAUD,   &CommSpec.uBaudRate, fResult);
        WinQueryDlgItemText(  hDlg, DB_STRING, 24, CommSpec.cString );

        CommSpec.uParity   = uTempParity    - DB_PARITY;
        CommSpec.uStopBits = uTempStopBits  - DB_STOPBITS;
        CommSpec.uDataBits = (uTempDataBits - DB_DATABITS)+7;

        bGotSettings     = TRUE; 
        bSettingsChanged = TRUE;

                   WinDismissDlg (hDlg, TRUE);
                   break ;

              case DID_CANCEL:
                   uTempParity   = CommSpec.uParity + DB_PARITY;
                   uTempStopBits = CommSpec.uStopBits + DB_STOPBITS;
                   uTempDataBits = CommSpec.uDataBits + (DB_DATABITS-7);

                   WinDismissDlg (hDlg, FALSE);
                   break ;
              default:
                   break ;
          }
          break ;

       default:
          return WinDefDlgProc (hDlg, msg, mp1, mp2);
  }
  return FALSE ;
}



/* ----------------------------------------------- */
MRESULT EXPENTRY PMCommWndProc (hwnd, msg, mp1, mp2)
HWND   hwnd ;
USHORT msg ;
MPARAM mp1 ;
MPARAM mp2 ;
{
   static SEL    selMemBlock ;
   static SHORT  iHscrollMax, iVscrollMax, iHscrollPos, iVscrollPos,
                 yDesc, xClient, yClient, xMax, yMax;

   static int    iBytesRead;     /* # of bytes read in comm buf */
   FONTMETRICS   fm ;
   HPS           hps ;
   POINTL        ptl ;
   SHORT         iPaintBegin, iPaintEnd, iHscrollInc, iVscrollInc ;
   int           iSpaces, j, iCount, iPaintBegin1 ;
   RECTL         rclInvalid ;
   LONG          lStyle ;

   QMSG          qmsg ;

   hGWnd = hwnd;    /* Set global window handle.  */
   switch (msg) {

    case WM_CREATE:

         /*----------------------
            Query character size
           ----------------------*/

         hps = WinGetPS (hwnd);

         GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm);
         xChar = (SHORT) fm.lAveCharWidth ;
         yChar = (SHORT) fm.lMaxBaselineExt ;
         yDesc = (SHORT) fm.lMaxDescender ;

         WinReleasePS (hps);

         hwndHscroll = WinWindowFromID (
                             WinQueryWindow (hwnd, QW_PARENT, FALSE),
                             FID_HORZSCROLL);

         hwndVscroll = WinWindowFromID (
                             WinQueryWindow (hwnd, QW_PARENT, FALSE),
                             FID_VERTSCROLL);

         bPauseOn = FALSE;
         WinEnableWindow (hwndHscroll, FALSE);
         WinEnableWindow (hwndVscroll, FALSE);

         /* hide scroll bars */
         WinSetParent(hwndHscroll, HWND_OBJECT, FALSE);
         WinSetParent(hwndVscroll, HWND_OBJECT, FALSE);

         bExitReadThread = FALSE;

         DosSemSet (&lReadSemTrigger);
	 if ( DosCreateThread (ReadCommThread, &idThread,
                             cReadThreadStack + sizeof cReadThreadStack))
           WinAlarm (HWND_DESKTOP, WA_ERROR);

         break ;

    case WM_DESTROY:

         if (bCommOpen)
           CloseComm();

         bExitReadThread = TRUE;

         /* make sure these belong to the Frame before ending  */
         /* or you could also use a WinDestroyWindow on these. */

         if (!bPauseOn) {
            WinSetParent(hwndHscroll, hWndFrame, FALSE);
            WinSetParent(hwndVscroll, hWndFrame, FALSE);
         }
         break ;


    case WM_SETFOCUS:

         if (LONGFROMMP (mp2))
              {
              WinCreateCursor (hwnd, xChar * xCursor,
                               yClient - yChar * (1 + yCursor),
                               xChar, yChar, CURSOR_SOLID, NULL);

              WinShowCursor (hwnd, xMax > 0 && yMax > 0);
              }
         else
              WinDestroyCursor (hwnd);
         break ;


    case WM_INITMENU:   /* Set menu state before displaying. */
         /* ------------- Echo ----------- */
         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_ECHO, TRUE),
                     MPFROM2SHORT (MIA_CHECKED,
                     bEchoOn ? MIA_CHECKED : 0 ));
         /* ------------- Word Wrap ----------- */
         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_WRAP, TRUE),
                     MPFROM2SHORT (MIA_CHECKED,
                     bWordWrap ? MIA_CHECKED : 0 ));
         /* ------------- Pause ----------- */
         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_PAUSE, TRUE),
                     MPFROM2SHORT (MIA_CHECKED,
                     bPauseOn    ? MIA_CHECKED : 0 ));
         /* ------------- Capture ----------- */
         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_CAPTURE, TRUE),
                     MPFROM2SHORT (MIA_CHECKED,
                     bCaptureOn ?  MIA_CHECKED : 0 ));
         /* ------------- Test ----------- */
         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_TEST, TRUE),
                     MPFROM2SHORT (MIA_CHECKED,
                     bTestOn     ? MIA_CHECKED : 0 ));
         /* ------------- Settings ----------- */
         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_SETTINGS, TRUE),
                     MPFROM2SHORT (MIA_CHECKED,
                     bGotSettings ? MIA_CHECKED : 0 ));

         /* ------------- Comm Open ----------- */

         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_START, TRUE),
                     MPFROM2SHORT (MIA_DISABLED,
                     (bCommOpen && bGotSettings) ? MIA_DISABLED : 0 ));

         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_STOP, TRUE),
                     MPFROM2SHORT (MIA_DISABLED,
                     bCommOpen   ? 0 : MIA_DISABLED ));

         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_CAPTURE, TRUE),
                     MPFROM2SHORT (MIA_DISABLED,
                     bCommOpen   ? 0 : MIA_DISABLED ));

         WinSendMsg (hGMenuWnd, MM_SETITEMATTR,
                     MPFROM2SHORT (IDM_BREAK, TRUE),
                     MPFROM2SHORT (MIA_DISABLED,
                     bCommOpen   ? 0 : MIA_DISABLED ));

         break ;


    case WM_BLAST:

         pTempBuf = cInBuffer;   /* set pointer to comm input buffer */
         iBytesRead = SHORT2FROMMP (mp1);

         if (bCaptureOn && iBytesRead > 0 ) {

            FILE    *fp ;

            if ((fp = fopen( cSaveFile, "ab")) != NULL) {
               fwrite( pTempBuf, 1, iBytesRead, fp );
               fclose(fp);
            }
         }

         WinShowCursor (hwnd, FALSE);
         for ( iToFormat=0 ; iToFormat<iBytesRead ; iToFormat++, pTempBuf++ ) {

            switch (*pTempBuf) {
               case '\b':  /* backspace */
                         iLineLength[iMaxLines]--;
                         xCursor--;
                         iBufPos--;

                         break;
               case '\r':
                         break;
               case '\n':

                         if ( (yCursor >= (yMax - 1)) ) {
                           WinScrollWindow (hwnd, 0, yChar * 1,
                                NULL, NULL, NULL, NULL,
                                SW_INVALIDATERGN); /* send Paint msg */
                           bScroll = TRUE;
                           WinUpdateWindow (hwnd);

                         }
                         else {
                             yCursor++;
                         }
                         if (iMaxLines +1 >= MAXLINES)
                            bOverFlow = TRUE;

                         iMaxLines = (iMaxLines + 1) % MAXLINES ;
                         iBufPos = iMaxLines * MAXWIDTH;
                         iMaxWidth = iBufPos + MAXWIDTH;

                         /* clear next line. This is not necessary because
                            line length is kept.  */
                         for ( i=iBufPos ; i<iBufPos+MAXWIDTH ; i++ )
                            cDisplayBuf[i] = ' ';

                         iLineLength[iMaxLines] = 0;
                         xCursor = 0 ;  /* move under \r */

                         break;

               case '\t':

                         iSpaces = min (8 - xCursor % 8, xMax - xCursor);

                         iLineLength[iMaxLines] += iSpaces;
                         xCursor += iSpaces;
                         iBufPos += iSpaces;

                         break ;

               default:  /* format & fill display buffer */

                         j=0; pBlastString = &cDisplayBuf[iBufPos];
                         while ( iToFormat < iBytesRead &&
                                *pTempBuf != '\b' &&
                                *pTempBuf != '\r' &&
                                *pTempBuf != '\n' &&
                                *pTempBuf != '\t'     ) {

                             cDisplayBuf[iBufPos] = *pTempBuf;
                             cDisplayBuf[iBufPos] = cInBuffer[iToFormat];

                             iBufPos++; iToFormat++; j++; pTempBuf++;

                             /* the next few lines are used to allow word wrap
                                    by forcing a \n as the next character.
                                This is safe to do since the 80th char is
                                    already in the Display Buffer.
                              */  

                             if (iBufPos >= iMaxWidth ) {
                                if (bWordWrap) {  /* simulate a line feed */
                                   iToFormat--;
                                   pTempBuf--;
                                   cInBuffer[iToFormat] = '\n';
                                }
                                else {  /* truncate rest of line. */
                                   while ( iToFormat < iBytesRead &&
                                          *pTempBuf != '\r' &&
                                          *pTempBuf != '\n'     ) {

                                        iToFormat++; pTempBuf++;
                                   }
                                }
                                break;
                             }
                             /* end of word wrap section */
                         }

                         /* the next few lines are used to compensate
                                for the increment in the for loop */
                         if (iToFormat != iBytesRead) {
                             iToFormat--;
                             pTempBuf--;
                         }
                         iLineLength[iMaxLines] += j;

                         hps = WinGetPS (hwnd);
                         ptl.x = xCursor * xChar ;
                         ptl.y = yClient - yChar * (yCursor + 1) + yDesc ;
                         GpiSetBackMix (hps, BM_OVERPAINT);
                         GpiCharStringAt (hps, &ptl, (long)j, pBlastString);
                         GpiRestorePS (hps, -1L); /* fix 2 */
                         WinReleasePS (hps);

                         xCursor += j;
                         break;

            } /* end switch */
         }    /* end for */

         iToFormat = 0;

         WinCreateCursor (hwnd, xChar * xCursor,
                          yClient - yChar * (1 + yCursor),
                          0, 0, CURSOR_SETPOS, NULL);
         WinShowCursor (hwnd, TRUE);

         DosSemClear (&lReadSemTrigger);

         break ;



     case WM_PAINT:
         hps = WinBeginPaint (hwnd, NULL, &rclInvalid);

         WinShowCursor (hwnd, FALSE);

         GpiErase (hps);

         iCount = 0;

         if (bScroll) {
            iPaintBegin = iMaxLines; /* skip painting */
            bScroll = FALSE;
         }
         else
             if ( (iMaxLines+1) <= yMax) {
                iPaintBegin = 0;
                yCursor = iMaxLines;  /* yMax-1 */
                if (bOverFlow) {
                   iCount = yMax - (iMaxLines+1);
                   iPaintBegin1 = (MAXLINES - iCount);
                   yCursor = yMax-1;
                }
             }
             else {
                   if ( (iMaxLines+1) > yMax) {
                      iPaintBegin = (iMaxLines+1) - yMax;
                      yCursor = yMax-1;
                   }
             }
         ptl.x = 0;

         for ( i=0 ; i<iCount ; i++,iPaintBegin1++) {
            ptl.y = (yClient - (yChar * (i + 1 ))) + yDesc ;
            GpiCharStringAt (hps, &ptl, (LONG) iLineLength[iPaintBegin1],
                                                pStartLine[iPaintBegin1] );
         }
         while ( usRetCode = (USHORT)WinQueryQueueStatus(hab) ) {
              WinPeekMsg (hab, &qmsg, NULL, 0, 0, PM_NOREMOVE);
              if ( qmsg.msg == WM_QUIT ) return TRUE;
              WinGetMsg (hab, &qmsg, NULL, 0, 0);
              WinDispatchMsg (hab, &qmsg);
         }
         for ( i=0 ; iPaintBegin<=iMaxLines ; i++,iPaintBegin++) {
            ptl.y = (yClient - (yChar * (iCount + i + 1 ))) + yDesc ;
            GpiCharStringAt (hps, &ptl, (LONG) iLineLength[iPaintBegin],
                                                pStartLine[iPaintBegin] );
         }
         GpiRestorePS (hps, -1L); /* fix 2 */
         WinEndPaint (hps);

         WinCreateCursor (hwnd, xChar*xCursor, yClient - yChar * (1 + yCursor),
                                0, 0, CURSOR_SETPOS, NULL);
         WinShowCursor (hwnd, TRUE);

         break ;



    case WM_SIZE:
         xClient = SHORT1FROMMP (mp2);
         yClient = SHORT2FROMMP (mp2);

         xMax = min (MAXWIDTH, xClient / xChar);
         yMax = min (MAXLINES, yClient / yChar);

         iHscrollMax = max (0, MAXWIDTH + 2 - xClient / xChar);
         iHscrollPos = min (iHscrollPos, iHscrollMax);

         iVscrollMax = max (0, iMaxLines - yClient / yChar);
         iVscrollPos = min (iVscrollPos, iVscrollMax);

         if (hwndHscroll) {
            WinSendMsg (hwndHscroll, SBM_SETSCROLLBAR,
                                     MPFROM2SHORT (iHscrollPos, 0),
                                     MPFROM2SHORT (0, iHscrollMax));

            WinSendMsg (hwndVscroll, SBM_SETSCROLLBAR,
                                     MPFROM2SHORT (iVscrollPos, 0),
                                     MPFROM2SHORT (0, iVscrollMax));
         }

         if ( bPauseOn ) {
           WinEnableWindow (hwndHscroll, iHscrollMax ? TRUE : FALSE);
           WinEnableWindow (hwndVscroll, iVscrollMax ? TRUE : FALSE);
         }

         /* this changes the clipping region of the cursor */
         WinDestroyCursor (hwnd);
         WinCreateCursor (hwnd, xChar * xCursor,
                                yClient - yChar * (1 + yCursor),
                                xChar, 0, CURSOR_SOLID | CURSOR_FLASH, NULL);

         WinShowCursor (hwnd, xMax > 0 && yMax > 0);

         break ;


    case WM_COMMAND:

         switch (COMMANDMSG(&msg)->cmd) {
            case IDM_ABOUT:
                 WinDlgBox (HWND_DESKTOP, hwnd, AboutDlgProc,
                            NULL, IDD_ABOUT, NULL);
                 break ;

            case IDM_CTRLC:
                 WriteCommPort( 0x03 );

                 break ;

            case IDM_DATE:
                 TestComm(); /* display date */

                 break ;

            case IDM_SETTINGS:
                 WinDlgBox (HWND_DESKTOP, hwnd, SettingsDlgProc,
                                       NULL, IDD_SETTINGS, NULL);
                 break ;

            case IDM_START:
                 if (bGotSettings) {

                    InitBuffers();

                    bResult = InitCommPort(); /* init and open COMM port */
                    if (bResult == TRUE) {
                       bCommOpen = TRUE;
                       DosSemClear (&lReadSemTrigger);
                       WinInvalidateRect( hGWnd, NULL, FALSE );
                       WinSetFocus( HWND_DESKTOP, hGWnd);
                    }

                    /* make modem connection if requested */
                    /*    if (modem())
                     *       Result = make_modem_conn();   
                     */
                 }
                 else
                    WinMessageBox ( HWND_DESKTOP, hwnd,
                    "Comm settings must be set first.", NULL, NULL, MB_OK);
                 break ;

            case IDM_STOP:
                 if (bCommOpen)
                   CloseComm();
                 bCommOpen  = FALSE;
                 bCaptureOn = FALSE;

                 break ;

            case IDM_ECHO:
                 bEchoOn = !bEchoOn;
                 break ;

            case IDM_WRAP:
                 bWordWrap = !bWordWrap;
                 break ;

            case IDM_CAPTURE:

                 if ( bCaptureOn == FALSE ) { /* get capture file name */
                    WinDlgBox (HWND_DESKTOP, hwnd, GetFileDlgProc,
                                         NULL, IDD_GETFILE, NULL);
                 }
                 else
                       bCaptureOn = FALSE;

                 WinQueryWindowText( WinQueryWindow (hGWnd, QW_PARENT, FALSE),
                                     40, cCaptionBuf );

                 pTempPt = cCaptionBuf;

                 while (*pTempPt != ']')
                        pTempPt++;

                 pTempPt--;
                 *pTempPt = (char)(bCaptureOn ? 'C' : ' ');
                 WinSetWindowText( WinQueryWindow (hGWnd, QW_PARENT, FALSE),
                                   cCaptionBuf );

                 break ;

            case IDM_TEST:
                 bTestOn = !bTestOn;

                 Dump();

                 break ;

            case IDM_BREAK :/* send BREAK to the com port */
                 /*  break = 0x7F, DEC 127 */
                 if ((usRetCode = DosDevIOCtl(&uStatus, 0L,
                                    SETBREAKON, SERIAL, uCommHandle)) != 0)
                   Error(ERR_IOCTLSETBREAKON, usRetCode);
                 DosSleep(1L);
                 if ((usRetCode = DosDevIOCtl(&uStatus, 0L,
                                    SETBREAKOFF, SERIAL, uCommHandle)) != 0)
                   Error(ERR_IOCTLSETBREAKOFF, usRetCode);
                 break;


            case IDM_PAUSE:
                 bPauseOn = !bPauseOn;

                 WinMessageBox (HWND_DESKTOP, hGWnd,
                            "Due to time,\nPause has not been implemented",
                            "WARNING!", NULL, MB_OK);

                 if (bPauseOn) { /* un-hide scroll bars */
                    WinSetParent(hwndHscroll, hWndFrame, FALSE);
                    WinSetParent(hwndVscroll, hWndFrame, FALSE);
                    /* send control S to host? */

                 }
                 else { /* hide scroll bars */
                    WinSetParent(hwndHscroll, HWND_OBJECT, FALSE);
                    WinSetParent(hwndVscroll, HWND_OBJECT, FALSE);
                    /* send control S to host? */

                 }

                 WinEnableWindow (hwndHscroll, bPauseOn ? TRUE : FALSE);
                 WinEnableWindow (hwndVscroll, bPauseOn ? TRUE : FALSE);

                 WinPostMsg (hWndFrame, WM_UPDATEFRAME, 0L, 0L);
                 /* make this smarter */
                 WinInvalidateRect( hGWnd, NULL, FALSE );

                 break ;

            default:
                 break ;
         }                    /* end switch */
         break ;              /* break WM_COMMAND */


    case WM_HSCROLL:
         switch (SHORT2FROMMP (mp2))
              {
              case SB_LINELEFT:
                   iHscrollInc = -1 ;
                   break ;

              case SB_LINERIGHT:
                   iHscrollInc = 1 ;
                   break ;

              case SB_PAGELEFT:
                   iHscrollInc = -8 ;
                   break ;

              case SB_PAGERIGHT:
                   iHscrollInc = 8 ;
                   break ;

              case SB_SLIDERPOSITION:
                   iHscrollInc = SHORT1FROMMP (mp2) - iHscrollPos;
                   break ;

              default:
                   iHscrollInc = 0 ;
                   break ;
              }

         if (iHscrollInc = max (-iHscrollPos,
                        min (iHscrollInc, iHscrollMax - iHscrollPos)))
              {
              iHscrollPos += iHscrollInc ;
              WinScrollWindow (hwnd, -xChar * iHscrollInc, 0,
                             NULL, NULL, NULL, NULL, SW_INVALIDATERGN);

              WinSendMsg (hwndHscroll, SBM_SETPOS,
                                  MPFROM2SHORT (iHscrollPos, 0L), NULL);
              }
         break ;


    case WM_VSCROLL:
         switch (SHORT2FROMMP (mp2)) {
              case SB_LINEUP:
                   iVscrollInc = -1 ;
                   break ;

              case SB_LINEDOWN:
                   iVscrollInc = 1 ;
                   break ;

              case SB_PAGEUP:
                   iVscrollInc = min (-1, -yClient / yChar);
                   break ;

              case SB_PAGEDOWN:
                   iVscrollInc = max (1, yClient / yChar);
                   break ;

              case SB_SLIDERTRACK:
                   iVscrollInc = SHORT1FROMMP (mp2) - iVscrollPos;
                   break ;

              default:
                   iVscrollInc = 0 ;
                   break ;
              }
         if ( yCursor ) {
              WinScrollWindow (hwnd, 0, yChar * iVscrollInc,
                               NULL, NULL, NULL, NULL,
                               SW_INVALIDATERGN); /* send Paint msg */
              bScroll = TRUE;
              WinUpdateWindow (hwnd);
         }
         break ;


    case WM_CHAR:

         if (xMax == 0 || yMax == 0)
            break ;

         if (CHARMSG(&msg)->fs & KC_KEYUP)
            break ;

         for (i = 0 ; i < CHARMSG(&msg)->cRepeat ; i++) {
             ptl.x = xCursor * xChar ;
             ptl.y = yClient - yChar * (yCursor + 1) + yDesc ;

               /*------------------------
                  Process character keys
                ------------------------*/

             if (CHARMSG(&msg)->fs & KC_CHAR) {

                switch (CHARMSG(&msg)->chr) {

                       /*---------------
                          Backspace key
                         ---------------*/
                   case '\b':

                        if (xCursor == 0)
                             break ;

                        if (bEchoOn) {
                          WinShowCursor (hwnd, FALSE);
                          WinSendMsg (hwnd, WM_CHAR,
                               MPFROM2SHORT (KC_VIRTUALKEY, 1),
                               MPFROM2SHORT (0, VK_LEFT));

                          WinSendMsg (hwnd, WM_CHAR,
                               MPFROM2SHORT (KC_VIRTUALKEY, 1),
                               MPFROM2SHORT (0, VK_DELETE));

                          /* this should go in VK_DEL section */

                          xCursor--;
                          iBufPos--;
                          cDisplayBuf[iBufPos] = ' ';
                          iLineLength[iMaxLines]--;
                        }

                        if (bCommOpen)
                          WriteCommPort( LOUSHORT(mp2) );

                        break ;

                    /*---------
                       Tab key
                      ---------*/
                   case '\t':

                        if (bEchoOn) {
                           i = min (8 - xCursor % 8, xMax - xCursor);

                           WinSendMsg (hwnd, WM_CHAR,
                                MPFROM2SHORT (KC_CHAR, i),
                                MPFROM2SHORT ((USHORT) ' ', 0));
                        }

                        if (bCommOpen)
                          WriteCommPort( LOUSHORT(mp2) );

                        break ;

                    /*-----------------------
                       Enter (or Return) key
                      -----------------------*/
                   case '\r':

                        if (bEchoOn) {

                          if ( (yCursor >= (yMax - 1)) ) {
                            WinSendMsg (hwnd, WM_VSCROLL, 0L,
                                        MPFROM2SHORT(0,SB_LINEDOWN) );
                            WinShowCursor (hwnd, FALSE);
                          }
                          else {
                              yCursor++;
                          }
                          if (iMaxLines +1 >= MAXLINES)
                             bOverFlow = TRUE;

                          iMaxLines = (iMaxLines + 1) % MAXLINES ;

                          iLineLength[iMaxLines] = 0;

                          iBufPos = iMaxLines * MAXWIDTH;

                          xCursor = 0 ;
                        }

                        if (bCommOpen) {
                           WriteCommPort( '\r' );
                        /* WriteCommPort( '\n' ); */
                        }
                        break ;

                   case '\n':   /* this must be \n for enter to work */
                             break ;

                        /*-------------------
                           Normal characters
                          -------------------*/
                   default:

                        cDisplayBuf[iBufPos] = (char)(LOUSHORT(mp2));
                        /*
                           FILLBUF (xCursor, yCursor) =
                                   (CHAR) CHARMSG(&msg)->chr ;
                         */

                        if (bEchoOn) {
                          WinShowCursor (hwnd, FALSE);

                          xCursor++;
                          iBufPos++;

                          iLineLength[iMaxLines]++;

                          hps = WinGetPS (hwnd);

                          GpiSetBackMix (hps, BM_OVERPAINT);
                          GpiCharStringAt (hps, &ptl, 1L,
                                    (CHAR *) & CHARMSG(&msg)->chr);
                          GpiRestorePS (hps, -1L); /* fix 2 */

                          WinReleasePS (hps);

                          WinShowCursor (hwnd, TRUE);
                        }

                        if (bCommOpen)
                          WriteCommPort( LOUSHORT(mp2) );
                        break ;
                }
             }
                  /*---------------------------
                     Process noncharacter keys
                    ---------------------------*/

             else if ( CHARMSG(&msg)->fs & KC_VIRTUALKEY
                        && bPauseOn == TRUE )
                   {
                   switch (CHARMSG(&msg)->vkey) {
                         /*----------------------
                            Cursor movement keys
                           ----------------------*/

                       case VK_LEFT:

                            xCursor = (xCursor - 1 + xMax) % xMax ;

                            if (xCursor == xMax - 1)
                                 yCursor = (yCursor - 1 + yMax) % yMax ;
                            break ;

                       case VK_RIGHT:

                            if (0 == (xCursor = (xCursor + 1) % xMax))
                                 yCursor = (yCursor + 1) % yMax ;
                            break ;

                       case VK_UP:

                            yCursor = (yCursor - 1 + yMax) % yMax ;

                            if (yCursor == yMax - 1)
                                 xCursor = (xCursor - 1 + xMax) % xMax ;
                            break ;

                       case VK_DOWN:

                            if (0 == (yCursor = (yCursor + 1) % yMax))
                                 xCursor = (xCursor + 1) % xMax ;
                            break ;

                       case VK_PAGEUP:

                            yCursor = 0 ;
                            break ;

                       case VK_PAGEDOWN:

                            yCursor = yMax - 1 ;
                            break ;

                       case VK_HOME:

                            xCursor = 0 ;
                            break ;

                       case VK_END:

                            xCursor = min (iLineLength[iMaxLines]+1, xMax - 1);
                            break ;

                       default:
                            return FALSE ;
                       }
                  }

              else
                   if ( CHARMSG(&msg)->fs & KC_VIRTUALKEY &&
                        CHARMSG(&msg)->vkey == VK_DELETE ) {

                        if (bCommOpen)
                           WriteCommPort( 0x7F );
                        break ;
                   }
              else
                   return FALSE ;
              }
         /* this test was put here if a delete key was pressed during the
                painting process. */
         if (iToFormat >= iBytesRead ) {
            WinCreateCursor (hwnd, xChar * xCursor,
                                   yClient - yChar * (1 + yCursor),
                                   0, 0, CURSOR_SETPOS, NULL);
            WinShowCursor (hwnd, TRUE);
         }
         return TRUE ;


    case WM_ERASEBACKGROUND:
         return TRUE ;

    default:
            return WinDefWindowProc (hwnd, msg, mp1, mp2);
    }
  return FALSE ;
  }



/* ------------------------------------------------
   Dump the current contents of Display Buffer
   to a file to examine 
   ------------------------------------------------ */
void Dump()
{
   FILE    *fp ;
   USHORT  i;

   if ((fp = fopen("f:display.dmp", "w")) != NULL) {
      i = fwrite( pStartLine[0], 1, BUFFERMAX, fp );
      for ( i=0 ; i<MAXLINES ; i++ )
         fprintf(fp, "\n Bytes: %d,%s ", iLineLength[i], pStartLine[i] );
      fclose(fp);
   }
}



/* ---------------------------------------------------- */
void TestComm()
{
   USHORT   uNumBytes;       /* return # of bytes actually written */
   char     cTestString[9];

   cTestString[0] = 'c';
   cTestString[1] = 'a';
   cTestString[2] = 'l';
   cTestString[3] = ' ';
   cTestString[4] = '1';
   cTestString[5] = '9';
   cTestString[6] = '8';
   cTestString[7] = '8';
   cTestString[8] = '\r';

   if ((usRetCode = DosWrite(uCommHandle, cTestString, 9, &uNumBytes )) != 0)
     Error(ERR_DOSWRITE, usRetCode);

}

/* ---------------------------------------------------- */
void Error( iErrNum, iRetCode)
int  iErrNum;
int  iRetCode;
{
   WinMessageBox ( HWND_DESKTOP, hGWnd, ErrMsg[iErrNum] , NULL, NULL, MB_OK);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.