#ifndef _EMS_MEMORY_H_H_
#define _EMS_MEMORY_H_H_

#ifndef TRUE
#define TRUE  1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#include <stdlib.h>
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <sys\\stat.h>


#define XMSMEMORY_STYLE_NORMAL  0
#define XMSMEMORY_STYLE_DISK    1
#define XMSMEMORY_STYLE_EMSCARD 2


//#define  USE_EMSMEMORY_FLAGS  FALSE
#define  EMS_PAGE_LENGTH   (16L*1024L)
#define  MANAGER_EMS_PAGE  (64L*1024L/(EMS_PAGE_LENGTH))
typedef struct _tagEMSMOVEPARAMETERBLOCK
{
	DWORD   dwCount;
	BYTE	bySourceType;
	HANDLE  hSource;
	WORD    wSourceOffset;
	WORD    wSourceSeg;
	BYTE	byTargetType;
	HANDLE  hTarget;
	WORD    wTargetOffset;
	WORD    wTargetSeg;
}EMSMOVEPARAMETERBLOCK;


struct XMS_MEMORY_BLOCK1
{
	DWORD dwDead;
    DWORD dwActiveCount;
    DWORD dwFirst;
    DWORD dwLast;
};


#define MEMORY_CONTROL_FLAGS 0x005AA55Alu
#define XMS2_MIN_BUFFER_COUNT  80L

struct XMS_MEMORY_BLOCK2
{
	DWORD dwFlags;
	long dwSelf;
    long dwPrev;
    long dwNext;
    long dwBusy;
  	long dwSize;
	long dwTrueSize;
};


#define EMSMEMORY_INT_CODE  0x67

//_CLASSDEF(CEmsMemory);
class  CEmsMemory
{
protected:
	static   BOOL    m_bInit;
protected:
	BYTE     FAR *m_pPhysicalEms;
	HANDLE   m_hMemory;
	WORD	 m_wLocal;
	BOOL	 m_bEmsFrame;

	DWORD	 m_dwBufferSize;
	WORD     m_wLogicalPageCount;
protected:
	WORD     m_wLocalMap[1][2];
public:
	static   BOOL     m_sbGlobalMap[MANAGER_EMS_PAGE];
public:
	void   SetWrite(BOOL bWrite){m_wLocalMap[0][1]=bWrite;}
	BOOL   GetWrite(){return(m_wLocalMap[0][1]);}
	BOOL   IsEms();
	int    GetEmsVersion();
	BOOL   FreeEms();
	BOOL   MallocEms(DWORD  dwCount);
	BOOL   RemallocEms(DWORD  dwCount);
	HANDLE GetEmsHandle(){return(m_hMemory);}
	WORD   GetEmsPageFrame();
	BOOL   SaveFrameToEms();
	BOOL   MoveEmsToPageFrame(WORD wLogicalPage);
	BOOL   MoveEmsBlock(EMSMOVEPARAMETERBLOCK *pEmsMoveParameterBlock);
	BOOL   LoadFile(const char *pszFile);

	BYTE*  GetPoint(DWORD dwIndex,int nCount=1);
	BOOL   SetSize(DWORD dwSize,DWORD dwCount=1);
	BOOL   SetSizeEx(DWORD dwSize,DWORD dwCount=1);
	BYTE   GetByteData(DWORD dwIndex);
	BYTE   GetByteData(DWORD dwIndex,BYTE* pByte,DWORD dwCount);

	int    GetIntData(DWORD dwIndex);
	long   GetLongData(DWORD dwIndex);
	float  GetFloatData(DWORD dwIndex);
	BOOL   SetByteData(DWORD dwIndex,BYTE );
	BOOL   SetByteData(DWORD dwIndex,BYTE* pbyData,DWORD dwCount);
	BOOL   SetIntData(DWORD dwIndex,int);
	BOOL   SetLongData(DWORD dwIndex,long);
	BOOL   SetFloatData(DWORD dwIndex,float);
public:
	BOOL CoEmsMemory(BOOL bEmsFrame);
	CEmsMemory();
	~CEmsMemory();
public:
	DWORD  GetSize(){return(m_dwBufferSize);}
};


class  CXmsMemory
{
protected:
    static void*    m_pIntVector;
    BOOL     m_bWrite;
    int      m_nLockCounter;
	HANDLE   m_hMemory;
	DWORD    m_lgSegment;

    WORD     m_wXmsPageLength;
    BYTE*    m_pBuffer;//[XMS_PAGE_LENGTH];
protected:
    DWORD    m_dwSize;
	FILE*    m_pFile;

    int      m_nXmsStyle;
    BOOL     m_bChangeXms;
protected:
    int      m_nShift;
    void     ModifyXmsStyle();
protected:
	static BOOL     InitXmsMemoryIntVector();
	BOOL     __ssMallocXms(DWORD dwCount, BOOL bV3);
	BOOL     __ssRemallocXms(DWORD dwCount, BOOL bV3);
	int   CalcShift(int nFrameSize);

public:
	static BOOL     IsExistXms();
	void     SetXmsStyle(int nStyle);

	WORD     GetVersion(WORD* pwCode2 = NULL, WORD* pwCode3 = NULL);
	BOOL     GetFreeInformation(WORD* pwMaxFreeBlock, WORD* pwTotalFreeBlock);

	BOOL     MallocXms(DWORD  dwCount);
	BOOL     MallocXmsV3(DWORD dwCount);

