#!/usr/bin/perl -w
# -----------------------------------------------------------------------------
# TWC
# Treuwert-Computer GmbH
# Schloßbergring 9
# 79098 Freiburg
#
# Author: Klaus Reger <K.Reger@twc.de>
#
# -----------------------------------------------------------------------------
# Program-Data
# -----------------------------------------------------------------------------
# Project  :
# System   :
# Program  :
# Module   : $RCSfile: HTML.pm,v $
# Version  : $Revision: 1.9 $
# Date     : $Date: 2002/02/25 10:50:44 $
# State    : $State: Exp $
#
# Description:
#   This module handles all the things of WWWdb, which have
#   to do with HTML
#
# Change-log (See at end of this file)
#
# --- Known Bugs -------------
# please look at the BUGS-File
# --- TODO -------------------
# please look at the TODO-File
# ----------------------------------------------------------------------------

use strict;

use CGI qw(:all);


use WWWdb::Base;

=head1 NAME

WWWdb::HTML - HTML-Objects for WWWdb

=head1 SYNOPSIS

 use WWWdb::HTML;

=cut



# --------------------------------------------------------------------
# HTML:Form
# --------------------------------------------------------------------
package HTML::Form;
use vars qw(%hAttribs);

@HTML::Form::ISA = qw(Base);

{

    %hAttribs =
        (
         BgColorHtmlPar      => ["c", "public",  "r", undef],
         BackgroundHtmlPar   => ["c", "public",  "r", undef],
         LinkHtmlPar         => ["c", "public",  "r", undef],
         VLinkHtmlPar        => ["c", "public",  "r", undef],
         ALinkHtmlPar        => ["c", "public",  "r", undef],
         TopMarginHtmlPar    => ["i", "public",  "r", 0],
         LeftMarginHtmlPar   => ["i", "public",  "r", 0],
         MarginWidthHtmlPar  => ["i", "public",  "r", 0],
         MarginHeightHtmlPar => ["i", "public",  "r", 0],
         AuthorHtmlPar       => ["c", "public",  "r", undef],
         TitleHtmlPar        => ["c", "public",  "r", ""],
         MetaHtmlPar         => ["h", "public",  "r", undef],
         EncTypeFormPar      => ["c", "public",  "r", &CGI::MULTIPART],
         MethodFormPar       => ["c", "public",  "r", "POST"],
         ActionFormPar       => ["c", "public",  "r", undef],
         ExpireHeadPar       => ["c", "public",  "r", "now"],
         Seq                 => ["h", "private", "r", undef]
         );

}


# --- Insert an element in the column --------------------------------
# The following forms are allowed

# Element(sequence, Data)
sub HTML::Form::Element($$)
{
    my $hSelfPI = shift;

    my $iSeqPI  = shift;
    my $pDataPI = shift;

    $hSelfPI->{"Seq"}->{$iSeqPI} = $pDataPI
	if defined($pDataPI);

    return $hSelfPI->{"Seq"}->{$iSeqPI};
}



sub HTML::Form::HtmlCode ()
{
    my $hSelfPI = shift;

    my $iSeq;
    my %hHeadParams = ();
    my %hHtmlParams = ();
    my %hFormParams = ();

    my $cResult = "";

    # generate the table-attributes
    foreach (keys %$hSelfPI)
    {
	# ignore non-parameters
	if (/^(.*)(Html)Par$/)
	{
	    $hHtmlParams{"-" . $1} = $hSelfPI->{$_}
	        if defined $hSelfPI->{$_};
	}
	elsif(/^(.*)(Form)Par$/)
	{
	    $hFormParams{"-" . $1} = $hSelfPI->{$_}
	        if defined $hSelfPI->{$_};
	}
	elsif(/^(.*)(Head)Par$/)
	{
	    $hFormParams{"-" . $1} = $hSelfPI->{$_}
	        if defined $hSelfPI->{$_};
	}
    }

    $cResult .= CGI::header(%hHeadParams);
    $cResult .= CGI::start_html(%hHtmlParams);
    $cResult .= CGI::start_form(%hFormParams);

    # now traverse the Form-sequence
    foreach $iSeq (sort {$a <=> $b} keys %{$hSelfPI->{"Seq"}})
    {
	my $pPrintObj = $hSelfPI->{"Seq"}{$iSeq};

	if(ref($pPrintObj))
	{
	    $cResult .= (($hSelfPI->{"Seq"}{$iSeq})->HtmlCode() .
			 "\n");
	}
	else
	{
	    $cResult .= $hSelfPI->{"Seq"}{$iSeq} . "\n";
	}
    }

    $cResult .= CGI::end_form();
    $cResult .= CGI::end_html();

    return $cResult;

}





