<<>> <> <> <> <<>> DIRECTORY Basics USING [BoundsCheckInt, NonNegative], Char USING [CharCode, CharSet, Make, XCHAR], NodeReader USING [Ref, Rep, CharInfo], Rope USING [ROPE, AppendChars, Size], Rosary USING [ROSARY, ContainingRun, FetchContainingRun], TextEdit USING [CharSetFromItem, LooksFromItem, PropListFromItem], TextFind USING [CharMap, CharMapFromCase], Tioga USING [Node, Looks, PropList]; NodeReaderImpl: CEDAR MONITOR IMPORTS Basics, Char, Rope, Rosary, TextEdit, TextFind EXPORTS NodeReader = BEGIN ROPE: TYPE ~ Rope.ROPE; ROSARY: TYPE ~ Rosary.ROSARY; Ref: TYPE ~ NodeReader.Ref; Rep: TYPE ~ NodeReader.Rep; CharInfo: TYPE ~ NodeReader.CharInfo; CacheIndex: TYPE ~ [0..3); cache: ARRAY CacheIndex OF Ref ¬ ALL[NIL]; CacheAlloc: ENTRY PROC RETURNS [reader: Ref ¬ NIL] = { FOR i: CacheIndex IN CacheIndex DO IF (reader ¬ cache[i])#NIL THEN { cache[i] ¬ NIL; EXIT }; ENDLOOP; }; CacheFree: ENTRY PROC [reader: Ref] = { FOR i: CacheIndex IN CacheIndex DO IF cache[i]=reader THEN RETURN; -- don't cache it twice! ENDLOOP; FOR i: CacheIndex IN CacheIndex DO IF cache[i]=NIL THEN { cache[i] ¬ reader; EXIT }; ENDLOOP; }; New: PUBLIC PROC [node: Tioga.Node, oldReader: Ref ¬ NIL] RETURNS [reader: Ref] ~ { reader ¬ oldReader; IF reader=NIL THEN reader ¬ CacheAlloc[]; IF reader=NIL THEN reader ¬ NEW[Rep]; Set[reader, node]; }; Free: PUBLIC PROC [reader: Ref] ~ { Set[reader, NIL]; CacheFree[reader]; }; textSize: NAT ~ 128; Set: PUBLIC PROC [reader: Ref, node: Tioga.Node] ~ { IF node#NIL THEN SetParts[reader, node.rope, node.runs, node.charSets, node.charProps] ELSE SetParts[reader, NIL, NIL, NIL, NIL]; }; SetParts: PUBLIC PROC [reader: Ref, rope: ROPE, runs, charSets, charProps: ROSARY] ~ { text: REF TEXT ¬ reader.text; IF text=NIL OR text.maxLength0 THEN { IF runs=NIL THEN reader.looksEnd ¬ reader.size; -- noLooks for all chars IF charSets=NIL THEN reader.charSetEnd ¬ reader.size; -- 0 for all chars IF charProps=NIL THEN reader.propsEnd ¬ reader.size; -- NIL for all chars }; }; UpdateText: PROC [reader: Ref, index: INT] ~ { start: INT ~ (Basics.BoundsCheckInt[index, reader.size]/textSize)*textSize; text: REF TEXT ~ reader.text; IF text.maxLength