/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CExcelRecord.h  -  description
                             -------------------
    begin                : Mon Jan 19 2004
    copyright            : (C) 2000-2006 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library is distributed in the hope that it will be useful, but 
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef __CEXCELRECORD_H__
#define __CEXCELRECORD_H__

#include <sptk3/CBuffer.h>
#include <sptk3/CVariant.h>
#include <vector>

namespace sptk {

#define MAX_MS_RECSIZE   9000

#define MS_UNIX_DATE_DIFF (70*365.2422+1)

#define DATE_FORMAT      14

#define MS1904             0x22
#define ADDIN              0x87
#define ADDMENU            0xC2
#define ARRAY              0x221
#define AUTOFILTER         0x9E
#define AUTOFILTERINFO     0x9D
#define BACKUP             0x40
#define BLANK              0x201
#define BOF                0x809
#define BOOKBOOL           0xDA
#define BOOLERR            0x205
#define BOTTOMMARGIN       0x29
#define BOUNDSHEET         0x85
#define CALCCOUNT          0x0C
#define CALCMODE           0x0D
#define CODEPAGE           0x42
#define COLINFO            0x7D
#define CONTINUE           0x3C
#define COORDLIST          0xA9
#define COUNTRY            0x8C
#define CRN                0x5A
#define DBCELL             0xD7
#define DCON               0x50
#define DCONNAME           0x52
#define DCONREF            0x51
#define DEFAULTROWHEIGHT   0x225
#define DEFCOLWIDTH        0x55
#define DELMENU            0xC3
#define DELTA              0x10
#define DIMENSIONS         0x200
#define DOCROUTE           0xB8
#define DSF                0x161
#define EDG                0x88
#define MSEOF              0x0A
#define EXTERNCOUNT        0x16
#define EXTERNNAME         0x223
#define EXTERNSHEET        0x17
#define EXTSST             0xFF
#define FILEPASS           0x2F
#define FILESHARING        0x5B
#define FILESHARING2       0x1A5
#define FILTERMODE         0x9B
#define FNGROUPCOUNT       0x9C
#define FNGROUPNAME        0x9A
#define FONT1              0x231  // Microsoft docs wrong?
#define FONT2              0x31
#define FOOTER             0x15
#define FORMAT             0x41E
#define FORMULA1           0x406  // Microsoft docs wrong?
#define FORMULA2           0x06
#define GCW                0xAB
#define GRIDSET            0x82
#define GUTS               0x80
#define HCENTER            0x83
#define HEADER             0x14
#define HIDEOBJ            0x8D
#define HORIZONTALPAGEBREAKS     0x1B
#define IMDATA             0x7F
#define INDEX              0x20B
#define INTERFACEEND       0xE2
#define INTERFACEHDR       0xE1
#define ITERATION          0x11
#define LABEL              0x204
#define LABELSST           0xFD
#define LEFTMARGIN         0x26
#define LHNGRAPH           0x95
#define LHRECORD           0x94
#define LPR                0x98
#define MMS                0xC1
#define MSODRAWINGGROUP    0xEB
#define MSODRAWING         0xEC
#define MSODRAWINGSELECTION 0xED
#define MULBLANK           0xBE
#define MULRK              0xBD
#define NAME               0x218
#define NOTE               0x1C
#define NUMBER             0x203
#define OBJ                0x5D
#define OBJPROTECT         0x63
#define OBPROJ             0xD3
#define OLESIZE            0xDE
#define PALETTE            0x92
#define PANE               0x41
#define PASSWORD           0x13
#define PLS                0x4D
#define PRECISION          0x0E
#define PRINTGRIDLINES     0x2B
#define PRINTHEADERS       0x2A
#define PROTECT            0x12
#define PROT4REV           0x1AF
#define PROT4REVPASS       0x1BC
#define PUB                0x89
#define RECIPNAME          0xB9
#define REFMODE            0x0F
#define REFRESHALL         0x1B7
#define RIGHTMARGIN        0x27
#define RK                 0x27E
#define ROW                0x208
#define RSTRING            0xD6
#define SAVERECALC         0x5F
#define SCENARIO           0xAF
#define SCENMAN            0xAE
#define SCENPROTECT        0xDD
#define SCL                0xA0
#define SELECTION          0x1D
#define SETUP              0xA1
#define SHRFMLA            0xBC
#define SORT               0x90
#define SOUND              0x96
#define SST                0xFC
#define STANDARDWIDTH      0x99
#define STRING             0x207
#define STYLE              0x293
#define SUB                0x91
#define SUPBOOK            0x1AE
#define SXDI               0xC5
#define SXEXT              0xDC
#define SXIDSTM            0xD5
#define SXIVD              0xB4
#define SXLI               0xB5
#define SXPI               0xB6
#define SXSTRING           0xCD
#define SXTBL              0xD0
#define SXTBPG             0xD2
#define SXTBRGIITM         0xD1
#define SXVD               0xB1
#define SXVI               0xB2
#define SXVIEW             0xB0
#define SXVS               0xE3
#define TABID              0x13D
#define TABIDCONF          0xEA
#define TABLE              0x236
#define TEMPLATE           0x60
#define TOPMARGIN          0x28
#define UDDESC             0xDF
#define UNCALCED           0x5E
#define USESELFS           0x160
#define VCENTER            0x84
#define VERTICALPAGEBREAKS 0x1A
#define WINDOW1            0x3D
#define WINDOW2            0x23E
#define WINDOWPROTECT      0x19
#define WRITEACCESS        0x5C
#define WRITEPROT          0x86
#define WSBOOL             0x81
#define XCT                0x59
#define XF                 0xE0

