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
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.