refactoring
authorEdouard Tisserant
Mon, 07 May 2012 18:47:29 +0200
changeset 717 1c23952dbde1
parent 716 180e4a7d945c
child 718 5d4dc150b956
refactoring
Beremiz.py
ConfigTree.py
LPCBeremiz.py
confnodes/.cvsignore
confnodes/__init__.py
confnodes/c_ext/.cvsignore
confnodes/c_ext/CFileEditor.py
confnodes/c_ext/README
confnodes/c_ext/__init__.py
confnodes/c_ext/c_ext.py
confnodes/c_ext/cext_xsd.xsd
confnodes/canfestival/.cvsignore
confnodes/canfestival/NetworkEditor.py
confnodes/canfestival/README
confnodes/canfestival/SlaveEditor.py
confnodes/canfestival/__init__.py
confnodes/canfestival/canfestival.py
confnodes/canfestival/cf_runtime.c
confnodes/canfestival/config_utils.py
confnodes/canfestival/test_config/eds/PEAK MicroMod.eds
confnodes/canfestival/test_config/master.od
confnodes/canfestival/test_config/nodelist.cpj
confnodes/canfestival/test_config/result.txt
confnodes/python/PythonEditor.py
confnodes/python/README
confnodes/python/__init__.py
confnodes/python/modules/__init__.py
confnodes/python/modules/svgui/README
confnodes/python/modules/svgui/__init__.py
confnodes/python/modules/svgui/livesvg.js
confnodes/python/modules/svgui/pous.xml
confnodes/python/modules/svgui/pyjs/__init__.py
confnodes/python/modules/svgui/pyjs/build.py
confnodes/python/modules/svgui/pyjs/jsonrpc/README.txt
confnodes/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py
confnodes/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py
confnodes/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py
confnodes/python/modules/svgui/pyjs/lib/_pyjs.js
confnodes/python/modules/svgui/pyjs/lib/json.js
confnodes/python/modules/svgui/pyjs/lib/pyjslib.py
confnodes/python/modules/svgui/pyjs/lib/sys.py
confnodes/python/modules/svgui/pyjs/pyjs.py
confnodes/python/modules/svgui/svgui.py
confnodes/python/modules/svgui/svgui_server.py
confnodes/python/modules/svgui/svguilib.py
confnodes/python/modules/wxglade_hmi/README
confnodes/python/modules/wxglade_hmi/__init__.py
confnodes/python/modules/wxglade_hmi/wxglade_hmi.py
confnodes/python/plc_python.c
confnodes/python/pous.xml
confnodes/python/python.py
confnodes/python/python_xsd.xsd
connectors/LPC/LPCBootObject.py
connectors/LPC/LPCObject.py
connectors/LPC/__init__.py
connectors/PYRO/__init__.py
connectors/__init__.py
plugger.py
plugins/.cvsignore
plugins/__init__.py
plugins/c_ext/.cvsignore
plugins/c_ext/CFileEditor.py
plugins/c_ext/README
plugins/c_ext/__init__.py
plugins/c_ext/c_ext.py
plugins/c_ext/cext_xsd.xsd
plugins/canfestival/.cvsignore
plugins/canfestival/NetworkEditor.py
plugins/canfestival/README
plugins/canfestival/SlaveEditor.py
plugins/canfestival/__init__.py
plugins/canfestival/canfestival.py
plugins/canfestival/cf_runtime.c
plugins/canfestival/config_utils.py
plugins/canfestival/test_config/eds/PEAK MicroMod.eds
plugins/canfestival/test_config/master.od
plugins/canfestival/test_config/nodelist.cpj
plugins/canfestival/test_config/result.txt
plugins/python/PythonEditor.py
plugins/python/README
plugins/python/__init__.py
plugins/python/modules/__init__.py
plugins/python/modules/svgui/README
plugins/python/modules/svgui/__init__.py
plugins/python/modules/svgui/livesvg.js
plugins/python/modules/svgui/pous.xml
plugins/python/modules/svgui/pyjs/__init__.py
plugins/python/modules/svgui/pyjs/build.py
plugins/python/modules/svgui/pyjs/jsonrpc/README.txt
plugins/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py
plugins/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py
plugins/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py
plugins/python/modules/svgui/pyjs/lib/_pyjs.js
plugins/python/modules/svgui/pyjs/lib/json.js
plugins/python/modules/svgui/pyjs/lib/pyjslib.py
plugins/python/modules/svgui/pyjs/lib/sys.py
plugins/python/modules/svgui/pyjs/pyjs.py
plugins/python/modules/svgui/svgui.py
plugins/python/modules/svgui/svgui_server.py
plugins/python/modules/svgui/svguilib.py
plugins/python/modules/wxglade_hmi/README
plugins/python/modules/wxglade_hmi/__init__.py
plugins/python/modules/wxglade_hmi/wxglade_hmi.py
plugins/python/plc_python.c
plugins/python/pous.xml
plugins/python/python.py
plugins/python/python_xsd.xsd
runtime/PLCObject.py
targets/LPC/__init__.py
targets/Xenomai/__init__.py
targets/toolchain_gcc.py
targets/toolchain_makefile.py
tests/canopen_master/canopen@canfestival/baseconfnode.xml
tests/canopen_master/canopen@canfestival/baseplugin.xml
tests/canopen_master/canopen@canfestival/confnode.xml
tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseconfnode.xml
tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseplugin.xml
tests/canopen_master/canopen@canfestival/master@CanOpenNode/confnode.xml
tests/canopen_master/canopen@canfestival/master@CanOpenNode/plugin.xml
tests/canopen_master/canopen@canfestival/plugin.xml
tests/canopen_slave/canopen@canfestival/baseconfnode.xml
tests/canopen_slave/canopen@canfestival/baseplugin.xml
tests/canopen_slave/canopen@canfestival/confnode.xml
tests/canopen_slave/canopen@canfestival/plugin.xml
tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseconfnode.xml
tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseplugin.xml
tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/confnode.xml
tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/plugin.xml
tests/python/python@python/baseconfnode.xml
tests/python/python@python/baseplugin.xml
tests/svgui/python@python/baseconfnode.xml
tests/svgui/python@python/baseplugin.xml
tests/svgui/python@python/svgui@svgui/baseconfnode.xml
tests/svgui/python@python/svgui@svgui/baseplugin.xml
tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseconfnode.xml
tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseplugin.xml
tests/wxGlade/python@python/baseconfnode.xml
tests/wxGlade/python@python/baseplugin.xml
--- a/Beremiz.py	Thu May 03 19:02:34 2012 +0200
+++ b/Beremiz.py	Mon May 07 18:47:29 2012 +0200
@@ -146,13 +146,13 @@
 import TextCtrlAutoComplete, cPickle
 from BrowseValuesLibraryDialog import BrowseValuesLibraryDialog
 import types, time, re, platform, time, traceback, commands
-from plugger import PluginsRoot, MiniTextControler, MATIEC_ERROR_MODEL
+from ConfigTree import ConfigTreeRoot, MiniTextControler, MATIEC_ERROR_MODEL
 from wxPopen import ProcessLogger
 
 from docutils import *
 from PLCOpenEditor import IDEFrame, AppendMenu, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, SCALING, PAGETITLES, USE_AUI
 from PLCOpenEditor import EditorPanel, Viewer, TextViewer, GraphicViewer, ResourceEditor, ConfigurationEditor, DataTypeEditor
-from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
 
 SCROLLBAR_UNIT = 10
 WINDOW_COLOUR = wx.Colour(240,240,240)
@@ -378,18 +378,18 @@
 [ID_FILEMENURECENTPROJECTS,
 ] = [wx.NewId() for _init_ctrls in range(1)]
 
-PLUGINMENU_POSITION = 3
+CONFNODEMENU_POSITION = 3
 
 class Beremiz(IDEFrame):
 	
     def _init_coll_MenuBar_Menus(self, parent):
         IDEFrame._init_coll_MenuBar_Menus(self, parent)
         
-        parent.Insert(pos=PLUGINMENU_POSITION, 
-                      menu=self.PluginMenu, title=_(u'&Plugin'))
+        parent.Insert(pos=CONFNODEMENU_POSITION, 
+                      menu=self.ConfNodeMenu, title=_(u'&ConfNode'))
     
     def _init_utils(self):
-        self.PluginMenu = wx.Menu(title='')
+        self.ConfNodeMenu = wx.Menu(title='')
         self.RecentProjectsMenu = wx.Menu(title='')
         
         IDEFrame._init_utils(self)
@@ -451,25 +451,25 @@
     
     def _init_coll_PLCConfigMainSizer_Items(self, parent):
         parent.AddSizer(self.PLCParamsSizer, 0, border=10, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
-        parent.AddSizer(self.PluginTreeSizer, 0, border=10, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT)
+        parent.AddSizer(self.ConfNodeTreeSizer, 0, border=10, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT)
         
     def _init_coll_PLCConfigMainSizer_Growables(self, parent):
         parent.AddGrowableCol(0)
         parent.AddGrowableRow(1)
     
-    def _init_coll_PluginTreeSizer_Growables(self, parent):
+    def _init_coll_ConfNodeTreeSizer_Growables(self, parent):
         parent.AddGrowableCol(0)
         parent.AddGrowableCol(1)
         
     def _init_beremiz_sizers(self):
         self.PLCConfigMainSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=2, vgap=2)
         self.PLCParamsSizer = wx.BoxSizer(wx.VERTICAL)
-        #self.PluginTreeSizer = wx.FlexGridSizer(cols=3, hgap=0, rows=0, vgap=2)
-        self.PluginTreeSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=0, vgap=2)
+        #self.ConfNodeTreeSizer = wx.FlexGridSizer(cols=3, hgap=0, rows=0, vgap=2)
+        self.ConfNodeTreeSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=0, vgap=2)
         
         self._init_coll_PLCConfigMainSizer_Items(self.PLCConfigMainSizer)
         self._init_coll_PLCConfigMainSizer_Growables(self.PLCConfigMainSizer)
-        self._init_coll_PluginTreeSizer_Growables(self.PluginTreeSizer)
+        self._init_coll_ConfNodeTreeSizer_Growables(self.ConfNodeTreeSizer)
         
         self.PLCConfig.SetSizer(self.PLCConfigMainSizer)
         
@@ -485,8 +485,8 @@
                                 ("Build",    wx.WXK_F11)]:
             def OnMethodGen(obj,meth):
                 def OnMethod(evt):
-                    if obj.PluginRoot is not None:
-                       obj.PluginRoot.CallMethod('_'+meth)
+                    if obj.CTR is not None:
+                       obj.CTR.CallMethod('_'+meth)
                     wx.CallAfter(self.RefreshAll)
                 return OnMethod
             newid = wx.NewId()
@@ -516,7 +516,7 @@
         
         self._init_beremiz_sizers()
 
-    def __init__(self, parent, projectOpen=None, buildpath=None, plugin_root=None, debug=True):
+    def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True):
         IDEFrame.__init__(self, parent, debug)
         self.Log = LogPseudoFile(self.LogConsole,self.RiseLogConsole)
         
@@ -530,7 +530,7 @@
         
         self.LastPanelSelected = None
         
-        self.PluginInfos = {}
+        self.ConfNodeInfos = {}
         
         # Define Tree item icon list
         self.LocationImageList = wx.ImageList(16, 16)
@@ -538,7 +538,7 @@
         
         # Icons for location items
         for imgname, itemtype in [
-            ("CONFIGURATION", LOCATION_PLUGIN),
+            ("CONFIGURATION", LOCATION_CONFNODE),
             ("RESOURCE",      LOCATION_MODULE),
             ("PROGRAM",       LOCATION_GROUP),
             ("VAR_INPUT",     LOCATION_VAR_INPUT),
@@ -555,9 +555,9 @@
                 projectOpen = None
         
         if projectOpen is not None and os.path.isdir(projectOpen):
-            self.PluginRoot = PluginsRoot(self, self.Log)
-            self.Controler = self.PluginRoot
-            result = self.PluginRoot.LoadProject(projectOpen, buildpath)
+            self.CTR = ConfigTreeRoot(self, self.Log)
+            self.Controler = self.CTR
+            result = self.CTR.LoadProject(projectOpen, buildpath)
             if not result:
                 self.LibraryPanel.SetControler(self.Controler)
                 self.RefreshConfigRecentProjects(os.path.abspath(projectOpen))
@@ -567,19 +567,19 @@
                 self.ResetView()
                 self.ShowErrorMessage(result)
         else:
-            self.PluginRoot = plugin_root
-            self.Controler = plugin_root
-            if plugin_root is not None:
+            self.CTR = ctr
+            self.Controler = ctr
+            if ctr is not None:
                 self.LibraryPanel.SetControler(self.Controler)
                 self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
                 self.RefreshAll()
         if self.EnableDebug:
-            self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+            self.DebugVariablePanel.SetDataProducer(self.CTR)
         
         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
         
         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
-        self.RefreshPluginMenu()
+        self.RefreshConfNodeMenu()
         self.LogConsole.SetFocus()
 
     def RiseLogConsole(self):
@@ -587,9 +587,9 @@
         
     def RefreshTitle(self):
         name = _("Beremiz")
-        if self.PluginRoot is not None:
-            projectname = self.PluginRoot.GetProjectName()
-            if self.PluginRoot.ProjectTestModified():
+        if self.CTR is not None:
+            projectname = self.CTR.GetProjectName()
+            if self.CTR.ProjectTestModified():
                 projectname = "~%s~" % projectname
             self.SetTitle("%s - %s" % (name, projectname))
         else:
@@ -640,20 +640,20 @@
         event.Skip()
 
     def SearchLineForError(self):
-        if self.PluginRoot is not None:
+        if self.CTR is not None:
             text = self.LogConsole.GetRange(0, self.LogConsole.GetInsertionPoint())
             line = self.LogConsole.GetLineText(len(text.splitlines()) - 1)
             result = MATIEC_ERROR_MODEL.match(line)
             if result is not None:
                 first_line, first_column, last_line, last_column, error = result.groups()
-                infos = self.PluginRoot.ShowError(self.Log,
+                infos = self.CTR.ShowError(self.Log,
                                                   (int(first_line), int(first_column)), 
                                                   (int(last_line), int(last_column)))
 	
     ## Function displaying an Error dialog in PLCOpenEditor.
     #  @return False if closing cancelled.
     def CheckSaveBeforeClosing(self, title=_("Close Project")):
-        if self.PluginRoot.ProjectTestModified():
+        if self.CTR.ProjectTestModified():
             dialog = wx.MessageDialog(self,
                                       _("There are changes, do you want to save?"),
                                       title,
@@ -661,7 +661,7 @@
             answer = dialog.ShowModal()
             dialog.Destroy()
             if answer == wx.ID_YES:
-                self.PluginRoot.SaveProject()
+                self.CTR.SaveProject()
             elif answer == wx.ID_CANCEL:
                 return False
         return True
@@ -674,33 +674,33 @@
                                  ResourceEditor, 
                                  ConfigurationEditor, 
                                  DataTypeEditor))):
-            return ("plugin", tab.Controler.PlugFullName())
+            return ("confnode", tab.Controler.PlugFullName())
         elif (isinstance(tab, TextViewer) and 
               (tab.Controler is None or isinstance(tab.Controler, MiniTextControler))):
-            return ("plugin", None, tab.GetInstancePath())
+            return ("confnode", None, tab.GetInstancePath())
         else:
             return IDEFrame.GetTabInfos(self, tab)
     
     def LoadTab(self, notebook, page_infos):
-        if page_infos[0] == "plugin":
+        if page_infos[0] == "confnode":
             if page_infos[1] is None:
-                plugin = self.PluginRoot
+                confnode = self.CTR
             else:
-                plugin = self.PluginRoot.GetChildByName(page_infos[1])
-            return notebook.GetPageIndex(plugin._OpenView(*page_infos[2:]))
+                confnode = self.CTR.GetChildByName(page_infos[1])
+            return notebook.GetPageIndex(confnode._OpenView(*page_infos[2:]))
         else:
             return IDEFrame.LoadTab(self, notebook, page_infos)
     
     def OnCloseFrame(self, event):
-        if self.PluginRoot is None or self.CheckSaveBeforeClosing(_("Close Application")):
-            if self.PluginRoot is not None:
-                self.PluginRoot.KillDebugThread()
+        if self.CTR is None or self.CheckSaveBeforeClosing(_("Close Application")):
+            if self.CTR is not None:
+                self.CTR.KillDebugThread()
             self.KillLocalRuntime()
             
             self.SaveLastState()
             
-            if self.PluginRoot is not None:
-                project_path = os.path.realpath(self.PluginRoot.GetProjectPath())
+            if self.CTR is not None:
+                project_path = os.path.realpath(self.CTR.GetProjectPath())
             else:
                 project_path = ""
             self.Config.Write("currenteditedproject", project_path)    
@@ -732,7 +732,7 @@
         self.RefreshRecentProjectsMenu()
         
         MenuToolBar = self.Panes["MenuToolBar"]
-        if self.PluginRoot is not None:
+        if self.CTR is not None:
             selected = self.TabsOpened.GetSelection()
             if selected >= 0:
                 graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer)
@@ -754,7 +754,7 @@
                 self.FileMenu.Enable(wx.ID_PRINT, False)
                 MenuToolBar.EnableTool(wx.ID_PRINT, False)
             self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
-            project_modified = self.PluginRoot.ProjectTestModified()
+            project_modified = self.CTR.ProjectTestModified()
             self.FileMenu.Enable(wx.ID_SAVE, project_modified)
             MenuToolBar.EnableTool(wx.ID_SAVE, project_modified)
             self.FileMenu.Enable(wx.ID_SAVEAS, True)
@@ -789,7 +789,7 @@
     
     def GenerateOpenRecentProjectFunction(self, projectpath):
         def OpenRecentProject(event):
-            if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+            if self.CTR is not None and not self.CheckSaveBeforeClosing():
                 return
             
             self.OpenProject(projectpath)
@@ -810,28 +810,28 @@
                 if callback is not None:
                     self.Bind(wx.EVT_MENU, callback, id=id)
     
-    def RefreshPluginMenu(self):
-        if self.PluginRoot is not None:
+    def RefreshConfNodeMenu(self):
+        if self.CTR is not None:
             selected = self.TabsOpened.GetSelection()
             if selected >= 0:
                 panel = self.TabsOpened.GetPage(selected)
             else:
                 panel = None
             if panel != self.LastPanelSelected:
-                for i in xrange(self.PluginMenu.GetMenuItemCount()):
-                    item = self.PluginMenu.FindItemByPosition(0)
-                    self.PluginMenu.Delete(item.GetId())
+                for i in xrange(self.ConfNodeMenu.GetMenuItemCount()):
+                    item = self.ConfNodeMenu.FindItemByPosition(0)
+                    self.ConfNodeMenu.Delete(item.GetId())
                 self.LastPanelSelected = panel
                 if panel is not None:
-                    items = panel.GetPluginMenuItems()
+                    items = panel.GetConfNodeMenuItems()
                 else:
                     items = []
-                self.MenuBar.EnableTop(PLUGINMENU_POSITION, len(items) > 0)
-                self.GenerateMenuRecursive(items, self.PluginMenu)
+                self.MenuBar.EnableTop(CONFNODEMENU_POSITION, len(items) > 0)
+                self.GenerateMenuRecursive(items, self.ConfNodeMenu)
             if panel is not None:
-                panel.RefreshPluginMenu(self.PluginMenu)
-        else:
-            self.MenuBar.EnableTop(PLUGINMENU_POSITION, False)
+                panel.RefreshConfNodeMenu(self.ConfNodeMenu)
+        else:
+            self.MenuBar.EnableTop(CONFNODEMENU_POSITION, False)
         self.MenuBar.UpdateMenus()
     
     def RefreshScrollBars(self):
@@ -850,15 +850,15 @@
         self.Freeze()
         self.ClearSizer(self.PLCParamsSizer)
         
-        if self.PluginRoot is not None:    
+        if self.CTR is not None:    
             plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
-            if self.PluginRoot.PlugTestModified():
+            if self.CTR.PlugTestModified():
                 bkgdclr = CHANGED_TITLE_COLOUR
             else:
                 bkgdclr = TITLE_COLOUR
                 
-            if self.PluginRoot not in self.PluginInfos:
-                self.PluginInfos[self.PluginRoot] = {"right_visible" : False}
+            if self.CTR not in self.ConfNodeInfos:
+                self.ConfNodeInfos[self.CTR] = {"right_visible" : False}
             
             plcwindow.SetBackgroundColour(TITLE_COLOUR)
             plcwindow.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
@@ -869,15 +869,15 @@
             
             st = wx.StaticText(plcwindow, -1)
             st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
-            st.SetLabel(self.PluginRoot.GetProjectName())
+            st.SetLabel(self.CTR.GetProjectName())
             plcwindowsizer.AddWindow(st, 0, border=5, flag=wx.ALL|wx.ALIGN_CENTER)
             
             addbutton_id = wx.NewId()
             addbutton = wx.lib.buttons.GenBitmapButton(id=addbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Add.png')),
-                  name='AddPluginButton', parent=plcwindow, pos=wx.Point(0, 0),
+                  name='AddConfNodeButton', parent=plcwindow, pos=wx.Point(0, 0),
                   size=wx.Size(16, 16), style=wx.NO_BORDER)
-            addbutton.SetToolTipString(_("Add a sub plugin"))
-            addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddPluginMenu(self.PluginRoot), id=addbutton_id)
+            addbutton.SetToolTipString(_("Add a sub confnode"))
+            addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddConfNodeMenu(self.CTR), id=addbutton_id)
             plcwindowsizer.AddWindow(addbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER)
     
             plcwindowmainsizer = wx.BoxSizer(wx.VERTICAL)
@@ -886,7 +886,7 @@
             plcwindowbuttonsizer = wx.BoxSizer(wx.HORIZONTAL)
             plcwindowmainsizer.AddSizer(plcwindowbuttonsizer, 0, border=0, flag=wx.ALIGN_CENTER)
             
-            msizer = self.GenerateMethodButtonSizer(self.PluginRoot, plcwindow, not self.PluginInfos[self.PluginRoot]["right_visible"])
+            msizer = self.GenerateMethodButtonSizer(self.CTR, plcwindow, not self.ConfNodeInfos[self.CTR]["right_visible"])
             plcwindowbuttonsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW)
             
             paramswindow = wx.Panel(plcwindow, -1, size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
@@ -897,10 +897,10 @@
             psizer = wx.BoxSizer(wx.HORIZONTAL)
             paramswindow.SetSizer(psizer)
             
-            plugin_infos = self.PluginRoot.GetParamsAttributes()
-            self.RefreshSizerElement(paramswindow, psizer, self.PluginRoot, plugin_infos, None, False)
-            
-            if not self.PluginInfos[self.PluginRoot]["right_visible"]:
+            confnode_infos = self.CTR.GetParamsAttributes()
+            self.RefreshSizerElement(paramswindow, psizer, self.CTR, confnode_infos, None, False)
+            
+            if not self.ConfNodeInfos[self.CTR]["right_visible"]:
                 paramswindow.Hide()
             
             minimizebutton_id = wx.NewId()
@@ -909,7 +909,7 @@
                   size=wx.Size(24, 24), style=wx.NO_BORDER)
             make_genbitmaptogglebutton_flat(minimizebutton)
             minimizebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Minimize.png')))
-            minimizebutton.SetToggle(self.PluginInfos[self.PluginRoot]["right_visible"])
+            minimizebutton.SetToggle(self.ConfNodeInfos[self.CTR]["right_visible"])
             plcwindowbuttonsizer.AddWindow(minimizebutton, 0, border=5, flag=wx.ALL)
             
             def togglewindow(event):
@@ -918,32 +918,32 @@
                     msizer.SetCols(1)
                 else:
                     paramswindow.Hide()
-                    msizer.SetCols(len(self.PluginRoot.PluginMethods))
-                self.PluginInfos[self.PluginRoot]["right_visible"] = minimizebutton.GetToggle()
+                    msizer.SetCols(len(self.CTR.ConfNodeMethods))
+                self.ConfNodeInfos[self.CTR]["right_visible"] = minimizebutton.GetToggle()
                 self.PLCConfigMainSizer.Layout()
                 self.RefreshScrollBars()
                 event.Skip()
             minimizebutton.Bind(wx.EVT_BUTTON, togglewindow, id=minimizebutton_id)
         
-            self.PluginInfos[self.PluginRoot]["main"] = plcwindow
-            self.PluginInfos[self.PluginRoot]["params"] = paramswindow
+            self.ConfNodeInfos[self.CTR]["main"] = plcwindow
+            self.ConfNodeInfos[self.CTR]["params"] = paramswindow
             
         self.PLCConfigMainSizer.Layout()
         self.RefreshScrollBars()
         self.Thaw()
 
-    def GenerateEnableButton(self, parent, sizer, plugin):
-        enabled = plugin.PlugEnabled()
+    def GenerateEnableButton(self, parent, sizer, confnode):
+        enabled = confnode.PlugEnabled()
         if enabled is not None:
             enablebutton_id = wx.NewId()
             enablebutton = wx.lib.buttons.GenBitmapToggleButton(id=enablebutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Disabled.png')),
                   name='EnableButton', parent=parent, size=wx.Size(16, 16), pos=wx.Point(0, 0), style=0)#wx.NO_BORDER)
-            enablebutton.SetToolTipString(_("Enable/Disable this plugin"))
+            enablebutton.SetToolTipString(_("Enable/Disable this confnode"))
             make_genbitmaptogglebutton_flat(enablebutton)
             enablebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Enabled.png')))
             enablebutton.SetToggle(enabled)
             def toggleenablebutton(event):
-                res = self.SetPluginParamsAttribute(plugin, "BaseParams.Enabled", enablebutton.GetToggle())
+                res = self.SetConfNodeParamsAttribute(confnode, "BaseParams.Enabled", enablebutton.GetToggle())
                 enablebutton.SetToggle(res)
                 event.Skip()
             enablebutton.Bind(wx.EVT_BUTTON, toggleenablebutton, id=enablebutton_id)
@@ -951,23 +951,23 @@
         else:
             sizer.AddSpacer(wx.Size(16, 16))
     
-    def GenerateMethodButtonSizer(self, plugin, parent, horizontal = True):
+    def GenerateMethodButtonSizer(self, confnode, parent, horizontal = True):
         normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"])
         mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"])
         if horizontal:
-            msizer = wx.FlexGridSizer(cols=len(plugin.PluginMethods))
+            msizer = wx.FlexGridSizer(cols=len(confnode.ConfNodeMethods))
         else:
             msizer = wx.FlexGridSizer(cols=1)
-        for plugin_method in plugin.PluginMethods:
-            if "method" in plugin_method and plugin_method.get("shown",True):
+        for confnode_method in confnode.ConfNodeMethods:
+            if "method" in confnode_method and confnode_method.get("shown",True):
                 id = wx.NewId()
-                label = plugin_method["name"]
+                label = confnode_method["name"]
                 button = GenBitmapTextButton(id=id, parent=parent,
-                    bitmap=wx.Bitmap(Bpath( "%s.png"%plugin_method.get("bitmap", os.path.join("images", "Unknown")))), label=label, 
+                    bitmap=wx.Bitmap(Bpath( "%s.png"%confnode_method.get("bitmap", os.path.join("images", "Unknown")))), label=label, 
                     name=label, pos=wx.DefaultPosition, style=wx.NO_BORDER)
                 button.SetFont(normal_bt_font)
-                button.SetToolTipString(plugin_method["tooltip"])
-                button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(plugin, plugin_method["method"]), id=id)
+                button.SetToolTipString(confnode_method["tooltip"])
+                button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode, confnode_method["method"]), id=id)
                 # a fancy underline on mouseover
                 def setFontStyle(b, s):
                     def fn(event):
@@ -978,12 +978,12 @@
                 button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font))
                 button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font))
                 #hack to force size to mini
-                if not plugin_method.get("enabled",True):
+                if not confnode_method.get("enabled",True):
                     button.Disable()
                 msizer.AddWindow(button, 0, border=0, flag=wx.ALIGN_CENTER)
         return msizer
 
-    def GenerateParamsPanel(self, plugin, bkgdclr, top_offset=0):
+    def GenerateParamsPanel(self, confnode, bkgdclr, top_offset=0):
         rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
         rightwindow.SetBackgroundColour(bkgdclr)
         
@@ -995,7 +995,7 @@
         rightwindowsizer.AddGrowableRow(0)
         rightwindowmainsizer.AddSizer(rightwindowsizer, 0, border=0, flag=wx.GROW)
         
-        msizer = self.GenerateMethodButtonSizer(plugin, rightwindow, not self.PluginInfos[plugin]["right_visible"])
+        msizer = self.GenerateMethodButtonSizer(confnode, rightwindow, not self.ConfNodeInfos[confnode]["right_visible"])
         rightwindowsizer.AddSizer(msizer, 0, border=top_offset, flag=wx.TOP|wx.GROW)
         
         rightparamssizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -1006,15 +1006,15 @@
         
         psizer = wx.BoxSizer(wx.VERTICAL)
         paramswindow.SetSizer(psizer)
-        self.PluginInfos[plugin]["params"] = paramswindow
+        self.ConfNodeInfos[confnode]["params"] = paramswindow
         
         rightparamssizer.AddWindow(paramswindow, 0, border=5, flag=wx.ALL)
         
-        plugin_infos = plugin.GetParamsAttributes()
-        if len(plugin_infos) > 0:
-            self.RefreshSizerElement(paramswindow, psizer, plugin, plugin_infos, None, False)
-            
-            if not self.PluginInfos[plugin]["right_visible"]:
+        confnode_infos = confnode.GetParamsAttributes()
+        if len(confnode_infos) > 0:
+            self.RefreshSizerElement(paramswindow, psizer, confnode, confnode_infos, None, False)
+            
+            if not self.ConfNodeInfos[confnode]["right_visible"]:
                 paramswindow.Hide()
             
             rightminimizebutton_id = wx.NewId()
@@ -1023,7 +1023,7 @@
                   size=wx.Size(24, 24), style=wx.NO_BORDER)
             make_genbitmaptogglebutton_flat(rightminimizebutton)
             rightminimizebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Minimize.png')))
-            rightminimizebutton.SetToggle(self.PluginInfos[plugin]["right_visible"])
+            rightminimizebutton.SetToggle(self.ConfNodeInfos[confnode]["right_visible"])
             rightparamssizer.AddWindow(rightminimizebutton, 0, border=5, flag=wx.ALL)
                         
             def togglerightwindow(event):
@@ -1032,8 +1032,8 @@
                     msizer.SetCols(1)
                 else:
                     rightparamssizer.Hide(0)
-                    msizer.SetCols(len(plugin.PluginMethods))
-                self.PluginInfos[plugin]["right_visible"] = rightminimizebutton.GetToggle()
+                    msizer.SetCols(len(confnode.ConfNodeMethods))
+                self.ConfNodeInfos[confnode]["right_visible"] = rightminimizebutton.GetToggle()
                 self.PLCConfigMainSizer.Layout()
                 self.RefreshScrollBars()
                 event.Skip()
@@ -1042,58 +1042,58 @@
         return rightwindow
     
 
-    def RefreshPluginTree(self):
+    def RefreshConfNodeTree(self):
         self.Freeze()
-        self.ClearSizer(self.PluginTreeSizer)
-        if self.PluginRoot is not None:
-            for child in self.PluginRoot.IECSortedChilds():
+        self.ClearSizer(self.ConfNodeTreeSizer)
+        if self.CTR is not None:
+            for child in self.CTR.IECSortedChilds():
                 self.GenerateTreeBranch(child)
-                if not self.PluginInfos[child]["expanded"]:
-                    self.CollapsePlugin(child)
+                if not self.ConfNodeInfos[child]["expanded"]:
+                    self.CollapseConfNode(child)
         self.PLCConfigMainSizer.Layout()
         self.RefreshScrollBars()
         self.Thaw()
 
-    def SetPluginParamsAttribute(self, plugin, *args, **kwargs):
-        res, StructChanged = plugin.SetParamsAttribute(*args, **kwargs)
+    def SetConfNodeParamsAttribute(self, confnode, *args, **kwargs):
+        res, StructChanged = confnode.SetParamsAttribute(*args, **kwargs)
         if StructChanged:
-            wx.CallAfter(self.RefreshPluginTree)
-        else:
-            if plugin == self.PluginRoot:
+            wx.CallAfter(self.RefreshConfNodeTree)
+        else:
+            if confnode == self.CTR:
                 bkgdclr = CHANGED_TITLE_COLOUR
                 items = ["main", "params"]
             else:
                 bkgdclr = CHANGED_WINDOW_COLOUR
                 items = ["left", "right", "params"]
             for i in items:
-                self.PluginInfos[plugin][i].SetBackgroundColour(bkgdclr)
-                self.PluginInfos[plugin][i].Refresh()
+                self.ConfNodeInfos[confnode][i].SetBackgroundColour(bkgdclr)
+                self.ConfNodeInfos[confnode][i].Refresh()
         self._Refresh(TITLE, FILEMENU)
         return res
 
-    def ExpandPlugin(self, plugin, force = False):
-        for child in self.PluginInfos[plugin]["children"]:
-            self.PluginInfos[child]["left"].Show()
-            self.PluginInfos[child]["right"].Show()
-            if force or self.PluginInfos[child]["expanded"]:
-                self.ExpandPlugin(child, force)
+    def ExpandConfNode(self, confnode, force = False):
+        for child in self.ConfNodeInfos[confnode]["children"]:
+            self.ConfNodeInfos[child]["left"].Show()
+            self.ConfNodeInfos[child]["right"].Show()
+            if force or self.ConfNodeInfos[child]["expanded"]:
+                self.ExpandConfNode(child, force)
                 if force:
-                    self.PluginInfos[child]["expanded"] = True
-        locations_infos = self.PluginInfos[plugin].get("locations_infos", None)
+                    self.ConfNodeInfos[child]["expanded"] = True
+        locations_infos = self.ConfNodeInfos[confnode].get("locations_infos", None)
         if locations_infos is not None:
             if force or locations_infos["root"]["expanded"]:
                 self.ExpandLocation(locations_infos, "root", force)
                 if force:
                     locations_infos["root"]["expanded"] = True
     
-    def CollapsePlugin(self, plugin, force = False):
-        for child in self.PluginInfos[plugin]["children"]:
-            self.PluginInfos[child]["left"].Hide()
-            self.PluginInfos[child]["right"].Hide()
-            self.CollapsePlugin(child, force)
+    def CollapseConfNode(self, confnode, force = False):
+        for child in self.ConfNodeInfos[confnode]["children"]:
+            self.ConfNodeInfos[child]["left"].Hide()
+            self.ConfNodeInfos[child]["right"].Hide()
+            self.CollapseConfNode(child, force)
             if force:
-                self.PluginInfos[child]["expanded"] = False
-        locations_infos = self.PluginInfos[plugin].get("locations_infos", None)
+                self.ConfNodeInfos[child]["expanded"] = False
+        locations_infos = self.ConfNodeInfos[confnode].get("locations_infos", None)
         if locations_infos is not None:
             self.CollapseLocation(locations_infos, "root", force)
             if force:
@@ -1129,30 +1129,30 @@
         if locations_infos["root"]["left"] is not None and refresh_size:
             self.RefreshTreeCtrlSize(locations_infos["root"]["left"])
     
-    def GenerateTreeBranch(self, plugin):
+    def GenerateTreeBranch(self, confnode):
         leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
-        if plugin.PlugTestModified():
+        if confnode.PlugTestModified():
             bkgdclr=CHANGED_WINDOW_COLOUR
         else:
             bkgdclr=WINDOW_COLOUR
 
         leftwindow.SetBackgroundColour(bkgdclr)
         
-        if not self.PluginInfos.has_key(plugin):
-            self.PluginInfos[plugin] = {"expanded" : False, "right_visible" : False}
-            
-        self.PluginInfos[plugin]["children"] = plugin.IECSortedChilds()
-        plugin_locations = []
-        if len(self.PluginInfos[plugin]["children"]) == 0:
-            plugin_locations = plugin.GetVariableLocationTree()["children"]
-            if not self.PluginInfos[plugin].has_key("locations_infos"):
-                self.PluginInfos[plugin]["locations_infos"] = {"root": {"expanded" : False}}
-            
-            self.PluginInfos[plugin]["locations_infos"]["root"]["left"] = None
-            self.PluginInfos[plugin]["locations_infos"]["root"]["right"] = None
-            self.PluginInfos[plugin]["locations_infos"]["root"]["children"] = []
-        
-        self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
+        if not self.ConfNodeInfos.has_key(confnode):
+            self.ConfNodeInfos[confnode] = {"expanded" : False, "right_visible" : False}
+            
+        self.ConfNodeInfos[confnode]["children"] = confnode.IECSortedChilds()
+        confnode_locations = []
+        if len(self.ConfNodeInfos[confnode]["children"]) == 0:
+            confnode_locations = confnode.GetVariableLocationTree()["children"]
+            if not self.ConfNodeInfos[confnode].has_key("locations_infos"):
+                self.ConfNodeInfos[confnode]["locations_infos"] = {"root": {"expanded" : False}}
+            
+            self.ConfNodeInfos[confnode]["locations_infos"]["root"]["left"] = None
+            self.ConfNodeInfos[confnode]["locations_infos"]["root"]["right"] = None
+            self.ConfNodeInfos[confnode]["locations_infos"]["root"]["children"] = []
+        
+        self.ConfNodeTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
         
         leftwindowsizer = wx.FlexGridSizer(cols=1, rows=2)
         leftwindowsizer.AddGrowableCol(0)
@@ -1171,38 +1171,38 @@
         rolesizer = wx.BoxSizer(wx.HORIZONTAL)
         leftsizer.AddSizer(rolesizer, 0, border=0, flag=wx.GROW|wx.RIGHT)
         
-        #self.GenerateEnableButton(leftwindow, rolesizer, plugin)
+        #self.GenerateEnableButton(leftwindow, rolesizer, confnode)
 
         roletext = wx.StaticText(leftwindow, -1)
-        roletext.SetLabel(plugin.PlugHelp)
+        roletext.SetLabel(confnode.PlugHelp)
         rolesizer.AddWindow(roletext, 0, border=5, flag=wx.RIGHT|wx.ALIGN_LEFT)
         
-        plugin_IECChannel = plugin.BaseParams.getIEC_Channel()
+        confnode_IECChannel = confnode.BaseParams.getIEC_Channel()
         
         iecsizer = wx.BoxSizer(wx.HORIZONTAL)
         leftsizer.AddSizer(iecsizer, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
 
         st = wx.StaticText(leftwindow, -1)
         st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
-        st.SetLabel(plugin.GetFullIEC_Channel())
+        st.SetLabel(confnode.GetFullIEC_Channel())
         iecsizer.AddWindow(st, 0, border=0, flag=0)
 
         updownsizer = wx.BoxSizer(wx.VERTICAL)
         iecsizer.AddSizer(updownsizer, 0, border=5, flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL)
 
-        if plugin_IECChannel > 0:
+        if confnode_IECChannel > 0:
             ieccdownbutton_id = wx.NewId()
             ieccdownbutton = wx.lib.buttons.GenBitmapButton(id=ieccdownbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'IECCDown.png')),
                   name='IECCDownButton', parent=leftwindow, pos=wx.Point(0, 0),
                   size=wx.Size(16, 16), style=wx.NO_BORDER)
-            ieccdownbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(plugin, plugin_IECChannel - 1), id=ieccdownbutton_id)
+            ieccdownbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(confnode, confnode_IECChannel - 1), id=ieccdownbutton_id)
             updownsizer.AddWindow(ieccdownbutton, 0, border=0, flag=wx.ALIGN_LEFT)
 
         ieccupbutton_id = wx.NewId()
         ieccupbutton = wx.lib.buttons.GenBitmapTextButton(id=ieccupbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'IECCUp.png')),
               name='IECCUpButton', parent=leftwindow, pos=wx.Point(0, 0),
               size=wx.Size(16, 16), style=wx.NO_BORDER)
-        ieccupbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(plugin, plugin_IECChannel + 1), id=ieccupbutton_id)
+        ieccupbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(confnode, confnode_IECChannel + 1), id=ieccupbutton_id)
         updownsizer.AddWindow(ieccupbutton, 0, border=0, flag=wx.ALIGN_LEFT)
 
         adddeletesizer = wx.BoxSizer(wx.VERTICAL)
@@ -1210,19 +1210,19 @@
 
         deletebutton_id = wx.NewId()
         deletebutton = wx.lib.buttons.GenBitmapButton(id=deletebutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Delete.png')),
-              name='DeletePluginButton', parent=leftwindow, pos=wx.Point(0, 0),
+              name='DeleteConfNodeButton', parent=leftwindow, pos=wx.Point(0, 0),
               size=wx.Size(16, 16), style=wx.NO_BORDER)
-        deletebutton.SetToolTipString(_("Delete this plugin"))
-        deletebutton.Bind(wx.EVT_BUTTON, self.GetDeleteButtonFunction(plugin), id=deletebutton_id)
+        deletebutton.SetToolTipString(_("Delete this confnode"))
+        deletebutton.Bind(wx.EVT_BUTTON, self.GetDeleteButtonFunction(confnode), id=deletebutton_id)
         adddeletesizer.AddWindow(deletebutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER)
 
-        if len(plugin.PlugChildsTypes) > 0:
+        if len(confnode.PlugChildsTypes) > 0:
             addbutton_id = wx.NewId()
             addbutton = wx.lib.buttons.GenBitmapButton(id=addbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Add.png')),
-                  name='AddPluginButton', parent=leftwindow, pos=wx.Point(0, 0),
+                  name='AddConfNodeButton', parent=leftwindow, pos=wx.Point(0, 0),
                   size=wx.Size(16, 16), style=wx.NO_BORDER)
-            addbutton.SetToolTipString(_("Add a sub plugin"))
-            addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddPluginMenu(plugin), id=addbutton_id)
+            addbutton.SetToolTipString(_("Add a sub confnode"))
+            addbutton.Bind(wx.EVT_BUTTON, self.Gen_AddConfNodeMenu(confnode), id=addbutton_id)
             adddeletesizer.AddWindow(addbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER)
         
         expandbutton_id = wx.NewId()
@@ -1234,27 +1234,27 @@
         expandbutton.SetUseFocusIndicator(False)
         expandbutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'minus.png')))
             
-        if len(self.PluginInfos[plugin]["children"]) > 0:
-            expandbutton.SetToggle(self.PluginInfos[plugin]["expanded"])
+        if len(self.ConfNodeInfos[confnode]["children"]) > 0:
+            expandbutton.SetToggle(self.ConfNodeInfos[confnode]["expanded"])
             def togglebutton(event):
                 if expandbutton.GetToggle():
-                    self.ExpandPlugin(plugin)
+                    self.ExpandConfNode(confnode)
                 else:
-                    self.CollapsePlugin(plugin)
-                self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+                    self.CollapseConfNode(confnode)
+                self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
                 self.PLCConfigMainSizer.Layout()
                 self.RefreshScrollBars()
                 event.Skip()
             expandbutton.Bind(wx.EVT_BUTTON, togglebutton, id=expandbutton_id)
-        elif len(plugin_locations) > 0:
-            locations_infos = self.PluginInfos[plugin]["locations_infos"]
+        elif len(confnode_locations) > 0:
+            locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
             expandbutton.SetToggle(locations_infos["root"]["expanded"])
             def togglebutton(event):
                 if expandbutton.GetToggle():
                     self.ExpandLocation(locations_infos, "root")
                 else:
                     self.CollapseLocation(locations_infos, "root")
-                self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+                self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
                 locations_infos["root"]["expanded"] = expandbutton.GetToggle()
                 self.PLCConfigMainSizer.Layout()
                 self.RefreshScrollBars()
@@ -1267,22 +1267,22 @@
         tc_id = wx.NewId()
         tc = wx.TextCtrl(leftwindow, tc_id, size=wx.Size(150, 25), style=wx.NO_BORDER)
         tc.SetFont(wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
-        tc.ChangeValue(plugin.MandatoryParams[1].getName())
-        tc.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(tc, plugin, "BaseParams.Name"), id=tc_id)
+        tc.ChangeValue(confnode.MandatoryParams[1].getName())
+        tc.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(tc, confnode, "BaseParams.Name"), id=tc_id)
         iecsizer.AddWindow(tc, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
         
-        rightwindow = self.GenerateParamsPanel(plugin, bkgdclr, 8)
-        self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
-        
-        self.PluginInfos[plugin]["left"] = leftwindow
-        self.PluginInfos[plugin]["right"] = rightwindow
-        for child in self.PluginInfos[plugin]["children"]:
+        rightwindow = self.GenerateParamsPanel(confnode, bkgdclr, 8)
+        self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+        
+        self.ConfNodeInfos[confnode]["left"] = leftwindow
+        self.ConfNodeInfos[confnode]["right"] = rightwindow
+        for child in self.ConfNodeInfos[confnode]["children"]:
             self.GenerateTreeBranch(child)
-            if not self.PluginInfos[child]["expanded"]:
-                self.CollapsePlugin(child)
-        
-        if len(plugin_locations) > 0:
-            locations_infos = self.PluginInfos[plugin]["locations_infos"]
+            if not self.ConfNodeInfos[child]["expanded"]:
+                self.CollapseConfNode(child)
+        
+        if len(confnode_locations) > 0:
+            locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
             treectrl = wx.TreeCtrl(self.PLCConfig, -1, size=wx.DefaultSize, 
                                    style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.NO_BORDER|wx.TR_HIDE_ROOT|wx.TR_NO_LINES|wx.TR_LINES_AT_ROOT)
             treectrl.SetImageList(self.LocationImageList)
@@ -1292,19 +1292,19 @@
             treectrl.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheelTreeCtrl)
             
             treectrl.AddRoot("")
-            self.PluginTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
+            self.ConfNodeTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
             
             rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
             rightwindow.SetBackgroundColour(wx.WHITE)
-            self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+            self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
             
             locations_infos["root"]["left"] = treectrl
             locations_infos["root"]["right"] = rightwindow
-            for location in plugin_locations:
+            for location in confnode_locations:
                 locations_infos["root"]["children"].append("root.%s" % location["name"])
                 self.GenerateLocationTreeBranch(treectrl, treectrl.GetRootItem(), locations_infos, "root", location)
             if locations_infos["root"]["expanded"]:
-                self.PluginTreeSizer.Layout()
+                self.ConfNodeTreeSizer.Layout()
                 self.ExpandLocation(locations_infos, "root")
             else:
                 self.RefreshTreeCtrlSize(treectrl)
@@ -1399,38 +1399,38 @@
     
     def RefreshAll(self):
         self.RefreshPLCParams()
-        self.RefreshPluginTree()
-        
-    def GetItemChannelChangedFunction(self, plugin, value):
-        def OnPluginTreeItemChannelChanged(event):
-            res = self.SetPluginParamsAttribute(plugin, "BaseParams.IEC_Channel", value)
+        self.RefreshConfNodeTree()
+        
+    def GetItemChannelChangedFunction(self, confnode, value):
+        def OnConfNodeTreeItemChannelChanged(event):
+            res = self.SetConfNodeParamsAttribute(confnode, "BaseParams.IEC_Channel", value)
             event.Skip()
-        return OnPluginTreeItemChannelChanged
-    
-    def _GetAddPluginFunction(self, name, plugin):
-        def OnPluginMenu(event):
-            wx.CallAfter(self.AddPlugin, name, plugin)
-        return OnPluginMenu
-    
-    def Gen_AddPluginMenu(self, plugin):
-        def AddPluginMenu(event):
+        return OnConfNodeTreeItemChannelChanged
+    
+    def _GetAddConfNodeFunction(self, name, confnode):
+        def OnConfNodeMenu(event):
+            wx.CallAfter(self.AddConfNode, name, confnode)
+        return OnConfNodeMenu
+    
+    def Gen_AddConfNodeMenu(self, confnode):
+        def AddConfNodeMenu(event):
             main_menu = wx.Menu(title='')
-            if len(plugin.PlugChildsTypes) > 0:
-                for name, XSDClass, help in plugin.PlugChildsTypes:
+            if len(confnode.PlugChildsTypes) > 0:
+                for name, XSDClass, help in confnode.PlugChildsTypes:
                     new_id = wx.NewId()
                     main_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text=_("Append ")+help)
-                    self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name, plugin), id=new_id)
+                    self.Bind(wx.EVT_MENU, self._GetAddConfNodeFunction(name, confnode), id=new_id)
             self.PopupMenuXY(main_menu)
             main_menu.Destroy()
-        return AddPluginMenu
-    
-    def GetButtonCallBackFunction(self, plugin, method):
-        """ Generate the callbackfunc for a given plugin method"""
+        return AddConfNodeMenu
+    
+    def GetButtonCallBackFunction(self, confnode, method):
+        """ Generate the callbackfunc for a given confnode method"""
         def OnButtonClick(event):
             # Disable button to prevent re-entrant call 
             event.GetEventObject().Disable()
             # Call
-            getattr(plugin,method)()
+            getattr(confnode,method)()
             # Re-enable button 
             event.GetEventObject().Enable()
             # Trigger refresh on Idle
@@ -1438,20 +1438,20 @@
             event.Skip()
         return OnButtonClick
     
-    def GetChoiceCallBackFunction(self, choicectrl, plugin, path):
+    def GetChoiceCallBackFunction(self, choicectrl, confnode, path):
         def OnChoiceChanged(event):
-            res = self.SetPluginParamsAttribute(plugin, path, choicectrl.GetStringSelection())
+            res = self.SetConfNodeParamsAttribute(confnode, path, choicectrl.GetStringSelection())
             choicectrl.SetStringSelection(res)
             event.Skip()
         return OnChoiceChanged
     
-    def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, plugin, path):
+    def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, confnode, path):
         def OnChoiceContentChanged(event):
-            res = self.SetPluginParamsAttribute(plugin, path, choicectrl.GetStringSelection())
+            res = self.SetConfNodeParamsAttribute(confnode, path, choicectrl.GetStringSelection())
             if wx.VERSION < (2, 8, 0):
                 self.ParamsPanel.Freeze()
                 choicectrl.SetStringSelection(res)
-                infos = self.PluginRoot.GetParamsAttributes(path)
+                infos = self.CTR.GetParamsAttributes(path)
                 staticbox = staticboxsizer.GetStaticBox()
                 staticbox.SetLabel("%(name)s - %(value)s"%infos)
                 self.RefreshSizerElement(self.ParamsPanel, staticboxsizer, infos["children"], "%s.%s"%(path, infos["name"]), selected=selected)
@@ -1463,27 +1463,27 @@
             event.Skip()
         return OnChoiceContentChanged
     
-    def GetTextCtrlCallBackFunction(self, textctrl, plugin, path):
+    def GetTextCtrlCallBackFunction(self, textctrl, confnode, path):
         def OnTextCtrlChanged(event):
-            res = self.SetPluginParamsAttribute(plugin, path, textctrl.GetValue())
+            res = self.SetConfNodeParamsAttribute(confnode, path, textctrl.GetValue())
             if res != textctrl.GetValue():
                 textctrl.ChangeValue(res)
             event.Skip()
         return OnTextCtrlChanged
     
-    def GetCheckBoxCallBackFunction(self, chkbx, plugin, path):
+    def GetCheckBoxCallBackFunction(self, chkbx, confnode, path):
         def OnCheckBoxChanged(event):
-            res = self.SetPluginParamsAttribute(plugin, path, chkbx.IsChecked())
+            res = self.SetConfNodeParamsAttribute(confnode, path, chkbx.IsChecked())
             chkbx.SetValue(res)
             event.Skip()
         return OnCheckBoxChanged
     
-    def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, plugin, path):
+    def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, confnode, path):
         infos = [value_infos]
         def OnBrowseButton(event):
             dialog = BrowseValuesLibraryDialog(self, name, library, infos[0])
             if dialog.ShowModal() == wx.ID_OK:
-                value, value_infos = self.SetPluginParamsAttribute(plugin, path, dialog.GetValueInfos())
+                value, value_infos = self.SetConfNodeParamsAttribute(confnode, path, dialog.GetValueInfos())
                 textctrl.ChangeValue(value)
                 infos[0] = value_infos
             dialog.Destroy()
@@ -1502,7 +1502,7 @@
         for staticbox in staticboxes:
             staticbox.Destroy()
                 
-    def RefreshSizerElement(self, parent, sizer, plugin, elements, path, clean = True):
+    def RefreshSizerElement(self, parent, sizer, confnode, elements, path, clean = True):
         if clean:
             if wx.VERSION < (2, 8, 0):
                 self.ClearSizer(sizer)
@@ -1524,7 +1524,7 @@
                     sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW|wx.TOP)
                 else:
                     sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW)
-                self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path)
+                self.RefreshSizerElement(parent, staticboxsizer, confnode, element_infos["children"], element_path)
             else:
                 boxsizer = wx.FlexGridSizer(cols=3, rows=1)
                 boxsizer.AddGrowableCol(1)
@@ -1561,7 +1561,7 @@
                         browse_boxsizer.AddWindow(button, 0, border=0, flag=0)
                         button.Bind(wx.EVT_BUTTON, 
                                     self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"], 
-                                                                   value_infos, plugin, element_path), 
+                                                                   value_infos, confnode, element_path), 
                                     id=button_id)
                     else:
                         combobox = wx.ComboBox(id=id, name=element_infos["name"], parent=parent, 
@@ -1579,12 +1579,12 @@
                                 pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0)
                             staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL)
                             sizer.AddSizer(staticboxsizer, 0, border=5, flag=wx.GROW|wx.BOTTOM)
-                            self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path)
-                            callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, plugin, element_path)
+                            self.RefreshSizerElement(parent, staticboxsizer, confnode, element_infos["children"], element_path)
+                            callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, confnode, element_path)
                         else:
                             for choice in element_infos["type"]:
                                 combobox.Append(choice)
-                            callback = self.GetChoiceCallBackFunction(combobox, plugin, element_path)
+                            callback = self.GetChoiceCallBackFunction(combobox, confnode, element_path)
                         if element_infos["value"] is None:
                             combobox.SetStringSelection("")
                         else:
@@ -1603,7 +1603,7 @@
                     boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
                     if element_infos["value"] is not None:
                         spinctrl.SetValue(element_infos["value"])
-                    spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path), id=id)
+                    spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, confnode, element_path), id=id)
                 else:
                     if element_infos["type"] == "boolean":
                         checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=parent, 
@@ -1611,7 +1611,7 @@
                         boxsizer.AddWindow(checkbox, 0, border=0, flag=0)
                         if element_infos["value"] is not None:
                             checkbox.SetValue(element_infos["value"])
-                        checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, plugin, element_path), id=id)
+                        checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, confnode, element_path), id=id)
                     elif element_infos["type"] in ["unsignedLong", "long","integer"]:
                         if element_infos["type"].startswith("unsigned"):
                             scmin = 0
@@ -1624,7 +1624,7 @@
                         boxsizer.AddWindow(spinctrl, 0, border=0, flag=0)
                         if element_infos["value"] is not None:
                             spinctrl.SetValue(element_infos["value"])
-                        spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path), id=id)
+                        spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, confnode, element_path), id=id)
                     else:
                         choices = cPickle.loads(str(self.Config.Read(element_path, cPickle.dumps([""]))))
                         textctrl = TextCtrlAutoComplete.TextCtrlAutoComplete(id=id, 
@@ -1640,15 +1640,15 @@
                         boxsizer.AddWindow(textctrl, 0, border=0, flag=0)
                         if element_infos["value"] is not None:
                             textctrl.ChangeValue(str(element_infos["value"]))
-                        textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path))
+                        textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, confnode, element_path))
             first = False
     
     def ResetView(self):
         IDEFrame.ResetView(self)
-        self.PluginInfos = {}
-        if self.PluginRoot is not None:
-            self.PluginRoot.CloseProject()
-        self.PluginRoot = None
+        self.ConfNodeInfos = {}
+        if self.CTR is not None:
+            self.CTR.CloseProject()
+        self.CTR = None
         self.Log.flush()
         if self.EnableDebug:
             self.DebugVariablePanel.SetDataProducer(None)
@@ -1662,7 +1662,7 @@
         self.Config.Flush()
     
     def OnNewProjectMenu(self, event):
-        if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+        if self.CTR is not None and not self.CheckSaveBeforeClosing():
             return
         
         if not self.Config.HasEntry("lastopenedfolder"):
@@ -1676,15 +1676,15 @@
             self.Config.Write("lastopenedfolder", os.path.dirname(projectpath))
             self.Config.Flush()
             self.ResetView()
-            plugin_root = PluginsRoot(self, self.Log)
-            result = plugin_root.NewProject(projectpath)
+            ctr = ConfigTreeRoot(self, self.Log)
+            result = ctr.NewProject(projectpath)
             if not result:
-                self.PluginRoot = plugin_root
-                self.Controler = self.PluginRoot
+                self.CTR = ctr
+                self.Controler = self.CTR
                 self.LibraryPanel.SetControler(self.Controler)
                 self.RefreshConfigRecentProjects(projectpath)
                 if self.EnableDebug:
-                    self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+                    self.DebugVariablePanel.SetDataProducer(self.CTR)
                 self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
                 self.RefreshAll()
             else:
@@ -1694,7 +1694,7 @@
         dialog.Destroy()
     
     def OnOpenProjectMenu(self, event):
-        if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+        if self.CTR is not None and not self.CheckSaveBeforeClosing():
             return
         
         if not self.Config.HasEntry("lastopenedfolder"):
@@ -1712,14 +1712,14 @@
             self.Config.Write("lastopenedfolder", os.path.dirname(projectpath))
             self.Config.Flush()
             self.ResetView()
-            self.PluginRoot = PluginsRoot(self, self.Log)
-            self.Controler = self.PluginRoot
-            result = self.PluginRoot.LoadProject(projectpath)
+            self.CTR = ConfigTreeRoot(self, self.Log)
+            self.Controler = self.CTR
+            result = self.CTR.LoadProject(projectpath)
             if not result:
                 self.LibraryPanel.SetControler(self.Controler)
                 self.RefreshConfigRecentProjects(projectpath)
                 if self.EnableDebug:
-                    self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
+                    self.DebugVariablePanel.SetDataProducer(self.CTR)
                 self.LoadProjectOrganization()
                 self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
                 self.RefreshAll()
@@ -1731,7 +1731,7 @@
         self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU)
     
     def OnCloseProjectMenu(self, event):
-        if self.PluginRoot is not None and not self.CheckSaveBeforeClosing():
+        if self.CTR is not None and not self.CheckSaveBeforeClosing():
             return
         
         self.SaveProjectOrganization()
@@ -1740,14 +1740,14 @@
         self.RefreshAll()
     
     def OnSaveProjectMenu(self, event):
-        if self.PluginRoot is not None:
-            self.PluginRoot.SaveProject()
+        if self.CTR is not None:
+            self.CTR.SaveProject()
             self.RefreshAll()
             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
     
     def OnSaveProjectAsMenu(self, event):
-        if self.PluginRoot is not None:
-            self.PluginRoot.SaveProjectAs()
+        if self.CTR is not None:
+            self.CTR.SaveProjectAs()
             self.RefreshAll()
             self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
         event.Skip()
@@ -1765,53 +1765,53 @@
         OpenHtmlFrame(self,_("About Beremiz"), Bpath("doc","about.html"), wx.Size(550, 500))
     
     def OnPouSelectedChanged(self, event):
-        wx.CallAfter(self.RefreshPluginMenu)
+        wx.CallAfter(self.RefreshConfNodeMenu)
         IDEFrame.OnPouSelectedChanged(self, event)
     
     def OnPageClose(self, event):
-        wx.CallAfter(self.RefreshPluginMenu)
+        wx.CallAfter(self.RefreshConfNodeMenu)
         IDEFrame.OnPageClose(self, event)
     
-    def GetAddButtonFunction(self, plugin, window):
+    def GetAddButtonFunction(self, confnode, window):
         def AddButtonFunction(event):
-            if plugin and len(plugin.PlugChildsTypes) > 0:
-                plugin_menu = wx.Menu(title='')
-                for name, XSDClass, help in plugin.PlugChildsTypes:
+            if confnode and len(confnode.PlugChildsTypes) > 0:
+                confnode_menu = wx.Menu(title='')
+                for name, XSDClass, help in confnode.PlugChildsTypes:
                     new_id = wx.NewId()
-                    plugin_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text=name)
-                    self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name, plugin), id=new_id)
+                    confnode_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text=name)
+                    self.Bind(wx.EVT_MENU, self._GetAddConfNodeFunction(name, confnode), id=new_id)
                 window_pos = window.GetPosition()
-                wx.CallAfter(self.PLCConfig.PopupMenu, plugin_menu)
+                wx.CallAfter(self.PLCConfig.PopupMenu, confnode_menu)
             event.Skip()
         return AddButtonFunction
     
-    def GetDeleteButtonFunction(self, plugin):
+    def GetDeleteButtonFunction(self, confnode):
         def DeleteButtonFunction(event):
-            wx.CallAfter(self.DeletePlugin, plugin)
+            wx.CallAfter(self.DeleteConfNode, confnode)
             event.Skip()
         return DeleteButtonFunction
     
-    def AddPlugin(self, PluginType, plugin):
-        if self.PluginRoot.CheckProjectPathPerm():
-            dialog = wx.TextEntryDialog(self, _("Please enter a name for plugin:"), _("Add Plugin"), "", wx.OK|wx.CANCEL)
+    def AddConfNode(self, ConfNodeType, confnode):
+        if self.CTR.CheckProjectPathPerm():
+            dialog = wx.TextEntryDialog(self, _("Please enter a name for confnode:"), _("Add ConfNode"), "", wx.OK|wx.CANCEL)
             if dialog.ShowModal() == wx.ID_OK:
-                PluginName = dialog.GetValue()
-                plugin.PlugAddChild(PluginName, PluginType)
-                self.PluginRoot.RefreshPluginsBlockLists()
+                ConfNodeName = dialog.GetValue()
+                confnode.PlugAddChild(ConfNodeName, ConfNodeType)
+                self.CTR.RefreshConfNodesBlockLists()
                 self._Refresh(TITLE, FILEMENU)
-                self.RefreshPluginTree()
+                self.RefreshConfNodeTree()
             dialog.Destroy()
     
-    def DeletePlugin(self, plugin):
-        if self.PluginRoot.CheckProjectPathPerm():
-            dialog = wx.MessageDialog(self, _("Really delete plugin ?"), _("Remove plugin"), wx.YES_NO|wx.NO_DEFAULT)
+    def DeleteConfNode(self, confnode):
+        if self.CTR.CheckProjectPathPerm():
+            dialog = wx.MessageDialog(self, _("Really delete confnode ?"), _("Remove confnode"), wx.YES_NO|wx.NO_DEFAULT)
             if dialog.ShowModal() == wx.ID_YES:
-                self.PluginInfos.pop(plugin)
-                plugin.PlugRemove()
-                del plugin
-                self.PluginRoot.RefreshPluginsBlockLists()
+                self.ConfNodeInfos.pop(confnode)
+                confnode.PlugRemove()
+                del confnode
+                self.CTR.RefreshConfNodesBlockLists()
                 self._Refresh(TITLE, FILEMENU)
-                self.RefreshPluginTree()
+                self.RefreshConfNodeTree()
             dialog.Destroy()
     
 #-------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ConfigTree.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2063 @@
+"""
+Base definitions for beremiz confnodes
+"""
+
+import os,sys,traceback
+import time
+import confnodes
+import types
+import shutil
+from xml.dom import minidom
+import wx
+
+#Quick hack to be able to find Beremiz IEC tools. Should be config params.
+base_folder = os.path.split(sys.path[0])[0]
+
+from xmlclass import GenerateClassesFromXSDstring
+from wxPopen import ProcessLogger
+
+from PLCControler import PLCControler, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+
+_BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
+        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+          <xsd:element name="BaseParams">
+            <xsd:complexType>
+              <xsd:attribute name="Name" type="xsd:string" use="optional" default="__unnamed__"/>
+              <xsd:attribute name="IEC_Channel" type="xsd:integer" use="required"/>
+              <xsd:attribute name="Enabled" type="xsd:boolean" use="optional" default="true"/>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>""")["BaseParams"]
+
+NameTypeSeparator = '@'
+
+class MiniTextControler:
+    
+    def __init__(self, filepath):
+        self.FilePath = filepath
+    
+    def PlugFullName(self):
+        return ""
+    
+    def SetEditedElementText(self, tagname, text):
+        file = open(self.FilePath, "w")
+        file.write(text)
+        file.close()
+        
+    def GetEditedElementText(self, tagname, debug = False):
+        if os.path.isfile(self.FilePath):
+            file = open(self.FilePath, "r")
+            text = file.read()
+            file.close()
+            return text
+        return ""
+    
+    def GetEditedElementInterfaceVars(self, tagname, debug = False):
+        return []
+    
+    def GetEditedElementType(self, tagname, debug = False):
+        return "program"
+    
+    def GetBlockTypes(self, tagname = "", debug = False):
+        return []
+    
+    def GetDataTypes(self, tagname = "", basetypes = True, only_locatables = False, debug = False):
+        return []
+    
+    def GetEnumeratedDataValues(self, debug = False):
+        return []
+    
+    def StartBuffering(self):
+        pass
+
+    def EndBuffering(self):
+        pass
+
+    def BufferProject(self):
+        pass
+
+# helper func to get path to images
+def opjimg(imgname):
+    return os.path.join(base_folder, "beremiz", "images",imgname)
+    
+# helper func to check path write permission
+def CheckPathPerm(path):
+    if path is None or not os.path.isdir(path):
+        return False
+    for root, dirs, files in os.walk(path):
+         for name in files:
+             if os.access(root, os.W_OK) is not True or os.access(os.path.join(root, name), os.W_OK) is not True:
+                 return False
+    return True
+    
+class ConfigTreeNode:
+    """
+    This class is the one that define confnodes.
+    """
+
+    XSD = None
+    PlugChildsTypes = []
+    PlugMaxCount = None
+    ConfNodeMethods = []
+    LibraryControler = None
+    EditorType = None
+
+    def _AddParamsMembers(self):
+        self.PlugParams = None
+        if self.XSD:
+            self.Classes = GenerateClassesFromXSDstring(self.XSD)
+            Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
+            if len(Classes) == 1:
+                name, XSDclass = Classes[0]
+                obj = XSDclass()
+                self.PlugParams = (name, obj)
+                setattr(self, name, obj)
+
+    def __init__(self):
+        # Create BaseParam 
+        self.BaseParams = _BaseParamsClass()
+        self.MandatoryParams = ("BaseParams", self.BaseParams)
+        self._AddParamsMembers()
+        self.PluggedChilds = {}
+        self._View = None
+        # copy ConfNodeMethods so that it can be later customized
+        self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
+        self.LoadSTLibrary()
+        
+    def ConfNodeBaseXmlFilePath(self, PlugName=None):
+        return os.path.join(self.PlugPath(PlugName), "baseconfnode.xml")
+    
+    def ConfNodeXmlFilePath(self, PlugName=None):
+        return os.path.join(self.PlugPath(PlugName), "confnode.xml")
+
+    def ConfNodeLibraryFilePath(self):
+        return os.path.join(self.ConfNodePath(), "pous.xml")
+
+    def ConfNodePath(self):
+        return os.path.join(self.PlugParent.ConfNodePath(), self.PlugType)
+
+    def PlugPath(self,PlugName=None):
+        if not PlugName:
+            PlugName = self.PlugName()
+        return os.path.join(self.PlugParent.PlugPath(),
+                            PlugName + NameTypeSeparator + self.PlugType)
+    
+    def PlugName(self):
+        return self.BaseParams.getName()
+    
+    def PlugEnabled(self):
+        return self.BaseParams.getEnabled()
+    
+    def PlugFullName(self):
+        parent = self.PlugParent.PlugFullName()
+        if parent != "":
+            return parent + "." + self.PlugName()
+        return self.BaseParams.getName()
+    
+    def GetIconPath(self, name):
+        return opjimg(name)
+    
+    def PlugTestModified(self):
+        return self.ChangesToSave
+
+    def ProjectTestModified(self):
+        """
+        recursively check modified status
+        """
+        if self.PlugTestModified():
+            return True
+
+        for PlugChild in self.IterChilds():
+            if PlugChild.ProjectTestModified():
+                return True
+
+        return False
+    
+    def RemoteExec(self, script, **kwargs):
+        return self.PlugParent.RemoteExec(script, **kwargs)
+    
+    def OnPlugSave(self):
+        #Default, do nothing and return success
+        return True
+
+    def GetParamsAttributes(self, path = None):
+        if path:
+            parts = path.split(".", 1)
+            if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
+                return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
+            elif self.PlugParams and parts[0] == self.PlugParams[0]:
+                return self.PlugParams[1].getElementInfos(parts[0], parts[1])
+        else:
+            params = []
+            if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
+                params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
+            if self.PlugParams:
+                params.append(self.PlugParams[1].getElementInfos(self.PlugParams[0]))
+            return params
+        
+    def SetParamsAttribute(self, path, value):
+        self.ChangesToSave = True
+        # Filter IEC_Channel and Name, that have specific behavior
+        if path == "BaseParams.IEC_Channel":
+            old_leading = ".".join(map(str, self.GetCurrentLocation()))
+            new_value = self.FindNewIEC_Channel(value)
+            new_leading = ".".join(map(str, self.PlugParent.GetCurrentLocation() + (new_value,)))
+            self.GetPlugRoot().UpdateProjectVariableLocation(old_leading, new_leading)
+            return new_value, True
+        elif path == "BaseParams.Name":
+            res = self.FindNewName(value)
+            self.PlugRequestSave()
+            return res, True
+        
+        parts = path.split(".", 1)
+        if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
+            self.MandatoryParams[1].setElementValue(parts[1], value)
+        elif self.PlugParams and parts[0] == self.PlugParams[0]:
+            self.PlugParams[1].setElementValue(parts[1], value)
+        return value, False
+
+    def PlugMakeDir(self):
+        os.mkdir(self.PlugPath())
+
+    def PlugRequestSave(self):
+        if self.GetPlugRoot().CheckProjectPathPerm(False):
+            # If confnode do not have corresponding directory
+            plugpath = self.PlugPath()
+            if not os.path.isdir(plugpath):
+                # Create it
+                os.mkdir(plugpath)
+    
+            # generate XML for base XML parameters controller of the confnode
+            if self.MandatoryParams:
+                BaseXMLFile = open(self.ConfNodeBaseXmlFilePath(),'w')
+                BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+                BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
+                BaseXMLFile.close()
+            
+            # generate XML for XML parameters controller of the confnode
+            if self.PlugParams:
+                XMLFile = open(self.ConfNodeXmlFilePath(),'w')
+                XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+                XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0).encode("utf-8"))
+                XMLFile.close()
+            
+            # Call the confnode specific OnPlugSave method
+            result = self.OnPlugSave()
+            if not result:
+                return _("Error while saving \"%s\"\n")%self.PlugPath()
+    
+            # mark confnode as saved
+            self.ChangesToSave = False
+            # go through all childs and do the same
+            for PlugChild in self.IterChilds():
+                result = PlugChild.PlugRequestSave()
+                if result:
+                    return result
+        return None
+    
+    def PlugImport(self, src_PlugPath):
+        shutil.copytree(src_PlugPath, self.PlugPath)
+        return True
+
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Generate C code
+        @param locations: List of complete variables locations \
+            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+            "NAME" : name of the variable (generally "__IW0_1_2" style)
+            "DIR" : direction "Q","I" or "M"
+            "SIZE" : size "X", "B", "W", "D", "L"
+            "LOC" : tuple of interger for IEC location (0,1,2,...)
+            }, ...]
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        self.GetPlugRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
+        return [],"",False
+    
+    def _Generate_C(self, buildpath, locations):
+        # Generate confnodes [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
+        # extra_files = [(fname,fobject), ...]
+        gen_result = self.PlugGenerate_C(buildpath, locations)
+        PlugCFilesAndCFLAGS, PlugLDFLAGS, DoCalls = gen_result[:3]
+        extra_files = gen_result[3:]
+        # if some files have been generated put them in the list with their location
+        if PlugCFilesAndCFLAGS:
+            LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS, DoCalls)]
+        else:
+            LocationCFilesAndCFLAGS = []
+
+        # confnode asks for some LDFLAGS
+        if PlugLDFLAGS:
+            # LDFLAGS can be either string
+            if type(PlugLDFLAGS)==type(str()):
+                LDFLAGS=[PlugLDFLAGS]
+            #or list of strings
+            elif type(PlugLDFLAGS)==type(list()):
+                LDFLAGS=PlugLDFLAGS[:]
+        else:
+            LDFLAGS=[]
+        
+        # recurse through all childs, and stack their results
+        for PlugChild in self.IECSortedChilds():
+            new_location = PlugChild.GetCurrentLocation()
+            # How deep are we in the tree ?
+            depth=len(new_location)
+            _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \
+                PlugChild._Generate_C(
+                    #keep the same path
+                    buildpath,
+                    # filter locations that start with current IEC location
+                    [loc for loc in locations if loc["LOC"][0:depth] == new_location ])
+            # stack the result
+            LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS
+            LDFLAGS += _LDFLAGS
+            extra_files += _extra_files
+        
+        return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
+
+    def ConfNodeTypesFactory(self):
+        if self.LibraryControler is not None:
+            return [{"name" : self.PlugType, "types": self.LibraryControler.Project}]
+        return []
+
+    def ParentsTypesFactory(self):
+        return self.PlugParent.ParentsTypesFactory() + self.ConfNodeTypesFactory()
+
+    def ConfNodesTypesFactory(self):
+        list = self.ConfNodeTypesFactory()
+        for PlugChild in self.IterChilds():
+            list += PlugChild.ConfNodesTypesFactory()
+        return list
+
+    def STLibraryFactory(self):
+        if self.LibraryControler is not None:
+            program, errors, warnings = self.LibraryControler.GenerateProgram()
+            return program + "\n"
+        return ""
+
+    def ConfNodesSTLibraryFactory(self):
+        program = self.STLibraryFactory()
+        for PlugChild in self.IECSortedChilds():
+            program += PlugChild.ConfNodesSTLibraryFactory()
+        return program
+        
+    def IterChilds(self):
+        for PlugType, PluggedChilds in self.PluggedChilds.items():
+            for PlugInstance in PluggedChilds:
+                yield PlugInstance
+    
+    def IECSortedChilds(self):
+        # reorder childs by IEC_channels
+        ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChilds()]
+        if ordered:
+            ordered.sort()
+            return zip(*ordered)[1]
+        else:
+            return []
+    
+    def _GetChildBySomething(self, something, toks):
+        for PlugInstance in self.IterChilds():
+            # if match component of the name
+            if getattr(PlugInstance.BaseParams, something) == toks[0]:
+                # if Name have other components
+                if len(toks) >= 2:
+                    # Recurse in order to find the latest object
+                    return PlugInstance._GetChildBySomething( something, toks[1:])
+                # No sub name -> found
+                return PlugInstance
+        # Not found
+        return None
+
+    def GetChildByName(self, Name):
+        if Name:
+            toks = Name.split('.')
+            return self._GetChildBySomething("Name", toks)
+        else:
+            return self
+
+    def GetChildByIECLocation(self, Location):
+        if Location:
+            return self._GetChildBySomething("IEC_Channel", Location)
+        else:
+            return self
+    
+    def GetCurrentLocation(self):
+        """
+        @return:  Tupple containing confnode IEC location of current confnode : %I0.0.4.5 => (0,0,4,5)
+        """
+        return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),)
+
+    def GetCurrentName(self):
+        """
+        @return:  String "ParentParentName.ParentName.Name"
+        """
+        return  self.PlugParent._GetCurrentName() + self.BaseParams.getName()
+
+    def _GetCurrentName(self):
+        """
+        @return:  String "ParentParentName.ParentName.Name."
+        """
+        return  self.PlugParent._GetCurrentName() + self.BaseParams.getName() + "."
+
+    def GetPlugRoot(self):
+        return self.PlugParent.GetPlugRoot()
+
+    def GetFullIEC_Channel(self):
+        return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x"
+
+    def GetLocations(self):
+        location = self.GetCurrentLocation()
+        return [loc for loc in self.PlugParent.GetLocations() if loc["LOC"][0:len(location)] == location]
+
+    def GetVariableLocationTree(self):
+        '''
+        This function is meant to be overridden by confnodes.
+
+        It should returns an list of dictionaries
+        
+        - IEC_type is an IEC type like BOOL/BYTE/SINT/...
+        - location is a string of this variable's location, like "%IX0.0.0"
+        '''
+        children = []
+        for child in self.IECSortedChilds():
+            children.append(child.GetVariableLocationTree())
+        return {"name": self.BaseParams.getName(),
+                "type": LOCATION_CONFNODE,
+                "location": self.GetFullIEC_Channel(),
+                "children": children}
+
+    def FindNewName(self, DesiredName):
+        """
+        Changes Name to DesiredName if available, Name-N if not.
+        @param DesiredName: The desired Name (string)
+        """
+        # Get Current Name
+        CurrentName = self.BaseParams.getName()
+        # Do nothing if no change
+        #if CurrentName == DesiredName: return CurrentName
+        # Build a list of used Name out of parent's PluggedChilds
+        AllNames=[]
+        for PlugInstance in self.PlugParent.IterChilds():
+            if PlugInstance != self:
+                AllNames.append(PlugInstance.BaseParams.getName())
+
+        # Find a free name, eventually appending digit
+        res = DesiredName
+        suffix = 1
+        while res in AllNames:
+            res = "%s-%d"%(DesiredName, suffix)
+            suffix += 1
+        
+        # Get old path
+        oldname = self.PlugPath()
+        # Check previous confnode existance
+        dontexist = self.BaseParams.getName() == "__unnamed__"
+        # Set the new name
+        self.BaseParams.setName(res)
+        # Rename confnode dir if exist
+        if not dontexist:
+            shutil.move(oldname, self.PlugPath())
+        # warn user he has two left hands
+        if DesiredName != res:
+            self.GetPlugRoot().logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res))
+        return res
+
+    def GetAllChannels(self):
+        AllChannels=[]
+        for PlugInstance in self.PlugParent.IterChilds():
+            if PlugInstance != self:
+                AllChannels.append(PlugInstance.BaseParams.getIEC_Channel())
+        AllChannels.sort()
+        return AllChannels
+
+    def FindNewIEC_Channel(self, DesiredChannel):
+        """
+        Changes IEC Channel number to DesiredChannel if available, nearest available if not.
+        @param DesiredChannel: The desired IEC channel (int)
+        """
+        # Get Current IEC channel
+        CurrentChannel = self.BaseParams.getIEC_Channel()
+        # Do nothing if no change
+        #if CurrentChannel == DesiredChannel: return CurrentChannel
+        # Build a list of used Channels out of parent's PluggedChilds
+        AllChannels = self.GetAllChannels()
+        
+        # Now, try to guess the nearest available channel
+        res = DesiredChannel
+        while res in AllChannels: # While channel not free
+            if res < CurrentChannel: # Want to go down ?
+                res -=  1 # Test for n-1
+                if res < 0 :
+                    self.GetPlugRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel)
+                    return CurrentChannel # Can't go bellow 0, do nothing
+            else : # Want to go up ?
+                res +=  1 # Test for n-1
+        # Finally set IEC Channel
+        self.BaseParams.setIEC_Channel(res)
+        return res
+
+    def _OpenView(self, name=None):
+        if self.EditorType is not None and self._View is None:
+            app_frame = self.GetPlugRoot().AppFrame
+            
+            self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
+            
+            app_frame.EditProjectElement(self._View, self.PlugName())
+            
+            return self._View
+        return None
+
+    def OnCloseEditor(self, view):
+        if self._View == view:
+            self._View = None
+
+    def OnPlugClose(self):
+        if self._View is not None:
+            app_frame = self.GetPlugRoot().AppFrame
+            if app_frame is not None:
+                app_frame.DeletePage(self._View)
+        return True
+
+    def _doRemoveChild(self, PlugInstance):
+        # Remove all childs of child
+        for SubPlugInstance in PlugInstance.IterChilds():
+            PlugInstance._doRemoveChild(SubPlugInstance)
+        # Call the OnCloseMethod
+        PlugInstance.OnPlugClose()
+        # Delete confnode dir
+        shutil.rmtree(PlugInstance.PlugPath())
+        # Remove child of PluggedChilds
+        self.PluggedChilds[PlugInstance.PlugType].remove(PlugInstance)
+        # Forget it... (View have to refresh)
+
+    def PlugRemove(self):
+        # Fetch the confnode
+        #PlugInstance = self.GetChildByName(PlugName)
+        # Ask to his parent to remove it
+        self.PlugParent._doRemoveChild(self)
+
+    def PlugAddChild(self, PlugName, PlugType, IEC_Channel=0):
+        """
+        Create the confnodes that may be added as child to this node self
+        @param PlugType: string desining the confnode class name (get name from PlugChildsTypes)
+        @param PlugName: string for the name of the confnode instance
+        """
+        # reorgabize self.PlugChildsTypes tuples from (name, PlugClass, Help)
+        # to ( name, (PlugClass, Help)), an make a dict
+        transpose = zip(*self.PlugChildsTypes)
+        PlugChildsTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2])))
+        # Check that adding this confnode is allowed
+        try:
+            PlugClass, PlugHelp = PlugChildsTypes[PlugType]
+        except KeyError:
+            raise Exception, _("Cannot create child %s of type %s ")%(PlugName, PlugType)
+        
+        # if PlugClass is a class factory, call it. (prevent unneeded imports)
+        if type(PlugClass) == types.FunctionType:
+            PlugClass = PlugClass()
+        
+        # Eventualy Initialize child instance list for this class of confnode
+        PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType, list())
+        # Check count
+        if getattr(PlugClass, "PlugMaxCount", None) and len(PluggedChildsWithSameClass) >= PlugClass.PlugMaxCount:
+            raise Exception, _("Max count (%d) reached for this confnode of type %s ")%(PlugClass.PlugMaxCount, PlugType)
+        
+        # create the final class, derived of provided confnode and template
+        class FinalPlugClass(PlugClass, ConfigTreeNode):
+            """
+            ConfNode class is derivated into FinalPlugClass before being instanciated
+            This way __init__ is overloaded to ensure ConfigTreeNode.__init__ is called 
+            before PlugClass.__init__, and to do the file related stuff.
+            """
+            def __init__(_self):
+                # self is the parent
+                _self.PlugParent = self
+                # Keep track of the confnode type name
+                _self.PlugType = PlugType
+                # remind the help string, for more fancy display
+                _self.PlugHelp = PlugHelp
+                # Call the base confnode template init - change XSD into class members
+                ConfigTreeNode.__init__(_self)
+                # check name is unique
+                NewPlugName = _self.FindNewName(PlugName)
+                # If dir have already be made, and file exist
+                if os.path.isdir(_self.PlugPath(NewPlugName)): #and os.path.isfile(_self.ConfNodeXmlFilePath(PlugName)):
+                    #Load the confnode.xml file into parameters members
+                    _self.LoadXMLParams(NewPlugName)
+                    # Basic check. Better to fail immediately.
+                    if (_self.BaseParams.getName() != NewPlugName):
+                        raise Exception, _("Project tree layout do not match confnode.xml %s!=%s ")%(NewPlugName, _self.BaseParams.getName())
+
+                    # Now, self.PlugPath() should be OK
+                    
+                    # Check that IEC_Channel is not already in use.
+                    _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
+                    # Call the confnode real __init__
+                    if getattr(PlugClass, "__init__", None):
+                        PlugClass.__init__(_self)
+                    #Load and init all the childs
+                    _self.LoadChilds()
+                    #just loaded, nothing to saved
+                    _self.ChangesToSave = False
+                else:
+                    # If confnode do not have corresponding file/dirs - they will be created on Save
+                    _self.PlugMakeDir()
+                    # Find an IEC number
+                    _self.FindNewIEC_Channel(IEC_Channel)
+                    # Call the confnode real __init__
+                    if getattr(PlugClass, "__init__", None):
+                        PlugClass.__init__(_self)
+                    _self.PlugRequestSave()
+                    #just created, must be saved
+                    _self.ChangesToSave = True
+                
+            def _getBuildPath(_self):
+                return self._getBuildPath()
+            
+        # Create the object out of the resulting class
+        newConfNodeOpj = FinalPlugClass()
+        # Store it in PluggedChils
+        PluggedChildsWithSameClass.append(newConfNodeOpj)
+        
+        return newConfNodeOpj
+    
+    def ClearPluggedChilds(self):
+        for child in self.IterChilds():
+            child.ClearPluggedChilds()
+        self.PluggedChilds = {}
+    
+    def LoadSTLibrary(self):
+        # Get library blocks if plcopen library exist
+        library_path = self.ConfNodeLibraryFilePath()
+        if os.path.isfile(library_path):
+            self.LibraryControler = PLCControler()
+            self.LibraryControler.OpenXMLFile(library_path)
+            self.LibraryControler.ClearConfNodeTypes()
+            self.LibraryControler.AddConfNodeTypesList(self.ParentsTypesFactory())
+
+    def LoadXMLParams(self, PlugName = None):
+        methode_name = os.path.join(self.PlugPath(PlugName), "methods.py")
+        if os.path.isfile(methode_name):
+            execfile(methode_name)
+        
+        # Get the base xml tree
+        if self.MandatoryParams:
+            try:
+                basexmlfile = open(self.ConfNodeBaseXmlFilePath(PlugName), 'r')
+                basetree = minidom.parse(basexmlfile)
+                self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
+                basexmlfile.close()
+            except Exception, exc:
+                self.GetPlugRoot().logger.write_error(_("Couldn't load confnode base parameters %s :\n %s") % (PlugName, str(exc)))
+                self.GetPlugRoot().logger.write_error(traceback.format_exc())
+        
+        # Get the xml tree
+        if self.PlugParams:
+            try:
+                xmlfile = open(self.ConfNodeXmlFilePath(PlugName), 'r')
+                tree = minidom.parse(xmlfile)
+                self.PlugParams[1].loadXMLTree(tree.childNodes[0])
+                xmlfile.close()
+            except Exception, exc:
+                self.GetPlugRoot().logger.write_error(_("Couldn't load confnode parameters %s :\n %s") % (PlugName, str(exc)))
+                self.GetPlugRoot().logger.write_error(traceback.format_exc())
+        
+    def LoadChilds(self):
+        # Iterate over all PlugName@PlugType in confnode directory, and try to open them
+        for PlugDir in os.listdir(self.PlugPath()):
+            if os.path.isdir(os.path.join(self.PlugPath(), PlugDir)) and \
+               PlugDir.count(NameTypeSeparator) == 1:
+                pname, ptype = PlugDir.split(NameTypeSeparator)
+                try:
+                    self.PlugAddChild(pname, ptype)
+                except Exception, exc:
+                    self.GetPlugRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc)))
+                    self.GetPlugRoot().logger.write_error(traceback.format_exc())
+
+    def EnableMethod(self, method, value):
+        for d in self.ConfNodeMethods:
+            if d["method"]==method:
+                d["enabled"]=value
+                return True
+        return False
+
+    def ShowMethod(self, method, value):
+        for d in self.ConfNodeMethods:
+            if d["method"]==method:
+                d["shown"]=value
+                return True
+        return False
+
+    def CallMethod(self, method):
+        for d in self.ConfNodeMethods:
+            if d["method"]==method and d.get("enabled", True) and d.get("shown", True):
+                getattr(self, method)()
+
+def _GetClassFunction(name):
+    def GetRootClass():
+        return getattr(__import__("confnodes." + name), name).RootClass
+    return GetRootClass
+
+
+####################################################################################
+####################################################################################
+####################################################################################
+###################################   ROOT    ######################################
+####################################################################################
+####################################################################################
+####################################################################################
+
+if wx.Platform == '__WXMSW__':
+    exe_ext=".exe"
+else:
+    exe_ext=""
+
+# import for project creation timestamping
+from threading import Timer, Lock, Thread, Semaphore
+from time import localtime
+from datetime import datetime
+# import necessary stuff from PLCOpenEditor
+from PLCOpenEditor import PLCOpenEditor, ProjectDialog
+from TextViewer import TextViewer
+from plcopen.structures import IEC_KEYWORDS, TypeHierarchy_list
+
+
+import re, tempfile
+import targets
+from targets.typemapping import DebugTypesSize
+
+import connectors
+from discovery import DiscoveryDialog
+from weakref import WeakKeyDictionary
+
+MATIEC_ERROR_MODEL = re.compile(".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): error : (.*)$")
+
+DEBUG_RETRIES_WARN = 3
+DEBUG_RETRIES_REREGISTER = 4
+
+class ConfigTreeRoot(ConfigTreeNode, PLCControler):
+    """
+    This class define Root object of the confnode tree. 
+    It is responsible of :
+    - Managing project directory
+    - Building project
+    - Handling PLCOpenEditor controler and view
+    - Loading user confnodes and instanciante them as childs
+    - ...
+    
+    """
+
+    # For root object, available Childs Types are modules of the confnode packages.
+    PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(confnodes.__all__,confnodes.helps)]
+
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="BeremizRoot">
+        <xsd:complexType>
+          <xsd:sequence>
+            <xsd:element name="TargetType">
+              <xsd:complexType>
+                <xsd:choice minOccurs="0">
+                """+targets.targetchoices+"""
+                </xsd:choice>
+              </xsd:complexType>
+            </xsd:element>
+          </xsd:sequence>
+          <xsd:attribute name="URI_location" type="xsd:string" use="optional" default=""/>
+          <xsd:attribute name="Enable_ConfNodes" type="xsd:boolean" use="optional" default="true"/>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """
+
+    def __init__(self, frame, logger):
+        PLCControler.__init__(self)
+
+        self.MandatoryParams = None
+        self.SetAppFrame(frame, logger)
+        self._builder = None
+        self._connector = None
+        
+        self.iec2c_path = os.path.join(base_folder, "matiec", "iec2c"+exe_ext)
+        self.ieclib_path = os.path.join(base_folder, "matiec", "lib")
+        
+        # Setup debug information
+        self.IECdebug_datas = {}
+        self.IECdebug_lock = Lock()
+
+        self.DebugTimer=None
+        self.ResetIECProgramsAndVariables()
+        
+        #This method are not called here... but in NewProject and OpenProject
+        #self._AddParamsMembers()
+        #self.PluggedChilds = {}
+
+        # In both new or load scenario, no need to save
+        self.ChangesToSave = False
+        # root have no parent
+        self.PlugParent = None
+        # Keep track of the confnode type name
+        self.PlugType = "Beremiz"
+        self.PluggedChilds = {}
+        # After __init__ root confnode is not valid
+        self.ProjectPath = None
+        self._setBuildPath(None)
+        self.DebugThread = None
+        self.debug_break = False
+        self.previous_plcstate = None
+        # copy ConfNodeMethods so that it can be later customized
+        self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods]
+        self.LoadSTLibrary()
+
+    def __del__(self):
+        if self.DebugTimer:
+            self.DebugTimer.cancel()
+        self.KillDebugThread()
+
+    def SetAppFrame(self, frame, logger):
+        self.AppFrame = frame
+        self.logger = logger
+        self.StatusTimer = None
+        
+        if frame is not None:
+            # Timer to pull PLC status
+            ID_STATUSTIMER = wx.NewId()
+            self.StatusTimer = wx.Timer(self.AppFrame, ID_STATUSTIMER)
+            self.AppFrame.Bind(wx.EVT_TIMER, self.PullPLCStatusProc, self.StatusTimer)
+        
+            self.RefreshConfNodesBlockLists()
+
+    def ResetAppFrame(self, logger):
+        if self.AppFrame is not None:
+            self.AppFrame.Unbind(wx.EVT_TIMER, self.StatusTimer)
+            self.StatusTimer = None
+            self.AppFrame = None
+        
+        self.logger = logger
+
+    def ConfNodeLibraryFilePath(self):
+        return os.path.join(os.path.split(__file__)[0], "pous.xml")
+
+    def PlugTestModified(self):
+         return self.ChangesToSave or not self.ProjectIsSaved()
+
+    def PlugFullName(self):
+        return ""
+
+    def GetPlugRoot(self):
+        return self
+
+    def GetIECLibPath(self):
+        return self.ieclib_path
+    
+    def GetIEC2cPath(self):
+        return self.iec2c_path
+    
+    def GetCurrentLocation(self):
+        return ()
+
+    def GetCurrentName(self):
+        return ""
+    
+    def _GetCurrentName(self):
+        return ""
+
+    def GetProjectPath(self):
+        return self.ProjectPath
+
+    def GetProjectName(self):
+        return os.path.split(self.ProjectPath)[1]
+    
+    def GetDefaultTargetName(self):
+        if wx.Platform == '__WXMSW__':
+            return "Win32"
+        else:
+            return "Linux"
+
+    def GetTarget(self):
+        target = self.BeremizRoot.getTargetType()
+        if target.getcontent() is None:
+            target = self.Classes["BeremizRoot_TargetType"]()
+            target_name = self.GetDefaultTargetName()
+            target.setcontent({"name": target_name, "value": self.Classes["TargetType_%s"%target_name]()})
+        return target
+    
+    def GetParamsAttributes(self, path = None):
+        params = ConfigTreeNode.GetParamsAttributes(self, path)
+        if params[0]["name"] == "BeremizRoot":
+            for child in params[0]["children"]:
+                if child["name"] == "TargetType" and child["value"] == '':
+                    child.update(self.GetTarget().getElementInfos("TargetType")) 
+        return params
+        
+    def SetParamsAttribute(self, path, value):
+        if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
+            self.BeremizRoot.setTargetType(self.GetTarget())
+        return ConfigTreeNode.SetParamsAttribute(self, path, value)
+        
+    # helper func to check project path write permission
+    def CheckProjectPathPerm(self, dosave=True):
+        if CheckPathPerm(self.ProjectPath):
+            return True
+        dialog = wx.MessageDialog(self.AppFrame, 
+                    _('You must have permission to work on the project\nWork on a project copy ?'),
+                    _('Error'), 
+                    wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+        answer = dialog.ShowModal()
+        dialog.Destroy()
+        if answer == wx.ID_YES:
+            if self.SaveProjectAs():
+                self.AppFrame.RefreshAll()
+                self.AppFrame.RefreshTitle()
+                self.AppFrame.RefreshFileMenu()
+                return True
+        return False
+    
+    def NewProject(self, ProjectPath, BuildPath=None):
+        """
+        Create a new project in an empty folder
+        @param ProjectPath: path of the folder where project have to be created
+        @param PLCParams: properties of the PLCOpen program created
+        """
+        # Verify that chosen folder is empty
+        if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0:
+            return _("Chosen folder isn't empty. You can't use it for a new project!")
+        
+        dialog = ProjectDialog(self.AppFrame)
+        if dialog.ShowModal() == wx.ID_OK:
+            values = dialog.GetValues()
+            values["creationDateTime"] = datetime(*localtime()[:6])
+            dialog.Destroy()
+        else:
+            dialog.Destroy()
+            return _("Project not created")
+        
+        # Create PLCOpen program
+        self.CreateNewProject(values)
+        # Change XSD into class members
+        self._AddParamsMembers()
+        self.PluggedChilds = {}
+        # Keep track of the root confnode (i.e. project path)
+        self.ProjectPath = ProjectPath
+        self._setBuildPath(BuildPath)
+        # get confnodes bloclist (is that usefull at project creation?)
+        self.RefreshConfNodesBlockLists()
+        # this will create files base XML files
+        self.SaveProject()
+        return None
+        
+    def LoadProject(self, ProjectPath, BuildPath=None):
+        """
+        Load a project contained in a folder
+        @param ProjectPath: path of the project folder
+        """
+        if os.path.basename(ProjectPath) == "":
+            ProjectPath = os.path.dirname(ProjectPath)
+		# Verify that project contains a PLCOpen program
+        plc_file = os.path.join(ProjectPath, "plc.xml")
+        if not os.path.isfile(plc_file):
+            return _("Chosen folder doesn't contain a program. It's not a valid project!")
+        # Load PLCOpen file
+        result = self.OpenXMLFile(plc_file)
+        if result:
+            return result
+        # Change XSD into class members
+        self._AddParamsMembers()
+        self.PluggedChilds = {}
+        # Keep track of the root confnode (i.e. project path)
+        self.ProjectPath = ProjectPath
+        self._setBuildPath(BuildPath)
+        # If dir have already be made, and file exist
+        if os.path.isdir(self.PlugPath()) and os.path.isfile(self.ConfNodeXmlFilePath()):
+            #Load the confnode.xml file into parameters members
+            result = self.LoadXMLParams()
+            if result:
+                return result
+            #Load and init all the childs
+            self.LoadChilds()
+        self.RefreshConfNodesBlockLists()
+        
+        if os.path.exists(self._getBuildPath()):
+            self.EnableMethod("_Clean", True)
+
+        if os.path.isfile(self._getIECrawcodepath()):
+            self.ShowMethod("_showIECcode", True)
+
+        return None
+    
+    def CloseProject(self):
+        self.ClearPluggedChilds()
+        self.ResetAppFrame(None)
+        
+    def SaveProject(self):
+        if self.CheckProjectPathPerm(False):
+            self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
+            result = self.PlugRequestSave()
+            if result:
+                self.logger.write_error(result)
+    
+    def SaveProjectAs(self, dosave=True):
+        # Ask user to choose a path with write permissions
+        if wx.Platform == '__WXMSW__':
+            path = os.getenv("USERPROFILE")
+        else:
+            path = os.getenv("HOME")
+        dirdialog = wx.DirDialog(self.AppFrame , _("Choose a directory to save project"), path, wx.DD_NEW_DIR_BUTTON)
+        answer = dirdialog.ShowModal()
+        dirdialog.Destroy()
+        if answer == wx.ID_OK:
+            newprojectpath = dirdialog.GetPath()
+            if os.path.isdir(newprojectpath):
+                self.ProjectPath = newprojectpath
+                if dosave:
+                    self.SaveProject()
+                self._setBuildPath(self.BuildPath)
+                return True
+        return False
+    
+    # Update PLCOpenEditor ConfNode Block types from loaded confnodes
+    def RefreshConfNodesBlockLists(self):
+        if getattr(self, "PluggedChilds", None) is not None:
+            self.ClearConfNodeTypes()
+            self.AddConfNodeTypesList(self.ConfNodesTypesFactory())
+        if self.AppFrame is not None:
+            self.AppFrame.RefreshLibraryPanel()
+            self.AppFrame.RefreshEditor()
+    
+    # Update a PLCOpenEditor Pou variable location
+    def UpdateProjectVariableLocation(self, old_leading, new_leading):
+        self.Project.updateElementAddress(old_leading, new_leading)
+        self.BufferProject()
+        if self.AppFrame is not None:
+            self.AppFrame.RefreshTitle()
+            self.AppFrame.RefreshInstancesTree()
+            self.AppFrame.RefreshFileMenu()
+            self.AppFrame.RefreshEditMenu()
+            self.AppFrame.RefreshEditor()
+    
+    def GetVariableLocationTree(self):
+        '''
+        This function is meant to be overridden by confnodes.
+
+        It should returns an list of dictionaries
+        
+        - IEC_type is an IEC type like BOOL/BYTE/SINT/...
+        - location is a string of this variable's location, like "%IX0.0.0"
+        '''
+        children = []
+        for child in self.IECSortedChilds():
+            children.append(child.GetVariableLocationTree())
+        return children
+    
+    def ConfNodePath(self):
+        return os.path.join(os.path.split(__file__)[0], "confnodes")
+    
+    def PlugPath(self, PlugName=None):
+        return self.ProjectPath
+    
+    def ConfNodeXmlFilePath(self, PlugName=None):
+        return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
+
+    def ParentsTypesFactory(self):
+        return self.ConfNodeTypesFactory()
+
+    def _setBuildPath(self, buildpath):
+        if CheckPathPerm(buildpath):
+            self.BuildPath = buildpath
+        else:
+            self.BuildPath = None
+        self.BuildPath = buildpath
+        self.DefaultBuildPath = None
+        if self._builder is not None:
+            self._builder.SetBuildPath(self._getBuildPath())
+
+    def _getBuildPath(self):
+        # BuildPath is defined by user
+        if self.BuildPath is not None:
+            return self.BuildPath
+        # BuildPath isn't defined by user but already created by default
+        if self.DefaultBuildPath is not None:
+            return self.DefaultBuildPath
+        # Create a build path in project folder if user has permissions
+        if CheckPathPerm(self.ProjectPath):
+            self.DefaultBuildPath = os.path.join(self.ProjectPath, "build")
+        # Create a build path in temp folder
+        else:
+            self.DefaultBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
+            
+        if not os.path.exists(self.DefaultBuildPath):
+            os.makedirs(self.DefaultBuildPath)
+        return self.DefaultBuildPath
+    
+    def _getExtraFilesPath(self):
+        return os.path.join(self._getBuildPath(), "extra_files")
+
+    def _getIECcodepath(self):
+        # define name for IEC code file
+        return os.path.join(self._getBuildPath(), "plc.st")
+    
+    def _getIECgeneratedcodepath(self):
+        # define name for IEC generated code file
+        return os.path.join(self._getBuildPath(), "generated_plc.st")
+    
+    def _getIECrawcodepath(self):
+        # define name for IEC raw code file
+        return os.path.join(self.PlugPath(), "raw_plc.st")
+    
+    def GetLocations(self):
+        locations = []
+        filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h")
+        if os.path.isfile(filepath):
+            # IEC2C compiler generate a list of located variables : LOCATED_VARIABLES.h
+            location_file = open(os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h"))
+            # each line of LOCATED_VARIABLES.h declares a located variable
+            lines = [line.strip() for line in location_file.readlines()]
+            # This regular expression parses the lines genereated by IEC2C
+            LOCATED_MODEL = re.compile("__LOCATED_VAR\((?P<IEC_TYPE>[A-Z]*),(?P<NAME>[_A-Za-z0-9]*),(?P<DIR>[QMI])(?:,(?P<SIZE>[XBWDL]))?,(?P<LOC>[,0-9]*)\)")
+            for line in lines:
+                # If line match RE, 
+                result = LOCATED_MODEL.match(line)
+                if result:
+                    # Get the resulting dict
+                    resdict = result.groupdict()
+                    # rewrite string for variadic location as a tuple of integers
+                    resdict['LOC'] = tuple(map(int,resdict['LOC'].split(',')))
+                    # set located size to 'X' if not given 
+                    if not resdict['SIZE']:
+                        resdict['SIZE'] = 'X'
+                    # finally store into located variable list
+                    locations.append(resdict)
+        return locations
+        
+    def _Generate_SoftPLC(self):
+        """
+        Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2C
+        @param buildpath: path where files should be created
+        """
+
+        # Update PLCOpenEditor ConfNode Block types before generate ST code
+        self.RefreshConfNodesBlockLists()
+        
+        self.logger.write(_("Generating SoftPLC IEC-61131 ST/IL/SFC code...\n"))
+        buildpath = self._getBuildPath()
+        # ask PLCOpenEditor controller to write ST/IL/SFC code file
+        program, errors, warnings = self.GenerateProgram(self._getIECgeneratedcodepath())
+        if len(warnings) > 0:
+            self.logger.write_warning(_("Warnings in ST/IL/SFC code generator :\n"))
+            for warning in warnings:
+                self.logger.write_warning("%s\n"%warning)
+        if len(errors) > 0:
+            # Failed !
+            self.logger.write_error(_("Error in ST/IL/SFC code generator :\n%s\n")%errors[0])
+            return False
+        plc_file = open(self._getIECcodepath(), "w")
+        # Add ST Library from confnodes
+        plc_file.write(self.ConfNodesSTLibraryFactory())
+        if os.path.isfile(self._getIECrawcodepath()):
+            plc_file.write(open(self._getIECrawcodepath(), "r").read())
+            plc_file.write("\n")
+        plc_file.close()
+        plc_file = open(self._getIECcodepath(), "r")
+        self.ProgramOffset = 0
+        for line in plc_file.xreadlines():
+            self.ProgramOffset += 1
+        plc_file.close()
+        plc_file = open(self._getIECcodepath(), "a")
+        plc_file.write(open(self._getIECgeneratedcodepath(), "r").read())
+        plc_file.close()
+
+        self.logger.write(_("Compiling IEC Program into C code...\n"))
+
+        # Now compile IEC code into many C files
+        # files are listed to stdout, and errors to stderr. 
+        status, result, err_result = ProcessLogger(
+               self.logger,
+               "\"%s\" -f -I \"%s\" -T \"%s\" \"%s\""%(
+                         self.iec2c_path,
+                         self.ieclib_path, 
+                         buildpath,
+                         self._getIECcodepath()),
+               no_stdout=True, no_stderr=True).spin()
+        if status:
+            # Failed !
+            
+            # parse iec2c's error message. if it contains a line number,
+            # then print those lines from the generated IEC file.
+            for err_line in err_result.split('\n'):
+                self.logger.write_warning(err_line + "\n")
+
+                m_result = MATIEC_ERROR_MODEL.match(err_line)
+                if m_result is not None:
+                    first_line, first_column, last_line, last_column, error = m_result.groups()
+                    first_line, last_line = int(first_line), int(last_line)
+                    
+                    last_section = None
+                    f = open(self._getIECcodepath())
+
+                    for i, line in enumerate(f.readlines()):
+                        i = i + 1
+                        if line[0] not in '\t \r\n':
+                            last_section = line
+
+                        if first_line <= i <= last_line:
+                            if last_section is not None:
+                                self.logger.write_warning("In section: " + last_section)
+                                last_section = None # only write section once
+                            self.logger.write_warning("%04d: %s" % (i, line))
+
+                    f.close()
+            
+            self.logger.write_error(_("Error : IEC to C compiler returned %d\n")%status)
+            return False
+        
+        # Now extract C files of stdout
+        C_files = [ fname for fname in result.splitlines() if fname[-2:]==".c" or fname[-2:]==".C" ]
+        # remove those that are not to be compiled because included by others
+        C_files.remove("POUS.c")
+        if not C_files:
+            self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n"))
+            return False
+        # transform those base names to full names with path
+        C_files = map(lambda filename:os.path.join(buildpath, filename), C_files)
+        self.logger.write(_("Extracting Located Variables...\n"))
+        # Keep track of generated located variables for later use by self._Generate_C
+        self.PLCGeneratedLocatedVars = self.GetLocations()
+        # Keep track of generated C files for later use by self.PlugGenerate_C
+        self.PLCGeneratedCFiles = C_files
+        # compute CFLAGS for plc
+        self.plcCFLAGS = "\"-I"+self.ieclib_path+"\""
+        return True
+
+    def GetBuilder(self):
+        """
+        Return a Builder (compile C code into machine code)
+        """
+        # Get target, module and class name
+        targetname = self.GetTarget().getcontent()["name"]
+        modulename = "targets." + targetname
+        classname = targetname + "_target"
+
+        # Get module reference
+        try :
+            targetmodule = getattr(__import__(modulename), targetname)
+
+        except Exception, msg:
+            self.logger.write_error(_("Can't find module for target %s!\n")%targetname)
+            self.logger.write_error(str(msg))
+            return None
+        
+        # Get target class
+        targetclass = getattr(targetmodule, classname)
+
+        # if target already 
+        if self._builder is None or not isinstance(self._builder,targetclass):
+            # Get classname instance
+            self._builder = targetclass(self)
+        return self._builder
+
+    def ResetBuildMD5(self):
+        builder=self.GetBuilder()
+        if builder is not None:
+            builder.ResetBinaryCodeMD5()
+        self.EnableMethod("_Transfer", False)
+
+    def GetLastBuildMD5(self):
+        builder=self.GetBuilder()
+        if builder is not None:
+            return builder.GetBinaryCodeMD5()
+        else:
+            return None
+
+    #######################################################################
+    #
+    #                C CODE GENERATION METHODS
+    #
+    #######################################################################
+    
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Return C code generated by iec2c compiler 
+        when _generate_softPLC have been called
+        @param locations: ignored
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+
+        return ([(C_file_name, self.plcCFLAGS) 
+                for C_file_name in self.PLCGeneratedCFiles ], 
+               "", # no ldflags
+               False) # do not expose retreive/publish calls
+    
+    def ResetIECProgramsAndVariables(self):
+        """
+        Reset variable and program list that are parsed from
+        CSV file generated by IEC2C compiler.
+        """
+        self._ProgramList = None
+        self._VariablesList = None
+        self._IECPathToIdx = {}
+        self._Ticktime = 0
+        self.TracedIECPath = []
+
+    def GetIECProgramsAndVariables(self):
+        """
+        Parse CSV-like file  VARIABLES.csv resulting from IEC2C compiler.
+        Each section is marked with a line staring with '//'
+        list of all variables used in various POUs
+        """
+        if self._ProgramList is None or self._VariablesList is None:
+            try:
+                csvfile = os.path.join(self._getBuildPath(),"VARIABLES.csv")
+                # describes CSV columns
+                ProgramsListAttributeName = ["num", "C_path", "type"]
+                VariablesListAttributeName = ["num", "vartype", "IEC_path", "C_path", "type"]
+                self._ProgramList = []
+                self._VariablesList = []
+                self._IECPathToIdx = {}
+                
+                # Separate sections
+                ListGroup = []
+                for line in open(csvfile,'r').xreadlines():
+                    strippedline = line.strip()
+                    if strippedline.startswith("//"):
+                        # Start new section
+                        ListGroup.append([])
+                    elif len(strippedline) > 0 and len(ListGroup) > 0:
+                        # append to this section
+                        ListGroup[-1].append(strippedline)
+        
+                # first section contains programs
+                for line in ListGroup[0]:
+                    # Split and Maps each field to dictionnary entries
+                    attrs = dict(zip(ProgramsListAttributeName,line.strip().split(';')))
+                    # Truncate "C_path" to remove conf an ressources names
+                    attrs["C_path"] = '__'.join(attrs["C_path"].split(".",2)[1:])
+                    # Push this dictionnary into result.
+                    self._ProgramList.append(attrs)
+        
+                # second section contains all variables
+                for line in ListGroup[1]:
+                    # Split and Maps each field to dictionnary entries
+                    attrs = dict(zip(VariablesListAttributeName,line.strip().split(';')))
+                    # Truncate "C_path" to remove conf an ressources names
+                    parts = attrs["C_path"].split(".",2)
+                    if len(parts) > 2:
+                        attrs["C_path"] = '__'.join(parts[1:])
+                    else:
+                        attrs["C_path"] = '__'.join(parts)
+                    # Push this dictionnary into result.
+                    self._VariablesList.append(attrs)
+                    # Fill in IEC<->C translation dicts
+                    IEC_path=attrs["IEC_path"]
+                    Idx=int(attrs["num"])
+                    self._IECPathToIdx[IEC_path]=(Idx, attrs["type"])
+                
+                # third section contains ticktime
+                if len(ListGroup) > 2:
+                    self._Ticktime = int(ListGroup[2][0]) 
+                
+            except Exception,e:
+                self.logger.write_error(_("Cannot open/parse VARIABLES.csv!\n"))
+                self.logger.write_error(traceback.format_exc())
+                self.ResetIECProgramsAndVariables()
+                return False
+
+        return True
+
+    def Generate_plc_debugger(self):
+        """
+        Generate trace/debug code out of PLC variable list
+        """
+        self.GetIECProgramsAndVariables()
+
+        # prepare debug code
+        debug_code = targets.code("plc_debug") % {
+           "buffer_size": reduce(lambda x, y: x + y, [DebugTypesSize.get(v["type"], 0) for v in self._VariablesList], 0),
+           "programs_declarations":
+               "\n".join(["extern %(type)s %(C_path)s;"%p for p in self._ProgramList]),
+           "extern_variables_declarations":"\n".join([
+              {"EXT":"extern __IEC_%(type)s_p %(C_path)s;",
+               "IN":"extern __IEC_%(type)s_p %(C_path)s;",
+               "MEM":"extern __IEC_%(type)s_p %(C_path)s;",
+               "OUT":"extern __IEC_%(type)s_p %(C_path)s;",
+               "VAR":"extern __IEC_%(type)s_t %(C_path)s;"}[v["vartype"]]%v 
+               for v in self._VariablesList if v["vartype"] != "FB" and v["C_path"].find('.')<0]),
+           "for_each_variable_do_code":"\n".join([
+               {"EXT":"    (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
+                "IN":"    (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
+                "MEM":"    (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
+                "OUT":"    (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
+                "VAR":"    (*fp)((void*)&%(C_path)s,%(type)s_ENUM);\n"}[v["vartype"]]%v
+                for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ]),
+           "find_variable_case_code":"\n".join([
+               "    case %(num)s:\n"%v+
+               "        *varp = (void*)&%(C_path)s;\n"%v+
+               {"EXT":"        return %(type)s_P_ENUM;\n",
+                "IN":"        return %(type)s_P_ENUM;\n",
+                "MEM":"        return %(type)s_O_ENUM;\n",
+                "OUT":"        return %(type)s_O_ENUM;\n",
+                "VAR":"        return %(type)s_ENUM;\n"}[v["vartype"]]%v
+                for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ])}
+        
+        return debug_code
+        
+    def Generate_plc_common_main(self):
+        """
+        Use confnodes layout given in LocationCFilesAndCFLAGS to
+        generate glue code that dispatch calls to all confnodes
+        """
+        # filter location that are related to code that will be called
+        # in retreive, publish, init, cleanup
+        locstrs = map(lambda x:"_".join(map(str,x)),
+           [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls])
+
+        # Generate main, based on template
+        if self.BeremizRoot.getEnable_ConfNodes():
+            plc_main_code = targets.code("plc_common_main") % {
+                "calls_prototypes":"\n".join([(
+                      "int __init_%(s)s(int argc,char **argv);\n"+
+                      "void __cleanup_%(s)s(void);\n"+
+                      "void __retrieve_%(s)s(void);\n"+
+                      "void __publish_%(s)s(void);")%{'s':locstr} for locstr in locstrs]),
+                "retrieve_calls":"\n    ".join([
+                      "__retrieve_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]),
+                "publish_calls":"\n    ".join([ #Call publish in reverse order
+                      "__publish_%s();"%locstr for locstr in locstrs]),
+                "init_calls":"\n    ".join([
+                      "init_level=%d; "%(i+1)+
+                      "if((res = __init_%s(argc,argv))){"%locstr +
+                      #"printf(\"%s\"); "%locstr + #for debug
+                      "return res;}" for i,locstr in enumerate(locstrs)]),
+                "cleanup_calls":"\n    ".join([
+                      "if(init_level >= %d) "%i+
+                      "__cleanup_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)])
+                }
+        else:
+            plc_main_code = targets.code("plc_common_main") % {
+                "calls_prototypes":"\n",
+                "retrieve_calls":"\n",
+                "publish_calls":"\n",
+                "init_calls":"\n",
+                "cleanup_calls":"\n"
+                }
+        plc_main_code += targets.targetcode(self.GetTarget().getcontent()["name"])
+        return plc_main_code
+
+        
+    def _Build(self):
+        """
+        Method called by user to (re)build SoftPLC and confnode tree
+        """
+        if self.AppFrame is not None:
+            self.AppFrame.ClearErrors()
+        
+        buildpath = self._getBuildPath()
+
+        # Eventually create build dir
+        if not os.path.exists(buildpath):
+            os.mkdir(buildpath)
+        # There is something to clean
+        self.EnableMethod("_Clean", True)
+
+        self.logger.flush()
+        self.logger.write(_("Start build in %s\n") % buildpath)
+
+        # Generate SoftPLC IEC code
+        IECGenRes = self._Generate_SoftPLC()
+        self.ShowMethod("_showIECcode", True)
+
+        # If IEC code gen fail, bail out.
+        if not IECGenRes:
+            self.logger.write_error(_("IEC-61131-3 code generation failed !\n"))
+            self.ResetBuildMD5()
+            return False
+
+        # Reset variable and program list that are parsed from
+        # CSV file generated by IEC2C compiler.
+        self.ResetIECProgramsAndVariables()
+        
+        # Generate C code and compilation params from confnode hierarchy
+        self.logger.write(_("Generating confnodes C code\n"))
+        try:
+            self.LocationCFilesAndCFLAGS, self.LDFLAGS, ExtraFiles = self._Generate_C(
+                buildpath, 
+                self.PLCGeneratedLocatedVars)
+        except Exception, exc:
+            self.logger.write_error(_("ConfNodes code generation failed !\n"))
+            self.logger.write_error(traceback.format_exc())
+            self.ResetBuildMD5()
+            return False
+
+        # Get temporary directory path
+        extrafilespath = self._getExtraFilesPath()
+        # Remove old directory
+        if os.path.exists(extrafilespath):
+            shutil.rmtree(extrafilespath)
+        # Recreate directory
+        os.mkdir(extrafilespath)
+        # Then write the files
+        for fname,fobject in ExtraFiles:
+            fpath = os.path.join(extrafilespath,fname)
+            open(fpath, "wb").write(fobject.read())
+        # Now we can forget ExtraFiles (will close files object)
+        del ExtraFiles
+        
+        # Template based part of C code generation
+        # files are stacked at the beginning, as files of confnode tree root
+        for generator, filename, name in [
+           # debugger code
+           (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
+           # init/cleanup/retrieve/publish, run and align code
+           (self.Generate_plc_common_main,"plc_common_main.c","Common runtime")]:
+            try:
+                # Do generate
+                code = generator()
+                if code is None:
+                     raise
+                code_path = os.path.join(buildpath,filename)
+                open(code_path, "w").write(code)
+                # Insert this file as first file to be compiled at root confnode
+                self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS))
+            except Exception, exc:
+                self.logger.write_error(name+_(" generation failed !\n"))
+                self.logger.write_error(traceback.format_exc())
+                self.ResetBuildMD5()
+                return False
+
+        self.logger.write(_("C code generated successfully.\n"))
+
+        # Get current or fresh builder
+        builder = self.GetBuilder()
+        if builder is None:
+            self.logger.write_error(_("Fatal : cannot get builder.\n"))
+            self.ResetBuildMD5()
+            return False
+
+        # Build
+        try:
+            if not builder.build() :
+                self.logger.write_error(_("C Build failed.\n"))
+                return False
+        except Exception, exc:
+            self.logger.write_error(_("C Build crashed !\n"))
+            self.logger.write_error(traceback.format_exc())
+            self.ResetBuildMD5()
+            return False
+
+        self.logger.write(_("Successfully built.\n"))
+        # Update GUI status about need for transfer
+        self.CompareLocalAndRemotePLC()
+        return True
+    
+    def ShowError(self, logger, from_location, to_location):
+        chunk_infos = self.GetChunkInfos(from_location, to_location)
+        for infos, (start_row, start_col) in chunk_infos:
+            start = (from_location[0] - start_row, from_location[1] - start_col)
+            end = (to_location[0] - start_row, to_location[1] - start_col)
+            #print from_location, to_location, start_row, start_col, start, end
+            if self.AppFrame is not None:
+                self.AppFrame.ShowError(infos, start, end)
+
+    def _showIECcode(self):
+        self._OpenView("IEC code")
+
+    def _editIECrawcode(self):
+        self._OpenView("IEC raw code")
+
+    def _OpenView(self, name=None):
+        if name == "IEC code":
+            plc_file = self._getIECcodepath()
+        
+            IEC_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, None, instancepath=name)
+            #IEC_code_viewer.Enable(False)
+            IEC_code_viewer.SetTextSyntax("ALL")
+            IEC_code_viewer.SetKeywords(IEC_KEYWORDS)
+            try:
+                text = file(plc_file).read()
+            except:
+                text = '(* No IEC code have been generated at that time ! *)'
+            IEC_code_viewer.SetText(text = text)
+            IEC_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
+                
+            self.AppFrame.EditProjectElement(IEC_code_viewer, name)
+            
+            return IEC_code_viewer
+        
+        elif name == "IEC raw code":
+            controler = MiniTextControler(self._getIECrawcodepath())
+            IEC_raw_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, controler, instancepath=name)
+            #IEC_raw_code_viewer.Enable(False)
+            IEC_raw_code_viewer.SetTextSyntax("ALL")
+            IEC_raw_code_viewer.SetKeywords(IEC_KEYWORDS)
+            IEC_raw_code_viewer.RefreshView()
+            IEC_raw_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
+                
+            self.AppFrame.EditProjectElement(IEC_raw_code_viewer, name)
+
+            return IEC_raw_code_viewer
+        
+        return None
+
+    def _Clean(self):
+        if os.path.isdir(os.path.join(self._getBuildPath())):
+            self.logger.write(_("Cleaning the build directory\n"))
+            shutil.rmtree(os.path.join(self._getBuildPath()))
+        else:
+            self.logger.write_error(_("Build directory already clean\n"))
+        self.ShowMethod("_showIECcode", False)
+        self.EnableMethod("_Clean", False)
+        # kill the builder
+        self._builder = None
+        self.CompareLocalAndRemotePLC()
+
+    ############# Real PLC object access #############
+    def UpdateMethodsFromPLCStatus(self):
+        # Get PLC state : Running or Stopped
+        # TODO : use explicit status instead of boolean
+        status = None
+        if self._connector is not None:
+            status = self._connector.GetPLCstatus()
+        if status is None:
+            self._connector = None
+            status = "Disconnected"
+        if(self.previous_plcstate != status):
+            for args in {
+                     "Started" :     [("_Run", False),
+                                      ("_Stop", True)],
+                     "Stopped" :     [("_Run", True),
+                                      ("_Stop", False)],
+                     "Empty" :       [("_Run", False),
+                                      ("_Stop", False)],
+                     "Broken" :      [],
+                     "Disconnected" :[("_Run", False),
+                                      ("_Stop", False),
+                                      ("_Transfer", False),
+                                      ("_Connect", True),
+                                      ("_Disconnect", False)],
+                   }.get(status,[]):
+                self.ShowMethod(*args)
+            self.previous_plcstate = status
+            return True
+        return False
+    
+    def PullPLCStatusProc(self, event):
+        if self._connector is None:
+            self.StatusTimer.Stop()
+        if self.UpdateMethodsFromPLCStatus():
+            
+            status = _(self.previous_plcstate)
+            {"Broken": self.logger.write_error,
+             None: lambda x: None}.get(
+                self.previous_plcstate, self.logger.write)(_("PLC is %s\n")%status)
+            self.AppFrame.RefreshAll()
+        
+    def RegisterDebugVarToConnector(self):
+        self.DebugTimer=None
+        Idxs = []
+        self.TracedIECPath = []
+        if self._connector is not None:
+            self.IECdebug_lock.acquire()
+            IECPathsToPop = []
+            for IECPath,data_tuple in self.IECdebug_datas.iteritems():
+                WeakCallableDict, data_log, status, fvalue = data_tuple
+                if len(WeakCallableDict) == 0:
+                    # Callable Dict is empty.
+                    # This variable is not needed anymore!
+                    #print "Unused : " + IECPath
+                    IECPathsToPop.append(IECPath)
+                elif IECPath != "__tick__":
+                    # Convert 
+                    Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
+                    if Idx is not None:
+                        if IEC_Type in DebugTypesSize: 
+                            Idxs.append((Idx, IEC_Type, fvalue, IECPath))
+                        else:
+                            self.logger.write_warning(_("Debug : Unsuppoted type to debug %s\n")%IEC_Type)
+                    else:
+                        self.logger.write_warning(_("Debug : Unknown variable %s\n")%IECPath)
+            for IECPathToPop in IECPathsToPop:
+                self.IECdebug_datas.pop(IECPathToPop)
+
+            if Idxs:
+                Idxs.sort()
+                self.TracedIECPath = zip(*Idxs)[3]
+                self._connector.SetTraceVariablesList(zip(*zip(*Idxs)[0:3]))
+            else:
+                self.TracedIECPath = []
+                self._connector.SetTraceVariablesList([])
+            self.IECdebug_lock.release()
+            
+            #for IEC_path, IECdebug_data in self.IECdebug_datas.iteritems():
+            #    print IEC_path, IECdebug_data[0].keys()
+
+    def ReArmDebugRegisterTimer(self):
+        if self.DebugTimer is not None:
+            self.DebugTimer.cancel()
+
+        # Timer to prevent rapid-fire when registering many variables
+        # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
+        self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
+        # Rearm anti-rapid-fire timer
+        self.DebugTimer.start()
+
+    def GetDebugIECVariableType(self, IECPath):
+        Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
+        return IEC_Type
+        
+    def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs):
+        """
+        Dispatching use a dictionnary linking IEC variable paths
+        to a WeakKeyDictionary linking 
+        weakly referenced callables to optionnal args
+        """
+        if IECPath != "__tick__" and not self._IECPathToIdx.has_key(IECPath):
+            return None
+        
+        self.IECdebug_lock.acquire()
+        # If no entry exist, create a new one with a fresh WeakKeyDictionary
+        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+        if IECdebug_data is None:
+            IECdebug_data  = [
+                    WeakKeyDictionary(), # Callables
+                    [],                  # Data storage [(tick, data),...]
+                    "Registered",        # Variable status
+                    None]                # Forced value
+            self.IECdebug_datas[IECPath] = IECdebug_data
+        
+        IECdebug_data[0][callableobj]=(args, kwargs)
+
+        self.IECdebug_lock.release()
+        
+        self.ReArmDebugRegisterTimer()
+        
+        return IECdebug_data[1]
+
+    def UnsubscribeDebugIECVariable(self, IECPath, callableobj):
+        #print "Unsubscribe", IECPath, callableobj
+        self.IECdebug_lock.acquire()
+        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+        if IECdebug_data is not None:
+            IECdebug_data[0].pop(callableobj,None)
+        self.IECdebug_lock.release()
+
+        self.ReArmDebugRegisterTimer()
+
+    def UnsubscribeAllDebugIECVariable(self):
+        self.IECdebug_lock.acquire()
+        IECdebug_data = {}
+        self.IECdebug_lock.release()
+
+        self.ReArmDebugRegisterTimer()
+
+    def ForceDebugIECVariable(self, IECPath, fvalue):
+        if not self.IECdebug_datas.has_key(IECPath):
+            return
+        
+        self.IECdebug_lock.acquire()
+        
+        # If no entry exist, create a new one with a fresh WeakKeyDictionary
+        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+        IECdebug_data[2] = "Forced"
+        IECdebug_data[3] = fvalue
+        
+        self.IECdebug_lock.release()
+        
+        self.ReArmDebugRegisterTimer()
+    
+    def ReleaseDebugIECVariable(self, IECPath):
+        if not self.IECdebug_datas.has_key(IECPath):
+            return
+        
+        self.IECdebug_lock.acquire()
+        
+        # If no entry exist, create a new one with a fresh WeakKeyDictionary
+        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
+        IECdebug_data[2] = "Registered"
+        IECdebug_data[3] = None
+        
+        self.IECdebug_lock.release()
+        
+        self.ReArmDebugRegisterTimer()
+    
+    def CallWeakcallables(self, IECPath, function_name, *cargs):
+        data_tuple = self.IECdebug_datas.get(IECPath, None)
+        if data_tuple is not None:
+            WeakCallableDict, data_log, status, fvalue = data_tuple
+            #data_log.append((debug_tick, value))
+            for weakcallable,(args,kwargs) in WeakCallableDict.iteritems():
+                #print weakcallable, value, args, kwargs
+                function = getattr(weakcallable, function_name, None)
+                if function is not None:
+                    if status == "Forced" and cargs[1] == fvalue:
+                        function(*(cargs + (True,) + args), **kwargs)
+                    else:
+                        function(*(cargs + args), **kwargs)
+                # This will block thread if more than one call is waiting
+
+    def GetTicktime(self):
+        return self._Ticktime
+
+    def RemoteExec(self, script, **kwargs):
+        if self._connector is None:
+            return -1, "No runtime connected!"
+        return self._connector.RemoteExec(script, **kwargs)
+
+    def DebugThreadProc(self):
+        """
+        This thread waid PLC debug data, and dispatch them to subscribers
+        """
+        self.debug_break = False
+        debug_getvar_retry = 0
+        while (not self.debug_break) and (self._connector is not None):
+            Trace = self._connector.GetTraceVariables()
+            if(Trace):
+                plc_status, debug_tick, debug_vars = Trace
+            else:
+                plc_status = None
+            debug_getvar_retry += 1
+            #print debug_tick, debug_vars
+            if plc_status == "Started":
+                self.IECdebug_lock.acquire()
+                if len(debug_vars) == len(self.TracedIECPath):
+                    if debug_getvar_retry > DEBUG_RETRIES_WARN:
+                        self.logger.write(_("... debugger recovered\n"))
+                    debug_getvar_retry = 0
+                    for IECPath,value in zip(self.TracedIECPath, debug_vars):
+                        if value is not None:
+                            self.CallWeakcallables(IECPath, "NewValue", debug_tick, value)
+                    self.CallWeakcallables("__tick__", "NewDataAvailable")
+                self.IECdebug_lock.release()
+                if debug_getvar_retry == DEBUG_RETRIES_WARN:
+                    self.logger.write(_("Waiting debugger to recover...\n"))
+                if debug_getvar_retry == DEBUG_RETRIES_REREGISTER:
+                    # re-register debug registry to PLC
+                    wx.CallAfter(self.RegisterDebugVarToConnector)
+                if debug_getvar_retry != 0:
+                    # Be patient, tollerate PLC to come up before debugging
+                    time.sleep(0.1)
+            else:
+                self.debug_break = True
+        self.logger.write(_("Debugger disabled\n"))
+        self.DebugThread = None
+
+    def KillDebugThread(self):
+        tmp_debugthread = self.DebugThread
+        self.debug_break = True
+        if tmp_debugthread is not None:
+            self.logger.writeyield(_("Stopping debugger...\n"))
+            tmp_debugthread.join(timeout=5)
+            if tmp_debugthread.isAlive() and self.logger:
+                self.logger.write_warning(_("Couldn't stop debugger.\n"))
+            else:
+                self.logger.write(_("Debugger stopped.\n"))
+        self.DebugThread = None
+
+    def _connect_debug(self): 
+        if self.AppFrame:
+            self.AppFrame.ResetGraphicViewers()
+        self.RegisterDebugVarToConnector()
+        if self.DebugThread is None:
+            self.DebugThread = Thread(target=self.DebugThreadProc)
+            self.DebugThread.start()
+    
+    def _Run(self):
+        """
+        Start PLC
+        """
+        if self.GetIECProgramsAndVariables():
+            self._connector.StartPLC()
+            self.logger.write(_("Starting PLC\n"))
+            self._connect_debug()
+        else:
+            self.logger.write_error(_("Couldn't start PLC !\n"))
+        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+       
+    def _Stop(self):
+        """
+        Stop PLC
+        """
+        if self._connector is not None and not self._connector.StopPLC():
+            self.logger.write_error(_("Couldn't stop PLC !\n"))
+
+        # debugthread should die on his own
+        #self.KillDebugThread()
+        
+        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+
+    def _Connect(self):
+        # don't accept re-connetion is already connected
+        if self._connector is not None:
+            self.logger.write_error(_("Already connected. Please disconnect\n"))
+            return
+        
+        # Get connector uri
+        uri = self.\
+              BeremizRoot.\
+              getURI_location().\
+              strip()
+
+        # if uri is empty launch discovery dialog
+        if uri == "":
+            # Launch Service Discovery dialog
+            dialog = DiscoveryDialog(self.AppFrame)
+            answer = dialog.ShowModal()
+            uri = dialog.GetURI()
+            dialog.Destroy()
+            
+            # Nothing choosed or cancel button
+            if uri is None or answer == wx.ID_CANCEL:
+                self.logger.write_error(_("Connection canceled!\n"))
+                return
+            else:
+                self.\
+                BeremizRoot.\
+                setURI_location(uri)
+       
+        # Get connector from uri
+        try:
+            self._connector = connectors.ConnectorFactory(uri, self)
+        except Exception, msg:
+            self.logger.write_error(_("Exception while connecting %s!\n")%uri)
+            self.logger.write_error(traceback.format_exc())
+
+        # Did connection success ?
+        if self._connector is None:
+            # Oups.
+            self.logger.write_error(_("Connection failed to %s!\n")%uri)
+        else:
+            self.ShowMethod("_Connect", False)
+            self.ShowMethod("_Disconnect", True)
+            self.ShowMethod("_Transfer", True)
+
+            self.CompareLocalAndRemotePLC()
+            
+            # Init with actual PLC status and print it
+            self.UpdateMethodsFromPLCStatus()
+            if self.previous_plcstate is not None:
+                status = _(self.previous_plcstate)
+            else:
+                status = ""
+            self.logger.write(_("PLC is %s\n")%status)
+            
+            # Start the status Timer
+            self.StatusTimer.Start(milliseconds=500, oneShot=False)
+            
+            if self.previous_plcstate=="Started":
+                if self.DebugAvailable() and self.GetIECProgramsAndVariables():
+                    self.logger.write(_("Debug connect matching running PLC\n"))
+                    self._connect_debug()
+                else:
+                    self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n"))
+
+    def CompareLocalAndRemotePLC(self):
+        if self._connector is None:
+            return
+        # We are now connected. Update button status
+        MD5 = self.GetLastBuildMD5()
+        # Check remote target PLC correspondance to that md5
+        if MD5 is not None:
+            if not self._connector.MatchMD5(MD5):
+#                self.logger.write_warning(
+#                   _("Latest build does not match with target, please transfer.\n"))
+                self.EnableMethod("_Transfer", True)
+            else:
+#                self.logger.write(
+#                   _("Latest build matches target, no transfer needed.\n"))
+                self.EnableMethod("_Transfer", True)
+                # warns controller that program match
+                self.ProgramTransferred()
+                #self.EnableMethod("_Transfer", False)
+        else:
+#            self.logger.write_warning(
+#                _("Cannot compare latest build to target. Please build.\n"))
+            self.EnableMethod("_Transfer", False)
+
+
+    def _Disconnect(self):
+        self._connector = None
+        self.StatusTimer.Stop()
+        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+        
+    def _Transfer(self):
+        # Get the last build PLC's 
+        MD5 = self.GetLastBuildMD5()
+        
+        # Check if md5 file is empty : ask user to build PLC 
+        if MD5 is None :
+            self.logger.write_error(_("Failed : Must build before transfer.\n"))
+            return False
+
+        # Compare PLC project with PLC on target
+        if self._connector.MatchMD5(MD5):
+            self.logger.write(
+                _("Latest build already matches current target. Transfering anyway...\n"))
+
+        # Get temprary directory path
+        extrafilespath = self._getExtraFilesPath()
+        extrafiles = [(name, open(os.path.join(extrafilespath, name), 
+                                  'rb').read()) \
+                      for name in os.listdir(extrafilespath) \
+                      if not name=="CVS"]
+
+        # Send PLC on target
+        builder = self.GetBuilder()
+        if builder is not None:
+            data = builder.GetBinaryCode()
+            if data is not None :
+                if self._connector.NewPLC(MD5, data, extrafiles) and self.GetIECProgramsAndVariables():
+                    self.UnsubscribeAllDebugIECVariable()
+                    self.ProgramTransferred()
+                    if self.AppFrame is not None:
+                        self.AppFrame.RefreshInstancesTree()
+                        self.AppFrame.CloseObsoleteDebugTabs()
+                    self.logger.write(_("Transfer completed successfully.\n"))
+                else:
+                    self.logger.write_error(_("Transfer failed\n"))
+            else:
+                self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n"))
+
+        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
+
+    ConfNodeMethods = [
+        {"bitmap" : opjimg("Build"),
+         "name" : _("Build"),
+         "tooltip" : _("Build project into build folder"),
+         "method" : "_Build"},
+        {"bitmap" : opjimg("Clean"),
+         "name" : _("Clean"),
+         "enabled" : False,
+         "tooltip" : _("Clean project build folder"),
+         "method" : "_Clean"},
+        {"bitmap" : opjimg("Run"),
+         "name" : _("Run"),
+         "shown" : False,
+         "tooltip" : _("Start PLC"),
+         "method" : "_Run"},
+        {"bitmap" : opjimg("Stop"),
+         "name" : _("Stop"),
+         "shown" : False,
+         "tooltip" : _("Stop Running PLC"),
+         "method" : "_Stop"},
+        {"bitmap" : opjimg("Connect"),
+         "name" : _("Connect"),
+         "tooltip" : _("Connect to the target PLC"),
+         "method" : "_Connect"},
+        {"bitmap" : opjimg("Transfer"),
+         "name" : _("Transfer"),
+         "shown" : False,
+         "tooltip" : _("Transfer PLC"),
+         "method" : "_Transfer"},
+        {"bitmap" : opjimg("Disconnect"),
+         "name" : _("Disconnect"),
+         "shown" : False,
+         "tooltip" : _("Disconnect from PLC"),
+         "method" : "_Disconnect"},
+        {"bitmap" : opjimg("ShowIECcode"),
+         "name" : _("Show code"),
+         "shown" : False,
+         "tooltip" : _("Show IEC code generated by PLCGenerator"),
+         "method" : "_showIECcode"},
+        {"bitmap" : opjimg("editIECrawcode"),
+         "name" : _("Raw IEC code"),
+         "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"),
+         "method" : "_editIECrawcode"},
+    ]
--- a/LPCBeremiz.py	Thu May 03 19:02:34 2012 +0200
+++ b/LPCBeremiz.py	Mon May 07 18:47:29 2012 +0200
@@ -59,25 +59,25 @@
     __builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation
 
 from Beremiz import *
-from plugger import PluginsRoot, PlugTemplate, opjimg, connectors
+from ConfigTree import ConfigTreeRoot, ConfigTreeNode, opjimg, connectors
 from plcopen.structures import LOCATIONDATATYPES
-from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP,\
+from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP,\
                          LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
 from PLCOpenEditor import IDEFrame, ProjectDialog
 
 havecanfestival = False
 try:
-    from plugins.canfestival import RootClass as CanOpenRootClass
-    from plugins.canfestival.canfestival import _SlavePlug, _NodeListPlug, NodeManager
+    from confnodes.canfestival import RootClass as CanOpenRootClass
+    from confnodes.canfestival.canfestival import _SlavePlug, _NodeListPlug, NodeManager
     havecanfestival = True
 except:
     havecanfestival = False
     
 
 #-------------------------------------------------------------------------------
-#                          CANFESTIVAL PLUGIN HACK
+#                          CANFESTIVAL CONFNODE HACK
 #-------------------------------------------------------------------------------
-# from plugins.canfestival import canfestival
+# from confnodes.canfestival import canfestival
 # class LPC_canfestival_config:
 #     def getCFLAGS(self, *args):
 #         return ""
@@ -148,9 +148,9 @@
             if group["type"] == LOCATION_GROUP and child in group["children"]:
                 group["children"].remove(child)
 
-BUS_TEXT = """/* Code generated by LPCBus plugin */
-
-/* LPCBus plugin includes */
+BUS_TEXT = """/* Code generated by LPCBus confnode */
+
+/* LPCBus confnode includes */
 #include "app_glue.h"
 #ifdef _WINDOWS_H
   #include "iec_types.h"
@@ -160,10 +160,10 @@
 
 %(declare_code)s
 
-/* LPCBus plugin user variables definition */
+/* LPCBus confnode user variables definition */
 %(var_decl)s
 
-/* LPCBus plugin functions */
+/* LPCBus confnode functions */
 int __init_%(location_str)s(int argc,char **argv)
 {
 %(init_code)s
@@ -240,7 +240,7 @@
     
     def GetVariableLocationTree(self):
         return {"name": self.BaseParams.getName(),
-                "type": LOCATION_PLUGIN,
+                "type": LOCATION_CONFNODE,
                 "location": self.GetFullIEC_Channel(),
                 "icon": self.Icon, 
                 "children": [self._GetVariableLocationTree(self.GetCurrentLocation(), child) 
@@ -291,7 +291,7 @@
     def PlugGenerate_C(self, buildpath, locations):
         """
         Generate C code
-        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
+        @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
         @param locations: List of complete variables locations \
             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
             "NAME" : name of the variable (generally "__IW0_1_2" style)
@@ -367,7 +367,7 @@
         return [(Gen_Module_path, matiec_flags)],"",True
 
 #-------------------------------------------------------------------------------
-#                          LPC CanFestival Plugin Class
+#                          LPC CanFestival ConfNode Class
 #-------------------------------------------------------------------------------
 
 if havecanfestival:
@@ -444,7 +444,7 @@
             return ""
         
         def LoadChilds(self):
-            PlugTemplate.LoadChilds(self)
+            ConfigTreeNode.LoadChilds(self)
             
             if self.GetChildByName("Master") is None:
                 master = self.PlugAddChild("Master", "CanOpenNode", 0)
@@ -456,7 +456,7 @@
     
 
 #-------------------------------------------------------------------------------
-#                              LPCPluginsRoot Class
+#                              LPCConfigTreeRoot Class
 #-------------------------------------------------------------------------------
 
 def mycopytree(src, dst):
@@ -479,9 +479,9 @@
 
 [SIMULATION_MODE, TRANSFER_MODE] = range(2)
 
-class LPCPluginsRoot(PluginsRoot):
-
-    PluginMethods = [
+class LPCConfigTreeRoot(ConfigTreeRoot):
+
+    ConfNodeMethods = [
         {"bitmap" : opjimg("Debug"),
          "name" : _("Simulate"),
          "tooltip" : _("Simulate PLC"),
@@ -510,7 +510,7 @@
     def __init__(self, frame, logger, buildpath):
         self.OrigBuildPath = buildpath
         
-        PluginsRoot.__init__(self, frame, logger)
+        ConfigTreeRoot.__init__(self, frame, logger)
         
         if havecanfestival:
             self.PlugChildsTypes += [("LPCBus", LPCBus, "LPC bus"), ("CanOpen", LPCCanOpen, "CanOpen bus")]
@@ -528,23 +528,23 @@
         
         self.AbortTransferTimer = None
     
-    def PluginLibraryFilePath(self):
+    def ConfNodeLibraryFilePath(self):
         if self.OrigBuildPath is not None:
             return os.path.join(self.OrigBuildPath, "pous.xml")
         else:
-            return PluginsRoot.PluginLibraryFilePath(self)
+            return ConfigTreeRoot.ConfNodeLibraryFilePath(self)
     
     def GetProjectName(self):
         return self.Project.getname()
 
     def GetDefaultTargetName(self):
         if self.CurrentMode == SIMULATION_MODE:
-            return PluginsRoot.GetDefaultTargetName(self)
+            return ConfigTreeRoot.GetDefaultTargetName(self)
         else:
             return "LPC"
 
     def GetTarget(self):
-        target = PluginsRoot.GetTarget(self)
+        target = ConfigTreeRoot.GetTarget(self)
         if self.CurrentMode != SIMULATION_MODE:
             target.getcontent()["value"].setBuildPath(self.BuildPath)
         return target
@@ -555,7 +555,7 @@
                 self.SimulationBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
             return self.SimulationBuildPath
         else:
-            return PluginsRoot._getBuildPath(self)
+            return ConfigTreeRoot._getBuildPath(self)
 
     def _Build(self):
         save = self.ProjectTestModified()
@@ -564,7 +564,7 @@
             self.AppFrame._Refresh(TITLE, FILEMENU)
         if self.BuildPath is not None:
             mycopytree(self.OrigBuildPath, self.BuildPath)
-        PluginsRoot._Build(self)
+        ConfigTreeRoot._Build(self)
         if save:
             wx.CallAfter(self.AppFrame.RefreshAll)
     
@@ -678,7 +678,7 @@
         self._AddParamsMembers()
         self.PluggedChilds = {}
         
-        # Keep track of the root plugin (i.e. project path)
+        # Keep track of the root confnode (i.e. project path)
         self.ProjectPath = ProjectPath
         
         self.BuildPath = self._getBuildPath()
@@ -686,8 +686,8 @@
             mycopytree(self.OrigBuildPath, self.BuildPath)
         
         # If dir have already be made, and file exist
-        if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
-            #Load the plugin.xml file into parameters members
+        if os.path.isdir(self.PlugPath()) and os.path.isfile(self.ConfNodeXmlFilePath()):
+            #Load the confnode.xml file into parameters members
             result = self.LoadXMLParams()
             if result:
                 return result
@@ -703,9 +703,9 @@
             self.SaveProject()
         
         if wx.GetApp() is None:
-            self.RefreshPluginsBlockLists()
+            self.RefreshConfNodesBlockLists()
         else:
-            wx.CallAfter(self.RefreshPluginsBlockLists)
+            wx.CallAfter(self.RefreshConfNodesBlockLists)
 
         return None
 
@@ -889,7 +889,7 @@
         else:
             self.LocationCFilesAndCFLAGS = []
 
-        # plugin asks for some LDFLAGS
+        # confnode asks for some LDFLAGS
         if PlugLDFLAGS:
             # LDFLAGS can be either string
             if type(PlugLDFLAGS)==type(str()):
@@ -901,7 +901,7 @@
             self.LDFLAGS=[]
         
         # Template based part of C code generation
-        # files are stacked at the beginning, as files of plugin tree root
+        # files are stacked at the beginning, as files of confnode tree root
         for generator, filename, name in [
            # debugger code
            (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
@@ -918,7 +918,7 @@
                      raise
                 code_path = os.path.join(buildpath,filename)
                 open(code_path, "w").write(code)
-                # Insert this file as first file to be compiled at root plugin
+                # Insert this file as first file to be compiled at root confnode
                 self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS))
             except Exception, exc:
                 self.logger.write_error(name+_(" generation failed !\n"))
@@ -970,7 +970,7 @@
         self.ApplyOnlineMode()
     
     def _Stop(self):
-        PluginsRoot._Stop(self)
+        ConfigTreeRoot._Stop(self)
         
         if self.CurrentMode == SIMULATION_MODE:
             self.StopSimulation()
@@ -1001,7 +1001,7 @@
         if self.CurrentMode is None and self.OnlineMode != "OFF":
             self.CurrentMode = TRANSFER_MODE
             
-            if PluginsRoot._Build(self):
+            if ConfigTreeRoot._Build(self):
             
                 ID_ABORTTRANSFERTIMER = wx.NewId()
                 self.AbortTransferTimer = wx.Timer(self.AppFrame, ID_ABORTTRANSFERTIMER)
@@ -1023,7 +1023,7 @@
         self.logger.write(_("Start PLC transfer\n"))
         
         self.AbortTransferTimer.Stop()
-        PluginsRoot._Transfer(self)
+        ConfigTreeRoot._Transfer(self)
         self.AbortTransferTimer.Start(milliseconds=5000, oneShot=True)
     
     def AbortTransfer(self, event):
@@ -1113,11 +1113,11 @@
             
             frame.Hide()
             
-            self.PluginRoot.ResetAppFrame(lpcberemiz_cmd.Log)
-            if self.PluginRoot.OnlineMode == 0:
-                self.PluginRoot._connector = None
-            
-            self.PluginRoot.KillDebugThread()
+            self.CTR.ResetAppFrame(lpcberemiz_cmd.Log)
+            if self.CTR.OnlineMode == 0:
+                self.CTR._connector = None
+            
+            self.CTR.KillDebugThread()
             self.KillLocalRuntime()
             
             self.SaveLastState()
@@ -1141,7 +1141,7 @@
 
     def RefreshFileMenu(self):
         MenuToolBar = self.Panes["MenuToolBar"]
-        if self.PluginRoot is not None:
+        if self.CTR is not None:
             selected = self.TabsOpened.GetSelection()
             if selected >= 0:
                 graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer)
@@ -1163,7 +1163,7 @@
                 self.FileMenu.Enable(wx.ID_PRINT, False)
                 MenuToolBar.EnableTool(wx.ID_PRINT, False)
             self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
-            project_modified = self.PluginRoot.ProjectTestModified()
+            project_modified = self.CTR.ProjectTestModified()
             self.FileMenu.Enable(wx.ID_SAVE, project_modified)
             MenuToolBar.EnableTool(wx.ID_SAVE, project_modified)
             self.FileMenu.Enable(wx.ID_PROPERTIES, True)
@@ -1181,15 +1181,15 @@
         self.Freeze()
         self.ClearSizer(self.PLCParamsSizer)
         
-        if self.PluginRoot is not None:    
+        if self.CTR is not None:    
             plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
-            if self.PluginRoot.PlugTestModified():
+            if self.CTR.PlugTestModified():
                 bkgdclr = CHANGED_TITLE_COLOUR
             else:
                 bkgdclr = TITLE_COLOUR
                 
-            if self.PluginRoot not in self.PluginInfos:
-                self.PluginInfos[self.PluginRoot] = {"right_visible" : False}
+            if self.CTR not in self.ConfNodeInfos:
+                self.ConfNodeInfos[self.CTR] = {"right_visible" : False}
             
             plcwindow.SetBackgroundColour(TITLE_COLOUR)
             plcwindow.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
@@ -1200,7 +1200,7 @@
             
             st = wx.StaticText(plcwindow, -1)
             st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
-            st.SetLabel(self.PluginRoot.GetProjectName())
+            st.SetLabel(self.CTR.GetProjectName())
             plcwindowsizer.AddWindow(st, 0, border=5, flag=wx.ALL|wx.ALIGN_CENTER)
             
             plcwindowmainsizer = wx.BoxSizer(wx.VERTICAL)
@@ -1209,38 +1209,38 @@
             plcwindowbuttonsizer = wx.BoxSizer(wx.HORIZONTAL)
             plcwindowmainsizer.AddSizer(plcwindowbuttonsizer, 0, border=0, flag=wx.ALIGN_CENTER)
             
-            msizer = self.GenerateMethodButtonSizer(self.PluginRoot, plcwindow, not self.PluginInfos[self.PluginRoot]["right_visible"])
+            msizer = self.GenerateMethodButtonSizer(self.CTR, plcwindow, not self.ConfNodeInfos[self.CTR]["right_visible"])
             plcwindowbuttonsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW)
             
         self.PLCConfigMainSizer.Layout()
         self.RefreshScrollBars()
         self.Thaw()
 
-    def GenerateTreeBranch(self, plugin):
+    def GenerateTreeBranch(self, confnode):
         leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
-        if plugin.PlugTestModified():
+        if confnode.PlugTestModified():
             bkgdclr=CHANGED_WINDOW_COLOUR
         else:
             bkgdclr=WINDOW_COLOUR
 
         leftwindow.SetBackgroundColour(bkgdclr)
         
-        if plugin not in self.PluginInfos:
-            self.PluginInfos[plugin] = {"expanded" : False, "left_visible" : False, "right_visible" : False}
-            
-        self.PluginInfos[plugin]["children"] = plugin.IECSortedChilds()
-        plugin_infos = plugin.GetVariableLocationTree()
-        plugin_locations = []
-        if len(self.PluginInfos[plugin]["children"]) == 0:
-            plugin_locations = plugin_infos["children"]
-            if not self.PluginInfos[plugin].has_key("locations_infos"):
-                self.PluginInfos[plugin]["locations_infos"] = {"root": {"expanded" : False}}
-            
-            self.PluginInfos[plugin]["locations_infos"]["root"]["left"] = None
-            self.PluginInfos[plugin]["locations_infos"]["root"]["right"] = None
-            self.PluginInfos[plugin]["locations_infos"]["root"]["children"] = []
-        
-        self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
+        if confnode not in self.ConfNodeInfos:
+            self.ConfNodeInfos[confnode] = {"expanded" : False, "left_visible" : False, "right_visible" : False}
+            
+        self.ConfNodeInfos[confnode]["children"] = confnode.IECSortedChilds()
+        confnode_infos = confnode.GetVariableLocationTree()
+        confnode_locations = []
+        if len(self.ConfNodeInfos[confnode]["children"]) == 0:
+            confnode_locations = confnode_infos["children"]
+            if not self.ConfNodeInfos[confnode].has_key("locations_infos"):
+                self.ConfNodeInfos[confnode]["locations_infos"] = {"root": {"expanded" : False}}
+            
+            self.ConfNodeInfos[confnode]["locations_infos"]["root"]["left"] = None
+            self.ConfNodeInfos[confnode]["locations_infos"]["root"]["right"] = None
+            self.ConfNodeInfos[confnode]["locations_infos"]["root"]["children"] = []
+        
+        self.ConfNodeTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
         
         leftwindowvsizer = wx.BoxSizer(wx.VERTICAL)
         leftwindow.SetSizer(leftwindowvsizer)
@@ -1248,11 +1248,11 @@
         leftwindowsizer = wx.BoxSizer(wx.HORIZONTAL)
         leftwindowvsizer.AddSizer(leftwindowsizer, 0, border=0, flag=0)
         
-        self.GenerateEnableButton(leftwindow, leftwindowsizer, plugin)
+        self.GenerateEnableButton(leftwindow, leftwindowsizer, confnode)
         
         st = wx.StaticText(leftwindow, -1)
         st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
-        st.SetLabel(plugin.GetFullIEC_Channel())
+        st.SetLabel(confnode.GetFullIEC_Channel())
         leftwindowsizer.AddWindow(st, 0, border=5, flag=wx.RIGHT)
         
         expandbutton_id = wx.NewId()
@@ -1264,27 +1264,27 @@
         expandbutton.SetUseFocusIndicator(False)
         expandbutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'minus.png')))
             
-        if len(self.PluginInfos[plugin]["children"]) > 0:
-            expandbutton.SetToggle(self.PluginInfos[plugin]["expanded"])
+        if len(self.ConfNodeInfos[confnode]["children"]) > 0:
+            expandbutton.SetToggle(self.ConfNodeInfos[confnode]["expanded"])
             def togglebutton(event):
                 if expandbutton.GetToggle():
-                    self.ExpandPlugin(plugin)
+                    self.ExpandConfNode(confnode)
                 else:
-                    self.CollapsePlugin(plugin)
-                self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+                    self.CollapseConfNode(confnode)
+                self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
                 self.PLCConfigMainSizer.Layout()
                 self.RefreshScrollBars()
                 event.Skip()
             expandbutton.Bind(wx.EVT_BUTTON, togglebutton, id=expandbutton_id)
-        elif len(plugin_locations) > 0:
-            locations_infos = self.PluginInfos[plugin]["locations_infos"]
+        elif len(confnode_locations) > 0:
+            locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
             expandbutton.SetToggle(locations_infos["root"]["expanded"])
             def togglebutton(event):
                 if expandbutton.GetToggle():
                     self.ExpandLocation(locations_infos, "root")
                 else:
                     self.CollapseLocation(locations_infos, "root")
-                self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle()
+                self.ConfNodeInfos[confnode]["expanded"] = expandbutton.GetToggle()
                 locations_infos["root"]["expanded"] = expandbutton.GetToggle()
                 self.PLCConfigMainSizer.Layout()
                 self.RefreshScrollBars()
@@ -1295,9 +1295,9 @@
         leftwindowsizer.AddWindow(expandbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
         
         sb = wx.StaticBitmap(leftwindow, -1)
-        icon = plugin_infos.get("icon", None)
+        icon = confnode_infos.get("icon", None)
         if icon is None:
-            icon_bitmap = self.LocationImageList.GetBitmap(self.LocationImageDict[plugin_infos["type"]])
+            icon_bitmap = self.LocationImageList.GetBitmap(self.LocationImageDict[confnode_infos["type"]])
         else: 
             icon_bitmap = wx.Bitmap(icon)
         sb.SetBitmap(icon_bitmap)
@@ -1306,21 +1306,21 @@
         st_id = wx.NewId()
         st = wx.StaticText(leftwindow, st_id, size=wx.DefaultSize, style=wx.NO_BORDER)
         st.SetFont(wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
-        st.SetLabel(plugin.MandatoryParams[1].getName())
+        st.SetLabel(confnode.MandatoryParams[1].getName())
         leftwindowsizer.AddWindow(st, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
         
-        rightwindow = self.GenerateParamsPanel(plugin, bkgdclr)
-        self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
-
-        self.PluginInfos[plugin]["left"] = leftwindow
-        self.PluginInfos[plugin]["right"] = rightwindow
-        for child in self.PluginInfos[plugin]["children"]:
+        rightwindow = self.GenerateParamsPanel(confnode, bkgdclr)
+        self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+
+        self.ConfNodeInfos[confnode]["left"] = leftwindow
+        self.ConfNodeInfos[confnode]["right"] = rightwindow
+        for child in self.ConfNodeInfos[confnode]["children"]:
             self.GenerateTreeBranch(child)
-            if not self.PluginInfos[child]["expanded"]:
-                self.CollapsePlugin(child)
-        
-        if len(plugin_locations) > 0:
-            locations_infos = self.PluginInfos[plugin]["locations_infos"]
+            if not self.ConfNodeInfos[child]["expanded"]:
+                self.CollapseConfNode(child)
+        
+        if len(confnode_locations) > 0:
+            locations_infos = self.ConfNodeInfos[confnode]["locations_infos"]
             treectrl = wx.TreeCtrl(self.PLCConfig, -1, size=wx.DefaultSize, 
                                    style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.NO_BORDER|wx.TR_HIDE_ROOT|wx.TR_NO_LINES|wx.TR_LINES_AT_ROOT)
             treectrl.SetImageList(self.LocationImageList)
@@ -1329,15 +1329,15 @@
             treectrl.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.GenerateLocationExpandCollapseFunction(locations_infos, False))
             
             treectrl.AddRoot("")
-            self.PluginTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
+            self.ConfNodeTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
             
             rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
             rightwindow.SetBackgroundColour(wx.WHITE)
-            self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
+            self.ConfNodeTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
             
             locations_infos["root"]["left"] = treectrl
             locations_infos["root"]["right"] = rightwindow
-            for location in plugin_locations:
+            for location in confnode_locations:
                 locations_infos["root"]["children"].append("root.%s" % location["name"])
                 self.GenerateLocationTreeBranch(treectrl, treectrl.GetRootItem(), locations_infos, "root", location)
             if locations_infos["root"]["expanded"]:
@@ -1416,11 +1416,11 @@
         prompt = ""
         RefreshTimer = None
         
-        def __init__(self, PluginRoot, Log):
+        def __init__(self, CTR, Log):
             cmd.Cmd.__init__(self, stdin=Log, stdout=Log)
             self.use_rawinput = False
             self.Log = Log
-            self.PluginRoot = PluginRoot
+            self.CTR = CTR
             
         def RestartTimer(self):
             if self.RefreshTimer is not None:
@@ -1440,7 +1440,7 @@
         def Show(self):
             global frame
             if frame is not None:
-                self.PluginRoot.SetAppFrame(frame, frame.Log)
+                self.CTR.SetAppFrame(frame, frame.Log)
                 frame.Show()
                 frame.Raise()
         
@@ -1454,77 +1454,77 @@
         def Close(self):
             global frame
             
-            self.PluginRoot.ResetAppFrame(self.Log)
+            self.CTR.ResetAppFrame(self.Log)
             if frame is not None:
                 frame.Hide()
         
         def Compile(self):
-            self.PluginRoot._Build()
+            self.CTR._Build()
         
         def SetProjectProperties(self, projectname, productname, productversion, companyname):
-            properties = self.PluginRoot.GetProjectProperties()
+            properties = self.CTR.GetProjectProperties()
             new_properties = properties.copy()
             new_properties["projectName"] = projectname
             new_properties["productName"] = productname
             new_properties["productVersion"] = productversion
             new_properties["companyName"] = companyname
             if new_properties != properties:
-                self.PluginRoot.SetProjectProperties(properties=new_properties, buffer=False)
+                self.CTR.SetProjectProperties(properties=new_properties, buffer=False)
                 self.RestartTimer()
         
         def SetOnlineMode(self, mode, path=None):
-            self.PluginRoot.SetOnlineMode(mode, path)
+            self.CTR.SetOnlineMode(mode, path)
             self.RestartTimer()
         
         def AddBus(self, iec_channel, name, icon=None):
-            for child in self.PluginRoot.IterChilds():
+            for child in self.CTR.IterChilds():
                 if child.BaseParams.getName() == name:
                     return "Error: A bus named %s already exists\n" % name
                 elif child.BaseParams.getIEC_Channel() == iec_channel:
                     return "Error: A bus with IEC_channel %d already exists\n" % iec_channel
-            bus = self.PluginRoot.PlugAddChild(name, "LPCBus", iec_channel)
+            bus = self.CTR.PlugAddChild(name, "LPCBus", iec_channel)
             if bus is None:
                 return "Error: Unable to create bus\n"
             bus.SetIcon(icon)
             self.RestartTimer()
         
         def RenameBus(self, iec_channel, name):
-            bus = self.PluginRoot.GetChildByIECLocation((iec_channel,))
+            bus = self.CTR.GetChildByIECLocation((iec_channel,))
             if bus is None:
                 return "Error: No bus found\n"
-            for child in self.PluginRoot.IterChilds():
+            for child in self.CTR.IterChilds():
                 if child != bus and child.BaseParams.getName() == name:
                     return "Error: A bus named %s already exists\n" % name
             bus.BaseParams.setName(name)
             self.RestartTimer()
         
         def ChangeBusIECChannel(self, old_iec_channel, new_iec_channel):
-            bus = self.PluginRoot.GetChildByIECLocation((old_iec_channel,))
+            bus = self.CTR.GetChildByIECLocation((old_iec_channel,))
             if bus is None:
                 return "Error: No bus found\n"
-            for child in self.PluginRoot.IterChilds():
+            for child in self.CTR.IterChilds():
                 if child != bus and child.BaseParams.getIEC_Channel() == new_iec_channel:
                     return "Error: A bus with IEC_channel %d already exists\n" % new_iec_channel
             if wx.GetApp() is None:
-                self.PluginRoot.UpdateProjectVariableLocation(str(old_iec_channel), 
+                self.CTR.UpdateProjectVariableLocation(str(old_iec_channel), 
                                                               str(new_iec_channel))
             else:
-                self.PluginRoot.UpdateProjectVariableLocation(
+                self.CTR.UpdateProjectVariableLocation(
                              str(old_iec_channel), 
                              str(new_iec_channel))
             bus.BaseParams.setIEC_Channel(new_iec_channel)
             self.RestartTimer()
         
         def RemoveBus(self, iec_channel):
-            bus = self.PluginRoot.GetChildByIECLocation((iec_channel,))
+            bus = self.CTR.GetChildByIECLocation((iec_channel,))
             if bus is None:
                 return "Error: No bus found\n"
-            self.PluginRoot.RemoveProjectVariableByFilter(str(iec_channel))
-            self.PluginRoot.PluggedChilds["LPCBus"].remove(bus)
+            self.CTR.RemoveProjectVariableByFilter(str(iec_channel))
+            self.CTR.PluggedChilds["LPCBus"].remove(bus)
             self.RestartTimer()
     
         def AddModule(self, parent, iec_channel, name, icode, icon=None):
-            module = self.PluginRoot.GetChildByIECLocation(parent)
+            module = self.CTR.GetChildByIECLocation(parent)
             if module is None:
                 return "Error: No parent found\n"
             for child in _GetModuleChildren(module):
@@ -1541,11 +1541,11 @@
             self.RestartTimer()
     
         def RenameModule(self, iec_location, name):
-            module = self.PluginRoot.GetChildByIECLocation(iec_location)
+            module = self.CTR.GetChildByIECLocation(iec_location)
             if module is None:
                 return "Error: No module found\n"
-            parent = self.PluginRoot.GetChildByIECLocation(iec_location[:-1])
-            if parent is self.PluginRoot:
+            parent = self.CTR.GetChildByIECLocation(iec_location[:-1])
+            if parent is self.CTR:
                 return "Error: No module found\n"
             if module["name"] != name:
                 for child in _GetModuleChildren(parent):
@@ -1555,39 +1555,39 @@
             self.RestartTimer()
     
         def ChangeModuleIECChannel(self, old_iec_location, new_iec_channel):
-            module = self.PluginRoot.GetChildByIECLocation(old_iec_location)
+            module = self.CTR.GetChildByIECLocation(old_iec_location)
             if module is None:
                 return "Error: No module found\n"
-            parent = self.PluginRoot.GetChildByIECLocation(old_iec_location[:-1])
-            if parent is self.PluginRoot:
+            parent = self.CTR.GetChildByIECLocation(old_iec_location[:-1])
+            if parent is self.CTR:
                 return "Error: No module found\n"
             if module["IEC_Channel"] != new_iec_channel:
                 for child in _GetModuleChildren(parent):
                     if child["IEC_Channel"] == new_iec_channel:
                         return "Error: A module with IEC_channel %d already exists\n" % new_iec_channel
-            self.PluginRoot.UpdateProjectVariableLocation(".".join(map(str, old_iec_location)), ".".join(map(str, old_iec_location[:1] + (new_iec_channel,))))
+            self.CTR.UpdateProjectVariableLocation(".".join(map(str, old_iec_location)), ".".join(map(str, old_iec_location[:1] + (new_iec_channel,))))
             module["IEC_Channel"] = new_iec_channel
             self.RestartTimer()
         
         def ChangeModuleInitCode(self, iec_location, icode):
-            module = self.PluginRoot.GetChildByIECLocation(iec_location)
+            module = self.CTR.GetChildByIECLocation(iec_location)
             if module is None:
                 return "Error: No module found\n"
             module["init"] = icode
         
         def RemoveModule(self, parent, iec_channel):
-            module = self.PluginRoot.GetChildByIECLocation(parent)
+            module = self.CTR.GetChildByIECLocation(parent)
             if module is None:
                 return "Error: No parent found\n"
             child = _GetModuleBySomething(module, "IEC_Channel", (iec_channel,))
             if child is None:
                 return "Error: No module found\n"
-            self.PluginRoot.RemoveProjectVariableByFilter(".".join(map(str, parent + (iec_channel,))))
+            self.CTR.RemoveProjectVariableByFilter(".".join(map(str, parent + (iec_channel,))))
             _RemoveModuleChild(module, child)
             self.RestartTimer()
         
         def StartGroup(self, parent, name, icon=None):
-            module = self.PluginRoot.GetChildByIECLocation(parent)
+            module = self.CTR.GetChildByIECLocation(parent)
             if module is None:
                 return "Error: No parent found\n"
             for child in module["children"]:
@@ -1600,7 +1600,7 @@
             self.RestartTimer()
     
         def AddVariable(self, parent, location, name, direction, type, rcode, pcode, description=""):
-            module = self.PluginRoot.GetChildByIECLocation(parent)
+            module = self.CTR.GetChildByIECLocation(parent)
             if module is None:
                 return "Error: No parent found\n"
             for child in _GetModuleChildren(module):
@@ -1618,7 +1618,7 @@
             self.RestartTimer()
 
         def ChangeVariableParams(self, parent, location, new_name, new_direction, new_type, new_rcode, new_pcode, new_description=None):
-            module = self.PluginRoot.GetChildByIECLocation(parent)
+            module = self.CTR.GetChildByIECLocation(parent)
             if module is None:
                 return "Error: No parent found\n"
             variable = None
@@ -1630,7 +1630,7 @@
             if variable is None:
                 return "Error: No variable found\n"
             if variable["name"] != new_name:
-                self.PluginRoot.UpdateProjectVariableName(variable["name"], new_name)
+                self.CTR.UpdateProjectVariableName(variable["name"], new_name)
                 variable["name"] = new_name
             variable["type"] = LOCATION_TYPES[new_direction]
             variable["IEC_type"] = new_type
@@ -1641,15 +1641,15 @@
             self.RestartTimer()
     
         def RemoveVariable(self, parent, location, direction):
-            module = self.PluginRoot.GetChildByIECLocation(parent)
+            module = self.CTR.GetChildByIECLocation(parent)
             if module is None:
                 return "Error: No parent found\n"
             child = _GetModuleVariable(module, location, direction)
             if child is None:
                 return "Error: No variable found\n"
-            size = LOCATION_SIZES[self.PluginRoot.GetBaseType(child["IEC_type"])]
+            size = LOCATION_SIZES[self.CTR.GetBaseType(child["IEC_type"])]
             address = "%" + LOCATION_DIRS[child["type"]] + size + ".".join(map(str, parent + location))
-            self.PluginRoot.RemoveProjectVariableByAddress(address)
+            self.CTR.RemoveProjectVariableByAddress(address)
             _RemoveModuleChild(module, child)
             self.RestartTimer()
         
@@ -1714,7 +1714,7 @@
                 return res
         return CmdFunction
 
-    def CmdThreadProc(PluginRoot, Log):
+    def CmdThreadProc(CTR, Log):
         global lpcberemiz_cmd
         for function, (arg_types, opt) in {"Exit": ([], 0),
                                            "Show": ([], 0),
@@ -1738,26 +1738,26 @@
                                            "RemoveVariable": ([location, location], 0)}.iteritems():
             
             setattr(LPCBeremiz_Cmd, "do_%s" % function, GetCmdFunction(function, arg_types, opt))
-        lpcberemiz_cmd = LPCBeremiz_Cmd(PluginRoot, Log)
+        lpcberemiz_cmd = LPCBeremiz_Cmd(CTR, Log)
         lpcberemiz_cmd.cmdloop()
 
     Log = StdoutPseudoFile(port)
 
-    PluginRoot = LPCPluginsRoot(None, Log, buildpath)
+    CTR = LPCConfigTreeRoot(None, Log, buildpath)
     if projectOpen is not None and os.path.isdir(projectOpen):
-        result = PluginRoot.LoadProject(projectOpen)
+        result = CTR.LoadProject(projectOpen)
         if result:
             Log.write("Error: Invalid project directory", result)
     else:
         Log.write("Error: No such file or directory")
     
-    cmd_thread=Thread(target=CmdThreadProc, args=[PluginRoot, Log])
+    cmd_thread=Thread(target=CmdThreadProc, args=[CTR, Log])
     cmd_thread.start()
 
     # Install a exception handle for bug reports
     AddExceptHook(os.getcwd(),__version__)
     
-    frame = LPCBeremiz(None, plugin_root=PluginRoot, debug=True)
+    frame = LPCBeremiz(None, ctr=CTR, debug=True)
     
     app.MainLoop()
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/.cvsignore	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,13 @@
+from os import listdir, path
+
+_base_path = path.split(__file__)[0]
+
+__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
+
+helps = []
+for name in __all__:
+    helpfilename = path.join(_base_path, name, "README")
+    if path.isfile(helpfilename):
+        helps.append(open(helpfilename).readline().strip())
+    else:
+        helps.append(name)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/.cvsignore	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/CFileEditor.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,967 @@
+import keyword
+
+import wx
+import wx.grid
+import wx.stc as stc
+import wx.lib.buttons
+
+from controls import CustomGrid, CustomTable, EditorPanel
+
+if wx.Platform == '__WXMSW__':
+    faces = { 'times': 'Times New Roman',
+              'mono' : 'Courier New',
+              'helv' : 'Arial',
+              'other': 'Comic Sans MS',
+              'size' : 10,
+              'size2': 8,
+             }
+else:
+    faces = { 'times': 'Times',
+              'mono' : 'Courier',
+              'helv' : 'Helvetica',
+              'other': 'new century schoolbook',
+              'size' : 12,
+              'size2': 10,
+             }
+
+
+def AppendMenu(parent, help, id, kind, text):
+    if wx.VERSION >= (2, 6, 0):
+        parent.Append(help=help, id=id, kind=kind, text=text)
+    else:
+        parent.Append(helpString=help, id=id, kind=kind, item=text)
+
+
+[ID_CPPEDITOR,
+] = [wx.NewId() for _init_ctrls in range(1)]
+
+CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", 
+    "const", "const_cast", "continue", "default", "delete", "do", "double", 
+    "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", 
+    "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", 
+    "namespace", "new", "operator", "private", "protected", "public", "register", 
+    "reinterpret_cast", "return", "short", "signed", "sizeof", "static", 
+    "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
+    "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", 
+    "void", "volatile", "wchar_t", "while"]
+
+def GetCursorPos(old, new):
+    old_length = len(old)
+    new_length = len(new)
+    common_length = min(old_length, new_length)
+    i = 0
+    for i in xrange(common_length):
+        if old[i] != new[i]:
+            break
+    if old_length < new_length:
+        if common_length > 0 and old[i] != new[i]:
+            return i + new_length - old_length
+        else:
+            return i + new_length - old_length + 1
+    elif old_length > new_length or i < min(old_length, new_length) - 1:
+        if common_length > 0 and old[i] != new[i]:
+            return i
+        else:
+            return i + 1
+    else:
+        return None
+
+class CppEditor(stc.StyledTextCtrl):
+
+    fold_symbols = 3
+    
+    def __init__(self, parent, name, window, controler):
+        stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, 
+                 wx.Size(0, 0), 0)
+
+        self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
+        self.SetMarginWidth(1, 25)
+
+        self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
+        self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
+
+        self.SetLexer(stc.STC_LEX_CPP)
+        self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
+
+        self.SetProperty("fold", "1")
+        self.SetProperty("tab.timmy.whinge.level", "1")
+        self.SetMargins(0,0)
+
+        self.SetViewWhiteSpace(False)
+        #self.SetBufferedDraw(False)
+        #self.SetViewEOL(True)
+        #self.SetEOLMode(stc.STC_EOL_CRLF)
+        #self.SetUseAntiAliasing(True)
+        
+        self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
+        self.SetEdgeColumn(78)
+
+        # Setup a margin to hold fold markers
+        #self.SetFoldFlags(16)  ###  WHAT IS THIS VALUE?  WHAT ARE THE OTHER FLAGS?  DOES IT MATTER?
+        self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
+        self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
+        self.SetMarginSensitive(2, True)
+        self.SetMarginWidth(2, 12)
+
+        if self.fold_symbols == 0:
+            # Arrow pointing right for contracted folders, arrow pointing down for expanded
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
+            
+        elif self.fold_symbols == 1:
+            # Plus for contracted folders, minus for expanded
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
+
+        elif self.fold_symbols == 2:
+            # Like a flattened tree control using circular headers and curved joins
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
+
+        elif self.fold_symbols == 3:
+            # Like a flattened tree control using square headers
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
+            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
+
+
+        self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+        self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
+
+        # Make some styles,  The lexer defines what each style is used for, we
+        # just have to define what each style looks like.  This set is adapted from
+        # Scintilla sample property files.
+
+        # Global default styles for all languages
+        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
+        self.StyleClearAll()  # Reset all to be like the default
+
+        # Global default styles for all languages
+        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
+        self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
+        self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
+        self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
+        self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
+
+        self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
+        self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
+        self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
+        self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
+        self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
+        self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
+        self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
+        self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
+        self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
+        
+        # register some images for use in the AutoComplete box.
+        #self.RegisterImage(1, images.getSmilesBitmap())
+        self.RegisterImage(1, 
+            wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
+        self.RegisterImage(2, 
+            wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
+        self.RegisterImage(3, 
+            wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
+
+        # Indentation size
+        self.SetTabWidth(2)
+        self.SetUseTabs(0)
+
+        self.Controler = controler
+        self.ParentWindow = window
+        
+        self.DisableEvents = True
+        self.Name = name
+        self.CurrentAction = None
+        
+        self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
+
+        self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
+        self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+        self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
+    
+    def OnModification(self, event):
+        if not self.DisableEvents:
+            mod_type = event.GetModificationType()
+            if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
+                if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
+                    if self.CurrentAction == None:
+                        self.StartBuffering()
+                    elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
+                        self.Controler.EndBuffering()
+                        self.StartBuffering()
+                    self.CurrentAction = ("Add", event.GetPosition())
+                    wx.CallAfter(self.RefreshModel)
+                elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
+                    if self.CurrentAction == None:
+                        self.StartBuffering()
+                    elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
+                        self.Controler.EndBuffering()
+                        self.StartBuffering()
+                    self.CurrentAction = ("Delete", event.GetPosition())
+                    wx.CallAfter(self.RefreshModel)
+        event.Skip()
+    
+    def OnDoDrop(self, event):
+        self.ResetBuffer()
+        wx.CallAfter(self.RefreshModel)
+        event.Skip()
+
+    # Buffer the last model state
+    def RefreshBuffer(self):
+        self.Controler.BufferCFile()
+        if self.ParentWindow is not None:
+            self.ParentWindow.RefreshTitle()
+            self.ParentWindow.RefreshFileMenu()
+            self.ParentWindow.RefreshEditMenu()
+            self.ParentWindow.RefreshPageTitles()
+    
+    def StartBuffering(self):
+        self.Controler.StartBuffering()
+        if self.ParentWindow is not None:
+            self.ParentWindow.RefreshTitle()
+            self.ParentWindow.RefreshFileMenu()
+            self.ParentWindow.RefreshEditMenu()
+            self.ParentWindow.RefreshPageTitles()
+    
+    def ResetBuffer(self):
+        if self.CurrentAction != None:
+            self.Controler.EndBuffering()
+            self.CurrentAction = None
+
+    def RefreshView(self):
+        self.ResetBuffer()
+        self.DisableEvents = True
+        old_cursor_pos = self.GetCurrentPos()
+        old_text = self.GetText()
+        new_text = self.Controler.GetPartText(self.Name)
+        self.SetText(new_text)
+        new_cursor_pos = GetCursorPos(old_text, new_text)
+        if new_cursor_pos != None:
+            self.GotoPos(new_cursor_pos)
+        else:
+            self.GotoPos(old_cursor_pos)
+        self.ScrollToColumn(0)
+        self.EmptyUndoBuffer()
+        self.DisableEvents = False
+        
+        self.Colourise(0, -1)
+
+    def DoGetBestSize(self):
+        return self.ParentWindow.GetPanelBestSize()
+
+    def RefreshModel(self):
+        self.Controler.SetPartText(self.Name, self.GetText())
+
+    def OnKeyPressed(self, event):
+        if self.CallTipActive():
+            self.CallTipCancel()
+        key = event.GetKeyCode()
+
+        if key == 32 and event.ControlDown():
+            pos = self.GetCurrentPos()
+
+            # Tips
+            if event.ShiftDown():
+                pass
+##                self.CallTipSetBackground("yellow")
+##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
+##                                 'show some suff, maybe parameters..\n\n'
+##                                 'fubar(param1, param2)')
+            # Code completion
+            else:
+                self.AutoCompSetIgnoreCase(False)  # so this needs to match
+
+                # Images are specified with a appended "?type"
+                self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
+        else:
+            event.Skip()
+
+    def OnKillFocus(self, event):
+        self.AutoCompCancel()
+        event.Skip()
+
+    def OnUpdateUI(self, evt):
+        # check for matching braces
+        braceAtCaret = -1
+        braceOpposite = -1
+        charBefore = None
+        caretPos = self.GetCurrentPos()
+
+        if caretPos > 0:
+            charBefore = self.GetCharAt(caretPos - 1)
+            styleBefore = self.GetStyleAt(caretPos - 1)
+
+        # check before
+        if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
+            braceAtCaret = caretPos - 1
+
+        # check after
+        if braceAtCaret < 0:
+            charAfter = self.GetCharAt(caretPos)
+            styleAfter = self.GetStyleAt(caretPos)
+
+            if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
+                braceAtCaret = caretPos
+
+        if braceAtCaret >= 0:
+            braceOpposite = self.BraceMatch(braceAtCaret)
+
+        if braceAtCaret != -1  and braceOpposite == -1:
+            self.BraceBadLight(braceAtCaret)
+        else:
+            self.BraceHighlight(braceAtCaret, braceOpposite)
+            #pt = self.PointFromPosition(braceOpposite)
+            #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
+            #print pt
+            #self.Refresh(False)
+
+
+    def OnMarginClick(self, evt):
+        # fold and unfold as needed
+        if evt.GetMargin() == 2:
+            if evt.GetShift() and evt.GetControl():
+                self.FoldAll()
+            else:
+                lineClicked = self.LineFromPosition(evt.GetPosition())
+
+                if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
+                    if evt.GetShift():
+                        self.SetFoldExpanded(lineClicked, True)
+                        self.Expand(lineClicked, True, True, 1)
+                    elif evt.GetControl():
+                        if self.GetFoldExpanded(lineClicked):
+                            self.SetFoldExpanded(lineClicked, False)
+                            self.Expand(lineClicked, False, True, 0)
+                        else:
+                            self.SetFoldExpanded(lineClicked, True)
+                            self.Expand(lineClicked, True, True, 100)
+                    else:
+                        self.ToggleFold(lineClicked)
+
+
+    def FoldAll(self):
+        lineCount = self.GetLineCount()
+        expanding = True
+
+        # find out if we are folding or unfolding
+        for lineNum in range(lineCount):
+            if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
+                expanding = not self.GetFoldExpanded(lineNum)
+                break
+
+        lineNum = 0
+
+        while lineNum < lineCount:
+            level = self.GetFoldLevel(lineNum)
+            if level & stc.STC_FOLDLEVELHEADERFLAG and \
+               (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+
+                if expanding:
+                    self.SetFoldExpanded(lineNum, True)
+                    lineNum = self.Expand(lineNum, True)
+                    lineNum = lineNum - 1
+                else:
+                    lastChild = self.GetLastChild(lineNum, -1)
+                    self.SetFoldExpanded(lineNum, False)
+
+                    if lastChild > lineNum:
+                        self.HideLines(lineNum+1, lastChild)
+
+            lineNum = lineNum + 1
+
+
+
+    def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
+        lastChild = self.GetLastChild(line, level)
+        line = line + 1
+
+        while line <= lastChild:
+            if force:
+                if visLevels > 0:
+                    self.ShowLines(line, line)
+                else:
+                    self.HideLines(line, line)
+            else:
+                if doExpand:
+                    self.ShowLines(line, line)
+
+            if level == -1:
+                level = self.GetFoldLevel(line)
+
+            if level & stc.STC_FOLDLEVELHEADERFLAG:
+                if force:
+                    if visLevels > 1:
+                        self.SetFoldExpanded(line, True)
+                    else:
+                        self.SetFoldExpanded(line, False)
+
+                    line = self.Expand(line, doExpand, force, visLevels-1)
+
+                else:
+                    if doExpand and self.GetFoldExpanded(line):
+                        line = self.Expand(line, True, force, visLevels-1)
+                    else:
+                        line = self.Expand(line, False, force, visLevels-1)
+            else:
+                line = line + 1
+
+        return line
+
+    def Cut(self):
+        self.ResetBuffer()
+        self.DisableEvents = True
+        self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
+        self.DisableEvents = False
+        self.RefreshModel()
+        self.RefreshBuffer()
+    
+    def Copy(self):
+        self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
+    
+    def Paste(self):
+        self.ResetBuffer()
+        self.DisableEvents = True
+        self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
+        self.DisableEvents = False
+        self.RefreshModel()
+        self.RefreshBuffer()
+
+
+#-------------------------------------------------------------------------------
+#                         Helper for VariablesGrid values
+#-------------------------------------------------------------------------------
+
+class VariablesTable(CustomTable):
+    
+    def GetValue(self, row, col):
+        if row < self.GetNumberRows():
+            if col == 0:
+                return row + 1
+            else:
+                return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
+    
+    def _updateColAttrs(self, grid):
+        """
+        wxGrid -> update the column attributes to add the
+        appropriate renderer given the column name.
+
+        Otherwise default to the default renderer.
+        """
+        
+        typelist = None
+        accesslist = None
+        for row in range(self.GetNumberRows()):
+            for col in range(self.GetNumberCols()):
+                editor = None
+                renderer = None
+                colname = self.GetColLabelValue(col, False)
+                
+                if colname == "Name":
+                    editor = wx.grid.GridCellTextEditor()
+                elif colname == "Class":
+                    editor = wx.grid.GridCellChoiceEditor()
+                    editor.SetParameters("input,memory,output")
+                elif colname == "Type":
+                    pass
+                else:
+                    grid.SetReadOnly(row, col, True)
+                
+                grid.SetCellEditor(row, col, editor)
+                grid.SetCellRenderer(row, col, renderer)
+                
+                grid.SetCellBackgroundColour(row, col, wx.WHITE)
+            self.ResizeRow(grid, row)
+    
+
+[ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID,
+ ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON, 
+ ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON
+] = [wx.NewId() for _init_ctrls in range(6)]
+
+class VariablesEditor(wx.Panel):
+    
+    if wx.VERSION < (2, 6, 0):
+        def Bind(self, event, function, id = None):
+            if id is not None:
+                event(self, id, function)
+            else:
+                event(self, function)
+    
+    def _init_coll_MainSizer_Growables(self, parent):
+        parent.AddGrowableCol(0)
+        parent.AddGrowableRow(0)
+
+    def _init_coll_MainSizer_Items(self, parent):
+        parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
+        parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW)
+
+    def _init_coll_ButtonsSizer_Growables(self, parent):
+        parent.AddGrowableCol(0)
+        parent.AddGrowableRow(0)
+
+    def _init_coll_ButtonsSizer_Items(self, parent):
+        parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT)
+        parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0)
+        parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0)
+        parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0)
+
+    def _init_sizers(self):
+        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
+        self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
+        
+        self._init_coll_MainSizer_Growables(self.MainSizer)
+        self._init_coll_MainSizer_Items(self.MainSizer)
+        self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer)
+        self._init_coll_ButtonsSizer_Items(self.ButtonsSizer)
+        
+        self.SetSizer(self.MainSizer)
+
+    def _init_ctrls(self, prnt):
+        wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt,
+              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        
+        self.VariablesGrid = CustomGrid(id=ID_VARIABLESEDITORVARIABLESGRID,
+              name='VariablesGrid', parent=self, pos=wx.Point(0, 0), 
+              size=wx.Size(-1, -1), style=wx.VSCROLL)
+        if wx.VERSION >= (2, 5, 0):
+            self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
+            self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
+            self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
+        else:
+            wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
+            wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
+            wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
+        
+        self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable',
+              name='AddVariableButton', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(122, 32), style=0)
+        
+        self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable',
+              name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(122, 32), style=0)
+        
+        self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^',
+              name='UpVariableButton', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(32, 32), style=0)
+        
+        self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v',
+              name='DownVariableButton', parent=self, pos=wx.Point(0, 0),
+              size=wx.Size(32, 32), style=0)
+        
+        self._init_sizers()
+
+    def __init__(self, parent, window, controler):
+        self._init_ctrls(parent)
+        
+        self.ParentWindow = window
+        self.Controler = controler
+        
+        self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
+        self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
+        self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
+        self.ColSizes = [40, 200, 150, 150]
+        self.VariablesGrid.SetTable(self.Table)
+        self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
+                                       "Delete": self.DeleteVariableButton,
+                                       "Up": self.UpVariableButton,
+                                       "Down": self.DownVariableButton})
+        
+        def _AddVariable(new_row):
+            self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy())
+            self.RefreshModel()
+            self.RefreshView()
+            return new_row
+        setattr(self.VariablesGrid, "_AddRow", _AddVariable)
+        
+        def _DeleteVariable(row):
+            self.Table.RemoveRow(row)
+            self.RefreshModel()
+            self.RefreshView()
+        setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
+        
+        def _MoveVariable(row, move):
+            new_row = self.Table.MoveRow(row, move)
+            if new_row != row:
+                self.RefreshModel()
+                self.RefreshView()
+            return new_row
+        setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
+        
+        self.VariablesGrid.SetRowLabelSize(0)
+        for col in range(self.Table.GetNumberCols()):
+            attr = wx.grid.GridCellAttr()
+            attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
+            self.VariablesGrid.SetColAttr(col, attr)
+            self.VariablesGrid.SetColSize(col, self.ColSizes[col])
+        self.Table.ResetView(self.VariablesGrid)
+
+    def RefreshModel(self):
+        self.Controler.SetVariables(self.Table.GetData())
+        self.RefreshBuffer()
+        
+    # Buffer the last model state
+    def RefreshBuffer(self):
+        self.Controler.BufferCFile()
+        self.ParentWindow.RefreshTitle()
+        self.ParentWindow.RefreshFileMenu()
+        self.ParentWindow.RefreshEditMenu()
+        self.ParentWindow.RefreshPageTitles()
+
+    def RefreshView(self):
+        self.Table.SetData(self.Controler.GetVariables())
+        self.Table.ResetView(self.VariablesGrid)
+        self.VariablesGrid.RefreshButtons()
+    
+    def DoGetBestSize(self):
+        return self.ParentWindow.GetPanelBestSize()
+    
+    def OnVariablesGridCellChange(self, event):
+        self.RefreshModel()
+        wx.CallAfter(self.RefreshView)
+        event.Skip()
+
+    def OnVariablesGridEditorShown(self, event):
+        row, col = event.GetRow(), event.GetCol() 
+        if self.Table.GetColLabelValue(col) == "Type":
+            type_menu = wx.Menu(title='')
+            base_menu = wx.Menu(title='')
+            for base_type in self.Controler.GetBaseTypes():
+                new_id = wx.NewId()
+                AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
+                self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
+            type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
+            datatype_menu = wx.Menu(title='')
+            for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
+                new_id = wx.NewId()
+                AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
+                self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
+            type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
+            rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
+            
+            self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
+            type_menu.Destroy()
+            event.Veto()
+        else:
+            event.Skip()
+
+    def GetVariableTypeFunction(self, base_type):
+        def VariableTypeFunction(event):
+            row = self.VariablesGrid.GetGridCursorRow()
+            self.Table.SetValueByName(row, "Type", base_type)
+            self.Table.ResetView(self.VariablesGrid)
+            self.RefreshModel()
+            self.RefreshView()
+            event.Skip()
+        return VariableTypeFunction
+
+    def OnVariablesGridCellLeftClick(self, event):
+        if event.GetCol() == 0:
+            row = event.GetRow()
+            num = 0
+            if self.Table.GetValueByName(row, "Class") == "input":
+                dir = "%I"
+                for i in xrange(row):
+                    if self.Table.GetValueByName(i, "Class") == "input":
+                        num += 1
+            elif self.Table.GetValueByName(row, "Class") == "memory":
+                dir = "%M"
+                for i in xrange(row):
+                    if self.Table.GetValueByName(i, "Class") == "memory":
+                        num += 1
+            else:
+                dir = "%Q"
+                for i in xrange(row):
+                    if self.Table.GetValueByName(i, "Class") == "output":
+                        num += 1
+            data_type = self.Table.GetValueByName(row, "Type")
+            var_name = self.Table.GetValueByName(row, "Name")
+            base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation()))
+            location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num)
+            data = wx.TextDataObject(str((location, "location", data_type, var_name, "")))
+            dragSource = wx.DropSource(self.VariablesGrid)
+            dragSource.SetData(data)
+            dragSource.DoDragDrop()
+        event.Skip()
+    
+
+#-------------------------------------------------------------------------------
+#                          SVGUIEditor Main Frame Class
+#-------------------------------------------------------------------------------
+
+CFILE_PARTS = [
+    ("Includes", CppEditor), 
+    ("Variables", VariablesEditor), 
+    ("Globals", CppEditor), 
+    ("Init", CppEditor), 
+    ("CleanUp", CppEditor), 
+    ("Retrieve", CppEditor), 
+    ("Publish", CppEditor),
+]
+
+#----------------------------------------------------------------------
+# different icons for the collapsed/expanded states.
+# Taken from standard Windows XP collapsed/expanded states.
+#----------------------------------------------------------------------
+
+def GetCollapsedIconData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\
+\xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\
+\xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\
+H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\
+\xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\
+\xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\
+\x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\
+\xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\
+zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\
+\x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\
+~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\
+\x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\
+\xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\
+\xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\
+0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\
+\x00\x00\x00IEND\xaeB`\x82' 
+
+def GetCollapsedIconBitmap():
+    return wx.BitmapFromImage(GetCollapsedIconImage())
+
+def GetCollapsedIconImage():
+    import cStringIO
+    stream = cStringIO.StringIO(GetCollapsedIconData())
+    return wx.ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def GetExpandedIconData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\
+\xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\
+\x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\
+\xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\
+\x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\
+\x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\
+\x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\
+\xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\
+\x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\
+\x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\
+\xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\
+\xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\
+\x05\x10\x81\xce\xc9\xa8\xf6><G\xd8\xed\xbbA)X\xd9\x0c\x01\x9a\xc6Q\x14\xd9h\
+[\x04\xda\xd6c\xadFkE\xf0\xc2\xab\xd7\xb7\xc9\x08\x00\xf8\xf6\xbd\x1b\x8cQ\
+\xd8|\xb9\x0f\xd3\x9a\x8a\xc7\x08\x00\x9f?\xdd%\xde\x07\xda\x93\xc3{\x19C\
+\x8a\x9c\x03\x0b8\x17\xe8\x9d\xbf\x02.>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\
+\xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\
+`\x82' 
+
+def GetExpandedIconBitmap():
+    return wx.BitmapFromImage(GetExpandedIconImage())
+
+def GetExpandedIconImage():
+    import cStringIO
+    stream = cStringIO.StringIO(GetExpandedIconData())
+    return wx.ImageFromStream(stream)
+
+class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton):
+    
+    def GetBackgroundBrush(self, dc):
+        colBg = self.GetBackgroundColour()
+        brush = wx.Brush(colBg, wx.SOLID)
+        if self.style & wx.BORDER_NONE:
+            myAttr = self.GetDefaultAttributes()
+            parAttr = self.GetParent().GetDefaultAttributes()
+            myDef = colBg == myAttr.colBg
+            parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
+            if myDef and parDef:
+                if wx.Platform == "__WXMAC__":
+                    brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
+                elif wx.Platform == "__WXMSW__":
+                    if self.DoEraseBackground(dc):
+                        brush = None
+            elif myDef and not parDef:
+                colBg = self.GetParent().GetBackgroundColour()
+                brush = wx.Brush(colBg, wx.SOLID)
+        return brush
+    
+    def DrawLabel(self, dc, width, height, dx=0, dy=0):
+        bmp = self.bmpLabel
+        if bmp is not None:     # if the bitmap is used
+            if self.bmpDisabled and not self.IsEnabled():
+                bmp = self.bmpDisabled
+            if self.bmpFocus and self.hasFocus:
+                bmp = self.bmpFocus
+            if self.bmpSelected and not self.up:
+                bmp = self.bmpSelected
+            bw,bh = bmp.GetWidth(), bmp.GetHeight()
+            hasMask = bmp.GetMask() is not None
+        else:
+            bw = bh = 0     # no bitmap -> size is zero
+        
+        dc.SetFont(self.GetFont())
+        if self.IsEnabled():
+            dc.SetTextForeground(self.GetForegroundColour())
+        else:
+            dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
+
+        label = self.GetLabel()
+        tw, th = dc.GetTextExtent(label)        # size of text
+        
+        if bmp is not None:
+            dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available
+        
+        dc.DrawText(label, 2, (height-th)/2)      # draw the text
+
+        dc.SetPen(wx.Pen(self.GetForegroundColour()))
+        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+        dc.DrawRectangle(0, 0, width, height)
+
+[ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER, 
+ ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED, 
+] = [wx.NewId() for _init_ctrls in range(4)]
+
+class CFileEditor(EditorPanel):
+    
+    def _init_Editor(self, prnt):
+        self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0), 
+                size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        
+        self.Panels = {}
+        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2 * len(CFILE_PARTS) + 1, vgap=0)
+        self.MainSizer.AddGrowableCol(0)
+        
+        for idx, (name, panel_class) in enumerate(CFILE_PARTS):
+            button_id = wx.NewId()
+            button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name, 
+                  label=name, bitmap=GetCollapsedIconBitmap(), parent=self.Editor, pos=wx.Point(0, 0),
+                  size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT)
+            button.SetBitmapSelected(GetExpandedIconBitmap())
+            button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id)
+            self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW)
+            
+            if panel_class == VariablesEditor:
+                panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler)
+            else:
+                panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
+            self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
+            panel.Hide()
+            
+            self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1}
+        
+        self.Spacer = wx.Panel(self.Editor, -1)
+        self.SpacerExpanded = True
+        self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
+        
+        self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
+        
+        self.Editor.SetSizer(self.MainSizer)
+        
+    def __init__(self, parent, controler, window):
+        EditorPanel.__init__(self, parent, "", window, controler)
+        
+        img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+        
+    def __del__(self):
+        self.Controler.OnCloseEditor(self)
+    
+    def GetTitle(self):
+        fullname = self.Controler.PlugFullName()
+        if not self.Controler.CFileIsSaved():
+            return "~%s~" % fullname
+        return fullname
+    
+    def GetBufferState(self):
+        return self.Controler.GetBufferState()
+        
+    def Undo(self):
+        self.Controler.LoadPrevious()
+        self.RefreshView()
+            
+    def Redo(self):
+        self.Controler.LoadNext()
+        self.RefreshView()
+    
+    def HasNoModel(self):
+        return False
+
+    def RefreshView(self):
+        for infos in self.Panels.itervalues():
+            infos["panel"].RefreshView()
+
+    def GenPanelButtonCallback(self, name):
+        def PanelButtonCallback(event):
+            self.TogglePanel(name)
+        return PanelButtonCallback
+
+    def ExpandPanel(self, name):
+        infos = self.Panels.get(name, None)
+        if infos is not None and not infos["expanded"]:
+            infos["expanded"] = True
+            infos["button"].SetToggle(True)
+            infos["panel"].Show()
+            self.MainSizer.AddGrowableRow(infos["row"])
+        
+            self.RefreshSizerLayout()
+    
+    def CollapsePanel(self, name):
+        infos = self.Panels.get(name, None)
+        if infos is not None and infos["expanded"]:
+            infos["expanded"] = False
+            infos["button"].SetToggle(False)
+            infos["panel"].Hide()
+            self.MainSizer.RemoveGrowableRow(infos["row"])
+        
+            self.RefreshSizerLayout()
+        
+    def TogglePanel(self, name):
+        infos = self.Panels.get(name, None)
+        if infos is not None:
+            infos["expanded"] = not infos["expanded"]
+            infos["button"].SetToggle(infos["expanded"])
+            if infos["expanded"]:
+                infos["panel"].Show()
+                self.MainSizer.AddGrowableRow(infos["row"])
+            else:
+                infos["panel"].Hide()
+                self.MainSizer.RemoveGrowableRow(infos["row"])
+            
+            self.RefreshSizerLayout()
+    
+    def RefreshSizerLayout(self):
+        expand_spacer = True
+        for infos in self.Panels.itervalues():
+            expand_spacer = expand_spacer and not infos["expanded"]
+        
+        if self.SpacerExpanded != expand_spacer:
+            self.SpacerExpanded = expand_spacer
+            if expand_spacer:
+                self.Spacer.Show()
+                self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
+            else:
+                self.Spacer.Hide()
+                self.MainSizer.RemoveGrowableRow(2 * len(CFILE_PARTS))
+        
+        self.MainSizer.Layout()
+            
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/README	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+C extension
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from c_ext import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/c_ext.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,315 @@
+import wx
+import os
+from xml.dom import minidom
+import cPickle
+
+from xmlclass import *
+
+from ConfigTree import ConfigTreeNode, opjimg
+from CFileEditor import CFileEditor
+from PLCControler import PLCControler, UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
+
+CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd"))
+
+TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
+    "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
+    "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
+
+class _Cfile:
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="CExtension">
+        <xsd:complexType>
+          <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
+          <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """
+    EditorType = CFileEditor
+    
+    def __init__(self):
+        filepath = self.CFileName()
+        
+        self.CFile = CFileClasses["CFile"]()
+        if os.path.isfile(filepath):
+            xmlfile = open(filepath, 'r')
+            tree = minidom.parse(xmlfile)
+            xmlfile.close()
+            
+            for child in tree.childNodes:
+                if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
+                    self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
+                    self.CreateCFileBuffer(True)
+        else:
+            self.CreateCFileBuffer(False)
+            self.OnPlugSave()
+
+    def CFileName(self):
+        return os.path.join(self.PlugPath(), "cfile.xml")
+
+    def GetBaseTypes(self):
+        return self.GetPlugRoot().GetBaseTypes()
+
+    def GetDataTypes(self, basetypes = False, only_locatables = False):
+        return self.GetPlugRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
+
+    def GetSizeOfType(self, type):
+        return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None)
+
+    def SetVariables(self, variables):
+        self.CFile.variables.setvariable([])
+        for var in variables:
+            variable = CFileClasses["variables_variable"]()
+            variable.setname(var["Name"])
+            variable.settype(var["Type"])
+            variable.setclass(var["Class"])
+            self.CFile.variables.appendvariable(variable)
+    
+    def GetVariables(self):
+        datas = []
+        for var in self.CFile.variables.getvariable():
+            datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
+        return datas
+
+    def GetVariableLocationTree(self):
+        '''See ConfigTreeNode.GetVariableLocationTree() for a description.'''
+
+        current_location = ".".join(map(str, self.GetCurrentLocation()))
+        
+        vars = []
+        input = memory = output = 0
+        for var in self.CFile.variables.getvariable():
+            var_size = self.GetSizeOfType(var.gettype())
+            var_location = ""
+            if var.getclass() == "input":
+                var_class = LOCATION_VAR_INPUT
+                if var_size is not None:
+                    var_location = "%%I%s%s.%d"%(var_size, current_location, input)
+                input += 1
+            elif var.getclass() == "memory":
+                var_class = LOCATION_VAR_INPUT
+                if var_size is not None:
+                    var_location = "%%M%s%s.%d"%(var_size, current_location, memory)
+                memory += 1
+            else:
+                var_class = LOCATION_VAR_OUTPUT
+                if var_size is not None:
+                    var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
+                output += 1
+            vars.append({"name": var.getname(),
+                         "type": var_class,
+                         "size": var_size,
+                         "IEC_type": var.gettype(),
+                         "var_name": var.getname(),
+                         "location": var_location,
+                         "description": "",
+                         "children": []})
+                
+        return  {"name": self.BaseParams.getName(),
+                "type": LOCATION_CONFNODE,
+                "location": self.GetFullIEC_Channel(),
+                "children": vars}
+
+    def SetPartText(self, name, text):
+        if name == "Includes":
+            self.CFile.includes.settext(text)
+        elif name == "Globals":
+            self.CFile.globals.settext(text)
+        elif name == "Init":
+            self.CFile.initFunction.settext(text)
+        elif name == "CleanUp":
+            self.CFile.cleanUpFunction.settext(text)
+        elif name == "Retrieve":
+            self.CFile.retrieveFunction.settext(text)
+        elif name == "Publish":
+            self.CFile.publishFunction.settext(text)
+        
+    def GetPartText(self, name):
+        if name == "Includes":
+            return self.CFile.includes.gettext()
+        elif name == "Globals":
+            return self.CFile.globals.gettext()
+        elif name == "Init":
+            return self.CFile.initFunction.gettext()
+        elif name == "CleanUp":
+            return self.CFile.cleanUpFunction.gettext()
+        elif name == "Retrieve":
+            return self.CFile.retrieveFunction.gettext()
+        elif name == "Publish":
+            return self.CFile.publishFunction.gettext()
+        return ""
+                
+    ConfNodeMethods = [
+        {"bitmap" : os.path.join("images", "EditCfile"),
+         "name" : _("Edit C File"), 
+         "tooltip" : _("Edit C File"),
+         "method" : "_OpenView"},
+    ]
+
+    def PlugTestModified(self):
+        return self.ChangesToSave or not self.CFileIsSaved()    
+
+    def OnPlugSave(self):
+        filepath = self.CFileName()
+        
+        text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+        extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
+                  "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
+                  "xsi:schemaLocation" : "cext_xsd.xsd"}
+        text += self.CFile.generateXMLText("CFile", 0, extras)
+
+        xmlfile = open(filepath,"w")
+        xmlfile.write(text.encode("utf-8"))
+        xmlfile.close()
+        
+        self.MarkCFileAsSaved()
+        return True
+
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Generate C code
+        @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+        @param locations: List of complete variables locations \
+            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+            "NAME" : name of the variable (generally "__IW0_1_2" style)
+            "DIR" : direction "Q","I" or "M"
+            "SIZE" : size "X", "B", "W", "D", "L"
+            "LOC" : tuple of interger for IEC location (0,1,2,...)
+            }, ...]
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        current_location = self.GetCurrentLocation()
+        # define a unique name for the generated C file
+        location_str = "_".join(map(str, current_location))
+        
+        text = "/* Code generated by Beremiz c_ext confnode */\n\n"
+        
+        # Adding includes
+        text += "/* User includes */\n"
+        text += self.CFile.includes.gettext()
+        text += "\n"
+        
+        text += """/* Beremiz c_ext confnode includes */
+#ifdef _WINDOWS_H
+  #include "iec_types.h"
+#else
+  #include "iec_std_lib.h"
+#endif
+
+"""
+
+        # Adding variables
+        vars = []
+        inputs = memories = outputs = 0
+        for variable in self.CFile.variables.variable:
+            var = {"Name" : variable.getname(), "Type" : variable.gettype()}
+            if variable.getclass() == "input":
+                var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs)
+                inputs += 1
+            elif variable.getclass() == "memory":
+                var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
+                memories += 1
+            else:
+                var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
+                outputs += 1
+            vars.append(var)
+        text += "/* Beremiz c_ext confnode user variables definition */\n"
+        base_types = self.GetPlugRoot().GetBaseTypes()
+        for var in vars:
+            if var["Type"] in base_types:
+                prefix = "IEC_"
+            else:
+                prefix = ""
+            text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
+            text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
+        text += "/* User variables reference */\n"
+        for var in vars:
+            text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
+        text += "\n"
+        
+        # Adding user global variables and routines
+        text += "/* User internal user variables and routines */\n"
+        text += self.CFile.globals.gettext()
+        
+        # Adding Beremiz confnode functions
+        text += "/* Beremiz confnode functions */\n"
+        text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
+        text += self.CFile.initFunction.gettext()
+        text += "  return 0;\n"
+        text += "\n}\n\n"
+        
+        text += "void __cleanup_%s(void)\n{\n"%location_str
+        text += self.CFile.cleanUpFunction.gettext()
+        text += "\n}\n\n"
+        
+        text += "void __retrieve_%s(void)\n{\n"%location_str
+        text += self.CFile.retrieveFunction.gettext()
+        text += "\n}\n\n"
+        
+        text += "void __publish_%s(void)\n{\n"%location_str
+        text += self.CFile.publishFunction.gettext()
+        text += "\n}\n\n"
+        
+        Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
+        cfile = open(Gen_Cfile_path,'w')
+        cfile.write(text)
+        cfile.close()
+        
+        matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
+        
+        return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
+
+
+#-------------------------------------------------------------------------------
+#                      Current Buffering Management Functions
+#-------------------------------------------------------------------------------
+
+    """
+    Return a copy of the cfile model
+    """
+    def Copy(self, model):
+        return cPickle.loads(cPickle.dumps(model))
+
+    def CreateCFileBuffer(self, saved):
+        self.Buffering = False
+        self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
+
+    def BufferCFile(self):
+        self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
+    
+    def StartBuffering(self):
+        self.Buffering = True
+        
+    def EndBuffering(self):
+        if self.Buffering:
+            self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
+            self.Buffering = False
+    
+    def MarkCFileAsSaved(self):
+        self.EndBuffering()
+        self.CFileBuffer.CurrentSaved()
+    
+    def CFileIsSaved(self):
+        return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
+        
+    def LoadPrevious(self):
+        self.EndBuffering()
+        self.CFile = cPickle.loads(self.CFileBuffer.Previous())
+    
+    def LoadNext(self):
+        self.CFile = cPickle.loads(self.CFileBuffer.Next())
+    
+    def GetBufferState(self):
+        first = self.CFileBuffer.IsFirst() and not self.Buffering
+        last = self.CFileBuffer.IsLast()
+        return not first, not last
+
+class RootClass:
+
+    PlugChildsTypes = [("C_File",_Cfile, "C file")]
+    
+    def PlugGenerate_C(self, buildpath, locations):
+        return [],"",False
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/c_ext/cext_xsd.xsd	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xsd:schema targetNamespace="cext_xsd.xsd" 
+            xmlns:cext="cext_xsd.xsd" 
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="qualified" 
+            attributeFormDefault="unqualified">
+
+  <xsd:element name="CFile">
+    <xsd:complexType>
+      <xsd:sequence>
+        <xsd:element name="includes" type="cext:CCode"/>
+        <xsd:element name="variables">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="variable" minOccurs="0" maxOccurs="unbounded">
+                <xsd:complexType>
+                  <xsd:attribute name="name" type="xsd:string" use="required"/>
+                  <xsd:attribute name="type" type="xsd:string" use="required"/>
+                  <xsd:attribute name="class" use="required">
+                    <xsd:simpleType>
+                      <xsd:restriction base="xsd:string">
+                        <xsd:enumeration value="input"/>
+                        <xsd:enumeration value="memory"/>
+                        <xsd:enumeration value="output"/>
+                      </xsd:restriction>
+                    </xsd:simpleType>
+                  </xsd:attribute>
+                </xsd:complexType>
+              </xsd:element>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="globals" type="cext:CCode"/>
+        <xsd:element name="initFunction" type="cext:CCode"/>
+        <xsd:element name="cleanUpFunction" type="cext:CCode"/>
+        <xsd:element name="retrieveFunction" type="cext:CCode"/>
+        <xsd:element name="publishFunction" type="cext:CCode"/>
+      </xsd:sequence>
+    </xsd:complexType>
+  </xsd:element>
+  <xsd:complexType name="CCode">
+    <xsd:annotation>
+      <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
+    </xsd:annotation>
+    <xsd:sequence>
+      <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
+    </xsd:sequence>
+  </xsd:complexType>
+</xsd:schema>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/.cvsignore	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/NetworkEditor.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,122 @@
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
+
+import wx
+
+from subindextable import EditingPanel
+from networkedit import NetworkEditorTemplate
+from controls import EditorPanel
+
+[ID_NETWORKEDITOR, 
+] = [wx.NewId() for _init_ctrls in range(1)]
+
+[ID_NETWORKEDITORCONFNODEMENUADDSLAVE, ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, 
+ ID_NETWORKEDITORCONFNODEMENUMASTER, 
+] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(3)]
+
+[ID_NETWORKEDITORMASTERMENUNODEINFOS, ID_NETWORKEDITORMASTERMENUDS301PROFILE,
+ ID_NETWORKEDITORMASTERMENUDS302PROFILE, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE,
+ ID_NETWORKEDITORMASTERMENUADD, 
+] = [wx.NewId() for _init_coll_MasterMenu_Items in range(5)]
+
+[ID_NETWORKEDITORADDMENUSDOSERVER, ID_NETWORKEDITORADDMENUSDOCLIENT,
+ ID_NETWORKEDITORADDMENUPDOTRANSMIT, ID_NETWORKEDITORADDMENUPDORECEIVE,
+ ID_NETWORKEDITORADDMENUMAPVARIABLE, ID_NETWORKEDITORADDMENUUSERTYPE,
+] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
+
+class NetworkEditor(EditorPanel, NetworkEditorTemplate):
+    
+    ID = ID_NETWORKEDITOR
+    
+    def _init_coll_MainSizer_Items(self, parent):
+        parent.AddWindow(self.NetworkNodes, 0, border=5, flag=wx.GROW|wx.ALL)
+
+    def _init_coll_MainSizer_Growables(self, parent):
+        parent.AddGrowableCol(0)
+        parent.AddGrowableRow(0)
+    
+    def _init_sizers(self):
+        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0)
+        
+        self._init_coll_MainSizer_Items(self.MainSizer)
+        self._init_coll_MainSizer_Growables(self.MainSizer)
+        
+        self.Editor.SetSizer(self.MainSizer)
+    
+    def _init_Editor(self, prnt):
+        self.Editor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0), 
+                size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
+        
+        NetworkEditorTemplate._init_ctrls(self, self.Editor)
+        
+        self._init_sizers()
+        
+    def __init__(self, parent, controler, window):
+        EditorPanel.__init__(self, parent, "", window, controler)
+        NetworkEditorTemplate.__init__(self, controler, window, False)
+    
+        img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+        
+        self.RefreshNetworkNodes()
+        self.RefreshBufferState()
+    
+    def __del__(self):
+        self.Controler.OnCloseEditor(self)
+    
+    def GetConfNodeMenuItems(self):
+        add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_NETWORKEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
+                    (wx.ITEM_NORMAL, (_('SDO Client'), ID_NETWORKEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
+                    (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_NETWORKEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
+                    (wx.ITEM_NORMAL, (_('PDO Receive'), ID_NETWORKEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
+                    (wx.ITEM_NORMAL, (_('Map Variable'), ID_NETWORKEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
+                    (wx.ITEM_NORMAL, (_('User Type'), ID_NETWORKEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
+        
+        profile = self.Manager.GetCurrentProfileName()
+        if profile not in ("None", "DS-301"):
+            other_profile_text = _("%s Profile") % profile
+            add_menu.append((wx.ITEM_SEPARATOR, None))
+            for text, indexes in self.Manager.GetCurrentSpecificMenu():
+                add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
+        else:
+            other_profile_text = _('Other Profile')
+        
+        master_menu = [(wx.ITEM_NORMAL, (_('Node infos'), ID_NETWORKEDITORMASTERMENUNODEINFOS, '', self.OnNodeInfosMenu)),
+                       (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_NETWORKEDITORMASTERMENUDS301PROFILE, '', self.OnCommunicationMenu)),
+                       (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_NETWORKEDITORMASTERMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
+                       (wx.ITEM_NORMAL, (other_profile_text, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
+                       (wx.ITEM_SEPARATOR, None),
+                       (add_menu, (_('Add'), ID_NETWORKEDITORMASTERMENUADD))]
+        
+        return [(wx.ITEM_NORMAL, (_('Add slave'), ID_NETWORKEDITORCONFNODEMENUADDSLAVE, '', self.OnAddSlaveMenu)),
+                (wx.ITEM_NORMAL, (_('Remove slave'), ID_NETWORKEDITORCONFNODEMENUREMOVESLAVE, '', self.OnRemoveSlaveMenu)),
+                (wx.ITEM_SEPARATOR, None),
+                (master_menu, (_('Master'), ID_NETWORKEDITORCONFNODEMENUMASTER))]
+    
+    def RefreshMainMenu(self):
+        pass
+    
+    def RefreshConfNodeMenu(self, confnode_menu):
+        confnode_menu.Enable(ID_NETWORKEDITORCONFNODEMENUMASTER, self.NetworkNodes.GetSelection() == 0)
+    
+    def GetTitle(self):
+        fullname = self.Controler.PlugFullName()
+        if not self.Manager.CurrentIsSaved():
+            return "~%s~" % fullname
+        return fullname
+
+    def RefreshView(self):
+        self.RefreshCurrentIndexList()
+    
+    def RefreshBufferState(self):
+        NetworkEditorTemplate.RefreshBufferState(self)
+        self.ParentWindow.RefreshTitle()
+        self.ParentWindow.RefreshFileMenu()
+        self.ParentWindow.RefreshEditMenu()
+        self.ParentWindow.RefreshPageTitles()
+    
+    def OnNodeSelectedChanged(self, event):
+        NetworkEditorTemplate.OnNodeSelectedChanged(self, event)
+        wx.CallAfter(self.ParentWindow.RefreshConfNodeMenu)
+        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/README	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+CANOpen
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/SlaveEditor.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,83 @@
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
+
+import wx
+
+from subindextable import EditingPanel
+from nodeeditor import NodeEditorTemplate
+from controls import EditorPanel
+
+[ID_SLAVEEDITORCONFNODEMENUNODEINFOS, ID_SLAVEEDITORCONFNODEMENUDS301PROFILE,
+ ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE,
+ ID_SLAVEEDITORCONFNODEMENUADD, 
+] = [wx.NewId() for _init_coll_ConfNodeMenu_Items in range(5)]
+
+[ID_SLAVEEDITORADDMENUSDOSERVER, ID_SLAVEEDITORADDMENUSDOCLIENT,
+ ID_SLAVEEDITORADDMENUPDOTRANSMIT, ID_SLAVEEDITORADDMENUPDORECEIVE,
+ ID_SLAVEEDITORADDMENUMAPVARIABLE, ID_SLAVEEDITORADDMENUUSERTYPE,
+] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
+
+class SlaveEditor(EditorPanel, NodeEditorTemplate):
+    
+    def _init_Editor(self, prnt):
+        self.Editor = EditingPanel(prnt, self, self.Controler, self.Editable)
+        
+    def __init__(self, parent, controler, window, editable=True):
+        self.Editable = editable
+        EditorPanel.__init__(self, parent, "", window, controler)
+        NodeEditorTemplate.__init__(self, controler, window, False)
+        
+        img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+    
+    def __del__(self):
+        self.Controler.OnCloseEditor(self)
+    
+    def GetConfNodeMenuItems(self):
+        if self.Editable:
+            add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_SLAVEEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
+                        (wx.ITEM_NORMAL, (_('SDO Client'), ID_SLAVEEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
+                        (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_SLAVEEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
+                        (wx.ITEM_NORMAL, (_('PDO Receive'), ID_SLAVEEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
+                        (wx.ITEM_NORMAL, (_('Map Variable'), ID_SLAVEEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
+                        (wx.ITEM_NORMAL, (_('User Type'), ID_SLAVEEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
+            
+            profile = self.Controler.GetCurrentProfileName()
+            if profile not in ("None", "DS-301"):
+                other_profile_text = _("%s Profile") % profile
+                add_menu.append((wx.ITEM_SEPARATOR, None))
+                for text, indexes in self.Manager.GetCurrentSpecificMenu():
+                    add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
+            else:
+                other_profile_text = _('Other Profile')
+            
+            return [(wx.ITEM_NORMAL, (_('Node infos'), ID_SLAVEEDITORCONFNODEMENUNODEINFOS, '', self.OnNodeInfosMenu)),
+                    (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_SLAVEEDITORCONFNODEMENUDS301PROFILE, '', self.OnCommunicationMenu)),
+                    (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_SLAVEEDITORCONFNODEMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
+                    (wx.ITEM_NORMAL, (other_profile_text, ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
+                    (wx.ITEM_SEPARATOR, None),
+                    (add_menu, (_('Add'), ID_SLAVEEDITORCONFNODEMENUADD))]
+        return []
+    
+    def RefreshConfNodeMenu(self, confnode_menu):
+        confnode_menu.Enable(ID_SLAVEEDITORCONFNODEMENUDSOTHERPROFILE, False)
+    
+    def GetTitle(self):
+        fullname = self.Controler.PlugFullName()
+        if not self.Controler.CurrentIsSaved():
+            return "~%s~" % fullname
+        return fullname
+
+    def RefreshView(self):
+        self.Editor.RefreshIndexList()
+
+    def RefreshCurrentIndexList(self):
+        self.RefreshView()
+    
+    def RefreshBufferState(self):
+        self.ParentWindow.RefreshTitle()
+        self.ParentWindow.RefreshFileMenu()
+        self.ParentWindow.RefreshEditMenu()
+        self.ParentWindow.RefreshPageTitles()
+            
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from canfestival import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/canfestival.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,484 @@
+import os, sys
+base_folder = os.path.split(sys.path[0])[0]
+CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
+sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
+
+from nodelist import NodeList
+from nodemanager import NodeManager
+import config_utils, gen_cfile, eds_utils
+from networkedit import networkedit
+from objdictedit import objdictedit
+import canfestival_config as local_canfestival_config
+from ConfigTree import ConfigTreeNode
+from commondialogs import CreateNodeDialog
+import wx
+
+from SlaveEditor import SlaveEditor
+from NetworkEditor import NetworkEditor
+
+from gnosis.xml.pickle import *
+from gnosis.xml.pickle.util import setParanoia
+setParanoia(0)
+
+if wx.Platform == '__WXMSW__':
+    DEFAULT_SETTINGS = {
+        "CAN_Driver": "can_tcp_win32",
+        "CAN_Device": "127.0.0.1",
+        "CAN_Baudrate": "125K",
+        "Slave_NodeId": 2,
+        "Master_NodeId": 1,
+    }
+else:
+    DEFAULT_SETTINGS = {
+        "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so",
+        "CAN_Device": "vcan0",
+        "CAN_Baudrate": "125K",
+        "Slave_NodeId": 2,
+        "Master_NodeId": 1,
+    }
+
+#--------------------------------------------------
+#                    SLAVE
+#--------------------------------------------------
+
+class _SlavePlug(NodeManager):
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="CanFestivalSlaveNode">
+        <xsd:complexType>
+          <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/>
+          <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
+          <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Slave_NodeId)d"/>
+          <xsd:attribute name="Sync_Align" type="xsd:integer" use="optional" default="0"/>
+          <xsd:attribute name="Sync_Align_Ratio" use="optional" default="50">
+            <xsd:simpleType>
+                <xsd:restriction base="xsd:integer">
+                    <xsd:minInclusive value="1"/>
+                    <xsd:maxInclusive value="99"/>
+                </xsd:restriction>
+            </xsd:simpleType>
+          </xsd:attribute>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """ % DEFAULT_SETTINGS
+    
+    EditorType = SlaveEditor
+
+    def __init__(self):
+        # TODO change netname when name change
+        NodeManager.__init__(self)
+        odfilepath = self.GetSlaveODPath()
+        if(os.path.isfile(odfilepath)):
+            self.OpenFileInCurrent(odfilepath)
+        else:
+            self.FilePath = ""
+            dialog = CreateNodeDialog(None, wx.OK)
+            dialog.Type.Enable(False)
+            dialog.GenSYNC.Enable(False)
+            if dialog.ShowModal() == wx.ID_OK:
+                name, id, nodetype, description = dialog.GetValues()
+                profile, filepath = dialog.GetProfile()
+                NMT = dialog.GetNMTManagement()
+                options = dialog.GetOptions()
+                self.CreateNewNode(name,       # Name - will be changed at build time
+                                   id,         # NodeID - will be changed at build time
+                                   "slave",    # Type
+                                   description,# description 
+                                   profile,    # profile
+                                   filepath,   # prfile filepath
+                                   NMT,        # NMT
+                                   options)     # options
+            else:
+                self.CreateNewNode("SlaveNode",  # Name - will be changed at build time
+                                   0x00,         # NodeID - will be changed at build time
+                                   "slave",      # Type
+                                   "",           # description 
+                                   "None",       # profile
+                                   "", # prfile filepath
+                                   "heartbeat",  # NMT
+                                   [])           # options
+            dialog.Destroy()
+            self.OnPlugSave()
+
+    def GetSlaveODPath(self):
+        return os.path.join(self.PlugPath(), 'slave.od')
+
+    def GetCanDevice(self):
+        return self.CanFestivalSlaveNode.getCan_Device()
+
+    def _OpenView(self):
+        ConfigTreeNode._OpenView(self)
+        if self._View is not None:
+            self._View.SetBusId(self.GetCurrentLocation())
+
+    ConfNodeMethods = [
+        {"bitmap" : os.path.join("images", "NetworkEdit"),
+         "name" : "Edit slave", 
+         "tooltip" : "Edit CanOpen slave with ObjdictEdit",
+         "method" : "_OpenView"},
+    ]
+
+    def OnPlugClose(self):
+        if self._View:
+            self._View.Close()
+
+    def PlugTestModified(self):
+        return self.ChangesToSave or self.OneFileHasChanged()
+        
+    def OnPlugSave(self):
+        return self.SaveCurrentInFile(self.GetSlaveODPath())
+
+    def SetParamsAttribute(self, path, value):
+        result = ConfigTreeNode.SetParamsAttribute(self, path, value)
+        
+        # Filter IEC_Channel and Name, that have specific behavior
+        if path == "BaseParams.IEC_Channel" and self._View is not None:
+            self._View.SetBusId(self.GetCurrentLocation())
+        
+        return result
+        
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Generate C code
+        @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+        @param locations: List of complete variables locations \
+            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+            "NAME" : name of the variable (generally "__IW0_1_2" style)
+            "DIR" : direction "Q","I" or "M"
+            "SIZE" : size "X", "B", "W", "D", "L"
+            "LOC" : tuple of interger for IEC location (0,1,2,...)
+            }, ...]
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        current_location = self.GetCurrentLocation()
+        # define a unique name for the generated C file
+        prefix = "_".join(map(str, current_location))
+        Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
+        # Create a new copy of the model
+        slave = self.GetCurrentNodeCopy()
+        slave.SetNodeName("OD_%s"%prefix)
+        # allow access to local OD from Slave PLC
+        pointers = config_utils.LocalODPointers(locations, current_location, slave)
+        res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
+        if res :
+            raise Exception, res
+        res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
+        if res :
+            raise Exception, res
+        return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
+
+    def LoadPrevious(self):
+        self.LoadCurrentPrevious()
+    
+    def LoadNext(self):
+        self.LoadCurrentNext()
+    
+    def GetBufferState(self):
+        return self.GetCurrentBufferState()
+
+#--------------------------------------------------
+#                    MASTER
+#--------------------------------------------------
+
+class MiniNodeManager(NodeManager):
+    
+    def __init__(self, parent, filepath, fullname):
+        NodeManager.__init__(self)
+        
+        self.OpenFileInCurrent(filepath)
+            
+        self.Parent = parent
+        self.Fullname = fullname
+        
+    def OnCloseEditor(self, view):
+        self.Parent.OnCloseEditor(view)
+    
+    def PlugFullName(self):
+        return self.Fullname
+    
+    def GetBufferState(self):
+        return self.GetCurrentBufferState()
+
+class _NodeListPlug(NodeList):
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="CanFestivalNode">
+        <xsd:complexType>
+          <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/>
+          <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
+          <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Master_NodeId)d"/>
+          <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """ % DEFAULT_SETTINGS
+    
+    EditorType = NetworkEditor
+    
+    def __init__(self):
+        manager = NodeManager()
+        NodeList.__init__(self, manager)
+        self.LoadProject(self.PlugPath())
+        self.SetNetworkName(self.BaseParams.getName())
+    
+    def GetCanDevice(self):
+        return self.CanFestivalNode.getCan_Device()
+    
+    def SetParamsAttribute(self, path, value):
+        result = ConfigTreeNode.SetParamsAttribute(self, path, value)
+        
+        # Filter IEC_Channel and Name, that have specific behavior
+        if path == "BaseParams.IEC_Channel" and self._View is not None:
+            self._View.SetBusId(self.GetCurrentLocation())
+        elif path == "BaseParams.Name":
+            self.SetNetworkName(value)
+        
+        return result
+    
+    def _OpenView(self):
+        ConfigTreeNode._OpenView(self)
+        if self._View is not None:
+            self._View.SetBusId(self.GetCurrentLocation())
+    
+    _GeneratedView = None
+    def _ShowMasterGenerated(self):
+        if self._GeneratedView is None:
+            buildpath = self._getBuildPath()
+            # Eventually create build dir
+            if not os.path.exists(buildpath):
+                self.GetPlugRoot().logger.write_error(_("Error: No PLC built\n"))
+                return
+            
+            masterpath = os.path.join(buildpath, "MasterGenerated.od")
+            if not os.path.exists(masterpath):
+                self.GetPlugRoot().logger.write_error(_("Error: No Master generated\n"))
+                return
+            
+            app_frame = self.GetPlugRoot().AppFrame
+            
+            manager = MiniNodeManager(self, masterpath, self.PlugFullName() + ".generated_master")
+            self._GeneratedView = SlaveEditor(app_frame.TabsOpened, manager, app_frame, False)
+            
+            app_frame.EditProjectElement(self._GeneratedView, "MasterGenerated")
+    
+    def _CloseGenerateView(self):
+        if self._GeneratedView is not None:
+            app_frame = self.GetPlugRoot().AppFrame
+            if app_frame is not None:
+                app_frame.DeletePage(self._GeneratedView)
+    
+    ConfNodeMethods = [
+        {"bitmap" : os.path.join("images", "NetworkEdit"),
+         "name" : _("Edit network"), 
+         "tooltip" : _("Edit CanOpen Network with NetworkEdit"),
+         "method" : "_OpenView"},
+        {"bitmap" : os.path.join("images", "ShowMaster"),
+         "name" : _("Show Master"), 
+         "tooltip" : _("Show Master generated by config_utils"),
+         "method" : "_ShowMasterGenerated"}
+    ]
+    
+    def OnCloseEditor(self, view):
+        ConfigTreeNode.OnCloseEditor(self, view)
+        if self._GeneratedView == view:
+            self._GeneratedView = None
+
+    def OnPlugClose(self):
+        ConfigTreeNode.OnPlugClose(self)
+        self._CloseGenerateView()
+        return True
+
+    def PlugTestModified(self):
+        return self.ChangesToSave or self.HasChanged()
+        
+    def OnPlugSave(self):
+        self.SetRoot(self.PlugPath())
+        return self.SaveProject() is None
+
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Generate C code
+        @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+        @param locations: List of complete variables locations \
+            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+            "NAME" : name of the variable (generally "__IW0_1_2" style)
+            "DIR" : direction "Q","I" or "M"
+            "SIZE" : size "X", "B", "W", "D", "L"
+            "LOC" : tuple of interger for IEC location (0,1,2,...)
+            }, ...]
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        self._CloseGenerateView()
+        current_location = self.GetCurrentLocation()
+        # define a unique name for the generated C file
+        prefix = "_".join(map(str, current_location))
+        Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
+        # Create a new copy of the model with DCF loaded with PDO mappings for desired location
+        try:
+            master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
+        except config_utils.PDOmappingException, e:
+            raise Exception, e.message
+        # Do generate C file.
+        res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
+        if res :
+            raise Exception, res
+        
+        file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
+        dump(master, file)
+        file.close()
+        
+        return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
+    
+    def LoadPrevious(self):
+        self.Manager.LoadCurrentPrevious()
+    
+    def LoadNext(self):
+        self.Manager.LoadCurrentNext()
+    
+    def GetBufferState(self):
+        return self.Manager.GetCurrentBufferState()
+    
+class RootClass:
+    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <xsd:element name="CanFestivalInstance">
+        <xsd:complexType>
+          <xsd:attribute name="CAN_Driver" type="xsd:string" use="optional" default="%(CAN_Driver)s"/>
+          <xsd:attribute name="Debug_mode" type="xsd:boolean" use="optional" default="false"/>
+        </xsd:complexType>
+      </xsd:element>
+    </xsd:schema>
+    """ % DEFAULT_SETTINGS
+    
+    PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen Master"),
+                       ("CanOpenSlave",_SlavePlug, "CanOpen Slave")]
+    def GetParamsAttributes(self, path = None):
+        infos = ConfigTreeNode.GetParamsAttributes(self, path = None)
+        for element in infos:
+            if element["name"] == "CanFestivalInstance":
+                for child in element["children"]:
+                    if child["name"] == "CAN_Driver":
+                        DLL_LIST= getattr(local_canfestival_config,"DLL_LIST",None)
+                        if DLL_LIST is not None:
+                            child["type"] = DLL_LIST  
+        return infos
+    
+    def GetCanDriver(self):
+        can_driver = self.CanFestivalInstance.getCAN_Driver()
+        if sys.platform == 'win32':
+            if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(can_driver + '_DEBUG.dll'))):
+                can_driver += '_DEBUG.dll'
+            else:
+                can_driver += '.dll'
+        return can_driver
+    
+    def PlugGenerate_C(self, buildpath, locations):
+        
+        format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
+                       "candriver" : self.GetCanDriver(),
+                       "nodes_includes" : "",
+                       "board_decls" : "",
+                       "nodes_init" : "",
+                       "nodes_open" : "",
+                       "nodes_stop" : "",
+                       "nodes_close" : "",
+                       "nodes_send_sync" : "",
+                       "nodes_proceed_sync" : "",
+                       "slavebootups" : "",
+                       "slavebootup_register" : "",
+                       "post_sync" : "",
+                       "post_sync_register" : "",
+                       }
+        for child in self.IECSortedChilds():
+            childlocstr = "_".join(map(str,child.GetCurrentLocation()))
+            nodename = "OD_%s" % childlocstr
+            
+            # Try to get Slave Node
+            child_data = getattr(child, "CanFestivalSlaveNode", None)
+            if child_data is None:
+                # Not a slave -> master
+                child_data = getattr(child, "CanFestivalNode")
+                # Apply sync setting
+                format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n    '%(
+                       nodename,
+                       child_data.getNodeId())
+                if child_data.getSync_TPDOs():
+                    format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n    '%(nodename)
+                    format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n    '%(nodename)
+
+                # initialize and declare node boot status variables for post_SlaveBootup lookup
+                SlaveIDs = child.GetSlaveIDs()
+                if len(SlaveIDs) == 0:
+                    # define post_SlaveBootup lookup functions
+                    format_dict["slavebootups"] += (
+                        "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
+                else:
+                    for id in SlaveIDs:
+                        format_dict["slavebootups"] += (
+                        "int %s_slave_%d_booted = 0;\n"%(nodename, id))
+                    # define post_SlaveBootup lookup functions
+                    format_dict["slavebootups"] += (
+                        "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n"%(nodename)+
+                        "    switch(nodeId){\n")
+                    # one case per declared node, mark node as booted
+                    for id in SlaveIDs:
+                        format_dict["slavebootups"] += (
+                        "        case %d:\n"%(id)+
+                        "            %s_slave_%d_booted = 1;\n"%(nodename, id)+
+                        "            break;\n")
+                    format_dict["slavebootups"] += (
+                        "        default:\n"+
+                        "            break;\n"+
+                        "    }\n"+
+                        "    if( ")
+                    # expression to test if all declared nodes booted
+                    format_dict["slavebootups"] += " && ".join(["%s_slave_%d_booted"%(nodename, id) for id in SlaveIDs])
+                    format_dict["slavebootups"] += " )\n" + (
+                        "        Master_post_SlaveBootup(d,nodeId);\n"+
+                        "}\n")
+                # register previously declared func as post_SlaveBootup callback for that node
+                format_dict["slavebootup_register"] += (
+                    "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n"%(nodename,nodename))
+            else:
+                # Slave node
+                align = child_data.getSync_Align()
+                align_ratio=child_data.getSync_Align_Ratio()
+                if align > 0:
+                    format_dict["post_sync"] += (
+                        "static int %s_CalCount = 0;\n"%(nodename)+
+                        "static void %s_post_sync(CO_Data* d){\n"%(nodename)+
+                        "    if(%s_CalCount < %d){\n"%(nodename, align)+
+                        "        %s_CalCount++;\n"%(nodename)+
+                        "        align_tick(-1);\n"+
+                        "    }else{\n"+
+                        "        align_tick(%d);\n"%(align_ratio)+
+                        "    }\n"+
+                        "}\n")
+                    format_dict["post_sync_register"] += (
+                        "%s_Data.post_sync = %s_post_sync;\n"%(nodename,nodename))
+                format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n    '%(
+                       nodename,
+                       child_data.getNodeId())
+    
+            # Include generated OD headers
+            format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
+            # Declare CAN channels according user filled config
+            format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
+                   nodename,
+                   child.GetCanDevice(),
+                   child_data.getCAN_Baudrate())
+            format_dict["nodes_open"] += 'NODE_OPEN(%s)\n    '%(nodename)
+            format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n    '%(nodename)
+            format_dict["nodes_stop"] += 'NODE_STOP(%s)\n    '%(nodename)
+        
+        filename = os.path.join(os.path.split(__file__)[0],"cf_runtime.c")
+        cf_main = open(filename).read() % format_dict
+        cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict)
+        f = open(cf_main_path,'w')
+        f.write(cf_main)
+        f.close()
+        
+        return [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/cf_runtime.c	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,150 @@
+
+#include "canfestival.h"
+
+/* CanFestival nodes generated OD headers*/
+%(nodes_includes)s
+
+#define BOARD_DECL(nodename, busname, baudrate)\
+    s_BOARD nodename##Board = {busname, baudrate};
+
+/* CAN channels declaration */
+%(board_decls)s
+
+/* Keep track of init level to cleanup correctly */
+static int init_level=0;
+/* Retrieve PLC cycle time */
+extern int common_ticktime__;
+
+/* Called once all NetworkEdit declares slaves have booted*/
+static void Master_post_SlaveBootup(CO_Data* d, UNS8 nodeId)
+{
+    /* Put the master in operational mode */
+    setState(d, Operational);
+
+    /* Ask slave node to go in operational mode */
+    masterSendNMTstateChange (d, 0, NMT_Start_Node);
+}
+
+/* Per master node slavebootup callbacks. Checks that
+ * every node have booted before calling Master_post_SlaveBootup */
+%(slavebootups)s
+
+/* One slave node post_sync callback.
+ * Used to align PLC tick-time on CANopen SYNC
+ */
+%(post_sync)s
+
+#define NODE_FORCE_SYNC(nodename) \
+    /* Artificially force sync state to 1 so that it is not started */\
+    nodename##_Data.CurrentCommunicationState.csSYNC = -1;\
+    /* Force sync period to common_ticktime__ so that other node can read it*/\
+    *nodename##_Data.COB_ID_Sync = 0x40000080;\
+    *nodename##_Data.Sync_Cycle_Period = common_ticktime__ * 1000;
+
+#define NODE_INIT(nodename, nodeid) \
+    /* Defining the node Id */\
+    setNodeId(&nodename##_Data, nodeid);\
+    /* init */\
+    setState(&nodename##_Data, Initialisation);
+
+#define NODE_MASTER_INIT(nodename, nodeid) \
+    NODE_FORCE_SYNC(nodename) \
+    NODE_INIT(nodename, nodeid)
+
+#define NODE_SLAVE_INIT(nodename, nodeid) \
+    NODE_INIT(nodename, nodeid)
+
+void InitNodes(CO_Data* d, UNS32 id)
+{
+    %(slavebootup_register)s
+    %(post_sync_register)s
+    %(nodes_init)s
+}
+
+#define NODE_STOP(nodename) \
+    if(init_level-- > 0)\
+    {\
+        masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\
+        setState(&nodename##_Data, Stopped);\
+    }
+
+void Exit(CO_Data* d, UNS32 id)
+{
+    %(nodes_stop)s
+}
+
+#define NODE_CLOSE(nodename) \
+    if(init_level_c-- > 0)\
+    {\
+      canClose(&nodename##_Data);\
+    }
+
+void __cleanup_%(locstr)s(void)
+{
+    // Stop timer thread
+    if(init_level-- > 0){
+    int init_level_c = init_level;
+        StopTimerLoop(&Exit);
+        %(nodes_close)s
+    }
+
+    TimerCleanup();
+}
+
+#ifndef stderr
+#define fprintf(...)
+#define fflush(...)
+#endif
+
+#define NODE_OPEN(nodename)\
+    if(!canOpen(&nodename##Board,&nodename##_Data)){\
+        fprintf(stderr,"Cannot open CAN intefrace %%s at speed %%s\n for CANopen node \"" #nodename "\"",nodename##Board.busname, nodename##Board.baudrate);\
+        fflush(stderr);\
+        return -1;\
+    }\
+    init_level++;
+
+/***************************  INIT  *****************************************/
+int __init_%(locstr)s(int argc,char **argv)
+{
+#ifndef NOT_USE_DYNAMIC_LOADING
+    if( !LoadCanDriver("%(candriver)s") ){
+        fprintf(stderr, "Cannot load CAN interface library for CanFestival (%(candriver)s)\n");\
+        fflush(stderr);\
+        return -1;\
+    }
+#endif
+
+    TimerInit();
+
+    %(nodes_open)s
+
+    // Start timer thread
+    StartTimerLoop(&InitNodes);
+    init_level++;
+    return 0;
+}
+
+#define NODE_SEND_SYNC(nodename)\
+    sendSYNCMessage(&nodename##_Data);
+
+void __retrieve_%(locstr)s(void)
+{
+    /* Locks the stack, so that no changes occurs while PLC access variables
+     * TODO : implement buffers to avoid such a big lock
+     *  */
+    EnterMutex();
+    /* Send Sync */
+    %(nodes_send_sync)s
+}
+
+#define NODE_PROCEED_SYNC(nodename)\
+    proceedSYNC(&nodename##_Data);
+
+void __publish_%(locstr)s(void)
+{
+    /* Process sync event */
+    %(nodes_proceed_sync)s
+    LeaveMutex();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/config_utils.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,737 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of Beremiz, a Integrated Development Environment for
+#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+from types import *
+
+# Translation between IEC types and Can Open types
+IECToCOType = {"BOOL":0x01, "SINT":0x02, "INT":0x03,"DINT":0x04,"LINT":0x10,
+               "USINT":0x05,"UINT":0x06,"UDINT":0x07,"ULINT":0x1B,"REAL":0x08,
+               "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07,
+               "LWORD":0x1B,"WSTRING":0x0B}
+
+# Constants for PDO types 
+RPDO = 1
+TPDO = 2
+
+SlavePDOType = {"I" : TPDO, "Q" : RPDO}
+InvertPDOType = {RPDO : TPDO, TPDO : RPDO}
+PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800}
+PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180}
+
+VariableIncrement = 0x100
+VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000}
+VariableDirText = {TPDO : "__I", RPDO : "__Q"}
+VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6)))
+
+TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
+
+#-------------------------------------------------------------------------------
+#                  Specific exception for PDO mapping errors
+#-------------------------------------------------------------------------------
+
+class PDOmappingException(Exception):
+    pass
+
+
+def LE_to_BE(value, size):
+    """
+    Convert Little Endian to Big Endian
+    @param value: value expressed in integer
+    @param size: number of bytes generated
+    @return: a string containing the value converted
+    """
+    
+    data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
+    list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
+    list_car.reverse()
+    return "".join([chr(int(car, 16)) for car in list_car])
+
+
+def GetNodePDOIndexes(node, type, parameters = False):
+    """
+    Find the PDO indexes of a node
+    @param node: node 
+    @param type: type of PDO searched (RPDO or TPDO or both)
+    @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
+    @return: a list of indexes found
+    """
+    
+    indexes = []
+    if type & RPDO:
+        indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
+    if type & TPDO:
+        indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF])
+    if not parameters:
+        return [idx + 0x200 for idx in indexes]
+    else:
+        return indexes
+
+
+def SearchNodePDOMapping(loc_infos, node):
+    """
+    Find the PDO indexes of a node
+    @param node: node 
+    @param type: type of PDO searched (RPDO or TPDO or both)
+    @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
+    @return: a list of indexes found
+    """
+    
+    model = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8)
+    
+    for PDOidx in GetNodePDOIndexes(node, loc_infos["pdotype"]):
+        values = node.GetEntry(PDOidx)
+        if values != None:
+            for subindex, mapping in enumerate(values):
+                if subindex != 0 and mapping & 0xFFFFFF00 == model:
+                    return PDOidx, subindex
+    return None
+
+
+def GeneratePDOMappingDCF(idx, cobid, transmittype, pdomapping):
+    """
+    Build concise DCF value for configuring a PDO
+    @param idx: index of PDO parameters
+    @param cobid: PDO generated COB ID
+    @param transmittype : PDO transmit type
+    @param pdomapping: list of PDO mappings
+    @return: a tuple of value and number of parameters to add to DCF 
+    """
+    
+    # Create entry for RPDO or TPDO parameters and Disable PDO
+    dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x80000000 + cobid, 4)
+    # Set Transmit type synchrone
+    dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1)
+    # Re-Enable PDO
+    #         ---- INDEX -----   --- SUBINDEX ----   ----- SIZE ------   ------ DATA ------
+    dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4)
+    nbparams = 3
+    if len(pdomapping) > 0:
+        dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(0x00, 1) + LE_to_BE(0x01, 4) + LE_to_BE(len(pdomapping), 1)
+        nbparams += 1
+        # Map Variables
+        for subindex, (name, loc_infos) in enumerate(pdomapping):
+            value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"]
+            dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4)
+            nbparams += 1
+    return dcfdata, nbparams
+
+class ConciseDCFGenerator:
+
+    def __init__(self, nodelist, nodename):
+        # Dictionary of location informations classed by name
+        self.IECLocations = {}
+        # Dictionary of location that have not been mapped yet
+        self.LocationsNotMapped = {}
+        # Dictionary of location informations classed by name
+        self.MasterMapping = {}
+        # List of COB IDs available
+        self.ListCobIDAvailable = range(0x180, 0x580)
+        # Dictionary of mapping value where unexpected variables are stored
+        self.TrashVariables = {}
+        # Dictionary of pointed variables
+        self.PointedVariables = {}
+        
+        self.NodeList = nodelist
+        self.Manager = self.NodeList.Manager
+        self.MasterNode = self.Manager.GetCurrentNodeCopy()
+        self.MasterNode.SetNodeName(nodename)
+        self.PrepareMasterNode()
+
+    def GetPointedVariables(self):
+        return self.PointedVariables
+    
+    def RemoveUsedNodeCobId(self, node):
+        """
+        Remove all PDO COB ID used by the given node from the list of available COB ID
+        @param node: node
+        @return: a tuple of number of RPDO and TPDO for the node
+        """
+        
+        # Get list of all node TPDO and RPDO indexes
+        nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True)
+        nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True)
+        
+        # Mark all the COB ID of the node already mapped PDO as not available
+        for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes:
+            pdo_cobid = node.GetEntry(PdoIdx, 0x01)
+            # Extract COB ID, if PDO isn't active
+            if pdo_cobid > 0x600 :
+                pdo_cobid -= 0x80000000
+            # Remove COB ID from the list of available COB ID
+            if pdo_cobid in self.ListCobIDAvailable:
+                self.ListCobIDAvailable.remove(pdo_cobid)
+        
+        return len(nodeRpdoIndexes), len(nodeTpdoIndexes)
+
+    
+    def PrepareMasterNode(self):
+        """
+        Add mandatory entries for DCF generation into MasterNode.
+        """
+        
+        # Adding DCF entry into Master node
+        if not self.MasterNode.IsEntry(0x1F22):
+            self.MasterNode.AddEntry(0x1F22, 1, "")
+        self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode)
+        
+        # Adding trash mappable variables for unused mapped datas
+        idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID()
+        # Add an entry for storing unexpected all variable
+        self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode)
+        for subidx, (size, typeidx) in enumerate(TrashVariables):
+            # Add a subentry for storing unexpected variable of this size
+            self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode)
+            self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode)
+            # Store the mapping value for this entry
+            self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size
+        
+        RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode)
+        
+        # Store the indexes of the first RPDO and TPDO available for MasterNode
+        self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber}
+
+        # Prepare MasterNode with all nodelist slaves
+        for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()):
+            node = nodeinfos["Node"]
+            node.SetNodeID(nodeid)
+            
+            RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
+            
+            # Get Slave's default SDO server parameters
+            RSDO_cobid = node.GetEntry(0x1200,0x01)
+            if not RSDO_cobid:
+                RSDO_cobid = 0x600 + nodeid
+            TSDO_cobid = node.GetEntry(0x1200,0x02)
+            if not TSDO_cobid:
+                TSDO_cobid = 0x580 + nodeid
+            
+            # Configure Master's SDO parameters entries
+            self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode)
+            self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid)
+            self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid)
+            self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid)        
+        
+    
+    def GetMasterNode(self):
+        """
+        Return MasterNode.
+        """
+        return self.MasterNode
+    
+    def AddParamsToDCF(self, nodeid, data, nbparams):
+        """
+        Add entry to DCF, for the requested nodeID
+        @param nodeid: id of the slave (int)
+        @param data: data to add to slave DCF (string)
+        @param nbparams: number of params added to slave DCF (int)
+        """
+        # Get current DCF for slave
+        nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid)
+        
+        # Extract data and number of params in current DCF
+        if nodeDCF != None and nodeDCF != '':
+            tmpnbparams = [i for i in nodeDCF[:4]]
+            tmpnbparams.reverse()
+            nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
+            data = nodeDCF[4:] + data
+        
+        # Build new DCF
+        dcf = LE_to_BE(nbparams, 0x04) + data
+        # Set new DCF for slave
+        self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
+    
+    def GetEmptyPDO(self, nodeid, pdotype, start_index=None):
+        """
+        Search a not configured PDO for a slave
+        @param node: the slave node object
+        @param pdotype: type of PDO to generated (RPDO or TPDO)
+        @param start_index: Index where search must start (default: None)
+        @return tuple of PDO index, COB ID and number of subindex defined
+        """
+        # If no start_index defined, start with PDOtype base index
+        if start_index is None:
+            index = PDOTypeBaseIndex[pdotype]
+        else:
+            index = start_index
+        
+        # Search for all PDO possible index until find a configurable PDO
+        # starting from start_index
+        while index < PDOTypeBaseIndex[pdotype] + 0x200:
+            values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200)
+            if values != None and values[0] > 0:
+                # Check that all subindex upper than 0 equal 0 => configurable PDO
+                if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True):
+                    cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1)
+                    # If no COB ID defined in PDO, generate a new one (not used)
+                    if cobid == 0:
+                        if len(self.ListCobIDAvailable) == 0:
+                            return None
+                        # Calculate COB ID from standard values
+                        if index < PDOTypeBaseIndex[pdotype] + 4:
+                            cobid = PDOTypeBaseCobId[pdotype] + 0x100 * (index - PDOTypeBaseIndex[pdotype]) + nodeid
+                        if cobid not in self.ListCobIDAvailable:
+                            cobid = self.ListCobIDAvailable.pop(0)
+                    return index, cobid, values[0]
+            index += 1
+        return None
+    
+    def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs):
+        """
+        Record a new mapping request for a slave, and add related slave config to the DCF
+        @param nodeid: id of the slave (int)
+        @param pdotype: type of PDO to generated (RPDO or TPDO)
+        @param pdomapping: list od variables to map with PDO
+        """
+        # Add an entry to MasterMapping
+        self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], 
+            "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
+        
+        # Return the data to add to DCF
+        if sync_TPDOs:
+            return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
+        else:
+            return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
+        return 0, ""
+    
+    def GenerateDCF(self, locations, current_location, sync_TPDOs):
+        """
+        Generate Concise DCF of MasterNode for the locations list given
+        @param locations: list of locations to be mapped
+        @param current_location: tuple of the located prefixes not to be considered
+        @param sync_TPDOs: indicate if TPDO must be synchronous
+        """
+        
+        #-------------------------------------------------------------------------------
+        #               Verify that locations correspond to real slave variables
+        #-------------------------------------------------------------------------------
+        
+        # Get list of locations check if exists and mappables -> put them in IECLocations
+        for location in locations:
+            COlocationtype = IECToCOType[location["IEC_TYPE"]]
+            name = location["NAME"]
+            if name in self.IECLocations:
+                if self.IECLocations[name]["type"] != COlocationtype:
+                    raise PDOmappingException, _("Type conflict for location \"%s\"") % name 
+            else:
+                # Get only the part of the location that concern this node
+                loc = location["LOC"][len(current_location):]
+                # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
+                if len(loc) not in (2, 3, 4):
+                    raise PDOmappingException, _("Bad location size : %s") % str(loc)
+                elif len(loc) == 2:
+                    continue
+                
+                direction = location["DIR"]
+                
+                sizelocation = location["SIZE"]
+                
+                # Extract and check nodeid
+                nodeid, index, subindex = loc[:3]
+                
+                # Check Id is in slave node list
+                if nodeid not in self.NodeList.SlaveNodes.keys():
+                    raise PDOmappingException, _("Non existing node ID : %d (variable %s)") % (nodeid,name)
+                
+                # Get the model for this node (made from EDS)
+                node = self.NodeList.SlaveNodes[nodeid]["Node"]
+                
+                # Extract and check index and subindex
+                if not node.IsEntry(index, subindex):
+                    raise PDOmappingException, _("No such index/subindex (%x,%x) in ID : %d (variable %s)") % (index,subindex,nodeid,name)
+                
+                # Get the entry info
+                subentry_infos = node.GetSubentryInfos(index, subindex)
+                
+                # If a PDO mappable
+                if subentry_infos and subentry_infos["pdo"]:
+                    if sizelocation == "X" and len(loc) > 3:
+                        numbit = loc[3]
+                    elif sizelocation != "X" and len(loc) > 3:
+                        raise PDOmappingException, _("Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
+                    else:
+                        numbit = None
+                    
+                    if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
+                        raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d  for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
+                    
+                    typeinfos = node.GetEntryInfos(COlocationtype)
+                    self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
+                                                "nodeid": nodeid, "index": index,"subindex": subindex,
+                                                "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation}
+                else:
+                    raise PDOmappingException, _("Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
+        
+        #-------------------------------------------------------------------------------
+        #                         Search for locations already mapped
+        #-------------------------------------------------------------------------------
+        
+        for name, locationinfos in self.IECLocations.items():
+            node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"]
+            
+            # Search if slave has a PDO mapping this locations
+            result = SearchNodePDOMapping(locationinfos, node)
+            if result != None:
+                index, subindex = result
+                # Get COB ID of the PDO
+                cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1)
+                
+                # Add PDO to MasterMapping
+                if cobid not in self.MasterMapping.keys():
+                    # Verify that PDO transmit type is conform to sync_TPDOs
+                    transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2)
+                    if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF:
+                        if sync_TPDOs:
+                            # Change TransmitType to SYNCHRONE
+                            data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, [])
+                        else:
+                            # Change TransmitType to ASYCHRONE
+                            data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, [])
+                        
+                        # Add entry to slave dcf to change transmit type of 
+                        self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams)
+                                    
+                    mapping = [None]
+                    values = node.GetEntry(index)
+                    # Store the size of each entry mapped in PDO
+                    for value in values[1:]:
+                        if value != 0:
+                            mapping.append(value % 0x100)
+                    self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping}
+            
+                # Indicate that this PDO entry must be saved
+                if locationinfos["bit"] is not None:
+                    if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType):
+                        self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex]
+                    if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]):
+                        self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name)
+                else:
+                    self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
+                
+            else:
+                # Add location to those that haven't been mapped yet
+                if locationinfos["nodeid"] not in self.LocationsNotMapped.keys():
+                    self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []}
+                self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos))
+    
+        #-------------------------------------------------------------------------------
+        #                         Build concise DCF for the others locations
+        #-------------------------------------------------------------------------------
+        
+        for nodeid, locations in self.LocationsNotMapped.items():
+            node = self.NodeList.SlaveNodes[nodeid]["Node"]
+            
+            # Initialize number of params and data to add to node DCF
+            nbparams = 0
+            dataparams = ""
+            
+            # Generate the best PDO mapping for each type of PDO
+            for pdotype in (TPDO, RPDO):
+                if len(locations[pdotype]) > 0:
+                    pdosize = 0
+                    pdomapping = []
+                    result = self.GetEmptyPDO(nodeid, pdotype)
+                    if result is None:
+                        raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
+                    pdoindex, pdocobid, pdonbparams = result
+                    for name, loc_infos in locations[pdotype]:
+                        pdosize += loc_infos["size"]
+                        # If pdo's size > 64 bits
+                        if pdosize > 64 or len(pdomapping) >= pdonbparams:
+                            # Generate a new PDO Mapping
+                            data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
+                            dataparams += data
+                            nbparams += nbaddedparams
+                            pdosize = loc_infos["size"]
+                            pdomapping = [(name, loc_infos)]
+                            result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
+                            if result is None:
+                                raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
+                            pdoindex, pdocobid, pdonbparams = result
+                        else:
+                            pdomapping.append((name, loc_infos))
+                    # If there isn't locations yet but there is still a PDO to generate
+                    if len(pdomapping) > 0:
+                        # Generate a new PDO Mapping
+                        data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
+                        dataparams += data
+                        nbparams += nbaddedparams
+                
+            # Add number of params and data to node DCF
+            self.AddParamsToDCF(nodeid, dataparams, nbparams)
+        
+        #-------------------------------------------------------------------------------
+        #                         Master Node Configuration
+        #-------------------------------------------------------------------------------
+        
+        # Generate Master's Configuration from informations stored in MasterMapping
+        for cobid, pdo_infos in self.MasterMapping.items():
+            # Get next PDO index in MasterNode for this PDO type
+            current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]]
+            
+            # Search if there is already a PDO in MasterNode with this cob id
+            for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True):
+                if self.MasterNode.GetEntry(idx, 1) == cobid:
+                    current_idx = idx
+            
+            # Add a PDO to MasterNode if not PDO have been found
+            if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]:
+                addinglist = [current_idx, current_idx + 0x200]
+                self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode)
+                self.MasterNode.SetEntry(current_idx, 0x01, cobid)
+                
+                # Increment the number of PDO for this PDO type
+                self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1
+            
+            # Change the transmit type of the PDO
+            if sync_TPDOs:
+                self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
+            else:
+                self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
+            
+            mapping = []
+            for item in pdo_infos["mapping"]:
+                if isinstance(item, ListType):
+                    mapping.extend(item)
+                else:
+                    mapping.append(item)
+            
+            # Add some subentries to PDO mapping if there is not enough
+            if len(mapping) > 1:
+                self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
+            
+            # Generate MasterNode's PDO mapping
+            for subindex, variable in enumerate(mapping):
+                if subindex == 0:
+                    continue
+                new_index = False
+                
+                if isinstance(variable, (IntType, LongType)):
+                    # If variable is an integer then variable is unexpected
+                    self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
+                else:
+                    typeidx, varname = variable
+                    variable_infos = self.IECLocations[varname]
+                    
+                    # Calculate base index for storing variable
+                    mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \
+                                     VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
+                                     variable_infos["nodeid"]
+                    
+                    # Generate entry name
+                    indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
+                                                 variable_infos["sizelocation"],
+                                                 '_'.join(map(str,current_location)),
+                                                 variable_infos["nodeid"])    
+                    
+                    # Search for an entry that has an empty subindex 
+                    while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
+                        # Entry doesn't exist
+                        if not self.MasterNode.IsEntry(mapvariableidx):    
+                            # Add entry to MasterNode
+                            self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
+                            new_index = True
+                            nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
+                        else:
+                            # Get Number of subentries already defined
+                            nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
+                            # if entry is full, go to next entry possible or stop now
+                            if nbsubentries == 0xFF:
+                                mapvariableidx += 8 * VariableIncrement
+                            else:
+                                break
+                                
+                    # Verify that a not full entry has been found
+                    if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
+                        # Generate subentry name
+                        if variable_infos["bit"] != None:
+                            subindexname = "%(index)d_%(subindex)d_%(bit)d"%variable_infos
+                        else:
+                            subindexname = "%(index)d_%(subindex)d"%variable_infos
+                        # If entry have just been created, no subentry have to be added
+                        if not new_index:
+                            self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode)
+                            nbsubentries += 1
+                        # Add informations to the new subentry created
+                        self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname})
+                        self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx})
+                        
+                        # Set value of the PDO mapping
+                        typeinfos = self.Manager.GetEntryInfos(typeidx)
+                        if typeinfos != None:
+                            value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
+                            self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
+                        
+                        # Add variable to pointed variables
+                        self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
+
+def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename):
+    """
+    Fills a CanFestival network editor model, with DCF with requested PDO mappings.
+    @param locations: List of complete variables locations \
+        [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+        "NAME" : name of the variable (generally "__IW0_1_2" style)
+        "DIR" : direction "Q","I" or "M"
+        "SIZE" : size "X", "B", "W", "D", "L"
+        "LOC" : tuple of interger for IEC location (0,1,2,...)
+        }, ...]
+    @param nodelist: CanFestival network editor model
+    @return: a modified copy of the given CanFestival network editor model
+    """
+    
+    dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
+    dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
+    masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
+    # allow access to local OD from Master PLC
+    pointers.update(LocalODPointers(locations, current_location, masternode))
+    return masternode,pointers
+
+def LocalODPointers(locations, current_location, slave):
+    IECLocations = {}
+    pointers = {}
+    for location in locations:
+        COlocationtype = IECToCOType[location["IEC_TYPE"]]
+        name = location["NAME"]
+        if name in IECLocations:
+            if IECLocations[name] != COlocationtype:
+                raise PDOmappingException, _("Type conflict for location \"%s\"") % name 
+        else:
+            # Get only the part of the location that concern this node
+            loc = location["LOC"][len(current_location):]
+            # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
+            if len(loc) not in (2, 3, 4):
+                raise PDOmappingException, _("Bad location size : %s") % str(loc)
+            elif len(loc) != 2:
+                continue
+            
+            # Extract and check nodeid
+            index, subindex = loc[:2]
+            
+            # Extract and check index and subindex
+            if not slave.IsEntry(index, subindex):
+                raise PDOmappingException, _("No such index/subindex (%x,%x) (variable %s)") % (index, subindex, name)
+            
+            # Get the entry info
+            subentry_infos = slave.GetSubentryInfos(index, subindex)    
+            if subentry_infos["type"] != COlocationtype:
+                raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d  for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
+            
+            IECLocations[name] = COlocationtype
+            pointers[(index, subindex)] = name
+    return pointers
+        
+if __name__ == "__main__":
+    import os, sys, getopt
+
+    def usage():
+        print """
+Usage of config_utils.py test :
+
+    %s [options]
+
+Options:
+    --help  (-h)
+            Displays help informations for config_utils
+
+    --reset (-r)
+            Reset the reference result of config_utils test.
+            Use with caution. Be sure that config_utils
+            is currently working properly.
+"""%sys.argv[0]
+    
+    # Boolean that indicate if reference result must be redefined
+    reset = False
+
+    # Extract command options
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"])
+    except getopt.GetoptError:
+        # print help information and exit:
+        usage()
+        sys.exit(2)
+
+    # Test each option
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif o in ("-r", "--reset"):
+            reset = True
+
+    # Extract workspace base folder
+    base_folder = sys.path[0]
+    for i in xrange(3):
+        base_folder = os.path.split(base_folder)[0]
+    # Add CanFestival folder to search pathes
+    sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
+    
+    from nodemanager import *
+    from nodelist import *
+    
+    # Open the test nodelist contained into test_config folder
+    manager = NodeManager()
+    nodelist = NodeList(manager)
+    result = nodelist.LoadProject("test_config")
+    
+    # List of locations, we try to map for test
+    locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)},
+                 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)},
+                 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)},
+                 {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)},
+                 {"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24578_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24578,1)},
+                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)},
+                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)},
+                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)},
+                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)},
+                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}]
+    
+    # Generate MasterNode configuration
+    try:
+        masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
+    except ValueError, message:
+        print "%s\nTest Failed!"%message
+        sys.exit()
+    
+    import pprint
+    # Get Text corresponding to MasterNode 
+    result_node = masternode.PrintString()
+    result_vars = pprint.pformat(pointedvariables)
+    result = result_node + "\n********POINTERS*********\n" + result_vars + "\n"
+    
+    # If reset has been choosen
+    if reset:
+        # Write Text into reference result file
+        testfile = open("test_config/result.txt", "w")
+        testfile.write(result)
+        testfile.close()
+        
+        print "Reset Successful!"
+    else:
+        import os
+        
+        testfile = open("test_config/result_tmp.txt", "w")
+        testfile.write(result)
+        testfile.close()
+        
+        os.system("diff test_config/result.txt test_config/result_tmp.txt")
+        os.remove("test_config/result_tmp.txt")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/eds/PEAK MicroMod.eds	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1289 @@
+[FileInfo]
+CreatedBy=ESAcademy
+ModifiedBy=ESAcademy
+Description=PEAK MicroMod CANopenIA Generic
+CreationTime=09:41PM
+CreationDate=05-05-2003
+ModificationTime=05:05PM
+ModificationDate=03-23-2005
+FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds
+FileVersion=1
+FileRevision=1
+EDSVersion=4
+
+[DeviceInfo]
+VendorName=PEAK System Technik
+VendorNumber=0x00000175
+ProductName=PEAK MicroMod CANopenIA Generic
+ProductNumber=0x00100000
+RevisionNumber=0x00010001
+OrderCode=na
+BaudRate_10=0
+BaudRate_20=0
+BaudRate_50=1
+BaudRate_125=1
+BaudRate_250=1
+BaudRate_500=1
+BaudRate_800=1
+BaudRate_1000=1
+SimpleBootUpMaster=0
+SimpleBootUpSlave=1
+Granularity=0
+DynamicChannelsSupported=0
+CompactPDO=0
+GroupMessaging=0
+NrOfRXPDO=4
+NrOfTXPDO=4
+LSS_Supported=0
+
+[DummyUsage]
+Dummy0001=0
+Dummy0002=0
+Dummy0003=0
+Dummy0004=0
+Dummy0005=1
+Dummy0006=1
+Dummy0007=1
+
+[Comments]
+Lines=0
+
+[MandatoryObjects]
+SupportedObjects=3
+1=0x1000
+2=0x1001
+3=0x1018
+
+[1000]
+ParameterName=Device Type
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x000F0191
+PDOMapping=0
+
+[1001]
+ParameterName=Error Register
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=0
+PDOMapping=0
+
+[1018]
+ParameterName=Identity Object
+ObjectType=0x9
+SubNumber=4
+
+[1018sub0]
+ParameterName=number of entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=3
+PDOMapping=0
+
+[1018sub1]
+ParameterName=Vendor ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x00000175
+PDOMapping=0
+
+[1018sub2]
+ParameterName=Product Code
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x00100000
+PDOMapping=0
+
+[1018sub3]
+ParameterName=Revision number
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+DefaultValue=0x00010001
+PDOMapping=0
+
+[OptionalObjects]
+SupportedObjects=41
+1=0x1002
+2=0x1005
+3=0x1008
+4=0x1009
+5=0x100A
+6=0x100C
+7=0x100D
+8=0x1010
+9=0x1011
+10=0x1016
+11=0x1017
+12=0x1020
+13=0x1400
+14=0x1401
+15=0x1402
+16=0x1403
+17=0x1600
+18=0x1601
+19=0x1602
+20=0x1603
+21=0x1800
+22=0x1801
+23=0x1802
+24=0x1803
+25=0x1A00
+26=0x1A01
+27=0x1A02
+28=0x1A03
+29=0x1F50
+30=0x6000
+31=0x6002
+32=0x6200
+33=0x6202
+34=0x6206
+35=0x6207
+36=0x6401
+37=0x6411
+38=0x6423
+39=0x6426
+40=0x6443
+41=0x6444
+
+[1002]
+ParameterName=PEAK Status Register
+ObjectType=0x7
+DataType=0x0007
+AccessType=ro
+PDOMapping=0
+
+[1005]
+ParameterName=COB-ID SYNC
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x00000080
+PDOMapping=0
+
+[1008]
+ParameterName=Manufacturer Device Name
+ObjectType=0x7
+DataType=0x0009
+AccessType=const
+PDOMapping=0
+
+[1009]
+ParameterName=Manufacturer Hardware Version
+ObjectType=0x7
+DataType=0x0009
+AccessType=const
+PDOMapping=0
+
+[100a]
+ParameterName=Manufacturer Software Version
+ObjectType=0x7
+DataType=0x0009
+AccessType=const
+PDOMapping=0
+
+[100c]
+ParameterName=Guard Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[100d]
+ParameterName=Life Time Factor
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0x00
+PDOMapping=0
+
+[1010]
+ParameterName=Store Parameter Field
+ObjectType=0x8
+SubNumber=2
+
+[1010sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[1010sub1]
+ParameterName=Save all Parameters
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1011]
+ParameterName=Restore Default Parameters
+ObjectType=0x8
+SubNumber=2
+
+[1011sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[1011sub1]
+ParameterName=Restore all Default Parameters
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1016]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x8
+SubNumber=4
+
+[1016sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=3
+PDOMapping=0
+LowLimit=0x1
+
+[1016sub1]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1016sub2]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1016sub3]
+ParameterName=Consumer Heartbeat Time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1017]
+ParameterName=Producer Heartbeat Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1020]
+ParameterName=Verify Configuration
+ObjectType=0x8
+SubNumber=3
+
+[1020sub0]
+ParameterName=Number of entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+
+[1020sub1]
+ParameterName=Configuration date
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1020sub2]
+ParameterName=Configuration time
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+PDOMapping=0
+
+[1400]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1400sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+
+[1400sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x200
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1400sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1401]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1401sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+
+[1401sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x300
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1401sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1402]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1402sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1402sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x80000400
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1402sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1403]
+ParameterName=Receive PDO Communication Parameter
+ObjectType=0x9
+SubNumber=3
+
+[1403sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=2
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1403sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x80000500
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1403sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1600]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=2
+
+[1600sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=1
+PDOMapping=0
+
+[1600sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x62000108
+PDOMapping=0
+
+[1601]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1601sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=4
+PDOMapping=0
+
+[1601sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110110
+PDOMapping=0
+
+[1601sub2]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110210
+PDOMapping=0
+
+[1601sub3]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110310
+PDOMapping=0
+
+[1601sub4]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64110410
+PDOMapping=0
+
+[1602]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=1
+
+[1602sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1603]
+ParameterName=Receive PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=1
+
+[1603sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1800]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1800sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1800sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x180
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1800sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1800sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1800sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1801]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1801sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1801sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x280
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1801sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1801sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1801sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1802]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1802sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1802sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x380
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1802sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1802sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1802sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1803]
+ParameterName=Transmit PDO Communication Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1803sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=5
+PDOMapping=0
+LowLimit=0x02
+HighLimit=0x05
+
+[1803sub1]
+ParameterName=COB-ID
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=$NODEID+0x80000480
+PDOMapping=0
+LowLimit=0x00000001
+HighLimit=0xFFFFFFFF
+
+[1803sub2]
+ParameterName=Transmission Type
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=255
+PDOMapping=0
+
+[1803sub3]
+ParameterName=Inhibit Time
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0x0000
+PDOMapping=0
+
+[1803sub5]
+ParameterName=Event Timer
+ObjectType=0x7
+DataType=0x0006
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1a00]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=2
+
+[1a00sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=1
+PDOMapping=0
+
+[1a00sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x60000108
+PDOMapping=0
+
+[1a01]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1a01sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=4
+PDOMapping=0
+
+[1a01sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010110
+PDOMapping=0
+
+[1a01sub2]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010210
+PDOMapping=0
+
+[1a01sub3]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010310
+PDOMapping=0
+
+[1a01sub4]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010410
+PDOMapping=0
+
+[1a02]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=5
+
+[1a02sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=4
+PDOMapping=0
+
+[1a02sub1]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010510
+PDOMapping=0
+
+[1a02sub2]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010610
+PDOMapping=0
+
+[1a02sub3]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010710
+PDOMapping=0
+
+[1a02sub4]
+ParameterName=PDO Mapping Entry
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0x64010810
+PDOMapping=0
+
+[1a03]
+ParameterName=Transmit PDO Mapping Parameter
+ObjectType=0x9
+SubNumber=1
+
+[1a03sub0]
+ParameterName=Number of Entries
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[1f50]
+ParameterName=Download Program Data
+ObjectType=0x8
+SubNumber=2
+
+[1f50sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=3
+PDOMapping=0
+
+[1f50sub3]
+ParameterName=Download Program Data - HW Settings
+ObjectType=0x7
+DataType=0x000F
+AccessType=rw
+PDOMapping=0
+
+[6000]
+ParameterName=Read Digital Input 8-bit
+ObjectType=0x8
+SubNumber=2
+
+[6000sub0]
+ParameterName=Number of Elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6000sub1]
+ParameterName=DigInput8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+PDOMapping=1
+
+[6002]
+ParameterName=Polarity Digital Input
+ObjectType=0x8
+SubNumber=2
+
+[6002sub0]
+ParameterName=Number of Elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6002sub1]
+ParameterName=Polarity8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6200]
+ParameterName=Write Digital Output 8-bit
+ObjectType=0x8
+SubNumber=2
+
+[6200sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6200sub1]
+ParameterName=DigOutput8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rww
+PDOMapping=1
+
+[6202]
+ParameterName=Polarity Digital Output
+ObjectType=0x8
+SubNumber=2
+
+[6202sub0]
+ParameterName=Number of Elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6202sub1]
+ParameterName=Polarity8_1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6206]
+ParameterName=Error Mode Digital Output
+ObjectType=0x8
+SubNumber=2
+
+[6206sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6206sub1]
+ParameterName=Error Mode 1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6207]
+ParameterName=Error Value Digital Output
+ObjectType=0x8
+SubNumber=2
+
+[6207sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=1
+PDOMapping=0
+
+[6207sub1]
+ParameterName=Error Value 1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6401]
+ParameterName=Read Analog Input 16-bit
+ObjectType=0x8
+SubNumber=9
+
+[6401sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=8
+PDOMapping=0
+
+[6401sub1]
+ParameterName=AnalogInput16_1
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub2]
+ParameterName=AnalogInput16_2
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub3]
+ParameterName=AnalogInput16_3
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub4]
+ParameterName=AnalogInput16_4
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub5]
+ParameterName=AnalogInput16_5
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub6]
+ParameterName=AnalogInput16_6
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub7]
+ParameterName=AnalogInput16_7
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6401sub8]
+ParameterName=AnalogInput16_8
+ObjectType=0x7
+DataType=0x0003
+AccessType=ro
+PDOMapping=1
+
+[6411]
+ParameterName=Write Analog Output 16-bit
+ObjectType=0x8
+SubNumber=5
+
+[6411sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=4
+PDOMapping=0
+
+[6411sub1]
+ParameterName=AnalogOutput16_1
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6411sub2]
+ParameterName=AnalogOutput16_2
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6411sub3]
+ParameterName=AnalogOutput16_3
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6411sub4]
+ParameterName=AnalogOutput16_4
+ObjectType=0x7
+DataType=0x0003
+AccessType=rww
+PDOMapping=1
+
+[6423]
+ParameterName=Analog Input Global Interrupt
+ObjectType=0x7
+DataType=0x0001
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426]
+ParameterName=Analog Input Interrupt Delta
+ObjectType=0x8
+SubNumber=9
+
+[6426sub0]
+ParameterName=NrOfObjects
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=8
+PDOMapping=0
+
+[6426sub1]
+ParameterName=Analog Input Delta 1
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub2]
+ParameterName=Analog Input Delta 2
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub3]
+ParameterName=Analog Input Delta 3
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub4]
+ParameterName=Analog Input Delta 4
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub5]
+ParameterName=Analog Input Delta 5
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub6]
+ParameterName=Analog Input Delta 6
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub7]
+ParameterName=Analog Input Delta 7
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6426sub8]
+ParameterName=Analog Input Delta 8
+ObjectType=0x7
+DataType=0x0007
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443]
+ParameterName=Error Mode Analog Output
+ObjectType=0x8
+SubNumber=5
+
+[6443sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=4
+PDOMapping=0
+
+[6443sub1]
+ParameterName=Error Mode 1
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443sub2]
+ParameterName=Error Mode 2
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443sub3]
+ParameterName=Error Mode 3
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6443sub4]
+ParameterName=Error Mode 4
+ObjectType=0x7
+DataType=0x0005
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444]
+ParameterName=Error Value Analog Output
+ObjectType=0x8
+SubNumber=5
+
+[6444sub0]
+ParameterName=Number of elements
+ObjectType=0x7
+DataType=0x0005
+AccessType=ro
+DefaultValue=4
+PDOMapping=0
+
+[6444sub1]
+ParameterName=Error Value 1
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444sub2]
+ParameterName=Error Value 2
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444sub3]
+ParameterName=Error Value 3
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[6444sub4]
+ParameterName=Error Value 4
+ObjectType=0x7
+DataType=0x0004
+AccessType=rw
+DefaultValue=0
+PDOMapping=0
+
+[ManufacturerObjects]
+SupportedObjects=0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/master.od	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,314 @@
+<?xml version="1.0"?>
+<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
+<PyObject module="node" class="Node" id="148584620">
+<attr name="Profile" type="dict" id="148589396" >
+</attr>
+<attr name="Description" type="string" value="" />
+<attr name="Dictionary" type="dict" id="148592132" >
+  <entry>
+    <key type="numeric" value="4096" />
+    <val type="numeric" value="302" />
+  </entry>
+  <entry>
+    <key type="numeric" value="4097" />
+    <val type="numeric" value="0" />
+  </entry>
+  <entry>
+    <key type="numeric" value="6144" />
+    <val type="list" id="148585004" >
+      <item type="string" value="{True:&quot;$NODEID+0x%X80&quot;%(base+1),False:0x80000000}[base&lt;4]" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="5120" />
+    <val type="list" id="148586060" >
+      <item type="numeric" value="448" />
+      <item type="numeric" value="1" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4101" />
+    <val type="numeric" value="1073741952" />
+  </entry>
+  <entry>
+    <key type="numeric" value="4102" />
+    <val type="numeric" value="50000" />
+  </entry>
+  <entry>
+    <key type="numeric" value="8192" />
+    <val type="numeric" value="0" />
+  </entry>
+  <entry>
+    <key type="numeric" value="6656" />
+    <val type="list" id="148585228" >
+      <item type="numeric" value="268501000" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="5632" />
+    <val type="list" id="148585036" >
+      <item type="numeric" value="536870920" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4120" />
+    <val type="list" id="148585292" >
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4118" />
+    <val type="list" id="148585100" >
+      <item type="numeric" value="4195804" />
+    </val>
+  </entry>
+</attr>
+<attr name="SpecificMenu" type="list" id="148584044" >
+</attr>
+<attr name="ParamsDictionary" type="dict" id="148592268" >
+</attr>
+<attr name="UserMapping" type="dict" id="148592404" >
+  <entry>
+    <key type="numeric" value="8192" />
+    <val type="dict" id="148592540" >
+      <entry>
+        <key type="string" value="need" />
+        <val type="False" value="" />
+      </entry>
+      <entry>
+        <key type="string" value="values" />
+        <val type="list" id="148585868" >
+          <item type="dict" id="148592676" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="rw" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="True" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="5" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string">Read Inputs</val>
+            </entry>
+          </item>
+        </val>
+      </entry>
+      <entry>
+        <key type="string" value="name" />
+        <val type="string">Read Inputs</val>
+      </entry>
+      <entry>
+        <key type="string" value="struct" />
+        <val type="numeric" value="1" />
+      </entry>
+    </val>
+  </entry>
+</attr>
+<attr name="DS302" type="dict" id="148592812" >
+  <entry>
+    <key type="numeric" value="7968" />
+    <val type="dict" id="148592948" >
+      <entry>
+        <key type="string" value="need" />
+        <val type="False" value="" />
+      </entry>
+      <entry>
+        <key type="string" value="values" />
+        <val type="list" id="148584684" >
+          <item type="dict" id="148593084" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="ro" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="False" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="5" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string" value="Number of Entries" />
+            </entry>
+          </item>
+          <item type="dict" id="148593220" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="rw" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="False" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="15" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string" value="Store DCF for node %d[(sub)]" />
+            </entry>
+            <entry>
+              <key type="string" value="nbmax" />
+              <val type="numeric" value="127" />
+            </entry>
+          </item>
+        </val>
+      </entry>
+      <entry>
+        <key type="string" value="name" />
+        <val type="string" value="Store DCF" />
+      </entry>
+      <entry>
+        <key type="string" value="struct" />
+        <val type="numeric" value="7" />
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="7969" />
+    <val type="dict" id="148593356" >
+      <entry>
+        <key type="string" value="need" />
+        <val type="False" value="" />
+      </entry>
+      <entry>
+        <key type="string" value="values" />
+        <val type="list" id="148585516" >
+          <item type="dict" id="148593492" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="ro" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="False" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="5" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string" value="Number of Entries" />
+            </entry>
+          </item>
+          <item type="dict" id="148593628" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="rw" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="False" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="2" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string" value="Storage Format for Node %d[(sub)]" />
+            </entry>
+            <entry>
+              <key type="string" value="nbmax" />
+              <val type="numeric" value="127" />
+            </entry>
+          </item>
+        </val>
+      </entry>
+      <entry>
+        <key type="string" value="name" />
+        <val type="string" value="Storage Format" />
+      </entry>
+      <entry>
+        <key type="string" value="struct" />
+        <val type="numeric" value="7" />
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="7970" />
+    <val type="dict" id="148593764" >
+      <entry>
+        <key type="string" value="need" />
+        <val type="False" value="" />
+      </entry>
+      <entry>
+        <key type="string" value="values" />
+        <val type="list" id="148594956" >
+          <item type="dict" id="148593900" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="ro" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="False" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="5" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string" value="Number of Entries" />
+            </entry>
+          </item>
+          <item type="dict" id="148594036" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="rw" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="False" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="15" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string" value="Concise DCF for Node %d[(sub)]" />
+            </entry>
+            <entry>
+              <key type="string" value="nbmax" />
+              <val type="numeric" value="127" />
+            </entry>
+          </item>
+        </val>
+      </entry>
+      <entry>
+        <key type="string" value="name" />
+        <val type="string" value="Concise DCF" />
+      </entry>
+      <entry>
+        <key type="string" value="struct" />
+        <val type="numeric" value="7" />
+      </entry>
+    </val>
+  </entry>
+</attr>
+<attr name="ProfileName" type="string" value="None" />
+<attr name="Type" type="string">master</attr>
+<attr name="ID" type="numeric" value="0" />
+<attr name="Name" type="string">TestMaster</attr>
+</PyObject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/nodelist.cpj	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,7 @@
+[TOPOLOGY]
+NetName=None
+Nodes=0x01
+Node64Present=0x01
+Node64Name=micromod
+Node64DCFName=PEAK MicroMod.eds
+EDSBaseName=eds
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/canfestival/test_config/result.txt	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,257 @@
+1000 (Device Type): 12E
+1001 (Error Register): 0
+1005 (SYNC COB ID): 40000080
+1006 (Communication / Cycle Period): C350
+1016 (Consumer Heartbeat Time):
+1016 01 (Consumer Heartbeat Time): 4005DC
+1018 (Identity):
+1018 01 (Vendor ID): 0
+1018 02 (Product Code): 0
+1018 03 (Revision Number): 0
+1018 04 (Serial Number): 0
+1280 (Client SDO 1 Parameter):
+1280 01 (COB ID Client to Server (Transmit SDO)): 640
+1280 02 (COB ID Server to Client (Receive SDO)): 5C0
+1280 03 (Node ID of the SDO Server): 40
+1400 (Receive PDO 1 Parameter):
+1400 01 (COB ID used by PDO): 1C0
+1400 02 (Transmission Type): 1
+1400 03 (Inhibit Time): 0
+1400 04 (Compatibility Entry): 0
+1400 05 (Event Timer): 0
+1401 (Receive PDO 2 Parameter):
+1401 01 (COB ID used by PDO): 2C0
+1401 02 (Transmission Type): 1
+1401 03 (Inhibit Time): 0
+1401 04 (Compatibility Entry): 0
+1401 05 (Event Timer): 0
+1402 (Receive PDO 3 Parameter):
+1402 01 (COB ID used by PDO): 182
+1402 02 (Transmission Type): 1
+1402 03 (Inhibit Time): 0
+1402 04 (Compatibility Entry): 0
+1402 05 (Event Timer): 0
+1403 (Receive PDO 4 Parameter):
+1403 01 (COB ID used by PDO): 183
+1403 02 (Transmission Type): 1
+1403 03 (Inhibit Time): 0
+1403 04 (Compatibility Entry): 0
+1403 05 (Event Timer): 0
+1404 (Receive PDO 5 Parameter):
+1404 01 (COB ID used by PDO): 181
+1404 02 (Transmission Type): 1
+1404 03 (Inhibit Time): 0
+1404 04 (Compatibility Entry): 0
+1404 05 (Event Timer): 0
+1600 (Receive PDO 1 Mapping):
+1600 01 (PDO 1 Mapping for an application object 1): 22400108
+1600 02 (PDO 1 Mapping for an application object 2): 0
+1601 (Receive PDO 2 Mapping):
+1601 01 (PDO 2 Mapping for an application object 1): 20000310
+1601 02 (PDO 2 Mapping for an application object 2): 23400110
+1601 03 (PDO 2 Mapping for an application object 3): 23400210
+1601 04 (PDO 2 Mapping for an application object 4): 20000310
+1602 (Receive PDO 3 Mapping):
+1602 01 (PDO 3 Mapping for an application object 1): 24400120
+1602 02 (PDO 3 Mapping for an application object 2): 24400220
+1603 (Receive PDO 4 Mapping):
+1603 01 (PDO 4 Mapping for an application object 1): 24400320
+1604 (Receive PDO 5 Mapping):
+1604 01 (PDO 5 Mapping for an application object 1): 22400208
+1604 02 (PDO 5 Mapping for an application object 2): 24400420
+1800 (Transmit PDO 1 Parameter):
+1800 01 (COB ID used by PDO): {True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4]
+1800 02 (Transmission Type): 0
+1800 03 (Inhibit Time): 0
+1800 04 (Compatibility Entry): 0
+1800 05 (Event Timer): 0
+1801 (Transmit PDO 2 Parameter):
+1801 01 (COB ID used by PDO): 340
+1801 02 (Transmission Type): 1
+1801 03 (Inhibit Time): 0
+1801 04 (Compatibility Entry): 0
+1801 05 (Event Timer): 0
+1A00 (Transmit PDO 1 Mapping):
+1A00 01 (PDO 1 Mapping for a process data variable 1): 10010008
+1A01 (Transmit PDO 2 Mapping):
+1A01 01 (PDO 2 Mapping for a process data variable 1): 43400110
+1A01 02 (PDO 2 Mapping for a process data variable 2): 20000310
+1A01 03 (PDO 2 Mapping for a process data variable 3): 20000310
+1A01 04 (PDO 2 Mapping for a process data variable 4): 20000310
+1F22 (Concise DCF):
+1F22 01 (Concise DCF for Node 1): 
+1F22 02 (Concise DCF for Node 2): 
+1F22 03 (Concise DCF for Node 3): 
+1F22 04 (Concise DCF for Node 4): 
+1F22 05 (Concise DCF for Node 5): 
+1F22 06 (Concise DCF for Node 6): 
+1F22 07 (Concise DCF for Node 7): 
+1F22 08 (Concise DCF for Node 8): 
+1F22 09 (Concise DCF for Node 9): 
+1F22 0A (Concise DCF for Node 10): 
+1F22 0B (Concise DCF for Node 11): 
+1F22 0C (Concise DCF for Node 12): 
+1F22 0D (Concise DCF for Node 13): 
+1F22 0E (Concise DCF for Node 14): 
+1F22 0F (Concise DCF for Node 15): 
+1F22 10 (Concise DCF for Node 16): 
+1F22 11 (Concise DCF for Node 17): 
+1F22 12 (Concise DCF for Node 18): 
+1F22 13 (Concise DCF for Node 19): 
+1F22 14 (Concise DCF for Node 20): 
+1F22 15 (Concise DCF for Node 21): 
+1F22 16 (Concise DCF for Node 22): 
+1F22 17 (Concise DCF for Node 23): 
+1F22 18 (Concise DCF for Node 24): 
+1F22 19 (Concise DCF for Node 25): 
+1F22 1A (Concise DCF for Node 26): 
+1F22 1B (Concise DCF for Node 27): 
+1F22 1C (Concise DCF for Node 28): 
+1F22 1D (Concise DCF for Node 29): 
+1F22 1E (Concise DCF for Node 30): 
+1F22 1F (Concise DCF for Node 31): 
+1F22 20 (Concise DCF for Node 32): 
+1F22 21 (Concise DCF for Node 33): 
+1F22 22 (Concise DCF for Node 34): 
+1F22 23 (Concise DCF for Node 35): 
+1F22 24 (Concise DCF for Node 36): 
+1F22 25 (Concise DCF for Node 37): 
+1F22 26 (Concise DCF for Node 38): 
+1F22 27 (Concise DCF for Node 39): 
+1F22 28 (Concise DCF for Node 40): 
+1F22 29 (Concise DCF for Node 41): 
+1F22 2A (Concise DCF for Node 42): 
+1F22 2B (Concise DCF for Node 43): 
+1F22 2C (Concise DCF for Node 44): 
+1F22 2D (Concise DCF for Node 45): 
+1F22 2E (Concise DCF for Node 46): 
+1F22 2F (Concise DCF for Node 47): 
+1F22 30 (Concise DCF for Node 48): 
+1F22 31 (Concise DCF for Node 49): 
+1F22 32 (Concise DCF for Node 50): 
+1F22 33 (Concise DCF for Node 51): 
+1F22 34 (Concise DCF for Node 52): 
+1F22 35 (Concise DCF for Node 53): 
+1F22 36 (Concise DCF for Node 54): 
+1F22 37 (Concise DCF for Node 55): 
+1F22 38 (Concise DCF for Node 56): 
+1F22 39 (Concise DCF for Node 57): 
+1F22 3A (Concise DCF for Node 58): 
+1F22 3B (Concise DCF for Node 59): 
+1F22 3C (Concise DCF for Node 60): 
+1F22 3D (Concise DCF for Node 61): 
+1F22 3E (Concise DCF for Node 62): 
+1F22 3F (Concise DCF for Node 63): 
+1F22 40 (Concise DCF for Node 64): 23 arg defined
+1F22 40, arg 1: 1800 01 00000004 800001C0
+1F22 40, arg 2: 1800 02 00000001 01
+1F22 40, arg 3: 1800 01 00000004 000001C0
+1F22 40, arg 4: 1801 01 00000004 800002C0
+1F22 40, arg 5: 1801 02 00000001 01
+1F22 40, arg 6: 1801 01 00000004 000002C0
+1F22 40, arg 7: 1401 01 00000004 80000340
+1F22 40, arg 8: 1401 02 00000001 01
+1F22 40, arg 9: 1401 01 00000004 00000340
+1F22 40, arg 10: 1804 01 00000004 80000181
+1F22 40, arg 11: 1804 02 00000001 01
+1F22 40, arg 12: 1804 01 00000004 00000181
+1F22 40, arg 13: 1A04 01 00000004 60020108
+1F22 40, arg 14: 1A04 02 00000004 64260120
+1F22 40, arg 15: 1805 01 00000004 80000182
+1F22 40, arg 16: 1805 02 00000001 01
+1F22 40, arg 17: 1805 01 00000004 00000182
+1F22 40, arg 18: 1A05 01 00000004 64260220
+1F22 40, arg 19: 1A05 02 00000004 64260320
+1F22 40, arg 20: 1806 01 00000004 80000183
+1F22 40, arg 21: 1806 02 00000001 01
+1F22 40, arg 22: 1806 01 00000004 00000183
+1F22 40, arg 23: 1A06 01 00000004 64260420
+1F22 41 (Concise DCF for Node 65): 
+1F22 42 (Concise DCF for Node 66): 
+1F22 43 (Concise DCF for Node 67): 
+1F22 44 (Concise DCF for Node 68): 
+1F22 45 (Concise DCF for Node 69): 
+1F22 46 (Concise DCF for Node 70): 
+1F22 47 (Concise DCF for Node 71): 
+1F22 48 (Concise DCF for Node 72): 
+1F22 49 (Concise DCF for Node 73): 
+1F22 4A (Concise DCF for Node 74): 
+1F22 4B (Concise DCF for Node 75): 
+1F22 4C (Concise DCF for Node 76): 
+1F22 4D (Concise DCF for Node 77): 
+1F22 4E (Concise DCF for Node 78): 
+1F22 4F (Concise DCF for Node 79): 
+1F22 50 (Concise DCF for Node 80): 
+1F22 51 (Concise DCF for Node 81): 
+1F22 52 (Concise DCF for Node 82): 
+1F22 53 (Concise DCF for Node 83): 
+1F22 54 (Concise DCF for Node 84): 
+1F22 55 (Concise DCF for Node 85): 
+1F22 56 (Concise DCF for Node 86): 
+1F22 57 (Concise DCF for Node 87): 
+1F22 58 (Concise DCF for Node 88): 
+1F22 59 (Concise DCF for Node 89): 
+1F22 5A (Concise DCF for Node 90): 
+1F22 5B (Concise DCF for Node 91): 
+1F22 5C (Concise DCF for Node 92): 
+1F22 5D (Concise DCF for Node 93): 
+1F22 5E (Concise DCF for Node 94): 
+1F22 5F (Concise DCF for Node 95): 
+1F22 60 (Concise DCF for Node 96): 
+1F22 61 (Concise DCF for Node 97): 
+1F22 62 (Concise DCF for Node 98): 
+1F22 63 (Concise DCF for Node 99): 
+1F22 64 (Concise DCF for Node 100): 
+1F22 65 (Concise DCF for Node 101): 
+1F22 66 (Concise DCF for Node 102): 
+1F22 67 (Concise DCF for Node 103): 
+1F22 68 (Concise DCF for Node 104): 
+1F22 69 (Concise DCF for Node 105): 
+1F22 6A (Concise DCF for Node 106): 
+1F22 6B (Concise DCF for Node 107): 
+1F22 6C (Concise DCF for Node 108): 
+1F22 6D (Concise DCF for Node 109): 
+1F22 6E (Concise DCF for Node 110): 
+1F22 6F (Concise DCF for Node 111): 
+1F22 70 (Concise DCF for Node 112): 
+1F22 71 (Concise DCF for Node 113): 
+1F22 72 (Concise DCF for Node 114): 
+1F22 73 (Concise DCF for Node 115): 
+1F22 74 (Concise DCF for Node 116): 
+1F22 75 (Concise DCF for Node 117): 
+1F22 76 (Concise DCF for Node 118): 
+1F22 77 (Concise DCF for Node 119): 
+1F22 78 (Concise DCF for Node 120): 
+1F22 79 (Concise DCF for Node 121): 
+1F22 7A (Concise DCF for Node 122): 
+1F22 7B (Concise DCF for Node 123): 
+1F22 7C (Concise DCF for Node 124): 
+1F22 7D (Concise DCF for Node 125): 
+1F22 7E (Concise DCF for Node 126): 
+1F22 7F (Concise DCF for Node 127): 
+2000 (Read Inputs): 0
+2240 (beremiz__IB0_1_64):
+2240 01 (24576_1): 0
+2240 02 (24578_1): 0
+2340 (beremiz__IW0_1_64):
+2340 01 (25601_2): 0
+2340 02 (25601_3): 0
+2440 (beremiz__ID0_1_64):
+2440 01 (25638_2): 0
+2440 02 (25638_3): 0
+2440 03 (25638_4): 0
+2440 04 (25638_1): 0
+4340 (beremiz__QW0_1_64):
+4340 01 (25617_1): 0
+
+********POINTERS*********
+{(4096, 0): '__ID0_1_4096_0',
+ (8768, 1): '__IB0_1_64_24576_1',
+ (8768, 2): '__IB0_1_64_24578_1',
+ (9024, 1): '__IW0_1_64_25601_2',
+ (9024, 2): '__IW0_1_64_25601_3',
+ (9280, 1): '__ID0_1_64_25638_2',
+ (9280, 2): '__ID0_1_64_25638_3',
+ (9280, 3): '__ID0_1_64_25638_4',
+ (9280, 4): '__ID0_1_64_25638_1',
+ (17216, 1): '__QW0_1_64_25617_1'}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/PythonEditor.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,505 @@
+import  wx, wx.grid
+import  wx.stc  as  stc
+import keyword
+
+from controls import EditorPanel
+
+if wx.Platform == '__WXMSW__':
+    faces = { 'times': 'Times New Roman',
+              'mono' : 'Courier New',
+              'helv' : 'Arial',
+              'other': 'Comic Sans MS',
+              'size' : 10,
+              'size2': 8,
+             }
+elif wx.Platform == '__WXMAC__':
+    faces = { 'times': 'Times New Roman',
+              'mono' : 'Monaco',
+              'helv' : 'Arial',
+              'other': 'Comic Sans MS',
+              'size' : 12,
+              'size2': 10,
+             }
+else:
+    faces = { 'times': 'Times',
+              'mono' : 'Courier',
+              'helv' : 'Helvetica',
+              'other': 'new century schoolbook',
+              'size' : 12,
+              'size2': 10,
+             }
+
+[ID_PYTHONEDITOR,
+] = [wx.NewId() for _init_ctrls in range(1)]
+
+def GetCursorPos(old, new):
+    old_length = len(old)
+    new_length = len(new)
+    common_length = min(old_length, new_length)
+    i = 0
+    for i in xrange(common_length):
+        if old[i] != new[i]:
+            break
+    if old_length < new_length:
+        if common_length > 0 and old[i] != new[i]:
+            return i + new_length - old_length
+        else:
+            return i + new_length - old_length + 1
+    elif old_length > new_length or i < min(old_length, new_length) - 1:
+        if common_length > 0 and old[i] != new[i]:
+            return i
+        else:
+            return i + 1
+    else:
+        return None
+
+class PythonEditor(EditorPanel):
+
+    fold_symbols = 3
+    
+    def _init_Editor(self, prnt):
+        self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
+                 name="TextViewer", pos=wx.DefaultPosition, 
+                 size=wx.DefaultSize, style=0)
+
+        self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
+        self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
+
+        self.Editor.SetLexer(stc.STC_LEX_PYTHON)
+        self.Editor.SetKeyWords(0, " ".join(keyword.kwlist))
+
+        self.Editor.SetProperty("fold", "1")
+        self.Editor.SetProperty("tab.timmy.whinge.level", "1")
+        self.Editor.SetMargins(0,0)
+
+        self.Editor.SetViewWhiteSpace(False)
+        
+        self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
+        self.Editor.SetEdgeColumn(78)
+
+        # Set up the numbers in the margin for margin #1
+        self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
+        # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
+        self.Editor.SetMarginWidth(1, 40)
+
+        # Setup a margin to hold fold markers
+        self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
+        self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS)
+        self.Editor.SetMarginSensitive(2, True)
+        self.Editor.SetMarginWidth(2, 12)
+
+        if self.fold_symbols == 0:
+            # Arrow pointing right for contracted folders, arrow pointing down for expanded
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
+            
+        elif self.fold_symbols == 1:
+            # Plus for contracted folders, minus for expanded
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
+
+        elif self.fold_symbols == 2:
+            # Like a flattened tree control using circular headers and curved joins
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
+
+        elif self.fold_symbols == 3:
+            # Like a flattened tree control using square headers
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
+            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
+
+
+        self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+        self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
+        self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
+
+        # Global default style
+        if wx.Platform == '__WXMSW__':
+            self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New')
+        elif wx.Platform == '__WXMAC__':
+            # TODO: if this looks fine on Linux too, remove the Mac-specific case 
+            # and use this whenever OS != MSW.
+            self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco')
+        else:
+            defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize()
+            self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize)
+
+        # Clear styles and revert to default.
+        self.Editor.StyleClearAll()
+
+        # Following style specs only indicate differences from default.
+        # The rest remains unchanged.
+
+        # Line numbers in margin
+        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')    
+        # Highlighted brace
+        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
+        # Unmatched brace
+        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
+        # Indentation guide
+        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
+
+        # Python styles
+        self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
+        # Comments
+        self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE,  'fore:#008000,back:#F0FFF0')
+        self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
+        # Numbers
+        self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
+        # Strings and characters
+        self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
+        self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
+        # Keywords
+        self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
+        # Triple quotes
+        self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
+        self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
+        # Class names
+        self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
+        # Function names
+        self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
+        # Operators
+        self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
+        # Identifiers. I leave this as not bold because everything seems
+        # to be an identifier if it doesn't match the above criterae
+        self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
+
+        # Caret color
+        self.Editor.SetCaretForeground("BLUE")
+        # Selection background
+        self.Editor.SetSelBackground(1, '#66CCFF')
+
+        self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
+        self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
+        
+        # register some images for use in the AutoComplete box.
+        #self.RegisterImage(1, images.getSmilesBitmap())
+        self.Editor.RegisterImage(1, 
+            wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
+        self.Editor.RegisterImage(2, 
+            wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
+        self.Editor.RegisterImage(3, 
+            wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
+
+        # Indentation and tab stuff
+        self.Editor.SetIndent(4)               # Proscribed indent size for wx
+        self.Editor.SetIndentationGuides(True) # Show indent guides
+        self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
+        self.Editor.SetTabIndents(True)        # Tab key indents
+        self.Editor.SetTabWidth(4)             # Proscribed tab size for wx
+        self.Editor.SetUseTabs(False)          # Use spaces rather than tabs, or
+                                        # TabTimmy will complain!    
+        # White space
+        self.Editor.SetViewWhiteSpace(False)   # Don't view white space
+
+        # EOL: Since we are loading/saving ourselves, and the
+        # strings will always have \n's in them, set the STC to
+        # edit them that way.            
+        self.Editor.SetEOLMode(wx.stc.STC_EOL_LF)
+        self.Editor.SetViewEOL(False)
+        
+        # No right-edge mode indicator
+        self.Editor.SetEdgeMode(stc.STC_EDGE_NONE)
+        
+        self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
+
+        self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
+        self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+        self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR)
+
+
+    def __init__(self, parent, controler, window):
+        EditorPanel.__init__(self, parent, "", window, controler)
+        
+        self.DisableEvents = False
+        self.CurrentAction = None
+        
+        img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
+        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
+    
+    def __del__(self):
+        self.Controler.OnCloseEditor(self)
+    
+    def GetTitle(self):
+        fullname = self.Controler.PlugFullName()
+        if not self.Controler.PythonIsSaved():
+            return "~%s~" % fullname
+        return fullname
+    
+    def GetBufferState(self):
+        return self.Controler.GetBufferState()
+        
+    def Undo(self):
+        self.Controler.LoadPrevious()
+        self.RefreshView()
+            
+    def Redo(self):
+        self.Controler.LoadNext()
+        self.RefreshView()
+    
+    def HasNoModel(self):
+        return False
+    
+    def OnModification(self, event):
+        if not self.DisableEvents:
+            mod_type = event.GetModificationType()
+            if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
+                if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
+                    if self.CurrentAction is None:
+                        self.StartBuffering()
+                    elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
+                        self.Controler.EndBuffering()
+                        self.StartBuffering()
+                    self.CurrentAction = ("Add", event.GetPosition())
+                    wx.CallAfter(self.RefreshModel)
+                elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
+                    if self.CurrentAction == None:
+                        self.StartBuffering()
+                    elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
+                        self.Controler.EndBuffering()
+                        self.StartBuffering()
+                    self.CurrentAction = ("Delete", event.GetPosition())
+                    wx.CallAfter(self.RefreshModel)
+        event.Skip()
+    
+    def OnDoDrop(self, event):
+        self.ResetBuffer()
+        wx.CallAfter(self.RefreshModel)
+        event.Skip()
+
+    # Buffer the last model state
+    def RefreshBuffer(self):
+        self.Controler.BufferPython()
+        if self.ParentWindow is not None:
+            self.ParentWindow.RefreshTitle()
+            self.ParentWindow.RefreshFileMenu()
+            self.ParentWindow.RefreshEditMenu()
+            self.ParentWindow.RefreshPageTitles()
+    
+    def StartBuffering(self):
+        self.Controler.StartBuffering()
+        if self.ParentWindow is not None:
+            self.ParentWindow.RefreshTitle()
+            self.ParentWindow.RefreshFileMenu()
+            self.ParentWindow.RefreshEditMenu()
+            self.ParentWindow.RefreshPageTitles()
+    
+    def ResetBuffer(self):
+        if self.CurrentAction != None:
+            self.Controler.EndBuffering()
+            self.CurrentAction = None
+
+    def RefreshView(self):
+        self.ResetBuffer()
+        self.DisableEvents = True
+        old_cursor_pos = self.Editor.GetCurrentPos()
+        old_text = self.Editor.GetText()
+        new_text = self.Controler.GetPythonCode()
+        self.Editor.SetText(new_text)
+        new_cursor_pos = GetCursorPos(old_text, new_text)
+        if new_cursor_pos != None:
+            self.Editor.GotoPos(new_cursor_pos)
+        else:
+            self.Editor.GotoPos(old_cursor_pos)
+        self.Editor.ScrollToColumn(0)
+        self.Editor.EmptyUndoBuffer()
+        self.DisableEvents = False
+        
+        self.Editor.Colourise(0, -1)
+
+    def RefreshModel(self):
+        self.Controler.SetPythonCode(self.Editor.GetText())
+
+    def OnKeyPressed(self, event):
+        if self.Editor.CallTipActive():
+            self.Editor.CallTipCancel()
+        key = event.GetKeyCode()
+
+        if key == 32 and event.ControlDown():
+            pos = self.Editor.GetCurrentPos()
+
+            # Tips
+            if event.ShiftDown():
+                pass
+##                self.CallTipSetBackground("yellow")
+##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
+##                                 'show some suff, maybe parameters..\n\n'
+##                                 'fubar(param1, param2)')
+            # Code completion
+            else:
+                self.Editor.AutoCompSetIgnoreCase(False)  # so this needs to match
+
+                # Images are specified with a appended "?type"
+                self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
+        else:
+            event.Skip()
+
+    def OnKillFocus(self, event):
+        self.Editor.AutoCompCancel()
+        event.Skip()
+
+    def OnUpdateUI(self, evt):
+        # check for matching braces
+        braceAtCaret = -1
+        braceOpposite = -1
+        charBefore = None
+        caretPos = self.Editor.GetCurrentPos()
+
+        if caretPos > 0:
+            charBefore = self.Editor.GetCharAt(caretPos - 1)
+            styleBefore = self.Editor.GetStyleAt(caretPos - 1)
+
+        # check before
+        if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
+            braceAtCaret = caretPos - 1
+
+        # check after
+        if braceAtCaret < 0:
+            charAfter = self.Editor.GetCharAt(caretPos)
+            styleAfter = self.Editor.GetStyleAt(caretPos)
+
+            if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
+                braceAtCaret = caretPos
+
+        if braceAtCaret >= 0:
+            braceOpposite = self.Editor.BraceMatch(braceAtCaret)
+
+        if braceAtCaret != -1  and braceOpposite == -1:
+            self.Editor.BraceBadLight(braceAtCaret)
+        else:
+            self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
+            #pt = self.Editor.PointFromPosition(braceOpposite)
+            #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
+            #print pt
+            #self.Editor.Refresh(False)
+
+
+    def OnMarginClick(self, evt):
+        # fold and unfold as needed
+        if evt.GetMargin() == 2:
+            if evt.GetShift() and evt.GetControl():
+                self.FoldAll()
+            else:
+                lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
+
+                if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
+                    if evt.GetShift():
+                        self.Editor.SetFoldExpanded(lineClicked, True)
+                        self.Expand(lineClicked, True, True, 1)
+                    elif evt.GetControl():
+                        if self.Editor.GetFoldExpanded(lineClicked):
+                            self.Editor.SetFoldExpanded(lineClicked, False)
+                            self.Expand(lineClicked, False, True, 0)
+                        else:
+                            self.Editor.SetFoldExpanded(lineClicked, True)
+                            self.Expand(lineClicked, True, True, 100)
+                    else:
+                        self.Editor.ToggleFold(lineClicked)
+
+
+    def FoldAll(self):
+        lineCount = self.Editor.GetLineCount()
+        expanding = True
+
+        # find out if we are folding or unfolding
+        for lineNum in range(lineCount):
+            if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
+                expanding = not self.Editor.GetFoldExpanded(lineNum)
+                break
+
+        lineNum = 0
+
+        while lineNum < lineCount:
+            level = self.Editor.GetFoldLevel(lineNum)
+            if level & stc.STC_FOLDLEVELHEADERFLAG and \
+               (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+
+                if expanding:
+                    self.Editor.SetFoldExpanded(lineNum, True)
+                    lineNum = self.Expand(lineNum, True)
+                    lineNum = lineNum - 1
+                else:
+                    lastChild = self.Editor.GetLastChild(lineNum, -1)
+                    self.Editor.SetFoldExpanded(lineNum, False)
+
+                    if lastChild > lineNum:
+                        self.Editor.HideLines(lineNum+1, lastChild)
+
+            lineNum = lineNum + 1
+
+
+
+    def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
+        lastChild = self.Editor.GetLastChild(line, level)
+        line = line + 1
+
+        while line <= lastChild:
+            if force:
+                if visLevels > 0:
+                    self.Editor.ShowLines(line, line)
+                else:
+                    self.Editor.HideLines(line, line)
+            else:
+                if doExpand:
+                    self.Editor.ShowLines(line, line)
+
+            if level == -1:
+                level = self.Editor.GetFoldLevel(line)
+
+            if level & stc.STC_FOLDLEVELHEADERFLAG:
+                if force:
+                    if visLevels > 1:
+                        self.Editor.SetFoldExpanded(line, True)
+                    else:
+                        self.Editor.SetFoldExpanded(line, False)
+
+                    line = self.Expand(line, doExpand, force, visLevels-1)
+
+                else:
+                    if doExpand and self.Editor.GetFoldExpanded(line):
+                        line = self.Expand(line, True, force, visLevels-1)
+                    else:
+                        line = self.Expand(line, False, force, visLevels-1)
+            else:
+                line = line + 1
+
+        return line
+
+    def Cut(self):
+        self.ResetBuffer()
+        self.DisableEvents = True
+        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
+        self.DisableEvents = False
+        self.RefreshModel()
+        self.RefreshBuffer()
+    
+    def Copy(self):
+        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
+    
+    def Paste(self):
+        self.ResetBuffer()
+        self.DisableEvents = True
+        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
+        self.DisableEvents = False
+        self.RefreshModel()
+        self.RefreshBuffer()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/README	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+Asynchronous Python Interpreter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from python import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,13 @@
+from os import listdir, path
+
+_base_path = path.split(__file__)[0]
+
+__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
+
+helps = []
+for name in __all__:
+    helpfilename = path.join(_base_path, name, "README")
+    if path.isfile(helpfilename):
+        helps.append(open(helpfilename).readline().strip())
+    else:
+        helps.append(name)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/README	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+SVGUI HMI
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from svgui import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/livesvg.js	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,59 @@
+// import Nevow.Athena
+// import Divmod.Base
+
+function updateAttr(id, param, value) {
+  Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value);
+}
+
+var svguiWidgets = new Array();
+
+var currentObject = null;
+function setCurrentObject(obj) {
+	currentObject = obj;
+}
+function isCurrentObject(obj) {
+	return currentObject == obj;
+}
+
+function getSVGElementById(id) {
+	return document.getElementById(id);
+}
+
+function blockSVGElementDrag(element) {
+	element.addEventListener("draggesture", function(event){event.stopPropagation()}, true);
+}
+
+LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget');
+LiveSVGPage.LiveSVGWidget.methods(
+
+    function handleEvent(self, evt) {
+        if (currentObject != null) {
+            currentObject.handleEvent(evt);
+        }
+    },
+
+    function receiveData(self, data){
+        dataReceived = json_parse(data);
+        gadget = svguiWidgets[dataReceived.id]
+        if (gadget) {
+        	gadget.updateValues(json_parse(dataReceived.kwargs));
+        }
+        //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState);
+    },
+    
+    function init(self, arg1){
+        //console.log("Object received : " + arg1);
+        for (ind in arg1) {
+            gad = json_parse(arg1[ind]);
+            args = json_parse(gad.kwargs);
+            gadget = new svguilib[gad.__class__](self, gad.id, args);
+            svguiWidgets[gadget.id]=gadget;
+            //console.log('GADGET :' + gadget);
+        }
+        var elements = document.getElementsByTagName("svg");
+        for (var i = 0; i < elements.length; i++) {
+        	elements[i].addEventListener("mouseup", self, false);
+        }
+        //console.log("SVGUIWIDGETS : " + svguiWidgets);
+    }
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pous.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1428 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://www.plcopen.org/xml/tc6.xsd"
+         xmlns:xhtml="http://www.w3.org/1999/xhtml"
+         xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
+  <fileHeader companyName="Beremiz"
+              productName="Beremiz"
+              productVersion="0.0"
+              creationDateTime="2008-12-14T16:53:26"/>
+  <contentHeader name="Beremiz non-standard POUs library"
+                 modificationDateTime="2009-08-12T15:35:33">
+    <coordinateInfo>
+      <fbd>
+        <scaling x="0" y="0"/>
+      </fbd>
+      <ld>
+        <scaling x="0" y="0"/>
+      </ld>
+      <sfc>
+        <scaling x="0" y="0"/>
+      </sfc>
+    </coordinateInfo>
+  </contentHeader>
+  <types>
+    <dataTypes/>
+    <pous>
+      <pou name="GetBoolString" pouType="functionBlock">
+        <interface>
+          <inputVars>
+            <variable name="VALUE">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </inputVars>
+          <outputVars>
+            <variable name="CODE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </outputVars>
+        </interface>
+        <body>
+          <ST>
+<![CDATA[IF VALUE THEN
+  CODE := 'True';
+ELSE
+  CODE := 'False';
+END_IF;]]>
+          </ST>
+        </body>
+      </pou>
+      <pou name="TextCtrl" pouType="functionBlock">
+        <interface>
+          <localVars>
+            <variable name="ID">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </localVars>
+          <inputVars>
+            <variable name="back_id">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="set_text">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="text">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </inputVars>
+          <localVars>
+            <variable name="SVGUI_TEXTCTRL">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="setstate_Command">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <FBD>
+            <block localId="1" width="193" height="160" typeName="CONCAT">
+              <position x="626" y="122"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="43"/>
+                    <connection refLocalId="2">
+                      <position x="626" y="165"/>
+                      <position x="535" y="165"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="89"/>
+                    <connection refLocalId="3">
+                      <position x="626" y="211"/>
+                      <position x="535" y="211"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN3">
+                  <connectionPointIn>
+                    <relPosition x="0" y="135"/>
+                    <connection refLocalId="6">
+                      <position x="626" y="257"/>
+                      <position x="532" y="257"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="193" y="43"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="2" height="30" width="460">
+              <position x="75" y="150"/>
+              <connectionPointOut>
+                <relPosition x="460" y="15"/>
+              </connectionPointOut>
+              <expression>'createSVGUIControl("textControl", back_id="'</expression>
+            </inVariable>
+            <inVariable localId="3" height="35" width="85">
+              <position x="450" y="196"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>back_id</expression>
+            </inVariable>
+            <inVariable localId="6" height="30" width="50">
+              <position x="482" y="242"/>
+              <connectionPointOut>
+                <relPosition x="50" y="15"/>
+              </connectionPointOut>
+              <expression>'")'</expression>
+            </inVariable>
+            <block localId="7" width="125" height="115" typeName="python_eval" instanceName="SVGUI_TEXTCTRL">
+              <position x="909" y="75"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="45"/>
+                    <connection refLocalId="9">
+                      <position x="909" y="120"/>
+                      <position x="886" y="120"/>
+                      <position x="886" y="85"/>
+                      <position x="869" y="85"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="90"/>
+                    <connection refLocalId="1" formalParameter="OUT">
+                      <position x="909" y="165"/>
+                      <position x="819" y="165"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="45"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="90"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="9" height="30" width="70">
+              <position x="799" y="70"/>
+              <connectionPointOut>
+                <relPosition x="70" y="15"/>
+              </connectionPointOut>
+              <expression>BOOL#1</expression>
+            </inVariable>
+            <outVariable localId="10" height="30" width="30">
+              <position x="1094" y="150"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="7" formalParameter="RESULT">
+                  <position x="1094" y="165"/>
+                  <position x="1034" y="165"/>
+                </connection>
+              </connectionPointIn>
+              <expression>ID</expression>
+            </outVariable>
+            <connector name="CREATED" localId="11" height="30" width="110">
+              <position x="1096" y="105"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="7" formalParameter="ACK">
+                  <position x="1096" y="120"/>
+                  <position x="1034" y="120"/>
+                </connection>
+              </connectionPointIn>
+            </connector>
+            <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
+              <position x="957" y="472"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="31" formalParameter="OUT">
+                      <position x="957" y="522"/>
+                      <position x="909" y="522"/>
+                      <position x="909" y="444"/>
+                      <position x="857" y="444"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="12" formalParameter="OUT">
+                      <position x="957" y="582"/>
+                      <position x="822" y="582"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="50"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="110"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <continuation name="CREATED" localId="5" height="30" width="110">
+              <position x="589" y="429"/>
+              <connectionPointOut>
+                <relPosition x="110" y="15"/>
+              </connectionPointOut>
+            </continuation>
+            <block localId="12" width="186" height="288" typeName="CONCAT">
+              <position x="636" y="536"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="46"/>
+                    <connection refLocalId="14">
+                      <position x="636" y="582"/>
+                      <position x="526" y="582"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="99"/>
+                    <connection refLocalId="8">
+                      <position x="636" y="635"/>
+                      <position x="526" y="635"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN3">
+                  <connectionPointIn>
+                    <relPosition x="0" y="152"/>
+                    <connection refLocalId="15">
+                      <position x="636" y="688"/>
+                      <position x="527" y="688"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN4">
+                  <connectionPointIn>
+                    <relPosition x="0" y="205"/>
+                    <connection refLocalId="32">
+                      <position x="636" y="741"/>
+                      <position x="528" y="741"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN5">
+                  <connectionPointIn>
+                    <relPosition x="0" y="258"/>
+                    <connection refLocalId="16">
+                      <position x="636" y="794"/>
+                      <position x="528" y="794"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="186" y="46"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="8" height="30" width="53">
+              <position x="473" y="620"/>
+              <connectionPointOut>
+                <relPosition x="53" y="15"/>
+              </connectionPointOut>
+              <expression>ID</expression>
+            </inVariable>
+            <inVariable localId="13" height="35" width="100">
+              <position x="599" y="469"/>
+              <connectionPointOut>
+                <relPosition x="100" y="17"/>
+              </connectionPointOut>
+              <expression>set_text</expression>
+            </inVariable>
+            <inVariable localId="14" height="30" width="120">
+              <position x="406" y="567"/>
+              <connectionPointOut>
+                <relPosition x="120" y="15"/>
+              </connectionPointOut>
+              <expression>'setAttr('</expression>
+            </inVariable>
+            <inVariable localId="15" height="30" width="122">
+              <position x="405" y="673"/>
+              <connectionPointOut>
+                <relPosition x="122" y="15"/>
+              </connectionPointOut>
+              <expression>',"text","'</expression>
+            </inVariable>
+            <inVariable localId="16" height="30" width="50">
+              <position x="478" y="779"/>
+              <connectionPointOut>
+                <relPosition x="50" y="15"/>
+              </connectionPointOut>
+              <expression>'")'</expression>
+            </inVariable>
+            <block localId="31" width="75" height="105" typeName="AND">
+              <position x="782" y="403"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="41"/>
+                    <connection refLocalId="5">
+                      <position x="782" y="444"/>
+                      <position x="699" y="444"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="83"/>
+                    <connection refLocalId="13">
+                      <position x="782" y="486"/>
+                      <position x="699" y="486"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="75" y="41"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="32" height="30" width="90">
+              <position x="438" y="726"/>
+              <connectionPointOut>
+                <relPosition x="90" y="15"/>
+              </connectionPointOut>
+              <expression>text</expression>
+            </inVariable>
+          </FBD>
+        </body>
+      </pou>
+      <pou name="Button" pouType="functionBlock">
+        <interface>
+          <localVars>
+            <variable name="ID">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </localVars>
+          <inputVars>
+            <variable name="back_id">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="sele_id">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="toggle">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="set_state">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="state_in">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </inputVars>
+          <outputVars>
+            <variable name="state_out">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </outputVars>
+          <localVars>
+            <variable name="init_Command">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="GetButtonState">
+              <type>
+                <derived name="GetBoolString"/>
+              </type>
+            </variable>
+            <variable name="setstate_Command">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="getstate_Command">
+              <type>
+                <derived name="python_poll"/>
+              </type>
+            </variable>
+            <variable name="GetButtonToggle">
+              <type>
+                <derived name="GetBoolString"/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <FBD>
+            <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
+              <position x="838" y="32"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="10">
+                      <position x="838" y="82"/>
+                      <position x="781" y="82"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="2" formalParameter="OUT">
+                      <position x="838" y="142"/>
+                      <position x="641" y="142"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="50"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="110"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <block localId="2" width="150" height="442" typeName="CONCAT">
+              <position x="491" y="92"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="3">
+                      <position x="491" y="142"/>
+                      <position x="433" y="142"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="11">
+                      <position x="491" y="202"/>
+                      <position x="431" y="202"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN3">
+                  <connectionPointIn>
+                    <relPosition x="0" y="170"/>
+                    <connection refLocalId="5">
+                      <position x="491" y="262"/>
+                      <position x="431" y="262"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN4">
+                  <connectionPointIn>
+                    <relPosition x="0" y="230"/>
+                    <connection refLocalId="12">
+                      <position x="491" y="322"/>
+                      <position x="430" y="322"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN5">
+                  <connectionPointIn>
+                    <relPosition x="0" y="290"/>
+                    <connection refLocalId="23">
+                      <position x="491" y="382"/>
+                      <position x="463" y="382"/>
+                      <position x="463" y="370"/>
+                      <position x="430" y="370"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN6">
+                  <connectionPointIn>
+                    <relPosition x="0" y="350"/>
+                    <connection refLocalId="24" formalParameter="CODE">
+                      <position x="491" y="442"/>
+                      <position x="429" y="442"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN7">
+                  <connectionPointIn>
+                    <relPosition x="0" y="410"/>
+                    <connection refLocalId="9">
+                      <position x="491" y="502"/>
+                      <position x="430" y="502"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="150" y="50"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="3" height="30" width="400">
+              <position x="33" y="127"/>
+              <connectionPointOut>
+                <relPosition x="400" y="15"/>
+              </connectionPointOut>
+              <expression>'createSVGUIControl("button",back_id="'</expression>
+            </inVariable>
+            <inVariable localId="5" height="30" width="140">
+              <position x="291" y="247"/>
+              <connectionPointOut>
+                <relPosition x="140" y="15"/>
+              </connectionPointOut>
+              <expression>'",sele_id="'</expression>
+            </inVariable>
+            <inVariable localId="9" height="30" width="180">
+              <position x="250" y="487"/>
+              <connectionPointOut>
+                <relPosition x="180" y="15"/>
+              </connectionPointOut>
+              <expression>',active=True)'</expression>
+            </inVariable>
+            <inVariable localId="10" height="30" width="70">
+              <position x="711" y="67"/>
+              <connectionPointOut>
+                <relPosition x="70" y="15"/>
+              </connectionPointOut>
+              <expression>BOOL#1</expression>
+            </inVariable>
+            <inVariable localId="11" height="35" width="85">
+              <position x="346" y="187"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>back_id</expression>
+            </inVariable>
+            <inVariable localId="12" height="35" width="85">
+              <position x="345" y="307"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>sele_id</expression>
+            </inVariable>
+            <inVariable localId="13" height="35" width="100">
+              <position x="452" y="639"/>
+              <connectionPointOut>
+                <relPosition x="100" y="15"/>
+              </connectionPointOut>
+              <expression>set_state</expression>
+            </inVariable>
+            <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonState">
+              <position x="239" y="897"/>
+              <inputVariables>
+                <variable formalParameter="VALUE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="32">
+                      <position x="239" y="927"/>
+                      <position x="181" y="927"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="CODE">
+                  <connectionPointOut>
+                    <relPosition x="140" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <outVariable localId="29" height="30" width="53">
+              <position x="1015" y="127"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="1" formalParameter="RESULT">
+                  <position x="1015" y="142"/>
+                  <position x="963" y="142"/>
+                </connection>
+              </connectionPointIn>
+              <expression>ID</expression>
+            </outVariable>
+            <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
+              <position x="810" y="640"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="31" formalParameter="OUT">
+                      <position x="810" y="690"/>
+                      <position x="762" y="690"/>
+                      <position x="762" y="612"/>
+                      <position x="710" y="612"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="7" formalParameter="OUT">
+                      <position x="810" y="750"/>
+                      <position x="643" y="750"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="50"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="110"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <connector name="CREATED" localId="30" height="30" width="110">
+              <position x="1014" y="67"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="1" formalParameter="ACK">
+                  <position x="1014" y="82"/>
+                  <position x="963" y="82"/>
+                </connection>
+              </connectionPointIn>
+            </connector>
+            <continuation name="CREATED" localId="6" height="30" width="110">
+              <position x="442" y="597"/>
+              <connectionPointOut>
+                <relPosition x="110" y="15"/>
+              </connectionPointOut>
+            </continuation>
+            <block localId="31" width="75" height="105" typeName="AND">
+              <position x="635" y="571"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="41"/>
+                    <connection refLocalId="6">
+                      <position x="635" y="612"/>
+                      <position x="552" y="612"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="83"/>
+                    <connection refLocalId="13">
+                      <position x="635" y="654"/>
+                      <position x="552" y="654"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="75" y="41"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="32" height="30" width="90">
+              <position x="91" y="912"/>
+              <connectionPointOut>
+                <relPosition x="90" y="15"/>
+              </connectionPointOut>
+              <expression>state_in</expression>
+            </inVariable>
+            <outVariable localId="33" height="30" width="100">
+              <position x="1334" y="1184"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="26" formalParameter="OUT">
+                  <position x="1334" y="1199"/>
+                  <position x="1286" y="1199"/>
+                </connection>
+              </connectionPointIn>
+              <expression>state_out</expression>
+            </outVariable>
+            <block localId="7" width="150" height="319" typeName="CONCAT">
+              <position x="493" y="701"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="49"/>
+                    <connection refLocalId="14">
+                      <position x="493" y="750"/>
+                      <position x="379" y="750"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="108"/>
+                    <connection refLocalId="8">
+                      <position x="493" y="809"/>
+                      <position x="435" y="809"/>
+                      <position x="435" y="803"/>
+                      <position x="379" y="803"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN3">
+                  <connectionPointIn>
+                    <relPosition x="0" y="167"/>
+                    <connection refLocalId="15">
+                      <position x="493" y="868"/>
+                      <position x="435" y="868"/>
+                      <position x="435" y="855"/>
+                      <position x="379" y="855"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN4">
+                  <connectionPointIn>
+                    <relPosition x="0" y="226"/>
+                    <connection refLocalId="28" formalParameter="CODE">
+                      <position x="493" y="927"/>
+                      <position x="379" y="927"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN5">
+                  <connectionPointIn>
+                    <relPosition x="0" y="285"/>
+                    <connection refLocalId="16">
+                      <position x="493" y="986"/>
+                      <position x="377" y="986"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="150" y="49"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="8" height="30" width="53">
+              <position x="326" y="788"/>
+              <connectionPointOut>
+                <relPosition x="53" y="15"/>
+              </connectionPointOut>
+              <expression>ID</expression>
+            </inVariable>
+            <inVariable localId="14" height="30" width="120">
+              <position x="259" y="735"/>
+              <connectionPointOut>
+                <relPosition x="120" y="15"/>
+              </connectionPointOut>
+              <expression>'setAttr('</expression>
+            </inVariable>
+            <inVariable localId="15" height="30" width="122">
+              <position x="257" y="840"/>
+              <connectionPointOut>
+                <relPosition x="122" y="15"/>
+              </connectionPointOut>
+              <expression>',"state",'</expression>
+            </inVariable>
+            <inVariable localId="16" height="30" width="41">
+              <position x="336" y="971"/>
+              <connectionPointOut>
+                <relPosition x="41" y="15"/>
+              </connectionPointOut>
+              <expression>')'</expression>
+            </inVariable>
+            <block localId="17" width="125" height="140" typeName="python_poll" instanceName="getstate_Command">
+              <position x="801" y="1089"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="18">
+                      <position x="801" y="1139"/>
+                      <position x="763" y="1139"/>
+                      <position x="763" y="1099"/>
+                      <position x="720" y="1099"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="22" formalParameter="OUT">
+                      <position x="801" y="1199"/>
+                      <position x="643" y="1199"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="50"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="110"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <block localId="25" width="145" height="45" typeName="STRING_TO_INT">
+              <position x="966" y="1169"/>
+              <inputVariables>
+                <variable formalParameter="IN">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="17" formalParameter="RESULT">
+                      <position x="966" y="1199"/>
+                      <position x="926" y="1199"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="145" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <block localId="26" width="125" height="45" typeName="INT_TO_BOOL">
+              <position x="1161" y="1169"/>
+              <inputVariables>
+                <variable formalParameter="IN">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="25" formalParameter="OUT">
+                      <position x="1161" y="1199"/>
+                      <position x="1111" y="1199"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <continuation name="CREATED" localId="18" height="30" width="110">
+              <position x="610" y="1084"/>
+              <connectionPointOut>
+                <relPosition x="110" y="15"/>
+              </connectionPointOut>
+            </continuation>
+            <inVariable localId="19" height="30" width="53">
+              <position x="383" y="1238"/>
+              <connectionPointOut>
+                <relPosition x="53" y="15"/>
+              </connectionPointOut>
+              <expression>ID</expression>
+            </inVariable>
+            <inVariable localId="20" height="30" width="150">
+              <position x="286" y="1184"/>
+              <connectionPointOut>
+                <relPosition x="150" y="15"/>
+              </connectionPointOut>
+              <expression>'int(getAttr('</expression>
+            </inVariable>
+            <inVariable localId="21" height="30" width="190">
+              <position x="246" y="1292"/>
+              <connectionPointOut>
+                <relPosition x="190" y="15"/>
+              </connectionPointOut>
+              <expression>',"state",False))'</expression>
+            </inVariable>
+            <block localId="22" width="150" height="183" typeName="CONCAT">
+              <position x="493" y="1152"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="47"/>
+                    <connection refLocalId="20">
+                      <position x="493" y="1199"/>
+                      <position x="436" y="1199"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="101"/>
+                    <connection refLocalId="19">
+                      <position x="493" y="1253"/>
+                      <position x="436" y="1253"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN3">
+                  <connectionPointIn>
+                    <relPosition x="0" y="155"/>
+                    <connection refLocalId="21">
+                      <position x="493" y="1307"/>
+                      <position x="483" y="1307"/>
+                      <position x="483" y="1307"/>
+                      <position x="436" y="1307"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="150" y="47"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="23" height="30" width="130">
+              <position x="300" y="355"/>
+              <connectionPointOut>
+                <relPosition x="130" y="15"/>
+              </connectionPointOut>
+              <expression>'",toggle='</expression>
+            </inVariable>
+            <block localId="24" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonToggle">
+              <position x="289" y="412"/>
+              <inputVariables>
+                <variable formalParameter="VALUE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="27">
+                      <position x="289" y="442"/>
+                      <position x="220" y="442"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="CODE">
+                  <connectionPointOut>
+                    <relPosition x="140" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="27" height="30" width="90">
+              <position x="130" y="427"/>
+              <connectionPointOut>
+                <relPosition x="90" y="15"/>
+              </connectionPointOut>
+              <expression>toggle</expression>
+            </inVariable>
+          </FBD>
+        </body>
+      </pou>
+      <pou name="Led" pouType="functionBlock">
+        <interface>
+          <localVars>
+            <variable name="ID">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </localVars>
+          <inputVars>
+            <variable name="back_id">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="sele_id">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="state_in">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </inputVars>
+          <localVars>
+            <variable name="init_Command">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="setstate_Command">
+              <type>
+                <derived name="python_poll"/>
+              </type>
+            </variable>
+            <variable name="GetLedState">
+              <type>
+                <derived name="GetBoolString"/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <FBD>
+            <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
+              <position x="810" y="30"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="10">
+                      <position x="810" y="80"/>
+                      <position x="753" y="80"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="2" formalParameter="OUT">
+                      <position x="810" y="140"/>
+                      <position x="640" y="140"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="50"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="110"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <block localId="2" width="150" height="322" typeName="CONCAT">
+              <position x="490" y="90"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="3">
+                      <position x="490" y="140"/>
+                      <position x="415" y="140"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="11">
+                      <position x="490" y="200"/>
+                      <position x="415" y="200"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN3">
+                  <connectionPointIn>
+                    <relPosition x="0" y="170"/>
+                    <connection refLocalId="5">
+                      <position x="490" y="260"/>
+                      <position x="415" y="260"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN4">
+                  <connectionPointIn>
+                    <relPosition x="0" y="230"/>
+                    <connection refLocalId="12">
+                      <position x="490" y="320"/>
+                      <position x="414" y="320"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN5">
+                  <connectionPointIn>
+                    <relPosition x="0" y="290"/>
+                    <connection refLocalId="9">
+                      <position x="490" y="380"/>
+                      <position x="414" y="380"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="150" y="50"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="3" height="30" width="400">
+              <position x="15" y="125"/>
+              <connectionPointOut>
+                <relPosition x="400" y="15"/>
+              </connectionPointOut>
+              <expression>'createSVGUIControl("button",back_id="'</expression>
+            </inVariable>
+            <block localId="4" width="125" height="140" typeName="python_poll" instanceName="setstate_Command">
+              <position x="782" y="536"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="6">
+                      <position x="782" y="586"/>
+                      <position x="653" y="586"/>
+                      <position x="653" y="552"/>
+                      <position x="602" y="552"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="110"/>
+                    <connection refLocalId="7" formalParameter="OUT">
+                      <position x="782" y="646"/>
+                      <position x="615" y="646"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="50"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="110"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="5" height="30" width="140">
+              <position x="275" y="245"/>
+              <connectionPointOut>
+                <relPosition x="140" y="15"/>
+              </connectionPointOut>
+              <expression>'",sele_id="'</expression>
+            </inVariable>
+            <continuation name="CREATED" localId="6" height="30" width="110">
+              <position x="492" y="537"/>
+              <connectionPointOut>
+                <relPosition x="110" y="15"/>
+              </connectionPointOut>
+            </continuation>
+            <block localId="7" width="150" height="319" typeName="CONCAT">
+              <position x="465" y="597"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="49"/>
+                    <connection refLocalId="14">
+                      <position x="465" y="646"/>
+                      <position x="351" y="646"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="108"/>
+                    <connection refLocalId="8">
+                      <position x="465" y="705"/>
+                      <position x="407" y="705"/>
+                      <position x="407" y="699"/>
+                      <position x="351" y="699"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN3">
+                  <connectionPointIn>
+                    <relPosition x="0" y="167"/>
+                    <connection refLocalId="15">
+                      <position x="465" y="764"/>
+                      <position x="407" y="764"/>
+                      <position x="407" y="751"/>
+                      <position x="351" y="751"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN4">
+                  <connectionPointIn>
+                    <relPosition x="0" y="226"/>
+                    <connection refLocalId="28" formalParameter="CODE">
+                      <position x="465" y="823"/>
+                      <position x="351" y="823"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN5">
+                  <connectionPointIn>
+                    <relPosition x="0" y="285"/>
+                    <connection refLocalId="16">
+                      <position x="465" y="882"/>
+                      <position x="407" y="882"/>
+                      <position x="407" y="883"/>
+                      <position x="351" y="883"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="150" y="49"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="8" height="30" width="53">
+              <position x="298" y="684"/>
+              <connectionPointOut>
+                <relPosition x="53" y="15"/>
+              </connectionPointOut>
+              <expression>ID</expression>
+            </inVariable>
+            <inVariable localId="9" height="30" width="300">
+              <position x="124" y="365"/>
+              <connectionPointOut>
+                <relPosition x="300" y="15"/>
+              </connectionPointOut>
+              <expression>'",toggle=True,active=False)'</expression>
+            </inVariable>
+            <inVariable localId="10" height="30" width="70">
+              <position x="683" y="65"/>
+              <connectionPointOut>
+                <relPosition x="70" y="15"/>
+              </connectionPointOut>
+              <expression>BOOL#1</expression>
+            </inVariable>
+            <inVariable localId="11" height="35" width="85">
+              <position x="330" y="185"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>back_id</expression>
+            </inVariable>
+            <inVariable localId="12" height="35" width="85">
+              <position x="329" y="305"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>sele_id</expression>
+            </inVariable>
+            <inVariable localId="14" height="30" width="120">
+              <position x="231" y="631"/>
+              <connectionPointOut>
+                <relPosition x="120" y="15"/>
+              </connectionPointOut>
+              <expression>'setAttr('</expression>
+            </inVariable>
+            <inVariable localId="15" height="30" width="122">
+              <position x="229" y="736"/>
+              <connectionPointOut>
+                <relPosition x="122" y="15"/>
+              </connectionPointOut>
+              <expression>',"state",'</expression>
+            </inVariable>
+            <inVariable localId="16" height="30" width="41">
+              <position x="310" y="868"/>
+              <connectionPointOut>
+                <relPosition x="41" y="15"/>
+              </connectionPointOut>
+              <expression>')'</expression>
+            </inVariable>
+            <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetLedState">
+              <position x="211" y="793"/>
+              <inputVariables>
+                <variable formalParameter="VALUE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="32">
+                      <position x="211" y="823"/>
+                      <position x="153" y="823"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="CODE">
+                  <connectionPointOut>
+                    <relPosition x="140" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <outVariable localId="29" height="30" width="53">
+              <position x="987" y="125"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="1" formalParameter="RESULT">
+                  <position x="987" y="140"/>
+                  <position x="935" y="140"/>
+                </connection>
+              </connectionPointIn>
+              <expression>ID</expression>
+            </outVariable>
+            <connector name="CREATED" localId="30" height="30" width="110">
+              <position x="986" y="65"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="1" formalParameter="ACK">
+                  <position x="986" y="80"/>
+                  <position x="935" y="80"/>
+                </connection>
+              </connectionPointIn>
+            </connector>
+            <inVariable localId="32" height="30" width="90">
+              <position x="63" y="808"/>
+              <connectionPointOut>
+                <relPosition x="90" y="15"/>
+              </connectionPointOut>
+              <expression>state_in</expression>
+            </inVariable>
+          </FBD>
+        </body>
+      </pou>
+    </pous>
+  </types>
+  <instances>
+    <configurations/>
+  </instances>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+from pyjs import *
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/build.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,724 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import shutil
+from copy import copy
+from os.path import join, dirname, basename, abspath, split, isfile, isdir
+from optparse import OptionParser
+import pyjs
+from cStringIO import StringIO
+try:
+    # Python 2.5 and above
+    from hashlib import md5
+except:
+    import md5
+import re
+
+usage = """
+  usage: %prog [options] <application module name or path>
+
+This is the command line builder for the pyjamas project, which can
+be used to build Ajax applications from Python.
+For more information, see the website at http://pyjs.org/
+"""
+
+# GWT1.2 Impl  | GWT1.2 Output         | Pyjamas 0.2 Platform | Pyjamas 0.2 Output
+# -------------+-----------------------+----------------------+----------------------
+# IE6          | ie6                   | IE6                  | ie6
+# Opera        | opera                 | Opera                | opera
+# Safari       | safari                | Safari               | safari
+# --           | gecko1_8              | Mozilla              | mozilla
+# --           | gecko                 | OldMoz               | oldmoz
+# Standard     | all                   | (default code)       | all
+# Mozilla      | gecko1_8, gecko       | --                   | --
+# Old          | safari, gecko, opera  | --                   | --
+
+version = "%prog pyjamas version 2006-08-19"
+
+# these names in lowercase need match the strings
+# returned by "provider$user.agent" in order to be selected corretly
+app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla']
+
+# usually defaults to e.g. /usr/share/pyjamas
+_data_dir = os.path.join(pyjs.prefix, "share/pyjamas")
+
+
+# .cache.html files produces look like this
+CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$')
+
+# ok these are the three "default" library directories, containing
+# the builtins (str, List, Dict, ord, round, len, range etc.)
+# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.)
+# and the contributed addons
+
+for p in ["library/builtins",
+          "library",
+          "addons"]:
+    p = os.path.join(_data_dir, p)
+    if os.path.isdir(p):
+        pyjs.path.append(p)
+
+
+def read_boilerplate(data_dir, filename):
+    return open(join(data_dir, "builder/boilerplate", filename)).read()
+
+def copy_boilerplate(data_dir, filename, output_dir):
+    filename = join(data_dir, "builder/boilerplate", filename)
+    shutil.copy(filename, output_dir)
+
+
+# taken and modified from python2.4
+def copytree_exists(src, dst, symlinks=False):
+    if not os.path.exists(src):
+        return
+
+    names = os.listdir(src)
+    try:
+        os.mkdir(dst)
+    except:
+        pass
+
+    errors = []
+    for name in names:
+        if name.startswith('CVS'):
+            continue
+        if name.startswith('.git'):
+            continue
+        if name.startswith('.svn'):
+            continue
+
+        srcname = os.path.join(src, name)
+        dstname = os.path.join(dst, name)
+        try:
+            if symlinks and os.path.islink(srcname):
+                linkto = os.readlink(srcname)
+                os.symlink(linkto, dstname)
+            elif isdir(srcname):
+                copytree_exists(srcname, dstname, symlinks)
+            else:
+                shutil.copy2(srcname, dstname)
+        except (IOError, os.error), why:
+            errors.append((srcname, dstname, why))
+    if errors:
+        print errors
+
+def check_html_file(source_file, dest_path):
+    """ Checks if a base HTML-file is available in the PyJamas
+        output directory.
+        If the HTML-file isn't available, it will be created.
+
+        If a CSS-file with the same name is available
+        in the output directory, a reference to this CSS-file
+        is included.
+
+        If no CSS-file is found, this function will look for a special
+        CSS-file in the output directory, with the name
+        "pyjamas_default.css", and if found it will be referenced
+        in the generated HTML-file.
+
+        [thank you to stef mientki for contributing this function]
+    """
+
+    base_html = """\
+<html>
+    <!-- auto-generated html - you should consider editing and
+         adapting this to suit your requirements
+     -->
+    <head>
+      <meta name="pygwt:module" content="%(modulename)s">
+      %(css)s
+      <title>%(title)s</title>
+    </head>
+    <body bgcolor="white">
+      <script language="javascript" src="pygwt.js"></script>
+    </body>
+</html>
+"""
+
+    filename = os.path.split    ( source_file )[1]
+    mod_name = os.path.splitext ( filename    )[0]
+    file_name = os.path.join     ( dest_path, mod_name + '.html' )
+
+    # if html file in output directory exists, leave it alone.
+    if os.path.exists ( file_name ):
+        return 0
+
+    if os.path.exists (
+        os.path.join ( dest_path, mod_name + '.css' ) ) :
+        css = "<link rel='stylesheet' href='" + mod_name + ".css'>"
+    elif os.path.exists (
+        os.path.join ( dest_path, 'pyjamas_default.css' ) ) :
+        css = "<link rel='stylesheet' href='pyjamas_default.css'>"
+
+    else:
+        css = ''
+
+    title = 'PyJamas Auto-Generated HTML file ' + mod_name
+
+    base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css}
+
+    fh = open (file_name, 'w')
+    fh.write  (base_html)
+    fh.close  ()
+
+    return 1
+
+
+def build(app_name, output, js_includes=(), debug=False, dynamic=0,
+          data_dir=None, cache_buster=False, optimize=False):
+
+    # make sure the output directory is always created in the current working
+    # directory or at the place given if it is an absolute path.
+    output = os.path.abspath(output)
+    msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals()
+    if debug:
+        msg += " with debugging statements"
+    print msg
+
+    # check the output directory
+    if os.path.exists(output) and not os.path.isdir(output):
+        print >>sys.stderr, "Output destination %s exists and is not a directory" % output
+        return
+    if not os.path.isdir(output):
+        try:
+            print "Creating output directory"
+            os.mkdir(output)
+        except StandardError, e:
+            print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e)
+
+    ## public dir
+    for p in pyjs.path:
+        pub_dir = join(p, 'public')
+        if isdir(pub_dir):
+            print "Copying: public directory of library %r" % p
+            copytree_exists(pub_dir, output)
+
+    ## AppName.html - can be in current or public directory
+    html_input_filename = app_name + ".html"
+    html_output_filename = join(output, basename(html_input_filename))
+    if os.path.isfile(html_input_filename):
+        if not os.path.isfile(html_output_filename) or \
+               os.path.getmtime(html_input_filename) > \
+               os.path.getmtime(html_output_filename):
+            try:
+                shutil.copy(html_input_filename, html_output_filename)
+            except:
+                print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename
+
+            print "Copying: %(html_input_filename)s" % locals()
+
+    if check_html_file(html_input_filename, output):
+        print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename
+
+    ## pygwt.js
+
+    print "Copying: pygwt.js"
+
+    pygwt_js_template = read_boilerplate(data_dir, "pygwt.js")
+    pygwt_js_output = open(join(output, "pygwt.js"), "w")
+
+    print >>pygwt_js_output, pygwt_js_template
+
+    pygwt_js_output.close()
+
+    ## Images
+
+    print "Copying: Images and History"
+    copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_topleft.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_topright.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output)
+    copy_boilerplate(data_dir, "corner_dialog_edge.png", output)
+    copy_boilerplate(data_dir, "tree_closed.gif", output)
+    copy_boilerplate(data_dir, "tree_open.gif", output)
+    copy_boilerplate(data_dir, "tree_white.gif", output)
+    copy_boilerplate(data_dir, "history.html", output)
+
+
+    ## all.cache.html
+    app_files = generateAppFiles(data_dir, js_includes, app_name, debug,
+                                 output, dynamic, cache_buster, optimize)
+
+    ## AppName.nocache.html
+
+    print "Creating: %(app_name)s.nocache.html" % locals()
+
+    home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html")
+    home_nocache_html_output = open(join(output, app_name + ".nocache.html"),
+                                    "w")
+
+    # the selector templ is added to the selectScript function
+    select_tmpl = """O(["true","%s"],"%s");"""
+    script_selectors = StringIO()
+
+    for platform, file_prefix in app_files:
+        print >> script_selectors, select_tmpl % (platform, file_prefix)
+
+    print >>home_nocache_html_output, home_nocache_html_template % dict(
+        app_name = app_name,
+        script_selectors = script_selectors.getvalue(),
+    )
+
+    home_nocache_html_output.close()
+
+    print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals()
+
+
+def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic,
+                     cache_buster, optimize):
+
+    all_cache_html_template = read_boilerplate(data_dir, "all.cache.html")
+    mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html")
+
+    # clean out the old ones first
+    for name in os.listdir(output):
+        if CACHE_HTML_PAT.match(name):
+            p = join(output, name)
+            print "Deleting existing app file %s" % p
+            os.unlink(p)
+
+    app_files = []
+    tmpl = read_boilerplate(data_dir, "all.cache.html")
+    parser = pyjs.PlatformParser("platform")
+    app_headers = ''
+    scripts = ['<script type="text/javascript" src="%s"></script>'%script \
+                                                  for script in js_includes]
+    app_body = '\n'.join(scripts)
+
+    mod_code = {}
+    mod_libs = {}
+    modules = {}
+    app_libs = {}
+    early_app_libs = {}
+    app_code = {}
+    overrides = {}
+    pover = {}
+    app_modnames = {}
+    mod_levels = {}
+
+    # First, generate all the code.
+    # Second, (dynamic only), post-analyse the places where modules
+    # haven't changed
+    # Third, write everything out.
+    
+    for platform in app_platforms:
+
+        mod_code[platform] = {}
+        mod_libs[platform] = {}
+        modules[platform] = []
+        pover[platform] = {}
+        app_libs[platform] = ''
+        early_app_libs[platform] = ''
+        app_code[platform] = {}
+        app_modnames[platform] = {}
+
+        # Application.Platform.cache.html
+
+        parser.setPlatform(platform)
+        app_translator = pyjs.AppTranslator(
+            parser=parser, dynamic=dynamic, optimize=optimize)
+        early_app_libs[platform], appcode = \
+                     app_translator.translate(None, is_app=False,
+                                              debug=debug,
+                                      library_modules=['dynamicajax.js',
+                                                    '_pyjs.js', 'sys',
+                                                     'pyjslib'])
+        pover[platform].update(app_translator.overrides.items())
+        for mname, name in app_translator.overrides.items():
+            pd = overrides.setdefault(mname, {})
+            pd[platform] = name
+
+        print appcode
+        #mod_code[platform][app_name] = appcode
+
+        # platform.Module.cache.js 
+
+        modules_done = ['pyjslib', 'sys', '_pyjs.js']
+        #modules_to_do = [app_name] + app_translator.library_modules
+        modules_to_do = [app_name] + app_translator.library_modules 
+
+        dependencies = {}
+
+        deps = map(pyjs.strip_py, modules_to_do)
+        for d in deps:
+            sublist = add_subdeps(dependencies, d)
+            modules_to_do += sublist
+        deps = uniquify(deps)
+        #dependencies[app_name] = deps
+
+        modules[platform] = modules_done + modules_to_do
+
+        while modules_to_do:
+
+            #print "modules to do", modules_to_do
+
+            mn = modules_to_do.pop()
+            mod_name = pyjs.strip_py(mn)
+
+            if mod_name in modules_done:
+                continue
+
+            modules_done.append(mod_name)
+
+            mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name)
+
+            parser.setPlatform(platform)
+            mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize)
+            mod_libs[platform][mod_name], mod_code[platform][mod_name] = \
+                              mod_translator.translate(mod_name,
+                                                  is_app=False,
+                                                  debug=debug)
+            pover[platform].update(mod_translator.overrides.items())
+            for mname, name in mod_translator.overrides.items():
+                pd = overrides.setdefault(mname, {})
+                pd[platform] = name
+
+            mods = mod_translator.library_modules
+            modules_to_do += mods
+            modules[platform] += mods
+
+            deps = map(pyjs.strip_py, mods)
+            sd = subdeps(mod_name)
+            if len(sd) > 1:
+                deps += sd[:-1]
+            while mod_name in deps:
+                deps.remove(mod_name)
+
+            #print
+            #print
+            #print "modname preadd:", mod_name, deps
+            #print
+            #print
+            for d in deps:
+                sublist = add_subdeps(dependencies, d)
+                modules_to_do += sublist
+            modules_to_do += add_subdeps(dependencies, mod_name)
+            #print "modname:", mod_name, deps
+            deps = uniquify(deps)
+            #print "modname:", mod_name, deps
+            dependencies[mod_name] = deps
+            
+        # work out the dependency ordering of the modules
+    
+        mod_levels[platform] = make_deps(None, dependencies, modules_done)
+
+    # now write everything out
+
+    for platform in app_platforms:
+
+        early_app_libs_ = early_app_libs[platform]
+        app_libs_ = app_libs[platform]
+        app_code_ = app_code[platform]
+        #modules_ = filter_mods(app_name, modules[platform])
+        mods = flattenlist(mod_levels[platform])
+        mods.reverse()
+        modules_ = filter_mods(None, mods)
+
+        for mod_name in modules_:
+
+            mod_code_ = mod_code[platform][mod_name]
+
+            mod_name = pyjs.strip_py(mod_name)
+
+            override_name = "%s.%s" % (platform.lower(), mod_name)
+            if pover[platform].has_key(override_name):
+                mod_cache_name = "%s.cache.js" % (override_name)
+            else:
+                mod_cache_name = "%s.cache.js" % (mod_name)
+
+            print "Creating: " + mod_cache_name
+
+            modlevels = make_deps(None, dependencies, dependencies[mod_name])
+
+            modnames = []
+
+            for md in modlevels:
+                mnames = map(lambda x: "'%s'" % x, md)
+                mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
+                modnames.append(mnames)
+
+            modnames.reverse()
+            modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames)
+
+            # convert the overrides
+
+            overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
+            overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
+
+            if dynamic:
+                mod_cache_html_output = open(join(output, mod_cache_name), "w")
+            else:
+                mod_cache_html_output = StringIO()
+
+            print >>mod_cache_html_output, mod_cache_html_template % dict(
+                mod_name = mod_name,
+                app_name = app_name,
+                modnames = modnames,
+                overrides = overnames,
+                mod_libs = mod_libs[platform][mod_name],
+                dynamic = dynamic,
+                mod_code = mod_code_,
+            )
+
+            if dynamic:
+                mod_cache_html_output.close()
+            else:
+                mod_cache_html_output.seek(0)
+                app_libs_ += mod_cache_html_output.read()
+
+        # write out the dependency ordering of the modules
+    
+        app_modnames = []
+
+        for md in mod_levels[platform]:
+            mnames = map(lambda x: "'%s'" % x, md)
+            mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
+            app_modnames.append(mnames)
+
+        app_modnames.reverse()
+        app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames)
+
+        # convert the overrides
+
+        overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
+        overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
+
+        #print "platform names", platform, overnames
+        #print pover
+
+        # now write app.allcache including dependency-ordered list of
+        # library modules
+
+        file_contents = all_cache_html_template % dict(
+            app_name = app_name,
+            early_app_libs = early_app_libs_,
+            app_libs = app_libs_,
+            app_code = app_code_,
+            app_body = app_body,
+            overrides = overnames,
+            platform = platform.lower(),
+            dynamic = dynamic,
+            app_modnames = app_modnames,
+            app_headers = app_headers
+        )
+        if cache_buster:
+            digest = md5.new(file_contents).hexdigest()
+            file_name = "%s.%s.%s" % (platform.lower(), app_name, digest)
+        else:
+            file_name = "%s.%s" % (platform.lower(), app_name)
+        file_name += ".cache.html" 
+        out_path = join(output, file_name)
+        out_file = open(out_path, 'w')
+        out_file.write(file_contents)
+        out_file.close()
+        app_files.append((platform.lower(), file_name))
+        print "Created app file %s:%s: %s" % (
+            app_name, platform, out_path)
+
+    return app_files
+
+def flattenlist(ll):
+    res = []
+    for l in ll:
+        res += l
+    return res
+
+# creates sub-dependencies e.g. pyjamas.ui.Widget
+# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
+def subdeps(m):
+    d = []
+    m = m.split(".")
+    for i in range(0, len(m)):
+        d.append('.'.join(m[:i+1]))
+    return d
+
+import time
+
+def add_subdeps(deps, mod_name):
+    sd = subdeps(mod_name)
+    if len(sd) == 1:
+        return []
+    #print "subdeps", mod_name, sd
+    #print "deps", deps
+    res = []
+    for i in range(0, len(sd)-1):
+        parent = sd[i]
+        child = sd[i+1]
+        l = deps.get(child, [])
+        l.append(parent)
+        deps[child] = l
+        if parent not in res:
+            res.append(parent)
+    #print deps
+    return res
+
+# makes unique and preserves list order
+def uniquify(md):
+    res = []
+    for m in md:
+        if m not in res:
+            res.append(m)
+    return res
+
+def filter_mods(app_name, md):
+    while 'sys' in md:
+        md.remove('sys')
+    while 'pyjslib' in md:
+        md.remove('pyjslib')
+    while app_name in md:
+        md.remove(app_name)
+    md = filter(lambda x: not x.endswith('.js'), md)
+    md = map(pyjs.strip_py, md)
+
+    return uniquify(md)
+
+def filter_deps(app_name, deps):
+
+    res = {}
+    for (k, l) in deps.items():
+        mods = filter_mods(k, l)
+        while k in mods:
+            mods.remove(k)
+        res[k] = mods
+    return res
+
+def has_nodeps(mod, deps):
+    if not deps.has_key(mod) or not deps[mod]:
+        return True
+    return False
+
+def nodeps_list(mod_list, deps):
+    res = []
+    for mod in mod_list:
+        if has_nodeps(mod, deps):
+            res.append(mod)
+    return res
+        
+# this function takes a dictionary of dependent modules and
+# creates a list of lists.  the first list will be modules
+# that have no dependencies; the second list will be those
+# modules that have the first list as dependencies; the
+# third will be those modules that have the first and second...
+# etc.
+
+
+def make_deps(app_name, deps, mod_list):
+    print "Calculating Dependencies ..."
+    mod_list = filter_mods(app_name, mod_list)
+    deps = filter_deps(app_name, deps)
+
+    if not mod_list:
+        return []
+
+    #print mod_list
+    #print deps
+
+    ordered_deps = []
+    last_len = -1
+    while deps:
+        l_deps = len(deps)
+        #print l_deps
+        if l_deps==last_len:
+            for m, dl in deps.items():
+                for d in dl:
+                    if m in deps.get(d, []):
+                        raise Exception('Circular Imports found: \n%s %s -> %s %s'
+                                        % (m, dl, d, deps[d]))
+            #raise Exception('Could not calculate dependencies: \n%s' % deps)
+            break
+        last_len = l_deps
+        #print "modlist", mod_list
+        nodeps = nodeps_list(mod_list, deps)
+        #print "nodeps", nodeps
+        mod_list = filter(lambda x: x not in nodeps, mod_list)
+        newdeps = {}
+        for k in deps.keys():
+            depslist = deps[k]
+            depslist = filter(lambda x: x not in nodeps, depslist)
+            if depslist:
+                newdeps[k] = depslist
+        #print "newdeps", newdeps
+        deps = newdeps
+        ordered_deps.append(nodeps)
+        #time.sleep(0)
+
+    if mod_list:
+        ordered_deps.append(mod_list) # last dependencies - usually the app(s)
+
+    ordered_deps.reverse()
+
+    return ordered_deps
+
+def main():
+    global app_platforms
+
+    parser = OptionParser(usage = usage, version = version)
+    parser.add_option("-o", "--output", dest="output",
+        help="directory to which the webapp should be written")
+    parser.add_option("-j", "--include-js", dest="js_includes", action="append",
+        help="javascripts to load into the same frame as the rest of the script")
+    parser.add_option("-I", "--library_dir", dest="library_dirs",
+        action="append", help="additional paths appended to PYJSPATH")
+    parser.add_option("-D", "--data_dir", dest="data_dir",
+        help="path for data directory")
+    parser.add_option("-m", "--dynamic-modules", action="store_true",
+        dest="dynamic", default=False,
+        help="Split output into separate dynamically-loaded modules (experimental)")
+    parser.add_option("-P", "--platforms", dest="platforms",
+        help="platforms to build for, comma-separated")
+    parser.add_option("-d", "--debug", action="store_true", dest="debug")
+    parser.add_option("-O", "--optimize", action="store_true",
+                      dest="optimize", default=False,
+                      help="Optimize generated code (removes all print statements)",
+                      )
+    parser.add_option("-c", "--cache_buster", action="store_true",
+                  dest="cache_buster",
+        help="Enable browser cache-busting (MD5 hash added to output filenames)")
+
+    parser.set_defaults(output = "output", js_includes=[], library_dirs=[],
+                        platforms=(','.join(app_platforms)),
+                        data_dir=os.path.join(sys.prefix, "share/pyjamas"),
+                        dynamic=False,
+                        cache_buster=False,
+                        debug=False)
+    (options, args) = parser.parse_args()
+    if len(args) != 1:
+        parser.error("incorrect number of arguments")
+
+    data_dir = abspath(options.data_dir)
+
+    app_path = args[0]
+    if app_path.endswith('.py'):
+        app_path = abspath(app_path)
+        if not isfile(app_path):
+            parser.error("Application file not found %r" % app_path)
+        app_path, app_name = split(app_path)
+        app_name = app_name[:-3]
+        pyjs.path.append(app_path)
+    elif os.path.sep in app_path:
+        parser.error("Not a valid module declaration %r" % app_path)
+    else:
+        app_name = app_path
+
+    for d in options.library_dirs:
+        pyjs.path.append(abspath(d))
+
+    if options.platforms:
+       app_platforms = options.platforms.split(',')
+
+    # this is mostly for getting boilerplate stuff
+    data_dir = os.path.abspath(options.data_dir)
+
+    build(app_name, options.output, options.js_includes,
+          options.debug, options.dynamic and 1 or 0, data_dir,
+          options.cache_buster, options.optimize)
+
+if __name__ == "__main__":
+    main()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/README.txt	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,12 @@
+These classes are intended for use server-side.
+
+e.g. in a django view.py :
+
+    from pyjs.jsonrpc.django import JSONService, jsonremote
+
+    jsonservice = JSONRPCService()
+
+    @jsonremote(jsonservice)
+    def test(request, echo_param):
+         return "echoing the param back: %s" % echo_param
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,226 @@
+# jsonrpc.py
+#   original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas
+#   also from: http://www.pimentech.fr/technologies/outils
+from django.utils import simplejson
+from django.http import HttpResponse
+import sys
+
+from pyjs.jsonrpc import JSONRPCServiceBase
+# JSONRPCService and jsonremote are used in combination to drastically
+# simplify the provision of JSONRPC services.  use as follows:
+#
+# jsonservice = JSONRPCService()
+#
+# @jsonremote(jsonservice)
+# def test(request, echo_param):
+#     return "echoing the param back: %s" % echo_param
+#
+# dump jsonservice into urlpatterns:
+#  (r'^service1/$', 'djangoapp.views.jsonservice'),
+
+class JSONRPCService(JSONRPCServiceBase):
+    
+    def __call__(self, request, extra=None):
+        return self.process(request.raw_post_data)
+
+def jsonremote(service):
+    """Make JSONRPCService a decorator so that you can write :
+    
+    from jsonrpc import JSONRPCService
+    chatservice = JSONRPCService()
+
+    @jsonremote(chatservice)
+    def login(request, user_name):
+        (...)
+    """
+    def remotify(func):
+        if isinstance(service, JSONRPCService):
+            service.add_method(func.__name__, func)
+        else:
+            emsg = 'Service "%s" not found' % str(service.__name__)
+            raise NotImplementedError, emsg
+        return func
+    return remotify
+
+
+# FormProcessor provides a mechanism for turning Django Forms into JSONRPC
+# Services.  If you have an existing Django app which makes prevalent
+# use of Django Forms it will save you rewriting the app.
+# use as follows.  in djangoapp/views.py :
+#
+# class SimpleForm(forms.Form):
+#     testfield = forms.CharField(max_length=100)
+#
+# class SimpleForm2(forms.Form):
+#     testfield = forms.CharField(max_length=20)
+#
+# processor = FormProcessor({'processsimpleform': SimpleForm,
+#                            'processsimpleform2': SimpleForm2})
+#
+# this will result in a JSONRPC service being created with two
+# RPC functions.  dump "processor" into urlpatterns to make it
+# part of the app:
+#  (r'^formsservice/$', 'djangoapp.views.processor'),
+
+from django import forms 
+
+def builderrors(form):
+    d = {}
+    for error in form.errors.keys():
+        if error not in d:
+            d[error] = []
+        for errorval in form.errors[error]:
+            d[error].append(unicode(errorval))
+    return d
+
+
+# contains the list of arguments in each field
+field_names = {
+ 'CharField': ['max_length', 'min_length'],
+ 'IntegerField': ['max_value', 'min_value'],
+ 'FloatField': ['max_value', 'min_value'],
+ 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'],
+ 'DateField': ['input_formats'],
+ 'DateTimeField': ['input_formats'],
+ 'TimeField': ['input_formats'],
+ 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr
+ 'EmailField': ['max_length', 'min_length'],
+ 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'],
+ 'ChoiceField': ['choices'],
+ 'FilePathField': ['path', 'match', 'recursive', 'choices'],
+ 'IPAddressField': ['max_length', 'min_length'],
+ }
+
+def describe_field_errors(field):
+    res = {}
+    field_type = field.__class__.__name__
+    msgs = {}
+    for n, m in field.error_messages.items():
+        msgs[n] = unicode(m)
+    res['error_messages'] = msgs
+    if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
+        res['fields'] = map(describe_field, field.fields)
+    return res
+
+def describe_fields_errors(fields, field_names):
+    res = {}
+    if not field_names:
+        field_names = fields.keys()
+    for name in field_names:
+        field = fields[name]
+        res[name] = describe_field_errors(field)
+    return res
+
+def describe_field(field):
+    res = {}
+    field_type = field.__class__.__name__
+    for fname in field_names.get(field_type, []) + \
+          ['help_text', 'label', 'initial', 'required']:
+        res[fname] = getattr(field, fname)
+    if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
+        res['fields'] = map(describe_field, field.fields)
+    return res
+
+def describe_fields(fields, field_names):
+    res = {}
+    if not field_names:
+        field_names = fields.keys()
+    for name in field_names:
+        field = fields[name]
+        res[name] = describe_field(field)
+    return res
+
+class FormProcessor(JSONRPCService):
+    def __init__(self, forms, _formcls=None):
+
+        if _formcls is None:
+            JSONRPCService.__init__(self)
+            for k in forms.keys():
+                s  = FormProcessor({}, forms[k])
+                self.add_method(k, s.__process)
+        else:
+            JSONRPCService.__init__(self, forms)
+            self.formcls = _formcls
+
+    def __process(self, request, params, command=None):
+
+        f = self.formcls(params)
+
+        if command is None: # just validate
+            if not f.is_valid():
+                return {'success':False, 'errors': builderrors(f)}
+            return {'success':True}
+
+        elif command.has_key('describe_errors'):
+            field_names = command['describe_errors']
+            return describe_fields_errors(f.fields, field_names)
+
+        elif command.has_key('describe'):
+            field_names = command['describe']
+            return describe_fields(f.fields, field_names)
+
+        elif command.has_key('save'):
+            if not f.is_valid():
+                return {'success':False, 'errors': builderrors(f)}
+            instance = f.save() # XXX: if you want more, over-ride save.
+            return {'success': True, 'instance': json_convert(instance) }
+
+        elif command.has_key('html'):
+            return {'success': True, 'html': f.as_table()}
+
+        return "unrecognised command"
+
+
+
+
+# The following is incredibly convenient for saving vast amounts of
+# coding, avoiding doing silly things like this:
+#     jsonresult = {'field1': djangoobject.field1,
+#                   'field2': djangoobject.date.strftime('%Y.%M'),
+#                    ..... }
+#
+# The date/time flatten function is there because JSONRPC doesn't
+# support date/time objects or formats, so conversion to a string
+# is the most logical choice.  pyjamas, being python, can easily
+# be used to parse the string result at the other end.
+#
+# use as follows:
+#
+# jsonservice = JSONRPCService()
+#
+# @jsonremote(jsonservice)
+# def list_some_model(request, start=0, count=10):
+#     l = SomeDjangoModelClass.objects.filter()
+#     res = json_convert(l[start:end])
+#
+# @jsonremote(jsonservice)
+# def list_another_model(request, start=0, count=10):
+#     l = AnotherDjangoModelClass.objects.filter()
+#     res = json_convert(l[start:end])
+#
+# dump jsonservice into urlpatterns to make the two RPC functions,
+# list_some_model and list_another_model part of the django app:
+#  (r'^service1/$', 'djangoapp.views.jsonservice'),
+
+from django.core.serializers import serialize
+import datetime
+from datetime import date
+
+def dict_datetimeflatten(item):
+    d = {}
+    for k, v in item.items():
+        k = str(k)
+        if isinstance(v, datetime.date):
+            d[k] = str(v)
+        elif isinstance(v, dict):
+            d[k] = dict_datetimeflatten(v)
+        else:
+            d[k] = v
+    return d
+
+def json_convert(l, fields=None):
+    res = []
+    for item in serialize('python', l, fields=fields):
+        res.append(dict_datetimeflatten(item))
+    return res
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,43 @@
+import gluon.contrib.simplejson as simplejson
+import types
+import sys
+
+class JSONRPCServiceBase:
+
+    def __init__(self):
+        self.methods={}
+
+    def response(self, id, result):
+        return simplejson.dumps({'version': '1.1', 'id':id,
+                                 'result':result, 'error':None})
+    def error(self, id, code, message):
+        return simplejson.dumps({'id': id,
+                                 'version': '1.1',
+                                 'error': {'name': 'JSONRPCError',
+                                           'code': code,
+                                           'message': message
+                                           }
+                                     })
+
+    def add_method(self, name, method):
+        self.methods[name] = method
+
+    def process(self, data):
+        data = simplejson.loads(data)
+        id, method, params = data["id"], data["method"], data["params"]
+        if method in self.methods:
+            try:
+                result =self.methods[method](*params)
+                return self.response(id, result)
+            except BaseException:
+                etype, eval, etb = sys.exc_info()
+                return self.error(id, 100, '%s: %s' %(etype.__name__, eval))
+            except:
+                etype, eval, etb = sys.exc_info()
+                return self.error(id, 100, 'Exception %s: %s' %(etype, eval))
+        else:
+            return self.error(id, 100, 'method "%s" does not exist' % method)
+
+    def listmethods(self):
+        return self.methods.keys() 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,11 @@
+from pyjs.jsonrpc import JSONRPCServiceBase
+
+class JSONRPCService(JSONRPCServiceBase):
+
+    def serve(self):
+        return self.process(request.body.read())
+
+    def __call__(self,func):
+        self.methods[func.__name__]=func
+        return func
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/_pyjs.js	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,160 @@
+function pyjs_extend(klass, base) {
+    function klass_object_inherit() {}
+    klass_object_inherit.prototype = base.prototype;
+    klass_object = new klass_object_inherit();
+    for (var i in base.prototype.__class__) {
+        v = base.prototype.__class__[i];
+        if (typeof v == "function" && (v.class_method || v.static_method || v.unbound_method))
+        {
+            klass_object[i] = v;
+        }
+    }
+
+    function klass_inherit() {}
+    klass_inherit.prototype = klass_object;
+    klass.prototype = new klass_inherit();
+    klass_object.constructor = klass;
+    klass.prototype.__class__ = klass_object;
+
+    for (var i in base.prototype) {
+        v = base.prototype[i];
+        if (typeof v == "function" && v.instance_method)
+        {
+            klass.prototype[i] = v;
+        }
+    }
+}
+
+/* creates a class, derived from bases, with methods and variables */
+function pyjs_type(clsname, bases, methods)
+{
+    var fn_cls = function() {};
+    fn_cls.__name__ = clsname;
+    var fn = function() {
+        var instance = new fn_cls();
+        if(instance.__init__) instance.__init__.apply(instance, arguments);
+        return instance;
+    }
+    fn_cls.__initialize__ = function() {
+        if (fn_cls.__was_initialized__) return;
+        fn_cls.__was_initialized__ = true;
+        fn_cls.__extend_baseclasses();
+        fn_cls.prototype.__class__.__new__ = fn;
+        fn_cls.prototype.__class__.__name__ = clsname;
+    }
+    fn_cls.__extend_baseclasses = function() {
+        var bi;
+        for (bi in fn_cls.__baseclasses)
+        {
+            var b = fn_cls.__baseclasses[bi];
+            if (b.__was_initialized__)
+            {
+                continue;
+            }
+            b.__initialize__();
+        }
+        for (bi in fn_cls.__baseclasses)
+        {
+            var b = fn_cls.__baseclasses[bi];
+            pyjs_extend(fn_cls, b);
+        }
+    }
+    if (!bases) {
+        bases = [pyjslib.__Object];
+    }
+    fn_cls.__baseclasses = bases;
+
+    fn_cls.__initialize__();
+
+    for (k in methods) {
+        var mth = methods[k];
+        var mtype = typeof mth;
+        if (mtype == "function" ) {
+            fn_cls.prototype[k] = mth;
+            fn_cls.prototype.__class__[k] = function () {
+                return fn_cls.prototype[k].call.apply(
+                       fn_cls.prototype[k], arguments);
+            };
+            fn_cls.prototype.__class__[k].unbound_method = true;
+            fn_cls.prototype.instance_method = true;
+            fn_cls.prototype.__class__[k].__name__ = k;
+            fn_cls.prototype[k].__name__ = k;
+        } else {
+            fn_cls.prototype.__class__[k] = mth;
+        }
+    }
+    return fn;
+}
+function pyjs_kwargs_call(obj, func, star_args, args)
+{
+    var call_args;
+
+    if (star_args)
+    {
+        if (!pyjslib.isIteratable(star_args))
+        {
+            throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args)));
+        }
+        call_args = Array();
+        var __i = star_args.__iter__();
+        var i = 0;
+        try {
+            while (true) {
+                call_args[i]=__i.next();
+                i++;
+            }
+        } catch (e) {
+            if (e != pyjslib.StopIteration) {
+                throw e;
+            }
+        }
+
+        if (args)
+        {
+            var n = star_args.length;
+            for (var i=0; i < args.length; i++) {
+                call_args[n+i]=args[i];
+            }
+        }
+    }
+    else
+    {
+        call_args = args;
+    }
+    return func.apply(obj, call_args);
+}
+
+function pyjs_kwargs_function_call(func, star_args, args)
+{
+    return pyjs_kwargs_call(null, func, star_args, args);
+}
+
+function pyjs_kwargs_method_call(obj, method_name, star_args, args)
+{
+    var method = obj[method_name];
+    if (method.parse_kwargs)
+    {
+        args = method.parse_kwargs.apply(null, args);
+    }
+    return pyjs_kwargs_call(obj, method, star_args, args);
+}
+
+//String.prototype.__getitem__ = String.prototype.charAt;
+//String.prototype.upper = String.prototype.toUpperCase;
+//String.prototype.lower = String.prototype.toLowerCase;
+//String.prototype.find=pyjslib.String_find;
+//String.prototype.join=pyjslib.String_join;
+//String.prototype.isdigit=pyjslib.String_isdigit;
+//String.prototype.__iter__=pyjslib.String___iter__;
+//
+//String.prototype.__replace=String.prototype.replace;
+//String.prototype.replace=pyjslib.String_replace;
+//
+//String.prototype.split=pyjslib.String_split;
+//String.prototype.strip=pyjslib.String_strip;
+//String.prototype.lstrip=pyjslib.String_lstrip;
+//String.prototype.rstrip=pyjslib.String_rstrip;
+//String.prototype.startswith=pyjslib.String_startswith;
+
+var str = String;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/json.js	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,293 @@
+json_parse = (function () {
+
+// This is a function that can parse a JSON text, producing a JavaScript
+// data structure. It is a simple, recursive descent parser. It does not use
+// eval or regular expressions, so it can be used as a model for implementing
+// a JSON parser in other languages.
+
+// We are defining the function inside of another function to avoid creating
+// global variables.
+
+    var at,     // The index of the current character
+        ch,     // The current character
+        escapee = {
+            '"':  '"',
+            '\\': '\\',
+            '/':  '/',
+            b:    '\b',
+            f:    '\f',
+            n:    '\n',
+            r:    '\r',
+            t:    '\t'
+        },
+        text,
+
+        error = function (m) {
+
+// Call error when something is wrong.
+
+            throw {
+                name:    'SyntaxError',
+                message: m,
+                at:      at,
+                text:    text
+            };
+        },
+
+        next = function (c) {
+
+// If a c parameter is provided, verify that it matches the current character.
+
+            if (c && c !== ch) {
+                error("Expected '" + c + "' instead of '" + ch + "'");
+            }
+
+// Get the next character. When there are no more characters,
+// return the empty string.
+
+            ch = text.charAt(at);
+            at += 1;
+            return ch;
+        },
+
+        number = function () {
+
+// Parse a number value.
+
+            var number,
+                string = '';
+
+            if (ch === '-') {
+                string = '-';
+                next('-');
+            }
+            while (ch >= '0' && ch <= '9') {
+                string += ch;
+                next();
+            }
+            if (ch === '.') {
+                string += '.';
+                while (next() && ch >= '0' && ch <= '9') {
+                    string += ch;
+                }
+            }
+            if (ch === 'e' || ch === 'E') {
+                string += ch;
+                next();
+                if (ch === '-' || ch === '+') {
+                    string += ch;
+                    next();
+                }
+                while (ch >= '0' && ch <= '9') {
+                    string += ch;
+                    next();
+                }
+            }
+            number = +string;
+            if (isNaN(number)) {
+                error("Bad number");
+            } else {
+                return number;
+            }
+        },
+
+        string = function () {
+
+// Parse a string value.
+
+            var hex,
+                i,
+                string = '',
+                uffff;
+
+// When parsing for string values, we must look for " and \ characters.
+
+            if (ch === '"') {
+                while (next()) {
+                    if (ch === '"') {
+                        next();
+                        return string;
+                    } else if (ch === '\\') {
+                        next();
+                        if (ch === 'u') {
+                            uffff = 0;
+                            for (i = 0; i < 4; i += 1) {
+                                hex = parseInt(next(), 16);
+                                if (!isFinite(hex)) {
+                                    break;
+                                }
+                                uffff = uffff * 16 + hex;
+                            }
+                            string += String.fromCharCode(uffff);
+                        } else if (typeof escapee[ch] === 'string') {
+                            string += escapee[ch];
+                        } else {
+                            break;
+                        }
+                    } else {
+                        string += ch;
+                    }
+                }
+            }
+            error("Bad string");
+        },
+
+        white = function () {
+
+// Skip whitespace.
+
+            while (ch && ch <= ' ') {
+                next();
+            }
+        },
+
+        word = function () {
+
+// true, false, or null.
+
+            switch (ch) {
+            case 't':
+                next('t');
+                next('r');
+                next('u');
+                next('e');
+                return true;
+            case 'f':
+                next('f');
+                next('a');
+                next('l');
+                next('s');
+                next('e');
+                return false;
+            case 'n':
+                next('n');
+                next('u');
+                next('l');
+                next('l');
+                return null;
+            }
+            error("Unexpected '" + ch + "'");
+        },
+
+        value,  // Place holder for the value function.
+
+        array = function () {
+
+// Parse an array value.
+
+            var array = [];
+
+            if (ch === '[') {
+                next('[');
+                white();
+                if (ch === ']') {
+                    next(']');
+                    return array;   // empty array
+                }
+                while (ch) {
+                    array.push(value());
+                    white();
+                    if (ch === ']') {
+                        next(']');
+                        return array;
+                    }
+                    next(',');
+                    white();
+                }
+            }
+            error("Bad array");
+        },
+
+        object = function () {
+
+// Parse an object value.
+
+            var key,
+                object = {};
+
+            if (ch === '{') {
+                next('{');
+                white();
+                if (ch === '}') {
+                    next('}');
+                    return object;   // empty object
+                }
+                while (ch) {
+                    key = string();
+                    white();
+                    next(':');
+                    if (Object.hasOwnProperty.call(object, key)) {
+                        error('Duplicate key "' + key + '"');
+                    }
+                    object[key] = value();
+                    white();
+                    if (ch === '}') {
+                        next('}');
+                        return object;
+                    }
+                    next(',');
+                    white();
+                }
+            }
+            error("Bad object");
+        };
+
+    value = function () {
+
+// Parse a JSON value. It could be an object, an array, a string, a number,
+// or a word.
+
+        white();
+        switch (ch) {
+        case '{':
+            return object();
+        case '[':
+            return array();
+        case '"':
+            return string();
+        case '-':
+            return number();
+        default:
+            return ch >= '0' && ch <= '9' ? number() : word();
+        }
+    };
+
+// Return the json_parse function. It will have access to all of the above
+// functions and variables.
+
+    return function (source, reviver) {
+        var result;
+
+        text = source;
+        at = 0;
+        ch = ' ';
+        result = value();
+        white();
+        if (ch) {
+            error("Syntax error");
+        }
+
+// If there is a reviver function, we recursively walk the new structure,
+// passing each name/value pair to the reviver function for possible
+// transformation, starting with a temporary root object that holds the result
+// in an empty key. If there is not a reviver function, we simply return the
+// result.
+
+        return typeof reviver === 'function' ? (function walk(holder, key) {
+            var k, v, value = holder[key];
+            if (value && typeof value === 'object') {
+                for (k in value) {
+                    if (Object.hasOwnProperty.call(value, k)) {
+                        v = walk(value, k);
+                        if (v !== undefined) {
+                            value[k] = v;
+                        } else {
+                            delete value[k];
+                        }
+                    }
+                }
+            }
+            return reviver.call(holder, key, value);
+        }({'': result}, '')) : result;
+    };
+}());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/pyjslib.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1365 @@
+# Copyright 2006 James Tauber and contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# iteration from Bob Ippolito's Iteration in JavaScript
+
+from __pyjamas__ import JS
+
+# must declare import _before_ importing sys
+
+def import_module(path, parent_module, module_name, dynamic=1, async=False):
+    """ 
+    """
+
+    JS("""
+        var cache_file;
+
+        if (module_name == "sys" || module_name == 'pyjslib')
+        {
+            /*module_load_request[module_name] = 1;*/
+            return;
+        }
+
+        if (path == null)
+        {
+            path = './';
+        }
+
+        var override_name = sys.platform + "." + module_name;
+        if (((sys.overrides != null) && 
+             (sys.overrides.has_key(override_name))))
+        {
+            cache_file =  sys.overrides.__getitem__(override_name) ;
+        }
+        else
+        {
+            cache_file =  module_name ;
+        }
+
+        cache_file = (path + cache_file + '.cache.js' ) ;
+
+        //alert("cache " + cache_file + " " + module_name + " " + parent_module);
+
+        /* already loaded? */
+        if (module_load_request[module_name])
+        {
+            if (module_load_request[module_name] >= 3 && parent_module != null)
+            {
+                //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';';
+                //pyjs_eval(onload_fn); /* set up the parent-module namespace */
+            }
+            return;
+        }
+        if (typeof (module_load_request[module_name]) == 'undefined')
+        {
+            module_load_request[module_name] = 1;
+        }
+
+        /* following a load, this first executes the script 
+         * "preparation" function MODULENAME_loaded_fn()
+         * and then sets up the loaded module in the namespace
+         * of the parent.
+         */
+
+        onload_fn = ''; // module_name + "_loaded_fn();"
+
+        if (parent_module != null)
+        {
+            //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';';
+            /*pmod = parent_module + '.' + module_name;
+            onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/
+        }
+
+
+        if (dynamic)
+        {
+            /* this one tacks the script onto the end of the DOM
+             */
+
+            pyjs_load_script(cache_file, onload_fn, async);
+
+            /* this one actually RUNS the script (eval) into the page.
+               my feeling is that this would be better for non-async
+               but i can't get it to work entirely yet.
+             */
+            /*pyjs_ajax_eval(cache_file, onload_fn, async);*/
+        }
+        else
+        {
+            if (module_name != "pyjslib" &&
+                module_name != "sys")
+                pyjs_eval(onload_fn);
+        }
+
+    """)
+
+JS("""
+function import_wait(proceed_fn, parent_mod, dynamic) {
+
+    var data = '';
+    var element = $doc.createElement("div");
+    $doc.body.appendChild(element);
+    function write_dom(txt) {
+        element.innerHTML = txt + '<br />';
+    }
+
+    var timeoutperiod = 1;
+    if (dynamic)
+        var timeoutperiod = 1;
+
+    var wait = function() {
+
+        var status = '';
+        for (l in module_load_request)
+        {
+            var m = module_load_request[l];
+            if (l == "sys" || l == 'pyjslib')
+                continue;
+            status += l + m + " ";
+        }
+
+        //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
+        wait_count += 1;
+
+        if (status == '')
+        {
+            setTimeout(wait, timeoutperiod);
+            return;
+        }
+
+        for (l in module_load_request)
+        {
+            var m = module_load_request[l];
+            if (l == "sys" || l == 'pyjslib')
+            {
+                module_load_request[l] = 4;
+                continue;
+            }
+            if ((parent_mod != null) && (l == parent_mod))
+            {
+                if (m == 1)
+                {
+                    setTimeout(wait, timeoutperiod);
+                    return;
+                }
+                if (m == 2)
+                {
+                    /* cheat and move app on to next stage */
+                    module_load_request[l] = 3;
+                }
+            }
+            if (m == 1 || m == 2)
+            {
+                setTimeout(wait, timeoutperiod);
+                return;
+            }
+            if (m == 3)
+            {
+                //alert("waited for module " + l + ": loaded");
+                module_load_request[l] = 4;
+                mod_fn = modules[l];
+            }
+        }
+        //alert("module wait done");
+
+        if (proceed_fn.importDone)
+            proceed_fn.importDone(proceed_fn);
+        else
+            proceed_fn();
+    }
+
+    wait();
+}
+""")
+
+class Object:
+    pass
+
+object = Object
+
+class Modload:
+
+    def __init__(self, path, app_modlist, app_imported_fn, dynamic,
+                 parent_mod):
+        self.app_modlist = app_modlist
+        self.app_imported_fn = app_imported_fn
+        self.path = path
+        self.idx = 0;
+        self.dynamic = dynamic
+        self.parent_mod = parent_mod
+
+    def next(self):
+        
+        for i in range(len(self.app_modlist[self.idx])):
+            app = self.app_modlist[self.idx][i]
+            import_module(self.path, self.parent_mod, app, self.dynamic, True);
+        self.idx += 1
+
+        if self.idx >= len(self.app_modlist):
+            import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
+        else:
+            import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
+
+def get_module(module_name):
+    ev = "__mod = %s;" % module_name
+    JS("pyjs_eval(ev);")
+    return __mod
+
+def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
+                        parent_mod=None):
+
+    loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
+    loader.next()
+
+import sys
+
+class BaseException:
+
+    name = "BaseException"
+
+    def __init__(self, *args):
+        self.args = args
+
+    def __str__(self):
+        if len(self.args) is 0:
+            return ''
+        elif len(self.args) is 1:
+            return repr(self.args[0])
+        return repr(self.args)
+
+    def toString(self):
+        return str(self)
+
+class Exception(BaseException):
+
+    name = "Exception"
+
+class TypeError(BaseException):
+    name = "TypeError"
+
+class StandardError(Exception):
+    name = "StandardError"
+
+class LookupError(StandardError):
+    name = "LookupError"
+
+    def toString(self):
+        return self.name + ": " + self.args[0]
+
+class KeyError(LookupError):
+    name = "KeyError"
+
+class AttributeError(StandardError):
+
+    name = "AttributeError"
+
+    def toString(self):
+        return "AttributeError: %s of %s" % (self.args[1], self.args[0])
+
+JS("""
+pyjslib.StopIteration = function () { };
+pyjslib.StopIteration.prototype = new Error();
+pyjslib.StopIteration.name = 'StopIteration';
+pyjslib.StopIteration.message = 'StopIteration';
+
+pyjslib.String_find = function(sub, start, end) {
+    var pos=this.indexOf(sub, start);
+    if (pyjslib.isUndefined(end)) return pos;
+
+    if (pos + sub.length>end) return -1;
+    return pos;
+}
+
+pyjslib.String_join = function(data) {
+    var text="";
+
+    if (pyjslib.isArray(data)) {
+        return data.join(this);
+    }
+    else if (pyjslib.isIteratable(data)) {
+        var iter=data.__iter__();
+        try {
+            text+=iter.next();
+            while (true) {
+                var item=iter.next();
+                text+=this + item;
+            }
+        }
+        catch (e) {
+            if (e != pyjslib.StopIteration) throw e;
+        }
+    }
+
+    return text;
+}
+
+pyjslib.String_isdigit = function() {
+    return (this.match(/^\d+$/g) != null);
+}
+
+pyjslib.String_replace = function(old, replace, count) {
+    var do_max=false;
+    var start=0;
+    var new_str="";
+    var pos=0;
+
+    if (!pyjslib.isString(old)) return this.__replace(old, replace);
+    if (!pyjslib.isUndefined(count)) do_max=true;
+
+    while (start<this.length) {
+        if (do_max && !count--) break;
+
+        pos=this.indexOf(old, start);
+        if (pos<0) break;
+
+        new_str+=this.substring(start, pos) + replace;
+        start=pos+old.length;
+    }
+    if (start<this.length) new_str+=this.substring(start);
+
+    return new_str;
+}
+
+pyjslib.String_split = function(sep, maxsplit) {
+    var items=new pyjslib.List();
+    var do_max=false;
+    var subject=this;
+    var start=0;
+    var pos=0;
+
+    if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) {
+        sep=" ";
+        subject=subject.strip();
+        subject=subject.replace(/\s+/g, sep);
+    }
+    else if (!pyjslib.isUndefined(maxsplit)) do_max=true;
+
+    if (subject.length == 0) {
+        return items;
+    }
+
+    while (start<subject.length) {
+        if (do_max && !maxsplit--) break;
+
+        pos=subject.indexOf(sep, start);
+        if (pos<0) break;
+
+        items.append(subject.substring(start, pos));
+        start=pos+sep.length;
+    }
+    if (start<=subject.length) items.append(subject.substring(start));
+
+    return items;
+}
+
+pyjslib.String___iter__ = function() {
+    var i = 0;
+    var s = this;
+    return {
+        'next': function() {
+            if (i >= s.length) {
+                throw pyjslib.StopIteration;
+            }
+            return s.substring(i++, i, 1);
+        },
+        '__iter__': function() {
+            return this;
+        }
+    };
+}
+
+pyjslib.String_strip = function(chars) {
+    return this.lstrip(chars).rstrip(chars);
+}
+
+pyjslib.String_lstrip = function(chars) {
+    if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, "");
+
+    return this.replace(new RegExp("^[" + chars + "]+"), "");
+}
+
+pyjslib.String_rstrip = function(chars) {
+    if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, "");
+
+    return this.replace(new RegExp("[" + chars + "]+$"), "");
+}
+
+pyjslib.String_startswith = function(prefix, start) {
+    if (pyjslib.isUndefined(start)) start = 0;
+
+    if (this.substring(start, prefix.length) == prefix) return true;
+    return false;
+}
+
+pyjslib.abs = Math.abs;
+
+""")
+
+class Class:
+    def __init__(self, name):
+        self.name = name
+
+    def __str___(self):
+        return self.name
+
+def eq(a,b):
+    JS("""
+    if (pyjslib.hasattr(a, "__cmp__")) {
+        return a.__cmp__(b) == 0;
+    } else if (pyjslib.hasattr(b, "__cmp__")) {
+        return b.__cmp__(a) == 0;
+    }
+    return a == b;
+    """)
+
+def cmp(a,b):
+    if hasattr(a, "__cmp__"):
+        return a.__cmp__(b)
+    elif hasattr(b, "__cmp__"):
+        return -b.__cmp__(a)
+    if a > b:
+        return 1
+    elif b > a:
+        return -1
+    else:
+        return 0
+
+def bool(v):
+    # this needs to stay in native code without any dependencies here,
+    # because this is used by if and while, we need to prevent
+    # recursion
+    JS("""
+    if (!v) return false;
+    switch(typeof v){
+    case 'boolean':
+        return v;
+    case 'object':
+        if (v.__nonzero__){
+            return v.__nonzero__();
+        }else if (v.__len__){
+            return v.__len__()>0;
+        }
+        return true;
+    }
+    return Boolean(v);
+    """)
+
+class List:
+    def __init__(self, data=None):
+        JS("""
+        this.l = [];
+        this.extend(data);
+        """)
+
+    def append(self, item):
+        JS("""    this.l[this.l.length] = item;""")
+
+    def extend(self, data):
+        JS("""
+        if (pyjslib.isArray(data)) {
+            n = this.l.length;
+            for (var i=0; i < data.length; i++) {
+                this.l[n+i]=data[i];
+                }
+            }
+        else if (pyjslib.isIteratable(data)) {
+            var iter=data.__iter__();
+            var i=this.l.length;
+            try {
+                while (true) {
+                    var item=iter.next();
+                    this.l[i++]=item;
+                    }
+                }
+            catch (e) {
+                if (e != pyjslib.StopIteration) throw e;
+                }
+            }
+        """)
+
+    def remove(self, value):
+        JS("""
+        var index=this.index(value);
+        if (index<0) return false;
+        this.l.splice(index, 1);
+        return true;
+        """)
+
+    def index(self, value, start=0):
+        JS("""
+        var length=this.l.length;
+        for (var i=start; i<length; i++) {
+            if (this.l[i]==value) {
+                return i;
+                }
+            }
+        return -1;
+        """)
+
+    def insert(self, index, value):
+        JS("""    var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
+
+    def pop(self, index = -1):
+        JS("""
+        if (index<0) index = this.l.length + index;
+        var a = this.l[index];
+        this.l.splice(index, 1);
+        return a;
+        """)
+
+    def __cmp__(self, l):
+        if not isinstance(l, List):
+            return -1
+        ll = len(self) - len(l)
+        if ll != 0:
+            return ll
+        for x in range(len(l)):
+            ll = cmp(self.__getitem__(x), l[x])
+            if ll != 0:
+                return ll
+        return 0
+
+    def slice(self, lower, upper):
+        JS("""
+        if (upper==null) return pyjslib.List(this.l.slice(lower));
+        return pyjslib.List(this.l.slice(lower, upper));
+        """)
+
+    def __getitem__(self, index):
+        JS("""
+        if (index<0) index = this.l.length + index;
+        return this.l[index];
+        """)
+
+    def __setitem__(self, index, value):
+        JS("""    this.l[index]=value;""")
+
+    def __delitem__(self, index):
+        JS("""    this.l.splice(index, 1);""")
+
+    def __len__(self):
+        JS("""    return this.l.length;""")
+
+    def __contains__(self, value):
+        return self.index(value) >= 0
+
+    def __iter__(self):
+        JS("""
+        var i = 0;
+        var l = this.l;
+        return {
+            'next': function() {
+                if (i >= l.length) {
+                    throw pyjslib.StopIteration;
+                }
+                return l[i++];
+            },
+            '__iter__': function() {
+                return this;
+            }
+        };
+        """)
+
+    def reverse(self):
+        JS("""    this.l.reverse();""")
+
+    def sort(self, compareFunc=None, keyFunc=None, reverse=False):
+        if not compareFunc:
+            global cmp
+            compareFunc = cmp
+        if keyFunc and reverse:
+            def thisSort1(a,b):
+                return -compareFunc(keyFunc(a), keyFunc(b))
+            self.l.sort(thisSort1)
+        elif keyFunc:
+            def thisSort2(a,b):
+                return compareFunc(keyFunc(a), keyFunc(b))
+            self.l.sort(thisSort2)
+        elif reverse:
+            def thisSort3(a,b):
+                return -compareFunc(a, b)
+            self.l.sort(thisSort3)
+        else:
+            self.l.sort(compareFunc)
+
+    def getArray(self):
+        """
+        Access the javascript Array that is used internally by this list
+        """
+        return self.l
+
+    def __str__(self):
+        return repr(self)
+
+list = List
+
+class Tuple:
+    def __init__(self, data=None):
+        JS("""
+        this.l = [];
+        this.extend(data);
+        """)
+
+    def append(self, item):
+        JS("""    this.l[this.l.length] = item;""")
+
+    def extend(self, data):
+        JS("""
+        if (pyjslib.isArray(data)) {
+            n = this.l.length;
+            for (var i=0; i < data.length; i++) {
+                this.l[n+i]=data[i];
+                }
+            }
+        else if (pyjslib.isIteratable(data)) {
+            var iter=data.__iter__();
+            var i=this.l.length;
+            try {
+                while (true) {
+                    var item=iter.next();
+                    this.l[i++]=item;
+                    }
+                }
+            catch (e) {
+                if (e != pyjslib.StopIteration) throw e;
+                }
+            }
+        """)
+
+    def remove(self, value):
+        JS("""
+        var index=this.index(value);
+        if (index<0) return false;
+        this.l.splice(index, 1);
+        return true;
+        """)
+
+    def index(self, value, start=0):
+        JS("""
+        var length=this.l.length;
+        for (var i=start; i<length; i++) {
+            if (this.l[i]==value) {
+                return i;
+                }
+            }
+        return -1;
+        """)
+
+    def insert(self, index, value):
+        JS("""    var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
+
+    def pop(self, index = -1):
+        JS("""
+        if (index<0) index = this.l.length + index;
+        var a = this.l[index];
+        this.l.splice(index, 1);
+        return a;
+        """)
+
+    def __cmp__(self, l):
+        if not isinstance(l, Tuple):
+            return -1
+        ll = len(self) - len(l)
+        if ll != 0:
+            return ll
+        for x in range(len(l)):
+            ll = cmp(self.__getitem__(x), l[x])
+            if ll != 0:
+                return ll
+        return 0
+
+    def slice(self, lower, upper):
+        JS("""
+        if (upper==null) return pyjslib.Tuple(this.l.slice(lower));
+        return pyjslib.Tuple(this.l.slice(lower, upper));
+        """)
+
+    def __getitem__(self, index):
+        JS("""
+        if (index<0) index = this.l.length + index;
+        return this.l[index];
+        """)
+
+    def __setitem__(self, index, value):
+        JS("""    this.l[index]=value;""")
+
+    def __delitem__(self, index):
+        JS("""    this.l.splice(index, 1);""")
+
+    def __len__(self):
+        JS("""    return this.l.length;""")
+
+    def __contains__(self, value):
+        return self.index(value) >= 0
+
+    def __iter__(self):
+        JS("""
+        var i = 0;
+        var l = this.l;
+        return {
+            'next': function() {
+                if (i >= l.length) {
+                    throw pyjslib.StopIteration;
+                }
+                return l[i++];
+            },
+            '__iter__': function() {
+                return this;
+            }
+        };
+        """)
+
+    def reverse(self):
+        JS("""    this.l.reverse();""")
+
+    def sort(self, compareFunc=None, keyFunc=None, reverse=False):
+        if not compareFunc:
+            global cmp
+            compareFunc = cmp
+        if keyFunc and reverse:
+            def thisSort1(a,b):
+                return -compareFunc(keyFunc(a), keyFunc(b))
+            self.l.sort(thisSort1)
+        elif keyFunc:
+            def thisSort2(a,b):
+                return compareFunc(keyFunc(a), keyFunc(b))
+            self.l.sort(thisSort2)
+        elif reverse:
+            def thisSort3(a,b):
+                return -compareFunc(a, b)
+            self.l.sort(thisSort3)
+        else:
+            self.l.sort(compareFunc)
+
+    def getArray(self):
+        """
+        Access the javascript Array that is used internally by this list
+        """
+        return self.l
+
+    def __str__(self):
+        return repr(self)
+
+tuple = Tuple
+
+
+class Dict:
+    def __init__(self, data=None):
+        JS("""
+        this.d = {};
+
+        if (pyjslib.isArray(data)) {
+            for (var i in data) {
+                var item=data[i];
+                this.__setitem__(item[0], item[1]);
+                //var sKey=pyjslib.hash(item[0]);
+                //this.d[sKey]=item[1];
+                }
+            }
+        else if (pyjslib.isIteratable(data)) {
+            var iter=data.__iter__();
+            try {
+                while (true) {
+                    var item=iter.next();
+                    this.__setitem__(item.__getitem__(0), item.__getitem__(1));
+                    }
+                }
+            catch (e) {
+                if (e != pyjslib.StopIteration) throw e;
+                }
+            }
+        else if (pyjslib.isObject(data)) {
+            for (var key in data) {
+                this.__setitem__(key, data[key]);
+                }
+            }
+        """)
+
+    def __setitem__(self, key, value):
+        JS("""
+        var sKey = pyjslib.hash(key);
+        this.d[sKey]=[key, value];
+        """)
+
+    def __getitem__(self, key):
+        JS("""
+        var sKey = pyjslib.hash(key);
+        var value=this.d[sKey];
+        if (pyjslib.isUndefined(value)){
+            throw pyjslib.KeyError(key);
+        }
+        return value[1];
+        """)
+
+    def __nonzero__(self):
+        JS("""
+        for (var i in this.d){
+            return true;
+        }
+        return false;
+        """)
+
+    def __len__(self):
+        JS("""
+        var size=0;
+        for (var i in this.d) size++;
+        return size;
+        """)
+
+    def has_key(self, key):
+        return self.__contains__(key)
+
+    def __delitem__(self, key):
+        JS("""
+        var sKey = pyjslib.hash(key);
+        delete this.d[sKey];
+        """)
+
+    def __contains__(self, key):
+        JS("""
+        var sKey = pyjslib.hash(key);
+        return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
+        """)
+
+    def keys(self):
+        JS("""
+        var keys=new pyjslib.List();
+        for (var key in this.d) {
+            keys.append(this.d[key][0]);
+        }
+        return keys;
+        """)
+
+    def values(self):
+        JS("""
+        var values=new pyjslib.List();
+        for (var key in this.d) values.append(this.d[key][1]);
+        return values;
+        """)
+
+    def items(self):
+        JS("""
+        var items = new pyjslib.List();
+        for (var key in this.d) {
+          var kv = this.d[key];
+          items.append(new pyjslib.List(kv))
+          }
+          return items;
+        """)
+
+    def __iter__(self):
+        return self.keys().__iter__()
+
+    def iterkeys(self):
+        return self.__iter__()
+
+    def itervalues(self):
+        return self.values().__iter__();
+
+    def iteritems(self):
+        return self.items().__iter__();
+
+    def setdefault(self, key, default_value):
+        if not self.has_key(key):
+            self[key] = default_value
+
+    def get(self, key, default_=None):
+        if not self.has_key(key):
+            return default_
+        return self[key]
+
+    def update(self, d):
+        for k,v in d.iteritems():
+            self[k] = v
+
+    def getObject(self):
+        """
+        Return the javascript Object which this class uses to store
+        dictionary keys and values
+        """
+        return self.d
+
+    def copy(self):
+        return Dict(self.items())
+
+    def __str__(self):
+        return repr(self)
+
+dict = Dict
+
+# taken from mochikit: range( [start,] stop[, step] )
+def range():
+    JS("""
+    var start = 0;
+    var stop = 0;
+    var step = 1;
+
+    if (arguments.length == 2) {
+        start = arguments[0];
+        stop = arguments[1];
+        }
+    else if (arguments.length == 3) {
+        start = arguments[0];
+        stop = arguments[1];
+        step = arguments[2];
+        }
+    else if (arguments.length>0) stop = arguments[0];
+
+    return {
+        'next': function() {
+            if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
+            var rval = start;
+            start += step;
+            return rval;
+            },
+        '__iter__': function() {
+            return this;
+            }
+        }
+    """)
+
+def slice(object, lower, upper):
+    JS("""
+    if (pyjslib.isString(object)) {
+        if (lower < 0) {
+           lower = object.length + lower;
+        }
+        if (upper < 0) {
+           upper = object.length + upper;
+        }
+        if (pyjslib.isNull(upper)) upper=object.length;
+        return object.substring(lower, upper);
+    }
+    if (pyjslib.isObject(object) && object.slice)
+        return object.slice(lower, upper);
+
+    return null;
+    """)
+
+def str(text):
+    JS("""
+    if (pyjslib.hasattr(text,"__str__")) {
+        return text.__str__();
+    }
+    return String(text);
+    """)
+
+def ord(x):
+    if(isString(x) and len(x) is 1):
+        JS("""
+            return x.charCodeAt(0);
+        """)
+    else:
+        JS("""
+            throw pyjslib.TypeError();
+        """)
+    return None
+
+def chr(x):
+    JS("""
+        return String.fromCharCode(x)
+    """)
+
+def is_basetype(x):
+    JS("""
+       var t = typeof(x);
+       return t == 'boolean' ||
+       t == 'function' ||
+       t == 'number' ||
+       t == 'string' ||
+       t == 'undefined'
+       ;
+    """)
+
+def get_pyjs_classtype(x):
+    JS("""
+       if (pyjslib.hasattr(x, "__class__"))
+           if (pyjslib.hasattr(x.__class__, "__new__"))
+               var src = x.__class__.__name__;
+               return src;
+       return null;
+    """)
+
+def repr(x):
+    """ Return the string representation of 'x'.
+    """
+    JS("""
+       if (x === null)
+           return "null";
+
+       if (x === undefined)
+           return "undefined";
+
+       var t = typeof(x);
+
+        //alert("repr typeof " + t + " : " + x);
+
+       if (t == "boolean")
+           return x.toString();
+
+       if (t == "function")
+           return "<function " + x.toString() + ">";
+
+       if (t == "number")
+           return x.toString();
+
+       if (t == "string") {
+           if (x.indexOf("'") == -1)
+               return "'" + x + "'";
+           if (x.indexOf('"') == -1)
+               return '"' + x + '"';
+           var s = x.replace(new RegExp('"', "g"), '\\\\"');
+           return '"' + s + '"';
+       };
+
+       if (t == "undefined")
+           return "undefined";
+
+       // If we get here, x is an object.  See if it's a Pyjamas class.
+
+       if (!pyjslib.hasattr(x, "__init__"))
+           return "<" + x.toString() + ">";
+
+       // Handle the common Pyjamas data types.
+
+       var constructor = "UNKNOWN";
+
+       constructor = pyjslib.get_pyjs_classtype(x);
+
+        //alert("repr constructor: " + constructor);
+
+       if (constructor == "Tuple") {
+           var contents = x.getArray();
+           var s = "(";
+           for (var i=0; i < contents.length; i++) {
+               s += pyjslib.repr(contents[i]);
+               if (i < contents.length - 1)
+                   s += ", ";
+           };
+           s += ")"
+           return s;
+       };
+
+       if (constructor == "List") {
+           var contents = x.getArray();
+           var s = "[";
+           for (var i=0; i < contents.length; i++) {
+               s += pyjslib.repr(contents[i]);
+               if (i < contents.length - 1)
+                   s += ", ";
+           };
+           s += "]"
+           return s;
+       };
+
+       if (constructor == "Dict") {
+           var keys = new Array();
+           for (var key in x.d)
+               keys.push(key);
+
+           var s = "{";
+           for (var i=0; i<keys.length; i++) {
+               var key = keys[i]
+               s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]);
+               if (i < keys.length-1)
+                   s += ", "
+           };
+           s += "}";
+           return s;
+       };
+
+       // If we get here, the class isn't one we know -> return the class name.
+       // Note that we replace underscores with dots so that the name will
+       // (hopefully!) look like the original Python name.
+
+       //var s = constructor.replace(new RegExp('_', "g"), '.');
+       return "<" + constructor + " object>";
+    """)
+
+def float(text):
+    JS("""
+    return parseFloat(text);
+    """)
+
+def int(text, radix=0):
+    JS("""
+    return parseInt(text, radix);
+    """)
+
+def len(object):
+    JS("""
+    if (object==null) return 0;
+    if (pyjslib.isObject(object) && object.__len__) return object.__len__();
+    return object.length;
+    """)
+
+def isinstance(object_, classinfo):
+    if pyjslib.isUndefined(object_):
+        return False
+    if not pyjslib.isObject(object_):
+        
+        return False
+    if _isinstance(classinfo, Tuple):
+        for ci in classinfo:
+            if isinstance(object_, ci):
+                return True
+        return False
+    else:
+        return _isinstance(object_, classinfo)
+
+def _isinstance(object_, classinfo):
+    if not pyjslib.isObject(object_):
+        return False
+    JS("""
+    if (object_.__class__){
+        var res =  object_ instanceof classinfo.constructor;
+        return res;
+    }
+    return false;
+    """)
+
+def getattr(obj, name, default_):
+    JS("""
+    if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
+        if (pyjslib.isUndefined(default_)){
+            throw pyjslib.AttributeError(obj, name);
+        }else{
+        return default_;
+        }
+    }
+    if (!pyjslib.isFunction(obj[name])) return obj[name];
+    var fnwrap = function() {
+        var args = [];
+        for (var i = 0; i < arguments.length; i++) {
+          args.push(arguments[i]);
+        }
+        return obj[name].apply(obj,args);
+        }
+    fnwrap.__name__ = name;
+    return fnwrap;
+    """)
+
+def setattr(obj, name, value):
+    JS("""
+    if (!pyjslib.isObject(obj)) return null;
+
+    obj[name] = value;
+
+    """)
+
+def hasattr(obj, name):
+    JS("""
+    if (!pyjslib.isObject(obj)) return false;
+    if (pyjslib.isUndefined(obj[name])) return false;
+
+    return true;
+    """)
+
+def dir(obj):
+    JS("""
+    var properties=new pyjslib.List();
+    for (property in obj) properties.append(property);
+    return properties;
+    """)
+
+def filter(obj, method, sequence=None):
+    # object context is LOST when a method is passed, hence object must be passed separately
+    # to emulate python behaviour, should generate this code inline rather than as a function call
+    items = []
+    if sequence is None:
+        sequence = method
+        method = obj
+
+        for item in sequence:
+            if method(item):
+                items.append(item)
+    else:
+        for item in sequence:
+            if method.call(obj, item):
+                items.append(item)
+
+    return items
+
+
+def map(obj, method, sequence=None):
+    items = []
+
+    if sequence is None:
+        sequence = method
+        method = obj
+
+        for item in sequence:
+            items.append(method(item))
+    else:
+        for item in sequence:
+            items.append(method.call(obj, item))
+
+    return items
+
+
+def enumerate(sequence):
+    enumeration = []
+    nextIndex = 0
+    for item in sequence:
+        enumeration.append([nextIndex, item])
+        nextIndex = nextIndex + 1
+    return enumeration
+
+
+def min(*sequence):
+    minValue = None
+    for item in sequence:
+        if minValue is None:
+            minValue = item
+        elif item < minValue:
+            minValue = item
+    return minValue
+
+
+def max(*sequence):
+    maxValue = None
+    for item in sequence:
+        if maxValue is None:
+            maxValue = item
+        elif item > maxValue:
+            maxValue = item
+    return maxValue
+
+
+next_hash_id = 0
+
+def hash(obj):
+    JS("""
+    if (obj == null) return null;
+
+    if (obj.$H) return obj.$H;
+    if (obj.__hash__) return obj.__hash__();
+    if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
+
+    obj.$H = ++pyjslib.next_hash_id;
+    return obj.$H;
+    """)
+
+
+# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
+def isObject(a):
+    JS("""
+    return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
+    """)
+
+def isFunction(a):
+    JS("""
+    return typeof a == 'function';
+    """)
+
+def isString(a):
+    JS("""
+    return typeof a == 'string';
+    """)
+
+def isNull(a):
+    JS("""
+    return typeof a == 'object' && !a;
+    """)
+
+def isArray(a):
+    JS("""
+    return pyjslib.isObject(a) && a.constructor == Array;
+    """)
+
+def isUndefined(a):
+    JS("""
+    return typeof a == 'undefined';
+    """)
+
+def isIteratable(a):
+    JS("""
+    return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
+    """)
+
+def isNumber(a):
+    JS("""
+    return typeof a == 'number' && isFinite(a);
+    """)
+
+def toJSObjects(x):
+    """
+       Convert the pyjs pythonic List and Dict objects into javascript Object and Array
+       objects, recursively.
+    """
+    if isArray(x):
+        JS("""
+        var result = [];
+        for(var k=0; k < x.length; k++) {
+           var v = x[k];
+           var tv = pyjslib.toJSObjects(v);
+           result.push(tv);
+        }
+        return result;
+        """)
+    if isObject(x):
+        if isinstance(x, Dict):
+            JS("""
+            var o = x.getObject();
+            var result = {};
+            for (var i in o) {
+               result[o[i][0].toString()] = o[i][1];
+            }
+            return pyjslib.toJSObjects(result)
+            """)
+        elif isinstance(x, List):
+            return toJSObjects(x.l)
+        elif hasattr(x, '__class__'):
+            # we do not have a special implementation for custom
+            # classes, just pass it on
+            return x
+    if isObject(x):
+        JS("""
+        var result = {};
+        for(var k in x) {
+            var v = x[k];
+            var tv = pyjslib.toJSObjects(v)
+            result[k] = tv;
+            }
+            return result;
+         """)
+    return x
+
+def printFunc(objs):
+    JS("""
+    if ($wnd.console==undefined)  return;
+    var s = "";
+    for(var i=0; i < objs.length; i++) {
+        if(s != "") s += " ";
+        s += objs[i];
+    }
+    console.debug(s)
+    """)
+
+def type(clsname, bases=None, methods=None):
+    """ creates a class, derived from bases, with methods and variables
+    """
+
+    JS(" var mths = {}; ")
+    if methods:
+        for k in methods.keys():
+            mth = methods[k]
+            JS(" mths[k] = mth; ")
+
+    JS(" var bss = null; ")
+    if bases:
+        JS("bss = bases.l;")
+    JS(" return pyjs_type(clsname, bss, mths); ")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/lib/sys.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,59 @@
+# the platform name (PyV8, smjs, Mozilla, IE6, Opera, Safari etc.)
+platform = '' # to be updated by app, on compile
+
+# a dictionary of module override names (platform-specific)
+overrides = None # to be updated by app, on compile
+
+# the remote path for loading modules
+loadpath = None 
+
+stacktrace = None 
+
+appname = None 
+
+def setloadpath(lp):
+    global loadpath
+    loadpath = lp
+
+def setappname(an):
+    global appname
+    appname = an
+
+def getloadpath():
+    global loadpath
+    return loadpath
+
+def addoverride(module_name, path):
+    global overrides
+    overrides[module_name] = path
+
+def addstack(linedebug):
+    JS("""
+        if (pyjslib.bool((sys.stacktrace === null))) {
+            sys.stacktrace = new pyjslib.List([]);
+        }
+        sys.stacktrace.append(linedebug);
+    """)
+def popstack():
+    JS("""
+        sys.stacktrace.pop()
+    """)
+
+def printstack():
+    JS("""
+        var res = '';
+
+        var __l = sys.stacktrace.__iter__();
+        try {
+            while (true) {
+                var l = __l.next();
+                res +=  ( l + '\\n' ) ;
+            }
+        } catch (e) {
+            if (e != pyjslib.StopIteration) {
+                throw e;
+            }
+        }
+
+        return res;
+    """)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/pyjs/pyjs.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1777 @@
+#!/usr/bin/env python
+# Copyright 2006 James Tauber and contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import sys
+from types import StringType
+import compiler
+from compiler import ast
+import os
+import copy
+
+# the standard location for builtins (e.g. pyjslib) can be
+# over-ridden by changing this.  it defaults to sys.prefix
+# so that on a system-wide install of pyjamas the builtins
+# can be found in e.g. {sys.prefix}/share/pyjamas
+#
+# over-rides can be done by either explicitly modifying
+# pyjs.prefix or by setting an environment variable, PYJSPREFIX.
+
+prefix = sys.prefix
+
+if os.environ.has_key('PYJSPREFIX'):
+    prefix = os.environ['PYJSPREFIX']
+
+# pyjs.path is the list of paths, just like sys.path, from which
+# library modules will be searched for, for compile purposes.
+# obviously we don't want to use sys.path because that would result
+# in compiling standard python modules into javascript!
+
+path = [os.path.abspath('')]
+
+if os.environ.has_key('PYJSPATH'):
+    for p in os.environ['PYJSPATH'].split(os.pathsep):
+        p = os.path.abspath(p)
+        if os.path.isdir(p):
+            path.append(p)
+
+# this is the python function used to wrap native javascript
+NATIVE_JS_FUNC_NAME = "JS"
+
+UU = ""
+
+PYJSLIB_BUILTIN_FUNCTIONS=("cmp",
+                           "map",
+                           "filter",
+                           "dir",
+                           "getattr",
+                           "setattr",
+                           "hasattr",
+                           "int",
+                           "float",
+                           "str",
+                           "repr",
+                           "range",
+                           "len",
+                           "hash",
+                           "abs",
+                           "ord",
+                           "chr",
+                           "enumerate",
+                           "min",
+                           "max",
+                           "bool",
+                           "type",
+                           "isinstance")
+
+PYJSLIB_BUILTIN_CLASSES=("BaseException",
+                         "Exception",
+                         "StandardError",
+                         "StopIteration",
+                         "AttributeError",
+                         "TypeError",
+                         "KeyError",
+                         "LookupError",
+                         "list",
+                         "dict",
+                         "object",
+                         "tuple",
+                        )
+
+def pyjs_builtin_remap(name):
+    # XXX HACK!
+    if name == 'list':
+        name = 'List'
+    if name == 'object':
+        name = '__Object'
+    if name == 'dict':
+        name = 'Dict'
+    if name == 'tuple':
+        name = 'Tuple'
+    return name
+
+# XXX: this is a hack: these should be dealt with another way
+# however, console is currently the only global name which is causing
+# problems.
+PYJS_GLOBAL_VARS=("console")
+
+# This is taken from the django project.
+# Escape every ASCII character with a value less than 32.
+JS_ESCAPES = (
+    ('\\', r'\x5C'),
+    ('\'', r'\x27'),
+    ('"', r'\x22'),
+    ('>', r'\x3E'),
+    ('<', r'\x3C'),
+    ('&', r'\x26'),
+    (';', r'\x3B')
+    ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)])
+
+def escapejs(value):
+    """Hex encodes characters for use in JavaScript strings."""
+    for bad, good in JS_ESCAPES:
+        value = value.replace(bad, good)
+    return value
+
+def uuprefix(name, leave_alone=0):
+    name = name.split(".")
+    name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:])
+    return '.'.join(name)
+
+class Klass:
+
+    klasses = {}
+
+    def __init__(self, name, name_):
+        self.name = name
+        self.name_ = name_
+        self.klasses[name] = self
+        self.functions = set()
+
+    def set_base(self, base_name):
+        self.base = self.klasses.get(base_name)
+
+    def add_function(self, function_name):
+        self.functions.add(function_name)
+
+
+class TranslationError(Exception):
+    def __init__(self, message, node):
+        self.message = "line %s:\n%s\n%s" % (node.lineno, message, node)
+
+    def __str__(self):
+        return self.message
+
+def strip_py(name):
+    return name
+
+def mod_var_name_decl(raw_module_name):
+    """ function to get the last component of the module e.g.
+        pyjamas.ui.DOM into the "namespace".  i.e. doing
+        "import pyjamas.ui.DOM" actually ends up with _two_
+        variables - one pyjamas.ui.DOM, the other just "DOM".
+        but "DOM" is actually local, hence the "var" prefix.
+
+        for PyV8, this might end up causing problems - we'll have
+        to see: gen_mod_import and mod_var_name_decl might have
+        to end up in a library-specific module, somewhere.
+    """
+    name = raw_module_name.split(".")
+    if len(name) == 1:
+        return ''
+    child_name = name[-1]
+    return "var %s = %s;\n" % (child_name, raw_module_name)
+
+def gen_mod_import(parentName, importName, dynamic=1):
+    #pyjs_ajax_eval("%(n)s.cache.js", null, true);
+    return """
+    pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false);
+    """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \
+    mod_var_name_decl(importName)
+
+class Translator:
+
+    def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output,
+                 dynamic=0, optimize=False,
+                 findFile=None):
+
+        if module_name:
+            self.module_prefix = module_name + "."
+        else:
+            self.module_prefix = ""
+        self.raw_module_name = raw_module_name
+        src = src.replace("\r\n", "\n")
+        src = src.replace("\n\r", "\n")
+        src = src.replace("\r",   "\n")
+        self.src = src.split("\n")
+        self.debug = debug
+        self.imported_modules = []
+        self.imported_modules_as = []
+        self.imported_js = set()
+        self.top_level_functions = set()
+        self.top_level_classes = set()
+        self.top_level_vars = set()
+        self.local_arg_stack = [[]]
+        self.output = output
+        self.imported_classes = {}
+        self.method_imported_globals = set()
+        self.method_self = None
+        self.nextTupleAssignID = 1
+        self.dynamic = dynamic
+        self.optimize = optimize
+        self.findFile = findFile
+
+        if module_name.find(".") >= 0:
+            vdec = ''
+        else:
+            vdec = 'var '
+        print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name)
+
+        print >>self.output, "    if("+module_name+".__was_initialized__) return;"
+        print >>self.output, "    "+UU+module_name+".__was_initialized__ = true;"
+        print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn)
+        print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name)
+
+        decl = mod_var_name_decl(raw_module_name)
+        if decl:
+            print >>self.output, decl
+
+
+        if self.debug:
+            haltException = self.module_prefix + "HaltException"
+            print >>self.output, haltException + ' = function () {'
+            print >>self.output, '  this.message = "Program Halted";'
+            print >>self.output, '  this.name = "' + haltException + '";'
+            print >>self.output, '}'
+            print >>self.output, ''
+            print >>self.output, haltException + ".prototype.__str__ = function()"
+            print >>self.output, '{'
+            print >>self.output, 'return this.message ;'
+            print >>self.output, '}'
+
+            print >>self.output, haltException + ".prototype.toString = function()"
+            print >>self.output, '{'
+            print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";'
+            print >>self.output, '}'
+
+            isHaltFunction = self.module_prefix + "IsHaltException"
+            print >>self.output, """
+    %s = function (s) {
+      var suffix="HaltException";
+      if (s.length < suffix.length) {
+        //alert(s + " " + suffix);
+        return false;
+      } else {
+        var ss = s.substring(s.length, (s.length - suffix.length));
+        //alert(s + " " + suffix + " " + ss);
+        return ss == suffix;
+      }
+    }
+                """ % isHaltFunction
+        for child in mod.node:
+            if isinstance(child, ast.Function):
+                self.top_level_functions.add(child.name)
+            elif isinstance(child, ast.Class):
+                self.top_level_classes.add(child.name)
+
+        for child in mod.node:
+            if isinstance(child, ast.Function):
+                self._function(child, False)
+            elif isinstance(child, ast.Class):
+                self._class(child)
+            elif isinstance(child, ast.Import):
+                importName = child.names[0][0]
+                if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
+                    pass
+                elif importName.endswith('.js'):
+                   self.imported_js.add(importName)
+                else:
+                   self.add_imported_module(strip_py(importName))
+            elif isinstance(child, ast.From):
+                if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
+                    pass
+                else:
+                    self.add_imported_module(child.modname)
+                    self._from(child)
+            elif isinstance(child, ast.Discard):
+                self._discard(child, None)
+            elif isinstance(child, ast.Assign):
+                self._assign(child, None, True)
+            elif isinstance(child, ast.AugAssign):
+                self._augassign(child, None)
+            elif isinstance(child, ast.If):
+                self._if(child, None)
+            elif isinstance(child, ast.For):
+                self._for(child, None)
+            elif isinstance(child, ast.While):
+                self._while(child, None)
+            elif isinstance(child, ast.Subscript):
+                self._subscript_stmt(child, None)
+            elif isinstance(child, ast.Global):
+                self._global(child, None)
+            elif isinstance(child, ast.Printnl):
+               self._print(child, None)
+            elif isinstance(child, ast.Print):
+               self._print(child, None)
+            elif isinstance(child, ast.TryExcept):
+                self._tryExcept(child, None)
+            elif isinstance(child, ast.Raise):
+                self._raise(child, None)
+            elif isinstance(child, ast.Stmt):
+                self._stmt(child, None)
+            else:
+                raise TranslationError("unsupported type (in __init__)", child)
+
+        # Initialize all classes for this module
+        #print >> self.output, "__"+self.modpfx()+\
+        #          "classes_initialize = function() {\n"
+        #for className in self.top_level_classes:
+        #    print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();"
+        #print >> self.output, "};\n"
+
+        print >> self.output, "return this;\n"
+        print >> self.output, "}; /* end %s */ \n"  % module_name
+
+    def module_imports(self):
+        return self.imported_modules + self.imported_modules_as
+
+    def add_local_arg(self, varname):
+        local_vars = self.local_arg_stack[-1]
+        if varname not in local_vars:
+            local_vars.append(varname)
+
+    def add_imported_module(self, importName):
+
+        if importName in self.imported_modules:
+            return
+        self.imported_modules.append(importName)
+        name = importName.split(".")
+        if len(name) != 1:
+            # add the name of the module to the namespace,
+            # but don't add the short name to imported_modules
+            # because then the short name would be attempted to be
+            # added to the dependencies, and it's half way up the
+            # module import directory structure!
+            child_name = name[-1]
+            self.imported_modules_as.append(child_name) 
+        print >> self.output, gen_mod_import(self.raw_module_name,
+                                             strip_py(importName),
+                                             self.dynamic)
+
+    def _default_args_handler(self, node, arg_names, current_klass,
+                              output=None):
+        if len(node.defaults):
+            output = output or self.output
+            default_pos = len(arg_names) - len(node.defaults)
+            if arg_names and arg_names[0] == self.method_self:
+                default_pos -= 1
+            for default_node in node.defaults:
+                if isinstance(default_node, ast.Const):
+                    default_value = self._const(default_node)
+                elif isinstance(default_node, ast.Name):
+                    default_value = self._name(default_node, current_klass)
+                elif isinstance(default_node, ast.UnarySub):
+                    default_value = self._unarysub(default_node, current_klass)
+                else:
+                    raise TranslationError("unsupported type (in _method)", default_node)
+
+                default_name = arg_names[default_pos]
+                default_pos += 1
+                print >> output, "    if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value)
+
+    def _varargs_handler(self, node, varargname, arg_names, current_klass):
+        print >>self.output, "    var", varargname, '= new pyjslib.Tuple();'
+        print >>self.output, "    for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {"
+        print >>self.output, "        var __arg = arguments[__va_arg];"
+        print >>self.output, "        "+varargname+".append(__arg);"
+        print >>self.output, "    }"
+
+    def _kwargs_parser(self, node, function_name, arg_names, current_klass):
+        if len(node.defaults) or node.kwargs:
+            default_pos = len(arg_names) - len(node.defaults)
+            if arg_names and arg_names[0] == self.method_self:
+                default_pos -= 1
+            print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {"
+            for default_node in node.defaults:
+                default_value = self.expr(default_node, current_klass)
+#                if isinstance(default_node, ast.Const):
+#                    default_value = self._const(default_node)
+#                elif isinstance(default_node, ast.Name):
+#                    default_value = self._name(default_node)
+#                elif isinstance(default_node, ast.UnarySub):
+#                    default_value = self._unarysub(default_node, current_klass)
+#                else:
+#                    raise TranslationError("unsupported type (in _method)", default_node)
+
+                default_name = arg_names[default_pos]
+                print >>self.output, "    if (typeof %s == 'undefined')"%(default_name)
+                print >>self.output, "        %s=__kwargs.%s;"% (default_name, default_name)
+                default_pos += 1
+
+            #self._default_args_handler(node, arg_names, current_klass)
+            if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"]
+            print >>self.output, "    var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";"
+            if node.varargs:
+                self._varargs_handler(node, "__args", arg_names, current_klass)
+                print >>self.output, "    __r.push.apply(__r, __args.getArray())"
+            print >>self.output, "    return __r;"
+            print >>self.output, "};"
+
+    def _function(self, node, local=False):
+        if local:
+            function_name = node.name
+            self.add_local_arg(function_name)
+        else:
+            function_name = UU + self.modpfx() + node.name
+
+        arg_names = list(node.argnames)
+        normal_arg_names = list(arg_names)
+        if node.kwargs: kwargname = normal_arg_names.pop()
+        if node.varargs: varargname = normal_arg_names.pop()
+        declared_arg_names = list(normal_arg_names)
+        if node.kwargs: declared_arg_names.append(kwargname)
+
+        function_args = "(" + ", ".join(declared_arg_names) + ")"
+        print >>self.output, "%s = function%s {" % (function_name, function_args)
+        self._default_args_handler(node, normal_arg_names, None)
+
+        local_arg_names = normal_arg_names + declared_arg_names 
+
+        if node.varargs:
+            self._varargs_handler(node, varargname, declared_arg_names, None)
+            local_arg_names.append(varargname)
+
+        # stack of local variable names for this function call
+        self.local_arg_stack.append(local_arg_names)
+
+        for child in node.code:
+            self._stmt(child, None)
+
+        # remove the top local arg names
+        self.local_arg_stack.pop()
+
+        # we need to return null always, so it is not undefined
+        lastStmt = [p for p in node.code][-1]
+        if not isinstance(lastStmt, ast.Return):
+            if not self._isNativeFunc(lastStmt):
+                print >>self.output, "    return null;"
+
+        print >>self.output, "};"
+        print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name)
+
+
+        self._kwargs_parser(node, function_name, normal_arg_names, None)
+
+
+    def _return(self, node, current_klass):
+        expr = self.expr(node.value, current_klass)
+        # in python a function call always returns None, so we do it
+        # here too
+        print >>self.output, "    return " + expr + ";"
+
+
+    def _break(self, node, current_klass):
+        print >>self.output, "    break;"
+
+
+    def _continue(self, node, current_klass):
+        print >>self.output, "    continue;"
+
+
+    def _callfunc(self, v, current_klass):
+
+        if isinstance(v.node, ast.Name):
+            if v.node.name in self.top_level_functions:
+                call_name = self.modpfx() + v.node.name
+            elif v.node.name in self.top_level_classes:
+                call_name = self.modpfx() + v.node.name
+            elif self.imported_classes.has_key(v.node.name):
+                call_name = self.imported_classes[v.node.name] + '.' + v.node.name
+            elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS:
+                call_name = 'pyjslib.' + v.node.name
+            elif v.node.name in PYJSLIB_BUILTIN_CLASSES:
+                name = pyjs_builtin_remap(v.node.name)
+                call_name = 'pyjslib.' + name
+            elif v.node.name == "callable":
+                call_name = "pyjslib.isFunction"
+            else:
+                call_name = v.node.name
+            call_args = []
+        elif isinstance(v.node, ast.Getattr):
+            attr_name = v.node.attrname
+
+            if isinstance(v.node.expr, ast.Name):
+                call_name = self._name2(v.node.expr, current_klass, attr_name)
+                call_args = []
+            elif isinstance(v.node.expr, ast.Getattr):
+                call_name = self._getattr2(v.node.expr, current_klass, attr_name)
+                call_args = []
+            elif isinstance(v.node.expr, ast.CallFunc):
+                call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname
+                call_args = []
+            elif isinstance(v.node.expr, ast.Subscript):
+                call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname
+                call_args = []
+            elif isinstance(v.node.expr, ast.Const):
+                call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname
+                call_args = []
+            else:
+                raise TranslationError("unsupported type (in _callfunc)", v.node.expr)
+        else:
+            raise TranslationError("unsupported type (in _callfunc)", v.node)
+
+        call_name = strip_py(call_name)
+
+        kwargs = []
+        star_arg_name = None
+        if v.star_args:
+            star_arg_name = self.expr(v.star_args, current_klass)
+
+        for ch4 in v.args:
+            if isinstance(ch4, ast.Keyword):
+                kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass)
+                kwargs.append(kwarg)
+            else:
+                arg = self.expr(ch4, current_klass)
+                call_args.append(arg)
+
+        if kwargs:
+            fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args)
+        else:
+            fn_args = ", ".join(call_args)
+
+        if kwargs or star_arg_name:
+            if not star_arg_name:
+                star_arg_name = 'null'
+            try: call_this, method_name = call_name.rsplit(".", 1)
+            except ValueError:
+                # Must be a function call ...
+                return ("pyjs_kwargs_function_call("+call_name+", "
+                                  + star_arg_name 
+                                  + ", ["+fn_args+"]"
+                                  + ")" )
+            else:
+                return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', "
+                                  + star_arg_name 
+                                  + ", ["+fn_args+"]"
+                                  + ")")
+        else:
+            return call_name + "(" + ", ".join(call_args) + ")"
+
+    def _print(self, node, current_klass):
+        if self.optimize:
+            return
+        call_args = []
+        for ch4 in node.nodes:
+            arg = self.expr(ch4, current_klass)
+            call_args.append(arg)
+
+        print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");"
+
+    def _tryExcept(self, node, current_klass):
+        if len(node.handlers) != 1:
+            raise TranslationError("except statements in this form are" +
+                                   " not supported", node)
+
+        expr = node.handlers[0][0]
+        as_ = node.handlers[0][1]
+        if as_:
+            errName = as_.name
+        else:
+            errName = 'err'
+
+        # XXX TODO: check that this should instead be added as a _separate_
+        # local scope, temporary to the function.  oh dearie me.
+        self.add_local_arg(errName)
+
+        print >>self.output, "    try {"
+        for stmt in node.body.nodes:
+            self._stmt(stmt, current_klass)
+        print >> self.output, "    } catch(%s) {" % errName
+        if expr:
+            l = []
+            if isinstance(expr, ast.Tuple):
+                for x in expr.nodes:
+                    l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass)))
+            else:
+                l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ]
+            print >> self.output, "   if(%s) {" % '||\n\t\t'.join(l)
+        for stmt in node.handlers[0][2]:
+            self._stmt(stmt, current_klass)
+        if expr:
+            #print >> self.output, "} else { throw(%s); } " % errName
+            print >> self.output, "}"
+        if node.else_ != None:
+            print >>self.output, "    } finally {"
+            for stmt in node.else_:
+                self._stmt(stmt, current_klass)
+        print >>self.output, "    }"
+
+    # XXX: change use_getattr to True to enable "strict" compilation
+    # but incurring a 100% performance penalty. oops.
+    def _getattr(self, v, current_klass, use_getattr=False):
+        attr_name = v.attrname
+        if isinstance(v.expr, ast.Name):
+            obj = self._name(v.expr, current_klass, return_none_for_module=True)
+            if obj == None and v.expr.name in self.module_imports():
+                # XXX TODO: distinguish between module import classes
+                # and variables.  right now, this is a hack to get
+                # the sys module working.
+                #if v.expr.name == 'sys':
+                return v.expr.name+'.'+attr_name
+                #return v.expr.name+'.__'+attr_name+'.prototype.__class__'
+            if not use_getattr or attr_name == '__class__' or \
+                    attr_name == '__name__':
+                return obj + "." + attr_name
+            return "pyjslib.getattr(%s, '%s')" % (obj, attr_name)
+        elif isinstance(v.expr, ast.Getattr):
+            return self._getattr(v.expr, current_klass) + "." + attr_name
+        elif isinstance(v.expr, ast.Subscript):
+            return self._subscript(v.expr, self.modpfx()) + "." + attr_name
+        elif isinstance(v.expr, ast.CallFunc):
+            return self._callfunc(v.expr, self.modpfx()) + "." + attr_name
+        else:
+            raise TranslationError("unsupported type (in _getattr)", v.expr)
+
+
+    def modpfx(self):
+        return strip_py(self.module_prefix)
+        
+    def _name(self, v, current_klass, top_level=False,
+                                      return_none_for_module=False):
+
+        if v.name == 'ilikesillynamesfornicedebugcode':
+            print top_level, current_klass, repr(v)
+            print self.top_level_vars
+            print self.top_level_functions
+            print self.local_arg_stack
+            print "error..."
+
+        local_var_names = None
+        las = len(self.local_arg_stack)
+        if las > 0:
+            local_var_names = self.local_arg_stack[-1]
+
+        if v.name == "True":
+            return "true"
+        elif v.name == "False":
+            return "false"
+        elif v.name == "None":
+            return "null"
+        elif v.name == '__name__' and current_klass is None:
+            return self.modpfx() + v.name
+        elif v.name == self.method_self:
+            return "this"
+        elif v.name in self.top_level_functions:
+            return UU+self.modpfx() + v.name
+        elif v.name in self.method_imported_globals:
+            return UU+self.modpfx() + v.name
+        elif not current_klass and las == 1 and v.name in self.top_level_vars:
+            return UU+self.modpfx() + v.name
+        elif v.name in local_var_names:
+            return v.name
+        elif self.imported_classes.has_key(v.name):
+            return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__"
+        elif v.name in self.top_level_classes:
+            return UU+self.modpfx() + "__" + v.name + ".prototype.__class__"
+        elif v.name in self.module_imports() and return_none_for_module:
+            return None
+        elif v.name in PYJSLIB_BUILTIN_CLASSES:
+            return "pyjslib." + pyjs_builtin_remap( v.name )
+        elif current_klass:
+            if v.name not in local_var_names and \
+               v.name not in self.top_level_vars and \
+               v.name not in PYJS_GLOBAL_VARS and \
+               v.name not in self.top_level_functions:
+
+                cls_name = current_klass
+                if hasattr(cls_name, "name"):
+                    cls_name_ = cls_name.name_
+                    cls_name = cls_name.name
+                else:
+                    cls_name_ = current_klass + "_" # XXX ???
+                name = UU+cls_name_ + ".prototype.__class__." \
+                                   + v.name
+                if v.name == 'listener':
+                    name = 'listener+' + name
+                return name
+
+        return v.name
+
+    def _name2(self, v, current_klass, attr_name):
+        obj = v.name
+
+        if obj in self.method_imported_globals:
+            call_name = UU+self.modpfx() + obj + "." + attr_name
+        elif self.imported_classes.has_key(obj):
+            #attr_str = ""
+            #if attr_name != "__init__":
+            attr_str = ".prototype.__class__." + attr_name
+            call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str
+        elif obj in self.module_imports():
+            call_name = obj + "." + attr_name
+        elif obj[0] == obj[0].upper(): # XXX HACK ALERT
+            call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name
+        else:
+            call_name = UU+self._name(v, current_klass) + "." + attr_name
+
+        return call_name
+
+
+    def _getattr2(self, v, current_klass, attr_name):
+        if isinstance(v.expr, ast.Getattr):
+            call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name)
+        elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports():
+            call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name
+        else:
+            obj = self.expr(v.expr, current_klass)
+            call_name = obj + "." + v.attrname + "." + attr_name
+
+        return call_name
+
+
+    def _class(self, node):
+        """
+        Handle a class definition.
+
+        In order to translate python semantics reasonably well, the following
+        structure is used:
+
+        A special object is created for the class, which inherits attributes
+        from the superclass, or Object if there's no superclass.  This is the
+        class object; the object which you refer to when specifying the
+        class by name.  Static, class, and unbound methods are copied
+        from the superclass object.
+
+        A special constructor function is created with the same name as the
+        class, which is used to create instances of that class.
+
+        A javascript class (e.g. a function with a prototype attribute) is
+        created which is the javascript class of created instances, and
+        which inherits attributes from the class object. Bound methods are
+        copied from the superclass into this class rather than inherited,
+        because the class object contains unbound, class, and static methods
+        that we don't necessarily want to inherit.
+
+        The type of a method can now be determined by inspecting its
+        static_method, unbound_method, class_method, or instance_method
+        attribute; only one of these should be true.
+
+        Much of this work is done in pyjs_extend, is pyjslib.py
+        """
+        class_name = self.modpfx() + uuprefix(node.name, 1)
+        class_name_ = self.modpfx() + uuprefix(node.name)
+        current_klass = Klass(class_name, class_name_)
+        init_method = None
+        for child in node.code:
+            if isinstance(child, ast.Function):
+                current_klass.add_function(child.name)
+                if child.name == "__init__":
+                    init_method = child
+
+
+        if len(node.bases) == 0:
+            base_class = "pyjslib.__Object"
+        elif len(node.bases) == 1:
+            if isinstance(node.bases[0], ast.Name):
+                if self.imported_classes.has_key(node.bases[0].name):
+                    base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name
+                    base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name
+                else:
+                    base_class_ = self.modpfx() + "__" + node.bases[0].name
+                    base_class = self.modpfx() + node.bases[0].name
+            elif isinstance(node.bases[0], ast.Getattr):
+                # the bases are not in scope of the class so do not
+                # pass our class to self._name
+                base_class_ = self._name(node.bases[0].expr, None) + \
+                             ".__" + node.bases[0].attrname
+                base_class = self._name(node.bases[0].expr, None) + \
+                             "." + node.bases[0].attrname
+            else:
+                raise TranslationError("unsupported type (in _class)", node.bases[0])
+
+            current_klass.set_base(base_class)
+        else:
+            raise TranslationError("more than one base (in _class)", node)
+
+        print >>self.output, UU+class_name_ + " = function () {"
+        # call superconstructor
+        #if base_class:
+        #    print >>self.output, "    __" + base_class + ".call(this);"
+        print >>self.output, "}"
+
+        if not init_method:
+            init_method = ast.Function([], "__init__", ["self"], [], 0, None, [])
+            #self._method(init_method, current_klass, class_name)
+
+        # Generate a function which constructs the object
+        clsfunc = ast.Function([],
+           node.name,
+           init_method.argnames[1:],
+           init_method.defaults,
+           init_method.flags,
+           None,
+           [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const(
+#            I attempted lazy initialization, but then you can't access static class members
+#            "    if(!__"+base_class+".__was_initialized__)"+
+#            "        __" + class_name + "_initialize();\n" +
+            "    var instance = new " + UU + class_name_ + "();\n" +
+            "    if(instance.__init__) instance.__init__.apply(instance, arguments);\n" +
+            "    return instance;"
+            )]))])
+
+        self._function(clsfunc, False)
+        print >>self.output, UU+class_name_ + ".__initialize__ = function () {"
+        print >>self.output, "    if("+UU+class_name_+".__was_initialized__) return;"
+        print >>self.output, "    "+UU+class_name_+".__was_initialized__ = true;"
+        cls_obj = UU+class_name_ + '.prototype.__class__'
+
+        if class_name == "pyjslib.__Object":
+            print >>self.output, "    "+cls_obj+" = {};"
+        else:
+            if base_class and base_class not in ("object", "pyjslib.__Object"):
+                print >>self.output, "    if(!"+UU+base_class_+".__was_initialized__)"
+                print >>self.output, "        "+UU+base_class_+".__initialize__();"
+                print >>self.output, "    pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");"
+            else:
+                print >>self.output, "    pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);"
+
+        print >>self.output, "    "+cls_obj+".__new__ = "+UU+class_name+";"
+        print >>self.output, "    "+cls_obj+".__name__ = '"+UU+node.name+"';"
+
+        for child in node.code:
+            if isinstance(child, ast.Pass):
+                pass
+            elif isinstance(child, ast.Function):
+                self._method(child, current_klass, class_name, class_name_)
+            elif isinstance(child, ast.Assign):
+                self.classattr(child, current_klass)
+            elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const):
+                # Probably a docstring, turf it
+                pass
+            else:
+                raise TranslationError("unsupported type (in _class)", child)
+        print >>self.output, "}"
+
+        print >> self.output, class_name_+".__initialize__();"
+
+
+    def classattr(self, node, current_klass):
+        self._assign(node, current_klass, True)
+
+    def _raise(self, node, current_klass):
+        if node.expr2:
+            raise TranslationError("More than one expression unsupported",
+                                   node)
+        print >> self.output, "throw (%s);" % self.expr(
+            node.expr1, current_klass)
+
+    def _method(self, node, current_klass, class_name, class_name_):
+        # reset global var scope
+        self.method_imported_globals = set()
+
+        arg_names = list(node.argnames)
+
+        classmethod = False
+        staticmethod = False
+        if node.decorators:
+            for d in node.decorators:
+                if d.name == "classmethod":
+                    classmethod = True
+                elif d.name == "staticmethod":
+                    staticmethod = True
+
+        if staticmethod:
+            staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno)
+            self._function(staticfunc, True)
+            print >>self.output, "    " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";";
+            print >>self.output, "    " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;";
+            return
+        else:
+            if len(arg_names) == 0:
+                raise TranslationError("methods must take an argument 'self' (in _method)", node)
+            self.method_self = arg_names[0]
+
+            #if not classmethod and arg_names[0] != "self":
+            #    raise TranslationError("first arg not 'self' (in _method)", node)
+
+        normal_arg_names = arg_names[1:]
+        if node.kwargs: kwargname = normal_arg_names.pop()
+        if node.varargs: varargname = normal_arg_names.pop()
+        declared_arg_names = list(normal_arg_names)
+        if node.kwargs: declared_arg_names.append(kwargname)
+
+        function_args = "(" + ", ".join(declared_arg_names) + ")"
+
+        if classmethod:
+            fexpr = UU + class_name_ + ".prototype.__class__." + node.name
+        else:
+            fexpr = UU + class_name_ + ".prototype." + node.name
+        print >>self.output, "    "+fexpr + " = function" + function_args + " {"
+
+        # default arguments
+        self._default_args_handler(node, normal_arg_names, current_klass)
+
+        local_arg_names = normal_arg_names + declared_arg_names 
+
+        if node.varargs:
+            self._varargs_handler(node, varargname, declared_arg_names, current_klass)
+            local_arg_names.append(varargname)
+
+
+        # stack of local variable names for this function call
+        self.local_arg_stack.append(local_arg_names)
+
+        for child in node.code:
+            self._stmt(child, current_klass)
+
+        # remove the top local arg names
+        self.local_arg_stack.pop()
+
+        print >>self.output, "    };"
+
+        self._kwargs_parser(node, fexpr, normal_arg_names, current_klass)
+
+        if classmethod:
+            # Have to create a version on the instances which automatically passes the
+            # class as "self"
+            altexpr = UU + class_name_ + ".prototype." + node.name
+            print >>self.output, "    "+altexpr + " = function() {"
+            print >>self.output, "        return " + fexpr + ".apply(this.__class__, arguments);"
+            print >>self.output, "    };"
+            print >>self.output, "    "+fexpr+".class_method = true;"
+            print >>self.output, "    "+altexpr+".instance_method = true;"
+        else:
+            # For instance methods, we need an unbound version in the class object
+            altexpr = UU + class_name_ + ".prototype.__class__." + node.name
+            print >>self.output, "    "+altexpr + " = function() {"
+            print >>self.output, "        return " + fexpr + ".call.apply("+fexpr+", arguments);"
+            print >>self.output, "    };"
+            print >>self.output, "    "+altexpr+".unbound_method = true;"
+            print >>self.output, "    "+fexpr+".instance_method = true;"
+            print >>self.output, "    "+altexpr+".__name__ = '%s';" % node.name
+
+        print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \
+                (node.name, node.name)
+
+        if node.kwargs or len(node.defaults):
+            print >>self.output, "    "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;"
+
+        self.method_self = None
+        self.method_imported_globals = set()
+
+    def _isNativeFunc(self, node):
+        if isinstance(node, ast.Discard):
+            if isinstance(node.expr, ast.CallFunc):
+                if isinstance(node.expr.node, ast.Name) and \
+                       node.expr.node.name == NATIVE_JS_FUNC_NAME:
+                    return True
+        return False
+
+    def _stmt(self, node, current_klass):
+        debugStmt = self.debug and not self._isNativeFunc(node)
+        if debugStmt:
+            print >>self.output, '  try {'
+
+        if isinstance(node, ast.Return):
+            self._return(node, current_klass)
+        elif isinstance(node, ast.Break):
+            self._break(node, current_klass)
+        elif isinstance(node, ast.Continue):
+            self._continue(node, current_klass)
+        elif isinstance(node, ast.Assign):
+            self._assign(node, current_klass)
+        elif isinstance(node, ast.AugAssign):
+            self._augassign(node, current_klass)
+        elif isinstance(node, ast.Discard):
+            self._discard(node, current_klass)
+        elif isinstance(node, ast.If):
+            self._if(node, current_klass)
+        elif isinstance(node, ast.For):
+            self._for(node, current_klass)
+        elif isinstance(node, ast.While):
+            self._while(node, current_klass)
+        elif isinstance(node, ast.Subscript):
+            self._subscript_stmt(node, current_klass)
+        elif isinstance(node, ast.Global):
+            self._global(node, current_klass)
+        elif isinstance(node, ast.Pass):
+            pass
+        elif isinstance(node, ast.Function):
+            self._function(node, True)
+        elif isinstance(node, ast.Printnl):
+           self._print(node, current_klass)
+        elif isinstance(node, ast.Print):
+           self._print(node, current_klass)
+        elif isinstance(node, ast.TryExcept):
+            self._tryExcept(node, current_klass)
+        elif isinstance(node, ast.Raise):
+            self._raise(node, current_klass)
+        else:
+            raise TranslationError("unsupported type (in _stmt)", node)
+
+        if debugStmt:
+
+            lt = self.get_line_trace(node)
+
+            haltException = self.module_prefix + "HaltException"
+            isHaltFunction = self.module_prefix + "IsHaltException"
+
+            print >>self.output, '  } catch (__err) {'
+            print >>self.output, '      if (' + isHaltFunction + '(__err.name)) {'
+            print >>self.output, '          throw __err;'
+            print >>self.output, '      } else {'
+            print >>self.output, "          st = sys.printstack() + "\
+                                                + '"%s"' % lt + "+ '\\n' ;"
+            print >>self.output, '          alert("' + "Error in " \
+                                                + lt + '"' \
+                                                + '+"\\n"+__err.name+": "+__err.message'\
+                                                + '+"\\n\\nStack trace:\\n"' \
+                                                + '+st' \
+                                                + ');'
+            print >>self.output, '          debugger;'
+
+            print >>self.output, '          throw new ' + self.module_prefix + "HaltException();"
+            print >>self.output, '      }'
+            print >>self.output, '  }'
+
+
+    def get_line_trace(self, node):
+        lineNum = "Unknown"
+        srcLine = ""
+        if hasattr(node, "lineno"):
+            if node.lineno != None:
+                lineNum = node.lineno
+                srcLine = self.src[min(lineNum, len(self.src))-1]
+                srcLine = srcLine.replace('\\', '\\\\')
+                srcLine = srcLine.replace('"', '\\"')
+                srcLine = srcLine.replace("'", "\\'")
+
+        return self.raw_module_name + ".py, line " \
+               + str(lineNum) + ":"\
+               + "\\n" \
+               + "    " + srcLine
+
+    def _augassign(self, node, current_klass):
+        v = node.node
+        if isinstance(v, ast.Getattr):
+            # XXX HACK!  don't allow += on return result of getattr.
+            # TODO: create a temporary variable or something.
+            lhs = self._getattr(v, current_klass, False)
+        else:
+            lhs = self._name(node.node, current_klass)
+        op = node.op
+        rhs = self.expr(node.expr, current_klass)
+        print >>self.output, "    " + lhs + " " + op + " " + rhs + ";"
+
+
+    def _assign(self, node, current_klass, top_level = False):
+        if len(node.nodes) != 1:
+            tempvar = '__temp'+str(node.lineno)
+            tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno)
+            self._assign(tnode, current_klass, top_level)
+            for v in node.nodes:
+               tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno)
+               self._assign(tnode2, current_klass, top_level)
+            return
+
+        local_var_names = None
+        if len(self.local_arg_stack) > 0:
+            local_var_names = self.local_arg_stack[-1]
+
+        def _lhsFromAttr(v, current_klass):
+            attr_name = v.attrname
+            if isinstance(v.expr, ast.Name):
+                obj = v.expr.name
+                lhs = self._name(v.expr, current_klass) + "." + attr_name
+            elif isinstance(v.expr, ast.Getattr):
+                lhs = self._getattr(v, current_klass)
+            elif isinstance(v.expr, ast.Subscript):
+                lhs = self._subscript(v.expr, current_klass) + "." + attr_name
+            else:
+                raise TranslationError("unsupported type (in _assign)", v.expr)
+            return lhs
+
+        def _lhsFromName(v, top_level, current_klass):
+            if top_level:
+                if current_klass:
+                    lhs = UU+current_klass.name_ + ".prototype.__class__." \
+                               + v.name
+                else:
+                    self.top_level_vars.add(v.name)
+                    vname = self.modpfx() + v.name
+                    if not self.modpfx() and v.name not in\
+                           self.method_imported_globals:
+                        lhs = "var " + vname
+                    else:
+                        lhs = UU + vname
+                    self.add_local_arg(v.name)
+            else:
+                if v.name in local_var_names:
+                    lhs = v.name
+                elif v.name in self.method_imported_globals:
+                    lhs = self.modpfx() + v.name
+                else:
+                    lhs = "var " + v.name
+                    self.add_local_arg(v.name)
+            return lhs
+
+        dbg = 0
+        v = node.nodes[0]
+        if isinstance(v, ast.AssAttr):
+            lhs = _lhsFromAttr(v, current_klass)
+            if v.flags == "OP_ASSIGN":
+                op = "="
+            else:
+                raise TranslationError("unsupported flag (in _assign)", v)
+
+        elif isinstance(v, ast.AssName):
+            lhs = _lhsFromName(v, top_level, current_klass)
+            if v.flags == "OP_ASSIGN":
+                op = "="
+            else:
+                raise TranslationError("unsupported flag (in _assign)", v)
+        elif isinstance(v, ast.Subscript):
+            if v.flags == "OP_ASSIGN":
+                obj = self.expr(v.expr, current_klass)
+                if len(v.subs) != 1:
+                    raise TranslationError("must have one sub (in _assign)", v)
+                idx = self.expr(v.subs[0], current_klass)
+                value = self.expr(node.expr, current_klass)
+                print >>self.output, "    " + obj + ".__setitem__(" + idx + ", " + value + ");"
+                return
+            else:
+                raise TranslationError("unsupported flag (in _assign)", v)
+        elif isinstance(v, (ast.AssList, ast.AssTuple)):
+            uniqueID = self.nextTupleAssignID
+            self.nextTupleAssignID += 1
+            tempName = "__tupleassign" + str(uniqueID) + "__"
+            print >>self.output, "    var " + tempName + " = " + \
+                                 self.expr(node.expr, current_klass) + ";"
+            for index,child in enumerate(v.getChildNodes()):
+                rhs = tempName + ".__getitem__(" + str(index) + ")"
+
+                if isinstance(child, ast.AssAttr):
+                    lhs = _lhsFromAttr(child, current_klass)
+                elif isinstance(child, ast.AssName):
+                    lhs = _lhsFromName(child, top_level, current_klass)
+                elif isinstance(child, ast.Subscript):
+                    if child.flags == "OP_ASSIGN":
+                        obj = self.expr(child.expr, current_klass)
+                        if len(child.subs) != 1:
+                            raise TranslationError("must have one sub " +
+                                                   "(in _assign)", child)
+                        idx = self.expr(child.subs[0], current_klass)
+                        value = self.expr(node.expr, current_klass)
+                        print >>self.output, "    " + obj + ".__setitem__(" \
+                                           + idx + ", " + rhs + ");"
+                        continue
+                print >>self.output, "    " + lhs + " = " + rhs + ";"
+            return
+        else:
+            raise TranslationError("unsupported type (in _assign)", v)
+
+        rhs = self.expr(node.expr, current_klass)
+        if dbg:
+            print "b", repr(node.expr), rhs
+        print >>self.output, "    " + lhs + " " + op + " " + rhs + ";"
+
+
+    def _discard(self, node, current_klass):
+        
+        if isinstance(node.expr, ast.CallFunc):
+            debugStmt = self.debug and not self._isNativeFunc(node)
+            if debugStmt and isinstance(node.expr.node, ast.Name) and \
+               node.expr.node.name == 'import_wait':
+               debugStmt = False
+            if debugStmt:
+                st = self.get_line_trace(node)
+                print >>self.output, "sys.addstack('%s');\n" % st
+            if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME:
+                if len(node.expr.args) != 1:
+                    raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr)
+                if not isinstance(node.expr.args[0], ast.Const):
+                    raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr)
+                raw_js = node.expr.args[0].value
+                print >>self.output, raw_js
+            else:
+                expr = self._callfunc(node.expr, current_klass)
+                print >>self.output, "    " + expr + ";"
+
+            if debugStmt:
+                print >>self.output, "sys.popstack();\n"
+
+        elif isinstance(node.expr, ast.Const):
+            if node.expr.value is not None: # Empty statements generate ignore None
+                print >>self.output, self._const(node.expr)
+        else:
+            raise TranslationError("unsupported type (in _discard)", node.expr)
+
+
+    def _if(self, node, current_klass):
+        for i in range(len(node.tests)):
+            test, consequence = node.tests[i]
+            if i == 0:
+                keyword = "if"
+            else:
+                keyword = "else if"
+
+            self._if_test(keyword, test, consequence, current_klass)
+
+        if node.else_:
+            keyword = "else"
+            test = None
+            consequence = node.else_
+
+            self._if_test(keyword, test, consequence, current_klass)
+
+
+    def _if_test(self, keyword, test, consequence, current_klass):
+        if test:
+            expr = self.expr(test, current_klass)
+
+            print >>self.output, "    " + keyword + " (pyjslib.bool(" + expr + ")) {"
+        else:
+            print >>self.output, "    " + keyword + " {"
+
+        if isinstance(consequence, ast.Stmt):
+            for child in consequence.nodes:
+                self._stmt(child, current_klass)
+        else:
+            raise TranslationError("unsupported type (in _if_test)", consequence)
+
+        print >>self.output, "    }"
+
+
+    def _from(self, node):
+        for name in node.names:
+            # look up "hack" in AppTranslator as to how findFile gets here
+            module_name = node.modname + "." + name[0]
+            try:
+                ff = self.findFile(module_name + ".py")
+            except Exception:
+                ff = None
+            if ff:
+                self.add_imported_module(module_name)
+            else:
+                self.imported_classes[name[0]] = node.modname
+
+
+    def _compare(self, node, current_klass):
+        lhs = self.expr(node.expr, current_klass)
+
+        if len(node.ops) != 1:
+            raise TranslationError("only one ops supported (in _compare)", node)
+
+        op = node.ops[0][0]
+        rhs_node = node.ops[0][1]
+        rhs = self.expr(rhs_node, current_klass)
+
+        if op == "==":
+            return "pyjslib.eq(%s, %s)" % (lhs, rhs)
+        if op == "in":
+            return rhs + ".__contains__(" + lhs + ")"
+        elif op == "not in":
+            return "!" + rhs + ".__contains__(" + lhs + ")"
+        elif op == "is":
+            op = "==="
+        elif op == "is not":
+            op = "!=="
+
+        return "(" + lhs + " " + op + " " + rhs + ")"
+
+
+    def _not(self, node, current_klass):
+        expr = self.expr(node.expr, current_klass)
+
+        return "!(" + expr + ")"
+
+    def _or(self, node, current_klass):
+        expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')'
+        return expr
+
+    def _and(self, node, current_klass):
+        expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")"
+        return expr
+
+    def _for(self, node, current_klass):
+        assign_name = ""
+        assign_tuple = ""
+
+        # based on Bob Ippolito's Iteration in Javascript code
+        if isinstance(node.assign, ast.AssName):
+            assign_name = node.assign.name
+            self.add_local_arg(assign_name)
+            if node.assign.flags == "OP_ASSIGN":
+                op = "="
+        elif isinstance(node.assign, ast.AssTuple):
+            op = "="
+            i = 0
+            for child in node.assign:
+                child_name = child.name
+                if assign_name == "":
+                    assign_name = "temp_" + child_name
+                self.add_local_arg(child_name)
+                assign_tuple += """
+                var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i);
+                """ % locals()
+                i += 1
+        else:
+            raise TranslationError("unsupported type (in _for)", node.assign)
+
+        if isinstance(node.list, ast.Name):
+            list_expr = self._name(node.list, current_klass)
+        elif isinstance(node.list, ast.Getattr):
+            list_expr = self._getattr(node.list, current_klass)
+        elif isinstance(node.list, ast.CallFunc):
+            list_expr = self._callfunc(node.list, current_klass)
+        else:
+            raise TranslationError("unsupported type (in _for)", node.list)
+
+        lhs = "var " + assign_name
+        iterator_name = "__" + assign_name
+
+        print >>self.output, """
+        var %(iterator_name)s = %(list_expr)s.__iter__();
+        try {
+            while (true) {
+                %(lhs)s %(op)s %(iterator_name)s.next();
+                %(assign_tuple)s
+        """ % locals()
+        for node in node.body.nodes:
+            self._stmt(node, current_klass)
+        print >>self.output, """
+            }
+        } catch (e) {
+            if (e.__name__ != pyjslib.StopIteration.__name__) {
+                throw e;
+            }
+        }
+        """ % locals()
+
+
+    def _while(self, node, current_klass):
+        test = self.expr(node.test, current_klass)
+        print >>self.output, "    while (pyjslib.bool(" + test + ")) {"
+        if isinstance(node.body, ast.Stmt):
+            for child in node.body.nodes:
+                self._stmt(child, current_klass)
+        else:
+            raise TranslationError("unsupported type (in _while)", node.body)
+        print >>self.output, "    }"
+
+
+    def _const(self, node):
+        if isinstance(node.value, int):
+            return str(node.value)
+        elif isinstance(node.value, float):
+            return str(node.value)
+        elif isinstance(node.value, basestring):
+            v = node.value
+            if isinstance(node.value, unicode):
+                v = v.encode('utf-8')
+            return  "String('%s')" % escapejs(v)
+        elif node.value is None:
+            return "null"
+        else:
+            raise TranslationError("unsupported type (in _const)", node)
+
+    def _unaryadd(self, node, current_klass):
+        return self.expr(node.expr, current_klass)
+
+    def _unarysub(self, node, current_klass):
+        return "-" + self.expr(node.expr, current_klass)
+
+    def _add(self, node, current_klass):
+        return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass)
+
+    def _sub(self, node, current_klass):
+        return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass)
+
+    def _div(self, node, current_klass):
+        return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass)
+
+    def _mul(self, node, current_klass):
+        return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass)
+
+    def _mod(self, node, current_klass):
+        if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType):
+           self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used
+           return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")"
+        return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass)
+
+    def _invert(self, node, current_klass):
+        return "~" + self.expr(node.expr, current_klass)
+
+    def _bitand(self, node, current_klass):
+        return " & ".join([self.expr(child, current_klass) for child in node.nodes])
+
+    def _bitshiftleft(self, node, current_klass):
+        return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass)
+
+    def _bitshiftright(self, node, current_klass):
+        return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass)
+
+    def _bitxor(self,node, current_klass):
+        return " ^ ".join([self.expr(child, current_klass) for child in node.nodes])
+
+    def _bitor(self, node, current_klass):
+        return " | ".join([self.expr(child, current_klass) for child in node.nodes])
+
+    def _subscript(self, node, current_klass):
+        if node.flags == "OP_APPLY":
+            if len(node.subs) == 1:
+                return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")"
+            else:
+                raise TranslationError("must have one sub (in _subscript)", node)
+        else:
+            raise TranslationError("unsupported flag (in _subscript)", node)
+
+    def _subscript_stmt(self, node, current_klass):
+        if node.flags == "OP_DELETE":
+            print >>self.output, "    " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");"
+        else:
+            raise TranslationError("unsupported flag (in _subscript)", node)
+
+    def _list(self, node, current_klass):
+        return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
+
+    def _dict(self, node, current_klass):
+        items = []
+        for x in node.items:
+            key = self.expr(x[0], current_klass)
+            value = self.expr(x[1], current_klass)
+            items.append("[" + key + ", " + value + "]")
+        return "new pyjslib.Dict([" + ", ".join(items) + "])"
+
+    def _tuple(self, node, current_klass):
+        return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
+
+    def _lambda(self, node, current_klass):
+        if node.varargs:
+            raise TranslationError("varargs are not supported in Lambdas", node)
+        if node.kwargs:
+            raise TranslationError("kwargs are not supported in Lambdas", node)
+        res = cStringIO.StringIO()
+        arg_names = list(node.argnames)
+        function_args = ", ".join(arg_names)
+        for child in node.getChildNodes():
+            expr = self.expr(child, None)
+        print >> res, "function (%s){" % function_args
+        self._default_args_handler(node, arg_names, None,
+                                   output=res)
+        print >> res, 'return %s;}' % expr
+        return res.getvalue()
+
+    def _slice(self, node, current_klass):
+        if node.flags == "OP_APPLY":
+            lower = "null"
+            upper = "null"
+            if node.lower != None:
+                lower = self.expr(node.lower, current_klass)
+            if node.upper != None:
+                upper = self.expr(node.upper, current_klass)
+            return  "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")"
+        else:
+            raise TranslationError("unsupported flag (in _slice)", node)
+
+    def _global(self, node, current_klass):
+        for name in node.names:
+            self.method_imported_globals.add(name)
+
+    def expr(self, node, current_klass):
+        if isinstance(node, ast.Const):
+            return self._const(node)
+        # @@@ not sure if the parentheses should be here or in individual operator functions - JKT
+        elif isinstance(node, ast.Mul):
+            return " ( " + self._mul(node, current_klass) + " ) "
+        elif isinstance(node, ast.Add):
+            return " ( " + self._add(node, current_klass) + " ) "
+        elif isinstance(node, ast.Sub):
+            return " ( " + self._sub(node, current_klass) + " ) "
+        elif isinstance(node, ast.Div):
+            return " ( " + self._div(node, current_klass) + " ) "
+        elif isinstance(node, ast.Mod):
+            return self._mod(node, current_klass)
+        elif isinstance(node, ast.UnaryAdd):
+            return self._unaryadd(node, current_klass)
+        elif isinstance(node, ast.UnarySub):
+            return self._unarysub(node, current_klass)
+        elif isinstance(node, ast.Not):
+            return self._not(node, current_klass)
+        elif isinstance(node, ast.Or):
+            return self._or(node, current_klass)
+        elif isinstance(node, ast.And):
+            return self._and(node, current_klass)
+        elif isinstance(node, ast.Invert):
+            return self._invert(node, current_klass)
+        elif isinstance(node, ast.Bitand):
+            return "("+self._bitand(node, current_klass)+")"
+        elif isinstance(node,ast.LeftShift):
+            return self._bitshiftleft(node, current_klass)
+        elif isinstance(node, ast.RightShift):
+            return self._bitshiftright(node, current_klass)
+        elif isinstance(node, ast.Bitxor):
+            return "("+self._bitxor(node, current_klass)+")"
+        elif isinstance(node, ast.Bitor):
+            return "("+self._bitor(node, current_klass)+")"
+        elif isinstance(node, ast.Compare):
+            return self._compare(node, current_klass)
+        elif isinstance(node, ast.CallFunc):
+            return self._callfunc(node, current_klass)
+        elif isinstance(node, ast.Name):
+            return self._name(node, current_klass)
+        elif isinstance(node, ast.Subscript):
+            return self._subscript(node, current_klass)
+        elif isinstance(node, ast.Getattr):
+            return self._getattr(node, current_klass)
+        elif isinstance(node, ast.List):
+            return self._list(node, current_klass)
+        elif isinstance(node, ast.Dict):
+            return self._dict(node, current_klass)
+        elif isinstance(node, ast.Tuple):
+            return self._tuple(node, current_klass)
+        elif isinstance(node, ast.Slice):
+            return self._slice(node, current_klass)
+        elif isinstance(node, ast.Lambda):
+            return self._lambda(node, current_klass)
+        else:
+            raise TranslationError("unsupported type (in expr)", node)
+
+
+
+import cStringIO
+
+def translate(file_name, module_name, debug=False):
+    f = file(file_name, "r")
+    src = f.read()
+    f.close()
+    output = cStringIO.StringIO()
+    mod = compiler.parseFile(file_name)
+    t = Translator(module_name, module_name, module_name, src, debug, mod, output)
+    return output.getvalue()
+
+
+class PlatformParser:
+    def __init__(self, platform_dir = "", verbose=True):
+        self.platform_dir = platform_dir
+        self.parse_cache = {}
+        self.platform = ""
+        self.verbose = verbose
+
+    def setPlatform(self, platform):
+        self.platform = platform
+
+    def parseModule(self, module_name, file_name):
+
+        importing = False
+        if not self.parse_cache.has_key(file_name):
+            importing = True
+            mod = compiler.parseFile(file_name)
+            self.parse_cache[file_name] = mod
+        else:
+            mod = self.parse_cache[file_name]
+
+        override = False
+        platform_file_name = self.generatePlatformFilename(file_name)
+        if self.platform and os.path.isfile(platform_file_name):
+            mod = copy.deepcopy(mod)
+            mod_override = compiler.parseFile(platform_file_name)
+            self.merge(mod, mod_override)
+            override = True
+
+        if self.verbose:
+            if override:
+                print "Importing %s (Platform %s)" % (module_name, self.platform)
+            elif importing:
+                print "Importing %s" % (module_name)
+
+        return mod, override
+
+    def generatePlatformFilename(self, file_name):
+        (module_name, extension) = os.path.splitext(os.path.basename(file_name))
+        platform_file_name = module_name + self.platform + extension
+
+        return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name)
+
+    def merge(self, tree1, tree2):
+        for child in tree2.node:
+            if isinstance(child, ast.Function):
+                self.replaceFunction(tree1, child.name, child)
+            elif isinstance(child, ast.Class):
+                self.replaceClassMethods(tree1, child.name, child)
+
+        return tree1
+
+    def replaceFunction(self, tree, function_name, function_node):
+        # find function to replace
+        for child in tree.node:
+            if isinstance(child, ast.Function) and child.name == function_name:
+                self.copyFunction(child, function_node)
+                return
+        raise TranslationError("function not found: " + function_name, function_node)
+
+    def replaceClassMethods(self, tree, class_name, class_node):
+        # find class to replace
+        old_class_node = None
+        for child in tree.node:
+            if isinstance(child, ast.Class) and child.name == class_name:
+                old_class_node = child
+                break
+
+        if not old_class_node:
+            raise TranslationError("class not found: " + class_name, class_node)
+
+        # replace methods
+        for function_node in class_node.code:
+            if isinstance(function_node, ast.Function):
+                found = False
+                for child in old_class_node.code:
+                    if isinstance(child, ast.Function) and child.name == function_node.name:
+                        found = True
+                        self.copyFunction(child, function_node)
+                        break
+
+                if not found:
+                    raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node)
+
+    def copyFunction(self, target, source):
+        target.code = source.code
+        target.argnames = source.argnames
+        target.defaults = source.defaults
+        target.doc = source.doc # @@@ not sure we need to do this any more
+
+def dotreplace(fname):
+    path, ext = os.path.splitext(fname)
+    return path.replace(".", "/") + ext
+
+class AppTranslator:
+
+    def __init__(self, library_dirs=[], parser=None, dynamic=False,
+                 optimize=False, verbose=True):
+        self.extension = ".py"
+        self.optimize = optimize
+        self.library_modules = []
+        self.overrides = {}
+        self.library_dirs = path + library_dirs
+        self.dynamic = dynamic
+        self.verbose = verbose
+
+        if not parser:
+            self.parser = PlatformParser()
+        else:
+            self.parser = parser
+
+        self.parser.dynamic = dynamic
+
+    def findFile(self, file_name):
+        if os.path.isfile(file_name):
+            return file_name
+
+        for library_dir in self.library_dirs:
+            file_name = dotreplace(file_name)
+            full_file_name = os.path.join(
+                os.path.abspath(os.path.dirname(__file__)), library_dir, file_name)
+            if os.path.isfile(full_file_name):
+                return full_file_name
+
+            fnameinit, ext = os.path.splitext(file_name)
+            fnameinit = fnameinit + "/__init__.py"
+
+            full_file_name = os.path.join(
+                os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit)
+            if os.path.isfile(full_file_name):
+                return full_file_name
+
+        raise Exception("file not found: " + file_name)
+
+    def _translate(self, module_name, is_app=True, debug=False,
+                   imported_js=set()):
+        if module_name not in self.library_modules:
+            self.library_modules.append(module_name)
+
+        file_name = self.findFile(module_name + self.extension)
+
+        output = cStringIO.StringIO()
+
+        f = file(file_name, "r")
+        src = f.read()
+        f.close()
+
+        mod, override = self.parser.parseModule(module_name, file_name)
+        if override:
+            override_name = "%s.%s" % (self.parser.platform.lower(),
+                                           module_name)
+            self.overrides[override_name] = override_name
+        if is_app:
+            mn = '__main__'
+        else:
+            mn = module_name
+        t = Translator(mn, module_name, module_name,
+                       src, debug, mod, output, self.dynamic, self.optimize,
+                       self.findFile)
+
+        module_str = output.getvalue()
+        imported_js.update(set(t.imported_js))
+        imported_modules_str = ""
+        for module in t.imported_modules:
+            if module not in self.library_modules:
+                self.library_modules.append(module)
+                #imported_js.update(set(t.imported_js))
+                #imported_modules_str += self._translate(
+                #    module, False, debug=debug, imported_js=imported_js)
+
+        return imported_modules_str + module_str
+
+
+    def translate(self, module_name, is_app=True, debug=False,
+                  library_modules=[]):
+        app_code = cStringIO.StringIO()
+        lib_code = cStringIO.StringIO()
+        imported_js = set()
+        self.library_modules = []
+        self.overrides = {}
+        for library in library_modules:
+            if library.endswith(".js"):
+                imported_js.add(library)
+                continue
+            self.library_modules.append(library)
+            if self.verbose:
+                print 'Including LIB', library
+            print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n'
+            print >> lib_code, self._translate(
+                library, False, debug=debug, imported_js=imported_js)
+
+            print >> lib_code, "/* initialize static library */"
+            print >> lib_code, "%s%s();\n" % (UU, library)
+
+            print >> lib_code, '\n//\n// END LIB '+library+'\n//\n'
+        if module_name:
+            print >> app_code, self._translate(
+                module_name, is_app, debug=debug, imported_js=imported_js)
+        for js in imported_js:
+           path = self.findFile(js)
+           if os.path.isfile(path):
+              if self.verbose:
+                  print 'Including JS', js
+              print >> lib_code,  '\n//\n// BEGIN JS '+js+'\n//\n'
+              print >> lib_code, file(path).read()
+              print >> lib_code,  '\n//\n// END JS '+js+'\n//\n'
+           else:
+              print >>sys.stderr, 'Warning: Unable to find imported javascript:', js
+        return lib_code.getvalue(), app_code.getvalue()
+
+usage = """
+  usage: %s file_name [module_name]
+"""
+
+def main():
+    import sys
+    if len(sys.argv)<2:
+        print >> sys.stderr, usage % sys.argv[0]
+        sys.exit(1)
+    file_name = os.path.abspath(sys.argv[1])
+    if not os.path.isfile(file_name):
+        print >> sys.stderr, "File not found %s" % file_name
+        sys.exit(1)
+    if len(sys.argv) > 2:
+        module_name = sys.argv[2]
+    else:
+        module_name = None
+    print translate(file_name, module_name),
+
+if __name__ == "__main__":
+    main()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/svgui.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,112 @@
+import wx
+import os, sys, shutil
+
+from ConfigTree import opjimg
+from confnodes.python import PythonCodeTemplate
+
+from pyjs import translate
+
+from docutils import *
+
+class RootClass:
+
+    ConfNodeMethods = [
+        {"bitmap" : os.path.join("images","ImportSVG"),
+         "name" : _("Import SVG"),
+         "tooltip" : _("Import SVG"),
+         "method" : "_ImportSVG"},
+        {"bitmap" : os.path.join("images","ImportSVG"),
+         "name" : _("Inkscape"),
+         "tooltip" : _("Create HMI"),
+         "method" : "_StartInkscape"},
+    ]
+
+    def ConfNodePath(self):
+        return os.path.join(self.PlugParent.ConfNodePath(), "modules", self.PlugType)
+
+    def _getSVGpath(self):
+        # define name for IEC raw code file
+        return os.path.join(self.PlugPath(), "gui.svg")
+
+    def _getSVGUIserverpath(self):
+        return os.path.join(os.path.dirname(__file__), "svgui_server.py")
+
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Return C code generated by iec2c compiler 
+        when _generate_softPLC have been called
+        @param locations: ignored
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        
+        current_location = self.GetCurrentLocation()
+        # define a unique name for the generated C file
+        location_str = "_".join(map(lambda x:str(x), current_location))
+        
+        res = ([], "", False)
+        
+        svgfile=self._getSVGpath()
+        if os.path.exists(svgfile):
+            res += (("gui.svg", file(svgfile,"rb")),)
+
+        svguiserverfile = open(self._getSVGUIserverpath(), 'r')
+        svguiservercode = svguiserverfile.read()
+        svguiserverfile.close()
+
+        svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js")
+        svguilibfile = open(svguilibpath, 'w')
+        svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys"))
+        svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read())
+        svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib"))
+        svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib"))
+        svguilibfile.write("pyjslib();\nsvguilib();\n")
+        svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read())
+        svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read())
+        svguilibfile.close()
+        jsmodules = {"LiveSVGPage": "svguilib.js"}
+        res += (("svguilib.js", file(svguilibpath,"rb")),)
+        
+        runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
+        runtimefile = open(runtimefile_path, 'w')
+        runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"})
+        runtimefile.write("""
+def _runtime_%(location)s_begin():
+    website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
+    
+def _runtime_%(location)s_cleanup():
+    website.UnLoadHMI()
+    
+""" % {"location": location_str,
+       "svgui_class": "SVGUI_HMI",
+       "jsmodules" : str(jsmodules),
+      })
+        runtimefile.close()
+        
+        res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),)
+        
+        return res
+
+    def _ImportSVG(self):
+        dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "",  _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN)
+        if dialog.ShowModal() == wx.ID_OK:
+            svgpath = dialog.GetPath()
+            if os.path.isfile(svgpath):
+                shutil.copy(svgpath, self._getSVGpath())
+            else:
+                self.GetPlugRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath)
+        dialog.Destroy()  
+
+    def _StartInkscape(self):
+        svgfile = self._getSVGpath()
+        open_inkscape = True
+        if not self.GetPlugRoot().CheckProjectPathPerm():
+            dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                      _("You don't have write permissions.\nOpen Inkscape anyway ?"),
+                                      _("Open Inkscape"),
+                                      wx.YES_NO|wx.ICON_QUESTION)
+            open_inkscape = dialog.ShowModal() == wx.ID_YES
+            dialog.Destroy()
+        if open_inkscape:
+            if not os.path.isfile(svgfile):
+                svgfile = None
+            open_svg(svgfile)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/svgui_server.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,130 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import os
+
+from nevow import rend, appserver, inevow, tags, loaders, athena
+import simplejson as json
+
+svgfile = '%(svgfile)s'
+
+svguiWidgets = {}
+
+currentId = 0
+def getNewId():
+    global currentId
+    currentId += 1
+    return currentId
+
+class SvguiWidget:
+    
+    def __init__(self, classname, id, **kwargs):
+        self.classname = classname
+        self.id = id
+        self.attrs = kwargs.copy()
+        self.inputs = {}
+        self.outputs = {}
+        self.inhibit = False
+        self.changed = False
+
+    def setinput(self, attrname, value):
+        self.inputs[attrname] = value
+        
+    def getinput(self, attrname, default=None):
+        if not self.inputs.has_key(attrname):
+            self.inputs[attrname] = default
+        return self.inputs[attrname]
+
+    def setoutput(self, attrname, value):
+        if self.outputs.get(attrname) != value:
+            self.outputs[attrname] = value
+            self.changed = True
+            self.RefreshInterface()
+        
+    def updateoutputs(self, **kwargs):
+        for attrname, value in kwargs.iteritems():
+            if self.outputs.get(attrname) != value:
+                self.outputs[attrname] = value
+                self.changed = True
+        self.RefreshInterface()
+        
+    def RefreshInterface(self):
+        interface = website.getHMI()
+        if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit:
+            self.changed = False
+            d = interface.sendData(self)
+            if d is not None:
+                self.inhibit = True
+                d.addCallback(self.InterfaceRefreshed)
+    
+    def InterfaceRefreshed(self, result):
+        self.inhibit = False
+        if self.changed:
+            self.RefreshInterface()
+
+def get_object_init_state(obj):
+    # Convert objects to a dictionary of their representation
+    attrs = obj.attrs.copy()
+    attrs.update(obj.inputs)
+    d = { '__class__': obj.classname,
+          'id': obj.id,
+          'kwargs': json.dumps(attrs),
+          }
+    return d
+
+def get_object_current_state(obj):
+    # Convert objects to a dictionary of their representation
+    d = { '__class__': obj.classname,
+          'id': obj.id,
+          'kwargs': json.dumps(obj.outputs),
+          }
+    return d
+
+class SVGUI_HMI(website.PLCHMI):
+    jsClass = u"LiveSVGPage.LiveSVGWidget"
+    
+    docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[                                    
+                                         tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))),
+                                         ])
+    
+    def HMIinitialisation(self):
+        gadgets = []
+        for gadget in svguiWidgets.values():
+            gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
+        d = self.callRemote('init', gadgets)
+        d.addCallback(self.HMIinitialised)
+    
+    def sendData(self,data):
+        if self.initialised:
+            return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
+        return None
+        
+    def setattr(self, id, attrname, value):
+        svguiWidgets[id].setinput(attrname, value)
+
+def createSVGUIControl(*args, **kwargs):
+    id = getNewId()
+    gad = SvguiWidget(args[0], id, **kwargs)
+    svguiWidgets[id] = gad
+    gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
+    interface = website.getHMI()
+    if isinstance(interface, SVGUI_HMI) and interface.initialised:
+        interface.callRemote('init', gadget)
+    return id
+
+def setAttr(id, attrname, value):
+    gad = svguiWidgets.get(id, None)
+    if gad is not None:
+        gad.setoutput(attrname, value)
+
+def updateAttr(id, **kwargs):
+    gad = svguiWidgets.get(id, None)
+    if gad is not None:
+        gad.updateoutput(**kwargs)
+
+def getAttr(id, attrname, default=None):
+    gad = svguiWidgets.get(id, None)
+    if gad is not None:
+        return gad.getinput(attrname, default)
+    return default
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/svgui/svguilib.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,117 @@
+
+class button:
+    
+    def __init__(self, parent, id, args):
+        self.parent = parent
+        self.id = id
+        self.back_elt = getSVGElementById(args.back_id)
+        self.sele_elt = getSVGElementById(args.sele_id)
+        self.toggle = args.toggle
+        self.active = args.active
+        if args.state != undefined:
+            self.state = args.state
+        else:
+            self.state = False
+        self.dragging = False
+        if self.toggle:
+            self.up = not self.state
+        else:
+            self.up = True
+        
+        # Add event on each element of the button
+        if self.active:
+            self.back_elt.addEventListener("mouseup", self, False)
+            self.back_elt.addEventListener("mousedown", self, False)
+            self.back_elt.addEventListener("mouseover", self, False)
+            self.back_elt.addEventListener("mouseout", self, False)
+            
+            self.sele_elt.addEventListener("mouseup", self, False)
+            self.sele_elt.addEventListener("mousedown", self, False)
+            self.sele_elt.addEventListener("mouseover", self, False)
+            self.sele_elt.addEventListener("mouseout", self, False)
+        
+        blockSVGElementDrag(self.back_elt)
+        blockSVGElementDrag(self.sele_elt)
+
+        self.updateElements()
+
+    # method to display the current state of interface
+    def updateElements(self):
+        if self.up:
+            self.sele_elt.setAttribute("display", "none")
+            self.back_elt.removeAttribute("display")
+        else:
+            self.sele_elt.removeAttribute("display")
+            self.back_elt.setAttribute("display", "none")
+            
+    def updateValues(self, values):
+        if values.state != self.state:
+            self.state = values.state
+            self.up = not self.state
+            updateAttr(self.id, 'state', self.state)
+            self.updateElements()
+
+    def handleEvent(self, evt):
+        # Quand le bouton de la souris est presse
+        if evt.type == "mousedown":
+            evt.stopPropagation()
+            setCurrentObject(self)
+            
+            self.dragging = True
+            
+            if self.toggle:
+                self.up = self.state
+            else:
+                self.up = False
+                self.state = True
+                updateAttr(self.id, 'state', self.state)
+            self.updateElements()
+        
+        if isCurrentObject(self) and self.dragging:
+            # Quand le bouton est survole
+            if evt.type == "mouseover" and self.toggle:
+                self.up = self.state
+                self.updateElements()
+            
+            # Quand le curseur quitte la zone du bouton
+            elif evt.type == "mouseout" and self.toggle:       
+                self.up = not self.state
+                self.updateElements()
+            
+            # Quand le bouton de la souris est relache
+            elif evt.type == "mouseup":
+                evt.stopPropagation()
+                if self.toggle and self.up == self.state:
+                    self.state = not self.state
+                    updateAttr(self.id, 'state', self.state)
+                elif not self.toggle:
+                    self.up = True
+                    self.state = False
+                    updateAttr(self.id, 'state', self.state)
+                    self.updateElements()
+                self.dragging = False
+
+class textControl:
+    
+    def __init__(self, parent, id, args):
+        self.parent = parent
+        self.id = id
+        self.back_elt = getSVGElementById(args.back_id)
+        if args.text != undefined:
+            self.text = args.text
+        else:
+            self.text = ""
+        self.updateElements()
+    
+    def updateValues(self, values):
+        if values.text != self.value:
+            self.text = values.text
+            updateAttr(self.id, 'text', self.text)
+            self.updateElements()
+    
+    def updateElements(self):
+        self.back_elt.firstChild.firstChild.textContent = self.text
+    
+    def handleEvent(self, evt):
+        pass
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/wxglade_hmi/README	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+WxGlade HMI
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/wxglade_hmi/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,1 @@
+from wxglade_hmi import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/modules/wxglade_hmi/wxglade_hmi.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,124 @@
+import wx
+import os, sys
+from xml.dom import minidom
+
+from ConfigTree import opjimg
+from confnodes.python import PythonCodeTemplate
+
+class RootClass(PythonCodeTemplate):
+
+    ConfNodeMethods = [
+        {"bitmap" : opjimg("editWXGLADE"),
+         "name" : _("WXGLADE GUI"),
+         "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
+         "method" : "_editWXGLADE"},
+    ]
+
+    def _getWXGLADEpath(self):
+        # define name for IEC raw code file
+        return os.path.join(self.PlugPath(), "hmi.wxg")
+
+    def launch_wxglade(self, options, wait=False):
+        from wxglade import __file__ as fileName
+        path = os.path.dirname(fileName)
+        glade = os.path.join(path, 'wxglade.py')
+        if wx.Platform == '__WXMSW__':
+            glade = "\"%s\""%glade
+        mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait]
+        os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options)
+
+
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Return C code generated by iec2c compiler 
+        when _generate_softPLC have been called
+        @param locations: ignored
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        
+        current_location = self.GetCurrentLocation()
+        # define a unique name for the generated C file
+        location_str = "_".join(map(lambda x:str(x), current_location))
+        
+        runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
+        runtimefile = open(runtimefile_path, 'w')
+        
+        hmi_frames = {}
+        
+        wxgfile_path=self._getWXGLADEpath()
+        if os.path.exists(wxgfile_path):
+            wxgfile = open(wxgfile_path, 'r')
+            wxgtree = minidom.parse(wxgfile)
+            wxgfile.close()
+            
+            for node in wxgtree.childNodes[1].childNodes:
+                if node.nodeType == wxgtree.ELEMENT_NODE:
+                    hmi_frames[node._attrs["name"].value] =  node._attrs["class"].value
+                    
+            hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py")
+            if wx.Platform == '__WXMSW__':
+                wxgfile_path = "\"%s\""%wxgfile_path
+                wxghmipyfile_path = "\"%s\""%hmipyfile_path
+            else:
+                wxghmipyfile_path = hmipyfile_path
+            self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True)
+            
+            hmipyfile = open(hmipyfile_path, 'r')
+            runtimefile.write(hmipyfile.read())
+            hmipyfile.close()
+        
+        runtimefile.write(self.GetPythonCode())
+        runtimefile.write("""
+%(declare)s
+
+def _runtime_%(location)s_begin():
+    global %(global)s
+    
+    def OnCloseFrame(evt):
+        wx.MessageBox(_("Please stop PLC to close"))
+    
+    %(init)s
+    
+def _runtime_%(location)s_cleanup():
+    global %(global)s
+    
+    %(cleanup)s
+
+""" % {"location": location_str,
+       "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())),
+       "global": ",".join(hmi_frames.keys()),
+       "init": "\n".join(map(lambda x: """
+    %(name)s = %(class)s(None)
+    %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
+    %(name)s.Show()
+""" % {"name": x[0], "class": x[1]},
+                             hmi_frames.items())),
+       "cleanup": "\n    ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))})
+        runtimefile.close()
+        
+        return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
+
+    def _editWXGLADE(self):
+        wxg_filename = self._getWXGLADEpath()
+        open_wxglade = True
+        if not self.GetPlugRoot().CheckProjectPathPerm():
+            dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
+                                      _("You don't have write permissions.\nOpen wxGlade anyway ?"),
+                                      _("Open wxGlade"),
+                                      wx.YES_NO|wx.ICON_QUESTION)
+            open_wxglade = dialog.ShowModal() == wx.ID_YES
+            dialog.Destroy()
+        if open_wxglade:
+            if not os.path.exists(wxg_filename):
+                hmi_name = self.BaseParams.getName()
+                open(wxg_filename,"w").write("""<?xml version="1.0"?>
+    <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
+        <object class="%(class)s" name="%(name)s" base="EditFrame">
+            <style>wxDEFAULT_FRAME_STYLE</style>
+            <title>frame_1</title>
+        </object>
+    </application>
+    """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
+            if wx.Platform == '__WXMSW__':
+                wxg_filename = "\"%s\""%wxg_filename
+            self.launch_wxglade([wxg_filename])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/plc_python.c	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,216 @@
+/*
+ * Python Asynchronous execution code
+ *
+ * PLC put python commands in a fifo, respecting execution order
+ * with the help of C pragmas inserted in python_eval FB code
+ *
+ * Buffer content is read asynchronously, (from non real time part),
+ * commands are executed and result stored for later use by PLC.
+ *
+ * In this implementation, fifo is a list of pointer to python_eval
+ * function blocks structures. Some local variables have been added in
+ * python_eval interface. We use those local variables as buffer and state
+ * flags.
+ *
+ * */
+
+#include "iec_types_all.h"
+#include "POUS.h"
+#include <string.h>
+
+/* The fifo (fixed size, as number of FB is fixed) */
+static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d];
+/* Producer and consumer cursors */
+static int Current_PLC_EvalFB;
+static int Current_Python_EvalFB;
+
+/* A global IEC-Python gateway state, for use inside python_eval FBs*/
+static int PythonState;
+#define PYTHON_LOCKED_BY_PYTHON 0
+#define PYTHON_LOCKED_BY_PLC 1
+#define PYTHON_MUSTWAKEUP 2
+#define PYTHON_FINISHED 4
+
+/* Each python_eval FunctionBlock have it own state */
+#define PYTHON_FB_FREE 0
+#define PYTHON_FB_REQUESTED 1
+#define PYTHON_FB_PROCESSING 2
+#define PYTHON_FB_ANSWERED 3
+
+int WaitPythonCommands(void);
+void UnBlockPythonCommands(void);
+int TryLockPython(void);
+void UnLockPython(void);
+void LockPython(void);
+
+int __init_%(location)s()
+{
+	int i;
+	/* Initialize cursors */
+	Current_Python_EvalFB = 0;
+	Current_PLC_EvalFB = 0;
+	PythonState = PYTHON_LOCKED_BY_PYTHON;
+	for(i = 0; i < %(python_eval_fb_count)d; i++)
+		EvalFBs[i] = NULL;
+  return 0;
+}
+
+void __cleanup_%(location)s()
+{
+	PythonState = PYTHON_FINISHED;
+	UnBlockPythonCommands();
+}
+
+void __retrieve_%(location)s()
+{
+	/* Check Python thread is not being
+	 * modifying internal python_eval data */
+	PythonState = TryLockPython() ?
+	                PYTHON_LOCKED_BY_PLC :
+	                PYTHON_LOCKED_BY_PYTHON;
+	/* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
+	 * and python_eval will no do anything */
+}
+
+void __publish_%(location)s()
+{
+	if(PythonState & PYTHON_LOCKED_BY_PLC){
+		/* If runnig PLC did push something in the fifo*/
+		if(PythonState & PYTHON_MUSTWAKEUP){
+			/* WakeUp python thread */
+			UnBlockPythonCommands();
+		}
+		UnLockPython();
+	}
+}
+/**
+ * Called by the PLC, each time a python_eval
+ * FB instance is executed
+ */
+void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
+{
+	/* detect rising edge on TRIG to trigger evaluation */
+	if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) ||
+	   /* polling is equivalent to trig on value rather than on rising edge*/
+	    (poll && __GET_VAR(data__->TRIG) )) &&
+	    /* trig only if not already trigged */
+	    __GET_VAR(data__->TRIGGED) == 0){
+		/* mark as trigged */
+	    __SET_VAR(data__->, TRIGGED, 1);
+		/* make a safe copy of the code */
+		__SET_VAR(data__->, PREBUFFER, __GET_VAR(data__->CODE));
+	}
+	/* retain value for next rising edge detection */
+	__SET_VAR(data__->, TRIGM1, __GET_VAR(data__->TRIG));
+
+	/* python thread is not in ? */
+	if( PythonState & PYTHON_LOCKED_BY_PLC){
+		/* if some answer are waiting, publish*/
+		if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){
+			/* Copy buffer content into result*/
+			__SET_VAR(data__->, RESULT, __GET_VAR(data__->BUFFER));
+			/* signal result presece to PLC*/
+			__SET_VAR(data__->, ACK, 1);
+			/* Mark as free */
+			__SET_VAR(data__->, STATE, PYTHON_FB_FREE);
+			/* mark as not trigged */
+			if(!poll)
+			    __SET_VAR(data__->, TRIGGED, 0);
+			/*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
+		}else if(poll){
+			/* when in polling, no answer == ack down */
+		    __SET_VAR(data__->, ACK, 0);
+		}
+		/* got the order to act ?*/
+		if(__GET_VAR(data__->TRIGGED) == 1 &&
+		   /* and not already being processed */
+		   __GET_VAR(data__->STATE) == PYTHON_FB_FREE)
+		{
+			/* Enter the block in the fifo
+			 * Don't have to check if fifo cell is free
+			 * as fifo size == FB count, and a FB cannot
+			 * be requested twice */
+			EvalFBs[Current_PLC_EvalFB] = data__;
+			/* copy into BUFFER local*/
+			__SET_VAR(data__->, BUFFER, __GET_VAR(data__->PREBUFFER));
+			/* Set ACK pin to low so that we can set a rising edge on result */
+			if(!poll){
+				/* when not polling, a new answer imply reseting ack*/
+			    __SET_VAR(data__->, ACK, 0);
+			}else{
+				/* when in polling, acting reset trigger */
+			    __SET_VAR(data__->, TRIGGED, 0);
+			}
+			/* Mark FB busy */
+			__SET_VAR(data__->, STATE, PYTHON_FB_REQUESTED);
+			/* Have to wakeup python thread in case he was asleep */
+			PythonState |= PYTHON_MUSTWAKEUP;
+			/*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
+			/* Get a new line */
+			Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
+		}
+	}
+}
+
+char* PythonIterator(char* result)
+{
+	char* next_command;
+	PYTHON_EVAL* data__;
+	//printf("PythonIterator result %%s\n", result);
+    /*emergency exit*/
+    if(PythonState & PYTHON_FINISHED) return NULL;
+	/* take python mutex to prevent changing PLC data while PLC running */
+	LockPython();
+	/* Get current FB */
+	data__ = EvalFBs[Current_Python_EvalFB];
+	if(data__ && /* may be null at first run */
+	    __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/
+	   	/* If result not None */
+	   	if(result){
+			/* Get results len */
+	   	    __SET_VAR(data__->, BUFFER, strlen(result), .len);
+			/* prevent results overrun */
+			if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN)
+			{
+			    __SET_VAR(data__->, BUFFER, STR_MAX_LEN, .len );
+				/* TODO : signal error */
+			}
+			/* Copy results to buffer */
+			strncpy((char*)__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len));
+	   	}else{
+	   	    __SET_VAR(data__->, BUFFER, 0, .len);
+	   	}
+		/* remove block from fifo*/
+		EvalFBs[Current_Python_EvalFB] = NULL;
+		/* Mark block as answered */
+		__SET_VAR(data__->, STATE, PYTHON_FB_ANSWERED);
+		/* Get a new line */
+		Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
+		//printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
+	}
+	/* while next slot is empty */
+	while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
+	 	  /* or doesn't contain command */
+	      __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED)
+	{
+		UnLockPython();
+		/* wait next FB to eval */
+		//printf("PythonIterator wait\n");
+		if(WaitPythonCommands()) return NULL;
+		/*emergency exit*/
+		if(PythonState & PYTHON_FINISHED) return NULL;
+		LockPython();
+	}
+	/* Mark block as processing */
+	__SET_VAR(data__->, STATE, PYTHON_FB_PROCESSING);
+	//printf("PythonIterator\n");
+	/* make BUFFER a null terminated string */
+	__SET_VAR(data__->, BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]);
+	/* next command is BUFFER */
+	next_command = (char*)__GET_VAR(data__->BUFFER, .body);
+	/* free python mutex */
+	UnLockPython();
+	/* return the next command to eval */
+	return next_command;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/pous.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://www.plcopen.org/xml/tc6.xsd"
+         xmlns:xhtml="http://www.w3.org/1999/xhtml"
+         xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
+  <fileHeader companyName="Beremiz"
+              productName="Beremiz"
+              productVersion="0.0"
+              creationDateTime="2008-12-14T16:53:26"/>
+  <contentHeader name="Beremiz non-standard POUs library"
+                 modificationDateTime="2008-12-23T22:35:46">
+    <coordinateInfo>
+      <fbd>
+        <scaling x="0" y="0"/>
+      </fbd>
+      <ld>
+        <scaling x="0" y="0"/>
+      </ld>
+      <sfc>
+        <scaling x="0" y="0"/>
+      </sfc>
+    </coordinateInfo>
+  </contentHeader>
+  <types>
+    <dataTypes/>
+    <pous>
+      <pou name="python_eval" pouType="functionBlock">
+        <interface>
+          <inputVars>
+            <variable name="TRIG">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="CODE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </inputVars>
+          <outputVars>
+            <variable name="ACK">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="RESULT">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </outputVars>
+          <localVars>
+            <variable name="STATE">
+              <type>
+                <DWORD/>
+              </type>
+            </variable>
+            <variable name="BUFFER">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="PREBUFFER">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="TRIGM1">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="TRIGGED">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <ST>
+<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(0, data__);}]]>
+          </ST>
+        </body>
+      </pou>
+      <pou name="python_poll" pouType="functionBlock">
+        <interface>
+          <inputVars>
+            <variable name="TRIG">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="CODE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </inputVars>
+          <outputVars>
+            <variable name="ACK">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="RESULT">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </outputVars>
+          <localVars>
+            <variable name="STATE">
+              <type>
+                <DWORD/>
+              </type>
+            </variable>
+            <variable name="BUFFER">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="PREBUFFER">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="TRIGM1">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="TRIGGED">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <ST>
+<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(1,(PYTHON_EVAL*)(void*)data__);}]]>
+          </ST>
+        </body>
+      </pou>
+    <pou name="python_gear" pouType="functionBlock">
+        <interface>
+          <inputVars>
+            <variable name="N">
+              <type>
+                <USINT/>
+              </type>
+            </variable>
+            <variable name="TRIG">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="CODE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </inputVars>
+          <outputVars>
+            <variable name="ACK">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="RESULT">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </outputVars>
+          <localVars>
+            <variable name="py_eval">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="COUNTER">
+              <type>
+                <USINT/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <FBD>
+            <block localId="1" width="125" height="110" typeName="python_eval" instanceName="py_eval">
+              <position x="525" y="580"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="40"/>
+                    <connection refLocalId="7" formalParameter="OUT">
+                      <position x="525" y="620"/>
+                      <position x="495" y="620"/>
+                      <position x="495" y="575"/>
+                      <position x="465" y="575"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="CODE">
+                  <connectionPointIn>
+                    <relPosition x="0" y="85"/>
+                    <connection refLocalId="4">
+                      <position x="525" y="665"/>
+                      <position x="370" y="665"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="ACK">
+                  <connectionPointOut>
+                    <relPosition x="125" y="40"/>
+                  </connectionPointOut>
+                </variable>
+                <variable formalParameter="RESULT">
+                  <connectionPointOut>
+                    <relPosition x="125" y="85"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="2" height="35" width="25">
+              <position x="435" y="270"/>
+              <connectionPointOut>
+                <relPosition x="25" y="15"/>
+              </connectionPointOut>
+              <expression>N</expression>
+            </inVariable>
+            <inVariable localId="3" height="35" width="55">
+              <position x="275" y="585"/>
+              <connectionPointOut>
+                <relPosition x="55" y="15"/>
+              </connectionPointOut>
+              <expression>TRIG</expression>
+            </inVariable>
+            <inVariable localId="4" height="35" width="55">
+              <position x="315" y="650"/>
+              <connectionPointOut>
+                <relPosition x="55" y="15"/>
+              </connectionPointOut>
+              <expression>CODE</expression>
+            </inVariable>
+            <outVariable localId="5" height="35" width="45">
+              <position x="740" y="605"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="1" formalParameter="ACK">
+                  <position x="740" y="620"/>
+                  <position x="650" y="620"/>
+                </connection>
+              </connectionPointIn>
+              <expression>ACK</expression>
+            </outVariable>
+            <outVariable localId="6" height="35" width="75">
+              <position x="740" y="650"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="1" formalParameter="RESULT">
+                  <position x="740" y="665"/>
+                  <position x="650" y="665"/>
+                </connection>
+              </connectionPointIn>
+              <expression>RESULT</expression>
+            </outVariable>
+            <block localId="7" width="80" height="65" typeName="AND">
+              <position x="385" y="545"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="13" formalParameter="OUT">
+                      <position x="385" y="575"/>
+                      <position x="335" y="575"/>
+                      <position x="335" y="455"/>
+                      <position x="625" y="455"/>
+                      <position x="625" y="285"/>
+                      <position x="615" y="285"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="55"/>
+                    <connection refLocalId="3">
+                      <position x="385" y="600"/>
+                      <position x="330" y="600"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="80" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="9" height="35" width="85">
+              <position x="240" y="330"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>COUNTER</expression>
+            </inVariable>
+            <block localId="10" width="80" height="65" typeName="ADD">
+              <position x="380" y="330"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="9">
+                      <position x="380" y="360"/>
+                      <position x="352" y="360"/>
+                      <position x="352" y="345"/>
+                      <position x="325" y="345"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="55"/>
+                    <connection refLocalId="11">
+                      <position x="380" y="385"/>
+                      <position x="325" y="385"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="80" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="11" height="35" width="85">
+              <position x="240" y="370"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>USINT#1</expression>
+            </inVariable>
+            <block localId="13" width="80" height="65" typeName="EQ">
+              <position x="535" y="255"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="2">
+                      <position x="535" y="285"/>
+                      <position x="460" y="285"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="55"/>
+                    <connection refLocalId="10" formalParameter="OUT">
+                      <position x="535" y="310"/>
+                      <position x="497" y="310"/>
+                      <position x="497" y="360"/>
+                      <position x="460" y="360"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="80" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <block localId="15" width="80" height="135" typeName="SEL">
+              <position x="785" y="245"/>
+              <inputVariables>
+                <variable formalParameter="G">
+                  <connectionPointIn>
+                    <relPosition x="0" y="40"/>
+                    <connection refLocalId="13" formalParameter="OUT">
+                      <position x="785" y="285"/>
+                      <position x="615" y="285"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN0">
+                  <connectionPointIn>
+                    <relPosition x="0" y="75"/>
+                    <connection refLocalId="10" formalParameter="OUT">
+                      <position x="785" y="320"/>
+                      <position x="650" y="320"/>
+                      <position x="650" y="360"/>
+                      <position x="460" y="360"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="115"/>
+                    <connection refLocalId="16">
+                      <position x="785" y="360"/>
+                      <position x="760" y="360"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="80" y="40"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inVariable localId="16" height="35" width="85">
+              <position x="675" y="345"/>
+              <connectionPointOut>
+                <relPosition x="85" y="15"/>
+              </connectionPointOut>
+              <expression>USINT#0</expression>
+            </inVariable>
+            <outVariable localId="17" height="35" width="85">
+              <position x="905" y="270"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="15" formalParameter="OUT">
+                  <position x="905" y="285"/>
+                  <position x="865" y="285"/>
+                </connection>
+              </connectionPointIn>
+              <expression>COUNTER</expression>
+            </outVariable>
+          </FBD>
+        </body>
+      </pou>
+    </pous>
+  </types>
+  <instances>
+    <configurations/>
+  </instances>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/python.py	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,185 @@
+import wx
+import os
+import modules
+from ConfigTree import ConfigTreeNode, opjimg
+from PLCControler import UndoBuffer
+from PythonEditor import PythonEditor
+
+from xml.dom import minidom
+from xmlclass import *
+import cPickle
+
+PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd")) 
+
+class PythonCodeTemplate:
+    
+    EditorType = PythonEditor
+    
+    def __init__(self):
+        
+        self.ConfNodeMethods.insert(0, 
+                {"bitmap" : opjimg("editPYTHONcode"),
+                 "name" : _("Edit Python File"), 
+                 "tooltip" : _("Edit Python File"),
+                 "method" : "_OpenView"},
+        )
+
+        filepath = self.PythonFileName()
+        
+        self.PythonCode = PythonClasses["Python"]()
+        if os.path.isfile(filepath):
+            xmlfile = open(filepath, 'r')
+            tree = minidom.parse(xmlfile)
+            xmlfile.close()
+            
+            for child in tree.childNodes:
+                if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
+                    self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
+                    self.CreatePythonBuffer(True)
+        else:
+            self.CreatePythonBuffer(False)
+            self.OnPlugSave()
+
+    def ConfNodePath(self):
+        return os.path.join(self.PlugParent.ConfNodePath(), "modules", self.PlugType)
+
+    def PythonFileName(self):
+        return os.path.join(self.PlugPath(), "python.xml")
+
+    def GetFilename(self):
+        if self.PythonBuffer.IsCurrentSaved():
+            return "python"
+        else:
+            return "~python~"
+
+    def SetPythonCode(self, text):
+        self.PythonCode.settext(text)
+        
+    def GetPythonCode(self):
+        return self.PythonCode.gettext()
+    
+    def PlugTestModified(self):
+        return self.ChangesToSave or not self.PythonIsSaved()
+    
+    def OnPlugSave(self):
+        filepath = self.PythonFileName()
+        
+        text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
+        extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
+                  "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
+                  "xsi:schemaLocation" : "python_xsd.xsd"}
+        text += self.PythonCode.generateXMLText("Python", 0, extras)
+
+        xmlfile = open(filepath,"w")
+        xmlfile.write(text.encode("utf-8"))
+        xmlfile.close()
+        
+        self.MarkPythonAsSaved()
+        return True
+        
+#-------------------------------------------------------------------------------
+#                      Current Buffering Management Functions
+#-------------------------------------------------------------------------------
+
+    """
+    Return a copy of the project
+    """
+    def Copy(self, model):
+        return cPickle.loads(cPickle.dumps(model))
+
+    def CreatePythonBuffer(self, saved):
+        self.Buffering = False
+        self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
+
+    def BufferPython(self):
+        self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
+    
+    def StartBuffering(self):
+        self.Buffering = True
+        
+    def EndBuffering(self):
+        if self.Buffering:
+            self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
+            self.Buffering = False
+    
+    def MarkPythonAsSaved(self):
+        self.EndBuffering()
+        self.PythonBuffer.CurrentSaved()
+    
+    def PythonIsSaved(self):
+        return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
+        
+    def LoadPrevious(self):
+        self.EndBuffering()
+        self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
+    
+    def LoadNext(self):
+        self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
+    
+    def GetBufferState(self):
+        first = self.PythonBuffer.IsFirst() and not self.Buffering
+        last = self.PythonBuffer.IsLast()
+        return not first, not last
+
+def _GetClassFunction(name):
+    def GetRootClass():
+        __import__("confnodes.python.modules." + name)
+        return getattr(modules, name).RootClass
+    return GetRootClass
+
+class RootClass(PythonCodeTemplate):
+
+    # For root object, available Childs Types are modules of the modules packages.
+    PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
+    
+    def ConfNodePath(self):
+        return os.path.join(self.PlugParent.ConfNodePath(), self.PlugType)
+    
+    def PlugGenerate_C(self, buildpath, locations):
+        """
+        Generate C code
+        @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
+        @param locations: List of complete variables locations \
+            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+            "NAME" : name of the variable (generally "__IW0_1_2" style)
+            "DIR" : direction "Q","I" or "M"
+            "SIZE" : size "X", "B", "W", "D", "L"
+            "LOC" : tuple of interger for IEC location (0,1,2,...)
+            }, ...]
+        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+        """
+        current_location = self.GetCurrentLocation()
+        # define a unique name for the generated C file
+        location_str = "_".join(map(lambda x:str(x), current_location))
+        
+        ctr = self.GetPlugRoot()
+        ctr.GetIECProgramsAndVariables()
+        
+        plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c")
+        plc_python_file = open(plc_python_filepath, 'r')
+        plc_python_code = plc_python_file.read()
+        plc_python_file.close()
+        python_eval_fb_list = []
+        for v in ctr._VariablesList:
+            if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]:
+                python_eval_fb_list.append(v)
+        python_eval_fb_count = max(1, len(python_eval_fb_list))
+        
+        # prepare python code
+        plc_python_code = plc_python_code % {
+           "python_eval_fb_count": python_eval_fb_count,
+           "location": location_str}
+        
+        Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str)
+        pythonfile = open(Gen_Pythonfile_path,'w')
+        pythonfile.write(plc_python_code)
+        pythonfile.close()
+        
+        runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
+        runtimefile = open(runtimefile_path, 'w')
+        runtimefile.write(self.GetPythonCode())
+        runtimefile.close()
+        
+        matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
+        
+        return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/confnodes/python/python_xsd.xsd	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xsd:schema targetNamespace="python_xsd.xsd" 
+            xmlns:cext="python_xsd.xsd" 
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            elementFormDefault="qualified" 
+            attributeFormDefault="unqualified">
+
+  <xsd:element name="Python">
+	  <xsd:complexType>
+	    <xsd:annotation>
+	      <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
+	    </xsd:annotation>
+	    <xsd:sequence>
+	      <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
+	    </xsd:sequence>
+	  </xsd:complexType>
+	</xsd:element>
+</xsd:schema>
--- a/connectors/LPC/LPCBootObject.py	Thu May 03 19:02:34 2012 +0200
+++ b/connectors/LPC/LPCBootObject.py	Mon May 07 18:47:29 2012 +0200
@@ -26,8 +26,8 @@
 from LPCObject import *
 
 class LPCBootObject(LPCObject):
-    def __init__(self, pluginsroot, comportstr):
-        LPCObject.__init__(self, pluginsroot, comportstr)
+    def __init__(self, confnodesroot, comportstr):
+        LPCObject.__init__(self, confnodesroot, comportstr)
         self.successfully_transfered = False
     
     def connect(self,comport):
--- a/connectors/LPC/LPCObject.py	Thu May 03 19:02:34 2012 +0200
+++ b/connectors/LPC/LPCObject.py	Mon May 07 18:47:29 2012 +0200
@@ -27,16 +27,16 @@
 
 
 class LPCObject():
-    def __init__(self, pluginsroot, comportstr):
+    def __init__(self, confnodesroot, comportstr):
         self.PLCStatus = "Disconnected"
-        self.pluginsroot = pluginsroot
-        self.PLCprint = pluginsroot.logger.writeyield
+        self.confnodesroot = confnodesroot
+        self.PLCprint = confnodesroot.logger.writeyield
         self._Idxs = []
         comport = int(comportstr[3:]) - 1
         try:
             self.connect(comportstr)
         except Exception,e:
-            self.pluginsroot.logger.write_error(str(e)+"\n")
+            self.confnodesroot.logger.write_error(str(e)+"\n")
             self.SerialConnection = None
             self.PLCStatus = "Disconnected"
 
@@ -46,14 +46,14 @@
                 self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction)
                 return res
             except LPCProtoError,e:
-                self.pluginsroot.logger.write(_("PLC disconnected\n"))
+                self.confnodesroot.logger.write(_("PLC disconnected\n"))
                 if self.SerialConnection is not None:
                     self.SerialConnection.close()
                     self.SerialConnection = None
                 self.PLCStatus = "Disconnected"
                 return None
             except Exception,e:
-                self.pluginsroot.logger.write_warning(str(e)+"\n")
+                self.confnodesroot.logger.write_warning(str(e)+"\n")
         
     def StartPLC(self, debug=False):
         raise LPCProtoError("Not implemented")
--- a/connectors/LPC/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ b/connectors/LPC/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -19,7 +19,7 @@
 #License along with this library; if not, write to the Free Software
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-def LPC_connector_factory(uri, pluginsroot):
+def LPC_connector_factory(uri, confnodesroot):
     """
     This returns the connector to LPC style PLCobject
     """
@@ -27,9 +27,9 @@
     mode,comportstr = location.split('/')
     if mode=="APPLICATION":
         from LPCAppObject import LPCAppObject 
-        return LPCAppObject(pluginsroot,comportstr)
+        return LPCAppObject(confnodesroot,comportstr)
     elif mode=="BOOTLOADER":
         from LPCBootObject import LPCBootObject 
-        return LPCBootObject(pluginsroot,comportstr)
+        return LPCBootObject(confnodesroot,comportstr)
 
 
--- a/connectors/PYRO/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ b/connectors/PYRO/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -26,17 +26,17 @@
 import copy
 
 # this module attribute contains a list of DNS-SD (Zeroconf) service types
-# supported by this connector plugin.
+# supported by this connector confnode.
 #
 # for connectors that do not support DNS-SD, this attribute can be omitted
 # or set to an empty list.
 supported_dnssd_services = ["_PYRO._tcp.local."]
 
-def PYRO_connector_factory(uri, pluginsroot):
+def PYRO_connector_factory(uri, confnodesroot):
     """
     This returns the connector to Pyro style PLCobject
     """
-    pluginsroot.logger.write(_("Connecting to URI : %s\n")%uri)
+    confnodesroot.logger.write(_("Connecting to URI : %s\n")%uri)
 
     servicetype, location = uri.split("://")
     
@@ -44,8 +44,8 @@
     try :
         RemotePLCObjectProxy = pyro.getAttrProxyForURI("PYROLOC://"+location+"/PLCObject")
     except Exception, msg:
-        pluginsroot.logger.write_error(_("Wrong URI, please check it !\n"))
-        pluginsroot.logger.write_error(traceback.format_exc())
+        confnodesroot.logger.write_error(_("Wrong URI, please check it !\n"))
+        confnodesroot.logger.write_error(traceback.format_exc())
         return None
 
     def PyroCatcher(func, default=None):
@@ -59,21 +59,21 @@
             except Pyro.errors.ProtocolError, e:
                 pass
             except Pyro.errors.ConnectionClosedError, e:
-                pluginsroot.logger.write_error("Connection lost!\n")
-                pluginsroot._connector = None
+                confnodesroot.logger.write_error("Connection lost!\n")
+                confnodesroot._connector = None
             except Exception,e:
-                #pluginsroot.logger.write_error(traceback.format_exc())
+                #confnodesroot.logger.write_error(traceback.format_exc())
                 errmess = ''.join(Pyro.util.getPyroTraceback(e))
-                pluginsroot.logger.write_error(errmess+"\n")
+                confnodesroot.logger.write_error(errmess+"\n")
                 print errmess
-                pluginsroot._connector = None
+                confnodesroot._connector = None
                 return default
         return catcher_func
 
     # Check connection is effective. 
     # lambda is for getattr of GetPLCstatus to happen inside catcher
     if PyroCatcher(lambda:RemotePLCObjectProxy.GetPLCstatus())() == None:
-        pluginsroot.logger.write_error(_("Cannot get PLC status - connection failed.\n"))
+        confnodesroot.logger.write_error(_("Cannot get PLC status - connection failed.\n"))
         return None
 
 
@@ -95,25 +95,25 @@
 
         def _PyroStartPLC(self, *args, **kwargs):
             """
-            pluginsroot._connector.GetPyroProxy() is used 
+            confnodesroot._connector.GetPyroProxy() is used 
             rather than RemotePLCObjectProxy because
             object is recreated meanwhile, 
             so we must not keep ref to it here
             """
-            current_status = pluginsroot._connector.GetPyroProxy().GetPLCstatus()
+            current_status = confnodesroot._connector.GetPyroProxy().GetPLCstatus()
             if current_status == "Dirty":
                 """
                 Some bad libs with static symbols may polute PLC
                 ask runtime to suicide and come back again
                 """
-                pluginsroot.logger.write(_("Force runtime reload\n"))
-                pluginsroot._connector.GetPyroProxy().ForceReload()
-                pluginsroot._Disconnect()
+                confnodesroot.logger.write(_("Force runtime reload\n"))
+                confnodesroot._connector.GetPyroProxy().ForceReload()
+                confnodesroot._Disconnect()
                 # let remote PLC time to resurect.(freeze app)
                 sleep(0.5)
-                pluginsroot._Connect()
-            self.RemotePLCObjectProxyCopy = copy.copy(pluginsroot._connector.GetPyroProxy())
-            return pluginsroot._connector.GetPyroProxy().StartPLC(*args, **kwargs)
+                confnodesroot._Connect()
+            self.RemotePLCObjectProxyCopy = copy.copy(confnodesroot._connector.GetPyroProxy())
+            return confnodesroot._connector.GetPyroProxy().StartPLC(*args, **kwargs)
         StartPLC = PyroCatcher(_PyroStartPLC, False)
 
 
@@ -122,7 +122,7 @@
             for safe use in from debug thread, must use the copy
             """
             if self.RemotePLCObjectProxyCopy is None:
-                self.RemotePLCObjectProxyCopy = copy.copy(pluginsroot._connector.GetPyroProxy())
+                self.RemotePLCObjectProxyCopy = copy.copy(confnodesroot._connector.GetPyroProxy())
             return self.RemotePLCObjectProxyCopy.GetTraceVariables()
         GetTraceVariables = PyroCatcher(_PyroGetTraceVariables,("Broken",None,None))
 
--- a/connectors/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ b/connectors/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -46,7 +46,7 @@
         for st in new_module.supported_dnssd_services:
             dnssd_connectors[st] = new_module
 
-def ConnectorFactory(uri, pluginsroot):
+def ConnectorFactory(uri, confnodesroot):
     """
     Return a connector corresponding to the URI
     or None if cannot connect to URI
@@ -56,12 +56,12 @@
         # import module according to uri type
         connectormodule = connector_modules[servicetype]
         factoryname = servicetype + "_connector_factory"
-        return getattr(connectormodule, factoryname)(uri, pluginsroot)
+        return getattr(connectormodule, factoryname)(uri, confnodesroot)
     elif servicetype == "LOCAL":
-        runtime_port = pluginsroot.AppFrame.StartLocalRuntime(taskbaricon=True)
+        runtime_port = confnodesroot.AppFrame.StartLocalRuntime(taskbaricon=True)
         return PYRO.PYRO_connector_factory(
                        "PYRO://127.0.0.1:"+str(runtime_port), 
-                       pluginsroot)
+                       confnodesroot)
     else :
         return None    
 
--- a/plugger.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2063 +0,0 @@
-"""
-Base definitions for beremiz plugins
-"""
-
-import os,sys,traceback
-import time
-import plugins
-import types
-import shutil
-from xml.dom import minidom
-import wx
-
-#Quick hack to be able to find Beremiz IEC tools. Should be config params.
-base_folder = os.path.split(sys.path[0])[0]
-
-from xmlclass import GenerateClassesFromXSDstring
-from wxPopen import ProcessLogger
-
-from PLCControler import PLCControler, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
-
-_BaseParamsClass = GenerateClassesFromXSDstring("""<?xml version="1.0" encoding="ISO-8859-1" ?>
-        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-          <xsd:element name="BaseParams">
-            <xsd:complexType>
-              <xsd:attribute name="Name" type="xsd:string" use="optional" default="__unnamed__"/>
-              <xsd:attribute name="IEC_Channel" type="xsd:integer" use="required"/>
-              <xsd:attribute name="Enabled" type="xsd:boolean" use="optional" default="true"/>
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:schema>""")["BaseParams"]
-
-NameTypeSeparator = '@'
-
-class MiniTextControler:
-    
-    def __init__(self, filepath):
-        self.FilePath = filepath
-    
-    def PlugFullName(self):
-        return ""
-    
-    def SetEditedElementText(self, tagname, text):
-        file = open(self.FilePath, "w")
-        file.write(text)
-        file.close()
-        
-    def GetEditedElementText(self, tagname, debug = False):
-        if os.path.isfile(self.FilePath):
-            file = open(self.FilePath, "r")
-            text = file.read()
-            file.close()
-            return text
-        return ""
-    
-    def GetEditedElementInterfaceVars(self, tagname, debug = False):
-        return []
-    
-    def GetEditedElementType(self, tagname, debug = False):
-        return "program"
-    
-    def GetBlockTypes(self, tagname = "", debug = False):
-        return []
-    
-    def GetDataTypes(self, tagname = "", basetypes = True, only_locatables = False, debug = False):
-        return []
-    
-    def GetEnumeratedDataValues(self, debug = False):
-        return []
-    
-    def StartBuffering(self):
-        pass
-
-    def EndBuffering(self):
-        pass
-
-    def BufferProject(self):
-        pass
-
-# helper func to get path to images
-def opjimg(imgname):
-    return os.path.join(base_folder, "beremiz", "images",imgname)
-    
-# helper func to check path write permission
-def CheckPathPerm(path):
-    if path is None or not os.path.isdir(path):
-        return False
-    for root, dirs, files in os.walk(path):
-         for name in files:
-             if os.access(root, os.W_OK) is not True or os.access(os.path.join(root, name), os.W_OK) is not True:
-                 return False
-    return True
-    
-class PlugTemplate:
-    """
-    This class is the one that define plugins.
-    """
-
-    XSD = None
-    PlugChildsTypes = []
-    PlugMaxCount = None
-    PluginMethods = []
-    LibraryControler = None
-    EditorType = None
-
-    def _AddParamsMembers(self):
-        self.PlugParams = None
-        if self.XSD:
-            self.Classes = GenerateClassesFromXSDstring(self.XSD)
-            Classes = [(name, XSDclass) for name, XSDclass in self.Classes.items() if XSDclass.IsBaseClass]
-            if len(Classes) == 1:
-                name, XSDclass = Classes[0]
-                obj = XSDclass()
-                self.PlugParams = (name, obj)
-                setattr(self, name, obj)
-
-    def __init__(self):
-        # Create BaseParam 
-        self.BaseParams = _BaseParamsClass()
-        self.MandatoryParams = ("BaseParams", self.BaseParams)
-        self._AddParamsMembers()
-        self.PluggedChilds = {}
-        self._View = None
-        # copy PluginMethods so that it can be later customized
-        self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
-        self.LoadSTLibrary()
-        
-    def PluginBaseXmlFilePath(self, PlugName=None):
-        return os.path.join(self.PlugPath(PlugName), "baseplugin.xml")
-    
-    def PluginXmlFilePath(self, PlugName=None):
-        return os.path.join(self.PlugPath(PlugName), "plugin.xml")
-
-    def PluginLibraryFilePath(self):
-        return os.path.join(self.PluginPath(), "pous.xml")
-
-    def PluginPath(self):
-        return os.path.join(self.PlugParent.PluginPath(), self.PlugType)
-
-    def PlugPath(self,PlugName=None):
-        if not PlugName:
-            PlugName = self.PlugName()
-        return os.path.join(self.PlugParent.PlugPath(),
-                            PlugName + NameTypeSeparator + self.PlugType)
-    
-    def PlugName(self):
-        return self.BaseParams.getName()
-    
-    def PlugEnabled(self):
-        return self.BaseParams.getEnabled()
-    
-    def PlugFullName(self):
-        parent = self.PlugParent.PlugFullName()
-        if parent != "":
-            return parent + "." + self.PlugName()
-        return self.BaseParams.getName()
-    
-    def GetIconPath(self, name):
-        return opjimg(name)
-    
-    def PlugTestModified(self):
-        return self.ChangesToSave
-
-    def ProjectTestModified(self):
-        """
-        recursively check modified status
-        """
-        if self.PlugTestModified():
-            return True
-
-        for PlugChild in self.IterChilds():
-            if PlugChild.ProjectTestModified():
-                return True
-
-        return False
-    
-    def RemoteExec(self, script, **kwargs):
-        return self.PlugParent.RemoteExec(script, **kwargs)
-    
-    def OnPlugSave(self):
-        #Default, do nothing and return success
-        return True
-
-    def GetParamsAttributes(self, path = None):
-        if path:
-            parts = path.split(".", 1)
-            if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
-                return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
-            elif self.PlugParams and parts[0] == self.PlugParams[0]:
-                return self.PlugParams[1].getElementInfos(parts[0], parts[1])
-        else:
-            params = []
-            if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
-                params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
-            if self.PlugParams:
-                params.append(self.PlugParams[1].getElementInfos(self.PlugParams[0]))
-            return params
-        
-    def SetParamsAttribute(self, path, value):
-        self.ChangesToSave = True
-        # Filter IEC_Channel and Name, that have specific behavior
-        if path == "BaseParams.IEC_Channel":
-            old_leading = ".".join(map(str, self.GetCurrentLocation()))
-            new_value = self.FindNewIEC_Channel(value)
-            new_leading = ".".join(map(str, self.PlugParent.GetCurrentLocation() + (new_value,)))
-            self.GetPlugRoot().UpdateProjectVariableLocation(old_leading, new_leading)
-            return new_value, True
-        elif path == "BaseParams.Name":
-            res = self.FindNewName(value)
-            self.PlugRequestSave()
-            return res, True
-        
-        parts = path.split(".", 1)
-        if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
-            self.MandatoryParams[1].setElementValue(parts[1], value)
-        elif self.PlugParams and parts[0] == self.PlugParams[0]:
-            self.PlugParams[1].setElementValue(parts[1], value)
-        return value, False
-
-    def PlugMakeDir(self):
-        os.mkdir(self.PlugPath())
-
-    def PlugRequestSave(self):
-        if self.GetPlugRoot().CheckProjectPathPerm(False):
-            # If plugin do not have corresponding directory
-            plugpath = self.PlugPath()
-            if not os.path.isdir(plugpath):
-                # Create it
-                os.mkdir(plugpath)
-    
-            # generate XML for base XML parameters controller of the plugin
-            if self.MandatoryParams:
-                BaseXMLFile = open(self.PluginBaseXmlFilePath(),'w')
-                BaseXMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
-                BaseXMLFile.write(self.MandatoryParams[1].generateXMLText(self.MandatoryParams[0], 0).encode("utf-8"))
-                BaseXMLFile.close()
-            
-            # generate XML for XML parameters controller of the plugin
-            if self.PlugParams:
-                XMLFile = open(self.PluginXmlFilePath(),'w')
-                XMLFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
-                XMLFile.write(self.PlugParams[1].generateXMLText(self.PlugParams[0], 0).encode("utf-8"))
-                XMLFile.close()
-            
-            # Call the plugin specific OnPlugSave method
-            result = self.OnPlugSave()
-            if not result:
-                return _("Error while saving \"%s\"\n")%self.PlugPath()
-    
-            # mark plugin as saved
-            self.ChangesToSave = False
-            # go through all childs and do the same
-            for PlugChild in self.IterChilds():
-                result = PlugChild.PlugRequestSave()
-                if result:
-                    return result
-        return None
-    
-    def PlugImport(self, src_PlugPath):
-        shutil.copytree(src_PlugPath, self.PlugPath)
-        return True
-
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Generate C code
-        @param locations: List of complete variables locations \
-            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
-            "NAME" : name of the variable (generally "__IW0_1_2" style)
-            "DIR" : direction "Q","I" or "M"
-            "SIZE" : size "X", "B", "W", "D", "L"
-            "LOC" : tuple of interger for IEC location (0,1,2,...)
-            }, ...]
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-        self.GetPlugRoot().logger.write_warning(".".join(map(lambda x:str(x), self.GetCurrentLocation())) + " -> Nothing to do\n")
-        return [],"",False
-    
-    def _Generate_C(self, buildpath, locations):
-        # Generate plugins [(Cfiles, CFLAGS)], LDFLAGS, DoCalls, extra_files
-        # extra_files = [(fname,fobject), ...]
-        gen_result = self.PlugGenerate_C(buildpath, locations)
-        PlugCFilesAndCFLAGS, PlugLDFLAGS, DoCalls = gen_result[:3]
-        extra_files = gen_result[3:]
-        # if some files have been generated put them in the list with their location
-        if PlugCFilesAndCFLAGS:
-            LocationCFilesAndCFLAGS = [(self.GetCurrentLocation(), PlugCFilesAndCFLAGS, DoCalls)]
-        else:
-            LocationCFilesAndCFLAGS = []
-
-        # plugin asks for some LDFLAGS
-        if PlugLDFLAGS:
-            # LDFLAGS can be either string
-            if type(PlugLDFLAGS)==type(str()):
-                LDFLAGS=[PlugLDFLAGS]
-            #or list of strings
-            elif type(PlugLDFLAGS)==type(list()):
-                LDFLAGS=PlugLDFLAGS[:]
-        else:
-            LDFLAGS=[]
-        
-        # recurse through all childs, and stack their results
-        for PlugChild in self.IECSortedChilds():
-            new_location = PlugChild.GetCurrentLocation()
-            # How deep are we in the tree ?
-            depth=len(new_location)
-            _LocationCFilesAndCFLAGS, _LDFLAGS, _extra_files = \
-                PlugChild._Generate_C(
-                    #keep the same path
-                    buildpath,
-                    # filter locations that start with current IEC location
-                    [loc for loc in locations if loc["LOC"][0:depth] == new_location ])
-            # stack the result
-            LocationCFilesAndCFLAGS += _LocationCFilesAndCFLAGS
-            LDFLAGS += _LDFLAGS
-            extra_files += _extra_files
-        
-        return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
-
-    def PluginTypesFactory(self):
-        if self.LibraryControler is not None:
-            return [{"name" : self.PlugType, "types": self.LibraryControler.Project}]
-        return []
-
-    def ParentsTypesFactory(self):
-        return self.PlugParent.ParentsTypesFactory() + self.PluginTypesFactory()
-
-    def PluginsTypesFactory(self):
-        list = self.PluginTypesFactory()
-        for PlugChild in self.IterChilds():
-            list += PlugChild.PluginsTypesFactory()
-        return list
-
-    def STLibraryFactory(self):
-        if self.LibraryControler is not None:
-            program, errors, warnings = self.LibraryControler.GenerateProgram()
-            return program + "\n"
-        return ""
-
-    def PluginsSTLibraryFactory(self):
-        program = self.STLibraryFactory()
-        for PlugChild in self.IECSortedChilds():
-            program += PlugChild.PluginsSTLibraryFactory()
-        return program
-        
-    def IterChilds(self):
-        for PlugType, PluggedChilds in self.PluggedChilds.items():
-            for PlugInstance in PluggedChilds:
-                yield PlugInstance
-    
-    def IECSortedChilds(self):
-        # reorder childs by IEC_channels
-        ordered = [(chld.BaseParams.getIEC_Channel(),chld) for chld in self.IterChilds()]
-        if ordered:
-            ordered.sort()
-            return zip(*ordered)[1]
-        else:
-            return []
-    
-    def _GetChildBySomething(self, something, toks):
-        for PlugInstance in self.IterChilds():
-            # if match component of the name
-            if getattr(PlugInstance.BaseParams, something) == toks[0]:
-                # if Name have other components
-                if len(toks) >= 2:
-                    # Recurse in order to find the latest object
-                    return PlugInstance._GetChildBySomething( something, toks[1:])
-                # No sub name -> found
-                return PlugInstance
-        # Not found
-        return None
-
-    def GetChildByName(self, Name):
-        if Name:
-            toks = Name.split('.')
-            return self._GetChildBySomething("Name", toks)
-        else:
-            return self
-
-    def GetChildByIECLocation(self, Location):
-        if Location:
-            return self._GetChildBySomething("IEC_Channel", Location)
-        else:
-            return self
-    
-    def GetCurrentLocation(self):
-        """
-        @return:  Tupple containing plugin IEC location of current plugin : %I0.0.4.5 => (0,0,4,5)
-        """
-        return self.PlugParent.GetCurrentLocation() + (self.BaseParams.getIEC_Channel(),)
-
-    def GetCurrentName(self):
-        """
-        @return:  String "ParentParentName.ParentName.Name"
-        """
-        return  self.PlugParent._GetCurrentName() + self.BaseParams.getName()
-
-    def _GetCurrentName(self):
-        """
-        @return:  String "ParentParentName.ParentName.Name."
-        """
-        return  self.PlugParent._GetCurrentName() + self.BaseParams.getName() + "."
-
-    def GetPlugRoot(self):
-        return self.PlugParent.GetPlugRoot()
-
-    def GetFullIEC_Channel(self):
-        return ".".join([str(i) for i in self.GetCurrentLocation()]) + ".x"
-
-    def GetLocations(self):
-        location = self.GetCurrentLocation()
-        return [loc for loc in self.PlugParent.GetLocations() if loc["LOC"][0:len(location)] == location]
-
-    def GetVariableLocationTree(self):
-        '''
-        This function is meant to be overridden by plugins.
-
-        It should returns an list of dictionaries
-        
-        - IEC_type is an IEC type like BOOL/BYTE/SINT/...
-        - location is a string of this variable's location, like "%IX0.0.0"
-        '''
-        children = []
-        for child in self.IECSortedChilds():
-            children.append(child.GetVariableLocationTree())
-        return {"name": self.BaseParams.getName(),
-                "type": LOCATION_PLUGIN,
-                "location": self.GetFullIEC_Channel(),
-                "children": children}
-
-    def FindNewName(self, DesiredName):
-        """
-        Changes Name to DesiredName if available, Name-N if not.
-        @param DesiredName: The desired Name (string)
-        """
-        # Get Current Name
-        CurrentName = self.BaseParams.getName()
-        # Do nothing if no change
-        #if CurrentName == DesiredName: return CurrentName
-        # Build a list of used Name out of parent's PluggedChilds
-        AllNames=[]
-        for PlugInstance in self.PlugParent.IterChilds():
-            if PlugInstance != self:
-                AllNames.append(PlugInstance.BaseParams.getName())
-
-        # Find a free name, eventually appending digit
-        res = DesiredName
-        suffix = 1
-        while res in AllNames:
-            res = "%s-%d"%(DesiredName, suffix)
-            suffix += 1
-        
-        # Get old path
-        oldname = self.PlugPath()
-        # Check previous plugin existance
-        dontexist = self.BaseParams.getName() == "__unnamed__"
-        # Set the new name
-        self.BaseParams.setName(res)
-        # Rename plugin dir if exist
-        if not dontexist:
-            shutil.move(oldname, self.PlugPath())
-        # warn user he has two left hands
-        if DesiredName != res:
-            self.GetPlugRoot().logger.write_warning(_("A child names \"%s\" already exist -> \"%s\"\n")%(DesiredName,res))
-        return res
-
-    def GetAllChannels(self):
-        AllChannels=[]
-        for PlugInstance in self.PlugParent.IterChilds():
-            if PlugInstance != self:
-                AllChannels.append(PlugInstance.BaseParams.getIEC_Channel())
-        AllChannels.sort()
-        return AllChannels
-
-    def FindNewIEC_Channel(self, DesiredChannel):
-        """
-        Changes IEC Channel number to DesiredChannel if available, nearest available if not.
-        @param DesiredChannel: The desired IEC channel (int)
-        """
-        # Get Current IEC channel
-        CurrentChannel = self.BaseParams.getIEC_Channel()
-        # Do nothing if no change
-        #if CurrentChannel == DesiredChannel: return CurrentChannel
-        # Build a list of used Channels out of parent's PluggedChilds
-        AllChannels = self.GetAllChannels()
-        
-        # Now, try to guess the nearest available channel
-        res = DesiredChannel
-        while res in AllChannels: # While channel not free
-            if res < CurrentChannel: # Want to go down ?
-                res -=  1 # Test for n-1
-                if res < 0 :
-                    self.GetPlugRoot().logger.write_warning(_("Cannot find lower free IEC channel than %d\n")%CurrentChannel)
-                    return CurrentChannel # Can't go bellow 0, do nothing
-            else : # Want to go up ?
-                res +=  1 # Test for n-1
-        # Finally set IEC Channel
-        self.BaseParams.setIEC_Channel(res)
-        return res
-
-    def _OpenView(self, name=None):
-        if self.EditorType is not None and self._View is None:
-            app_frame = self.GetPlugRoot().AppFrame
-            
-            self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
-            
-            app_frame.EditProjectElement(self._View, self.PlugName())
-            
-            return self._View
-        return None
-
-    def OnCloseEditor(self, view):
-        if self._View == view:
-            self._View = None
-
-    def OnPlugClose(self):
-        if self._View is not None:
-            app_frame = self.GetPlugRoot().AppFrame
-            if app_frame is not None:
-                app_frame.DeletePage(self._View)
-        return True
-
-    def _doRemoveChild(self, PlugInstance):
-        # Remove all childs of child
-        for SubPlugInstance in PlugInstance.IterChilds():
-            PlugInstance._doRemoveChild(SubPlugInstance)
-        # Call the OnCloseMethod
-        PlugInstance.OnPlugClose()
-        # Delete plugin dir
-        shutil.rmtree(PlugInstance.PlugPath())
-        # Remove child of PluggedChilds
-        self.PluggedChilds[PlugInstance.PlugType].remove(PlugInstance)
-        # Forget it... (View have to refresh)
-
-    def PlugRemove(self):
-        # Fetch the plugin
-        #PlugInstance = self.GetChildByName(PlugName)
-        # Ask to his parent to remove it
-        self.PlugParent._doRemoveChild(self)
-
-    def PlugAddChild(self, PlugName, PlugType, IEC_Channel=0):
-        """
-        Create the plugins that may be added as child to this node self
-        @param PlugType: string desining the plugin class name (get name from PlugChildsTypes)
-        @param PlugName: string for the name of the plugin instance
-        """
-        # reorgabize self.PlugChildsTypes tuples from (name, PlugClass, Help)
-        # to ( name, (PlugClass, Help)), an make a dict
-        transpose = zip(*self.PlugChildsTypes)
-        PlugChildsTypes = dict(zip(transpose[0],zip(transpose[1],transpose[2])))
-        # Check that adding this plugin is allowed
-        try:
-            PlugClass, PlugHelp = PlugChildsTypes[PlugType]
-        except KeyError:
-            raise Exception, _("Cannot create child %s of type %s ")%(PlugName, PlugType)
-        
-        # if PlugClass is a class factory, call it. (prevent unneeded imports)
-        if type(PlugClass) == types.FunctionType:
-            PlugClass = PlugClass()
-        
-        # Eventualy Initialize child instance list for this class of plugin
-        PluggedChildsWithSameClass = self.PluggedChilds.setdefault(PlugType, list())
-        # Check count
-        if getattr(PlugClass, "PlugMaxCount", None) and len(PluggedChildsWithSameClass) >= PlugClass.PlugMaxCount:
-            raise Exception, _("Max count (%d) reached for this plugin of type %s ")%(PlugClass.PlugMaxCount, PlugType)
-        
-        # create the final class, derived of provided plugin and template
-        class FinalPlugClass(PlugClass, PlugTemplate):
-            """
-            Plugin class is derivated into FinalPlugClass before being instanciated
-            This way __init__ is overloaded to ensure PlugTemplate.__init__ is called 
-            before PlugClass.__init__, and to do the file related stuff.
-            """
-            def __init__(_self):
-                # self is the parent
-                _self.PlugParent = self
-                # Keep track of the plugin type name
-                _self.PlugType = PlugType
-                # remind the help string, for more fancy display
-                _self.PlugHelp = PlugHelp
-                # Call the base plugin template init - change XSD into class members
-                PlugTemplate.__init__(_self)
-                # check name is unique
-                NewPlugName = _self.FindNewName(PlugName)
-                # If dir have already be made, and file exist
-                if os.path.isdir(_self.PlugPath(NewPlugName)): #and os.path.isfile(_self.PluginXmlFilePath(PlugName)):
-                    #Load the plugin.xml file into parameters members
-                    _self.LoadXMLParams(NewPlugName)
-                    # Basic check. Better to fail immediately.
-                    if (_self.BaseParams.getName() != NewPlugName):
-                        raise Exception, _("Project tree layout do not match plugin.xml %s!=%s ")%(NewPlugName, _self.BaseParams.getName())
-
-                    # Now, self.PlugPath() should be OK
-                    
-                    # Check that IEC_Channel is not already in use.
-                    _self.FindNewIEC_Channel(_self.BaseParams.getIEC_Channel())
-                    # Call the plugin real __init__
-                    if getattr(PlugClass, "__init__", None):
-                        PlugClass.__init__(_self)
-                    #Load and init all the childs
-                    _self.LoadChilds()
-                    #just loaded, nothing to saved
-                    _self.ChangesToSave = False
-                else:
-                    # If plugin do not have corresponding file/dirs - they will be created on Save
-                    _self.PlugMakeDir()
-                    # Find an IEC number
-                    _self.FindNewIEC_Channel(IEC_Channel)
-                    # Call the plugin real __init__
-                    if getattr(PlugClass, "__init__", None):
-                        PlugClass.__init__(_self)
-                    _self.PlugRequestSave()
-                    #just created, must be saved
-                    _self.ChangesToSave = True
-                
-            def _getBuildPath(_self):
-                return self._getBuildPath()
-            
-        # Create the object out of the resulting class
-        newPluginOpj = FinalPlugClass()
-        # Store it in PluggedChils
-        PluggedChildsWithSameClass.append(newPluginOpj)
-        
-        return newPluginOpj
-    
-    def ClearPluggedChilds(self):
-        for child in self.IterChilds():
-            child.ClearPluggedChilds()
-        self.PluggedChilds = {}
-    
-    def LoadSTLibrary(self):
-        # Get library blocks if plcopen library exist
-        library_path = self.PluginLibraryFilePath()
-        if os.path.isfile(library_path):
-            self.LibraryControler = PLCControler()
-            self.LibraryControler.OpenXMLFile(library_path)
-            self.LibraryControler.ClearPluginTypes()
-            self.LibraryControler.AddPluginTypesList(self.ParentsTypesFactory())
-
-    def LoadXMLParams(self, PlugName = None):
-        methode_name = os.path.join(self.PlugPath(PlugName), "methods.py")
-        if os.path.isfile(methode_name):
-            execfile(methode_name)
-        
-        # Get the base xml tree
-        if self.MandatoryParams:
-            try:
-                basexmlfile = open(self.PluginBaseXmlFilePath(PlugName), 'r')
-                basetree = minidom.parse(basexmlfile)
-                self.MandatoryParams[1].loadXMLTree(basetree.childNodes[0])
-                basexmlfile.close()
-            except Exception, exc:
-                self.GetPlugRoot().logger.write_error(_("Couldn't load plugin base parameters %s :\n %s") % (PlugName, str(exc)))
-                self.GetPlugRoot().logger.write_error(traceback.format_exc())
-        
-        # Get the xml tree
-        if self.PlugParams:
-            try:
-                xmlfile = open(self.PluginXmlFilePath(PlugName), 'r')
-                tree = minidom.parse(xmlfile)
-                self.PlugParams[1].loadXMLTree(tree.childNodes[0])
-                xmlfile.close()
-            except Exception, exc:
-                self.GetPlugRoot().logger.write_error(_("Couldn't load plugin parameters %s :\n %s") % (PlugName, str(exc)))
-                self.GetPlugRoot().logger.write_error(traceback.format_exc())
-        
-    def LoadChilds(self):
-        # Iterate over all PlugName@PlugType in plugin directory, and try to open them
-        for PlugDir in os.listdir(self.PlugPath()):
-            if os.path.isdir(os.path.join(self.PlugPath(), PlugDir)) and \
-               PlugDir.count(NameTypeSeparator) == 1:
-                pname, ptype = PlugDir.split(NameTypeSeparator)
-                try:
-                    self.PlugAddChild(pname, ptype)
-                except Exception, exc:
-                    self.GetPlugRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc)))
-                    self.GetPlugRoot().logger.write_error(traceback.format_exc())
-
-    def EnableMethod(self, method, value):
-        for d in self.PluginMethods:
-            if d["method"]==method:
-                d["enabled"]=value
-                return True
-        return False
-
-    def ShowMethod(self, method, value):
-        for d in self.PluginMethods:
-            if d["method"]==method:
-                d["shown"]=value
-                return True
-        return False
-
-    def CallMethod(self, method):
-        for d in self.PluginMethods:
-            if d["method"]==method and d.get("enabled", True) and d.get("shown", True):
-                getattr(self, method)()
-
-def _GetClassFunction(name):
-    def GetRootClass():
-        return getattr(__import__("plugins." + name), name).RootClass
-    return GetRootClass
-
-
-####################################################################################
-####################################################################################
-####################################################################################
-###################################   ROOT    ######################################
-####################################################################################
-####################################################################################
-####################################################################################
-
-if wx.Platform == '__WXMSW__':
-    exe_ext=".exe"
-else:
-    exe_ext=""
-
-# import for project creation timestamping
-from threading import Timer, Lock, Thread, Semaphore
-from time import localtime
-from datetime import datetime
-# import necessary stuff from PLCOpenEditor
-from PLCOpenEditor import PLCOpenEditor, ProjectDialog
-from TextViewer import TextViewer
-from plcopen.structures import IEC_KEYWORDS, TypeHierarchy_list
-
-
-import re, tempfile
-import targets
-from targets.typemapping import DebugTypesSize
-
-import connectors
-from discovery import DiscoveryDialog
-from weakref import WeakKeyDictionary
-
-MATIEC_ERROR_MODEL = re.compile(".*\.st:(\d+)-(\d+)\.\.(\d+)-(\d+): error : (.*)$")
-
-DEBUG_RETRIES_WARN = 3
-DEBUG_RETRIES_REREGISTER = 4
-
-class PluginsRoot(PlugTemplate, PLCControler):
-    """
-    This class define Root object of the plugin tree. 
-    It is responsible of :
-    - Managing project directory
-    - Building project
-    - Handling PLCOpenEditor controler and view
-    - Loading user plugins and instanciante them as childs
-    - ...
-    
-    """
-
-    # For root object, available Childs Types are modules of the plugin packages.
-    PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(plugins.__all__,plugins.helps)]
-
-    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
-    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-      <xsd:element name="BeremizRoot">
-        <xsd:complexType>
-          <xsd:sequence>
-            <xsd:element name="TargetType">
-              <xsd:complexType>
-                <xsd:choice minOccurs="0">
-                """+targets.targetchoices+"""
-                </xsd:choice>
-              </xsd:complexType>
-            </xsd:element>
-          </xsd:sequence>
-          <xsd:attribute name="URI_location" type="xsd:string" use="optional" default=""/>
-          <xsd:attribute name="Enable_Plugins" type="xsd:boolean" use="optional" default="true"/>
-        </xsd:complexType>
-      </xsd:element>
-    </xsd:schema>
-    """
-
-    def __init__(self, frame, logger):
-        PLCControler.__init__(self)
-
-        self.MandatoryParams = None
-        self.SetAppFrame(frame, logger)
-        self._builder = None
-        self._connector = None
-        
-        self.iec2c_path = os.path.join(base_folder, "matiec", "iec2c"+exe_ext)
-        self.ieclib_path = os.path.join(base_folder, "matiec", "lib")
-        
-        # Setup debug information
-        self.IECdebug_datas = {}
-        self.IECdebug_lock = Lock()
-
-        self.DebugTimer=None
-        self.ResetIECProgramsAndVariables()
-        
-        #This method are not called here... but in NewProject and OpenProject
-        #self._AddParamsMembers()
-        #self.PluggedChilds = {}
-
-        # In both new or load scenario, no need to save
-        self.ChangesToSave = False
-        # root have no parent
-        self.PlugParent = None
-        # Keep track of the plugin type name
-        self.PlugType = "Beremiz"
-        self.PluggedChilds = {}
-        # After __init__ root plugin is not valid
-        self.ProjectPath = None
-        self._setBuildPath(None)
-        self.DebugThread = None
-        self.debug_break = False
-        self.previous_plcstate = None
-        # copy PluginMethods so that it can be later customized
-        self.PluginMethods = [dic.copy() for dic in self.PluginMethods]
-        self.LoadSTLibrary()
-
-    def __del__(self):
-        if self.DebugTimer:
-            self.DebugTimer.cancel()
-        self.KillDebugThread()
-
-    def SetAppFrame(self, frame, logger):
-        self.AppFrame = frame
-        self.logger = logger
-        self.StatusTimer = None
-        
-        if frame is not None:
-            # Timer to pull PLC status
-            ID_STATUSTIMER = wx.NewId()
-            self.StatusTimer = wx.Timer(self.AppFrame, ID_STATUSTIMER)
-            self.AppFrame.Bind(wx.EVT_TIMER, self.PullPLCStatusProc, self.StatusTimer)
-        
-            self.RefreshPluginsBlockLists()
-
-    def ResetAppFrame(self, logger):
-        if self.AppFrame is not None:
-            self.AppFrame.Unbind(wx.EVT_TIMER, self.StatusTimer)
-            self.StatusTimer = None
-            self.AppFrame = None
-        
-        self.logger = logger
-
-    def PluginLibraryFilePath(self):
-        return os.path.join(os.path.split(__file__)[0], "pous.xml")
-
-    def PlugTestModified(self):
-         return self.ChangesToSave or not self.ProjectIsSaved()
-
-    def PlugFullName(self):
-        return ""
-
-    def GetPlugRoot(self):
-        return self
-
-    def GetIECLibPath(self):
-        return self.ieclib_path
-    
-    def GetIEC2cPath(self):
-        return self.iec2c_path
-    
-    def GetCurrentLocation(self):
-        return ()
-
-    def GetCurrentName(self):
-        return ""
-    
-    def _GetCurrentName(self):
-        return ""
-
-    def GetProjectPath(self):
-        return self.ProjectPath
-
-    def GetProjectName(self):
-        return os.path.split(self.ProjectPath)[1]
-    
-    def GetDefaultTargetName(self):
-        if wx.Platform == '__WXMSW__':
-            return "Win32"
-        else:
-            return "Linux"
-
-    def GetTarget(self):
-        target = self.BeremizRoot.getTargetType()
-        if target.getcontent() is None:
-            target = self.Classes["BeremizRoot_TargetType"]()
-            target_name = self.GetDefaultTargetName()
-            target.setcontent({"name": target_name, "value": self.Classes["TargetType_%s"%target_name]()})
-        return target
-    
-    def GetParamsAttributes(self, path = None):
-        params = PlugTemplate.GetParamsAttributes(self, path)
-        if params[0]["name"] == "BeremizRoot":
-            for child in params[0]["children"]:
-                if child["name"] == "TargetType" and child["value"] == '':
-                    child.update(self.GetTarget().getElementInfos("TargetType")) 
-        return params
-        
-    def SetParamsAttribute(self, path, value):
-        if path.startswith("BeremizRoot.TargetType.") and self.BeremizRoot.getTargetType().getcontent() is None:
-            self.BeremizRoot.setTargetType(self.GetTarget())
-        return PlugTemplate.SetParamsAttribute(self, path, value)
-        
-    # helper func to check project path write permission
-    def CheckProjectPathPerm(self, dosave=True):
-        if CheckPathPerm(self.ProjectPath):
-            return True
-        dialog = wx.MessageDialog(self.AppFrame, 
-                    _('You must have permission to work on the project\nWork on a project copy ?'),
-                    _('Error'), 
-                    wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
-        answer = dialog.ShowModal()
-        dialog.Destroy()
-        if answer == wx.ID_YES:
-            if self.SaveProjectAs():
-                self.AppFrame.RefreshAll()
-                self.AppFrame.RefreshTitle()
-                self.AppFrame.RefreshFileMenu()
-                return True
-        return False
-    
-    def NewProject(self, ProjectPath, BuildPath=None):
-        """
-        Create a new project in an empty folder
-        @param ProjectPath: path of the folder where project have to be created
-        @param PLCParams: properties of the PLCOpen program created
-        """
-        # Verify that chosen folder is empty
-        if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0:
-            return _("Chosen folder isn't empty. You can't use it for a new project!")
-        
-        dialog = ProjectDialog(self.AppFrame)
-        if dialog.ShowModal() == wx.ID_OK:
-            values = dialog.GetValues()
-            values["creationDateTime"] = datetime(*localtime()[:6])
-            dialog.Destroy()
-        else:
-            dialog.Destroy()
-            return _("Project not created")
-        
-        # Create PLCOpen program
-        self.CreateNewProject(values)
-        # Change XSD into class members
-        self._AddParamsMembers()
-        self.PluggedChilds = {}
-        # Keep track of the root plugin (i.e. project path)
-        self.ProjectPath = ProjectPath
-        self._setBuildPath(BuildPath)
-        # get plugins bloclist (is that usefull at project creation?)
-        self.RefreshPluginsBlockLists()
-        # this will create files base XML files
-        self.SaveProject()
-        return None
-        
-    def LoadProject(self, ProjectPath, BuildPath=None):
-        """
-        Load a project contained in a folder
-        @param ProjectPath: path of the project folder
-        """
-        if os.path.basename(ProjectPath) == "":
-            ProjectPath = os.path.dirname(ProjectPath)
-		# Verify that project contains a PLCOpen program
-        plc_file = os.path.join(ProjectPath, "plc.xml")
-        if not os.path.isfile(plc_file):
-            return _("Chosen folder doesn't contain a program. It's not a valid project!")
-        # Load PLCOpen file
-        result = self.OpenXMLFile(plc_file)
-        if result:
-            return result
-        # Change XSD into class members
-        self._AddParamsMembers()
-        self.PluggedChilds = {}
-        # Keep track of the root plugin (i.e. project path)
-        self.ProjectPath = ProjectPath
-        self._setBuildPath(BuildPath)
-        # If dir have already be made, and file exist
-        if os.path.isdir(self.PlugPath()) and os.path.isfile(self.PluginXmlFilePath()):
-            #Load the plugin.xml file into parameters members
-            result = self.LoadXMLParams()
-            if result:
-                return result
-            #Load and init all the childs
-            self.LoadChilds()
-        self.RefreshPluginsBlockLists()
-        
-        if os.path.exists(self._getBuildPath()):
-            self.EnableMethod("_Clean", True)
-
-        if os.path.isfile(self._getIECrawcodepath()):
-            self.ShowMethod("_showIECcode", True)
-
-        return None
-    
-    def CloseProject(self):
-        self.ClearPluggedChilds()
-        self.ResetAppFrame(None)
-        
-    def SaveProject(self):
-        if self.CheckProjectPathPerm(False):
-            self.SaveXMLFile(os.path.join(self.ProjectPath, 'plc.xml'))
-            result = self.PlugRequestSave()
-            if result:
-                self.logger.write_error(result)
-    
-    def SaveProjectAs(self, dosave=True):
-        # Ask user to choose a path with write permissions
-        if wx.Platform == '__WXMSW__':
-            path = os.getenv("USERPROFILE")
-        else:
-            path = os.getenv("HOME")
-        dirdialog = wx.DirDialog(self.AppFrame , _("Choose a directory to save project"), path, wx.DD_NEW_DIR_BUTTON)
-        answer = dirdialog.ShowModal()
-        dirdialog.Destroy()
-        if answer == wx.ID_OK:
-            newprojectpath = dirdialog.GetPath()
-            if os.path.isdir(newprojectpath):
-                self.ProjectPath = newprojectpath
-                if dosave:
-                    self.SaveProject()
-                self._setBuildPath(self.BuildPath)
-                return True
-        return False
-    
-    # Update PLCOpenEditor Plugin Block types from loaded plugins
-    def RefreshPluginsBlockLists(self):
-        if getattr(self, "PluggedChilds", None) is not None:
-            self.ClearPluginTypes()
-            self.AddPluginTypesList(self.PluginsTypesFactory())
-        if self.AppFrame is not None:
-            self.AppFrame.RefreshLibraryPanel()
-            self.AppFrame.RefreshEditor()
-    
-    # Update a PLCOpenEditor Pou variable location
-    def UpdateProjectVariableLocation(self, old_leading, new_leading):
-        self.Project.updateElementAddress(old_leading, new_leading)
-        self.BufferProject()
-        if self.AppFrame is not None:
-            self.AppFrame.RefreshTitle()
-            self.AppFrame.RefreshInstancesTree()
-            self.AppFrame.RefreshFileMenu()
-            self.AppFrame.RefreshEditMenu()
-            self.AppFrame.RefreshEditor()
-    
-    def GetVariableLocationTree(self):
-        '''
-        This function is meant to be overridden by plugins.
-
-        It should returns an list of dictionaries
-        
-        - IEC_type is an IEC type like BOOL/BYTE/SINT/...
-        - location is a string of this variable's location, like "%IX0.0.0"
-        '''
-        children = []
-        for child in self.IECSortedChilds():
-            children.append(child.GetVariableLocationTree())
-        return children
-    
-    def PluginPath(self):
-        return os.path.join(os.path.split(__file__)[0], "plugins")
-    
-    def PlugPath(self, PlugName=None):
-        return self.ProjectPath
-    
-    def PluginXmlFilePath(self, PlugName=None):
-        return os.path.join(self.PlugPath(PlugName), "beremiz.xml")
-
-    def ParentsTypesFactory(self):
-        return self.PluginTypesFactory()
-
-    def _setBuildPath(self, buildpath):
-        if CheckPathPerm(buildpath):
-            self.BuildPath = buildpath
-        else:
-            self.BuildPath = None
-        self.BuildPath = buildpath
-        self.DefaultBuildPath = None
-        if self._builder is not None:
-            self._builder.SetBuildPath(self._getBuildPath())
-
-    def _getBuildPath(self):
-        # BuildPath is defined by user
-        if self.BuildPath is not None:
-            return self.BuildPath
-        # BuildPath isn't defined by user but already created by default
-        if self.DefaultBuildPath is not None:
-            return self.DefaultBuildPath
-        # Create a build path in project folder if user has permissions
-        if CheckPathPerm(self.ProjectPath):
-            self.DefaultBuildPath = os.path.join(self.ProjectPath, "build")
-        # Create a build path in temp folder
-        else:
-            self.DefaultBuildPath = os.path.join(tempfile.mkdtemp(), os.path.basename(self.ProjectPath), "build")
-            
-        if not os.path.exists(self.DefaultBuildPath):
-            os.makedirs(self.DefaultBuildPath)
-        return self.DefaultBuildPath
-    
-    def _getExtraFilesPath(self):
-        return os.path.join(self._getBuildPath(), "extra_files")
-
-    def _getIECcodepath(self):
-        # define name for IEC code file
-        return os.path.join(self._getBuildPath(), "plc.st")
-    
-    def _getIECgeneratedcodepath(self):
-        # define name for IEC generated code file
-        return os.path.join(self._getBuildPath(), "generated_plc.st")
-    
-    def _getIECrawcodepath(self):
-        # define name for IEC raw code file
-        return os.path.join(self.PlugPath(), "raw_plc.st")
-    
-    def GetLocations(self):
-        locations = []
-        filepath = os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h")
-        if os.path.isfile(filepath):
-            # IEC2C compiler generate a list of located variables : LOCATED_VARIABLES.h
-            location_file = open(os.path.join(self._getBuildPath(),"LOCATED_VARIABLES.h"))
-            # each line of LOCATED_VARIABLES.h declares a located variable
-            lines = [line.strip() for line in location_file.readlines()]
-            # This regular expression parses the lines genereated by IEC2C
-            LOCATED_MODEL = re.compile("__LOCATED_VAR\((?P<IEC_TYPE>[A-Z]*),(?P<NAME>[_A-Za-z0-9]*),(?P<DIR>[QMI])(?:,(?P<SIZE>[XBWDL]))?,(?P<LOC>[,0-9]*)\)")
-            for line in lines:
-                # If line match RE, 
-                result = LOCATED_MODEL.match(line)
-                if result:
-                    # Get the resulting dict
-                    resdict = result.groupdict()
-                    # rewrite string for variadic location as a tuple of integers
-                    resdict['LOC'] = tuple(map(int,resdict['LOC'].split(',')))
-                    # set located size to 'X' if not given 
-                    if not resdict['SIZE']:
-                        resdict['SIZE'] = 'X'
-                    # finally store into located variable list
-                    locations.append(resdict)
-        return locations
-        
-    def _Generate_SoftPLC(self):
-        """
-        Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2C
-        @param buildpath: path where files should be created
-        """
-
-        # Update PLCOpenEditor Plugin Block types before generate ST code
-        self.RefreshPluginsBlockLists()
-        
-        self.logger.write(_("Generating SoftPLC IEC-61131 ST/IL/SFC code...\n"))
-        buildpath = self._getBuildPath()
-        # ask PLCOpenEditor controller to write ST/IL/SFC code file
-        program, errors, warnings = self.GenerateProgram(self._getIECgeneratedcodepath())
-        if len(warnings) > 0:
-            self.logger.write_warning(_("Warnings in ST/IL/SFC code generator :\n"))
-            for warning in warnings:
-                self.logger.write_warning("%s\n"%warning)
-        if len(errors) > 0:
-            # Failed !
-            self.logger.write_error(_("Error in ST/IL/SFC code generator :\n%s\n")%errors[0])
-            return False
-        plc_file = open(self._getIECcodepath(), "w")
-        # Add ST Library from plugins
-        plc_file.write(self.PluginsSTLibraryFactory())
-        if os.path.isfile(self._getIECrawcodepath()):
-            plc_file.write(open(self._getIECrawcodepath(), "r").read())
-            plc_file.write("\n")
-        plc_file.close()
-        plc_file = open(self._getIECcodepath(), "r")
-        self.ProgramOffset = 0
-        for line in plc_file.xreadlines():
-            self.ProgramOffset += 1
-        plc_file.close()
-        plc_file = open(self._getIECcodepath(), "a")
-        plc_file.write(open(self._getIECgeneratedcodepath(), "r").read())
-        plc_file.close()
-
-        self.logger.write(_("Compiling IEC Program into C code...\n"))
-
-        # Now compile IEC code into many C files
-        # files are listed to stdout, and errors to stderr. 
-        status, result, err_result = ProcessLogger(
-               self.logger,
-               "\"%s\" -f -I \"%s\" -T \"%s\" \"%s\""%(
-                         self.iec2c_path,
-                         self.ieclib_path, 
-                         buildpath,
-                         self._getIECcodepath()),
-               no_stdout=True, no_stderr=True).spin()
-        if status:
-            # Failed !
-            
-            # parse iec2c's error message. if it contains a line number,
-            # then print those lines from the generated IEC file.
-            for err_line in err_result.split('\n'):
-                self.logger.write_warning(err_line + "\n")
-
-                m_result = MATIEC_ERROR_MODEL.match(err_line)
-                if m_result is not None:
-                    first_line, first_column, last_line, last_column, error = m_result.groups()
-                    first_line, last_line = int(first_line), int(last_line)
-                    
-                    last_section = None
-                    f = open(self._getIECcodepath())
-
-                    for i, line in enumerate(f.readlines()):
-                        i = i + 1
-                        if line[0] not in '\t \r\n':
-                            last_section = line
-
-                        if first_line <= i <= last_line:
-                            if last_section is not None:
-                                self.logger.write_warning("In section: " + last_section)
-                                last_section = None # only write section once
-                            self.logger.write_warning("%04d: %s" % (i, line))
-
-                    f.close()
-            
-            self.logger.write_error(_("Error : IEC to C compiler returned %d\n")%status)
-            return False
-        
-        # Now extract C files of stdout
-        C_files = [ fname for fname in result.splitlines() if fname[-2:]==".c" or fname[-2:]==".C" ]
-        # remove those that are not to be compiled because included by others
-        C_files.remove("POUS.c")
-        if not C_files:
-            self.logger.write_error(_("Error : At least one configuration and one resource must be declared in PLC !\n"))
-            return False
-        # transform those base names to full names with path
-        C_files = map(lambda filename:os.path.join(buildpath, filename), C_files)
-        self.logger.write(_("Extracting Located Variables...\n"))
-        # Keep track of generated located variables for later use by self._Generate_C
-        self.PLCGeneratedLocatedVars = self.GetLocations()
-        # Keep track of generated C files for later use by self.PlugGenerate_C
-        self.PLCGeneratedCFiles = C_files
-        # compute CFLAGS for plc
-        self.plcCFLAGS = "\"-I"+self.ieclib_path+"\""
-        return True
-
-    def GetBuilder(self):
-        """
-        Return a Builder (compile C code into machine code)
-        """
-        # Get target, module and class name
-        targetname = self.GetTarget().getcontent()["name"]
-        modulename = "targets." + targetname
-        classname = targetname + "_target"
-
-        # Get module reference
-        try :
-            targetmodule = getattr(__import__(modulename), targetname)
-
-        except Exception, msg:
-            self.logger.write_error(_("Can't find module for target %s!\n")%targetname)
-            self.logger.write_error(str(msg))
-            return None
-        
-        # Get target class
-        targetclass = getattr(targetmodule, classname)
-
-        # if target already 
-        if self._builder is None or not isinstance(self._builder,targetclass):
-            # Get classname instance
-            self._builder = targetclass(self)
-        return self._builder
-
-    def ResetBuildMD5(self):
-        builder=self.GetBuilder()
-        if builder is not None:
-            builder.ResetBinaryCodeMD5()
-        self.EnableMethod("_Transfer", False)
-
-    def GetLastBuildMD5(self):
-        builder=self.GetBuilder()
-        if builder is not None:
-            return builder.GetBinaryCodeMD5()
-        else:
-            return None
-
-    #######################################################################
-    #
-    #                C CODE GENERATION METHODS
-    #
-    #######################################################################
-    
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Return C code generated by iec2c compiler 
-        when _generate_softPLC have been called
-        @param locations: ignored
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-
-        return ([(C_file_name, self.plcCFLAGS) 
-                for C_file_name in self.PLCGeneratedCFiles ], 
-               "", # no ldflags
-               False) # do not expose retreive/publish calls
-    
-    def ResetIECProgramsAndVariables(self):
-        """
-        Reset variable and program list that are parsed from
-        CSV file generated by IEC2C compiler.
-        """
-        self._ProgramList = None
-        self._VariablesList = None
-        self._IECPathToIdx = {}
-        self._Ticktime = 0
-        self.TracedIECPath = []
-
-    def GetIECProgramsAndVariables(self):
-        """
-        Parse CSV-like file  VARIABLES.csv resulting from IEC2C compiler.
-        Each section is marked with a line staring with '//'
-        list of all variables used in various POUs
-        """
-        if self._ProgramList is None or self._VariablesList is None:
-            try:
-                csvfile = os.path.join(self._getBuildPath(),"VARIABLES.csv")
-                # describes CSV columns
-                ProgramsListAttributeName = ["num", "C_path", "type"]
-                VariablesListAttributeName = ["num", "vartype", "IEC_path", "C_path", "type"]
-                self._ProgramList = []
-                self._VariablesList = []
-                self._IECPathToIdx = {}
-                
-                # Separate sections
-                ListGroup = []
-                for line in open(csvfile,'r').xreadlines():
-                    strippedline = line.strip()
-                    if strippedline.startswith("//"):
-                        # Start new section
-                        ListGroup.append([])
-                    elif len(strippedline) > 0 and len(ListGroup) > 0:
-                        # append to this section
-                        ListGroup[-1].append(strippedline)
-        
-                # first section contains programs
-                for line in ListGroup[0]:
-                    # Split and Maps each field to dictionnary entries
-                    attrs = dict(zip(ProgramsListAttributeName,line.strip().split(';')))
-                    # Truncate "C_path" to remove conf an ressources names
-                    attrs["C_path"] = '__'.join(attrs["C_path"].split(".",2)[1:])
-                    # Push this dictionnary into result.
-                    self._ProgramList.append(attrs)
-        
-                # second section contains all variables
-                for line in ListGroup[1]:
-                    # Split and Maps each field to dictionnary entries
-                    attrs = dict(zip(VariablesListAttributeName,line.strip().split(';')))
-                    # Truncate "C_path" to remove conf an ressources names
-                    parts = attrs["C_path"].split(".",2)
-                    if len(parts) > 2:
-                        attrs["C_path"] = '__'.join(parts[1:])
-                    else:
-                        attrs["C_path"] = '__'.join(parts)
-                    # Push this dictionnary into result.
-                    self._VariablesList.append(attrs)
-                    # Fill in IEC<->C translation dicts
-                    IEC_path=attrs["IEC_path"]
-                    Idx=int(attrs["num"])
-                    self._IECPathToIdx[IEC_path]=(Idx, attrs["type"])
-                
-                # third section contains ticktime
-                if len(ListGroup) > 2:
-                    self._Ticktime = int(ListGroup[2][0]) 
-                
-            except Exception,e:
-                self.logger.write_error(_("Cannot open/parse VARIABLES.csv!\n"))
-                self.logger.write_error(traceback.format_exc())
-                self.ResetIECProgramsAndVariables()
-                return False
-
-        return True
-
-    def Generate_plc_debugger(self):
-        """
-        Generate trace/debug code out of PLC variable list
-        """
-        self.GetIECProgramsAndVariables()
-
-        # prepare debug code
-        debug_code = targets.code("plc_debug") % {
-           "buffer_size": reduce(lambda x, y: x + y, [DebugTypesSize.get(v["type"], 0) for v in self._VariablesList], 0),
-           "programs_declarations":
-               "\n".join(["extern %(type)s %(C_path)s;"%p for p in self._ProgramList]),
-           "extern_variables_declarations":"\n".join([
-              {"EXT":"extern __IEC_%(type)s_p %(C_path)s;",
-               "IN":"extern __IEC_%(type)s_p %(C_path)s;",
-               "MEM":"extern __IEC_%(type)s_p %(C_path)s;",
-               "OUT":"extern __IEC_%(type)s_p %(C_path)s;",
-               "VAR":"extern __IEC_%(type)s_t %(C_path)s;"}[v["vartype"]]%v 
-               for v in self._VariablesList if v["vartype"] != "FB" and v["C_path"].find('.')<0]),
-           "for_each_variable_do_code":"\n".join([
-               {"EXT":"    (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
-                "IN":"    (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
-                "MEM":"    (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
-                "OUT":"    (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
-                "VAR":"    (*fp)((void*)&%(C_path)s,%(type)s_ENUM);\n"}[v["vartype"]]%v
-                for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ]),
-           "find_variable_case_code":"\n".join([
-               "    case %(num)s:\n"%v+
-               "        *varp = (void*)&%(C_path)s;\n"%v+
-               {"EXT":"        return %(type)s_P_ENUM;\n",
-                "IN":"        return %(type)s_P_ENUM;\n",
-                "MEM":"        return %(type)s_O_ENUM;\n",
-                "OUT":"        return %(type)s_O_ENUM;\n",
-                "VAR":"        return %(type)s_ENUM;\n"}[v["vartype"]]%v
-                for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ])}
-        
-        return debug_code
-        
-    def Generate_plc_common_main(self):
-        """
-        Use plugins layout given in LocationCFilesAndCFLAGS to
-        generate glue code that dispatch calls to all plugins
-        """
-        # filter location that are related to code that will be called
-        # in retreive, publish, init, cleanup
-        locstrs = map(lambda x:"_".join(map(str,x)),
-           [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls])
-
-        # Generate main, based on template
-        if self.BeremizRoot.getEnable_Plugins():
-            plc_main_code = targets.code("plc_common_main") % {
-                "calls_prototypes":"\n".join([(
-                      "int __init_%(s)s(int argc,char **argv);\n"+
-                      "void __cleanup_%(s)s(void);\n"+
-                      "void __retrieve_%(s)s(void);\n"+
-                      "void __publish_%(s)s(void);")%{'s':locstr} for locstr in locstrs]),
-                "retrieve_calls":"\n    ".join([
-                      "__retrieve_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)]),
-                "publish_calls":"\n    ".join([ #Call publish in reverse order
-                      "__publish_%s();"%locstr for locstr in locstrs]),
-                "init_calls":"\n    ".join([
-                      "init_level=%d; "%(i+1)+
-                      "if((res = __init_%s(argc,argv))){"%locstr +
-                      #"printf(\"%s\"); "%locstr + #for debug
-                      "return res;}" for i,locstr in enumerate(locstrs)]),
-                "cleanup_calls":"\n    ".join([
-                      "if(init_level >= %d) "%i+
-                      "__cleanup_%s();"%locstrs[i-1] for i in xrange(len(locstrs), 0, -1)])
-                }
-        else:
-            plc_main_code = targets.code("plc_common_main") % {
-                "calls_prototypes":"\n",
-                "retrieve_calls":"\n",
-                "publish_calls":"\n",
-                "init_calls":"\n",
-                "cleanup_calls":"\n"
-                }
-        plc_main_code += targets.targetcode(self.GetTarget().getcontent()["name"])
-        return plc_main_code
-
-        
-    def _Build(self):
-        """
-        Method called by user to (re)build SoftPLC and plugin tree
-        """
-        if self.AppFrame is not None:
-            self.AppFrame.ClearErrors()
-        
-        buildpath = self._getBuildPath()
-
-        # Eventually create build dir
-        if not os.path.exists(buildpath):
-            os.mkdir(buildpath)
-        # There is something to clean
-        self.EnableMethod("_Clean", True)
-
-        self.logger.flush()
-        self.logger.write(_("Start build in %s\n") % buildpath)
-
-        # Generate SoftPLC IEC code
-        IECGenRes = self._Generate_SoftPLC()
-        self.ShowMethod("_showIECcode", True)
-
-        # If IEC code gen fail, bail out.
-        if not IECGenRes:
-            self.logger.write_error(_("IEC-61131-3 code generation failed !\n"))
-            self.ResetBuildMD5()
-            return False
-
-        # Reset variable and program list that are parsed from
-        # CSV file generated by IEC2C compiler.
-        self.ResetIECProgramsAndVariables()
-        
-        # Generate C code and compilation params from plugin hierarchy
-        self.logger.write(_("Generating plugins C code\n"))
-        try:
-            self.LocationCFilesAndCFLAGS, self.LDFLAGS, ExtraFiles = self._Generate_C(
-                buildpath, 
-                self.PLCGeneratedLocatedVars)
-        except Exception, exc:
-            self.logger.write_error(_("Plugins code generation failed !\n"))
-            self.logger.write_error(traceback.format_exc())
-            self.ResetBuildMD5()
-            return False
-
-        # Get temporary directory path
-        extrafilespath = self._getExtraFilesPath()
-        # Remove old directory
-        if os.path.exists(extrafilespath):
-            shutil.rmtree(extrafilespath)
-        # Recreate directory
-        os.mkdir(extrafilespath)
-        # Then write the files
-        for fname,fobject in ExtraFiles:
-            fpath = os.path.join(extrafilespath,fname)
-            open(fpath, "wb").write(fobject.read())
-        # Now we can forget ExtraFiles (will close files object)
-        del ExtraFiles
-        
-        # Template based part of C code generation
-        # files are stacked at the beginning, as files of plugin tree root
-        for generator, filename, name in [
-           # debugger code
-           (self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
-           # init/cleanup/retrieve/publish, run and align code
-           (self.Generate_plc_common_main,"plc_common_main.c","Common runtime")]:
-            try:
-                # Do generate
-                code = generator()
-                if code is None:
-                     raise
-                code_path = os.path.join(buildpath,filename)
-                open(code_path, "w").write(code)
-                # Insert this file as first file to be compiled at root plugin
-                self.LocationCFilesAndCFLAGS[0][1].insert(0,(code_path, self.plcCFLAGS))
-            except Exception, exc:
-                self.logger.write_error(name+_(" generation failed !\n"))
-                self.logger.write_error(traceback.format_exc())
-                self.ResetBuildMD5()
-                return False
-
-        self.logger.write(_("C code generated successfully.\n"))
-
-        # Get current or fresh builder
-        builder = self.GetBuilder()
-        if builder is None:
-            self.logger.write_error(_("Fatal : cannot get builder.\n"))
-            self.ResetBuildMD5()
-            return False
-
-        # Build
-        try:
-            if not builder.build() :
-                self.logger.write_error(_("C Build failed.\n"))
-                return False
-        except Exception, exc:
-            self.logger.write_error(_("C Build crashed !\n"))
-            self.logger.write_error(traceback.format_exc())
-            self.ResetBuildMD5()
-            return False
-
-        self.logger.write(_("Successfully built.\n"))
-        # Update GUI status about need for transfer
-        self.CompareLocalAndRemotePLC()
-        return True
-    
-    def ShowError(self, logger, from_location, to_location):
-        chunk_infos = self.GetChunkInfos(from_location, to_location)
-        for infos, (start_row, start_col) in chunk_infos:
-            start = (from_location[0] - start_row, from_location[1] - start_col)
-            end = (to_location[0] - start_row, to_location[1] - start_col)
-            #print from_location, to_location, start_row, start_col, start, end
-            if self.AppFrame is not None:
-                self.AppFrame.ShowError(infos, start, end)
-
-    def _showIECcode(self):
-        self._OpenView("IEC code")
-
-    def _editIECrawcode(self):
-        self._OpenView("IEC raw code")
-
-    def _OpenView(self, name=None):
-        if name == "IEC code":
-            plc_file = self._getIECcodepath()
-        
-            IEC_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, None, instancepath=name)
-            #IEC_code_viewer.Enable(False)
-            IEC_code_viewer.SetTextSyntax("ALL")
-            IEC_code_viewer.SetKeywords(IEC_KEYWORDS)
-            try:
-                text = file(plc_file).read()
-            except:
-                text = '(* No IEC code have been generated at that time ! *)'
-            IEC_code_viewer.SetText(text = text)
-            IEC_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
-                
-            self.AppFrame.EditProjectElement(IEC_code_viewer, name)
-            
-            return IEC_code_viewer
-        
-        elif name == "IEC raw code":
-            controler = MiniTextControler(self._getIECrawcodepath())
-            IEC_raw_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, controler, instancepath=name)
-            #IEC_raw_code_viewer.Enable(False)
-            IEC_raw_code_viewer.SetTextSyntax("ALL")
-            IEC_raw_code_viewer.SetKeywords(IEC_KEYWORDS)
-            IEC_raw_code_viewer.RefreshView()
-            IEC_raw_code_viewer.SetIcon(self.AppFrame.GenerateBitmap("ST"))
-                
-            self.AppFrame.EditProjectElement(IEC_raw_code_viewer, name)
-
-            return IEC_raw_code_viewer
-        
-        return None
-
-    def _Clean(self):
-        if os.path.isdir(os.path.join(self._getBuildPath())):
-            self.logger.write(_("Cleaning the build directory\n"))
-            shutil.rmtree(os.path.join(self._getBuildPath()))
-        else:
-            self.logger.write_error(_("Build directory already clean\n"))
-        self.ShowMethod("_showIECcode", False)
-        self.EnableMethod("_Clean", False)
-        # kill the builder
-        self._builder = None
-        self.CompareLocalAndRemotePLC()
-
-    ############# Real PLC object access #############
-    def UpdateMethodsFromPLCStatus(self):
-        # Get PLC state : Running or Stopped
-        # TODO : use explicit status instead of boolean
-        status = None
-        if self._connector is not None:
-            status = self._connector.GetPLCstatus()
-        if status is None:
-            self._connector = None
-            status = "Disconnected"
-        if(self.previous_plcstate != status):
-            for args in {
-                     "Started" :     [("_Run", False),
-                                      ("_Stop", True)],
-                     "Stopped" :     [("_Run", True),
-                                      ("_Stop", False)],
-                     "Empty" :       [("_Run", False),
-                                      ("_Stop", False)],
-                     "Broken" :      [],
-                     "Disconnected" :[("_Run", False),
-                                      ("_Stop", False),
-                                      ("_Transfer", False),
-                                      ("_Connect", True),
-                                      ("_Disconnect", False)],
-                   }.get(status,[]):
-                self.ShowMethod(*args)
-            self.previous_plcstate = status
-            return True
-        return False
-    
-    def PullPLCStatusProc(self, event):
-        if self._connector is None:
-            self.StatusTimer.Stop()
-        if self.UpdateMethodsFromPLCStatus():
-            
-            status = _(self.previous_plcstate)
-            {"Broken": self.logger.write_error,
-             None: lambda x: None}.get(
-                self.previous_plcstate, self.logger.write)(_("PLC is %s\n")%status)
-            self.AppFrame.RefreshAll()
-        
-    def RegisterDebugVarToConnector(self):
-        self.DebugTimer=None
-        Idxs = []
-        self.TracedIECPath = []
-        if self._connector is not None:
-            self.IECdebug_lock.acquire()
-            IECPathsToPop = []
-            for IECPath,data_tuple in self.IECdebug_datas.iteritems():
-                WeakCallableDict, data_log, status, fvalue = data_tuple
-                if len(WeakCallableDict) == 0:
-                    # Callable Dict is empty.
-                    # This variable is not needed anymore!
-                    #print "Unused : " + IECPath
-                    IECPathsToPop.append(IECPath)
-                elif IECPath != "__tick__":
-                    # Convert 
-                    Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
-                    if Idx is not None:
-                        if IEC_Type in DebugTypesSize: 
-                            Idxs.append((Idx, IEC_Type, fvalue, IECPath))
-                        else:
-                            self.logger.write_warning(_("Debug : Unsuppoted type to debug %s\n")%IEC_Type)
-                    else:
-                        self.logger.write_warning(_("Debug : Unknown variable %s\n")%IECPath)
-            for IECPathToPop in IECPathsToPop:
-                self.IECdebug_datas.pop(IECPathToPop)
-
-            if Idxs:
-                Idxs.sort()
-                self.TracedIECPath = zip(*Idxs)[3]
-                self._connector.SetTraceVariablesList(zip(*zip(*Idxs)[0:3]))
-            else:
-                self.TracedIECPath = []
-                self._connector.SetTraceVariablesList([])
-            self.IECdebug_lock.release()
-            
-            #for IEC_path, IECdebug_data in self.IECdebug_datas.iteritems():
-            #    print IEC_path, IECdebug_data[0].keys()
-
-    def ReArmDebugRegisterTimer(self):
-        if self.DebugTimer is not None:
-            self.DebugTimer.cancel()
-
-        # Timer to prevent rapid-fire when registering many variables
-        # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
-        self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
-        # Rearm anti-rapid-fire timer
-        self.DebugTimer.start()
-
-    def GetDebugIECVariableType(self, IECPath):
-        Idx, IEC_Type = self._IECPathToIdx.get(IECPath,(None,None))
-        return IEC_Type
-        
-    def SubscribeDebugIECVariable(self, IECPath, callableobj, *args, **kwargs):
-        """
-        Dispatching use a dictionnary linking IEC variable paths
-        to a WeakKeyDictionary linking 
-        weakly referenced callables to optionnal args
-        """
-        if IECPath != "__tick__" and not self._IECPathToIdx.has_key(IECPath):
-            return None
-        
-        self.IECdebug_lock.acquire()
-        # If no entry exist, create a new one with a fresh WeakKeyDictionary
-        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
-        if IECdebug_data is None:
-            IECdebug_data  = [
-                    WeakKeyDictionary(), # Callables
-                    [],                  # Data storage [(tick, data),...]
-                    "Registered",        # Variable status
-                    None]                # Forced value
-            self.IECdebug_datas[IECPath] = IECdebug_data
-        
-        IECdebug_data[0][callableobj]=(args, kwargs)
-
-        self.IECdebug_lock.release()
-        
-        self.ReArmDebugRegisterTimer()
-        
-        return IECdebug_data[1]
-
-    def UnsubscribeDebugIECVariable(self, IECPath, callableobj):
-        #print "Unsubscribe", IECPath, callableobj
-        self.IECdebug_lock.acquire()
-        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
-        if IECdebug_data is not None:
-            IECdebug_data[0].pop(callableobj,None)
-        self.IECdebug_lock.release()
-
-        self.ReArmDebugRegisterTimer()
-
-    def UnsubscribeAllDebugIECVariable(self):
-        self.IECdebug_lock.acquire()
-        IECdebug_data = {}
-        self.IECdebug_lock.release()
-
-        self.ReArmDebugRegisterTimer()
-
-    def ForceDebugIECVariable(self, IECPath, fvalue):
-        if not self.IECdebug_datas.has_key(IECPath):
-            return
-        
-        self.IECdebug_lock.acquire()
-        
-        # If no entry exist, create a new one with a fresh WeakKeyDictionary
-        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
-        IECdebug_data[2] = "Forced"
-        IECdebug_data[3] = fvalue
-        
-        self.IECdebug_lock.release()
-        
-        self.ReArmDebugRegisterTimer()
-    
-    def ReleaseDebugIECVariable(self, IECPath):
-        if not self.IECdebug_datas.has_key(IECPath):
-            return
-        
-        self.IECdebug_lock.acquire()
-        
-        # If no entry exist, create a new one with a fresh WeakKeyDictionary
-        IECdebug_data = self.IECdebug_datas.get(IECPath, None)
-        IECdebug_data[2] = "Registered"
-        IECdebug_data[3] = None
-        
-        self.IECdebug_lock.release()
-        
-        self.ReArmDebugRegisterTimer()
-    
-    def CallWeakcallables(self, IECPath, function_name, *cargs):
-        data_tuple = self.IECdebug_datas.get(IECPath, None)
-        if data_tuple is not None:
-            WeakCallableDict, data_log, status, fvalue = data_tuple
-            #data_log.append((debug_tick, value))
-            for weakcallable,(args,kwargs) in WeakCallableDict.iteritems():
-                #print weakcallable, value, args, kwargs
-                function = getattr(weakcallable, function_name, None)
-                if function is not None:
-                    if status == "Forced" and cargs[1] == fvalue:
-                        function(*(cargs + (True,) + args), **kwargs)
-                    else:
-                        function(*(cargs + args), **kwargs)
-                # This will block thread if more than one call is waiting
-
-    def GetTicktime(self):
-        return self._Ticktime
-
-    def RemoteExec(self, script, **kwargs):
-        if self._connector is None:
-            return -1, "No runtime connected!"
-        return self._connector.RemoteExec(script, **kwargs)
-
-    def DebugThreadProc(self):
-        """
-        This thread waid PLC debug data, and dispatch them to subscribers
-        """
-        self.debug_break = False
-        debug_getvar_retry = 0
-        while (not self.debug_break) and (self._connector is not None):
-            Trace = self._connector.GetTraceVariables()
-            if(Trace):
-                plc_status, debug_tick, debug_vars = Trace
-            else:
-                plc_status = None
-            debug_getvar_retry += 1
-            #print debug_tick, debug_vars
-            if plc_status == "Started":
-                self.IECdebug_lock.acquire()
-                if len(debug_vars) == len(self.TracedIECPath):
-                    if debug_getvar_retry > DEBUG_RETRIES_WARN:
-                        self.logger.write(_("... debugger recovered\n"))
-                    debug_getvar_retry = 0
-                    for IECPath,value in zip(self.TracedIECPath, debug_vars):
-                        if value is not None:
-                            self.CallWeakcallables(IECPath, "NewValue", debug_tick, value)
-                    self.CallWeakcallables("__tick__", "NewDataAvailable")
-                self.IECdebug_lock.release()
-                if debug_getvar_retry == DEBUG_RETRIES_WARN:
-                    self.logger.write(_("Waiting debugger to recover...\n"))
-                if debug_getvar_retry == DEBUG_RETRIES_REREGISTER:
-                    # re-register debug registry to PLC
-                    wx.CallAfter(self.RegisterDebugVarToConnector)
-                if debug_getvar_retry != 0:
-                    # Be patient, tollerate PLC to come up before debugging
-                    time.sleep(0.1)
-            else:
-                self.debug_break = True
-        self.logger.write(_("Debugger disabled\n"))
-        self.DebugThread = None
-
-    def KillDebugThread(self):
-        tmp_debugthread = self.DebugThread
-        self.debug_break = True
-        if tmp_debugthread is not None:
-            self.logger.writeyield(_("Stopping debugger...\n"))
-            tmp_debugthread.join(timeout=5)
-            if tmp_debugthread.isAlive() and self.logger:
-                self.logger.write_warning(_("Couldn't stop debugger.\n"))
-            else:
-                self.logger.write(_("Debugger stopped.\n"))
-        self.DebugThread = None
-
-    def _connect_debug(self): 
-        if self.AppFrame:
-            self.AppFrame.ResetGraphicViewers()
-        self.RegisterDebugVarToConnector()
-        if self.DebugThread is None:
-            self.DebugThread = Thread(target=self.DebugThreadProc)
-            self.DebugThread.start()
-    
-    def _Run(self):
-        """
-        Start PLC
-        """
-        if self.GetIECProgramsAndVariables():
-            self._connector.StartPLC()
-            self.logger.write(_("Starting PLC\n"))
-            self._connect_debug()
-        else:
-            self.logger.write_error(_("Couldn't start PLC !\n"))
-        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-       
-    def _Stop(self):
-        """
-        Stop PLC
-        """
-        if self._connector is not None and not self._connector.StopPLC():
-            self.logger.write_error(_("Couldn't stop PLC !\n"))
-
-        # debugthread should die on his own
-        #self.KillDebugThread()
-        
-        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-
-    def _Connect(self):
-        # don't accept re-connetion is already connected
-        if self._connector is not None:
-            self.logger.write_error(_("Already connected. Please disconnect\n"))
-            return
-        
-        # Get connector uri
-        uri = self.\
-              BeremizRoot.\
-              getURI_location().\
-              strip()
-
-        # if uri is empty launch discovery dialog
-        if uri == "":
-            # Launch Service Discovery dialog
-            dialog = DiscoveryDialog(self.AppFrame)
-            answer = dialog.ShowModal()
-            uri = dialog.GetURI()
-            dialog.Destroy()
-            
-            # Nothing choosed or cancel button
-            if uri is None or answer == wx.ID_CANCEL:
-                self.logger.write_error(_("Connection canceled!\n"))
-                return
-            else:
-                self.\
-                BeremizRoot.\
-                setURI_location(uri)
-       
-        # Get connector from uri
-        try:
-            self._connector = connectors.ConnectorFactory(uri, self)
-        except Exception, msg:
-            self.logger.write_error(_("Exception while connecting %s!\n")%uri)
-            self.logger.write_error(traceback.format_exc())
-
-        # Did connection success ?
-        if self._connector is None:
-            # Oups.
-            self.logger.write_error(_("Connection failed to %s!\n")%uri)
-        else:
-            self.ShowMethod("_Connect", False)
-            self.ShowMethod("_Disconnect", True)
-            self.ShowMethod("_Transfer", True)
-
-            self.CompareLocalAndRemotePLC()
-            
-            # Init with actual PLC status and print it
-            self.UpdateMethodsFromPLCStatus()
-            if self.previous_plcstate is not None:
-                status = _(self.previous_plcstate)
-            else:
-                status = ""
-            self.logger.write(_("PLC is %s\n")%status)
-            
-            # Start the status Timer
-            self.StatusTimer.Start(milliseconds=500, oneShot=False)
-            
-            if self.previous_plcstate=="Started":
-                if self.DebugAvailable() and self.GetIECProgramsAndVariables():
-                    self.logger.write(_("Debug connect matching running PLC\n"))
-                    self._connect_debug()
-                else:
-                    self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n"))
-
-    def CompareLocalAndRemotePLC(self):
-        if self._connector is None:
-            return
-        # We are now connected. Update button status
-        MD5 = self.GetLastBuildMD5()
-        # Check remote target PLC correspondance to that md5
-        if MD5 is not None:
-            if not self._connector.MatchMD5(MD5):
-#                self.logger.write_warning(
-#                   _("Latest build does not match with target, please transfer.\n"))
-                self.EnableMethod("_Transfer", True)
-            else:
-#                self.logger.write(
-#                   _("Latest build matches target, no transfer needed.\n"))
-                self.EnableMethod("_Transfer", True)
-                # warns controller that program match
-                self.ProgramTransferred()
-                #self.EnableMethod("_Transfer", False)
-        else:
-#            self.logger.write_warning(
-#                _("Cannot compare latest build to target. Please build.\n"))
-            self.EnableMethod("_Transfer", False)
-
-
-    def _Disconnect(self):
-        self._connector = None
-        self.StatusTimer.Stop()
-        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-        
-    def _Transfer(self):
-        # Get the last build PLC's 
-        MD5 = self.GetLastBuildMD5()
-        
-        # Check if md5 file is empty : ask user to build PLC 
-        if MD5 is None :
-            self.logger.write_error(_("Failed : Must build before transfer.\n"))
-            return False
-
-        # Compare PLC project with PLC on target
-        if self._connector.MatchMD5(MD5):
-            self.logger.write(
-                _("Latest build already matches current target. Transfering anyway...\n"))
-
-        # Get temprary directory path
-        extrafilespath = self._getExtraFilesPath()
-        extrafiles = [(name, open(os.path.join(extrafilespath, name), 
-                                  'rb').read()) \
-                      for name in os.listdir(extrafilespath) \
-                      if not name=="CVS"]
-
-        # Send PLC on target
-        builder = self.GetBuilder()
-        if builder is not None:
-            data = builder.GetBinaryCode()
-            if data is not None :
-                if self._connector.NewPLC(MD5, data, extrafiles) and self.GetIECProgramsAndVariables():
-                    self.UnsubscribeAllDebugIECVariable()
-                    self.ProgramTransferred()
-                    if self.AppFrame is not None:
-                        self.AppFrame.RefreshInstancesTree()
-                        self.AppFrame.CloseObsoleteDebugTabs()
-                    self.logger.write(_("Transfer completed successfully.\n"))
-                else:
-                    self.logger.write_error(_("Transfer failed\n"))
-            else:
-                self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n"))
-
-        wx.CallAfter(self.UpdateMethodsFromPLCStatus)
-
-    PluginMethods = [
-        {"bitmap" : opjimg("Build"),
-         "name" : _("Build"),
-         "tooltip" : _("Build project into build folder"),
-         "method" : "_Build"},
-        {"bitmap" : opjimg("Clean"),
-         "name" : _("Clean"),
-         "enabled" : False,
-         "tooltip" : _("Clean project build folder"),
-         "method" : "_Clean"},
-        {"bitmap" : opjimg("Run"),
-         "name" : _("Run"),
-         "shown" : False,
-         "tooltip" : _("Start PLC"),
-         "method" : "_Run"},
-        {"bitmap" : opjimg("Stop"),
-         "name" : _("Stop"),
-         "shown" : False,
-         "tooltip" : _("Stop Running PLC"),
-         "method" : "_Stop"},
-        {"bitmap" : opjimg("Connect"),
-         "name" : _("Connect"),
-         "tooltip" : _("Connect to the target PLC"),
-         "method" : "_Connect"},
-        {"bitmap" : opjimg("Transfer"),
-         "name" : _("Transfer"),
-         "shown" : False,
-         "tooltip" : _("Transfer PLC"),
-         "method" : "_Transfer"},
-        {"bitmap" : opjimg("Disconnect"),
-         "name" : _("Disconnect"),
-         "shown" : False,
-         "tooltip" : _("Disconnect from PLC"),
-         "method" : "_Disconnect"},
-        {"bitmap" : opjimg("ShowIECcode"),
-         "name" : _("Show code"),
-         "shown" : False,
-         "tooltip" : _("Show IEC code generated by PLCGenerator"),
-         "method" : "_showIECcode"},
-        {"bitmap" : opjimg("editIECrawcode"),
-         "name" : _("Raw IEC code"),
-         "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"),
-         "method" : "_editIECrawcode"},
-    ]
--- a/plugins/.cvsignore	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
--- a/plugins/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-from os import listdir, path
-
-_base_path = path.split(__file__)[0]
-
-__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
-
-helps = []
-for name in __all__:
-    helpfilename = path.join(_base_path, name, "README")
-    if path.isfile(helpfilename):
-        helps.append(open(helpfilename).readline().strip())
-    else:
-        helps.append(name)
--- a/plugins/c_ext/.cvsignore	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
--- a/plugins/c_ext/CFileEditor.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,967 +0,0 @@
-import keyword
-
-import wx
-import wx.grid
-import wx.stc as stc
-import wx.lib.buttons
-
-from controls import CustomGrid, CustomTable, EditorPanel
-
-if wx.Platform == '__WXMSW__':
-    faces = { 'times': 'Times New Roman',
-              'mono' : 'Courier New',
-              'helv' : 'Arial',
-              'other': 'Comic Sans MS',
-              'size' : 10,
-              'size2': 8,
-             }
-else:
-    faces = { 'times': 'Times',
-              'mono' : 'Courier',
-              'helv' : 'Helvetica',
-              'other': 'new century schoolbook',
-              'size' : 12,
-              'size2': 10,
-             }
-
-
-def AppendMenu(parent, help, id, kind, text):
-    if wx.VERSION >= (2, 6, 0):
-        parent.Append(help=help, id=id, kind=kind, text=text)
-    else:
-        parent.Append(helpString=help, id=id, kind=kind, item=text)
-
-
-[ID_CPPEDITOR,
-] = [wx.NewId() for _init_ctrls in range(1)]
-
-CPP_KEYWORDS = ["asm", "auto", "bool", "break", "case", "catch", "char", "class", 
-    "const", "const_cast", "continue", "default", "delete", "do", "double", 
-    "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", 
-    "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", 
-    "namespace", "new", "operator", "private", "protected", "public", "register", 
-    "reinterpret_cast", "return", "short", "signed", "sizeof", "static", 
-    "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
-    "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", 
-    "void", "volatile", "wchar_t", "while"]
-
-def GetCursorPos(old, new):
-    old_length = len(old)
-    new_length = len(new)
-    common_length = min(old_length, new_length)
-    i = 0
-    for i in xrange(common_length):
-        if old[i] != new[i]:
-            break
-    if old_length < new_length:
-        if common_length > 0 and old[i] != new[i]:
-            return i + new_length - old_length
-        else:
-            return i + new_length - old_length + 1
-    elif old_length > new_length or i < min(old_length, new_length) - 1:
-        if common_length > 0 and old[i] != new[i]:
-            return i
-        else:
-            return i + 1
-    else:
-        return None
-
-class CppEditor(stc.StyledTextCtrl):
-
-    fold_symbols = 3
-    
-    def __init__(self, parent, name, window, controler):
-        stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, 
-                 wx.Size(0, 0), 0)
-
-        self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
-        self.SetMarginWidth(1, 25)
-
-        self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
-        self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
-
-        self.SetLexer(stc.STC_LEX_CPP)
-        self.SetKeyWords(0, " ".join(CPP_KEYWORDS))
-
-        self.SetProperty("fold", "1")
-        self.SetProperty("tab.timmy.whinge.level", "1")
-        self.SetMargins(0,0)
-
-        self.SetViewWhiteSpace(False)
-        #self.SetBufferedDraw(False)
-        #self.SetViewEOL(True)
-        #self.SetEOLMode(stc.STC_EOL_CRLF)
-        #self.SetUseAntiAliasing(True)
-        
-        self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
-        self.SetEdgeColumn(78)
-
-        # Setup a margin to hold fold markers
-        #self.SetFoldFlags(16)  ###  WHAT IS THIS VALUE?  WHAT ARE THE OTHER FLAGS?  DOES IT MATTER?
-        self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
-        self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
-        self.SetMarginSensitive(2, True)
-        self.SetMarginWidth(2, 12)
-
-        if self.fold_symbols == 0:
-            # Arrow pointing right for contracted folders, arrow pointing down for expanded
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
-            
-        elif self.fold_symbols == 1:
-            # Plus for contracted folders, minus for expanded
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
-
-        elif self.fold_symbols == 2:
-            # Like a flattened tree control using circular headers and curved joins
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
-
-        elif self.fold_symbols == 3:
-            # Like a flattened tree control using square headers
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
-            self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
-
-
-        self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
-        self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
-        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
-
-        # Make some styles,  The lexer defines what each style is used for, we
-        # just have to define what each style looks like.  This set is adapted from
-        # Scintilla sample property files.
-
-        # Global default styles for all languages
-        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
-        self.StyleClearAll()  # Reset all to be like the default
-
-        # Global default styles for all languages
-        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(mono)s,size:%(size)d" % faces)
-        self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
-        self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
-        self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
-        self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
-
-        self.StyleSetSpec(stc.STC_C_COMMENT, 'fore:#408060')
-        self.StyleSetSpec(stc.STC_C_COMMENTLINE, 'fore:#408060')
-        self.StyleSetSpec(stc.STC_C_COMMENTDOC, 'fore:#408060')
-        self.StyleSetSpec(stc.STC_C_NUMBER, 'fore:#0076AE')
-        self.StyleSetSpec(stc.STC_C_WORD, 'bold,fore:#800056')
-        self.StyleSetSpec(stc.STC_C_STRING, 'fore:#2a00ff')
-        self.StyleSetSpec(stc.STC_C_PREPROCESSOR, 'bold,fore:#800056')
-        self.StyleSetSpec(stc.STC_C_OPERATOR, 'bold')
-        self.StyleSetSpec(stc.STC_C_STRINGEOL, 'back:#FFD5FF')
-        
-        # register some images for use in the AutoComplete box.
-        #self.RegisterImage(1, images.getSmilesBitmap())
-        self.RegisterImage(1, 
-            wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
-        self.RegisterImage(2, 
-            wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
-        self.RegisterImage(3, 
-            wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
-
-        # Indentation size
-        self.SetTabWidth(2)
-        self.SetUseTabs(0)
-
-        self.Controler = controler
-        self.ParentWindow = window
-        
-        self.DisableEvents = True
-        self.Name = name
-        self.CurrentAction = None
-        
-        self.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
-
-        self.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_CPPEDITOR)
-        self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
-        self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_CPPEDITOR)
-    
-    def OnModification(self, event):
-        if not self.DisableEvents:
-            mod_type = event.GetModificationType()
-            if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
-                if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
-                    if self.CurrentAction == None:
-                        self.StartBuffering()
-                    elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
-                        self.Controler.EndBuffering()
-                        self.StartBuffering()
-                    self.CurrentAction = ("Add", event.GetPosition())
-                    wx.CallAfter(self.RefreshModel)
-                elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
-                    if self.CurrentAction == None:
-                        self.StartBuffering()
-                    elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
-                        self.Controler.EndBuffering()
-                        self.StartBuffering()
-                    self.CurrentAction = ("Delete", event.GetPosition())
-                    wx.CallAfter(self.RefreshModel)
-        event.Skip()
-    
-    def OnDoDrop(self, event):
-        self.ResetBuffer()
-        wx.CallAfter(self.RefreshModel)
-        event.Skip()
-
-    # Buffer the last model state
-    def RefreshBuffer(self):
-        self.Controler.BufferCFile()
-        if self.ParentWindow is not None:
-            self.ParentWindow.RefreshTitle()
-            self.ParentWindow.RefreshFileMenu()
-            self.ParentWindow.RefreshEditMenu()
-            self.ParentWindow.RefreshPageTitles()
-    
-    def StartBuffering(self):
-        self.Controler.StartBuffering()
-        if self.ParentWindow is not None:
-            self.ParentWindow.RefreshTitle()
-            self.ParentWindow.RefreshFileMenu()
-            self.ParentWindow.RefreshEditMenu()
-            self.ParentWindow.RefreshPageTitles()
-    
-    def ResetBuffer(self):
-        if self.CurrentAction != None:
-            self.Controler.EndBuffering()
-            self.CurrentAction = None
-
-    def RefreshView(self):
-        self.ResetBuffer()
-        self.DisableEvents = True
-        old_cursor_pos = self.GetCurrentPos()
-        old_text = self.GetText()
-        new_text = self.Controler.GetPartText(self.Name)
-        self.SetText(new_text)
-        new_cursor_pos = GetCursorPos(old_text, new_text)
-        if new_cursor_pos != None:
-            self.GotoPos(new_cursor_pos)
-        else:
-            self.GotoPos(old_cursor_pos)
-        self.ScrollToColumn(0)
-        self.EmptyUndoBuffer()
-        self.DisableEvents = False
-        
-        self.Colourise(0, -1)
-
-    def DoGetBestSize(self):
-        return self.ParentWindow.GetPanelBestSize()
-
-    def RefreshModel(self):
-        self.Controler.SetPartText(self.Name, self.GetText())
-
-    def OnKeyPressed(self, event):
-        if self.CallTipActive():
-            self.CallTipCancel()
-        key = event.GetKeyCode()
-
-        if key == 32 and event.ControlDown():
-            pos = self.GetCurrentPos()
-
-            # Tips
-            if event.ShiftDown():
-                pass
-##                self.CallTipSetBackground("yellow")
-##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
-##                                 'show some suff, maybe parameters..\n\n'
-##                                 'fubar(param1, param2)')
-            # Code completion
-            else:
-                self.AutoCompSetIgnoreCase(False)  # so this needs to match
-
-                # Images are specified with a appended "?type"
-                self.AutoCompShow(0, " ".join([word + "?1" for word in CPP_KEYWORDS]))
-        else:
-            event.Skip()
-
-    def OnKillFocus(self, event):
-        self.AutoCompCancel()
-        event.Skip()
-
-    def OnUpdateUI(self, evt):
-        # check for matching braces
-        braceAtCaret = -1
-        braceOpposite = -1
-        charBefore = None
-        caretPos = self.GetCurrentPos()
-
-        if caretPos > 0:
-            charBefore = self.GetCharAt(caretPos - 1)
-            styleBefore = self.GetStyleAt(caretPos - 1)
-
-        # check before
-        if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
-            braceAtCaret = caretPos - 1
-
-        # check after
-        if braceAtCaret < 0:
-            charAfter = self.GetCharAt(caretPos)
-            styleAfter = self.GetStyleAt(caretPos)
-
-            if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
-                braceAtCaret = caretPos
-
-        if braceAtCaret >= 0:
-            braceOpposite = self.BraceMatch(braceAtCaret)
-
-        if braceAtCaret != -1  and braceOpposite == -1:
-            self.BraceBadLight(braceAtCaret)
-        else:
-            self.BraceHighlight(braceAtCaret, braceOpposite)
-            #pt = self.PointFromPosition(braceOpposite)
-            #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
-            #print pt
-            #self.Refresh(False)
-
-
-    def OnMarginClick(self, evt):
-        # fold and unfold as needed
-        if evt.GetMargin() == 2:
-            if evt.GetShift() and evt.GetControl():
-                self.FoldAll()
-            else:
-                lineClicked = self.LineFromPosition(evt.GetPosition())
-
-                if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
-                    if evt.GetShift():
-                        self.SetFoldExpanded(lineClicked, True)
-                        self.Expand(lineClicked, True, True, 1)
-                    elif evt.GetControl():
-                        if self.GetFoldExpanded(lineClicked):
-                            self.SetFoldExpanded(lineClicked, False)
-                            self.Expand(lineClicked, False, True, 0)
-                        else:
-                            self.SetFoldExpanded(lineClicked, True)
-                            self.Expand(lineClicked, True, True, 100)
-                    else:
-                        self.ToggleFold(lineClicked)
-
-
-    def FoldAll(self):
-        lineCount = self.GetLineCount()
-        expanding = True
-
-        # find out if we are folding or unfolding
-        for lineNum in range(lineCount):
-            if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
-                expanding = not self.GetFoldExpanded(lineNum)
-                break
-
-        lineNum = 0
-
-        while lineNum < lineCount:
-            level = self.GetFoldLevel(lineNum)
-            if level & stc.STC_FOLDLEVELHEADERFLAG and \
-               (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
-
-                if expanding:
-                    self.SetFoldExpanded(lineNum, True)
-                    lineNum = self.Expand(lineNum, True)
-                    lineNum = lineNum - 1
-                else:
-                    lastChild = self.GetLastChild(lineNum, -1)
-                    self.SetFoldExpanded(lineNum, False)
-
-                    if lastChild > lineNum:
-                        self.HideLines(lineNum+1, lastChild)
-
-            lineNum = lineNum + 1
-
-
-
-    def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
-        lastChild = self.GetLastChild(line, level)
-        line = line + 1
-
-        while line <= lastChild:
-            if force:
-                if visLevels > 0:
-                    self.ShowLines(line, line)
-                else:
-                    self.HideLines(line, line)
-            else:
-                if doExpand:
-                    self.ShowLines(line, line)
-
-            if level == -1:
-                level = self.GetFoldLevel(line)
-
-            if level & stc.STC_FOLDLEVELHEADERFLAG:
-                if force:
-                    if visLevels > 1:
-                        self.SetFoldExpanded(line, True)
-                    else:
-                        self.SetFoldExpanded(line, False)
-
-                    line = self.Expand(line, doExpand, force, visLevels-1)
-
-                else:
-                    if doExpand and self.GetFoldExpanded(line):
-                        line = self.Expand(line, True, force, visLevels-1)
-                    else:
-                        line = self.Expand(line, False, force, visLevels-1)
-            else:
-                line = line + 1
-
-        return line
-
-    def Cut(self):
-        self.ResetBuffer()
-        self.DisableEvents = True
-        self.CmdKeyExecute(wx.stc.STC_CMD_CUT)
-        self.DisableEvents = False
-        self.RefreshModel()
-        self.RefreshBuffer()
-    
-    def Copy(self):
-        self.CmdKeyExecute(wx.stc.STC_CMD_COPY)
-    
-    def Paste(self):
-        self.ResetBuffer()
-        self.DisableEvents = True
-        self.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
-        self.DisableEvents = False
-        self.RefreshModel()
-        self.RefreshBuffer()
-
-
-#-------------------------------------------------------------------------------
-#                         Helper for VariablesGrid values
-#-------------------------------------------------------------------------------
-
-class VariablesTable(CustomTable):
-    
-    def GetValue(self, row, col):
-        if row < self.GetNumberRows():
-            if col == 0:
-                return row + 1
-            else:
-                return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
-    
-    def _updateColAttrs(self, grid):
-        """
-        wxGrid -> update the column attributes to add the
-        appropriate renderer given the column name.
-
-        Otherwise default to the default renderer.
-        """
-        
-        typelist = None
-        accesslist = None
-        for row in range(self.GetNumberRows()):
-            for col in range(self.GetNumberCols()):
-                editor = None
-                renderer = None
-                colname = self.GetColLabelValue(col, False)
-                
-                if colname == "Name":
-                    editor = wx.grid.GridCellTextEditor()
-                elif colname == "Class":
-                    editor = wx.grid.GridCellChoiceEditor()
-                    editor.SetParameters("input,memory,output")
-                elif colname == "Type":
-                    pass
-                else:
-                    grid.SetReadOnly(row, col, True)
-                
-                grid.SetCellEditor(row, col, editor)
-                grid.SetCellRenderer(row, col, renderer)
-                
-                grid.SetCellBackgroundColour(row, col, wx.WHITE)
-            self.ResizeRow(grid, row)
-    
-
-[ID_VARIABLESEDITOR, ID_VARIABLESEDITORVARIABLESGRID,
- ID_VARIABLESEDITORADDVARIABLEBUTTON, ID_VARIABLESEDITORDELETEVARIABLEBUTTON, 
- ID_VARIABLESEDITORUPVARIABLEBUTTON, ID_VARIABLESEDITORDOWNVARIABLEBUTTON
-] = [wx.NewId() for _init_ctrls in range(6)]
-
-class VariablesEditor(wx.Panel):
-    
-    if wx.VERSION < (2, 6, 0):
-        def Bind(self, event, function, id = None):
-            if id is not None:
-                event(self, id, function)
-            else:
-                event(self, function)
-    
-    def _init_coll_MainSizer_Growables(self, parent):
-        parent.AddGrowableCol(0)
-        parent.AddGrowableRow(0)
-
-    def _init_coll_MainSizer_Items(self, parent):
-        parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW)
-        parent.AddSizer(self.ButtonsSizer, 0, border=0, flag=wx.GROW)
-
-    def _init_coll_ButtonsSizer_Growables(self, parent):
-        parent.AddGrowableCol(0)
-        parent.AddGrowableRow(0)
-
-    def _init_coll_ButtonsSizer_Items(self, parent):
-        parent.AddWindow(self.AddVariableButton, 0, border=0, flag=wx.ALIGN_RIGHT)
-        parent.AddWindow(self.DeleteVariableButton, 0, border=0, flag=0)
-        parent.AddWindow(self.UpVariableButton, 0, border=0, flag=0)
-        parent.AddWindow(self.DownVariableButton, 0, border=0, flag=0)
-
-    def _init_sizers(self):
-        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
-        self.ButtonsSizer = wx.FlexGridSizer(cols=5, hgap=5, rows=1, vgap=0)
-        
-        self._init_coll_MainSizer_Growables(self.MainSizer)
-        self._init_coll_MainSizer_Items(self.MainSizer)
-        self._init_coll_ButtonsSizer_Growables(self.ButtonsSizer)
-        self._init_coll_ButtonsSizer_Items(self.ButtonsSizer)
-        
-        self.SetSizer(self.MainSizer)
-
-    def _init_ctrls(self, prnt):
-        wx.Panel.__init__(self, id=ID_VARIABLESEDITOR, name='', parent=prnt,
-              size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-        
-        self.VariablesGrid = CustomGrid(id=ID_VARIABLESEDITORVARIABLESGRID,
-              name='VariablesGrid', parent=self, pos=wx.Point(0, 0), 
-              size=wx.Size(-1, -1), style=wx.VSCROLL)
-        if wx.VERSION >= (2, 5, 0):
-            self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnVariablesGridCellChange)
-            self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnVariablesGridCellLeftClick)
-            self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, self.OnVariablesGridEditorShown)
-        else:
-            wx.grid.EVT_GRID_CELL_CHANGE(self.VariablesGrid, self.OnVariablesGridCellChange)
-            wx.grid.EVT_GRID_CELL_LEFT_CLICK(self.VariablesGrid, self.OnVariablesGridCellLeftClick)
-            wx.grid.EVT_GRID_EDITOR_SHOWN(self.VariablesGrid, self.OnVariablesGridEditorShown)
-        
-        self.AddVariableButton = wx.Button(id=ID_VARIABLESEDITORADDVARIABLEBUTTON, label='Add Variable',
-              name='AddVariableButton', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(122, 32), style=0)
-        
-        self.DeleteVariableButton = wx.Button(id=ID_VARIABLESEDITORDELETEVARIABLEBUTTON, label='Delete Variable',
-              name='DeleteVariableButton', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(122, 32), style=0)
-        
-        self.UpVariableButton = wx.Button(id=ID_VARIABLESEDITORUPVARIABLEBUTTON, label='^',
-              name='UpVariableButton', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(32, 32), style=0)
-        
-        self.DownVariableButton = wx.Button(id=ID_VARIABLESEDITORDOWNVARIABLEBUTTON, label='v',
-              name='DownVariableButton', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(32, 32), style=0)
-        
-        self._init_sizers()
-
-    def __init__(self, parent, window, controler):
-        self._init_ctrls(parent)
-        
-        self.ParentWindow = window
-        self.Controler = controler
-        
-        self.VariablesDefaultValue = {"Name" : "", "Class" : "input", "Type" : ""}
-        self.Table = VariablesTable(self, [], ["#", "Name", "Class", "Type"])
-        self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
-        self.ColSizes = [40, 200, 150, 150]
-        self.VariablesGrid.SetTable(self.Table)
-        self.VariablesGrid.SetButtons({"Add": self.AddVariableButton,
-                                       "Delete": self.DeleteVariableButton,
-                                       "Up": self.UpVariableButton,
-                                       "Down": self.DownVariableButton})
-        
-        def _AddVariable(new_row):
-            self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy())
-            self.RefreshModel()
-            self.RefreshView()
-            return new_row
-        setattr(self.VariablesGrid, "_AddRow", _AddVariable)
-        
-        def _DeleteVariable(row):
-            self.Table.RemoveRow(row)
-            self.RefreshModel()
-            self.RefreshView()
-        setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
-        
-        def _MoveVariable(row, move):
-            new_row = self.Table.MoveRow(row, move)
-            if new_row != row:
-                self.RefreshModel()
-                self.RefreshView()
-            return new_row
-        setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
-        
-        self.VariablesGrid.SetRowLabelSize(0)
-        for col in range(self.Table.GetNumberCols()):
-            attr = wx.grid.GridCellAttr()
-            attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
-            self.VariablesGrid.SetColAttr(col, attr)
-            self.VariablesGrid.SetColSize(col, self.ColSizes[col])
-        self.Table.ResetView(self.VariablesGrid)
-
-    def RefreshModel(self):
-        self.Controler.SetVariables(self.Table.GetData())
-        self.RefreshBuffer()
-        
-    # Buffer the last model state
-    def RefreshBuffer(self):
-        self.Controler.BufferCFile()
-        self.ParentWindow.RefreshTitle()
-        self.ParentWindow.RefreshFileMenu()
-        self.ParentWindow.RefreshEditMenu()
-        self.ParentWindow.RefreshPageTitles()
-
-    def RefreshView(self):
-        self.Table.SetData(self.Controler.GetVariables())
-        self.Table.ResetView(self.VariablesGrid)
-        self.VariablesGrid.RefreshButtons()
-    
-    def DoGetBestSize(self):
-        return self.ParentWindow.GetPanelBestSize()
-    
-    def OnVariablesGridCellChange(self, event):
-        self.RefreshModel()
-        wx.CallAfter(self.RefreshView)
-        event.Skip()
-
-    def OnVariablesGridEditorShown(self, event):
-        row, col = event.GetRow(), event.GetCol() 
-        if self.Table.GetColLabelValue(col) == "Type":
-            type_menu = wx.Menu(title='')
-            base_menu = wx.Menu(title='')
-            for base_type in self.Controler.GetBaseTypes():
-                new_id = wx.NewId()
-                AppendMenu(base_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=base_type)
-                self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(base_type), id=new_id)
-            type_menu.AppendMenu(wx.NewId(), "Base Types", base_menu)
-            datatype_menu = wx.Menu(title='')
-            for datatype in self.Controler.GetDataTypes(basetypes=False, only_locatables=True):
-                new_id = wx.NewId()
-                AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
-                self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
-            type_menu.AppendMenu(wx.NewId(), "User Data Types", datatype_menu)
-            rect = self.VariablesGrid.BlockToDeviceRect((row, col), (row, col))
-            
-            self.VariablesGrid.PopupMenuXY(type_menu, rect.x + rect.width, rect.y + self.VariablesGrid.GetColLabelSize())
-            type_menu.Destroy()
-            event.Veto()
-        else:
-            event.Skip()
-
-    def GetVariableTypeFunction(self, base_type):
-        def VariableTypeFunction(event):
-            row = self.VariablesGrid.GetGridCursorRow()
-            self.Table.SetValueByName(row, "Type", base_type)
-            self.Table.ResetView(self.VariablesGrid)
-            self.RefreshModel()
-            self.RefreshView()
-            event.Skip()
-        return VariableTypeFunction
-
-    def OnVariablesGridCellLeftClick(self, event):
-        if event.GetCol() == 0:
-            row = event.GetRow()
-            num = 0
-            if self.Table.GetValueByName(row, "Class") == "input":
-                dir = "%I"
-                for i in xrange(row):
-                    if self.Table.GetValueByName(i, "Class") == "input":
-                        num += 1
-            elif self.Table.GetValueByName(row, "Class") == "memory":
-                dir = "%M"
-                for i in xrange(row):
-                    if self.Table.GetValueByName(i, "Class") == "memory":
-                        num += 1
-            else:
-                dir = "%Q"
-                for i in xrange(row):
-                    if self.Table.GetValueByName(i, "Class") == "output":
-                        num += 1
-            data_type = self.Table.GetValueByName(row, "Type")
-            var_name = self.Table.GetValueByName(row, "Name")
-            base_location = ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation()))
-            location = "%s%s%s.%d"%(dir, self.Controler.GetSizeOfType(data_type), base_location, num)
-            data = wx.TextDataObject(str((location, "location", data_type, var_name, "")))
-            dragSource = wx.DropSource(self.VariablesGrid)
-            dragSource.SetData(data)
-            dragSource.DoDragDrop()
-        event.Skip()
-    
-
-#-------------------------------------------------------------------------------
-#                          SVGUIEditor Main Frame Class
-#-------------------------------------------------------------------------------
-
-CFILE_PARTS = [
-    ("Includes", CppEditor), 
-    ("Variables", VariablesEditor), 
-    ("Globals", CppEditor), 
-    ("Init", CppEditor), 
-    ("CleanUp", CppEditor), 
-    ("Retrieve", CppEditor), 
-    ("Publish", CppEditor),
-]
-
-#----------------------------------------------------------------------
-# different icons for the collapsed/expanded states.
-# Taken from standard Windows XP collapsed/expanded states.
-#----------------------------------------------------------------------
-
-def GetCollapsedIconData():
-    return \
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\
-\xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\
-\xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\
-H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\
-\xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\
-\xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\
-\x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\
-\xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\
-zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\
-\x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\
-~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\
-\x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\
-\xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\
-\xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\
-0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\
-\x00\x00\x00IEND\xaeB`\x82' 
-
-def GetCollapsedIconBitmap():
-    return wx.BitmapFromImage(GetCollapsedIconImage())
-
-def GetCollapsedIconImage():
-    import cStringIO
-    stream = cStringIO.StringIO(GetCollapsedIconData())
-    return wx.ImageFromStream(stream)
-
-#----------------------------------------------------------------------
-def GetExpandedIconData():
-    return \
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
-\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
-\x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\
-\xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\
-\x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\
-\xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\
-\x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\
-\x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\
-\x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\
-\xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\
-\x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\
-\x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\
-\xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\
-\xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\
-\x05\x10\x81\xce\xc9\xa8\xf6><G\xd8\xed\xbbA)X\xd9\x0c\x01\x9a\xc6Q\x14\xd9h\
-[\x04\xda\xd6c\xadFkE\xf0\xc2\xab\xd7\xb7\xc9\x08\x00\xf8\xf6\xbd\x1b\x8cQ\
-\xd8|\xb9\x0f\xd3\x9a\x8a\xc7\x08\x00\x9f?\xdd%\xde\x07\xda\x93\xc3{\x19C\
-\x8a\x9c\x03\x0b8\x17\xe8\x9d\xbf\x02.>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\
-\xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\
-`\x82' 
-
-def GetExpandedIconBitmap():
-    return wx.BitmapFromImage(GetExpandedIconImage())
-
-def GetExpandedIconImage():
-    import cStringIO
-    stream = cStringIO.StringIO(GetExpandedIconData())
-    return wx.ImageFromStream(stream)
-
-class FoldPanelCaption(wx.lib.buttons.GenBitmapTextToggleButton):
-    
-    def GetBackgroundBrush(self, dc):
-        colBg = self.GetBackgroundColour()
-        brush = wx.Brush(colBg, wx.SOLID)
-        if self.style & wx.BORDER_NONE:
-            myAttr = self.GetDefaultAttributes()
-            parAttr = self.GetParent().GetDefaultAttributes()
-            myDef = colBg == myAttr.colBg
-            parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg
-            if myDef and parDef:
-                if wx.Platform == "__WXMAC__":
-                    brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive
-                elif wx.Platform == "__WXMSW__":
-                    if self.DoEraseBackground(dc):
-                        brush = None
-            elif myDef and not parDef:
-                colBg = self.GetParent().GetBackgroundColour()
-                brush = wx.Brush(colBg, wx.SOLID)
-        return brush
-    
-    def DrawLabel(self, dc, width, height, dx=0, dy=0):
-        bmp = self.bmpLabel
-        if bmp is not None:     # if the bitmap is used
-            if self.bmpDisabled and not self.IsEnabled():
-                bmp = self.bmpDisabled
-            if self.bmpFocus and self.hasFocus:
-                bmp = self.bmpFocus
-            if self.bmpSelected and not self.up:
-                bmp = self.bmpSelected
-            bw,bh = bmp.GetWidth(), bmp.GetHeight()
-            hasMask = bmp.GetMask() is not None
-        else:
-            bw = bh = 0     # no bitmap -> size is zero
-        
-        dc.SetFont(self.GetFont())
-        if self.IsEnabled():
-            dc.SetTextForeground(self.GetForegroundColour())
-        else:
-            dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
-
-        label = self.GetLabel()
-        tw, th = dc.GetTextExtent(label)        # size of text
-        
-        if bmp is not None:
-            dc.DrawBitmap(bmp, width - bw - 2, (height-bh)/2, hasMask) # draw bitmap if available
-        
-        dc.DrawText(label, 2, (height-th)/2)      # draw the text
-
-        dc.SetPen(wx.Pen(self.GetForegroundColour()))
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.DrawRectangle(0, 0, width, height)
-
-[ID_CFILEEDITOR, ID_CFILEEDITORMAINSPLITTER, 
- ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED, 
-] = [wx.NewId() for _init_ctrls in range(4)]
-
-class CFileEditor(EditorPanel):
-    
-    def _init_Editor(self, prnt):
-        self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0), 
-                size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-        
-        self.Panels = {}
-        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2 * len(CFILE_PARTS) + 1, vgap=0)
-        self.MainSizer.AddGrowableCol(0)
-        
-        for idx, (name, panel_class) in enumerate(CFILE_PARTS):
-            button_id = wx.NewId()
-            button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name, 
-                  label=name, bitmap=GetCollapsedIconBitmap(), parent=self.Editor, pos=wx.Point(0, 0),
-                  size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT)
-            button.SetBitmapSelected(GetExpandedIconBitmap())
-            button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id)
-            self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW)
-            
-            if panel_class == VariablesEditor:
-                panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler)
-            else:
-                panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler)
-            self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW)
-            panel.Hide()
-            
-            self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1}
-        
-        self.Spacer = wx.Panel(self.Editor, -1)
-        self.SpacerExpanded = True
-        self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW)
-        
-        self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
-        
-        self.Editor.SetSizer(self.MainSizer)
-        
-    def __init__(self, parent, controler, window):
-        EditorPanel.__init__(self, parent, "", window, controler)
-        
-        img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
-        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-        
-    def __del__(self):
-        self.Controler.OnCloseEditor(self)
-    
-    def GetTitle(self):
-        fullname = self.Controler.PlugFullName()
-        if not self.Controler.CFileIsSaved():
-            return "~%s~" % fullname
-        return fullname
-    
-    def GetBufferState(self):
-        return self.Controler.GetBufferState()
-        
-    def Undo(self):
-        self.Controler.LoadPrevious()
-        self.RefreshView()
-            
-    def Redo(self):
-        self.Controler.LoadNext()
-        self.RefreshView()
-    
-    def HasNoModel(self):
-        return False
-
-    def RefreshView(self):
-        for infos in self.Panels.itervalues():
-            infos["panel"].RefreshView()
-
-    def GenPanelButtonCallback(self, name):
-        def PanelButtonCallback(event):
-            self.TogglePanel(name)
-        return PanelButtonCallback
-
-    def ExpandPanel(self, name):
-        infos = self.Panels.get(name, None)
-        if infos is not None and not infos["expanded"]:
-            infos["expanded"] = True
-            infos["button"].SetToggle(True)
-            infos["panel"].Show()
-            self.MainSizer.AddGrowableRow(infos["row"])
-        
-            self.RefreshSizerLayout()
-    
-    def CollapsePanel(self, name):
-        infos = self.Panels.get(name, None)
-        if infos is not None and infos["expanded"]:
-            infos["expanded"] = False
-            infos["button"].SetToggle(False)
-            infos["panel"].Hide()
-            self.MainSizer.RemoveGrowableRow(infos["row"])
-        
-            self.RefreshSizerLayout()
-        
-    def TogglePanel(self, name):
-        infos = self.Panels.get(name, None)
-        if infos is not None:
-            infos["expanded"] = not infos["expanded"]
-            infos["button"].SetToggle(infos["expanded"])
-            if infos["expanded"]:
-                infos["panel"].Show()
-                self.MainSizer.AddGrowableRow(infos["row"])
-            else:
-                infos["panel"].Hide()
-                self.MainSizer.RemoveGrowableRow(infos["row"])
-            
-            self.RefreshSizerLayout()
-    
-    def RefreshSizerLayout(self):
-        expand_spacer = True
-        for infos in self.Panels.itervalues():
-            expand_spacer = expand_spacer and not infos["expanded"]
-        
-        if self.SpacerExpanded != expand_spacer:
-            self.SpacerExpanded = expand_spacer
-            if expand_spacer:
-                self.Spacer.Show()
-                self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS))
-            else:
-                self.Spacer.Hide()
-                self.MainSizer.RemoveGrowableRow(2 * len(CFILE_PARTS))
-        
-        self.MainSizer.Layout()
-            
--- a/plugins/c_ext/README	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-C extension
\ No newline at end of file
--- a/plugins/c_ext/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from c_ext import *
--- a/plugins/c_ext/c_ext.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-import wx
-import os
-from xml.dom import minidom
-import cPickle
-
-from xmlclass import *
-
-from plugger import PlugTemplate, opjimg
-from CFileEditor import CFileEditor
-from PLCControler import PLCControler, UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
-
-CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd"))
-
-TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
-    "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
-    "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
-
-class _Cfile:
-    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
-    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-      <xsd:element name="CExtension">
-        <xsd:complexType>
-          <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
-          <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/>
-        </xsd:complexType>
-      </xsd:element>
-    </xsd:schema>
-    """
-    EditorType = CFileEditor
-    
-    def __init__(self):
-        filepath = self.CFileName()
-        
-        self.CFile = CFileClasses["CFile"]()
-        if os.path.isfile(filepath):
-            xmlfile = open(filepath, 'r')
-            tree = minidom.parse(xmlfile)
-            xmlfile.close()
-            
-            for child in tree.childNodes:
-                if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
-                    self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
-                    self.CreateCFileBuffer(True)
-        else:
-            self.CreateCFileBuffer(False)
-            self.OnPlugSave()
-
-    def CFileName(self):
-        return os.path.join(self.PlugPath(), "cfile.xml")
-
-    def GetBaseTypes(self):
-        return self.GetPlugRoot().GetBaseTypes()
-
-    def GetDataTypes(self, basetypes = False, only_locatables = False):
-        return self.GetPlugRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
-
-    def GetSizeOfType(self, type):
-        return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None)
-
-    def SetVariables(self, variables):
-        self.CFile.variables.setvariable([])
-        for var in variables:
-            variable = CFileClasses["variables_variable"]()
-            variable.setname(var["Name"])
-            variable.settype(var["Type"])
-            variable.setclass(var["Class"])
-            self.CFile.variables.appendvariable(variable)
-    
-    def GetVariables(self):
-        datas = []
-        for var in self.CFile.variables.getvariable():
-            datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
-        return datas
-
-    def GetVariableLocationTree(self):
-        '''See PlugTemplate.GetVariableLocationTree() for a description.'''
-
-        current_location = ".".join(map(str, self.GetCurrentLocation()))
-        
-        vars = []
-        input = memory = output = 0
-        for var in self.CFile.variables.getvariable():
-            var_size = self.GetSizeOfType(var.gettype())
-            var_location = ""
-            if var.getclass() == "input":
-                var_class = LOCATION_VAR_INPUT
-                if var_size is not None:
-                    var_location = "%%I%s%s.%d"%(var_size, current_location, input)
-                input += 1
-            elif var.getclass() == "memory":
-                var_class = LOCATION_VAR_INPUT
-                if var_size is not None:
-                    var_location = "%%M%s%s.%d"%(var_size, current_location, memory)
-                memory += 1
-            else:
-                var_class = LOCATION_VAR_OUTPUT
-                if var_size is not None:
-                    var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
-                output += 1
-            vars.append({"name": var.getname(),
-                         "type": var_class,
-                         "size": var_size,
-                         "IEC_type": var.gettype(),
-                         "var_name": var.getname(),
-                         "location": var_location,
-                         "description": "",
-                         "children": []})
-                
-        return  {"name": self.BaseParams.getName(),
-                "type": LOCATION_PLUGIN,
-                "location": self.GetFullIEC_Channel(),
-                "children": vars}
-
-    def SetPartText(self, name, text):
-        if name == "Includes":
-            self.CFile.includes.settext(text)
-        elif name == "Globals":
-            self.CFile.globals.settext(text)
-        elif name == "Init":
-            self.CFile.initFunction.settext(text)
-        elif name == "CleanUp":
-            self.CFile.cleanUpFunction.settext(text)
-        elif name == "Retrieve":
-            self.CFile.retrieveFunction.settext(text)
-        elif name == "Publish":
-            self.CFile.publishFunction.settext(text)
-        
-    def GetPartText(self, name):
-        if name == "Includes":
-            return self.CFile.includes.gettext()
-        elif name == "Globals":
-            return self.CFile.globals.gettext()
-        elif name == "Init":
-            return self.CFile.initFunction.gettext()
-        elif name == "CleanUp":
-            return self.CFile.cleanUpFunction.gettext()
-        elif name == "Retrieve":
-            return self.CFile.retrieveFunction.gettext()
-        elif name == "Publish":
-            return self.CFile.publishFunction.gettext()
-        return ""
-                
-    PluginMethods = [
-        {"bitmap" : os.path.join("images", "EditCfile"),
-         "name" : _("Edit C File"), 
-         "tooltip" : _("Edit C File"),
-         "method" : "_OpenView"},
-    ]
-
-    def PlugTestModified(self):
-        return self.ChangesToSave or not self.CFileIsSaved()    
-
-    def OnPlugSave(self):
-        filepath = self.CFileName()
-        
-        text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-        extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
-                  "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
-                  "xsi:schemaLocation" : "cext_xsd.xsd"}
-        text += self.CFile.generateXMLText("CFile", 0, extras)
-
-        xmlfile = open(filepath,"w")
-        xmlfile.write(text.encode("utf-8"))
-        xmlfile.close()
-        
-        self.MarkCFileAsSaved()
-        return True
-
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Generate C code
-        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
-        @param locations: List of complete variables locations \
-            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
-            "NAME" : name of the variable (generally "__IW0_1_2" style)
-            "DIR" : direction "Q","I" or "M"
-            "SIZE" : size "X", "B", "W", "D", "L"
-            "LOC" : tuple of interger for IEC location (0,1,2,...)
-            }, ...]
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-        current_location = self.GetCurrentLocation()
-        # define a unique name for the generated C file
-        location_str = "_".join(map(str, current_location))
-        
-        text = "/* Code generated by Beremiz c_ext plugin */\n\n"
-        
-        # Adding includes
-        text += "/* User includes */\n"
-        text += self.CFile.includes.gettext()
-        text += "\n"
-        
-        text += """/* Beremiz c_ext plugin includes */
-#ifdef _WINDOWS_H
-  #include "iec_types.h"
-#else
-  #include "iec_std_lib.h"
-#endif
-
-"""
-
-        # Adding variables
-        vars = []
-        inputs = memories = outputs = 0
-        for variable in self.CFile.variables.variable:
-            var = {"Name" : variable.getname(), "Type" : variable.gettype()}
-            if variable.getclass() == "input":
-                var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs)
-                inputs += 1
-            elif variable.getclass() == "memory":
-                var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
-                memories += 1
-            else:
-                var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
-                outputs += 1
-            vars.append(var)
-        text += "/* Beremiz c_ext plugin user variables definition */\n"
-        base_types = self.GetPlugRoot().GetBaseTypes()
-        for var in vars:
-            if var["Type"] in base_types:
-                prefix = "IEC_"
-            else:
-                prefix = ""
-            text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
-            text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
-        text += "/* User variables reference */\n"
-        for var in vars:
-            text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
-        text += "\n"
-        
-        # Adding user global variables and routines
-        text += "/* User internal user variables and routines */\n"
-        text += self.CFile.globals.gettext()
-        
-        # Adding Beremiz plugin functions
-        text += "/* Beremiz plugin functions */\n"
-        text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
-        text += self.CFile.initFunction.gettext()
-        text += "  return 0;\n"
-        text += "\n}\n\n"
-        
-        text += "void __cleanup_%s(void)\n{\n"%location_str
-        text += self.CFile.cleanUpFunction.gettext()
-        text += "\n}\n\n"
-        
-        text += "void __retrieve_%s(void)\n{\n"%location_str
-        text += self.CFile.retrieveFunction.gettext()
-        text += "\n}\n\n"
-        
-        text += "void __publish_%s(void)\n{\n"%location_str
-        text += self.CFile.publishFunction.gettext()
-        text += "\n}\n\n"
-        
-        Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
-        cfile = open(Gen_Cfile_path,'w')
-        cfile.write(text)
-        cfile.close()
-        
-        matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
-        
-        return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
-
-
-#-------------------------------------------------------------------------------
-#                      Current Buffering Management Functions
-#-------------------------------------------------------------------------------
-
-    """
-    Return a copy of the cfile model
-    """
-    def Copy(self, model):
-        return cPickle.loads(cPickle.dumps(model))
-
-    def CreateCFileBuffer(self, saved):
-        self.Buffering = False
-        self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
-
-    def BufferCFile(self):
-        self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
-    
-    def StartBuffering(self):
-        self.Buffering = True
-        
-    def EndBuffering(self):
-        if self.Buffering:
-            self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
-            self.Buffering = False
-    
-    def MarkCFileAsSaved(self):
-        self.EndBuffering()
-        self.CFileBuffer.CurrentSaved()
-    
-    def CFileIsSaved(self):
-        return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
-        
-    def LoadPrevious(self):
-        self.EndBuffering()
-        self.CFile = cPickle.loads(self.CFileBuffer.Previous())
-    
-    def LoadNext(self):
-        self.CFile = cPickle.loads(self.CFileBuffer.Next())
-    
-    def GetBufferState(self):
-        first = self.CFileBuffer.IsFirst() and not self.Buffering
-        last = self.CFileBuffer.IsLast()
-        return not first, not last
-
-class RootClass:
-
-    PlugChildsTypes = [("C_File",_Cfile, "C file")]
-    
-    def PlugGenerate_C(self, buildpath, locations):
-        return [],"",False
-
-
--- a/plugins/c_ext/cext_xsd.xsd	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<xsd:schema targetNamespace="cext_xsd.xsd" 
-            xmlns:cext="cext_xsd.xsd" 
-            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-            elementFormDefault="qualified" 
-            attributeFormDefault="unqualified">
-
-  <xsd:element name="CFile">
-    <xsd:complexType>
-      <xsd:sequence>
-        <xsd:element name="includes" type="cext:CCode"/>
-        <xsd:element name="variables">
-          <xsd:complexType>
-            <xsd:sequence>
-              <xsd:element name="variable" minOccurs="0" maxOccurs="unbounded">
-                <xsd:complexType>
-                  <xsd:attribute name="name" type="xsd:string" use="required"/>
-                  <xsd:attribute name="type" type="xsd:string" use="required"/>
-                  <xsd:attribute name="class" use="required">
-                    <xsd:simpleType>
-                      <xsd:restriction base="xsd:string">
-                        <xsd:enumeration value="input"/>
-                        <xsd:enumeration value="memory"/>
-                        <xsd:enumeration value="output"/>
-                      </xsd:restriction>
-                    </xsd:simpleType>
-                  </xsd:attribute>
-                </xsd:complexType>
-              </xsd:element>
-            </xsd:sequence>
-          </xsd:complexType>
-        </xsd:element>
-        <xsd:element name="globals" type="cext:CCode"/>
-        <xsd:element name="initFunction" type="cext:CCode"/>
-        <xsd:element name="cleanUpFunction" type="cext:CCode"/>
-        <xsd:element name="retrieveFunction" type="cext:CCode"/>
-        <xsd:element name="publishFunction" type="cext:CCode"/>
-      </xsd:sequence>
-    </xsd:complexType>
-  </xsd:element>
-  <xsd:complexType name="CCode">
-    <xsd:annotation>
-      <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
-    </xsd:annotation>
-    <xsd:sequence>
-      <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
-    </xsd:sequence>
-  </xsd:complexType>
-</xsd:schema>
--- a/plugins/canfestival/.cvsignore	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
--- a/plugins/canfestival/NetworkEditor.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-import os, sys
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-
-import wx
-
-from subindextable import EditingPanel
-from networkedit import NetworkEditorTemplate
-from controls import EditorPanel
-
-[ID_NETWORKEDITOR, 
-] = [wx.NewId() for _init_ctrls in range(1)]
-
-[ID_NETWORKEDITORPLUGINMENUADDSLAVE, ID_NETWORKEDITORPLUGINMENUREMOVESLAVE, 
- ID_NETWORKEDITORPLUGINMENUMASTER, 
-] = [wx.NewId() for _init_coll_PluginMenu_Items in range(3)]
-
-[ID_NETWORKEDITORMASTERMENUNODEINFOS, ID_NETWORKEDITORMASTERMENUDS301PROFILE,
- ID_NETWORKEDITORMASTERMENUDS302PROFILE, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE,
- ID_NETWORKEDITORMASTERMENUADD, 
-] = [wx.NewId() for _init_coll_MasterMenu_Items in range(5)]
-
-[ID_NETWORKEDITORADDMENUSDOSERVER, ID_NETWORKEDITORADDMENUSDOCLIENT,
- ID_NETWORKEDITORADDMENUPDOTRANSMIT, ID_NETWORKEDITORADDMENUPDORECEIVE,
- ID_NETWORKEDITORADDMENUMAPVARIABLE, ID_NETWORKEDITORADDMENUUSERTYPE,
-] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
-
-class NetworkEditor(EditorPanel, NetworkEditorTemplate):
-    
-    ID = ID_NETWORKEDITOR
-    
-    def _init_coll_MainSizer_Items(self, parent):
-        parent.AddWindow(self.NetworkNodes, 0, border=5, flag=wx.GROW|wx.ALL)
-
-    def _init_coll_MainSizer_Growables(self, parent):
-        parent.AddGrowableCol(0)
-        parent.AddGrowableRow(0)
-    
-    def _init_sizers(self):
-        self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=1, vgap=0)
-        
-        self._init_coll_MainSizer_Items(self.MainSizer)
-        self._init_coll_MainSizer_Growables(self.MainSizer)
-        
-        self.Editor.SetSizer(self.MainSizer)
-    
-    def _init_Editor(self, prnt):
-        self.Editor = wx.Panel(id=-1, parent=prnt, pos=wx.Point(0, 0), 
-                size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
-        
-        NetworkEditorTemplate._init_ctrls(self, self.Editor)
-        
-        self._init_sizers()
-        
-    def __init__(self, parent, controler, window):
-        EditorPanel.__init__(self, parent, "", window, controler)
-        NetworkEditorTemplate.__init__(self, controler, window, False)
-    
-        img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
-        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-        
-        self.RefreshNetworkNodes()
-        self.RefreshBufferState()
-    
-    def __del__(self):
-        self.Controler.OnCloseEditor(self)
-    
-    def GetPluginMenuItems(self):
-        add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_NETWORKEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
-                    (wx.ITEM_NORMAL, (_('SDO Client'), ID_NETWORKEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
-                    (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_NETWORKEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
-                    (wx.ITEM_NORMAL, (_('PDO Receive'), ID_NETWORKEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
-                    (wx.ITEM_NORMAL, (_('Map Variable'), ID_NETWORKEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
-                    (wx.ITEM_NORMAL, (_('User Type'), ID_NETWORKEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
-        
-        profile = self.Manager.GetCurrentProfileName()
-        if profile not in ("None", "DS-301"):
-            other_profile_text = _("%s Profile") % profile
-            add_menu.append((wx.ITEM_SEPARATOR, None))
-            for text, indexes in self.Manager.GetCurrentSpecificMenu():
-                add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
-        else:
-            other_profile_text = _('Other Profile')
-        
-        master_menu = [(wx.ITEM_NORMAL, (_('Node infos'), ID_NETWORKEDITORMASTERMENUNODEINFOS, '', self.OnNodeInfosMenu)),
-                       (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_NETWORKEDITORMASTERMENUDS301PROFILE, '', self.OnCommunicationMenu)),
-                       (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_NETWORKEDITORMASTERMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
-                       (wx.ITEM_NORMAL, (other_profile_text, ID_NETWORKEDITORMASTERMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
-                       (wx.ITEM_SEPARATOR, None),
-                       (add_menu, (_('Add'), ID_NETWORKEDITORMASTERMENUADD))]
-        
-        return [(wx.ITEM_NORMAL, (_('Add slave'), ID_NETWORKEDITORPLUGINMENUADDSLAVE, '', self.OnAddSlaveMenu)),
-                (wx.ITEM_NORMAL, (_('Remove slave'), ID_NETWORKEDITORPLUGINMENUREMOVESLAVE, '', self.OnRemoveSlaveMenu)),
-                (wx.ITEM_SEPARATOR, None),
-                (master_menu, (_('Master'), ID_NETWORKEDITORPLUGINMENUMASTER))]
-    
-    def RefreshMainMenu(self):
-        pass
-    
-    def RefreshPluginMenu(self, plugin_menu):
-        plugin_menu.Enable(ID_NETWORKEDITORPLUGINMENUMASTER, self.NetworkNodes.GetSelection() == 0)
-    
-    def GetTitle(self):
-        fullname = self.Controler.PlugFullName()
-        if not self.Manager.CurrentIsSaved():
-            return "~%s~" % fullname
-        return fullname
-
-    def RefreshView(self):
-        self.RefreshCurrentIndexList()
-    
-    def RefreshBufferState(self):
-        NetworkEditorTemplate.RefreshBufferState(self)
-        self.ParentWindow.RefreshTitle()
-        self.ParentWindow.RefreshFileMenu()
-        self.ParentWindow.RefreshEditMenu()
-        self.ParentWindow.RefreshPageTitles()
-    
-    def OnNodeSelectedChanged(self, event):
-        NetworkEditorTemplate.OnNodeSelectedChanged(self, event)
-        wx.CallAfter(self.ParentWindow.RefreshPluginMenu)
-        
--- a/plugins/canfestival/README	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-CANOpen
\ No newline at end of file
--- a/plugins/canfestival/SlaveEditor.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-import os, sys
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-
-import wx
-
-from subindextable import EditingPanel
-from nodeeditor import NodeEditorTemplate
-from controls import EditorPanel
-
-[ID_SLAVEEDITORPLUGINMENUNODEINFOS, ID_SLAVEEDITORPLUGINMENUDS301PROFILE,
- ID_SLAVEEDITORPLUGINMENUDS302PROFILE, ID_SLAVEEDITORPLUGINMENUDSOTHERPROFILE,
- ID_SLAVEEDITORPLUGINMENUADD, 
-] = [wx.NewId() for _init_coll_PluginMenu_Items in range(5)]
-
-[ID_SLAVEEDITORADDMENUSDOSERVER, ID_SLAVEEDITORADDMENUSDOCLIENT,
- ID_SLAVEEDITORADDMENUPDOTRANSMIT, ID_SLAVEEDITORADDMENUPDORECEIVE,
- ID_SLAVEEDITORADDMENUMAPVARIABLE, ID_SLAVEEDITORADDMENUUSERTYPE,
-] = [wx.NewId() for _init_coll_AddMenu_Items in range(6)]
-
-class SlaveEditor(EditorPanel, NodeEditorTemplate):
-    
-    def _init_Editor(self, prnt):
-        self.Editor = EditingPanel(prnt, self, self.Controler, self.Editable)
-        
-    def __init__(self, parent, controler, window, editable=True):
-        self.Editable = editable
-        EditorPanel.__init__(self, parent, "", window, controler)
-        NodeEditorTemplate.__init__(self, controler, window, False)
-        
-        img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
-        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-    
-    def __del__(self):
-        self.Controler.OnCloseEditor(self)
-    
-    def GetPluginMenuItems(self):
-        if self.Editable:
-            add_menu = [(wx.ITEM_NORMAL, (_('SDO Server'), ID_SLAVEEDITORADDMENUSDOSERVER, '', self.OnAddSDOServerMenu)),
-                        (wx.ITEM_NORMAL, (_('SDO Client'), ID_SLAVEEDITORADDMENUSDOCLIENT, '', self.OnAddSDOClientMenu)),
-                        (wx.ITEM_NORMAL, (_('PDO Transmit'), ID_SLAVEEDITORADDMENUPDOTRANSMIT, '', self.OnAddPDOTransmitMenu)),
-                        (wx.ITEM_NORMAL, (_('PDO Receive'), ID_SLAVEEDITORADDMENUPDORECEIVE, '', self.OnAddPDOReceiveMenu)),
-                        (wx.ITEM_NORMAL, (_('Map Variable'), ID_SLAVEEDITORADDMENUMAPVARIABLE, '', self.OnAddMapVariableMenu)),
-                        (wx.ITEM_NORMAL, (_('User Type'), ID_SLAVEEDITORADDMENUUSERTYPE, '', self.OnAddUserTypeMenu))]
-            
-            profile = self.Controler.GetCurrentProfileName()
-            if profile not in ("None", "DS-301"):
-                other_profile_text = _("%s Profile") % profile
-                add_menu.append((wx.ITEM_SEPARATOR, None))
-                for text, indexes in self.Manager.GetCurrentSpecificMenu():
-                    add_menu.append((wx.ITEM_NORMAL, (text, wx.NewId(), '', self.GetProfileCallBack(text))))
-            else:
-                other_profile_text = _('Other Profile')
-            
-            return [(wx.ITEM_NORMAL, (_('Node infos'), ID_SLAVEEDITORPLUGINMENUNODEINFOS, '', self.OnNodeInfosMenu)),
-                    (wx.ITEM_NORMAL, (_('DS-301 Profile'), ID_SLAVEEDITORPLUGINMENUDS301PROFILE, '', self.OnCommunicationMenu)),
-                    (wx.ITEM_NORMAL, (_('DS-302 Profile'), ID_SLAVEEDITORPLUGINMENUDS302PROFILE, '', self.OnOtherCommunicationMenu)),
-                    (wx.ITEM_NORMAL, (other_profile_text, ID_SLAVEEDITORPLUGINMENUDSOTHERPROFILE, '', self.OnEditProfileMenu)),
-                    (wx.ITEM_SEPARATOR, None),
-                    (add_menu, (_('Add'), ID_SLAVEEDITORPLUGINMENUADD))]
-        return []
-    
-    def RefreshPluginMenu(self, plugin_menu):
-        plugin_menu.Enable(ID_SLAVEEDITORPLUGINMENUDSOTHERPROFILE, False)
-    
-    def GetTitle(self):
-        fullname = self.Controler.PlugFullName()
-        if not self.Controler.CurrentIsSaved():
-            return "~%s~" % fullname
-        return fullname
-
-    def RefreshView(self):
-        self.Editor.RefreshIndexList()
-
-    def RefreshCurrentIndexList(self):
-        self.RefreshView()
-    
-    def RefreshBufferState(self):
-        self.ParentWindow.RefreshTitle()
-        self.ParentWindow.RefreshFileMenu()
-        self.ParentWindow.RefreshEditMenu()
-        self.ParentWindow.RefreshPageTitles()
-            
--- a/plugins/canfestival/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from canfestival import *
--- a/plugins/canfestival/canfestival.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
-import os, sys
-base_folder = os.path.split(sys.path[0])[0]
-CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
-sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
-
-from nodelist import NodeList
-from nodemanager import NodeManager
-import config_utils, gen_cfile, eds_utils
-from networkedit import networkedit
-from objdictedit import objdictedit
-import canfestival_config as local_canfestival_config
-from plugger import PlugTemplate
-from commondialogs import CreateNodeDialog
-import wx
-
-from SlaveEditor import SlaveEditor
-from NetworkEditor import NetworkEditor
-
-from gnosis.xml.pickle import *
-from gnosis.xml.pickle.util import setParanoia
-setParanoia(0)
-
-if wx.Platform == '__WXMSW__':
-    DEFAULT_SETTINGS = {
-        "CAN_Driver": "can_tcp_win32",
-        "CAN_Device": "127.0.0.1",
-        "CAN_Baudrate": "125K",
-        "Slave_NodeId": 2,
-        "Master_NodeId": 1,
-    }
-else:
-    DEFAULT_SETTINGS = {
-        "CAN_Driver": "../CanFestival-3/drivers/can_socket/libcanfestival_can_socket.so",
-        "CAN_Device": "vcan0",
-        "CAN_Baudrate": "125K",
-        "Slave_NodeId": 2,
-        "Master_NodeId": 1,
-    }
-
-#--------------------------------------------------
-#                    SLAVE
-#--------------------------------------------------
-
-class _SlavePlug(NodeManager):
-    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
-    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-      <xsd:element name="CanFestivalSlaveNode">
-        <xsd:complexType>
-          <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/>
-          <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
-          <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Slave_NodeId)d"/>
-          <xsd:attribute name="Sync_Align" type="xsd:integer" use="optional" default="0"/>
-          <xsd:attribute name="Sync_Align_Ratio" use="optional" default="50">
-            <xsd:simpleType>
-                <xsd:restriction base="xsd:integer">
-                    <xsd:minInclusive value="1"/>
-                    <xsd:maxInclusive value="99"/>
-                </xsd:restriction>
-            </xsd:simpleType>
-          </xsd:attribute>
-        </xsd:complexType>
-      </xsd:element>
-    </xsd:schema>
-    """ % DEFAULT_SETTINGS
-    
-    EditorType = SlaveEditor
-
-    def __init__(self):
-        # TODO change netname when name change
-        NodeManager.__init__(self)
-        odfilepath = self.GetSlaveODPath()
-        if(os.path.isfile(odfilepath)):
-            self.OpenFileInCurrent(odfilepath)
-        else:
-            self.FilePath = ""
-            dialog = CreateNodeDialog(None, wx.OK)
-            dialog.Type.Enable(False)
-            dialog.GenSYNC.Enable(False)
-            if dialog.ShowModal() == wx.ID_OK:
-                name, id, nodetype, description = dialog.GetValues()
-                profile, filepath = dialog.GetProfile()
-                NMT = dialog.GetNMTManagement()
-                options = dialog.GetOptions()
-                self.CreateNewNode(name,       # Name - will be changed at build time
-                                   id,         # NodeID - will be changed at build time
-                                   "slave",    # Type
-                                   description,# description 
-                                   profile,    # profile
-                                   filepath,   # prfile filepath
-                                   NMT,        # NMT
-                                   options)     # options
-            else:
-                self.CreateNewNode("SlaveNode",  # Name - will be changed at build time
-                                   0x00,         # NodeID - will be changed at build time
-                                   "slave",      # Type
-                                   "",           # description 
-                                   "None",       # profile
-                                   "", # prfile filepath
-                                   "heartbeat",  # NMT
-                                   [])           # options
-            dialog.Destroy()
-            self.OnPlugSave()
-
-    def GetSlaveODPath(self):
-        return os.path.join(self.PlugPath(), 'slave.od')
-
-    def GetCanDevice(self):
-        return self.CanFestivalSlaveNode.getCan_Device()
-
-    def _OpenView(self):
-        PlugTemplate._OpenView(self)
-        if self._View is not None:
-            self._View.SetBusId(self.GetCurrentLocation())
-
-    PluginMethods = [
-        {"bitmap" : os.path.join("images", "NetworkEdit"),
-         "name" : "Edit slave", 
-         "tooltip" : "Edit CanOpen slave with ObjdictEdit",
-         "method" : "_OpenView"},
-    ]
-
-    def OnPlugClose(self):
-        if self._View:
-            self._View.Close()
-
-    def PlugTestModified(self):
-        return self.ChangesToSave or self.OneFileHasChanged()
-        
-    def OnPlugSave(self):
-        return self.SaveCurrentInFile(self.GetSlaveODPath())
-
-    def SetParamsAttribute(self, path, value):
-        result = PlugTemplate.SetParamsAttribute(self, path, value)
-        
-        # Filter IEC_Channel and Name, that have specific behavior
-        if path == "BaseParams.IEC_Channel" and self._View is not None:
-            self._View.SetBusId(self.GetCurrentLocation())
-        
-        return result
-        
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Generate C code
-        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
-        @param locations: List of complete variables locations \
-            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
-            "NAME" : name of the variable (generally "__IW0_1_2" style)
-            "DIR" : direction "Q","I" or "M"
-            "SIZE" : size "X", "B", "W", "D", "L"
-            "LOC" : tuple of interger for IEC location (0,1,2,...)
-            }, ...]
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-        current_location = self.GetCurrentLocation()
-        # define a unique name for the generated C file
-        prefix = "_".join(map(str, current_location))
-        Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
-        # Create a new copy of the model
-        slave = self.GetCurrentNodeCopy()
-        slave.SetNodeName("OD_%s"%prefix)
-        # allow access to local OD from Slave PLC
-        pointers = config_utils.LocalODPointers(locations, current_location, slave)
-        res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
-        if res :
-            raise Exception, res
-        res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
-        if res :
-            raise Exception, res
-        return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
-
-    def LoadPrevious(self):
-        self.LoadCurrentPrevious()
-    
-    def LoadNext(self):
-        self.LoadCurrentNext()
-    
-    def GetBufferState(self):
-        return self.GetCurrentBufferState()
-
-#--------------------------------------------------
-#                    MASTER
-#--------------------------------------------------
-
-class MiniNodeManager(NodeManager):
-    
-    def __init__(self, parent, filepath, fullname):
-        NodeManager.__init__(self)
-        
-        self.OpenFileInCurrent(filepath)
-            
-        self.Parent = parent
-        self.Fullname = fullname
-        
-    def OnCloseEditor(self, view):
-        self.Parent.OnCloseEditor(view)
-    
-    def PlugFullName(self):
-        return self.Fullname
-    
-    def GetBufferState(self):
-        return self.GetCurrentBufferState()
-
-class _NodeListPlug(NodeList):
-    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
-    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-      <xsd:element name="CanFestivalNode">
-        <xsd:complexType>
-          <xsd:attribute name="CAN_Device" type="xsd:string" use="optional" default="%(CAN_Device)s"/>
-          <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="optional" default="%(CAN_Baudrate)s"/>
-          <xsd:attribute name="NodeId" type="xsd:string" use="optional" default="%(Master_NodeId)d"/>
-          <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
-        </xsd:complexType>
-      </xsd:element>
-    </xsd:schema>
-    """ % DEFAULT_SETTINGS
-    
-    EditorType = NetworkEditor
-    
-    def __init__(self):
-        manager = NodeManager()
-        NodeList.__init__(self, manager)
-        self.LoadProject(self.PlugPath())
-        self.SetNetworkName(self.BaseParams.getName())
-    
-    def GetCanDevice(self):
-        return self.CanFestivalNode.getCan_Device()
-    
-    def SetParamsAttribute(self, path, value):
-        result = PlugTemplate.SetParamsAttribute(self, path, value)
-        
-        # Filter IEC_Channel and Name, that have specific behavior
-        if path == "BaseParams.IEC_Channel" and self._View is not None:
-            self._View.SetBusId(self.GetCurrentLocation())
-        elif path == "BaseParams.Name":
-            self.SetNetworkName(value)
-        
-        return result
-    
-    def _OpenView(self):
-        PlugTemplate._OpenView(self)
-        if self._View is not None:
-            self._View.SetBusId(self.GetCurrentLocation())
-    
-    _GeneratedView = None
-    def _ShowMasterGenerated(self):
-        if self._GeneratedView is None:
-            buildpath = self._getBuildPath()
-            # Eventually create build dir
-            if not os.path.exists(buildpath):
-                self.GetPlugRoot().logger.write_error(_("Error: No PLC built\n"))
-                return
-            
-            masterpath = os.path.join(buildpath, "MasterGenerated.od")
-            if not os.path.exists(masterpath):
-                self.GetPlugRoot().logger.write_error(_("Error: No Master generated\n"))
-                return
-            
-            app_frame = self.GetPlugRoot().AppFrame
-            
-            manager = MiniNodeManager(self, masterpath, self.PlugFullName() + ".generated_master")
-            self._GeneratedView = SlaveEditor(app_frame.TabsOpened, manager, app_frame, False)
-            
-            app_frame.EditProjectElement(self._GeneratedView, "MasterGenerated")
-    
-    def _CloseGenerateView(self):
-        if self._GeneratedView is not None:
-            app_frame = self.GetPlugRoot().AppFrame
-            if app_frame is not None:
-                app_frame.DeletePage(self._GeneratedView)
-    
-    PluginMethods = [
-        {"bitmap" : os.path.join("images", "NetworkEdit"),
-         "name" : _("Edit network"), 
-         "tooltip" : _("Edit CanOpen Network with NetworkEdit"),
-         "method" : "_OpenView"},
-        {"bitmap" : os.path.join("images", "ShowMaster"),
-         "name" : _("Show Master"), 
-         "tooltip" : _("Show Master generated by config_utils"),
-         "method" : "_ShowMasterGenerated"}
-    ]
-    
-    def OnCloseEditor(self, view):
-        PlugTemplate.OnCloseEditor(self, view)
-        if self._GeneratedView == view:
-            self._GeneratedView = None
-
-    def OnPlugClose(self):
-        PlugTemplate.OnPlugClose(self)
-        self._CloseGenerateView()
-        return True
-
-    def PlugTestModified(self):
-        return self.ChangesToSave or self.HasChanged()
-        
-    def OnPlugSave(self):
-        self.SetRoot(self.PlugPath())
-        return self.SaveProject() is None
-
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Generate C code
-        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
-        @param locations: List of complete variables locations \
-            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
-            "NAME" : name of the variable (generally "__IW0_1_2" style)
-            "DIR" : direction "Q","I" or "M"
-            "SIZE" : size "X", "B", "W", "D", "L"
-            "LOC" : tuple of interger for IEC location (0,1,2,...)
-            }, ...]
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-        self._CloseGenerateView()
-        current_location = self.GetCurrentLocation()
-        # define a unique name for the generated C file
-        prefix = "_".join(map(str, current_location))
-        Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
-        # Create a new copy of the model with DCF loaded with PDO mappings for desired location
-        try:
-            master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
-        except config_utils.PDOmappingException, e:
-            raise Exception, e.message
-        # Do generate C file.
-        res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
-        if res :
-            raise Exception, res
-        
-        file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
-        dump(master, file)
-        file.close()
-        
-        return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
-    
-    def LoadPrevious(self):
-        self.Manager.LoadCurrentPrevious()
-    
-    def LoadNext(self):
-        self.Manager.LoadCurrentNext()
-    
-    def GetBufferState(self):
-        return self.Manager.GetCurrentBufferState()
-    
-class RootClass:
-    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
-    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-      <xsd:element name="CanFestivalInstance">
-        <xsd:complexType>
-          <xsd:attribute name="CAN_Driver" type="xsd:string" use="optional" default="%(CAN_Driver)s"/>
-          <xsd:attribute name="Debug_mode" type="xsd:boolean" use="optional" default="false"/>
-        </xsd:complexType>
-      </xsd:element>
-    </xsd:schema>
-    """ % DEFAULT_SETTINGS
-    
-    PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen Master"),
-                       ("CanOpenSlave",_SlavePlug, "CanOpen Slave")]
-    def GetParamsAttributes(self, path = None):
-        infos = PlugTemplate.GetParamsAttributes(self, path = None)
-        for element in infos:
-            if element["name"] == "CanFestivalInstance":
-                for child in element["children"]:
-                    if child["name"] == "CAN_Driver":
-                        DLL_LIST= getattr(local_canfestival_config,"DLL_LIST",None)
-                        if DLL_LIST is not None:
-                            child["type"] = DLL_LIST  
-        return infos
-    
-    def GetCanDriver(self):
-        can_driver = self.CanFestivalInstance.getCAN_Driver()
-        if sys.platform == 'win32':
-            if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(can_driver + '_DEBUG.dll'))):
-                can_driver += '_DEBUG.dll'
-            else:
-                can_driver += '.dll'
-        return can_driver
-    
-    def PlugGenerate_C(self, buildpath, locations):
-        
-        format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
-                       "candriver" : self.GetCanDriver(),
-                       "nodes_includes" : "",
-                       "board_decls" : "",
-                       "nodes_init" : "",
-                       "nodes_open" : "",
-                       "nodes_stop" : "",
-                       "nodes_close" : "",
-                       "nodes_send_sync" : "",
-                       "nodes_proceed_sync" : "",
-                       "slavebootups" : "",
-                       "slavebootup_register" : "",
-                       "post_sync" : "",
-                       "post_sync_register" : "",
-                       }
-        for child in self.IECSortedChilds():
-            childlocstr = "_".join(map(str,child.GetCurrentLocation()))
-            nodename = "OD_%s" % childlocstr
-            
-            # Try to get Slave Node
-            child_data = getattr(child, "CanFestivalSlaveNode", None)
-            if child_data is None:
-                # Not a slave -> master
-                child_data = getattr(child, "CanFestivalNode")
-                # Apply sync setting
-                format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n    '%(
-                       nodename,
-                       child_data.getNodeId())
-                if child_data.getSync_TPDOs():
-                    format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n    '%(nodename)
-                    format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n    '%(nodename)
-
-                # initialize and declare node boot status variables for post_SlaveBootup lookup
-                SlaveIDs = child.GetSlaveIDs()
-                if len(SlaveIDs) == 0:
-                    # define post_SlaveBootup lookup functions
-                    format_dict["slavebootups"] += (
-                        "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
-                else:
-                    for id in SlaveIDs:
-                        format_dict["slavebootups"] += (
-                        "int %s_slave_%d_booted = 0;\n"%(nodename, id))
-                    # define post_SlaveBootup lookup functions
-                    format_dict["slavebootups"] += (
-                        "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n"%(nodename)+
-                        "    switch(nodeId){\n")
-                    # one case per declared node, mark node as booted
-                    for id in SlaveIDs:
-                        format_dict["slavebootups"] += (
-                        "        case %d:\n"%(id)+
-                        "            %s_slave_%d_booted = 1;\n"%(nodename, id)+
-                        "            break;\n")
-                    format_dict["slavebootups"] += (
-                        "        default:\n"+
-                        "            break;\n"+
-                        "    }\n"+
-                        "    if( ")
-                    # expression to test if all declared nodes booted
-                    format_dict["slavebootups"] += " && ".join(["%s_slave_%d_booted"%(nodename, id) for id in SlaveIDs])
-                    format_dict["slavebootups"] += " )\n" + (
-                        "        Master_post_SlaveBootup(d,nodeId);\n"+
-                        "}\n")
-                # register previously declared func as post_SlaveBootup callback for that node
-                format_dict["slavebootup_register"] += (
-                    "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n"%(nodename,nodename))
-            else:
-                # Slave node
-                align = child_data.getSync_Align()
-                align_ratio=child_data.getSync_Align_Ratio()
-                if align > 0:
-                    format_dict["post_sync"] += (
-                        "static int %s_CalCount = 0;\n"%(nodename)+
-                        "static void %s_post_sync(CO_Data* d){\n"%(nodename)+
-                        "    if(%s_CalCount < %d){\n"%(nodename, align)+
-                        "        %s_CalCount++;\n"%(nodename)+
-                        "        align_tick(-1);\n"+
-                        "    }else{\n"+
-                        "        align_tick(%d);\n"%(align_ratio)+
-                        "    }\n"+
-                        "}\n")
-                    format_dict["post_sync_register"] += (
-                        "%s_Data.post_sync = %s_post_sync;\n"%(nodename,nodename))
-                format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n    '%(
-                       nodename,
-                       child_data.getNodeId())
-    
-            # Include generated OD headers
-            format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
-            # Declare CAN channels according user filled config
-            format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
-                   nodename,
-                   child.GetCanDevice(),
-                   child_data.getCAN_Baudrate())
-            format_dict["nodes_open"] += 'NODE_OPEN(%s)\n    '%(nodename)
-            format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n    '%(nodename)
-            format_dict["nodes_stop"] += 'NODE_STOP(%s)\n    '%(nodename)
-        
-        filename = os.path.join(os.path.split(__file__)[0],"cf_runtime.c")
-        cf_main = open(filename).read() % format_dict
-        cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict)
-        f = open(cf_main_path,'w')
-        f.write(cf_main)
-        f.close()
-        
-        return [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True
-
-
--- a/plugins/canfestival/cf_runtime.c	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-
-#include "canfestival.h"
-
-/* CanFestival nodes generated OD headers*/
-%(nodes_includes)s
-
-#define BOARD_DECL(nodename, busname, baudrate)\
-    s_BOARD nodename##Board = {busname, baudrate};
-
-/* CAN channels declaration */
-%(board_decls)s
-
-/* Keep track of init level to cleanup correctly */
-static int init_level=0;
-/* Retrieve PLC cycle time */
-extern int common_ticktime__;
-
-/* Called once all NetworkEdit declares slaves have booted*/
-static void Master_post_SlaveBootup(CO_Data* d, UNS8 nodeId)
-{
-    /* Put the master in operational mode */
-    setState(d, Operational);
-
-    /* Ask slave node to go in operational mode */
-    masterSendNMTstateChange (d, 0, NMT_Start_Node);
-}
-
-/* Per master node slavebootup callbacks. Checks that
- * every node have booted before calling Master_post_SlaveBootup */
-%(slavebootups)s
-
-/* One slave node post_sync callback.
- * Used to align PLC tick-time on CANopen SYNC
- */
-%(post_sync)s
-
-#define NODE_FORCE_SYNC(nodename) \
-    /* Artificially force sync state to 1 so that it is not started */\
-    nodename##_Data.CurrentCommunicationState.csSYNC = -1;\
-    /* Force sync period to common_ticktime__ so that other node can read it*/\
-    *nodename##_Data.COB_ID_Sync = 0x40000080;\
-    *nodename##_Data.Sync_Cycle_Period = common_ticktime__ * 1000;
-
-#define NODE_INIT(nodename, nodeid) \
-    /* Defining the node Id */\
-    setNodeId(&nodename##_Data, nodeid);\
-    /* init */\
-    setState(&nodename##_Data, Initialisation);
-
-#define NODE_MASTER_INIT(nodename, nodeid) \
-    NODE_FORCE_SYNC(nodename) \
-    NODE_INIT(nodename, nodeid)
-
-#define NODE_SLAVE_INIT(nodename, nodeid) \
-    NODE_INIT(nodename, nodeid)
-
-void InitNodes(CO_Data* d, UNS32 id)
-{
-    %(slavebootup_register)s
-    %(post_sync_register)s
-    %(nodes_init)s
-}
-
-#define NODE_STOP(nodename) \
-    if(init_level-- > 0)\
-    {\
-        masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\
-        setState(&nodename##_Data, Stopped);\
-    }
-
-void Exit(CO_Data* d, UNS32 id)
-{
-    %(nodes_stop)s
-}
-
-#define NODE_CLOSE(nodename) \
-    if(init_level_c-- > 0)\
-    {\
-      canClose(&nodename##_Data);\
-    }
-
-void __cleanup_%(locstr)s(void)
-{
-    // Stop timer thread
-    if(init_level-- > 0){
-    int init_level_c = init_level;
-        StopTimerLoop(&Exit);
-        %(nodes_close)s
-    }
-
-    TimerCleanup();
-}
-
-#ifndef stderr
-#define fprintf(...)
-#define fflush(...)
-#endif
-
-#define NODE_OPEN(nodename)\
-    if(!canOpen(&nodename##Board,&nodename##_Data)){\
-        fprintf(stderr,"Cannot open CAN intefrace %%s at speed %%s\n for CANopen node \"" #nodename "\"",nodename##Board.busname, nodename##Board.baudrate);\
-        fflush(stderr);\
-        return -1;\
-    }\
-    init_level++;
-
-/***************************  INIT  *****************************************/
-int __init_%(locstr)s(int argc,char **argv)
-{
-#ifndef NOT_USE_DYNAMIC_LOADING
-    if( !LoadCanDriver("%(candriver)s") ){
-        fprintf(stderr, "Cannot load CAN interface library for CanFestival (%(candriver)s)\n");\
-        fflush(stderr);\
-        return -1;\
-    }
-#endif
-
-    TimerInit();
-
-    %(nodes_open)s
-
-    // Start timer thread
-    StartTimerLoop(&InitNodes);
-    init_level++;
-    return 0;
-}
-
-#define NODE_SEND_SYNC(nodename)\
-    sendSYNCMessage(&nodename##_Data);
-
-void __retrieve_%(locstr)s(void)
-{
-    /* Locks the stack, so that no changes occurs while PLC access variables
-     * TODO : implement buffers to avoid such a big lock
-     *  */
-    EnterMutex();
-    /* Send Sync */
-    %(nodes_send_sync)s
-}
-
-#define NODE_PROCEED_SYNC(nodename)\
-    proceedSYNC(&nodename##_Data);
-
-void __publish_%(locstr)s(void)
-{
-    /* Process sync event */
-    %(nodes_proceed_sync)s
-    LeaveMutex();
-}
-
--- a/plugins/canfestival/config_utils.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,737 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-#This file is part of Beremiz, a Integrated Development Environment for
-#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. 
-#
-#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
-#
-#See COPYING file for copyrights details.
-#
-#This library is free software; you can redistribute it and/or
-#modify it under the terms of the GNU General Public
-#License as published by the Free Software Foundation; either
-#version 2.1 of the License, or (at your option) any later version.
-#
-#This library is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#General Public License for more details.
-#
-#You should have received a copy of the GNU General Public
-#License along with this library; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-from types import *
-
-# Translation between IEC types and Can Open types
-IECToCOType = {"BOOL":0x01, "SINT":0x02, "INT":0x03,"DINT":0x04,"LINT":0x10,
-               "USINT":0x05,"UINT":0x06,"UDINT":0x07,"ULINT":0x1B,"REAL":0x08,
-               "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07,
-               "LWORD":0x1B,"WSTRING":0x0B}
-
-# Constants for PDO types 
-RPDO = 1
-TPDO = 2
-
-SlavePDOType = {"I" : TPDO, "Q" : RPDO}
-InvertPDOType = {RPDO : TPDO, TPDO : RPDO}
-PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800}
-PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180}
-
-VariableIncrement = 0x100
-VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000}
-VariableDirText = {TPDO : "__I", RPDO : "__Q"}
-VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6)))
-
-TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)]
-
-#-------------------------------------------------------------------------------
-#                  Specific exception for PDO mapping errors
-#-------------------------------------------------------------------------------
-
-class PDOmappingException(Exception):
-    pass
-
-
-def LE_to_BE(value, size):
-    """
-    Convert Little Endian to Big Endian
-    @param value: value expressed in integer
-    @param size: number of bytes generated
-    @return: a string containing the value converted
-    """
-    
-    data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
-    list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
-    list_car.reverse()
-    return "".join([chr(int(car, 16)) for car in list_car])
-
-
-def GetNodePDOIndexes(node, type, parameters = False):
-    """
-    Find the PDO indexes of a node
-    @param node: node 
-    @param type: type of PDO searched (RPDO or TPDO or both)
-    @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
-    @return: a list of indexes found
-    """
-    
-    indexes = []
-    if type & RPDO:
-        indexes.extend([idx for idx in node.GetIndexes() if 0x1400 <= idx <= 0x15FF])
-    if type & TPDO:
-        indexes.extend([idx for idx in node.GetIndexes() if 0x1800 <= idx <= 0x19FF])
-    if not parameters:
-        return [idx + 0x200 for idx in indexes]
-    else:
-        return indexes
-
-
-def SearchNodePDOMapping(loc_infos, node):
-    """
-    Find the PDO indexes of a node
-    @param node: node 
-    @param type: type of PDO searched (RPDO or TPDO or both)
-    @param parameters: indicate which indexes are expected (PDO paramaters : True or PDO mappings : False)
-    @return: a list of indexes found
-    """
-    
-    model = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8)
-    
-    for PDOidx in GetNodePDOIndexes(node, loc_infos["pdotype"]):
-        values = node.GetEntry(PDOidx)
-        if values != None:
-            for subindex, mapping in enumerate(values):
-                if subindex != 0 and mapping & 0xFFFFFF00 == model:
-                    return PDOidx, subindex
-    return None
-
-
-def GeneratePDOMappingDCF(idx, cobid, transmittype, pdomapping):
-    """
-    Build concise DCF value for configuring a PDO
-    @param idx: index of PDO parameters
-    @param cobid: PDO generated COB ID
-    @param transmittype : PDO transmit type
-    @param pdomapping: list of PDO mappings
-    @return: a tuple of value and number of parameters to add to DCF 
-    """
-    
-    # Create entry for RPDO or TPDO parameters and Disable PDO
-    dcfdata = LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(0x80000000 + cobid, 4)
-    # Set Transmit type synchrone
-    dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x02, 1) + LE_to_BE(0x01, 4) + LE_to_BE(transmittype, 1)
-    # Re-Enable PDO
-    #         ---- INDEX -----   --- SUBINDEX ----   ----- SIZE ------   ------ DATA ------
-    dcfdata += LE_to_BE(idx, 2) + LE_to_BE(0x01, 1) + LE_to_BE(0x04, 4) + LE_to_BE(cobid, 4)
-    nbparams = 3
-    if len(pdomapping) > 0:
-        dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(0x00, 1) + LE_to_BE(0x01, 4) + LE_to_BE(len(pdomapping), 1)
-        nbparams += 1
-        # Map Variables
-        for subindex, (name, loc_infos) in enumerate(pdomapping):
-            value = (loc_infos["index"] << 16) + (loc_infos["subindex"] << 8) + loc_infos["size"]
-            dcfdata += LE_to_BE(idx + 0x200, 2) + LE_to_BE(subindex + 1, 1) + LE_to_BE(0x04, 4) + LE_to_BE(value, 4)
-            nbparams += 1
-    return dcfdata, nbparams
-
-class ConciseDCFGenerator:
-
-    def __init__(self, nodelist, nodename):
-        # Dictionary of location informations classed by name
-        self.IECLocations = {}
-        # Dictionary of location that have not been mapped yet
-        self.LocationsNotMapped = {}
-        # Dictionary of location informations classed by name
-        self.MasterMapping = {}
-        # List of COB IDs available
-        self.ListCobIDAvailable = range(0x180, 0x580)
-        # Dictionary of mapping value where unexpected variables are stored
-        self.TrashVariables = {}
-        # Dictionary of pointed variables
-        self.PointedVariables = {}
-        
-        self.NodeList = nodelist
-        self.Manager = self.NodeList.Manager
-        self.MasterNode = self.Manager.GetCurrentNodeCopy()
-        self.MasterNode.SetNodeName(nodename)
-        self.PrepareMasterNode()
-
-    def GetPointedVariables(self):
-        return self.PointedVariables
-    
-    def RemoveUsedNodeCobId(self, node):
-        """
-        Remove all PDO COB ID used by the given node from the list of available COB ID
-        @param node: node
-        @return: a tuple of number of RPDO and TPDO for the node
-        """
-        
-        # Get list of all node TPDO and RPDO indexes
-        nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True)
-        nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True)
-        
-        # Mark all the COB ID of the node already mapped PDO as not available
-        for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes:
-            pdo_cobid = node.GetEntry(PdoIdx, 0x01)
-            # Extract COB ID, if PDO isn't active
-            if pdo_cobid > 0x600 :
-                pdo_cobid -= 0x80000000
-            # Remove COB ID from the list of available COB ID
-            if pdo_cobid in self.ListCobIDAvailable:
-                self.ListCobIDAvailable.remove(pdo_cobid)
-        
-        return len(nodeRpdoIndexes), len(nodeTpdoIndexes)
-
-    
-    def PrepareMasterNode(self):
-        """
-        Add mandatory entries for DCF generation into MasterNode.
-        """
-        
-        # Adding DCF entry into Master node
-        if not self.MasterNode.IsEntry(0x1F22):
-            self.MasterNode.AddEntry(0x1F22, 1, "")
-        self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode)
-        
-        # Adding trash mappable variables for unused mapped datas
-        idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID()
-        # Add an entry for storing unexpected all variable
-        self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode)
-        for subidx, (size, typeidx) in enumerate(TrashVariables):
-            # Add a subentry for storing unexpected variable of this size
-            self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode)
-            self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode)
-            # Store the mapping value for this entry
-            self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size
-        
-        RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode)
-        
-        # Store the indexes of the first RPDO and TPDO available for MasterNode
-        self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber}
-
-        # Prepare MasterNode with all nodelist slaves
-        for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()):
-            node = nodeinfos["Node"]
-            node.SetNodeID(nodeid)
-            
-            RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node)
-            
-            # Get Slave's default SDO server parameters
-            RSDO_cobid = node.GetEntry(0x1200,0x01)
-            if not RSDO_cobid:
-                RSDO_cobid = 0x600 + nodeid
-            TSDO_cobid = node.GetEntry(0x1200,0x02)
-            if not TSDO_cobid:
-                TSDO_cobid = 0x580 + nodeid
-            
-            # Configure Master's SDO parameters entries
-            self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode)
-            self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid)
-            self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid)
-            self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid)        
-        
-    
-    def GetMasterNode(self):
-        """
-        Return MasterNode.
-        """
-        return self.MasterNode
-    
-    def AddParamsToDCF(self, nodeid, data, nbparams):
-        """
-        Add entry to DCF, for the requested nodeID
-        @param nodeid: id of the slave (int)
-        @param data: data to add to slave DCF (string)
-        @param nbparams: number of params added to slave DCF (int)
-        """
-        # Get current DCF for slave
-        nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid)
-        
-        # Extract data and number of params in current DCF
-        if nodeDCF != None and nodeDCF != '':
-            tmpnbparams = [i for i in nodeDCF[:4]]
-            tmpnbparams.reverse()
-            nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16)
-            data = nodeDCF[4:] + data
-        
-        # Build new DCF
-        dcf = LE_to_BE(nbparams, 0x04) + data
-        # Set new DCF for slave
-        self.MasterNode.SetEntry(0x1F22, nodeid, dcf)
-    
-    def GetEmptyPDO(self, nodeid, pdotype, start_index=None):
-        """
-        Search a not configured PDO for a slave
-        @param node: the slave node object
-        @param pdotype: type of PDO to generated (RPDO or TPDO)
-        @param start_index: Index where search must start (default: None)
-        @return tuple of PDO index, COB ID and number of subindex defined
-        """
-        # If no start_index defined, start with PDOtype base index
-        if start_index is None:
-            index = PDOTypeBaseIndex[pdotype]
-        else:
-            index = start_index
-        
-        # Search for all PDO possible index until find a configurable PDO
-        # starting from start_index
-        while index < PDOTypeBaseIndex[pdotype] + 0x200:
-            values = self.NodeList.GetSlaveNodeEntry(nodeid, index + 0x200)
-            if values != None and values[0] > 0:
-                # Check that all subindex upper than 0 equal 0 => configurable PDO
-                if reduce(lambda x, y: x and y, map(lambda x: x == 0, values[1:]), True):
-                    cobid = self.NodeList.GetSlaveNodeEntry(nodeid, index, 1)
-                    # If no COB ID defined in PDO, generate a new one (not used)
-                    if cobid == 0:
-                        if len(self.ListCobIDAvailable) == 0:
-                            return None
-                        # Calculate COB ID from standard values
-                        if index < PDOTypeBaseIndex[pdotype] + 4:
-                            cobid = PDOTypeBaseCobId[pdotype] + 0x100 * (index - PDOTypeBaseIndex[pdotype]) + nodeid
-                        if cobid not in self.ListCobIDAvailable:
-                            cobid = self.ListCobIDAvailable.pop(0)
-                    return index, cobid, values[0]
-            index += 1
-        return None
-    
-    def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs):
-        """
-        Record a new mapping request for a slave, and add related slave config to the DCF
-        @param nodeid: id of the slave (int)
-        @param pdotype: type of PDO to generated (RPDO or TPDO)
-        @param pdomapping: list od variables to map with PDO
-        """
-        # Add an entry to MasterMapping
-        self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], 
-            "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]}
-        
-        # Return the data to add to DCF
-        if sync_TPDOs:
-            return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping)
-        else:
-            return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping)
-        return 0, ""
-    
-    def GenerateDCF(self, locations, current_location, sync_TPDOs):
-        """
-        Generate Concise DCF of MasterNode for the locations list given
-        @param locations: list of locations to be mapped
-        @param current_location: tuple of the located prefixes not to be considered
-        @param sync_TPDOs: indicate if TPDO must be synchronous
-        """
-        
-        #-------------------------------------------------------------------------------
-        #               Verify that locations correspond to real slave variables
-        #-------------------------------------------------------------------------------
-        
-        # Get list of locations check if exists and mappables -> put them in IECLocations
-        for location in locations:
-            COlocationtype = IECToCOType[location["IEC_TYPE"]]
-            name = location["NAME"]
-            if name in self.IECLocations:
-                if self.IECLocations[name]["type"] != COlocationtype:
-                    raise PDOmappingException, _("Type conflict for location \"%s\"") % name 
-            else:
-                # Get only the part of the location that concern this node
-                loc = location["LOC"][len(current_location):]
-                # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
-                if len(loc) not in (2, 3, 4):
-                    raise PDOmappingException, _("Bad location size : %s") % str(loc)
-                elif len(loc) == 2:
-                    continue
-                
-                direction = location["DIR"]
-                
-                sizelocation = location["SIZE"]
-                
-                # Extract and check nodeid
-                nodeid, index, subindex = loc[:3]
-                
-                # Check Id is in slave node list
-                if nodeid not in self.NodeList.SlaveNodes.keys():
-                    raise PDOmappingException, _("Non existing node ID : %d (variable %s)") % (nodeid,name)
-                
-                # Get the model for this node (made from EDS)
-                node = self.NodeList.SlaveNodes[nodeid]["Node"]
-                
-                # Extract and check index and subindex
-                if not node.IsEntry(index, subindex):
-                    raise PDOmappingException, _("No such index/subindex (%x,%x) in ID : %d (variable %s)") % (index,subindex,nodeid,name)
-                
-                # Get the entry info
-                subentry_infos = node.GetSubentryInfos(index, subindex)
-                
-                # If a PDO mappable
-                if subentry_infos and subentry_infos["pdo"]:
-                    if sizelocation == "X" and len(loc) > 3:
-                        numbit = loc[3]
-                    elif sizelocation != "X" and len(loc) > 3:
-                        raise PDOmappingException, _("Cannot set bit offset for non bool '%s' variable (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
-                    else:
-                        numbit = None
-                    
-                    if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
-                        raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d  for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
-                    
-                    typeinfos = node.GetEntryInfos(COlocationtype)
-                    self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
-                                                "nodeid": nodeid, "index": index,"subindex": subindex,
-                                                "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation}
-                else:
-                    raise PDOmappingException, _("Not PDO mappable variable : '%s' (ID:%d,Idx:%x,sIdx:%x))") % (name,nodeid,index,subindex)
-        
-        #-------------------------------------------------------------------------------
-        #                         Search for locations already mapped
-        #-------------------------------------------------------------------------------
-        
-        for name, locationinfos in self.IECLocations.items():
-            node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"]
-            
-            # Search if slave has a PDO mapping this locations
-            result = SearchNodePDOMapping(locationinfos, node)
-            if result != None:
-                index, subindex = result
-                # Get COB ID of the PDO
-                cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1)
-                
-                # Add PDO to MasterMapping
-                if cobid not in self.MasterMapping.keys():
-                    # Verify that PDO transmit type is conform to sync_TPDOs
-                    transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2)
-                    if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF:
-                        if sync_TPDOs:
-                            # Change TransmitType to SYNCHRONE
-                            data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, [])
-                        else:
-                            # Change TransmitType to ASYCHRONE
-                            data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, [])
-                        
-                        # Add entry to slave dcf to change transmit type of 
-                        self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams)
-                                    
-                    mapping = [None]
-                    values = node.GetEntry(index)
-                    # Store the size of each entry mapped in PDO
-                    for value in values[1:]:
-                        if value != 0:
-                            mapping.append(value % 0x100)
-                    self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping}
-            
-                # Indicate that this PDO entry must be saved
-                if locationinfos["bit"] is not None:
-                    if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType):
-                        self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex]
-                    if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]):
-                        self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name)
-                else:
-                    self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name)
-                
-            else:
-                # Add location to those that haven't been mapped yet
-                if locationinfos["nodeid"] not in self.LocationsNotMapped.keys():
-                    self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []}
-                self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos))
-    
-        #-------------------------------------------------------------------------------
-        #                         Build concise DCF for the others locations
-        #-------------------------------------------------------------------------------
-        
-        for nodeid, locations in self.LocationsNotMapped.items():
-            node = self.NodeList.SlaveNodes[nodeid]["Node"]
-            
-            # Initialize number of params and data to add to node DCF
-            nbparams = 0
-            dataparams = ""
-            
-            # Generate the best PDO mapping for each type of PDO
-            for pdotype in (TPDO, RPDO):
-                if len(locations[pdotype]) > 0:
-                    pdosize = 0
-                    pdomapping = []
-                    result = self.GetEmptyPDO(nodeid, pdotype)
-                    if result is None:
-                        raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
-                    pdoindex, pdocobid, pdonbparams = result
-                    for name, loc_infos in locations[pdotype]:
-                        pdosize += loc_infos["size"]
-                        # If pdo's size > 64 bits
-                        if pdosize > 64 or len(pdomapping) >= pdonbparams:
-                            # Generate a new PDO Mapping
-                            data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
-                            dataparams += data
-                            nbparams += nbaddedparams
-                            pdosize = loc_infos["size"]
-                            pdomapping = [(name, loc_infos)]
-                            result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1)
-                            if result is None:
-                                raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid
-                            pdoindex, pdocobid, pdonbparams = result
-                        else:
-                            pdomapping.append((name, loc_infos))
-                    # If there isn't locations yet but there is still a PDO to generate
-                    if len(pdomapping) > 0:
-                        # Generate a new PDO Mapping
-                        data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs)
-                        dataparams += data
-                        nbparams += nbaddedparams
-                
-            # Add number of params and data to node DCF
-            self.AddParamsToDCF(nodeid, dataparams, nbparams)
-        
-        #-------------------------------------------------------------------------------
-        #                         Master Node Configuration
-        #-------------------------------------------------------------------------------
-        
-        # Generate Master's Configuration from informations stored in MasterMapping
-        for cobid, pdo_infos in self.MasterMapping.items():
-            # Get next PDO index in MasterNode for this PDO type
-            current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]]
-            
-            # Search if there is already a PDO in MasterNode with this cob id
-            for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True):
-                if self.MasterNode.GetEntry(idx, 1) == cobid:
-                    current_idx = idx
-            
-            # Add a PDO to MasterNode if not PDO have been found
-            if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]:
-                addinglist = [current_idx, current_idx + 0x200]
-                self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode)
-                self.MasterNode.SetEntry(current_idx, 0x01, cobid)
-                
-                # Increment the number of PDO for this PDO type
-                self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1
-            
-            # Change the transmit type of the PDO
-            if sync_TPDOs:
-                self.MasterNode.SetEntry(current_idx, 0x02, 0x01)
-            else:
-                self.MasterNode.SetEntry(current_idx, 0x02, 0xFF)
-            
-            mapping = []
-            for item in pdo_infos["mapping"]:
-                if isinstance(item, ListType):
-                    mapping.extend(item)
-                else:
-                    mapping.append(item)
-            
-            # Add some subentries to PDO mapping if there is not enough
-            if len(mapping) > 1:
-                self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode)
-            
-            # Generate MasterNode's PDO mapping
-            for subindex, variable in enumerate(mapping):
-                if subindex == 0:
-                    continue
-                new_index = False
-                
-                if isinstance(variable, (IntType, LongType)):
-                    # If variable is an integer then variable is unexpected
-                    self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable])
-                else:
-                    typeidx, varname = variable
-                    variable_infos = self.IECLocations[varname]
-                    
-                    # Calculate base index for storing variable
-                    mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \
-                                     VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
-                                     variable_infos["nodeid"]
-                    
-                    # Generate entry name
-                    indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
-                                                 variable_infos["sizelocation"],
-                                                 '_'.join(map(str,current_location)),
-                                                 variable_infos["nodeid"])    
-                    
-                    # Search for an entry that has an empty subindex 
-                    while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
-                        # Entry doesn't exist
-                        if not self.MasterNode.IsEntry(mapvariableidx):    
-                            # Add entry to MasterNode
-                            self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
-                            new_index = True
-                            nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
-                        else:
-                            # Get Number of subentries already defined
-                            nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
-                            # if entry is full, go to next entry possible or stop now
-                            if nbsubentries == 0xFF:
-                                mapvariableidx += 8 * VariableIncrement
-                            else:
-                                break
-                                
-                    # Verify that a not full entry has been found
-                    if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
-                        # Generate subentry name
-                        if variable_infos["bit"] != None:
-                            subindexname = "%(index)d_%(subindex)d_%(bit)d"%variable_infos
-                        else:
-                            subindexname = "%(index)d_%(subindex)d"%variable_infos
-                        # If entry have just been created, no subentry have to be added
-                        if not new_index:
-                            self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode)
-                            nbsubentries += 1
-                        # Add informations to the new subentry created
-                        self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname})
-                        self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx})
-                        
-                        # Set value of the PDO mapping
-                        typeinfos = self.Manager.GetEntryInfos(typeidx)
-                        if typeinfos != None:
-                            value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
-                            self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
-                        
-                        # Add variable to pointed variables
-                        self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
-
-def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename):
-    """
-    Fills a CanFestival network editor model, with DCF with requested PDO mappings.
-    @param locations: List of complete variables locations \
-        [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
-        "NAME" : name of the variable (generally "__IW0_1_2" style)
-        "DIR" : direction "Q","I" or "M"
-        "SIZE" : size "X", "B", "W", "D", "L"
-        "LOC" : tuple of interger for IEC location (0,1,2,...)
-        }, ...]
-    @param nodelist: CanFestival network editor model
-    @return: a modified copy of the given CanFestival network editor model
-    """
-    
-    dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
-    dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
-    masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
-    # allow access to local OD from Master PLC
-    pointers.update(LocalODPointers(locations, current_location, masternode))
-    return masternode,pointers
-
-def LocalODPointers(locations, current_location, slave):
-    IECLocations = {}
-    pointers = {}
-    for location in locations:
-        COlocationtype = IECToCOType[location["IEC_TYPE"]]
-        name = location["NAME"]
-        if name in IECLocations:
-            if IECLocations[name] != COlocationtype:
-                raise PDOmappingException, _("Type conflict for location \"%s\"") % name 
-        else:
-            # Get only the part of the location that concern this node
-            loc = location["LOC"][len(current_location):]
-            # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
-            if len(loc) not in (2, 3, 4):
-                raise PDOmappingException, _("Bad location size : %s") % str(loc)
-            elif len(loc) != 2:
-                continue
-            
-            # Extract and check nodeid
-            index, subindex = loc[:2]
-            
-            # Extract and check index and subindex
-            if not slave.IsEntry(index, subindex):
-                raise PDOmappingException, _("No such index/subindex (%x,%x) (variable %s)") % (index, subindex, name)
-            
-            # Get the entry info
-            subentry_infos = slave.GetSubentryInfos(index, subindex)    
-            if subentry_infos["type"] != COlocationtype:
-                raise PDOmappingException, _("Invalid type \"%s\"-> %d != %d  for location\"%s\"") % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
-            
-            IECLocations[name] = COlocationtype
-            pointers[(index, subindex)] = name
-    return pointers
-        
-if __name__ == "__main__":
-    import os, sys, getopt
-
-    def usage():
-        print """
-Usage of config_utils.py test :
-
-    %s [options]
-
-Options:
-    --help  (-h)
-            Displays help informations for config_utils
-
-    --reset (-r)
-            Reset the reference result of config_utils test.
-            Use with caution. Be sure that config_utils
-            is currently working properly.
-"""%sys.argv[0]
-    
-    # Boolean that indicate if reference result must be redefined
-    reset = False
-
-    # Extract command options
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "hr", ["help","reset"])
-    except getopt.GetoptError:
-        # print help information and exit:
-        usage()
-        sys.exit(2)
-
-    # Test each option
-    for o, a in opts:
-        if o in ("-h", "--help"):
-            usage()
-            sys.exit()
-        elif o in ("-r", "--reset"):
-            reset = True
-
-    # Extract workspace base folder
-    base_folder = sys.path[0]
-    for i in xrange(3):
-        base_folder = os.path.split(base_folder)[0]
-    # Add CanFestival folder to search pathes
-    sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen"))
-    
-    from nodemanager import *
-    from nodelist import *
-    
-    # Open the test nodelist contained into test_config folder
-    manager = NodeManager()
-    nodelist = NodeList(manager)
-    result = nodelist.LoadProject("test_config")
-    
-    # List of locations, we try to map for test
-    locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)},
-                 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)},
-                 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)},
-                 {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)},
-                 {"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24578_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24578,1)},
-                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)},
-                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)},
-                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)},
-                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)},
-                 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}]
-    
-    # Generate MasterNode configuration
-    try:
-        masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode")
-    except ValueError, message:
-        print "%s\nTest Failed!"%message
-        sys.exit()
-    
-    import pprint
-    # Get Text corresponding to MasterNode 
-    result_node = masternode.PrintString()
-    result_vars = pprint.pformat(pointedvariables)
-    result = result_node + "\n********POINTERS*********\n" + result_vars + "\n"
-    
-    # If reset has been choosen
-    if reset:
-        # Write Text into reference result file
-        testfile = open("test_config/result.txt", "w")
-        testfile.write(result)
-        testfile.close()
-        
-        print "Reset Successful!"
-    else:
-        import os
-        
-        testfile = open("test_config/result_tmp.txt", "w")
-        testfile.write(result)
-        testfile.close()
-        
-        os.system("diff test_config/result.txt test_config/result_tmp.txt")
-        os.remove("test_config/result_tmp.txt")
--- a/plugins/canfestival/test_config/eds/PEAK MicroMod.eds	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1289 +0,0 @@
-[FileInfo]
-CreatedBy=ESAcademy
-ModifiedBy=ESAcademy
-Description=PEAK MicroMod CANopenIA Generic
-CreationTime=09:41PM
-CreationDate=05-05-2003
-ModificationTime=05:05PM
-ModificationDate=03-23-2005
-FileName=C:\CANopenCT\Tests\PEAK MicroMod.eds
-FileVersion=1
-FileRevision=1
-EDSVersion=4
-
-[DeviceInfo]
-VendorName=PEAK System Technik
-VendorNumber=0x00000175
-ProductName=PEAK MicroMod CANopenIA Generic
-ProductNumber=0x00100000
-RevisionNumber=0x00010001
-OrderCode=na
-BaudRate_10=0
-BaudRate_20=0
-BaudRate_50=1
-BaudRate_125=1
-BaudRate_250=1
-BaudRate_500=1
-BaudRate_800=1
-BaudRate_1000=1
-SimpleBootUpMaster=0
-SimpleBootUpSlave=1
-Granularity=0
-DynamicChannelsSupported=0
-CompactPDO=0
-GroupMessaging=0
-NrOfRXPDO=4
-NrOfTXPDO=4
-LSS_Supported=0
-
-[DummyUsage]
-Dummy0001=0
-Dummy0002=0
-Dummy0003=0
-Dummy0004=0
-Dummy0005=1
-Dummy0006=1
-Dummy0007=1
-
-[Comments]
-Lines=0
-
-[MandatoryObjects]
-SupportedObjects=3
-1=0x1000
-2=0x1001
-3=0x1018
-
-[1000]
-ParameterName=Device Type
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x000F0191
-PDOMapping=0
-
-[1001]
-ParameterName=Error Register
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=0
-PDOMapping=0
-
-[1018]
-ParameterName=Identity Object
-ObjectType=0x9
-SubNumber=4
-
-[1018sub0]
-ParameterName=number of entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=3
-PDOMapping=0
-
-[1018sub1]
-ParameterName=Vendor ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x00000175
-PDOMapping=0
-
-[1018sub2]
-ParameterName=Product Code
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x00100000
-PDOMapping=0
-
-[1018sub3]
-ParameterName=Revision number
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-DefaultValue=0x00010001
-PDOMapping=0
-
-[OptionalObjects]
-SupportedObjects=41
-1=0x1002
-2=0x1005
-3=0x1008
-4=0x1009
-5=0x100A
-6=0x100C
-7=0x100D
-8=0x1010
-9=0x1011
-10=0x1016
-11=0x1017
-12=0x1020
-13=0x1400
-14=0x1401
-15=0x1402
-16=0x1403
-17=0x1600
-18=0x1601
-19=0x1602
-20=0x1603
-21=0x1800
-22=0x1801
-23=0x1802
-24=0x1803
-25=0x1A00
-26=0x1A01
-27=0x1A02
-28=0x1A03
-29=0x1F50
-30=0x6000
-31=0x6002
-32=0x6200
-33=0x6202
-34=0x6206
-35=0x6207
-36=0x6401
-37=0x6411
-38=0x6423
-39=0x6426
-40=0x6443
-41=0x6444
-
-[1002]
-ParameterName=PEAK Status Register
-ObjectType=0x7
-DataType=0x0007
-AccessType=ro
-PDOMapping=0
-
-[1005]
-ParameterName=COB-ID SYNC
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x00000080
-PDOMapping=0
-
-[1008]
-ParameterName=Manufacturer Device Name
-ObjectType=0x7
-DataType=0x0009
-AccessType=const
-PDOMapping=0
-
-[1009]
-ParameterName=Manufacturer Hardware Version
-ObjectType=0x7
-DataType=0x0009
-AccessType=const
-PDOMapping=0
-
-[100a]
-ParameterName=Manufacturer Software Version
-ObjectType=0x7
-DataType=0x0009
-AccessType=const
-PDOMapping=0
-
-[100c]
-ParameterName=Guard Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[100d]
-ParameterName=Life Time Factor
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0x00
-PDOMapping=0
-
-[1010]
-ParameterName=Store Parameter Field
-ObjectType=0x8
-SubNumber=2
-
-[1010sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[1010sub1]
-ParameterName=Save all Parameters
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1011]
-ParameterName=Restore Default Parameters
-ObjectType=0x8
-SubNumber=2
-
-[1011sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[1011sub1]
-ParameterName=Restore all Default Parameters
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1016]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x8
-SubNumber=4
-
-[1016sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=3
-PDOMapping=0
-LowLimit=0x1
-
-[1016sub1]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1016sub2]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1016sub3]
-ParameterName=Consumer Heartbeat Time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1017]
-ParameterName=Producer Heartbeat Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1020]
-ParameterName=Verify Configuration
-ObjectType=0x8
-SubNumber=3
-
-[1020sub0]
-ParameterName=Number of entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-
-[1020sub1]
-ParameterName=Configuration date
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1020sub2]
-ParameterName=Configuration time
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-PDOMapping=0
-
-[1400]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1400sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-
-[1400sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x200
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1400sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1401]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1401sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-
-[1401sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x300
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1401sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1402]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1402sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1402sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x80000400
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1402sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1403]
-ParameterName=Receive PDO Communication Parameter
-ObjectType=0x9
-SubNumber=3
-
-[1403sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=2
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1403sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x80000500
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1403sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1600]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=2
-
-[1600sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=1
-PDOMapping=0
-
-[1600sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x62000108
-PDOMapping=0
-
-[1601]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1601sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=4
-PDOMapping=0
-
-[1601sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110110
-PDOMapping=0
-
-[1601sub2]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110210
-PDOMapping=0
-
-[1601sub3]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110310
-PDOMapping=0
-
-[1601sub4]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64110410
-PDOMapping=0
-
-[1602]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=1
-
-[1602sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1603]
-ParameterName=Receive PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=1
-
-[1603sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1800]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1800sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1800sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x180
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1800sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1800sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1800sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1801]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1801sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1801sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x280
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1801sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1801sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1801sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1802]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1802sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1802sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x380
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1802sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1802sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1802sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1803]
-ParameterName=Transmit PDO Communication Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1803sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=5
-PDOMapping=0
-LowLimit=0x02
-HighLimit=0x05
-
-[1803sub1]
-ParameterName=COB-ID
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=$NODEID+0x80000480
-PDOMapping=0
-LowLimit=0x00000001
-HighLimit=0xFFFFFFFF
-
-[1803sub2]
-ParameterName=Transmission Type
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=255
-PDOMapping=0
-
-[1803sub3]
-ParameterName=Inhibit Time
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0x0000
-PDOMapping=0
-
-[1803sub5]
-ParameterName=Event Timer
-ObjectType=0x7
-DataType=0x0006
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1a00]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=2
-
-[1a00sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=1
-PDOMapping=0
-
-[1a00sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x60000108
-PDOMapping=0
-
-[1a01]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1a01sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=4
-PDOMapping=0
-
-[1a01sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010110
-PDOMapping=0
-
-[1a01sub2]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010210
-PDOMapping=0
-
-[1a01sub3]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010310
-PDOMapping=0
-
-[1a01sub4]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010410
-PDOMapping=0
-
-[1a02]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=5
-
-[1a02sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=4
-PDOMapping=0
-
-[1a02sub1]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010510
-PDOMapping=0
-
-[1a02sub2]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010610
-PDOMapping=0
-
-[1a02sub3]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010710
-PDOMapping=0
-
-[1a02sub4]
-ParameterName=PDO Mapping Entry
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0x64010810
-PDOMapping=0
-
-[1a03]
-ParameterName=Transmit PDO Mapping Parameter
-ObjectType=0x9
-SubNumber=1
-
-[1a03sub0]
-ParameterName=Number of Entries
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[1f50]
-ParameterName=Download Program Data
-ObjectType=0x8
-SubNumber=2
-
-[1f50sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=3
-PDOMapping=0
-
-[1f50sub3]
-ParameterName=Download Program Data - HW Settings
-ObjectType=0x7
-DataType=0x000F
-AccessType=rw
-PDOMapping=0
-
-[6000]
-ParameterName=Read Digital Input 8-bit
-ObjectType=0x8
-SubNumber=2
-
-[6000sub0]
-ParameterName=Number of Elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6000sub1]
-ParameterName=DigInput8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-PDOMapping=1
-
-[6002]
-ParameterName=Polarity Digital Input
-ObjectType=0x8
-SubNumber=2
-
-[6002sub0]
-ParameterName=Number of Elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6002sub1]
-ParameterName=Polarity8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6200]
-ParameterName=Write Digital Output 8-bit
-ObjectType=0x8
-SubNumber=2
-
-[6200sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6200sub1]
-ParameterName=DigOutput8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rww
-PDOMapping=1
-
-[6202]
-ParameterName=Polarity Digital Output
-ObjectType=0x8
-SubNumber=2
-
-[6202sub0]
-ParameterName=Number of Elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6202sub1]
-ParameterName=Polarity8_1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6206]
-ParameterName=Error Mode Digital Output
-ObjectType=0x8
-SubNumber=2
-
-[6206sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6206sub1]
-ParameterName=Error Mode 1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6207]
-ParameterName=Error Value Digital Output
-ObjectType=0x8
-SubNumber=2
-
-[6207sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=1
-PDOMapping=0
-
-[6207sub1]
-ParameterName=Error Value 1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6401]
-ParameterName=Read Analog Input 16-bit
-ObjectType=0x8
-SubNumber=9
-
-[6401sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=8
-PDOMapping=0
-
-[6401sub1]
-ParameterName=AnalogInput16_1
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub2]
-ParameterName=AnalogInput16_2
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub3]
-ParameterName=AnalogInput16_3
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub4]
-ParameterName=AnalogInput16_4
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub5]
-ParameterName=AnalogInput16_5
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub6]
-ParameterName=AnalogInput16_6
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub7]
-ParameterName=AnalogInput16_7
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6401sub8]
-ParameterName=AnalogInput16_8
-ObjectType=0x7
-DataType=0x0003
-AccessType=ro
-PDOMapping=1
-
-[6411]
-ParameterName=Write Analog Output 16-bit
-ObjectType=0x8
-SubNumber=5
-
-[6411sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=4
-PDOMapping=0
-
-[6411sub1]
-ParameterName=AnalogOutput16_1
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6411sub2]
-ParameterName=AnalogOutput16_2
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6411sub3]
-ParameterName=AnalogOutput16_3
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6411sub4]
-ParameterName=AnalogOutput16_4
-ObjectType=0x7
-DataType=0x0003
-AccessType=rww
-PDOMapping=1
-
-[6423]
-ParameterName=Analog Input Global Interrupt
-ObjectType=0x7
-DataType=0x0001
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426]
-ParameterName=Analog Input Interrupt Delta
-ObjectType=0x8
-SubNumber=9
-
-[6426sub0]
-ParameterName=NrOfObjects
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=8
-PDOMapping=0
-
-[6426sub1]
-ParameterName=Analog Input Delta 1
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub2]
-ParameterName=Analog Input Delta 2
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub3]
-ParameterName=Analog Input Delta 3
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub4]
-ParameterName=Analog Input Delta 4
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub5]
-ParameterName=Analog Input Delta 5
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub6]
-ParameterName=Analog Input Delta 6
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub7]
-ParameterName=Analog Input Delta 7
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6426sub8]
-ParameterName=Analog Input Delta 8
-ObjectType=0x7
-DataType=0x0007
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443]
-ParameterName=Error Mode Analog Output
-ObjectType=0x8
-SubNumber=5
-
-[6443sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=4
-PDOMapping=0
-
-[6443sub1]
-ParameterName=Error Mode 1
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443sub2]
-ParameterName=Error Mode 2
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443sub3]
-ParameterName=Error Mode 3
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6443sub4]
-ParameterName=Error Mode 4
-ObjectType=0x7
-DataType=0x0005
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444]
-ParameterName=Error Value Analog Output
-ObjectType=0x8
-SubNumber=5
-
-[6444sub0]
-ParameterName=Number of elements
-ObjectType=0x7
-DataType=0x0005
-AccessType=ro
-DefaultValue=4
-PDOMapping=0
-
-[6444sub1]
-ParameterName=Error Value 1
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444sub2]
-ParameterName=Error Value 2
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444sub3]
-ParameterName=Error Value 3
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[6444sub4]
-ParameterName=Error Value 4
-ObjectType=0x7
-DataType=0x0004
-AccessType=rw
-DefaultValue=0
-PDOMapping=0
-
-[ManufacturerObjects]
-SupportedObjects=0
--- a/plugins/canfestival/test_config/master.od	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
-<PyObject module="node" class="Node" id="148584620">
-<attr name="Profile" type="dict" id="148589396" >
-</attr>
-<attr name="Description" type="string" value="" />
-<attr name="Dictionary" type="dict" id="148592132" >
-  <entry>
-    <key type="numeric" value="4096" />
-    <val type="numeric" value="302" />
-  </entry>
-  <entry>
-    <key type="numeric" value="4097" />
-    <val type="numeric" value="0" />
-  </entry>
-  <entry>
-    <key type="numeric" value="6144" />
-    <val type="list" id="148585004" >
-      <item type="string" value="{True:&quot;$NODEID+0x%X80&quot;%(base+1),False:0x80000000}[base&lt;4]" />
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-    </val>
-  </entry>
-  <entry>
-    <key type="numeric" value="5120" />
-    <val type="list" id="148586060" >
-      <item type="numeric" value="448" />
-      <item type="numeric" value="1" />
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-    </val>
-  </entry>
-  <entry>
-    <key type="numeric" value="4101" />
-    <val type="numeric" value="1073741952" />
-  </entry>
-  <entry>
-    <key type="numeric" value="4102" />
-    <val type="numeric" value="50000" />
-  </entry>
-  <entry>
-    <key type="numeric" value="8192" />
-    <val type="numeric" value="0" />
-  </entry>
-  <entry>
-    <key type="numeric" value="6656" />
-    <val type="list" id="148585228" >
-      <item type="numeric" value="268501000" />
-    </val>
-  </entry>
-  <entry>
-    <key type="numeric" value="5632" />
-    <val type="list" id="148585036" >
-      <item type="numeric" value="536870920" />
-    </val>
-  </entry>
-  <entry>
-    <key type="numeric" value="4120" />
-    <val type="list" id="148585292" >
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-      <item type="numeric" value="0" />
-    </val>
-  </entry>
-  <entry>
-    <key type="numeric" value="4118" />
-    <val type="list" id="148585100" >
-      <item type="numeric" value="4195804" />
-    </val>
-  </entry>
-</attr>
-<attr name="SpecificMenu" type="list" id="148584044" >
-</attr>
-<attr name="ParamsDictionary" type="dict" id="148592268" >
-</attr>
-<attr name="UserMapping" type="dict" id="148592404" >
-  <entry>
-    <key type="numeric" value="8192" />
-    <val type="dict" id="148592540" >
-      <entry>
-        <key type="string" value="need" />
-        <val type="False" value="" />
-      </entry>
-      <entry>
-        <key type="string" value="values" />
-        <val type="list" id="148585868" >
-          <item type="dict" id="148592676" >
-            <entry>
-              <key type="string" value="access" />
-              <val type="string" value="rw" />
-            </entry>
-            <entry>
-              <key type="string" value="pdo" />
-              <val type="True" value="" />
-            </entry>
-            <entry>
-              <key type="string" value="type" />
-              <val type="numeric" value="5" />
-            </entry>
-            <entry>
-              <key type="string" value="name" />
-              <val type="string">Read Inputs</val>
-            </entry>
-          </item>
-        </val>
-      </entry>
-      <entry>
-        <key type="string" value="name" />
-        <val type="string">Read Inputs</val>
-      </entry>
-      <entry>
-        <key type="string" value="struct" />
-        <val type="numeric" value="1" />
-      </entry>
-    </val>
-  </entry>
-</attr>
-<attr name="DS302" type="dict" id="148592812" >
-  <entry>
-    <key type="numeric" value="7968" />
-    <val type="dict" id="148592948" >
-      <entry>
-        <key type="string" value="need" />
-        <val type="False" value="" />
-      </entry>
-      <entry>
-        <key type="string" value="values" />
-        <val type="list" id="148584684" >
-          <item type="dict" id="148593084" >
-            <entry>
-              <key type="string" value="access" />
-              <val type="string" value="ro" />
-            </entry>
-            <entry>
-              <key type="string" value="pdo" />
-              <val type="False" value="" />
-            </entry>
-            <entry>
-              <key type="string" value="type" />
-              <val type="numeric" value="5" />
-            </entry>
-            <entry>
-              <key type="string" value="name" />
-              <val type="string" value="Number of Entries" />
-            </entry>
-          </item>
-          <item type="dict" id="148593220" >
-            <entry>
-              <key type="string" value="access" />
-              <val type="string" value="rw" />
-            </entry>
-            <entry>
-              <key type="string" value="pdo" />
-              <val type="False" value="" />
-            </entry>
-            <entry>
-              <key type="string" value="type" />
-              <val type="numeric" value="15" />
-            </entry>
-            <entry>
-              <key type="string" value="name" />
-              <val type="string" value="Store DCF for node %d[(sub)]" />
-            </entry>
-            <entry>
-              <key type="string" value="nbmax" />
-              <val type="numeric" value="127" />
-            </entry>
-          </item>
-        </val>
-      </entry>
-      <entry>
-        <key type="string" value="name" />
-        <val type="string" value="Store DCF" />
-      </entry>
-      <entry>
-        <key type="string" value="struct" />
-        <val type="numeric" value="7" />
-      </entry>
-    </val>
-  </entry>
-  <entry>
-    <key type="numeric" value="7969" />
-    <val type="dict" id="148593356" >
-      <entry>
-        <key type="string" value="need" />
-        <val type="False" value="" />
-      </entry>
-      <entry>
-        <key type="string" value="values" />
-        <val type="list" id="148585516" >
-          <item type="dict" id="148593492" >
-            <entry>
-              <key type="string" value="access" />
-              <val type="string" value="ro" />
-            </entry>
-            <entry>
-              <key type="string" value="pdo" />
-              <val type="False" value="" />
-            </entry>
-            <entry>
-              <key type="string" value="type" />
-              <val type="numeric" value="5" />
-            </entry>
-            <entry>
-              <key type="string" value="name" />
-              <val type="string" value="Number of Entries" />
-            </entry>
-          </item>
-          <item type="dict" id="148593628" >
-            <entry>
-              <key type="string" value="access" />
-              <val type="string" value="rw" />
-            </entry>
-            <entry>
-              <key type="string" value="pdo" />
-              <val type="False" value="" />
-            </entry>
-            <entry>
-              <key type="string" value="type" />
-              <val type="numeric" value="2" />
-            </entry>
-            <entry>
-              <key type="string" value="name" />
-              <val type="string" value="Storage Format for Node %d[(sub)]" />
-            </entry>
-            <entry>
-              <key type="string" value="nbmax" />
-              <val type="numeric" value="127" />
-            </entry>
-          </item>
-        </val>
-      </entry>
-      <entry>
-        <key type="string" value="name" />
-        <val type="string" value="Storage Format" />
-      </entry>
-      <entry>
-        <key type="string" value="struct" />
-        <val type="numeric" value="7" />
-      </entry>
-    </val>
-  </entry>
-  <entry>
-    <key type="numeric" value="7970" />
-    <val type="dict" id="148593764" >
-      <entry>
-        <key type="string" value="need" />
-        <val type="False" value="" />
-      </entry>
-      <entry>
-        <key type="string" value="values" />
-        <val type="list" id="148594956" >
-          <item type="dict" id="148593900" >
-            <entry>
-              <key type="string" value="access" />
-              <val type="string" value="ro" />
-            </entry>
-            <entry>
-              <key type="string" value="pdo" />
-              <val type="False" value="" />
-            </entry>
-            <entry>
-              <key type="string" value="type" />
-              <val type="numeric" value="5" />
-            </entry>
-            <entry>
-              <key type="string" value="name" />
-              <val type="string" value="Number of Entries" />
-            </entry>
-          </item>
-          <item type="dict" id="148594036" >
-            <entry>
-              <key type="string" value="access" />
-              <val type="string" value="rw" />
-            </entry>
-            <entry>
-              <key type="string" value="pdo" />
-              <val type="False" value="" />
-            </entry>
-            <entry>
-              <key type="string" value="type" />
-              <val type="numeric" value="15" />
-            </entry>
-            <entry>
-              <key type="string" value="name" />
-              <val type="string" value="Concise DCF for Node %d[(sub)]" />
-            </entry>
-            <entry>
-              <key type="string" value="nbmax" />
-              <val type="numeric" value="127" />
-            </entry>
-          </item>
-        </val>
-      </entry>
-      <entry>
-        <key type="string" value="name" />
-        <val type="string" value="Concise DCF" />
-      </entry>
-      <entry>
-        <key type="string" value="struct" />
-        <val type="numeric" value="7" />
-      </entry>
-    </val>
-  </entry>
-</attr>
-<attr name="ProfileName" type="string" value="None" />
-<attr name="Type" type="string">master</attr>
-<attr name="ID" type="numeric" value="0" />
-<attr name="Name" type="string">TestMaster</attr>
-</PyObject>
--- a/plugins/canfestival/test_config/nodelist.cpj	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-[TOPOLOGY]
-NetName=None
-Nodes=0x01
-Node64Present=0x01
-Node64Name=micromod
-Node64DCFName=PEAK MicroMod.eds
-EDSBaseName=eds
--- a/plugins/canfestival/test_config/result.txt	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-1000 (Device Type): 12E
-1001 (Error Register): 0
-1005 (SYNC COB ID): 40000080
-1006 (Communication / Cycle Period): C350
-1016 (Consumer Heartbeat Time):
-1016 01 (Consumer Heartbeat Time): 4005DC
-1018 (Identity):
-1018 01 (Vendor ID): 0
-1018 02 (Product Code): 0
-1018 03 (Revision Number): 0
-1018 04 (Serial Number): 0
-1280 (Client SDO 1 Parameter):
-1280 01 (COB ID Client to Server (Transmit SDO)): 640
-1280 02 (COB ID Server to Client (Receive SDO)): 5C0
-1280 03 (Node ID of the SDO Server): 40
-1400 (Receive PDO 1 Parameter):
-1400 01 (COB ID used by PDO): 1C0
-1400 02 (Transmission Type): 1
-1400 03 (Inhibit Time): 0
-1400 04 (Compatibility Entry): 0
-1400 05 (Event Timer): 0
-1401 (Receive PDO 2 Parameter):
-1401 01 (COB ID used by PDO): 2C0
-1401 02 (Transmission Type): 1
-1401 03 (Inhibit Time): 0
-1401 04 (Compatibility Entry): 0
-1401 05 (Event Timer): 0
-1402 (Receive PDO 3 Parameter):
-1402 01 (COB ID used by PDO): 182
-1402 02 (Transmission Type): 1
-1402 03 (Inhibit Time): 0
-1402 04 (Compatibility Entry): 0
-1402 05 (Event Timer): 0
-1403 (Receive PDO 4 Parameter):
-1403 01 (COB ID used by PDO): 183
-1403 02 (Transmission Type): 1
-1403 03 (Inhibit Time): 0
-1403 04 (Compatibility Entry): 0
-1403 05 (Event Timer): 0
-1404 (Receive PDO 5 Parameter):
-1404 01 (COB ID used by PDO): 181
-1404 02 (Transmission Type): 1
-1404 03 (Inhibit Time): 0
-1404 04 (Compatibility Entry): 0
-1404 05 (Event Timer): 0
-1600 (Receive PDO 1 Mapping):
-1600 01 (PDO 1 Mapping for an application object 1): 22400108
-1600 02 (PDO 1 Mapping for an application object 2): 0
-1601 (Receive PDO 2 Mapping):
-1601 01 (PDO 2 Mapping for an application object 1): 20000310
-1601 02 (PDO 2 Mapping for an application object 2): 23400110
-1601 03 (PDO 2 Mapping for an application object 3): 23400210
-1601 04 (PDO 2 Mapping for an application object 4): 20000310
-1602 (Receive PDO 3 Mapping):
-1602 01 (PDO 3 Mapping for an application object 1): 24400120
-1602 02 (PDO 3 Mapping for an application object 2): 24400220
-1603 (Receive PDO 4 Mapping):
-1603 01 (PDO 4 Mapping for an application object 1): 24400320
-1604 (Receive PDO 5 Mapping):
-1604 01 (PDO 5 Mapping for an application object 1): 22400208
-1604 02 (PDO 5 Mapping for an application object 2): 24400420
-1800 (Transmit PDO 1 Parameter):
-1800 01 (COB ID used by PDO): {True:"$NODEID+0x%X80"%(base+1),False:0x80000000}[base<4]
-1800 02 (Transmission Type): 0
-1800 03 (Inhibit Time): 0
-1800 04 (Compatibility Entry): 0
-1800 05 (Event Timer): 0
-1801 (Transmit PDO 2 Parameter):
-1801 01 (COB ID used by PDO): 340
-1801 02 (Transmission Type): 1
-1801 03 (Inhibit Time): 0
-1801 04 (Compatibility Entry): 0
-1801 05 (Event Timer): 0
-1A00 (Transmit PDO 1 Mapping):
-1A00 01 (PDO 1 Mapping for a process data variable 1): 10010008
-1A01 (Transmit PDO 2 Mapping):
-1A01 01 (PDO 2 Mapping for a process data variable 1): 43400110
-1A01 02 (PDO 2 Mapping for a process data variable 2): 20000310
-1A01 03 (PDO 2 Mapping for a process data variable 3): 20000310
-1A01 04 (PDO 2 Mapping for a process data variable 4): 20000310
-1F22 (Concise DCF):
-1F22 01 (Concise DCF for Node 1): 
-1F22 02 (Concise DCF for Node 2): 
-1F22 03 (Concise DCF for Node 3): 
-1F22 04 (Concise DCF for Node 4): 
-1F22 05 (Concise DCF for Node 5): 
-1F22 06 (Concise DCF for Node 6): 
-1F22 07 (Concise DCF for Node 7): 
-1F22 08 (Concise DCF for Node 8): 
-1F22 09 (Concise DCF for Node 9): 
-1F22 0A (Concise DCF for Node 10): 
-1F22 0B (Concise DCF for Node 11): 
-1F22 0C (Concise DCF for Node 12): 
-1F22 0D (Concise DCF for Node 13): 
-1F22 0E (Concise DCF for Node 14): 
-1F22 0F (Concise DCF for Node 15): 
-1F22 10 (Concise DCF for Node 16): 
-1F22 11 (Concise DCF for Node 17): 
-1F22 12 (Concise DCF for Node 18): 
-1F22 13 (Concise DCF for Node 19): 
-1F22 14 (Concise DCF for Node 20): 
-1F22 15 (Concise DCF for Node 21): 
-1F22 16 (Concise DCF for Node 22): 
-1F22 17 (Concise DCF for Node 23): 
-1F22 18 (Concise DCF for Node 24): 
-1F22 19 (Concise DCF for Node 25): 
-1F22 1A (Concise DCF for Node 26): 
-1F22 1B (Concise DCF for Node 27): 
-1F22 1C (Concise DCF for Node 28): 
-1F22 1D (Concise DCF for Node 29): 
-1F22 1E (Concise DCF for Node 30): 
-1F22 1F (Concise DCF for Node 31): 
-1F22 20 (Concise DCF for Node 32): 
-1F22 21 (Concise DCF for Node 33): 
-1F22 22 (Concise DCF for Node 34): 
-1F22 23 (Concise DCF for Node 35): 
-1F22 24 (Concise DCF for Node 36): 
-1F22 25 (Concise DCF for Node 37): 
-1F22 26 (Concise DCF for Node 38): 
-1F22 27 (Concise DCF for Node 39): 
-1F22 28 (Concise DCF for Node 40): 
-1F22 29 (Concise DCF for Node 41): 
-1F22 2A (Concise DCF for Node 42): 
-1F22 2B (Concise DCF for Node 43): 
-1F22 2C (Concise DCF for Node 44): 
-1F22 2D (Concise DCF for Node 45): 
-1F22 2E (Concise DCF for Node 46): 
-1F22 2F (Concise DCF for Node 47): 
-1F22 30 (Concise DCF for Node 48): 
-1F22 31 (Concise DCF for Node 49): 
-1F22 32 (Concise DCF for Node 50): 
-1F22 33 (Concise DCF for Node 51): 
-1F22 34 (Concise DCF for Node 52): 
-1F22 35 (Concise DCF for Node 53): 
-1F22 36 (Concise DCF for Node 54): 
-1F22 37 (Concise DCF for Node 55): 
-1F22 38 (Concise DCF for Node 56): 
-1F22 39 (Concise DCF for Node 57): 
-1F22 3A (Concise DCF for Node 58): 
-1F22 3B (Concise DCF for Node 59): 
-1F22 3C (Concise DCF for Node 60): 
-1F22 3D (Concise DCF for Node 61): 
-1F22 3E (Concise DCF for Node 62): 
-1F22 3F (Concise DCF for Node 63): 
-1F22 40 (Concise DCF for Node 64): 23 arg defined
-1F22 40, arg 1: 1800 01 00000004 800001C0
-1F22 40, arg 2: 1800 02 00000001 01
-1F22 40, arg 3: 1800 01 00000004 000001C0
-1F22 40, arg 4: 1801 01 00000004 800002C0
-1F22 40, arg 5: 1801 02 00000001 01
-1F22 40, arg 6: 1801 01 00000004 000002C0
-1F22 40, arg 7: 1401 01 00000004 80000340
-1F22 40, arg 8: 1401 02 00000001 01
-1F22 40, arg 9: 1401 01 00000004 00000340
-1F22 40, arg 10: 1804 01 00000004 80000181
-1F22 40, arg 11: 1804 02 00000001 01
-1F22 40, arg 12: 1804 01 00000004 00000181
-1F22 40, arg 13: 1A04 01 00000004 60020108
-1F22 40, arg 14: 1A04 02 00000004 64260120
-1F22 40, arg 15: 1805 01 00000004 80000182
-1F22 40, arg 16: 1805 02 00000001 01
-1F22 40, arg 17: 1805 01 00000004 00000182
-1F22 40, arg 18: 1A05 01 00000004 64260220
-1F22 40, arg 19: 1A05 02 00000004 64260320
-1F22 40, arg 20: 1806 01 00000004 80000183
-1F22 40, arg 21: 1806 02 00000001 01
-1F22 40, arg 22: 1806 01 00000004 00000183
-1F22 40, arg 23: 1A06 01 00000004 64260420
-1F22 41 (Concise DCF for Node 65): 
-1F22 42 (Concise DCF for Node 66): 
-1F22 43 (Concise DCF for Node 67): 
-1F22 44 (Concise DCF for Node 68): 
-1F22 45 (Concise DCF for Node 69): 
-1F22 46 (Concise DCF for Node 70): 
-1F22 47 (Concise DCF for Node 71): 
-1F22 48 (Concise DCF for Node 72): 
-1F22 49 (Concise DCF for Node 73): 
-1F22 4A (Concise DCF for Node 74): 
-1F22 4B (Concise DCF for Node 75): 
-1F22 4C (Concise DCF for Node 76): 
-1F22 4D (Concise DCF for Node 77): 
-1F22 4E (Concise DCF for Node 78): 
-1F22 4F (Concise DCF for Node 79): 
-1F22 50 (Concise DCF for Node 80): 
-1F22 51 (Concise DCF for Node 81): 
-1F22 52 (Concise DCF for Node 82): 
-1F22 53 (Concise DCF for Node 83): 
-1F22 54 (Concise DCF for Node 84): 
-1F22 55 (Concise DCF for Node 85): 
-1F22 56 (Concise DCF for Node 86): 
-1F22 57 (Concise DCF for Node 87): 
-1F22 58 (Concise DCF for Node 88): 
-1F22 59 (Concise DCF for Node 89): 
-1F22 5A (Concise DCF for Node 90): 
-1F22 5B (Concise DCF for Node 91): 
-1F22 5C (Concise DCF for Node 92): 
-1F22 5D (Concise DCF for Node 93): 
-1F22 5E (Concise DCF for Node 94): 
-1F22 5F (Concise DCF for Node 95): 
-1F22 60 (Concise DCF for Node 96): 
-1F22 61 (Concise DCF for Node 97): 
-1F22 62 (Concise DCF for Node 98): 
-1F22 63 (Concise DCF for Node 99): 
-1F22 64 (Concise DCF for Node 100): 
-1F22 65 (Concise DCF for Node 101): 
-1F22 66 (Concise DCF for Node 102): 
-1F22 67 (Concise DCF for Node 103): 
-1F22 68 (Concise DCF for Node 104): 
-1F22 69 (Concise DCF for Node 105): 
-1F22 6A (Concise DCF for Node 106): 
-1F22 6B (Concise DCF for Node 107): 
-1F22 6C (Concise DCF for Node 108): 
-1F22 6D (Concise DCF for Node 109): 
-1F22 6E (Concise DCF for Node 110): 
-1F22 6F (Concise DCF for Node 111): 
-1F22 70 (Concise DCF for Node 112): 
-1F22 71 (Concise DCF for Node 113): 
-1F22 72 (Concise DCF for Node 114): 
-1F22 73 (Concise DCF for Node 115): 
-1F22 74 (Concise DCF for Node 116): 
-1F22 75 (Concise DCF for Node 117): 
-1F22 76 (Concise DCF for Node 118): 
-1F22 77 (Concise DCF for Node 119): 
-1F22 78 (Concise DCF for Node 120): 
-1F22 79 (Concise DCF for Node 121): 
-1F22 7A (Concise DCF for Node 122): 
-1F22 7B (Concise DCF for Node 123): 
-1F22 7C (Concise DCF for Node 124): 
-1F22 7D (Concise DCF for Node 125): 
-1F22 7E (Concise DCF for Node 126): 
-1F22 7F (Concise DCF for Node 127): 
-2000 (Read Inputs): 0
-2240 (beremiz__IB0_1_64):
-2240 01 (24576_1): 0
-2240 02 (24578_1): 0
-2340 (beremiz__IW0_1_64):
-2340 01 (25601_2): 0
-2340 02 (25601_3): 0
-2440 (beremiz__ID0_1_64):
-2440 01 (25638_2): 0
-2440 02 (25638_3): 0
-2440 03 (25638_4): 0
-2440 04 (25638_1): 0
-4340 (beremiz__QW0_1_64):
-4340 01 (25617_1): 0
-
-********POINTERS*********
-{(4096, 0): '__ID0_1_4096_0',
- (8768, 1): '__IB0_1_64_24576_1',
- (8768, 2): '__IB0_1_64_24578_1',
- (9024, 1): '__IW0_1_64_25601_2',
- (9024, 2): '__IW0_1_64_25601_3',
- (9280, 1): '__ID0_1_64_25638_2',
- (9280, 2): '__ID0_1_64_25638_3',
- (9280, 3): '__ID0_1_64_25638_4',
- (9280, 4): '__ID0_1_64_25638_1',
- (17216, 1): '__QW0_1_64_25617_1'}
--- a/plugins/python/PythonEditor.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,505 +0,0 @@
-import  wx, wx.grid
-import  wx.stc  as  stc
-import keyword
-
-from controls import EditorPanel
-
-if wx.Platform == '__WXMSW__':
-    faces = { 'times': 'Times New Roman',
-              'mono' : 'Courier New',
-              'helv' : 'Arial',
-              'other': 'Comic Sans MS',
-              'size' : 10,
-              'size2': 8,
-             }
-elif wx.Platform == '__WXMAC__':
-    faces = { 'times': 'Times New Roman',
-              'mono' : 'Monaco',
-              'helv' : 'Arial',
-              'other': 'Comic Sans MS',
-              'size' : 12,
-              'size2': 10,
-             }
-else:
-    faces = { 'times': 'Times',
-              'mono' : 'Courier',
-              'helv' : 'Helvetica',
-              'other': 'new century schoolbook',
-              'size' : 12,
-              'size2': 10,
-             }
-
-[ID_PYTHONEDITOR,
-] = [wx.NewId() for _init_ctrls in range(1)]
-
-def GetCursorPos(old, new):
-    old_length = len(old)
-    new_length = len(new)
-    common_length = min(old_length, new_length)
-    i = 0
-    for i in xrange(common_length):
-        if old[i] != new[i]:
-            break
-    if old_length < new_length:
-        if common_length > 0 and old[i] != new[i]:
-            return i + new_length - old_length
-        else:
-            return i + new_length - old_length + 1
-    elif old_length > new_length or i < min(old_length, new_length) - 1:
-        if common_length > 0 and old[i] != new[i]:
-            return i
-        else:
-            return i + 1
-    else:
-        return None
-
-class PythonEditor(EditorPanel):
-
-    fold_symbols = 3
-    
-    def _init_Editor(self, prnt):
-        self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
-                 name="TextViewer", pos=wx.DefaultPosition, 
-                 size=wx.DefaultSize, style=0)
-
-        self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
-        self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
-
-        self.Editor.SetLexer(stc.STC_LEX_PYTHON)
-        self.Editor.SetKeyWords(0, " ".join(keyword.kwlist))
-
-        self.Editor.SetProperty("fold", "1")
-        self.Editor.SetProperty("tab.timmy.whinge.level", "1")
-        self.Editor.SetMargins(0,0)
-
-        self.Editor.SetViewWhiteSpace(False)
-        
-        self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
-        self.Editor.SetEdgeColumn(78)
-
-        # Set up the numbers in the margin for margin #1
-        self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
-        # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
-        self.Editor.SetMarginWidth(1, 40)
-
-        # Setup a margin to hold fold markers
-        self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
-        self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS)
-        self.Editor.SetMarginSensitive(2, True)
-        self.Editor.SetMarginWidth(2, 12)
-
-        if self.fold_symbols == 0:
-            # Arrow pointing right for contracted folders, arrow pointing down for expanded
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_ARROWDOWN, "black", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_ARROW, "black", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "black", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "black", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY,     "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY,     "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY,     "white", "black")
-            
-        elif self.fold_symbols == 1:
-            # Plus for contracted folders, minus for expanded
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_MINUS, "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_PLUS,  "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_EMPTY, "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_EMPTY, "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_EMPTY, "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black")
-
-        elif self.fold_symbols == 2:
-            # Like a flattened tree control using circular headers and curved joins
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_CIRCLEMINUS,          "white", "#404040")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_CIRCLEPLUS,           "white", "#404040")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,                "white", "#404040")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNERCURVE,         "white", "#404040")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_CIRCLEPLUSCONNECTED,  "white", "#404040")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE,         "white", "#404040")
-
-        elif self.fold_symbols == 3:
-            # Like a flattened tree control using square headers
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
-            self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
-
-
-        self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
-        self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
-        self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
-
-        # Global default style
-        if wx.Platform == '__WXMSW__':
-            self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New')
-        elif wx.Platform == '__WXMAC__':
-            # TODO: if this looks fine on Linux too, remove the Mac-specific case 
-            # and use this whenever OS != MSW.
-            self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco')
-        else:
-            defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize()
-            self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize)
-
-        # Clear styles and revert to default.
-        self.Editor.StyleClearAll()
-
-        # Following style specs only indicate differences from default.
-        # The rest remains unchanged.
-
-        # Line numbers in margin
-        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')    
-        # Highlighted brace
-        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
-        # Unmatched brace
-        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
-        # Indentation guide
-        self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
-
-        # Python styles
-        self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
-        # Comments
-        self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE,  'fore:#008000,back:#F0FFF0')
-        self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
-        # Numbers
-        self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
-        # Strings and characters
-        self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
-        self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
-        # Keywords
-        self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
-        # Triple quotes
-        self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
-        self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
-        # Class names
-        self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
-        # Function names
-        self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
-        # Operators
-        self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
-        # Identifiers. I leave this as not bold because everything seems
-        # to be an identifier if it doesn't match the above criterae
-        self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
-
-        # Caret color
-        self.Editor.SetCaretForeground("BLUE")
-        # Selection background
-        self.Editor.SetSelBackground(1, '#66CCFF')
-
-        self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
-        self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
-        
-        # register some images for use in the AutoComplete box.
-        #self.RegisterImage(1, images.getSmilesBitmap())
-        self.Editor.RegisterImage(1, 
-            wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16)))
-        self.Editor.RegisterImage(2, 
-            wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
-        self.Editor.RegisterImage(3, 
-            wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
-
-        # Indentation and tab stuff
-        self.Editor.SetIndent(4)               # Proscribed indent size for wx
-        self.Editor.SetIndentationGuides(True) # Show indent guides
-        self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
-        self.Editor.SetTabIndents(True)        # Tab key indents
-        self.Editor.SetTabWidth(4)             # Proscribed tab size for wx
-        self.Editor.SetUseTabs(False)          # Use spaces rather than tabs, or
-                                        # TabTimmy will complain!    
-        # White space
-        self.Editor.SetViewWhiteSpace(False)   # Don't view white space
-
-        # EOL: Since we are loading/saving ourselves, and the
-        # strings will always have \n's in them, set the STC to
-        # edit them that way.            
-        self.Editor.SetEOLMode(wx.stc.STC_EOL_LF)
-        self.Editor.SetViewEOL(False)
-        
-        # No right-edge mode indicator
-        self.Editor.SetEdgeMode(stc.STC_EDGE_NONE)
-        
-        self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE)
-
-        self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR)
-        self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
-        self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR)
-
-
-    def __init__(self, parent, controler, window):
-        EditorPanel.__init__(self, parent, "", window, controler)
-        
-        self.DisableEvents = False
-        self.CurrentAction = None
-        
-        img = wx.Bitmap(self.Controler.GetIconPath("Cfile.png"), wx.BITMAP_TYPE_PNG).ConvertToImage()
-        self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16)))
-    
-    def __del__(self):
-        self.Controler.OnCloseEditor(self)
-    
-    def GetTitle(self):
-        fullname = self.Controler.PlugFullName()
-        if not self.Controler.PythonIsSaved():
-            return "~%s~" % fullname
-        return fullname
-    
-    def GetBufferState(self):
-        return self.Controler.GetBufferState()
-        
-    def Undo(self):
-        self.Controler.LoadPrevious()
-        self.RefreshView()
-            
-    def Redo(self):
-        self.Controler.LoadNext()
-        self.RefreshView()
-    
-    def HasNoModel(self):
-        return False
-    
-    def OnModification(self, event):
-        if not self.DisableEvents:
-            mod_type = event.GetModificationType()
-            if not (mod_type&wx.stc.STC_PERFORMED_UNDO or mod_type&wx.stc.STC_PERFORMED_REDO):
-                if mod_type&wx.stc.STC_MOD_BEFOREINSERT:
-                    if self.CurrentAction is None:
-                        self.StartBuffering()
-                    elif self.CurrentAction[0] != "Add" or self.CurrentAction[1] != event.GetPosition() - 1:
-                        self.Controler.EndBuffering()
-                        self.StartBuffering()
-                    self.CurrentAction = ("Add", event.GetPosition())
-                    wx.CallAfter(self.RefreshModel)
-                elif mod_type&wx.stc.STC_MOD_BEFOREDELETE:
-                    if self.CurrentAction == None:
-                        self.StartBuffering()
-                    elif self.CurrentAction[0] != "Delete" or self.CurrentAction[1] != event.GetPosition() + 1:
-                        self.Controler.EndBuffering()
-                        self.StartBuffering()
-                    self.CurrentAction = ("Delete", event.GetPosition())
-                    wx.CallAfter(self.RefreshModel)
-        event.Skip()
-    
-    def OnDoDrop(self, event):
-        self.ResetBuffer()
-        wx.CallAfter(self.RefreshModel)
-        event.Skip()
-
-    # Buffer the last model state
-    def RefreshBuffer(self):
-        self.Controler.BufferPython()
-        if self.ParentWindow is not None:
-            self.ParentWindow.RefreshTitle()
-            self.ParentWindow.RefreshFileMenu()
-            self.ParentWindow.RefreshEditMenu()
-            self.ParentWindow.RefreshPageTitles()
-    
-    def StartBuffering(self):
-        self.Controler.StartBuffering()
-        if self.ParentWindow is not None:
-            self.ParentWindow.RefreshTitle()
-            self.ParentWindow.RefreshFileMenu()
-            self.ParentWindow.RefreshEditMenu()
-            self.ParentWindow.RefreshPageTitles()
-    
-    def ResetBuffer(self):
-        if self.CurrentAction != None:
-            self.Controler.EndBuffering()
-            self.CurrentAction = None
-
-    def RefreshView(self):
-        self.ResetBuffer()
-        self.DisableEvents = True
-        old_cursor_pos = self.Editor.GetCurrentPos()
-        old_text = self.Editor.GetText()
-        new_text = self.Controler.GetPythonCode()
-        self.Editor.SetText(new_text)
-        new_cursor_pos = GetCursorPos(old_text, new_text)
-        if new_cursor_pos != None:
-            self.Editor.GotoPos(new_cursor_pos)
-        else:
-            self.Editor.GotoPos(old_cursor_pos)
-        self.Editor.ScrollToColumn(0)
-        self.Editor.EmptyUndoBuffer()
-        self.DisableEvents = False
-        
-        self.Editor.Colourise(0, -1)
-
-    def RefreshModel(self):
-        self.Controler.SetPythonCode(self.Editor.GetText())
-
-    def OnKeyPressed(self, event):
-        if self.Editor.CallTipActive():
-            self.Editor.CallTipCancel()
-        key = event.GetKeyCode()
-
-        if key == 32 and event.ControlDown():
-            pos = self.Editor.GetCurrentPos()
-
-            # Tips
-            if event.ShiftDown():
-                pass
-##                self.CallTipSetBackground("yellow")
-##                self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
-##                                 'show some suff, maybe parameters..\n\n'
-##                                 'fubar(param1, param2)')
-            # Code completion
-            else:
-                self.Editor.AutoCompSetIgnoreCase(False)  # so this needs to match
-
-                # Images are specified with a appended "?type"
-                self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist]))
-        else:
-            event.Skip()
-
-    def OnKillFocus(self, event):
-        self.Editor.AutoCompCancel()
-        event.Skip()
-
-    def OnUpdateUI(self, evt):
-        # check for matching braces
-        braceAtCaret = -1
-        braceOpposite = -1
-        charBefore = None
-        caretPos = self.Editor.GetCurrentPos()
-
-        if caretPos > 0:
-            charBefore = self.Editor.GetCharAt(caretPos - 1)
-            styleBefore = self.Editor.GetStyleAt(caretPos - 1)
-
-        # check before
-        if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
-            braceAtCaret = caretPos - 1
-
-        # check after
-        if braceAtCaret < 0:
-            charAfter = self.Editor.GetCharAt(caretPos)
-            styleAfter = self.Editor.GetStyleAt(caretPos)
-
-            if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
-                braceAtCaret = caretPos
-
-        if braceAtCaret >= 0:
-            braceOpposite = self.Editor.BraceMatch(braceAtCaret)
-
-        if braceAtCaret != -1  and braceOpposite == -1:
-            self.Editor.BraceBadLight(braceAtCaret)
-        else:
-            self.Editor.BraceHighlight(braceAtCaret, braceOpposite)
-            #pt = self.Editor.PointFromPosition(braceOpposite)
-            #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5))
-            #print pt
-            #self.Editor.Refresh(False)
-
-
-    def OnMarginClick(self, evt):
-        # fold and unfold as needed
-        if evt.GetMargin() == 2:
-            if evt.GetShift() and evt.GetControl():
-                self.FoldAll()
-            else:
-                lineClicked = self.Editor.LineFromPosition(evt.GetPosition())
-
-                if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
-                    if evt.GetShift():
-                        self.Editor.SetFoldExpanded(lineClicked, True)
-                        self.Expand(lineClicked, True, True, 1)
-                    elif evt.GetControl():
-                        if self.Editor.GetFoldExpanded(lineClicked):
-                            self.Editor.SetFoldExpanded(lineClicked, False)
-                            self.Expand(lineClicked, False, True, 0)
-                        else:
-                            self.Editor.SetFoldExpanded(lineClicked, True)
-                            self.Expand(lineClicked, True, True, 100)
-                    else:
-                        self.Editor.ToggleFold(lineClicked)
-
-
-    def FoldAll(self):
-        lineCount = self.Editor.GetLineCount()
-        expanding = True
-
-        # find out if we are folding or unfolding
-        for lineNum in range(lineCount):
-            if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
-                expanding = not self.Editor.GetFoldExpanded(lineNum)
-                break
-
-        lineNum = 0
-
-        while lineNum < lineCount:
-            level = self.Editor.GetFoldLevel(lineNum)
-            if level & stc.STC_FOLDLEVELHEADERFLAG and \
-               (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
-
-                if expanding:
-                    self.Editor.SetFoldExpanded(lineNum, True)
-                    lineNum = self.Expand(lineNum, True)
-                    lineNum = lineNum - 1
-                else:
-                    lastChild = self.Editor.GetLastChild(lineNum, -1)
-                    self.Editor.SetFoldExpanded(lineNum, False)
-
-                    if lastChild > lineNum:
-                        self.Editor.HideLines(lineNum+1, lastChild)
-
-            lineNum = lineNum + 1
-
-
-
-    def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
-        lastChild = self.Editor.GetLastChild(line, level)
-        line = line + 1
-
-        while line <= lastChild:
-            if force:
-                if visLevels > 0:
-                    self.Editor.ShowLines(line, line)
-                else:
-                    self.Editor.HideLines(line, line)
-            else:
-                if doExpand:
-                    self.Editor.ShowLines(line, line)
-
-            if level == -1:
-                level = self.Editor.GetFoldLevel(line)
-
-            if level & stc.STC_FOLDLEVELHEADERFLAG:
-                if force:
-                    if visLevels > 1:
-                        self.Editor.SetFoldExpanded(line, True)
-                    else:
-                        self.Editor.SetFoldExpanded(line, False)
-
-                    line = self.Expand(line, doExpand, force, visLevels-1)
-
-                else:
-                    if doExpand and self.Editor.GetFoldExpanded(line):
-                        line = self.Expand(line, True, force, visLevels-1)
-                    else:
-                        line = self.Expand(line, False, force, visLevels-1)
-            else:
-                line = line + 1
-
-        return line
-
-    def Cut(self):
-        self.ResetBuffer()
-        self.DisableEvents = True
-        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT)
-        self.DisableEvents = False
-        self.RefreshModel()
-        self.RefreshBuffer()
-    
-    def Copy(self):
-        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY)
-    
-    def Paste(self):
-        self.ResetBuffer()
-        self.DisableEvents = True
-        self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE)
-        self.DisableEvents = False
-        self.RefreshModel()
-        self.RefreshBuffer()
--- a/plugins/python/README	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Asynchronous Python Interpreter
--- a/plugins/python/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from python import *
--- a/plugins/python/modules/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-from os import listdir, path
-
-_base_path = path.split(__file__)[0]
-
-__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")]
-
-helps = []
-for name in __all__:
-    helpfilename = path.join(_base_path, name, "README")
-    if path.isfile(helpfilename):
-        helps.append(open(helpfilename).readline().strip())
-    else:
-        helps.append(name)
--- a/plugins/python/modules/svgui/README	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-SVGUI HMI
\ No newline at end of file
--- a/plugins/python/modules/svgui/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from svgui import *
--- a/plugins/python/modules/svgui/livesvg.js	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-// import Nevow.Athena
-// import Divmod.Base
-
-function updateAttr(id, param, value) {
-  Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value);
-}
-
-var svguiWidgets = new Array();
-
-var currentObject = null;
-function setCurrentObject(obj) {
-	currentObject = obj;
-}
-function isCurrentObject(obj) {
-	return currentObject == obj;
-}
-
-function getSVGElementById(id) {
-	return document.getElementById(id);
-}
-
-function blockSVGElementDrag(element) {
-	element.addEventListener("draggesture", function(event){event.stopPropagation()}, true);
-}
-
-LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget');
-LiveSVGPage.LiveSVGWidget.methods(
-
-    function handleEvent(self, evt) {
-        if (currentObject != null) {
-            currentObject.handleEvent(evt);
-        }
-    },
-
-    function receiveData(self, data){
-        dataReceived = json_parse(data);
-        gadget = svguiWidgets[dataReceived.id]
-        if (gadget) {
-        	gadget.updateValues(json_parse(dataReceived.kwargs));
-        }
-        //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState);
-    },
-    
-    function init(self, arg1){
-        //console.log("Object received : " + arg1);
-        for (ind in arg1) {
-            gad = json_parse(arg1[ind]);
-            args = json_parse(gad.kwargs);
-            gadget = new svguilib[gad.__class__](self, gad.id, args);
-            svguiWidgets[gadget.id]=gadget;
-            //console.log('GADGET :' + gadget);
-        }
-        var elements = document.getElementsByTagName("svg");
-        for (var i = 0; i < elements.length; i++) {
-        	elements[i].addEventListener("mouseup", self, false);
-        }
-        //console.log("SVGUIWIDGETS : " + svguiWidgets);
-    }
-);
--- a/plugins/python/modules/svgui/pous.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1428 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://www.plcopen.org/xml/tc6.xsd"
-         xmlns:xhtml="http://www.w3.org/1999/xhtml"
-         xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
-  <fileHeader companyName="Beremiz"
-              productName="Beremiz"
-              productVersion="0.0"
-              creationDateTime="2008-12-14T16:53:26"/>
-  <contentHeader name="Beremiz non-standard POUs library"
-                 modificationDateTime="2009-08-12T15:35:33">
-    <coordinateInfo>
-      <fbd>
-        <scaling x="0" y="0"/>
-      </fbd>
-      <ld>
-        <scaling x="0" y="0"/>
-      </ld>
-      <sfc>
-        <scaling x="0" y="0"/>
-      </sfc>
-    </coordinateInfo>
-  </contentHeader>
-  <types>
-    <dataTypes/>
-    <pous>
-      <pou name="GetBoolString" pouType="functionBlock">
-        <interface>
-          <inputVars>
-            <variable name="VALUE">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-          </inputVars>
-          <outputVars>
-            <variable name="CODE">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </outputVars>
-        </interface>
-        <body>
-          <ST>
-<![CDATA[IF VALUE THEN
-  CODE := 'True';
-ELSE
-  CODE := 'False';
-END_IF;]]>
-          </ST>
-        </body>
-      </pou>
-      <pou name="TextCtrl" pouType="functionBlock">
-        <interface>
-          <localVars>
-            <variable name="ID">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </localVars>
-          <inputVars>
-            <variable name="back_id">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="set_text">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="text">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </inputVars>
-          <localVars>
-            <variable name="SVGUI_TEXTCTRL">
-              <type>
-                <derived name="python_eval"/>
-              </type>
-            </variable>
-            <variable name="setstate_Command">
-              <type>
-                <derived name="python_eval"/>
-              </type>
-            </variable>
-          </localVars>
-        </interface>
-        <body>
-          <FBD>
-            <block localId="1" width="193" height="160" typeName="CONCAT">
-              <position x="626" y="122"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="43"/>
-                    <connection refLocalId="2">
-                      <position x="626" y="165"/>
-                      <position x="535" y="165"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="89"/>
-                    <connection refLocalId="3">
-                      <position x="626" y="211"/>
-                      <position x="535" y="211"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN3">
-                  <connectionPointIn>
-                    <relPosition x="0" y="135"/>
-                    <connection refLocalId="6">
-                      <position x="626" y="257"/>
-                      <position x="532" y="257"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="193" y="43"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="2" height="30" width="460">
-              <position x="75" y="150"/>
-              <connectionPointOut>
-                <relPosition x="460" y="15"/>
-              </connectionPointOut>
-              <expression>'createSVGUIControl("textControl", back_id="'</expression>
-            </inVariable>
-            <inVariable localId="3" height="35" width="85">
-              <position x="450" y="196"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>back_id</expression>
-            </inVariable>
-            <inVariable localId="6" height="30" width="50">
-              <position x="482" y="242"/>
-              <connectionPointOut>
-                <relPosition x="50" y="15"/>
-              </connectionPointOut>
-              <expression>'")'</expression>
-            </inVariable>
-            <block localId="7" width="125" height="115" typeName="python_eval" instanceName="SVGUI_TEXTCTRL">
-              <position x="909" y="75"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="45"/>
-                    <connection refLocalId="9">
-                      <position x="909" y="120"/>
-                      <position x="886" y="120"/>
-                      <position x="886" y="85"/>
-                      <position x="869" y="85"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="90"/>
-                    <connection refLocalId="1" formalParameter="OUT">
-                      <position x="909" y="165"/>
-                      <position x="819" y="165"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="45"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="90"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="9" height="30" width="70">
-              <position x="799" y="70"/>
-              <connectionPointOut>
-                <relPosition x="70" y="15"/>
-              </connectionPointOut>
-              <expression>BOOL#1</expression>
-            </inVariable>
-            <outVariable localId="10" height="30" width="30">
-              <position x="1094" y="150"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="7" formalParameter="RESULT">
-                  <position x="1094" y="165"/>
-                  <position x="1034" y="165"/>
-                </connection>
-              </connectionPointIn>
-              <expression>ID</expression>
-            </outVariable>
-            <connector name="CREATED" localId="11" height="30" width="110">
-              <position x="1096" y="105"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="7" formalParameter="ACK">
-                  <position x="1096" y="120"/>
-                  <position x="1034" y="120"/>
-                </connection>
-              </connectionPointIn>
-            </connector>
-            <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
-              <position x="957" y="472"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="31" formalParameter="OUT">
-                      <position x="957" y="522"/>
-                      <position x="909" y="522"/>
-                      <position x="909" y="444"/>
-                      <position x="857" y="444"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="12" formalParameter="OUT">
-                      <position x="957" y="582"/>
-                      <position x="822" y="582"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="50"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="110"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <continuation name="CREATED" localId="5" height="30" width="110">
-              <position x="589" y="429"/>
-              <connectionPointOut>
-                <relPosition x="110" y="15"/>
-              </connectionPointOut>
-            </continuation>
-            <block localId="12" width="186" height="288" typeName="CONCAT">
-              <position x="636" y="536"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="46"/>
-                    <connection refLocalId="14">
-                      <position x="636" y="582"/>
-                      <position x="526" y="582"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="99"/>
-                    <connection refLocalId="8">
-                      <position x="636" y="635"/>
-                      <position x="526" y="635"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN3">
-                  <connectionPointIn>
-                    <relPosition x="0" y="152"/>
-                    <connection refLocalId="15">
-                      <position x="636" y="688"/>
-                      <position x="527" y="688"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN4">
-                  <connectionPointIn>
-                    <relPosition x="0" y="205"/>
-                    <connection refLocalId="32">
-                      <position x="636" y="741"/>
-                      <position x="528" y="741"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN5">
-                  <connectionPointIn>
-                    <relPosition x="0" y="258"/>
-                    <connection refLocalId="16">
-                      <position x="636" y="794"/>
-                      <position x="528" y="794"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="186" y="46"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="8" height="30" width="53">
-              <position x="473" y="620"/>
-              <connectionPointOut>
-                <relPosition x="53" y="15"/>
-              </connectionPointOut>
-              <expression>ID</expression>
-            </inVariable>
-            <inVariable localId="13" height="35" width="100">
-              <position x="599" y="469"/>
-              <connectionPointOut>
-                <relPosition x="100" y="17"/>
-              </connectionPointOut>
-              <expression>set_text</expression>
-            </inVariable>
-            <inVariable localId="14" height="30" width="120">
-              <position x="406" y="567"/>
-              <connectionPointOut>
-                <relPosition x="120" y="15"/>
-              </connectionPointOut>
-              <expression>'setAttr('</expression>
-            </inVariable>
-            <inVariable localId="15" height="30" width="122">
-              <position x="405" y="673"/>
-              <connectionPointOut>
-                <relPosition x="122" y="15"/>
-              </connectionPointOut>
-              <expression>',"text","'</expression>
-            </inVariable>
-            <inVariable localId="16" height="30" width="50">
-              <position x="478" y="779"/>
-              <connectionPointOut>
-                <relPosition x="50" y="15"/>
-              </connectionPointOut>
-              <expression>'")'</expression>
-            </inVariable>
-            <block localId="31" width="75" height="105" typeName="AND">
-              <position x="782" y="403"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="41"/>
-                    <connection refLocalId="5">
-                      <position x="782" y="444"/>
-                      <position x="699" y="444"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="83"/>
-                    <connection refLocalId="13">
-                      <position x="782" y="486"/>
-                      <position x="699" y="486"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="75" y="41"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="32" height="30" width="90">
-              <position x="438" y="726"/>
-              <connectionPointOut>
-                <relPosition x="90" y="15"/>
-              </connectionPointOut>
-              <expression>text</expression>
-            </inVariable>
-          </FBD>
-        </body>
-      </pou>
-      <pou name="Button" pouType="functionBlock">
-        <interface>
-          <localVars>
-            <variable name="ID">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </localVars>
-          <inputVars>
-            <variable name="back_id">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="sele_id">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="toggle">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="set_state">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="state_in">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-          </inputVars>
-          <outputVars>
-            <variable name="state_out">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-          </outputVars>
-          <localVars>
-            <variable name="init_Command">
-              <type>
-                <derived name="python_eval"/>
-              </type>
-            </variable>
-            <variable name="GetButtonState">
-              <type>
-                <derived name="GetBoolString"/>
-              </type>
-            </variable>
-            <variable name="setstate_Command">
-              <type>
-                <derived name="python_eval"/>
-              </type>
-            </variable>
-            <variable name="getstate_Command">
-              <type>
-                <derived name="python_poll"/>
-              </type>
-            </variable>
-            <variable name="GetButtonToggle">
-              <type>
-                <derived name="GetBoolString"/>
-              </type>
-            </variable>
-          </localVars>
-        </interface>
-        <body>
-          <FBD>
-            <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
-              <position x="838" y="32"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="10">
-                      <position x="838" y="82"/>
-                      <position x="781" y="82"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="2" formalParameter="OUT">
-                      <position x="838" y="142"/>
-                      <position x="641" y="142"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="50"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="110"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <block localId="2" width="150" height="442" typeName="CONCAT">
-              <position x="491" y="92"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="3">
-                      <position x="491" y="142"/>
-                      <position x="433" y="142"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="11">
-                      <position x="491" y="202"/>
-                      <position x="431" y="202"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN3">
-                  <connectionPointIn>
-                    <relPosition x="0" y="170"/>
-                    <connection refLocalId="5">
-                      <position x="491" y="262"/>
-                      <position x="431" y="262"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN4">
-                  <connectionPointIn>
-                    <relPosition x="0" y="230"/>
-                    <connection refLocalId="12">
-                      <position x="491" y="322"/>
-                      <position x="430" y="322"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN5">
-                  <connectionPointIn>
-                    <relPosition x="0" y="290"/>
-                    <connection refLocalId="23">
-                      <position x="491" y="382"/>
-                      <position x="463" y="382"/>
-                      <position x="463" y="370"/>
-                      <position x="430" y="370"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN6">
-                  <connectionPointIn>
-                    <relPosition x="0" y="350"/>
-                    <connection refLocalId="24" formalParameter="CODE">
-                      <position x="491" y="442"/>
-                      <position x="429" y="442"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN7">
-                  <connectionPointIn>
-                    <relPosition x="0" y="410"/>
-                    <connection refLocalId="9">
-                      <position x="491" y="502"/>
-                      <position x="430" y="502"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="150" y="50"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="3" height="30" width="400">
-              <position x="33" y="127"/>
-              <connectionPointOut>
-                <relPosition x="400" y="15"/>
-              </connectionPointOut>
-              <expression>'createSVGUIControl("button",back_id="'</expression>
-            </inVariable>
-            <inVariable localId="5" height="30" width="140">
-              <position x="291" y="247"/>
-              <connectionPointOut>
-                <relPosition x="140" y="15"/>
-              </connectionPointOut>
-              <expression>'",sele_id="'</expression>
-            </inVariable>
-            <inVariable localId="9" height="30" width="180">
-              <position x="250" y="487"/>
-              <connectionPointOut>
-                <relPosition x="180" y="15"/>
-              </connectionPointOut>
-              <expression>',active=True)'</expression>
-            </inVariable>
-            <inVariable localId="10" height="30" width="70">
-              <position x="711" y="67"/>
-              <connectionPointOut>
-                <relPosition x="70" y="15"/>
-              </connectionPointOut>
-              <expression>BOOL#1</expression>
-            </inVariable>
-            <inVariable localId="11" height="35" width="85">
-              <position x="346" y="187"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>back_id</expression>
-            </inVariable>
-            <inVariable localId="12" height="35" width="85">
-              <position x="345" y="307"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>sele_id</expression>
-            </inVariable>
-            <inVariable localId="13" height="35" width="100">
-              <position x="452" y="639"/>
-              <connectionPointOut>
-                <relPosition x="100" y="15"/>
-              </connectionPointOut>
-              <expression>set_state</expression>
-            </inVariable>
-            <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonState">
-              <position x="239" y="897"/>
-              <inputVariables>
-                <variable formalParameter="VALUE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="32">
-                      <position x="239" y="927"/>
-                      <position x="181" y="927"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="CODE">
-                  <connectionPointOut>
-                    <relPosition x="140" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <outVariable localId="29" height="30" width="53">
-              <position x="1015" y="127"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="1" formalParameter="RESULT">
-                  <position x="1015" y="142"/>
-                  <position x="963" y="142"/>
-                </connection>
-              </connectionPointIn>
-              <expression>ID</expression>
-            </outVariable>
-            <block localId="4" width="125" height="140" typeName="python_eval" instanceName="setstate_Command">
-              <position x="810" y="640"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="31" formalParameter="OUT">
-                      <position x="810" y="690"/>
-                      <position x="762" y="690"/>
-                      <position x="762" y="612"/>
-                      <position x="710" y="612"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="7" formalParameter="OUT">
-                      <position x="810" y="750"/>
-                      <position x="643" y="750"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="50"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="110"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <connector name="CREATED" localId="30" height="30" width="110">
-              <position x="1014" y="67"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="1" formalParameter="ACK">
-                  <position x="1014" y="82"/>
-                  <position x="963" y="82"/>
-                </connection>
-              </connectionPointIn>
-            </connector>
-            <continuation name="CREATED" localId="6" height="30" width="110">
-              <position x="442" y="597"/>
-              <connectionPointOut>
-                <relPosition x="110" y="15"/>
-              </connectionPointOut>
-            </continuation>
-            <block localId="31" width="75" height="105" typeName="AND">
-              <position x="635" y="571"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="41"/>
-                    <connection refLocalId="6">
-                      <position x="635" y="612"/>
-                      <position x="552" y="612"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="83"/>
-                    <connection refLocalId="13">
-                      <position x="635" y="654"/>
-                      <position x="552" y="654"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="75" y="41"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="32" height="30" width="90">
-              <position x="91" y="912"/>
-              <connectionPointOut>
-                <relPosition x="90" y="15"/>
-              </connectionPointOut>
-              <expression>state_in</expression>
-            </inVariable>
-            <outVariable localId="33" height="30" width="100">
-              <position x="1334" y="1184"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="26" formalParameter="OUT">
-                  <position x="1334" y="1199"/>
-                  <position x="1286" y="1199"/>
-                </connection>
-              </connectionPointIn>
-              <expression>state_out</expression>
-            </outVariable>
-            <block localId="7" width="150" height="319" typeName="CONCAT">
-              <position x="493" y="701"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="49"/>
-                    <connection refLocalId="14">
-                      <position x="493" y="750"/>
-                      <position x="379" y="750"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="108"/>
-                    <connection refLocalId="8">
-                      <position x="493" y="809"/>
-                      <position x="435" y="809"/>
-                      <position x="435" y="803"/>
-                      <position x="379" y="803"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN3">
-                  <connectionPointIn>
-                    <relPosition x="0" y="167"/>
-                    <connection refLocalId="15">
-                      <position x="493" y="868"/>
-                      <position x="435" y="868"/>
-                      <position x="435" y="855"/>
-                      <position x="379" y="855"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN4">
-                  <connectionPointIn>
-                    <relPosition x="0" y="226"/>
-                    <connection refLocalId="28" formalParameter="CODE">
-                      <position x="493" y="927"/>
-                      <position x="379" y="927"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN5">
-                  <connectionPointIn>
-                    <relPosition x="0" y="285"/>
-                    <connection refLocalId="16">
-                      <position x="493" y="986"/>
-                      <position x="377" y="986"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="150" y="49"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="8" height="30" width="53">
-              <position x="326" y="788"/>
-              <connectionPointOut>
-                <relPosition x="53" y="15"/>
-              </connectionPointOut>
-              <expression>ID</expression>
-            </inVariable>
-            <inVariable localId="14" height="30" width="120">
-              <position x="259" y="735"/>
-              <connectionPointOut>
-                <relPosition x="120" y="15"/>
-              </connectionPointOut>
-              <expression>'setAttr('</expression>
-            </inVariable>
-            <inVariable localId="15" height="30" width="122">
-              <position x="257" y="840"/>
-              <connectionPointOut>
-                <relPosition x="122" y="15"/>
-              </connectionPointOut>
-              <expression>',"state",'</expression>
-            </inVariable>
-            <inVariable localId="16" height="30" width="41">
-              <position x="336" y="971"/>
-              <connectionPointOut>
-                <relPosition x="41" y="15"/>
-              </connectionPointOut>
-              <expression>')'</expression>
-            </inVariable>
-            <block localId="17" width="125" height="140" typeName="python_poll" instanceName="getstate_Command">
-              <position x="801" y="1089"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="18">
-                      <position x="801" y="1139"/>
-                      <position x="763" y="1139"/>
-                      <position x="763" y="1099"/>
-                      <position x="720" y="1099"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="22" formalParameter="OUT">
-                      <position x="801" y="1199"/>
-                      <position x="643" y="1199"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="50"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="110"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <block localId="25" width="145" height="45" typeName="STRING_TO_INT">
-              <position x="966" y="1169"/>
-              <inputVariables>
-                <variable formalParameter="IN">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="17" formalParameter="RESULT">
-                      <position x="966" y="1199"/>
-                      <position x="926" y="1199"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="145" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <block localId="26" width="125" height="45" typeName="INT_TO_BOOL">
-              <position x="1161" y="1169"/>
-              <inputVariables>
-                <variable formalParameter="IN">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="25" formalParameter="OUT">
-                      <position x="1161" y="1199"/>
-                      <position x="1111" y="1199"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <continuation name="CREATED" localId="18" height="30" width="110">
-              <position x="610" y="1084"/>
-              <connectionPointOut>
-                <relPosition x="110" y="15"/>
-              </connectionPointOut>
-            </continuation>
-            <inVariable localId="19" height="30" width="53">
-              <position x="383" y="1238"/>
-              <connectionPointOut>
-                <relPosition x="53" y="15"/>
-              </connectionPointOut>
-              <expression>ID</expression>
-            </inVariable>
-            <inVariable localId="20" height="30" width="150">
-              <position x="286" y="1184"/>
-              <connectionPointOut>
-                <relPosition x="150" y="15"/>
-              </connectionPointOut>
-              <expression>'int(getAttr('</expression>
-            </inVariable>
-            <inVariable localId="21" height="30" width="190">
-              <position x="246" y="1292"/>
-              <connectionPointOut>
-                <relPosition x="190" y="15"/>
-              </connectionPointOut>
-              <expression>',"state",False))'</expression>
-            </inVariable>
-            <block localId="22" width="150" height="183" typeName="CONCAT">
-              <position x="493" y="1152"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="47"/>
-                    <connection refLocalId="20">
-                      <position x="493" y="1199"/>
-                      <position x="436" y="1199"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="101"/>
-                    <connection refLocalId="19">
-                      <position x="493" y="1253"/>
-                      <position x="436" y="1253"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN3">
-                  <connectionPointIn>
-                    <relPosition x="0" y="155"/>
-                    <connection refLocalId="21">
-                      <position x="493" y="1307"/>
-                      <position x="483" y="1307"/>
-                      <position x="483" y="1307"/>
-                      <position x="436" y="1307"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="150" y="47"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="23" height="30" width="130">
-              <position x="300" y="355"/>
-              <connectionPointOut>
-                <relPosition x="130" y="15"/>
-              </connectionPointOut>
-              <expression>'",toggle='</expression>
-            </inVariable>
-            <block localId="24" width="140" height="40" typeName="GetBoolString" instanceName="GetButtonToggle">
-              <position x="289" y="412"/>
-              <inputVariables>
-                <variable formalParameter="VALUE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="27">
-                      <position x="289" y="442"/>
-                      <position x="220" y="442"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="CODE">
-                  <connectionPointOut>
-                    <relPosition x="140" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="27" height="30" width="90">
-              <position x="130" y="427"/>
-              <connectionPointOut>
-                <relPosition x="90" y="15"/>
-              </connectionPointOut>
-              <expression>toggle</expression>
-            </inVariable>
-          </FBD>
-        </body>
-      </pou>
-      <pou name="Led" pouType="functionBlock">
-        <interface>
-          <localVars>
-            <variable name="ID">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </localVars>
-          <inputVars>
-            <variable name="back_id">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="sele_id">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="state_in">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-          </inputVars>
-          <localVars>
-            <variable name="init_Command">
-              <type>
-                <derived name="python_eval"/>
-              </type>
-            </variable>
-            <variable name="setstate_Command">
-              <type>
-                <derived name="python_poll"/>
-              </type>
-            </variable>
-            <variable name="GetLedState">
-              <type>
-                <derived name="GetBoolString"/>
-              </type>
-            </variable>
-          </localVars>
-        </interface>
-        <body>
-          <FBD>
-            <block localId="1" width="125" height="140" typeName="python_eval" instanceName="init_Command">
-              <position x="810" y="30"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="10">
-                      <position x="810" y="80"/>
-                      <position x="753" y="80"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="2" formalParameter="OUT">
-                      <position x="810" y="140"/>
-                      <position x="640" y="140"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="50"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="110"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <block localId="2" width="150" height="322" typeName="CONCAT">
-              <position x="490" y="90"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="3">
-                      <position x="490" y="140"/>
-                      <position x="415" y="140"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="11">
-                      <position x="490" y="200"/>
-                      <position x="415" y="200"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN3">
-                  <connectionPointIn>
-                    <relPosition x="0" y="170"/>
-                    <connection refLocalId="5">
-                      <position x="490" y="260"/>
-                      <position x="415" y="260"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN4">
-                  <connectionPointIn>
-                    <relPosition x="0" y="230"/>
-                    <connection refLocalId="12">
-                      <position x="490" y="320"/>
-                      <position x="414" y="320"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN5">
-                  <connectionPointIn>
-                    <relPosition x="0" y="290"/>
-                    <connection refLocalId="9">
-                      <position x="490" y="380"/>
-                      <position x="414" y="380"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="150" y="50"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="3" height="30" width="400">
-              <position x="15" y="125"/>
-              <connectionPointOut>
-                <relPosition x="400" y="15"/>
-              </connectionPointOut>
-              <expression>'createSVGUIControl("button",back_id="'</expression>
-            </inVariable>
-            <block localId="4" width="125" height="140" typeName="python_poll" instanceName="setstate_Command">
-              <position x="782" y="536"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="50"/>
-                    <connection refLocalId="6">
-                      <position x="782" y="586"/>
-                      <position x="653" y="586"/>
-                      <position x="653" y="552"/>
-                      <position x="602" y="552"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="110"/>
-                    <connection refLocalId="7" formalParameter="OUT">
-                      <position x="782" y="646"/>
-                      <position x="615" y="646"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="50"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="110"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="5" height="30" width="140">
-              <position x="275" y="245"/>
-              <connectionPointOut>
-                <relPosition x="140" y="15"/>
-              </connectionPointOut>
-              <expression>'",sele_id="'</expression>
-            </inVariable>
-            <continuation name="CREATED" localId="6" height="30" width="110">
-              <position x="492" y="537"/>
-              <connectionPointOut>
-                <relPosition x="110" y="15"/>
-              </connectionPointOut>
-            </continuation>
-            <block localId="7" width="150" height="319" typeName="CONCAT">
-              <position x="465" y="597"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="49"/>
-                    <connection refLocalId="14">
-                      <position x="465" y="646"/>
-                      <position x="351" y="646"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="108"/>
-                    <connection refLocalId="8">
-                      <position x="465" y="705"/>
-                      <position x="407" y="705"/>
-                      <position x="407" y="699"/>
-                      <position x="351" y="699"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN3">
-                  <connectionPointIn>
-                    <relPosition x="0" y="167"/>
-                    <connection refLocalId="15">
-                      <position x="465" y="764"/>
-                      <position x="407" y="764"/>
-                      <position x="407" y="751"/>
-                      <position x="351" y="751"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN4">
-                  <connectionPointIn>
-                    <relPosition x="0" y="226"/>
-                    <connection refLocalId="28" formalParameter="CODE">
-                      <position x="465" y="823"/>
-                      <position x="351" y="823"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN5">
-                  <connectionPointIn>
-                    <relPosition x="0" y="285"/>
-                    <connection refLocalId="16">
-                      <position x="465" y="882"/>
-                      <position x="407" y="882"/>
-                      <position x="407" y="883"/>
-                      <position x="351" y="883"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="150" y="49"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="8" height="30" width="53">
-              <position x="298" y="684"/>
-              <connectionPointOut>
-                <relPosition x="53" y="15"/>
-              </connectionPointOut>
-              <expression>ID</expression>
-            </inVariable>
-            <inVariable localId="9" height="30" width="300">
-              <position x="124" y="365"/>
-              <connectionPointOut>
-                <relPosition x="300" y="15"/>
-              </connectionPointOut>
-              <expression>'",toggle=True,active=False)'</expression>
-            </inVariable>
-            <inVariable localId="10" height="30" width="70">
-              <position x="683" y="65"/>
-              <connectionPointOut>
-                <relPosition x="70" y="15"/>
-              </connectionPointOut>
-              <expression>BOOL#1</expression>
-            </inVariable>
-            <inVariable localId="11" height="35" width="85">
-              <position x="330" y="185"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>back_id</expression>
-            </inVariable>
-            <inVariable localId="12" height="35" width="85">
-              <position x="329" y="305"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>sele_id</expression>
-            </inVariable>
-            <inVariable localId="14" height="30" width="120">
-              <position x="231" y="631"/>
-              <connectionPointOut>
-                <relPosition x="120" y="15"/>
-              </connectionPointOut>
-              <expression>'setAttr('</expression>
-            </inVariable>
-            <inVariable localId="15" height="30" width="122">
-              <position x="229" y="736"/>
-              <connectionPointOut>
-                <relPosition x="122" y="15"/>
-              </connectionPointOut>
-              <expression>',"state",'</expression>
-            </inVariable>
-            <inVariable localId="16" height="30" width="41">
-              <position x="310" y="868"/>
-              <connectionPointOut>
-                <relPosition x="41" y="15"/>
-              </connectionPointOut>
-              <expression>')'</expression>
-            </inVariable>
-            <block localId="28" width="140" height="40" typeName="GetBoolString" instanceName="GetLedState">
-              <position x="211" y="793"/>
-              <inputVariables>
-                <variable formalParameter="VALUE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="32">
-                      <position x="211" y="823"/>
-                      <position x="153" y="823"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="CODE">
-                  <connectionPointOut>
-                    <relPosition x="140" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <outVariable localId="29" height="30" width="53">
-              <position x="987" y="125"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="1" formalParameter="RESULT">
-                  <position x="987" y="140"/>
-                  <position x="935" y="140"/>
-                </connection>
-              </connectionPointIn>
-              <expression>ID</expression>
-            </outVariable>
-            <connector name="CREATED" localId="30" height="30" width="110">
-              <position x="986" y="65"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="1" formalParameter="ACK">
-                  <position x="986" y="80"/>
-                  <position x="935" y="80"/>
-                </connection>
-              </connectionPointIn>
-            </connector>
-            <inVariable localId="32" height="30" width="90">
-              <position x="63" y="808"/>
-              <connectionPointOut>
-                <relPosition x="90" y="15"/>
-              </connectionPointOut>
-              <expression>state_in</expression>
-            </inVariable>
-          </FBD>
-        </body>
-      </pou>
-    </pous>
-  </types>
-  <instances>
-    <configurations/>
-  </instances>
-</project>
--- a/plugins/python/modules/svgui/pyjs/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-from pyjs import *
-
--- a/plugins/python/modules/svgui/pyjs/build.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import os
-import shutil
-from copy import copy
-from os.path import join, dirname, basename, abspath, split, isfile, isdir
-from optparse import OptionParser
-import pyjs
-from cStringIO import StringIO
-try:
-    # Python 2.5 and above
-    from hashlib import md5
-except:
-    import md5
-import re
-
-usage = """
-  usage: %prog [options] <application module name or path>
-
-This is the command line builder for the pyjamas project, which can
-be used to build Ajax applications from Python.
-For more information, see the website at http://pyjs.org/
-"""
-
-# GWT1.2 Impl  | GWT1.2 Output         | Pyjamas 0.2 Platform | Pyjamas 0.2 Output
-# -------------+-----------------------+----------------------+----------------------
-# IE6          | ie6                   | IE6                  | ie6
-# Opera        | opera                 | Opera                | opera
-# Safari       | safari                | Safari               | safari
-# --           | gecko1_8              | Mozilla              | mozilla
-# --           | gecko                 | OldMoz               | oldmoz
-# Standard     | all                   | (default code)       | all
-# Mozilla      | gecko1_8, gecko       | --                   | --
-# Old          | safari, gecko, opera  | --                   | --
-
-version = "%prog pyjamas version 2006-08-19"
-
-# these names in lowercase need match the strings
-# returned by "provider$user.agent" in order to be selected corretly
-app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla']
-
-# usually defaults to e.g. /usr/share/pyjamas
-_data_dir = os.path.join(pyjs.prefix, "share/pyjamas")
-
-
-# .cache.html files produces look like this
-CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$')
-
-# ok these are the three "default" library directories, containing
-# the builtins (str, List, Dict, ord, round, len, range etc.)
-# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.)
-# and the contributed addons
-
-for p in ["library/builtins",
-          "library",
-          "addons"]:
-    p = os.path.join(_data_dir, p)
-    if os.path.isdir(p):
-        pyjs.path.append(p)
-
-
-def read_boilerplate(data_dir, filename):
-    return open(join(data_dir, "builder/boilerplate", filename)).read()
-
-def copy_boilerplate(data_dir, filename, output_dir):
-    filename = join(data_dir, "builder/boilerplate", filename)
-    shutil.copy(filename, output_dir)
-
-
-# taken and modified from python2.4
-def copytree_exists(src, dst, symlinks=False):
-    if not os.path.exists(src):
-        return
-
-    names = os.listdir(src)
-    try:
-        os.mkdir(dst)
-    except:
-        pass
-
-    errors = []
-    for name in names:
-        if name.startswith('CVS'):
-            continue
-        if name.startswith('.git'):
-            continue
-        if name.startswith('.svn'):
-            continue
-
-        srcname = os.path.join(src, name)
-        dstname = os.path.join(dst, name)
-        try:
-            if symlinks and os.path.islink(srcname):
-                linkto = os.readlink(srcname)
-                os.symlink(linkto, dstname)
-            elif isdir(srcname):
-                copytree_exists(srcname, dstname, symlinks)
-            else:
-                shutil.copy2(srcname, dstname)
-        except (IOError, os.error), why:
-            errors.append((srcname, dstname, why))
-    if errors:
-        print errors
-
-def check_html_file(source_file, dest_path):
-    """ Checks if a base HTML-file is available in the PyJamas
-        output directory.
-        If the HTML-file isn't available, it will be created.
-
-        If a CSS-file with the same name is available
-        in the output directory, a reference to this CSS-file
-        is included.
-
-        If no CSS-file is found, this function will look for a special
-        CSS-file in the output directory, with the name
-        "pyjamas_default.css", and if found it will be referenced
-        in the generated HTML-file.
-
-        [thank you to stef mientki for contributing this function]
-    """
-
-    base_html = """\
-<html>
-    <!-- auto-generated html - you should consider editing and
-         adapting this to suit your requirements
-     -->
-    <head>
-      <meta name="pygwt:module" content="%(modulename)s">
-      %(css)s
-      <title>%(title)s</title>
-    </head>
-    <body bgcolor="white">
-      <script language="javascript" src="pygwt.js"></script>
-    </body>
-</html>
-"""
-
-    filename = os.path.split    ( source_file )[1]
-    mod_name = os.path.splitext ( filename    )[0]
-    file_name = os.path.join     ( dest_path, mod_name + '.html' )
-
-    # if html file in output directory exists, leave it alone.
-    if os.path.exists ( file_name ):
-        return 0
-
-    if os.path.exists (
-        os.path.join ( dest_path, mod_name + '.css' ) ) :
-        css = "<link rel='stylesheet' href='" + mod_name + ".css'>"
-    elif os.path.exists (
-        os.path.join ( dest_path, 'pyjamas_default.css' ) ) :
-        css = "<link rel='stylesheet' href='pyjamas_default.css'>"
-
-    else:
-        css = ''
-
-    title = 'PyJamas Auto-Generated HTML file ' + mod_name
-
-    base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css}
-
-    fh = open (file_name, 'w')
-    fh.write  (base_html)
-    fh.close  ()
-
-    return 1
-
-
-def build(app_name, output, js_includes=(), debug=False, dynamic=0,
-          data_dir=None, cache_buster=False, optimize=False):
-
-    # make sure the output directory is always created in the current working
-    # directory or at the place given if it is an absolute path.
-    output = os.path.abspath(output)
-    msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals()
-    if debug:
-        msg += " with debugging statements"
-    print msg
-
-    # check the output directory
-    if os.path.exists(output) and not os.path.isdir(output):
-        print >>sys.stderr, "Output destination %s exists and is not a directory" % output
-        return
-    if not os.path.isdir(output):
-        try:
-            print "Creating output directory"
-            os.mkdir(output)
-        except StandardError, e:
-            print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e)
-
-    ## public dir
-    for p in pyjs.path:
-        pub_dir = join(p, 'public')
-        if isdir(pub_dir):
-            print "Copying: public directory of library %r" % p
-            copytree_exists(pub_dir, output)
-
-    ## AppName.html - can be in current or public directory
-    html_input_filename = app_name + ".html"
-    html_output_filename = join(output, basename(html_input_filename))
-    if os.path.isfile(html_input_filename):
-        if not os.path.isfile(html_output_filename) or \
-               os.path.getmtime(html_input_filename) > \
-               os.path.getmtime(html_output_filename):
-            try:
-                shutil.copy(html_input_filename, html_output_filename)
-            except:
-                print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename
-
-            print "Copying: %(html_input_filename)s" % locals()
-
-    if check_html_file(html_input_filename, output):
-        print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename
-
-    ## pygwt.js
-
-    print "Copying: pygwt.js"
-
-    pygwt_js_template = read_boilerplate(data_dir, "pygwt.js")
-    pygwt_js_output = open(join(output, "pygwt.js"), "w")
-
-    print >>pygwt_js_output, pygwt_js_template
-
-    pygwt_js_output.close()
-
-    ## Images
-
-    print "Copying: Images and History"
-    copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_topleft.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_topright.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output)
-    copy_boilerplate(data_dir, "corner_dialog_edge.png", output)
-    copy_boilerplate(data_dir, "tree_closed.gif", output)
-    copy_boilerplate(data_dir, "tree_open.gif", output)
-    copy_boilerplate(data_dir, "tree_white.gif", output)
-    copy_boilerplate(data_dir, "history.html", output)
-
-
-    ## all.cache.html
-    app_files = generateAppFiles(data_dir, js_includes, app_name, debug,
-                                 output, dynamic, cache_buster, optimize)
-
-    ## AppName.nocache.html
-
-    print "Creating: %(app_name)s.nocache.html" % locals()
-
-    home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html")
-    home_nocache_html_output = open(join(output, app_name + ".nocache.html"),
-                                    "w")
-
-    # the selector templ is added to the selectScript function
-    select_tmpl = """O(["true","%s"],"%s");"""
-    script_selectors = StringIO()
-
-    for platform, file_prefix in app_files:
-        print >> script_selectors, select_tmpl % (platform, file_prefix)
-
-    print >>home_nocache_html_output, home_nocache_html_template % dict(
-        app_name = app_name,
-        script_selectors = script_selectors.getvalue(),
-    )
-
-    home_nocache_html_output.close()
-
-    print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals()
-
-
-def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic,
-                     cache_buster, optimize):
-
-    all_cache_html_template = read_boilerplate(data_dir, "all.cache.html")
-    mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html")
-
-    # clean out the old ones first
-    for name in os.listdir(output):
-        if CACHE_HTML_PAT.match(name):
-            p = join(output, name)
-            print "Deleting existing app file %s" % p
-            os.unlink(p)
-
-    app_files = []
-    tmpl = read_boilerplate(data_dir, "all.cache.html")
-    parser = pyjs.PlatformParser("platform")
-    app_headers = ''
-    scripts = ['<script type="text/javascript" src="%s"></script>'%script \
-                                                  for script in js_includes]
-    app_body = '\n'.join(scripts)
-
-    mod_code = {}
-    mod_libs = {}
-    modules = {}
-    app_libs = {}
-    early_app_libs = {}
-    app_code = {}
-    overrides = {}
-    pover = {}
-    app_modnames = {}
-    mod_levels = {}
-
-    # First, generate all the code.
-    # Second, (dynamic only), post-analyse the places where modules
-    # haven't changed
-    # Third, write everything out.
-    
-    for platform in app_platforms:
-
-        mod_code[platform] = {}
-        mod_libs[platform] = {}
-        modules[platform] = []
-        pover[platform] = {}
-        app_libs[platform] = ''
-        early_app_libs[platform] = ''
-        app_code[platform] = {}
-        app_modnames[platform] = {}
-
-        # Application.Platform.cache.html
-
-        parser.setPlatform(platform)
-        app_translator = pyjs.AppTranslator(
-            parser=parser, dynamic=dynamic, optimize=optimize)
-        early_app_libs[platform], appcode = \
-                     app_translator.translate(None, is_app=False,
-                                              debug=debug,
-                                      library_modules=['dynamicajax.js',
-                                                    '_pyjs.js', 'sys',
-                                                     'pyjslib'])
-        pover[platform].update(app_translator.overrides.items())
-        for mname, name in app_translator.overrides.items():
-            pd = overrides.setdefault(mname, {})
-            pd[platform] = name
-
-        print appcode
-        #mod_code[platform][app_name] = appcode
-
-        # platform.Module.cache.js 
-
-        modules_done = ['pyjslib', 'sys', '_pyjs.js']
-        #modules_to_do = [app_name] + app_translator.library_modules
-        modules_to_do = [app_name] + app_translator.library_modules 
-
-        dependencies = {}
-
-        deps = map(pyjs.strip_py, modules_to_do)
-        for d in deps:
-            sublist = add_subdeps(dependencies, d)
-            modules_to_do += sublist
-        deps = uniquify(deps)
-        #dependencies[app_name] = deps
-
-        modules[platform] = modules_done + modules_to_do
-
-        while modules_to_do:
-
-            #print "modules to do", modules_to_do
-
-            mn = modules_to_do.pop()
-            mod_name = pyjs.strip_py(mn)
-
-            if mod_name in modules_done:
-                continue
-
-            modules_done.append(mod_name)
-
-            mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name)
-
-            parser.setPlatform(platform)
-            mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize)
-            mod_libs[platform][mod_name], mod_code[platform][mod_name] = \
-                              mod_translator.translate(mod_name,
-                                                  is_app=False,
-                                                  debug=debug)
-            pover[platform].update(mod_translator.overrides.items())
-            for mname, name in mod_translator.overrides.items():
-                pd = overrides.setdefault(mname, {})
-                pd[platform] = name
-
-            mods = mod_translator.library_modules
-            modules_to_do += mods
-            modules[platform] += mods
-
-            deps = map(pyjs.strip_py, mods)
-            sd = subdeps(mod_name)
-            if len(sd) > 1:
-                deps += sd[:-1]
-            while mod_name in deps:
-                deps.remove(mod_name)
-
-            #print
-            #print
-            #print "modname preadd:", mod_name, deps
-            #print
-            #print
-            for d in deps:
-                sublist = add_subdeps(dependencies, d)
-                modules_to_do += sublist
-            modules_to_do += add_subdeps(dependencies, mod_name)
-            #print "modname:", mod_name, deps
-            deps = uniquify(deps)
-            #print "modname:", mod_name, deps
-            dependencies[mod_name] = deps
-            
-        # work out the dependency ordering of the modules
-    
-        mod_levels[platform] = make_deps(None, dependencies, modules_done)
-
-    # now write everything out
-
-    for platform in app_platforms:
-
-        early_app_libs_ = early_app_libs[platform]
-        app_libs_ = app_libs[platform]
-        app_code_ = app_code[platform]
-        #modules_ = filter_mods(app_name, modules[platform])
-        mods = flattenlist(mod_levels[platform])
-        mods.reverse()
-        modules_ = filter_mods(None, mods)
-
-        for mod_name in modules_:
-
-            mod_code_ = mod_code[platform][mod_name]
-
-            mod_name = pyjs.strip_py(mod_name)
-
-            override_name = "%s.%s" % (platform.lower(), mod_name)
-            if pover[platform].has_key(override_name):
-                mod_cache_name = "%s.cache.js" % (override_name)
-            else:
-                mod_cache_name = "%s.cache.js" % (mod_name)
-
-            print "Creating: " + mod_cache_name
-
-            modlevels = make_deps(None, dependencies, dependencies[mod_name])
-
-            modnames = []
-
-            for md in modlevels:
-                mnames = map(lambda x: "'%s'" % x, md)
-                mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
-                modnames.append(mnames)
-
-            modnames.reverse()
-            modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames)
-
-            # convert the overrides
-
-            overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
-            overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
-
-            if dynamic:
-                mod_cache_html_output = open(join(output, mod_cache_name), "w")
-            else:
-                mod_cache_html_output = StringIO()
-
-            print >>mod_cache_html_output, mod_cache_html_template % dict(
-                mod_name = mod_name,
-                app_name = app_name,
-                modnames = modnames,
-                overrides = overnames,
-                mod_libs = mod_libs[platform][mod_name],
-                dynamic = dynamic,
-                mod_code = mod_code_,
-            )
-
-            if dynamic:
-                mod_cache_html_output.close()
-            else:
-                mod_cache_html_output.seek(0)
-                app_libs_ += mod_cache_html_output.read()
-
-        # write out the dependency ordering of the modules
-    
-        app_modnames = []
-
-        for md in mod_levels[platform]:
-            mnames = map(lambda x: "'%s'" % x, md)
-            mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames)
-            app_modnames.append(mnames)
-
-        app_modnames.reverse()
-        app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames)
-
-        # convert the overrides
-
-        overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items())
-        overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames)
-
-        #print "platform names", platform, overnames
-        #print pover
-
-        # now write app.allcache including dependency-ordered list of
-        # library modules
-
-        file_contents = all_cache_html_template % dict(
-            app_name = app_name,
-            early_app_libs = early_app_libs_,
-            app_libs = app_libs_,
-            app_code = app_code_,
-            app_body = app_body,
-            overrides = overnames,
-            platform = platform.lower(),
-            dynamic = dynamic,
-            app_modnames = app_modnames,
-            app_headers = app_headers
-        )
-        if cache_buster:
-            digest = md5.new(file_contents).hexdigest()
-            file_name = "%s.%s.%s" % (platform.lower(), app_name, digest)
-        else:
-            file_name = "%s.%s" % (platform.lower(), app_name)
-        file_name += ".cache.html" 
-        out_path = join(output, file_name)
-        out_file = open(out_path, 'w')
-        out_file.write(file_contents)
-        out_file.close()
-        app_files.append((platform.lower(), file_name))
-        print "Created app file %s:%s: %s" % (
-            app_name, platform, out_path)
-
-    return app_files
-
-def flattenlist(ll):
-    res = []
-    for l in ll:
-        res += l
-    return res
-
-# creates sub-dependencies e.g. pyjamas.ui.Widget
-# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
-def subdeps(m):
-    d = []
-    m = m.split(".")
-    for i in range(0, len(m)):
-        d.append('.'.join(m[:i+1]))
-    return d
-
-import time
-
-def add_subdeps(deps, mod_name):
-    sd = subdeps(mod_name)
-    if len(sd) == 1:
-        return []
-    #print "subdeps", mod_name, sd
-    #print "deps", deps
-    res = []
-    for i in range(0, len(sd)-1):
-        parent = sd[i]
-        child = sd[i+1]
-        l = deps.get(child, [])
-        l.append(parent)
-        deps[child] = l
-        if parent not in res:
-            res.append(parent)
-    #print deps
-    return res
-
-# makes unique and preserves list order
-def uniquify(md):
-    res = []
-    for m in md:
-        if m not in res:
-            res.append(m)
-    return res
-
-def filter_mods(app_name, md):
-    while 'sys' in md:
-        md.remove('sys')
-    while 'pyjslib' in md:
-        md.remove('pyjslib')
-    while app_name in md:
-        md.remove(app_name)
-    md = filter(lambda x: not x.endswith('.js'), md)
-    md = map(pyjs.strip_py, md)
-
-    return uniquify(md)
-
-def filter_deps(app_name, deps):
-
-    res = {}
-    for (k, l) in deps.items():
-        mods = filter_mods(k, l)
-        while k in mods:
-            mods.remove(k)
-        res[k] = mods
-    return res
-
-def has_nodeps(mod, deps):
-    if not deps.has_key(mod) or not deps[mod]:
-        return True
-    return False
-
-def nodeps_list(mod_list, deps):
-    res = []
-    for mod in mod_list:
-        if has_nodeps(mod, deps):
-            res.append(mod)
-    return res
-        
-# this function takes a dictionary of dependent modules and
-# creates a list of lists.  the first list will be modules
-# that have no dependencies; the second list will be those
-# modules that have the first list as dependencies; the
-# third will be those modules that have the first and second...
-# etc.
-
-
-def make_deps(app_name, deps, mod_list):
-    print "Calculating Dependencies ..."
-    mod_list = filter_mods(app_name, mod_list)
-    deps = filter_deps(app_name, deps)
-
-    if not mod_list:
-        return []
-
-    #print mod_list
-    #print deps
-
-    ordered_deps = []
-    last_len = -1
-    while deps:
-        l_deps = len(deps)
-        #print l_deps
-        if l_deps==last_len:
-            for m, dl in deps.items():
-                for d in dl:
-                    if m in deps.get(d, []):
-                        raise Exception('Circular Imports found: \n%s %s -> %s %s'
-                                        % (m, dl, d, deps[d]))
-            #raise Exception('Could not calculate dependencies: \n%s' % deps)
-            break
-        last_len = l_deps
-        #print "modlist", mod_list
-        nodeps = nodeps_list(mod_list, deps)
-        #print "nodeps", nodeps
-        mod_list = filter(lambda x: x not in nodeps, mod_list)
-        newdeps = {}
-        for k in deps.keys():
-            depslist = deps[k]
-            depslist = filter(lambda x: x not in nodeps, depslist)
-            if depslist:
-                newdeps[k] = depslist
-        #print "newdeps", newdeps
-        deps = newdeps
-        ordered_deps.append(nodeps)
-        #time.sleep(0)
-
-    if mod_list:
-        ordered_deps.append(mod_list) # last dependencies - usually the app(s)
-
-    ordered_deps.reverse()
-
-    return ordered_deps
-
-def main():
-    global app_platforms
-
-    parser = OptionParser(usage = usage, version = version)
-    parser.add_option("-o", "--output", dest="output",
-        help="directory to which the webapp should be written")
-    parser.add_option("-j", "--include-js", dest="js_includes", action="append",
-        help="javascripts to load into the same frame as the rest of the script")
-    parser.add_option("-I", "--library_dir", dest="library_dirs",
-        action="append", help="additional paths appended to PYJSPATH")
-    parser.add_option("-D", "--data_dir", dest="data_dir",
-        help="path for data directory")
-    parser.add_option("-m", "--dynamic-modules", action="store_true",
-        dest="dynamic", default=False,
-        help="Split output into separate dynamically-loaded modules (experimental)")
-    parser.add_option("-P", "--platforms", dest="platforms",
-        help="platforms to build for, comma-separated")
-    parser.add_option("-d", "--debug", action="store_true", dest="debug")
-    parser.add_option("-O", "--optimize", action="store_true",
-                      dest="optimize", default=False,
-                      help="Optimize generated code (removes all print statements)",
-                      )
-    parser.add_option("-c", "--cache_buster", action="store_true",
-                  dest="cache_buster",
-        help="Enable browser cache-busting (MD5 hash added to output filenames)")
-
-    parser.set_defaults(output = "output", js_includes=[], library_dirs=[],
-                        platforms=(','.join(app_platforms)),
-                        data_dir=os.path.join(sys.prefix, "share/pyjamas"),
-                        dynamic=False,
-                        cache_buster=False,
-                        debug=False)
-    (options, args) = parser.parse_args()
-    if len(args) != 1:
-        parser.error("incorrect number of arguments")
-
-    data_dir = abspath(options.data_dir)
-
-    app_path = args[0]
-    if app_path.endswith('.py'):
-        app_path = abspath(app_path)
-        if not isfile(app_path):
-            parser.error("Application file not found %r" % app_path)
-        app_path, app_name = split(app_path)
-        app_name = app_name[:-3]
-        pyjs.path.append(app_path)
-    elif os.path.sep in app_path:
-        parser.error("Not a valid module declaration %r" % app_path)
-    else:
-        app_name = app_path
-
-    for d in options.library_dirs:
-        pyjs.path.append(abspath(d))
-
-    if options.platforms:
-       app_platforms = options.platforms.split(',')
-
-    # this is mostly for getting boilerplate stuff
-    data_dir = os.path.abspath(options.data_dir)
-
-    build(app_name, options.output, options.js_includes,
-          options.debug, options.dynamic and 1 or 0, data_dir,
-          options.cache_buster, options.optimize)
-
-if __name__ == "__main__":
-    main()
-
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/README.txt	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-These classes are intended for use server-side.
-
-e.g. in a django view.py :
-
-    from pyjs.jsonrpc.django import JSONService, jsonremote
-
-    jsonservice = JSONRPCService()
-
-    @jsonremote(jsonservice)
-    def test(request, echo_param):
-         return "echoing the param back: %s" % echo_param
-
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-# jsonrpc.py
-#   original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas
-#   also from: http://www.pimentech.fr/technologies/outils
-from django.utils import simplejson
-from django.http import HttpResponse
-import sys
-
-from pyjs.jsonrpc import JSONRPCServiceBase
-# JSONRPCService and jsonremote are used in combination to drastically
-# simplify the provision of JSONRPC services.  use as follows:
-#
-# jsonservice = JSONRPCService()
-#
-# @jsonremote(jsonservice)
-# def test(request, echo_param):
-#     return "echoing the param back: %s" % echo_param
-#
-# dump jsonservice into urlpatterns:
-#  (r'^service1/$', 'djangoapp.views.jsonservice'),
-
-class JSONRPCService(JSONRPCServiceBase):
-    
-    def __call__(self, request, extra=None):
-        return self.process(request.raw_post_data)
-
-def jsonremote(service):
-    """Make JSONRPCService a decorator so that you can write :
-    
-    from jsonrpc import JSONRPCService
-    chatservice = JSONRPCService()
-
-    @jsonremote(chatservice)
-    def login(request, user_name):
-        (...)
-    """
-    def remotify(func):
-        if isinstance(service, JSONRPCService):
-            service.add_method(func.__name__, func)
-        else:
-            emsg = 'Service "%s" not found' % str(service.__name__)
-            raise NotImplementedError, emsg
-        return func
-    return remotify
-
-
-# FormProcessor provides a mechanism for turning Django Forms into JSONRPC
-# Services.  If you have an existing Django app which makes prevalent
-# use of Django Forms it will save you rewriting the app.
-# use as follows.  in djangoapp/views.py :
-#
-# class SimpleForm(forms.Form):
-#     testfield = forms.CharField(max_length=100)
-#
-# class SimpleForm2(forms.Form):
-#     testfield = forms.CharField(max_length=20)
-#
-# processor = FormProcessor({'processsimpleform': SimpleForm,
-#                            'processsimpleform2': SimpleForm2})
-#
-# this will result in a JSONRPC service being created with two
-# RPC functions.  dump "processor" into urlpatterns to make it
-# part of the app:
-#  (r'^formsservice/$', 'djangoapp.views.processor'),
-
-from django import forms 
-
-def builderrors(form):
-    d = {}
-    for error in form.errors.keys():
-        if error not in d:
-            d[error] = []
-        for errorval in form.errors[error]:
-            d[error].append(unicode(errorval))
-    return d
-
-
-# contains the list of arguments in each field
-field_names = {
- 'CharField': ['max_length', 'min_length'],
- 'IntegerField': ['max_value', 'min_value'],
- 'FloatField': ['max_value', 'min_value'],
- 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'],
- 'DateField': ['input_formats'],
- 'DateTimeField': ['input_formats'],
- 'TimeField': ['input_formats'],
- 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr
- 'EmailField': ['max_length', 'min_length'],
- 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'],
- 'ChoiceField': ['choices'],
- 'FilePathField': ['path', 'match', 'recursive', 'choices'],
- 'IPAddressField': ['max_length', 'min_length'],
- }
-
-def describe_field_errors(field):
-    res = {}
-    field_type = field.__class__.__name__
-    msgs = {}
-    for n, m in field.error_messages.items():
-        msgs[n] = unicode(m)
-    res['error_messages'] = msgs
-    if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
-        res['fields'] = map(describe_field, field.fields)
-    return res
-
-def describe_fields_errors(fields, field_names):
-    res = {}
-    if not field_names:
-        field_names = fields.keys()
-    for name in field_names:
-        field = fields[name]
-        res[name] = describe_field_errors(field)
-    return res
-
-def describe_field(field):
-    res = {}
-    field_type = field.__class__.__name__
-    for fname in field_names.get(field_type, []) + \
-          ['help_text', 'label', 'initial', 'required']:
-        res[fname] = getattr(field, fname)
-    if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']:
-        res['fields'] = map(describe_field, field.fields)
-    return res
-
-def describe_fields(fields, field_names):
-    res = {}
-    if not field_names:
-        field_names = fields.keys()
-    for name in field_names:
-        field = fields[name]
-        res[name] = describe_field(field)
-    return res
-
-class FormProcessor(JSONRPCService):
-    def __init__(self, forms, _formcls=None):
-
-        if _formcls is None:
-            JSONRPCService.__init__(self)
-            for k in forms.keys():
-                s  = FormProcessor({}, forms[k])
-                self.add_method(k, s.__process)
-        else:
-            JSONRPCService.__init__(self, forms)
-            self.formcls = _formcls
-
-    def __process(self, request, params, command=None):
-
-        f = self.formcls(params)
-
-        if command is None: # just validate
-            if not f.is_valid():
-                return {'success':False, 'errors': builderrors(f)}
-            return {'success':True}
-
-        elif command.has_key('describe_errors'):
-            field_names = command['describe_errors']
-            return describe_fields_errors(f.fields, field_names)
-
-        elif command.has_key('describe'):
-            field_names = command['describe']
-            return describe_fields(f.fields, field_names)
-
-        elif command.has_key('save'):
-            if not f.is_valid():
-                return {'success':False, 'errors': builderrors(f)}
-            instance = f.save() # XXX: if you want more, over-ride save.
-            return {'success': True, 'instance': json_convert(instance) }
-
-        elif command.has_key('html'):
-            return {'success': True, 'html': f.as_table()}
-
-        return "unrecognised command"
-
-
-
-
-# The following is incredibly convenient for saving vast amounts of
-# coding, avoiding doing silly things like this:
-#     jsonresult = {'field1': djangoobject.field1,
-#                   'field2': djangoobject.date.strftime('%Y.%M'),
-#                    ..... }
-#
-# The date/time flatten function is there because JSONRPC doesn't
-# support date/time objects or formats, so conversion to a string
-# is the most logical choice.  pyjamas, being python, can easily
-# be used to parse the string result at the other end.
-#
-# use as follows:
-#
-# jsonservice = JSONRPCService()
-#
-# @jsonremote(jsonservice)
-# def list_some_model(request, start=0, count=10):
-#     l = SomeDjangoModelClass.objects.filter()
-#     res = json_convert(l[start:end])
-#
-# @jsonremote(jsonservice)
-# def list_another_model(request, start=0, count=10):
-#     l = AnotherDjangoModelClass.objects.filter()
-#     res = json_convert(l[start:end])
-#
-# dump jsonservice into urlpatterns to make the two RPC functions,
-# list_some_model and list_another_model part of the django app:
-#  (r'^service1/$', 'djangoapp.views.jsonservice'),
-
-from django.core.serializers import serialize
-import datetime
-from datetime import date
-
-def dict_datetimeflatten(item):
-    d = {}
-    for k, v in item.items():
-        k = str(k)
-        if isinstance(v, datetime.date):
-            d[k] = str(v)
-        elif isinstance(v, dict):
-            d[k] = dict_datetimeflatten(v)
-        else:
-            d[k] = v
-    return d
-
-def json_convert(l, fields=None):
-    res = []
-    for item in serialize('python', l, fields=fields):
-        res.append(dict_datetimeflatten(item))
-    return res
-
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/jsonrpc.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-import gluon.contrib.simplejson as simplejson
-import types
-import sys
-
-class JSONRPCServiceBase:
-
-    def __init__(self):
-        self.methods={}
-
-    def response(self, id, result):
-        return simplejson.dumps({'version': '1.1', 'id':id,
-                                 'result':result, 'error':None})
-    def error(self, id, code, message):
-        return simplejson.dumps({'id': id,
-                                 'version': '1.1',
-                                 'error': {'name': 'JSONRPCError',
-                                           'code': code,
-                                           'message': message
-                                           }
-                                     })
-
-    def add_method(self, name, method):
-        self.methods[name] = method
-
-    def process(self, data):
-        data = simplejson.loads(data)
-        id, method, params = data["id"], data["method"], data["params"]
-        if method in self.methods:
-            try:
-                result =self.methods[method](*params)
-                return self.response(id, result)
-            except BaseException:
-                etype, eval, etb = sys.exc_info()
-                return self.error(id, 100, '%s: %s' %(etype.__name__, eval))
-            except:
-                etype, eval, etb = sys.exc_info()
-                return self.error(id, 100, 'Exception %s: %s' %(etype, eval))
-        else:
-            return self.error(id, 100, 'method "%s" does not exist' % method)
-
-    def listmethods(self):
-        return self.methods.keys() 
-
--- a/plugins/python/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-from pyjs.jsonrpc import JSONRPCServiceBase
-
-class JSONRPCService(JSONRPCServiceBase):
-
-    def serve(self):
-        return self.process(request.body.read())
-
-    def __call__(self,func):
-        self.methods[func.__name__]=func
-        return func
-
--- a/plugins/python/modules/svgui/pyjs/lib/_pyjs.js	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-function pyjs_extend(klass, base) {
-    function klass_object_inherit() {}
-    klass_object_inherit.prototype = base.prototype;
-    klass_object = new klass_object_inherit();
-    for (var i in base.prototype.__class__) {
-        v = base.prototype.__class__[i];
-        if (typeof v == "function" && (v.class_method || v.static_method || v.unbound_method))
-        {
-            klass_object[i] = v;
-        }
-    }
-
-    function klass_inherit() {}
-    klass_inherit.prototype = klass_object;
-    klass.prototype = new klass_inherit();
-    klass_object.constructor = klass;
-    klass.prototype.__class__ = klass_object;
-
-    for (var i in base.prototype) {
-        v = base.prototype[i];
-        if (typeof v == "function" && v.instance_method)
-        {
-            klass.prototype[i] = v;
-        }
-    }
-}
-
-/* creates a class, derived from bases, with methods and variables */
-function pyjs_type(clsname, bases, methods)
-{
-    var fn_cls = function() {};
-    fn_cls.__name__ = clsname;
-    var fn = function() {
-        var instance = new fn_cls();
-        if(instance.__init__) instance.__init__.apply(instance, arguments);
-        return instance;
-    }
-    fn_cls.__initialize__ = function() {
-        if (fn_cls.__was_initialized__) return;
-        fn_cls.__was_initialized__ = true;
-        fn_cls.__extend_baseclasses();
-        fn_cls.prototype.__class__.__new__ = fn;
-        fn_cls.prototype.__class__.__name__ = clsname;
-    }
-    fn_cls.__extend_baseclasses = function() {
-        var bi;
-        for (bi in fn_cls.__baseclasses)
-        {
-            var b = fn_cls.__baseclasses[bi];
-            if (b.__was_initialized__)
-            {
-                continue;
-            }
-            b.__initialize__();
-        }
-        for (bi in fn_cls.__baseclasses)
-        {
-            var b = fn_cls.__baseclasses[bi];
-            pyjs_extend(fn_cls, b);
-        }
-    }
-    if (!bases) {
-        bases = [pyjslib.__Object];
-    }
-    fn_cls.__baseclasses = bases;
-
-    fn_cls.__initialize__();
-
-    for (k in methods) {
-        var mth = methods[k];
-        var mtype = typeof mth;
-        if (mtype == "function" ) {
-            fn_cls.prototype[k] = mth;
-            fn_cls.prototype.__class__[k] = function () {
-                return fn_cls.prototype[k].call.apply(
-                       fn_cls.prototype[k], arguments);
-            };
-            fn_cls.prototype.__class__[k].unbound_method = true;
-            fn_cls.prototype.instance_method = true;
-            fn_cls.prototype.__class__[k].__name__ = k;
-            fn_cls.prototype[k].__name__ = k;
-        } else {
-            fn_cls.prototype.__class__[k] = mth;
-        }
-    }
-    return fn;
-}
-function pyjs_kwargs_call(obj, func, star_args, args)
-{
-    var call_args;
-
-    if (star_args)
-    {
-        if (!pyjslib.isIteratable(star_args))
-        {
-            throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args)));
-        }
-        call_args = Array();
-        var __i = star_args.__iter__();
-        var i = 0;
-        try {
-            while (true) {
-                call_args[i]=__i.next();
-                i++;
-            }
-        } catch (e) {
-            if (e != pyjslib.StopIteration) {
-                throw e;
-            }
-        }
-
-        if (args)
-        {
-            var n = star_args.length;
-            for (var i=0; i < args.length; i++) {
-                call_args[n+i]=args[i];
-            }
-        }
-    }
-    else
-    {
-        call_args = args;
-    }
-    return func.apply(obj, call_args);
-}
-
-function pyjs_kwargs_function_call(func, star_args, args)
-{
-    return pyjs_kwargs_call(null, func, star_args, args);
-}
-
-function pyjs_kwargs_method_call(obj, method_name, star_args, args)
-{
-    var method = obj[method_name];
-    if (method.parse_kwargs)
-    {
-        args = method.parse_kwargs.apply(null, args);
-    }
-    return pyjs_kwargs_call(obj, method, star_args, args);
-}
-
-//String.prototype.__getitem__ = String.prototype.charAt;
-//String.prototype.upper = String.prototype.toUpperCase;
-//String.prototype.lower = String.prototype.toLowerCase;
-//String.prototype.find=pyjslib.String_find;
-//String.prototype.join=pyjslib.String_join;
-//String.prototype.isdigit=pyjslib.String_isdigit;
-//String.prototype.__iter__=pyjslib.String___iter__;
-//
-//String.prototype.__replace=String.prototype.replace;
-//String.prototype.replace=pyjslib.String_replace;
-//
-//String.prototype.split=pyjslib.String_split;
-//String.prototype.strip=pyjslib.String_strip;
-//String.prototype.lstrip=pyjslib.String_lstrip;
-//String.prototype.rstrip=pyjslib.String_rstrip;
-//String.prototype.startswith=pyjslib.String_startswith;
-
-var str = String;
-
--- a/plugins/python/modules/svgui/pyjs/lib/json.js	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,293 +0,0 @@
-json_parse = (function () {
-
-// This is a function that can parse a JSON text, producing a JavaScript
-// data structure. It is a simple, recursive descent parser. It does not use
-// eval or regular expressions, so it can be used as a model for implementing
-// a JSON parser in other languages.
-
-// We are defining the function inside of another function to avoid creating
-// global variables.
-
-    var at,     // The index of the current character
-        ch,     // The current character
-        escapee = {
-            '"':  '"',
-            '\\': '\\',
-            '/':  '/',
-            b:    '\b',
-            f:    '\f',
-            n:    '\n',
-            r:    '\r',
-            t:    '\t'
-        },
-        text,
-
-        error = function (m) {
-
-// Call error when something is wrong.
-
-            throw {
-                name:    'SyntaxError',
-                message: m,
-                at:      at,
-                text:    text
-            };
-        },
-
-        next = function (c) {
-
-// If a c parameter is provided, verify that it matches the current character.
-
-            if (c && c !== ch) {
-                error("Expected '" + c + "' instead of '" + ch + "'");
-            }
-
-// Get the next character. When there are no more characters,
-// return the empty string.
-
-            ch = text.charAt(at);
-            at += 1;
-            return ch;
-        },
-
-        number = function () {
-
-// Parse a number value.
-
-            var number,
-                string = '';
-
-            if (ch === '-') {
-                string = '-';
-                next('-');
-            }
-            while (ch >= '0' && ch <= '9') {
-                string += ch;
-                next();
-            }
-            if (ch === '.') {
-                string += '.';
-                while (next() && ch >= '0' && ch <= '9') {
-                    string += ch;
-                }
-            }
-            if (ch === 'e' || ch === 'E') {
-                string += ch;
-                next();
-                if (ch === '-' || ch === '+') {
-                    string += ch;
-                    next();
-                }
-                while (ch >= '0' && ch <= '9') {
-                    string += ch;
-                    next();
-                }
-            }
-            number = +string;
-            if (isNaN(number)) {
-                error("Bad number");
-            } else {
-                return number;
-            }
-        },
-
-        string = function () {
-
-// Parse a string value.
-
-            var hex,
-                i,
-                string = '',
-                uffff;
-
-// When parsing for string values, we must look for " and \ characters.
-
-            if (ch === '"') {
-                while (next()) {
-                    if (ch === '"') {
-                        next();
-                        return string;
-                    } else if (ch === '\\') {
-                        next();
-                        if (ch === 'u') {
-                            uffff = 0;
-                            for (i = 0; i < 4; i += 1) {
-                                hex = parseInt(next(), 16);
-                                if (!isFinite(hex)) {
-                                    break;
-                                }
-                                uffff = uffff * 16 + hex;
-                            }
-                            string += String.fromCharCode(uffff);
-                        } else if (typeof escapee[ch] === 'string') {
-                            string += escapee[ch];
-                        } else {
-                            break;
-                        }
-                    } else {
-                        string += ch;
-                    }
-                }
-            }
-            error("Bad string");
-        },
-
-        white = function () {
-
-// Skip whitespace.
-
-            while (ch && ch <= ' ') {
-                next();
-            }
-        },
-
-        word = function () {
-
-// true, false, or null.
-
-            switch (ch) {
-            case 't':
-                next('t');
-                next('r');
-                next('u');
-                next('e');
-                return true;
-            case 'f':
-                next('f');
-                next('a');
-                next('l');
-                next('s');
-                next('e');
-                return false;
-            case 'n':
-                next('n');
-                next('u');
-                next('l');
-                next('l');
-                return null;
-            }
-            error("Unexpected '" + ch + "'");
-        },
-
-        value,  // Place holder for the value function.
-
-        array = function () {
-
-// Parse an array value.
-
-            var array = [];
-
-            if (ch === '[') {
-                next('[');
-                white();
-                if (ch === ']') {
-                    next(']');
-                    return array;   // empty array
-                }
-                while (ch) {
-                    array.push(value());
-                    white();
-                    if (ch === ']') {
-                        next(']');
-                        return array;
-                    }
-                    next(',');
-                    white();
-                }
-            }
-            error("Bad array");
-        },
-
-        object = function () {
-
-// Parse an object value.
-
-            var key,
-                object = {};
-
-            if (ch === '{') {
-                next('{');
-                white();
-                if (ch === '}') {
-                    next('}');
-                    return object;   // empty object
-                }
-                while (ch) {
-                    key = string();
-                    white();
-                    next(':');
-                    if (Object.hasOwnProperty.call(object, key)) {
-                        error('Duplicate key "' + key + '"');
-                    }
-                    object[key] = value();
-                    white();
-                    if (ch === '}') {
-                        next('}');
-                        return object;
-                    }
-                    next(',');
-                    white();
-                }
-            }
-            error("Bad object");
-        };
-
-    value = function () {
-
-// Parse a JSON value. It could be an object, an array, a string, a number,
-// or a word.
-
-        white();
-        switch (ch) {
-        case '{':
-            return object();
-        case '[':
-            return array();
-        case '"':
-            return string();
-        case '-':
-            return number();
-        default:
-            return ch >= '0' && ch <= '9' ? number() : word();
-        }
-    };
-
-// Return the json_parse function. It will have access to all of the above
-// functions and variables.
-
-    return function (source, reviver) {
-        var result;
-
-        text = source;
-        at = 0;
-        ch = ' ';
-        result = value();
-        white();
-        if (ch) {
-            error("Syntax error");
-        }
-
-// If there is a reviver function, we recursively walk the new structure,
-// passing each name/value pair to the reviver function for possible
-// transformation, starting with a temporary root object that holds the result
-// in an empty key. If there is not a reviver function, we simply return the
-// result.
-
-        return typeof reviver === 'function' ? (function walk(holder, key) {
-            var k, v, value = holder[key];
-            if (value && typeof value === 'object') {
-                for (k in value) {
-                    if (Object.hasOwnProperty.call(value, k)) {
-                        v = walk(value, k);
-                        if (v !== undefined) {
-                            value[k] = v;
-                        } else {
-                            delete value[k];
-                        }
-                    }
-                }
-            }
-            return reviver.call(holder, key, value);
-        }({'': result}, '')) : result;
-    };
-}());
--- a/plugins/python/modules/svgui/pyjs/lib/pyjslib.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1365 +0,0 @@
-# Copyright 2006 James Tauber and contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-# iteration from Bob Ippolito's Iteration in JavaScript
-
-from __pyjamas__ import JS
-
-# must declare import _before_ importing sys
-
-def import_module(path, parent_module, module_name, dynamic=1, async=False):
-    """ 
-    """
-
-    JS("""
-        var cache_file;
-
-        if (module_name == "sys" || module_name == 'pyjslib')
-        {
-            /*module_load_request[module_name] = 1;*/
-            return;
-        }
-
-        if (path == null)
-        {
-            path = './';
-        }
-
-        var override_name = sys.platform + "." + module_name;
-        if (((sys.overrides != null) && 
-             (sys.overrides.has_key(override_name))))
-        {
-            cache_file =  sys.overrides.__getitem__(override_name) ;
-        }
-        else
-        {
-            cache_file =  module_name ;
-        }
-
-        cache_file = (path + cache_file + '.cache.js' ) ;
-
-        //alert("cache " + cache_file + " " + module_name + " " + parent_module);
-
-        /* already loaded? */
-        if (module_load_request[module_name])
-        {
-            if (module_load_request[module_name] >= 3 && parent_module != null)
-            {
-                //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';';
-                //pyjs_eval(onload_fn); /* set up the parent-module namespace */
-            }
-            return;
-        }
-        if (typeof (module_load_request[module_name]) == 'undefined')
-        {
-            module_load_request[module_name] = 1;
-        }
-
-        /* following a load, this first executes the script 
-         * "preparation" function MODULENAME_loaded_fn()
-         * and then sets up the loaded module in the namespace
-         * of the parent.
-         */
-
-        onload_fn = ''; // module_name + "_loaded_fn();"
-
-        if (parent_module != null)
-        {
-            //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';';
-            /*pmod = parent_module + '.' + module_name;
-            onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/
-        }
-
-
-        if (dynamic)
-        {
-            /* this one tacks the script onto the end of the DOM
-             */
-
-            pyjs_load_script(cache_file, onload_fn, async);
-
-            /* this one actually RUNS the script (eval) into the page.
-               my feeling is that this would be better for non-async
-               but i can't get it to work entirely yet.
-             */
-            /*pyjs_ajax_eval(cache_file, onload_fn, async);*/
-        }
-        else
-        {
-            if (module_name != "pyjslib" &&
-                module_name != "sys")
-                pyjs_eval(onload_fn);
-        }
-
-    """)
-
-JS("""
-function import_wait(proceed_fn, parent_mod, dynamic) {
-
-    var data = '';
-    var element = $doc.createElement("div");
-    $doc.body.appendChild(element);
-    function write_dom(txt) {
-        element.innerHTML = txt + '<br />';
-    }
-
-    var timeoutperiod = 1;
-    if (dynamic)
-        var timeoutperiod = 1;
-
-    var wait = function() {
-
-        var status = '';
-        for (l in module_load_request)
-        {
-            var m = module_load_request[l];
-            if (l == "sys" || l == 'pyjslib')
-                continue;
-            status += l + m + " ";
-        }
-
-        //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
-        wait_count += 1;
-
-        if (status == '')
-        {
-            setTimeout(wait, timeoutperiod);
-            return;
-        }
-
-        for (l in module_load_request)
-        {
-            var m = module_load_request[l];
-            if (l == "sys" || l == 'pyjslib')
-            {
-                module_load_request[l] = 4;
-                continue;
-            }
-            if ((parent_mod != null) && (l == parent_mod))
-            {
-                if (m == 1)
-                {
-                    setTimeout(wait, timeoutperiod);
-                    return;
-                }
-                if (m == 2)
-                {
-                    /* cheat and move app on to next stage */
-                    module_load_request[l] = 3;
-                }
-            }
-            if (m == 1 || m == 2)
-            {
-                setTimeout(wait, timeoutperiod);
-                return;
-            }
-            if (m == 3)
-            {
-                //alert("waited for module " + l + ": loaded");
-                module_load_request[l] = 4;
-                mod_fn = modules[l];
-            }
-        }
-        //alert("module wait done");
-
-        if (proceed_fn.importDone)
-            proceed_fn.importDone(proceed_fn);
-        else
-            proceed_fn();
-    }
-
-    wait();
-}
-""")
-
-class Object:
-    pass
-
-object = Object
-
-class Modload:
-
-    def __init__(self, path, app_modlist, app_imported_fn, dynamic,
-                 parent_mod):
-        self.app_modlist = app_modlist
-        self.app_imported_fn = app_imported_fn
-        self.path = path
-        self.idx = 0;
-        self.dynamic = dynamic
-        self.parent_mod = parent_mod
-
-    def next(self):
-        
-        for i in range(len(self.app_modlist[self.idx])):
-            app = self.app_modlist[self.idx][i]
-            import_module(self.path, self.parent_mod, app, self.dynamic, True);
-        self.idx += 1
-
-        if self.idx >= len(self.app_modlist):
-            import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
-        else:
-            import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
-
-def get_module(module_name):
-    ev = "__mod = %s;" % module_name
-    JS("pyjs_eval(ev);")
-    return __mod
-
-def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
-                        parent_mod=None):
-
-    loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
-    loader.next()
-
-import sys
-
-class BaseException:
-
-    name = "BaseException"
-
-    def __init__(self, *args):
-        self.args = args
-
-    def __str__(self):
-        if len(self.args) is 0:
-            return ''
-        elif len(self.args) is 1:
-            return repr(self.args[0])
-        return repr(self.args)
-
-    def toString(self):
-        return str(self)
-
-class Exception(BaseException):
-
-    name = "Exception"
-
-class TypeError(BaseException):
-    name = "TypeError"
-
-class StandardError(Exception):
-    name = "StandardError"
-
-class LookupError(StandardError):
-    name = "LookupError"
-
-    def toString(self):
-        return self.name + ": " + self.args[0]
-
-class KeyError(LookupError):
-    name = "KeyError"
-
-class AttributeError(StandardError):
-
-    name = "AttributeError"
-
-    def toString(self):
-        return "AttributeError: %s of %s" % (self.args[1], self.args[0])
-
-JS("""
-pyjslib.StopIteration = function () { };
-pyjslib.StopIteration.prototype = new Error();
-pyjslib.StopIteration.name = 'StopIteration';
-pyjslib.StopIteration.message = 'StopIteration';
-
-pyjslib.String_find = function(sub, start, end) {
-    var pos=this.indexOf(sub, start);
-    if (pyjslib.isUndefined(end)) return pos;
-
-    if (pos + sub.length>end) return -1;
-    return pos;
-}
-
-pyjslib.String_join = function(data) {
-    var text="";
-
-    if (pyjslib.isArray(data)) {
-        return data.join(this);
-    }
-    else if (pyjslib.isIteratable(data)) {
-        var iter=data.__iter__();
-        try {
-            text+=iter.next();
-            while (true) {
-                var item=iter.next();
-                text+=this + item;
-            }
-        }
-        catch (e) {
-            if (e != pyjslib.StopIteration) throw e;
-        }
-    }
-
-    return text;
-}
-
-pyjslib.String_isdigit = function() {
-    return (this.match(/^\d+$/g) != null);
-}
-
-pyjslib.String_replace = function(old, replace, count) {
-    var do_max=false;
-    var start=0;
-    var new_str="";
-    var pos=0;
-
-    if (!pyjslib.isString(old)) return this.__replace(old, replace);
-    if (!pyjslib.isUndefined(count)) do_max=true;
-
-    while (start<this.length) {
-        if (do_max && !count--) break;
-
-        pos=this.indexOf(old, start);
-        if (pos<0) break;
-
-        new_str+=this.substring(start, pos) + replace;
-        start=pos+old.length;
-    }
-    if (start<this.length) new_str+=this.substring(start);
-
-    return new_str;
-}
-
-pyjslib.String_split = function(sep, maxsplit) {
-    var items=new pyjslib.List();
-    var do_max=false;
-    var subject=this;
-    var start=0;
-    var pos=0;
-
-    if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) {
-        sep=" ";
-        subject=subject.strip();
-        subject=subject.replace(/\s+/g, sep);
-    }
-    else if (!pyjslib.isUndefined(maxsplit)) do_max=true;
-
-    if (subject.length == 0) {
-        return items;
-    }
-
-    while (start<subject.length) {
-        if (do_max && !maxsplit--) break;
-
-        pos=subject.indexOf(sep, start);
-        if (pos<0) break;
-
-        items.append(subject.substring(start, pos));
-        start=pos+sep.length;
-    }
-    if (start<=subject.length) items.append(subject.substring(start));
-
-    return items;
-}
-
-pyjslib.String___iter__ = function() {
-    var i = 0;
-    var s = this;
-    return {
-        'next': function() {
-            if (i >= s.length) {
-                throw pyjslib.StopIteration;
-            }
-            return s.substring(i++, i, 1);
-        },
-        '__iter__': function() {
-            return this;
-        }
-    };
-}
-
-pyjslib.String_strip = function(chars) {
-    return this.lstrip(chars).rstrip(chars);
-}
-
-pyjslib.String_lstrip = function(chars) {
-    if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, "");
-
-    return this.replace(new RegExp("^[" + chars + "]+"), "");
-}
-
-pyjslib.String_rstrip = function(chars) {
-    if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, "");
-
-    return this.replace(new RegExp("[" + chars + "]+$"), "");
-}
-
-pyjslib.String_startswith = function(prefix, start) {
-    if (pyjslib.isUndefined(start)) start = 0;
-
-    if (this.substring(start, prefix.length) == prefix) return true;
-    return false;
-}
-
-pyjslib.abs = Math.abs;
-
-""")
-
-class Class:
-    def __init__(self, name):
-        self.name = name
-
-    def __str___(self):
-        return self.name
-
-def eq(a,b):
-    JS("""
-    if (pyjslib.hasattr(a, "__cmp__")) {
-        return a.__cmp__(b) == 0;
-    } else if (pyjslib.hasattr(b, "__cmp__")) {
-        return b.__cmp__(a) == 0;
-    }
-    return a == b;
-    """)
-
-def cmp(a,b):
-    if hasattr(a, "__cmp__"):
-        return a.__cmp__(b)
-    elif hasattr(b, "__cmp__"):
-        return -b.__cmp__(a)
-    if a > b:
-        return 1
-    elif b > a:
-        return -1
-    else:
-        return 0
-
-def bool(v):
-    # this needs to stay in native code without any dependencies here,
-    # because this is used by if and while, we need to prevent
-    # recursion
-    JS("""
-    if (!v) return false;
-    switch(typeof v){
-    case 'boolean':
-        return v;
-    case 'object':
-        if (v.__nonzero__){
-            return v.__nonzero__();
-        }else if (v.__len__){
-            return v.__len__()>0;
-        }
-        return true;
-    }
-    return Boolean(v);
-    """)
-
-class List:
-    def __init__(self, data=None):
-        JS("""
-        this.l = [];
-        this.extend(data);
-        """)
-
-    def append(self, item):
-        JS("""    this.l[this.l.length] = item;""")
-
-    def extend(self, data):
-        JS("""
-        if (pyjslib.isArray(data)) {
-            n = this.l.length;
-            for (var i=0; i < data.length; i++) {
-                this.l[n+i]=data[i];
-                }
-            }
-        else if (pyjslib.isIteratable(data)) {
-            var iter=data.__iter__();
-            var i=this.l.length;
-            try {
-                while (true) {
-                    var item=iter.next();
-                    this.l[i++]=item;
-                    }
-                }
-            catch (e) {
-                if (e != pyjslib.StopIteration) throw e;
-                }
-            }
-        """)
-
-    def remove(self, value):
-        JS("""
-        var index=this.index(value);
-        if (index<0) return false;
-        this.l.splice(index, 1);
-        return true;
-        """)
-
-    def index(self, value, start=0):
-        JS("""
-        var length=this.l.length;
-        for (var i=start; i<length; i++) {
-            if (this.l[i]==value) {
-                return i;
-                }
-            }
-        return -1;
-        """)
-
-    def insert(self, index, value):
-        JS("""    var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
-
-    def pop(self, index = -1):
-        JS("""
-        if (index<0) index = this.l.length + index;
-        var a = this.l[index];
-        this.l.splice(index, 1);
-        return a;
-        """)
-
-    def __cmp__(self, l):
-        if not isinstance(l, List):
-            return -1
-        ll = len(self) - len(l)
-        if ll != 0:
-            return ll
-        for x in range(len(l)):
-            ll = cmp(self.__getitem__(x), l[x])
-            if ll != 0:
-                return ll
-        return 0
-
-    def slice(self, lower, upper):
-        JS("""
-        if (upper==null) return pyjslib.List(this.l.slice(lower));
-        return pyjslib.List(this.l.slice(lower, upper));
-        """)
-
-    def __getitem__(self, index):
-        JS("""
-        if (index<0) index = this.l.length + index;
-        return this.l[index];
-        """)
-
-    def __setitem__(self, index, value):
-        JS("""    this.l[index]=value;""")
-
-    def __delitem__(self, index):
-        JS("""    this.l.splice(index, 1);""")
-
-    def __len__(self):
-        JS("""    return this.l.length;""")
-
-    def __contains__(self, value):
-        return self.index(value) >= 0
-
-    def __iter__(self):
-        JS("""
-        var i = 0;
-        var l = this.l;
-        return {
-            'next': function() {
-                if (i >= l.length) {
-                    throw pyjslib.StopIteration;
-                }
-                return l[i++];
-            },
-            '__iter__': function() {
-                return this;
-            }
-        };
-        """)
-
-    def reverse(self):
-        JS("""    this.l.reverse();""")
-
-    def sort(self, compareFunc=None, keyFunc=None, reverse=False):
-        if not compareFunc:
-            global cmp
-            compareFunc = cmp
-        if keyFunc and reverse:
-            def thisSort1(a,b):
-                return -compareFunc(keyFunc(a), keyFunc(b))
-            self.l.sort(thisSort1)
-        elif keyFunc:
-            def thisSort2(a,b):
-                return compareFunc(keyFunc(a), keyFunc(b))
-            self.l.sort(thisSort2)
-        elif reverse:
-            def thisSort3(a,b):
-                return -compareFunc(a, b)
-            self.l.sort(thisSort3)
-        else:
-            self.l.sort(compareFunc)
-
-    def getArray(self):
-        """
-        Access the javascript Array that is used internally by this list
-        """
-        return self.l
-
-    def __str__(self):
-        return repr(self)
-
-list = List
-
-class Tuple:
-    def __init__(self, data=None):
-        JS("""
-        this.l = [];
-        this.extend(data);
-        """)
-
-    def append(self, item):
-        JS("""    this.l[this.l.length] = item;""")
-
-    def extend(self, data):
-        JS("""
-        if (pyjslib.isArray(data)) {
-            n = this.l.length;
-            for (var i=0; i < data.length; i++) {
-                this.l[n+i]=data[i];
-                }
-            }
-        else if (pyjslib.isIteratable(data)) {
-            var iter=data.__iter__();
-            var i=this.l.length;
-            try {
-                while (true) {
-                    var item=iter.next();
-                    this.l[i++]=item;
-                    }
-                }
-            catch (e) {
-                if (e != pyjslib.StopIteration) throw e;
-                }
-            }
-        """)
-
-    def remove(self, value):
-        JS("""
-        var index=this.index(value);
-        if (index<0) return false;
-        this.l.splice(index, 1);
-        return true;
-        """)
-
-    def index(self, value, start=0):
-        JS("""
-        var length=this.l.length;
-        for (var i=start; i<length; i++) {
-            if (this.l[i]==value) {
-                return i;
-                }
-            }
-        return -1;
-        """)
-
-    def insert(self, index, value):
-        JS("""    var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
-
-    def pop(self, index = -1):
-        JS("""
-        if (index<0) index = this.l.length + index;
-        var a = this.l[index];
-        this.l.splice(index, 1);
-        return a;
-        """)
-
-    def __cmp__(self, l):
-        if not isinstance(l, Tuple):
-            return -1
-        ll = len(self) - len(l)
-        if ll != 0:
-            return ll
-        for x in range(len(l)):
-            ll = cmp(self.__getitem__(x), l[x])
-            if ll != 0:
-                return ll
-        return 0
-
-    def slice(self, lower, upper):
-        JS("""
-        if (upper==null) return pyjslib.Tuple(this.l.slice(lower));
-        return pyjslib.Tuple(this.l.slice(lower, upper));
-        """)
-
-    def __getitem__(self, index):
-        JS("""
-        if (index<0) index = this.l.length + index;
-        return this.l[index];
-        """)
-
-    def __setitem__(self, index, value):
-        JS("""    this.l[index]=value;""")
-
-    def __delitem__(self, index):
-        JS("""    this.l.splice(index, 1);""")
-
-    def __len__(self):
-        JS("""    return this.l.length;""")
-
-    def __contains__(self, value):
-        return self.index(value) >= 0
-
-    def __iter__(self):
-        JS("""
-        var i = 0;
-        var l = this.l;
-        return {
-            'next': function() {
-                if (i >= l.length) {
-                    throw pyjslib.StopIteration;
-                }
-                return l[i++];
-            },
-            '__iter__': function() {
-                return this;
-            }
-        };
-        """)
-
-    def reverse(self):
-        JS("""    this.l.reverse();""")
-
-    def sort(self, compareFunc=None, keyFunc=None, reverse=False):
-        if not compareFunc:
-            global cmp
-            compareFunc = cmp
-        if keyFunc and reverse:
-            def thisSort1(a,b):
-                return -compareFunc(keyFunc(a), keyFunc(b))
-            self.l.sort(thisSort1)
-        elif keyFunc:
-            def thisSort2(a,b):
-                return compareFunc(keyFunc(a), keyFunc(b))
-            self.l.sort(thisSort2)
-        elif reverse:
-            def thisSort3(a,b):
-                return -compareFunc(a, b)
-            self.l.sort(thisSort3)
-        else:
-            self.l.sort(compareFunc)
-
-    def getArray(self):
-        """
-        Access the javascript Array that is used internally by this list
-        """
-        return self.l
-
-    def __str__(self):
-        return repr(self)
-
-tuple = Tuple
-
-
-class Dict:
-    def __init__(self, data=None):
-        JS("""
-        this.d = {};
-
-        if (pyjslib.isArray(data)) {
-            for (var i in data) {
-                var item=data[i];
-                this.__setitem__(item[0], item[1]);
-                //var sKey=pyjslib.hash(item[0]);
-                //this.d[sKey]=item[1];
-                }
-            }
-        else if (pyjslib.isIteratable(data)) {
-            var iter=data.__iter__();
-            try {
-                while (true) {
-                    var item=iter.next();
-                    this.__setitem__(item.__getitem__(0), item.__getitem__(1));
-                    }
-                }
-            catch (e) {
-                if (e != pyjslib.StopIteration) throw e;
-                }
-            }
-        else if (pyjslib.isObject(data)) {
-            for (var key in data) {
-                this.__setitem__(key, data[key]);
-                }
-            }
-        """)
-
-    def __setitem__(self, key, value):
-        JS("""
-        var sKey = pyjslib.hash(key);
-        this.d[sKey]=[key, value];
-        """)
-
-    def __getitem__(self, key):
-        JS("""
-        var sKey = pyjslib.hash(key);
-        var value=this.d[sKey];
-        if (pyjslib.isUndefined(value)){
-            throw pyjslib.KeyError(key);
-        }
-        return value[1];
-        """)
-
-    def __nonzero__(self):
-        JS("""
-        for (var i in this.d){
-            return true;
-        }
-        return false;
-        """)
-
-    def __len__(self):
-        JS("""
-        var size=0;
-        for (var i in this.d) size++;
-        return size;
-        """)
-
-    def has_key(self, key):
-        return self.__contains__(key)
-
-    def __delitem__(self, key):
-        JS("""
-        var sKey = pyjslib.hash(key);
-        delete this.d[sKey];
-        """)
-
-    def __contains__(self, key):
-        JS("""
-        var sKey = pyjslib.hash(key);
-        return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
-        """)
-
-    def keys(self):
-        JS("""
-        var keys=new pyjslib.List();
-        for (var key in this.d) {
-            keys.append(this.d[key][0]);
-        }
-        return keys;
-        """)
-
-    def values(self):
-        JS("""
-        var values=new pyjslib.List();
-        for (var key in this.d) values.append(this.d[key][1]);
-        return values;
-        """)
-
-    def items(self):
-        JS("""
-        var items = new pyjslib.List();
-        for (var key in this.d) {
-          var kv = this.d[key];
-          items.append(new pyjslib.List(kv))
-          }
-          return items;
-        """)
-
-    def __iter__(self):
-        return self.keys().__iter__()
-
-    def iterkeys(self):
-        return self.__iter__()
-
-    def itervalues(self):
-        return self.values().__iter__();
-
-    def iteritems(self):
-        return self.items().__iter__();
-
-    def setdefault(self, key, default_value):
-        if not self.has_key(key):
-            self[key] = default_value
-
-    def get(self, key, default_=None):
-        if not self.has_key(key):
-            return default_
-        return self[key]
-
-    def update(self, d):
-        for k,v in d.iteritems():
-            self[k] = v
-
-    def getObject(self):
-        """
-        Return the javascript Object which this class uses to store
-        dictionary keys and values
-        """
-        return self.d
-
-    def copy(self):
-        return Dict(self.items())
-
-    def __str__(self):
-        return repr(self)
-
-dict = Dict
-
-# taken from mochikit: range( [start,] stop[, step] )
-def range():
-    JS("""
-    var start = 0;
-    var stop = 0;
-    var step = 1;
-
-    if (arguments.length == 2) {
-        start = arguments[0];
-        stop = arguments[1];
-        }
-    else if (arguments.length == 3) {
-        start = arguments[0];
-        stop = arguments[1];
-        step = arguments[2];
-        }
-    else if (arguments.length>0) stop = arguments[0];
-
-    return {
-        'next': function() {
-            if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
-            var rval = start;
-            start += step;
-            return rval;
-            },
-        '__iter__': function() {
-            return this;
-            }
-        }
-    """)
-
-def slice(object, lower, upper):
-    JS("""
-    if (pyjslib.isString(object)) {
-        if (lower < 0) {
-           lower = object.length + lower;
-        }
-        if (upper < 0) {
-           upper = object.length + upper;
-        }
-        if (pyjslib.isNull(upper)) upper=object.length;
-        return object.substring(lower, upper);
-    }
-    if (pyjslib.isObject(object) && object.slice)
-        return object.slice(lower, upper);
-
-    return null;
-    """)
-
-def str(text):
-    JS("""
-    if (pyjslib.hasattr(text,"__str__")) {
-        return text.__str__();
-    }
-    return String(text);
-    """)
-
-def ord(x):
-    if(isString(x) and len(x) is 1):
-        JS("""
-            return x.charCodeAt(0);
-        """)
-    else:
-        JS("""
-            throw pyjslib.TypeError();
-        """)
-    return None
-
-def chr(x):
-    JS("""
-        return String.fromCharCode(x)
-    """)
-
-def is_basetype(x):
-    JS("""
-       var t = typeof(x);
-       return t == 'boolean' ||
-       t == 'function' ||
-       t == 'number' ||
-       t == 'string' ||
-       t == 'undefined'
-       ;
-    """)
-
-def get_pyjs_classtype(x):
-    JS("""
-       if (pyjslib.hasattr(x, "__class__"))
-           if (pyjslib.hasattr(x.__class__, "__new__"))
-               var src = x.__class__.__name__;
-               return src;
-       return null;
-    """)
-
-def repr(x):
-    """ Return the string representation of 'x'.
-    """
-    JS("""
-       if (x === null)
-           return "null";
-
-       if (x === undefined)
-           return "undefined";
-
-       var t = typeof(x);
-
-        //alert("repr typeof " + t + " : " + x);
-
-       if (t == "boolean")
-           return x.toString();
-
-       if (t == "function")
-           return "<function " + x.toString() + ">";
-
-       if (t == "number")
-           return x.toString();
-
-       if (t == "string") {
-           if (x.indexOf("'") == -1)
-               return "'" + x + "'";
-           if (x.indexOf('"') == -1)
-               return '"' + x + '"';
-           var s = x.replace(new RegExp('"', "g"), '\\\\"');
-           return '"' + s + '"';
-       };
-
-       if (t == "undefined")
-           return "undefined";
-
-       // If we get here, x is an object.  See if it's a Pyjamas class.
-
-       if (!pyjslib.hasattr(x, "__init__"))
-           return "<" + x.toString() + ">";
-
-       // Handle the common Pyjamas data types.
-
-       var constructor = "UNKNOWN";
-
-       constructor = pyjslib.get_pyjs_classtype(x);
-
-        //alert("repr constructor: " + constructor);
-
-       if (constructor == "Tuple") {
-           var contents = x.getArray();
-           var s = "(";
-           for (var i=0; i < contents.length; i++) {
-               s += pyjslib.repr(contents[i]);
-               if (i < contents.length - 1)
-                   s += ", ";
-           };
-           s += ")"
-           return s;
-       };
-
-       if (constructor == "List") {
-           var contents = x.getArray();
-           var s = "[";
-           for (var i=0; i < contents.length; i++) {
-               s += pyjslib.repr(contents[i]);
-               if (i < contents.length - 1)
-                   s += ", ";
-           };
-           s += "]"
-           return s;
-       };
-
-       if (constructor == "Dict") {
-           var keys = new Array();
-           for (var key in x.d)
-               keys.push(key);
-
-           var s = "{";
-           for (var i=0; i<keys.length; i++) {
-               var key = keys[i]
-               s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]);
-               if (i < keys.length-1)
-                   s += ", "
-           };
-           s += "}";
-           return s;
-       };
-
-       // If we get here, the class isn't one we know -> return the class name.
-       // Note that we replace underscores with dots so that the name will
-       // (hopefully!) look like the original Python name.
-
-       //var s = constructor.replace(new RegExp('_', "g"), '.');
-       return "<" + constructor + " object>";
-    """)
-
-def float(text):
-    JS("""
-    return parseFloat(text);
-    """)
-
-def int(text, radix=0):
-    JS("""
-    return parseInt(text, radix);
-    """)
-
-def len(object):
-    JS("""
-    if (object==null) return 0;
-    if (pyjslib.isObject(object) && object.__len__) return object.__len__();
-    return object.length;
-    """)
-
-def isinstance(object_, classinfo):
-    if pyjslib.isUndefined(object_):
-        return False
-    if not pyjslib.isObject(object_):
-        
-        return False
-    if _isinstance(classinfo, Tuple):
-        for ci in classinfo:
-            if isinstance(object_, ci):
-                return True
-        return False
-    else:
-        return _isinstance(object_, classinfo)
-
-def _isinstance(object_, classinfo):
-    if not pyjslib.isObject(object_):
-        return False
-    JS("""
-    if (object_.__class__){
-        var res =  object_ instanceof classinfo.constructor;
-        return res;
-    }
-    return false;
-    """)
-
-def getattr(obj, name, default_):
-    JS("""
-    if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
-        if (pyjslib.isUndefined(default_)){
-            throw pyjslib.AttributeError(obj, name);
-        }else{
-        return default_;
-        }
-    }
-    if (!pyjslib.isFunction(obj[name])) return obj[name];
-    var fnwrap = function() {
-        var args = [];
-        for (var i = 0; i < arguments.length; i++) {
-          args.push(arguments[i]);
-        }
-        return obj[name].apply(obj,args);
-        }
-    fnwrap.__name__ = name;
-    return fnwrap;
-    """)
-
-def setattr(obj, name, value):
-    JS("""
-    if (!pyjslib.isObject(obj)) return null;
-
-    obj[name] = value;
-
-    """)
-
-def hasattr(obj, name):
-    JS("""
-    if (!pyjslib.isObject(obj)) return false;
-    if (pyjslib.isUndefined(obj[name])) return false;
-
-    return true;
-    """)
-
-def dir(obj):
-    JS("""
-    var properties=new pyjslib.List();
-    for (property in obj) properties.append(property);
-    return properties;
-    """)
-
-def filter(obj, method, sequence=None):
-    # object context is LOST when a method is passed, hence object must be passed separately
-    # to emulate python behaviour, should generate this code inline rather than as a function call
-    items = []
-    if sequence is None:
-        sequence = method
-        method = obj
-
-        for item in sequence:
-            if method(item):
-                items.append(item)
-    else:
-        for item in sequence:
-            if method.call(obj, item):
-                items.append(item)
-
-    return items
-
-
-def map(obj, method, sequence=None):
-    items = []
-
-    if sequence is None:
-        sequence = method
-        method = obj
-
-        for item in sequence:
-            items.append(method(item))
-    else:
-        for item in sequence:
-            items.append(method.call(obj, item))
-
-    return items
-
-
-def enumerate(sequence):
-    enumeration = []
-    nextIndex = 0
-    for item in sequence:
-        enumeration.append([nextIndex, item])
-        nextIndex = nextIndex + 1
-    return enumeration
-
-
-def min(*sequence):
-    minValue = None
-    for item in sequence:
-        if minValue is None:
-            minValue = item
-        elif item < minValue:
-            minValue = item
-    return minValue
-
-
-def max(*sequence):
-    maxValue = None
-    for item in sequence:
-        if maxValue is None:
-            maxValue = item
-        elif item > maxValue:
-            maxValue = item
-    return maxValue
-
-
-next_hash_id = 0
-
-def hash(obj):
-    JS("""
-    if (obj == null) return null;
-
-    if (obj.$H) return obj.$H;
-    if (obj.__hash__) return obj.__hash__();
-    if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
-
-    obj.$H = ++pyjslib.next_hash_id;
-    return obj.$H;
-    """)
-
-
-# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
-def isObject(a):
-    JS("""
-    return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
-    """)
-
-def isFunction(a):
-    JS("""
-    return typeof a == 'function';
-    """)
-
-def isString(a):
-    JS("""
-    return typeof a == 'string';
-    """)
-
-def isNull(a):
-    JS("""
-    return typeof a == 'object' && !a;
-    """)
-
-def isArray(a):
-    JS("""
-    return pyjslib.isObject(a) && a.constructor == Array;
-    """)
-
-def isUndefined(a):
-    JS("""
-    return typeof a == 'undefined';
-    """)
-
-def isIteratable(a):
-    JS("""
-    return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
-    """)
-
-def isNumber(a):
-    JS("""
-    return typeof a == 'number' && isFinite(a);
-    """)
-
-def toJSObjects(x):
-    """
-       Convert the pyjs pythonic List and Dict objects into javascript Object and Array
-       objects, recursively.
-    """
-    if isArray(x):
-        JS("""
-        var result = [];
-        for(var k=0; k < x.length; k++) {
-           var v = x[k];
-           var tv = pyjslib.toJSObjects(v);
-           result.push(tv);
-        }
-        return result;
-        """)
-    if isObject(x):
-        if isinstance(x, Dict):
-            JS("""
-            var o = x.getObject();
-            var result = {};
-            for (var i in o) {
-               result[o[i][0].toString()] = o[i][1];
-            }
-            return pyjslib.toJSObjects(result)
-            """)
-        elif isinstance(x, List):
-            return toJSObjects(x.l)
-        elif hasattr(x, '__class__'):
-            # we do not have a special implementation for custom
-            # classes, just pass it on
-            return x
-    if isObject(x):
-        JS("""
-        var result = {};
-        for(var k in x) {
-            var v = x[k];
-            var tv = pyjslib.toJSObjects(v)
-            result[k] = tv;
-            }
-            return result;
-         """)
-    return x
-
-def printFunc(objs):
-    JS("""
-    if ($wnd.console==undefined)  return;
-    var s = "";
-    for(var i=0; i < objs.length; i++) {
-        if(s != "") s += " ";
-        s += objs[i];
-    }
-    console.debug(s)
-    """)
-
-def type(clsname, bases=None, methods=None):
-    """ creates a class, derived from bases, with methods and variables
-    """
-
-    JS(" var mths = {}; ")
-    if methods:
-        for k in methods.keys():
-            mth = methods[k]
-            JS(" mths[k] = mth; ")
-
-    JS(" var bss = null; ")
-    if bases:
-        JS("bss = bases.l;")
-    JS(" return pyjs_type(clsname, bss, mths); ")
-
--- a/plugins/python/modules/svgui/pyjs/lib/sys.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-# the platform name (PyV8, smjs, Mozilla, IE6, Opera, Safari etc.)
-platform = '' # to be updated by app, on compile
-
-# a dictionary of module override names (platform-specific)
-overrides = None # to be updated by app, on compile
-
-# the remote path for loading modules
-loadpath = None 
-
-stacktrace = None 
-
-appname = None 
-
-def setloadpath(lp):
-    global loadpath
-    loadpath = lp
-
-def setappname(an):
-    global appname
-    appname = an
-
-def getloadpath():
-    global loadpath
-    return loadpath
-
-def addoverride(module_name, path):
-    global overrides
-    overrides[module_name] = path
-
-def addstack(linedebug):
-    JS("""
-        if (pyjslib.bool((sys.stacktrace === null))) {
-            sys.stacktrace = new pyjslib.List([]);
-        }
-        sys.stacktrace.append(linedebug);
-    """)
-def popstack():
-    JS("""
-        sys.stacktrace.pop()
-    """)
-
-def printstack():
-    JS("""
-        var res = '';
-
-        var __l = sys.stacktrace.__iter__();
-        try {
-            while (true) {
-                var l = __l.next();
-                res +=  ( l + '\\n' ) ;
-            }
-        } catch (e) {
-            if (e != pyjslib.StopIteration) {
-                throw e;
-            }
-        }
-
-        return res;
-    """)
--- a/plugins/python/modules/svgui/pyjs/pyjs.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1777 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2006 James Tauber and contributors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-import sys
-from types import StringType
-import compiler
-from compiler import ast
-import os
-import copy
-
-# the standard location for builtins (e.g. pyjslib) can be
-# over-ridden by changing this.  it defaults to sys.prefix
-# so that on a system-wide install of pyjamas the builtins
-# can be found in e.g. {sys.prefix}/share/pyjamas
-#
-# over-rides can be done by either explicitly modifying
-# pyjs.prefix or by setting an environment variable, PYJSPREFIX.
-
-prefix = sys.prefix
-
-if os.environ.has_key('PYJSPREFIX'):
-    prefix = os.environ['PYJSPREFIX']
-
-# pyjs.path is the list of paths, just like sys.path, from which
-# library modules will be searched for, for compile purposes.
-# obviously we don't want to use sys.path because that would result
-# in compiling standard python modules into javascript!
-
-path = [os.path.abspath('')]
-
-if os.environ.has_key('PYJSPATH'):
-    for p in os.environ['PYJSPATH'].split(os.pathsep):
-        p = os.path.abspath(p)
-        if os.path.isdir(p):
-            path.append(p)
-
-# this is the python function used to wrap native javascript
-NATIVE_JS_FUNC_NAME = "JS"
-
-UU = ""
-
-PYJSLIB_BUILTIN_FUNCTIONS=("cmp",
-                           "map",
-                           "filter",
-                           "dir",
-                           "getattr",
-                           "setattr",
-                           "hasattr",
-                           "int",
-                           "float",
-                           "str",
-                           "repr",
-                           "range",
-                           "len",
-                           "hash",
-                           "abs",
-                           "ord",
-                           "chr",
-                           "enumerate",
-                           "min",
-                           "max",
-                           "bool",
-                           "type",
-                           "isinstance")
-
-PYJSLIB_BUILTIN_CLASSES=("BaseException",
-                         "Exception",
-                         "StandardError",
-                         "StopIteration",
-                         "AttributeError",
-                         "TypeError",
-                         "KeyError",
-                         "LookupError",
-                         "list",
-                         "dict",
-                         "object",
-                         "tuple",
-                        )
-
-def pyjs_builtin_remap(name):
-    # XXX HACK!
-    if name == 'list':
-        name = 'List'
-    if name == 'object':
-        name = '__Object'
-    if name == 'dict':
-        name = 'Dict'
-    if name == 'tuple':
-        name = 'Tuple'
-    return name
-
-# XXX: this is a hack: these should be dealt with another way
-# however, console is currently the only global name which is causing
-# problems.
-PYJS_GLOBAL_VARS=("console")
-
-# This is taken from the django project.
-# Escape every ASCII character with a value less than 32.
-JS_ESCAPES = (
-    ('\\', r'\x5C'),
-    ('\'', r'\x27'),
-    ('"', r'\x22'),
-    ('>', r'\x3E'),
-    ('<', r'\x3C'),
-    ('&', r'\x26'),
-    (';', r'\x3B')
-    ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)])
-
-def escapejs(value):
-    """Hex encodes characters for use in JavaScript strings."""
-    for bad, good in JS_ESCAPES:
-        value = value.replace(bad, good)
-    return value
-
-def uuprefix(name, leave_alone=0):
-    name = name.split(".")
-    name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:])
-    return '.'.join(name)
-
-class Klass:
-
-    klasses = {}
-
-    def __init__(self, name, name_):
-        self.name = name
-        self.name_ = name_
-        self.klasses[name] = self
-        self.functions = set()
-
-    def set_base(self, base_name):
-        self.base = self.klasses.get(base_name)
-
-    def add_function(self, function_name):
-        self.functions.add(function_name)
-
-
-class TranslationError(Exception):
-    def __init__(self, message, node):
-        self.message = "line %s:\n%s\n%s" % (node.lineno, message, node)
-
-    def __str__(self):
-        return self.message
-
-def strip_py(name):
-    return name
-
-def mod_var_name_decl(raw_module_name):
-    """ function to get the last component of the module e.g.
-        pyjamas.ui.DOM into the "namespace".  i.e. doing
-        "import pyjamas.ui.DOM" actually ends up with _two_
-        variables - one pyjamas.ui.DOM, the other just "DOM".
-        but "DOM" is actually local, hence the "var" prefix.
-
-        for PyV8, this might end up causing problems - we'll have
-        to see: gen_mod_import and mod_var_name_decl might have
-        to end up in a library-specific module, somewhere.
-    """
-    name = raw_module_name.split(".")
-    if len(name) == 1:
-        return ''
-    child_name = name[-1]
-    return "var %s = %s;\n" % (child_name, raw_module_name)
-
-def gen_mod_import(parentName, importName, dynamic=1):
-    #pyjs_ajax_eval("%(n)s.cache.js", null, true);
-    return """
-    pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false);
-    """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \
-    mod_var_name_decl(importName)
-
-class Translator:
-
-    def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output,
-                 dynamic=0, optimize=False,
-                 findFile=None):
-
-        if module_name:
-            self.module_prefix = module_name + "."
-        else:
-            self.module_prefix = ""
-        self.raw_module_name = raw_module_name
-        src = src.replace("\r\n", "\n")
-        src = src.replace("\n\r", "\n")
-        src = src.replace("\r",   "\n")
-        self.src = src.split("\n")
-        self.debug = debug
-        self.imported_modules = []
-        self.imported_modules_as = []
-        self.imported_js = set()
-        self.top_level_functions = set()
-        self.top_level_classes = set()
-        self.top_level_vars = set()
-        self.local_arg_stack = [[]]
-        self.output = output
-        self.imported_classes = {}
-        self.method_imported_globals = set()
-        self.method_self = None
-        self.nextTupleAssignID = 1
-        self.dynamic = dynamic
-        self.optimize = optimize
-        self.findFile = findFile
-
-        if module_name.find(".") >= 0:
-            vdec = ''
-        else:
-            vdec = 'var '
-        print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name)
-
-        print >>self.output, "    if("+module_name+".__was_initialized__) return;"
-        print >>self.output, "    "+UU+module_name+".__was_initialized__ = true;"
-        print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn)
-        print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name)
-
-        decl = mod_var_name_decl(raw_module_name)
-        if decl:
-            print >>self.output, decl
-
-
-        if self.debug:
-            haltException = self.module_prefix + "HaltException"
-            print >>self.output, haltException + ' = function () {'
-            print >>self.output, '  this.message = "Program Halted";'
-            print >>self.output, '  this.name = "' + haltException + '";'
-            print >>self.output, '}'
-            print >>self.output, ''
-            print >>self.output, haltException + ".prototype.__str__ = function()"
-            print >>self.output, '{'
-            print >>self.output, 'return this.message ;'
-            print >>self.output, '}'
-
-            print >>self.output, haltException + ".prototype.toString = function()"
-            print >>self.output, '{'
-            print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";'
-            print >>self.output, '}'
-
-            isHaltFunction = self.module_prefix + "IsHaltException"
-            print >>self.output, """
-    %s = function (s) {
-      var suffix="HaltException";
-      if (s.length < suffix.length) {
-        //alert(s + " " + suffix);
-        return false;
-      } else {
-        var ss = s.substring(s.length, (s.length - suffix.length));
-        //alert(s + " " + suffix + " " + ss);
-        return ss == suffix;
-      }
-    }
-                """ % isHaltFunction
-        for child in mod.node:
-            if isinstance(child, ast.Function):
-                self.top_level_functions.add(child.name)
-            elif isinstance(child, ast.Class):
-                self.top_level_classes.add(child.name)
-
-        for child in mod.node:
-            if isinstance(child, ast.Function):
-                self._function(child, False)
-            elif isinstance(child, ast.Class):
-                self._class(child)
-            elif isinstance(child, ast.Import):
-                importName = child.names[0][0]
-                if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
-                    pass
-                elif importName.endswith('.js'):
-                   self.imported_js.add(importName)
-                else:
-                   self.add_imported_module(strip_py(importName))
-            elif isinstance(child, ast.From):
-                if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter
-                    pass
-                else:
-                    self.add_imported_module(child.modname)
-                    self._from(child)
-            elif isinstance(child, ast.Discard):
-                self._discard(child, None)
-            elif isinstance(child, ast.Assign):
-                self._assign(child, None, True)
-            elif isinstance(child, ast.AugAssign):
-                self._augassign(child, None)
-            elif isinstance(child, ast.If):
-                self._if(child, None)
-            elif isinstance(child, ast.For):
-                self._for(child, None)
-            elif isinstance(child, ast.While):
-                self._while(child, None)
-            elif isinstance(child, ast.Subscript):
-                self._subscript_stmt(child, None)
-            elif isinstance(child, ast.Global):
-                self._global(child, None)
-            elif isinstance(child, ast.Printnl):
-               self._print(child, None)
-            elif isinstance(child, ast.Print):
-               self._print(child, None)
-            elif isinstance(child, ast.TryExcept):
-                self._tryExcept(child, None)
-            elif isinstance(child, ast.Raise):
-                self._raise(child, None)
-            elif isinstance(child, ast.Stmt):
-                self._stmt(child, None)
-            else:
-                raise TranslationError("unsupported type (in __init__)", child)
-
-        # Initialize all classes for this module
-        #print >> self.output, "__"+self.modpfx()+\
-        #          "classes_initialize = function() {\n"
-        #for className in self.top_level_classes:
-        #    print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();"
-        #print >> self.output, "};\n"
-
-        print >> self.output, "return this;\n"
-        print >> self.output, "}; /* end %s */ \n"  % module_name
-
-    def module_imports(self):
-        return self.imported_modules + self.imported_modules_as
-
-    def add_local_arg(self, varname):
-        local_vars = self.local_arg_stack[-1]
-        if varname not in local_vars:
-            local_vars.append(varname)
-
-    def add_imported_module(self, importName):
-
-        if importName in self.imported_modules:
-            return
-        self.imported_modules.append(importName)
-        name = importName.split(".")
-        if len(name) != 1:
-            # add the name of the module to the namespace,
-            # but don't add the short name to imported_modules
-            # because then the short name would be attempted to be
-            # added to the dependencies, and it's half way up the
-            # module import directory structure!
-            child_name = name[-1]
-            self.imported_modules_as.append(child_name) 
-        print >> self.output, gen_mod_import(self.raw_module_name,
-                                             strip_py(importName),
-                                             self.dynamic)
-
-    def _default_args_handler(self, node, arg_names, current_klass,
-                              output=None):
-        if len(node.defaults):
-            output = output or self.output
-            default_pos = len(arg_names) - len(node.defaults)
-            if arg_names and arg_names[0] == self.method_self:
-                default_pos -= 1
-            for default_node in node.defaults:
-                if isinstance(default_node, ast.Const):
-                    default_value = self._const(default_node)
-                elif isinstance(default_node, ast.Name):
-                    default_value = self._name(default_node, current_klass)
-                elif isinstance(default_node, ast.UnarySub):
-                    default_value = self._unarysub(default_node, current_klass)
-                else:
-                    raise TranslationError("unsupported type (in _method)", default_node)
-
-                default_name = arg_names[default_pos]
-                default_pos += 1
-                print >> output, "    if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value)
-
-    def _varargs_handler(self, node, varargname, arg_names, current_klass):
-        print >>self.output, "    var", varargname, '= new pyjslib.Tuple();'
-        print >>self.output, "    for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {"
-        print >>self.output, "        var __arg = arguments[__va_arg];"
-        print >>self.output, "        "+varargname+".append(__arg);"
-        print >>self.output, "    }"
-
-    def _kwargs_parser(self, node, function_name, arg_names, current_klass):
-        if len(node.defaults) or node.kwargs:
-            default_pos = len(arg_names) - len(node.defaults)
-            if arg_names and arg_names[0] == self.method_self:
-                default_pos -= 1
-            print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {"
-            for default_node in node.defaults:
-                default_value = self.expr(default_node, current_klass)
-#                if isinstance(default_node, ast.Const):
-#                    default_value = self._const(default_node)
-#                elif isinstance(default_node, ast.Name):
-#                    default_value = self._name(default_node)
-#                elif isinstance(default_node, ast.UnarySub):
-#                    default_value = self._unarysub(default_node, current_klass)
-#                else:
-#                    raise TranslationError("unsupported type (in _method)", default_node)
-
-                default_name = arg_names[default_pos]
-                print >>self.output, "    if (typeof %s == 'undefined')"%(default_name)
-                print >>self.output, "        %s=__kwargs.%s;"% (default_name, default_name)
-                default_pos += 1
-
-            #self._default_args_handler(node, arg_names, current_klass)
-            if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"]
-            print >>self.output, "    var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";"
-            if node.varargs:
-                self._varargs_handler(node, "__args", arg_names, current_klass)
-                print >>self.output, "    __r.push.apply(__r, __args.getArray())"
-            print >>self.output, "    return __r;"
-            print >>self.output, "};"
-
-    def _function(self, node, local=False):
-        if local:
-            function_name = node.name
-            self.add_local_arg(function_name)
-        else:
-            function_name = UU + self.modpfx() + node.name
-
-        arg_names = list(node.argnames)
-        normal_arg_names = list(arg_names)
-        if node.kwargs: kwargname = normal_arg_names.pop()
-        if node.varargs: varargname = normal_arg_names.pop()
-        declared_arg_names = list(normal_arg_names)
-        if node.kwargs: declared_arg_names.append(kwargname)
-
-        function_args = "(" + ", ".join(declared_arg_names) + ")"
-        print >>self.output, "%s = function%s {" % (function_name, function_args)
-        self._default_args_handler(node, normal_arg_names, None)
-
-        local_arg_names = normal_arg_names + declared_arg_names 
-
-        if node.varargs:
-            self._varargs_handler(node, varargname, declared_arg_names, None)
-            local_arg_names.append(varargname)
-
-        # stack of local variable names for this function call
-        self.local_arg_stack.append(local_arg_names)
-
-        for child in node.code:
-            self._stmt(child, None)
-
-        # remove the top local arg names
-        self.local_arg_stack.pop()
-
-        # we need to return null always, so it is not undefined
-        lastStmt = [p for p in node.code][-1]
-        if not isinstance(lastStmt, ast.Return):
-            if not self._isNativeFunc(lastStmt):
-                print >>self.output, "    return null;"
-
-        print >>self.output, "};"
-        print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name)
-
-
-        self._kwargs_parser(node, function_name, normal_arg_names, None)
-
-
-    def _return(self, node, current_klass):
-        expr = self.expr(node.value, current_klass)
-        # in python a function call always returns None, so we do it
-        # here too
-        print >>self.output, "    return " + expr + ";"
-
-
-    def _break(self, node, current_klass):
-        print >>self.output, "    break;"
-
-
-    def _continue(self, node, current_klass):
-        print >>self.output, "    continue;"
-
-
-    def _callfunc(self, v, current_klass):
-
-        if isinstance(v.node, ast.Name):
-            if v.node.name in self.top_level_functions:
-                call_name = self.modpfx() + v.node.name
-            elif v.node.name in self.top_level_classes:
-                call_name = self.modpfx() + v.node.name
-            elif self.imported_classes.has_key(v.node.name):
-                call_name = self.imported_classes[v.node.name] + '.' + v.node.name
-            elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS:
-                call_name = 'pyjslib.' + v.node.name
-            elif v.node.name in PYJSLIB_BUILTIN_CLASSES:
-                name = pyjs_builtin_remap(v.node.name)
-                call_name = 'pyjslib.' + name
-            elif v.node.name == "callable":
-                call_name = "pyjslib.isFunction"
-            else:
-                call_name = v.node.name
-            call_args = []
-        elif isinstance(v.node, ast.Getattr):
-            attr_name = v.node.attrname
-
-            if isinstance(v.node.expr, ast.Name):
-                call_name = self._name2(v.node.expr, current_klass, attr_name)
-                call_args = []
-            elif isinstance(v.node.expr, ast.Getattr):
-                call_name = self._getattr2(v.node.expr, current_klass, attr_name)
-                call_args = []
-            elif isinstance(v.node.expr, ast.CallFunc):
-                call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname
-                call_args = []
-            elif isinstance(v.node.expr, ast.Subscript):
-                call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname
-                call_args = []
-            elif isinstance(v.node.expr, ast.Const):
-                call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname
-                call_args = []
-            else:
-                raise TranslationError("unsupported type (in _callfunc)", v.node.expr)
-        else:
-            raise TranslationError("unsupported type (in _callfunc)", v.node)
-
-        call_name = strip_py(call_name)
-
-        kwargs = []
-        star_arg_name = None
-        if v.star_args:
-            star_arg_name = self.expr(v.star_args, current_klass)
-
-        for ch4 in v.args:
-            if isinstance(ch4, ast.Keyword):
-                kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass)
-                kwargs.append(kwarg)
-            else:
-                arg = self.expr(ch4, current_klass)
-                call_args.append(arg)
-
-        if kwargs:
-            fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args)
-        else:
-            fn_args = ", ".join(call_args)
-
-        if kwargs or star_arg_name:
-            if not star_arg_name:
-                star_arg_name = 'null'
-            try: call_this, method_name = call_name.rsplit(".", 1)
-            except ValueError:
-                # Must be a function call ...
-                return ("pyjs_kwargs_function_call("+call_name+", "
-                                  + star_arg_name 
-                                  + ", ["+fn_args+"]"
-                                  + ")" )
-            else:
-                return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', "
-                                  + star_arg_name 
-                                  + ", ["+fn_args+"]"
-                                  + ")")
-        else:
-            return call_name + "(" + ", ".join(call_args) + ")"
-
-    def _print(self, node, current_klass):
-        if self.optimize:
-            return
-        call_args = []
-        for ch4 in node.nodes:
-            arg = self.expr(ch4, current_klass)
-            call_args.append(arg)
-
-        print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");"
-
-    def _tryExcept(self, node, current_klass):
-        if len(node.handlers) != 1:
-            raise TranslationError("except statements in this form are" +
-                                   " not supported", node)
-
-        expr = node.handlers[0][0]
-        as_ = node.handlers[0][1]
-        if as_:
-            errName = as_.name
-        else:
-            errName = 'err'
-
-        # XXX TODO: check that this should instead be added as a _separate_
-        # local scope, temporary to the function.  oh dearie me.
-        self.add_local_arg(errName)
-
-        print >>self.output, "    try {"
-        for stmt in node.body.nodes:
-            self._stmt(stmt, current_klass)
-        print >> self.output, "    } catch(%s) {" % errName
-        if expr:
-            l = []
-            if isinstance(expr, ast.Tuple):
-                for x in expr.nodes:
-                    l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass)))
-            else:
-                l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ]
-            print >> self.output, "   if(%s) {" % '||\n\t\t'.join(l)
-        for stmt in node.handlers[0][2]:
-            self._stmt(stmt, current_klass)
-        if expr:
-            #print >> self.output, "} else { throw(%s); } " % errName
-            print >> self.output, "}"
-        if node.else_ != None:
-            print >>self.output, "    } finally {"
-            for stmt in node.else_:
-                self._stmt(stmt, current_klass)
-        print >>self.output, "    }"
-
-    # XXX: change use_getattr to True to enable "strict" compilation
-    # but incurring a 100% performance penalty. oops.
-    def _getattr(self, v, current_klass, use_getattr=False):
-        attr_name = v.attrname
-        if isinstance(v.expr, ast.Name):
-            obj = self._name(v.expr, current_klass, return_none_for_module=True)
-            if obj == None and v.expr.name in self.module_imports():
-                # XXX TODO: distinguish between module import classes
-                # and variables.  right now, this is a hack to get
-                # the sys module working.
-                #if v.expr.name == 'sys':
-                return v.expr.name+'.'+attr_name
-                #return v.expr.name+'.__'+attr_name+'.prototype.__class__'
-            if not use_getattr or attr_name == '__class__' or \
-                    attr_name == '__name__':
-                return obj + "." + attr_name
-            return "pyjslib.getattr(%s, '%s')" % (obj, attr_name)
-        elif isinstance(v.expr, ast.Getattr):
-            return self._getattr(v.expr, current_klass) + "." + attr_name
-        elif isinstance(v.expr, ast.Subscript):
-            return self._subscript(v.expr, self.modpfx()) + "." + attr_name
-        elif isinstance(v.expr, ast.CallFunc):
-            return self._callfunc(v.expr, self.modpfx()) + "." + attr_name
-        else:
-            raise TranslationError("unsupported type (in _getattr)", v.expr)
-
-
-    def modpfx(self):
-        return strip_py(self.module_prefix)
-        
-    def _name(self, v, current_klass, top_level=False,
-                                      return_none_for_module=False):
-
-        if v.name == 'ilikesillynamesfornicedebugcode':
-            print top_level, current_klass, repr(v)
-            print self.top_level_vars
-            print self.top_level_functions
-            print self.local_arg_stack
-            print "error..."
-
-        local_var_names = None
-        las = len(self.local_arg_stack)
-        if las > 0:
-            local_var_names = self.local_arg_stack[-1]
-
-        if v.name == "True":
-            return "true"
-        elif v.name == "False":
-            return "false"
-        elif v.name == "None":
-            return "null"
-        elif v.name == '__name__' and current_klass is None:
-            return self.modpfx() + v.name
-        elif v.name == self.method_self:
-            return "this"
-        elif v.name in self.top_level_functions:
-            return UU+self.modpfx() + v.name
-        elif v.name in self.method_imported_globals:
-            return UU+self.modpfx() + v.name
-        elif not current_klass and las == 1 and v.name in self.top_level_vars:
-            return UU+self.modpfx() + v.name
-        elif v.name in local_var_names:
-            return v.name
-        elif self.imported_classes.has_key(v.name):
-            return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__"
-        elif v.name in self.top_level_classes:
-            return UU+self.modpfx() + "__" + v.name + ".prototype.__class__"
-        elif v.name in self.module_imports() and return_none_for_module:
-            return None
-        elif v.name in PYJSLIB_BUILTIN_CLASSES:
-            return "pyjslib." + pyjs_builtin_remap( v.name )
-        elif current_klass:
-            if v.name not in local_var_names and \
-               v.name not in self.top_level_vars and \
-               v.name not in PYJS_GLOBAL_VARS and \
-               v.name not in self.top_level_functions:
-
-                cls_name = current_klass
-                if hasattr(cls_name, "name"):
-                    cls_name_ = cls_name.name_
-                    cls_name = cls_name.name
-                else:
-                    cls_name_ = current_klass + "_" # XXX ???
-                name = UU+cls_name_ + ".prototype.__class__." \
-                                   + v.name
-                if v.name == 'listener':
-                    name = 'listener+' + name
-                return name
-
-        return v.name
-
-    def _name2(self, v, current_klass, attr_name):
-        obj = v.name
-
-        if obj in self.method_imported_globals:
-            call_name = UU+self.modpfx() + obj + "." + attr_name
-        elif self.imported_classes.has_key(obj):
-            #attr_str = ""
-            #if attr_name != "__init__":
-            attr_str = ".prototype.__class__." + attr_name
-            call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str
-        elif obj in self.module_imports():
-            call_name = obj + "." + attr_name
-        elif obj[0] == obj[0].upper(): # XXX HACK ALERT
-            call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name
-        else:
-            call_name = UU+self._name(v, current_klass) + "." + attr_name
-
-        return call_name
-
-
-    def _getattr2(self, v, current_klass, attr_name):
-        if isinstance(v.expr, ast.Getattr):
-            call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name)
-        elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports():
-            call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name
-        else:
-            obj = self.expr(v.expr, current_klass)
-            call_name = obj + "." + v.attrname + "." + attr_name
-
-        return call_name
-
-
-    def _class(self, node):
-        """
-        Handle a class definition.
-
-        In order to translate python semantics reasonably well, the following
-        structure is used:
-
-        A special object is created for the class, which inherits attributes
-        from the superclass, or Object if there's no superclass.  This is the
-        class object; the object which you refer to when specifying the
-        class by name.  Static, class, and unbound methods are copied
-        from the superclass object.
-
-        A special constructor function is created with the same name as the
-        class, which is used to create instances of that class.
-
-        A javascript class (e.g. a function with a prototype attribute) is
-        created which is the javascript class of created instances, and
-        which inherits attributes from the class object. Bound methods are
-        copied from the superclass into this class rather than inherited,
-        because the class object contains unbound, class, and static methods
-        that we don't necessarily want to inherit.
-
-        The type of a method can now be determined by inspecting its
-        static_method, unbound_method, class_method, or instance_method
-        attribute; only one of these should be true.
-
-        Much of this work is done in pyjs_extend, is pyjslib.py
-        """
-        class_name = self.modpfx() + uuprefix(node.name, 1)
-        class_name_ = self.modpfx() + uuprefix(node.name)
-        current_klass = Klass(class_name, class_name_)
-        init_method = None
-        for child in node.code:
-            if isinstance(child, ast.Function):
-                current_klass.add_function(child.name)
-                if child.name == "__init__":
-                    init_method = child
-
-
-        if len(node.bases) == 0:
-            base_class = "pyjslib.__Object"
-        elif len(node.bases) == 1:
-            if isinstance(node.bases[0], ast.Name):
-                if self.imported_classes.has_key(node.bases[0].name):
-                    base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name
-                    base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name
-                else:
-                    base_class_ = self.modpfx() + "__" + node.bases[0].name
-                    base_class = self.modpfx() + node.bases[0].name
-            elif isinstance(node.bases[0], ast.Getattr):
-                # the bases are not in scope of the class so do not
-                # pass our class to self._name
-                base_class_ = self._name(node.bases[0].expr, None) + \
-                             ".__" + node.bases[0].attrname
-                base_class = self._name(node.bases[0].expr, None) + \
-                             "." + node.bases[0].attrname
-            else:
-                raise TranslationError("unsupported type (in _class)", node.bases[0])
-
-            current_klass.set_base(base_class)
-        else:
-            raise TranslationError("more than one base (in _class)", node)
-
-        print >>self.output, UU+class_name_ + " = function () {"
-        # call superconstructor
-        #if base_class:
-        #    print >>self.output, "    __" + base_class + ".call(this);"
-        print >>self.output, "}"
-
-        if not init_method:
-            init_method = ast.Function([], "__init__", ["self"], [], 0, None, [])
-            #self._method(init_method, current_klass, class_name)
-
-        # Generate a function which constructs the object
-        clsfunc = ast.Function([],
-           node.name,
-           init_method.argnames[1:],
-           init_method.defaults,
-           init_method.flags,
-           None,
-           [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const(
-#            I attempted lazy initialization, but then you can't access static class members
-#            "    if(!__"+base_class+".__was_initialized__)"+
-#            "        __" + class_name + "_initialize();\n" +
-            "    var instance = new " + UU + class_name_ + "();\n" +
-            "    if(instance.__init__) instance.__init__.apply(instance, arguments);\n" +
-            "    return instance;"
-            )]))])
-
-        self._function(clsfunc, False)
-        print >>self.output, UU+class_name_ + ".__initialize__ = function () {"
-        print >>self.output, "    if("+UU+class_name_+".__was_initialized__) return;"
-        print >>self.output, "    "+UU+class_name_+".__was_initialized__ = true;"
-        cls_obj = UU+class_name_ + '.prototype.__class__'
-
-        if class_name == "pyjslib.__Object":
-            print >>self.output, "    "+cls_obj+" = {};"
-        else:
-            if base_class and base_class not in ("object", "pyjslib.__Object"):
-                print >>self.output, "    if(!"+UU+base_class_+".__was_initialized__)"
-                print >>self.output, "        "+UU+base_class_+".__initialize__();"
-                print >>self.output, "    pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");"
-            else:
-                print >>self.output, "    pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);"
-
-        print >>self.output, "    "+cls_obj+".__new__ = "+UU+class_name+";"
-        print >>self.output, "    "+cls_obj+".__name__ = '"+UU+node.name+"';"
-
-        for child in node.code:
-            if isinstance(child, ast.Pass):
-                pass
-            elif isinstance(child, ast.Function):
-                self._method(child, current_klass, class_name, class_name_)
-            elif isinstance(child, ast.Assign):
-                self.classattr(child, current_klass)
-            elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const):
-                # Probably a docstring, turf it
-                pass
-            else:
-                raise TranslationError("unsupported type (in _class)", child)
-        print >>self.output, "}"
-
-        print >> self.output, class_name_+".__initialize__();"
-
-
-    def classattr(self, node, current_klass):
-        self._assign(node, current_klass, True)
-
-    def _raise(self, node, current_klass):
-        if node.expr2:
-            raise TranslationError("More than one expression unsupported",
-                                   node)
-        print >> self.output, "throw (%s);" % self.expr(
-            node.expr1, current_klass)
-
-    def _method(self, node, current_klass, class_name, class_name_):
-        # reset global var scope
-        self.method_imported_globals = set()
-
-        arg_names = list(node.argnames)
-
-        classmethod = False
-        staticmethod = False
-        if node.decorators:
-            for d in node.decorators:
-                if d.name == "classmethod":
-                    classmethod = True
-                elif d.name == "staticmethod":
-                    staticmethod = True
-
-        if staticmethod:
-            staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno)
-            self._function(staticfunc, True)
-            print >>self.output, "    " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";";
-            print >>self.output, "    " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;";
-            return
-        else:
-            if len(arg_names) == 0:
-                raise TranslationError("methods must take an argument 'self' (in _method)", node)
-            self.method_self = arg_names[0]
-
-            #if not classmethod and arg_names[0] != "self":
-            #    raise TranslationError("first arg not 'self' (in _method)", node)
-
-        normal_arg_names = arg_names[1:]
-        if node.kwargs: kwargname = normal_arg_names.pop()
-        if node.varargs: varargname = normal_arg_names.pop()
-        declared_arg_names = list(normal_arg_names)
-        if node.kwargs: declared_arg_names.append(kwargname)
-
-        function_args = "(" + ", ".join(declared_arg_names) + ")"
-
-        if classmethod:
-            fexpr = UU + class_name_ + ".prototype.__class__." + node.name
-        else:
-            fexpr = UU + class_name_ + ".prototype." + node.name
-        print >>self.output, "    "+fexpr + " = function" + function_args + " {"
-
-        # default arguments
-        self._default_args_handler(node, normal_arg_names, current_klass)
-
-        local_arg_names = normal_arg_names + declared_arg_names 
-
-        if node.varargs:
-            self._varargs_handler(node, varargname, declared_arg_names, current_klass)
-            local_arg_names.append(varargname)
-
-
-        # stack of local variable names for this function call
-        self.local_arg_stack.append(local_arg_names)
-
-        for child in node.code:
-            self._stmt(child, current_klass)
-
-        # remove the top local arg names
-        self.local_arg_stack.pop()
-
-        print >>self.output, "    };"
-
-        self._kwargs_parser(node, fexpr, normal_arg_names, current_klass)
-
-        if classmethod:
-            # Have to create a version on the instances which automatically passes the
-            # class as "self"
-            altexpr = UU + class_name_ + ".prototype." + node.name
-            print >>self.output, "    "+altexpr + " = function() {"
-            print >>self.output, "        return " + fexpr + ".apply(this.__class__, arguments);"
-            print >>self.output, "    };"
-            print >>self.output, "    "+fexpr+".class_method = true;"
-            print >>self.output, "    "+altexpr+".instance_method = true;"
-        else:
-            # For instance methods, we need an unbound version in the class object
-            altexpr = UU + class_name_ + ".prototype.__class__." + node.name
-            print >>self.output, "    "+altexpr + " = function() {"
-            print >>self.output, "        return " + fexpr + ".call.apply("+fexpr+", arguments);"
-            print >>self.output, "    };"
-            print >>self.output, "    "+altexpr+".unbound_method = true;"
-            print >>self.output, "    "+fexpr+".instance_method = true;"
-            print >>self.output, "    "+altexpr+".__name__ = '%s';" % node.name
-
-        print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \
-                (node.name, node.name)
-
-        if node.kwargs or len(node.defaults):
-            print >>self.output, "    "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;"
-
-        self.method_self = None
-        self.method_imported_globals = set()
-
-    def _isNativeFunc(self, node):
-        if isinstance(node, ast.Discard):
-            if isinstance(node.expr, ast.CallFunc):
-                if isinstance(node.expr.node, ast.Name) and \
-                       node.expr.node.name == NATIVE_JS_FUNC_NAME:
-                    return True
-        return False
-
-    def _stmt(self, node, current_klass):
-        debugStmt = self.debug and not self._isNativeFunc(node)
-        if debugStmt:
-            print >>self.output, '  try {'
-
-        if isinstance(node, ast.Return):
-            self._return(node, current_klass)
-        elif isinstance(node, ast.Break):
-            self._break(node, current_klass)
-        elif isinstance(node, ast.Continue):
-            self._continue(node, current_klass)
-        elif isinstance(node, ast.Assign):
-            self._assign(node, current_klass)
-        elif isinstance(node, ast.AugAssign):
-            self._augassign(node, current_klass)
-        elif isinstance(node, ast.Discard):
-            self._discard(node, current_klass)
-        elif isinstance(node, ast.If):
-            self._if(node, current_klass)
-        elif isinstance(node, ast.For):
-            self._for(node, current_klass)
-        elif isinstance(node, ast.While):
-            self._while(node, current_klass)
-        elif isinstance(node, ast.Subscript):
-            self._subscript_stmt(node, current_klass)
-        elif isinstance(node, ast.Global):
-            self._global(node, current_klass)
-        elif isinstance(node, ast.Pass):
-            pass
-        elif isinstance(node, ast.Function):
-            self._function(node, True)
-        elif isinstance(node, ast.Printnl):
-           self._print(node, current_klass)
-        elif isinstance(node, ast.Print):
-           self._print(node, current_klass)
-        elif isinstance(node, ast.TryExcept):
-            self._tryExcept(node, current_klass)
-        elif isinstance(node, ast.Raise):
-            self._raise(node, current_klass)
-        else:
-            raise TranslationError("unsupported type (in _stmt)", node)
-
-        if debugStmt:
-
-            lt = self.get_line_trace(node)
-
-            haltException = self.module_prefix + "HaltException"
-            isHaltFunction = self.module_prefix + "IsHaltException"
-
-            print >>self.output, '  } catch (__err) {'
-            print >>self.output, '      if (' + isHaltFunction + '(__err.name)) {'
-            print >>self.output, '          throw __err;'
-            print >>self.output, '      } else {'
-            print >>self.output, "          st = sys.printstack() + "\
-                                                + '"%s"' % lt + "+ '\\n' ;"
-            print >>self.output, '          alert("' + "Error in " \
-                                                + lt + '"' \
-                                                + '+"\\n"+__err.name+": "+__err.message'\
-                                                + '+"\\n\\nStack trace:\\n"' \
-                                                + '+st' \
-                                                + ');'
-            print >>self.output, '          debugger;'
-
-            print >>self.output, '          throw new ' + self.module_prefix + "HaltException();"
-            print >>self.output, '      }'
-            print >>self.output, '  }'
-
-
-    def get_line_trace(self, node):
-        lineNum = "Unknown"
-        srcLine = ""
-        if hasattr(node, "lineno"):
-            if node.lineno != None:
-                lineNum = node.lineno
-                srcLine = self.src[min(lineNum, len(self.src))-1]
-                srcLine = srcLine.replace('\\', '\\\\')
-                srcLine = srcLine.replace('"', '\\"')
-                srcLine = srcLine.replace("'", "\\'")
-
-        return self.raw_module_name + ".py, line " \
-               + str(lineNum) + ":"\
-               + "\\n" \
-               + "    " + srcLine
-
-    def _augassign(self, node, current_klass):
-        v = node.node
-        if isinstance(v, ast.Getattr):
-            # XXX HACK!  don't allow += on return result of getattr.
-            # TODO: create a temporary variable or something.
-            lhs = self._getattr(v, current_klass, False)
-        else:
-            lhs = self._name(node.node, current_klass)
-        op = node.op
-        rhs = self.expr(node.expr, current_klass)
-        print >>self.output, "    " + lhs + " " + op + " " + rhs + ";"
-
-
-    def _assign(self, node, current_klass, top_level = False):
-        if len(node.nodes) != 1:
-            tempvar = '__temp'+str(node.lineno)
-            tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno)
-            self._assign(tnode, current_klass, top_level)
-            for v in node.nodes:
-               tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno)
-               self._assign(tnode2, current_klass, top_level)
-            return
-
-        local_var_names = None
-        if len(self.local_arg_stack) > 0:
-            local_var_names = self.local_arg_stack[-1]
-
-        def _lhsFromAttr(v, current_klass):
-            attr_name = v.attrname
-            if isinstance(v.expr, ast.Name):
-                obj = v.expr.name
-                lhs = self._name(v.expr, current_klass) + "." + attr_name
-            elif isinstance(v.expr, ast.Getattr):
-                lhs = self._getattr(v, current_klass)
-            elif isinstance(v.expr, ast.Subscript):
-                lhs = self._subscript(v.expr, current_klass) + "." + attr_name
-            else:
-                raise TranslationError("unsupported type (in _assign)", v.expr)
-            return lhs
-
-        def _lhsFromName(v, top_level, current_klass):
-            if top_level:
-                if current_klass:
-                    lhs = UU+current_klass.name_ + ".prototype.__class__." \
-                               + v.name
-                else:
-                    self.top_level_vars.add(v.name)
-                    vname = self.modpfx() + v.name
-                    if not self.modpfx() and v.name not in\
-                           self.method_imported_globals:
-                        lhs = "var " + vname
-                    else:
-                        lhs = UU + vname
-                    self.add_local_arg(v.name)
-            else:
-                if v.name in local_var_names:
-                    lhs = v.name
-                elif v.name in self.method_imported_globals:
-                    lhs = self.modpfx() + v.name
-                else:
-                    lhs = "var " + v.name
-                    self.add_local_arg(v.name)
-            return lhs
-
-        dbg = 0
-        v = node.nodes[0]
-        if isinstance(v, ast.AssAttr):
-            lhs = _lhsFromAttr(v, current_klass)
-            if v.flags == "OP_ASSIGN":
-                op = "="
-            else:
-                raise TranslationError("unsupported flag (in _assign)", v)
-
-        elif isinstance(v, ast.AssName):
-            lhs = _lhsFromName(v, top_level, current_klass)
-            if v.flags == "OP_ASSIGN":
-                op = "="
-            else:
-                raise TranslationError("unsupported flag (in _assign)", v)
-        elif isinstance(v, ast.Subscript):
-            if v.flags == "OP_ASSIGN":
-                obj = self.expr(v.expr, current_klass)
-                if len(v.subs) != 1:
-                    raise TranslationError("must have one sub (in _assign)", v)
-                idx = self.expr(v.subs[0], current_klass)
-                value = self.expr(node.expr, current_klass)
-                print >>self.output, "    " + obj + ".__setitem__(" + idx + ", " + value + ");"
-                return
-            else:
-                raise TranslationError("unsupported flag (in _assign)", v)
-        elif isinstance(v, (ast.AssList, ast.AssTuple)):
-            uniqueID = self.nextTupleAssignID
-            self.nextTupleAssignID += 1
-            tempName = "__tupleassign" + str(uniqueID) + "__"
-            print >>self.output, "    var " + tempName + " = " + \
-                                 self.expr(node.expr, current_klass) + ";"
-            for index,child in enumerate(v.getChildNodes()):
-                rhs = tempName + ".__getitem__(" + str(index) + ")"
-
-                if isinstance(child, ast.AssAttr):
-                    lhs = _lhsFromAttr(child, current_klass)
-                elif isinstance(child, ast.AssName):
-                    lhs = _lhsFromName(child, top_level, current_klass)
-                elif isinstance(child, ast.Subscript):
-                    if child.flags == "OP_ASSIGN":
-                        obj = self.expr(child.expr, current_klass)
-                        if len(child.subs) != 1:
-                            raise TranslationError("must have one sub " +
-                                                   "(in _assign)", child)
-                        idx = self.expr(child.subs[0], current_klass)
-                        value = self.expr(node.expr, current_klass)
-                        print >>self.output, "    " + obj + ".__setitem__(" \
-                                           + idx + ", " + rhs + ");"
-                        continue
-                print >>self.output, "    " + lhs + " = " + rhs + ";"
-            return
-        else:
-            raise TranslationError("unsupported type (in _assign)", v)
-
-        rhs = self.expr(node.expr, current_klass)
-        if dbg:
-            print "b", repr(node.expr), rhs
-        print >>self.output, "    " + lhs + " " + op + " " + rhs + ";"
-
-
-    def _discard(self, node, current_klass):
-        
-        if isinstance(node.expr, ast.CallFunc):
-            debugStmt = self.debug and not self._isNativeFunc(node)
-            if debugStmt and isinstance(node.expr.node, ast.Name) and \
-               node.expr.node.name == 'import_wait':
-               debugStmt = False
-            if debugStmt:
-                st = self.get_line_trace(node)
-                print >>self.output, "sys.addstack('%s');\n" % st
-            if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME:
-                if len(node.expr.args) != 1:
-                    raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr)
-                if not isinstance(node.expr.args[0], ast.Const):
-                    raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr)
-                raw_js = node.expr.args[0].value
-                print >>self.output, raw_js
-            else:
-                expr = self._callfunc(node.expr, current_klass)
-                print >>self.output, "    " + expr + ";"
-
-            if debugStmt:
-                print >>self.output, "sys.popstack();\n"
-
-        elif isinstance(node.expr, ast.Const):
-            if node.expr.value is not None: # Empty statements generate ignore None
-                print >>self.output, self._const(node.expr)
-        else:
-            raise TranslationError("unsupported type (in _discard)", node.expr)
-
-
-    def _if(self, node, current_klass):
-        for i in range(len(node.tests)):
-            test, consequence = node.tests[i]
-            if i == 0:
-                keyword = "if"
-            else:
-                keyword = "else if"
-
-            self._if_test(keyword, test, consequence, current_klass)
-
-        if node.else_:
-            keyword = "else"
-            test = None
-            consequence = node.else_
-
-            self._if_test(keyword, test, consequence, current_klass)
-
-
-    def _if_test(self, keyword, test, consequence, current_klass):
-        if test:
-            expr = self.expr(test, current_klass)
-
-            print >>self.output, "    " + keyword + " (pyjslib.bool(" + expr + ")) {"
-        else:
-            print >>self.output, "    " + keyword + " {"
-
-        if isinstance(consequence, ast.Stmt):
-            for child in consequence.nodes:
-                self._stmt(child, current_klass)
-        else:
-            raise TranslationError("unsupported type (in _if_test)", consequence)
-
-        print >>self.output, "    }"
-
-
-    def _from(self, node):
-        for name in node.names:
-            # look up "hack" in AppTranslator as to how findFile gets here
-            module_name = node.modname + "." + name[0]
-            try:
-                ff = self.findFile(module_name + ".py")
-            except Exception:
-                ff = None
-            if ff:
-                self.add_imported_module(module_name)
-            else:
-                self.imported_classes[name[0]] = node.modname
-
-
-    def _compare(self, node, current_klass):
-        lhs = self.expr(node.expr, current_klass)
-
-        if len(node.ops) != 1:
-            raise TranslationError("only one ops supported (in _compare)", node)
-
-        op = node.ops[0][0]
-        rhs_node = node.ops[0][1]
-        rhs = self.expr(rhs_node, current_klass)
-
-        if op == "==":
-            return "pyjslib.eq(%s, %s)" % (lhs, rhs)
-        if op == "in":
-            return rhs + ".__contains__(" + lhs + ")"
-        elif op == "not in":
-            return "!" + rhs + ".__contains__(" + lhs + ")"
-        elif op == "is":
-            op = "==="
-        elif op == "is not":
-            op = "!=="
-
-        return "(" + lhs + " " + op + " " + rhs + ")"
-
-
-    def _not(self, node, current_klass):
-        expr = self.expr(node.expr, current_klass)
-
-        return "!(" + expr + ")"
-
-    def _or(self, node, current_klass):
-        expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')'
-        return expr
-
-    def _and(self, node, current_klass):
-        expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")"
-        return expr
-
-    def _for(self, node, current_klass):
-        assign_name = ""
-        assign_tuple = ""
-
-        # based on Bob Ippolito's Iteration in Javascript code
-        if isinstance(node.assign, ast.AssName):
-            assign_name = node.assign.name
-            self.add_local_arg(assign_name)
-            if node.assign.flags == "OP_ASSIGN":
-                op = "="
-        elif isinstance(node.assign, ast.AssTuple):
-            op = "="
-            i = 0
-            for child in node.assign:
-                child_name = child.name
-                if assign_name == "":
-                    assign_name = "temp_" + child_name
-                self.add_local_arg(child_name)
-                assign_tuple += """
-                var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i);
-                """ % locals()
-                i += 1
-        else:
-            raise TranslationError("unsupported type (in _for)", node.assign)
-
-        if isinstance(node.list, ast.Name):
-            list_expr = self._name(node.list, current_klass)
-        elif isinstance(node.list, ast.Getattr):
-            list_expr = self._getattr(node.list, current_klass)
-        elif isinstance(node.list, ast.CallFunc):
-            list_expr = self._callfunc(node.list, current_klass)
-        else:
-            raise TranslationError("unsupported type (in _for)", node.list)
-
-        lhs = "var " + assign_name
-        iterator_name = "__" + assign_name
-
-        print >>self.output, """
-        var %(iterator_name)s = %(list_expr)s.__iter__();
-        try {
-            while (true) {
-                %(lhs)s %(op)s %(iterator_name)s.next();
-                %(assign_tuple)s
-        """ % locals()
-        for node in node.body.nodes:
-            self._stmt(node, current_klass)
-        print >>self.output, """
-            }
-        } catch (e) {
-            if (e.__name__ != pyjslib.StopIteration.__name__) {
-                throw e;
-            }
-        }
-        """ % locals()
-
-
-    def _while(self, node, current_klass):
-        test = self.expr(node.test, current_klass)
-        print >>self.output, "    while (pyjslib.bool(" + test + ")) {"
-        if isinstance(node.body, ast.Stmt):
-            for child in node.body.nodes:
-                self._stmt(child, current_klass)
-        else:
-            raise TranslationError("unsupported type (in _while)", node.body)
-        print >>self.output, "    }"
-
-
-    def _const(self, node):
-        if isinstance(node.value, int):
-            return str(node.value)
-        elif isinstance(node.value, float):
-            return str(node.value)
-        elif isinstance(node.value, basestring):
-            v = node.value
-            if isinstance(node.value, unicode):
-                v = v.encode('utf-8')
-            return  "String('%s')" % escapejs(v)
-        elif node.value is None:
-            return "null"
-        else:
-            raise TranslationError("unsupported type (in _const)", node)
-
-    def _unaryadd(self, node, current_klass):
-        return self.expr(node.expr, current_klass)
-
-    def _unarysub(self, node, current_klass):
-        return "-" + self.expr(node.expr, current_klass)
-
-    def _add(self, node, current_klass):
-        return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass)
-
-    def _sub(self, node, current_klass):
-        return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass)
-
-    def _div(self, node, current_klass):
-        return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass)
-
-    def _mul(self, node, current_klass):
-        return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass)
-
-    def _mod(self, node, current_klass):
-        if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType):
-           self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used
-           return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")"
-        return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass)
-
-    def _invert(self, node, current_klass):
-        return "~" + self.expr(node.expr, current_klass)
-
-    def _bitand(self, node, current_klass):
-        return " & ".join([self.expr(child, current_klass) for child in node.nodes])
-
-    def _bitshiftleft(self, node, current_klass):
-        return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass)
-
-    def _bitshiftright(self, node, current_klass):
-        return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass)
-
-    def _bitxor(self,node, current_klass):
-        return " ^ ".join([self.expr(child, current_klass) for child in node.nodes])
-
-    def _bitor(self, node, current_klass):
-        return " | ".join([self.expr(child, current_klass) for child in node.nodes])
-
-    def _subscript(self, node, current_klass):
-        if node.flags == "OP_APPLY":
-            if len(node.subs) == 1:
-                return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")"
-            else:
-                raise TranslationError("must have one sub (in _subscript)", node)
-        else:
-            raise TranslationError("unsupported flag (in _subscript)", node)
-
-    def _subscript_stmt(self, node, current_klass):
-        if node.flags == "OP_DELETE":
-            print >>self.output, "    " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");"
-        else:
-            raise TranslationError("unsupported flag (in _subscript)", node)
-
-    def _list(self, node, current_klass):
-        return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
-
-    def _dict(self, node, current_klass):
-        items = []
-        for x in node.items:
-            key = self.expr(x[0], current_klass)
-            value = self.expr(x[1], current_klass)
-            items.append("[" + key + ", " + value + "]")
-        return "new pyjslib.Dict([" + ", ".join(items) + "])"
-
-    def _tuple(self, node, current_klass):
-        return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])"
-
-    def _lambda(self, node, current_klass):
-        if node.varargs:
-            raise TranslationError("varargs are not supported in Lambdas", node)
-        if node.kwargs:
-            raise TranslationError("kwargs are not supported in Lambdas", node)
-        res = cStringIO.StringIO()
-        arg_names = list(node.argnames)
-        function_args = ", ".join(arg_names)
-        for child in node.getChildNodes():
-            expr = self.expr(child, None)
-        print >> res, "function (%s){" % function_args
-        self._default_args_handler(node, arg_names, None,
-                                   output=res)
-        print >> res, 'return %s;}' % expr
-        return res.getvalue()
-
-    def _slice(self, node, current_klass):
-        if node.flags == "OP_APPLY":
-            lower = "null"
-            upper = "null"
-            if node.lower != None:
-                lower = self.expr(node.lower, current_klass)
-            if node.upper != None:
-                upper = self.expr(node.upper, current_klass)
-            return  "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")"
-        else:
-            raise TranslationError("unsupported flag (in _slice)", node)
-
-    def _global(self, node, current_klass):
-        for name in node.names:
-            self.method_imported_globals.add(name)
-
-    def expr(self, node, current_klass):
-        if isinstance(node, ast.Const):
-            return self._const(node)
-        # @@@ not sure if the parentheses should be here or in individual operator functions - JKT
-        elif isinstance(node, ast.Mul):
-            return " ( " + self._mul(node, current_klass) + " ) "
-        elif isinstance(node, ast.Add):
-            return " ( " + self._add(node, current_klass) + " ) "
-        elif isinstance(node, ast.Sub):
-            return " ( " + self._sub(node, current_klass) + " ) "
-        elif isinstance(node, ast.Div):
-            return " ( " + self._div(node, current_klass) + " ) "
-        elif isinstance(node, ast.Mod):
-            return self._mod(node, current_klass)
-        elif isinstance(node, ast.UnaryAdd):
-            return self._unaryadd(node, current_klass)
-        elif isinstance(node, ast.UnarySub):
-            return self._unarysub(node, current_klass)
-        elif isinstance(node, ast.Not):
-            return self._not(node, current_klass)
-        elif isinstance(node, ast.Or):
-            return self._or(node, current_klass)
-        elif isinstance(node, ast.And):
-            return self._and(node, current_klass)
-        elif isinstance(node, ast.Invert):
-            return self._invert(node, current_klass)
-        elif isinstance(node, ast.Bitand):
-            return "("+self._bitand(node, current_klass)+")"
-        elif isinstance(node,ast.LeftShift):
-            return self._bitshiftleft(node, current_klass)
-        elif isinstance(node, ast.RightShift):
-            return self._bitshiftright(node, current_klass)
-        elif isinstance(node, ast.Bitxor):
-            return "("+self._bitxor(node, current_klass)+")"
-        elif isinstance(node, ast.Bitor):
-            return "("+self._bitor(node, current_klass)+")"
-        elif isinstance(node, ast.Compare):
-            return self._compare(node, current_klass)
-        elif isinstance(node, ast.CallFunc):
-            return self._callfunc(node, current_klass)
-        elif isinstance(node, ast.Name):
-            return self._name(node, current_klass)
-        elif isinstance(node, ast.Subscript):
-            return self._subscript(node, current_klass)
-        elif isinstance(node, ast.Getattr):
-            return self._getattr(node, current_klass)
-        elif isinstance(node, ast.List):
-            return self._list(node, current_klass)
-        elif isinstance(node, ast.Dict):
-            return self._dict(node, current_klass)
-        elif isinstance(node, ast.Tuple):
-            return self._tuple(node, current_klass)
-        elif isinstance(node, ast.Slice):
-            return self._slice(node, current_klass)
-        elif isinstance(node, ast.Lambda):
-            return self._lambda(node, current_klass)
-        else:
-            raise TranslationError("unsupported type (in expr)", node)
-
-
-
-import cStringIO
-
-def translate(file_name, module_name, debug=False):
-    f = file(file_name, "r")
-    src = f.read()
-    f.close()
-    output = cStringIO.StringIO()
-    mod = compiler.parseFile(file_name)
-    t = Translator(module_name, module_name, module_name, src, debug, mod, output)
-    return output.getvalue()
-
-
-class PlatformParser:
-    def __init__(self, platform_dir = "", verbose=True):
-        self.platform_dir = platform_dir
-        self.parse_cache = {}
-        self.platform = ""
-        self.verbose = verbose
-
-    def setPlatform(self, platform):
-        self.platform = platform
-
-    def parseModule(self, module_name, file_name):
-
-        importing = False
-        if not self.parse_cache.has_key(file_name):
-            importing = True
-            mod = compiler.parseFile(file_name)
-            self.parse_cache[file_name] = mod
-        else:
-            mod = self.parse_cache[file_name]
-
-        override = False
-        platform_file_name = self.generatePlatformFilename(file_name)
-        if self.platform and os.path.isfile(platform_file_name):
-            mod = copy.deepcopy(mod)
-            mod_override = compiler.parseFile(platform_file_name)
-            self.merge(mod, mod_override)
-            override = True
-
-        if self.verbose:
-            if override:
-                print "Importing %s (Platform %s)" % (module_name, self.platform)
-            elif importing:
-                print "Importing %s" % (module_name)
-
-        return mod, override
-
-    def generatePlatformFilename(self, file_name):
-        (module_name, extension) = os.path.splitext(os.path.basename(file_name))
-        platform_file_name = module_name + self.platform + extension
-
-        return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name)
-
-    def merge(self, tree1, tree2):
-        for child in tree2.node:
-            if isinstance(child, ast.Function):
-                self.replaceFunction(tree1, child.name, child)
-            elif isinstance(child, ast.Class):
-                self.replaceClassMethods(tree1, child.name, child)
-
-        return tree1
-
-    def replaceFunction(self, tree, function_name, function_node):
-        # find function to replace
-        for child in tree.node:
-            if isinstance(child, ast.Function) and child.name == function_name:
-                self.copyFunction(child, function_node)
-                return
-        raise TranslationError("function not found: " + function_name, function_node)
-
-    def replaceClassMethods(self, tree, class_name, class_node):
-        # find class to replace
-        old_class_node = None
-        for child in tree.node:
-            if isinstance(child, ast.Class) and child.name == class_name:
-                old_class_node = child
-                break
-
-        if not old_class_node:
-            raise TranslationError("class not found: " + class_name, class_node)
-
-        # replace methods
-        for function_node in class_node.code:
-            if isinstance(function_node, ast.Function):
-                found = False
-                for child in old_class_node.code:
-                    if isinstance(child, ast.Function) and child.name == function_node.name:
-                        found = True
-                        self.copyFunction(child, function_node)
-                        break
-
-                if not found:
-                    raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node)
-
-    def copyFunction(self, target, source):
-        target.code = source.code
-        target.argnames = source.argnames
-        target.defaults = source.defaults
-        target.doc = source.doc # @@@ not sure we need to do this any more
-
-def dotreplace(fname):
-    path, ext = os.path.splitext(fname)
-    return path.replace(".", "/") + ext
-
-class AppTranslator:
-
-    def __init__(self, library_dirs=[], parser=None, dynamic=False,
-                 optimize=False, verbose=True):
-        self.extension = ".py"
-        self.optimize = optimize
-        self.library_modules = []
-        self.overrides = {}
-        self.library_dirs = path + library_dirs
-        self.dynamic = dynamic
-        self.verbose = verbose
-
-        if not parser:
-            self.parser = PlatformParser()
-        else:
-            self.parser = parser
-
-        self.parser.dynamic = dynamic
-
-    def findFile(self, file_name):
-        if os.path.isfile(file_name):
-            return file_name
-
-        for library_dir in self.library_dirs:
-            file_name = dotreplace(file_name)
-            full_file_name = os.path.join(
-                os.path.abspath(os.path.dirname(__file__)), library_dir, file_name)
-            if os.path.isfile(full_file_name):
-                return full_file_name
-
-            fnameinit, ext = os.path.splitext(file_name)
-            fnameinit = fnameinit + "/__init__.py"
-
-            full_file_name = os.path.join(
-                os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit)
-            if os.path.isfile(full_file_name):
-                return full_file_name
-
-        raise Exception("file not found: " + file_name)
-
-    def _translate(self, module_name, is_app=True, debug=False,
-                   imported_js=set()):
-        if module_name not in self.library_modules:
-            self.library_modules.append(module_name)
-
-        file_name = self.findFile(module_name + self.extension)
-
-        output = cStringIO.StringIO()
-
-        f = file(file_name, "r")
-        src = f.read()
-        f.close()
-
-        mod, override = self.parser.parseModule(module_name, file_name)
-        if override:
-            override_name = "%s.%s" % (self.parser.platform.lower(),
-                                           module_name)
-            self.overrides[override_name] = override_name
-        if is_app:
-            mn = '__main__'
-        else:
-            mn = module_name
-        t = Translator(mn, module_name, module_name,
-                       src, debug, mod, output, self.dynamic, self.optimize,
-                       self.findFile)
-
-        module_str = output.getvalue()
-        imported_js.update(set(t.imported_js))
-        imported_modules_str = ""
-        for module in t.imported_modules:
-            if module not in self.library_modules:
-                self.library_modules.append(module)
-                #imported_js.update(set(t.imported_js))
-                #imported_modules_str += self._translate(
-                #    module, False, debug=debug, imported_js=imported_js)
-
-        return imported_modules_str + module_str
-
-
-    def translate(self, module_name, is_app=True, debug=False,
-                  library_modules=[]):
-        app_code = cStringIO.StringIO()
-        lib_code = cStringIO.StringIO()
-        imported_js = set()
-        self.library_modules = []
-        self.overrides = {}
-        for library in library_modules:
-            if library.endswith(".js"):
-                imported_js.add(library)
-                continue
-            self.library_modules.append(library)
-            if self.verbose:
-                print 'Including LIB', library
-            print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n'
-            print >> lib_code, self._translate(
-                library, False, debug=debug, imported_js=imported_js)
-
-            print >> lib_code, "/* initialize static library */"
-            print >> lib_code, "%s%s();\n" % (UU, library)
-
-            print >> lib_code, '\n//\n// END LIB '+library+'\n//\n'
-        if module_name:
-            print >> app_code, self._translate(
-                module_name, is_app, debug=debug, imported_js=imported_js)
-        for js in imported_js:
-           path = self.findFile(js)
-           if os.path.isfile(path):
-              if self.verbose:
-                  print 'Including JS', js
-              print >> lib_code,  '\n//\n// BEGIN JS '+js+'\n//\n'
-              print >> lib_code, file(path).read()
-              print >> lib_code,  '\n//\n// END JS '+js+'\n//\n'
-           else:
-              print >>sys.stderr, 'Warning: Unable to find imported javascript:', js
-        return lib_code.getvalue(), app_code.getvalue()
-
-usage = """
-  usage: %s file_name [module_name]
-"""
-
-def main():
-    import sys
-    if len(sys.argv)<2:
-        print >> sys.stderr, usage % sys.argv[0]
-        sys.exit(1)
-    file_name = os.path.abspath(sys.argv[1])
-    if not os.path.isfile(file_name):
-        print >> sys.stderr, "File not found %s" % file_name
-        sys.exit(1)
-    if len(sys.argv) > 2:
-        module_name = sys.argv[2]
-    else:
-        module_name = None
-    print translate(file_name, module_name),
-
-if __name__ == "__main__":
-    main()
-
--- a/plugins/python/modules/svgui/svgui.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-import wx
-import os, sys, shutil
-
-from plugger import opjimg
-from plugins.python import PythonCodeTemplate
-
-from pyjs import translate
-
-from docutils import *
-
-class RootClass:
-
-    PluginMethods = [
-        {"bitmap" : os.path.join("images","ImportSVG"),
-         "name" : _("Import SVG"),
-         "tooltip" : _("Import SVG"),
-         "method" : "_ImportSVG"},
-        {"bitmap" : os.path.join("images","ImportSVG"),
-         "name" : _("Inkscape"),
-         "tooltip" : _("Create HMI"),
-         "method" : "_StartInkscape"},
-    ]
-
-    def PluginPath(self):
-        return os.path.join(self.PlugParent.PluginPath(), "modules", self.PlugType)
-
-    def _getSVGpath(self):
-        # define name for IEC raw code file
-        return os.path.join(self.PlugPath(), "gui.svg")
-
-    def _getSVGUIserverpath(self):
-        return os.path.join(os.path.dirname(__file__), "svgui_server.py")
-
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Return C code generated by iec2c compiler 
-        when _generate_softPLC have been called
-        @param locations: ignored
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-        
-        current_location = self.GetCurrentLocation()
-        # define a unique name for the generated C file
-        location_str = "_".join(map(lambda x:str(x), current_location))
-        
-        res = ([], "", False)
-        
-        svgfile=self._getSVGpath()
-        if os.path.exists(svgfile):
-            res += (("gui.svg", file(svgfile,"rb")),)
-
-        svguiserverfile = open(self._getSVGUIserverpath(), 'r')
-        svguiservercode = svguiserverfile.read()
-        svguiserverfile.close()
-
-        svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js")
-        svguilibfile = open(svguilibpath, 'w')
-        svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys"))
-        svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read())
-        svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib"))
-        svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib"))
-        svguilibfile.write("pyjslib();\nsvguilib();\n")
-        svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read())
-        svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read())
-        svguilibfile.close()
-        jsmodules = {"LiveSVGPage": "svguilib.js"}
-        res += (("svguilib.js", file(svguilibpath,"rb")),)
-        
-        runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
-        runtimefile = open(runtimefile_path, 'w')
-        runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"})
-        runtimefile.write("""
-def _runtime_%(location)s_begin():
-    website.LoadHMI(%(svgui_class)s, %(jsmodules)s)
-    
-def _runtime_%(location)s_cleanup():
-    website.UnLoadHMI()
-    
-""" % {"location": location_str,
-       "svgui_class": "SVGUI_HMI",
-       "jsmodules" : str(jsmodules),
-      })
-        runtimefile.close()
-        
-        res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),)
-        
-        return res
-
-    def _ImportSVG(self):
-        dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "",  _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN)
-        if dialog.ShowModal() == wx.ID_OK:
-            svgpath = dialog.GetPath()
-            if os.path.isfile(svgpath):
-                shutil.copy(svgpath, self._getSVGpath())
-            else:
-                self.GetPlugRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath)
-        dialog.Destroy()  
-
-    def _StartInkscape(self):
-        svgfile = self._getSVGpath()
-        open_inkscape = True
-        if not self.GetPlugRoot().CheckProjectPathPerm():
-            dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
-                                      _("You don't have write permissions.\nOpen Inkscape anyway ?"),
-                                      _("Open Inkscape"),
-                                      wx.YES_NO|wx.ICON_QUESTION)
-            open_inkscape = dialog.ShowModal() == wx.ID_YES
-            dialog.Destroy()
-        if open_inkscape:
-            if not os.path.isfile(svgfile):
-                svgfile = None
-            open_svg(svgfile)
--- a/plugins/python/modules/svgui/svgui_server.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import os
-
-from nevow import rend, appserver, inevow, tags, loaders, athena
-import simplejson as json
-
-svgfile = '%(svgfile)s'
-
-svguiWidgets = {}
-
-currentId = 0
-def getNewId():
-    global currentId
-    currentId += 1
-    return currentId
-
-class SvguiWidget:
-    
-    def __init__(self, classname, id, **kwargs):
-        self.classname = classname
-        self.id = id
-        self.attrs = kwargs.copy()
-        self.inputs = {}
-        self.outputs = {}
-        self.inhibit = False
-        self.changed = False
-
-    def setinput(self, attrname, value):
-        self.inputs[attrname] = value
-        
-    def getinput(self, attrname, default=None):
-        if not self.inputs.has_key(attrname):
-            self.inputs[attrname] = default
-        return self.inputs[attrname]
-
-    def setoutput(self, attrname, value):
-        if self.outputs.get(attrname) != value:
-            self.outputs[attrname] = value
-            self.changed = True
-            self.RefreshInterface()
-        
-    def updateoutputs(self, **kwargs):
-        for attrname, value in kwargs.iteritems():
-            if self.outputs.get(attrname) != value:
-                self.outputs[attrname] = value
-                self.changed = True
-        self.RefreshInterface()
-        
-    def RefreshInterface(self):
-        interface = website.getHMI()
-        if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit:
-            self.changed = False
-            d = interface.sendData(self)
-            if d is not None:
-                self.inhibit = True
-                d.addCallback(self.InterfaceRefreshed)
-    
-    def InterfaceRefreshed(self, result):
-        self.inhibit = False
-        if self.changed:
-            self.RefreshInterface()
-
-def get_object_init_state(obj):
-    # Convert objects to a dictionary of their representation
-    attrs = obj.attrs.copy()
-    attrs.update(obj.inputs)
-    d = { '__class__': obj.classname,
-          'id': obj.id,
-          'kwargs': json.dumps(attrs),
-          }
-    return d
-
-def get_object_current_state(obj):
-    # Convert objects to a dictionary of their representation
-    d = { '__class__': obj.classname,
-          'id': obj.id,
-          'kwargs': json.dumps(obj.outputs),
-          }
-    return d
-
-class SVGUI_HMI(website.PLCHMI):
-    jsClass = u"LiveSVGPage.LiveSVGWidget"
-    
-    docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[                                    
-                                         tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))),
-                                         ])
-    
-    def HMIinitialisation(self):
-        gadgets = []
-        for gadget in svguiWidgets.values():
-            gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii'))
-        d = self.callRemote('init', gadgets)
-        d.addCallback(self.HMIinitialised)
-    
-    def sendData(self,data):
-        if self.initialised:
-            return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii'))
-        return None
-        
-    def setattr(self, id, attrname, value):
-        svguiWidgets[id].setinput(attrname, value)
-
-def createSVGUIControl(*args, **kwargs):
-    id = getNewId()
-    gad = SvguiWidget(args[0], id, **kwargs)
-    svguiWidgets[id] = gad
-    gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')]
-    interface = website.getHMI()
-    if isinstance(interface, SVGUI_HMI) and interface.initialised:
-        interface.callRemote('init', gadget)
-    return id
-
-def setAttr(id, attrname, value):
-    gad = svguiWidgets.get(id, None)
-    if gad is not None:
-        gad.setoutput(attrname, value)
-
-def updateAttr(id, **kwargs):
-    gad = svguiWidgets.get(id, None)
-    if gad is not None:
-        gad.updateoutput(**kwargs)
-
-def getAttr(id, attrname, default=None):
-    gad = svguiWidgets.get(id, None)
-    if gad is not None:
-        return gad.getinput(attrname, default)
-    return default
-
--- a/plugins/python/modules/svgui/svguilib.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-
-class button:
-    
-    def __init__(self, parent, id, args):
-        self.parent = parent
-        self.id = id
-        self.back_elt = getSVGElementById(args.back_id)
-        self.sele_elt = getSVGElementById(args.sele_id)
-        self.toggle = args.toggle
-        self.active = args.active
-        if args.state != undefined:
-            self.state = args.state
-        else:
-            self.state = False
-        self.dragging = False
-        if self.toggle:
-            self.up = not self.state
-        else:
-            self.up = True
-        
-        # Add event on each element of the button
-        if self.active:
-            self.back_elt.addEventListener("mouseup", self, False)
-            self.back_elt.addEventListener("mousedown", self, False)
-            self.back_elt.addEventListener("mouseover", self, False)
-            self.back_elt.addEventListener("mouseout", self, False)
-            
-            self.sele_elt.addEventListener("mouseup", self, False)
-            self.sele_elt.addEventListener("mousedown", self, False)
-            self.sele_elt.addEventListener("mouseover", self, False)
-            self.sele_elt.addEventListener("mouseout", self, False)
-        
-        blockSVGElementDrag(self.back_elt)
-        blockSVGElementDrag(self.sele_elt)
-
-        self.updateElements()
-
-    # method to display the current state of interface
-    def updateElements(self):
-        if self.up:
-            self.sele_elt.setAttribute("display", "none")
-            self.back_elt.removeAttribute("display")
-        else:
-            self.sele_elt.removeAttribute("display")
-            self.back_elt.setAttribute("display", "none")
-            
-    def updateValues(self, values):
-        if values.state != self.state:
-            self.state = values.state
-            self.up = not self.state
-            updateAttr(self.id, 'state', self.state)
-            self.updateElements()
-
-    def handleEvent(self, evt):
-        # Quand le bouton de la souris est presse
-        if evt.type == "mousedown":
-            evt.stopPropagation()
-            setCurrentObject(self)
-            
-            self.dragging = True
-            
-            if self.toggle:
-                self.up = self.state
-            else:
-                self.up = False
-                self.state = True
-                updateAttr(self.id, 'state', self.state)
-            self.updateElements()
-        
-        if isCurrentObject(self) and self.dragging:
-            # Quand le bouton est survole
-            if evt.type == "mouseover" and self.toggle:
-                self.up = self.state
-                self.updateElements()
-            
-            # Quand le curseur quitte la zone du bouton
-            elif evt.type == "mouseout" and self.toggle:       
-                self.up = not self.state
-                self.updateElements()
-            
-            # Quand le bouton de la souris est relache
-            elif evt.type == "mouseup":
-                evt.stopPropagation()
-                if self.toggle and self.up == self.state:
-                    self.state = not self.state
-                    updateAttr(self.id, 'state', self.state)
-                elif not self.toggle:
-                    self.up = True
-                    self.state = False
-                    updateAttr(self.id, 'state', self.state)
-                    self.updateElements()
-                self.dragging = False
-
-class textControl:
-    
-    def __init__(self, parent, id, args):
-        self.parent = parent
-        self.id = id
-        self.back_elt = getSVGElementById(args.back_id)
-        if args.text != undefined:
-            self.text = args.text
-        else:
-            self.text = ""
-        self.updateElements()
-    
-    def updateValues(self, values):
-        if values.text != self.value:
-            self.text = values.text
-            updateAttr(self.id, 'text', self.text)
-            self.updateElements()
-    
-    def updateElements(self):
-        self.back_elt.firstChild.firstChild.textContent = self.text
-    
-    def handleEvent(self, evt):
-        pass
-    
\ No newline at end of file
--- a/plugins/python/modules/wxglade_hmi/README	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-WxGlade HMI
\ No newline at end of file
--- a/plugins/python/modules/wxglade_hmi/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from wxglade_hmi import *
--- a/plugins/python/modules/wxglade_hmi/wxglade_hmi.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-import wx
-import os, sys
-from xml.dom import minidom
-
-from plugger import opjimg
-from plugins.python import PythonCodeTemplate
-
-class RootClass(PythonCodeTemplate):
-
-    PluginMethods = [
-        {"bitmap" : opjimg("editWXGLADE"),
-         "name" : _("WXGLADE GUI"),
-         "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
-         "method" : "_editWXGLADE"},
-    ]
-
-    def _getWXGLADEpath(self):
-        # define name for IEC raw code file
-        return os.path.join(self.PlugPath(), "hmi.wxg")
-
-    def launch_wxglade(self, options, wait=False):
-        from wxglade import __file__ as fileName
-        path = os.path.dirname(fileName)
-        glade = os.path.join(path, 'wxglade.py')
-        if wx.Platform == '__WXMSW__':
-            glade = "\"%s\""%glade
-        mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait]
-        os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options)
-
-
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Return C code generated by iec2c compiler 
-        when _generate_softPLC have been called
-        @param locations: ignored
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-        
-        current_location = self.GetCurrentLocation()
-        # define a unique name for the generated C file
-        location_str = "_".join(map(lambda x:str(x), current_location))
-        
-        runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
-        runtimefile = open(runtimefile_path, 'w')
-        
-        hmi_frames = {}
-        
-        wxgfile_path=self._getWXGLADEpath()
-        if os.path.exists(wxgfile_path):
-            wxgfile = open(wxgfile_path, 'r')
-            wxgtree = minidom.parse(wxgfile)
-            wxgfile.close()
-            
-            for node in wxgtree.childNodes[1].childNodes:
-                if node.nodeType == wxgtree.ELEMENT_NODE:
-                    hmi_frames[node._attrs["name"].value] =  node._attrs["class"].value
-                    
-            hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py")
-            if wx.Platform == '__WXMSW__':
-                wxgfile_path = "\"%s\""%wxgfile_path
-                wxghmipyfile_path = "\"%s\""%hmipyfile_path
-            else:
-                wxghmipyfile_path = hmipyfile_path
-            self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True)
-            
-            hmipyfile = open(hmipyfile_path, 'r')
-            runtimefile.write(hmipyfile.read())
-            hmipyfile.close()
-        
-        runtimefile.write(self.GetPythonCode())
-        runtimefile.write("""
-%(declare)s
-
-def _runtime_%(location)s_begin():
-    global %(global)s
-    
-    def OnCloseFrame(evt):
-        wx.MessageBox(_("Please stop PLC to close"))
-    
-    %(init)s
-    
-def _runtime_%(location)s_cleanup():
-    global %(global)s
-    
-    %(cleanup)s
-
-""" % {"location": location_str,
-       "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())),
-       "global": ",".join(hmi_frames.keys()),
-       "init": "\n".join(map(lambda x: """
-    %(name)s = %(class)s(None)
-    %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
-    %(name)s.Show()
-""" % {"name": x[0], "class": x[1]},
-                             hmi_frames.items())),
-       "cleanup": "\n    ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))})
-        runtimefile.close()
-        
-        return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
-
-    def _editWXGLADE(self):
-        wxg_filename = self._getWXGLADEpath()
-        open_wxglade = True
-        if not self.GetPlugRoot().CheckProjectPathPerm():
-            dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame,
-                                      _("You don't have write permissions.\nOpen wxGlade anyway ?"),
-                                      _("Open wxGlade"),
-                                      wx.YES_NO|wx.ICON_QUESTION)
-            open_wxglade = dialog.ShowModal() == wx.ID_YES
-            dialog.Destroy()
-        if open_wxglade:
-            if not os.path.exists(wxg_filename):
-                hmi_name = self.BaseParams.getName()
-                open(wxg_filename,"w").write("""<?xml version="1.0"?>
-    <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
-        <object class="%(class)s" name="%(name)s" base="EditFrame">
-            <style>wxDEFAULT_FRAME_STYLE</style>
-            <title>frame_1</title>
-        </object>
-    </application>
-    """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
-            if wx.Platform == '__WXMSW__':
-                wxg_filename = "\"%s\""%wxg_filename
-            self.launch_wxglade([wxg_filename])
--- a/plugins/python/plc_python.c	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Python Asynchronous execution code
- *
- * PLC put python commands in a fifo, respecting execution order
- * with the help of C pragmas inserted in python_eval FB code
- *
- * Buffer content is read asynchronously, (from non real time part),
- * commands are executed and result stored for later use by PLC.
- *
- * In this implementation, fifo is a list of pointer to python_eval
- * function blocks structures. Some local variables have been added in
- * python_eval interface. We use those local variables as buffer and state
- * flags.
- *
- * */
-
-#include "iec_types_all.h"
-#include "POUS.h"
-#include <string.h>
-
-/* The fifo (fixed size, as number of FB is fixed) */
-static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d];
-/* Producer and consumer cursors */
-static int Current_PLC_EvalFB;
-static int Current_Python_EvalFB;
-
-/* A global IEC-Python gateway state, for use inside python_eval FBs*/
-static int PythonState;
-#define PYTHON_LOCKED_BY_PYTHON 0
-#define PYTHON_LOCKED_BY_PLC 1
-#define PYTHON_MUSTWAKEUP 2
-#define PYTHON_FINISHED 4
-
-/* Each python_eval FunctionBlock have it own state */
-#define PYTHON_FB_FREE 0
-#define PYTHON_FB_REQUESTED 1
-#define PYTHON_FB_PROCESSING 2
-#define PYTHON_FB_ANSWERED 3
-
-int WaitPythonCommands(void);
-void UnBlockPythonCommands(void);
-int TryLockPython(void);
-void UnLockPython(void);
-void LockPython(void);
-
-int __init_%(location)s()
-{
-	int i;
-	/* Initialize cursors */
-	Current_Python_EvalFB = 0;
-	Current_PLC_EvalFB = 0;
-	PythonState = PYTHON_LOCKED_BY_PYTHON;
-	for(i = 0; i < %(python_eval_fb_count)d; i++)
-		EvalFBs[i] = NULL;
-  return 0;
-}
-
-void __cleanup_%(location)s()
-{
-	PythonState = PYTHON_FINISHED;
-	UnBlockPythonCommands();
-}
-
-void __retrieve_%(location)s()
-{
-	/* Check Python thread is not being
-	 * modifying internal python_eval data */
-	PythonState = TryLockPython() ?
-	                PYTHON_LOCKED_BY_PLC :
-	                PYTHON_LOCKED_BY_PYTHON;
-	/* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
-	 * and python_eval will no do anything */
-}
-
-void __publish_%(location)s()
-{
-	if(PythonState & PYTHON_LOCKED_BY_PLC){
-		/* If runnig PLC did push something in the fifo*/
-		if(PythonState & PYTHON_MUSTWAKEUP){
-			/* WakeUp python thread */
-			UnBlockPythonCommands();
-		}
-		UnLockPython();
-	}
-}
-/**
- * Called by the PLC, each time a python_eval
- * FB instance is executed
- */
-void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
-{
-	/* detect rising edge on TRIG to trigger evaluation */
-	if(((__GET_VAR(data__->TRIG) && !__GET_VAR(data__->TRIGM1)) ||
-	   /* polling is equivalent to trig on value rather than on rising edge*/
-	    (poll && __GET_VAR(data__->TRIG) )) &&
-	    /* trig only if not already trigged */
-	    __GET_VAR(data__->TRIGGED) == 0){
-		/* mark as trigged */
-	    __SET_VAR(data__->, TRIGGED, 1);
-		/* make a safe copy of the code */
-		__SET_VAR(data__->, PREBUFFER, __GET_VAR(data__->CODE));
-	}
-	/* retain value for next rising edge detection */
-	__SET_VAR(data__->, TRIGM1, __GET_VAR(data__->TRIG));
-
-	/* python thread is not in ? */
-	if( PythonState & PYTHON_LOCKED_BY_PLC){
-		/* if some answer are waiting, publish*/
-		if(__GET_VAR(data__->STATE) == PYTHON_FB_ANSWERED){
-			/* Copy buffer content into result*/
-			__SET_VAR(data__->, RESULT, __GET_VAR(data__->BUFFER));
-			/* signal result presece to PLC*/
-			__SET_VAR(data__->, ACK, 1);
-			/* Mark as free */
-			__SET_VAR(data__->, STATE, PYTHON_FB_FREE);
-			/* mark as not trigged */
-			if(!poll)
-			    __SET_VAR(data__->, TRIGGED, 0);
-			/*printf("__PythonEvalFB pop %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
-		}else if(poll){
-			/* when in polling, no answer == ack down */
-		    __SET_VAR(data__->, ACK, 0);
-		}
-		/* got the order to act ?*/
-		if(__GET_VAR(data__->TRIGGED) == 1 &&
-		   /* and not already being processed */
-		   __GET_VAR(data__->STATE) == PYTHON_FB_FREE)
-		{
-			/* Enter the block in the fifo
-			 * Don't have to check if fifo cell is free
-			 * as fifo size == FB count, and a FB cannot
-			 * be requested twice */
-			EvalFBs[Current_PLC_EvalFB] = data__;
-			/* copy into BUFFER local*/
-			__SET_VAR(data__->, BUFFER, __GET_VAR(data__->PREBUFFER));
-			/* Set ACK pin to low so that we can set a rising edge on result */
-			if(!poll){
-				/* when not polling, a new answer imply reseting ack*/
-			    __SET_VAR(data__->, ACK, 0);
-			}else{
-				/* when in polling, acting reset trigger */
-			    __SET_VAR(data__->, TRIGGED, 0);
-			}
-			/* Mark FB busy */
-			__SET_VAR(data__->, STATE, PYTHON_FB_REQUESTED);
-			/* Have to wakeup python thread in case he was asleep */
-			PythonState |= PYTHON_MUSTWAKEUP;
-			/*printf("__PythonEvalFB push %%d - %%*s\n",Current_PLC_EvalFB, data__->BUFFER.len, data__->BUFFER.body);*/
-			/* Get a new line */
-			Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
-		}
-	}
-}
-
-char* PythonIterator(char* result)
-{
-	char* next_command;
-	PYTHON_EVAL* data__;
-	//printf("PythonIterator result %%s\n", result);
-    /*emergency exit*/
-    if(PythonState & PYTHON_FINISHED) return NULL;
-	/* take python mutex to prevent changing PLC data while PLC running */
-	LockPython();
-	/* Get current FB */
-	data__ = EvalFBs[Current_Python_EvalFB];
-	if(data__ && /* may be null at first run */
-	    __GET_VAR(data__->STATE) == PYTHON_FB_PROCESSING){ /* some answer awaited*/
-	   	/* If result not None */
-	   	if(result){
-			/* Get results len */
-	   	    __SET_VAR(data__->, BUFFER, strlen(result), .len);
-			/* prevent results overrun */
-			if(__GET_VAR(data__->BUFFER, .len) > STR_MAX_LEN)
-			{
-			    __SET_VAR(data__->, BUFFER, STR_MAX_LEN, .len );
-				/* TODO : signal error */
-			}
-			/* Copy results to buffer */
-			strncpy((char*)__GET_VAR(data__->BUFFER, .body), result, __GET_VAR(data__->BUFFER,.len));
-	   	}else{
-	   	    __SET_VAR(data__->, BUFFER, 0, .len);
-	   	}
-		/* remove block from fifo*/
-		EvalFBs[Current_Python_EvalFB] = NULL;
-		/* Mark block as answered */
-		__SET_VAR(data__->, STATE, PYTHON_FB_ANSWERED);
-		/* Get a new line */
-		Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
-		//printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
-	}
-	/* while next slot is empty */
-	while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
-	 	  /* or doesn't contain command */
-	      __GET_VAR(data__->STATE) != PYTHON_FB_REQUESTED)
-	{
-		UnLockPython();
-		/* wait next FB to eval */
-		//printf("PythonIterator wait\n");
-		if(WaitPythonCommands()) return NULL;
-		/*emergency exit*/
-		if(PythonState & PYTHON_FINISHED) return NULL;
-		LockPython();
-	}
-	/* Mark block as processing */
-	__SET_VAR(data__->, STATE, PYTHON_FB_PROCESSING);
-	//printf("PythonIterator\n");
-	/* make BUFFER a null terminated string */
-	__SET_VAR(data__->, BUFFER, 0, .body[__GET_VAR(data__->BUFFER, .len)]);
-	/* next command is BUFFER */
-	next_command = (char*)__GET_VAR(data__->BUFFER, .body);
-	/* free python mutex */
-	UnLockPython();
-	/* return the next command to eval */
-	return next_command;
-}
-
--- a/plugins/python/pous.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://www.plcopen.org/xml/tc6.xsd"
-         xmlns:xhtml="http://www.w3.org/1999/xhtml"
-         xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd">
-  <fileHeader companyName="Beremiz"
-              productName="Beremiz"
-              productVersion="0.0"
-              creationDateTime="2008-12-14T16:53:26"/>
-  <contentHeader name="Beremiz non-standard POUs library"
-                 modificationDateTime="2008-12-23T22:35:46">
-    <coordinateInfo>
-      <fbd>
-        <scaling x="0" y="0"/>
-      </fbd>
-      <ld>
-        <scaling x="0" y="0"/>
-      </ld>
-      <sfc>
-        <scaling x="0" y="0"/>
-      </sfc>
-    </coordinateInfo>
-  </contentHeader>
-  <types>
-    <dataTypes/>
-    <pous>
-      <pou name="python_eval" pouType="functionBlock">
-        <interface>
-          <inputVars>
-            <variable name="TRIG">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="CODE">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </inputVars>
-          <outputVars>
-            <variable name="ACK">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="RESULT">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </outputVars>
-          <localVars>
-            <variable name="STATE">
-              <type>
-                <DWORD/>
-              </type>
-            </variable>
-            <variable name="BUFFER">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="PREBUFFER">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="TRIGM1">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="TRIGGED">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-          </localVars>
-        </interface>
-        <body>
-          <ST>
-<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(0, data__);}]]>
-          </ST>
-        </body>
-      </pou>
-      <pou name="python_poll" pouType="functionBlock">
-        <interface>
-          <inputVars>
-            <variable name="TRIG">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="CODE">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </inputVars>
-          <outputVars>
-            <variable name="ACK">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="RESULT">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </outputVars>
-          <localVars>
-            <variable name="STATE">
-              <type>
-                <DWORD/>
-              </type>
-            </variable>
-            <variable name="BUFFER">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="PREBUFFER">
-              <type>
-                <string/>
-              </type>
-            </variable>
-            <variable name="TRIGM1">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="TRIGGED">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-          </localVars>
-        </interface>
-        <body>
-          <ST>
-<![CDATA[{extern void __PythonEvalFB(int, PYTHON_EVAL*);__PythonEvalFB(1,(PYTHON_EVAL*)(void*)data__);}]]>
-          </ST>
-        </body>
-      </pou>
-    <pou name="python_gear" pouType="functionBlock">
-        <interface>
-          <inputVars>
-            <variable name="N">
-              <type>
-                <USINT/>
-              </type>
-            </variable>
-            <variable name="TRIG">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="CODE">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </inputVars>
-          <outputVars>
-            <variable name="ACK">
-              <type>
-                <BOOL/>
-              </type>
-            </variable>
-            <variable name="RESULT">
-              <type>
-                <string/>
-              </type>
-            </variable>
-          </outputVars>
-          <localVars>
-            <variable name="py_eval">
-              <type>
-                <derived name="python_eval"/>
-              </type>
-            </variable>
-            <variable name="COUNTER">
-              <type>
-                <USINT/>
-              </type>
-            </variable>
-          </localVars>
-        </interface>
-        <body>
-          <FBD>
-            <block localId="1" width="125" height="110" typeName="python_eval" instanceName="py_eval">
-              <position x="525" y="580"/>
-              <inputVariables>
-                <variable formalParameter="TRIG">
-                  <connectionPointIn>
-                    <relPosition x="0" y="40"/>
-                    <connection refLocalId="7" formalParameter="OUT">
-                      <position x="525" y="620"/>
-                      <position x="495" y="620"/>
-                      <position x="495" y="575"/>
-                      <position x="465" y="575"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="CODE">
-                  <connectionPointIn>
-                    <relPosition x="0" y="85"/>
-                    <connection refLocalId="4">
-                      <position x="525" y="665"/>
-                      <position x="370" y="665"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="ACK">
-                  <connectionPointOut>
-                    <relPosition x="125" y="40"/>
-                  </connectionPointOut>
-                </variable>
-                <variable formalParameter="RESULT">
-                  <connectionPointOut>
-                    <relPosition x="125" y="85"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="2" height="35" width="25">
-              <position x="435" y="270"/>
-              <connectionPointOut>
-                <relPosition x="25" y="15"/>
-              </connectionPointOut>
-              <expression>N</expression>
-            </inVariable>
-            <inVariable localId="3" height="35" width="55">
-              <position x="275" y="585"/>
-              <connectionPointOut>
-                <relPosition x="55" y="15"/>
-              </connectionPointOut>
-              <expression>TRIG</expression>
-            </inVariable>
-            <inVariable localId="4" height="35" width="55">
-              <position x="315" y="650"/>
-              <connectionPointOut>
-                <relPosition x="55" y="15"/>
-              </connectionPointOut>
-              <expression>CODE</expression>
-            </inVariable>
-            <outVariable localId="5" height="35" width="45">
-              <position x="740" y="605"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="1" formalParameter="ACK">
-                  <position x="740" y="620"/>
-                  <position x="650" y="620"/>
-                </connection>
-              </connectionPointIn>
-              <expression>ACK</expression>
-            </outVariable>
-            <outVariable localId="6" height="35" width="75">
-              <position x="740" y="650"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="1" formalParameter="RESULT">
-                  <position x="740" y="665"/>
-                  <position x="650" y="665"/>
-                </connection>
-              </connectionPointIn>
-              <expression>RESULT</expression>
-            </outVariable>
-            <block localId="7" width="80" height="65" typeName="AND">
-              <position x="385" y="545"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="13" formalParameter="OUT">
-                      <position x="385" y="575"/>
-                      <position x="335" y="575"/>
-                      <position x="335" y="455"/>
-                      <position x="625" y="455"/>
-                      <position x="625" y="285"/>
-                      <position x="615" y="285"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="55"/>
-                    <connection refLocalId="3">
-                      <position x="385" y="600"/>
-                      <position x="330" y="600"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="80" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="9" height="35" width="85">
-              <position x="240" y="330"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>COUNTER</expression>
-            </inVariable>
-            <block localId="10" width="80" height="65" typeName="ADD">
-              <position x="380" y="330"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="9">
-                      <position x="380" y="360"/>
-                      <position x="352" y="360"/>
-                      <position x="352" y="345"/>
-                      <position x="325" y="345"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="55"/>
-                    <connection refLocalId="11">
-                      <position x="380" y="385"/>
-                      <position x="325" y="385"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="80" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="11" height="35" width="85">
-              <position x="240" y="370"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>USINT#1</expression>
-            </inVariable>
-            <block localId="13" width="80" height="65" typeName="EQ">
-              <position x="535" y="255"/>
-              <inputVariables>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="30"/>
-                    <connection refLocalId="2">
-                      <position x="535" y="285"/>
-                      <position x="460" y="285"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN2">
-                  <connectionPointIn>
-                    <relPosition x="0" y="55"/>
-                    <connection refLocalId="10" formalParameter="OUT">
-                      <position x="535" y="310"/>
-                      <position x="497" y="310"/>
-                      <position x="497" y="360"/>
-                      <position x="460" y="360"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="80" y="30"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <block localId="15" width="80" height="135" typeName="SEL">
-              <position x="785" y="245"/>
-              <inputVariables>
-                <variable formalParameter="G">
-                  <connectionPointIn>
-                    <relPosition x="0" y="40"/>
-                    <connection refLocalId="13" formalParameter="OUT">
-                      <position x="785" y="285"/>
-                      <position x="615" y="285"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN0">
-                  <connectionPointIn>
-                    <relPosition x="0" y="75"/>
-                    <connection refLocalId="10" formalParameter="OUT">
-                      <position x="785" y="320"/>
-                      <position x="650" y="320"/>
-                      <position x="650" y="360"/>
-                      <position x="460" y="360"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-                <variable formalParameter="IN1">
-                  <connectionPointIn>
-                    <relPosition x="0" y="115"/>
-                    <connection refLocalId="16">
-                      <position x="785" y="360"/>
-                      <position x="760" y="360"/>
-                    </connection>
-                  </connectionPointIn>
-                </variable>
-              </inputVariables>
-              <inOutVariables/>
-              <outputVariables>
-                <variable formalParameter="OUT">
-                  <connectionPointOut>
-                    <relPosition x="80" y="40"/>
-                  </connectionPointOut>
-                </variable>
-              </outputVariables>
-            </block>
-            <inVariable localId="16" height="35" width="85">
-              <position x="675" y="345"/>
-              <connectionPointOut>
-                <relPosition x="85" y="15"/>
-              </connectionPointOut>
-              <expression>USINT#0</expression>
-            </inVariable>
-            <outVariable localId="17" height="35" width="85">
-              <position x="905" y="270"/>
-              <connectionPointIn>
-                <relPosition x="0" y="15"/>
-                <connection refLocalId="15" formalParameter="OUT">
-                  <position x="905" y="285"/>
-                  <position x="865" y="285"/>
-                </connection>
-              </connectionPointIn>
-              <expression>COUNTER</expression>
-            </outVariable>
-          </FBD>
-        </body>
-      </pou>
-    </pous>
-  </types>
-  <instances>
-    <configurations/>
-  </instances>
-</project>
--- a/plugins/python/python.py	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-import wx
-import os
-import modules
-from plugger import PlugTemplate, opjimg
-from PLCControler import UndoBuffer
-from PythonEditor import PythonEditor
-
-from xml.dom import minidom
-from xmlclass import *
-import cPickle
-
-PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "python_xsd.xsd")) 
-
-class PythonCodeTemplate:
-    
-    EditorType = PythonEditor
-    
-    def __init__(self):
-        
-        self.PluginMethods.insert(0, 
-                {"bitmap" : opjimg("editPYTHONcode"),
-                 "name" : _("Edit Python File"), 
-                 "tooltip" : _("Edit Python File"),
-                 "method" : "_OpenView"},
-        )
-
-        filepath = self.PythonFileName()
-        
-        self.PythonCode = PythonClasses["Python"]()
-        if os.path.isfile(filepath):
-            xmlfile = open(filepath, 'r')
-            tree = minidom.parse(xmlfile)
-            xmlfile.close()
-            
-            for child in tree.childNodes:
-                if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python":
-                    self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
-                    self.CreatePythonBuffer(True)
-        else:
-            self.CreatePythonBuffer(False)
-            self.OnPlugSave()
-
-    def PluginPath(self):
-        return os.path.join(self.PlugParent.PluginPath(), "modules", self.PlugType)
-
-    def PythonFileName(self):
-        return os.path.join(self.PlugPath(), "python.xml")
-
-    def GetFilename(self):
-        if self.PythonBuffer.IsCurrentSaved():
-            return "python"
-        else:
-            return "~python~"
-
-    def SetPythonCode(self, text):
-        self.PythonCode.settext(text)
-        
-    def GetPythonCode(self):
-        return self.PythonCode.gettext()
-    
-    def PlugTestModified(self):
-        return self.ChangesToSave or not self.PythonIsSaved()
-    
-    def OnPlugSave(self):
-        filepath = self.PythonFileName()
-        
-        text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
-        extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
-                  "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
-                  "xsi:schemaLocation" : "python_xsd.xsd"}
-        text += self.PythonCode.generateXMLText("Python", 0, extras)
-
-        xmlfile = open(filepath,"w")
-        xmlfile.write(text.encode("utf-8"))
-        xmlfile.close()
-        
-        self.MarkPythonAsSaved()
-        return True
-        
-#-------------------------------------------------------------------------------
-#                      Current Buffering Management Functions
-#-------------------------------------------------------------------------------
-
-    """
-    Return a copy of the project
-    """
-    def Copy(self, model):
-        return cPickle.loads(cPickle.dumps(model))
-
-    def CreatePythonBuffer(self, saved):
-        self.Buffering = False
-        self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved)
-
-    def BufferPython(self):
-        self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
-    
-    def StartBuffering(self):
-        self.Buffering = True
-        
-    def EndBuffering(self):
-        if self.Buffering:
-            self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode))
-            self.Buffering = False
-    
-    def MarkPythonAsSaved(self):
-        self.EndBuffering()
-        self.PythonBuffer.CurrentSaved()
-    
-    def PythonIsSaved(self):
-        return self.PythonBuffer.IsCurrentSaved() and not self.Buffering
-        
-    def LoadPrevious(self):
-        self.EndBuffering()
-        self.PythonCode = cPickle.loads(self.PythonBuffer.Previous())
-    
-    def LoadNext(self):
-        self.PythonCode = cPickle.loads(self.PythonBuffer.Next())
-    
-    def GetBufferState(self):
-        first = self.PythonBuffer.IsFirst() and not self.Buffering
-        last = self.PythonBuffer.IsLast()
-        return not first, not last
-
-def _GetClassFunction(name):
-    def GetRootClass():
-        __import__("plugins.python.modules." + name)
-        return getattr(modules, name).RootClass
-    return GetRootClass
-
-class RootClass(PythonCodeTemplate):
-
-    # For root object, available Childs Types are modules of the modules packages.
-    PlugChildsTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)]
-    
-    def PluginPath(self):
-        return os.path.join(self.PlugParent.PluginPath(), self.PlugType)
-    
-    def PlugGenerate_C(self, buildpath, locations):
-        """
-        Generate C code
-        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
-        @param locations: List of complete variables locations \
-            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
-            "NAME" : name of the variable (generally "__IW0_1_2" style)
-            "DIR" : direction "Q","I" or "M"
-            "SIZE" : size "X", "B", "W", "D", "L"
-            "LOC" : tuple of interger for IEC location (0,1,2,...)
-            }, ...]
-        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
-        """
-        current_location = self.GetCurrentLocation()
-        # define a unique name for the generated C file
-        location_str = "_".join(map(lambda x:str(x), current_location))
-        
-        plugin_root = self.GetPlugRoot()
-        plugin_root.GetIECProgramsAndVariables()
-        
-        plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c")
-        plc_python_file = open(plc_python_filepath, 'r')
-        plc_python_code = plc_python_file.read()
-        plc_python_file.close()
-        python_eval_fb_list = []
-        for v in plugin_root._VariablesList:
-            if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]:
-                python_eval_fb_list.append(v)
-        python_eval_fb_count = max(1, len(python_eval_fb_list))
-        
-        # prepare python code
-        plc_python_code = plc_python_code % {
-           "python_eval_fb_count": python_eval_fb_count,
-           "location": location_str}
-        
-        Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str)
-        pythonfile = open(Gen_Pythonfile_path,'w')
-        pythonfile.write(plc_python_code)
-        pythonfile.close()
-        
-        runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str)
-        runtimefile = open(runtimefile_path, 'w')
-        runtimefile.write(self.GetPythonCode())
-        runtimefile.close()
-        
-        matiec_flags = '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath())
-        
-        return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb"))
--- a/plugins/python/python_xsd.xsd	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<xsd:schema targetNamespace="python_xsd.xsd" 
-            xmlns:cext="python_xsd.xsd" 
-            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-            elementFormDefault="qualified" 
-            attributeFormDefault="unqualified">
-
-  <xsd:element name="Python">
-	  <xsd:complexType>
-	    <xsd:annotation>
-	      <xsd:documentation>Formatted text according to parts of XHTML 1.1</xsd:documentation>
-	    </xsd:annotation>
-	    <xsd:sequence>
-	      <xsd:any namespace="http://www.w3.org/1999/xhtml" processContents="lax"/>
-	    </xsd:sequence>
-	  </xsd:complexType>
-	</xsd:element>
-</xsd:schema>
--- a/runtime/PLCObject.py	Thu May 03 19:02:34 2012 +0200
+++ b/runtime/PLCObject.py	Mon May 07 18:47:29 2012 +0200
@@ -109,7 +109,7 @@
                 
                 self._stopPLC = self._stopPLC_real
             else:
-                # If python plugin is not enabled, we reuse _PythonIterator
+                # If python confnode is not enabled, we reuse _PythonIterator
                 # as a call that block pythonthread until StopPLC 
                 self.PythonIteratorLock = Lock()
                 self.PythonIteratorLock.acquire()
--- a/targets/LPC/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ b/targets/LPC/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -6,9 +6,9 @@
 class LPC_target(toolchain_makefile):
     #extension = ".ld"
     #DebugEnabled = False
-    def __init__(self, PluginsRootInstance):
+    def __init__(self, ConfigTreeRootInstance):
         self.binmd5key = None
-        toolchain_makefile.__init__(self, PluginsRootInstance)
+        toolchain_makefile.__init__(self, ConfigTreeRootInstance)
 
     def _GetBinMD5FileName(self):
         return os.path.join(self.buildpath, "lastbuildPLCbin.md5")
@@ -64,7 +64,7 @@
             f.write(self.binmd5key)
             f.close()
             try:
-                self.PluginsRootInstance.logger.write(
+                self.ConfigTreeRootInstance.logger.write(
                     _("Binary is %s bytes long\n")%
                         str(os.path.getsize(
                             os.path.join(self.buildpath, "ArmPLC_rom.bin"))))
--- a/targets/Xenomai/__init__.py	Thu May 03 19:02:34 2012 +0200
+++ b/targets/Xenomai/__init__.py	Mon May 07 18:47:29 2012 +0200
@@ -4,14 +4,14 @@
     extension = ".so"
     def getXenoConfig(self, flagsname):
         """ Get xeno-config from target parameters """
-        xeno_config=self.PluginsRootInstance.GetTarget().getcontent()["value"].getXenoConfig()
+        xeno_config=self.ConfigTreeRootInstance.GetTarget().getcontent()["value"].getXenoConfig()
         if xeno_config:
             from wxPopen import ProcessLogger
-            status, result, err_result = ProcessLogger(self.PluginsRootInstance.logger,
+            status, result, err_result = ProcessLogger(self.ConfigTreeRootInstance.logger,
                                                        xeno_config + " --skin=native --"+flagsname,
                                                        no_stdout=True).spin()
             if status:
-                self.PluginsRootInstance.logger.write_error(_("Unable to get Xenomai's %s \n")%flagsname)
+                self.ConfigTreeRootInstance.logger.write_error(_("Unable to get Xenomai's %s \n")%flagsname)
             return [result.strip()]
         return []
     
--- a/targets/toolchain_gcc.py	Thu May 03 19:02:34 2012 +0200
+++ b/targets/toolchain_gcc.py	Mon May 07 18:47:29 2012 +0200
@@ -10,23 +10,23 @@
     It cannot be used as this and should be inherited in a target specific
     class such as target_linux or target_win32
     """
-    def __init__(self, PluginsRootInstance):
-        self.PluginsRootInstance = PluginsRootInstance
+    def __init__(self, ConfigTreeRootInstance):
+        self.ConfigTreeRootInstance = ConfigTreeRootInstance
         self.buildpath = None
-        self.SetBuildPath(self.PluginsRootInstance._getBuildPath())
+        self.SetBuildPath(self.ConfigTreeRootInstance._getBuildPath())
     
     def getBuilderCFLAGS(self):
         """
         Returns list of builder specific CFLAGS
         """
-        return [self.PluginsRootInstance.GetTarget().getcontent()["value"].getCFLAGS()]
+        return [self.ConfigTreeRootInstance.GetTarget().getcontent()["value"].getCFLAGS()]
 
     def getBuilderLDFLAGS(self):
         """
         Returns list of builder specific LDFLAGS
         """
-        return self.PluginsRootInstance.LDFLAGS + \
-               [self.PluginsRootInstance.GetTarget().getcontent()["value"].getLDFLAGS()]
+        return self.ConfigTreeRootInstance.LDFLAGS + \
+               [self.ConfigTreeRootInstance.GetTarget().getcontent()["value"].getLDFLAGS()]
 
     def GetBinaryCode(self):
         try:
@@ -56,7 +56,7 @@
     def SetBuildPath(self, buildpath):
         if self.buildpath != buildpath:
             self.buildpath = buildpath
-            self.exe = self.PluginsRootInstance.GetProjectName() + self.extension
+            self.exe = self.ConfigTreeRootInstance.GetProjectName() + self.extension
             self.exe_path = os.path.join(self.buildpath, self.exe)
             self.md5key = None
             self.srcmd5 = {}
@@ -89,7 +89,7 @@
                 
     def build(self):
         # Retrieve toolchain user parameters
-        toolchain_params = self.PluginsRootInstance.GetTarget().getcontent()["value"]
+        toolchain_params = self.ConfigTreeRootInstance.GetTarget().getcontent()["value"]
         self.compiler = toolchain_params.getCompiler()
         self.linker = toolchain_params.getLinker()
 
@@ -99,11 +99,11 @@
         obns = []
         objs = []
         relink = False
-        for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS:
+        for Location, CFilesAndCFLAGS, DoCalls in self.ConfigTreeRootInstance.LocationCFilesAndCFLAGS:
             if Location:
-                self.PluginsRootInstance.logger.write(_("Plugin : ") + self.PluginsRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n")
+                self.ConfigTreeRootInstance.logger.write(_("ConfNode : ") + self.ConfigTreeRootInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n")
             else:
-                self.PluginsRootInstance.logger.write(_("PLC :\n"))
+                self.ConfigTreeRootInstance.logger.write(_("PLC :\n"))
                 
             for CFile, CFLAGS in CFilesAndCFLAGS:
                 if CFile.endswith(".c"):
@@ -114,21 +114,21 @@
                     match = self.check_and_update_hash_and_deps(bn)
                     
                     if match:
-                        self.PluginsRootInstance.logger.write("   [pass]  "+bn+" -> "+obn+"\n")
+                        self.ConfigTreeRootInstance.logger.write("   [pass]  "+bn+" -> "+obn+"\n")
                     else:
                         relink = True
 
-                        self.PluginsRootInstance.logger.write("   [CC]  "+bn+" -> "+obn+"\n")
+                        self.ConfigTreeRootInstance.logger.write("   [CC]  "+bn+" -> "+obn+"\n")
                         
                         status, result, err_result = ProcessLogger(
-                               self.PluginsRootInstance.logger,
+                               self.ConfigTreeRootInstance.logger,
                                "\"%s\" -c \"%s\" -o \"%s\" %s %s"%
                                    (self.compiler, CFile, objectfilename, Builder_CFLAGS, CFLAGS)
                                ).spin()
 
                         if status :
                             self.srcmd5.pop(bn)
-                            self.PluginsRootInstance.logger.write_error(_("C compilation of %s failed.\n")%bn)
+                            self.ConfigTreeRootInstance.logger.write_error(_("C compilation of %s failed.\n")%bn)
                             return False
                     obns.append(obn)
                     objs.append(objectfilename)
@@ -138,7 +138,7 @@
 
         ######### GENERATE library FILE ########################################
         # Link all the object files into one binary file
-        self.PluginsRootInstance.logger.write(_("Linking :\n"))
+        self.ConfigTreeRootInstance.logger.write(_("Linking :\n"))
         if relink:
             objstring = []
     
@@ -147,10 +147,10 @@
     
             ALLldflags = ' '.join(self.getBuilderLDFLAGS())
     
-            self.PluginsRootInstance.logger.write("   [CC]  " + ' '.join(obns)+" -> " + self.exe + "\n")
+            self.ConfigTreeRootInstance.logger.write("   [CC]  " + ' '.join(obns)+" -> " + self.exe + "\n")
     
             status, result, err_result = ProcessLogger(
-                   self.PluginsRootInstance.logger,
+                   self.ConfigTreeRootInstance.logger,
                    "\"%s\" %s -o \"%s\" %s"%
                        (self.linker,
                         listobjstring,
@@ -162,7 +162,7 @@
                 return False
                 
         else:
-            self.PluginsRootInstance.logger.write("   [pass]  " + ' '.join(obns)+" -> " + self.exe + "\n")
+            self.ConfigTreeRootInstance.logger.write("   [pass]  " + ' '.join(obns)+" -> " + self.exe + "\n")
         
         # Calculate md5 key and get data for the new created PLC
         data=self.GetBinaryCode()
--- a/targets/toolchain_makefile.py	Thu May 03 19:02:34 2012 +0200
+++ b/targets/toolchain_makefile.py	Mon May 07 18:47:29 2012 +0200
@@ -7,11 +7,11 @@
 includes_re =  re.compile('\s*#include\s*["<]([^">]*)[">].*')
 
 class toolchain_makefile():
-    def __init__(self, PluginsRootInstance):
-        self.PluginsRootInstance = PluginsRootInstance
+    def __init__(self, ConfigTreeRootInstance):
+        self.ConfigTreeRootInstance = ConfigTreeRootInstance
         self.md5key = None 
         self.buildpath = None
-        self.SetBuildPath(self.PluginsRootInstance._getBuildPath())
+        self.SetBuildPath(self.ConfigTreeRootInstance._getBuildPath())
 
     def SetBuildPath(self, buildpath):
         if self.buildpath != buildpath:
@@ -60,7 +60,7 @@
         srcfiles= []
         cflags = []
         wholesrcdata = "" 
-        for Location, CFilesAndCFLAGS, DoCalls in self.PluginsRootInstance.LocationCFilesAndCFLAGS:
+        for Location, CFilesAndCFLAGS, DoCalls in self.ConfigTreeRootInstance.LocationCFilesAndCFLAGS:
             # Get CFiles list to give it to makefile
             for CFile, CFLAGS in CFilesAndCFLAGS:
                 CFileName = os.path.basename(CFile)
@@ -72,7 +72,7 @@
                         
         oldmd5 = self.md5key
         self.md5key = hashlib.md5(wholesrcdata).hexdigest()
-        props = self.PluginsRootInstance.GetProjectProperties()
+        props = self.ConfigTreeRootInstance.GetProjectProperties()
         self.md5key += '#'.join([props[key] for key in ['companyName',
                                                         'projectName',
                                                         'productName']])
@@ -88,21 +88,21 @@
                               "md5": '"'+self.md5key+'"'
                              }
             
-            target = self.PluginsRootInstance.GetTarget().getcontent()["value"]
+            target = self.ConfigTreeRootInstance.GetTarget().getcontent()["value"]
             command = target.getCommand().split(' ') +\
                       [target.getBuildPath()] +\
                       [arg % beremizcommand for arg in target.getArguments().split(' ')] +\
                       target.getRule().split(' ')
             
             # Call Makefile to build PLC code and link it with target specific code
-            status, result, err_result = ProcessLogger(self.PluginsRootInstance.logger,
+            status, result, err_result = ProcessLogger(self.ConfigTreeRootInstance.logger,
                                                        command).spin()
             if status :
                 self.md5key = None
-                self.PluginsRootInstance.logger.write_error(_("C compilation failed.\n"))
+                self.ConfigTreeRootInstance.logger.write_error(_("C compilation failed.\n"))
                 return False
             return True
         else :
-            self.PluginsRootInstance.logger.write(_("Source didn't change, no build.\n"))
+            self.ConfigTreeRootInstance.logger.write(_("Source didn't change, no build.\n"))
             return True
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="canopen" IEC_Channel="0"/>
--- a/tests/canopen_master/canopen@canfestival/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="canopen" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/confnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CanFestivalInstance/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="master" IEC_Channel="0"/>
--- a/tests/canopen_master/canopen@canfestival/master@CanOpenNode/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="master" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_master/canopen@canfestival/master@CanOpenNode/confnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CanFestivalNode/>
--- a/tests/canopen_master/canopen@canfestival/master@CanOpenNode/plugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<CanFestivalNode/>
--- a/tests/canopen_master/canopen@canfestival/plugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<CanFestivalInstance/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="canopen" IEC_Channel="0"/>
--- a/tests/canopen_slave/canopen@canfestival/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="canopen" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/confnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CanFestivalInstance/>
--- a/tests/canopen_slave/canopen@canfestival/plugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<CanFestivalInstance/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="slave" IEC_Channel="0"/>
--- a/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="slave" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/confnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CanFestivalSlaveNode/>
--- a/tests/canopen_slave/canopen@canfestival/slave@CanOpenSlave/plugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<CanFestivalSlaveNode/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/python@python/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="python" IEC_Channel="0"/>
--- a/tests/python/python@python/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="python" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@python/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="python" IEC_Channel="0"/>
--- a/tests/svgui/python@python/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="python" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svgui/python@python/svgui@svgui/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="svgui" IEC_Channel="0"/>
--- a/tests/svgui/python@python/svgui@svgui/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="svgui" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="HMIFrame" IEC_Channel="0"/>
--- a/tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="HMIFrame" IEC_Channel="0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/wxGlade/python@python/baseconfnode.xml	Mon May 07 18:47:29 2012 +0200
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BaseParams Name="python" IEC_Channel="0"/>
--- a/tests/wxGlade/python@python/baseplugin.xml	Thu May 03 19:02:34 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<BaseParams Name="python" IEC_Channel="0"/>