[Zope-Checkins] SVN: Zope/trunk/ Fixed 1349: HEAD doesn't have rest-header-level

Christian 'Tiran' Heimes heimes at faho.rwth-aachen.de
Mon Jul 26 13:36:59 EDT 2004


Log message for revision 26767:
  Fixed 1349:  HEAD doesn't have rest-header-level
  Updated docutils including a fix for 1426:  System locale breaks reStructuredText horribly
  Added rest-language-code to zope.conf schema. it's used instead of the locales


Changed:
  U   Zope/trunk/lib/python/App/config.py
  U   Zope/trunk/lib/python/Interface/pprint.py
  U   Zope/trunk/lib/python/Zope/Startup/handlers.py
  U   Zope/trunk/lib/python/Zope/Startup/zopeschema.xml
  U   Zope/trunk/lib/python/docutils/__init__.py
  U   Zope/trunk/lib/python/docutils/core.py
  U   Zope/trunk/lib/python/docutils/frontend.py
  U   Zope/trunk/lib/python/docutils/io.py
  U   Zope/trunk/lib/python/docutils/languages/__init__.py
  U   Zope/trunk/lib/python/docutils/languages/pt_br.py
  U   Zope/trunk/lib/python/docutils/nodes.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/__init__.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py
  A   Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/roles.py
  U   Zope/trunk/lib/python/docutils/parsers/rst/states.py
  U   Zope/trunk/lib/python/docutils/readers/pep.py
  U   Zope/trunk/lib/python/docutils/readers/python/__init__.py
  U   Zope/trunk/lib/python/docutils/readers/python/moduleparser.py
  U   Zope/trunk/lib/python/docutils/readers/python/pynodes.py
  U   Zope/trunk/lib/python/docutils/statemachine.py
  U   Zope/trunk/lib/python/docutils/transforms/peps.py
  U   Zope/trunk/lib/python/docutils/utils.py
  U   Zope/trunk/lib/python/docutils/writers/__init__.py
  U   Zope/trunk/lib/python/docutils/writers/docutils_xml.py
  U   Zope/trunk/lib/python/docutils/writers/html4css1.py
  U   Zope/trunk/lib/python/docutils/writers/latex2e.py
  U   Zope/trunk/lib/python/reStructuredText/__init__.py
  U   Zope/trunk/lib/python/reStructuredText/reStructuredText.txt
  U   Zope/trunk/skel/etc/zope.conf.in


-=-
Modified: Zope/trunk/lib/python/App/config.py
===================================================================
--- Zope/trunk/lib/python/App/config.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/App/config.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -93,3 +93,4 @@
         self.rest_input_encoding = default_enc
         self.rest_output_encoding = default_enc
         self.rest_header_level = 3
+        self.rest_language_code = 'en'

Modified: Zope/trunk/lib/python/Interface/pprint.py
===================================================================
--- Zope/trunk/lib/python/Interface/pprint.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/Interface/pprint.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -19,7 +19,7 @@
                 min_indent=indent
         for line in lines[1:]:
             nlines.append(line[min_indent:])
-    return '\n'.join(nlines, '\n')
+    return '\n'.join(nlines)
 
 
 

Modified: Zope/trunk/lib/python/Zope/Startup/handlers.py
===================================================================
--- Zope/trunk/lib/python/Zope/Startup/handlers.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/Zope/Startup/handlers.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -83,6 +83,14 @@
     value and _setenv('REST_OUTPUT_ENCODING' , value)
     return value
 
+def rest_header_level(value):
+    value and _setenv('REST_DEFAULT_LEVEL' , value)
+    return value
+
+def rest_language_code(value):
+    value and _setenv('REST_LANGUAGE_CODE' , value)
+    return value
+
 # server handlers
 
 def root_handler(config):

Modified: Zope/trunk/lib/python/Zope/Startup/zopeschema.xml
===================================================================
--- Zope/trunk/lib/python/Zope/Startup/zopeschema.xml	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/Zope/Startup/zopeschema.xml	2004-07-26 17:36:58 UTC (rev 26767)
@@ -482,6 +482,25 @@
     <metadefault>unset</metadefault>
   </key>
 
+  <key name="rest-header-level" datatype="integer" default="3"
+       handler="rest_header_level">
+    <description>
+     Set the default starting HTML header level for restructured text
+     documents. The default is 3, which implies that top-level headers
+     will be created with an H3 HTML tag.
+    </description>
+    <metadefault>3</metadefault>
+  </key>
+
+  <key name="rest-language-code" handler="rest_language_code" default="en">
+    <description>
+     Language code used for some internal translations inside of the docutils
+     package and for DTD bibliographic elements mapping. See
+     lib/python/docutils/languages/ for a list of supported language codes.
+    </description>
+    <metadefault>en</metadefault>
+  </key>
+
   <key name="publisher-profile-file">
     <description>
      Causing this directive to point to a file on the filesystem will

Modified: Zope/trunk/lib/python/docutils/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/__init__.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/__init__.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -52,13 +52,11 @@
 __docformat__ = 'reStructuredText'
 
 __version__ = '0.3.4'
-"""``major.minor.micro`` version number.  The micro number is bumped
-any time there's a change in the API incompatible with one of the
-front ends or significant new functionality, and at any alpha or beta
-release.  The minor number is bumped whenever there is a stable
-project release.  The major number will be bumped when the project is
-feature-complete, and perhaps if there is a major change in the
-design."""
+"""``major.minor.micro`` version number.  The micro number is bumped for API
+changes, for new functionality, and for interim project releases.  The minor
+number is bumped whenever there is a significant project release.  The major
+number will be bumped when the project is feature-complete, and perhaps if
+there is a major change in the design."""
 
 
 class ApplicationError(StandardError): pass
@@ -76,22 +74,36 @@
     settings_spec = ()
     """Runtime settings specification.  Override in subclasses.
 
-    Specifies runtime settings and associated command-line options, as used by
-    `docutils.frontend.OptionParser`.  This tuple contains one or more sets of
-    option group title, description, and a list/tuple of tuples: ``('help
-    text', [list of option strings], {keyword arguments})``.  Group title
-    and/or description may be `None`; a group title of `None` implies no
-    group, just a list of single options.  The "keyword arguments" dictionary
-    contains arguments to the OptionParser/OptionGroup ``add_option`` method,
-    with the addition of a "validator" keyword (see the
-    `docutils.frontend.OptionParser.validators` instance attribute).  Runtime
-    settings names are derived implicitly from long option names
-    ("--a-setting" becomes ``settings.a_setting``) or explicitly from the
-    "dest" keyword argument."""
+    Defines runtime settings and associated command-line options, as used by
+    `docutils.frontend.OptionParser`.  This is a tuple of:
 
+    - Option group title (string or `None` which implies no group, just a list
+      of single options).
+    
+    - Description (string or `None`).
+    
+    - A sequence of option tuples.  Each consists of:
+
+      - Help text (string)
+      
+      - List of option strings (e.g. ``['-Q', '--quux']``).
+      
+      - Dictionary of keyword arguments.  It contains arguments to the
+        OptionParser/OptionGroup ``add_option`` method, possibly with the
+        addition of a 'validator' keyword (see the
+        `docutils.frontend.OptionParser.validators` instance attribute).  Runtime
+        settings names are derived implicitly from long option names
+        ('--a-setting' becomes ``settings.a_setting``) or explicitly from the
+        'dest' keyword argument.  See optparse docs for more details.
+
+    - More triples of group title, description, options, as many times as
+      needed.  Thus, `settings_spec` tuples can be simply concatenated.
+    """
+
     settings_defaults = None
-    """A dictionary of defaults for internal or inaccessible (by command-line
-    or config file) settings.  Override in subclasses."""
+    """A dictionary of defaults for settings not in `settings_spec` (internal
+    settings, intended to be inaccessible by command-line and config file).
+    Override in subclasses."""
 
     settings_default_overrides = None
     """A dictionary of auxiliary defaults, to override defaults for settings
@@ -126,14 +138,21 @@
     """Transforms required by this class.  Override in subclasses."""
     
     unknown_reference_resolvers = ()
-    """List of functions to try to resolve unknown references.  Called when
-    FinalCheckVisitor is unable to find a correct target.  The list should
-    contain functions which will try to resolve unknown references, with the
-    following signature::
+    """List of functions to try to resolve unknown references.  Unknown
+    references have a 'refname' attribute which doesn't correspond to any
+    target in the document.  Called when FinalCheckVisitor is unable to find a
+    correct target.  The list should contain functions which will try to
+    resolve unknown references, with the following signature::
 
         def reference_resolver(node):
             '''Returns boolean: true if resolved, false if not.'''
 
+    If the function is able to resolve the reference, it should also remove
+    the 'refname' attribute and mark the node as resolved::
+
+        del node['refname']
+        node.resolved = 1
+
     Each function must have a "priority" attribute which will affect the order
     the unknown_reference_resolvers are run::
 

Modified: Zope/trunk/lib/python/docutils/core.py
===================================================================
--- Zope/trunk/lib/python/docutils/core.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/core.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -9,14 +9,17 @@
 `Publisher` object) with component names will result in default
 behavior.  For custom behavior (setting component options), create
 custom component objects first, and pass *them* to
-``publish_*``/`Publisher`.
+``publish_*``/`Publisher`.  See `The Docutils Publisher`_.
+
+.. _The Docutils Publisher: http://docutils.sf.net/docs/api/publisher.html
 """
 
 __docformat__ = 'reStructuredText'
 
 import sys
-from docutils import __version__, Component, SettingsSpec
-from docutils import frontend, io, utils, readers, parsers, writers
+import pprint
+from docutils import __version__, SettingsSpec
+from docutils import frontend, io, utils, readers, writers
 from docutils.frontend import OptionParser
 
 
@@ -37,22 +40,23 @@
         """
 
         self.reader = reader
-        """A `readers.Reader` instance."""
+        """A `docutils.readers.Reader` instance."""
 
         self.parser = parser
-        """A `parsers.Parser` instance."""
+        """A `docutils.parsers.Parser` instance."""
 
         self.writer = writer
-        """A `writers.Writer` instance."""
+        """A `docutils.writers.Writer` instance."""
 
         self.source = source
-        """The source of input data, an `io.Input` instance."""
+        """The source of input data, a `docutils.io.Input` instance."""
 
         self.source_class = source_class
         """The class for dynamically created source objects."""
 
         self.destination = destination
-        """The destination for docutils output, an `io.Output` instance."""
+        """The destination for docutils output, a `docutils.io.Output`
+        instance."""
 
         self.destination_class = destination_class
         """The class for dynamically created destination objects."""
@@ -85,8 +89,9 @@
     def setup_option_parser(self, usage=None, description=None,
                             settings_spec=None, config_section=None,
                             **defaults):
-        if config_section and not settings_spec:
-            settings_spec = SettingsSpec()
+        if config_section:
+            if not settings_spec:
+                settings_spec = SettingsSpec()
             settings_spec.config_section = config_section
             parts = config_section.split()
             if len(parts) > 1 and parts[-1] == 'application':
@@ -112,6 +117,17 @@
         self.settings = option_parser.get_default_values()
         return self.settings
 
+    def process_programmatic_settings(self, settings_spec,
+                                      settings_overrides,
+                                      config_section):
+        if self.settings is None:
+            defaults = (settings_overrides or {}).copy()
+            # Propagate exceptions by default when used programmatically:
+            defaults.setdefault('traceback', 1)
+            self.get_settings(settings_spec=settings_spec,
+                              config_section=config_section,
+                              **defaults)
+
     def process_command_line(self, argv=None, usage=None, description=None,
                              settings_spec=None, config_section=None,
                              **defaults):
@@ -122,7 +138,7 @@
         Set components first (`self.set_reader` & `self.set_writer`).
         """
         option_parser = self.setup_option_parser(
-            usage, description, settings_spec, config_section,**defaults)
+            usage, description, settings_spec, config_section, **defaults)
         if argv is None:
             argv = sys.argv[1:]
         self.settings = option_parser.parse_args(argv)
@@ -160,7 +176,7 @@
 
     def publish(self, argv=None, usage=None, description=None,
                 settings_spec=None, settings_overrides=None,
-                config_section=None, enable_exit=None):
+                config_section=None, enable_exit_status=None):
         """
         Process command line options and arguments (if `self.settings` not
         already set), run `self.reader` and then `self.writer`.  Return
@@ -170,8 +186,6 @@
             self.process_command_line(
                 argv, usage, description, settings_spec, config_section,
                 **(settings_overrides or {}))
-        elif settings_overrides:
-            self.settings._update(settings_overrides, 'loose')
         self.set_io()
         exit = None
         document = None
@@ -181,48 +195,89 @@
             self.apply_transforms(document)
             output = self.writer.write(document, self.destination)
             self.writer.assemble_parts()
-        except utils.SystemMessage, error:
-            if self.settings.traceback:
-                raise
-            print >>sys.stderr, ('Exiting due to level-%s (%s) system message.'
-                                 % (error.level,
-                                    utils.Reporter.levels[error.level]))
-            exit = 1
         except Exception, error:
-            if self.settings.traceback:
+            if self.settings.traceback: # propagate exceptions?
                 raise
-            print >>sys.stderr, error
-            print >>sys.stderr, ("""\
-Exiting due to error.  Use "--traceback" to diagnose.
-Please report errors to <docutils-users at lists.sf.net>.
-Include "--traceback" output, Docutils version (%s),
-Python version (%s), your OS type & version, and the
-command line used.""" % (__version__, sys.version.split()[0]))
+            self.report_Exception(error)
             exit = 1
+        self.debugging_dumps(document)
+        if (enable_exit_status and document
+            and (document.reporter.max_level
+                 >= self.settings.exit_status_level)):
+            sys.exit(document.reporter.max_level + 10)
+        elif exit:
+            sys.exit(1)
+        return output
+
+    def debugging_dumps(self, document):
         if self.settings.dump_settings:
-            from pprint import pformat
             print >>sys.stderr, '\n::: Runtime settings:'
-            print >>sys.stderr, pformat(self.settings.__dict__)
+            print >>sys.stderr, pprint.pformat(self.settings.__dict__)
         if self.settings.dump_internals and document:
-            from pprint import pformat
             print >>sys.stderr, '\n::: Document internals:'
-            print >>sys.stderr, pformat(document.__dict__)
+            print >>sys.stderr, pprint.pformat(document.__dict__)
         if self.settings.dump_transforms and document:
-            from pprint import pformat
             print >>sys.stderr, '\n::: Transforms applied:'
-            print >>sys.stderr, pformat(document.transformer.applied)
+            print >>sys.stderr, pprint.pformat(document.transformer.applied)
         if self.settings.dump_pseudo_xml and document:
             print >>sys.stderr, '\n::: Pseudo-XML:'
             print >>sys.stderr, document.pformat().encode(
                 'raw_unicode_escape')
-        if enable_exit and document and (document.reporter.max_level
-                                         >= self.settings.exit_level):
-            sys.exit(document.reporter.max_level + 10)
-        elif exit:
-            sys.exit(1)
-        return output
 
+    def report_Exception(self, error):
+        if isinstance(error, utils.SystemMessage):
+            self.report_SystemMessage(error)
+        elif isinstance(error, UnicodeError):
+            self.report_UnicodeError(error)
+        else:
+            print >>sys.stderr, '%s: %s' % (error.__class__.__name__, error)
+            print >>sys.stderr, ("""\
+Exiting due to error.  Use "--traceback" to diagnose.
+Please report errors to <docutils-users at lists.sf.net>.
+Include "--traceback" output, Docutils version (%s),
+Python version (%s), your OS type & version, and the
+command line used.""" % (__version__, sys.version.split()[0]))
 
+    def report_SystemMessage(self, error):
+        print >>sys.stderr, ('Exiting due to level-%s (%s) system message.'
+                             % (error.level,
+                                utils.Reporter.levels[error.level]))
+
+    def report_UnicodeError(self, error):
+        sys.stderr.write(
+            '%s: %s\n'
+            '\n'
+            'The specified output encoding (%s) cannot\n'
+            'handle all of the output.\n'
+            'Try setting "--output-encoding-error-handler" to\n'
+            '\n'
+            '* "xmlcharrefreplace" (for HTML & XML output);\n'
+            % (error.__class__.__name__, error,
+               self.settings.output_encoding))
+        try:
+            data = error.object[error.start:error.end]
+            sys.stderr.write(
+                '  the output will contain "%s" and should be usable.\n'
+                '* "backslashreplace" (for other output formats, Python 2.3+);\n'
+                '  look for "%s" in the output.\n'
+                % (data.encode('ascii', 'xmlcharrefreplace'),
+                   data.encode('ascii', 'backslashreplace')))
+        except AttributeError:
+            sys.stderr.write('  the output should be usable as-is.\n')
+        sys.stderr.write(
+            '* "replace"; look for "?" in the output.\n'
+            '\n'
+            '"--output-encoding-error-handler" is currently set to "%s".\n'
+            '\n'
+            'Exiting due to error.  Use "--traceback" to diagnose.\n'
+            'If the advice above doesn\'t eliminate the error,\n'
+            'please report it to <docutils-users at lists.sf.net>.\n'
+            'Include "--traceback" output, Docutils version (%s),\n'
+            'Python version (%s), your OS type & version, and the\n'
+            'command line used.\n'
+            % (self.settings.output_encoding_error_handler,
+               __version__, sys.version.split()[0]))
+
 default_usage = '%prog [options] [<source> [<destination>]]'
 default_description = ('Reads from <source> (default is stdin) and writes to '
                        '<destination> (default is stdout).')
@@ -232,30 +287,15 @@
                     writer=None, writer_name='pseudoxml',
                     settings=None, settings_spec=None,
                     settings_overrides=None, config_section=None,
-                    enable_exit=1, argv=None,
+                    enable_exit_status=1, argv=None,
                     usage=default_usage, description=default_description):
     """
-    Set up & run a `Publisher`.  For command-line front ends.
+    Set up & run a `Publisher` for command-line-based file I/O (input and
+    output file paths taken automatically from the command line).  Return the
+    encoded string output also.
 
-    Parameters:
+    Parameters: see `publish_programmatically` for the remainder.
 
-    - `reader`: A `docutils.readers.Reader` object.
-    - `reader_name`: Name or alias of the Reader class to be instantiated if
-      no `reader` supplied.
-    - `parser`: A `docutils.parsers.Parser` object.
-    - `parser_name`: Name or alias of the Parser class to be instantiated if
-      no `parser` supplied.
-    - `writer`: A `docutils.writers.Writer` object.
-    - `writer_name`: Name or alias of the Writer class to be instantiated if
-      no `writer` supplied.
-    - `settings`: Runtime settings object.
-    - `settings_spec`: Extra settings specification; a `docutils.SettingsSpec`
-      subclass.  Used only if no `settings` specified.
-    - `settings_overrides`: A dictionary containing program-specific overrides
-      of component settings.
-    - `config_section`: Name of configuration file section for application.
-      Used only if no `settings` or `settings_spec` specified.
-    - `enable_exit`: Boolean; enable exit status at end of processing?
     - `argv`: Command-line argument list to use instead of ``sys.argv[1:]``.
     - `usage`: Usage string, output if there's a problem parsing the command
       line.
@@ -264,8 +304,10 @@
     """
     pub = Publisher(reader, parser, writer, settings=settings)
     pub.set_components(reader_name, parser_name, writer_name)
