TextLooks.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
written by Bill Paxton, February 1981
last edit by Bill Paxton, December 13, 1982 1:17 pm
Last Edited by: Maxwell, January 5, 1983 12:35 pm
Michael Plass, March 14, 1985 10:00:03 am PST
Doug Wyatt, March 2, 1985 3:22:04 pm PST
This package provides Looks for text in Tioga
it allows a client to associate looks with characters in a rope
looks are represented as a vector of 32 bits
The implementation expects that long sequences will have the same looks
and thus uses a run encoding to save space.
The runs of looks are immutable just like the text in a rope.
i.e., you don't change runs;
instead you build new ones out of parts of old ones
Also like ropes, we use piece tables in the implementation
thus making the cost of setting looks independent of the size of the rope.
DIRECTORY
Rope USING [ROPE];
TextLooks: CEDAR DEFINITIONS
= BEGIN
Runs: TYPE = REF RunsBody;
Looks: TYPE = PACKED ARRAY Look OF Bit;
Look: TYPE = CHAR ['a..'a+31]; -- 32 bits; indexed from "a"
Bit: TYPE = BOOLFALSE;
noLooks: Looks = ALL[FALSE];
allLooks: Looks = ALL[TRUE];
Offset: TYPE = INT;
MaxOffset: INT = LAST[INT];
General operations on runs
CreateRun: PROC [len: INT, looks: Looks ← noLooks] RETURNS [Runs];
FetchLooks: PROC [runs: Runs, index: INT] RETURNS [Looks];
returns the looks for the character at the given location
CountRuns: PROC [runs: Runs, start, len: INT,
limit: INT ← MaxOffset, merge: BOOLFALSE, firstLooks: Looks ← noLooks
] RETURNS [count: INT, nonempty: BOOL, lastLooks: Looks];
counts the number of runs in the given range
stops counting if reaches limit
if merge is true, then doesn't count first run if its looks=firstLooks
Size: PROC [base: Runs] RETURNS [size: INT];
Operations to change looks
ChangeLooks: PROC [runs: Runs, size: INT, remove, add: Looks,
start: INT ← 0, len: INT ← MaxOffset] RETURNS [Runs];
first remove then add in the given range
Editing Operations
Substr: PROC [base: Runs, start: INT, len: INT] RETURNS [Runs];
returns a substring of the runs
Flatten: PROC [base: Runs] RETURNS [new: Runs];
returns a flattened version of base runs
Concat: PROC [base, rest: Runs, baseLen, restLen: INT] RETURNS [Runs];
returns the concatenation of two Runs
Replace: PROC [base: Runs, start, len: INT, replace: Runs, baseSize, repSize: INT,
tryFlat: BOOLTRUE] RETURNS [Runs];
returns new Runs with the given range replaced
Copy: PROC [dest: Runs, destLoc: INT, source: Runs, start, len, destSize: INT]
RETURNS [Runs];
ReplaceByRun: PROC [dest: Runs, start, len, runLen, destSize: INT,
inherit: BOOL, looks: Looks] RETURNS [Runs];
equivalent to, but faster than,
Replace[dest,start,len,CreateRun[runLen,xlooks],destSize,runLen]
where xlooks determined in the following manner:
if inherit is false, looks specifed in arg list
if inherit is true, looks found in following manner:
if destSize is 0, then take looks from argument list, else
if start > 0, then looks of previous char,
else looks following replacement
LooksStats: PROC [base: Runs, start: INT ← 0, len: INT ← MaxOffset]
RETURNS [size, pieces, depth: INT];
Miscellaneous
OutOfBounds: ERROR;
LooksToRope: PROC [looks: Looks] RETURNS [rope: Rope.ROPE];
RopeToLooks: PROC [rope: Rope.ROPE] RETURNS [looks: Looks];
Internal declarations
LooksBytes: TYPE = MACHINE DEPENDENT RECORD [
byte0(0:0..7), byte1(0:8..15),
byte2(1:0..7), byte3(1:8..15): [0..255] ← 0
];
RunsBody: TYPE = RECORD [
SELECT tag: * FROM
base => [runs: SEQUENCE length: NAT OF Run],
node => [
SELECT case: * FROM
substr => [size: INT, base: Runs, start: INT],
concat => [size: INT, base, rest: Runs, pos: INT],
replace => [size: INT, base, replace: Runs, start, oldPos, newPos: INT],
change => [size: INT, base: Runs, remove, add: Looks, start, len: INT],
ENDCASE
],
ENDCASE
];
RunsBody is modeled after Rope.RopeRep
Run: TYPE = RECORD [after: INT ← 0, looks: Looks ← noLooks];
BaseRuns: TYPE = REF Tbase;
Tbase: TYPE = base RunsBody;
Tsubstr: TYPE = substr node RunsBody;
Tconcat: TYPE = concat node RunsBody;
Treplace: TYPE = replace node RunsBody;
Tchange: TYPE = change node RunsBody;
FlatMax: INT = 10; -- flatten if length of run <= FlatMax
END.