#ifndef __cplusplus
#error STS Btrieve Classes require C++ compilation (use a .cpp suffix)
#endif 

#include <afxwin.h>   
#include <afx.h>
#include <afxcoll.h>
         
#ifndef __AFXBTR_H__         
#define __AFXBTR_H__
                       
#include "magdate.h"
 
#define SEGMENT 0
#define LASTSEG 1
#define VARLEN  1
                       
// BTRIEVE interface
extern "C"
{
#include "wbtrv.h"
int BTRV(int,char*,char*,int*,char*,int);
void FAR PASCAL InitBtrieve();
void FAR PASCAL StopBtrieve(); 
}
                     


typedef DWORD BTRPOS;
        
	                         
typedef struct tagKEYSPECSTRUCT
		{
	    	int 	nKeyPos;
	    	int 	nKeyLength;
	    	int 	nKeyFlags;
	    	DWORD   dwDummy1;
	    	char    cExtType;
	    	char    cNullVal;
	    	DWORD   dwDummy2;
	    } KEYSPECSTRUCT;	 
                  
                  
typedef struct tagFILESPECSTRUCT
{
	int 	nRecLen;
    int 	nPageSize;
    int 	nNumKeys;
    DWORD 	dwDummy1;
    int     nFileFlags;
    WORD    wDummy2;
    int     nAllocation;
} FILESPECSTRUCT;    
                 

typedef struct tagBTRCREATESTRUCT
{   
 	FILESPECSTRUCT filespec;
 	KEYSPECSTRUCT  keyspec[1];
} BTRCREATESTRUCT;

 	                
class CField:public CObject 
{                         
friend class CBtrFile;
friend class CDataFile;
DECLARE_DYNAMIC(CField)
public:
// Field Types
   enum FieldTypes
      {
        fieldVarLen=1
      };        
// Extended Types
   enum ExtTypes
      {
        string,
        integer,
        floats,
        date,
        time,
        decimal,
        money,
        logical,
        numeric,
        bfloat,
        lstring,
        zstring,
        ubinary,
        autoinc
      };  
      
  CField(int nField,int nFieldLength,DWORD dwFieldType); 
  ~CField();

//operations       
virtual  int   GetPos() const;
  DWORD GetType() const;
virtual  int   GetLength() const;
  int   GetMaxLength() const;
  int   GetFieldNum() const;
  void  AssertValid() const;
#ifdef _DEBUG
  void Dump(CDumpContext& dc) const;
#endif  

CString m_name;

protected:    
// data members                      
  int 		m_nFieldPos;
  DWORD		m_dwFieldType;
  int 		m_nFieldLength;
  int       m_nMaxLen;
  int       m_nFieldNum;
  char*     m_pFieldBuf;
  
};  
  

class CKey:public CObject
{     
public:     
    CKey(int KeyNum,int SegNum,int nField,int LastSeg,int KeyType,char NullVal);
    ~CKey(); 
    
    int GetKeySeg() const;
    int GetKey() const;
    int GetField() const;
    int GetType() const;
    char GetNull() const;
      
    CString m_name; 
    
protected:    
   	int   m_nKeyType;
   	int   m_nKeyNum;
   	int   m_nNumSeg;
   	char  m_cNullVal;
   	int   m_nField;
};

        	                            
class CBtrFile:public CObject
{
DECLARE_SERIAL(CBtrFile)
public:
 //Operation codes
  enum OpCodes
      {
        codeOpen,
        codeClose,
        codeInsert,
        codeUpdate,
        codeDelete,
        codeGetEqual,
        codeGetNext,
        codeGetPrev,
        codeGetGreater,
        codeGetGtEqu,
        codeGetLess,      
        codeGetLtEqu,
        codeGetFirst,
        codeGetLast,
        codeCreate,
        codeStat,
        codeExtend,
        codeSetDir,
        codeGetDir,
        codeBeginTrans,
        codeEndTrans,
        codeAbortTrans,
        codeGetPosition,
        codeGetDirect,
        codeStepNext,
        codeStop,
        codeVersion,
        codeUnlock,
        codeReset,
        codeSetOwner,
        codeClearOwner,
        codeCreateIndex,
        codeDropIndex,
        codeStepFirst,
        codeStepLast,
        codeStepPrev, 
        codeKey      = 50
      }; 
        
// File flags

