]> Creatis software - gdcm.git/blobdiff - src/gdcmDocument.cxx
* Remove memory leaks
[gdcm.git] / src / gdcmDocument.cxx
index c916dcc612584e6041273e3eb87148ab7d9e17bd..d975fd54d4c2dcd30375f0153c1641eff50ffd51 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmDocument.cxx,v $
   Language:  C++
-  Date:      $Date: 2005/09/20 15:11:19 $
-  Version:   $Revision: 1.281 $
+  Date:      $Date: 2005/10/25 09:22:15 $
+  Version:   $Revision: 1.305 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -17,8 +17,6 @@
 =========================================================================*/
 
 #include "gdcmDocument.h"
-#include "gdcmValEntry.h"
-#include "gdcmBinEntry.h"
 #include "gdcmSeqEntry.h"
 #include "gdcmGlobal.h"
 #include "gdcmUtil.h"
@@ -27,6 +25,7 @@
 #include "gdcmDictSet.h"
 #include "gdcmDocEntrySet.h"
 #include "gdcmSQItem.h"
+#include "gdcmDataEntry.h"
 
 #include <vector>
 #include <iomanip>
@@ -51,7 +50,7 @@ const unsigned int Document::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff; // 4096
  *         
  */
 Document::Document() 
-         :ElementSet(-1)
+         :ElementSet()
 {
    Fp = 0;
 
@@ -67,29 +66,6 @@ Document::Document()
    SetFileName("");
 }
 
-/**
- * \brief   Constructor (DEPRECATED : not to break the API) 
- * @param   fileName 'Document' (File or DicomDir) to be open for parsing
- */
-Document::Document( std::string const &fileName )
-         :ElementSet(-1) 
-{
-   Fp = 0;
-
-   SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
-   Initialize();
-   SwapCode = 1234;
-   Filetype = ExplicitVR;
-   Group0002Parsed = false;
-   LoadMode = LD_ALL; // Load everything, later
-
-   // Load will set it to true if sucessfull
-   IsDocumentAlreadyLoaded = false;
-   IsDocumentModified = true;
-
-   SetFileName(fileName);
-   Load( );
-}
 /**
  * \brief   Canonical destructor.
  */
@@ -137,21 +113,6 @@ bool Document::DoTheLoadingDocumentJob(  )
    if ( ! IsDocumentModified ) // Nothing to do !
       return true;
 
- //     if ( Filename == fileName )
- //     {
- //        gdcmWarningMacro( "The file was already parsed inside this "
- //                       << "gdcm::Document (its name is: "
- //                       << Filename.c_str() );
- //        return true;
- //     }
-  
-   //gdcmWarningMacro( "A file was already parsed inside this "
-   //                  << "gdcm::Document (previous name was: "
-   //                  << Filename.c_str() << ". New name is :"
-   //                  << fileName );
-     // clean out the Entries, if already parsed
-     // (probabely a mistake from the user)
    ClearEntry();
 
    Fp = 0;
@@ -166,7 +127,7 @@ bool Document::DoTheLoadingDocumentJob(  )
 
    Group0002Parsed = false;
 
-   gdcmWarningMacro( "Starting parsing of file: " << Filename.c_str());
+   gdcmDebugMacro( "Starting parsing of file: " << Filename.c_str());
 
    Fp->seekg(0, std::ios::end);
    long lgt = Fp->tellg();       // total length of the file
@@ -204,7 +165,7 @@ bool Document::DoTheLoadingDocumentJob(  )
    
    // Load 'non string' values
       
-   std::string PhotometricInterpretation = GetEntryValue(0x0028,0x0004);   
+   std::string PhotometricInterpretation = GetEntryString(0x0028,0x0004);   
    if ( PhotometricInterpretation == "PALETTE COLOR " )
    {
    // FIXME
@@ -217,16 +178,16 @@ bool Document::DoTheLoadingDocumentJob(  )
       /// defined as having an US Value Representation in the public
       /// dictionary. BUT the semantics implied by the three following
       /// lines state that the corresponding tag contents are in fact
-      /// the ones of a BinEntry.
+      /// the ones of a DataEntry.
       /// In order to fix things "Quick and Dirty" the dictionary was
       /// altered on PURPOSE but now contains a WRONG value.
       /// In order to fix things and restore the dictionary to its
       /// correct value, one needs to decided of the semantics by deciding
       /// whether the following tags are either :
-      /// - multivaluated US, and hence loaded as ValEntry, but afterwards
-      ///   also used as BinEntry, which requires the proper conversion,
-      /// - OW, and hence loaded as BinEntry, but afterwards also used
-      ///   as ValEntry, which requires the proper conversion.
+      /// - multivaluated US, and hence loaded as DataEntry, but afterwards
+      ///   also used as DataEntry, which requires the proper conversion,
+      /// - OW, and hence loaded as DataEntry, but afterwards also used
+      ///   as DataEntry, which requires the proper conversion.
       LoadEntryBinArea(0x0028,0x1201);  // R    LUT
       LoadEntryBinArea(0x0028,0x1202);  // G    LUT
       LoadEntryBinArea(0x0028,0x1203);  // B    LUT
@@ -246,12 +207,12 @@ bool Document::DoTheLoadingDocumentJob(  )
       SQItem *sqi= modLutSeq->GetFirstSQItem();
       if ( sqi != 0 )
       {
-         BinEntry *b = sqi->GetBinEntry(0x0028,0x3006);
-         if ( b != 0 )
+         DataEntry *dataEntry = sqi->GetDataEntry(0x0028,0x3006);
+         if ( dataEntry != 0 )
          {
-            if ( b->GetLength() != 0 )
+            if ( dataEntry->GetLength() != 0 )
             {
-               LoadEntryBinArea(b);    //LUT Data (CTX dependent)
+               LoadEntryBinArea(dataEntry);    //LUT Data (CTX dependent)
             }   
         }
      }      
@@ -277,26 +238,7 @@ bool Document::DoTheLoadingDocumentJob(  )
          continue;
       }
 
-      if ( dynamic_cast<ValEntry *>(d) )
-      {
-         LoadDocEntry(d, true);
-         continue;
-      }
-
-      BinEntry *b = dynamic_cast<BinEntry *>(d);
-      if ( b )
-      {
-         LoadEntryBinArea(b);
-         b->SetValue(GDCM_BINLOADED);
-         continue;
-      }
-      if ( dynamic_cast<SeqEntry *>(d) )
-      {
-         gdcmWarningMacro( "You cannot 'ForceLoad' a SeqEntry :" << std::hex
-                           << (*it).Group <<"|"<< (*it).Elem );
-         continue;
-      }
+      LoadDocEntry(d, true);
    }
 
    CloseFile(); 
@@ -312,16 +254,16 @@ bool Document::DoTheLoadingDocumentJob(  )
    // we switch lineNumber and columnNumber
    //
    std::string RecCode;
