texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

texinfo/tp TODO Texinfo/Common.pm Texinfo/Conve...


From: Patrice Dumas
Subject: texinfo/tp TODO Texinfo/Common.pm Texinfo/Conve...
Date: Sun, 27 Mar 2011 22:55:14 +0000

CVSROOT:        /sources/texinfo
Module name:    texinfo
Changes by:     Patrice Dumas <pertusus>        11/03/27 22:55:13

Modified files:
        tp             : TODO 
        tp/Texinfo     : Common.pm 
        tp/Texinfo/Convert: Converter.pm Plaintext.pm Text.pm 
        tp/t           : 02coverage.t test_utils.pl 
Added files:
        tp/Texinfo/Convert: HTML.pm 

Log message:
        Unfinished and non functional HTML output.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/TODO?cvsroot=texinfo&r1=1.116&r2=1.117
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/Texinfo/Common.pm?cvsroot=texinfo&r1=1.26&r2=1.27
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/Texinfo/Convert/Converter.pm?cvsroot=texinfo&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/Texinfo/Convert/Plaintext.pm?cvsroot=texinfo&r1=1.129&r2=1.130
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/Texinfo/Convert/Text.pm?cvsroot=texinfo&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/Texinfo/Convert/HTML.pm?cvsroot=texinfo&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/t/02coverage.t?cvsroot=texinfo&r1=1.46&r2=1.47
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/t/test_utils.pl?cvsroot=texinfo&r1=1.77&r2=1.78

Patches:
Index: TODO
===================================================================
RCS file: /sources/texinfo/texinfo/tp/TODO,v
retrieving revision 1.116
retrieving revision 1.117
diff -u -b -r1.116 -r1.117
--- TODO        27 Mar 2011 17:12:46 -0000      1.116
+++ TODO        27 Mar 2011 22:55:12 -0000      1.117
@@ -9,8 +9,8 @@
   complex commands, that have both arguments and contents, like quotations,
   the call would be
 
-fun($converter, $cmd_or_type_name, $command_in_tree, $contents_formatted,
-    $args_formatted);
+fun($converter, $cmd_or_type_name, $command_in_tree, $args_formatted,
+    $contents_formatted);
 
   For a command with contents and no meaningful arg (like @example
   or @table):

Index: Texinfo/Common.pm
===================================================================
RCS file: /sources/texinfo/texinfo/tp/Texinfo/Common.pm,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- Texinfo/Common.pm   27 Mar 2011 14:20:22 -0000      1.26
+++ Texinfo/Common.pm   27 Mar 2011 22:55:13 -0000      1.27
@@ -271,10 +271,18 @@
   $brace_commands{$accent_command} = 1;
 }
 
-foreach my $one_arg_command ('asis','b','cite','clicksequence',
-  'ctrl','dfn','dmn','emph','headitemfont',
-  'i','slanted','sansserif','r','sc','strong',
-  't','var', 'w', 
+our %style_commands;
+foreach my $style_command ('asis','b','cite','clicksequence',
+  'dfn', 'emph',
+  'i', 'sc', 't', 'r', 'slanted', 'sansserif', 'var',
+  'headitemfont', 'code', 'command', 'env', 'file', 'kbd',
+  'option', 'samp', 'strong') {
+  $brace_commands{$style_command} = 1;
+  $style_commands{$style_command} = 1;
+}
+
+foreach my $one_arg_command (
+  'ctrl','dmn', 'w', 
   'titlefont','hyphenation','anchor') {
   $brace_commands{$one_arg_command} = 1;
 }

Index: Texinfo/Convert/Converter.pm
===================================================================
RCS file: /sources/texinfo/texinfo/tp/Texinfo/Convert/Converter.pm,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- Texinfo/Convert/Converter.pm        27 Mar 2011 17:12:47 -0000      1.4
+++ Texinfo/Convert/Converter.pm        27 Mar 2011 22:55:13 -0000      1.5
@@ -364,4 +364,87 @@
     = $Texinfo::Convert::Text::text_no_brace_commands{$text_no_brace_commands};
 }
 
+my %xml_accent_entities = (
+          '"',  'uml',
+          '~',  'tilde',
+          '^',  'circ',
+          '`',  'grave',
+          "'", 'acute',
+          ",", 'cedil',
+          'ringaccent', 'ring',
+          'ogonek', 'ogon',
+         );
+
+my %xml_accent_text_with_entities = (
+      'ringaccent' => 'aA',
+      "'"          => 'aeiouyAEIOUY',
+      ','          => 'cC',
+      '^'          => 'aeiouAEIOU',
+      '`'          => 'aeiouAEIOU',
+      '~'          => 'nNaoAO',
+      '"'          => 'aeiouyAEIOU',
+# according to http://www2.lib.virginia.edu/small/vhp/download/ISO.txt
+# however this doesn't seems to work in firefox
+#      'ogonek'     => 'aeiuAEIU',
+);
+
+
+sub xml_accent($$;$)
+{
+  my $text = shift;
+  my $command = shift;
+  my $use_numeric_entities = shift;
+  my $accent = $command->{'cmdname'};
+  
+  return "&${text}$xml_accent_entities{$accent};" 
+    if (defined($xml_accent_entities{$accent}) 
+        and defined($xml_accent_text_with_entities{$accent}) 
+        and ($text =~ /^[$xml_accent_text_with_entities{$accent}]$/));
+  if ($use_numeric_entities
+      and exists($Texinfo::Convert::unicode_accented_letters{$accent}) 
+      and 
exists($Texinfo::Convert::unicode_accented_letters{$accent}->{$text})) {
+    return ('&#' . 
+      hex($Texinfo::Convert::unicode_accented_letters{$accent}->{$text}). ';');
+  }
+  return $text . '&lt;' if ($accent eq 'v');
+  return Texinfo::Convert::Text::ascii_accent($text, $command);
+}
+
+sub xml_accent_numeric_entities($$)
+{
+  my $text = shift;
+  my $command = shift;
+  return xml_accent($text, $command, 1);
+}
+
+sub xml_accents($$)
+{ 
+  my $self = shift;
+  my $accent = shift;
+  my $format_accents;
+  if ($self->{'USE_NUMERIC_ENTITY'}) {
+    $format_accents = \&xml_accent_numeric_entities;
+  } else {
+    $format_accents = \&xml_accent;
+  }
+  
+  if ($self->{'ENABLE_ENCODING'}) {
+    if ($self->{'encoding_name'} and $self->{'encoding_name'} eq 'utf-8') {
+      return Texinfo::Convert::Text::unicode_accents($accent, $format_accents);
+    } elsif ($self->{'encoding_name'} 
+           and 
$Texinfo::Common::eight_bit_encoding_aliases{$self->{'encoding_name'}}) {
+      return Texinfo::Convert::Text::eight_bit_accents($accent, 
+                                      $self->{'encoding_name'}, 
$format_accents);
+    }
+  }
+  my ($contents, $innermost_accent, $stack)
+      = Texinfo::Convert::Text::_find_innermost_accent_contents($accent);
+  my $result = $self->_convert({'contents' => $contents});
+  
+  foreach my $accent_command (reverse(@$stack)) {
+    $result = &$format_accents ($result, {'cmdname' => $accent_command});
+  }
+  return $result;
+}
+
 1;

