1398 lines
31 KiB
C++
1398 lines
31 KiB
C++
#include "stdafx.h"
|
|
#include "DBFTableDef.h"
|
|
|
|
#define MIN_DATE (-657434L) // about year 100
|
|
#define MAX_DATE 2958465L // about year 9999
|
|
|
|
// CDBFTableDef
|
|
IMPLEMENT_DYNAMIC(CDBFTableDef, CObject)
|
|
|
|
CDBFTableDef::CDBFTableDef()
|
|
{
|
|
m_bOpen = FALSE;
|
|
m_bNew = FALSE;
|
|
m_nOpenFlag = TG_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;
|
|
}
|
|
}
|
|
|
|
BOOL CDBFTableDef::Open(LPCTSTR lpszName, UINT nOpenFlag)
|
|
{
|
|
if (!lpszName)
|
|
return FALSE;
|
|
|
|
m_nOpenFlag = nOpenFlag | CFile::typeBinary;
|
|
|
|
CTDbfString strMemoFileExt;
|
|
if (IsOpen())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if(m_DBFFields.m_pFields != NULL)
|
|
delete[] m_DBFFields.m_pFields;
|
|
|
|
|
|
// TRY
|
|
// {
|
|
|
|
DBF_CHECK_ERROR(
|
|
m_DBFile.Open(lpszName, m_nOpenFlag), TG_DBF_ERROR_DBFILE_OPEN);
|
|
DBF_CHECK_ERROR(
|
|
m_DBFile.Read(&m_DBFHead, sizeof(m_DBFHead)) == sizeof(DBF_HEAD), TG_DBF_ERROR_DBFHEADER_READ);
|
|
|
|
DBF_CHECK_ERROR(
|
|
m_DBFHead.rec_size > 1 && m_DBFHead.last_rec >= 0, TG_DBF_ERROR_NOT_TABLE);
|
|
|
|
DBF_CHECK_ERROR(
|
|
m_DBFile.GetLength() - (m_DBFHead.data_offset + m_DBFHead.rec_size * m_DBFHead.last_rec) <= 1, TG_DBF_ERROR_NOT_TABLE);
|
|
|
|
|
|
if(m_DBFHead.dbf_id == 0x30)
|
|
{
|
|
m_DBFFields.m_nFieldCount = (m_DBFHead.data_offset - 296)/sizeof(FIELD_REC);
|
|
|
|
DBF_CHECK_ERROR(
|
|
m_DBFFields.m_nFieldCount > 0, TG_DBF_ERROR_NOT_FIELDS);
|
|
|
|
DBF_CHECK_ERROR(
|
|
m_DBFile.GetLength() >= (DWORD)(m_DBFHead.data_offset + (m_DBFHead.last_rec * m_DBFHead.rec_size)),
|
|
TG_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),
|
|
TG_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))
|
|
{
|
|
delete[] pFields;
|
|
TGThrowDBFException(TG_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
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
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:
|
|
{
|
|
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;
|
|
}
|
|
|
|
CTDbfString CDBFTableDef::GetName()
|
|
{
|
|
return m_DBFile.GetFileName();
|
|
}
|
|
|
|
CTDbfString CDBFTableDef::GetDBFilePath()
|
|
{
|
|
return m_DBFile.GetFilePath();
|
|
}
|
|
|
|
CTime CDBFTableDef::GetDateCreated()
|
|
{
|
|
assert(IsOpen());
|
|
CFileStatus fStatus;
|
|
m_DBFile.GetStatus(fStatus);
|
|
|
|
return fStatus.m_ctime;
|
|
}
|
|
|
|
CTime CDBFTableDef::GetDateLastUpdated()
|
|
{
|
|
assert(IsOpen());
|
|
return CTime(TG_DBF_CENTURY + m_DBFHead.last_update[0],m_DBFHead.last_update[1],m_DBFHead.last_update[2]);
|
|
}
|
|
|
|
long CDBFTableDef::GetRecordCount()
|
|
{
|
|
assert(IsOpen());
|
|
return m_DBFHead.last_rec;
|
|
}
|
|
|
|
short CDBFTableDef::GetFieldCount()
|
|
{
|
|
return m_DBFFields.m_nFieldCount;
|
|
}
|
|
|
|
void CDBFTableDef::ReadRecord(LONG_PTR lRecNumber, void* lpBuffer)
|
|
{
|
|
assert(IsOpen());
|
|
if (!lpBuffer || lRecNumber > GetRecordCount())
|
|
return;
|
|
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_PTR lOffset = m_DBFHead.data_offset + m_DBFHead.rec_size * lRecNumber;
|
|
if(lOffset < sizeof(DBF_HEAD) || lOffset + m_DBFHead.rec_size > (LONG_PTR)m_DBFile.GetLength())
|
|
TGThrowDBFException(TG_DBF_ERROR_RECORD_OUTOFRANGE);
|
|
else
|
|
TGThrowDBFException(TG_DBF_ERROR_RECORD_READ);
|
|
}
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
memset(&lpBuffer,'\0', m_DBFHead.rec_size);
|
|
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
TGThrowDBFException(TG_DBF_ERROR_RECORD_READ);
|
|
|
|
} END_CATCH
|
|
|
|
}
|
|
|
|
void CDBFTableDef::WriteRecord(long lRecNumber, void* lpBuffer)
|
|
{
|
|
assert(IsOpen());
|
|
if (!lpBuffer || lRecNumber > GetRecordCount())
|
|
return;
|
|
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();
|
|
|
|
TGThrowDBFException(TG_DBF_ERROR_RECORD_WRITE);
|
|
|
|
} END_CATCH
|
|
|
|
}
|
|
|
|
BOOL CDBFTableDef::ReadHeader()
|
|
{
|
|
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();
|
|
|
|
TGThrowDBFException(TG_DBF_ERROR_DBFHEADER_WRITE);
|
|
|
|
} END_CATCH
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void CDBFTableDef::WriteHeader()
|
|
{
|
|
assert(IsOpen());
|
|
TRY
|
|
{
|
|
m_DBFile.Seek(0, CFile::begin);
|
|
|
|
m_DBFile.Write(&m_DBFHead, sizeof(m_DBFHead));
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
TGThrowDBFException(TG_DBF_ERROR_DBFHEADER_WRITE);
|
|
|
|
} END_CATCH
|
|
|
|
}
|
|
|
|
|
|
void CDBFTableDef::ReadMemoRecord(DBF_ULONG lOffsetRec, DBF_LONG& nLen, CTDbfString& strMemo)
|
|
{
|
|
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(IsOpen());
|
|
if(m_pMemoFile != NULL)
|
|
m_pMemoFile->ReadMemoRecord(lOffsetRec, nLen, pMemoData);
|
|
}
|
|
|
|
|
|
void CDBFTableDef::WriteMemoRecord(DBF_ULONG& lOffsetRec, DBF_LONG& nLen, CTDbfString& strMemo)
|
|
{
|
|
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
|
|
{
|
|
|
|
|
|
CObject::Dump(dc);
|
|
|
|
dc << "m_bOpen = " << m_bOpen;
|
|
dc << "\nm_bNew = " << m_bNew;
|
|
|
|
dc << "\n";
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
// CDBFTableDef inlines
|
|
inline BOOL CDBFTableDef::IsOpen() const
|
|
{ return m_bOpen; }
|
|
|
|
|
|
|
|
void CDBFTableDef::AddField(FIELD_REC *pFieldRec)
|
|
{
|
|
if (m_nEditMode == noMode)
|
|
return;
|
|
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)
|
|
{
|
|
if (m_nEditMode == noMode || nIndex > m_DBFFields.m_nFieldCount)
|
|
return;
|
|
|
|
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)
|
|
{
|
|
if (m_nEditMode == noMode || nIndex > m_DBFFields.m_nFieldCount)
|
|
return;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CDBFTableDef::UpdateTable()
|
|
{
|
|
if (m_nEditMode == noMode || m_DBFFields.m_nFieldCount < 0)
|
|
return FALSE;
|
|
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), TG_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)
|
|
TGGetFieldValue(pOldRec, m_pOldDBFFields->GetFieldRec(m_pSwapFld[j]), varValue);
|
|
TGSetFieldValue(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)
|
|
{
|
|
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), TG_DBF_ERROR_DBFILE_OPEN);
|
|
}
|
|
|
|
m_nEditMode = noMode;
|
|
|
|
m_bNew = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDBFTableDef::CreateTable(LPCTSTR lpszName)
|
|
{
|
|
assert(!IsOpen());
|
|
if (!lpszName)
|
|
return FALSE;
|
|
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), TG_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() - TG_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(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() - TG_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)
|
|
{
|
|
if (m_nEditMode == noMode || nIndex > m_DBFFields.m_nFieldCount)
|
|
return;
|
|
m_DBFFields.m_pFields[nIndex] = *pFieldRec;
|
|
}
|
|
|
|
void CDBFTableDef::MoveField(short nIndex, short nNewIndex)
|
|
{
|
|
if (m_nEditMode == noMode ||
|
|
nIndex > m_DBFFields.m_nFieldCount ||
|
|
nNewIndex > m_DBFFields.m_nFieldCount)
|
|
return;
|
|
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()
|
|
{
|
|
if (m_nEditMode == noMode)
|
|
return;
|
|
|
|
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 TGGetFieldValue(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:
|
|
{
|
|
|
|
lLen = pFieldRec->len_info.char_len;
|
|
char *buffer = new char[lLen+1];
|
|
memset(buffer, 0, lLen+1);
|
|
//char* buffer = strValue.GetBuffer(lLen + 1);
|
|
|
|
memcpy(buffer, &pRec[nOffset], lLen);
|
|
buffer[lLen] = '\0';
|
|
CTDbfString _Value(buffer);
|
|
delete [] buffer;
|
|
CString strValue = _Value.toCString();
|
|
//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:
|
|
{
|
|
lLen = pFieldRec->len_info.num_size.len;
|
|
|
|
//char* buffer = strValue.GetBuffer(lLen + 1);
|
|
char *buffer = new char[lLen+1];
|
|
|
|
memcpy(buffer, &pRec[nOffset], lLen);
|
|
buffer[lLen] = '\0';
|
|
//strValue.ReleaseBuffer(lLen + 1);
|
|
CString strValue(buffer);
|
|
delete [] buffer;
|
|
|
|
varValue = strValue;
|
|
}
|
|
}
|
|
|
|
return lLen;
|
|
}
|
|
|
|
void TGSetFieldValue(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)
|
|
{
|
|
CTDbfString strValue = varValue.bstrVal;
|
|
strncpy(&pRec[nOffset], strValue.toLPCSTR(), min((int)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(_T("%s.%uf"),_T("%"),bDec);
|
|
strValue.Format(strFormat,varValue.dblVal);
|
|
}
|
|
|
|
if(strValue.GetLength() > lLen)
|
|
{
|
|
if(strValue.GetAt(lLen) == '.')
|
|
strValue = ' ' + strValue;
|
|
strValue = strValue.Left(lLen);
|
|
}
|
|
CTDbfString _Value(strValue);
|
|
strncpy(&pRec[nOffset + (lLen - _Value.GetLength())], _Value.toLPCSTR(), _Value.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(_T("%d"),dte.GetYear());
|
|
CTDbfString _Value(strValue);
|
|
strncpy(&pRec[nOffset + 4 - _Value.GetLength()], _Value.toLPCSTR(), _Value.GetLength());
|
|
strValue.Format(_T("%d"),dte.GetMonth());
|
|
_Value = strValue;
|
|
strncpy(&pRec[nOffset + 6 - _Value.GetLength()], _Value.toLPCSTR(), _Value.GetLength());
|
|
strValue.Format(_T("%d"),dte.GetDay());
|
|
_Value = strValue;
|
|
strncpy(&pRec[nOffset + 8 - _Value.GetLength()], _Value.toLPCSTR(), _Value.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:
|
|
{
|
|
CTDbfString strValue = varValue.boolVal == TRUE ? "T" : "F";
|
|
strncpy(&pRec[nOffset], strValue.toLPCSTR(), 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 strTmp;
|
|
strTmp.Format(_T("%u"),varValue.ulVal);
|
|
CTDbfString strOffsetRec(strTmp);
|
|
memcpy(&pRec[nOffset + (lLen - strOffsetRec.GetLength())], strOffsetRec.toLPCSTR(), 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(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), TG_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), TG_DBF_ERROR_DBFILE_OPEN);
|
|
return FALSE;
|
|
}
|
|
|
|
m_nOpenFlag = nNewFlag;
|
|
return TRUE;
|
|
}
|