home *** CD-ROM | disk | FTP | other *** search
- { Title : Comm -- a HyperCard XCMD to control a communications session. }
- { Author : Chris Knepper }
- { Date : 3/30/88 }
- { From : DannyGoodman's HyperCard Developer's Guide }
- { Publisher : Bantam Books, Inc. }
- { Copyright 1988 by Danny Goodman. All rights reserved. }
-
- UNIT CommUnit;
- INTERFACE
-
- uses
- MemTypes,
- QuickDraw,
- OSIntf,
- ToolIntf,
- PackIntf,
-
- HyperXCmd;
-
- PROCEDURE Comm (paramPtr: XCmdPtr);
-
- IMPLEMENTATION
-
- PROCEDURE Comm (paramPtr: XCmdPtr);
- label
- 1; { the END of Comm }
- const
- BUFF_SIZE = $800; { size of the input serial buffer -- 2K }
- var
- controlStr { stores 1st param to Comm }
- : Str255;
- inRefNum, { Stores input reference number }
- outRefNum { Stores output reference number }
- : integer;
- err { stores the error codes of various Device Manager calls }
- : OSErr;
- count { stores the number of bytes to read~write }
- : longint;
- myBuffPtr { stores a pointer to the serial input buffer }
- : Ptr;
- myPBlock { Used in calls to PBRead and PBWrite. }
- : ParamBlockRec;
- myHdl { Stores handle O-terminated string }
- : Handle;
-
- {-----------------------------------------------}
- PROCEDURE HandleError (myStr: Str255);
-
- { HandleError sets the cursor to the arrow cursor and displays an error Alert }
- { informing the user of the error. This PROCEDURE assumes that the ALRT & DITL }
- { resources WITH id ~ 3100 exist in HyperCard's resource fork. Although this is a }
- { valid assumption in HyperCard versions 1.1 and 1.0.1. Calls to GetResource() verify }
- { that these resources DO, in fact, exist. IF they don't, this PROCEDURE produces a beep. }
- const
- ERROR = 3100; { use a HC ALRT for error messages. }
- var
- whichItem: integer; { stores result of the Alert FUNCTION }
- BEGIN
- IF (GetResource('ALRT', 3100) = nil) or (GetResource('DITL', 3100) = nil) THEN
- SysBeep(60) { beep IF no ALRT or DITL resource }
- ELSE
- BEGIN
- InitCursor; { set cursor to the arrow cursor }
- ParamText(myStr, '', '', ''); { specify the ALRT's text }
- whichItem := Alert(ERROR, nil); { display and handle the ALRT}
- SendCardMessage(paramPtr, 'set cursor to 4'); { set back to watch cursor }
- END;
- END; { PROCEDURE HandleError }
-
- {-----------------------------------------------}
- function ErrOccurred (errNum: OSErr; routineName: Str255): Boolean;
- { ErrOccurred determines IF an error occured by comparing errNum WITH NoErr. }
- { IF equal, ErrOccurred returns FALSE indicating that no error occurred. Otherwise, }
- { it returns TRUE, indicating that an error occurred and creates a string from }
- { errNum and routineName which it THEN passes to HandleError. }
- var
- errStr { store error number as a Pascal string }
- : Str255;
- BEGIN
- IF (errNum = noErr) THEN
- ErrOccurred := FALSE { no error occurred -- return FALSE }
- ELSE
- BEGIN
- ErrOccurred := TRUE; { oops, error occurred -- return TRUE }
- NumToString(errNum, errStr); { convert error number to a string }
- HandleError(Concat(routineName, 'returned', errStr, '.')); { inform user}
- END;
- END; { function ErrOccurred }
-
- {-----------------------------------------------}
- function Clear_RefNums_SerBuffPtr: boolean;
- { Clear_RefNums_SerBuffPtr sets the HyperTalk global "CommStorage" to }
- { empty and returns TRUE IF successful, or FALSE IF not successful. }
- var
- pascalStr: Str255; { stores message to send to HC }
- BEGIN
- pascalStr := 'put empty into CommStorage'; { clear CommStorage WITH a..}
- SendCardMessage(paramPtr, pascalStr); { ...HyperTalk command }
- IF (paramPtr^.result = xResSucc) THEN { test the callback }
- Clear_RefNums_SerBuffPtr := TRUE { SendCardMessage succeeded }
- ELSE
- BEGIN
- Clear_RefNums_SerBuffPtr := FALSE; { SendCardMessage failed }
- HandleError('SendCardMessage callback failed.'); { inform user }
- END;
- END; { function Clear RefNums SerBuffPtr }
-
- {-----------------------------------------------}
- function Set_RefNums_SerBuffPtr (output, input: integer; buffer: Ptr): boolean;
- { Set_RefNums_SerBuffPtr stores the input/output refnums and a pointer to }
- { the Input buffer in a HyperTalk global called "CommStorage." IF the function }
- { fails, it returns FALSE, otherwise it returns TRUE. }
- var
- pascalStr1, { converts LONGlNTs, passed to PasToZero }
- pascalStr2 { converts LONGlNTs }
- : Str255;
- BEGIN
- Set_RefNums_SerBuffPtr := TRUE; { indicate that no error occurred }
- NumToString(output, pascalStr1 ); { convert output refnum to StRSS }
- NumToString(input, pascalStr2); { convert input refnum to Str255 }
- pascalStr1 := Concat(pascalStr1, ',', pascalStr2); { a "," delimitted Str255 }
- NumToString(ORD4(buffer), pascalStr2); { convert the serial buf ptr to Str255 }
- pascalStr1 := Concat(pascalStr1, ',', pascalStr2); { a "," delimitted Str255 }
- myHdl := PasToZero(paramPtr, pascalStr1 ); { store Str255 in a handle }
- IF (paramPtr^.result <> xResSucc) THEN
- BEGIN
- Set_RefNums_SerBuffPtr := FALSE; { indicate that an error occurred }
- HandleError('PasToZero callback failed.');
- END
- ELSE
- BEGIN
- SetGlobal(paramPtr, 'CommStorage', myHdl); { set the global }
- IF (paramPtr^.result <> xResSucc) THEN
- BEGIN
- Set_RefNums_SerBuffPtr := FALSE; { indicate that an error occurred }
- HandleError('SetGlobal callback failed.');
- END
- END;
- END; { function Set_RefNums_SerBuffPtr}
-
- {-----------------------------------------------}
- function Get_RefNums_SerBuffPtr (var output, input: integer;
- var buffer: Ptr): boolean;
- { Get_RefNums_SerBuffPtr gets the refnums which have been stored in the }
- { HyperTalk global ~CommStorage.~ n this global is empty, THEN an error }
- { has occurred and the function returns FALSE. Otherwise, the function }
- { gets the values in CommStorage and returns TRUE. CommStorage contains }
- { 3 items. Item 1 is the output refnum, item 2 is the input refnum, and item 3 }
- { is the address of the input buffer. }
- label
- 5; { the END of Get_RefNums_SerBuffPtr }
- var
- whichItem, { used as a FOR loop counter }
- scrInt { used when converting strings to nums }
- : Integer;
- scrLongint { scratch longint }
- : Longint;
- pascalStr, { used FOR local storage of Str255 }
- myExpr { used to pass a HyperTalk expression to HC }
- : Str255;
- BEGIN
- Get_RefNums_SerBuffPtr := FALSE; { return FALSE indicates errors }
- myExpr := 'CommStorage is empty'; { determine IF the global CommStorage..}
- myHdl := EvalExpr(paramPtr, myExpr); { is empty }
- IF (paramPtr^.result <> xresSucc) THEN { result is set by EvalExpr }
- BEGIN
- HandleError('EvalExpr failed to test IF CommStorage is empty.');
- DisposHandle(myHdl); { dispose of memory EvalExpr allocated }
- goto 5; { exit Get_RefNums_SerBuffPtr}
- END;
- HLock(myHdl); { lock handle before ZeroToPas }
- ZeroToPas(paramPtr, myHdl^, pascalStr);
- DisposHandle(myHdl);
- IF (paramPtr^.result <> xresSucc) THEN { result is set by ZeroToPas }
- BEGIN
- HandleError('ZeroToPas failed while testing IF CommStorage is empty.');
- goto 5; { exitGet_RefNums_SerBuffPtr}
- END;
- IF pascalStr = 'true' THEN { is CommStorage empty? }
- BEGIN
- HandleError('CommStorage is empty.'); { inform user }
- goto 5; { exit Get_RefNums_SerBuffPtr}
- END;
- FOR whichItem := 1 to 3 DO { Get 3 items of CommStorage }
- BEGIN
- NumToString(whichItem, pascalStr); { convert item to pascalStr }
- myExpr := Concat('item ', pascalStr, ' of CommStorage');
- myHdl := EvalExpr(paramPtr, myExpr); { evaluate the expression }
- IF ((myHdl = nil) or (paramPtr^.result <> xresSucc)) THEN
- BEGIN { inform user of error }
- HandleError(Concat('Can''t get item ', pascalStr, ' of CommStorage'));
- DisposHandle(myHdl); { dispose of memory EvalExpr allocated }
- goto 5; { exit Get_RefNums_SerBuffPtr}
- END;
- HLock(myHdl); { lock handle before ZeroToPas }
- ZeroToPas(paramPtr, myHdl^, pascalStr);
- IF (paramPtr^.result <> xresSucc) THEN { set by ZeroToPas }
- BEGIN
- NumToString(whichItem, pascalStr); { convert item to string }
- pascalStr := Concat('Can''t convert item ', pascalStr);
- HandleError(Concat(pascalStr, ' of CommStorage to Pascal string.'));
- DisposHandle(myHdl); { dispose of the storage allocated by EvalExpr }
- goto 5; { exit Get_RefNums_SerBuffPtr }
- END;
- DisposHandle(myHdl); { dispose of the storage allocated by EvalExpr }
- StringToNum(pascalStr, scrLongint); { convert to a number }
- case whichItem of
- 1: { the first item is the output refnum }
- output := scrLongint;
- 2: { the second item is the input refnum }
- input := scrLongint;
- 3: { the third item is the buffer pointer }
- buffer := POINTER(scrLongint);
- END; { case statement }
- END; { FOR loop }
- Get_RefNums_SerBuffPtr := TRUE; { return TRUE indicates success }
- 5: { the END of Get_RefNums_SerBuffPtr }
- END; { function Get_RefNums_SerBuffPtr }
-
- {-----------------------------------------------}
- function UserConfig (var serConfig: integer): BOOLEAN;
- { This function gets the configuration specified by the user in the parameters to }
- { Comm. 3rd parameter is baud, 4th parameter is stop bits, 5th parameter is }
- { parity, 6th parameter is data bits. IF no parameters are passed (besides "Open") }
- { THEN the defaun configuration is returned. IF error occurs, UserConfig returns }
- { FALSE, otherwise it returns TRUE. The configuration is returned in serConfig. }
- label
- 7; { the END of UserConfig }
- var
- pascalStr: Str255; { used when converting to pascal strings }
- BEGIN
- UserConfig := TRUE;
- serConfig := 0;
- IF (paramPtr^.paramCount = 1) THEN { Assume the 1st parameter was ~open~. }
- serConfig := baud1200 + stop10 + noParity + data8 { Default configuration. }
- ELSE
- BEGIN
- { *** Get the third parameter -- Baud rate *** }
- HLock(paramPtr^.params[3]);
- ZeroToPas(paramPtr, paramPtr^.params[3]^, pascalStr);
- HUnlock(paramPtr^.params[3]);
- UprString(pascalStr, FALSE);
- IF (pascalStr = '300') THEN
- serConfig := serConfig + baud300
- ELSE IF (pascalStr = '600') THEN
- serConfig := serConfig + baud600
- ELSE IF (pascalStr = '1200') THEN
- serConfig := serConfig + baud1200
- ELSE IF (pascalStr = '1800') THEN
- serConfig := serConfig + baud1800
- ELSE IF (pascalStr = '2400') THEN
- serConfig := serConfig + baud2400
- ELSE IF (pascalStr = '3600') THEN
- serConfig := serConfig + baud3600
- ELSE IF (pascalStr = '4800') THEN
- serConfig := serConfig + baud4800
- ELSE IF (pascalStr = '7200') THEN
- serConfig := serConfig + baud7200
- ELSE IF (pascalStr = '9600') THEN
- serConfig := serConfig + baud9600
- ELSE IF (pascalStr = '19200') THEN
- serConfig := serConfig + baud19200
- ELSE IF (pascalStr = '57600') THEN
- serConfig := serConfig + baud57600
- ELSE
- BEGIN { Error occurred in specifying baud rate. }
- HandleError('Error in specifying baud rate.');
- UserConfig := FALSE;
- goto 7;
- END;
- { *** Get the fourth parameter -- Stop bits *** }
- HLock(paramPtr^.params[4]);
- ZeroToPas(paramPtr, paramPtr^.params[4]^, pascalStr);
- HUnlock(paramPtr^.params[4]);
- UprString(pascalStr, FALSE);
- IF (pascalStr = '1') THEN
- serConfig := serConfig + stop10
- ELSE IF (pascalStr = '1.5') THEN
- serConfig := serConfig + stop15
- ELSE IF (pascalStr = '2') THEN
- serConfig := serConfig + stop20
- ELSE
- BEGIN { Error occurred in specifying stop bits. }
- HandleError('Error in specifying stop bits.');
- UserConfig := FALSE;
- goto 7;
- END;
- { *** Get the fifth parameter -- Parity *** }
- HLock(paramPtr^.params[5]);
- ZeroToPas(paramPtr, paramPtr^.params[5]^, pascalStr);
- HUnlock(paramPtr^.params[5]);
- UprString(pascalStr, FALSE);
- IF (pascalStr = 'NO') THEN
- serConfig := serConfig + noParity
- ELSE IF (pascalStr = 'ODD') THEN
- serConfig := serConfig + oddParity
- ELSE IF (pascalStr = 'EVEN') THEN
- serConfig := serConfig + evenParity
- ELSE
- BEGIN { Error occurred in specifying parity. }
- HandleError('Error in specifying parity.');
- UserConfig := FALSE;
- goto 7;
- END;
- { *** Get the sixth parameter -- Data bits *** }
- HLock(paramPtr^.params[6]);
- ZeroToPas(paramPtr, paramPtr^.params[6]^, pascalStr);
- HUnlock(paramPtr^.params[6]);
- UprString(pascalStr, FALSE);
- IF (pascalStr = '5') THEN
- serConfig := serConfig + data5
- ELSE IF (pascalStr = '6') THEN
- serConfig := serConfig + data6
- ELSE IF (pascalStr = '7') THEN
- serConfig := serConfig + data7
- ELSE IF (pascalStr = '8') THEN
- serConfig := serConfig + data8
- ELSE
- BEGIN { Error occurred in specifying data bits. }
- HandleError('Error in specifying data bits.');
- UserConfig := FALSE;
- END;
- END; { IF one or more than one parameter }
- 7: { label 7 is the END of UserConfig }
- END; { function UserConfig }
-
- {-----------------------------------------------}
- function PrinterOrModem (var outputStr, inputStr: Str255): boolean;
- { PrinterOrModem determines whether the user is opening the printer or }
- { modem ports. NOTE: cannot have BOTH the printer AND modem port open at the }
- { same time. IF the user calls Comm("Open") THEN default to modem port. The }
- { name of printer or modem driver is returned in outputStr and inputStr. }
- var
- pascalStr: Str255; { used to convert args to upper case }
- BEGIN
- PrinterOrModem := TRUE; { TRUE indicates no errors }
- IF (paramPtr^.paramCount = 1 ) THEN
- BEGIN { assume 1st parameter was "open" }
- inputStr := '.AIn';
- outputStr := '.AOut';
- END
- ELSE
- BEGIN { user specifies modem or printer port }
- HLock(paramPtr^.params[2]);
- ZeroToPas(paramPtr, paramPtr^.params[2]^, pascalStr);
- HUnlock(paramPtr^.params[2]);
- UprString(pascalStr, FALSE); { Convert to upper case. }
- IF (pascalStr = 'MODEM') THEN
- BEGIN
- inputStr := '.Aln';
- outputStr := '.AOut';
- END
- ELSE IF (pascalStr = 'PRINTER') THEN
- BEGIN
- inputStr := '.BIn';
- outputStr := '.BOut';
- END
- ELSE
- BEGIN { Error in specifying printer or modem. }
- HandleError('Comm expects Printer or Modem.');
- PrinterOrModem := FALSE; { Inform user second param was bad. }
- END;
- END; { IF paramCount = 1. }
- END; { function PrinterOrModem }
-
- {-----------------------------------------------}
- function MySerShk: SerShk;
- { Returns the serial hand shake options and other control information. }
- var
- tempSerShk: SerShk; { stores the serial handshake settings }
- BEGIN
- WITH tempSerShk DO
- BEGIN
- fXon :=1; { Enable XOn/XOff output flow control. }
- fCTS :=1; { Enable CTS hardware handshake. }
- xOn := CHR(17); { Set to control-e FOR continue. }
- xOff := CHR(19); { Set to control-s FOR pause. }
- errs := 0; { Errors which abort input requests }
- evts := 0;
- fInX := 1; { Enable XOn/XOff input flow control. }
- END;
- MySerShk := tempSerShk;
- END; { function MySerShk }
-
- {-----------------------------------------------}
- PROCEDURE CheckCumErrs;
- { This PROCEDURE checks the input and output serial ports FOR errors. }
- { K an error occurred, THEN the Mac beeps. }
- var
- mySerStat: SerStaRec; { stores status information }
- BEGIN
- err := SerStatus(outRefNum, mySerStat);
- IF (mySerStat.cumErrs <> 0) THEN
- SysBeep(1); { beep IF errors in output port }
- err := SerStatus(inRefNum, mySerStat);
- IF (mySerStat.cumErrs <> 0) THEN
- SysBeep(1); { beep IF errors in input port }
- END; { PROCEDURE CheckCumErrs }
-
- {-----------------------------------------------}
- PROCEDURE CommOpen;
- { CommOpen opens the serial port to initiate communication. }
- label
- 1; { the END of CommOpen }
- var
- serConfig { Stores configuration info FOR the port }
- : integer;
- inputStr, { stores either '.Aln' or '.Bln'. }
- outputStr { stores either '.AOut' or '.BOut'. }
- : Str255;
- BEGIN
- { Ensure that Comm("Open"...) was called correctly. }
- IF (paramPtr^.paramCount <> 6) and (paramPtr^.paramCount <> 1 ) THEN
- BEGIN
- HandleError('Error: Comm Open expects 1 or 6 parameters');
- goto 1; { exit CommOpen }
- END;
- { Init CommStorage to empty -- later store inRefNum/outRefNum }
- { and a pointer to the serial input buffer here. }
- IF not Clear_RefNums_SerBuffPtr THEN
- goto 1;
- IF not PrinterOrModem(outputStr, inputStr) THEN { use the Printer or Modem port? }
- goto 1; { exit CommOpen }
- IF not UserConfig(serConfig) THEN { Get the configuration FOR the input/output ports. }
- goto 1; { exit CommOpen }
- myBuffPtr := NewPtr(BUFF_SIZE); { Allocate memory FOR the input buffer. }
- IF ErrOccurred(MemError, 'NewPtr') THEN
- goto 1; { exit CommOpen }
- err := OpenDriver(outputStr, outRefNum); { Open the output port. }
- IF ErrOccurred(err, 'OpenDriver') THEN
- goto 1; { exit CommOpen }
- err := OpenDriver(inputStr, inRefNum); { Open the input port. }
- IF ErrOccurred(err, 'OpenDriver') THEN
- goto 1; { exit CommOpen }
- err := SerReset(outRefNum, serConfig); { Configure the output port. }
- IF ErrOccurred(err, 'SerReset') THEN
- goto 1; { exit CommOpen }
- err := SerHShake(outRefNum, MySerShk); { set up output port handshake }
- IF ErrOccurred(err, 'SerHShake') THEN
- goto 1; { exit CommOpen }
- err := SerReset(inRefNum, serConfig); { Configure the input port. }
- IF ErrOccurred(err, 'SerReset') THEN
- goto 1; { exit CommOpen }
- err := SerHShake(inRefNum, MySerShk); { set up input port handshake }
- IF ErrOccurred(err, 'SerHShake') THEN
- goto 1; { exit CommOpen }
- err := SerSetBuf(inRefNum, myBuffPtr, BUFF_SIZE); { Set up the input buffer. }
- IF ErrOccurred(err, 'SerSetBuf') THEN
- goto 1; { exit CommOpen }
- { Save the input/output port refnums and serial input buffer pointer. }
- IF not Set_RefNums_SerBuffPtr(outRefNum, inRefNum, myBuffPtr) THEN
- ; { DO nothing, since at END }
- 1: { the END of CommOpen }
- END; { PROCEDURE CommOpen }
-
- {-----------------------------------------------}
- PROCEDURE CommWrite;
- { CommWrite writes data to the serial port. }
- label
- 1; { the END of CommWrite }
- BEGIN
- IF (paramPtr^.paramCount <> 2) THEN { ensure Comm was called correctly }
- BEGIN
- HandleError('Error: Comm Write expects 2 parameters');
- goto 1; { exit CommWrite }
- END;
- { Send the data out the serial port. }
- HLock(paramPtr^.params[2]);
- count := StringLength(paramPtr, paramPtr^.params[2]^);
- WITH myPBlock DO
- BEGIN
- ioRefNum := outRefNum;
- ioBuffer := paramPtr^.params[2]^;
- ioReqCount := count;
- ioPosMode := 0; { write from current mark }
- END;
- err := PBWrite(@myPBlock, FALSE);
- HUnlock(paramPtr^.params[2]);
- IF ErrOccurred(err, 'PBWrite') THEN
- ; { DO nothing since at END }
- 1: { the END of PROCEDURE CommWrite }
- END; { PROCEDURE CommWrite }
-
- {-----------------------------------------------}
- PROCEDURE CommRead;
- { CommRead reads data from the serial port. }
- label
- 1; { the END of CommRead }
- var
- counter, { FOR loop counter. }
- scratchInt, { Scratch integer necessary FOR BitAnd. }
- noLF_cntr { Counts good chars, ie. no line feeds. }
- : integer;
- myCharPtr { points to chars in the input stream }
- : Ptr;
- BEGIN
- IF (paramPtr^.paramCount <> 1 ) THEN { ensure Comm was called correctly }
- BEGIN
- HandleError('Error: Comm Read expects only 1 parameter');
- goto 1; { exit CommRead }
- END;
- { Look at the serial input buffer -- exit IF there's an error }
- { in looking at it or IF there are no characters in it. }
- err := SerGetBuf(inRefNum, count);
- IF (ErrOccurred(err, 'SerGetBuf') or (count <= 0)) THEN
- goto 1; { exit CommRead }
- { Allocate the storage area FOR the result of the read. The size is equal to }
- { the number of characters in the buffer. }
- myHdl := NewHandle(count + 1 ); { add 1 to ensure it's a O-terminated string }
- IF (ErrOccurred(MemError, 'NewHandle') or (myHdl = nil)) THEN
- goto 1; { exit CommRead }
- HLock(myHdl); { lock it during the call to PBRead }
- WITH myPBlock DO { set up the parameter block FOR PBRead }
- BEGIN
- ioRefNum := inRefNum; { read from the input buffer }
- ioBuffer := myHdl^; { point to the storage area }
- ioReqCount := count; { read as many characters as are in the buffer }
- ioPosMode := 0; { read from current mark }
- END;
- err := PBRead(@myPBlock, FALSE); { read ! }
- IF ErrOccurred(err, 'PBRead') THEN { any errors during read? }
- BEGIN { IF so, THEN release the space..}
- DisposHandle(myHdl); { ..allocated to the handle. }
- goto 1; { exit CommRead }
- END;
- { Since some hosts transmit WITH the high-bit set, we'll turn off the high-bit FOR all }
- { incoming characters. Also, we'll strip all non-printing characters (ASCII $00-$1 F & $7F) }
- { except the carriage return (ASCII $0D). }
- noLF_cntr := 0;
- FOR counter := 0 to (myPBlock.ioActCount - 1 ) DO
- BEGIN
- myCharPtr := POINTER(ORD(myHdl^) + counter);
- scratchInt := BitAnd(Byte(myCharPtr^), $7F); { Turn off high-bit. }
- IF ((scratchInt > $1F) or (scratchInt = $0D)) and (scratchInt <> $7F) THEN
- BEGIN
- myCharPtr := POINTER(ORD(myHdl^) + noLF_cntr);
- myCharPtr^ := Byte(scratchInt);
- noLF_cntr := noLF_cntr + 1;
- END;
- END;
- { make it a zero-terminated string }
- IF (noLF_cntr = 0) THEN
- BEGIN { IF no good characters in the input..}
- DisposHandle(myHdl); { ..THEN return nothing! }
- END
- ELSE
- BEGIN { make last byte a 0 }
- myCharPtr := POINTER(ORD(myHdl^) + noLF_cntr);
- myCharPtr^ := Byte(0);
- SetHandleSize(myHdl, noLF_cntr + 1 ); { set the handle to the correct size }
- HUnlock(myHdl); { unlock it before passing it back to HyperCard }
- paramPtr^.returnValue := myHdl; { Return the string read from the input buffer. }
- END;
- CheckCumErrs; { beep IF there are errors in the driver }
- 1: { the END of CommRead }
- END; { PROCEDURE CommRead }
-
- {-----------------------------------------------}
- PROCEDURE CommClose;
- { CommClose restores the input buffer to the defaun buffer and releases the }
- { memory used FOR Comm's input buffer. }
- BEGIN
- err := SerSetBuf(inRefNum, nil, 0); { restore the input serial buffer }
- IF ErrOccurred(err, 'SerSetBuf') THEN
- ; { DO nothing }
- IF not Clear_RefNums_SerBuffPtr THEN
- ; { DO nothing }
- DisposPtr(myBuffPtr); { dispose of the allocated buffer }
- IF ErrOccurred(MemError, 'DisposPtr') THEN
- ; { DO nothing }
- END; { PROCEDURE CommClose }
-
- {-----------------------------------------------}
- BEGIN { PROCEDURE Comm }
- { Comm requires parameters, so check FOR at least one here. }
- IF (paramPtr^.paramCount < 1) THEN
- BEGIN
- HandleError('No parameters were sent to Comm.');
- goto 1; { exit Comm }
- END;
- { Get the first parameter -- this controlStr indicates what Comm should DO. }
- HLock(paramPtr^.params[1]);
- ZeroToPas(paramPtr, paramPtr^.params[1]^, controlStr);
- HUnlock(paramPtr^.params[1 ]);
- UprString(controlStr, FALSE); { Convert to upper case, strip diacriticals. }
- IF (controlStr = 'OPEN') THEN
- CommOpen { open the communications session }
- ELSE
- BEGIN
- { IF we get here, the communications session has already been established, so }
- { get the refnums FOR the input/output ports and serial input buffer pointer. }
- IF not Get_RefNums_SerBuffPtr(outRefNum, inRefNum, myBuffPtr) THEN
- goto 1; { exit Comm }
- IF (controlStr = 'WRITE') THEN
- CommWrite { write to the serial port }
- ELSE IF (controlStr = 'READ') THEN
- CommRead { read from the serial port }
- ELSE IF (controlStr = 'CLOSE') THEN
- CommClose { restore the serial port }
- ELSE
- { IF we get here, the first parameter to Comm doesn't match any of }
- { the control strings, so a bad control string was passed in. }
- HandleError('Comm doesn"t recognize the 1st parameter.'); { inform user }
- END; { IF}
- 1: { the END of Comm }
- END; { PROCEDURE Comm }
-
- {-----------------------------------------------}
- END. { UNIT CommUnit }
- {-----------------------------------------------}
-