PutInterFileImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
written by Paxton. May 1981
McGregor. September 10, 1982 1:17 pm
Maxwell, January 5, 1983 12:59 pm
Russ Atkinson, July 25, 1983 2:58 pm
Plass, March 14, 1985 1:27:50 pm PST
Rick Beach, March 27, 1985 1:05:30 pm PST
Doug Wyatt, August 28, 1986 6:03:03 pm PDT
DIRECTORY
Atom USING [GetPName],
FileWriter USING [Close, OpenC, Ref, ToRope, ToStream, WriteChar, WriteText],
FS USING [Close, Open, OpenFile],
InterFile USING [],
IO USING [STREAM],
NodeProps USING [GetSpecs, MapProps],
Rope USING [Flatten, ROPE, Size],
RopeReader USING [FreeRopeReader, Get, GetRopeReader, Ref, SetPosition],
RunReader USING [FreeRunReader, GetRunReader, MergedGet, Ref, SetPosition],
TextLooks USING [CountRuns, Flatten, Look, Looks, noLooks, Runs],
TextNode USING [FirstChild, IsLastSibling, Next, Node, Parent];
PutInterFileImpl: CEDAR PROGRAM
IMPORTS Atom, FileWriter, FS, NodeProps, Rope, RopeReader, RunReader, TextLooks, TextNode
EXPORTS InterFile
= BEGIN OPEN InterFile, TextNode;
ROPE: TYPE ~ Rope.ROPE;
ToRope: PUBLIC PROC [node: Node, flatten: BOOLTRUE] RETURNS [output: ROPE] = {
data: FileWriter.Ref = FileWriter.ToRope[FALSE].data;
Header[data];
Finish[data,node,flatten];
Trailer[data];
output ← FileWriter.Close[NIL,NIL,data,FALSE].output;
};
ToStream: PUBLIC PROC
[stream: IO.STREAM, node: Node, flatten: BOOLTRUE] RETURNS [count: INT] = {
data: FileWriter.Ref = FileWriter.ToStream[stream,FALSE].data;
Header[data];
Finish[data,node,flatten];
Trailer[data];
count ← FileWriter.Close[NIL,NIL,data,FALSE].count;
};
ToFile: PUBLIC PROC
[fileName: ROPE, node: Node, start: INT ← 0, flatten: BOOLTRUE] RETURNS [count: INT] = {
file: FS.OpenFile = FS.Open[fileName, write];
data: FileWriter.Ref = FileWriter.OpenC[file,start,FALSE].data;
Header[data];
Finish[data,node,flatten];
Trailer[data];
count ← FileWriter.Close[NIL,NIL,data,FALSE].count;
FS.Close[file];
};
Header: PROC [data: FileWriter.Ref] = {
WC['{,data];
FileWriter.WriteText["Interdoc/Interchange/0.0",data];
WC[15C,data];
};
Trailer: PROC [data: FileWriter.Ref] = {
WC['},data] };
WC: PROC [c: CHAR, data: FileWriter.Ref] = { FileWriter.WriteChar[c,data] };
Finish: PROC [data: FileWriter.Ref, root: Node, flatten: BOOL,
runReader: RunReader.Ref ← NIL, ropeReader: RopeReader.Ref ← NIL,
nameText: REF TEXTNIL, indent: NAT ← 0] = {
WriteChar: PROC [c: CHAR] = { FileWriter.WriteChar[c,data] };
WriteAtom: PROC [atom: ATOM] = {
WriteRope[Atom.GetPName[atom]] };
WriteRope: PROC [r: ROPE, start: INT ← 0, len: INTINT.LAST] = {
WriteChar['<]; WriteSimpleRope[r, start, len]; WriteChar['>] };
WriteSimpleRope: PROC [r: ROPE, start: INT ← 0, len: INTINT.LAST] = {
size: INT ~ Rope.Size[r];
rem: INT ~ size-start;
RopeReader.SetPosition[ropeReader, r, start];
THROUGH [0..MIN[len, rem]) DO
char: CHAR ~ RopeReader.Get[ropeReader];
SELECT char FROM
'>, '# => WriteInt[char];
ENDCASE => FileWriter.WriteChar[char,data];
ENDLOOP;
};
WriteInt: PROC [c: CHAR] = {
i: [0..255] ← LOOPHOLE[c];
WriteChar['#];
WriteChar['A + i/16];
WriteChar['A + i MOD 16];
WriteChar['#] };
WriteLooks: PROC [lks: TextLooks.Looks] = {
Look: TYPE = TextLooks.Look;
WriteRope["looks=<"];
FOR c:Look IN Look DO IF lks[c] THEN WriteChar[c]; ENDLOOP;
WriteChar['>] };
WriteProp: PROC [name: ATOM, value: REF] RETURNS [BOOL] = {
WritePropName: PROC = {
WriteAtom[name];
WriteChar['=] };
WITH value SELECT FROM
x: Node => { -- prop value is a node
WritePropName;
Finish[data,x,flatten,
runReader,ropeReader,nameText,indent+nesting];
LineBreak };
ENDCASE => { -- write specs as a rope
specs: ROPE ← NodeProps.GetSpecs[name,value];
IF specs # NIL THEN {
WritePropName;
WriteRope[specs];
LineBreak }};
RETURN [FALSE] };
LineBreak: PROC = {
WriteChar[15C];
FOR i: NAT IN [0..indent) DO WriteChar[' ]; ENDLOOP };
nesting: NAT = 4; -- number of spaces per level of nesting
formatName: ATOM;
terminal: BOOL;
node,nodeChild: Node;
freeRunReader, freeRopeReader: BOOLTRUE;
IF runReader=NIL THEN runReader ← RunReader.GetRunReader[]
ELSE freeRunReader ← FALSE;
IF ropeReader=NIL THEN ropeReader ← RopeReader.GetRopeReader[]
ELSE freeRopeReader ← FALSE;
IF nameText=NIL THEN nameText ← NEW[TEXT[32]];
node ← root;
DO -- start the node
rope: ROPE;
size: INT;
runs: TextLooks.Runs;
LineBreak; WriteChar['{];
-- write format
IF (formatName ← node.formatName) # NIL THEN {
WriteRope[Atom.GetPName[formatName]]; LineBreak[] };
-- write node props
IF node.props # NIL THEN [] ← NodeProps.MapProps[node,WriteProp];
-- now write contents
IF flatten THEN { -- flatten rope and runs
node.rope ← Rope.Flatten[node.rope];
node.runs ← TextLooks.Flatten[node.runs] };
rope ← node.rope; size ← Rope.Size[rope];
IF (runs ← node.runs) = NIL THEN WriteRope[rope]
ELSE { -- write each run separately
loc, cnt, numRuns: INT ← 0;
[numRuns,,] ← TextLooks.CountRuns[runs,0,size];
RunReader.SetPosition[runReader,runs,0];
WHILE (cnt𡤌nt+1) <= numRuns DO
looks: TextLooks.Looks;
len: INT;
[len,looks] ← RunReader.MergedGet[runReader];
IF looks = TextLooks.noLooks THEN WriteRope[rope, loc, len]
ELSE {
WriteChar['{];
WriteLooks[looks];
WriteRope[rope, loc, len];
WriteChar['}] };
loc ← loc+len;
ENDLOOP;
IF loc # size THEN ERROR };
-- move to the next node
terminal ← (nodeChild𡤏irstChild[node])=NIL;
IF ~terminal THEN { node ← nodeChild; indent ← indent+nesting }
ELSE { -- node has no children
WriteChar['}];
DO IF node=root THEN GOTO Finis;
IF ~IsLastSibling[node] THEN { node ← Next[node]; EXIT };
node ← Parent[node]; WriteChar['}]; indent ← indent-nesting;
ENDLOOP };
REPEAT Finis => {
IF freeRunReader THEN RunReader.FreeRunReader[runReader];
IF freeRopeReader THEN RopeReader.FreeRopeReader[ropeReader] };
ENDLOOP;
};
END.