-- file: EditorFiles.Mesa
-- edited by Schroeder, January 13, 1981 11:37 AM
-- edited by Brotz, April 27, 1981 4:37 PM
-- edited by Levin, February 22, 1980 12:42 PM

DIRECTORY
Ascii,
dsD: FROM "DisplayDefs",
Editor,
exD: FROM "ExceptionDefs",
inD: FROM "InteractorDefs",
intCommon: FROM "IntCommon",
lmD: FROM "LaurelMenuDefs",
opD: FROM "OperationsDefs",
ovD: FROM "OverviewDefs",
Storage,
String,
vmD: FROM "VirtualMgrDefs";

EditorFiles: PROGRAM
IMPORTS dsD, Editor, exD, inD, intC: intCommon, lmD, opD, Storage, String, vmD
EXPORTS Editor, inD, lmD =

BEGIN

OPEN Editor, inD;


GCommand: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr] =
-- Replaces the current primary selection with the contents of the file named in
-- the get/put brackets.
BEGIN
ChangeEditorMenu[getPut];
IndicateCommandBusy[intC.currentCommand ← intC.getCommandHouse];
exD.DisplayExceptionLine[exD.confirmFileName, 1];
IF ConfirmBrackets[hp: intC.getPutBracketsHouse, fileExtension: ".form."L] THEN
Getter[intC.target.start, intC.target.end, mnp];
IndicateCommandFinished[intC.getCommandHouse];
intC.currentCommand ← NIL;
END; -- of GCommand --


GetCommand: PUBLIC CommandProcedure =
-- Replaces the current composed message with the contents of the file named in
-- the brackets.
BEGIN
oldText: STRING ← [maxBracketStringLength];
ChangeEditorMenu[getPut];
String.AppendString[oldText, intC.getPutBracketsHouse.text];
IF ~confirmed
AND ~ConfirmBrackets[hp: intC.getPutBracketsHouse, fileExtension: ".form."L]
THEN RETURN;
IF intC.composedMessageEdited AND vmD.GetMessageSize[intC.cmTextNbr.message] # 0
AND ~AskUserToConfirm[exD.willReplaceMessage]
THEN {RestoreGetPutBracketsString[oldText]; RETURN};
Getter[0, vmD.GetMessageSize[intC.cmTextNbr.message], intC.cmTextNbr];
intC.runCommandMode ← FALSE;
END; -- of GetCommand --


Getter: PROCEDURE [start, end: ovD.CharIndex, mnp: MessageTextNbrPtr] =
-- Replaces [start .. end) from mnp.message with contents of file named in the
-- getPutBracketsHouse.
BEGIN
error: ovD.ErrorCode;
errorMsg: STRING;
selectionLength: CARDINAL = end - start;
insertionLength: CARDINAL;
preInsertionMessageLength: CARDINAL;
preGetMessageLength: ovD.CharIndex ← vmD.GetMessageSize[mnp.message];
whereToInsert: vmD.ComposeMessagePtr;
completeGet: BOOLEAN = (start = 0 AND end = preGetMessageLength);
bracketsText: STRING ← intC.getPutBracketsHouse.text;
isForm: BOOLEAN ← FALSE;
dotForm: STRING ← ".form"L;
trailerSSD: String.SubStringDescriptor
← String.SubStringDescriptor[base: bracketsText, offset: bracketsText.length - 5, length: 5];
dotFormSSD: String.SubStringDescriptor
← String.SubStringDescriptor[base: dotForm, offset: 0, length: 5];

CancelSourceSelection[mnp];
ResetBuffers[mnp];
IF completeGet THEN whereToInsert ← mnp.deletionBuffer
ELSE BEGIN
InsertRangeInMess[targetIndex: 0, targetMessage: mnp.deletionBuffer,
from: vmD.MessageRange[start, end, mnp.message]];
vmD.DeleteRangeInMessage[from: vmD.MessageRange[start, end, mnp.message]];
whereToInsert ← vmD.MapVirtualToComposeMessage[mnp.message];
END;
preInsertionMessageLength ← vmD.GetMessageSize[whereToInsert];
IF bracketsText.length > 5 AND String.EquivalentSubString[@trailerSSD, @dotFormSSD]
THEN isForm ← TRUE;

[error, errorMsg] ← vmD.InsertFileInMessage
[targetIndex: start, targetMessage: whereToInsert, file: bracketsText, user: intC.user];
IF error = ovD.fileNotFound THEN
BEGIN -- try adding .form to the filename.
IF bracketsText.length > 0 THEN
FOR i: CARDINAL IN [0 .. bracketsText.length) DO
IF bracketsText[i] = ’. THEN EXIT;
REPEAT
FINISHED =>
BEGIN
fName: STRING ← Storage.String[bracketsText.length + 5];
String.AppendString[fName, bracketsText];
String.AppendString[fName, dotForm];
IF errorMsg # NIL THEN Storage.FreeString[errorMsg];
[error, errorMsg] ← vmD.InsertFileInMessage
[targetIndex: start, targetMessage: whereToInsert, file: fName, user: intC.user];
Storage.FreeString[fName];
isForm ← TRUE;
END;
ENDLOOP;
END;

