Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

1404 lines
32 KiB
C++

#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 = 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;
}