Changes in / [20:30]

Show
Ignore:
Location:
/branches
Files:
4 added
28 removed
19 modified

Legend:

Unmodified
Added
Removed
  • /branches/greitmayr/extensions/WikiSyntax.py

    r7 r21  
    1414UrlRE           = re.compile("((?:wiki|file|https?|ftp|mailto)://[^\s<]*)") 
    1515BulletRE        = re.compile("^(\s*)(\*)\s([^\\n]*)") 
    16 NumericBulletRE = re.compile("^(\s*)(\d+)\.\s([^\\n]*)") 
     16NumericBulletRE = re.compile("^(\s*)((?:\d+\.)*)(\d+)\.\s([^\\n]*)") 
    1717IndentedContentRE = re.compile("^((?:\s{4})+)()([^\\n]*)") 
    1818 
  • /branches/greitmayr/extensions/WikidPadHooks.py

    r7 r25  
    11from os.path import join 
     2 
     3WIKIDPAD_PLUGIN = (("hooks", 1),) 
    24 
    35def startup(wikidPad): 
  • /branches/greitmayr/extensions/KeyBindings.py

    r9 r22  
    3636Eval="Ctrl-E" 
    3737InsertDate="Ctrl-Alt-D" 
     38MakeWikiWord="Ctrl-J" 
    3839 
    3940def makeBold(editor): 
     
    4849    editor.AddText('+') 
    4950    editor.GotoPos(pos) 
     51     
     52def makeWikiWord(editor): 
     53    text = editor.GetSelectedText() 
     54    text = text.replace("'", "") 
     55    text = text[0:1].upper() + text[1:] 
     56    text = "[" + text + "]" 
     57    editor.ReplaceSelection(text) 
  • /branches/greitmayr/lib/pwiki/WikiTxtCtrl.py

    r7 r21  
    534534                    match = WikiFormatting.NumericBulletRE.search(previousLine) 
    535535                    if match: 
    536                         prevNumStr = match.group(2) 
     536                        prevNumStr = match.group(3) 
    537537                        prevNum = int(prevNumStr) 
    538538                        nextNum = prevNum+1 
    539539                        adjustment = len(str(nextNum)) - len(prevNumStr) 
    540540                         
    541                         self.AddText("%s%d. " % (" " * (self.GetLineIndentation(currentLine-1) - adjustment), int(prevNum)+1)) 
     541                        self.AddText("%s%s%d. " % (" " * (self.GetLineIndentation(currentLine-1) - adjustment), match.group(2), int(prevNum)+1)) 
    542542                    else: 
    543543                        self.AddText(" " * self.GetLineIndentation(currentLine-1)) 
  • /branches/greitmayr/lib/pwiki/WikiData.py

    r18 r23  
    379379            cursor.execute(sql, params) 
    380380        else: 
    381         cursor.execute(sql) 
     381            cursor.execute(sql) 
    382382        data = cursor.fetchall() 
    383383        cursor.close() 
  • /branches/greitmayr/lib/pwiki/PersonalWikiFrame.py

    r16 r28  
    1414import WikiFormatting 
    1515from Config import * 
     16from PluginManager import * 
    1617 
    1718class PersonalWikiFrame(wxFrame): 
     
    6970        self.wikiHistory = [] 
    7071 
     72        # setup plugin manager and hooks API 
     73        self.pluginManager = PluginManager() 
     74        self.hooks = self.pluginManager.registerPluginAPI(("hooks",1), 
     75            ["startup", "newWiki", "createdWiki", "openWiki", "openedWiki",  
     76             "openWikiWord", "newWikiWord", "openedWikiWord", "savingWikiWord", 
     77             "savedWikiWord", "renamedWikiWord", "deletedWikiWord", "exit"] ) 
     78        # interface for editor functions menu plugins 
     79        self.editorFunctions = self.pluginManager.registerPluginAPI(("EditorFunctions",1),  
     80                                ["describeMenuItem", "describeToolbarItem"]) 
     81 
    7182        # load extensions 
    7283        self.loadExtensions() 
     
    7687 
    7788        # trigger hook             
    78         for plugin in self.plugins: 
    79             plugin.startup(self) 
     89        self.hooks.startup(self) 
    8090  
    8191        # if it already exists read it in 
    8292        if (exists(self.globalConfigLoc)):             
    8393            self.globalConfig.read(self.globalConfigLoc) 
    84         else: 
     94        if not self.globalConfig.has_section("main"): 
    8595            self.createDefaultGlobalConfig() 
    8696 
     
    181191        self.evalLib = self.getExtension('EvalLibrary', 'EvalLibrary.py') 
    182192        self.wikiSyntax = self.getExtension('SyntaxLibrary', 'WikiSyntax.py') 
    183         self.plugins = self.getPlugins()  
     193        dirs = [ join(self.wikiAppDir, 'user_extensions'), join(self.wikiAppDir, 'extensions') ] 
     194        self.pluginManager.loadPlugins( dirs, [ 'KeyBindings.py', 'EvalLibrary.py', 'WikiSyntax.py' ] ) 
    184195 
    185196    def getExtension(self, extensionName, fileName): 
     
    189200        extensionFile = open(extensionFileName) 
    190201        return importCode(extensionFile, extensionName)         
    191  
    192     def getPlugins(self): 
    193         import sys 
    194          
    195         # set up some data 
    196         exclusions = [ 'KeyBindings.py', 'EvalLibrary.py', 'WikiSyntax.py' ] 
    197         result = [] 
    198          
    199         # walk the user extension path first to override any plugins in the system extension 
    200         userExtensionPath = join(self.wikiAppDir, 'user_extensions') 
    201         files = os.listdir(userExtensionPath) 
    202         for name in files: 
    203             fullname = join(userExtensionPath, name) 
    204             ( moduleName, ext ) = splitext(name) 
    205             if isfile(fullname) and ext == '.py' and name not in exclusions: 
    206                 module = importCode(open(fullname), moduleName) 
    207                 result.append(module) 
    208                 exclusions.append(name)                 
    209          
    210         # then walk the system extension with the user plugins added to the exclusions already         
    211         extensionPath = join(self.wikiAppDir, 'extensions') 
    212         files = os.listdir(extensionPath) 
    213         for name in files: 
    214             fullname = join(extensionPath, name) 
    215             ( moduleName, ext ) = splitext(name) 
    216             if isfile(fullname) and ext == '.py' and name not in exclusions: 
    217                 module = importCode(open(fullname), moduleName) 
    218                 result.append(module)                 
    219                  
    220         return result    
    221202 
    222203    def createDefaultGlobalConfig(self): 
     
    478459        formattingMenu.AppendItem(menuItem) 
    479460        EVT_MENU(self, menuID, lambda evt: self.editor.AddText(self.evalLib.now())) 
     461 
     462        menuID=wxNewId() 
     463        menuItem = wxMenuItem(formattingMenu, menuID, 'Wikize Selected Word\t' + self.keyBindings.MakeWikiWord, 'Wikize Selected Word') 
     464        (id, bitmap) = self.iconLookup["pin"] 
     465        menuItem.SetBitmap(bitmap) 
     466        formattingMenu.AppendItem(menuItem) 
     467        EVT_MENU(self, menuID, lambda evt: self.keyBindings.makeWikiWord(self.editor)) 
    480468 
    481469        formattingMenu.AppendSeparator() 
     
    685673        EVT_MENU(self, menuID, lambda evt: self.showAboutDialog()) 
    686674 
     675        # get info for any plugin menu items and create them as necessary 
     676        pluginMenu = None 
     677        menuItems = self.editorFunctions.describeMenuItem(self) 
     678        if len(menuItems) > 0: 
     679            pluginMenu = wxMenu() 
     680            for function, item, tooltip in menuItems: 
     681                menuID = wxNewId() 
     682                pluginMenu.Append(menuID, item, tooltip) 
     683                EVT_MENU(self, menuID, lambda evt: function(self)) 
     684                 
    687685        self.mainmenu.Append(wikiMenu, 'W&iki') 
    688686        self.mainmenu.Append(wikiWordMenu, '&Wiki Words') 
    689687        self.mainmenu.Append(historyMenu, '&History') 
    690688        self.mainmenu.Append(formattingMenu, '&Editor') 
     689        if pluginMenu: 
     690            self.mainmenu.Append(pluginMenu, "Pl&ugins") 
    691691        self.mainmenu.Append(helpMenu, 'He&lp') 
    692692 
     
    791791        tb.AddSimpleTool(tbID, icon, "Zoom Out", "Zoom Out") 
    792792        EVT_TOOL(self, tbID, lambda evt: self.editor.CmdKeyExecute(wxSTC_CMD_ZOOMOUT)) 
     793 
     794        (index, icon) = self.iconLookup["pin"] 
     795        tbID = wxNewId() 
     796        tb.AddSimpleTool(tbID, icon, "Wikize Selected Word", "Wikize Selected Word") 
     797        EVT_TOOL(self, tbID, lambda evt: self.keyBindings.makeWikiWord(self.editor)) 
     798 
     799        # get info for any toolbar items and create them as necessary 
     800        toolbarItems = self.editorFunctions.describeToolbarItem(self)     
     801        for function, label, icon, tooltip in toolbarItems: 
     802            tbID = wxNewId() 
     803            tb.AddLabelTool( tbID, label, icon, wxNullBitmap, 0, tooltip) 
     804            EVT_TOOL(self, tbID, lambda evt: function(self)) 
    793805 
    794806        tb.Realize() 
     
    883895        "creates a new wiki" 
    884896 
    885         for plugin in self.plugins: 
    886             plugin.newWiki(self, wikiName, wikiDir) 
     897        self.hooks.newWiki(self, wikiName, wikiDir) 
    887898 
    888899        wikiName = string.replace(wikiName, " ", "") 
     
    963974 
    964975                # trigger hook 
    965                 for plugin in self.plugins: 
    966                     plugin.createdWiki(self, wikiName, wikiDir) 
     976                self.hooks.createdWiki(self, wikiName, wikiDir) 
    967977 
    968978                # reopen the root 
     
    973983        "opens up a wiki" 
    974984 
    975         for plugin in self.plugins: 
    976             plugin.openWiki(self, wikiConfigFile) 
     985        # trigger hooks 
     986        self.hooks.openWiki(self, wikiConfigFile) 
    977987 
    978988        # Save the state of the currently open wiki, if there was one open 
     
    11081118 
    11091119        # trigger hook 
    1110         for plugin in self.plugins: 
    1111             plugin.openedWiki(self, self.wikiName, wikiConfigFile) 
     1120        self.hooks.openedWiki(self, self.wikiName, wikiConfigFile) 
    11121121  
    11131122        # return that the wiki was opened successfully 
     
    11411150 
    11421151    def openWikiPage(self, wikiWord, addToHistory=True, forceTreeSyncFromRoot=False): 
    1143         wikiWord = WikiFormatting.convertForWX(wikiWord) 
    1144  
    11451152        self.statusBar.SetStatusText("Opening wiki word '%s'" % wikiWord, 0) 
    11461153 
     
    11661173 
    11671174        # trigger hook 
    1168         for plugin in self.plugins: 
    1169             plugin.openWikiWord(self, wikiWord) 
     1175        self.hooks.openWikiWord(self, wikiWord) 
    11701176 
    11711177        # check if this is an alias 
     
    11831189        except WikiWordNotFoundException, e: 
    11841190            self.currentWikiPage = self.wikiData.createPage(wikiWord) 
    1185             for plugin in self.plugins: 
    1186                 plugin.newWikiWord(self, wikiWord) 
     1191            # trigger hooks 
     1192            self.hooks.newWikiWord(self, wikiWord) 
    11871193 
    11881194        # set the editor text 
     
    12461252 
    12471253        # trigger hook 
    1248         for plugin in self.plugins: 
    1249             plugin.openedWikiWord(self, wikiWord) 
     1254        self.hooks.openedWikiWord(self, wikiWord) 
    12501255 
    12511256 
     
    13881393    def saveCurrentWikiPage(self): 
    13891394        self.statusBar.SetStatusText("Saving WikiPage", 0) 
    1390         for plugin in self.plugins: 
    1391             plugin.savingWikiWord(self, self.currentWikiWord) 
     1395        # trigger hooks 
     1396        self.hooks.savingWikiWord(self, self.currentWikiWord) 
    13921397 
    13931398        error = False 
     
    14091414            self.statusBar.SetStatusText("", 0) 
    14101415            self.editor.SetSavePoint() 
    1411             for plugin in self.plugins: 
    1412                 plugin.savedWikiWord(self, self.currentWikiWord) 
     1416            # trigger hooks 
     1417            self.hooks.savedWikiWord(self, self.currentWikiWord) 
    14131418 
    14141419            # if saving the root open it in the tree 
     
    15501555                    self.openWiki(renamedConfigFile) 
    15511556 
    1552                 for plugin in self.plugins: 
    1553                     plugin.renamedWikiWord(self, wikiWord, toWikiWord)                 
     1557                # trigger hooks 
     1558                self.hooks.renamedWikiWord(self, wikiWord, toWikiWord)                 
    15541559                self.tree.collapse() 
    15551560                self.openWikiPage(toWikiWord, forceTreeSyncFromRoot=True) 
     
    16011606            try: 
    16021607                self.wikiData.deleteWord(wikiWord) 
    1603                 for plugin in self.plugins: 
    1604                     plugin.deletedWikiWord(self, wikiWord) 
     1608                # trigger hooks 
     1609                self.hooks.deletedWikiWord(self, wikiWord) 
    16051610                if wikiWord == self.currentWikiWord: 
    16061611                    self.tree.collapse() 
     
    18491854 
    18501855        # trigger hook 
    1851         for plugin in self.plugins: 
    1852             plugin.exit(self) 
     1856        self.hooks.exit(self) 
    18531857 
    18541858        wxTheClipboard.Flush() 
  • /branches/mbutscher/work/extensions/WikiSyntax.py

    r19 r26  
    2525 
    2626# The following 3 are not in WikiFormatting.FormatExpressions 
    27 BulletRE        = re.compile(u"^(\s*)(\*)\s([^\\n]*)") 
    28 NumericBulletRE = re.compile(u"^(\s*)(\d+)\.\s([^\\n]*)") 
    29 IndentedContentRE = re.compile(u"^((?:\s{4})+)()([^\\n]*)") 
     27BulletRE        = re.compile(ur"^(\s*)(\*)\s([^\n]*)", 
     28        re.DOTALL | re.LOCALE | re.MULTILINE) 
     29NumericBulletRE = re.compile(ur"^(\s*)((?:\d+\.)*)(\d+)\.\s([^\n]*)", 
     30        re.DOTALL | re.LOCALE | re.MULTILINE) 
     31IndentedContentRE = re.compile(ur"^((?:\s{4})+)()([^\n]*)", 
     32        re.DOTALL | re.LOCALE | re.MULTILINE) 
    3033 
    3134# WikiWords 
  • /branches/mbutscher/work/extensions/WikidPadHooks.py

    r7 r27  
    11from os.path import join 
     2 
     3WIKIDPAD_PLUGIN = (("hooks", 1),) 
    24 
    35def startup(wikidPad): 
  • /branches/mbutscher/work/extensions/KeyBindings.py

    r19 r26  
    3838Eval="Ctrl-E" 
    3939InsertDate="Ctrl-Alt-D" 
     40MakeWikiWord="Ctrl-J" 
    4041 
    4142def makeBold(editor): 
     
    5051    editor.AddText(u'+') 
    5152    editor.GotoPos(bytePos) 
     53 
     54def makeWikiWord(editor): 
     55    text = editor.GetSelectedText() 
     56    text = text.replace(u"'", u"") 
     57    text = text[0:1].upper() + text[1:] 
     58    text = u"[" + text + u"]" 
     59    editor.ReplaceSelection(text) 
     60 
  • /branches/mbutscher/work/license.txt

    r7 r26  
    1 Copyright (c) 2005, Jason Horman 
     1Copyright (c) 2005, Jason Horman, Michael Butscher, Gerhard Reitmayr 
    22All rights reserved. 
    33 
    4 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 
    54 
    6     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
    7     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 
    8     * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
     5Redistribution and use in source and binary forms, with or without modification, 
     6are permitted provided that the following conditions are met: 
    97 
    10 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     8    * Redistributions of source code must retain the above copyright notice, 
     9      this list of conditions and the following disclaimer. 
     10    * Redistributions in binary form must reproduce the above copyright notice, 
     11      this list of conditions and the following disclaimer in the documentation 
     12      and/or other materials provided with the distribution. 
     13    * Neither the name of the <ORGANIZATION> nor the names of its contributors 
     14      may be used to endorse or promote products derived from this software 
     15      without specific prior written permission. 
     16 
     17 
     18THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
     19AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
     20IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
     21ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
     22LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
     23CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
     24SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
     25INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
     26CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
     27ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
     28POSSIBILITY OF SUCH DAMAGE. 
  • /branches/mbutscher/work/lib/pwiki/StringOps.py

    r19 r26  
    200200 
    201201def applyBinCompact(a, bops): 
     202    """ 
     203    Apply binary diff operations bops to a to create b 
     204    """ 
    202205    return applyCompact(a, binCompactToCompact(bops)) 
    203206 
     
    205208def getBinCompactForDiff(a, b): 
    206209    """ 
    207     Return the binary compact codes to change string a to b 
     210    Return the binary compact codes to change string a to b. 
     211    For strings a and b (NOT unicode) it is true that 
     212        applyBinCompact(a, getBinCompactForDiff(a, b)) == b 
    208213    """ 
    209214 
  • /branches/mbutscher/work/lib/pwiki/WikiTxtCtrl.py

    r19 r26  
    330330        # print "buildStyling start", self.wikiWordsEnabled 
    331331        if self.wikiWordsEnabled: 
    332             combre = WikiFormatting.CombinedWithCamelCaseRE 
     332            combre = WikiFormatting.CombinedSyntaxHighlightWithCamelCaseRE 
    333333        else: 
    334             combre = WikiFormatting.CombinedWithoutCamelCaseRE 
     334            combre = WikiFormatting.CombinedSyntaxHighlightWithoutCamelCaseRE 
    335335 
    336336        charstylepos = 0  # styling position in characters in text 
     
    605605 
    606606 
    607     # TODO UNICODE 
    608          
    609607    def rewrapText(self): 
    610608        curPos = self.GetCurrentPos() 
     
    780778                    match = WikiFormatting.NumericBulletRE.search(previousLine) 
    781779                    if match: 
    782                         prevNumStr = match.group(2) 
     780                        prevNumStr = match.group(3) 
    783781                        prevNum = int(prevNumStr) 
    784782                        nextNum = prevNum+1 
    785783                        adjustment = len(str(nextNum)) - len(prevNumStr) 
    786784 
    787                         self.AddText(u"%s%d. " % (u" " * (self.GetLineIndentation(currentLine-1) - adjustment), int(prevNum)+1)) 
     785                        self.AddText(u"%s%s%d. " % (u" " * (self.GetLineIndentation(currentLine-1) - adjustment), match.group(2), int(prevNum)+1)) 
    788786                    else: 
    789787                        self.AddText(u" " * self.GetLineIndentation(currentLine-1)) 
  • /branches/mbutscher/work/lib/pwiki/Exporters.py

    r19 r29  
     1from Enum import Enumeration 
     2import WikiFormatting 
    13import re 
    24import os 
    35from os.path import join, exists 
    4 import sys, traceback 
     6import sys 
    57import shutil 
    6 # from xml.sax.saxutils import escape 
     8## from xml.sax.saxutils import escape 
    79from time import localtime 
    810 
    9 from Enum import Enumeration 
    10 from StringOps import mbcsWriter, utf8Writer, mbcsEnc, strToBool, BOM_UTF8 
    11 import WikiFormatting 
    12 from WikiExceptions import * 
    13  
    14  
    15 ExportTypes = Enumeration("ExportTypes", ["WikiToSingleHtmlPage", "WikiToSetOfHtmlPages", "WikiWordToHtmlPage", 
    16                                           "WikiSubTreeToSingleHtmlPage", "WikiSubTreeToSetOfHtmlPages", 
    17                                           "WikiToXml"], 1) 
     11import WikiData 
     12import StringOps 
     13from StringOps import mbcsWriter, utf8Writer, utf8Enc, mbcsEnc, strToBool 
     14 
     15import wxPython.xrc as xrc 
     16 
     17from wxHelper import XrcControls 
     18 
    1819 
    1920 
     
    3132 
    3233 
    33 class HtmlExporter: 
    34     def __init__(self, pWiki): 
     34# ExportTypes = Enumeration("ExportTypes", ["WikiToSingleHtmlPage", "WikiToSetOfHtmlPages", "WikiWordToHtmlPage", 
     35#                                           "WikiSubTreeToSingleHtmlPage", "WikiSubTreeToSetOfHtmlPages", 
     36#                                           "WikiToXml"], 1) 
     37 
     38class HtmlXmlExporter: 
     39    def __init__(self): 
     40        self.pWiki = None 
     41        self.wikiData = None 
     42        self.wordList = None 
     43        self.exportDest = None 
     44 
     45 
     46    def getExportTypes(self, guiparent): 
     47        """ 
     48        Return sequence of tuples with the description of export types provided 
     49        by this object. A tuple has the form (<exp. type>, 
     50            <human readbale desctiption>, <panel for add. options or None>) 
     51        If panels for additional options must be created, they should use 
     52        guiparent as parent 
     53        """ 
     54        return ( 
     55            (u"html_single", u'Single HTML page', None), 
     56            (u"html_multi", u'Set of HTML pages', None), 
     57            (u"xml", u'XML file', None) 
     58            ) 
     59 
     60 
     61    def getAddOptVersion(self): 
     62        """ 
     63        Returns the version of the additional options information returned 
     64        by getAddOpt(). If the return value is -1, the version info can't 
     65        be stored between application sessions. 
     66         
     67        Otherwise, the addopt information can be stored between sessions 
     68        and can later handled back to the export method of the object 
     69        without previously showing the export dialog. 
     70        """ 
     71        return 0 
     72 
     73 
     74    def getAddOpt(self, addoptpanel): 
     75        """ 
     76        Reads additional options from panel addoptpanel. 
     77        If getAddOptVersion() > -1, the return value must be a sequence 
     78        of simple string and/or numeric objects. Otherwise, any object 
     79        can be returned (normally the addoptpanel itself) 
     80        """ 
     81        return () 
     82 
     83             
     84    def export(self, pWiki, wikiData, wordList, exportType, exportDest, 
     85            addopt): 
     86        """ 
     87        Run export operation. 
     88         
     89        pWiki -- PersonalWikiFrame object 
     90        wikiData -- WikiData object 
     91        wordList -- Sequence of wiki words to export 
     92        exportType -- string tag to identify how to export 
     93        exportDest -- Path to destination directory or file to export to 
     94        addopt -- additional options returned by getAddOpt() 
     95        """ 
     96         
    3597        self.pWiki = pWiki 
    36         self.wikiData = self.pWiki.wikiData 
    37  
    38     def export(self, type, dir): 
    39         if type == ExportTypes.WikiToSingleHtmlPage: 
    40             self.exportWikiToSingleHtmlPage(dir) 
    41         elif type == ExportTypes.WikiToSetOfHtmlPages: 
    42             self.exportWikiToSetOfHtmlPages(dir) 
    43         elif type == ExportTypes.WikiWordToHtmlPage: 
    44             self.exportWordToHtmlPage(dir) 
    45         elif type == ExportTypes.WikiSubTreeToSingleHtmlPage: 
    46             self.exportSubTreeToSingleHtmlPage(dir) 
    47         elif type == ExportTypes.WikiSubTreeToSetOfHtmlPages: 
    48             self.exportSubTreeToSetOfHtmlPages(dir) 
    49         elif type == ExportTypes.WikiToXml: 
    50             self.exportWikiToXml(dir) 
    51  
    52     def exportWikiToSingleHtmlPage(self, dir): 
    53         outputFile = mbcsEnc(join(dir, u"%s.html" % self.pWiki.wikiName))[0] 
     98        self.wikiData = wikiData # self.pWiki.wikiData 
     99        self.wordList = wordList 
     100        self.exportDest = exportDest 
     101        if exportType == u"html_single": 
     102            startfile = self.exportHtmlSingleFile() 
     103        elif exportType == u"html_multi": 
     104            startfile = self.exportHtmlMultipleFiles() 
     105        elif exportType == u"xml": 
     106            startfile = self.exportXml() 
     107             
     108        if self.pWiki.configuration.getboolean( 
     109                "main", "start_browser_after_export") and startfile: 
     110            os.startfile(startfile) 
     111 
     112 
     113    def exportHtmlSingleFile(self): 
     114        if len(self.wordList) == 1: 
     115            return self.exportHtmlMultipleFiles() 
     116 
     117        outputFile = mbcsEnc(join(self.exportDest, u"%s.html" % self.pWiki.wikiName))[0] 
    54118        if exists(outputFile): 
    55119            os.unlink(outputFile) 
     
    59123        fp.write(self.getFileHeader(self.pWiki.wikiName)) 
    60124         
    61         words = self.wikiData.getAllDefinedPageNames() 
    62         for word in words: 
     125        for word in self.wordList: 
    63126            wikiPage = self.wikiData.getPage(word, toload=["parents", "children", "props"]) 
    64127            if not self.shouldExport(word, wikiPage): 
     
    79142                     
    80143                formattedContent = self.formatContent(word, content, links) 
    81                 fp.write((u'<span class="wiki-name-ref">[<a name="%s">%s</a>]'+ 
    82                         u'</span><br><br><span class="parent-nodes">'+ 
    83                         u'parent nodes: %s</span><br>%s%s<hr size="1"/>') % 
    84                         (word, word, self.getParentLinks(wikiPage, False), formattedContent, '<br />\n'*10)) 
     144                fp.write((u'<span class="wiki-name-ref">'+ 
     145                        u'[<a name="%s">%s</a>]</span><br><br>'+ 
     146                        u'<span class="parent-nodes">parent nodes: %s</span>'+ 
     147                        u'<br>%s%s<hr size="1"/>') % 
     148                        (word, word, self.getParentLinks(wikiPage, False), 
     149                        formattedContent, u'<br />\n'*10)) 
    85150            except Exception, e: 
    86                 traceback.print_exc() 
    87151                pass 
    88152 
     
    90154        fp.reset()         
    91155        realfp.close()         
    92         self.copyCssFile(dir) 
    93         if self.pWiki.configuration.getboolean("main", "start_browser_after_export"): 
    94             os.startfile(outputFile) 
    95  
    96          
    97     def exportWikiToSetOfHtmlPages(self, dir): 
    98         words = self.wikiData.getAllDefinedPageNames() 
    99         for word in words: 
     156        self.copyCssFile(self.exportDest) 
     157        return outputFile 
     158 
     159 
     160    def exportHtmlMultipleFiles(self): 
     161        for word in self.wordList: 
    100162            wikiPage = self.wikiData.getPage(word, toload=["parents", "children", "props"]) 
    101163            if not self.shouldExport(word, wikiPage): 
     
    113175                    links[relation] = u"%s.html" % relation 
    114176                                 
    115             self.exportWordToHtmlPage(dir, word, links, False) 
    116         self.copyCssFile(dir) 
    117         rootFile = mbcsEnc(join(dir, u"%s.html" % self.pWiki.wikiName))[0] 
    118         if self.pWiki.configuration.getboolean("main", "start_browser_after_export"): 
    119             os.startfile(rootFile) 
    120  
    121  
    122     def exportWordToHtmlPage(self, dir, word=None, links=None, startFile=True, onlyInclude=None): 
    123         if not word: 
    124             word = self.pWiki.currentWikiWord 
    125  
    126         outputFile = mbcsEnc(join(dir, u"%s.html" % word))[0] 
    127         try: 
    128             wikiPage = self.wikiData.getPage(word, toload=["parents"]) 
    129             content = wikiPage.getContent() 
    130             formattedContent = self.formatContent(word, content, links) 
    131  
    132             if exists(outputFile): 
    133                 os.unlink(outputFile) 
    134  
    135             realfp = open(outputFile, "w") 
    136             fp = mbcsWriter(realfp, "replace") 
    137             fp.write(self.getFileHeader(word)) 
    138  
    139             # if startFile is set then this is the only page being exported so 
    140             # do not include the parent header. 
    141             if not startFile: 
    142                 fp.write(u'<span class="parent-nodes">parent nodes: %s</span>' % 
    143                         self.getParentLinks(wikiPage, True, onlyInclude)) 
    144                  
    145             fp.write(formattedContent) 
    146             fp.write(self.getFileFooter()) 
    147             fp.reset()         
    148             realfp.close()         
    149         except Exception, e: 
    150             traceback.print_exc() 
    151             pass 
    152          
    153         self.copyCssFile(dir) 
    154         if startFile and self.pWiki.configuration.getboolean( 
    155                 "main", "start_browser_after_export"): 
    156             os.startfile(outputFile) 
    157  
    158  
    159     def exportSubTreeToSingleHtmlPage(self, dir, rootWord=None): 
    160         if not rootWord: 
    161             rootWord = self.pWiki.currentWikiWord 
    162  
    163         outputFile = mbcsEnc(join(dir, u"%s.html" % rootWord))[0] 
     177            self.exportWordToHtmlPage(self.exportDest, word, links, False) 
     178        self.copyCssFile(self.exportDest) 
     179        rootFile = mbcsEnc(join(self.exportDest, u"%s.html" % self.wordList[0]))[0]     #self.pWiki.wikiName))[0] 
     180        return rootFile 
     181             
     182             
     183    def exportXml(self): 
     184        outputFile = mbcsEnc(join(self.exportDest, u"%s.xml" % self.pWiki.wikiName))[0] 
    164185 
    165186        if exists(outputFile): 
     
    167188 
    168189        realfp = open(outputFile, "w") 
    169         fp = mbcsWriter(realfp, "replace") 
    170         fp.write(self.getFileHeader(rootWord)) 
    171  
    172         words = self.wikiData.getAllSubWords(rootWord, True) 
    173         for word in words: 
    174             wikiPage = self.wikiData.getPage(word, toload=["parents", "children", "props"]) 
    175             if not self.shouldExport(word, wikiPage): 
    176                 continue 
    177  
    178             try: 
    179                 content = wikiPage.getContent() 
    180                 links = {} 
    181                 for relation in wikiPage.childRelations: 
    182                     if not self.shouldExport(relation): 
    183                         continue 
    184  
    185                     # get aliases too 
    186                     wordForAlias = self.wikiData.getAliasesWikiWord(relation) 
    187                     if wordForAlias: 
    188                         links[relation] = u"#%s" % wordForAlias 
    189                     else: 
    190                         links[relation] = u"#%s" % relation 
    191                      
    192                 formattedContent = self.formatContent(word, content, links) 
    193                 fp.write((u'<span class="wiki-name-ref">[<a name="%s">%s</a>]'+ 
    194                         u'</span><br><br><span class="parent-nodes">'+ 
    195                         u'parent nodes: %s</span><br>%s%s<hr size="1"/>') % 
    196                         (word, word, self.getParentLinks(wikiPage, False, words), 
    197                         formattedContent, u'<br />\n'*10)) 
    198             except Exception, e: 
    199                 pass 
    200  
    201         fp.write(self.getFileFooter()) 
    202         fp.reset()         
    203         realfp.close()         
    204         self.copyCssFile(dir) 
    205         if self.pWiki.configuration.getboolean("main", "start_browser_after_export"): 
    206             os.startfile(outputFile) 
    207  
    208  
    209     def exportSubTreeToSetOfHtmlPages(self, dir, rootWord=None): 
    210         if not rootWord: 
    211             rootWord = self.pWiki.currentWikiWord 
    212  
    213         words = self.wikiData.getAllSubWords(rootWord, True) 
    214         for word in words: 
    215             wikiPage = self.wikiData.getPage(word, toload=["parents", "children", "props"]) 
    216             if not self.shouldExport(word, wikiPage): 
    217                 continue 
    218  
    219             links = {} 
    220             for relation in wikiPage.childRelations: 
    221                 if not self.shouldExport(relation): 
    222                     continue 
    223  
    224                 # get aliases too 
    225                 wordForAlias = self.wikiData.getAliasesWikiWord(relation) 
    226                 if wordForAlias: 
    227                     links[relation] = u"%s.html" % wordForAlias 
    228                 else: 
    229                     links[relation] = u"%s.html" % relation 
    230                                  
    231             self.exportWordToHtmlPage(dir, word, links, False, words) 
    232         self.copyCssFile(dir) 
    233         rootFile = mbcsEnc(join(dir, u"%s.html" % rootWord))[0] 
    234         if self.pWiki.configuration.getboolean("main", "start_browser_after_export"): 
    235             os.startfile(rootFile) 
    236  
    237  
    238     def exportWikiToXml(self, dir): 
    239         outputFile = mbcsEnc(join(dir, u"%s.xml" % self.pWiki.wikiName))[0] 
    240  
    241         if exists(outputFile): 
    242             os.unlink(outputFile) 
    243  
    244         realfp = open(outputFile, "w") 
    245         realfp.write(BOM_UTF8) 
    246190        fp = utf8Writer(realfp, "replace") 
    247         fp.write(u'<?xml version="1.0" encoding="utf-8" ?>') 
    248  
    249  
     191 
     192        fp.write(u'<?xml version="1.0" encoding="utf-8" ?>')  # TODO Encoding 
    250193        fp.write(u'<wiki name="%s">' % self.pWiki.wikiName) 
    251194         
    252         words = self.wikiData.getAllDefinedPageNames() 
    253         for word in words: 
     195        for word in self.wordList: 
    254196            wikiPage = self.wikiData.getPage(word, toload=["info", "parents", "children", "props"]) 
    255197            if not self.shouldExport(word, wikiPage): 
    256198                continue 
    257  
     199                 
     200            # Why localtime? 
    258201            created = localtime(float(wikiPage.created)) 
    259202            modified = localtime(float(wikiPage.modified)) 
     
    286229        fp.write(u"</wiki>") 
    287230        fp.reset()         
    288         realfp.close()         
    289         if self.pWiki.configuration.getboolean("main", "start_browser_after_export"): 
    290             os.startfile(outputFile) 
    291  
    292  
     231        realfp.close() 
     232 
     233        return outputFile 
     234         
     235             
     236             
    293237    def getFileHeader(self, title): 
    294238        return u"""<html> 
     
    305249</html> 
    306250""" 
    307  
    308     def getParentLinks(self, wikiPage, asHref=True, wordsToInclude=None): 
    309         parents = u"" 
    310         wikiPage.parentRelations.sort() 
    311         for relation in wikiPage.parentRelations: 
    312             if wordsToInclude and relation not in wordsToInclude: 
    313                 continue 
    314              
    315             if parents != u"": 
    316                 parents = parents + u" | " 
    317  
    318             if asHref: 
    319                 parents = parents + u'<span class="parent-node"><a href="%s.html">%s</a></span>' % (relation, relation) 
    320             else: 
    321                 parents = parents + u'<span class="parent-node"><a href="#%s">%s</a></span>' % (relation, relation) 
    322  
    323         return parents 
    324      
    325      
    326     def formatContent(self, word, content, links=None, asXml=False): 
    327         # change the <<>> blocks into [[]] blocks so they aren't escaped 
    328         content = WikiFormatting.SuppressHighlightingRE.sub('[[\\1]]', content) 
    329         content = escape(content) 
    330         contentBeforeProcessing = content 
    331  
    332         content = WikiFormatting.ItalicRE.sub(u'<i>\\1</i>', content) 
    333         content = WikiFormatting.Heading3RE.sub(u'<h3>\\1</h3>', content) 
    334         content = WikiFormatting.Heading2RE.sub(u'<h2>\\1</h2>', content) 
    335         content = WikiFormatting.Heading1RE.sub(u'<h1>\\1</h1>', content) 
    336  
    337         if asXml: 
    338             content = WikiFormatting.ToDoREWithContent.sub(u'<todo>\\1</todo>', content) 
    339         else: 
    340             content = WikiFormatting.ToDoREWithContent.sub( 
    341                     u'<span class="todo">\\1</span><br />', content) 
    342              
    343         content = WikiFormatting.ScriptRE.sub('', content) 
    344  
    345         if asXml:         
    346             content = WikiFormatting.PropertyRE.sub( 
    347                     u'<property name="\\1" value="\\2"/>', content) 
    348         else: 
    349             content = WikiFormatting.PropertyRE.sub( 
    350                     u'<span class="property">[\\1: \\2]</span>', content) 
    351  
    352         if not asXml:     
    353             content = WikiFormatting.HorizLineRE.sub(u'<hr size="1"/>', content) 
    354  
    355         # add the ul/ol/li tags for bullets 
    356         content = self.createBullets(content, asXml) 
    357  
    358         # add the blockquote tags for indents 
    359         content = self.createIndents(content, asXml) 
    360  
    361         # do bold last to make sure it doesn't mess with bullets 
    362         content = WikiFormatting.BoldRE.sub(u'<b>\\1</b>', content) 
    363  
    364         # link the wiki words 
    365         if links: 
    366             content = self.linkWikiWords(content, links, asXml) 
    367  
    368         # replace URL's last 
    369         if asXml: 
    370             content = WikiFormatting.UrlRE.sub(u'<link type="href">\\1</link>', content) 
    371         else: 
    372             def replaceLink(match): 
    373                 lowerLink = match.group(1).lower() 
    374                 if lowerLink.endswith(u".jpg") or lowerLink.endswith(u".gif") or\ 
    375                         lowerLink.endswith(u".png"): 
    376                     return u'<img src="%s" border="0">' % match.group(1) 
    377                 else: 
    378                     return u'<a href="%s">%s</a>' % (match.group(1), match.group(1)) 
    379             content = WikiFormatting.UrlRE.sub(replaceLink, content) 
    380  
    381         # add <pre> tags for suppressed regions 
    382         SuppressHighlightingRE = re.compile(u"\[\[(.*?)\]\]", re.DOTALL) 
    383  
    384         # tracks which [] block we are on 
    385         matchIndex = MatchIndex() 
    386         def suppress(match): 
    387             # now search the pre-processed text for the same match 
    388             bpMatchNumber = 0 
    389             bpMatch = SuppressHighlightingRE.search(contentBeforeProcessing) 
    390             while bpMatch: 
    391                 if bpMatchNumber == matchIndex.get(): 
    392                     break 
    393                 bpMatch = SuppressHighlightingRE.search(contentBeforeProcessing, bpMatch.end()) 
    394                 bpMatchNumber = bpMatchNumber + 1 
    395  
    396             if (bpMatch): 
    397                 matchContent = bpMatch.group(1) 
    398                 htmlRe = re.compile(u"<.+?>") 
    399                 matchContent = htmlRe.sub('', matchContent) 
    400                 matchIndex.increment() 
    401                 return u'<pre>%s</pre>' % matchContent 
    402             else: 
    403                 return match.group(1) 
    404          
    405         content = SuppressHighlightingRE.sub(suppress, content) 
    406          
    407         return content 
    408      
    409  
     251             
     252    # TODO Handle this correctly: 
     253    """ 
     254    * Bullet 
     255    * Bullet 
     256 
     257    1. Number 
     258    2. Number 
     259    """ 
    410260    def createBullets(self, content, asXml=False): 
    411261        lastBulletDepth = 0 
     
    420270                 
    421271            if match: 
    422                 if match.group(2) == '*': 
     272                if match.group(2) == u'*': 
    423273                    lastUolTag = u"ul" 
    424274                else: 
     
    466316                    if len(line.strip()) == 0: 
    467317                        newContent.append(u"<p />\n") 
    468                     elif len(line) < 50 and line.find("<h") == -1: 
     318                    elif len(line) < 50 and line.find(u"<h") == -1: 
    469319                        newContent.append(u"%s<br />\n" % line) 
    470320                    else: 
     
    530380                    if len(line.strip()) == 0: 
    531381                        newContent.append(u"<p />\n") 
    532                     elif len(line) < 50 and line.find("<h") == -1: 
    533                         newContent.append(u"%s<br />\n" % line) 
     382                    ## elif len(line) < 50 and line.find("<h") == -1:   # TODO: ??? 
     383                    ##    newContent.append("%s<br />\n" % line) 
    534384                    else: 
    535385                        newContent.append(u"%s\n" % line) 
     
    555405        return len(replaceRe.sub(u" ", str)); 
    556406 
     407    def getParentLinks(self, wikiPage, asHref=True, wordsToInclude=None): 
     408        parents = u"" 
     409        wikiPage.parentRelations.sort() 
     410        for relation in wikiPage.parentRelations: 
     411            if wordsToInclude and relation not in wordsToInclude: 
     412                continue 
     413             
     414            if parents != u"": 
     415                parents = parents + u" | " 
     416 
     417            if asHref: 
     418                parents = parents + u'<span class="parent-node"><a href="%s.html">%s</a></span>' % (relation, relation) 
     419            else: 
     420                parents = parents + u'<span class="parent-node"><a href="#%s">%s</a></span>' % (relation, relation) 
     421 
     422        return parents 
    557423 
    558424    def linkWikiWords(self, content, links, asXml=False): 
     
    582448 
    583449    def copyCssFile(self, dir): 
    584         if not exists(join(dir, 'wikistyle.css')): 
    585             cssFile = join(self.pWiki.wikiAppDir, 'export', 'wikistyle.css') 
     450        if not exists(mbcsEnc(join(dir, 'wikistyle.css'))[0]): 
     451            cssFile = mbcsEnc(join(self.pWiki.wikiAppDir, 'export', 'wikistyle.css'))[0] 
    586452            if exists(cssFile): 
    587453                shutil.copy(cssFile, dir) 
     
    591457            try: 
    592458                wikiPage = self.wikiData.getPage(wikiWord, toload=["props"]) 
    593             except WikiWordNotFoundException: 
     459            except WikiData.WikiWordNotFoundException: 
    594460                return False 
    595461             
     
    598464             
    599465        return strToBool(wikiPage.props.get("export", ("True",))[0]) 
    600              
     466 
     467     
     468    def formatContent(self, word, content, links=None, asXml=False): 
     469        # change the <<>> blocks into [[]] blocks so they aren't escaped 
     470        content = WikiFormatting.SuppressHighlightingRE.sub(u'[[\\1]]', content) 
     471        content = escape(content) 
     472        contentBeforeProcessing = content 
     473 
     474        content = WikiFormatting.ItalicRE.sub(u'<i>\\1</i>', content) 
     475        content = WikiFormatting.Heading4RE.sub(u'<h4>\\1</h4>', content) 
     476        content = WikiFormatting.Heading3RE.sub(u'<h3>\\1</h3>', content) 
     477        content = WikiFormatting.Heading2RE.sub(u'<h2>\\1</h2>', content) 
     478        content = WikiFormatting.Heading1RE.sub(u'<h1>\\1</h1>', content) 
     479 
     480        if asXml: 
     481            content = WikiFormatting.ToDoREWithContent.sub(u'<todo>\\1</todo>', content) 
     482        else: 
     483            content = WikiFormatting.ToDoREWithContent.sub(u'<span class="todo">\\1</span><br />', content) 
     484             
     485        content = WikiFormatting.ScriptRE.sub(u'', content) 
     486 
     487        if asXml:         
     488            content = WikiFormatting.PropertyRE.sub(u'<property name="\\1" value="\\2"/>', content) 
     489        else: 
     490            content = WikiFormatting.PropertyRE.sub(u'<span class="property">[\\1: \\2]</span>', content) 
     491 
     492        if not asXml:     
     493            content = WikiFormatting.HorizLineRE.sub(u'<hr size="1"/>', content) 
     494 
     495        # add the ul/ol/li tags for bullets 
     496        content = self.createBullets(content, asXml) 
     497 
     498        # add the blockquote tags for indents 
     499        content = self.createIndents(content, asXml) 
     500 
     501        # do bold last to make sure it doesn't mess with bullets 
     502        content = WikiFormatting.BoldRE.sub(u'<b>\\1</b>', content) 
     503 
     504        # link the wiki words 
     505        if links: 
     506            content = self.linkWikiWords(content, links, asXml) 
     507 
     508        # replace URL's last 
     509        if asXml: 
     510            content = WikiFormatting.UrlRE.sub(u'<link type="href">\\1</link>', content) 
     511        else: 
     512            def replaceLink(match): 
     513                lowerLink = match.group(1).lower() 
     514                if lowerLink.endswith(".jpg") or lowerLink.endswith(".gif") or lowerLink.endswith(".png"): 
     515                    return u'<img src="%s" border="0">' % match.group(1) 
     516                else: 
     517                    return u'<a href="%s">%s</a>' % (match.group(1), match.group(1)) 
     518            content = WikiFormatting.UrlRE.sub(replaceLink, content) 
     519 
     520        # add <pre> tags for suppressed regions 
     521        SuppressHighlightingRE = re.compile(u"\[\[(.*?)\]\]", re.DOTALL) 
     522 
     523        # tracks which [] block we are on 
     524        matchIndex = MatchIndex() 
     525        def suppress(match): 
     526            # now search the pre-processed text for the same match 
     527            bpMatchNumber = 0 
     528            bpMatch = SuppressHighlightingRE.search(contentBeforeProcessing) 
     529            while bpMatch: 
     530                if bpMatchNumber == matchIndex.get(): 
     531                    break 
     532                bpMatch = SuppressHighlightingRE.search(contentBeforeProcessing, bpMatch.end()) 
     533                bpMatchNumber = bpMatchNumber + 1 
     534 
     535            if (bpMatch): 
     536                matchContent = bpMatch.group(1) 
     537                htmlRe = re.compile(u"<.+?>") 
     538                matchContent = htmlRe.sub('', matchContent) 
     539                matchIndex.increment() 
     540                return u'<pre>%s</pre>' % matchContent 
     541            else: 
     542                return match.group(1) 
     543         
     544        content = SuppressHighlightingRE.sub(suppress, content) 
     545         
     546        return content 
     547 
     548     
     549    def exportWordToHtmlPage(self, dir, word, links=None, startFile=True, onlyInclude=None): 
     550        outputFile = mbcsEnc(join(dir, u"%s.html" % word))[0] 
     551        try: 
     552            wikiPage = self.wikiData.getPage(word, toload=["parents"]) 
     553            content = wikiPage.getContent() 
     554            formattedContent = self.formatContent(word, content, links) 
     555 
     556            if exists(outputFile): 
     557                os.unlink(outputFile) 
     558 
     559            realfp = open(outputFile, "w") 
     560            fp = mbcsWriter(realfp, "replace") 
     561            fp.write(self.getFileHeader(word)) 
     562 
     563            # if startFile is set then this is the only page being exported so 
     564            # do not include the parent header. 
     565            if not startFile: 
     566                fp.write(u'<span class="parent-nodes">parent nodes: %s</span>' 
     567                        % self.getParentLinks(wikiPage, True, onlyInclude)) 
     568 
     569            fp.write(formattedContent) 
     570            fp.write(self.getFileFooter()) 
     571            fp.reset()         
     572            realfp.close()         
     573        except Exception, e: 
     574            pass 
     575         
     576        self.copyCssFile(dir) 
     577        return outputFile 
     578#         if startFile: 
     579#             os.startfile(outputFile) 
     580 
     581         
     582         
    601583class MatchIndex: 
    602584    def __init__(self): 
     
    606588    def get(self): 
    607589        return self.matchIndex 
    608          
     590 
     591 
     592 
     593class TextExporter: 
     594    """ 
     595    Exports raw text 
     596    """ 
     597    def __init__(self): 
     598        self.pWiki = None 
     599        self.wikiData = None 
     600        self.wordList = None 
     601        self.exportDest = None 
     602 
     603 
     604    def getExportTypes(self, guiparent): 
     605        """ 
     606        Return sequence of tuples with the description of export types provided 
     607        by this object. A tuple has the form (<exp. type>, 
     608            <human readable desctiption>, <panel for add. options or None>) 
     609        If panels for additional options must be created, they should use 
     610        guiparent as parent 
     611        """ 
     612         
     613        res = xrc.wxXmlResource.Get() 
     614         
     615#         self.additOptions = wxPanel(self) 
     616#         res.AttachUnknownControl("additOptions", self.additOptions, self) 
     617 
     618        textPanel = res.LoadPanel(guiparent, "ExportSubText") # .ctrls.additOptions 
     619         
     620        return ( 
     621            ("raw_files", 'Set of *.wiki files', textPanel), 
     622            ) 
     623 
     624 
     625    def getAddOptVersion(self): 
     626        """ 
     627        Returns the version of the additional options information returned 
     628        by getAddOpt(). If the return value is -1, the version info can't 
     629        be stored between application sessions. 
     630         
     631        Otherwise, the addopt information can be stored between sessions 
     632        and can later handled back to the export method of the object 
     633        without previously showing the export dialog. 
     634        """ 
     635        return 0 
     636 
     637 
     638    def getAddOpt(self, addoptpanel): 
     639        """ 
     640        Reads additional options from panel addoptpanel. 
     641        If getAddOptVersion() > -1, the return value must be a sequence 
     642        of simple string and/or numeric objects. Otherwise, any object 
     643        can be returned (normally the addoptpanel itself) 
     644        """ 
     645        ctrls = XrcControls(addoptpanel) 
     646         
     647        # Which encoding: 
     648        # 0:System standard, 1:utf-8 with BOM, 2: utf-8 without BOM 
     649 
     650        return (ctrls.chTextEncoding.GetSelection(),) 
     651 
     652             
     653 
     654    def export(self, pWiki, wikiData, wordList, exportType, exportDest, 
     655            addopt): 
     656        """ 
     657        Run export operation. 
     658         
     659        pWiki -- PersonalWikiFrame object 
     660        wikiData -- WikiData object 
     661        wordList -- Sequence of wiki words to export 
     662        exportType -- string tag to identify how to export 
     663        exportDest -- Path to destination directory or file to export to 
     664        addopt -- additional options returned by getAddOpt() 
     665        """ 
     666        self.pWiki = pWiki 
     667        self.wikiData = wikiData # self.pWiki.wikiData 
     668        self.wordList = wordList 
     669        self.exportDest = exportDest 
     670         
     671        # 0:System standard, 1:utf-8 with BOM, 2: utf-8 without BOM 
     672        encoding = addopt[0] 
     673                 
     674        if encoding == 0: 
     675            enc = mbcsEnc 
     676        else: 
     677            enc = utf8Enc 
     678             
     679        if encoding == 1: 
     680            filehead = StringOps.BOM_UTF8 
     681        else: 
     682            filehead = "" 
     683 
     684        for word in self.wordList: 
     685            try: 
     686                content, modified = self.wikiData.getContentAndInfo(word)[:2] 
     687            except: 
     688                continue 
     689                 
     690            outputFile = mbcsEnc(join(self.exportDest, u"%s.wiki" % word))[0] 
     691            try: 
     692#                 if exists(outputFile): 
     693#                     os.unlink(outputFile) 
     694     
     695                fp = open(outputFile, "wb") 
     696                fp.write(filehead) 
     697                fp.write(enc(content, "replace")[0]) 
     698                fp.close() 
     699                 
     700                try: 
     701                    os.utime(outputFile, (long(modified), long(modified))) 
     702                except: 
     703                    pass 
     704            except: 
     705                continue 
     706 
     707 
     708def describeExporters(): 
     709    return (HtmlXmlExporter(), TextExporter()) 
     710     
  • /branches/mbutscher/work/lib/pwiki/WikiData.py

    r19 r26  
    2222import gadfly 
    2323import WikiFormatting 
    24 from WikiExceptions import *   # TODO make normal import 
     24from WikiExceptions import *   # TODO make normal import? 
    2525 
    2626from StringOps import mbcsEnc, mbcsDec, utf8Enc, utf8Dec, BOM_UTF8, \ 
     
    4040    else: 
    4141        return ob 
    42          
    4342 
    4443 
     
    5150        self.pWiki = pWiki 
    5251        self.dataDir = dataDir 
    53         self.dbConn = gadfly.gadfly("wikidb", dataDir) 
     52        self.dbConn = None 
     53        self.cachedWikiWords = None 
     54         
     55        self._reinit() 
     56         
     57 
     58    def _reinit(self): 
     59        """ 
     60        Actual initialization or reinitialization after rebuildWiki() 
     61        """ 
     62        self.dbConn = gadfly.gadfly("wikidb", self.dataDir) 
    5463 
    5564        # create word caches 
     
    115124        return fileContentToUnicode(content) 
    116125 
    117         # TODO Remove method, create rebuildWiki method 
     126        # TODO Remove method 
    118127    def updatePageEntry(self, word, moddate = None, creadate = None): 
    119128        """ 
     
    187196         
    188197 
     198    # ---------- Rebuilding the wiki ---------- 
     199    def rebuildWiki(self, progresshandler): 
     200        """ 
     201        progresshandler -- Object, fulfilling the GuiProgressHandler 
     202            protocol 
     203        """ 
     204        # get all of the wikiWords 
     205        wikiWords = self.getAllPageNamesFromDisk()   # Replace this call 
     206        # get the saved searches 
     207        searches = self.getSavedSearches() 
     208 
     209        self.close() 
     210                 
     211        progresshandler.open(len(wikiWords) + len(searches) + 1) 
     212 
     213        try: 
     214            step = 1 
     215            # recreate the db 
     216            progresshandler.update(step, "Recreating database") 
     217            createWikiDB("", self.dataDir, True) 
     218            # reopen the wiki 
     219            self._reinit() 
     220            # re-save all of the pages 
     221            for wikiWord in wikiWords: 
     222                progresshandler.update(step, u"Rebuilding %s" % wikiWord) 
     223                wikiPage = self.createPage(wikiWord) 
     224                self.updatePageEntry(wikiWord) 
     225                wikiPage.update(wikiPage.getContent(), False) 
     226                step += 1 
     227 
     228            # resave searches 
     229            for search in searches: 
     230                progresshandler.update(step, u"Reading search %s" % search) 
     231                self.saveSearch(search) 
     232 
     233##             self.close() 
     234##             self._reinit() 
     235             
     236        finally:             
     237            progresshandler.close() 
     238     
     239     
     240     
    189241    # ---------- The rest ---------- 
    190242 
  • /branches/mbutscher/work/lib/pwiki/WikiFormatting.py

    r19 r26  
    3131    global ToDoREWithCapturing 
    3232    global FormatExpressions 
    33     global CombinedWithCamelCaseRE 
    34     global CombinedWithoutCamelCaseRE 
     33    global CombinedSyntaxHighlightWithCamelCaseRE 
     34    global CombinedSyntaxHighlightWithoutCamelCaseRE 
    3535     
    3636    BoldRE = wikiSyntax.BoldRE 
     
    9090 
    9191 
    92     CombinedWithCamelCaseRE = re.compile(u"|".join(WithCamelCase), re.DOTALL | re.LOCALE | re.MULTILINE | re.UNICODE) 
    93     CombinedWithoutCamelCaseRE = re.compile(u"|".join(WithoutCamelCase), re.DOTALL | re.LOCALE | re.MULTILINE | re.UNICODE) 
     92    CombinedSyntaxHighlightWithCamelCaseRE = \ 
     93            re.compile(u"|".join(WithCamelCase), 
     94                    re.DOTALL | re.LOCALE | re.MULTILINE | re.UNICODE) 
     95    CombinedSyntaxHighlightWithoutCamelCaseRE = \ 
     96            re.compile(u"|".join(WithoutCamelCase), 
     97                    re.DOTALL | re.LOCALE | re.MULTILINE | re.UNICODE) 
    9498     
    9599 
  • /branches/mbutscher/work/lib/pwiki/Configuration.py

    r19 r26  
    1717from StringOps import utf8Enc, utf8Dec, mbcsDec, strToBool 
    1818 
    19  
     19Error = ConfigParser.Error 
    2020 
    2121def _setValue(section, option, value, config): 
  • /branches/mbutscher/work/lib/pwiki/WikiTreeCtrl.py

    r19 r30  
    194194        # Refresh subtree 
    195195         
    196         ## self.Freeze() # Stop visual updates 
     196        self.Freeze() # Stop visual updates 
    197197        if self.IsExpanded(treeNode): 
    198198            treeChildren = self.getChildTreeNodes(treeNode) 
     
    233233                viewNode = self.addViewNode(treeNode, "Views", icon="orgchart") 
    234234                 
    235         ## self.Thaw() # Allow visual updates again 
     235        self.Thaw() # Allow visual updates again 
    236236         
    237237        return treeNode 
     
    259259            nodeValue = nodeText 
    260260        nodeText = getTextForNode(nodeText) 
    261         newNode = self.AppendItem(parentNode, mbcsEnc(nodeText, "replace")[0]) 
     261        newNode = self.AppendItem(parentNode, uniToGui(nodeText)) 
    262262        self.SetPyData(newNode, (nodeValue, viewData, searchData)) 
    263263 
     
    370370    def setNodeImage(self, node, image): 
    371371        try: 
    372             (index, icon) = self.pWiki.iconLookup[image] 
     372            index = self.pWiki.lookupIconIndex(image) 
    373373            ## if icon: 
    374374                ## self.SetItemImage(node, index, wxTreeItemIcon_Selected) 
     
    448448        elif name == "searches": 
    449449            for search in wikiData.getSavedSearches():     # ??? 
    450                 self.addViewNode(viewNode, search, "%s~searchFor" % name, icon="lens") 
     450                self.addViewNode(viewNode, search, u"%s~searchFor" % name, icon="lens") 
    451451 
    452452        elif name == "modified-within": 
     
    564564                     
    565565    def OnTreeItemExpand(self, event): 
    566         ## print "OnTreeItemExpand start" 
    567         ## _prof.start() 
    568566        item = event.GetItem() 
    569567        if not self.isViewNode(item): 
     
    574572        else: 
    575573            self.expandView(item) 
    576         ## _prof.stop() 
    577         ## print "OnTreeItemExpand stop" 
    578574 
    579575    def OnTreeItemCollapse(self, event): 
  • /branches/mbutscher/work/lib/pwiki/AdditionalDialogs.py

    r19 r30  
    1010from wxHelper import * 
    1111 
    12 from StringOps import uniToGui, guiToUni 
     12from StringOps import uniToGui, guiToUni, mbcsEnc, mbcsDec 
    1313import WikiFormatting 
    1414import Exporters 
     
    111111        wikiWord = self.value 
    112112        if not WikiFormatting.isWikiWord(wikiWord): 
    113             wikiWord = "[%s]" % wikiWord 
     113            wikiWord = u"[%s]" % wikiWord 
    114114        if not WikiFormatting.isWikiWord(wikiWord): 
    115             self.pWiki.displayErrorMessage("'%s' is an invalid WikiWord" % wikiWord) 
     115            self.pWiki.displayErrorMessage(u"'%s' is an invalid WikiWord" % wikiWord) 
    116116            self.ctrls.text.SetFocus() 
    117117            return 
    118118         
    119119        if self.pWiki.wikiData.isDefinedWikiWord(wikiWord): 
    120             self.pWiki.displayErrorMessage("'%s' exists already" % wikiWord) 
     120            self.pWiki.displayErrorMessage(u"'%s' exists already" % wikiWord) 
    121121            self.ctrls.text.SetFocus() 
    122122            return 
     
    134134        self.pWiki = pWiki 
    135135        self.iconImageList = self.pWiki.iconImageList 
    136         self.iconLookup = self.pWiki.iconLookup 
     136        self.lookupIconIndex = self.pWiki.lookupIconIndex 
    137137         
    138138        self.iconNames = filter(lambda n: not n.startswith("tb_"), 
    139                 self.pWiki.iconLookup.keys()) 
     139                self.pWiki.iconLookupCache.keys()) 
    140140        self.iconNames.sort() 
    141141         
     
    156156 
    157157        for icn in self.iconNames: 
    158             self.lc.InsertImageStringItem(sys.maxint, icn, self.iconLookup[icn][0]) 
     158            self.lc.InsertImageStringItem(sys.maxint, icn, 
     159                    self.lookupIconIndex(icn)) 
    159160        self.lc.SetColumnWidth(0, wxLIST_AUTOSIZE) 
    160161         
     
    337338    def __init__(self, pWiki, ID, title="Select Date Format", 
    338339                 pos=wxDefaultPosition, size=wxDefaultSize, 
    339                  style=wxNO_3D, deffmt=""): 
     340                 style=wxNO_3D, deffmt=u""): 
    340341        """ 
    341342        deffmt -- Initial value for format string 
     
    367368    def OnText(self, evt): 
    368369        preview = "<invalid>" 
    369         text = self.ctrls.fieldFormat.GetValue() 
     370        text = guiToUni(self.ctrls.fieldFormat.GetValue()) 
    370371        try: 
    371             preview = strftime(text) 
     372            # strftime can't handle unicode correctly, so conversion is needed 
     373            mstr = mbcsEnc(text, "replace")[0] 
     374            preview = mbcsDec(strftime(mstr), "replace")[0] 
    372375            self.value = text 
    373376        except: 
     
    421424        # Transfer options from dialog to config file 
    422425        for o, c, t in self.OPTION_TO_CONTROL: 
     426            #TODO Handle unicode text controls 
    423427            self.pWiki.configuration.set("main", o, repr(self.ctrls[c].GetValue())) 
    424428             
     
    456460                          # <readable description>, <additional options panel>) 
    457461         
    458         for ob in Exporters.getExporterObjects():   # TODO search plugins 
     462        for ob in Exporters.describeExporters():   # TODO search plugins 
    459463            for tp in ob.getExportTypes(self.ctrls.additOptions): 
    460464                panel = tp[2] 
     
    491495 
    492496 
    493         # ['Single HTML page', 'Set of HTML pages', 'XML file', 'Set of *.wiki files'] 
    494497        for e in self.exporterList: 
    495498            e[3].Show(False) 
     
    520523 
    521524    def OnOk(self, evt): 
    522         if not exists(self.ctrls.tfDirectory.GetValue()): 
     525        if not exists(guiToUni(self.ctrls.tfDirectory.GetValue())): 
    523526            self.pWiki.displayErrorMessage(u"Destination directory does not exist") 
    524527            return 
     
    541544        ob, t, desc, panel = \ 
    542545                self.exporterList[self.ctrls.chExportTo.GetSelection()][:4] 
    543                  
     546 
    544547        ob.export(self.pWiki, self.pWiki.wikiData, wordList, t,  
    545                 self.ctrls.tfDirectory.GetValue(), panel) 
    546   
     548                guiToUni(self.ctrls.tfDirectory.GetValue()), ob.getAddOpt(panel)) 
     549 
    547550        self.EndModal(wxID_OK) 
    548551 
    549552         
    550553    def OnSelectDir(self, evt): 
     554        # Only transfer between GUI elements, so no unicode conversion 
    551555        seldir = wxDirSelector(u"Select Export Directory", 
    552556                self.ctrls.tfDirectory.GetValue(), 
  • /branches/mbutscher/work/lib/pwiki/PersonalWikiFrame.py

    r19 r30  
    1 from Configuration import createConfiguration 
     1 
    22import os, gc, traceback 
    33from os.path import * 
     
    99from wxHelper import GUI_ID 
    1010 
     11import Configuration 
     12from Configuration import createConfiguration 
    1113from WikiData import * 
    1214from WikiTxtCtrl import * 
    1315from WikiTreeCtrl import * 
    1416from AdditionalDialogs import * 
    15 from Exporters import * 
     17import Exporters 
    1618from StringOps import uniToGui, guiToUni, mbcsDec, mbcsEnc 
    1719import WikiFormatting 
    1820 
    19  
     21from PluginManager import * 
    2022_COLORS = [ 
    2123    "AQUAMARINE", 
     
    9193 
    9294 
     95class wxGuiProgressHandler: 
     96    """ 
     97    Implementation of a GuiProgressListener to 
     98    show a wxProgressDialog 
     99    """ 
     100    def __init__(self, title, msg, addsteps, parent, flags=wxPD_APP_MODAL): 
     101        self.title = title 
     102        self.msg = msg 
     103        self.addsteps = addsteps 
     104        self.parent = parent 
     105        self.flags = flags 
     106 
     107    def open(self, sum): 
     108        """ 
     109        Start progress handler, set the number of steps, the operation will 
     110        take in sum. Will be called once before update() 
     111        is called several times 
     112        """ 
     113        self.progDlg = wxProgressDialog(self.title, self.msg, 
     114                sum + self.addsteps, self.parent, self.flags) 
     115         
     116    def update(self, step, msg): 
     117        """ 
     118        Called after a step is finished to trigger update 
     119        of GUI. 
     120        step -- Number of done steps 
     121        msg -- Human readable descripion what is currently done 
     122        returns: True to continue, False to stop operation 
     123        """ 
     124        self.progDlg.Update(step, uniToGui(msg)) 
     125        return True 
     126 
     127    def close(self): 
     128        """ 
     129        Called after finishing operation or after abort to  
     130        do clean-up if necessary 
     131        """ 
     132        self.progDlg.Destroy() 
     133        self.progDlg = None 
     134 
     135 
    93136 
    94137class PersonalWikiFrame(wxFrame): 
     
    105148            self.wikiAppDir = dirname(abspath(sys.argv[0])) 
    106149            if not self.wikiAppDir: 
    107                 self.wikiAppDir = "C:\Program Files\WikidPad" 
     150                self.wikiAppDir = r"C:\Program Files\WikidPad" 
    108151 
    109152            homeDir = os.environ.get("HOME") 
     
    113156                user = os.environ.get("USERNAME") 
    114157                if user: 
    115                     homeDir = "c:\Documents And Settings\%s" % user 
     158                    homeDir = r"c:\Documents And Settings\%s" % user 
    116159                    if homeDir and exists(homeDir): 
    117160                        globalConfigDir = homeDir 
    118161        except Exception, e: 
    119             self.displayErrorMessage("Error initializing environment", e) 
     162            self.displayErrorMessage(u"Error initializing environment", e) 
    120163 
    121164        if not globalConfigDir: 
     
    126169 
    127170        if not globalConfigDir or not exists(globalConfigDir): 
    128             self.displayErrorMessage("Error initializing environment, couldn't locate global config directory", "Shutting Down") 
     171            self.displayErrorMessage( 
     172                    u"Error initializing environment, couldn't locate "+ 
     173                    u"global config directory", u"Shutting Down") 
    129174            self.Close() 
    130175 
     
    132177        # initialize some variables 
    133178        self.globalConfigDir = globalConfigDir 
    134         self.globalConfigLoc = join(globalConfigDir, "WikidPad.config") 
     179        self.globalConfigLoc = join(globalConfigDir, u"WikidPad.config") 
    135180        self.configuration = createConfiguration() 
    136181 
    137         self.wikiPadHelp = join(self.wikiAppDir, 'WikidPadHelp', 'WikidPadHelp.wiki') 
     182        self.wikiPadHelp = join(self.wikiAppDir, u'WikidPadHelp', 
     183                u'WikidPadHelp.wiki') 
    138184 
    139185        # defaults 
     
    145191        self.wikiWordHistory = [] 
    146192        self.lastCursorPositionInPage = {} 
    147         self.iconLookup = {} 
     193        self.iconLookupCache = {} 
    148194        self.wikiHistory = [] 
     195 
     196        # setup plugin manager and hooks API 
     197        self.pluginManager = PluginManager() 
     198        self.hooks = self.pluginManager.registerPluginAPI(("hooks",1), 
     199            ["startup", "newWiki", "createdWiki", "openWiki", "openedWiki",  
     200             "openWikiWord", "newWikiWord", "openedWikiWord", "savingWikiWord", 
     201             "savedWikiWord", "renamedWikiWord", "deletedWikiWord", "exit"] ) 
     202        # interfaces for menu and toolbar plugins 
     203#         self.editorFunctions = self.pluginManager.registerPluginAPI(("EditorFunctions",1),  
     204#                                 ["describeMenuItem", "describeToolbarItem"]) 
     205        self.menuFunctions = self.pluginManager.registerPluginAPI(("MenuFunctions",1),  
     206                                ["describeMenuItems"]) 
     207        self.toolbarFunctions = self.pluginManager.registerPluginAPI(("ToolbarFunctions",1),  
     208                                ["describeToolbarItems"]) 
    149209 
    150210        # load extensions 
     
    155215 
    156216        # trigger hook 
    157         self.wikidPadHooks.startup(self) 
     217        self.hooks.startup(self) 
    158218 
    159219        # if it already exists read it in 
    160         if (exists(self.globalConfigLoc)): 
    161             self.configuration.loadGlobalConfig(self.globalConfigLoc) 
     220        if exists(self.globalConfigLoc): 
     221            try: 
     222                self.configuration.loadGlobalConfig(self.globalConfigLoc) 
     223            except Configuration.Error: 
     224                self.createDefaultGlobalConfig() 
    162225        else: 
    163226            self.createDefaultGlobalConfig() 
     
    166229        history = self.configuration.get("main", "wiki_history") 
    167230        if history: 
    168             self.wikiHistory = history.split(";") 
     231            self.wikiHistory = history.split(u";") 
    169232 
    170233        # resize the window to the last position/size 
     
    274337 
    275338    def loadExtensions(self): 
    276         self.wikidPadHooks = self.getExtension('WikidPadHooks', 'WikidPadHooks.py') 
    277         self.keyBindings = self.getExtension('KeyBindings', 'KeyBindings.py') 
    278         self.evalLib = self.getExtension('EvalLibrary', 'EvalLibrary.py') 
    279         self.wikiSyntax = self.getExtension('SyntaxLibrary', 'WikiSyntax.py') 
    280         self.presentationExt = self.getExtension('Presentation', 'Presentation.py') 
     339        self.wikidPadHooks = self.getExtension('WikidPadHooks', u'WikidPadHooks.py') 
     340        self.keyBindings = self.getExtension('KeyBindings', u'KeyBindings.py') 
     341        self.evalLib = self.getExtension('EvalLibrary', u'EvalLibrary.py') 
     342        self.wikiSyntax = self.getExtension('SyntaxLibrary', u'WikiSyntax.py') 
     343        self.presentationExt = self.getExtension('Presentation', u'Presentation.py') 
     344        dirs = [ join(self.wikiAppDir, u'user_extensions'), 
     345                join(self.wikiAppDir, u'extensions') ] 
     346        self.pluginManager.loadPlugins( dirs, [ u'KeyBindings.py', 
     347                u'EvalLibrary.py', u'WikiSyntax.py' ] ) 
    281348 
    282349    def getExtension(self, extensionName, fileName): 
     
    302369 
    303370 
    304     def fillIconLookup(self, createIconImageList=False): 
     371    # TODO! 
     372    def fillIconLookupCache(self, createIconImageList=False): 
    305373        """ 
    306         Fills or refills the self.iconLookup (if createIconImageList is 
     374        Fills or refills the self.iconLookupCache (if createIconImageList is 
    307375        false, it must exist already) 
    308376        If createIconImageList is true, self.iconImageList is also 
     
    313381            # create the image icon list 
    314382            self.iconImageList = wxImageList(16, 16) 
    315             self.iconLookup = {} 
     383            self.iconLookupCache = {} 
    316384 
    317385        for icon in self.iconFileList: 
     
    323391                    id = self.iconImageList.Add(bitmap, wxNullBitmap) 
    324392 
    325                 if self.lowResources and not icon.startswith("tb_"): 
     393                if self.lowResources:   # and not icon.startswith("tb_"): 
    326394                    bitmap = None 
    327395 
    328396                iconname = icon.replace('.gif', '') 
    329397                if id == -1: 
    330                     id = self.iconLookup[iconname][0] 
    331  
    332                 self.iconLookup[iconname] = (id, bitmap) 
     398                    id = self.iconLookupCache[iconname][0] 
     399 
     400                self.iconLookupCache[iconname] = (id, bitmap) 
    333401            except Exception, e: 
    334402                traceback.print_exc() 
    335403                sys.stderr.write("couldn't load icon %s\n" % iconFile) 
    336404 
    337  
    338     def addMenuItem(self, menu, label, text, evtfct, iconname=None, menuID=None): 
     405    def lookupIcon(self, iconname): 
     406        """ 
     407        Returns the bitmap object for the given iconname. 
     408        If the bitmap wasn't cached already, it is loaded and created. 
     409        If icon is unknown, None is returned. 
     410        """ 
     411        try: 
     412            bitmap = self.iconLookupCache[iconname][1] 
     413            if bitmap is not None: 
     414                return bitmap 
     415                 
     416            # Bitmap not yet available -> create it and store in the cache 
     417            iconFile = join(self.wikiAppDir, "icons", iconname+".gif") 
     418            bitmap = wxBitmap(iconFile, wxBITMAP_TYPE_GIF) 
     419             
     420            self.iconLookupCache[iconname] = (self.iconLookupCache[iconname][0], 
     421                    bitmap) 
     422            return bitmap 
     423 
     424        except KeyError: 
     425            return None 
     426 
     427 
     428    def lookupIconIndex(self, iconname): 
     429        """ 
     430        Returns the id number into self.iconImageList of the requested icon. 
     431        If icon is unknown, -1 is returned. 
     432        """ 
     433        try: 
     434            return self.iconLookupCache[iconname][0] 
     435        except KeyError: 
     436            return -1 
     437 
     438 
     439    def resolveIconDescriptor(self, desc, default=None): 
     440        """ 
     441        Used for plugins of type "MenuFunctions" or "ToolbarFunctions". 
     442        Tries to find and return an appropriate wxBitmap object. 
     443         
     444        An icon descriptor can be one of the following: 
     445            - None 
     446            - a wxBitmap object 
     447            - the filename of a bitmap 
     448            - a tuple of filenames, first existing file is used 
     449         
     450        If no bitmap can be found, default is returned instead. 
     451        """ 
     452        if desc is None: 
     453            return default             
     454        elif isinstance(desc, wxBitmap): 
     455            return desc 
     456        elif isinstance(desc, basestring): 
     457            result = self.lookupIcon(desc) 
     458            if result is not None: 
     459                return result 
     460             
     461            return default 
     462        else:    # A sequence of possible names 
     463            for n in desc: 
     464                result = self.lookupIcon(n) 
     465                if result is not None: 
     466                    return result 
     467 
     468            return default 
     469 
     470 
     471    def addMenuItem(self, menu, label, text, evtfct, icondesc=None, menuID=None): 
    339472        if menuID is None: 
    340473            menuID = wxNewId() 
    341474 
    342475        menuitem = wxMenuItem(menu, menuID, label, text) 
    343         if iconname:  # (not self.lowResources) and 
    344             (id, bitmap) = self.iconLookup[iconname] 
     476        # if icondesc:  # (not self.lowResources) and 
     477        bitmap = self.resolveIconDescriptor(icondesc) 
     478        if bitmap: 
    345479            menuitem.SetBitmap(bitmap) 
    346480 
     
    401535        wikiMenu.AppendSeparator() 
    402536 
    403 #         menuID=wxNewId() 
    404 #         wikiMenu.Append(menuID, 'Export Dialog', 'Export  Dialog') 
    405 #         EVT_MENU(self, menuID, lambda evt: self.showExportDialog()) 
    406  
    407  
    408537        exportWikisMenu = wxMenu() 
    409538        wikiMenu.AppendMenu(wxNewId(), 'Export', exportWikisMenu) 
    410539 
    411         menuID=wxNewId() 
    412         exportWikisMenu.Append(menuID, 'Export Wiki as Single HTML Page', 'Export As Single HTML Page') 
    413         EVT_MENU(self, menuID, lambda evt: self.exportWiki(ExportTypes.WikiToSingleHtmlPage)) 
    414  
    415         menuID=wxNewId() 
    416         exportWikisMenu.Append(menuID, 'Export Wiki as Set of HTML Pages', 'Export Wiki As Set of HTML Pages') 
    417         EVT_MENU(self, menuID, lambda evt: self.exportWiki(ExportTypes.WikiToSetOfHtmlPages)) 
    418  
    419         menuID=wxNewId() 
    420         exportWikisMenu.Append(menuID, 'Export Current Wiki Word as HTML Page', 'Export Current Wiki Word as HTML Page') 
    421         EVT_MENU(self, menuID, lambda evt: self.exportWiki(ExportTypes.WikiWordToHtmlPage)) 
    422  
    423         menuID=wxNewId() 
    424         exportWikisMenu.Append(menuID, 'Export Sub-Tree as Single HTML Page', 'Export Sub-Tree as Single HTML Page') 
    425         EVT_MENU(self, menuID, lambda evt: self.exportWiki(ExportTypes.WikiSubTreeToSingleHtmlPage)) 
    426  
    427         menuID=wxNewId() 
    428         exportWikisMenu.Append(menuID, 'Export Sub-Tree as Set of HTML Pages', 'Export Sub-Tree as Set of HTML Pages') 
    429         EVT_MENU(self, menuID, lambda evt: self.exportWiki(ExportTypes.WikiSubTreeToSetOfHtmlPages)) 
    430  
    431         menuID=wxNewId() 
    432         exportWikisMenu.Append(menuID, 'Export Wiki as XML', 'Export Wiki as XML') 
    433         EVT_MENU(self, menuID, lambda evt: self.exportWiki(ExportTypes.WikiToXml)) 
     540        self.addMenuItem(exportWikisMenu, 'Export Wiki as Single HTML Page', 
     541                'Export Wiki as Single HTML Page', self.OnExportWiki, 
     542                menuID=GUI_ID.MENU_EXPORT_WHOLE_AS_PAGE) 
     543 
     544        self.addMenuItem(exportWikisMenu, 'Export Wiki as Set of HTML Pages', 
     545                'Export Wiki as Set of HTML Pages', self.OnExportWiki, 
     546                menuID=GUI_ID.MENU_EXPORT_WHOLE_AS_PAGES) 
     547 
     548        self.addMenuItem(exportWikisMenu, 'Export Current Wiki Word as HTML Page', 
     549                'Export Current Wiki Word as HTML Page', self.OnExportWiki, 
     550                menuID=GUI_ID.MENU_EXPORT_WORD_AS_PAGE) 
     551 
     552        self.addMenuItem(exportWikisMenu, 'Export Sub-Tree as Single HTML Page', 
     553                'Export Sub-Tree as Single HTML Page', self.OnExportWiki, 
     554                menuID=GUI_ID.MENU_EXPORT_SUB_AS_PAGE) 
     555 
     556        self.addMenuItem(exportWikisMenu, 'Export Sub-Tree as Set of HTML Pages', 
     557                'Export Sub-Tree as Set of HTML Pages', self.OnExportWiki, 
     558                menuID=GUI_ID.MENU_EXPORT_SUB_AS_PAGES) 
     559 
     560        self.addMenuItem(exportWikisMenu, 'Export Wiki as XML', 
     561                'Export Wiki as XML in UTF-8', self.OnExportWiki, 
     562                menuID=GUI_ID.MENU_EXPORT_WHOLE_AS_XML) 
     563 
     564        self.addMenuItem(exportWikisMenu, 'Export Wiki to .wiki files', 
     565                'Export Wiki to .wiki files in UTF-8', self.OnExportWiki, 
     566                menuID=GUI_ID.MENU_EXPORT_WHOLE_AS_RAW) 
     567 
     568        self.addMenuItem(exportWikisMenu, 'Other Export...', 
     569                'Open export dialog', 
     570                lambda evt: self.showExportDialog()) 
    434571 
    435572        menuID=wxNewId() 
     
    541678        self.addMenuItem(formattingMenu, 'Set Date Format', 
    542679                'Set Date Format', lambda evt: self.showDateformatDialog()) 
     680 
     681        self.addMenuItem(formattingMenu, 
     682                'Wikize Selected Word\t' + self.keyBindings.MakeWikiWord, 
     683                'Wikize Selected Word', 
     684                lambda evt: self.keyBindings.makeWikiWord(self.editor), 
     685                "tb_pin") 
    543686 
    544687 
     
    624767            iconsMenu.AppendMenu(wxNewId(), 'T-Z', iconsMenu6) 
    625768 
    626             icons = self.iconLookup.keys(); 
     769            icons = self.iconLookupCache.keys();  # TODO: Create function? 
    627770            icons.sort() 
    628771 
     
    646789                menuID=wxNewId() 
    647790                menuItem = wxMenuItem(iconsSubMenu, menuID, id, id) 
    648                 (id2, bitmap) = self.iconLookup[id] 
     791                bitmap = self.lookupIcon(id) 
    649792                menuItem.SetBitmap(bitmap) 
    650793                iconsSubMenu.AppendItem(menuItem) 
     
    782925        EVT_MENU(self, menuID, lambda evt: self.showAboutDialog()) 
    783926 
     927        # get info for any plugin menu items and create them as necessary 
     928        pluginMenu = None 
     929        menuItems = reduce(lambda a, b: a+list(b), 
     930                self.menuFunctions.describeMenuItems(self), []) 
     931        if len(menuItems) > 0: 
     932            pluginMenu = wxMenu() 
     933                 
     934            def addPluginMenuItem(function, label, statustext, icondesc=None, 
     935                    menuID=None): 
     936                self.addMenuItem(pluginMenu, label, statustext, 
     937                        lambda evt: function(self, evt), icondesc, menuID) 
     938             
     939            for item in menuItems: 
     940                addPluginMenuItem(*item) 
     941 
     942 
    784943        self.mainmenu.Append(wikiMenu, 'W&iki') 
    785944        self.mainmenu.Append(wikiWordMenu, '&Wiki Words') 
    786945        self.mainmenu.Append(historyMenu, '&History') 
    787946        self.mainmenu.Append(formattingMenu, '&Editor') 
     947        if pluginMenu: 
     948            self.mainmenu.Append(pluginMenu, "Pl&ugins") 
    788949        self.mainmenu.Append(helpMenu, 'He&lp') 
    789950 
     
    819980 
    820981        tb = self.CreateToolBar(wxTB_HORIZONTAL | wxNO_BORDER | wxTB_FLAT | wxTB_TEXT) 
    821         (index, seperator) = self.iconLookup["tb_seperator"] 
    822  
    823         (index, icon) = self.iconLookup["tb_back"] 
     982        seperator = self.lookupIcon("tb_seperator") 
     983 
     984        icon = self.lookupIcon("tb_back") 
    824985        tbID = wxNewId() 
    825986        tb.AddSimpleTool(tbID, icon, "Back (Ctrl-Alt-Back)", "Back") 
    826987        EVT_TOOL(self, tbID, lambda evt: self.goInHistory(-1)) 
    827988 
    828         (index, icon) = self.iconLookup["tb_forward"] 
     989        icon = self.lookupIcon("tb_forward") 
    829990        tbID = wxNewId() 
    830991        tb.AddSimpleTool(tbID, icon, "Forward (Ctrl-Alt-Forward)", "Forward") 
    831992        EVT_TOOL(self, tbID, lambda evt: self.goInHistory(1)) 
    832993 
    833         (index, icon) = self.iconLookup["tb_home"] 
     994        icon = self.lookupIcon("tb_home") 
    834995        tbID = wxNewId() 
    835996        tb.AddSimpleTool(tbID, icon, "Wiki Home", "Wiki Home") 
    836997        EVT_TOOL(self, tbID, lambda evt: self.openWikiPage(self.wikiName, forceTreeSyncFromRoot=True)) 
    837998 
    838         (index, icon) = self.iconLookup["tb_doc"] 
     999        icon = self.lookupIcon("tb_doc") 
    8391000        tbID = wxNewId() 
    8401001        tb.AddSimpleTool(tbID, icon, "Open Wiki Word  (Ctrl-O)", "Open Wiki Word") 
    8411002        EVT_TOOL(self, tbID, lambda evt: self.showWikiWordOpenDialog()) 
    8421003 
    843         (index, icon) = self.iconLookup["tb_lens"] 
     1004        icon = self.lookupIcon("tb_lens") 
    8441005        tbID = wxNewId() 
    8451006        tb.AddSimpleTool(tbID, icon, "Search  (Ctrl-Alt-F)", "Search") 
    8461007        EVT_TOOL(self, tbID, lambda evt: self.showSearchDialog()) 
    8471008 
    848         (index, icon) = self.iconLookup["tb_cycle"] 
     1009        icon = self.lookupIcon("tb_cycle") 
    8491010        tbID = wxNewId() 
    8501011        tb.AddSimpleTool(tbID, icon, "Find current word in tree", "Find current word in tree") 
     
    8531014        tb.AddSimpleTool(wxNewId(), seperator, "Separator", "Separator") 
    8541015 
    855         (index, icon) = self.iconLookup["tb_save"] 
     1016        icon = self.lookupIcon("tb_save") 
    8561017        tbID = wxNewId() 
    8571018        tb.AddSimpleTool(tbID, icon, "Save Wiki Word (Ctrl-S)", "Save Wiki Word") 
    8581019        EVT_TOOL(self, tbID, lambda evt: (self.saveCurrentWikiPage(), self.wikiData.commit())) 
    8591020 
    860         (index, icon) = self.iconLookup["tb_rename"] 
     1021        icon = self.lookupIcon("tb_rename") 
    8611022        tbID = wxNewId() 
    8621023        tb.AddSimpleTool(tbID, icon, "Rename Wiki Word (Ctrl-Alt-R)", "Rename Wiki Word") 
    8631024        EVT_TOOL(self, tbID, lambda evt: self.showWikiWordRenameDialog()) 
    8641025 
    865         (index, icon) = self.iconLookup["tb_delete"] 
     1026        icon = self.lookupIcon("tb_delete") 
    8661027        tbID = wxNewId() 
    8671028        tb.AddSimpleTool(tbID, icon, "Delete (Ctrl-D)", "Delete Wiki Word") 
     
    8701031        tb.AddSimpleTool(wxNewId(), seperator, "Separator", "Separator") 
    8711032 
    872         (index, icon) = self.iconLookup["tb_heading"] 
     1033        icon = self.lookupIcon("tb_heading") 
    8731034        tbID = wxNewId() 
    8741035        tb.AddSimpleTool(tbID, icon, "Heading (Ctrl-Alt-H)", "Heading") 
    8751036        EVT_TOOL(self, tbID, lambda evt: self.keyBindings.addHeading(self.editor)) 
    8761037 
    877         (index, icon) = self.iconLookup["tb_bold"] 
     1038        icon = self.lookupIcon("tb_bold") 
    8781039        tbID = wxNewId() 
    8791040        tb.AddSimpleTool(tbID, icon, "Bold (Ctrl-B)", "Bold") 
    8801041        EVT_TOOL(self, tbID, lambda evt: self.keyBindings.makeBold(self.editor)) 
    8811042 
    882         (index, icon) = self.iconLookup["tb_italic"] 
     1043        icon = self.lookupIcon("tb_italic") 
    8831044        tbID = wxNewId() 
    8841045        tb.AddSimpleTool(tbID, icon, "Italic (Ctrl-I)", "Italic") 
     
    8871048        tb.AddSimpleTool(wxNewId(), seperator, "Separator", "Separator") 
    8881049 
    889         (index, icon) = self.iconLookup["tb_zoomin"] 
     1050        icon = self.lookupIcon("tb_zoomin") 
    8901051        tbID = wxNewId() 
    8911052        tb.AddSimpleTool(tbID, icon, "Zoom In", "Zoom In") 
    8921053        EVT_TOOL(self, tbID, lambda evt: self.editor.CmdKeyExecute(wxSTC_CMD_ZOOMIN)) 
    8931054 
    894         (index, icon) = self.iconLookup["tb_zoomout"] 
     1055        icon = self.lookupIcon("tb_zoomout") 
    8951056        tbID = wxNewId() 
    8961057        tb.AddSimpleTool(tbID, icon, "Zoom Out", "Zoom Out") 
    8971058        EVT_TOOL(self, tbID, lambda evt: self.editor.CmdKeyExecute(wxSTC_CMD_ZOOMOUT)) 
     1059 
     1060        icon = self.lookupIcon("tb_pin") 
     1061        tbID = wxNewId() 
     1062        tb.AddSimpleTool(tbID, icon, "Wikize Selected Word", "Wikize Selected Word") 
     1063        EVT_TOOL(self, tbID, lambda evt: self.keyBindings.makeWikiWord(self.editor)) 
     1064 
     1065        # get info for any plugin toolbar items and create them as necessary 
     1066        toolbarItems = reduce(lambda a, b: a+list(b), 
     1067                self.toolbarFunctions.describeToolbarItems(self), []) 
     1068         
     1069        def addPluginTool(function, label, tooltip, icondesc, tbID=None): 
     1070            if tbID is None: 
     1071                tbID = wxNewId() 
     1072                 
     1073            icon = self.resolveIconDescriptor(icondesc, self.lookupIcon(u"tb_doc")) 
     1074            tb.AddLabelTool(tbID, label, icon, wxNullBitmap, 0, tooltip) 
     1075            EVT_TOOL(self, tbID, lambda evt: function(self, evt)) 
     1076             
     1077        for item in toolbarItems: 
     1078            addPluginTool(*item) 
     1079 
    8981080 
    8991081        tb.Realize() 
     
    9211103 
    9221104        # Create iconImageList 
    923         self.fillIconLookup(True) 
     1105        self.fillIconLookupCache(True) 
    9241106 
    9251107        self.buildMainMenu() 
     
    9511133            self.tree.AssignImageList(self.iconImageList) 
    9521134        except Exception, e: 
    953             self.displayErrorMessage('There was an error loading the icons for the tree control.', e) 
     1135            self.displayErrorMessage('There was an error loading the icons '+ 
     1136                    'for the tree control.', e) 
    9541137 
    9551138 
     
    9901173 
    9911174        # turn on the tree control check box   # TODO: Doesn't work after restore from sleep mode 
    992         if self.vertSplitter.GetSashPosition() > 1: 
     1175        ## if self.vertSplitter.GetSashPosition() > 1: 
     1176        if self.lastSplitterPos > 1: 
    9931177            self.showTreeCtrlMenuItem.Check(1) 
    9941178        else: 
     
    10171201 
    10181202 
    1019         for k in self.iconLookup.keys(): 
    1020             self.iconLookup[k] = (self.iconLookup[k][0], None) 
     1203        for k in self.iconLookupCache.keys(): 
     1204            self.iconLookupCache[k] = (self.iconLookupCache[k][0], None) 
    10211205 
    10221206        gc.collect() 
     
    10311215        self.sleepMode = False 
    10321216 
    1033         self.fillIconLookup(False) 
    10341217        self.buildMainMenu() 
    10351218        self.buildToolbar() 
     
    11021285        "creates a new wiki" 
    11031286 
    1104         self.wikidPadHooks.newWiki(self, wikiName, wikiDir) 
    1105  
    1106         wikiName = string.replace(wikiName, " ", "") 
     1287        self.hooks.newWiki(self, wikiName, wikiDir) 
     1288 
     1289        wikiName = string.replace(wikiName, u" ", u"") 
    11071290        wikiDir = join(wikiDir, wikiName) 
    1108         configFileLoc = join(wikiDir, "%s.wiki" % wikiName) 
     1291        configFileLoc = join(wikiDir, u"%s.wiki" % wikiName) 
    11091292 
    11101293        self.statusBar.SetStatusText(uniToGui(u"Creating Wiki: %s" % wikiName), 0) 
     
    11121295        createIt = True; 
    11131296        if (exists(wikiDir)): 
    1114             dlg=wxMessageDialog(self, "A wiki already exists in '%s', overwrite?" % wikiDir, 
    1115                                'Warning', wxYES_NO) 
     1297            dlg=wxMessageDialog(self, 
     1298                    uniToGui(u"A wiki already exists in '%s', overwrite?" % 
     1299                    wikiDir), u'Warning', wxYES_NO) 
    11161300            result = dlg.ShowModal() 
    11171301            if result == wxID_YES: 
     
    11351319            except WikiDBExistsException: 
    11361320                # The DB exists, should it be overwritten 
    1137                 dlg=wxMessageDialog(self, 'A wiki database already exists in this location, overwrite?', 
    1138                                     'Wiki DB Exists', wxYES_NO) 
     1321                dlg=wxMessageDialog(self, u'A wiki database already exists '+ 
     1322                        u'in this location, overwrite?', 
     1323                        u'Wiki DB Exists', wxYES_NO) 
    11391324                result = dlg.ShowModal() 
    11401325                if result == wxID_YES: 
     
    11681353                # open the new wiki 
    11691354                self.openWiki(configFileLoc) 
     1355                p = self.wikiData.createPage(u"WikiSettings") 
     1356                text = u"""++ Wiki Settings 
     1357 
     1358 
     1359These are your default global settings. 
     1360 
     1361[global.importance.low.color: grey] 
     1362[global.importance.high.bold: true] 
     1363[global.contact.icon: contact] 
     1364[global.todo.bold: true] 
     1365[global.todo.icon: pin] 
     1366[global.wrap: 70] 
     1367 
     1368[icon: cog] 
     1369""" 
     1370                p.save(text, False) 
     1371                p.update(text, False) 
     1372 
     1373                p = self.wikiData.createPage(u"ScratchPad") 
     1374                text = u"++ Scratch Pad\n\n" 
     1375                p.save(text, False) 
     1376                p.update(text, False) 
     1377                 
    11701378                self.editor.GotoPos(self.editor.GetLength()) 
    1171                 self.editor.AddText("\n\n\t* WikiSettings\n") 
    1172  
    1173                 # create the WikiSettings page 
    1174                 self.openWikiPage("WikiSettings", False, False) 
    1175                 self.editor.GotoPos(self.editor.GetLength()) 
    1176                 self.editor.AddText("\n\nThese are your default global settings.\n\n") 
    1177                 self.editor.AddText("[global.importance.low.color: grey]\n") 
    1178                 self.editor.AddText("[global.importance.high.bold: true]\n") 
    1179                 self.editor.AddText("[global.contact.icon: contact]\n") 
    1180                 self.editor.AddText("[global.todo.bold: true]\n") 
    1181                 self.editor.AddText("[global.todo.icon: pin]\n") 
    1182                 self.editor.AddText("[global.wrap: 70]\n") 
    1183                 self.editor.AddText("\n[icon: cog]\n") 
     1379                self.editor.AddText(u"\n\n\t* WikiSettings\n") 
     1380                self.saveCurrentWikiPage() 
     1381                 
     1382 
     1383#                 # create the WikiSettings page 
     1384#                 self.openWikiPage("WikiSettings", False, False) 
     1385#                 self.editor.GotoPos(self.editor.GetLength()) 
     1386#                 self.editor.AddText(u"\n\nThese are your default global settings.\n\n") 
     1387#                 self.editor.AddText(u"[global.importance.low.color: grey]\n") 
     1388#                 self.editor.AddText(u"[global.importance.high.bold: true]\n") 
     1389#                 self.editor.AddText(u"[global.contact.icon: contact]\n") 
     1390#                 self.editor.AddText(u"[global.todo.bold: true]\n") 
     1391#                 self.editor.AddText(u"[global.todo.icon: pin]\n") 
     1392#                 self.editor.AddText(u"[global.wrap: 70]\n") 
     1393#                 self.editor.AddText(u"\n[icon: cog]\n") 
    11841394 
    11851395                # trigger hook 
    1186                 self.wikidPadHooks.createdWiki(self, wikiName, wikiDir) 
     1396                self.hooks.createdWiki(self, wikiName, wikiDir) 
    11871397 
    11881398                # reopen the root 
     
    11931403        "opens up a wiki" 
    11941404 
    1195         self.wikidPadHooks.openWiki(self, wikiConfigFilename) 
     1405        # trigger hooks 
     1406        self.hooks.openWiki(self, wikiConfigFilename) 
    11961407 
    11971408        # Save the state of the currently open wiki, if there was one open 
     
    12081419        # make sure the config exists 
    12091420        if (not exists(wikiConfigFilename)): 
    1210             self.displayErrorMessage("Wiki configuration file '%s' not found" % wikiConfigFilename) 
     1421            self.displayErrorMessage(u"Wiki configuration file '%s' not found" % 
     1422                    wikiConfigFilename) 
    12111423            if wikiConfigFilename in self.wikiHistory: 
    12121424                self.wikiHistory.remove(wikiConfigFilename) 
     
    12251437                parentDir = dirname(dirname(wikiConfigFilename)) 
    12261438                if parentDir: 
    1227                     wikiFiles = [file for file in os.listdir(parentDir) if file.endswith(".wiki")] 
     1439                    wikiFiles = [file for file in os.listdir(parentDir) \ 
     1440                            if file.endswith(".wiki")] 
    12281441                    if len(wikiFiles) > 0: 
    12291442                        wikiWord = basename(wikiConfigFilename) 
     
    12341447                        if windows83Marker != -1: 
    12351448                            wikiWord = wikiWord[0:windows83Marker] 
    1236                             matchingFiles = [file for file in wikiFiles if file.lower().startswith(wikiWord)] 
     1449                            matchingFiles = [file for file in wikiFiles \ 
     1450                                    if file.lower().startswith(wikiWord)] 
    12371451                            if matchingFiles: 
    12381452                                wikiWord = matchingFiles[0] 
     
    12401454                        return 
    12411455            except Exception, ne: 
    1242                 self.displayErrorMessage("Error reading config file '%s'" % wikiConfigFilename, e) 
     1456                self.displayErrorMessage(u"Error reading config file '%s'" % 
     1457                        wikiConfigFilename, e) 
    12431458                traceback.print_exc() 
    12441459                return False 
     
    13421557 
    13431558        # trigger hook 
    1344         self.wikidPadHooks.openedWiki(self, self.wikiName, wikiConfigFilename) 
     1559        self.hooks.openedWiki(self, self.wikiName, wikiConfigFilename) 
    13451560 
    13461561        # return that the wiki was opened successfully 
     
    13861601            forceTreeSyncFromRoot=False, forceReopen=False): 
    13871602 
    1388         self.statusBar.SetStatusText(uniToGui("Opening wiki word '%s'" % 
     1603        self.statusBar.SetStatusText(uniToGui(u"Opening wiki word '%s'" % 
    13891604                wikiWord), 0) 
    13901605 
    13911606        # make sure this is a valid wiki word 
    13921607        if not WikiFormatting.isWikiWord(wikiWord): 
    1393             self.displayErrorMessage("'%s' is an invalid wiki word." % wikiWord) 
     1608            self.displayErrorMessage(u"'%s' is an invalid wiki word." % wikiWord) 
    13941609 
    13951610        # don't reopen the currently open page 
    13961611        if (wikiWord == self.currentWikiWord) and not forceReopen: 
    13971612            # self.tree.buildTreeForWord(self.currentWikiWord)  # TODO Needed? 
    1398             self.statusBar.SetStatusText(uniToGui("Wiki word '%s' already open" % 
     1613            self.statusBar.SetStatusText(uniToGui(u"Wiki word '%s' already open" % 
    13991614                    wikiWord), 0) 
    14001615            return 
     
    14111626 
    14121627        # trigger hook 
    1413         self.wikidPadHooks.openWikiWord(self, wikiWord) 
     1628        self.hooks.openWikiWord(self, wikiWord) 
    14141629 
    14151630        # check if this is an alias 
     
    14271642        except WikiWordNotFoundException, e: 
    14281643            self.currentWikiPage = self.wikiData.createPage(wikiWord) 
    1429             self.wikidPadHooks.newWikiWord(self, wikiWord) 
     1644            # trigger hooks 
     1645            self.hooks.newWikiWord(self, wikiWord) 
    14301646 
    14311647        # set the editor text 
     
    14341650        try: 
    14351651            content = self.currentWikiPage.getContent() 
    1436             self.statusBar.SetStatusText(uniToGui("Opened wiki word '%s'" % 
     1652            self.statusBar.SetStatusText(uniToGui(u"Opened wiki word '%s'" % 
    14371653                    self.currentWikiWord), 0) 
    14381654        except WikiFileNotFoundException, e: 
     
    14811697 
    14821698        # set the title and add the word to the history 
    1483         self.SetTitle(uniToGui("Wiki: %s - %s" % 
     1699        self.SetTitle(uniToGui(u"Wiki: %s - %s" % 
    14841700                (self.wikiName,self.currentWikiWord))) 
    14851701        if addToHistory: self.addToHistory(wikiWord) 
     
    14911707 
    14921708        # trigger hook 
    1493         self.wikidPadHooks.openedWikiWord(self, wikiWord) 
     1709        self.hooks.openedWikiWord(self, wikiWord) 
    14941710 
    14951711 
     
    15051721 
    15061722        dlg = wxSingleChoiceDialog(self, 
    1507                                     "Parent nodes of '%s'" % ofWord, 
    1508                                     "Parent nodes of '%s'" % ofWord, 
     1723                                    uniToGui(u"Parent nodes of '%s'" % ofWord), 
     1724                                    uniToGui(u"Parent nodes of '%s'" % ofWord), 
    15091725                                    parents, 
    15101726                                    wxOK|wxCANCEL) 
     
    15371753        children = self.wikiData.getChildRelationships(ofWord) 
    15381754        dlg = wxSingleChoiceDialog(self, 
    1539                                    "Child nodes of '%s'" % ofWord, 
    1540                                    "Child nodes of '%s'" % ofWord, 
     1755                                   uniToGui(u"Child nodes of '%s'" % ofWord), 
     1756                                   uniToGui(u"Child nodes of '%s'" % ofWord), 
    15411757                                   children, 
    15421758                                   wxOK|wxCANCEL) 
     
    15711787 
    15721788    def goInHistory(self, posDelta=0): 
    1573         if (posDelta < 0 and self.historyPosition > 0) or (posDelta > 0 and self.historyPosition < (len(self.wikiWordHistory)-1)): 
     1789        if (posDelta < 0 and self.historyPosition > 0) or \ 
     1790                (posDelta > 0 and self.historyPosition < (len(self.wikiWordHistory)-1)): 
    15741791            self.historyPosition = self.historyPosition + posDelta 
    15751792        wikiWord = self.wikiWordHistory[self.historyPosition] 
     
    16001817    def viewHistory(self, posDelta=0): 
    16011818        dlg = wxSingleChoiceDialog(self, 
    1602                                    "History", 
    1603                                    "History", 
     1819                                   u"History", 
     1820                                   u"History", 
    16041821                                   self.wikiWordHistory, 
    16051822                                   wxOK|wxCANCEL) 
     
    16231840                                   u"Bookmarks", 
    16241841                                   u"Bookmarks", 
    1625                                    self.wikiData.getWordsWithPropertyValue("bookmarked", "true"), 
     1842                                   self.wikiData.getWordsWithPropertyValue("bookmarked", u"true"), 
    16261843                                   wxOK|wxCANCEL) 
    16271844 
     
    16391856 
    16401857    def saveWikiPage(self, word, page, text): 
    1641         self.statusBar.SetStatusText("Saving WikiPage", 0) 
    1642         self.wikidPadHooks.savingWikiWord(self, word) 
     1858        self.statusBar.SetStatusText(u"Saving WikiPage", 0) 
     1859        # trigger hooks 
     1860        self.hooks.savingWikiWord(self, word) 
    16431861 
    16441862        error = False 
     
    16521870                error = True 
    16531871                dlg=wxMessageDialog(self, 
    1654                         uniToGui(u'There was an error saving the contents of wiki page "%s".\n%s\n\nWould you like to try and save this document again?' % (word, e)), 
     1872                        uniToGui((u'There was an error saving the contents of '+ 
     1873                        u'wiki page "%s".\n%s\n\nWould you like to try and '+ 
     1874                        u'save this document again?') % (word, e)), 
    16551875                                    u'Error Saving!', wxYES_NO) 
    16561876                result = dlg.ShowModal() 
     
    16611881 
    16621882        if not error: 
    1663             self.statusBar.SetStatusText("", 0) 
     1883            self.statusBar.SetStatusText(u"", 0) 
    16641884            self.editor.SetSavePoint() 
    1665             self.wikidPadHooks.savedWikiWord(self, word) 
     1885            # trigger hooks 
     1886            self.hooks.savedWikiWord(self, word) 
    16661887 
    16671888 
     
    17421963            tooltip = None 
    17431964            if self.wikiConfigFilename:  # If a wiki is open 
    1744                 tooltip = "Wiki: %s" % self.wikiName 
     1965                tooltip = u"Wiki: %s" % self.wikiName 
    17451966            else: 
    1746                 tooltip = "Wikidpad" 
     1967                tooltip = u"Wikidpad" 
    17471968 
    17481969            self.tbIcon.SetIcon(wxIcon(os.path.join(self.wikiAppDir, 'icons', 'pwiki.ico'), 
    1749                     wxBITMAP_TYPE_ICO), tooltip) 
     1970                    wxBITMAP_TYPE_ICO), uniToGui(tooltip)) 
    17501971        else: 
    17511972            if self.tbIcon is not None: 
     
    17982019 
    17992020    def showWikiWordRenameDialog(self, wikiWord=None, toWikiWord=None): 
    1800         dlg = wxTextEntryDialog (self, "Rename '%s' to:" % self.currentWikiWord, 
    1801                                  "Rename Wiki Word", self.currentWikiWord, 
    1802                                  wxOK | wxCANCEL) 
     2021        dlg = wxTextEntryDialog (self, uniToGui(u"Rename '%s' to:" % 
     2022                self.currentWikiWord), u"Rename Wiki Word", self.currentWikiWord, 
     2023                wxOK | wxCANCEL) 
    18032024 
    18042025        try: 
     
    18242045 
    18252046        if wikiWord == toWikiWord: 
    1826             self.displayErrorMessage("Can't rename wiki home") 
     2047            self.displayErrorMessage(u"Can't rename wiki home") 
    18272048            return False 
    18282049 
    18292050        if wikiWord == "ScratchPad": 
    1830             self.displayErrorMessage("The scratch pad cannot be renamed.") 
     2051            self.displayErrorMessage(u"The scratch pad cannot be renamed.") 
    18312052            return False 
    18322053 
    18332054        if not WikiFormatting.isWikiWord(toWikiWord): 
    1834             toWikiWord = "[%s]" % toWikiWord 
     2055            toWikiWord = u"[%s]" % toWikiWord 
    18352056        if not WikiFormatting.isWikiWord(toWikiWord): 
    1836             self.displayErrorMessage("'%s' is an invalid WikiWord" % toWikiWord) 
     2057            self.displayErrorMessage(u"'%s' is an invalid WikiWord" % toWikiWord) 
    18372058            return False 
    18382059 
    18392060        if self.wikiData.isDefinedWikiWord(toWikiWord): 
    1840             self.displayErrorMessage("Cannot rename to '%s', word already exists" % toWikiWord) 
     2061            self.displayErrorMessage(u"Cannot rename to '%s', word already exists" % 
     2062                    toWikiWord) 
    18412063            return False 
    18422064 
    1843         dlg=wxMessageDialog(self, "Are you sure you want to rename wiki word '%s' to '%s'?" % (wikiWord, toWikiWord), 
    1844                             'Rename Wiki Word', wxYES_NO) 
     2065        dlg=wxMessageDialog(self, uniToGui((u"Are you sure you want to rename "+ 
     2066                u"wiki word '%s' to '%s'?") % (wikiWord, toWikiWord)), 
     2067                u'Rename Wiki Word', wxYES_NO) 
    18452068        renamed = False 
    18462069        result = dlg.ShowModal() 
     
    18562079                    self.saveCurrentWikiState() 
    18572080                    self.wikiHistory.remove(self.wikiConfigFilename) 
    1858                     renamedConfigFile = join(dirname(self.wikiConfigFilename), "%s.wiki" % toWikiWord) 
     2081                    renamedConfigFile = join(dirname(self.wikiConfigFilename), 
     2082                            u"%s.wiki" % toWikiWord) 
    18592083                    os.rename(self.wikiConfigFilename, renamedConfigFile) 
    18602084                    self.wikiConfigFilename = None 
    18612085                    self.openWiki(renamedConfigFile) 
    18622086 
    1863                 self.wikidPadHooks.renamedWikiWord(self, wikiWord, toWikiWord) 
     2087                # trigger hooks 
     2088                self.hooks.renamedWikiWord(self, wikiWord, toWikiWord)                 
    18642089                self.tree.collapse() 
    18652090                self.openWikiPage(toWikiWord, forceTreeSyncFromRoot=True) 
     
    19032128 
    19042129        if wikiWord == "ScratchPad": 
    1905             self.displayErrorMessage("The scratch pad cannot be deleted") 
     2130            self.displayErrorMessage(u"The scratch pad cannot be deleted") 
    19062131            return 
    19072132 
    1908         dlg=wxMessageDialog(self, "Are you sure you want to delete wiki word '%s'?" % wikiWord, 
    1909                             'Delete Wiki Word', wxYES_NO) 
     2133        dlg=wxMessageDialog(self, 
     2134                uniToGui(u"Are you sure you want to delete wiki word '%s'?" % wikiWord), 
     2135                'Delete Wiki Word', wxYES_NO) 
    19102136        result = dlg.ShowModal() 
    19112137        if result == wxID_YES: 
     
    19132139            try: 
    19142140                self.wikiData.deleteWord(wikiWord) 
    1915                 self.wikidPadHooks.deletedWikiWord(self, wikiWord) 
     2141                # trigger hooks 
     2142                self.hooks.deletedWikiWord(self, wikiWord) 
    19162143                if wikiWord == self.currentWikiWord: 
    19172144                    self.tree.collapse() 
     
    19302157        self.lastFindPos = -1 
    19312158        data = wxFindReplaceData() 
    1932         dlg = wxFindReplaceDialog(self, data, "Find and Replace", wxFR_REPLACEDIALOG) 
     2159        dlg = wxFindReplaceDialog(self, data, u"Find and Replace", wxFR_REPLACEDIALOG) 
    19332160        dlg.data = data 
    19342161        dlg.Show(True) 
    19352162 
    19362163    def showReplaceTextByWikiwordDialog(self): 
    1937         wikiWord = guiToUni(wxGetTextFromUser("Replace text by WikiWord:", 
    1938                 "Replace by Wiki Word", self.currentWikiWord, self)) 
     2164        wikiWord = guiToUni(wxGetTextFromUser(u"Replace text by WikiWord:", 
     2165                u"Replace by Wiki Word", self.currentWikiWord, self)) 
    19392166 
    19402167        if wikiWord: 
    19412168            if not WikiFormatting.isWikiWord(wikiWord): 
    1942                 wikiWord = "[%s]" % wikiWord 
     2169                wikiWord = u"[%s]" % wikiWord 
    19432170            if not WikiFormatting.isWikiWord(wikiWord): 
    19442171                self.displayErrorMessage(u"'%s' is an invalid WikiWord" % wikiWord) 
     
    20032230        dlg.Destroy() 
    20042231 
    2005         if result == wxID_OK: 
    2006             pass 
    2007  
    2008  
    2009     def exportWiki(self, type): 
    2010         dlg = wxDirDialog(self, "Select Export Directory", self.getLastActiveDir(), style=wxDD_DEFAULT_STYLE|wxDD_NEW_DIR_BUTTON) 
    2011         if dlg.ShowModal() == wxID_OK: 
    2012             exporter = HtmlExporter(self) 
    2013             dir = dlg.GetPath() 
    2014             exporter.export(type, dir) 
    2015             self.configuration.set("main", "last_active_dir", dir) 
    2016  
    2017     # TODO: Should be more general to support other databases 
     2232#         if result == wxID_OK: 
     2233#             pass 
     2234 
     2235 
     2236    EXPORT_PARAMS = { 
     2237            GUI_ID.MENU_EXPORT_WHOLE_AS_PAGE: 
     2238                    (Exporters.HtmlXmlExporter, u"html_single", ()), 
     2239            GUI_ID.MENU_EXPORT_WHOLE_AS_PAGES: 
     2240                    (Exporters.HtmlXmlExporter, u"html_multi", ()), 
     2241            GUI_ID.MENU_EXPORT_WORD_AS_PAGE: 
     2242                    (Exporters.HtmlXmlExporter, u"html_single", ()), 
     2243            GUI_ID.MENU_EXPORT_SUB_AS_PAGE: 
     2244                    (Exporters.HtmlXmlExporter, u"html_single", ()), 
     2245            GUI_ID.MENU_EXPORT_SUB_AS_PAGES: 
     2246                    (Exporters.HtmlXmlExporter, u"html_multi", ()), 
     2247            GUI_ID.MENU_EXPORT_WHOLE_AS_XML: 
     2248                    (Exporters.HtmlXmlExporter, u"xml", ()), 
     2249            GUI_ID.MENU_EXPORT_WHOLE_AS_RAW: 
     2250                    (Exporters.TextExporter, u"raw_files", (1,)) 
     2251            } 
     2252 
     2253 
     2254    def OnExportWiki(self, evt): 
     2255        dest = wxDirSelector(u"Select Export Directory", self.getLastActiveDir(), 
     2256        wxDD_DEFAULT_STYLE|wxDD_NEW_DIR_BUTTON, parent=self) 
     2257#         dlg = wxDirDialog(self, "Select Export Directory", 
     2258#                 self.getLastActiveDir(), 
     2259#                 style=wxDD_DEFAULT_STYLE|wxDD_NEW_DIR_BUTTON) 
     2260 
     2261        if dest: 
     2262            typ = evt.GetId() 
     2263             
     2264            if typ in (GUI_ID.MENU_EXPORT_WHOLE_AS_PAGE, 
     2265                    GUI_ID.MENU_EXPORT_WHOLE_AS_PAGES, 
     2266                    GUI_ID.MENU_EXPORT_WHOLE_AS_XML, 
     2267                    GUI_ID.MENU_EXPORT_WHOLE_AS_RAW): 
     2268                wordList = self.wikiData.getAllDefinedPageNames() 
     2269                 
     2270            elif typ in (GUI_ID.MENU_EXPORT_SUB_AS_PAGE, 
     2271                    GUI_ID.MENU_EXPORT_SUB_AS_PAGES): 
     2272                wordList = self.wikiData.getAllSubWords( 
     2273                        self.currentWikiWord, True) 
     2274            else: 
     2275                wordList = (self.currentWikiWord,) 
     2276                 
     2277            expclass, exptype, addopt = self.EXPORT_PARAMS[typ] 
     2278             
     2279            expclass().export(self, self.wikiData, wordList, exptype, dest, 
     2280                    addopt) 
     2281 
     2282 
     2283            self.configuration.set("main", "last_active_dir", dest) 
     2284 
     2285 
    20182286    def rebuildWiki(self, skipConfirm = False): 
    20192287        if not skipConfirm: 
    2020             result = wxMessageBox("Are you sure you want to rebuild this wiki? You may want to backup your data first!", 
    2021                     'Rebuild wiki', wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION, self) 
     2288            result = wxMessageBox(u"Are you sure you want to rebuild this wiki? "+ 
     2289                    u"You may want to backup your data first!", 
     2290                    u'Rebuild wiki', wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION, self) 
    20222291 
    20232292        if skipConfirm or result == wxYES : 
    2024             # get all of the wikiWords 
    2025             wikiWords = self.wikiData.getAllPageNamesFromDisk()   # Replace this call 
    2026             # get the saved searches 
    2027             searches = self.wikiData.getSavedSearches() 
    2028  
    2029             # close nulls the wikiConfigFilename var, so save it 
    2030             wikiConfigFilename = self.wikiConfigFilename 
    2031             # first close the existing wiki 
    2032             self.closeWiki() 
    2033  
    2034             progress = wxProgressDialog("Rebuilding wiki", "Rebuilding wiki", 
    2035                                         len(wikiWords) + len(searches) + 1, self, wxPD_APP_MODAL) 
    2036  
    20372293            try: 
    2038                 step = 1 
    2039                 # recreate the db 
    2040                 progress.Update(step, "Recreating database") 
    2041                 createWikiDB(self.wikiName, self.dataDir, True) 
    2042                 # reopen the wiki 
    2043                 wikiData = WikiData(self, self.dataDir) 
    2044                 # re-save all of the pages 
    2045                 for wikiWord in wikiWords: 
    2046                     progress.Update(step, "Rebuilding %s" % wikiWord) 
    2047                     wikiPage = wikiData.createPage(wikiWord) 
    2048                     wikiData.updatePageEntry(wikiWord) 
    2049                     wikiPage.update(wikiPage.getContent(), False) 
    2050                     step = step + 1 
    2051  
    2052                 # resave searches 
    2053                 for search in searches: 
    2054                     progress.Update(step, "Reading search %s" % search) 
    2055                     wikiData.saveSearch(search) 
    2056  
    2057                 wikiData.close() 
    2058                 progress.Destroy() 
    2059  
     2294                self.wikiData.rebuildWiki( 
     2295                        wxGuiProgressHandler(u"Rebuilding wiki", u"Rebuilding wiki", 
     2296                        0, self)) 
     2297 
     2298                self.tree.collapse() 
     2299                self.openWikiPage(self.currentWikiWord, forceTreeSyncFromRoot=True) 
    20602300            except Exception, e: 
    2061                 self.displayErrorMessage("Error rebuilding wiki", e) 
     2301                self.displayErrorMessage(u"Error rebuilding wiki", e) 
    20622302                traceback.print_exc() 
    2063             self.openWiki(wikiConfigFilename) 
    20642303 
    20652304 
     
    20812320    def displayMessage(self, title, str): 
    20822321        "pops up a dialog box" 
    2083         dlg_m = wxMessageDialog(self, "%s" % str, title, wxOK) 
     2322        dlg_m = wxMessageDialog(self, uniToGui(u"%s" % str), title, wxOK) 
    20842323        dlg_m.ShowModal() 
    20852324        dlg_m.Destroy() 
    20862325 
    20872326 
    2088     def displayErrorMessage(self, errorStr, e=""): 
     2327    def displayErrorMessage(self, errorStr, e=u""): 
    20892328        "pops up a error dialog box" 
    2090         dlg_m = wxMessageDialog(self, uniToGui("%s. %s." % (errorStr, e)), 'Error!', wxOK) 
     2329        dlg_m = wxMessageDialog(self, uniToGui(u"%s. %s." % (errorStr, e)), 'Error!', wxOK) 
    20912330        dlg_m.ShowModal() 
    20922331        dlg_m.Destroy() 
    20932332        try: 
    2094             self.statusBar.SetStatusText(errorStr, 0) 
     2333            self.statusBar.SetStatusText(uniToGui(errorStr), 0) 
    20952334        except: 
    20962335            pass 
     
    21042343 
    21052344    def getWikiPageTitle(self, wikiWord): 
    2106         title = re.sub(r'([A-Z\xc0-\xde]{2,})([a-z\xdf-\xff])', r'\1 \2', wikiWord) 
    2107         title = re.sub(r'([a-z\xdf-\xff])([A-Z\xc0-\xde])', r'\1 \2', title) 
     2345        title = re.sub(ur'([A-Z\xc0-\xde]{2,})([a-z\xdf-\xff])', r'\1 \2', wikiWord) 
     2346        title = re.sub(ur'([a-z\xdf-\xff])([A-Z\xc0-\xde])', r'\1 \2', title) 
    21082347        if title.startswith("["): 
    21092348            title = title[1:len(title)-1] 
     
    21192358 
    21202359    def OnWikiOpen(self, event): 
    2121         dlg = wxFileDialog(self, "Choose a Wiki to open", self.getLastActiveDir(), "", "*.wiki", wxOPEN) 
     2360        dlg = wxFileDialog(self, u"Choose a Wiki to open", 
     2361                self.getLastActiveDir(), "", "*.wiki", wxOPEN) 
    21222362        if dlg.ShowModal() == wxID_OK: 
    21232363            self.openWiki(abspath(dlg.GetPath())) 
     
    21262366 
    21272367    def OnWikiNew(self, event): 
    2128         dlg = wxTextEntryDialog (self, "Name for new wiki (must be in the form of a WikiWord):", 
    2129                                  "Create New Wiki", "MyWiki", wxOK | wxCANCEL) 
     2368        dlg = wxTextEntryDialog (self, 
     2369                u"Name for new wiki (must be in the form of a WikiWord):", 
     2370                u"Create New Wiki", u"MyWiki", wxOK | wxCANCEL) 
    21302371 
    21312372        if dlg.ShowModal() == wxID_OK: 
     
    21342375            # make sure this is a valid wiki word 
    21352376            if wikiName.find(u' ') == -1 and WikiFormatting.isWikiWord(wikiName): 
    2136                 dlg = wxDirDialog(self, "Directory to store new wiki", self.getLastActiveDir(), style=wxDD_DEFAULT_STYLE|wxDD_NEW_DIR_BUTTON) 
     2377                dlg = wxDirDialog(self, u"Directory to store new wiki", 
     2378                        self.getLastActiveDir(), 
     2379                        style=wxDD_DEFAULT_STYLE|wxDD_NEW_DIR_BUTTON) 
    21372380                if dlg.ShowModal() == wxID_OK: 
    21382381                    try: 
    21392382                        self.newWiki(wikiName, dlg.GetPath()) 
    21402383                    except IOError, e: 
    2141                         self.displayErrorMessage('There was an error while creating your new Wiki.', e) 
     2384                        self.displayErrorMessage(u'There was an error while '+ 
     2385                                'creating your new Wiki.', e) 
    21422386            else: 
    2143                 self.displayErrorMessage("'%s' is an invalid WikiWord. There must be no spaces and mixed caps" % wikiName) 
     2387                self.displayErrorMessage((u"'%s' is an invalid WikiWord. "+ 
     2388                u"There must be no spaces and mixed caps") % wikiName) 
    21442389 
    21452390        dlg.Destroy() 
     
    22492494 
    22502495        # trigger hook 
    2251         self.wikidPadHooks.exit(self) 
     2496        self.hooks.exit(self) 
    22522497 
    22532498        wxTheClipboard.Flush() 
     
    23412586            self.EndModal(wxID_CANCEL) 
    23422587        else: 
    2343             self.pWiki.displayErrorMessage("Invalid search string, can't save as view") 
     2588            self.pWiki.displayErrorMessage(u"Invalid search string, can't save as view") 
    23442589 
    23452590    def OnListBox(self, evt): 
     
    24642709            <tr><td width="30%" align="right"><font size="3"><b>Email:</b></font></td><td nowrap><font size="3">mbutscher@gmx.de</font></td></tr> 
    24652710            <tr><td width="30%" align="right"><font size="3"><b>URL:</b></font></td><td nowrap><font size="3">http://www.mbutscher.nextdesigns.net/software.html</font></td></tr> 
     2711            <tr><td width="30%" align="right">&nbsp;</td></tr> 
     2712            <tr><td width="30%" align="right"><font size="3"><b>Author:</b></font></td><td nowrap><font size="3">Gerhard Reitmayr</font></td></tr> 
     2713            <tr><td width="30%" align="right"><font size="3"><b>Email:</b></font></td><td nowrap><font size="3">gerhard.reitmayr@gmail.com</font></td></tr> 
    24662714        </table> 
    24672715    </center>