Attachment 'text_word.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3 MoinMoin - "text/word" Formatter
   4 
   5 Experimental by RS, derived from text_html.py
   6 
   7 Create MS Word Document as 'side effect'
   8 
   9 ORS modifications
  10 =================
  11 -        13.01.04 RS upgrade to 1.1.
  12 -        20.01.04 RS fatal errors handling
  13 -        22.01.04 RS print replaced by self.request.write
  14 -        28.01.05 RS fixed img handling (path problem)
  15 -        27.09.05 RS upgrade to 1.3.5, old 1.1 code removed
  16 
  17 @todo: Handle distorted tables (with spanning cells)        
  18 """
  19 
  20 # Imports
  21 import cgi, string, sys, time, os, re, copy,traceback,urllib
  22 from MoinMoin.formatter.base import FormatterBase
  23 from MoinMoin import wikiutil, config, user,webapi, i18n
  24 
  25 from MoinMoin.Page import Page
  26 #RS Word
  27 import win32com.client, win32com.client.dynamic
  28 vbTrue=-1
  29 vbFalse=0
  30 #RS end
  31 
  32 DOC_SUFFIX = ".doc"  # perhaps put this in config.py as html_suffix?
  33 
  34 #############################################################################
  35 ### HTML Formatter
  36 #############################################################################
  37 
  38 _debug=1
  39 
  40 class Formatter(FormatterBase):
  41     """
  42         Send HTML data.
  43     """
  44 
  45 #    hardspace = ' '
  46     hardspace = ' '
  47 
  48     def __init__(self, request, **kw):
  49         if _debug:
  50             traceback.print_stack(limit=1,file=sys.stdout)
  51         apply(FormatterBase.__init__, (self, request), kw)
  52 #RS additional property "mimetype"
  53         self.mimetype="text/word"
  54         sys.stderr.write("\nThis is the Word Formatter....")
  55 #RS end
  56         self.dead=0
  57         self.store_text=0 # store text in self._text instead of emitting it
  58         self.recordedtext=""
  59         self.recordedcursor=0
  60         # inline tags stack. When an inline tag is called, it goes into
  61         # the stack. When a block element starts, all inline tags in
  62         # the stack are closed.
  63         self._inlineStack = []
  64 
  65         self._in_li = 0
  66         self._first_li = 0
  67         self._first_tr = 0
  68         self._first_td = 0
  69         self._table_start=0
  70         self._ignore_next_paragraph=0
  71         self.list_levels={'ul':0,'ol':0,'dl':0,'table':0,'all':0}
  72         self.last_indent_type=''
  73         self._in_code = 0
  74         self._base_depth = 0
  75         self._in_code_area = 0
  76         self._in_code_line = 0
  77         self._code_area_num = 0
  78         self._code_area_js = 0
  79         self._code_area_state = ['', 0, -1, -1, 0]
  80         self._show_section_numbers = None
  81         self._content_ids = []
  82         self.pagelink_preclosed = False
  83         self._is_included = kw.get('is_included',False)
  84         self.request = request
  85         self.cfg = request.cfg
  86 #        self.targetdir=kw.get('targetdir',config.data_dir)
  87         self.targetdir=kw.get('targetdir',request.cfg.data_dir)
  88 
  89         if not hasattr(request, '_fmt_hd_counters'):
  90             request._fmt_hd_counters = []
  91         self.document=None
  92         self.doctemplate="D_ORS_Entwicklungsauftrag_v02.dot"
  93         self.doctemplate="Normal.dot"
  94         self.word_host = None
  95         self.doccount=0
  96         self.tt_start=0
  97         
  98     def _reset_indents(self):
  99         if _debug:
 100             traceback.print_stack(limit=1,file=sys.stdout)
 101         self._in_li = 0
 102         self._first_li = 0
 103         self._first_tr = 0
 104         self._first_td = 0
 105         self._table_start=0
 106         self._ignore_next_paragraph=0
 107         self.list_levels={'ul':0,'ol':0,'dl':0,'table':0,'all':0}
 108         self.last_indent_type=''
 109         
 110 
 111     def FatalEnd(self):
 112         """
 113         make sure we do not leave any ActiveX corpses behind if errors occur
 114         """
 115         if _debug:
 116             traceback.print_stack(limit=1,file=sys.stdout)
 117         try:
 118             if self.document is not None:
 119                 self.document.Close(-1)
 120             if self.word_host is not None:
 121                 self.word_host.Quit()
 122             self.document=None
 123             self.word_host=None
 124         except:
 125             pass
 126 #            raise
 127         self.dead=1
 128         
 129     def _save(self):
 130         if _debug:
 131             traceback.print_stack(limit=1,file=sys.stdout)
 132 #RS fatal error handling
 133         if self.dead==1:
 134             return
 135 #RS end
 136         if self.document!=None:
 137             self.document.Save()
 138 
 139     # Primitive formatter functions #####################################
 140 
 141     # all other methods should use these to format tags. This keeps the
 142     # code clean and handle pathological cases like unclosed p and
 143     # inline tags.
 144 
 145     def langAttr(self, lang=None):
 146         """ Return lang and dir attribute
 147 
 148         Must be used on all block elements - div, p, table, etc.
 149         @param lang: if defined, will return attributes for lang. if not
 150             defined, will return attributes only if the current lang is
 151             different from the content lang.
 152         @rtype: dict
 153         @return: language attributes
 154         """
 155         if not lang:
 156             lang = self.request.current_lang
 157             # Actions that generate content in user language should change
 158             # the content lang from the default defined in cfg.
 159             if lang == self.request.content_lang:
 160                 # lang is inherited from content div
 161                 return {}
 162 
 163         attr = {'lang': lang, 'dir': i18n.getDirection(lang),}
 164         return attr
 165 
 166     def formatAttributes(self, attr=None):
 167         """ Return formatted attributes string
 168 
 169         @param attr: dict containing keys and values
 170         @rtype: string ?
 171         @return: formated attributes or empty string
 172         """
 173         if attr:
 174             attr = [' %s="%s"' % (k, v) for k, v in attr.items()]           
 175             return ''.join(attr)
 176         return ''
 177 
 178     # TODO: use set when we require Python 2.3
 179     # TODO: The list is not complete, add missing from dtd
 180 #RS Word: use _blocks for all tags that can only be interpreted on close, i.e. text between open and close must be recorded    
 181 ##    _blocks = 'p div pre table tr td ol ul dl li dt dd h1 h2 h3 h4 h5 h6 hr form'
 182     _blocks = 'div pre dt dd h1 h2 h3 h4 h5 h6 form url pagelink'
 183 #RS end
 184     _blocks = dict(zip(_blocks.split(), [1] * len(_blocks)))
 185 
 186     def open(self, tag, newline=False, attr=None):
 187         """ Open a tag with optional attributes
 188         
 189         @param tag: html tag, string
 190         @param newline: render tag on a separate line
 191         @param attr: dict with tag attributes
 192         @rtype: string ?
 193         @return: open tag with attributes
 194         """
 195 #        if _debug:
 196 #            traceback.print_stack(limit=1,file=sys.stdout)
 197         if tag in self._blocks:
 198             # Block elements
 199 #RS word
 200             if _debug:
 201                 print "OPEN %s (recording)" % tag
 202 #                if self.document!=None:
 203 #                   self.word_host.Selection.TypeText("OPEN %s (recording)" % tag)
 204             self.store_text=1
 205             self.recordedtext=""
 206             if self.word_host:
 207                 self.recordedcursor=int(self.word_host.Selection.Range.End)
 208 #RS end
 209             result = []
 210             
 211             # Add language attributes, but let caller overide the default
 212             attributes = self.langAttr()
 213             if attr:
 214                 attributes.update(attr)
 215             
 216             # Format
 217             attributes = self.formatAttributes(attributes)
 218             result.append('<%s%s>' % (tag, attributes))
 219             if newline:
 220                 if _debug:
 221                     print "OPEN with NEWLINE"
 222                 if self.document:
 223                     self.word_host.Selection.TypeParagraph()
 224                 
 225                 result.append('\n')
 226             return ''.join(result)
 227         else:
 228             # Inline elements
 229             # Add to inlineStack
 230             if _debug:
 231                 print "OPEN %s (inline)" % tag
 232 #                if self.document!=None:
 233 #                   self.word_host.Selection.TypeText("OPEN %s (inline)" % tag)
 234             self._inlineStack.append(tag)
 235             # Format
 236             return '<%s%s>' % (tag, self.formatAttributes(attr))
 237        
 238     def close(self, tag, newline=False):
 239         """ Close tag
 240 
 241         @param tag: html tag, string
 242         @rtype: string ?
 243         @return: closing tag
 244         """
 245 #        if _debug:
 246 #            traceback.print_stack(limit=1,file=sys.stdout)
 247         if tag in self._blocks:
 248             # Block elements
 249             # Close all tags in inline stack
 250             # Work on a copy, because close(inline) manipulate the stack
 251 #RS word            
 252             if _debug:
 253                 try:
 254                     print 'CLOSE %s (recorded="%s", at %s)' % (tag,self.recordedtext,self.recordedcursor)
 255                 except:
 256                     print 'CLOSE %s (recorded=???, at %s)' % (tag,self.recordedcursor)
 257                     
 258 #                if self.document!=None:
 259 #                   self.word_host.Selection.TypeText("CLOSE %s (recorded)" % tag)
 260             self.store_text=0
 261             self.recordedtext=""
 262             self.recordedcursor=0
 263 #RS end            
 264             result = []
 265             stack = self._inlineStack[:]
 266             stack.reverse()
 267             for inline in stack:
 268                 result.append(self.close(inline))
 269             # Format with newline
 270             if newline:
 271                 if _debug:
 272                     print "CLOSE with NEWLINE"
 273                 result.append('\n')
 274             result.append('</%s>\n' % (tag))
 275             return ''.join(result)            
 276         else:
 277             # Inline elements 
 278             # Pull from stack, ignore order, that is not our problem.
 279             # The code that calls us should keep correct calling order.
 280             if _debug:
 281                 print "CLOSE %s (inline)" % tag
 282 #                if self.document!=None:
 283 #                   self.word_host.Selection.TypeText("CLOSE %s (inline)" % tag)
 284             if tag in self._inlineStack:
 285                 if _debug:
 286                     print "CLOSE %s (inline stack remove)" % tag
 287                 self._inlineStack.remove(tag)
 288             return '</%s>' % tag
 289 
 290     def startDocument(self, pagename):
 291         if _debug:
 292             traceback.print_stack(limit=1,file=sys.stdout)
 293             sys.stderr.write("\nThis is the Word Formatter::startDocument....")
 294         self.doccount+=1
 295         if self.word_host==None:
 296             try:
 297                 self.word_host = win32com.client.Dispatch("Word.Application") # open MS Word
 298                 
 299             except:
 300                 self.request.write( "#STARTDOC %s %s failed at Host Initialisation" % (self.doccount,pagename))
 301                 self.word_host=None
 302                 raise
 303 
 304             try:
 305                 self.word_host.Visible=1
 306             #Visible is essential, otherwise strange things may happen (Kill Bill!!!)
 307             except:
 308                 self.request.write("#STARTDOC %s %s failed at Host Visible" % (self.doccount,pagename))
 309             try:
 310                 self.request.write("#STARTDOC uses template dir %s" % str(self.word_host.Options.DefaultFilePath(win32com.client.constants.wdUserTemplatesPath)))
 311             except:
 312                 raise
 313         else:
 314             self.request.write("\nMSWORD HOST already active!\n")
 315         if self.document!=None:
 316             self.request.write("ignore#STARTDOC %s %s" % (self.doccount,pagename))
 317             return u"ignore#STARTDOC %s %s" % (self.doccount,pagename)
 318         try:
 319             
 320 ##            self.document=self.word_host.Documents.Add(Template=self.doctemplate,Visible=vbFalse)
 321             self.document=self.word_host.Documents.Add(Template=self.doctemplate,Visible=vbTrue)
 322             #we only want the styles from the template, not the content
 323         except:
 324             self.FatalEnd()
 325             self.request.write("#STARTDOC %s %s failed at Documents.Add(%s..." % (self.doccount,pagename,self.doctemplate))
 326             raise
 327         
 328         try:
 329             self.document.Content.Delete()
 330             self.wdCharacter=win32com.client.constants.wdCharacter
 331             self.wdExtend=win32com.client.constants.wdExtend
 332             self.ul_type=win32com.client.constants.wdListBullet
 333             self.ol_type=win32com.client.constants.wdListOutlineNumbering
 334             self.tt_style=win32com.client.constants.wdStyleHtmlTt
 335             self.pre_style=win32com.client.constants.wdStyleHtmlPre
 336             self.defchar_style=win32com.client.constants.wdStyleDefaultParagraphFont
 337             self.defpara_style=win32com.client.constants.wdStyleNormal
 338             self.wdWord9ListBehavior=win32com.client.constants.wdWord9ListBehavior
 339             self.wdNumberGallery=win32com.client.constants.wdNumberGallery
 340             self.wdListApplyToThisPointForward=win32com.client.constants.wdListApplyToThisPointForward
 341             
 342             self.word_host.Selection.Style=self.defpara_style
 343             self.normalstyle=self.word_host.Selection.Style
 344             self.request.write("NORMSTYLE: %s" % self.normalstyle)
 345             self._reset_indents()
 346             
 347             file = wikiutil.quoteWikinameFS(pagename) + DOC_SUFFIX
 348             filepath = os.path.abspath(os.path.join(self.targetdir, file))
 349             self.document.SaveAs(filepath,0)
 350 #            self.request.write("#STARTDOC %s %s" % (self.doccount,pagename)
 351             return u"#STARTDOC %s %s" % (self.doccount,pagename)
 352         except:
 353             self.FatalEnd()
 354             self.request.write("#STARTDOC %s %s failed" % (self.doccount,pagename))
 355             raise
 356 
 357     def endDocument(self):
 358 #RS fatal error handling
 359         if _debug:
 360             traceback.print_stack(limit=1,file=sys.stdout)
 361         if self.dead==1:
 362             return u""
 363 #RS end
 364         self.doccount-=1
 365         if self.doccount==0:
 366             try:
 367                 self.word_host.ActiveDocument.Fields.Update()
 368                 self.document.Close(-1)
 369                 self.word_host.Quit()
 370                 self.document=None
 371                 self.word_host=None
 372                 return u"#ENDDOC"
 373             except:
 374                 return u"#ENDDOC failed"
 375                 
 376         return u"#ENDDOC %s" % self.doccount
 377 
 378     def startContent(self, content_id='content', **kwargs):
 379         """ Start page content div """
 380         return ''
 381         if _debug:
 382             traceback.print_stack(limit=1,file=sys.stdout)
 383         # Setup id
 384         if content_id!='content':
 385             aid = 'top_%s' % (content_id,)
 386         else:
 387             aid = 'top'
 388         self._content_ids.append(content_id)
 389         result = []
 390         # Use the content language
 391         attr = self.langAttr(self.request.content_lang)
 392         attr['id'] = content_id
 393         result.append(self.open('div', newline=1, attr=attr))
 394         result.append(self.anchordef(aid))
 395         return ''.join(result)
 396         
 397     def endContent(self):
 398         """ Close page content div """
 399         return ''
 400         if _debug:
 401             traceback.print_stack(limit=1,file=sys.stdout)
 402 
 403         # Setup id
 404         try:
 405             cid = self._content_ids.pop()
 406         except:
 407             cid = 'content'
 408         if cid!='content':
 409             aid = 'bottom_%s' % (cid,)
 410         else:
 411             aid = 'bottom'
 412 
 413         result = []
 414         result.append(self.anchordef(aid))
 415         result.append(self.close('div', newline=1))
 416         return ''.join(result)
 417     
 418     def lang(self, on, lang_name):
 419         """ Insert text with specific lang and direction.
 420         
 421             Enclose within span tag if lang_name is different from
 422             the current lang    
 423         """
 424         tag = 'span'
 425         if lang_name != self.request.current_lang:
 426             # Enclose text in span using lang attributes
 427             if on:
 428                 attr = self.langAttr(lang=lang_name)
 429                 ret=self.open(tag, attr=attr)
 430                 return ret
 431             else:
 432                 if self.document!=None:
 433                     pass
 434 #TODO RS word: text with language info?
 435 ###                self.document.XXXX
 436                 ret=self.close(tag)
 437                 return ret
 438 
 439         # Direction did not change, no need for span
 440         return ''            
 441 
 442 
 443     def sysmsg(self, on, **kw):
 444         if _debug:
 445             traceback.print_stack(limit=1,file=sys.stdout)
 446 #RS fatal error handling
 447         if self.dead==1:
 448             return u""
 449 #RS end
 450         tag = 'div'
 451         if on:
 452             ret=self.open(tag, attr={'class': 'message'})
 453             return ret
 454         else:
 455             text=self.recordedtext
 456             if self.document!=None and text!=None:
 457                 self.document.Content.TypeText('#SYSMSG#'+text+'#')
 458             ret=self.close(tag)
 459             return ret
 460             
 461 
 462     def pagelink(self, on, pagename='', page=None, **kw):
 463         """ Link to a page.
 464 
 465             formatter.text_python will use an optimized call with a page!=None
 466             parameter. DO NOT USE THIS YOURSELF OR IT WILL BREAK.
 467 
 468             See wikiutil.link_tag() for possible keyword parameters.
 469         """
 470         if _debug:
 471             traceback.print_stack(limit=1,file=sys.stdout)
 472 #RS fatal error handling
 473         if self.dead==1:
 474             return u""
 475 #RS end
 476         apply(FormatterBase.pagelink, (self, on, pagename, page), kw)
 477         if page is None:
 478             page = Page(self.request, pagename, formatter=self);
 479         tag = 'pagelink'
 480         url = wikiutil.quoteWikinameFS(pagename) + DOC_SUFFIX
 481         if on:
 482             ret=self.open(tag, attr={'class': 'pagelink'})
 483             return ret
 484         else:
 485             text=self.recordedtext
 486             if text==None:
 487                 text=pagename
 488             if self.document!=None:
 489 #                if text!=None:
 490 #                    self.word_host.Selection.TypeText('#PLINK#'+str(text)+'#')
 491 #                else:
 492 #                    self.word_host.Selection.TypeText('#PLINK#'+str(pagename)+'#')
 493                 self.word_host.ActiveDocument.Hyperlinks.Add(\
 494                     Anchor=self.word_host.Selection.Range, Address=url,\
 495                     SubAddress="", ScreenTip="", TextToDisplay=text)
 496             ret=self.close(tag)
 497             return ret
 498 
 499             
 500             
 501 
 502     def interwikilink(self, on, interwiki='', pagename='', **kw):
 503         if not on: return '</a>'
 504         
 505         wikitag, wikiurl, wikitail, wikitag_bad = wikiutil.resolve_wiki(self.request, '%s:%s' % (interwiki, pagename))
 506         wikiurl = wikiutil.mapURL(self.request, wikiurl)
 507 
 508         if wikitag == 'Self': # for own wiki, do simple links
 509             import urllib
 510             if wikitail.find('#')>-1:
 511                 wikitail, kw['anchor'] = wikitail.split('#', 1)
 512             wikitail = urllib.unquote(wikitail)
 513             return apply(self.pagelink, (on, wikiutil.AbsPageName(self.request, self.page.page_name, wikitail)), kw)
 514         else: # return InterWiki hyperlink
 515             href = wikiutil.join_wiki(wikiurl, wikitail)
 516             if wikitag_bad:
 517                 html_class = 'badinterwiki'
 518             else:
 519                 html_class = 'interwiki'
 520 
 521             icon = ''
 522             if self.request.user.show_fancy_links:
 523                 icon = self.request.theme.make_icon('interwiki', {'wikitag': wikitag}) 
 524             return (self.url(1, href, title=wikitag, unescaped=0,
 525                 pretty_url=kw.get('pretty_url', 0), css = html_class) +
 526                 icon)
 527             # unescaped=1 was changed to 0 to make interwiki links with pages with umlauts (or other non-ascii) work
 528 
 529 
 530 #SYNC URL
 531 
 532     def url(self, on, url=None, css=None, **kw):
 533         """ render URL
 534 
 535         @keyword type: "www" or "mailto" to use that icon
 536         @keyword title: <a> title attribute
 537         @keyword attrs: just include those <a> attrs "as is"
 538         """
 539         if _debug:
 540             traceback.print_stack(limit=1,file=sys.stdout)
 541 #RS fatal error handling
 542         if self.dead==1:
 543             return u""
 544 #RS end
 545         if url is not None:
 546             url = wikiutil.mapURL(self.request, url)
 547         title = kw.get('title', None)
 548         attrs = kw.get('attrs', None)
 549 #RS 1.1
 550         target = kw.get('target', None)
 551 #RS stop
 552         str = ''
 553         if css: 
 554             str = '%s class="%s"' % (str, css)
 555         if title:
 556             str = '%s title="%s"' % (str, title)
 557         else:
 558             title=""
 559         if attrs:
 560             str = '%s %s' % (str, attrs)
 561 
 562         # create link
 563 #TODO? insert link icons and other pretty stuff?         
 564         tag = 'url'
 565         if on:
 566             #store this for the close action
 567             self.url_url=url
 568             self.url_title=title
 569             
 570             ret=self.open(tag, attr=attrs)
 571             return ret
 572         else:
 573             text=self.recordedtext
 574             url=self.url_url
 575             title=self.url_title
 576             if text is None:
 577                 text = url
 578             if self.document!=None:
 579                 self.word_host.ActiveDocument.Hyperlinks.Add(\
 580                     Anchor=self.word_host.Selection.Range, Address=wikiutil.escape(url, 1),\
 581                     SubAddress="", ScreenTip=title, TextToDisplay=text)
 582             ret=self.close(tag)
 583             return ret
 584 
 585 
 586     def _wordbookmark(self,name):
 587         """
 588         transform name into a valid Word bookmark name
 589         """
 590         return name.replace("-","_")
 591 
 592     def anchordef(self, id):
 593         if _debug:
 594             traceback.print_stack(limit=1,file=sys.stdout)
 595 #RS fatal error handling
 596         if self.dead==1:
 597             return u""
 598 #RS end
 599         if self.document!=None:
 600             self.document.Bookmarks.Add(Range=self.word_host.Selection.Range,Name=self._wordbookmark(id))
 601         return '<a id="%s"></a>\n' % (id, )
 602 
 603     def anchorlink(self, on, name='', id = None):
 604         if _debug:
 605             traceback.print_stack(limit=1,file=sys.stdout)
 606 ##        if self.document!=None:
 607 ##            self.word_host.Selection.TypeText('_'+text+'_')
 608 #RS fatal error handling
 609         if self.dead==1:
 610             return u""
 611 #RS end
 612         extra = ''
 613         if id:
 614             extra = ' id="%s"' % id
 615         else:
 616             id=''
 617         tag = 'a'
 618         if on:
 619             ret=self.open(tag, attr={'id':'%s' % id})
 620             #store this for the close action
 621             self.anchorlink_name=name
 622             self.anchorlink_id=id
 623             
 624             return ret
 625         else:
 626             text=self.recordedtext
 627             name=self.anchorlink_name
 628             id=self.anchorlink_id
 629             if text==None:
 630                 text=name
 631             if self.document!=None:
 632                 if _debug:
 633                     out="""
 634                 self.word_host.ActiveDocument.Hyperlinks.Add(\
 635                     Anchor=%s, Address="",\
 636                     SubAddress='%s', ScreenTip="", TextToDisplay='%s')
 637                     """ % (str(self.word_host.Selection.Range.Start),name,text)
 638                     sys.stdout.write(out)
 639                     sys.stdout.flush()
 640 #                self.word_host.Selection.TypeText('##')    
 641 #                self.word_host.Selection.MoveLeft(Unit=self.wdCharacter,Count=2,Extend=self.wdExtend)
 642                 self.word_host.ActiveDocument.Hyperlinks.Add(\
 643                     Anchor=self.word_host.Selection.Range, Address="",\
 644                     SubAddress=self._wordbookmark(name), ScreenTip="", TextToDisplay=text)
 645             ret=self.close(tag)
 646             return ret
 647 #RS
 648 
 649 ##    def escape(self,s, quote=None):
 650 ##        """
 651 ##        """
 652 ##        if _debug:
 653 ##            traceback.print_stack(limit=1,file=sys.stdout)
 654 ###        s = s.replace("&", "&amp;") # Must be done first!
 655 ###        s = s.replace("<", "&lt;")
 656 ###        s = s.replace(">", "&gt;")#
 657 ##        if quote:
 658 ##            s = s.replace('"', '""')
 659 ##        return s
 660 
 661 
 662     def pure(self, text):
 663         """
 664         this handles the "not in any markup" case
 665         used in formatters with "side effects"
 666         """
 667         if _debug:
 668             traceback.print_stack(limit=1,file=sys.stdout)
 669 #RS fatal error handling
 670         if self.dead==1:
 671             return u""
 672 #RS end
 673         if (self._table_start == 1):
 674             return u''
 675 #        if self.document!=None:
 676 #            self.word_host.Selection.InsertAfter(text)
 677 #            self.word_host.Selection.TypeText(text)
 678 #            self.document.Content.InsertAfter(text)
 679 #            self.document.Content.InsertAfter('#'+text+'#')
 680         return self._text(text)
 681 
 682     def _text(self, text):
 683 #        return '{'+text+'}'
 684 #RS fatal error handling
 685         if _debug:
 686             traceback.print_stack(limit=2,file=sys.stdout)
 687         if self.dead==1:
 688             return u""
 689 #RS end
 690         tx=self.escapedText(text)
 691         if self._in_code:
 692             tx=string.replace(self.escapedText(text), u' ', self.hardspace)
 693         if self.store_text:
 694             self.recordedtext+=tx
 695             return tx
 696         else:
 697             if self.document!=None:
 698                self.word_host.Selection.TypeText(tx)
 699             
 700         return tx
 701 
 702     # Inline ###########################################################
 703     def strong(self, on):
 704 #RS fatal error handling
 705         if self.dead==1:
 706             return u""
 707 #RS end
 708         tag = 'strong'
 709         if on:
 710             ret=self.open(tag)
 711             if self.document!=None:
 712                 self.word_host.Selection.Font.Bold=\
 713                     win32com.client.constants.wdToggle
 714                 self.word_host.Selection.TypeText('')
 715             return ret
 716         else:
 717             if self.document!=None:
 718                 pass
 719                 self.word_host.Selection.Font.Bold=\
 720                     win32com.client.constants.wdToggle
 721                 self.word_host.Selection.TypeText('')
 722             ret=self.close(tag)
 723             return ret
 724 
 725 
 726     def emphasis(self, on):
 727 #RS fatal error handling
 728         if self.dead==1:
 729             return u""
 730 #RS end
 731         tag = 'em'
 732         if on:
 733             ret=self.open(tag)
 734             if self.document!=None:
 735                 self.word_host.Selection.Font.Italic=\
 736                     win32com.client.constants.wdToggle
 737                 self.word_host.Selection.TypeText('')
 738             return ret
 739         else:
 740             if self.document!=None:
 741                 self.word_host.Selection.Font.Italic=\
 742                     win32com.client.constants.wdToggle
 743                 self.word_host.Selection.TypeText('')
 744             ret=self.close(tag)
 745             return ret
 746 
 747     def underline(self, on):
 748         if _debug:
 749             traceback.print_stack(limit=1,file=sys.stdout)
 750 #RS fatal error handling
 751         if self.dead==1:
 752             return u""
 753 #RS end
 754         tag = 'span'
 755         if on:
 756             ret=self.open(tag,attr={'class': 'u'})
 757             if self.document!=None:
 758                 self.word_host.Selection.Font.Underline=\
 759                     win32com.client.constants.wdUnderlineSingle
 760                 self.word_host.Selection.TypeText('')
 761             return ret
 762         else:
 763             if self.document!=None:
 764                 self.word_host.Selection.Font.Underline=\
 765                     win32com.client.constants.wdUnderlineNone
 766                 self.word_host.Selection.TypeText('')
 767             ret=self.close(tag)
 768             return ret
 769 
 770     def highlight(self, on):
 771 #RS fatal error handling
 772         if self.dead==1:
 773             return u""
 774 #RS end
 775         tag = 'strong'
 776         if on:
 777             ret=self.open(tag, attr={'class': 'highlight'})
 778             if self.document!=None:
 779                 self.word_host.Selection.Font.Bold=\
 780                     win32com.client.constants.wdToggle
 781                 self.word_host.Selection.TypeText('')
 782             return ret
 783         else:
 784             if self.document!=None:
 785                 self.word_host.Selection.Font.Bold=\
 786                     win32com.client.constants.wdToggle
 787                 self.word_host.Selection.TypeText('')
 788             ret=self.close(tag)
 789             return ret
 790 
 791     def sup(self, on):
 792 #RS fatal error handling
 793         if self.dead==1:
 794             return u""
 795 #RS end
 796         tag = 'sup'
 797         if on:
 798             ret=self.open(tag)
 799             if self.document!=None:
 800                 self.word_host.Selection.Font.Superscript=\
 801                     win32com.client.constants.wdToggle
 802                 self.word_host.Selection.TypeText('')
 803             return ret
 804         else:
 805             if self.document!=None:
 806                 self.word_host.Selection.Font.Superscript=\
 807                     win32com.client.constants.wdToggle
 808                 self.word_host.Selection.TypeText('')
 809             ret=self.close(tag)
 810             return ret
 811 
 812     def sub(self, on):
 813 #RS fatal error handling
 814         if self.dead==1:
 815             return u""
 816 #RS end
 817         tag = 'sub'
 818         if on:
 819             ret=self.open(tag)
 820             if self.document!=None:
 821                 self.word_host.Selection.Font.Subscript=\
 822                     win32com.client.constants.wdToggle
 823                 self.word_host.Selection.TypeText('')
 824             return ret
 825         else:
 826             if self.document!=None:
 827                 self.word_host.Selection.Font.Subscript=\
 828                     win32com.client.constants.wdToggle
 829                 self.word_host.Selection.TypeText('')
 830             ret=self.close(tag)
 831             return ret
 832 #RS end
 833 
 834 
 835     def code(self, on):
 836         if _debug:
 837             traceback.print_stack(limit=1,file=sys.stdout)
 838 #RS fatal error handling
 839         if self.dead==1:
 840             return u""
 841 #RS end
 842         tag = 'tt'
 843         self._in_code = on
 844         if on:
 845             ret=self.open(tag)
 846             if self.document!=None:
 847                 self.word_host.Selection.Style=self.tt_style
 848                 self.word_host.Selection.TypeText('')
 849             return ret
 850         else:
 851             if self.document!=None:
 852                 self.word_host.Selection.Style=self.defchar_style
 853                 self.word_host.Selection.TypeText('')
 854 ##                lastend=self.recordedcursor
 855 ##                currend=int(self.word_host.Selection.Range.End)
 856 ##                if lastend<currend and lastend>0:
 857 ##                    ttrange=self.document.Range(lastend,currend)
 858 ##                    ttrange.Style=self.tt_style
 859 ##                else:
 860 ##                    self.request.write("TT formatter error, ignored")
 861 ##                self.word_host.Selection.TypeText('')
 862             ret=self.close(tag)
 863             return ret
 864 
 865        
 866     def small(self, on):
 867         tag = 'small'
 868         if on:
 869             ret=self.open(tag)
 870             if self.document!=None:
 871                 pass
 872 #TODO
 873 #                self.word_host.Selection.Font.Subscript=\
 874 #                    win32com.client.constants.wdToggle
 875                 self.word_host.Selection.TypeText('')
 876             return ret
 877         else:
 878             if self.document!=None:
 879                 pass
 880 #TODO
 881 #                self.word_host.Selection.Font.Subscript=\
 882 #                    win32com.client.constants.wdToggle
 883                 self.word_host.Selection.TypeText('')
 884             ret=self.close(tag)
 885             return ret
 886                                                                                 
 887     def big(self, on):
 888         tag = 'big'
 889         if on:
 890             ret=self.open(tag)
 891             if self.document!=None:
 892                 pass
 893 #TODO
 894 #                self.word_host.Selection.Font.Subscript=\
 895 #                    win32com.client.constants.wdToggle
 896 #                self.word_host.Selection.TypeText('')
 897             return ret
 898         else:
 899             if self.document!=None:
 900                 pass
 901 #TODO
 902 #                self.word_host.Selection.Font.Subscript=\
 903 #                    win32com.client.constants.wdToggle
 904 #                self.word_host.Selection.TypeText('')
 905             ret=self.close(tag)
 906             return ret
 907 
 908     # Block elements ####################################################
 909 
 910 #framing pre:
 911 #Selection.ParagraphFormat.Borders(wdBorderLeft).LineStyle = wdLineStyleSingle    
 912 ##    Selection.MoveUp Unit:=wdLine, Count:=3, Extend:=wdExtend
 913 ##    With Selection.ParagraphFormat
 914 ##        With .Borders(wdBorderLeft)
 915 ##            .LineStyle = wdLineStyleSingle
 916 ##            .LineWidth = wdLineWidth050pt
 917 ##            .Color = wdColorAutomatic
 918 ##        End With
 919 ##        With .Borders(wdBorderRight)
 920 ##            .LineStyle = wdLineStyleSingle
 921 ##            .LineWidth = wdLineWidth050pt
 922 ##            .Color = wdColorAutomatic
 923 ##        End With
 924 ##        With .Borders(wdBorderTop)
 925 ##            .LineStyle = wdLineStyleSingle
 926 ##            .LineWidth = wdLineWidth050pt
 927 ##            .Color = wdColorAutomatic
 928 ##        End With
 929 ##        With .Borders(wdBorderBottom)
 930 ##            .LineStyle = wdLineStyleSingle
 931 ##            .LineWidth = wdLineWidth050pt
 932 ##            .Color = wdColorAutomatic
 933 ##        End With
 934 ##        .Borders(wdBorderHorizontal).LineStyle = wdLineStyleNone
 935 ##        With .Borders
 936 ##            .DistanceFromTop = 1
 937 ##            .DistanceFromLeft = 4
 938 ##            .DistanceFromBottom = 1
 939 ##            .DistanceFromRight = 4
 940 ##            .Shadow = False
 941 ##        End With
 942 ##    End With
 943 ##    With Options
 944 ##        .DefaultBorderLineStyle = wdLineStyleSingle
 945 ##        .DefaultBorderLineWidth = wdLineWidth050pt
 946 ##        .DefaultBorderColor = wdColorAutomatic
 947 ##    End With
 948     
 949 
 950     def preformatted(self, on):
 951         if _debug:
 952             traceback.print_stack(limit=1,file=sys.stdout)
 953 #RS fatal error handling
 954         if self.dead==1:
 955             return u""
 956 #RS end
 957         self.in_pre = on != 0
 958         tag = 'preformatted'
 959         if on:
 960             ret=self.open(tag,newline=1)
 961             if self.document!=None:
 962 ###                lastend=self.recordedcursor
 963 ###                currend=int(self.word_host.Selection.Range.End)
 964 ###                if lastend<currend and lastend>0:
 965 ###                    ttrange=self.document.Range(lastend,currend)
 966 ##                    ttrange.Style=self.pre_style
 967 ##                else:
 968 ##                    self.request.write("PRE formatter error, ignored")
 969                 self.word_host.Selection.TypeParagraph()
 970                 self.word_host.Selection.Style=self.pre_style
 971                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderTop).LineStyle = win32com.client.constants.wdLineStyleSingle    
 972                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderBottom).LineStyle = win32com.client.constants.wdLineStyleSingle    
 973                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderLeft).LineStyle = win32com.client.constants.wdLineStyleSingle    
 974                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderRight).LineStyle = win32com.client.constants.wdLineStyleSingle    
 975 
 976                 self.word_host.Selection.TypeParagraph()
 977             return ret
 978         else:
 979             if self.document!=None:
 980                 self.word_host.Selection.TypeParagraph()
 981                 self.word_host.Selection.Style=self.defpara_style
 982                 self.word_host.Selection.TypeParagraph()
 983                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderTop).LineStyle = win32com.client.constants.wdLineStyleNone    
 984                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderBottom).LineStyle = win32com.client.constants.wdLineStyleNone    
 985                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderLeft).LineStyle = win32com.client.constants.wdLineStyleNone    
 986                 self.word_host.Selection.ParagraphFormat.Borders(win32com.client.constants.wdBorderRight).LineStyle = win32com.client.constants.wdLineStyleNone    
 987 ##                lastend=self.recordedcursor
 988 ##                currend=int(self.word_host.Selection.Range.End)
 989 ##                if lastend<currend and lastend>0:
 990 ##                    ttrange=self.document.Range(lastend,currend)
 991 ##                    ttrange.Style=self.pre_style
 992 ##                else:
 993 ##                    self.request.write("PRE formatter error, ignored")
 994 ##                self.word_host.Selection.TypeParagraph()
 995 ##                self.word_host.Selection.Style=self.defpara_style
 996             ret=self.close(tag)
 997             return ret
 998 
 999 # special markup for syntax highlighting #############################
