home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C++ / Applications / Lookup 1.0d2 / Sources / CLookupDocument.cp < prev    next >
Encoding:
Text File  |  1995-10-22  |  7.6 KB  |  356 lines  |  [TEXT/CWIE]

  1. /*
  2.     CLookupDocument.cp
  3.     
  4.     Copyright © 1995 Alastair Rankine.
  5.     All Rights Reserved.
  6. */
  7.  
  8. #include "CLookupDocument.h"
  9. #include "CLookupApplication.h"
  10. #include "ResourceIDs.h"
  11. #include "MessageIDs.h"
  12. #include "CEntry.h"
  13.  
  14. #include <LWindow.h>
  15. #include <LFile.h>
  16. #include <LPrintout.h>
  17. #include <LPlaceHolder.h>
  18. #include <UMemoryMgr.h>
  19. #include <UWindows.h>
  20. #include <UAEGizmos.h>
  21. #include <String_Utils.h>
  22. #include <strstream>
  23.  
  24. CLookupDocument::CLookupDocument(LCommander    * inSuper, FSSpec * inFileSpec)
  25.     : LSingleDoc(inSuper)
  26.     , mDirty(false)
  27. {
  28.     // The record list is our submodel list...
  29.     mSubModels = &mEntryList;
  30.     
  31.     // First we need to see if it's a stationary file...
  32.     // ...
  33.  
  34.     Str255 title;
  35.     
  36.     if (inFileSpec == nil) {
  37.         // Set name of untitled window
  38.         NameUntitled(title);
  39.  
  40.     } else {
  41.         // Create a new File object, read the entire File contents,
  42.         // put the contents into the text view, and set the Window
  43.         // title to the name of the File.
  44.         
  45.         Try_ {
  46.             mFile = new LFile(*inFileSpec);
  47.             mFile->OpenDataFork(fsRdWrPerm);
  48.     
  49.             ReadFile();
  50.             
  51.             mIsSpecified = true;
  52.             
  53.             ::CopyPStr(inFileSpec->name, title);
  54.         }
  55.         
  56.         Catch_(inErr) {
  57.             delete this;
  58.             Throw_(inErr);
  59.         
  60.         } EndCatch_
  61.     }
  62.  
  63.     // Create window for our document
  64.     mWindow = LWindow::CreateWindow(WIND_LookupWindow, this);
  65.     mWindow->SetDescriptor(title);
  66.     
  67.     BroadcastMessage(msg_Reverted, 0);
  68. }
  69.  
  70.  
  71. void CLookupDocument::NameUntitled(StringPtr outTitle)
  72. {
  73.         // Start with the default name ("untitled")
  74.     ::GetIndString(outTitle, STRx_Untitled, 1);
  75.     
  76.     long    num = 0;
  77.     while (UWindows::FindNamedWindow(outTitle) != nil) {
  78.             
  79.             // An existing window has the current name
  80.             // Increment counter and try again
  81.  
  82.         ::GetIndString(outTitle, STRx_Untitled, 2);
  83.         num++;
  84.         Str15    numStr;
  85.         ::NumToString(num, numStr);
  86.         ConcatPStr(outTitle, numStr);
  87.     }        
  88. }
  89.  
  90.  
  91. void CLookupDocument::ReadFile()
  92. {
  93.     if(mEntryList.GetCount())
  94.         mEntryList.RemoveItemsAt(mEntryList.GetCount(), 1);
  95.     
  96.     Handle dataH = mFile->ReadDataFork();
  97.     {
  98.         StHandleLocker dataHlock(dataH);
  99.         
  100.         istrstream stream(*dataH, ::GetHandleSize(dataH));
  101.         while(stream.good())
  102.         {
  103.             CEntry * rec = new CEntry;
  104.             stream >> *rec;
  105.             
  106.             // This will insert the record into the list as well as set the super model.
  107.             rec->SetSuperModel(this);
  108.         }
  109.     }
  110.     ::DisposeHandle(dataH);
  111. }
  112.  
  113.  
  114.  
  115. Boolean CLookupDocument::IsModified()
  116. {
  117.     return mDirty;
  118. }
  119.  
  120.  
  121. void CLookupDocument::DoAESave(FSSpec & inFileSpec, OSType inFileType)
  122. {
  123.     delete mFile;                        // Kill existing file
  124.     
  125.     mFile = new LFile(inFileSpec);        // Make new file object
  126.     
  127.     OSType    fileType = 'TEXT';            // Find proper file type
  128.     if (inFileType != fileType_Default) {
  129.         fileType = inFileType;
  130.     }
  131.                                         // Make new file on disk
  132.     mFile->CreateNewDataFile(CLookupApplication::kSignature, kFileType, 0);
  133.     mFile->OpenDataFork(fsRdWrPerm);
  134.     DoSave();                            // Write out data
  135.                                         // Change window name
  136.     mWindow->SetDescriptor(inFileSpec.name);
  137.     mIsSpecified = true;                // Document now has a specified file
  138. }
  139.  
  140.  
  141. void CLookupDocument::DoSave()
  142. {
  143.                                         // Get text and write to file
  144.     ostrstream stream;
  145.     
  146.     CListIterator<CEntry> iterator(mEntryList, iterate_FromStart);
  147.     CEntry * theEntry;
  148.     while (iterator.Next(theEntry))
  149.         stream << *theEntry;
  150.  
  151.     stream << ends;
  152.  
  153.     mFile->WriteDataFork(stream.str(), stream.pcount());
  154.     
  155.     mDirty = false;            // Saving makes doc un-dirty
  156. }
  157.  
  158.  
  159. void CLookupDocument::DoRevert()
  160. {
  161.     ReadFile();
  162.     BroadcastMessage(msg_Reverted, 0);
  163. }
  164.  
  165.  
  166. void
  167. CLookupDocument::DoPrint()
  168. {
  169. /*
  170.     LPrintout        *thePrintout = LPrintout::CreatePrintout(prto_TextDoc);
  171.     thePrintout->SetPrintRecord(mPrintRecordH);
  172.     LPlaceHolder    *textPlace = (LPlaceHolder*)
  173.                                     thePrintout->FindPaneByID('TBox');
  174.     textPlace->InstallOccupant(mTextView, atNone);
  175.     
  176.     thePrintout->DoPrintJob();
  177.     delete thePrintout;
  178. */
  179. }
  180.  
  181. const CEntry & CLookupDocument::GetEntryAt(EntryIndex row) const
  182. {
  183.     const CEntry * rec = GetEntryPtrAt(row);
  184.     Assert_(rec);
  185.     
  186.     return *rec;
  187. }
  188.  
  189. EntryIndex CLookupDocument::GetEntryCount() const
  190. {
  191.     return mEntryList.GetCount();
  192. }
  193.  
  194. void CLookupDocument::NotifyEntryChanged(CEntry * rec)
  195. {
  196.     Int32 listPosition = mEntryList.IndexOf(rec);
  197.     Assert_(listPosition != arrayIndex_Bad);
  198.     
  199.     EntryIndex row = listPosition - 1;
  200.     BroadcastMessage(msg_EntryChanged, &row);
  201. }
  202.  
  203. const CEntry * CLookupDocument::GetEntryPtrAt(EntryIndex row) const
  204. {
  205.     return mEntryList.ItemAt(row + 1);
  206. }
  207.  
  208. LModelObject* CLookupDocument::HandleCreateElementEvent(DescType inElemClass,
  209.     DescType inInsertPosition, LModelObject * inTargetObject, const AppleEvent & inAppleEvent,
  210.     AppleEvent & outAEReply)
  211. {
  212.     LModelObject * rval = nil;
  213.     
  214.     if(inElemClass == CEntry::kModelID)
  215.     {
  216.         CEntry * rec = new CEntry(this);
  217.  
  218.         LAESubDesc aeSubDesc(inAppleEvent);
  219.         
  220.         // Set the initial properties:
  221.         LAESubDesc properties = aeSubDesc.KeyedItem(keyAEPropData);
  222.         if(properties.GetType() != typeNull)
  223.         {
  224.             StAEDescriptor propDesc;
  225.             properties.ToDesc(propDesc);
  226.             
  227.             StAEDescriptor bogusReply;
  228.             rec->SetAEProperty(pContents, propDesc, bogusReply.mDesc);
  229.         }
  230.  
  231.         // Until we can read it from the AE:
  232.         EntryIndex insertion = 0;
  233.  
  234.         switch(inInsertPosition)
  235.         {
  236.             case kAEBeginning:
  237.             default:
  238.                 // Insertion position is fine - don't do anything
  239.                 break;
  240.             
  241.             case kAEBefore:
  242.                 insertion = mEntryList.IndexOf((CEntry *)inTargetObject) - 1;
  243.                 break;
  244.             
  245.             case kAEAfter:
  246.                 insertion = mEntryList.IndexOf((CEntry *)inTargetObject);
  247.                 break;
  248.             
  249.             case kAEEnd:
  250.                 insertion = mEntryList.GetCount();
  251.                 break;
  252.         }
  253.  
  254.         // This inserts where we want to be in the list. Stupid AddSubModel() inserts it at
  255.         // the end - we need to move it to where it should be.
  256.         mEntryList.RemoveItemsAt(1, arrayIndex_Last);
  257.         mEntryList.InsertAt(1, insertion + 1, rec);
  258.  
  259.         // Tell the view to update itself.
  260.         BroadcastMessage(msg_EntryInserted, &insertion);
  261.         
  262.         mDirty = true;
  263.         
  264.         rval = rec;
  265.     }
  266.     else
  267.     {
  268.         LSingleDoc::HandleCreateElementEvent(inElemClass, inInsertPosition, inTargetObject,
  269.             inAppleEvent, outAEReply);
  270.     }
  271.     
  272.     return rval;
  273. }
  274.  
  275. void CLookupDocument::DeleteEntry(CEntry * rec)
  276. {
  277.     Int32 idx = mEntryList.IndexOf(rec);
  278.     Assert_(idx);
  279.     
  280.     // This will remove the record from the list...
  281.     delete rec;
  282.  
  283.     EntryIndex row = idx - 1;
  284.     BroadcastMessage(msg_EntryDeleted, &row);
  285.  
  286.     mDirty = true;
  287. }
  288.  
  289. void CLookupDocument::FindCommandStatus(CommandT inCommand, Boolean & outEnabled,
  290.     Boolean & outUsesMark, Char16 & outMark, Str255 outName)
  291. {
  292.     switch (inCommand) {
  293.     
  294.         case cmd_Print:
  295.         case cmd_PrintOne:
  296.             outEnabled = true;
  297.             break;
  298.         
  299.         default:
  300.             LSingleDoc::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
  301.             break;
  302.     }
  303. }
  304.  
  305.  
  306. void CLookupDocument::GetSubModelByComplexKey(DescType inModelID, DescType inKeyForm,
  307.     const AEDesc & inKeyData, AEDesc & outToken) const
  308. {
  309.     if(inKeyForm == formRange)
  310.     {
  311.         LAESubDesc keyData(inKeyData, typeRangeDescriptor);
  312.         
  313.         LAESubDesc startDesc = keyData.KeyedItem(keyAERangeStart);
  314.         LAESubDesc endDesc = keyData.KeyedItem(keyAERangeStop);
  315.         
  316.         LModelObject * startModel = startDesc.ToModelObject();
  317.         LModelObject * endModel = endDesc.ToModelObject();
  318.         
  319.         Assert_(mSubModels);
  320.         Int32 startIdx = mSubModels->FetchIndexOf(&startModel);
  321.         Int32 endIdx = mSubModels->FetchIndexOf(&endModel);
  322.         
  323.         // Validate the range...
  324.         Assert_(startIdx != arrayIndex_Bad);
  325.         Assert_(endIdx != arrayIndex_Bad);
  326.         if(startIdx > endIdx)
  327.             Throw_(errAEImpossibleRange);
  328.         
  329.         LAEStream out;
  330.         
  331.         out.OpenList();
  332.         for (Int32 i = startIdx; i <= endIdx; i++) {
  333.             StAEDescriptor subToken;
  334.             
  335.             PutInToken(mEntryList.ItemAt(i), subToken.mDesc);
  336.             out.WriteDesc(subToken.mDesc);
  337.         }
  338.         out.CloseList();
  339.         out.Close(&outToken);
  340.     }
  341.     else
  342.         LSingleDoc::GetSubModelByComplexKey(inModelID, inKeyForm, inKeyData, outToken);
  343. }
  344.  
  345. CLookupDocument::~CLookupDocument()
  346. {
  347.     // Don't let the LModelObject destructor get it's hands on the mSubModel list...
  348.     mSubModels = nil;
  349. }
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.