gzz-commits
[Top][All Lists]
Advanced

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

[Gzz-commits] CVSROOT: /cvsroot/navidoc


From: Asko Soukka
Subject: [Gzz-commits] CVSROOT: /cvsroot/navidoc
Date: Mon, 30 Jun 2003 11:30:16 -0400

Module name:    navidoc
Branch:         rel-0-1
Changes by:     Asko Soukka <address@hidden>    03/06/30 11:30:15
Reply-to: address@hidden

CVSROOT:        /cvsroot/navidoc
Module name:    navidoc
Branch:         rel-0-1
Changes by:     Asko Soukka <address@hidden>    03/06/30 11:30:15

Modified files:
        .              : Makefile README config.py default.css 
                         docutils.conf navidoc.conf rst2any.py 
        navidoc        : __init__.py parser.py 
        navidoc/link   : __init__.py docxx.py javadoc.py 
        navidoc/modules: imagemap.py 
        navidoc/mp     : __init__.py html.py uml.py vobs.py 
        navidoc/util   : debug.py path.py 
        test           : __init__.py parser.test path.test 
Added files:
        doc            : .cvsignore 
Removed files:
        .              : TODO-navidoc docutils.himalia gzz.css 
                         navidoc.himalia newpeg.py 
        diagrams       : dummy_directory_for_generated_diagram_data 
        navidoc/modules: metalink.py navbar.py texture.py 

Log message:
        stripping for release

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/Makefile.diff?only_with_tag=rel-0-1&tr1=1.20&tr2=1.20.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/README.diff?only_with_tag=rel-0-1&tr1=1.3&tr2=1.3.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/config.py.diff?only_with_tag=rel-0-1&tr1=1.38&tr2=1.38.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/default.css.diff?only_with_tag=rel-0-1&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/docutils.conf.diff?only_with_tag=rel-0-1&tr1=1.10&tr2=1.10.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc.conf.diff?only_with_tag=rel-0-1&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/rst2any.py.diff?only_with_tag=rel-0-1&tr1=1.32&tr2=1.32.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/doc/.cvsignore?only_with_tag=rel-0-1&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/__init__.py.diff?only_with_tag=rel-0-1&tr1=1.13&tr2=1.13.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/parser.py.diff?only_with_tag=rel-0-1&tr1=1.19&tr2=1.19.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/link/__init__.py.diff?only_with_tag=rel-0-1&tr1=1.24&tr2=1.24.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/link/docxx.py.diff?only_with_tag=rel-0-1&tr1=1.7&tr2=1.7.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/link/javadoc.py.diff?only_with_tag=rel-0-1&tr1=1.11&tr2=1.11.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/modules/imagemap.py.diff?only_with_tag=rel-0-1&tr1=1.11&tr2=1.11.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/mp/__init__.py.diff?only_with_tag=rel-0-1&tr1=1.42&tr2=1.42.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/mp/html.py.diff?only_with_tag=rel-0-1&tr1=1.4&tr2=1.4.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/mp/uml.py.diff?only_with_tag=rel-0-1&tr1=1.21&tr2=1.21.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/mp/vobs.py.diff?only_with_tag=rel-0-1&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/util/debug.py.diff?only_with_tag=rel-0-1&tr1=1.2&tr2=1.2.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/navidoc/util/path.py.diff?only_with_tag=rel-0-1&tr1=1.3&tr2=1.3.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/test/__init__.py.diff?only_with_tag=rel-0-1&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/test/parser.test.diff?only_with_tag=rel-0-1&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/navidoc/navidoc/test/path.test.diff?only_with_tag=rel-0-1&tr1=1.2&tr2=1.2.2.1&r1=text&r2=text

Patches:
Index: navidoc/Makefile
diff -u /dev/null navidoc/Makefile:1.20.2.1
--- /dev/null   Mon Jun 30 11:30:15 2003
+++ navidoc/Makefile    Mon Jun 30 11:30:15 2003
@@ -0,0 +1,75 @@
+#$Id: Makefile,v 1.20.2.1 2003/06/30 15:30:15 humppake Exp $
+
+##########################################################################
+# Variables
+
+NAVIDOC_DEPENDS = lib
+CLASSPATH =$(NAVIDOC_DEPENDS)/jython.jar:$(shell echo $$CLASSPATH)
+JVMFLAGS= -Xms64M -Xmx128M
+CLASSDIR=CLASSES/
+
+export CLASSPATH
+
+ifeq (,$(JYTHONPATH))  
+ 
JYTHONPATH=.:$(NAVIDOC_DEPENDS)/jythonlib.jar:$(NAVIDOC_DEPENDS)/pythonlib.jar:$(NAVIDOC_DEPENDS)/docutils.jar
+endif
+
+ifeq (,$(PYTHON))
+ PYTHON=/usr/bin/python
+endif
+
+ifeq (,$(JYTHON))
+# python.verbose can be: "error", "warning", "message", "comment", "debug"
+ JYTHON=$(JAVA) $(JVMFLAGS) -Dpython.cachedir=. -Dpython.path=$(JYTHONPATH) 
-Dpython.verbose=message $(EDITOR_OPTION) org.python.util.jython
+endif
+
+ifeq (,$(JAVA))
+ JAVA=java
+endif
+
+ifneq (,$(EDITOR))
+       EDITOR_OPTION=-Duser.editor=$(EDITOR)
+else
+       EDITOR_OPTION=
+endif
+
+##########################################################################
+# General targets
+
+all: docs
+
+docs: navidoc navilink
+
+clean:
+       @echo "Removing everything found in .cvsignores"
+       find . -name ".cvsignore"|while read ign; do (cd `dirname $$ign` && cat 
.cvsignore|while read files; do rm -Rf $$files; done); done
+       find . -name "*.pyc" | xargs rm -f
+       find . -name "*.class" | xargs rm -f
+
+navidoc:: # Compiles reST into HTML
+       make html RST="doc/"
+
+navilink: # Linking diagrams in compiled HTMLs bi-directionally using imagemaps
+       make imagemap HTML="doc/"
+
+##########################################################################
+# Navidoc targets
+
+html: # Compiles reST into HTML, directories are processed recursively (for 
"*.rst")
+       $(JYTHON) rst2any.py --html -d navidoc -d docutils -d mp.fail $(DBG) 
$(RST)
+
+html-loop: # Loops for quick recompiling (jython has a huge startup time)
+       $(JYTHON) rst2any.py --loop --html -d navidoc -d docutils -d mp.fail 
$(DBG) $(RST)
+
+imagemap: # Linking diagrams in compiled HTMLs bi-directionally using imagemaps
+       $(JYTHON) rst2any.py --imagemap -d navidoc -d mp.fail $(DBG) $(HTML)
+
+naviloop: # Compiles, links, loops
+       make html-loop DBG="--imagemap $(DBG)" RST="$(RST)"
+
+##########################################################################
+# Use: make test TEST=test/parser.test, to run a single test.
+TEST=.
+test::
+       $(JYTHON) test.py $(DBG) $(TEST)
+
Index: navidoc/README
diff -u /dev/null navidoc/README:1.3.2.1
--- /dev/null   Mon Jun 30 11:30:15 2003
+++ navidoc/README      Mon Jun 30 11:30:15 2003
@@ -0,0 +1,189 @@
+==============================================
+Navidoc - linking documentations via imagemaps
+==============================================
+
+Navidoc is a software engineering documentation tool, which turns
+lexically defined UML diagrams embedded in reST into
+multidirectionally hyperlinked menus connecting the design and
+embedded source code documentation.
+
+Please send comments about this software to::
+
+    address@hidden
+
+If you would like to subscribe to that mailing list, 
+please go to 
+  
+    http://mail.nongnu.org/mailman/listinfo/gzz-dev/
+
+Navidoc is a part of Fenfire project.
+
+License
+=======
+
+Navidoc Loom is released under the GNU Lesser General
+Public License (LGPL). For details, see file ``LICENSE``.
+
+Dependencies
+============
+
+Dependencies not provided under ``lib``:
+
++---------------+----------------+
+| Software name | Corresponding  |
+|               | Debian package |
++===============+================+
+| Netpbm        | netpbm         |
++---------------+----------------+
+| Metapost      | tetex-bin      |
++---------------+----------------+
+
+Current development snapshot of Docutils under ``lib`` is fetched
+``2003-04-10``. The snapshot has been patched to work better with
+Jython.
+
+For Navidoc functionality it's crucial that used Metapost version
+creates log files from its output. MetaPost version used in
+development was (``mpost -ver``)::
+
+   MetaPost (Web2C 7.4.5) 0.641
+   kpathsea version 3.4.5
+
+Setting up
+==========
+
+If correct dependencies exists, Navidoc installation could be tested
+by compiling the current documentation by::
+
+  make docs
+
+All modifiable settings are stored in ``navidoc.conf`` and
+``docutils.conf``. The both files are always searched and imported
+from the target file's directory before compiling. When compiling
+several files, the latest configuration remains effective.
+
+Available make targets
+======================
+
+html            
+       converts given $RST into html
+
+html-loop       
+       loops converting given $RST into html
+
+naviloop        
+       loops converting given $RST into html, creating 
+
+imagemap
+       for diagrams and embedding diagrams into their
+       elements' target files
+                                                                               
 
+The following targets are for project's whole documentation:
+                                                                               
 