	BOOL     FreeXms();
	BOOL     RemallocXms(DWORD  dwCount);
	BOOL     RemallocXmsV3(DWORD dwCount);

	BOOL     LockXms(DWORD* pdwPhysicalLinerPoint = NULL);
    BOOL     UnlockXms();

    BOOL     Fill(char nCh);
    void     SetWrite(BOOL bWrite){m_bWrite = bWrite;}
    BOOL     GetWrite(){return(m_bWrite);}
protected:
    BOOL     CopyMemory(BYTE* pBuffer, DWORD dwCount, DWORD dwIndex, BOOL bConventionalToXms);
public:
    static BOOL     EnableA20();
    static BOOL     DisableA20();
public:
    BOOL     MallocHma(WORD wSize);
    BOOL     FreeHma();

    BOOL     MallocUmb(DWORD dwSize, WORD* pwUmbNumber);
	BOOL     FreeUmb(WORD wUmbNumber);
public:
	DWORD    GetSize(){return(m_dwSize);}
	BOOL     SetSize(DWORD dwSize, DWORD dwCount = 1)
    {
        return(this->MallocXms(1L * dwCount * dwSize));
    }

	BOOL     SetSizeEx(DWORD dwSize, DWORD dwCount = 1)
    {
        return(this->RemallocXms(1L * dwCount * dwSize));
    }

	BOOL 	 AddFile(const char* strFile, DWORD dwFileIndex,
		DWORD dwXmsIndex, DWORD* pdwLoadSize = NULL);

	BOOL 	 AddFile(FILE* pFile, DWORD dwFileIndex,
		DWORD dwXmsIndex, DWORD* pdwLoadSize = NULL);

	BOOL     LoadFile(const char *strFile, DWORD dwFileIndex = 0);

	BOOL     SaveFile(const char *strFile, DWORD dwFileIndex = 0);

	BOOL   MoveXmsMemory(DWORD dwTarget, DWORD dwSource, DWORD dwCount);
	BYTE*    GetPoint(DWORD dwIndex, int nCount = 1);

    BYTE     GetByteData(DWORD dwIndex);
	int      GetIntData(DWORD dwIndex);
	long     GetLongData(DWORD dwIndex);
	float    GetFloatData(DWORD dwIndex);
	double   GetDoubleData(DWORD dwIndex);

	BOOL     SetByteData(DWORD dwIndex,BYTE);
	BOOL     SetIntData(DWORD dwIndex,int);
	BOOL     SetLongData(DWORD dwIndex,long);
	BOOL     SetFloatData(DWORD dwIndex,float);
	BOOL     SetDoubleData(DWORD dwIndex,double);

	BYTE*    GetByteData(DWORD dwIndex, BYTE* pByte, DWORD dwCount);
	BOOL     SetByteData(DWORD dwIndex, BYTE* pByte, DWORD dwCount);

	BYTE*    ChangeFrame(BYTE* pFrame, WORD wFrameLength);
	void     ChangeFrameSize(WORD wSize);
    WORD      GetXmsPageLength(){return(m_wXmsPageLength);}
private:
    BOOL CoXmsMemory();
public:
	CXmsMemory();
    CXmsMemory(WORD wPageLength);
	~CXmsMemory();
};

class CXmsMemoryListingManager:public CXmsMemory
{
private:
    XMS_MEMORY_BLOCK1 m_XmsMemoryBlock1;
public:
	BOOL  m_bRecycleBin;
private:
	BOOL  ExpandSize(DWORD dwSize);

public:
	BOOL  RecycleBin();
	DWORD FindMallocNode(DWORD dwRow);

    BOOL  GetContext(DWORD dwLoc, XMS_MEMORY_BLOCK2* pXmsMemoryBlock2);

	BOOL  SetText(DWORD dwLoc, BYTE* pBuffer, DWORD dwSize);
	BOOL  SetTextEx(DWORD dwLoc, DWORD dwIndex, BYTE* pBuffer, DWORD dwSize);

	BYTE* GetText(DWORD dwLoc, BYTE* pBuffer, DWORD* pdwSize);
	BYTE* GetTextEx(DWORD dwLoc, DWORD dwIndex, BYTE* pBuffer, DWORD* pdwSize);

    void Display();
public:
	XMS_MEMORY_BLOCK1* GetControlBlock(){return(&m_XmsMemoryBlock1);}
    void  SetAutoRecycleBin(BOOL bRecycleBin) {m_bRecycleBin = bRecycleBin; }
	BOOL  GetAutoRecycleBin() {return(m_bRecycleBin);}

	BOOL  InitListing(DWORD dwSize);
	DWORD New(DWORD dwSize, BOOL bAuto = TRUE);
    BOOL  Delete(DWORD dwLoc);

	BOOL  RemoveNode(DWORD dwLoc);
	BOOL  InsertNode(DWORD dwLoc, DWORD dwInsert);

public:
	CXmsMemoryListingManager(DWORD dwSize);
	CXmsMemoryListingManager();
};

BOOL FAR InitEmsBuffer();
BOOL FAR CloseEmsBuffer();

CXmsMemory* GetFontXms();
BOOL ReadDateFromFontXms(DWORD dwIndex,int nCount,BYTE *pStr);
void SetFontXmsDirty(BOOL bFlags);
BOOL GetFontXmsDirty();
int  FAR AfxGetXmsStyle();
/***************************************/
#endif