-- 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, 25-Apr-85 13:05:08
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;
--reconvert message window contents in case edits were made
BruceDefs.AsciiToBinary[intC.cmTextNbr.message, bruceRecipe
! MachineParseDefs.ParseFault => BEGIN
ReportParseFault[why, pfBegin, pfEnd];
GOTO oops;
END];
--update default recipe
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 --