   /// @addtogroup excel Excel Classes
   /// @{

   /// The record in Excel file
	class SP_EXPORT CExcelRecord {
	public:
		bool     m_manageMemory;  ///< Flag to manage the buffer memory or not
		unsigned m_bytes;         ///< The data size
		char    *m_data;          ///< External data buffer
		short    m_type;          ///< Record type
	public:
      /// Constructor
      /// @param rectype short, Excel record type
      /// @param reclen short, Excel record length
      /// @param buffer const char *, Excel record data
      /// @param manageMemory bool, true if memory for record data should be released in destructor
		CExcelRecord(short rectype,short reclen,const char *buffer=0L,bool manageMemory=false);

      /// Destructor
		~CExcelRecord() { if (m_manageMemory && m_data) delete m_data; }

      /// Appends the record data to the existing record. Memory is always allocated inside the object.
		void append(const char *data,unsigned sz);

      /// Returns Excel record type
		unsigned type() const { return m_type; }

      /// Returns the size of the Excel record data
		unsigned bytes() const { return m_bytes; }

      /// Returns pointer to the Excel record data
		const char *data() const { return m_data; }

      /// Reads the short integer (16 bit) from the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
		static unsigned short getshort(const char *rec,int offset);

      /// Writes the short integer (16 bit) to the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
      /// @param value short, the data to write
		static void           setshort(char *rec,int offset,short value);

      /// Reads the unsigned integer (32 bit) from the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
		static unsigned       getint(const char *rec,int offset);

      /// Writes the unsigned integer (32 bit) to the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
      /// @param value unsigned, the data to write
		static void           setint(char *rec,int offset,unsigned value);

      /// Reads the long integer (32 bit) from the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
		static long           getlong(const char *rec,int offset);

      /// Writes the long integer (32 bit) to the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
      /// @param value long, the data to write
		static void           setlong(char *rec,int offset,long value);

      /// Reads the double (64 bit) to the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
		static double         getdouble(const char *rec,int offset);

      /// Writes the double (64 bit) to the buffer
      /// @param rec const char *, the Excel record buffer
      /// @param offset int, the data offset in the record buffer
      /// @param value double, the data to write
		static void           setdouble(char *rec,int offset,double value);

      /// Converts an Excel RK (compact float or integer) number into regular number
      /// @param rkValue long, the (input) value of RK number
      /// @param rkType CVariantType&, the (output) type of RK number (VAR_INT or VAR_FLOAT)
      /// @returns the actual number stored in RK record
		static double         RK2double(long rkValue,CVariantType& rkType);

      /// Tries to represent integer as an RK number
      /// @param value int, (input) integer value
      /// @param rkValue int&, (output) RK number, if possible
      /// @returns true if conversion is performed. Otherwise the rkValue is unchanged.
		static bool           int2RK(int value,int& rkValue);

      /// Tries to represent double as an RK number
      /// @param value double, (input) double value
      /// @param rkValue int&, (output) RK number, if possible
      /// @returns true if conversion is performed. Otherwise the rkValue is unchanged.
		static bool           double2RK(double value,int& rkValue);

      /// Returns the name of the Excel record type, for debugging purposes
      /// @param rectype unsigned, the record type
		static char *         gettypename(unsigned rectype);

      /// Reoders the bytes of the value in accordancy with the platform (Big/Little Endian)
      /// @param val short, the input value
      /// @returns the converted value
		static short          reorderBytes(short val);

      /// Reoders the bytes of the value in accordancy with the platform (Big/Little Endian)
      /// @param val unsigned short, the input value
      /// @returns the converted value
		static unsigned short reorderBytes(unsigned short val);

      /// Reoders the bytes of the value in accordancy with the platform (Big/Little Endian)
      /// @param val int, the input value
      /// @returns the converted value
		static int            reorderBytes(int val);

      /// Reoders the bytes of the value in accordancy with the platform (Big/Little Endian)
      /// @param val unsigned, the input value
      /// @returns the converted value
		static unsigned       reorderBytes(unsigned val);

      /// Reoders the bytes of the value in accordancy with the platform (Big/Little Endian)
      /// @param val long, the input value
      /// @returns the converted value
		static long           reorderBytes(long val);

      /// Reoders the bytes of the value in accordancy with the platform (Big/Little Endian)
      /// @param val double, the input value
      /// @returns the converted value
		static double         reorderBytes(double val);
	};

   /// The list of the CExcelRecord elements
	class CExcelRecordList : public std::vector<CExcelRecord *> {
	public:
      /// Constructor
		CExcelRecordList()  {}

      /// Destructor
		~CExcelRecordList() { clear(); }

      /// Cleaner
		void clear();
	};
   /// @}
}
#endif
