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: ROSARYIF runs=NIL THEN nilRosary ELSE runs;
changeLooksAction: Rosary.RunActionType ~ {
PROC [item: Item, repeat: INT] RETURNS [quit: BOOLEANFALSE]
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.