# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - "text/pdf" Formatter

    Copyright (c) 2005 by OR Soft GmbH, based on other formatters (c) by Jürgen Hermann <jh@web.de>
    All rights reserved, see COPYING for details.

    ORS modifications:
        14.09.05 RS derived from text_html and text_word
        27.09.05 RS upgrade to 1.3.5, old code removed
"""

# Imports
import cgi, string, sys, time, os, copy, traceback
from MoinMoin.formatter.base import FormatterBase
from MoinMoin import wikiutil, config, user, webapi, i18n

from MoinMoin.Page import Page
#ABP REPORTLAB
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, Image
from reportlab.lib.units import inch, cm
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.colors import Color
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.lib.sequencer import Sequencer
from reportlab.lib.utils import ImageReader
from reportlab.pdfgen.canvas import Canvas


#from reportlab.rl_config import defaultPageSize
#ABP end

DOC_SUFFIX = ".pdf"  # perhaps put this in config.py as pdf_suffix?

#############################################################################
### PDF Formatter
#############################################################################

_debug=1


class Formatter(FormatterBase):
    """
        Send HTML data.
    """

    hardspace = '&#160;'
    hardspace = ' '



    def __init__(self, request, **kw):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
        apply(FormatterBase.__init__, (self, request), kw)
#RS additional property "mimetype"
        self.mimetype="text/pdf"
        sys.stderr.write("\nThis is the PDF Formatter....\n")
#RS end
        self.dead=0
        self.store_text=0 # store text in self._text instead of emitting it
        self.recordedtext=""
        self.recordedcursor=0
        # inline tags stack. When an inline tag is called, it goes into
        # the stack. When a block element starts, all inline tags in
        # the stack are closed.
        self._inlineStack = []

        self._in_li = 0
        self._first_li = 0
        self._first_tr = 0
        self._first_td = 0
        self._table_start=0
        self._ignore_next_paragraph=0
        self.list_levels={'ul':0,'ol':0,'dl':0,'table':0,'all':0}
        self.last_indent_type=''
        self._in_code = 0
        self._base_depth = 0
        self._in_code_area = 0
        self._in_code_line = 0
        self._code_area_num = 0
        self._code_area_js = 0
        self._code_area_state = ['', 0, -1, -1, 0]
        self._show_section_numbers = None
        self._content_ids = []
        self.pagelink_preclosed = False
        self._is_included = kw.get('is_included',False)
        self.request = request
        self.cfg = request.cfg
#        self.targetdir=kw.get('targetdir',config.data_dir)
        self.targetdir=kw.get('targetdir',request.cfg.data_dir)

# pdf style-definitions
        self.styles= getSampleStyleSheet()
        self.styleTitle= copy.deepcopy(self.styles['Title'])
        self.styleH1= copy.deepcopy(self.styles['Heading1'])
        self.styleH1.fontSize= 18
        self.styleH1.spaceBefore= 12 #is ignored at the top of a frame
        self.styleH1.spaceAfter= 7 #is ignored at the bottom of a frame
        self.styleH1.leading= 22 #is the spacing between adjacent lines of text
        self.styleH2= copy.deepcopy(self.styles['Heading2'])
        self.styleH2.fontSize= 16
        self.styleH2.spaceBefore= 12
        self.styleH2.spaceAfter= 7
        self.styleH2.leading= 20
        self.styleH3= copy.deepcopy(self.styles['Heading3'])
        self.styleH3.fontSize= 14
        self.styleH3.spaceBefore= 12
        self.styleH3.spaceAfter= 7
        self.styleH3.leading= 18
        self.styleH4= copy.deepcopy(self.styles['Heading3'])
        self.styleH4.fontName= "Times-BoldItalic"
        self.styleH4.fontSize= 12
        self.styleH4.spaceBefore= 12
        self.styleH4.spaceAfter= 7
        self.styleH4.leading= 16
        self.styleH5= copy.deepcopy(self.styles['Heading3'])
        self.styleH5.fontName= "Times-Italic"
        self.styleH5.fontSize= 12
        self.styleH5.spaceBefore= 12
        self.styleH5.spaceAfter= 7
        self.styleH5.leading= 14
        self.standardstyle= copy.deepcopy(self.styles['Normal'])
        self.standardstyle.spaceBefore= 6 
        self.standardstyle.spaceAfter= 6 
        self.standardstyle.leading= 13
        self.styleCode= copy.deepcopy(self.styles['Code'])
        self.styleBullet= copy.deepcopy(self.styles['Bullet'])
        self.styleBullet.spaceBefore= 6
        self.styleBullet.spaceAfter= 6
        self.styleBullet.leading= 13
        self.styleBullet.bulletFontName= "Symbol"
        self.styleBullet.leftIndent= 14
        self.styleBullet.bulletIndent= 4
        self.styleBullet.firstLineIndent= 0
        self.styleItalic= copy.deepcopy(self.styles['Italic'])
        self.styleDefinition= copy.deepcopy(self.styles['Definition'])
        self.currentstyle= copy.deepcopy(self.standardstyle)

        self.story= []
        self.para_story= ""
        self.title= ''
        self.bulletText= None
        self.seq= Sequencer()
        self.OLnumber= ""
        self.oltype= None
        self.olstart= None
        self.nobullet= 0
        self.li_marker= []
        self.p_marker= None
        self.styleStack= Privatestack()
        self.bulletStack= Privatestack()
        self.indenttypeStack= Privatestack()
        self.oltypeStack= Privatestack()
        self.p_markerStack= Privatestack()

        if not hasattr(request, '_fmt_hd_counters'):
            request._fmt_hd_counters = []
        self.document=None
        self.pdf_host= None
        self.doc= None
        self.doccount=0
        self.tt_start=0
        self.PAGE_HEIGHT= A4[1]
        self.PAGE_WIDTH= A4[0]

# not by SimpleDocTemplate        self.f = Frame(inch, inch, 6*inch, 9*inch, showBoundary=1)

    def _reset_indents(self):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
        self._in_li = 0
        self._first_li = 0
        self._first_tr = 0
        self._first_td = 0
        self._table_start=0
        self._ignore_next_paragraph=0
        self.list_levels={'ul':0,'ol':0,'dl':0,'table':0,'all':0}
        self.last_indent_type=''
    def FatalEnd(self):
        """
        make sure we do not leave any ActiveX corpses behind if errors occur
        """
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
        try:
            if self.document is not None:
#                pass
#TODO
##                self.pdf_host.drawText(self.document)
##                self.pdf_host.showPage()
##                self.pdf_host.save()
#                self.document.Close(-1)
#            if self.pdf_host is not None:
#                self.pdf_host.Quit()
                self.pdf_host.save()

            self.document=None
            self.pdf_host=None
        except:
            pass
#            raise
        self.dead=1
        
    def _save(self):
#RS fatal error handling
        if self.dead==1:
            return
#RS end
        if self.document!=None:
            pass
        #not doctemplate based
##        self.pdf_host.save()

    # Primitive formatter functions #####################################

    # all other methods should use these to format tags. This keeps the
    # code clean and handle pathological cases like unclosed p and
    # inline tags.

    def langAttr(self, lang=None):
        """ Return lang and dir attribute

        Must be used on all block elements - div, p, table, etc.
        @param lang: if defined, will return attributes for lang. if not
            defined, will return attributes only if the current lang is
            different from the content lang.
        @rtype: dict
        @retrun: language attributes
        """
        if not lang:
            lang = self.request.current_lang
            # Actions that generate content in user language should change
            # the content lang from the default defined in cfg.
            if lang == self.request.content_lang:
                # lang is inherited from content div
                return {}

        attr = {'lang': lang, 'dir': i18n.getDirection(lang),}
        return attr

    def formatAttributes(self, attr=None):
        """ Return formatted attributes string

        @param attr: dict containing keys and values
        @rtype: string ?
        @return: formated attributes or empty string
        """
        if attr:
            attr = [' %s="%s"' % (k, v) for k, v in attr.items()]           
            return ''.join(attr)
        return ''

    # TODO: use set when we require Python 2.3
    # TODO: The list is not complete, add missing from dtd
#RS Word: use _blocks for all tags that can only be interpreted on close, i.e. text between open and close must be recorded    
##    _blocks = 'p div pre table tr td ol ul dl li dt dd h1 h2 h3 h4 h5 h6 hr form'
    _blocks = 'div pre table tr td ol ul dl li dt dd h1 h2 h3 h4 h5 h6 hr form pagelink'
    _blocks = 'div pre dt dd h1 h2 h3 h4 h5 h6 form url pagelink'
    _blocks= 'h1 h2 h3 h4 h5'
#RS end
    _blocks = dict(zip(_blocks.split(), [1] * len(_blocks)))


    def open(self, tag, newline=False, attr=None):
        """ Open a tag with optional attributes

        @param tag: html tag, string
        @param newline: render tag on a separate line
        @parm attr: dict with tag attributes
        @rtype: string ?
        @return: open tag with attributes
        """
#        if _debug:
#            traceback.print_stack(limit=1,file=sys.stdout)
        if tag in self._blocks:
            # Block elements
#RS word            
            if _debug:
                print "OPEN %s (recording)" % tag
            self.store_text=1
            self.recordedtext=""
#TODO
#            if self.word_host:
#                self.recordedcursor=int(self.word_host.Selection.Range.End)

#RS end
            result = []

            # Add language attributes, but let caller overide the default
            attributes = self.langAttr()
            if attr:
                attributes.update(attr)

            # Format
            attributes = self.formatAttributes(attributes)
            result.append('<%s%s>' % (tag, attributes))
            if newline:
                if _debug:
                    print "OPEN with NEWLINE"
#TODO
#                if self.document:
#                    self.word_host.Selection.TypeParagraph()
                
                result.append('\n')
            return ''.join(result)
        else:
            # Inline elements
            # Add to inlineStack
            if _debug:
                print "OPEN %s (inline)" % tag
            self._inlineStack.append(tag)

            self.para_story += '<%s>' % tag
            # Format
            return '<%s%s>' % (tag, self.formatAttributes(attr))
       
    def close(self, tag, newline=False):
        """ Close tag

        @param tag: html tag, string
        @rtype: string ?
        @return: closing tag
        """
#        if _debug:
#            traceback.print_stack(limit=1,file=sys.stdout)
        if tag in self._blocks:
            # Block elements
            # Close all tags in inline stack
            # Work on a copy, because close(inline) manipulate the stack
#RS word            
            if _debug:
                try:
                    print 'CLOSE %s (recorded="%s")' % (tag,self.recordedtext)
                except:
                    print 'CLOSE %s (recorded=???)' % (tag)
            self.store_text=0
            self.recordedtext=""
#            self.recordedcursor=0
#RS end            
            result = []
            stack = self._inlineStack[:]
            stack.reverse()
            for inline in stack:
                result.append(self.close(inline))
            # Format with newline
            if newline:
                if _debug:
                    print "CLOSE with NEWLINE"
                result.append('\n')
            result.append('</%s>\n' % (tag))
            return ''.join(result)            
        else:
            # Inline elements 
            # Pull from stack, ignore order, that is not our problem.
            # The code that calls us should keep correct calling order.
            if _debug:
                print "CLOSE %s (inline)" % tag
            if tag in self._inlineStack:
                if _debug:
                    print "CLOSE %s (inline stack remove)" % tag
                self._inlineStack.remove(tag)
###bulletlistentag nicht in die para_story
##            if tag == 'ul':
##                pass
##            else:
##                self.para_story += "</%s>"  % tag
            self.para_story += "</%s>"  % tag
            return '</%s>' % tag


    def startDocument(self, pagename):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
            sys.stderr.write("\nThis is the PDF Formatter::startDocument....")
        self.doccount+=1
        self.title= self.request.getPragma('title', pagename)

        if self.pdf_host==None:

            try:
                file = wikiutil.quoteWikinameFS(pagename) + DOC_SUFFIX
                filepath = os.path.abspath(os.path.join(self.targetdir, file))
                #not doctemplate based
##                self.pdf_host = Canvas(filepath)
##                self.pdf_host.setTitle(title)
### TODO                self.pdf_host.setAuthor(TODO author)
###not implemented yet                self.pdf_host.setSubject(notimplementedyet subject)
                #SimpleDocTemplate based
                # pagesize per wikiaction? / showBoundary= 1 only for tests / allowSplitting= 1 allows the split of flowables 
                self.doc= SimpleDocTemplate(filepath, pagesize= A4, showBoundary= 1, allowSplitting= 1, title= self.title, author= '')
#debug                self.request.write( "#SimpleDocTemplate initialised! Title: %s Filename: %s" % (self.title, filepath))

            except:
                self.request.write( "#STARTDOC %s %s failed at Host Initialisation" % (self.doccount,pagename))
                self.pdf_host=None
                raise

        else:
            self.request.write("\nPDF HOST already active!\n")
        if self.document!=None:
            self.request.write("ignore#STARTDOC %s %s" % (self.doccount,pagename))
            return "ignore#STARTDOC %s %s" % (self.doccount,pagename)
        try:

            self.story = []
            self.story.append(Spacer(1, 7* cm))
#            self.story.append(Paragraph(pagename, self.styleTitle)) 

        except:
            self.FatalEnd()
            self.request.write("#STARTDOC %s %s failed at" % (self.doccount,pagename))            
            #self.request.write("#STARTDOC %s %s failed at Documents.Add(%s..." % (self.doccount,pagename,self.doctemplate))
            raise
        
        try:
            self._reset_indents()


#            self.document.SaveAs(filepath,0)
#            self.request.write("#STARTDOC %s %s" % (self.doccount,pagename)) # identisch der returnanweisung
            return "#STARTDOC %s %s" % (self.doccount,pagename)

        except:
            self.FatalEnd()
            self.request.write("#STARTDOC %s %s failed" % (self.doccount,pagename))
            raise

    def endDocument(self):

        def myFirstPage(canvas, doc):
            self.request.write( "#myFirstPage reached! ")
            canvas.saveState()
            rect=(8.8* cm, (self.PAGE_HEIGHT/5*4)-32, 12.2* cm, (self.PAGE_HEIGHT/5*4)-16)
            rgb=Color(0,0,1)
            url='www.orsoft.de'
            canvas.linkURL(url, rect, 1, 1, rgb)
            canvas.setFont('Times-Bold', 16)
            canvas.drawCentredString(self.PAGE_WIDTH/2, self.PAGE_HEIGHT/5*4, self.title)
            canvas.setFont('Times-Roman', 9)
            canvas.drawCentredString(self.PAGE_WIDTH/2, (self.PAGE_HEIGHT/5*4)-27, "OR Soft Jänicke GmbH")
            canvas.drawCentredString(self.PAGE_WIDTH/2, self.PAGE_HEIGHT-(0.75* inch), '') #eg a pageinfo
            canvas.drawCentredString(self.PAGE_WIDTH/2, 0.75* inch, "Page 1")
            canvas.restoreState()
            self.request.write( "#end of myFirstPage reached! " )

        def myLaterPages(canvas, doc):
            self.request.write( "#myLaterPages reached! ")
            canvas.saveState()
            canvas.setFont('Times-Roman',9)
            canvas.drawCentredString(self.PAGE_WIDTH/2, self.PAGE_HEIGHT-(0.75* inch), '') #eg a pageinfo
            canvas.drawCentredString(self.PAGE_WIDTH/2, 0.75* inch, "Page %d" % (doc.page))
            canvas.restoreState()
            self.request.write( "#end of myLaterPages reached! ")

#RS fatal error handling
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
        if self.dead==1:
            return u""
#RS end
        self.doccount-=1
        if self.doccount==0:
            try:

###                self.pdf_host.drawText(self.document)
###                self.pdf_host.showPage()
#                self.f.addFromList(self.story,self.pdf_host)
#                self.pdf_host.save()
                #SimpleDocTemplate based
                self.request.write( "#endDocument reached! len(self.story): %s " %  len(self.story))
                self.doc.build(self.story, onFirstPage= myFirstPage, onLaterPages= myLaterPages)
#                self.document=None
#                self.pdf_host=None
                return u"#ENDDOC"
            except:
                return u"#ENDDOC failed"
                raise
                
        return u"#ENDDOC %s" % self.doccount

    def startContent(self, content_id='content', **kwargs):
        """ Start page content div """
        return ""
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
        # Setup id
        if content_id!='content':
            aid = 'top_%s' % (content_id,)
        else:
            aid = 'top'
        self._content_ids.append(content_id)
        result = []
        # Use the content language
        attr = self.langAttr(self.request.content_lang)
        attr['id'] = content_id
        result.append(self.open('div', newline=1, attr=attr))
        result.append(self.anchordef(aid))
        return ''.join(result)
        
    def endContent(self):
        """ Close page content div """
        return ""
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)

        # Setup id
        try:
            cid = self._content_ids.pop()
        except:
            cid = 'content'
        if cid!='content':
            aid = 'bottom_%s' % (cid,)
        else:
            aid = 'bottom'

        result = []
        result.append(self.anchordef(aid))
        result.append(self.close('div', newline=1))
        return ''.join(result)

    def lang(self, on, lang_name):
        """ Insert text with specific lang and direction.
        
            Enclose within span tag if lang_name is different from
            the current lang    
        """
        tag = 'span'
        if lang_name != self.request.current_lang:
            # Enclose text in span using lang attributes
            if on:
                attr = self.langAttr(lang=lang_name)
                ret=self.open(tag, attr=attr)
                return ret
            else:
                if self.document!=None:
                    pass
#TODO : text with language info?
###                self.document.XXXX
                ret=self.close(tag)
                return ret

        # Direction did not change, no need for span
        return ''            
    

    def _langAttr(self):
        result = ''
        lang = self.request.current_lang
        if lang != config.default_lang:
            result += ' lang="%s" dir="%s"' % (
                lang, i18n.getDirection(self.request, lang))

        return result

    def sysmsg(self, text, **kw):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'div'
        if on:
            ret=self.open(tag, attr={'class': 'message'})
            return ret
        else:
            text=self.recordedtext
            if self.document!=None and text!=None:
                pass 
#TODO
#                self.document.Content.TypeText('#SYSMSG#'+text+'#')
            ret=self.close(tag)
            return ret


    def pagelink(self, on, pagename='', page=None, **kw):
        """ Link to a page.

            formatter.text_python will use an optimized call with a page!=None
            parameter. DO NOT USE THIS YOURSELF OR IT WILL BREAK.

            See wikiutil.link_tag() for possible keyword parameters.
        """
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        apply(FormatterBase.pagelink, (self, on, pagename, page), kw)
        if page is None:
            page = Page(self.request, pagename, formatter=self);
        tag = 'pagelink'
        url = wikiutil.quoteWikinameFS(pagename) + DOC_SUFFIX
        if on:
            ret=self.open(tag, attr={'class': 'pagelink'})
            return ret
        else:
            text=self.recordedtext
            if text==None:
                text=pagename
            if self.document!=None:
                pass
#TODO
#                self.word_host.ActiveDocument.Hyperlinks.Add(\
#                    Anchor=self.word_host.Selection.Range, Address=url,\
#                    SubAddress="", ScreenTip="", TextToDisplay=text)
            ret=self.close(tag)
            return ret
            
            

    def interwikilink(self, on, interwiki='', pagename='', **kw):
        if not on: return '</a>'
        
        wikitag, wikiurl, wikitail, wikitag_bad = wikiutil.resolve_wiki(self.request, '%s:%s' % (interwiki, pagename))
        wikiurl = wikiutil.mapURL(self.request, wikiurl)

        if wikitag == 'Self': # for own wiki, do simple links
            import urllib
            if wikitail.find('#')>-1:
                wikitail, kw['anchor'] = wikitail.split('#', 1)
            wikitail = urllib.unquote(wikitail)
            return apply(self.pagelink, (on, wikiutil.AbsPageName(self.request, self.page.page_name, wikitail)), kw)
        else: # return InterWiki hyperlink
            href = wikiutil.join_wiki(wikiurl, wikitail)
            if wikitag_bad:
                html_class = 'badinterwiki'
            else:
                html_class = 'interwiki'

            icon = ''
            if self.request.user.show_fancy_links:
                icon = self.request.theme.make_icon('interwiki', {'wikitag': wikitag}) 
            return (self.url(1, href, title=wikitag, unescaped=0,
                pretty_url=kw.get('pretty_url', 0), css = html_class) +
                icon)
            # unescaped=1 was changed to 0 to make interwiki links with pages with umlauts (or other non-ascii) work


#SYNC URL

    def url(self, on, url=None, css=None, **kw):
        """ render URL

        @keyword type: "www" or "mailto" to use that icon
        @keyword title: <a> title attribute
        @keyword attrs: just include those <a> attrs "as is"
        """
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        if url is not None:
            url = wikiutil.mapURL(self.request, url)
        title = kw.get('title', None)
        attrs = kw.get('attrs', None)
#RS 1.1
        target = kw.get('target', None)
#RS stop
        str = ''
        if css: 
            str = '%s class="%s"' % (str, css)
        if title:
            str = '%s title="%s"' % (str, title)
        else:
            title=""
        if attrs:
            str = '%s %s' % (str, attrs)

        # create link
#TODO? insert link icons and other pretty stuff?         
        tag = 'url'
        if on:
            #store this for the close action
            self.url_url=url
            self.url_title=title
            
            ret=self.open(tag, attr=attrs)
            return ret
        else:
            text=self.recordedtext
            url=self.url_url
            title=self.url_title
            if text is None:
                text = url
            if self.document!=None:
                pass
#TODO
#                self.word_host.ActiveDocument.Hyperlinks.Add(\
#                    Anchor=self.word_host.Selection.Range, Address=wikiutil.escape(url, 1),\
#                    SubAddress="", ScreenTip=title, TextToDisplay=text)
            

            ret=self.close(tag)
            return ret


    def anchordef(self, id):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        if self.document!=None:
            self.document.Bookmarks.Add(Range=self.word_host.Selection.Range,Name=id)
        return '<a id="%s"></a>\n' % (id, )

    def anchorlink(self, on, name='', id = None):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
##        if self.document!=None:
##            self.word_host.Selection.TypeText('_'+text+'_')
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        extra = ''
        if id:
            extra = ' id="%s"' % id
        tag = 'a'
        if on:
            ret=self.open(tag, attr={'id':'%s' % id})
            return ret
        else:
            text=self.recordedtext
            if text==None:
                text=name
            if self.document!=None:
                pass
#TODO
#                self.word_host.ActiveDocument.Hyperlinks.Add(\
#                    Anchor=self.word_host.Selection.Range, Address="",\
#                    SubAddress=name, ScreenTip="", TextToDisplay=text)
            ret=self.close(tag)
            return ret


    def pure(self, text):
        """
        this handles the "not in any markup" case
        used in formatters with "side effects"
        """
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
            print "PURE, recording=%s" % self.store_text
#RS fatal error handling
        if self.dead==1:
            raise
            return u""
#RS end
        if (self._table_start == 1):
            raise
            return u''
#        if self.document!=None:
#            pass
#TODO
#            self.word_host.Selection.TypeText(text)
        return self._text(text)
    
    def _text(self, text):
#        return '{'+text+'}'
#RS fatal error handling
        if _debug:
            traceback.print_stack(limit=2,file=sys.stdout)
        if self.dead==1:
            raise
            return u""
#RS end
        tx=self.escapedText(text)
        if self._in_code:
            tx=string.replace(self.escapedText(text), u' ', self.hardspace)
 #       if self.document!=None:
 #           self.document.Content.InsertAfter('„#“'+text+'#')
        if self.store_text==1:
            if _debug:
                print "_TEXT (recording)"
            self.recordedtext+=tx
            return tx
        else:
            self.para_story += tx
            if _debug:
                print "_TEXT (inline), tx=%s, STORY:%s" % (tx,self.para_story)

        return tx

    # Inline ###########################################################
    def strong(self, on):
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'b'
        if on:
            ret=self.open(tag)
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Bold=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')

# is now part of open()
##            self.para_story += "<b>"
            return ret
        else:
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Bold=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
# is now part of close()
##            self.para_story += "</b>"
            ret=self.close(tag)
            return ret


    def emphasis(self, on):
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'em'
        if on:
            ret=self.open(tag)
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Italic=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
# is now part of open()
##            self.para_story += "<i>"
            return ret
        else:
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Italic=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
# is now part of close()
##            self.para_story += "</i>"
            ret=self.close(tag)
            return ret

    def underline(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'span'
# new tagname for in-paragraph formatting matters
        tag = 'u'
        if on:
            ret=self.open(tag,attr={'class': 'u'})
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Underline=\
#                    win32com.client.constants.wdUnderlineSingle
#                self.word_host.Selection.TypeText('')
# is now part of open()
##            self.para_story += "<u>"
            return ret
        else:
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Underline=\
#                    win32com.client.constants.wdUnderlineNone
#                self.word_host.Selection.TypeText('')
# is now part of close()
##            self.para_story += "</u>"
            ret=self.close(tag)
            return ret

    def highlight(self, on):
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'strong'
        if on:
            ret=self.open(tag, attr={'class': 'highlight'})
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Bold=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
            return ret
        else:
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Bold=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
            ret=self.close(tag)
            return ret

    def sup(self, on):
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'sup'
# new tagname for in-paragraph formatting matters        
        tag = 'super'
        if on:
            ret=self.open(tag)
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Superscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
##            self.para_story += "<super>"
            return ret
        else:
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Superscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
##            self.para_story += "</super>"
            ret=self.close(tag)
            return ret

    def sub(self, on):
#RS fatal error handling
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
        if self.dead==1:
            return u""
#RS end
        tag = 'sub'
        if on:
            ret=self.open(tag)
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Subscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
##            self.para_story += "<sub>"
            return ret
        else:
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.Font.Subscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
##            self.para_story += "</sub>"
            ret=self.close(tag)
            return ret
#RS end


    def code(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'tt'
        tag = 'font'
        self._in_code = on
        if on:
            fontattr={'name': 'Courier','size':8}
##            self.para_story += '<font name="Courier" size=8>'
            ret=self.open(tag,attr=fontattr)
            return ret
        else:
            if self.document!=None:
                pass
#TODO
#                lastend=self.recordedcursor
#                currend=int(self.word_host.Selection.Range.End)
#                if lastend<currend and lastend>0:
#                    ttrange=self.document.Range(lastend,currend)
#                    ttrange.Style=self.tt_style
#                else:
#                    self.request.write("TT formatter error, ignored")
#                self.word_host.Selection.TypeText('')
##            self.para_story += "</font>"
            ret=self.close(tag)
            return ret

       
    def small(self, on):
        tag = 'small'
        if on:
            ret=self.open(tag)
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Subscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
            return ret
        else:
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Subscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
            ret=self.close(tag)
            return ret
                                                                                
    def big(self, on):
        tag = 'big'
        if on:
            ret=self.open(tag)
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Subscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
            return ret
        else:
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Font.Subscript=\
#                    win32com.client.constants.wdToggle
#                self.word_host.Selection.TypeText('')
            ret=self.close(tag)
            return ret


    # Block elements ####################################################

    def preformatted(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        self.in_pre = on != 0
        tag = 'pre'
        if on:
            ret=self.open(tag,newline=1)
            return ret
        else:
            if self.document!=None:
                pass
#TODO
#                lastend=self.recordedcursor
#                currend=int(self.word_host.Selection.Range.End)
#                if lastend<currend and lastend>0:
#                    ttrange=self.document.Range(lastend,currend)
#                    ttrange.Style=self.pre_style
#                else:
#                    self.request.write("PRE formatter error, ignored")
#                self.word_host.Selection.TypeParagraph()
#                self.word_host.Selection.Style=self.defpara_style
            ret=self.close(tag)
            return ret

# special markup for syntax highlighting #############################

    def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
#RS word: for now, just use preformatted?
        if on:
            # Open a code area
            self._in_code_area = 1
            self._in_code_line = 0
        else:
            # Close code area
            self._in_code_area = 0
            self._code_area_num += 1
        return self.preformatted(on)
#RS end    
        res = []
        ci = self.request.makeUniqueID('CA-%s_%03d' % (code_id, self._code_area_num))
        if on:
            # Open a code area
            self._in_code_area = 1
            self._in_code_line = 0
            self._code_area_state = [ci, show, start, step, start]

            # Open the code div - using left to right always!
            attr = {'class': 'codearea', 'lang': 'en', 'dir': 'ltr'}
            res.append(self.open('div', attr=attr))

            # Add the script only in the first code area on the page
            if self._code_area_js == 0 and self._code_area_state[1] >= 0:
                res.append(self._toggleLineNumbersScript)
                self._code_area_js = 1

            # Add line number link, but only for JavaScript enabled browsers.
            if self._code_area_state[1] >= 0:
                toggleLineNumbersLink = r'''
<script type="text/javascript">
document.write('<a href="#" onClick="return togglenumber(\'%s\', %d, %d);" \
                class="codenumbers">Toggle line numbers<\/a>');
</script>
''' % (self._code_area_state[0], self._code_area_state[2], self._code_area_state[3])
                res.append(toggleLineNumbersLink)

            # Open pre - using left to right always!
            attr = {'id': self._code_area_state[0], 'lang': 'en', 'dir': 'ltr'}
            res.append(self.open('pre', newline=True, attr=attr))
        else:
            # Close code area
            res = []
            if self._in_code_line:
                res.append(self.code_line(0))
            res.append(self.close('pre'))
            res.append(self.close('div'))

            # Update state
            self._in_code_area = 0
            self._code_area_num += 1

        return ''.join(res)

    def code_line(self, on):
#RS word: for now, just use preformatted?
        self._in_code_line = on != 0
        return self.preformatted(on)
#RS end    
#RS end    
        res = ''
        if not on or (on and self._in_code_line):
            res += '</span>\n'
        if on:
            res += '<span class="line">'
            if self._code_area_state[1] > 0:
                res += '<span class="LineNumber">%4d </span>' % (self._code_area_state[4], )
                self._code_area_state[4] += self._code_area_state[3]
        self._in_code_line = on != 0
        return res

    def code_token(self, on, tok_type):
#RS word: for now, just use code?
        return self.code(on)
#RS end
        return ['<span class="%s">' % tok_type, '</span>'][not on]


    # Paragraphs, Lines, Rules ###########################################
    
    def linebreak(self, preformatted=1):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        if self._in_code_area:
            preformatted = 1
#TODO
#        self.word_host.Selection.TypeText("\x0B ")
#        self.document.Content.InsertAfter("\x0B ")
        
        return ['\n', '<br>\n'][not preformatted]

    def paragraph(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        if self._terse:
            return ''
        FormatterBase.paragraph(self, on)
##        if self._in_li:
##            self._in_li = self._in_li + 1
        tag = 'p'
        if on:
            ret=self.open(tag)
#versuch indents
            if self.li_marker!= [] and self.li_marker[-1]> 0 and self.last_indent_type=='ul':
                if self.p_marker== None:
                    self.p_marker= 0
                self.p_marker+=1
# versuch ende
##            if self.document!=None:
##                if self._ignore_next_paragraph: #we already inserted a paragraph
##                    self._ignore_next_paragraph=0
##                    return u''
##                else:
###TODO
###                    self.word_host.Selection.TypeParagraph()
##                    return u'<pli>'
            return ret
        else:
##            text=self.recordedtext
##            if self.document!=None:
##                if self._ignore_next_paragraph: #we already inserted a paragraph
##                    self._ignore_next_paragraph=0
##                    return u''
##                else:
###TODO
###                    self.word_host.Selection.TypeParagraph()
##                    return u'<pli>'
            self.para_story += ""
# versuch indents
            if self.li_marker!= [] and self.li_marker[-1] > 0 and self.p_marker > 1 and self.last_indent_type=='ul':
                self.bulletStack.ppush(self.bulletText)
                self.bulletText= ''
#versuch pause
            self.story.append(Paragraph(str(self.para_story), self.currentstyle, self.bulletText))
#versuch weiter
            if self.li_marker!= [] and self.li_marker[-1] > 0 and self.p_marker > 1 and self.last_indent_type=='ul':
                self.bulletText= self.bulletStack.ppop()
#versuch ende
            if _debug:
                sys.stderr.write(self.para_story+"\n")
                print "\nSTORY: %s" % self.para_story
            self.para_story = ""
            ret=self.close(tag)
            return ret
        

    def rule(self, size=None):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
#TODO RS draw a line?
        if size:
            # Add hr class: hr1 - hr6
            return self.open('hr', newline=1, attr={'class': 'hr%d' % size})
        return self.open('hr', newline=1)

    def icon(self, type):
#TODO RS or just ignore (probably just wiki control icons)?        
        return self.request.theme.make_icon(type)

    def img_url(self, img):
        """ Generate an image href

        @param img: the image filename
        @rtype: string
        @return: the image href
        """
        return "%s%s\\img\\%s" % (self.cfg.url_prefix_dir, self.request.theme.name, img)


    def smiley(self, text):
        w, h, b, img = config.smileys[text.strip()]
        href = img
        if not href.startswith('/'):
            href = self.img_url(img)
        return self.image(src=href, alt=text, width=str(w), height=str(h))

    # Lists ##############################################################




    def number_list(self, on, type=None, start=None):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'ol'
        self.request.write("<number_list>:on=%s,type=%s,start=%s" % (str(on),str(type),str(start)))
        if on:
            self.oltypeStack.ppush(self.oltype)
            self.oltype= type
            self.olstart= start
            self.list_levels['ol']=self.list_levels['ol']+1
            self.list_levels['all']=self.list_levels['all']+1
            attr = {}
            if _debug:
                print "   oltype (ol=on):  %s    \n" % self.oltype
                print "   olstart:  %s   \n" % self.olstart
            if type is not None:
                attr['type'] = type
            if start is not None:
                attr['start'] = start
            ret=self.open(tag, newline=1, attr=attr)

            if self.document!=None:
#                self.word_host.Selection.TypeParagraph()
                self.request.write("<OL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
#TODO
#                if self.list_levels['ol']==1: #only first 
#                    if self.word_host.Selection.Range.ListFormat.ListType != self.ol_type:
#                        self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(win32com.client.constants.wdWord9ListBehavior)
#                        if self.last_indent_type=='ul':
#                            #need more indent
#                            self.request.write("UL->OL 1")
#                            self.word_host.Selection.Range.ListFormat.ListIndent()
#                else:
#                    if self.word_host.Selection.Range.ListFormat.ListType != self.ol_type:
#                        self.word_host.Selection.TypeText("{bulleton}")
#                        self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(win32com.client.constants.wdWord9ListBehavior)
#                        if self.last_indent_type=='ul':
#                            #need more indent
#                            self.request.write("UL->OL 2")
#                            self.word_host.Selection.Range.ListFormat.ListIndent()
#                    self.word_host.Selection.Range.ListFormat.ListIndent()
                
            #self._ignore_next_paragraph=1
            self._first_li = 1
            self.indenttypeStack.ppush(self.last_indent_type)
            self.last_indent_type='ol'
            self.bulletStack.ppush(self.bulletText)
            self.styleStack.ppush(self.currentstyle)

            self.styleBullet.bulletFontName= "Times-Roman"
            self.styleBullet.bulletFontSize= 10
            self.currentstyle= copy.deepcopy(self.styleBullet)

            self.styleBullet.leftIndent+= 14
            self.styleBullet.bulletIndent+= 14
            return ret

        else:
            self.seq.reset("OL%s" % self.list_levels['ol'])  #reset current OLnumber
            self.list_levels['ol']=self.list_levels['ol']-1
            self.list_levels['all']=self.list_levels['all']-1

            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.TypeParagraph()
#                self.request.write("</OL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
#                if self.list_levels['ul']==0: 
#                    if self.word_host.Selection.Range.ListFormat.ListType == self.ol_type:
#                        self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(win32com.client.constants.wdWord9ListBehavior)
#                        if self.last_indent_type=='ul':
#                            #need more outdent
#                            self.request.write("UL->OL ??1??")
#                            self.word_host.Selection.Range.ListFormat.ListOutdent()

#                else:
#                    if self.word_host.Selection.Range.ListFormat.ListType == self.ol_type:
#                        self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(win32com.client.constants.wdWord9ListBehavior)
#                    self.word_host.Selection.Range.ListFormat.ListOutdent()
            #self._ignore_next_paragraph=1
            self.last_indent_type='' #obsolete
            ret=self.close(tag)

            self.bulletText= self.bulletStack.ppop()
            self.currentstyle= self.styleStack.ppop()
            self.last_indent_type= self.indenttypeStack.ppop()
            self.oltype= self.oltypeStack.ppop()
            if _debug:
                print "   oltype (ol=off): %s    " % self.oltype
            self.styleBullet.leftIndent-= 14
            self.styleBullet.bulletIndent-= 14
            #styleStack returns None; set currentstyle
            if self.currentstyle==None:
                self.currentstyle= self.standardstyle

            return ret
            

    def bullet_list(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'ul'
        self.request.write("<bullet_list>:on=%s" % (str(on)))
        if on:
            ret=self.open(tag, newline=1)
            self.list_levels['ul']=self.list_levels['ul']+1
            self.list_levels['all']=self.list_levels['all']+1
##            if self.document!=None:
#TODO
##                self.request.write("<UL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
#                if self.list_levels['ul']==1: #only first 
#                    if self.word_host.Selection.Range.ListFormat.ListType != self.ul_type:
#                        self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
#                else:
#                    if self.word_host.Selection.Range.ListFormat.ListType != self.ul_type:
#                        self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
#                    self.word_host.Selection.Range.ListFormat.ListIndent()
            #self._ignore_next_paragraph=1

            self.indenttypeStack.ppush(self.last_indent_type)
            self.last_indent_type='ul'
            self.bulletStack.ppush(self.bulletText)
            self.styleStack.ppush(self.currentstyle)
            if self.list_levels['ul'] == 1:
                self.bulletText= '\267'
                self.styleBullet.bulletFontSize= 11
#            elif elf.list_levels['ul'] == 2:
            else:
                self.bulletText= '\267'
                self.styleBullet.bulletFontSize= 8
            self.styleBullet.bulletFontName= "Symbol"
            self.currentstyle= copy.deepcopy(self.styleBullet)
            self.styleBullet.leftIndent+= 14
            self.styleBullet.bulletIndent+= 14

            return ret
        else:
            self.list_levels['ul']=self.list_levels['ul']-1
            self.list_levels['all']=self.list_levels['all']-1
            if self.document!=None:
                self.request.write("<bullet_list>:on=%s" % (str(on)))
#                pass
#TODO
#                self.word_host.Selection.TypeParagraph()
#                self.request.write("</UL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
#                if self.list_levels['ul']==0: 
#                    if self.word_host.Selection.Range.ListFormat.ListType == self.ul_type:
#                        self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
#                else:
#                    if self.word_host.Selection.Range.ListFormat.ListType == self.ul_type:
#                        self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
#                    self.word_host.Selection.Range.ListFormat.ListOutdent()

            self._ignore_next_paragraph=1
            self.last_indent_type=''
            ret=self.close(tag)

            self.bulletText= self.bulletStack.ppop()
            self.currentstyle= self.styleStack.ppop()
            self.last_indent_type= self.indenttypeStack.ppop()
            self.styleBullet.leftIndent-= 14
            self.styleBullet.bulletIndent-= 14
            #styleStack returns None; set currentstyle
            if self.currentstyle==None:
                self.currentstyle= self.standardstyle
#verusch indents
            if self.list_levels['ul']== 0:
                while self.p_marker>0:
                    self.p_marker= self.p_markerStack.ppop()
                del self.li_marker[0:]
# versuch ende                
            return ret

    def listitem(self, on, **kw):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
##        self._in_li = on != 0
        tag = 'li'
        self._in_li = on != 0
        if on:
#versuch indents
            if self.last_indent_type=='ul':
                self.li_marker.append(1)
                self.p_markerStack.ppush(self.p_marker)
                self.p_marker= None
#versuch ende
            attr = {}
            css_class = kw.get('css_class', None)
            if css_class:
                attr['class'] = css_class
            style = kw.get('style', None)
            if style:
                attr['style'] = style
                if style=="list-style-type:none" : # ? or css_class == 'gap':
                    self.nobullet= 1
                    self.bulletStack.ppush(self.bulletText)
                    self.bulletText= ''
                    #this is indent, not bullet
            ret=self.open(tag, attr=attr)
            #only by numbered lists - OLnumber depends on the ol indent;set the sequence-format
            if self.last_indent_type=='ol':
                self.OLnumber="OL%s" % self.list_levels['ol']
                self.seq.setFormat(self.OLnumber, self.oltype)
                # difference between the default and a nondefault startvalue
                if self.olstart>0:
                    self.seq.reset(self.OLnumber)  #reset current OLnumber (nondefault startvalue)
                    i= 0
                    while i< (self.olstart-1): #increase to startvalue-1
                        self.seq.nextf(self.OLnumber)
                        i+= 1
                    self.olstart= None
                # increase the sequence of the current OLnumber and store it in self.bulletText
                self.bulletText= "%s." % self.seq.nextf(self.OLnumber)
##                if not self.oltype == "1":
##                    self.seq.setFormat(self.OLnumber, self.oltype)
##                    self.bulletText= "%s" % self.seq.nextf(self.OLnumber)
##                else:
##                    self.bulletText= "%d." % self.seq.next(self.OLnumber)
#            return
            return ret
        else:
#versuch indents
            if self.last_indent_type=='ul':
                del self.li_marker[-1]
                self.p_marker= self.p_markerStack.ppop()
#versuch ende
            if self.nobullet == 1:
                self.bulletText= self.bulletStack.ppop()
                self.nobullet= 0
            ret=self.close(tag)
#            return
            return ret
#RS end

    def definition_list(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'dl'
        if on:
            ret=self.open(tag, newline=1)
            self.list_levels['dl']=self.list_levels['dl']+1
            self.list_levels['all']=self.list_levels['all']+1
            return ret
        else:
            self.list_levels['dl']=self.list_levels['dl']-1
            self.list_levels['all']=self.list_levels['all']-1
            ret=self.close(tag)
            return ret

    def definition_term(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'dt'
        if on:
            ret=self.open(tag)
            return ret
        else:
            ret=self.close(tag)
            return ret
        

    def definition_desc(self, on):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'dd'
        if on:
            ret=self.open(tag)
            return ret
        else:
            ret=self.close(tag)
            return ret



    def heading(self, on, depth, id = None, **kw):
        # remember depth of first heading, and adapt current depth accordingly
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag= 'h'

        self._reset_indents()
        if not self._base_depth:
            self._base_depth = depth
#RS adapt base depth if included
            self._base_depth=long(self.request.getPragma('_base_depth',str(self._base_depth)))
        oridepth=depth

#RS isn't this nonsense???
#        depth = max(depth - (self._base_depth - 1), 1)
        count_depth = max(depth - (self._base_depth - 1), 1)

#?        depth = max(depth + (self._base_depth - 1), self._base_depth)
#RS 1.1
        # check numbering, possibly changing the default
        if self._show_section_numbers is None:
            self._show_section_numbers = self.cfg.show_section_numbers
            numbering = self.request.getPragma('section-numbers', '').lower()
            if numbering in ['0', 'off']:
                self._show_section_numbers = 0
            elif numbering in ['1', 'on']:
                self._show_section_numbers = 1
            elif numbering in ['2', '3', '4', '5', '6']:
                # explicit base level for section number display
                self._show_section_numbers = int(numbering)
#RS stop

        heading_depth = depth + 1
        if on:
            # create section number
            number = ''
            if self._show_section_numbers:
                # count headings on all levels
                self.request._fmt_hd_counters = self.request._fmt_hd_counters[:count_depth]
                while len(self.request._fmt_hd_counters) < count_depth:
                    self.request._fmt_hd_counters.append(0)
                self.request._fmt_hd_counters[-1] = self.request._fmt_hd_counters[-1] + 1
                number = '.'.join(map(str, self.request._fmt_hd_counters[self._show_section_numbers-1:]))
                if number: number += ". "
            attr = {}
            if id:
                attr['id'] = id
            # Add space before heading, easier to check source code
            ret='\n' +self.open('h%d' % depth, attr=attr)
            return "%s%s" % (ret,number)
            
        else:
##            # closing tag, with empty line after, to make source more readable
            title=self.recordedtext
#            if self.document!=None:
#                pass
#TODO
#                self.word_host.Selection.TypeParagraph()
#                style=win32com.client.constants.wdStyleHeading1 - depth +1
#                self.word_host.Selection.Paragraphs.Last.Style=style
#                self.word_host.Selection.TypeText('%s' % (title))
#                self.word_host.Selection.TypeParagraph()
#                self.word_host.Selection.Paragraphs.Last.Style=win32com.client.constants.wdStyleNormal
            self.currentstyle= copy.deepcopy(self.standardstyle)
            heading=""
            if depth == 1:
                self.currentstyle=self.styleH1
                for i in range(2,6):
                    self.seq.reset("H%s" % i)  # reset all deeper heading numbers
                heading= "%(H1+)s " % self.seq # increase the current depth and write heading numbers till the current depth
            elif depth == 2:
                self.currentstyle=self.styleH2
                for i in range(3,6):
                    self.seq.reset("H%s" % i)  # reset all deeper heading numbers
                heading= "%(H1)s.%(H2+)s " % self.seq # increase the current depth and write heading numbers till the current depth
            elif depth == 3:
                self.currentstyle=self.styleH3
                for i in range(4,6):
                    self.seq.reset("H%s" % i) # reset all deeper heading numbers
                heading= "%(H1)s.%(H2)s.%(H3+)s " % self.seq # increase the current depth and write heading numbers till the current depth
            elif depth == 4:
                self.currentstyle=self.styleH4
                for i in range(5,6):
                    self.seq.reset("H%s" % i) # reset all deeper heading numbers
                heading= "%(H1)s.%(H2)s.%(H3)s.%(H4+)s " % self.seq # increase the current depth and write heading numbers till the current depth
            elif depth == 5:
                self.currentstyle=self.styleH5
                for i in range(5,6):
                    self.seq.reset("H%s" % i) # reset all deeper heading numbers
                heading= "%(H1)s.%(H2)s.%(H3)s.%(H4)s.%(H5+)s " % self.seq # increase the current depth and write heading numbers till the current depth
            heading += title
#            self.story.append(Paragraph("[%s]%s" % (depth,title),self.currentstyle))
            self.story.append(Paragraph("%s" % (heading),self.currentstyle))
            if _debug:
                sys.stderr.write(self.para_story+"\n")            
            self.currentstyle= copy.deepcopy(self.standardstyle)

            ret=self.close('h%d' % depth)
            return ret



    # Tables #############################################################

    _allowed_table_attrs = {
        'table': ['class', 'id', 'style'],
        'row': ['class', 'id', 'style'],
        '': ['colspan', 'rowspan', 'class', 'id', 'style'],
    }

    def _checkTableAttr(self, attrs, prefix):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
        if not attrs: return u''

        result = ''
        for key, val in attrs.items():
            if prefix and key[:len(prefix)] != prefix: continue
            key = key[len(prefix):]
            if key not in self._allowed_table_attrs[prefix]: continue
            result = '%s %s=%s' % (result, key, val)

        return result

    def table(self, on, attrs=None):
        """ Create table

        @param on: start table
        @param attrs: table attributes
        @rtype: string
        @return start or end tag of a table
        """
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        result = []
        if on:
            # Open div to get correct alignment with table width smaller
            # than 100%
#            ret=self.open('div', newline=1)
#            result.append(ret)

            # Open table
            if not attrs:
                attrs = {}
            else:
                attrs = self._checkTableAttr(attrs, 'table')
            ret= self.open('table', newline=1, attr=attrs)

            self.list_levels['table']=self.list_levels['table']+1
            self.list_levels['all']=self.list_levels['all']+1
            if self.document!=None:
                pass
#TODO
#                if self.word_host.Selection.Range.ListFormat.ListType == win32com.client.constants.wdListBullet:
#                    self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
#                self.word_host.Selection.TypeParagraph()
#                self.document.Tables.Add(Range=self.word_host.Selection.Range,
#                    NumRows=1, NumColumns= 1, DefaultTableBehavior=win32com.client.constants.wdWord9TableBehavior,
#                    AutoFitBehavior= win32com.client.constants.wdAutoFitContent)
            self._first_tr = 1
            self._first_td = 1
            self._table_start=1
            return ret
        else:
            self.list_levels['table']=self.list_levels['table']-1
            self.list_levels['all']=self.list_levels['all']-1
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.MoveDown(Unit=win32com.client.constants.wdLine, Count=1)
#                self.word_host.Selection.TypeParagraph()

            ret=self.close('table')
#            ret=self.close('div')
            
            return ret

    def table_row(self, on, attrs=None):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'tr'
        if on:
            if not attrs:
                attrs = {}
            else:
                attrs = self._checkTableAttr(attrs, 'row')
            ret=self.open(tag, newline=1, attr=attrs)
            if self._first_tr == 0:
                #first row always existing
                if self.document!=None:
                    pass
#TODO
#                    self.word_host.Selection.InsertRowsBelow(1)
                self._first_td = 1
            elif self._first_td == 1:
#                if self.document!=None:
#                    self.word_host.Selection.TypeText('#')
                self._table_start = 0
            return ret
        else:
            self._first_tr = 0
            ret=self.close(tag)
            return ret
            

    def table_cell(self, on, attrs=None):
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        tag = 'tr'
        if on:
            if not attrs:
                attrs = {}
            else:
                attrs = self._checkTableAttr(attrs, 'row')
            ret=self.open(tag, newline=1, attr=attrs)
            if self.document!=None:
                pass
#TODO
#                self.word_host.Selection.Style=self.defchar_style
            if self._first_tr == 1:
                if self._first_td == 0:
                    #first cell always existing
                    if self.document!=None:
                        pass
#TODO
#                        self.word_host.Selection.InsertColumnsRight()
#                        self.word_host.Selection.Style=self.defchar_style
                        
            else:
                #jump into cell
                if self.document!=None:
                    pass
#TODO
#                    self.word_host.Selection.MoveRight(Unit=win32com.client.constants.wdCell)
#                    self.word_host.Selection.Style=self.defchar_style
                self._first_td = 0
            return ret
        else:
            self._first_td = 0
            ret=self.close(tag)
            return ret

    def macro(self, macro_obj, name, args):
        #not implemented yet
        return ""
        # call the macro
        if name in ['TableOfContents',]:
            #skip call, emulate behavior
##    With ActiveDocument
##        .TablesOfContents.Add Range:=Selection.Range, RightAlignPageNumbers:= _
##            True, UseHeadingStyles:=True, UpperHeadingLevel:=1, _
##            LowerHeadingLevel:=3, IncludePageNumbers:=True, AddedStyles:="", _
##            UseHyperlinks:=True, HidePageNumbersInWeb:=True
##        .TablesOfContents(1).TabLeader = wdTabLeaderSpaces
##        .TablesOfContents.Format = wdIndexIndent
            try:
                self.mindepth = max(int(self.request.getPragma('section-numbers', 1)),1)
            except (ValueError, TypeError):
                self.mindepth = 1

            try:
                self.maxdepth = max(int(args), 1)
            except (ValueError, TypeError):
                self.maxdepth = 9
            sys.stdout.write("TOCrange:%s-%s" % (self.mindepth,self.maxdepth))
            if self.document!=None:
                self.word_host.ActiveDocument.TablesOfContents.Add(\
                    Range=self.word_host.Selection.Range, UpperHeadingLevel=self.mindepth,\
                    LowerHeadingLevel=self.maxdepth,UseHyperlinks=vbTrue)
            return "<TOC/>"
        
        return macro_obj.execute(name, args) 



    def escapedText(self, text):
        return text
        return wikiutil.escape(text)


    def _img(self,imgurl,**kw):

        imageWidth= 0
        imageHeight= 0
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        trusted=1
        scheme = string.split(imgurl, ":", 1)[0]
        if scheme in tuple(string.split('http|https|ftp|nntp','|')):
            trusted=0
            filepath=imgurl
            self.request.write("adding http picture, filepath=%s  " % (filepath))
            #retrieve remote file to temp
            try:
                (filename, headers)=urllib.urlretrieve( imgurl)
                print "remote url %s retrieved to %s" % (imgurl,filename)
                filepath=filename
            except:
                filepath=imgurl
            self.request.write("adding http picture, filepath=%s" % (filepath))
        elif scheme in tuple(string.split('file|self|wiki','|')):
            trusted=0
            #filepath=imgurl
##            filepath= string.split(imgurl, ':', 1)[1]
##            if filepath[3]==':': # eg: (file:)//C:\bla
##                filepath= string.split(filepath, '//', 1)[1]
##            self.request.write("adding file|self|wiki picture, filepath=%s  " % (filepath))
#RS
            if scheme=="file":
                filepath = string.split(imgurl, ":", 1)[1]
                if filepath.find(":")!=-1:
                    filepath=filepath[2:]
                    self.request.write("adding file picture with drive, filepath=%s" % (filepath))
                else:
                    filepath='\\\\'+filepath[2:]
                    self.request.write("adding file picture with UNC, filepath=%s" % (filepath))
            else:
                filepath=imgurl
                self.request.write("adding self|wiki picture, filepath=%s" % (filepath))
        else:
            trusted=1
            if imgurl.startswith("./"):
                imgfile=imgurl[2:]        
                filepath = os.path.abspath(os.path.join(self.cfg.url_prefix_dir, imgfile))
            elif imgurl.startswith(".\\"):
                imgfile=imgurl[2:]
                print "attachment?"
                filepath = os.path.abspath(os.path.join(self.cfg.data_dir,"pages", imgfile))
            else:
                imgfile=imgurl
                filepath = os.path.abspath(os.path.join(self.cfg.url_prefix_dir, imgfile))
            self.request.write("\n adding .. picture, imgfile=%s, targetdir=%s, filepath=%s" % (imgfile,self.targetdir,filepath))
        if self.document!=None:
            pass 

        imageReader=ImageReader(filepath)
        imageWidth, imageHeight= imageReader.getSize()
        #scale imagesize (only a fixed maximum size at present : (PAGE_WIDTH- 6* cm):(PAGE_HEIGHT- 8* cm))
        if imageWidth > (self.PAGE_WIDTH- 6* cm) or imageHeight > (self.PAGE_HEIGHT- 8* cm):
            if imageWidth/ (self.PAGE_WIDTH- 6* cm) < imageHeight/ (self.PAGE_HEIGHT- 8* cm):
                imageWidth= imageWidth/ (imageHeight/ (self.PAGE_HEIGHT- 8* cm))
                imageHeight= imageHeight/ (imageHeight/ (self.PAGE_HEIGHT- 8* cm))
            else:
                imageHeight= imageHeight/ (imageWidth/ (self.PAGE_WIDTH- 6* cm))
                imageWidth= imageWidth/ (imageWidth/ (self.PAGE_WIDTH- 6* cm))
        self.story.append(Image(filepath, width= imageWidth, height= imageHeight))

#word
#            if self.word_host.Selection.Range.ListFormat.ListType == win32com.client.constants.wdListBullet:
#                self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
#            try:
#                self.word_host.Selection.InlineShapes.AddPicture(FileName=filepath,\
#                  LinkToFile=False, SaveWithDocument=True)
#            except:
#                if trusted:
#                    self.request.write("error in img, imgfile=%s, docpath=%s" % (filepath,str(self.document.Path)))
#                    self.request.write("Active %s" % str(self.word_host.Selection.Active))
#                    raise
#                    errtext='[internal image not found:%s]' % filepath
#                    self.document.Undo()
#                    try:
#                        self.word_host.Selection.TypeText(errtext)
#                    except:
#                        self.request.write("error reset did not work, may need Office 2000 SP3?")
#                        raise "error reset did not work, may need Office 2000 SP3?"
#                else:
#                    self.request.write("warning in img, imgfile=%s, docpath=%s" % (filepath,str(self.document.Path)))
#                    self.word_host.Selection.TypeText('[external image not found:%s]' % filepath)
#                    
#            self.word_host.Selection.TypeText(' ')
#            self._save()


    def image(self, **kw):
        """ Take HTML <IMG> tag attributes in `attr`.

            Attribute names have to be lowercase!
        """
        #self.request.write("#def image" )
        if _debug:
            traceback.print_stack(limit=1,file=sys.stdout)
#RS fatal error handling
        if self.dead==1:
            return u""
#RS end
        attrstr = u''
        for attr, value in kw.items():
            if attr=='html_class':
                attr='class'
            attrstr = attrstr + u' %s="%s"' % (attr, wikiutil.escape(value))
        imgurl=kw.get('src','')
        self.request.write("\ntry image, imgurl=%s  " % (imgurl))
        if imgurl!='':
            self._img(imgurl,**kw)
        result= u'<img%s/>' % attrstr
        return result



    def rawHTML(self, markup):
        """ This allows emitting pre-formatted HTML markup, and should be
            used wisely (i.e. very seldom).

            Using this event while generating content results in unwanted
            effects, like loss of markup or insertion of CDATA sections
            when output goes to XML formats.
        """
        return '<<'+markup+'>>'

class Privatestack:
    '''a private LIFO Stack
    you can ppush an element on and ppop it from'''

    def __init__(self):
        self.__privatestack_= []
    def ppush(self, element):
        '''push an element on the stack'''
        self.__privatestack_.append(element)
        return
    def ppop(self):
        '''returns the last element from the stack
        (returns None for an empty stack)'''
        if not len(self.__privatestack_):
            return None
        element= self.__privatestack_.pop()
        return element

###abp flow start
##styles = getSampleStyleSheet()
###Title = wikiutil.quoteFilename(pagename)
###Author = self.request.user.name
###goFile = Title + DOC_SUFFIX
###goFilePath = os.path.abspath(os.path.join(self.targetdir, goFile))
##goFilePath = ''
##
##def myFirstPage(canvas, doc):
##    canvas.saveState()
##    canvas.restoreState()
##
##def myLaterPages(canvas, doc):
##    canvas.saveState()
##    canvas.setFont('Times-Roman',9)
##    canvas.drawString(inch, 0.75 * inch, "Page %d" % doc.page)
##    canvas.restoreState()
##
##def go(goFilePath):
##    doc = SimpleDocTemplate(goFilePath,showBoundary='showboundary' in sys.argv)
##    doc.allowSplitting = not 'nosplitting' in sys.argv
##    doc.build(Elements,myFirstPage,myLaterPages)
##
##Elements = []
##
##ChapterStyle = copy.copy(styles["Heading1"])
##ChapterStyle.alignment = TA_CENTER
##ChapterStyle.fontsize = 16
##InitialStyle = copy.deepcopy(ChapterStyle)
##InitialStyle.fontsize = 16
##InitialStyle.leading = 20
##PreStyle = styles["Code"]
##
##def newPage():
##    Elements.append(PageBreak())
##
##def chapter(txt, style=ChapterStyle):
##    newPage()
##    Elements.append(Paragraph(txt, style))
##    Elements.append(Spacer(0.2*inch, 0.3*inch))
##
##def fTitle(txt,style=InitialStyle):
##    Elements.append(Paragraph(txt, style))
##
##ParaStyle = copy.deepcopy(styles["Normal"])
##ParaStyle.spaceBefore = 0.1*inch
##
##if 'right' in sys.argv:
##    ParaStyle.alignment = TA_RIGHT
##elif 'left' in sys.argv:
##    ParaStyle.alignment = TA_LEFT
##elif 'justify' in sys.argv:
##    ParaStyle.alignment = TA_JUSTIFY
##elif 'center' in sys.argv or 'centre' in sys.argv:
##    ParaStyle.alignment = TA_CENTER
##else:
##    ParaStyle.alignment = TA_JUSTIFY
##
##def spacer(inches):
##    Elements.append(Spacer(0.1*inch, inches*inch))
##
##def p(txt, style=ParaStyle):
##    Elements.append(Paragraph(txt, style))
##
##def pre(txt, style=PreStyle):
##    spacer(0.1)
##    p = Preformatted(txt, style)
##    Elements.append(p)
##
##def parseOdyssey(output, pfilepath, ptitle, pauthor):
##
###    from time import time
##    E = []
###    t0=time()
###   L = open(fn,'r').readlines()
##    L = []
##    #L.append(output)
##    #for a in output:
##    #    L.append(a)
##    L=output.split("\n")  #jedes Listenelement ist eine Textzeile ohne \n
###    L.insert(0,'')
###    L.insert(0,'-----')
##    L.insert(0,'')
##    global goFilePath
##    goFilePath = pfilepath
##    Title = ptitle
##    Author = pauthor
###    t1 = time()
###    print "open stream took %.4f seconds" %(t1-t0)
####    L=replace(L,'\012','')
####	L=map(lambda x:x+"\012",L)
####	for i in xrange(len(L)):
####		if L[i][-1]=='\012':
####			L[i] = L[i][:-1]
###    t2 = time()
###    print "Removing all linefeeds took %.4f seconds" %(t2-t1)
###    L.append('')
###    L.append('-----')
###    lo=L[0]
###    lp=L[1]
###    print testen,lo,lp
##
####    def findNext(L, i):
####        kind=1
####        while 1: #moegliche abbruchbedingungen fuer die schleife:
####                 # -> es existiert eine Leerzeile
####                 # a) und dann keine weitere zeile -> ende (Leerzeile und dann nichts mehr)
####                 # b) weitere zeilen, dann werden
####                     #anschliessende leerzeilen entfernt
####                     # b) dann existiert keine weitere zeile -> ende (Leerzeilen und dann nichts mehr)
####                     # c) weitere zeilen existieren
####                         # naechste zeile beginnt und endet mit -?
####                             # c) ja: dann wird die zeile geloescht
####                             # c) danach keine weitere Zeile? -> ende (Leerzeile(n) direkt danach von '-' umrahmte zeile und dann nichts mehr)
####                                 # d) danach weitere zeilen: loesche nachfolgende leerzeilen und dann -> ende (Leerzeile(n) direkt danach von '-' umrahmte zeile)
####                             # e) nein: -> ende mit kind=0 und sofortiger neubeginn mit index 0
####            if string.strip(L[i])=='': #ist zeile i ohne sonderzeichen leer?
####                del L[i] #dann loesche die zeile i (zeilenanzahl verringert sich um 1)
####                kind = 1
####                if i<len(L): #index i kleiner als die neue Zeilengesamtzahl?
####                    while string.strip(L[i])=='': #solange zeile i ohne sonderzeichen leer?;loescht nach der leerzeile jetzt alle nachfolgenden leerzeilen
####                        del L[i] # loesche zeile i
####
####                    if i<len(L): #index i kleiner als die neue Zeilengesamtzahl?
####                        #kind = L[i][-1]=='-' and L[i][0]=='-'
####                        if L[i][-1]=='-' and L[i][0]=='-': #letzte und erste zeichen der zeile i ein '-'?
####                            kind = 1
####                        else:
####                            kind = 0
####                        if kind: #wenn kind wahr, also zeile i von '-' eingerahmt, dann:
####                            del L[i]  #loesche diese zeile
####                            if i<len(L):#index i kleiner als die neue Zeilengesamtzahl?
####                                while string.strip(L[i])=='':#solange zeile i ohne sonderzeichen leer?
####                                    del L[i] #loesche zeile i
####                break
####            else:
####                i = i + 1
####
####        return i, kind
##
##    def findNext(L, i):
##        while 1: 
####            if string.strip(L[i])=='': #ist zeile i ohne sonderzeichen leer?
####                del L[i] #dann loesche die zeile i (zeilenanzahl verringert sich um 1)
####                kind = 1
##            kind=1
##            if i>=len(L): #index i groesser als die neue Zeilengesamtzahl?
##                break
##            else:
##                while string.strip(L[i])=='': #solange zeile i ohne sonderzeichen leer?
##                    del L[i] # loesche zeile i
##                    if i>=len(L): #index i groesser als die neue Zeilengesamtzahl?
##                        break
##
##                if i>len(L): #index i groesser als die neue Zeilengesamtzahl?
##                    break
##                else:
##                    if L[i][0:9] == '#STARTDOC' or L[i][-7:] == '#ENDDOC':
##                        kind = 1
##                    else:
##                        kind = 0
##                    if kind: 
##                       # del L[i]  #loesche diese zeile
##                        if i<=len(L):#index i kleiner gleich die neue Zeilengesamtzahl?
##                            while string.strip(L[i])=='':#solange zeile i ohne sonderzeichen leer?
##                                del L[i] #loesche zeile i
##                        break
##            i = i + 1
##
##        return i, kind
##
##
##    f = s = 0
##    while 1:
##        f, k = findNext(L,0)
##        if k: break
##
##    E.append([spacer,2])
##    E.append([fTitle, Title, InitialStyle])
##    E.append([fTitle,'<font size=-4>translated by</font> %s' % Author, InitialStyle])
###    print testen,L,E,f,k
##
##    while 1:
##        if f>=len(L): break
###        print testen,L,E,f,k
##        if string.upper(L[f].strip()[0:5])=='BOOK ':
##            E.append([chapter,L[f]])
##            f=f+1
##            while string.strip(L[f])=='': del L[f]
##            style = ParaStyle
##            func = p
##        else:
##            style = PreStyle
##            func = pre
##
##        while 1:
##            s=f
##            f, k=findNext(L,s)
##            sep= (func is pre) and '\012' or ' '
##            #print testen,L,E,s,f
##
##            E.append([func,string.join(L[s:f],sep),style])
##            if k: break
###    t3 = time()
###    print "Parsing into memory took %.4f seconds" %(t3-t2)
###    print testen,L,E
##    del L
###    t4 = time()
###    print "Deleting list of lines took %.4f seconds" %(t4-t3)
##    for i in xrange(len(E)):
##        apply(E[i][0],E[i][1:])
###    t5 = time()
###    print "Moving into platypus took %.4f seconds" %(t5-t4)
##    del E
###    t6 = time()
###    print "Deleting list of actions took %.4f seconds" %(t6-t5)
##    go(goFilePath)
###    t7 = time()
###    print "saving to PDF took %.4f seconds" %(t7-t6)
###    print "Total run took %.4f seconds"%(t7-t0)
##
###    for fn in ('odyssey.full.txt','odyssey.txt'):
###        if os.path.isfile(fn):
###            break
##
##
###abp flow pause