-- file VirtCMFiles.Mesa
-- edited by Schroeder, February 13, 1981 10:52 AM
-- edited by Brotz, January 29, 1981 12:05 PM

DIRECTORY
crD: FROM "CoreDefs",
exD: FROM "ExceptionDefs",
gsD: FROM "GlobalStorageDefs",
InlineDefs,
opD: FROM "OperationsDefs",
ovD: FROM "OverviewDefs",
TimeDefs,
vmD: FROM "VirtualMgrDefs";

VirtCMFiles: PROGRAM
IMPORTS crD, exD, gsD, InlineDefs, opD, vmD
EXPORTS vmD
SHARES vmD =

PUBLIC BEGIN

OPEN vmD;

PutRangeInFile: PROCEDURE [from: MessageRange, file: crD.UFilename,
user: crD.DMSUser, concurrenceNeeded: BOOLEAN,
UserConcurs: PROC [exD.Exception] RETURNS [BOOLEAN]]
RETURNS [errorCode: ovD.ErrorCode] =
-- Overwrites the entire contents of the file with the characters from the message range.
-- PCR bits are turned off. If file not empty and cuncurrenceNeeded, then
-- UserConcurs is called and the put proceeds only if TRUE is returned. Errors encountered
-- while opening or writing the file are returned. Own exception messages are written.
BEGIN
WITH m: from.message↑ SELECT FROM
CM =>
BEGIN
OverwriteCheck: PROCEDURE RETURNS [BOOLEAN] =
{RETURN [NOT concurrenceNeeded OR UserConcurs[exD.putWillOverwrite]]};
Get: PROCEDURE RETURNS [POINTER, CARDINAL, ovD.ErrorCode] =
BEGIN
copyCount, inPosition: CARDINAL;
outPosition: CARDINAL ← 0;
UNTIL outPosition = outBytes OR from.start >= from.end DO
[] ← GetMessageChar[from.message, from.start]; --load get cache with buffer page
inPosition ← from.start - m.get.first;
copyCount ← MIN[outBytes-outPosition, MIN[m.get.free, from.end] - from.start];
FOR i: CARDINAL IN [0 .. copyCount) DO
outString[outPosition+i] ←
InlineDefs.BITAND[m.get.string[inPosition+i], ovD.CharMask];
ENDLOOP;
outPosition ← outPosition + copyCount;
from.start ← from.start + copyCount;
ENDLOOP;
RETURN[outBuffer, outPosition, ovD.ok];
END; --of Get--
outBytes: CARDINAL = 1024;
outBuffer: POINTER ← gsD.GetMemoryPages[outBytes/512];
outString: STRING ← LOOPHOLE[outBuffer-2, STRING];
errorString: STRING;
[errorCode, errorString] ← opD.Stuff
[targetName: file, GetBlock: Get, OverwriteOK: OverwriteCheck, callerFileType: text];
gsD.ReturnMemoryPages[outBytes/512, outBuffer];
IF errorCode#ovD.ok AND errorCode#ovD.cancelCode THEN
BEGIN
exD.DisplayBothExceptionLines[NIL, exD.cantPut, errorString, exD.nil];
IF errorString # NIL THEN opD.FreeErrorString[errorString];
END;
END;
ENDCASE => exD.SysBug[];
END; -- of PutRangeInFile --



InsertFileInMessage: PROCEDURE [targetIndex: ovD.CharIndex,
targetMessage: ComposeMessagePtr, file: crD.UFilename, user: crD.DMSUser]
RETURNS [errorCode: ovD.ErrorCode, errorString: STRING] =
-- Inserts the entire contents of the local file, remote file or distribution list in the message
-- starting just before the targetIndex. The insertion is abandoned if any errors are
-- encountered.
BEGIN
AdjustFileSize: PROC [bytes: LONG CARDINAL, createTime: TimeDefs.PackedTime] =
BEGIN
cmMaxPages: CARDINAL = CARDINAL[cMOCharMapTableSize];
pages: PageNumber ← 0;
size: ovD.CharIndex ← GetMessageSize[targetMessage];
fakeEntry: MemoryTableEntry;
IF bytes < 2561 THEN RETURN; --dont extend in advance for small file--
IF bytes+size > LONG[cMOMaxCharPerPage]*cmMaxPages
THEN {tooBig ← TRUE; RETURN};
IF size # 0 THEN pages ← targetMessage.filePageFF;
pages ← pages +
InlineDefs.LowHalf [(bytes + cMOMaxCharPerPage - 1) / cMOMaxCharPerPage];
pages ← MIN[pages, cmMaxPages];
IF targetMessage.file # NIL
AND crD.UFileLength[targetMessage.file].lastPage >= pages
THEN RETURN;
fakeEntry.filePageNumber ← pages - 1;
fakeEntry.address ← LOOPHOLE[400B];
WritePageToFile[targetMessage, @fakeEntry];
END; -- of AdjustFileSize --
AcceptBlock: PROCEDURE [bP: POINTER, bytes: CARDINAL]
RETURNS [erc: ovD.ErrorCode]=
BEGIN
erc ← SELECT TRUE FROM
tooBig => ovD.cMTooBig,
(bytes = 0) => ovD.ok,
ENDCASE =>
InsertSubstringInMessage[targetMessage, LOOPHOLE[bP - 2, STRING], 0, bytes];
END; -- of AcceptBlock --
tooBig: BOOLEAN ← FALSE;
StartMessageInsertion[targetMessage, targetIndex];
[errorCode, errorString] ← opD.Expand[file, AcceptBlock, AdjustFileSize];
IF errorCode = ovD.ok
THEN StopMessageInsertion[targetMessage]
ELSE AbandonMessageInsertion[targetMessage];
END; -- of InsertFileInMessage --

END. -- of VirtCMFiles --