home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap22 / patron / document.cpp < prev    next >
C/C++ Source or Header  |  1996-05-23  |  40KB  |  1,683 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Patron Chapter 22
  4.  *
  5.  * Implementation of the CPatronDoc derivation of CDocument that
  6.  * manages pages for us.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #include "patron.h"
  17. #include <memory.h>
  18. #include <dlgs.h>       //Pring Dlg button IDs
  19.  
  20.  
  21. /*
  22.  * CPatronDoc::CPatronDoc
  23.  * CPatronDoc::~CPatronDoc
  24.  *
  25.  * Constructor Parameters:
  26.  *  hInst           HINSTANCE of the application.
  27.  *  pFR             PCFrame of the frame object.
  28.  *  pAdv            PCDocumentAdviseSink to notify on events.
  29.  */
  30.  
  31. CPatronDoc::CPatronDoc(HINSTANCE hInst, PCFrame pFR
  32.     , PCDocumentAdviseSink pAdv)
  33.     : CDocument(hInst, pFR, pAdv)
  34.     {
  35.     m_pPG=NULL;
  36.     m_lVer=VERSIONCURRENT;
  37.     m_pIStorage=NULL;
  38.     m_fPrintSetup=TRUE;
  39.     m_pDropTarget=NULL;
  40.  
  41.     //These CFSTR_* values are standard (defined in INC\CLASSLIB.H)
  42.     m_cfEmbeddedObject=RegisterClipboardFormat
  43.         (CFSTR_EMBEDDEDOBJECT);
  44.     m_cfObjectDescriptor=RegisterClipboardFormat
  45.         (CFSTR_OBJECTDESCRIPTOR);
  46.  
  47.     m_cfLinkSource=RegisterClipboardFormat(CFSTR_LINKSOURCE);
  48.     m_cfLinkSrcDescriptor=RegisterClipboardFormat
  49.         (CFSTR_LINKSRCDESCRIPTOR);
  50.  
  51.     m_fShowTypes=FALSE;
  52.     m_cRef=1L;
  53.     m_fRename=TRUE;
  54.     m_dwRegROT=0L;
  55.     m_dwRegROTWild=0L;
  56.     m_pImpIPersistFile=NULL;
  57.     m_pImpIOleItemContainer=NULL;
  58.  
  59.     //CHAPTER22MOD
  60.     m_pImpIOleIPUIWindow=NULL;
  61.     m_pIOleIPActiveObject=NULL;
  62.     m_fNoObjectFrameTools=TRUE;
  63.     //End CHAPTER22MOD
  64.  
  65.     return;
  66.     }
  67.  
  68.  
  69. CPatronDoc::~CPatronDoc(void)
  70.     {
  71.     INOLE_RevokeAsRunning(&m_dwRegROT);
  72.     INOLE_RevokeAsRunning(&m_dwRegROTWild);
  73.  
  74.     DeleteInterfaceImp(m_pImpIPersistFile);
  75.     DeleteInterfaceImp(m_pImpIOleItemContainer);
  76.  
  77.     if (NULL!=m_pPG)
  78.         delete m_pPG;
  79.  
  80.     //CHAPTER22MOD
  81.     DeleteInterfaceImp(m_pImpIOleIPUIWindow);
  82.     //End CHAPTER22MOD
  83.  
  84.     ReleaseInterface(m_pIStorage);
  85.     CoFreeUnusedLibraries();
  86.     return;
  87.     }
  88.  
  89.  
  90.  
  91.  
  92.  
  93. /*
  94.  * CPatronDoc::QueryInterface
  95.  * CPatronDoc::AddRef
  96.  * CPatronDoc::Release
  97.  */
  98.  
  99. STDMETHODIMP CPatronDoc::QueryInterface(REFIID riid, PPVOID ppv)
  100.     {
  101.     *ppv=NULL;
  102.  
  103.     /*
  104.      * WARNING:  Because the *ppv=this implicitly does
  105.      * *ppv=(LPVOID)this, the this pointer is incorrectly cast
  106.      * from a CPatronDoc pointer to LPVOID where we want an
  107.      * IUnknown pointer instead.  CPatronDoc uses multiple
  108.      * inheritance here which means that we have to explicitly
  109.      * provide the typecast to select the base class like
  110.      * IUnknown.  If you don't do this, calls to AddRef, for
  111.      * example, might call your desctructor!
  112.      */
  113.  
  114.     if (IID_IUnknown==riid)
  115.         *ppv=(LPUNKNOWN)this;
  116.  
  117.     if (IID_IOleItemContainer==riid || IID_IOleContainer==riid
  118.         || IID_IParseDisplayName==riid)
  119.         *ppv=m_pImpIOleItemContainer;
  120.  
  121.     if (IID_IPersistFile==riid || IID_IPersist==riid)
  122.         *ppv=m_pImpIPersistFile;
  123.  
  124.     //CHAPTER22MOD
  125.     if (IID_IOleWindow==riid || IID_IOleInPlaceUIWindow==riid)
  126.         *ppv=m_pImpIOleIPUIWindow;
  127.     //End CHAPTER22MOD
  128.  
  129.     if (NULL!=*ppv)
  130.         {
  131.         ((LPUNKNOWN)*ppv)->AddRef();
  132.         return NOERROR;
  133.         }
  134.  
  135.     return ResultFromScode(E_NOINTERFACE);
  136.     }
  137.  
  138.  
  139. STDMETHODIMP_(ULONG) CPatronDoc::AddRef(void)
  140.     {
  141.     return ++m_cRef;
  142.     }
  143.  
  144. STDMETHODIMP_(ULONG) CPatronDoc::Release(void)
  145.     {
  146.     if (0!=--m_cRef)
  147.         return m_cRef;
  148.  
  149.     PostMessage(m_hWnd, WM_CLOSE, 0, 0);
  150.     return 0;
  151.     }
  152.  
  153.  
  154.  
  155.  
  156. /*
  157.  * CPatronDoc::Init
  158.  *
  159.  * Purpose:
  160.  *  Initializes an already created document window.  The client
  161.  *  actually creates the window for us, then passes that here for
  162.  *  further initialization.
  163.  *
  164.  * Parameters:
  165.  *  pDI             PDOCUMENTINIT containing initialization
  166.  *                  parameters.
  167.  *
  168.  * Return Value:
  169.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  170.  */
  171.  
  172. BOOL CPatronDoc::Init(PDOCUMENTINIT pDI)
  173.     {
  174.     //Change the stringtable range to our customization.
  175.     pDI->idsMin=IDS_DOCUMENTMIN;
  176.     pDI->idsMax=IDS_DOCUMENTMAX;
  177.  
  178.     //Do default initialization
  179.     if (!CDocument::Init(pDI))
  180.         return FALSE;
  181.  
  182.     //Pages are created when we get a Load later.
  183.  
  184.     //Instantiate our interfaces
  185.     m_pImpIPersistFile=new CImpIPersistFile(this, this);
  186.  
  187.     if (NULL==m_pImpIPersistFile)
  188.         return FALSE;
  189.  
  190.     m_pImpIOleItemContainer=new CImpIOleItemContainer(this, this
  191.         , TRUE);
  192.  
  193.     if (NULL==m_pImpIOleItemContainer)
  194.         return FALSE;
  195.  
  196.     //CHAPTER22MOD
  197.     m_pImpIOleIPUIWindow=new CImpIOleInPlaceUIWindow(this, this);
  198.  
  199.     if (NULL==m_pImpIOleIPUIWindow)
  200.         return FALSE;
  201.     //End CHAPTER22MOD
  202.  
  203.     return TRUE;
  204.     }
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212. /*
  213.  * CPatronDoc::FMessageHook
  214.  *
  215.  * Purpose:
  216.  *  Processes WM_SIZE for the document so we can resize the Pages
  217.  *  window.
  218.  *
  219.  * Parameters:
  220.  *  <WndProc Parameters>
  221.  *  pLRes           LRESULT * in which to store the return
  222.  *                  value for the message.
  223.  *
  224.  * Return Value:
  225.  *  BOOL            TRUE to prevent further processing,
  226.  *                  FALSE otherwise.
  227.  */
  228.  
  229. BOOL CPatronDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  230.     , LPARAM lParam, LRESULT *pLRes)
  231.     {
  232.     UINT        dx, dy;
  233.     RECT        rc;
  234.  
  235.     *pLRes=0;
  236.  
  237.     //CHAPTER22MOD
  238.     //CLASSLIB always sends MDIACTIVATE, regardless of MDI or SDI.
  239.     if (WM_MDIACTIVATE==iMsg)
  240.         {
  241.         /*
  242.          * Win32 has hWndActivate in lParam.  Win16 has it in
  243.          * LOWORD(lParam).  (HWND)(UINT) handles both cases.
  244.          */
  245.         BOOL    fActivate=((HWND)(UINT)lParam==hWnd);
  246.  
  247.         if (NULL!=m_pIOleIPActiveObject)
  248.             {
  249.             //Hide our tools
  250.             if (fActivate)
  251.                 g_pFR->ShowUIAndTools(m_fNoObjectFrameTools, FALSE);
  252.  
  253.             m_pIOleIPActiveObject->OnDocWindowActivate(fActivate);
  254.             }
  255.         else
  256.             {
  257.             //Restore frame-level UI if we're becoming active.
  258.             if (fActivate)
  259.                 g_pFR->ReinstateUI();
  260.             }
  261.         }
  262.     //End CHAPTER22MOD
  263.  
  264.     //Eat to prevent flickering
  265.     if (WM_ERASEBKGND==iMsg)
  266.         return TRUE;
  267.  
  268.     if (WM_SIZE==iMsg && NULL!=m_pPG)
  269.         {
  270.         dx=LOWORD(lParam);
  271.         dy=HIWORD(lParam);
  272.  
  273.         if (SIZE_MINIMIZED!=wParam)
  274.             {
  275.             //Resize Pages window to fit the new document size.
  276.             GetClientRect(hWnd, &rc);
  277.             m_pPG->RectSet(&rc, FALSE);
  278.             }
  279.  
  280.         //CHAPTER22MOD
  281.         if (NULL!=m_pIOleIPActiveObject)
  282.             {
  283.             //Also tell in-place objects that document was resized.
  284.             m_pIOleIPActiveObject->ResizeBorder(&rc
  285.                 , m_pImpIOleIPUIWindow, FALSE);
  286.             }
  287.         //End CHAPTER22MOD
  288.         }
  289.  
  290.     if (WM_DESTROY==iMsg)
  291.         {
  292.         /*
  293.          * We have to revoke the drop target here because the window
  294.          * will be destroyed and the property forcefully removed
  295.          * before we could do this in the destructor.
  296.          */
  297.         if (NULL!=m_pDropTarget)
  298.             {
  299.             RevokeDragDrop(m_hWnd);
  300.             CoLockObjectExternal(m_pDropTarget, FALSE, TRUE);
  301.             m_pDropTarget->Release();
  302.             }
  303.  
  304.         return FALSE;
  305.         }
  306.  
  307.     /*
  308.      * We return FALSE even on WM_SIZE so we can let the default
  309.      * procedure handle maximized MDI child windows appropriately.
  310.      */
  311.     return FALSE;
  312.     }
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320. /*
  321.  * CPatronDoc::Clear
  322.  *
  323.  * Purpose:
  324.  *  Sets all contents in the document back to defaults with no
  325.  *  filename.
  326.  *
  327.  * Paramters:
  328.  *  None
  329.  *
  330.  * Return Value:
  331.  *  None
  332.  */
  333.  
  334. void CPatronDoc::Clear(void)
  335.     {
  336.     //Completely reset the pages
  337.     if (NULL!=m_pPG)
  338.         m_pPG->StorageSet(NULL, FALSE, FALSE);
  339.  
  340.     CDocument::Clear();
  341.     m_lVer=VERSIONCURRENT;
  342.     return;
  343.     }
  344.  
  345.  
  346.  
  347.  
  348. /*
  349.  * CPatronDoc::FDirtySet
  350.  *
  351.  * Purpose:
  352.  *  Sets or clears the document 'dirty' flag returning the previous
  353.  *  state of that same flag.  We override this to note change
  354.  *  times in the running object table.
  355.  *
  356.  * Parameters:
  357.  *  fDirty          BOOL indicating the new contents of the dirty
  358.  *                  flag.
  359.  *
  360.  * Return Value:
  361.  *  BOOL            Previous value of the dirty flag.
  362.  */
  363.  
  364. BOOL CPatronDoc::FDirtySet(BOOL fDirty)
  365.     {
  366.     BOOL        fRet;
  367.  
  368.     fRet=CDocument::FDirtySet(fDirty);
  369.     INOLE_NoteChangeTime(m_dwRegROT, NULL, NULL);
  370.     INOLE_NoteChangeTime(m_dwRegROTWild, NULL, NULL);
  371.  
  372.     return fRet;
  373.     }
  374.  
  375.  
  376.  
  377.  
  378. /*
  379.  * CPatronDoc::FDirtyGet
  380.  *
  381.  * Purpose:
  382.  *  Returns the current dirty status of the document.
  383.  *
  384.  * Parameters:
  385.  *  None
  386.  *
  387.  * Return Value:
  388.  *  BOOL            TRUE if the file is clean, FALSE otherwise.
  389.  */
  390.  
  391. BOOL CPatronDoc::FDirtyGet()
  392.     {
  393.     BOOL    fPageDirty;
  394.  
  395.     fPageDirty=m_pPG->FIsDirty();
  396.     return m_fDirty | fPageDirty;
  397.     }
  398.  
  399.  
  400.  
  401.  
  402.  
  403. /*
  404.  * CPatronDoc::Delete
  405.  *
  406.  * Purpose:
  407.  *  Removed the current object from the document.
  408.  *
  409.  * Paramters:
  410.  *  None
  411.  *
  412.  * Return Value:
  413.  *  None
  414.  */
  415.  
  416. void CPatronDoc::Delete(void)
  417.     {
  418.     if (NULL!=m_pPG)
  419.         m_pPG->TenantDestroy();
  420.  
  421.     CoFreeUnusedLibraries();
  422.     return;
  423.     }
  424.  
  425.  
  426.  
  427.  
  428.  
  429. /*
  430.  * CPatronDoc::FQueryObjectSelected
  431.  *
  432.  * Purpose:
  433.  *  Returns whether or not there is an object selected in this
  434.  *  document for Cut, Copy, Delete functions.
  435.  *
  436.  * Parameters:
  437.  *  hMenu           HMENU of the Edit menu.
  438.  *
  439.  * Return Value:
  440.  *  BOOL            TRUE if we have an object, FALSE otherwise.
  441.  */
  442.  
  443. BOOL CPatronDoc::FQueryObjectSelected(HMENU hMenu)
  444.     {
  445.     return m_pPG->FQueryObjectSelected(hMenu);
  446.     }
  447.  
  448.  
  449.  
  450.  
  451.  
  452. /*
  453.  * CPatronDoc::Load
  454.  *
  455.  * Purpose:
  456.  *  Loads a given document without any user interface overwriting
  457.  *  the previous contents of the editor.
  458.  *
  459.  * Parameters:
  460.  *  fChangeFile     BOOL indicating if we're to update the window
  461.  *                  title and the filename from using this file.
  462.  *  pszFile         LPTSTR to the filename to load.  Could be NULL
  463.  *                  for an untitled document.
  464.  *
  465.  * Return Value:
  466.  *  UINT            An error value from DOCERR_*
  467.  */
  468.  
  469. UINT CPatronDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  470.     {
  471.     RECT        rc;
  472.     LPSTORAGE   pIStorage;
  473.     HRESULT     hr;
  474.     CLSID       clsID;
  475.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE
  476.                     | STGM_SHARE_EXCLUSIVE;
  477.     LPMONIKER   pmk;
  478.  
  479.     if (NULL==pszFile)
  480.         {
  481.         //Create a new temp file.
  482.         hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE
  483.             | STGM_DELETEONRELEASE, 0, &pIStorage);
  484.  
  485.         //Mark this our class since we check with ReadClassStg.
  486.         if (SUCCEEDED(hr))
  487.             WriteClassStg(pIStorage, CLSID_PatronPages);
  488.         }
  489.     else
  490.         {
  491.         hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
  492.         }
  493.  
  494.     if (FAILED(hr))
  495.         return DOCERR_COULDNOTOPEN;
  496.  
  497.     //Check if this is our type of file and exit if not.
  498.     hr=ReadClassStg(pIStorage, &clsID);
  499.  
  500.     if (FAILED(hr) || CLSID_PatronPages!=clsID)
  501.         {
  502.         pIStorage->Release();
  503.         return DOCERR_READFAILURE;
  504.         }
  505.  
  506.     //Attempt to create our contained Pages window.
  507.     m_pPG=new CPages(m_hInst, m_cf);
  508.     GetClientRect(m_hWnd, &rc);
  509.  
  510.     //CHAPTER22MOD
  511.     //Always use WS_CLIPCHILDREN with in-place support.
  512.     if (!m_pPG->Init(m_hWnd, &rc, WS_CLIPCHILDREN | WS_CHILD
  513.         | WS_VISIBLE, ID_PAGES, NULL))
  514.     //End CHAPTER22MOD
  515.         {
  516.         pIStorage->Release();
  517.         return DOCERR_READFAILURE;
  518.         }
  519.  
  520.     /*
  521.      * This moniker registration insures that all the file opening
  522.      * sequence will see this instance of the document as running
  523.      * and be able to communicate with it.  This is so a link to
  524.      * an embedding on the same page of this document will hook
  525.      * up correctly.
  526.      */
  527.     if (NULL!=pszFile)
  528.         {
  529.         CreateFileMoniker(pszFile, &pmk);
  530.  
  531.         if (NULL!=pmk)
  532.             {
  533.             //This will be revoked and re-registered in Rename below
  534.             INOLE_RegisterAsRunning(this, pmk, 0, &m_dwRegROT);
  535.             pmk->Release();
  536.             }
  537.         }
  538.  
  539.     if (!m_pPG->StorageSet(pIStorage, FALSE, (NULL==pszFile)))
  540.         {
  541.         pIStorage->Release();
  542.         return DOCERR_READFAILURE;
  543.         }
  544.  
  545.     //Open the window up for drag-drop
  546.     m_pDropTarget=new CDropTarget(this);
  547.  
  548.     if (NULL!=m_pDropTarget)
  549.         {
  550.         m_pDropTarget->AddRef();
  551.         CoLockObjectExternal(m_pDropTarget, TRUE, FALSE);
  552.         RegisterDragDrop(m_hWnd, m_pDropTarget);
  553.         }
  554.  
  555.     m_pIStorage=pIStorage;
  556.     Rename(pszFile);
  557.  
  558.     //Do initial setup if new file, otherwise Pages handles things.
  559.     if (NULL==pszFile)
  560.         {
  561.         //Go initialize the Pages for the default printer.
  562.         if (!PrinterSetup(NULL, TRUE))
  563.             return DOCERR_COULDNOTOPEN;
  564.  
  565.         //Go create an initial page.
  566.         m_pPG->PageInsert(0);
  567.         }
  568.     else
  569.         {
  570.         //Can't change an already saved configuration
  571.         m_fPrintSetup=FALSE;
  572.         }
  573.  
  574.     FDirtySet(FALSE);
  575.     return DOCERR_NONE;
  576.     }
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584. /*
  585.  * CPatronDoc::Save
  586.  *
  587.  * Purpose:
  588.  *  Writes the file to a known filename, requiring that the user
  589.  *  has previously used FileOpen or FileSaveAs in order to have
  590.  *  a filename.
  591.  *
  592.  * Parameters:
  593.  *  uType           UINT indicating the type of file the user
  594.  *                  requested to save in the File Save As dialog.
  595.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  596.  *                  current name.
  597.  *
  598.  * Return Value:
  599.  *  UINT            An error value from DOCERR_*
  600.  */
  601.  
  602. UINT CPatronDoc::Save(UINT uType, LPTSTR pszFile)
  603.     {
  604.     HRESULT     hr;
  605.     LPSTORAGE   pIStorage;
  606.  
  607.     //Save or Save As with the same file is just a commit.
  608.     if (NULL==pszFile
  609.         || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
  610.         {
  611.         WriteFmtUserTypeStg(m_pIStorage, m_cf
  612.             , PSZ(IDS_CLIPBOARDFORMAT));
  613.  
  614.         //Insure pages are up to date.
  615.         m_pPG->StorageUpdate(FALSE);
  616.  
  617.         //Commit everyting
  618.         m_pIStorage->Commit(STGC_DEFAULT);
  619.  
  620.         FDirtySet(FALSE);
  621.         return DOCERR_NONE;
  622.         }
  623.  
  624.     /*
  625.      * When we're given a name, open the storage, creating it new
  626.      * if it does not exist or overwriting the old one.  Then CopyTo
  627.      * from the current to the new, Commit the new, Release the old.
  628.      */
  629.  
  630.     hr=StgCreateDocfile(pszFile, STGM_TRANSACTED | STGM_READWRITE
  631.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  632.  
  633.     if (FAILED(hr))
  634.         return DOCERR_COULDNOTOPEN;
  635.  
  636.     WriteClassStg(pIStorage, CLSID_PatronPages);
  637.     WriteFmtUserTypeStg(pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  638.  
  639.     //Insure all pages are up-to-date.
  640.     m_pPG->StorageUpdate(TRUE);
  641.  
  642.     //This also copies the CLSID we stuff in here on file creation.
  643.     hr=m_pIStorage->CopyTo(NULL, NULL, NULL, pIStorage);
  644.  
  645.     if (FAILED(hr))
  646.         {
  647.         SCODE       sc;
  648.  
  649.         pIStorage->Release();
  650.         sc=GetScode(hr);
  651.  
  652.         /*
  653.          * If we failed because of low memory, use IRootStorage
  654.          * to switch into the new file.
  655.          */
  656.         if (E_OUTOFMEMORY==sc)
  657.             {
  658.             LPROOTSTORAGE        pIRoot;
  659.  
  660.             //Delete file we already created
  661.             DeleteFile(pszFile);
  662.  
  663.             if (FAILED(m_pIStorage->QueryInterface
  664.                 (IID_IRootStorage, (PPVOID)&pIRoot)))
  665.                 return DOCERR_WRITEFAILURE;
  666.  
  667.            #ifdef WIN32ANSI
  668.             OLECHAR     szTemp[MAX_PATH];
  669.  
  670.             MultiByteToWideChar(CP_ACP, 0, pszFile, -1, szTemp, MAX_PATH);
  671.             hr=pIRoot->SwitchToFile(szTemp);
  672.            #else
  673.             hr=pIRoot->SwitchToFile(pszFile);
  674.            #endif
  675.             pIRoot->Release();
  676.  
  677.             if (FAILED(hr))
  678.                 return DOCERR_WRITEFAILURE;
  679.  
  680.             //If successful, the Commit below finishes the save.
  681.             pIStorage=m_pIStorage;
  682.             m_pIStorage->AddRef();    //Matches Release below
  683.             }
  684.         }
  685.  
  686.     if (m_fRename)
  687.         Rename(pszFile);    //Update caption bar.
  688.  
  689.     pIStorage->Commit(STGC_DEFAULT);
  690.  
  691.     /*
  692.      * Revert changes on the original storage.  If this was a temp
  693.      * file, it's deleted since we used STGM_DELETEONRELEASE.
  694.      */
  695.     m_pIStorage->Release();
  696.  
  697.     //Make this new storage current
  698.     m_pIStorage=pIStorage;
  699.     m_pPG->StorageSet(pIStorage, TRUE, FALSE);
  700.  
  701.     FDirtySet(FALSE);
  702.  
  703.     return DOCERR_NONE;
  704.     }
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713. /*
  714.  * CPatronDoc::Clip
  715.  *
  716.  * Purpose:
  717.  *  Places a private format, a metafile, and a bitmap of the display
  718.  *  on the clipboard, optionally implementing Cut by deleting the
  719.  *  data in the current window after rendering.
  720.  *
  721.  * Parameters:
  722.  *  hWndFrame       HWND of the main window.
  723.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  724.  *
  725.  * Return Value:
  726.  *  BOOL            TRUE if successful, FALSE otherwise.
  727.  */
  728.  
  729. BOOL CPatronDoc::Clip(HWND hWndFrame, BOOL fCut)
  730.     {
  731.     if (NULL==m_pPG)
  732.         return FALSE;
  733.  
  734.     return m_pPG->TenantClip(fCut);
  735.     }
  736.  
  737.  
  738.  
  739.  
  740.  
  741. /*
  742.  * CPatronDoc::Paste
  743.  *
  744.  * Purpose:
  745.  *  Retrieves the private data format from the clipboard and sets it
  746.  *  to the current figure in the editor window.
  747.  *
  748.  *  Note that if this function is called, then the clipboard format
  749.  *  is available because the Paste menu item is only enabled if the
  750.  *  format is present.
  751.  *
  752.  * Parameters:
  753.  *  hWndFrame       HWND of the main window.
  754.  *
  755.  * Return Value:
  756.  *  BOOL            TRUE if successful, FALSE otherwise.
  757.  */
  758.  
  759. BOOL CPatronDoc::Paste(HWND hWndFrame)
  760.     {
  761.     LPDATAOBJECT    pIDataObject;
  762.     BOOL            fRet=FALSE;
  763.     FORMATETC       fe;
  764.     TENANTTYPE      tType;
  765.  
  766.     if (NULL==m_pPG)
  767.         return FALSE;
  768.  
  769.     if (FAILED(OleGetClipboard(&pIDataObject)))
  770.         return FALSE;
  771.  
  772.     //Go get type and format we *can* paste, then actually paste it.
  773.     if (FQueryPasteFromData(pIDataObject, &fe, &tType))
  774.         {
  775.         fRet=PasteFromData(pIDataObject, &fe, tType, NULL
  776.             , 0L, TRUE);
  777.         }
  778.  
  779.     pIDataObject->Release();
  780.     return fRet;
  781.     }
  782.  
  783.  
  784.  
  785.  
  786. /*
  787.  * CPatronDoc::FQueryPaste
  788.  *
  789.  * Purpose:
  790.  *  Determines if we can paste data from the clipboard.
  791.  *
  792.  * Parameters:
  793.  *  None
  794.  *
  795.  * Return Value:
  796.  *  BOOL            TRUE if data is available, FALSE otherwise.
  797.  */
  798.  
  799. BOOL CPatronDoc::FQueryPaste(void)
  800.     {
  801.     LPDATAOBJECT    pIDataObject;
  802.     BOOL            fRet;
  803.  
  804.     if (FAILED(OleGetClipboard(&pIDataObject)))
  805.         return FALSE;
  806.  
  807.     fRet=FQueryPasteFromData(pIDataObject, NULL, NULL);
  808.  
  809.     fRet |= FQueryPasteLinkFromData(pIDataObject, NULL, NULL);
  810.     pIDataObject->Release();
  811.     return fRet;
  812.     }
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819. /*
  820.  * CPatronDoc::PasteSpecial
  821.  *
  822.  * Purpose:
  823.  *  Retrieves a specific data format from the clipboard and sends
  824.  *  it to the editor window appropriately.
  825.  *
  826.  *  Note that if this function is called, then the appropriate
  827.  *  format is available because the Paste menu item is only
  828.  *  enabled if the format is present.
  829.  *
  830.  * Parameters:
  831.  *  hWndFrame       HWND of the main window
  832.  *
  833.  * Return Value:
  834.  *  BOOL            TRUE if successful, FALSE otherwise.
  835.  */
  836.  
  837. BOOL CPatronDoc::PasteSpecial(HWND hWndFrame)
  838.     {
  839.     OLEUIPASTESPECIAL   ps;
  840.     OLEUIPASTEENTRY     rgPaste[6];
  841.     UINT                rgcf[1];        //For ps.m_arrLinkTypes
  842.     DWORD               dwData=0;
  843.     UINT                uTemp;
  844.     BOOL                fRet=FALSE;
  845.  
  846.     if (NULL==m_pPG)
  847.         return FALSE;
  848.  
  849.     memset(&ps, 0, sizeof(ps));
  850.  
  851.     if (FAILED(OleGetClipboard(&ps.lpSrcDataObj)))
  852.         return FALSE;
  853.  
  854.     ps.cbStruct=sizeof(ps);
  855.     ps.hWndOwner=hWndFrame;
  856.  
  857.     ps.dwFlags=PSF_SELECTPASTE;
  858.     ps.arrPasteEntries=rgPaste;
  859.  
  860.     //Set up Paste Special descriptor arrays.
  861.     SETDefFormatEtc(rgPaste[0].fmtetc, m_cf, TYMED_HGLOBAL);
  862.     rgPaste[0].lpstrFormatName=PSZ(IDS_CLIPBOARDFORMAT);
  863.     rgPaste[0].lpstrResultText=PSZ(IDS_PASTEASPATRON);
  864.     rgPaste[0].dwFlags=OLEUIPASTE_PASTEONLY;
  865.  
  866.     //Embedded objects can be iconic displays if the user wants.
  867.     SETDefFormatEtc(rgPaste[1].fmtetc, m_cfEmbeddedObject
  868.         , TYMED_ISTORAGE);
  869.     rgPaste[1].lpstrFormatName=PSZ(IDS_PASTEOBJECT);
  870.     rgPaste[1].lpstrResultText=PSZ(IDS_PASTEASOBJECT);
  871.  
  872.     /*
  873.      * CAUTION:  Use OLEUI_PASTE with embedded objects or else
  874.      * this item will not show up in the dialog.  I learned this the
  875.      * hard way (that is, after about 6 hours of pulling hair!).
  876.      */
  877.     rgPaste[1].dwFlags=OLEUIPASTE_PASTE | OLEUIPASTE_ENABLEICON;
  878.  
  879.  
  880.     SETDefFormatEtc(rgPaste[2].fmtetc,CF_METAFILEPICT,TYMED_MFPICT);
  881.     rgPaste[2].lpstrFormatName=PSZ(IDS_PASTEMETAFILE);
  882.     rgPaste[2].lpstrResultText=PSZ(IDS_PASTEASMETAFILE);
  883.     rgPaste[2].dwFlags=OLEUIPASTE_PASTEONLY;
  884.  
  885.     SETDefFormatEtc(rgPaste[3].fmtetc, CF_DIB, TYMED_HGLOBAL);
  886.     rgPaste[3].lpstrFormatName=PSZ(IDS_PASTEDIB);
  887.     rgPaste[3].lpstrResultText=PSZ(IDS_PASTEASDIB);
  888.     rgPaste[3].dwFlags=OLEUIPASTE_PASTEONLY;
  889.  
  890.     SETDefFormatEtc(rgPaste[4].fmtetc, CF_BITMAP, TYMED_GDI);
  891.     rgPaste[4].lpstrFormatName=PSZ(IDS_PASTEBITMAP);
  892.     rgPaste[4].lpstrResultText=PSZ(IDS_PASTEASBITMAP);
  893.     rgPaste[4].dwFlags=OLEUIPASTE_PASTEONLY;
  894.  
  895.     SETDefFormatEtc(rgPaste[5].fmtetc,m_cfLinkSource,TYMED_ISTREAM);
  896.     rgPaste[5].lpstrFormatName=PSZ(IDS_PASTELINK);
  897.     rgPaste[5].lpstrResultText=PSZ(IDS_PASTEASLINK);
  898.     rgPaste[5].dwFlags=OLEUIPASTE_LINKTYPE1 | OLEUIPASTE_ENABLEICON;
  899.  
  900.     //Types we can Paste Link from the clipboard.
  901.     rgcf[0]=m_cfLinkSource;
  902.     ps.arrLinkTypes=rgcf;
  903.     ps.cLinkTypes=1;
  904.     ps.cPasteEntries=6;
  905.  
  906.     uTemp=OleUIPasteSpecial(&ps);
  907.  
  908.     if (OLEUI_OK==uTemp)
  909.         {
  910.         UINT        i=ps.nSelectedIndex;
  911.         TENANTTYPE  tType;
  912.  
  913.         if (ps.fLink)
  914.             tType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  915.         else
  916.             {
  917.             if (1==ps.nSelectedIndex)
  918.                 tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  919.             else
  920.                 tType=TENANTTYPE_STATIC;
  921.             }
  922.  
  923.         //Handle iconic aspects...from links as well
  924.         if ((1==i || ps.fLink) && (PSF_CHECKDISPLAYASICON
  925.             & ps.dwFlags) && NULL!=ps.hMetaPict)
  926.             {
  927.             rgPaste[i].fmtetc.dwAspect=DVASPECT_ICON;
  928.             dwData=(DWORD)(UINT)ps.hMetaPict;
  929.             }
  930.  
  931.         fRet=PasteFromData(ps.lpSrcDataObj, &rgPaste[i].fmtetc
  932.             , tType, NULL, dwData, FALSE);
  933.  
  934.         //Always free this regardless of what we do with it.
  935.         INOLE_MetafilePictIconFree(ps.hMetaPict);
  936.         }
  937.  
  938.     ps.lpSrcDataObj->Release();
  939.     return fRet;
  940.     }
  941.  
  942.  
  943.  
  944.  
  945. /*
  946.  * CPatronDoc::FQueryPasteFromData
  947.  * (Protected)
  948.  *
  949.  * Purpose:
  950.  *  Determines if we can paste data from a data object.
  951.  *
  952.  * Parameters:
  953.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  954.  *  pFE             LPFORMATETC in which to return the first format
  955.  *                  we can use.  Ignored if NULL.
  956.  *  ptType          PTENANTTYPE in which to store the type of
  957.  *                  object we can paste.  Ignored if NULL.
  958.  *
  959.  * Return Value:
  960.  *  BOOL            TRUE if data is available, FALSE otherwise.
  961.  */
  962.  
  963. BOOL CPatronDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject
  964.     , LPFORMATETC pFE, PTENANTTYPE ptType)
  965.     {
  966.     FORMATETC       fe;
  967.     HRESULT         hr, hr2;
  968.  
  969.     if (NULL!=(LPVOID)ptType)
  970.         *ptType=TENANTTYPE_STATIC;
  971.  
  972.     //Any of our specific data here?
  973.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  974.     hr=pIDataObject->QueryGetData(&fe);
  975.  
  976.     //If embedded object data is available, set the appropriate type
  977.     hr2=OleQueryCreateFromData(pIDataObject);
  978.  
  979.     if (NOERROR==hr2)
  980.         {
  981.         if (NULL!=pFE)
  982.             {
  983.             /*
  984.              * Default to content.  Paste will use
  985.              * CFSTR_OBJECTDESCRIPTOR to figure the actual aspect.
  986.              */
  987.             SETDefFormatEtc(*pFE, m_cfEmbeddedObject
  988.                 , TYMED_ISTORAGE);
  989.             }
  990.  
  991.         if (NULL!=(LPVOID)ptType)
  992.             *ptType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  993.  
  994.         /*
  995.          * Return now if PatronObject wasn't available, otherwise
  996.          * break out so that pFE gets PatronObject format.
  997.          */
  998.         if (NOERROR!=hr)
  999.             return TRUE;
  1000.         }
  1001.  
  1002.  
  1003.     if (NOERROR!=hr && NOERROR!=hr2)
  1004.         {
  1005.         //Try metafile, DIB, then bitmap, setting fe each time
  1006.         SETDefFormatEtc(fe, CF_METAFILEPICT, TYMED_MFPICT);
  1007.         hr=pIDataObject->QueryGetData(&fe);
  1008.  
  1009.         if (NOERROR!=hr)
  1010.             {
  1011.             SETDefFormatEtc(fe, CF_DIB, TYMED_HGLOBAL);
  1012.             hr=pIDataObject->QueryGetData(&fe);
  1013.  
  1014.             if (NOERROR!=hr)
  1015.                 {
  1016.                 SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
  1017.                 hr=pIDataObject->QueryGetData(&fe);
  1018.                 }
  1019.             }
  1020.         }
  1021.  
  1022.     if (NOERROR==hr && NULL!=pFE)
  1023.         *pFE=fe;
  1024.  
  1025.     return (NOERROR==hr);
  1026.     }
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032. /*
  1033.  * CPatronDoc::FQueryPasteLinkFromData
  1034.  * (Protected)
  1035.  *
  1036.  * Purpose:
  1037.  *  Determines if we can paste link from a data object.
  1038.  *
  1039.  * Parameters:
  1040.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  1041.  *  pFE             LPFORMATETC in which to return the first format
  1042.  *                  we can use.  Ignored if NULL.
  1043.  *  ptType          PTENANTTYPE in which to store the type of object
  1044.  *                  we can paste.  Ignored if NULL.
  1045.  *
  1046.  * Return Value:
  1047.  *  BOOL            TRUE if data is available, FALSE otherwise.
  1048.  */
  1049.  
  1050. BOOL CPatronDoc::FQueryPasteLinkFromData(LPDATAOBJECT pIDataObject
  1051.     , LPFORMATETC pFE, PTENANTTYPE ptType)
  1052.     {
  1053.     HRESULT         hr;
  1054.  
  1055.     if (NULL==pIDataObject)
  1056.         return FALSE;
  1057.  
  1058.     hr=OleQueryLinkFromData(pIDataObject);
  1059.  
  1060.     if (NOERROR!=hr)
  1061.         return FALSE;
  1062.  
  1063.     if (NULL!=pFE)
  1064.         SETDefFormatEtc(*pFE, m_cfLinkSource, TYMED_ISTREAM);
  1065.  
  1066.     if (NULL!=(LPVOID)ptType)
  1067.         *ptType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  1068.  
  1069.     return TRUE;
  1070.     }
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077. /*
  1078.  * CPatronDoc::PasteFromData
  1079.  * (Protected)
  1080.  *
  1081.  * Purpose:
  1082.  *  Retrieves the private data format from a data object and sets
  1083.  *  it to the current figure in the editor window.
  1084.  *
  1085.  * Parameters:
  1086.  *  pIDataObject    LPDATAOBJECT from which to paste.
  1087.  *  pFE             LPFORMATETC to use in the paste. Cannot be NULL.
  1088.  *  tType           TENANTTYPE to paste.
  1089.  *  ppo             PPATRONOBJECT containing placement data.
  1090.  *  dwData          DWORD extra data sensitive to tType
  1091.  *  fUseObjDesc     BOOL indicating to use CFSTR_OBJECTDESCRIPTOR
  1092.  *                  format for determining the aspect of the object
  1093.  *                  if the format is available.
  1094.  *
  1095.  * Return Value:
  1096.  *  BOOL            TRUE if successful, FALSE otherwise.
  1097.  */
  1098.  
  1099. BOOL CPatronDoc::PasteFromData(LPDATAOBJECT pIDataObject
  1100.     , LPFORMATETC pFE, TENANTTYPE tType, PPATRONOBJECT ppo
  1101.     , DWORD dwData, BOOL fUseObjDesc)
  1102.     {
  1103.     BOOL                fRet;
  1104.     HRESULT             hr;
  1105.     PATRONOBJECT        po;
  1106.     STGMEDIUM           stm;
  1107.     LPOBJECTDESCRIPTOR  pOD;
  1108.     FORMATETC           fe;
  1109.     BOOL                fRelease=FALSE;
  1110.  
  1111.     if (NULL==pFE)
  1112.         return FALSE;
  1113.  
  1114.     //If not given any placement data, see if we can retrieve it
  1115.     if (pFE->cfFormat==m_cf && NULL==ppo)
  1116.         {
  1117.         hr=pIDataObject->GetData(pFE, &stm);
  1118.  
  1119.         if (SUCCEEDED(hr))
  1120.             {
  1121.             ppo=(PPATRONOBJECT)GlobalLock(stm.hGlobal);
  1122.  
  1123.             po=*ppo;
  1124.             ppo=&po;
  1125.  
  1126.             //If there's an object here, make sure type is right.
  1127.             if (ppo->fe.cfFormat==m_cfEmbeddedObject)
  1128.                 tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  1129.  
  1130.             if (ppo->fe.cfFormat==m_cfLinkSource)
  1131.                 tType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  1132.  
  1133.             GlobalUnlock(stm.hGlobal);
  1134.             ReleaseStgMedium(&stm);
  1135.             }
  1136.         }
  1137.  
  1138.     /*
  1139.      * If we're told to look at CFSTR_OBJECTDESCRIPTOR, then try to get
  1140.      * the data and copy the aspect out of it.  We're not interested
  1141.      * in any other part of it, however.
  1142.      */
  1143.     if (fUseObjDesc)
  1144.         {
  1145.         SETDefFormatEtc(fe, m_cfObjectDescriptor, TYMED_HGLOBAL);
  1146.  
  1147.         hr=pIDataObject->GetData(&fe, &stm);
  1148.  
  1149.         if (FAILED(hr))
  1150.             {
  1151.             SETDefFormatEtc(fe, m_cfLinkSrcDescriptor
  1152.                 , TYMED_HGLOBAL);
  1153.             hr=pIDataObject->GetData(&fe, &stm);
  1154.             }
  1155.  
  1156.         if (SUCCEEDED(hr))
  1157.             {
  1158.             pOD=(LPOBJECTDESCRIPTOR)GlobalLock(stm.hGlobal);
  1159.             pFE->dwAspect=pOD->dwDrawAspect;
  1160.  
  1161.             if (NULL!=ppo)
  1162.                 ppo->fe.dwAspect=pFE->dwAspect;
  1163.  
  1164.             GlobalUnlock(stm.hGlobal);
  1165.             ReleaseStgMedium(&stm);
  1166.  
  1167.             /*
  1168.              * Furthermore, if pFE->dwAspect is DVASPECT_ICON, get
  1169.              * the metafile which will always be the icon
  1170.              * representation.
  1171.              */
  1172.             SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
  1173.                 , TYMED_MFPICT, -1);
  1174.  
  1175.             if (SUCCEEDED(pIDataObject->GetData(&fe, &stm)))
  1176.                 {
  1177.                 dwData=(DWORD)(UINT)stm.hGlobal;
  1178.                 fRelease=TRUE;
  1179.                 }
  1180.             }
  1181.         }
  1182.  
  1183.     fRet=m_pPG->TenantCreate(tType, pIDataObject, pFE, ppo, dwData);
  1184.  
  1185.     //Release the stm from the last GetData
  1186.     if (fRelease)
  1187.         ReleaseStgMedium(&stm);
  1188.  
  1189.     if (fRet)
  1190.         {
  1191.         //Disable Printer Setup once we've created a tenant.
  1192.         m_fPrintSetup=FALSE;
  1193.         FDirtySet(TRUE);
  1194.         }
  1195.  
  1196.     return fRet;
  1197.     }
  1198.  
  1199.  
  1200.  
  1201.  
  1202. /*
  1203.  * CPatronDoc::FQueryEnableEditLinks
  1204.  *
  1205.  * Purpose:
  1206.  *  Determines whether or not the Edit Links menu item should be
  1207.  *  enabled on the frame window menu.
  1208.  *
  1209.  * Parameters:
  1210.  *  None
  1211.  *
  1212.  * Return Value:
  1213.  *  BOOL            TRUE to enable the item, FALSE otherwise.
  1214.  */
  1215.  
  1216. BOOL CPatronDoc::FQueryEnableEditLinks(void)
  1217.     {
  1218.     return m_pPG->FQueryLinksInPage();
  1219.     }
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225. /*
  1226.  * CPatronDoc::EditLinks
  1227.  *
  1228.  * Purpose:
  1229.  *  Invokes the links dialog in which the end-user can manipulate
  1230.  *  all the links in the current page.
  1231.  *
  1232.  * Parameters:
  1233.  *  hWndFrame       HWND of the frame window to use as the dialog
  1234.  *                  parent.
  1235.  *
  1236.  * Return Value:
  1237.  *  BOOL            TRUE if the function was successful,
  1238.  *                  FALSE otherwise.
  1239.  */
  1240.  
  1241. BOOL CPatronDoc::EditLinks(HWND hWndFrame)
  1242.     {
  1243.     UINT                    uRet;
  1244.     OLEUIEDITLINKS          el;
  1245.     PCIOleUILinkContainer   pIUILinks;
  1246.  
  1247.     memset(&el, 0, sizeof(el));
  1248.     el.cbStruct=sizeof(el);
  1249.     el.hWndOwner=hWndFrame;
  1250.  
  1251.     if (!m_pPG->GetUILinkContainer(&pIUILinks))
  1252.         return FALSE;
  1253.  
  1254.     el.lpOleUILinkContainer=pIUILinks;
  1255.     uRet=OleUIEditLinks(&el);
  1256.  
  1257.     //Only the IOleUILinkContainer interface will know dirtying.
  1258.     m_fDirty=pIUILinks->m_fDirty;
  1259.  
  1260.     el.lpOleUILinkContainer->Release();
  1261.     return TRUE;
  1262.     }
  1263.  
  1264.  
  1265.  
  1266. /*
  1267.  * CPatronDoc::ShowOrQueryObjectTypes
  1268.  *
  1269.  * Purpose:
  1270.  *  If querying, we return whether or not ShowObjects is active
  1271.  *  in this document.  Otherwise pass-through to
  1272.  *  CPages::ShowObjectTypes.
  1273.  *
  1274.  * Parameters:
  1275.  *  fQuery          BOOL indicating query or set.
  1276.  *  fShow           BOOL indicating to show the type or not.
  1277.  *
  1278.  * Return Value:
  1279.  *  None
  1280.  */
  1281.  
  1282. BOOL CPatronDoc::ShowOrQueryObjectTypes(BOOL fQuery, BOOL fShow)
  1283.     {
  1284.     if (fQuery)
  1285.         return m_fShowTypes;
  1286.  
  1287.     m_fShowTypes=fShow;
  1288.     m_pPG->ShowObjectTypes(fShow);
  1289.     return TRUE;
  1290.     }
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297. /*
  1298.  * CPatronDoc::NewPage
  1299.  *
  1300.  * Purpose:
  1301.  *  Creates a new page in the document's pages control after the
  1302.  *  current page.
  1303.  *
  1304.  * Parameters:
  1305.  *  None
  1306.  *
  1307.  * Return Value:
  1308.  *  UINT            Index of the new page.
  1309.  */
  1310.  
  1311. UINT CPatronDoc::NewPage(void)
  1312.     {
  1313.     FDirtySet(TRUE);
  1314.     return m_pPG->PageInsert(0);
  1315.     }
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323. /*
  1324.  * CPatronDoc::DeletePage
  1325.  *
  1326.  * Purpose:
  1327.  *  Deletes the current page from the document.
  1328.  *
  1329.  * Parameters:
  1330.  *  None
  1331.  *
  1332.  * Return Value:
  1333.  *  UINT            Index of the now current page.
  1334.  */
  1335.  
  1336. UINT CPatronDoc::DeletePage(void)
  1337.     {
  1338.     FDirtySet(TRUE);
  1339.     return m_pPG->PageDelete(0);
  1340.     }
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348. /*
  1349.  * CPatronDoc::NextPage
  1350.  *
  1351.  * Purpose:
  1352.  *  Shows the next page in the pages window.
  1353.  *
  1354.  * Parameters:
  1355.  *  None
  1356.  *
  1357.  * Return Value:
  1358.  *  UINT            Index of the new page.
  1359.  */
  1360.  
  1361. UINT CPatronDoc::NextPage(void)
  1362.     {
  1363.     UINT        iPage;
  1364.  
  1365.     iPage=m_pPG->CurPageGet();
  1366.     return m_pPG->CurPageSet(++iPage);
  1367.     }
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375. /*
  1376.  * CPatronDoc::PreviousPage
  1377.  *
  1378.  * Purpose:
  1379.  *  Shows the previous page in the pages window.
  1380.  *
  1381.  * Parameters:
  1382.  *  None
  1383.  *
  1384.  * Return Value:
  1385.  *  UINT            Index of the new page.
  1386.  */
  1387.  
  1388. UINT CPatronDoc::PreviousPage(void)
  1389.     {
  1390.     UINT        iPage;
  1391.  
  1392.     //If iPage is zero, then we wrap around to the end.
  1393.     iPage=m_pPG->CurPageGet();
  1394.     return m_pPG->CurPageSet(--iPage);
  1395.     }
  1396.  
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402. /*
  1403.  * CPatronDoc::FirstPage
  1404.  *
  1405.  * Purpose:
  1406.  *  Shows the first page page in the pages window.
  1407.  *
  1408.  * Parameters:
  1409.  *  None
  1410.  *
  1411.  * Return Value:
  1412.  *  UINT            Index of the new page.
  1413.  */
  1414.  
  1415. UINT CPatronDoc::FirstPage(void)
  1416.     {
  1417.     return m_pPG->CurPageSet(0);
  1418.     }
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425. /*
  1426.  * CPatronDoc::LastPage
  1427.  *
  1428.  * Purpose:
  1429.  *  Shows the last page in the pages window.
  1430.  *
  1431.  * Parameters:
  1432.  *  None
  1433.  *
  1434.  * Return Value:
  1435.  *  UINT            Index of the last page.
  1436.  */
  1437.  
  1438. UINT CPatronDoc::LastPage(void)
  1439.     {
  1440.     return m_pPG->CurPageSet(NOVALUE);
  1441.     }
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449. /*
  1450.  * CPatronDoc::Rename
  1451.  *
  1452.  * Purpose:
  1453.  *  Overrides the normal rename to include notification of tenants
  1454.  *  in this document of the new name.  This is so embedded objects
  1455.  *  are told the correct name through IOleObject::SetHostNames.
  1456.  *
  1457.  * Parameters:
  1458.  *  pszFile         LPTSTR to the new filename.
  1459.  *
  1460.  * Return Value:
  1461.  *  None
  1462.  */
  1463.  
  1464. void CPatronDoc::Rename(LPTSTR pszFile)
  1465.     {
  1466.     LPMONIKER   pmk;
  1467.  
  1468.     //We don't need to change the base class, just augment...
  1469.     CDocument::Rename(pszFile);
  1470.  
  1471.     //Unregister the old moniker (m_dwRegROT set to zero).
  1472.     INOLE_RevokeAsRunning(&m_dwRegROT);
  1473.  
  1474.     if (NULL==pszFile)
  1475.         return;
  1476.  
  1477.     CreateFileMoniker(pszFile, &pmk);
  1478.  
  1479.     if (NULL!=pmk)
  1480.         {
  1481.         LPMONIKER   pmkAll;
  1482.  
  1483.         INOLE_RegisterAsRunning(this, pmk, 0, &m_dwRegROT);
  1484.  
  1485.         //Give a moniker to linked objects in tenants.
  1486.         m_pPG->NotifyTenantsOfRename(pszFile, pmk);
  1487.  
  1488.         //Register a File!"\" wildcard moniker as well
  1489.         CreateItemMoniker(TEXT("!"), TEXT("\\"), &pmkAll);
  1490.  
  1491.         if (NULL!=pmkAll)
  1492.             {
  1493.             LPMONIKER   pmkWild;
  1494.  
  1495.             INOLE_RevokeAsRunning(&m_dwRegROTWild);
  1496.             pmk->ComposeWith(pmkAll, FALSE, &pmkWild);
  1497.  
  1498.             if (NULL!=pmkWild)
  1499.                 {
  1500.                 INOLE_RegisterAsRunning(this, pmk, 0
  1501.                     , &m_dwRegROTWild);
  1502.                 pmkWild->Release();
  1503.                 }
  1504.  
  1505.             pmkAll->Release();
  1506.             }
  1507.  
  1508.         //No need for us to hold on to this.
  1509.         pmk->Release();
  1510.         }
  1511.  
  1512.     return;
  1513.     }
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519. /*
  1520.  * CPatronDoc::InsertObject
  1521.  *
  1522.  * Purpose:
  1523.  *  Retrieves a CLSID or a filename from the Insert Object dialog
  1524.  *  box and creates an object using those identifiers.
  1525.  *
  1526.  * Parameters:
  1527.  *  hWndFrame       HWND of the main window
  1528.  *
  1529.  * Return Value:
  1530.  *  BOOL            TRUE if successful, FALSE otherwise.
  1531.  */
  1532.  
  1533. BOOL CPatronDoc::InsertObject(HWND hWndFrame)
  1534.     {
  1535.     OLEUIINSERTOBJECT   io;
  1536.     DWORD               dwData=0;
  1537.     TCHAR               szFile[CCHPATHMAX];
  1538.     UINT                uTemp;
  1539.     BOOL                fRet=FALSE;
  1540.  
  1541.     if (NULL==m_pPG)
  1542.         return FALSE;
  1543.  
  1544.     memset(&io, 0, sizeof(io));
  1545.  
  1546.     io.cbStruct=sizeof(io);
  1547.     io.hWndOwner=hWndFrame;
  1548.  
  1549.     szFile[0]=0;
  1550.     io.lpszFile=szFile;
  1551.     io.cchFile=CCHPATHMAX;
  1552.  
  1553.     //We now support linking, so remove the IOF_DISABLELINK flag.
  1554.     io.dwFlags=IOF_SELECTCREATENEW;
  1555.  
  1556.     uTemp=OleUIInsertObject(&io);
  1557.  
  1558.     if (OLEUI_OK==uTemp)
  1559.         {
  1560.         TENANTTYPE      tType;
  1561.         LPVOID          pv;
  1562.         FORMATETC       fe;
  1563.  
  1564.         SETDefFormatEtc(fe, 0, TYMED_NULL);
  1565.  
  1566.         if (io.dwFlags & IOF_SELECTCREATENEW)
  1567.             {
  1568.             tType=TENANTTYPE_EMBEDDEDOBJECT;
  1569.             pv=&io.clsid;
  1570.             }
  1571.         else
  1572.             {
  1573.             if (io.dwFlags & IOF_CHECKLINK)
  1574.                 tType=TENANTTYPE_LINKEDFILE;
  1575.             else
  1576.                 tType=TENANTTYPE_EMBEDDEDFILE;
  1577.  
  1578.             pv=szFile;
  1579.             }
  1580.  
  1581.         if ((io.dwFlags & IOF_CHECKDISPLAYASICON)
  1582.             && NULL!=io.hMetaPict)
  1583.             {
  1584.             fe.dwAspect=DVASPECT_ICON;
  1585.             dwData=(DWORD)(UINT)io.hMetaPict;
  1586.             }
  1587.  
  1588.         fRet=m_pPG->TenantCreate(tType, pv, &fe, NULL, dwData);
  1589.  
  1590.         //Free this regardless of what we do with it.
  1591.         INOLE_MetafilePictIconFree(io.hMetaPict);
  1592.  
  1593.         if (fRet)
  1594.             {
  1595.             //Disable Printer Setup once we've created a tenant.
  1596.             m_fPrintSetup=FALSE;
  1597.             FDirtySet(TRUE);
  1598.             }
  1599.         }
  1600.  
  1601.     return fRet;
  1602.     }
  1603.  
  1604.  
  1605.  
  1606.  
  1607. /*
  1608.  * CPatronDoc::ActivateObject
  1609.  *
  1610.  * Purpose:
  1611.  *  Executes a verb on the currently selected object.
  1612.  *
  1613.  * Parameters:
  1614.  *  iVerb           LONG of the selected verb.
  1615.  *  pMSG            LPMSG that caused the activation.
  1616.  *
  1617.  * Return Value:
  1618.  *  None
  1619.  */
  1620.  
  1621. //CHAPTER22MOD
  1622. void CPatronDoc::ActivateObject(LONG iVerb, LPMSG pMSG)
  1623.     {
  1624.     m_pPG->ActivateObject(iVerb, pMSG);
  1625.     return;
  1626.     }
  1627. //End CHAPTER22MOD
  1628.  
  1629.  
  1630. /*
  1631.  * CPatronDoc::ConvertObject
  1632.  *
  1633.  * Purpose:
  1634.  *  Invokes the Convert dialog on the current object.  Here it's
  1635.  *  just a pass-through to the pages.
  1636.  *
  1637.  * Parameters:
  1638.  *  hWndFrame       HWND of the frame window.
  1639.  *
  1640.  * Return Value:
  1641.  *  BOOL            TRUE if the function is successful, FALSE otherwise.
  1642.  */
  1643.  
  1644. BOOL CPatronDoc::ConvertObject(HWND hWndFrame)
  1645.     {
  1646.     return m_pPG->ConvertObject(hWndFrame);
  1647.     }
  1648.  
  1649.  
  1650.  
  1651.  
  1652. //CHAPTER22MOD
  1653. /*
  1654.  * CPatronDoc::NoObjectFrameTools
  1655.  *
  1656.  * Purpose:
  1657.  *  Saves/retrieves a flag with the document that says whether or
  1658.  *  not the object active in this document has *frame* tools.  We
  1659.  *  need this to tell the frame what to do when document activation
  1660.  *  switches.
  1661.  *
  1662.  * Parameters:
  1663.  *  fNoTools        BOOL TRUE to indicate the object has no tools.
  1664.  *                  FALSE says the object has tools.
  1665.  *  fSet            BOOL indicating if this is a set (TRUE) or get
  1666.  *                  (FALSE) operation.
  1667.  *
  1668.  * Return Value:
  1669.  *  BOOL            Value of flag for Get operations, previous value
  1670.  *                  for Set operations.
  1671.  */
  1672.  
  1673. BOOL CPatronDoc::NoObjectFrameTools(BOOL fNoTools, BOOL fSet)
  1674.     {
  1675.     BOOL        fLast=m_fNoObjectFrameTools;
  1676.  
  1677.     if (fSet)
  1678.         m_fNoObjectFrameTools=fNoTools;
  1679.  
  1680.     return fLast;
  1681.     }
  1682. //End CHAPTER22MOD
  1683.