refactoring
authorEdouard Tisserant
Tue, 08 May 2012 17:08:45 +0200
changeset 721 ecf4d203c4d4
parent 720 6be032177e2a
child 722 a94f361fc42e
refactoring
ConfigTree.py
LPCBeremiz.py
c_ext/.cvsignore
c_ext/CFileEditor.py
c_ext/README
c_ext/__init__.py
c_ext/c_ext.py
c_ext/cext_xsd.xsd
canfestival/.cvsignore
canfestival/NetworkEditor.py
canfestival/README
canfestival/SlaveEditor.py
canfestival/__init__.py
canfestival/canfestival.py
canfestival/cf_runtime.c
canfestival/config_utils.py
canfestival/test_config/eds/PEAK MicroMod.eds
canfestival/test_config/master.od
canfestival/test_config/nodelist.cpj
canfestival/test_config/result.txt
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
features.py
py_ext/PythonEditor.py
py_ext/README
py_ext/__init__.py
py_ext/modules/__init__.py
py_ext/modules/svgui/README
py_ext/modules/svgui/__init__.py
py_ext/modules/svgui/livesvg.js
py_ext/modules/svgui/pous.xml
py_ext/modules/svgui/pyjs/__init__.py
py_ext/modules/svgui/pyjs/build.py
py_ext/modules/svgui/pyjs/jsonrpc/README.txt
py_ext/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py
py_ext/modules/svgui/pyjs/jsonrpc/jsonrpc.py
py_ext/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py
py_ext/modules/svgui/pyjs/lib/_pyjs.js
py_ext/modules/svgui/pyjs/lib/json.js
py_ext/modules/svgui/pyjs/lib/pyjslib.py
py_ext/modules/svgui/pyjs/lib/sys.py
py_ext/modules/svgui/pyjs/pyjs.py
py_ext/modules/svgui/svgui.py
py_ext/modules/svgui/svgui_server.py
py_ext/modules/svgui/svguilib.py
py_ext/modules/wxglade_hmi/README
py_ext/modules/wxglade_hmi/__init__.py
py_ext/modules/wxglade_hmi/wxglade_hmi.py
py_ext/plc_python.c
py_ext/pous.xml
py_ext/py_ext.py
py_ext/py_ext_xsd.xsd
tests/python/python@py_ext/baseconfnode.xml
tests/python/python@py_ext/py_ext.xml
tests/python/python@python/baseconfnode.xml
tests/python/python@python/python.xml
tests/svgui/python@py_ext/baseconfnode.xml
tests/svgui/python@py_ext/py_ext.xml
tests/svgui/python@py_ext/svgui@svgui/baseconfnode.xml
tests/svgui/python@py_ext/svgui@svgui/gui.svg
tests/svgui/python@py_ext/svgui@svgui/py_ext.xml
tests/svgui/python@python/baseconfnode.xml
tests/svgui/python@python/python.xml
tests/svgui/python@python/svgui@svgui/baseconfnode.xml
tests/svgui/python@python/svgui@svgui/gui.svg
tests/svgui/python@python/svgui@svgui/python.xml
tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/baseconfnode.xml
tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/hmi.wxg
tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/py_ext.xml
tests/wxGlade/python@py_ext/baseconfnode.xml
tests/wxGlade/python@py_ext/py_ext.xml
tests/wxGlade/python@python/HMIFrame@wxglade_hmi/baseconfnode.xml
tests/wxGlade/python@python/HMIFrame@wxglade_hmi/hmi.wxg
tests/wxGlade/python@python/HMIFrame@wxglade_hmi/python.xml
tests/wxGlade/python@python/baseconfnode.xml
tests/wxGlade/python@python/python.xml
--- a/ConfigTree.py	Tue May 08 16:31:12 2012 +0200
+++ b/ConfigTree.py	Tue May 08 17:08:45 2012 +0200
@@ -4,7 +4,7 @@
 
 import os,sys,traceback
 import time
-import confnodes
+import features
 import types
 import shutil
 from xml.dom import minidom
