Click here to Skip to main content
Click here to Skip to main content
Articles » Database » Database » General » Downloads
 
Add your own
alternative version

The alxBase classes for work with DBF files

, 5 Nov 2002
The alxBase classes for work with dbf files.
alxbasea2.zip
alxBASE
alxBASE.dsp
alxBASE.dsw
alxBaseDLL.dsp
DLL
INCLUDE
res
nodrop.cur
Lib
Samples
DBFView
DBFViewApp.clw
DBFViewApp.dep
DBFViewApp.dsp
DBFViewApp.dsw
Release
DBFView.exe
res
bitmap1.bmp
DBFViewApp.ico
DBFViewDoc.ico
Toolbar.bmp
SRC
alxbasea3.zip
alxBASE.dep
alxBASE.dsp
alxBASE.dsw
alxBASE.mak
alxBASE.suo
alxBaseDLL.dsp
l.rus
nodrop.cur
DBFViewApp.clw
DBFViewApp.dep
DBFViewApp.dsp
DBFViewApp.dsw
RCa00472
DBFView.exe
bitmap1.bmp
DBFViewApp.ico
DBFViewDoc.ico
Toolbar.bmp
// DBFTableDef.cpp : implementation of the CDBFTableDef class
//
/////////////////////////////////////////////////////////////////////////////
/*
�����:              �������� �.�.
����������:         alxsoft@gazinter.net
*/
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DBFTableDef.h"

#define MIN_DATE		(-657434L)  // about year 100
#define MAX_DATE		2958465L    // about year 9999

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//////////////////////////////////////////////////////////////////////////
// CDBFTableDef
IMPLEMENT_DYNAMIC(CDBFTableDef, CObject)

/* ����������� */
CDBFTableDef::CDBFTableDef()
{
	m_bOpen = FALSE;
	m_bNew = FALSE;
	m_nOpenFlag = ALX_DBF_USE_READ_ONLY | CFile::typeBinary;

	m_pMemoFile = NULL;

	memset(&m_DBFHead, 0, sizeof(m_DBFHead));

	m_pOldDBFHead = NULL;
	m_pOldDBFFields = NULL;
	m_pSwapFld = NULL;
}

/* ���������� */
CDBFTableDef::~CDBFTableDef()
{
	Close();

	// ����������� ���������� �������
	if(m_pOldDBFHead != NULL)
	{
		delete[] m_pOldDBFHead;
		m_pOldDBFHead = NULL;
	}
	if(m_pOldDBFFields != NULL)
	{
		if(m_pOldDBFFields->m_pFields != NULL)
			delete[] m_pOldDBFFields->m_pFields;
		delete m_pOldDBFFields;
		m_pOldDBFFields = NULL;
	}
	if(m_pSwapFld != NULL)
	{
		delete[] m_pSwapFld;
		m_pSwapFld = NULL;
	}
}

/* ��������� ������� */
void CDBFTableDef::Open(LPCTSTR lpszName, UINT nOpenFlag)
{
	ASSERT_VALID(this);
	ASSERT(lpszName != NULL);

	// ��������� ��� �������� ����
	m_nOpenFlag = nOpenFlag | CFile::typeBinary;

	CString strMemoFileExt;
	// Re-open is invalid
	if (IsOpen())
	{
		ASSERT(FALSE);
		return;
	}

	if(m_DBFFields.m_pFields != NULL)
		delete[] m_DBFFields.m_pFields;


TRY
{

	// ��������� ����
	DBF_CHECK_ERROR(
		m_DBFile.Open(lpszName, m_nOpenFlag), ALX_DBF_ERROR_DBFILE_OPEN);
	// ������ ���������
	DBF_CHECK_ERROR(
		m_DBFile.Read(&m_DBFHead, sizeof(m_DBFHead)) == sizeof(DBF_HEAD), ALX_DBF_ERROR_DBFHEADER_READ);
	// ��������� ���������
	DBF_CHECK_ERROR(
		m_DBFHead.rec_size > 1 && m_DBFHead.last_rec >= 0, ALX_DBF_ERROR_NOT_TABLE);
	// ��������� ������ �����
	DBF_CHECK_ERROR(
		m_DBFile.GetLength() - (m_DBFHead.data_offset + m_DBFHead.rec_size * m_DBFHead.last_rec) <= 1, ALX_DBF_ERROR_NOT_TABLE);

	// ��������� ���������� �����
	if(m_DBFHead.dbf_id == 0x30) // ���� FoxPro 3.0
	{
		m_DBFFields.m_nFieldCount = (m_DBFHead.data_offset - 296)/sizeof(FIELD_REC);

		// ������ ����, ��������� ����, 1 ����
		DBF_CHECK_ERROR(
			m_DBFFields.m_nFieldCount > 0, ALX_DBF_ERROR_NOT_FIELDS);

		// ��������� ������ �����
		DBF_CHECK_ERROR(
			m_DBFile.GetLength() >= (DWORD)(m_DBFHead.data_offset + (m_DBFHead.last_rec * m_DBFHead.rec_size)),
			ALX_DBF_ERROR_FILE_SIZE);

		m_DBFFields.m_pFields = new FIELD_REC[m_DBFFields.m_nFieldCount];

		// ������ ������ �����
		DBF_CHECK_ERROR(
			m_DBFile.Read((void*)m_DBFFields.m_pFields, (UINT)m_DBFFields.m_nFieldCount*sizeof(FIELD_REC)) == (UINT)m_DBFFields.m_nFieldCount*sizeof(FIELD_REC),
			ALX_DBF_ERROR_FIELDS_READ);
	}
	else
	{
		short nIndCurField = 0;
		short nFieldWidth;
		DBF_LONG lFldOffset = 1;
		BOOL bIsMoreFields = TRUE;
		short nFieldCount = (m_DBFHead.data_offset - sizeof(DBF_HEAD) - 1)/sizeof(FIELD_REC);
		FIELD_REC*	pFields = new FIELD_REC[nFieldCount];
		// ��� ������� ����
		while(bIsMoreFields && nIndCurField < nFieldCount)
		{
			// ��������� ���� ����
			if(m_DBFile.Read(&pFields[nIndCurField],sizeof(FIELD_REC)) != sizeof(FIELD_REC))
			{
				ASSERT(FALSE);
				delete[] pFields;
				ALXThrowDBFException(ALX_DBF_ERROR_FIELDS_READ);
			}
			if(bIsMoreFields)
			{
				// ��� ��������� ����
				bIsMoreFields = (pFields[nIndCurField].field_name[0] != 0x0D);
				if(bIsMoreFields)
				{
					// ���,  �������� ���� � ������
					switch(pFields[nIndCurField].field_type)
					{
					case FLD_TYPE_NUMERIC:
					case FLD_TYPE_CURRENCY:
					case FLD_TYPE_FLOAT:
					case FLD_TYPE_DOUBLE:
					case FLD_TYPE_INTEGER:
						nFieldWidth = pFields[nIndCurField].len_info.num_size.len;
						break;
					default:
						nFieldWidth = pFields[nIndCurField].len_info.char_len;
					}

					pFields[nIndCurField].field_offset = lFldOffset;
					lFldOffset = lFldOffset + nFieldWidth;
					nIndCurField++;
				}
			}
		}

		m_DBFFields.m_nFieldCount = nIndCurField;
		m_DBFFields.m_pFields = new FIELD_REC[m_DBFFields.m_nFieldCount];
		memcpy(m_DBFFields.m_pFields, pFields, m_DBFFields.m_nFieldCount*sizeof(FIELD_REC));
		delete[]pFields;
	}

	UINT nMemoType = 0;

	// ����� �� ���� ���� ���� ?
	switch(m_DBFHead.dbf_id)
	{
	case 0x30: // Visual FoxPro 3.0
		{
			if(m_DBFHead.table_flag & 0x02)
			{
				CString strFileExt = lpszName;
				strFileExt = strFileExt.Right(strFileExt.GetLength()  - strFileExt.ReverseFind('.'));
				strFileExt.MakeUpper();
				if(strFileExt == _T(".DBC"))
					nMemoType = MEMO_TYPE_FOX_DATABASE;
				else
					nMemoType = MEMO_TYPE_FOXPRO;

				m_pMemoFile = new CFPTMemoFile;
			}
			break;
		}
	case 0xE5:// SMT ����
		{
			nMemoType = MEMO_TYPE_SIX;
			m_pMemoFile = new CSMTMemoFile;
			break;
		}
	case 0xF5:// FPT ����
		{
			nMemoType = MEMO_TYPE_FOXPRO;
			m_pMemoFile = new CFPTMemoFile;
			break;
		}
	case 0x8B://DBT ���� dBASE IV
	case 0x7B://dBASE IV with memo 
	case 0xCB://DBT ���� dBASE IV SQL
		{
			nMemoType = MEMO_TYPE_DBASEIV;
			m_pMemoFile = new CDBTMemoFile;
			break;
		}
	case 0x83:// DBT ���� FoxBASE+/dBASE III PLUS
		{
			nMemoType = MEMO_TYPE_DBASE;
			m_pMemoFile = new CMemoFile;
			break;
		}
	}

	// ���� �����, ��������� ���� ����.
	if(nMemoType)
	{
		CString strMemoFileName = lpszName;
		CString strMemoFileExt = lpszName;
		switch(nMemoType)
		{
		case MEMO_TYPE_FOXPRO:
			strMemoFileExt = _T(".FPT");
			break;
		case MEMO_TYPE_FOX_DATABASE:
			strMemoFileExt = _T(".DCT");
			break;
		case MEMO_TYPE_SIX:
			strMemoFileExt = _T(".SMT");
			break;
		default:
			strMemoFileExt = _T(".DBT");
		}
		strMemoFileName = strMemoFileName.Left(strMemoFileName.ReverseFind('.')) + strMemoFileExt;
		// ��������� ���� ����
		m_pMemoFile->Open(strMemoFileName, nOpenFlag);

	}

	m_DBFFields.m_pCurRec = new DBF_CHAR[m_DBFHead.rec_size];
	memset(m_DBFFields.m_pCurRec, 0, m_DBFHead.rec_size);

	m_bOpen = TRUE;
}
CATCH(CFileException, e)
{
	e->ReportError();
	e->Delete();
	Close();
}
END_CATCH

}

