-- TextNode.Mesa
-- written by Bill Paxton.  December 1980
-- last written by Paxton.  March 19, 1981  10:10 AM

DIRECTORY
Rope USING [Ref],
TextLooks USING [Runs];

TextNode: DEFINITIONS =
BEGIN

Card: TYPE = LONG CARDINAL;

Ref: TYPE = REF Body;
Body: TYPE = RECORD [
	next: Ref, -- points to next sibling, or if last=true, to parent
	child: Ref, -- points to first child, if any, of this node
	props: NodeProps, -- points to node property list
	typename: TypeName ← nullTypeName, -- name of type for the node
	last: BOOLEAN ← FALSE, -- true if this is last sibling
	hasstyle: BOOLEAN ← FALSE, -- true if node has style prop
	body: SELECT kind:OfNode FROM
					text => [rope: Rope.Ref, runs: TextLooks.Runs],
					other => [ref: REF ANY],
					ENDCASE];

OfNode: TYPE = {text,other};

TextBody: TYPE = text Body;
RefTextNode: TYPE = REF TextBody;
OtherBody: TYPE = other Body;
RefOtherNode: TYPE = REF OtherBody;

NodeProps: TYPE = REF NodePropsBody;
NodePropsBody: TYPE; -- exported by NodePropsImpl

-- here are some inlines for use with nodes

Next: PROC [n: Ref] RETURNS [Ref] = INLINE {
	RETURN[IF n.last THEN NIL ELSE n.next]};

Props: PROC [n: Ref] RETURNS [NodeProps] = INLINE {
	RETURN[n.props]};

NodeType: PROC [n: Ref] RETURNS [TypeName] = INLINE {
	RETURN[n.typename]};

IsLastSibling: PROC [n: Ref] RETURNS [BOOLEAN] = INLINE {
	RETURN[n.last]};

FirstChild: PROC [n: Ref] RETURNS [Ref] = INLINE {
	RETURN[n.child]};

NthChild: PROC [n: Ref, location: Card] RETURNS [child: Ref] = INLINE {
	FOR child ← FirstChild[n], Next[child] UNTIL child=NIL OR location=0 DO
		location ← location-1; ENDLOOP};

CountChildren: PROC [n: Ref] RETURNS [count: Card] = INLINE {
	count ← 0;
	FOR child: Ref ← FirstChild[n], Next[child] UNTIL child=NIL DO
		count ← count+1; ENDLOOP};

CountFollowing: PROC [n: Ref] RETURNS [count: Card] = INLINE {
	count ← 0;
	UNTIL (n ← Next[n])=NIL DO count ← count+1; ENDLOOP};

CountToParent: PROC [n: Ref] RETURNS [count: Card, parent: Ref] = INLINE {
	count ← 0;
	UNTIL n.last DO count ← count+1; n ← n.next ENDLOOP;
	parent ← n.next};

HasStyle: PROC [n: Ref] RETURNS [BOOLEAN] = INLINE {
	RETURN[n.hasstyle]};

NodeRope: PROC [n: RefTextNode] RETURNS [Rope.Ref] = INLINE {
	RETURN[n.rope]};

NodeRuns: PROC [n: RefTextNode] RETURNS [TextLooks.Runs] = INLINE {
	RETURN[n.runs]};

Parent: PROC [n: Ref] RETURNS [Ref] = INLINE { 
	UNTIL n.last DO n ← n.next ENDLOOP; RETURN [n.next]};

LastSibling: PROC [n: Ref] RETURNS [Ref] = INLINE {
	UNTIL n.last DO n ← n.next ENDLOOP; RETURN [n]};

FirstSibling: PROC [n: Ref] RETURNS [Ref] = INLINE {
	RETURN[FirstChild[Parent[n]]]};

Previous: PROC [n: Ref] RETURNS [nx: Ref] = INLINE {
	FOR nx ← FirstSibling[n], nx.next UNTIL nx.next=n DO ENDLOOP};

-- TypeNames and StyleNames are the same as names in TiogaJam
	-- declared as separate records to get type checking

TypeName: TYPE = RECORD [local: BOOLEAN, index: NAT];
nullTypeName: TypeName = [FALSE, 0];

StyleName: TYPE = RECORD [local: BOOLEAN, index: NAT];
nullStyleName: StyleName = [FALSE, 0];

END.