@@ -752,7 +752,7 @@
     """
 
     # For root object, available Children Types are modules of the confnode packages.
-    CTNChildrenTypes =  [(n, CTNClassFactory(c), d) for n,d,h,c in confnodes.catalog]
+    CTNChildrenTypes =  [(n, CTNClassFactory(c), d) for n,d,h,c in features.catalog]
 
     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
@@ -1054,7 +1054,7 @@
         return children
     
     def ConfNodePath(self):
-        return os.path.join(os.path.split(__file__)[0], "confnodes")
+        return os.path.split(__file__)[0]
     
     def CTNPath(self, CTNName=None):
         return self.ProjectPath
@@ -1480,13 +1480,12 @@
         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(_("Runtime extensions C code generation failed !\n"))
             self.logger.write_error(traceback.format_exc())
             self.ResetBuildMD5()
             return False
--- a/LPCBeremiz.py	Tue May 08 16:31:12 2012 +0200
+++ b/LPCBeremiz.py	Tue May 08 17:08:45 2012 +0200
@@ -67,8 +67,8 @@
 
 havecanfestival = False
 try:
-    from confnodes.canfestival import RootClass as CanOpenRootClass
-    from confnodes.canfestival.canfestival import _SlaveCTN, _NodeListCTN, NodeManager
+    from canfestival import RootClass as CanOpenRootClass
+    from canfestival.canfestival import _SlaveCTN, _NodeListCTN, NodeManager
     havecanfestival = True
 except:
     havecanfestival = False
@@ -77,7 +77,7 @@
 #-------------------------------------------------------------------------------
 #                          CANFESTIVAL CONFNODE HACK
 #-------------------------------------------------------------------------------
-# from confnodes.canfestival import canfestival
+# from canfestival import canfestival
 # class LPC_canfestival_config:
 #     def getCFLAGS(self, *args):
 #         return ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/.cvsignore	Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/CFileEditor.py	Tue May 08 17:08:45 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.CTNFullName()
+        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/c_ext/README	Tue May 08 17:08:45 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/c_ext/__init__.py	Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+from c_ext import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/c_ext.py	Tue May 08 17:08:45 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.OnCTNSave()
+
+    def CFileName(self):
+        return os.path.join(self.CTNPath(), "cfile.xml")
+
+    def GetBaseTypes(self):
+        return self.GetCTRoot().GetBaseTypes()
+
+    def GetDataTypes(self, basetypes = False, only_locatables = False):
+        return self.GetCTRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
+
+    def GetSizeOfType(self, type):
+        return TYPECONVERSION.get(self.GetCTRoot().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 CTNTestModified(self):
+        return self.ChangesToSave or not self.CFileIsSaved()    
+
+    def OnCTNSave(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 CTNGenerate_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.GetCTRoot().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.GetCTRoot().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:
+
+    CTNChildrenTypes = [("C_File",_Cfile, "C file")]
+    
+    def CTNGenerate_C(self, buildpath, locations):
+        return [],"",False
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c_ext/cext_xsd.xsd	Tue May 08 17:08:45 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/canfestival/.cvsignore	Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+*.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/NetworkEditor.py	Tue May 08 17:08:45 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.CTNFullName()
+        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/canfestival/README	Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+CANOpen
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/SlaveEditor.py	Tue May 08 17:08:45 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.CTNFullName()
+        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/canfestival/__init__.py	Tue May 08 17:08:45 2012 +0200
@@ -0,0 +1,1 @@
+from canfestival import *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/canfestival/canfestival.py	Tue May 08 17:08:45 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 _SlaveCTN(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.OnCTNSave()
+
+    def GetSlaveODPath(self):
+        return os.path.join(self.CTNPath(), '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 OnCTNClose(self):
+        if self._View:
+            self._View.Close()
+
+    def CTNTestModified(self):
+        return self.ChangesToSave or self.OneFileHasChanged()
+        
+    def OnCTNSave(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 CTNGenerate_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 CTNFullName(self):
+        return self.Fullname
+    
+    def GetBufferState(self):
+        return self.GetCurrentBufferState()
+
+class _NodeListCTN(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.CTNPath())
+        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.GetCTRoot().logger.write_error(_("Error: No PLC built\n"))
+                return
+            
+            masterpath = os.path.join(buildpath, "MasterGenerated.od")
+            if not os.path.exists(masterpath):
+                self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
+                return
+            
+            app_frame = self.GetCTRoot().AppFrame
+            
+            manager = MiniNodeManager(self, masterpath, self.CTNFullName() + ".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.GetCTRoot().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 OnCTNClose(self):
+        ConfigTreeNode.OnCTNClose(self)
+        self._CloseGenerateView()
+        return True
+
+    def CTNTestModified(self):
+        return self.ChangesToSave or self.HasChanged()
+        
+    def OnCTNSave(self):
+        self.SetRoot(self.CTNPath())
+        return self.SaveProject() is None
+
+    def CTNGenerate_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
+    
+    CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"),
+                       ("CanOpenSlave",_SlaveCTN, "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 CTNGenerate_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.IECSortedChildren():
+            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/canfestival/cf_runtime.c	Tue May 08 17:08:45 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/canfestival/config_utils.py	Tue May 08 17:08:45 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/canfestival/test_config/eds/PEAK MicroMod.eds	Tue May 08 17:08:45 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/canfestival/test_config/master.od	Tue May 08 17:08:45 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/canfestival/test_config/nodelist.cpj	Tue May 08 17:08:45 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/canfestival/test_config/result.txt	Tue May 08 17:08:45 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'}
--- a/confnodes/.cvsignore	Tue May 08 16:31:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
--- a/confnodes/__init__.py	Tue May 08 16:31:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-from os import listdir, path
-
-catalog = [
-    ('canfestival', _('CANopen support'), _('Map located variables over CANopen'), 'confnodes.canfestival.canfestival.RootClass'),
-    ('c_ext', _('C extention'), _('Extend project with C code accessing located variables'), 'confnodes.c_ext.c_ext.RootClass'),
-    ('python', _('Python extention'), _('Extend project with Pyhon code executed asynchronously'), 'confnodes.python.python.RootClass')]
-#    ('ethercat_master', _('Ethercat master'), _('Map located variables over EtherCat, as a master'), 'ethercat.EthercatPlug')]
-
-
-
--- a/confnodes/c_ext/.cvsignore	Tue May 08 16:31:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
--- a/confnodes/c_ext/CFileEditor.py	Tue May 08 16:31:12 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.CTNFullName()
-        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/confnodes/c_ext/README	Tue May 08 16:31:12 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/confnodes/c_ext/__init__.py	Tue May 08 16:31:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from c_ext import *
--- a/confnodes/c_ext/c_ext.py	Tue May 08 16:31:12 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 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.OnCTNSave()
-
-    def CFileName(self):
-        return os.path.join(self.CTNPath(), "cfile.xml")
-
-    def GetBaseTypes(self):
-        return self.GetCTRoot().GetBaseTypes()
-
-    def GetDataTypes(self, basetypes = False, only_locatables = False):
-        return self.GetCTRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
-
-    def GetSizeOfType(self, type):
-        return TYPECONVERSION.get(self.GetCTRoot().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 CTNTestModified(self):
-        return self.ChangesToSave or not self.CFileIsSaved()    
-
-    def OnCTNSave(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 CTNGenerate_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.GetCTRoot().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.GetCTRoot().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:
-
-    CTNChildrenTypes = [("C_File",_Cfile, "C file")]
-    
-    def CTNGenerate_C(self, buildpath, locations):
-        return [],"",False
-
-
--- a/confnodes/c_ext/cext_xsd.xsd	Tue May 08 16:31:12 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/confnodes/canfestival/.cvsignore	Tue May 08 16:31:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-*.pyc
--- a/confnodes/canfestival/NetworkEditor.py	Tue May 08 16:31:12 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_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.CTNFullName()
-        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)
-        
--- a/confnodes/canfestival/README	Tue May 08 16:31:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-CANOpen
\ No newline at end of file
--- a/confnodes/canfestival/SlaveEditor.py	Tue May 08 16:31:12 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_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.CTNFullName()
-        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/confnodes/canfestival/__init__.py	Tue May 08 16:31:12 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-from canfestival import *
--- a/confnodes/canfestival/canfestival.py	Tue May 08 16:31:12 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 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 _SlaveCTN(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.OnCTNSave()
-
-    def GetSlaveODPath(self):
-        return os.path.join(self.CTNPath(), '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 OnCTNClose(self):
-        if self._View:
-            self._View.Close()
-
-    def CTNTestModified(self):
-        return self.ChangesToSave or self.OneFileHasChanged()
-        
-    def OnCTNSave(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 CTNGenerate_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 CTNFullName(self):
-        return self.Fullname
-    
-    def GetBufferState(self):
-        return self.GetCurrentBufferState()
-
-class _NodeListCTN(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.CTNPath())
-        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.GetCTRoot().logger.write_error(_("Error: No PLC built\n"))
-                return
-            
-            masterpath = os.path.join(buildpath, "MasterGenerated.od")
-            if not os.path.exists(masterpath):
-                self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
-                return
-            
-            app_frame = self.GetCTRoot().AppFrame
-            
-            manager = MiniNodeManager(self, masterpath, self.CTNFullName() + ".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.GetCTRoot().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 OnCTNClose(self):
-        ConfigTreeNode.OnCTNClose(self)
-        self._CloseGenerateView()
-        return True
-
-    def CTNTestModified(self):
-        return self.ChangesToSave or self.HasChanged()
-        
-    def OnCTNSave(self):
-        self.SetRoot(self.CTNPath())
-        return self.SaveProject() is None
-
-    def CTNGenerate_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
-    
-    CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"),
-                       ("CanOpenSlave",_SlaveCTN, "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 CTNGenerate_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.IECSortedChildren():
-            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/confnodes/canfestival/cf_runtime.c	Tue May 08 16:31:12 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/confnodes/canfestival/config_utils.py	Tue May 08 16:31:12 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/confnodes/canfestival/test_config/eds/PEAK MicroMod.eds	Tue May 08 16:31:12 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]
-Paramet