-- WalnutLog.Mesa
-- Contents: types and procedures which take the current log file as implicit parameter
-- the current log file is the only file which Walnut writes on, except during an Expunge

-- Last Edited by: Willie-Sue, November 8, 1983 12:43 pm

-- Last Edited by: Donahue, July 18, 1983 9:23 am

DIRECTORY
 BasicTime USING [GMT],
DB USING [Transaction],
 GVBasics USING [RName, Timestamp],
 GVRetrieve USING [Handle],
IO USING [STREAM],
 Rope USING [ROPE],
 ViewerTools USING [TiogaContents];

WalnutLog: CEDAR DEFINITIONS =

BEGIN

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- generally useful TYPES to have defined

ROPE: TYPE = Rope.ROPE;
TiogaContents: TYPE = ViewerTools.TiogaContents;
RName: TYPE = GVBasics.RName;

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

LogEntryType: TYPE = {message, newMessage, insertion, deletion, hasbeenread};
msgIDRope: ROPE;
categoriesRope: ROPE;
copyBuffer: REF TEXT;
minPrefixLength: INT = 24;  -- magic constant from "**start**\n%05d %05d US%g\n"

MessageRecObject
: TYPE = RECORD[
 dateCode: BasicTime.GMT, -- date in msg (or Time.Current[] if none)
 date: ROPE,     -- date in msg
 gvSender: ROPE,    -- The sender as given by Grapevine
inMsgSender: ROPE,   -- if Sender: field is present
 gvID: ROPE,     -- Rope.Cat[gvSender, " $ ", gvTimeStamp]
 to: ROPE,      -- To: field
 from: ROPE,     -- From: field
 subject: ROPE,    -- Subject: field
 categoriesList: LIST OF ROPE, -- categories & keywords, from prefix
 inReplyTo: ROPE,   -- The In-Reply-To: field.
 voiceID: ROPE,    -- The VoiceFileID: field.
 hasBeenRead: BOOLFALSE, -- has this message been displayed or not
tocEntry: ROPE,    -- the table of contents entry for the message
 prefixPos: INT,    -- The log file pos where prefix for this message starts
 headersPos: INT,    -- The log file pos where this message starts
 msgLength: INT    -- The length of this message
 ] ;

MsgRec: TYPE = REF MessageRecObject;

currentSegment: ATOM;

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- see WalnutDB for parallel operation on Walnut's database

-- GVMessageToLog more or less corresponds to DeclareMsg

GVMessageToLog: PROC[
 gvH: GVRetrieve.Handle, timeStamp: GVBasics.Timestamp, gvSender: RName]
  RETURNS[BOOL];
-- reads message items from Grapevine & makes a log entry for this message

LogCreateMsgSet: PROC[mName: ROPE];
-- writes an entry for creating a msgSet

LogDestroyMsgSet: PROC[msName: ROPE];
-- writes an entry for destroying a msgSet

LogAddMsg: PROC[mName: ROPE, msName: ROPE];
-- writes an entry for adding a msg to a msgSet

LogRemoveMsg: PROC[mName: ROPE, msName: ROPE];
-- writes an entry for removing a msg from a msgSet

LogMsgHasBeenRead: PROC[mName: ROPE];
-- writes an entry for reading a msg (displaying for the first time)

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- like GVMessageToLog, but is used by OldMailReader

AddMessageToLog: PROC [entryText, prefix: ROPE];
-- makes a message LogEntryType on log (used by old mail reader)

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- utility routines & ones that read the log

InitializeLog: PROC[fileName: ROPE] RETURNS [curLength: INT];
-- initializes fileName as the current log stream

CloseLogStream: PROC;
-- closes any open stream on log

AbortLogTransaction: PROC;
-- called if FileIOAlpine.Aborted or FileIOAlpine.Failure is raised while Walnut is running
-- cleans up the stream & Walnut's local variables

LogLength: PROC[doFlush: BOOL] RETURNS[curLength: INT];
-- returns length of log file

TiogaTextFromLog: PROC[startPos, length: INT] RETURNS[contents: TiogaContents];
-- reads tioga text from log

RopeFromLog: PROC[startPos, length: INT] RETURNS[ROPE];
-- used by ArchiveMsgSet

NextMsgRecFromLog:
PROC[startPos: INT] RETURNS[endPos: INT, anymore: BOOL, msgRec: MsgRec];
-- scans current log, starting at startPos, until it finds the next message on the log,
-- returns the parsed version in msgRec
-- if there are no more messages, it returns anymore← FALSE

UpdateFromLog: PROC[startPos: INT] RETURNS[success: BOOL];

ResetLogToExpectedLength: PROC;

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

OpenWalnutTransaction
: PROC[segment: ATOM, trans: DB.Transaction, noLog: BOOL];
-- opens a transaction for Walnut, and initializes all the local cached entities
-- this gets called at startup time, and after catching DB.Aborted


CloseWalnutTransaction: PROC;
-- sets the log variables in the database and then closes the transaction

MarkWalnutTransaction: PROC;
-- does a commit of the transaction; also closes and re-opens the log file, to get its
-- create date changed

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- Expunge writes on or changes the current log

ExpungeMsgs: PROC[tempLog: IO.STREAM, doUpdates, tailRewrite: BOOL] RETURNS[ok: BOOL];
-- Dumping is driven from the log file & preserves the bits that came from Grapevine
-- Dumps all the Msgs in the database to a tempLog
-- IF doUpdates it sets all msgs' body pointers to reference the NEW log and
-- copies tempLog to logStream

FinishExpunge: PROC;
-- called if wCopyInProgress is TRUE during startup
-- copies "Walnut.Templog" onto the current log, starting at the StartExpungePos

-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- useful routines

RopeFromTimestamp: PROC[ts: GVBasics.Timestamp] RETURNS [ROPE];

ConstructMsgID: PROC[mr: MsgRec] RETURNS[ROPE];

ParseMsgID: PROC[mr: MsgRec];

GenerateNewMsgID: PROC[mr: MsgRec];

END.