/* ��������� ������� */
void CDBFTableDef::Close()
{
	if(m_bOpen || m_bNew)
	{
		m_DBFile.Close();
		if(m_pMemoFile != NULL)
		{
			if(m_pMemoFile->IsOpen())
				m_pMemoFile->Close();

			switch(m_pMemoFile->GetMemoFileType())
			{
			case MEMO_TYPE_FOXPRO: case MEMO_TYPE_FOX_DATABASE:
				delete (CFPTMemoFile*) m_pMemoFile;
				break;
			case MEMO_TYPE_DBASEIV:
				delete (CDBTMemoFile*) m_pMemoFile;
				break;
			case MEMO_TYPE_SIX:
				delete (CSMTMemoFile*) m_pMemoFile;
				break;
			case MEMO_TYPE_DBASE:
				delete (CMemoFile*) m_pMemoFile;
				break;
			default:
				{
					ASSERT(FALSE);
					delete m_pMemoFile;
				}
			}

			m_pMemoFile = NULL;
		}

	}

	m_bOpen = FALSE;
	m_bNew = FALSE;


	if(m_DBFFields.m_pFields != NULL)
	{
		if(m_DBFFields.m_pCurRec != NULL)
			delete[] m_DBFFields.m_pCurRec;

		delete[] m_DBFFields.m_pFields;
	}

	m_DBFFields.m_pFields = NULL;
}

/* ������� ���������� ��� ������� */
CString CDBFTableDef::GetName()
{
	return m_DBFile.GetFileName();
}

/* ������� ���������� ������ ���� � DBF ����� */
CString CDBFTableDef::GetDBFilePath()
{
	return m_DBFile.GetFilePath();
}

/* ���� �������� ������� */
CTime CDBFTableDef::GetDateCreated()
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	CFileStatus fStatus;
	m_DBFile.GetStatus(fStatus);

	return fStatus.m_ctime;
}

/* ���� ��������� ����������� ������� */
CTime CDBFTableDef::GetDateLastUpdated()
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	return CTime(ALX_DBF_CENTURY + m_DBFHead.last_update[0],m_DBFHead.last_update[1],m_DBFHead.last_update[2]);
}

/* ���-�� ������� � ������� */
long CDBFTableDef::GetRecordCount()
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	return m_DBFHead.last_rec;
}

/* ���-�� ����� � ������� */
short CDBFTableDef::GetFieldCount()
{
	ASSERT_VALID(this);

	return m_DBFFields.m_nFieldCount;
}

/* ������ ������ */
void CDBFTableDef::ReadRecord(long lRecNumber, void* lpBuffer)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());
	ASSERT(lpBuffer != NULL);
	ASSERT(lRecNumber < GetRecordCount());

TRY
{
	m_DBFile.Seek(m_DBFHead.data_offset + m_DBFHead.rec_size * lRecNumber, CFile::begin);
	// ������ ������
	int nRead = m_DBFile.Read(lpBuffer, m_DBFHead.rec_size);

	if(nRead != m_DBFHead.rec_size)
	{
		long lOffset = m_DBFHead.data_offset + m_DBFHead.rec_size * lRecNumber;
		if(lOffset < sizeof(DBF_HEAD) || lOffset + m_DBFHead.rec_size > (long)m_DBFile.GetLength())
			ALXThrowDBFException(ALX_DBF_ERROR_RECORD_OUTOFRANGE);
		else
			ALXThrowDBFException(ALX_DBF_ERROR_RECORD_READ);
	}
}
CATCH(CFileException, e)
{
	memset(&lpBuffer,'\0', m_DBFHead.rec_size);

	e->ReportError();
	e->Delete();

	ALXThrowDBFException(ALX_DBF_ERROR_RECORD_READ);

} END_CATCH

}

