home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / OLESRVR.ZIP / DOCUMENT.CPP next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  15.5 KB  |  572 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2.  
  3. /* implementation of class TOLEDocument */
  4.  
  5. #include <owl.h>
  6.  
  7. #define SERVERONLY
  8. #include <ole.h>
  9.  
  10. #include "olesrvr.h"
  11. #include <fstream.h>
  12. #include <CommDlg.h>
  13. #include <string.h>
  14.  
  15. #define UNNAMED_DOC   "(Untitled)"
  16. OLESERVERDOCVTBL      TOLEDocument::_vtbl;
  17.  
  18. //
  19. // overloaded stream operators defined in "object.cpp"
  20. //
  21. ostream  &operator<< (ostream &, TOLEObject &);
  22. istream  &operator>> (istream &, TOLEObject &);
  23.  
  24. /*
  25.     constructor
  26.     -----------
  27.  
  28.     if "szPath" is NULL then we create an untitled document and default object
  29.     
  30.     the type is "doctypeNew" if "lhDoc" is NULL and "doctypeEmbedded" if
  31.     "lhDoc" is non NULL
  32.     
  33.     if "szPath" is non NULL we create a document of type "doctypeFromFile"
  34.     and initialize it from file "szPath"
  35.     
  36.     if "lhDoc" is NULL then we call OleRegisterServerDoc() otherwise we
  37.     just use "lhDoc" as our registration handle
  38. */
  39. TOLEDocument::TOLEDocument (TOLEServer &server,
  40.                             LHSERVERDOC lhDoc,
  41.                             LPSTR       szPath,
  42.                             BOOL        dirty)
  43. {
  44.   szName = 0;
  45.   lpvtbl = &_vtbl;
  46.   fRelease = FALSE;
  47.   fDirty = dirty;
  48.  
  49.   server.pDocument = this;
  50.  
  51.   //
  52.   // since we only have one object we can create it now...
  53.   //
  54.   pObject = new TOLEObject;
  55.  
  56.   if (szPath)
  57.     LoadFromFile (szPath);
  58.  
  59.   else {
  60.     SetDocumentName (UNNAMED_DOC);
  61.  
  62.     type = lhDoc ? doctypeEmbedded : doctypeNew;
  63.   }
  64.  
  65.   if (lhDoc != 0)
  66.     this->lhDoc = lhDoc;  // use registration handle we were given
  67.  
  68.   else
  69.       OleRegisterServerDoc (server.lhServer, szName, this, (LHSERVERDOC FAR *) &this->lhDoc);
  70. }
  71.  
  72.  
  73. /*
  74.     SetDocumentName
  75.     ---------------
  76.  
  77.     changes instance variable "szName" and changes the window caption
  78. */
  79. void
  80. TOLEDocument::SetDocumentName (LPSTR newName, BOOL changeCaption)
  81. {
  82.   int   len = lstrlen (newName);
  83.  
  84.   delete szName;
  85.   szName = new char[len + 1];
  86.   lstrcpy (szName, newName);
  87.  
  88.   if (changeCaption) {
  89.     char  buf[MAXPATHLENGTH];
  90.  
  91.     wsprintf (buf, "%s - %s", (LPSTR) szAppName, newName);
  92.     GetApplicationObject()->MainWindow->SetCaption (buf);
  93.   }
  94. }
  95.  
  96.  
  97. /*
  98.     LoadFromFile
  99.     ------------
  100.  
  101.     returns TRUE if successful and FALSE otherwise
  102.  
  103.     SIDE EFFECTS: if successful sets type to "objtypeFromFile" and sets "szName"
  104.                   to "szPath"
  105. */
  106. BOOL
  107. TOLEDocument::LoadFromFile (LPSTR szPath)
  108. {
  109.   char      buf[MAXPATHLENGTH];
  110.   TOLEApp  *pApp = (TOLEApp *) GetApplicationObject();
  111.  
  112.   //
  113.   // in small model if I want to use C++ streams I need to have a near
  114.   // pointer...
  115.   //
  116.   lstrcpy (buf, szPath);
  117.  
  118.   ifstream  in (buf);
  119.  
  120.   if (in.fail()) {
  121.       wsprintf (buf, "Cannot open file %s!", szPath);
  122.       MessageBeep (0);
  123.       MessageBox (pApp->MainWindow->HWindow,
  124.                   buf,
  125.                   szAppName, 
  126.                   MB_OK | MB_ICONEXCLAMATION);
  127.     return FALSE;
  128.  
  129.   } else {
  130.     //
  131.     // read in the signature
  132.     //
  133.     in.read (buf, sizeof (szClassKey) - 1);
  134.  
  135.     if (strncmp (buf, szClassKey, sizeof (szClassKey) - 1) != 0) {
  136.       wsprintf (buf,
  137.                 "File %s is not an \"%s\" file!",
  138.                 szPath,
  139.                 (LPSTR) szAppName);
  140.       MessageBeep (0);
  141.       MessageBox (pApp->MainWindow->HWindow,
  142.                   buf,
  143.                   szAppName, 
  144.                   MB_OK | MB_ICONEXCLAMATION);
  145.  
  146.       return FALSE;
  147.  
  148.     } else {
  149.       in >> *pObject;
  150.       type = doctypeFromFile;
  151.       SetDocumentName (szPath);
  152.     }
  153.  
  154.     return TRUE;
  155.   }
  156. }
  157.  
  158.  
  159. /*
  160.     Reset
  161.     -----
  162.  
  163.     the only reason that we need this routine is that we re-use the document
  164.     object. if your app doesn't then you would delete the old object and create
  165.     a new one...
  166.  
  167.     SIDE EFFECTS: sets "fDirty" flag to FALSE and "fRelease" to FALSE
  168.  
  169.     if "lhDoc" is NULL then call OleRegisterServerDoc()
  170. */
  171. void
  172. TOLEDocument::Reset (LPSTR szPath)
  173. {
  174.   if (!szPath || !LoadFromFile (szPath)) {
  175.     ((TWindowServer *) GetApplicationObject()->MainWindow)->ShapeChange (objEllipse);
  176.  
  177.     pObject->native.type = objEllipse;
  178.     pObject->native.version = 1;
  179.  
  180.     type = doctypeNew;
  181.     SetDocumentName (UNNAMED_DOC);
  182.   }
  183.  
  184.   if (lhDoc == 0) {
  185.     TOLEApp  *pApp = (TOLEApp *) GetApplicationObject();
  186.  
  187.       OleRegisterServerDoc (pApp->pServer->lhServer, szName, this, (LHSERVERDOC FAR *) &lhDoc);
  188.   }
  189.  
  190.   fDirty = fRelease = FALSE;
  191. }
  192.  
  193.  
  194. static
  195. void
  196. Setup (OPENFILENAME *fnStruct)
  197. {
  198.   TOLEApp  *pApp = (TOLEApp *) GetApplicationObject();
  199.  
  200.   //
  201.   // we want the fully qualified pathname that is returned in "lpstrFile"
  202.   // and not the simple name/extension
  203.   //
  204.   static char simpleName[13]; 
  205.  
  206.   fnStruct->lStructSize = sizeof (OPENFILENAME);
  207.   fnStruct->nMaxFile = MAXPATHLENGTH;
  208.   fnStruct->Flags = 0;
  209.   fnStruct->hInstance = pApp->hInstance;
  210.   fnStruct->hwndOwner = pApp->MainWindow->HWindow;
  211.   fnStruct->lCustData = 0;
  212.   fnStruct->lpfnHook = 0;
  213.   fnStruct->lpstrCustomFilter = 0;
  214.   fnStruct->lpstrDefExt = szFileExt;
  215.   fnStruct->lpstrFilter = "OWL OLE Server (*." szFileExt ")\0*." szFileExt "\0" ;
  216.   fnStruct->lpstrFileTitle = simpleName;
  217.   fnStruct->lpstrInitialDir = 0;
  218.   fnStruct->lpstrTitle = 0;  // use default
  219.   fnStruct->lpTemplateName = 0;
  220.   fnStruct->nFilterIndex = 1;
  221.   fnStruct->nFileOffset = 0;
  222.   fnStruct->nFileExtension = 0;
  223.   fnStruct->nMaxCustFilter = 0;
  224. }
  225.  
  226.  
  227. /*
  228.     PromptForOpenFileName
  229.     ---------------------
  230. */
  231. BOOL
  232. TOLEDocument::PromptForOpenFileName (char *path)
  233. {
  234.   OPENFILENAME  fnStruct;
  235.  
  236.   Setup (&fnStruct);
  237.  
  238.   fnStruct.Flags |= OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
  239.   wsprintf (path, "*.%s", (LPSTR) szFileExt);
  240.   fnStruct.lpstrFile = path;
  241.  
  242.   return GetOpenFileName (&fnStruct);
  243. }
  244.  
  245.  
  246. /*
  247.     SaveAs
  248.     ------
  249.  
  250.     calls the common Windows dialog function to prompt the user for the
  251.     filename to use
  252. */
  253. void
  254. TOLEDocument::SaveAs ()
  255. {
  256.   char          path[MAXPATHLENGTH];  // result of GetSaveFileName()
  257.   OPENFILENAME  fnStruct;
  258.  
  259.   Setup (&fnStruct);
  260.   fnStruct.Flags |= OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
  261.   wsprintf (path, "*.%s", (LPSTR) szFileExt);
  262.   fnStruct.lpstrFile = path;
  263.  
  264.   if (GetSaveFileName (&fnStruct)) {
  265.     type = doctypeFromFile;
  266.     SetDocumentName (path);  // we must do this BEFORE we call SaveDoc()
  267.     SaveDoc();
  268.  
  269.     //
  270.     // now inform the server library that we have renamed the document
  271.     //
  272.     OleRenameServerDoc (lhDoc, szName);
  273.   }
  274. }
  275.  
  276.  
  277. /*
  278.     SaveDoc
  279.     -------
  280.  
  281.     save the document to file "szName" and mark the document as not "dirty"
  282. */
  283. void
  284. TOLEDocument::SaveDoc ()
  285. {
  286.   if (type == doctypeNew)
  287.     SaveAs();
  288.  
  289.   else {
  290.     ofstream  out (szName);
  291.  
  292.     out << szClassKey << " ";  // signature
  293.     out << *pObject;
  294.     fDirty = FALSE;
  295.   }
  296. }
  297.  
  298.  
  299. /*
  300.     callback Close
  301.     -------- -----
  302.  
  303.     we have been requested to close the document because the client that
  304.     contains a link (embedding or linking) to that document has shut down
  305.  
  306.     this method is always called *before* the document's "Release" method
  307.     is called
  308.  
  309.     WHAT TO DO:
  310.       - call OleRevokeServerDoc() and *don't* free any resources until
  311.         "Release" is called
  312.       - return the value of OleRevokeServerDoc()
  313.  
  314.     NOTE: since TOLEDocument is a subclass of OLESERVERDOC we can just cast
  315.           a LPOLESERVERDOC to a (TOLEDocument FAR *)
  316. */
  317. OLESTATUS FAR PASCAL _export
  318. TOLEDocument::Close (LPOLESERVERDOC lpOleDoc)
  319. {
  320.   return OleRevokeServerDoc (((TOLEDocument FAR *) lpOleDoc)->lhDoc);
  321. }
  322.  
  323.  
  324. /*
  325.     callback GetObjet
  326.     -------- --------
  327.  
  328.     server library calls this method whenever a client application creates
  329.     an object using a function like OleCreate()
  330.  
  331.     if "lpszObjName" is NULL, that means we are being called for an embedded
  332.     object after the server was sent "Create", "Edit", or "CreateFromTemplate"
  333.     and the server library requests the entire document
  334.  
  335.     if "lpszObjName" isn't NULL then the server has already received a "Open"
  336.     message to activate the linked object
  337.  
  338.     WHAT TO DO:
  339.       - allocate a TOLEObject if "lpszObjName" is NULL, or look up "lpszObjName"
  340.         in the list of objects if it isn't NULL
  341.       - store the pointer to the TOLEObject in "lplpOleObject"
  342.       - store "lpOleClient" so we can send notifications to the client
  343.         (used for linked objects)
  344.       - return OLE_OK if successful, OLE_ERROR_NAME if "lpszObjName" isn't
  345.         recognized, or OLE_ERROR_MEMORY if the object could not be allocated
  346.  
  347.     NOTE:
  348.       - we only have one object and it is created when the document is
  349.         created. Therefore, we don't actually create anything here...
  350.  
  351.       - "lpOleClient" resides in the rever library and is used on behalf of
  352.         a client application
  353. */
  354. OLESTATUS FAR PASCAL _export
  355. TOLEDocument::GetObject (LPOLESERVERDOC lpOleDoc,
  356.                            LPSTR          lpszObjName,
  357.                            LPOLEOBJECT    FAR *lplpOleObj,
  358.                            LPOLECLIENT    lpOleClient)
  359. {
  360.   TOLEDocument  *pDoc = (TOLEDocument *) lpOleDoc;
  361.  
  362.   //
  363.   // in either case (whether "lpszObjName" is null or not) we just return
  364.   // the object associated with the document
  365.   //
  366.   *lplpOleObj = pDoc->pObject;
  367.  
  368.   //
  369.   // if "lpszObjName" isn't NULL then we associate client "lpOleClient" with
  370.   // it...
  371.   //
  372.   // NOTE: we only have one object. if you have multiple objects then you would
  373.   //       have to search your objects to find the one that matched "lpszObjName"
  374.   //
  375.   if (lpszObjName)
  376.     pDoc->pObject->AddClientLink (lpOleClient);
  377.  
  378.     return OLE_OK;
  379. }
  380.  
  381.  
  382. /*
  383.     callback Execute
  384.     -------- -------
  385.  
  386.     if your app supports DDE execution commands then you would handle this
  387.     event
  388.  
  389.     since we don't we return OLE_ERROR_COMMAND
  390. */
  391. OLESTATUS FAR PASCAL _export
  392. TOLEDocument::Execute (LPOLESERVERDOC /* lpOleDoc */,
  393.                          HANDLE         /* hCommands */)
  394. {
  395.     return OLE_ERROR_COMMAND;
  396. }
  397.  
  398.  
  399. /*
  400.     callback Release
  401.     -------- -------
  402.  
  403.     the server library calls this routine when all conversations to the
  404.     object have been closed. at this point the server has called either
  405.     OleRevokeServerDoc() or OleRevokeServer()
  406.  
  407.     there will be no more calls to the document's methods. it is okay to
  408.     free the document's objects, but *not* the TOLEDocument yet...
  409.  
  410.     WHAT TO DO:
  411.       - free the document's objects and resources (e.g. atoms) but *not* the
  412.         document itself
  413.       - set a flag to indicate that "Release" has been called
  414.       - return OLE_OK if successful, OLE_ERROR_GENERIC otherwise
  415.  
  416.     NOTE: since we only have one document and one object within the
  417.           documeny we don't NOT delete the object here
  418.  
  419.           however, you might want to...
  420. */
  421. OLESTATUS FAR PASCAL _export
  422. TOLEDocument::Release (LPOLESERVERDOC lpOleDoc)
  423. {
  424.   ((TOLEDocument *) lpOleDoc)->fRelease = TRUE;
  425.     return OLE_OK;
  426. }
  427.  
  428.  
  429. /*
  430.     callback Save
  431.     -------- ----
  432.  
  433.     this method is only used when the server is editing a linked object:
  434.  
  435.     the client application is closing and the user has requested saving the
  436.     client document which contains a linked object
  437.  
  438.     WHAT TO DO:
  439.       - save the document to the filename which was passed in when the document
  440.         was opened for linking
  441.       - return OLE_OK if successful, OLE_ERROR_GENERIC otherwise
  442. */
  443. OLESTATUS FAR PASCAL _export
  444. TOLEDocument::Save (LPOLESERVERDOC lpOleDoc)
  445. {
  446.   TOLEDocument  *doc = (TOLEDocument *) lpOleDoc;
  447.  
  448.   if (doc->type != doctypeFromFile)
  449.     return OLE_ERROR_GENERIC;
  450.  
  451.   else {
  452.     doc->SaveDoc();
  453.     return OLE_OK;
  454.   }
  455. }
  456.  
  457.  
  458. /*
  459.     callback SetColorScheme
  460.     -------- --------------
  461. */
  462. OLESTATUS FAR PASCAL _export
  463. TOLEDocument::SetColorScheme (LPOLESERVERDOC /* lpOleDoc */,
  464.                                 LPLOGPALETTE   /* lpPal */)
  465. {
  466.     return OLE_ERROR_GENERIC;
  467. }
  468.  
  469.  
  470. /*
  471.     callback DocSetDimensions
  472.     -------- ----------------
  473.  
  474.     the client is informing  us how big the object should be
  475.  
  476.     "lpRect" is in MM_HIMETRIC units (all OLE libraries express the size of
  477.      every object in MM_HIMETRIC)
  478. */
  479. OLESTATUS FAR PASCAL _export
  480. TOLEDocument::SetDocDimensions (LPOLESERVERDOC /* lpOleDoc */,
  481.                                   LPRECT         /* lpRect */)
  482. {
  483.     return OLE_OK;
  484. }
  485.  
  486.  
  487. /*
  488.     callback SetHostNames
  489.     -------- ------------
  490.  
  491.     the server library is calling to provide the server with the name of the
  492.     client's document and the name of the object in the client application
  493.  
  494.     these names should be used to make the necessary window title bar and
  495.     menu changes
  496.  
  497.     this method is only called for embedded objects because linked objects
  498.     display their filename in the title bar
  499.  
  500.     WHAT IT DOES:
  501.       - change the title bar and File menu
  502.       - store the object and client names for later use
  503.       - return OLE_OK is successful, OLE_ERROR_GENERIC otherwise
  504.  
  505.     PARAMETERS:
  506.       - "lpClient" is the name of the client application document
  507.       - "lpDoc" is the name of the object in the client application
  508. */
  509. OLESTATUS FAR PASCAL _export
  510. TOLEDocument::SetHostNames (LPOLESERVERDOC lpOleDoc,
  511.                               LPSTR          lpClient,
  512.                               LPSTR          lpDoc)
  513. {
  514.   ((TWindowServer *) GetApplicationObject()->MainWindow)->UpdateFileMenu (lpDoc);
  515.  
  516.   //
  517.   // store the document name, but don't update the title bar we will do that
  518.   // below
  519.   //
  520.   ((TOLEDocument *) lpOleDoc)->SetDocumentName (lpDoc, FALSE);
  521.  
  522.   //
  523.   // set the caption to be <App Name> - <Object Name> in <Client App Document>
  524.   //
  525.   char  buf[128];
  526.  
  527.   wsprintf (buf, "%s - %s in %s", (LPSTR) szAppName, lpDoc, lpClient);
  528.   GetApplicationObject()->MainWindow->SetCaption (buf);
  529.     return OLE_OK;
  530. }
  531.  
  532.  
  533.  
  534. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCCLOSE)(LPOLESERVERDOC);
  535. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCGETOBJECT)(LPOLESERVERDOC,const char far *,LPOLEOBJECT FAR *,LPOLECLIENT);
  536. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCEXEC)(LPOLESERVERDOC,HANDLE);
  537. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCRELEASE)(LPOLESERVERDOC);
  538. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCSAVE)(LPOLESERVERDOC);
  539. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCSETCOLORSCHM)(LPOLESERVERDOC,const LOGPALETTE far *);
  540. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCSETDIMNSN)(LPOLESERVERDOC,const RECT far *);
  541. typedef OLESTATUS FAR PASCAL _export (FAR *LPDOCSETHOSTNAMES)(LPOLESERVERDOC,const char far *,const char far *);
  542.  
  543.  
  544. /*
  545.     InitVTBL
  546.     --------
  547.  
  548.     create thunks for OLESERVERDOC method callback tables
  549. */
  550. BOOL
  551. TOLEDocument::InitVTBL (HINSTANCE hInstance)
  552. {
  553.     _vtbl.Close = (LPDOCCLOSE) MakeProcInstance ((FARPROC) Close, hInstance);
  554.     _vtbl.GetObject = (LPDOCGETOBJECT) MakeProcInstance ((FARPROC) GetObject, hInstance);
  555.     _vtbl.Execute = (LPDOCEXEC) MakeProcInstance ((FARPROC) Execute, hInstance);
  556.     _vtbl.Release = (LPDOCRELEASE) MakeProcInstance ((FARPROC) Release, hInstance);
  557.     _vtbl.Save = (LPDOCSAVE) MakeProcInstance ((FARPROC) Save, hInstance);
  558.     _vtbl.SetColorScheme = (LPDOCSETCOLORSCHM) MakeProcInstance ((FARPROC) SetColorScheme, hInstance);
  559.     _vtbl.SetDocDimensions = (LPDOCSETDIMNSN) MakeProcInstance ((FARPROC) SetDocDimensions, hInstance);
  560.     _vtbl.SetHostNames = (LPDOCSETHOSTNAMES) MakeProcInstance ((FARPROC) SetHostNames, hInstance);
  561.  
  562.   return _vtbl.Close != NULL &&
  563.          _vtbl.GetObject != NULL &&
  564.          _vtbl.Execute != NULL &&
  565.          _vtbl.Release != NULL &&
  566.          _vtbl.Save != NULL &&
  567.          _vtbl.SetColorScheme != NULL &&
  568.          _vtbl.SetDocDimensions != NULL &&
  569.          _vtbl.SetHostNames != NULL;
  570. }
  571.  
  572.