DIRECTORY Atom USING [GetPName], CedarProcess USING [Priority, DoWithPriority], FileOps USING [comment, endNode, endOfFile, IntBytes, LengthByte, look1, look2, look3, looks, looksFirst, LooksIndex, prop, PropIndex, propShort, rope, runs, startNode, startNodeFirst, terminalTextNode, terminalTextNodeFirst, ThirdByte, FormatIndex], FileWriter USING [Close, OpenC, Ref, ToRope, ToStream, WriteChar, WriteRope], FS USING [Create, OpenFile, StreamFromOpenFile, StreamOpen], IO USING [Close, Error, GetIndex, PutChar, PutRope, RopeFromROS, ROS, SetLength, STREAM], NodeProps USING [GetSpecs, MapProps], PGSupport USING [CreatePGF, EnterLooks, EnterProp, EnterFormatName, FreePGF, PGF], PrincOpsUtils USING [], PutGet USING [], Rope, RopeEdit USING [BlankChar], RopeIO USING [PutRope, ToFileC], RopeReader USING [FreeRopeReader, GetRopeReader, Ref], RunReader USING [FreeRunReader, GetRunReader, MergedGet, Ref, SetPosition], TextLooks USING [CountRuns, Flatten, Look, Looks, LooksBytes, noLooks, Runs, RunsBody], TextNode USING [FirstChild, Forward, IsLastSibling, NarrowToTextNode, Next, NodeProps, Parent, Ref, RefTextNode], UserProfile USING [Number]; PutFileImpl: CEDAR PROGRAM IMPORTS Atom, CedarProcess, FileWriter, FS, IO, npI: NodeProps, PGSupport, Rope, RopeEdit, RopeIO, RopeReader, RunReader, TextLooks, TextNode, UserProfile EXPORTS PutGet = BEGIN OPEN PutGet; ROPE: TYPE = Rope.ROPE; ToRope: PUBLIC PROC [node: TextNode.Ref, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT, output: ROPE] = { control, comment, data: FileWriter.Ref; simple: BOOL; [output, simple] _ SimpleFile[node]; IF simple THEN { dataLen _ count _ Rope.Size[output]; RETURN }; [control, comment, data] _ FileWriter.ToRope[]; Finish[control, comment, data, node, flatten]; [dataLen, count, output] _ FileWriter.Close[control, comment, data, textOnly]; }; ToStream: PUBLIC PROC [stream: IO.STREAM, node: TextNode.Ref, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT] = { control, comment, data: FileWriter.Ref; rope: ROPE; simple: BOOL; [rope, simple] _ SimpleFile[node]; IF simple THEN { RopeIO.PutRope[stream, rope]; dataLen _ count _ Rope.Size[rope]; RETURN }; [control, comment, data] _ FileWriter.ToStream[stream]; Finish[control, comment, data, node, flatten]; [dataLen, count, ] _ FileWriter.Close[control, comment, data, textOnly]; }; ToFile: PUBLIC PROC [fileName: ROPE, node: TextNode.Ref, start: INT _ 0, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT] = { file: FS.OpenFile; fileName _ fileName.Flatten[0, fileName.SkipTo[0, "!"]]; file _ FS.Create[name: fileName, keep: UserProfile.Number["Tioga.defaultKeep", 2]]; [dataLen, count] _ ToFileC[file, node, start, flatten, textOnly]; }; ToFileC: PUBLIC PROC [file: FS.OpenFile, node: TextNode.Ref, start: INT _ 0, flatten, textOnly: BOOL _ FALSE] RETURNS [dataLen, count: INT] = { ropeToFile: PROC [rope: ROPE] = { RopeIO.ToFileC[file, rope, start] }; opener: PROC RETURNS [control, comment, data: FileWriter.Ref] = { [control, comment, data] _ FileWriter.OpenC[file, start] }; [dataLen, count] _ FileIt[ropeToFile, opener, node, flatten, textOnly]; }; savePriority: CedarProcess.Priority _ normal; FileIt: PROC [ropeToFile: PROC [ROPE], opener: PROC RETURNS [control, comment, data: FileWriter.Ref], node: TextNode.Ref, flatten, textOnly: BOOL ] RETURNS [dataLen, count: INT] = { innerFileIt: PROC ~ { rope: ROPE; simple: BOOL; [rope, simple] _ SimpleFile[node]; IF simple THEN { ropeToFile[rope]; dataLen _ count _ Rope.Size[rope]; } ELSE { control, comment, data: FileWriter.Ref; [control, comment, data] _ opener[]; Finish[control, comment, data, node, flatten]; [dataLen, count, ] _ FileWriter.Close[control, comment, data, textOnly]; }; }; CedarProcess.DoWithPriority[savePriority, innerFileIt]; }; SimpleFile: PROC [root: TextNode.Ref] RETURNS [rope: ROPE, simple: BOOL] = { SimpleNode: PROC [node: TextNode.Ref] RETURNS [ROPE, BOOL] = { HasInterestingProp: PROC RETURNS [BOOL] = { Check: PROC [name: ATOM, value: REF] RETURNS [BOOL] = { RETURN [SELECT name FROM $Viewer, $LockedViewer, $FromTiogaFile, $DocumentLock, $FileCreateDate, $FileExtension => FALSE, ENDCASE => TRUE] }; RETURN [npI.MapProps[node, Check, FALSE, FALSE]] }; text: TextNode.RefTextNode = node; IF node.formatName=NIL AND NOT text.comment AND NOT HasInterestingProp[] THEN { IF node.runs=NIL THEN RETURN [node.rope, TRUE] ELSE WITH node.runs SELECT FROM r: REF TextLooks.RunsBody.base => IF r.length=1 AND r[0].looks=TextLooks.noLooks THEN RETURN [node.rope, TRUE]; ENDCASE; }; RETURN [NIL, FALSE] }; IF root=NIL THEN RETURN [NIL, TRUE]; [rope, simple] _ SimpleNode[root]; IF ~simple THEN RETURN; -- not a simple root node IF root.child=NIL THEN RETURN; -- simple root and no child IF rope # NIL OR -- root has child and text, so not simple ~root.child.last OR root.child.child # NIL THEN RETURN [NIL, FALSE]; -- more than one child, so not simple [rope, simple] _ SimpleNode[root.child]; }; Finish: PROC [control, comment, data: FileWriter.Ref, root: TextNode.Ref, flatten: BOOL] = { WriteChar: PROC [c: CHAR, writer: FileWriter.Ref] = { FileWriter.WriteChar[c, writer] }; WriteAtom: PROC [atom: ATOM] = { WriteControlRope[Atom.GetPName[atom]] }; WriteRope: PROC [r: ROPE, writer: FileWriter.Ref] = { WriteLen[Rope.Size[r]]; FileWriter.WriteRope[r, Rope.Size[r], writer, ropeReader]; WriteChar[15C, writer] }; WriteControlRope: PROC [r: ROPE] = { size: INT _ Rope.Size[r]; WriteLen[size]; FileWriter.WriteRope[r, size, control, ropeReader] }; WriteLen: PROC [len: INT] = { first, second, fourth: FileOps.LengthByte; third: FileOps.ThirdByte; lenBytes: FileOps.IntBytes _ LOOPHOLE[len]; IF lenBytes.fourth # 0 THEN { fourth.data _ lenBytes.fourth; first.others _ second.others _ third.others _ TRUE }; IF lenBytes.thirdTop # 0 OR lenBytes.thirdBottom # 0 THEN { third.dataTop _ lenBytes.thirdTop; third.dataBottom _ lenBytes.thirdBottom; first.others _ second.others _ TRUE }; IF lenBytes.second # 0 THEN { second.data _ lenBytes.second; first.others _ TRUE }; first.data _ lenBytes.first; WriteChar[LOOPHOLE[first], control]; IF first.others THEN { WriteChar[LOOPHOLE[second], control]; IF second.others THEN { WriteChar[LOOPHOLE[third], control]; IF third.others THEN { WriteChar[LOOPHOLE[fourth], control] } } } }; WriteLooks: PROC [lks: TextLooks.LooksBytes] = { WriteChar[LOOPHOLE[lks.byte0], control]; WriteChar[LOOPHOLE[lks.byte1], control]; WriteChar[LOOPHOLE[lks.byte2], control]; WriteChar[LOOPHOLE[lks.byte3], control] }; CountLookBits: PROC [lks: TextLooks.Looks] RETURNS [cnt: NAT] = { cnt _ 0; FOR c: CHAR IN TextLooks.Look DO IF lks[c] THEN cnt _ cnt+1; ENDLOOP }; WriteLookChars: PROC [lks: TextLooks.Looks] = { FOR c: CHAR IN TextLooks.Look DO IF lks[c] THEN WriteChar[c, control]; ENDLOOP }; WriteProp: PROC [name: ATOM, value: REF] RETURNS [BOOL] = { -- write specs as a rope specs: ROPE _ npI.GetSpecs[name, value]; IF specs=NIL THEN RETURN [FALSE]; [ok, propindex] _ PGSupport.EnterProp[name, pgf]; IF ok THEN { -- can use short form WriteChar[FileOps.propShort, control]; WriteChar[LOOPHOLE[propindex], control] } ELSE { -- must write full prop name WriteChar[FileOps.prop, control]; WriteAtom[name] }; WriteControlRope[specs]; RETURN [FALSE] }; formatName: ATOM; ok, terminal: BOOL; formatindex: FileOps.FormatIndex; looksindex: FileOps.LooksIndex; propindex: FileOps.PropIndex; node, nodeChild: TextNode.Ref; pgf: PGSupport.PGF _ PGSupport.CreatePGF[]; runReader: RunReader.Ref _ RunReader.GetRunReader[]; ropeReader: RopeReader.Ref _ RopeReader.GetRopeReader[]; nameText: REF TEXT _ NEW[TEXT[32]]; node _ root; DO -- first write format rope: ROPE; size: INT; runs: TextLooks.Runs; terminal _ (nodeChild_TextNode.FirstChild[node])=NIL; [ok, formatindex] _ PGSupport.EnterFormatName[formatName _ node.formatName, pgf]; IF ok THEN { WriteChar[formatindex+(IF ~terminal THEN FileOps.startNodeFirst ELSE FileOps.terminalTextNodeFirst), control] } ELSE { WriteChar[IF ~terminal THEN FileOps.startNode ELSE FileOps.terminalTextNode, control]; WriteControlRope[IF formatName#NIL THEN Atom.GetPName[formatName] ELSE NIL] }; IF node.props # NIL THEN [] _ npI.MapProps[node, WriteProp, FALSE, FALSE]; IF flatten THEN { -- flatten rope and runs node.rope _ Rope.Balance[node.rope]; node.runs _ TextLooks.Flatten[node.runs]; }; rope _ node.rope; size _ Rope.Size[rope]; IF (runs _ node.runs) # NIL THEN { loc, cnt, numRuns: INT _ 0; [numRuns, , ] _ TextLooks.CountRuns[runs, 0, size]; WriteChar[FileOps.runs, control]; WriteLen[numRuns]; RunReader.SetPosition[runReader, runs, 0]; WHILE (cnt_cnt+1) <= numRuns DO looks: TextLooks.Looks; len: INT; [len, looks] _ RunReader.MergedGet[runReader]; [ok, looksindex] _ PGSupport.EnterLooks[looks, pgf]; IF ok THEN WriteChar[FileOps.looksFirst+looksindex, control] ELSE { -- must write out the looks SELECT CountLookBits[looks] FROM 1 => { WriteChar[FileOps.look1, control]; WriteLookChars[looks] }; 2 => { WriteChar[FileOps.look2, control]; WriteLookChars[looks] }; 3 => { WriteChar[FileOps.look3, control]; WriteLookChars[looks] }; ENDCASE => { WriteChar[FileOps.looks, control]; WriteLooks[LOOPHOLE[looks]] } }; WriteLen[len]; loc _ loc+len; ENDLOOP; IF loc # size THEN ERROR }; IF node.comment THEN { -- put text in comment area of file WriteChar[FileOps.comment, control]; WriteRope[rope, comment] } ELSE { -- put text in data area of file WriteChar[FileOps.rope, control]; WriteRope[rope, data] }; IF ~terminal THEN node _ nodeChild ELSE { -- node has no children DO IF node=root THEN GOTO Finis; IF ~TextNode.IsLastSibling[node] THEN { node _ TextNode.Next[node]; EXIT }; node _ TextNode.Parent[node]; WriteChar[FileOps.endNode, control]; ENDLOOP }; REPEAT Finis => { WriteChar[FileOps.endOfFile, control]; RunReader.FreeRunReader[runReader]; RopeReader.FreeRopeReader[ropeReader]; PGSupport.FreePGF[pgf] }; ENDLOOP }; WriteMesaFilePlain: PUBLIC PROC [fileName: ROPE, root: TextNode.Ref] = { h: IO.STREAM _ FS.StreamOpen[fileName: fileName, accessOptions: $create, keep: UserProfile.Number["Tioga.defaultKeep", 2]]; WritePlain[h, root, TRUE]; IO.Close[h]; }; WriteFilePlain: PUBLIC PROC [fileName: ROPE, root: TextNode.Ref] = { h: IO.STREAM _ FS.StreamOpen[fileName: fileName, accessOptions: $create, keep: UserProfile.Number["Tioga.defaultKeep", 2]]; WritePlain[h, root]; IO.Close[h]; }; WriteFileCPlain: PUBLIC PROC [file: FS.OpenFile, root: TextNode.Ref] = { h: IO.STREAM = FS.StreamFromOpenFile[file, $write]; WritePlain[h, root]; IO.Close[h]; }; WriteRopePlain: PUBLIC PROC [root: TextNode.Ref, restoreDashes: BOOL _ FALSE] RETURNS [output: ROPE] = { h: IO.STREAM = IO.ROS[]; WritePlain[h, root, restoreDashes]; RETURN [IO.RopeFromROS[h]] }; WritePlain: PUBLIC PROC [h: IO.STREAM, root: TextNode.Ref, restoreDashes: BOOL _ FALSE] = { HasInitialDashes: PROC [r: ROPE] RETURNS [BOOL] = { loc: INT _ 0; size: INT = Rope.Size[r]; c: CHAR; WHILE loc < size AND RopeEdit.BlankChar[c _ Rope.Fetch[r, loc]] DO loc _ loc+1; ENDLOOP; IF loc > size-2 OR c # '- OR Rope.Fetch[r, loc+1] # '- THEN RETURN [FALSE]; RETURN [TRUE] }; node: TextNode.Ref _ root; level: INTEGER _ 0; levelDelta: INTEGER; first: BOOL _ TRUE; DO text: TextNode.RefTextNode; [node, levelDelta] _ TextNode.Forward[node]; IF node=NIL THEN EXIT; IF first THEN first _ FALSE ELSE IO.PutChar[h, '\n]; -- carriage returns between nodes level _ level+levelDelta; IF (text _ TextNode.NarrowToTextNode[node])=NIL THEN LOOP; THROUGH [1..level) DO IO.PutChar[h, '\t]; ENDLOOP; -- output level-1 tabs IF restoreDashes AND text.comment AND ~HasInitialDashes[text.rope] THEN IO.PutRope[h, "-- "]; -- restore the leading dashes for Mesa comments IO.PutRope[h, text.rope]; ENDLOOP; { ENABLE IO.Error => IF ec = NotImplementedForThisStream THEN GOTO Exit; IO.SetLength[h, IO.GetIndex[h]] } EXITS Exit => RETURN }; END. φPutFileImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, October 31, 1985 10:52:43 am PST Rick Beach, March 27, 1985 1:04:56 pm PST Doug Wyatt, April 10, 1985 8:33:58 pm PST Russ Atkinson (RRA) August 7, 1985 12:49:05 pm PDT When add a new "system" property that should not go on files, add registration at end of TEditDocuments2Impl so will not copy/write the property. write node props now write contents first the rope, then the looks move to the next node Κ ‹˜codešœ™Kšœ Οmœ1™˜NKšžœžœ5˜=Kšžœžœ9žœ žœ˜ZKšœ žœ˜&Kšœ žœ>žœ˜SKšœžœ˜Kšœžœ˜Kšœ˜Kšœ žœ˜Kšœžœ˜!Kšœ žœ'˜7Kšœ žœ=˜LKšœ žœI˜XKšœ žœc˜qKšœ žœ ˜—K˜šΠbl œžœž˜Kšžœ!žœžœl˜šKšžœ˜Kšœžœžœ˜—˜Kšžœžœžœ˜K˜šΟnœžœžœ)žœžœžœžœ žœ˜yK˜'Kšœžœ˜ K˜$Kšžœžœ(žœ˜?K˜/K˜.K˜NK˜—K˜š œžœžœ žœžœ)žœžœžœžœ˜€K˜'Kšœžœ˜ Kšœžœ˜ K˜"šžœžœ˜K˜K˜"Kšžœ˜K˜—K˜7K˜.K˜HK˜—K˜š œžœžœ žœžœžœžœžœžœ˜‹Kšœžœ ˜K˜8KšœžœJ˜SK˜AK˜—K˜š œžœžœžœ&žœžœžœžœžœ˜Kšœ žœžœ*˜Fšœžœžœ-˜A˜9K˜——K˜GK˜—K˜Kšœ-˜-š œžœžœžœ žœžœSžœžœžœ˜·šœ žœ˜Kšœžœ˜ Kšœžœ˜ K˜"šžœ˜ šžœ˜K˜K˜"K˜—šžœ˜K˜'K˜$K˜.K˜HK˜——K˜—Kšœ7˜7K˜—K˜š   œžœžœžœ žœ˜Lš   œžœžœžœžœ˜>š œžœžœžœ˜+š  œžœžœ žœžœžœ˜7šžœžœž˜KšœZžœ˜aKšœ‘™‘Kšžœžœ˜—K˜—Kšžœžœžœ˜1K˜—K˜"šžœžœžœžœžœžœžœ˜OJš žœ žœžœžœ žœ˜.šžœžœ žœž˜Kšœžœžœ žœž˜UKšžœ žœ˜Kšžœ˜—Jšœ˜—Kšžœžœžœ˜K˜—Kš žœžœžœžœžœžœ˜$K˜"Kšžœ žœžœΟc˜1Kš žœ žœžœžœ‘˜:Kšžœžœžœ‘)˜:Kšœžœžœžœžœžœžœ‘%˜jK˜(K˜—K˜š œžœGžœ˜\Kš  œžœžœ@˜XK˜š  œžœžœ˜ K˜&K˜—K˜š  œžœžœ˜5K˜K˜:K˜K˜—K˜š œžœžœ˜$Kšœžœ˜K˜K˜3K˜—K˜š œžœžœ˜K˜*K˜Kšœžœ˜+šžœžœ˜K˜šœ.žœ˜3K˜——šžœžœžœ˜;K˜"K˜(šœžœ˜$K˜——šžœžœ˜šœ.žœ˜3K˜——K˜Kšœ žœ˜$šžœžœ˜Kšœ žœ˜%šžœžœ˜Kšœ žœ˜$šžœžœ˜Kšœ žœ˜%K˜—K˜—K˜—K˜—K˜š  œžœ ˜0Kšœ žœ˜(Kšœ žœ˜(Kšœ žœ˜(Kšœ žœ˜(K˜—K˜š  œžœžœžœ˜AK˜Kš žœžœžœžœžœžœ˜EK˜—K˜š œžœ˜/Kš žœžœžœžœžœžœ˜OK˜—K˜š   œžœžœ žœžœžœ‘˜TKšœžœ˜(Kš žœžœžœžœžœ˜!K˜1šžœ˜šžœ‘˜K˜&Kšœ žœ˜(K˜—šžœ‘˜#K˜!K˜K˜——K˜Kšžœžœ˜K˜—Kšœ žœ˜Kšœžœ˜K˜!K˜K˜K˜Kšœžœ˜+K˜4K˜8Kš œ žœžœžœžœ˜#K˜ šžœ‘˜Kšœžœ˜ Kšœžœ˜ K˜Kšœ1žœ˜6KšœQ˜Qšžœžœ˜ Jšœžœ žœžœ)˜mJšœ˜—šžœ˜Kšœ žœ žœžœ$˜VKš œžœ žœžœžœžœ˜LK˜—Kšœ™Kš žœžœžœ$žœžœ˜JKšœ™Kšœ™šžœ žœ‘˜*K˜$K˜)K˜—K˜)šžœžœžœ˜"Kšœžœ˜K˜3K˜!K˜K˜*šžœž˜K˜Kšœžœ˜ K˜.K˜4Kšžœž˜ K˜1šžœ‘˜"šžœž˜ ˜)K˜K˜—˜)K˜K˜—˜)K˜K˜—Kšžœ˜ K˜"Kšœ žœ ˜K˜—K˜—K˜K˜Kšžœ˜—Kšžœ žœžœ˜K˜—šžœžœ‘#˜:K˜$K˜K˜—šžœ‘ ˜'K˜!K˜K˜—Kšœ™šžœ žœ˜"šžœ‘˜šžœžœ žœžœ˜ Kšžœžœžœ˜KK˜K˜$Kšžœ˜—K˜——šžœ ˜K˜&K˜#K˜&K˜K˜—Kšžœ˜—K˜—K˜š œžœžœ žœ˜HKšœžœžœžœj˜{Kšœžœ˜Kšžœ ˜ K˜—K˜š œžœžœ žœ˜DKšœžœžœžœj˜{K˜Kšžœ ˜ K˜—K˜š œžœžœžœ"˜HKšœžœžœžœ"˜3K˜Kšžœ ˜ K˜—K˜š œžœžœ%žœžœžœ žœ˜iKš œžœžœžœžœ˜Kšœ#˜#Kšžœžœ˜K˜—K˜š  œžœžœžœžœ%žœžœ˜[š  œžœžœžœžœ˜3Kšœžœ˜ Kšœžœ˜Kšœžœ˜šžœ žœ,ž˜BKšœ žœ˜—Kš žœžœžœžœžœžœ˜KKšžœžœ˜K˜—K˜Kšœžœ˜Kšœ žœ˜Kšœžœžœ˜šž˜K˜K˜,Kšžœžœžœžœ˜šžœžœ ž˜Kšžœžœ‘!˜:—K˜Kšžœ*žœžœžœ˜:Kš žœ žœžœžœ‘˜IKšžœžœžœž˜GKšžœ‘/˜EKšžœ˜Kšžœ˜—š œžœžœ žœ"žœžœ˜HKšžœžœ˜ K˜—Kšžœ žœ˜K˜—K˜Kšžœ˜—K˜—…—.^=ί