NodeStyleApplyImpl.Mesa
written by Bill Paxton, January 1981
Last changed by Paxton, JuneAugust 2, 1983 10:11 am
Last Edited by: Maxwell, January 6, 1983 9:50 am
DIRECTORY
NodeStyleExtra,
NodeStyle,
NodeStyleObject,
TiogaNode,
TiogaNodeOps,
TiogaLooks,
TiogaLooksOps,
TiogaPathOps,
EditNotify,
NodeProps,
NameSymbolTable,
Inline,
JaMOps;
NodeStyleApplyImpl: CEDAR MONITOR
IMPORTS EditNotify, Inline, JaMOps, NameSymbolTable, NodeProps, NodeStyle, NodeStyleExtra, TiogaPathOps
EXPORTS NodeStyle, NodeStyleExtra =
BEGIN
OPEN NodeStyle, NodeStyleExtra;
Apply operations
defaultStyle: PUBLIC Ref; -- contains initial values for the style parameters
defaultName, rootName: Name;
ApplyAll: PUBLIC PROC [ref: Ref, path: TiogaNode.Path, kind: OfStyle ← screen] = {
[] ← DoApplyAll[ref, path, kind] };
DoApplyAll: PROC [ref: Ref, path: TiogaNode.Path, kind: OfStyle] RETURNS [depth: CARDINAL] = {
found: BOOLEAN;
parent: TiogaNode.Path;
alt: Name;
IF path.node=NIL THEN { ref^ ← defaultStyle^; RETURN [0] };
[found, depth] ← FindInApplyAllCache[ref, path, kind];
IF found THEN RETURN [depth+1];
parent ← TiogaPathOps.Parent[path];
alt ← IF parent=TiogaNode.nullPath THEN rootName ELSE defaultName;
depth ← DoApplyAll[ref, parent, kind];
ApplyForNode[ref, path, alt, kind];
EnterInApplyAllCache[ref, path, depth];
RETURN [depth+1] };
applyCacheInfo: REF ApplyCacheRecord ← NEW[ApplyCacheRecord];
ApplyCacheRecord: TYPE = RECORD [
applyCacheDepth: CARDINAL ← 0, -- next free entry
applyCacheResults: REF ApplyCacheResults,
applyCachePaths: REF ApplyCachePaths,
applyCacheProbes, applyCacheHits, applyCacheSaves: INT ← 0 ];
applyCacheSize: CARDINAL = 8; -- number of levels deep in tree
ApplyCachePaths: TYPE = ARRAY [0..applyCacheSize) OF TiogaNode.Path;
ApplyCacheResults: TYPE = ARRAY [0..applyCacheSize) OF StyleBody; 
InitApplyCacheRecord: PROC = { OPEN applyCacheInfo;
applyCacheResults ← NEW[ApplyCacheResults];
applyCachePaths ← NEW[ApplyCachePaths] };
RemoveAllFromApplyAllCache: PUBLIC PROC = { FlushApplyAllCache[] };
FlushApplyAllCache: PUBLIC ENTRY PROC [init: BOOLEANFALSE] = {
ENABLE UNWIND => NULL;
ClearApplyAllCache[init] };
ClearApplyAllCache: PROC [init: BOOLEAN] = { OPEN applyCacheInfo;
paths: REF ApplyCachePaths ← applyCachePaths;
when clearing, go all the way to applyCacheSize rather than stopping at applyCacheDepth
FOR i:CARDINAL IN [0..applyCacheSize) DO paths[i] ← TiogaNode.nullPath; ENDLOOP;
applyCacheDepth ← 0 };
RemoveNodeFromApplyAllCache: PUBLIC ENTRY PROC [node: TiogaNode.Ref] = {
Search for paths that end with this node and remove them.
OPEN applyCacheInfo;
ENABLE UNWIND => NULL;
paths: REF ApplyCachePaths ← applyCachePaths;
FOR i:CARDINAL IN [0..applyCacheDepth) DO
IF paths[i].node=node THEN { -- clear from here on
FOR j:CARDINAL IN [i..applyCacheSize) DO
paths[j] ← TiogaNode.nullPath; ENDLOOP;
applyCacheDepth ← i; EXIT };
ENDLOOP };
FindInApplyAllCache: ENTRY PROC [ref: Ref, path: TiogaNode.Path, kind: OfStyle]
RETURNS [found: BOOLEAN, depth: CARDINAL] = { OPEN applyCacheInfo;
ENABLE UNWIND => NULL;
node: TiogaNode.Ref = path.node;
paths: REF ApplyCachePaths ← applyCachePaths;
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 paths[i].node=node AND print=applyCacheResults[i].print AND
TiogaPathOps.Equal[paths[i], path] 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, path: TiogaNode.Path, depth: CARDINAL] = {
OPEN applyCacheInfo;
ENABLE UNWIND => NULL;
paths: REF ApplyCachePaths ← applyCachePaths;
IF depth >= applyCacheSize THEN RETURN;
paths[depth] ← path;
applyCacheResults[depth] ← ref^;
FOR i:CARDINAL IN [depth+1..applyCacheSize) DO paths[i] ← TiogaNode.nullPath; ENDLOOP;
applyCacheDepth ← depth+1 };
prefixAtom: ATOM = NodeProps.PrefixAtom[];
postfixAtom: ATOM = NodeProps.PostfixAtom[];
Notify: PROC [change: REF READONLY EditNotify.Change] = TRUSTED {
if change invalidates one node only, remove that node
else clear entire cache
called after the edit has taken place
HasSubstructure: PROC [node: TiogaNode.Ref] RETURNS [BOOL] = TRUSTED {
path: TiogaNode.Path = [node, NIL];
IF TiogaPathOps.Contents[path] # TiogaNode.nullPath THEN RETURN [TRUE];
IF TiogaPathOps.BranchChild[path] # TiogaNode.nullPath THEN RETURN [TRUE];
RETURN [FALSE] };
DoNode: PROC [node: TiogaNode.Ref] = TRUSTED {
IF HasSubstructure[node] THEN FlushApplyAllCache
ELSE RemoveNodeFromApplyAllCache[node] };
WITH x:change SELECT FROM
InsertingNode => IF HasSubstructure[x.new] THEN FlushApplyAllCache;
MovingNodes, MovingGroup => FlushApplyAllCache;
NodeNesting => IF x.first = x.last -- only changing one node
AND ~HasSubstructure[x.first] -- node has no substructure
THEN SELECT x.change FROM
1 => FlushApplyAllCache; -- increasing nesting in tree
-1 => RemoveNodeFromApplyAllCache[x.first]; -- decreasing nesting in tree
ENDCASE => FlushApplyAllCache
ELSE FlushApplyAllCache;
ChangingFormat => DoNode[x.node];
ChangingProp => SELECT x.propAtom FROM
prefixAtom, postfixAtom, $Comment, $StyleDef => DoNode[x.node];
ENDCASE;
ENDCASE => ERROR; -- not expecting notify for any other kinds of changes
};
ApplyForNode: PUBLIC PROC [ref: Ref, path: TiogaNode.Path, alt: Name, kind: OfStyle] = {
ext: ATOM;
node: TiogaNode.Ref = path.node;
ref.isComment ← node.comment;
ref.print ← (kind=print);
ref.nestingLevel ← MIN[TiogaPathOps.Level[path], MaxNestingLevel];
EvalFreeVars[ref, node];
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.GetPrefixObject[node], 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.format, alt, kind];
IF node.haspostfix THEN ApplyObject[ref, NodeProps.GetPostfixObject[node], kind] };
ApplyFormat: PUBLIC PROC [ref: Ref, name, alt: Name, kind: OfStyle ← screen] = {
OPEN ruleCacheInfo;
BITXOR: PROC[CARDINAL, CARDINAL] RETURNS[CARDINAL] = LOOPHOLE[Inline.BITXOR];
names: REF RuleCacheNames ← ruleCacheNames;
inputs: REF RuleCacheBodies ← ruleCacheInputs;
input: StyleBody;
initloc, loc: CARDINAL;
ok: BOOLEAN;
frame: Frame ← NIL;
styleName: Name;
FindInRuleCache: ENTRY PROC RETURNS [BOOLEAN] = {
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] };
NameSymbolTable.nullName => 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
NameSymbolTable.nullName => 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 = NameSymbolTable.nullName AND
(name ← alt) = NameSymbolTable.nullName THEN RETURN;
loc ← initloc ← BITXOR[LOOPHOLE[name, CARDINAL], Hash[ref]] MOD ruleCacheSize;
IF FindInRuleCache[] THEN RETURN;
frame ← GetFrame[ref, styleName ← ref.name[style], kind];
input ← ref^; -- save the input value of the record
ok ← ExecuteName[frame, name];
FreeFrame[frame, styleName, kind]; frame ← NIL;
IF ok THEN PutInRuleCache[] -- save results in cache
ELSE IF name # alt THEN ApplyFormat[ref, alt, NameSymbolTable.nullName] };
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 Name;
RuleCacheBodies: TYPE = ARRAY [0..ruleCacheSize) OF StyleBody;
InitRuleCacheInfo: PROC = { OPEN ruleCacheInfo;
ruleCacheNames ← NEW[RuleCacheNames];
ruleCacheInputs ← NEW[RuleCacheBodies];
ruleCacheResults ← NEW[RuleCacheBodies] };
FlushRuleCache: ENTRY PROC [init: BOOLEANFALSE] = {
ENABLE UNWIND => NULL;
ClearRuleCache[] };
ClearRuleCache: PROC [init: BOOLEANFALSE] = { OPEN ruleCacheInfo;
names: REF RuleCacheNames ← ruleCacheNames;
IF ~init AND ruleCacheCount = 0 THEN RETURN;
ruleCacheCount ← 0;
FOR i: CARDINAL IN [0..ruleCacheSize) DO
names[i] ← NameSymbolTable.nullName; ENDLOOP };
Hash: PROC [ref: Ref] RETURNS [CARDINAL] = {
BITXOR: PROC[CARDINAL, CARDINAL] RETURNS[CARDINAL] = LOOPHOLE[Inline.BITXOR];
RETURN [LOOPHOLE[
BITXOR[LOOPHOLE[ref.name[style]],
BITXOR[LOOPHOLE[ref.name[fontFamily], CARDINAL],
BITXOR[ref.real[fontSize],
BITXOR[ref.real[leftIndent],
ref.real[leading]]]]], CARDINAL]] };
ApplyLooks: PUBLIC PROC [ref: Ref, looks: TiogaLooks.Looks, kind: OfStyle] = {
OPEN looksCacheInfo;
BITXOR: PROC[CARDINAL, CARDINAL] RETURNS[CARDINAL] = LOOPHOLE[Inline.BITXOR];
lks: REF LooksCacheLooks ← looksCacheLooks;
inputs: REF LooksCacheBodies ← looksCacheInputs;
initloc, loc: CARDINAL;
input: StyleBody;
frame: Frame ← NIL;
styleName: Name;
FindInLooksCache: ENTRY PROC RETURNS [BOOLEAN] = {
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] };
TiogaLooks.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
TiogaLooks.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 = TiogaLooks.noLooks THEN RETURN;
loc ← initloc ←
BITXOR[LOOPHOLE[looks, TiogaLooksOps.LooksBytes].byte0,
BITXOR[LOOPHOLE[looks, TiogaLooksOps.LooksBytes].byte1,
BITXOR[LOOPHOLE[looks, TiogaLooksOps.LooksBytes].byte2,
Hash[ref]]]] MOD looksCacheSize;
IF FindInLooksCache[] THEN RETURN;
frame ← GetFrame[ref, styleName ← ref.name[style], kind];
input ← ref^; -- save the input value of the record
FOR c: CHARACTER IN TiogaLooks.Look DO
IF looks[c] THEN [] ← ExecuteName[frame, lookNames[c]]
ENDLOOP;
FreeFrame[frame, styleName, kind]; frame ← NIL;
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 TiogaLooks.Looks;
LooksCacheBodies: TYPE = ARRAY [0..looksCacheSize) OF StyleBody;
InitLooksCacheInfo: PROC = { OPEN looksCacheInfo;
looksCacheLooks ← NEW[LooksCacheLooks];
looksCacheInputs ← NEW[LooksCacheBodies];
looksCacheResults ← NEW[LooksCacheBodies] };
lookNames: ARRAY TiogaLooks.Look OF Name;
FlushLooksCache: ENTRY PROC [init: BOOLEANFALSE] = {
ENABLE UNWIND => NULL;
ClearLooksCache[] };
ClearLooksCache: PROC [init: BOOLEANFALSE] = { OPEN looksCacheInfo;
IF ~init AND looksCacheCount = 0 THEN RETURN;
looksCacheCount ← 0;
FOR i: CARDINAL IN [0..looksCacheSize) DO
looksCacheLooks[i] ← TiogaLooks.noLooks; ENDLOOP };
nullObject: NameSymbolTable.Object = NameSymbolTable.NullObject[];
ApplyObject: PUBLIC PROC [ref: Ref, object: NameSymbolTable.Object, kind: OfStyle ← screen] = {
OPEN objectCacheInfo;
BITXOR: PROC[CARDINAL, CARDINAL] RETURNS[CARDINAL] = LOOPHOLE[Inline.BITXOR];
objects: REF ObjectCacheObjects ← objectCacheObjects;
inputs: REF ObjectCacheBodies ← objectCacheInputs;
input: StyleBody;
initloc, loc: CARDINAL;
initDepth, finalDepth: CARDINAL;
obj: Object ← LOOPHOLE[object];
frame: Frame ← NIL;
styleName: Name;
FindInObjectCache: ENTRY PROC RETURNS [BOOLEAN] = {
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 };
HashObject: PROC RETURNS [CARDINAL] = {
ob: RECORD [ a, b, c, d: CARDINAL ] ← LOOPHOLE[object];
RETURN [ob.b] };
IF object = nullObject THEN RETURN;
loc ← initloc ← BITXOR[HashObject[], Hash[ref]] MOD objectCacheSize;
IF FindInObjectCache[] THEN RETURN;
frame ← GetFrame[ref, styleName ← ref.name[style], kind];
input ← ref^; -- save the input value of the record
TRUSTED {
initDepth ← JaMOps.CountStack[frame.opstk];
JaMOps.Execute[frame, CVX[obj]];
IF (finalDepth ← JaMOps.CountStack[frame.opstk]) # initDepth THEN {
PushObject[frame, obj];
PushText[frame, "Failed to leave stack at same depth after execution."];
StyleError[frame, 2] }
ELSE PutInObjectCache[]};
FreeFrame[frame, styleName, kind]; frame ← NIL };
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 NameSymbolTable.Object;
ObjectCacheBodies: TYPE = ARRAY [0..objectCacheSize) OF StyleBody;
InitObjectCacheInfo: PROC = { OPEN objectCacheInfo;
objectCacheObjects ← NEW[ObjectCacheObjects];
objectCacheInputs ← NEW[ObjectCacheBodies];
objectCacheResults ← NEW[ObjectCacheBodies] };
FlushObjectCache: ENTRY PROC [init: BOOLEANFALSE] = {
ENABLE UNWIND => NULL;
ClearObjectCache[] };
ClearObjectCache: PROC [init: BOOLEANFALSE] = { 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: BOOLEAN] = {
ClearApplyAllCache[init]; ClearRuleCache[init];
ClearLooksCache[init]; ClearObjectCache[init] };
***** Execute
executingName: PUBLIC Name;
ExecuteName: PROC [frame: Frame, name: Name] RETURNS [ok: BOOLEAN] = TRUSTED {
makes sure that same stack depth after execute
initDepth: CARDINAL ← JaMOps.CountStack[frame.opstk];
finalDepth: CARDINAL;
nameObj: Object;
[ok, ] ← JaMOps.TryToLoad[frame, nameObj ← NameToObject[name]];
IF ~ok THEN RETURN;
executingName ← name;
JaMOps.Execute[frame, CVX[nameObj]];
executingName ← NameSymbolTable.nullName;
IF (finalDepth ← JaMOps.CountStack[frame.opstk]) # initDepth THEN {
PushText[frame, "failed to leave stack at same depth after execution."];
PushName[frame, name];
StyleError[frame, 2] }};
StyleError: PUBLIC PROC [frame: Frame, num: INTEGER] = TRUSTED {
PushInteger[frame, num];
JaMOps.Execute[frame, CVX[NameToObject[styleerror]]] };
***** Miscellaneous
StyleNameForNode: PUBLIC PROC [path: TiogaNode.Path] RETURNS [name: Name] = {
does an ApplyAll and then returns the style name
s: Ref ← Alloc[];
ApplyAll[s, path];
name ← GetStyleName[s];
Free[s] };
Initialization
InitLookNames: PROC = TRUSTED {
names are "look.a", "look.b", "look.c", etc.
txt: STRING ← [6];
txt[0] ← 'l; txt[1] ← txt[2] ← 'o; txt[3] ← 'k; txt[4] ← '.; txt.length ← 6;
FOR c: CHARACTER IN TiogaLooks.Look DO
txt[5] ← c;
lookNames[c] ← MakeName[LOOPHOLE[LONG[txt], REF READONLY TEXT]];
ENDLOOP};
StartApply: PUBLIC PROCEDURE =
BEGIN
changeSet: EditNotify.ChangeSet;
frame: Frame ← NIL;
frame ← JaMOps.defaultFrame;
changeSet[ChangingProp] ← TRUE;
changeSet[ChangingFormat] ← TRUE;
changeSet[MovingNodes] ← TRUE;
changeSet[MovingGroup] ← TRUE;
changeSet[NodeNesting] ← TRUE;
changeSet[InsertingNode] ← TRUE;
EditNotify.AddNotifyProc[Notify, after, high, changeSet];
defaultStyle ← Create[];
defaultName ← MakeName["default"];
rootName ← MakeName["root"];
InitLookNames[];
InitApplyCacheRecord[];
InitRuleCacheInfo[];
InitLooksCacheInfo[];
InitObjectCacheInfo[];
ClearCaches[TRUE];
SetDefaultStyle["Cedar"];
END;
END.