DIRECTORY Atom, CDBasics, CD, CDInstances, CDCallSpecific, CDCommandOps, CDEvents, CDMenus, CDOps, CDPrivate, CDProperties, CDSequencer, CDValue, IO, RefTab, Rope, SymTab, TerminalIO; CDCommandOpsImpl: CEDAR MONITOR IMPORTS Atom, CDBasics, CDInstances, CDCallSpecific, CDEvents, CDMenus, CDOps, CDProperties, CDSequencer, CDValue, IO, RefTab, Rope, SymTab, TerminalIO EXPORTS CDCommandOps = BEGIN -- -- -- -- -- -- ProbablyLastChar: PROC [r: Rope.ROPE] RETURNS [CHAR] = BEGIN l: INT = r.Length[]; IF l<=0 THEN RETURN ['@]; RETURN [r.Fetch[l-1]] END; -- -- -- -- -- -- --ImplementSpecificCommand Entry: TYPE = RECORD [key: ATOM, text: Rope.ROPE_NIL, x: REF]; tableKey: REF = NEW[ATOM_$tableKey]; -- indirect to make inaccessible gTable: SymTab.Ref = SymTab.Create[]; GetTTable: PROC [t: CD.Technology] RETURNS [table: SymTab.Ref] = BEGIN IF t=NIL THEN table_gTable ELSE { x: REF _ CDValue.Fetch[boundTo: t, key: tableKey, propagation: technology]; IF x=NIL THEN { x _ SymTab.Create[7]; CDValue.Store[boundTo: t, key: tableKey, value: x] }; table _ NARROW[x] } END; GetEntry: PROC [tipKey: Rope.ROPE, tech: CD.Technology] RETURNS [entry: REF Entry_NIL] = BEGIN IF tipKey.Length[]>=2 THEN { x: REF; found: BOOL _ FALSE; tipKey _ tipKey.Substr[len: tipKey.Length[]]; IF tech#NIL THEN [found, x] _ SymTab.Fetch[GetTTable[tech], tipKey]; IF NOT found THEN [found, x] _ SymTab.Fetch[gTable, tipKey]; IF found THEN WITH x SELECT FROM e: REF Entry => entry_e ENDCASE => NULL } END; GeneralCommand: PROC [comm: CDSequencer.Command] = BEGIN n: NAT_0; t: Rope.ROPE = Atom.GetPName[comm.key]; entry: REF Entry = GetEntry[t, comm.design.technology]; IF entry=NIL THEN { TerminalIO.WriteRopes["unknown command: ", t]; } ELSE { TerminalIO.WriteRopes[entry.text, " "]; SELECT ProbablyLastChar[t] FROM 'S => { TerminalIO.WriteRope["selected "]; n _ CDCallSpecific.CallForSelected[design: comm.design, objectSpecific: entry.key, x: entry.x]; }; 'P => { TerminalIO.WriteRope["pointed "]; n _ CDCallSpecific.CallForPointed[design: comm.design, point: comm.pos, objectSpecific: entry.key, x: entry.x]; }; 'A => { TerminalIO.WriteRope["all "]; n _ CDCallSpecific.CallForAll[design: comm.design, objectSpecific: entry.key, x: entry.x]; }; 'X => { TerminalIO.WriteRope["(if 1 selected) "]; n _ CDCallSpecific.CallIfOneSelected[design: comm.design, objectSpecific: entry.key, x: entry.x]; }; 'F => { TerminalIO.WriteRope["(first selected) "]; n _ CDCallSpecific.CallForOneSelected[design: comm.design, objectSpecific: entry.key, x: entry.x]; }; ENDCASE => TerminalIO.WriteRope["bad modifier"]; }; TerminalIO.WriteRope["\n "]; TerminalIO.WriteInt[n]; TerminalIO.WriteRope[" objects handled\n"]; END; ImplementSpecificCommand: PUBLIC PROC [specificAtom: ATOM, text: Rope.ROPE_NIL, tipBase: Rope.ROPE_NIL, useFor: Rope.ROPE_NIL, x: REF_NIL, technology: CD.Technology_NIL] = BEGIN t: SymTab.Ref = GetTTable[technology]; entry: REF Entry; EachKey: Rope.ActionType -- PROC [c: CHAR] RETURNS [quit: BOOL _ FALSE] -- = BEGIN SELECT c FROM 'P, 'S, 'A, 'F, 'X => { fiddledTip: Rope.ROPE _ Rope.Concat[tipBase, Rope.FromChar[c]]; [] _ SymTab.Store[t, fiddledTip, entry]; CDSequencer.ImplementCommand[Atom.MakeAtom[fiddledTip], GeneralCommand, technology]; } ENDCASE => NULL END; IF useFor=NIL THEN useFor _ "PS"; IF tipBase=NIL THEN tipBase _ Atom.GetPName[specificAtom]; IF text=NIL THEN text _ tipBase; SELECT ProbablyLastChar[text] FROM '\n, ' => text _ text.Substr[len: text.Length[]-1]; ENDCASE => NULL; entry _ NEW[Entry _ [key: specificAtom, text: text, x: x]]; [] _ Rope.Map[base: useFor, action: EachKey]; END; -- -- -- -- -- -- TheInstance: PUBLIC PROC[comm: CDSequencer.Command, text: Rope.ROPE_NIL] RETURNS [inst: CD.Instance_NIL] = BEGIN multiple: BOOL; key: Rope.ROPE _ Atom.GetPName[comm.key]; IF text=NIL THEN text _ key; SELECT ProbablyLastChar[text] FROM '\n, ' => text _ text.Substr[len: text.Length[]-1]; ENDCASE => NULL; TerminalIO.WriteRopes[text, " "]; SELECT ProbablyLastChar[key] FROM 'S => { TerminalIO.WriteRope["selected\n"]; [inst, multiple] _ CDOps.SelectedInstance[comm.design]; IF multiple THEN {TerminalIO.WriteRope[" multiple selection\n"]; RETURN [NIL]}; IF inst=NIL THEN TerminalIO.WriteRope[" no selection\n"]; }; 'P => { TerminalIO.WriteRope["pointed\n"]; inst _ CDInstances.InstanceAt[CDOps.InstList[comm.design], comm.pos]; IF inst=NIL THEN TerminalIO.WriteRope[" no pointed application\n"]; }; 'X => { TerminalIO.WriteRope["(if 1 selected)\n"]; [inst, multiple] _ CDOps.SelectedInstance[comm.design]; IF multiple THEN {TerminalIO.WriteRope[" multiple selection\n"]; RETURN [NIL]}; IF inst=NIL THEN TerminalIO.WriteRope[" no selection\n"]; }; 'F => { -- and specially 'F TerminalIO.WriteRope["(first selected)\n"]; [inst, multiple] _ CDOps.SelectedInstance[comm.design]; IF inst=NIL THEN TerminalIO.WriteRope[" no selection\n"]; }; ENDCASE => { -- same as 'S TerminalIO.WriteRope["selected\n"]; [inst, multiple] _ CDOps.SelectedInstance[comm.design]; IF multiple THEN {TerminalIO.WriteRope[" multiple selection\n"]; RETURN [NIL]}; IF inst=NIL THEN TerminalIO.WriteRope[" no selection\n"]; }; IF inst#NIL THEN { IF inst.ob=NIL THEN {inst_NIL; TerminalIO.WriteRope[" bad object\n"]}; }; END; -- -- -- -- -- -- BoundingBox: PUBLIC PROC [design: CD.Design, onlySelected: BOOL] RETURNS [r: CD.Rect _ CDBasics.empty] = BEGIN IF onlySelected THEN r _ CDInstances.BoundingRectO[CDOps.InstList[design], TRUE] ELSE FOR l: LIST OF CD.PushRec _ design.actual, l.rest WHILE l#NIL DO r _ CDBasics.Surround[r, CDInstances.BoundingRectO[ NARROW[l.first.dummyCell.ob.specificRef, CD.CellPtr].contents ]] ENDLOOP; END; InstRope: PUBLIC PROC[inst: CD.Instance, verbosity: INT_0] RETURNS [r: Rope.ROPE] = BEGIN IF inst=NIL THEN r _ "nil instance" ELSE { r _ IF inst.ob=NIL THEN "nil object" ELSE IF inst.ob.class.describeInst#NIL THEN inst.ob.class.describeInst[inst] ELSE CDOps.ObjectInfo[inst.ob]; IF verbosity>0 THEN { WITH CDProperties.GetInstanceProp[inst, $SignalName] SELECT FROM n: Rope.ROPE => r _ Rope.Cat[r, " ", n]; a: ATOM => r _ Rope.Cat[r, " ", Atom.GetPName[a]]; ENDCASE => NULL; }; }; RETURN [Rope.Cat["(", r, ")"]] END; ToRope: PUBLIC PROC [x: REF, whenFailed: REF_NIL] RETURNS [rope: Rope.ROPE_NIL] = BEGIN WITH x SELECT FROM r: Rope.ROPE => rope _ r; rt: REF TEXT => rope _ Rope.FromRefText[rt]; i: REF INT => rope _ IO.PutFR["%0g", IO.int[i^]]; a: ATOM => rope _ Atom.GetPName[a]; l: CDPrivate.LayerRef => rope _ CDOps.LayerName[l.number]; ob: CD.Object => rope _ CDOps.ObjectInfo[ob]; inst: CD.Instance => rope _ inst.ob.class.describeInst[inst]; d: CD.Design => rope _ d.name; t: CD.Technology => rope _ t.name; ENDCASE => SELECT whenFailed FROM NIL => rope _ NIL; $Interactive => { RopeNeeded: SIGNAL [ ref: REF REF ] = CODE; refRef: REF REF = NEW[REF _ x]; TerminalIO.WriteRope["please enter a ROPE using the debugger"]; SIGNAL RopeNeeded[refRef]; rope _ ToRope[refRef^ ! RopeNeeded => ERROR]; }; ENDCASE => rope _ ToRope[whenFailed]; END; LambdaRope: PUBLIC PROC [n: CD.Number, lambda: CD.Number_1] RETURNS [Rope.ROPE] = BEGIN IF n MOD lambda = 0 THEN RETURN IO.PutFR1[" %g", IO.int[n/lambda]] ELSE { r: Rope.ROPE _ " ("; IF n<0 THEN {n _ ABS[n]; r _ " -("}; IF n/lambda>0 THEN r _ IO.PutFR["%0g%0g+", IO.rope[r], IO.int[n/lambda]]; RETURN [IO.PutFR["%0g%0g/%0g)", IO.rope[r], IO.int[n MOD lambda], IO.int[lambda]]]; } END; -- -- -- -- -- -- reCheck: CONDITION; Enter: ENTRY PROC [resource: REF, wait: BOOL, design: REF] RETURNS [ok: BOOL] = { IF design=NIL THEN design _ $NIL; DO ok _ RefTab.Insert[resourceTab, resource, design]; IF ok OR ~wait THEN EXIT; WAIT reCheck; ENDLOOP }; Leave: ENTRY PROC [resource: REF] = { [] _ RefTab.Delete[resourceTab, resource]; BROADCAST reCheck }; CallWithResource: PUBLIC PROC [proc: PROC[CDSequencer.Command], comm: CDSequencer.Command, resource: REF, abortFlag: REF BOOL_NIL, waitIfBusy: BOOL _ FALSE] RETURNS [skipped: BOOL_TRUE] = BEGIN ENABLE UNWIND => Leave[resource]; design: CD.Design = IF comm#NIL THEN comm.design ELSE NIL; IF ~Enter[resource, waitIfBusy, design] THEN TerminalIO.WriteRope[" not reentrant; skipped\n"] ELSE { previous: REF _ CDValue.Fetch[design, abortFlagKey]; CDValue.Store[boundTo: design, key: abortFlagKey, value: abortFlag]; IF abortFlag#NIL THEN abortFlag^ _ FALSE; proc[comm]; IF abortFlag#NIL AND abortFlag^ THEN TerminalIO.WriteRope[" aborted\n"] ELSE skipped _ FALSE; CDValue.Store[boundTo: design, key: abortFlagKey, value: previous]; Leave[resource]; } END; AbortEvent: CDEvents.EventProc = { EachResource: RefTab.EachPairAction = { quit _ FALSE; IF design=NIL OR design=val OR val=$NIL THEN WITH CDValue.Fetch[boundTo: val, key: abortFlagKey] SELECT FROM abortFlag: REF BOOL => abortFlag^ _ TRUE; ENDCASE => NULL; }; -- of EachResource [] _ RefTab.Pairs[resourceTab, EachResource] }; InitMenus: PROC [] = { [] _ CDMenus.CreateMenu["Programs on Rects", $RectProgramMenu]; [] _ CDMenus.CreateMenu["Additional Programs", $ProgramMenu]; [] _ CDMenus.CreateMenu["Other Programs", $OtherProgramMenu]; [] _ CDMenus.CreateMenu["Cell (s)", $CellMenu]; [] _ CDMenus.CreateMenu["Global menu", $GlobalMenu]; [] _ CDMenus.CreateMenu["Input / Output", $IOMenu]; [] _ CDMenus.CreateMenu["Directory options", $DirectoryMenu]; [] _ CDMenus.CreateMenu["Viewer options", $ViewerMenu]; [] _ CDMenus.CreateMenu["Special commands", $SpecialMenu]; [] _ CDMenus.CreateMenu["Hard copy", $HardCopyMenu]; [] _ CDMenus.CreateMenu["Display options", $DisplayMenu]; [] _ CDMenus.CreateMenu["Import and remote", $ImportMenu]; [] _ CDMenus.CreateMenu["Generator options", $GeneratorMenu]; [] _ CDMenus.CreateMenu["Text & Properties", $TextPropertyMenu]; CDMenus.ImplementCommandToCallMenu[$RectProgramMenu, $RectProgramMenu]; CDMenus.ImplementCommandToCallMenu[$ProgramMenu, $ProgramMenu]; CDMenus.ImplementCommandToCallMenu[$OtherProgramMenu, $OtherProgramMenu]; CDMenus.ImplementCommandToCallMenu[$CellMenu, $CellMenu]; CDMenus.ImplementCommandToCallMenu[$GlobalMenu, $GlobalMenu]; CDMenus.ImplementCommandToCallMenu[$IOMenu, $IOMenu]; CDMenus.ImplementCommandToCallMenu[$DirectoryMenu, $DirectoryMenu]; CDMenus.ImplementCommandToCallMenu[$ViewerMenu, $ViewerMenu]; CDMenus.ImplementCommandToCallMenu[$DisplayMenu, $DisplayMenu]; CDMenus.ImplementCommandToCallMenu[$SpecialMenu, $SpecialMenu]; CDMenus.ImplementCommandToCallMenu[$HardCopyMenu, $HardCopyMenu]; CDMenus.ImplementCommandToCallMenu[$ImportMenu, $ImportMenu]; CDMenus.ImplementCommandToCallMenu[$TextPropertyMenu, $TextPropertyMenu]; }; resourceTab: RefTab.Ref = RefTab.Create[3]; abortFlagKey: REF _ resourceTab; CDEvents.RegisterEventProc[$Abort, AbortEvent]; InitMenus[]; END. ΌCDCommandOpsImpl.mesa Copyright c 1984, 1986 by Xerox Corporation. All rights reserved. by Christian Jacobi, July 12, 1984 3:49:16 pm PDT last edited Christian Jacobi, March 28, 1986 5:11:34 pm PST Last Edited by: Jacobi June 2, 1986 5:14:49 pm PDT --generic --Implements a command which is executed by using CDCallSpecific --specificAtom: handled through to select CDCallSpecific command --text: logged; defaults to tipBase --tipBase: How command is called in tiptable; defaults to specificAtom --useFor: Suffix letters appended to tipBase getting the tip table entry --x: handled through to CDCallSpecific --technology: NIL => all technologies --set up defaults --do it --TheInstance --extracts the application given a command --if returned application is nil, all the messages are made and caller should return quiet; --if returned application is not nil; text line is written and object is there --Vanilla stuff --CallWithResource --Monitoring commands using global resourceTab --proc will be called with comm as parameter, but is skipped if resource is already in use --resource: typically atom; every resource is called only once at a time --abortFlag: will be set to TRUE if an abort event occurs while execution of proc --the procedure message on Terminal if it skipped the call, or, if abortFlag is true on return --PROC [event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL_FALSE] --PROC [key: Key, val: Val] RETURNS [quit: BOOLEAN] Κ η˜codešœ™Kšœ Οmœ7™BKšœ2™2Kšœ;™;K™2K˜—šΟk ˜ Kšœ˜Kšœž˜ Kšžœ˜K˜ K˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜K˜ K˜ K˜ K˜Kšœ˜Kšœ˜K˜K˜K˜ —K˜šΠblœžœž˜Kšžœ˜—Kšžœ˜—Kšž˜K˜K˜Kšœ ™ K˜š Οnœžœ žœžœžœ˜6Kšž˜Kšœžœ˜Kšžœžœžœ˜Kšžœ˜Kšžœ˜—K˜K˜K˜KšΟc˜K˜Kš œžœžœžœ žœž œ˜>K˜Kšœ žœžœžœ ‘ ˜EKšœ%˜%K˜š  œžœžœ žœ˜@Kšž˜Kšžœžœžœ ˜šžœ˜KšœžœE˜Kšžœžœžœ˜Kšœ˜Kšœ2˜2K˜—Kšœžœ˜K˜—Kšžœ˜—K˜š œžœžœžœ žœ žœžœ˜XKšž˜šžœžœ˜Kšœžœ˜Kšœž œ˜Kšœ-˜-Kšžœžœžœ4˜DKšžœžœžœ+˜<šžœž˜ Kš žœžœžœžœžœžœ˜;—K˜—Kšžœ˜—K˜K˜š œžœ˜2Kšž˜Kšœžœ˜ Kšœžœ˜'Kšœžœ-˜7šžœžœžœ˜Kšœ.˜.Kšœ˜—šžœ˜Kšœ'˜'šžœž˜šœ˜Kšœ"˜"Kšœ_˜_K˜—šœ˜Kšœ!˜!Kšœo˜oK˜—šœ˜Kšœ˜KšœZ˜ZK˜—šœ˜Kšœ)˜)Kšœa˜aK˜—šœ˜Kšœ*˜*Kšœb˜bK˜—Kšžœ)˜0—K˜—Kšœ˜K˜CKšžœ˜K˜—š œž œžœ žœžœžœžœžœžœžœžœžœ žœ˜«Kšœ@™@Kšœ@™@Kšœ#™#KšœF™FKšœH™HKšœ&™&Kšœ'™'Kšž˜Kšœ&˜&Kšœžœ˜K˜šΟbœ‘1œ˜LKšž˜šžœž˜ ˜Kšœžœ*˜?Kšœ(˜(KšœT˜TK˜—Kšžœž˜—Kšžœ˜—K˜Kšœ™Kšžœžœžœ˜!Kšžœ žœžœ'˜:Kšžœžœžœ˜ šžœž˜"Kšœ4˜4Kšžœžœ˜—Kšœ™Kšœžœ0˜;Kšœ-˜-Kšžœ˜—K˜K˜K˜Kšœ ™ K˜š  œž œ'žœžœžœžœ žœ˜jK™*Kšœ[™[KšœN™NKšž˜Kšœ žœ˜Kšœ žœ˜)Kšžœžœžœ˜šžœž˜"Kšœ4˜4Kšžœžœ˜—Kšœ!˜!šžœž˜!šœ˜Kšœ#˜#Kšœ7˜7Kšžœ žœ3žœžœ˜QKšžœžœžœ*˜:K˜—šœ˜Kšœ"˜"KšœE˜EKšžœžœžœ4˜DK˜—šœ˜Kšœ*˜*Kšœ7˜7Kšžœ žœ3žœžœ˜QKšžœžœžœ*˜:K˜—šœ‘˜Kšœ+˜+Kšœ7˜7Kšžœžœžœ*˜:Kšœ˜—šžœ‘˜Kšœ#˜#Kšœ7˜7Kšžœ žœ3žœžœ˜QKšžœžœžœ*˜:K˜——šžœžœžœ˜Kšžœ žœžœžœ*˜GK˜—Kšžœ˜K˜—K˜Kšœ™K˜š  œžœžœ žœžœžœžœ˜hKšž˜Kšžœžœ7žœ˜Pšž˜š žœžœžœžœ!žœžœž˜@˜3Kšžœ#žœ˜@—Kšžœ˜——Kšžœ˜K˜—š œžœžœžœžœžœ žœ˜SKšž˜Kšžœžœžœ˜#šžœ˜šœ˜Kšžœ žœžœ ˜ Kšžœžœžœžœ"˜MKšžœ˜—šžœ žœ˜šžœ1žœž˜@Kšœžœ˜)Kšœžœ,˜3Kšžœžœ˜—K˜—K˜—Kšžœ˜Kšžœ˜—K˜š œžœžœžœžœžœžœ žœ˜QKšž˜šžœžœž˜Kšœžœ ˜Kšœžœžœ ˜,Kš œžœžœ žœžœ ˜1Kšœžœ˜#Kšœ;˜;Kšœžœ'˜-Kšœžœ5˜=Kšœžœ˜Kšœžœ˜#šžœ˜ šžœ ž˜Kšžœ žœ˜˜Kš œ žœžœžœžœ˜+Kš œžœžœžœžœ˜Kšœ?˜?Kšžœ˜Kšœ&žœ˜-K˜—Kšžœ˜%———Kšžœ˜—K˜š  œžœžœžœžœ žœžœ˜QKšž˜Kš žœžœ žœžœžœžœ˜Bšžœ˜Kšœžœ˜Kšžœžœžœ˜$Kš žœ žœžœžœ žœ˜JKš žœžœžœ žœžœ žœ˜SK˜—Kšžœ˜—K˜K˜Kš‘™K˜Kšœ ž œ˜K˜š œžœžœ žœžœ žœžœžœ˜QKšžœžœžœ˜!šž˜Kšœ2˜2Kšžœžœžœžœ˜Kšžœ ˜ Kšž˜—K˜—K˜š œžœžœ žœ˜%Kšœ*˜*Jšž œ˜K˜—K˜š œžœžœžœ<žœ žœžœžœ žœžœžœ ž œ˜»Kšœ0™0Kšœ\™\KšœH™HKšœQ™QKšœa™aKšž˜šžœ˜Kšžœ˜—Kš œžœ žœžœžœ žœžœ˜:šžœ&žœ˜-Kšœ2˜2—šžœ˜Kšœ žœ'˜4KšœD˜DKšžœ žœžœžœ˜*Kšœ ˜ Kš žœ žœžœ žœ%žœ ž˜^KšœC˜CKšœ˜K˜—Kšžœ˜—K˜š’ œ˜"KšœI™Iš’œ’œ˜'Kšœ3™3Kšœžœ˜ š žœžœžœ žœ žœ˜.šžœ0žœž˜?Kšœ žœžœžœ˜)Kšžœžœ˜——Kšœ‘˜—Kšœ,˜,Kšœ˜—K˜š  œžœ˜Kšœ?˜?Kšœ=˜=Kšœ=˜=Kšœ/˜/Kšœ4˜4Kšœ3˜3Kšœ=˜=Kšœ7˜7Kšœ:˜:Kšœ4˜4Kšœ9˜9Kšœ:˜:Kšœ=˜=Kšœ@˜@K˜KšœG˜GKšœ?˜?KšœI˜IKšœ9˜9Kšœ=˜=Kšœ5˜5KšœC˜CKšœ=˜=Kšœ?˜?Kšœ?˜?KšœA˜AKšœ=˜=KšœI˜IKšœ˜—K˜Kšœ+˜+Kšœžœžœ ˜ Kšœ/˜/Kšœ ˜ Kšžœ˜K˜J˜—…—)Ύ=a