/* ���������� ������ */
void CDBFTableDef::WriteRecord(long lRecNumber, void* lpBuffer)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());
	ASSERT(lpBuffer != NULL);
	ASSERT(lRecNumber < GetRecordCount());

TRY
{
	m_DBFile.Seek(m_DBFHead.data_offset + m_DBFHead.rec_size * lRecNumber, CFile::begin);
	// ���������� ������
	m_DBFile.Write(lpBuffer, m_DBFHead.rec_size);

}
CATCH(CFileException, e)
{
	e->ReportError();
	e->Delete();

	ALXThrowDBFException(ALX_DBF_ERROR_RECORD_WRITE);

} END_CATCH

}

/* ������ ��������� ������� */
BOOL CDBFTableDef::ReadHeader()
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

TRY
{
	m_DBFile.Seek(0, CFile::begin);
	// ������ ���������
	if(m_DBFile.Read(&m_DBFHead, sizeof(m_DBFHead)) == sizeof(DBF_HEAD))
		return TRUE;
}
CATCH(CFileException, e)
{
	e->ReportError();
	e->Delete();

	ALXThrowDBFException(ALX_DBF_ERROR_DBFHEADER_WRITE);

} END_CATCH

	return FALSE;
}

/* ���������� ��������� ������� */
void CDBFTableDef::WriteHeader()
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

TRY
{
	m_DBFile.Seek(0, CFile::begin);
	// ���������� ���������
	m_DBFile.Write(&m_DBFHead, sizeof(m_DBFHead));
}
CATCH(CFileException, e)
{
	e->ReportError();
	e->Delete();

	ALXThrowDBFException(ALX_DBF_ERROR_DBFHEADER_WRITE);

} END_CATCH

}

/* ������ ���� ���� */
void CDBFTableDef::ReadMemoRecord(DBF_ULONG lOffsetRec, DBF_LONG& nLen, CString& strMemo)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	if(m_pMemoFile != NULL)
		m_pMemoFile->ReadMemoRecord(lOffsetRec, nLen, strMemo);
}

/* ������ ���� ���� */
void CDBFTableDef::ReadMemoRecord(DBF_ULONG lOffsetRec, DBF_LONG& nLen, unsigned char** pMemoData)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	if(m_pMemoFile != NULL)
		m_pMemoFile->ReadMemoRecord(lOffsetRec, nLen, pMemoData);
}

/* ���������� ���� ���� */
void CDBFTableDef::WriteMemoRecord(DBF_ULONG& lOffsetRec, DBF_LONG& nLen, CString& strMemo)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	if(m_pMemoFile != NULL)
		m_pMemoFile->WriteMemoRecord(lOffsetRec, nLen, strMemo);
}

#ifdef _DEBUG
void CDBFTableDef::AssertValid() const
{
	CObject::AssertValid();
}

void CDBFTableDef::Dump(CDumpContext& dc) const
{
	ASSERT_VALID(this);

	CObject::Dump(dc);

	dc << "m_bOpen = " << m_bOpen;
	dc << "\nm_bNew = " << m_bNew;

	dc << "\n";
}
#endif //_DEBUG

// CDBFTableDef inlines
inline BOOL CDBFTableDef::IsOpen() const
	{ ASSERT_VALID(this); return m_bOpen; }


/* ��������� ���� � ������� */
void CDBFTableDef::AddField(FIELD_REC *pFieldRec)
{
	ASSERT(m_nEditMode != noMode);

	if(m_DBFFields.m_nFieldCount > 0)
	{
		// ��������� ������� �������� �����
		FIELD_REC*	pFields = new FIELD_REC[m_DBFFields.m_nFieldCount];
		// �������� ������ �����
		memcpy(pFields, m_DBFFields.m_pFields, sizeof(FIELD_REC)*m_DBFFields.m_nFieldCount);
		// ����������� ������
		delete[] m_DBFFields.m_pFields;
		// ����������� �������
		m_DBFFields.m_pFields = new FIELD_REC[m_DBFFields.m_nFieldCount+1];
		// �������� ������ ����
		memcpy(m_DBFFields.m_pFields, pFields, sizeof(FIELD_REC)*m_DBFFields.m_nFieldCount);
		// �������� ����� ����
		memcpy(&m_DBFFields.m_pFields[m_DBFFields.m_nFieldCount], pFieldRec, sizeof(FIELD_REC));
		// �������� ����� ���������� �����
		m_DBFFields.m_nFieldCount++;
		// ����������� ��������� ������
		delete[] pFields;
		// ���� ����������� �������
		if(m_nEditMode == modify) // �������� ������ ������������ �����
		{	// �������� ��������� ������
			DBF_INT* pTmpSwapFld = new DBF_INT[m_DBFFields.m_nFieldCount-1];
			// ��������� ������
			memcpy(pTmpSwapFld, m_pSwapFld, sizeof(DBF_INT)*(m_DBFFields.m_nFieldCount-1));
			delete[] m_pSwapFld;
			m_pSwapFld = new DBF_INT[m_DBFFields.m_nFieldCount];
			memcpy(m_pSwapFld, pTmpSwapFld, sizeof(DBF_INT)*(m_DBFFields.m_nFieldCount-1));
			// ����������� �������� ������ ��������
			m_pSwapFld[m_DBFFields.m_nFieldCount-1] = -1; // ��� ���� � ������ ��������� �����. ������ ����
			delete[] pTmpSwapFld;
		}
	}
	else
	{
		// �������� ������
		m_DBFFields.m_pFields = new FIELD_REC[1];
		// �������� ����� ����
		memcpy(m_DBFFields.m_pFields, pFieldRec, sizeof(FIELD_REC));
		// �������� ����� ���������� �����
		m_DBFFields.m_nFieldCount = 1;
		// ���� ����������� �������
		if(m_nEditMode == modify)
		{	// �������� ������ ������������ �����
			m_pSwapFld = new DBF_INT[1];
			m_pSwapFld[0] = -1;
		}
	}
}

