TBaseImpl.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Doug Wyatt, March 6, 1992 4:17 pm PST
DIRECTORY
BasicTime USING [GMT],
Char,
IO,
NodeReader,
Rope,
TBase,
TextEdit,
TextNode,
Tioga;
TBaseImpl: CEDAR PROGRAM
IMPORTS Char, IO, NodeReader, Rope, TextEdit, TextNode
EXPORTS TBase
~ BEGIN OPEN TBase;
ROPE: TYPE ~ Rope.ROPE;
GetChars: PROC [loc1, loc2: Location] RETURNS [rope: ROPE ¬ NIL] ~ {
newline: ROPE ~ TextEdit.GetNewlineDelimiter[TextNode.Root[loc1.node]];
FOR node: Node ← loc1.node, TextNode.StepForward[node] UNTIL node=NIL DO
i0: INT ~ IF node=loc1.node THEN loc1.where ELSE 0;
i1: INT ~ IF node=loc2.node THEN loc2.where ELSE TextEdit.Size[node];
nrope: ROPE ~ Rope.Substr[TextEditBogus.GetRope[node], i0, i1];
rope ¬ Rope.Concat[rope, nrope];
IF node=loc2.node THEN EXIT;
rope ¬ Rope.Concat[rope, newline];
ENDLOOP;
};
Sel: TYPE ~ PACKED RECORD [
pdel: BOOL,
grain: SelectionGrain,
caret: BeforeAfter,
loc: ARRAY BeforeAfter OF Location
];
Map: PUBLIC PROC [direction: Direction, loc1, loc2: Location, action: MapAction]
RETURNS [quit: BOOL ¬ FALSE] ~ {
scratch: NodeReader.Ref ~ NodeReader.New[];
{ -- for EXITS
SELECT direction FROM
forward => {
FOR node: Node ← loc1.node, TextNode.StepForward[node] UNTIL node=NIL DO
rdr: NodeReader.Ref ~ NodeReader.New[node, scratch];
i0: INT ~ IF node=loc1.node THEN loc1.where ELSE 0;
i1: INT ~ IF node=loc2.node THEN loc2.where ELSE NodeReader.Size[rdr];
FOR i: INT IN[i0..i1) DO
IF action[node, i, NodeReader.FetchChar[rdr, i]] THEN GOTO Quit;
ENDLOOP;
IF node=loc2.node THEN EXIT;
ENDLOOP;
};
backward => {
FOR node: Node ← loc2.node, TextNode.StepBackward[node] UNTIL node=NIL DO
rdr: NodeReader.Ref ~ NodeReader.New[node, scratch];
i0: INT ~ IF node=loc1.node THEN loc1.where ELSE 0;
i1: INT ~ IF node=loc2.node THEN loc2.where ELSE NodeReader.Size[rdr];
FOR i: INT DECREASING IN[i0..i1) DO
IF action[node, i, NodeReader.FetchChar[rdr, i]] THEN GOTO Quit;
ENDLOOP;
IF node=loc1.node THEN EXIT;
ENDLOOP;
};
ENDCASE => ERROR;
EXITS Quit => quit ¬ TRUE;
};
NodeReader.Free[scratch];
};
ExpandToBrackets: PUBLIC PROC [char1, char2: XCHAR, loc1, loc2,
bound1, bound2: Location, includeInResult: BOOL]
RETURNS
[found: BOOL ¬ FALSE, result1, result2: Location ¬ [NIL, 0]] ~ {
extend [loc1..loc2) until includes matching left and right brackets
nest: CARD ¬ 0;
action1: MapAction ~ {
SELECT char FROM
char1 => IF nest>0 THEN nest ¬ nest-1 ELSE {
result1 ¬ [node, IF includeInResult THEN index ELSE index+1];
quit ¬ TRUE;
};
char2 => nest ¬ nest+1;
ENDCASE;
};
action2: MapAction ~ {
SELECT char FROM
char2 => IF nest>0 THEN nest ¬ nest-1 ELSE {
result2 ¬ [node, IF includeInResult THEN index+1 ELSE index];
quit ¬ TRUE;
};
char1 => nest ¬ nest+1;
ENDCASE;
};
found ¬ Map[backward, bound1, loc1, action1] AND Map[forward, loc2, bound2, action2];
IF NOT found THEN RETURN[FALSE]; -- to ensure null result locations
};
FindBrackets: PUBLIC PROC [direction: Direction, char1, char2: XCHAR, loc: Location,
bound1, bound2: Location, includeInResult: BOOL ¬ TRUE]
RETURNS
[found: BOOL ¬ FALSE, result1, result2: Location ¬ [NIL, 0]] ~ {
seed: Location;
action1: MapAction ~ {
IF char=char1 THEN { seed ← [node, index+1]; quit ¬ TRUE };
};
action2: MapAction ~ {
IF char=char2 THEN { seed ← [node, index]; quit ¬ TRUE };
};
SELECT direction FROM
forward => found ¬ Map[forward, loc, bound2, action1];
backward => found ¬ Map[backward, bound1, loc, action2];
ENDCASE;
IF NOT found THEN RETURN[FALSE]
ELSE RETURN ExpandToBrackets[char1: char1, char2: char2, loc1: seed, loc2: seed,
bound1: bound1, bound2: bound2, includeInResult: includeInResult];
};
InsertBrackets: PUBLIC PROC [loc1, loc2: Location, rope1, rope2: ROPE,
looks: Looks, props: PropList, includeInResult: BOOL,
event: Event] RETURNS [result1, result2: Location] ~ {
start1, len1, start2, len2: INT;
[resultStart: start2, resultLen: len2] ¬ TextEdit.ReplaceByRope[
root: NIL, dest: loc2.node, start: loc2.where, len: 0,
rope: rope2, charSet: 0, looks: looks, charProps: props, event: event];
[resultStart: start1, resultLen: len1] ¬ TextEdit.ReplaceByRope[
root: NIL, dest: loc1.node, start: loc1.where, len: 0,
rope: rope1, charSet: 0, looks: looks, charProps: props, event: event];
IF loc1.node=loc2.node THEN start2 ¬ start2+len1;
IF includeInResult
THEN RETURN[[loc1.node, start1], [loc2.node, start2+len2]]
ELSE RETURN[[loc1.node, start1+len1], [loc2.node, start2]];
};
MakeControlChar: PUBLIC PROC [node: Node, caret: INT, event: Event]
RETURNS [ok: BOOL ¬ FALSE, resultStart, resultLen: INT ¬ 0] ~ {
IF caret>0 THEN {
index: INT ~ caret-1;
action: TextEdit.ModifyCharsAction ~ {
IF set=0 THEN { char ¬ VAL[ORD[char] MOD 40B]; ok ¬ TRUE };
RETURN[char];
};
TextEdit.ModifyChars[root: NIL, dest: node, start: index, len: 1, action: action, event: event];
IF ok THEN { resultStart ¬ index; resultLen ¬ 1 };
};
};
UnMakeControlChar: PUBLIC PROC [node: Node, caret: INT, event: Event]
RETURNS [ok: BOOL ¬ FALSE, resultStart, resultLen: INT ¬ 0] ~ {
IF caret>0 THEN {
index: INT ~ caret-1;
action: TextEdit.ModifyCharsAction ~ {
IF set=0 AND ORD[char]<40B THEN { char ¬ VAL[100B+ORD[char]]; ok ¬ TRUE };
RETURN[char];
};
TextEdit.ModifyChars[root: NIL, dest: node, start: index, len: 1, action: action, event: event];
IF ok THEN { resultStart ¬ index; resultLen ¬ 1 };
};
};
x0: XCHAR ~ Char.Widen['0];
x7: XCHAR ~ Char.Widen['7];
MakeOctalChar: PUBLIC PROC [node: Node, caret: INT, event: Event]
RETURNS [ok: BOOL ¬ FALSE, resultStart, resultLen: INT ¬ 0] ~ {
end: INT ~ caret;
start: INT ¬ end;
code: Char.CharCode ¬ 0;
set: Char.CharSet ¬ 0;
GetChar: PROC [want: CHAR] RETURNS [BOOL ¬ FALSE] ~ {
IF start>0 THEN {
index: INT ~ start-1;
char: Char.XCHAR ~ TextEdit.FetchChar[node, index];
IF char=Char.Widen[want] THEN { start ¬ index; RETURN[TRUE] };
};
};
GetOctal: PROC [count: NAT] RETURNS [CARDINAL ¬ 0] = {
IF count>0 AND start>0 THEN {
index: INT ~ start-1;
char: Char.XCHAR ~ TextEdit.FetchChar[node, index];
IF char IN [x0..x7] THEN {
digit: [0..8) ~ ORD[char]-ORD[x0];
start ¬ index;
RETURN[IF count>0 THEN GetOctal[count-1]*8+digit ELSE digit];
};
};
};
IF GetChar[')]
THEN {
code ¬ GetOctal[3];
IF NOT GetChar['|] THEN GOTO Bad;
set ¬ GetOctal[3];
IF NOT GetChar['(] THEN GOTO Bad;
}
ELSE {
code ¬ GetOctal[3];
};
IF NOT (start<end AND set<256) THEN GOTO Bad;
[resultStart: resultStart, resultLen: resultLen] ¬ TextEdit.ReplaceByRope[
root: NIL, dest: node, start: start, len: end-start,
rope: Rope.FromChar[VAL[code]], charSet: set,
looks: TextEdit.FetchLooks[node, start],
charProps: TextEdit.GetCharPropList[node, start],
event: event];
ok ¬ TRUE;
EXITS Bad => RETURN[FALSE];
};
UnMakeOctalChar: PUBLIC PROC [node: Node, caret: INT, event: Event]
RETURNS [ok: BOOL ¬ FALSE, resultStart, resultLen: INT ¬ 0] ~ {
IF caret>0 THEN {
index: INT ~ caret-1;
char: XCHAR ~ TextEdit.FetchChar[node, index];
set: Char.CharSet ~ Char.Set[char];
code: Char.CharCode ~ Char.Code[char];
rope: ROPE ~ IF set=0
THEN IO.PutFR1["%03b", IO.card[code]]
ELSE IO.PutFR["(%03b|%03b)", IO.card[set], IO.card[code]];
[resultStart: resultStart, resultLen: resultLen] ¬ TextEdit.ReplaceByRope[
root: NIL, dest: node, start: index, len: 1,
rope: rope, charSet: 0,
looks: TextEdit.FetchLooks[node, index],
charProps: TextEdit.GetCharPropList[node, index],
event: event];
ok ¬ TRUE;
};
};
SetFormat: PUBLIC PROC [node1, node2: Node, format: ATOM, event: Event ¬ NIL] ~ {
FOR node: Node ¬ node1, TextNode.StepForward[node] UNTIL node=NIL DO
TextEdit.PutFormat[node, format, event];
IF node=node2 THEN EXIT;
ENDLOOP
};
SetComment: PUBLIC PROC [node1, node2: Node, comment: BOOL, event: Event ¬ NIL] ~ {
FOR node: Node ¬ node1, TextNode.StepForward[node] UNTIL node=NIL DO
TextEdit.PutComment[node, comment, event];
IF node=node2 THEN EXIT;
ENDLOOP
};
InsertTime: PUBLIC PROC [node: Node, index: INT, gmt: BasicTime.GMT,
looks: Looks ¬ noLooks, props: PropList ¬ NIL, event: Event ¬ NIL]
RETURNS [resultStart, resultLen, dateLen: INT] ~ {
date: ROPE ~ IO.PutR1[[time[gmt]]];
dateLen ¬ Rope.Index[date, 0, ", "];
IF dateLen<Rope.Size[date] THEN dateLen ¬ Rope.Index[date, dateLen+2, " "];
[resultStart: resultStart, resultLen: resultLen] ¬ TextEdit.ReplaceByRope[
root: NIL, dest: node, start: index, len: 0,
rope: date, charSet: 0, looks: looks, charProps: props,
event: event];
};
END.