TextLooksImpl.mesa
Copyright Ó 1985, 1986, 1988 by Xerox Corporation. All rights reserved.
written by Bill Paxton, February 1981
Bill Paxton, December 13, 1982 1:17 pm
Maxwell, January 5, 1983 3:54 pm
Russ Atkinson, July 25, 1983 3:36 pm
Michael Plass, March 29, 1985 5:24:46 pm PST
Doug Wyatt, February 17, 1988 5:28:53 pm PST
DIRECTORY
CardTab USING [Create, Ref, Update, UpdateAction],
Rope USING [Cat, Fetch, FromChar, ROPE, Size],
Rosary USING [CatSegments, Fetch, FromItem, MapRuns, ROSARY, RunActionType],
TextLooks USING [Look, Looks, LooksAnd, LooksNot, LooksOr, MaxOffset, noLooks, RunAction, Runs];
TextLooksImpl: CEDAR PROGRAM
IMPORTS CardTab, Rope, Rosary, TextLooks
EXPORTS TextLooks
=
BEGIN
OPEN TextLooks;
ROPE: TYPE ~ Rope.ROPE;
ROSARY: TYPE ~ Rosary.ROSARY;
Rope conversion
LooksToRope:
PUBLIC
PROC [looks: Looks]
RETURNS [rope:
ROPE] = {
FOR lk: TextLooks.Look
IN TextLooks.Look
DO
IF looks[lk] THEN rope ← Rope.Cat[rope, Rope.FromChar[lk]];
ENDLOOP;
};
RopeToLooks:
PUBLIC
PROC [rope:
ROPE]
RETURNS [looks: Looks] = {
looks ← noLooks;
FOR i:
INT
IN [0..Rope.Size[rope])
DO
char: CHAR ← Rope.Fetch[rope, i];
IF char IN Look THEN looks[char] ← TRUE;
ENDLOOP;
};
Edit operations
Size:
PUBLIC
PROC [runs: Runs]
RETURNS [
INT] ~ {
RETURN [IF runs=NIL THEN 0 ELSE runs.size];
};
nilRosary: ROSARY ~ Rosary.FromItem[NIL, INT.LAST]; -- "infinite" rosary of NIL
ItemNotNil: Rosary.RunActionType ~ { RETURN[quit: item#NIL] };
Replace:
PUBLIC
PROC [base: Runs, start, len:
INT, replace: Runs,
baseSize, repSize:
INT]
RETURNS [new: Runs] ~ {
d: ROSARY ~ IF base=NIL THEN nilRosary ELSE base;
d1: INT ~ MAX[LONG[0], MIN[start, baseSize]];
d2: INT ~ d1+MAX[LONG[0], MIN[len, baseSize-d1]];
s: ROSARY ~ IF replace=NIL THEN nilRosary ELSE replace;
r: ROSARY ~ Rosary.CatSegments[[d, 0, d1], [s, 0, repSize], [d, d2, baseSize-d2]];
RETURN[IF Rosary.MapRuns[[r], ItemNotNil] THEN r ELSE NIL];
};
General operations
refFromLooksTab: CardTab.Ref ~ CardTab.Create[];
RefFromLooks:
PROC [looks: Looks]
RETURNS [ref:
REF Looks ←
NIL] ~ {
refFromLooksAction: CardTab.UpdateAction ~ {
PROC [found: BOOL, val: Val] RETURNS [op: UpdateOperation ← none, new: Val ← NIL]
IF found THEN { ref ← NARROW[val]; RETURN[op: none] }
ELSE { ref ← NEW[Looks ← looks]; RETURN[op: store, new: ref] };
};
IF looks=noLooks THEN RETURN[NIL];
CardTab.Update[refFromLooksTab, LOOPHOLE[looks], refFromLooksAction];
IF ref^#looks THEN ERROR;
};
CreateRun:
PUBLIC
PROC [len:
INT, looks: Looks ← noLooks]
RETURNS [Runs] ~ {
refLooks: REF Looks ~ RefFromLooks[looks];
RETURN[Rosary.FromItem[refLooks, len]];
};
FetchLooks:
PUBLIC
PROC [runs: Runs, index:
INT]
RETURNS [Looks] = {
returns the looks for the character at the given location
IF runs#
NIL
THEN
WITH Rosary.Fetch[runs, index]
SELECT
FROM
refLooks: REF Looks => RETURN[refLooks^] ENDCASE;
RETURN[noLooks];
};
CountRuns:
PUBLIC
PROC [runs: Runs,
start:
INT ← 0, len:
INT ← MaxOffset]
RETURNS [count:
INT ← 0] ~ {
countAction: Rosary.RunActionType ~ { count ← count+1 };
[] ← Rosary.MapRuns[[runs, start, len], countAction];
};
MapRuns:
PUBLIC
PROC [runs: Runs, action: RunAction,
start:
INT ← 0, len:
INT ← MaxOffset]
RETURNS [quit:
BOOL] ~ {
mapAction: Rosary.RunActionType ~ {
refLooks: REF Looks ~ NARROW[item];
RETURN action[(IF refLooks=NIL THEN noLooks ELSE refLooks^), repeat];
};
RETURN Rosary.MapRuns[[runs, start, len], mapAction];
};
Operation to change looks
ModifyLooks:
PUBLIC
PROC [old, remove, add: Looks]
RETURNS [Looks] ~ {
RETURN [LooksOr[LooksAnd[old, LooksNot[remove]], add]];
};
ChangeLooks:
PUBLIC
PROC [runs: Runs, size:
INT, remove, add: Looks,
start, len:
INT]
RETURNS [Runs] ~ {
d: ROSARY ← IF runs=NIL THEN nilRosary ELSE runs;
changeLooksAction: Rosary.RunActionType ~ {
PROC [item: Item, repeat: INT] RETURNS [quit: BOOLEAN ← FALSE]
oldLooks: Looks ~ IF item=NIL THEN noLooks ELSE NARROW[item, REF Looks]^;
newLooks: Looks ~ ModifyLooks[oldLooks, remove, add];
replace: ROSARY ~ Rosary.FromItem[RefFromLooks[newLooks], repeat];
end: INT ~ start+repeat;
d ← Rosary.CatSegments[[d, 0, start], [replace], [d, end, size-end]];
start ← end;
};
[] ← Rosary.MapRuns[[d, start, len], changeLooksAction];
RETURN[IF Rosary.MapRuns[[d, 0, size], ItemNotNil] THEN d ELSE NIL];
};
END.