home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWSemEvt / Sources / FWScptbl.cpp < prev    next >
Encoding:
Text File  |  1996-08-16  |  36.0 KB  |  1,307 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWSemObj.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #ifndef FWSCPTBL_H
  11. #include "FWScptbl.h"
  12. #endif
  13.  
  14. #ifndef FWPART_H
  15. #include "FWPart.h"
  16. #endif
  17.  
  18. #ifndef FWSCPCOL_H
  19. #include "FWScpCol.h"
  20. #endif
  21.  
  22. #ifndef FWSEMINT_H
  23. #include "FWSemInt.h"
  24. #endif
  25.  
  26. #ifndef FWAPLEVT_H
  27. #include "FWAplEvt.h"
  28. #endif
  29.  
  30. #ifndef FWDSCOPR_H
  31. #include "FWDscOpr.h"
  32. #endif
  33.  
  34. #ifndef FWOBJSPC_H
  35. #include "FWObjSpc.h"
  36. #endif
  37.  
  38. #ifndef FWSCPPRP_H
  39. #include "FWScpPrp.h"
  40. #endif
  41.  
  42. // ----- OS Layer -----
  43.  
  44. #ifndef SLODFSTR_K
  45. #include "SLODFStr.k"
  46. #endif
  47.  
  48. #ifndef SLODFSTR_H
  49. #include "SLODFStr.h"
  50. #endif
  51.  
  52. #ifndef __AEOBJECTS__
  53. #include <AEObjects.h>
  54. #endif
  55.  
  56. #ifndef __AEPACKOBJECT__
  57. #include <AEPackObject.h>
  58. #endif
  59.  
  60. //========================================================================================
  61. //    Runtime Information
  62. //========================================================================================
  63.  
  64. #ifdef FW_BUILD_MAC    
  65. #pragma segment fwsemevt
  66. #endif
  67.  
  68. //========================================================================================
  69. //    Template Instantiations
  70. //========================================================================================
  71.  
  72. FW_DEFINE_AUTO_TEMPLATE(FW_TOrderedCollection, FW_MScriptable)
  73. FW_DEFINE_AUTO_TEMPLATE(FW_TOrderedCollectionIterator, FW_MScriptable)
  74.  
  75. #ifdef FW_USE_TEMPLATE_PRAGMAS
  76.  
  77. #pragma template_access public
  78. #pragma template FW_TOrderedCollection<FW_MScriptable>
  79. #pragma template FW_TOrderedCollectionIterator<FW_MScriptable>
  80.  
  81. #endif
  82.  
  83. FW_DEFINE_AUTO(FW_MScriptable)
  84. FW_DEFINE_AUTO(FW_CElementIterator)
  85.  
  86. //========================================================================================
  87. //    class FW_MScriptable
  88. //========================================================================================
  89.  
  90. FW_DEFINE_CLASS_M0(FW_MScriptable)
  91.  
  92. //---------------------------------------------------------------------------------------
  93. //    FW_MScriptable::FW_MScriptable
  94. //---------------------------------------------------------------------------------------
  95.  
  96. FW_MScriptable::FW_MScriptable() :
  97.     fDependents(NULL)
  98. {
  99.     FW_END_CONSTRUCTOR
  100. }
  101.  
  102. //---------------------------------------------------------------------------------------
  103. //    FW_MScriptable::~FW_MScriptable
  104. //---------------------------------------------------------------------------------------
  105.  
  106. FW_MScriptable::~FW_MScriptable()
  107. {
  108.     FW_START_DESTRUCTOR
  109.     
  110.     if (fDependents)
  111.     {
  112.         FW_TOrderedCollectionIterator<FW_MScriptable> iter(fDependents);
  113.         for (FW_MScriptable* i = iter.First(); iter.IsNotComplete(); i = iter.Next())
  114.         {
  115.             i->HandlePrimaryDeleted(this);
  116.         }
  117.         delete fDependents;
  118.     }
  119. }
  120.  
  121. //---------------------------------------------------------------------------------------
  122. //    FW_MScriptable::GetObjectClass
  123. //---------------------------------------------------------------------------------------
  124.  
  125. ODDescType FW_MScriptable::GetObjectClass() const
  126. {
  127.     return cObject;
  128. }
  129.  
  130. //---------------------------------------------------------------------------------------
  131. //    FW_MScriptable::GetSpecifierForm
  132. //---------------------------------------------------------------------------------------
  133.  
  134. ODDescType FW_MScriptable::GetSpecifierForm() const
  135. {
  136.     return formAbsolutePosition;
  137. }
  138.  
  139. //---------------------------------------------------------------------------------------
  140. //    FW_MScriptable::GetTokenType
  141. //---------------------------------------------------------------------------------------
  142.  
  143. ODDescType FW_MScriptable::GetTokenType() const
  144. {
  145.     return typeODFSemanticObject;
  146. }
  147.  
  148. //---------------------------------------------------------------------------------------
  149. //    FW_MScriptable::HandleSemanticEvent
  150. //---------------------------------------------------------------------------------------
  151.  
  152. void FW_MScriptable::HandleSemanticEvent(Environment* ev,
  153.                                         FW_CPart* part,
  154.                                         AEKeyword eventClass,
  155.                                         AEKeyword eventID,
  156.                                         const FW_CAppleEvent& event,
  157.                                         FW_CAppleEvent& reply)
  158. {
  159.     if (eventClass == kAECoreSuite)
  160.     {
  161.         switch (eventID)
  162.         {
  163.             case kAEClone:
  164.                 DoAEClone(ev, part, event, reply);
  165.                 break;
  166.             
  167.             case kAEClose:
  168.                 DoAEClose(ev, part, event, reply);
  169.                 break;
  170.                 
  171.             case kAECountElements:
  172.                 DoAECountElements(ev, part, event, reply);
  173.                 break;
  174.                 
  175.             case kAECreateElement:
  176.                 DoAECreateElement(ev, part, event, reply);
  177.                 break;
  178.                 
  179.             case kAEDelete:
  180.                 DoAEDelete(ev, part, event, reply);
  181.                 break;
  182.                 
  183.             case kAEDoObjectsExist:
  184.                 DoAEDoObjectsExist(ev, part, event, reply);
  185.                 break;
  186.                 
  187.             case kAEGetClassInfo:
  188.                 DoAEGetClassInfo(ev, part, event, reply);
  189.                 break;
  190.                 
  191.             case kAEGetData:
  192.                 DoAEGetData(ev, part, event, reply);
  193.                 break;
  194.             
  195.             case kAEGetDataSize:
  196.                 DoAEGetDataSize(ev, part, event, reply);
  197.                 break;
  198.                 
  199.             case kAEGetEventInfo:
  200.                 DoAEGetEventInfo(ev, part, event, reply);
  201.                 break;
  202.                 
  203.             case kAEMove:
  204.                 DoAEMove(ev, part, event, reply);
  205.                 break;
  206.                                 
  207.             case kAEOpen:
  208.                 DoAEOpen(ev, part, event, reply);
  209.                 break;
  210.                 
  211.             case kAEPrint:
  212.                 DoAEPrint(ev, part, event, reply);
  213.                 break;
  214.                 
  215.             case kAESave:
  216.                 DoAESave(ev, part, event, reply);
  217.                 break;
  218.                 
  219.             case kAESetData:
  220.                 DoAESetData(ev, part, event, reply);
  221.                 break;
  222.  
  223.             default:
  224.                 DoSemanticEvent(ev, part, eventClass, eventID, event, reply);
  225.                 break;
  226.         }
  227.     }
  228.     else
  229.         DoSemanticEvent(ev, part, eventClass, eventID, event, reply);
  230. }
  231.  
  232. //---------------------------------------------------------------------------------------
  233. //    FW_MScriptable::DoSemanticEvent
  234. //---------------------------------------------------------------------------------------
  235.  
  236. void FW_MScriptable::DoSemanticEvent(Environment* ev,
  237.                                     FW_CPart* part,
  238.                                     AEKeyword eventClass,
  239.                                     AEKeyword eventID,
  240.                                     const FW_CAppleEvent& event,
  241.                                     FW_CAppleEvent& reply)
  242. {
  243. FW_UNUSED(ev);
  244. FW_UNUSED(part);
  245. FW_UNUSED(eventClass);
  246. FW_UNUSED(eventID);
  247. FW_UNUSED(event);
  248. FW_UNUSED(reply);
  249.     FW_THROW(FW_XException(errAEEventNotHandled));
  250. }
  251.  
  252. //---------------------------------------------------------------------------------------
  253. //    FW_MScriptable::DoAEClone
  254. //---------------------------------------------------------------------------------------
  255.  
  256. void FW_MScriptable::DoAEClone(Environment* ev,
  257.                             FW_CPart* part,
  258.                             const FW_CAppleEvent& event,
  259.                             FW_CAppleEvent& reply)
  260. {
  261. FW_UNUSED(ev);
  262. FW_UNUSED(part);
  263. FW_UNUSED(event);
  264. FW_UNUSED(reply);
  265.     FW_THROW(FW_XException(errAEEventNotHandled));
  266. }
  267.  
  268. //---------------------------------------------------------------------------------------
  269. //    FW_MScriptable::DoAEClose
  270. //---------------------------------------------------------------------------------------
  271.  
  272. void FW_MScriptable::DoAEClose(Environment* ev,
  273.                             FW_CPart* part,
  274.                             const FW_CAppleEvent& event,
  275.                             FW_CAppleEvent& reply)
  276. {
  277. FW_UNUSED(ev);
  278. FW_UNUSED(part);
  279. FW_UNUSED(event);
  280. FW_UNUSED(reply);
  281.     FW_THROW(FW_XException(errAEEventNotHandled));
  282. }
  283.  
  284. //---------------------------------------------------------------------------------------
  285. //    FW_MScriptable::DoAECountElements
  286. //---------------------------------------------------------------------------------------
  287.  
  288. void FW_MScriptable::DoAECountElements(Environment* ev,
  289.                                         FW_CPart* part,
  290.                                         const FW_CAppleEvent& event,
  291.                                         FW_CAppleEvent& reply)
  292. {
  293.     reply.PutLongInteger(CountElements(ev, part, event.GetType(keyAEObjectClass)), keyAEResult);
  294. }
  295.  
  296. //---------------------------------------------------------------------------------------
  297. //    FW_MScriptable::DoAECreate
  298. //---------------------------------------------------------------------------------------
  299.  
  300. void FW_MScriptable::DoAECreateElement(Environment* ev,
  301.                                         FW_CPart* part,
  302.                                         const FW_CAppleEvent& event,
  303.                                         FW_CAppleEvent& reply)
  304. {
  305. FW_UNUSED(ev);
  306. FW_UNUSED(part);
  307. FW_UNUSED(event);
  308. FW_UNUSED(reply);
  309.     FW_THROW(FW_XException(errAEEventNotHandled));
  310. }
  311.  
  312. //---------------------------------------------------------------------------------------
  313. //    FW_MScriptable::DoAEDelete
  314. //---------------------------------------------------------------------------------------
  315.  
  316. void FW_MScriptable::DoAEDelete(Environment* ev,
  317.                                 FW_CPart* part,
  318.                                 const FW_CAppleEvent& event,
  319.                                 FW_CAppleEvent& reply)
  320. {
  321. FW_UNUSED(ev);
  322. FW_UNUSED(part);
  323. FW_UNUSED(event);
  324. FW_UNUSED(reply);
  325.     FW_THROW(FW_XException(errAEEventNotHandled));
  326. }
  327.  
  328. //---------------------------------------------------------------------------------------
  329. //    FW_MScriptable::DoAEDoObjectsExist
  330. //---------------------------------------------------------------------------------------
  331.  
  332. void FW_MScriptable::DoAEDoObjectsExist(Environment* ev,
  333.                                         FW_CPart* part,
  334.                                         const FW_CAppleEvent& event,
  335.                                         FW_CAppleEvent& reply)
  336. {
  337. FW_UNUSED(ev);
  338. FW_UNUSED(part);
  339. FW_UNUSED(event);
  340. FW_UNUSED(reply);
  341.     FW_THROW(FW_XException(errAEEventNotHandled));
  342. }
  343.  
  344. //---------------------------------------------------------------------------------------
  345. //    FW_MScriptable::DoAEGetClassInfo
  346. //---------------------------------------------------------------------------------------
  347.  
  348. void FW_MScriptable::DoAEGetClassInfo(Environment* ev,
  349.                                     FW_CPart* part,
  350.                                     const FW_CAppleEvent& event,
  351.                                     FW_CAppleEvent& reply)
  352. {
  353. FW_UNUSED(ev);
  354. FW_UNUSED(part);
  355. FW_UNUSED(event);
  356. FW_UNUSED(reply);
  357.     FW_THROW(FW_XException(errAEEventNotHandled));
  358. }
  359.  
  360. //---------------------------------------------------------------------------------------
  361. //    FW_MScriptable::DoAEGetData
  362. //---------------------------------------------------------------------------------------
  363.  
  364. void FW_MScriptable::DoAEGetData(Environment* ev,
  365.                                 FW_CPart* part,
  366.                                 const FW_CAppleEvent& event,
  367.                                 FW_CAppleEvent& reply)
  368. {
  369. FW_UNUSED(event);
  370.     FW_CDesc objectSpecifier;
  371.     
  372.     BuildObjectSpecifier(ev, part, GetFrame(ev, part), objectSpecifier, GetSpecifierForm());
  373.     reply.PutDataByDesc(objectSpecifier, keyAEResult);
  374. }
  375.  
  376. //---------------------------------------------------------------------------------------
  377. //    FW_MScriptable::DoAEGetDataSize
  378. //---------------------------------------------------------------------------------------
  379.  
  380. void FW_MScriptable::DoAEGetDataSize(Environment* ev,
  381.                                     FW_CPart* part,
  382.                                     const FW_CAppleEvent& event,
  383.                                     FW_CAppleEvent& reply)
  384. {
  385. FW_UNUSED(ev);
  386. FW_UNUSED(part);
  387. FW_UNUSED(event);
  388. FW_UNUSED(reply);
  389.     FW_THROW(FW_XException(errAEEventNotHandled));
  390. }
  391.  
  392. //---------------------------------------------------------------------------------------
  393. //    FW_MScriptable::DoAEGetEventInfo
  394. //---------------------------------------------------------------------------------------
  395.  
  396. void FW_MScriptable::DoAEGetEventInfo(Environment* ev,
  397.                                     FW_CPart* part,
  398.                                     const FW_CAppleEvent& event,
  399.                                     FW_CAppleEvent& reply)
  400. {
  401. FW_UNUSED(ev);
  402. FW_UNUSED(part);
  403. FW_UNUSED(event);
  404. FW_UNUSED(reply);
  405.     FW_THROW(FW_XException(errAEEventNotHandled));
  406. }
  407.  
  408. //---------------------------------------------------------------------------------------
  409. //    FW_MScriptable::DoAEMove
  410. //---------------------------------------------------------------------------------------
  411.  
  412. void FW_MScriptable::DoAEMove(Environment* ev,
  413.                             FW_CPart* part,
  414.                             const FW_CAppleEvent& event,
  415.                             FW_CAppleEvent& reply)
  416. {
  417. FW_UNUSED(ev);
  418. FW_UNUSED(part);
  419. FW_UNUSED(event);
  420. FW_UNUSED(reply);
  421.     FW_THROW(FW_XException(errAEEventNotHandled));
  422. }
  423.  
  424. //---------------------------------------------------------------------------------------
  425. //    FW_MScriptable::DoAEOpen
  426. //---------------------------------------------------------------------------------------
  427.  
  428. void FW_MScriptable::DoAEOpen(Environment* ev,
  429.                             FW_CPart* part,
  430.                             const FW_CAppleEvent& event,
  431.                             FW_CAppleEvent& reply)
  432. {
  433. FW_UNUSED(ev);
  434. FW_UNUSED(part);
  435. FW_UNUSED(event);
  436. FW_UNUSED(reply);
  437.     FW_THROW(FW_XException(errAEEventNotHandled));
  438. }
  439.  
  440. //---------------------------------------------------------------------------------------
  441. //    FW_MScriptable::DoAEPrint
  442. //---------------------------------------------------------------------------------------
  443.  
  444. void FW_MScriptable::DoAEPrint(Environment* ev,
  445.                             FW_CPart* part,
  446.                             const FW_CAppleEvent& event,
  447.                             FW_CAppleEvent& reply)
  448. {
  449. FW_UNUSED(ev);
  450. FW_UNUSED(part);
  451. FW_UNUSED(event);
  452. FW_UNUSED(reply);
  453.     FW_THROW(FW_XException(errAEEventNotHandled));
  454. }
  455.  
  456. //---------------------------------------------------------------------------------------
  457. //    FW_MScriptable::DoAESave
  458. //---------------------------------------------------------------------------------------
  459.  
  460. void FW_MScriptable::DoAESave(Environment* ev,
  461.                             FW_CPart* part,
  462.                             const FW_CAppleEvent& event,
  463.                             FW_CAppleEvent& reply)
  464. {
  465. FW_UNUSED(ev);
  466. FW_UNUSED(part);
  467. FW_UNUSED(event);
  468. FW_UNUSED(reply);
  469.     FW_THROW(FW_XException(errAEEventNotHandled));
  470. }
  471.  
  472. //---------------------------------------------------------------------------------------
  473. //    FW_MScriptable::DoAESetData
  474. //---------------------------------------------------------------------------------------
  475.  
  476. void FW_MScriptable::DoAESetData(Environment* ev,    
  477.                                 FW_CPart* part,
  478.                                 const FW_CAppleEvent& event,
  479.                                 FW_CAppleEvent& reply)
  480. {
  481. FW_UNUSED(ev);
  482. FW_UNUSED(part);
  483. FW_UNUSED(event);
  484. FW_UNUSED(reply);
  485.     FW_THROW(FW_XException(errAEEventNotHandled));
  486. }
  487.  
  488. //---------------------------------------------------------------------------------------
  489. //    FW_MScriptable::GetFrame
  490. //---------------------------------------------------------------------------------------
  491.  
  492. FW_CFrame* FW_MScriptable::GetFrame(Environment* ev, FW_CPart* part) const
  493. {
  494.     return (part->GetLastActiveFrame(ev));
  495. }
  496.  
  497. //---------------------------------------------------------------------------------------
  498. //    FW_MScriptable::Compare
  499. //---------------------------------------------------------------------------------------
  500.  
  501. FW_Boolean FW_MScriptable::CompareScriptableObjects(Environment* ev,
  502.                                                     FW_CPart* part,
  503.                                                     ODDescType operation,
  504.                                                     const FW_CDesc& other) const
  505. {
  506.     FW_Boolean result = FALSE;
  507.     
  508.     if (operation == kAEEquals && 
  509.         part->GetSemanticInterface(ev)->TypeIsSemanticObject(ev, other.DescriptorType()))
  510.     {
  511.         FW_MScriptable* otherObject = ::FW_ExtractScriptableFromDesc(other);
  512.         result = (this == otherObject);
  513.     }
  514.     
  515.     return result;
  516. }
  517.  
  518. //---------------------------------------------------------------------------------------
  519. //    FW_MScriptable::GetContainingObject
  520. //---------------------------------------------------------------------------------------
  521.  
  522. FW_MScriptable* FW_MScriptable::GetContainingObject(Environment* ev,
  523.                                                     FW_CPart* part) const
  524. {
  525. FW_UNUSED(ev);
  526.     FW_MScriptable* containingObject = FW_DYNAMIC_CAST(FW_MScriptable, part);
  527.     FW_ASSERT(containingObject != NULL);
  528.     
  529.     containingObject->AcquireScriptable();
  530.     return containingObject;
  531. }
  532.  
  533. //---------------------------------------------------------------------------------------
  534. //    FW_MScriptable::GetContainedObject
  535. //---------------------------------------------------------------------------------------
  536.  
  537. FW_Boolean FW_MScriptable::GetContainedObject(Environment* ev,
  538.                                             FW_CPart* part,
  539.                                             ODDescType desiredClass,
  540.                                             ODDescType form,
  541.                                             const FW_CDesc& selectionData,
  542.                                             FW_CDesc& containedObjectToken)
  543. {
  544.     FW_Boolean result = FALSE;
  545.     
  546.     if (desiredClass == cProperty)
  547.     {
  548.         ODDescType whichProperty;
  549.         
  550.         selectionData >> whichProperty;
  551.         
  552.         if (HasProperty(whichProperty))
  553.         {
  554.             FW_CPropertyDesignator* designator = FW_NEW(FW_CPropertyDesignator, (part, this, whichProperty));
  555.             ::FW_InsertScriptableIntoDesc(designator, containedObjectToken);
  556.             result = TRUE;
  557.         }
  558.     }
  559.     else
  560.     {
  561.         FW_MScriptable* requestedObject = NULL;
  562.  
  563.         switch (form)
  564.         {
  565.             case formName:
  566.                 {
  567.                     FW_CString desiredName;
  568.                     selectionData.GetString(desiredName);
  569.                     requestedObject = GetElementByName(ev, part, desiredClass, desiredName);
  570.                 }
  571.                 break;
  572.             
  573.             case formRelativePosition:
  574.                 {
  575.                     ODDescType relativePosition;
  576.                     
  577.                     relativePosition = selectionData.GetEnumeratedType();
  578.                     requestedObject = GetAdjacentObject(ev, part, desiredClass, relativePosition);
  579.                 }
  580.                 break;
  581.             
  582.             case formRange:
  583.                 {
  584.                     FW_MScriptable* startObject = NULL;
  585.                     FW_MScriptable* stopObject = NULL;
  586.                     
  587.                     FW_CSemanticInterface* semInt = part->GetSemanticInterface(ev);
  588.                     
  589.                     FW_ASSERT(semInt);
  590.                     
  591.                     FW_CDesc rangeRecord;
  592.                     FW_CDesc objectSpec;
  593.                     FW_CDesc objectToken;
  594.                     
  595.                     selectionData.Coerce(typeAERecord, rangeRecord);
  596.     
  597.                     rangeRecord.GetDataByDesc(objectSpec, keyAERangeStart);
  598.                     semInt->Resolve(ev, objectSpec, objectToken);
  599.                     startObject = semInt->GetScriptableFromToken(ev, objectToken);
  600.                     
  601.                     objectSpec.Clear();
  602.                     objectToken.Clear();
  603.                     
  604.                     rangeRecord.GetDataByDesc(objectSpec, keyAERangeStop);
  605.                     semInt->Resolve(ev, objectSpec, objectToken);
  606.                     stopObject = semInt->GetScriptableFromToken(ev, objectToken);
  607.                     
  608.                     requestedObject = GetElementsWithinRange(ev, part, desiredClass, startObject, stopObject);
  609.                 }
  610.                 break;
  611.             
  612.             case formUniqueID:
  613.                 break;
  614.                 
  615.             case formAbsolutePosition:
  616.                 requestedObject = GetElementByAbsolutePosition(ev, part, desiredClass, selectionData);
  617.                 break;
  618.                 
  619.             default:
  620.                 break;
  621.         }
  622.  
  623.         if (requestedObject)
  624.         {
  625.             ::FW_InsertScriptableIntoDesc(requestedObject, containedObjectToken);
  626.             result = TRUE;
  627.         }
  628.     }
  629.     return result;
  630. }
  631.  
  632. //---------------------------------------------------------------------------------------
  633. //    FW_MScriptable::GetElementByAbsolutePosition
  634. //---------------------------------------------------------------------------------------
  635.  
  636. FW_MScriptable* FW_MScriptable::GetElementByAbsolutePosition(Environment* ev,
  637.                                                             FW_CPart* part,
  638.                                                             ODDescType desiredClass,
  639.                                                             const FW_CDesc& selectionData)
  640. {
  641.     FW_MScriptable* requestedObject = NULL;
  642.     ODDescType        specifierType = selectionData.DescriptorType();
  643.     
  644.     if (specifierType == typeAbsoluteOrdinal)
  645.     {
  646.         switch (selectionData.GetAbsoluteOrdinal())
  647.         {
  648.             case kAEFirst:
  649.                 requestedObject = GetFirstElement(ev, part, desiredClass);
  650.                 break;
  651.             
  652.             case kAEMiddle:
  653.                 requestedObject = GetMiddleElement(ev, part, desiredClass);
  654.                 break;
  655.             
  656.             case kAELast:
  657.                 requestedObject = GetLastElement(ev, part, desiredClass);
  658.                 break;
  659.                 
  660.             case kAEAny:
  661.                 requestedObject = GetAnyElement(ev, part, desiredClass);
  662.                 break;
  663.                 
  664.             case kAEAll:
  665.                 requestedObject = GetAllElements(ev, part, desiredClass);
  666.                 break;
  667.                 
  668.             default:
  669.                 break;
  670.         }
  671.         
  672.     }
  673.     else if (specifierType == typeLongInteger)
  674.     {
  675.         long objectIndex;
  676.         selectionData >> objectIndex;
  677.         
  678.         if (objectIndex < 0)
  679.             objectIndex += (CountElements(ev, part, desiredClass) + 1);
  680.             
  681.         requestedObject = GetElementByIndex(ev, part, desiredClass, objectIndex);
  682.     }
  683.     
  684.     return requestedObject;
  685. }
  686.  
  687. //---------------------------------------------------------------------------------------
  688. // FW_MScriptable::GetElementByName: default implementation iterates through
  689. // contained elements of the specified type looking for a name match. Subclasses
  690. // may be able to optimize searching based on knowledge of content.
  691. //---------------------------------------------------------------------------------------
  692.  
  693. FW_MScriptable* FW_MScriptable::GetElementByName(Environment* ev,
  694.                                                 FW_CPart* part,
  695.                                                 ODDescType desiredClass,
  696.                                                 const FW_CString& desiredName)
  697. {
  698.     FW_CElementIterator* iter = NewElementIterator(ev, part, desiredClass);
  699.     
  700.     FW_VOLATILE(iter);
  701.     
  702.     FW_CDesc nameDesc;
  703.     FW_CString nameString;
  704.     FW_MScriptable* desiredObject = NULL;
  705.     
  706.     FW_TRY
  707.     {
  708.         for (FW_MScriptable* currentObject = iter->First(); 
  709.                 iter->IsNotComplete() && !desiredObject; currentObject = iter->Next())
  710.         {
  711.             if (currentObject->HasProperty(pName))
  712.             {
  713.                 currentObject->GetProperty(ev, part, nameDesc, pName, typeChar);
  714.                 nameDesc.GetString(nameString);
  715.                 
  716.                 if (desiredName == nameString)
  717.                     desiredObject = currentObject;
  718.                 else
  719.                     nameDesc.Clear();
  720.             }
  721.         }
  722.     }
  723.     FW_CATCH_BEGIN
  724.     FW_CATCH_EVERYTHING()
  725.     {
  726.         delete iter;
  727.         FW_THROW_SAME();
  728.     }
  729.     FW_CATCH_END
  730.     
  731.     delete iter;
  732.     
  733.     if (desiredObject)
  734.         desiredObject->AcquireScriptable();
  735.     return desiredObject;
  736. }
  737.  
  738.  
  739. //---------------------------------------------------------------------------------------
  740. //    FW_MScriptable::CountElements
  741. //---------------------------------------------------------------------------------------
  742.  
  743. long FW_MScriptable::CountElements(Environment* ev,
  744.                                     FW_CPart* part,
  745.                                     ODDescType desiredClass)
  746. {
  747.     unsigned long count = 0;
  748.     FW_CElementIterator* iter = NewElementIterator(ev, part, desiredClass);
  749.     FW_VOLATILE(iter);
  750.     
  751.     FW_TRY
  752.     {
  753.         for (iter->First(); iter->IsNotComplete(); iter->Next())
  754.             count++;
  755.     }
  756.     FW_CATCH_BEGIN
  757.     FW_CATCH_EVERYTHING()
  758.     {
  759.         delete iter;
  760.         FW_THROW_SAME();
  761.     }
  762.     FW_CATCH_END
  763.     
  764.     delete iter;
  765.     
  766.     return count;
  767. }
  768.  
  769. //---------------------------------------------------------------------------------------
  770. //    FW_MScriptable::GetElementByIndex
  771. //---------------------------------------------------------------------------------------
  772.  
  773. FW_MScriptable* FW_MScriptable::GetElementByIndex(Environment* ev,
  774.                                                 FW_CPart* part,
  775.                                                 ODDescType desiredClass, 
  776.                                                 long index)
  777. {
  778.     FW_MScriptable* desiredObject = NULL;
  779.     FW_CElementIterator* iter = NewElementIterator(ev, part, desiredClass);
  780.     FW_VOLATILE(iter);
  781.     
  782.     FW_TRY
  783.     {
  784.         long count = 0;
  785.         
  786.         for (FW_MScriptable* currentObject = iter->First(); count <= index && iter->IsNotComplete();
  787.             currentObject = iter->Next())
  788.         {
  789.             if (++count == index)
  790.                 desiredObject = currentObject;
  791.         }
  792.     }
  793.     FW_CATCH_BEGIN
  794.     FW_CATCH_EVERYTHING()
  795.     {
  796.         delete iter;
  797.         FW_THROW_SAME();
  798.     }
  799.     FW_CATCH_END
  800.     
  801.     delete iter;
  802.     
  803.     if (desiredObject)
  804.         desiredObject->AcquireScriptable();
  805.     return desiredObject;
  806. }
  807.  
  808. //---------------------------------------------------------------------------------------
  809. //    FW_MScriptable::GetFirstElement
  810. //---------------------------------------------------------------------------------------
  811.  
  812. FW_MScriptable* FW_MScriptable::GetFirstElement(Environment* ev,
  813.                                                 FW_CPart* part,
  814.                                                 ODDescType desiredClass)
  815. {
  816.     return (GetElementByIndex(ev, part, desiredClass, 1));
  817. }
  818.  
  819. //---------------------------------------------------------------------------------------
  820. //    FW_MScriptable::GetMiddleElement
  821. //---------------------------------------------------------------------------------------
  822.  
  823. FW_MScriptable* FW_MScriptable::GetMiddleElement(Environment* ev,
  824.                                                 FW_CPart* part,
  825.                                                 ODDescType desiredClass)
  826. {
  827.     return (GetElementByIndex(ev, part, desiredClass, (CountElements(ev, part, desiredClass) + 1) / 2));
  828. }
  829.  
  830. //---------------------------------------------------------------------------------------
  831. //    FW_MScriptable::GetLastElement
  832. //---------------------------------------------------------------------------------------
  833.  
  834. FW_MScriptable* FW_MScriptable::GetLastElement(Environment* ev,
  835.                                             FW_CPart* part,
  836.                                             ODDescType desiredClass)
  837. {
  838.     return (GetElementByIndex(ev, part, desiredClass, CountElements(ev, part, desiredClass)));
  839. }
  840.  
  841. //---------------------------------------------------------------------------------------
  842. //    FW_MScriptable::GetAnyElement
  843. //---------------------------------------------------------------------------------------
  844.  
  845. FW_MScriptable* FW_MScriptable::GetAnyElement(Environment* ev,
  846.                                             FW_CPart* part,
  847.                                             ODDescType desiredClass)
  848. {
  849. FW_UNUSED(ev);
  850. FW_UNUSED(part);
  851. FW_UNUSED(desiredClass);
  852.     FW_PRIV_ASSERT(Not_Yet_Implemented);
  853.     return NULL;
  854. }
  855.  
  856. //---------------------------------------------------------------------------------------
  857. //    FW_MScriptable::GetAllElements
  858. //---------------------------------------------------------------------------------------
  859.  
  860. FW_MScriptable* FW_MScriptable::GetAllElements(Environment* ev,
  861.                                             FW_CPart* part,
  862.                                             ODDescType desiredClass)
  863. {
  864.     FW_CElementIterator* iter = NULL;
  865.     FW_VOLATILE(iter);
  866.     FW_CScriptableCollection* collection = NULL;
  867.     FW_VOLATILE(collection);
  868.     
  869.     FW_TRY
  870.     {
  871.         iter = NewElementIterator(ev, part, desiredClass);
  872.         collection = FW_NEW(FW_CScriptableCollection, ());
  873.         
  874.         for (FW_MScriptable* currentObject = iter->First(); iter->IsNotComplete();
  875.             currentObject = iter->Next())
  876.         {
  877.             collection->Add(currentObject);
  878.         }
  879.         delete iter;
  880.     }
  881.     FW_CATCH_BEGIN
  882.     FW_CATCH_EVERYTHING()
  883.     {
  884.         delete collection;
  885.         delete iter;
  886.         
  887.         FW_THROW_SAME();
  888.     }
  889.     FW_CATCH_END
  890.             
  891.     if (collection->Count() == 0)
  892.     {
  893.         delete collection;
  894.         collection = NULL;
  895.     }
  896.  
  897.     return collection;
  898. }
  899.  
  900. //---------------------------------------------------------------------------------------
  901. //    FW_MScriptable::GetAdjacentObject
  902. //---------------------------------------------------------------------------------------
  903.  
  904. FW_MScriptable* FW_MScriptable::GetAdjacentObject(Environment* ev,
  905.                                                 FW_CPart* part,
  906.                                                 ODDescType desiredClass,
  907.                                                 ODDescType relativePosition) const
  908. {
  909.     FW_MScriptable* result = NULL;
  910.     FW_MScriptable* container = GetContainingObject(ev, part);
  911.     
  912.     if (container)
  913.     {
  914.         FW_CElementIterator* iter = container->NewElementIterator(ev, part, desiredClass);
  915.         FW_VOLATILE(iter);
  916.         
  917.         FW_MScriptable* previous = NULL;
  918.         FW_Boolean            keepGoing = TRUE;
  919.         FW_Boolean            fetchNext = FALSE;
  920.         
  921.         FW_TRY
  922.         {
  923.             for (FW_MScriptable* currentObject = iter->First(); keepGoing && iter->IsNotComplete();
  924.                 currentObject = iter->Next())
  925.             {
  926.                 if (fetchNext)
  927.                 {
  928.                     result = currentObject;
  929.                     keepGoing = FALSE;
  930.                 }
  931.                 else if (currentObject == this)
  932.                 {
  933.                     if (relativePosition == kAEPrevious)
  934.                     {
  935.                         result = previous;
  936.                         keepGoing = FALSE;
  937.                     }
  938.                     else
  939.                         fetchNext = TRUE;
  940.                 }
  941.                 previous = currentObject;
  942.             }
  943.         }
  944.         FW_CATCH_BEGIN
  945.         FW_CATCH_EVERYTHING()
  946.         {
  947.             delete iter;
  948.             FW_THROW_SAME();
  949.         }
  950.         FW_CATCH_END
  951.     }
  952.     
  953.     if (result)
  954.         result->AcquireScriptable();
  955.     return result;
  956. }
  957.  
  958. //---------------------------------------------------------------------------------------
  959. //    FW_MScriptable::GetElementsWithinRange
  960. //---------------------------------------------------------------------------------------
  961.  
  962. FW_MScriptable* FW_MScriptable::GetElementsWithinRange(Environment* ev,
  963.                                                     FW_CPart* part,
  964.                                                     ODDescType desiredClass,
  965.                                                     FW_MScriptable* startObject,
  966.                                                     FW_MScriptable* stopObject) const
  967. {
  968.     FW_CElementIterator* iter = NewElementIterator(ev, part, desiredClass);
  969.     FW_CScriptableCollection* collection = FW_NEW(FW_CScriptableCollection, ());
  970.     
  971.     FW_Boolean foundStart = FALSE;
  972.     FW_Boolean foundStop = FALSE;
  973.     
  974.     for (FW_MScriptable* currentObject = iter->First(); !foundStop && iter->IsNotComplete();
  975.         currentObject = iter->Next())
  976.     {
  977.         FW_CDesc objectDesc;
  978.         
  979.         ::FW_InsertScriptableIntoDesc(currentObject, objectDesc);
  980.         
  981.         if (!foundStart)
  982.             foundStart = startObject->CompareScriptableObjects(ev, part, kAEEquals, objectDesc);
  983.         
  984.         if (foundStart)
  985.             collection->Add(currentObject);
  986.         
  987.         foundStop = stopObject->CompareScriptableObjects(ev, part, kAEEquals, objectDesc);
  988.     }
  989.     
  990.     return collection;
  991. }
  992.  
  993. //---------------------------------------------------------------------------------------
  994. //    FW_MScriptable::NewElementIterator
  995. //---------------------------------------------------------------------------------------
  996.  
  997. FW_CElementIterator* FW_MScriptable::NewElementIterator(Environment* ev,
  998.                                                         FW_CPart* part,
  999.                                                         ODDescType desiredClass) const
  1000. {
  1001. FW_UNUSED(ev);
  1002. FW_UNUSED(part);
  1003. FW_UNUSED(desiredClass);
  1004.     FW_THROW(FW_XException(errAEEventNotHandled));
  1005.     return NULL;
  1006. }
  1007.  
  1008. //---------------------------------------------------------------------------------------
  1009. //    FW_MScriptable::HasProperty
  1010. //---------------------------------------------------------------------------------------
  1011.  
  1012. FW_Boolean FW_MScriptable::HasProperty(ODDescType whichProperty) const
  1013. {
  1014.     return (whichProperty == pClass);    // class is the only supported property
  1015. }
  1016.  
  1017. //---------------------------------------------------------------------------------------
  1018. //    FW_MScriptable::BuildObjectSpecifier
  1019. //---------------------------------------------------------------------------------------
  1020.  
  1021. void FW_MScriptable::BuildObjectSpecifier(Environment* ev,
  1022.                                         FW_CPart* part,
  1023.                                         const FW_CFrame* frame,
  1024.                                         FW_CDesc& specifier,
  1025.                                         ODDescType preferredForm) const
  1026. {
  1027.     FW_MScriptable* container = GetContainingObject(ev, part);
  1028.     
  1029.     FW_CDesc             containerSpecifier;
  1030.     FW_CDesc            mySpecifier;
  1031.     FW_Boolean            gotData = FALSE;
  1032.     
  1033.     container->BuildObjectSpecifier(ev, part, frame, containerSpecifier, container->GetSpecifierForm());
  1034.     
  1035.     switch (preferredForm)
  1036.     {
  1037.         case formName:
  1038.             gotData = HasProperty(pName) && GetProperty(ev, part, mySpecifier, pName);
  1039.             break;
  1040.             
  1041.         case formUniqueID:
  1042.             gotData  = HasProperty(pID) && GetProperty(ev, part, mySpecifier, pID);
  1043.             break;
  1044.             
  1045.         case formAbsolutePosition:
  1046.             gotData = HasProperty(pIndex) && GetProperty(ev, part, mySpecifier, pIndex);
  1047.             break;
  1048.             
  1049.         default:
  1050.             break;
  1051.     }
  1052.     
  1053.     if (!gotData)
  1054.         FW_THROW(FW_XException(errAECantSupplyType));
  1055.  
  1056.     ::FW_CreateObjSpecifier(GetObjectClass(), containerSpecifier, preferredForm, mySpecifier, specifier);
  1057. }
  1058.  
  1059. //---------------------------------------------------------------------------------------
  1060. //    FW_MScriptable::GetObjectSpecifier
  1061. //---------------------------------------------------------------------------------------
  1062.  
  1063. void FW_MScriptable::GetObjectSpecifier(Environment* ev,
  1064.                                         FW_CPart* part,
  1065.                                         FW_CDesc& specifier) const
  1066. {
  1067.     BuildObjectSpecifier(ev, part, GetFrame(ev, part), specifier, GetSpecifierForm());
  1068. }
  1069.  
  1070. //---------------------------------------------------------------------------------------
  1071. //    FW_MScriptable::GetPropertySpecifier
  1072. //---------------------------------------------------------------------------------------
  1073.  
  1074. void FW_MScriptable::GetPropertySpecifier(Environment* ev,
  1075.                                         FW_CPart* part,
  1076.                                         ODDescType whichProperty,
  1077.                                         FW_CDesc& specifier)
  1078. {
  1079.     if (HasProperty(whichProperty))
  1080.     {
  1081.         FW_CDesc     objectDesc;
  1082.         FW_CDesc    propertyDesc;
  1083.         
  1084.         GetObjectSpecifier(ev, part, objectDesc);
  1085.         propertyDesc.PutType(whichProperty);
  1086.         
  1087.         ::FW_CreateObjSpecifier(cProperty, objectDesc, formPropertyID, propertyDesc, specifier);
  1088.     }
  1089.     else
  1090.         FW_THROW(FW_XException(errAENoSuchObject));
  1091. }
  1092.  
  1093. //---------------------------------------------------------------------------------------
  1094. //    FW_MScriptable::GetPropertyInfo
  1095. //---------------------------------------------------------------------------------------
  1096.  
  1097. void FW_MScriptable::GetPropertyInfo(Environment* ev,
  1098.                                     FW_CPart* part,
  1099.                                     FW_Boolean& canUndo,
  1100.                                     FW_Boolean& causesChange) const
  1101. {
  1102. FW_UNUSED(ev);
  1103. FW_UNUSED(part);
  1104.     canUndo = TRUE;
  1105.     causesChange = TRUE;
  1106. }
  1107.  
  1108. //---------------------------------------------------------------------------------------
  1109. //    FW_MScriptable::GetProperty
  1110. //---------------------------------------------------------------------------------------
  1111.  
  1112. FW_Boolean FW_MScriptable::GetProperty(Environment* ev, 
  1113.                                     FW_CPart* part,
  1114.                                     FW_CDesc& propertyValue, 
  1115.                                     ODDescType whichProperty, 
  1116.                                     ODDescType desiredClass) const
  1117. {
  1118. FW_UNUSED(desiredClass);
  1119.     FW_Boolean hasProperty = FALSE;
  1120.     
  1121.     switch (whichProperty)
  1122.     {
  1123.         case pClass:
  1124.             {
  1125.                 ODDescType itsClass = GetObjectClass();
  1126.                 propertyValue << itsClass;
  1127.                 hasProperty = TRUE;
  1128.             }
  1129.             break;
  1130.         
  1131.         case pIndex:
  1132.             {
  1133.                 FW_MScriptable* container = GetContainingObject(ev, part);
  1134.                 FW_CElementIterator* iter = container->NewElementIterator(ev, part, GetObjectClass());
  1135.                 FW_VOLATILE(iter);
  1136.                 
  1137.                 long     index = 1;
  1138.                 
  1139.                 FW_TRY
  1140.                 {
  1141.                     for (FW_MScriptable* semObj = iter->First(); iter->IsNotComplete() && !hasProperty; semObj = iter->Next(), index++)
  1142.                     {
  1143.                         if (semObj == this)
  1144.                         {
  1145.                             propertyValue << index;
  1146.                             hasProperty = TRUE;
  1147.                         }
  1148.                     }
  1149.                 }
  1150.                 FW_CATCH_BEGIN
  1151.                 FW_CATCH_EVERYTHING()
  1152.                 {
  1153.                     delete iter;
  1154.                     FW_THROW_SAME();
  1155.                 }
  1156.                 FW_CATCH_END
  1157.             }
  1158.             break;
  1159.             
  1160.         default:
  1161.             hasProperty = FALSE;
  1162.             break;    
  1163.     }
  1164.     
  1165.     return hasProperty;
  1166. }
  1167.  
  1168. //---------------------------------------------------------------------------------------
  1169. //    FW_MScriptable::SetProperty
  1170. //---------------------------------------------------------------------------------------
  1171.  
  1172. void FW_MScriptable::SetProperty(Environment* ev, 
  1173.                                 FW_CPart* part, 
  1174.                                 FW_CDesc& propertyValue, 
  1175.                                 ODDescType whichProperty)
  1176. {
  1177. FW_UNUSED(ev);
  1178. FW_UNUSED(part);
  1179. FW_UNUSED(propertyValue);
  1180. FW_UNUSED(whichProperty);
  1181.     FW_THROW(FW_XException(errAEEventNotHandled));
  1182. }
  1183.  
  1184. //---------------------------------------------------------------------------------------
  1185. //    FW_MScriptable::SetProperties
  1186. //---------------------------------------------------------------------------------------
  1187.  
  1188. void FW_MScriptable::SetProperties(Environment* ev,
  1189.                                 FW_CPart* part,
  1190.                                 const FW_CDesc& contents)
  1191. {
  1192.     if (contents.IsRecord())
  1193.     {
  1194.         FW_CDesc value;
  1195.         long propertyCount = contents.GetItemCount();
  1196.         for (long index = 1; index <= propertyCount; index++)
  1197.         {
  1198.             ODDescType whichProperty;
  1199.             value.Clear();
  1200.             contents.GetDescFromList(index, whichProperty, value);
  1201.             SetProperty(ev, part, value, whichProperty);
  1202.         }
  1203.     }
  1204.     else
  1205.         FW_THROW(FW_XException(errAEEventNotHandled));
  1206. }
  1207.  
  1208. //---------------------------------------------------------------------------------------
  1209. //    FW_MScriptable::SetProperties
  1210. //---------------------------------------------------------------------------------------
  1211.  
  1212. void FW_MScriptable::SetProperties(Environment* ev,
  1213.                                 FW_CPart* part,
  1214.                                 const FW_CAppleEvent& event)
  1215. {
  1216.     
  1217.     if (event.HasDataKey(keyAEPropData))
  1218.     {
  1219.         FW_CDesc propertyList;
  1220.         
  1221.         event.GetDataByDesc(propertyList, keyAEPropData, typeAERecord);
  1222.         SetProperties(ev, part, propertyList);
  1223.     }
  1224. }
  1225.  
  1226. //---------------------------------------------------------------------------------------
  1227. //    FW_MScriptable::RestoreProperty
  1228. //---------------------------------------------------------------------------------------
  1229.  
  1230. void FW_MScriptable::RestoreProperty(Environment* ev,
  1231.                                     FW_CPart* part,
  1232.                                     FW_CDesc& propertyValue,
  1233.                                     ODDescType whichProperty)
  1234. {
  1235.     this->SetProperty(ev, part, propertyValue, whichProperty);
  1236. }
  1237.                                         
  1238. //---------------------------------------------------------------------------------------
  1239. //    FW_MScriptable::GetUndoSetPropertyStrings
  1240. //---------------------------------------------------------------------------------------
  1241.  
  1242. void FW_MScriptable::GetUndoStrings(Environment* ev,
  1243.                                     FW_CPart* part,
  1244.                                     ODDescType whichProperty,
  1245.                                     FW_CString& undoString,
  1246.                                     FW_CString& redoString) const
  1247. {
  1248. FW_UNUSED(part);
  1249. FW_UNUSED(whichProperty);
  1250.         // "Undo Set Property" and "Redo Set Property"
  1251.         // Subclasses can optionally override and provide more descriptive strings
  1252.     ::FW_PrivLoadUndoStrings(ev, FW_kUndoSetPropertyMsg, undoString, redoString);
  1253. }
  1254.  
  1255. //---------------------------------------------------------------------------------------
  1256. //    FW_MScriptable::AddDependent
  1257. //---------------------------------------------------------------------------------------
  1258.  
  1259. void FW_MScriptable::AddDependent(FW_MScriptable* dependent)
  1260. {
  1261.     if (!fDependents)
  1262.         fDependents = FW_NEW(FW_TOrderedCollection<FW_MScriptable>, ());
  1263.     fDependents->AddFirst(dependent);
  1264. }
  1265.  
  1266. //---------------------------------------------------------------------------------------
  1267. //    FW_MScriptable::RemoveDependent
  1268. //---------------------------------------------------------------------------------------
  1269.  
  1270. void FW_MScriptable::RemoveDependent(FW_MScriptable* dependent)
  1271. {
  1272.     FW_ASSERT(fDependents);
  1273.     fDependents->Remove(dependent);
  1274. }
  1275.  
  1276. //---------------------------------------------------------------------------------------
  1277. //    FW_MScriptable::HandlePrimaryDeleted
  1278. //---------------------------------------------------------------------------------------
  1279.  
  1280. void FW_MScriptable::HandlePrimaryDeleted(FW_MScriptable* primary)
  1281. {
  1282. FW_UNUSED(primary);
  1283.     FW_DEBUG_MESSAGE("FW_MScriptable::HandlePrimaryDeleted should be handled by a derived class");
  1284. }
  1285.  
  1286. //========================================================================================
  1287. //    class FW_CElementIterator
  1288. //========================================================================================
  1289.  
  1290. //---------------------------------------------------------------------------------------
  1291. //    FW_CElementIterator::FW_CElementIterator
  1292. //---------------------------------------------------------------------------------------
  1293.  
  1294. FW_CElementIterator::FW_CElementIterator()
  1295. {
  1296.     FW_END_CONSTRUCTOR
  1297. }
  1298.  
  1299. //---------------------------------------------------------------------------------------
  1300. //    FW_CElementIterator::~FW_CElementIterator
  1301. //---------------------------------------------------------------------------------------
  1302.  
  1303. FW_CElementIterator::~FW_CElementIterator()
  1304. {
  1305.     FW_START_DESTRUCTOR
  1306. }
  1307.