1000 
1001     def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
1002 #RS word: for now, just use preformatted?
1003         if on:
1004             # Open a code area
1005             self._in_code_area = 1
1006             self._in_code_line = 0
1007         else:
1008             # Close code area
1009             self._in_code_area = 0
1010             self._code_area_num += 1
1011         return self.preformatted(on)
1012 #RS end    
1013         res = []
1014         ci = self.request.makeUniqueID('CA-%s_%03d' % (code_id, self._code_area_num))
1015         if on:
1016             # Open a code area
1017             self._in_code_area = 1
1018             self._in_code_line = 0
1019             self._code_area_state = [ci, show, start, step, start]
1020 
1021             # Open the code div - using left to right always!
1022             attr = {'class': 'codearea', 'lang': 'en', 'dir': 'ltr'}
1023             res.append(self.open('div', attr=attr))
1024 
1025             # Add the script only in the first code area on the page
1026             if self._code_area_js == 0 and self._code_area_state[1] >= 0:
1027                 res.append(self._toggleLineNumbersScript)
1028                 self._code_area_js = 1
1029 
1030             # Add line number link, but only for JavaScript enabled browsers.
1031             if self._code_area_state[1] >= 0:
1032                 toggleLineNumbersLink = r'''
1033 <script type="text/javascript">
1034 document.write('<a href="#" onClick="return togglenumber(\'%s\', %d, %d);" \
1035                 class="codenumbers">Toggle line numbers<\/a>');
1036 </script>
1037 ''' % (self._code_area_state[0], self._code_area_state[2], self._code_area_state[3])
1038                 res.append(toggleLineNumbersLink)
1039 
1040             # Open pre - using left to right always!
1041             attr = {'id': self._code_area_state[0], 'lang': 'en', 'dir': 'ltr'}
1042             res.append(self.open('pre', newline=True, attr=attr))
1043         else:
1044             # Close code area
1045             res = []
1046             if self._in_code_line:
1047                 res.append(self.code_line(0))
1048             res.append(self.close('pre'))
1049             res.append(self.close('div'))
1050 
1051             # Update state
1052             self._in_code_area = 0
1053             self._code_area_num += 1
1054 
1055         return ''.join(res)
1056 
1057     def code_line(self, on):
1058 #RS word: for now, just linebreaks on on?
1059         self._in_code_line = on != 0
1060         if on:
1061             ret=self.linebreak(on)
1062         else:
1063             ret=''
1064         return ret
1065     
1066         return self.preformatted(on)
1067 #RS end    
1068 #RS end    
1069         res = ''
1070         if not on or (on and self._in_code_line):
1071             res += '</span>\n'
1072         if on:
1073             res += '<span class="line">'
1074             if self._code_area_state[1] > 0:
1075                 res += '<span class="LineNumber">%4d </span>' % (self._code_area_state[4], )
1076                 self._code_area_state[4] += self._code_area_state[3]
1077         self._in_code_line = on != 0
1078         return res
1079 
1080     def code_token(self, on, tok_type):
1081 #RS word: for now, just use code?
1082         return self.code(on)
1083 #RS end
1084         return ['<span class="%s">' % tok_type, '</span>'][not on]
1085 
1086     # Paragraphs, Lines, Rules ###########################################
1087     
1088     def linebreak(self, preformatted=1):
1089         if _debug:
1090             traceback.print_stack(limit=1,file=sys.stdout)
1091 #RS fatal error handling
1092         if self.dead==1:
1093             return u""
1094 #RS end
1095         if self._in_code_area:
1096             preformatted = 1
1097         if preformatted==1:
1098             
1099             self.word_host.Selection.TypeParagraph()
1100             return '#\n'
1101         else:    
1102             self.word_host.Selection.TypeText("#\x0B #")
1103             return '<br>\n'
1104 #        self.document.Content.InsertAfter("\x0B ")
1105    
1106 
1107     def paragraph(self, on):
1108         if _debug:
1109             traceback.print_stack(limit=1,file=sys.stdout)
1110 #RS fatal error handling
1111         if self.dead==1:
1112             return u""
1113 #RS end
1114         if self._terse:
1115             return ''
1116         FormatterBase.paragraph(self, on)
1117         if self._in_li:
1118             self._in_li = self._in_li + 1
1119         tag = 'p'
1120         if on:
1121             ret=self.open(tag)
1122             if self.document!=None:
1123                 if self._ignore_next_paragraph: #we already inserted a paragraph
1124                     self._ignore_next_paragraph=0
1125                     return u''
1126                 else:
1127                     self.word_host.Selection.TypeParagraph()
1128                     return u'<pli>'
1129             return ret
1130         else:
1131             text=self.recordedtext
1132             if self.document!=None:
1133                 if self._ignore_next_paragraph: #we already inserted a paragraph
1134                     self._ignore_next_paragraph=0
1135                     return u''
1136                 else:
1137                     self.word_host.Selection.TypeParagraph()
1138                     return u'</pli>'
1139             ret=self.close(tag)
1140             return ret
1141         
1142 
1143     def rule(self, size=None):
1144         if _debug:
1145             traceback.print_stack(limit=1,file=sys.stdout)
1146 #RS fatal error handling
1147         if self.dead==1:
1148             return u""
1149 #RS end
1150 #TODO RS draw a line?
1151         if size:
1152             # Add hr class: hr1 - hr6
1153             return self.open('hr', newline=1, attr={'class': 'hr%d' % size})
1154         return self.open('hr', newline=1)
1155 
1156     def icon(self, type):
1157 #TODO RS or just ignore (probably just wiki control icons)?        
1158         return self.request.theme.make_icon(type)
1159 
1160     def img_url(self, img):
1161         """ Generate an image href
1162 
1163         @param img: the image filename
1164         @rtype: string
1165         @return: the image href
1166         """
1167         return "%s%s\\img\\%s" % (self.cfg.url_prefix_dir, self.request.theme.name, img)
1168 
1169 
1170     def smiley(self, text):
1171         w, h, b, img = config.smileys[text.strip()]
1172         href = img
1173         if not href.startswith('/'):
1174             href = self.img_url(img)
1175         return self.image(src=href, alt=text, width=str(w), height=str(h))
1176 
1177     # Lists ##############################################################
1178 
1179 
1180     def number_list(self, on, type=None, start=None):
1181         if _debug:
1182             traceback.print_stack(limit=1,file=sys.stdout)
1183 #RS fatal error handling
1184         if self.dead==1:
1185             return u""
1186 #RS end
1187         tag = 'ol'
1188         self.request.write("<number_list>:on=%s,type=%s,start=%s" % (str(on),str(type),str(start)))
1189         if on:
1190             attr = {}
1191             if type is not None:
1192                 attr['type'] = type
1193             if start is not None:
1194                 attr['start'] = start
1195             ret=self.open(tag, newline=1, attr=attr)
1196 
1197             self.list_levels['ol']=self.list_levels['ol']+1
1198             self.list_levels['all']=self.list_levels['all']+1
1199             if self.document!=None:
1200 #                self.word_host.Selection.TypeParagraph()
1201                 self.request.write("<OL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
1202                 if self.list_levels['ol']==1: #only first 
1203                     if self.word_host.Selection.Range.ListFormat.ListType != self.ol_type:
1204 #                        self.word_host.Selection.TypeText("{bulleton}")
1205 ##                        self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(self.wdWord9ListBehavior)
1206                         if self.last_indent_type=='ul':
1207                             #need more indent
1208                             self.request.write("UL->OL 1")
1209                             self.word_host.Selection.Range.ListFormat.ListIndent()
1210                         listtemplate=self.word_host.ListGalleries(self.wdNumberGallery).ListTemplates(self.list_levels['ol'])    
1211                         self.word_host.Selection.Range.ListFormat.ApplyListTemplate(ListTemplate=listtemplate,
1212                             ContinuePreviousList=vbFalse, ApplyTo=self.wdListApplyToThisPointForward, DefaultListBehavior=self.wdWord9ListBehavior)
1213 
1214                 else:
1215                     if self.word_host.Selection.Range.ListFormat.ListType != self.ol_type:
1216 #                        self.word_host.Selection.TypeText("{bulleton}")
1217 ##                        self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(self.wdWord9ListBehavior)
1218                         listtemplate=self.word_host.ListGalleries(self.wdNumberGallery).ListTemplates(self.list_levels['ol'])    
1219                         self.word_host.Selection.Range.ListFormat.ApplyListTemplate(ListTemplate=listtemplate,
1220                             ContinuePreviousList=vbFalse, ApplyTo=self.wdListApplyToThisPointForward, DefaultListBehavior=self.wdWord9ListBehavior)
1221                         if self.last_indent_type=='ul':
1222                             #need more indent
1223                             self.request.write("UL->OL 2")
1224                             self.word_host.Selection.Range.ListFormat.ListIndent()
1225 #                    else:
1226                     self.word_host.Selection.Range.ListFormat.ListIndent()
1227                 
1228             self._ignore_next_paragraph=1
1229             self._first_li = 1
1230             self.last_indent_type='ol'
1231         else:
1232             self.list_levels['ol']=self.list_levels['ol']-1
1233             self.list_levels['all']=self.list_levels['all']-1
1234 
1235             if self.document!=None:
1236 #                self.word_host.Selection.TypeParagraph()
1237                 self.request.write("</OL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
1238                 if self.list_levels['ul']==0: 
1239                     if self.word_host.Selection.Range.ListFormat.ListType == self.ol_type:
1240 #                        self.word_host.Selection.TypeText("{bulletoff}")
1241                         self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(self.wdWord9ListBehavior)
1242                         if self.last_indent_type=='ul':
1243                             #need more outdent
1244                             self.request.write("UL->OL ??1??")
1245                             self.word_host.Selection.Range.ListFormat.ListOutdent()
1246 
1247                 else:
1248                     if self.word_host.Selection.Range.ListFormat.ListType == self.ol_type:
1249                         self.word_host.Selection.Range.ListFormat.ApplyNumberDefault(self.wdWord9ListBehavior)
1250 #                    else:
1251                     self.word_host.Selection.Range.ListFormat.ListOutdent()
1252             self._ignore_next_paragraph=1
1253             self.last_indent_type=''
1254 
1255             ret=self.close(tag)
1256             return ret
1257             
1258 
1259     def bullet_list(self, on):
1260         if _debug:
1261             traceback.print_stack(limit=1,file=sys.stdout)
1262 #RS fatal error handling
1263         if self.dead==1:
1264             return u""
1265 #RS end
1266         tag = 'ul'
1267         self.request.write("<bullet_list>:on=%s" % (str(on)))
1268         if on:
1269             ret=self.open(tag, newline=1)
1270             self.list_levels['ul']=self.list_levels['ul']+1
1271             self.list_levels['all']=self.list_levels['all']+1
1272             if self.document!=None:
1273 #                self.word_host.Selection.TypeParagraph()
1274                 self.request.write("<UL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
1275 #                self.word_host.Selection.TypeText("[%s]" % self.list_levels['all'])
1276                 if self.list_levels['ul']==1: #only first 
1277                     if self.word_host.Selection.Range.ListFormat.ListType != self.ul_type:
1278 #                        self.word_host.Selection.TypeText("{bulleton}")
1279                         self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(self.wdWord9ListBehavior)
1280                 else:
1281                     if self.word_host.Selection.Range.ListFormat.ListType != self.ul_type:
1282 #                        self.word_host.Selection.TypeText("{bulleton}")
1283                         self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(self.wdWord9ListBehavior)
1284 #                    else:
1285                     self.word_host.Selection.Range.ListFormat.ListIndent()
1286 #                    self.word_host.Selection.TypeText("{indent}")
1287             self._ignore_next_paragraph=1
1288             self.last_indent_type='ul'
1289             
1290             return ret
1291         else:
1292             self.list_levels['ul']=self.list_levels['ul']-1
1293             self.list_levels['all']=self.list_levels['all']-1
1294             if self.document!=None:
1295 #                self.word_host.Selection.TypeParagraph()
1296                 self.request.write("</UL> List type was: %s" % str(self.word_host.Selection.Range.ListFormat.ListType))
1297                 if self.list_levels['ul']==0: 
1298                     if self.word_host.Selection.Range.ListFormat.ListType == self.ul_type:
1299 #                        self.word_host.Selection.TypeText("{bulletoff}")
1300                         self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(self.wdWord9ListBehavior)
1301                 else:
1302                     if self.word_host.Selection.Range.ListFormat.ListType == self.ul_type:
1303                         self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(self.wdWord9ListBehavior)
1304 #                    else:
1305                     self.word_host.Selection.Range.ListFormat.ListOutdent()
1306 #                    self.word_host.Selection.TypeText("{outdent}")
1307 #                self.word_host.Selection.TypeText("[/%s]" % (self.list_levels['all']+1))
1308             self._ignore_next_paragraph=1
1309             self.last_indent_type=''
1310 
1311             ret=self.close(tag)
1312             return ret
1313 
1314     def listitem(self, on, **kw):
1315         if _debug:
1316             traceback.print_stack(limit=1,file=sys.stdout)
1317 #RS fatal error handling
1318         if self.dead==1:
1319             return u""
1320 #RS end
1321 ##        self._in_li = on != 0
1322         tag = 'li'
1323         self._in_li = on != 0
1324         if on:
1325             attr = {}
1326             css_class = kw.get('css_class', None)
1327             if css_class:
1328                 attr['class'] = css_class
1329             style = kw.get('style', None)
1330             if style:
1331                 attr['style'] = style
1332                 if style=="list-style-type:none":
1333                     pass
1334                     #this is indent, not bullet
1335             ret=self.open(tag, attr=attr)
1336             self._ignore_next_paragraph=1
1337             return ret
1338         else:
1339             ret=self.close(tag)
1340             return ret
1341 #RS end
1342 
1343     def definition_list(self, on):
1344         if _debug:
1345             traceback.print_stack(limit=1,file=sys.stdout)
1346 #RS fatal error handling
1347         if self.dead==1:
1348             return u""
1349 #RS end
1350         tag = 'dl'
1351         if on:
1352             ret=self.open(tag, newline=1)
1353             self.list_levels['dl']=self.list_levels['dl']+1
1354             self.list_levels['all']=self.list_levels['all']+1
1355             return ret
1356         else:
1357             self.list_levels['dl']=self.list_levels['dl']-1
1358             self.list_levels['all']=self.list_levels['all']-1
1359             ret=self.close(tag)
1360             return ret
1361 
1362     def definition_term(self, on):
1363         if _debug:
1364             traceback.print_stack(limit=1,file=sys.stdout)
1365 #RS fatal error handling
1366         if self.dead==1:
1367             return u""
1368 #RS end
1369         tag = 'dt'
1370         if on:
1371             ret=self.open(tag)
1372             return ret
1373         else:
1374             ret=self.close(tag)
1375             return ret
1376         
1377 
1378     def definition_desc(self, on):
1379         if _debug:
1380             traceback.print_stack(limit=1,file=sys.stdout)
1381 #RS fatal error handling
1382         if self.dead==1:
1383             return u""
1384 #RS end
1385         tag = 'dd'
1386         if on:
1387             ret=self.open(tag)
1388             return ret
1389         else:
1390             ret=self.close(tag)
1391             return ret
1392 
1393 
1394     def heading(self, on, depth, id = None, **kw):
1395         # remember depth of first heading, and adapt current depth accordingly
1396         if _debug:
1397             traceback.print_stack(limit=1,file=sys.stdout)
1398 #RS fatal error handling
1399         if self.dead==1:
1400             return u""
1401 #RS end
1402 
1403         self._reset_indents()
1404         if not self._base_depth:
1405             self._base_depth = depth
1406 #RS adapt base depth if included
1407             self._base_depth=long(self.request.getPragma('_base_depth',str(self._base_depth)))
1408         oridepth=depth
1409 
1410 #RS isn't this nonsense???
1411 #        depth = max(depth - (self._base_depth - 1), 1)
1412         count_depth = max(depth - (self._base_depth - 1), 1)
1413 
1414 #?        depth = max(depth + (self._base_depth - 1), self._base_depth)
1415 #RS 1.1
1416         # check numbering, possibly changing the default
1417         if self._show_section_numbers is None:
1418             self._show_section_numbers = self.cfg.show_section_numbers
1419             numbering = self.request.getPragma('section-numbers', '').lower()
1420             if numbering in ['0', 'off']:
1421                 self._show_section_numbers = 0
1422             elif numbering in ['1', 'on']:
1423                 self._show_section_numbers = 1
1424             elif numbering in ['2', '3', '4', '5', '6']:
1425                 # explicit base level for section number display
1426                 self._show_section_numbers = int(numbering)
1427 #RS stop
1428 
1429         heading_depth = depth + 1
1430         if on:
1431             # create section number
1432             number = ''
1433             if self._show_section_numbers:
1434                 # count headings on all levels
1435                 self.request._fmt_hd_counters = self.request._fmt_hd_counters[:count_depth]
1436                 while len(self.request._fmt_hd_counters) < count_depth:
1437                     self.request._fmt_hd_counters.append(0)
1438                 self.request._fmt_hd_counters[-1] = self.request._fmt_hd_counters[-1] + 1
1439                 number = '.'.join(map(str, self.request._fmt_hd_counters[self._show_section_numbers-1:]))
1440                 if number: number += ". "
1441             attr = {}
1442             if id:
1443                 attr['id'] = id
1444             # Add space before heading, easier to check source code
1445             ret='\n' +self.open('h%d' % heading_depth, attr=attr)
1446             return "%s%s" % (ret,number)
1447             
1448         else:
1449             # closing tag, with empty line after, to make source more readable
1450             title=self.recordedtext
1451             if self.document!=None:
1452                 self.word_host.Selection.TypeParagraph()
1453                 style=win32com.client.constants.wdStyleHeading1 - depth +1
1454                 self.word_host.Selection.Paragraphs.Last.Style=style
1455                 self.word_host.Selection.TypeText('%s' % (title))
1456                 self.word_host.Selection.TypeParagraph()
1457                 self.word_host.Selection.Paragraphs.Last.Style=win32com.client.constants.wdStyleNormal
1458             ret=self.close('h%d' % heading_depth) + '\n'
1459             return ret
1460 
1461 
1462 
1463     # Tables #############################################################
1464 
1465     _allowed_table_attrs = {
1466         'table': ['class', 'id', 'style'],
1467         'row': ['class', 'id', 'style'],
1468         '': ['colspan', 'rowspan', 'class', 'id', 'style'],
1469     }
1470 
1471     def _checkTableAttr(self, attrs, prefix):
1472         if _debug:
1473             traceback.print_stack(limit=1,file=sys.stdout)
1474         if not attrs: return u''
1475 
1476         result = ''
1477         for key, val in attrs.items():
1478             if prefix and key[:len(prefix)] != prefix: continue
1479             key = key[len(prefix):]
1480             if key not in self._allowed_table_attrs[prefix]: continue
1481             result = '%s %s=%s' % (result, key, val)
1482 
1483         return result
1484 
1485     def table(self, on, attrs=None):
1486         """ Create table
1487 
1488         @param on: start table
1489         @param attrs: table attributes
1490         @rtype: string
1491         @return start or end tag of a table
1492         """
1493         if _debug:
1494             traceback.print_stack(limit=1,file=sys.stdout)
1495 #RS fatal error handling
1496         if self.dead==1:
1497             return u""
1498 #RS end
1499         result = []
1500         if on:
1501             # Open div to get correct alignment with table width smaller
1502             # than 100%
1503 #            ret=self.open('div', newline=1)
1504 #            result.append(ret)
1505 
1506             # Open table
1507             if not attrs:
1508                 attrs = {}
1509             else:
1510                 attrs = self._checkTableAttr(attrs, 'table')
1511             ret= self.open('table', newline=1, attr=attrs)
1512 
1513             self.list_levels['table']=self.list_levels['table']+1
1514             self.list_levels['all']=self.list_levels['all']+1
1515             if self.document!=None:
1516                 ##self.word_host.Selection.TypeParagraph()
1517                 if self.word_host.Selection.Range.ListFormat.ListType == win32com.client.constants.wdListBullet:
1518                     self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
1519                 self.word_host.Selection.TypeParagraph()
1520                 self.document.Tables.Add(Range=self.word_host.Selection.Range,
1521                     NumRows=1, NumColumns= 1, DefaultTableBehavior=win32com.client.constants.wdWord9TableBehavior,
1522                     AutoFitBehavior= win32com.client.constants.wdAutoFitContent)
1523             self._first_tr = 1
1524             self._first_td = 1
1525             self._table_start=1
1526             return ret
1527         else:
1528             self.list_levels['table']=self.list_levels['table']-1
1529             self.list_levels['all']=self.list_levels['all']-1
1530             if self.document!=None:
1531                 self.word_host.Selection.MoveDown(Unit=win32com.client.constants.wdLine, Count=1)
1532                 self.word_host.Selection.TypeParagraph()
1533 
1534             ret=self.close('table')
1535 #            ret=self.close('div')
1536             
1537             return ret
1538 
1539     def table_row(self, on, attrs=None):
1540         if _debug:
1541             traceback.print_stack(limit=1,file=sys.stdout)
1542 #RS fatal error handling
1543         if self.dead==1:
1544             return u""
1545 #RS end
1546         tag = 'tr'
1547         if on:
1548             if not attrs:
1549                 attrs = {}
1550             else:
1551                 attrs = self._checkTableAttr(attrs, 'row')
1552             ret=self.open(tag, newline=1, attr=attrs)
1553             if self._first_tr == 0:
1554                 #first row always existing
1555                 if self.document!=None:
1556                     self.word_host.Selection.InsertRowsBelow(1)
1557                 self._first_td = 1
1558             elif self._first_td == 1:
1559 #                if self.document!=None:
1560 #                    self.word_host.Selection.TypeText('#')
1561                 self._table_start = 0
1562             return ret
1563         else:
1564             self._first_tr = 0
1565             ret=self.close(tag)
1566             return ret
1567             
1568 
1569     def table_cell(self, on, attrs=None):
1570         if _debug:
1571             traceback.print_stack(limit=1,file=sys.stdout)
1572 #RS fatal error handling
1573         if self.dead==1:
1574             return u""
1575 #RS end
1576         tag = 'tr'
1577         if on:
1578             if not attrs:
1579                 attrs = {}
1580             else:
1581                 attrs = self._checkTableAttr(attrs, 'row')
1582             ret=self.open(tag, newline=1, attr=attrs)
1583             if self.document!=None:
1584                 self.word_host.Selection.Style=self.defchar_style
1585             if self._first_tr == 1:
1586                 if self._first_td == 0:
1587                     #first cell always existing
1588                     if self.document!=None:
1589                         self.word_host.Selection.InsertColumnsRight()
1590                         self.word_host.Selection.Style=self.defchar_style
1591                         
1592             else:
1593                 #jump into cell
1594                 if self.document!=None:
1595                     self.word_host.Selection.MoveRight(Unit=win32com.client.constants.wdCell)
1596                     self.word_host.Selection.Style=self.defchar_style
1597                 self._first_td = 0
1598             return ret
1599         else:
1600             self._first_td = 0
1601             ret=self.close(tag)
1602             return ret
1603 
1604     def macro(self, macro_obj, name, args):
1605         # call the macro
1606         if name in ['TableOfContents',]:
1607             #skip call, emulate behavior
1608 ##    With ActiveDocument
1609 ##        .TablesOfContents.Add Range:=Selection.Range, RightAlignPageNumbers:= _
1610 ##            True, UseHeadingStyles:=True, UpperHeadingLevel:=1, _
1611 ##            LowerHeadingLevel:=3, IncludePageNumbers:=True, AddedStyles:="", _
1612 ##            UseHyperlinks:=True, HidePageNumbersInWeb:=True
1613 ##        .TablesOfContents(1).TabLeader = wdTabLeaderSpaces
1614 ##        .TablesOfContents.Format = wdIndexIndent
1615             try:
1616                 self.mindepth = max(int(self.request.getPragma('section-numbers', 1)),1)
1617             except (ValueError, TypeError):
1618                 self.mindepth = 1
1619 
1620             try:
1621                 self.maxdepth = max(int(args), 1)
1622             except (ValueError, TypeError):
1623                 self.maxdepth = 9
1624             sys.stdout.write("TOCrange:%s-%s" % (self.mindepth,self.maxdepth))
1625             if self.document!=None:
1626                 self.word_host.ActiveDocument.TablesOfContents.Add(\
1627                     Range=self.word_host.Selection.Range, UpperHeadingLevel=self.mindepth,\
1628                     LowerHeadingLevel=self.maxdepth,UseHyperlinks=vbTrue)
1629             return "<TOC/>"
1630         
1631         return macro_obj.execute(name, args)    
1632 
1633     def processor(self, processor_name, lines, is_parser = 0):
1634         """ processor_name MUST be valid!
1635             writes out the result instead of returning it!
1636         """
1637         if not is_parser:
1638             processor = wikiutil.importPlugin(self.request.cfg, "processor",
1639                                               processor_name, "process")
1640             processor(self.request, self, lines)
1641         else:
1642             if processor_name in ['tpython',]:
1643                 processor_name='wiki'
1644             parser = wikiutil.importPlugin(self.request.cfg, "parser",
1645                                            processor_name, "Parser")
1646             args = self._get_bang_args(lines[0])
1647             if args is not None:
1648                 lines=lines[1:]
1649             p = parser('\n'.join(lines), self.request, format_args = args)
1650             p.format(self)
1651             del p
1652         return ''
1653 
1654 
1655 
1656     def escapedText(self, text):
1657         return text
1658         return wikiutil.escape(text)
1659 
1660 
1661     def _img(self,imgurl,**kw):
1662 
1663         if _debug:
1664             traceback.print_stack(limit=1,file=sys.stdout)
1665 #RS fatal error handling
1666         if self.dead==1:
1667             return u""
1668 #RS end
1669         trusted=1
1670         scheme = string.split(imgurl, ":", 1)[0]
1671         if scheme in tuple(string.split('http|https|ftp|nntp','|')):
1672             trusted=0
1673             #retrieve remote file to temp
1674             try:
1675                 (filename, headers)=urllib.urlretrieve( imgurl)
1676                 print "remote url %s retrieved to %s" % (imgurl,filename)
1677                 filepath=filename
1678             except:
1679                 filepath=imgurl
1680             self.request.write("adding http picture, filepath=%s" % (filepath))
1681         elif scheme in tuple(string.split('file|self|wiki','|')):
1682             trusted=0
1683             filepath=imgurl
1684             self.request.write("adding file|self|wiki picture, filepath=%s" % (filepath))
1685         else:
1686             trusted=1
1687             if imgurl.startswith("./"):
1688                 imgfile=imgurl[2:]        
1689             else:
1690                 imgfile=imgurl
1691                 
1692                 
1693             filepath = os.path.abspath(os.path.join(self.cfg.url_prefix_dir, imgfile))
1694             self.request.write("\n adding .. picture, imgfile=%s, targetdir=%s, filepath=%s" % (imgfile,self.targetdir,filepath))
1695         if self.document!=None:
1696             if self.word_host.Selection.Range.ListFormat.ListType == win32com.client.constants.wdListBullet:
1697                 self.word_host.Selection.Range.ListFormat.ApplyBulletDefault(win32com.client.constants.wdWord9ListBehavior)
1698             try:
1699                 self.word_host.Selection.InlineShapes.AddPicture(FileName=filepath,\
1700                   LinkToFile=False, SaveWithDocument=True)
1701             except:
1702                 if trusted:
1703                     self.request.write("error in img, imgfile=%s, docpath=%s" % (filepath,str(self.document.Path)))
1704                     self.request.write("Active %s" % str(self.word_host.Selection.Active))
1705 #                    raise
1706                     errtext='[internal image not found:%s]' % filepath
1707 #                    self.document.Undo()
1708                     try:
1709                         self.word_host.Selection.TypeText(errtext)
1710                     except:
1711                         self.request.write("error reset did not work, may need Office 2000 SP3?")
1712                         raise "error reset did not work, may need Office 2000 SP3?"
1713                 else:
1714                     raise
1715                     self.request.write("warning in img, imgfile=%s, docpath=%s" % (filepath,str(self.document.Path)))
1716                     self.word_host.Selection.TypeText('[external image not found:%s]' % filepath)
1717                     
1718             self.word_host.Selection.TypeText(' ')
1719 #            self._save()
1720 
1721 
1722     def image(self, **kw):
1723         """ Take HTML <IMG> tag attributes in `attr`.
1724             Attribute names have to be lowercase!
1725         """
1726         if _debug:
1727             traceback.print_stack(limit=1,file=sys.stdout)
1728 #RS fatal error handling
1729         if self.dead==1:
1730             return u""
1731 #RS end
1732         attrstr = u''
1733         for attr, value in kw.items():
1734             if attr=='html_class':
1735                 attr='class'
1736             attrstr = attrstr + u' %s="%s"' % (attr, wikiutil.escape(value))
1737         imgurl=kw.get('src','')
1738         self.request.write("\n try image, imgurl=%s" % (imgurl))
1739         if imgurl!='':
1740             self._img(imgurl,**kw)
1741         result= u'<img%s/>' % attrstr
1742         return result
1743 
1744 
1745 
1746 
1747     def rawHTML(self, markup):
1748         """ This allows emitting pre-formatted HTML markup, and should be
1749             used wisely (i.e. very seldom).
1750 
1751             Using this event while generating content results in unwanted
1752             effects, like loss of markup or insertion of CDATA sections
1753             when output goes to XML formats.
1754         """
1755         return '<<'+markup+'>>'

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2005-10-24 16:41:36, 3.6 KB) [[attachment:FrontPage.pdf]]
  • [get | view] (2005-10-20 23:45:56, 124.5 KB) [[attachment:SyntaxReference.doc]]
  • [get | view] (2005-10-20 23:27:53, 19.0 KB) [[attachment:moin_export.py]]
  • [get | view] (2005-10-24 14:06:32, 3.9 KB) [[attachment:request_ors.py]]
  • [get | view] (2005-10-27 14:27:18, 81.6 KB) [[attachment:text_pdf.py]]
  • [get | view] (2005-10-20 23:29:45, 66.2 KB) [[attachment:text_word.py]]
  • [get | view] (2005-11-03 17:30:17, 53.9 KB) [[attachment:wiki_word.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.