ActionWorkAreasImpl.mesa
Warren Teitelman, May 13, 1983 10:44 am
DIRECTORY
ActionAreasDefs USING [ShowSource, PrintSource],
AMBridge USING [TVToCardinal, GetWorld],
AMTypes USING [IsNil],
BBAction USING [Abort, Action, ActionId, NextPendingAction, PeekData, WaitForChange],
BBBreak USING [BreakId, BreakIndex, ClearAllBreaks, CondProc],
BBContext USING [Context, ContextForLocalFrame],
BBEval USING [EvalHead],
BBVExtras USING [DisplayLocalFrame],
BBVForUserExec USING [ReportProc, SourceFromTV, Severity],
IconManager USING [IconNotify],
Icons USING [IconFlavor, NewIconFromFile],
IO USING [card, CurrentPosition, Flush, GetOutputStreamRope, GetToken, int, PutChar, PutF, PutRope, PutSignal, RIS, rope, ROPE, ROS, STREAM, TV, WhiteSpace],
Menus USING [ChangeNumberOfLines, ClickProc, FindEntry, Menu, MenuEntry, SetGuarded, SetLine],
MessageWindow USING [Append, Blink],
Process USING [Detach],
Rope USING [Find, IsEmpty, Substr, Cat, Concat],
TiogaOps USING [Location, SelectionGrain, SelectPoint, LastLocWithin, ViewerDoc, GetSelection, SetSelection, SelectionError],
UserExec USING [CommandProc, CreateUserExecutive, ExecHandle, Expression, GetExecHandle, GetStreams, HistoryEvent, RegisterCommand, StartListening, StuffIt, Viewer],
UserExecPrivate USING [ActionAreaData, AdviseExec, CaptionForExec, EvalHeadData, execHandleList, ExecPrivateRecord, GetEvalHead, GetPrivateStuff, secondMenuLine, ForAllSplitViewers, SplitViewerProc],
UserProfile USING [Boolean, ProfileChangedProc, CallWhenProfileChanges],
ViewerOps USING [PaintViewer, OpenIcon],
ViewerTools USING [GetSelectedViewer, SetSelection],
WorldVM USING [LocalWorld, WorldName, World]
;
ActionAreasImpl: CEDAR PROGRAM
IMPORTS ActionAreasDefs, AMBridge, AMTypes, BBAction, BBBreak, BBContext, BBVExtras, BBVForUserExec, IconManager, Icons, IO, Menus, MessageWindow, Process, Rope, TiogaOps, UserExec, UserExecPrivate, UserProfile, ViewerOps, ViewerTools, WorldVM
EXPORTS UserExec, ActionAreasDefs
SHARES IO
= BEGIN OPEN IO;
Types
ExecHandle: TYPE = UserExec.ExecHandle;
HistoryEvent: TYPE = UserExec.HistoryEvent;
Viewer: TYPE = UserExec.Viewer;
ClickProc: TYPE = Menus.ClickProc; -- [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL]
connecting concrete and opaque types
Action: TYPE = BBAction.Action;
ExecPrivateRecord: PUBLIC TYPE = UserExecPrivate.ExecPrivateRecord;
so can reference action, evalHead, etc.
for time being, to access commandLine, commandLineStream field of event.
spawnWorkAreas: BOOLEANTRUE;
Spawning areas: Mother, PrintAction, NewAction, FindAnArea
GetAction: PROC [exec: ExecHandle] RETURNS [Action] = INLINE {
private: REF ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec];
RETURN[IF private.actionAreaData # NIL THEN private.actionAreaData.action ELSE NIL];
};
Mother: PROC [proc: PROC [Action]] = {
this proc is the base of a process that watches for new actions
it calls a user procedure for each new action
lastChange: INT ← 0;
lastId: BBAction.ActionId ← 0;
DO
ENABLE ABORTED => EXIT;
maxId: BBAction.ActionId ← lastId;
lastChange ← BBAction.WaitForChange[lastChange];
FOR action: Action ← BBAction.NextPendingAction[NIL], BBAction.NextPendingAction[action]
UNTIL action = NIL DO
maxId ← MAX[maxId, action.id];
IF action.status # pendingOut THEN LOOP;
IF action.id <= lastId THEN EXIT; -- we have seen all the new ones
proc[action];
ENDLOOP;
lastId ← maxId;
ENDLOOP;
};
PrintAction: PROCEDURE [action: Action, parent: UserExec.ExecHandle, out: IO.STREAM] RETURNS[frameTV: TV] = TRUSTED { -- unsafe discrimination, WorldVM.LocalWorld, AMBridge.TVToCardinal
kind: ROPE;
Report: BBVForUserExec.ReportProc = CHECKED {ReportExec[NIL, msg, severity]};
WITH e: action.event SELECT FROM
booted => kind ← "booted";
break => kind ← "break";
call => kind ← "callDebugger";
signal => kind ← "signal";
interrupt => kind ← "interrupt";
unknown => kind ← "unknown";
ENDCASE => ERROR;
out.PutF["\nAction #%d", int[action.id]];
out.PutF[" (kind: %g, ", rope[kind]];
IF (action.event.world # WorldVM.LocalWorld[]) THEN out.PutF["world: %g, ", rope[WorldVM.WorldName[action.event.world]]];
out.PutF["process: %bB)", card[AMBridge.TVToCardinal[action.event.process]]];
IF parent # NIL THEN {
parentsPrivate: REF ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[parent];
out.PutF[" (from %g)", rope[Rope.Concat[IF parentsPrivate.actionAreaData # NIL THEN "Action Area " ELSE "Work Area ", parentsPrivate.id]]];
};
out.PutChar['\n];
frameTV ← action.event.frame;
WITH e: action.event SELECT FROM
booted => NULL;
break => {
WITH BBAction.PeekData[action] SELECT FROM
breakID: BBBreak.BreakId => {
out.PutF["Break #%d", int[breakID.index]];
IF breakID.entry THEN out.PutRope[" at entry to "]
ELSE IF breakID.exit THEN out.PutRope[" at exit to "]
ELSE out.PutRope[" in "];
};
ENDCASE => out.PutRope["Break #?? in "]; -- %$#$@#Rovner's break point, came in at a level below where he should.
BBVExtras.DisplayLocalFrame[out, frameTV, Report];
};
call => {
out.PutRope["from "];
BBVExtras.DisplayLocalFrame[out, frameTV, Report];
IF NOT Rope.IsEmpty[e.msg] THEN out.PutF["msg: %g\n", rope[e.msg]];
};
signal => {
out.PutSignal[e.signal, e.args];
out.PutRope[" from "];
BBVExtras.DisplayLocalFrame[out, frameTV, Report];
};
interrupt => NULL;
unknown => out.PutF["why: %g\n", rope[e.why]];
ENDCASE;
};
NewAction: PROCEDURE [action: Action] = {
abbrevMsg, fullMsg, ropeForIcon: ROPE;
exec, parent: ExecHandle;
break: BOOLFALSE;
private, parentsPrivate: REF ExecPrivateRecord;
viewer: Viewer;
evalHead: BBEval.EvalHead;
stream: IO.STREAM;
frameTV: TV;
IF NOT spawnWorkAreas THEN RETURN;
TRUSTED -- AMBridge, WorldVM
{ -- in here if anything goes wrong, don't spawn another work area.
ENABLE UNWIND => spawnWorkAreas ← TRUE;
spawnWorkAreas ← FALSE;
stream ← IO.ROS[];
find work area this action came from, if any
IF NOT AMTypes.IsNil[action.event.process] THEN -- if process is NIL, then can't be coming out of any exec, since this isn't a valid process to be running under. If don't make this check then whenever you get a NIL process (which means something is wrong) would incorrectly assume that the parent was any proceeded or aborted actionarea
FOR l: LIST OF ExecHandle ← UserExecPrivate.execHandleList, l.rest UNTIL l = NIL DO
private: REF ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[l.first];
IF (LOOPHOLE[private.process, CARDINAL] = AMBridge.TVToCardinal[action.event.process]) AND
(action.event.world = WorldVM.LocalWorld[]) THEN {
parent ← l.first;
parentsPrivate ← UserExecPrivate.GetPrivateStuff[parent];
EXIT;
};
ENDLOOP;
frameTV ← PrintAction[action: action, parent: parent, out: stream];
fullMsg ← stream.GetOutputStreamRope[];
WITH e: action.event SELECT FROM
booted => {
world: WorldVM.World = action.event.world;
ThisWorld: BBBreak.CondProc -- [bid: BreakId, lf: TV, data: REF ← NIL] -- = TRUSTED {
RETURN[world = AMBridge.GetWorld[lf]];
};
FOR l: LIST OF ExecHandle ← UserExecPrivate.execHandleList, l.rest UNTIL l = NIL DO
private: REF ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[l.first];
actionAreaData: REF UserExecPrivate.ActionAreaData = private.actionAreaData;
action: Action;
IF actionAreaData # NIL AND (action ← actionAreaData.action) # NIL AND action.event.world = world THEN {
ActionAreas.LeaveActionArea[exec: l.first, abort: FALSE, booted: TRUE];
IF action.status = pendingOut THEN [] ← BBAction.Abort[action];
private.execState ← dormant;
UserExecPrivate.ReleaseExec[exec];
IF private.execState = listening THEN UserExec.StuffIt[l.first, "\021EndSession\n"];
EXIT;
};
ENDLOOP;
BBBreak.ClearAllBreaks[ThisWorld];
IF action.status = pendingOut THEN [] ← BBAction.Abort[action];
spawnWorkAreas ← TRUE;
RETURN;
};
break => {
i: INT = Rope.Find[s1: fullMsg, s2: "Break"];
abbrevMsg ← Rope.Substr[base: fullMsg, start: i, len: Rope.Find[s1: fullMsg, s2: "\n", pos1: i] - i];
ropeForIcon ← Rope.Cat["Break in ", Rope.Substr[abbrevMsg, Rope.Find[abbrevMsg, "."] + 1]]; includes Break In.
ropeForIcon ← Rope.Substr[abbrevMsg, Rope.Find[abbrevMsg, "."] + 1]; -- just the name, no Break In
break ← TRUE;
};
call => {
i: INT = Rope.Find[s1: fullMsg, s2: "msg:", pos1: 1];
abbrevMsg ← "Call Debugger";
IF i # -1 THEN {
ropeForIcon ← Rope.Substr[base: fullMsg, start: i + 5, len: Rope.Find[s1: fullMsg, s2: "\n", pos1: i] - i - 5];
abbrevMsg ← Rope.Cat[abbrevMsg, " - ", ropeForIcon];
};
};
signal => {
i: INT = Rope.Find[s1: fullMsg, s2: "\n", pos1: 1] + 1;
j: INT = Rope.Find[s1: fullMsg, s2: "[", pos1: i];
IF j = -1 THEN -- signal/error has no arguments
abbrevMsg ← Rope.Substr[base: fullMsg, start: i, len: Rope.Find[s1: fullMsg, s2: "\n", pos1: i] - i]
ELSE {
k: INT = Rope.Find[s1: fullMsg, s2: "]", pos1: j];
abbrevMsg ← Rope.Concat[Rope.Substr[base: fullMsg, start: i, len: j - i],
Rope.Substr[base: fullMsg, start: k + 1, len: Rope.Find[s1: fullMsg, s2: "\n", pos1: k] - k - 1]];
};
ropeForIcon ← Rope.Substr[base: abbrevMsg, len: Rope.Find[abbrevMsg, " from"]]; -- includes SIGNAL
stream ← IO.RIS[abbrevMsg];
[] ← IO.GetToken[stream, IO.WhiteSpace];
ropeForIcon ← IO.GetToken[stream, IO.WhiteSpace]; -- just the name, no SIGNAL.
ropeForIcon ← Rope.Substr[base: ropeForIcon, start: Rope.Find[ropeForIcon, "."] + 1]; -- usually no room for interface
};
interrupt => abbrevMsg ← "Interrupt";
unknown => abbrevMsg ← "Unknown";
ENDCASE;
IF ropeForIcon = NIL THEN ropeForIcon ← abbrevMsg;
exec ← FindAnArea[parent, action.event.world];
IF exec = NIL THEN -- spawn a new one
{
exec ← UserExec.CreateUserExecutive[msg: "", paint: FALSE, iconic: TRUE, startListening: FALSE];
private ← exec.privateStuff;
Menus.ChangeNumberOfLines[menu: exec.viewer.menu, newLines: 2];
IF break THEN -- guard abort button
Menus.SetGuarded[Menus.FindEntry[menu: exec.viewer.menu, entryName: "Abort"], TRUE];
private.actionAreaData ← NEW[UserExecPrivate.ActionAreaData ← [parentExec: parent, action: action, world: action.event.world, fullMsg: fullMsg, abbrevMsg: abbrevMsg, iconMsg: ropeForIcon]];
[] ← UserExecPrivate.CaptionForExec[exec, FALSE];
ViewerOps.OpenIcon[exec.viewer]; -- in lieu of creating full size, paint = FALSE, and then having to paint the column
UserExecPrivate.AdviseExec[exec, SaveSel, RestoreSel, exec];
}
ELSE -- exec is already an action area of parent
{
viewerProc: UserExecPrivate.SplitViewerProc = TRUSTED {
Menus.SetLine[menu: viewer.menu, line: 1, entryList: UserExecPrivate.secondMenuLine];
Menus.SetGuarded[entry: Menus.FindEntry[menu: viewer.menu, entryName: "Abort"], guard: break];
IF viewer.iconic THEN ViewerOps.OpenIcon[viewer]
ELSE ViewerOps.PaintViewer[viewer: viewer, hint: menu];
};
private ← exec.privateStuff;
UserExecPrivate.ForAllSplitViewers[exec.viewer, viewerProc];
private.actionAreaData.fullMsg ← fullMsg;
private.actionAreaData.abbrevMsg ← abbrevMsg;
private.actionAreaData.iconMsg ← ropeForIcon;
private.actionAreaData.action ← action;
[] ← UserExecPrivate.CaptionForExec[exec, TRUE];
};
evalHead ← UserExecPrivate.GetEvalHead[exec];
evalHead.context ← BBContext.ContextForLocalFrame[frameTV];
IF parent # NIL THEN TRUSTED {
viewerProc: UserExecPrivate.SplitViewerProc = TRUSTED {
IF parentsPrivate.actionAreaData # NIL THEN {
viewer.icon ← inactiveActionAreaIcon;
Menus.SetLine[menu: viewer.menu, line: 1, entryList: NIL];
ViewerOps.PaintViewer[viewer, menu];
}
ELSE viewer.icon ← inactiveExecIcon;
};
UserExecPrivate.ForAllSplitViewers[parent.viewer, viewerProc];
IF parentsPrivate.evalHead # NIL THEN {
evalHeadData, parentsEvalHeadData: REF UserExecPrivate.EvalHeadData;
evalHeadData ← NARROW[evalHead.data];
parentsEvalHeadData ← NARROW[parentsPrivate.evalHead.data];
IF evalHeadData.defaultInterface = NIL THEN evalHeadData.defaultInterface ← parentsEvalHeadData.defaultInterface;
IF evalHead.globalContext = NIL THEN evalHead.globalContext ← parentsPrivate.evalHead.globalContext;
};
parentsPrivate.spawnedActionArea ← exec;
parentsPrivate.execState ← suspended;
InformParent[font: IF break THEN "*n*m" ELSE "*n*e", abbrevMsg: abbrevMsg, id: private.id, out: parentsPrivate.out ! ANY => CONTINUE];
[] ← UserExecPrivate.CaptionForExec[parent, TRUE];
};
private.out.PutF[Rope.Concat["*s", fullMsg]];
SaveSelection[exec];
private.evalMode ← TRUE;
[] ← UserExecPrivate.CaptionForExec[exec, TRUE];
{viewerProc: UserExecPrivate.SplitViewerProc = TRUSTED {viewer.icon ← actionAreaIcon};
UserExecPrivate.ForAllSplitViewers[exec.viewer, viewerProc];
};
IF (viewer ← ViewerTools.GetSelectedViewer[]) = NIL OR (parent # NIL AND viewer = parent.viewer) THEN ViewerTools.SetSelection[exec.viewer];
IF break AND UserProfile.Boolean["AutoShowSource", TRUE] THEN {
comment, fatal, success: BOOLFALSE;
Report: BBVForUserExec.ReportProc = CHECKED {
IF Rope.IsEmpty[msg] THEN RETURN;
SELECT severity FROM
comment => {IF comment THEN RETURN; comment ← TRUE};
fatal => {IF fatal THEN RETURN; fatal ← TRUE};
success => {IF success THEN RETURN; success ← TRUE};
ENDCASE => RETURN;
ReportExec[NIL, msg, severity];
};
name: ROPE;
index: INT;
[name, index] ← BBVForUserExec.SourceFromTV[frameTV, Report];
IF name = NIL THEN RETURN; -- something went wrong, would already have been reported
ActionAreasDefs.PrintSource[viewer: ActionAreasDefs.ShowSource[name: name, index: index, exec: exec, onlyIfAlreadyOpen: TRUE], index: index, exec: exec];
};
UserExec.StartListening[exec];
spawnWorkAreas ← TRUE;
}; -- of enable unwind
};
actionAreaIcon, inactiveActionAreaIcon, inactiveExecIcon: PUBLIC Icons.IconFlavor ← typescript;
SetIcons: UserProfile.ProfileChangedProc -- [reason: ProfileChangeReason] -- = {
IF UserProfile.Boolean["UseExecIcons", TRUE] THEN {
actionAreaIcon ← Icons.NewIconFromFile["UserExec.Icons", 0];
inactiveActionAreaIcon ← Icons.NewIconFromFile["UserExec.Icons", 3];
inactiveExecIcon ← Icons.NewIconFromFile["UserExec.Icons", 2];
}
ELSE actionAreaIcon ← inactiveActionAreaIcon ← inactiveExecIcon ← typescript;
};
InformParent: PROC [font, abbrevMsg, id: ROPE, out: IO.STREAM] = {
out.PutF[font];
out.PutF["%g\n*mcomputation suspended, switching to Action Area %g...", rope[abbrevMsg], rope[id]];
out.Flush[];
};
FindAnArea: PROCEDURE [parent: ExecHandle, world: WorldVM.World] RETURNS[exec: ExecHandle] = {
FOR l: LIST OF ExecHandle ← UserExecPrivate.execHandleList, l.rest UNTIL l = NIL DO
private: REF ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[l.first];
IF private.actionAreaData # NIL -- was an action area
AND private.actionAreaData.action = NIL -- that was proceeded or aborted
AND private.execState = dormant -- and is not executing a command
AND private.actionAreaData.parentExec = parent -- and came from same parent (or no parent)
AND private.actionAreaData.world = world -- and same world
-- AND NOT l.first.viewer.iconic and isnt iconic
THEN RETURN[l.first];
ENDLOOP;
}; -- some actions come out of thin air, i.e. not from a particular work area. In this case, reuse an area that also came out of thin air, i.e. parent = NIL.
Saving And Restoring the current selection
SaveSelection: PROC [exec: UserExec.ExecHandle] = TRUSTED {
private: REF UserExecPrivate.ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec];
actionAreaData: REF UserExecPrivate.ActionAreaData = private.actionAreaData;
IF actionAreaData = NIL THEN ERROR;
IF actionAreaData.world # WorldVM.LocalWorld[] THEN RETURN;
[actionAreaData.viewer, actionAreaData.start, actionAreaData.end, actionAreaData.level, actionAreaData.caretBefore, actionAreaData.pendingDelete] ← TiogaOps.GetSelection[];
IF actionAreaData.viewer = NIL THEN
{actionAreaData.viewer ← ViewerTools.GetSelectedViewer[];
actionAreaData.tiogaDoc ← FALSE;
}
ELSE actionAreaData.tiogaDoc ← TRUE;
};
RestoreSelection: PUBLIC PROC [exec: UserExec.ExecHandle] = TRUSTED {
private: REF UserExecPrivate.ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec];
actionAreaData: REF UserExecPrivate.ActionAreaData = private.actionAreaData;
savedViewer: Viewer = actionAreaData.viewer;
IF savedViewer = NIL OR savedViewer.destroyed OR ViewerTools.GetSelectedViewer[] # exec.viewer OR actionAreaData.world # WorldVM.LocalWorld[]
THEN NULL
ELSE IF actionAreaData.tiogaDoc THEN {
IF actionAreaData.parentExec # NIL AND savedViewer = actionAreaData.parentExec.viewer THEN {
ViewerTools.SetSelection[savedViewer]; -- put caret at end
TiogaOps.SelectPoint[viewer: savedViewer, caret: TiogaOps.LastLocWithin[TiogaOps.ViewerDoc[savedViewer]] ! TiogaOps.SelectionError => CONTINUE]; -- go to end. assumes that only one node in typescript.
}
ELSE TiogaOps.SetSelection[viewer: savedViewer, start: actionAreaData.start, end: actionAreaData.end, level: actionAreaData.level, caretBefore: actionAreaData.caretBefore, pendingDelete: actionAreaData.pendingDelete ! TiogaOps.SelectionError => CONTINUE]
}
ELSE IF savedViewer.iconic THEN IconManager.IconNotify[savedViewer, LIST[$Select]];
};
ShowSelCommandProc: UserExec.CommandProc = {
private: REF UserExecPrivate.ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec];
actionAreaData: REF UserExecPrivate.ActionAreaData ← private.actionAreaData;
IF actionAreaData = NIL THEN {UserExec.GetStreams[exec].out.PutF["*eNot An Action Area\n"]; RETURN[FALSE]};
RestoreSelection[exec];
};
RestoreSelCommandProc: UserExec.CommandProc = {
private: REF UserExecPrivate.ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec];
actionAreaData: REF UserExecPrivate.ActionAreaData ← private.actionAreaData;
IF actionAreaData = NIL THEN {UserExec.GetStreams[exec].out.PutF["*eNot An Action Area\n"]; RETURN[FALSE]};
actionAreaData.restoreSelAfterEachEvent ← NOT actionAreaData.restoreSelAfterEachEvent;
};
SaveSel: PROC [data: REF ANY] = {
exec: UserExec.ExecHandle = NARROW[data];
private: REF UserExecPrivate.ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec];
actionAreaData: REF UserExecPrivate.ActionAreaData = private.actionAreaData;
viewer: Viewer = actionAreaData.viewer;
IF viewer # NIL AND NOT viewer.destroyed AND ViewerTools.GetSelectedViewer[] = viewer THEN SaveSelection[exec]; -- user has done something which changed the selection. notice it
};
RestoreSel: PROC [data: REF ANY] = {
exec: UserExec.ExecHandle = NARROW[data];
private: REF UserExecPrivate.ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec];
actionAreaData: REF UserExecPrivate.ActionAreaData = private.actionAreaData;
IF actionAreaData = NIL THEN ERROR;
IF actionAreaData.restoreSelAfterEachEvent THEN RestoreSelection[exec];
};
ReportExec: PROC [exec: UserExec.ExecHandle, msg: ROPE, severity: BBVForUserExec.Severity, out: IO.STREAMNIL] = {
ReportProc: BBVForUserExec.ReportProc -- [msg: ROPE, severity: Severity] -- = {
MessageWindow.Append[msg];
IF severity = fatal THEN MessageWindow.Blink[];
};
ReportProc[msg, severity];
IF severity = comment THEN NULL
ELSE IF exec # NIL THEN
{out: STREAM = UserExec.GetStreams[exec].out;
IF out.CurrentPosition[] # 0 THEN out.PutChar['\t];
out.PutF[
SELECT severity FROM
success => "%g",
warning => "*m%g*s",
fatal => "*e%g*s",
ENDCASE => ERROR,
rope[msg]
];
}
ELSE IF out # NIL THEN out.PutRope[msg] -- when outRopeStreams can be given font changes, can handle exec and out case the same.
ELSE ReportProc[msg, severity];
};
Initialization
TRUSTED {Process.Detach[FORK Mother[NewAction]]};
UserProfile.CallWhenProfileChanges[SetIcons];
UserExec.RegisterCommand["ShowSelection", ShowSelCommandProc, "Shows what the current selection was before this action occurred."];
UserExec.RegisterCommand["RestoreSelection", RestoreSelCommandProc, "Restore current selection before each event.", "For use in action areas. Sets a flip/flop that controls whether prior to executing each event, the current selection is to be restored prior to executing each event, to what it was before the action occurred. This allows the user to interpret expressions which use or manipulate the current selection. (Note that the current selection is always restored for a Proceed or Abort.)"];
END.
Edited on January 28, 1983 4:32 pm, by Teitelman
changes to: ClearBreak say its ClearActionBreak if red click and selection in action area
Edited on February 1, 1983 1:54 pm, by Teitelman
changes to: NewAction
Edited on February 4, 1983 3:13 pm, by Teitelman
changes to: NewAction, Report (local of NewAction)
Edited on February 27, 1983 2:48 pm, by Teitelman
changes to: DIRECTORY, Report (local of NewAction), RestoreSelection, END
Edited on March 4, 1983 4:08 pm, by Teitelman
changes to: PrintAction, NewAction, DIRECTORY, IMPORTS, EXPORTS, NewAction, CaptionForActionArea, NewAction, actionAreaIcon, SetIcons
Edited on March 7, 1983 1:18 pm, by Teitelman
changes to: SetIcons
Edited on March 10, 1983 1:10 pm, by Teitelman
changes to: NewAction
Edited on March 11, 1983 8:14 pm, by Teitelman
changes to: DIRECTORY, IMPORTS, NewAction, NewAction
Edited on March 25, 1983 5:01 pm, by Teitelman
changes to: SetIcons
Edited on March 28, 1983 12:24 pm, by Teitelman
changes to: viewerProc (local of NewAction), NewAction, viewerProc (local of NewAction), MapViewerProc, MapViewer, SetIcons, EXPORTS, DIRECTORY, Report (local of PrintAction), ThisWorld (local of NewAction), NewAction, viewerProc (local of NewAction), Report (local of NewAction), NewAction
Edited on April 8, 1983 1:45 pm, by Teitelman
changes to: DIRECTORY, SaveSelection, RestoreSelection
Edited on May 13, 1983 10:44 am, by Teitelman
changes to: DIRECTORY, IMPORTS, NewAction, IMPORTS, NewAction, EXPORTS