/* ��������� ���� � ������� */
void CDBFTableDef::InsertField(short nIndex, FIELD_REC *pFieldRec)
{
	ASSERT(m_nEditMode != noMode);
	ASSERT(nIndex < m_DBFFields.m_nFieldCount);

	if(m_DBFFields.m_nFieldCount > 0)
	{
		// ��������� ������� �������� �����
		FIELD_REC*	pFields = new FIELD_REC[m_DBFFields.m_nFieldCount];
		// �������� ������ �����
		memcpy(pFields, m_DBFFields.m_pFields, sizeof(FIELD_REC)*m_DBFFields.m_nFieldCount);
		// ����������� ������
		delete[] m_DBFFields.m_pFields;
		// ����������� �������
		m_DBFFields.m_pFields = new FIELD_REC[m_DBFFields.m_nFieldCount+1];
		// �������� ������ ����
		memcpy(m_DBFFields.m_pFields, pFields, sizeof(FIELD_REC)*nIndex);
		memcpy(&m_DBFFields.m_pFields[nIndex+1], &pFields[nIndex], sizeof(FIELD_REC)*(m_DBFFields.m_nFieldCount-nIndex));
		// �������� ����� ����
		memcpy(&m_DBFFields.m_pFields[nIndex], pFieldRec, sizeof(FIELD_REC));
		// �������� ����� ���������� �����
		m_DBFFields.m_nFieldCount++;
		// ����������� ��������� ������
		delete[] pFields;
		// ���� ����������� �������
		if(m_nEditMode == modify) // �������� ������ ������������ �����
		{	// �������� ��������� ������	
			DBF_INT* pTmpSwapFld = new DBF_INT[m_DBFFields.m_nFieldCount-1];
			// ��������� ������
			memcpy(pTmpSwapFld, m_pSwapFld, sizeof(DBF_INT)*(m_DBFFields.m_nFieldCount-1));
			// ����������� ������
			delete[] m_pSwapFld;
			// �������� ������ ������ �������
			m_pSwapFld = new DBF_INT[m_DBFFields.m_nFieldCount];
			// ��������������� ����������� ��������
			memcpy(m_pSwapFld, pTmpSwapFld, sizeof(DBF_INT)*nIndex);
			memcpy(&m_pSwapFld[nIndex+1], &pTmpSwapFld[nIndex], sizeof(DBF_INT)*(m_DBFFields.m_nFieldCount-1-nIndex));
			m_pSwapFld[nIndex] = -1;
			delete[] pTmpSwapFld;
		}
	}
	else
	{
		// �������� ������
		m_DBFFields.m_pFields = new FIELD_REC[1];
		// �������� ����� ����
		memcpy(m_DBFFields.m_pFields, pFieldRec, sizeof(FIELD_REC));
		// �������� ����� ���������� �����
		m_DBFFields.m_nFieldCount = 1;
		// ���� ����������� �������
		if(m_nEditMode == modify)
		{	// �������� ������ ������������ �����
			m_pSwapFld = new DBF_INT[1];
			m_pSwapFld[0] = -1;
		}
	}
}

/* ������� ���� �� ������� */
void CDBFTableDef::DeleteField(short nIndex)
{
	ASSERT(m_nEditMode != noMode);
	ASSERT(nIndex < m_DBFFields.m_nFieldCount);

	if(m_DBFFields.m_nFieldCount > 1)
	{
		// ��������� ������� �������� �����
		FIELD_REC*	pFields = new FIELD_REC[m_DBFFields.m_nFieldCount];
		// �������� ������ �����
		memcpy(pFields, m_DBFFields.m_pFields, sizeof(FIELD_REC)*m_DBFFields.m_nFieldCount);
		// ����������� ������
		delete[] m_DBFFields.m_pFields;
		// �������� �������
		m_DBFFields.m_pFields = new FIELD_REC[m_DBFFields.m_nFieldCount-1];
		// �������� ������ ����
		memcpy(m_DBFFields.m_pFields, pFields, sizeof(FIELD_REC)*nIndex);
		memcpy(&m_DBFFields.m_pFields[nIndex], &pFields[nIndex+1], sizeof(FIELD_REC)*(m_DBFFields.m_nFieldCount-nIndex-1));
		// �������� ����� ���������� �����
		m_DBFFields.m_nFieldCount--;
		// ����������� ��������� ������
		delete[] pFields;
		// ���� ����������� �������
		if(m_nEditMode == modify) // �������� ������ ������������ �����
		{	// �������� ��������� ������	
			DBF_INT* pTmpSwapFld = new DBF_INT[m_DBFFields.m_nFieldCount+1];
			// ��������� ������
			memcpy(pTmpSwapFld, m_pSwapFld, sizeof(DBF_INT)*(m_DBFFields.m_nFieldCount+1));
			// ����������� ������
			delete[] m_pSwapFld;
			// �������� ������ ������ �������
			m_pSwapFld = new DBF_INT[m_DBFFields.m_nFieldCount];
			// ��������������� ����������� ��������
			memcpy(m_pSwapFld, pTmpSwapFld, sizeof(DBF_INT)*nIndex);
			memcpy(&m_pSwapFld[nIndex], &pTmpSwapFld[nIndex+1], sizeof(DBF_INT)*(m_DBFFields.m_nFieldCount+1-nIndex-1));
			delete[] pTmpSwapFld;
		}
	}
	else
	{
		// ����������� ������
		delete[] m_DBFFields.m_pFields;
		m_DBFFields.m_pFields = NULL;
		// �������� ����� ���������� �����
		m_DBFFields.m_nFieldCount = 0;
		// ���� ����������� �������
		if(m_nEditMode == modify)
		{	// �������� ������ ������������ �����
			delete[] m_pSwapFld;
			m_pSwapFld = NULL;
		}
	}
}

