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