IF error # ovD.ok THEN
BEGIN -- sorry, subsequent undo not permitted
IF ~completeGet THEN
InsertRangeInMess
[targetIndex: start, targetMessage: LOOPHOLE[mnp.message],
from: vmD.MessageRange[0, end - start, mnp.deletionBuffer]];
ResetDeletionBuffer[mnp];
exD.DisplayExceptionLine[exD.getFailed, 1];
exD.DisplayExceptionOrStringOnLine
[SELECT error FROM
ovD.cMTooBig => exD.messageTooBig,
ENDCASE => exD.nil,
errorMsg, 2];
exD.FlashExceptionsRegion[];
IF errorMsg # NIL THEN Storage.FreeString[errorMsg];
RETURN;
END;

insertionLength ← vmD.GetMessageSize[whereToInsert] - preInsertionMessageLength;
exD.ClearExceptionsRegion[];
exD.AppendDecimalToExceptionLine[insertionLength, 1];
exD.AppendStringToExceptionLine[" characters read."L, 1];
IF completeGet THEN
BEGIN
intC.target ← TextSelection[mnp, 0, 0, 0, char, FALSE];
SwapMessageWithDeletionBuffer[mnp];
intC.commandType ← get;
SetHighWaterMark[0];
RefreshSoThatFirstCharStartsLine[0, mnp.lines, mnp];
IF isForm THEN Editor.SelectNextBlank[mnp, TRUE];
TurnOnDeliver[];
intC.composedMessageEdited ← FALSE;
END
ELSE BEGIN
intC.target ← TextSelection[mnp, start, start + insertionLength, start, char, FALSE];
InsertRangeInMess
[targetIndex: 0, targetMessage: mnp.insertionBuffer,
from: vmD.MessageRange[start, start + insertionLength, mnp.message]];
intC.commandType ← replace;
UpdateScreen[start: start, nCharsDeleted: end - start,
nCharsInserted: insertionLength, mnp: mnp];
END;
intC.newTargetSelection ← TRUE;
intC.actionPoint ← start;
mnp.haveMessage ← TRUE;
END; -- of Getter --


PCommand: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr] =
-- Writes the current primary selection onto the file named in the get/put
-- brackets.
BEGIN
oldText: STRING ← [maxBracketStringLength];
IF intC.disableWriting THEN {UnrecognizedCommand[]; RETURN};
ChangeEditorMenu[getPut];
IndicateCommandBusy[intC.currentCommand ← intC.getCommandHouse.nextHouse];
exD.DisplayExceptionLine[exD.confirmFileName, 1];
String.AppendString[oldText, intC.getPutBracketsHouse.text];
IF ConfirmBrackets[intC.getPutBracketsHouse] THEN
[] ← Putter[intC.target.start, intC.target.end, mnp, oldText];
IndicateCommandFinished[intC.currentCommand];
intC.currentCommand ← NIL;
END; -- of PCommand --


PutCommand: PUBLIC CommandProcedure =
-- Writes the current composed message onto the file named in the get/put
-- brackets.
BEGIN
oldText: STRING ← [maxBracketStringLength];
ChangeEditorMenu[getPut];
String.AppendString[oldText, intC.getPutBracketsHouse.text];
IF (confirmed OR ConfirmBrackets[intC.getPutBracketsHouse])
AND Putter[0, vmD.GetMessageSize[intC.cmTextNbr.message], intC.cmTextNbr, oldText]
THEN intC.composedMessageEdited ← FALSE;
IndicateCommandFinished[hp];
IF CaretIsBlinking[] THEN SetCaretBlinking[intC.target.point, intC.target.mnp];
END; -- of PutCommand --


Putter: PROC [start, end: ovD.CharIndex, mnp: MessageTextNbrPtr, oldText: STRING]
RETURNS [successful: BOOLEAN] =
-- Writes [start .. end) from mnp.message onto file named in the getPutBracketsHouse.
BEGIN
error: ovD.ErrorCode;
savedCursor: dsD.CursorShape;
[savedCursor, , ] ← dsD.GetCursor[];
dsD.ChangeCursor[hourGlass];
error ← vmD.PutRangeInFile[from: vmD.MessageRange[start, end, mnp.message],
file: intC.getPutBracketsHouse.text, user: intC.user,
concurrenceNeeded: TRUE, UserConcurs: AskUserToConfirm];
SELECT error FROM
ovD.ok =>
BEGIN
exD.AppendDecimalToExceptionLine[end - start, 1];
exD.AppendStringToExceptionLine[" characters written."L, 1];
END;
ovD.cancelCode => RestoreGetPutBracketsString[oldText];
ENDCASE;
dsD.ChangeCursor[savedCursor];
RETURN[error = ovD.ok];
END; -- of Putter --


RestoreGetPutBracketsString: PROCEDURE [oldText: STRING] =
BEGIN
intC.getPutBracketsHouse.text.length ← 0;
String.AppendString[intC.getPutBracketsHouse.text, oldText];
BracketsHouseRefresher[intC.getPutBracketsHouse];
END; -- of RestoreGetPutBracketsString --


