-- file VirtCMFiles.Mesa -- edited by Schroeder, February 13, 1981 10:52 AM -- edited by Brotz, September 28, 1982 5:27 PM DIRECTORY exD: FROM "ExceptionDefs" USING [cantPut, DisplayBothExceptionLines, Exception, nil, putWillOverwrite], Inline USING [BITAND, LowHalf], opD: FROM "OperationsDefs" USING [Expand, FileError, Stuff], ovD: FROM "OverviewDefs" USING [CharMask], TimeDefs USING [PackedTime], vmD: FROM "VirtualMgrDefs" USING [AbandonMessageInsertion, CharIndex, CMOCharMapTableSize, CMOMaxCharPerPage, ComposedMessagePtr, EnsureCMBackingFile, GetMessageChar, GetMessageSize, InsertSubstringInMessage, MessageOverflow, MessageRange, PageNumber, StartMessageInsertion, StopMessageInsertion], VMDefs USING [AllocatePage, GetFileLength, Page, PageNumber, Release, SetFileLength]; VirtCMFiles: PROGRAM IMPORTS exD, Inline, opD, vmD, VMDefs EXPORTS vmD = BEGIN OPEN vmD; PutRangeInFile: PUBLIC PROCEDURE [from: MessageRange, file: STRING, concurrenceNeeded: BOOLEAN, UserConcurs: PROCEDURE [exD.Exception] RETURNS [BOOLEAN]] = -- Overwrites the entire contents of the file with the characters from the message range. -- Pseudo CR's are converted to blanks. If file not empty and concurrenceNeeded, then -- UserConcurs is called and the put proceeds only if TRUE is returned. -- May raise opD.FileError. BEGIN OverwriteCheck: PROCEDURE RETURNS [BOOLEAN] = {RETURN [NOT concurrenceNeeded OR UserConcurs[exD.putWillOverwrite]]}; Get: PROCEDURE RETURNS [POINTER, CARDINAL, BOOLEAN] = 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 - from.message.get.first; copyCount _ MIN[outBytes - outPosition, MIN[from.message.get.free, from.end] - from.start]; FOR i: CARDINAL IN [0 .. copyCount) DO outChars[outPosition + i] _ Inline.BITAND[from.message.buffer.chars[inPosition + i], ovD.CharMask]; ENDLOOP; outPosition _ outPosition + copyCount; from.start _ from.start + copyCount; ENDLOOP; RETURN[outBuffer, outPosition, TRUE]; END; -- of Get -- outBytes: CARDINAL = 512; outBuffer: VMDefs.Page _ VMDefs.AllocatePage[]; outChars: POINTER TO PACKED ARRAY [0 .. 0) OF CHARACTER _ LOOPHOLE[outBuffer]; opD.Stuff [targetName: file, GetBlock: Get, OverwriteOK: OverwriteCheck, callerFileType: text ! opD.FileError => BEGIN VMDefs.Release[outBuffer]; IF reason # cancel THEN exD.DisplayBothExceptionLines[NIL, exD.cantPut, errorString, exD.nil]; END]; VMDefs.Release[outBuffer]; END; -- of PutRangeInFile -- InsertFileInMessage: PUBLIC PROCEDURE [targetIndex: CharIndex, targetMessage: ComposedMessagePtr, file: STRING] = -- Inserts the entire contents of the file in the message starting just before the targetIndex. -- May raise opD.FileError or MessageOverflow. BEGIN AdjustFileSize: PROC [bytes: LONG CARDINAL, createTime: TimeDefs.PackedTime] = BEGIN cmMaxPages: CARDINAL = CARDINAL[CMOCharMapTableSize]; pages: PageNumber _ 0; size: CharIndex _ GetMessageSize[targetMessage]; IF bytes < 2561 THEN RETURN; --dont extend in advance for small file-- IF bytes + size > LONG[CMOMaxCharPerPage] * cmMaxPages THEN ERROR MessageOverflow; IF size # 0 THEN pages _ targetMessage.filePageFF; pages _ pages + Inline.LowHalf [(bytes + CMOMaxCharPerPage - 1) / CMOMaxCharPerPage]; pages _ MIN[pages, cmMaxPages]; EnsureCMBackingFile[targetMessage]; IF VMDefs.GetFileLength[targetMessage.file].page < pages THEN VMDefs.SetFileLength[targetMessage.file, [pages, 0]]; END; -- of AdjustFileSize -- AcceptBlock: PROCEDURE [bP: POINTER, bytes: CARDINAL] RETURNS [BOOLEAN] = BEGIN IF bytes # 0 THEN InsertSubstringInMessage[targetMessage, LOOPHOLE[bP - 2, STRING], 0, bytes]; RETURN[TRUE]; END; -- of AcceptBlock -- StartMessageInsertion[targetMessage, targetIndex]; opD.Expand[file, AcceptBlock, AdjustFileSize ! opD.FileError, vmD.MessageOverflow => AbandonMessageInsertion[targetMessage]]; StopMessageInsertion[targetMessage] END; -- of InsertFileInMessage -- END. -- of VirtCMFiles --z20461e1(529)\f1