/* ��������� ��������� � ������� */
void CDBFTableDef::UpdateTable()
{
	ASSERT_VALID(this);
	ASSERT(m_nEditMode != noMode);
	ASSERT(m_DBFFields.m_nFieldCount > 0);

	DBF_LONG field_offset = 1;
	// ���������� ��� ����
	for(short j = 0; j < m_DBFFields.GetFieldCount(); j++)
	{
		m_DBFFields.m_pFields[j].field_offset = field_offset;
		// ��������� �������� �� ���������� ����
		switch(m_DBFFields.m_pFields[j].field_type)
		{
		case FLD_TYPE_NUMERIC:
		case FLD_TYPE_FLOAT:
		case FLD_TYPE_CURRENCY:
		case FLD_TYPE_DATETIME:
		case FLD_TYPE_INTEGER:
		case FLD_TYPE_DOUBLE:
			field_offset = field_offset + m_DBFFields.m_pFields[j].len_info.num_size.len;
			break;
		default:
				field_offset = field_offset + m_DBFFields.m_pFields[j].len_info.char_len;
		}
	}

	// ��������� �������� �� ������
	m_DBFHead.data_offset = sizeof(DBF_HEAD) + sizeof(FIELD_REC) * m_DBFFields.GetFieldCount() + 1;
	if(m_DBFHead.dbf_id == 0x30)
		m_DBFHead.data_offset += 263;

	// ���������� ������ ����
	m_DBFHead.rec_size = (DBF_UINT)field_offset;

	CFile *pFileNew, *pFileOld;

	if(m_nEditMode == modify)
	{
		pFileNew = new CFile;
		pFileOld = &m_DBFile;

		// �������� ��� ���������� �����
		CString strTmpPath;
		strTmpPath = m_DBFile.GetFilePath();
		int i = strTmpPath.ReverseFind('.');
		if(i >= 0) strTmpPath = strTmpPath.Left(i);
		strTmpPath = strTmpPath + _T("._tmp");

		CFileFind mFileFind; // ������� ������ ��������� ����, ���� ����� ����
		if(mFileFind.FindFile(strTmpPath))
			CFile::Remove(strTmpPath);

		// ������� ��������� ����
		DBF_CHECK_ERROR(
			pFileNew->Open(strTmpPath, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive), ALX_DBF_ERROR_DBFILE_CREATE);
	}
	else
		pFileNew = &m_DBFile;


	// ���������� ���������
	pFileNew->Write(&m_DBFHead, sizeof(m_DBFHead));
	// ���������� ������ �����
	for(j = 0; j < m_DBFFields.GetFieldCount(); j++)
		pFileNew->Write(&m_DBFFields.m_pFields[j], sizeof(FIELD_REC));
	// ������ ������������ ����� ���������� � �������
	int nEmptySpace = m_DBFHead.data_offset - (sizeof(m_DBFHead) + sizeof(FIELD_REC) * m_DBFFields.GetFieldCount());
	if(nEmptySpace > 0)
	{
		DBF_CHAR* fill = new DBF_CHAR[nEmptySpace];
		memset(fill,'\0',nEmptySpace); // ��������� ������
		fill[0] = 0x0D; // ������� ����������
		pFileNew->Write(fill, nEmptySpace); // ����������
		delete[] fill;
	}

	if(m_nEditMode == modify)
	{
		DBF_CHAR* pOldRec = new DBF_CHAR[m_pOldDBFHead->rec_size];
		DBF_CHAR* pNewRec = new DBF_CHAR[m_DBFHead.rec_size];
		pFileOld->Seek(m_pOldDBFHead->data_offset, CFile::begin);
		pFileNew->Seek(m_DBFHead.data_offset, CFile::begin);
		// ������� �������
		for(long i = 0; i < m_pOldDBFHead->last_rec; i++)
		{
			pFileOld->Read(pOldRec, m_pOldDBFHead->rec_size);
			memset(pNewRec, ' ', m_DBFHead.rec_size);
			pNewRec[0] = pOldRec[0];
			// ���������� ����
			for(int j = 0; j < m_DBFFields.GetFieldCount(); j++)
			{
				COleVariant varValue;
				if(m_pSwapFld[j] >= 0)
					alxGetFieldValue(pOldRec, m_pOldDBFFields->GetFieldRec(m_pSwapFld[j]), varValue);
				alxSetFieldValue(pNewRec, m_DBFFields.GetFieldRec(j), varValue);
			}
			pFileNew->Write(pNewRec, m_DBFHead.rec_size);
		}
		delete[] pOldRec;
		delete[] pNewRec;

		delete[] m_pOldDBFHead;
		m_pOldDBFHead = NULL;
		delete[] m_pOldDBFFields->m_pFields;
		delete m_pOldDBFFields;
		m_pOldDBFFields = NULL;
		delete[] m_pSwapFld;
		m_pSwapFld = NULL;
	}

	char eof = REC_EOF;
	pFileNew->Write(&eof, 1);

	// �������� ������ �����
	pFileNew->SetLength(m_DBFHead.data_offset + m_DBFHead.last_rec * m_DBFHead.rec_size + 1);

	if(m_nEditMode == modify)
	{
		// ��������������� ��������� ���� � ���., � ���. � .bak
		CString strNewPath = pFileNew->GetFilePath(); 
		CString strOldPath = pFileOld->GetFilePath(); 
		CString strBakPath = pFileOld->GetFilePath();
		int i = strBakPath.ReverseFind('.');
		if(i >= 0) strBakPath = strBakPath.Left(i);
		strBakPath = strBakPath + _T(".bak");

		pFileOld->Close();
		pFileNew->Close();
		delete pFileNew;
		
		CFileFind mFileFind;
		if(mFileFind.FindFile(strBakPath))
			CFile::Remove(strBakPath);
		CFile::Rename(strOldPath, strBakPath);
		CFile::Rename(strNewPath, strOldPath);

		// ��������� ����
		DBF_CHECK_ERROR(
			m_DBFile.Open(strOldPath, m_nOpenFlag), ALX_DBF_ERROR_DBFILE_OPEN);

	}

	m_nEditMode = noMode;

	m_bNew = TRUE;

}

/* ������� ����� ������� */
BOOL CDBFTableDef::CreateTable(LPCTSTR lpszName)
{
	ASSERT_VALID(this);
	ASSERT(lpszName != NULL);
	ASSERT(!IsOpen());

	m_nOpenFlag = CFile::shareExclusive | CFile::modeReadWrite | CFile::typeBinary;

	if(m_DBFFields.m_pFields != NULL)
		delete[] m_DBFFields.m_pFields;
	m_DBFFields.m_pFields = NULL;

TRY
{
	// ������� ����
	DBF_CHECK_ERROR(
		m_DBFile.Open(lpszName, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive), ALX_DBF_ERROR_DBFILE_CREATE);

	COleDateTime curDate = COleDateTime::GetCurrentTime();
	memset(&m_DBFHead, 0, sizeof(DBF_HEAD));
	m_DBFHead.dbf_id = 0x03; // dBASE III // dBase IV
	m_DBFHead.last_update[0] = curDate.GetYear() - ALX_DBF_CENTURY;
	m_DBFHead.last_update[1] = curDate.GetMonth();
	m_DBFHead.last_update[2] = curDate.GetDay();
	m_DBFHead.last_rec = 0;
	m_DBFHead.data_offset = sizeof(DBF_HEAD) + 1;
	m_DBFHead.rec_size = 0;

	m_DBFFields.m_nFieldCount = 0;
	m_nEditMode = create;

	return TRUE;
}
CATCH(CFileException, e)
{

	e->ReportError();
	e->Delete();
	Close();
}
END_CATCH

	return FALSE;
}

/* ����������� ������� */
void CDBFTableDef::ModifyTable()
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	// ��������� ������� ��������� �������
	m_pOldDBFHead = new DBF_HEAD;
	memcpy(m_pOldDBFHead, &m_DBFHead, sizeof(DBF_HEAD));

	// ��������� ������� ��������� ����� �� ��������� �������
	m_pOldDBFFields = new CDBFFields;
	m_pOldDBFFields->m_pFields = new FIELD_REC[m_DBFFields.m_nFieldCount];
	memcpy(m_pOldDBFFields->m_pFields, m_DBFFields.m_pFields, sizeof(FIELD_REC) * m_DBFFields.m_nFieldCount);
	m_pOldDBFFields->m_nFieldCount = m_DBFFields.m_nFieldCount;
	m_pOldDBFFields->m_pCurRec = m_DBFFields.m_pCurRec;

	// �������� ������ ��� ������ ������������ ������ � ����� �����
	m_pSwapFld = new DBF_INT[m_DBFFields.m_nFieldCount];
	for(short i = 0; i < m_DBFFields.m_nFieldCount; i++)
		m_pSwapFld[i] = i; // ������ ������ ���� �����. ������� �������

	COleDateTime curDate = COleDateTime::GetCurrentTime();
	m_DBFHead.last_update[0] = curDate.GetYear() - ALX_DBF_CENTURY;
	m_DBFHead.last_update[1] = curDate.GetMonth();
	m_DBFHead.last_update[2] = curDate.GetDay();

	m_nEditMode = modify;

	return;
}