# --------------------------------------------------------------------
# HTML:Table
# --------------------------------------------------------------------
package HTML::Table;
use vars qw(%hAttribs);

use Carp::Assert;
# use Carp::Assert qw(:NDEBUG);

use constant CURRENT => -256;
use constant APPEND  => -512;

@HTML::Table::ISA = qw(Base);

{
    %hAttribs =
      (
       BorderPar      => ["i", "public",  "rw", undef],
       BackgroundPar  => ["c", "public",  "rw", undef],
       CellpaddingPar => ["i", "public",  "rw", 1],
       CellspacingPar => ["i", "public",  "rw", 0],
       BgColorPar     => ["c", "public",  "rw", undef],
       WidthPar       => ["c", "public",  "rw", undef],
       HeightPar      => ["c", "public",  "rw", undef],
       MaxCol         => ["i", "public",  "r",  0],
       MaxRow         => ["i", "public",  "r",  0],
       Rows           => ["h", "private", "r",  undef],
      );
}



# --- Insert an element in the table --------------------------------
# The following forms are allowed
# --- Setting ---
# Element(row, Row-Object)
# Element(row, column, Col-Object)
# Element(row, column, sequence, Data)
# --- Getting ---
# Element(row) => Row-object
# Element(row, column) => Column-object
# Element(row, column, sequence) => Data-Element
sub HTML::Table::Element($$$@)
{
    my $hSelfPI = shift;

    my $bChangeObject = (ref($_[-1])) || (@_ >= 4);

    my $iRowPI  = shift;
    my $iColPI  = shift;
    my $iSeqPI  = shift;
    my @lDataPI = @_;

    my $iRow = undef;
    my $iCol = undef;

    my $pResult = undef;

    assert ($iRowPI >= 0 ||
            $iRowPI == APPEND ||
            $iRowPI == CURRENT)
        if DEBUG;

    assert ($iColPI >= 0 ||
            $iColPI == APPEND ||
            $iColPI == CURRENT)
        if DEBUG;

    $iRow = ($iRowPI == APPEND?
	     $hSelfPI->{"MaxRow"}:
	     ($iRowPI == CURRENT?
	      $hSelfPI->{"MaxRow"} - 1:
	      $iRowPI))
        if !ref($iRowPI);

    $iCol = ($iColPI == APPEND?
	     $hSelfPI->{"MaxCol"}:
	     ($iColPI == CURRENT?
	      $hSelfPI->{"MaxCol"} - 1:
	      $iColPI))
        if !ref($iColPI);

    # update MaxRow, MaxColumn
    $hSelfPI->{"MaxRow"} = $iRow + 1
        if ($hSelfPI->{"MaxRow"} < ($iRow + 1));
    $hSelfPI->{"MaxCol"} = $iCol + 1
        if ($hSelfPI->{"MaxCol"} < ($iCol + 1));

    assert($iRow < 1000)
        if DEBUG;
    assert($iCol < 1000)
        if DEBUG;


    if($bChangeObject)
    {
	# We must create a new row
	if(!defined($hSelfPI->{"Rows"}->{$iRow}))
	{

	    # Attributes for row were given
	    if(ref($iColPI) eq "HTML::TableRow")
	    {
		$hSelfPI->{"Rows"}->{$iRow} = $iColPI;

		return $pResult;
	    }
	    else
	    {
		$hSelfPI->{"Rows"}->{$iRow} =
		  HTML::TableRow->new();
	    }
	}
        else
        {
            # Attributes for row were given
           if(ref($iColPI) eq "HTML::TableRow")
           {
              $hSelfPI->{"Rows"}->{$iRow} = $iColPI;

              return $pResult;
           }
        }

        $hSelfPI->{"Rows"}->{$iRow}->Element($iCol,
                                              $iSeqPI,
                                              @lDataPI);

    }
    else
    {
	if(defined($iCol))
	{
	    $pResult =
		$hSelfPI->{"Rows"}->{$iRow}->Element
		    ($iCol, $iSeqPI)
			if defined($hSelfPI->{"Rows"}->{$iRow});

	}
	# get row-info
	else
	{
	    $pResult = $hSelfPI->{"Rows"}->{$iRow}
	        if defined($hSelfPI->{"Rows"}->{$iRow});
	}

    }

    return $pResult;
}