Index: Texinfo/Convert/Plaintext.pm
===================================================================
RCS file: /sources/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm,v
retrieving revision 1.129
retrieving revision 1.130
diff -u -b -r1.129 -r1.130
--- Texinfo/Convert/Plaintext.pm        27 Mar 2011 17:12:47 -0000      1.129
+++ Texinfo/Convert/Plaintext.pm        27 Mar 2011 22:55:13 -0000      1.130
@@ -1232,8 +1232,12 @@
       return $result;
     # commands with braces
     } elsif ($accent_commands{$root->{'cmdname'}}) {
+      my $encoding;
+      if ($self->{'ENABLE_ENCODING'}) {
+        $encoding = $self->{'encoding_name'};
+      }
       my $accented_text 
-         = Texinfo::Convert::Text::text_accents($root, 
$self->{'encoding_name'});
+         = Texinfo::Convert::Text::text_accents($root, $encoding);
       $result .= $self->_count_added($formatter->{'container'},
          $formatter->{'container'}->add_text($accented_text));
       # in case the text added ends with punctuation.  

Index: Texinfo/Convert/Text.pm
===================================================================
RCS file: /sources/texinfo/texinfo/tp/Texinfo/Convert/Text.pm,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- Texinfo/Convert/Text.pm     27 Mar 2011 15:38:33 -0000      1.35
+++ Texinfo/Convert/Text.pm     27 Mar 2011 22:55:13 -0000      1.36
@@ -25,6 +25,8 @@
 # accent commands list.
 use Texinfo::Common;
 use Texinfo::Convert::Unicode;
+# for debugging
+use Texinfo::Convert::Texinfo;
 use Data::Dumper;
 
 require Exporter;
@@ -544,7 +546,9 @@
 }
 
 # find the innermost accent and the correspponding text contents
-# FIXME This is not output dependent, move to Texinfo::Parser?
+# FIXME This is not output dependent, so could be in 
+# Texinfo::Convert::Converter.  However this would create a 
+# dependency loop.
 sub _find_innermost_accent_contents($;$)
 {
   my $current = shift;
@@ -766,7 +770,7 @@
 
   foreach my $accent_command (reverse(@$stack)) {
     $result = Texinfo::Convert::Unicode::unicode_accent($result, 
-       {'cmdname' => $accent_command}, \&ascii_accent);
+       {'cmdname' => $accent_command}, $format_accents);
   }
   return $result;
 }

Index: t/02coverage.t
===================================================================
RCS file: /sources/texinfo/texinfo/tp/t/02coverage.t,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -b -r1.46 -r1.47
--- t/02coverage.t      19 Mar 2011 16:20:31 -0000      1.46
+++ t/02coverage.t      27 Mar 2011 22:55:13 -0000      1.47
@@ -667,6 +667,7 @@
 
 foreach my $test (@test_cases) {
   push @{$test->[2]->{'test_formats'}}, 'plaintext';
+#  push @{$test->[2]->{'test_formats'}}, 'html';
 }
 
 our ($arg_test_case, $arg_generate, $arg_debug);

Index: t/test_utils.pl
===================================================================
RCS file: /sources/texinfo/texinfo/tp/t/test_utils.pl,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -b -r1.77 -r1.78
--- t/test_utils.pl     24 Mar 2011 00:51:56 -0000      1.77
+++ t/test_utils.pl     27 Mar 2011 22:55:13 -0000      1.78
@@ -12,6 +12,7 @@
 use Texinfo::Structuring;
 use Texinfo::Convert::Plaintext;
 use Texinfo::Convert::Info;
+use Texinfo::Convert::HTML;
 use DebugTexinfo::DebugCount;
 use File::Basename;
 use Data::Dumper;
@@ -37,6 +38,7 @@
 my %formats = (
   'plaintext' => \&convert_to_plaintext,
   'info' => \&convert_to_info,
+  'html' => \&convert_to_html,
   'debugcount' => \&debugcount,
 );
 
@@ -221,6 +223,25 @@
   return ($errors, $result);
 }
 
