DIRECTORY Char USING [Code, Set], IO USING [PutChar, RopeFromROS, ROS, STREAM], NodeProps USING [PutProp, DoSpecs, GetSpecs], NodeReader, PFS, Prop USING [PropList], Rope USING [Concat, FromRefText, Flatten, Length, ROPE, Substr], Rosary USING [Concat, FromItem, ROSARY, Substr], TextEdit, TextNode, Tioga USING [Looks, noLooks, PropList, Node, Location], TiogaAccess USING [TiogaChar], TiogaAccessPrivate USING [Reader, ReaderRep, ropePieces, Writer, WriterRep], TiogaIO USING [FromFile, FromOpenFile, ToFile, ToOpenFile]; TiogaAccessImpl: CEDAR PROGRAM IMPORTS Char, IO, NodeProps, NodeReader, PFS, Rope, Rosary, TextEdit, TextNode, TiogaIO EXPORTS TiogaAccess ~ BEGIN ROPE: TYPE ~ Rope.ROPE; ROSARY: TYPE ~ Rosary.ROSARY; TiogaChar: TYPE ~ TiogaAccess.TiogaChar; Node: TYPE ~ Tioga.Node; Location: TYPE ~ Tioga.Location; Looks: TYPE ~ Tioga.Looks; noLooks: Looks ~ Tioga.noLooks; PropList: TYPE ~ Tioga.PropList; GetExternalProp: PUBLIC PROC [key: ATOM, value: REF] RETURNS [ROPE] ~ { RETURN [NodeProps.GetSpecs[key, value]] }; GetInternalProp: PUBLIC PROC [key: ATOM, value: ROPE] RETURNS [REF] ~ { RETURN [NodeProps.DoSpecs[key, value]] }; Error: PUBLIC ERROR [group: PFS.ErrorGroup, expl: ROPE] ~ CODE; Reader: TYPE ~ TiogaAccessPrivate.Reader; ReaderRep: PUBLIC TYPE ~ TiogaAccessPrivate.ReaderRep; GetLocation: PUBLIC PROC [reader: Reader] RETURNS [Location] ~ { RETURN[[reader.node, reader.index]]; }; LocNumber: PROC [reader: Reader, skip: BOOL ¬ FALSE] RETURNS [INT] ~ { RETURN[TextNode.LocOffset[loc1: [reader.root, 0], loc2: [reader.node, reader.index], skipCommentNodes: skip]]; }; LocWithin: PROC [reader: Reader, count: INT, skip: BOOL ¬ FALSE] RETURNS [Location] ~ { RETURN[TextNode.LocRelative[location: [reader.root, 0], count: count, skipCommentNodes: skip]]; }; SetLocation: PROC [reader: Reader, location: Location] ~ { prevNode: Node ~ reader.node; IF reader.putback#NIL THEN DiscardPutBack[reader]; NodeReader.Set[reader.rdr, reader.node ¬ location.node]; reader.index ¬ MIN[MAX[location.where, 0], NodeReader.Size[reader.rdr]]; IF reader.node#prevNode THEN reader.start ¬ LocNumber[reader]-reader.index; }; SkipToNextNode: PUBLIC PROC [reader: Reader] RETURNS [deltaLevel: INT] ~ { prevNode: Node ~ reader.node; prevSize: INT ~ NodeReader.Size[reader.rdr]; IF reader.putback#NIL THEN DiscardPutBack[reader]; IF prevNode=NIL THEN Error[client, "Attempt to read past end of document"]; [reader.node, deltaLevel] ¬ TextNode.Forward[prevNode]; NodeReader.Set[reader.rdr, reader.node]; reader.index ¬ 0; reader.start ¬ reader.start+prevSize+1; }; GetLen: PROC [reader: Reader, skip: BOOL] RETURNS [INT] ~ { loc1: Location ~ [reader.root, 0]; loc2: Location ~ TextNode.LastLocWithin[reader.root]; break: INT ~ IF (skip AND loc2.node.comment) THEN 0 ELSE 1; RETURN[TextNode.LocOffset[loc1: loc1, loc2: loc2, skipCommentNodes: skip]+break]; }; GetLength: PUBLIC PROC [reader: Reader] RETURNS [INT] ~ { loc1: Location ~ [reader.root, 0]; loc2: Location ~ TextNode.LastLocWithin[reader.root]; RETURN[TextNode.LocOffset[loc1: loc1, loc2: loc2, skipCommentNodes: FALSE]+1]; }; GetIndex: PUBLIC PROC [reader: Reader] RETURNS [index: INT] ~ { RETURN[reader.start+reader.index]; }; SetIndex: PUBLIC PROC [reader: Reader, index: INT] ~ { IF reader.putback#NIL THEN DiscardPutBack[reader]; IF index IN [reader.start..(reader.start+NodeReader.Size[reader.rdr])] THEN reader.index ¬ index-reader.start ELSE SetLocation[reader, LocWithin[reader, index]]; }; GetPosition: PUBLIC PROC [reader: Reader] RETURNS [INT] ~ { RETURN[reader.offset+LocNumber[reader, TRUE]]; }; SetPosition: PUBLIC PROC [reader: Reader, position: INT] ~ { SetLocation[reader, LocWithin[reader, position-reader.offset, TRUE]]; }; FromNode: PUBLIC PROC [node: Node, offset: INT ¬ 0] RETURNS [reader: Reader] ~ { reader ¬ NEW[ReaderRep ¬ [root: TextNode.Root[node], rdr: NodeReader.New[]]]; SetLocation[reader, [node, 0]]; reader.offset ¬ offset-LocNumber[reader, TRUE]; }; FromFile: PUBLIC PROC [fileName: ROPE] RETURNS [Reader] ~ { RETURN [FromNode[TiogaIO.FromFile[PFS.PathFromRope[fileName]].root]] }; FromOpenFile: PUBLIC PROC [openFile: PFS.OpenFile] RETURNS [Reader] ~ { RETURN [FromNode[TiogaIO.FromOpenFile[openFile].root]] }; Get: PUBLIC PROC [reader: Reader] RETURNS [TiogaChar] ~ { node: Node ~ reader.node; index: INT ~ reader.index; IF reader.putback#NIL THEN { t: LIST OF TiogaChar ~ reader.putback; reader.putback ¬ t.rest; RETURN[t.first]; }; IF node=NIL THEN ERROR Error[client, "Attempt to read past end of document"]; IF index0 THEN writer.runs ¬ FoldRosary[rosary: writer.runs, item: TextEdit.ItemFromLooks[writer.newLooks], repeat: writer.newLooksRepeat, size: writer.nodeSize]; writer.newLooks ¬ noLooks; writer.newLooksRepeat ¬ 0; }; GetRuns: PROC [writer: Writer] RETURNS [runs: ROSARY] ~ { FoldRuns[writer]; runs ¬ writer.runs; writer.runs ¬ NIL; }; FoldCharSets: PROC [writer: Writer] ~ { IF writer.newCharSetRepeat>0 THEN writer.charSets ¬ FoldRosary[rosary: writer.charSets, item: TextEdit.ItemFromCharSet[writer.newCharSet], repeat: writer.newCharSetRepeat, size: writer.nodeSize]; writer.newCharSet ¬ 0; writer.newCharSetRepeat ¬ 0; }; GetCharSets: PROC [writer: Writer] RETURNS [charSets: ROSARY] ~ { FoldCharSets[writer]; charSets ¬ writer.charSets; writer.charSets ¬ NIL; }; FoldCharProps: PROC [writer: Writer] ~ { IF writer.newCharPropRepeat>0 THEN writer.charProps ¬ FoldRosary[rosary: writer.charProps, item: writer.newCharProp, repeat: writer.newCharPropRepeat, size: writer.nodeSize]; writer.newCharProp ¬ NIL; writer.newCharPropRepeat ¬ 0; }; GetCharProps: PROC [writer: Writer] RETURNS [charProps: ROSARY] ~ { FoldCharProps[writer]; charProps ¬ writer.charProps; writer.charProps ¬ NIL; }; Put: PUBLIC PROC [writer: Writer, tiogaChar: TiogaChar] ~ { IF tiogaChar.endOfNode THEN { new: Node ¬ TextNode.NewTextNode[]; new.format ¬ tiogaChar.format; new.comment ¬ tiogaChar.comment; new.rope ¬ GetRope[writer]; new.runs ¬ GetRuns[writer]; new.charSets ¬ GetCharSets[writer]; new.charProps ¬ GetCharProps[writer]; FOR l: Prop.PropList ¬ tiogaChar.propList, l.rest UNTIL l = NIL DO NodeProps.PutProp[new, NARROW[l.first.key], l.first.val]; ENDLOOP; IF writer.root = NIL AND writer.level=0 AND tiogaChar.deltaLevel=1 AND Rope.Length[new.rope] = 0 THEN InsertRoot[writer, new] ELSE { IF writer.level < 1 THEN { InsertRoot[writer]; writer.level ¬ 1; }; WHILE writer.level < writer.lastLevel DO writer.last ¬ TextNode.Parent[writer.last]; writer.lastLevel ¬ writer.lastLevel - 1; ENDLOOP; IF writer.level = writer.lastLevel THEN InsertSibling[writer, new] ELSE IF writer.level = writer.lastLevel + 1 THEN InsertChild[writer, new] ELSE Error[client, "Nesting level may not increase by more than one"]; IF writer.first = NIL THEN writer.first ¬ new; }; writer.nodeSize ¬ 0; IF writer.lastLevel # writer.level THEN ERROR; writer.level ¬ MAX[writer.lastLevel + tiogaChar.deltaLevel, 1]; } ELSE { text: REF TEXT ~ writer.textBuf; IF tiogaChar.looks # writer.newLooks THEN { FoldRuns[writer]; writer.newLooks ¬ tiogaChar.looks; }; writer.newLooksRepeat ¬ writer.newLooksRepeat + 1; IF tiogaChar.charSet # writer.newCharSet THEN { FoldCharSets[writer]; writer.newCharSet ¬ tiogaChar.charSet; }; writer.newCharSetRepeat ¬ writer.newCharSetRepeat + 1; IF tiogaChar.propList # writer.newCharProp THEN { FoldCharProps[writer]; writer.newCharProp ¬ tiogaChar.propList; }; writer.newCharPropRepeat ¬ writer.newCharPropRepeat + 1; IF text.length = text.maxLength THEN FoldText[writer]; text[(text.length ¬ text.length+1)-1] ¬ tiogaChar.char; writer.nodeSize ¬ writer.nodeSize + 1; }; }; CopyNode: PUBLIC PROC [writer: Writer, reader: Reader, maxLength: INT] RETURNS [nodeEnd: BOOLEAN] ~ { textRope: ROPE ¬ NIL; textRuns: ROSARY ¬ NIL; textCharSets: ROSARY ¬ NIL; textCharProps: ROSARY ¬ NIL; textSize: INT ¬ 0; WHILE maxLength > 0 AND reader.putback # NIL DO tchar: TiogaChar ¬ Get[reader]; Put[writer, tchar]; maxLength ¬ maxLength - 1; IF tchar.endOfNode THEN RETURN [TRUE]; ENDLOOP; FoldText[writer]; FoldRuns[writer]; FoldCharSets[writer]; FoldCharProps[writer]; textRope ¬ PeekRope[reader]; textSize ¬ Rope.Length[textRope]; textRuns ¬ PeekRuns[reader]; textCharSets ¬ PeekCharSets[reader]; textCharProps ¬ PeekCharProps[reader]; nodeEnd ¬ textSize < maxLength; IF NOT nodeEnd THEN { textRope ¬ Rope.Substr[textRope, 0, maxLength]; textSize ¬ Rope.Length[textRope]; IF textRuns # NIL THEN textRuns ¬ Rosary.Substr[textRuns, 0, textSize]; IF textCharSets # NIL THEN textCharSets ¬ Rosary.Substr[textCharSets, 0, textSize]; IF textCharProps # NIL THEN textCharSets ¬ Rosary.Substr[textCharProps, 0, textSize]; }; FoldRope[writer, textRope]; writer.runs ¬ ConcatRosary[writer.runs, writer.nodeSize, textRuns, textSize]; writer.charSets ¬ ConcatRosary[writer.charSets, writer.nodeSize, textCharSets, textSize]; writer.charProps ¬ ConcatRosary[writer.charProps, writer.nodeSize, textCharProps, textSize]; reader.index ¬ reader.index + textSize; writer.nodeSize ¬ writer.nodeSize + textSize; IF nodeEnd THEN Put[writer, Get[reader]]; }; Nest: PUBLIC PROC [writer: Writer, delta: INT] ~ { level: INT ~ writer.level + delta; IF level > writer.lastLevel+1 THEN Error[client, "Nesting level may not increase by more than one"]; writer.level ¬ level; }; FinishWrite: PUBLIC PROC [writer: Writer, action: PROC [root, first, last: Node]] ~ { IF writer.nodeSize>0 THEN Put[writer, [ charSet: 0, char: '\n, looks: ALL[FALSE], format: NIL, comment: FALSE, endOfNode: TRUE, deltaLevel: 0, propList: NIL ]]; action[writer.root, writer.first, writer.last]; Reset[writer]; }; WriteFile: PUBLIC PROC [writer: Writer, fileName: ROPE] ~ { path: PFS.PATH ~ PFS.PathFromRope[fileName]; action: PROC [root, first, last: Node] ~ { [] ¬ TiogaIO.ToFile[path, root] }; FinishWrite[writer, action]; }; WriteOpenFile: PUBLIC PROC [writer: Writer, openFile: PFS.OpenFile] ~ { action: PROC [root, first, last: Node] ~ { [] ¬ TiogaIO.ToOpenFile[openFile, root] }; FinishWrite[writer, action]; }; WriteReader: PUBLIC PROC [writer: Writer] RETURNS [reader: Reader] ~ { action: PROC [root, first, last: Node] ~ { reader ¬ FromNode[root] }; FinishWrite[writer, action]; }; WriteNode: PUBLIC PROC [writer: Writer] RETURNS [node: Node] ~ { action: PROC [root, first, last: Node] ~ { node ¬ root; writer.root ¬ NIL }; FinishWrite[writer, action]; }; Reset: PUBLIC PROC [writer: Writer] ~ { IF writer.root # NIL THEN { writer.root ¬ NIL; }; writer.first ¬ writer.last ¬ NIL; writer.level ¬ 0; writer.lastLevel ¬ 0; writer.nodeSize ¬ 0; writer.ropes ¬ ALL[NIL]; writer.textBuf.length ¬ 0; writer.runs ¬ NIL; writer.newLooks ¬ noLooks; writer.newLooksRepeat ¬ 0; writer.charSets ¬ NIL; writer.newCharSet ¬ 0; writer.newCharSetRepeat ¬ 0; writer.charProps ¬ NIL; writer.newCharProp ¬ NIL; writer.newCharPropRepeat ¬ 0; }; END. F TiogaAccessImpl.mesa Copyright Σ 1985, 1986, 1988, 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Michael Plass, April 4, 1991 5:39 pm PST Tim Diebert May 13, 1985 12:06:39 pm PDT Russ Atkinson (RRA) July 2, 1985 11:08:52 am PDT Willie-s, April 5, 1991 2:48 pm PST Doug Wyatt, July 9, 1992 5:12 pm PDT Putback stuff is harder than all the rest! Largest size that will come from the small-grain allocator (see Allocator.maxSmallBlockSize) CreateOneMoreLevel: PROC [writer: Writer] ~ { IF writer.root = NIL THEN { InsertRoot[writer, TextNode.NewTextNode[]]; } ELSE { new: TextNode.Ref _ TextNode.NewTextNode[]; new^ _ writer.root^; writer.root.props _ NIL; writer.root.hasstyledef _ writer.root.hasprefix _ writer.root.haspostfix _ writer.root.hascharprops _ writer.root.hascharsets _ writer.root.hasartwork _ FALSE; new.last _ TRUE; new.child _ writer.root; new.next _ NIL; writer.root.next _ new; writer.root _ new; writer.lastLevel _ writer.lastLevel + 1; writer.level _ writer.level + 1; }; }; Collects all the pieces together. TEditInput.FreeTree[writer.root]; Κ•NewlineDelimiter –(cedarcode) style™code™Kšœ ΟeœU™`K™(K™(K™0K™#K™$K™—šΟk ˜ Kšœžœ ˜Kšžœžœžœžœ˜-Kšœ žœ˜-Kšœ ˜ Kšžœ˜Kšœžœ ˜Kšœžœ(žœ ˜@Kšœžœžœ ˜0Kšœ ˜ Kšœ ˜ Kšœžœ,˜7Kšœ žœ ˜Kšœžœ4˜LKšœžœ.˜;K˜—šΟnœžœž˜Kšžœžœžœ+˜WKšžœ ˜Kšœž˜K˜Kšžœžœžœ˜Kšžœžœ žœ˜Kšœ žœ˜(Kšœžœ˜Kšœ žœ˜ Kšœžœ˜Kšœ˜šœ žœ˜ K˜—K˜šŸœžœžœžœ žœžœžœ˜GKšžœ!˜'Kšœ˜K˜—šŸœžœžœžœ žœžœžœ˜GKšžœ ˜&Kšœ˜K˜—š Ÿœžœžœ žœžœžœ˜?K˜—K˜Kšœžœ˜)šœ žœžœ ˜6K˜—K˜šŸ œžœžœžœ˜@Kšžœ˜$Kšœ˜K˜—š Ÿ œžœžœžœžœžœ˜FKšžœi˜oKšœ˜K˜—š Ÿ œžœžœžœžœžœ˜WKšžœZ˜`Kšœ˜K˜—šŸ œžœ)˜:K˜Kšžœžœžœ˜2K˜8Kšœžœžœ2˜HKšžœžœ/˜KKšœ˜K˜—š Ÿœžœžœžœžœ˜JK˜Kšœ žœ˜,Kšžœžœžœ˜2Kšžœ žœžœ7˜KK˜7K˜(K˜K˜'Kšœ˜K˜—š Ÿœžœžœžœžœ˜;K˜"K˜5Kš œžœžœžœžœžœ˜;KšžœK˜QKšœ˜K˜—š Ÿ œžœžœžœžœ˜9K˜"K˜5Kšžœ>žœ˜NKšœ˜K˜—š Ÿœžœžœžœ žœ˜?Kšžœ˜"Kšœ˜K˜—šŸœžœžœžœ˜6Kšžœžœžœ˜2šžœžœ;˜FKšžœ"˜&Kšžœ/˜3—Kšœ˜K˜—š Ÿ œžœžœžœžœ˜;Kšžœ!žœ˜.Kšœ˜K˜—šŸ œžœžœžœ˜žœ˜EKšœ˜K˜—š Ÿœžœžœžœžœ˜PKšœ žœA˜MK˜Kšœ)žœ˜/Kšœ˜K˜—š Ÿœžœžœ žœžœ ˜;Kšžœžœ˜DKšœ˜K˜—š Ÿ œžœžœ žœ žœ ˜GKšžœ0˜6Kšœ˜K˜—K˜šŸœžœžœžœ˜9K˜Kšœžœ˜šžœžœžœ˜Kšœžœžœ˜&Kšœ˜Kšžœ ˜Kšœ˜—Kšžœžœžœžœ7˜Mšžœ"˜$šžœ˜K˜@K˜šžœ˜Kšœ˜Kšœžœ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜Kšœ ž˜K˜—K˜—šžœ˜Kšœ žœ˜-šžœ˜Kšœ ˜ Kšœ Οcœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ž˜Kšœ˜—K˜——K˜K˜—šŸœžœžœžœ˜:K˜Kšœžœ˜Kšžœžœžœžœ˜8Kšžœžœžœžœ7˜Mšžœ"˜$šžœ˜K˜@šžœ˜Kšœ˜Kšœžœ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜Kšœ ž˜K˜—K˜—šžœ˜Kšœ žœ%˜8šžœ˜Kšœ ˜ Kšœ  œ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ž˜Kšœ˜—K˜——K˜K˜—š Ÿœžœžœžœžœžœ˜Ešžœžœžœ˜Kšœ*™*Kš œžœžœžœžœ˜š žœžœžœ$žœžœž˜@Kšžœžœžœžœ˜4Kšžœ #˜@Kšžœ˜—Kšœžœ˜K˜—Kšžœ*žœU˜…Kšœ˜K˜—šŸœžœžœžœ˜4K˜Kš žœ žœžœžœžœ˜"Kšžœ6˜Kšžœ7˜=Kšœ˜K˜—šŸ œžœžœ žœžœ žœžœžœ˜XKšžœžœžœžœžœžœžœ˜&Kšžœžœžœžœ ˜0Kšžœžœžœžœ ˜0Kšžœ˜Kšœ˜K˜—šŸœžœ˜#Kšžœžœ–˜΅K˜K˜Kšœ˜K˜—šŸœžœžœžœ˜9Kšœ˜K˜Kšœžœ˜Kšœ˜K˜—šŸ œžœ˜'Kšžœžœ€˜ΕK˜K˜Kšœ˜K˜—šŸ œžœžœ žœ˜AKšœ˜K˜Kšœžœ˜Kšœ˜K˜—šŸ œžœ˜(KšžœžœŽ˜°Kšœžœ˜K˜Kšœ˜K˜—šŸ œžœžœ žœ˜CKšœ˜K˜Kšœžœ˜Kšœ˜K˜—šŸœžœžœ+˜;šžœžœ˜K˜#K˜K˜ K˜K˜K˜#K˜%šžœ/žœžœž˜BKšœžœ˜9Kšžœ˜—Kš žœžœžœžœžœžœ˜}šžœ˜šžœžœ˜Kšœ˜K˜Kšœ˜—šžœ!ž˜(K˜+K˜(Kšžœ˜—Kšžœ!žœ˜BKšžœžœ%žœ˜IKšžœB˜FKšžœžœžœ˜.Kšœ˜—K˜Kšžœ!žœžœ˜.Kšœžœ-˜?Kšœ˜—šžœ˜Kšœžœžœ˜ šžœ#žœ˜+Kšœ˜K˜"K˜—K˜2šžœ'žœ˜/Kšœ˜K˜&Kšœ˜—K˜6šžœ)žœ˜1Kšœ˜K˜(Kšœ˜—K˜8Kšžœžœ˜6K˜7K˜&Kšœ˜—Kšœ˜K˜—š Ÿœžœžœ-žœžœ žœ˜eKšœ žœžœ˜Kšœ žœžœ˜Kšœžœžœ˜Kšœžœžœ˜Kšœ žœ˜šžœžœžœž˜/K˜Kšœ˜K˜Kšžœžœžœžœ˜&Kšžœ˜—Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜K˜!K˜K˜$K˜&K˜šžœžœ žœ˜K˜/K˜!Kšžœ žœžœ1˜GKšžœžœžœ9˜SKšžœžœžœ:˜UKšœ˜—Kšœ˜K˜MK˜YK˜\K˜'K˜-Kšžœ žœ˜)Kšœ˜K˜—šŸœžœžœžœ˜2Kšœžœ˜"KšžœžœB˜dK˜Kšœ˜K˜—šŸ œžœžœžœ˜UK™!šžœžœ˜'Kšœ ˜ Kšœ ˜ Kšœžœžœ˜Kšœžœ˜ Kšœ žœ˜Kšœ žœ˜K˜Kšœ ž˜ Kšœ˜—K˜/Kšœ˜Kšœ˜K˜—šŸ œžœžœžœ˜;Kšœžœžœžœ˜,KšœžœA˜MKšœ˜Kšœ˜K˜—šŸ œžœžœžœ˜GKšœžœI˜UKšœ˜Kšœ˜K˜—šŸ œžœžœžœ˜FKšœžœ9˜EKšœ˜Kšœ˜K˜—šŸ œžœžœžœ˜@Kšœžœ:žœ˜LKšœ˜Kšœ˜K˜—šŸœžœžœ˜'šžœžœžœ˜Kšœ!™!Kšœžœ˜Kšœ˜—Kšœžœ˜!Kšœ˜Kšœ˜Kšœ˜Kšœžœžœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšœ˜Kšœžœ˜Kšœ˜Kšœ˜Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ˜K˜—K˜—Kšžœ˜—…—?hY°