Salome HOME
0020598: EDF 1191 GEOM : Creation of hexa block from two faces
[modules/geom.git] / src / GEOM / GEOM_Engine.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21
22 #ifdef WNT
23 #pragma warning( disable:4786 )
24 #endif
25
26 #include "GEOM_Engine.hxx"
27
28 #include "GEOM_Solver.hxx"
29 #include "GEOM_Function.hxx"
30 #include "GEOM_ISubShape.hxx"
31 #include "GEOM_SubShapeDriver.hxx"
32 #include "GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient.hxx"
33 #include "GEOM_PythonDump.hxx"
34
35 #include "utilities.h"
36
37 #include <TDF_Tool.hxx>
38 #include <TDF_Data.hxx>
39 #include <TDF_Reference.hxx>
40 #include <TDF_LabelSequence.hxx>
41 #include <TDataStd_Integer.hxx>
42 #include <TDataStd_ChildNodeIterator.hxx>
43 #include <TFunction_Driver.hxx>
44 #include <TFunction_DriverTable.hxx>
45 #include <TDataStd_HArray1OfByte.hxx>
46 #include <TDataStd_ByteArray.hxx>
47 #include <TDataStd_UAttribute.hxx>
48 #include <TDF_ChildIterator.hxx>
49 #include <TDataStd_Comment.hxx>
50
51 #include <TopExp.hxx>
52 #include <TopTools_IndexedMapOfShape.hxx>
53
54 #include <TCollection_AsciiString.hxx>
55 #include <TCollection_ExtendedString.hxx>
56 #include <TColStd_SequenceOfAsciiString.hxx>
57 #include <TColStd_MapOfTransient.hxx>
58 #include <TColStd_HSequenceOfInteger.hxx>
59
60 #include <Interface_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
61 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
62
63 #include <set>
64 #include <map>
65 #include <string>
66 #include <vector>
67
68 #include <Standard_Failure.hxx>
69 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
70
71 #define COMMA ','
72 #define O_BRACKET '('
73 #define C_BRACKET ')'
74 #define O_SQR_BRACKET '['
75 #define C_SQR_BRACKET ']'
76 #define PY_NULL "None"
77
78 #ifdef _DEBUG_
79 static int MYDEBUG = 0;
80 #else
81 static int MYDEBUG = 0;
82 #endif
83
84 static GEOM_Engine* TheEngine = NULL;
85
86 using namespace std;
87
88 static TCollection_AsciiString BuildIDFromObject(Handle(GEOM_Object)& theObject)
89 {
90   TCollection_AsciiString anID(theObject->GetDocID()), anEntry;
91   TDF_Tool::Entry(theObject->GetEntry(), anEntry);
92   anID+=(TCollection_AsciiString("_")+anEntry);
93   return anID;
94 }
95
96 static TCollection_AsciiString BuildID(Standard_Integer theDocID, char* theEntry)
97 {
98   TCollection_AsciiString anID(theDocID);
99   anID+=(TCollection_AsciiString("_")+theEntry);
100   return anID;
101 }
102
103 static Standard_Integer ExtractDocID(TCollection_AsciiString& theID)
104 {
105   TCollection_AsciiString aDocID = theID.Token("_");
106   if(aDocID.Length() < 1) return -1;
107   return aDocID.IntegerValue();
108 }
109
110 bool ProcessFunction(Handle(GEOM_Function)&   theFunction,
111                      TCollection_AsciiString& theScript,
112                      TCollection_AsciiString& theAfterScript,
113                      const TVariablesList&    theVariables,
114                      const bool               theIsPublished,
115                      TDF_LabelMap&            theProcessed,
116                      std::set<std::string>&   theIgnoreObjs,
117                      bool&                    theIsDumpCollected);
118
119 void ReplaceVariables(TCollection_AsciiString& theCommand, 
120                       const TVariablesList&    theVariables);
121
122 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString);
123
124 void ReplaceEntriesByNames (TCollection_AsciiString&                  theScript,
125                             Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
126                             const bool                                theIsPublished,
127                             Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName,
128                             TColStd_SequenceOfAsciiString&            theObjListToPublish);
129
130 void AddObjectColors (int                                             theDocID,
131                       TCollection_AsciiString&                        theScript,
132                       const Resource_DataMapOfAsciiStringAsciiString& theObjectNames);
133
134 void AddTextures (int theDocID, TCollection_AsciiString& theScript);
135
136 void PublishObject (const TCollection_AsciiString&                  theEntry,
137                     const TCollection_AsciiString&                  theName,
138                     const Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
139                     const Resource_DataMapOfAsciiStringAsciiString& theEntry2StEntry,
140                     const Resource_DataMapOfAsciiStringAsciiString& theStEntry2Entry,
141                     const Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName,
142                     std::map< int, std::string >&                   theEntryToCommandMap,
143                     std::set<std::string>&                          theMapOfPublished);
144
145 //=======================================================================
146 //function : GetTextureGUID
147 //purpose  :
148 //=======================================================================
149 const Standard_GUID& GEOM_Engine::GetTextureGUID()
150 {
151   static Standard_GUID anID("FF1BBB01-5D14-4df2-980B-3A668264EA17");
152   return anID;
153 }
154
155 //=============================================================================
156 /*!
157  *  GetEngine
158  */
159 //=============================================================================
160 GEOM_Engine* GEOM_Engine::GetEngine() { return TheEngine; }
161
162 //=============================================================================
163 /*!
164  *  SetEngine
165  */
166 //=============================================================================
167 void GEOM_Engine::SetEngine(GEOM_Engine* theEngine) { TheEngine = theEngine; }
168
169 //=============================================================================
170 /*!
171  *  Constructor
172  */
173 //=============================================================================
174 GEOM_Engine::GEOM_Engine()
175 {
176   TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
177
178   _OCAFApp = new GEOM_Application();
179   _UndoLimit = 10;
180 }
181
182 /*!
183  *  Destructor
184  */
185 GEOM_Engine::~GEOM_Engine()
186 {
187   GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It(_objects);
188   for(; It.More(); It.Next())
189     {
190       RemoveObject(Handle(GEOM_Object)::DownCast(It.Value()));
191     }
192
193   //Close all documents not closed
194   for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
195     Close(anItr.Key());
196
197   _mapIDDocument.Clear();
198   _objects.Clear();
199 }
200
201 //=============================================================================
202 /*!
203  *  GetDocument
204  */
205 //=============================================================================
206 Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID, bool force)
207 {
208   Handle(TDocStd_Document) aDoc;
209   if(_mapIDDocument.IsBound(theDocID)) {
210     aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
211   }
212   else if (force) {
213     _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
214     aDoc->SetUndoLimit(_UndoLimit);
215     _mapIDDocument.Bind(theDocID, aDoc);
216     TDataStd_Integer::Set(aDoc->Main(), theDocID);
217   }
218   return aDoc;
219 }
220
221 //=============================================================================
222 /*!
223  *  GetDocID
224  */
225 //=============================================================================
226 int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument)
227 {
228   if(theDocument.IsNull()) return -1;
229   for(Interface_DataMapIteratorOfDataMapOfIntegerTransient anItr(_mapIDDocument); anItr.More(); anItr.Next())
230     if(anItr.Value() == theDocument) return anItr.Key();
231
232   return -1;
233
234 }
235
236 //=============================================================================
237 /*!
238  *  GetObject
239  */
240 //=============================================================================
241 Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry, bool force)
242 {
243   Handle(GEOM_Object) anObject;
244
245   TCollection_AsciiString anID = BuildID(theDocID, theEntry);
246
247   if (_objects.IsBound(anID)) {
248     anObject = Handle(GEOM_Object)::DownCast(_objects(anID));
249   }
250   else if (force) {
251     Handle(TDocStd_Document) aDoc = GetDocument(theDocID, force);
252     if ( !aDoc.IsNull()) {
253       TDF_Label aLabel;
254       TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True);
255       anObject = new GEOM_Object(aLabel);
256       _objects.Bind(anID, anObject);
257     }
258   }
259
260   return anObject;
261 }
262
263 //=============================================================================
264 /*!
265  *  AddObject
266  */
267 //=============================================================================
268 Handle(GEOM_Object) GEOM_Engine::AddObject(int theDocID, int theType)
269 {
270   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
271   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
272
273   // NPAL18604: use existing label to decrease memory usage,
274   //            if this label has been freed (object deleted)
275   bool useExisting = false;
276   TDF_Label aChild;
277   if (_freeLabels.find(theDocID) != _freeLabels.end()) {
278     std::list<TDF_Label>& aFreeLabels = _freeLabels[theDocID];
279     if (!aFreeLabels.empty()) {
280       useExisting = true;
281       aChild = aFreeLabels.front();
282       aFreeLabels.pop_front();
283     }
284   }
285   if (!useExisting) {
286     // create new label
287     aChild = TDF_TagSource::NewChild(aDoc->Main());
288   }
289
290   Handle(GEOM_Object) anObject = new GEOM_Object(aChild, theType);
291
292   //Put an object in the map of created objects
293   TCollection_AsciiString anID = BuildIDFromObject(anObject);
294   if(_objects.IsBound(anID)) _objects.UnBind(anID);
295   _objects.Bind(anID, anObject);
296
297   return anObject;
298 }
299
300 //=============================================================================
301 /*!
302  *  AddSubShape
303  */
304 //=============================================================================
305 Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape,
306                                              Handle(TColStd_HArray1OfInteger) theIndices,
307                                              bool isStandaloneOperation)
308 {
309   if(theMainShape.IsNull() || theIndices.IsNull()) return NULL;
310
311   Handle(TDocStd_Document) aDoc = GetDocument(theMainShape->GetDocID());
312   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
313
314   // NPAL18604: use existing label to decrease memory usage,
315   //            if this label has been freed (object deleted)
316   bool useExisting = false;
317   TDF_Label aChild;
318   /*
319   if (!_lastCleared.IsNull()) {
320     if (_lastCleared.Root() == aDoc->Main().Root()) {
321       useExisting = true;
322       aChild = _lastCleared;
323       // 0020229: if next label exists and is empty, try to reuse it
324       Standard_Integer aNextTag = aChild.Tag() + 1;
325       TDF_Label aNextL = aDoc->Main().FindChild(aNextTag, Standard_False);
326       if (!aNextL.IsNull() && !aNextL.HasAttribute())
327         _lastCleared = aNextL;
328       else
329         _lastCleared.Nullify();
330     }
331   }
332   */
333   int aDocID = theMainShape->GetDocID();
334   if (_freeLabels.find(aDocID) != _freeLabels.end()) {
335     std::list<TDF_Label>& aFreeLabels = _freeLabels[aDocID];
336     if (!aFreeLabels.empty()) {
337       useExisting = true;
338       aChild = aFreeLabels.front();
339       aFreeLabels.pop_front();
340     }
341   }
342   if (!useExisting) {
343     // create new label
344     aChild = TDF_TagSource::NewChild(aDoc->Main());
345   }
346
347   Handle(GEOM_Function) aMainShape = theMainShape->GetLastFunction();
348   Handle(GEOM_Object) anObject = new GEOM_Object(aChild, 28); //28 is SUBSHAPE type
349   Handle(GEOM_Function) aFunction = anObject->AddFunction(GEOM_Object::GetSubShapeID(), 1);
350
351   GEOM_ISubShape aSSI(aFunction);
352   aSSI.SetMainShape(aMainShape);
353   aSSI.SetIndices(theIndices);
354
355   try {
356 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
357     OCC_CATCH_SIGNALS;
358 #endif
359     GEOM_Solver aSolver (GEOM_Engine::GetEngine());
360     if (!aSolver.ComputeFunction(aFunction)) {
361       MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
362       return NULL;
363     }
364   }
365   catch (Standard_Failure) {
366     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
367     MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
368     return NULL;
369   }
370
371   //Put an object in the map of created objects
372   TCollection_AsciiString anID = BuildIDFromObject(anObject);
373   if(_objects.IsBound(anID)) _objects.UnBind(anID);
374   _objects.Bind(anID, anObject);
375
376   GEOM::TPythonDump pd (aFunction);
377
378   if (isStandaloneOperation) {
379     pd << anObject << " = geompy.GetSubShape(" << theMainShape << ", [";
380     Standard_Integer i = theIndices->Lower(), up = theIndices->Upper();
381     for (; i <= up - 1; i++) {
382       pd << theIndices->Value(i) << ", ";
383     }
384     pd << theIndices->Value(up) << "])";
385   }
386   else
387     pd << "None";
388
389   return anObject;
390 }
391
392 //=============================================================================
393 /*!
394  *  RemoveObject
395  */
396 //=============================================================================
397 bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject)
398 {
399   if (theObject.IsNull()) return false;
400
401   int aDocID = theObject->GetDocID();
402   if(!_mapIDDocument.IsBound(aDocID))
403     return false;  // document is closed...
404   
405   //Remove an object from the map of available objects
406   TCollection_AsciiString anID = BuildIDFromObject(theObject);
407   if (_objects.IsBound(anID)) _objects.UnBind(anID);
408
409   int nb = theObject->GetNbFunctions();
410   Handle(TDataStd_TreeNode) aNode;
411   for (int i = 1; i<=nb; i++) {
412     Handle(GEOM_Function) aFunction = theObject->GetFunction(i);
413     if (aFunction->GetEntry().FindAttribute(GEOM_Function::GetFunctionTreeID(), aNode))
414       aNode->Remove();
415   }
416
417   TDF_Label aLabel = theObject->GetEntry();
418   aLabel.ForgetAllAttributes(Standard_True);
419
420   // Remember the label to reuse it then
421   std::list<TDF_Label>& aFreeLabels = _freeLabels[aDocID];
422   aFreeLabels.push_back(aLabel);
423
424   theObject.Nullify();
425
426   return true;
427 }
428
429 //=============================================================================
430 /*!
431  *  Undo
432  */
433 //=============================================================================
434 void GEOM_Engine::Undo(int theDocID)
435 {
436   GetDocument(theDocID)->Undo();
437 }
438
439 //=============================================================================
440 /*!
441  *  Redo
442  */
443 //=============================================================================
444 void GEOM_Engine::Redo(int theDocID)
445 {
446   GetDocument(theDocID)->Redo();
447 }
448
449 //=============================================================================
450 /*!
451  *  Save
452  */
453 //=============================================================================
454 bool GEOM_Engine::Save(int theDocID, char* theFileName)
455 {
456   if(!_mapIDDocument.IsBound(theDocID)) return false;
457   Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
458
459   _OCAFApp->SaveAs(aDoc, theFileName);
460
461   return true;
462 }
463
464 //=============================================================================
465 /*!
466  *  Load
467  */
468 //=============================================================================
469 bool GEOM_Engine::Load(int theDocID, char* theFileName)
470 {
471   Handle(TDocStd_Document) aDoc;
472   if(_OCAFApp->Open(theFileName, aDoc) != CDF_RS_OK) {
473     return false;
474   }
475
476   aDoc->SetUndoLimit(_UndoLimit);
477
478   if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
479   _mapIDDocument.Bind(theDocID, aDoc);
480
481   TDataStd_Integer::Set(aDoc->Main(), theDocID);
482
483   return true;
484 }
485
486 //=============================================================================
487 /*!
488  *  Close
489  */
490 //=============================================================================
491 void GEOM_Engine::Close(int theDocID)
492 {
493   if (_mapIDDocument.IsBound(theDocID)) {
494     Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
495
496     //Remove all GEOM Objects associated to the given document
497     TColStd_SequenceOfAsciiString aSeq;
498     GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient It (_objects);
499     for (; It.More(); It.Next()) {
500       TCollection_AsciiString anObjID (It.Key());
501       Standard_Integer anID = ExtractDocID(anObjID);
502       if (theDocID == anID) aSeq.Append(It.Key());
503     }
504     for (Standard_Integer i=1; i<=aSeq.Length(); i++) _objects.UnBind(aSeq.Value(i));
505
506     // Forget free labels for this document
507     TFreeLabelsList::iterator anIt = _freeLabels.find(theDocID);
508     if (anIt != _freeLabels.end()) {
509       _freeLabels.erase(anIt);
510     }
511
512     _mapIDDocument.UnBind(theDocID);
513     _OCAFApp->Close(aDoc);
514     aDoc.Nullify();
515   }
516 }
517
518 //=============================================================================
519 /*!
520  *  DumpPython
521  */
522 //=============================================================================
523 TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
524                                                 Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
525                                                 TVariablesList theVariables,
526                                                 bool isPublished,
527                                                 bool& aValidScript)
528 {
529   TCollection_AsciiString aScript;
530   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
531
532   if (aDoc.IsNull()) return TCollection_AsciiString("def RebuildData(theStudy): pass\n");
533
534   aScript  = "import GEOM\n";
535   aScript += "import geompy\n";
536   aScript += "import math\n";
537   aScript += "import SALOMEDS\n\n";
538   aScript += "def RebuildData(theStudy):";
539   aScript += "\n\tgeompy.init_geom(theStudy)\n";
540
541   AddTextures(theDocID, aScript);
542
543   Standard_Integer posToInsertGlobalVars = aScript.Length() + 1;
544
545   Resource_DataMapOfAsciiStringAsciiString aEntry2StEntry, aStEntry2Entry;
546   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString anEntryToNameIt;
547   // build maps entry <-> studyEntry
548   for (anEntryToNameIt.Initialize( theObjectNames );
549        anEntryToNameIt.More();
550        anEntryToNameIt.Next())
551   {
552     const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
553     // look for an object by entry
554     TDF_Label L;
555     TDF_Tool::Label( aDoc->GetData(), aEntry, L );
556     if ( L.IsNull() ) continue;
557     Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
558     // fill maps
559     if ( !obj.IsNull() ) {
560       TCollection_AsciiString aStudyEntry (obj->GetAuxData());
561       aEntry2StEntry.Bind( aEntry,  aStudyEntry);
562       aStEntry2Entry.Bind( aStudyEntry, aEntry );
563     }
564   }
565
566   // collect objects entries to be published
567   TColStd_SequenceOfAsciiString aObjListToPublish;
568   
569   // iterates on functions till critical (that requiers publication of objects)
570   Handle(TDataStd_TreeNode) aNode, aRoot;
571   Handle(GEOM_Function) aFunction;
572   TDF_LabelMap aCheckedFuncMap;
573   std::set<std::string> anIgnoreObjMap;
574
575   TCollection_AsciiString aFuncScript;
576   Resource_DataMapOfAsciiStringAsciiString anEntryToBadName;
577
578   if (aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
579     TDataStd_ChildNodeIterator Itr(aRoot);
580     for (; Itr.More(); Itr.Next()) {
581       aNode = Itr.Value();
582       aFunction = GEOM_Function::GetFunction(aNode->Label());
583       if (aFunction.IsNull()) {
584         MESSAGE ( "Null function !!!!" );
585         continue;
586       }
587       bool isDumpCollected = false;
588       TCollection_AsciiString aCurScript, anAfterScript;
589       if (!ProcessFunction(aFunction, aCurScript, anAfterScript, theVariables,
590                            isPublished, aCheckedFuncMap, anIgnoreObjMap,
591                            isDumpCollected ))
592         continue;
593       // add function description before dump
594       if (!aCurScript.IsEmpty())
595         aFuncScript += aCurScript;
596       if (isDumpCollected ) {
597         // Replace entries by the names
598         ReplaceEntriesByNames( aFuncScript, theObjectNames,
599                                isPublished, anEntryToBadName, aObjListToPublish );
600         
601         // publish collected objects
602         std::map< int, std::string > anEntryToCommandMap; // sort publishing commands by object entry
603         int i = 1, n = aObjListToPublish.Length();
604         for ( ; i <= n; i++ )
605         {
606           const TCollection_AsciiString& aEntry = aObjListToPublish.Value(i);
607           if (!theObjectNames.IsBound( aEntry ))
608             continue;
609           PublishObject( aEntry, theObjectNames.Find(aEntry),
610                         theObjectNames, aEntry2StEntry, aStEntry2Entry,
611                         anEntryToBadName, anEntryToCommandMap, anIgnoreObjMap );
612         }
613         // add publishing commands to the script
614         std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin();
615         for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand )
616           aFuncScript += (char*)anEntryToCommand->second.c_str();
617         
618         // PTv, 0020001 add result objects from RestoreSubShapes into ignore list,
619         //  because they will be published during command execution
620         int indx = anAfterScript.Search( "RestoreSubShapes" );
621         if ( indx != -1 ) {
622           TCollection_AsciiString aSubStr = anAfterScript.SubString(1, indx);
623           Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aSubStr);
624           i = 1, n = aSeq->Length();
625           for ( ; i <= n; i+=2) {
626             TCollection_AsciiString anEntry =
627               aSubStr.SubString(aSeq->Value(i), aSeq->Value(i+1));
628             if (!anIgnoreObjMap.count(anEntry.ToCString()))
629               anIgnoreObjMap.insert(anEntry.ToCString());
630           }
631         }
632
633         aObjListToPublish.Clear();
634         aScript += aFuncScript;
635         aFuncScript.Clear();
636       }
637       aFuncScript += anAfterScript;
638     }
639   }
640
641   // Replace entries by the names
642   aObjListToPublish.Clear();
643   ReplaceEntriesByNames( aFuncScript, theObjectNames,
644                          isPublished, anEntryToBadName, aObjListToPublish );
645   
646   aScript += aFuncScript;
647
648   // ouv : NPAL12872
649   AddObjectColors( theDocID, aScript, theObjectNames );
650
651   // Make script to publish in study
652   if ( isPublished )
653   {
654     std::map< int, std::string > anEntryToCommandMap; // sort publishing commands by object entry
655     for (anEntryToNameIt.Initialize( theObjectNames );
656          anEntryToNameIt.More();
657          anEntryToNameIt.Next())
658     {
659       const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
660       if (anIgnoreObjMap.count(aEntry.ToCString()))
661         continue; // should not be dumped
662       const TCollection_AsciiString& aName = anEntryToNameIt.Value();
663       PublishObject( aEntry, aName, theObjectNames,
664                     aEntry2StEntry, aStEntry2Entry,
665                     anEntryToBadName, anEntryToCommandMap, anIgnoreObjMap );
666     }
667     // add publishing commands to the script
668     std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin();
669     for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand )
670       aScript += (char*)anEntryToCommand->second.c_str();
671   }
672
673   //aScript += "\n\tpass\n";
674   aScript += "\n";
675   aValidScript = true;
676
677   // fill _studyEntry2NameMap and build globalVars
678   TCollection_AsciiString globalVars;
679   _studyEntry2NameMap.Clear();
680   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString aStEntryToEntryIt;
681   for (aStEntryToEntryIt.Initialize( aStEntry2Entry );
682        aStEntryToEntryIt.More();
683        aStEntryToEntryIt.Next() )
684   {
685     const TCollection_AsciiString & name = theObjectNames( aStEntryToEntryIt.Value() );
686     _studyEntry2NameMap.Bind (aStEntryToEntryIt.Key(), name );
687     if ( !globalVars.IsEmpty() )
688       globalVars += ", ";
689     globalVars += name;
690   }
691   if ( !globalVars.IsEmpty() ) {
692     globalVars.Insert( 1, "\n\tglobal " );
693     aScript.Insert( posToInsertGlobalVars, globalVars );
694   }
695
696   return aScript;
697 }
698
699 //=======================================================================
700 //function : GetDumpName
701 //purpose  :
702 //=======================================================================
703
704 const char* GEOM_Engine::GetDumpName (const char* theStudyEntry) const
705 {
706   if ( _studyEntry2NameMap.IsBound( (char*)theStudyEntry ))
707     return _studyEntry2NameMap( (char*)theStudyEntry ).ToCString();
708
709   return NULL;
710 }
711
712 //=======================================================================
713 //function : GetAllDumpNames
714 //purpose  :
715 //=======================================================================
716
717 Handle(TColStd_HSequenceOfAsciiString) GEOM_Engine::GetAllDumpNames() const
718 {
719   Handle(TColStd_HSequenceOfAsciiString) aRetSeq = new TColStd_HSequenceOfAsciiString;
720
721   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString it (_studyEntry2NameMap);
722   for (; it.More(); it.Next()) {
723     aRetSeq->Append(it.Value());
724   }
725
726   return aRetSeq;
727 }
728
729 #define TEXTURE_LABEL_ID       1
730 #define TEXTURE_LABEL_FILE     2
731 #define TEXTURE_LABEL_WIDTH    3
732 #define TEXTURE_LABEL_HEIGHT   4
733 #define TEXTURE_LABEL_DATA     5
734
735 int GEOM_Engine::addTexture(int theDocID, int theWidth, int theHeight, 
736                             const Handle(TDataStd_HArray1OfByte)& theTexture,
737                             const TCollection_AsciiString& theFileName)
738 {
739   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
740   Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main());
741
742   // NPAL18604: use existing label to decrease memory usage,
743   //            if this label has been freed (object deleted)
744   bool useExisting = false;
745   TDF_Label aChild;
746   if (_freeLabels.find(theDocID) != _freeLabels.end()) {
747     std::list<TDF_Label>& aFreeLabels = _freeLabels[theDocID];
748     if (!aFreeLabels.empty()) {
749       useExisting = true;
750       aChild = aFreeLabels.front();
751       aFreeLabels.pop_front();
752     }
753   }
754   if (!useExisting) {
755     // create new label
756     aChild = TDF_TagSource::NewChild(aDoc->Main());
757   }
758
759   aChild.ForgetAllAttributes(Standard_True);
760   Handle(TDataStd_TreeNode) node;
761   if ( !aChild.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), node ) )
762     node = TDataStd_TreeNode::Set(aChild);
763   TDataStd_UAttribute::Set(aChild, GetTextureGUID());
764
765   static int aTextureID = 0;
766
767   TDataStd_Integer::Set(aChild.FindChild(TEXTURE_LABEL_ID),     ++aTextureID);
768   TDataStd_Comment::Set(aChild.FindChild(TEXTURE_LABEL_FILE),   theFileName);
769   TDataStd_Integer::Set(aChild.FindChild(TEXTURE_LABEL_WIDTH),  theWidth);
770   TDataStd_Integer::Set(aChild.FindChild(TEXTURE_LABEL_HEIGHT), theHeight);
771
772   Handle(TDataStd_ByteArray) anAttr =
773     TDataStd_ByteArray::Set(aChild.FindChild(TEXTURE_LABEL_DATA), 
774                             theTexture.IsNull() ? 0 : theTexture->Lower(),
775                             theTexture.IsNull() ? 0 : theTexture->Upper());
776   anAttr->ChangeArray(theTexture);
777
778   return aTextureID;
779 }
780
781 Handle(TDataStd_HArray1OfByte) GEOM_Engine::getTexture(int theDocID, int theTextureID,
782                                                        int& theWidth, int& theHeight,
783                                                        TCollection_AsciiString& theFileName)
784 {
785   Handle(TDataStd_HArray1OfByte) anArray;
786   theWidth = theHeight = 0;
787
788   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
789
790   TDF_ChildIterator anIterator(aDoc->Main(), Standard_True);
791   bool found = false;
792   for (; anIterator.More() && !found; anIterator.Next()) {
793     TDF_Label aTextureLabel = anIterator.Value();
794     if (aTextureLabel.IsAttribute( GetTextureGUID())) {
795       TDF_Label anIDLabel = aTextureLabel.FindChild(TEXTURE_LABEL_ID, Standard_False);
796       Handle(TDataStd_Integer) anIdAttr;
797       if(!anIDLabel.IsNull() && anIDLabel.FindAttribute(TDataStd_Integer::GetID(), anIdAttr) && 
798          anIdAttr->Get() == theTextureID) {
799         TDF_Label aFileLabel   = aTextureLabel.FindChild(TEXTURE_LABEL_FILE,    Standard_False);
800         TDF_Label aWidthLabel  = aTextureLabel.FindChild(TEXTURE_LABEL_WIDTH,   Standard_False);
801         TDF_Label aHeightLabel = aTextureLabel.FindChild(TEXTURE_LABEL_HEIGHT,  Standard_False);
802         TDF_Label aDataLabel   = aTextureLabel.FindChild(TEXTURE_LABEL_DATA,    Standard_False);
803         Handle(TDataStd_Integer) aWidthAttr, aHeightAttr;
804         Handle(TDataStd_ByteArray) aTextureAttr;
805         Handle(TDataStd_Comment) aFileAttr;
806         if (!aWidthLabel.IsNull()  && aWidthLabel.FindAttribute(TDataStd_Integer::GetID(),  aWidthAttr) &&
807             !aHeightLabel.IsNull() && aHeightLabel.FindAttribute(TDataStd_Integer::GetID(), aHeightAttr) &&
808             !aDataLabel.IsNull()   && aDataLabel.FindAttribute(TDataStd_ByteArray::GetID(), aTextureAttr)) {
809           theWidth = aWidthAttr->Get();
810           theHeight = aHeightAttr->Get();
811           anArray = aTextureAttr->InternalArray();
812         }
813         if (!aFileLabel.IsNull() && aFileLabel.FindAttribute(TDataStd_Comment::GetID(), aFileAttr))
814           theFileName = aFileAttr->Get();
815         found = true;
816       }
817     }
818   }
819   return anArray;
820 }
821
822 std::list<int> GEOM_Engine::getAllTextures(int theDocID)
823 {
824   std::list<int> id_list;
825
826   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
827
828   TDF_ChildIterator anIterator(aDoc->Main(), Standard_True);
829   for (; anIterator.More(); anIterator.Next()) {
830     TDF_Label aTextureLabel = anIterator.Value();
831     if (aTextureLabel.IsAttribute( GetTextureGUID())) {
832       TDF_Label anIDLabel = aTextureLabel.FindChild(TEXTURE_LABEL_ID, Standard_False);
833       Handle(TDataStd_Integer) anIdAttr;
834       if(!anIDLabel.IsNull() && anIDLabel.FindAttribute(TDataStd_Integer::GetID(), anIdAttr))
835         id_list.push_back((int)anIdAttr->Get());
836     }
837   }
838   return id_list;
839 }
840
841 //===========================================================================
842 //                     Internal functions
843 //===========================================================================
844
845 //=============================================================================
846 /*!
847  *  ProcessFunction: Dump fucntion description into script
848  */
849 //=============================================================================
850 bool ProcessFunction(Handle(GEOM_Function)&     theFunction,
851                      TCollection_AsciiString&   theScript,
852                      TCollection_AsciiString&   theAfterScript,
853                      const TVariablesList&      theVariables,
854                      const bool                 theIsPublished,
855                      TDF_LabelMap&              theProcessed,
856                      std::set<std::string>&     theIgnoreObjs,
857                      bool&                      theIsDumpCollected)
858 {
859   theIsDumpCollected = false;
860   if (theFunction.IsNull()) return false;
861
862   if (theProcessed.Contains(theFunction->GetEntry())) return false;
863
864   // pass functions, that depends on nonexisting ones
865   bool doNotProcess = false;
866   TDF_LabelSequence aSeq;
867   theFunction->GetDependency(aSeq);
868   Standard_Integer aLen = aSeq.Length();
869   for (Standard_Integer i = 1; i <= aLen && !doNotProcess; i++) {
870     TDF_Label aRefLabel = aSeq.Value(i);
871     Handle(TDF_Reference) aRef;
872     if (!aRefLabel.FindAttribute(TDF_Reference::GetID(), aRef)) {
873       doNotProcess = true;
874     }
875     else {
876       if (aRef.IsNull() || aRef->Get().IsNull()) {
877         doNotProcess = true;
878       }
879       else {
880         Handle(TDataStd_TreeNode) aT;
881         if (!TDataStd_TreeNode::Find(aRef->Get(), aT)) {
882           doNotProcess = true;
883         }
884         else {
885           TDF_Label aDepLabel = aT->Label();
886           Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(aDepLabel);
887
888           if (aFunction.IsNull()) doNotProcess = true;
889           else if (!theProcessed.Contains(aDepLabel)) doNotProcess = true;
890         }
891       }
892     }
893   }
894
895   if (doNotProcess) {
896     TCollection_AsciiString anObjEntry;
897     TDF_Tool::Entry(theFunction->GetOwnerEntry(), anObjEntry);
898     theIgnoreObjs.insert(anObjEntry.ToCString());
899     return false;
900   }
901   theProcessed.Add(theFunction->GetEntry());
902
903   TCollection_AsciiString aDescr = theFunction->GetDescription();
904   if(aDescr.Length() == 0) return false;
905
906   //Check if its internal function which doesn't requires dumping
907   if(aDescr == "None") return false;
908
909   // 0020001 PTv, check for critical functions, which requier dump of objects
910   if (theIsPublished)
911   {
912     // currently, there is only one function "RestoreSubShapes",
913     // later this check could be replaced by iterations on list of such functions
914     if (aDescr.Search( "RestoreSubShapes" ) != -1)
915       theIsDumpCollected = true;
916   }
917
918   //Replace parameter by notebook variables
919   ReplaceVariables(aDescr,theVariables);
920   if ( theIsDumpCollected ) {
921     int i = 1;
922     bool isBefore = true;
923     TCollection_AsciiString aSubStr = aDescr.Token("\n\t", i++);
924     while (!aSubStr.IsEmpty()) {
925       if (isBefore && aSubStr.Search( "RestoreSubShapes" ) == -1)
926         theScript += TCollection_AsciiString("\n\t") + aSubStr;
927       else
928         theAfterScript += TCollection_AsciiString("\n\t") + aSubStr;
929       aSubStr = aDescr.Token("\n\t", i++);
930     }
931   }
932   else {
933     theScript += "\n\t";
934     theScript += aDescr;
935   }
936   return true;
937 }
938
939 //=============================================================================
940 /*!
941  *  FindEntries: Returns a sequence of start/end positions of entries in the string
942  */
943 //=============================================================================
944 Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString)
945 {
946   Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
947   Standard_Integer aLen = theString.Length();
948   Standard_Boolean isFound = Standard_False;
949
950   const char* arr = theString.ToCString();
951   Standard_Integer i = 0, j;
952
953   while(i < aLen) {
954     int c = (int)arr[i];
955     j = i+1;
956     if(c >= 48 && c <= 57) { //Is digit?
957
958       isFound = Standard_False;
959       while((j < aLen) && ((c >= 48 && c <= 57) || c == 58) ) { //Check if it is an entry
960         c = (int)arr[j++];
961         if(c == 58) isFound = Standard_True;
962       }
963
964       if(isFound && arr[j-2] != 58) { // last char should be a diggit
965         aSeq->Append(i+1); // +1 because AsciiString starts from 1
966         aSeq->Append(j-1);
967       }
968     }
969
970     i = j;
971   }
972
973   return aSeq;
974 }
975
976 //=============================================================================
977 /*!
978  *  ReplaceVariables: Replace parameters of the function by variales from 
979  *                    Notebook if need
980  */
981 //=============================================================================
982 void ReplaceVariables(TCollection_AsciiString& theCommand, 
983                       const TVariablesList&    theVariables)
984 {
985   if (MYDEBUG)
986     cout<<"Command : "<<theCommand<<endl;
987
988   if (MYDEBUG) {
989     cout<<"All Entries:"<<endl;
990     TVariablesList::const_iterator it = theVariables.begin();
991     for(;it != theVariables.end();it++)
992       cout<<"\t'"<<(*it).first<<"'"<<endl;
993   }
994
995   //Additional case - multi-row commands
996   int aCommandIndex = 1;
997   while( aCommandIndex < 10 ) { // tmp check
998     TCollection_AsciiString aCommand = theCommand.Token("\n",aCommandIndex);
999     if( aCommand.Length() == 0 )
1000       break;
1001
1002     if (MYDEBUG)
1003       cout<<"Sub-command : "<<aCommand<<endl;
1004
1005     Standard_Integer aStartCommandPos = theCommand.Location(aCommand,1,theCommand.Length());
1006     Standard_Integer aEndCommandPos = aStartCommandPos + aCommand.Length();
1007
1008     //Get Entry of the result object
1009     TCollection_AsciiString anEntry;
1010     if( aCommand.Search("=") != -1 ) // command returns an object
1011       anEntry = aCommand.Token("=",1);
1012     else { // command modifies the object
1013       if (int aStartEntryPos = aCommand.Location(1,'(',1,aCommand.Length()))
1014         if (int aEndEntryPos = aCommand.Location(1,',',aStartEntryPos,aCommand.Length()))
1015           anEntry = aCommand.SubString(aStartEntryPos+1, aEndEntryPos-1);
1016     }
1017     //Remove white spaces
1018     anEntry.RightAdjust();
1019     anEntry.LeftAdjust();
1020     if(MYDEBUG)
1021       cout<<"Result entry : '" <<anEntry<<"'"<<endl;
1022
1023     if ( anEntry.IsEmpty() ) {
1024       aCommandIndex++;
1025       continue;
1026     }
1027
1028     //Check if result is list of entries - enough to get the first entry in this case
1029     int aNbEntries = 1;
1030     if( anEntry.Value( 1 ) == O_SQR_BRACKET && anEntry.Value( anEntry.Length() ) == C_SQR_BRACKET ) {
1031       while(anEntry.Location(aNbEntries,COMMA,1,anEntry.Length()))
1032         aNbEntries++;
1033       TCollection_AsciiString aSeparator(COMMA);
1034       anEntry = anEntry.Token(aSeparator.ToCString(),1);
1035       anEntry.Remove( 1, 1 );
1036       anEntry.RightAdjust();
1037       anEntry.LeftAdjust();
1038       if(MYDEBUG)
1039         cout<<"Sub-entry : '" <<anEntry<<"'"<<endl;
1040     }
1041     
1042     //Find variables used for object construction
1043     ObjectStates* aStates = 0;
1044     TVariablesList::const_iterator it = theVariables.find(anEntry);
1045     if( it != theVariables.end() )
1046       aStates = (*it).second;
1047
1048     if(!aStates) {
1049       if(MYDEBUG)
1050         cout<<"Valiables list empty!!!"<<endl;
1051       aCommandIndex++;
1052       continue;
1053     }
1054
1055     TState aVariables = aStates->GetCurrectState();
1056
1057     if(MYDEBUG) {
1058       cout<<"Variables from SObject:"<<endl;
1059       for (int i = 0; i < aVariables.size();i++)
1060         cout<<"\t Variable["<<i<<"] = "<<aVariables[i].myVariable<<endl;
1061     }
1062
1063     //Calculate total number of parameters
1064     Standard_Integer aTotalNbParams = 1;
1065     while(aCommand.Location(aTotalNbParams,COMMA,1,aCommand.Length()))
1066       aTotalNbParams++;
1067
1068     if(MYDEBUG)
1069       cout<<"aTotalNbParams = "<<aTotalNbParams<<endl;
1070
1071     Standard_Integer aFirstParam = aNbEntries;
1072
1073     //Replace parameters by variables
1074     Standard_Integer aStartPos = 0;
1075     Standard_Integer aEndPos = 0;
1076     int iVar = 0;
1077     TCollection_AsciiString aVar, aReplacedVar;
1078     for(Standard_Integer i=aFirstParam;i <= aTotalNbParams;i++) {
1079       //Replace first parameter (bettwen '(' character and first ',' character)
1080       if(i == aFirstParam)
1081       {
1082         aStartPos = aCommand.Location(O_BRACKET, 1, aCommand.Length()) + 1;
1083         if(aTotalNbParams - aNbEntries > 0 )
1084           aEndPos = aCommand.Location(aFirstParam, COMMA, 1, aCommand.Length());
1085         else
1086           aEndPos = aCommand.Location(C_BRACKET, 1, aCommand.Length()); 
1087       }
1088       //Replace last parameter (bettwen ',' character and ')' character)
1089       else if(i == aTotalNbParams)
1090       {
1091         aStartPos = aCommand.Location(i-1, COMMA, 1, aCommand.Length()) + 2;
1092         aEndPos = aCommand.Location(C_BRACKET, 1, aCommand.Length());
1093       }
1094       //Replace other parameters (bettwen two ',' characters)
1095       else if(i != aFirstParam && i != aTotalNbParams )
1096       {
1097         aStartPos = aCommand.Location(i-1, COMMA, 1, aCommand.Length()) + 2;
1098         aEndPos = aCommand.Location(i, COMMA, 1, aCommand.Length());
1099       }
1100
1101       if( aCommand.Value( aStartPos ) == O_SQR_BRACKET )
1102         aStartPos++;
1103       if( aCommand.Value( aEndPos-1 ) == C_SQR_BRACKET )
1104         aEndPos--;
1105       if ( aStartPos == aEndPos )
1106         continue; // PAL20889: for "[]"
1107
1108       if(MYDEBUG) 
1109         cout<<"aStartPos = "<<aStartPos<<", aEndPos = "<<aEndPos<<endl;
1110
1111       aVar = aCommand.SubString(aStartPos, aEndPos-1);
1112       aVar.RightAdjust();
1113       aVar.LeftAdjust();
1114     
1115       if(MYDEBUG) 
1116         cout<<"Variable: '"<< aVar <<"'"<<endl;
1117
1118       // specific case for sketcher
1119       if(aVar.Location( TCollection_AsciiString("Sketcher:"), 1, aVar.Length() ) != 0) {
1120         Standard_Integer aNbSections = 1;
1121         while( aVar.Location( aNbSections, ':', 1, aVar.Length() ) )
1122           aNbSections++;
1123         aNbSections--;
1124
1125         int aStartSectionPos = 0, aEndSectionPos = 0;
1126         TCollection_AsciiString aSection, aReplacedSection;
1127         for(Standard_Integer aSectionIndex = 1; aSectionIndex <= aNbSections; aSectionIndex++) {
1128           aStartSectionPos = aVar.Location( aSectionIndex, ':', 1, aVar.Length() ) + 1;
1129           if( aSectionIndex != aNbSections )
1130             aEndSectionPos = aVar.Location( aSectionIndex + 1, ':', 1, aVar.Length() );
1131           else
1132             aEndSectionPos = aVar.Length();
1133
1134           aSection = aVar.SubString(aStartSectionPos, aEndSectionPos-1);
1135           if(MYDEBUG) 
1136             cout<<"aSection: "<<aSection<<endl;
1137
1138           Standard_Integer aNbParams = 1;
1139           while( aSection.Location( aNbParams, ' ', 1, aSection.Length() ) )
1140             aNbParams++;
1141           aNbParams--;
1142
1143           int aStartParamPos = 0, aEndParamPos = 0;
1144           TCollection_AsciiString aParameter, aReplacedParameter;
1145           for(Standard_Integer aParamIndex = 1; aParamIndex <= aNbParams; aParamIndex++) {
1146             aStartParamPos = aSection.Location( aParamIndex, ' ', 1, aSection.Length() ) + 1;
1147             if( aParamIndex != aNbParams )
1148               aEndParamPos = aSection.Location( aParamIndex + 1, ' ', 1, aSection.Length() );
1149             else
1150               aEndParamPos = aSection.Length() + 1;
1151
1152             aParameter = aSection.SubString(aStartParamPos, aEndParamPos-1);
1153             if(MYDEBUG) 
1154               cout<<"aParameter: "<<aParameter<<endl;
1155
1156             if(iVar >= aVariables.size())
1157               continue;
1158
1159             aReplacedParameter = aVariables[iVar].myVariable;
1160             if(aReplacedParameter.IsEmpty()) {
1161               iVar++;
1162               continue;
1163             }
1164
1165             if(aVariables[iVar].isVariable) {
1166               aReplacedParameter.InsertBefore(1,"'");
1167               aReplacedParameter.InsertAfter(aReplacedParameter.Length(),"'");
1168             }
1169
1170             if(MYDEBUG) 
1171               cout<<"aSection before : "<<aSection<<endl;
1172             aSection.Remove(aStartParamPos, aEndParamPos - aStartParamPos);
1173             aSection.Insert(aStartParamPos, aReplacedParameter);
1174             if(MYDEBUG) 
1175               cout<<"aSection after  : "<<aSection<<endl<<endl;
1176             iVar++;
1177           }
1178           if(MYDEBUG) 
1179             cout<<"aVar before : "<<aVar<<endl;
1180           aVar.Remove(aStartSectionPos, aEndSectionPos - aStartSectionPos);
1181           aVar.Insert(aStartSectionPos, aSection);
1182           if(MYDEBUG) 
1183             cout<<"aVar after  : "<<aVar<<endl<<endl;
1184         }
1185
1186         if(MYDEBUG) 
1187           cout<<"aCommand before : "<<aCommand<<endl;
1188         aCommand.Remove(aStartPos, aEndPos - aStartPos);
1189         aCommand.Insert(aStartPos, aVar);
1190         if(MYDEBUG) 
1191           cout<<"aCommand after  : "<<aCommand<<endl;
1192
1193         break;
1194       } // end of specific case for sketcher
1195
1196       //If parameter is entry or 'None', skip it
1197       if(theVariables.find(aVar) != theVariables.end() || aVar.Search(":") != -1 || aVar == PY_NULL)
1198         continue;
1199
1200       if(iVar >= aVariables.size())
1201         continue;
1202
1203       aReplacedVar = aVariables[iVar].myVariable;
1204       if(aReplacedVar.IsEmpty()) {
1205         iVar++;
1206         continue;
1207       }
1208
1209       if(aVariables[iVar].isVariable) {
1210         aReplacedVar.InsertBefore(1,"\"");
1211         aReplacedVar.InsertAfter(aReplacedVar.Length(),"\"");
1212       }
1213
1214       aCommand.Remove(aStartPos, aEndPos - aStartPos);
1215       aCommand.Insert(aStartPos, aReplacedVar);
1216       iVar++;
1217     }
1218
1219     theCommand.Remove(aStartCommandPos, aEndCommandPos - aStartCommandPos);
1220     theCommand.Insert(aStartCommandPos, aCommand);
1221
1222     aCommandIndex++;
1223
1224     aStates->IncrementState();
1225   }
1226
1227   if (MYDEBUG)
1228     cout<<"Command : "<<theCommand<<endl;
1229 }
1230
1231 //=============================================================================
1232 /*!
1233  *  ReplaceEntriesByNames: Replace object entries by their names
1234  */
1235 //=============================================================================
1236 void ReplaceEntriesByNames (TCollection_AsciiString&                  theScript,
1237                             Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
1238                             const bool                                theIsPublished,
1239                             Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName,
1240                             TColStd_SequenceOfAsciiString&            theObjListToPublish)
1241 {
1242   Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(theScript);
1243   Standard_Integer aLen = aSeq->Length(), objectCounter = 0, aStart = 1, aScriptLength = theScript.Length();
1244   Resource_DataMapOfAsciiStringAsciiString aNameToEntry;
1245
1246   //Replace entries by the names
1247   TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("geomObj_"),
1248     allowedChars ("qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0987654321_");
1249   if (aLen == 0) anUpdatedScript = theScript;
1250
1251   for (Standard_Integer i = 1; i <= aLen; i+=2) {
1252     anUpdatedScript += theScript.SubString(aStart, aSeq->Value(i)-1);
1253     anEntry = theScript.SubString(aSeq->Value(i), aSeq->Value(i+1));
1254     theObjListToPublish.Append( anEntry );
1255     if (theObjectNames.IsBound(anEntry)) {
1256       aName = theObjectNames.Find(anEntry);
1257       // check validity of aName
1258       bool isValidName = true;
1259       if ( aName.IsIntegerValue() ) { // aName must not start with a digit
1260         aName.Insert( 1, 'a' );
1261         isValidName = false;
1262       }
1263       int p, p2=1; // replace not allowed chars
1264       while ((p = aName.FirstLocationNotInSet(allowedChars, p2, aName.Length()))) {
1265         aName.SetValue(p, '_');
1266         p2=p;
1267         isValidName = false;
1268       }
1269       if ( aNameToEntry.IsBound( aName ) && anEntry != aNameToEntry( aName ))
1270       {  // diff objects have same name - make a new name by appending a digit
1271         TCollection_AsciiString aName2;
1272         Standard_Integer i = 0;
1273         do {
1274           aName2 = aName + "_" + ++i;
1275         } while ( aNameToEntry.IsBound( aName2 ) && anEntry != aNameToEntry( aName2 ));
1276         aName = aName2;
1277         isValidName = false;
1278       }
1279       if ( !isValidName ) {
1280         if ( theIsPublished )
1281           theEntryToBadName.Bind( anEntry, theObjectNames.Find(anEntry) );
1282         theObjectNames( anEntry ) = aName;
1283       }
1284     }
1285     else {
1286       do {
1287         aName = aBaseName + TCollection_AsciiString(++objectCounter);
1288       } while(aNameToEntry.IsBound(aName));
1289       theObjectNames.Bind(anEntry, aName);
1290     }
1291     aNameToEntry.Bind(aName, anEntry); // to detect same name of diff objects
1292
1293     anUpdatedScript += aName;
1294     aStart = aSeq->Value(i+1) + 1;
1295   }
1296
1297   //Add final part of the script
1298   if (aLen && aSeq->Value(aLen) < aScriptLength)
1299     anUpdatedScript += theScript.SubString(aSeq->Value(aLen)+1, aScriptLength); // mkr : IPAL11865
1300
1301   theScript = anUpdatedScript;
1302 }
1303
1304 //=============================================================================
1305 /*!
1306  *  AddObjectColors: Add color to objects
1307  */
1308 //=============================================================================
1309 void AddObjectColors (int                                             theDocID,
1310                       TCollection_AsciiString&                        theScript,
1311                       const Resource_DataMapOfAsciiStringAsciiString& theObjectNames)
1312 {
1313   GEOM_Engine* engine = GEOM_Engine::GetEngine();
1314   Handle(TDocStd_Document) aDoc = engine->GetDocument(theDocID);
1315
1316   Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString anEntryToNameIt;
1317   for (anEntryToNameIt.Initialize( theObjectNames );
1318        anEntryToNameIt.More();
1319        anEntryToNameIt.Next())
1320   {
1321     const TCollection_AsciiString& aEntry = anEntryToNameIt.Key();
1322     const TCollection_AsciiString& aName = anEntryToNameIt.Value();
1323
1324     TDF_Label L;
1325     TDF_Tool::Label( aDoc->GetData(), aEntry, L );
1326     if ( L.IsNull() )
1327       continue;
1328
1329     Handle(GEOM_Object) obj = GEOM_Object::GetObject( L );
1330     if ( obj.IsNull() )
1331       continue;
1332
1333     bool anAutoColor = obj->GetAutoColor();
1334     if ( anAutoColor )
1335     {
1336       TCollection_AsciiString aCommand( "\n\t" );
1337       aCommand += aName + ".SetAutoColor(1)";
1338       theScript += aCommand.ToCString();
1339     }
1340
1341     SALOMEDS::Color aColor = obj->GetColor();
1342     if ( aColor.R >= 0 && aColor.G >= 0 && aColor.B >= 0 )
1343     {
1344       TCollection_AsciiString aCommand( "\n\t" );
1345       aCommand += aName + ".SetColor(SALOMEDS.Color(" + aColor.R + "," + aColor.G + "," + aColor.B + "))";
1346       theScript += aCommand.ToCString();
1347     }
1348     
1349     Aspect_TypeOfMarker aMarkerType = obj->GetMarkerType();
1350     if (aMarkerType >= Aspect_TOM_POINT && aMarkerType < Aspect_TOM_USERDEFINED) {
1351       TCollection_AsciiString aCommand( "\n\t" );
1352       aCommand += aName + ".SetMarkerStd(";
1353       switch (aMarkerType) {
1354       case Aspect_TOM_POINT:   aCommand += "GEOM.MT_POINT";   break;
1355       case Aspect_TOM_PLUS:    aCommand += "GEOM.MT_PLUS";    break;
1356       case Aspect_TOM_STAR:    aCommand += "GEOM.MT_STAR";    break;
1357       case Aspect_TOM_O:       aCommand += "GEOM.MT_O";       break;
1358       case Aspect_TOM_X:       aCommand += "GEOM.MT_X";       break;
1359       case Aspect_TOM_O_POINT: aCommand += "GEOM.MT_O_POINT"; break;
1360       case Aspect_TOM_O_PLUS:  aCommand += "GEOM.MT_O_PLUS";  break;
1361       case Aspect_TOM_O_STAR:  aCommand += "GEOM.MT_O_STAR";  break;
1362       case Aspect_TOM_O_X:     aCommand += "GEOM.MT_O_X";     break;
1363       case Aspect_TOM_BALL:    aCommand += "GEOM.MT_BALL";    break;
1364       case Aspect_TOM_RING1:   aCommand += "GEOM.MT_RING1";   break;
1365       case Aspect_TOM_RING2:   aCommand += "GEOM.MT_RING2";   break;
1366       case Aspect_TOM_RING3:   aCommand += "GEOM.MT_RING3";   break;
1367       default:                 aCommand += "GEOM.MT_NONE";    break; // just for completeness, should not get here
1368       }
1369       aCommand += ", ";
1370       int aSize = (int)( obj->GetMarkerSize()/0.5 ) - 1;
1371       switch (aSize) {
1372       case  1: aCommand += "GEOM.MS_10";   break;
1373       case  2: aCommand += "GEOM.MS_15";   break;
1374       case  3: aCommand += "GEOM.MS_20";   break;
1375       case  4: aCommand += "GEOM.MS_25";   break;
1376       case  5: aCommand += "GEOM.MS_30";   break;
1377       case  6: aCommand += "GEOM.MS_35";   break;
1378       case  7: aCommand += "GEOM.MS_40";   break;
1379       case  8: aCommand += "GEOM.MS_45";   break;
1380       case  9: aCommand += "GEOM.MS_50";   break;
1381       case 10: aCommand += "GEOM.MS_55";   break;
1382       case 11: aCommand += "GEOM.MS_60";   break;
1383       case 12: aCommand += "GEOM.MS_65";   break;
1384       case 13: aCommand += "GEOM.MS_70";   break;
1385       default: aCommand += "GEOM.MS_NONE"; break;
1386       }
1387       aCommand += ")";
1388       theScript += aCommand.ToCString();
1389     }
1390     else if (aMarkerType == Aspect_TOM_USERDEFINED) {
1391       int aMarkerTextureID = obj->GetMarkerTexture();
1392       if (aMarkerTextureID >= 0) {
1393         TCollection_AsciiString aCommand( "\n\t" );
1394         aCommand += aName + ".SetMarkerTexture(texture_map[";
1395         aCommand += aMarkerTextureID;
1396         aCommand += "])";
1397         theScript += aCommand.ToCString();
1398       }
1399     }
1400   }
1401 }
1402
1403 static TCollection_AsciiString pack_data(const Handle(TDataStd_HArray1OfByte)& aData )
1404 {
1405   TCollection_AsciiString stream;
1406   if (!aData.IsNull()) {
1407     for (Standard_Integer i = aData->Lower(); i <= aData->Upper(); i++) {
1408       Standard_Byte byte = aData->Value(i);
1409       TCollection_AsciiString strByte = "";
1410       for (int j = 0; j < 8; j++)
1411         strByte.Prepend((byte & (1<<j)) ? "1" : "0");
1412       stream += strByte;
1413     }
1414   }
1415   return stream;
1416 }
1417
1418 void AddTextures (int theDocID, TCollection_AsciiString& theScript)
1419 {
1420   GEOM_Engine* engine = GEOM_Engine::GetEngine();
1421   std::list<int> allTextures = engine->getAllTextures(theDocID);
1422   std::list<int>::const_iterator it;
1423
1424   if (allTextures.size() > 0) {
1425     theScript += "\n\ttexture_map = {}\n";
1426     
1427     for (it = allTextures.begin(); it != allTextures.end(); ++it) {
1428       if (*it <= 0) continue;
1429       Standard_Integer aWidth, aHeight;
1430       TCollection_AsciiString aFileName;
1431       Handle(TDataStd_HArray1OfByte) aTexture = engine->getTexture(theDocID, *it, aWidth, aHeight, aFileName);
1432       if (aWidth > 0 && aHeight > 0 && !aTexture.IsNull() && aTexture->Length() > 0 ) {
1433         TCollection_AsciiString aCommand = "\n\t";
1434         aCommand += "texture_map["; aCommand += *it; aCommand += "] = ";
1435         if (aFileName != "" ) {
1436           aCommand += "geompy.LoadTexture(\"";
1437           aCommand += aFileName.ToCString();
1438           aCommand += "\")";
1439         }
1440         else {
1441           aCommand += "geompy.AddTexture(";
1442           aCommand += aWidth; aCommand += ", "; aCommand += aHeight; aCommand += ", \"";
1443           aCommand += pack_data(aTexture);
1444           aCommand += "\")";
1445         }
1446         theScript += aCommand;
1447       }
1448     }
1449     theScript += "\n";
1450   }
1451 }
1452
1453 //=============================================================================
1454 /*!
1455  *  PublishObject: publish object in study script
1456  */
1457 //=============================================================================
1458 void PublishObject (const TCollection_AsciiString&                  theEntry,
1459                     const TCollection_AsciiString&                  theName,
1460                     const Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
1461                     const Resource_DataMapOfAsciiStringAsciiString& theEntry2StEntry,
1462                     const Resource_DataMapOfAsciiStringAsciiString& theStEntry2Entry,
1463                     const Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName,
1464                     std::map< int, std::string >&                   theEntryToCommandMap,
1465                     std::set<std::string>&                          theMapOfPublished)
1466 {
1467   if ( !theEntry2StEntry.IsBound( theEntry ))
1468     return; // was not published
1469   if ( theMapOfPublished.count(theEntry.ToCString()) )
1470     return; // aready published
1471   theMapOfPublished.insert( theEntry.ToCString() );
1472
1473   TCollection_AsciiString aCommand("\n\tgeompy."), aFatherEntry;
1474
1475   // find a father entry
1476   const TCollection_AsciiString& aStudyEntry = theEntry2StEntry( theEntry );
1477   TCollection_AsciiString aFatherStudyEntry =
1478     aStudyEntry.SubString( 1, aStudyEntry.SearchFromEnd(":") - 1 );
1479   if ( theStEntry2Entry.IsBound( aFatherStudyEntry ))
1480     aFatherEntry = theStEntry2Entry( aFatherStudyEntry );
1481
1482   // make a command
1483   if ( !aFatherEntry.IsEmpty() && theObjectNames.IsBound( aFatherEntry )) {
1484         aCommand += "addToStudyInFather( ";
1485         aCommand += theObjectNames( aFatherEntry ) + ", ";
1486   }
1487   else
1488     aCommand += "addToStudy( ";
1489   if ( theEntryToBadName.IsBound( theEntry ))
1490     aCommand += theName + ", \"" + theEntryToBadName( theEntry ) + "\" )";
1491   else
1492     aCommand += theName + ", \"" + theName + "\" )";
1493
1494   // bind a command to the last digit of the entry
1495   int tag =
1496     theEntry.SubString( theEntry.SearchFromEnd(":")+1, theEntry.Length() ).IntegerValue();
1497   theEntryToCommandMap.insert( std::make_pair( tag, aCommand.ToCString() ));
1498 }
1499
1500 //================================================================================
1501 /*!
1502  * \brief Constructor
1503  */
1504 //================================================================================
1505 ObjectStates::ObjectStates()
1506 {
1507   _dumpstate = 0;
1508 }
1509
1510 //================================================================================
1511 /*!
1512  * \brief Destructor
1513  */
1514 //================================================================================
1515 ObjectStates::~ObjectStates()
1516 {
1517 }
1518
1519 //================================================================================
1520 /*!
1521  * \brief Return current object state
1522  * \retval state - Object state (vector of notebook variable)
1523  */
1524 //================================================================================
1525 TState ObjectStates::GetCurrectState() const
1526 {
1527   if(_states.size() > _dumpstate)
1528     return _states[_dumpstate];
1529   return TState();
1530 }
1531
1532 //================================================================================
1533 /*!
1534  * \brief Add new object state 
1535  * \param theState - Object state (vector of notebook variable)
1536  */
1537 //================================================================================
1538 void ObjectStates::AddState(const TState &theState)
1539 {
1540   _states.push_back(theState);
1541 }
1542
1543 //================================================================================
1544 /*!
1545  * \brief Increment object state
1546  */
1547 //================================================================================
1548 void ObjectStates::IncrementState()
1549 {
1550   _dumpstate++;
1551 }