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; 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]] ~ { 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 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 dateLenK˜—K˜—š Ÿœžœ žœžœžœ ˜6šžœ žœ žœ˜Kšœžœ ˜Kšœ žœ#˜3šžœžœ žœ˜Kšœžœžœ˜"K˜Kšžœžœ žœžœ˜=K˜—K˜—K˜—šžœ ˜šžœ˜K˜Kšžœžœ žœžœ˜!K˜Kšžœžœ žœžœ˜!K˜—šžœ˜K˜K˜——Kš žœžœ žœ žœžœ˜-KšœQžœ@žœƒ˜šKšœžœ˜ Kšžœžœžœ˜K˜K˜—šŸœžœžœžœžœžœžœžœ ˜„šžœ žœ˜Kšœžœ ˜Kšœžœ#˜.K˜#Kšœ&˜&šœžœžœ˜Kšžœžœžœ ˜%Kšžœžœžœ žœ ˜:—KšœQžœ©˜ύKšœžœ˜ K˜—K˜K˜—š Ÿ œžœžœžœžœ˜Qšžœ0žœžœž˜DKšœ(˜(Kšžœ žœžœ˜Kšžœ˜—K˜K˜—š Ÿ œžœžœžœžœ˜Sšžœ0žœžœž˜DK˜*Kšžœ žœžœ˜Kšžœ˜—K˜K˜—šŸ œžœžœžœžœ-žœžœžœ#žœ˜ΌKšœžœžœ˜#Kšœ$˜$Kšžœžœ,˜KKšœQžœl˜ΐK˜—J˜Kšžœ˜—…—j+6