sub HTML::Table::HtmlCode ()
{
    my $hSelfPI = shift;

    my $iCol;
    my $iRow;
    my $iSeq;
    my $iLastRow  = 0;

    my $cResult = "<TABLE";


    # generate the table-attributes
    foreach (keys %$hSelfPI)
    {
	# ignore non-parameters
	if (/^(\w*)Par$/)
	{
	    my $cDelim = ((($hAttribs{$_})[0] eq "c")? '"': "");

	    $cResult .= sprintf("\n  %s=%s%s%s",
				uc($1),
				$cDelim,
				$hSelfPI->{$_},
				$cDelim)
		if defined $hSelfPI->{$_};
	}
    }

    $cResult .= ">\n";

    # now traverse the table-hierarchy
    foreach $iRow (sort {$a <=> $b}
		   keys %{$hSelfPI->{"Rows"}})
    {
	my $oTableRow = HTML::TableRow->new();

	for (my $iRowInd = $iLastRow;
	     $iRowInd < $iRow - 1;
	     $iRowInd ++)
	{
	    # $cResult .= $oTableRow->HtmlCode();
	    $cResult .= "<TR><TD>&nbsp;</TD></TR>";
	}

	$iLastRow = $iRow;

	$cResult .= $hSelfPI->{"Rows"}{$iRow}->HtmlCode()
	    if defined($hSelfPI->{"Rows"}{$iRow});

    }

    $cResult .= "</TABLE>\n";

    return $cResult;

}



# --------------------------------------------------------------------
# HTML:TableRow
# --------------------------------------------------------------------
package HTML::TableRow;

use vars qw(%hAttribs);

@HTML::TableRow::ISA = qw(Base);

{

    %hAttribs =
      (AlignPar      => ["c", "public",  "rw", undef],
       BgColorPar    => ["c", "public",  "rw", undef],
       BorderPar     => ["i", "public",  "rw", undef],
       CharPar       => ["c", "public",  "rw", undef],
       ValignPar     => ["c", "public",  "rw", undef],
       ColsPar       => ["h", "private", "r",  undef],
       BackgroundPar => ["c", "public",  "rw", undef],
      );
}




# --- Insert an element in the row --------------------------------
# The following forms are allowed
# --- Setting ---
# Element(Row-Object)
# Element(column, Col-Object)
# Element(column, sequence, Data)
# --- Getting ---
# Element(column) => Column-object
# Element(column, sequence) => Data-Element
sub HTML::TableRow::Element($$$)
{
    my $hSelfPI = shift;

    my $bChangeObject = (ref($_[-1])) || (@_ >= 3);

    my $iColPI  = shift;
    my $iSeqPI  = shift;
    my @lDataPI = @_;

    my $pResult = undef;

    if($bChangeObject)
    {
	# We must create a new row
	if(!defined($hSelfPI->{"Cols"}->{$iColPI}))
	{

	    # Attributes for row were given
	    if(ref($iSeqPI) eq "HTML::TableCol")
	    {
		$hSelfPI->{"Cols"}->{$iColPI} = ($iSeqPI);

		return $pResult;
	    }
	    else
	    {
		$hSelfPI->{"Cols"}->{$iColPI} =
		  HTML::TableCol->new();
	    }
	}

	# now set up the rest
	$hSelfPI->{"Cols"}->{$iColPI}->Element($iSeqPI, @lDataPI);
    }
    else
    {
	# get col-info
	unless(defined($iSeqPI))
	{
	    $pResult = $hSelfPI->{"Cols"}->{$iColPI}
	         if defined($hSelfPI->{"Cols"}->{$iColPI});
	}

    }
}



