|
|
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);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.