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; 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] Action: TYPE = BBAction.Action; ExecPrivateRecord: PUBLIC TYPE = UserExecPrivate.ExecPrivateRecord; spawnWorkAreas: BOOLEAN _ TRUE; 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]] = { 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 { 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.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]]; }; 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; 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]; 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 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. 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 { 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]; }; 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. ActionWorkAreasImpl.mesa Warren Teitelman, April 8, 1983 1:47 pm Types connecting concrete and opaque types so can reference action, evalHead, etc. for time being, to access commandLine, commandLineStream field of event. Spawning areas: Mother, PrintAction, NewAction, FindAnArea this proc is the base of a process that watches for new actions it calls a user procedure for each new action ActionAreas.LeaveActionArea[exec: l.first, abort: FALSE, booted: TRUE]; IF action.status = pendingOut THEN [] _ BBAction.Abort[action]; private.execState _ dormant; UserExecPrivate.ReleaseExec[exec]; ropeForIcon _ Rope.Cat["Break in ", Rope.Substr[abbrevMsg, Rope.Find[abbrevMsg, "."] + 1]]; includes Break In. ropeForIcon _ Rope.Substr[base: abbrevMsg, len: Rope.Find[abbrevMsg, " from"]]; -- includes SIGNAL find work area this action came from, if any ELSE IF action.event.world = WorldVM.LocalWorld[] THEN cameFrom _ NARROW[UserExec.ProcessGetProp[LOOPHOLE[AMBridge.TVToCardinal[action.event.process], UNSAFE PROCESS], $Name]]; -- AND NOT l.first.viewer.iconic and isnt iconic Saving And Restoring the current selection ViewerTools.SetSelection[savedViewer]; -- put caret at end Initialization 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 Ê®– "Cedar" style˜J˜JšÏc™Jšœ™'J˜šÏk ˜ Jšœ žœ˜Jšœ žœ˜(Jšœžœ ˜Jšœ žœG˜UJšœžœ1˜>Jšœ žœ!˜0Jšœžœ ˜Jšœ žœ!˜0Jšœžœ˜,Jšœ žœ˜Jšœžœ˜*Jš žœžœgžœž œžœžœ ˜JšœžœS˜^Jšœžœ˜$Jšœžœ ˜Jšœžœ&˜0Jšœ žœo˜}Jšœ žœ—˜¥Jšœžœ²˜ÇJšœ žœ7˜HJšœ žœ˜(Jšœ žœ#˜4Jšœžœ˜,šœ˜J˜——J˜JšÐblœžœžœ˜!J˜JšžœQžœ|˜ÖJ˜Jšžœ˜J˜Jšžœž˜ J˜Jšœžœžœžœ˜head™JšÏn œžœ˜'Jš  œžœ˜+Jš œžœ˜Jš  œžœN˜tKšœ$™$Jš œžœ˜š œžœžœ%˜CJ™'—˜J™H—Jš œžœžœ˜—šœÐpr*™:š  œžœžœ ž˜>Jšœ žœ;˜GJš žœžœžœžœžœžœ˜TJšœ˜—J˜š œžœžœ˜&Jš?™?Jš-™-Jšœ žœ˜J˜šž˜Jšžœžœžœ˜J˜"J˜0šžœ-žœ%˜Xšžœ žœž˜Jšœžœ˜Jšžœžœžœ˜(Jšžœžœžœ ˜BJ˜ Jšžœ˜—J˜Jšžœ˜——J˜J˜—š  œž œžœžœžœ žœžœC˜žJšœžœ˜ š œžœ žœ˜MJ˜—šžœžœž˜ J˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšžœžœ˜—JšœA˜AJšžœ-žœF˜yJšœO˜OJ˜ šžœžœž˜ J˜Jšœ žœ˜J˜˜ šžœžœž˜*šœ˜J˜+Jšžœžœ˜3Jšžœžœ˜6Jšžœ˜J˜—Jšžœ#H˜r—Jšœ2˜2J˜—J˜˜ J˜Jšœ2˜2Jšžœžœžœ$˜CJ˜—J˜˜ J˜ J˜Jšœ2˜2Jšœ˜—J˜Jšœ žœ˜J˜Jšœ.˜.J˜Jšžœ˜ —J˜J˜—J˜š  œž œ˜+Jšœ+žœ˜0J˜Jšœžœžœ˜Jšœžœ˜/J˜Jšœ˜Jšœžœžœ˜Jšœ žœ˜ Jšžœžœžœžœ˜"Jšžœ˜šœA˜DJšžœžœžœ˜'Jšœžœ˜Jšœ žœžœ˜J˜3J˜'šžœžœž˜ J˜˜ Jšœ*˜*š  œ-œžœ˜VJšžœ ˜&J˜—š žœžœžœ5žœžœž˜SJšœ žœ>˜JJšœžœ9˜LJ˜š žœžœžœ$žœž˜hJšœ2žœ žœ™GJšžœžœž™?Jšœž™Jšœ"™"Jšžœžœ/˜TJšž˜Jšœ˜—Jšžœ˜—J˜"Jšžœžœž˜?Jšœžœ˜Jšžœ˜J˜—J˜˜ Jšœžœ'˜-J˜eJšœo™oJšœF˜cJšœžœ˜ J˜—J˜šœ ˜ Jšœžœ/˜5Jšœ˜šžœžœ˜Jšœo˜oJ˜4J˜—J˜—J˜˜ Jšœžœ1˜7Jšœžœ,˜2šžœžœ ˜/J˜d—šž˜Jšœžœ,˜2˜IJ˜b—J˜—JšœQ™cJšœ žœžœ ˜J˜(J˜OJšœW ˜wJ˜J˜—šœ%˜%J˜—šœ!˜!J˜—šžœ˜ J˜——Jšžœžœžœ˜2J™Jš,™,šžœžœ%žœ ˜Ñš žœžœžœ5žœžœž˜SJšœ žœ>˜Jšžœžœžœ1ž˜ZJšœ,žœ˜3J˜Jšœ9˜9Jšžœ˜Jšœ˜—Jšžœ˜——J˜.Jšžœ žœžœžœ!žœžœžœ"˜Jšžœžœ+žœ žœžœ.žœžœ ™°Jšžœžœžœ;˜]šžœžœžœ˜%šœ˜Jšœ4žœ žœžœ˜`J˜Jšœ?˜?šžœžœ˜#JšœNžœ˜T—Jšœžœ¡˜½Jšœ*žœ˜1Jšœ"T˜vJšœ=˜=J˜——šžœ,˜1šœ˜š  œ$žœ˜7J˜UJ˜^Jšžœžœ˜0Jšžœ3˜7J˜—J˜Jšœ<˜šžœžœžœ˜'Jšœ#žœ˜DJšœžœ˜%Jšœžœ˜;Jšžœ!žœžœF˜qJšžœžœžœ@˜dJšœ˜—Jšœ(˜(J˜%Jš œžœžœžœIžœžœ˜†Jšœ,žœ˜2J˜—JšœÐboœ"˜-Jšœ˜Jšœžœ˜Jšœ*žœ˜0Jšœ  œ%žœ ˜WJšœ<˜˜>J˜Jšœ˜—JšžœI˜MJ˜—J˜š   œžœžœžœžœ˜DJš¢œ ˜Jš¢œ`˜cJšœ ˜ Jšœ˜—J˜J˜š  œž œ,žœ˜^š žœžœžœ5žœžœž˜SJšœ žœ>˜JJšžœžœ˜6Jšœžœ!žœ ˜KJšžœ!˜CJšœžœ.+˜]Jšžœ'˜;Jšœžœžœ™4Jšžœžœ ˜Jšžœ˜—šœš˜žJ˜———šœ*™*š  œžœžœ˜;Jšœ žœK˜WJšœžœ9˜LJšžœžœžœžœ˜#Jšžœ-žœžœ˜;Jšœ¬˜¬šžœžœž˜#Jšœ9˜9Jšœžœ˜ Jšœ˜—Jšžœžœ˜$J˜—J˜š œžœžœžœ˜EJšœ žœK˜WJšœžœ9˜LJšœ,˜,Jš žœžœžœžœ/žœ.˜Jšœžœžœ˜ šžœž˜&šžœžœžœ0žœ˜\Jšœ(™;Jšœ†žœ7˜ÉJ˜—Jšžœñžœ˜þJ˜—Jšžœžœžœ%žœ ˜TJ˜J˜—š œ˜,Jšœ žœK˜WJšœžœ9˜LJš žœžœžœ@žœžœ˜kJ˜J˜—J˜š œ˜/Jšœ žœK˜WJšœžœ9˜LJš žœžœžœ@žœžœ˜kJšœ*žœ(˜VJ˜—J˜š œžœžœžœ˜!Jšœžœ˜)Jšœ žœK˜WJšœžœ9˜LJšœ'˜'Jš žœ žœžœžœžœ*žœA˜²J˜—J˜š  œžœžœžœ˜$Jšœžœ˜)Jšœ žœK˜WJšœžœ9˜LJšžœžœžœžœ˜#Jšžœ)žœ˜GJ˜—J˜š   œžœ"žœ*žœžœžœ˜uš  œž%œž˜PJ˜Jšžœžœ˜/J˜—Jšœž˜Jšžœžœž˜šžœžœžœž˜Jšœžœ!˜-Jšžœžœ˜3šœ ˜ šžœ ž˜Jšœ˜Jšœ˜Jšœ˜Jšžœžœ˜—Jšœ ˜ Jšœ˜—J˜—Jš žœžœžœžœÐbcT˜Jšžœ˜J˜J˜——™šžœžœ˜1J˜—J˜-J˜J˜ƒJ˜òJ˜J˜—Jšžœ˜™0Jšœ Ïr œC™Y—™0Jšœ ¤ ™—™0Jšœ ¤œ™2—™1Jšœ ¤œ¤™I—™-Jšœ ¤y™…—™-Jšœ ¤™—™.Jšœ ¤ ™—™.Jšœ ¤(™4—™.Jšœ ¤™—™/Jšœ ¤ œ¤œ¤@œ¤ œ¤œ¤œ¤ ™¢—J™J™J™™-Jšœ ¤*™6—J™—…—H0câ