  enum FileFlags
      {       
        varLen       = 1, 
        blankTrunc   = 2, 
        preAlloc     = 4,
        compress     = 8,
        keyOnly      = 16,
        free10       = 64,
        free20       = 128,
        free30       = 192
      };
                           
// Key Flags
  enum KeyFlags
      {        
        duplicate   = 1,
        modifiable  = 2,
        binary      = 4,
        null        = 8,
        segmented   = 16,
        altSequence = 32,
        descend     = 64,
        supplKey    = 128,
        extType     = 256,
        manual      = 512
      };  

       
  enum CreateModes { createOver,createNew = -1};
  enum OpenModes
  	  { 
  	  	openNormal,
  		openFast 		= -1,
  		openReadOnly	= -2,
  		openVerify  	= -3,
  		openExclusive   = -4
  	  };

  enum Locks
      {
        lockSnglWait 	= 100,
        lockSnglNoWait	= 200,
        lockMulWait     = 300,
        lockMulNoWait	= 400
      };  
        
  CBtrFile();             // constructor
  ~CBtrFile();       
  
//record & file operations
  
  virtual void 	Create(char* name,int mode); 
  virtual void 	Open(char* name,int mode);
  virtual void 	Insert(int lock=0);
  virtual void 	Update(int lock=0);
  virtual void  Close();
  virtual void 	Delete();
  virtual void 	GetEqual(int lock=0);
  virtual void 	GetNext(int lock=0);
  virtual void 	GetPrev(int lock=0);
  virtual void 	GetGreater(int lock=0);
  virtual void 	GetGreaterEq(int lock=0);
  virtual void 	GetLess(int lock=0);
  virtual void 	GetLessEq(int lock=0);
  virtual void 	GetFirst(int lock=0);
  virtual void 	GetLast(int lock=0);
  virtual void 	Stat();
  virtual void 	Extend();
  virtual void 	SetDir();
  virtual void 	GetDir();
  virtual void 	BeginTrans(int lock=0){};
  virtual void 	EndTrans(){};
  virtual void 	AbortTrans(){};
        BTRPOS 	GetPosition();
  virtual void 	GetDirect(BTRPOS pos);
  virtual void  StepNext(int lock=0){};
  virtual void  StepPrev(int lock=0){};
  virtual void  StepFirst(int lock=0){};
  virtual void  StepLast(int lock=0){};
  virtual void  Stop();
  virtual void  Reset(){};
  virtual char* Version(){return NULL;} 
  virtual int   CreateIndex(){return 0;}             
  virtual void  DropIndex(int index){};  
  
// non-standard operations  
  
  virtual void  Clone(CBtrFile* source);
  virtual int   UseKey(int key);
  virtual int   GetActiveKey();  
  
// Field operations
  
  virtual CField* GetFieldObject(int nFieldNum) const;
  virtual CKey* GetKeySeg(int nKeySeg,int Key);
  virtual void 
   CreateField(int nField,int nFieldLength,int FieldType=0,int varlen=0);  
  virtual void
   CreateKey(int nKey,int nSeg,int nField,int LastSeg=1,int type=0,char NullVal=0);
   
  virtual void*  GetField(int nField) const;
  virtual CString  GetFieldStr(int nField) const;
  virtual int    GetFieldInt(int nField) const;
  virtual long   GetFieldLong(int nField) const;
  virtual float  GetFieldFloat(int nField) const;
  virtual double GetFieldDouble(int nField) const; 
  