/* �������� ���� ������� */
void CDBFTableDef::ModifyField(short nIndex, FIELD_REC *pFieldRec)
{
	ASSERT(m_nEditMode != noMode);
	ASSERT(nIndex < m_DBFFields.m_nFieldCount);

	m_DBFFields.m_pFields[nIndex] = *pFieldRec;
}

/* ���������� ���� ������� �� ����� ������� */
void CDBFTableDef::MoveField(short nIndex, short nNewIndex)
{
	ASSERT(m_nEditMode != noMode);
	ASSERT(nIndex < m_DBFFields.m_nFieldCount);
	ASSERT(nNewIndex < m_DBFFields.m_nFieldCount);

	while(nIndex > nNewIndex)
	{
		FIELD_REC FieldRec = m_DBFFields.m_pFields[nIndex];
		m_DBFFields.m_pFields[nIndex] = m_DBFFields.m_pFields[nIndex - 1];
		m_DBFFields.m_pFields[nIndex - 1] = FieldRec;

		if(m_nEditMode == modify)
		{
			DBF_INT iSwapFld = m_pSwapFld[nIndex];
			m_pSwapFld[nIndex] = m_pSwapFld[nIndex - 1];
			m_pSwapFld[nIndex - 1] = iSwapFld;
		}

		nIndex--;
	}
	while(nIndex < nNewIndex)
	{
		FIELD_REC FieldRec = m_DBFFields.m_pFields[nIndex];
		m_DBFFields.m_pFields[nIndex] = m_DBFFields.m_pFields[nIndex + 1];
		m_DBFFields.m_pFields[nIndex + 1] = FieldRec;

		if(m_nEditMode == modify)
		{
			DBF_INT iSwapFld = m_pSwapFld[nIndex];
			m_pSwapFld[nIndex] = m_pSwapFld[nIndex + 1];
			m_pSwapFld[nIndex + 1] = iSwapFld;
		}
		nIndex++;
	}

}

/* ����� �� ��������� ��������� � ��������� ������� */
void CDBFTableDef::CancelUpdateTable()
{
	ASSERT(m_nEditMode != noMode);

	if(m_nEditMode == modify)
	{
		memcpy(&m_DBFHead, m_pOldDBFHead, sizeof(DBF_HEAD));

		memcpy(m_DBFFields.m_pFields, m_pOldDBFFields->m_pFields, sizeof(FIELD_REC) * m_pOldDBFFields->m_nFieldCount);
		m_DBFFields.m_nFieldCount = m_pOldDBFFields->m_nFieldCount;
		m_DBFFields.m_pCurRec = m_pOldDBFFields->m_pCurRec;
	}
	else
	{
		if(m_DBFile.GetLength() == 0)
		{
			CString strFilePath = m_DBFile.GetFilePath();
			m_DBFile.Close();
			::DeleteFile(strFilePath);
		}
		else
			m_DBFile.Close();
	}

	if(m_pOldDBFHead != NULL)
	{
		delete[] m_pOldDBFHead;
		m_pOldDBFHead = NULL;
	}
	if(m_pOldDBFFields != NULL)
	{
		if(m_pOldDBFFields->m_pFields != NULL)
			delete[] m_pOldDBFFields->m_pFields;
		delete m_pOldDBFFields;
		m_pOldDBFFields = NULL;
	}
	if(m_pSwapFld != NULL)
	{
		delete[] m_pSwapFld;
		m_pSwapFld = NULL;
	}
}

