Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/perl -w
      2 #
      3 # Format ImageMagick comments into POD-format or HTML format
      4 # documentation
      5 # Produces *.pod or *.html files corresponding to *.c files
      6 #
      7 # Written by Bob Friesenhahn, April 1997
      8 #
      9 
     10 $opt_format='html';
     11 $opt_srcdir='';
     12 $opt_outdir='';
     13 
     14 use Getopt::Long;
     15 if ( ! GetOptions(
     16                   'format=s'	=> \$opt_format,
     17                   'srcdir=s'	=> \$opt_srcdir,
     18                   'outdir=s'	=> \$opt_outdir,
     19                  )
     20    ) {
     21   print("Usage: fmtdocs [-srcdir srcdir] [-outdir outdir] [-format format] \n");
     22   exit(1);
     23 }
     24 
     25 #
     26 # Source files to use
     27 #
     28 @srcs = ('animate.c',
     29 	 'annotate.c',
     30 	 'attribute.c',
     31 	 'blob.c',
     32 	 'cache.c',
     33 	 'cache-view.c',
     34 	 'color.c',
     35 	 'colorspace.c',
     36 	 'compare.c',
     37 	 'composite.c',
     38 	 'constitute.c',
     39 	 'decorate.c',
     40    'deprecate.c',
     41 	 'draw.c',
     42 	 'drawing-wand.c',
     43 	 'display.c',
     44 	 'effect.c',
     45 	 'enhance.c',
     46 	 'exception.c',
     47 	 'fx.c',
     48 	 'image.c',
     49 	 'list.c',
     50 	 'magick.c',
     51 	 'magick-wand.c',
     52 	 'memory.c',
     53 	 'monitor.c',
     54 	 'montage.c',
     55    'paint.c',
     56 	 'pixel-iterator.c',
     57 	 'pixel-wand.c',
     58 	 'profile.c',
     59 	 'quantize.c',
     60 	 'registry.c',
     61    'resource.c',
     62 	 'segment.c',
     63 	 'shear.c',
     64 	 'signature.c',
     65 	 'stream.c',
     66 	 'transform.c',
     67 	 'resize.c',
     68    'version.c');
     69 
     70 $tmpname_pre_format = "/tmp/fmtdocs_pre.$$";
     71 $tmpname_pod = "/tmp/fmtdocs_pod.$$";
     72 $tmpname_html = "/tmp/fmtdocs_html.$$";
     73 
     74 #@srcs = ('draw.c');
     75 
     76 #
     77 # What is for source files
     78 #
     79 %whatis =
     80 (
     81  'animate',	'Interactively Animate an Image Sequence',
     82  'annotate',	'Annotate an Image',
     83  'attribute',	'Set Text Attributes',
     84  'blob',	'Read or Write Binary Large OBjects',
     85  'color',	'Count the Colors in an Image',
     86  'colorspace',	'Dealing with Image Colorspaces',
     87  'compare',	'Compare an Image to a Reconstructed Image',
     88  'constitute',	'Constitute an Image',
     89  'composite',	'Composite an Image',
     90  'decorate',	'Decorate an Image',
     91  'deprecate',	'Deprecated Methods',
     92  'display',	'Interactively Display and Edit an Image',
     93  'draw',	'Draw on an Image',
     94  'drawing_wand',	'Image Vector Drawing',
     95  'effect',	'Add an Effect',
     96  'fx',		'Add a Special Effect',
     97  'enhance',	'Enhance an Image',
     98  'exception',	'Dealing with Exceptions',
     99  'image',	'Image Methods',
    100  'list',	'Working with Image Lists',
    101  'cache',	'Get or Set Image Pixels',
    102  'cache_view',	'Working with Cache Views',
    103  'magick',	'Read or List Image formats',
    104  'magick_wand',	'Magick Wand',
    105  'memory',	'Memory Allocation',
    106  'monitor',	'Monitor the Progress of an Image Operation',
    107  'montage',	'Create an Image Thumbnail',
    108  'paint',	'Paint on an Image',
    109  'pixel_iterator',	'Pixel Iterator',
    110  'pixel_wand',	'Pixel Wand',
    111  'profile',	'Dealing with Image Profiles',
    112  'quantize',	'Reduce the Number of Unique Colors in an Image',
    113  'registry',	'The Registry',
    114  'resource',	'Minitor or Limit Resource Consumption',
    115  'segment',	'Segment an Image with Thresholding Fuzzy c-Means',
    116  'shear',	'Shear or Rotate an Image by an Arbitrary Angle',
    117  'signature',	'Compute a Digital Signature for an Image',
    118  'stream',	'The Pixel FIFO',
    119  'transform',	'Transform an Image',
    120  'resize',	'Resize an Image',
    121  'version',	'Get Version and Copyright',
    122 );
    123 
    124 #
    125 # Key words to replace with HTML links
    126 #
    127 my %keywords =
    128   (
    129    AffineMatrix		=> 'types.html#AffineMatrix',
    130    BlobInfo		=> 'types.html#BlobInfo',
    131    Cache		=> 'types.html#Cache',
    132    ChannelType		=> 'types.html#ChannelType',
    133    ChromaticityInfo	=> 'types.html#ChromaticityInfo',
    134    ClassType		=> 'types.html#ClassType',
    135    ClipPathUnits	=> 'types.html#ClipPathUnits',
    136    ColorPacket		=> 'types.html#ColorPacket',
    137    ColorspaceType	=> 'types.html#ColorspaceType',
    138    ComplianceType	=> 'types.html#ComplianceType',
    139    CompositeOperator	=> 'types.html#CompositeOperator',
    140    CompressionType	=> 'types.html#CompressionType',
    141    DecorationType	=> 'types.html#DecorationType',
    142    DrawContext		=> 'types.html#DrawContext',
    143    DrawInfo		=> 'types.html#DrawInfo',
    144    ErrorHandler		=> 'types.html#ErrorHandler',
    145    ExceptionInfo	=> 'types.html#ExceptionInfo',
    146    ExceptionType	=> 'types.html#ExceptionType',
    147    FillRule		=> 'types.html#FillRule',
    148    FilterTypes		=> 'types.html#FilterTypes',
    149    FrameInfo		=> 'types.html#FrameInfo',
    150    GravityType		=> 'types.html#GravityType',
    151    Image		=> 'types.html#Image',
    152    ImageInfo		=> 'types.html#ImageInfo',
    153    ImageType		=> 'types.html#ImageType',
    154    InterlaceType	=> 'types.html#InterlaceType',
    155    LayerType		=> 'types.html#LayerType',
    156    MagickInfo		=> 'types.html#MagickInfo',
    157    MonitorHandler	=> 'types.html#MonitorHandler',
    158    MontageInfo		=> 'types.html#MontageInfo',
    159    NoiseType		=> 'types.html#NoiseType',
    160    PaintMethod		=> 'types.html#PaintMethod',
    161    PixelPacket		=> 'types.html#PixelPacket',
    162    PointInfo		=> 'types.html#PointInfo',
    163    ProfileInfo		=> 'types.html#ProfileInfo',
    164    QuantizeInfo		=> 'types.html#QuantizeInfo',
    165    Quantum		=> 'types.html#Quantum',
    166    QuantumType		=> 'types.html#QuantumType',
    167    RectangleInfo	=> 'types.html#RectangleInfo',
    168    RegistryType		=> 'types.html#RegistryType',
    169    RenderingIntent	=> 'types.html#RenderingIntent',
    170    ResolutionType	=> 'types.html#ResolutionType',
    171    ResourceType		=> 'types.html#ResourceType',
    172    SegmentInfo		=> 'types.html#SegmentInfo',
    173    SignatureInfo	=> 'types.html#SignatureInfo',
    174    StorageType		=> 'types.html#StorageType',
    175    StreamHandler	=> 'types.html#StreamHandler',
    176    StretchType		=> 'types.html#StretchType',
    177    StyleType		=> 'types.html#StyleType',
    178    TypeMetric		=> 'types.html#TypeMetric',
    179    CacheView		=> 'types.html#CacheView',
    180    VirtualPixelMethod	=> 'types.html#VirtualPixelMethod',
    181    XResourceInfo	=> 'types.html#XResourceInfo',
    182 );
    183 
    184 
    185 foreach $src (@srcs) {
    186 
    187   my($out,$command);
    188 
    189   # Compute POD name
    190   ($base = $src) =~ s/\.[^\.]*$//g;
    191 
    192   $out = "${base}.${opt_format}";
    193   if ("${opt_outdir}" ne "") {
    194     $out = "${opt_outdir}/${base}.${opt_format}";
    195   }
    196 
    197   if ("${opt_srcdir}" ne "") {
    198     $src = "${opt_srcdir}/${src}";
    199   }
    200 
    201   $command='pod2html -netscape';
    202   if ( $opt_format eq 'html' ) {
    203     $command='pod2html -netscape';
    204   } elsif ( $opt_format eq 'latex' ) {
    205     $command='pod2latex';
    206   } elsif ( $opt_format eq 'man' ) {
    207     $command='pod2man';
    208   } elsif ( $opt_format eq 'text' ) {
    209     $command='pod2text';
    210   } elsif ( $opt_format eq 'pod' ) {
    211     $command='cat';
    212   }
    213 
    214   print( "Processing $src -> $out\n" );
    215 
    216   pre_format($src, $tmpname_pre_format);		# Make easily parsed
    217   format_to_pod($tmpname_pre_format, $tmpname_pod);	# Format to pod.
    218 
    219   if ( $opt_format eq 'html' ) {
    220     system("$command $tmpname_pod > \"$tmpname_html\"");
    221     reformat_html($tmpname_html,$out);
    222   } else {
    223     system("$command $tmpname_pod > \"$out\"");
    224   }
    225   unlink($tmpname_pre_format);
    226   unlink($tmpname_pod);
    227   unlink($tmpname_html);
    228 }
    229 
    230 #unlink($tmpname_pre_format);
    231 exit(0);
    232 
    233 #
    234 # Reformat pod2html-generated HTML into nicer form.
    235 #
    236 sub reformat_html {
    237   my($infile, $outfile) = @_;
    238 
    239   open( IN, "<$infile" ) || die("Failed to open \"$infile\" for read\n" );
    240   open( OUT, ">$outfile" ) || die("Failed to open \"$outfile\" for write\n" );
    241 
    242  INPUT:
    243   while(<IN>) {
    244     s|<\!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">|<\!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    245   "http://www.w3.org/TR/html4/loose.dtd">|;
    246     s|<HEAD>|<HEAD>
    247 <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
    248 <STYLE>
    249 <!--
    250 \@page { size: 8.5in 11in }
    251 TD P { color: #000000; font-family: "Verdana", "Arial", "Helvetica", sans-serif; font-size: 12pt }
    252 P { color: #000000; font-family: "Verdana", "Arial", "Helvetica", sans-serif; font-size: 12pt }
    253 H2 { color: #000000 }
    254 A:link { color: #0085c0 }
    255 A:visited { color: #800080 }
    256 -->
    257 </STYLE>
    258 |;
    259     s|<link rev="made" href="mailto:root\@localhost" />|<link rel="stylesheet" type="text/css" href="../magick.css">|;
    260     s|<body style="background-color: white">|<body marginheight="1" marginwidth="1" topmargin="1" leftmargin="1">
    261 <a name="top"></a> 
    262 <table border="0" cellpadding="0" cellspacing="0" summary="Masthead" width="100%">
    263 <tbody>
    264 <tr>
    265 <td bgcolor="#003399" width="25%" height="118" background="../../images/background.gif"><a href="http://www.imagemagick.org/"><img src="../../images/script.gif" width="278" height="118" border="0" alt="" /></a></td>
    266 <td bgcolor="#003399" width="60%" height="118" background="../../images/background.gif"><a href="http://www.networkeleven.com/direct.php?magick_all"><img src="../../images/promote.png" border="0" width="186" height="52" vspace="29" alt="Powered by NetworkEleven" /></a></td>
    267 <td bgcolor="#003399" width="114" height="118" align="right"><img src="../../images/sprite.png" width="114" height="118" alt="" /></td>
    268 <td bgcolor="#003399" width="114" height="118" align="right"><a href="http://www.imagemagick.net"><img src="../../images/logo.png" width="114" height="118" border="0" alt="ImageMagick logo" /></a></td>
    269 </tr></tbody></table>
    270 <table align="left" border="0" cellpadding="2" cellspacing="2" summary="Navigation buttons" width="20%">
    271 <tr>
    272 <td>
    273 <form target="_self" action="../../index.html"><input type="submit" title="ImageMagick Home" value=" Home" style="background-color: #1947A3; background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold"></form></td>
    274 <td>
    275 <form target="_self" action="../../www/apis.html"><input type="submit" title="ImageMagick API" value=" API " style="background-color: #1947A3; background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold"></form></td>
    276 <td>
    277 <form target="_self" action="../../www/download.html"><input type="submit" title="ImageMagick Download" value="Download" style="background-color: #1947A3; background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold"></form></td></tr></table>
    278 <div align="right" style="margin-top:3px; padding-right:4px">
    279 <form action="http://studio.imagemagick.org/Sage/scripts/Sage.cgi"><input type="TEXT" name="query" size="32" maxlength="255"> <input type="SUBMIT" name="sa" value="Search" style="background-color: #1947A3; background-image:url('../../../images/background.gif'); bgcolor:#003399; color:#fbc713; font-weight:bold"></form></div>
    280 <table align="left" border="0" cellpadding="10" cellspacing="0" style="margin-top:-17px" width="100%">
    281 <tr>
    282 <td>
    283 |;
    284     s|</body>|
    285 <HR>
    286 
    287 <a href="#top"><img src="../../../images/top.gif" border=0 width="35" height="46" align="right" alt="Top of page"></a>
    288 <form action="http://studio.imagemagick.org/magick/" style="margin-top:5px">
    289 <input type="submit" title="Help!" value="Help!" style="background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold">
    290   <small>&quot;Image manipulation software that works like magick&quot;</small>
    291 </form></td>
    292 </tr></table>
    293 
    294 </body>
    295 |;
    296     s|<FONT SIZE=-1>||g;
    297     s|</FONT>||g;
    298 
    299     s|<H2>|<H3>|g;
    300     s|</H2>|</H3>|g;
    301 
    302     s|<H1>|<H2>|g;
    303     s|</H1>|</H2>|g;
    304 
    305     s|<DT>|<DD><P></P><DT>|g;
    306     s|<DL>|<DL><DT><DD><DL>|g;
    307     s|</DL>|</DL></DL>|g;
    308     s|<dd>|<DD>|g;
    309     s|<p>|<P>|g;
    310     s|</p>|</P>|g;
    311     s|</LI>||g;
    312     s|>o |>|g;
    313     s|unsignedint|unsigned int|g;
    314     print( OUT $_ );
    315   }
    316   close( TMP );
    317   close( IN );
    318 }
    319 
    320 #
    321 # Pre-process file into intermediate form
    322 #
    323 # Initializes globals:
    324 #
    325 #  @functions	- Function names
    326 #  %synopsis	- Function synopsis
    327 #
    328 sub pre_format {
    329   my($infile, $tmpfile) = @_;
    330 
    331   my $inpara = 0;	# Set to 1 if in paragraph
    332   my $inlist = 0;	# Set to 1 if in list-item paragraph
    333 
    334   # Open C source file
    335   open( IN, "<$infile" ) || die("Failed to open \"$infile\" for read\n" );
    336 
    337   # Open TMP file
    338   open( TMP, ">$tmpfile" ) || die("Failed to open \"$tmpfile\" for write\n" );
    339 
    340   undef @functions;
    341   undef %synopsis;
    342 
    343   # Skip past first form feed
    344   while(<IN>) {
    345     last if m/\014/;
    346   }
    347 
    348 LINE:
    349   while(<IN>) {
    350     if (m/^\+/) {
    351       while(<IN>) {
    352 	last unless m/^%/;
    353       }
    354       next;
    355     }
    356     next unless m/^%/ ;
    357     chop;
    358 
    359     # Extract and save function title
    360     if (m/^%\s+((\w )+)\s+%/) {
    361       ($ftitle = $1) =~ s/ //g;
    362       push(@functions, $ftitle);
    363       print( TMP "===$ftitle\n" );
    364       next;
    365     }
    366 
    367     # Zap text we don't want
    368     next if ( m/^%.+%/ );	# "%*%
    369     s/^%\s{0,2}//;
    370 
    371     # Extract and save synopsis info
    372     if (m /\(\)/ ) {
    373       # nothing
    374       ;
    375     }
    376     elsif ( m/${ftitle}\(.*\)$/ ) {
    377       s/,/ , /g;
    378       s/\(/ ( /g;
    379       s/\)/ ) /g;
    380       s/\*/ * /g;
    381       s/\s+/ /g;
    382 
    383       s/\(\s+\*/(*/g;
    384       s/ ,/,/g;
    385       s/ \(/(/g;
    386       s/\) /)/g;
    387       s/ \* / */g;
    388 
    389       s/^\s*//;
    390       $synopsis{$ftitle} = $_ . ';'; # Append semi-colon, prototype style
    391       print ( TMP " " . $synopsis{$ftitle} . "\n" );
    392       next LINE;
    393      }
    394      elsif ( m/${ftitle}\(.*/ ) {
    395       $synopsis{$ftitle} = $_;
    396       do {
    397 	$_ = <IN>;
    398 	chop;
    399 	# Zap text we don't want
    400 	next if m/^%.+%/;	# "%*%
    401 	s/^%\s{0,2}//;
    402 	$synopsis{$ftitle} .= $_;
    403       } until m/^\s*$/;
    404       $_ = $synopsis{$ftitle};
    405 
    406       s/,/ , /g;
    407       s/\(/ ( /g;
    408       s/\)/ ) /g;
    409       s/\*/ * /g;
    410       s/\s+/ /g;
    411 
    412       s/\(\s+\*/(*/g;
    413       s/ ,/,/g;
    414       s/ \(/(/g;
    415       s/\) /)/g;
    416       s/ \* / */g;
    417 
    418       s/^\s*//;
    419       $synopsis{$ftitle} = $_ . ';'; # Append semi-colon, prototype style
    420       print ( TMP " " . $synopsis{$ftitle} . "\n" );
    421       next LINE;
    422     }
    423 
    424   # Keep track of paragraphing
    425   if( ! m/^$/ ) {
    426     if ( $inpara == 0 ) {
    427       $inpara = 1;	# Start of paragraph
    428       $para = "$_";	# Start paragraph string
    429     } else {
    430       # Inside paragraph
    431       $para .= " $_";	# Add line to paragraph
    432     }
    433   }
    434   # Keep track of list items so they can
    435   # be wrapped as a paragraph
    436   if( m/^\s+(o[^:]+:|o|[0-9]\.)\s(.*)/ ) {
    437     $inlist = 1;
    438   }
    439 
    440   if ( $inpara == 1 ) {
    441     if( $para =~ m/^\s+\S+/ && ! $inlist ) {
    442       # Lines that start with a space shouldn't be munged
    443       $inpara = 0;	# End of paragraph
    444       $inlist = 0;
    445       $para .= "";	# Terminate paragraph
    446       print( TMP "$para\n" );
    447     }
    448     elsif( m/^$/ ) {
    449       # End of paragraph
    450       $inpara = 0;	# End of paragraph
    451       $inlist = 0;
    452       $para .= "";	# Terminate paragraph
    453       $para =~ s/^\s+//g;		# Eliminate any leading space
    454       $para =~ s/\s+/ /g;		# Canonicalize whitespace
    455       $para =~ s/ $//;		# Trim final space
    456       $para =~ s/([a-zA-Z0-9][.!?][)'"]*) /$1  /g; #' Fix sentance ends
    457 		  print( TMP "\n$para\n\n" );
    458 		}
    459     }
    460   }
    461 
    462   close( TMP );
    463   close( IN );
    464 }
    465 
    466 #
    467 # Second pass
    468 # Process into formatted form
    469 #
    470 sub format_to_pod {
    471     my($infile, $outfile) = @_;
    472 
    473     my $func;
    474 
    475     my $inlist = 0;		# Set to one if in indented list
    476 
    477     # Open input file
    478     open( IN, "<$infile" ) || die("Failed to open \"$infile\" for read\n" );
    479 
    480     # Open output file
    481     open( OUT, ">$outfile" ) || die("Failed to open \"$outfile\" for write\n" );
    482 
    483     # Name field
    484     print( OUT head1("NAME") );
    485     if (!defined($whatis{$base})) {
    486       print("Whatis definition missing for \"$base\"!\n");
    487       print( OUT "${base} - Unknown\n\n" );
    488     } else {
    489       print( OUT "${base} - $whatis{$base}\n\n" );
    490     }
    491 
    492     # Synopsis field (function signatures)
    493     print( OUT head1("SYNOPSIS") );
    494     foreach $func (sort( @functions )) {
    495       if (defined $synopsis{$func} ) {
    496 	$_ = $synopsis{$func};
    497 	s/$func/ B<$func>/;
    498 	s/^\s*//;
    499 	my $synopsis = $_;
    500 	print( OUT $synopsis, "\n\n" );
    501       }
    502     }
    503 
    504     # Description field
    505     print( OUT head1("FUNCTION DESCRIPTIONS") );
    506 
    507     while(<IN>){
    508 	chop;
    509 	next if m/^$/;
    510 
    511 	# Match list element
    512 	if( m/^(o[^:]+:|o|[0-9]\.?)\s(.*)/ ) {
    513 	    my $bullet = $1;
    514 	    my $bullet_text = $2;
    515 
    516 	    print( OUT startlist() ) unless $inlist;
    517 	    $inlist = 1;
    518 	    print( OUT item($bullet), "$bullet_text\n\n" );
    519 	    next;
    520 	} else {
    521 	    print( OUT endlist() ) if $inlist;
    522 	    $inlist = 0;
    523 	}
    524 
    525 	# Match synopsis item
    526 	if( defined $func && m/$func\s*\(.*\)/ ) {
    527 	  # Split all words with spaces to aid with tokenization
    528 	  s/,/ , /g;
    529 	  s/\(/ ( /g;
    530 	  s/\)/ ) /g;
    531 	  s/\*/ * /g;
    532 
    533 	  my $html = '';
    534 
    535 	  # Replace tokens matching keywords with HTML links.
    536 TOKEN:	  foreach $token ( split(' ', $_ ) ) {
    537 	    foreach $keyword ( %keywords ) {
    538 	      if ( $token eq $keyword ) {
    539 		$html .= linked( $keyword, $keywords{$keyword} );
    540 		$html .= " ";
    541 		next TOKEN;
    542 	      }
    543 	    }
    544 	    $html .= "$token ";
    545 	  }
    546 	  $_ = $html;
    547 	  # Remove excess spaces
    548 	  s/\s+/ /g;
    549 	  s/ ,/,/g;
    550 	  s/\* /*/g;
    551 	  s/\)\s*\;/);/;
    552 	  s/^\s*//;
    553           s/ \( *\)/\(\)/;
    554 
    555           # This is very poor because text is output specifically
    556           # for HTML so the text isn't output at all for other target
    557           # formats.
    558 	  print( OUT html("<blockquote>$_</blockquote>") );
    559 	    next;
    560 	}
    561 
    562 	# Match function title
    563 	if( m/===([a-zA-Z0-9]+)/ ) {
    564 	    $func = $1;
    565 	    print( OUT head2($func) );
    566 	    next;
    567 	}
    568 
    569         print( OUT "\n") if /^[^ ]/;
    570 	print( OUT "$_\n") ;
    571         print( OUT "\n") if /^[^ ]/;
    572     }
    573 
    574     close( OUT );
    575     close( IN );
    576 }
    577 
    578 #
    579 # Return level 1 heading
    580 # Similar to: <H1>heading</H1>
    581 #
    582 sub head1 {
    583     my($heading) = @_;
    584     return( "=head1 $heading\n\n" );
    585 }
    586 
    587 #
    588 # Return level 2 heading
    589 # Similar to: <H2>heading</H2>
    590 #
    591 sub head2 {
    592     my($heading) = @_;
    593     return( "=head2 $heading\n\n" );
    594 }
    595 
    596 
    597 #
    598 # Return item
    599 # Simlar to: <I>
    600 #
    601 sub item {
    602     my($item) = @_;
    603     return( "=item $item\n\n" );
    604 }
    605 
    606 
    607 #
    608 # Start list
    609 # Similar to: <UL>
    610 #
    611 sub startlist {
    612     return( "=over 4\n\n" )
    613 }
    614 
    615 #
    616 # End list
    617 # Similar to: </UL>
    618 #
    619 sub endlist {
    620     return( "=back\n\n" );
    621 }
    622 
    623 #
    624 # Preformatted text
    625 # Similar to <PRE></PRE>
    626 #
    627 sub formated {
    628     my($text) = @_;
    629     return( " $text\n\n" );
    630 }
    631 
    632 #
    633 # Raw HTML paragraph
    634 #
    635 sub html {
    636   my($html) = @_;
    637   return return( "=for html $html\n\n" );
    638 }
    639 
    640 #
    641 # HTML Link
    642 # Similar to: <A HREF="url">description</A>
    643 #
    644 sub linked {
    645   local($description, $url) = @_;
    646   return( "<A HREF=\"" . $url . "\">" . $description . "</A>" );
    647 }
    648