DIRECTORY Atom USING [GetPName, MakeAtom], IO USING [PutFR], NodeStyle USING [GetReal, RealParam, Ref, SetReal], NodeStyleOps USING [Create, defaultStyleName, FlushCaches, OfStyle], NodeStyleValidate USING [], NodeStyleWorks USING [AddRealProc, ForceLowerName, LoadProc, Ops, OpsRec, Param, ParamRec, PercentProc, PopName, RegisterStyleCommand, run, SetNameProc, StoreProc, TryToPopName, TypeCheckDict, TypeCheckName, WhoIsExecuting], PFS USING [AbsoluteName, Error, FileInfo, nullUniqueID, PATH, PathFromRope, RopeFromPath, UniqueID], Process USING [GetCurrent], RefTab USING [Create, Fetch, Pairs, Ref, Store], Rope USING [Cat, Concat, Equal, FromChar, ROPE], SimpleFeedback USING [Append, Blink], Tioga USING [Look, Looks], TJaM USING [ABind, ACopy, AGet, Any, APut, Array, AtomFromAny, AtomFromRope, AttachDict, Begin, ClrDict, CommandProc, CountStack, CvX, DetachAll, DetachDict, Dict, DictLength, DictTop, End, Execute, ExecuteAtom, Frame, Load, NewArray, NewDict, NewFrame, Object, Pop, PopDict, PopReal, Push, PushInt, PushReal, PushRope, Put, Register, RopeFromAtom, Stop, TryToGet, TryToLoad], UserProfile USING [ListOfTokens]; NodeStyleWorks1Impl: CEDAR MONITOR IMPORTS Atom, PFS, IO, NodeStyle, NodeStyleOps, NodeStyleWorks, Process, RefTab, Rope, SimpleFeedback, TJaM, UserProfile EXPORTS NodeStyleWorks, NodeStyleValidate ~ BEGIN OPEN NodeStyle, NodeStyleWorks; ROPE: TYPE ~ Rope.ROPE; Frame: TYPE ~ TJaM.Frame; OfStyle: TYPE ~ NodeStyleOps.OfStyle; Object: TYPE ~ TJaM.Object; defaultFrame: PUBLIC Frame; FrameInfo: TYPE ~ REF FrameInfoBody; FrameInfoBody: TYPE ~ RECORD [ frame: Frame, style: Ref, rest: FrameInfo ]; GetFrame: PUBLIC PROC [style: Ref, styleName: ATOM, kind: OfStyle] RETURNS [frame: Frame] ~ { found: BOOL; AllocFrame: ENTRY PROC [name: ATOM, kind: OfStyle] ~ INLINE { ENABLE UNWIND => NULL; allocFrameCalls ฌ allocFrameCalls+1; IF name # NIL THEN { IF name = styleName1 AND kind = styleKind1 AND freeFrame1 # NIL THEN { frame ฌ freeFrame1; freeFrame1 ฌ NIL; RETURN }; IF name = styleName2 AND kind = styleKind2 AND freeFrame2 # NIL THEN { frame ฌ freeFrame2; freeFrame2 ฌ NIL; RETURN }; IF name = styleName3 AND kind = styleKind3 AND freeFrame3 # NIL THEN { frame ฌ freeFrame3; freeFrame3 ฌ NIL; RETURN }; IF name = styleName4 AND kind = styleKind4 AND freeFrame4 # NIL THEN { frame ฌ freeFrame4; freeFrame4 ฌ NIL; RETURN }}; IF freeFrame1 # NIL THEN { frame ฌ freeFrame1; freeFrame1 ฌ NIL } ELSE IF freeFrame2 # NIL THEN { frame ฌ freeFrame2; freeFrame2 ฌ NIL } ELSE IF freeFrame3 # NIL THEN { frame ฌ freeFrame3; freeFrame3 ฌ NIL } ELSE IF freeFrame4 # NIL THEN { frame ฌ freeFrame4; freeFrame4 ฌ NIL } ELSE { frame ฌ TJaM.NewFrame[]; frameAlloc ฌ frameAlloc+1; TJaM.Begin[frame, styledict]; }; }; SaveStyleInfo: ENTRY PROC ~ INLINE { ENABLE UNWIND => NULL; IF frame1 = NIL THEN { frame1 ฌ frame; style1 ฌ style } ELSE IF frame2 = NIL THEN { frame2 ฌ frame; style2 ฌ style } ELSE IF frame3 = NIL THEN { frame3 ฌ frame; style3 ฌ style } ELSE IF frame4 = NIL THEN { frame4 ฌ frame; style4 ฌ style } ELSE FOR lst: FrameInfo ฌ frameList, lst.rest UNTIL lst=NIL DO IF lst.frame = NIL THEN { lst.frame ฌ frame; lst.style ฌ style; EXIT }; REPEAT FINISHED => frameList ฌ NEW[FrameInfoBody ฌ [frame, style, frameList]]; ENDLOOP; }; AllocFrame[styleName, kind]; -- use styleName and kind as hint about which to allocate IF styleName # NIL THEN { styleNameObj: Object; done: BOOL ฌ FALSE; [found, styleNameObj] ฌ TJaM.TryToLoad[frame, styleDictName]; IF found THEN { -- some style dictionary on stack already IF TypeCheckName[styleNameObj] = styleName THEN { -- still must check kind of style kindNameObj: Object; [found, kindNameObj] ฌ TJaM.TryToLoad[frame, styleKindName]; IF found AND TypeCheckName[kindNameObj] = kindNames[kind] THEN done ฌ TRUE; }; -- already there IF NOT done THEN -- get rid of top dictionary WHILE TJaM.DictTop[frame] # styledict DO TJaM.End[frame]; ENDLOOP; }; IF NOT done THEN TJaM.Begin[frame, GetStyleDict[frame, styleName, kind]] } ELSE WHILE TJaM.DictTop[frame] # styledict DO TJaM.End[frame] ENDLOOP; SaveStyleInfo[]; }; FreeFrame: PUBLIC ENTRY PROC [frame: Frame, styleName: ATOM, kind: OfStyle] ~ { ENABLE UNWIND => NULL; freeFrameCalls ฌ freeFrameCalls+1; IF freeFrame1 = NIL THEN { freeFrame1 ฌ frame; styleName1 ฌ styleName; styleKind1 ฌ kind } ELSE IF freeFrame2 = NIL THEN { freeFrame2 ฌ frame; styleName2 ฌ styleName; styleKind2 ฌ kind } ELSE IF freeFrame3 = NIL THEN { freeFrame3 ฌ frame; styleName3 ฌ styleName; styleKind3 ฌ kind } ELSE IF freeFrame4 = NIL THEN { freeFrame4 ฌ frame; styleName4 ฌ styleName; styleKind4 ฌ kind } ELSE { frameFree ฌ frameFree+1; }; -- let garbage collector find it SELECT frame FROM frame1 => { frame1 ฌ NIL; style1 ฌ NIL }; frame2 => { frame2 ฌ NIL; style2 ฌ NIL }; frame3 => { frame3 ฌ NIL; style3 ฌ NIL }; frame4 => { frame4 ฌ NIL; style4 ฌ NIL }; ENDCASE => FOR lst: FrameInfo ฌ frameList, lst.rest UNTIL lst=NIL DO IF lst.frame = frame THEN { lst.frame ฌ NIL; lst.style ฌ NIL; EXIT }; ENDLOOP; }; frame1, frame2, frame3, frame4: Frame ฌ NIL; -- small cache of active frames frameAlloc: INT ฌ 0; -- number of frames allocated from TJaM frameFree: INT ฌ 0; -- number of frames freed by TJaM allocFrameCalls: INT ฌ 0; -- number of times called AllocFrame freeFrameCalls: INT ฌ 0; -- number of times called FreeFrame. should = allocFrameCalls style1, style2, style3, style4: Ref; -- style bodies associated with active frames 1,2,3,4 frameList: FrameInfo; -- chain of known frames beyond the small cache here freeFrame1, freeFrame2, freeFrame3, freeFrame4: Frame ฌ NIL; styleName1, styleName2, styleName3, styleName4: ATOM ฌ NIL; styleKind1, styleKind2, styleKind3, styleKind4: OfStyle ฌ screen; debugFlag: BOOL ฌ TRUE; debugStyle: Ref; StyleForFrame: PUBLIC PROC [frame: Frame] RETURNS [style: Ref] ~ { GetIt: ENTRY PROC RETURNS [s: Ref] ~ { ENABLE UNWIND => NULL; SELECT frame FROM frame1 => RETURN [style1]; frame2 => RETURN [style2]; frame3 => RETURN [style3]; frame4 => RETURN [style4]; ENDCASE => FOR lst: FrameInfo ฌ frameList, lst.rest UNTIL lst=NIL DO IF lst.frame=frame THEN RETURN [lst.style]; ENDLOOP }; IF (style ฌ GetIt[]) = NIL THEN { -- failed to find the frame IF debugFlag THEN { IF debugStyle = NIL THEN debugStyle ฌ NodeStyleOps.Create[]; RETURN [debugStyle]; }; ERROR; }; RETURN [style]; }; GetStyleDict: PUBLIC PROC [frame: Frame, styleName: ATOM, kind: OfStyle, def: ROPE ฌ NIL] RETURNS [d: TJaM.Dict] ~ { found, ok: BOOL; styleName ฌ ForceLowerName[styleName]; [d, found] ฌ CheckStyleDict[styleName, kind]; IF found THEN RETURN; ok ฌ IF def # NIL THEN RunStyleString[frame, styleName, def] ELSE RunStyle[frame, styleName]; IF ok THEN [d, found] ฌ CheckStyleDict[styleName, kind]; IF NOT found THEN { BadStyleFile[frame, styleName]; [d, found] ฌ CheckStyleDict[styleName, kind]; }; }; BadStyleFile: PUBLIC PROC [frame: Frame, styleName: ATOM] ~ { { ENABLE { WhatStyle => RESUME[styleName]; StartOfStyle => RESUME; EndOfStyle => RESUME; }; BeginStyleOp[frame, NIL]; IF styleName # NodeStyleOps.defaultStyleName THEN { TJaM.Push[frame, NodeStyleOps.defaultStyleName]; AttachStyleOp[frame, NIL]; }; EndStyleOp[frame, NIL]; }; [] ฌ RefTab.Store[fileForStyle, styleName, NEW [FileIDRep ฌ []]]; SimpleFeedback.Append[$Tioga, middle, $Error, " ... "]; SimpleFeedback.Append[$Tioga, middle, $Error, TJaM.RopeFromAtom[styleName]]; SimpleFeedback.Append[$Tioga, end, $Error, ".style could not be loaded. "]; SimpleFeedback.Blink[$Tioga, $Error]; }; CheckStyleDict: PROC [styleName: ATOM, kind: OfStyle] RETURNS [d: TJaM.Dict, found: BOOL] ~ { obj: Object; [found, obj] ฌ TJaM.TryToGet[stylesDicts[kind], styleName]; IF found THEN d ฌ TypeCheckDict[obj]; }; CreateStyleDict: PROC RETURNS [d: TJaM.Dict] ~ INLINE { -- creates dict for style RETURN [TJaM.NewDict[50]]; }; EnterStyleDict: PROC [styleName: ATOM, d: Object, kind: OfStyle] ~ INLINE { TJaM.Put[stylesDicts[kind], styleName, d]; }; dirStyles: ROPE ~ "/cedar/styles"; defaultSearch: LIST OF ROPE ฌ LIST[dirStyles]; FileID: TYPE ~ REF FileIDRep; FileIDRep: TYPE ~ RECORD [name: ROPE ฌ NIL, uid: PFS.UniqueID]; Same: PROC [a, b: FileID] RETURNS [BOOL] ~ INLINE { RETURN [a.uid = b.uid AND Rope.Equal[a.name, b.name, FALSE]] }; GetFileID: PROC [shortName: ATOM, extension: ROPE] RETURNS [FileID] ~ { dirs: LIST OF ROPE ฌ UserProfile.ListOfTokens["Tioga.StyleSearchRules", defaultSearch]; name: ROPE ~ Rope.Concat[TJaM.RopeFromAtom[shortName], extension]; fileNamePath: PFS.PATH ฌ NIL; uid: PFS.UniqueID ฌ PFS.nullUniqueID; WHILE fileNamePath = NIL AND dirs # NIL DO [fullFName: fileNamePath, uniqueID: uid] ฌ PFS.FileInfo[name: PFS.AbsoluteName[short: PFS.PathFromRope[name], wDir: PFS.PathFromRope[dirs.first] ] ! PFS.Error => CONTINUE]; dirs ฌ dirs.rest; ENDLOOP; IF fileNamePath = NIL THEN RETURN [NIL]; RETURN [NEW[FileIDRep ฌ [PFS.RopeFromPath[fileNamePath], uid]]]; }; styleLockProcess: UNSAFE PROCESS ฌ NIL; styleLockCount: CARDINAL ฌ 0; styleLockFree: CONDITION; DoLocked: PUBLIC PROC [action: PROC] ~ { me: UNSAFE PROCESS ~ Process.GetCurrent[]; Lock: ENTRY PROC ~ { UNTIL styleLockProcess = me OR styleLockCount = 0 DO WAIT styleLockFree ENDLOOP; styleLockProcess ฌ me; styleLockCount ฌ styleLockCount + 1; }; Unlock: ENTRY PROC ~ { styleLockCount ฌ styleLockCount - 1; IF styleLockCount = 0 THEN {styleLockProcess ฌ NIL; NOTIFY styleLockFree}; }; Lock[]; action[ ! UNWIND => Unlock[]]; Unlock[]; }; fileForStyle: RefTab.Ref ~ RefTab.Create[5]; ValidateStyles: PUBLIC PROC RETURNS [changed: BOOL ฌ FALSE] ~ { Locked: PROC ~ { Action: PROC [key: REF, val: REF] RETURNS [quit: BOOLEAN] ~ { IF ValidateStyle[NARROW[key]] THEN changed ฌ TRUE; RETURN [FALSE] }; [] ฌ RefTab.Pairs[fileForStyle, Action]; }; DoLocked[Locked]; }; ValidateStyle: PUBLIC PROC [styleName: ATOM] RETURNS [changed: BOOL ฌ FALSE] ~ { Locked: PROC ~ { fileID: FileID ~ GetFileID[styleName, ".style"]; oldFileID: FileID ~ NARROW[RefTab.Fetch[fileForStyle, styleName].val]; IF oldFileID = NIL OR fileID = NIL OR Same[fileID, oldFileID] THEN changed ฌ FALSE ELSE { frame: Frame ฌ GetFrame[NIL, NIL, screen]; changed ฌ TRUE; IF RunStyle[frame, styleName] THEN FreeFrame[frame, NIL, screen] ELSE BadStyleFile[frame, styleName]; }; }; DoLocked[Locked]; }; runNesting: CARDINAL ฌ 0; -- to decide whether to clear message window. RunStyle: PUBLIC PROC [frame: Frame, styleName: ATOM] RETURNS [ok: BOOL ฌ FALSE] ~ { Inner: PROC ~ { started, finished: BOOL ฌ FALSE; fileID: FileID ~ GetFileID[styleName, ".style"]; TJaM.Put[attachmentsDict, styleName, TJaM.NewArray[0]]; IF fileID = NIL THEN {ok ฌ FALSE; RETURN}; SimpleFeedback.Append[$Tioga, IF runNesting=0 THEN begin ELSE middle, $Progress, "Using "]; SimpleFeedback.Append[$Tioga, middle, $Progress, fileID.name]; SimpleFeedback.Append[$Tioga, middle, $Progress, " . . . "]; runNesting ฌ runNesting + 1; TJaM.PushRope[frame, fileID.name]; TJaM.Execute[frame, run ! WhatStyle => RESUME[styleName]; StartOfStyle => { started ฌ TRUE; RESUME }; EndOfStyle => { finished ฌ TRUE; RESUME }; TJaM.Stop => { finished ฌ FALSE; CONTINUE }; ]; runNesting ฌ runNesting - 1; ok ฌ started AND finished; IF ok THEN SimpleFeedback.Append[$Tioga, middle, $Progress, "ok "]; IF ok THEN [] ฌ RefTab.Store[fileForStyle, styleName, fileID]; IF ok AND runNesting=0 THEN SimpleFeedback.Append[$Tioga, end, $Progress, ""]; }; DoLocked[Inner]; }; RunStyleString: PUBLIC PROC [frame: Frame, styleName: ATOM, def: ROPE] RETURNS [ok: BOOL] ~ { started, finished: BOOL ฌ FALSE; TJaM.Put[attachmentsDict, styleName, TJaM.NewArray[0]]; TJaM.Execute[frame, TJaM.CvX[def] ! WhatStyle => { RESUME[styleName] }; StartOfStyle => { started ฌ TRUE; RESUME }; EndOfStyle => { finished ฌ TRUE; RESUME }; TJaM.Stop => { finished ฌ FALSE; CONTINUE }; ]; RETURN [started AND finished]; }; sysdict: PUBLIC TJaM.Dict; userdict: PUBLIC TJaM.Dict; styledict: PUBLIC TJaM.Dict; styleDictName: ATOM ~ TJaM.AtomFromRope["##styleDictName"]; styleKindName: ATOM ~ TJaM.AtomFromRope["##styleKindName"]; InitDict: PUBLIC PROC [name: ATOM, size: CARDINAL ฌ 100] RETURNS [dictionary: TJaM.Dict] ~ { found: BOOL; d: Object; [found, d] ฌ TJaM.TryToGet[sysdict, name]; IF found THEN dictionary ฌ TypeCheckDict[d] ELSE { dictionary ฌ TJaM.NewDict[size]; TJaM.Put[sysdict, name, dictionary]; } }; bindingDict: PUBLIC TJaM.Dict; attachmentsDict: PUBLIC TJaM.Dict; kindNames: REF ARRAY OfStyle OF ATOM ฌ NEW[ARRAY OfStyle OF ATOM ฌ [ $screen, $print, $base]]; styleRuleDictNames: REF ARRAY OfStyle OF ATOM ~ NEW[ARRAY OfStyle OF ATOM ฌ [ TJaM.AtomFromRope["##BaseStyleRuleDictName"], TJaM.AtomFromRope["##ScreenStyleRuleDictName"], TJaM.AtomFromRope["##PrintStyleRuleDictName"] ]]; styleDictNames: REF ARRAY OfStyle OF ATOM ~ NEW[ARRAY OfStyle OF ATOM ฌ[ TJaM.AtomFromRope["##BaseStyleDictName"], TJaM.AtomFromRope["##ScreenStyleDictName"], TJaM.AtomFromRope["##PrintStyleDictName"] ]]; stylesDicts: PUBLIC REF ARRAY OfStyle OF TJaM.Dict ฌ NEW[ARRAY OfStyle OF TJaM.Dict]; StartOfStyle: SIGNAL ~ CODE; -- raised to indicate start of loading style EndOfStyle: SIGNAL ~ CODE; -- raised to indicate successful loading WhatStyle: SIGNAL RETURNS [ATOM] ~ CODE; -- raised to find name of style being loaded BeginStyleOp: TJaM.CommandProc ~ { name: ATOM ฌ ForceLowerName[SIGNAL WhatStyle]; -- get style name from RunStyle screenDict, printDict, baseDict: TJaM.Dict; ResetDict: PROC [dict: TJaM.Dict] ~ INLINE { TJaM.ClrDict[dict]; TJaM.DetachAll[dict]; }; MakeDict: PROC [kind: OfStyle] RETURNS [dict: TJaM.Dict] ~ INLINE { dict ฌ CreateStyleDict[]; EnterStyleDict[name, dict, kind]; }; SetupDict: PROC [dict: TJaM.Dict, kind: OfStyle] ~ INLINE { TJaM.Put[baseDict, styleRuleDictNames[kind], TJaM.NewDict[50]]; TJaM.Put[dict, styleKindName, kindNames[kind]]; }; found: BOOL; [baseDict, found] ฌ CheckStyleDict[name, base]; -- check if reloading IF found THEN { ResetDict[baseDict]; [printDict, ] ฌ CheckStyleDict[name, print]; ResetDict[printDict]; [screenDict, ] ฌ CheckStyleDict[name, screen]; ResetDict[screenDict]; NodeStyleOps.FlushCaches[]; } ELSE { baseDict ฌ MakeDict[base]; screenDict ฌ MakeDict[screen]; printDict ฌ MakeDict[print]; }; SetupDict[baseDict, base]; SetupDict[screenDict, screen]; SetupDict[printDict, print]; TJaM.AttachDict[screenDict, baseDict]; TJaM.AttachDict[printDict, baseDict]; TJaM.Put[baseDict, styleDictNames[screen], screenDict]; TJaM.Put[baseDict, styleDictNames[print], printDict]; TJaM.Put[baseDict, styleDictNames[base], baseDict]; TJaM.Put[baseDict, styleDictName, name]; TJaM.Begin[frame, baseDict]; TJaM.Push[frame, baseDict]; -- leave this around for EndStyleOp SIGNAL StartOfStyle; -- caught by RunStyle }; EndStyleOp: TJaM.CommandProc ~ { d1, d2: TJaM.Dict ฌ NIL; d1 ฌ TJaM.DictTop[frame]; -- the current dictionary d2 ฌ TJaM.PopDict[frame]; -- pushed by StyleOp IF d1 # d2 THEN { TJaM.PushRope[frame, "mismatched Style and EndStyle commands"]; StyleError[frame, 1]; } ELSE { -- change attachments so look in own basicDict before any attached dicts name: ATOM ฌ SIGNAL WhatStyle; screenDict: TJaM.Dict ~ CheckStyleDict[name, screen].d; printDict: TJaM.Dict ~ CheckStyleDict[name, print].d; TJaM.DetachDict[screenDict, d1]; TJaM.DetachDict[printDict, d1]; TJaM.AttachDict[screenDict, d1]; TJaM.AttachDict[printDict, d1]; TJaM.End[frame]; }; SIGNAL EndOfStyle; -- caught by RunStyle }; StyleNameOp: TJaM.CommandProc ~ { -- expects style dictionary on op stack TJaM.Push[frame, TJaM.Load[frame, styleDictName]] }; StyleRuleOp: TJaM.CommandProc ~ { DefineStyleRule[frame, base] }; PrintRuleOp: TJaM.CommandProc ~ { DefineStyleRule[frame, print] }; ScreenRuleOp: TJaM.CommandProc ~ { DefineStyleRule[frame, screen] }; PutNew: PROC [frame: Frame, dict: TJaM.Dict, key: ATOM, val: TJaM.Any] ~ { IF RefTab.Fetch[dict.refTab, key].found THEN { TJaM.Push[frame, key]; TJaM.PushRope[frame, "is multiply defined"]; TJaM.PushInt[frame, 2]; TJaM.ExecuteAtom[frame, $ReportStyleError]; }; TJaM.Put[dict, key, val]; -- save the definition }; DefineStyleRule: PROC [frame: Frame, kind: OfStyle] ~ { definition: Object ฌ TJaM.Pop[frame]; comment: Object ฌ TJaM.Pop[frame]; styleRule: ATOM ฌ PopName[frame]; name: ATOM ฌ ForceLowerName[styleRule]; dict: TJaM.Dict ฌ LoadStyleDict[frame, kind]; styleName: ATOM ฌ TJaM.AtomFromAny[TJaM.Load[frame, styleDictName]]; WITH definition SELECT FROM x: TJaM.Array => TJaM.ABind[x, bindingDict]; ENDCASE; -- def may be a string definition ฌ TJaM.CvX[definition]; PutNew[frame, dict, name, definition]; -- save the definition IF name # styleRule THEN PutNew[frame, dict, styleRule, definition]; TJaM.Put[dict, Atom.MakeAtom[Rope.Cat[Atom.GetPName[styleName], ".", Atom.GetPName[name]]], definition]; -- save the definition TJaM.Put[LoadStyleRuleDict[frame, kind], name, comment]; -- save the comment in the rule name dict }; LoadStyleDict: PROC [frame: Frame, kind: OfStyle] RETURNS [TJaM.Dict] ~ { RETURN [TypeCheckDict[TJaM.Load[frame, styleDictNames[kind]]]]; }; LoadStyleRuleDict: PROC [frame: Frame, kind: OfStyle] RETURNS [TJaM.Dict] ~ { RETURN [TypeCheckDict[TJaM.Load[frame, styleRuleDictNames[kind]]]]; }; AttachStyleOp: TJaM.CommandProc ~ { -- expects opstk to contain style name as a rope name: ATOM ฌ ForceLowerName[PopName[frame]]; found: BOOL; printDict, screenDict: TJaM.Dict; array: TJaM.Array; styleName: ATOM ฌ SIGNAL WhatStyle; val: Object; [printDict, found] ฌ CheckStyleDict[name, print]; IF NOT found THEN { IF RunStyle[frame, name] THEN [printDict, found] ฌ CheckStyleDict[name, print]; IF NOT found THEN { BadStyleFile[frame, name]; RETURN; }; }; [screenDict, found] ฌ CheckStyleDict[name, screen]; IF NOT found THEN ERROR; TJaM.AttachDict[LoadStyleDict[frame, screen], screenDict]; TJaM.AttachDict[LoadStyleDict[frame, print], printDict]; [found, val] ฌ TJaM.TryToGet[attachmentsDict, styleName]; IF NOT found THEN array ฌ TJaM.NewArray[1] -- this is the first attachment ELSE { -- add new item to the array WITH val SELECT FROM x: TJaM.Array => array ฌ x; ENDCASE => ERROR; array ฌ TJaM.ACopy[array: array, expand: 1]; }; TJaM.APut[array, array.len-1, name]; TJaM.Put[attachmentsDict, styleName, array]; }; ForEachAttachedStyle: PUBLIC PROC [dictName: ATOM, proc: PROC [attached: ATOM] RETURNS [stop: BOOL]] ~ { val: Object; array: TJaM.Array; found: BOOL; dictName ฌ ForceLowerName[dictName]; [found, val] ฌ TJaM.TryToGet[attachmentsDict, dictName]; IF NOT found THEN RETURN; WITH val SELECT FROM x: TJaM.Array => array ฌ x; ENDCASE => ERROR; FOR i: CARDINAL IN [0..array.len) DO IF proc[TypeCheckName[TJaM.AGet[array, i]]] THEN RETURN; ENDLOOP; }; scratchDict: TJaM.Dict ฌ NIL; AllocProtectDict: ENTRY PROC RETURNS [protectDict: TJaM.Dict] ~ INLINE { ENABLE UNWIND => NULL; protectDict ฌ scratchDict; scratchDict ฌ NIL; IF protectDict = NIL THEN { Illegal: PROC [name: ROPE, nArgs: INT] ~ { ob: TJaM.Any ~ TJaM.CvX[IO.PutFR["(%g command not allowed in style rules) %g StyleError", [rope[name]], [integer[nArgs+1]]]]; TJaM.Put[dict: protectDict, key: Atom.MakeAtom[name], val: ob]; }; protectDict ฌ TJaM.NewDict[]; Illegal[".store", 2]; Illegal["PrintRule", 3]; Illegal["ScreenRule", 3]; Illegal["StyleParam", 2]; Illegal["StyleRule", 3]; }; }; FreeProtectDict: ENTRY PROC [protectDict: TJaM.Dict] ~ INLINE { scratchDict ฌ protectDict; }; ExecuteObject: PROC [frame: Frame, object: Object] RETURNS [ok: BOOL ฌ TRUE] ~ { initDepth: CARDINAL ฌ TJaM.CountStack[frame]; finalDepth: CARDINAL ฌ 0; protectDict: TJaM.Dict ฌ AllocProtectDict[]; beforeSize: INT ~ TJaM.DictLength[protectDict]; TJaM.Begin[frame: frame, dict: protectDict]; TJaM.Execute[frame, object]; finalDepth ฌ TJaM.CountStack[frame]; IF finalDepth # initDepth THEN { TJaM.Push[frame, object]; TJaM.PushRope[frame, "Failed to leave stack at same depth after execution."]; StyleError[frame, 2]; ok ฌ FALSE; }; IF TJaM.DictTop[frame] = protectDict AND TJaM.DictLength[protectDict] = beforeSize AND protectDict.attach = NIL THEN { TJaM.End[frame]; FreeProtectDict[protectDict] } ELSE { IF TJaM.DictTop[frame] = protectDict THEN TJaM.End[frame]; TJaM.Push[frame, object]; TJaM.PushRope[frame, "Illegally modified dictionary."]; StyleError[frame, 2]; ok ฌ FALSE; }; }; ExecuteName: PUBLIC PROC [frame: Frame, name: ATOM] RETURNS [ok: BOOL ฌ FALSE] ~ { ok ฌ ExecuteObject[frame, name ! TJaM.Stop => {ok ฌ FALSE; CONTINUE}; NodeStyleWorks.WhoIsExecuting => {RESUME[name]}; ]; }; ExecuteNameInStyle: PUBLIC PROC [ref: Ref, kind: OfStyle, styleRule: ATOM] RETURNS [ok: BOOL ฌ FALSE] ~ { styleName: ATOM ฌ ref.name[style]; frame: Frame ฌ GetFrame[ref, styleName, kind]; IF NOT TJaM.TryToLoad[frame, styleRule].found THEN { FreeFrame[frame, styleName, kind]; frame ฌ NIL; RETURN [ok: FALSE]; }; ok ฌ ExecuteName[frame, styleRule]; IF ok THEN FreeFrame[frame, styleName, kind]; frame ฌ NIL; }; ExecuteObjectInStyle: PUBLIC PROC [ref: Ref, kind: OfStyle, object: Object] RETURNS [ok: BOOL ฌ TRUE] ~ { styleName: ATOM ฌ ref.name[style]; frame: Frame ฌ GetFrame[ref, styleName, kind]; { ENABLE TJaM.Stop => GO TO stop; ok ฌ ExecuteObject[frame, TJaM.CvX[object]]; EXITS stop => ok ฌ FALSE; }; IF ok THEN FreeFrame[frame, styleName, kind]; frame ฌ NIL; }; ExecuteLooksInStyle: PUBLIC PROC [ref: Ref, kind: OfStyle, looks: Tioga.Looks] RETURNS [ok: BOOL ฌ TRUE] ~ { styleName: ATOM ฌ ref.name[style]; frame: Frame ฌ GetFrame[ref, styleName, kind]; FOR c: CHAR IN Tioga.Look DO IF looks[c] AND TJaM.TryToLoad[frame, lookNames[c]].found THEN ok ฌ ExecuteName[frame, lookNames[c]] AND ok ENDLOOP; IF ok THEN FreeFrame[frame, styleName, kind]; frame ฌ NIL; }; LookNames: TYPE ~ ARRAY Tioga.Look OF ATOM; lookNames: REF LookNames ฌ InitLookNames[]; InitLookNames: PROC RETURNS [names: REF LookNames] ~ --gfi saver-- INLINE { names ฌ NEW[LookNames]; FOR c: CHAR IN Tioga.Look DO names[c] ฌ TJaM.AtomFromRope[Rope.Concat["look.", Rope.FromChar[c]]]; ENDLOOP; }; StyleError: PUBLIC PROC [frame: Frame, num: INTEGER] ~ { TJaM.PushInt[frame, num]; TJaM.Execute[frame, $StyleError ! TJaM.Stop => CONTINUE]; }; DoStyleOp: PUBLIC PROC [frame: Frame, p: Param] ~ { aName: BOOL; name: ATOM; style: Ref ฌ StyleForFrame[frame]; Error: PROC ~ --gfi saver-- INLINE { TJaM.Push[frame, name]; TJaM.PushRope[frame, "illegal as qualifer for"]; TJaM.Push[frame, p.opName]; StyleError[frame, 3]; }; [name, aName] ฌ TryToPopName[frame]; IF NOT aName THEN p.ops.Store[frame, p, style] -- e.g., "10 pt leading" ELSE SELECT name FROM $the => p.ops.Load[frame, p, style]; -- e.g., "the leading" $bigger => { [name, aName] ฌ TryToPopName[frame]; IF NOT aName THEN p.ops.AddReal[frame, TJaM.PopReal[frame], p, style] ELSE IF name = $percent THEN p.ops.Percent[frame, 100+TJaM.PopReal[frame], p, style] ELSE { Error[]; RETURN }; }; $smaller => { [name, aName] ฌ TryToPopName[frame]; IF NOT aName THEN p.ops.AddReal[frame, -TJaM.PopReal[frame], p, style] ELSE IF name = $percent THEN p.ops.Percent[frame, 100-TJaM.PopReal[frame], p, style] ELSE { Error[]; RETURN }; }; $percent => p.ops.Percent[frame, TJaM.PopReal[frame], p, style]; ENDCASE => p.ops.SetName[frame, name, p, style]; -- e.g., "TimesRoman family" }; StoreError: PUBLIC StoreProc ~ { ob: Object ฌ TJaM.Pop[frame]; TJaM.Push[frame, ob]; TJaM.PushRope[frame, "is not legal as value for"]; TJaM.Push[frame, p.opName]; StyleError[frame, 3]; }; AddRealError: PUBLIC AddRealProc ~ { TJaM.PushRope[frame, "Numbers are illegal as values for"]; TJaM.Push[frame, p.opName]; StyleError[frame, 2]; }; PercentError: PUBLIC PercentProc ~ { TJaM.PushRope[frame, "Numbers are illegal as values for"]; TJaM.Push[frame, p.opName]; StyleError[frame, 2]; }; SetNameError: PUBLIC SetNameProc ~ { TJaM.PushRope[frame, "Only numbers are legal as values for"]; TJaM.Push[frame, p.opName]; StyleError[frame, 2]; }; nameOps: PUBLIC Ops ฌ NEW [OpsRec ฌ [LoadNameParam, StoreError, AddRealError, PercentError, SetNameParam]]; LoadNameParam: PUBLIC LoadProc ~ { TJaM.Push[frame, style.name[NARROW[p, REF ParamRec.name].param]]; }; SetNameParam: PUBLIC SetNameProc ~ { style.name[NARROW[p, REF ParamRec.name].param] ฌ name; }; NameError: PUBLIC PROC [frame: Frame, name: ATOM, p: Param] ~ { TJaM.Push[frame, name]; TJaM.PushRope[frame, "illegal as value for"]; TJaM.Push[frame, p.opName]; StyleError[frame, 3]; }; realOps: PUBLIC Ops ฌ NEW [OpsRec ฌ [RealOpLoad, RealOpSetReal, RealOpAddReal, RealOpPercent, SetNameError]]; RealOpLoad: PUBLIC LoadProc ~ { TJaM.PushReal[frame, GetReal[style, NARROW[p, REF ParamRec.real].param]]}; RealOpSetReal: PUBLIC StoreProc ~ { SetReal[style, NARROW[p, REF ParamRec.real].param, TJaM.PopReal[frame]]}; RealOpAddReal: PUBLIC AddRealProc ~ { x: REF ParamRec.real ~ NARROW[p]; SetReal[style, x.param, GetReal[style, x.param]+inc]}; RealOpPercent: PUBLIC PercentProc ~ { val: REAL ฌ GetReal[style, NARROW[p, REF ParamRec.real].param]; SetReal[style, NARROW[p, REF ParamRec.real].param, (percent*0.01)*val]; }; glueOps: PUBLIC Ops ฌ NEW [OpsRec ฌ [GlueOpLoad, GlueOpSetReal, GlueOpAddReal, GlueOpPercent, SetNameError]]; GlueOpLoad: PUBLIC LoadProc ~ { Get: PROC [param: RealParam] ~ --gfi saver-- INLINE { TJaM.PushReal[frame, GetReal[style, param]] }; x: REF ParamRec.glue ~ NARROW[p]; Get[x.size]; Get[x.stretch]; Get[x.shrink]; }; GlueOpSetReal: PUBLIC StoreProc ~ { Set: PROC [param: RealParam] ~ --gfi saver-- INLINE { SetReal[style, param, TJaM.PopReal[frame]] }; x: REF ParamRec.glue ~ NARROW[p]; Set[x.shrink]; Set[x.stretch]; Set[x.size]; }; GlueOpAddReal: PUBLIC AddRealProc ~ { Add: PROC [param: RealParam] ~ --gfi saver-- INLINE { SetReal[style, param, GetReal[style, param]+inc] }; x: REF ParamRec.glue ~ NARROW[p]; Add[x.size]; Add[x.stretch]; Add[x.shrink]; }; GlueOpPercent: PUBLIC PercentProc ~ { Set: PROC [param: RealParam] ~ --gfi saver-- INLINE { val: REAL ฌ GetReal[style, param]; SetReal[style, param, (percent*0.01)*val]; }; x: REF ParamRec.glue ~ NARROW[p]; Set[x.size]; Set[x.stretch]; Set[x.shrink]; }; colorOps: PUBLIC Ops ฌ NEW [OpsRec ฌ [ColorOpLoad, ColorOpSetReal, ColorOpAddReal, ColorOpPercent, SetNameError]]; ColorOpLoad: PUBLIC LoadProc ~ { Get: PROC [param: RealParam] ~ --gfi saver-- INLINE { TJaM.PushReal[frame, GetReal[style, param]]; }; x: REF ParamRec.color ~ NARROW[p]; Get[x.hue]; Get[x.saturation]; Get[x.brightness]; }; ColorOpSetReal: PUBLIC StoreProc ~ { Set: PROC [param: RealParam] ~ --gfi saver-- INLINE { SetReal[style, param, TJaM.PopReal[frame]]; }; x: REF ParamRec.color ~ NARROW[p]; Set[x.brightness]; Set[x.saturation]; Set[x.hue]; }; ColorOpAddReal: PUBLIC AddRealProc ~ { Add: PROC [param: RealParam] ~ --gfi saver-- INLINE { SetReal[style, param, GetReal[style, param]+inc]; }; x: REF ParamRec.color ~ NARROW[p]; Add[x.hue]; Add[x.saturation]; Add[x.brightness]; }; ColorOpPercent: PUBLIC PercentProc ~ { Set: PROC [param: RealParam] ~ --gfi saver-- INLINE { val: REAL ฌ GetReal[style, param]; SetReal[style, param, (percent*0.01)*val]; }; x: REF ParamRec.color ~ NARROW[p]; Set[x.hue]; Set[x.saturation]; Set[x.brightness]; }; RegisterWorks1: PUBLIC PROC [frame: Frame] ~ { RegisterStyleCommand[frame, $BeginStyle, BeginStyleOp]; RegisterStyleCommand[frame, $EndStyle, EndStyleOp]; RegisterStyleCommand[frame, $StyleRule, StyleRuleOp]; RegisterStyleCommand[frame, $PrintRule, PrintRuleOp]; RegisterStyleCommand[frame, $ScreenRule, ScreenRuleOp]; RegisterStyleCommand[frame, $AttachStyle, AttachStyleOp]; TJaM.Register[frame, $StyleName, StyleNameOp]; }; END. ๐ NodeStyleWorks1Impl.mesa Copyright ำ 1985, 1986, 1987, 1988, 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Rick Beach, November 25, 1985 1:03:07 pm PST Michael Plass, September 24, 1991 2:06 pm PDT Russ Atkinson (RRA) August 8, 1985 1:09:13 am PDT Spreitze, July 9, 1990 5:03 pm PDT Willie-s, June 27, 1991 10:45 am PDT Doug Wyatt, October 19, 1993 1:16 pm PDT Execution Frames for Style Machinery -- style is the StyleRef you will be using with the frame -- styleName tells which style dictionary you want -- will give you default style if requested style bombs during load -- first try to find one that already has the right style -- look for any free one get the proper style dictionary on the frame dictionary stack name and kind are just a hint about what style dictionary is on the frame stack add it to cache of free frames or really free it if cache full remove it from active frame info Style Dictionaries fake it so looks as if had a file saying "BeginStyle (Cedar) AttachStyle EndStyle" TJaM.Push[frame, styleName]; TJaM.PushRope[frame, "style was bad."]; StyleError[frame, 2]; Style File handling. Search rule handling Locking to avoid concurrent changes to internal style representation. Running styles and validation of style to file correspondence. Called from elsewhere in Tioga when something changes that may have changed any style. Does not attempt to refresh screen. Called from elsewhere in Tioga when something changes that may have changed a style. Does not attempt to refresh screen. this is probably where the use of working directories for style files needs to be added bindingDictName: PUBLIC ATOM; -- removed by mfp November 19, 1987 attachmentsDictName: PUBLIC ATOM; -- removed by mfp November 19, 1987 styledictName: PUBLIC ATOM; -- removed by mfp November 19, 1987 stylesDictsNames: PUBLIC REF ARRAY OfStyle OF ATOM _ NEW[ARRAY OfStyle OF ATOM]; -- not used; removed by mfp November 19, 1987 is the following redundant? I think so, so I commented it out. RJB stylesDictNames: PUBLIC REF ARRAY OfStyle OF ATOM _ NEW[ARRAY OfStyle OF ATOM]; create rule name dict in baseDict record the style kind expects on op stack OpenPrintStyleOp: TJaM.CommandProc ~ { -- expects style name on op stack OpenStyle[frame, print]; }; OpenScreenStyleOp: TJaM.CommandProc ~ { -- expects style name on op stack OpenStyle[frame, screen]; }; OpenStyle: PROC [frame: Frame, kind: OfStyle] ~ { name: ATOM _ PopName[frame]; IF NOT NodeStyleOps.LoadStyle[name] THEN RETURN; WHILE TJaM.DictTop[frame] # sysdict DO TJaM.End[frame]; ENDLOOP; TJaM.Begin[frame, styledict]; TJaM.Begin[frame, GetStyleDict[frame, name, kind]]; }; ResetTestStyleOp: TJaM.CommandProc ~ { IF debugStyle=NIL THEN debugStyle _ NodeStyleOps.Create[]; debugStyle^ _ NodeStyleOps.defaultStyle^; }; StyleRuleDictOp: TJaM.CommandProc ~ { GetRuleDict[frame, base] }; PrintRuleDictOp: TJaM.CommandProc ~ { GetRuleDict[frame, print] }; ScreenRuleDictOp: TJaM.CommandProc ~ { GetRuleDict[frame, screen] }; GetRuleDict: PROC [frame: Frame, kind: OfStyle] ~ { TJaM.Push[frame, styleRuleDictNames[kind]]; TJaM.Execute[frame, get]; }; Execute Styles Utility routine; ensures same stack depth after execution; protects against defs; does NOT handle TJaM.Stop makes sure that same stack depth after execute makes sure that same stack depth after execute makes sure that same stack depth after execute makes sure that same stack depth after execute names are "look.a", "look.b", "look.c", etc. Implementing Style Attribute Operations -- e.g., "2 pt bigger leading" -- e.g., "2 percent bigger leading" -- e.g., "2 pt smaller leading" -- e.g., "2 percent smaller leading" General Error Routines Name Parameter Operations Real Parameter Operations Glue Parameter Operations Color Parameter Operations Initialization register the various style commands and JaM commands in this module -- the following don't seem to be documented or used, so I removed them - mfp TJaM.Register[frame, $OpenPrintStyle, OpenPrintStyleOp]; TJaM.Register[frame, $OpenScreenStyle, OpenScreenStyleOp]; TJaM.Register[frame, $ResetTestStyle, ResetTestStyleOp]; TJaM.Register[frame, $StyleRuleDict, StyleRuleDictOp]; TJaM.Register[frame, $PrintRuleDict, PrintRuleDictOp]; TJaM.Register[frame, $ScreenRuleDict, ScreenRuleDictOp]; ส#˜–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ฯeœ[™fK™,K™-K™1K™"K™$K™(K™—šฯk ˜ Kšœžœ˜ Kšžœžœ ˜Kšœ žœ$˜3Kšœ žœ2˜DKšœžœ˜Kšœžœฬ˜เKšžœžœ/žœ(˜dKšœžœ˜Kšœžœ$˜0Kšœžœ žœ˜0Kšœžœ˜%Kšœžœ˜Kšœžœ๎˜๘Kšœ žœ˜!—K˜šะblœžœž˜"Kšžœžœžœc˜xKšžœ"˜)Kšœžœžœ˜'K˜—headšœ$™$K˜Kšžœžœžœ˜K˜Kšœžœ˜Kšœ žœ˜%Kšœžœ˜K˜Kšœžœ˜Kšœ žœžœ˜$Kšœžœžœ/˜KK˜š ฯnœžœžœžœžœ˜]Kšœ9™9Kšœ2™2KšœC™CKšœžœ˜ š   œžœžœžœžœ˜>Kšžœžœžœ˜K˜$šžœžœžœ˜Kšœ:™:š žœžœžœžœž˜DKšœ#žœžœ˜1—š žœžœžœžœž˜DKšœ#žœžœ˜1—š žœžœžœžœž˜DKšœ#žœžœ˜1—š žœžœžœžœž˜DKšœ#žœžœ˜2——Kšœ™Kšžœžœžœ$žœ˜AKš žœžœžœžœ$žœ˜FKš žœžœžœžœ$žœ˜FKš žœžœžœžœ$žœ˜Fšžœ˜Kšœ˜K˜K˜K˜—K˜—š  œžœžœžœ˜$Kšžœžœžœ˜Kšžœ žœžœ#˜7Kšžœžœ žœžœ#˜Kšžœ žœžœ)žœ˜GKšžœžœžœ,˜NKšžœ˜—Kšœ˜—Kšœฯc9˜Všžœ žœžœ˜Kšœ=™=K˜Kšœžœžœ˜K˜=šžœžœก)˜9šžœ)žœก!˜SK˜K˜<šžœžœ.ž˜>Kšœžœ˜ —Kšœก˜—šžœžœžœก˜-šžœ!ž˜(Kšœžœ˜——Kšœ˜—Kšžœžœžœ8˜HKšœ˜—Kšžœžœ!žœžœ˜FK˜K˜—K˜š   œžœžœžœžœ˜OKšœO™OKšžœžœžœ˜K˜"Kšœ>™>šžœžœžœ˜Kšœ?˜?—šžœžœžœžœ˜Kšœ?˜?—šžœžœžœžœ˜ K˜?—šžœžœžœžœ˜K˜?—Kšžœก ˜CKšœ ™ šžœž˜Kšœžœ žœ˜)Kšœžœ žœ˜)Kšœžœ žœ˜)Kšœžœ žœ˜)š žœžœ&žœžœž˜DKš žœžœžœžœžœ˜EKšžœ˜——K˜—K˜Kšœ(žœก˜LKšœ žœก'˜Kšœžœก=˜VKšœ&ก5˜[Kšœก4˜KK˜Kšœ8žœ˜™>šœ,˜,K˜—š  œžœžœžœ žœžœ˜?K™VK™#š œžœ˜š  œžœžœžœžœžœ˜=Kšžœžœžœ žœ˜2Kšžœžœ˜Kšœ˜—Kšœ(˜(Kšœ˜—Kšœ˜Kšœ˜K˜—š  œžœžœ žœžœ žœžœ˜PK™TK™#š œžœ˜Kšœ0˜0Kšœžœ,˜Fš žœ žœžœ žœžœ˜=Kšžœ ž˜šžœ˜Kšœžœžœ ˜*Kšœ žœ˜Kšžœžœžœ žœ ˜eKšœ˜——Kšœ˜—Kšœ˜Kšœ˜K˜—Kšœ žœก-˜Hš œžœžœžœžœžœžœ˜Tš œžœ˜Kšœžœžœ˜ KšœW™WKšœ0˜0K˜7Kš žœ žœžœžœžœ˜*Kšœžœžœžœ˜[Kšœ>˜>Kšœ<˜Kšžœžœžœ3˜NKšœ˜—Kšœ˜Kšœ˜K˜—š œžœžœžœžœžœžœ˜]Kšœžœžœ˜ K˜7šœ$˜$Kšœžœ˜#Kšœžœžœ˜+Kšœžœžœ˜*Kšœžœžœ˜,Kšœ˜—Kšžœ žœ ˜Kšœ˜—K˜—Kšœ žœ ˜Kšœ žœ ˜Kšœ žœ ˜K˜Kšœžœ(˜;Kšœžœ(˜;K˜š  œžœžœžœžœžœ˜\Kšœžœ˜ K˜ K˜*Kšžœžœ˜+šžœ˜Kšœ ˜ K˜$K˜—K˜K˜—Kšœžœžœ&™BKšœžœžœ&™Fšœžœžœ&™@K˜—Kšœ žœ ˜Kšœžœ ˜"K˜Kšœ žœžœ žœžœžœžœ žœžœ˜^šœžœžœ žœžœžœžœ žœžœ˜MKšœ-˜-Kšœ/˜/Kšœ-˜-Kšœ˜—šœžœžœ žœžœžœžœ žœžœ˜HKšœ)˜)Kšœ+˜+Kšœ)˜)Kšœ˜—K˜Kšœž œžœ žœžœžœžœ žœžœ1™K™CKšœž œžœ žœžœžœžœ žœžœ™OK˜Kš œ ž œžœ žœ žœžœ žœ ˜UK˜Kšœžœžœก,˜IKšœ žœžœก(˜CKš œ žœžœžœžœก,˜UK˜š  œ˜"Kšœžœžœ ก˜NK˜+š  œžœžœ˜,Kšœ˜Kšœ˜Kšœ˜—š œžœžœžœ˜CK˜K˜!K˜—š  œžœ$žœ˜;K˜?Kšœ!™!K˜/Kšœ™K˜—Kšœžœ˜ Kšœ0ก˜Ešžœ˜šžœ˜K˜K˜,K˜K˜.K˜K˜K˜—šžœ˜K˜K˜K˜K˜——K˜VK˜&K˜%K˜7K˜5K˜3K˜(K˜Kšœก#˜?Kšžœก˜*Kšœ˜K˜—š  œ˜ Kšœžœ˜Kšœก˜3Kšœก˜.šžœ˜ šžœ˜K˜?K˜K˜—šžœกH˜OKšœžœžœ ˜K˜7K˜5K˜ K˜K˜ K˜K˜K˜——Kšžœ ก˜(Kšœ˜K˜—š  œก'˜IKšœ1˜1K˜K˜—K˜š  œ6˜AK˜—š  œ7˜BK˜—Kš  œ8˜DK˜•StartOfExpansion1[dict: TJaM.Dict, key: ATOM, val: TJaM.Any]š œžœ&žœ˜Jšžœ&žœ˜.Kšœ˜Kšœ,˜,Kšœ˜Kšœ+˜+Kšœ˜—Kšœก˜0Kšœ˜K˜—š œžœ"˜7Kšœ1™1K˜%K˜"Kšœ žœ˜!Kšœžœ˜'K˜-Kšœ žœ5˜Dšžœ žœž˜K˜,Kšžœก˜—Kšœ"˜"Kšœ'ก˜=Kšžœžœ,˜DKšœiก˜Kšœ9ก)˜bK˜K˜—š  œžœžœ˜IKšžœ9˜?Kšœ˜K˜—š œžœžœ˜MKšžœ=˜CKšœ˜K˜—š œก!™HK™K™K™—š œก!™IK™K™K™—š  œžœ"™1Kšœžœ™Kšžœžœžœžœ™0Kšžœžœžœ™@K™K™3K™K™—š œ™'Kšžœ žœžœ$™:Kšœ)™)K™—K˜š œ2™AK™—š œ3™BK™—Kš œ4™DK˜š  œžœ"™3K™+K™K™K™—š  œก0˜TKšœžœ"˜,Kšœžœ˜ K˜!K˜Kšœ žœžœ ˜#K˜ K˜1šžœžœžœ˜Kšžœžœ2˜Ošžœžœžœ˜K˜Kšžœ˜Kšœ˜—Kšœ˜—K˜3Kšžœžœžœžœ˜K˜:K˜8K˜9Kšžœžœžœก˜Jšžœก˜#šžœžœž˜K˜Kšžœžœ˜—K–([array: TJaM.Array, expand: INT _ 0]˜,K˜—K˜$K˜,K˜K˜—š œžœžœ žœžœ žœžœžœ˜hK˜ K˜Kšœžœ˜ K˜$K˜8Kšžœžœžœžœ˜šžœžœž˜K˜Kšžœžœ˜—šžœžœžœž˜$Kšžœ*žœžœ˜8Kšžœ˜—K˜K˜——™Kšœžœ˜š  œžœžœžœžœ˜HKšžœžœžœ˜Kšœ)žœ˜-šžœžœžœ˜š œžœžœ žœ˜*Kšœ}˜}K–1[dict: TJaM.Dict, key: ATOM, val: TJaM.Any]šœ?˜?Kšœ˜—Kšœ˜Kšœ˜K–1[dict: TJaM.Dict, key: ATOM, val: TJaM.Any]šœ˜K–1[dict: TJaM.Dict, key: ATOM, val: TJaM.Any]šœ˜K–1[dict: TJaM.Dict, key: ATOM, val: TJaM.Any]šœ˜K–1[dict: TJaM.Dict, key: ATOM, val: TJaM.Any]šœ˜Kšœ˜—Kšœ˜K˜—š œžœžœžœ˜?Kšœ˜Kšœ˜K˜—š   œžœ žœžœžœ˜PKšกbœ ™kKšœ žœ˜-Kšœ žœ˜Kšœ,˜,K–([frame: TJaM.Frame, dict: TJaM.Dict]šœ žœ ˜/Kšœ,˜,Kšœ˜Kšœ$˜$šžœžœ˜ Kšœ˜K˜MKšœ˜Kšœžœ˜ Kšœ˜—šžœ#žœ+žœž˜oKšžœ2˜6šžœ˜Kšžœ#žœ˜:Kšœ˜K˜7Kšœ˜Kšœžœ˜ Kšœ˜——šœ˜K˜——š  œžœžœžœžœžœžœ˜RKšก.™.šœ ˜ Kšœžœžœ˜$Kšœ"žœ˜0Kšœ˜—šœ˜K˜——š œžœžœ&žœžœžœžœ˜iKšก.™.Kšœ žœ˜"Kšœ.˜.šžœžœ(žœ˜4Kšœ+žœ˜/Kšžœžœ˜Kšœ˜—Kšœ#˜#Kšžœžœ#˜-Kšœžœ˜ šœ˜K˜——š  œžœžœ+žœžœžœ˜iKšก.™.Kšœ žœ˜"Kšœ.˜.˜Kšžœžœžœ˜Kšœ,˜,Kšžœžœ˜K˜—Kšžœžœ#˜-Kšœžœ˜ šœ˜K˜——š  œžœžœ/žœžœžœ˜lKšก.™.Kšœ žœ˜"Kšœ.˜.šžœžœžœ ž˜Kšžœ žœ+žœ'žœ˜kKšžœ˜—Kšžœžœ#˜-Kšœžœ˜ šœ˜K˜——Kš œ žœžœ žœžœ˜,šœ žœ˜+š   œžœžœ žœก œžœ˜KKšก,™,Kšœžœ ˜šžœžœžœ ž˜KšœE˜EKšžœ˜—Kšœ˜——K˜š  œžœžœžœ˜8Kšœ˜Kšœ/žœ˜9Kšœ˜K˜——™'K˜š  œž œ˜3Kšœžœ˜ Kšœžœ˜ K˜"š œžœก œžœ˜$K˜K˜0K˜K˜K˜—K˜$Kšžœžœžœก˜Gšžœžœž˜Kšœ%ก˜;šœ ˜ Kšœ$˜$šžœžœžœ4˜EKšœ™—šžœžœžœ8˜TKšœ#™#—Kšžœ žœ˜Kšœ˜—šœ ˜ Kšœ$˜$šžœžœžœ5˜FKšœ™—šžœžœžœ8˜TKšœ$™$—Kšžœ žœ˜Kšœ˜—Kšœ@˜@Kšžœ*ก˜M—K˜K˜——šœ™K˜š  œžœ˜ K˜K˜K˜2K˜K˜K˜K˜—š  œžœ˜%K˜:K˜K˜K˜K˜—š  œžœ˜%K˜:K˜K˜K˜K˜—š  œžœ˜%K˜=K˜K˜K˜K˜——šœ™K˜Kšœ žœžœR˜kK˜š  œžœ ˜"Kšœžœžœ˜Ašœ˜K˜——š  œžœ˜$Kšœ žœžœ˜6Kšœ˜—K˜š  œžœžœžœ˜?K˜K˜-K˜K˜K˜K˜——šœ™K˜Kšœ žœžœT˜mK˜š  œžœ ˜šœ$žœžœ˜JK˜——š  œžœ˜#šœžœžœ-˜IK˜——š  œžœ˜%Kšœžœžœ˜!šœ6˜6K˜——š  œžœ˜%Kšœžœžœžœ˜?Kšœžœžœ+˜GKšœ˜K˜——šœ™K˜Kšœ žœžœT˜mK˜š  œžœ ˜š œžœก œžœ˜5Kšœ.˜.—Kšœžœžœ˜!Kšœ+˜+šœ˜K˜——š  œžœ˜#š œžœก œžœ˜5K˜-—Kšœžœžœ˜!Kšœ+˜+šœ˜K˜——š  œžœ˜%š œžœก œžœ˜5K˜3—Kšœžœžœ˜!Kšœ+˜+šœ˜K˜——š  œžœ˜%š œžœก œžœ˜5Kšœžœ˜"K˜*K˜—Kšœžœžœ˜!Kšœ+˜+šœ˜K˜———šœ™K˜Kšœ žœžœX˜rK˜š  œžœ ˜ š œžœก œžœ˜5Kšœ,˜,K˜—Kšœžœžœ˜"Kšœ1˜1šœ˜K˜——š œžœ˜$š œžœก œžœ˜5K˜+K˜—Kšœžœžœ˜"Kšœ1˜1šœ˜K˜——š œžœ˜&š œžœก œžœ˜5K˜1K˜—Kšœžœžœ˜"Kšœ1˜1šœ˜K˜——š œžœ˜&š œžœก œžœ˜5Kšœžœ˜"K˜*K˜—Kšœžœžœ˜"Kšœ1˜1Kšœ˜K˜——™K˜š œžœžœ˜.KšœC™CKšœ7˜7Kšœ3˜3Kšœ5˜5Kšœ5˜5Kšœ7˜7Kšœ9˜9K˜.™MK™8K™:K™8K™6K™6K™8—K˜——K™Kšžœ˜K™—…—jฎŸ6