DIRECTORY BasicTime USING [GMT, nullGMT], FS USING [Error, FileInfo], MessageWindow USING [Append, Blink, Clear], NodeStyle USING [GetReal, RealParam, Ref, SetReal], NodeStyleFont USING [FontFromStyleParams], NodeStyleOps USING [Create, defaultStyle, defaultStyleName, FlushCaches, LoadStyle, OfStyle], NodeStyleValidate USING [], NodeStyleWorks USING [AddRealProc, ForceLowerName, get, LoadProc, Ops, OpsRec, Param, ParamRec, PercentProc, PopName, RegisterStyleCommand, run, SetNameProc, StoreProc, TryToPopName, TypeCheckDict, TypeCheckName], PrincOpsUtils USING [], Process USING [GetCurrent], RefTab USING [Create, Fetch, Pairs, Ref, Store], Rope USING [Concat, Equal, FromChar, ROPE], TextLooks USING [Look, Looks], TJaM USING [ABind, ACopy, AGet, APut, Array, AtomFromRope, AttachDict, Begin, ClrDict, CommandProc, CountStack, CvX, DetachAll, DetachDict, Dict, DictTop, End, Execute, 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 FS, MessageWindow, NodeStyle, NodeStyleFont, NodeStyleOps, NodeStyleWorks, Process, RefTab, Rope, 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] ~ { 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 ~ { 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]; IF styleName # NodeStyleOps.defaultStyleName THEN { TJaM.Push[frame, NodeStyleOps.defaultStyleName]; AttachStyleOp[frame]; }; EndStyleOp[frame]; }; [] _ RefTab.Store[fileForStyle, styleName, NEW [FileIDRep _ []]]; MessageWindow.Append[TJaM.RopeFromAtom[styleName], TRUE]; MessageWindow.Append[".style could not be loaded."]; MessageWindow.Blink[]; TJaM.Push[frame, styleName]; TJaM.PushRope[frame, "style was bad."]; StyleError[frame, 2]; }; 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] ~ { -- creates dict for style RETURN [TJaM.NewDict[50]]; }; EnterStyleDict: PROC [styleName: ATOM, d: Object, kind: OfStyle] ~ { TJaM.Put[stylesDicts[kind], styleName, d]; }; defaultSearch: LIST OF ROPE _ LIST["[]<>Commands>", "[]<>"]; FileID: TYPE ~ REF FileIDRep; FileIDRep: TYPE ~ RECORD [name: ROPE _ NIL, time: BasicTime.GMT _ BasicTime.nullGMT]; Same: PROC [a, b: FileID] RETURNS [BOOL] ~ { RETURN [a.time = b.time 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]; fileName: ROPE _ NIL; created: BasicTime.GMT _ BasicTime.nullGMT; WHILE fileName = NIL AND dirs # NIL DO [fullFName: fileName, created: created] _ FS.FileInfo[name: name, wDir: dirs.first ! FS.Error => CONTINUE]; dirs _ dirs.rest; ENDLOOP; IF fileName = NIL THEN RETURN [NIL]; RETURN [NEW[FileIDRep _ [fileName, created]]]; }; 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]; IF NOT RunStyle[frame, styleName] THEN BadStyleFile[frame, styleName]; FreeFrame[frame, NIL, screen]; changed _ TRUE; }; }; 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}; MessageWindow.Append["Using ", runNesting=0]; MessageWindow.Append[fileID.name, FALSE]; MessageWindow.Append[" . . . ", FALSE]; 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 MessageWindow.Append["ok ", FALSE]; IF ok THEN [] _ RefTab.Store[fileForStyle, styleName, fileID]; IF ok AND runNesting=0 THEN MessageWindow.Clear[]; }; 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]; } }; bindingDictName: PUBLIC ATOM; attachmentsDictName: PUBLIC ATOM; styledictName: PUBLIC ATOM; 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"] ]]; stylesDictsNames: PUBLIC REF ARRAY OfStyle OF ATOM _ NEW[ARRAY OfStyle OF ATOM]; 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] ~ { TJaM.ClrDict[dict]; TJaM.DetachAll[dict]; }; MakeDict: PROC [kind: OfStyle] RETURNS [dict: TJaM.Dict] ~ { dict _ CreateStyleDict[]; EnterStyleDict[name, dict, kind]; }; SetupDict: PROC [dict: TJaM.Dict, kind: OfStyle] ~ { 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; 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] }; 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]; WITH definition SELECT FROM x: TJaM.Array => TJaM.ABind[x, bindingDict]; ENDCASE; -- def may be a string definition _ TJaM.CvX[definition]; TJaM.Put[dict, name, definition]; -- save the definition IF name # styleRule THEN TJaM.Put[dict, styleRule, 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]]]]; }; 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]; }; 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 ~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, 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; }; ExecuteObject: PROC [frame: Frame, object: Object] RETURNS [ok: BOOL _ TRUE] ~ { initDepth: CARDINAL _ TJaM.CountStack[frame]; finalDepth: CARDINAL; TJaM.Execute[frame, object]; finalDepth _ TJaM.CountStack[frame]; IF finalDepth # initDepth THEN { TJaM.PushRope[frame, "Failed to leave stack at same depth after execution.\n"]; TJaM.Push[frame, object]; StyleError[frame, 2]; ok _ FALSE; }; }; ExecuteName: PUBLIC PROC [frame: Frame, name: ATOM] RETURNS [ok: BOOL] ~ { oldName: ATOM _ executingName; [ok, ] _ TJaM.TryToLoad[frame, name]; executingName _ name; IF ok THEN ok _ ExecuteObject[frame, name ! TJaM.Stop => {ok _ FALSE; CONTINUE}]; executingName _ oldName; }; ExecuteNameInStyle: PUBLIC PROC [ref: Ref, kind: OfStyle, styleRule: ATOM] RETURNS [ok: BOOL] ~ { styleName: ATOM _ ref.name[style]; frame: Frame _ GetFrame[ref, styleName, kind]; ok _ ExecuteName[frame, styleRule]; FreeFrame[frame, styleName, kind]; frame _ NIL; ref.font _ 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; }; FreeFrame[frame, styleName, kind]; frame _ NIL; ref.font _ NIL; }; ExecuteLooksInStyle: PUBLIC PROC [ref: Ref, kind: OfStyle, looks: TextLooks.Looks] RETURNS [ok: BOOL _ TRUE] ~ { styleName: ATOM _ ref.name[style]; frame: Frame _ GetFrame[ref, styleName, kind]; FOR c: CHAR IN TextLooks.Look DO IF looks[c] THEN ok _ ExecuteName[frame, lookNames[c]] ENDLOOP; FreeFrame[frame, styleName, kind]; frame _ NIL; ref.font _ NIL; IF nodeStyleFonts THEN { ref.font _ NodeStyleFont.FontFromStyleParams[prefix: ref.name[fontPrefix], family: ref.name[fontFamily], face: ref.fontFace, size: GetReal[ref, fontSize], alphabets: ref.fontAlphabets]; }; }; nodeStyleFonts: BOOL _ FALSE; executingName: PUBLIC ATOM _ NIL; lookNames: REF LookNames _ NEW[LookNames]; LookNames: TYPE ~ ARRAY TextLooks.Look OF ATOM; InitLookNames: PROC ~ { FOR c: CHAR IN TextLooks.Look DO lookNames[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 ~ { TJaM.Push[frame, p.opName]; TJaM.PushRope[frame, "illegal as qualifer for"]; TJaM.Push[frame, name]; 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, p.opName]; TJaM.PushRope[frame, "is not legal as value for"]; TJaM.Push[frame, ob]; StyleError[frame, 3]; }; AddRealError: PUBLIC AddRealProc ~ { TJaM.Push[frame, p.opName]; TJaM.PushRope[frame, "Numbers are illegal as values for"]; StyleError[frame, 2]; }; PercentError: PUBLIC PercentProc ~ { TJaM.Push[frame, p.opName]; TJaM.PushRope[frame, "Numbers are illegal as values for"]; StyleError[frame, 2]; }; SetNameError: PUBLIC SetNameProc ~ { TJaM.Push[frame, p.opName]; TJaM.PushRope[frame, "Only numbers are legal as values for"]; 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, p.opName]; TJaM.PushRope[frame, "illegal as value for"]; TJaM.Push[frame, name]; 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/100)*val]; }; glueOps: PUBLIC Ops _ NEW [OpsRec _ [GlueOpLoad, GlueOpSetReal, GlueOpAddReal, GlueOpPercent, SetNameError]]; GlueOpLoad: PUBLIC LoadProc ~ { Get: PROC [param: RealParam] ~ { 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] ~ { 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] ~ { 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] ~ { val: REAL _ GetReal[style, param]; SetReal[style, param, (percent/100)*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] ~ { 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] ~ { 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] ~ { 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] ~ { val: REAL _ GetReal[style, param]; SetReal[style, param, (percent/100)*val]; }; x: REF ParamRec.color ~ NARROW[p]; Set[x.hue]; Set[x.saturation]; Set[x.brightness]; }; RegisterWorks1: PUBLIC PROC [frame: Frame] ~ { InitLookNames[]; 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]; 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]; }; END. άNodeStyleWorks1Impl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Doug Wyatt, March 5, 1985 10:51:57 am PST Rick Beach, November 25, 1985 1:03:07 pm PST Michael Plass, May 6, 1986 5:29:07 pm PDT Russ Atkinson (RRA) August 8, 1985 1:09:13 am 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 (default) AttachStyle EndStyle" 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 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 Execute Styles Utility routine; ensures same stack depth after execution; 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 Rick Beach, November 25, 1985 1:01:05 pm PST changes to: RunStyle to force style filenames to be in the root directory Κl˜codešœ™Kšœ Οmœ7™BK™)K™,K™)K™1—K™šΟk ˜ Jšœ žœžœ ˜Jšžœžœ˜Jšœžœ˜+Jšœ žœ$˜3Jšœžœ˜*Jšœ žœK˜]Jšœžœ˜JšœžœΑ˜ΥJšœžœ˜Jšœžœ˜Jšœžœ$˜0Jšœžœžœ˜+Jšœ žœ˜JšœžœΓ˜ΝJšœ žœ˜!—K˜šΠblœžœž˜"Kšžœt˜{Kšžœ"˜)Kšœžœžœ˜'K˜—headšœ$™$K˜Kšžœžœžœ˜K˜Kšœžœ˜Kšœ žœ˜%Kšœžœ˜K˜Kšœžœ˜Kšœ žœžœ˜$Kšœžœžœ/˜KK˜š Οnœžœžœžœžœ˜]Kšœ9™9Kšœ2™2KšœC™CKšœžœ˜ š  œžœžœžœ˜7Kšžœžœžœ˜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šœ˜—š   œžœ žœ žœžœ ˜GKšœžœžœžœE˜WKšœžœ8˜BKšœ žœžœ˜Kšœžœ˜+š žœ žœžœžœž˜&Kšœ*žœ)žœ žœ˜kKšœ˜Kšžœ˜—Kš žœ žœžœžœžœ˜$Kšžœžœ#˜.Kšœ˜——™EKšœžœžœ˜'Kšœžœ˜Kšœž œ˜š œžœžœ žœ˜(Kšœžœ˜*š œžœžœ˜Kš žœžœžœžœžœ˜PKšœ;˜;Kšœ˜—š œžœžœ˜Kšœ$˜$Kšžœžœžœžœ˜JKšœ˜—Kšœ˜Kšœ žœ˜Kšœ ˜ Kšœ˜——šœ>™>šœ,˜,K˜—š  œžœžœžœ žœžœ˜?K™VK™#š œžœ˜š  œžœžœžœžœžœ˜=Kšžœžœžœ žœ˜2Kšžœžœ˜Kšœ˜—Kšœ(˜(Kšœ˜—Kšœ˜Kšœ˜K˜—š  œžœžœ žœžœ žœžœ˜PK™TK™#š œžœ˜Kšœ0˜0Kšœžœ,˜Fš žœ žœžœ žœžœ˜=Kšžœ ž˜šžœ˜Kšœžœžœ ˜*Kšžœžœžœ ˜FKšœžœ ˜Kšœ žœ˜Kšœ˜——Kšœ˜—Kšœ˜Kšœ˜K˜—Kšœ žœ‘-˜Hš œžœžœžœžœžœžœ˜Tš œžœ˜Kšœžœžœ˜ KšœW™WKšœ0˜0K˜7Kš žœ žœžœžœžœ˜*Kšœ-˜-Kšœ"žœ˜)Kšœ žœ˜'Kšœ˜Kšœ"˜"˜Kšœ žœ ˜Kšœžœžœ˜+Kšœžœžœ˜*Kšœžœžœ˜,Kšœ˜—Kšœ˜Kšœ žœ ˜Kšžœžœžœ˜.Kšžœžœ4˜>Kšžœžœžœ˜2Kšœ˜—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šœžœžœ˜Kšœžœžœ˜!šœžœžœ˜K˜—Kšœ žœ ˜Kšœžœ ˜"K˜Kšœ žœžœ žœžœžœžœ žœžœ˜^šœžœžœ žœžœžœžœ žœžœ˜MKšœ-˜-Kšœ/˜/Kšœ-˜-Kšœ˜—šœžœžœ žœžœžœžœ žœžœ˜HKšœ)˜)Kšœ+˜+Kšœ)˜)Kšœ˜—K˜Kšœž œžœ žœžœžœžœ žœžœ˜PK™CKšœž œžœ žœžœžœžœ žœžœ™OK˜Kš œ ž œžœ žœ žœžœ žœ ˜UK˜Kšœžœžœ‘,˜IKšœ žœžœ‘(˜CKš œ žœžœžœžœ‘,˜UK˜š  œ˜"Kšœžœžœ ‘˜NK˜+š  œžœ˜%Kšœ˜Kšœ˜Kšœ˜—š œžœžœ˜