#
# FILE            $Id: HTMLgenFormatter.py,v 1.7 1998/02/04 17:56:23 dlarsson Exp $
#
# DESCRIPTION     Manual Formatter using Robin Friedrich's HTMLgen module.
#
# AUTHOR          SEISY/LKSB Daniel Larsson
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of ABB Industrial Systems
# not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior permission.
#
# ABB INDUSTRIAL SYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO
# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS, IN NO EVENT SHALL ABB INDUSTRIAL SYSTEMS BE LIABLE
# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# Copyright (C) ABB Industrial Systems AB, 1996
# Unpublished work.  All Rights Reserved.
#
# HISTORY:
# $Log: HTMLgenFormatter.py,v $
# Revision 1.7  1998/02/04 17:56:23  dlarsson
# Python 1.5 changes (ni is obsolete).
# HTMLgen changes from R. Friedrich.
#
# Revision 1.6  1996/09/06  19:22:59  omfadmin
# Removed debug printouts.
#
# Revision 1.5  1996/09/06  09:51:03  omfadmin
# Updated for the 0.6 release.
#
# Revision 1.4  1996/08/26  20:27:21  omfadmin
# I removed '_' from the rendered link instead of only the link text,
# which ment URL's got stripped too!
#
# Various fixes to support nested lists.
#
# Revision 1.3  1996/07/10  02:58:05  omfadmin
# Added special author support.
#
# Revision 1.2  1996/07/08  05:14:12  omfadmin
# Moved searching of HTML.rc files into standard HTML.rc.
# Added render_navigation() to include navigation buttons.
# Implemented convert_text (simply calls HTMLgen.escape).
#
# Revision 1.1  1996/06/24  10:07:57  omfadmin
# Initial revision
#
#

__author__ = "Daniel Larsson, dlarsson@sw.seisy.abb.se"
__version__ = "$Revision: 1.7 $"

import HTMLgen, regex, string

ldd = '[' + string.letters + string.digits + '.' + ']+'

email_regex = regex.compile(ldd + '@' + ldd)


class Para:
    """A HTML paragraph.

    Since the formatter converts setext tags, like bold text,
    italics, etc, before creating the paragraph, HTMLgen's
    Paragraph class will escape the markup characters."""

    def __init__(self, text):
	self.text = text

    def __repr__(self):
	return '\n<P>' + self.text + '</P>\n'

def html_rc():
    """Returns path to the HTML.rc file.

    Searches for a HTML.rc file in the following directories:

    - current directory
    - user's home directory
    - the formatter subdirectory
    """

    from os import path
    import gendoc.formatters
    file = path.join(gendoc.formatters.__path__[0], 'HTML.rc')
    return file


def strip_type(data):
    """Strip list type from nested lists"""
    if type(data) == type(''):
	return data
    else:
	return map(strip_type, data[1])

class HTMLg:
    """Manual formatter generating HTML.

    This formatter uses Robin Friedrich's HTMLgen module for
    more customized HTML output. Read HTMLgen.py for intructions
    how to customize."""

    file_ext = '.html'

    def _add_(self, txt):
	# Add text to the document
	self._text_ = self._text_ + txt

    # -----   THESE ARE THE REQUIRED METHODS  -----
    def __init__(self):
	pass

    def render_title(self, manpage, title, marker):
	"""Render document title.

	~manpage~ is a reference back to the manual page object.
	~title~ is the title of the document.
	~marker~ is a list of markers for the title. Markers
	are used to implement indices. See the MIFFormatter
	for how its used.
	"""
	# String to collect document text
	self.doc = HTMLgen.Document(html_rc())
	self.doc.title = title

	if manpage.author:
	    # Check for email address
	    ix = email_regex.search(manpage.author)
	    if ix >= 0:
		email = email_regex.group(0)
		author = manpage.author[:ix] + manpage.author[ix + len(email):]
		author = string.strip(author)
		while author[-1] in ',.:;-': author = author[:-1]
	    else:
		email = 'dev@null'
		author = manpage.author

	    self.doc.author = author
	    self.doc.email = email

    def render_navigation(self, top, prev, next):
	"""Render navigation buttons.

	~prev~ and ~next~ are ManualPage instances, ~top~ is
	either a string or a ManualPage instance"""

	if top:
	    if type(top) == type(''):
		self.doc.gotop = top
	    else:
		self.doc.gotop = top.name() + self.file_ext
	if prev:
	    self.doc.goprev = prev.name() + self.file_ext
	if next:
	    self.doc.gonext = next.name() + self.file_ext

    def render_section(self, manpage, lvl, section, marker):
	"""Render a section heading.
	
	~lvl~ is an integer indicating the nesting depth of
	the section. The title is at level 0, top level sections
	at level 1, and so on.
	"""
	if marker:
	    section = HTMLgen.Name(url=section, text=section)
	self.doc.append(HTMLgen.Heading(lvl+1, section))


    def render_paragraph(self, manpage, para):
	"""Render a paragraph

	~para~ is the paragraph text.
	"""
	# We cannot use the Paragraph class, since it
	# escapes characters we already substituted
	# in render_bold, etc, below.
	self.doc.append(Para(para))

    def render_code(self, manpage, code):
	"""Render code snippet.
	
	~code~ is the code snippet.
	"""
	self.doc.append(HTMLgen.Pre(code))

    def render_list(self, manpage, listt):
	"""Render an unordered list (bullet list)

	~list~ is a possibly nested list of items.
	"""
	from gendoc.ManualPage import UN_LIST, OR_LIST
	listtype, list = listt
	if listtype == UN_LIST:
	    ListClass = HTMLgen.UL
	else:
	    ListClass = HTMLgen.OL
	self.doc.append(ListClass(strip_type(listt)))

    def render_deflist(self, manpage, list):
	self.doc.append(HTMLgen.DL(list))

    def render_strong(self, text):
	return str(HTMLgen.Strong(text))

    def render_emphasis(self, text):
	return str(HTMLgen.Emphasis(text))

    def render_underline(self, text):
	return str(HTMLgen.Emphasis(text))

    def render_quoted(self, text):
	return str(HTMLgen.Code(text))

    def render_internal_link(self, link, link_text):
	return str(HTMLgen.Href('#'+link, link_text))

    def render_external_link(self, link, link_text):
	import urllib
	t, rest = urllib.splittype(link)
	host, path = urllib.splithost(rest)
	import posixpath
	base = posixpath.basename(path)
	root, ext = posixpath.splitext(base)
	if ext == '' and base:
	    link = link+self.file_ext
	return str(HTMLgen.Href(link, link_text))

    def convert_text(self, text):
	"""Escape HTML special characters."""

	return HTMLgen.escape(text)

    def end(self):
	"""Return the rendered document.

	_IMPORTANT_: The same formatter object is very likely
	to be used for more than one ManualPage, so we must
	remove the text also (alternatively, we might initialise
	self._text_ in 'render_title', since it is always called
	first).
	"""
	return str(self.doc)

