## -*- perl -*-
## ----------------------------------------------------------------------
## spec/text: SGML conversion specification for plain text output
## ----------------------------------------------------------------------
## Copyright (C) 1998 Ardo van Rangelrooij
## Copyright (C) 1996 Ian Jackson
##
## This is free software; see the GNU General Public Licence
## version 2 or later for copying conditions.  There is NO warranty.
## ----------------------------------------------------------------------

## ----------------------------------------------------------------------
use POSIX;

## ----------------------------------------------------------------------
$format = '.text';

## ----------------------------------------------------------------------
## language definition
( $lang = POSIX::setlocale( LANG ) ) =~ s/_.*//;
if ( -r $ENV{ 'DEBIANDOCSGMLSPEC' } . '/i18n/' . $lang . $format )
{
    do $ENV{ 'DEBIANDOCSGMLSPEC' } . '/i18n/' . $lang . $format;
}
else
{
    %lang = (
	     'abstract' => 'Abstract',
	     'copyright notice' => 'Copyright Notice',
	     'contents' => 'Contents',
	     );
}

## ----------------------------------------------------------------------
## layout definitions
$perindent = 5;
$linewidth = 79;
$textwidth = 75;
$unbreakbackoff = 20;
$indentlevel = 1;

## ----------------------------------------------------------------------
## tag processing
## ----------------------------------------------------------------------

## ----------------------------------------------------------------------
sub start_chapt
{
    _sect( -1, @_ );
}
sub end_chapt
{
}

## ----------------------------------------------------------------------
sub start_appendix
{
    _sect( -2, @_ );
}
sub end_appendix
{
}

## ----------------------------------------------------------------------
sub start_heading
{
}
sub end_heading
{
    _end_heading();
    $indentlevel = 1;
}

## ----------------------------------------------------------------------
sub start_footnotebody
{
    ( $element, $event ) = @_;
    push( @elements, $element );
    push_output( 'string' );
    my $footnotenum = _a( 'NUMBER' );
    _para_lhtag( "[$footnotenum]" );
    $indentlevel++;
}
sub end_footnotebody
{
    $indentlevel--;
    my $footnotebody = pop_output;
    $element = pop( @elements );
    _output_footnotebody( $footnotebody ) if length( $footnotebody );
}

## ----------------------------------------------------------------------
sub start_list
{
    _start_list( 'plain', @_ );
}
sub end_list
{
    _end_list();
}

## ----------------------------------------------------------------------
sub start_enumlist
{
    _start_list( 'enum', @_ );
}
sub end_enumlist
{
    _end_list();
}

## ----------------------------------------------------------------------
sub start_taglist
{
    _start_list( 'tag', @_ );
}
sub end_taglist
{
    _end_list();
}

## ----------------------------------------------------------------------
sub start_item
{
    if ( $listtypes[0] eq 'enum' )
    {
        _para_lhtag( ++( $listcounters[0] ) . '.' );
    }
    elsif ( $listtypes[0] eq 'plain' )
    {
        _para_lhtag( ( " " x ( $perindent - 2 ) ) . "*" );
    }
}
sub end_item
{
}

## ----------------------------------------------------------------------
## output definitions
## ----------------------------------------------------------------------

