home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / ocfsrc.pak / OCDOC.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  8KB  |  337 lines

  1. //
  2. //----------------------------------------------------------------------------
  3. // ObjectComponents
  4. // (C) Copyright 1994 by Borland International, All Rights Reserved
  5. //
  6. //   Implementation of TOcDocument Class
  7. //----------------------------------------------------------------------------
  8. #include <ocf/ocfpch.h>
  9. #include <ocf/ocstorag.h>
  10. #include <ocf/ocdoc.h>
  11. #include <ocf/ocpart.h>
  12. #include <ocf/ocapp.h>
  13. #include <ocf/ocremvie.h>
  14.  
  15. DIAG_DECLARE_GROUP(OcRefCount);
  16.  
  17. const char  DocStreamName[] = "OcDocument";
  18.  
  19. TOcDocument::TOcDocument(TOcApp& app, const char far* fileName)
  20. :
  21.   OcApp(app),
  22. #if defined(BI_DATA_NEAR)
  23.   Name(*new string(fileName)),
  24.   PartCollection(*new TOcPartCollection),
  25.   ViewCollection(*new TOcViewCollection)
  26. #else
  27.   Name(fileName),
  28.   PartCollection(),
  29.   ViewCollection()
  30. #endif
  31. {
  32.   // client support...
  33.   //
  34.   ActiveView = 0;
  35.   NumViews   = 0;
  36.   PartID     = 0;
  37.   Storage    = 0;
  38.  
  39.   bool createNew = ToBool(!fileName || !fileName[0]);
  40.   Storage = new TOcStorage(fileName, createNew);
  41.   TRACEX(OcRefCount, 1, "TOcDocument() @" << (void*)this);
  42. }
  43.  
  44. TOcDocument::TOcDocument(TOcApp& app, const char far* fileName, IStorage far* storageI)
  45. :
  46.   OcApp(app),
  47. #if defined(BI_DATA_NEAR)
  48.   Name(*new string(fileName)),
  49.   PartCollection(*new TOcPartCollection),
  50.   ViewCollection(*new TOcViewCollection)
  51. #else
  52.   Name(fileName),
  53.   PartCollection(),
  54.   ViewCollection()
  55. #endif
  56. {
  57.   // client support...
  58.   //
  59.   ActiveView = 0;
  60.   NumViews   = 0;
  61.   PartID     = 0;
  62.   Storage    = 0;
  63.   OrgStorage = 0;
  64.  
  65.   if (storageI) // storage already created by application
  66.     Storage = new TOcStorage(storageI);
  67.   else
  68.     Storage = 0; // no storage yet
  69.   TRACEX(OcRefCount, 1, "TOcDocument() @" << (void*)this);
  70. }
  71.  
  72. TOcDocument::~TOcDocument()
  73. {
  74.   delete Storage;
  75. #if defined(BI_DATA_NEAR)
  76.   delete &PartCollection;
  77.   delete &ViewCollection;
  78.   delete &Name;
  79. #endif
  80. }
  81.  
  82. //----------------------------------------------------------------------------
  83.  
  84. //
  85. // Set the storage for this document
  86. //
  87. void
  88. TOcDocument::SetStorage(IStorage* storage, bool remember)
  89. {
  90.   if (Storage && (storage == Storage->GetIStorage()))
  91.     return;
  92.  
  93.   if (remember) {
  94.     delete Storage;
  95.     OrgStorage = 0;
  96.   }
  97.   else
  98.     OrgStorage = Storage;
  99.  
  100.   if (storage)
  101.     Storage = new TOcStorage(storage);
  102.   else
  103.     Storage = 0;
  104. }
  105.  
  106. //
  107. // Set the storage for this document
  108. //
  109. void
  110. TOcDocument::SetStorage(const char far* path)
  111. {
  112.   delete Storage;
  113.   Storage = new TOcStorage(path, false);
  114.   SetName(path);    // new Storage now has path as a name
  115. }
  116.  
  117. //
  118. // Restore the original root IStorage before the save operation
  119. //
  120. bool
  121. TOcDocument::RestoreStorage()
  122. {
  123.   if (OrgStorage) {
  124.     delete Storage;
  125.  
  126.     Storage    = OrgStorage;
  127.     OrgStorage = 0;
  128.   }
  129.  
  130.   return true;
  131. }
  132.  
  133. //
  134. // Perform saveas operation
  135. //
  136. bool
  137. TOcDocument::SaveToFile(const char far* newName)
  138. {
  139.   PRECONDITION(newName);
  140.  
  141.   TOcStorage newStorage(newName, true);
  142.   Name = newName;
  143.   return SaveParts(newStorage.GetIStorage(), false);
  144. }
  145.  
  146. //
  147. // Save the embedded parts to the provided storage. 'remember' flag is not
  148. // really used here, as our save/restore is done outside here.
  149. //
  150. bool
  151. TOcDocument::SaveParts(IStorage* storage, bool sameAsLoaded, bool remember)
  152. {
  153.   if (!Storage)
  154.     return true;
  155.  
  156.   TOcStorage* oldStorage = 0;
  157.  
  158.   // If the storage passed is not the same as the one we loaded, wrap the new
  159.   // one & use it in here.
  160.   //
  161.   if (!sameAsLoaded) {
  162.     CHECK(storage);
  163.  
  164.     // If we are switching storages, make sure parts all all pulled in now
  165.     //
  166.     for (TOcPartCollectionIter i(PartCollection); i; i++) {
  167.       TOcPart& part = *i.Current();
  168.       part.FinishLoading();
  169.     }
  170.     oldStorage = Storage;
  171.     Storage = new TOcStorage(storage);
  172.   }
  173.  
  174.   // Create a stream for part information
  175.   //
  176.   STATSTG statstg;
  177.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  178.     return false;
  179.  
  180.   TOcStream  stream(*Storage, ::DocStreamName, true, statstg.grfMode);
  181.  
  182.   // Write TOcDocument data into stream
  183.   //
  184.   ulong count;
  185.   bool  ok;
  186.   ulong value = PartCollection.Count();
  187.   ok = ToBool(HRSucceeded(stream.Write(&PartID, sizeof PartID, &count)) &&
  188.               HRSucceeded(stream.Write(&value, sizeof value, &count)));
  189.  
  190.   if (ok) {
  191.     for (TOcPartCollectionIter i(PartCollection); i; i++) {
  192.       TOcPart& part = *i.Current();
  193.       int16 len = int16(part.GetName().Length());
  194.  
  195.       // Write the part name string, pascal style [len]+chars, no 0
  196.       //
  197.       ok = ToBool(HRSucceeded(stream.Write(&len, sizeof len, &count)) &&
  198.                   HRSucceeded(stream.Write((char far*)part.GetName(), len, &count)) &&
  199.                   part.Save(sameAsLoaded, remember));
  200.  
  201.       if (!ok)
  202.         break;
  203.     }
  204.   }
  205.  
  206.   // Deal with the alloc'd storage if there was one. Either put things back on
  207.   // failure, or keep the new storage around for a while
  208.   //
  209.   if (!sameAsLoaded) {
  210.     if (!ok) {
  211.       delete Storage;
  212.       Storage = oldStorage;
  213.     }
  214.     else
  215.       delete oldStorage;
  216.   }
  217.  
  218.   return ok;
  219. }
  220.  
  221. //
  222. // Loads the parts from the current storage into the PartCollection. Return
  223. // false if a serious error occurs. Having no part stream at all is OK.
  224. //
  225. bool
  226. TOcDocument::LoadParts()
  227. {
  228.   if (!Storage)
  229.     return true;
  230.  
  231.   // Clear the part collection
  232.   //
  233.   PartCollection.Clear();
  234.  
  235.   // Open a stream with part information
  236.   //
  237.   STATSTG statstg;
  238.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  239.     return false;
  240.  
  241.   try {
  242.     TOcStream  stream(*Storage, ::DocStreamName, false, statstg.grfMode);
  243.  
  244.     // Read TOcDocument data from stream. Return false if any of the data
  245.     // is missing--something must have been corrupted.
  246.     //
  247.     if (!HRSucceeded(stream.Read(&PartID, sizeof PartID)))
  248.       return false;
  249.  
  250.     ulong value;
  251.     if (!HRSucceeded(stream.Read(&value, sizeof value)))
  252.       return false;
  253.  
  254.     // Rebuild the part collection
  255.     //
  256.     for (int i = (int)value; i; i--) {
  257.       char name[33];
  258.       int16 len;
  259.  
  260.       // Read the part name string, pascal style [len]+chars, no 0
  261.       //
  262.       if (!HRSucceeded(stream.Read(&len, sizeof len)))
  263.         return false;
  264.  
  265.       if (len >= sizeof name) // too big for our buffer, how could that happen?
  266.         return false;
  267.  
  268.       if (!HRSucceeded(stream.Read(name, len)))
  269.         return false;
  270.       name[len] = 0;  // 0 was not written
  271.  
  272.       new TOcPart(*this, name);
  273.     }
  274.   }
  275.   catch (TXObjComp&) {
  276.     // There is no part related info stream. Thats OK, we then have a document
  277.     // with no parts
  278.   }
  279.   return true;
  280. }
  281.  
  282. void
  283. TOcDocument::RenameParts(IBRootLinkable far* bLDocumentI)
  284. {
  285.   if (Name.is_null())
  286.     return; // Temporary file does not have moniker
  287.  
  288.   for (TOcPartCollectionIter i(PartCollection); i; i++) {
  289.     TOcPart& part = *i.Current();
  290.  
  291.     IBLinkable far* linkI;
  292.     if (HRSucceeded(part.QueryInterface(IID_IBLinkable, &(LPVOID)linkI))) {
  293.       linkI->OnRename(bLDocumentI, part.GetName());
  294.       linkI->Release();
  295.     }
  296.   }
  297. }
  298.  
  299. void
  300. TOcDocument::Close()
  301. {
  302.   for (TOcPartCollectionIter i(PartCollection); i; i++) {
  303.     TOcPart& part = *i.Current();
  304.     part.Close();
  305.   }
  306.  
  307.   for (TOcViewCollectionIter j(ViewCollection); j; j++) {
  308.     TOcLinkView& view = *j.Current();
  309.     view.Disconnect();
  310.   }
  311.  
  312.   ViewCollection.Clear(); // remove the link views now
  313. }
  314.  
  315. void
  316. TOcDocument::SetActiveView(TOcView* view)
  317. {
  318.   ActiveView = view;
  319. }
  320.  
  321. //
  322. // Notify container that doc pathname has changed
  323. //
  324. void
  325. TOcDocument::SetName(const string& newName)
  326. {
  327.   Name = newName;
  328.  
  329.   // create a moniker for this document
  330.   //
  331.   if (!Name.is_null() && ActiveView)
  332.     ActiveView->Rename();
  333. }
  334.  
  335.  
  336.  
  337.