<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
package kdocDocIter;

use strict;
use kdocAstUtil;
use kdocAstSearch;

=head1 kdocDocIter -- Iteration over DocNode children

=head2 TextIter -- Iterate over doc data (non-attribute children).

	p: docNode, sS, sE, sTextP, sRefP, sSectP, sPreP, sImageP,
		sParaP, sListS, sListE, sListP

"$s..." means subref.

$..S and $...E means start and end, P means "print".
eg $sS means doc start, $sTextP means print text.

All subrefs receive ( node, text ) as params (text should be ignored
if it is not pertinent to the type).

It is safe to leave any subref undefined.

=cut

sub TextIter
{
	my ( $docNode, $sS, $sE, $sTextP, $sRefP, $sSectP, $sPreP, $sImageP,
		$sParaP, $sListS, $sListE, $sListP ) = @_;
	return if !defined $docNode;

	my $text = $docNode-&gt;{Text};
	return if !defined $text || $#$text &lt; 0;

	my $lastType = "";

	$sS-&gt;( $docNode ) if defined $sS;

	foreach my $tnode ( @$text ) {
		my $type = $tnode-&gt;{NodeType};
		my $name = $tnode-&gt;{astNodeName};
		
		if ( $lastType eq "ListItem" &amp;&amp; $type ne $lastType ) {
			$sListE-&gt;( $tnode, $name ) if defined $sListE;
		}

		if ( $type eq "DocText" ) {
			$sTextP-&gt;( $tnode, $name ) if defined $sTextP;
		}
		elsif ( $type eq "Pre" ) {
			$sPreP-&gt;( $tnode, $name, $tnode-&gt;{Desc} ) if defined $sPreP;
		}
		elsif ( $type eq "Ref" ) {
			$sRefP-&gt;( $tnode, $name, $tnode-&gt;{Ref} ) if defined $sRefP;
		}
		elsif ( $type eq "DocSection" ) {
			$sSectP-&gt;( $tnode, $name ) if defined $sSectP;
		}
		elsif ( $type eq "Image" ) {
			$sImageP-&gt;( $tnode, $name, $tnode-&gt;{Path} ) if defined $sImageP;
		}
		elsif( $type eq "ParaBreak" ) {
			$sParaP-&gt;( $tnode, $name ) if defined $sParaP;
		}
		elsif( $type eq "ListItem" ) {
			if ( $lastType ne "ListItem" ) {
				$sListS-&gt;( $tnode, $name ) if defined $sListS;
			}
			$sListP-&gt;( $tnode, $name ) if defined $sListP;
		}
		else {
#			warn "Unknown DocNode:Text node: $name ($type)\n";
		}

		$lastType = $type;
	}

	if ( $lastType eq "ListItem" ) {
		$sListE-&gt;( undef, undef ) if defined $sListE;
	}

	$sE-&gt;( $docNode ) if defined $sE;
}

=head2 ParamIter

	p: docNode, sS, sE, sP

Iterate over @params in the doc node.

=cut

sub ParamIter
{
	my ( $docNode, $sS, $sE, $sP ) = @_;
	return unless defined $docNode &amp;&amp; defined $docNode-&gt;{Text};

	my @params = ();
	kdocAstUtil::findNodes( \@params, $docNode-&gt;{Text}, "NodeType", "Param" );
	return unless $#params &gt;= 0;

	$sS-&gt;() if defined $sS;

	foreach my $param ( @params ) {
		$sP-&gt;( $param-&gt;{Name}, $param-&gt;{astNodeName} ) if defined $sP;
	}

	$sE-&gt;() if defined $sE;
}

sub SeeAlso
{
	my ( $node, $nonesub, $startsub, $printsub, $endsub ) = @_;

	if( !defined $node ) {
		$nonesub-&gt;() if defined $nonesub;
		return;
	}

	my $doc = $node;

	if ( $node-&gt;{NodeType} ne "DocNode" ) {
		$doc = $node-&gt;{DocNode};
		if ( !defined $doc ) {
			$nonesub-&gt;() if defined $nonesub;
			return;
		}
	}

	if ( !defined $doc-&gt;{See} ) {
		$nonesub-&gt;() if defined $nonesub;
		return;
	}

	my $see = $doc-&gt;{See};
	my $ref = $doc-&gt;{SeeRef};

	if ( $#$see &lt; 0 ) {
		$nonesub-&gt;() if defined $nonesub;
		return;
	}

	$startsub-&gt;( $node ) if defined $startsub;

	for my $i ( 0..$#$see ) {
		my $seelabel = $see-&gt;[ $i ];
		my $seenode = undef;
		if ( defined $ref ) {
			$seenode = $ref-&gt;[ $i ]; 
		}

		$printsub-&gt;( $seelabel, $seenode ) if defined $printsub;
	}

	$endsub-&gt;( $node ) if defined $endsub;

	return;
}

sub Throws
{
	my ( $node, $nonesub, $startsub, $printsub, $endsub ) = @_;

	if( !defined $node ) {
		$nonesub-&gt;() if defined $nonesub;
		return;
	}

	my $doc = $node;

	if ( $node-&gt;{NodeType} ne "DocNode" ) {
		$doc = $node-&gt;{DocNode};
		if ( !defined $doc ) {
			$nonesub-&gt;() if defined $nonesub;
			return;
		}
	}

	if ( !defined $doc-&gt;{Throws} ) {
		$nonesub-&gt;() if defined $nonesub;
		return;
	}

	my $see = $doc-&gt;{Throws};

	if ( $#$see &lt; 0 ) {
		$nonesub-&gt;() if defined $nonesub;
		return;
	}

	$startsub-&gt;( $node ) if defined $startsub;

	if ( defined $printsub ) {
		foreach my $throwtext ( @$see ) {
			$printsub-&gt;( $throwtext );
		}
	}

	$endsub-&gt;( $node ) if defined $endsub;

	return;
}


=head2 Deref

	p: text, node, sTextP, sRefP, sParamP

	Iterates over text and @ref parts of a text string.

=cut

sub Deref
{
	my ( $text, $node, $sTextP, $sRefP, $sParamP ) = @_;

	foreach my $part ( split (/(\@(?:ref|p)\s+[^\s\.]+)/, $text ) ) {
		if ( $part =~ /\@(ref|p)\s+([^\s\.]+)/ ) {
			$part = $2;
			my $call = $1;
			if ( defined $sRefP &amp;&amp; $call eq "ref" ) {
				my $ref = kdocAstSearch::findRef( $node, $part );

				if ( defined $ref ) {
					$sRefP-&gt;( $ref );
					next;
				}
			}
			elsif( defined $sParamP &amp;&amp; $call eq "p" ) {
				$sParamP-&gt;( $part );
				next;
			}
		}

		$sTextP-&gt;( $part ) if defined $sTextP;
	}
}


=head2 TextRef

	p: text, node, sTextP, sRefP

Iterate over every word in the text, calling $sRefP for every reference
match and $sTextP for everything else (or if $sRefP is undefined).

=cut

sub TextRef
{
	my ( $text, $node, $sTextP, $sRefP ) = @_;

	foreach my $part ( split( /([^\w:]+)/, $text ) ) {
		if ( $part =~ /^[\w:]/ ) {
			if ( defined $sRefP ) {
				my $ref = kdocAstSearch::findRef( $node, $part );

				if ( defined $ref ) {
					$sRefP-&gt;( $ref );
					next;
				}
			}
		}

		$sTextP-&gt;( $part ) if defined $sTextP;
	}
}

1;
</pre></body></html>