/* ������� ���������� �������� ���� �� ������ ������ */
long alxGetFieldValue(DBF_CHAR* pRec, FIELD_REC* pFieldRec, COleVariant& varValue)
{
	// Clear out variant
	varValue.Clear();
	varValue.vt = VT_EMPTY;

	long lLen;
	long nOffset = pFieldRec->field_offset;
	// � ����������� �� ���� ����
	switch(pFieldRec->field_type)
	{
	case FLD_TYPE_CHARACTER:
		{
			CString strValue;
			lLen = pFieldRec->len_info.char_len;
			// �������� ������ ��� ����
			char* buffer = strValue.GetBuffer(lLen + 1);
			// �������� ���������� ���� � �����
			memcpy(buffer, &pRec[nOffset], lLen);
			buffer[lLen] = '\0';
			strValue.ReleaseBuffer(lLen + 1);
			if(pFieldRec->field_flag != FLD_FLAG_BINARY)
				strValue.TrimRight();
			varValue = strValue;
			break;
		}
	case FLD_TYPE_NUMERIC:
	case FLD_TYPE_FLOAT:
		{
			lLen = pFieldRec->len_info.num_size.len;
			// �������� ������ ��� ����
			char* buffer = new char[ lLen + 1 ];
			// �������� ���������� ���� � �����
			memcpy(buffer, &pRec[nOffset], lLen);
			buffer[lLen] = '\0';
			varValue.dblVal = atof(buffer);
			varValue.vt = VT_R8;
			delete[] buffer;
			break;
		}
	case FLD_TYPE_DATE:
		{
			unsigned int nYear;
			unsigned char bMonth, bDay;
			lLen = pFieldRec->len_info.char_len;
			// �������� ������ ��� ����
			char* buffer = new char[ 5 ];

			memcpy(buffer, &pRec[nOffset], 4);
			buffer[4] = '\0';
			nYear = atoi(buffer);
			memcpy(buffer, &pRec[nOffset+4], 2);
			buffer[2] = '\0';
			bMonth = atoi(buffer);
			memcpy(buffer, &pRec[nOffset+6], 2);
			buffer[2] = '\0';
			bDay = atoi(buffer);

			delete[] buffer;

			COleDateTime dteValue(nYear,bMonth,bDay,0,0,0);
			if(dteValue.GetStatus() == COleDateTime::valid)
				varValue = dteValue;
			break;
		}
	case FLD_TYPE_LOGICAL:
		{
			DBF_UCHAR chValue;
			lLen = pFieldRec->len_info.char_len;
			memcpy(&chValue, &pRec[nOffset], sizeof(DBF_UCHAR));
			if(chValue == 'T' || chValue == 't' ||chValue == 'Y' || chValue == 'y')
				varValue.boolVal = TRUE;
			else
				varValue.boolVal = FALSE;
			varValue.vt = VT_BOOL;
			break;
		}
	case FLD_TYPE_CURRENCY:
		{
			lLen = pFieldRec->len_info.num_size.len;
			memcpy(&varValue.cyVal, &pRec[nOffset], sizeof(varValue.cyVal));
			varValue.vt = VT_CY;
			break;
		}
	case FLD_TYPE_DATETIME:
		{
			COleDateTime dteValue(1,1,1,0,0,0);
			lLen = pFieldRec->len_info.char_len;
			long lDay,lHour, lMin, lSec;
			memcpy(&lDay, &pRec[nOffset], sizeof(lDay));
			memcpy(&lSec, &pRec[nOffset+4], sizeof(lSec));
			if(lDay >= 0x1A4452)
			{
				lDay = lDay - 0x1A4452;
				lSec = (lSec + 1) / 1000;
				lHour = lSec / 60 / 60;
				lSec = lSec - lHour * 60 * 60;
				lMin = lSec / 60;
				lSec = lSec - lMin * 60;

				COleDateTimeSpan dteSpan(lDay,lHour,lMin,lSec);
				dteValue = dteValue + dteSpan;
				varValue = dteValue;
			}
			break;
		}
	case FLD_TYPE_INTEGER:
		{
			lLen = pFieldRec->len_info.num_size.len;
			memcpy(&varValue.lVal, &pRec[nOffset], sizeof(varValue.lVal));
			varValue.vt = VT_I4;
			break;
		}
	case FLD_TYPE_DOUBLE: // �������� FLD_TYPE_BINARY
		{
			lLen = pFieldRec->len_info.num_size.len;
			// ���� FLD_TYPE_DOUBLE
			if(lLen == sizeof(DBF_DOUBLE))
			{
				memcpy(&varValue.dblVal, &pRec[nOffset], sizeof(varValue.dblVal));
				varValue.vt = VT_R8;
				break;
			}
		}
	case FLD_TYPE_MEMO:
		{
			lLen = pFieldRec->len_info.num_size.len;
			// ���� ����� ������� � ������� SIX (��������� ���� ���� 0x0800)
			if(lLen == 10 && pRec[nOffset] <= 0x08 && pRec[nOffset+1] == 0x00)
			{
				memcpy(&varValue.decVal.Hi32, &pRec[nOffset+2], sizeof(varValue.decVal.Hi32));
				memcpy(&varValue.decVal.Lo32, &pRec[nOffset+6], sizeof(varValue.decVal.Lo32));
				varValue.vt = VT_DECIMAL;
				break;
			}
		}
	case FLD_TYPE_GENERAL:
	case FLD_TYPE_PICTURE:
		{
			lLen = pFieldRec->len_info.num_size.len;
			if(lLen == sizeof(DBF_ULONG))
				memcpy(&varValue.ulVal, &pRec[nOffset], sizeof(varValue.ulVal));
			else if(lLen == 10)
			{
				char* buffer = new char[11];
				memcpy(buffer, &pRec[nOffset], lLen);
				buffer[lLen] = '\0';
				varValue.ulVal = atol(buffer);
				delete[] buffer;
			}
			varValue.vt = VT_UI4;
			break;
		}
	case FLD_TYPE_NULLFLAGS:
		{
			lLen = pFieldRec->len_info.num_size.len;
			varValue.ulVal = 0;
			memcpy(&varValue.ulVal, &pRec[nOffset], lLen);
			varValue.vt = VT_UI4;
			break;
		}
	default:
		{
			CString strValue;
			lLen = pFieldRec->len_info.num_size.len;
			// �������� ������ ��� ����
			char* buffer = strValue.GetBuffer(lLen + 1);
			// �������� ���������� ���� � �����
			memcpy(buffer, &pRec[nOffset], lLen);
			buffer[lLen] = '\0';
			strValue.ReleaseBuffer(lLen + 1);

			varValue = strValue;
		}
	}

	return lLen;
}

