DIRECTORY Ascii USING [Lower], Atom USING [GetPName, MakeAtom], Checksum USING [ComputeChecksum], Convert USING [RopeFromInt], EditNotify USING [AddNotifyProc, Change, ChangeSet], NodeProps USING [CopyInfoProc, GetProp, Register], NodePropsExtras USING [Is], NodeStyle USING [DataEntry, DataList, GetStyleName, IntegerValue, MaxNestingLevel, RealCode, Ref, SetReal, StyleBody], NodeStyleOps USING [ExtObjPair, LocalStyle, LocalStyleRec, OfStyle], NodeStyleWorks USING [BadStyleFile, ExecuteLooksInStyle, ExecuteNameInStyle, ExecuteObjectInStyle, FreeFrame, GetFrame, GetStyleDict, RunStyle, StyleParamKey], Rope USING [Cat, Concat, ROPE, Translate], TextLooks USING [Looks, noLooks], TextNode USING [FirstChild, Level, Next, Parent, Ref], TJaM USING [Frame, NumberRep, Object, TryToLoad]; NodeStyleOpsImpl: CEDAR MONITOR IMPORTS Ascii, Atom, Checksum, Convert, EditNotify, NodeProps, NodePropsExtras, NodeStyle, NodeStyleWorks, Rope, TextNode, TJaM EXPORTS NodeStyleOps ~ BEGIN OPEN NodeStyle, NodeStyleOps; ROPE: TYPE ~ Rope.ROPE; Frame: TYPE ~ TJaM.Frame; Object: TYPE ~ TJaM.Object; Create: PUBLIC PROC RETURNS [Ref] ~ { RETURN [NEW[StyleBody]]; }; Copy: PUBLIC PROC [dest, source: Ref] ~ { dest^ _ source^; }; Alloc: PUBLIC ENTRY PROC RETURNS [s: Ref] ~ { ENABLE UNWIND => NULL; IF s3 # NIL THEN { s _ s3; s3 _ NIL } ELSE IF s2 # NIL THEN { s _ s2; s2 _ NIL } ELSE IF s1 # NIL THEN { s _ s1; s1 _ NIL } ELSE s _ Create[]; }; s1, s2, s3: Ref; -- the small cache! Free: PUBLIC ENTRY PROC [s: Ref] ~ { ENABLE UNWIND => NULL; IF s3 = NIL THEN s3 _ s ELSE IF s2 = NIL THEN s2 _ s ELSE IF s1 = NIL THEN s1 _ s; }; LoadStyle: PUBLIC PROC [name: ATOM] RETURNS [ok: BOOL] ~ { frame: Frame _ NodeStyleWorks.GetFrame[NIL, NIL, screen]; [] _ NodeStyleWorks.GetStyleDict[frame, name, screen]; NodeStyleWorks.FreeFrame[frame, NIL, screen]; RETURN [TRUE]; }; DefineStyle: PUBLIC PROC [name: ATOM, def: ROPE] RETURNS [ok: BOOL] ~ { frame: Frame _ NodeStyleWorks.GetFrame[NIL, NIL, screen]; IF def = NIL THEN NodeStyleWorks.BadStyleFile[frame, name] ELSE [] _ NodeStyleWorks.GetStyleDict[frame, name, screen, def]; NodeStyleWorks.FreeFrame[frame, NIL, screen]; RETURN [TRUE]; }; ReloadStyle: PUBLIC PROC [name: ATOM] RETURNS [ok: BOOL] ~ { ForceLowerName: PROC [name: ATOM] RETURNS [ATOM] ~ { RETURN [Atom.MakeAtom[ForceRopeLower[Atom.GetPName[name]]]]; }; name _ ForceLowerName[name]; FOR kind: NodeStyleOps.OfStyle IN NodeStyleOps.OfStyle DO frame: Frame _ NodeStyleWorks.GetFrame[NIL, NIL, kind]; ok _ NodeStyleWorks.RunStyle[frame, name]; IF ~ok THEN NodeStyleWorks.BadStyleFile[frame, name]; NodeStyleWorks.FreeFrame[frame, NIL, kind]; ENDLOOP; }; defaultStyleName: PUBLIC ATOM; defaultStylesForExtensions: PUBLIC LIST OF ExtObjPair; SetDefaultStyle: PUBLIC PROC [name: ROPE] ~ { defaultStyleName _ Atom.MakeAtom[ForceRopeLower[name]]; defaultStyle.name[style] _ defaultStyleName; FlushCaches[]; }; ForceRopeLower: PROC [r: ROPE] RETURNS [ROPE] ~ { ForceCharLower: PROC [old: CHAR] RETURNS [new: CHAR] ~ { RETURN [Ascii.Lower[old]] }; RETURN [Rope.Translate[base: r, translator: ForceCharLower]]; }; SetExtensionStyles: PUBLIC PROC [value: LIST OF ROPE] ~ { defaultStylesForExtensions _ NIL; UNTIL value=NIL OR value.rest=NIL DO ext: ATOM _ Atom.MakeAtom[ForceRopeLower[value.first]]; -- the extension styleObject: Object _ Rope.Cat["\"", ForceRopeLower[value.rest.first], "\" style"]; defaultStylesForExtensions _ CONS[[ext, styleObject], defaultStylesForExtensions]; value _ value.rest.rest; ENDLOOP; FlushCaches[]; }; localStyleNumber: INT _ 0; ReadSpecs: PROC [name: ATOM, specs: ROPE] RETURNS [value: REF] ~ { GenLocalName: ENTRY PROC RETURNS [gen: ROPE] ~ { localStyleNumber _ localStyleNumber + 1; gen _ Rope.Concat["LocalStyle-", Convert.RopeFromInt[localStyleNumber]]; }; localStyle: LocalStyle _ NEW[LocalStyleRec]; localStyleName: ROPE ~ GenLocalName[]; localStyle.name _ Atom.MakeAtom[localStyleName]; localStyle.def _ specs; [] _ DefineStyle[localStyle.name, specs]; RETURN [localStyle]; }; WriteSpecs: PROC [name: ATOM, value: REF] RETURNS [specs: ROPE] ~ { localStyle: LocalStyle _ NARROW[value]; RETURN [IF localStyle=NIL THEN NIL ELSE localStyle.def]; }; CopyInfoProc: PROC [name: ATOM, value: REF] RETURNS [new: REF] ~ { RETURN [value] }; defaultStyle: PUBLIC Ref _ NIL; rootFormatName: ATOM; defaultFormatName: ATOM; ApplyAll: PUBLIC PROC [ref: Ref, node: TextNode.Ref, kind: OfStyle _ screen] ~ { [] _ DoApplyAll[ref, node, kind]; }; DoApplyAll: PROC [ref: Ref, node: TextNode.Ref, kind: OfStyle] RETURNS [depth: CARDINAL] ~ { found: BOOL; parent: TextNode.Ref; alt: ATOM; IF node = NIL THEN { ref^ _ defaultStyle^; RETURN [0] }; [found, depth] _ FindInApplyAllCache[ref, node, kind]; IF found THEN RETURN [depth+1]; parent _ TextNode.Parent[node]; alt _ IF parent=NIL THEN rootFormatName ELSE defaultFormatName; depth _ DoApplyAll[ref, parent, kind]; ApplyForNode[ref, node, alt, kind]; EnterInApplyAllCache[ref, node, depth]; RETURN [depth+1]; }; ApplyForNode: PUBLIC PROC [ref: Ref, node: TextNode.Ref, alt: ATOM, kind: OfStyle] ~ { ext: ATOM; ref.isComment _ IF node # NIL THEN node.comment ELSE FALSE; ref.print _ (kind = print); ref.nestingLevel _ MIN[TextNode.Level[node], MaxNestingLevel]; IF node.hasstyledef THEN { localStyle: LocalStyle _ NARROW[NodeProps.GetProp[node, $StyleDef]]; IF localStyle # NIL THEN ref.name[style] _ localStyle.name; }; IF node.hasprefix THEN ApplyObject[ref, NodeProps.GetProp[node, $Prefix], kind] ELSE IF ref.nestingLevel=0 -- root node -- AND -- check for file extension default (ext _ NARROW[NodeProps.GetProp[node, $FileExtension]]) # NIL THEN FOR list: LIST OF ExtObjPair _ defaultStylesForExtensions, list.rest UNTIL list = NIL DO IF list.first.fileExtension # ext THEN LOOP; ApplyObject[ref, list.first.styleObject, kind]; EXIT; ENDLOOP; ApplyFormat[ref, node.formatName, alt, kind]; IF node.haspostfix THEN ApplyObject[ref, NodeProps.GetProp[node, $Postfix], kind]; }; applyCacheInfo: REF ApplyCacheRecord _ NEW[ApplyCacheRecord]; ApplyCacheRecord: TYPE ~ RECORD [ applyCacheDepth: CARDINAL _ 0, -- next free entry applyCacheResults: REF ApplyCacheResults, applyCacheNodes: REF ApplyCacheNodes, applyCacheProbes, applyCacheHits, applyCacheSaves: INT _ 0 ]; applyCacheSize: CARDINAL ~ 8; -- number of levels deep in tree ApplyCacheNodes: TYPE ~ ARRAY [0..applyCacheSize) OF TextNode.Ref; ApplyCacheResults: TYPE ~ ARRAY [0..applyCacheSize) OF StyleBody; InitApplyCacheRecord: PROC ~ { OPEN applyCacheInfo; applyCacheResults _ NEW[ApplyCacheResults]; applyCacheNodes _ NEW[ApplyCacheNodes]; }; RemoveAllFromApplyAllCache: PUBLIC PROC ~ { FlushApplyAllCache[] }; FlushApplyAllCache: PUBLIC ENTRY PROC [init: BOOL _ FALSE] ~ { ENABLE UNWIND => NULL; ClearApplyAllCache[init]; }; ClearApplyAllCache: PROC [init: BOOL] ~ { OPEN applyCacheInfo; nodes: REF ApplyCacheNodes _ applyCacheNodes; FOR i: CARDINAL IN [0..applyCacheSize) DO nodes[i] _ NIL; ENDLOOP; applyCacheDepth _ 0; }; RemoveNodeFromApplyAllCache: PUBLIC ENTRY PROC [node: TextNode.Ref] ~ { OPEN applyCacheInfo; ENABLE UNWIND => NULL; nodes: REF ApplyCacheNodes _ applyCacheNodes; FOR i:CARDINAL IN [0..applyCacheDepth) DO IF nodes[i]=node THEN { -- clear from here on FOR j: CARDINAL IN [i..applyCacheSize) DO nodes[j] _ NIL; ENDLOOP; applyCacheDepth _ i; EXIT }; ENDLOOP; }; FindInApplyAllCache: ENTRY PROC [ref: Ref, node: TextNode.Ref, kind: OfStyle] RETURNS [found: BOOL, depth: CARDINAL] ~ { OPEN applyCacheInfo; ENABLE UNWIND => NULL; nodes: REF ApplyCacheNodes _ applyCacheNodes; print: BOOL ~ (kind=print); -- if true, then find result with print true also applyCacheProbes _ applyCacheProbes+1; FOR i: CARDINAL DECREASING IN [0..applyCacheDepth) DO IF nodes[i]=node AND print=applyCacheResults[i].print THEN { -- found it applyCacheHits _ applyCacheHits+1; applyCacheSaves _ applyCacheSaves+i+1; ref^ _ applyCacheResults[i]; RETURN [TRUE, i] }; ENDLOOP; RETURN [FALSE, 0]; }; EnterInApplyAllCache: ENTRY PROC [ref: Ref, node: TextNode.Ref, depth: CARDINAL] ~ { OPEN applyCacheInfo; ENABLE UNWIND => NULL; nodes: REF ApplyCacheNodes _ applyCacheNodes; IF depth >= applyCacheSize THEN RETURN; nodes[depth] _ node; applyCacheResults[depth] _ ref^; FOR i:CARDINAL IN [depth+1..applyCacheSize) DO nodes[i] _ NIL; ENDLOOP; applyCacheDepth _ depth+1; }; Change: TYPE ~ EditNotify.Change; Notify: PROC [change: REF READONLY Change] ~ { DoNode: PROC [node: TextNode.Ref] ~ { IF TextNode.FirstChild[node] # NIL THEN FlushApplyAllCache[] ELSE RemoveNodeFromApplyAllCache[node] }; WITH change SELECT FROM x: REF READONLY Change.InsertingNode => IF TextNode.FirstChild[x.new] # NIL THEN FlushApplyAllCache; x: REF READONLY Change.MovingNodes => FlushApplyAllCache; x: REF READONLY Change.NodeNesting => IF x.first = x.last -- only changing one node AND TextNode.FirstChild[x.first] = NIL -- node has no children THEN SELECT x.change FROM 1 => -- increasing nesting in tree IF TextNode.Next[x.first] = NIL THEN RemoveNodeFromApplyAllCache[x.first] ELSE FlushApplyAllCache; -1 => -- decreasing nesting in tree RemoveNodeFromApplyAllCache[x.first]; ENDCASE => FlushApplyAllCache ELSE FlushApplyAllCache; x: REF READONLY Change.ChangingFormat => DoNode[x.node]; x: REF READONLY Change.ChangingProp => { IF NodePropsExtras.Is[x.propAtom, $Visible] THEN DoNode[x.node]; }; ENDCASE => ERROR; -- not expecting notify for any other kinds of changes }; ApplyFormat: PUBLIC PROC [ref: Ref, name, alt: ATOM, kind: OfStyle] ~ { OPEN ruleCacheInfo; names: REF RuleCacheNames _ ruleCacheNames; inputs: REF RuleCacheBodies _ ruleCacheInputs; input: StyleBody; initloc, loc: CARDINAL; FindInRuleCache: ENTRY PROC RETURNS [BOOL] ~ { ENABLE UNWIND => NULL; ruleCacheProbes _ ruleCacheProbes+1; DO -- search cache SELECT names[loc] FROM name => IF inputs[loc] = ref^ THEN { ref^ _ ruleCacheResults[loc]; ruleCacheHits _ ruleCacheHits+1; RETURN [TRUE] }; NIL => RETURN [FALSE]; -- this is an unused entry ENDCASE; SELECT (loc _ loc+1) FROM ruleCacheSize => IF (loc _ 0)=initloc THEN RETURN [FALSE]; initloc => RETURN [FALSE]; ENDCASE; ENDLOOP; }; PutInRuleCache: ENTRY PROC ~ { ENABLE UNWIND => NULL; IF ruleCacheCount = ruleCacheMax THEN ClearRuleCache[]; loc _ initloc; DO -- search cache for place to put the entry SELECT names[loc] FROM name => IF inputs[loc] = input THEN RETURN; -- already in cache NIL => EXIT; -- this is an unused entry ENDCASE; SELECT (loc _ loc+1) FROM ruleCacheSize => IF (loc _ 0) = initloc THEN ERROR; -- cache full initloc => ERROR; -- cache full ENDCASE; ENDLOOP; ruleCacheCount _ ruleCacheCount+1; inputs[loc] _ input; ruleCacheResults[loc] _ ref^; names[loc] _ name; }; IF name = NIL AND (name _ alt) = NIL THEN RETURN; loc _ initloc _ HashStyle[ref, , name] MOD ruleCacheSize; IF FindInRuleCache[] THEN RETURN; input _ ref^; -- save the input value of the record IF NodeStyleWorks.ExecuteNameInStyle[ref, kind, name] THEN PutInRuleCache[] ELSE IF name # alt THEN ApplyFormat[ref, alt, NIL, kind]; }; ruleCacheInfo: REF RuleCacheInfoRecord _ NEW[RuleCacheInfoRecord]; RuleCacheInfoRecord: TYPE ~ RECORD [ ruleCacheCount: CARDINAL _ 0, -- number of entries currently in use ruleCacheNames: REF RuleCacheNames, ruleCacheInputs: REF RuleCacheBodies, ruleCacheResults: REF RuleCacheBodies, ruleCacheProbes, ruleCacheHits: INT _ 0 ]; ruleCacheSize: CARDINAL ~ 64; -- should be a power of 2 ruleCacheMax: CARDINAL ~ (ruleCacheSize*4)/5; -- don't fill too full RuleCacheNames: TYPE ~ ARRAY [0..ruleCacheSize) OF ATOM; RuleCacheBodies: TYPE ~ ARRAY [0..ruleCacheSize) OF StyleBody; InitRuleCacheInfo: PROC ~ { OPEN ruleCacheInfo; ruleCacheNames _ NEW[RuleCacheNames]; ruleCacheInputs _ NEW[RuleCacheBodies]; ruleCacheResults _ NEW[RuleCacheBodies]; }; FlushRuleCache: ENTRY PROC [init: BOOL _ FALSE] ~ { ENABLE UNWIND => NULL; ClearRuleCache[]; }; ClearRuleCache: PROC [init: BOOL _ FALSE] ~ { OPEN ruleCacheInfo; names: REF RuleCacheNames _ ruleCacheNames; IF ~init AND ruleCacheCount = 0 THEN RETURN; ruleCacheCount _ 0; FOR i: CARDINAL IN [0..ruleCacheSize) DO names[i] _ NIL; ENDLOOP; }; HashStyle: PROC [ref: Ref, looks: TextLooks.Looks _ TextLooks.noLooks, anotherRef: REF _ NIL] RETURNS [CARDINAL] ~ TRUSTED { Bits: TYPE ~ MACHINE DEPENDENT RECORD [ REF, REF, REF, REF, RealCode, RealCode, RealCode, RealCode, TextLooks.Looks]; bits: Bits _ [ref.name[style], ref.name[fontPrefix], ref.name[fontFamily], anotherRef, ref.real[fontSize], ref.real[leftIndent], ref.real[leading], 0, looks]; RETURN [Checksum.ComputeChecksum[3145, SIZE[Bits], @bits]]; }; ApplyLooks: PUBLIC PROC [ref: Ref, looks: TextLooks.Looks, kind: OfStyle] ~ { OPEN looksCacheInfo; lks: REF LooksCacheLooks _ looksCacheLooks; inputs: REF LooksCacheBodies _ looksCacheInputs; initloc, loc: CARDINAL; input: StyleBody; FindInLooksCache: ENTRY PROC RETURNS [BOOL] ~ { ENABLE UNWIND => NULL; looksCacheProbes _ looksCacheProbes+1; DO -- search cache SELECT lks[loc] FROM looks => IF inputs[loc] = ref^ THEN { ref^ _ looksCacheResults[loc]; looksCacheHits _ looksCacheHits+1; RETURN [TRUE] }; TextLooks.noLooks => RETURN [FALSE]; -- this is an unused entry ENDCASE; SELECT (loc _ loc+1) FROM looksCacheSize => IF (loc _ 0)=initloc THEN RETURN [FALSE]; initloc => RETURN [FALSE]; ENDCASE; ENDLOOP; }; PutInLooksCache: ENTRY PROC ~ { ENABLE UNWIND => NULL; IF looksCacheCount = looksCacheMax THEN ClearLooksCache[]; loc _ initloc; DO -- search cache SELECT lks[loc] FROM looks => IF inputs[loc] = input THEN RETURN; -- already in cache TextLooks.noLooks => EXIT; -- this is an unused entry ENDCASE; SELECT (loc _ loc+1) FROM looksCacheSize => IF (loc _ 0)=initloc THEN ERROR; -- cache full initloc => ERROR; -- cache full ENDCASE; ENDLOOP; looksCacheResults[loc] _ ref^; lks[loc] _ looks; inputs[loc] _ input; looksCacheCount _ looksCacheCount+1; }; IF looks = TextLooks.noLooks THEN RETURN; loc _ initloc _ HashStyle[ref, looks] MOD looksCacheSize; IF FindInLooksCache[] THEN RETURN; input _ ref^; -- save the input value of the record IF NodeStyleWorks.ExecuteLooksInStyle[ref, kind, looks] THEN PutInLooksCache[]; }; looksCacheInfo: REF LooksCacheInfoRecord _ NEW[LooksCacheInfoRecord]; LooksCacheInfoRecord: TYPE ~ RECORD [ looksCacheCount: CARDINAL _ 0, looksCacheLooks: REF LooksCacheLooks, looksCacheInputs: REF LooksCacheBodies, looksCacheResults: REF LooksCacheBodies, looksCacheProbes, looksCacheHits: INT _ 0 ]; looksCacheSize: CARDINAL ~ 16; -- should be a power of 2 looksCacheMax: CARDINAL ~ (looksCacheSize*4)/5; -- don't fill too full LooksCacheLooks: TYPE ~ ARRAY [0..looksCacheSize) OF TextLooks.Looks; LooksCacheBodies: TYPE ~ ARRAY [0..looksCacheSize) OF StyleBody; InitLooksCacheInfo: PROC ~ { OPEN looksCacheInfo; looksCacheLooks _ NEW[LooksCacheLooks]; looksCacheInputs _ NEW[LooksCacheBodies]; looksCacheResults _ NEW[LooksCacheBodies]; }; FlushLooksCache: ENTRY PROC [init: BOOL _ FALSE] ~ { ENABLE UNWIND => NULL; ClearLooksCache[]; }; ClearLooksCache: PROC [init: BOOL _ FALSE] ~ { OPEN looksCacheInfo; IF ~init AND looksCacheCount = 0 THEN RETURN; looksCacheCount _ 0; FOR i: CARDINAL IN [0..looksCacheSize) DO looksCacheLooks[i] _ TextLooks.noLooks; ENDLOOP; }; ApplyObject: PUBLIC PROC [ref: Ref, object: Object, kind: OfStyle _ screen] ~ { OPEN objectCacheInfo; objects: REF ObjectCacheObjects _ objectCacheObjects; inputs: REF ObjectCacheBodies _ objectCacheInputs; input: StyleBody; initloc, loc: CARDINAL; FindInObjectCache: ENTRY PROC RETURNS [BOOL] ~ { ENABLE UNWIND => NULL; objectCacheProbes _ objectCacheProbes+1; DO -- search cache SELECT objects[loc] FROM object => IF inputs[loc] = ref^ THEN { ref^ _ objectCacheResults[loc]; objectCacheHits _ objectCacheHits+1; RETURN [TRUE] }; nullObject => RETURN [FALSE]; -- this is an unused entry ENDCASE; SELECT (loc _ loc+1) FROM objectCacheSize => IF (loc _ 0)=initloc THEN RETURN [FALSE]; initloc => RETURN [FALSE]; ENDCASE; ENDLOOP; }; PutInObjectCache: ENTRY PROC ~ { ENABLE UNWIND => NULL; IF objectCacheCount = objectCacheMax THEN ClearObjectCache[]; loc _ initloc; DO -- search cache for place to put the entry SELECT objects[loc] FROM object => IF inputs[loc] = input THEN RETURN; -- already in cache nullObject => EXIT; -- this is an unused entry ENDCASE; SELECT (loc _ loc+1) FROM objectCacheSize => IF (loc _ 0)=initloc THEN ERROR; -- cache full initloc => ERROR; -- cache full ENDCASE; ENDLOOP; objectCacheCount _ objectCacheCount+1; inputs[loc] _ input; objectCacheResults[loc] _ ref^; objects[loc] _ object; }; IF object = nullObject THEN RETURN; loc _ initloc _ HashStyle[ref, , object] MOD objectCacheSize; IF FindInObjectCache[] THEN RETURN; IF NodeStyleWorks.ExecuteObjectInStyle[ref, kind, object] THEN PutInObjectCache[]; }; objectCacheInfo: REF ObjectCacheInfoRecord _ NEW[ObjectCacheInfoRecord]; ObjectCacheInfoRecord: TYPE ~ RECORD [ objectCacheCount: CARDINAL, objectCacheObjects: REF ObjectCacheObjects, objectCacheInputs: REF ObjectCacheBodies, objectCacheResults: REF ObjectCacheBodies, objectCacheProbes, objectCacheHits: INT _ 0 ]; objectCacheSize: CARDINAL ~ 16; -- should be a power of 2 objectCacheMax: CARDINAL ~ (objectCacheSize*4)/5; -- don't fill too full ObjectCacheObjects: TYPE ~ ARRAY [0..objectCacheSize) OF Object; ObjectCacheBodies: TYPE ~ ARRAY [0..objectCacheSize) OF StyleBody; nullObject: Object ~ NIL; InitObjectCacheInfo: PROC ~ { OPEN objectCacheInfo; objectCacheObjects _ NEW[ObjectCacheObjects]; objectCacheInputs _ NEW[ObjectCacheBodies]; objectCacheResults _ NEW[ObjectCacheBodies]; }; FlushObjectCache: ENTRY PROC [init: BOOL _ FALSE] ~ { ENABLE UNWIND => NULL; ClearObjectCache[]; }; ClearObjectCache: PROC [init: BOOL _ FALSE] ~ { OPEN objectCacheInfo; IF ~init AND objectCacheCount = 0 THEN RETURN; objectCacheCount _ 0; FOR i: CARDINAL IN [0..objectCacheSize) DO objectCacheObjects[i] _ nullObject; ENDLOOP; }; FlushCaches: PUBLIC ENTRY PROC ~ { ENABLE UNWIND => NULL; ClearCaches[FALSE]; }; ClearCaches: PROC [init: BOOL] ~ { ClearApplyAllCache[init]; ClearRuleCache[init]; ClearLooksCache[init]; ClearObjectCache[init]; }; nonNumeric: PUBLIC ERROR ~ CODE; GetStyleParam: PUBLIC PROC [s: Ref, name: ATOM, styleName: ATOM, kind: OfStyle] RETURNS [r: REAL] ~ { obj: Object _ GetStyleParamObj[s, name, styleName, kind]; WITH obj SELECT FROM x: REF TJaM.NumberRep.int => r _ x.int; x: REF TJaM.NumberRep.real => r _ x.real; ENDCASE => ERROR nonNumeric; RETURN [r]; }; GetStyleParamI: PUBLIC PROC [s: Ref, name: ATOM, styleName: ATOM, kind: OfStyle] RETURNS [i: INTEGER] ~ { obj: Object _ GetStyleParamObj[s, name, styleName, kind]; WITH obj SELECT FROM x: REF TJaM.NumberRep.int => i _ x.int; x: REF TJaM.NumberRep.real => i _ NodeStyle.IntegerValue[x.real]; ENDCASE => ERROR nonNumeric; RETURN [i]; }; GetStyleParamObj: PUBLIC PROC [s: Ref, name: ATOM, styleName: ATOM, kind: OfStyle] RETURNS [obj: Object] ~ { frame: Frame; key: ATOM _ NodeStyleWorks.StyleParamKey[name]; FOR x: DataList _ s.dataList, x.next UNTIL x=NIL DO WITH x SELECT FROM xx: REF NodeStyle.DataEntry.object => IF xx.name = key THEN RETURN[xx.object]; ENDCASE; ENDLOOP; frame _ NodeStyleWorks.GetFrame[s, styleName, kind]; obj _ TJaM.TryToLoad[frame, key].val; NodeStyleWorks.FreeFrame[frame, styleName, kind]; RETURN [obj]; }; StyleNameForNode: PUBLIC PROC [node: TextNode.Ref] RETURNS [name: ATOM] ~ { s: Ref _ Alloc[]; ApplyAll[s, node]; name _ GetStyleName[s]; Free[s]; }; InitializeDefaultStyle: PUBLIC PROC [suggestedStyle: ROPE] ~ { changeSet: EditNotify.ChangeSet; PointsPerInch: REAL ~ 1.0/0.0138370; changeSet[ChangingProp] _ TRUE; changeSet[ChangingFormat] _ TRUE; changeSet[MovingNodes] _ TRUE; changeSet[NodeNesting] _ TRUE; changeSet[InsertingNode] _ TRUE; EditNotify.AddNotifyProc[Notify, after, high, changeSet]; InitApplyCacheRecord[]; InitRuleCacheInfo[]; InitLooksCacheInfo[]; InitObjectCacheInfo[]; ClearCaches[TRUE]; defaultStyle _ Create[]; defaultFormatName _ $default; rootFormatName _ $root; defaultStyle.name[fontFamily] _ $Helvetica; SetReal[defaultStyle, fontSize, 10]; SetReal[defaultStyle, leading, 12]; SetReal[defaultStyle, tabStops, 4]; SetReal[defaultStyle, pageWidth, 8.5*PointsPerInch]; SetReal[defaultStyle, pageLength, 11*PointsPerInch]; SetReal[defaultStyle, leftMargin, 1*PointsPerInch]; SetReal[defaultStyle, rightMargin, 1*PointsPerInch]; SetReal[defaultStyle, topMargin, 1*PointsPerInch]; SetReal[defaultStyle, bottomMargin, 1*PointsPerInch]; SetReal[defaultStyle, lineLength, 6.5*PointsPerInch]; SetReal[defaultStyle, underlineThickness, 1]; SetReal[defaultStyle, underlineDescent, 1]; SetReal[defaultStyle, strikeoutThickness, 1]; SetReal[defaultStyle, strikeoutAscent, 4]; NodeProps.Register[name: $StyleDef, reader: ReadSpecs, writer: WriteSpecs, copier: CopyInfoProc]; SetDefaultStyle[suggestedStyle]; }; END. pNodeStyleOpsImpl.mesa Copyright Σ 1985, 1986 by Xerox Corporation. All rights reserved. written by Bill Paxton, January 1981 Paxton, December 21, 1982 9:55 am Maxwell, January 6, 1983 9:50 am Doug Wyatt, March 5, 1985 10:53:24 am PST Russ Atkinson, March 7, 1985 3:29:21 am PST Michael Plass, May 9, 1986 12:27:55 pm PDT Rick Beach, March 27, 1985 10:54:03 am PST Style Operations create a style body copy a style body get from a small cache don't free more than once or disaster! Local Styles Apply Style to Node NodeStyleObsolete.EvalFreeVars[ref, node]; ApplyAll Cache -- when clearing, go all the way to applyCacheSize rather than stopping at applyCacheDepth Update ApplyAll Cache due to Editing Operations if change invalidates one node only, remove that node else clear entire cache Style Rule Cache Looks Cache Object Cache Flush Caches Style Parameter Extensions May raise NodeStyleOps.nonNumeric or TJaM.Error[undefkey]. May raise NodeStyleOps.nonNumeric or TJaM.Error[undefkey]. Miscellaneous Does an ApplyAll and then returns the style name Initialization register the notify proc that updates the style caches when edits occur initialize all the style caches establish the default styles wired into Tioga provide some basic style attribute values in case no style gets loaded successfully register the special handling procedures for the local style property: StyleDef Κ˜˜codešœ™KšœB™BKšœ$™$Kšœ!™!K™ K™)K™+K™*J™*—K™šΟk ˜ Jšœœ ˜Jšœœ˜ Jšœ œ˜!Jšœœ˜Jšœ œ$˜4Jšœ œ#˜2Jšœœ˜Jšœ œg˜vJšœ œ2˜DJšœœ‹˜ŸJšœœœ ˜*Jšœ œ˜!Jšœ œ(˜6Jšœœ'˜1—K˜KšΠblœœ˜Kšœx˜Kšœ ˜šœœœ˜%K™Kšœœœ˜Kšœœ˜Kšœœ˜—headšœ™šΟnœœœœ ˜%Kšœ™Kšœœ ˜Kšœ˜K˜—šŸœœœ˜)Kšœ™K˜K˜K˜—š Ÿœœœœœ ˜-Kšœ™Kšœœœ˜Kšœœœœ˜%Kš œœœœœ˜*Kš œœœœœ˜*Kšœ˜Kšœ˜—KšœΟc˜$K˜šŸœœœœ ˜$Kšœ&™&Kšœœœ˜Kšœœœ˜Kšœœœœ˜Kšœœœœ˜Kšœ˜K˜—š Ÿ œœœœœœ˜:Kšœ'œœ ˜9K˜6Kšœ œ ˜-Kšœœ˜Kšœ˜K˜—šŸ œœœœœœœ˜GKšœ'œœ ˜9šœ˜ Kšœ)˜-Kšœ<˜@—Kšœ œ ˜-Kšœœ˜Kšœ˜K˜—š Ÿ œœœœœœ˜<š Ÿœœœœœ˜4Jšœ6˜K™*šœœ˜Kšœœ%˜DKšœœœ#˜;Kšœ˜—šœ˜Kšœ9˜=šœœ œœ #œœ-œ˜•š œœœ4œœ˜XKšœ œœ˜,Kšœ/˜/Kšœ˜Kšœ˜———Kšœ-˜-Kšœœ;˜Ršœ˜K˜———™Kšœœœ˜=šœœœ˜!Kšœœ ˜2Kšœœ˜)Kšœœ˜%Kšœ3œ˜=—Kšœœ  ˜>Kšœœœœ˜BKšœœœœ ˜BK˜šŸœœœ˜3Kšœœ˜+Kšœœ˜'Kšœ˜K˜—šŸœœœ˜CK˜—š Ÿœœœœœœ˜>Kšœœœ˜K˜K˜K˜—šŸœœœ˜)Kšœ˜Kšœœ#˜-KšœZ™ZKš œœœœ œœ˜BK˜K˜K˜—šŸœœœœ˜GKšœ˜Kšœœœ˜Kšœœ#˜-šœœœœ˜*šœœ ˜-šœœœ˜)Kšœ œ˜Kšœ˜—Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜K˜—š Ÿœœœ0œ œ œ˜yKšœ˜Kšœœœ˜Kšœœ#˜-Kšœœ 1˜MK˜&š œœ œœ˜5šœœ"œ  ˜HK˜"K˜&K˜Kšœœ˜Kšœ˜—Kšœ˜—Kšœœ˜Kšœ˜K˜—šŸœœœ'œ˜TKšœ˜Kšœœœ˜Kšœœ#˜-Kšœœœ˜'K˜K˜ Kš œœœœ œœ˜GK˜K˜K˜——™/Kšœœ˜!šŸœœ œœ ˜.Kšœ5™5Kšœ™šŸœœ˜%Kšœœœ˜šœœ ˜šœ ˜"Kšœœœ%˜IKšœ˜—šœ ˜#K˜%—Kšœ˜—Kšœ˜—Kšœœœ)˜8šœœœ˜(Kšœ*œ˜@Kšœ˜—Kšœœ 6˜H—K˜K˜——™šŸ œœœœ˜GKšœ˜Kšœœ!˜+Kšœœ#˜.K˜Kšœœ˜š Ÿœœœœœ˜.Kšœœœ˜K˜$šœ ˜šœ ˜šœœœ˜$K˜K˜ Kšœœ˜—Kšœœœ ˜1Kšœ˜—šœ˜Kš œœœœœ˜:Kšœ œœ˜Kšœ˜—Kšœ˜—Kšœ˜—šŸœœœ˜Kšœœœ˜Kšœœ˜7K˜šœ *˜-šœ ˜Kšœœœœ ˜?Kšœœ ˜'Kšœ˜—šœ˜Kšœœœœ  ˜AKšœ œ  ˜Kšœ˜—Kšœ˜—K˜"K˜K˜K˜K˜—Kš œœœœœœ˜1Kšœ'œ˜9Kšœœœ˜!Kšœ %˜3šœ3˜5Kšœ˜Kšœœ œœ˜9—Kšœ˜K˜—Kšœœœ˜Bšœœœ˜$Kšœœ %˜CKšœœ˜#Kšœœ˜%Kšœœ˜&Kšœ œ˜'Kšœ˜—Kšœœ ˜7Kšœœ ˜DKš œœœœœ˜8Kšœœœœ ˜>K˜šŸœœ˜Kšœ˜Kšœœ˜%Kšœœ˜'Kšœœ˜(Kšœ˜K˜—š Ÿœœœœœ˜3Kšœœœ˜K˜K˜K˜—šŸœœœœ˜-Kšœ˜Kšœœ!˜+Kšœœœœ˜,K˜Kš œœœœ œœ˜AKšœ˜K˜—šŸ œœDœœœœœ˜}Kšœœœ œœœœœœ;˜uKšœž˜žKšœ!œ˜;šœ˜K˜———™ šŸ œœœ6˜MKšœ˜Kšœœ#˜+Kšœœ%˜0Kšœœ˜K˜K˜š Ÿœœœœœ˜/Kšœœœ˜K˜&šœ ˜šœ ˜šœ œœ˜%K˜K˜"Kšœœ˜—Kšœœœ ˜?Kšœ˜—šœ˜Kš œœœœœ˜;Kšœ œœ˜Kšœ˜—Kšœ˜—šœ˜K˜——šŸœœœ˜Kšœœœ˜Kšœ!œ˜:K˜šœ ˜šœ ˜Kšœ œœœ ˜@Kšœœ ˜5Kšœ˜—šœ˜Kšœœœœ  ˜@Kšœ œ  ˜Kšœ˜—Kšœ˜—K˜K˜K˜K˜$K˜K˜—Kšœœœ˜)Kšœ&œ˜9Kšœœœ˜"Kšœ %˜3Kšœ5œ˜OK˜K˜—Kšœœœ˜Ešœœœ˜%Kšœœ˜Kšœœ˜%Kšœœ˜'Kšœœ˜(Kšœ"œ˜)Kšœ˜—Kšœœ ˜8Kšœœ ˜FKšœœœœ˜EKšœœœœ ˜@K˜šŸœœ˜Kšœ˜Kšœœ˜'Kšœœ˜)Kšœœ˜*K˜K˜—š Ÿœœœœœ˜4Kšœœœ˜K˜K˜K˜—šŸœœœœ˜.Kšœ˜Kšœœœœ˜-K˜Kš œœœœ)œ˜ZKšœ˜K˜——™ šŸ œœœ7˜OKšœ˜Kšœ œ)˜5Kšœœ'˜2K˜Kšœœ˜š Ÿœœœœœ˜0Kšœœœ˜K˜(šœ ˜šœ˜šœ œœ˜&K˜K˜$Kšœœ˜—Kšœœœ ˜8Kšœ˜—šœ˜Kš œœœœœ˜K˜ Kšœœ˜$K˜KšœG™GKšœœ˜Kšœœ˜!Kšœœ˜Kšœœ˜Kšœœ˜ K˜9K˜Kšœ™K˜K˜K˜K˜Kšœ œ˜K˜Kšœ-™-K˜K˜K˜K˜KšœS™SK˜+K˜$K˜#K˜#K˜4K˜4K˜3K˜4K˜2K˜5K˜5Kšœ-˜-Kšœ+˜+Kšœ-˜-Kšœ*˜*K˜KšœO™OKšœa˜aK˜Kšœ ˜ Kšœ˜——K˜Kšœ˜—…—Pςqϊ