-    pub.publish(argv, usage, description, settings_spec, settings_overrides,
-                config_section=config_section, enable_exit=enable_exit)
+    output = pub.publish(
+        argv, usage, description, settings_spec, settings_overrides,
+        config_section=config_section, enable_exit_status=enable_exit_status)
+    return output
 
 def publish_file(source=None, source_path=None,
                  destination=None, destination_path=None,
@@ -273,63 +315,40 @@
                  parser=None, parser_name='restructuredtext',
                  writer=None, writer_name='pseudoxml',
                  settings=None, settings_spec=None, settings_overrides=None,
-                 config_section=None, enable_exit=None):
+                 config_section=None, enable_exit_status=None):
     """
-    Set up & run a `Publisher`.  For programmatic use with file-like I/O.
+    Set up & run a `Publisher` for programmatic use with file-like I/O.
+    Return the encoded string output also.
 
-    Parameters:
-
-    - `source`: A file-like object (must have "read" and "close" methods).
-    - `source_path`: Path to the input file.  Opened if no `source` supplied.
-      If neither `source` nor `source_path` are supplied, `sys.stdin` is used.
-    - `destination`: A file-like object (must have "write" and "close"
-      methods).
-    - `destination_path`: Path to the input file.  Opened if no `destination`
-      supplied.  If neither `destination` nor `destination_path` are supplied,
-      `sys.stdout` is used.
-    - `reader`: A `docutils.readers.Reader` object.
-    - `reader_name`: Name or alias of the Reader class to be instantiated if
-      no `reader` supplied.
-    - `parser`: A `docutils.parsers.Parser` object.
-    - `parser_name`: Name or alias of the Parser class to be instantiated if
-      no `parser` supplied.
-    - `writer`: A `docutils.writers.Writer` object.
-    - `writer_name`: Name or alias of the Writer class to be instantiated if
-      no `writer` supplied.
-    - `settings`: Runtime settings object.
-    - `settings_spec`: Extra settings specification; a `docutils.SettingsSpec`
-      subclass.  Used only if no `settings` specified.
-    - `settings_overrides`: A dictionary containing program-specific overrides
-      of component settings.
-    - `config_section`: Name of configuration file section for application.
-      Used only if no `settings` or `settings_spec` specified.
-    - `enable_exit`: Boolean; enable exit status at end of processing?
+    Parameters: see `publish_programmatically`.
     """
-    pub = Publisher(reader, parser, writer, settings=settings)
-    pub.set_components(reader_name, parser_name, writer_name)
-    if settings is None:
-        settings = pub.get_settings(settings_spec=settings_spec,
-                                    config_section=config_section)
-    if settings_overrides:
-        settings._update(settings_overrides, 'loose')
-    pub.set_source(source, source_path)
-    pub.set_destination(destination, destination_path)
-    pub.publish(enable_exit=enable_exit)
+    output, pub = publish_programmatically(
+        source_class=io.FileInput, source=source, source_path=source_path,
+        destination_class=io.FileOutput,
+        destination=destination, destination_path=destination_path,
+        reader=reader, reader_name=reader_name,
+        parser=parser, parser_name=parser_name,
+        writer=writer, writer_name=writer_name,
+        settings=settings, settings_spec=settings_spec,
+        settings_overrides=settings_overrides,
+        config_section=config_section,
+        enable_exit_status=enable_exit_status)
+    return output
 
-def publish_string(source, source_path=None, destination_path=None, 
+def publish_string(source, source_path=None, destination_path=None,
                    reader=None, reader_name='standalone',
                    parser=None, parser_name='restructuredtext',
                    writer=None, writer_name='pseudoxml',
                    settings=None, settings_spec=None,
                    settings_overrides=None, config_section=None,
-                   enable_exit=None):
+                   enable_exit_status=None):
     """
-    Set up & run a `Publisher`, and return the string output.
-    For programmatic use with string I/O.
+    Set up & run a `Publisher` for programmatic use with string I/O.  Return
+    the encoded string or Unicode string output.
 
-    For encoded string output, be sure to set the "output_encoding" setting to
-    the desired encoding.  Set it to "unicode" for unencoded Unicode string
-    output.  Here's how::
+    For encoded string output, be sure to set the 'output_encoding' setting to
+    the desired encoding.  Set it to 'unicode' for unencoded Unicode string
+    output.  Here's one way::
 
         publish_string(..., settings_overrides={'output_encoding': 'unicode'})
 
@@ -337,103 +356,159 @@
 
         publish_string(..., settings_overrides={'input_encoding': 'unicode'})
 
-    Parameters:
-
-    - `source`: An input string; required.  This can be an encoded 8-bit
-      string (set the "input_encoding" setting to the correct encoding) or a
-      Unicode string (set the "input_encoding" setting to "unicode").
-    - `source_path`: Path to the file or object that produced `source`;
-      optional.  Only used for diagnostic output.
-    - `destination_path`: Path to the file or object which will receive the
-      output; optional.  Used for determining relative paths (stylesheets,
-      source links, etc.).
-    - `reader`: A `docutils.readers.Reader` object.
-    - `reader_name`: Name or alias of the Reader class to be instantiated if
-      no `reader` supplied.
-    - `parser`: A `docutils.parsers.Parser` object.
-    - `parser_name`: Name or alias of the Parser class to be instantiated if
-      no `parser` supplied.
-    - `writer`: A `docutils.writers.Writer` object.
-    - `writer_name`: Name or alias of the Writer class to be instantiated if
-      no `writer` supplied.
-    - `settings`: Runtime settings object.
-    - `settings_spec`: Extra settings specification; a `docutils.SettingsSpec`
-      subclass.  Used only if no `settings` specified.
-    - `settings_overrides`: A dictionary containing program-specific overrides
-      of component settings.
-    - `config_section`: Name of configuration file section for application.
-      Used only if no `settings` or `settings_spec` specified.
-    - `enable_exit`: Boolean; enable exit status at end of processing?
+    Parameters: see `publish_programmatically`.
     """
-    pub = Publisher(reader, parser, writer, settings=settings,
-                    source_class=io.StringInput,
-                    destination_class=io.StringOutput)
-    pub.set_components(reader_name, parser_name, writer_name)
-    if settings is None:
-        settings = pub.get_settings(settings_spec=settings_spec,
-                                    config_section=config_section)
-    if settings_overrides:
-        settings._update(settings_overrides, 'loose')
-    pub.set_source(source, source_path)
-    pub.set_destination(destination_path=destination_path)
-    return pub.publish(enable_exit=enable_exit)
+    output, pub = publish_programmatically(
+        source_class=io.StringInput, source=source, source_path=source_path,
+        destination_class=io.StringOutput,
+        destination=None, destination_path=destination_path,
+        reader=reader, reader_name=reader_name,
+        parser=parser, parser_name=parser_name,
+        writer=writer, writer_name=writer_name,
+        settings=settings, settings_spec=settings_spec,
+        settings_overrides=settings_overrides,
+        config_section=config_section,
+        enable_exit_status=enable_exit_status)
+    return output
 
-def publish_parts(source, source_path=None, destination_path=None, 
+def publish_parts(source, source_path=None, destination_path=None,
                   reader=None, reader_name='standalone',
                   parser=None, parser_name='restructuredtext',
                   writer=None, writer_name='pseudoxml',
                   settings=None, settings_spec=None,
                   settings_overrides=None, config_section=None,
-                  enable_exit=None):
+                  enable_exit_status=None):
     """
     Set up & run a `Publisher`, and return a dictionary of document parts.
     Dictionary keys are the names of parts, and values are Unicode strings;
     encoding is up to the client.  For programmatic use with string I/O.
 
-    For encoded string input, be sure to set the "input_encoding" setting to
-    the desired encoding.  Set it to "unicode" for unencoded Unicode string
+    For encoded string input, be sure to set the 'input_encoding' setting to
+    the desired encoding.  Set it to 'unicode' for unencoded Unicode string
     input.  Here's how::
 
         publish_string(..., settings_overrides={'input_encoding': 'unicode'})
 
+    Parameters: see `publish_programmatically`.
+    """
+    output, pub = publish_programmatically(
+        source_class=io.StringInput, source=source, source_path=source_path,
+        destination_class=io.StringOutput,
+        destination=None, destination_path=destination_path,
+        reader=reader, reader_name=reader_name,
+        parser=parser, parser_name=parser_name,
+        writer=writer, writer_name=writer_name,
+        settings=settings, settings_spec=settings_spec,
+        settings_overrides=settings_overrides,
+        config_section=config_section,
+        enable_exit_status=enable_exit_status)
+    return pub.writer.parts
+
+def publish_programmatically(source_class, source, source_path,
+                            destination_class, destination, destination_path,
+                            reader, reader_name,
+                            parser, parser_name,
+                            writer, writer_name,
+                            settings, settings_spec,
+                            settings_overrides, config_section,
+                            enable_exit_status):
+    """
+    Set up & run a `Publisher` for custom programmatic use.  Return the
+    encoded string output and the Publisher object.
+
+    Applications should not need to call this function directly.  If it does
+    seem to be necessary to call this function directly, please write to the
+    docutils-develop at lists.sourceforge.net mailing list.
+
     Parameters:
 
-    - `source`: An input string; required.  This can be an encoded 8-bit
-      string (set the "input_encoding" setting to the correct encoding) or a
-      Unicode string (set the "input_encoding" setting to "unicode").
-    - `source_path`: Path to the file or object that produced `source`;
-      optional.  Only used for diagnostic output.
-    - `destination_path`: Path to the file or object which will receive the
-      output; optional.  Used for determining relative paths (stylesheets,
-      source links, etc.).
-    - `reader`: A `docutils.readers.Reader` object.
-    - `reader_name`: Name or alias of the Reader class to be instantiated if
+    * `source_class` **required**: The class for dynamically created source
+      objects.  Typically `io.FileInput` or `io.StringInput`.
+
+    * `source`: Type depends on `source_class`:
+
+      - `io.FileInput`: Either a file-like object (must have 'read' and
+        'close' methods), or ``None`` (`source_path` is opened).  If neither
+        `source` nor `source_path` are supplied, `sys.stdin` is used.
+
+      - `io.StringInput` **required**: The input string, either an encoded
+        8-bit string (set the 'input_encoding' setting to the correct
+        encoding) or a Unicode string (set the 'input_encoding' setting to
+        'unicode').
+
+    * `source_path`: Type depends on `source_class`:
+
+      - `io.FileInput`: Path to the input file, opened if no `source`
+        supplied.
+
+      - `io.StringInput`: Optional.  Path to the file or object that produced
+        `source`.  Only used for diagnostic output.
+
+    * `destination_class` **required**: The class for dynamically created
+      destination objects.  Typically `io.FileOutput` or `io.StringOutput`.
+
+    * `destination`: Type depends on `destination_class`:
+
+      - `io.FileOutput`: Either a file-like object (must have 'write' and
+        'close' methods), or ``None`` (`destination_path` is opened).  If
+        neither `destination` nor `destination_path` are supplied,
+        `sys.stdout` is used.
+
+      - `io.StringOutput`: Not used; pass ``None``.
+
+    * `destination_path`: Type depends on `destination_class`:
+
+      - `io.FileOutput`: Path to the output file.  Opened if no `destination`
+        supplied.
+
+      - `io.StringOutput`: Path to the file or object which will receive the
+        output; optional.  Used for determining relative paths (stylesheets,
+        source links, etc.).
+
+    * `reader`: A `docutils.readers.Reader` object.
+
+    * `reader_name`: Name or alias of the Reader class to be instantiated if
       no `reader` supplied.
-    - `parser`: A `docutils.parsers.Parser` object.
-    - `parser_name`: Name or alias of the Parser class to be instantiated if
+
+    * `parser`: A `docutils.parsers.Parser` object.
+
+    * `parser_name`: Name or alias of the Parser class to be instantiated if
       no `parser` supplied.
-    - `writer`: A `docutils.writers.Writer` object.
-    - `writer_name`: Name or alias of the Writer class to be instantiated if
+
+    * `writer`: A `docutils.writers.Writer` object.
+
+    * `writer_name`: Name or alias of the Writer class to be instantiated if
       no `writer` supplied.
-    - `settings`: Runtime settings object.
-    - `settings_spec`: Extra settings specification; a `docutils.SettingsSpec`
-      subclass.  Used only if no `settings` specified.
-    - `settings_overrides`: A dictionary containing program-specific overrides
-      of component settings.
-    - `config_section`: Name of configuration file section for application.
-      Used only if no `settings` or `settings_spec` specified.
-    - `enable_exit`: Boolean; enable exit status at end of processing?
+
+    * `settings`: A runtime settings (`docutils.frontend.Values`) object, for
+      dotted-attribute access to runtime settings.  It's the end result of the
+      `SettingsSpec`, config file, and option processing.  If `settings` is
+      passed, it's assumed to be complete and no further setting/config/option
+      processing is done.
+
+    * `settings_spec`: A `docutils.SettingsSpec` subclass or object.  Provides
+      extra application-specific settings definitions independently of
+      components.  In other words, the application becomes a component, and
+      its settings data is processed along with that of the other components.
+      Used only if no `settings` specified.
+
+    * `settings_overrides`: A dictionary containing application-specific
+      settings defaults that override the defaults of other components.
+      Used only if no `settings` specified.
+
+    * `config_section`: A string, the name of the configuration file section
+      for this application.  Overrides the ``config_section`` attribute
+      defined by `settings_spec`.  Used only if no `settings` specified.
+
+    * `enable_exit_status`: Boolean; enable exit status at end of processing?
     """
     pub = Publisher(reader, parser, writer, settings=settings,
-                    source_class=io.StringInput,
-                    destination_class=io.NullOutput)
+                    source_class=source_class,
+                    destination_class=destination_class)
     pub.set_components(reader_name, parser_name, writer_name)
-    if settings is None:
-        settings = pub.get_settings(settings_spec=settings_spec,
-                                    config_section=config_section)
-    if settings_overrides:
-        settings._update(settings_overrides, 'loose')
+    pub.process_programmatic_settings(
+        settings_spec, settings_overrides, config_section)
     pub.set_source(source, source_path)
-    pub.set_destination(destination_path=destination_path)
-    pub.publish(enable_exit=enable_exit)
-    return pub.writer.parts
+    pub.set_destination(destination, destination_path)
+    output = pub.publish(enable_exit_status=enable_exit_status)
+    return output, pub

Modified: Zope/trunk/lib/python/docutils/frontend.py
===================================================================
--- Zope/trunk/lib/python/docutils/frontend.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/frontend.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -43,7 +43,7 @@
 def store_multiple(option, opt, value, parser, *args, **kwargs):
     """
     Store multiple values in `parser.values`.  (Option callback.)
-    
+
     Store `None` for each attribute named in `args`, and store the value for
     each key (attribute name) in `kwargs`.
     """
@@ -77,10 +77,10 @@
     try:
         codecs.lookup_error(value)
     except AttributeError:              # prior to Python 2.3