## ----------------------------------------------------------------------
sub _output_start_book
{
}
sub _output_end_book
{
    output( "\n\n" );
    _h_rule();
    output( "\n\n" );
    _para_new();
    output( $title );
    _para_end( 1 );
    output( "\n" );
    for ( $index = 0; $index <= $#authors; $index++ )
    {
	_para_new();
	output( $authors[ $index ] );
	_para_end( 1 );
    }
    output( "\n" );
    _para_new();
    output( $version ) if length( $version );
    _para_end( 1 );
    output( "\n" );
}

## ----------------------------------------------------------------------
sub _output_titlepag
{
    output( "\n" );
    _para_new();
    output( $title );
    _para_end( 0, 'centre-underdash' );
    output( "\n" );
    $verbatim--;
    for ( $index = 0; $index <= $#authors; $index++ )
    {
	_para_new();
	output( $authors[ $index ] );
	_para_end( 0, 'centre' );
    }
    if ( length( $version ) )
    {
	output( "\n" );
	_para_new();
	output( $version );
	_para_end( 0, 'centre' );
	output( "\n" );
    }
    output( "\n" );
    _h_rule();
    if ( length( $abstract ) )
    {
	output( "\n" );
	output( "\n" );
	_start_heading();
	output( $lang{ 'abstract' } );
	_end_heading();
	output( "\n" );
	_para_new();
	output( $abstract );
	_para_end( $indentlevel );
    }
    if ( length ( $copyright ) )
    {
	$blanklinedone = 0;
        output( "\n" );
	output( "\n" );
        _start_heading();
        output( $lang{ 'copyright notice' } );
	_end_heading();
        output( "\n" );
        output( $copyright );
    }
}

## ----------------------------------------------------------------------
sub _output_copyrightsummaries
{
    my ( @copyrightsummaries ) = @_;
    foreach $copyrightsummary ( @copyrightsummaries )
    {
	_para_new();
	output( $copyrightsummary );
	_para_end( $indentlevel );
    }
}

## ----------------------------------------------------------------------
sub _output_toc
{
    my ( $toc ) = @_;
    output( "\n\n" );
    _h_rule();
    output( "\n\n" );
    _start_heading();
    output( $lang{ 'contents' } );
    _end_heading();
    output( $toc );
}

## ----------------------------------------------------------------------
sub _output_tocentry
{
    my ( $tocentry ) = @_;
    my $toclevel = _num_level( _a( 'LEVEL' ) );
    return if $toclevel > $tocdetail;
    output( "\n" ) if ! $toclevel;
    _para_lhtag( _a( 'CHAPT' ) . _a( 'SECT' ) . '.' );
    _para_lhtag( '' );
    _para_lhtag( '' ) if $toclevel > 1;
    _para_new();
    output( $tocentry );
    _para_end( $toclevel > 1 ? 4 : 3 );
}

## ----------------------------------------------------------------------
sub _output_p
{
    my ( $paragraph ) = @_;
    _insert_blankline();
    _para_new();
    output( $paragraph );
    _para_end( $indentlevel );
}

## ----------------------------------------------------------------------
sub _output_example
{
    my ( $example ) = @_;
    $example =~ s/[ \t]+\n/\n/g;
    $example =~ s/^\n+//;
    $example =~ s/\n+$//;
    my @el = split( /\n/, $example );
    my @ec = @el;
    grep( s/\0..\0//g, @ec );
    my @toolong = grep( length( $_ ) + ( $perindent * ( $indentlevel + 1 ) )
			> $linewidth, @ec );
    if ( @toolong )
    {
        output( "\0=l\0" );
    }
    else
    {
        output( "\0=o\0" );
    }
    output( join( "\0=n\0", @el ) );
    output( "\0=c\0" );
}

## ----------------------------------------------------------------------
sub _output_footnotes
{
}

## ----------------------------------------------------------------------
sub _output_footnote
{
}

## ----------------------------------------------------------------------
sub _output_footnotebody
{
    my ( $footnotebody ) = @_;
    output( $footnotebody );
}

## ----------------------------------------------------------------------
sub _output_footnoteref
{
    my ( $footnoteref ) = @_;
    output( "[$footnoteref]" );
}

## ----------------------------------------------------------------------
sub _output_tag
{
    my ( $tag ) = @_;
    _insert_blankline();
    _para_new();
    output( $tag );
    _para_end( $indentlevel - 1 );
    $blanklinedone = 1;
}

## ----------------------------------------------------------------------
sub _output_em
{
    my ( $em ) = @_;
    output( '_' );
    output( "$em" );
    output( '_' );
}

## ----------------------------------------------------------------------
sub _output_strong
{
    my ( $strong ) = @_;
    output( '_' );
    output( "$strong" );
    output( '_' );
}

## ----------------------------------------------------------------------
sub _output_var
{
    my ( $var ) = @_;
    output( '<' );
    output( "$var" );
    output( '>' );
}

## ----------------------------------------------------------------------
sub _output_package
{
    my ( $package ) = @_;
    output( '`' );
    output( "$package" );
    output( "'" );
}

## ----------------------------------------------------------------------
sub _output_prgn
{
    my ( $prgn ) = @_;
    output( '`' );
    output( "$prgn" );
    output( "'" );
}

## ----------------------------------------------------------------------
sub _output_file
{
    my ( $file ) = @_;
    output( '`' );
    output( "$file" );
    output( "'" );
}

## ----------------------------------------------------------------------
sub _output_tt
{
    my ( $tt ) = @_;
    output( '`' );
    output( "$tt" );
    output( "'" );
}

## ----------------------------------------------------------------------
sub _output_qref
{
    my ( $qref ) = @_;
    output( $qref );
}

## ----------------------------------------------------------------------
sub _output_ref
{
    my ( $ref ) = @_;
    my $refname = _a( 'HNAME' );
    output( $refname . ', `' );
    output( $ref );
    output( "'" );
}

## ----------------------------------------------------------------------
sub _output_manref
{
    my ( $name, $section ) = @_;
    output( $name . '(' . $section . ')' );
}

## ----------------------------------------------------------------------
sub _output_email
{
    my ( $email ) = @_;
    output( " " ) if ( $in_author );
    output( '<' );
    output( "$email" );
    output( '>' );
}

## ----------------------------------------------------------------------
sub _output_ftpsite
{
    my ( $ftpsite ) = @_;
    output( $ftpsite );
}

## ----------------------------------------------------------------------
sub _output_ftppath
{
    my ( $ftpsite, $ftppath ) = @_;
    output( $ftppath );
}

## ----------------------------------------------------------------------
sub _output_httpsite
{
    my ( $httpsite ) = @_;
    output( $httpsite );
}

## ----------------------------------------------------------------------
sub _output_httppath
{
    my ( $httpsite, $httppath ) = @_;
    output( $httppath );
}

## ----------------------------------------------------------------------
sub _output_url
{
    my ( $id, $name ) = @_;
    _odata( $name ) if $name ne "";
    output( " (" ) if $name ne "";
    _odata( $id );
    output( ")" ) if $name ne "";
}

## ----------------------------------------------------------------------
sub _odata
{
    ( $data, $event ) = @_;
    output( $data );
}

## ----------------------------------------------------------------------
## helper definitions
## ----------------------------------------------------------------------

## ----------------------------------------------------------------------
sub _sect
{
    ( my $hlevel, $element, $event ) = @_;
    output( "\n" ) if $hlevel < 0;
    output( "\n" ) if $hlevel < 0;
    _h_rule() if $hlevel < 0;
    output( "\n" );
    output( "\n" ) if $hlevel <= 0;
    _para_new();
    my $number = _a( 'CHAPT' );
    $number .= _a( 'SECT' ) if $hlevel >= 0;
    $number .= '. ';
    output( $number );
}

## ----------------------------------------------------------------------
sub _start_heading
{
    _para_new();
}
sub _end_heading
{
    _para_end( 0, 'underdash' );
}

## ----------------------------------------------------------------------
sub _para_new
{
    push_output( 'string' );
    @stylestack = ();
}
sub _para_end
{
    my ( $inum, $fmt, $lhtagdefer ) = @_;
    # fmt is one of undef,'centre','centre-underdash','underdash'
    # lhtagdefer is 1 if we can safely defer a paralhtag til later
    my $pd = pop_output();
    local ( @b, @u );
    @b = @u = ( 0 );
    my $here, $maxwidth, $evstr, $pis, $pil, $npis, $av, $ls_pis, $ls_pil;
    my $nobreak, $code, $reducedwidth, $indentdone, $lhs;
    my $centre = ( $fmt eq 'centre' || $fmt eq 'centre-underdash' );
    my $udash = ( $fmt eq 'underdash' || $fmt eq 'centre-underdash' );
    $maxwidth = 0;
    return if $pd !~ m/\S/ && ( $lhtagdefer || ! length( $paralhtag ) );
    if ( length( $paralhtag ) )
    {
        output( " " x ( $perindent * ( $inum - $paralhindents ) ) );
        output( _emph_string( $paralhtag ) );
        $reducedwidth = length( $paralhtag ) - ( $perindent * $paralhindents );
        $reducedwidth = 0 if $reducedwidth < 0;
        $paralhtag = '';
	$indentdone = 1;
	$paralhindents = 0;
    }
  outer:
    while ( length( $pd ) )
    {
        next if ! $nobreak && $pd =~ s/^\s+//;
        $pil = 0;
	$av = $textwidth - $perindent * $inum - $reducedwidth;
        $pis = 0;
	$reducedwidth = 0;
	$ls_pis = -1;
        while ( $pis < length( $pd ) && ( $nobreak || $pil <= $av ) )
	{
            $here = substr( $pd, $pis, 1 );
            if ( $here eq "\0" )
	    {
                $code = substr( $pd, $pis + 1, 2 );
                if ( $code eq '=o' )
		{
                    last if $pis;
                    $nobreak = 1;
		    $lhs = 0;
                }
		elsif ( $code eq '=l' )
		{
                    last if $pis || $indentdone;
                    $nobreak = 1;
		    $lhs = 1;
                }
		elsif ( $code eq '=c' )
		{
                    last if $pis;
                    $nobreak = 0;
		    $lhs = 0;
                }
		elsif ( $code eq '=n' )
		{
                    $pis += 4;
		    last;
                }
		else
		{
                    $pis += 4;
		    next;
                }
                $pd = substr( $pd, 4 );
		next outer;
            }
            if ( ! $nobreak && $here =~ m/^\s$/ )
	    {
                $here = substr( $pd, $pis );
		$here =~ s/^\s+/ /;
                $pd = substr( $pd, 0, $pis ) . $here;
                $ls_pis = $pis;
		$ls_pil = $pil;
            }
            if ( $ls_pis < 0 && $pil >= $av - $unbreakbackoff )
	    {
                $ls_pis = $pis;
		$ls_pil = $pil;
            }
            $pis++;
	    $pil++;
        }
        if ( ! $nobreak && $pil > $av )
	{
	    $pis = $ls_pis;
	    $ls_pil = $pil;
	}
        $maxwidth = $pil if $pil > $maxwidth;
        output( " " x ( ( $centre ? ( $textwidth - $pil ) / 2 : 0 )
			+ ( $lhs ? 0 : ( $inum + $nobreak ) * $perindent ) ) )
            if ! $indentdone;
        output( _emph_string( substr( $pd, 0, $pis ) ) );
        output( "\n" );
	$indentdone = 0;
        $pd = substr( $pd, $pis );
    }
    if ( $udash )
    {
        output( " " x ( ( $centre ? ( $textwidth - $maxwidth ) / 2 : 0 )
			+ ( $inum * $perindent ) ) );
        output( ( $b[0] ? "--" : "-" ) x $maxwidth . "\n" );
    }
    $blanklinedone = 0;
}

## ----------------------------------------------------------------------
sub _start_list
{
    ( $type, $element, $event ) = @_;
    unshift( @listtypes, $type );
    unshift( @listcounters, 0 );
    _para_end( $indentlevel, '', 1 );
    $indentlevel++;
    if ( $incompact || $element->attribute( 'COMPACT' )->type eq 'TOKEN' )
    {
	$incompact++;
    }
}
sub _end_list
{
    shift( @listtypes );
    shift( @listcounters );
    _insert_blankline();
    _para_new();
    $indentlevel--;
    $incompact-- if $incompact;
}

## ----------------------------------------------------------------------
sub _para_lhtag
{
    my ( $ntag ) = @_;
    $paralhindents++;
    $paralhtag .= $ntag;
    $paralhtag .= ' ' x ( $paralhindents * $perindent 
			  - length( $paralhtag ) - 1 );
    $paralhtag .= ' ';
}

## ----------------------------------------------------------------------
sub _emph_string
{
    my ( $string ) = @_;
    my $i, $here, $ar, $sv;
    for ( $i = 0; $i < length( $string ); $i++ )
    {
        $here = substr( $string,$i, 1 );
        if ( $here eq "\0" )
	{
            $ar = substr( $string, $i + 1, 1 );
	    $sv = substr( $string, $i + 2, 1 );
            if ( $sv eq '-' )
	    {
                $es = "shift(\@$ar);1;";
		eval $es || die "$@ / $es";
            }
	    elsif ( $sv ne '=' )
	    {
                $es = "unshift(\@$ar,\$sv);1;";
		eval $es || die "$@ / $es";
            }
            $i += 3;
	    next;
        }
        if ( $b[0] )
	{
	    output( "$here" );
	}
        elsif ( $u[0] )
	{
	    output( "_" );
	}
        output( $here );
    }
    return;
}

## ----------------------------------------------------------------------
sub _insert_blankline
{
    if ( !$incompact && ! $blanklinedone )
    {
	output( "\n" );
	$blanklinedone = 1;
    }
}

## ----------------------------------------------------------------------
sub _h_rule
{
    output( ( "-" x $linewidth ) . "\n" );
}

## ----------------------------------------------------------------------
## SGML definitions
## ----------------------------------------------------------------------

use DebianDoc_SGML;

## ----------------------------------------------------------------------