+sub convert_to_html($$$;$)
+{
+  my $self = shift;
+  my $tree = shift;
+  my $parser = shift;
+  my $converter_options = shift;
+  $converter_options = {} if (!defined($converter_options));
+  my $converter =
+     Texinfo::Convert::HTML->converter ({'DEBUG' => $self->{'DEBUG'},
+                                         'parser' => $parser,
+                                         'OUTFILE' => '',
+                                         'output_format' => 'html',
+                                          %$converter_options });
+  my $result = $converter->output($tree);
+  die if (!defined($result));
+  my ($errors, $error_nrs) = $converter->errors();
+  return ($errors, $result);
+}
+
 sub debugcount($$$;$)
 {
   my $self = shift;

Index: Texinfo/Convert/HTML.pm
===================================================================
RCS file: Texinfo/Convert/HTML.pm
diff -N Texinfo/Convert/HTML.pm
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Texinfo/Convert/HTML.pm     27 Mar 2011 22:55:13 -0000      1.1
@@ -0,0 +1,1172 @@
+# HTML.pm: output tree as HTML.
+#
+# Copyright 2011 Free Software Foundation, Inc.
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License,
+# or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# 
+# Original author: Patrice Dumas <address@hidden>
+
+package Texinfo::Convert::HTML;
+
+use 5.00405;
+use strict;
+
+use Texinfo::Convert::Converter;
+use Texinfo::Common;
+use Texinfo::Report;
+use Texinfo::Convert::Texinfo;
+use Texinfo::Convert::Text;
+use Texinfo::Parser qw(gdt);
+
+use Carp qw(cluck);
+
+require Exporter;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
address@hidden = qw(Exporter Texinfo::Convert::Converter);
+
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+
+# This allows declaration       use Texinfo::Convert::Plaintext ':all';
+# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
+# will save memory.
+%EXPORT_TAGS = ( 'all' => [ qw(
+  convert
+  output
+) ] );
+
address@hidden = ( @{ $EXPORT_TAGS{'all'} } );
+
address@hidden = qw(
+);
+
+$VERSION = '0.01';
+
+# misc commands that are of use for formatting.
+my %formatting_misc_commands = 
%Texinfo::Convert::Text::formatting_misc_commands;
+my %text_no_brace_commands = %Texinfo::Convert::Text::text_no_brace_commands;
+my %no_brace_commands = %Texinfo::Convert::Text::no_brace_commands;
+my %text_brace_no_arg_commands = 
%Texinfo::Convert::Text::text_brace_no_arg_commands;
+my %accent_commands = %Texinfo::Common::accent_commands;
+my %misc_commands = %Texinfo::Common::misc_commands;
+my %sectioning_commands = %Texinfo::Common::sectioning_commands;
+my %def_commands = %Texinfo::Common::def_commands;
+my %ref_commands = %Texinfo::Common::ref_commands;
+my %brace_commands = %Texinfo::Common::brace_commands;
+my %block_commands = %Texinfo::Common::block_commands;
+my %menu_commands = %Texinfo::Common::menu_commands;
+my %root_commands = %Texinfo::Common::root_commands;
+my %preformatted_commands = %Texinfo::Common::preformatted_commands;
+my %explained_commands = %Texinfo::Common::explained_commands;
+my %item_container_commands = %Texinfo::Common::item_container_commands;
+my %raw_commands = %Texinfo::Common::raw_commands;
+my @out_formats = @Texinfo::Common::out_formats;
+my %code_style_commands       = %Texinfo::Common::code_style_commands;
+my %preformatted_code_commands = %Texinfo::Common::preformatted_code_commands;
+my %default_index_commands = %Texinfo::Common::default_index_commands;
+my %style_commands = %Texinfo::Common::style_commands;
+
+foreach my $def_command (keys(%def_commands)) {
+  $formatting_misc_commands{$def_command} = 1 if 
($misc_commands{$def_command});
+}
+
+
+my %defaults = (
+  'ENABLE_ENCODING'      => 1,
+  'SHOW_MENU'            => 1,
+  'footnotestyle'        => 'end',
+#  'perl_encoding'        => 'ascii',
+#  'encoding_name'      => 'us-ascii',
+  'encoding_name'        => undef,
+  'perl_encoding'        => undef,
+  'OUTFILE'              => undef,
+  'SUBDIR'               => undef,
+  'documentlanguage'     => undef,
+  'NUMBER_FOOTNOTES'     => 1,
+  'expanded_formats'     => undef,
+  'include_directories'  => undef,
+  'NUMBER_SECTIONS'      => 1,
+  'USE_NODES'            => 1,
+  'SPLIT'                => 0,
+# if set style is added in attribute.
+  'INLINE_CSS_STYLE'     => 0,
+# if set, no css is used.
+  'NO_CSS'               => 0,
+# if set, use node anchors for sections targets
+  'USE_NODE_TARGET'      => 1,
+  'OPEN_QUOTE_SYMBOL'    => '&lsquo;',
+  'CLOSE_QUOTE_SYMBOL'   => '&rsquo;',
+  'USE_ISO'              => 1,
+
+
+  'DEBUG'                => 0,
+  'TEST'                 => 0,
+);
+
+sub _defaults($)
+{
+  return %defaults;
+}
+
+my $NO_BULLET_LIST_STYLE = 'list-style: none';
+my $NO_BULLET_LIST_CLASS = 'no-bullet';
+my $NO_BULLET_LIST_ATTRIBUTE = ' class="'.$NO_BULLET_LIST_CLASS.'"';
+
+my $MENU_PRE_STYLE = 'font-family: serif';
+
+my %css_map =      (
+         "ul.$NO_BULLET_LIST_CLASS" => "$NO_BULLET_LIST_STYLE",
+         'pre.menu-comment'       => "$MENU_PRE_STYLE",
+         'pre.menu-preformatted'  => "$MENU_PRE_STYLE",
+         'a.summary-letter'       => 'text-decoration: none',
+         'blockquote.smallquotation' => 'font-size: smaller',
+#         'pre.display'            => 'font-family: inherit',
+#         'pre.smalldisplay'       => 'font-family: inherit; font-size: 
smaller',
+         'pre.display'            => 'font-family: serif',
+         'pre.smalldisplay'       => 'font-family: serif; font-size: smaller',
+         'pre.smallexample'       => 'font-size: smaller',
+         'span.sansserif'         => 'font-family:sans-serif; 
font-weight:normal',
+         'span.roman'         => 'font-family:serif; font-weight:normal',
+         'span.nocodebreak'   => 'white-space:pre',
+         'span.nolinebreak'   => 'white-space:pre'
+     );
+
+$css_map{'pre.format'} = $css_map{'pre.display'};
+$css_map{'pre.smallformat'} = $css_map{'pre.smalldisplay'};
+$css_map{'pre.smalllisp'} = $css_map{'pre.smallexample'};
+
+foreach my $indented_format ('example', 'display', 'lisp')
+{
+  $css_map{"div.$indented_format"} = 'margin-left: 3.2em';
+  $css_map{"div.small$indented_format"} = 'margin-left: 3.2em';
+}
+
+# Default for the function references used for the formatting
+# of commands.
+my %default_commands_conversion;
+
+# Ignored commands
+
+my %kept_misc_commands;
+foreach my $command ('footnotestyle', 'documentlanguage', 
+      'allowcodebreaks') {
+  $kept_misc_commands{$command} = 1;
+}
+
+# taken from global
+# 'xrefautomaticsectiontitle' (or in Parser?)
+# 'documentencoding'
+# 'setcontentsaftertitlepage', 'setshortcontentsaftertitlepage'
+# 'novalidate'
+foreach my $misc_command('verbatiminclude', 'contents', 'shortcontents',
+        'summarycontents', 'insertcopying', 'printindex', 'listoffloats',
+# not sure for settitle
+        'shorttitle', 'shorttitlepage', 'settitle', 'author', 'subtitle',
+        'title', keys(%default_index_commands)) {
+  $kept_misc_commands{$misc_command} = 1;
+}
+
+#my %ignored_misc_commands;
+foreach my $misc_command (keys(%misc_commands)) {
+#  $ignored_misc_commands{$misc_command} = 1 
+  $default_commands_conversion{$misc_command} = undef
+    unless ($formatting_misc_commands{$misc_command});
+}
+
+foreach my $ignored_brace_commands ('caption', 'shortcaption', 
+  'hyphenation') {
+  #$ignored_commands{$ignored_brace_commands} = 1;
+  $default_commands_conversion{$ignored_brace_commands} = undef;
+}
+
+# commands that leads to advancing the paragraph number.  This is mostly
+#used to determine the first line, in fact.
+my %advance_paragraph_count_commands;
+foreach my $command (keys(%block_commands)) {
+  next if ($menu_commands{$command} 
+            or $block_commands{$command} eq 'raw');
+  $advance_paragraph_count_commands{$command} = 1;
+}
+
+foreach my $ignored_block_commands ('ignore', 'macro', 'rmacro', 'copying',
+  'documentdescription', 'titlepage', 'direntry') {
+  #$ignored_commands{$ignored_block_commands} = 1;
+  $default_commands_conversion{$ignored_block_commands} = undef;
+};
+
+# Formatting of commands without args
+
+# The hask holding the defaults for the formatting of
+# most commands without args 
+my %default_commands_formatting;
+
+foreach my $command 
(keys(%{$Texinfo::Convert::Converter::default_xml_commands_formatting{'normal'}}))
 {
+  $default_commands_formatting{'normal'}->{$command} = 
+    
$Texinfo::Convert::Converter::default_xml_commands_formatting{'normal'}->{$command};
+}
+
+$default_commands_formatting{'normal'}->{' '} = '&nbsp;';
+$default_commands_formatting{'normal'}->{"\t"} = '&nbsp;';
+$default_commands_formatting{'normal'}->{"\n"} = '&nbsp;';
+
+foreach my $command (keys(%{$default_commands_formatting{'normal'}})) {
+  $default_commands_formatting{'preformatted'}->{$command} = 
+     $default_commands_formatting{'normal'}->{$command} 
+       unless exists($default_commands_formatting{'preformatted'}->{$command});
+  $default_commands_formatting{'string'}->{$command} =
+     $default_commands_formatting{'normal'}->{$command} 
+       unless exists($default_commands_formatting{'string'}->{$command});
+}
+
+$default_commands_formatting{'normal'}->{'enddots'} 
+    = '<small class="enddots">...</small>';
+$default_commands_formatting{'normal'}->{'*'} = '<br>';
+
+
+sub no_arg_commands($$$)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $command = shift;
+
+  if ($cmdname eq 'click' and $command->{'extra'} 
+      and exists($command->{'extra'}->{'clickstyle'})) {
+    $cmdname = $command->{'extra'}->{'clickstyle'};
+  }
+
+  my $result;
+  if ($self->in_preformatted() or $self->in_math()) {
+    $result = $self->{'commands_formatting'}->{'preformatted'}->{$cmdname};
+  } elsif ($self->in_string()) {
+    $result = $self->{'commands_formatting'}->{'string'}->{$cmdname};
+  } else {
+    $result = $self->{'commands_formatting'}->{'normal'}->{$cmdname};
+  }
+  return $result;
+}
+
+foreach my $command(keys(%{$default_commands_formatting{'normal'}})) {
+  $default_commands_conversion{$command} = \&no_arg_commands;
+}
+
+sub convert_today($$$)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $command = shift;
+
+  my $tree = $self->expand_today();
+  return $self->_convert($tree);
+}
+
+$default_commands_conversion{'today'} = \&convert_today;
+
+# style commands
+
+my %quoted_style_commands;
+foreach my $quoted_command ('file', 'option', 'samp') {
+  $quoted_style_commands{$quoted_command} = 1;
+}
+
+my %style_attribute_commands;
+$style_attribute_commands{'normal'} = {
+      'b'           => 'b',
+      'cite'        => 'cite',
+      'code'        => 'code',
+      'command'     => 'code',
+      'dfn'         => 'em',
+      'emph'        => 'em',
+      'env'         => 'code',
+      'file'        => 'tt',
+      'headitemfont' => 'b', # not really that, in fact it is 
+                             # in <th> rather than <td>
+      'i'           => 'i',
+      'slanted'     => 'i',
+      'sansserif'   => 'span class="sansserif"',
+      'kbd'         => 'kbd',
+      'option'      => 'samp',
+      'r'           => 'span class="roman"',
+      'samp'        => 'samp',
+      'sc'          => 'small',
+      'strong'      => 'strong',
+      't'           => 'tt',
+      'var'         => 'var',
+      'verb'        => 'tt',
+};
+
+foreach my $command (keys(%{$default_commands_formatting{'normal'}})) {
+  $style_attribute_commands{'preformatted'}->{$command} = 
+     $style_attribute_commands{'normal'}->{$command};
+}
+
+my %style_commands_formatting;
+foreach my $command(keys(%style_commands)) {
+  # default is no attribute.
+  if ($style_attribute_commands{'normal'}->{$command}) {
+    $style_commands_formatting{'normal'}->{$command}->{'attribute'}
+     = $style_attribute_commands{'normal'}->{$command};
+    $style_commands_formatting{'preformatted'}->{$command}->{'attribute'}
+     = $style_attribute_commands{'normal'}->{$command};
+  }
+  if ($style_attribute_commands{'preformatted'}->{$command}) {
+    $style_commands_formatting{'preformatted'}->{$command}->{'attribute'} =
+      $style_attribute_commands{'preformatted'}->{$command}; 
+  }
+  if ($quoted_style_commands{$command}) {
+    foreach my $context ('normal', 'string', 'preformatted') {
+      $style_commands_formatting{$context}->{$command}->{'quote'} = 1;
+    }
+  }
+  $default_commands_conversion{$command} = \&style_commands;
+}
+
+delete $style_commands_formatting{'preformatted'}->{'sc'}->{'attribute'};
+delete $style_commands_formatting{'preformatted'}->{'sc'};
+
+#      'email',      {'function' => \&html_default_email},
+#      'key',        {'begin' => '&lt;', 'end' => '&gt;'},
+#      'uref',       {'function' => \&html_default_uref},
+#      'url',        {'function' => \&html_default_uref},
+#      'math',       {'function' => \&html_default_math},
+#      'indicateurl', {'begin' => '&lt;<code>', 'end' => '</code>&gt;'},
+
+sub _parse_attribute($)
+{
+  my $element = shift;
+  return ('', '', '') if (!defined($element));
+  my ($class, $attributes) = ('', '');
+  if ($element =~ /^(\w+)(\s+.*)/)
+  {
+    $element = $1;
+    $attributes = $2;
+    if ($attributes =~ s/^\s+class=\"([^\"]+)\"//) {
+      $class = $1;
+    }
+  }
+  return ($element, $class, $attributes);
+}
+
+sub style_commands($$$$)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $command = shift;
+  my $args = shift;
+
+  my $text = $args->[0]->{'normal'};
+
+  my $attribute_hash = {};
+  if ($self->in_preformatted()) {
+    $attribute_hash = $self->{'style_commands_formatting'}->{'preformatted'};
+  } elsif (!$self->in_string()) {
+    $attribute_hash = $self->{'style_commands_formatting'}->{'normal'};
+  }
+  if (defined($attribute_hash->{$cmdname})) {
+    if (defined($attribute_hash->{$cmdname}->{'attribute'})) {
+      my ($style, $class, $attribute_text)
+        = parse_attribute ($attribute_hash->{$cmdname}->{'attribute'});
+      $text = attribute_class($style, $class) . "$attribute_text>" 
+              . "$text" . "</$style>";
+    }
+    if (defined($attribute_hash->{$cmdname}->{'quote'})) {
+      $text = $self->{'OPEN_QUOTE_SYMBOL'} . $text
+                . $self->{'CLOSE_QUOTE_SYMBOL'};
+    }
+  }
+  return $text;
+}
+
+sub accent_commands($$$$)
+{
+  my $self = shift;
+  my $cmdname = shift;
+  my $command = shift;
+  my $args = shift;
+
+  return $self->xml_accents($command);
+}
+
+foreach my $command (keys(%accent_commands)) {
+$default_commands_conversion{$command} = \&accent_commands;
+}
+
+my %default_types_conversion;
+
+#my %ignored_types;
+foreach my $type ('empty_line_after_command', 'preamble',
+            'empty_spaces_after_command', 'spaces_at_end',
+            'empty_spaces_before_argument', 'empty_spaces_before_paragraph',
+            'empty_spaces_after_close_brace') {
+  #$ignored_types{$type} = 1;
+  $default_types_conversion{$type} = undef;
+}
+
+my %paragraph_style = (
+      'center'     => 'center',
+      'flushleft'  => 'left',
+      'flushright' => 'right',
+      );
+
+sub paragraph_type($$$$)
+{
+  my $self = shift;
+  my $type = shift;
+  my $command = shift;
+  my $content = shift;
+
+  if ($self->paragraph_number() == 1) {
+    my $in_format = $self->in_format();
+    return $content 
+      if ($in_format eq 'itemize' 
+          or $in_format eq 'enumerate'
+          or $in_format eq 'multitable');
+  }
+  if ($self->align()) {
+    my $align = $self->align();
+    return "<p align=\"$paragraph_style{$align}\">".$content."</p>";
+  } else {
+    return "<p>".$content."</p>";
+  }
+}
+
+$default_types_conversion{'paragraph'} = \&paragraph_type;
+
+sub empty_line($$$) {
+  my $self = shift;
+  my $type = shift;
+  my $command = shift;
+
+  return "\n";
+}
+
+$default_types_conversion{'empty_line'} = \&empty_line;
+$default_types_conversion{'after_description_line'} = \&empty_line;
+
+sub process_text($$$)
+{
+  my $self = shift;
+  my $type = shift;
+  my $command = shift;
+  my $text = shift;
+
+  $text = uc($text) if ($self->in_upper_case());
+  $text = $self->xml_protect_text($text);
+  if ($self->{'ENABLE_ENCODING'} and !$self->{'ENABLE_ENCODING_USE_ENTITY'}
+      and $self->{'encoding_name'} and $self->{'encoding_name'} eq 'utf-8') {
+    my $context = {'code' => $self->in_code(), 
+                   'preformatted' => $self->in_preformatted()};
+    $text = Texinfo::Convert::Unicode::unicode_text($self, $text, $command,
+                                                         $context);
+  } elsif (!$self->in_code() and !$self->in_preformatted()) {
+    if ($self->{'USE_ISO'}) {
+      $text =~ s/---/\&mdash\;/g;
+      $text =~ s/--/\&ndash\;/g;
+      $text =~ s/``/\&ldquo\;/g;
+      $text =~ s/''/\&rdquo\;/g;
+      $text =~ s/'/\&rsquo\;/g;
+      $text =~ s/`/\&lsquo\;/g;
+    } else {
+      $text =~ s/``/&quot;/g;
+      $text =~ s/''/&quot;/g;
+      $text =~ s/---/\x{1F}/g;
+      $text =~ s/--/-/g;
+      $text =~ s/\x{1F}/--/g;
+    }
+  }
+  $text = $self->protect_space_codebreak($text);
+  return $text;
+}
+
+$default_types_conversion{'text'} = \&process_text;
+
+sub _initialize($)
+{
+  my $self = shift;
+  %{$self->{'css_map'}} = %css_map;
+
+  foreach my $context (keys(%default_commands_formatting)) {
+    foreach my $command (keys(%{$default_commands_formatting{$context}})) {
+      if (exists 
($Texinfo::Config::commands_formatting{$context}->{$command})) {
+        $self->{'commands_formatting'}->{$context}->{$command} 
+           = $Texinfo::Config::commands_formatting{$context}->{$command};
+      } else {
+        $self->{'commands_formatting'}->{$context}->{$command} 
+           = $default_commands_formatting{$context}->{$command};
+      }
+    }
+  }
+
+  foreach my $context (keys(%style_commands_formatting)) {
+    foreach my $command (keys(%{$style_commands_formatting{$context}})) {
+      if (exists 
($Texinfo::Config::style_commands_formatting{$context}->{$command})) {
+        $self->{'style_commands_formatting'}->{$context}->{$command} 
+           = $Texinfo::Config::style_commands_formatting{$context}->{$command};
+      } elsif (exists($style_commands_formatting{$context}->{$command})) {
+        $self->{'style_commands_formatting'}->{$context}->{$command} 
+           = $style_commands_formatting{$context}->{$command};
+      }
+    }
+  }
+
+  foreach my $command (keys(%misc_commands), keys(%brace_commands),
+     keys (%block_commands), keys(%no_brace_commands)) {
+    if (exists($Texinfo::Config::commands_conversion{$command})) {
+      $self->{'commands_conversion'}->{$command} 
+          = $Texinfo::Config::commands_conversion{$command};
+    } else {
+      $self->{'commands_conversion'}->{$command}
+         = $default_commands_conversion{$command};
+    }
+  }
+
+  foreach my $type (keys(%default_types_conversion)) {
+    if (exists($Texinfo::Config::types_conversion{$type})) {
+      $self->{'types_conversion'}->{$type}
+          = $Texinfo::Config::types_conversion{$type};
+    } else {
+      $self->{'types_conversion'}->{$type} 
+          = $default_types_conversion{$type};
+    }
+  }
+
+  return $self;
+}
+
+sub _convert_element($$)
+{
+  my $self = shift;
+  my $element = shift;
+
+  my $result = '';
+
+  print STDERR "NEW ELEMENT\n" if ($self->{'DEBUG'});
+
+  $result .= $self->_convert($element);
+
+  print STDERR "END ELEMENT\n" if ($self->{'DEBUG'});
+
+  #$result .= $self->_footnotes($element);
+
+  #print STDERR "AFTER FOOTNOTES\n" if ($self->{'DEBUG'});
+
+  return $result;
+}
+
+sub _normalized_to_id($)
+{
+  my $id = shift;
+  $id =~ s/^([0-9_])/g_t$1/;
+  return $id;
+}
+
+# TODO also convert to html, to use name in cross-refs
+sub _set_root_commands_id($$)
+{
+  my $self = shift;
+  my $elements = shift;
+
+  foreach my $element (@$elements) {
+    foreach my $root_command($element->{'contents'}) {
+      if ($root_command->{'cmdname'} eq 'node') {
+        my $target = 
_normalized_to_id($root_command->{'extra'}->{'normalzed'});
+        my $id = $target;
+        # FIXME something spcial for Top node ?
+        if (defined($Texinfo::Config::node_target_name)) {
+          ($target, $id) = &Texinfo::Config::node_target_name($root_command,
+                                                             $target, $id);
+        }
+        $self->{'targets'}->{$root_command} = {'target' => $target, 
+                                              'id' => $id};
+      } elsif ($Texinfo::Common::root_commands{$root_command->{'cmdname'}}) {
+        my $no_unidecode;
+        $no_unidecode = 1 if (defined($self->{'USE_UNIDECODE'})
+                              and !$self->{'USE_UNIDECODE'});
+        my $target_base = _normalized_to_id(
+           Texinfo::Convert::NodeNameNormalization::transliterate_texinfo(
+              {'contents' => $root_command->{'extra'}->{'misc_content'}},
+              $no_unidecode));
+        my $nr=0;
+        my $target = $target_base;
+        while ($self->{'labels'}->{$target}) {
+          $target = $target_base.'-'.$nr;
+          $nr++;
+          # Avoid integer overflow
+          die if ($nr == 0);
+        }
+        my $id = $target;
+        if ($root_command->{'associated_node'} and $self->{'USE_NODE_TARGET'}) 
{
+          $id = 
$self->{'targets'}->{$root_command->{'associated_node'}}->{'id'};
+        }
+        if (defined($Texinfo::Config::sectioning_command_target_name)) {
+          ($target, $id) = &Texinfo::Config::sectioning_command_target_name(
+                                                             $root_command,
+                                                             $target, $id);
+        }
+        $self->{'targets'}->{$root_command} = {'target' => $target, 
+                                              'id' => $id};
+      }
+    }
+  }
+}
+
+sub _prepare_elements($$)
+{
+  my $self = shift;
+  my $root = shift;
+
+  my $elements;
+  if ($self->{'USE_NODES'}) {
+    $elements = Texinfo::Structuring::split_by_node($root);
+  } else {
+    $elements = Texinfo::Structuring::split_by_section($root);
+  }
+  $self->_set_root_commands_id($elements) if ($elements);
+  return $elements;
+}
+
+sub page_head($$$)
+{
+  my $self = shift;
+  my $filename = shift;
+  my $page = shift;
+
+  # TODO
+  return '';
+}
+
+sub convert($$)
+{
+  my $self = shift;
+  my $root = shift;
+
+  my $result = '';
+
+  # This should return undef if called on a tree without node or sections.
+  my $elements = $self->_prepare_elements($root);
+
+  if (!defined($elements)) {
+    $result = $self->_convert($root);
+    #my $footnotes = $self->_footnotes();
+    #$result .= $footnotes;
+  } else {
+    foreach my $element (@$elements) {
+      my $element_text = $self->_convert_element($element);
+      $result .= $element_text;
+    }
+  }
+
+  return $result;
+}
+
+# output fo $fh if defined, otherwise return the text.
+sub _output_text($$)
+{
+  my $text = shift;
+  my $fh = shift;
+  if ($fh) {
+    print $fh $text;
+    return '';
+  } else {
+    return $text;
+  }
+}
+
+sub output($$)
+{
+  my $self = shift;
+  my $root = shift;
+
+  # no splitting when writing to the null device or to stdout or returning
+  # a string
+  if (defined($self->{'OUTFILE'})
+      and ($Texinfo::Common::null_device_file{$self->{'OUTFILE'}}
+           or $self->{'OUTFILE'} eq '-'
+           or $self->{'OUTFILE'} eq '')) {
+    $self->{'SPLIT'} = 0;
+  }
+  # This should return undef if called on a tree without node or sections.
+  my $elements = $self->_prepare_elements($root);
+
+  # undef if no elements or not split
+  my $pages = Texinfo::Structuring::split_pages($elements, $self->{'SPLIT'});
+  
+  # TODO handle special elements, footnotes element, contents and 
shortcontents
+  # elements, titlepage association
+
+  # this sets OUTFILE, to be used if not split, but also 'output_dir',
+  # and 'output_filename' that are useful when split.
+  $self->_set_outfile();
+
+  my $fh;
+  my $output = '';
+  if (!$pages) {
+    if ($self->{'OUTFILE'} ne '') {
+      $fh = $self->Texinfo::Common::open_out ($self->{'OUTFILE'},
+                                            $self->{'perl_encoding'});
+       if (!$fh) {
+         $self->document_error(sprintf($self->__("Could not open %s for 
writing: %s"),
+                                    $self->{'OUTFILE'}, $!));
+        return undef;
+      }
+      #$self->{'fh'} = $fh;
+      
+    }
+    my $header = page_head($self, $self->{'output_filename'}, undef);
+    $output .= _output_text($header, $fh);
+    if ($elements and @$elements) {
+      foreach my $element (@$elements) {
+        my $element_text = $self->_convert_element($element);
+        $output .= _output_text($element_text, $fh);
+      }
+    } else {
+      $output .= _output_text($self->_convert($root), $fh);
+    } 
+  } else {
+    my %files;
+    # TODO set page file names $page->{'filename'} (relative) and 
+    # $page->{'out_filename'} (absolute)
+    # also set $files{$page->{'filename'}}->{'counter'}
+    
+    foreach my $page (@$pages) {
+      my $file_fh;
+      if (!$files{$page->{'filename'}}->{'fh'}) {
+        $file_fh = $self->Texinfo::Common::open_out ($page->{'out_filename'},
+                                                      
$self->{'perl_encoding'});
+        if (!$file_fh) {
+         $self->document_error(sprintf($self->__("Could not open %s for 
writing: %s"),
+                                    $page->{'out_filename'}, $!));
+          # FIXME close/remove files already created
+          return undef;
+        }
+        #print $file_fh page_head(
+        print $file_fh "".page_head($self, $page->{'filename'}, $page);
+        $files{$page->{'filename'}}->{'fh'} = $file_fh;
+      } else {
+        $file_fh = $files{$page->{'filename'}}->{'fh'};
+      }
+      foreach my $element (@{$page->{'contents'}}) {
+        my $element_text = $self->_convert_element($element);
+        print $file_fh $element_text;
+      }
+      $files{$page->{'filename'}}->{'counter'}--;
+      if ($files{$page->{'filename'}}->{'counter'} == 0) {
+        # end file
+      }
+    }
+  }
+}
+
+sub attribute_class($$$)
+{
+  my $self = shift;
+  my $element = shift;
+  my $class = shift;
+
+  return "<$element" if (!defined($class) or $class eq '' or 
$self->{'NO_CSS'});
+
+  my $style = '';
+
+  if ($self->{'INLINE_CSS_STYLE'} 
+      and defined($self->{'css_map'}->{"$element.$class"})) {
+    $style = ' style="'.$self->{'css_map'}->{"$element.$class"}.'"';
+  }
+  return "<$element class=\"$class\"$style";
+}
+
+sub protect_space_codebreak($$)
+{
+  my $self = shift;
+  my $text = shift;
+
+  return $text if ($self->in_preformatted());
+
+  my $in_w = 1 if ($self->in_space_protected());
+
+  if ($in_w or $self->in_code() and $self->{'allowcodebreaks'} eq 'false') {
+    my $class = 'nolinebreak';
+    $class = 'nocodebreak' if ($self->in_code() 
+                               and $self->{'allowcodebreaks'} eq 'false');
+    my $open = $self->attribute_class('span', $class).'>';
+    # protect spaces in the html leading attribute in case we are in 'w'
+    $open =~ s/ /\x{1F}/g if ($in_w);
+    # special span to avoid breaking at _-
+    $text =~ s/(\S*[_-]\S*)/${open}$1<\/span>/g;
+  }
+  if ($in_w) {
+    $text .= '&nbsp;' if (chomp($text));
+    # protect spaces within text
+    $text =~ s/ /&nbsp;/g;
+    # revert protected spaces in leading html attribute
+    $text =~ s/\x{1F}/ /g;
+  }
+  return $text;
+}
+
+
+sub _definition_category($$$$)
+{
+  my $self = shift;
+  my $current = shift;
+  my $arg_category = shift;
+  my $arg_class = shift;
+  return $arg_category
+    if (!defined($arg_class));
+  
+  my $style = 
+    
$Texinfo::Common::command_index_prefix{$current->{'extra'}->{'def_command'}};
+  #my $category = Texinfo::Convert::Texinfo::convert($arg_category->[0]);
+  #my $class = Texinfo::Convert::Texinfo::convert($arg_class->[0]);
+  #print STDERR "DEFINITION CATEGORY($style): $category $class\n"
+  #  if ($self->{'DEBUG'});
+  if ($style eq 'f') {
+    #return Texinfo::Parser::parse_texi_line (undef, "$category on $class");
+    return $self->gdt('{category} on {class}', { 'category' => $arg_category, 
+                                          'class' => $arg_class });
+  } elsif ($style eq 'v') {
+    #return Texinfo::Parser::parse_texi_line (undef, "$category of $class");
+    return $self->gdt('{category} of {class}', { 'category' => $arg_category, 
+                                          'class' => $arg_class });
+  }
+  return $arg_category;
+}
+
+sub _contents($$$)
+{
+  my $self = shift;
+  my $section_root = shift;
+  my $contents_or_shortcontents = shift;
+
+  my $contents = 1 if ($contents_or_shortcontents eq 'contents');
+
+  #my $section = $section_root->{'section_childs'}->[0];
+  my $root_level = $section_root->{'section_childs'}->[0]->{'level'};
+  foreach my $top_section(@{$section_root->{'section_childs'}}) {
+    $root_level = $top_section->{'level'} 
+      if ($top_section->{'level'} < $root_level);
+  }
+
+  my $result = '';
+  # This is done like that because the tree may not be well formed if
+  # there is a @part after a @chapter for example.
+  foreach my $top_section (@{$section_root->{'section_childs'}}) {
+    my $section = $top_section;
+ SECTION:
+    while ($section) {
+      my $section_title = $self->_convert({'contents'
+                => $section->{'extra'}->{'misc_content'},
+               'type' => 'frenchspacing'});
+      
+      my $text = numbered_heading($section, 
+                            $section_title, $self->{'NUMBER_SECTIONS'})."\n";
+      # FIXME get ref.
+      # FIXME do li
+      $result .= (' ' x (2*($section->{'level'} - ($root_level+1)))) . $text;
+      if ($section->{'section_childs'} 
+          and ($contents or $section->{'level'} < $root_level+1)) {
+        # FIXME do ul
+        $section = $section->{'section_childs'}->[0];
+      } elsif ($section->{'section_next'}) {
+        last if ($section eq $top_section);
+        $section = $section->{'section_next'};
+      } else {
+        last if ($section eq $top_section);
+        while ($section->{'section_up'}) {
+          # FIXME close ul
+          $section = $section->{'section_up'};
+          last SECTION if ($section eq $top_section);
+          if ($section->{'section_next'}) {
+            $section = $section->{'section_next'};
+            last;
+          }
+        }
+      }
+    }
+  }
+  return $result;
+}
+
+sub _menu($$)
+{
+  my $self = shift;
+  my $menu_command = shift;
+
+  if ($menu_command->{'cmdname'} eq 'menu') {
+    my $result = "* Menu:\n\n";
+    $self->_add_text_count($result);
+    $self->_add_lines_count(2);
+    return $result;
+  } else {
+    return '';
+  }
+}
+
+sub _printindex($$)
+{
+  my $self = shift;
+  my $printindex = shift;
+  return ('');
+}
+
+sub _node($$)
+{
+  my $self = shift;
+  my $node = shift;
+
+  return '';
+}
+
+# no error in plaintext
+sub _error_outside_of_any_node($$)
+{
+  my $self = shift;
+  my $root = shift;
+}
+
+sub _anchor($$)
+{
+  my $self = shift;
+  my $anchor = shift;
+
+  if (!($self->{'multiple_pass'} or $self->{'in_copying_header'})) {
+    $self->_add_location($anchor); 
+    $self->_error_outside_of_any_node($anchor);
+  }
+  return '';
+}
+
+sub _image($$)
+{
+  my $self = shift;
+  my $root = shift;
+
+  if (defined($root->{'extra'}->{'brace_command_contents'}->[0])) {
+    my $basefile = Texinfo::Convert::Text::convert(
+     {'contents' => $root->{'extra'}->{'brace_command_contents'}->[0]});
+    my $result = $self->_image_text($root, $basefile);
+    if (defined($result)) {
+      if (!$self->{'formatters'}->[-1]->{'_top_formatter'}) {
+        $result = '['.$result.']';
+      }
+      my $lines_count = ($result =~ tr/\n/\n/);
+      return ($result, $lines_count);
+    }
+  }
+  return ('', 0);
+}
+
+# on top, the converter object which holds some global information
+# 
+# context (for footnotes, multitable cells):
+# 'preformatted'
+# 'max'
+#
+# format_context
+# indentation + count for prepending text
+# also paragraph count and maybe empty line count
+#
+# containers on their own stack
+# in container
+# 'upper_case'
+# 'code'
+# 
+# paragraph number: incremented with block commands except html and such
+# and group and raggedright and menu*
+# and also center and listoffloats
+# and with paragraphs. 
+
+# preformatted
+
+sub _convert($$);
+
+sub _convert($$)
+{
+  my $self = shift;
+  my $root = shift;
+
+  if ($self->{'DEBUG'}) {
+    print STDERR "ROOT:$root (".join('|',@{$self->{'context'}})."), ->";
+    print STDERR " cmd: $root->{'cmdname'}," if ($root->{'cmdname'});
+    print STDERR " type: $root->{'type'}" if ($root->{'type'});
+    my $text = $root->{'text'}; 
+    if (defined($text)) {
+      $text =~ s/\n/\\n/;
+      print STDERR " text: $text";
+    }
+    print STDERR "\n";
+   
+    #print STDERR "  Special def_command: $root->{'extra'}->{'def_command'}\n"
+    #  if (defined($root->{'extra'}) and $root->{'extra'}->{'def_command'});
+  }
+
+  if (($root->{'type'}
+        and exists ($self->{'types_conversion'}->{$root->{'type'}})
+        and !defined($self->{'types_conversion'}->{$root->{'type'}}))
+       or ($root->{'cmdname'}
+            and exists($self->{'commands_conversion'}->{$root->{'cmdname'}})
+            and 
!defined($self->{'commands_conversion'}->{$root->{'cmdname'}}))) {
+    print STDERR "IGNORED\n" if ($self->{'DEBUG'});
+    return '';
+  }
+
+  # process text
+  if (defined($root->{'text'})) {
+    return &{$self->{'types_conversion'}->{'text'}} ($self, 
+                                                      $root->{'type'},
+                                                      $root,
+                                                      $root->{'text'});
+  }
+
+  if ($root->{'extra'}) {
+    if ($root->{'extra'}->{'invalid_nesting'}) {
+      print STDERR "INVALID_NESTING\n" if ($self->{'DEBUG'});
+      return '';
+    } elsif ($root->{'extra'}->{'missing_argument'} 
+             and (!$root->{'contents'} or address@hidden>{'contents'}})) {
+      print STDERR "MISSING_ARGUMENT\n" if ($self->{'DEBUG'});
+      return '';
+    }
+  }
+
+  # FIXME here process only real index entries
+  if ($root->{'extra'} and $root->{'extra'}->{'index_entry'}) {
+      #and !$self->{'multiple_pass'} and !$self->{'in_copying_header'}) {
+    # special case for index entry not associated with a node but seen. 
+    # this will be an index entry in @copying, in @insertcopying.
+#    if (!$root->{'extra'}->{'index_entry'}->{'node'} and $self->{'node'}) {
+#      $location->{'node'} = $self->{'node'};
+#    }
+#    $self->{'index_entries_line_location'}->{$root} = $location;
+#    print STDERR "INDEX ENTRY lines_count $location->{'lines'}, index_entry 
$location->{'index_entry'}\n" 
+#       if ($self->{'DEBUG'});
+  }
+
+
+  # TODO special: center, footnote, menu?
+  my $cell;
+  my $preformatted;
+  if ($root->{'cmdname'}) {
+    # TODO if w -> set protext_space
+    #      if code_style -> set it
+    #    if ($code_style_commands{$command});
+    #      if sc -> also in_upper_case
+    #      align command
+    #      preformatted
+    # FIXME definfoenclose_command 
+    # ($root->{'type'} and $root->{'type'} eq 'definfoenclose_command'))
+    if (exists($self->{'commands_conversion'}->{$root->{'cmdname'}})) {
+      my $content_formatted;
+      if ($root->{'contents'}) {
+        $content_formatted = '';
+        # TODO different types of contents
+        foreach my $content (@{$root->{'contents'}}) {
+          $content_formatted .= $self->_convert($content);
+        }
+      }
+      my $args_formatted;
+      if ($brace_commands{$root->{'cmdname'}} 
+          or ($misc_commands{$root->{'cmdname'}} 
+              and $misc_commands{$root->{'cmdname'}} eq 'line')
+          or ($root->{'cmdname'} eq 'quotation' 
+              or $root->{'cmdname'} eq 'smallquotation')
+              or ($root->{'cmdname'} eq 'float')) {
+        $args_formatted = [];
+        if ($root->{'args'}) {
+          foreach my $arg (@{$root->{'args'}}) {
+            push @$args_formatted, {'normal' => $self->_convert($arg)};
+          }
+        }
+        return &{$self->{'commands_conversion'}->{$root->{'cmdname'}}}($self,
+                $root->{'cmdname'}, $root, $args_formatted, 
$content_formatted);
+      } else {
+        return &{$self->{'commands_conversion'}->{$root->{'cmdname'}}}($self,
+                $root->{'cmdname'}, $root, $content_formatted);
+      }
+    } else {
+      print STDERR "BUG: unknown command $root->{'cmdname'}\n";
+    }
+  } elsif ($root->{'type'}) {
+    my $content_formatted;
+    if ($root->{'contents'}) {
+      $content_formatted = '';
+      # TODO different types of contents
+      foreach my $content (@{$root->{'contents'}}) {
+        $content_formatted .= $self->_convert($content);
+      }
+    }
+    if (exists($self->{'types_conversion'}->{$root->{'type'}})) {
+      return &{$self->{'types_conversion'}->{$root->{'type'}}} ($self,
+                                                 $root->{'type'},
+                                                 $root,
+                                                 $content_formatted);
+    } elsif (defined($content_formatted)) {
+      return $content_formatted;
+    }
+  }
+    #} elsif ($command eq 'value') {
+    #  my $expansion = $self->gdt('@{No value for `{value}\'@}', 
+    #                                {'value' => $root->{'type'}});
+    #  if ($formatter->{'_top_formatter'}) {
+    #    $expansion = {'type' => 'paragraph',
+    #                  'contents' => [$expansion]};
+    #  }
+    #  $result .= $self->_convert($expansion);
+      #  unshift @{$self->{'current_contents'}->[-1]}, $expansion;
+   #   #return '';
+   #   return $result;
+#    } elsif ($root->{'cmdname'} eq 'center') {
+#      #my ($counts, $new_locations);
+ #   } elsif ($root->{'cmdname'} eq 'verbatiminclude') {
+ #     my $expansion = $self->Texinfo::Parser::expand_verbatiminclude($root);
+ #     unshift @{$self->{'current_contents'}->[-1]}, $expansion
+ #       if ($expansion);
+ #     return '';
+#    } elsif ($root->{'cmdname'} eq 'insertcopying') {
+#      if ($self->{'extra'} and $self->{'extra'}->{'copying'}) {
+#        unshift @{$self->{'current_contents'}->[-1]}, 
+#           {'contents' => $self->{'extra'}->{'copying'}->{'contents'}};
+#      }
+#      return '';
+#    } elsif ($root->{'cmdname'} eq 'printindex') {
+#      $result = $self->_printindex($root);
+#      return $result;
+#    } elsif ($root->{'cmdname'} eq 'listoffloats') {
+#    } elsif ($root->{'cmdname'} eq 'sp') {
+#    } elsif ($root->{'cmdname'} eq 'contents') {
+#    } elsif ($root->{'cmdname'} eq 'shortcontents' 
+#               or $root->{'cmdname'} eq 'summarycontents') {
+#    } elsif ($informative_commands{$root->{'cmdname'}}) {
+#      $self->_informative_command($root);
+
+# TODO types
+#    } elsif ($root->{'type'} eq 'preformatted') {
+#    } elsif ($root->{'type'} eq 'def_line') {
+#    } elsif ($root->{'type'} eq 'menu_entry') {
+#    } elsif ($root->{'type'} eq 'code') {
+ # TODO ?
+ #   } elsif ($root->{'type'} eq 'bracketed') {
+
+ #   } elsif ($root->{'cmdname'} eq 'quotation' and $root->{'extra'} 
+ #            and $root->{'extra'}->{'authors'}) {
+ #     foreach my $author (@{$root->{'extra'}->{'authors'}}) {
+ #       $result .= $self->_convert(
+ #                $self->gdt("address@hidden --- address@hidden",
+ #                   {'author' => $author->{'extra'}->{'misc_content'}}));
+ #     }
+ #   }
+  print STDERR "DEBUG: HERE!\n";
+  #return $result;
+}
+
+1;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]