home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / DOCTEMPL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-04  |  12.1 KB  |  449 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE2_SEG
  14. #pragma code_seg(AFX_CORE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CDocTemplate construction/destruction
  26.  
  27. CDocTemplate::CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
  28.     CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
  29. {
  30.     ASSERT_VALID_IDR(nIDResource);
  31.     ASSERT(pDocClass == NULL ||
  32.         pDocClass->IsDerivedFrom(RUNTIME_CLASS(CDocument)));
  33.     ASSERT(pFrameClass == NULL ||
  34.         pFrameClass->IsDerivedFrom(RUNTIME_CLASS(CFrameWnd)));
  35.     ASSERT(pViewClass == NULL ||
  36.         pViewClass->IsDerivedFrom(RUNTIME_CLASS(CView)));
  37.  
  38.     m_nIDResource = nIDResource;
  39.     m_nIDServerResource = NULL;
  40.     m_nIDEmbeddingResource = NULL;
  41.     m_nIDContainerResource = NULL;
  42.  
  43.     m_pDocClass = pDocClass;
  44.     m_pFrameClass = pFrameClass;
  45.     m_pViewClass = pViewClass;
  46.     m_pOleFrameClass = NULL;
  47.     m_pOleViewClass = NULL;
  48.  
  49.     m_pAttachedFactory = NULL;
  50.     m_hMenuInPlace = NULL;
  51.     m_hAccelInPlace = NULL;
  52.     m_hMenuEmbedding = NULL;
  53.     m_hAccelEmbedding = NULL;
  54.     m_hMenuInPlaceServer = NULL;
  55.     m_hAccelInPlaceServer = NULL;
  56.  
  57.     // add to pStaticList if constructed as static instead of on heap
  58.     if (CDocManager::bStaticInit)
  59.     {
  60.         m_bAutoDelete = FALSE;
  61.         if (CDocManager::pStaticList == NULL)
  62.             CDocManager::pStaticList = new CPtrList;
  63.         if (CDocManager::pStaticDocManager == NULL)
  64.             CDocManager::pStaticDocManager = new CDocManager;
  65.         CDocManager::pStaticList->AddTail(this);
  66.     }
  67.     else
  68.     {
  69.         m_bAutoDelete = TRUE;   // usually allocated on the heap
  70.         LoadTemplate();
  71.     }
  72. }
  73.  
  74. void CDocTemplate::LoadTemplate()
  75. {
  76.     if (m_strDocStrings.IsEmpty() && !m_strDocStrings.LoadString(m_nIDResource))
  77.     {
  78.         TRACE1("Warning: no document names in string for template #%d.\n",
  79.             m_nIDResource);
  80.     }
  81.  
  82.     if (m_nIDEmbeddingResource != 0 && m_hMenuEmbedding == NULL)
  83.     {
  84.         // load menu to be used while editing an embedding (as a server)
  85.         HINSTANCE hInst = AfxFindResourceHandle(
  86.             MAKEINTRESOURCE(m_nIDEmbeddingResource), RT_MENU);
  87.         m_hMenuEmbedding =
  88.             ::LoadMenu(hInst, MAKEINTRESOURCE(m_nIDEmbeddingResource));
  89.         m_hAccelEmbedding =
  90.             ::LoadAccelerators(hInst, MAKEINTRESOURCE(m_nIDEmbeddingResource));
  91.     }
  92.     if (m_nIDServerResource != 0 && m_hMenuInPlaceServer == NULL)
  93.     {
  94.         // load menu to be used while editing in-place (as a server)
  95.         HINSTANCE hInst = AfxFindResourceHandle(
  96.             MAKEINTRESOURCE(m_nIDServerResource), RT_MENU);
  97.         m_hMenuInPlaceServer = ::LoadMenu(hInst,
  98.             MAKEINTRESOURCE(m_nIDServerResource));
  99.         m_hAccelInPlaceServer = ::LoadAccelerators(hInst,
  100.             MAKEINTRESOURCE(m_nIDServerResource));
  101.     }
  102.  
  103.     if (m_nIDContainerResource != 0 && m_hMenuInPlace == NULL)
  104.     {
  105.         // load menu to be used while in-place editing session (as a container)
  106.         HINSTANCE hInst = AfxFindResourceHandle(
  107.             MAKEINTRESOURCE(m_nIDContainerResource), RT_MENU);
  108.         m_hMenuInPlace = ::LoadMenu(hInst,
  109.             MAKEINTRESOURCE(m_nIDContainerResource));
  110.         m_hAccelInPlace = ::LoadAccelerators(hInst,
  111.             MAKEINTRESOURCE(m_nIDContainerResource));
  112.     }
  113. }
  114.  
  115. void CDocTemplate::SetServerInfo(UINT nIDOleEmbedding, UINT nIDOleInPlaceServer,
  116.     CRuntimeClass* pOleFrameClass, CRuntimeClass* pOleViewClass)
  117. {
  118.     ASSERT_VALID_IDR(nIDOleEmbedding);
  119.     if (nIDOleInPlaceServer != 0)
  120.         ASSERT_VALID_IDR(nIDOleInPlaceServer);
  121.     ASSERT(pOleFrameClass == NULL ||
  122.         pOleFrameClass->IsDerivedFrom(RUNTIME_CLASS(CFrameWnd)));
  123.     ASSERT(pOleViewClass == NULL ||
  124.         pOleViewClass->IsDerivedFrom(RUNTIME_CLASS(CView)));
  125.  
  126.     m_pOleFrameClass = pOleFrameClass;
  127.     m_pOleViewClass = pOleViewClass;
  128.  
  129.     m_nIDEmbeddingResource = nIDOleEmbedding;
  130.     m_nIDServerResource = nIDOleInPlaceServer;
  131.     if (!CDocManager::bStaticInit)
  132.         LoadTemplate();
  133. }
  134.  
  135. void CDocTemplate::SetContainerInfo(UINT nIDOleInPlaceContainer)
  136. {
  137.     ASSERT(nIDOleInPlaceContainer != 0);
  138.  
  139.     m_nIDContainerResource = nIDOleInPlaceContainer;
  140.     if (!CDocManager::bStaticInit)
  141.         LoadTemplate();
  142. }
  143.  
  144. CDocTemplate::~CDocTemplate()
  145. {
  146.     // delete OLE resources
  147.     if (m_hMenuInPlace != NULL)
  148.         ::DestroyMenu(m_hMenuInPlace);
  149.     if (m_hAccelInPlace != NULL)
  150.         ::FreeResource(m_hAccelInPlace);
  151.     if (m_hMenuEmbedding != NULL)
  152.         ::DestroyMenu(m_hMenuEmbedding);
  153.     if (m_hAccelEmbedding != NULL)
  154.         ::FreeResource(m_hAccelEmbedding);
  155.     if (m_hMenuInPlaceServer != NULL)
  156.         ::DestroyMenu(m_hMenuInPlaceServer);
  157.     if (m_hAccelInPlaceServer != NULL)
  158.         ::FreeResource(m_hAccelInPlaceServer);
  159. }
  160.  
  161. /////////////////////////////////////////////////////////////////////////////
  162. // CDocTemplate attributes
  163.  
  164. BOOL CDocTemplate::GetDocString(CString& rString, enum DocStringIndex i) const
  165. {
  166.     return AfxExtractSubString(rString, m_strDocStrings, (int)i);
  167. }
  168.  
  169. /////////////////////////////////////////////////////////////////////////////
  170. // Document management
  171.  
  172. void CDocTemplate::AddDocument(CDocument* pDoc)
  173. {
  174.     ASSERT_VALID(pDoc);
  175.     ASSERT(pDoc->m_pDocTemplate == NULL);   // no template attached yet
  176.     pDoc->m_pDocTemplate = this;
  177. }
  178.  
  179. void CDocTemplate::RemoveDocument(CDocument* pDoc)
  180. {
  181.     ASSERT_VALID(pDoc);
  182.     ASSERT(pDoc->m_pDocTemplate == this);   // must be attached to us
  183.     pDoc->m_pDocTemplate = NULL;
  184. }
  185.  
  186. #ifndef _MAC
  187. CDocTemplate::Confidence CDocTemplate::MatchDocType(LPCTSTR lpszPathName,
  188.     CDocument*& rpDocMatch)
  189. #else
  190. CDocTemplate::Confidence CDocTemplate::MatchDocType(LPCTSTR lpszPathName,
  191.     DWORD dwFileType, CDocument*& rpDocMatch)
  192. #endif
  193. {
  194.     ASSERT(lpszPathName != NULL);
  195.     rpDocMatch = NULL;
  196.  
  197.     // go through all documents
  198.     POSITION pos = GetFirstDocPosition();
  199.     while (pos != NULL)
  200.     {
  201.         CDocument* pDoc = GetNextDoc(pos);
  202.         if (AfxComparePath(pDoc->GetPathName(), lpszPathName))
  203.         {
  204.             // already open
  205.             rpDocMatch = pDoc;
  206.             return yesAlreadyOpen;
  207.         }
  208.     }
  209.  
  210.     // see if it matches our default suffix
  211.     CString strFilterExt;
  212.     if (GetDocString(strFilterExt, CDocTemplate::filterExt) &&
  213.       !strFilterExt.IsEmpty())
  214.     {
  215. #ifndef _MAC
  216.         // see if extension matches
  217.         ASSERT(strFilterExt[0] == '.');
  218.         LPCTSTR lpszDot = _tcsrchr(lpszPathName, '.');
  219.         if (lpszDot != NULL && lstrcmpi(lpszDot, strFilterExt) == 0)
  220.             return yesAttemptNative; // extension matches, looks like ours
  221. #else
  222.         // see if file type matches
  223.         ASSERT(strFilterExt.GetLength() == 4);
  224.         if (dwFileType == *(DWORD*)(const char*)strFilterExt)
  225.             return yesAttemptNative; // file type matches, looks like ours
  226. #endif
  227.     }
  228.  
  229.     // otherwise we will guess it may work
  230.     return yesAttemptForeign;
  231. }
  232.  
  233. CDocument* CDocTemplate::CreateNewDocument()
  234. {
  235.     // default implementation constructs one from CRuntimeClass
  236.     if (m_pDocClass == NULL)
  237.     {
  238.         TRACE0("Error: you must override CDocTemplate::CreateNewDocument.\n");
  239.         ASSERT(FALSE);
  240.         return NULL;
  241.     }
  242.     CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();
  243.     if (pDocument == NULL)
  244.     {
  245.         TRACE1("Warning: Dynamic create of document type %hs failed.\n",
  246.             m_pDocClass->m_lpszClassName);
  247.         return NULL;
  248.     }
  249.     ASSERT_KINDOF(CDocument, pDocument);
  250.     AddDocument(pDocument);
  251.     return pDocument;
  252. }
  253.  
  254. /////////////////////////////////////////////////////////////////////////////
  255. // Default frame creation
  256.  
  257. CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)
  258. {
  259.     if (pDoc != NULL)
  260.         ASSERT_VALID(pDoc);
  261.     // create a frame wired to the specified document
  262.  
  263.     ASSERT(m_nIDResource != 0); // must have a resource ID to load from
  264.     CCreateContext context;
  265.     context.m_pCurrentFrame = pOther;
  266.     context.m_pCurrentDoc = pDoc;
  267.     context.m_pNewViewClass = m_pViewClass;
  268.     context.m_pNewDocTemplate = this;
  269.  
  270.     if (m_pFrameClass == NULL)
  271.     {
  272.         TRACE0("Error: you must override CDocTemplate::CreateNewFrame.\n");
  273.         ASSERT(FALSE);
  274.         return NULL;
  275.     }
  276.     CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
  277.     if (pFrame == NULL)
  278.     {
  279.         TRACE1("Warning: Dynamic create of frame %hs failed.\n",
  280.             m_pFrameClass->m_lpszClassName);
  281.         return NULL;
  282.     }
  283.     ASSERT_KINDOF(CFrameWnd, pFrame);
  284.  
  285.     if (context.m_pNewViewClass == NULL)
  286.         TRACE0("Warning: creating frame with no default view.\n");
  287.  
  288.     // create new from resource
  289.     if (!pFrame->LoadFrame(m_nIDResource,
  290.             WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,   // default frame styles
  291.             NULL, &context))
  292.     {
  293.         TRACE0("Warning: CDocTemplate couldn't create a frame.\n");
  294.         // frame will be deleted in PostNcDestroy cleanup
  295.         return NULL;
  296.     }
  297.  
  298.     // it worked !
  299.     return pFrame;
  300. }
  301.  
  302. CFrameWnd* CDocTemplate::CreateOleFrame(CWnd* pParentWnd, CDocument* pDoc,
  303.     BOOL bCreateView)
  304. {
  305.     CCreateContext context;
  306.     context.m_pCurrentFrame = NULL;
  307.     context.m_pCurrentDoc = pDoc;
  308.     context.m_pNewViewClass = bCreateView ? m_pOleViewClass : NULL;
  309.     context.m_pNewDocTemplate = this;
  310.  
  311.     if (m_pOleFrameClass == NULL)
  312.     {
  313.         TRACE0("Warning: pOleFrameClass not specified for doc template.\n");
  314.         return NULL;
  315.     }
  316.  
  317.     ASSERT(m_nIDServerResource != 0); // must have a resource ID to load from
  318.     CFrameWnd* pFrame = (CFrameWnd*)m_pOleFrameClass->CreateObject();
  319.     if (pFrame == NULL)
  320.     {
  321.         TRACE1("Warning: Dynamic create of frame %hs failed.\n",
  322.             m_pOleFrameClass->m_lpszClassName);
  323.         return NULL;
  324.     }
  325.  
  326.     // create new from resource (OLE frames are created as child windows)
  327.     if (!pFrame->LoadFrame(m_nIDServerResource,
  328.         WS_CHILD|WS_CLIPSIBLINGS, pParentWnd, &context))
  329.     {
  330.         TRACE0("Warning: CDocTemplate couldn't create an OLE frame.\n");
  331.         // frame will be deleted in PostNcDestroy cleanup
  332.         return NULL;
  333.     }
  334.  
  335.     // it worked !
  336.     return pFrame;
  337. }
  338.  
  339. void CDocTemplate::InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc,
  340.     BOOL bMakeVisible)
  341. {
  342.     // just delagate to implementation in CFrameWnd
  343.     pFrame->InitialUpdateFrame(pDoc, bMakeVisible);
  344. }
  345.  
  346. /////////////////////////////////////////////////////////////////////////////
  347. // CDocTemplate commands and command helpers
  348.  
  349. BOOL CDocTemplate::SaveAllModified()
  350. {
  351.     POSITION pos = GetFirstDocPosition();
  352.     while (pos != NULL)
  353.     {
  354.         CDocument* pDoc = GetNextDoc(pos);
  355.         if (!pDoc->SaveModified())
  356.             return FALSE;
  357.     }
  358.     return TRUE;
  359. }
  360.  
  361.  
  362. void CDocTemplate::CloseAllDocuments(BOOL)
  363. {
  364.     POSITION pos = GetFirstDocPosition();
  365.     while (pos != NULL)
  366.     {
  367.         CDocument* pDoc = GetNextDoc(pos);
  368.         pDoc->OnCloseDocument();
  369.     }
  370. }
  371.  
  372. void CDocTemplate::OnIdle()
  373. {
  374.     POSITION pos = GetFirstDocPosition();
  375.     while (pos != NULL)
  376.     {
  377.         CDocument* pDoc = GetNextDoc(pos);
  378.         ASSERT_VALID(pDoc);
  379.         ASSERT_KINDOF(CDocument, pDoc);
  380.         pDoc->OnIdle();
  381.     }
  382. }
  383.  
  384. BOOL CDocTemplate::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  385.     AFX_CMDHANDLERINFO* pHandlerInfo)
  386. {
  387.     BOOL bReturn;
  388.     CCmdTarget* pFactory = DYNAMIC_DOWNCAST(CCmdTarget, m_pAttachedFactory);
  389.  
  390.     if (nCode == CN_OLE_UNREGISTER && pFactory != NULL)
  391.         bReturn = pFactory->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  392.     else
  393.         bReturn = CCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  394.  
  395.     return bReturn;
  396. }
  397.  
  398. /////////////////////////////////////////////////////////////////////////////
  399. // CDocTemplate diagnostics
  400.  
  401. #ifdef _DEBUG
  402. void CDocTemplate::Dump(CDumpContext& dc) const
  403. {
  404.     CCmdTarget::Dump(dc);
  405.  
  406.     dc << "m_nIDResource = " << m_nIDResource;
  407.     dc << "\nm_strDocStrings: " << m_strDocStrings;
  408.  
  409.     if (m_pDocClass)
  410.         dc << "\nm_pDocClass = " << m_pDocClass->m_lpszClassName;
  411.     else
  412.         dc << "\nm_pDocClass = NULL";
  413.  
  414.     if (dc.GetDepth() > 0)
  415.     {
  416.         dc << "\ndocument list = {";
  417.         POSITION pos = GetFirstDocPosition();
  418.         while (pos != NULL)
  419.         {
  420.             CDocument* pDoc = GetNextDoc(pos);
  421.             dc << "\ndocument " << pDoc;
  422.         }
  423.         dc << "\n}";
  424.     }
  425.  
  426.     dc << "\n";
  427. }
  428.  
  429. void CDocTemplate::AssertValid() const
  430. {
  431.     CCmdTarget::AssertValid();
  432.  
  433.     POSITION pos = GetFirstDocPosition();
  434.     while (pos != NULL)
  435.     {
  436.         CDocument* pDoc = GetNextDoc(pos);
  437.         ASSERT_VALID(pDoc);
  438.     }
  439. }
  440. #endif //_DEBUG
  441.  
  442. #ifdef AFX_INIT_SEG
  443. #pragma code_seg(AFX_INIT_SEG)
  444. #endif
  445.  
  446. IMPLEMENT_DYNAMIC(CDocTemplate, CCmdTarget)
  447.  
  448. /////////////////////////////////////////////////////////////////////////////
  449.