0025418: Debug output to be limited to OCC development environment
[occt.git] / src / TDocStd / TDocStd_Document.cxx
1 // Copyright (c) 2006-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <TDocStd_Document.ixx>
15
16 #include <TDocStd.hxx>
17
18 #include <TDocStd_XLink.hxx>
19 #include <TDocStd_XLinkIterator.hxx>
20 #include <TDocStd_Application.hxx>
21
22 #include <TDocStd_Context.hxx>
23 #include <TCollection_ExtendedString.hxx>
24 #include <TCollection_AsciiString.hxx>
25 #include <TDF_AttributeIterator.hxx>
26 #include <TDF_ListIteratorOfDeltaList.hxx>
27 #include <TDF_AttributeList.hxx>
28 #include <TDF_ListIteratorOfAttributeList.hxx>
29 #include <TDF_AttributeDelta.hxx>
30 #include <TDF_AttributeDeltaList.hxx>
31 #include <TDF_ListIteratorOfAttributeDeltaList.hxx>
32 #include <TDF_Label.hxx>
33 #include <TDF_Delta.hxx>
34 #include <TDocStd_CompoundDelta.hxx>
35 #include <TDocStd_Owner.hxx>
36 #include <TDocStd_Modified.hxx>
37
38 #include <TDF_IDMap.hxx>
39 #include <TDocStd_LabelIDMapDataMap.hxx>
40
41 #include <CDM_MetaData.hxx>
42
43 // List should have a RemoveLast...
44 #define TDocStd_List_RemoveLast(theList) \
45 TDF_ListIteratorOfDeltaList it(theList); \
46 Standard_Integer i,n = theList.Extent(); \
47 for (i = 1; i < n; i++) it.Next(); \
48 theList.Remove(it);
49
50 #undef DEB_TRANS
51
52 #undef DEB_DELTA
53
54 #define BUC60836
55
56 #define SRN_DELTA_COMPACT
57
58 //=======================================================================
59 //function : Get
60 //purpose  : 
61 //=======================================================================
62
63 Handle(TDocStd_Document) TDocStd_Document::Get (const TDF_Label& acces)
64 {
65   return TDocStd_Owner::GetDocument(acces.Data());
66 }
67
68 //=======================================================================
69 //function : TDocStd_Document
70 //purpose  : 
71 //=======================================================================
72
73
74 TDocStd_Document::TDocStd_Document(const TCollection_ExtendedString& aStorageFormat) : 
75 myStorageFormat(aStorageFormat),
76 myData (new TDF_Data()),
77 myUndoLimit(0),
78 mySaveTime(0),
79 myIsNestedTransactionMode(0)
80 {
81   TDF_Transaction* pTr =  new TDF_Transaction (myData,"UNDO");
82   myUndoTransaction    = *pTr; delete pTr;
83   TDocStd_Owner::SetDocument(myData,this);
84
85 #ifdef SRN_DELTA_COMPACT
86   myFromUndo.Nullify();  
87   myFromRedo.Nullify();
88 #endif
89 }
90
91
92 //=======================================================================
93 //function : IsSaved
94 //purpose  : 
95 //=======================================================================
96
97 Standard_Boolean TDocStd_Document::IsSaved() const
98 {
99   return CDM_Document::IsStored();
100 }
101
102
103 //=======================================================================
104 //function : GetName
105 //purpose  : 
106 //=======================================================================
107
108 TCollection_ExtendedString TDocStd_Document::GetName () const
109 {
110   return CDM_Document::MetaData()->Name();
111 }
112
113 //=======================================================================
114 //function : GetPath
115 //purpose  : 
116 //=======================================================================
117
118 TCollection_ExtendedString TDocStd_Document::GetPath () const
119 {
120   return CDM_Document::MetaData()->Path();
121 }
122
123
124 //=======================================================================
125 //function : SetData
126 //purpose  : 
127 //=======================================================================
128
129 void TDocStd_Document::SetData (const Handle(TDF_Data)& D)
130 {
131   myData = D;
132   TDF_Transaction* pTr = new TDF_Transaction(myData,"UNDO");
133   myUndoTransaction = *pTr; delete pTr;  
134 }
135
136 //=======================================================================
137 //function : GetData
138 //purpose  : 
139 //=======================================================================
140
141 Handle(TDF_Data) TDocStd_Document::GetData () const
142 {
143   return myData;
144 }
145
146 //=======================================================================
147 //function : Main
148 //purpose  : 
149 //=======================================================================
150
151 TDF_Label TDocStd_Document::Main () const
152
153   return  myData->Root().FindChild(1,Standard_True);
154 }
155
156 //=======================================================================
157 //function : IsEmpty
158 //purpose  : 
159 //=======================================================================
160
161 Standard_Boolean TDocStd_Document::IsEmpty() const
162 {
163   TDF_AttributeIterator It (Main());
164   return !It.More();
165 }
166
167 //=======================================================================
168 //function : IsValid
169 //purpose  : 
170 //=======================================================================
171
172 Standard_Boolean TDocStd_Document::IsValid() const
173 {
174   return TDocStd_Modified::IsEmpty(Main());
175 }
176
177 //=======================================================================
178 //function : SetModified
179 //purpose  : 
180 //=======================================================================
181
182 void TDocStd_Document::SetModified (const TDF_Label& L)                                  
183 {  
184   TDocStd_Modified::Add(L);
185 }
186
187 //=======================================================================
188 //function : IsModified
189 //purpose  : 
190 //=======================================================================
191 //Standard_Boolean TDocStd_Document::IsModified (const TDF_Label& L) const                                 
192 //{  
193 //  return TDocStd_Modified::Contains(L);
194 //}
195
196 //=======================================================================
197 //function : PurgeModified
198 //purpose  : 
199 //=======================================================================
200
201 void TDocStd_Document::PurgeModified()
202 {   
203   TDocStd_Modified::Clear(Main()); 
204 }
205
206 //=======================================================================
207 //function : GetModified
208 //purpose  : 
209 //=======================================================================
210
211 const TDF_LabelMap&  TDocStd_Document::GetModified() const
212 {  
213   return TDocStd_Modified::Get(Main());  
214 }
215
216
217
218 //=======================================================================
219 //function : Update
220 //purpose  : 
221 //=======================================================================
222
223 void TDocStd_Document::Update(const Handle(CDM_Document)& /*aToDocument*/,
224                                const Standard_Integer aReferenceIdentifier,
225                                const Standard_Address aModifContext) 
226 {
227   const TDocStd_Context* CC = static_cast<TDocStd_Context*> (aModifContext);
228   if (CC->ModifiedReferences() || !IsUpToDate(aReferenceIdentifier)) {
229     TCollection_AsciiString aDocEntry(aReferenceIdentifier);
230     UpdateReferences(aDocEntry);
231     SetIsUpToDate(aReferenceIdentifier);
232   }
233 }
234
235 //=======================================================================
236 //function : NewCommand
237 //purpose  : 
238 //=======================================================================
239
240 void TDocStd_Document::NewCommand()
241 {
242 #ifdef OCCT_DEBUG_TRANS
243   if (myUndoTransaction.IsOpen() && myData->Transaction() > 1) {
244     Standard_DomainError::Raise ("NewCommand : many open transactions");
245   }
246 #endif
247
248   CommitTransaction();
249   OpenTransaction();
250
251 #ifdef OCCT_DEBUG_TRANS
252   cout<<"End NewCommand"<<endl;
253 #endif
254 }
255
256
257 //=======================================================================
258 //function : HasOpenCommand
259 //purpose  : 
260 //=======================================================================
261 Standard_Boolean TDocStd_Document::HasOpenCommand() const
262 {
263   return myUndoTransaction.IsOpen();
264 }
265
266 //=======================================================================
267 //function : OpenCommand
268 //purpose  : 
269 //=======================================================================
270
271 void TDocStd_Document::OpenCommand ()
272 {
273   if (!myIsNestedTransactionMode && myUndoTransaction.IsOpen()) {
274     Standard_DomainError::Raise("TDocStd_Document::OpenCommand : already open");
275   }
276   OpenTransaction();
277 //  if (myUndoLimit != 0) myUndoTransaction.Open();
278 }
279
280 //=======================================================================
281 //function : CommitCommand
282 //purpose  : 
283 //=======================================================================
284
285 Standard_Boolean TDocStd_Document::CommitCommand ()
286 {
287   return CommitTransaction();
288 }
289
290
291 //=======================================================================
292 //function : AbortCommand
293 //purpose  : 
294 //=======================================================================
295
296 void TDocStd_Document::AbortCommand ()
297
298   AbortTransaction();
299 }
300
301
302 //=======================================================================
303 //function : CommitTransaction
304 //purpose  : Private method.
305 //=======================================================================
306
307 Standard_Boolean TDocStd_Document::CommitTransaction()
308 {
309   myData->AllowModification(Standard_True);
310
311   Standard_Boolean isDone = Standard_False;
312   // nested transaction mode
313   if (myIsNestedTransactionMode && myUndoTransaction.IsOpen()) {
314
315     Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
316     Handle(TDocStd_CompoundDelta) aCompDelta =
317       Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
318     AppendDeltaToTheFirst(aCompDelta, D);
319     D = aCompDelta;
320     myUndoFILO.RemoveFirst();
321     if(myUndoFILO.Extent()) {
322       aCompDelta = Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
323       AppendDeltaToTheFirst(aCompDelta, D);
324       myUndoTransaction.Open();
325     }
326     else {
327       if(!D->IsEmpty()) {
328         myUndos.Append(D);
329         myRedos.Clear(); // if we push an Undo we clear the redos
330         isDone = Standard_True;
331       }
332     }
333
334     // deny modifications if the transaction is not opened
335     if(myOnlyTransactionModification) {
336       myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
337                                 ? Standard_True :Standard_False);
338     }
339
340   } else {
341
342   // are we undoing...
343     if (myUndoLimit != 0 && myUndoTransaction.IsOpen()) {
344
345       Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
346       if (!(D.IsNull() || D->IsEmpty())) {
347         isDone = Standard_True;
348
349         myRedos.Clear(); // if we push an Undo we clear the redos
350         myUndos.Append(D); // New undos are at the end of the list
351         // Check  the limit to remove the oldest one
352         if (myUndos.Extent() > myUndoLimit) {
353 #ifdef SRN_DELTA_COMPACT
354           Handle(TDF_Delta) aDelta = myUndos.First();
355 #endif
356           myUndos.RemoveFirst();
357 #ifdef SRN_DELTA_COMPACT
358           if(myFromUndo == aDelta) {
359             //The oldest Undo delta coincides with `from` delta
360             if(myUndos.Extent() == 1) {   //There is the only Undo
361               myFromUndo.Nullify();
362               myFromRedo.Nullify();
363             }
364             else
365               myFromUndo = myUndos.First();
366           }
367 #endif
368         }
369       }
370
371     }
372
373     // deny or allow modifications acording to transaction state
374     if(myOnlyTransactionModification) {
375       myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
376                                  ? Standard_True :Standard_False);
377     }
378   }
379   // Notify CDM_Application of the successful commit
380   if (isDone && IsOpened()) {
381     const Handle(TDocStd_Application) anAppli =
382       Handle(TDocStd_Application)::DownCast(Application());
383     if (!anAppli.IsNull())
384       anAppli -> OnCommitTransaction (this);
385   }
386   return isDone;
387 }
388
389
390 //=======================================================================
391 //function : AbortTransaction
392 //purpose  : Private method.
393 //=======================================================================
394
395 void TDocStd_Document::AbortTransaction()
396 {
397   myData->AllowModification(Standard_True);
398   
399   if (myUndoTransaction.IsOpen())
400     if (myUndoLimit != 0)
401       myUndoTransaction.Abort();
402
403   if (myIsNestedTransactionMode && myUndoFILO.Extent()) {
404     if (!myUndoFILO.First()->IsEmpty())
405       myData->Undo(myUndoFILO.First(),Standard_True);
406     myUndoFILO.RemoveFirst();
407     if (myUndoFILO.Extent())
408       myUndoTransaction.Open();
409   }
410   // deny or allow modifications acording to transaction state
411   if (myOnlyTransactionModification) {
412     myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
413                                ? Standard_True :Standard_False);
414   }
415   // Notify CDM_Application of the event
416   if (IsOpened()) {
417     const Handle(TDocStd_Application) anAppli =
418       Handle(TDocStd_Application)::DownCast(Application());
419     if (!anAppli.IsNull())
420       anAppli -> OnAbortTransaction (this);
421   }
422 }
423
424
425 //=======================================================================
426 //function :OpenTransaction
427 //purpose  : Private method.
428 //=======================================================================
429
430 void TDocStd_Document::OpenTransaction()
431 {
432   myData->AllowModification(Standard_True);
433
434   // nested transaction mode
435   if (myIsNestedTransactionMode) {
436
437     if (myUndoTransaction.IsOpen()) {
438       Handle(TDF_Delta) D = myUndoTransaction.Commit(Standard_True);
439       Handle(TDocStd_CompoundDelta) aCompDelta =
440         Handle(TDocStd_CompoundDelta)::DownCast(myUndoFILO.First());
441       AppendDeltaToTheFirst(aCompDelta, D);
442     }
443     Standard_Integer aLastTime = myData->Time();
444     if (myUndoFILO.Extent())
445       aLastTime = myUndoFILO.First()->EndTime();
446     Handle(TDocStd_CompoundDelta) aCompoundDelta =
447       new TDocStd_CompoundDelta;
448     aCompoundDelta->Validity(aLastTime, aLastTime);
449     myUndoFILO.Prepend(aCompoundDelta);
450   } 
451
452   if (myUndoLimit != 0) myUndoTransaction.Open();
453
454   // deny or allow modifications acording to transaction state
455   if (myOnlyTransactionModification) {
456     myData->AllowModification (myUndoTransaction.IsOpen() && myUndoLimit
457                                ? Standard_True :Standard_False);
458   }
459   // Notify CDM_Application of the event
460   if (IsOpened()) {
461     const Handle(TDocStd_Application) anAppli =
462       Handle(TDocStd_Application)::DownCast(Application());
463     if (!anAppli.IsNull())
464       anAppli -> OnOpenTransaction (this);
465   }
466 }
467
468 //=======================================================================
469 //function : SetUndoLimit
470 //purpose  : 
471 //=======================================================================
472
473 void TDocStd_Document::SetUndoLimit(const Standard_Integer L)
474 {  
475 #ifdef SRN_DELTA_COMPACT
476   myFromUndo.Nullify();  //Compaction has to aborted
477   myFromRedo.Nullify();
478 #endif
479
480   CommitTransaction ();
481   myUndoLimit = (L > 0) ? L : 0;
482   Standard_Integer n = myUndos.Extent() - myUndoLimit;
483   while (n > 0) {
484     myUndos.RemoveFirst();
485     --n;
486   }
487   // deny or allow modifications acording to transaction state
488   if(myOnlyTransactionModification) {
489     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
490                               ? Standard_True :Standard_False);
491   }
492   //OpenTransaction(); dp 15/10/99
493 }
494
495 //=======================================================================
496 //function : GetUndoLimit
497 //purpose  : 
498 //=======================================================================
499
500 Standard_Integer TDocStd_Document::GetUndoLimit() const
501 {
502   return myUndoLimit;
503 }
504
505 //=======================================================================
506 //function : Undos
507 //purpose  : 
508 //=======================================================================
509
510 Standard_Integer TDocStd_Document::GetAvailableUndos() const
511 {
512   return myUndos.Extent();
513 }
514
515 //=======================================================================
516 //function : ClearUndos
517 //purpose  : 
518 //=======================================================================
519
520 void TDocStd_Document::ClearUndos()
521 {
522   myUndos.Clear();
523   myRedos.Clear();
524 #ifdef SRN_DELTA_COMPACT
525   myFromRedo.Nullify();
526   myFromUndo.Nullify();
527 #endif
528 }
529
530 //=======================================================================
531 //function : ClearRedos
532 //purpose  : 
533 //=======================================================================
534
535 void TDocStd_Document::ClearRedos()
536 {
537   myRedos.Clear();
538 #ifdef SRN_DELTA_COMPACT
539   myFromRedo.Nullify();
540 #endif
541 }
542
543 //=======================================================================
544 //function : Undo
545 //purpose  : 
546 // Some importante notice:
547 // 1) The most recent undo delta is at the end of the list.
548 // 2) Removing the LAST item of a list is tedious, but it is done only on
549 //    Undo. Remove first is done at each command if the limit is reached!
550 // 3) To make fun, the redos are not like the undos: the most recent delta
551 //    is at the beginning! Like this, it is easier to remove it after use.
552 //=======================================================================
553 Standard_Boolean TDocStd_Document::Undo() 
554 {
555   // Don't call NewCommand(), because it may commit Interactive Attributes
556   // and generate a undesirable Delta!
557
558   Standard_Boolean isOpened = myUndoTransaction.IsOpen();
559   Standard_Boolean undoDone = Standard_False;
560   //TDF_Label currentObjectLabel = CurrentLabel (); //Sauve pour usage ulterieur.
561
562   if (!myUndos.IsEmpty()) {
563     // Reset the transaction
564     AbortTransaction();
565
566     // only for nested transaction mode
567     while(myIsNestedTransactionMode && myUndoFILO.Extent())
568       AbortTransaction();
569
570     // allow modifications
571     myData->AllowModification(Standard_True);
572
573     // Apply the Undo
574     // should test the applicability before.
575 #ifdef OCCT_DEBUG_DELTA
576     cout<<"DF before Undo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
577 #endif
578     Handle(TDF_Delta) D = myData->Undo(myUndos.Last(),Standard_True);
579 #ifdef BUC60836 
580     D->SetName(myUndos.Last()->Name());
581 #endif
582 #ifdef OCCT_DEBUG_DELTA
583     cout<<"DF after Undo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
584 #endif
585     // Push the redo
586     myRedos.Prepend(D);
587     // Remove the last Undo
588     TDocStd_List_RemoveLast(myUndos);
589     undoDone = Standard_True;
590   }
591
592   if (isOpened && undoDone) OpenTransaction();
593
594   // deny or allow modifications acording to transaction state
595   if(myOnlyTransactionModification) {
596     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
597                               ? Standard_True :Standard_False);
598   }
599   
600   return undoDone;
601 }
602
603 //=======================================================================
604 //function : GetAvailableRedos
605 //purpose  : 
606 //=======================================================================
607
608 Standard_Integer TDocStd_Document:: GetAvailableRedos() const
609 {
610   // should test the applicability before.
611   return myRedos.Extent();
612 }
613
614 //=======================================================================
615 //function : Redo
616 //purpose  : 
617 //=======================================================================
618 Standard_Boolean TDocStd_Document::Redo() 
619 {
620   Standard_Boolean isOpened = myUndoTransaction.IsOpen();
621   Standard_Boolean undoDone = Standard_False;
622   // TDF_Label currentObjectLabel = CurrentLabel();//Sauve pour usage ulterieur.
623   if (!myRedos.IsEmpty()) {
624     // should test the applicability before.
625     // Reset the transaction
626     AbortTransaction();
627
628     // only for nested transaction mode
629     while(myIsNestedTransactionMode && myUndoFILO.Extent())
630       AbortTransaction();
631
632     // allow modifications
633     myData->AllowModification(Standard_True);
634
635     // Apply the Redo
636 #ifdef OCCT_DEBUG_DELTA
637     cout<<"DF before Redo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
638 #endif
639     Handle(TDF_Delta) D = myData->Undo(myRedos.First(),Standard_True);
640 #ifdef BUC60836
641     D->SetName(myRedos.First()->Name());
642 #endif
643 #ifdef OCCT_DEBUG_DELTA
644     cout<<"DF after Redo =================================="<<endl; TDF_Tool::DeepDump(cout,myData);
645 #endif
646     // Push the redo of the redo as an undo (got it !)
647     myUndos.Append(D);
648     // remove the Redo from the head
649     myRedos.RemoveFirst();
650     undoDone = Standard_True;
651   }
652   
653   if (isOpened && undoDone) OpenTransaction();
654
655   // deny or allow modifications acording to transaction state
656   if(myOnlyTransactionModification) {
657     myData->AllowModification(myUndoTransaction.IsOpen() && myUndoLimit
658                               ? Standard_True :Standard_False);
659   }
660
661   return undoDone;
662 }
663
664 //=======================================================================
665 //function : UpdateReferences
666 //purpose  : 
667 //=======================================================================
668
669 void TDocStd_Document::UpdateReferences(const TCollection_AsciiString& aDocEntry) 
670 {
671
672   TDF_AttributeList aRefList;
673   TDocStd_XLink* xRefPtr;
674   for (TDocStd_XLinkIterator xItr (this); xItr.More(); xItr.Next()) {
675     xRefPtr = xItr.Value();
676     if (xRefPtr->DocumentEntry() == aDocEntry) {
677       aRefList.Append(xRefPtr->Update());
678     }
679   }
680   TDF_ListIteratorOfAttributeList It(aRefList);
681   for (;It.More();It.Next()) {
682     //     // mise a jour import
683     SetModified(It.Value()->Label());
684   }
685 }
686
687
688 //=======================================================================
689 //function : GetUndos
690 //purpose  : 
691 //=======================================================================
692
693 const TDF_DeltaList& TDocStd_Document::GetUndos() const 
694 {
695   return myUndos;
696 }
697
698
699 //=======================================================================
700 //function : GetRedos
701 //purpose  : 
702 //=======================================================================
703
704 const TDF_DeltaList& TDocStd_Document::GetRedos() const 
705 {
706   return myRedos;
707 }
708
709 //=======================================================================
710 //function : InitDeltaCompaction
711 //purpose  : 
712 //=======================================================================
713
714 Standard_Boolean TDocStd_Document::InitDeltaCompaction()
715 {
716 #ifdef SRN_DELTA_COMPACT
717   if (myUndoLimit == 0 || myUndos.Extent() == 0) {
718     myFromRedo.Nullify();
719     myFromUndo.Nullify();
720     return Standard_False; //No Undos to compact
721   }
722
723   myFromRedo.Nullify();
724
725   myFromUndo = myUndos.Last();
726   if(myRedos.Extent() > 0) myFromRedo = myRedos.First();
727 #endif
728   return Standard_True;
729 }
730
731 //=======================================================================
732 //function : PerformDeltaCompaction
733 //purpose  : 
734 //=======================================================================
735
736 Standard_Boolean TDocStd_Document::PerformDeltaCompaction()  
737
738 #ifdef SRN_DELTA_COMPACT
739   if(myFromUndo.IsNull()) return Standard_False;  //Redo can be Null for this operation 
740
741   TDF_DeltaList aList; 
742   Handle(TDocStd_CompoundDelta) aCompoundDelta = new TDocStd_CompoundDelta; 
743   TDF_ListIteratorOfDeltaList anIterator(myUndos); 
744   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator;
745   TDocStd_LabelIDMapDataMap aMap; 
746   Standard_Boolean isFound = Standard_False, isTimeSet = Standard_False; 
747
748   //Process Undos
749
750   for(; anIterator.More(); anIterator.Next()) { 
751     if(!isFound) { 
752       if(myFromUndo == anIterator.Value()) isFound = Standard_True; 
753       aList.Append(anIterator.Value());  //Fill the list of deltas that precede compound delta 
754       continue;
755     } 
756
757     if(!isTimeSet) {  //Set begin and end time when the compound delta is valid
758       aCompoundDelta->Validity(anIterator.Value()->BeginTime(), myUndos.Last()->EndTime());
759       isTimeSet = Standard_True;
760     } 
761     
762     aDeltasIterator.Initialize(anIterator.Value()->AttributeDeltas());
763     for(; aDeltasIterator.More(); aDeltasIterator.Next()) {   
764       if(!aMap.IsBound(aDeltasIterator.Value()->Label())) {
765         TDF_IDMap* pIDMap = new TDF_IDMap();
766         aMap.Bind(aDeltasIterator.Value()->Label(), *pIDMap);
767         delete pIDMap;
768         }
769       if(aMap(aDeltasIterator.Value()->Label()).Add(aDeltasIterator.Value()->ID())) //The attribute is not 
770         aCompoundDelta->AddAttributeDelta(aDeltasIterator.Value());                 //already in the delta
771     }
772   } 
773
774   myUndos.Clear(); 
775   myUndos.Assign(aList); 
776   myUndos.Append(aCompoundDelta); 
777
778   //Process Redos
779
780   if(myFromRedo.IsNull()) {
781     myRedos.Clear();
782     return Standard_True;
783   }
784
785   aList.Clear();
786
787   for(anIterator.Initialize(myRedos); anIterator.More(); anIterator.Next()) { 
788     aList.Append(anIterator.Value()); 
789     if(anIterator.Value() == myFromRedo) break;
790   }
791
792   myRedos.Clear();
793   myRedos.Assign(aList); 
794 #endif
795   return Standard_True; 
796
797
798
799 //=======================================================================
800 //function : StorageFormat
801 //purpose  : 
802 //=======================================================================
803
804 TCollection_ExtendedString TDocStd_Document::StorageFormat() const 
805 {
806   return myStorageFormat;
807 }
808
809
810 //=======================================================================
811 //function : ChangeStorageFormat
812 //purpose  : 
813 //=======================================================================
814
815 void TDocStd_Document::ChangeStorageFormat (const TCollection_ExtendedString& newStorageFormat) 
816 {
817   if (newStorageFormat != myStorageFormat) {
818     myStorageFormat = newStorageFormat;
819     myResourcesAreLoaded = Standard_False;
820     CDM_Document::LoadResources ();
821   }
822 }
823
824
825
826
827 //=======================================================================
828 //function : Recompute
829 //purpose  : 
830 //=======================================================================
831
832 void TDocStd_Document::Recompute ()
833 {
834   if (IsValid()) return;
835   // find the top function and execute it
836   //  Handle(TDesign_Function) F;
837   //  if (Main().FindAttribute(TDesign_Function::GetID(),F)) {
838   // TFunction_Solver slv;
839   // slv.SetTouched(GetModified());
840   // slv.ExecuteFrom(F);
841   PurgeModified();
842 }
843
844 //=======================================================================
845 //function : AppendDeltaToTheFirst
846 //purpose  : Appends delta to the first delta in the myUndoFILO
847 //=======================================================================
848
849 void TDocStd_Document::AppendDeltaToTheFirst
850   (const Handle(TDocStd_CompoundDelta)& theDelta1,
851    const Handle(TDF_Delta)& theDelta2)
852 {
853   if(theDelta2->IsEmpty()) return;
854   TDocStd_LabelIDMapDataMap aMap; 
855     
856   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator1
857     (theDelta1->AttributeDeltas());
858   for(; aDeltasIterator1.More(); aDeltasIterator1.Next()) {   
859     TDF_Label aLabel = aDeltasIterator1.Value()->Label();
860     if(!aMap.IsBound(aLabel)) {
861       TDF_IDMap aTmpIDMap;
862       aMap.Bind(aLabel, aTmpIDMap);
863     }
864     Standard_GUID anID = aDeltasIterator1.Value()->ID();
865     TDF_IDMap& anIDMap = aMap.ChangeFind(aLabel);
866     anIDMap.Add(anID);
867   }
868   
869   theDelta1->Validity(theDelta1->BeginTime(), theDelta2->EndTime());
870   TDF_ListIteratorOfAttributeDeltaList aDeltasIterator2
871     (theDelta2->AttributeDeltas());
872   for(; aDeltasIterator2.More(); aDeltasIterator2.Next()) {   
873     TDF_Label aLabel = aDeltasIterator2.Value()->Label();
874     Standard_GUID anID = aDeltasIterator2.Value()->ID();
875     if(aMap.IsBound(aLabel)) {
876       const TDF_IDMap& anIDMap = aMap.Find(aLabel);
877       if(anIDMap.Contains(anID)) continue;
878     }
879     theDelta1->AddAttributeDelta(aDeltasIterator2.Value());
880   }
881 }
882
883 //=======================================================================
884 //function : RemoveFirstUndo
885 //purpose  : 
886 //=======================================================================
887 void TDocStd_Document::RemoveFirstUndo() {
888   if (myUndos.IsEmpty()) return;
889   myUndos.RemoveFirst();
890 }
891
892 //=======================================================================
893 //function : BeforeClose
894 //purpose  : 
895 //=======================================================================
896 void TDocStd_Document::BeforeClose() 
897 {
898   SetModificationMode(Standard_False);
899   AbortTransaction();
900   if(myIsNestedTransactionMode)
901          myUndoFILO.Clear();
902   ClearUndos();
903 }