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 / OpenDoc Development / Debugging Support / OpenDoc Source Code / Binding / BindngH.cpp < prev    next >
Encoding:
Text File  |  1996-04-22  |  30.7 KB  |  1,040 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        BindngH.cpp
  3.  
  4.     Contains:    C++ Implementation for Binding Helper class.
  5.  
  6.     Owned by:    Caia Grisar
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <3>     1/26/96    VL        1170098: Removed call to IsEditorLoaded
  13.                                     because it unnecessarily loads and unloads
  14.                                     the part library.
  15.          <2>      1/8/96    CG        1299331 1.0.1: Substitution warning dlg
  16.                                     nolonger displayed in background.
  17.         <48>    10/24/95    TJ        Included TempIter.h
  18.         <47>    10/23/95    CG        #1294762 GM: Out-of-memory on close forces
  19.                                     close without saving changes
  20.                                     #1295082 GM: Crash switching editor if lib
  21.                                     can't load
  22.                                     #1295186 GM: Failure in InitPartFromStorage
  23.                                     doesn't abort editor switch
  24.                                     #1295105 GM: Fail during Editor Change can
  25.                                     leave Preferred Kind set incorrectly
  26.         <46>     10/9/95    CC        1291425: Fixed logic in
  27.                                     ChangeKindAndEditor.
  28.         <45>     10/4/95    CG        #1284324 GM: PartInfo dialog may display
  29.                                     wrong editor.
  30.         <44>     9/12/95    DM        1280020 FB1 part trans dlg mem leaks
  31.         <43>      9/8/95    CG        #1283252 FB1: Allocate memory for Editor
  32.                                     string in NoPart case.
  33.         <42>      9/8/95    TÇ        1281096 FB2:Many constants in ODTypesB
  34.                                     without kOD prefix!
  35.         <41>      9/7/95    CG        #1262630 FB2: Bad warning when NoPart
  36.                                     rebinds.
  37.         <40>     8/30/95    CG        #1244563    FB1:Missing editor needs
  38.                                     explanatory alert
  39.                                     #1215054    FB: Too many substitute editor
  40.                                     dialog
  41.                                     #1276989    FB:Leakage from SU::GetType calls
  42.         <39>     8/12/95    TÇ        1276807 Opt./Bug: use StdTypIO routines for
  43.                                     portable streaming & smaller footprint,
  44.                                     1276810 Binding writes to storage without
  45.                                     checking permissions!
  46.         <38>      8/8/95    jpa        Fixed ChooseDirectEditorForKind, which was
  47.                                     returning disposed pointers. [1275499]
  48.         <37>     6/21/95    CC        1260937: BB: ODTypeListIterator must return
  49.                                     copies of ODType values.
  50.         <36>     6/19/95    VL        1170098: Set return result for
  51.                                     GetPreferredEditorForPart to kODNULL if the
  52.                                     operation fails.
  53.         <35>     6/16/95    EL        #1254926: Don't return an editor that does
  54.                                     not exists.
  55.         <34>     6/16/95    CC        1259719: Added ChangeEditor and
  56.                                     ChangeKindAndEditor.
  57.         <33>     5/18/95    CG        #1249728 BB: BindingH.cpp needs to call
  58.                                     StdTypIO routines for ISOStr
  59.                                     #1249263 BB: BndNSUtl.cpp does not compile
  60.                                     standalone.
  61.         <32>     4/27/95    CC        1243813: Removed ShowAlert and
  62.                                     BindingDialogFilter; replaced by ShowAlert
  63.                                     in DlogUtil.
  64.         <31>     4/26/95    CG        1210975 BB: 5$ Bugs need to be evaluatedand
  65.                                     removed from Binding.
  66.         <30>     4/26/95    CG        1210975 BB: 5$ Bugs need to be evaluated
  67.                                     and removed from Binding.
  68.         <29>     4/13/95    CG        Removed obsolete #include.
  69.         <28>     3/28/95    CG        #1211901 BB:  Binding methods check for
  70.                                     null storage unit.
  71.         <27>     2/16/95    CG        #1213926 BB:binding respects preferred
  72.                                     kinds.  #1210975 BB: 5$ fixes.
  73.         <26>     2/14/95    TJ        Fixed copyright date.
  74.         <25>     2/14/95    jpa        Fixed GetContainerSuite to always return
  75.                                     NULL on failure, and to use the
  76.                                     SysPrefContainerSuites namespace. [1205141]
  77.         <24>      2/2/95    CG        #1195019:  ValueNameSpace entries are now
  78.                                     copied in and out instead of pointers being
  79.                                     passed around.
  80.         <23>     1/25/95    jpa        Fixed no-prefs crashes [1214750]
  81.         <22>     1/24/95    CG        In GetContainerSuite now check return value
  82.                                     of ValueNameSpaceGetEntry instead of return
  83.                                     parameter.  broke last build.
  84.         <21>     1/23/95    CG        #1195019: ValueNameSpace methods now take
  85.                                     ODByteArray parameter instead of ODPtr.
  86.         <20>     1/13/95    RR        Removed include of ODTypesM.xh
  87.         <19>     1/12/95    jpa        Don't use obsolete Toolbox names. [1211211]
  88.         <18>     1/10/95    CG        #1201731:  BB: Now get NoPart if a part
  89.                                     can't be loaded because of an error.
  90.         <17>    12/20/94    VL        1195012: Make Storage calls be
  91.                                     marshallable.
  92.         <16>    12/13/94    CG        #1193522: Warning dialog displayed if
  93.                                     automatic binding has occurred.
  94.         <15>     10/7/94    CG        #1184728:  Broke NoPart with last fix!
  95.         <14>     10/7/94    CG        #1184728: Binding to another part that
  96.                                     supports the same kind when original editor
  97.                                     not found now works.
  98.         <13>      9/9/94    CG        1182933: changed NoPart editor id.
  99.         <12>      9/9/94    jpa        Fixed IsEditorLoaded to call new
  100.                                     ODClassExists rather than use SOM; this fix
  101.                                     re-enables debugging of parts. [1182105]
  102.         <11>     8/24/94    CG        #1181622: Updated file ownership.
  103.         <10>     8/17/94    CG        #1181440 The View and EditorKinds name
  104.                                     spaces were changed to be of type
  105.                                     ODObjectNameSpace.
  106.          <9>     7/29/94    CG        NameSpace API changes.
  107.          <8>     7/26/94    jpa        Don't call InitObject from InitBinding.
  108.          <7>      7/1/94    CG        Changes to IsEditorLoaded.
  109.          <6>      7/1/94    CG        Added som calls to IsEditorLoaded.
  110.          <5>     6/28/94    VL        Use Translt.cpp.
  111.          <4>     6/27/94    CG        Moved IsEditorLoaded here from Prefs.
  112.                                     Removed fEv.
  113.          <3>     6/23/94    eeh        oops....include EditrSet.h
  114.          <2>     6/23/94    eeh        remove ODEditorSetIterator and EditorSet
  115.          <1>     6/20/94    CG        first checked in
  116.  
  117.     To Do:
  118.     In Progress:
  119.         
  120. */
  121.  
  122. #ifndef __ERRORS__
  123. #include <Errors.h>
  124. #endif
  125.  
  126. #ifndef _BINDNGH_
  127. #include "BindngH.h"
  128. #endif
  129.  
  130. #ifndef _EDITRSET_
  131. #include "EditrSet.h"
  132. #endif
  133.  
  134. #ifndef _ODMEMORY_
  135. #include "ODMemory.h"
  136. #endif
  137.  
  138. #ifndef SOM_ODStorageUnit_xh
  139. #include "StorageU.xh"
  140. #endif
  141.  
  142. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  143. #include "StdDefs.xh"
  144. #endif
  145.  
  146. #ifndef SOM_Module_OpenDoc_StdProps_defined
  147. #include "StdProps.xh"
  148. #endif
  149.  
  150. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  151. #include "StdTypes.xh"
  152. #endif
  153.  
  154. #ifndef _ODUTILS_
  155. #include "ODUtils.h"
  156. #endif
  157.  
  158. #ifndef SOM_ODTranslation_xh
  159. #include "Translt.xh"
  160. #endif
  161.  
  162. #ifndef _ODSESSN_
  163. #include "ODSessn.xh"
  164. #endif
  165.  
  166. #ifndef SOM_ODValueNameSpace_xh
  167. #include "ValueNS.xh"
  168. #endif
  169.  
  170. #ifndef SOM_ODObjectNameSpace_xh
  171. #include "ObjectNS.xh"
  172. #endif
  173.  
  174. #ifndef _ORDCOLL_
  175. #include "OrdColl.h"
  176. #endif
  177.  
  178. #ifndef SOM_ODNameSpaceManager_xh
  179. #include "NmSpcMg.xh"
  180. #endif
  181.  
  182. #ifndef _EXCEPT_
  183. #include "Except.h"
  184. #endif
  185.  
  186. #ifndef _PASCLSTR_
  187. #include "PasclStr.h"
  188. #endif
  189.  
  190. #ifndef _ISOSTR_
  191. #include "ISOStr.h"
  192. #endif
  193.  
  194. #ifndef SOM_Apple_NoPart_xh
  195. #include <NoPart.xh>
  196. #endif
  197.  
  198. #ifndef SOM_ODTypeList_xh
  199. #include <TypeList.xh>
  200. #endif
  201.  
  202. #ifndef SOM_ODTypeListIterator_xh
  203. #include <TypLsItr.xh>
  204. #endif
  205.  
  206. #ifndef _BNDNSUTL_
  207. #include "BndNSUtl.h"
  208. #endif
  209.  
  210. #ifndef _ODNEWOBJ_
  211. #include <ODNewObj.h>
  212. #endif
  213.  
  214. #ifndef __DIALOGS__
  215. #include <Dialogs.h>
  216. #endif
  217.  
  218. #ifndef SOM_ODWindowState_xh
  219. #include <WinStat.xh>
  220. #endif
  221.  
  222. #ifndef SOM_ODWindow_xh
  223. #include <Window.xh>
  224. #endif
  225.  
  226. #ifndef _USERSRCM_
  227. #include <UseRsrcM.h>
  228. #endif
  229.  
  230. #ifndef _STORUTIL_
  231. #include <StorUtil.h>
  232. #endif
  233.  
  234. #ifndef _BNDNGDEF_
  235. #include "BndngDef.h"
  236. #endif
  237.  
  238. #ifndef SOM_ODFrame_xh
  239. #include <Frame.xh>
  240. #endif
  241.  
  242. #ifndef _NMSPCUTL_
  243. #include <NmSpcUtl.h>
  244. #endif
  245.  
  246. #ifndef SOM_ODDispatcher_xh
  247. #include <Disptch.xh>
  248. #endif
  249.  
  250. #ifndef _DLOGUTIL_
  251. #include <DlogUtil.h>
  252. #endif
  253.  
  254. #ifndef SOM_ODPartWrapper_xh
  255. #include <PartWrap.xh>
  256. #endif
  257.  
  258. #ifndef _DOCUTILS_
  259. #include <DocUtils.h>
  260. #endif
  261.  
  262. #ifndef _STDTYPIO_
  263. #include <StdTypIO.h>
  264. #endif
  265.  
  266. #ifndef _INFOUTIL_
  267. #include "InfoUtil.h"
  268. #endif
  269.  
  270. #ifndef _TEMPOBJ_
  271. #include <TempObj.h>
  272. #endif
  273.  
  274. #ifndef _TEMPITER_
  275. #include "TempIter.h"
  276. #endif
  277.  
  278. #include <somcls.xh>
  279. #include <somcm.xh>
  280.  
  281. #pragma segment Binding
  282.  
  283.  
  284. //==============================================================================
  285. // Constants
  286. //==============================================================================
  287.  
  288. #define kEditorSubstitutionList "EditorSubstitutions"
  289.  
  290. //=========================================================================
  291. // Globals
  292. //=========================================================================
  293.  
  294. //static ODSession* gSession;    // For use in Dialog Filter Proc
  295.  
  296. //=========================================================================
  297. // Function Prototypes
  298. //=========================================================================
  299.  
  300. pascal Boolean BindingDialogFilter(DialogPtr dialog,
  301.                               EventRecord* event,
  302.                               short* itemHit);
  303. ODStatic ODIconFamily GetRootPartIconFamily( Environment*    ev, 
  304.                                         ODSession* session );
  305. ODStatic void ODPascal BindingNMResponse( NMRecPtr theNMRecPtr );
  306.  
  307. ODStatic StringPtr BuildNotificationString(ODSShort strResourceID, Str255 catString, Str255 editorString);
  308.  
  309. //==============================================================================
  310. // Static functions
  311. //==============================================================================
  312.  
  313. ODStatic void ODPascal BindingNMResponse( NMRecPtr theNMRecPtr )
  314. {
  315.     OSErr error = NMRemove(theNMRecPtr);
  316. }
  317.  
  318. ODStatic ODIconFamily GetRootPartIconFamily( Environment*    ev, ODSession* session )
  319. {
  320.     static ODIconFamily sIcon = kODNULL;
  321.     if( !sIcon ) {
  322.         TempODWindow odWindow = session->GetWindowState(ev)->AcquireFrontRootWindow(ev);
  323.         ODFrame* rootFrame = odWindow ? odWindow->GetRootFrame(ev) : kODNULL;
  324.         sIcon = ODGetIconFamily(ev, rootFrame);
  325.     }
  326.     return sIcon;
  327. }
  328.  
  329. //------------------------------------------------------------------------------
  330. // BuildNotificationString
  331. //------------------------------------------------------------------------------
  332.  
  333. ODStatic StringPtr BuildNotificationString(ODSShort strResourceID, Str255 catString, Str255 editorString)
  334. {
  335.     Str255 msgStr;
  336.  
  337.     StringPtr result = kODNULL;
  338.     
  339.     ODSLong savedRefNum;
  340.     BeginUsingLibraryResources(savedRefNum);
  341.  
  342.     ReplaceIntoString(strResourceID, catString, editorString, msgStr);
  343.  
  344.     if ( msgStr[0] > 0 )
  345.     {
  346.         ODULong ptrSize = msgStr[0]+1;
  347.         result = (StringPtr) ODNewPtr(ptrSize);
  348.         if ( result )
  349.             ODBlockMove((ODPtr) &msgStr, (ODPtr) result, ptrSize);
  350.     }
  351.     
  352.     EndUsingLibraryResources(savedRefNum);
  353.     
  354.     return result;
  355. }
  356.  
  357. //==============================================================================
  358. // Class Binding
  359. //==============================================================================
  360.  
  361. //------------------------------------------------------------------------------
  362. // Binding::Binding
  363. //------------------------------------------------------------------------------
  364. Binding::Binding()
  365. {
  366.     fSession            = (ODSession*) kODNULL;
  367. }
  368.  
  369. //------------------------------------------------------------------------------
  370. // Binding::~Binding
  371. //------------------------------------------------------------------------------
  372. Binding::~Binding()
  373. {
  374.     Environment* ev = somGetGlobalEnvironment ();
  375.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  376.     nsm->DeleteNameSpace(ev, fSubstitutionList);
  377.     if ( fNMResponseUPP != kODNULL )
  378.         DisposeRoutineDescriptor(fNMResponseUPP);
  379.  
  380.     if ( fNMRecPtr )
  381.         ODDisposePtr((ODPtr) fNMRecPtr->nmStr);
  382.     ODDisposePtr(fNMRecPtr);
  383. }
  384.  
  385. //------------------------------------------------------------------------------
  386. // Binding::InitBinding
  387. //------------------------------------------------------------------------------
  388. void Binding::InitBinding(ODSession* session )
  389. {
  390.     Environment* ev = somGetGlobalEnvironment ();
  391.     
  392.     fSession = session;
  393.     //gSession = fSession;
  394.  
  395.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  396.  
  397.     fSubstitutionList = (ODValueNameSpace*)nsm->CreateNameSpace(ev, 
  398.         (ODISOStr)kEditorSubstitutionList, kODNULL, 1, kODNSDataTypeODValue);
  399.  
  400.     fNMResponseUPP = NewNMProc(BindingNMResponse);
  401.     fNMRecPtr = (NMRecPtr) ODNewPtr(sizeof(NMRec));
  402.     THROW_IF_NULL(fNMRecPtr);
  403.     fNMRecPtr->nmStr = kODNULL;    
  404. }
  405.  
  406. //------------------------------------------------------------------------------
  407. // Binding::Purge
  408. //------------------------------------------------------------------------------
  409. ODSize Binding::Purge(ODSize size)
  410. {
  411. ODUnused(size);
  412.     // The only memory that Binding has to purge is owned by NmSpcMgr and
  413.     // is being purge from there.
  414.     return 0;
  415. }
  416.  
  417.  
  418.     //---------------------------------
  419.     // Direct editor bindings
  420.  
  421. //------------------------------------------------------------------------------
  422. // Binding::ChooseEditorForPart
  423. //------------------------------------------------------------------------------
  424. ODEditor Binding::ChooseEditorForPart(ODStorageUnit* thePartSU, ODType newKind )
  425. {
  426.     ODEditor theChosenEditor = (ODEditor)kODNULL; ODVolatile( theChosenEditor );
  427.     ODBoolean noPreferredEditorProp = kODFalse;
  428.     
  429.     TRY
  430.         if (thePartSU)
  431.             theChosenEditor = GetPreferredEditorForPart(thePartSU, &noPreferredEditorProp);
  432.         if (theChosenEditor) 
  433.             return theChosenEditor;
  434.     
  435.             theChosenEditor = ChooseDirectEditorForPart(thePartSU, newKind);
  436.     
  437. /*
  438.         // NO AUTOMATIC TRANSLATION in v1
  439.         
  440.         if (!theChosenEditor && AutomaticTranslation()) 
  441.             theChosenEditor = TranslateAndChooseEditorForPart(thePartSU);
  442. */    
  443.     
  444.         if (!theChosenEditor) 
  445.         {
  446.             theChosenEditor = (ODEditor) ODNewPtrClear( 
  447.                                     sizeof(kODBlackBoxHandlerOfLastResort) + 1);
  448.             ODBlockMove( kODBlackBoxHandlerOfLastResort,  
  449.                 theChosenEditor, sizeof(kODBlackBoxHandlerOfLastResort) + 1 );
  450.         }
  451.         else
  452.         {
  453.             Environment* ev = somGetGlobalEnvironment ();
  454.     
  455.             if (thePartSU)
  456.             {
  457.                 ODSetISOStrProp(ev, thePartSU, kODPropPreferredEditor, 
  458.                                                         kODEditor, theChosenEditor);
  459.                 if (!noPreferredEditorProp)
  460.                     this->SubstitutionWarning(theChosenEditor, thePartSU);
  461.             }
  462.         }
  463.         
  464.     CATCH_ALL
  465.         ODDeleteObject( theChosenEditor );
  466.         RERAISE;
  467.     ENDTRY
  468.  
  469.     return theChosenEditor;
  470. }
  471.  
  472. //------------------------------------------------------------------------------
  473. // Binding::TranslateAndChooseEditorForPart
  474. //------------------------------------------------------------------------------
  475.  
  476. ODEditor Binding::TranslateAndChooseEditorForPart(ODStorageUnit* thePartSU)
  477. {
  478. ODUnused(thePartSU);
  479.     return (ODEditor)kODNULL;
  480. }    
  481.  
  482. //------------------------------------------------------------------------------
  483. // Binding::ChooseDirectEditorForPart
  484. //------------------------------------------------------------------------------
  485.  
  486. ODEditor Binding::ChooseDirectEditorForPart(ODStorageUnit* thePartSU, 
  487.                                                                 ODType newKind )
  488. {
  489. // NOTE: This method does NOT check the preferred editor of the given part
  490.  
  491.     Environment* ev = somGetGlobalEnvironment ();
  492.     ODEditor theEditor = kODNULL;
  493.     
  494.     if (thePartSU)
  495.     {
  496.             // Check for preferredKind property
  497.         ODType preferredKind;
  498.         if ((preferredKind = ODGetISOStrProp(ev, thePartSU, 
  499.                                 kODPropPreferredKind, kODISOStr, kODNULL, kODNULL))
  500.             != kODNULL)
  501.         {            
  502.             theEditor = ChooseDirectEditorForKind(preferredKind,thePartSU);
  503.             ODDisposePtr(preferredKind);
  504.         }
  505.         
  506.         if (theEditor) 
  507.                 return theEditor;
  508.             // Attempt to bind using the content values in their fidelity order
  509.         for (ODValueIndex valueIndex = 1;
  510.             thePartSU->Exists(ev, kODPropContents,(ODValueType)kODNULL,valueIndex)
  511.                                                           && (theEditor == kODNULL);
  512.             valueIndex++)
  513.         {
  514.             thePartSU->Focus(ev, kODPropContents,kODPosSame,(ODValueType)kODNULL,
  515.                                                              valueIndex,kODPosSame);
  516.             TempODValueType type = thePartSU->GetType(ev);
  517.             theEditor = ChooseDirectEditorForKind(type,thePartSU);
  518.         }
  519.         if (theEditor) 
  520.                 return theEditor;
  521.     }
  522.     
  523.     theEditor = ChooseDirectEditorForKind(newKind,thePartSU);
  524.     
  525.     if (theEditor) 
  526.         return theEditor;
  527.     else
  528.         return kODNULL;
  529. }
  530.     
  531. //------------------------------------------------------------------------------
  532. // Binding::ChooseDirectEditorForKind
  533. //------------------------------------------------------------------------------
  534.  
  535. ODEditor Binding::ChooseDirectEditorForKind(ODType aKind, 
  536.                                                        ODStorageUnit* thePartSU)
  537. {
  538.     ODEditor theEditor = kODNULL;    ODVolatile( theEditor );
  539.     EditorSet* editorSet = kODNULL; ODVolatile( editorSet );
  540.     Environment* ev = somGetGlobalEnvironment ();
  541.  
  542.     if (!aKind )
  543.         return theEditor;
  544.         
  545.     TRY
  546.         ODNameSpaceManager* theNameSpaceManager = fSession->GetNameSpaceManager(ev);
  547.         
  548.         if (thePartSU)
  549.         {
  550.             EditorSet* theEditorSet = GetAllRestrictedEditorsForKind(thePartSU->
  551.                                                                 GetDraft(ev),aKind);
  552.             if (theEditorSet != kODNULL) 
  553.             {
  554.                 theEditor = AlphaNumChooseEditor(theEditorSet);
  555.                 SetSysPrefEditorForKind(theNameSpaceManager, aKind,theEditor);
  556.                 return theEditor;
  557.             }
  558.         }
  559.         
  560.         theEditor = GetSysPrefEditorForKind(theNameSpaceManager, aKind);
  561.         if (theEditor && EditorExists(theEditor)) 
  562.             return theEditor;
  563.         else
  564.         {
  565.             ODDisposePtr( theEditor );
  566.             theEditor = kODNULL;
  567.         }
  568.     
  569.         ODTypeList* categories = GetCategoriesOfKind(theNameSpaceManager, aKind);
  570.         if (categories)
  571.         {
  572.             ODBoolean     editorFound = kODFalse;
  573.             for (TempODTypeListIterator catItr(ev,categories);
  574.                 catItr.Current() && !editorFound;
  575.                 catItr.Next())
  576.             {
  577.                 theEditor = GetSysPrefEditorForCategory(theNameSpaceManager,
  578.                                                                          catItr.Current());
  579.                 editorFound = (theEditor &&
  580.                     EditorSupportsKind(theNameSpaceManager, theEditor,aKind) &&
  581.                     EditorExists(theEditor));
  582.             }
  583.             if (editorFound)
  584.                 return theEditor;
  585.             else
  586.             {
  587.                 ODDisposePtr( theEditor );
  588.                 theEditor = kODNULL;
  589.             }
  590.         }
  591.     
  592.         editorSet = new EditorSet;
  593.         editorSet->InitEditorSet();
  594.         
  595.         if (GetAllEditorsForKind( theNameSpaceManager, aKind, editorSet )) 
  596.         {
  597.             theEditor = AlphaNumChooseEditor(editorSet);
  598.             if (EditorExists(theEditor)) {
  599.                 SetSysPrefEditorForKind(theNameSpaceManager, aKind,theEditor);
  600.                 theEditor = ODISOStrFromCStr(theEditor);    // Duplicate the string!
  601.             } else
  602.                 theEditor = kODNULL;
  603.         }
  604.         
  605.         ODDeleteObject( editorSet );
  606.     CATCH_ALL
  607.         ODDeleteObject( editorSet );
  608.         ODDisposePtr( theEditor );
  609.         RERAISE;
  610.     ENDTRY
  611.     
  612.     return theEditor;
  613. }
  614.  
  615.     //---------------------------------
  616.     // Editor related utility methods
  617.  
  618. //------------------------------------------------------------------------------
  619. // Binding::EditorExists
  620. //
  621. //     lookup editor in editorkinds namespace and return kODTrue if it exists
  622. //------------------------------------------------------------------------------
  623.  
  624. ODBoolean Binding::EditorExists(ODEditor editor)
  625. {
  626.     Environment* ev = somGetGlobalEnvironment ();
  627.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  628.     
  629.     /*  Try twice to find the editor. If the first search fails, re-synch the
  630.         name-space (by hitting the disk and searching all available "Editors"
  631.         folders) and try again. If the second search fails, give up. --jpa */
  632.     
  633.     /*    ????? This could be slow if we are called many times in a row with
  634.         genuinely nonexistent editors. If this turns out to be a real problem,
  635.         one could keep around the time of last synching, and not synch more than
  636.         once every five seconds. */
  637.     
  638.     ODBoolean synched = kODFalse;
  639.     for( ;; ) {
  640.         ODNameSpace* editorkindsNameSpace = 
  641.             fSession->GetNameSpaceManager(ev)->HasNameSpace( ev, kODEditorKinds );
  642.         
  643.         if ( editorkindsNameSpace
  644.                 && editorkindsNameSpace->Exists(ev, (ODISOStr)editor) )
  645.             return kODTrue;
  646.         
  647.         if( !synched ) {
  648.             synched = kODTrue;
  649.             nsm->SynchNSTable(ev);
  650.             continue;
  651.         } else
  652.             return kODFalse;
  653.     }
  654. }
  655.         
  656. //------------------------------------------------------------------------------
  657. // Binding::IsEditorLoaded
  658. //------------------------------------------------------------------------------
  659. ODBoolean Binding::IsEditorLoaded(ODEditor editor)
  660. {
  661.     return ODClassExists(editor);
  662. }
  663.  
  664. //------------------------------------------------------------------------------
  665. // Binding::GetPreferredEditorForPart
  666. //------------------------------------------------------------------------------
  667. ODEditor Binding::GetPreferredEditorForPart(ODStorageUnit* thePartSU, 
  668.                                               ODBoolean* noPreferredEditorProp)
  669. {
  670.     // read preferred editor from thePartSU
  671.     Environment* ev = somGetGlobalEnvironment ();
  672.     ODEditor preferredEditor = kODNULL;
  673.     if (thePartSU->Exists(ev, kODPropPreferredEditor,kODEditor,0))
  674.     {
  675.         ODULong size;
  676.         preferredEditor = ODGetISOStrProp(ev, thePartSU, 
  677.                             kODPropPreferredEditor, kODEditor, kODNULL, &size);
  678.         if (preferredEditor)
  679.         {
  680.             if (EditorExists(preferredEditor))
  681.             {
  682.                 *noPreferredEditorProp = kODFalse;
  683.             } else {
  684.                 ODDisposePtr(preferredEditor);
  685.                 preferredEditor = kODNULL;
  686.                     // the prop exists in SU but is empty
  687.                 if (size == 0)
  688.                     *noPreferredEditorProp = kODTrue;
  689.             }
  690.         }
  691.     }
  692.     else 
  693.     {
  694.         *noPreferredEditorProp = kODTrue;
  695.         if (HAS_WRITE_ACCESS(thePartSU->GetDraft(ev)->GetPermissions(ev)))
  696.             ODSUAddPropValue(ev, thePartSU, kODPropPreferredEditor, kODEditor);
  697.     }
  698.     return preferredEditor;
  699. }
  700.  
  701.  
  702. //------------------------------------------------------------------------------
  703. // Binding::GetKindsSupported
  704. //
  705. //     lookup editor in editorkinds namespace and return kinds supported
  706. //------------------------------------------------------------------------------
  707.  
  708. ODTypeList* Binding::GetKindsSupported(ODEditor editor)
  709. {
  710.     ODTypeList*    kindsList = kODNULL;
  711.     Environment* ev = somGetGlobalEnvironment ();
  712.     
  713.         // get the editorkinds namespace
  714.     ODObjectNameSpace* editorkindsNameSpace = 
  715.         (ODObjectNameSpace*)fSession->GetNameSpaceManager(ev)->HasNameSpace( ev,
  716.                                                                kODEditorKinds );
  717.     
  718.     if (editorkindsNameSpace)
  719.     {
  720.             // Lookup the kinds list by editor class ID
  721.         if (editorkindsNameSpace->GetEntry( ev, (ODISOStr)editor, 
  722.                                     (ODObject**)&kindsList ))
  723.             return kindsList;
  724.         else
  725.             return kODNULL;
  726.     }
  727.     return kindsList;
  728. }
  729.  
  730. //------------------------------------------------------------------------------
  731. // Binding::AlphaNumChooseEditor
  732. //------------------------------------------------------------------------------
  733.  
  734. ODEditor Binding::AlphaNumChooseEditor(EditorSet* editorSet)
  735. {
  736.     ODEditor bestEditor = (ODEditor)kODBlackBoxHandlerOfLastResort;
  737.     
  738.     EditorSetIterator* eit = editorSet->CreateIterator();
  739.     
  740.     for (ODEditor editor = eit->First();
  741.         eit->IsNotComplete();
  742.         editor = eit->Next())
  743.     {
  744.         bestEditor = AlphaNumChooseAnEditorFromTwo(editor,bestEditor);
  745.     }
  746.     
  747.     ODDeleteObject( eit );
  748.     return bestEditor;
  749. }
  750.  
  751. //------------------------------------------------------------------------------
  752. // Binding::AlphaNumChooseAnEditorFromTwo
  753. //------------------------------------------------------------------------------
  754.  
  755. ODEditor Binding::AlphaNumChooseAnEditorFromTwo(ODEditor e1, ODEditor e2)
  756. {
  757.     Environment* ev = somGetGlobalEnvironment ();
  758.     ODObjectNameSpace*    theViewerNameSpace = ViewerNameSpace();
  759.     ODObject*    ignore;
  760.     ODBoolean e1IsViewer = kODFalse;
  761.     ODBoolean e2IsViewer = kODFalse;
  762.  
  763.     if (theViewerNameSpace)
  764.     {
  765.         e1IsViewer = theViewerNameSpace->GetEntry(ev, (ODISOStr)e1, &ignore);
  766.         e2IsViewer = theViewerNameSpace->GetEntry(ev, (ODISOStr)e2, &ignore);
  767.     }
  768.     
  769.     if (!e1IsViewer && e2IsViewer)
  770.         return e1;
  771.     else if (!e2IsViewer && e1IsViewer)
  772.         return e2;
  773.     else if (kODTrue) /*(strcmp((char*)e1,(char*)e2)>=0)*/
  774.         return e1;
  775.     else
  776.         return e2;
  777. }
  778.         
  779. //------------------------------------------------------------------------------
  780. // Binding::DraftRestrictsEditors
  781. //------------------------------------------------------------------------------
  782.  
  783. ODBoolean Binding::DraftRestrictsEditors(ODDraft* draft)
  784. {
  785. ODUnused(draft);
  786.     // return whether or not restrictedEditors property exists
  787.     return kODFalse;
  788. }
  789.  
  790. //------------------------------------------------------------------------------
  791. // Binding::GetAllRestrictedEditorsForKind
  792. //------------------------------------------------------------------------------
  793.  
  794. EditorSet* Binding::GetAllRestrictedEditorsForKind(ODDraft* draft, ODType kind)
  795. {
  796. ODUnused(draft);
  797. ODUnused(kind);
  798.     // read and return restrictedEditors property of draftProperties
  799.     return kODNULL;
  800. }
  801.         
  802.     //---------------------------------
  803.     // Category and kind mappings
  804.  
  805. //------------------------------------------------------------------------------
  806. // Binding::ViewerNameSpace
  807. //------------------------------------------------------------------------------
  808. ODObjectNameSpace*    Binding::ViewerNameSpace()
  809. {
  810.     Environment* ev = somGetGlobalEnvironment ();
  811.     return (ODObjectNameSpace*)fSession->GetNameSpaceManager(ev)->HasNameSpace( 
  812.                                                                 ev, kODViewer );
  813. }
  814.  
  815.  
  816. //------------------------------------------------------------------------------
  817. // Binding::GetContainerSuite
  818. //------------------------------------------------------------------------------
  819.  
  820. ODContainerSuite Binding::GetContainerSuite(ODContainerType containerType)
  821. {
  822.     /* Two things can happen here. If containerType is the name of an actual
  823.         container suite, we look it up in the ContainerSuite namespace and
  824.         return the classname. But containerType might also be a constant
  825.         indicating a type of default container suite (e.g. kODDefaultFileContainer)
  826.         in which case we have to first look it up in the system-preferred
  827.         ContainerSuite namespace to get the real container suite name, then
  828.         do the lookup as above to get the classname. */
  829.     
  830.     ODContainerSuite     theContainerSuite;
  831.     
  832.     // First look it up in the ContainerSuite namespace:
  833.     theContainerSuite = ValueNameSpaceGetString(fSession,kODContainerSuite,containerType);
  834.     if( !theContainerSuite ) {
  835.         ODContainerSuite realType;
  836.         ODBoolean isDefault = kODFalse;
  837.         // Not found, look it up in the System-preferred Container Suites namespace:
  838.         realType = ValueNameSpaceGetString(fSession,kODSysPrefContainerSuites,containerType);
  839.         if( !realType ) {
  840.             // Not found there either, check some hardcoded defaults:
  841.             isDefault = kODTrue;
  842.             if( ODISOStrEqual(containerType,kODDefaultMemoryContainer) )
  843.                 realType = kODBentoMemoryContainer;
  844.             else if( ODISOStrEqual(containerType,kODDefaultFileContainer) )
  845.                 realType = kODBentoFileContainer;
  846.         }
  847.         if( realType ) {
  848.             // Now that we have a real containerType, look it up in ContainerSuite:
  849.             theContainerSuite = ValueNameSpaceGetString(fSession,kODContainerSuite,realType);
  850.             if( !isDefault )
  851.                 ODDisposePtr(realType);
  852.         }
  853.     }
  854.     return theContainerSuite;
  855. }
  856.  
  857. //------------------------------------------------------------------------------
  858. // Binding::SubstitutionWarning 
  859. //------------------------------------------------------------------------------
  860.  
  861. void Binding::SubstitutionWarning(ODEditor theEditor, ODStorageUnit* thePartSU)
  862. {
  863.     Environment* ev = somGetGlobalEnvironment ();
  864.  
  865.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  866.     TempODIText category = ODGetCatFromPartSU( ev, thePartSU, nsm); // DMc: temp to ensure it's deleted
  867.     TempODISOStr theCategory = (ODISOStr)ODNewPtrClear(GetITextStringLength(category)+1);
  868.     GetITextCString( category, (char*)theCategory );
  869.  
  870.     if (!NotifiedSubstitutions(theEditor, theCategory))
  871.     {
  872.         ODIText* editorUserString = kODNULL;
  873.         Str255     editorString = "\p";
  874.         Str255     catString = "\p";
  875.         
  876.         GetITextPString( category, catString );
  877.  
  878.         GetUserEditorFromEditor( nsm, theEditor, &editorUserString );
  879.         TempODIText tempEditorUserString = editorUserString; // DMc: ensure it's deleted
  880.         GetITextPString( editorUserString, editorString );
  881.     
  882.         NMRemove(fNMRecPtr);    // ensure not already queued
  883.         fNMRecPtr->qType = nmType;
  884.         fNMRecPtr->nmMark = 0;
  885.         fNMRecPtr->nmIcon = nil;
  886.         fNMRecPtr->nmSound = nil;
  887.         ODDisposePtr((ODPtr) fNMRecPtr->nmStr);
  888.         fNMRecPtr->nmStr = BuildNotificationString(kBindingWarning, catString, editorString);
  889.         fNMRecPtr->nmResp = fNMResponseUPP;
  890.         ODError error = NMInstall(fNMRecPtr);
  891.  
  892.         if (fSubstitutionList)
  893.         {
  894.             ValueNameSpaceRegister(fSubstitutionList, ev, (ODISOStr)theCategory, 
  895.                                   (ODPtr)theEditor, ODISOStrLength(theEditor) + 1);
  896.         }
  897.     }
  898. }
  899.  
  900.  
  901. //------------------------------------------------------------------------------
  902. // Binding::NotifiedSubstitutions
  903. //------------------------------------------------------------------------------
  904.  
  905. ODBoolean Binding::NotifiedSubstitutions(ODEditor theEditor, ODISOStr theCategory)
  906. {
  907.     Environment* ev = somGetGlobalEnvironment ();
  908.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  909.  
  910.     ODBoolean    subAlreadyNotified = kODFalse;
  911.     
  912.     if (fSubstitutionList)
  913.     {
  914.             // Lookup the substitutionList by editor class ID
  915.         ODISOStr editorSub = ValueNameSpaceGetString(fSession, 
  916.                                             kEditorSubstitutionList, theCategory);
  917.         //WARN("ValueNameSpaceGetString returned '%s'", editorSub);
  918.         if (ODISOStrEqual(editorSub, theEditor))
  919.             subAlreadyNotified = kODTrue;
  920.             
  921.         ODDisposePtr( editorSub );
  922.     }
  923.  
  924.     return subAlreadyNotified;
  925. }
  926.  
  927. //------------------------------------------------------------------------------
  928. // IsNoPart
  929. //------------------------------------------------------------------------------
  930.  
  931. ODBoolean IsNoPart(Environment* ev, ODPart* rootPart)
  932. {
  933.     ODEditor editor = ((ODPartWrapper*)rootPart)->GetEditor(ev);
  934.  
  935.     ODUShort length = (ODUShort)ODISOStrLength(editor);
  936.     return (ODISOStrNCompare(editor, kODBlackBoxHandlerOfLastResort, length) == 0);
  937. }
  938.  
  939. //------------------------------------------------------------------------------
  940. // GetCurrentEditorForPart
  941. //------------------------------------------------------------------------------
  942. ODEditor GetCurrentEditorForPart(ODPart* part )
  943. {
  944.     Environment* ev = somGetGlobalEnvironment();
  945.  
  946.     ODEditor theEditor = ((ODPartWrapper*)part)->GetEditor(ev);
  947.     ODUShort length = (ODUShort)ODISOStrLength(theEditor);
  948.     
  949.     ODEditor partName = (ODEditor)ODNewPtrClear( length+1 );;
  950.     ODBlockMove(theEditor,  partName, length+1 );
  951.     return partName;
  952. }
  953.  
  954. //------------------------------------------------------------------------------
  955. // ChangeEditor
  956. //------------------------------------------------------------------------------
  957.  
  958. void ChangeEditor(ODPart* part, ODEditor editorID)
  959. {
  960.     Environment* ev = somGetGlobalEnvironment();
  961.     ((ODPartWrapper*)part)->UseEditor(ev, editorID);
  962.     ODStorageUnit* thePartSU = part->GetStorageUnit(ev);
  963.     ODSetISOStrProp(ev, thePartSU, kODPropPreferredEditor, kODEditor, editorID);
  964. }
  965.  
  966. //------------------------------------------------------------------------------
  967. // ChangeKindAndEditor
  968. //------------------------------------------------------------------------------
  969.  
  970. void ChangeKindAndEditor (Environment *ev,
  971.         ODPart* part,
  972.         ODType newKind,
  973.         ODEditor newEditor,
  974.         ODNameSpaceManager* nsm)
  975. {
  976.     ODStorageUnit* partSU = part->GetStorageUnit(ev);    ODVolatile(partSU);
  977.     TempODEditor curEditor = GetCurrentEditorForPart(part);
  978.     TempODType curKind = ODGetKindFromPartSU(ev, partSU);
  979.     
  980.     if ( ODISOStrEqual(curEditor, newEditor) )
  981.     {
  982.         if ( !ODISOStrEqual(curKind, newKind) )
  983.             part->ChangeKind(ev, newKind);
  984.     }
  985.     else if ( partSU->Exists(ev, kODPropContents, newKind, 0) )
  986.     {
  987.         // Before changing the editor, ensure newKind is set as
  988.         // the preferred property
  989.         ODULong unused;
  990.         TempODType oldKind = ODGetISOStrProp(ev, partSU, kODPropPreferredKind, kODISOStr, kODNULL, &unused);
  991.         ODSetISOStrProp(ev, partSU, kODPropPreferredKind, kODISOStr, newKind);
  992.         TRY
  993.             ChangeEditor(part, newEditor);
  994.         CATCH_ALL
  995.             // If the editor didn't change, restore the preferred kind
  996.             TempODEditor failEditor = GetCurrentEditorForPart(part);
  997.             if ( ODISOStrEqual(failEditor, curEditor) )
  998.             {
  999.                 if ( (ODType) oldKind != kODNULL )
  1000.                 {
  1001.                     ODSetISOStrProp(ev, partSU, kODPropPreferredKind, kODISOStr, oldKind);
  1002.                 }
  1003.                 else
  1004.                 {
  1005.                     if ( ODSUExistsThenFocus(ev, partSU, kODPropPreferredKind, kODNULL) )
  1006.                         partSU->Remove(ev);
  1007.                 }
  1008.             }
  1009.             RERAISE;
  1010.         ENDTRY
  1011.     }
  1012.     else if ( EditorSupportsKind(nsm, curEditor, newKind) )
  1013.     {
  1014.         // change kind first, then editor
  1015.         part->ChangeKind(ev, newKind);
  1016.  
  1017.         // verify that the change took place before changing editor
  1018.         TempODType tempKind = ODGetKindFromPartSU(ev,partSU);
  1019.         if ( ODISOStrEqual(tempKind, newKind) )
  1020.             ChangeEditor(part, newEditor);
  1021.     }
  1022.     else if ( EditorSupportsKind(nsm, newEditor, curKind) )
  1023.     {
  1024.         // change editor first, then kind
  1025.         ChangeEditor( part, newEditor);
  1026.         part->ChangeKind(ev, newKind);
  1027.  
  1028.         // if the kind didn't actually change, revert back to curEditor
  1029.         TempODType tempKind = ODGetKindFromPartSU(ev,partSU);
  1030.         if ( ODISOStrEqual(tempKind, curKind) )
  1031.             ChangeEditor(part, curEditor);
  1032.     }
  1033.     else
  1034.     {
  1035.         // Internal error; editors do not support a common kind and
  1036.         // translation has not been performed.
  1037.         WARN("ChangeKindAndEditor cannot change kind or editor");
  1038.     }
  1039. }
  1040.