-- UnparserBuffer.mesa, December 7, 1982 3:57 pm by Greg Nelson

-- Last Edited by GNelson, December 6, 1983 2:03 am

-- 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 either united or ununited. If any breakpoint of an object is broken, then all that object's united breakpoints are broken. An ununited breakpoint is broken only if it is necessary to do so to prevent overflowing the right margin.

DIRECTORY IO, Rope, Atom;

UnparserBuffer: DEFINITIONS =
BEGIN

Handle: TYPE = REF HandleRec;

NewHandle: PROC RETURNS [Handle];

Init: PUBLIC 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
h.margin, h.output,
--
h.width, or h.clientData, which are the feilds that a client may alter.

Setb: PUBLIC PROC [h: Handle]; -- begin an object

Endb: PUBLIC PROC [h: Handle]; -- end an object

Bp: PUBLIC PROC[h: Handle,
     united: BOOL,
offset: INTEGER];

-- 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.

Charb: PUBLIC PROC [h: Handle, ch: CHAR]; -- outputs the character

Ropeb: PUBLIC PROC[h: Handle, r: Rope.ROPE]; -- outputs the rope

Atomb: PUBLIC PROC[h: Handle, a: ATOM]; -- outputs the pname of the atom

Newlineb: PUBLIC PROC[h: Handle, offset: INTEGER];

-- just like a breakpoint except that it is certain to break, thus the effect is
-- to insert a new line into the output.


HandleRec: TYPE = RECORD [

-- The following four fields may be set by the client if the default values are
-- not satisfactory. The
output field must be set by the client. As all character widths
-- currently must be expressed as multiples of the width of the space character, the
-- main purpose of the
width array is to set the widths of certain characters to zero
-- to pass them through the buffer as some kind of code for later processing.

margin: PUBLIC INTEGER ← 80,
width: ARRAY CHAR OF INTEGERALL [1],
output: IO.STREAM,
clientData: REF ← NIL,

-- Client, kindly ignore the remaining fields.

bufferWidth: INTEGER ← 0,
bl, cl, br, cr, sr, srx: INTEGER ← 0,
c: ARRAY [0 .. n) OF CHAR,
b: ARRAY [0 .. n) OF RECORD [
type: {setb, breakpoint},
united: BOOL,
offset: INTEGER,
p: [0 .. n)],
s: ARRAY [0 .. n) OF INTEGER,
indentation: INTEGER ← 0];

n: INT = 256;  -- size of various internal buffers; plenty large for reasonable margins.
     -- should be a parameter of the module but ....

END.