#include "stdafx.h" #include "DBFCursorset.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC(CDBFCursorset, CDBFRecordset) CDBFCursorset::CDBFCursorset(CDBFTableDef* pDBFTable) { m_bDesc = FALSE; m_bShowDeletedRec = TRUE; m_nCurCursorRecN = -1; m_bBOF = TRUE; m_bEOF = TRUE; m_lpfnIsInclude = NULL; } CDBFCursorset::~CDBFCursorset() { if (IsOpen()) Close(); } void CDBFCursorset::Open(LPCTSTR lpszFileName, UINT nOpenFlag) { if (!this) return; CString strFileName; if(lpszFileName == NULL) strFileName = GetDefaultDBName(); else strFileName = lpszFileName; if(!(strFileName.GetLength() > 4)) return; // Re-Opening is invalid. if (IsOpen()) { return; } m_pTableDef = new CDBFTableDef; m_pTableDef->m_bOpen = FALSE; m_pTableDef->Open(strFileName, nOpenFlag); if(!IsOpen()) return; m_DBFFields = m_pTableDef->m_DBFFields; Requery(); } void CDBFCursorset::Close() { CDBFRecordset::Close(); m_bDesc = FALSE; m_bShowDeletedRec = TRUE; m_nCurCursorRecN = -1; m_bBOF = TRUE; m_bEOF = TRUE; m_RecPtr.RemoveAll(); } BOOL CDBFCursorset::IsBOF() const { return m_bBOF; } BOOL CDBFCursorset::IsEOF() const { return m_bEOF; } long CDBFCursorset::GetRecordCount() { if (!IsOpen()) return -1; return m_RecPtr.GetSize(); } long CDBFCursorset::GetAbsolutePosition() { if (!IsOpen()) return -1; return m_nCurCursorRecN; } void CDBFCursorset::SetAbsolutePosition(long lPosition) { if (!IsOpen()) return ; if (!(lPosition >= 0 && lPosition < GetRecordCount())) return; DBF_LONG lCursorRecN = lPosition; // Call Move. m_pTableDef->ReadRecord(m_RecPtr[lCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[lCursorRecN]; m_nCurCursorRecN = lCursorRecN; m_bBOF = m_bEOF = FALSE; } void CDBFCursorset::MoveNext() { if (IsEOF()) return; m_nEditMode = DbfUtility::noMode; DBF_LONG lCursorRecN = m_nCurCursorRecN; lCursorRecN++; if(lCursorRecN < GetRecordCount()) { // Call Move. m_pTableDef->ReadRecord(m_RecPtr[lCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[lCursorRecN]; m_nCurCursorRecN = lCursorRecN; m_bBOF = m_bEOF = FALSE; } else { m_bEOF = TRUE; m_bBOF = GetRecordCount() > 0; } } void CDBFCursorset::MovePrev() { if (IsBOF()) return; m_nEditMode = DbfUtility::noMode; DBF_LONG lCursorRecN = m_nCurCursorRecN; lCursorRecN--; if(lCursorRecN < GetRecordCount()) { // Call Move. m_pTableDef->ReadRecord(m_RecPtr[lCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[lCursorRecN]; m_nCurCursorRecN = lCursorRecN; } else { m_bEOF = TRUE; m_bBOF = GetRecordCount() > 0; } } void CDBFCursorset::MoveFirst() { if (GetRecordCount() <= 0) return; m_nEditMode = DbfUtility::noMode; DBF_LONG lCursorRecN = 0; // Call Move. m_pTableDef->ReadRecord(m_RecPtr[lCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[lCursorRecN]; m_nCurCursorRecN = lCursorRecN; m_bBOF = m_bEOF = FALSE; } void CDBFCursorset::MoveLast() { if (GetRecordCount() <= 0) return; m_nEditMode = DbfUtility::noMode; DBF_LONG lCursorRecN = 0; lCursorRecN = GetRecordCount() - 1; // Call Move. m_pTableDef->ReadRecord(m_RecPtr[lCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[lCursorRecN]; m_nCurCursorRecN = lCursorRecN; m_bBOF = m_bEOF = FALSE; } void CDBFCursorset::Move(long lOffsetRec) { if (GetRecordCount() <= 0) return; m_nEditMode = DbfUtility::noMode; DBF_LONG lCursorRecN = m_nCurCursorRecN + lOffsetRec; if(lOffsetRec < 0) { if(lCursorRecN < 0) { lCursorRecN = 0; m_bBOF = TRUE; } else m_bBOF = FALSE; m_bEOF = FALSE; } else if(lOffsetRec > 0) { if(lCursorRecN >= GetRecordCount()) { lCursorRecN = GetRecordCount() - 1; m_bEOF = TRUE; } else m_bEOF = FALSE; m_bBOF = FALSE; } // Call Move. m_pTableDef->ReadRecord(m_RecPtr[lCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[lCursorRecN]; m_nCurCursorRecN = lCursorRecN; } void CDBFCursorset::CancelUpdate() { if (!IsOpen()) return; if (m_nEditMode == DbfUtility::noMode) return; m_pTableDef->ReadRecord(m_RecPtr[m_nCurCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[m_nCurCursorRecN]; m_nEditMode = DbfUtility::noMode; } void CDBFCursorset::AddNew() { if (!IsOpen()) return; m_nEditMode = DbfUtility::addnew; memset(m_DBFFields.m_pCurRec, 0, m_pTableDef->m_DBFHead.rec_size); COleVariant varEmpty; varEmpty.Clear(); for(short i = 0; i < m_DBFFields.GetFieldCount(); i++) { FIELD_REC* pFieldRec = m_DBFFields.GetFieldRec(i); TGSetFieldValue(m_DBFFields.m_pCurRec, pFieldRec, varEmpty); } m_DBFFields.m_pCurRec[0] = REC_FLAG_NORMAL; } void CDBFCursorset::Edit() { if (!IsOpen()) return; if (m_nEditMode != DbfUtility::noMode) return; m_nEditMode = DbfUtility::edit; } void CDBFCursorset::Update() { if (!IsOpen()) return; if (m_nEditMode == DbfUtility::noMode) return; switch(m_nEditMode) { case DbfUtility::edit: { m_pTableDef->WriteRecord(m_nCurTableRecN, m_DBFFields.m_pCurRec); break; } case DbfUtility::addnew: { m_pTableDef->ReadHeader(); m_pTableDef->m_DBFHead.last_rec++; m_nCurTableRecN = max(0,m_pTableDef->m_DBFHead.last_rec - 1); m_pTableDef->WriteRecord(m_nCurTableRecN, m_DBFFields.m_pCurRec); m_pTableDef->WriteHeader(); m_RecPtr.Add(m_nCurTableRecN); m_nCurCursorRecN = GetRecordCount() -1; break; } } m_nEditMode = DbfUtility::noMode; } void CDBFCursorset::Remove() { if (!IsOpen()) return; if (m_nEditMode != DbfUtility::noMode) return; m_RecPtr.RemoveAt(m_nCurCursorRecN); if(m_nCurCursorRecN >= m_RecPtr.GetSize() && m_nCurCursorRecN > 0) m_nCurCursorRecN--; if(GetRecordCount() > 0) { m_pTableDef->ReadRecord(m_RecPtr[m_nCurCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[m_nCurCursorRecN]; } } BOOL CDBFCursorset::IsOpen() const { return (m_pTableDef == NULL ? FALSE : m_pTableDef->m_bOpen); } void CDBFCursorset::ThrowDBFException(long nTGDBFError) { TGThrowDBFException(nTGDBFError); } #ifdef _DEBUG void CDBFCursorset::AssertValid() const { CDBFRecordset::AssertValid(); } void CDBFCursorset::Dump(CDumpContext& dc) const { CDBFRecordset::Dump(dc); dc << "\n"; } #endif //_DEBUG void CDBFCursorset::SetRecord(long lRecNumber, const DBF_CHAR* lpBuffer){} void CDBFCursorset::SortByField(const char* lpszName, BOOL bDesc /* = FALSE */) { for(short nIndex = 0; _stricmp(m_DBFFields.m_pFields[nIndex].field_name, lpszName) != 0 && nIndex <= m_DBFFields.m_nFieldCount; nIndex++) SortByField(nIndex, bDesc); } void CDBFCursorset::SortByField(int nIndex, BOOL bDesc /* = FALSE */) { m_nSortedField = nIndex; m_bDesc = bDesc; if(GetRecordCount() > 1) { FIELD_REC* pFieldRec = m_DBFFields.GetFieldRec(nIndex); switch(pFieldRec->field_type) { case FLD_TYPE_DOUBLE: //FLD_TYPE_BINARY //FLD_TYPE_DOUBLE if(pFieldRec->len_info.num_size.len == sizeof(DBF_DOUBLE)) break; case FLD_TYPE_GENERAL: case FLD_TYPE_PICTURE: return; } qsort( 0, GetRecordCount() - 1 ); m_pTableDef->ReadRecord(m_RecPtr[m_nCurCursorRecN], m_DBFFields.m_pCurRec); m_nCurTableRecN = m_RecPtr[m_nCurCursorRecN]; } } int CDBFCursorset::compare(const long elem1, const long elem2) { // if elem1 < elem2 return TRUE else return FALSE COleVariant var1, var2; BOOL bResult; if(m_bDesc) { m_pTableDef->ReadRecord(elem1, m_DBFFields.m_pCurRec); var2 = GetFieldValue(m_nSortedField); m_pTableDef->ReadRecord(elem2, m_DBFFields.m_pCurRec); var1 = GetFieldValue(m_nSortedField); } else { m_pTableDef->ReadRecord(elem1, m_DBFFields.m_pCurRec); var1 = GetFieldValue(m_nSortedField); m_pTableDef->ReadRecord(elem2, m_DBFFields.m_pCurRec); var2 = GetFieldValue(m_nSortedField); } if(var1 == var2) bResult = FALSE; else { if(var1.vt == VT_EMPTY && var2.vt != VT_EMPTY) bResult = TRUE; else if (var2.vt == VT_EMPTY && var1.vt != VT_EMPTY) bResult = FALSE; else { switch(var1.vt) { case VT_BSTR: { CTDbfString str1 = var1.bstrVal; CTDbfString str2 = var2.bstrVal; bResult = (str1 < str2); break; } case VT_R8: { bResult = (var1.dblVal < var2.dblVal); break; } case VT_I4: { bResult = (var1.lVal < var2.lVal); break; } case VT_CY: { COleCurrency cur1, cur2; cur1.m_cur = var1.cyVal; cur2.m_cur = var2.cyVal; bResult = (cur1 < cur2); break; } case VT_DATE: { bResult = (var1.date < var2.date); break; } case VT_BOOL: { bResult = (var1.boolVal < var2.boolVal); break; } } } } return bResult; } void CDBFCursorset::qsort(int from, int to) { int i, j; long x, tmp; // int from = 0; // int to = m_RecPtr.GetSize(); if( from >= to ) return; i = from; j = to; x = m_RecPtr[ (i+j) / 2 ]; do { while( compare(m_RecPtr[i], x) ) i++ ; // m_RecPtr[i] < x while( compare(x, m_RecPtr[j]) ) j--; // x < m_RecPtr[j] if( i <= j ) { tmp = m_RecPtr[i]; m_RecPtr[i] = m_RecPtr[j] ; m_RecPtr[j] = tmp; i++; j--; } } while( i <= j ); if( (j - from) < (to - i) ) { qsort( from, j ); qsort( i, to ); } else { qsort( i, to ); qsort( from, j ); } } void CDBFCursorset::SetDelete(BOOL bHideDeleteRec /* = TRUE */) { m_bShowDeletedRec = !bHideDeleteRec; } BOOL CDBFCursorset::GetDelete() { return !m_bShowDeletedRec; } void CDBFCursorset::Requery() { if (!IsOpen()) return; m_nEditMode = DbfUtility::noMode; m_RecPtr.SetSize(m_pTableDef->GetRecordCount()); long nRec = 0; if(m_bShowDeletedRec) { for(long i = 0; i < m_RecPtr.GetSize(); i++) { m_RecPtr[nRec] = i; if(m_lpfnIsInclude != NULL) { if((*m_lpfnIsInclude)((DBF_CHAR*)m_RecPtr[nRec],&m_DBFFields)) nRec++; } else nRec++; } } else { for(long i = 0; i < m_RecPtr.GetSize(); i++) { m_pTableDef->ReadRecord(m_RecPtr[nRec], m_DBFFields.m_pCurRec); if(REC_FLAG_DELETED != m_DBFFields.m_pCurRec[0]) { if(m_lpfnIsInclude != NULL) { if((*m_lpfnIsInclude)(m_DBFFields.m_pCurRec,&m_DBFFields)) nRec++; } else nRec++; } } } m_RecPtr.SetSize(nRec); if(GetRecordCount() > 0) MoveFirst(); else { m_nCurTableRecN = 0; m_nCurCursorRecN = 0; } } void CDBFCursorset::SetFilter(BOOL (FAR * lpfnIsInclude) (DBF_CHAR*, CDBFFields* pDBFFields)) { m_lpfnIsInclude = lpfnIsInclude; }