-        if value not in ('strict', 'ignore', 'replace'):
+        if value not in ('strict', 'ignore', 'replace', 'xmlcharrefreplace'):
             raise (LookupError(
                 'unknown encoding error handler: "%s" (choices: '
-                '"strict", "ignore", or "replace")' % value),
+                '"strict", "ignore", "replace", or "xmlcharrefreplace")' % value),
                    None, sys.exc_info()[2])
     except LookupError:
         raise (LookupError(
@@ -143,6 +143,15 @@
         value.extend(last.split(':'))
     return value
 
+def validate_url_trailing_slash(
+    setting, value, option_parser, config_parser=None, config_section=None):
+    if not value:
+        return './'
+    elif value.endswith('/'):
+        return value
+    else:
+        return value + '/'
+
 def make_paths_absolute(pathdict, keys, base_path=None):
     """
     Interpret filesystem path settings relative to the `base_path` given.
@@ -311,8 +320,9 @@
           ['--quiet', '-q'], {'action': 'store_const', 'const': 'none',
                               'dest': 'report_level'}),
          ('Set the threshold (<level>) at or above which system messages are '
-          'converted to exceptions, halting execution immediately.  Levels '
-          'as in --report.  Default is 4 (severe).',
+          'converted to exceptions, halting execution immediately by '
+          'exiting (or propagating the exception if --traceback set).  '
+          'Levels as in --report.  Default is 4 (severe).',
           ['--halt'], {'choices': threshold_choices, 'dest': 'halt_level',
                        'default': 4, 'metavar': '<level>',
                        'validator': validate_threshold}),
@@ -323,9 +333,10 @@
           'system messages (at or above <level>) were generated.  Levels as '
           'in --report.  Default is 5 (disabled).  Exit status is the maximum '
           'system message level plus 10 (11 for INFO, etc.).',
-          ['--exit'], {'choices': threshold_choices, 'dest': 'exit_level',
-                       'default': 5, 'metavar': '<level>',
-                       'validator': validate_threshold}),
+          ['--exit-status'], {'choices': threshold_choices,
+                              'dest': 'exit_status_level',
+                              'default': 5, 'metavar': '<level>',
+                              'validator': validate_threshold}),
          ('Report debug-level system messages and generate diagnostic output.',
           ['--debug'], {'action': 'store_true', 'validator': validate_boolean}),
          ('Do not report debug-level system messages or generate diagnostic '
@@ -333,7 +344,9 @@
           ['--no-debug'], {'action': 'store_false', 'dest': 'debug'}),
          ('Send the output of system messages (warnings) to <file>.',
           ['--warnings'], {'dest': 'warning_stream', 'metavar': '<file>'}),
-         ('Enable Python tracebacks when an error occurs.',
+         ('Enable Python tracebacks when halt-level system messages and '
+          'other exceptions occur.  Useful for debugging, and essential for '
+          'issue reports.',
           ['--traceback'], {'action': 'store_true', 'default': None,
                             'validator': validate_boolean}),
          ('Disable Python tracebacks when errors occur; report just the error '
@@ -343,23 +356,31 @@
           ['--input-encoding', '-i'],
           {'metavar': '<name>', 'validator': validate_encoding}),
          ('Specify the text encoding for output.  Default is UTF-8.  '
-          'Optionally also specify the encoding error handler for unencodable '
-          'characters (see "--error-encoding"); default is "strict".',
+          'Optionally also specify the error handler for unencodable '
+          'characters, after a colon (":"); default is "strict".  (See '
+          '"--output-encoding-error-encoding".)',
           ['--output-encoding', '-o'],
           {'metavar': '<name[:handler]>', 'default': 'utf-8',
            'validator': validate_encoding_and_error_handler}),
-         (SUPPRESS_HELP,                # usually handled by --output-encoding
+         ('Specify the error handler for unencodable characters in '
+          'the output.  Acceptable values include "strict", "ignore", '
+          '"replace", "xmlcharrefreplace", and '
+          '"backslashreplace" (in Python 2.3+).  Default is "strict".  '
+          'Usually specified as part of --output-encoding.',
           ['--output-encoding-error-handler'],
           {'default': 'strict', 'validator': validate_encoding_error_handler}),
          ('Specify the text encoding for error output.  Default is ASCII.  '
-          'Optionally also specify the encoding error handler for unencodable '
-          'characters, after a colon (":").  Acceptable values are the same '
-          'as for the "error" parameter of Python\'s ``encode`` string '
-          'method.  Default is "%s".' % default_error_encoding_error_handler,
+          'Optionally also specify the error handler for unencodable '
+          'characters, after a colon (":"); default is "%s".  (See '
+          '"--output-encoding-error-encoding".'
+          % default_error_encoding_error_handler,
           ['--error-encoding', '-e'],
           {'metavar': '<name[:handler]>', 'default': 'ascii',
            'validator': validate_encoding_and_error_handler}),
-         (SUPPRESS_HELP,                # usually handled by --error-encoding
+         ('Specify the error handler for unencodable characters in '
+          'error output.  See --output-encoding-error-handler for acceptable '
+          'values.  Default is "%s".  Usually specified as part of '
+          '--error-encoding.' % default_error_encoding_error_handler,
           ['--error-encoding-error-handler'],
           {'default': default_error_encoding_error_handler,
            'validator': validate_encoding_error_handler}),
@@ -386,7 +407,9 @@
     ends.  Setting specs specific to individual Docutils components are also
     used (see `populate_from_components()`)."""
 
-    settings_defaults = {'_disable_config': None}
+    settings_defaults = {'_disable_config': None,
+                         '_source': None,
+                         '_destination': None}
     """Defaults for settings that don't have command-line option equivalents."""
 
     relative_path_settings = ('warning_stream',)
@@ -425,16 +448,13 @@
         self.relative_path_settings = list(self.relative_path_settings)
         self.components = (self,) + tuple(components)
         self.populate_from_components(self.components)
-        defaults = defaults or {}
+        self.set_defaults(**(defaults or {}))
         if read_config_files and not self.defaults['_disable_config']:
             try:
                 config_settings = self.get_standard_config_settings()
             except ValueError, error:
                 self.error(error)
-            defaults.update(config_settings.__dict__)
-        # Internal settings with no defaults from settings specifications;
-        # initialize manually:
-        self.set_defaults(_source=None, _destination=None, **defaults)
+            self.set_defaults(**config_settings.__dict__)
 
     def populate_from_components(self, components):
         """
@@ -446,11 +466,10 @@
         for component in components:
             if component is None:
                 continue
-            i = 0
             settings_spec = component.settings_spec
             self.relative_path_settings.extend(
                 component.relative_path_settings)
-            while i < len(settings_spec):
+            for i in range(0, len(settings_spec), 3):
                 title, description, option_spec = settings_spec[i:i+3]
                 if title:
                     group = optparse.OptionGroup(self, title, description)
@@ -472,7 +491,6 @@
                         self.lists[option.dest] = 1
                 if component.settings_defaults:
                     self.defaults.update(component.settings_defaults)
-                i += 3
         for component in components:
             if component and component.settings_default_overrides:
                 self.defaults.update(component.settings_default_overrides)
@@ -552,8 +570,8 @@
     old_warning = """
 The "[option]" section is deprecated.  Support for old-format configuration
 files may be removed in a future Docutils release.  Please revise your
-configuration files.  See <http://docutils.sf.net/docs/config.html>, section
-"Old-Format Configuration Files".
+configuration files.  See <http://docutils.sf.net/docs/user/config.html>,
+section "Old-Format Configuration Files".
 """
 
     def read(self, filenames, option_parser):

Modified: Zope/trunk/lib/python/docutils/io.py
===================================================================
--- Zope/trunk/lib/python/docutils/io.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/io.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -121,15 +121,34 @@
                 % (self.__class__, self.destination, self.destination_path))
 
     def write(self, data):
+        """`data` is a Unicode string, to be encoded by `self.encode`."""
         raise NotImplementedError
 
     def encode(self, data):
         if self.encoding and self.encoding.lower() == 'unicode':
             return data
         else:
-            return data.encode(self.encoding, self.error_handler)
+            try:
+                return data.encode(self.encoding, self.error_handler)
+            except ValueError:
+                # ValueError is raised if there are unencodable chars
+                # in data and the error_handler isn't found.
+                if self.error_handler == 'xmlcharrefreplace':
+                    # We are using xmlcharrefreplace with a Python
+                    # version that doesn't support it (2.1 or 2.2), so
+                    # we emulate its behavior.
+                    return ''.join([self.xmlcharref_encode(char) for char in data])
+                else:
+                    raise
 
+    def xmlcharref_encode(self, char):
+        """Emulate Python 2.3's 'xmlcharrefreplace' encoding error handler."""
+        try:
+            return char.encode(self.encoding, 'strict')
+        except UnicodeError:
+            return '&#%i;' % ord(char)
 
+
 class FileInput(Input):
 
     """
@@ -172,7 +191,9 @@
                 pass
 
     def read(self):
-        """Read and decode a single file and return the data."""
+        """
+        Read and decode a single file and return the data (Unicode string).
+        """
         data = self.source.read()
         if self.autoclose:
             self.close()

Modified: Zope/trunk/lib/python/docutils/languages/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/__init__.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/languages/__init__.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -18,6 +18,9 @@
 def get_language(language_code):
     if _languages.has_key(language_code):
         return _languages[language_code]
-    module = __import__(language_code, globals(), locals())
+    try:
+        module = __import__(language_code, globals(), locals())
+    except ImportError:
+        return None
     _languages[language_code] = module
     return module

Modified: Zope/trunk/lib/python/docutils/languages/pt_br.py
===================================================================
--- Zope/trunk/lib/python/docutils/languages/pt_br.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/languages/pt_br.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -20,43 +20,43 @@
       # fixed: language-dependent
       'author': u'Autor',
       'authors': u'Autores',
-      'organization': unicode('Organização', 'latin1'),
-      'address': unicode('Endereço', 'latin1'),
+      'organization': u'Organiza\u00E7\u00E3o',
+      'address': u'Endere\u00E7o',
       'contact': u'Contato',
-      'version': unicode('Versão', 'latin1'),
-      'revision': unicode('Revisão', 'latin1'),
+      'version': u'Vers\u00E3o',
+      'revision': u'Revis\u00E3o',
       'status': u'Estado',
       'date': u'Data',
       'copyright': u'Copyright',
-      'dedication': unicode('Dedicatória', 'latin1'),
+      'dedication': u'Dedicat\u00F3ria',
       'abstract': u'Resumo',
-      'attention': unicode('Attenção!', 'latin1'),
+      'attention': u'Atten\u00E7\u00E3o!',
       'caution': u'Cuidado!',
       'danger': u'PERIGO!',
       'error': u'Erro',
-      'hint': unicode('Sugestão', 'latin1'),
+      'hint': u'Sugest\u00E3o',
       'important': u'Importante',
       'note': u'Nota',
       'tip': u'Dica',
       'warning': u'Aviso',
-      'contents': unicode('Sumário', 'latin1')}
+      'contents': u'Sum\u00E1rio'}
 """Mapping of node class name to label text."""
 
 bibliographic_fields = {
       # language-dependent: fixed
       u'autor': 'author',
       u'autores': 'authors',
-      unicode('organização', 'latin1'): 'organization',
-      unicode('endereço', 'latin1'): 'address',
+      u'organiza\u00E7\u00E3o': 'organization',
+      u'endere\u00E7o': 'address',
       u'contato': 'contact',
-      unicode('versão', 'latin1'): 'version',
-      unicode('revisão', 'latin1'): 'revision',
+      u'vers\u00E3o': 'version',
+      u'revis\u00E3o': 'revision',
       u'estado': 'status',
       u'data': 'date',
       u'copyright': 'copyright',
-      unicode('dedicatória', 'latin1'): 'dedication',
+      u'dedicat\u00F3ria': 'dedication',
       u'resumo': 'abstract'}
-"""English (lowcased) to canonical name mapping for bibliographic fields."""
+"""Brazilian Portuguese (lowcased) to canonical name mapping for bibliographic fields."""
 
 author_separators = [';', ',']
 """List of separator strings for the 'Authors' bibliographic field. Tried in

Modified: Zope/trunk/lib/python/docutils/nodes.py
===================================================================
--- Zope/trunk/lib/python/docutils/nodes.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/nodes.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -18,7 +18,7 @@
 ``isinstance(node, base_class)`` to determine the position of the node in the
 hierarchy.
 
-.. _DTD: http://docutils.sourceforge.net/spec/docutils.dtd
+.. _DTD: http://docutils.sourceforge.net/docs/ref/docutils.dtd
 """
 
 __docformat__ = 'reStructuredText'
@@ -1123,8 +1123,8 @@
 
     But the "contents" directive can't do its work until the entire document
     has been parsed and possibly transformed to some extent.  So the directive
-    code leaves a placeholder behind that will trigger the second phase of the
-    its processing, something like this::
+    code leaves a placeholder behind that will trigger the second phase of its
+    processing, something like this::
 
         <pending ...public attributes...> + internal attributes
 

Modified: Zope/trunk/lib/python/docutils/parsers/rst/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/__init__.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/__init__.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -88,12 +88,21 @@
     settings_spec = (
         'reStructuredText Parser Options',
         None,
-        (('Recognize and link to PEP references (like "PEP 258").',
+        (('Recognize and link to standalone PEP references (like "PEP 258").',
           ['--pep-references'],
           {'action': 'store_true', 'validator': frontend.validate_boolean}),
-         ('Recognize and link to RFC references (like "RFC 822").',
+         ('Base URL for PEP references '
+          '(default "http://www.python.org/peps/").',
+          ['--pep-base-url'],
+          {'metavar': '<URL>', 'default': 'http://www.python.org/peps/',
+           'validator': frontend.validate_url_trailing_slash}),
+         ('Recognize and link to standalone RFC references (like "RFC 822").',
           ['--rfc-references'],
           {'action': 'store_true', 'validator': frontend.validate_boolean}),
+         ('Base URL for RFC references (default "http://www.faqs.org/rfcs/").',
+          ['--rfc-base-url'],
+          {'metavar': '<URL>', 'default': 'http://www.faqs.org/rfcs/',
+           'validator': frontend.validate_url_trailing_slash}),
          ('Set number of spaces for tab expansion (default 8).',
           ['--tab-width'],
           {'metavar': '<width>', 'type': 'int', 'default': 8}),

Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/__init__.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -20,11 +20,12 @@
 
 Parameters:
 
-- ``name`` is the directive type or name.
+- ``name`` is the directive type or name (string).
 
-- ``arguments`` is a list of positional arguments.
+- ``arguments`` is a list of positional arguments (strings).
 
-- ``options`` is a dictionary mapping option names to values.
+- ``options`` is a dictionary mapping option names (strings) to values (type
+  depends on option conversion functions; see below).
 
 - ``content`` is a list of strings, the directive content.
 
@@ -63,6 +64,10 @@
   options to parse.  Several directive option conversion functions are defined
   in this module.
 
+  Option conversion functions take a single parameter, the option argument (a
+  string or ``None``), validate it and/or convert it to the appropriate form.
+  Conversion functions may raise ``ValueError`` and ``TypeError`` exceptions.
+
 - ``content``: A boolean; true if content is allowed.  Client code must handle
   the case where content is required but not supplied (an empty content list
   will be supplied).
@@ -74,11 +79,12 @@
 See `Creating reStructuredText Directives`_ for more information.
 
 .. _Creating reStructuredText Directives:
-   http://docutils.sourceforge.net/spec/howto/rst-directives.html
+   http://docutils.sourceforge.net/docs/howto/rst-directives.html
 """
 
 __docformat__ = 'reStructuredText'
 
+import re
 from docutils import nodes
 from docutils.parsers.rst.languages import en as _fallback_language_module
 
@@ -102,8 +108,9 @@
       'epigraph': ('body', 'epigraph'),
       'highlights': ('body', 'highlights'),
       'pull-quote': ('body', 'pull_quote'),
-      'table': ('body', 'table'),
       #'questions': ('body', 'question_list'),
+      'table': ('tables', 'table'),
+      'csv-table': ('tables', 'csv_table'),
       'image': ('images', 'image'),
       'figure': ('images', 'figure'),
       'contents': ('parts', 'contents'),
@@ -193,12 +200,12 @@
         return None, messages
     return function, messages
 
-def register_directive(name, directive):
+def register_directive(name, directive_function):
     """
     Register a nonstandard application-defined directive function.
     Language lookups are not needed for such functions.
     """
-    _directives[name] = directive
+    _directives[name] = directive_function
 
 def flag(argument):
     """
@@ -278,6 +285,60 @@
         raise ValueError('cannot make "%s" into a class name' % argument)
     return class_name
 
+unicode_pattern = re.compile(
+    r'(?:0x|x|\\x|U\+?|\\u)([0-9a-f]+)$|&#x([0-9a-f]+);$', re.IGNORECASE)
+
+def unicode_code(code):
+    r"""
+    Convert a Unicode character code to a Unicode character.
+
+    Codes may be decimal numbers, hexadecimal numbers (prefixed by ``0x``,
+    ``x``, ``\x``, ``U+``, ``u``, or ``\u``; e.g. ``U+262E``), or XML-style
+    numeric character entities (e.g. ``&#x262E;``).  Other text remains as-is.
+    """
+    try:
+        if code.isdigit():                  # decimal number
+            return unichr(int(code))
+        else:
+            match = unicode_pattern.match(code)
+            if match:                       # hex number
+                value = match.group(1) or match.group(2)
+                return unichr(int(value, 16))
+            else:                           # other text
+                return code
+    except OverflowError, detail:
+        raise ValueError('code too large (%s)' % detail)
+
+
+def single_char_or_unicode(argument):
+    char = unicode_code(argument)
+    if len(char) > 1:
+        raise ValueError('%r invalid; must be a single character or '
+                         'a Unicode code' % char)
+    return char
+
+def single_char_or_whitespace_or_unicode(argument):
+    if argument == 'tab':
+        char = '\t'
+    elif argument == 'space':
+        char = ' '
+    else:
+        char = single_char_or_unicode(argument)
+    return char
+
+def positive_int(argument):
+    value = int(argument)
+    if value < 1:
+        raise ValueError('negative or zero value; must be positive')
+    return value
+
+def positive_int_list(argument):
+    if ',' in argument:
+        entries = argument.split(',')
+    else:
+        entries = argument.split()
+    return [positive_int(entry) for entry in entries]
+
 def format_values(values):
     return '%s, or "%s"' % (', '.join(['"%s"' % s for s in values[:-1]]),
                             values[-1])

Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/body.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -15,7 +15,7 @@
 from docutils import nodes
 from docutils.parsers.rst import directives
 
-
+              
 def topic(name, arguments, options, content, lineno,
           content_offset, block_text, state, state_machine,
           node_class=nodes.topic):
@@ -74,6 +74,7 @@
     text = '\n'.join(content)
     text_nodes, messages = state.inline_text(text, lineno)
     node = node_class(text, '', *text_nodes, **options)
+    node.line = content_offset + 1
     return [node] + messages
 
 line_block.options = {'class': directives.class_option}
@@ -121,38 +122,3 @@
     return [block_quote] + messages
 
 pull_quote.content = 1
-
-def table(name, arguments, options, content, lineno,
-          content_offset, block_text, state, state_machine):
-    if not content:
-        warning = state_machine.reporter.warning(
-            'Content block expected for the "%s" directive; none found.'
-            % name, nodes.literal_block(block_text, block_text),
-            line=lineno)
-        return [warning]
-    if arguments:
-        title_text = arguments[0]
-        text_nodes, messages = state.inline_text(title_text, lineno)
-        title = nodes.title(title_text, '', *text_nodes)
-    else:
-        title = None
-    node = nodes.Element()          # anonymous container for parsing
-    text = '\n'.join(content)
-    state.nested_parse(content, content_offset, node)
-    if len(node) != 1 or not isinstance(node[0], nodes.table):
-        error = state_machine.reporter.error(
-            'Error parsing content block for the "%s" directive: '
-            'exactly one table expected.'
-            % name, nodes.literal_block(block_text, block_text),
-            line=lineno)
-        return [error]
-    table_node = node[0]
-    if options.has_key('class'):
-        table_node.set_class(options['class'])
-    if title:
-        table_node.insert(0, title)
-    return [table_node]
-
-table.arguments = (0, 1, 1)
-table.options = {'class': directives.class_option}
-table.content = 1

Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/images.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -28,6 +28,7 @@
 
 def image(name, arguments, options, content, lineno,
           content_offset, block_text, state, state_machine):
+    messages = []
     reference = ''.join(arguments[0].split('\n'))
     if reference.find(' ') != -1:
         error = state_machine.reporter.error(
@@ -35,23 +36,26 @@
               nodes.literal_block(block_text, block_text), line=lineno)
         return [error]
     options['uri'] = reference
+    reference_node = None
     if options.has_key('target'):
         block = states.escape2null(options['target']).splitlines()
         block = [line for line in block]
         target_type, data = state.parse_target(block, block_text, lineno)
         if target_type == 'refuri':
-            node_list = nodes.reference(refuri=data)
+            reference_node = nodes.reference(refuri=data)
         elif target_type == 'refname':
-            node_list = nodes.reference(
+            reference_node = nodes.reference(
                 refname=data, name=whitespace_normalize_name(options['target']))
-            state.document.note_refname(node_list)
+            state.document.note_refname(reference_node)
         else:                           # malformed target
-            node_list = [data]          # data is a system message
+            messages.append(data)       # data is a system message
         del options['target']
+    image_node = nodes.image(block_text, **options)
+    if reference_node:
+        reference_node += image_node
+        return messages + [reference_node]
     else:
-        node_list = []
-    node_list.append(nodes.image(block_text, **options))
-    return node_list
+        return messages + [image_node]
 
 image.arguments = (1, 0, 1)
 image.options = {'alt': directives.unchanged,

Modified: Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/misc.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -117,7 +117,7 @@
                   nodes.literal_block(block_text, block_text), line=lineno)
             return [severe]
         text = raw_file.read()
-        raw_file.close()        
+        raw_file.close()
         attributes['source'] = options['file']
     else:
         error = state_machine.reporter.warning(
@@ -185,29 +185,19 @@
     element = nodes.Element()
     for code in codes:
         try:
-            if code.isdigit():
-                element += nodes.Text(unichr(int(code)))
-            else:
-                match = unicode_pattern.match(code)
-                if match:
-                    value = match.group(1) or match.group(2)
-                    element += nodes.Text(unichr(int(value, 16)))
-                else:
-                    element += nodes.Text(code)
-        except (ValueError, OverflowError), err:
+            decoded = directives.unicode_code(code)
+        except ValueError, err:
             error = state_machine.reporter.error(
                 'Invalid character code: %s\n%s: %s'
                 % (code, err.__class__.__name__, err),
                 nodes.literal_block(block_text, block_text), line=lineno)
             return [error]
+        element += nodes.Text(decoded)
     return element.children
 
 unicode_directive.arguments = (1, 0, 1)
-unicode_pattern = re.compile(
-    r'(?:0x|x|\\x|U\+?|\\u)([0-9a-f]+)$|&#x([0-9a-f]+);$', re.IGNORECASE)
 unicode_comment_pattern = re.compile(r'( |\n|^).. ')
 
-
 def class_directive(name, arguments, options, content, lineno,
                        content_offset, block_text, state, state_machine):
     """"""
@@ -259,7 +249,7 @@
             return messages + [error]
     else:
         base_role = roles.generic_custom_role
-    assert not hasattr(base_role, 'arguments'), ( 
+    assert not hasattr(base_role, 'arguments'), (
         'Supplemental directive arguments for "%s" directive not supported'
         '(specified by "%r" role).' % (name, base_role))
     try:

Added: Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/directives/tables.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -0,0 +1,295 @@
+# Authors: David Goodger, David Priest
+# Contact: goodger at python.org
+# Revision: $Revision: 1.2 $
+# Date: $Date: 2004/06/19 22:53:32 $
+# Copyright: This module has been placed in the public domain.
+
+"""
+Directives for table elements.
+"""
+
+__docformat__ = 'reStructuredText'
+
+
+import sys
+import os.path
+from docutils import nodes, statemachine, utils
+from docutils.utils import SystemMessagePropagation
+from docutils.parsers.rst import directives
+
+try:
+    import csv                          # new in Python 2.3
+except ImportError:
+    csv = None
+
+try:
+    import urllib2
+except ImportError:
+    urllib2 = None
+
+try:
+    True
+except NameError:                       # Python 2.2 & 2.1 compatibility
+    True = not 0
+    False = not 1
+
+
+def table(name, arguments, options, content, lineno,
+          content_offset, block_text, state, state_machine):
+    if not content:
+        warning = state_machine.reporter.warning(
+            'Content block expected for the "%s" directive; none found.'
+            % name, nodes.literal_block(block_text, block_text),
+            line=lineno)
+        return [warning]
+    title, messages = make_title(arguments, state, lineno)
+    node = nodes.Element()          # anonymous container for parsing
+    text = '\n'.join(content)
+    state.nested_parse(content, content_offset, node)
+    if len(node) != 1 or not isinstance(node[0], nodes.table):
+        error = state_machine.reporter.error(
+            'Error parsing content block for the "%s" directive: '
+            'exactly one table expected.'
+            % name, nodes.literal_block(block_text, block_text),
+            line=lineno)
+        return [error]
+    table_node = node[0]
+    if options.has_key('class'):
+        table_node.set_class(options['class'])
+    if title:
+        table_node.insert(0, title)
+    return [table_node] + messages
+
+table.arguments = (0, 1, 1)
+table.options = {'class': directives.class_option}
+table.content = 1
+
+def make_title(arguments, state, lineno):
+    if arguments:
+        title_text = arguments[0]
+        text_nodes, messages = state.inline_text(title_text, lineno)
+        title = nodes.title(title_text, '', *text_nodes)
+    else:
+        title = None
+        messages = []
+    return title, messages
+
+
+if csv:
+    class DocutilsDialect(csv.Dialect):
+
+        """CSV dialect for `csv_table` directive function."""
+
+        delimiter = ','
+        quotechar = '"'
+        doublequote = True
+        skipinitialspace = True
+        lineterminator = '\n'
+        quoting = csv.QUOTE_MINIMAL
+
+        def __init__(self, options):
+            if options.has_key('delim'):
+                self.delimiter = str(options['delim'])
+            if options.has_key('keepspace'):
+                self.skipinitialspace = False
+            if options.has_key('quote'):
+                self.quotechar = str(options['quote'])
+            if options.has_key('escape'):
+                self.doublequote = False
+                self.escapechar = str(options['escape'])
+            csv.Dialect.__init__(self)
+
+
+    class HeaderDialect(csv.Dialect):
+
+        """CSV dialect to use for the "header" option data."""
+
+        delimiter = ','
+        quotechar = '"'
+        escapechar = '\\'
+        doublequote = False
+        skipinitialspace = True
+        lineterminator = '\n'
+        quoting = csv.QUOTE_MINIMAL
+
+
+def csv_table(name, arguments, options, content, lineno,
+             content_offset, block_text, state, state_machine):
+    try:
+        check_requirements(name, lineno, block_text, state_machine)
+        title, messages = make_title(arguments, state, lineno)
+        csv_data, source = get_csv_data(
+            name, options, content, lineno, block_text, state, state_machine)
+        table_head, max_header_cols = process_header_option(
+            options, state_machine, lineno)
+        rows, max_cols = parse_csv_data_into_rows(
+            csv_data, DocutilsDialect(options), source, options)
+        max_cols = max(max_cols, max_header_cols)
+        header_rows = options.get('header-rows', 0) # default 0
+        check_table_dimensions(
+            rows, header_rows, name, lineno, block_text, state_machine)
+        table_head.extend(rows[:header_rows])
+        table_body = rows[header_rows:]
+        col_widths = get_column_widths(
+            max_cols, name, options, lineno, block_text, state_machine)
+        extend_short_rows_with_empty_cells(max_cols, (table_head, table_body))
+    except SystemMessagePropagation, detail:
+        return [detail.args[0]]
+    except csv.Error, detail:
+        error = state_machine.reporter.error(
+            'Error with CSV data in "%s" directive:\n%s' % (name, detail),
+            nodes.literal_block(block_text, block_text), line=lineno)
+        return [error]
+    table = (col_widths, table_head, table_body)
+    table_node = state.build_table(table, content_offset)
+    if options.has_key('class'):
+        table_node.set_class(options['class'])
+    if title:
+        table_node.insert(0, title)
+    return [table_node] + messages
+
+csv_table.arguments = (0, 1, 1)
+csv_table.options = {'header-rows': directives.nonnegative_int,
+                     'header': directives.unchanged,
+                     'widths': directives.positive_int_list,
+                     'file': directives.path,
+                     'url': directives.path,
+                     'class': directives.class_option,
+                     # field delimiter char
+                     'delim': directives.single_char_or_whitespace_or_unicode,
+                     # treat whitespace after delimiter as significant
+                     'keepspace': directives.flag,
+                     # text field quote/unquote char:
+                     'quote': directives.single_char_or_unicode,
+                     # char used to escape delim & quote as-needed:
+                     'escape': directives.single_char_or_unicode,}
+csv_table.content = 1
+
+def check_requirements(name, lineno, block_text, state_machine):
+    if not csv:
+        error = state_machine.reporter.error(
+            'The "%s" directive is not compatible with this version of '
+            'Python (%s).  Requires the "csv" module, new in Python 2.3.'
+            % (name, sys.version.split()[0]),
+            nodes.literal_block(block_text, block_text), line=lineno)
+        raise SystemMessagePropagation(error)
+
+def get_csv_data(name, options, content, lineno, block_text,
+                 state, state_machine):
+    """
+    CSV data can come from the directive content, from an external file, or
+    from a URL reference.
+    """
+    if content:                         # CSV data is from directive content
+        if options.has_key('file') or options.has_key('url'):
+            error = state_machine.reporter.error(
+                  '"%s" directive may not both specify an external file and '
+                  'have content.' % name,
+                  nodes.literal_block(block_text, block_text), line=lineno)
+            raise SystemMessagePropagation(error)
+        source = content.source(0)
+        csv_data = content
+    elif options.has_key('file'):       # CSV data is from an external file
+        if options.has_key('url'):
+            error = state_machine.reporter.error(
+                  'The "file" and "url" options may not be simultaneously '
+                  'specified for the "%s" directive.' % name,
+                  nodes.literal_block(block_text, block_text), line=lineno)
+            raise SystemMessagePropagation(error)
+        source_dir = os.path.dirname(
+            os.path.abspath(state.document.current_source))
+        source = os.path.normpath(os.path.join(source_dir, options['file']))
+        source = utils.relative_path(None, source)
+        try:
+            csv_file = open(source, 'rb')
+            try:
+                csv_data = csv_file.read().splitlines()
+            finally:
+                csv_file.close()
+        except IOError, error:
+            severe = state_machine.reporter.severe(
+                  'Problems with "%s" directive path:\n%s.' % (name, error),
+                  nodes.literal_block(block_text, block_text), line=lineno)
+            raise SystemMessagePropagation(severe)
+    elif options.has_key('url'):        # CSV data is from a URL
+        if not urllib2:
+            severe = state_machine.reporter.severe(
+                  'Problems with the "%s" directive and its "url" option: '
+                  'unable to access the required functionality (from the '
+                  '"urllib2" module).' % name,
+                  nodes.literal_block(block_text, block_text), line=lineno)
+            raise SystemMessagePropagation(severe)
+        source = options['url']
+        try:
+            csv_data = urllib2.urlopen(source).read().splitlines()
+        except (urllib2.URLError, IOError, OSError, ValueError), error:
+            severe = state_machine.reporter.severe(
+                  'Problems with "%s" directive URL "%s":\n%s.'
+                  % (name, options['url'], error),
+                  nodes.literal_block(block_text, block_text), line=lineno)
+            raise SystemMessagePropagation(severe)
+    else:
+        error = state_machine.reporter.warning(
+            'The "%s" directive requires content; none supplied.' % (name),
+            nodes.literal_block(block_text, block_text), line=lineno)
+        raise SystemMessagePropagation(error)
+    return csv_data, source
+
+def process_header_option(options, state_machine, lineno):
+    source = state_machine.get_source(lineno - 1)
+    table_head = []
+    max_header_cols = 0
+    if options.has_key('header'):       # separate table header in option
+        rows, max_header_cols = parse_csv_data_into_rows(
+            options['header'].split('\n'), HeaderDialect(), source, options)
+        table_head.extend(rows)
+    return table_head, max_header_cols
+
+def parse_csv_data_into_rows(csv_data, dialect, source, options):
+    csv_reader = csv.reader(csv_data, dialect=dialect)
+    rows = []
+    max_cols = 0
+    for row in csv_reader:
+        row_data = []
+        for cell in row:
+            cell_data = (0, 0, 0, statemachine.StringList(cell.splitlines(),
+                                                          source=source))
+            row_data.append(cell_data)
+        rows.append(row_data)
+        max_cols = max(max_cols, len(row))
+    return rows, max_cols
+
+def check_table_dimensions(rows, header_rows, name, lineno, block_text,
+                           state_machine):
+    if len(rows) < header_rows:
+        error = state_machine.reporter.error(
+            '%s header row(s) specified but only %s row(s) of data supplied '
+            '("%s" directive).' % (header_rows, len(rows), name),
+            nodes.literal_block(block_text, block_text), line=lineno)
+        raise SystemMessagePropagation(error)
+    elif len(rows) == header_rows > 0:
+        error = state_machine.reporter.error(
+            'Insufficient data supplied (%s row(s)); no data remaining for '
+            'table body, required by "%s" directive.' % (len(rows), name),
+            nodes.literal_block(block_text, block_text), line=lineno)
+        raise SystemMessagePropagation(error)
+
+def get_column_widths(max_cols, name, options, lineno, block_text,
+                      state_machine):
+    if options.has_key('widths'):
+        col_widths = options['widths']
+        if len(col_widths) != max_cols:
+            error = state_machine.reporter.error(
+              '"%s" widths do not match the number of columns in table (%s).'
+              % (name, max_cols),
+              nodes.literal_block(block_text, block_text), line=lineno)
+            raise SystemMessagePropagation(error)
+    else:
+        col_widths = [100 / max_cols] * max_cols
+    return col_widths
+
+def extend_short_rows_with_empty_cells(columns, parts):
+    for part in parts:
+        for row in part:
+            if len(row) < columns:
+                row.extend([(0, 0, 0, [])] * (columns - len(row)))

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/af.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -36,10 +36,11 @@
       'epigraaf': 'epigraph',
       'hoogtepunte': 'highlights',
       'pull-quote (translation required)': 'pull-quote',
-      'table (translation required)': 'table',
       #'vrae': 'questions',
       #'qa': 'questions',
       #'faq': 'questions',
+      'table (translation required)': 'table',
+      'csv-table (translation required)': 'csv-table',
       'meta': 'meta',
       #'beeldkaart': 'imagemap',
       'beeld': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/cs.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -37,10 +37,11 @@
       u'moto': 'epigraph',
       u'highlights': 'highlights',
       u'pull-quote': 'pull-quote',
-      u'table (translation required)': 'table',
       #'questions': 'questions',
       #'qa': 'questions',
       #'faq': 'questions',
+      u'table (translation required)': 'table',
+      u'csv-table (translation required)': 'csv-table',
       u'meta': 'meta',
       #'imagemap': 'imagemap',
       u'image': 'image',   # obrazek

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/de.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -37,10 +37,11 @@
       'epigraph (translation required)': 'epigraph',
       'highlights (translation required)': 'highlights',
       'pull-quote (translation required)': 'pull-quote', # kasten too ?
-      'table (translation required)': 'table',
       #'questions': 'questions',
       #'qa': 'questions',
       #'faq': 'questions',
+      'table (translation required)': 'table',
+      'csv-table (translation required)': 'csv-table',
       'meta': 'meta',
       #'imagemap': 'imagemap',
       'bild': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/en.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -37,8 +37,9 @@
       'epigraph': 'epigraph',
       'highlights': 'highlights',
       'pull-quote': 'pull-quote',
+      #'questions': 'questions',
       'table': 'table',
-      #'questions': 'questions',
+      'csv-table': 'csv-table',
       #'qa': 'questions',
       #'faq': 'questions',
       'meta': 'meta',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/eo.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -40,10 +40,12 @@
       u'elstara\u0135oj': 'highlights',
       u'ekstera-citajxo': 'pull-quote',
       u'ekstera-cita\u0135o': 'pull-quote',
-      u'tabelo': 'table',
       #'questions': 'questions',
       #'qa': 'questions',
       #'faq': 'questions',
+      u'tabelo': 'table',
+      u'tabelo-vdk': 'csv-table', # "valoroj disigitaj per komoj"
+      u'tabelo-csv': 'csv-table',
       u'meta': 'meta',
       #'imagemap': 'imagemap',
       u'bildo': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/es.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -42,10 +42,12 @@
       u'epigrafe': 'epigraph',
       u'destacado': 'highlights',
       u'cita-destacada': 'pull-quote',
-      u'tabla': 'table',
       #'questions': 'questions',
       #'qa': 'questions',
       #'faq': 'questions',
+      u'tabla': 'table',
+      u'tabla-vsc': 'csv-table',
+      u'tabla-csv': 'csv-table',
       u'meta': 'meta',
       #'imagemap': 'imagemap',
       u'imagen': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/fr.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -38,10 +38,11 @@
       u'\u00E9pigraphe': 'epigraph',
       u'chapeau': 'highlights',
       u'accroche': 'pull-quote',
-      u'tableau': 'table',
       #u'questions': 'questions',
       #u'qr': 'questions',
       #u'faq': 'questions',
+      u'tableau': 'table',
+      u'csv-table (translation required)': 'csv-table',
       u'm\u00E9ta': 'meta',
       #u'imagemap (translation required)': 'imagemap',
       u'image': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/it.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -31,10 +31,11 @@
       'epigrafe': 'epigraph',
       'evidenzia': 'highlights',
       'pull-quote (translation required)': 'pull-quote',
-      'tabella': 'table',
       #'questions': 'questions',
       #'qa': 'questions',
       #'faq': 'questions',
+      'tabella': 'table',
+      'csv-table (translation required)': 'csv-table',
       'meta': 'meta',
       #'imagemap': 'imagemap',
       'immagine': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/pt_br.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -20,78 +20,79 @@
 
 directives = {
       # language-dependent: fixed
-      u'atenção': 'attention',
+      u'aten\u00E7\u00E3o': 'attention',
       'cuidado': 'caution',
       'perigo': 'danger',
       'erro': 'error',
-      u'sugestão': 'hint',
+      u'sugest\u00E3o': 'hint',
       'importante': 'important',
       'nota': 'note',
       'dica': 'tip',
       'aviso': 'warning',
-      u'exortação': 'admonition',
+      u'exorta\u00E7\u00E3o': 'admonition',
       'barra-lateral': 'sidebar',
-      u'tópico': 'topic',
+      u't\u00F3pico': 'topic',
       'bloco-de-linhas': 'line-block',
       'literal-interpretado': 'parsed-literal',
       'rubrica': 'rubric',
-      u'epígrafo': 'epigraph',
+      u'ep\u00EDgrafo': 'epigraph',
       'destaques': 'highlights',
-      u'citação-destacada': 'pull-quote',
-      u'table (translation required)': 'table',
+      u'cita\u00E7\u00E3o-destacada': 'pull-quote',
       #'perguntas': 'questions',
       #'qa': 'questions',
       #'faq': 'questions',
+      u'table (translation required)': 'table',
+      u'csv-table (translation required)': 'csv-table',
       'meta': 'meta',
       #'imagemap': 'imagemap',
       'imagem': 'image',
       'figura': 'figure',
-      u'inclusão': 'include',
+      u'inclus\u00E3o': 'include',
       'cru': 'raw',
-      u'substituição': 'replace',
+      u'substitui\u00E7\u00E3o': 'replace',
       'unicode': 'unicode',
       'classe': 'class',
       'role (translation required)': 'role',
-      u'índice': 'contents',
+      u'\u00EDndice': 'contents',
       'numsec': 'sectnum',
-      u'numeração-de-seções': 'sectnum',
-      #u'notas-de-rorapé': 'footnotes',
-      #u'citações': 'citations',
-      u'links-no-rodapé': 'target-notes',
+      u'numera\u00E7\u00E3o-de-se\u00E7\u00F5es': 'sectnum',
+      #u'notas-de-rorap\u00E9': 'footnotes',
+      #u'cita\u00E7\u00F5es': 'citations',
+      u'links-no-rodap\u00E9': 'target-notes',
       'restructuredtext-test-directive': 'restructuredtext-test-directive'}
-"""English name to registered (in directives/__init__.py) directive name
-mapping."""
+"""Brazilian Portuguese name to registered (in directives/__init__.py)
+directive name mapping."""
 
 roles = {
     # language-dependent: fixed
-    u'abbreviação': 'abbreviation',
+    u'abbrevia\u00E7\u00E3o': 'abbreviation',
     'ab': 'abbreviation',
-    u'acrônimo': 'acronym',
+    u'acr\u00F4nimo': 'acronym',
     'ac': 'acronym',
-    u'índice-remissivo': 'index',
+    u'\u00EDndice-remissivo': 'index',
     'i': 'index',
     'subscrito': 'subscript',
     'sub': 'subscript',
     'sobrescrito': 'superscript',
     'sob': 'superscript',
-    u'referência-a-título': 'title-reference',
-    u'título': 'title-reference',
+    u'refer\u00EAncia-a-t\u00EDtulo': 'title-reference',
+    u't\u00EDtulo': 'title-reference',
     't': 'title-reference',
-    u'referência-a-pep': 'pep-reference',
+    u'refer\u00EAncia-a-pep': 'pep-reference',
     'pep': 'pep-reference',
-    u'referência-a-rfc': 'rfc-reference',
+    u'refer\u00EAncia-a-rfc': 'rfc-reference',
     'rfc': 'rfc-reference',
-    u'ênfase': 'emphasis',
+    u'\u00EAnfase': 'emphasis',
     'forte': 'strong',
     'literal': 'literal',
-    u'referência-por-nome': 'named-reference',
-    u'referência-anônima': 'anonymous-reference',
-    u'referência-a-nota-de-rodapé': 'footnote-reference',
-    u'referência-a-citação': 'citation-reference',
-    u'referência-a-substituição': 'substitution-reference',
+    u'refer\u00EAncia-por-nome': 'named-reference',
+    u'refer\u00EAncia-an\u00F4nima': 'anonymous-reference',
+    u'refer\u00EAncia-a-nota-de-rodap\u00E9': 'footnote-reference',
+    u'refer\u00EAncia-a-cita\u00E7\u00E3o': 'citation-reference',
+    u'refer\u00EAncia-a-substitui\u00E7\u00E3o': 'substitution-reference',
     'alvo': 'target',
-    u'referência-a-uri': 'uri-reference',
+    u'refer\u00EAncia-a-uri': 'uri-reference',
     'uri': 'uri-reference',
     'url': 'uri-reference',}
-"""Mapping of English role names to canonical role names for interpreted text.
-"""
+"""Mapping of Brazilian Portuguese role names to canonical role names
+for interpreted text."""

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/ru.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -24,6 +24,7 @@
  u'\u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f-\u0446\u0438\u0442\u0430\u0442\u0430':
  u'pull-quote',
  u'table (translation required)': 'table',
+ u'csv-table (translation required)': 'csv-table',
  u'\u0441\u044b\u0440\u043e\u0439': u'raw',
  u'\u0437\u0430\u043c\u0435\u043d\u0430': u'replace',
  u'\u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f-\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430-restructuredtext':

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/sk.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -36,10 +36,11 @@
       u'epigraph (translation required)': 'epigraph',
       u'highlights (translation required)': 'highlights',
       u'pull-quote (translation required)': 'pull-quote',
-      u'table (translation required)': 'table',
       #u'questions': 'questions',
       #u'qa': 'questions',
       #u'faq': 'questions',
+      u'table (translation required)': 'table',
+      u'csv-table (translation required)': 'csv-table',
       u'meta': 'meta',
       #u'imagemap': 'imagemap',
       u'obr\xe1zok': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/languages/sv.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -35,11 +35,12 @@
       u'epigraph (translation required)': 'epigraph',
       u'highlights (translation required)': 'highlights',
       u'pull-quote (translation required)': 'pull-quote',
-      u'table (translation required)': 'table',
       # u'fr\u00e5gor': 'questions',
       # NOTE: A bit long, but recommended by http://www.nada.kth.se/dataterm/:
       # u'fr\u00e5gor-och-svar': 'questions',
       # u'vanliga-fr\u00e5gor': 'questions',  
+      u'table (translation required)': 'table',
+      u'csv-table (translation required)': 'csv-table',
       u'meta': 'meta',
       # u'bildkarta': 'imagemap',   # FIXME: Translation might be too literal.
       u'bild': 'image',

Modified: Zope/trunk/lib/python/docutils/parsers/rst/roles.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/roles.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/roles.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -263,7 +263,7 @@
         prb = inliner.problematic(rawtext, rawtext, msg)
         return [prb], [msg]
     # Base URL mainly used by inliner.pep_reference; so this is correct:
-    ref = inliner.pep_url % pepnum
+    ref = inliner.document.settings.pep_base_url + inliner.pep_url % pepnum
     return [nodes.reference(rawtext, 'PEP ' + text, refuri=ref, **options)], []
 
 register_canonical_role('pep-reference', pep_reference_role)
@@ -281,7 +281,7 @@
         prb = inliner.problematic(rawtext, rawtext, msg)
         return [prb], [msg]
     # Base URL mainly used by inliner.rfc_reference, so this is correct:
-    ref = inliner.rfc_url % rfcnum
+    ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
     node = nodes.reference(rawtext, 'RFC ' + text, refuri=ref, **options)
     return [node], []
 

Modified: Zope/trunk/lib/python/docutils/parsers/rst/states.py
===================================================================
--- Zope/trunk/lib/python/docutils/parsers/rst/states.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/parsers/rst/states.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -556,14 +556,19 @@
     # Valid URI characters (see RFC 2396 & RFC 2732);
     # final \x00 allows backslash escapes in URIs:
     uric = r"""[-_.!~*'()[\];/:@&=+$,%a-zA-Z0-9\x00]"""
+    # Delimiter indicating the end of a URI (not part of the URI):
+    uri_end_delim = r"""[>]"""
     # Last URI character; same as uric but no punctuation:
-    urilast = r"""[_~/a-zA-Z0-9]"""
+    urilast = r"""[_~*/=+a-zA-Z0-9]"""
+    # End of a URI (either 'urilast' or 'uric followed by a
+    # uri_end_delim'):
+    uri_end = r"""(?:%(urilast)s|%(uric)s(?=%(uri_end_delim)s))""" % locals()
     emailc = r"""[-_!~*'{|}/#?^`&=+$%a-zA-Z0-9\x00]"""
     email_pattern = r"""
           %(emailc)s+(?:\.%(emailc)s+)*   # name
           @                               # at
           %(emailc)s+(?:\.%(emailc)s*)*   # host
-          %(urilast)s                     # final URI char
+          %(uri_end)s                     # final URI char
           """
     parts = ('initial_inline', start_string_prefix, '',
              [('start', '', non_whitespace_after,  # simple start-strings
@@ -642,15 +647,15 @@
                       (                       # either:
                         (//?)?                  # hierarchical URI
                         %(uric)s*               # URI characters
-                        %(urilast)s             # final URI char
+                        %(uri_end)s             # final URI char
                       )
                       (                       # optional query
                         \?%(uric)s*
-                        %(urilast)s
+                        %(uri_end)s
                       )?
                       (                       # optional fragment
                         \#%(uric)s*
-                        %(urilast)s
+                        %(uri_end)s
                       )?
                     )
                   )
@@ -954,9 +959,7 @@
         else:                   # not a valid scheme
             raise MarkupMismatch
 
-    pep_url_local = 'pep-%04d.html'
-    pep_url_absolute = 'http://www.python.org/peps/pep-%04d.html'
-    pep_url = pep_url_absolute
+    pep_url = 'pep-%04d.html'
 
     def pep_reference(self, match, lineno):
         text = match.group(0)
@@ -966,17 +969,17 @@
             pepnum = int(match.group('pepnum2'))
         else:
             raise MarkupMismatch
-        ref = self.pep_url % pepnum
+        ref = self.document.settings.pep_base_url + self.pep_url % pepnum
         unescaped = unescape(text, 0)
         return [nodes.reference(unescape(text, 1), unescaped, refuri=ref)]
 
-    rfc_url = 'http://www.faqs.org/rfcs/rfc%d.html'
+    rfc_url = 'rfc%d.html'
 
     def rfc_reference(self, match, lineno):
         text = match.group(0)
         if text.startswith('RFC'):
             rfcnum = int(match.group('rfcnum'))
-            ref = self.rfc_url % rfcnum
+            ref = self.document.settings.rfc_base_url + self.rfc_url % rfcnum
         else:
             raise MarkupMismatch
         unescaped = unescape(text, 0)
@@ -2542,9 +2545,10 @@
             indented.trim_end()
         if not indented:
             return self.quoted_literal_block()
-        nodelist = []
         data = '\n'.join(indented)
-        nodelist.append(nodes.literal_block(data, data))
+        literal_block = nodes.literal_block(data, data)
+        literal_block.line = offset + 1
+        nodelist = [literal_block]
         if not blank_finish:
             nodelist.append(self.unindent_warning('Literal block'))
         return nodelist

Modified: Zope/trunk/lib/python/docutils/readers/pep.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/pep.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/readers/pep.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -16,15 +16,6 @@
 from docutils.parsers import rst
 
 
-class Inliner(rst.states.Inliner):
-
-    """
-    Extend `rst.Inliner` for local PEP references.
-    """
-
-    pep_url = rst.states.Inliner.pep_url_local
-
-
 class Reader(standalone.Reader):
 
     supported = ('pep',)
@@ -52,7 +43,7 @@
 
     settings_default_overrides = {'pep_references': 1, 'rfc_references': 1}
 
-    inliner_class = Inliner
+    inliner_class = rst.states.Inliner
 
     def __init__(self, parser=None, parser_name=None):
         """`parser` should be ``None``."""

Modified: Zope/trunk/lib/python/docutils/readers/python/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/python/__init__.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/readers/python/__init__.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -1,11 +1,14 @@
 # Author: David Goodger
 # Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.3.2.1.8.1 $
-# Date: $Date: 2004/05/12 19:57:53 $
+# Revision: $Revision: 1.7 $
+# Date: $Date: 2004/07/25 01:45:26 $
 # Copyright: This module has been placed in the public domain.
 
 """
 This package contains the Python Source Reader modules.
+
+It requires Python 2.2 or higher (`moduleparser` depends on `compiler` and
+`tokenizer` modules).
 """
 
 __docformat__ = 'reStructuredText'

Modified: Zope/trunk/lib/python/docutils/readers/python/moduleparser.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/python/moduleparser.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/readers/python/moduleparser.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -1,11 +1,11 @@
 # Author: David Goodger
 # Contact: goodger at users.sourceforge.net
-# Revision: $Revision: 1.3.2.1.8.1 $
-# Date: $Date: 2004/05/12 19:57:53 $
+# Revision: $Revision: 1.14 $
+# Date: $Date: 2004/07/25 01:45:26 $
 # Copyright: This module has been placed in the public domain.
 
 """
-Parser for Python modules.
+Parser for Python modules.  Requires Python 2.2 or higher.
 
 The `parse_module()` function takes a module's text and file name,
 runs it through the module parser (using compiler.py and tokenize.py)

Modified: Zope/trunk/lib/python/docutils/readers/python/pynodes.py
===================================================================
--- Zope/trunk/lib/python/docutils/readers/python/pynodes.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/readers/python/pynodes.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -3,8 +3,8 @@
 """
 :Author: David Goodger
 :Contact: goodger at users.sourceforge.net
-:Revision: $Revision: 1.1.2.1 $
-:Date: $Date: 2004/05/12 19:57:53 $
+:Revision: $Revision: 1.3 $
+:Date: $Date: 2004/03/23 23:21:11 $
 :Copyright: This module has been placed in the public domain.
 
 """

Modified: Zope/trunk/lib/python/docutils/statemachine.py
===================================================================
--- Zope/trunk/lib/python/docutils/statemachine.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/statemachine.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -344,6 +344,10 @@
         finally:
             self.notify_observers()
 
+    def get_source(self, line_offset):
+        """Return source of line at absolute line offset `line_offset`."""
+        return self.input_lines.source(line_offset - self.input_offset)
+
     def abs_line_offset(self):
         """Return line offset of current line, from beginning of file."""
         return self.line_offset + self.input_offset

Modified: Zope/trunk/lib/python/docutils/transforms/peps.py
===================================================================
--- Zope/trunk/lib/python/docutils/transforms/peps.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/transforms/peps.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -118,7 +118,9 @@
                 for refpep in re.split(',?\s+', body.astext()):
                     pepno = int(refpep)
                     newbody.append(nodes.reference(
-                          refpep, refpep, refuri=self.pep_url % pepno))
+                        refpep, refpep,
+                        refuri=(self.document.settings.pep_base_url
+                                + self.pep_url % pepno)))
                     newbody.append(space)
                 para[:] = newbody[:-1] # drop trailing space
             elif name == 'last-modified':
@@ -128,7 +130,7 @@
                     para[:] = [nodes.reference('', date, refuri=cvs_url)]
             elif name == 'content-type':
                 pep_type = para.astext()
-                uri = self.pep_url % 12
+                uri = self.document.settings.pep_base_url + self.pep_url % 12
                 para[:] = [nodes.reference('', pep_type, refuri=uri)]
             elif name == 'version' and len(body):
                 utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions)
@@ -266,7 +268,8 @@
                 text = p.astext()
                 try:
                     pep = int(text)
-                    ref = self.pep_url % pep
+                    ref = (self.document.settings.pep_base_url
+                           + self.pep_url % pep)
                     p[0] = nodes.reference(text, text, refuri=ref)
                 except ValueError:
                     pass

Modified: Zope/trunk/lib/python/docutils/utils.py
===================================================================
--- Zope/trunk/lib/python/docutils/utils.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/utils.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -25,6 +25,9 @@
         self.level = level
 
 
+class SystemMessagePropagation(ApplicationError): pass
+
+
 class Reporter:
 
     """
@@ -52,7 +55,7 @@
     is compared to the thresholds stored in the category, and a warning or
     error is generated as appropriate.  Debug messages are produced iff the
     stored debug switch is on.  Message output is sent to the stored warning
-    stream.
+    stream if not set to ''.
 
     The default category is '' (empty string).  By convention, Writers should
     retrieve reporting conditions from the 'writer' category (which, unless
@@ -89,7 +92,8 @@
               exceptions will be raised, halting execution.
             - `debug`: Show debug (level=0) system messages?
             - `stream`: Where warning output is sent.  Can be file-like (has a
-              ``.write`` method), a string (file name, opened for writing), or
+              ``.write`` method), a string (file name, opened for writing), 
+              '' (empty string, for discarding all stream messages) or
               `None` (implies `sys.stderr`; default).
             - `encoding`: The encoding for stderr output.
             - `error_handler`: The error handler for stderr output encoding.
@@ -100,7 +104,12 @@
         if stream is None:
             stream = sys.stderr
         elif type(stream) in (StringType, UnicodeType):
-            raise NotImplementedError('This should open a file for writing.')
+            # Leave stream untouched if it's ''.
+            if stream != '':
+                if type(stream) == StringType:
+                    stream = open(stream, 'w')
+                elif type(stream) == UnicodeType:
+                    stream = open(stream.encode(), 'w')
 
         self.encoding = encoding
         """The character encoding for the stderr output."""
@@ -175,7 +184,7 @@
                                    type=self.levels[level],
                                    *children, **attributes)
         debug, report_level, halt_level, stream = self[category].astuple()
-        if level >= report_level or debug and level == 0:
+        if (level >= report_level or debug and level == 0) and stream:
             msgtext = msg.astext().encode(self.encoding, self.error_handler)
             if category:
                 print >>stream, msgtext, '[%s]' % category
@@ -265,6 +274,8 @@
         - `KeyError` for unknown option names.
         - `ValueError` for invalid option values (raised by the conversion
            function).
+        - `TypeError` for invalid option value types (raised by conversion
+           function).
         - `DuplicateOptionError` for duplicate options.
         - `BadOptionError` for invalid fields.
         - `BadOptionDataError` for invalid option data (missing name,
@@ -321,6 +332,8 @@
         - `DuplicateOptionError` for duplicate options.
         - `ValueError` for invalid option values (raised by conversion
            function).
+        - `TypeError` for invalid option value types (raised by conversion
+           function).
     """
     options = {}
     for name, value in option_list:

Modified: Zope/trunk/lib/python/docutils/writers/__init__.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/__init__.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/writers/__init__.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -36,13 +36,15 @@
     """The document to write (Docutils doctree); set by `write`."""
 
     output = None
-    """Final translated form of `document`; set by `translate`."""
+    """Final translated form of `document` (Unicode string);
+    set by `translate`."""
 
     language = None
     """Language module for the document; set by `write`."""
 
     destination = None
-    """`docutils.io` IO object; where to write the document.  Set by `write`."""
+    """`docutils.io` Output object; where to write the document.
+    Set by `write`."""
 
     def __init__(self):
 
@@ -73,8 +75,8 @@
 
     def translate(self):
         """
-        Do final translation of `self.document` into `self.output`.
-        Called from `write`.  Override in subclasses.
+        Do final translation of `self.document` into `self.output` (Unicode
+        string).  Called from `write`.  Override in subclasses.
 
         Usually done with a `docutils.nodes.NodeVisitor` subclass, in
         combination with a call to `docutils.nodes.Node.walk()` or

Modified: Zope/trunk/lib/python/docutils/writers/docutils_xml.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/docutils_xml.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/writers/docutils_xml.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -50,7 +50,7 @@
     doctype = (
         '<!DOCTYPE document PUBLIC'
         ' "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML"'
-        ' "http://docutils.sourceforge.net/spec/docutils.dtd">\n')
+        ' "http://docutils.sourceforge.net/docs/ref/docutils.dtd">\n')
     generator = '<!-- Generated by Docutils %s -->\n'
 
     def translate(self):

Modified: Zope/trunk/lib/python/docutils/writers/html4css1.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/html4css1.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/writers/html4css1.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -418,7 +418,6 @@
         self.body.append(self.starttag(node, 'table', CLASS='citation',
                                        frame="void", rules="none"))
         self.body.append('<colgroup><col class="label" /><col /></colgroup>\n'
-                         '<col />\n'
                          '<tbody valign="top">\n'
                          '<tr>')
         self.footnote_backrefs(node)
@@ -1143,7 +1142,7 @@
         self.body.append(
               # "border=None" is a boolean attribute;
               # it means "standard border", not "no border":
-              self.starttag(node, 'table', CLASS="table", border=None))
+              self.starttag(node, 'table', CLASS="table", border="1"))
 
     def depart_table(self, node):
         self.body.append('</table>\n')

Modified: Zope/trunk/lib/python/docutils/writers/latex2e.py
===================================================================
--- Zope/trunk/lib/python/docutils/writers/latex2e.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/docutils/writers/latex2e.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -34,10 +34,10 @@
           ['--documentclass'],
           {'default': 'article', }),
          ('Specify document options.  Multiple options can be given, '
-          'separated by commas.  Default is "10pt".',
+          'separated by commas.  Default is "10pt,a4paper".',
           ['--documentoptions'],
-          {'default': '10pt', }),
-         ('Use LaTeX footnotes. '
+          {'default': '10pt,a4paper', }),
+         ('Use LaTeX footnotes. LaTeX supports only numbered footnotes (does it?). '
           'Default: no, uses figures.',
           ['--use-latex-footnotes'],
           {'default': 0, 'action': 'store_true',
@@ -47,6 +47,11 @@
           ['--footnote-references'],
           {'choices': ['superscript', 'brackets'], 'default': 'brackets',
            'metavar': '<format>'}),
+         ('Use LaTeX citations. '
+          'Default: no, uses figures which might get mixed with images.',
+          ['--use-latex-citations'],
+          {'default': 0, 'action': 'store_true',
+           'validator': frontend.validate_boolean}),
          ('Format for block quote attributions: one of "dash" (em-dash '
           'prefix), "parentheses"/"parens", or "none".  Default is "dash".',
           ['--attribution'],
@@ -112,7 +117,20 @@
           ['--use-verbatim-when-possible'],
           {'default': 0, 'action': 'store_true',
            'validator': frontend.validate_boolean}),
-          ))
+         ('Table style. "standard" with horizontal and vertical lines, '
+          '"booktabs" (LaTeX booktabs style) only horizontal lines '
+          'above and below the table and below the header or "nolines".'
+          'default: "standard"',
+          ['--table-style'],
+          {'choices': ['standard', 'booktabs','nolines'], 'default': 'standard',
+           'metavar': '<format>'}),
+          ('LaTeX graphicx package option.'
+           'Possible values are "dvips", "pdftex". "auto" includes LaTeX code '
+           'to use "pdftex" if processing with pdf(la)tex and dvips otherwise. '
+           'Default is no option.',
+           ['--graphicx-option'],
+           {'default': ''}),
+          ),)
 
     settings_defaults = {'output_encoding': 'latin-1'}
 
