-- LaurelTTYEditor.mesa -- Edited by Brotz, June 25, 1982 5:26 PM -- Edited by Taft, May 8, 1983 2:11 PM DIRECTORY Answer, Ascii, Editor, exD: FROM "ExceptionDefs", inD: FROM "InteractorDefs", Inline, intCommon, LaurelTTYDefs, opD: FROM "OperationsDefs", Storage, String, vmD: FROM "VirtualMgrDefs"; LaurelTTYEditor: PROGRAM IMPORTS Answer, Editor, exD, inD, Inline, intC: intCommon, opD, Storage, String, vmD EXPORTS LaurelTTYDefs = BEGIN commandBuffer: vmD.ComposedMessagePtr _ NIL; buffer: PUBLIC vmD.ComposedMessagePtr _ NIL; pointer: vmD.CharIndex _ 0; qBuffer: ARRAY [0 .. 9] OF vmD.ComposedMessagePtr _ [NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL]; qRegister: ARRAY [0 .. 9] OF LONG INTEGER _ ALL[0]; edited: BOOLEAN _ FALSE; filename: STRING _ [64]; TTYEditor: PUBLIC PROCEDURE [h: LaurelTTYDefs.Handle] = BEGIN OPEN h; char: CHARACTER; IF buffer = NIL THEN ZeroBuffer[@buffer]; DO WriteLine[""L]; WriteChar['*]; SendNow[]; ZeroBuffer[@commandBuffer]; DO length: vmD.CharIndex _ vmD.GetMessageSize[commandBuffer]; char _ ReadChar[]; SELECT char FROM Ascii.ControlA, Ascii.BS => BEGIN IF length > 0 THEN BEGIN WriteChar['/]; WriteChar[vmD.GetMessageChar[commandBuffer, length - 1]]; SendNow[]; vmD.UnAppendMessageChar[commandBuffer]; END ELSE BEGIN vmD.AppendMessageChar[commandBuffer, Ascii.BS]; WriteLine[""L]; [] _ ExecuteCommandString[h, commandBuffer]; EXIT; END; END; Ascii.ControlQ => {WriteString[" XXX"L]; EXIT}; Ascii.ControlR => BEGIN WriteLine[""L]; FOR i: vmD.TOCIndex IN [0 .. vmD.GetMessageSize[commandBuffer]) DO WriteChar[vmD.GetMessageChar[commandBuffer, i]]; ENDLOOP; SendNow[]; END; Ascii.ESC => BEGIN WriteLine["$"L]; IF ExecuteCommandString[h, commandBuffer] THEN RETURN ELSE EXIT; END; ENDCASE => BEGIN vmD.AppendMessageChar[commandBuffer, char]; IF length = 0 AND char = Ascii.LF THEN {WriteLine[""L]; [] _ ExecuteCommandString[h, commandBuffer]; EXIT}; WriteChar[char]; SendNow[]; END; ENDLOOP; ENDLOOP; END; -- of TTYEditor -- ExecuteCommandString: PROCEDURE [h: LaurelTTYDefs.Handle, cm: vmD.ComposedMessagePtr] RETURNS [return: BOOLEAN] = BEGIN OPEN h; arg1, arg2: LONG INTEGER _ 0; haveArg1, haveArg2: BOOLEAN _ FALSE; Term: PROCEDURE RETURNS [n: LONG INTEGER, found: BOOLEAN] = BEGIN unaryMinus: BOOLEAN _ FALSE; found _ FALSE; n _ 0; UNTIL index >= vmD.GetMessageSize[cm] DO char: CHARACTER _ vmD.GetMessageChar[cm, index]; SELECT char FROM IN ['0 .. '9] => BEGIN found _ TRUE; n _ n * 10 + (char - '0); index _ index + 1; END; '- => BEGIN IF found THEN EXIT; IF unaryMinus THEN ERROR SyntaxError; index _ index + 1; unaryMinus _ TRUE; END; 'B, 'b => BEGIN IF found OR unaryMinus THEN ERROR SyntaxError; found _ TRUE; index _ index + 1; n _ 0; END; 'Q, 'q => BEGIN IF found THEN ERROR SyntaxError; index _ index + 1; IF index >= vmD.GetMessageSize[cm] THEN ERROR SyntaxError; char _ vmD.GetMessageChar[cm, index]; IF char ~IN ['0 .. '9] THEN {WriteLine["Q-registers 0 - 9 only"L]; ERROR ErrorNoted}; index _ index + 1; n _ qRegister[char - '0]; found _ TRUE; END; '% => BEGIN IF found THEN ERROR SyntaxError; index _ index + 1; IF index >= vmD.GetMessageSize[cm] THEN ERROR SyntaxError; char _ vmD.GetMessageChar[cm, index]; IF char ~IN ['0 .. '9] THEN {WriteLine["Q-registers 0 - 9 only"L]; ERROR ErrorNoted}; index _ index + 1; n _ qRegister[char - '0] _ qRegister[char - '0] + 1; found _ TRUE; END; 'Z, 'z => BEGIN IF found OR unaryMinus THEN ERROR SyntaxError; found _ TRUE; index _ index + 1; n _ vmD.GetMessageSize[buffer]; END; '. => BEGIN IF found THEN ERROR SyntaxError; found _ TRUE; index _ index + 1; n _ pointer; END; '\ => BEGIN IF found THEN EXIT; found _ TRUE; index _ index + 1; UNTIL pointer >= vmD.GetMessageSize[buffer] DO char _ vmD.GetMessageChar[buffer, pointer]; IF char ~IN ['0 .. '9] THEN EXIT; n _ n * 10 + (char - '0); pointer _ pointer + 1; ENDLOOP; EXIT; END; ': => BEGIN IF found OR unaryMinus THEN ERROR SyntaxError; index _ index + 1; IF index >= vmD.GetMessageSize[cm] THEN ERROR SyntaxError; char _ vmD.GetMessageChar[cm, index]; index _ index + 1; arg1 _ 1; haveArg1 _ TRUE; SELECT char FROM 'S, 's => {found _ TRUE; n _ IF SearchOperation[FALSE] THEN -1 ELSE 0}; 'R, 'r => {found _ TRUE; n _ IF SearchOperation[TRUE] THEN -1 ELSE 0}; ENDCASE => ERROR SyntaxError; END; 'S, 's => IF iterationLevel > 0 THEN BEGIN IF found OR unaryMinus THEN ERROR SyntaxError; index _ index + 1; arg1 _ 1; haveArg1 _ TRUE; found _ TRUE; n _ IF SearchOperation[FALSE] THEN -1 ELSE 0; END ELSE EXIT; 'R, 'r => IF iterationLevel > 0 THEN BEGIN IF found OR unaryMinus THEN ERROR SyntaxError; index _ index + 1; arg1 _ 1; haveArg1 _ TRUE; found _ TRUE; n _ IF SearchOperation[TRUE] THEN -1 ELSE 0; END ELSE EXIT; '( => BEGIN index _ index + 1; [n, found] _ Expression[]; IF index >= vmD.GetMessageSize[cm] OR vmD.GetMessageChar[cm, index] # ') THEN ERROR SyntaxError; index _ index + 1; END; ENDCASE => EXIT; ENDLOOP; IF unaryMinus THEN BEGIN n _ (IF found THEN -n ELSE -1); found _ TRUE; END; END; -- of Term -- Expression: PROCEDURE RETURNS [n: LONG INTEGER, found: BOOLEAN] = BEGIN termFound: BOOLEAN; termN: LONG INTEGER; [n, found] _ Term[]; UNTIL index >= vmD.GetMessageSize[buffer] DO char: CHARACTER _ vmD.GetMessageChar[cm, index]; SELECT char FROM '+ => BEGIN index _ index + 1; [termN, termFound] _ Term[]; IF ~termFound THEN ERROR SyntaxError ELSE n _ n + termN; END; '- => BEGIN index _ index + 1; [termN, termFound] _ Term[]; IF ~termFound THEN ERROR SyntaxError ELSE n _ n - termN; END; '* => BEGIN index _ index + 1; [termN, termFound] _ Term[]; IF ~termFound THEN ERROR SyntaxError ELSE n _ n * termN; END; '/ => BEGIN index _ index + 1; [termN, termFound] _ Term[]; IF ~termFound THEN ERROR SyntaxError ELSE IF termN # 0 THEN n _ n / termN ELSE {WriteLine["Divide by 0!"L]; ERROR ErrorNoted}; END; ENDCASE => EXIT; ENDLOOP; END; -- of Expression -- ACommand: PROCEDURE = BEGIN -- Answer message n answerError: BOOLEAN _ FALSE; toc: vmD.TOCHandle = intC.tocTextNbr.toc; dm: vmD.DisplayMessagePtr; key: CARDINAL; index: vmD.TOCIndex; GetChar: PROCEDURE [index: CARDINAL] RETURNS [CHARACTER] = {RETURN[vmD.GetMessageChar[dm, index]]}; PutBlock: PROCEDURE [block: Answer.Block] = BEGIN [] _ vmD.InsertSubstringInMessage [buffer, LOOPHOLE[Inline.LowHalf[block.buffer] - 2, STRING], 0, block.length]; END; -- of PutBlock -- GetPages: PROCEDURE [nPages: CARDINAL] RETURNS [LONG POINTER] = {RETURN[Storage.Pages[nPages]]}; FreePages: PROCEDURE [p: LONG POINTER] = {Storage.FreePages[Inline.LowHalf[p]]}; answerBody: STRING ="Message "L; -- main body of ACommand IF ~haveArg1 THEN ERROR SyntaxError; IF edited THEN BEGIN WriteString["Message has been edited but not saved! "L]; IF ~inD.Confirm[1] THEN RETURN END; index _ Inline.LowHalf[arg1]; key _ vmD.WaitForLock[toc]; IF index ~IN [1 .. toc.indexFF) THEN {vmD.UnlockTOC[toc, key]; WriteString["Illegal message number."L]; ERROR ErrorNoted}; dm _ vmD.AllocateDisplayMessageObject[]; vmD.LoadDisplayMessage[toc, key, index, dm]; vmD.DeleteRangeInMessage[[0, vmD.GetMessageSize[buffer], buffer]]; vmD.StartMessageInsertion[buffer, 0]; answerError _ Answer.MakeHeader [getChar: GetChar, getLength: vmD.GetMessageSize[dm], putBlock: PutBlock, getPages: GetPages, freePages: FreePages, userName: intC.user.name, userRegistry: intC.user.registry, cForCopies: intC.cForCopies]; vmD.FlushDisplayMessage[dm, key]; vmD.UnlockTOC[toc, key]; vmD.FreeVirtualMessageObject[dm]; [] _ vmD.InsertStringInMessage[buffer, answerBody]; vmD.StopMessageInsertion[buffer]; pointer _ 0; edited _ FALSE; END; -- of ACommand -- CCommand: PROCEDURE = BEGIN IF ~haveArg1 THEN arg1 _ 1; IF arg1 > 0 AND arg1 + pointer > vmD.GetMessageSize[buffer] OR arg1 < 0 AND arg1 + pointer < 0 THEN {WriteString["Off the edge!"L]; ERROR ErrorNoted}; pointer _ Inline.LowHalf[arg1 + pointer]; END; -- of CCommand -- DCommand: PROCEDURE = BEGIN IF ~haveArg1 THEN arg1 _ 1; IF arg1 > 0 THEN BEGIN IF arg1 + pointer > vmD.GetMessageSize[buffer] THEN {WriteString["Off the edge!"L]; ERROR ErrorNoted}; vmD.DeleteRangeInMessage[[pointer, Inline.LowHalf[arg1 + pointer], buffer]]; END ELSE BEGIN IF arg1 + pointer < 0 THEN {WriteString["Off the edge!"L]; ERROR ErrorNoted}; vmD.DeleteRangeInMessage[[Inline.LowHalf[arg1 + pointer], pointer, buffer]]; pointer _ Inline.LowHalf[arg1 + pointer]; END; edited _ TRUE; END; -- of DCommand -- EXCommand: PROCEDURE = BEGIN index _ vmD.GetMessageSize[commandBuffer]; IF edited THEN BEGIN WriteString["The text has been edited, but hasn't been saved. Still want to exit? "L]; IF NextCharConfirms[] THEN WriteString["Yes. "L] ELSE {WriteLine["XXX"L]; RETURN}; END; WriteLine["Exiting editor."L]; ERROR Exit; END; -- of EXCommand -- GCommand: PROCEDURE = BEGIN char: CHARACTER; IF index >= vmD.GetMessageSize[cm] THEN ERROR SyntaxError; char _ vmD.GetMessageChar[cm, index]; IF char ~IN ['0 .. '9] THEN {WriteLine["Q-registers 0 - 9 only"L]; ERROR ErrorNoted}; index _ index + 1; vmD.InsertRangeInMessage [pointer, buffer, [0, vmD.GetMessageSize[qBuffer[char - '0]], qBuffer[char - '0]]]; pointer _ pointer + vmD.GetMessageSize[qBuffer[char - '0]]; END; -- of GCommand -- ICommand: PROCEDURE = BEGIN char: CHARACTER; vmD.StartMessageInsertion[buffer, pointer]; IF haveArg1 THEN BEGIN char _ Inline.LowHalf[arg1]; vmD.InsertMessageChar[buffer, char]; pointer _ pointer + 1; END ELSE UNTIL index >= vmD.GetMessageSize[cm] DO char _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char = Ascii.ControlD THEN EXIT; vmD.InsertMessageChar[buffer, char]; pointer _ pointer + 1; ENDLOOP; vmD.StopMessageInsertion[buffer]; edited _ TRUE; END; -- of ICommand -- JCommand: PROCEDURE = BEGIN SELECT TRUE FROM ~haveArg1 => pointer _ 0; haveArg2 => ERROR SyntaxError; arg1 IN [0 .. vmD.GetMessageSize[buffer]] => pointer _ Inline.LowHalf[arg1]; ENDCASE => {WriteLine["Off the edge!"L]; ERROR ErrorNoted}; END; -- of JCommand -- KCommand: PROCEDURE = BEGIN IF ~haveArg1 THEN arg1 _ 1; IF haveArg2 THEN BEGIN arg1 _ MIN[MAX[arg1, 0], vmD.GetMessageSize[buffer]]; arg2 _ MIN[ABS[arg2], vmD.GetMessageSize[buffer]]; IF arg2 >= arg1 THEN BEGIN pointer _ Inline.LowHalf[arg1]; vmD.DeleteRangeInMessage[[pointer, Inline.LowHalf[arg2], buffer]]; END; SendNow[]; END ELSE BEGIN lines: CARDINAL _ 0; arg1 _ ABS[arg1]; FOR i: vmD.CharIndex IN [pointer .. vmD.GetMessageSize[buffer]) DO IF vmD.GetMessageChar[buffer, i] = Ascii.CR THEN lines _ lines + 1; IF lines = arg1 THEN {vmD.DeleteRangeInMessage[[pointer, i + 1, buffer]]; EXIT}; REPEAT FINISHED => vmD.DeleteRangeInMessage[[pointer, vmD.GetMessageSize[buffer], buffer]]; ENDLOOP END; edited _ TRUE; END; -- of KCommand -- LCommand: PROCEDURE = BEGIN start, end: vmD.CharIndex; IF ~haveArg1 THEN arg1 _ 1; [start, end] _ MapLinesToRange[Inline.LowHalf[arg1]]; pointer _ IF arg1 > 0 THEN end ELSE start; END; -- of LCommand -- MCommand: PROCEDURE = BEGIN char: CHARACTER; IF index >= vmD.GetMessageSize[cm] THEN ERROR SyntaxError; char _ vmD.GetMessageChar[cm, index]; IF char ~IN ['0 .. '9] THEN {WriteLine["Q-buffers 0 - 9 only"L]; ERROR ErrorNoted}; index _ index + 1; IF qBuffer[char - '0] = NIL THEN {WriteLine["Q-buffer is empty!"L]; ERROR ErrorNoted}; [] _ ExecuteCommandString[h, qBuffer[char - '0]]; END; -- of MCommand -- NCommand: PROCEDURE = BEGIN -- New form command -- string: STRING _ "Subject: xxx To: xxx xxx "L; IF edited THEN BEGIN WriteString["Message has been edited but not saved! "L]; IF ~inD.Confirm[1] THEN RETURN END; vmD.DeleteRangeInMessage[[0, vmD.GetMessageSize[buffer], buffer]]; vmD.StartMessageInsertion[buffer, 0]; [] _ vmD.InsertStringInMessage[buffer, string]; vmD.StopMessageInsertion[buffer]; pointer _ 0; edited _ FALSE; END; -- of NCommand -- RCommand: PROCEDURE = BEGIN IF ~SearchOperation[TRUE] THEN WriteLine["Search failed!"L]; END; -- of RCommand -- SearchOperation: PROCEDURE [replace: BOOLEAN] RETURNS [succeed: BOOLEAN] = BEGIN searchPattern: STRING _ [inD.maxBracketStringLength]; char: CHARACTER; start: vmD.CharIndex _ pointer; at, atEnd, end, insertStartIndex: vmD.CharIndex; found: BOOLEAN; IF ~haveArg1 THEN arg1 _ 1; UNTIL index >= vmD.GetMessageSize[cm] DO char _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char = Ascii.ControlD THEN EXIT; IF searchPattern.length >= searchPattern.maxlength THEN {WriteLine["Search string too big!"L]; ERROR ErrorNoted}; searchPattern[searchPattern.length] _ char; searchPattern.length _ searchPattern.length + 1; ENDLOOP; insertStartIndex _ index; IF arg1 = 0 THEN {succeed _ TRUE; GO TO Return}; IF arg1 > 0 THEN BEGIN THROUGH [1 .. Inline.LowHalf[arg1]] DO [found, at, atEnd] _ Editor.FindOperation[searchPattern, start, vmD.GetMessageSize[buffer], buffer]; IF ~found THEN {succeed _ FALSE; GO TO Return}; IF replace THEN BEGIN vmD.DeleteRangeInMessage[[at, atEnd, buffer]]; vmD.StartMessageInsertion[buffer, at]; UNTIL index >= vmD.GetMessageSize[cm] DO char _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char = Ascii.ControlD THEN EXIT; vmD.InsertMessageChar[buffer, char]; at _ at + 1; ENDLOOP; vmD.StopMessageInsertion[buffer]; index _ insertStartIndex; start _ pointer _ at; END ELSE start _ at + 1; REPEAT FINISHED => {IF ~replace THEN pointer _ atEnd; succeed _ TRUE; GO TO Return}; ENDLOOP; END ELSE BEGIN arg1 _ ABS[arg1]; end _ pointer; THROUGH [1 .. Inline.LowHalf[arg1]] DO start _ end; DO [found, at, atEnd] _ Editor.FindOperation[searchPattern, start, end, buffer]; IF found THEN BEGIN IF atEnd > 0 THEN end _ atEnd - 1 ELSE end _ 0; EXIT; END; IF start = 0 THEN {succeed _ FALSE; GO TO Return}; start _ start - 1; ENDLOOP; IF replace THEN BEGIN vmD.DeleteRangeInMessage[[at, atEnd, buffer]]; atEnd _ at; vmD.StartMessageInsertion[buffer, at]; UNTIL index >= vmD.GetMessageSize[cm] DO char _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char = Ascii.ControlD THEN EXIT; vmD.InsertMessageChar[buffer, char]; atEnd _ atEnd + 1; ENDLOOP; vmD.StopMessageInsertion[buffer]; pointer _ end _ atEnd; index _ insertStartIndex; END; REPEAT FINISHED => {pointer _ atEnd; succeed _ TRUE; GO TO Return}; ENDLOOP; END; EXITS Return => IF replace THEN UNTIL index >= vmD.GetMessageSize[cm] DO char: CHARACTER _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char = Ascii.ControlD THEN EXIT; ENDLOOP; END; -- of SearchOperation -- SCommand: PROCEDURE = BEGIN IF ~SearchOperation[FALSE] THEN WriteLine["Search failed!"L]; END; -- of SCommand -- TCommand: PROCEDURE = BEGIN start, end: vmD.CharIndex; IF ~haveArg1 THEN arg1 _ 1; IF haveArg2 THEN BEGIN start _ Inline.LowHalf[MAX[arg1, 0]]; end _ MIN[Inline.LowHalf[ABS[arg2]], vmD.GetMessageSize[buffer]]; END ELSE [start, end] _ MapLinesToRange[Inline.LowHalf[arg1]]; FOR i: vmD.CharIndex IN [start .. end) DO WriteChar[vmD.GetMessageChar[buffer, i]]; ENDLOOP; SendNow[]; END; -- of TCommand -- UCommand: PROCEDURE = BEGIN char: CHARACTER; IF ~haveArg1 THEN {WriteLine["Missing argument for U."L]; ERROR ErrorNoted}; IF index >= vmD.GetMessageSize[cm] THEN ERROR SyntaxError; char _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char ~IN ['0 .. '9] THEN {WriteLine["Q-registers 0 - 9 only"L]; ERROR ErrorNoted}; qRegister[char - '0] _ arg1; END; -- of UCommand -- VCommand: PROCEDURE = BEGIN start, end: vmD.CharIndex; IF ~haveArg1 THEN arg1 _ 1; arg1 _ MAX[ABS[arg1], 1]; IF ~haveArg2 THEN arg2 _ arg1; arg2 _ ABS[arg2]; [start, ] _ MapLinesToRange[Inline.LowHalf[1 - arg1]]; [ , end] _ MapLinesToRange[Inline.LowHalf[arg2]]; FOR i: vmD.CharIndex IN [start .. end) DO WriteChar[vmD.GetMessageChar[buffer, i]]; ENDLOOP; END; -- of VCommand -- XCommand: PROCEDURE = BEGIN char: CHARACTER; start, end: vmD.CharIndex; IF index >= vmD.GetMessageSize[cm] THEN ERROR SyntaxError; char _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char ~IN ['0 .. '9] THEN {WriteLine["Q-registers 0 - 9 only"L]; ERROR ErrorNoted}; IF haveArg2 THEN BEGIN -- m,nX command -- start _ Inline.LowHalf[arg1]; end _ Inline.LowHalf[arg2]; IF start > end THEN {WriteLine["Backward substring!"L]; ERROR ErrorNoted}; IF start > vmD.GetMessageSize[buffer] OR end > vmD.GetMessageSize[buffer] THEN {WriteLine["Off the edge!"L]; ERROR ErrorNoted}; END ELSE BEGIN IF ~haveArg1 THEN arg1 _ 1; [start, end] _ MapLinesToRange[Inline.LowHalf[arg1]]; END; ZeroBuffer[@qBuffer[char - '0]]; vmD.InsertRangeInMessage[0, qBuffer[char - '0], [start, end, buffer]]; vmD.DeleteRangeInMessage[[start, end, buffer]]; pointer _ start; END; -- of XCommand -- MapLinesToRange: PROCEDURE [n: INTEGER] RETURNS [start, end: vmD.CharIndex] = BEGIN lines: INTEGER _ 0; IF n <= 0 THEN BEGIN end _ pointer; n _ ABS[n]; FOR i: vmD.CharIndex DECREASING IN [0 .. pointer) DO IF vmD.GetMessageChar[buffer, i] = Ascii.CR THEN BEGIN IF lines >= n THEN {start _ i + 1; EXIT}; lines _ lines + 1; END; REPEAT FINISHED => start _ 0; ENDLOOP; END ELSE BEGIN start _ pointer; FOR i: vmD.CharIndex IN [pointer .. vmD.GetMessageSize[buffer]) DO IF vmD.GetMessageChar[buffer, i] = Ascii.CR THEN BEGIN lines _ lines + 1; IF lines >= n THEN {end _ i + 1; EXIT}; END; REPEAT FINISHED => end _ vmD.GetMessageSize[buffer]; ENDLOOP END; END; -- of MapLinesToRange -- LineFeedCommand: PROCEDURE = BEGIN haveArg1 _ TRUE; arg1 _ 1; LCommand[]; TCommand[]; END; -- of LineFeedCommand -- BackSpaceCommand: PROCEDURE = BEGIN haveArg1 _ TRUE; arg1 _ -1; LCommand[]; TCommand[]; END; -- of BackSpaceCommand -- BackSlashCommand: PROCEDURE = BEGIN string: STRING _ [11]; -- -6553665536 -- IF ~haveArg1 THEN ERROR SyntaxError; String.AppendLongDecimal[string, arg1]; vmD.StartMessageInsertion[buffer, pointer]; vmD.InsertStringInMessage[buffer, string]; vmD.StopMessageInsertion[buffer]; pointer _ pointer + string.length; END; -- of BackSlashCommand -- SemiGCommand: PROCEDURE = BEGIN -- Get message n into buffer -- index: vmD.TOCIndex; dm: vmD.DisplayMessagePtr; toc: vmD.TOCHandle _ intC.tocTextNbr.toc; key: CARDINAL; IF ~haveArg1 THEN ERROR SyntaxError; index _ Inline.LowHalf[arg1]; key _ vmD.WaitForLock[toc]; IF index ~IN [1 .. toc.indexFF) THEN {vmD.UnlockTOC[toc, key]; WriteString["Illegal message number."L]; ERROR ErrorNoted}; dm _ vmD.AllocateDisplayMessageObject[]; vmD.LoadDisplayMessage[toc, key, index, dm]; vmD.InsertRangeInMessage[pointer, buffer, [0, vmD.GetMessageSize[dm], dm]]; pointer _ pointer + vmD.GetMessageSize[dm]; vmD.FlushDisplayMessage[dm, key]; vmD.UnlockTOC[toc, key]; vmD.FreeVirtualMessageObject[dm]; END; -- of SemiGCommand -- SemiTCommand: PROCEDURE = BEGIN UNTIL index >= vmD.GetMessageSize[cm] DO char: CHARACTER _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char = Ascii.ControlD THEN EXIT; WriteChar[char]; ENDLOOP; END; -- of SemiTCommand -- SemiYCommand: PROCEDURE = BEGIN WriteString["Input file: "L]; [] _ ReadString[filename]; WriteLine[""L]; vmD.InsertFileInMessage[targetIndex: pointer, targetMessage: buffer, file: filename ! opD.FileError => BEGIN WriteLine[IF reason = notFound THEN "File not found"L ELSE "File error."L]; GO TO Return; END; vmD.MessageOverflow => {WriteLine["Can't yank: message would get too big."L]; GO TO Return}]; WriteLine["OK"L]; edited _ TRUE; EXITS Return => NULL; END; -- of SemiYCommand -- SemiUCommand: PROCEDURE = BEGIN WriteString["Output file: "L]; [] _ ReadString[filename]; WriteLine[""L]; vmD.PutRangeInFile[from: vmD.MessageRange[0, vmD.GetMessageSize[buffer], buffer], file: filename, concurrenceNeeded: TRUE, UserConcurs: UserConcurs ! opD.FileError => {WriteLine[IF reason = cancel THEN "Cancelled."L ELSE "File error"L]; GO TO done}]; WriteLine["OK"L]; edited _ FALSE; EXITS done => NULL; END; -- of SemiUCommand -- StartIterationCommand: PROCEDURE = BEGIN IF iterationLevel = maxIterationLevel THEN {WriteLine["Iteration level too deep!"L]; ERROR ErrorNoted}; iterationLevel _ iterationLevel + 1; IF haveArg1 THEN BEGIN IF arg1 <= 0 THEN {WriteLine["Non-positive iteration constant!"L]; ERROR ErrorNoted}; iterationStack[iterationLevel].times _ Inline.LowHalf[arg1] - 1; END ELSE iterationStack[iterationLevel].times _ LAST[CARDINAL]; iterationStack[iterationLevel].index _ index; END; -- of StartIterationCommand -- StopIterationCommand: PROCEDURE = BEGIN IF iterationLevel = 0 THEN ERROR SyntaxError; IF iterationStack[iterationLevel].times = 0 THEN {iterationLevel _ iterationLevel - 1; RETURN}; IF iterationStack[iterationLevel].times # LAST[CARDINAL] THEN iterationStack[iterationLevel].times _ iterationStack[iterationLevel].times - 1; index _ iterationStack[iterationLevel].index; END; -- of StopIterationCommand -- IterationSkipCommand: PROCEDURE = BEGIN IF ~haveArg1 OR iterationLevel = 0 THEN ERROR SyntaxError; IF arg1 >= 0 THEN BEGIN iterationLevel _ iterationLevel - 1; UNTIL index >= vmD.GetMessageSize[cm] DO char: CHARACTER _ vmD.GetMessageChar[cm, index]; index _ index + 1; IF char = '> THEN EXIT; REPEAT FINISHED => ERROR SyntaxError; ENDLOOP; END; END; -- of IterationSkipCommand -- UserConcurs: PROCEDURE [exception: exD.Exception] RETURNS [confirmed: BOOLEAN] = BEGIN string: STRING _ [100]; exD.GetExceptionString[exception, string]; WriteString[string]; WriteString[" [Confirm]"L]; RETURN[NextCharConfirms[]] END; -- of UserConcurs -- NextCharConfirms: PROCEDURE RETURNS [BOOLEAN] = BEGIN SELECT ReadChar[] FROM Ascii.CR, Ascii.SP, Ascii.TAB, Ascii.ESC, 'y, 'Y => RETURN[TRUE]; ENDCASE; RETURN[FALSE]; END; -- of NextCharConfirms -- ScanAndExecuteCommand: PROCEDURE = BEGIN char: CHARACTER; haveArg2 _ FALSE; [arg1, haveArg1] _ Expression[]; IF index >= vmD.GetMessageSize[cm] THEN RETURN; char _ vmD.GetMessageChar[cm, index]; SELECT char FROM 'H, 'h => BEGIN IF haveArg1 THEN ERROR SyntaxError; arg1 _ 0; arg2 _ vmD.GetMessageSize[buffer]; haveArg1 _ haveArg2 _ TRUE; index _ index + 1; END; ', => BEGIN IF ~haveArg1 THEN ERROR SyntaxError; index _ index + 1; [arg2, haveArg2] _ Expression[]; IF ~haveArg2 THEN ERROR SyntaxError; END; ENDCASE; char _ vmD.GetMessageChar[cm, index]; index _ index + 1; SELECT char FROM '; => BEGIN IF index >= vmD.GetMessageSize[cm] THEN ERROR UnrecognizedCommand; char _ vmD.GetMessageChar[cm, index]; index _ index + 1; SELECT char FROM 'G, 'g => SemiGCommand[]; 'T, 't => SemiTCommand[]; 'U, 'u => SemiUCommand[]; 'Y, 'y => SemiYCommand[]; Ascii.SP => IterationSkipCommand[]; ENDCASE => ERROR UnrecognizedCommand; END; 'A, 'a => ACommand[]; 'C, 'c => CCommand[]; 'D, 'd => DCommand[]; 'E, 'e => BEGIN IF index >= vmD.GetMessageSize[cm] THEN ERROR UnrecognizedCommand; char _ vmD.GetMessageChar[cm, index]; index _ index + 1; SELECT char FROM 'X, 'x => EXCommand[]; ENDCASE => ERROR UnrecognizedCommand; END; 'G, 'g => GCommand[]; 'I, 'i => ICommand[]; 'J, 'j => JCommand[]; 'K, 'k => KCommand[]; 'L, 'l => LCommand[]; 'M, 'm => MCommand[]; 'N, 'n => NCommand[]; 'R, 'r => RCommand[]; 'S, 's => SCommand[]; 'T, 't => TCommand[]; 'U, 'u => UCommand[]; 'V, 'v => VCommand[]; 'X, 'x => XCommand[]; Ascii.LF => LineFeedCommand[]; Ascii.BS => BackSpaceCommand[]; Ascii.ControlD => NULL; '\ => BackSlashCommand[]; '< => StartIterationCommand[]; '> => StopIterationCommand[]; '= => BEGIN IF ~haveArg1 OR haveArg2 THEN ERROR SyntaxError; WriteLongDecimal[arg1]; WriteLine[""L]; SendNow[]; END; '? => BEGIN WriteLine["Commands are:"L]; WriteLine["? (help message), A(nswer message), nC(haracters advance pointer),"L]; WriteLine["nD(elete n characters),"L]; WriteLine["^D(o nothing), EX(it editor), Gq(Get q buffer - insert q at pointer),"L]; WriteLine["I(nsert ^D), nI(insert Ascii char n), nJ(ump pointer),"L]; WriteLine["nK(ill n lines), n,mK(ill characters n up to m),"L]; WriteLine["nL(ines-move pointer to start of current+nth line),"L]; WriteLine["Mq(Macro from q buffer), N(ew form),"L]; WriteLine["nR(eplace ^D by ^D n times),"L]; WriteLine["nS(earch for ^D n times), nT(ype n lines), nUq(Set q to n),"L]; WriteLine["m,nV(iew lines), m,nT(ype characters m up to n),"L]; WriteLine["nXq(Extract n lines to q buffer), m,nXq(Extract chars m,n to q buffer),"L]; WriteLine["n;G(et message n into buffer) ;T(ype ^D), ;U(nget file-Save file),"L]; WriteLine[";Y(ank file-Get file)."L]; WriteLine["LF(Line Feed-type next line), BS(Back Space, ^H-type previous line),"L]; WriteLine["=(type value of argument), \(Pick up next number),"L]; WriteLine["n\(Insert string for n), <(Start interation), >(Stop iteration)."L]; SendNow[]; END; ENDCASE => ERROR UnrecognizedCommand; END; -- of ScanAndExecuteCommand -- SyntaxError: ERROR = CODE; Exit: ERROR = CODE; UnrecognizedCommand: ERROR = CODE; ErrorNoted: ERROR = CODE; index: vmD.CharIndex _ 0; IterationRecord: TYPE = RECORD [times: CARDINAL, index: vmD.CharIndex]; iterationStack: ARRAY [1 .. maxIterationLevel] OF IterationRecord; iterationLevel: CARDINAL _ 0; maxIterationLevel: CARDINAL = 10; UNTIL index >= vmD.GetMessageSize[cm] DO ScanAndExecuteCommand [ ! SyntaxError => GO TO syntaxError; Exit => GO TO exitExit; UnrecognizedCommand => GO TO unrecognizedCommand; ErrorNoted => GO TO done]; REPEAT unrecognizedCommand => {WriteString["Unrecognized command at "L]; WriteDecimal[index]; RETURN[FALSE]}; exitExit => RETURN[TRUE]; syntaxError => {WriteString["Syntax error at "L]; WriteDecimal[index]; RETURN[FALSE]}; done => RETURN[FALSE]; ENDLOOP; IF iterationLevel > 0 THEN WriteLine["Missing right iteration bracket!"L]; RETURN[FALSE]; END; -- of ExecuteCommandString -- ZeroBuffer: PUBLIC PROCEDURE [cm: POINTER TO vmD.ComposedMessagePtr] = BEGIN IF cm^ = NIL THEN cm^ _ vmD.AllocateComposedMessageObject[]; vmD.InitComposedMessage[cm^, ""L]; END; -- of ZeroBuffer -- CleanupTTYEditor: PUBLIC PROCEDURE = BEGIN IF commandBuffer # NIL THEN {vmD.FreeVirtualMessageObject[commandBuffer]; commandBuffer _ NIL}; IF buffer # NIL THEN {vmD.FreeVirtualMessageObject[buffer]; buffer _ NIL}; FOR i: CARDINAL IN [0 .. 9] DO IF qBuffer[i] # NIL THEN {vmD.FreeVirtualMessageObject[qBuffer[i]]; qBuffer[i] _ NIL}; ENDLOOP; END; -- of CleanupTTYEditor -- END. -- of LaurelTTYEditor --(635)\f1