-- AppendOp.mesa -- Edited by Schroeder, Wednesday Nov. 5, 1980 2:32 pm PST. -- Edited by Brotz, September 1, 1980 10:03 AM DIRECTORY crD: FROM "CoreDefs", exD: FROM "ExceptionDefs", gsD: FROM "GlobalStorageDefs", inD: FROM "InteractorDefs", intCommon: FROM "IntCommon", mfD: FROM "MailFormatDefs", opD: FROM "OperationsDefs", ovD: FROM "OverviewDefs", tsD: FROM "TOCSelectionDefs", vmD: FROM "VirtualMgrDefs"; AppendOp: PROGRAM IMPORTS crD, gsD, inD, intC:intCommon, mfD, tsD, vmD EXPORTS opD SHARES opD = BEGIN fileAccessError: ERROR = CODE; -- Had error return trying to read or write a file AppendMailToFileOperation: PUBLIC PROCEDURE [appendFileName: crD.UFilename] RETURNS [ovD.ErrorCode] = BEGIN -- variables of the procedure appendFileHandle: crD.UFileHandle; errorCode, errorCode2: ovD.ErrorCode; tOCEntry: vmD.TOCFixedPart; tb: vmD.TOCFixedPartPtr = @tOCEntry; b, count, bytesToCopy, index: CARDINAL; messageIndex: vmD.TOCIndex; aMessageWasCopied: BOOLEAN _ FALSE; outBufferPage: gsD.MemoryPagePtr; outBufferString: STRING; -- turns the BufferPage into a string outBufferSize: CARDINAL; -- size in bytes, always a multiple of 512 nextOutSlot: CARDINAL; pageInOutBuffer: crD.PageNumber; inBufferPage: gsD.MemoryPagePtr; inBufferString: STRING; -- turns the BufferPage into a string nextInSlot: CARDINAL; pageInInBuffer: crD.PageNumber; eofPage: crD.PageNumber; eofByte: CARDINAL; -- internal procedures of AppendMailToFileOperation WriteOutputBuffer: PROCEDURE = BEGIN IF (errorCode _ crD.WritePages[outBufferPage, nextOutSlot, pageInOutBuffer, appendFileHandle]) # ovD.ok THEN ERROR fileAccessError; pageInOutBuffer _ pageInOutBuffer + outBufferSize/512; nextOutSlot _ 0; END; -- of WriteOutputBuffer -- ReadInputBuffer: PROCEDURE = BEGIN [errorCode, ] _ crD.ReadPages[inBufferPage, 512, pageInInBuffer, intC.mailFileHandle]; IF errorCode # ovD.ok THEN ERROR fileAccessError; END; -- of ReadInputBuffer -- APutChar: PROCEDURE [c: CHARACTER] = BEGIN IF nextOutSlot >= outBufferSize THEN WriteOutputBuffer[]; outBufferString[nextOutSlot] _ c; nextOutSlot _ nextOutSlot +1; count _ count +1; END; -- of APutChar -- AGetChar: PROCEDURE RETURNS [CHARACTER] = BEGIN --assumes that page boundary won't be crossed nextOutSlot _ nextOutSlot + 1; RETURN[outBufferString[nextOutSlot - 1]]; END; -- of AGetChar -- -- code for AppendMailToFileOperation [errorCode, appendFileHandle] _ crD.OpenFile[intC.user, appendFileName, update]; IF errorCode # ovD.ok THEN RETURN[errorCode]; outBufferSize _ IF tsD.LastSelectedEntry[] < tsD.FirstSelectedEntry[] + 20 THEN 1024 ELSE 2048; outBufferPage _ gsD.GetMemoryPages[outBufferSize / 512]; outBufferString _ LOOPHOLE[outBufferPage - 2, STRING]; inBufferPage _ gsD.GetMemoryPages[1]; inBufferString _ LOOPHOLE[inBufferPage - 2, STRING]; BEGIN -- block for exits ENABLE fileAccessError => BEGIN IF errorCode = ovD.diskFull OR errorCode = ovD.fileTooBig THEN [] _ crD.UFileTruncate[eofPage, eofByte, appendFileHandle]; GOTO cleanupAndReturn; END; [errorCode, eofPage, eofByte] _ crD.UFileLength[appendFileHandle]; IF errorCode # ovD.ok THEN GOTO cleanupAndReturn; IF eofPage # 0 OR eofByte # 0 THEN BEGIN --see if target file looks like a mail file pageInOutBuffer _ nextOutSlot _ 0; [errorCode, ] _ crD.ReadPages[outBufferPage, 512, pageInOutBuffer, appendFileHandle]; IF errorCode # ovD.ok THEN GOTO cleanupAndReturn; IF mfD.ParseStamp[AGetChar, tb] # ovD.ok THEN {IF ~inD.AskUserToConfirm[exD.moveTargetExists] THEN GOTO cleanupAndReturn}; END; pageInOutBuffer _ eofPage; nextOutSlot _ eofByte; IF pageInOutBuffer > 0 AND nextOutSlot > 0 THEN BEGIN [errorCode, ] _ crD.ReadPages[outBufferPage, 512, pageInOutBuffer, appendFileHandle]; IF errorCode # ovD.ok THEN GOTO cleanupAndReturn; END; pageInInBuffer _ 77777B; FOR messageIndex _ tsD.FirstSelectedEntry[], tsD.NextSelectedEntry[messageIndex] UNTIL messageIndex = 0 DO -- loop for each message vmD.GetTOCFixedPart[messageIndex,tb]; IF ~tb.deleted THEN BEGIN IF tb.changed THEN BEGIN count _ 0; mfD.CreateStamp[tb, APutChar]; b _ tb.firstByte + count; tb.firstPage _ tb.firstPage + b/512; tb.firstByte _ b MOD 512; tb.offsetToHeader _ tb.offsetToHeader - count; END; IF pageInInBuffer # tb.firstPage THEN {pageInInBuffer _ tb.firstPage; ReadInputBuffer[]}; nextInSlot _ tb.firstByte; bytesToCopy _ tb.offsetToHeader + tb.textLength; UNTIL bytesToCopy = 0 DO IF nextInSlot > 511 THEN --need a new page in the input buffer {pageInInBuffer _ pageInInBuffer +1; ReadInputBuffer[]; nextInSlot _ 0}; DO -- copy input buffer count _ MIN[outBufferSize - nextOutSlot, 512 - nextInSlot, bytesToCopy]; FOR index IN [0 .. count) DO outBufferString[nextOutSlot + index] _ inBufferString[nextInSlot + index]; ENDLOOP; nextInSlot _ nextInSlot + count; bytesToCopy _ bytesToCopy - count; IF (nextOutSlot _ nextOutSlot + count) >= outBufferSize THEN WriteOutputBuffer[]; IF nextInSlot > 511 OR bytesToCopy = 0 THEN EXIT; ENDLOOP; -- copy input buffer ENDLOOP; -- UNTIL bytesToCopy = 0 aMessageWasCopied _ TRUE; END; -- of ~tb.deleted THEN block ENDLOOP; -- loop for each message IF aMessageWasCopied AND nextOutSlot # 0 THEN WriteOutputBuffer[]; GOTO cleanupAndReturn; EXITS cleanupAndReturn => BEGIN errorCode2 _ crD.CloseFile[appendFileHandle]; IF errorCode = ovD.ok THEN errorCode _ errorCode2; --return the first error gsD.ReturnMemoryPages[outBufferSize / 512, outBufferPage]; gsD.ReturnMemoryPages[1, inBufferPage]; RETURN[IF (~aMessageWasCopied AND errorCode = ovD.ok) THEN ovD.noMessagesMoved ELSE errorCode]; END; END; -- of EXITS block END; -- of AppendMailToFileOperation -- END. -- of AppendOp --z20461(529)\f1 5801f0