ActionWorkAreasImpl.mesa
Warren Teitelman, April 8, 1983 1:47 pm
DIRECTORY
ActionAreas USING [],
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, ShowSource],
BBVForUserExec USING [ReportProc, 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 AMBridge, AMTypes, BBAction, BBBreak, BBContext, BBVExtras, IconManager, Icons, IO, Menus, MessageWindow, Process, Rope, TiogaOps, UserExec, UserExecPrivate, UserProfile, ViewerOps, ViewerTools, WorldVM
EXPORTS UserExec, ActionAreas
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: BOOLEAN ← TRUE;
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, 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 (kind: %g, ", int[action.id], rope[kind]];
IF (action.event.world # WorldVM.LocalWorld[]) THEN out.PutF["world: %g, ", rope[WorldVM.WorldName[action.event.world]]];
out.PutF["process: %bB)\n", card[AMBridge.TVToCardinal[action.event.process]]];
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, cameFrom: ROPE;
exec, parent: ExecHandle;
break: BOOL ← FALSE;
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[];
frameTV ← PrintAction[action: action, 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";
IF ropeForIcon = NIL THEN ropeForIcon ← abbrevMsg;
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;
exec ← FindAnArea[parent, action.event.world];
IF parent # NIL THEN cameFrom ← Rope.Concat[IF parentsPrivate.actionAreaData # NIL THEN "Action Area " ELSE "Work Area ", parentsPrivate.id];
ELSE IF action.event.world = WorldVM.LocalWorld[] THEN cameFrom ← NARROW[UserExec.ProcessGetProp[LOOPHOLE[AMBridge.TVToCardinal[action.event.process], UNSAFE PROCESS], $Name]];
IF NOT Rope.IsEmpty[cameFrom] THEN fullMsg ← Rope.Cat[fullMsg, "(came from ", cameFrom, ")"];
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];
};
UserExec.StartListening[exec];
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: BOOL ← FALSE;
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];
};
BBVExtras.ShowSource[tv: frameTV, report: Report, onlyIfAlreadyOpen: TRUE];
};
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.
STREAM ←
NIL] = {
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