CopyCommand: PUBLIC CommandProcedure =
-- Copies a remote or local file to a remote or local file using opD.Copy. The composed
-- message is not affected by this command.
BEGIN
error: ovD.ErrorCode;
getOrPut: opD.GetOrPutType;
errorString: STRING;
bytesCopied: LONG CARDINAL;

OverwriteOK: PROCEDURE RETURNS [BOOLEAN] =
{RETURN[AskUserToConfirm[exD.putWillOverwrite]]};

ChangeEditorMenu[copy];
IF ~(confirmed OR ConfirmBrackets[intC.copySourceBracketsHouse])
OR ~ConfirmBrackets[intC.copyTargetBracketsHouse] THEN RETURN;

exD.ClearExceptionsRegion[];
[error, getOrPut, errorString, bytesCopied] ← opD.Copy
[intC.copySourceBracketsHouse.text, intC.copyTargetBracketsHouse.text, OverwriteOK];
IF error # ovD.ok THEN
BEGIN
exD.DisplayExceptionStringOnLine["Copy failed: "L, 1];
exD.AppendStringToExceptionLine
[IF getOrPut = get THEN "can’t get "L ELSE "can’t put "L, 1];
exD.AppendStringToExceptionLine
[IF getOrPut = get THEN intC.copySourceBracketsHouse.text
ELSE intC.copyTargetBracketsHouse.text, 1
! exD.ExceptionLineOverflow => CONTINUE];
exD.DisplayExceptionStringOnLine[errorString, 2];
exD.FlashExceptionsRegion[];
IF errorString # NIL THEN opD.FreeErrorString[errorString];
END
ELSE BEGIN
count: STRING = [12];
String.AppendLongNumber[count, bytesCopied, 10];
exD.AppendStringToExceptionLine[count, 1];
exD.AppendStringToExceptionLine[" bytes copied."L, 1];
END;
END; -- of CopyCommand --


MenuChange: PUBLIC SIGNAL = CODE;
-- Raised by ChangeCommandMenu to notify any HousePtr holders that they may be
-- invalid.


ChangeEditorMenu: PUBLIC PROCEDURE [newState: lmD.EditorMenuState] =
-- Change the Editor menu to reflect the newState. Raises the resumable SIGNAL
-- MenuChange if the menu is actually changing.
BEGIN
deliverHouse: HousePtr = intC.deliverCommandHouse;
IF newState = intC.editorMenuState THEN RETURN;
SIGNAL MenuChange;
SELECT intC.editorMenuState FROM
singleLine => NULL;
getPut => lmD.ReleaseMenu[intC.getPutMenuSegment];
run => lmD.ReleaseMenu[intC.runMenuSegment];
find => lmD.ReleaseMenu[intC.findMenuSegment];
substitute => lmD.ReleaseMenu[intC.substituteMenuSegment];
copy => lmD.ReleaseMenu[intC.copyMenuSegment];
ENDCASE => exD.SysBug[];
SELECT newState FROM
singleLine => deliverHouse.nextHouse ← NIL;
getPut => BEGIN
deliverHouse.nextHouse ← lmD.SwapInMenu[intC.getPutMenuSegment];
intC.getPutBracketsHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber, lmD.getPutBracketsNumber];
END;
run => BEGIN
deliverHouse.nextHouse ← lmD.SwapInMenu[intC.runMenuSegment];
intC.runBracketsHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber, lmD.runBracketsNumber];
END;
find => BEGIN
deliverHouse.nextHouse ← lmD.SwapInMenu[intC.findMenuSegment];
intC.findHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber, lmD.findCommandNumber];
intC.findBracketsHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber, lmD.findBracketsNumber];
END;
substitute => BEGIN
deliverHouse.nextHouse ← lmD.SwapInMenu[intC.substituteMenuSegment];
intC.substituteHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber,
lmD.substituteCommandNumber];
intC.substituteNewBracketsHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber,
lmD.substituteNewBracketsNumber];
intC.substituteOldBracketsHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber,
lmD.substituteOldBracketsNumber];
END;
copy => BEGIN
deliverHouse.nextHouse ← lmD.SwapInMenu[intC.copyMenuSegment];
intC.copySourceBracketsHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber,
lmD.copySourceBracketsNumber];
intC.copyTargetBracketsHouse ← lmD.MapHouseNumberToHousePtr
[deliverHouse, lmD.deliverCommandNumber,
lmD.copyTargetBracketsNumber];
END;
ENDCASE => exD.SysBug[];
intC.editorMenuState ← newState;
ChangeCommandMenu
[cnp: intC.cmCommandNbr, region: intC.CMCommandRegion, linesToKeep: 1];
END; -- of ChangeEditorMenu --


ShortenEditorMenuCommand: PUBLIC CommandProcedure =
BEGIN
ChangeEditorMenu[singleLine];
IF CaretIsBlinking[] THEN SetCaretBlinking[intC.target.point, intC.target.mnp];
END; -- of ShortenEditorMenuCommand --


END. -- of EditorFiles --