-   RecCode = GetEntryValue(0x0008, 0x0010); // recognition code (RET)
+   RecCode = GetEntryString(0x0008, 0x0010); // recognition code (RET)
    if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
        RecCode == "CANRME_AILIBOD1_1." )  // for brain-damaged softwares
                                           // with "little-endian strings"
    {
          Filetype = ACR_LIBIDO; 
-         std::string rows    = GetEntryValue(0x0028, 0x0010);
-         std::string columns = GetEntryValue(0x0028, 0x0011);
-         SetValEntry(columns, 0x0028, 0x0010);
-         SetValEntry(rows   , 0x0028, 0x0011);
+         std::string rows    = GetEntryString(0x0028, 0x0010);
+         std::string columns = GetEntryString(0x0028, 0x0011);
+         SetEntryString(columns, 0x0028, 0x0010);
+         SetEntryString(rows   , 0x0028, 0x0011);
    }
    // --- End of ACR-LibIDO kludge --- 
    return true;
@@ -335,7 +277,7 @@ bool Document::DoTheLoadingDocumentJob(  )
  */
 void Document::AddForceLoadElement (uint16_t group, uint16_t elem) 
 { 
-   Element el;
+   DicomElement el;
    el.Group = group;
    el.Elem  = elem;
    UserForceLoadList.push_back(el); 
@@ -457,9 +399,9 @@ std::string Document::GetTransferSyntax()
    // The entry might be present but not loaded (parsing and loading
    // happen at different stages): try loading and proceed with check...
    LoadDocEntrySafe(entry);
-   if (ValEntry *valEntry = dynamic_cast< ValEntry* >(entry) )
+   if (DataEntry *dataEntry = dynamic_cast<DataEntry *>(entry) )
    {
-      std::string transfer = valEntry->GetValue();
+      std::string transfer = dataEntry->GetString();
       // The actual transfer (as read from disk) might be padded. We
       // first need to remove the potential padding. We can make the
       // weak assumption that padding was not executed with digits...
@@ -471,6 +413,11 @@ std::string Document::GetTransferSyntax()
       while ( !isdigit((unsigned char)transfer[transfer.length()-1]) )
       {
          transfer.erase(transfer.length()-1, 1);
+         if  ( transfer.length() == 0 )
+         {
+            // for brain damaged headers
+            return GDCM_UNKNOWN;
+         }
       }
       return transfer;
    }
@@ -484,7 +431,7 @@ std::string Document::GetTransferSyntax()
 std::string Document::GetTransferSyntaxName()
 {
    // use the TS (TS : Transfer Syntax)
-   std::string transferSyntax = GetEntryValue(0x0002,0x0010);
+   std::string transferSyntax = GetEntryString(0x0002,0x0010);
 
    if ( (transferSyntax.find(GDCM_NOTLOADED) < transferSyntax.length()) )
    {
@@ -648,17 +595,17 @@ bool Document::CloseFile()
 }
 
 /**
- * \brief Writes in a file all the Header Entries (Dicom Elements) 
+ * \brief Writes in a file all the Entries (Dicom Elements) 
  * @param fp file pointer on an already open file (actually: Output File Stream)
  * @param filetype Type of the File to be written 
  *          (ACR-NEMA, ExplicitVR, ImplicitVR)
- * @return Always true.
  */
 void Document::WriteContent(std::ofstream *fp, FileType filetype)
 {
    // Skip if user wants to write an ACR-NEMA file
 
-   if ( filetype == ImplicitVR || filetype == ExplicitVR )
+   if ( filetype == ImplicitVR || filetype == ExplicitVR ||
+     filetype == JPEG )
    {
       // writing Dicom File Preamble
       char filePreamble[128];
@@ -693,58 +640,93 @@ void Document::WriteContent(std::ofstream *fp, FileType filetype)
 void Document::LoadEntryBinArea(uint16_t group, uint16_t elem)
 {
    // Search the corresponding DocEntry
-   DocEntry *docElement = GetDocEntry(group, elem);
-   if ( !docElement )
+   DocEntry *docEntry = GetDocEntry(group, elem);
+   if ( !docEntry )
    {
       gdcmWarningMacro(std::hex << group << "|" << elem 
                        <<  "doesn't exist" );
       return;
    }
-   BinEntry *binElement = dynamic_cast<BinEntry *>(docElement);
-   if ( !binElement )
+   DataEntry *dataEntry = dynamic_cast<DataEntry *>(docEntry);
+   if ( !dataEntry )
    {
       gdcmWarningMacro(std::hex << group << "|" << elem 
-                       <<  "is NOT a BinEntry");
+                       <<  "is NOT a DataEntry");
       return;
    }
-   LoadEntryBinArea(binElement);
+   LoadEntryBinArea(dataEntry);
 }
 
 /**
  * \brief Loads (from disk) the element content 
  *        when a string is not suitable
- * @param elem  Entry whose binArea is going to be loaded
+ * @param entry  Entry whose binArea is going to be loaded
  */
-void Document::LoadEntryBinArea(BinEntry *elem
+void Document::LoadEntryBinArea(DataEntry *entry
 {
-   if (elem->GetBinArea() )
+   if( entry->GetBinArea() )
       return;
 
    bool openFile = !Fp;
    if ( openFile )
       OpenFile();
 
-   size_t o =(size_t)elem->GetOffset();
+   size_t o =(size_t)entry->GetOffset();
    Fp->seekg(o, std::ios::beg);
 
-   size_t l = elem->GetLength();
-   uint8_t *a = new uint8_t[l];
-   if ( !a )
+   size_t l = entry->GetLength();
+   uint8_t *data = new uint8_t[l];
+   if ( !data )
    {
-      gdcmWarningMacro(  "Cannot allocate BinEntry content for : "
-                       << std::hex << elem->GetGroup() 
-                       << "|" << elem->GetElement() );
+      gdcmWarningMacro(  "Cannot allocate DataEntry content for : "
+                       << std::hex << entry->GetGroup() 
+                       << "|" << entry->GetElement() );
       return;
    }
 
-   Fp->read((char*)a, l);
+   // Read the data
+   Fp->read((char*)data, l);
    if ( Fp->fail() || Fp->eof() )
    {
-      delete[] a;
+      delete[] data;
+      entry->SetState(DataEntry::STATE_UNREAD);
       return;
    }
 
-   elem->SetBinArea(a);
+   // Swap the data content if necessary
+   uint32_t i;
+   unsigned short vrLgth = 
+                        Global::GetVR()->GetAtomicElementLength(entry->GetVR());
+   if( entry->GetVR() == "OW" )
+      vrLgth = 1;
+
+   switch(vrLgth)
+   {
+      case 2:
+      {
+         uint16_t *data16 = (uint16_t *)data;
+         for(i=0;i<l/vrLgth;i++)
+            data16[i] = SwapShort(data16[i]);
+         break;
+      }
+      case 4:
+      {
+         uint32_t *data32 = (uint32_t *)data;
+         for(i=0;i<l/vrLgth;i++)
+            data32[i] = SwapLong(data32[i]);
+         break;
+      }
+      case 8:
+      {
+         gdcmWarningMacro("Can't swap 64 bits data");
+/*         uint64_t *data64 = (uint64_t *)data;
+         for(i=0;i<l/vrLgth;i++)
+            data64[i] = SwapLongLong(data64[i]);*/
+         break;
+      }
+   }
+   
+   entry->SetBinArea(data);
 
    if ( openFile )
       CloseFile();
@@ -776,8 +758,8 @@ void Document::LoadDocEntrySafe(DocEntry *entry)
 bool Document::operator<(Document &document)
 {
    // Patient Name
-   std::string s1 = GetEntryValue(0x0010,0x0010);
-   std::string s2 = document.GetEntryValue(0x0010,0x0010);
+   std::string s1 = GetEntryString(0x0010,0x0010);
+   std::string s2 = document.GetEntryString(0x0010,0x0010);
    if (s1 < s2)
    {
       return true;
@@ -789,8 +771,8 @@ bool Document::operator<(Document &document)
    else
    {
       // Patient ID
-      s1 = GetEntryValue(0x0010,0x0020);
-      s2 = document.GetEntryValue(0x0010,0x0020);
+      s1 = GetEntryString(0x0010,0x0020);
+      s2 = document.GetEntryString(0x0010,0x0020);
       if ( s1 < s2 )
       {
          return true;
@@ -802,8 +784,8 @@ bool Document::operator<(Document &document)
       else
       {
          // Study Instance UID
-         s1 = GetEntryValue(0x0020,0x000d);
-         s2 = document.GetEntryValue(0x0020,0x000d);
+         s1 = GetEntryString(0x0020,0x000d);
+         s2 = document.GetEntryString(0x0020,0x000d);
          if ( s1 < s2 )
          {
             return true;
@@ -815,8 +797,8 @@ bool Document::operator<(Document &document)
          else
          {
             // Serie Instance UID
-            s1 = GetEntryValue(0x0020,0x000e);
-            s2 = document.GetEntryValue(0x0020,0x000e);    
+            s1 = GetEntryString(0x0020,0x000e);
+            s2 = document.GetEntryString(0x0020,0x000e);    
             if ( s1 < s2 )
             {
                return true;
@@ -891,10 +873,10 @@ void Document::SkipBytes(uint32_t nBytes)
 /**
  * \brief   Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
  */
-int Document::ComputeGroup0002Length( /*FileType filetype*/ 
+int Document::ComputeGroup0002Length( ) 
 {
    uint16_t gr;
-   std::string vr;
+   VRKey vr;
    
    int groupLength = 0;
    bool found0002 = false;   
@@ -917,11 +899,11 @@ int Document::ComputeGroup0002Length( /*FileType filetype*/ )
  
             //if ( filetype == ExplicitVR )
             //{
-            //   if ( (vr == "OB") || (vr == "OW") || (vr == "UT") || (vr == "SQ") )
+            //if ( (vr == "OB")||(vr == "OW")||(vr == "UT")||(vr == "SQ"))
             // (no SQ, OW, UT in group 0x0002;)
                if ( vr == "OB" ) 
                {
-                  // explicit VR AND OB, OW, SQ, UT : 4 more bytes
+                  // explicit VR AND (OB, OW, SQ, UT) : 4 more bytes
                   groupLength +=  4;
                }
             //}
@@ -960,14 +942,15 @@ void Document::ParseDES(DocEntrySet *set, long offset,
                         long l_max, bool delim_mode)
 {
    DocEntry *newDocEntry;
-   ValEntry *newValEntry;
-   BinEntry *newBinEntry;
+   DataEntry *newDataEntry;
    SeqEntry *newSeqEntry;
    VRKey vr;
    bool used; // will be set to false when something wrong happens to an Entry.
               // (Entry will then be deleted)
    bool delim_mode_intern = delim_mode;
-   bool first = true;  
+   bool first = true;
+   gdcmWarningMacro( "Enter in ParseDES, delim-mode " <<  delim_mode
+                     << " at offset " << std::hex << offset ); 
    while (true)
    {
       if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
@@ -977,6 +960,13 @@ void Document::ParseDES(DocEntrySet *set, long offset,
 
       newDocEntry = ReadNextDocEntry( );
 
+      // FIXME :
+      // Private tag, in IMplicit VR are defaulted as a DataEntry,
+      // Very often they are only composed of Printable characters, 
+      // and could be defaulted as a DataEntry.
+      // It's too late to do the Job
+      // (we should check the value, but we know it after LoadDocEntry ...)
+
       // Uncoment this printf line to be able to 'follow' the DocEntries
       // when something *very* strange happens
 
@@ -989,7 +979,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          break;
       }
 
-       // an Item Starter found elsewhere but the first postition
+       // an Item Starter found elsewhere but the first position
        // of a SeqEntry  means previous entry was a Sequence
        // but we didn't get it (private Sequence + Implicit VR)
        // we have to backtrack.
@@ -1003,124 +993,73 @@ void Document::ParseDES(DocEntrySet *set, long offset,
       }
  
       used = true;
-      newValEntry = dynamic_cast<ValEntry*>(newDocEntry);
-      newBinEntry = dynamic_cast<BinEntry*>(newDocEntry);
+      newDataEntry = dynamic_cast<DataEntry*>(newDocEntry);
 
-      if ( newValEntry || newBinEntry )  
+      if ( newDataEntry )  
       {
-       //////////////////////////// ContentEntry
-         if ( newBinEntry )
-         {
-            vr = newDocEntry->GetVR();
-            if ( Filetype == ExplicitVR && 
-                 !Global::GetVR()->IsVROfBinaryRepresentable(vr) )
-            { 
-                ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR
-                gdcmWarningMacro( std::hex << newDocEntry->GetGroup() 
-                                  << "|" << newDocEntry->GetElement()
-                                  << " : Neither Valentry, nor BinEntry." 
-                                  "Probably unknown VR.");
-            }
-
-         //////////////////// BinEntry or UNKOWN VR:
-
-            // When "this" is a Document the Key is simply of the
-            // form ( group, elem )...
-            //if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
-            //{
-            //   newBinEntry->SetKey( newBinEntry->GetKey() );
-            //}
-            // but when "this" is a SQItem, we are inserting this new
-            // valEntry in a sequence item, and the key has the
-            // generalized form (refer to \ref BaseTagKey):
+         //////////////////////////// DataEntry
+         vr = newDocEntry->GetVR();
+         // Useless checking, now !
+         /*
+         if ( Filetype == ExplicitVR && 
+               !Global::GetVR()->IsVROfBinaryRepresentable(vr) )
+         { 
+               ////// No DataEntry: should mean UNKOWN VR
+               gdcmWarningMacro( std::hex << newDocEntry->GetGroup() 
+                                 << "|" << newDocEntry->GetElement()
+                                 << " : unknown VR." 
+                                 " Probably 'Implicit VR' entry within "
+                                 "an explicit VR 'document'.");
+         }
+         */
 
-            // time waste hunting
-            //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
-            //{
-            //   newBinEntry->SetKey(  parentSQItem->GetBaseTagKey()
-            //                       + newBinEntry->GetKey() );
-            //}
-           
-            if ( !set->AddEntry( newBinEntry ) )
-            {
-               gdcmWarningMacro( "in ParseDES : cannot add a BinEntry "
-                                   << newBinEntry->GetKey()  
-                                   << " (at offset : " 
-                                   << newBinEntry->GetOffset() << " )" );
-               used=false;
-            }
-            else
-            {
-               // Load only if we can add (not a duplicate key)
-               LoadDocEntry( newBinEntry );
-            }
-         }  // end BinEntry
+         if ( !set->AddEntry( newDataEntry ) )
+         {
+            gdcmWarningMacro( "in ParseDES : cannot add a DataEntry "
+                                 << newDataEntry->GetKey()  
+                                 << " (at offset : " 
+                                 << newDataEntry->GetOffset() << " )" );
+            used=false;
+         }
          else
          {
-         /////////////////////// ValEntry
-
-            // When "set" is a Document, then we are at the top of the
-            // hierarchy and the Key is simply of the form ( group, elem )...
-            //if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
-            //{
-            //   newValEntry->SetKey( newValEntry->GetKey() );
-            //}
-            // ...but when "set" is a SQItem, we are inserting this new
-            // valEntry in a sequence item. Hence the key has the
-            // generalized form (refer to \ref BaseTagKey):
-
-            // time waste hunting
-            //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
-            //{
-            //   newValEntry->SetKey(  parentSQItem->GetBaseTagKey()
-            //                      + newValEntry->GetKey() );
-            //}
-
-            if ( !set->AddEntry( newValEntry ) )
-            {
-              gdcmWarningMacro( "in ParseDES : cannot add a ValEntry "
-                                  << newValEntry->GetKey()
-                                  << " (at offset : " 
-                                  << newValEntry->GetOffset() << " )" );   
-              used=false;
-            }
-            else
-            {
-               // Load only if we can add (not a duplicate key)
-               LoadDocEntry( newValEntry );
-            }
+            newDataEntry->Delete();
+            // Load only if we can add (not a duplicate key)
+            LoadDocEntry( newDataEntry );
+         }
 
-            if ( newValEntry->GetElement() == 0x0000 ) // if on group length
+         if ( newDataEntry->GetElement() == 0x0000 ) // if on group length
+         {
+            if ( newDataEntry->GetGroup()%2 != 0 )   // if Shadow Group
             {
-               if ( newValEntry->GetGroup()%2 != 0 )   // if Shadow Group
+               if ( LoadMode & LD_NOSHADOW ) // if user asked to skip shad.gr
                {
-                  if ( LoadMode & LD_NOSHADOW ) // if user asked to skip shad.gr
+                  std::string strLgrGroup = newDataEntry->GetString();
+                  int lgrGroup;
+                  if ( newDataEntry->IsUnfound() )
                   {
-                     std::string strLgrGroup = newValEntry->GetValue();
-                     int lgrGroup;
-                     if ( strLgrGroup != GDCM_UNFOUND)
-                     {
-                        lgrGroup = atoi(strLgrGroup.c_str());
-                        Fp->seekg(lgrGroup, std::ios::cur);
-                        used = false;
-                        RemoveEntry( newDocEntry );
-                        // bcc 5.5 is right "assigned a value that's never used"
-                        // newDocEntry = 0;
-                        continue;
-                     }
+                     lgrGroup = atoi(strLgrGroup.c_str());
+                     Fp->seekg(lgrGroup, std::ios::cur);
+                     //used = false;  // never used
+                     RemoveEntry( newDocEntry );  // Remove and delete
+                     // bcc 5.5 is right "assigned a value that's never used"
+                     // newDocEntry = 0;
+                     continue;
                   }
                }
             }
+         }
 
-            bool delimitor = newValEntry->IsItemDelimitor();
+         bool delimitor = newDataEntry->IsItemDelimitor();
 
-            if ( (delimitor) || 
-                (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) )
-            {
-               if ( !used )
-                  delete newDocEntry;
-               break;
-            }
+         if ( (delimitor) || 
+               (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) )
+         {
+            if ( !used )
+               newDocEntry->Delete();
+            break;
          }
 
          // Just to make sure we are at the beginning of next entry.
@@ -1149,7 +1088,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
             if ( newDocEntry->GetGroup()%2 != 0 )
             {
                 Fp->seekg( l, std::ios::cur);
-                used = false;
+                newDocEntry->Delete();  // Delete, not in the set 
                 continue;  
             } 
          } 
@@ -1157,7 +1096,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          {
            // User asked to skip *any* SeQuence
             Fp->seekg( l, std::ios::cur);
-            used = false;
+            newDocEntry->Delete(); // Delete, not in the set
             continue;
          }
          // delay the dynamic cast as late as possible
@@ -1170,11 +1109,9 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          // is a Document, then we are building the first depth level.
          // Hence the SeqEntry we are building simply has a depth
          // level of one:
-//         SQItem *parentSQItem = dynamic_cast< SQItem* > ( set );
         if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
          {
             newSeqEntry->SetDepthLevel( 1 );
-         //   newSeqEntry->SetKey( newSeqEntry->GetKey() );
          }
          // But when "set" is already a SQItem, we are building a nested
          // sequence, and hence the depth level of the new SeqEntry
@@ -1184,16 +1121,21 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          else if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
          {
             newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
-
-          //  newSeqEntry->SetKey(  parentSQItem->GetBaseTagKey()
-          //                      + newSeqEntry->GetKey() );
          }
 
          if ( l != 0 )
          {  // Don't try to parse zero-length sequences
+
+            gdcmWarningMacro( "Entry in ParseSQ, delim " << delim_mode_intern
+                               << " at offset " << std::hex
+                               << newDocEntry->GetOffset() );
+
             ParseSQ( newSeqEntry, 
                      newDocEntry->GetOffset(),
                      l, delim_mode_intern);
+
+            gdcmWarningMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
          }
          if ( !set->AddEntry( newSeqEntry ) )
          {
@@ -1203,21 +1145,26 @@ void Document::ParseDES(DocEntrySet *set, long offset,
                                 << newSeqEntry->GetOffset() << " )" ); 
             used = false;
          }
+         else
+         {
+            newDocEntry->Delete();
+         }
  
-        if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+         if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
          {
             if ( !used )
-               delete newDocEntry;  
-               break;
+               newDocEntry->Delete();
+            break;
          }
       }  // end SeqEntry : VR = "SQ"
 
       if ( !used )
       {
-         delete newDocEntry;
+         newDocEntry->Delete();
       }
       first = false;
    }                               // end While
+   gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode );
 }
 
 /**
@@ -1247,24 +1194,17 @@ void Document::ParseSQ( SeqEntry *seqEntry,
          if ( newDocEntry->IsSequenceDelimitor() )
          {
             seqEntry->SetDelimitationItem( newDocEntry ); 
+            newDocEntry->Delete();
             break;
          }
       }
       if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
       {
-         delete newDocEntry;
+         newDocEntry->Delete();
          break;
       }
       // create the current SQItem
       SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() );
-/*
-      std::ostringstream newBase;
-      newBase << seqEntry->GetKey()
-              << "/"
-              << SQItemNumber
-              << "#";
-      itemSQ->SetBaseTagKey( newBase.str() );
-*/
       unsigned int l = newDocEntry->GetReadLength();
       
       if ( l == 0xffffffff )
@@ -1278,7 +1218,6 @@ void Document::ParseSQ( SeqEntry *seqEntry,
 
       // Let's try :------------
       // remove fff0,e000, created out of the SQItem
-      delete newDocEntry;
       Fp->seekg(offsetStartCurrentSQItem, std::ios::beg);
       // fill up the current SQItem, starting at the beginning of fff0,e000
 
@@ -1288,6 +1227,7 @@ void Document::ParseSQ( SeqEntry *seqEntry,
       // end try -----------------
  
       seqEntry->AddSQItem( itemSQ, SQItemNumber ); 
+      newDocEntry->Delete();
       SQItemNumber++;
       if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max )
       {
@@ -1306,7 +1246,7 @@ DocEntry *Document::Backtrack(DocEntry *docEntry)
 {
    // delete the Item Starter, built erroneously out of any Sequence
    // it's not yet in the HTable/chained list
-   delete docEntry;
+   docEntry->Delete();
 
    // Get all info we can from PreviousDocEntry
    uint16_t group = PreviousDocEntry->GetGroup();
@@ -1328,18 +1268,20 @@ DocEntry *Document::Backtrack(DocEntry *docEntry)
    Fp->seekg( 0, std::ios::beg);
    Fp->seekg(offset, std::ios::cur);
 
-return newEntry;
+   return newEntry;
 }
 
 /**
  * \brief   Loads (or not) the element content depending if its length exceeds
  *          or not the value specified with Document::SetMaxSizeLoadEntry()
  * @param   entry Header Entry (Dicom Element) to be dealt with
+ * @param forceLoad whether you want to force loading of 'long' elements
  */
 void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
 {
    uint16_t group  = entry->GetGroup();
-   std::string  vr = entry->GetVR();
+   uint16_t elem  = entry->GetElement();
+   const VRKey  &vr = entry->GetVR();
    uint32_t length = entry->GetLength();
 
    Fp->seekg((long)entry->GetOffset(), std::ios::beg);
@@ -1348,16 +1290,26 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
    //          (fffe e000) tells us an Element is beginning
    //          (fffe e00d) tells us an Element just ended
    //          (fffe e0dd) tells us the current SeQuence just ended
-   if ( group == 0xfffe )
+   //
+   //          (fffe 0000) is an 'impossible' tag value, 
+   //                                    found in MR-PHILIPS-16-Multi-Seq.dcm
+   
+   if ( (group == 0xfffe && elem != 0x0000 ) || vr == "SQ" )
    {
       // NO more value field for SQ !
       return;
    }
 
+   DataEntry *dataEntryPtr = dynamic_cast< DataEntry* >(entry);
+   if( !dataEntryPtr )
+   {
+      return;
+   }
+
    // When the length is zero things are easy:
    if ( length == 0 )
    {
-      ((ValEntry *)entry)->SetValue("");
+      dataEntryPtr->SetBinArea(NULL,true);
       return;
    }
 
@@ -1371,30 +1323,8 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
    {
       if (length > MaxSizeLoadEntry)
       {
-         if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
-         {  
-            s << GDCM_NOTLOADED;
-            s << " Ad.:" << (long)entry->GetOffset();
-            s << " x(" << std::hex << entry->GetOffset() << ")";
-            s << std::dec;
-            s << " Lgt:"  << entry->GetLength();
-            s << " x(" << std::hex << entry->GetLength() << ")";
-            binEntryPtr->SetValue(s.str());
-         }
-         else if (ValEntry *valEntryPtr = dynamic_cast< ValEntry* >(entry) )
-         {
-            s << GDCM_NOTLOADED;  
-            s << " Address:" << (long)entry->GetOffset();
-            s << " Length:"  << entry->GetLength();
-            s << " x(" << std::hex << entry->GetLength() << ")";
-            valEntryPtr->SetValue(s.str());
-         }
-         else
-         {
-            // fusible
-            gdcmErrorMacro( "MaxSizeLoadEntry exceeded, neither a BinEntry "
-                         << "nor a ValEntry ?! Should never print that !" );
-         }
+         dataEntryPtr->SetBinArea(NULL,true);
+         dataEntryPtr->SetState(DataEntry::STATE_NOTLOADED);
 
          // to be sure we are at the end of the value ...
          Fp->seekg((long)entry->GetOffset()+(long)entry->GetLength(),
@@ -1403,113 +1333,7 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
       }
    }
 
-   // When we find a BinEntry not very much can be done :
-   if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
-   {
-      s << GDCM_BINLOADED;
-      binEntryPtr->SetValue(s.str());
-      LoadEntryBinArea(binEntryPtr); // last one, not to erase length !
-      return;
-   }
-
-   if ( IsDocEntryAnInteger(entry) )
-   {   
-      uint32_t NewInt;
-      int nbInt;
-      // When short integer(s) are expected, read and convert the following 
-      // (n * 2) characters properly i.e. consider them as short integers as
-      // opposed to strings.
-      // Elements with Value Multiplicity > 1
-      // contain a set of integers (not a single one)       
-      if (vr == "US" || vr == "SS")
-      {
-         nbInt = length / 2;
-         NewInt = ReadInt16();
-         s << NewInt;
-         if (nbInt > 1)
-         {
-            for (int i=1; i < nbInt; i++)
-            {
-               s << '\\';
-               NewInt = ReadInt16();
-               s << NewInt;
-            }
-         }
-      }
-      // See above comment on multiple integers (mutatis mutandis).
-      else if (vr == "UL" || vr == "SL")
-      {
-         nbInt = length / 4;
-         NewInt = ReadInt32();
-         s << NewInt;
-         if (nbInt > 1)
-         {
-            for (int i=1; i < nbInt; i++)
-            {
-               s << '\\';
-               NewInt = ReadInt32();
-               s << NewInt;
-            }
-         }
-      }
-#ifdef GDCM_NO_ANSI_STRING_STREAM
-      s << std::ends; // to avoid oddities on Solaris
-#endif //GDCM_NO_ANSI_STRING_STREAM
-
-      ((ValEntry *)entry)->SetValue(s.str());
-      return;
-   }
-   
-  // FIXME: We need an additional byte for storing \0 that is not on disk
-   char *str = new char[length+1];
-   Fp->read(str, (size_t)length);
-   str[length] = '\0'; //this is only useful when length is odd
-   // Special DicomString call to properly handle \0 and even length
-   std::string newValue;
-   if ( length % 2 )
-   {
-      newValue = Util::DicomString(str, length+1);
-      gdcmWarningMacro("Warning: bad length: " << length <<
-                       " For string :" <<  newValue.c_str()); 
-      // Since we change the length of string update it length
-      //entry->SetReadLength(length+1);
-   }
-   else
-   {
-      newValue = Util::DicomString(str, length);
-   }
-   delete[] str;
-
-   if ( ValEntry *valEntry = dynamic_cast<ValEntry* >(entry) )
-   {
-      if ( Fp->fail() || Fp->eof())
-      {
-         if ( Fp->fail() )
-            gdcmWarningMacro("--> fail");
-
-         gdcmWarningMacro("Unread element value " << valEntry->GetKey() 
-                          << " lgt : " << valEntry->GetReadLength() 
-                          << " at " << std::hex << valEntry->GetOffset());
-         valEntry->SetValue(GDCM_UNREAD);
-         return;
-      }
-
-      if ( vr == "UI" )
-      {
-         // Because of correspondance with the VR dic
-         valEntry->SetValue(newValue);
-      }
-      else
-      {
-         valEntry->SetValue(newValue);
-      }
-   }
-   else
-   {
-      gdcmWarningMacro("Should have a ValEntry, here ! " << valEntry->GetKey() 
-                          << " lgt : " << valEntry->GetReadLength() 
-                          << " at " << std::hex << valEntry->GetOffset());
-   }
+   LoadEntryBinArea(dataEntryPtr); // last one, not to erase length !
 }
 
 /**
@@ -1519,13 +1343,13 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
 void Document::FindDocEntryLength( DocEntry *entry )
    throw ( FormatError )
 {
-   std::string  vr  = entry->GetVR();
+   const VRKey &vr  = entry->GetVR();
    uint16_t length16;       
    
    if ( Filetype == ExplicitVR && !entry->IsImplicitVR() ) 
    {
       if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UT" 
-                                                           /*|| vr == "UN"*/ )
+                                                           || vr == "UN" )
       {
          // The following reserved two bytes (see PS 3.5-2003, section
          // "7.1.2 Data element structure with explicit vr", p 27) must be
@@ -1660,10 +1484,10 @@ uint32_t Document::FindDocEntryLengthOBOrOW()
  * \brief     Find the Value Representation of the current Dicom Element.
  * @return    Value Representation of the current Entry
  */
-std::string Document::FindDocEntryVR()
+VRKey Document::FindDocEntryVR()
 {
    if ( Filetype != ExplicitVR )
-      return GDCM_UNKNOWN;
+      return GDCM_VRUNKNOWN;
 
    long positionOnEntry = Fp->tellg();
    // Warning: we believe this is explicit VR (Value Representation) because
@@ -1674,14 +1498,15 @@ std::string Document::FindDocEntryVR()
    // is in explicit VR and try to fix things if it happens not to be
    // the case.
 
-   char vr[3];
-   Fp->read (vr, (size_t)2);
-   vr[2] = 0;
+   VRKey vr;
+   Fp->read(&(vr[0]),(size_t)2);
 
+   gdcmDebugMacro( "--> VR: " << vr )
    if ( !CheckDocEntryVR(vr) )
    {
+      gdcmWarningMacro( "Unknown VR '" << vr << "'" )
       Fp->seekg(positionOnEntry, std::ios::beg);
-      return GDCM_UNKNOWN;
+      return GDCM_VRUNKNOWN;
    }
    return vr;
 }
@@ -1694,142 +1519,9 @@ std::string Document::FindDocEntryVR()
  * @return    false if the VR is incorrect or if the VR isn't referenced
  *            otherwise, it returns true
 */
-bool Document::CheckDocEntryVR(VRKey vr)
+bool Document::CheckDocEntryVR(const VRKey &vr)
 {
-   if ( !Global::GetVR()->IsValidVR(vr) )
-      return false;
-
-   return true; 
-}
-
-/**
- * \brief   Get the transformed value of the header entry. The VR value 
- *          is used to define the transformation to operate on the value
- * \warning NOT end user intended method !
- * @param   entry entry to tranform
- * @return  Transformed entry value
- */
-std::string Document::GetDocEntryValue(DocEntry *entry)
-{
-   if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
-   {
-      std::string val = ((ValEntry *)entry)->GetValue();
-      std::string vr  = entry->GetVR();
-      uint32_t length = entry->GetLength();
-      std::ostringstream s;
-      int nbInt;
-
-      // When short integer(s) are expected, read and convert the following 
-      // n * 2 bytes properly i.e. as a multivaluated strings
-      // (each single value is separated fromthe next one by '\'
-      // as usual for standard multivaluated filels
-      // Elements with Value Multiplicity > 1
-      // contain a set of short integers (not a single one) 
-   
-      if ( vr == "US" || vr == "SS" )
-      {
-         uint16_t newInt16;
-
-         nbInt = length / 2;
-         for (int i=0; i < nbInt; i++) 
-         {
-            if ( i != 0 )
-            {
-               s << '\\';
-            }
-            newInt16 = ( val[2*i+0] & 0xFF ) + ( ( val[2*i+1] & 0xFF ) << 8);
-            newInt16 = SwapShort( newInt16 );
-            s << newInt16;
-         }
-      }
-
-      // When integer(s) are expected, read and convert the following 
-      // n * 4 bytes properly i.e. as a multivaluated strings
-      // (each single value is separated fromthe next one by '\'
-      // as usual for standard multivaluated filels
-      // Elements with Value Multiplicity > 1
-      // contain a set of integers (not a single one) 
-      else if ( vr == "UL" || vr == "SL" )
-      {
-         uint32_t newInt32;
-
-         nbInt = length / 4;
-         for (int i=0; i < nbInt; i++) 
-         {
-            if ( i != 0)
-            {
-               s << '\\';
-            }
-            newInt32 = ( val[4*i+0] & 0xFF )
-                    + (( val[4*i+1] & 0xFF ) <<  8 )
-                    + (( val[4*i+2] & 0xFF ) << 16 )
-                    + (( val[4*i+3] & 0xFF ) << 24 );
-            newInt32 = SwapLong( newInt32 );
-            s << newInt32;
-         }
-      }
-#ifdef GDCM_NO_ANSI_STRING_STREAM
-      s << std::ends; // to avoid oddities on Solaris
-#endif //GDCM_NO_ANSI_STRING_STREAM
-      return s.str();
-   }
-   return ((ValEntry *)entry)->GetValue();
-}
-
-/**
- * \brief   Get the reverse transformed value of the header entry. The VR 
- *          value is used to define the reverse transformation to operate on
- *          the value
- * \warning NOT end user intended method !
- * @param   entry Entry to reverse transform
- * @return  Reverse transformed entry value
- */
-std::string Document::GetDocEntryUnvalue(DocEntry *entry)
-{
-   if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
-   {
-      std::string vr = entry->GetVR();
-      std::vector<std::string> tokens;
-      std::ostringstream s;
-
-      if ( vr == "US" || vr == "SS" ) 
-      {
-         uint16_t newInt16;
-
-         tokens.erase( tokens.begin(), tokens.end()); // clean any previous value
-         Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
-         for (unsigned int i=0; i<tokens.size(); i++) 
-         {
-            newInt16 = atoi(tokens[i].c_str());
-            s << (  newInt16        & 0xFF ) 
-              << (( newInt16 >> 8 ) & 0xFF );
-         }
-         tokens.clear();
-      }
-      if ( vr == "UL" || vr == "SL")
-      {
-         uint32_t newInt32;
-
-         tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
-         Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
-         for (unsigned int i=0; i<tokens.size();i++) 
-         {
-            newInt32 = atoi(tokens[i].c_str());
-            s << (char)(  newInt32         & 0xFF ) 
-              << (char)(( newInt32 >>  8 ) & 0xFF )
-              << (char)(( newInt32 >> 16 ) & 0xFF )
-              << (char)(( newInt32 >> 24 ) & 0xFF );
-         }
-         tokens.clear();
-      }
-
-#ifdef GDCM_NO_ANSI_STRING_STREAM
-      s << std::ends; // to avoid oddities on Solaris
-#endif //GDCM_NO_ANSI_STRING_STREAM
-      return s.str();
-   }
-
-   return ((ValEntry *)entry)->GetValue();
+   return Global::GetVR()->IsValidVR(vr);
 }
 
 /**
@@ -1870,7 +1562,7 @@ void Document::SkipToNextDocEntry(DocEntry *currentDocEntry)
 void Document::FixDocEntryFoundLength(DocEntry *entry,
                                       uint32_t foundLength)
 {
-   entry->SetReadLength( foundLength ); // will be updated only if a bug is found        
+   entry->SetReadLength( foundLength );// will be updated only if a bug is found
    if ( foundLength == 0xffffffff)
    {
       foundLength = 0;
@@ -1881,7 +1573,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
      
    if ( foundLength % 2)
    {
-      gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength 
+      gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength
         <<  " in x(" << std::hex << gr << "," << elem <<")");
    }
       
@@ -1908,7 +1600,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
    else if ( gr   == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
    {
       foundLength = 4;
-      entry->SetReadLength(4); // a bug is to be fixed !?
+      entry->SetReadLength(4); // a bug is to be fixed !
    } 
  
    else if ( entry->GetVR() == "SQ" )
@@ -1928,7 +1620,11 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
      {
         foundLength = 0;
      }
-   }            
+     else
+     {
+        foundLength=12; // to skip the mess that follows this bugged Tag !
+     }
+   }                
    entry->SetLength(foundLength);
 }
 
@@ -1942,7 +1638,7 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry)
 {
    uint16_t elem         = entry->GetElement();
    uint16_t group        = entry->GetGroup();
-   const std::string &vr = entry->GetVR();
+   const VRKey &vr = entry->GetVR();
    uint32_t length       = entry->GetLength();
 
    // When we have some semantics on the element we just read, and if we
@@ -1956,9 +1652,9 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry)
       }
       else 
       {
-         // Allthough this should never happen, still some images have a
+         // Although this should never happen, still some images have a
          // corrupted group length [e.g. have a glance at offset x(8336) of
-         // gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm].
+         // gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm.
          // Since for dicom compliant and well behaved headers, the present
          // test is useless (and might even look a bit paranoid), when we
          // encounter such an ill-formed image, we simply display a warning
@@ -2004,7 +1700,7 @@ bool Document::CheckSwap()
    char *entCur = deb + 128;
    if ( memcmp(entCur, "DICM", (size_t)4) == 0 )
    {
-      gdcmWarningMacro( "Looks like DICOM Version3 (preamble + DCM)" );
+      gdcmDebugMacro( "Looks like DICOM Version3 (preamble + DCM)" );
       
       // Group 0002 should always be VR, and the first element 0000
       // Let's be carefull (so many wrong headers ...)
@@ -2036,24 +1732,24 @@ bool Document::CheckSwap()
       // instead of just checking for UL, OB and UI !? group 0000 
       {
          Filetype = ExplicitVR;
-         gdcmWarningMacro( "Group 0002 : Explicit Value Representation");
+         gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
       } 
       else 
       {
          Filetype = ImplicitVR;
-         gdcmWarningMacro( "Group 0002 :Not an explicit Value Representation;"
+         gdcmErrorMacro( "Group 0002 :Not an explicit Value Representation;"
                         << "Looks like a bugged Header!");
       }
       
       if ( net2host )
       {
          SwapCode = 4321;
-         gdcmWarningMacro( "HostByteOrder != NetworkByteOrder");
+         gdcmDebugMacro( "HostByteOrder != NetworkByteOrder");
       }
       else 
       {
          SwapCode = 1234;
-         gdcmWarningMacro( "HostByteOrder = NetworkByteOrder");
+         gdcmDebugMacro( "HostByteOrder = NetworkByteOrder");
       }
       
       // Position the file position indicator at first tag 
@@ -2100,7 +1796,7 @@ bool Document::CheckSwap()
            memcmp(entCur, "OB", (size_t)2) == 0 )
          {
             Filetype = ExplicitVR;
-            gdcmWarningMacro( "Group 0002 : Explicit Value Representation");
+            gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
             return true;
           }
     }
@@ -2146,7 +1842,7 @@ bool Document::CheckSwap()
          //  Only 0 or 4321 will be possible 
          //  (no oportunity to check for the formerly well known
          //  ACR-NEMA 'Bad Big Endian' or 'Bad Little Endian' 
-         //  if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc -3, 4, ..., 8-) 
+         //  if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc-3, 4, ..., 8-)
          //  the file IS NOT ACR-NEMA nor DICOM V3
          //  Find a trick to tell it the caller...
       
@@ -2177,7 +1873,7 @@ bool Document::CheckSwap()
                Filetype = ACR;
                return true;
             default :
-               gdcmWarningMacro("ACR/NEMA unfound swap info (Really hopeless !)");
+               gdcmWarningMacro("ACR/NEMA unfound swap info (Hopeless !)");
                Filetype = Unknown;
                return false;
          }
@@ -2189,8 +1885,8 @@ bool Document::CheckSwap()
  */
 void Document::SwitchByteSwapCode() 
 {
-   gdcmWarningMacro( "Switching Byte Swap code from "<< SwapCode
-                     << " at :" <<std::hex << Fp->tellg() );
+   gdcmDebugMacro( "Switching Byte Swap code from "<< SwapCode
+                     << " at: 0x" << std::hex << Fp->tellg() );
    if ( SwapCode == 1234 ) 
    {
       SwapCode = 4321;
@@ -2207,6 +1903,7 @@ void Document::SwitchByteSwapCode()
    {
       SwapCode = 3412;
    }
+   gdcmDebugMacro( " Into: "<< SwapCode );
 }
 
 /**
@@ -2258,10 +1955,11 @@ DocEntry *Document::ReadNextDocEntry()
    if ( HasDCMPreamble )
       HandleOutOfGroup0002(group, elem);
  
-   std::string vr = FindDocEntryVR();
-   std::string realVR = vr;
+   VRKey vr = FindDocEntryVR();
+   
+   VRKey realVR = vr;
 
-   if ( vr == GDCM_UNKNOWN )
+   if ( vr == GDCM_VRUNKNOWN )
    {
       if ( elem == 0x0000 ) // Group Length
       {
@@ -2269,9 +1967,9 @@ DocEntry *Document::ReadNextDocEntry()
       }
       else if (group%2 == 1 &&  (elem >= 0x0010 && elem <=0x00ff ))
       {  
-      //DICOM PS 3-5 7.8.1 a) states that those 
-      //(gggg-0010->00FF where gggg is odd) attributes have to be LO
-         realVR= "LO";
+      // DICOM PS 3-5 7.8.1 a) states that those 
+      // (gggg-0010->00FF where gggg is odd) attributes have to be LO
+         realVR = "LO";
       }
       else
       {
@@ -2279,19 +1977,22 @@ DocEntry *Document::ReadNextDocEntry()
          if ( dictEntry )
          {
             realVR = dictEntry->GetVR();
+            dictEntry->Unregister();
          }
       }
    }
+   gdcmDebugMacro( "Found VR: " << vr << " / Real VR: " << realVR );
 
    DocEntry *newEntry;
    if ( Global::GetVR()->IsVROfSequence(realVR) )
       newEntry = NewSeqEntry(group, elem);
-   else if ( Global::GetVR()->IsVROfStringRepresentable(realVR) )
-      newEntry = NewValEntry(group, elem, vr);
-   else
-      newEntry = NewBinEntry(group, elem, vr);
+   else 
+   {
+      newEntry = NewDataEntry(group, elem, realVR);
+      static_cast<DataEntry *>(newEntry)->SetState(DataEntry::STATE_NOTLOADED);
+   }
 
-   if ( vr == GDCM_UNKNOWN )
+   if ( vr == GDCM_VRUNKNOWN )
    {
       if ( Filetype == ExplicitVR )
       {
@@ -2301,8 +2002,9 @@ DocEntry *Document::ReadNextDocEntry()
          { 
             std::string msg;
             int offset = Fp->tellg();
-            msg = Util::Format("Entry (%04x,%04x) at 0x(%x) should be Explicit VR\n", 
-                          newEntry->GetGroup(), newEntry->GetElement(), offset );
+            msg = Util::Format(
+                        "Entry (%04x,%04x) at x(%x) should be Explicit VR\n", 
+                        newEntry->GetGroup(), newEntry->GetElement(), offset );
             gdcmWarningMacro( msg.c_str() );
           }
       }
@@ -2316,7 +2018,7 @@ DocEntry *Document::ReadNextDocEntry()
    catch ( FormatError )
    {
       // Call it quits
-      delete newEntry;
+      newEntry->Delete();
       return 0;
    }
 
@@ -2333,7 +2035,8 @@ DocEntry *Document::ReadNextDocEntry()
  */
 void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
 {
-   // Endian reversion. Some files contain groups of tags with reversed endianess.
+   // Endian reversion. 
+   // Some files contain groups of tags with reversed endianess.
    static int reversedEndian = 0;
    // try to fix endian switching in the middle of headers
    if ((group == 0xfeff) && (elem == 0x00e0))
@@ -2351,6 +2054,22 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
      reversedEndian--;
      SwitchByteSwapCode();
    }
+   else if (group == 0xfeff && elem == 0xdde0) 
+   {
+     // reversed Sequence Terminator found
+     // probabely a bug in the header !
+     // Do what you want, it breaks !
+     //reversedEndian--;
+     //SwitchByteSwapCode();
+     gdcmWarningMacro( "Should never get here! reversed Sequence Terminator!" );
+     // fix the tag
+      group = 0xfffe;
+      elem  = 0xe0dd;  
+   }
+   else if (group == 0xfffe && elem == 0xe0dd) 
+   {
+      gdcmWarningMacro( "Straight Sequence Terminator." );  
+   }
 }
 
 /**
@@ -2360,7 +2079,8 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
  */
 void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
 {
-   // Endian reversion. Some files contain groups of tags with reversed endianess.
+   // Endian reversion. 
+   // Some files contain groups of tags with reversed endianess.
    if ( !Group0002Parsed && group != 0x0002)
    {
       Group0002Parsed = true;
@@ -2374,16 +2094,24 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
          return;
       }
 
-      // Group 0002 is always 'Explicit ...' enven when Transfer Syntax says 'Implicit ..." 
+      // Group 0002 is always 'Explicit ...' 
+      // even when Transfer Syntax says 'Implicit ..." 
 
-      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian )
+      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == 
+                                                    TS::ImplicitVRLittleEndian )
          {
             Filetype = ImplicitVR;
          }
        
       // FIXME Strangely, this works with 
-      //'Implicit VR Transfer Syntax (GE Private)
-      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian )
+      //'Implicit VR BigEndian Transfer Syntax (GE Private)
+      //
+      // --> Probabely normal, since we considered we never have 
+      // to trust manufacturers.
+      // (we find very often 'Implicit VR' tag, 
+      // even when Transfer Syntax tells us it's Explicit ...
+      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == 
+                                                       TS::ExplicitVRBigEndian )
       {
          gdcmWarningMacro("Transfer Syntax Name = [" 
                         << GetTransferSyntaxName() << "]" );