-- file: BruceTalker.mesa -- edited by Barth, March 26, 1982 1:41 PM -- edited by Chi Yung Fu, April 30, 1982 2:40 PM -- edited by Chi Yung Fu, September 1, 1983 11:28 AM -- edited by JWhite, 22-Dec-83 9:34:50 DIRECTORY BruceDefs, csD: FROM "CoreStreamDefs", dsD: FROM "DisplayDefs", Editor, exD: FROM "ExceptionDefs", InlineDefs, inD: FROM "InteractorDefs", intCommon, lmD: FROM "LaurelMenuDefs", MachineParseDefs, MiscDefs, Process, prD: FROM "ProtectionDefs", Storage, String, vmD: FROM "VirtualMgrDefs", VMDefs; BruceTalker: PROGRAM IMPORTS BruceDefs, csD, Editor, exD, InlineDefs, inD, intC: intCommon, lmD, MachineParseDefs, MiscDefs, Process, prD, Storage, String, vmD, VMDefs EXPORTS BruceDefs = BEGIN running: BOOLEAN ← TRUE; bufferIndex: TYPE = [0..SIZE[BruceDefs.Recipe]); bufferPtr: TYPE = POINTER TO ARRAY bufferIndex OF WORD; bruceRecipe: BruceDefs.RecipePtr; bruceDefault: BruceDefs.RecipePtr; oldCmHp: inD.HousePtr; LowerHp: inD.HousePtr; TubeTextHp: inD.HousePtr; StartTalker: PUBLIC PROCEDURE= BEGIN sh:csD.StreamHandle; bp:bufferPtr; cm: inD.MessageTextNbrPtr = intC.cmTextNbr; LowerMenu: ARRAY [0 .. 12) OF lmD.HouseDescriptor ← [[text: "Start"L, command: StartCommand], [text: "Abort"L, command: AbortCommand], [text: "AckAlarm"L, command: AckAlarmCommand], [text: "Get"L, type: brackets, bracketsText: ""L, command: GetCommand], [text: "Put"L, type: brackets, bracketsText: ""L, command: PutCommand], [text: "Tube"L, type: brackets, bracketsText: " "L, command: TubeCommand], [text: "Upload"L, command: UploadCommand], [text: "Download"L, command: DownloadCommand], [text: "Quit"L, command: BruceQuitCommand, indicDone: FALSE], [text: "Compile"L, command: CompileCommand], [text: "InitTables"L, command: InitTablesCommand], [text: "UpdateDefault"L, command: UpdateDefault]]; LowerHp ← lmD.CreateCommandHouses [DESCRIPTOR[LowerMenu], Storage.Node, Storage.String]; TubeTextHp ← lmD.MapHouseTextToHousePtr[LowerHp, "Tube"L].nextHouse; bruceDefault ← Storage.Node[SIZE[BruceDefs.Recipe]]; bp ← LOOPHOLE[bruceDefault]; sh ← csD.OpenFromName["BruceDefaultRecipe.binary"L, word, read ! VMDefs.CantOpen => GOTO defaultNotFound]; FOR i:CARDINAL IN bufferIndex DO bp[i] ← csD.Read[sh ! VMDefs.Error => GOTO earlyEnd]; ENDLOOP; csD.Destroy[sh]; Editor.Getter[0, vmD.GetMessageSize[cm.message], cm, "BruceConstants.text"L]; BruceDefs.InitTables[cm.message ! MachineParseDefs.ParseFault => BEGIN ReportParseFault[why, pfBegin, pfEnd]; GOTO oops; END]; EXITS defaultNotFound => exD.DisplayExceptionString[ "Couldn't find file BruceDefaultRecipe.binary"L]; earlyEnd => exD.DisplayExceptionString[ "File BruceDefaultRecipe.binary is messed up"L]; oops => NULL; END; -- of StartTalker InstallTalker: PUBLIC PROCEDURE = BEGIN bruceRecipe ← Storage.Node[SIZE[BruceDefs.Recipe]]; MiscDefs.Zero[bruceRecipe,SIZE[BruceDefs.Recipe]]; inD.StopBlinkingCaret[]; oldCmHp ← intC.cmCommandNbr.houses; intC.cmCommandNbr.houses ← LowerHp; inD.ChangeCommandMenu [cnp: intC.cmCommandNbr, region: intC.CMCommandRegion, linesToKeep: 0]; IF inD.CaretIsBlinking[] THEN inD.SetCaretBlinking[intC.target.point, intC.target.mnp]; BruceDefs.Initialize[]; END; -- of InstallTalker -- ExecuteStep: PUBLIC PROCEDURE [data, spec: vmD.VirtualMessagePtr] RETURNS [result: STRING] = BEGIN tube:BruceDefs.TubeNumber; InlineDefs.COPY[bruceDefault, SIZE[BruceDefs.Recipe], bruceRecipe]; tube ← BruceDefs.SpecToBinary[data, spec, bruceRecipe ! MachineParseDefs.ParseFault => BEGIN ReportParseFault[why, pfBegin, pfEnd]; GOTO oops; END]; BruceDefs.DownLoad[tube, bruceRecipe !BruceDefs.CommFailure => {ReportCommFailure[]; GOTO oops}]; BruceDefs.Command[tube, Start !BruceDefs.CommFailure => {ReportCommFailure[]; GOTO oops}]; EXITS oops => NULL; END; -- of ExecuteStep -- GetDefault: PUBLIC PROCEDURE[brp: BruceDefs.RecipePtr] = BEGIN InlineDefs.COPY[bruceDefault, SIZE[BruceDefs.Recipe], brp]; END; -- of GetDefault -- UpdateDefault: inD.CommandProcedure = BEGIN sh:csD.StreamHandle; bp:bufferPtr; bp ← LOOPHOLE[bruceDefault]; --get confirmation before updating default receipe exD.DisplayBothExceptionLines ["Do you really want to update the default receipe.",0, "", 0, FALSE]; IF ~inD.Confirm[2] THEN GOTO oops; exD.DisplayBothExceptionLines ["LAST CHANCE! Do you really want to do this? Can't claim computer failure.", 0, "", 0, TRUE]; IF ~inD.Confirm[2] THEN GOTO oops; --update default receipe InlineDefs.COPY[bruceRecipe, SIZE[BruceDefs.Recipe], bruceDefault]; sh ← csD.OpenFromName["BruceDefaultRecipe.binary"L, word, overwrite ! VMDefs.CantOpen => GOTO streamFailure]; FOR i:CARDINAL IN bufferIndex DO csD.Write[sh, bp[i] ! VMDefs.Error => GOTO streamFailure]; ENDLOOP; csD.Close[sh! VMDefs.Error => GOTO streamFailure]; EXITS oops => NULL; streamFailure => exD.DisplayExceptionString[ "Couldn't write BruceDefaultRecipe.binary"L]; END; -- of UpdateDefault -- BruceQuitCommand: inD.CommandProcedure = BEGIN Storage.Free[bruceRecipe]; inD.StopBlinkingCaret[]; intC.cmCommandNbr.houses ← oldCmHp; inD.ChangeCommandMenu [cnp: intC.cmCommandNbr, region: intC.CMCommandRegion, linesToKeep: 0]; IF inD.CaretIsBlinking[] THEN inD.SetCaretBlinking[intC.target.point, intC.target.mnp]; BruceDefs.Terminate[]; running ← FALSE; END; -- of BruceQuitCommand -- GetCommand: inD.CommandProcedure = BEGIN cm: inD.MessageTextNbrPtr = intC.cmTextNbr; oldText: STRING ← [inD.maxBracketStringLength]; String.AppendString[oldText, hp.nextHouse.text]; IF ~confirmed AND ~inD.ConfirmBrackets[hp: hp.nextHouse, fileExtension: ".form."L] THEN RETURN; IF intC.composedMessageEdited AND vmD.GetMessageSize[cm.message] # 0 AND ~inD.AskUserToConfirm[exD.willReplaceMessage] THEN {inD.RefreshHouse[hp.nextHouse, oldText]; RETURN}; Editor.Getter[0, vmD.GetMessageSize[cm.message], cm, hp.nextHouse.text]; intC.runCommandMode ← FALSE; END; -- of GetCommand -- PutCommand: inD.CommandProcedure = BEGIN oldText: STRING ← [inD.maxBracketStringLength]; String.AppendString[oldText, hp.nextHouse.text]; IF (confirmed OR inD.ConfirmBrackets[hp: hp.nextHouse, fileExtension: ".form."L]) AND Editor.Putter[0, vmD.GetMessageSize[intC.cmTextNbr.message], intC.cmTextNbr, hp.nextHouse, oldText] THEN intC.composedMessageEdited ← FALSE; IF inD.CaretIsBlinking[] THEN inD.SetCaretBlinking[intC.target.point, intC.target.mnp]; END; -- of PutCommand -- TubeCommand: inD.CommandProcedure = BEGIN oldText: STRING ← [inD.maxBracketStringLength]; String.AppendString[oldText, hp.nextHouse.text]; IF ~confirmed AND ~inD.ConfirmBrackets[hp: hp.nextHouse] THEN RETURN; IF hp.nextHouse.text.length#1 OR LOOPHOLE[hp.nextHouse.text[0],CARDINAL] < LOOPHOLE['1,CARDINAL] OR LOOPHOLE[hp.nextHouse.text[0],CARDINAL] > LOOPHOLE['8,CARDINAL] THEN BEGIN exD.DisplayExceptionString["Invalid tube number"L]; inD.RefreshHouse[hp.nextHouse, oldText]; RETURN; END; END; -- of TubeCommand -- GetTubeNumber: PROCEDURE RETURNS[tube:BruceDefs.TubeNumber]= BEGIN tube ← LOOPHOLE[TubeTextHp.text[0], CARDINAL] - LOOPHOLE['0, CARDINAL]; END; -- of GetTubeNumber ReportCommFailure: PROCEDURE= BEGIN exD.DisplayExceptionString["Communications failure, try again."L]; END; -- of ReportCommFailure StartCommand: inD.CommandProcedure = BEGIN exD.DisplayBothExceptionLines ["Is the tube number correct? I hope you human know what you are doing.",0, "", 0, FALSE]; IF ~inD.Confirm[2] THEN GOTO oops; exD.DisplayBothExceptionLines ["FINAL CALL! Otherwise, wave goodbye to the wafers.", 0, "", 0, TRUE]; IF ~inD.Confirm[2] THEN GOTO oops; BruceDefs.Command[GetTubeNumber[], Start !BruceDefs.CommFailure => {ReportCommFailure[]; GOTO oops}]; EXITS oops => NULL; END; -- of StartCommand -- AbortCommand: inD.CommandProcedure = BEGIN BruceDefs.Command[GetTubeNumber[], Abort !BruceDefs.CommFailure => {ReportCommFailure[]; GOTO oops}]; EXITS oops => NULL; END; -- of AbortCommand -- AckAlarmCommand: inD.CommandProcedure = BEGIN BruceDefs.Command[GetTubeNumber[], AckAlarm !BruceDefs.CommFailure => {ReportCommFailure[]; GOTO oops}]; EXITS oops => NULL; END; -- of AckAlarmCommand -- UploadCommand: inD.CommandProcedure = BEGIN mnp: inD.MessageTextNbrPtr = intC.cmTextNbr; composedMessage: vmD.ComposedMessagePtr; IF ~confirmed AND intC.composedMessageEdited AND vmD.GetMessageSize[mnp.message] # 0 AND ~inD.AskUserToConfirm[exD.willReplaceMessage] THEN RETURN; BruceDefs.UpLoad[GetTubeNumber[], bruceRecipe !BruceDefs.CommFailure => {ReportCommFailure[]; GOTO oops}]; Editor.SwapMessageWithDeletionBuffer[mnp]; Editor.ResetInsertionBuffer[mnp]; composedMessage ← vmD.ComposedMessage[mnp.message]; vmD.InitComposedMessage[composedMessage, ""L]; BruceDefs.BinaryToAscii[composedMessage, bruceRecipe]; intC.commandType ← get; intC.source ← inD.TextSelection [mnp: mnp, start: 0, end: 0, point: 0, mode: char, pendingDelete: FALSE, key: 0]; intC.target ← inD.TextSelection [mnp: mnp, start: 0, end: 0, point: 0, mode: char, pendingDelete: FALSE, key: 0]; intC.newTargetSelection ← TRUE; intC.actionPoint ← 0; intC.pendingDeleteSetByControl ← FALSE; IF mnp.protectedFieldPtr # NIL THEN prD.UnprotectAllFields[@mnp.protectedFieldPtr]; Editor.RefreshSoThatFirstCharStartsLine[firstChar: 0, firstLine: mnp.lines, mnp: mnp]; mnp.haveMessage ← TRUE; intC.runCommandMode ← FALSE; intC.composedMessageEdited ← FALSE; EXITS oops => NULL; END; -- of UploadCommand -- DownloadCommand: inD.CommandProcedure = BEGIN exD.DisplayBothExceptionLines ["Tube number correct? Download into a wrong tube could be DISASTROUS.",0, "", 0, FALSE]; IF ~inD.Confirm[2] THEN GOTO oops; exD.DisplayBothExceptionLines ["LAST CHANCE! Uncle Bill may get you for this. Just don't blame it on me.", 0, "", 0, TRUE]; IF ~inD.Confirm[2] THEN GOTO oops; InlineDefs.COPY[bruceDefault, SIZE[BruceDefs.Recipe], bruceRecipe]; BruceDefs.AsciiToBinary[intC.cmTextNbr.message, bruceRecipe ! MachineParseDefs.ParseFault => BEGIN ReportParseFault[why, pfBegin, pfEnd]; GOTO oops; END]; BruceDefs.DownLoad[GetTubeNumber[], bruceRecipe !BruceDefs.CommFailure => {ReportCommFailure[]; GOTO oops}]; EXITS oops => NULL; END; -- of DownloadCommand -- CompileCommand: inD.CommandProcedure = BEGIN mnp: inD.MessageTextNbrPtr = intC.cmTextNbr; composedMessage: vmD.ComposedMessagePtr; tube:BruceDefs.TubeNumber; composedMessage ← vmD.ComposedMessage[mnp.message]; InlineDefs.COPY[bruceDefault, SIZE[BruceDefs.Recipe], bruceRecipe]; tube ← BruceDefs.SpecToBinary[NIL, mnp.message, bruceRecipe ! MachineParseDefs.ParseFault => BEGIN ReportParseFault[why, pfBegin, pfEnd]; GOTO oops; END]; BruceDefs.BinaryToAscii[composedMessage, bruceRecipe]; Editor.RefreshSoThatFirstCharStartsLine[firstChar: 0, firstLine: mnp.lines, mnp: mnp]; EXITS oops => NULL; END; -- of CompileCommand -- InitTablesCommand: inD.CommandProcedure = BEGIN mnp: inD.MessageTextNbrPtr = intC.cmTextNbr; composedMessage: vmD.ComposedMessagePtr; composedMessage ← vmD.ComposedMessage[mnp.message]; exD.DisplayBothExceptionLines ["Are you sure you want InitTable.",0, "", 0, FALSE]; IF ~inD.Confirm[2] THEN GOTO oops; exD.DisplayBothExceptionLines ["LAST CHANCE. Are you ABSOLUTELY sure you want InitTable.", 0, "", 0, TRUE]; IF ~inD.Confirm[2] THEN GOTO oops; BruceDefs.InitTables[composedMessage ! MachineParseDefs.ParseFault => BEGIN ReportParseFault[why, pfBegin, pfEnd]; GOTO oops; END]; EXITS oops => NULL; END; -- of CompileCommand -- ReportParseFault: PROCEDURE[why:STRING, pfBegin:vmD.CharIndex, pfEnd:vmD.CharIndex] = BEGIN BruceDefs.WarningCarat[pfBegin,pfEnd]; IF intC.editorType = modeless THEN inD.SetCaretBlinking[intC.target.point, intC.cmTextNbr]; exD.DisplayExceptionString[why]; END; -- of ReportParseFault -- WarningCarat: PUBLIC PROCEDURE[pfBegin:vmD.CharIndex,pfEnd:vmD.CharIndex] = BEGIN Editor.CancelTargetSelection[]; Editor.CancelSourceSelection[intC.cmTextNbr]; inD.StopBlinkingCaret[]; intC.target ← inD.TextSelection [intC.cmTextNbr, pfBegin, pfEnd, pfBegin, 0, char, intC.editorType = modeless AND pfBegin < pfEnd]; intC.pendingDeleteSetByControl ← FALSE; Editor.DoTargetSelection[]; [] ← Editor.MakeCharIndexVisible[pfBegin, intC.cmTextNbr]; END; -- of WarningCarat -- StartTalker[]; InstallTalker[]; WHILE running DO Process.Yield[]; ENDLOOP; END. -- of BruceTalker --