Salome HOME
[bos #32720] EDF 25230 - partition fails on small case
[modules/geom.git] / src / GEOM / GEOM_Engine.cxx
index 32d3e97c284ab764724d4ac44f6fb2496ef9e01c..14a0c516d8411af592dbe4fd673cd8a4873aad67 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// 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
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#ifdef WNT
+#ifdef WIN32
 #pragma warning( disable:4786 )
 #endif
 
 #include "GEOM_Engine.hxx"
 
-#include "GEOM_Solver.hxx"
+#include "GEOM_Field.hxx"
 #include "GEOM_Function.hxx"
 #include "GEOM_ISubShape.hxx"
-#include "GEOM_SubShapeDriver.hxx"
-#include "GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient.hxx"
 #include "GEOM_PythonDump.hxx"
-
-#include <Basics_OCCTVersion.hxx>
+#include "GEOM_Solver.hxx"
+#include "GEOM_SubShapeDriver.hxx"
+#include "Sketcher_Profile.hxx"
 
 #include "utilities.h"
 
 #include <Basics_Utils.hxx>
+#include <Basics_OCCTVersion.hxx>
 
 #include <TDF_Tool.hxx>
 #include <TDF_Data.hxx>
 #include <TColStd_MapOfTransient.hxx>
 #include <TColStd_HSequenceOfInteger.hxx>
 
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
-#include <TColStd_HArray1OfByte.hxx>
 #include <TColStd_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
-#else
-#include <TDataStd_HArray1OfByte.hxx>
-#include <Interface_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
-#endif
 
+#if OCC_VERSION_LARGE < 0x07050000
 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
+#endif
+
+#include <BinDrivers.hxx>
+#include <StdDrivers_DocumentRetrievalDriver.hxx>
+#include <PCDM_StorageDriver.hxx>
 
 #include <set>
 
 #define C_SQR_BRACKET ']'
 #define PY_NULL "None"
 
-#ifdef _DEBUG_
-static int MYDEBUG = 0;
-#else
-static int MYDEBUG = 0;
-#endif
+// VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
+// Next macro, when defined, causes appearing of SubShapeAllIDs(), SubShapeAllSortedIDs(), GetSameIDs()
+// and other such commands in Python dump.
+// See also GEOMImpl_IShapesOperations.cxx.
+// ---------------------------------------
+// #define DUMP_SUBSHAPE_IDS
+// ---------------------------------------
 
 typedef std::map< TCollection_AsciiString, TCollection_AsciiString > TSting2StringMap;
 typedef std::map< TCollection_AsciiString, TObjectData >             TSting2ObjDataMap;
 typedef std::map< TCollection_AsciiString, TObjectData* >            TSting2ObjDataPtrMap;
+typedef std::map< int, std::list < int > >                           TIntToListIntMap;
 
 static GEOM_Engine* TheEngine = NULL;
 
 
-static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_Object)& theObject)
+static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_BaseObject)& theObject)
 {
-  TCollection_AsciiString anID(theObject->GetDocID()), anEntry;
+  TCollection_AsciiString anEntry;
   TDF_Tool::Entry(theObject->GetEntry(), anEntry);
-  anID+=(TCollection_AsciiString("_")+anEntry);
-  return anID;
-}
-
-static TCollection_AsciiString BuildID(Standard_Integer theDocID, char* theEntry)
-{
-  TCollection_AsciiString anID(theDocID);
-  anID+=(TCollection_AsciiString("_")+theEntry);
-  return anID;
-}
-
-static Standard_Integer ExtractDocID(TCollection_AsciiString& theID)
-{
-  TCollection_AsciiString aDocID = theID.Token("_");
-  if(aDocID.Length() < 1) return -1;
-  return aDocID.IntegerValue();
+  return anEntry;
 }
 
 bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
                      TCollection_AsciiString&           theScript,
                      TCollection_AsciiString&           theAfterScript,
                      const TVariablesList&              theVariables,
-                     const bool                         theIsPublished,
+                     const bool                         /*theIsPublished*/,
                      TDF_LabelMap&                      theProcessed,
                      std::set<TCollection_AsciiString>& theIgnoreObjs,
                      bool&                              theIsDumpCollected);
 
+static int GetTag(const TCollection_AsciiString &theEntry);
+
+static void FillMapOfRef(const Handle(GEOM_Function) &theFunction,
+                               TIntToListIntMap      &theRefMap);
+
 void ReplaceVariables(TCollection_AsciiString& theCommand,
                       const TVariablesList&    theVariables);
 
@@ -139,11 +132,10 @@ void ReplaceEntriesByNames (TCollection_AsciiString&                  theScript,
                             Standard_Integer&                         objectCounter,
                             Resource_DataMapOfAsciiStringAsciiString& aNameToEntry);
 
-void AddObjectColors (int                      theDocID,
-                      TCollection_AsciiString& theScript,
+void AddObjectColors (TCollection_AsciiString& theScript,
                       const TSting2ObjDataMap& theEntry2ObjData);
 
-void AddTextures (int theDocID, TCollection_AsciiString& theScript);
+void AddTextures (TCollection_AsciiString& theScript);
 
 void PublishObject (TObjectData&                              theObjectData,
                     TSting2ObjDataMap&                        theEntry2ObjData,
@@ -152,30 +144,36 @@ void PublishObject (TObjectData&                              theObjectData,
                     std::map< int, TCollection_AsciiString >& theEntryToCmdMap,
                     std::set<TCollection_AsciiString>&        theMapOfPublished);
 
-namespace
+static TCollection_AsciiString GetPublishCommands
+                   (const int                                       theTag,
+                    const std::map< int, TCollection_AsciiString > &theEntryToCmdMap,
+                    const TIntToListIntMap                         &theMapRefs,
+                          std::set< int >                          &thePublished);
+
+void Prettify(TCollection_AsciiString& theScript);
+
+//================================================================================
+/*!
+ * \brief Fix up the name of python variable
+ */
+//================================================================================
+
+void GEOM_Engine::healPyName( TCollection_AsciiString&                  pyName,
+                              const TCollection_AsciiString&            anEntry,
+                              Resource_DataMapOfAsciiStringAsciiString& aNameToEntry)
 {
-  //================================================================================
-  /*!
-   * \brief Fix up the name of python variable
-   */
-  //================================================================================
-
-  void healPyName( TCollection_AsciiString&                  pyName,
-                   const TCollection_AsciiString&            anEntry,
-                   Resource_DataMapOfAsciiStringAsciiString& aNameToEntry)
-  {
-    const TCollection_AsciiString allowedChars
-      ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
+  const TCollection_AsciiString allowedChars
+    ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
 
-    if ( pyName.IsIntegerValue() ) { // pyName must not start with a digit
-      pyName.Insert( 1, 'a' );
-    }
-    int p, p2=1; // replace not allowed chars
-    while ((p = pyName.FirstLocationNotInSet(allowedChars, p2, pyName.Length()))) {
-      pyName.SetValue(p, '_');
-      p2=p;
-    }
-    if ( aNameToEntry.IsBound( pyName ) && anEntry != aNameToEntry( pyName ))
+  if ( pyName.IsIntegerValue() ) { // pyName must not start with a digit
+    pyName.Insert( 1, 'a' );
+  }
+  int p, p2=1; // replace not allowed chars
+  while ((p = pyName.FirstLocationNotInSet(allowedChars, p2, pyName.Length()))) {
+    pyName.SetValue(p, '_');
+    p2=p;
+  }
+  if ( aNameToEntry.IsBound( pyName ) && anEntry != aNameToEntry( pyName ))
     {  // diff objects have same name - make a new name by appending a digit
       TCollection_AsciiString aName2;
       Standard_Integer i = 0;
@@ -184,7 +182,6 @@ namespace
       } while ( aNameToEntry.IsBound( aName2 ) && anEntry != aNameToEntry( aName2 ));
       pyName = aName2;
     }
-  }
 }
 
 //=======================================================================
@@ -221,7 +218,10 @@ GEOM_Engine::GEOM_Engine()
   TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
   
   _OCAFApp = new GEOM_Application();
-  _UndoLimit = 10;
+  _OCAFApp->DefineFormat("SALOME_GEOM", "GEOM Document Version 1.0", "sgd",
+                         new StdDrivers_DocumentRetrievalDriver, 0);
+  BinDrivers::DefineFormat(_OCAFApp);
+  _UndoLimit = 0;
 }
 
 /*!
@@ -237,18 +237,8 @@ GEOM_Engine::~GEOM_Engine()
   for(objit = objs.begin(); objit != objs.end(); ++objit)
     RemoveObject(*objit);
 
-  //Close all documents not closed
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
-  TColStd_DataMapIteratorOfDataMapOfIntegerTransient anItr (_mapIDDocument);
-#else
-  Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr (_mapIDDocument);
-#endif
-  for (; anItr.More(); anItr.Next())
-  {
-    Close(anItr.Key());
-    anItr.Initialize( _mapIDDocument ); // anItr becomes invalid at _mapIDDocument.UnBind(docId)
-  }
-  _mapIDDocument.Clear();
+  //Close document
+  Close();
   _objects.Clear();
 }
 
@@ -257,61 +247,47 @@ GEOM_Engine::~GEOM_Engine()
  *  GetDocument
  */
 //=============================================================================
-Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID, bool force)
+Handle(TDocStd_Document) GEOM_Engine::GetDocument(bool force)
 {
   Handle(TDocStd_Document) aDoc;
-  if(_mapIDDocument.IsBound(theDocID)) {
-    aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
+  if (_document) {
+    aDoc = _document;
   }
   else if (force) {
-    _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
+    _OCAFApp->NewDocument("BinOcaf", aDoc);
     aDoc->SetUndoLimit(_UndoLimit);
-    _mapIDDocument.Bind(theDocID, aDoc);
-    TDataStd_Integer::Set(aDoc->Main(), theDocID);
+    _document = aDoc;
   }
   return aDoc;
 }
 
-//=============================================================================
-/*!
- *  GetDocID
- */
-//=============================================================================
-int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument)
-{
-  if (theDocument.IsNull()) return -1;
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
-  TColStd_DataMapIteratorOfDataMapOfIntegerTransient anItr (_mapIDDocument);
-#else
-  Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr (_mapIDDocument);
-#endif
-  for (; anItr.More(); anItr.Next())
-    if (anItr.Value() == theDocument) return anItr.Key();
-
-  return -1;
-}
-
 //=============================================================================
 /*!
  *  GetObject
  */
 //=============================================================================
-Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry, bool force)
-{
-  Handle(GEOM_Object) anObject;
 
-  TCollection_AsciiString anID = BuildID(theDocID, theEntry);
+Handle(GEOM_BaseObject) GEOM_Engine::GetObject(const char* theEntry, bool force)
+{
+  Handle(GEOM_BaseObject) anObject;
 
-  if (_objects.IsBound(anID)) {
-    anObject = Handle(GEOM_Object)::DownCast(_objects(anID));
+  if (_objects.IsBound(theEntry)) {
+    anObject = Handle(GEOM_BaseObject)::DownCast(_objects(theEntry));
   }
   else if (force) {
-    Handle(TDocStd_Document) aDoc = GetDocument(theDocID, force);
+    Handle(TDocStd_Document) aDoc = GetDocument(force);
     if ( !aDoc.IsNull()) {
       TDF_Label aLabel;
       TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True);
-      anObject = new GEOM_Object(aLabel);
-      _objects.Bind(anID, anObject);
+      if ( !aLabel.IsNull() ) {
+        int objType = GEOM_BaseObject::GetType( aLabel );
+        switch ( objType ) {
+        case GEOM_FIELD_OBJTYPE:      anObject = new GEOM_Field    (aLabel); break;
+        case GEOM_FIELD_STEP_OBJTYPE: anObject = new GEOM_FieldStep(aLabel); break;
+        default:                      anObject = new GEOM_Object   (aLabel);
+        }
+        _objects.Bind(theEntry, anObject);
+      }
     }
   }
 
@@ -320,32 +296,35 @@ Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry, bool fo
 
 //=============================================================================
 /*!
- *  AddObject
+ *  AddBaseObject
  */
 //=============================================================================
-Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
+
+Handle(GEOM_BaseObject) GEOM_Engine::AddBaseObject(int theType)
 {
-  Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
+  Handle(TDocStd_Document) aDoc = GetDocument();
   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
 
   // NPAL18604: use existing label to decrease memory usage,
   //            if this label has been freed (object deleted)
   bool useExisting = false;
   TDF_Label aChild;
-  if (_freeLabels.find(theDocID) != _freeLabels.end()) {
-    std::list<TDF_Label>& aFreeLabels = _freeLabels[theDocID];
-    if (!aFreeLabels.empty()) {
-      useExisting = true;
-      aChild = aFreeLabels.front();
-      aFreeLabels.pop_front();
-    }
+  if (!_freeLabels.empty()) {
+    useExisting = true;
+    aChild = _freeLabels.front();
+    _freeLabels.pop_front();
   }
   if (!useExisting) {
     // create new label
     aChild = TDF_TagSource::NewChild(aDoc->Main());
   }
 
-  Handle(GEOM_Object) anObject = new GEOM_Object(aChild, theType);
+  Handle(GEOM_BaseObject) anObject;
+  switch ( theType ) {
+  case GEOM_FIELD_OBJTYPE:      anObject = new GEOM_Field    (aChild, theType); break;
+  case GEOM_FIELD_STEP_OBJTYPE: anObject = new GEOM_FieldStep(aChild, theType); break;
+  default:                      anObject = new GEOM_Object   (aChild, theType);
+  }
 
   //Put an object in the map of created objects
   TCollection_AsciiString anID = BuildIDFromObject(anObject);
@@ -355,32 +334,40 @@ Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
   return anObject;
 }
 
+//================================================================================
+/*!
+ * \brief Adds a new object of the type theType in the OCAF document
+ */
+//================================================================================
+
+Handle(GEOM_Object) GEOM_Engine::AddObject(int theType)
+{
+  return Handle(GEOM_Object)::DownCast( AddBaseObject(theType) );
+}
+
 //=============================================================================
 /*!
  *  AddSubShape
  */
 //=============================================================================
-Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape,
+
+Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object)              theMainShape,
                                              Handle(TColStd_HArray1OfInteger) theIndices,
                                              bool isStandaloneOperation)
 {
   if (theMainShape.IsNull() || theIndices.IsNull()) return NULL;
 
-  Handle(TDocStd_Document) aDoc = GetDocument(theMainShape->GetDocID());
+  Handle(TDocStd_Document) aDoc = GetDocument();
   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
 
   // NPAL18604: use existing label to decrease memory usage,
   //            if this label has been freed (object deleted)
   bool useExisting = false;
-  TDF_Label aChild;
-  int aDocID = theMainShape->GetDocID();
-  if (_freeLabels.find(aDocID) != _freeLabels.end()) {
-    std::list<TDF_Label>& aFreeLabels = _freeLabels[aDocID];
-    if (!aFreeLabels.empty()) {
-      useExisting = true;
-      aChild = aFreeLabels.front();
-      aFreeLabels.pop_front();
-    }
+  TDF_Label aChild;;
+  if (!_freeLabels.empty()) {
+    useExisting = true;
+    aChild = _freeLabels.front();
+    _freeLabels.pop_front();
   }
   if (!useExisting) {
     // create new label
@@ -396,18 +383,15 @@ Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape,
   aSSI.SetIndices(theIndices);
 
   try {
-#if OCC_VERSION_LARGE > 0x06010000
     OCC_CATCH_SIGNALS;
-#endif
     GEOM_Solver aSolver (GEOM_Engine::GetEngine());
     if (!aSolver.ComputeFunction(aFunction)) {
       MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
       return NULL;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail.GetMessageString());
     return NULL;
   }
 
@@ -440,20 +424,29 @@ Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape,
  *  RemoveObject
  */
 //=============================================================================
-bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
+bool GEOM_Engine::RemoveObject(Handle(GEOM_BaseObject)& theObject)
 {
   if (theObject.IsNull()) return false;
 
-  int aDocID = theObject->GetDocID();
-  if(!_mapIDDocument.IsBound(aDocID))
+  if(!_document)
     return false;  // document is closed...
 
+  TDF_Label aLabel = theObject->GetEntry();
+  if ( aLabel == aLabel.Root() )
+    return false; // already removed object
+
   //Remove an object from the map of available objects
   TCollection_AsciiString anID = BuildIDFromObject(theObject);
-  if (_objects.IsBound(anID)) _objects.UnBind(anID);
+  if (_objects.IsBound(anID)) {
+    Handle(GEOM_BaseObject) anObject = Handle(GEOM_BaseObject)::DownCast(_objects(anID));
+    if ( anObject != theObject )
+      anObject->_label = anObject->_label.Root();
+    _objects.UnBind(anID);
+  }
 
   // If sub-shape, remove it from the list of sub-shapes of its main shape
-  if (!theObject->IsMainShape()) {
+  Handle(GEOM_Object) aGO = Handle(GEOM_Object)::DownCast( theObject );
+  if ( !aGO.IsNull() && !aGO->IsMainShape()) {
     Handle(GEOM_Function) aFunction = theObject->GetFunction(1);
     GEOM_ISubShape aSSI (aFunction);
     Handle(GEOM_Function) aMainShape = aSSI.GetMainShape();
@@ -470,12 +463,17 @@ bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
       aNode->Remove();
   }
 
-  TDF_Label aLabel = theObject->GetEntry();
   aLabel.ForgetAllAttributes(Standard_True);
 
   // Remember the label to reuse it then
-  std::list<TDF_Label>& aFreeLabels = _freeLabels[aDocID];
-  aFreeLabels.push_back(aLabel);
+  if ( _freeLabels.empty() || _freeLabels.back() != aLabel )
+    _freeLabels.push_back(aLabel);
+
+  // we can't explicitly delete theObject. At least prevent its functioning
+  // as an alive object when aLabel is reused for a new object
+  theObject->_label = aLabel.Root();
+  theObject->_ior.Clear();
+  theObject->_parameters.Clear();;
 
   theObject.Nullify();
 
@@ -487,9 +485,9 @@ bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
  *  Undo
  */
 //=============================================================================
-void GEOM_Engine::Undo(int theDocID)
+void GEOM_Engine::Undo()
 {
-  GetDocument(theDocID)->Undo();
+  GetDocument()->Undo();
 }
 
 //=============================================================================
@@ -497,9 +495,9 @@ void GEOM_Engine::Undo(int theDocID)
  *  Redo
  */
 //=============================================================================
-void GEOM_Engine::Redo(int theDocID)
+void GEOM_Engine::Redo()
 {
-  GetDocument(theDocID)->Redo();
+  GetDocument()->Redo();
 }
 
 //=============================================================================
@@ -507,14 +505,17 @@ void GEOM_Engine::Redo(int theDocID)
  *  Save
  */
 //=============================================================================
-bool GEOM_Engine::Save(int theDocID, char* theFileName)
+bool GEOM_Engine::Save(const char* theFileName)
 {
-  if(!_mapIDDocument.IsBound(theDocID)) return false;
-  Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
+  if(!_document) return false;
 
-  _OCAFApp->SaveAs(aDoc, theFileName);
+#if defined(WIN32) && defined(UNICODE)
+  std::wstring aFileName = Kernel_Utils::utf8_decode_s(theFileName);
+#else
+  std::string aFileName = theFileName;
+#endif
 
-  return true;
+  return _OCAFApp->SaveAs( _document, aFileName.c_str() ) == PCDM_SS_OK;
 }
 
 //=============================================================================
@@ -522,23 +523,26 @@ bool GEOM_Engine::Save(int theDocID, char* theFileName)
  *  Load
  */
 //=============================================================================
-bool GEOM_Engine::Load(int theDocID, char* theFileName)
+bool GEOM_Engine::Load(const char* theFileName)
 {
-  Handle(TDocStd_Document) aDoc;
-#if OCC_VERSION_LARGE > 0x06050100 // For OCCT6.5.2 and higher
-  if (_OCAFApp->Open(theFileName, aDoc) != PCDM_RS_OK) {
+#if defined(WIN32) && defined(UNICODE)
+       std::wstring aFileName = Kernel_Utils::utf8_decode_s(theFileName);
 #else
-  if (_OCAFApp->Open(theFileName, aDoc) != CDF_RS_OK) {
+       std::string aFileName = theFileName;
 #endif
+  Handle(TDocStd_Document) aDoc;
+  if (_OCAFApp->Open(aFileName.c_str(), aDoc) != PCDM_RS_OK) {
     return false;
   }
 
-  aDoc->SetUndoLimit(_UndoLimit);
+  // Replace old document format by the new one.
+  if (aDoc->StorageFormat().IsEqual("SALOME_GEOM")) {
+    aDoc->ChangeStorageFormat("BinOcaf");
+  }
 
-  if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
-  _mapIDDocument.Bind(theDocID, aDoc);
+  aDoc->SetUndoLimit(_UndoLimit);
 
-  TDataStd_Integer::Set(aDoc->Main(), theDocID);
+  _document = aDoc;
 
   return true;
 }
@@ -548,30 +552,24 @@ bool GEOM_Engine::Load(int theDocID, char* theFileName)
  *  Close
  */
 //=============================================================================
-void GEOM_Engine::Close(int theDocID)
+void GEOM_Engine::Close()
 {
-  if (_mapIDDocument.IsBound(theDocID)) {
-    Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
-
-    //Remove all GEOM Objects associated to the given document
+  if (_document) {
+    //Remove all GEOM Objects associated to the document
     TColStd_SequenceOfAsciiString aSeq;
     GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It (_objects);
     for (; It.More(); It.Next()) {
-      TCollection_AsciiString anObjID (It.Key());
-      Standard_Integer anID = ExtractDocID(anObjID);
-      if (theDocID == anID) aSeq.Append(It.Key());
+      aSeq.Append(It.Key());
     }
-    for (Standard_Integer i=1; i<=aSeq.Length(); i++) _objects.UnBind(aSeq.Value(i));
-
-    // Forget free labels for this document
-    TFreeLabelsList::iterator anIt = _freeLabels.find(theDocID);
-    if (anIt != _freeLabels.end()) {
-      _freeLabels.erase(anIt);
+    for (Standard_Integer i=1; i<=aSeq.Length(); i++) {
+      _objects.UnBind(aSeq.Value(i));
     }
 
-    _mapIDDocument.UnBind(theDocID);
-    _OCAFApp->Close(aDoc);
-    aDoc.Nullify();
+    // Forget free labels for document
+    _freeLabels.clear();
+
+    _OCAFApp->Close(_document);
+    _document.Nullify();
   }
 }
 
@@ -580,8 +578,7 @@ void GEOM_Engine::Close(int theDocID)
  *  DumpPython
  */
 //=============================================================================
-TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
-                                                std::vector<TObjectData>& theObjectData,
+TCollection_AsciiString GEOM_Engine::DumpPython(std::vector<TObjectData>& theObjectData,
                                                 TVariablesList theVariables,
                                                 bool isPublished,
                                                 bool isMultiFile, 
@@ -591,33 +588,36 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
   Kernel_Utils::Localizer loc;
 
   TCollection_AsciiString aScript;
-  Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
+  Handle(TDocStd_Document) aDoc = GetDocument();
 
   if (aDoc.IsNull())
   {
     TCollection_AsciiString anEmptyScript;
     if( isMultiFile )
-      anEmptyScript = "def RebuildData(theStudy): pass\n";
+      anEmptyScript = "def RebuildData(): pass\n";
     return anEmptyScript;
   }
+  
+  if( isMultiFile )
+    aScript  = "import salome\n";
 
-  aScript  = "import GEOM\n";
-  aScript += "import geompy\n";
+  aScript += "import GEOM\n";
+  aScript += "from salome.geom import geomBuilder\n";
   aScript += "import math\n";
   aScript += "import SALOMEDS\n\n";
   if( isMultiFile )
-    aScript += "def RebuildData(theStudy):";
+    aScript += "def RebuildData():";
 
-  aScript += "\n\tgeompy.init_geom(theStudy)\n";
+  aScript += "\n\tgeompy = geomBuilder.New()\n";
 
-  AddTextures(theDocID, aScript);
+  AddTextures(aScript);
 
   Standard_Integer posToInsertGlobalVars = aScript.Length() + 1;
 
   // a map containing copies of TObjectData from theObjectData
   TSting2ObjDataMap    aEntry2ObjData;
   // contains pointers to TObjectData of either aEntry2ObjData or theObjectData; the latter
-  // occures when several StudyEntries correspond to one Entry
+  // occurs when several StudyEntries correspond to one Entry
   TSting2ObjDataPtrMap aStEntry2ObjDataPtr;
 
   //Resource_DataMapOfAsciiStringAsciiString aEntry2StEntry, aStEntry2Entry, theObjectNames;
@@ -628,7 +628,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
     TDF_Label L;
     TDF_Tool::Label( aDoc->GetData(), data._entry, L );
     if ( L.IsNull() ) continue;
-    Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
+    Handle(GEOM_BaseObject) obj = GEOM_BaseObject::GetObject( L );
     // fill maps
     if ( !obj.IsNull() ) {
       TSting2ObjDataMap::iterator ent2Data =
@@ -655,6 +655,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
   // Mantis issue 0020768
   Standard_Integer objectCounter = 0;
   Resource_DataMapOfAsciiStringAsciiString aNameToEntry;
+  TIntToListIntMap                         aRefMap;
 
   if (aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
     TDataStd_ChildNodeIterator Itr(aRoot);
@@ -683,6 +684,10 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
             continue; // aCurScript is already at the end of aFuncScript
         aFuncScript += aCurScript;
       }
+
+      // Fill the map of references.
+      FillMapOfRef(aFunction, aRefMap);
+
       if (isDumpCollected ) {
         // Replace entries by the names
         ReplaceEntriesByNames( aFuncScript, aEntry2ObjData, isPublished,
@@ -698,9 +703,16 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
                          aNameToEntry, anEntryToCmdMap, anIgnoreObjMap );
         }
         // add publishing commands to the script
+        std::set< int >                                    aPublished;
         std::map< int, TCollection_AsciiString >::iterator anEntryToCmd = anEntryToCmdMap.begin();
-        for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd )
-          aFuncScript += anEntryToCmd->second;
+
+        for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd ) {
+          const TCollection_AsciiString aPublishCmds =
+              GetPublishCommands(anEntryToCmd->first, anEntryToCmdMap,
+                                 aRefMap, aPublished);
+
+          aFuncScript += aPublishCmds;
+        }
 
         // PTv, 0020001 add result objects from RestoreGivenSubShapes into ignore list,
         //  because they will be published during command execution
@@ -734,7 +746,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
   aScript += aFuncScript;
 
   // ouv : NPAL12872
-  AddObjectColors( theDocID, aScript, aEntry2ObjData );
+  AddObjectColors(aScript, aEntry2ObjData );
 
   // Make script to publish in study
   TSting2ObjDataPtrMap::iterator aStEntry2ObjDataPtrIt;
@@ -753,9 +765,16 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
                      aNameToEntry, anEntryToCmdMap, anIgnoreObjMap );
     }
     // add publishing commands to the script
+    std::set< int >                                    aPublished;
     std::map< int, TCollection_AsciiString >::iterator anEntryToCmd = anEntryToCmdMap.begin();
-    for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd )
-      aScript += anEntryToCmd->second;
+
+    for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd ) {
+      const TCollection_AsciiString aPublishCmds =
+          GetPublishCommands(anEntryToCmd->first, anEntryToCmdMap,
+                             aRefMap, aPublished);
+
+      aScript += aPublishCmds;
+    }
   }
 
   //RNV: issue 16219: EDF PAL 469: "RemoveFromStudy" Function
@@ -771,7 +790,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
     {
       TObjectData* data = aStEntry2ObjDataPtrIt->second;      
       if ( data->_unpublished && !data->_pyName.IsEmpty() ) {
-       aScript +=  unpublishCmd + data->_pyName + ")";
+        aScript +=  unpublishCmd + data->_pyName + ")";
       }
     }    
   
@@ -798,6 +817,11 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
     aScript.Insert( posToInsertGlobalVars, globalVars );
   }
 
+  // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
+#ifndef DUMP_SUBSHAPE_IDS
+  Prettify(aScript);
+#endif
+
   return aScript;
 }
 
@@ -837,28 +861,21 @@ Handle(TColStd_HSequenceOfAsciiString) GEOM_Engine::GetAllDumpNames() const
 #define TEXTURE_LABEL_HEIGHT   4
 #define TEXTURE_LABEL_DATA     5
 
-int GEOM_Engine::addTexture(int theDocID, int theWidth, int theHeight,
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
+int GEOM_Engine::addTexture(int theWidth, int theHeight,
                             const Handle(TColStd_HArray1OfByte)& theTexture,
-#else
-                            const Handle(TDataStd_HArray1OfByte)& theTexture,
-#endif
                             const TCollection_AsciiString& theFileName)
 {
-  Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
+  Handle(TDocStd_Document) aDoc = GetDocument();
   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
 
   // NPAL18604: use existing label to decrease memory usage,
   //            if this label has been freed (object deleted)
   bool useExisting = false;
   TDF_Label aChild;
-  if (_freeLabels.find(theDocID) != _freeLabels.end()) {
-    std::list<TDF_Label>& aFreeLabels = _freeLabels[theDocID];
-    if (!aFreeLabels.empty()) {
-      useExisting = true;
-      aChild = aFreeLabels.front();
-      aFreeLabels.pop_front();
-    }
+  if (!_freeLabels.empty()) {
+    useExisting = true;
+    aChild = _freeLabels.front();
+    _freeLabels.pop_front();
   }
   if (!useExisting) {
     // create new label
@@ -887,22 +904,14 @@ int GEOM_Engine::addTexture(int theDocID, int theWidth, int theHeight,
   return aTextureID;
 }
 
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
-Handle(TColStd_HArray1OfByte) GEOM_Engine::getTexture(int theDocID, int theTextureID,
-#else
-Handle(TDataStd_HArray1OfByte) GEOM_Engine::getTexture(int theDocID, int theTextureID,
-#endif
+Handle(TColStd_HArray1OfByte) GEOM_Engine::getTexture(int theTextureID,
                                                       int& theWidth, int& theHeight,
                                                       TCollection_AsciiString& theFileName)
 {
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
   Handle(TColStd_HArray1OfByte) anArray;
-#else
-  Handle(TDataStd_HArray1OfByte) anArray;
-#endif
   theWidth = theHeight = 0;
 
-  Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
+  Handle(TDocStd_Document) aDoc = GetDocument();
 
   TDF_ChildIterator anIterator(aDoc->Main(), Standard_True);
   bool found = false;
@@ -936,11 +945,11 @@ Handle(TDataStd_HArray1OfByte) GEOM_Engine::getTexture(int theDocID, int theText
   return anArray;
 }
 
-std::list<int> GEOM_Engine::getAllTextures(int theDocID)
+std::list<int> GEOM_Engine::getAllTextures()
 {
   std::list<int> id_list;
 
-  Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
+  Handle(TDocStd_Document) aDoc = GetDocument();
 
   TDF_ChildIterator anIterator(aDoc->Main(), Standard_True);
   for (; anIterator.More(); anIterator.Next()) {
@@ -959,6 +968,107 @@ std::list<int> GEOM_Engine::getAllTextures(int theDocID)
 //                     Internal functions
 //===========================================================================
 
+//=============================================================================
+/*!
+ *  MakeCommandfor3DSketcher: Make new command for 3DSketcher
+ */
+//=============================================================================
+TCollection_AsciiString MakeCommandfor3DSketcher (const TCollection_AsciiString& theDescr )
+{
+    TCollection_AsciiString aNewDescr;
+    int i = 1;
+    TCollection_AsciiString aSubStr = theDescr.Token("\n\t", i);
+    for (; !aSubStr.IsEmpty(); aSubStr = theDescr.Token("\n\t", i)) {
+      if (aSubStr.Search( "Make3DSketcherCommand" ) != -1) {
+        TCollection_AsciiString aResult = aSubStr.Token(" ", 1);
+        // "3DSketcher:CMD[:CMD[:CMD...]]"
+        TCollection_AsciiString aCommand = aSubStr.Token("\"", 2);
+
+        // Split the command string to separate CMDs
+        int icmd = 2;
+        TColStd_SequenceOfAsciiString aSequence;
+        if (aCommand.Length()) {
+          TCollection_AsciiString aToken = aCommand.Token(":", icmd);
+          while (aToken.Length() > 0) {
+            aSequence.Append(aToken);
+            aToken = aCommand.Token(":", ++icmd);
+          }
+        }
+
+        if (aSequence.Length() > 0) {
+          if (i > 1)
+            aNewDescr += "\n\t";
+
+          aNewDescr += "\nsk = geompy.Sketcher3D()";
+          int nbCMDs = aSequence.Length();
+          for (icmd = 1; icmd <= nbCMDs; icmd++) {
+            aNewDescr += "\n\t";
+
+            TCollection_AsciiString aCMD = aSequence.Value(icmd);
+
+            // Split the CMD into string values
+            TColStd_SequenceOfAsciiString aStrVals;
+            int ival = 1;
+            TCollection_AsciiString aToken = aCMD.Token(" ", ival);
+            while (aToken.Length() > 0) {
+              aStrVals.Append(aToken);
+              aToken = aCMD.Token(" ", ++ival);
+            }
+
+            TCollection_AsciiString aCMDpref = aStrVals.Value(1);
+            if (aCMDpref == "TT") {
+              aNewDescr += "sk.addPointsAbsolute(";
+              aNewDescr += aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + aStrVals.Value(4) + ")";
+            }
+            else if (aCMDpref == "T") {
+              aNewDescr += "sk.addPointsRelative(";
+              aNewDescr += aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + aStrVals.Value(4) + ")";
+            }
+            else if (aCMDpref == "WW") {
+              aNewDescr += "sk.close()";
+            }
+            else if (aCMDpref.Value(1) == 'O'){
+              TCollection_AsciiString aCMDtrunc = aStrVals.Value(1);
+              aCMDtrunc.Trunc(3);
+              if (aCMDpref.Value(4) == 'C')
+                aNewDescr += "sk.addPointRadiusAngleH";
+              else
+                aNewDescr += "sk.addPointRadiusAngles";
+              if (aCMDpref.Value(5) == 'A')
+                aNewDescr += "Absolute(";
+              else
+                aNewDescr += "Relative(";
+              aNewDescr +=  aStrVals.Value(4) + ", " +
+                aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + "\""+aCMDtrunc+"\"" + ")";
+            }
+          }
+          aNewDescr += "\n\t";
+          aNewDescr += aResult + " = sk.wire()";
+        }
+      } // Make3DSketcherCommand
+      else if (aSubStr.Search( "Make3DSketcher" ) != -1) {
+        TCollection_AsciiString aResult = aSubStr.Token(" ", 1);
+        TCollection_AsciiString aCommand = aSubStr.Token("[", 2);
+        aCommand = aCommand.Token("]", 1);
+        if (i > 1)
+          aNewDescr += "\n\t";
+        aNewDescr += "\nsk = geompy.Sketcher3D()";
+        aNewDescr += "\n\t";
+        aNewDescr += "sk.addPointsAbsolute(";
+        aNewDescr += aCommand + ")";
+        aNewDescr += "\n\t";
+        aNewDescr += aResult + " = sk.wire()";
+      }
+      else {
+        if (i > 1)
+          aNewDescr += "\n\t";
+        aNewDescr += aSubStr;
+      }
+      i++;
+    }
+    return aNewDescr;
+}
+
 //=============================================================================
 /*!
  *  ProcessFunction: Dump function description into script
@@ -1048,91 +1158,13 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
   ReplaceVariables(aDescr,theVariables);
 
   //Process sketcher functions, replacing string command by calls to Sketcher interface
+  if ( ( aDescr.Search( "MakeSketcherOnPlane" ) != -1 ) || ( aDescr.Search( "MakeSketcher" ) != -1 ) ) {
+    Sketcher_Profile aProfile( aDescr.ToCString());
+    // Make new command for SketcherOnPlane and for Sketcher
+    aDescr = aProfile.GetDump();
+  }
   if (aDescr.Search( "Make3DSketcher" ) != -1) {
-    TCollection_AsciiString aNewDescr;
-    int i = 1;
-    TCollection_AsciiString aSubStr = aDescr.Token("\n\t", i);
-    for (; !aSubStr.IsEmpty(); aSubStr = aDescr.Token("\n\t", i)) {
-      if (aSubStr.Search( "Make3DSketcherCommand" ) != -1) {
-        TCollection_AsciiString aResult = aSubStr.Token(" ", 1);
-        // "3DSketcher:CMD[:CMD[:CMD...]]"
-        TCollection_AsciiString aCommand = aSubStr.Token("\"", 2);
-
-        // Split the command string to separate CMDs
-        int icmd = 2;
-        TColStd_SequenceOfAsciiString aSequence;
-        if (aCommand.Length()) {
-          TCollection_AsciiString aToken = aCommand.Token(":", icmd);
-          while (aToken.Length() > 0) {
-            aSequence.Append(aToken);
-            aToken = aCommand.Token(":", ++icmd);
-          }
-        }
-
-        if (aSequence.Length() > 0) {
-          if (i > 1)
-            aNewDescr += "\n\t";
-
-          aNewDescr += "sk = geompy.Sketcher3D()";
-          int nbCMDs = aSequence.Length();
-          for (icmd = 1; icmd <= nbCMDs; icmd++) {
-            aNewDescr += "\n\t";
-
-            TCollection_AsciiString aCMD = aSequence.Value(icmd);
-
-            // Split the CMD into string values
-            TColStd_SequenceOfAsciiString aStrVals;
-            int ival = 1;
-            TCollection_AsciiString aToken = aCMD.Token(" ", ival);
-            while (aToken.Length() > 0) {
-              aStrVals.Append(aToken);
-              aToken = aCMD.Token(" ", ++ival);
-            }
-
-            TCollection_AsciiString aCMDpref = aStrVals.Value(1);
-            if (aCMDpref == "TT") {
-              aNewDescr += "sk.addPointsAbsolute(";
-              aNewDescr += aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + aStrVals.Value(4) + ")";
-            }
-            else if (aCMDpref == "T") {
-              aNewDescr += "sk.addPointsRelative(";
-              aNewDescr += aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + aStrVals.Value(4) + ")";
-            }
-            else if (aCMDpref == "WW") {
-              aNewDescr += "sk.close()";
-            }
-            else {
-              aNewDescr += "sk.addPointAnglesLength(\"";
-              aNewDescr += aCMDpref + "\", " +
-                aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + aStrVals.Value(4) + ")";
-            }
-          }
-          aNewDescr += "\n\t";
-          aNewDescr += aResult + " = sk.wire()";
-        }
-      } // Make3DSketcherCommand
-      else if (aSubStr.Search( "Make3DSketcher" ) != -1) {
-        TCollection_AsciiString aResult = aSubStr.Token(" ", 1);
-        TCollection_AsciiString aCommand = aSubStr.Token("[", 2);
-        aCommand = aCommand.Token("]", 1);
-        if (i > 1)
-          aNewDescr += "\n\t";
-        aNewDescr += "sk = geompy.Sketcher3D()";
-        aNewDescr += "\n\t";
-        aNewDescr += "sk.addPointsAbsolute(";
-        aNewDescr += aCommand + ")";
-        aNewDescr += "\n\t";
-        aNewDescr += aResult + " = sk.wire()";
-      }
-      else {
-        if (i > 1)
-          aNewDescr += "\n\t";
-        aNewDescr += aSubStr;
-      }
-
-      i++;
-    }
-    aDescr = aNewDescr;
+    aDescr = MakeCommandfor3DSketcher ( aDescr );
   }
 
   if ( theIsDumpCollected ) {
@@ -1156,6 +1188,67 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
   return true;
 }
 
+//=============================================================================
+/*!
+ *  GetTag: Returns the tag from entry
+ */
+//=============================================================================
+int GetTag(const TCollection_AsciiString &theEntry)
+{
+  const int aGeomObjDepth = 3;
+  const int aTag          = theEntry.Token(":", aGeomObjDepth).IntegerValue();
+
+  return aTag;
+}
+
+//=============================================================================
+/*!
+ *  FillMapOfRef: Fill the map of references
+ */
+//=============================================================================
+void FillMapOfRef(const Handle(GEOM_Function) &theFunction,
+                        TIntToListIntMap      &theRefMap)
+{
+  TDF_LabelSequence       aSeq;
+  TCollection_AsciiString anObjEntry;
+  int                     anObjTag;
+
+  TDF_Tool::Entry(theFunction->GetOwnerEntry(), anObjEntry);
+  anObjTag = GetTag(anObjEntry);
+  theFunction->GetDependency(aSeq);
+
+  const Standard_Integer aLen = aSeq.Length();
+  Standard_Integer       i;
+
+  for (i = 1; i <= aLen; i++) {
+    TDF_Label             aRefLabel = aSeq.Value(i);
+    Handle(TDF_Reference) aRef;
+
+    if (aRefLabel.FindAttribute(TDF_Reference::GetID(), aRef)) {
+      if (!aRef.IsNull() && !aRef->Get().IsNull()) {
+        Handle(TDataStd_TreeNode) aT;
+
+        if (TDataStd_TreeNode::Find(aRef->Get(), aT)) {
+          TDF_Label             aDepLabel = aT->Label();
+          Handle(GEOM_Function) aRefFunct = GEOM_Function::GetFunction(aDepLabel);
+
+          if (!aRefFunct.IsNull()) {
+            // Get entry of the referenced object.
+            TDF_Tool::Entry(aRefFunct->GetOwnerEntry(), anObjEntry);
+
+            const int aRefTag = GetTag(anObjEntry);
+
+            if (anObjTag != aRefTag) {
+              // Avoid making references for operations without copy.
+              theRefMap[anObjTag].push_back(aRefTag);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
 //=============================================================================
 /*!
  *  FindEntries: Returns a sequence of start/end positions of entries in the string
@@ -1181,7 +1274,7 @@ Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theStrin
         if(c == 58) isFound = Standard_True;
       }
 
-      if(isFound && arr[j-2] != 58) { // last char should be a diggit
+      if(isFound && arr[j-2] != 58) { // last char should be a digit
         aSeq->Append(i+1); // +1 because AsciiString starts from 1
         aSeq->Append(j-1);
       }
@@ -1202,14 +1295,14 @@ Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theStrin
 void ReplaceVariables(TCollection_AsciiString& theCommand,
                       const TVariablesList&    theVariables)
 {
-  if (MYDEBUG)
-    cout<<"Command : "<<theCommand<<endl;
+  if (SALOME::VerbosityActivated())
+    std::cout<<"Command : "<<theCommand<<std::endl;
 
-  if (MYDEBUG) {
-    cout<<"All Entries:"<<endl;
+  if (SALOME::VerbosityActivated()) {
+    std::cout<<"All Entries:"<<std::endl;
     TVariablesList::const_iterator it = theVariables.begin();
     for(;it != theVariables.end();it++)
-      cout<<"\t'"<<(*it).first<<"'"<<endl;
+      std::cout<<"\t'"<<(*it).first<<"'"<<std::endl;
   }
 
   //Additional case - multi-row commands
@@ -1219,8 +1312,8 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     if( aCommand.Length() == 0 )
       break;
 
-    if (MYDEBUG)
-      cout<<"Sub-command : "<<aCommand<<endl;
+    if (SALOME::VerbosityActivated())
+      std::cout<<"Sub-command : "<<aCommand<<std::endl;
 
     Standard_Integer aStartCommandPos = theCommand.Location(aCommand,1,theCommand.Length());
     Standard_Integer aEndCommandPos = aStartCommandPos + aCommand.Length();
@@ -1237,8 +1330,8 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     //Remove white spaces
     anEntry.RightAdjust();
     anEntry.LeftAdjust();
-    if(MYDEBUG)
-      cout<<"Result entry : '" <<anEntry<<"'"<<endl;
+    if(SALOME::VerbosityActivated())
+      std::cout<<"Result entry : '" <<anEntry<<"'"<<std::endl;
 
     if ( anEntry.IsEmpty() ) {
       aCommandIndex++;
@@ -1255,8 +1348,8 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
       anEntry.Remove( 1, 1 );
       anEntry.RightAdjust();
       anEntry.LeftAdjust();
-      if(MYDEBUG)
-        cout<<"Sub-entry : '" <<anEntry<<"'"<<endl;
+      if(SALOME::VerbosityActivated())
+                   std::cout<<"Sub-entry : '" <<anEntry<<"'"<<std::endl;
     }
 
     //Find variables used for object construction
@@ -1266,18 +1359,18 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
       aStates = (*it).second;
 
     if(!aStates) {
-      if(MYDEBUG)
-        cout<<"Valiables list empty!!!"<<endl;
+      if(SALOME::VerbosityActivated())
+                   std::cout<<"Valiables list empty!!!"<<std::endl;
       aCommandIndex++;
       continue;
     }
 
     TState aVariables = aStates->GetCurrectState();
 
-    if(MYDEBUG) {
-      cout<<"Variables from SObject:"<<endl;
-      for (int i = 0; i < aVariables.size();i++)
-        cout<<"\t Variable["<<i<<"] = "<<aVariables[i].myVariable<<endl;
+    if(SALOME::VerbosityActivated()) {
+          std::cout<<"Variables from SObject:"<<std::endl;
+      for (size_t i = 0; i < aVariables.size();i++)
+        std::cout<<"\t Variable["<<i<<"] = "<<aVariables[i].myVariable<<std::endl;
     }
 
     //Calculate total number of parameters
@@ -1285,15 +1378,15 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     while(aCommand.Location(aTotalNbParams,COMMA,1,aCommand.Length()))
       aTotalNbParams++;
 
-    if(MYDEBUG)
-      cout<<"aTotalNbParams = "<<aTotalNbParams<<endl;
+    if(SALOME::VerbosityActivated())
+           std::cout<<"aTotalNbParams = "<<aTotalNbParams<<std::endl;
 
     Standard_Integer aFirstParam = aNbEntries;
 
     //Replace parameters by variables
     Standard_Integer aStartPos = 0;
     Standard_Integer aEndPos = 0;
-    int iVar = 0;
+    size_t iVar = 0;
     TCollection_AsciiString aVar, aReplacedVar;
     for(Standard_Integer i=aFirstParam;i <= aTotalNbParams;i++) {
       //Replace first parameter (bettwen '(' character and first ',' character)
@@ -1317,6 +1410,8 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
         aStartPos = aCommand.Location(i-1, COMMA, 1, aCommand.Length()) + 2;
         aEndPos = aCommand.Location(i, COMMA, 1, aCommand.Length());
       }
+      if (aStartPos == 0 || aEndPos == 0)
+        continue;
 
       if( aCommand.Value( aStartPos ) == O_SQR_BRACKET )
         aStartPos++;
@@ -1325,15 +1420,15 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
       if ( aStartPos == aEndPos )
         continue; // PAL20889: for "[]"
 
-      if(MYDEBUG)
-        cout<<"aStartPos = "<<aStartPos<<", aEndPos = "<<aEndPos<<endl;
+      if(SALOME::VerbosityActivated())
+        std::cout<<"aStartPos = "<<aStartPos<<", aEndPos = "<<aEndPos<<std::endl;
 
       aVar = aCommand.SubString(aStartPos, aEndPos-1);
       aVar.RightAdjust();
       aVar.LeftAdjust();
 
-      if(MYDEBUG)
-        cout<<"Variable: '"<< aVar <<"'"<<endl;
+      if(SALOME::VerbosityActivated())
+        std::cout<<"Variable: '"<< aVar <<"'"<<std::endl;
 
       // specific case for sketcher
       if(aVar.Location( TCollection_AsciiString("Sketcher:"), 1, aVar.Length() ) != 0) {
@@ -1352,8 +1447,8 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
             aEndSectionPos = aVar.Length();
 
           aSection = aVar.SubString(aStartSectionPos, aEndSectionPos-1);
-          if(MYDEBUG)
-            cout<<"aSection: "<<aSection<<endl;
+          if(SALOME::VerbosityActivated())
+                             std::cout<<"aSection: "<<aSection<<std::endl;
 
           Standard_Integer aNbParams = 1;
           while( aSection.Location( aNbParams, ' ', 1, aSection.Length() ) )
@@ -1369,15 +1464,15 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
             else
               aEndParamPos = aSection.Length() + 1;
 
-            if(MYDEBUG)
-              cout<<"aParamIndex: "<<aParamIndex<<" aStartParamPos: " <<aStartParamPos<<" aEndParamPos: "<<aEndParamPos<<endl;
+            if(SALOME::VerbosityActivated())
+              std::cout<<"aParamIndex: "<<aParamIndex<<" aStartParamPos: " <<aStartParamPos<<" aEndParamPos: "<<aEndParamPos<<std::endl;
 
-           if ( aStartParamPos == aEndParamPos)
-             continue;
+            if ( aStartParamPos == aEndParamPos)
+              continue;
 
             aParameter = aSection.SubString(aStartParamPos, aEndParamPos-1);
-            if(MYDEBUG)
-              cout<<"aParameter: "<<aParameter<<endl;
+            if(SALOME::VerbosityActivated())
+                               std::cout<<"aParameter: "<<aParameter<<std::endl;
 
             if(iVar >= aVariables.size())
               continue;
@@ -1393,28 +1488,31 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
               aReplacedParameter.InsertAfter(aReplacedParameter.Length(),"'");
             }
 
-            if(MYDEBUG)
-              cout<<"aSection before : "<<aSection<<endl;
+            if(SALOME::VerbosityActivated())
+                               std::cout<<"aSection before : "<<aSection<< std::endl;
             aSection.Remove(aStartParamPos, aEndParamPos - aStartParamPos);
             aSection.Insert(aStartParamPos, aReplacedParameter);
-            if(MYDEBUG)
-              cout<<"aSection after  : "<<aSection<<endl<<endl;
+            if(SALOME::VerbosityActivated())
+              std::cout<<"aSection after  : "<<aSection<<std::endl<<std::endl;
             iVar++;
           }
-          if(MYDEBUG)
-            cout<<"aVar before : "<<aVar<<endl;
+
+          if(SALOME::VerbosityActivated())
+            std::cout<<"aVar before : "<<aVar<<std::endl;
+
           aVar.Remove(aStartSectionPos, aEndSectionPos - aStartSectionPos);
           aVar.Insert(aStartSectionPos, aSection);
-          if(MYDEBUG)
-            cout<<"aVar after  : "<<aVar<<endl<<endl;
+
+          if(SALOME::VerbosityActivated())
+            std::cout<<"aVar after  : "<<aVar<<std::endl<<std::endl;
         }
 
-        if(MYDEBUG)
-          cout<<"aCommand before : "<<aCommand<<endl;
+        if(SALOME::VerbosityActivated())
+          std::cout<<"aCommand before : "<<aCommand<<std::endl;
         aCommand.Remove(aStartPos, aEndPos - aStartPos);
         aCommand.Insert(aStartPos, aVar);
-        if(MYDEBUG)
-          cout<<"aCommand after  : "<<aCommand<<endl;
+        if(SALOME::VerbosityActivated())
+          std::cout<<"aCommand after  : "<<aCommand<<std::endl;
 
         break;
       } // end of specific case for sketcher
@@ -1450,8 +1548,8 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     aStates->IncrementState();
   }
 
-  if (MYDEBUG)
-    cout<<"Command : "<<theCommand<<endl;
+  if (SALOME::VerbosityActivated())
+    std::cout<<"Command : "<<theCommand<<std::endl;
 }
 
 //=============================================================================
@@ -1461,11 +1559,12 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
 //=============================================================================
 void ReplaceEntriesByNames (TCollection_AsciiString&                  theScript,
                             TSting2ObjDataMap&                        aEntry2ObjData,
-                            const bool                                theIsPublished,
+                            const bool                                /*theIsPublished*/,
                             TColStd_SequenceOfAsciiString&            theObjListToPublish,
                             Standard_Integer&                         objectCounter,
                             Resource_DataMapOfAsciiStringAsciiString& aNameToEntry)
 {
+  GEOM_Engine* engine = GEOM_Engine::GetEngine();
   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(theScript);
   Standard_Integer aLen = aSeq->Length(), aStart = 1, aScriptLength = theScript.Length();
 
@@ -1480,10 +1579,10 @@ void ReplaceEntriesByNames (TCollection_AsciiString&                  theScript,
     theObjListToPublish.Append( anEntry );
     
     TObjectData& data = aEntry2ObjData[ anEntry ];
-    if ( data._pyName.IsEmpty() ) { // encounted for the 1st time
+    if ( data._pyName.IsEmpty() ) { // encountered for the 1st time
       if ( !data._name.IsEmpty() ) { // published object
         data._pyName = data._name;
-        healPyName( data._pyName, anEntry, aNameToEntry);
+        engine->healPyName( data._pyName, anEntry, aNameToEntry);
       }
       else {
         do {
@@ -1510,12 +1609,11 @@ void ReplaceEntriesByNames (TCollection_AsciiString&                  theScript,
  *  AddObjectColors: Add color to objects
  */
 //=============================================================================
-void AddObjectColors (int                      theDocID,
-                      TCollection_AsciiString& theScript,
+void AddObjectColors (TCollection_AsciiString& theScript,
                       const TSting2ObjDataMap& theEntry2ObjData)
 {
   GEOM_Engine* engine = GEOM_Engine::GetEngine();
-  Handle(TDocStd_Document) aDoc = engine->GetDocument(theDocID);
+  Handle(TDocStd_Document) aDoc = engine->GetDocument();
 
   TSting2ObjDataMap::const_iterator anEntryToNameIt;
   for (anEntryToNameIt = theEntry2ObjData.begin();
@@ -1558,16 +1656,16 @@ void AddObjectColors (int                      theDocID,
       case Aspect_TOM_POINT:   aCommand += "GEOM.MT_POINT";   break;
       case Aspect_TOM_PLUS:    aCommand += "GEOM.MT_PLUS";    break;
       case Aspect_TOM_STAR:    aCommand += "GEOM.MT_STAR";    break;
-      case Aspect_TOM_O:       aCommand += "GEOM.MT_O";       break;
       case Aspect_TOM_X:       aCommand += "GEOM.MT_X";       break;
+      case Aspect_TOM_O:       aCommand += "GEOM.MT_O";       break;
       case Aspect_TOM_O_POINT: aCommand += "GEOM.MT_O_POINT"; break;
       case Aspect_TOM_O_PLUS:  aCommand += "GEOM.MT_O_PLUS";  break;
       case Aspect_TOM_O_STAR:  aCommand += "GEOM.MT_O_STAR";  break;
       case Aspect_TOM_O_X:     aCommand += "GEOM.MT_O_X";     break;
-      case Aspect_TOM_BALL:    aCommand += "GEOM.MT_BALL";    break;
       case Aspect_TOM_RING1:   aCommand += "GEOM.MT_RING1";   break;
       case Aspect_TOM_RING2:   aCommand += "GEOM.MT_RING2";   break;
       case Aspect_TOM_RING3:   aCommand += "GEOM.MT_RING3";   break;
+      case Aspect_TOM_BALL:    aCommand += "GEOM.MT_BALL";    break;
       default:                 aCommand += "GEOM.MT_NONE";    break; // just for completeness, should not get here
       }
       aCommand += ", ";
@@ -1604,11 +1702,7 @@ void AddObjectColors (int                      theDocID,
   }
 }
 
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
 static TCollection_AsciiString pack_data (const Handle(TColStd_HArray1OfByte)& aData)
-#else
-static TCollection_AsciiString pack_data (const Handle(TDataStd_HArray1OfByte)& aData)
-#endif
 {
   TCollection_AsciiString stream;
   if (!aData.IsNull()) {
@@ -1623,10 +1717,10 @@ static TCollection_AsciiString pack_data (const Handle(TDataStd_HArray1OfByte)&
   return stream;
 }
 
-void AddTextures (int theDocID, TCollection_AsciiString& theScript)
+void AddTextures (TCollection_AsciiString& theScript)
 {
   GEOM_Engine* engine = GEOM_Engine::GetEngine();
-  std::list<int> allTextures = engine->getAllTextures(theDocID);
+  std::list<int> allTextures = engine->getAllTextures();
   std::list<int>::const_iterator it;
 
   if (allTextures.size() > 0) {
@@ -1636,12 +1730,8 @@ void AddTextures (int theDocID, TCollection_AsciiString& theScript)
       if (*it <= 0) continue;
       Standard_Integer aWidth, aHeight;
       TCollection_AsciiString aFileName;
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
       Handle(TColStd_HArray1OfByte) aTexture =
-#else
-      Handle(TDataStd_HArray1OfByte) aTexture =
-#endif
-        engine->getTexture(theDocID, *it, aWidth, aHeight, aFileName);
+        engine->getTexture(*it, aWidth, aHeight, aFileName);
       if (aWidth > 0 && aHeight > 0 && !aTexture.IsNull() && aTexture->Length() > 0 ) {
         TCollection_AsciiString aCommand = "\n\t";
         aCommand += "texture_map["; aCommand += *it; aCommand += "] = ";
@@ -1675,6 +1765,7 @@ void PublishObject (TObjectData&                              theObjectData,
                     std::map< int, TCollection_AsciiString >& theEntryToCmdMap,
                     std::set< TCollection_AsciiString>&       theIgnoreMap)
 {
+  GEOM_Engine* engine = GEOM_Engine::GetEngine();
   if ( theObjectData._studyEntry.IsEmpty() )
     return; // was not published
   if ( theIgnoreMap.count( theObjectData._entry ) )
@@ -1691,8 +1782,6 @@ void PublishObject (TObjectData&                              theObjectData,
   if ( stEntry2DataPtr != theStEntry2ObjDataPtr.end() )
     aFatherData = stEntry2DataPtr->second;
 
-  const int geomObjDepth = 3;
-
   // treat multiply published object
   if ( theObjectData._pyName.IsEmpty() )
   {
@@ -1700,14 +1789,14 @@ void PublishObject (TObjectData&                              theObjectData,
     if ( data0._pyName.IsEmpty() ) return; // something wrong
 
     theObjectData._pyName = theObjectData._name;
-    healPyName( theObjectData._pyName, theObjectData._entry, theNameToEntry);
+    engine->healPyName( theObjectData._pyName, theObjectData._entry, theNameToEntry);
 
     TCollection_AsciiString aCreationCommand("\n\t");
     aCreationCommand += theObjectData._pyName + " = " + data0._pyName;
 
     // store aCreationCommand before publishing commands
-    int tag = theObjectData._entry.Token( ":", geomObjDepth ).IntegerValue();
-    theEntryToCmdMap.insert( std::make_pair( tag + 2*theEntry2ObjData.size(), aCreationCommand ));
+    int tag = GetTag(theObjectData._entry);
+    theEntryToCmdMap.insert( std::make_pair( tag + -2*theEntry2ObjData.size(), aCreationCommand ));
   }
 
   // make a command
@@ -1721,12 +1810,94 @@ void PublishObject (TObjectData&                              theObjectData,
   aCommand += theObjectData._pyName + ", '" + theObjectData._name + "' )";
 
   // bind a command to the study entry
-  int tag = theObjectData._entry.Token( ":", geomObjDepth ).IntegerValue();
+  int tag = GetTag(theObjectData._entry);
   theEntryToCmdMap.insert( std::make_pair( tag, aCommand ));
 
   theObjectData._studyEntry.Clear(); // not to publish any more
 }
 
+//================================================================================
+/*!
+ * \brief Returns the string of publishing commands. Take into account that
+ *  references should be published prior to the objects refer to them.
+ */
+//================================================================================
+TCollection_AsciiString GetPublishCommands
+                   (const int                                       theTag,
+                    const std::map< int, TCollection_AsciiString > &theEntryToCmdMap,
+                    const TIntToListIntMap                         &theMapRefs,
+                          std::set< int >                          &thePublished)
+{
+  TCollection_AsciiString aResult;
+
+  if (!thePublished.count(theTag)) {
+    // This object is not published yet.
+    thePublished.insert(theTag);
+
+    std::map< int, TCollection_AsciiString >::const_iterator anIt =
+      theEntryToCmdMap.find(theTag);
+
+    if (anIt != theEntryToCmdMap.end()) {
+      // There is a pubish cmd.
+      TIntToListIntMap::const_iterator aRefIt = theMapRefs.find(theTag);
+
+      if (aRefIt != theMapRefs.end()) {
+        // Recursively publish all references.         
+        std::list< int >::const_iterator aRefTagIt = aRefIt->second.begin();
+
+        for(; aRefTagIt != aRefIt->second.end(); ++aRefTagIt) {
+          const TCollection_AsciiString aRefCmd = GetPublishCommands
+            (*aRefTagIt, theEntryToCmdMap, theMapRefs, thePublished);
+
+          aResult += aRefCmd;
+        }
+      }
+
+      // Add the object command.
+      aResult += anIt->second;
+    }
+  }
+
+  return aResult;
+}
+
+void Prettify(TCollection_AsciiString& theScript)
+{
+  TCollection_AsciiString output;
+  static std::list<TCollection_AsciiString> ToRemove;
+  if (ToRemove.empty()) {
+    ToRemove.push_back("geompy.SubShapeAllIDs");
+    ToRemove.push_back("geompy.SubShapeAllSortedCentresIDs");
+    ToRemove.push_back("geompy.SubShapeAllSortedIDs");
+    ToRemove.push_back("geompy.GetFreeFacesIDs");
+    ToRemove.push_back("geompy.GetShapesOnBoxIDs");
+    ToRemove.push_back("geompy.GetShapesOnShapeIDs");
+    ToRemove.push_back("geompy.GetShapesOnPlaneIDs");
+    ToRemove.push_back("geompy.GetShapesOnPlaneWithLocationIDs");
+    ToRemove.push_back("geompy.GetShapesOnCylinderIDs");
+    ToRemove.push_back("geompy.GetShapesOnCylinderWithLocationIDs");
+    ToRemove.push_back("geompy.GetShapesOnSphereIDs");
+    ToRemove.push_back("geompy.GetShapesOnQuadrangleIDs");
+    ToRemove.push_back("geompy.GetSameIDs");
+  }
+
+  int start = 1;
+  while (start <= theScript.Length()) {
+    int end = theScript.Location("\n", start, theScript.Length());
+    if (end == -1) end = theScript.Length();
+    TCollection_AsciiString line = theScript.SubString(start, end);
+    bool found = false;
+    for (std::list<TCollection_AsciiString>::const_iterator it = ToRemove.begin(); it != ToRemove.end() && !found; ++it)
+      found = line.Search( *it ) != -1;
+    if (!found)
+      output += line;
+    start = end + 1;
+  }
+  theScript = output;
+
+  //OK @@@@@@@@@@@@@@@@@@@@@@@@@@@
+}
+
 //================================================================================
 /*!
  * \brief Constructor
@@ -1754,7 +1925,7 @@ ObjectStates::~ObjectStates()
 //================================================================================
 TState ObjectStates::GetCurrectState() const
 {
-  if(_states.size() > _dumpstate)
+  if((int)_states.size() > _dumpstate)
     return _states[_dumpstate];
   return TState();
 }