-- file: EditorUndo.Mesa
-- edited by Brotz, May 4, 1981 4:32 PM
-- edited by Levin, February 22, 1980 12:42 PM
DIRECTORY
Editor,
exD: FROM "ExceptionDefs",
inD: FROM "InteractorDefs",
intCommon: FROM "IntCommon",
ovD: FROM "OverviewDefs",
vmD: FROM "VirtualMgrDefs";
EditorUndo: PROGRAM
IMPORTS Editor, exD, intC: intCommon, vmD
EXPORTS Editor =
BEGIN
OPEN Editor, inD;
Undo: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr] =
-- Undoes the last command, ignoring subsequent window commands or selections.
BEGIN
commandType: POINTER TO CommandType = @intC.commandType;
actionPoint: POINTER TO ovD.CharIndex = @intC.actionPoint;
target: TextSelectionPtr = @intC.target;
modelessEditor: BOOLEAN = (intC.editorType = modeless);
IF commandType↑ = noCommand THEN RETURN;
CancelTargetSelection[];
IF commandType↑ = get THEN
BEGIN -- flip buffers back
SwapMessageWithDeletionBuffer[mnp];
target↑ ← TextSelection[mnp, 0, vmD.GetMessageSize[mnp.message], 0, char, FALSE];
IF modelessEditor THEN {target.start ← target.end; intC.newTargetSelection ← FALSE};
SetHighWaterMark[0];
RefreshSoThatFirstCharStartsLine[0, mnp.lines, mnp];
TurnOnDeliver[];
END
ELSE BEGIN
thisInsertionLength: CARDINAL = vmD.GetMessageSize[mnp.deletionBuffer];
thisDeletionLength: CARDINAL = vmD.GetMessageSize[mnp.insertionBuffer];
ReplaceRangeInMess[
to: vmD.MessageRange
[actionPoint↑, actionPoint↑ + vmD.GetMessageSize[mnp.insertionBuffer],
mnp.message],
from: vmD.MessageRange[0, thisInsertionLength, mnp.deletionBuffer]];
SwapInsertionWithDeletionBuffer[mnp];
target↑ ← TextSelection
[mnp, actionPoint↑, actionPoint↑ + thisInsertionLength, 0, char, FALSE];
IF modelessEditor THEN {target.start ← target.end; intC.newTargetSelection ← FALSE};
UpdateScreen[start: actionPoint↑, nCharsDeleted: thisDeletionLength,
nCharsInserted: thisInsertionLength, mnp: mnp];
END;
commandType↑ ← SELECT commandType↑ FROM
get => get,
insert, append => delete,
delete => insert,
ENDCASE => replace;
END; -- of Undo --
Redo: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr] =
-- Redoes the last command with the Segment [start .. end).
BEGIN
commandType: POINTER TO CommandType = @intC.commandType;
target: TextSelectionPtr = @intC.target;
start: ovD.CharIndex ← target.start;
end: ovD.CharIndex ← target.end;
modelessEditor: BOOLEAN = (intC.editorType = modeless);
insertionLength: CARDINAL = vmD.GetMessageSize[mnp.insertionBuffer];
deletionBufferLength: CARDINAL = vmD.GetMessageSize[mnp.deletionBuffer];
IF modelessEditor AND start = end THEN RETURN;
SELECT commandType↑ FROM
noCommand, get => RETURN;
insert => IF modelessEditor THEN start ← end ← target.point ELSE end ← start;
append => IF modelessEditor THEN start ← end ← target.point ELSE start ← end;
ENDCASE;
IF commandType↑ = insert OR commandType↑ = append THEN
CancelTargetSelection[]
ELSE target.pendingDelete ← FALSE;
intC.actionPoint ← start;
ReplaceRangeInMess
[to: vmD.MessageRange[0, deletionBufferLength, mnp.deletionBuffer],
from: vmD.MessageRange[start, end, mnp.message]];
ReplaceRangeInMess
[to: vmD.MessageRange[start, end, mnp.message],
from: vmD.MessageRange[0, insertionLength, mnp.insertionBuffer]];
target↑ ← TextSelection[mnp, start, start + insertionLength, 0, char, FALSE];
IF modelessEditor THEN
{target.start ← target.end; intC.newTargetSelection ← FALSE};
UpdateScreen[start: start, nCharsDeleted: end - start,
nCharsInserted: insertionLength, mnp: mnp];
END; -- of Redo --
InsertFromLastCommand: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr] =
-- Only callable if editorType = modal.
BEGIN
target: TextSelectionPtr = @intC.target;
insertionLength: CARDINAL;
IF intC.editorType = modeless OR intC.pendingCommandType = noCommand THEN
exD.SysBug[];
IF (intC.pendingCommandType = insert OR intC.pendingCommandType = append)
AND intC.commandType = delete
THEN BEGIN
SwapInsertionWithDeletionBuffer[mnp];
ResetDeletionBuffer[mnp];
END;
intC.commandType ← intC.pendingCommandType;
intC.actionPoint ← target.point;
intC.pendingCommandType ← noCommand;
CancelTargetSelection[];
insertionLength ← vmD.GetMessageSize[mnp.insertionBuffer];
InsertRangeInMess
[targetIndex: target.point, targetMessage: LOOPHOLE[mnp.message],
from: vmD.MessageRange[0, insertionLength, mnp.insertionBuffer]];
target↑ ← TextSelection
[mnp, intC.actionPoint, intC.actionPoint + insertionLength, 0, char, FALSE];
UpdateScreen[start: intC.actionPoint, nCharsDeleted: 0,
nCharsInserted: insertionLength, mnp: mnp];
END; -- of InsertFromLastCommand --
InsertLastDeletion: PUBLIC PROCEDURE [mnp: MessageTextNbrPtr] =
BEGIN
-- Only callable if editor is modeless.
target: TextSelectionPtr = @intC.target;
commandType: POINTER TO CommandType = @intC.commandType;
insertionLength: CARDINAL= vmD.GetMessageSize[mnp.deletionBuffer];
deletionLength: CARDINAL ← 0;
insertionBufferIndex: ovD.CharIndex;
IF intC.newTargetSelection THEN
BEGIN
IF target.pendingDelete THEN
BEGIN
target.point ← target.start;
commandType↑ ← replace;
END
ELSE {CancelTargetSelection[]; commandType↑ ← insert};
ResetInsertionBuffer[mnp];
intC.actionPoint ← target.point;
intC.newTargetSelection ← FALSE;
END
ELSE IF commandType↑ = delete THEN commandType↑ ← replace;
insertionBufferIndex ← vmD.GetMessageSize[mnp.insertionBuffer];
-- Move deletion buffer contents to insertion buffer.
InsertRangeInMess
[targetIndex: insertionBufferIndex, targetMessage: mnp.insertionBuffer,
from: vmD.MessageRange[0, insertionLength, mnp.deletionBuffer]];
IF target.pendingDelete THEN
BEGIN
-- Move selection to deletion buffer.
deletionLength ← target.end - target.start;
ReplaceRangeInMess[to: [0, insertionLength, mnp.deletionBuffer],
from: [target.start, target.end, mnp.message]];
END;
-- Move new stuff to message.
ReplaceRangeInMess[
to: [target.point, target.point + deletionLength, LOOPHOLE[mnp.message]],
from: [insertionBufferIndex, insertionBufferIndex + insertionLength,
mnp.insertionBuffer]];
target↑ ← TextSelection
[mnp, target.point + insertionLength, target.point + insertionLength,
target.point, char, FALSE];
UpdateScreen[start: target.point, nCharsDeleted: deletionLength,
nCharsInserted: insertionLength, mnp: mnp];
END; -- of InsertLastDeletion --
END. -- of EditorUndo --