UnparserBuffer.mesa
Copyright Ó 1991 by Xerox Corporation. All rights reserved.
Created December 7, 1982 3:57 pm by Greg Nelson
GNelson, December 6, 1983 2:03 am
Mike Spreitzer July 30, 1986 8:43:58 pm PDT
JKF October 2, 1988 1:13:43 pm PDT
Willie-s, September 25, 1991 9:56 pm PDT
DIRECTORY Atom, IO, Rope;
UnparserBuffer: CEDAR DEFINITIONS =
Formatted output routines. Send a stream of characters through a buffer, delineate the stream into subsequences called objects. The objects can be nested. (Objects are called "groups" in CGN9.) For each object, specify within it a set of breakpoints. The routines will format the text as follows. (1) An object will be printed all on one line if possible. (2) If an object cannot fit on one line, new lines will be started at one or more of the object's breakpoints, so that no text overflows the right margin. (3) With each breakpoint there is associated an integer call the breakpoint's offset. If a new line is started at a breakpoint, then the new line will be indented by the sum of the breakpoint's offset plus the indentation of the first character of the smallest object that contains the breakpoint. (4) Each breakpoint is labelled with the rules used for determining if it breaks. There are four sets of rules available: (width) break if and only if necessary to avoid overflowing the right margin; (united) like width, but also break if the smallest containing object contains (recursively) a breakpoint that breaks; (left-looking) like width, but also break if an object between the breakpoint in question and the preceeding breakpoint directly in the smallest enclosing object, if any, else the beginning of the smallest enclosing object, breaks; and (always) always break. (5) Each breakpoint has a sep, which is a string. If that breakpoint does not break, that string is inserted into the text after the breakpoint. If the breakpoint does break, the string is not inserted into the text.
BEGIN
Nat: TYPE ~ INTEGER[0..INTEGER.LAST];
ROPE: TYPE = Rope.ROPE;
PropList: TYPE = Atom.PropList;
CharSet: TYPE ~ [0..256); --just like in TiogaAccess
Handle: TYPE = REF PublicParts;
PublicParts: TYPE = RECORD [
margin: NAT ¬ 80,
Shouldn't modify this unless between lines.
width: ARRAY CHAR OF INTEGER ¬ ALL [1],
spacers: LIST OF CHAR ¬ NIL,
Width of each element should evenly divide width of previous element.
Width of last element must evenly divide every possible indentation.
output: BufferOutput,
ps: Privates ¬ NIL
];
The fields, except privates, are public --- the client may read and write these synchronously with calls on routines in this interface.
BufferOutputKind: TYPE = {stream};
BufferOutput: TYPE = RECORD [
variant: SELECT kind: BufferOutputKind FROM
stream => [stream: IO.STREAM],
Char props are set by stream.PutF["%p", [refAny[props]]].
Node format is set by stream.PutF["%n", [atom[format]]].
Node props are set by stream.PutF["%n", [refAny[props]]].
Node commentness is set by stream.PutF["%n", [boolean[comment]]].
ENDCASE];
Privates: TYPE = REF PrivateParts;
PrivateParts: TYPE;
BogusInput: ERROR [msg: ROPE];
Create: PROC [publics: PublicParts, miserable: BOOL ¬ TRUE, newline: ROPE ¬ NIL, debug: BOOL ¬ FALSE] RETURNS [Handle];
That's `miser'-able, and chooses one of two implementations.
newline=NIL means to use "\n" (the `native' newline).
When debugging, the object-level actions are translated into text, and no processing is done.
NewInittedHandle: PROC [publics: PublicParts] RETURNS [Handle];
= Create[miserable: FALSE]
Makes the privates and allocates the record.
Sets spacers ← LIST[IO.SP] if it was NIL.
Inits too.
CreatePrivates: PROC [margin: NAT ¬ 80] RETURNS [Privates];
XCreatePrivates: PROC [margin: Nat ¬ 80, miserable: BOOL ¬ TRUE, newline: ROPE ¬ NIL, debug: BOOL ¬ FALSE] RETURNS [Privates];
Init: PROC [h: Handle];
Destroys any information in the internal buffers and makes the buffers all empty. Almost like allocating a new handle, but does not affect the public parts (margin, width, spacers, and output).
Setb: PROC [h: Handle];
Begin an object.
Endb: PROC [h: Handle];
End an object.
Bp: PROC [h: Handle, cond: BreakCondition, offset: INTEGER, sep: ROPE];
Inserts a breakpoint. If the breakpoint breaks, the next line will be indented by offset from the beginning of the object to which this breakpoint belongs.
BreakCondition: TYPE = {width, lookLeft, united, always};
XBp: PROC [h: Handle, cond: XBreakCondition, offset: INTEGER, sep: ROPE];
Allows a wider choice of BreakCondition.
XBreakCondition: TYPE = {never, miser, width, lookLeft, united, always};
Extended break conditions. At the time of this writing (February 21, 1990), there is an input restriction concerning use of miser breakpoints; consult the doc.
Charb: PROC [h: Handle, ch: CHAR];
Outputs the character
Ropeb: PROC [h: Handle, r: ROPE];
Outputs the rope
Textb: PROC [h: Handle, rt: REF READONLY TEXT, startIndex: NAT ¬ 0, count: NAT ¬ NAT.LAST];
Outputs the given substring. If rt is not actually a ROPE, then copying is done.
Atomb: PROC [h: Handle, a: ATOM];
Outputs the pname of the atom
Newlineb: PROC [h: Handle, offset: INTEGER]
= INLINE {Bp[h, always, offset, NIL]};
Just like a breakpoint except that it is certain to break, thus the effect is to insert a new line into the output.
Looksb: PROC [h: Handle, looks: ROPE];
Affects the looks of the following characters in the standard way.
CharPropsb: PROC [h: Handle, props: --immutable--PropList];
The following characters have the given properties.
CharSetb: PROC [h: Handle, charSet: CharSet];
The following characters are in this set.
The following affect nodes that end after insertion point.
NodeFormatb: PROC [h: Handle, format: ATOM];
NodeCommentb: PROC [h: Handle, comment: BOOL];
NodePropsb: PROC [h: Handle, props: --immutable--PropList];
END.