home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / CHKBOOK.PAK / FXRECDOC.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  5.9 KB  |  208 lines

  1. // fxrecdoc.cpp : implementation of the CFixedLenRecDoc and
  2. //                CFixedLenRecHint classes
  3. //
  4. // This is a part of the Microsoft Foundation Classes C++ library.
  5. // Copyright (C) 1992-1995 Microsoft Corporation
  6. // All rights reserved.
  7. //
  8. // This source code is only intended as a supplement to the
  9. // Microsoft Foundation Classes Reference and related
  10. // electronic documentation provided with the library.
  11. // See these sources for detailed information regarding the
  12. // Microsoft Foundation Classes product.
  13.  
  14. #include "stdafx.h"
  15. #include "fxrecdoc.h"
  16. #include <string.h>
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char BASED_CODE THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. IMPLEMENT_DYNAMIC(CFixedLenRecHint, CObject)
  24. IMPLEMENT_DYNAMIC(CFixedLenRecDoc, CDocument)
  25.  
  26. ///////////////////////////////////////////////////////////////////////
  27. CFixedLenRecHint::CFixedLenRecHint()
  28. {
  29. }
  30.  
  31. CFixedLenRecDoc::CFixedLenRecDoc()
  32. {
  33.     m_header.nRecordCount = 0;
  34.     m_header.nExtraHeaderLength = 0;
  35. }
  36.  
  37. CFixedLenRecDoc::~CFixedLenRecDoc()
  38. {
  39. }
  40.  
  41. ///////////////////////////////////////////////////////////////////////
  42. // CDocument overrides
  43.  
  44. BOOL CFixedLenRecDoc::OnOpenDocument(LPCTSTR lpszPathName)
  45. {
  46.     // The standard CDocument::OnOpenDocument() opens the document,
  47.     // deserializes it, and then closes the document.
  48.     // CFixedLenRecDoc::Serialize() only reads the header.
  49.     // We reopen the document's file here so that we can update
  50.     // the file (via CFile::write's) on a per transaction basis.
  51.  
  52.     if (!CDocument::OnOpenDocument(lpszPathName))
  53.         return FALSE;
  54.     ASSERT(m_file.m_hFile == CFile::hFileNull);
  55.     if (!m_file.Open(lpszPathName,
  56.             CFile::modeReadWrite | CFile::shareExclusive))
  57.     {
  58.         return FALSE;
  59.     }
  60.  
  61.     // If the file is empty, that is so because the application has
  62.     // just created a new file in its override of CChkBook::OnFileNew.
  63.     // It this case, we need to create a header for the new file.
  64.     // We pass bNewHeader=TRUE to WriteHeader so that the CChkBookDoc
  65.     // takes the opportunity to write the first record in its override
  66.     // of OnWriteHeader.
  67.  
  68.     if (m_file.GetLength() == 0L)
  69.     {
  70.         WriteHeader(&m_file, TRUE);
  71.     }
  72.     else
  73.     {
  74.         return (ReadHeader(&m_file));
  75.     }
  76.  
  77.     return TRUE;
  78. }
  79.  
  80. void CFixedLenRecDoc::DeleteContents()
  81. {
  82.     // We reopened the file in the override of CDocument::OnOpenDocument,
  83.     // after we deserialized the document, so we can update the file
  84.     // on a per transaction basis.
  85.     // Similarly, we now close the file when the framework wants to
  86.     // clear out the CDocument object for potential reuse.
  87.  
  88.     if (m_file.m_hFile != CFile::hFileNull)
  89.         m_file.Close();
  90. }
  91.  
  92. ///////////////////////////////////////////////////////////////////////
  93. // Operations
  94.  
  95. void CFixedLenRecDoc::WriteHeader(CFile* pFile, BOOL bNewHeader)
  96. {
  97.     pFile->Seek(0L, CFile::begin);
  98.     pFile->Write(&m_header, sizeof(m_header));
  99.     if (m_header.nExtraHeaderLength > 0)
  100.     {
  101.         // OnWriteExtraHeader must be implemented by the derived class
  102.         OnWriteExtraHeader(bNewHeader);
  103.     }
  104. }
  105.  
  106. BOOL CFixedLenRecDoc::OnReadExtraHeader()
  107. {
  108.     TRACE0("Derived class has specified extra header but didn't override OnReadExtraHeader");
  109.     ASSERT(FALSE);
  110.     return FALSE;
  111. }
  112.  
  113. void CFixedLenRecDoc::OnWriteExtraHeader(BOOL)
  114. {
  115.     TRACE0("Derived class has specified extra header but didn't override OnWriteExtraHeader");
  116.     ASSERT(FALSE);
  117. }
  118.  
  119. BOOL CFixedLenRecDoc::ReadHeader(CFile* pFile)
  120. {
  121.     pFile->Seek(0L, CFile::begin);
  122.     if (pFile->Read(&m_header, sizeof(m_header)) < sizeof(m_header))
  123.         return FALSE;
  124.     if (m_header.nExtraHeaderLength < 1)
  125.         return TRUE;
  126.  
  127.     // OnReadExtraHeader is implemented by the derived class.
  128.     return (OnReadExtraHeader());
  129. }
  130.  
  131. UINT CFixedLenRecDoc::CreateNewRecord()
  132. {
  133.     // CreateNewRecord is called by the view to create a new fixed
  134.     // length record.  Increment the record count and update the
  135.     // the header to reflect the addition of a new record in the file.
  136.     // Notify all views about the new record.
  137.  
  138.     UINT nNewRecordIndex = m_header.nRecordCount++;
  139.     WriteHeader(&m_file, FALSE);
  140.     FileSeekRecord(nNewRecordIndex);
  141.     void* pNewRecord = OnCreateNewRecord(nNewRecordIndex);
  142.     m_file.Write(pNewRecord, m_header.nRecordLength);
  143.  
  144. #ifdef _DEBUG
  145.     // Read back the record just written to see if were written correctly.
  146.     void* pCompareRec = malloc(m_header.nRecordLength);
  147.     FileSeekRecord(nNewRecordIndex);
  148.     if (m_file.Read(pCompareRec, m_header.nRecordLength)
  149.         < m_header.nRecordLength)
  150.         ASSERT(FALSE);
  151.     ASSERT(memcmp(pCompareRec, pNewRecord, m_header.nRecordLength) == 0);
  152.     free(pCompareRec);
  153. #endif
  154.  
  155.     UpdateAllViewsWithRecord(NULL, nNewRecordIndex);
  156.     return nNewRecordIndex;
  157. }
  158.  
  159. ///////////////////////////////////////////////////////////////////////
  160. // Implementation
  161.  
  162. void CFixedLenRecDoc::FileSeekRecord(UINT nRecord)
  163. {
  164.     m_file.Seek(sizeof(m_header) + m_header.nExtraHeaderLength
  165.             + nRecord * m_header.nRecordLength,
  166.         CFile::begin);
  167. }
  168.  
  169. void CFixedLenRecDoc::GetRecord(UINT nRecordIndex, void* pRecord)
  170. {
  171.     FileSeekRecord(nRecordIndex);
  172.     if (m_file.Read(pRecord, m_header.nRecordLength)
  173.         < m_header.nRecordLength)
  174.             ASSERT(FALSE);
  175. }
  176.  
  177.  
  178. void CFixedLenRecDoc::UpdateRecord(CView* pSourceView, UINT nRecordIndex,
  179.         void* pRecord)  // called by view
  180. {
  181.     FileSeekRecord(nRecordIndex);
  182.     m_file.Write(pRecord, m_header.nRecordLength);
  183.     UpdateAllViewsWithRecord(pSourceView, nRecordIndex);
  184. }
  185.  
  186. void CFixedLenRecDoc::UpdateAllViewsWithRecord(CView* pSourceView,
  187.     UINT nRecordIndex)
  188. {
  189.     CFixedLenRecHint hint;
  190.     UpdateAllViews(pSourceView, MAKELONG(nRecordIndex, 0), &hint);
  191. }
  192.  
  193. void CFixedLenRecDoc::Serialize(CArchive& ar)
  194. {
  195.     // It's not necessary to store anything in the file on File Save/As,
  196.     // since we have been updating the file on every transaction.
  197.     // We need only read the file header on File Open.
  198.  
  199.     if (ar.IsStoring())
  200.     {
  201.         if (!ReadHeader(ar.GetFile()))
  202.         {
  203.             // The header can't be interpreted.
  204.             AfxThrowArchiveException(CArchiveException::badSchema);
  205.         }
  206.     }
  207. }
  208.