  virtual int SetField(int nField,void* FieldBuf,int len=0);            
  virtual int SetField(int nField,char* FieldBuf);            
  virtual int SetField(int nField,int value);            
  virtual int SetField(int nField,long value);            
  virtual int SetField(int nField,float value);            
  virtual int SetField(int nField,double value);            
  
  virtual int GetFieldLength(int nField) const;
  void AssertValid() const{};
#ifdef _DEBUG
  void Dump(CDumpContext& dc) const{};
#endif  
    
//data members

int     m_nRecLength;


protected:
//data
CString m_PathName;
int     m_nAllocation;
int     m_nNumKeys; 
int     m_nFileStyles;
int     m_nPageSize;
int     m_nActiveKey; 
CObList m_FieldsList;
CObList m_KeysList;
int     m_nNumVarFields;
int     m_nNumFields;   
char __based(__segname("_DATA")) m_szPosBlock[128];
char __based(__segname("_DATA")) m_szKeyBuffer[255];
//operations
virtual void VarFieldRead(CField*,char*);
virtual int  VarFieldWrite(CField*,char*); 
virtual int GetXX(int code,int lock=0);
};

class CBtrException : public CException
{
	DECLARE_DYNAMIC(CBtrException)

public:
  enum {
		none,
		OpCode,
		io,
		notOpened,
		keyNotFound,
		keyDuplicate,
		keyInvalid,
		keyDifferent,
		position,
		endOfFile,
		keyModify,
		fileName,
		fileNotFound,
		extendedFile,
		preImageOpen,
		preImageIO,
		expansion,
		fileClose,
		diskFull,
		unrecoverable,
		btrieveInactive,
		keyBufferShort,
		posBlockLength,
		pageSize,
		createIO,
		numOfKeys,
		keyPos,
		recLength,
		keyLength,
		notBtrieveFile,
		fileExtended,
		extendIO,
		unknown,
		extName,
		dirError,
		transError,
		transActive,
		transFileIO,
		transEndAbort,
		transMaxFiles,
		opNotAllowed,
		fastAccess,
		invalidRecAddr,
		nullKeyPath,
		invalidKeyFlags,
		fileAccessDenied,
		maxFiles,
		invalidAltSeq,
		keyType,
		ownerSet,
		invalidOwner,
		writeCache,
		interface,
		varPage,
		autoIncr,
		incomplIndex,
		expMem,
		compBufShort,
		fileExist,
		conflict          	= 80,
		lock          		= 81,
		lostPos       		= 82,
		readOutsideTrans    = 83,
		recordInUse         = 84,
		fileInUse           = 85,
		fileTableFull       = 86,
		handleTableFull     = 87,
		openMode			= 88,
		lockType            = 93,
		permission          = 94,
	   };	
		
// Constructor

	CBtrException(int cause = CBtrException::none);

// Attributes
	int m_cause;

// Operations
   virtual void GetErrorText(LPSTR);

#ifdef _DEBUG
	virtual void Dump(CDumpContext&) const;
#endif
};

// Standard exception throw

void AFXAPI AfxThrowBtrException(int cause);

//////////////////////////////////////////////////////////////////
//            Part 2 - Derived classes        
//////////////////////////////////////////////////////////////////


class CDataFile:public CBtrFile
{
public:
  CDataFile():CBtrFile(){};
    
protected:
  void VarFieldRead(CField*,char*);  
  int  VarFieldWrite(CField*,char*);  
};


class CMagicFile:public CDataFile
{
public:
	CMagicFile():CDataFile(){};
	
    CMagicDate GetFieldDate(int nField);
    int SetFieldDate(int nField,const CMagicDate& MagicDate);
	
protected:	
    void  VarFieldRead(CField*,char*);  
    int   VarFieldWrite(CField*,char*);
virtual char* Compress(const char* pBuf,int& len);  
virtual char* DeCompress(const char* pBuf,int& len);  
};

#endif

