-- SendPress.mesa, Edit: Johnsson, October 1, 1980 10:03 AM
-- converted to Laurel by Ken Pier, July 31, 1981 12:09 PM
-- last edited by Ken Pier, August 11, 1981 10:34 AM
-- converted to Laurel 6.1 by Ken Pier, 17-May-83 10:33:30
-- edited by Taft, May 17, 1983 3:37 PM

DIRECTORY
AltoFileDefs USING [FP],
EFTPDefs USING [
EFTPAbortSending, EFTPFinishSending, EFTPOpenForSending,
eftpReceiverBusyAbort, EFTPSendBlock, EFTPTimeOut, EFTPTroubleSending],
PressFormat USING [DDV, PressPasswd],
PressUtilities USING [hardcopyUserName, ParameterProc],
PupDefs USING [GetPupAddress, PupAddress],
PupTypes USING [eftpReceiveSoc],
csD: FROM "CoreStreamDefs",
VMDefs,
Core,
ovD: FROM "OverviewDefs",
intCommon,
Storage USING [Pages],
PrintDefs USING [PError, CloseF, DestroyS],
StringDefs USING [MesaToBcplString];

SendPress: PROGRAM
IMPORTS
PrintDefs, PressUtilities, csD, intCommon, Storage,
StringDefs, EFTPDefs, PupDefs, Core, VMDefs
EXPORTS PressUtilities =
BEGIN

ServerBusy: PUBLIC SIGNAL = CODE;
ServerTimeout: PUBLIC SIGNAL = CODE;
ServerTrouble: PUBLIC ERROR [message: STRING] = CODE;

wordsPerPressRecord: CARDINAL = 256;
bytesPerPressRecord: CARDINAL = 512;


IsPressFile: PUBLIC PROCEDURE [fh: VMDefs.FileHandle]
RETURNS [isPressFile: BOOLEAN, lastPage: CARDINAL] =
BEGIN
p: VMDefs.Page ← Storage.Pages[1];
byte: CARDINAL;
pos: VMDefs.Position ← VMDefs.GetFileLength[fh];
lastPage ← pos.page;
byte ← pos.byte;
--press files have first free byte =0 and exactly lastPage pages
IF byte # 0 THEN RETURN[FALSE, 0];
p ← VMDefs.ReadPage[addr:[fh,lastPage-1]];--what about diskError here?
isPressFile ← p.words[0] = PressFormat.PressPasswd AND p.words[1] = lastPage;
VMDefs.Release[p];
RETURN
END;

SendPressFile: PUBLIC PROCEDURE [
fileName, host: STRING, copies: CARDINAL ← 1,
parameterProc: PressUtilities.ParameterProc ← NIL] =
BEGIN
fh: VMDefs.FileHandle ← NIL;
BEGIN ENABLE UNWIND => fh ← PrintDefs.CloseF[fh];
lastPage: CARDINAL ← 0;
isPressFormat: BOOLEAN ← FALSE;
cfh: AltoFileDefs.FP;
user: Core.DMSUser ← @intCommon.user;
Core.Login[user];
fh ← Core.Open[fileName, read ! VMDefs.CantOpen, VMDefs.Error => PrintDefs.PError[InputFileError];];
cfh ← Core.LookupInFileCache[fileName];
--IF cfh # AltoFileDefs.NullFP THEN Core.FreeCacheEntry[fileName];--
[isPressFormat, lastPage] ← IsPressFile[fh];
IF ~isPressFormat THEN BEGIN fh ← PrintDefs.CloseF[fh];
PrintDefs.PError[FileNotPressFormat]; END
ELSE
BEGIN
sh: csD.StreamHandle ← csD.Open[fh, word, read];
SendPressStream[
sh, lastPage, host, copies, parameterProc ! UNWIND => sh ← PrintDefs.DestroyS[sh]];
sh ← PrintDefs.DestroyS[sh];
END;
END;--of ENABLE UNWIND block
END;--of SendPressFile

SendPressStream: PUBLIC PROCEDURE [
stream: csD.StreamHandle, nPages: CARDINAL, host: STRING,
copies: CARDINAL ← 1, parameterProc: PressUtilities.ParameterProc ← NIL] =
BEGIN OPEN EFTPDefs;
ENABLE UNWIND => EFTPAbortSending[""]; -- oops, this may be too often
ba: ARRAY [0..wordsPerPressRecord) OF WORD;
numChars: CARDINAL ← 0;
buffer: POINTER TO ARRAY [0..wordsPerPressRecord) OF WORD ← @ba;
who: PupDefs.PupAddress ← [, , PupTypes.eftpReceiveSoc];
PupDefs.GetPupAddress[@who, host];
EFTPOpenForSending[
who ! EFTPTimeOut => BEGIN SIGNAL ServerTimeout; RESUME ; END;
EFTPTroubleSending =>
BEGIN
IF e = eftpReceiverBusyAbort THEN BEGIN SIGNAL ServerBusy; RETRY; END
ELSE ERROR ServerTrouble[s]; END];
IF parameterProc # NIL THEN
BEGIN
bytes: CARDINAL ← parameterProc[buffer];
IF bytes # 0 THEN EFTPSendBlock[buffer, bytes !
EFTPTimeOut => ERROR ServerTrouble["Timeout"L];
EFTPTroubleSending => ERROR ServerTrouble[s]];
END;
FOR i: CARDINAL IN [1..nPages] DO
numChars ← csD.ReadBlock[stream, buffer, 0, bytesPerPressRecord];
SELECT numChars FROM
bytesPerPressRecord =>
BEGIN
IF i = nPages THEN FillInDDV[LOOPHOLE[buffer], copies];
EFTPSendBlock[buffer, bytesPerPressRecord !
EFTPTimeOut => ERROR ServerTrouble["Timeout"L];
EFTPTroubleSending => ERROR ServerTrouble[s]];
END;
0 => EXIT;
ENDCASE => PrintDefs.PError[FileNotPressFormat]; -- must be whole records
ENDLOOP;
EFTPFinishSending[];
END;

FillInDDV: PROCEDURE [ddv: POINTER TO PressFormat.DDV, copies: CARDINAL] =
BEGIN OPEN PressUtilities;
IF ddv.Passwd # PressFormat.PressPasswd THEN
PrintDefs.PError[FileNotPressFormat];
IF hardcopyUserName # NIL AND
hardcopyUserName.length < LENGTH[ddv.CreatStr]*2 THEN
StringDefs.MesaToBcplString[hardcopyUserName, LOOPHOLE[@ddv.CreatStr]]
ELSE IF intCommon.user.name.length < LENGTH[ddv.CreatStr]*2 THEN
StringDefs.MesaToBcplString[intCommon.user.name, LOOPHOLE[@ddv.CreatStr]]
ELSE StringDefs.MesaToBcplString["NoName"L, LOOPHOLE[@ddv.CreatStr]];
IF copies # 0 THEN BEGIN ddv.fCopy ← 1; ddv.lCopy ← copies END;
END;
END.

--Former Errors
FileNotPressFormat: PUBLIC ERROR = CODE;