@@ -285,10 +303,15 @@
 
     # BUG: LaTeX has no deeper sections (actually paragrah is no
     # section either).
+    # BUG: No support for unknown document classes.  Make 'article'
+    # default?
     _class_sections = {
         'book': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
+        'scrbook': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
         'report': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
+        'scrreprt': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
         'article': ( 'section', 'subsection', 'subsubsection' ),
+        'scrartcl': ( 'section', 'subsection', 'subsubsection' ),
         }
     _deepest_section = 'subsubsection'
 
@@ -307,28 +330,183 @@
         else:
             return self._deepest_section
 
+class Table:
+    """ Manage a table while traversing. 
+        Maybe change to a mixin defining the visit/departs, but then
+        class Table internal variables are in the Translator.
+    """
+    def __init__(self,latex_type,table_style):
+        self._latex_type = latex_type
+        self._table_style = table_style
+        self._open = 0
+        # miscellaneous attributes
+        self._attrs = {}
+        self._col_width = []
+        self._rowspan = []
 
+    def open(self):
+        self._open = 1
+        self._col_specs = []
+        self.caption = None
+        self._attrs = {}
+        self._in_head = 0 # maybe context with search
+    def close(self):
+        self._open = 0
+        self._col_specs = None
+        self.caption = None
+        self._attrs = {}
+    def is_open(self):
+        return self._open
+    def used_packages(self):
+        if self._table_style == 'booktabs':
+            return '\\usepackage{booktabs}\n'
+        return ''
+    def is_open(self):
+        return self._open
+    def get_latex_type(self):
+        return self._latex_type
+    
+    def set(self,attr,value):
+        self._attrs[attr] = value
+    def get(self,attr):
+        if self._attrs.has_key(attr):
+            return self._attrs[attr]
+        return None
+    def get_vertical_bar(self):
+        if self._table_style == 'standard':
+            return '|'
+        return ''
+    # horizontal lines are drawn below a row, because we.
+    def get_opening(self):
+        return '\\begin{%s}[c]' % self._latex_type
+    def get_closing(self):
+        line = ""
+        if self._table_style == 'booktabs':
+            line = '\\bottomrule\n'
+        elif self._table_style == 'standard':
+            lines = '\\hline\n'
+        return '%s\\end{%s}' % (line,self._latex_type)
+
+    def visit_colspec(self,node):
+        self._col_specs.append(node)
+
+    def get_colspecs(self):
+        """
+        Return column specification for longtable.
+
+        Assumes reST line length being 80 characters.
+        Table width is hairy.
+
+        === ===
+        ABC DEF
+        === ===
+
+        usually gets to narrow, therefore we add 1 (fiddlefactor).
+        """
+        width = 80
+
+        total_width = 0.0
+        # first see if we get too wide.
+        for node in self._col_specs:
+            colwidth = float(node['colwidth']+1) / width
+            total_width += colwidth
+        self._col_width = []
+        self._rowspan = []
+        # donot make it full linewidth
+        factor = 0.93
+        if total_width > 1.0:
+            factor /= total_width
+        bar = self.get_vertical_bar()
+        latex_table_spec = ""
+        for node in self._col_specs:
+            colwidth = factor * float(node['colwidth']+1) / width
+            self._col_width.append(colwidth+0.005)
+            self._rowspan.append(0)
+            latex_table_spec += "%sp{%.2f\\locallinewidth}" % (bar,colwidth+0.005)
+        return latex_table_spec+bar
+
+    def get_column_width(self):
+        """ return columnwidth for current cell (not multicell) 
+        """
+        return "%.2f\\locallinewidth" % self._col_width[self._cell_in_row-1]
+
+    def visit_thead(self):
+        self._in_thead = 1
+        if self._table_style == 'standard':
+            return ['\\hline\n']
+        elif self._table_style == 'booktabs':
+            return ['\\toprule\n']
+        return []
+    def depart_thead(self):
+        a = []
+        #if self._table_style == 'standard':
+        #    a.append('\\hline\n')
+        if self._table_style == 'booktabs':
+            a.append('\\midrule\n')
+        a.append('\\endhead\n')
+        # for longtable one could add firsthead, foot and lastfoot
+        self._in_thead = 0
+        return a
+    def visit_row(self):
+        self._cell_in_row = 0
+    def depart_row(self):
+        res = [' \\\\\n']
+        self._cell_in_row = None  # remove cell counter
+        for i in range(len(self._rowspan)):
+            if (self._rowspan[i]>0):
+                self._rowspan[i] -= 1
+        
+        if self._table_style == 'standard':
+            rowspans = []
+            for i in range(len(self._rowspan)):
+                if (self._rowspan[i]<=0):
+                    rowspans.append(i+1)
+            if len(rowspans)==len(self._rowspan):
+                res.append('\\hline\n')
+            else:
+                cline = ''
+                rowspans.reverse()
+                # TODO merge clines
+                while 1:
+                    try:
+                        c_start = rowspans.pop()
+                    except:
+                        break
+                    cline += '\\cline{%d-%d}\n' % (c_start,c_start)
+                res.append(cline)
+        return res
+
+    def set_rowspan(self,cell,value):
+        try:
+            self._rowspan[cell] = value
+        except:
+            pass
+    def get_rowspan(self,cell):
+        try:
+            return self._rowspan[cell]
+        except:
+            return 0
+    def get_entry_number(self):
+        return self._cell_in_row
+    def visit_entry(self):
+        self._cell_in_row += 1
+
+        
 class LaTeXTranslator(nodes.NodeVisitor):
     # When options are given to the documentclass, latex will pass them
     # to other packages, as done with babel.
     # Dummy settings might be taken from document settings
 
