package CGI::PrintWrapper;

# This is a lightweight wrapper for CGI so that you can call its
# methods, but have the results printed to the request object (passing
# through the Template object, of course).

use strict;

use Carp ( );
use CGI ( );


$CGI::PrintWrapper::VERSION = (substr q$Revision: 1.3 $, 10) - 1;
my $rcs = '$Id: PrintWrapper.pm,v 1.3 1999/11/15 20:56:18 binkley Exp $';


sub new ($$) {
  my ($this, $h) = @_;

  $h or Carp::croak ('No print handle');
  $h->can ('print') or Carp::croak ("'$h' is not a print handle");

  my $class = ref ($this) || $this;
  # Need to create an empty CGI object to avoid CGI trying to read in
  # the parameters -- we are using CGI for printing forms, not for
  # processing scripts:
  my $cgi = CGI->new ('');

  bless [$h, $cgi], $class;
}

sub io ($) {
  shift->[0];
}

sub AUTOLOAD {
  no strict qw(refs);

  my $sub = $CGI::PrintWrapper::AUTOLOAD;
  $sub =~ s/.*:://; # strip package

  # Fixup our call to invoke the same-named CGI function, but to print
  # the resulting string to our handle.  Update our symbol table so
  # that future calls can bypass AUTOLOAD entirely.  Be careful to
  # capture the handle ($$self) inside the sub--not outside--so that
  # calls from other instances don't reuse a previous handle (correct
  # scoping):
  *{$CGI::PrintWrapper::AUTOLOAD} = sub {
    my $self = shift;

    $self->[0]->print (&{"CGI::$sub"} ($self->[1], @_));

    return $self;
  };

  goto &$CGI::PrintWrapper::AUTOLOAD;
}

1;


__END__


=head1 NAME

CGI::PrintWrapper - CGI methods output to a print handle

=head1 SYNOPSIS

    use CGI::PrintHandle;
    use IO::Scalar; # just an example
    use HTML::Stream; # continuing the example

    my $content = '';
    my $handle = IO::Scalar->new (\$content);
    my $cgi = CGI::PrintHandle ($handle);
    my $html = HTML::Stream->new ($handle);

    # Not a very exciting example:
    $cgi->start_form;
    $html->STRONG->t ('I am a form.')->_STRONG;
    $cgi->submit;
    $cgi->end_form;

    print "$content\n";
<FORM METHOD="POST"  ENCTYPE="application/x-www-form-urlencoded">
<STRONG>I am a form.</STRONG><INPUT TYPE="submit" NAME=".submit"></FORM>

=head1 DESCRIPTION

B<CGI::PrintWrapper> arranges for CGI methods to output their results
by printing onto an arbitrary handle.  This gets around the problem
that the B<CGI>'s subs return strings.

You could just call C<print> yourself on the appropriate file handle,
but there are many contexts in which it is cleaner to provide the
extra abstraction (such as mixing B<CGI> with B<HTML::Stream>, the
problem which prompted my solution, illustrated above).

B<CGI::PrintWrapper> creates the necessary callbacks for printing
dynamically, updating the symbol table as it encounters a new B<CGI>
method.

=head1 CONSTRUCTOR

=over

=item C<new($h)>

Creates a new B<CGI::PrintWrapper>, printing the results of B<CGI>
methods onto the print handle object, C<$h>.

=back

=head1 METHODS

=over

=item C<io()>

Returns the underlying print handle object.

=item C<AUTOLOAD>

Initially, C<CGI::PrintWrapper> has no methods (except C<io>).  As the
caller invokes B<CGI> methods, C<AUTOLOAD> creates anonymous
subroutines to perform the actual B<CGI> method call and print the
results with the print handle object.  It also updates the symbol
table so that future calls can bypass C<AUTOLOAD>.

=back

=head1 SEE ALSO

L<CGI>, L<IO::Scalar>, L<HTML::Stream>, L<perlfunc/print>

B<CGI> is the canonical package for working with fill-out forms on the
web.

B<IO::Scalar> is a handy package for treating a string as an object
supporting IO handle semantics.

B<HTML::Stream> is a nice package for writing HTML markup and content
into an IO handle with stream semantics.

=head1 DIAGNOSTICS

The following are the diagnostics generated by B<Class::Class>.  Items
marked "(W)" are non-fatal (invoke C<Carp::carp>); those marked "(F)"
are fatal (invoke C<Carp::croak>).

=over

=item No print handle

(F) The caller tried to create a new C<CGI::PrintWrapper> without
supplying an object which supports C<print>.

=item '%s' is not a print handle

(F) The caller tried to create a new C<CGI::PrintWrapper> using an
object which does not support C<print>.

=back

=head1 BUGS AND CAVEATS

So far, none, but you never know.  I<Caveat emptor.>

=head1 AUTHORS

B. K. Oxley (binkley) at Home E<lt>binkley@bigfoot.comE<gt>

=head1 COPYRIGHT

  $Id: PrintWrapper.pm,v 1.3 1999/11/15 20:56:18 binkley Exp $

  Copyright 1999, B. K. Oxley (binkley).

This library is free software; you may redistribute it and/or modify
it under the same terms as Perl itself.

=cut