sub HTML::TableRow::HtmlCode ()
{
    my $hSelfPI = shift;

    my $iCol;
    my $iRow;
    my $iSeq;
    my $iLastCol  = 0;

    my $cResult = "<TR";


    # generate the table-attributes
    foreach (keys %$hSelfPI)
    {
	# ignore non-parameters
	if (/^(\w*)Par$/)
	{
	    my $cDelim = ((($hAttribs{$_})[0] eq "c")? '"': "");

	    $cResult .= sprintf("\n  %s=%s%s%s",
				uc($1),
				$cDelim,
				$hSelfPI->{$_},
				$cDelim)
		if defined $hSelfPI->{$_};
	}
    }

    $cResult .= ">\n";

    # now traverse the table-hierarchy

    foreach $iCol (sort {$a <=> $b}
		   keys %{$hSelfPI->{"Cols"}})
    {
	my $oTableCol = HTML::TableCol->new();

	for (my $iColInd = $iLastCol;
	     $iColInd < $iCol - 1;
	     $iColInd ++)
	{
	    # $cResult .= $oTableCol->HtmlCode();
	    $cResult .= "<TD>&nbsp;</TD>";
	}

	$iLastCol = $iCol;

	if (defined($hSelfPI->{"Cols"}{$iCol}))
	{
	    $cResult .= $hSelfPI->{"Cols"}{$iCol}->HtmlCode();
	}
	else
	{
	    $cResult .= "&nbsp;";
	}
    }

    $cResult .= "</TR>\n";

    return $cResult;

}



# --------------------------------------------------------------------
# HTML:TableCol
# --------------------------------------------------------------------
package HTML::TableCol;

use Carp::Assert;
# use Carp::Assert qw(:NDEBUG);

use vars qw(%hAttribs);

@HTML::TableCol::ISA = qw(Base);

{
    %hAttribs =
      (AlignPar       => ["c", "public",  "rw", undef],
       BgColorPar     => ["c", "public",  "rw", undef],
       BorderPar      => ["i", "public",  "rw", undef],
       CharPar        => ["c", "public",  "rw", undef],
       ValignPar      => ["c", "public",  "rw", undef],
       ColspanPar     => ["i", "public",  "rw", undef],
       HeightPar      => ["i", "public",  "rw", undef],
       NowrapPar      => ["b", "public",  "rw", undef],
       RowspanPar     => ["i", "public",  "rw", undef],
       WidthPar       => ["i", "public",  "rw", undef],
       BackgroundPar  => ["c", "public",  "rw", undef],
      );

}



# --- Insert an element in the column --------------------------------
# The following forms are allowed

# Element(sequence, Data)
sub HTML::TableCol::Element($$)
{
    my $hSelfPI = shift;

    my $iSeqPI  = shift;
    my $pDataPI = shift;

    my $iSeq;

    assert ($iSeqPI >= 0 ||
            $iSeqPI == HTML::Table::APPEND ||
            $iSeqPI == HTML::Table::CURRENT)
        if DEBUG;


    # seq HTML::TABLE::APPEND means: append to table
    $iSeq = ($iSeqPI == HTML::Table::APPEND?
	     $hSelfPI->{"Seq"}:
	     ($iSeqPI == HTML::Table::CURRENT?
	      $hSelfPI->{"Seq"}:
	      $iSeqPI));

    $hSelfPI->{"Seq"}->{$iSeqPI} = $pDataPI;

    return;
}




sub HTML::TableCol::HtmlCode ()
{
    my $hSelfPI = shift;

    my $cResult = "<TD";
    my $iSeq;

    # generate the table-attributes
    foreach (keys %$hSelfPI)
    {
	# ignore non-parameters
	if (/^(\w*)Par$/)
	{
	    my $cDelim = ((($hAttribs{$_})[0] eq "c")? '"': "");

	    $cResult .= sprintf("\n  %s=%s%s%s",
				uc($1),
				$cDelim,
				$hSelfPI->{$_},
				$cDelim)
		if $hSelfPI->{$_};
	}
    }

    $cResult .= ">\n";

    # now traverse the table-hierarchy
    foreach $iSeq (sort {$a <=> $b} keys %{$hSelfPI->{"Seq"}})
    {
	my $pPrintObj = $hSelfPI->{"Seq"}{$iSeq};

	if(ref($pPrintObj))
	{
	    $cResult .= (($hSelfPI->{"Seq"}{$iSeq})->HtmlCode() .
			 "\n");
	}
	else
	{
	    $cResult .= $hSelfPI->{"Seq"}{$iSeq} . "\n";
	}
    }

    $cResult .= "</TD>\n";

    return $cResult;

}


1;



