-- file: ChollaSpecs.mesa -- edited by Brotz, March 7, 1983 1:27 PM DIRECTORY ccD: FROM "ChollaCmdDefs", dsD: FROM "DisplayDefs", Editor, exD: FROM "ExceptionDefs", inD: FROM "InteractorDefs", intCommon, lmD: FROM "LaurelMenuDefs", MailParseDefs, MessageParse, opD: FROM "OperationsDefs", Storage, String, tsD: FROM "TOCSelectionDefs", vmD: FROM "VirtualMgrDefs"; ChollaSpecs: PROGRAM IMPORTS ccD, dsD, Editor, exD, inD, intC: intCommon, lmD, MailParseDefs, MessageParse, opD, Storage, String, tsD, vmD EXPORTS ccD = BEGIN specOrData: ccD.ChollaFileType; specOrDataFileName: STRING _ [ccD.tocCacheFileStringLength]; InstallSpecs: PUBLIC PROCEDURE = BEGIN tnp: inD.TOCTextNbrPtr = intC.tocTextNbr; toc: vmD.TOCHandle; key: CARDINAL; toc _ tnp.toc; key _ vmD.WaitForLock[toc]; tnp.toc _ NIL; tnp.haveToc _ FALSE; vmD.UnlockTOC[toc, key]; dsD.ClearRectangle[inD.leftMargin, inD.rightMargin, tnp.topY, tnp.bottomY]; intC.bboardCommandHouse.command _ SpecsBBoardCommand; intC.userBracketsHouse.nextHouse _ specsTopHp; inD.ChangeCommandMenu [cnp: intC.mailCommandNbr, region: intC.mailCommandRegion, linesToKeep: 2]; intC.tocCommandNbr.houses _ specsMiddleHp; inD.ChangeCommandMenu [cnp: intC.tocCommandNbr, region: intC.TOCCommandRegion, linesToKeep: 0]; specPostHp.text.length _ 0; specPostHp.typeface _ plainFace; lmD.ChangeEditorMenu[singleLine]; intC.cmCommandNbr.houses _ specsLowerHp; inD.ChangeCommandMenu [cnp: intC.cmCommandNbr, region: intC.CMCommandRegion, linesToKeep: 0]; specOrData _ none; END; -- of InstallSpecs -- SpecsSpecCommand: inD.CommandProcedure = BEGIN IF ~ccD.IsAuthorized[onlooker, hp] THEN RETURN; SELECT TRUE FROM ~confirmed AND ~inD.ConfirmBrackets[hp: specAndDataBracketsHp, fileExtension: "Spec.chml."L] => NULL; specAndDataBracketsHp.text.length = 0 => exD.DisplayExceptionString["Must name a spec file."L]; specAndDataBracketsHp.text.length > ccD.maxSpecNameLength => exD.DisplayExceptionString["Spec name is too long!"L]; ENDCASE => InstallSpecOrData[spec, specAndDataBracketsHp.text]; inD.IndicateCommandFinished[hp]; IF specOrData = spec THEN {inD.IndicateCommandFinished[dataCommandHp]; DrawLineUnder[hp]}; END; -- of SpecsSpecCommand -- SpecsDataCommand: inD.CommandProcedure = BEGIN IF ~ccD.IsAuthorized[onlooker, hp] THEN RETURN; SELECT TRUE FROM ~confirmed AND ~inD.ConfirmBrackets[hp: specAndDataBracketsHp, fileExtension: "Data.chml."L] => NULL; specAndDataBracketsHp.text.length = 0 => exD.DisplayExceptionString["Must name a data file."L]; specAndDataBracketsHp.text.length > ccD.maxSpecNameLength => exD.DisplayExceptionString["Data name is too long!"L]; ENDCASE => InstallSpecOrData[data, specAndDataBracketsHp.text]; inD.IndicateCommandFinished[hp]; IF specOrData = data THEN {inD.IndicateCommandFinished[specCommandHp]; DrawLineUnder[hp]}; END; -- of SpecsDataCommand -- SpecsLaurelCommand: inD.CommandProcedure = BEGIN ccD.RestoreLaurel[]; END; -- of SpecsLaurelCommand -- InstallSpecOrData: PROCEDURE [type: ccD.ChollaFileType, specOrDataName: STRING] = BEGIN postNewDataForm: STRING _ "Post new data form"L; postNewSpec: STRING _ "Post new spec"L; tnp: inD.TOCTextNbrPtr = intC.tocTextNbr; toc: vmD.TOCHandle; key: CARDINAL; ccD.CleanupDisplayMessage[]; IF tnp.toc # NIL THEN BEGIN key _ vmD.WaitForLock[tnp.toc]; toc _ tnp.toc; tnp.toc _ NIL; vmD.UnlockTOC[toc, key]; tnp.haveToc _ FALSE; END; specOrDataFileName.length _ 0; String.AppendString[specOrDataFileName, specOrDataName]; String.AppendString [specOrDataFileName, IF type = spec THEN "Spec"L ELSE "Data"L]; specOrData _ type; [toc, key] _ ccD.GetTOCForFile[specOrDataFileName, IF type = spec THEN spec ELSE data]; IF toc = NIL THEN exD.SysBug[]; tsD.ResetTOCSelection[toc, key]; tnp.toc _ toc; tnp.haveToc _ TRUE; dsD.ClearRectangle[inD.leftMargin, inD.rightMargin, tnp.topY, tnp.bottomY]; inD.TOCTextPainter[tnp, key]; vmD.UnlockTOC[toc, key]; specPostHp.text.length _ 0; specPostHp.typeface _ boldFace; String.AppendString [specPostHp.text, IF type = spec THEN postNewSpec ELSE postNewDataForm]; inD.TextHouseRefresher[specPostHp]; END; -- of InstallSpecOrData -- SpecsBBoardCommand: inD.CommandProcedure = BEGIN IF ~ccD.IsAuthorized[onlooker, hp] THEN RETURN; ccD.CleanupDisplayMessage[]; ccD.InstallBB[]; END; -- of SpecsBBoardCommand -- SpecsDisplayCommand: inD.CommandProcedure = BEGIN IF ~ccD.IsAuthorized[onlooker, hp] THEN RETURN; inD.DisplayMessageCommand[hp, TRUE]; END; -- of SpecsDisplayCommand -- SpecsVersionCommand: inD.CommandProcedure = BEGIN cm: vmD.ComposedMessagePtr; key: CARDINAL; toc: vmD.TOCHandle; newVersionNumber: CARDINAL _ 0; newVersionString: STRING = hp.nextHouse.text; IF ~ccD.IsAuthorized[maven, hp] THEN RETURN; IF specOrData = none THEN {exD.DisplayExceptionString["Neither a spec nor a data file is specified."L]; RETURN}; IF ~confirmed AND ~inD.ConfirmBrackets[hp: hp.nextHouse] THEN RETURN; cm _ vmD.AllocateComposedMessageObject[]; [toc, key] _ ccD.GetTOCForFile [specOrDataFileName, IF specOrData = spec THEN spec ELSE data]; newVersionNumber _ String.StringToDecimal[newVersionString ! String.InvalidNumber => CONTINUE]; IF newVersionNumber + 1 ~IN [2 .. toc.indexFF) THEN exD.DisplayExceptionString["Invalid version number."L] ELSE BEGIN subjectString: STRING _ [30]; fieldList: MessageParse.FieldList; ccD.LoadComposedMessage[toc, key, 1, cm]; String.AppendString[subjectString, "Current version is "L]; String.AppendString[subjectString, hp.nextHouse.text]; fieldList _ MessageParse.MakeFieldList[cm]; MessageParse.ReplaceOrAppendField[cm, @fieldList, "Subject"L, subjectString]; MessageParse.ReplaceOrAppendField[cm, @fieldList, "CurrentVersion"L, hp.nextHouse.text]; MessageParse.ReplaceOrAppendField[cm, @fieldList, "FileName"L, specOrDataFileName]; IF ~ccD.SendChollaMail[replace, specOrData, toc, key, 1, cm, @fieldList] THEN exD.DisplayExceptionString["Problem sending version update!"L]; MessageParse.FreeFieldList[fieldList]; END; vmD.UnlockTOC[toc, key]; vmD.FreeVirtualMessageObject[cm]; END; -- of SpecsVersionCommand -- SpecsPostCommand: inD.CommandProcedure = BEGIN mnp: inD.MessageTextNbrPtr = intC.cmTextNbr; cm: vmD.ComposedMessagePtr = vmD.ComposedMessage[mnp.message]; fieldList: MessageParse.FieldList; key: CARDINAL; toc: vmD.TOCHandle; IF ~ccD.IsAuthorized[maven, hp] THEN RETURN; IF ~ValidatePostedSpecOrData[cm] THEN {exD.DisplayExceptionString["Improper syntax for spec or data form."L]; RETURN}; [toc, key] _ ccD.GetTOCForFile [specOrDataFileName, IF specOrData = spec THEN spec ELSE data]; IF toc.indexFF = 1 THEN BEGIN cm: vmD.ComposedMessagePtr = vmD.AllocateComposedMessageObject[]; verFieldList: MessageParse.FieldList; vmD.InitComposedMessage[cm, "Subject: Current version is 1 CurrentVersion: 1 "L]; verFieldList _ MessageParse.MakeFieldList[cm]; MessageParse.ReplaceOrAppendField[cm, @verFieldList, "FileName"L, specOrDataFileName]; IF ~ccD.SendChollaMail[insert, specOrData, toc, key, 1, cm, @verFieldList] THEN exD.DisplayExceptionString["Problem sending version message!"L]; IF toc.indexFF # 2 THEN exD.SysBug[]; vmD.FreeVirtualMessageObject[cm]; MessageParse.FreeFieldList[verFieldList]; END; fieldList _ MessageParse.MakeFieldList[cm]; MessageParse.ReplaceOrAppendField[cm, @fieldList, "FileName"L, specOrDataFileName]; IF ~ccD.SendChollaMail[insert, specOrData, toc, key, toc.indexFF, cm, @fieldList] THEN exD.DisplayExceptionString["Problem posting new spec or data form!"L] ELSE IF ~WriteMessageToArchive[toc, key, toc.indexFF - 1] THEN exD.DisplayExceptionString["Problem archiving new spec or data form!"L]; vmD.UnlockTOC[toc, key]; MessageParse.DeleteField[cm, @fieldList, "FileName"L]; MessageParse.DeleteField[cm, @fieldList, "UniqueID"L]; MessageParse.DeleteField[cm, @fieldList, "ThisID"L]; MessageParse.DeleteField[cm, @fieldList, "Format"L]; MessageParse.FreeFieldList[fieldList]; Editor.RefreshSoThatFirstCharStartsLine[firstChar: 0, firstLine: mnp.lines, mnp: mnp]; END; -- of SpecsPostCommand -- SpecsArchiveCommand: inD.CommandProcedure = BEGIN toc: vmD.TOCHandle; key, count: CARDINAL; fieldList, subjectFL: MessageParse.FieldList; cm: vmD.ComposedMessagePtr; dm: vmD.DisplayMessagePtr; fp: vmD.TOCFixedPart; IF ~ccD.IsAuthorized[kahuna, hp] THEN RETURN; IF specOrData = none THEN {exD.DisplayExceptionString["Neither a spec nor a data file is specified."L]; RETURN}; dm _ vmD.AllocateDisplayMessageObject[]; cm _ vmD.AllocateComposedMessageObject[]; [toc, key] _ ccD.GetTOCForFile [specOrDataFileName, IF specOrData = spec THEN spec ELSE data]; FOR index: vmD.TOCIndex _ tsD.FirstSelectedEntry[toc, key], tsD.NextSelectedEntry[toc, key, index] UNTIL index = 0 DO vmD.GetTOCFixedPart[toc, key, index, @fp]; IF fp.mark = 'a THEN exD.DisplayExceptionString["Message already archived!"L] ELSE BEGIN uniqueID: ccD.UniqueID; [] _ WriteMessageToArchive[toc, key, index]; vmD.LoadDisplayMessage[toc, key, index, dm]; fieldList _ MessageParse.MakeFieldList[dm]; vmD.InitComposedMessage[cm, "Subject:"L]; [subjectFL, count] _ MessageParse.LocateField[fieldList, "Subject"L]; IF count > 0 THEN vmD.InsertRangeInMessage [vmD.GetMessageSize[cm], cm, [subjectFL.valueStart, subjectFL.valueEnd, dm]]; uniqueID _ ccD.GetIDUsingVM[dm, @fieldList, "UniqueID"L]; vmD.FlushDisplayMessage[dm, key]; ccD.InsertString[cm, vmD.GetMessageSize[cm], ", Archived Archived: TRUE "L]; MessageParse.FreeFieldList[fieldList]; fieldList _ MessageParse.MakeFieldList[cm]; ccD.FillIDField[cm, @fieldList, "UniqueID"L, @uniqueID]; MessageParse.ReplaceOrAppendField[cm, @fieldList, "FileName"L, specOrDataFileName]; IF ~ccD.SendChollaMail[replace, specOrData, toc, key, index, cm, @fieldList] THEN exD.DisplayExceptionString["Problem sending archive update!"L]; MessageParse.FreeFieldList[fieldList]; END; ENDLOOP; vmD.FreeVirtualMessageObject[dm]; vmD.FreeVirtualMessageObject[cm]; vmD.UnlockTOC[toc, key]; END; -- of SpecsArchiveCommand -- SpecsUnarchiveCommand: inD.CommandProcedure = BEGIN toc: vmD.TOCHandle; key: CARDINAL; fieldList: MessageParse.FieldList; cm: vmD.ComposedMessagePtr; fp: vmD.TOCFixedPart; IF ~ccD.IsAuthorized[kahuna, hp] THEN RETURN; IF specOrData = none THEN {exD.DisplayExceptionString["Neither a spec nor a data file is specified."L]; RETURN}; cm _ vmD.AllocateComposedMessageObject[]; [toc, key] _ ccD.GetTOCForFile [specOrDataFileName, IF specOrData = spec THEN spec ELSE data]; FOR index: vmD.TOCIndex _ tsD.FirstSelectedEntry[toc, key], tsD.NextSelectedEntry[toc, key, index] UNTIL index = 0 DO vmD.GetTOCFixedPart[toc, key, index, @fp]; IF fp.mark # 'a THEN exD.DisplayExceptionString["Message wasn't archived!"L] ELSE BEGIN IF ~RetrieveFromArchive[specOrDataFileName, index - 1, cm] THEN {exD.DisplayExceptionString["Problem retrieving from archive!"L]; LOOP}; fieldList _ MessageParse.MakeFieldList[cm]; MessageParse.ReplaceOrAppendField[cm, @fieldList, "FileName"L, specOrDataFileName]; IF ~ccD.SendChollaMail[replace, specOrData, toc, key, index, cm, @fieldList] THEN exD.DisplayExceptionString["Problem sending unarchive update!"L]; MessageParse.FreeFieldList[fieldList]; END; ENDLOOP; vmD.FreeVirtualMessageObject[cm]; vmD.UnlockTOC[toc, key]; END; -- of SpecsUnarchiveCommand -- WriteMessageToArchive: PROCEDURE [toc: vmD.TOCHandle, key: CARDINAL, index: vmD.TOCIndex] RETURNS [BOOLEAN] = BEGIN archiveToc: vmD.TOCHandle; archiveKey: CARDINAL; archiveFile: STRING _ [64]; dm: vmD.DisplayMessagePtr; archiveFF: vmD.TOCIndex; String.AppendString[archiveFile, intC.chollaArchiveFilePath]; String.AppendString[archiveFile, specOrDataFileName]; String.AppendString[archiveFile, ".archive"L]; [archiveToc, archiveKey] _ ccD.GetTOCForFile[archiveFile, archive]; IF archiveToc = NIL THEN RETURN[FALSE]; archiveFF _ vmD.FirstFreeTOCIndex[archiveToc, archiveKey]; dm _ vmD.AllocateDisplayMessageObject[]; FOR i: vmD.TOCIndex IN [archiveFF .. index) DO vmD.LoadDisplayMessage[toc, key, i + 1, dm]; [] _ opD.ReplaceMailOperation [delete: FALSE, index: i, msg: dm, toc: archiveToc, key: archiveKey]; vmD.FlushDisplayMessage[dm, key]; ENDLOOP; vmD.FreeVirtualMessageObject[dm]; vmD.UnlockTOC[archiveToc, archiveKey]; [ , ] _ ccD.GetTOCForFile[NIL, archive]; RETURN[TRUE]; END; -- of WriteMessageToArchive -- RetrieveFromArchive: PUBLIC PROCEDURE [name: STRING, version: CARDINAL, cm: vmD.ComposedMessagePtr] RETURNS [haveIt: BOOLEAN] = -- Fills in cm with a copy of the version'th message from the archived file whose root is -- "name". BEGIN archiveToc: vmD.TOCHandle; archiveKey: CARDINAL; archiveFile: STRING _ [64]; String.AppendString[archiveFile, intC.chollaArchiveFilePath]; String.AppendString[archiveFile, name]; String.AppendString[archiveFile, ".archive"L]; [archiveToc, archiveKey] _ ccD.GetTOCForFile[archiveFile, archive]; IF archiveToc = NIL THEN RETURN[FALSE]; ccD.LoadComposedMessage[archiveToc, archiveKey, version, cm]; vmD.UnlockTOC[archiveToc, archiveKey]; [ , ] _ ccD.GetTOCForFile[NIL, archive]; RETURN[TRUE]; END; -- of RetrieveFromArchive -- ValidatePostedSpecOrData: PROC [vm: vmD.VirtualMessagePtr] RETURNS [valid: BOOLEAN] = BEGIN charIndex: vmD.CharIndex _ 0; vmSize: vmD.CharIndex = vmD.GetMessageSize[vm]; pH: MailParseDefs.ParseHandle = MailParseDefs.InitializeParse[NextChar]; NextChar: PROCEDURE RETURNS [c: CHARACTER] = BEGIN c _ IF charIndex >= vmSize THEN MailParseDefs.endOfInput ELSE vmD.GetMessageChar[vm, charIndex]; charIndex _ charIndex + 1; END; -- of NextChar -- valid _ FALSE; DO string: STRING _ [8]; -- large enough for "Subject" IF ~MailParseDefs.GetFieldName [pH, string ! MailParseDefs.ParseError => GO TO NotParsable] THEN EXIT; IF String.EquivalentString[string, "Subject"L] THEN valid _ TRUE; MailParseDefs.GetFieldBody[pH, string ! MailParseDefs.ParseError => GO TO NotParsable]; REPEAT NotParsable => valid _ FALSE; ENDLOOP; MailParseDefs.FinalizeParse[pH]; END; -- of ValidatePostedSpecOrData -- DrawLineUnder: PROCEDURE [hp: inD.HousePtr] = BEGIN IF hp.topY = hp.bottomY OR hp.leftX = hp.rightX THEN RETURN; dsD.BlackenRectangle[hp.leftX, hp.rightX, hp.bottomY - 2, hp.bottomY]; END; -- of DrawLineUnder -- -- Startup code for ChollaSpecs -- specsTopHp, specsMiddleHp, specsLowerHp, specAndDataBracketsHp, specPostHp, specCommandHp, dataCommandHp: inD.HousePtr; Init: PROCEDURE = BEGIN x: inD.ScreenXCoord; hp: inD.HousePtr; postNewDataForm: STRING = "Post new data form"L; specsTopMenu: ARRAY [0 .. 4) OF lmD.HouseDescriptor _ [[text: "Spec"L, command: SpecsSpecCommand, indicDone: FALSE], [text: ", "L, type: text], [text: "Data"L, type: brackets, bracketsText: ""L, command: SpecsDataCommand, indicDone: FALSE], [text: "Laurel"L, command: SpecsLaurelCommand, indicDone: FALSE, endOfLine: TRUE, rightFlush: TRUE]]; specsMiddleMenu: ARRAY [0 .. 3) OF lmD.HouseDescriptor _ [[text: "Display"L, command: SpecsDisplayCommand], [text: "Archive"L, command: SpecsArchiveCommand], [text: "Unarchive"L, command: SpecsUnarchiveCommand]]; specsLowerMenu: ARRAY [0 .. 3) OF lmD.HouseDescriptor _ [[text: "Get"L, command: inD.GetCommand], [text: "Current version"L, command: SpecsVersionCommand, type: brackets, bracketsText: ""L], [text: postNewDataForm, rightFlush: TRUE, command: SpecsPostCommand]]; specsTopHp _ lmD.CreateCommandHouses [DESCRIPTOR[specsTopMenu], Storage.Node, Storage.String, 2, intC.newMailCommandHouse.leftX]; hp _ specsTopHp.nextHouse; hp.leftX _ x _ specsTopHp.rightX; hp.typeface _ boldFace; hp.rightX _ x _ x + dsD.GetStringWidth[hp.text, boldFace]; hp _ hp.nextHouse; hp.leftX _ x; hp.rightX _ x _ x + dsD.GetStringWidth[hp.text, boldFace]; hp _ hp.nextHouse; x _ x + 7; hp.rightX _ hp.rightX - (hp.leftX - x); hp.leftX _ x; specCommandHp _ lmD.MapHouseTextToHousePtr[specsTopHp, "Spec"L]; dataCommandHp _ lmD.MapHouseTextToHousePtr[specCommandHp, "Data"L]; specAndDataBracketsHp _ dataCommandHp.nextHouse; specsMiddleHp _ lmD.CreateCommandHouses [DESCRIPTOR[specsMiddleMenu], Storage.Node, Storage.String, 0]; specsLowerHp _ lmD.CreateCommandHouses [DESCRIPTOR[specsLowerMenu], Storage.Node, Storage.String, 0]; specPostHp _ lmD.MapHouseTextToHousePtr[specsLowerHp, postNewDataForm]; specPostHp.fixedEdge _ right; END; -- of Init -- Init[]; END. -- of ChollaSpecs --(635)\f1