-    d_paper = 'a4paper' # papersize
-    d_margins = '2cm'
-
     latex_head = '\\documentclass[%s]{%s}\n'
     encoding = '\\usepackage[%s]{inputenc}\n'
     linking = '\\usepackage[colorlinks=%s,linkcolor=%s,urlcolor=%s]{hyperref}\n'
-    geometry = '\\usepackage[%s,margin=%s,nohead]{geometry}\n'
     stylesheet = '\\input{%s}\n'
     # add a generated on day , machine by user using docutils version.
     generator = '%% generator Docutils: http://docutils.sourceforge.net/\n'
 
     # use latex tableofcontents or let docutils do it.
     use_latex_toc = 0
-    # table kind: if 0 tabularx (single page), 1 longtable
-    # maybe should be decided on row count.
-    use_longtable = 1
+
     # TODO: use mixins for different implementations.
     # list environment for option-list. else tabularx
     use_optionlist_for_option_list = 1
@@ -354,8 +532,10 @@
         self.use_latex_toc = settings.use_latex_toc
         self.use_latex_docinfo = settings.use_latex_docinfo
         self.use_latex_footnotes = settings.use_latex_footnotes
+        self._use_latex_citations = settings.use_latex_citations
         self.hyperlink_color = settings.hyperlink_color
         self.compound_enumerators = settings.compound_enumerators