/* ������� ���������� �������� ���� � ����� ������ */
void alxSetFieldValue(DBF_CHAR* pRec, FIELD_REC* pFieldRec, const COleVariant& var)
{
	long lLen;
	long nOffset = pFieldRec->field_offset;
	COleVariant varValue = var;
	// � ����������� �� ���� ����
	switch(pFieldRec->field_type)
	{
	case FLD_TYPE_CHARACTER:
		{
			lLen = pFieldRec->len_info.char_len;
			memset(&pRec[nOffset],' ',lLen);
			if(varValue.vt != VT_NULL)
				varValue.ChangeType(VT_BSTR);
			// � ����������� �� ���� ��������
			if(varValue.vt == VT_BSTR)
			{
				CString strValue = varValue.bstrVal;
				strncpy(&pRec[nOffset], strValue, min(strValue.GetLength(),lLen));
			}
			break;
		}
	case FLD_TYPE_NUMERIC:
	case FLD_TYPE_FLOAT:
		{
			CString strValue,strFormat;
			lLen = pFieldRec->len_info.num_size.len;
			DBF_CHAR bDec = pFieldRec->len_info.num_size.dec;
			memset(&pRec[nOffset],' ',lLen);
			if(varValue.vt != VT_NULL)
				varValue.ChangeType(VT_R8);
			// � ����������� �� ���� ��������
			if(varValue.vt == VT_R8)
			{
				CString strFormat;
				strFormat.Format("%s.%uf","%",bDec);
				strValue.Format(strFormat,varValue.dblVal);
			}

			if(strValue.GetLength() > lLen)
			{
				if(strValue.GetAt(lLen) == '.')
					strValue = ' ' + strValue;
				strValue = strValue.Left(lLen);
			}

			strncpy(&pRec[nOffset + (lLen - strValue.GetLength())], strValue, strValue.GetLength());

			break;
		}
	case FLD_TYPE_DATE:
		{
			lLen = pFieldRec->len_info.char_len;
			COleDateTime dte;
			if(varValue.vt != VT_DATE)
				varValue.ChangeType(VT_BSTR);
			// � ����������� �� ���� ��������
			switch(varValue.vt)
			{
			case VT_BSTR:
				{
					CString strValue = varValue.bstrVal;
					if(!dte.ParseDateTime(strValue))
					{
						memset(&pRec[nOffset],' ',lLen);
						break;
					}
				}
			case VT_DATE:
				{
					memset(&pRec[nOffset],'0',lLen);
					dte.m_dt = varValue.date;
					CString strValue;
					strValue.Format("%d",dte.GetYear());
					strncpy(&pRec[nOffset + 4 - strValue.GetLength()], strValue, strValue.GetLength());
					strValue.Format("%d",dte.GetMonth());
					strncpy(&pRec[nOffset + 6 - strValue.GetLength()], strValue, strValue.GetLength());
					strValue.Format("%d",dte.GetDay());
					strncpy(&pRec[nOffset + 8 - strValue.GetLength()], strValue, strValue.GetLength());
					break;
				}
			default:
				memset(&pRec[nOffset],' ',lLen);
			}
			break;
		}
	case FLD_TYPE_DATETIME:
		{
			lLen = pFieldRec->len_info.char_len;
			COleDateTime dte;
			if(varValue.vt != VT_DATE)
				varValue.ChangeType(VT_BSTR);
			// � ����������� �� ���� ��������
			switch(varValue.vt)
			{
			case VT_BSTR:
				{
					CString strValue = varValue.bstrVal;
					if(!dte.ParseDateTime(strValue))
					{
						memset(&pRec[nOffset],' ',lLen);
						break;
					}
				 }
			case VT_DATE:
				{
					dte.m_dt = varValue.date;
					long lDay = ((long)dte.m_dt) + 0x1A4452 + 693959 - 366;
					memcpy(&pRec[nOffset], &lDay, lLen/2);
					long lSec = (dte.GetHour()* 60 * 60 + dte.GetMinute() * 60 + dte.GetSecond()) * 1000;
					memcpy(&pRec[nOffset + lLen/2], &lSec, lLen/2);
					break;
				}
			default:
				memset(&pRec[nOffset],0,lLen);
			}
			break;
		}
	case FLD_TYPE_LOGICAL:
		{
			lLen = pFieldRec->len_info.char_len;
			if(varValue.vt != VT_NULL)
				varValue.ChangeType(VT_BOOL);
			// � ����������� �� ���� ��������
			switch(varValue.vt)
			{
			case VT_BOOL:
				{
					CString strValue = varValue.boolVal == TRUE ? "T" : "F";
					strncpy(&pRec[nOffset], strValue, lLen);
					break;
				}
			default:
				memset(&pRec[nOffset],' ',lLen);
			}
			break;
		}
	case FLD_TYPE_CURRENCY:
		{
			lLen = pFieldRec->len_info.num_size.len;
			if(varValue.vt != VT_NULL)
				varValue.ChangeType(VT_CY);
			// � ����������� �� ���� ��������
			switch(varValue.vt)
			{
			case VT_CY:
				memcpy(&pRec[nOffset], &varValue.cyVal, lLen);
				break;
			default:
				memset(&pRec[nOffset],0,lLen);
			}
			break;
		}
	case FLD_TYPE_INTEGER:
		{
			// � ����������� �� ���� ��������
			lLen = pFieldRec->len_info.num_size.len;
			if(varValue.vt != VT_NULL)
				varValue.ChangeType(VT_I4);
			switch(varValue.vt)
			{
			case VT_I4:
				memcpy(&pRec[nOffset], &varValue.lVal, lLen);
				break;
			default:
				memset(&pRec[nOffset],0,lLen);
			}
			break;
		}
	case FLD_TYPE_DOUBLE: // �������� FLD_TYPE_BINARY
		{
			lLen = pFieldRec->len_info.num_size.len;
			// ���� FLD_TYPE_DOUBLE
			if(lLen == sizeof(DBF_DOUBLE))
			{
				if(varValue.vt != VT_NULL)
					varValue.ChangeType(VT_R8);
				// � ����������� �� ���� ��������
				switch(varValue.vt)
				{
				case VT_R8:
					memcpy(&pRec[nOffset], &varValue.dblVal, lLen);
					break;
				default:
					memset(&pRec[nOffset],0,lLen);
				}
			}
			break;
		}
	case FLD_TYPE_NULLFLAGS:
		{
			lLen = pFieldRec->len_info.num_size.len;
			// � ����������� �� ���� ��������
			switch(varValue.vt)
			{
			case VT_UI4:
				memcpy(&pRec[nOffset], &varValue.ulVal, lLen);
				break;
			default:
				memset(&pRec[nOffset],0,lLen);
			}
			break;
		}
	case FLD_TYPE_MEMO:
		{
			lLen = pFieldRec->len_info.num_size.len;
			if(varValue.vt == VT_UI4)
			{
				if(lLen == sizeof(DBF_ULONG))
					memcpy(&pRec[nOffset], &varValue.ulVal, lLen);
				else if(lLen == 10)
				{
					// ��������� ���������
					memset(&pRec[nOffset],' ',lLen);
					if(varValue.ulVal > 0) // ���� ������
					{
						CString strOffsetRec;
						strOffsetRec.Format("%u",varValue.ulVal);
						memcpy(&pRec[nOffset + (lLen - strOffsetRec.GetLength())], (LPCSTR)strOffsetRec, lLen);
					}

				}
			}
			else if (varValue.vt == VT_DECIMAL && lLen == 10) // SIX
			{
				if(varValue.decVal.Lo32 > 0) // ���� ������
					pRec[nOffset] = 0x08;
				else
				{
					pRec[nOffset] = 0x00;
					varValue.decVal.Hi32 = varValue.decVal.Lo32 = 0;
				}
				pRec[nOffset+1] = 0x00;
				memcpy(&pRec[nOffset+2],&varValue.decVal.Hi32, sizeof(varValue.decVal.Hi32));
				memcpy(&pRec[nOffset+6],&varValue.decVal.Lo32, sizeof(varValue.decVal.Lo32));
			}
			break;
		}
	}
}


BOOL CDBFTableDef::ChangeOpenFlag(UINT nNewFlag)
{
	ASSERT_VALID(this);
	ASSERT(IsOpen());

	// ��������� ��� �������� ����
	nNewFlag = nNewFlag | CFile::typeBinary;

	if(m_nOpenFlag == nNewFlag)
		return TRUE;

	if(m_pMemoFile != NULL && m_pMemoFile->IsOpen())
	{
		CString strMemoFileName = m_pMemoFile->GetFilePath();
		m_pMemoFile->CFile::Close();
		// ��������� ����
		if(!m_pMemoFile->CFile::Open(strMemoFileName,nNewFlag))
		{
			// ��������� ����
			DBF_CHECK_ERROR(
				m_pMemoFile->CFile::Open(strMemoFileName, m_nOpenFlag), ALX_DBF_ERROR_MEMO_OPEN);
			return FALSE;
		}
	}

	CFile* pDBFile = (CFile*) &m_DBFile;
	CString strDBFileName = pDBFile->GetFilePath();
	pDBFile->Close();
	// ��������� ����
	if(!pDBFile->Open(strDBFileName,nNewFlag))
	{
		// ��������� ����
		DBF_CHECK_ERROR(
			pDBFile->Open(strDBFileName, m_nOpenFlag), ALX_DBF_ERROR_DBFILE_OPEN);
		return FALSE;
	}

	m_nOpenFlag = nNewFlag;
	return TRUE;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Alexey
Web Developer
Russian Federation Russian Federation
Year of birth - 1974.
Eeducation - was ended by Kaliningrad State University in 1997.
Now I work as the engineer-programmer in Kaliningrad (RUSSIA).

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 6 Nov 2002
Article Copyright 2002 by Alexey
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid