home *** CD-ROM | disk | FTP | other *** search
/ CLIX - Fazer Clix Custa Nix / CLIX-CD.cdr / mac / lib / HTML / FormatPS.pm < prev    next >
Text File  |  1997-09-05  |  17KB  |  698 lines

  1. package HTML::FormatPS;
  2.  
  3. # $Id: FormatPS.pm,v 1.21 1997/08/16 10:34:31 aas Exp $
  4.  
  5. $DEFAULT_PAGESIZE = "A4";
  6.  
  7. =head1 NAME
  8.  
  9. HTML::FormatPS - Format HTML as postscript
  10.  
  11. =head1 SYNOPSIS
  12.  
  13.   require HTML::FormatPS;
  14.   $html = parse_htmlfile("test.html");
  15.   $formatter = new HTML::FormatPS
  16.            FontFamily => 'Helvetica',
  17.            PaperSize  => 'Letter';
  18.   print $formatter->format($html);
  19.  
  20. =head1 DESCRIPTION
  21.  
  22. The HTML::FormatPS is a formatter that outputs PostScript code.
  23. Formatting of HTML tables and forms is not implemented.
  24.  
  25. You might specify the following parameters when constructing the formatter:
  26.  
  27. =over 4
  28.  
  29. =item PaperSize
  30.  
  31. What kind of paper should we format for.  The value can be one of
  32. these: A3, A4, A5, B4, B5, Letter, Legal, Executive, Tabloid,
  33. Statement, Folio, 10x14, Quarto.
  34.  
  35. The default is "A4".
  36.  
  37. =item PaperWidth
  38.  
  39. The width of the paper in points.  Setting PaperSize also defines this
  40. value.
  41.  
  42. =item PaperHeight
  43.  
  44. The height of the paper in points.  Setting PaperSize also defines
  45. this value.
  46.  
  47. =item LeftMargin
  48.  
  49. The left margin in points.
  50.  
  51. =item RightMargin
  52.  
  53. The right margin in points.
  54.  
  55. =item HorizontalMargin
  56.  
  57. Both left and right margin at the same time.  The default value is 4 cm.
  58.  
  59. =item TopMargin
  60.  
  61. The top margin in points.
  62.  
  63. =item BottomMargin
  64.  
  65. The bottom margin in points.
  66.  
  67. =item VerticalMargin
  68.  
  69. Both top and bottom margin at the same time.  The default value is 2 cm.
  70.  
  71. =item PageNo
  72.  
  73. The parameter determines if we should put page numbers on the pages.
  74. The default is yes, so you have to set this value to 0 in order to
  75. suppress page numbers.
  76.  
  77. =item FontFamily
  78.  
  79. The parameter specifies which family of fonts to use for the formatting.
  80. Legal values are "Courier", "Helvetica" and "Times".  The default is
  81. "Times".
  82.  
  83. =item FontScale
  84.  
  85. All fontsizes might be scaled by this factor.
  86.  
  87. =item Leading
  88.  
  89. How much space between lines.  This is a factor of the fontsize used
  90. for that line.  Default is 0.1.
  91.  
  92. =back
  93.  
  94. =head1 SEE ALSO
  95.  
  96. L<HTML::Formatter>
  97.  
  98. =head1 COPYRIGHT
  99.  
  100. Copyright (c) 1995 Gisle Aas. All rights reserved.
  101.  
  102. This library is free software; you can redistribute it and/or
  103. modify it under the same terms as Perl itself.
  104.  
  105. =head1 AUTHOR
  106.  
  107. Gisle Aas <aas@oslonett.no>
  108.  
  109. =cut
  110.  
  111. use Carp;
  112.  
  113. require HTML::Formatter;
  114. @ISA = qw(HTML::Formatter);
  115.  
  116. # A few routines that convert lengths into points
  117. sub mm { $_[0] * 72 / 25.4; }
  118. sub in { $_[0] * 72; }
  119.  
  120. %PaperSizes =
  121. (
  122.  A3        => [mm(297), mm(420)],
  123.  A4        => [mm(210), mm(297)],
  124.  A5        => [mm(148), mm(210)],
  125.  B4        => [729,     1032   ],
  126.  B5        => [516,     729    ],
  127.  Letter    => [in(8.5), in(11) ],
  128.  Legal     => [in(8.5), in(14) ],
  129.  Executive => [in(7.5), in(10) ],
  130.  Tabloid   => [in(11),  in(17) ],
  131.  Statement => [in(5.5), in(8.5)],
  132.  Folio     => [in(8.5), in(13) ],
  133.  "10x14"   => [in(10),  in(14) ],
  134.  Quarto    => [610,     780    ],
  135. );
  136.  
  137. %FontFamilies =
  138. (
  139.  Courier   => [qw(Courier
  140.           Courier-Bold
  141.           Courier-Oblique
  142.           Courier-BoldOblique)],
  143.  
  144.  Helvetica => [qw(Helvetica
  145.           Helvetica-Bold
  146.           Helvetica-Oblique
  147.           Helvetica-BoldOblique)],
  148.  
  149.  Times     => [qw(Times-Roman
  150.           Times-Bold
  151.           Times-Italic
  152.           Times-BoldItalic)],
  153. );
  154.  
  155.       # size   0   1   2   3   4   5   6   7
  156. @FontSizes = ( 5,  6,  8, 10, 12, 14, 18, 24, 32);
  157.  
  158. sub BOLD   { 0x01; }
  159. sub ITALIC { 0x02; }
  160.  
  161. %param =
  162. (
  163.  papersize        => 'papersize',
  164.  paperwidth       => 'paperwidth',
  165.  paperheight      => 'paperheigth',
  166.  leftmargin       => 'lmW',
  167.  rightmargin      => 'rmW',
  168.  horizontalmargin => 'mW',
  169.  topmargin        => 'tmH',
  170.  bottommargin     => 'bmH',
  171.  verticalmargin   => 'mH',
  172.  pageno           => 'printpageno',
  173.  fontfamily       => 'family',
  174.  fontscale        => 'fontscale',
  175.  leading          => 'leading',
  176. );
  177.  
  178.  
  179. sub new
  180. {
  181.     my $class = shift;
  182.  
  183.     # Set up defaults
  184.     my $self = bless {
  185.     family => "Times",
  186.     mH => mm(40),
  187.     mW => mm(20),
  188.     printpageno => 1,
  189.     fontscale   => 1,
  190.     leading     => 0.1,
  191.     }, $class;
  192.     $self->papersize($DEFAULT_PAGESIZE);
  193.  
  194.     # Parse constructor arguments (might override defaults)
  195.     while (($key, $val) = splice(@_, 0, 2)) {
  196.     $key = lc $key;
  197.     croak "Illegal parameter ($key => $val)" unless exists $param{$key};
  198.     $key = $param{$key};
  199.     {
  200.         $key eq "family" && do {
  201.         $val = "\u\L$val";
  202.         croak "Unknown font family ($val)"
  203.           unless exists $FontFamilies{$val};
  204.         $self->{family} = $val;
  205.         last;
  206.         };
  207.         $key eq "papersize" && do {
  208.         $self->papersize($val) || croak "Unknown papersize ($val)";
  209.         last;
  210.         };
  211.         $self->{$key} = lc $val;
  212.     }
  213.     }
  214.     $self->{title} = "";
  215.     $self;
  216. }
  217.  
  218.  
  219. sub papersize
  220. {
  221.     my($self, $val) = @_;
  222.     $val = "\u\L$val";
  223.     my($width, $height) = @{$PaperSizes{$val}};
  224.     return 0 unless defined $width;
  225.     $self->{papersize} = $val;
  226.     $self->{paperwidth} = $width;
  227.     $self->{paperheight} = $height;
  228.     1;
  229. }
  230.  
  231.  
  232. sub fontsize
  233. {
  234.     my $self = shift;
  235.     my $size = $self->{font_size}[-1];
  236.     $size = 8 if $size > 8;
  237.     $size = 3 if $size < 0;
  238.     $FontSizes[$size] * $self->{fontscale};
  239. }
  240.  
  241.  
  242. sub findfont
  243. {
  244.     my($self, $plain_with_size) = @_;
  245.     my $index = 0;
  246.     my $family = $self->{family} || 'Times';
  247.     my $size = $plain_with_size;
  248.     unless ($plain_with_size) {
  249.     $index |= BOLD   if $self->{bold};
  250.     $index |= ITALIC if $self->{italic} || $self->{underline};
  251.     $family = 'Courier' if $self->{teletype};
  252.     $size = $self->fontsize;
  253.     }
  254.     my $font = $FontFamilies{$family}[$index];
  255.     my $font_with_size = "$font-$size";
  256.     if ($self->{currentfont} eq $font_with_size) {
  257.     return "";
  258.     }
  259.     $self->{currentfont} = $font_with_size;
  260.     $self->{pointsize} = $size;
  261.     my $fontmod = "Font::Metrics::$font";
  262.     $fontmod =~ s/-//g;
  263.     my $fontfile = $fontmod . ".pm";
  264.     $fontfile =~ s,::,/,g;
  265.     require $fontfile;
  266.     $self->{wx} = \@{ "${fontmod}::wx" };
  267.     $font = $self->{fonts}{$font_with_size} || do {
  268.     my $fontID = "F" . ++$self->{fno};
  269.     $self->{fonts}{$font_with_size} = $fontID;
  270.     $fontID;
  271.     };
  272.     "$font SF";
  273. }
  274.  
  275.  
  276. sub width
  277. {
  278.     my $self = shift;
  279.     my $w = 0;
  280.     my $wx = $self->{wx};
  281.     my $sz = $self->{pointsize};
  282.     for (unpack("C*", $_[0])) {
  283.     $w += $wx->[$_] * $sz;
  284.     }
  285.     $w;
  286. }
  287.  
  288.  
  289. sub begin
  290. {
  291.     my $self = shift;
  292.     $self->HTML::Formatter::begin;
  293.  
  294.     # Margins is points
  295.     $self->{lm} = $self->{lmW} || $self->{mW};
  296.     $self->{rm} = $self->{paperwidth}  - ($self->{rmW} || $self->{mW});
  297.     $self->{tm} = $self->{paperheight} - ($self->{tmH} || $self->{mH});
  298.     $self->{bm} = $self->{bmH} || $self->{mH};
  299.  
  300.     # Font setup
  301.     $self->{fno} = 0;
  302.     $self->{fonts} = {};
  303.     $self->{en} = 0.55 * $self->fontsize(3);
  304.  
  305.     # Initial position
  306.     $self->{xpos} = $self->{lm};  # top of the current line
  307.     $self->{ypos} = $self->{tm};
  308.  
  309.     $self->{pageno} = 1;
  310.  
  311.     $self->{line} = "";
  312.     $self->{showstring} = "";
  313.     $self->{currentfont} = "";
  314.     $self->{prev_currentfont} = "";
  315.     $self->{largest_pointsize} = 0;
  316.  
  317.     $self->newpage;
  318. }
  319.  
  320.  
  321. sub end
  322. {
  323.     my $self = shift;
  324.     $self->showline;
  325.     $self->endpage if $self->{out};
  326.     my $pages = $self->{pageno} - 1;
  327.  
  328.     my @prolog = ();
  329.     push(@prolog, "%!PS-Adobe-3.0\n");
  330.     #push(@prolog,"%%Title: No title\n"); # should look for the <title> element
  331.     push(@prolog, "%%Creator: HTML::FormatPS (libwww-perl)\n");
  332.     push(@prolog, "%%CreationDate: " . localtime() . "\n");
  333.     push(@prolog, "%%Pages: $pages\n");
  334.     push(@prolog, "%%PageOrder: Ascend\n");
  335.     push(@prolog, "%%Orientation: Portrait\n");
  336.     my($pw, $ph) = map { int($_); } @{$self}{qw(paperwidth paperheight)};
  337.  
  338.     push(@prolog, "%%DocumentMedia: Plain $pw $ph 0 white ()\n");
  339.     push(@prolog, "%%DocumentNeededResources: \n");
  340.     my($full, %seenfont);
  341.     for $full (sort keys %{$self->{fonts}}) {
  342.     $full =~ s/-\d+$//;
  343.     next if $seenfont{$full}++;
  344.     push(@prolog, "%%+ font $full\n");
  345.     }
  346.     push(@prolog, "%%DocumentSuppliedResources: procset newencode 1.0 0\n");
  347.     push(@prolog, "%%+ encoding ISOLatin1Encoding\n");
  348.     push(@prolog, "%%EndComments\n");
  349.     push(@prolog, <<'EOT');
  350.  
  351. %%BeginProlog
  352. /S/show load def
  353. /M/moveto load def
  354. /SF/setfont load def
  355.  
  356. %%BeginResource: encoding ISOLatin1Encoding
  357. systemdict /ISOLatin1Encoding known not {
  358.     /ISOLatin1Encoding [
  359.     /space /space /space /space /space /space /space /space
  360.     /space /space /space /space /space /space /space /space
  361.     /space /space /space /space /space /space /space /space
  362.     /space /space /space /space /space /space /space /space
  363.     /space /exclam /quotedbl /numbersign /dollar /percent /ampersand
  364.         /quoteright
  365.     /parenleft /parenright /asterisk /plus /comma /minus /period /slash
  366.     /zero /one /two /three /four /five /six /seven
  367.     /eight /nine /colon /semicolon /less /equal /greater /question
  368.     /at /A /B /C /D /E /F /G
  369.     /H /I /J /K /L /M /N /O
  370.     /P /Q /R /S /T /U /V /W
  371.     /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore
  372.     /quoteleft /a /b /c /d /e /f /g
  373.     /h /i /j /k /l /m /n /o
  374.     /p /q /r /s /t /u /v /w
  375.     /x /y /z /braceleft /bar /braceright /asciitilde /space
  376.     /space /space /space /space /space /space /space /space
  377.     /space /space /space /space /space /space /space /space
  378.     /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
  379.     /dieresis /space /ring /cedilla /space /hungarumlaut /ogonek /caron
  380.     /space /exclamdown /cent /sterling /currency /yen /brokenbar /section
  381.     /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen
  382.         /registered /macron
  383.     /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph
  384.         /periodcentered
  385.     /cedillar /onesuperior /ordmasculine /guillemotright /onequarter
  386.         /onehalf /threequarters /questiondown
  387.     /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla
  388.     /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex
  389.         /Idieresis
  390.     /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply
  391.     /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn
  392.         /germandbls
  393.     /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla
  394.     /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex
  395.         /idieresis
  396.     /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide
  397.     /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn
  398.         /ydieresis
  399.     ] def
  400. } if
  401. %%EndResource
  402. %%BeginResource: procset newencode 1.0 0
  403. /NE { %def
  404.    findfont begin
  405.       currentdict dup length dict begin
  406.      { %forall
  407.         1 index/FID ne {def} {pop pop} ifelse
  408.      } forall
  409.      /FontName exch def
  410.      /Encoding exch def
  411.      currentdict dup
  412.       end
  413.    end
  414.    /FontName get exch definefont pop
  415. } bind def
  416. %%EndResource
  417. %%EndProlog
  418. EOT
  419.  
  420.     push(@prolog, "\n%%BeginSetup\n");
  421.     for $full (sort keys %{$self->{fonts}}) {
  422.     my $short = $self->{fonts}{$full};
  423.     $full =~ s/-(\d+)$//;
  424.     my $size = $1;
  425.     push(@prolog, "ISOLatin1Encoding/$full-ISO/$full NE\n");
  426.     push(@prolog, "/$short/$full-ISO findfont $size scalefont def\n");
  427.     }
  428.     push(@prolog, "%%EndSetup\n");
  429.  
  430.     $self->collect("\n%%Trailer\n%%EOF\n");
  431.     unshift(@{$self->{output}}, @prolog);
  432. }
  433.  
  434.  
  435. sub header_start
  436. {
  437.     my($self, $level, $node) = @_;
  438.     # If we are close enough to be bottom of the page, start a new page
  439.     # instead of this:
  440.     $self->vspace(1 + (6-$level) * 0.4);
  441.     $self->eat_leading_space;
  442.     $self->{bold}++;
  443.     push(@{$self->{font_size}}, 8 - $level);
  444.     1;
  445. }
  446.  
  447.  
  448. sub header_end
  449. {
  450.     my($self, $level, $node) = @_;
  451.     $self->vspace(1);
  452.     $self->{bold}--;
  453.     pop(@{$self->{font_size}});
  454.     1;
  455. }
  456.  
  457. sub hr_start
  458. {
  459.     my $self = shift;
  460.     $self->showline;
  461.     $self->vspace(0.5);
  462.     $self->skip_vspace;
  463.     my $lm = $self->{lm};
  464.     my $rm = $self->{rm};
  465.     my $y = $self->{ypos};
  466.     $self->collect(sprintf "newpath %.1f %.1f M %.1f %.1f lineto stroke\n",
  467.            $lm, $y, $rm, $y);
  468.     $self->vspace(0.5);
  469. }
  470.  
  471.  
  472. sub skip_vspace
  473. {
  474.     my $self = shift;
  475.     if (defined $self->{vspace}) {
  476.     $self->showline;
  477.     if ($self->{out}) {
  478.         $self->{ypos} -= $self->{vspace} * 10 * $self->{fontscale};
  479.         if ($self->{ypos} < $self->{bm}) {
  480.         $self->newpage;
  481.         }
  482.     }
  483.     $self->{xpos} = $self->{lm};
  484.     $self->{vspace} = undef;
  485.     }
  486. }
  487.  
  488.  
  489. sub show
  490. {
  491.     my $self = shift;
  492.     my $str = $self->{showstring};
  493.     return unless length $str;
  494.     $str =~ s/([\(\)\\])/\\$1/g;    # must escape parentesis
  495.     $self->{line} .= "($str)S\n";
  496.     $self->{showstring} = "";
  497. }
  498.  
  499.  
  500. sub showline
  501. {
  502.     my $self = shift;
  503.     $self->show;
  504.     my $line = $self->{line};
  505.     return unless length $line;
  506.     $self->{ypos} -= $self->{largest_pointsize} || $self->{pointsize};
  507.     if ($self->{ypos} < $self->{bm}) {
  508.     $self->newpage;
  509.     $self->{ypos} -= $self->{pointsize};
  510.     # must set current font again
  511.     my $font = $self->{prev_currentfont};
  512.     if ($font) {
  513.         $self->collect("$self->{fonts}{$font} SF\n");
  514.     }
  515.     }
  516.     my $lm = $self->{lm};
  517.     my $x = $lm;
  518.     if ($self->{center}) {
  519.     # Unfortunately, the center attribute is gone when we get here,
  520.     # so this code is never activated
  521.     my $linewidth = $self->{xpos} - $lm;
  522.     $x += ($self->{rm} - $lm - $linewidth) / 2;
  523.     }
  524.  
  525.     $self->collect(sprintf "%.1f %.1f M\n", $x, $self->{ypos});  # moveto
  526.     $line =~ s/\s\)S$/)S/;  # many lines will end with space
  527.     $self->collect($line);
  528.  
  529.     if ($self->{bullet}) {
  530.     # Putting this behind the first line of the list item
  531.     # makes it more likely that we get the right font.  We should
  532.     # really set the font that we want to use.
  533.     my $bullet = $self->{bullet};
  534.     if ($bullet eq '*') {
  535.         # There is no character that is really suitable.  Lets make
  536.         # filled cirle ourself.
  537.         my $radius = $self->{pointsize} / 4;
  538.         $self->collect(sprintf "newpath %.1f %.1f %.1f 0 360 arc fill\n",
  539.                $self->{bullet_pos} + $radius,
  540.                $self->{ypos} + $radius, $radius);
  541.     } else {
  542.         $self->collect(sprintf "%.1f %.1f M\n", # moveto
  543.                $self->{bullet_pos},
  544.                $self->{ypos});
  545.         $self->collect("($bullet)S\n");
  546.     }
  547.     $self->{bullet} = '';
  548.  
  549.     }
  550.  
  551.     $self->{prev_currentfont} = $self->{currentfont};
  552.     $self->{largest_pointsize} = 0;
  553.     $self->{line} = "";
  554.     $self->{xpos} = $lm;
  555.     # Additional linespacing
  556.     $self->{ypos} -= $self->{leading} * $self->{pointsize};
  557. }
  558.  
  559.  
  560. sub endpage
  561. {
  562.     my $self = shift;
  563.     # End previous page
  564.     $self->collect("showpage\n");
  565.     $self->{pageno}++;
  566. }
  567.  
  568.  
  569. sub newpage
  570. {
  571.     my $self = shift;
  572.     if ($self->{'out'}) {
  573.     $self->endpage;
  574.     }
  575.     $self->{'out'} = 0;
  576.     my $pageno = $self->{pageno};
  577.     $self->collect("\n%%Page: $pageno $pageno\n");
  578.  
  579.     # Print area marker (just for debugging)
  580.     if ($DEBUG) {
  581.     my($llx, $lly, $urx, $ury) = map { sprintf "%.1f", $_}
  582.                      @{$self}{qw(lm bm rm tm)};
  583.     $self->collect("gsave 0.1 setlinewidth\n");
  584.     $self->collect("clippath 0.9 setgray fill 1 setgray\n");
  585.     $self->collect("$llx $lly moveto $urx $lly lineto $urx $ury lineto $llx $ury lineto closepath fill\n");
  586.     $self->collect("grestore\n");
  587.     }
  588.  
  589.     # Print page number
  590.     if ($self->{printpageno}) {
  591.     $self->collect("%% Title and pageno\n");
  592.     my $f = $self->findfont(8);
  593.     $self->collect("$f\n") if $f;
  594.         my $x = $self->{paperwidth};
  595.         if ($x) { $x -= 30; } else { $x = 30; }
  596.         $self->collect(sprintf "%.1f 30.0 M($pageno)S\n", $x);
  597.     $x = $self->{lm};
  598.     $self->collect(sprintf "%.1f 30.0 M($self->{title})S\n", $x);
  599.     }
  600.     $self->collect("\n");
  601.  
  602.     $self->{xpos} = $self->{lm};
  603.     $self->{ypos} = $self->{tm};
  604. }
  605.  
  606.  
  607. sub out
  608. {
  609.     my($self, $text) = @_;
  610.     if ($self->{collectingTheTitle}) {
  611.         # Both collect and print the title
  612.         $text =~ s/([\(\)\\])/\\$1/g; # Escape parens.
  613.         $self->{title} .= $text;
  614.     return;
  615.     }
  616.     $self->skip_vspace;
  617.  
  618.     my $font = $self->findfont();
  619.     if (length $font) {
  620.     $self->show;
  621.     $self->{line} .= "$font\n";
  622.     }
  623.     my $w = $self->width($text);
  624.     if ($self->{xpos} + $w > $self->{rm}) {
  625.     $self->showline;
  626.     return if $text =~ /^\s*$/;
  627.     };
  628.     $self->{xpos} += $w;
  629.     $self->{showstring} .= $text;
  630.     $self->{largest_pointsize} = $self->{pointsize}
  631.       if $self->{largest_pointsize} < $self->{pointsize};
  632.     $self->{'out'}++;
  633. }
  634.  
  635.  
  636. sub pre_out
  637. {
  638.     my($self, $text) = @_;
  639.     $self->skip_vspace;
  640.     $self->tt_start;
  641.     my $font = $self->findfont();
  642.     if (length $font) {
  643.     $self->show;
  644.     $self->{line} .= "$font\n";
  645.     }
  646.     while ($text =~ s/(.*)\n//) {
  647.         $self->{'out'}++;
  648.     $self->{showstring} .= $1;
  649.     $self->showline;
  650.     }
  651.     $self->{showstring} .= $text;
  652.     $self->tt_end;
  653. }
  654.  
  655. sub bullet
  656. {
  657.     my($self, $bullet) = @_;
  658.     $self->{bullet} = $bullet;
  659.     $self->{bullet_pos} = $self->{lm};
  660. }
  661.  
  662. sub adjust_lm
  663. {
  664.     my $self = shift;
  665.     $self->showline;
  666.     $self->{lm} += $_[0] * $self->{en};
  667. }
  668.  
  669.  
  670. sub adjust_rm
  671. {
  672.     my $self = shift;
  673.     $self->showline;
  674.     $self->{rm} += $_[0] * $self->{en};
  675. }
  676.  
  677. sub head_start {
  678.     1;
  679. }
  680.  
  681. sub head_end {
  682.     1;
  683. }
  684.  
  685. sub title_start {
  686.     my($self) = @_;
  687.     $self->{collectingTheTitle} = 1;
  688.     1;
  689. }
  690.  
  691. sub title_end {
  692.     my($self) = @_;
  693.     $self->{collectingTheTitle} = 0;
  694.     1;
  695. }
  696.  
  697. 1;
  698.