<<>> <> <> <> <> <<>> DIRECTORY BlackCherry, BlackCherryInternal, BlackCherrySidedoor, IO, RefText, Rope; BlackCherrySidedoorImpl: CEDAR MONITOR IMPORTS BlackCherryInternal, BlackCherrySidedoor, IO, Rope EXPORTS BlackCherryInternal ~ BEGIN OPEN BlackCherry, BlackCherryInternal, BlackCherrySidedoor; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; <
> <<>> <> BCMailLog: PUBLIC PROC[ fileData: BlackCherry.BCFileData, strmProc: MsgFromStreamProc, ropeProc: MsgFromRopesProc] RETURNS[ok: BOOL ¬ FALSE] = { writeStream: STREAM = fileData.writeStream; posForEntry: INT ~ writeStream.GetIndex[]; endOfMsgs, posForMsgs: INT; numMsgs: INT ¬ 0; msgH, lastMsgH, thisMsgH: MsgHandle; writeStream.PutF[relTocPointerEntryTemplate, [integer[0]], [integer[0]] ]; posForMsgs ¬ writeStream.GetIndex[]; DO entryPos, msgTemplatePos, headersPos, thisTextLen, thisFormatLen: INT; streamForMsg: STREAM; thisMsgID, text, formatting: ROPE; unRead: BOOL; IF strmProc # NIL THEN { [streamForMsg, thisMsgID, unRead, thisTextLen, thisFormatLen] ¬ strmProc[]; IF streamForMsg = NIL THEN EXIT; } ELSE { [thisMsgID, text, formatting, unRead] ¬ ropeProc[]; IF thisMsgID = NIL THEN EXIT; IF NOT Rope.IsEmpty[formatting] THEN text ¬ text.Substr[1]; }; numMsgs ¬ numMsgs + 1; writeStream.SetIndex[entryPos ¬ writeStream.GetLength[]]; writeStream.PutF1[headerEntryTemplate, [integer[0]] ]; msgTemplatePos ¬ writeStream.GetIndex[]; writeStream.PutF[createMsgTemplate, [rope[thisMsgID]], [integer[0]], [integer[0]] ]; headersPos ¬ writeStream.GetIndex[]; IF streamForMsg # NIL THEN CopyBytes[to: writeStream, from: streamForMsg, num: thisTextLen+thisFormatLen] ELSE { writeStream.PutRope[text]; writeStream.PutRope[formatting]; thisTextLen ¬ text.Length[]; thisFormatLen ¬ formatting.Length[]; }; writeStream.PutChar['\r]; writeStream.SetIndex[msgTemplatePos]; writeStream.PutF[createMsgTemplate, [rope[thisMsgID]], [integer[thisTextLen]], [integer[thisFormatLen]] ]; writeStream.SetIndex[entryPos]; writeStream.PutF1[headerEntryTemplate, [integer[writeStream.GetLength[] - entryPos]] ]; thisMsgH ¬ NEW[MsgHandleRec ¬ [headersPos: headersPos, textLen: thisTextLen, formatPos: headersPos+thisTextLen, formatLen: thisFormatLen] ]; thisMsgH.unRead ¬ unRead; thisMsgH.entryStart ¬ entryPos; thisMsgH.entryLen ¬ writeStream.GetLength[] - entryPos; IF ( msgH = NIL ) THEN msgH ¬ lastMsgH ¬ thisMsgH ELSE IF ( thisMsgH # NIL ) THEN { lastMsgH.next ¬ thisMsgH; lastMsgH ¬ thisMsgH }; ENDLOOP; endOfMsgs ¬ writeStream.GetLength[]; writeStream.SetIndex[posForEntry]; writeStream.PutF[relTocPointerEntryTemplate, [integer[posForMsgs-posForEntry]], [integer[endOfMsgs]] ]; [] ¬ BlackCherryInternal.WriteTOC[fileData.readStream, writeStream, numMsgs, 0, msgH, TRUE]; fileData.writeStream.Close[]; fileData.readStream.Close[ ! IO.Error => CONTINUE]; ok ¬ TRUE; }; <<>> <> bufsiz: NAT ~ RefText.page; copyBuffer: REF TEXT ¬ NEW[TEXT[bufsiz]]; CopyBytes: PROC [to, from: IO.STREAM, num: INT] ~ { bytes: INT ¬ num; WHILE ( bytes >= bufsiz ) DO [] ¬ from.GetBlock[copyBuffer, 0, bufsiz]; to.PutBlock[copyBuffer]; bytes ¬ bytes - bufsiz; ENDLOOP; IF ( bytes # 0 ) THEN { [] ¬ from.GetBlock[copyBuffer, 0, bytes]; to.PutBlock[copyBuffer]; }; }; <<>> END.