/******************************************************************************
**  libDXFrw - Library to read/write DXF files (ascii & binary)              **
**                                                                           **
**  Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com               **
**                                                                           **
**  This library is free software, licensed under the terms of the GNU       **
**  General Public License as published by the Free Software Foundation,     **
**  either version 2 of the License, or (at your option) any later version.  **
**  You should have received a copy of the GNU General Public License        **
**  along with this program.  If not, see <http://www.gnu.org/licenses/>.    **
******************************************************************************/

#include <sstream>
#include "drw_dbg.h"
#include "dwgutil.h"
#include "rscodec.h"
#include "../libdwgr.h"

#include "qgslogger.h"

/** Utility function
 * convert a int to string in hex
 **/
namespace DRW
{
  std::string toHexStr( int n )
  {
#if defined(__APPLE__)
    char buffer[9] = {'\0'};
    snprintf( buffer, 9, "%X", n );
    return std::string( buffer );
#else
    std::ostringstream Convert;
    Convert << std::uppercase << std::hex << n;
    return Convert.str();
#endif
  }
}

/**
 * @brief dwgRSCodec::decode239I
 * @param in : input data (at least 255*blk bytes)
 * @param out : output data (at least 239*blk bytes)
 * @param blk number of codewords ( 1 cw == 255 bytes)
 */
void dwgRSCodec::decode239I( unsigned char *in, unsigned char *out, duint32 blk )
{
  int k = 0;
  unsigned char data[255];
  RScodec rsc( 0x96, 8, 8 ); //(255, 239)
  for ( duint32 i = 0; i < blk; i++ )
  {
    k = i;
    for ( int j = 0; j < 255; j++ )
    {
      data[j] = in[k];
      k += blk;
    }
    int r = rsc.decode( data );
    if ( r < 0 )
    {
      QgsDebugMsg( "WARNING: can't correct all errors" );
    }
    k = i * 239;
    for ( int j = 0; j < 239; j++ )
    {
      out[k++] = data[j];
    }
  }
}

/**
 * @brief dwgRSCodec::decode251I
 * @param in : input data (at least 255*blk bytes)
 * @param out : output data (at least 251*blk bytes)
 * @param blk number of codewords ( 1 cw == 255 bytes)
 */
void dwgRSCodec::decode251I( unsigned char *in, unsigned char *out, duint32 blk )
{
  int k = 0;
  unsigned char data[255];
  RScodec rsc( 0xB8, 8, 2 ); //(255, 251)
  for ( duint32 i = 0; i < blk; i++ )
  {
    k = i;
    for ( int j = 0; j < 255; j++ )
    {
      data[j] = in[k];
      k += blk;
    }
    int r = rsc.decode( data );
    if ( r < 0 )
    {
      QgsDebugMsg( "WARNING: dwgRSCodec::decode251I, can't correct all errors" );
    }
    k = i * 251;
    for ( int j = 0; j < 251; j++ )
    {
      out[k++] = data[j];
    }
  }
}

duint32 dwgCompressor::twoByteOffset( duint32 *ll )
{
  duint32 cont = 0;
  duint8 fb = bufC[pos++];
  cont = ( fb >> 2 ) | ( bufC[pos++] << 6 );
  *ll = ( fb & 0x03 );
  return cont;
}

duint32 dwgCompressor::longCompressionOffset()
{
  duint32 cont = 0;
  duint8 ll = bufC[pos++];
  while ( ll == 0x00 )
  {
    cont += 0xFF;
    ll = bufC[pos++];
  }
  cont += ll;
  return cont;
}

duint32 dwgCompressor::long20CompressionOffset()
{
//    duint32 cont = 0;
  duint32 cont = 0x0F;
  duint8 ll = bufC[pos++];
  while ( ll == 0x00 )
  {
//        cont += 0xFF;
    ll = bufC[pos++];
  }
  cont += ll;
  return cont;
}

duint32 dwgCompressor::litLength18()
{
  duint32 cont = 0;
  duint8 ll = bufC[pos++];
  //no literal length, this byte is next opCode
  if ( ll > 0x0F )
  {
    pos--;
    return 0;
  }

  if ( ll == 0x00 )
  {
    cont = 0x0F;
    ll = bufC[pos++];
    while ( ll == 0x00 ) //repeat until ll != 0x00
    {
      cont += 0xFF;
      ll = bufC[pos++];
    }
  }
  cont += ll;
  cont += 3; //already sum 3
  return cont;
}

