-- TexNodeDefs.Mesa

-- definitions related to Nodes
-- last written by Doug Wyatt, December 19, 1979  12:33 AM

DIRECTORY
	TexDefs: FROM "TexDefs",
	TexGlueDefs: FROM "TexGlueDefs",
	TexTokenDefs: FROM "TexTokenDefs";

TexNodeDefs: DEFINITIONS =
BEGIN OPEN TexGlueDefs,TexDefs;

NodeType: TYPE = {char, string, box, rule, glue, space, kern, leader, hyph,
	penalty, disc, eject, mark, ins, unset, listhead};

StringLength: TYPE = [0..32);
maxstringlength: CARDINAL = LAST[StringLength];
HyphControl: TYPE = {on,off};

Node: TYPE = RECORD
	[
	link: NodePtr,
	body: SELECT type: NodeType FROM
		char,disc => [c: FChar],
		string => [font: Font, length: StringLength,
			text: PACKED ARRAY [0..0) OF Char],
		box =>
			[
			dir: Direction, -- which direction (v or h)
			altered: BOOLEAN, -- if TRUE, box dimensions have been altered
			encloses: BOOLEAN, -- if TRUE, this box encloses its contents' bbox
			head: NodePtr,
			width, depth, height, shiftamt: Dimn,
			glueset: GlueSet
			],
		rule => [width, depth, height: Dimn],
		glue => [g: GluePtr],
		space, kern => [s: Dimn], -- glue with no stretch or shrink
		-- kern nodes usually have s<0. The line-breaking and justification
		-- machinery must be able to distinguish between kerns and spaces
		leader => [p: NodePtr],
		hyph => [auto: HyphControl],
		penalty => [pts: Penalty],
		eject => NULL,
		mark => [t: TexTokenDefs.TokenListPtr],
		ins =>
			[
			where: TopBotType,
			dir: Direction,
			vlist: NodePtr,
			glue: GluePtr
			],
		unset =>
			[
			box: BoxNodePtr, -- points to box Node
			totalStretch: FlexSums
			],
		listhead => [last: NodePtr], -- points to last node in list
		ENDCASE
	];

NodePtr: TYPE = POINTER TO Node;
CharNodePtr: TYPE = POINTER TO char Node;
StringNodePtr: TYPE = POINTER TO string Node;
RuleNodePtr: TYPE = POINTER TO rule Node;
BoxNodePtr: TYPE = POINTER TO box Node;
GlueNodePtr: TYPE = POINTER TO glue Node;
InsNodePtr: TYPE = POINTER TO ins Node;
UnsetNodePtr: TYPE = POINTER TO unset Node;

NodeListPtr: TYPE = POINTER TO listhead Node;

-- given  list: NodeListPtr,
-- 	list.link  points to the first node in the list
-- 	list.last   points to the last node in the list
-- if the list is empty, list.link=NIL and list.last=list
-- if the list has one node, list.link=list.last
-- list.last.link=NIL at all times
-- to append a node [pointed to by p] to the list, do:
-- 	list.last.link←p; list.last←p; [p.link←NIL;]

InitNodeList: PROCEDURE RETURNS[NodeListPtr];
MakeNodeList: PROCEDURE[p: NodePtr] RETURNS[NodeListPtr];
FinishNodeList: PROCEDURE[NodeListPtr] RETURNS[NodePtr];
StoreNode: PROCEDURE[list: NodeListPtr, p: NodePtr];
--	= INLINE BEGIN list.last.link←p; list.last←p END;
InsertNode: PROCEDURE[list: NodeListPtr, p: NodePtr];
RemoveNode: PROCEDURE[list: NodeListPtr] RETURNS[NodePtr];
InsertNodeList: PROCEDURE[list, inslist: NodeListPtr];
	-- inserts inslist at the front of list; destroys inslist's list head
AppendNodeList: PROCEDURE[list, applist: NodeListPtr];
	-- appends applist at the back of list; destroys applist's list head
RemoveNodeList: PROCEDURE[list: NodeListPtr, p: NodePtr]
	RETURNS[NodeListPtr];
	-- removes nodes up to and including p from the front of list;
	-- makes and returns a new list
FreeNodeList: PROCEDURE[list: NodeListPtr] = INLINE
	BEGIN DsNodeList[FinishNodeList[list]] END;

stringNodeSize: PRIVATE CARDINAL = SIZE[string Node];
StringNodeSize: PROCEDURE[length: CARDINAL] RETURNS[CARDINAL]
	= INLINE BEGIN RETURN[stringNodeSize+(length+1)/2] END;

DsNode: PROCEDURE[NodePtr]; -- free a node and anything it points to
DsNodeList: PROCEDURE[NodePtr]; -- free a list of nodes

MakeBoxNode: PROCEDURE[dir: Direction, head: NodePtr, h,d,w: Dimn]
	RETURNS[BoxNodePtr];
NullBox: PROCEDURE RETURNS[BoxNodePtr];
MakeCharNode: PROCEDURE[FChar] RETURNS[CharNodePtr];
MakeStringNode: PROCEDURE[Font,STRING] RETURNS[StringNodePtr];
MakeDiscNode: PROCEDURE[FChar] RETURNS[NodePtr];
MakeEjectNode: PROCEDURE RETURNS[NodePtr];
MakeGlueNode: PROCEDURE[GluePtr] RETURNS[GlueNodePtr];
MakeHyphNode: PROCEDURE[HyphControl] RETURNS[NodePtr];
MakeInsNode: PROCEDURE[tb: TopBotType, dir: Direction,
	hd: NodePtr, g: GluePtr] RETURNS[InsNodePtr];
MakeUnsetNode: PROCEDURE[box: BoxNodePtr,fPtr: FlexSumsPtr]
	RETURNS[UnsetNodePtr];
MakeKernNode: PROCEDURE[Dimn] RETURNS[NodePtr];
MakeLeaderNode: PROCEDURE[NodePtr] RETURNS[NodePtr];
MakeMarkNode: PROCEDURE[TexTokenDefs.TokenListPtr] RETURNS[NodePtr];
MakePenaltyNode: PROCEDURE[Penalty] RETURNS[NodePtr];
MakeRuleNode: PROCEDURE[width,height,depth: Dimn] RETURNS[RuleNodePtr];
MakeSpace: PROCEDURE[Dimn] RETURNS[NodePtr];

TexNode: PROGRAM;

END.