+        self.fontenc = ''
         self.section_prefix_for_enumerators = (
             settings.section_prefix_for_enumerators)
         self.section_enumerator_separator = (
@@ -377,15 +557,47 @@
                     self.babel.get_language()
 
         self.d_class = DocumentClass(settings.documentclass)
+        # object for a table while proccessing.
+        self.active_table = Table('longtable',settings.table_style)
 
+        # HACK.  Should have more sophisticated typearea handling.
+        if settings.documentclass.find('scr') == -1:
+            self.typearea = '\\usepackage[DIV12]{typearea}\n'
+        else:
+            if self.d_options.find('DIV') == -1 and self.d_options.find('BCOR') == -1:
+                self.typearea = '\\typearea{12}\n'
+            else:
+                self.typearea = ''
+
+        if self.fontenc == 'T1':
+            fontenc = '\\usepackage[T1]{fontenc}\n'
+        else:
+            fontenc = ''
+
+        if self.settings.graphicx_option == '':
+            self.graphicx_package = '\\usepackage{graphicx}\n'
+        elif self.settings.graphicx_option.lower() == 'auto':
+            self.graphicx_package = '\n'.join(
+                ('%Check if we are compiling under latex or pdflatex',
+                 '\\ifx\\pdftexversion\\undefined',
+                 '  \\usepackage{graphicx}',
+                 '\\else',
+                 '  \\usepackage[pdftex]{graphicx}',
+                 '\\fi\n'))
+        else:
+            self.graphicx_package = (
+                '\\usepackage[%s]{graphicx}\n' % self.settings.graphicx_option)
+
         self.head_prefix = [
               self.latex_head % (self.d_options,self.settings.documentclass),
               '\\usepackage{babel}\n',     # language is in documents settings.
+              fontenc,
               '\\usepackage{shortvrb}\n',  # allows verb in footnotes.
               self.encoding % self.to_latex_encoding(settings.output_encoding),
               # * tabularx: for docinfo, automatic width of columns, always on one page.
               '\\usepackage{tabularx}\n',
               '\\usepackage{longtable}\n',
+              self.active_table.used_packages(),
               # possible other packages.
               # * fancyhdr
               # * ltxtable is a combination of tabularx and longtable (pagebreaks).
@@ -394,13 +606,12 @@
               # extra space between text in tables and the line above them
               '\\setlength{\\extrarowheight}{2pt}\n',
               '\\usepackage{amsmath}\n',   # what fore amsmath.
-              '\\usepackage{graphicx}\n',
+              self.graphicx_package,
               '\\usepackage{color}\n',
               '\\usepackage{multirow}\n',
+              '\\usepackage{ifthen}\n',   # before hyperref!
               self.linking % (self.colorlinks, self.hyperlink_color, self.hyperlink_color),
-              # geometry and fonts might go into style.tex.
-              self.geometry % (self.d_paper, self.d_margins),
-              #
+              self.typearea,
               self.generator,
               # latex lengths
               '\\newlength{\\admonitionwidth}\n',
@@ -443,7 +654,6 @@
         self.context = []
         self.topic_class = ''
         # column specification for tables
-        self.colspecs = []
         self.table_caption = None
         # do we have one or more authors
         self.author_stack = None
@@ -470,6 +680,8 @@
         # them into a compound enumeration
         self._enumeration_counters = []
 
+        self._bibitems = []
+
         # docinfo.
         self.docinfo = None
         # inside literal block: no quote mangling.
@@ -527,6 +739,23 @@
     def language_label(self, docutil_label):
         return self.language.labels[docutil_label]
 
+    def utf8_to_latex(self,text):
+        # see LaTeX codec http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252124
+        # Only some special chracters are translated, for documents with many utf-8
+        # chars one should use the LaTeX unicode package.
+        latex_equivalents = {
+            u'\u00A0' : '~',
+            u'\u00A9' : '{\\copyright}',
+            u'\u2013' : '{--}',
+            u'\u2014' : '{---}',
+            u'\u2020' : '{\\dag}',
+            u'\u2021' : '{\\ddag}',
+            u'\u21d4' : '{$\\Leftrightarrow$}',
+                }
+        for uchar in latex_equivalents.keys():
+            text = text.replace(uchar,latex_equivalents[uchar])
+        return text
+
     def encode(self, text):
         """
         Encode special characters in `text` & return.
@@ -563,7 +792,6 @@
             text = text.replace(">", '{\\textgreater}')
         # then
         text = text.replace("&", '{\\&}')
-        text = text.replace("_", '{\\_}')
         # the ^:
         # * verb|^| does not work in mbox.
         # * mathmode has wedge. hat{~} would also work.
@@ -575,10 +803,19 @@
         if self.literal_block or self.literal:
             # pdflatex does not produce doublequotes for ngerman.
             text = self.babel.double_quotes_in_tt(text)
+            if self.fontenc == 'T1': 
+                # make sure "--" does not become a "-".
+                # the same for "<<" and ">>".
+                text = text.replace("--","-{}-").replace("--","-{}-")
+                text = text.replace(">>",">{}>").replace(">>",">{}>")
+                text = text.replace("<<","<{}<").replace("<<","<{}<")
+            # replace underline by underlined blank, because this has correct width.
+            text = text.replace("_", '{\\underline{ }}')
         else:
             text = self.babel.quote_quotes(text)
-        if self.insert_newline:
-            # HACK: insert a blank before the newline, to avoid
+            text = text.replace("_", '{\\_}')
+        if self.insert_newline or self.literal_block:
+            # Insert a blank before the newline, to avoid
             # ! LaTeX Error: There's no line here to end.
             text = text.replace("\n", '~\\\\\n')
         elif self.mbox_newline:
@@ -589,10 +826,12 @@
                 closings = ""
                 openings = ""
             text = text.replace("\n", "%s}\\\\\n\\mbox{%s" % (closings,openings))
+        # lines starting with "[" give errors.
+        text = text.replace('[', '{[}')
         if self.insert_none_breaking_blanks:
             text = text.replace(' ', '~')
-        # unicode !!!
-        text = text.replace(u'\u2020', '{$\\dagger$}')
+        if self.settings.output_encoding != 'utf-8':
+            text = self.utf8_to_latex(text)
         return text
 
     def attval(self, text,
@@ -709,28 +948,46 @@
     def depart_caution(self, node):
         self.depart_admonition()
 
-    def visit_citation(self, node):
-        self.visit_footnote(node)
-
-    def depart_citation(self, node):
-        self.depart_footnote(node)
-
     def visit_title_reference(self, node):
         self.body.append( '\\titlereference{' )
 
     def depart_title_reference(self, node):
         self.body.append( '}' )
 
+    def visit_citation(self, node):
+        # TODO maybe use cite bibitems
+        if self._use_latex_citations:
+            self.context.append(len(self.body))
+        else:
+            self.body.append('\\begin{figure}[b]')
+            self.body.append('\\hypertarget{%s}' % node['id'])
+
+    def depart_citation(self, node):
+        if self._use_latex_citations:
+            size = self.context.pop()
+            label = self.body[size]
+            text = ''.join(self.body[size+1:])
+            del self.body[size:]
+            self._bibitems.append([label, text])
+        else:
+            self.body.append('\\end{figure}\n')
+
     def visit_citation_reference(self, node):
-        href = ''
-        if node.has_key('refid'):
-            href = node['refid']
-        elif node.has_key('refname'):
-            href = self.document.nameids[node['refname']]
-        self.body.append('[\\hyperlink{%s}{' % href)
+        if self._use_latex_citations:
+            self.body.append('\\cite{')
+        else:
+            href = ''
+            if node.has_key('refid'):
+                href = node['refid']
+            elif node.has_key('refname'):
+                href = self.document.nameids[node['refname']]
+            self.body.append('[\\hyperlink{%s}{' % href)
 
     def depart_citation_reference(self, node):
-        self.body.append('}]')
+        if self._use_latex_citations:
+            self.body.append('}')
+        else:
+            self.body.append('}]')
 
     def visit_classifier(self, node):
         self.body.append( '(\\textbf{' )
@@ -739,10 +996,7 @@
         self.body.append( '})\n' )
 
     def visit_colspec(self, node):
-        if self.use_longtable:
-            self.colspecs.append(node)
-        else:
-            self.context[-1] += 1
+        self.active_table.visit_colspec(node)
 
     def depart_colspec(self, node):
         pass
@@ -871,12 +1125,25 @@
 
     def visit_document(self, node):
         self.body_prefix.append('\\begin{document}\n')
+        # BUG: \maketitle without title (i.e. --no-doc-title) adds
+        # unnecessary vspace.
         self.body_prefix.append('\\maketitle\n\n')
         # alternative use titlepage environment.
         # \begin{titlepage}
         self.body.append('\n\\setlength{\\locallinewidth}{\\linewidth}\n')
 
     def depart_document(self, node):
+        # TODO insertion point of bibliography should none automatic.
+        if self._use_latex_citations and len(self._bibitems)>0:
+            widest_label = ""
+            for bi in self._bibitems:
+                if len(widest_label)<len(bi[0]):
+                    widest_label = bi[0]
+            self.body.append('\n\\begin{thebibliography}{%s}\n'%widest_label)
+            for bi in self._bibitems:
+                self.body.append('\\bibitem[%s]{%s}{%s}\n' % (bi[0], bi[0], bi[1]))
+            self.body.append('\\end{thebibliography}\n')
+            
         self.body_suffix.append('\\end{document}\n')
 
     def visit_emphasis(self, node):
@@ -888,33 +1155,41 @@
         self.literal_block_stack.pop()
 
     def visit_entry(self, node):
+        self.active_table.visit_entry()
         # cell separation
-        column_one = 1
-        if self.context[-1] > 0:
-            column_one = 0
-        if not column_one:
+        if self.active_table.get_entry_number() == 1:
+            # if the firstrow is a multirow, this actually is the second row.
+            # this gets hairy if rowspans follow each other.
+            if self.active_table.get_rowspan(0):
+                self.body.append(' & ')
+                self.active_table.visit_entry() # increment cell count
+        else:
             self.body.append(' & ')
 
         # multi{row,column}
+        # IN WORK BUG TODO HACK continues here
+        # multirow in LaTeX simply will enlarge the cell over several rows
+        # (the following n if n is positive, the former if negative).
         if node.has_key('morerows') and node.has_key('morecols'):
-            raise NotImplementedError('LaTeX can\'t handle cells that '
-            'span multiple rows *and* columns, sorry.')
-        atts = {}
+            raise NotImplementedError('Cells that '
+            'span multiple rows *and* columns are not supported, sorry.')
         if node.has_key('morerows'):
-            raise NotImplementedError('multiple rows are not working (yet), sorry.')
             count = node['morerows'] + 1
-            self.body.append('\\multirow{%d}*{' % count)
+            self.active_table.set_rowspan(self.active_table.get_entry_number()-1,count)
+            self.body.append('\\multirow{%d}{%s}{' % \
+                    (count,self.active_table.get_column_width()))
             self.context.append('}')
             # BUG following rows must have empty cells.
         elif node.has_key('morecols'):
             # the vertical bar before column is missing if it is the first column.
             # the one after always.
-            if column_one:
-                bar = '|'
+            if self.active_table.get_entry_number() == 1:
+                bar1 = self.active_table.get_vertical_bar()
             else:
-                bar = ''
+                bar1 = ''
             count = node['morecols'] + 1
-            self.body.append('\\multicolumn{%d}{%sl|}{' % (count, bar))
+            self.body.append('\\multicolumn{%d}{%sl%s}{' % \
+                    (count, bar1, self.active_table.get_vertical_bar()))
             self.context.append('}')
         else:
             self.context.append('')
@@ -929,8 +1204,17 @@
     def depart_entry(self, node):
         self.body.append(self.context.pop()) # header / not header
         self.body.append(self.context.pop()) # multirow/column
-        self.context[-1] += 1
+        # if following row is spanned from above.
+        if self.active_table.get_rowspan(self.active_table.get_entry_number()):
+           self.body.append(' & ')
+           self.active_table.visit_entry() # increment cell count
 
+    def visit_row(self, node):
+        self.active_table.visit_row()
+
+    def depart_row(self, node):
+        self.body.extend(self.active_table.depart_row())
+
     def visit_enumerated_list(self, node):
         # We create our own enumeration list environment.
         # This allows to set the style and starting value
@@ -1034,10 +1318,10 @@
             self.body.append(':]')
 
     def visit_figure(self, node):
-        self.body.append( '\\begin{figure}\n' )
+        self.body.append( '\\begin{figure}[htbp]\\begin{center}\n' )
 
     def depart_figure(self, node):
-        self.body.append( '\\end{figure}\n' )
+        self.body.append( '\\end{center}\\end{figure}\n' )
 
     def visit_footer(self, node):
         self.context.append(len(self.body))
@@ -1054,15 +1338,14 @@
             num,text = node.astext().split(None,1)
             num = self.encode(num.strip())
             self.body.append('\\footnotetext['+num+']')
-            self.body.append('{'+self.encode(text)+'}')
-            raise nodes.SkipNode
+            self.body.append('{')
         else:
             self.body.append('\\begin{figure}[b]')
             self.body.append('\\hypertarget{%s}' % node['id'])
 
     def depart_footnote(self, node):
         if self.use_latex_footnotes:
-            self.body.append('}')
+            self.body.append('}\n')
         else:
             self.body.append('\\end{figure}\n')
 
@@ -1070,7 +1353,6 @@
         if self.use_latex_footnotes:
             self.body.append("\\footnotemark["+self.encode(node.astext())+"]")
             raise nodes.SkipNode
-            return
         href = ''
         if node.has_key('refid'):
             href = node['refid']
@@ -1092,6 +1374,20 @@
             return
         self.body.append('}%s' % self.context.pop())
 
+    # footnote/citation label
+    def visit_label(self, node):
+        if isinstance(node.parent, nodes.footnote) and self.use_latex_footnotes:
+            raise nodes.SkipNode
+        elif isinstance(node.parent, nodes.citation) and self._use_latex_citations:
+            pass
+        else:
+            self.body.append('[')
+
+    def depart_label(self, node):
+        if isinstance(node.parent, nodes.citation) and self._use_latex_citations:
+            return
+        self.body.append(']')
+
     # elements generated by the framework e.g. section numbers.
     def visit_generated(self, node):
         pass
@@ -1120,12 +1416,12 @@
         pre = []                        # in reverse order
         post = ['\\includegraphics{%s}' % attrs['uri']]
         inline = isinstance(node.parent, nodes.TextElement)
-        if 'scale' in attrs:
+        if attrs.has_key('scale'):
             # Could also be done with ``scale`` option to
             # ``\includegraphics``; doing it this way for consistency.
             pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,))
             post.append('}')
-        if 'align' in attrs:
+        if attrs.has_key('align'):
             align_prepost = {
                 # By default latex aligns the top of an image.
                 (1, 'top'): ('', ''),
@@ -1165,13 +1461,6 @@
     def depart_interpreted(self, node):
         self.depart_literal(node)
 
-    def visit_label(self, node):
-        # footnote/citation label
-        self.body.append('[')
-
-    def depart_label(self, node):
-        self.body.append(']')
-
     def visit_legend(self, node):
         self.body.append('{\\small ')
 
@@ -1184,10 +1473,11 @@
         * inline markup is supported.
         * serif typeface
 
-        mbox would stop LaTeX from wrapping long lines.
         """
         self.body.append('\\begin{flushleft}\n')
         self.insert_none_breaking_blanks = 1
+        # mbox would stop LaTeX from wrapping long lines.
+        # but line_blocks are allowed to wrap.
         self.line_block_without_mbox = 1
         if self.line_block_without_mbox:
             self.insert_newline = 1
@@ -1205,7 +1495,7 @@
         self.body.append('\n\\end{flushleft}\n')
 
     def visit_list_item(self, node):
-        # HACK append "{}" in case the next character is "[", which would break
+        # Append "{}" in case the next character is "[", which would break
         # LaTeX's list environment (no numbering and the "[" is not printed).
         self.body.append('\\item {} ')
 
@@ -1228,8 +1518,6 @@
         blocks of text, where the inline markup is not recognized,
         but are also the product of the parsed-literal directive,
         where the markup is respected.
-        
-        mbox stops LaTeX from wrapping long lines.
         """
         # In both cases, we want to use a typewriter/monospaced typeface.
         # For "real" literal-blocks, we can use \verbatim, while for all
@@ -1239,34 +1527,39 @@
         # siblings the compose this node: if it is composed by a
         # single element, it's surely is either a real one, otherwise
         # it's a parsed-literal that does not contain any markup.
-        # 
+        #
         if (self.settings.use_verbatim_when_possible and (len(node) == 1)
               # in case of a parsed-literal containing just a "**bold**" word:
               and isinstance(node[0], nodes.Text)):
             self.verbatim = 1
-            self.body.append('\\begin{verbatim}\n')
+            self.body.append('\\begin{quote}\\begin{verbatim}\n')
         else:
             self.literal_block = 1
             self.insert_none_breaking_blanks = 1
-            self.body.append('\\begin{ttfamily}\\begin{flushleft}\n')
-            self.mbox_newline = 1
-            if self.mbox_newline:
-                self.body.append('\\mbox{')
+            if self.active_table.is_open():
+                self.body.append('\n{\\ttfamily \\raggedright \\noindent\n')
+            else:
+                # no quote inside tables, to avoid vertical sppace between
+                # table border and literal block.
+                # BUG: fails if normal text preceeds the literal block.
+                self.body.append('\\begin{quote}')
+                self.body.append('{\\ttfamily \\raggedright \\noindent\n')
             # * obey..: is from julien and never worked for me (grubert).
             #   self.body.append('{\\obeylines\\obeyspaces\\ttfamily\n')
 
     def depart_literal_block(self, node):
         if self.verbatim:
-            self.body.append('\n\\end{verbatim}\n')
+            self.body.append('\n\\end{verbatim}\\end{quote}\n')
             self.verbatim = 0
         else:
-            if self.mbox_newline:
-                self.body.append('}')
-            self.body.append('\n\\end{flushleft}\\end{ttfamily}\n')
+            if self.active_table.is_open():
+                self.body.append('\n}\n')
+            else:
+                self.body.append('\n')
+                self.body.append('}\\end{quote}\n')
             self.insert_none_breaking_blanks = 0
-            self.mbox_newline = 0
+            self.literal_block = 0
             # obey end: self.body.append('}\n')
-            self.literal_block = 0
 
     def visit_meta(self, node):
         self.body.append('[visit_meta]\n')
@@ -1302,7 +1595,6 @@
         if self.use_optionlist_for_option_list:
             self.body.append('\\item [')
         else:
-            atts = {}
             if len(node.astext()) > 14:
                 self.body.append('\\multicolumn{2}{l}{')
                 self.context.append('} \\\\\n  ')
@@ -1398,14 +1690,6 @@
     def depart_revision(self, node):
         self.depart_docinfo_item(node)
 
-    def visit_row(self, node):
-        self.context.append(0)
-
-    def depart_row(self, node):
-        self.context.pop()  # remove cell counter
-        self.body.append(' \\\\ \\hline\n')
-        # BUG if multirow cells \cline{x-y}
-
     def visit_section(self, node):
         self.section_level += 1
         # Initialize counter for potential subsections:
@@ -1482,71 +1766,20 @@
         if node['level'] < self.document.reporter['writer'].report_level:
             raise nodes.SkipNode
 
-
     def depart_system_message(self, node):
         self.body.append('\n')
 
-    def get_colspecs(self):
-        """
-        Return column specification for longtable.
-
-        Assumes reST line length being 80 characters.
-        Table width is hairy.
-
-        === ===
-        ABC DEF
-        === ===
-
-        usually gets to narrow, therefore we add 1 (fiddlefactor).
-        """
-        width = 80
-
-        total_width = 0.0
-        # first see if we get too wide.
-        for node in self.colspecs:
-            colwidth = float(node['colwidth']+1) / width
-            total_width += colwidth
-        # donot make it full linewidth
-        factor = 0.93
-        if total_width > 1.0:
-            factor /= total_width
-
-        latex_table_spec = ""
-        for node in self.colspecs:
-            colwidth = factor * float(node['colwidth']+1) / width
-            latex_table_spec += "|p{%.2f\\locallinewidth}" % (colwidth+0.005)
-        self.colspecs = []
-        return latex_table_spec+"|"
-
     def visit_table(self, node):
-        if self.use_longtable:
-            self.body.append('\n\\begin{longtable}[c]')
-        else:
-            self.body.append('\n\\begin{tabularx}{\\linewidth}')
-            self.context.append('table_sentinel') # sentinel
-            self.context.append(0) # column counter
+        if self.active_table.is_open():
+            print 'nested tables are not supported'
+            raise AssertionError
+        self.active_table.open()
+        self.body.append('\n' + self.active_table.get_opening())
 
     def depart_table(self, node):
-        if self.use_longtable:
-            self.body.append('\\end{longtable}\n')
-        else:
-            self.body.append('\\end{tabularx}\n')
-            sentinel = self.context.pop()
-            if sentinel != 'table_sentinel':
-                print 'context:', self.context + [sentinel]
-                raise AssertionError
+        self.body.append(self.active_table.get_closing() + '\n')
+        self.active_table.close()
 
-    def table_preamble(self):
-        if self.use_longtable:
-            self.body.append('{%s}\n' % self.get_colspecs())
-            if self.table_caption:
-                self.body.append('\\caption{%s}\\\\\n' % self.table_caption)
-                self.table_caption = None
-        else:
-            if self.context[-1] != 'table_sentinel':
-                self.body.append('{%s}' % ('|X' * self.context.pop() + '|'))
-                self.body.append('\n\\hline')
-
     def visit_target(self, node):
         # BUG: why not (refuri or refid or refname) means not footnote ?
         if not (node.has_key('refuri') or node.has_key('refid')
@@ -1562,13 +1795,12 @@
     def visit_tbody(self, node):
         # BUG write preamble if not yet done (colspecs not [])
         # for tables without heads.
-        if self.colspecs:
+        if not self.active_table.get('preamble written'):
             self.visit_thead(None)
-            self.depart_thead(None)
-        self.body.append('%[visit_tbody]\n')
+            # self.depart_thead(None)
 
     def depart_tbody(self, node):
-        self.body.append('%[depart_tbody]\n')
+        pass
 
     def visit_term(self, node):
         self.body.append('\\item[')
@@ -1586,30 +1818,28 @@
         pass
 
     def visit_thead(self, node):
-        # number_of_columns will be zero after get_colspecs.
-        # BUG ! push onto context for depart to pop it.
-        number_of_columns = len(self.colspecs)
-        self.table_preamble()
-        #BUG longtable needs firstpage and lastfooter too.
-        self.body.append('\\hline\n')
+        self.body.append('{%s}\n' % self.active_table.get_colspecs())
+        if self.active_table.caption:
+            self.body.append('\\caption{%s}\\\\\n' % self.active_table.caption)
+        self.active_table.set('preamble written',1)
+        # TODO longtable supports firsthead and lastfoot too.
+        self.body.extend(self.active_table.visit_thead())
 
     def depart_thead(self, node):
-        if self.use_longtable:
-            # the table header written should be on every page
-            # => \endhead
-            self.body.append('\\endhead\n')
-            # and the firsthead => \endfirsthead
-            # BUG i want a "continued from previous page" on every not
-            # firsthead, but then we need the header twice.
-            #
-            # there is a \endfoot and \endlastfoot too.
-            # but we need the number of columns to
-            # self.body.append('\\multicolumn{%d}{c}{"..."}\n' % number_of_columns)
-            # self.body.append('\\hline\n\\endfoot\n')
-            # self.body.append('\\hline\n')
-            # self.body.append('\\endlastfoot\n')
+        # the table header written should be on every page
+        # => \endhead
+        self.body.extend(self.active_table.depart_thead())
+        # and the firsthead => \endfirsthead
+        # BUG i want a "continued from previous page" on every not
+        # firsthead, but then we need the header twice.
+        #
+        # there is a \endfoot and \endlastfoot too.
+        # but we need the number of columns to
+        # self.body.append('\\multicolumn{%d}{c}{"..."}\n' % number_of_columns)
+        # self.body.append('\\hline\n\\endfoot\n')
+        # self.body.append('\\hline\n')
+        # self.body.append('\\endlastfoot\n')
 
-
     def visit_tip(self, node):
         self.visit_admonition(node, 'tip')
 
@@ -1630,14 +1860,13 @@
                 if l>0:
                     l = l-1
                 # pdftex does not like "_" subscripts in titles
-                text = node.astext().replace("_","\\_")
+                text = self.encode(node.astext())
                 self.body.append('\\pdfbookmark[%d]{%s}{%s}\n' % \
                         (l,text,node.parent['id']))
 
     def visit_title(self, node):
         """Only 3 section levels are supported by LaTeX article (AFAIR)."""
 
-
         if isinstance(node.parent, nodes.topic):
             # section titles before the table of contents.
             self.bookmark(node)
@@ -1646,12 +1875,15 @@
             self.body.append('\\subsection*{~\\hfill ')
             # the closing brace for subsection.
             self.context.append('\\hfill ~}\n')
-        elif isinstance(node.parent, nodes.sidebar):
+        # TODO: for admonition titles before the first section
+        # either specify every possible node or ... ?
+        elif isinstance(node.parent, nodes.sidebar) \
+        or isinstance(node.parent, nodes.admonition):
             self.body.append('\\textbf{\\large ')
             self.context.append('}\n\\smallskip\n')
         elif isinstance(node.parent, nodes.table):
             # caption must be written after column spec
-            self.table_caption = node.astext()
+            self.active_table.caption = node.astext()
             raise nodes.SkipNode
         elif self.section_level == 0:
             # document title
@@ -1690,8 +1922,6 @@
         self.body.append('\n')
 
     def visit_rubric(self, node):
-#        self.body.append('\\hfill {\\color{red}\\bfseries{}')
-#        self.context.append('} \\hfill ~\n')
         self.body.append('\\rubric{')
         self.context.append('}\n')
 
@@ -1705,7 +1935,6 @@
         self.body.append('\n\n')
 
     def depart_transition(self, node):
-        #self.body.append('[depart_transition]')
         pass
 
     def visit_version(self, node):

Modified: Zope/trunk/lib/python/reStructuredText/__init__.py
===================================================================
--- Zope/trunk/lib/python/reStructuredText/__init__.py	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/reStructuredText/__init__.py	2004-07-26 17:36:58 UTC (rev 26767)
@@ -15,6 +15,19 @@
 This implementation requires docutils 0.3.4+ from http://docutils.sf.net/
 """
 
+try:
+    import docutils
+except ImportError:
+    raise ImportError, 'Please install docutils 0.3.3+ from http://docutils.sourceforge.net/#download.'
+
+version = docutils.__version__.split('.')
+if version < ['0', '3', '3']:
+    raise ImportError, """Old version of docutils found:
+Got: %(version)s, required: 0.3.3+
+Please remove docutils from %(path)s and replace it with a new version. You
+can download docutils at http://docutils.sourceforge.net/#download.
+""" % {'version' : docutils.__version__, 'path' : docutils.__path__[0] }
+
 import sys, os, locale
 from App.config import getConfiguration
 from docutils.core import publish_parts
@@ -28,10 +41,10 @@
 default_level = 3
 initial_header_level = getConfiguration().rest_header_level or default_level
 
-# default language
-default_lang = getConfiguration().locale or locale.getdefaultlocale()[0]
-if default_lang and '_' in default_lang:
-    default_lang = default_lang[:default_lang.index('_')]
+# default language used for internal translations and language mappings for DTD
+# elements
+default_lang = 'en'
+default_language_code = getConfiguration().rest_language_code or default_language
 
 
 class Warnings:
@@ -48,7 +61,7 @@
            stylesheet='default.css',
            input_encoding=default_input_encoding,
            output_encoding=default_output_encoding,
-           language_code=default_lang,
+           language_code=default_language_code,
            initial_header_level = initial_header_level,
            settings = {}):
     """get the rendered parts of the document the and warning object
@@ -60,7 +73,7 @@
     settings['stylesheet'] = stylesheet
     settings['language_code'] = language_code
     # starting level for <H> elements:
-    settings['initial_header_level'] = initial_header_level
+    settings['initial_header_level'] = initial_header_level + 1
     # set the reporting level to something sane:
     settings['report_level'] = report_level
     # don't break if we get errors:
@@ -80,7 +93,7 @@
          stylesheet='default.css',
          input_encoding=default_input_encoding,
          output_encoding=default_output_encoding,
-         language_code=default_lang,
+         language_code=default_language_code,
          initial_header_level = initial_header_level,
          warnings = None,
          settings = {}):
@@ -119,17 +132,23 @@
                                    initial_header_level = initial_header_level,
                                    settings = settings)
 
-    output = ('<h%(level)s class="title">%(title)s</h%(level)s>\n'
-              '%(docinfo)s%(body)s' % {
+    header = '<h%(level)s class="title">%(title)s</h%(level)s>\n' % {
                   'level': initial_header_level,
                   'title': parts['title'],
+             }
+
+    body = '%(docinfo)s%(body)s' % {
                   'docinfo': parts['docinfo'],
-                  'body': parts['body']
-              }).encode(output_encoding)
+                  'body': parts['body'],
+             }
 
+    if parts['title']:
+        output = header + body
+    else:
+        output = body
+
     warnings = ''.join(warning_stream.messages)
 
-    return output
+    return output.encode(output_encoding)
 
-
 __all__ = ("HTML", 'render')

Modified: Zope/trunk/lib/python/reStructuredText/reStructuredText.txt
===================================================================
--- Zope/trunk/lib/python/reStructuredText/reStructuredText.txt	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/lib/python/reStructuredText/reStructuredText.txt	2004-07-26 17:36:58 UTC (rev 26767)
@@ -3,8 +3,9 @@
 =======================================
 :Author: David Goodger
 :Contact: goodger at users.sourceforge.net
-:Revision: $Revision: 1.2 $
-:Date: $Date: 2003/02/01 15:45:16 $
+:Revision: $Revision: 1.64 $
+:Date: $Date: 2004/07/24 18:35:08 $
+:Copyright: This document has been placed in the public domain.
 
 .. Note::
 
@@ -13,8 +14,8 @@
    reStructuredText, please read `A ReStructuredText Primer`_ and the
    `Quick reStructuredText`_ user reference first.
 
-.. _A ReStructuredText Primer: ../../docs/rst/quickstart.html
-.. _Quick reStructuredText: ../../docs/rst/quickref.html
+.. _A ReStructuredText Primer: ../../user/rst/quickstart.html
+.. _Quick reStructuredText: ../../user/rst/quickref.html
 
 
 reStructuredText_ is plaintext that uses simple and intuitive
@@ -123,8 +124,9 @@
 
 - `Literal blocks`_::
 
-      Literal blocks are indented, and indicated with a double-colon
-      ("::") at the end of the preceding paragraph (right here -->)::
+      Literal blocks are either indented or line-prefix-quoted blocks,
+      and indicated with a double-colon ("::") at the end of the
+      preceding paragraph (right here -->)::
 
           if literal_block:
               text = 'is left as-is'
@@ -137,7 +139,7 @@
 
           This theory, that is mine, is mine.
 
-          Anne Elk (Miss)
+          -- Anne Elk (Miss)
 
 - `Doctest blocks`_::
 
@@ -207,11 +209,11 @@
  Syntax Details
 ----------------
 
-Descriptions below list "DTD elements" (XML "generic identifiers")
-corresponding to syntax constructs.  For details on the hierarchy of
-elements, please see `Docutils Document Tree Structure`_ and the
-`Generic Plaintext Document Interface DTD`_ XML document type
-definition.
+Descriptions below list "doctree elements" (document tree element
+names; XML DTD generic identifiers) corresponding to syntax
+constructs.  For details on the hierarchy of elements, please see `The
+Docutils Document Tree`_ and the `Docutils Generic DTD`_ XML document
+type definition.
 
 
 Whitespace
@@ -343,13 +345,17 @@
 the markup.  In reStructuredText we use the backslash, commonly used
 as an escaping character in other domains.
 
-A backslash followed by any character escapes that character.  The
-escaped character represents the character itself, and is prevented
-from playing a role in any markup interpretation.  The backslash is
-removed from the output.  A literal backslash is represented by two
-backslashes in a row (the first backslash "escapes" the second,
-preventing it being interpreted in an "escaping" role).
+A backslash followed by any character (except whitespace characters)
+escapes that character.  The escaped character represents the
+character itself, and is prevented from playing a role in any markup
+interpretation.  The backslash is removed from the output.  A literal
+backslash is represented by two backslashes in a row (the first
+backslash "escapes" the second, preventing it being interpreted in an
+"escaping" role).
 
+Backslash-escaped whitespace characters are removed from the document.
+This allows for character-level `inline markup`_.
+
 There are two contexts in which backslashes have no special meaning:
 literal blocks and inline literals.  In these contexts, a single
 backslash represents a literal backslash, without having to double up.
@@ -421,7 +427,7 @@
 Document
 --------
 
-DTD element: document.
+Doctree element: document.
 
 The top-level element of a parsed reStructuredText document is the
 "document" element.  After initial parsing, the document element is a
@@ -437,14 +443,15 @@
 subtitle explicitly in reStructuredText.  Instead, a lone top-level
 section title (see Sections_ below) can be treated as the document
 title.  Similarly, a lone second-level section title immediately after
-the "document title" can become the document subtitle.  See the
-`DocTitle transform`_ for details.
+the "document title" can become the document subtitle.  The rest of
+the sections are then lifted up a level or two.  See the `DocTitle
+transform`_ for details.
 
 
 Sections
 --------
 
-DTD elements: section, title.
+Doctree elements: section, title.
 
 Sections are identified through their titles, which are marked up with
 adornment: "underlines" below the title text, or underlines and
@@ -467,7 +474,7 @@
    Some characters are more suitable than others.  The following are
    recommended::
 
-       = - ` : ' " ~ ^ _ * + # < >
+       = - ` : . ' " ~ ^ _ * + #
 
 Rather than imposing a fixed number and order of section title
 adornment styles, the order enforced will be the order as encountered.
@@ -538,7 +545,7 @@
 Transitions
 -----------
 
-DTD element: transition.
+Doctree element: transition.
 
     Instead of subheads, extra space or a type ornament between
     paragraphs may be used to mark text divisions or to signal
@@ -578,7 +585,7 @@
 Paragraphs
 ----------
 
-DTD element: paragraph.
+Doctree element: paragraph.
 
 Paragraphs consist of blocks of left-aligned text with no markup
 indicating any other body element.  Blank lines separate paragraphs
@@ -601,7 +608,7 @@
 Bullet Lists
 ------------
 
-DTD elements: bullet_list, list_item.
+Doctree elements: bullet_list, list_item.
 
 A text block which begins with a "-", "*", or "+", followed by
 whitespace, is a bullet list item (a.k.a. "unordered" list item).
@@ -650,7 +657,7 @@
 Enumerated Lists
 ----------------
 
-DTD elements: enumerated_list, list_item.
+Doctree elements: enumerated_list, list_item.
 
 Enumerated lists (a.k.a. "ordered" lists) are similar to bullet lists,
 but use enumerators instead of bullets.  An enumerator consists of an
@@ -730,8 +737,8 @@
 Definition Lists
 ----------------
 
-DTD elements: definition_list, definition_list_item, term, classifier,
-definition.
+Doctree elements: definition_list, definition_list_item, term,
+classifier, definition.
 
 Each definition list item contains a term, an optional classifier, and
 a definition.  A term is a simple one-line word or phrase.  An
@@ -784,7 +791,7 @@
 Field Lists
 -----------
 
-DTD elements: field_list, field, field_name, field_body.
+Doctree elements: field_list, field, field_name, field_body.
 
 Field lists are used as part of an extension syntax, such as options
 for directives_, or database-like records meant for further
@@ -797,13 +804,14 @@
 
 Field lists are mappings from field names to field bodies, modeled on
 RFC822_ headers.  A field name is made up of one or more letters,
-numbers, whitespace, and punctuation, except colons (":").  Field
-names are case-insensitive.  The field name, along with a single colon
-prefix and suffix, together form the field marker.  The field marker
-is followed by whitespace and the field body.  The field body may
-contain multiple body elements, indented relative to the field marker.
-The first line after the field name marker determines the indentation
-of the field body.  For example::
+numbers, whitespace, and punctuation, except colons (":").  Inline
+markup is parsed in field names.  Field names are case-insensitive
+when further processed or transformed.  The field name, along with a
+single colon prefix and suffix, together form the field marker.  The
+field marker is followed by whitespace and the field body.  The field
+body may contain multiple body elements, indented relative to the
+field marker.  The first line after the field name marker determines
+the indentation of the field body.  For example::
 
     :Date: 2001-08-16
     :Version: 1
@@ -841,7 +849,7 @@
 Bibliographic Fields
 ````````````````````
 
-DTD elements: docinfo, author, authors, organization, contact,
+Doctree elements: docinfo, author, authors, organization, contact,
 version, status, date, copyright, field, topic.
 
 When a field list is the first non-comment element in a document
@@ -851,7 +859,7 @@
 copyright page.
 
 Certain registered field names (listed below) are recognized and
-transformed to the corresponding DTD elements, most becoming child
+transformed to the corresponding doctree elements, most becoming child
 elements of the "docinfo" element.  No ordering is required of these
 fields, although they may be rearranged to fit the document structure,
 as noted.  Unless otherwise indicated below, each of the bibliographic
@@ -860,8 +868,8 @@
 unrecognized fields will remain as generic fields in the docinfo
 element.
 
-The registered bibliographic field names and their corresponding DTD
-elements are as follows:
+The registered bibliographic field names and their corresponding
+doctree elements are as follows:
 
 - Field name "Author": author element.
 - "Authors": authors.
@@ -921,7 +929,7 @@
 text".  The dollar sign delimiters and leading RCS keyword name are
 removed.
 
-The RCS keyword processing only kicks in when all of these conditions
+The RCS keyword processing only kicks in when both of these conditions
 hold:
 
 1. The field list is in bibliographic context (first non-comment
@@ -930,14 +938,11 @@
 
 2. The field name is a recognized bibliographic field name.
 
-3. The sole contents of the field is an expanded RCS keyword, of the
-   form "$Keyword: data $".
 
-
 Option Lists
 ------------
 
-DTD elements: option_list, option_list_item, option_group, option,
+Doctree elements: option_list, option_list_item, option_group, option,
 option_string, option_argument, description.
 
 Option lists are two-column lists of command-line options and
@@ -997,8 +1002,15 @@
 Options may be followed by an argument placeholder, whose role and
 syntax should be explained in the description text.  Either a space or
 an equals sign may be used as a delimiter between options and option
-argument placeholders.
+argument placeholders; short options ("-" or "+" prefix only) may omit
+the delimiter.  Option arguments may take one of two forms:
 
+- Begins with a letter (``[a-zA-Z]``) and subsequently consists of
+  letters, numbers, underscores and hyphens (``[a-zA-Z0-9_-]``).
+- Begins with an open-angle-bracket (``<``) and ends with a
+  close-angle-bracket (``>``); any characters except angle brackets
+  are allowed internally.
+
 Multiple option "synonyms" may be listed, sharing a single
 description.  They must be separated by comma-space.
 
@@ -1021,14 +1033,15 @@
 Literal Blocks
 --------------
 
-DTD element: literal_block.
+Doctree element: literal_block.
 
-A paragraph consisting of two colons ("::") signifies that all
-following **indented** text blocks comprise a literal block.  No
-markup processing is done within a literal block.  It is left as-is,
-and is typically rendered in a monospaced typeface::
+A paragraph consisting of two colons ("::") signifies that the
+following text block(s) comprise a literal block.  The literal block
+must either be indented or quoted (see below).  No markup processing
+is done within a literal block.  It is left as-is, and is typically
+rendered in a monospaced typeface::
 
-    This is a typical paragraph.  A literal block follows.
+    This is a typical paragraph.  An indented literal block follows.
 
     ::
 
@@ -1074,12 +1087,22 @@
 
           Literal block
 
-The minimum leading whitespace will be removed from each line of the
-literal block.  Other than that, all whitespace (including line
-breaks) is preserved.  Blank lines are required before and after a
-literal block, but these blank lines are not included as part of the
-literal block.
+All whitespace (including line breaks, but excluding minimum
+indentation for indented literal blocks) is preserved.  Blank lines
+are required before and after a literal block, but these blank lines
+are not included as part of the literal block.
 
+
+Indented Literal Blocks
+```````````````````````
+
+Indented literal blocks are indicated by indentation relative to the
+surrounding text (leading whitespace on each line).  The minimum
+indentation will be removed from each line of an indented literal
+block.  The literal block need not be contiguous; blank lines are
+allowed between sections of indented text.  The literal block ends
+with the end of the indentation.
+
 Syntax diagram::
 
     +------------------------------+
@@ -1087,14 +1110,53 @@
     | (ends with "::")             |
     +------------------------------+
        +---------------------------+
-       | literal block             |
+       | indented literal block    |
        +---------------------------+
 
 
+Quoted Literal Blocks
+`````````````````````
+
+Quoted literal blocks are unindented contiguous blocks of text where
+each line begins with the same non-alphanumeric printable 7-bit ASCII
+character [#]_.  A blank line ends a quoted literal block.  The
+quoting characters are preserved in the processed document.
+
+.. [#]
+   The following are all valid quoting characters::
+
+       ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
+
+   Note that these are the same characters as are valid for title
+   adornment of sections_.
+
+Possible uses include literate programming in Haskell and email
+quoting::
+
+    John Doe wrote::
+
+    >> Great idea!
+    >
+    > Why didn't I think of that?
+
+    You just did!  ;-)
+
+Syntax diagram::
+
+    +------------------------------+
+    | paragraph                    |
+    | (ends with "::")             |
+    +------------------------------+
+    +------------------------------+
+    | ">" per-line-quoted          |
+    | ">" contiguous literal block |
+    +------------------------------+
+
+
 Block Quotes
 ------------
 
-DTD element: block_quote.
+Doctree element: block_quote, attribution.
 
 A text block that is indented relative to the preceding text, without
 markup indicating it to be a literal block, is a block quote.  All
@@ -1107,6 +1169,11 @@
 
         -- Sherlock Holmes
 
+If the final block of a block quote begins with "--", "---", or a true
+em-dash (flush left within the block quote), it is interpreted as an
+attribution.  If the attribution consists of multiple lines, the left
+edges of the second and subsequent lines must align.
+
 Blank lines are required before and after a block quote, but these
 blank lines are not included as part of the block quote.
 
@@ -1119,13 +1186,16 @@
        +---------------------------+
        | block quote               |
        | (body elements)+          |
+       |                           |
+       | -- attribution text       |
+       |    (optional)             |
        +---------------------------+
 
 
 Doctest Blocks
 --------------
 
-DTD element: doctest_block.
+Doctree element: doctest_block.
 
 Doctest blocks are interactive Python sessions cut-and-pasted into
 docstrings.  They are meant to illustrate usage by example, and
@@ -1155,7 +1225,7 @@
 Tables
 ------
 
-DTD elements: table, tgroup, colspec, thead, tbody, row, entry.
+Doctree elements: table, tgroup, colspec, thead, tbody, row, entry.
 
 ReStructuredText provides two syntaxes for delineating table cells:
 `Grid Tables`_ and `Simple Tables`_.
@@ -1373,7 +1443,7 @@
 Footnotes
 `````````
 
-DTD elements: footnote, label.
+Doctree elements: footnote, label.
 
 Each footnote consists of an explicit markup start (".. "), a left
 square bracket, the footnote label, a right square bracket, and
@@ -1493,15 +1563,15 @@
 marks [#]_:
 
 - asterisk/star ("*")
-- dagger (HTML character entity "&dagger;")
-- double dagger ("&Dagger;")
-- section mark ("&sect;")
-- pilcrow or paragraph mark ("&para;")
+- dagger (HTML character entity "&dagger;", Unicode U+02020)
+- double dagger ("&Dagger;"/U+02021)
+- section mark ("&sect;"/U+000A7)
+- pilcrow or paragraph mark ("&para;"/U+000B6)
 - number sign ("#")
-- spade suit ("&spades;")
-- heart suit ("&hearts;")
-- diamond suit ("&diams;")
-- club suit ("&clubs;")
+- spade suit ("&spades;"/U+02660)
+- heart suit ("&hearts;"/U+02665)
+- diamond suit ("&diams;"/U+02666)
+- club suit ("&clubs;"/U+02663)
 
 .. [#] This list was inspired by the list of symbols for "Note
    Reference Marks" in The Chicago Manual of Style, 14th edition,
@@ -1512,7 +1582,16 @@
 If more than ten symbols are required, the same sequence will be
 reused, doubled and then tripled, and so on ("**" etc.).
 
+.. Note:: When using auto-symbol footnotes, the choice of output
+   encoding is important.  Many of the symbols used are not encodable
+   in certain common text encodings such as Latin-1 (ISO 8859-1).  The
+   use of UTF-8 for the output encoding is recommended.  An
+   alternative for HTML and XML output is to use the
+   "xmlcharrefreplace" `output encoding error handler`__.
 
+__ ../../user/config.html#output-encoding-error-handler
+
+
 Mixed Manual and Auto-Numbered Footnotes
 ........................................
 
@@ -1558,7 +1637,7 @@
 Hyperlink Targets
 `````````````````
 
-DTD element: target.
+Doctree element: target.
 
 These are also called _`explicit hyperlink targets`, to differentiate
 them from `implicit hyperlink targets`_ defined below.
@@ -1624,8 +1703,8 @@
        .. _archive:
        .. _Doc-SIG: http://mail.python.org/pipermail/doc-sig/
 
-    An inline form of internal hyperlink target is available; see
-    `Inline Internal Targets`_.
+   An inline form of internal hyperlink target is available; see
+   `Inline Internal Targets`_.
 
 2. _`External hyperlink targets` have an absolute or relative URI or
    email address in their link blocks.  For example, take the
@@ -1768,11 +1847,12 @@
 Directives
 ``````````
 
-DTD elements: depend on the directive.
+Doctree elements: depend on the directive.
 
 Directives are an extension mechanism for reStructuredText, a way of
-adding support for new constructs without adding new syntax.  All
-standard directives (those implemented and registered in the reference
+adding support for new constructs without adding new primary syntax
+(directives may support additional syntax locally).  All standard
+directives (those implemented and registered in the reference
 reStructuredText parser) are described in the `reStructuredText
 Directives`_ document, and are always available.  Any other directives
 are domain-specific, and may require special action to make them
@@ -1801,15 +1881,17 @@
 no whitespace).  Two colons are used after the directive type for
 these reasons:
 
-- To avoid clashes with common comment text like::
+- Two colons are distinctive, and unlikely to be used in common text.
 
+- Two colons avoids clashes with common comment text like::
+
       .. Danger: modify at your own risk!
 
 - If an implementation of reStructuredText does not recognize a
-  directive (i.e., the directive-handler is not installed), the entire
-  directive block (including the directive itself) will be treated as
-  a literal block, and a level-3 (error) system message generated.
-  Thus "::" is a natural choice.
+  directive (i.e., the directive-handler is not installed), a level-3
+  (error) system message is generated, and the entire directive block
+  (including the directive itself) will be included as a literal
+  block.  Thus "::" is a natural choice.
 
 The directive block is consists of any text on the first line of the
 directive after the directive marker, and any subsequent indented
@@ -1870,7 +1952,7 @@
 Substitution Definitions
 ````````````````````````
 
-DTD element: substitution_definition.
+Doctree element: substitution_definition.
 
 Substitution definitions are indicated by an explicit markup start
 (".. ") followed by a vertical bar, the substitution text, another
@@ -1889,13 +1971,15 @@
 
 `Substitution references`_ are replaced in-line by the processed
 contents of the corresponding definition (linked by matching
-substitution text).  Substitution definitions allow the power and
-flexibility of block-level directives_ to be shared by inline text.
-They are a way to include arbitrarily complex inline structures within
-text, while keeping the details out of the flow of text.  They are the
-equivalent of SGML/XML's named entities or programming language
-macros.
+substitution text).  Matches are case-sensitive but forgiving; if no
+exact match is found, a case-insensitive comparison is attempted.
 
+Substitution definitions allow the power and flexibility of
+block-level directives_ to be shared by inline text.  They are a way
+to include arbitrarily complex inline structures within text, while
+keeping the details out of the flow of text.  They are the equivalent
+of SGML/XML's named entities or programming language macros.
+
 Without the substitution mechanism, every time someone wants an
 application-specific new inline structure, they would have to petition
 for a syntax change.  In combination with existing directive syntax,
@@ -2064,7 +2148,7 @@
 Comments
 ````````
 
-DTD element: comment.
+Doctree element: comment.
 
 Arbitrary indented text may follow the explicit markup start and will
 be processed as a comment element.  No further processing is done on
@@ -2142,9 +2226,8 @@
 a text block.  The same whitespace and punctuation that serves to
 delimit words in written text is used to delimit the inline markup
 syntax constructs.  The text within inline markup may not begin or end
-with whitespace.  Arbitrary character-level markup is not supported
-[#]_; it is not possible to mark up individual characters within a
-word.  Inline markup cannot be nested.
+with whitespace.  Arbitrary `character-level inline markup`_ is
+supported although not encouraged.  Inline markup cannot be nested.
 
 There are nine inline markup constructs.  Five of the constructs use
 identical start-strings and end-strings to indicate the markup:
@@ -2183,7 +2266,7 @@
 4. Inline markup end-strings must end a text block or be immediately
    followed by whitespace or one of::
 
-       ' " ) ] } > - / : . , ; ! ?
+       ' " ) ] } > - / : . , ; ! ? \
 
 5. If an inline markup start-string is immediately preceded by a
    single or double quote, "(", "[", "{", or "<", it must not be
@@ -2245,23 +2328,41 @@
 
 - `Standalone hyperlinks`_ are the last to be recognized.
 
-.. [#] Backslash escapes can be used to allow arbitrary text to
-   immediately follow inline markup::
 
-       Python ``list``\s use square bracket syntax.
+Character-Level Inline Markup
+-----------------------------
 
-   The backslash will disappear from the processed document.  The word
-   "list" will appear as inline literal text, and the letter "s" will
-   immediately follow it as normal text, with no space in-between.
+It is possible to mark up individual characters within a word with
+backslash escapes (see `Escaping Mechanism`_ above).  Backslash
+escapes can be used to allow arbitrary text to immediately follow
+inline markup::
 
-   There is not yet any way for arbitrary text to immediately precede
-   inline markup.
+    Python ``list``\s use square bracket syntax.
 
+The backslash will disappear from the processed document.  The word
+"list" will appear as inline literal text, and the letter "s" will
+immediately follow it as normal text, with no space in-between.
 
+Arbitrary text may immediately precede inline markup using
+backslash-escaped whitespace::
+
+    Possible in *re*\ ``Structured``\ *Text*, though not encouraged.
+
+The backslashes and spaces separating "re", "Structured", and "Text"
+above will disappear from the processed document.
+
+.. CAUTION::
+
+   The use of backslash-escapes for character-level inline markup is
+   not encouraged.  Such use is ugly and detrimental to the
+   unprocessed document's readability.  Please use this feature
+   sparingly and only where absolutely necessary.
+
+
 Emphasis
 --------
 
-DTD element: emphasis.
+Doctree element: emphasis.
 
 Start-string = end-string = "*".
 
@@ -2275,7 +2376,7 @@
 Strong Emphasis
 ---------------
 
-DTD element: strong.
+Doctree element: strong.
 
 Start-string = end-string = "**".
 
@@ -2289,7 +2390,8 @@
 Interpreted Text
 ----------------
 
-DTD element: depends on the explicit or implicit role and processing.
+Doctree element: depends on the explicit or implicit role and
+processing.
 
 Start-string = end-string = "`".
 
@@ -2327,7 +2429,7 @@
 Inline Literals
 ---------------
 
-DTD element: literal.
+Doctree element: literal.
 
 Start-string = end-string = "``".
 
@@ -2356,7 +2458,7 @@
 Hyperlink References
 --------------------
 
-DTD element: reference.
+Doctree element: reference.
 
 - Named hyperlink references:
 
@@ -2427,8 +2529,16 @@
 
     See `HTML Element: \<a>`_ below.
 
-.. Caution::
+The reference text may also be omitted, in which case the URI will be
+duplicated for use as the reference text.  This is useful for relative
+URIs where the address or file name is also the desired reference
+text::
 
+    See `<a_named_relative_link>`_ or `<an_anonymous_relative_link>`__
+    for details.
+
+.. CAUTION::
+
    This construct offers easy authoring and maintenance of hyperlinks
    at the expense of general readability.  Inline URIs, especially
    long ones, inevitably interrupt the natural flow of text.  For
@@ -2441,7 +2551,7 @@
 Inline Internal Targets
 ------------------------
 
-DTD element: target.
+Doctree element: target.
 
 Start-string = "_`", end-string = "`".
 
@@ -2463,7 +2573,7 @@
 Footnote References
 -------------------
 
-DTD element: footnote_reference.
+Doctree element: footnote_reference.
 
 Start-string = "[", end-string = "]_".
 
@@ -2489,7 +2599,7 @@
 Citation References
 -------------------
 
-DTD element: citation_reference.
+Doctree element: citation_reference.
 
 Start-string = "[", end-string = "]_".
 
@@ -2508,7 +2618,7 @@
 Substitution References
 -----------------------
 
-DTD element: substitution_reference, reference.
+Doctree element: substitution_reference, reference.
 
 Start-string = "|", end-string = "|" (optionally followed by "_" or
 "__").
@@ -2519,8 +2629,9 @@
 used for the reference text in the named case.
 
 The processing system replaces substitution references with the
-processed contents of the corresponding `substitution definitions`_.
-Substitution definitions produce inline-compatible elements.
+processed contents of the corresponding `substitution definitions`_
+(which see for the definition of "correspond").  Substitution
+definitions produce inline-compatible elements.
 
 Examples::
 
@@ -2535,7 +2646,7 @@
 Standalone Hyperlinks
 ---------------------
 
-DTD element: reference.
+Doctree element: reference.
 
 Start-string = end-string = "" (empty string).
 
@@ -2558,8 +2669,8 @@
    The scheme is the name of the protocol, such as "http", "ftp",
    "mailto", or "telnet".  The scheme consists of an initial letter,
    followed by letters, numbers, and/or "+", "-", ".".  Recognition is
-   limited to known schemes, per the W3C's `Index of WWW Addressing
-   Schemes`_.
+   limited to known schemes, per the `Official IANA Registry of URI
+   Schemes`_ and the W3C's `Retired Index of WWW Addressing Schemes`_.
 
    The scheme-specific part of the resource identifier may be either
    hierarchical or opaque:
@@ -2588,7 +2699,11 @@
 
        someone at somewhere.com
 
-Punctuation at the end of a URI is not considered part of the URI.
+Punctuation at the end of a URI is not considered part of the URI,
+unless the URI is terminated by a closing angle bracket (">").
+Backslashes may be used in URIs to escape markup characters,
+specifically asterisks ("*") and underscores ("_") which are vaid URI
+characters (see `Escaping Mechanism`_ above).
 
 .. [#URI] Uniform Resource Identifier.  URIs are a general form of
    URLs (Uniform Resource Locators).  For the syntax of URIs see
@@ -2599,7 +2714,7 @@
  Error Handling
 ----------------
 
-DTD element: system_message, problematic.
+Doctree element: system_message, problematic.
 
 Markup errors are handled according to the specification in `PEP
 258`_.
@@ -2607,8 +2722,8 @@
 
 .. _reStructuredText: http://docutils.sourceforge.net/rst.html
 .. _Docutils: http://docutils.sourceforge.net/
-.. _Docutils Document Tree Structure: ../doctree.html
-.. _Generic Plaintext Document Interface DTD: ../gpdi.dtd
+.. _The Docutils Document Tree: ../doctree.html
+.. _Docutils Generic DTD: ../docutils.dtd
 .. _transforms:
    http://docutils.sourceforge.net/docutils/transforms/
 .. _Grouch: http://www.mems-exchange.org/software/grouch/
@@ -2619,23 +2734,25 @@
 .. _getopt.py:
    http://www.python.org/doc/current/lib/module-getopt.html
 .. _GNU libc getopt_long():
-   http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_516.html
+   http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html
 .. _doctest module:
    http://www.python.org/doc/current/lib/module-doctest.html
 .. _Emacs table mode: http://table.sourceforge.net/
-.. _Index of WWW Addressing Schemes:
+.. _Official IANA Registry of URI Schemes:
+   http://www.iana.org/assignments/uri-schemes
+.. _Retired Index of WWW Addressing Schemes:
    http://www.w3.org/Addressing/schemes.html
 .. _World Wide Web Consortium: http://www.w3.org/
 .. _HTML Techniques for Web Content Accessibility Guidelines:
    http://www.w3.org/TR/WCAG10-HTML-TECHS/#link-text
 .. _reStructuredText Directives: directives.html
-.. _reStructuredText Interpreted Text Roles: interpreted.html
+.. _reStructuredText Interpreted Text Roles: roles.html
 .. _RFC2396: http://www.rfc-editor.org/rfc/rfc2396.txt
 .. _RFC2732: http://www.rfc-editor.org/rfc/rfc2732.txt
 .. _Zope: http://www.zope.com/
-.. _PEP 258: http://docutils.sourceforge.net/spec/pep-0258.txt
+.. _PEP 258: ../../peps/pep-0258.html
 
-
+
 ..
    Local Variables:
    mode: indented-text

Modified: Zope/trunk/skel/etc/zope.conf.in
===================================================================
--- Zope/trunk/skel/etc/zope.conf.in	2004-07-26 16:03:45 UTC (rev 26766)
+++ Zope/trunk/skel/etc/zope.conf.in	2004-07-26 17:36:58 UTC (rev 26767)
@@ -335,6 +335,32 @@
 #
 #    rest-output-encoding iso-8859-15
 
+# Directive: rest-header-level
+#
+# Description:
+#     Set the default starting HTML header level for restructured text
+#     documents. The default is 3, which implies that top-level headers
+#     will be created with an <H3> tag.
+#
+# Default: 3
+#
+# Example:
+#
+#    rest-header-level 2
+
+# Directive: rest-language-code
+#
+# Description:
+#    Language code used for some internal translations inside of the docutils
+#    package and for DTD bibliographic elements mapping. See
+#    lib/python/docutils/languages/ for a list of supported language codes.
+#
+# Default: en
+#
+# Example:
+#
+#    rest-language-code de
+
 # Directive: cgi-environment
 #
 # Description:



More information about the Zope-Checkins mailing list