void dwgCompressor::decompress18( duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize )
{
  bufC = cbuf;
  bufD = dbuf;
  sizeC = csize - 2;
  sizeD = dsize;
  QgsDebugMsgLevel( QString( "last 2 bytes: 0x%1 0x%2" ).arg( bufC[sizeC], 0, 16 ).arg( bufC[sizeC+1], 0, 16 ), 5 );
  sizeC = csize;

  duint32 compBytes;
  duint32 compOffset;
  duint32 litCount;

  pos = 0; //current position in compressed buffer
  rpos = 0; //current position in resulting decompressed buffer
  litCount = litLength18();
  //copy first lileral lenght
  for ( duint32 i = 0; i < litCount; ++i )
  {
    bufD[rpos++] = bufC[pos++];
  }

  while ( pos < csize && ( rpos < dsize + 1 ) ) //rpos < dsize to prevent crash more robust are needed
  {
    duint8 oc = bufC[pos++]; //next opcode
    if ( oc == 0x10 )
    {
      compBytes = longCompressionOffset() + 9;
      compOffset = twoByteOffset( &litCount ) + 0x3FFF;
      if ( litCount == 0 )
        litCount = litLength18();
    }
    else if ( oc > 0x11 && oc < 0x20 )
    {
      compBytes = ( oc & 0x0F ) + 2;
      compOffset = twoByteOffset( &litCount ) + 0x3FFF;
      if ( litCount == 0 )
        litCount = litLength18();
    }
    else if ( oc == 0x20 )
    {
      compBytes = longCompressionOffset() + 0x21;
      compOffset = twoByteOffset( &litCount );
      if ( litCount == 0 )
        litCount = litLength18();
      else
        oc = 0x00;
    }
    else if ( oc > 0x20 && oc < 0x40 )
    {
      compBytes = oc - 0x1E;
      compOffset = twoByteOffset( &litCount );
      if ( litCount == 0 )
        litCount = litLength18();
    }
    else if ( oc > 0x3F )
    {
      compBytes = (( oc & 0xF0 ) >> 4 ) - 1;
      duint8 ll2 = bufC[pos++];
      compOffset = ( ll2 << 2 ) | (( oc & 0x0C ) >> 2 );
      litCount = oc & 0x03;
      if ( litCount < 1 )
      {
        litCount = litLength18();
      }
    }
    else if ( oc == 0x11 )
    {
      QgsDebugMsgLevel( QString( "end of input stream, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ), 5 );
      return; //end of input stream
    }
    else   //ll < 0x10
    {
      QgsDebugMsg( QString( "failed illegal char, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ) );
      return; //fails, not valid
    }
    //copy "compressed data", TODO Needed verify out of bounds
    duint32 remaining = sizeD - ( litCount + rpos );
    if ( remaining < compBytes )
    {
      compBytes = remaining;
      QgsDebugMsg( QString( "bad compBytes size, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ) );
    }
    for ( duint32 i = 0, j = rpos - compOffset - 1; i < compBytes; i++ )
    {
      bufD[rpos++] = bufD[j++];
    }
    //copy "uncompressed data", TODO Needed verify out of bounds
    for ( duint32 i = 0; i < litCount; i++ )
    {
      bufD[rpos++] = bufC[pos++];
    }
  }
  QgsDebugMsg( QString( "bad out, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ) );
}


void dwgCompressor::decrypt18Hdr( duint8 *buf, duint32 size, duint32 offset )
{
  duint8 max = size / 4;
  duint32 secMask = 0x4164536b ^ offset;
  duint32* pHdr = ( duint32* )buf;
  for ( duint8 j = 0; j < max; j++ )
    *pHdr++ ^= secMask;
}

/*void dwgCompressor::decrypt18Data(duint8 *buf, duint32 size, duint32 offset){
    duint8 max = size / 4;
    duint32 secMask = 0x4164536b ^ offset;
    duint32* pHdr = (duint32*)buf;
    for (duint8 j = 0; j < max; j++)
        *pHdr++ ^= secMask;
}*/

duint32 dwgCompressor::litLength21( duint8 *cbuf, duint8 oc, duint32 *si )
{

  duint32 srcIndex = *si;

  duint32 length = oc + 8;
  if ( length == 0x17 )
  {
    duint32 n = cbuf[srcIndex++];
    length += n;
    if ( n == 0xff )
    {
      do
      {
        n = cbuf[srcIndex++];
        n |= ( duint32 )( cbuf[srcIndex++] << 8 );
        length += n;
      }
      while ( n == 0xffff );
    }
  }

  *si = srcIndex;
  return length;
}

void dwgCompressor::decompress21( duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize )
{
  duint32 srcIndex = 0;
  duint32 dstIndex = 0;
  duint32 length = 0;
  duint32 sourceOffset;
  duint8 opCode;

  opCode = cbuf[srcIndex++];
  if (( opCode >> 4 ) == 2 )
  {
    srcIndex = srcIndex + 2;
    length = cbuf[srcIndex++] & 0x07;
  }

  while ( srcIndex < csize && ( dstIndex < dsize + 1 ) ) //dstIndex < dsize to prevent crash more robust are needed
  {
    if ( length == 0 )
      length = litLength21( cbuf, opCode, &srcIndex );
    copyCompBytes21( cbuf, dbuf, length, srcIndex, dstIndex );
    srcIndex += length;
    dstIndex += length;
    if ( dstIndex >= dsize ) break; //check if last chunk are compressed & terminate

    length = 0;
    opCode = cbuf[srcIndex++];
    readInstructions21( cbuf, &srcIndex, &opCode, &sourceOffset, &length );
    while ( true )
    {
      //prevent crash with corrupted data
      if ( sourceOffset > dstIndex )
      {
        QgsDebugMsg( QString( "WARNING sourceOffset > dstIndex: csize=%1, srcIndex=%2 dsize=%3 dstIndex=%4" )
                     .arg( csize ).arg( srcIndex ).arg( dsize ).arg( dstIndex )
                   );
        sourceOffset = dstIndex;
      }
      //prevent crash with corrupted data
      if ( length > dsize - dstIndex )
      {
        QgsDebugMsg( QString( "WARNING length > dsize - dstIndex: csize=%1, srcIndex=%2 dsize=%3 dstIndex=%4" )
                     .arg( csize ).arg( srcIndex ).arg( dsize ).arg( dstIndex )
                   );
        length = dsize - dstIndex;
        srcIndex = csize;//force exit
      }
      sourceOffset = dstIndex - sourceOffset;
      for ( duint32 i = 0; i < length; i++ )
        dbuf[dstIndex++] = dbuf[sourceOffset+i];

      length = opCode & 7;
      if (( length != 0 ) || ( srcIndex >= csize ) )
      {
        break;
      }
      opCode = cbuf[srcIndex++];
      if (( opCode >> 4 ) == 0 )
      {
        break;
      }
      if (( opCode >> 4 ) == 15 )
      {
        opCode &= 15;
      }
      readInstructions21( cbuf, &srcIndex, &opCode, &sourceOffset, &length );
    }
  }
  QgsDebugMsg( QString( "csize=%1, srcIndex=%2 dsize=%3 dstIndex=%4" )
               .arg( csize ).arg( srcIndex ).arg( dsize ).arg( dstIndex )
             );
}

void dwgCompressor::readInstructions21( duint8 *cbuf, duint32 *si, duint8 *oc, duint32 *so, duint32 *l )
{
  duint32 length;
  duint32 srcIndex = *si;
  duint32 sourceOffset;
  unsigned char opCode = *oc;
  switch (( opCode >> 4 ) )
  {
    case 0:
      length = ( opCode & 0xf ) + 0x13;
      sourceOffset = cbuf[srcIndex++];
      opCode = cbuf[srcIndex++];
      length = (( opCode >> 3 ) & 0x10 ) + length;
      sourceOffset = (( opCode & 0x78 ) << 5 ) + 1 + sourceOffset;
      break;
    case 1:
      length = ( opCode & 0xf ) + 3;
      sourceOffset = cbuf[srcIndex++];
      opCode = cbuf[srcIndex++];
      sourceOffset = (( opCode & 0xf8 ) << 5 ) + 1 + sourceOffset;
      break;
    case 2:
      sourceOffset = cbuf[srcIndex++];
      sourceOffset = (( cbuf[srcIndex++] << 8 ) & 0xff00 ) | sourceOffset;
      length = opCode & 7;
      if (( opCode & 8 ) == 0 )
      {
        opCode = cbuf[srcIndex++];
        length = ( opCode & 0xf8 ) + length;
      }
      else
      {
        sourceOffset++;
        length = ( cbuf[srcIndex++] << 3 ) + length;
        opCode = cbuf[srcIndex++];
        length = ((( opCode & 0xf8 ) << 8 ) + length ) + 0x100;
      }
      break;
    default:
      length = opCode >> 4;
      sourceOffset = opCode & 15;
      opCode = cbuf[srcIndex++];
      sourceOffset = ((( opCode & 0xf8 ) << 1 ) + sourceOffset ) + 1;
      break;
  }
  *oc = opCode;
  *si = srcIndex;
  *so = sourceOffset;
  *l = length;
}


void dwgCompressor::copyCompBytes21( duint8 *cbuf, duint8 *dbuf, duint32 l, duint32 si, duint32 di )
{
  duint32 length = l;
  duint32 dix = di;
  duint32 six = si;

  while ( length > 31 )
  {
    //in doc: 16-31, 0-15
    for ( duint32 i = six + 24; i < six + 32; i++ )
      dbuf[dix++] = cbuf[i];
    for ( duint32 i = six + 16; i < six + 24; i++ )
      dbuf[dix++] = cbuf[i];
    for ( duint32 i = six + 8; i < six + 16; i++ )
      dbuf[dix++] = cbuf[i];
    for ( duint32 i = six; i < six + 8; i++ )
      dbuf[dix++] = cbuf[i];
    six = six + 32;
    length = length - 32;
  }

  switch ( length )
  {
    case 0:
      break;
    case 1: //Ok
      dbuf[dix] = cbuf[six];
      break;
    case 2: //Ok
      dbuf[dix++] = cbuf[six+1];
      dbuf[dix] = cbuf[six];
      break;
    case 3: //Ok
      dbuf[dix++] = cbuf[six+2];
      dbuf[dix++] = cbuf[six+1];
      dbuf[dix] = cbuf[six];
      break;
    case 4: //Ok
      for ( int i = 0; i < 4;i++ ) //RLZ is OK, or are inverse?, OK
        dbuf[dix++] = cbuf[six++];
      break;
    case 5: //Ok
      dbuf[dix++] = cbuf[six+4];
      for ( int i = 0; i < 4;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 6: //Ok
      dbuf[dix++] = cbuf[six+5];
      for ( int i = 1; i < 5;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix] = cbuf[six];
      break;
    case 7:
      //in doc: six+5, six+6, 1-5, six+0
      dbuf[dix++] = cbuf[six+6];
      dbuf[dix++] = cbuf[six+5];
      for ( int i = 1; i < 5;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix] = cbuf[six];
    case 8: //Ok
      for ( int i = 0; i < 8;i++ ) //RLZ 4[0],4[4] or 4[4],4[0]
        dbuf[dix++] = cbuf[six++];
      break;
    case 9: //Ok
      dbuf[dix++] = cbuf[six+8];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 10: //Ok
      dbuf[dix++] = cbuf[six+9];
      for ( int i = 1; i < 9;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix] = cbuf[six];
      break;
    case 11:
      //in doc: six+9, six+10, 1-9, six+0
      dbuf[dix++] = cbuf[six+10];
      dbuf[dix++] = cbuf[six+9];
      for ( int i = 1; i < 9;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix] = cbuf[six];
      break;
    case 12: //Ok
      for ( int i = 8; i < 12;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 13: //Ok
      dbuf[dix++] = cbuf[six+12];
      for ( int i = 8; i < 12;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 14: //Ok
      dbuf[dix++] = cbuf[six+13];
      for ( int i = 9; i < 13; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 1; i < 9; i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix] = cbuf[six];
      break;
    case 15:
      //in doc: six+13, six+14, 9-12, 1-8, six+0
      dbuf[dix++] = cbuf[six+14];
      dbuf[dix++] = cbuf[six+13];
      for ( int i = 9; i < 13; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 1; i < 9; i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix] = cbuf[six];
      break;
    case 16: //Ok
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 17: //Seems Ok
      for ( int i = 9; i < 17;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix++] = cbuf[six+8];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 18:
      //in doc: six+17, 1-16, six+0
      dbuf[dix++] = cbuf[six+17];
      for ( int i = 9; i < 17;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 1; i < 9;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix] = cbuf[six];
      break;
    case 19:
      //in doc: 16-18, 0-15
      dbuf[dix++] = cbuf[six+18];
      dbuf[dix++] = cbuf[six+17];
      dbuf[dix++] = cbuf[six+16];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 20:
      //in doc: 16-19, 0-15
      for ( int i = 16; i < 20;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 21:
      //in doc: six+20, 16-19, 0-15
      dbuf[dix++] = cbuf[six+20];
      for ( int i = 16; i < 20;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six+i];
      break;
    case 22:
      //in doc: six+20, six+21, 16-19, 0-15
      dbuf[dix++] = cbuf[six+21];
      dbuf[dix++] = cbuf[six+20];
      for ( int i = 16; i < 20;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 23:
      //in doc: six+20, six+21, six+22, 16-19, 0-15
      dbuf[dix++] = cbuf[six+22];
      dbuf[dix++] = cbuf[six+21];
      dbuf[dix++] = cbuf[six+20];
      for ( int i = 16; i < 20;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8;i++ )
        dbuf[dix++] = cbuf[six+i];
      break;
    case 24:
      //in doc: 16-23, 0-15
      for ( int i = 16; i < 24;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8; i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 25:
      //in doc: 17-24, six+16, 0-15
      for ( int i = 17; i < 25;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix++] = cbuf[six+16];
      for ( int i = 8; i < 16; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8; i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 26:
      //in doc: six+25, 17-24, six+16, 0-15
      dbuf[dix++] = cbuf[six+25];
      for ( int i = 17; i < 25;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix++] = cbuf[six+16];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8; i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 27:
      //in doc: six+25, six+26, 17-24, six+16, 0-15
      dbuf[dix++] = cbuf[six+26];
      dbuf[dix++] = cbuf[six+25];
      for ( int i = 17; i < 25;i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix++] = cbuf[six+16];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8; i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 28:
      //in doc: 24-27, 16-23, 0-15
      for ( int i = 24; i < 28; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 16; i < 24;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8; i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 29:
      //in doc: six+28, 24-27, 16-23, 0-15
      dbuf[dix++] = cbuf[six+28];
      for ( int i = 24; i < 28; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 16; i < 24;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8; i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 30:
      //in doc: six+28, six+29, 24-27, 16-23, 0-15
      dbuf[dix++] = cbuf[six+29];
      dbuf[dix++] = cbuf[six+28];
      for ( int i = 24; i < 28; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 16; i < 24;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 8; i < 16;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 0; i < 8; i++ )
        dbuf[dix++] = cbuf[six++];
      break;
    case 31:
      //in doc: six+30, 26-29, 18-25, 2-17, 0-1
      dbuf[dix++] = cbuf[six+30];
      for ( int i = 26; i < 30;i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 18; i < 26;i++ )
        dbuf[dix++] = cbuf[six+i];
      /*        for (int i = 2; i<18; i++)
                  dbuf[dix++] = cbuf[six+i];*/
      for ( int i = 10; i < 18; i++ )
        dbuf[dix++] = cbuf[six+i];
      for ( int i = 2; i < 10; i++ )
        dbuf[dix++] = cbuf[six+i];
      dbuf[dix++] = cbuf[six+1];
      dbuf[dix] = cbuf[six];
      break;
    default:
      QgsDebugMsg( "WARNING bad output." );
      break;
  }
}


secEnum::DWGSection secEnum::getEnum( std::string nameSec )
{
  //TODO: complete it
  if ( nameSec == "AcDb:Header" )
  {
    return HEADER;
  }
  else if ( nameSec == "AcDb:Classes" )
  {
    return CLASSES;
  }
  else if ( nameSec == "AcDb:SummaryInfo" )
  {
    return SUMARYINFO;
  }
  else if ( nameSec == "AcDb:Preview" )
  {
    return PREVIEW;
  }
  else if ( nameSec == "AcDb:VBAProject" )
  {
    return VBAPROY;
  }
  else if ( nameSec == "AcDb:AppInfo" )
  {
    return APPINFO;
  }
  else if ( nameSec == "AcDb:FileDepList" )
  {
    return FILEDEP;
  }
  else if ( nameSec == "AcDb:RevHistory" )
  {
    return REVHISTORY;
  }
  else if ( nameSec == "AcDb:Security" )
  {
    return SECURITY;
  }
  else if ( nameSec == "AcDb:AcDbObjects" )
  {
    return OBJECTS;
  }
  else if ( nameSec == "AcDb:ObjFreeSpace" )
  {
    return OBJFREESPACE;
  }
  else if ( nameSec == "AcDb:Template" )
  {
    return TEMPLATE;
  }
  else if ( nameSec == "AcDb:Handles" )
  {
    return HANDLES;
  }
  else if ( nameSec == "AcDb:AcDsPrototype_1b" )
  {
    return PROTOTYPE;
  }
  else if ( nameSec == "AcDb:AuxHeader" )
  {
    return AUXHEADER;
  }
  else if ( nameSec == "AcDb:Signature" )
  {
    return SIGNATURE;
  }
  else if ( nameSec == "AcDb:AppInfoHistory" )  //in ac1021
  {
    return APPINFOHISTORY;
//    } else if (nameSec=="AcDb:Extended Entity Data"){
//        return EXTEDATA;
//    } else if (nameSec=="AcDb:PROXY ENTITY GRAPHICS"){
//        return PROXYGRAPHICS;
  }
  return UNKNOWNS;
}