+navidoc
+       compiles reST under project/doc/
+
+navilink
+       imagemaps diagrams under project/doc/
+
+
+Using Navidoc with native Python and Docutils
+=============================================
+
+It would be faster to use Navidoc with native Python and Docutils than
+with Jython (and Docutils snapshot) provided under ``lib``. The latest
+Docutils snapshot, Navidoc was tested to be compliant, was fetched
+2003-04-10, but there should be no reasons, why it wouldn't work also
+with current snapshots. Sufficient Python is version 2.1.
+
+Navidoc could be executed directly i.e. with the following commands::
+
+   python rst2any.py --html foo.rst bar.rst
+   python rst2any.py --html --loop foo.rst bar.rst
+   python rst2any.py --naviloop foo.rst bar.rst
+   python rst2any.py --imagemap foo.gen.html bar.gen.html
+   python rst2any.py --naviloop doc/
+
+To enable default output, add ``-d navidoc -d docutils -d mp.fail``
+before the target file.
+
+If you have installed a latex writer in your docutils installation,
+you may also use ``--latex`` instead of ``--html`` to embed Navidoc
+diagrams also into your LaTeX documents. Altough, please, note that
+``--imagemap`` won't work with ``--latex``.
+
+Getting the bleeding-edge version from CVS
+==========================================
+
+You will need to check out both the ``navidoc`` 
+and the ``navidoc-depends`` CVS module
+from the same directory::
+
+  cvs -d:pserver:address@hidden:/cvsroot/navidoc login
+  cvs -z3 -d:pserver:address@hidden:/cvsroot/navidoc co navidoc
+  cvs -z3 -d:pserver:address@hidden:/cvsroot/navidoc co navidoc-depends
+
+To update your checked out copy, run the following command both in
+your ``navidoc/`` and ``navidoc-depends/`` directories::
+
+  cvs up -dP
+
+Homepage and mailing lists
+==========================
+
+Navidoc project homepages could be found at
+
+   http://www.nongnu.org/navidoc/
+
+   http://savannah.nongnu.org/projects/navidoc/
+
+Navidoc is currently developed as part of the Fenfire project at
+
+   http://fenfire.org/
+ 
+   http://savannah.nongnu.org/projects/fenfire/
+
+The mailing list is [gzz-dev]:
+
+   http://mail.nongnu.org/mailman/listinfo/gzz-dev/
+
+and CVS commit messages are sent to [gzz-commits]:
+
+   http://mail.nongnu.org/mailman/listinfo/gzz-commits/
+
+This is because Fenfire evolved out of an earlier project
+called Gzz and we haven't fully made the move yet.
+
+Please send bug reports as well as any comments
+to [gzz-dev].
+
+David Goodger's Docutils can be found at:
+
+    http://docutils.sourceforge.net/
+
+Problem Solving
+===============
+
+- Diagrams are compiled without text (and usually only connections are
+  shown).
+
+  Fonts (tfm) under navidoc/mp/ should be copied
+  also to diagrams' temporary directory.
+
+- Diagrams won't comple and no ``digramname.mp.log`` -files are
+  generated into diagrams' temporary directory.
+ 
+  All MetaPost versions won't create log files and 
+  Navidoc won't work with them.
+
+  Our MetaPost version is::
+
+    MetaPost (Web2C 7.4.5) 0.641
+    kpathsea version 3.4.5
+
+- Got a lot of strange MetaPost errors.
+
+  Check for possible typos in diagram elements' variable names.
+  That seems to be the most usual reason.
+
+  Check the syntax of UML directives' MetaPost part.
Index: navidoc/config.py
diff -u /dev/null navidoc/config.py:1.38.2.1
--- /dev/null   Mon Jun 30 11:30:15 2003
+++ navidoc/config.py   Mon Jun 30 11:30:15 2003
@@ -0,0 +1,97 @@
+# 
+# Copyright (c) 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+# $Id: config.py,v 1.38.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+"""
+Navidoc configuration module.
+"""
+
+dbg = None
+
+import os, ConfigParser
+
+import navidoc.util.debug
+
+# General debug filter
+dbg = navidoc.util.debug.DebugFilter()
+
+# System calls
+metapost = 'mpost'
+pnmscale = 'pnmscale'
+pstopnm = 'pstopnm'
+pnmtopng = 'pnmtopng'
+stderr = '/dev/null'
+
+# Initializing dynamic settings
+# These should be kept up-to-date in code
+# always when compiling reST or diagrams
+working_directory = '.'
+input_filename = ''
+output_filename = ''
+link_base_directory = None # if different than working_directory
+
+# Set the default docutils.conf
+docutils_conf = './docutils.conf'
+
+# Set the default navidoc.conf
+navidoc_conf = './navidoc.conf'
+read_navidoc_conf = ''
+
+# Holder of packagenames when linking diagrams
+# will be cleaned after every diagram
+linkpackages = {}
+
+# Should linked parts of the diagram be emphasized
+# using colors and rough edge
+link_emphasize = 0
+
+# Should diagrams be generated at all
+# this is altered to halt image generation
+# temporarily
+mp_generate = 1
+
+# Generate only eps -versions of diagrams
+# Usable, when compiling reSTs into LaTeX
+mp_eps_only = 0
+
+# Should context menu be added into diagrams
+# this is modifiable later as UML direvtive option
+mp_context_menu = 0
+
+def read_config(module, filepath):
+    """
+    read_config(module, filepath)
+    
+    Reads a config file and updates
+    attributes in module.
+    """
+    cp = ConfigParser.ConfigParser()
+    cp.read(filepath)
+    for section in cp.sections():
+        for option in cp.options(section):
+            setattr(module, option, eval(cp.get(section, option)))
Index: navidoc/default.css
diff -u navidoc/default.css:1.1.2.1 navidoc/default.css:1.1.2.2
--- navidoc/default.css:1.1.2.1 Mon Jun 30 11:19:24 2003
+++ navidoc/default.css Mon Jun 30 11:30:15 2003
@@ -1,8 +1,8 @@
 /*
 :Author: David Goodger
 :Contact: address@hidden
-:date: $Date: 2003/06/30 15:19:24 $
-:version: $Revision: 1.1.2.1 $
+:date: $Date: 2003/06/30 15:30:15 $
+:version: $Revision: 1.1.2.2 $
 :copyright: This stylesheet has been placed in the public domain.
 
 Default cascading style sheet for the HTML output of Docutils.
Index: navidoc/doc/.cvsignore
diff -u /dev/null navidoc/doc/.cvsignore:1.1.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/doc/.cvsignore      Mon Jun 30 11:30:15 2003
@@ -0,0 +1,4 @@
+*.class
+*.pyc
+*.gen.*
+*.~*
Index: navidoc/docutils.conf
diff -u /dev/null navidoc/docutils.conf:1.10.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/docutils.conf       Mon Jun 30 11:30:15 2003
@@ -0,0 +1,14 @@
+#$Id: docutils.conf,v 1.10.2.1 2003/06/30 15:30:15 humppake Exp $
+
+[options]
+
+# These entries affect all processing:
+input-encoding = iso-8859-1
+output-encoding = iso-8859-1
+source-link = 1
+language-code = en
+datestamp = %c
+generator = 1
+
+# These entries affect HTML output:
+stylesheet-path = default.css
Index: navidoc/navidoc.conf
diff -u /dev/null navidoc/navidoc.conf:1.1.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc.conf        Mon Jun 30 11:30:15 2003
@@ -0,0 +1,25 @@
+# $Id: navidoc.conf,v 1.1.2.1 2003/06/30 15:30:15 humppake Exp $
+
+[navidoc]
+# Midfix for generated files
+# e.g. foo.rst => foo.gen.rst
+midfix = '.gen'
+
+[link]
+# Settings for linking diagrams to generated documentation
+# The search order is ascending with sudden death
+javadoc_directories = ['doc',
+                       ]
+docxx_directories = ['doc',
+                     ]
+
+# Enables crosslinkin between different projects
+# e.g. link foo
+#           bar.gen.html
+# Links to bar.gen.html in project foo
+link_redirection = {'navidoc': 'doc',
+                    }
+
+[directives]
+# Settings for MetaPost directives
+mp_directory = 'diagrams' # Path to temporary diagram directory, relative to 
execution directory
Index: navidoc/navidoc/__init__.py
diff -u /dev/null navidoc/navidoc/__init__.py:1.13.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/__init__.py Mon Jun 30 11:30:15 2003
@@ -0,0 +1,110 @@
+# 
+# Copyright (c) 2002, 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: __init__.py,v 1.13.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+import config
+
+import docutils.core
+
+import util.path
+
+# Because Docutils' own relative_path had problems with
+# paths beginning with '../', we had to build our own.
+# Probably we can overwrite our own by Docutils' on some day :-)
+docutils.utils.relative_path = util.path.relative_path
+
+class DocutilsException(Exception):
+    def __init__(self, system_message):
+        self.value = system_message.astext()
+        Exception.__init__(self, self.value)
+    def __str__(self):
+        return self.value
+
+def docutils_system_message(self, level, message, *children, **kwargs):
+    """
+    See docutils.utils.Reporter.system_message()
+    This modified copy redirects Docutils system messages
+    to navidoc debug.
+    """
+    attributes = kwargs.copy()
+    category = kwargs.get('category', '')
+    if kwargs.has_key('category'):
+       del attributes['category']
+    if kwargs.has_key('base_node'):
+       source, line = docutils.utils.get_source_line(kwargs['base_node'])
+       del attributes['base_node']
+        if source is not None:
+            attributes.setdefault('source', source)
+        if line is not None:
+            attributes.setdefault('line', line)
+    attributes.setdefault('source', self.source)
+    msg = docutils.nodes.system_message(message, level=level,
+                                       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 category:
+            config.dbg.out("docutils", msg.astext(), '[%s]' % category)
+        else:
+            config.dbg.out("docutils", msg.astext())
+    if level >= halt_level:
+        raise docutils.utils.SystemMessage(msg)
+    if level > 0 or debug:
+       self.notify_observers(msg)
+    return msg
+docutils.utils.Reporter.system_message = docutils_system_message
+docutils.utils.SystemMessage = DocutilsException
+
+class Element:
+    """
+    The general element for all subelements.
+    """
+
+class NamedElement(Element):
+    """
+    Element with name and linking features.
+    """
+    def do_contents(self, list):
+        """
+        do_contents(list)
+
+        Default implementation for element to parse and
+        handle its contents.
+        """
+        self.link = None
+       for element in list:
+           self.handle_contained(element)
+
+    def handle_contained(self, element):
+        """
+        handle_contained(element)
+
+        Default implementation for element to parse and
+        handle its subelement.
+        """
+        config.element_list.add_contained_element(self, element)
Index: navidoc/navidoc/link/__init__.py
diff -u /dev/null navidoc/navidoc/link/__init__.py:1.24.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/link/__init__.py    Mon Jun 30 11:30:15 2003
@@ -0,0 +1,139 @@
+# 
+# Copyright (c) 2002, 2003 by Tuomas Lukka, Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: __init__.py,v 1.24.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Tuomas Lukka, Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+"""
+Module contain the default link elements and basic methods for
+checking the existence of a target file.
+"""
+
+import config
+
+import os.path, re
+
+import navidoc
+
+from navidoc.util.path import *
+
+dbg = config.dbg.shorthand('link')
+
+class Link (navidoc.Element):
+    key = 'link'
+
+    title = '' #None
+    bbox = '' #None
+    focus = 0
+    rough_edge = 1
+    error = 0
+    target = '' #None
+
+    def __init__(self, var, toks, list):
+       dbg("link: %s %s %s" % (var, toks,list))
+
+        self.var = var or toks[0]
+        self.title = toks[0]
+
+        if config.link_base_directory == None:
+            redirection_path = config.working_directory
+        else: redirection_path = config.link_base_directory
+
+        if (len(toks) > 1):
+            """
+            The ``link`` may be followed by an attribute, which is
+            interpreted as keyword for one of the redirections mapped
+            in config.
+            """
+            self.title = toks[0]
+            redirection = toks[-1]
+            if config.link_redirection.has_key(redirection):
+                toks.remove(redirection)
+                redirection_path = config.link_redirection[redirection]
+                dbg('Redirection %s: %s' % (redirection, redirection_path))
+
+        if (len(list) > 0):
+            """
+            Multiple link could be given.
+            Let the last working one overwrite others.
+            """
+            for link in list:
+                if type(link[0]) == type([]):
+                    link = link[0][0]
+                else: link = link[0]
+                if self.target == None or \
+                       not os.path.isfile(self.target):
+                    if link.startswith('http://'): self.target = link
+                    else: self.target = 
os.path.normpath(slashify(redirection_path) + link)
+
+            """
+            Final check and setting attributes.
+            """
+            self.set_status(set_title=1)
+        
+        dbg(self.key+" title: %s, target: %s, error: %s" % (self.title, 
self.target, self.error))
+
+    def set_status(self, set_title=0):
+        """
+        set_status(set_title=0)
+        
+        Check if the link target exists. Check if the target
+        file is the current file. Could also parse
+        <title> from the file and set it to title.
+        """
+        if self.target.startswith('http://'):
+            self.error = 0
+            return
+
+        path = self.target
+
+        tmp = path.rfind("#")
+        if tmp != -1: path = path[0:tmp]
+
+        if not os.path.isfile(path): self.error = 1
+
+        if not self.error and set_title:
+            file = open(path)                
+            title = re.compile('<title>([^<]*)</title>')
+            strip = re.compile('[a-zA-ZåäöÅÄÖ\-\_ ]*')
+            title = title.findall(file.read())
+            file.close()
+            if len(title) > 0: self.title = strip.findall(title[0])[0]
+
+        if not self.error and os.path.abspath(path) \
+           == 
os.path.abspath(slashify(config.working_directory)+config.output_filename):
+            self.focus = 1
+            self.target = ''
+            self.title = ''
+
+        
+    def setup_code(self): return ''
+
+    def draw_code(self):
+        """
+        This should be overwritten by drawing implementation.
+        """
+        return ''
Index: navidoc/navidoc/link/docxx.py
diff -u /dev/null navidoc/navidoc/link/docxx.py:1.7.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/link/docxx.py       Mon Jun 30 11:30:15 2003
@@ -0,0 +1,107 @@
+# 
+# Copyright (c) 2002, 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: docxx.py,v 1.7.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+"""
+Doc++ link element.
+"""
+
+import config
+
+import navidoc
+import os.path, re
+
+from navidoc.util.path import *
+
+dbg = config.dbg.shorthand('link')
+dbg_navidoc = config.dbg.shorthand('navidoc')
+config.linkpackages['clink'] = ''
+
+targets = {}
+
+def __init__():
+    global targets
+    for docxx in config.docxx_directories:
+        if os.path.isfile(slashify(docxx)+'index.html'):
+            index = open(slashify(docxx)+'index.html')
+            tuples = re.compile('<A HREF="([^<]*)">([^<]*)</A>')
+            tuples = tuples.findall(index.read())
+            index.close()
+            for link, name in tuples:
+                targets[name] = slashify(docxx)+link
+
+class CLinkPackage(navidoc.Element):
+    key = "clinkpackage"
+
+    def __init__(self, var, toks, list):
+        if len(toks) > 0: package = toks[0]
+        else: package = ''
+        dbg("Set clinkpackage to: "+package)
+        config.linkpackages['clink'] = package
+
+    def setup_code(self): return ''
+
+    def draw_code(self):  return ''
+
+class CLink(navidoc.link.Link):
+    key = "clink"
+
+    def __init__(self, var, toks, list):
+        navidoc.link.Link.__init__(self, var, toks, list)
+
+        if not self.target or self.error:
+            self.error = 0
+            if len(list) > 0 and len(list[0][0][0]) > 0:
+                self.target = list[0][0][0]
+            else: self.target = toks[0]
+            self.set_target()
+            self.set_status()
+            if self.error:
+                dbg_navidoc('[clink] Target not found: %s.' % (self.target))
+            dbg(self.key+" Doc++ target: %s, error: %s" % (self.target, 
self.error))
+
+    def set_target(self):
+         """
+         Set the doc++ target.
+         """
+         parts = self.target.split('.')
+         self.target = '::'.join(parts);
+         
+         if targets.has_key(self.target):
+             self.target = targets[self.target]
+             return
+         
+         if len(config.linkpackages['clink']) > 0:
+             package_parts = config.linkpackages['clink'].split('.')
+             clinkpackage = '::'.join(package_parts)
+             self.target = clinkpackage+'::'+self.target
+
+         if targets.has_key(self.target):
+             self.target = targets[self.target]
+             return
+         
Index: navidoc/navidoc/link/javadoc.py
diff -u /dev/null navidoc/navidoc/link/javadoc.py:1.11.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/link/javadoc.py     Mon Jun 30 11:30:15 2003
@@ -0,0 +1,109 @@
+# 
+# Copyright (c) 2002, 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: javadoc.py,v 1.11.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+
+"""
+Javadoc link element.
+"""
+
+import config
+
+import navidoc
+import os.path, re
+
+from navidoc.util.path import *
+
+dbg = config.dbg.shorthand('link')
+dbg_navidoc = config.dbg.shorthand('navidoc')
+
+config.linkpackages['jlink'] = ''
+
+class JLinkPackage(navidoc.Element):
+    key = "jlinkpackage"
+
+    def __init__(self, var, toks, list):
+        if len(toks) > 0: package = toks[0]
+        else: package = ''
+        dbg("Set jlinkpackage to: "+package)
+        config.linkpackages['jlink'] = package
+
+    def setup_code(self): return ''
+
+    def draw_code(self):  return ''
+
+class JLink(navidoc.link.Link):
+    key = "jlink"
+
+    def __init__(self, var, toks, list):
+        navidoc.link.Link.__init__(self, var, toks, list)
+
+        if not self.target or self.error:
+            self.error = 0
+
+            if len(list) > 0 and len(list[0][0][0]) > 0:
+                self.target = list[0][0][0]
+            else: self.target = toks[0]
+            self.set_target()
+            self.set_status()
+
+            if self.error:
+                dbg_navidoc('[jlink] Target not found: %s.' % (self.target))
+            dbg(self.key+" Javadoc target: %s, error: %s" % (self.target, 
self.error))
+
+    def set_target(self):
+         """
+         Set the javadoc target.
+         """
+         parts = self.target.split('.')
+         self.target = '/'.join(parts);
+
+         if re.match('^[a-z]', parts[-1]):
+             self.target = slashify(self.target) + 'package-summary.html'
+         else:
+             self.target = self.target + '.html'
+
+         for dir in config.javadoc_directories:
+             if os.path.isfile(slashify(dir)+self.target):
+                 self.target = slashify(dir)+self.target
+                 if self.target.endswith('/package-summary.html'):
+                     self.target = self.target+'#package_description'
+                 return 
+ 
+         if len(config.linkpackages['jlink']) > 0:
+             package_parts = config.linkpackages['jlink'].split('.')
+             jlinkpackage = '/'.join(package_parts)
+             self.target = slashify(jlinkpackage)+self.target
+
+         for dir in config.javadoc_directories:
+             if os.path.isfile(slashify(dir)+self.target):
+                 self.target = slashify(dir)+self.target
+                 if self.target.endswith('/package-summary.html'):
+                     self.target = self.target+'#package_description'
+                 return 
+
Index: navidoc/navidoc/modules/imagemap.py
diff -u /dev/null navidoc/navidoc/modules/imagemap.py:1.11.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/modules/imagemap.py Mon Jun 30 11:30:15 2003
@@ -0,0 +1,297 @@
+#
+# Copyright (c) 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: imagemap.py,v 1.11.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+"""
+The postprocessing module, which creates imagemaps
+for linked diagrams and embeds focused and imagemapped
+diagrams also into target documents.
+"""
+
+import config
+
+import os.path, re
+
+from navidoc.mp import create_uml, MPLink, psbbox
+
+from navidoc.util.path import *
+
+dbg = config.dbg.shorthand('imagemap')
+dbg_navidoc = config.dbg.shorthand('navidoc')
+
+def postprocess(path):
+    """
+    HTML postprocessing function called from rst2any.py.
+    """
+
+    dirlist = []
+    if (os.path.isfile(path)): embed_imagemap(path)
+    else: dirlist = listdir(path, "html", dirs=1)
+
+    for entry in dirlist:        
+        if os.path.isdir(slashify(path)+entry) \
+               and not os.path.islink(slashify(path)+entry):
+            postprocess(slashify(path)+entry)
+        elif os.path.isfile(slashify(path)+entry):
+            embed_imagemap(slashify(path)+entry)
+
+def embed_javascript(filepath):
+    html_file = open(filepath)
+    html = html_file.read()
+    html_file.close()
+
+    if html.find('function setImg') == -1:
+        insert = html.upper().find('</HEAD>')
+        out = open(filepath, "w")            
+        out.write(html[:insert]);
+        out.write("""
+<script language="JavaScript">
+<!-- Begin JavaScript
+function setImg(img_id, img_src, img_usemap) {
+document[img_id].setAttribute("src", img_src);
+document[img_id].setAttribute("usemap", img_usemap);
+}
+// End -->
+</script>
+""")
+        out.write(html[insert:])
+        out.close()
+
+def embed_imagemap(filepath):
+    dbg('Checking %s for imagemapping diagrams' % (filepath))
+
+    config.working_directory = os.path.normpath(os.path.dirname(filepath))
+    config.input_filename = os.path.basename(filepath)
+    config.output_filename = os.path.basename(filepath)
+
+    embed_javascript(filepath)
+    
+    htmlfile = open(filepath)
+    html = htmlfile.read()
+    htmlfile.close()
+    
+    insert = html.find('<img _uml="')
+    while insert > -1:
+        diagram = html[insert+11:html.find('"', insert+11)]
+        
+        context = filepath.replace("/","_")
+        if context.endswith(config.midfix+'.html'):
+            context = context[0:len(context)-(len(config.midfix)+5)]
+        if context.endswith(".html"): context = context[0:len(context)-5]
+
+        out = open(filepath, "w")            
+        out.write(html[0:insert]);
+        if not is_linked(diagram):
+            out.write('<img ')
+            html = html[html.find('"', insert+1)+1:len(html)]
+        else:
+            out.close()
+            create_uml(diagram, context)
+            create_uml(diagram, context+'_implicit', scale=0.5)
+            out = open(filepath, "w")            
+            out.write(html[0:insert]);
+            dbg_navidoc("Mapping diagram %s within %s" % (diagram, filepath))
+            imgmap = get_imagemap(diagram, context)
+            imgmap_implicit = get_imagemap(diagram, context+'_implicit', 
scale=0.5, id_postfix="_implicit")
+            dbg("Diagram %s imagemap: %s" % (diagram, "\n"+str(imgmap)))
+            out.write("\n"+'<a id="%s"></a>' %(diagram) + "\n")
+            out.write(imgmap)
+            out.write(imgmap_implicit)
+            if len(context) > 0: context = '_'+context
+            out.write('<img 
src="'+slashify(relative_path(config.working_directory, config.mp_directory)) \
+                  +diagram+context+config.midfix+'.png" usemap="#' \
+                  +diagram+'_map" alt="'+diagram+'" id="'+diagram+'_img" 
/>'+"\n")
+            html = html[html.find(">", insert)+1:len(html)]
+        out.write(html)
+        out.close()
+                
+        htmlfile = open(filepath)
+        html = htmlfile.read()
+        htmlfile.close()
+        insert = html.find('<img _uml="')
+
+        implicit_targets = get_targets(diagram)
+        dbg('Diagram %s implicit targets: %s' % (diagram, 
str(implicit_targets)))
+        for target in implicit_targets: 
+            tmp = target.rfind("#")
+            if tmp != -1: target = target[0:tmp]
+            if os.path.isfile(target):
+                embed_implicit_diagram(target, diagram) 
+
+
+def embed_implicit_diagram(filepath, diagram):
+    dbg_navidoc('Embedding implicitly diagram %s into %s' % (diagram, 
filepath))
+
+    config.link_base_directory = config.working_directory
+    init_input_filename = config.input_filename
+    init_output_filename = config.output_filename
+    
+    config.working_directory = os.path.normpath(os.path.dirname(filepath))
+    config.input_filename = os.path.basename(filepath)
+    config.output_filename = os.path.basename(filepath)
+
+    embed_javascript(filepath)
+
+    htmlfile = open(filepath)
+    html = htmlfile.read()
+    htmlfile.close()
+
+    id = html.find('<a id="'+diagram+'"></a>') + 1
+    insert = html.find('<map id="'+diagram+'_implicit_map"')
+
+    """If explicit diagram found, will not insert implicit on."""
+    explicit = html.find('<map id="'+diagram+'_map"')
+    if explicit == -1: explicit = html.find('_uml="'+diagram)
+
+    if not id:
+        """
+        When embedding implicit diagrams, the diagram id is located
+        right after <body> tag. This way it could be used better
+        as anchor.
+        """        
+        insert_id = html.upper().find('<BODY')
+        insert_id = html.upper().find('>', insert_id)+1
+        out = open(filepath, "w")            
+        out.write(html[:insert_id]);
+        out.write('<a id="'+diagram+'"></a>'+'\n')
+        out.write(html[insert_id:])
+        out.close()
+
+        htmlfile = open(filepath)
+        html = htmlfile.read()
+        htmlfile.close()
+        
+    if insert == -1 and explicit == -1:
+        """
+        Implicit imagemaps are embedded after the first header or after
+        the <body> tag.
+        """
+        for index in range(6):
+            insert = html.upper().find('</H%s>' % (str(index)))+5
+            if insert != 4: break
+        if insert == 4:
+            insert = html.upper().find('<BODY')
+            insert = html.upper().find('>', insert)+1
+        insert_left = insert
+    else: insert_left = html.find('/>', html.find('<img', insert))+2
+    
+    if insert != -1 and explicit == -1:
+        context = filepath.replace("/","_")
+        if context.endswith(config.midfix+'.html'):
+            context = context[0:len(context)-(len(config.midfix)+5)]
+        if context.endswith(".html"): context = context[0:len(context)-5]
+        create_uml(diagram, context)
+        create_uml(diagram, context+'_implicit', scale=0.5)
+        out = open(filepath, "w")            
+        out.write(html[0:insert]);
+        out.close()
+        out = open(filepath, "w")            
+        out.write(html[0:insert]);
+        dbg("Mapping diagram %s within %s" % (diagram, filepath))
+        imgmap = get_imagemap(diagram, context)
+        imgmap_implicit = get_imagemap(diagram, context+'_implicit', 
scale=0.5, id_postfix="_implicit")
+        dbg("Diagram %s imagemap: %s" % (diagram, "\n"+str(imgmap_implicit)))
+        out.write(imgmap)
+        out.write(imgmap_implicit)
+        if len(context) > 0: context = '_'+context
+        out.write('<img 
src="'+slashify(relative_path(config.working_directory, config.mp_directory)) \
+                  +diagram+context+'_implicit'+config.midfix+'.png" usemap="#' 
\
+                  +diagram+'_implicit_map" alt="'+diagram+'" 
id="'+diagram+'_img" />'+"\n")
+        html = html[insert_left:len(html)]
+        out.write(html)
+        out.close()
+
+    config.working_directory = config.link_base_directory
+    config.input_filename = init_input_filename
+    config.output_filename = init_output_filename
+    config.link_base_directory = None
+
+def is_linked(diagram):
+    log_file = 
open(slashify(config.mp_directory)+diagram+config.midfix+'.mp.log')
+    log = log_file.read()
+    log_file.close()
+    log = log.replace("\n",'') # MetaPost (mpost) splits lines awkwardly in 
the log.
+    
+    # Grep all linked areas from log file.
+    for link in re.findall('\"LINKRECT\((.*?)\)\"', log):
+       els = link.split(',')
+        if els[0] != '"bbox"': return 1
+
+    return 0
+
+def get_imagemap(diagram, context, scale=1.0, id_postfix=''):
+    if len(context) > 0: context = '_'+context
+
+    log_file = 
open(slashify(config.mp_directory)+diagram+context+config.midfix+'.mp.log')
+    log = log_file.read()
+    log_file.close()
+    log = log.replace("\n",'') # MetaPost (mpost) splits lines awkwardly in 
the log.
+    
+    links = []
+    bbox = None
+
+    # Grep all linked areas from log file.
+    for link in re.findall('\"LINKRECT\((.*?)\)\"', log):
+       els = link.split(',')
+        if els[0] == '"bbox"': bbox = els[2:len(els)]
+        else: links.append(MPLink(els))
+
+    imgmap = None
+
+    if len(links) > 0:
+        bbox = psbbox(bbox)
+        for link in links:
+            if not link.target.startswith('http://') and not link.target == '':
+                link.target = relative_path(config.working_directory, 
link.target)
+            link.map_corners(bbox.map_point)
+
+        imgmap = "\n"+'<map id="'+diagram+id_postfix+'_map" 
name="'+diagram+id_postfix+'_map">'+"\n" \
+                 +"\n".join([link.imgmapanchor(scale=scale, diagram=diagram, 
context=context) \
+                             for link in links]) \
+                 +'</map>'+"\n"
+    return imgmap
+
+def get_targets(diagram):
+    """
+    Load log file generated by MetaPost while compiling diagram,
+    parse link from log file and return all gathered targets.
+    """
+    targets = []
+
+    log_file = 
open(slashify(config.mp_directory)+diagram+config.midfix+'.mp.log')
+    log = log_file.read()
+    log_file.close()
+    log = log.replace("\n",'') # MetaPost (mpost) splits lines awkwardly in 
the log.
+
+    # Grep all linked areas from log file.
+    for link in re.findall('\"LINKRECT\((.*?)\)\"', log):
+       els = link.split(',')
+       if els[0] != '"bbox"': targets.append(MPLink(els).target)
+
+    return targets
+
Index: navidoc/navidoc/mp/__init__.py
diff -u /dev/null navidoc/navidoc/mp/__init__.py:1.42.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/mp/__init__.py      Mon Jun 30 11:30:15 2003
@@ -0,0 +1,381 @@
+# 
+# Copyright (c) 2002, 2003 Tuomas Lukka, Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+# $Id: __init__.py,v 1.42.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Tuomas Lukka, Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+"""
+Metapost module.
+"""
+
+import config
+
+import os, os.path, re
+import navidoc.link, navidoc.parser
+
+from navidoc.util.path import *
+from navidoc.util.parser import random_var
+
+dbg = config.dbg.shorthand('mp')
+dbg_navidoc = config.dbg.shorthand('navidoc')
+dbg_fail = config.dbg.shorthand('mp.fail')
+
+rough_edges = []
+
+def link_draw_code(self):
+    """
+    Metapost implementation of navidoc.link.draw_code.
+    """
+    if config.mp_eps_only: return ''
+    if not config.link_emphasize: return 'showlinksize("'+self.target+'", 
"'+self.title+'", ('+self.bbox+'));'
+    if self.error: return 'showlinkerror("'+self.target+'", "'+self.title+'", 
('+self.bbox+'));'
+    if not self.focus: return 'showlink("'+self.target+'", "'+self.title+'", 
('+self.bbox+'));'
+    else:
+        if self.rough_edge:
+            navidoc.mp.rough_edges.extend([self.bbox])
+            return 'showfocus("'+self.target+'", "'+self.title+'", 
('+self.bbox+'));'+"\n"
+        else: return 'showfocus("'+self.target+'", "'+self.title+'", 
('+self.bbox+'));'
+navidoc.link.Link.draw_code = link_draw_code
+
+class MetapostElement(navidoc.NamedElement):
+    def repl(self, s):
+       s = s.replace("%%", self.var)
+       s = s.replace("%name%", self.name)
+       if "stereo" in dir(self):
+           s = s.replace("%stereo%", self.stereo or "")
+       return s
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           """
+       return self.repl(s)
+
+class SimpleElement(MetapostElement):
+    def __init__(self, var, toks, list):
+       dbg("Simple element: %s %s %s" % (var, toks, list))
+       self.var = var or toks[0]
+       self.name = toks[0]
+       self.do_contents(list)
+        if self.link != None:
+            self.link.bbox = ('bboxmeasuredpic(%s)' % (self.var))
+
+class mptitle(MetapostElement):
+    key = 'title'
+    def __init__(self, var, toks, list = []):
+       dbg("mptitle: %s %s %s" % (var, toks, list))
+        if not var: raise UMLException('No variable given name for title 
(%s).' %(' '.join(toks)))
+        self.var = var
+        self.name = var
+        self.title = ' '.join(toks)
+
+        # Removing possible quotes
+        if self.title.startswith('"') and self.title.endswith('"'):
+            self.title = self.title[1:len(self.title)-1]
+        
+        self.do_contents(list)
+        if self.link != None:
+            self.link.bbox = ('bboxmeasuredpic(%s)' % (self.var))
+            self.link.rough_edge = 1
+    def setup_code(self):
+       s = """
+           picture %%.pict;
+           %%.pict = diagramTitle("""+'"'+self.title+'"'+""");
+           picmeasurements(%%);
+           """
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           """ 
+       return self.repl(s)
+
+class mpContextMenu(MetapostElement):
+    key = 'contextmenu'
+    def __init__(self, var, toks, list = []):
+        config.mp_context_menu = 1
+    def setup_code(self):
+        return ''
+    def draw_code(self):
+        return ''
+
+def context_menu(diagram):
+    """ Creates the "menu" above the diagram. """
+
+    context_menu = ''
+    
+    # Refers must exist.
+    filepath = slashify(config.mp_directory)+diagram+config.midfix+'.refers'
+    if (filepath):
+        refers_file = open(filepath, "r")
+        refers = refers_file.readlines()
+        refers_file.close()
+
+        # Remove white spaces, just for case
+        for index in range(len(refers)):
+            refers[index] = refers[index].strip()
+        while refers.count(''): refers.remove('')
+        
+        # List through in descending order.
+        refer_names = {}
+        for id_inv in range(len(refers)):
+            id = len(refers)-(id_inv+1)
+            refers[id] = refers[id].replace("\n", '')
+            
+            try:
+                refers_file = open(refers[id], 'r')                
+                title = re.compile('<title>([^<]*)</title>')
+                title = title.findall(refers_file.read())
+                refers_file.close()
+            except IOError:
+                raise MetapostException("Referenced file %s defined in %s was 
not found." % (refers[id], filepath))
+
+            strip = re.compile('[a-zA-ZåäöÅÄÖ\-\_ ]*')
+            if len(title) > 0: title = strip.findall(title[0])[0]
+            else: title = refers[id].split("/")[-1].split(".")[0]
+
+            if config.link_base_directory == None:
+                target = relative_path(config.working_directory, refers[id])
+            else:
+                target = relative_path(config.link_base_directory, refers[id])
+            refer_names[id] = random_var()
+
+            element = mptitle(refer_names[id], [title],
+                              [[['link'], [target]]])
+            if id == len(refers)-1:
+                context_menu += "\tdraw ulcorner(bbox(currentpicture))+(0,10) 
-- urcorner(bbox(currentpicture))+(0,10) withpen pencircle scaled 1.5pt;\n"
+                context_menu += element.setup_code()
+                context_menu += "\t"+refer_names[id]+".sw = 
ulcorner(bbox(currentpicture))+(35,0);\n"
+                context_menu += element.link.draw_code()
+                context_menu += element.draw_code()
+            else:
+                context_menu += element.setup_code()
+                context_menu += "\t"+refer_names[id]+".sw = "\
+                                  +refer_names[id+1]\
+                                  +".nw;\n"
+                context_menu += element.link.draw_code()
+                context_menu += element.draw_code()
+            if id == 0:
+                context_menu += "\tdraw (infontBB(\"from:\", \"Helvetica\") 
scaled 1.3) shifted (ulcorner(bbox(currentpicture))+(2,-13));\n"                
    
+    return context_menu
+
+def create_uml(diagram, context='', scale=1.0):
+    """
+    """
+    if not 
os.path.isfile(slashify(config.mp_directory)+diagram+config.midfix+'.uml'):
+        raise MetapostException(slashify(config.mp_directory) \
+                                +diagram+config.midfix+'.uml'+' not found')
+    if not 
os.path.isfile(slashify(config.mp_directory)+diagram+config.midfix+'.mp'):
+        raise MetapostException(slashify(config.mp_directory) \
+                                +diagram+config.midfix+'.mp'+' not found')
+    
+    s_file = open(slashify(config.mp_directory)+diagram+config.midfix+'.uml')
+    s = s_file.read()
+    s_file.close()
+    l = navidoc.util.parser.parse_indented(s)
+    m = navidoc.parser.ElementList(l)
+
+    draw_extra = ''
+
+    if len(context) > 0:
+        context = '_'+context
+        if config.mp_context_menu: draw_extra = context_menu(diagram);
+    config.mp_context_menu = 0
+
+    dir = slashify(config.mp_directory)
+
+    gen1 = open(dir+diagram+context+config.midfix+'.mp.2', 'w')
+    gen1.write(m.setup_code()+'\n')
+    gen1.close()
+    gen2 = open(dir+diagram+context+config.midfix+'.mp.3', 'w')
+    gen2.write(m.draw_code()+"\n")
+    gen2.write(draw_extra+"\n")
+
+    global rough_edges
+    for rough_bbox in rough_edges:
+        """Print stored roughEdges now, on top of everything else."""
+        gen2.write('drawRoughEdge(('+rough_bbox+'), (bbox currentpicture), 
('+str(scale)+'));'+"\n")
+    gen2.write('showlinksize("bbox", "'+diagram+'", (bbox 
currentpicture));'+"\n")
+    gen2.close()
+    rough_edges = []
+
+    midfix = config.midfix
+    gen3 = open(dir+diagram+context+config.midfix+".mp.4", "w")
+    gen3.write("""
+       prologues := 1;
+        """)
+    for include in config.mp_includes:
+        gen3.write("""
+       input """+slashify(relative_path(config.mp_directory, 
'navidoc/mp/'))+include)
+    gen3.write("""        
+       beginfig(1)
+           input %(diagram)s%(context)s%(midfix)s.mp.2
+           input %(diagram)s%(midfix)s.mp
+           input %(diagram)s%(context)s%(midfix)s.mp.3
+       endfig
+       end
+       """ % locals())
+    gen3.close()
+
+    mp2png(diagram+context, scale)
+
+def mp2png(diagram, scale=1.0):
+    """
+    """
+    config.dbg.out('navidoc', 'Compiling diagram '+diagram)
+
+    syscmd = config.metapost+' --file-line-error-style ' \
+             + '--interaction nonstopmode ' \
+             + diagram + config.midfix + '.mp.4 >'+config.stderr
+
+    dbg(syscmd)
+    os.system('cd '+config.mp_directory+';'+syscmd)
+
+    if config.mp_eps_only:
+        if config.midfix.startswith('.'):
+            midfix = '_'+config.midfix[1:]
+        else: midfix = config.midfix
+        os.rename(slashify(config.mp_directory)+diagram+config.midfix+'.mp.1',
+                  slashify(config.mp_directory)+diagram+midfix+'.eps')
+        return
+
+    log_file = 
open(slashify(config.mp_directory)+diagram+config.midfix+'.mp.log')
+    log = log_file.read()
+    log_file.close()
+    
+    if log.find("\n"+'!') != -1:
+        dbg_navidoc('[mp] Converting diagram %s failed.' % (diagram))
+        dbg_fail('An error was found from MetPost log when convertin diagram 
%s. The log is shown below.' % (diagram))
+        dbg_fail(log)
+    
+    links = []
+    log = log.replace("\n",'') # mpost splits lines awkwardly in the log.
+
+    bbox = 0
+    scaling = 2
+    list = ''
+
+    # grep all linked areas from log file
+    for link in re.findall('\"LINKRECT\((.*?)\)\"', log):
+        dbg(link)
+       els = link.split(',')
+       if els[0] == '"bbox"':
+           bbox = els
+       else:
+            dbg(els)
+           links.append(MPLink(els))
+    dbg(bbox)
+
+    # Scale the bounding box and prepares it for pstopnm
+    if (bbox):
+        bbox = psbbox(bbox[2:])
+        list = bbox.pstopnm(scaling)
+    dbg(bbox)
+
+    scaling = int(scaling / scale)
+
+    dbg("List: "+str(list))
+    syscmd = config.pstopnm+' '+' '.join(list)+' 
<'+slashify(config.mp_directory)+diagram+config.midfix \
+             +'.mp.1 2>'+config.stderr+' | '+config.pnmscale+" -reduce 
%s"%(scaling)+' 2>'+config.stderr+' | '  \
+             +config.pnmtopng+' -transparent =white 
>'+slashify(config.mp_directory) \
+             +diagram+config.midfix+'.png 2>'+config.stderr
+
+    dbg(syscmd)
+    os.system(syscmd)
+
+class psbbox:
+    """
+    PostScriptBoundingBox.
+    """
+    def __init__(self, els):
+       self.x=(int(float(els[0])), int(float(els[2])))
+       self.y=(int(float(els[1])), int(float(els[3])))
+       self.scale = 1 # 1 point = 1 pixel
+       self.w = self.scale*(self.x[1]-self.x[0])
+       self.h = self.scale*(self.y[0]-self.y[1])
+    def map_point(self, x, y):
+       return (self.scale * (x - self.x[0]), 
+               self.h - self.scale * (y - self.y[1])); # reverse y
+    def pstopnm(self, scale):
+       dpi = 72.0
+       return ["%s"%r for r in [ "-llx", self.x[0]/dpi, "-lly", self.y[1]/dpi,
+               "-urx", self.x[1]/dpi, "-ury", self.y[0]/dpi,
+               "-xsize", self.w * scale, "-ysize", self.h * scale,
+               "-xborder", 0, "-yborder", 0]]
+
+class MPLink:
+    def __init__(self, elements):
+        """
+        Initilize MetaPost link. Parse link target, title and corners
+        of linked area from elements read from MP log file.
+        """
+       self.target = re.match('^"(.*)"$', elements[0]).group(1)
+       self.title = re.match('^"(.*)"$', elements[1]).group(1)
+       self.corners = [float(element) for element in elements[2:]]
+       dbg("Link init: "+self.title)
+
+    def map_corners(self, mapper):
+        """
+        Map exact coordinates from corner elements using
+        provided mapper.
+        """
+       dbg("Unmapped corners: "+str(self.corners))
+       self.corners = [int(element) for element in (
+           mapper(self.corners[0], self.corners[1]) +
+           mapper(self.corners[2], self.corners[3]) 
+            )]
+        dbg("Mapped corners: "+str(self.corners))
+
+    def imgmapanchor(self, scale=1.0, diagram='', context=''):
+        # Adding javascript thingy, when target not defined
+        if context.endswith('_implicit'):
+            id_postfix = ''
+            context = context[:len(context)-len('_implicit')]
+        else:
+            id_postfix = '_implicit'
+            context = context + '_implicit'
+            
+        if self.target == '' and diagram and context:
+            self.target = "javascript:setImg('"+diagram+"_img', 
'"+slashify(relative_path(config.working_directory, 
config.mp_directory))+diagram+context+config.midfix+".png', 
'#"+diagram+id_postfix+"_map')"
+
+        if not self.target.startswith('javascript'): diagram = '#'+diagram
+        else: diagram = ''
+
+        return """<area href="%s%s" shape="rect" coords="%s" target="%s" 
title="%s" alt="%s" />""" \
+               % (self.target, diagram,
+                  ",".join(["%s"%(int(c*scale)) for c in self.corners]), 
'_top',
+                  self.title, self.title)
+
+class MetapostException(Exception):
+    def __init__(self, value):
+        Exception.__init__(self)
+        self.value = value
+    def __str__(self):
+        return self.value
+
+def round_down(x):
+    return int(float(x) - 5)
+def round_up(x):
+    return int(float(x) + 5)
Index: navidoc/navidoc/mp/html.py
diff -u /dev/null navidoc/navidoc/mp/html.py:1.4.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/mp/html.py  Mon Jun 30 11:30:15 2003
@@ -0,0 +1,79 @@
+# 
+# Copyright (c) 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+# $Id: html.py,v 1.4.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+import config
+
+import re
+
+import navidoc
+
+dbg = config.dbg.shorthand('html')
+
+class mppage(navidoc.mp.MetapostElement):
+    key = 'page'
+    def __init__(self, var, toks, list):
+       dbg("mppage: %s %s %s" % (var, toks, list))
+        if not var and len(toks) == 1: var = toks[0]
+        if not var: raise navidoc.mp.uml.UMLException('No variable name given 
for page (%s).' %(' '.join(toks)))
+        self.var = var
+        self.name = var
+        self.title = ' '.join(toks)
+
+        # Remove possible quotes
+        if self.title.startswith('"') and self.title.endswith('"'):
+            self.title = self.title[1:len(self.title)-1]
+
+       self.do_contents(list)
+        if self.link != None:
+            self.link.bbox = ('bboxmeasuredpic(%s)' % (self.var))
+    def setup_code(self):
+       s = """
+           picture %%.pict;
+           %%.pict = classTitle("""+'"'+self.title+'"'+""");
+            picture %%.page;
+            %%.page = nullpicture;
+           addto %%.page doublepath 
((0,5)--(0,38)--(7,45)--(35,45)--(35,5)--cycle) withpen currentpen;
+           addto %%.page doublepath ((0,38)--(7,38)--(7,45)) withpen 
currentpen;
+           addto %%.page doublepath ((12,37)--(30,37)) withpen currentpen;
+           addto %%.page doublepath ((12,32)--(30,32)) withpen currentpen;
+           addto %%.page doublepath ((6,27)--(30,27)) withpen currentpen;
+           addto %%.page doublepath ((6,22)--(30,22)) withpen currentpen;
+           addto %%.page doublepath ((6,17)--(30,17)) withpen currentpen;
+           addto %%.page doublepath ((6,12)--(30,12)) withpen currentpen;
+            addto %%.pict also %%.page shifted (center(%%.pict) + (-17, 5));
+            setbounds %%.pict to bbox %%.pict;
+           picmeasurements(%%);
+            """
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           draw bboxmeasuredpic(%%);
+           """ 
+       return self.repl(s)
Index: navidoc/navidoc/mp/uml.py
diff -u /dev/null navidoc/navidoc/mp/uml.py:1.21.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/mp/uml.py   Mon Jun 30 11:30:15 2003
@@ -0,0 +1,610 @@
+# 
+# Copyright (c) 2002, 2003 Tuomas Lukka, Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+# $Id: uml.py,v 1.21.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Tuomas Lukka, Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+import config
+
+import re
+
+from navidoc.util.parser import *
+
+dbg = config.dbg.shorthand('uml')
+
+class UMLException(Exception):
+    def __init__(self, value):
+        Exception.__init__(self)
+        self.value = value
+    def __str__(self):
+        return self.value
+
+class mpsequence(navidoc.Element):
+    key = 'sequence'
+    
+    def getVarForY(self, before, after):
+       """Get a variable name for a Y coordinate.
+       Padding before and after.
+       """
+       v1 = random_var()
+       v2 = random_var()
+       yvar = self.yvar
+       self.ycode += """
+           numeric %(v1)s, %(v2)s;
+           %(v2)s = %(yvar)s - %(before)s - %(after)s;
+           %(v1)s = %(yvar)s - %(before)s;
+       """ % locals()
+       self.yvar = v2
+       return v1;
+
+    class call:
+       def __init__(self, parent, sourcex, toks, list):
+           self.var = random_var()
+           self.parent = parent
+           self.targetx = "(xpart(%s.c))" % (toks[1])
+           self.targetname = toks[1]
+           if toks[1] not in parent.seqobjs:
+               parent.seqobjs.append(toks[1])
+           if sourcex == None:
+               # self.sourcex = "(" + self.targetx + " - 100)"
+               self.sourcex = "-50"
+           else:
+               self.sourcex = sourcex
+           if len(toks) > 2:
+               self.text = " ".join(toks[2:])
+           else:
+               self.text = "\"\""
+           self.list = parent.parse_contents(self.targetx, list)
+       def setup_code(self):
+           return " ".join([el.setup_code() for el in self.list])
+       def measure(self):
+           self.yu = self.parent.getVarForY(5,5)
+           for el in self.list:
+               el.measure()
+           self.yl = self.parent.getVarForY(0, 15)
+       def draw_code_measure(self):
+           s = """
+               sequencecallmeasure(%(sourcex)s, %(targetx)s, %(yu)s, %(yl)s, 
%(text)s);
+           """ % self.__dict__;
+           return s + " ".join([el.draw_code_measure() for el in self.list])
+       def draw_code_draw(self):
+           s = """
+               sequencecall(%(sourcex)s, %(targetx)s, %(yu)s, %(yl)s, 
%(text)s);
+           """ % self.__dict__;
+           return s + " ".join([el.draw_code_draw() for el in self.list])
+
+    class delete(call):
+       def draw_code_measure(self):
+           s = mpsequencel.call.draw_code_measure(self)
+           self.parent.seqobjsdeletes[self.targetname] = self.yl;
+           return s
+
+       def draw_code_draw(self):
+           s = mpsequencel.call.draw_code_draw(self)
+           return (s + 
+            " sequencedestroy( %(targetx)s, %(yl)s ); " 
+                   % self.__dict__)
+
+    class create(call):
+       def measure(self):
+           self.yu = self.parent.getVarForY(10,10)
+           for el in self.list:
+               el.measure()
+           self.yl = self.parent.getVarForY(20, 20)
+       def draw_code_measure(self):
+           s = """
+               sequencecreatemeasure(%(sourcex)s, %(targetname)s, %(yu)s, 
%(yl)s, %(text)s);
+           """ % self.__dict__;
+           return s + " ".join([el.draw_code_measure() for el in self.list])
+
+       def draw_code_draw(self):
+           s = """
+               sequencecreate(%(sourcex)s, %(targetname)s, %(yu)s, %(yl)s, 
%(text)s);
+           """ % self.__dict__;
+           return s + " ".join([el.draw_code_draw() for el in self.list])
+
+    def __init__(self, var, toks, list):
+        dbg("mpsequence: %s %s %s" % (var, toks, list))
+       self.seqobjs = []
+       self.seqobjsdeletes = {}
+       s = toks[0]
+       self.var = var or s
+       self.name = s
+       self.list = self.parse_contents(None, list)
+       self.ycode = ""
+
+    def parse_contents(self, source_name, list):
+       l = []
+       for el in list:
+           toks = el[0]
+           s = toks[0]
+           if s == "call":
+               l.append(self.call(self, source_name, toks, el[1:]))
+           elif s == "delete":
+               l.append(self.delete(self, source_name, toks, el[1:]))
+           elif s == "create":
+               l.append(self.create(self, source_name, toks, el[1:]))
+           elif s == "return":
+               pass
+           else:
+               raise UMLException("Must have call or return, not '"+s+"'")
+       return l
+    def setup_code(self):
+       return self.repl(
+           " ".join([el.setup_code() for el in self.list])
+           )
+    def lifeend(self, obj):
+       return self.seqobjsdeletes.get(obj, self.yvar)
+    def draw_code(self):
+       self.yvar = random_var()
+       self.ycode = "numeric %(yvar)s; %(yvar)s = -50;" % self.__dict__;
+       for el in self.list:
+           el.measure()
+       m = self.ycode
+       m += " ".join([el.draw_code_measure() for el in self.list])
+       m += " ".join([
+           "sequencedrawlifeline(%s, %s);" % (seqobj, self.lifeend(seqobj))
+            for seqobj in self.seqobjs
+            ])
+       m += " ".join([el.draw_code_draw() for el in self.list])
+       return self.repl(m)
+    def repl(self, s):
+       s = s.replace("%%", self.var)
+       return s
+
+class mpclass(navidoc.mp.MetapostElement):
+    key = 'class'
+    def __init__(self, var, toks, list):
+       dbg("mpclass: %s %s %s" % (var, toks, list))
+       self.var = var or toks[0]
+       self.name = toks[0]
+
+       self.stereo = None
+       for tok in toks:
+           mat = re.match('^"(.*)"$', tok)
+           if mat: self.stereo = mat.group(1)
+
+       self.methods = self.fields = []
+       self.do_contents(list)
+        if self.link:
+            self.link.bbox = ('bboxmeasuredpic(%s)' %(self.var))             
+    def handle_contained(self, el):
+       if el[0][0] == "fields":
+           self.methods = el[1:]
+       elif el[0][0] == "methods":
+           self.fields = el[1:]
+       else:
+           navidoc.mp.MetapostElement.handle_contained(self, el)
+    def setup_code(self):
+       s = """
+           picture %%.cls, %%.pict, %%.meth, %%.sep, %%.fiel, %%.stereo;
+           numeric %%.maxwid;
+           %%.cls = classTitle("%name%");
+           %%.meth = stackStrings(defaultfont, 1, METHODS);
+           %%.fiel = stackStrings(defaultfont, 1, FIELDS);
+           STEREO
+
+           maxwid(%%.maxwid, %%.stereo);
+           maxwid(%%.maxwid, %%.cls);
+           maxwid(%%.maxwid, %%.meth);
+           maxwid(%%.maxwid, %%.fiel);
+
+           maxwidctr(%%.maxwid, %%.stereo);
+           maxwidctr(%%.maxwid, %%.cls);
+
+           %%.sep = nullpicture;
+            addto %%.sep doublepath (0,0)--(%%.maxwid,0) withpen currentpen;
+            """
+        if self.fields and self.methods:
+            s = s + """
+            %%.pict = stackpics(%%.stereo, %%.cls, %%.sep, %%.meth, %%.sep, 
%%.fiel);
+            """
+        elif self.fields or self.methods:
+            s = s + """
+            %%.pict = stackpics(%%.stereo, %%.cls, %%.sep, %%.meth, %%.fiel);
+            """
+        else:
+            s = s + """
+            %%.pict = stackpics(%%.stereo, %%.cls, %%.meth, %%.fiel);
+            """
+        s = s + """
+            setbounds %%.pict to bbox %%.pict;
+           picmeasurements(%%);
+           """
+       s = s.replace("FIELDS", ", ".join(
+           [ '"'+' '.join(m[0])+'"' for m in self.fields ] ))
+       s = s.replace("METHODS", ", ".join(
+           [ '"'+' '.join(m[0])+'"' for m in self.methods ] ))
+       if self.stereo:
+           s = s.replace("STEREO", 
+               "%%.stereo = stereotype(\"%stereo%\");")
+       else:
+           s = s.replace("STEREO", 
+               "%%.stereo = nullpicture;")
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           draw bboxmeasuredpic(%%);
+           """ 
+       return self.repl(s)
+
+class mppackage(navidoc.mp.MetapostElement):
+    key = 'package'
+    def __init__(self, var, toks, list):
+       dbg("mppackage: %s %s %s" % (var, toks, list))
+       self.var = var or toks[0]
+       self.name = toks[0]
+       self.do_contents(list)
+        if self.link != None:
+            self.link.bbox = ('bboxmeasuredpic(%s)' % (self.var))
+    def setup_code(self):
+       s = """
+           picture %%.pict;
+           %%.pict = classTitle("%name%");
+            setbounds %%.pict to bbox %%.pict;
+           picmeasurements(%%);
+           """
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           draw bboxmeasuredpic(%%);
+           draw (((0,0)--(15,0)--(15,5)--(0,5)--cycle) shifted %%.nw);
+           """ 
+       return self.repl(s)
+
+# XXX underlining
+class mpseqobject(navidoc.mp.SimpleElement):
+    key = 'seqobject'
+    def setup_code(self):
+       s = """
+           picture %%.titl, %%.pict;
+           picture %%.ghost.pict;
+           %%.titl = classTitle("%name%");
+           %%.pict = %%.titl;
+           addto %%.pict doublepath bbox %%.titl;
+           %%.ghost.pict = %%.titl;
+           picmeasurements(%%);
+           picmeasurements(%%.ghost);
+           xpart(%%.c) = xpart(%%.ghost.c);
+           """
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           if not known(ypart(%%.c)):
+               ypart(%%.c) = ypart(%%.ghost.c);
+           fi
+           drawmeasuredpic(%%);
+           """
+       return self.repl(s)
+
+class mpcomponent(navidoc.mp.SimpleElement):
+    key = 'component'
+    def setup_code(self):
+       s = """
+           picture %%.titl, %%.pict;
+           %%.titl = classTitle("%name%");
+           %%.pict = %%.titl;
+           addto %%.pict doublepath bbox %%.titl;
+            setbounds %%.pict to bbox %%.pict;
+           picmeasurements(%%);
+           """
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           """
+       return self.repl(s)
+
+class mpinterface(navidoc.mp.SimpleElement):
+    key = 'interface'
+    def setup_code(self):
+       s = """
+           picture %%.titl, %%.pict, %%.intlabel.pict;
+           %%.pict = nullpicture;
+           addto %%.pict doublepath (((0,1)..(1,0)..(0,-1)..(-1,0)..cycle) 
scaled 5);
+           %%.intlabel.pict = classTitle("%name%");
+
+           picmeasurements(%%);
+           picmeasurements(%%.intlabel);
+           """
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           if not known %%.intlabel.c:
+               %%.intlabel.nw = %%.se;
+           fi
+           drawmeasuredpic(%%.intlabel);
+           """
+       return self.repl(s)
+
+class mpnary(navidoc.mp.SimpleElement):
+    key = 'naryassoc'
+    def setup_code(self):
+       s = """
+           picture %%.pict;
+           %%.pict = naryassoc;
+           picmeasurements(%%);
+           """
+       return self.repl(s)
+    def draw_code(self):
+       s = """
+           drawmeasuredpic(%%);
+           """
+       return self.repl(s)
+
+class mpbigpackage(navidoc.mp.MetapostElement):
+    key = 'bigpackage'
+    def __init__(self, var, toks, list):
+       dbg("mpbigpackaget: %s %s %s" % (var, toks, list))
+        self.elements = []
+       self.var = var or toks[0]
+       self.name = toks[0]
+       self.do_contents(list)
+
+        if self.link != None:
+            self.link.bbox = ('bboxmeasuredpic(%s)' % (self.var))
+    def handle_contained(self, element):
+        element = config.element_list.parse_element(element)
+        config.element_list.list.append(element)
+        if hasattr(element, 'var') and element.var:
+            self.elements.append(element.var)
+    def setup_code(self):
+        titlebox = """
+           addto %%.titl.pict doublepath 
(urcorner(%%.titl.pict)--lrcorner(%%.titl.pict)) withpen currentpen;
+           addto %%.titl.pict doublepath 
(ulcorner(%%.titl.pict)--llcorner(%%.titl.pict)) withpen currentpen;
+           addto %%.titl.pict doublepath 
(ulcorner(%%.titl.pict)--urcorner(%%.titl.pict)) withpen currentpen;
+            """
+       s = """
+           picture %%.titl.pict;
+           %%.titl.pict = classTitle("%name%");
+            setbounds %%.titl.pict to bbox %%.titl.pict;
+            """
+        if not self.elements: s = s + titlebox
+        s = s + """
+           unknownpicmeasurements(%%);
+           picmeasurements(%%.titl);
+           %%.titl.sw = %%.nw;
+           """
+        if self.elements: s = s + titlebox
+       return self.repl(s)
+    def draw_code(self):
+        s = ''
+        if self.elements:
+            elements_sw_x = 'xpart ' + '.sw, xpart '.join(self.elements) + 
'.sw'
+            elements_sw_y = 'ypart ' + '.sw, ypart '.join(self.elements) + 
'.sw'
+            elements_ne_x = 'xpart ' + '.ne, xpart '.join(self.elements) + 
'.ne'
+            elements_ne_y = 'ypart ' + '.ne, ypart '.join(self.elements) + 
'.ne'
+            
+            s = """
+            %%.sw = (min("""+elements_sw_x+"""), min("""+elements_sw_y+""")) - 
(10,10);
+            %%.ne = (max("""+elements_ne_x+"""), max("""+elements_ne_y+""")) + 
(10,10);
+            """
+        s = s + """
+            draw bboxmeasuredpic(%%);
+            drawmeasuredpic(%%.titl);
+            """
+       return self.repl(s)
+
+class mpqual(navidoc.mp.MetapostElement):
+    key = 'qual'
+    def __init__(self, var, toks, list):
+       self.var = var or toks[0]
+       self.name = toks[0]
+       self.fields = []
+       self.do_contents(list)
+    def handle_contained(self, el):
+       if el[0][0] == "fields":
+           self.fields = el[1:]
+       else:
+           navidoc.mp.MetapostElement.handle_contained(self, el)
+    def setup_code(self):
+       s = """
+           picture %%.pict;
+           %%.pict = stackStrings(defaultfont, 1, FIELDS);
+           addto %%.pict doublepath bbox(%%.pict) ;
+           picmeasurements(%%);
+           """
+       s = s.replace("FIELDS", ", ".join(
+           [ '"'' '+' '.join(m[0])+'"' for m in self.fields ] ))
+       return self.repl(s)
+
+class mpassoc(navidoc.mp.MetapostElement):
+    key = 'assoc'
+    class end(navidoc.mp.MetapostElement):
+       def __init__(self, var, list):
+           self.var = var
+           self.name = ""
+           self.obj = list.pop(0)
+           self.type = ""
+           self.role = " "
+           self.multi = " "
+           while len(list) > 0:
+               el = list.pop(0)
+               if el == "-":
+                   return
+               elif el == "aggreg" or el == "compos":
+                   self.type = el
+               else:
+                   mat = re.match("^multi\((.*)\)$", el)
+                   if mat:
+                       self.multi = mat.group(1)
+                       continue
+                   mat = re.match("^role\((.*)\)$", el)
+                   if mat:
+                       self.role = mat.group(1)
+                       continue
+                   mat = re.match("^multi\((.*)\)$", el)
+                   if mat:
+                       self.multi = mat.group(1)
+                       continue
+                   raise UMLException("Invalid assoc adorn "+el)
+       def setup_code(self):
+           s = """
+               picture %%.multi, %%.role;
+               path %%.p;
+               %%.multi = adornmentName("MULTI");
+               %%.role = adornmentName("ROLE");
+               """
+           s = s.replace("MULTI", self.multi).replace("ROLE", self.role)
+           return self.repl(s)
+       def draw_code(self):
+           s = """
+               %sassoc(%%.p, %%.multi, %%.role);
+               """
+           s = self.repl(s) % self.type;
+           return s
+
+           
+    def __init__(self, var, toks, list):
+        dbg("mpassoc: %s %s %s" % (var, toks, list))
+       self.var = var or random_var()
+       self.name = ""
+
+        # XXX This might not be a good idea. Anyway, the point is to allow
+        # creating very simple assoc with only "assoc foo" without '-' at 
start.
+        # as in "assoc - foo".
+        if toks.count('-') == 0:
+            toks.insert(1, '-')
+            
+       self.a = self.end(self.var+".a", toks)
+       toks.reverse()
+       self.b = self.end(self.var+".b", toks)
+
+    def setup_code(self):
+       s = """
+           path %%.p;
+           """ + self.a.setup_code() + self.b.setup_code() 
+       return self.repl(s) 
+    def draw_code(self):
+       s = """
+           if not known %%.p:
+               %%.p = backuppath(START, END);
+               show %%.p;
+           else:
+               %%.p := clipmeasuredpath(START, END, %%.p);
+           fi
+           %%.a.p = subpath(0,0.5*length(%%.p)) of %%.p;
+           %%.b.p = subpath(length(%%.p),0.5*length(%%.p)) of %%.p;
+           """ + self.a.draw_code() + self.b.draw_code() 
+       return self.repl(s).replace("START", self.a.obj).replace("END", 
self.b.obj)
+
+class SimpleRelation(navidoc.mp.MetapostElement):
+    def __init__(self, var, toks, list):
+        dbg("SimpleRelation: %s %s %s" % (var, toks, list))
+       self.var = var or random_var()
+       self.name = ""
+        if len(toks) != 2:
+            raise UMLException('Error when creating SimpleRelation (%s). 
len(toks) != 2.' % (' '.join(toks)))
+       self.start = toks[0]
+       self.end = toks[1]
+    def setup_code(self):
+       s = """
+           path %%.p;
+           """
+       return self.repl(s) 
+    def pathCode(self):
+       s = """
+           if not known %%.p:
+               %%.p = backuppath(START, END);
+               show %%.p;
+           else:
+               %%.p := clipmeasuredpath(START, END, %%.p);
+           fi
+           """
+       return self.repl(s).replace("START", self.start).replace("END", 
self.end)
+
+class mpsupply(SimpleRelation):
+    key = 'supply'
+    def draw_code(self):
+       return self.pathCode() + self.repl(" draw %%.p; ")
+
+class mpuse(SimpleRelation):
+    key = 'use'
+    def draw_code(self):
+       return self.pathCode() + self.repl(" drawarrow %%.p dashed evenly; ")
+
+class mprealize(SimpleRelation):
+    key = 'realize'
+    def draw_code(self):
+       return self.pathCode() + self.repl(" realize(%%.p); ")
+
+class mpinherit(SimpleRelation):
+    key = 'inherit'
+    def draw_code(self):
+       return self.pathCode() + self.repl(" inherit(%%.p); ")
+
+class mpdep(SimpleRelation):
+    key = 'dep'
+    def __init__(self, var, toks, list):
+        if len(toks) < 3: raise UMLException("Not enough arguments for 'dep' 
%s." % (' '.join(toks)))
+        if len(toks) > 3: raise UMLException("Too many arguments for 'dep' 
%s." %(' '.join(toks)))
+        self.stereo = None
+       for tok in toks:
+           mat = re.match('^"(.*)"$', tok)
+           if mat:
+                self.stereo = mat.group(1)
+                toks.remove(tok)
+        if self.stereo == None: raise UMLException("Dependency role not given 
in %s." %(' '.join(toks)))
+       SimpleRelation.__init__(self, var, toks, list)
+    def draw_code(self):
+       return self.pathCode() + self.repl(' dep(%%.p, "%stereo%"); ')
+
+#All placements are done in metapost code and these are deprecated
+
+#class placement(navidoc.mp.MetapostElement):
+#    def __init__(self, var, toks, list):
+#      self.var = var or random_var()
+#      self.name = ""
+#        (self.start, self.end, self.length) = toks
+#    def draw_code(self):
+#        return ""
+
+#class above(placement):
+#    key = 'above'
+#    def setup_code(self):
+#        return self.repl(' vertically(%s, %s, %s, %s);' %
+#                         (self.length, self.var, self.start, self.end))
+
+#class under(placement):
+#    key = 'under'
+#    def setup_code(self):
+#        return self.repl(' vertically(%s, %s, %s, %s);' %
+#                         (self.length, self.var, self.end, self.start))
+
+#class leftOf(placement):
+#    key = 'leftof'
+#    def setup_code(self):
+#        return self.repl(' horizontally(%s, %s, %s, %s);' %
+#                         (self.length, self.var, self.start, self.end))
+
+#class rightOf(placement):
+#    key = 'rightof'
+#    def setup_code(self):
+#        return self.repl(' horizontally(%s, %s, %s, %s);' %
+#                         (self.length, self.var, self.end, self.start))
Index: navidoc/navidoc/mp/vobs.py
diff -u /dev/null navidoc/navidoc/mp/vobs.py:1.1.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/mp/vobs.py  Mon Jun 30 11:30:15 2003
@@ -0,0 +1,62 @@
+# 
+# Copyright (c) 2002, 2003 by Tuomas Lukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+# $Id: vobs.py,v 1.1.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Tuomas Lukka
+#
+
+__docformat__ = 'reStructuredText'
+
+import config
+
+import re
+
+import navidoc
+
+dbg = config.dbg.shorthand('uml')
+
+class mpvobtransform(navidoc.mp.uml.mpassoc):
+    key = 'vobtransform'
+    def __init__(self, var, toks, list):
+       navidoc.mp.uml.mpassoc.__init__(self, var, toks, list)
+       self.a.type = "vobtransformfrom"
+       self.b.type = "vobtransformto"
+
+class mpvobtransformsub(navidoc.mp.uml.mpassoc):
+    key = 'vobtransformsub'
+    def __init__(self, var, toks, list):
+       navidoc.mp.uml.mpassoc.__init__(self, var, toks, list)
+       self.a.type = "vobtransformfromsub"
+       self.b.type = "vobtransformtosub"
+
+class mpvobin(navidoc.mp.uml.mpassoc):
+    key = 'vobin'
+    def __init__(self, var, toks, list):
+       navidoc.mp.uml.mpassoc.__init__(self, var, toks, list)
+       self.a.type = "vobinfrom"
+       self.b.type = "vobinto"
+
+class mpvobsubmatch(navidoc.mp.uml.SimpleRelation):
+    key = 'vobsubmatch'
+    def draw_code(self):
+       return self.pathCode() + self.repl(" vobsubmatch(%%.p); ")
Index: navidoc/navidoc/parser.py
diff -u /dev/null navidoc/navidoc/parser.py:1.19.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/parser.py   Mon Jun 30 11:30:15 2003
@@ -0,0 +1,201 @@
+# 
+# Copyright (c) 2002, 2003 Tuomas Lukka, Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+# $Id: parser.py,v 1.19.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Tuomas Lukka, Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+import config
+
+import mp, link
+
+from util.parser import *
+
+dbg = config.dbg.shorthand('parser')
+
+class ElementFactor:
+    """
+    Factor to build elements imported from 'navidoc.mp' and navidoc.link'.
+    """
+
+    top_class = navidoc.Element # Elements must be inherited from the top_class
+
+    def __init__(self, module_paths):
+        self.types = {}
+        # Gathers elements from modules.
+        for module_path in module_paths:
+            dbg ("Checking module: "+str(module_path))
+            self.types.update(keys_for_classes(module_path, self.top_class))
+            for module in dir(module_path):
+                if module not in ['os', 're']: module = getattr(module_path, 
module)
+                if type(module) == type(navidoc):
+                    dbg ("Checking module: "+str(module))
+                    # XXX Needs check for conflicting element types and raise 
an exception
+                    self.types.update(keys_for_classes(module, self.top_class))
+        dbg("Collected: "+str(self.types))
+
+    def is_type(self, key): return self.types.has_key(key)
+        
+    def get_type(self, key):
+        """
+        get_type(key)
+
+        Return a class reference for correct element type referred by
+        the key.
+        """
+        if self.types.has_key(key):
+            return self.types[key]
+       else: raise ParserException("Unknown element key: "+key)
+
+    def create_new(self, key, var, s, list):
+        """
+        create_new(key, var, s, list)
+
+        Create and return a new element of given type. ``Var`` is name
+        identifier of the new element, ``s`` parameters for it and
+        ``list`` contains all its subelements.
+        """
+        type = self.get_type(key)
+        dbg("Found element: "+str(type))
+        new = type(var, s, list)
+        return new
+
+class ElementList:
+    """
+    Container class for parsed elements. Provide the interface
+    to generate all rendering code for its elements.
+    """
+    def __init__(self, list):
+        """
+        Initializes ElementList by parsing all elements in list.
+        """
+        dbg("List: "+str(list))
+        for key in config.linkpackages.keys():
+            config.linkpackages[key] = ''
+        config.element_list = self # XXX
+        self.factor = ElementFactor([mp, link])
+        self.list = []
+        self.extras = []
+        for element in list:
+            element = self.parse_element(element)
+            # Borders of linked elements should be drawn before element itself.
+            # Move link border element from ``extras`` stack into ``elements``
+            # in front of the linked element.
+            if len(self.extras) > 0 and \
+                   isinstance(self.extras[0], navidoc.link.Link):
+                self.list.append(self.extras.pop(0))
+            self.list.append(element)
+        self.list.extend(self.extras)
+
+    def add_contained_element(self, super, elements):
+        """
+        add_contained_element(super, elements)
+        
+        Add a subelement.
+        """
+       toks = elements[0]
+        key = toks[0]
+        toks.remove(key)
+
+        # XXX Why no explicit var is given?
+        if super.var != None: toks.insert(0, super.var)
+        else: toks.insert(0, super.name)
+        element = self.factor.create_new(key, None, toks, elements[1:])
+
+        if isinstance(element, navidoc.link.Link):
+            # mpclass may have different var and name, links should be based 
on name
+            # and need special handling :/
+            if isinstance(element, navidoc.link.Link) and super.var != 
super.name:
+                toks[0] = super.name
+                element = self.factor.create_new(key, None, toks, elements[1:])
+            super.link = element
+            self.extras.insert(0, element)
+        else: self.extras.append(element)
+            
+    def parse_element(self, element):
+        """
+        parse_element(element)
+        
+        Parse a single element.
+        """
+
+       init = element[0]
+        name = None
+
+        # Catch explicit variable name from "element (foo) foo1"
+        for tok in init:
+            mat = re.match('^\((.*)\)$', tok)
+            if mat:
+                name = mat.group(1)
+                init.remove(tok)
+
+        # Catch explicit variable name from "foo = element foo1"
+        if init.count('='):
+            if init.index('=') != 1:
+                raise ParserException('Variable preceding "=" cannot ' \
+                                      +'contain any whitespaces in "%s".' % ' 
'.join(init))
+            if len(init) < 3:
+                raise ParserException('Missing element name in "%s".' % ' 
'.join(init))
+            name = init[0]
+            init = init[2:]
+
+        dbg('Creating %s %s %s %s.' % (init[0], name, init[1:], element[1:]))
+        element = self.factor.create_new(init[0], name, init[1:], element[1:])
+
+        # element's variable name can't contain any numbers
+        if hasattr(element, 'var') and element.var:
+            can_s = re.subn('[0-9]', '', element.var)[0]
+            if can_s != element.var: raise ParserException(
+"""
+Class variable name %s contains numbers.
+Please, use syntax "foo = class foo123" or "class (foo) foo123"
+and refer it later using "foo".'
+""" % (element.var))
+
+        if isinstance(element, navidoc.link.Link):
+            element.bbox = 'bboxmeasuredpic(%s)' % (element.var)
+
+        return element
+
+    def setup_code(self):
+       """
+        Return the code to set up the objects for user geometry code.
+        """
+       return "\n".join([element.setup_code() for element in self.list]) + "\n"
+
+    def draw_code(self):
+       """
+        Return code to draw the objects after the user code.
+        """
+       code = "\n".join([element.draw_code() for element in self.list]) + "\n"
+       return code
+
+class ParserException(Exception):
+    def __init__(self, value):
+        Exception.__init__(self)
+        self.value = value
+    def __str__(self):
+        return self.value
+
Index: navidoc/navidoc/util/debug.py
diff -u /dev/null navidoc/navidoc/util/debug.py:1.2.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/util/debug.py       Mon Jun 30 11:30:15 2003
@@ -0,0 +1,99 @@
+# 
+# Copyright (c) 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: debug.py,v 1.2.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+"""
+Navidoc debug.
+"""
+
+class DebugFilter:
+    """
+    Navidoc debug stream handler class.
+    """
+
+    short = "d:D:"
+    long = ["--dbg="]
+    all = ["-d", "-D"] + long
+
+    output_enabled = {}
+    buffer = {}
+
+    def __init__(self):
+        pass
+
+    def enable(self, dbg_name):
+        """
+        enable(self, dbg_name)
+        
+        Enable output of a named debug stream.
+        """
+        self.output_enabled[dbg_name] = 1
+
+    def mute(self, dbg_name):
+        """
+        mute(self, dbg_name)
+        
+        Mute output of a named debug stream.
+        """
+        self.output_enabled[dbg_name] = 0
+
+    def out(self, dbg_name, dbg_str):
+        """
+        out(self, dbg_name, dbg_str)
+
+        Print string to a named debug stream.
+        If the debug stream is muted, add string into
+        its buffer.
+        """
+        if self.output_enabled.has_key(dbg_name) \
+               and self.output_enabled[dbg_name]:
+            print "[", dbg_name, "]", dbg_str
+        else:
+            if not self.buffer.has_key(dbg_name):
+                self.buffer['dbg_name'] = []
+            self.buffer['dbg_name'].append(dbg_str)
+
+    def shorthand(self, dbg_name):
+        """
+        shorthand(self, dbg_name)
+
+        Return shorthand for use of a named debug stream.
+        """
+        return lambda dbg_string, self=self, dbg_name=dbg_name: \
+                                        self.out(dbg_name, dbg_string)
+
+    def flush(self, dbg_name):
+        """
+        flush(self, dbg_name)
+
+        Flush the buffer of a named debug stream.
+        """
+        if self.buffer.has_key(dbg_name):
+            for line in self.buffer['dbg_name']:
+                print "[", dbg_name, "]", line
+            self.buffer['dbg_name'] = []
Index: navidoc/navidoc/util/path.py
diff -u /dev/null navidoc/navidoc/util/path.py:1.3.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/navidoc/util/path.py        Mon Jun 30 11:30:15 2003
@@ -0,0 +1,103 @@
+# 
+# Copyright (c) 2002, 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: path.py,v 1.3.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+import os.path
+
+def listdir(path, extensions, dirs=0):
+    """
+    listdir(path, extensions, dirs=0)
+
+    Quite specialized listdir, which return all directories and files
+    with specific extensions under given path. Nonrecursive.
+
+    Skipping files starting with '.' or including some of 'CVS', '#', '~'.
+    """
+    files = [f for f in os.listdir(path) if not f.startswith('.')
+             and not f == 'CVS' and '#' not in f and '~' not in f]
+
+    if extensions:
+        files = [f for f in files if extensions.count(f.split('.')[-1]) > 0 \
+                 or os.path.isdir(slashify(path)+f)]
+    if not dirs:
+        files = [f for f in files if os.path.isfile(slashify(path)+f)]
+    return files
+
+def slashify(path):
+    """
+    slashify(path)
+
+    End path with a trailing slash, if still necessary.
+    """
+    if len(path) > 0:
+        return (path+'/').replace('//','/')
+    return path
+
+def relative_path(source, target):
+    """
+    relative_path(source, target)
+
+    Return a relative filepath from the source filepath to the target
+    filepath.
+    """
+    import config
+    dbg = config.dbg.shorthand('path')
+
+    if source == None or len(source) == 0: return target
+
+    source = os.path.normpath(os.path.abspath(source))
+    target = os.path.normpath(os.path.abspath(target))
+
+    if os.path.isdir(source): source = slashify(source)
+    if os.path.isdir(target): target = slashify(target)
+
+    dbg('Source: %s, Target: %s' % (source, target)) 
+
+    depth = source.count('/')
+    source_parts = source.split('/')
+    target_parts = target.split('/')
+
+    parts = len(source_parts) < len(target_parts) \
+            and len(source_parts) or len(target_parts)
+
+    for i in range(parts):
+        if source_parts[i] != target_parts[i]:
+            parts = i
+            break
+
+    relative = ''.join(['../' for i in range(depth-parts)]) \
+               +''.join([target_parts[i+parts]+'/' \
+                         for i in range(len(target_parts)-parts)])
+
+    path = relative[0:len(relative)-1]
+
+    if path=='' and os.path.isdir(target): path = './'
+    elif path == '': path = os.path.basename(target)
+
+    dbg('Relative path: '+path)
+    return (path)
Index: navidoc/rst2any.py
diff -u /dev/null navidoc/rst2any.py:1.32.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/rst2any.py  Mon Jun 30 11:30:15 2003
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+
+# 
+# Copyright (c) 2002, 2003 by Asko Soukka
+# 
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
+
+#$Id: rst2any.py,v 1.32.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+__docformat__ = 'reStructuredText'
+
+"""
+The main frontend for running Navidoc.
+"""
+
+import config
+config.read_config(config, config.navidoc_conf)
+
+import sys, os, getopt
+
+import docutils.core
+
+import navidoc.directives
+import navidoc.modules
+
+from navidoc.util.path import *
+
+# Import parser "plugins" from 'navidoc/link' and 'navidoc/mp'
+config.mp_includes = listdir('navidoc/mp',['mp'],dirs=0)
+dirlist = listdir('navidoc/mp',['py'],dirs=0)
+for module in dirlist:
+    if module != '__init__.py': exec('import navidoc.mp.%s' % 
module[0:len(module)-3])
+
+dirlist = listdir('navidoc/link',['py'],dirs=0)
+for module in dirlist:
+    if module != '__init__.py': exec('import navidoc.link.%s' % 
module[0:len(module)-3])
+
+dbg = config.dbg.shorthand('navidoc')
+dbg_config = config.dbg.shorthand('config')
+
+# Docutils wants locales to be cleaned
+import locale
+try:
+    locale.setlocale(locale.LC_ALL, '')
+except:
+    pass
+
+# Catch actions from the command line
+try: sys.argv.remove('--imagemap'); imagemap = 1
+except ValueError: imagemap = 0
+
+try: sys.argv.remove('--latex'); latex = 1
+except ValueError: latex = 0
+
+try: sys.argv.remove('--html'); html = 1
+except ValueError: html = 0
+
+try: sys.argv.remove('--metalink'); metalink = 1
+except ValueError: metalink = 0
+
+try: sys.argv.remove('--navbar'); navbar = 1
+except ValueError: navbar = 0
+
+try: sys.argv.remove('--texture'); texture = 1
+except ValueError: texture = 0
+
+try: sys.argv.remove('--loop'); loop = 1
+except ValueError: loop = 0
+
+def rst2any(input):
+    """
+    rst2any(input)
+    
+    Run docutils for a single file.
+    """
+    last_dot = input.replace("../", "__/").rfind('.')
+    if last_dot != -1: output = input[:last_dot]
+    else: output = input
+
+    dbg_config('Working directory: '+config.working_directory)
+    dbg_config('Input file: '+config.input_filename)
+
+    if (config.read_navidoc_conf != config.navidoc_conf):
+        config.read_config(config, config.navidoc_conf)
+        navidoc.link.docxx.__init__() # init Doc++ linking information
+        # of course that could be done everytime, when processing a clink, 
but...
+        config.read_navidoc_conf = config.navidoc_conf
+
+    if html:
+        dbg('Compiling reST '+input)
+        output = output+config.midfix+'.html'
+        config.output_filename = os.path.basename(output)
+        dbg_config('Output file: '+config.output_filename)
+        args = '--config '+config.docutils_conf+' '+input+' '+output
+
+        config.mp_eps_only = 0
+        docutils.core.publish_cmdline(writer_name='html', argv=args.split())
+
+    if latex:
+        dbg('Compiling reST '+input)
+        output = output+config.midfix+'.latex'
+        config.output_filename = os.path.basename(output)
+        dbg_config('Output file: '+config.output_filename)
+        args = '--config '+config.docutils_conf+' '+input+' '+output
+
+        config.mp_eps_only = 1
+        docutils.core.publish_cmdline(writer_name='latex', argv=args.split())
+
+    config.output_filename = ''
+
+def postprocess(path):
+    """
+    postprocess(path)
+    
+    Run selected postprocessing modules.
+    """
+    
+    if imagemap:
+        if os.path.isfile(path):
+            last_dot = path.replace("../", "__/").rfind('.')
+            if last_dot != -1: path = path[:last_dot]+config.midfix+'.html'
+            
+        config.link_emphasize = 1
+        import navidoc.modules.imagemap
+        config.working_directory = os.path.normpath(os.path.dirname(path))
+        navidoc.modules.imagemap.postprocess(path)
+        config.link_emphasize = 0
+
+def run_docutils(path):
+    """
+    run_docutils(path)
+    
+    Select all reST files under ``path`` directory (or the single file
+    specified by ``path``) and forward them to conversion method.
+    """
+    if os.path.isdir(path) and not os.path.islink(path):
+       dirlist = listdir(path,['rst'],dirs=1)
+        if os.path.isfile(slashify(path) + 'docutils.conf'):
+            config.docutils_conf = slashify(path) + 'docutils.conf'
+        if os.path.isfile(slashify(path) + 'navidoc.conf'):
+            config.navidoc_conf = slashify(path) + 'navidoc.conf'
+        for entry in dirlist:
+            run_docutils(slashify(path)+entry)
+
+    elif os.path.isfile(path):
+        config.working_directory = os.path.normpath(os.path.dirname(path))
+        if os.path.isfile(slashify(config.working_directory) + 
'docutils.conf'):
+            config.docutils_conf = slashify(config.working_directory) + 
'docutils.conf'
+        if os.path.isfile(slashify(config.working_directory) + 'navidoc.conf'):
+            config.navidoc_conf = slashify(config.working_directory) + 
'navidoc.conf'
+        config.input_filename = os.path.basename(path)
+        rst2any(path)
+        
+    elif os.path.isfile(path+'.rst'):
+        config.working_directory = os.path.normpath(os.path.dirname(path))
+        if os.path.isfile(slashify(config.working_directory) + 
'docutils.conf'):
+            config.docutils_conf = slashify(config.working_directory) + 
'docutils.conf'
+        if os.path.isfile(slashify(config.working_directory) + 'navidoc.conf'):
+            config.navidoc_conf = slashify(config.working_directory) + 
'navidoc.conf'
+        config.input_filename = os.path.basename(path+'.rst')
+        rst2any(path+'.rst')
+    config.input_filename = ''
+    
+# Catch debug parameters
+dbg_names, sys.argv = getopt.getopt(sys.argv[1:], config.dbg.short, 
config.dbg.long)
+for dbg_name in dbg_names:
+    config.dbg.enable(dbg_name[1])
+    print 'Enabling debug output for:', dbg_name[1]
+
+# Conversion loop
+while 1:
+    
+    # The first pass; Docutils with Navidoc directives
+    for filepath in sys.argv:
+        try: 
+            run_docutils(filepath)
+        except navidoc.DocutilsException, e:
+            dbg("Fatal, DocutilsException: "+e.value)
+            break
+        except navidoc.parser.ParserException, e:
+            dbg("Fatal, ParserException: "+e.value)
+            break
+        except navidoc.mp.MetapostException, e:
+            dbg("Fatal, MetapostException: "+e.value)
+            break
+        except navidoc.mp.uml.UMLException, e:
+            dbg("Fatal, UMLException: "+e.value)
+            break
+
+    # The second pass; Postprocessing modules
+    for filepath in sys.argv:
+        try:
+            postprocess(filepath)
+        except navidoc.DocutilsException, e:
+            dbg("Fatal, DocutilsException: "+e.value)
+            break
+        except navidoc.parser.ParserException, e:
+            dbg("Fatal, ParserException: "+e.value)
+            break
+        except navidoc.mp.MetapostException, e:
+            dbg("Fatal, MetapostException: "+e.value)
+            break
+        except navidoc.mp.uml.UMLException, e:
+            dbg("Fatal, UMLException: "+e.value)
+            break
+
+    if not loop: break
+    print "\n\n"+'Navidoc has finished. Press Enter to recompile.'+"\n"+ \
+          'Enter any other key to exit the loop and quit Navidoc.'
+    if  raw_input().lower() != '':
+        break
+    print 'Rerunning Navidoc...'
Index: navidoc/test/__init__.py
diff -u /dev/null navidoc/test/__init__.py:1.1.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/test/__init__.py    Mon Jun 30 11:30:15 2003
@@ -0,0 +1,17 @@
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+# 
Index: navidoc/test/parser.test
diff -u /dev/null navidoc/test/parser.test:1.1.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/test/parser.test    Mon Jun 30 11:30:15 2003
@@ -0,0 +1,58 @@
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+#  
+
+# $Id: parser.test,v 1.1.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+def test_tabs_to_spaces():
+    from navidoc.util.parser import tabs_to_spaces
+    assert tabs_to_spaces("\t") == '        ', tabs_to_spaces("\t")
+    assert tabs_to_spaces("\t\t") == '                ', tabs_to_spaces("\t\t")
+
+def test_parse_indented():
+    from navidoc.util.parser import parse_indented
+    assert parse_indented('a') == [[['a']]], parse_indented('a')
+    assert parse_indented('a\nb') == [[['a']], [['b']]], parse_indented('a\nb')
+    assert parse_indented('a\nb\n c') == [[['a']], [['b'], [['c']]]], 
parse_indented('a\nb\n c')
+    assert parse_indented('a\nb\n c d') == [[['a']], [['b'], [['c', 'd']]]], 
parse_indented('a\nb\n c d')
+    assert parse_indented('a\nb\n c d\ne') == [[['a']], [['b'], [['c', 'd']]], 
[['e']]], parse_indented('a\nb\n c d\ne')
+    assert parse_indented('a\nb\n c d\ne', tokenize=0) == [['a'], ['b', ['c 
d']], ['e']], parse_indented('a\nb\n c d\ne', tokenize=0)
+
+def test_random_var():
+    """Test that variables seem to be random."""
+    from navidoc.util.parser import random_var
+    vars = []
+    for n in range(100):
+       tmp = random_var()
+       vars.extend([tmp])
+       assert vars.count(tmp) == 1, vars.count(tmp)
+
+def test_init_spaces():
+    from navidoc.util.parser import init_spaces
+    assert init_spaces(' foo')[0] == 1, init_spaces(' foo')
+    assert init_spaces(' foo')[1] == 'foo', init_spaces(' foo')
+    assert init_spaces(' foo', tokenize=1)[1] == ['foo'], init_spaces(' foo', 
tokenize=1)
+    assert init_spaces(' fo o', tokenize=1)[1] == ['fo', 'o'], init_spaces(' 
foo', tokenize=1)
+
+def test_match_remove():
+    from navidoc.util.parser import match_remove
+    assert match_remove('a', 'aaa')[1] == '', match_remove('a', 'aaa')
+    assert match_remove('[b]', 'babab')[1] == 'aa', match_remove('[b]', 
'babab')
\ No newline at end of file
Index: navidoc/test/path.test
diff -u /dev/null navidoc/test/path.test:1.2.2.1
--- /dev/null   Mon Jun 30 11:30:16 2003
+++ navidoc/test/path.test      Mon Jun 30 11:30:15 2003
@@ -0,0 +1,39 @@
+# This file is part of Navidoc.
+# 
+# Navidoc is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Navidoc is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
+# Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General
+# Public License along with Navidoc; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA  02111-1307  USA
+#  
+
+# $Id: path.test,v 1.2.2.1 2003/06/30 15:30:15 humppake Exp $
+
+#
+# Written by Asko Soukka
+#
+
+def test_slashify():
+    """Test slashifying a path."""
+    from navidoc.util.path import slashify
+    assert slashify('') == '', slashify('')
+    assert slashify('foo') == 'foo/', slashify('foo')
+    assert slashify('foo/') == 'foo/', slashify('foo/') 
+
+def test_relative_path():
+    """Test building of relative path."""
+    from navidoc.util.path import relative_path
+    assert relative_path('navidoc', 'test') == '../test/', 
relative_path('navidoc', 'test')
+    assert relative_path('', 'test') == 'test', relative_path('', 'test')
+    assert relative_path('navidoc', 'Makefile') == '../Makefile', 
relative_path('navidoc', 'Makefile')
+    assert relative_path('navidoc/__init__.py', 'Makefile') == '../Makefile', 
relative_path('navidoc/__init__.py', 'Makefile')
+    assert relative_path('navidoc/util', 'test/path.test') == 
'../../test/path.test', relative_path('navidoc/util', 'test/path.test')




reply via email to

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