home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osr1.exe / src / DragDrp.cpp < prev    next >
C/C++ Source or Header  |  1997-04-02  |  126KB  |  4,091 lines

  1. /* @(#)Z 1.19 os2/src/storage/DragDrp.cpp, oddataxfer, od96os2, odos29714c 97/04/02 17:20:18 (97/04/02 10:57:34) */
  2. //====START_GENERATED_PROLOG======================================
  3. //
  4. //
  5. //   COMPONENT_NAME: oddataxfer
  6. //
  7. //   CLASSES: none
  8. //
  9. //   ORIGINS: 82,27
  10. //
  11. //
  12. //   (C) COPYRIGHT International Business Machines Corp. 1995,1996
  13. //   All Rights Reserved
  14. //   Licensed Materials - Property of IBM
  15. //   US Government Users Restricted Rights - Use, duplication or
  16. //   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  17. //       
  18. //   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  19. //   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20. //   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21. //   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  22. //   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  23. //   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  24. //   OR PERFORMANCE OF THIS SOFTWARE.
  25. //
  26. //====END_GENERATED_PROLOG========================================
  27. //
  28.  
  29. /*---------------------------------------------------------------------------
  30.    Name:        DragDrp.cpp
  31.  
  32.    Description: Contains the implementation of the OS/2 Opendoc Drag&Drop
  33.                 Object.
  34.  
  35.    Notes:
  36.                 - source part can place data or promise data into drag su
  37.                 - source part can affect dragitem structure placed in
  38.                   drag su at getcontentstorageunit time.
  39.    see below    - target part can create view and call getdatafromdragmanager
  40.    see below    - the rmf on getdatafromdragmanager will be used to focus
  41.                   the drag su. data will be written to this value.
  42.  
  43.    Assumptions:
  44.  
  45.    To Do:
  46.  
  47.    Design discoveries:
  48.  
  49.     The OS/2 Merlin OpenDoc team designed ODDragAndDrop with the
  50.     primary goal, I'm guessing, of allowing OpenDoc parts to 'fully
  51.     participate' in the community of happy OS/2 desktop applications.
  52.  
  53.     Apple DR4 ODDragAndDrop was designed to allow parts to initiate
  54.     drag and drop operations and to receive dragged and dropped
  55.     content.  When the user indicates that he wishes to drag selected
  56.     content, parts get one or more storage units from their session's
  57.     ODDragAndDrop object and store in them the user's selected
  58.     content.  The parts then request a StartDrag, and the
  59.     ODDragAndDrop object uses platform APIs to drag the content around
  60.     the user desktop.  As the user gesture enters and moves within a
  61.     part's facet(s), the part receives DragEnter and DragWithin
  62.     messages from the ODDragAndDrop object; the part can respond to
  63.     these calls to communicate its willingness to accept the dragged
  64.     content to the ODDragAndDrop object, and to indicate to the user
  65.     that same information via whatever feedback is appropriate.  Parts
  66.     accomplish these tasks by examining the drag source's storage
  67.     units made available to them via a drag item iterator passed in
  68.     the DragEnter/DragWithin calls.  Finally, the ODDragAndDrop object
  69.     sends a Drop message to the part's facet under the cursor when the
  70.     user completes the drag gesture.  The list of the source part's
  71.     storage units is once again passed to the destination part via a
  72.     drag item iterator, and the destination part may embed,
  73.     incorporate or refuse the dropped content as it chooses.
  74.  
  75.     The Merlin design departs from this model in at least one key
  76.     area: parts receiving DragEnter, DragWithin and Drop messages are
  77.     not passed an iterator to the list of the source part's storage
  78.     units; parts instead receive an iterator to a list of storage
  79.     units that contain OS/2 DRAGITEM structures.  Parts are required
  80.     to call the OS/2-only OpenDoc APIs 'CanEmbed' or 'CanIncorporate'
  81.     during DragEnter/DragWithin to determine their ability to accept
  82.     the dragged content, and parts are required to call the OS/2-only
  83.     OpenDoc API GetDataFromDragManager during the Drop method to
  84.     obtain the "true" storage unit(s) containing the content that the
  85.     source part intended to transfer in the drag and drop operation.
  86.  
  87.     I am guessing that this design change was done to allow parts to
  88.     manipulate the DRAGITEM and DRAGINFO structures that are used in
  89.     the OS/2 Direct Manipulation (Drag and Drop) API; it appears that
  90.     access to OS/2 DRAGITEM/DRAGINFO structures was given to OS/2
  91.     drag-capable source parts, allowing them to insert their own OS/2
  92.     direct manipulation information, so that the information would
  93.     subsequently be available to destination parts via methods
  94.     DragEnter, DragWithin, and Drop.  Unfortunately, this results in
  95.     extra work for part writers, it dramatically reduces the
  96.     portability of OpenDoc parts, and I think that in many cases the
  97.     same functionality could be achieved via existing OpenDoc APIs.
  98.  
  99.     Additional responsibilities of OS/2 OpenDoc parts beyond the
  100.     usual DR4 design:
  101.  
  102.     1)    In their DragEnter/DragWithin methods, parts must call
  103.         CanEmbed and/or CanIncorporate to determine if they can accept
  104.         the dragged content.
  105.     2)    In their Drop methods, parts must, for each drag item made
  106.         available by the passed drag item iterator:
  107.         a) focus on the kODDragItem value
  108.         b) create a storage unit view
  109.         c) call GetDataFromDragManager to obtain the 'translated'
  110.            storage units that contain the original data placed in
  111.            the storage units by the source part
  112.  
  113.     Changes from previous OS/2 OpenDoc implementations:
  114.  
  115.     1)    Parts should not return MRESULTs in response to DragEnter,
  116.         DragWithin or Drop, but should instead return regular OpenDoc
  117.         boolean ODDragResults or ODDropResults.
  118.  
  119.  
  120.    Format considerations:    formatted for tab width of 4
  121.  
  122.  
  123. ---------------------------------------------------------------------------*/
  124.  
  125. /*---------------------------------------------------------------------------
  126.                             Include Files
  127. ---------------------------------------------------------------------------*/
  128. #define INCL_WINMESSAGEMGR
  129. #define INCL_WINSTDFILE
  130. #define INCL_DOS
  131. #define INCL_DOSERRORS
  132. #define INCL_DOSFILEMGR
  133. #define INCL_DOSMODULEMGR
  134. #define INCL_DOSRESOURCES
  135. #define INCL_WININPUT
  136. #define INCL_WINSTDDRAG
  137. #define INCL_WINFRAMEMGR
  138. #define INCL_WINWINDOWMGR
  139. #define INCL_WINPOINTERS
  140. #define INCL_WINACCELERATORS
  141. #define INCL_WINSYS
  142. // #define INCL_OSAAPI
  143. // #define INCL_OSAEVENTS
  144.  
  145. #ifdef _UNICODE_
  146. #define INCL_WIN
  147. #endif
  148.  
  149. #include <os2.h>
  150.  
  151. #ifndef _ALTPOINT_
  152. #include "AltPoint.h"                // Use C++ savvy XMPPoint and XMPRect
  153. #endif
  154.  
  155. #ifndef _ODTYPES_
  156. #include <ODTypes.h>                //  the OpenDoc kitchen sink
  157. #endif
  158.  
  159. #define ODDragAndDrop_Class_Source
  160. #define VARIABLE_MACROS
  161. #include <DragDrp.xih>
  162.  
  163. #ifndef SOM_ODDragItemIterator_xh
  164. #include <DgItmIt.xh>
  165. #endif
  166.  
  167. #ifndef _DRAGPRIV_
  168. #include <DragPriv.h>
  169. #endif
  170.  
  171. #ifndef SOM_Module_OpenDoc_StdProps_defined
  172. #include <StdProps.xh>
  173. #endif
  174.  
  175. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  176. #include <StdTypes.xh>
  177. #endif
  178.  
  179. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  180. #include <StdDefs.xh>   // [140007]
  181. #endif
  182.  
  183. #ifndef SOM_ODSession_xh
  184. #include <ODSessn.xh>
  185. #endif
  186.  
  187. #ifndef SOM_ODStorageSystem_xh
  188. #include <ODStor.xh>
  189. #endif
  190.  
  191. #ifndef SOM_ODContainer_xh
  192. #include <ODCtr.xh>
  193. #endif
  194.  
  195. #ifndef SOM_ODDocument_xh
  196. #include <Document.xh>
  197. #endif
  198.  
  199. #ifndef SOM_ODDraft_xh
  200. #include <Draft.xh>
  201. #endif
  202.  
  203. #ifndef SOM_ODFrame_xh
  204. #include <Frame.xh>
  205. #endif
  206.  
  207. #ifndef SOM_ODFacet_xh
  208. #include <Facet.xh>
  209. #endif
  210.  
  211. #ifndef SOM_ODWindow_xh
  212. #include <Window.xh>
  213. #endif
  214.  
  215. #ifndef SOM_ODWindowState_xh
  216. #include <WinStat.xh>
  217. #endif
  218.  
  219. #ifndef SOM_ODPart_xh
  220. #include <Part.xh>
  221. #endif
  222.  
  223. #ifndef SOM_ODTranslation_xh
  224. #include <Translt.xh>
  225. #endif
  226.  
  227. #ifndef _ODMEMORY_
  228. #include "ODMemory.h"
  229. #endif
  230.  
  231. #ifndef _ODNew_
  232. #include "ODNew.h"
  233. #endif
  234.  
  235. #ifndef _EXCEPT_
  236. #include "Except.h"
  237. #endif
  238.  
  239. #ifndef _LINKLIST_
  240. #include "LinkList.h"
  241. #endif
  242.  
  243. #ifndef SOM_ODStorageUnitView_xh
  244. #include <SUView.xh>
  245. #endif
  246.  
  247. #ifndef _STORDEF_
  248. #include "StorDef.h"
  249. #endif
  250.  
  251. #ifndef SOM_CMStorageUnit_xh
  252. #include <CMSU.xh>
  253. #endif
  254.  
  255. #ifndef _PLFMFILE_
  256. #include <PlfmFile.h>
  257. #endif
  258.  
  259. #ifndef _PASCLSTR_
  260. #include <PasclStr.h>
  261. #endif
  262.  
  263. #ifndef _LINKDLGS_
  264. #include "LinkDlgs.h"
  265. #endif
  266.  
  267. #ifndef __MEMORY__
  268. #include <Memory.h>
  269. #endif
  270.  
  271. #ifndef _BARRAY_
  272. #include <BArray.h>
  273. #endif
  274.  
  275. #ifndef SOM_ODNameSpaceManager_xh
  276. #include <NmSpcMg.xh>
  277. #endif
  278.  
  279. #ifndef SOM_ODValueNameSpace_xh
  280. #include <ValueNS.xh>
  281. #endif
  282.  
  283. #ifndef _STORUTIL_
  284. #include "StorUtil.h"
  285. #endif
  286.  
  287. #include <string.h>
  288.  
  289. #ifndef _ODDEBUG_
  290. #include "ODDebug.h"
  291. #endif
  292.  
  293. #if ODDebug
  294. #ifndef __strstream_h            // for StackCrawl stuff
  295. #include <strstrea.h>
  296. #endif
  297. #include "stkcrawl.h"
  298. #endif
  299.  
  300. #ifndef _NMSPCUTL_
  301. #include <NmSpcUtl.h>
  302. #endif
  303.  
  304. #ifndef _ODUTILS_
  305. #include <ODUtils.h>
  306. #endif
  307.  
  308. #ifndef _TEMPOBJ_
  309. #include "TempObj.h"
  310. #endif
  311.  
  312. //  [140007] Part registration includes
  313. #include    <RManager.xh>
  314. #include    <ODPrtReg.xh>
  315.  
  316. //==============================================================================
  317. // Constants
  318. //==============================================================================
  319.  
  320. #if ODDebug
  321. // #define ODDebug_DragAndDrop 1
  322. #endif
  323.  
  324. // NASTY HACK:
  325. // Because of the way that the OS/2 implementation dorks the storage units that
  326. // are dragged around by the ODDragAndDrop object (see 'Design discoveries' at
  327. // top of file for complete discussion), we need a way to communicate the
  328. // original clone kind of a drag and drop data transfer operation to the target
  329. // of a drop when the target is in a different process than the source.  In my
  330. // quest to find the nastiest hack possible, I have decided to change the case
  331. // of the hstrTargetName when the source specifies that the clone operation is
  332. // a copy.  This will allow ODDragAndDrop objects in non-local target processes
  333. // to quickly determine if the source's original clone kind was a copy or not.
  334. // [For more boring discussion of the implications of not properly interpreting
  335. // the clone kind, see the comments in dmDrop that start with the line:
  336. //     'check to see whether the source wants to allow only copy']
  337. // 
  338. // So, careful now - don't change the OPENDOC_FILENAME_DEFAULT unless you know
  339. // what is going on.  When the OS/2 implementation is brought in line with DR4,
  340. // this nasty hack won't be necessary.
  341. #define OPENDOC_FILENAME_DEFAULT        "OPENDOC.OD"
  342. #define OPENDOC_FILENAME_FOR_CLONECOPY    "OpenDoc.OD"
  343.  
  344. //==============================================================================
  345. // Scalar Types
  346. //==============================================================================
  347.  
  348. typedef struct
  349. {
  350.     ODPart            *sourcePart;
  351.     ODStorageUnitView *destSUView;
  352. } ODPromiseDesc;
  353.  
  354. /*---------------------------------------------------------------------------
  355.                                Typedefs
  356. ---------------------------------------------------------------------------*/
  357.  
  358. // Structures to aid in accessing the EA information lists.
  359. // (taken from shfsys.h)
  360.  
  361. // Ascii subtype used to help read the ASCII type in an MVMT list.
  362. typedef struct eastascii
  363. {
  364.     USHORT        wEASType;
  365.     USHORT        cbValue;
  366.     char          bValue[1];
  367. } EASTASCII;
  368.  
  369. // ASCII EA type structure.
  370. typedef struct eatascii
  371. {
  372.     USHORT        cbValue;
  373.     char          bValue[1];
  374. } EATASCII;
  375.  
  376. // MVMT EA type structure.
  377. typedef struct eatmvmt
  378. {
  379.     USHORT        wReserved;
  380.     USHORT        cItem;
  381. } EATMVMT;
  382.  
  383. // Union of EA type structures.
  384. typedef union eatypes
  385. {
  386.     EATASCII      stEATAscii;
  387.     EATMVMT       stEATMvmt;
  388. } EATYPES;
  389.  
  390. // Value output structure used to help read EA values.
  391. typedef struct ea2value
  392. {
  393.     USHORT        wEAType;
  394.     EATYPES       unEATypes;
  395. } FEA2VALUE;
  396.  
  397. /*---------------------------------------------------------------------------
  398.                               Prototypes
  399. ---------------------------------------------------------------------------*/
  400. USHORT SetEAFromName(PSZ pszFilePath,
  401.                      PSZ pszEAName,
  402.                      PSZ pszEAValue);
  403.  
  404. USHORT GetEAFromName(PSZ pszFilePath,
  405.                      PSZ pszEAName,
  406.                      USHORT *pwEAType,
  407.                      PSZ    pszEAValue);
  408.  
  409. BOOL GetFileName(PSZ szFullPath);
  410.  
  411. BOOL GetEAFromPFEA(PFEA2 pFEA,
  412.                    USHORT *pwEAType,
  413.                    PSZ pszEAValue);
  414.  
  415. ODBoolean WriteDragItemtoFile(ODDragAndDrop *somSelf,
  416.                               Environment *ev,
  417.                               ODPtr theItem,
  418.                               ODUByte *pathName,
  419.                               ODUByte *fileName,
  420.                               PSZ type);
  421. // [129057]
  422. void GiveMemoryIfNecessary(HWND hwndTarget,
  423.                            HWND hwndSource,
  424.                            PBYTE pbData);
  425.  
  426. PBYTE AllocSharedMem(PDRAGTRANSFER pDragTransfer,
  427.                      ULONG dataSize);
  428. // [140007] :
  429. void ParseRMF(PSZ pszRMF,
  430.               LinkedList *fRMFList);
  431.  
  432. PSZ GetNextRMF(PSZ buf);
  433.  
  434. void AddXProductRMF(PSZ buf,
  435.                     LinkedList* fRMFList);
  436.  
  437. PSZ GetToken(PSZ start,
  438.              PSZ buf);
  439.  
  440. void AddRMF(PSZ buf,
  441.             LinkedList* fRMFList);
  442.  
  443. ODBoolean SupportedRMF(PSZ theRMF);
  444.  
  445. PSZ GetKindForFormat(PSZ fmt);
  446.  
  447. PSZ GetFormatFromRMF(PSZ buf);
  448.  
  449. ODBoolean GetRMFForKind(PSZ kind,
  450.                         PSZ pszRMF);
  451.  
  452. ODBoolean QueryRMF(PSZ pszRMF,
  453.                    PSZ mech,
  454.                    PSZ fmt);
  455.  
  456. ODBoolean KindInTypeList(PSZ kind,
  457.                          PSZ typeList);
  458. // end [140007]
  459.  
  460. // [145338]
  461. //---------------------------------------------------------------------------
  462. // VK_SHIFT  VK_CTRL  VK_ALT  VK_CAPSLOCK  VK_NUMLOCK  VK_SCRLLOCK VK_ALTGRAF
  463. //---------------------------------------------------------------------------
  464. BOOL key_shift(SHORT vk_key)
  465. {
  466.     SHORT key_state = WinGetKeyState(HWND_DESKTOP, vk_key);
  467.     return (BOOL)(key_state & 0x8000);
  468. }
  469. // end [145338]
  470.  
  471. /*---------------------------------------------------------------------------
  472.                             ODDragAndDrop
  473. ---------------------------------------------------------------------------*/
  474.  
  475. #if ODDebug
  476. // turn this on/off via the debugger to enable/disable logging
  477. static BOOL fDebugLogging = kODTrue;
  478. // this helps reduce logging of DM_DRAGOVER messages
  479. static int counter = 0;
  480. #endif
  481. #ifdef SOMDEBUG
  482. // this will turn on the MethodDebug statements in the DLL
  483. int SOM_TraceLevel = 1;
  484. #endif
  485.  
  486. /*---------------------------------------------------------------------------
  487.         ODDragAndDrop::ShowPasteAsDialog
  488. ---------------------------------------------------------------------------*/
  489. SOM_Scope ODBoolean  SOMLINK ODDragAndDropShowPasteAsDialog(ODDragAndDrop *somSelf,
  490.                                                             Environment   *ev,
  491.                                                             ODBoolean canPasteLink,
  492.                                                             ODPasteAsMergeSetting mergeSetting,
  493.                                                             ODFacet* facet,
  494.                                                             ODTypeToken viewType,
  495.                                                             ODStorageUnit * contentSU,
  496.                                                             ODPasteAsResult* result)
  497.  
  498. {
  499.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  500.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropShowPasteAsDialog");
  501.  
  502. #if ODDebug
  503.     if (fDebugLogging)
  504.         somPrintf("in ShowPasteAsDialog\n");
  505. #endif
  506.  
  507.     THROW_IF_NULL(facet);
  508.     THROW_IF_NULL(contentSU);
  509.     THROW_IF_NULL(result);
  510.  
  511.     ODBoolean returnValue = ShowPasteAsDialog(canPasteLink,
  512.                                               mergeSetting,
  513.                                               (somSelf->GetDropResult(ev) == kODDropMove),
  514.                                               contentSU,
  515.                                               facet,
  516.                                               viewType,
  517.                                               result);
  518.  
  519.     return returnValue;
  520. }
  521.  
  522. /*---------------------------------------------------------------------------
  523.         ODDragAndDrop::InitDragAndDrop
  524. ---------------------------------------------------------------------------*/
  525. SOM_Scope void  SOMLINK ODDragAndDropInitDragAndDrop(ODDragAndDrop *somSelf,
  526.                                                      Environment   *ev,
  527.                                                      ODSession     *session)
  528. {
  529.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  530.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropInitDragAndDrop");
  531.  
  532.     if (session == kODNULL)                           //D127323
  533.         THROW(kODErrIllegalNullInput);                  //D127323
  534.  
  535. //TDF    if (somSelf->IsInitialized(ev))
  536. //TDF        return;
  537.  
  538.     _fSession = session;
  539.  
  540.     _fWindowState      = kODNULL;        //  moved from somInit
  541.     _fStorageSystem    = kODNULL;        //  moved from somInit
  542.     _fDragItemList     = kODNULL;        //  moved from somInit
  543.     _fDragGarbageList  = kODNULL;        //  moved from somInit
  544.     _fListFromHandler  = kODFalse;        //  moved from somInit
  545.     _fDragItemIterator = kODNULL;        //  moved from somInit
  546.     _fAttributes       = 0;                //  moved from somInit
  547.     _fDragReference    = 0;                //  moved from somInit
  548.     _fDragOperation    = 0;                //  moved from somInit
  549.     _fDragItem         = 0;                //  moved from somInit
  550.     _fPrevFacet        = kODNULL;        //  moved from somInit
  551.     _fSourceFrame      = kODNULL;        //  moved from somInit
  552.     _fSourcePart       = kODNULL;        //  moved from somInit
  553.     _fDestFacet        = kODNULL;        //  moved from somInit
  554.     _fDragInform       = kODNULL;        //  moved from somInit
  555.     _fNeverDrop        = kODFalse;        //  moved from somInit
  556.  
  557.     somSelf->InitObject(ev);
  558.  
  559.     TRY
  560.         _fWindowState      = _fSession->GetWindowState(ev);
  561.         _fStorageSystem    = _fSession->GetStorageSystem(ev);
  562.           _fDragItemList     = new LinkedList;
  563.           _fDragGarbageList  = new LinkedList;
  564.  
  565.     CATCH_ALL
  566.         _fWindowState   = kODNULL;
  567.         _fStorageSystem = kODNULL;
  568.         if (_fDragItemList)
  569.         {
  570.             delete _fDragItemList;
  571.             _fDragItemList = kODNULL;
  572.         }
  573.         if (_fDragGarbageList)
  574.         {
  575.             delete _fDragGarbageList;
  576.             _fDragGarbageList = kODNULL;
  577.         }
  578.         RERAISE;
  579.     ENDTRY
  580. }
  581.  
  582. /*---------------------------------------------------------------------------
  583.         ODDragAndDrop::GetDragAttributes
  584. ---------------------------------------------------------------------------*/
  585. SOM_Scope ODULong  SOMLINK ODDragAndDropGetDragAttributes(ODDragAndDrop *somSelf,
  586.                                                           Environment   *ev)
  587. {
  588.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  589.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragAttributes");
  590.  
  591.     return _fAttributes;
  592. }
  593.  
  594. /*---------------------------------------------------------------------------
  595.         ODDragAndDrop::GetDragOperation
  596. ---------------------------------------------------------------------------*/
  597. SOM_Scope ODUShort SOMLINK ODDragAndDropGetDragOperation(ODDragAndDrop *somSelf,
  598.                                                          Environment   *ev)
  599. {
  600.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  601.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragOperation");
  602.  
  603.     return _fDragOperation;
  604. }
  605.  
  606. /*---------------------------------------------------------------------------
  607.         ODDragAndDrop::GetDragReference
  608. ---------------------------------------------------------------------------*/
  609. SOM_Scope ODPlatformDragReference SOMLINK ODDragAndDropGetDragReference(
  610.                                                         ODDragAndDrop *somSelf,
  611.                                                         Environment   *ev)
  612. {
  613.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  614.     ODDragAndDropMethodDebug("ODDragAndDrop", "ODDragAndDropGetDragReference");
  615.  
  616.     return _fDragReference;
  617. }
  618.  
  619. /*---------------------------------------------------------------------------
  620.         ODDragAndDrop::FindTargetFacet
  621.  
  622. NOTE: this method is not currently called in this OS/2 implementation!
  623.       Probably, when the OS/2 drag and drop implementation is redesigned,
  624.       this method should be used in a similar fashion to the way it is
  625.       used by the NT implementation, and the actual code of this method
  626.       should follow the NT implementation's code closely, as well (the
  627.       NT implementation of this method is actually very close to DR4).
  628. ---------------------------------------------------------------------------*/
  629. SOM_Scope ODFacet * SOMLINK ODDragAndDropFindTargetFacet(ODDragAndDrop    *somSelf,
  630.                                                          Environment      *ev,
  631.                                                          ODPlatformWindow theWindow,
  632.                                                          PPOINTL          mouse,
  633.                                                          ODPoint          *local)
  634. {
  635.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  636.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropFindTargetFacet");
  637.  
  638.     ODFacet  *targetFacet = kODNULL;
  639.     POINTL   ptl;
  640.  
  641.     SOM_TRY
  642.         ODFacet  *curFacet;
  643.         {
  644.             TempODWindow targetWindow = _fWindowState->AcquireODWindow(ev, theWindow);
  645.             if (!targetWindow)
  646.                 return kODNULL;
  647.         
  648.             //  ... so how come the NT port doesn't need to map the window point here?
  649.             ptl = *mouse;
  650.             WinMapWindowPoints(HWND_DESKTOP,
  651.                                WinWindowFromID(theWindow, FID_CLIENT), 
  652.                                &ptl, 
  653.                                1);
  654.             local->x = MAKEFIXED(ptl.x,0);
  655.             local->y = MAKEFIXED(ptl.y,0);
  656.         
  657.             curFacet = targetWindow->GetFacetUnderPoint(ev, local);
  658.         }
  659.         
  660.         while (curFacet && !targetFacet)
  661.         {
  662.             ODFrame* curFrame = curFacet->GetFrame(ev);
  663.             if (!curFrame->IsDragging(ev) &&
  664.                 curFrame->IsDroppable(ev) &&
  665.                 !curFrame->IsFrozen(ev))
  666.               targetFacet = curFacet;
  667.  
  668.             curFacet = curFacet->GetContainingFacet(ev);
  669.         }
  670.  
  671.     SOM_CATCH_ALL
  672.     SOM_ENDTRY
  673.  
  674.     return targetFacet;
  675. }
  676.  
  677. /*---------------------------------------------------------------------------
  678.         ODDragAndDrop::GetPromiseFromDragManager
  679. ---------------------------------------------------------------------------*/
  680. SOM_Scope void  SOMLINK ODDragAndDropGetPromiseFromDragManager(
  681.                                             ODDragAndDrop     *somSelf,
  682.                                             Environment       *ev,
  683.                                             ODPart            *sourcePart,
  684.                                             ODStorageUnitView *destSUView)
  685. {
  686.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  687.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPromiseFromDragManager");
  688.  
  689.     // 127321 - check for null input
  690.     if (destSUView == kODNULL || sourcePart == kODNULL)
  691.     {
  692. #if ODDebug
  693.       if (fDebugLogging)
  694.         somPrintf("GetPromiseFromDragManager: Bad parameter\n");
  695. #endif
  696.       return;
  697.     }
  698.  
  699.     ODValueType type = destSUView->GetType(ev);
  700.  
  701.     (sourcePart)->FulfillPromise(ev, destSUView);
  702. }
  703.  
  704. /*---------------------------------------------------------------------------
  705.         ODDragAndDrop::GetDataFromDragManager
  706. ---------------------------------------------------------------------------*/
  707. SOM_Scope ODBoolean SOMLINK ODDragAndDropGetDataFromDragManager(
  708.                                         ODDragAndDrop     *somSelf,
  709.                                         Environment       *ev,
  710.                                         ODStorageUnitView *theSUView,
  711.                                         ODStorageUnit     **renderedSU)
  712. {
  713.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  714.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDataFromDragManager");
  715.  
  716.     ODMemDragItem        *newItem = kODNULL;
  717.     ODDragLink            *newLink = kODNULL;
  718.     DRAGITEM            DragItem;
  719.     PDRAGITEM            pDragItem;
  720.     PDRAGTRANSFER        pDragTransfer;
  721.     CHAR                szName[CCHMAXPATH];
  722.     BOOL                fFile = FALSE;
  723.     PDRAGINFO            pDragInfo = (PDRAGINFO)_fDragReference;
  724.     ODBoolean            fSuccess = kODTrue;
  725.     ODULong                size;
  726. // [140007] :
  727.     CHAR szSelectedKind[CCHMAXPATH];
  728.     CHAR szSelectedRMF[CCHMAXPATH];
  729.     PSZ pszSelectedKind = kODNULL;
  730.  
  731.     // whoa - this method is no good until a drop has occurred:
  732.     if (_fDestFacet == kODNULL)
  733.     {
  734.         ASSERT(_fDestFacet != kODNULL, kODErrDropFacetNotKnown);
  735. #if ODDebug
  736.         if (fDebugLogging)
  737.             somPrintf("GDFDM: _fDestFacet = NULL (GDFDM called too early?)\n");
  738. #endif
  739.         return kODFalse;
  740.     }
  741.  
  742. #if ODDebug
  743.     if (fDebugLogging)
  744.         somPrintf("GDFDM: theSUView = %08p, renderedSU = %08p\n",
  745.                   theSUView, renderedSU);
  746. #endif
  747.  
  748.     // see if we can embed the dragged content
  749.     ODStorageUnit* su = theSUView->GetStorageUnit(ev);
  750.     if (!su->Exists(ev, kODPropContents, (ODValueType)kODSelectedRMF, 0))
  751.         if (!somSelf->CanEmbed(ev, su))
  752.             return kODFalse;
  753. #if ODDebug
  754.     if (fDebugLogging)
  755.         somPrintf("GDFDM: content embeddable\n");
  756. #endif
  757.  
  758.     // focus and get value of selected RMF
  759.     su->Focus(ev,
  760.               kODPropContents,
  761.               kODPosUndefined,
  762.               (ODValueType)kODSelectedRMF,
  763.               0,
  764.               kODPosUndefined);
  765.     size = su->GetSize(ev);
  766.     if (!size)
  767.         return kODFalse;
  768.     StorageUnitGetValue(su, ev, size, szSelectedRMF);
  769.  
  770.     // focus and get value of selected kind
  771.     if (su->Exists(ev, kODPropContents,kODSelectedKind,0))
  772.     {
  773.         su->Focus(ev,
  774.                   kODPropContents,
  775.                   kODPosUndefined,
  776.                   (ODValueType)kODSelectedKind,
  777.                   0,
  778.                   kODPosUndefined);
  779.         size = su->GetSize(ev);
  780.         if (size)
  781.         {
  782.             StorageUnitGetValue(su, ev, size, szSelectedKind);
  783.             pszSelectedKind = szSelectedKind;
  784.         }
  785.     }
  786. #if ODDebug
  787.     if (fDebugLogging)
  788.         somPrintf("GDFDM: RMF = \"%s\", kind = \"%s\"\n",
  789.                   szSelectedRMF, pszSelectedKind);
  790. #endif
  791. // [140007] end
  792.  
  793.     // allocate the storage unit we will return to caller...
  794.     newItem = new(ODGetDefaultHeap()) ODMemDragItem(_fStorageSystem, kODFalse);
  795.     ASSERT(newItem != kODNULL, kODErrCannotAllocateDragItem);
  796.     newItem->Initialize(ev);
  797.     newLink = new ODDragLink(newItem, kODTrue);
  798.     if (!newLink)
  799.     {
  800.         delete newItem;
  801.         ASSERT(newLink != kODNULL, kODErrCannotAllocateDragItem);
  802.         fSuccess = kODFalse;
  803.     }
  804.     else
  805.     {
  806.         // grab the dragitem from the user
  807.         StorageUnitViewGetValue(theSUView,
  808.                                 ev,
  809.                                 sizeof(DRAGITEM),
  810.                                 &DragItem);
  811.         theSUView->SetOffset(ev, sizeof(DRAGITEM));
  812.         StorageUnitViewGetValue(theSUView,
  813.                                 ev,
  814.                                 sizeof(PDRAGITEM),
  815.                                 &pDragItem);
  816.  
  817.         // bring over whatever changes the user has made (trust)
  818.         memcpy(pDragItem, &DragItem, sizeof(DRAGITEM));
  819. #if ODDebug
  820.         if (fDebugLogging)
  821.             somPrintf("GDFDM: user's drag item: %08p\n", pDragItem);
  822. #endif
  823.  
  824.         //clean this up - just refer to pDragItem from now on
  825. // [140007]:
  826.         // if we don't handle the RMF, let the part do the rendering
  827.         if (!SupportedRMF((PSZ)szSelectedRMF))
  828.         {
  829.             newItem->fSU->AddProperty(ev, kODPropContents)->AddValue(ev,(ODValueType)szSelectedRMF);
  830.             newItem->fSU->AddValue(ev,(ODValueType)kODDragitem);
  831.             StorageUnitSetValue(newItem->fSU, ev,sizeof(DRAGITEM), pDragItem);
  832.             _fDragGarbageList->AddLast(newLink);
  833.             *renderedSU = newItem->fSU;
  834. #if ODDebug
  835.             if (fDebugLogging)
  836.                 somPrintf("GDFDM: unsupported RMF; returning SU (%08p) to part to render\n",
  837.                           *renderedSU);
  838. #endif
  839.             return kODTrue;
  840.         }
  841.  
  842.         // if the selected RMF is an DRM_OS2FILE then we want
  843.         // to fill in the name info
  844.         if (!strncmp((PCSZ)szSelectedRMF, "<DRM_OS2FILE", 12))
  845.             fFile = TRUE;
  846. // [140007] end
  847.  
  848.         // start the drag/drop conversation by sending the DM_RENDER;
  849.         // initialize drag transfer structure
  850.         HWND hwndClient = WinWindowFromID(_fDestFacet->GetWindow(ev)->GetPlatformWindow(ev),
  851.                                           FID_CLIENT);
  852.         pDragTransfer = DrgAllocDragtransfer(1);
  853.         pDragTransfer->cb = sizeof(DRAGTRANSFER);
  854.         pDragTransfer->hwndClient = hwndClient;
  855.         pDragTransfer->pditem = pDragItem;
  856.         DrgPushDraginfo(pDragInfo, pDragInfo->hwndSource);
  857.         pDragTransfer->hstrSelectedRMF = DrgAddStrHandle((PCSZ)szSelectedRMF);
  858.  
  859.         // set hstrRenderToName appropriately:
  860.         // if the selected RMF is a DRM_OS2FILE ...
  861.         if (fFile)
  862.         {
  863.             szName[0] = 0;
  864.             CHAR tbuf[CCHMAXPATH];
  865.             DrgQueryStrName(DragItem.hstrContainerName, CCHMAXPATH, szName);
  866.             if (!szName[0])
  867.                 WinQueryActiveDesktopPathname(szName,sizeof(szName));
  868.             if (szName[strlen(szName)-1] != '\\')
  869.                 strcat (szName, "\\");
  870.             tbuf[0] = 0;
  871.             DrgQueryStrName(DragItem.hstrSourceName, CCHMAXPATH, tbuf);
  872.             if (!tbuf[0])
  873.                 DrgQueryStrName(DragItem.hstrTargetName, CCHMAXPATH, tbuf);
  874.             if (!tbuf[0])
  875.                 sprintf(tbuf,"%d.TMP",rand());
  876.             strcat(szName,tbuf);
  877.             pDragTransfer->hstrRenderToName = DrgAddStrHandle(szName);
  878. #if ODDebug
  879.             if (fDebugLogging)
  880.                 somPrintf("GDFDM: name is %s\n", szName);
  881. #endif
  882.         }
  883.         else
  884.             pDragTransfer->hstrRenderToName = 0;
  885.  
  886.         pDragTransfer->ulTargetInfo = (ULONG)pDragInfo;            // save the drag info pointer
  887.         pDragTransfer->usOperation = pDragInfo->usOperation;
  888.         pDragTransfer->fsReply = 0;
  889.  
  890.         // Send DM_RENDERPREPARE here if fsReply & DC_PREPARE
  891.         if (pDragItem->fsControl & DC_PREPARE)
  892.             if (!DrgSendTransferMsg(pDragInfo->hwndSource,
  893.                                    DM_RENDERPREPARE,
  894.                                    (MPARAM)pDragTransfer,
  895.                                    (MPARAM)NULL))
  896.                 fSuccess = kODFalse;
  897. #if ODDebug
  898.         if (fDebugLogging)
  899.         {
  900.             somPrintf("GDFDM: sending xfer - hwndClient: %08p\n", hwndClient);
  901.             somPrintf("GDFDM: sending xfer - DragItem.hwndItem: %08p\n", DragItem.hwndItem);
  902.             somPrintf("GDFDM: pdragitem: %08p\n", pDragItem);
  903.         }
  904. #endif
  905.  
  906.         // send transfer message:
  907.         _fRenderCompleteReceived = kODFalse;
  908.         MRESULT mr = DrgSendTransferMsg(pDragItem->hwndItem,
  909.                                         DM_RENDER,
  910.                                         (MPARAM)pDragTransfer,
  911.                                         (MPARAM)NULL);
  912.  
  913.         if (mr && fFile)
  914.         {     // [140007]
  915.             // see if the file exists; if it does, don't wait for DM_RENDERCOMPLETE
  916.             FILESTATUS3 fInfo;
  917.             if (DosQueryPathInfo(szName, FIL_STANDARD, &fInfo, sizeof(fInfo)) == NO_ERROR)
  918.                 mr = kODFalse;
  919.         }
  920.         if (mr)
  921.         {
  922.             // The source will render the data later on DM_RENDERCOMPLETE;
  923.             // here is where the Merlin guys spin on the message queue
  924.             // to accommodate the OpenDoc single thread design
  925. #if ODDebug
  926.             if (fDebugLogging)
  927.                 somPrintf("GDFDM: Waiting for DM_RENDERCOMPLETE\n");
  928. #endif
  929.             QMSG qmsg;
  930. //            HAB hab = WinQueryAnchorBlock(_fDestFacet->GetWindow(ev)->GetPlatformWindow(ev));
  931.  
  932.             //TDF: I bet this should get reset every time ...
  933.             //     otherwise, how do we know it has been initialized?
  934.             //     maybe it gets set in dmRenderComplete every time ...
  935.             _fRenderCompleteFlag = 0;
  936.  
  937.             while(!_fRenderCompleteReceived)
  938.             {
  939.                 if (WinPeekMsg(0L, &qmsg, 0L, 0, 0, PM_NOREMOVE))
  940.                 {
  941.                     if (!WinGetMsg(0L, &qmsg, 0L, 0, 0))
  942.                         break;
  943.                     if (qmsg.msg == DM_RENDERCOMPLETE)
  944.                     {
  945.                         _fRenderCompleteFlag = DMFL_RENDEROK;
  946.                         break;
  947.                     }
  948.                     WinDispatchMsg(0L,&qmsg);
  949.                 }
  950.             }
  951.  
  952.             if (_fRenderCompleteFlag != DMFL_RENDEROK)
  953.             {
  954.                 fSuccess = kODFalse;
  955. #if ODDebug
  956.                 if (fDebugLogging)
  957.                     somPrintf("GDFDM: flag != DMFL_RENDEROK\n");
  958. #endif
  959.             }
  960.             else
  961.             {
  962. #if ODDebug
  963.                 if (fDebugLogging)
  964.                     somPrintf("GDFDM: flag == DMFL_RENDEROK\n");
  965. #endif
  966.             }
  967.         }
  968.  
  969. #if ODDebug
  970.         if (fDebugLogging)
  971.             somPrintf("GDFDM: fSuccess: %X\n", fSuccess);
  972. #endif
  973.         // if render was successful, receive the data:
  974.         if (fSuccess)
  975.         {
  976. #if ODDebug
  977.             if (fDebugLogging)
  978.                 somPrintf("GDFDM: about to do receive\n");
  979. #endif
  980.             if (somSelf->dmDoReceive(ev, 
  981.                                      (PSZ)szSelectedRMF,
  982.                                      pDragTransfer->usOperation,
  983.                                      pDragTransfer->hstrRenderToName,
  984.                                      pDragItem->hstrType,
  985.                                      pszSelectedKind,
  986.                                      (ODPtr)newItem))
  987.             {
  988. #if ODDebug
  989.                 if (fDebugLogging)
  990.                     somPrintf("GDFDM: receive ok\n");
  991. #endif
  992. // [146814]
  993.                 if (!newItem->fSU->Exists(ev, kODPropMouseDownOffset, kODPoint, 0))
  994.                 {
  995.                     ODPoint offset;
  996.                     offset.x = MAKEFIXED(-pDragItem->cxOffset,0);
  997.                     offset.y = MAKEFIXED(-pDragItem->cyOffset,0);
  998.                     newItem->fSU->AddProperty(ev, kODPropMouseDownOffset)->AddValue(ev,(ODValueType)kODPoint);
  999.                     StorageUnitSetValue(newItem->fSU, ev,sizeof(Point), (ODValue)&offset);
  1000.                 }
  1001. // [146814] end
  1002.             }
  1003.             else
  1004.             {
  1005. #if ODDebug
  1006.                 if (fDebugLogging)
  1007.                     somPrintf("GDFDM: receive did not work\n");
  1008. #endif
  1009.                 fSuccess = kODFalse;
  1010.             }
  1011.         }
  1012.  
  1013.         // end the rendering conversation
  1014.         DrgSendTransferMsg(pDragItem->hwndItem,
  1015.                            DM_ENDCONVERSATION,
  1016.                            (MPARAM)pDragItem->ulItemID,
  1017.                            (fSuccess == kODTrue)
  1018.                                    ? (MPARAM)DMFL_TARGETSUCCESSFUL
  1019.                                    : (MPARAM)DMFL_TARGETFAIL);
  1020.  
  1021.         DrgFreeDragtransfer(pDragTransfer);
  1022.     }
  1023.  
  1024.     // clean up
  1025.     if (fSuccess == kODTrue)
  1026.     {
  1027.         _fDragGarbageList->AddLast(newLink);
  1028.         *renderedSU = newItem->fSU;
  1029.     }
  1030.     else
  1031.     {
  1032.         if (newItem) delete newItem;
  1033.     }
  1034.  
  1035. #if ODDebug
  1036.     if (fDebugLogging)
  1037.         somPrintf("GDFDM: returning to caller\n");
  1038. #endif
  1039.     return(fSuccess);
  1040. }
  1041.  
  1042. /*---------------------------------------------------------------------------
  1043.         ODDragAndDrop::somUninit
  1044. ---------------------------------------------------------------------------*/
  1045. SOM_Scope void  SOMLINK ODDragAndDropsomUninit(ODDragAndDrop *somSelf)
  1046. {
  1047.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1048.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropsomUninit");
  1049.  
  1050. //   DosCloseEventSem(_fHEVRenderComplete);
  1051.  
  1052.     if (_fDragItemList)
  1053.     {
  1054.         _fDragItemList->DeleteAllLinks();
  1055.         delete _fDragItemList;
  1056.     }
  1057.     if (_fDragGarbageList)
  1058.     {
  1059.         _fDragGarbageList->DeleteAllLinks();
  1060.         delete _fDragGarbageList;
  1061.     }
  1062.  
  1063.     if (_fDragItemIterator)
  1064.         delete _fDragItemIterator;
  1065. }
  1066.  
  1067. /*---------------------------------------------------------------------------
  1068.         ODDragAndDrop::Clear
  1069. ---------------------------------------------------------------------------*/
  1070. SOM_Scope void  SOMLINK ODDragAndDropClear(ODDragAndDrop *somSelf,
  1071.                                            Environment   *ev)
  1072. {
  1073.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1074.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropClear");
  1075.  
  1076.     _fPrevFacet = kODNULL; // [pfe] 123942
  1077.  
  1078. #if ODDebug
  1079.     if (fDebugLogging)
  1080.         somPrintf("Clear: _fDragItemIterator = %08p, _fDragItemList = %08p, _fDragGarbageList = %08p\n",
  1081.                   _fDragItemIterator, _fDragItemList, _fDragGarbageList);
  1082.  
  1083.     if (getenv("STACKCRAWL_CLEAR") != NULL)
  1084.     {
  1085.         StackCrawl stackCrawl;
  1086.         strstream stack;
  1087.         stackCrawl.DumpStack(0, 20, stack);
  1088.         somPrintf("\n%s", stack.str());
  1089.         stack.rdbuf()->freeze(0);
  1090.     }
  1091. #endif
  1092.  
  1093.     SOM_TRY
  1094.         if (_fDragItemIterator)
  1095.         {
  1096.             delete _fDragItemIterator;
  1097.             _fDragItemIterator = kODNULL;
  1098.         }
  1099.         _fDragItemList->DeleteAllLinks();
  1100.  
  1101.         if (_fDragGarbageList)
  1102.             _fDragGarbageList->DeleteAllLinks();
  1103.  
  1104.     SOM_CATCH_ALL
  1105.     SOM_ENDTRY
  1106.  
  1107.     _fulItemID = 0;
  1108. }
  1109.  
  1110. /*---------------------------------------------------------------------------
  1111.         ODDragAndDrop::GetContentStorageUnit
  1112. ---------------------------------------------------------------------------*/
  1113. SOM_Scope ODStorageUnit*  SOMLINK ODDragAndDropGetContentStorageUnit(
  1114.                                                     ODDragAndDrop *somSelf,
  1115.                                                     Environment   *ev)
  1116. {
  1117.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1118.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetContentStorageUnit");
  1119.  
  1120.     ODStorageUnit* contentSU = kODNULL;
  1121.  
  1122.     SOM_TRY
  1123.         ODMemDragItem        *newItem;
  1124.         ODDragLink           *newLink;
  1125.         DRAGITEM             DragItem;
  1126.         
  1127.         newItem = new(ODGetDefaultHeap()) ODMemDragItem(_fStorageSystem, kODFalse);
  1128.         ASSERT(newItem != kODNULL, kODErrCannotAllocateDragItem);
  1129.         newItem->Initialize(ev);
  1130.         newLink = new ODDragLink(newItem, kODTrue);
  1131.         if (!newLink)
  1132.         {
  1133.             delete newItem;
  1134.             ASSERT(newLink != kODNULL, kODErrCannotAllocateDragItem);
  1135.         }
  1136.         _fDragItemList->AddLast(newLink);
  1137.         contentSU = newItem->fSU;
  1138.  
  1139.         memset(&DragItem, 0, sizeof(DRAGITEM));
  1140.  
  1141.         // Can't set this field here... it will be set in StartDrag()
  1142.         // DragItem.hwndItem = hwndSource;
  1143.  
  1144.         DragItem.ulItemID = _fulItemID++;
  1145.         DragItem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
  1146.         DragItem.hstrRMF =
  1147.  
  1148.           // 126007 - don't show DRM_PRINT
  1149.           DrgAddStrHandle("(DRM_SHAREDMEM,DRM_OS2FILE,DRM_DISCARD)x(DRF_OPENDOCDOCUMENT)");
  1150. //          DrgAddStrHandle("(DRM_SHAREDMEM,DRM_OS2FILE,DRM_DISCARD,DRM_PRINT)x(DRF_OPENDOCDOCUMENT)");
  1151.  
  1152.         // DragItem.hstrContainerName = DrgAddStrHandle (""); // source rendering
  1153.         DragItem.hstrSourceName = DrgAddStrHandle(OPENDOC_FILENAME_DEFAULT);
  1154.         DragItem.hstrTargetName = DrgAddStrHandle(OPENDOC_FILENAME_DEFAULT);
  1155.         DragItem.cxOffset = 0;
  1156.         DragItem.cyOffset = 0;
  1157.         DragItem.fsControl = 0;
  1158.         DragItem.fsSupportedOps = DO_COPYABLE | DO_MOVEABLE;
  1159.  
  1160.         contentSU->AddProperty(ev, kODPropContents);
  1161.         contentSU->AddValue(ev, (ODValueType)kODDragitem);
  1162.         StorageUnitSetValue(contentSU, 
  1163.                             ev,
  1164.                             (ODULong) sizeof(DRAGITEM),
  1165.                             &DragItem);
  1166.     SOM_CATCH_ALL
  1167.     SOM_ENDTRY
  1168.  
  1169. #if ODDebug
  1170.     if (fDebugLogging)
  1171.         somPrintf("GCSU: returning SU %08p\n", contentSU);
  1172. #endif
  1173.     return contentSU;
  1174. }
  1175.  
  1176. /*---------------------------------------------------------------------------
  1177.         ODDragAndDrop::StartDrag
  1178. ---------------------------------------------------------------------------*/
  1179. SOM_Scope ODDropResult  SOMLINK ODDragAndDropStartDrag(ODDragAndDrop *somSelf,
  1180.                                                        Environment *ev,
  1181.                                                        ODFrame* srcFrame,
  1182.                                                        ODType imageType,
  1183.                                                        ODByteArray* image,
  1184.                                                        ODPart** destPart,
  1185.                                                        ODByteArray* refCon)
  1186. {
  1187.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1188.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropStartDrag");
  1189.  
  1190. #if ODDebug
  1191.     // reset DM_DRAGOVER counter
  1192.     counter = 0;
  1193.  
  1194.     // avoid reentrancy during testing:
  1195.     static int drag_in_progress = FALSE;
  1196.     if (drag_in_progress)
  1197.     {
  1198.         somPrintf("StartDrag: reentrancy flag set at entry!\n");
  1199.         return (kODDropFail);
  1200.     }
  1201.     else
  1202.         drag_in_progress = TRUE;
  1203. #endif
  1204.  
  1205.     // check for bad input:
  1206.     if ((srcFrame == kODNULL) ||                    // srcFrame must be != kODNULL
  1207.         (destPart == kODNULL) ||                    // destPart must be != kODNULL
  1208.         ((strncmp(imageType, kODOS2DragImage, strlen(kODOS2DragImage)) != 0)
  1209.          && (imageType != kODNULL)))                // imageType must be == kODOS2DragImage or == kODNULL
  1210.                                                     // (to support legacy OS/2 OpenDoc applications,
  1211.                                                     // imageType can be == kODNULL; this tolerance should
  1212.                                                     // go away in a future release!)
  1213. #if ODDebug
  1214.     {
  1215.         if (fDebugLogging)
  1216.             somPrintf("StartDrag: returning kODDropFail - parameter validation failed\n");
  1217.         drag_in_progress = FALSE;
  1218. #endif
  1219.         return(kODDropFail);
  1220. #if ODDebug
  1221.     }
  1222. #endif
  1223.  
  1224.     ASSERT(image != kODNULL, kODErrIllegalNullInput);
  1225.     ASSERT(refCon != kODNULL, kODErrIllegalNullInput);
  1226.  
  1227.     LinkedListIterator *theIter = kODNULL;
  1228.     HWND             hwndDrop   = kODNULL;       // Handle of drop window
  1229.     PDRAGINFO        pDragInfo;
  1230.     DRAGITEM         DragItem;
  1231.     PDRAGITEM        pDragItem;
  1232.     CHAR kindList[CCHMAXPATH];    // [140007]
  1233.     kindList[0] = 0;
  1234.     _fDropResult                = kODDropFail;
  1235.     _fAttributes                = 0;
  1236.     _fHasLeftSourceFrame        = kODFalse;
  1237.     _fSourceFrame               = srcFrame;
  1238.     _fDestFacet                 = kODNULL;
  1239.     _fPrevFacet                 = kODNULL;
  1240.     _fNeverDrop                 = kODFalse;
  1241.  
  1242.     _fSourcePart                = srcFrame->AcquirePart(ev);
  1243.  
  1244.     ODWindow * window           = srcFrame->AcquireWindow(ev);
  1245.  
  1246.     HWND hwndSource = WinWindowFromID(window->GetPlatformWindow(ev), FID_CLIENT);
  1247. #if ODDebug
  1248.     if (fDebugLogging)
  1249.         somPrintf("StartDrag: hwndSource = %08p\n", hwndSource);
  1250. #endif        
  1251.  
  1252.     ODReleaseObject(ev, window);
  1253.  
  1254.     TRY
  1255.  
  1256.         theIter            = new LinkedListIterator(_fDragItemList);
  1257.         
  1258.         _fDragItemIterator = new ODDragItemIterator();
  1259.         _fDragItemIterator->InitDragItemIterator(ev, theIter);
  1260.         
  1261.         ULONG cDitem = 0, index, ulTmp;
  1262.         ODDragLink *theDragLink;
  1263.         ODMemDragItem *theDragItem;
  1264.         ODStorageUnit *theSU;
  1265.         
  1266.         // Determine how many storage units we have been given
  1267.         // (In reality - there should only be one storage unit on an
  1268.         //  Opendoc initiated drag.)
  1269.         for (theDragLink = (ODDragLink*) theIter->First();
  1270.              theDragLink != kODNULL;
  1271.              theDragLink = (ODDragLink*) theIter->Next())
  1272.             cDitem++;              // bump count
  1273.         
  1274.         if (0 == cDitem)
  1275.         {
  1276. #if ODDebug
  1277.             if (fDebugLogging)
  1278.                 somPrintf("StartDrag: nothing selected\n");
  1279.             drag_in_progress = FALSE;
  1280. #endif        
  1281.             delete theIter;
  1282.             return(_fDropResult);
  1283.         }
  1284.  
  1285. #if ODDebug
  1286.         if (fDebugLogging)
  1287.             somPrintf("StartDrag: count of su's: %ld\n", cDitem);
  1288. #endif
  1289.  
  1290.         // alloc the pm drag info block
  1291.         pDragInfo = DrgAllocDraginfo(cDitem);
  1292.  
  1293.         // store it in our instance data
  1294.         _fDragInform = pDragInfo;
  1295.  
  1296.         // retrieve our dragitems from each storage unit, and set into
  1297.         // the draginfo struct.
  1298.         for (theDragLink = (ODDragLink*) theIter->First(), index = 0;
  1299.              theDragLink != kODNULL;
  1300.              theDragLink = (ODDragLink*) theIter->Next(), index++)
  1301.         {
  1302.             theSU = theDragLink->fItem->fSU;
  1303.  
  1304.                         // rrk 20mar97 - if we are read-only, don't export a linkspec
  1305.                         ODWindow *window = _fSession->GetWindowState(ev)->AcquireActiveWindow(ev);
  1306.                         if(window) {
  1307.                  ODDraft *theDraft = window->GetDraft(ev);
  1308.                       if (theDraft) {
  1309.                                ODBoolean isDraftReadOnly = (theDraft->GetPermissions(ev) == kODDPReadOnly);
  1310.                                //PRINT("ExportClipboard: isDraftReadOnly is %d.\n", isDraftReadOnly);
  1311.                                if (isDraftReadOnly)
  1312.                               if ( theSU->Exists(ev, kODPropLinkSpec, kODNULL, 0) )
  1313.                               ODSURemoveProperty(ev, theSU, kODPropLinkSpec);
  1314.             }
  1315.                            ODReleaseObject(ev,window);
  1316.                         }
  1317.  
  1318.             if (theSU->Exists(ev, kODPropContents, (ODValueType)kODDragitem, 0))
  1319.             {
  1320.                 theSU->Focus(ev,
  1321.                              kODPropContents,
  1322.                              kODPosUndefined,
  1323.                              (ODValueType)kODDragitem,
  1324.                              0,
  1325.                              kODPosUndefined);
  1326.                 StorageUnitGetValue(theSU,
  1327.                                     ev,
  1328.                                     sizeof(DRAGITEM),
  1329.                                     &DragItem);
  1330.                 // This is the one field we couldn't set in GetContentStorageUnit
  1331.                 DragItem.hwndItem = hwndSource;
  1332.  
  1333. //TDF Warning!  NASTY HACK!  See notes in Constants section at top of file:
  1334.                 // here's the nasty hack: if the cloneKind is Copy, change
  1335.                 // the case of the TargetName string handle on the dragitem:
  1336.                 ODCloneKind cloneKind = GetOriginalCloneKind(ev, theSU->GetDraft(ev));
  1337.                 if (cloneKind == kODCloneCopy)
  1338.                     DragItem.hstrTargetName = DrgAddStrHandle(OPENDOC_FILENAME_FOR_CLONECOPY);
  1339. //TDF:  end of NASTY HACK!
  1340. #if ODDebug
  1341.                 if (fDebugLogging)
  1342.                     somPrintf("StartDrag: storing DrgItem.hwndItem: %08p \n", hwndSource);
  1343. #endif
  1344. // [140007] :
  1345.                 kindList[0] = 0;
  1346.                 for (ODValueIndex valueIndex = 1;
  1347.                      theSU->Exists(ev, kODPropContents,(ODValueType)kODNULL,valueIndex);
  1348.                      valueIndex++)
  1349.                 {
  1350.                     theSU->Focus(ev,
  1351.                                  kODPropContents,
  1352.                                  kODPosSame,
  1353.                                  (ODValueType)kODNULL,
  1354.                                  valueIndex,
  1355.                                  kODPosSame);
  1356.                     PSZ kind = theSU->GetType(ev);
  1357.  
  1358.                     if (!strcmp(kind, kODDragitem)        ||
  1359.                         !strcmp(kind, kODDragOperation)    ||
  1360.                         !strcmp(kind, kODSelectedKind)    ||
  1361.                         !strcmp(kind, kODSelectedRMF)    ||
  1362.                         !strcmp(kind, kODFileType)        ||
  1363.                         !strcmp(kind, kODFileTypeEA))
  1364.                       continue;
  1365.  
  1366.                     if (strlen(kindList))
  1367.                       strcat(kindList,",");
  1368.  
  1369.                     strcat(kindList,kind);
  1370.                 }
  1371.                 if (strlen(kindList))
  1372. #if ODDebug
  1373.                 {
  1374.                     if (fDebugLogging)
  1375.                         somPrintf("StartDrag: kindList is \"%s\"\n", kindList);
  1376. #endif
  1377.                     DragItem.hstrType = DrgAddStrHandle(kindList);
  1378. #if ODDebug
  1379.                 }
  1380. #endif
  1381.  
  1382.                 theSU->Focus(ev,
  1383.                              kODPropContents,
  1384.                              kODPosUndefined,
  1385.                              (ODValueType)kODDragitem,
  1386.                              0,
  1387.                              kODPosUndefined);
  1388. // [140007] end
  1389.                 DrgSetDragitem(pDragInfo, &DragItem, sizeof(DRAGITEM), index);
  1390.  
  1391.                 theSU->SetOffset(ev, 0);
  1392.                 StorageUnitSetValue(theSU,
  1393.                                     ev,
  1394.                                     (ODULong) sizeof(DRAGITEM),
  1395.                                     &DragItem);
  1396.                 ulTmp = (ULONG)DrgQueryDragitemPtr(pDragInfo, index);
  1397.                 theSU->SetOffset(ev, sizeof(DRAGITEM));
  1398.                 StorageUnitSetValue(theSU,
  1399.                                     ev,
  1400.                                     (ODULong) sizeof(PDRAGITEM),
  1401.                                     &ulTmp);
  1402.             }
  1403. #if ODDebug
  1404.             else
  1405.             {
  1406.                 // panic
  1407.                 if (fDebugLogging)
  1408.                     somPrintf("StartDrag: panic - storage unit value type kODDragitem doesn't exist\n");
  1409.             }
  1410. #endif
  1411.         }
  1412.         hwndDrop = DrgDrag(hwndSource,
  1413.                            pDragInfo,
  1414.                            (PDRAGIMAGE)image->_buffer,
  1415.                            1,
  1416.                            VK_ENDDRAG,
  1417.                            0);
  1418.  
  1419. #if ODDebug
  1420.         if (fDebugLogging)
  1421.             somPrintf("StartDrag: back from DrgDrag: hwndDrop == %08p\n", hwndDrop);
  1422. #endif
  1423.  
  1424.         // 146002 - store draginfo in our instance data again, as it can be
  1425.         // changed (zeroed) for interprocess drag and drops
  1426.         _fDragInform = pDragInfo;                 // 146002
  1427.  
  1428.         // Later - when we post ourselves a WM_PROCESSDROP message to get
  1429.         // off the PM win input thread, we will need to move this stuff
  1430.         // to the place where the render actually takes place and just
  1431.         // fall thru here....
  1432.  
  1433.         if (!hwndDrop)
  1434.         {
  1435.             DrgFreeDraginfo((PDRAGINFO)_fDragInform);
  1436.             _fDragInform = 0;
  1437.         }
  1438.  
  1439.         if (hwndDrop && _fDragInform)
  1440.         {
  1441.             switch (((PDRAGINFO)_fDragInform)->usOperation)
  1442.             {
  1443.                 case DO_MOVE:
  1444. #if ODDebug
  1445.                     if (fDebugLogging)
  1446.                         somPrintf("StartDrag: A move operation (0x%04X) was requested by the drag target.\n",
  1447.                                   ((PDRAGINFO)_fDragInform)->usOperation);
  1448. #endif
  1449.                     _fDropResult = kODDropMove;
  1450.                     break;
  1451.                 
  1452.                 case DO_LINK:            // [145338]
  1453. #if ODDebug
  1454.                     if (fDebugLogging)
  1455.                         somPrintf("StartDrag: A link operation (0x%04X) was requested by the drag target.\n",
  1456.                                   ((PDRAGINFO)_fDragInform)->usOperation);
  1457. #endif
  1458.                     _fDropResult = kODDropLink;
  1459.                     break;
  1460.                 
  1461.                 default:
  1462. #if ODDebug
  1463.                     if (fDebugLogging)
  1464.                         somPrintf("StartDrag: A non- move, link, copy or create operation (0x%04X) was\n"
  1465.                                   "           requested by the drag target - treat as a copy\n",
  1466.                                   ((PDRAGINFO)_fDragInform)->usOperation);
  1467.                                   
  1468. #endif
  1469.                 case DO_COPY:
  1470.                 case DO_CREATE:
  1471. #if ODDebug
  1472.                     if (fDebugLogging)
  1473.                         somPrintf("StartDrag: A copy operation (0x%04X) was requested by the drag target.\n",
  1474.                                   ((PDRAGINFO)_fDragInform)->usOperation);
  1475. #endif
  1476.                     _fDropResult = kODDropCopy;
  1477.                     break;
  1478.             }
  1479.         }
  1480.         else
  1481.             _fDropResult = kODDropFail;
  1482.  
  1483.         // need to check pid of drop window against this pid,
  1484.         // set destpart to -1 if not the same, otherwise caller thinks
  1485.         // it was a nop.
  1486.         PID pid;
  1487.         TID tid;
  1488.         PTIB pptib;
  1489.         PPIB pppib;
  1490.  
  1491.         WinQueryWindowProcess(hwndDrop, &pid, &tid);
  1492.         DosGetInfoBlocks(&pptib, &pppib);
  1493.  
  1494.         //  if the pids don't match, then another process
  1495.         //  handled the drop - so I guess this code is here
  1496.         //  just to bump the reference count?  It's from DR4 ...
  1497.         if ((pid == pppib->pib_ulpid) && (_fDestFacet))
  1498.             *destPart = _fDestFacet->GetFrame(ev)->AcquirePart(ev);
  1499.         else
  1500.             *destPart = kODNULL;
  1501.  
  1502. #ifdef ASYNCHRONOUS_DRAGGING_SUPPORTED
  1503. // This call to DropCompleted has been #ifdef'd out because it can
  1504. // lead to refcount problems on parts.  Parts written for OS/2 don't
  1505. // expect to have both Drop and DropCompleted called, so until OS/2
  1506. // asynchronous dragging has been properly designed and implemented,
  1507. // we should not call DropCompleted on OS/2 OpenDoc parts.
  1508. #if ODDebug
  1509.         if (fDebugLogging)
  1510.             somPrintf("StartDrag: calling DropCompleted on source part...\n");
  1511. #endif
  1512.         _fSourcePart->DropCompleted(ev, *destPart, _fDropResult);
  1513. #endif // ASYNCHRONOUS_DRAGGING_SUPPORTED
  1514.  
  1515.         if (_fDragInform)
  1516.         {
  1517.             DrgFreeDraginfo((PDRAGINFO)_fDragInform);
  1518.             _fDragInform = kODNULL;
  1519.         }
  1520.  
  1521.         _fDragItem      = kODNULL;
  1522.         _fDragReference = kODNULL;
  1523.         _fDragOperation = kODNULL;
  1524.         _fSourceFrame   = kODNULL;
  1525.         ODReleaseObject(ev, _fSourcePart);
  1526.         _fDestFacet     = kODNULL;
  1527.  
  1528.         if (theIter)
  1529.         {
  1530.             delete theIter;
  1531.             theIter = kODNULL;
  1532.         }
  1533.  
  1534.         somSelf->Clear(ev);
  1535.  
  1536.     CATCH_ALL
  1537.  
  1538.         if (theIter)
  1539.             delete theIter;
  1540.  
  1541.     RERAISE;
  1542.  
  1543.     ENDTRY
  1544.  
  1545. #if ODDebug
  1546.     if (fDebugLogging)
  1547.         somPrintf("StartDrag: returning %d\n", _fDropResult);
  1548.     drag_in_progress = FALSE;
  1549. #endif        
  1550.     return _fDropResult;
  1551. }
  1552.  
  1553. SOM_Scope LinkedList*  SOMLINK ODDragAndDropGetDragItemList(ODDragAndDrop *somSelf, Environment *ev)
  1554. {
  1555.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1556.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemList");
  1557.  
  1558.   return _fDragItemList;
  1559. }
  1560.  
  1561. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemList(ODDragAndDrop *somSelf, Environment *ev,
  1562.     LinkedList* list)
  1563. {
  1564.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1565.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemList");
  1566.  
  1567.   _fDragItemList = list;
  1568. }
  1569.  
  1570. SOM_Scope ODBoolean  SOMLINK ODDragAndDropGetListFromHandler(ODDragAndDrop *somSelf, Environment *ev)
  1571. {
  1572.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1573.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetListFromHandler");
  1574.  
  1575.     return _fListFromHandler;
  1576. }
  1577.  
  1578. SOM_Scope void  SOMLINK ODDragAndDropSetListFromHandler(ODDragAndDrop *somSelf, Environment *ev,
  1579.     ODBoolean listFromHandler)
  1580. {
  1581.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1582.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetListFromHandler");
  1583.  
  1584.   _fListFromHandler = listFromHandler;
  1585. }
  1586.  
  1587. SOM_Scope ODFrame*  SOMLINK ODDragAndDropGetSourceFrame(ODDragAndDrop *somSelf, Environment *ev)
  1588. {
  1589.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1590.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourceFrame");
  1591.  
  1592.   return _fSourceFrame;
  1593. }
  1594.  
  1595. SOM_Scope void  SOMLINK ODDragAndDropSetSourceFrame(ODDragAndDrop *somSelf, Environment *ev,
  1596.     ODFrame* sourceFrame)
  1597. {
  1598.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1599.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourceFrame");
  1600.  
  1601.   _fSourceFrame = sourceFrame;
  1602. }
  1603.  
  1604. SOM_Scope ODULong  SOMLINK ODDragAndDropGetAttributes(ODDragAndDrop *somSelf, Environment *ev)
  1605. {
  1606.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1607.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetAttributes");
  1608.  
  1609.   return _fAttributes;
  1610. }
  1611.  
  1612. SOM_Scope void  SOMLINK ODDragAndDropSetAttributes(ODDragAndDrop *somSelf, Environment *ev,
  1613.     ODULong attr)
  1614. {
  1615.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1616.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetAttributes");
  1617.  
  1618.   _fAttributes = attr;
  1619. }
  1620.  
  1621. SOM_Scope ODPart*  SOMLINK ODDragAndDropGetSourcePart(ODDragAndDrop *somSelf, Environment *ev)
  1622. {
  1623.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1624.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourcePart");
  1625.  
  1626.   return _fSourcePart;
  1627. }
  1628.  
  1629. SOM_Scope void  SOMLINK ODDragAndDropSetSourcePart(ODDragAndDrop *somSelf, Environment *ev,
  1630.     ODPart* sourcePart)
  1631. {
  1632.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1633.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourcePart");
  1634.  
  1635.   _fSourcePart = sourcePart;
  1636. }
  1637.  
  1638. SOM_Scope ODDragItemIterator*  SOMLINK ODDragAndDropGetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev)
  1639. {
  1640.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1641.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemIterator");
  1642.  
  1643.   return _fDragItemIterator;
  1644. }
  1645.  
  1646. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev,
  1647.     ODDragItemIterator* iter)
  1648. {
  1649.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1650.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemIterator");
  1651.  
  1652.   _fDragItemIterator = iter;
  1653. }
  1654.  
  1655. SOM_Scope ODSession*  SOMLINK ODDragAndDropGetSession(ODDragAndDrop *somSelf, Environment *ev)
  1656. {
  1657.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1658.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSession");
  1659.  
  1660.   return _fSession;
  1661. }
  1662.  
  1663. SOM_Scope ODStorageSystem*  SOMLINK ODDragAndDropGetStorageSystem(ODDragAndDrop *somSelf, Environment *ev)
  1664. {
  1665.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1666.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetStorageSystem");
  1667.  
  1668.   return _fStorageSystem;
  1669. }
  1670.  
  1671. SOM_Scope void  SOMLINK ODDragAndDropSetDragReference(ODDragAndDrop *somSelf, Environment *ev,
  1672.     ODPlatformDragReference dragReference)
  1673. {
  1674.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1675.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragReference");
  1676.  
  1677.   _fDragReference = dragReference;
  1678. }
  1679.  
  1680. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetPrevFacet(ODDragAndDrop *somSelf, Environment *ev)
  1681. {
  1682.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1683.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPrevFacet");
  1684.  
  1685.   return _fPrevFacet;
  1686. }
  1687.  
  1688. SOM_Scope void  SOMLINK ODDragAndDropSetPrevFacet(ODDragAndDrop *somSelf, Environment *ev,
  1689.     ODFacet* prevFacet)
  1690. {
  1691.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1692.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetPrevFacet");
  1693.  
  1694.   _fPrevFacet = prevFacet;
  1695. }
  1696.  
  1697. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetDestFacet(ODDragAndDrop *somSelf, Environment *ev)
  1698. {
  1699.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1700.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDestFacet");
  1701.  
  1702.   return _fDestFacet;
  1703. }
  1704.  
  1705. SOM_Scope void  SOMLINK ODDragAndDropSetDestFacet(ODDragAndDrop *somSelf, Environment *ev,
  1706.     ODFacet* destFacet)
  1707. {
  1708.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1709.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDestFacet");
  1710.  
  1711.   _fDestFacet = destFacet;
  1712. }
  1713.  
  1714. SOM_Scope ODDropResult  SOMLINK ODDragAndDropGetDropResult(ODDragAndDrop *somSelf, Environment *ev)
  1715. {
  1716.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1717.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1718.  
  1719.   return _fDropResult;
  1720. }
  1721.  
  1722. SOM_Scope void  SOMLINK ODDragAndDropSetDropResult(ODDragAndDrop *somSelf, Environment *ev,
  1723.     ODDropResult dropResult)
  1724. {
  1725.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1726.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDropResult");
  1727.  
  1728.   _fDropResult = dropResult;
  1729. }
  1730.  
  1731. /*---------------------------------------------------------------------------
  1732.         ODDragAndDrop::DispatchHandler
  1733. ---------------------------------------------------------------------------*/
  1734. SOM_Scope ODBoolean SOMLINK ODDragAndDropDispatchHandler(ODDragAndDrop *somSelf,
  1735.                                                          Environment   *ev,
  1736.                                                          ODEventData   *evt,
  1737.                                                          ODFacet* targetfacet)
  1738. {
  1739.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1740.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropDispatchHandler");
  1741.  
  1742.     ODBoolean fHandled = FALSE;
  1743.  
  1744.     switch (evt->msg)
  1745.     {
  1746.         case DM_DISCARDOBJECT:
  1747.           fHandled = somSelf->dmDiscardObject(ev, evt);
  1748.           break;
  1749.  
  1750.         case DM_DRAGERROR:
  1751.           fHandled = somSelf->dmDragError(ev, evt);
  1752.           break;
  1753.  
  1754.         case DM_DRAGLEAVE:
  1755.           fHandled = somSelf->dmDragLeave(ev, evt);
  1756.           break;
  1757.  
  1758.         case DM_DRAGOVER:
  1759.           fHandled = somSelf->dmDragOver(ev, evt, targetfacet);   // [138899] - ced
  1760.           break;
  1761.  
  1762.         case DM_DRAGOVERNOTIFY:
  1763.           fHandled = somSelf->dmDragOverNotify(ev, evt);
  1764.           break;
  1765.  
  1766.         case DM_DROP:
  1767.           fHandled = somSelf->dmDrop(ev, evt);
  1768.           break;
  1769.  
  1770.         case DM_DROPHELP:
  1771.           fHandled = somSelf->dmDropHelp(ev, evt);
  1772.           break;
  1773.  
  1774.         case DM_ENDCONVERSATION:
  1775.           fHandled = somSelf->dmEndConversation(ev, evt);
  1776.           break;
  1777.  
  1778.         case DM_PRINTOBJECT:
  1779.           fHandled = somSelf->dmPrintObject(ev, evt);
  1780.           break;
  1781.  
  1782.         case DM_RENDER:
  1783.           fHandled = somSelf->dmRender(ev, evt);
  1784.           break;
  1785.  
  1786.         case DM_RENDERCOMPLETE:
  1787.           fHandled = somSelf->dmRenderComplete(ev, evt);
  1788.           break;
  1789.  
  1790.         case DM_RENDERPREPARE:
  1791.           fHandled = somSelf->dmRenderPrepare(ev, evt);
  1792.           break;
  1793.  
  1794.         default:
  1795.           break;
  1796.     }
  1797.    return(fHandled ? TRUE : FALSE);
  1798. }
  1799.  
  1800. /*---------------------------------------------------------------------------
  1801.         ODDragAndDrop::dmDiscardObject
  1802. ---------------------------------------------------------------------------*/
  1803. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmDiscardObject(
  1804.                                   ODDragAndDrop *somSelf,
  1805.                                   Environment   *ev,
  1806.                                   ODEventData   *evt)
  1807. {
  1808.    ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1809.    ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmDiscardObject");
  1810.  
  1811.    evt->result = (MRESULT)DRR_ABORT;
  1812.    return(TRUE);
  1813. }
  1814.  
  1815. /*---------------------------------------------------------------------------
  1816.         ODDragAndDrop::dmDoReceive
  1817. ---------------------------------------------------------------------------*/
  1818. SOM_Scope ODBoolean  SOMLINK ODDragAndDropdmDoReceive(ODDragAndDrop *somSelf,
  1819.                                                       Environment *ev,
  1820.                                                       ODPtr    pszSelectedRMF,
  1821.                                                       ODUShort usOperation,
  1822.                                                       ODULong  hstrRenderToName,
  1823.                                                       ODULong  hstrType,
  1824.                                                       ODPtr    pszSelectedKind,
  1825.                                                       ODPtr    dragItem)
  1826. {
  1827.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1828.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmDoReceive");
  1829.  
  1830. #if ODDebug
  1831.     if (fDebugLogging)
  1832.         somPrintf("in doReceive\n");
  1833. #endif
  1834.  
  1835.     PBYTE pData;
  1836.     ODBoolean fSuccess = FALSE;
  1837.     CHAR  szFile[CCHMAXPATH];
  1838.     CHAR  szSubject[CCHMAXPATH];
  1839.     ULONG rc;
  1840.     HFILE  hFile;
  1841.     ULONG  ulAction, ulBytes;
  1842.     FILESTATUS3 FileInfoBuf;
  1843.     PBYTE pbData;
  1844.     PULONG pulData;
  1845.     ULONG  dataSize;
  1846.     ODMemDragItem *theDragItem = (ODMemDragItem *)dragItem;
  1847.  
  1848.     if (!strcmp((PSZ)pszSelectedRMF, "<DRM_SHAREDMEM,DRF_OPENDOCDOCUMENT>"))
  1849.     {
  1850.         pbData = (PBYTE) hstrRenderToName;
  1851. #if ODDebug
  1852.         if (fDebugLogging)
  1853.             somPrintf("format == pointer, address = %08p\n", pbData);
  1854. #endif
  1855.  
  1856.         // no need to issue DosGetSharedMem here - it was given by source
  1857.         pulData = (PULONG)pbData;
  1858.         dataSize = *pulData;
  1859.  
  1860.         theDragItem->Close(ev);    // [142637] - ced
  1861.  
  1862.         theDragItem->fContainerHandle = ODNewHandle(dataSize);
  1863.  
  1864.         memcpy(*((ODHandle)theDragItem->fContainerHandle),
  1865.                pbData + sizeof(ULONG),
  1866.                dataSize);
  1867.  
  1868.         DosFreeMem(pbData);
  1869.  
  1870.         fSuccess = kODTrue;
  1871.  
  1872.         TRY
  1873.             theDragItem->Open(ev);
  1874.         CATCH_ALL
  1875.             fSuccess = kODFalse;
  1876.         ENDTRY
  1877.     }
  1878.     else
  1879.         if (!strcmp((PSZ)pszSelectedRMF, "<DRM_OS2FILE,DRF_OPENDOCDOCUMENT>"))
  1880.         {
  1881.             szFile[0] = 0;
  1882.             DrgQueryStrName (hstrRenderToName, CCHMAXPATH, szFile);
  1883. #if ODDebug
  1884.             if (fDebugLogging)
  1885.                 somPrintf("format = file: (%s)\n", szFile);
  1886. #endif
  1887.  
  1888.             rc = DosOpen(szFile,
  1889.                          &hFile,
  1890.                          &ulAction,
  1891.                          0,
  1892.                          FILE_NORMAL,
  1893.                          OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
  1894.                          OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
  1895.                          0);
  1896.             if (rc)
  1897.             {
  1898. #if ODDebug
  1899.                 if (fDebugLogging)
  1900.                     somPrintf("open failed: %d - (%s)\n", rc, szFile);
  1901. #endif
  1902.                 fSuccess = FALSE;
  1903.             }
  1904.             else
  1905.             {
  1906.                 DosQueryFileInfo(hFile, 1, &FileInfoBuf, sizeof(FileInfoBuf));
  1907.  
  1908.                 theDragItem->Close(ev);           // [142637] - ced
  1909.  
  1910.                 theDragItem->fContainerHandle = ODNewHandle(FileInfoBuf.cbFile);
  1911.  
  1912.                 rc = DosRead(hFile,
  1913.                              *((ODHandle)theDragItem->fContainerHandle),
  1914.                              FileInfoBuf.cbFile,
  1915.                              &ulBytes);
  1916. #if ODDebug
  1917.                 if (fDebugLogging)
  1918.                     somPrintf("read: rc = %ld - bytes = %ld\n", rc, FileInfoBuf.cbFile);
  1919. #endif
  1920.                 DosClose(hFile);
  1921.  
  1922.                 fSuccess = kODTrue;
  1923.                 TRY
  1924.                     theDragItem->Open(ev);
  1925.                 CATCH_ALL
  1926.                     fSuccess = kODFalse;
  1927.                 ENDTRY
  1928.             }
  1929.         }
  1930.         else
  1931.             if (!strncmp((PSZ)pszSelectedRMF, "<DRM_OS2FILE",12)) // [140007]
  1932.             {
  1933.                 szFile[0] = 0;
  1934.                 DrgQueryStrName (hstrRenderToName, CCHMAXPATH, szFile);
  1935. #if ODDebug
  1936.                 if (fDebugLogging)
  1937.                     somPrintf("unknown format = file: (%s)\n", szFile);
  1938. #endif
  1939.  
  1940.                 theDragItem->fSU->AddProperty(ev, kODPropContents);
  1941.                 if (pszSelectedKind)
  1942.                 {
  1943.                     theDragItem->fSU->AddValue(ev, (ODValueType)pszSelectedKind);
  1944.                 }
  1945.                 theDragItem->fSU->AddValue(ev, (ODValueType)kODFileType);
  1946.                 StorageUnitSetValue(theDragItem->fSU,
  1947.                                     ev,
  1948.                                     (ODULong)strlen(szFile) + 1,
  1949.                                     szFile);
  1950.  
  1951.                 szSubject[0] = 0;
  1952.                 if (!GetEAFromName(szFile, ".TYPE", NULL, szSubject))
  1953.                     DrgQueryStrName (hstrType, CCHMAXPATH, szSubject);
  1954.                 if (szSubject[0])
  1955.                 {
  1956.                     theDragItem->fSU->AddValue(ev, (ODValueType)kODFileTypeEA);
  1957.                     StorageUnitSetValue(theDragItem->fSU,
  1958.                                         ev,
  1959.                                         (ODULong)sizeof(szSubject),
  1960.                                         szSubject);
  1961.                 }
  1962.                 theDragItem->fSU->AddValue(ev, kODSelectedRMF);
  1963.                 StorageUnitSetValue(theDragItem->fSU,
  1964.                                     ev,
  1965.                                     (ODULong)strlen((PSZ)pszSelectedRMF) + 1,
  1966.                                     pszSelectedRMF);
  1967.                 theDragItem->fSU->AddValue(ev, (ODValueType)kODDragOperation);
  1968.                 StorageUnitSetValue(theDragItem->fSU,
  1969.                                     ev,
  1970.                                     (ODULong)sizeof(USHORT),
  1971.                                     &usOperation);
  1972.  
  1973.                 fSuccess = TRUE;
  1974.             }
  1975.             else
  1976.                 if (!strncmp((PSZ)pszSelectedRMF, "<DRM_SHAREDMEM",14)) // [140007]
  1977.                 {
  1978.                     // This must be a 'part-specific' format. just add a
  1979.                     // value for it.
  1980.                     // NOTE: I am assuming this is an in memory transfer...
  1981. #if ODDebug
  1982.                     if (fDebugLogging)
  1983.                         somPrintf("special format = (%s)\n", pszSelectedRMF);
  1984. #endif
  1985.  
  1986.                     theDragItem->fSU->AddProperty(ev, kODPropContents);
  1987.                     theDragItem->fSU->AddValue(ev, (ODValueType)pszSelectedRMF);
  1988.  
  1989.                     pbData = (PBYTE) hstrRenderToName;
  1990. #if ODDebug
  1991.                     if (fDebugLogging)
  1992.                         somPrintf("address = %08p\n", pbData);
  1993. #endif
  1994.  
  1995.                     // no need to issue DosGetSharedMem here -
  1996.                     // it was given by source
  1997.                     pulData = (PULONG)pbData;
  1998.                     dataSize = *pulData;
  1999.  
  2000.                     StorageUnitSetValue(theDragItem->fSU,
  2001.                                         ev,
  2002.                                         (ODULong)dataSize,
  2003.                                         pbData + sizeof(ULONG));
  2004.  
  2005.                     fSuccess = TRUE;
  2006.                 }
  2007.  
  2008.     return fSuccess;
  2009. }
  2010.  
  2011. /*---------------------------------------------------------------------------
  2012.         ODDragAndDrop::dmDrop
  2013. ---------------------------------------------------------------------------*/
  2014. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmDrop(ODDragAndDrop *somSelf,
  2015.                                                 Environment   *ev,
  2016.                                                 ODEventData   *evt)
  2017. {
  2018.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2019.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmDrop");
  2020.  
  2021.     ODPoint      localMouse;
  2022.     POINTL       mouse;
  2023.     PDRAGINFO    pDragInfo = (PDRAGINFO)evt->mp1;
  2024.     ODFacet      *targetFacet;
  2025.     ODDropResult dropResult = kODDropFail;
  2026.  
  2027. #if ODDebug
  2028.     if (fDebugLogging)
  2029.         somPrintf("dmDrop (entry): hwndTarget = %08p, usOperation = 0x%08X,"
  2030.                   " _fAttributes = 0x%08X\n",
  2031.                   evt->hwnd, pDragInfo->usOperation, _fAttributes);
  2032. #endif
  2033.  
  2034.     mouse.x = pDragInfo->xDrop;
  2035.     mouse.y = pDragInfo->yDrop;
  2036. // [138899] begin - ced
  2037.     WinMapWindowPoints(HWND_DESKTOP, evt->hwnd, &mouse, 1);
  2038.     localMouse.x = MAKEFIXED(mouse.x,0);
  2039.     localMouse.y = MAKEFIXED(mouse.y,0);
  2040.  
  2041. //TDF:  hmm ... investigate re-enabling this code:
  2042. //
  2043. //    targetFacet = somSelf->FindTargetFacet(ev,
  2044. //                               WinQueryWindow(evt->hwnd, QW_PARENT),
  2045. //                               &mouse, &localMouse);
  2046. //    
  2047. //    _fDestFacet = targetFacet;
  2048. //    _fLocalMouse = localMouse;
  2049.     targetFacet = _fPrevFacet;
  2050. // [138899] end - ced
  2051.  
  2052. #ifdef    PORTABILITY_HACK
  2053. // OK - read long, boring 'design change' comment in header for
  2054. // the rationale behind this nasty hack:
  2055.  
  2056.     LinkedListIterator             *theIter        = kODNULL;
  2057.     ODDragLink                    *theDragLink;
  2058.     ODStorageUnit                *dragitemSU;
  2059.     ODStorageUnit                *renderedSU;
  2060.     int                            count            = 0;
  2061.  
  2062.     //  Scan through all items in the drag and convert each one
  2063.     //  via GetDataFromDragManager
  2064.     theIter            = new LinkedListIterator(_fDragItemList);
  2065.     _fDragItemIterator = new ODDragItemIterator();
  2066.     _fDragItemIterator->InitDragItemIterator(ev, theIter);
  2067.     for (theDragLink = (ODDragLink*)theIter->First();
  2068.          theDragLink != kODNULL;
  2069.          theDragLink = (ODDragLink*)theIter->Next())
  2070.     {
  2071.         count++;
  2072. #if ODDebug
  2073.         if (fDebugLogging)
  2074.             somPrintf("dmDrop: drag link %d: %08p\n", count, theDragLink);
  2075. #endif
  2076.  
  2077.         //  alias the current storage unit
  2078.         dragitemSU = theDragLink->fItem->fSU;
  2079. #if ODDebug
  2080.         if (fDebugLogging)
  2081.             somPrintf("dmDrop: dragitemSU %d: %08p\n", count, dragitemSU);
  2082. #endif
  2083.  
  2084.         // now: focus on the DRAGITEM
  2085.         dragitemSU->Focus(ev,
  2086.                           kODPropContents,
  2087.                           kODPosUndefined,
  2088.                           (ODValueType)kODDragitem,
  2089.                           0,
  2090.                           kODPosUndefined);
  2091.         
  2092.         // create a view on the dragitem storage unit
  2093.         ODStorageUnitView *unitView = dragitemSU->CreateView(ev);
  2094.         
  2095.         // now get the real data (will be added to _fDragGarbageList)
  2096.         if (!somSelf->GetDataFromDragManager(ev, unitView, &renderedSU))
  2097.         {
  2098. #if ODDebug
  2099.             if (fDebugLogging)
  2100.                 somPrintf("dmDrop: GDFDM returned FALSE\n");
  2101. #endif
  2102.             continue;
  2103.         }
  2104.     }
  2105.     delete theIter;
  2106.  
  2107.     // now, create iterator over _fDragGarbageList to let part
  2108.     // have that iterator instead of _fDragItemIterator:
  2109.     ODDragItemIterator *DragGarbageIterator;
  2110.     theIter = new LinkedListIterator(_fDragGarbageList);
  2111.     DragGarbageIterator = new ODDragItemIterator();
  2112.     DragGarbageIterator->InitDragItemIterator(ev, theIter);
  2113. #endif // PORTABILITY_HACK
  2114.  
  2115. #ifdef MERLIN_CODE
  2116.     // Note: this really needs to be cleaned up to mimic what Apple is doing.
  2117.  
  2118.     //TDF:    my interpretation of this code is as follows:
  2119.     //
  2120.     //  If the dragged content has been dropped in a draft other than the
  2121.     //  source draft, then the current state of the modifier keys completely
  2122.     //  determines the type of drop (link, move or copy).  If the dragged
  2123.     //  content has been dropped in the source draft, then the type of drop
  2124.     //  is determined by the DragInfo operation field as was received by
  2125.     //  the DM_DROP message, ignoring the current state of the modifier keys
  2126.     //  (note, however, that the modifier key states previously determined
  2127.     //  the operation that was passed to DM_DROP)
  2128.  
  2129.     //  first, clear any move, copy, link and paste as attributes that may be
  2130.     //  left over from when they were set during DM_DRAGOVERs ... now that we
  2131.     //  have been dropped on, we will redetermine these attributes since the
  2132.     //  drag operation is in its final state:
  2133.     _fAttributes &= ~(kODDropIsMove | kODDropIsCopy | kODDropIsLink | kODDropIsPasteAs);
  2134.  
  2135.     // Are we going across Drafts?
  2136.     if ((_fSourcePart == kODNULL) ||
  2137.         (_fPrevFacet->GetFrame(ev)->GetStorageUnit(ev)->GetDraft(ev) !=
  2138.          _fSourcePart->GetStorageUnit(ev)->GetDraft(ev)))
  2139.     {
  2140.         if (key_shift(VK_SHIFT))
  2141.         {
  2142.             if (key_shift(VK_CTRL))
  2143.                 _fAttributes |= kODDropIsLink;
  2144.             else
  2145.                 _fAttributes |= kODDropIsMove;
  2146.         }
  2147.         else
  2148.             _fAttributes |= kODDropIsCopy;
  2149.     }
  2150.     else
  2151.     {
  2152.         switch (pDragInfo->usOperation)
  2153.         {
  2154.             case DO_LINK:
  2155.               _fAttributes |= kODDropIsLink;
  2156.               break;
  2157.  
  2158.             case DO_MOVE:
  2159.               _fAttributes |= kODDropIsMove;
  2160.               break;
  2161.  
  2162.             case DO_COPY:
  2163.             default:
  2164.               _fAttributes |= kODDropIsCopy;
  2165.               break;
  2166.         }
  2167.     }
  2168.  
  2169.     if (key_shift(VK_ALT))
  2170.     {
  2171.         _fAttributes |= kODDropIsPasteAs;
  2172.     }
  2173. #endif //MERLIN_CODE
  2174.  
  2175.     //  grab the target part to allow us to determine whether or not
  2176.     //  the target of the drop is the same as the source of the drop
  2177.     //  (use TempODPart to complement call to AcquirePart)
  2178.     TempODPart targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2179.  
  2180.     //  determine the initial state of _fDropResult:
  2181.     
  2182.     //  start by assuming the _fDropResult will be kODDropMove
  2183.     somSelf->SetDropResult(ev, kODDropMove);
  2184.     
  2185.     //  if we are going across drafts, make kODDropCopy the default
  2186.     if ((_fSourcePart == kODNULL) ||
  2187.         (targetFacet->GetFrame(ev)->GetStorageUnit(ev)->GetDraft(ev) !=
  2188.          _fSourcePart->GetStorageUnit(ev)->GetDraft(ev)))
  2189.         somSelf->SetDropResult(ev, kODDropCopy);
  2190.  
  2191.     //  set attributes for inspection by target:
  2192.  
  2193.     //  start by clearing all attributes
  2194.     _fAttributes = 0;
  2195.  
  2196.     //  now set the real 'Drop' attributes:
  2197.     if (targetFacet->GetFrame(ev) == _fSourceFrame)
  2198.         _fAttributes = kODDropIsInSourcePart | kODDropIsInSourceFrame;
  2199.     else
  2200.         if (targetPart == _fSourcePart)
  2201.             _fAttributes |= kODDropIsInSourcePart;
  2202.  
  2203.     //  interpret modifier keys
  2204.     if (key_shift(VK_ALT))                            // ALT key overrides other modifiers
  2205.       _fAttributes |= kODDropIsPasteAs;
  2206.       //  do I also need to set drop result to Move here?
  2207.     else
  2208.       if (key_shift(VK_CTRL))                        // CTRL key indicates Copy or ...
  2209.       {
  2210.         somSelf->SetDropResult(ev, kODDropCopy);
  2211.         if (key_shift(VK_SHIFT))                    // with SHIFT key indicates Link
  2212.           _fAttributes |= kODDropIsLink;
  2213.         else
  2214.           _fAttributes |= kODDropIsCopy;
  2215.       }
  2216.       else
  2217.         if (key_shift(VK_SHIFT))                    // SHIFT key alone indicates Move
  2218.         {
  2219.           _fAttributes |= kODDropIsMove;
  2220.           somSelf->SetDropResult(ev, kODDropMove);
  2221.         }
  2222.         else
  2223.           //  no modifier keys pressed - use the initial state
  2224.           //  of _fDropResult to set the initial drop attribute:
  2225.           if (somSelf->GetDropResult(ev) == kODDropCopy)
  2226.             _fAttributes |= kODDropIsCopy;
  2227.           else
  2228.             _fAttributes |= kODDropIsMove;
  2229.  
  2230.     //  check to see whether the source wants to allow only copy
  2231.     //
  2232.     //  NOTE: Apple DR4 placed this block of code immediately after
  2233.     //  the interpretation of modifier keys, which means that any
  2234.     //  attempts by the user to override a default copy operation
  2235.     //  with modifier keys will be ignored.  Although this seems
  2236.     //  overly restrictive, we have uncovered at least one situation
  2237.     //  where this logic appears to be neccessary: dragging content
  2238.     //  that is participating in a link from one part to another
  2239.     //  part in the same draft.  In this situation, the destination
  2240.     //  part must not be allowed to modify the drag from a copy to a
  2241.     //  move because that would allow Draft code to 'reparent' the
  2242.     //  content into the destination, rather than enforcing the
  2243.     //  desired copy.  This reparenting is designed to be an
  2244.     //  optimization by the draft code, but it unfortunately opens a
  2245.     //  hole in Apple's design - if content is reparented, then both
  2246.     //  the source and the destination parts 'own' the content
  2247.     //  simultaneously until the source cleans itself up after the
  2248.     //  drop.
  2249.     //  
  2250.     //  This becomes a problem when content participating in a link
  2251.     //  is dragged from a part that supports linking to a part that
  2252.     //  does not support linking: if the user is allowed to modify
  2253.     //  the drop from a copy to a move, the non-linking destination
  2254.     //  part will receive the content and update the content's link
  2255.     //  status information to indicate the content is no longer in a
  2256.     //  link-capable environment.  However, because of the
  2257.     //  reparenting that occurs as discussed above, the source still
  2258.     //  'owns' (points to) that same dropped content.  When the Drop
  2259.     //  method invoked on the destination returns and control comes
  2260.     //  back to the source via the return from the source's
  2261.     //  StartDrag call, the source will attempt to clean up its
  2262.     //  links, but it will be unable to determine if it should
  2263.     //  update any link status that concerns the content that was
  2264.     //  involved in the drag and drop because the destination will
  2265.     //  have ALREADY cleared the relevant information from the
  2266.     //  content.  The source then disregards content that should be
  2267.     //  marked as 'no longer involved in a link', and when a
  2268.     //  corresponding link is updated, the source will trap.
  2269. #ifdef OS2_IMPLEMENTATION_FOLLOWS_DR4
  2270.     if (somSelf->GetDropResult(ev) != kODDropCopy)
  2271.     {
  2272.         ODDragItemIterator* dragItemIter = somSelf->GetDragItemIterator(ev);
  2273.         if (dragItemIter)
  2274.         {
  2275.             ODStorageUnit* su = dragItemIter->First(ev);
  2276.             ODDraft* draft = su->GetDraft(ev);
  2277.             ODCloneKind cloneKind = GetOriginalCloneKind(ev, draft);
  2278.             if (cloneKind == kODCloneCopy)
  2279.             {
  2280.                 somSelf->SetDropResult(ev, kODDropCopy);
  2281.                 _fAttributes &= ~kODDropIsMove;
  2282.                 _fAttributes |= kODDropIsCopy;
  2283.             }
  2284.         }
  2285.     }
  2286. #else
  2287.     //TDF Warning!  NASTY HACK!  See notes in Constants section at top of file:
  2288.     if (somSelf->GetDropResult(ev) != kODDropCopy)
  2289.         if (DrgAccessDraginfo(pDragInfo))
  2290.         {
  2291.             if (DrgQueryDragitemCount(pDragInfo) > 0)
  2292.             {
  2293.                 PDRAGITEM pDragItem = DrgQueryDragitemPtr(pDragInfo, 0);
  2294.                 if (pDragItem != NULL)
  2295.                 {
  2296.                     int sizeTargetName = DrgQueryStrNameLen(pDragItem->hstrTargetName) + 1;
  2297.                     char *szTargetName = (char *)malloc(sizeTargetName);
  2298.                     DrgQueryStrName(pDragItem->hstrTargetName, sizeTargetName, szTargetName);
  2299.                     if (strncmp(szTargetName,
  2300.                                 OPENDOC_FILENAME_FOR_CLONECOPY,
  2301.                                 strlen(OPENDOC_FILENAME_FOR_CLONECOPY)) == 0)
  2302.                     {
  2303.                         somSelf->SetDropResult(ev, kODDropCopy);
  2304.                         _fAttributes &= ~kODDropIsMove;
  2305.                         _fAttributes |= kODDropIsCopy;
  2306.                     }
  2307.                     free(szTargetName);
  2308.                 }
  2309.             }
  2310.             //DrgFreeDraginfo(pDragInfo);        //don't free drag info yet!
  2311.         }
  2312. #endif // OS2_IMPLEMENTATION_FOLLOWS_DR4
  2313.  
  2314.     //  cache the destination facet and call Drop on the part
  2315.     _fDestFacet = targetFacet;
  2316.     _fPrevFacet = NULL;
  2317.  
  2318. #if ODDebug
  2319.     if (fDebugLogging)
  2320.         somPrintf("dmDrop: about to call part's drop routine;\n"
  2321.                   "        drop result initially %d, _fAttributes = 0x%08X, targetFacet = %08p\n",
  2322.                   _fDropResult, _fAttributes, targetFacet);
  2323. #endif
  2324.  
  2325. #ifdef    PORTABILITY_HACK
  2326. #if ODDebug
  2327.     if (fDebugLogging)
  2328.         somPrintf("dmDrop:  passing iterator over _fDragGarbageList to part\n");
  2329. #endif // ODDebug
  2330.     // give part the iterator over the drag items set up by GetDataFromDragManager:
  2331.     dropResult  = targetFacet->Drop(ev, &localMouse, DragGarbageIterator, kODNULL);
  2332.     if (DragGarbageIterator)
  2333.         delete DragGarbageIterator;
  2334.     if (theIter)
  2335.         delete theIter;
  2336. #else
  2337.     dropResult  = targetFacet->Drop(ev, &localMouse, _fDragItemIterator, kODNULL);
  2338. #endif // PORTABILITY_HACK
  2339.  
  2340. #if ODDebug
  2341.     if (fDebugLogging)
  2342.         somPrintf("dmDrop: back from part's drop routine - dropResult = %d\n",
  2343.                   dropResult);
  2344. #endif
  2345.  
  2346.     //  update our _fDropResult - it will remain the same
  2347.     //  value as determined before the target's Drop method
  2348.     //  was called unless the target returned kODDropFail,
  2349.     //  or if the target turned a move into a copy:
  2350.     if ((dropResult == kODDropFail) ||
  2351.         ((somSelf->GetDropResult(ev) == kODDropMove) &&
  2352.          (dropResult == kODDropCopy)))
  2353.       somSelf->SetDropResult(ev, dropResult);
  2354.  
  2355.     //  Set the drop operation type properly.
  2356.     //  This will return user's intentions to PM for
  2357.     //  subsequent interpretation by source's StartDrag
  2358.     switch (somSelf->GetDropResult(ev))
  2359.     {
  2360.         case kODDropMove:
  2361.           pDragInfo->usOperation = DO_MOVE;
  2362.           break;
  2363.  
  2364.         case kODDropLink:
  2365.           pDragInfo->usOperation = DO_LINK;
  2366.           break;
  2367.  
  2368.         case kODDropCopy:
  2369.           if (_fAttributes & kODDropIsLink)
  2370.             pDragInfo->usOperation = DO_LINK;
  2371.           else
  2372.             pDragInfo->usOperation = DO_COPY;
  2373.           break;
  2374.  
  2375.         //    How do I communicate back to the source the
  2376.         //    kODDropIsPasteAs attribute?  Does the source
  2377.         //    even care or need to know?
  2378.  
  2379.         case kODDropFail:
  2380.         default:
  2381.             pDragInfo->usOperation = DO_UNKNOWN;
  2382.             break;
  2383.     }
  2384.     evt->result = (MRESULT)TRUE;
  2385.  
  2386.     // this really marks the end of the drop.
  2387.     somSelf->Clear(ev);
  2388.     _fDragReference = kODNULL; // [146749]
  2389.  
  2390. #if ODDebug
  2391.     if (fDebugLogging)
  2392.         somPrintf("dmDrop (exit): drop result set to %d, usOperation == 0x%08X\n",
  2393.                   _fDropResult, pDragInfo->usOperation);
  2394. #endif
  2395.  
  2396.     return(TRUE);
  2397. }
  2398.  
  2399. /*---------------------------------------------------------------------------
  2400.         ODDragAndDrop::dmDragError
  2401. ---------------------------------------------------------------------------*/
  2402. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmDragError(
  2403.                                   ODDragAndDrop *somSelf,
  2404.                                   Environment   *ev,
  2405.                                   ODEventData   *evt)
  2406. {
  2407.    ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2408.    ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmDragError");
  2409.  
  2410.    evt->result = (MRESULT)FALSE;
  2411.    return(FALSE);
  2412. }
  2413.  
  2414. /*---------------------------------------------------------------------------
  2415.         ODDragAndDrop::dmDragLeave
  2416. ---------------------------------------------------------------------------*/
  2417. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmDragLeave(ODDragAndDrop *somSelf,
  2418.                                                      Environment   *ev,
  2419.                                                      ODEventData   *evt)
  2420. {
  2421.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2422.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmDragLeave");
  2423.  
  2424. #if ODDebug
  2425.     if (getenv("STACKCRAWL_DL") != NULL)
  2426.     {
  2427.         StackCrawl stackCrawl;
  2428.         strstream stack;
  2429.         stackCrawl.DumpStack(0, 20, stack);
  2430.         somPrintf("\n%s", stack.str());
  2431.         stack.rdbuf()->freeze(0);
  2432.     }
  2433. #endif
  2434.  
  2435.     ODPoint localMouse;
  2436.  
  2437. // [138899] begin - ced
  2438.     POINTL mouse;
  2439.     PDRAGINFO pDragInfo = (PDRAGINFO)evt->mp1;
  2440.  
  2441.     mouse.x = pDragInfo->xDrop;
  2442.     mouse.y = pDragInfo->yDrop;
  2443.  
  2444.     WinMapWindowPoints(HWND_DESKTOP, evt->hwnd, &mouse, 1);
  2445.     localMouse.x = MAKEFIXED(mouse.x,0);
  2446.     localMouse.y = MAKEFIXED(mouse.y,0);
  2447. // [138899] end - ced
  2448.  
  2449. #if ODDebug
  2450.     if (fDebugLogging)
  2451.         somPrintf("dmDragLeave: hwnd = %08p, fPrevFacet = %08p\n",
  2452.                   evt->hwnd, _fPrevFacet);
  2453. #endif
  2454.  
  2455.     _fAttributes = 0;
  2456.     if (_fPrevFacet)
  2457.     {
  2458.         _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2459.         _fPrevFacet = kODNULL;
  2460.     }
  2461.  
  2462.     //  any given DragLeave will mean that the drag is
  2463.     //  currently leaving the source frame or must have
  2464.     //  already left the source frame on a previous
  2465.     //  DragLeave, so it is always appropriate to set
  2466.     //  this flag:
  2467.     _fHasLeftSourceFrame = kODTrue;
  2468.  
  2469.    // [123546] First attempt at this fix failed. We may be receiving this
  2470.    // DM_DRAGLEAVE on our way out of the docshell, towards the workplace.
  2471.    // In that case, we don't want to call Clear() as it would destroy our
  2472.    // drag information. _fSourcePart will be set in StartDrag() if we are
  2473.    // the initiator...
  2474.     if (!_fSourcePart)
  2475.         somSelf->Clear(ev);                // 123546
  2476.  
  2477.     _fDragReference = kODNULL;              // [146749]
  2478.  
  2479.     evt->result = (MRESULT)FALSE;
  2480. #if ODDebug
  2481.     if (fDebugLogging)
  2482.         somPrintf("dmDragLeave: returning TRUE, _fSourcePart == %08p\n", _fSourcePart);
  2483. #endif
  2484.     return(TRUE);
  2485. }
  2486.  
  2487. /*---------------------------------------------------------------------------
  2488.         ODDragAndDrop::dmDragOver
  2489. ---------------------------------------------------------------------------*/
  2490. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmDragOver(ODDragAndDrop *somSelf,
  2491.                                                     Environment   *ev,
  2492.                                                     ODEventData   *evt,
  2493.                                                     ODFacet* targetFacet)        // [138899] - ced
  2494. {
  2495.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2496.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmDragOver");
  2497.  
  2498. #if ODDebug
  2499. #define DEFAULT_SKIP 10
  2500.     int skip;
  2501.     counter++;
  2502.     if (getenv("SKIP_COUNT") != NULL)
  2503.         skip = strtoul(getenv("SKIP_COUNT"), NULL, 0);
  2504.     else
  2505.         skip = DEFAULT_SKIP;
  2506.  
  2507.     if (fDebugLogging)
  2508.     {
  2509.         if (counter % skip == 0)
  2510.         {
  2511.             somPrintf("dmDragOver: at entry - evt->hwnd = %08p, targetFacet = %08p\n",
  2512.                       evt->hwnd, targetFacet);
  2513.             somPrintf("dmDragOver: at entry - _fPrevFacet = %08p, _fDragItemIterator = %08p\n",
  2514.                       _fPrevFacet, _fDragItemIterator);
  2515.         }
  2516.         if (counter == 1 && (getenv("STACKCRAWL_DO") != NULL))
  2517.         {
  2518.             StackCrawl stackCrawl;
  2519.             strstream stack;
  2520.             stackCrawl.DumpStack(0, 20, stack);
  2521.             somPrintf("\n%s", stack.str());
  2522.             stack.rdbuf()->freeze(0);
  2523.         }
  2524.     }
  2525. #endif
  2526. //    ODFacet      *targetFacet;   [138899] - ced
  2527. //TDF    MRESULT      dragResult;
  2528.     ODDragResult dragResult = kODFalse;
  2529.     POINTL       mouse;
  2530.     ODPoint      localMouse;
  2531.     PDRAGINFO    pDInfo = (PDRAGINFO)(evt->mp1);
  2532. //    LinkedListIterator *theIter = kODNULL;
  2533.  
  2534.     DrgAccessDraginfo(pDInfo);
  2535.  
  2536.     _fDragReference = (ODPlatformDragReference)pDInfo;
  2537.     _fDragOperation = pDInfo->usOperation;
  2538. #if ODDebug
  2539.     if (fDebugLogging && (counter % skip == 0))
  2540.         somPrintf("dmDragOver:  _fDragReference = %08p, _fDragOperation = %d (0x%08X)\n",
  2541.                   _fDragReference, _fDragOperation, _fDragOperation);
  2542. #endif
  2543.  
  2544.     //  I assume this if block is here to rebuild drag items in the
  2545.     //  cross-process drag scenario ...
  2546.     if (_fDragItemIterator == kODNULL)
  2547.     {
  2548. #if ODDebug
  2549.         if (fDebugLogging)
  2550.             somPrintf("dmDragOver:  entered hwnd %08p, rebuilding drag item iterator\n",
  2551.                       evt->hwnd);
  2552. #endif
  2553.         somSelf->Clear(ev);
  2554.  
  2555.         ULONG cItems = DrgQueryDragitemCount(pDInfo);
  2556. #if ODDebug
  2557.         if (fDebugLogging)
  2558.             somPrintf("dmDragOver:  DrgQueryDragitemCount = %ld\n", cItems);
  2559. #endif
  2560.  
  2561.         for (ULONG index = 0; index < cItems; index++)
  2562.         {
  2563.             // create intermediate storage unit that will be
  2564.             // passed to GetDataFromDragManager:
  2565.             ODStorageUnit *unit = somSelf->GetContentStorageUnit(ev);
  2566.             DRAGITEM DItem;
  2567.             ULONG ulTmp;
  2568.  
  2569.             DrgQueryDragitem(pDInfo, sizeof(DRAGITEM), &DItem, index);
  2570.  
  2571.             unit->AddProperty(ev, kODPropContents);
  2572.             unit->AddValue(ev, (ODValueType)kODDragitem);
  2573.             StorageUnitSetValue(unit, ev, (ODULong)sizeof(DRAGITEM), &DItem);
  2574.             ulTmp = (ULONG)DrgQueryDragitemPtr(pDInfo, index);
  2575.             unit->SetOffset(ev, sizeof(DRAGITEM));
  2576.             StorageUnitSetValue(unit, ev, (ODULong)sizeof(PDRAGITEM), &ulTmp);
  2577. #if ODDebug
  2578.             if (fDebugLogging)
  2579.                 somPrintf("dmDragOver:  storing pDragItem = %08p\n", ulTmp);
  2580. #endif
  2581.         }
  2582.  
  2583.         LinkedListIterator *theIter = kODNULL;
  2584.         theIter            = new LinkedListIterator(_fDragItemList);
  2585.  
  2586.         _fDragItemIterator = new ODDragItemIterator();
  2587.         _fDragItemIterator->InitDragItemIterator(ev, theIter);
  2588. #if ODDebug
  2589.         if (fDebugLogging)
  2590.             somPrintf("dmDragOver:  new _fDragItemIterator = %08p\n", _fDragItemIterator);
  2591. #endif
  2592.     }
  2593.  
  2594.     mouse.x = SHORT1FROMMP(evt->mp2);
  2595.     mouse.y = SHORT2FROMMP(evt->mp2);
  2596.  
  2597. // [138899] begin - ced
  2598.  
  2599.     WinMapWindowPoints(HWND_DESKTOP, evt->hwnd, &mouse, 1);
  2600.     localMouse.x = MAKEFIXED(mouse.x,0);
  2601.     localMouse.y = MAKEFIXED(mouse.y,0);
  2602.  
  2603. // targetFacet = somSelf->FindTargetFacet(ev,
  2604. //                           WinQueryWindow(evt->hwnd, QW_PARENT),
  2605. //                           &mouse, &localMouse);
  2606.  
  2607. // [138899] end - ced
  2608.  
  2609.     //  since all drag attributes are determinable in every drag within,
  2610.     //  let's clear all flags and set them according to the results of
  2611.     //  the FindTargetFacet call (well, in the current OS/2 implementation,
  2612.     //  we aren't using FindTargetFacet, so we just check to see if
  2613.     //  the target facet we were passed is non-null ...)
  2614.     _fAttributes = 0;
  2615.     if (targetFacet)
  2616.     {
  2617.         TempODPart tempPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2618.         if ((targetFacet->GetFrame(ev) == _fSourceFrame) && (_fHasLeftSourceFrame == kODFalse))
  2619.             _fAttributes |= (kODDragIsInSourcePart | kODDragIsInSourceFrame);
  2620.         else
  2621.         {
  2622.             _fHasLeftSourceFrame = kODTrue;
  2623.             if (tempPart == _fSourcePart)
  2624.                 _fAttributes |= kODDragIsInSourcePart;
  2625.         }
  2626.  
  2627.         //  send appropriate drag messages along
  2628.         if (_fPrevFacet == targetFacet)
  2629.         {
  2630.             if (!_fNeverDrop)
  2631.                 dragResult = targetFacet->DragWithin(ev, 
  2632.                                                      &localMouse,
  2633.                                                      _fDragItemIterator,
  2634.                                                      kODNULL);
  2635.         }
  2636.         else
  2637.         {
  2638.             if (_fPrevFacet)
  2639.                 _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2640.  
  2641.             dragResult = targetFacet->DragEnter(ev,
  2642.                                                 &localMouse,
  2643.                                                 _fDragItemIterator,
  2644.                                                 kODNULL);
  2645.         }
  2646.  
  2647. #if ODDebug
  2648.         if (fDebugLogging && (counter % skip == 0))
  2649.             somPrintf("dmDragOver:  dragResult = %d, _fAttributes = 0x%08X\n", dragResult, _fAttributes);
  2650. #endif
  2651.         //  if the facet cannot accept the drag ...
  2652.         if (!dragResult)
  2653.         {
  2654.             //  would there be a better operation to indicate here than DO_UNKNOWN?
  2655.             evt->result = MRFROM2SHORT(DOR_NODROP, DO_UNKNOWN);
  2656.             _fNeverDrop = kODTrue;
  2657. #if ODDebug
  2658.             if (fDebugLogging)
  2659.                 somPrintf("dmDragOver:  _fNeverDrop set to kODTrue, evt->result = 0x%08X\n", evt->result);
  2660. #endif
  2661.         }
  2662.         else
  2663.         {
  2664.             //  so what happens here?  do I need to check modifier keys like NT does?
  2665.             //  or check to see if I am still in the source part?
  2666. #if ODDebug
  2667.             if (getenv("DO_COPY") != NULL)
  2668.                 evt->result = MRFROM2SHORT(DOR_DROP, DO_COPY);
  2669.             else
  2670. #endif
  2671.                 evt->result = MRFROM2SHORT(DOR_DROP, DO_MOVE);
  2672.             _fNeverDrop = kODFalse;
  2673. #if ODDebug
  2674.             if (fDebugLogging && (counter % skip == 0))
  2675.                 somPrintf("dmDragOver:  _fNeverDrop set to kODFalse, evt->result = 0x%08X\n", evt->result);
  2676. #endif
  2677.         }
  2678.     }
  2679.     else    // !targetFacet
  2680.     {
  2681.         //  We weren't over any facet; therefore, we
  2682.         //  must have left our source frame and part ...
  2683.         _fHasLeftSourceFrame = kODTrue;
  2684.         _fAttributes &= ~(kODDragIsInSourceFrame | kODDragIsInSourcePart);
  2685.  
  2686.         if (_fPrevFacet)
  2687.             _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2688.     }
  2689.  
  2690.     _fPrevFacet = targetFacet;
  2691.  
  2692.     return(TRUE);
  2693. }
  2694.  
  2695. /*---------------------------------------------------------------------------
  2696.         ODDragAndDrop::dmDragOverNotify
  2697. ---------------------------------------------------------------------------*/
  2698. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmDragOverNotify(
  2699.                                   ODDragAndDrop *somSelf,
  2700.                                   Environment   *ev,
  2701.                                   ODEventData   *evt)
  2702. {
  2703.    ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2704.    ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmDragOverNotify");
  2705.  
  2706. #if ODDebug
  2707.         if (fDebugLogging)
  2708.                 somPrintf("drag over notify\n");
  2709. #endif
  2710.  
  2711.    evt->result = (MRESULT)FALSE;
  2712.    return(TRUE);
  2713. }
  2714.  
  2715. /*---------------------------------------------------------------------------
  2716.         ODDragAndDrop::dmEndConversation
  2717. ---------------------------------------------------------------------------*/
  2718. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmEndConversation(ODDragAndDrop *somSelf,
  2719.                                                            Environment   *ev,
  2720.                                                            ODEventData   *evt)
  2721. {
  2722.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2723.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropDragdmEndConversation");
  2724.  
  2725.     unsigned long flags = (unsigned long)evt->mp2;
  2726.  
  2727. #if ODDebug
  2728.     if (fDebugLogging)
  2729.         somPrintf("EndConversation\n");
  2730. #endif
  2731.  
  2732.     if (_fDragInform && (flags & DMFL_TARGETFAIL))
  2733.     {
  2734. #if ODDebug
  2735.         if (fDebugLogging)
  2736.             somPrintf("TARGETFAIL\n");
  2737. #endif
  2738.  
  2739.         DrgFreeDraginfo((PDRAGINFO)_fDragInform);
  2740.         _fDragInform = kODNULL;
  2741.     }
  2742.  
  2743.     evt->result = (MRESULT)FALSE;
  2744.     return(TRUE);
  2745. }
  2746.  
  2747. /*---------------------------------------------------------------------------
  2748.         ODDragAndDrop::dmDropHelp
  2749. ---------------------------------------------------------------------------*/
  2750. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmDropHelp(
  2751.                                   ODDragAndDrop *somSelf,
  2752.                                   Environment   *ev,
  2753.                                   ODEventData   *evt)
  2754. {
  2755.    ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2756.    ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropDragdmDropHelp");
  2757.  
  2758. #if ODDebug
  2759.         if (fDebugLogging)
  2760.                 somPrintf("DropHelp\n");
  2761. #endif
  2762.  
  2763.    evt->result = (MRESULT)FALSE;
  2764. //TDF   return(TRUE);
  2765.    return(FALSE);
  2766. }
  2767.  
  2768. /*---------------------------------------------------------------------------
  2769.         ODDragAndDrop::dmPrintObject
  2770. ---------------------------------------------------------------------------*/
  2771. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmPrintObject(
  2772.                                   ODDragAndDrop *somSelf,
  2773.                                   Environment   *ev,
  2774.                                   ODEventData   *evt)
  2775. {
  2776.    ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2777.    ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmPrintObject");
  2778.  
  2779. #if ODDebug
  2780.         if (fDebugLogging)
  2781.                 somPrintf("PrintObject\n");
  2782. #endif
  2783.  
  2784.    evt->result = (MRESULT)DRR_ABORT;
  2785.    return(TRUE);
  2786. }
  2787.  
  2788. /*---------------------------------------------------------------------------
  2789.         ODDragAndDrop::dmRender
  2790. ---------------------------------------------------------------------------*/
  2791. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmRender(ODDragAndDrop *somSelf,
  2792.                                                   Environment   *ev,
  2793.                                                   ODEventData   *evt)
  2794. {
  2795.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2796.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmRender");
  2797.  
  2798.     HFILE hFile;
  2799.     ULONG ulAction;
  2800.     CHAR szFile[CCHMAXPATH];
  2801.     CHAR szSubject[CCHMAXPATH];
  2802.     USHORT usOperation;
  2803.     BOOL fSuccess = FALSE;
  2804.     PBYTE pData;
  2805.     ULONG cbSize;
  2806.     ODDragLink         *theDragLink;
  2807.     ODMemDragItem      *theDragItem;
  2808.     ULONG dataSize, rc, ulBytes;
  2809.     PBYTE pbData, pbLocalData;
  2810.     PULONG pulData;
  2811.  
  2812. #if ODDebug
  2813.     if (fDebugLogging)
  2814.         somPrintf("dmRender: entry\n");
  2815. #endif
  2816.  
  2817.     //------------------------------------------------------------------------
  2818.     // Tell the workplace there will not be a RENDERCOMPLETE to follow.
  2819.     //------------------------------------------------------------------------
  2820.     evt->result = (MRESULT)kODFalse;
  2821.  
  2822.     //------------------------------------------------------------------------
  2823.     // First make sure we are not being lied to
  2824.     //------------------------------------------------------------------------
  2825.     PDRAGTRANSFER pDragTransfer = (PDRAGTRANSFER)evt->mp1;
  2826.     if (pDragTransfer == kODNULL)
  2827.     {
  2828. #if ODDebug
  2829.         if (fDebugLogging)
  2830.             somPrintf("dmRender: pDragTransfer is null in dmRender\n");
  2831. #endif
  2832.         return(kODTrue);
  2833.     }
  2834.  
  2835.     //------------------------------------------------------------------------
  2836.     // Use the ulItemID to determine the requested storage unit
  2837.     //------------------------------------------------------------------------
  2838.     PDRAGITEM pDragItem = pDragTransfer->pditem;
  2839.     ULONG ulItemID      = pDragItem->ulItemID;
  2840.     
  2841.     LinkedListIterator *theIter = kODNULL;
  2842.     theIter            = new LinkedListIterator(_fDragItemList);
  2843.     
  2844.     theDragItem = (ODMemDragItem *)kODNULL;
  2845.     for (theDragLink = (ODDragLink*) theIter->First();
  2846.          theDragLink != kODNULL;
  2847.          theDragLink = (ODDragLink*) theIter->Next())
  2848.     {
  2849.         if (ulItemID-- == 0)
  2850.             theDragItem = (ODMemDragItem *)theDragLink->fItem;
  2851.     }
  2852.     delete theIter;
  2853.  
  2854.     if (theDragItem == kODNULL)
  2855.     {
  2856. #if ODDebug
  2857.         if (fDebugLogging)
  2858.             somPrintf("dmRender: theDragItem not assigned in dmRender\n");
  2859. #endif
  2860.         pDragTransfer->fsReply |= DMFL_RENDERFAIL;
  2861.         return(kODTrue);
  2862.     }
  2863.  
  2864.     //------------------------------------------------------------------------
  2865.     // Let's see how we are being asked to render...
  2866.     //------------------------------------------------------------------------
  2867.     CHAR  szSelectedRMF[CCHMAXPATH];
  2868.     DrgQueryStrName (pDragTransfer->hstrSelectedRMF, CCHMAXPATH, szSelectedRMF);
  2869. #if ODDebug
  2870.     if (fDebugLogging)
  2871.         somPrintf("dmRender: RMF = (%s)\n", szSelectedRMF);
  2872. #endif
  2873.  
  2874.     // This is a temporary hack. Currently the workplace always asks for
  2875.     // <OS2_FILE,UNKNOWN>, even if we had shown opendocdocdocument.
  2876.     if (!strcmp(szSelectedRMF, "<DRM_OS2FILE,DRF_UNKNOWN>"))
  2877.     {
  2878.         CHAR szTmp[CCHMAXPATH];
  2879.         DrgQueryStrName(pDragItem->hstrRMF, CCHMAXPATH, szTmp);
  2880.         if (strstr(szTmp, "DRF_OPENDOCDOCUMENT"))
  2881.             strcpy(szSelectedRMF, "<DRM_OS2FILE,DRF_OPENDOCDOCUMENT>");
  2882.     }
  2883.  
  2884.     //------------------------------------------------------------------------
  2885.     // Test 1: Check if its an Opendoc Document to disk
  2886.     //------------------------------------------------------------------------
  2887.     if (!strcmp(szSelectedRMF, "<DRM_OS2FILE,DRF_OPENDOCDOCUMENT>"))
  2888.     {
  2889.         DrgQueryStrName(pDragTransfer->hstrRenderToName,
  2890.                         CCHMAXPATH, szFile);
  2891.  
  2892. #if ODDebug
  2893.         if (fDebugLogging)
  2894.             somPrintf("dmRender: szFile: (%s)\n", szFile);
  2895. #endif
  2896.         if (szFile[0] != '\x0' && strlen(szFile))
  2897.         {
  2898. // [140007] :
  2899.             CHAR kindList[CCHMAXPATH];
  2900.             kindList[0] = 0;
  2901.             DrgQueryStrName(pDragItem->hstrType, CCHMAXPATH, kindList);
  2902.             theDragItem->fSU->ResolveAllPromises(ev); // [146343]
  2903.             WriteDragItemtoFile(somSelf,
  2904.                                 ev,
  2905.                                 (ODPtr)theDragItem,
  2906.                                 0,
  2907.                                 (ODUByte *)szFile,
  2908.                                 kindList);
  2909. // end [140007]
  2910. #if ODDebug
  2911.             if (fDebugLogging)
  2912.                 somPrintf("dmRender: back from writedragtofile\n");
  2913. #endif
  2914.  
  2915.             pDragTransfer->fsReply |= (DMFL_NATIVERENDER | DMFL_RENDEROK);
  2916.         }
  2917.         else
  2918.         {
  2919. #if ODDebug
  2920.             if (fDebugLogging)
  2921.                 somPrintf("dmRender: no file specified\n");
  2922. #endif
  2923.             pDragTransfer->fsReply |= DMFL_RENDERFAIL;
  2924.         }
  2925.     }
  2926.     //------------------------------------------------------------------------
  2927.     // Test 2: Check for Opendoc doc in shared memory....
  2928.     //------------------------------------------------------------------------
  2929.     else
  2930.         if (!strcmp(szSelectedRMF, "<DRM_SHAREDMEM,DRF_OPENDOCDOCUMENT>"))
  2931.         {
  2932.             theDragItem->fSU->ResolveAllPromises(ev);   // [146373]
  2933.             theDragItem->Close(ev);
  2934.  
  2935.             dataSize = ODGetHandleSize(theDragItem->fContainerHandle);
  2936.             ODLockHandle(theDragItem->fContainerHandle);
  2937.             pbLocalData = (PBYTE)*((ODHandle)theDragItem->fContainerHandle);
  2938.  
  2939.             if (pbData = AllocSharedMem(pDragTransfer, dataSize))
  2940.             {
  2941.                 memcpy(((PBYTE)pbData + sizeof(ULONG)), pbLocalData, dataSize);
  2942.  
  2943.                 GiveMemoryIfNecessary(pDragTransfer->hwndClient,
  2944.                                       evt->hwnd,
  2945.                                       pbData);
  2946.             }
  2947.  
  2948. //TDF:  Ja, you bet ...
  2949. //TDF:            // maybe try reopen here instead...
  2950. //TDF:             ODDisposeHandle(theDragItem->fContainerHandle);
  2951. //TDF:             theDragItem->fContainerHandle = (ODHandle) kODNULL;
  2952.             ODUnlockHandle(theDragItem->fContainerHandle);
  2953.             theDragItem->Open(ev);
  2954.         }
  2955.         //------------------------------------------------------------------------
  2956.         // Test 3: Next check if the RMF is present as a value.
  2957.         //------------------------------------------------------------------------
  2958.         else
  2959.         {
  2960.             // [146373] do RMF-to-kind mapping
  2961.             PSZ theKind = szSelectedRMF;
  2962.             if (!strncmp(szSelectedRMF, "<DRM_OS2FILE", 11))
  2963.             {
  2964.                 PSZ theFmt = GetFormatFromRMF(szSelectedRMF);
  2965.                 if (theFmt && strcmp(theFmt,"DRF_UNKNOWN"))
  2966.                 {
  2967.                     theKind = GetKindForFormat(theFmt);
  2968.                     if (!theKind)
  2969.                         theKind = szSelectedRMF;
  2970.                 }
  2971.             }
  2972.             // [146373] end
  2973.             if (theDragItem->fSU->Exists(ev,
  2974.                                          kODPropContents,
  2975.                                          (ODValueType)theKind,
  2976.                                          0))
  2977.             {
  2978.                 theDragItem->fSU->Focus(ev,
  2979.                                         kODPropContents,
  2980.                                         kODPosUndefined,
  2981.                                         (ODValueType)theKind,
  2982.                                         0,
  2983.                                         kODPosUndefined);
  2984.  
  2985.          //------------------------------------------------------------------
  2986.          // Test 4: If its not a promise, just render it
  2987.          //------------------------------------------------------------------
  2988.                 if (! theDragItem->fSU->IsPromiseValue(ev))
  2989.                 {
  2990.          //------------------------------------------------------------------
  2991.          // Test 5: Check for shared memory
  2992.          //------------------------------------------------------------------
  2993.                     if (!strncmp(szSelectedRMF, "<DRM_SHAREDMEM", 14))
  2994.                     {
  2995.                         dataSize = theDragItem->fSU->GetSize(ev);
  2996.  
  2997.                         if (pbData = AllocSharedMem(pDragTransfer, dataSize))
  2998.                         {
  2999.                             StorageUnitGetValue(theDragItem->fSU,
  3000.                                                 ev,
  3001.                                                 dataSize,
  3002.                                                 ((PBYTE)pbData + sizeof(ULONG)));
  3003.  
  3004.                             GiveMemoryIfNecessary(pDragTransfer->hwndClient,
  3005.                                                   evt->hwnd,
  3006.                                                   pbData);
  3007.                         }
  3008.  
  3009.                         ODDisposeHandle(theDragItem->fContainerHandle);
  3010.                         theDragItem->fContainerHandle = (ODHandle) kODNULL;
  3011.                     }
  3012.         //------------------------------------------------------------------
  3013.         // Test 6: Check for file
  3014.         //------------------------------------------------------------------
  3015.                     else
  3016.                         if (!strncmp(szSelectedRMF, "<DRM_OS2FILE", 11))
  3017.                         {
  3018.                             DrgQueryStrName(pDragTransfer->hstrRenderToName,
  3019.                                             CCHMAXPATH,
  3020.                                             szFile);
  3021.  
  3022.                             // we'll write the file to disk
  3023.  
  3024.                             dataSize = theDragItem->fSU->GetSize(ev);
  3025.                             rc = DosAllocMem((PPVOID)&pbData,
  3026.                                              dataSize,
  3027.                                              PAG_READ | PAG_WRITE | PAG_COMMIT);
  3028.                             if (rc)
  3029.                             {
  3030.                                 pDragTransfer->fsReply |= DMFL_RENDERFAIL;
  3031. #if ODDebug
  3032.                                 if (fDebugLogging)
  3033.                                     somPrintf("dmRender: Out of memory.\n");
  3034. #endif
  3035.                             }
  3036.                             else
  3037.                             {
  3038.                                 StorageUnitGetValue(theDragItem->fSU,
  3039.                                                     ev,
  3040.                                                     dataSize,
  3041.                                                     pbData);
  3042.  
  3043.                                 rc = DosOpen(szFile,
  3044.                                              &hFile,
  3045.                                              &ulAction,
  3046.                                              0,
  3047.                                              FILE_NORMAL,
  3048.                                              OPEN_ACTION_CREATE_IF_NEW |
  3049.                                               OPEN_ACTION_REPLACE_IF_EXISTS,
  3050.                                              OPEN_SHARE_DENYNONE |
  3051.                                               OPEN_ACCESS_READWRITE,
  3052.                                              0);
  3053.                                 if (rc)
  3054.                                 {
  3055.                                     pDragTransfer->fsReply |= DMFL_RENDERFAIL;
  3056. #if ODDebug
  3057.                                     if (fDebugLogging)
  3058.                                         somPrintf("dmRender: Cannot open file (%s).\n", szFile);
  3059. #endif
  3060.                                 }
  3061.                                 else
  3062.                                 {
  3063.                                     DosWrite(hFile, (PVOID)pbData, dataSize, &ulBytes);
  3064.                                     DosClose(hFile);
  3065.                                     pDragTransfer->fsReply |= (DMFL_NATIVERENDER | DMFL_RENDEROK);
  3066.                                 }
  3067.                                 DosFreeMem(pbData);
  3068.                             }
  3069.                         }
  3070.                         else // error
  3071.                         {
  3072. #if ODDebug
  3073.                             if (fDebugLogging)
  3074.                                 somPrintf("dmRender: Don't know how to handle format.\n");
  3075. #endif
  3076.                         }
  3077.                 }
  3078.          //------------------------------------------------------------------
  3079.          // It's a promise - check for shared mem vs disk
  3080.          //------------------------------------------------------------------
  3081.                 else
  3082.                 {
  3083.             //------------------------------------------------------------------
  3084.             // Test 7: Check for shared memory
  3085.             //------------------------------------------------------------------
  3086.                     if (!strncmp(szSelectedRMF, "<DRM_SHAREDMEM", 14))
  3087.                     {
  3088.                         ODByteArray ba;  // [146373]
  3089.                         ODPart *sourcePart;
  3090.                         theDragItem->fSU->GetPromiseValue(ev,
  3091.                                                           (ODValueType)theKind,
  3092.                                                           0,
  3093.                                                           0,
  3094.                                                           &ba,
  3095.                                                           &sourcePart);
  3096.  
  3097.                         // Note: this differs from below (promise to file) in that
  3098.                         // both we and the promiser are allocating memory for this
  3099.                         // transfer.
  3100.                         if (sourcePart)    // [146373]
  3101.                         {
  3102.                             ODStorageUnitView *destSUView = theDragItem->fSU->CreateView(ev);
  3103.                             sourcePart->FulfillPromise(ev, destSUView);
  3104.                             dataSize = destSUView->GetSize(ev);
  3105.  
  3106. //                            dataSize = ba->_length;
  3107.  
  3108.                             if (pbData = AllocSharedMem(pDragTransfer, dataSize))
  3109.                             {
  3110.                                 StorageUnitViewGetValue(destSUView,
  3111.                                                         ev,
  3112.                                                         dataSize,
  3113.                                                         (ODValue)pbData);
  3114. //                                memcpy(((PBYTE)pbData + sizeof(ULONG)),
  3115. //                                       ba->_buffer,
  3116. //                                       dataSize);
  3117.  
  3118.                                 GiveMemoryIfNecessary(pDragTransfer->hwndClient,
  3119.                                                       evt->hwnd,
  3120.                                                       pbData);
  3121.                             }
  3122.                         }   // [146373] end
  3123.                         ODDisposeHandle(theDragItem->fContainerHandle);
  3124.                         theDragItem->fContainerHandle = (ODHandle) kODNULL;
  3125.  
  3126. //                        delete ba;
  3127.                     }
  3128.             //------------------------------------------------------------------
  3129.             // Test 8: Check for file
  3130.             //------------------------------------------------------------------
  3131.                     else
  3132.                         if (!strncmp(szSelectedRMF, "<DRM_OS2FILE", 11))
  3133.                         {
  3134.                             DrgQueryStrName(pDragTransfer->hstrRenderToName,
  3135.                                             CCHMAXPATH,
  3136.                                             szFile);
  3137.  
  3138.                             // let the promiser write the file to disk, tell him
  3139.                             theDragItem->fSU->AddProperty(ev, kODPropContents);
  3140.                             theDragItem->fSU->AddValue(ev, (ODValueType)kODFileType);
  3141.                             StorageUnitSetValue(theDragItem->fSU, ev, (ODULong) strlen(szFile) + 1, szFile);
  3142.  
  3143.                             if (GetEAFromName(szFile, ".TYPE", NULL, szSubject))
  3144.                             {
  3145.                                 theDragItem->fSU->AddValue(ev, (ODValueType)kODFileTypeEA);
  3146.                                 StorageUnitSetValue(theDragItem->fSU, ev, (ODULong) sizeof(szSubject), szSubject);
  3147.                             }
  3148.  
  3149.                             theDragItem->fSU->AddValue(ev, (ODValueType)kODDragOperation);
  3150.                             StorageUnitSetValue(theDragItem->fSU,
  3151.                                                 ev,
  3152.                                                 (ODULong) sizeof(USHORT),
  3153.                                                 &usOperation);
  3154.  
  3155.                             ODByteArray ba;      // [146373]
  3156.                             ODPart *sourcePart;
  3157.                             theDragItem->fSU->GetPromiseValue(ev,
  3158.                                                               (ODValueType)theKind,
  3159.                                                               0,
  3160.                                                               0,
  3161.                                                               &ba,
  3162.                                                               &sourcePart);
  3163.                             if (sourcePart)   // [146373]
  3164.                             {
  3165.                                 ODStorageUnitView *destSUView = theDragItem->fSU->CreateView(ev);
  3166.                                 sourcePart->FulfillPromise(ev, destSUView);
  3167.                             }
  3168. //                            delete ba;
  3169.                             // [146373] end
  3170.                             ODDisposeHandle(theDragItem->fContainerHandle);
  3171.                             theDragItem->fContainerHandle = (ODHandle) kODNULL;
  3172.                         }
  3173.                         else // error
  3174.                         {
  3175. #if ODDebug
  3176.                             if (fDebugLogging)
  3177.                                 somPrintf("dmRender: Don't know how to handle format.\n");
  3178. #endif
  3179.                         }
  3180.                 } // promise
  3181.             }
  3182.         }
  3183.     return(kODTrue);
  3184. }
  3185.  
  3186. /*---------------------------------------------------------------------------
  3187.         ODDragAndDrop::dmRenderComplete
  3188.  
  3189.         Because of the fact that GetDataFromDragManager is a synchronous
  3190.         thing and that when we fall out from it we return immediately to
  3191.         the part, we need to use a pm semaphore to wait for the source
  3192.         to render.
  3193. ---------------------------------------------------------------------------*/
  3194. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmRenderComplete(
  3195.                                         ODDragAndDrop *somSelf,
  3196.                                         Environment   *ev,
  3197.                                         ODEventData   *evt)
  3198. {
  3199.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  3200.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmComplete");
  3201.  
  3202. //   ULONG  ulWaitingTime;
  3203.     PDRAGTRANSFER pDragTransfer  = (PDRAGTRANSFER)evt->mp1;
  3204.  
  3205.    // need to get this flag back to doReceive...
  3206.     _fRenderCompleteFlag         = SHORT1FROMMP(evt->mp2);
  3207.  
  3208. #if ODDebug
  3209.     if (fDebugLogging)
  3210.         somPrintf("dmRenderComplete: pDragTransfer = %08p, _fRenderCompleteFlag = 0x%08X\n",
  3211.                   pDragTransfer, _fRenderCompleteFlag);
  3212. #endif
  3213.  
  3214. // [140007]
  3215. //   DosResetEventSem(_fHEVRenderComplete, &ulWaitingTime);
  3216. //   DosPostEventSem(_fHEVRenderComplete);
  3217.     _fRenderCompleteReceived = kODTrue;
  3218.  
  3219.     evt->result = (MRESULT)kODTrue;
  3220.     return(TRUE);
  3221. }
  3222.  
  3223. /*---------------------------------------------------------------------------
  3224.         ODDragAndDrop::dmRenderPrepare
  3225. ---------------------------------------------------------------------------*/
  3226. SOM_Scope ODBoolean SOMLINK ODDragAndDropdmRenderPrepare(
  3227.                                   ODDragAndDrop *somSelf,
  3228.                                   Environment   *ev,
  3229.                                   ODEventData   *evt)
  3230. {
  3231.    ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  3232.    ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropdmRenderPrepare");
  3233.  
  3234. #if ODDebug
  3235.         if (fDebugLogging)
  3236.                 somPrintf("RenderPrepare\n");
  3237. #endif
  3238.  
  3239.    evt->result = (MRESULT)FALSE;
  3240.    return(FALSE);
  3241. }
  3242.  
  3243. /*---------------------------------------------------------------------------
  3244.         ODDragAndDrop::CanEmbed
  3245. ---------------------------------------------------------------------------*/
  3246. SOM_Scope ODBoolean  SOMLINK ODDragAndDropCanEmbed(ODDragAndDrop *somSelf,
  3247.                                                    Environment   *ev,
  3248.                                                    ODStorageUnit* dropSU)
  3249. {
  3250.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  3251.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropCanEmbed");
  3252.  
  3253.     DRAGITEM DragItem;
  3254.     CHAR szRMF[CCHMAXPATH];
  3255.     CHAR selectedRMF[CCHMAXPATH];
  3256.     CHAR selectedKind[CCHMAXPATH];
  3257.     CHAR szType[CCHMAXPATH];
  3258.     ODBoolean result = kODTrue;
  3259.     selectedRMF[0] = 0;
  3260.     selectedKind[0] = 0;
  3261.  
  3262.     if (!dropSU->Exists(ev, kODPropContents, (ODValueType)kODDragitem, 0))
  3263.         return kODFalse;
  3264.     dropSU->Focus(ev,
  3265.                   kODPropContents,
  3266.                   kODPosUndefined,
  3267.                   (ODValueType)kODDragitem,
  3268.                   0,
  3269.                   kODPosUndefined);
  3270.     StorageUnitGetValue(dropSU, ev,sizeof(DRAGITEM), &DragItem);
  3271.     if (DrgVerifyRMF(&DragItem, "DRM_SHAREDMEM", "DRF_OPENDOCDOCUMENT"))
  3272.         strcpy(selectedRMF, "<DRM_SHAREDMEM,DRF_OPENDOCDOCUMENT>");
  3273.     else
  3274.         if (DrgVerifyRMF(&DragItem, "DRM_OS2FILE", "DRF_OPENDOCDOCUMENT"))
  3275.             strcpy(selectedRMF, "<DRM_OS2FILE,DRF_OPENDOCDOCUMENT>");
  3276.         else
  3277.         {
  3278.             szRMF[0] = 0;
  3279.             DrgQueryStrName(DragItem.hstrRMF, CCHMAXPATH, szRMF);
  3280.             DrgQueryStrName(DragItem.hstrType, CCHMAXPATH, szType);
  3281.  
  3282.             if (!szRMF[0])
  3283.                 return kODFalse;
  3284.             LinkedList* fRMFList     = new LinkedList;
  3285.             ParseRMF(szRMF,fRMFList);
  3286.             LinkedListIterator *theIter = new LinkedListIterator(fRMFList);
  3287.             if (!theIter)
  3288.             {
  3289.                 delete fRMFList;
  3290.                 return kODFalse;
  3291.             }
  3292.             RegistryManager* registrationMgr;
  3293.             registrationMgr = new RegistryManager;
  3294.             ODPartHandlerRegistry* odRegistry;
  3295.             odRegistry = registrationMgr->GetODPartHandlerRegistry(ev);
  3296.             PSZ theRMF;
  3297.             PSZ theFmt;
  3298.             PSZ theKind;
  3299.             result = kODFalse;
  3300.             ODDragRMF* item;
  3301.             for (item = (ODDragRMF *)theIter->First();
  3302.                   item != kODNULL;
  3303.                   item = (ODDragRMF *)theIter->Next())
  3304.             {
  3305.                 theRMF = item->fRMF;
  3306.                 theKind = theRMF;
  3307.                 theFmt = GetFormatFromRMF(theRMF);
  3308.  
  3309.                 if (theFmt)
  3310.                 {
  3311.                     if (strcmp(theFmt,"DRF_UNKNOWN"))
  3312.                     {
  3313.                         theKind = GetKindForFormat(theFmt);
  3314.                         if (!theKind)
  3315.                             theKind = theRMF;
  3316.                     }
  3317.                     else
  3318.                         theKind = kODNULL;
  3319.                 }
  3320.                 _IDL_SEQUENCE_ISOString partHandlerList = 
  3321.                   (theKind)
  3322.                       ? odRegistry->GetPartHandlerList(ev, theKind, 0)
  3323.                       : odRegistry->GetPartHandlerListForFileTypes(ev, szType);
  3324.                 if (partHandlerList. _length)
  3325.                 {
  3326.                     result = kODTrue;
  3327.                     strcpy(selectedRMF, theRMF);
  3328.                     if (theKind)
  3329.                         strcpy(selectedKind,theKind);
  3330.                 }
  3331.                 for (int i = 0; i < partHandlerList. _length; i++)
  3332.                     SOMFree(partHandlerList. _buffer[i]);
  3333.  
  3334.                 SOMFree(partHandlerList. _buffer);
  3335.                 if (result)
  3336.                     break;
  3337.             }
  3338.             delete theIter;
  3339.             delete fRMFList;
  3340.         }
  3341.  
  3342.     if (result)
  3343.     {
  3344.         if (dropSU->Exists(ev, kODPropContents, (ODValueType)kODSelectedRMF, 0))
  3345.         {
  3346.             dropSU->Focus(ev,
  3347.                           kODPropContents,
  3348.                           kODPosUndefined,
  3349.                           (ODValueType)kODSelectedRMF,
  3350.                           0,
  3351.                           kODPosUndefined);
  3352.             dropSU->Remove(ev);
  3353.         }
  3354.         dropSU->AddProperty(ev,kODPropContents)->AddValue(ev, kODSelectedRMF);
  3355.         StorageUnitSetValue(dropSU, ev, (ODULong) strlen(selectedRMF) + 1, selectedRMF);
  3356.         if (dropSU->Exists(ev, kODPropContents, (ODValueType)kODSelectedKind, 0))
  3357.         {
  3358.             dropSU->Focus(ev,
  3359.                           kODPropContents,
  3360.                           kODPosUndefined,
  3361.                           (ODValueType)kODSelectedKind,
  3362.                           0,
  3363.                           kODPosUndefined);
  3364.             dropSU->Remove(ev);
  3365.         }
  3366.         if (selectedKind[0])
  3367.         {
  3368.             dropSU->AddProperty(ev,kODPropContents)->AddValue(ev, kODSelectedKind);
  3369.             StorageUnitSetValue(dropSU, ev, (ODULong) strlen(selectedKind) + 1, selectedKind);
  3370.         }
  3371.     }
  3372.     return result;
  3373. }
  3374.  
  3375. /*---------------------------------------------------------------------------
  3376.         ODDragAndDrop::CanIncorporate
  3377. ---------------------------------------------------------------------------*/
  3378. SOM_Scope ODBoolean  SOMLINK ODDragAndDropCanIncorporate(ODDragAndDrop *somSelf,
  3379.                                                          Environment   *ev,
  3380.                                                          ODStorageUnit* dropSU,
  3381.                                                          ODType kind)
  3382. {
  3383.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  3384.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropCanIncorporate");
  3385.  
  3386.     CHAR szRMF[CCHMAXPATH];
  3387.     CHAR szKindRMF[CCHMAXPATH];
  3388.     CHAR szMech[CCHMAXPATH];
  3389.     CHAR szFmt[CCHMAXPATH];
  3390.     CHAR szKind[CCHMAXPATH];
  3391.     CHAR szType[CCHMAXPATH];
  3392.     CHAR szName[CCHMAXPATH];
  3393.     DRAGITEM DragItem;
  3394.  
  3395.     // OpenDoc data, check kind list from hstrType
  3396.     if (!dropSU->Exists(ev, kODPropContents, (ODValueType)kODDragitem, 0))
  3397.         return kODFalse;
  3398.     dropSU->Focus(ev,
  3399.                   kODPropContents,
  3400.                   kODPosUndefined,
  3401.                   (ODValueType)kODDragitem,
  3402.                   0,
  3403.                   kODPosUndefined);
  3404.     StorageUnitGetValue(dropSU, ev,sizeof(DRAGITEM), &DragItem);
  3405.     if (DrgVerifyRMF(&DragItem,NULL,"DRF_OPENDOCDOCUMENT"))
  3406.     {
  3407.         if (DrgVerifyRMF(&DragItem, "DRM_SHAREDMEM", "DRF_OPENDOCDOCUMENT"))
  3408.         {
  3409.             strcpy(szKindRMF, "<DRM_SHAREDMEM,DRF_OPENDOCDOCUMENT>");
  3410.             DrgQueryStrName(DragItem.hstrType, CCHMAXPATH, szType);
  3411.         }
  3412.         else
  3413.             if (DrgVerifyRMF(&DragItem, "DRM_OS2FILE", "DRF_OPENDOCDOCUMENT"))
  3414.             {
  3415.                 strcpy(szKindRMF, "<DRM_OS2FILE,DRF_OPENDOCDOCUMENT>");
  3416.                 szName[0] = 0;
  3417.                 DrgQueryStrName(DragItem.hstrContainerName, CCHMAXPATH, szName);
  3418.                 if (!szName[0])
  3419.                     return kODFalse;
  3420.                 if (szName[strlen(szName)-1] != '\\')
  3421.                     strcat (szName, "\\");
  3422.                 CHAR tbuf[CCHMAXPATH];
  3423.                 tbuf[0] = 0;
  3424.                 DrgQueryStrName (DragItem.hstrSourceName, CCHMAXPATH, tbuf);
  3425.                 if (!tbuf[0])
  3426.                     DrgQueryStrName (DragItem.hstrTargetName, CCHMAXPATH, tbuf);
  3427.                 if (!tbuf[0])
  3428.                     return kODFalse;
  3429.                 strcat(szName,tbuf);
  3430.                 if (!GetEAFromName(szName, "OD.KIND", NULL, szType))
  3431.                     return kODFalse;
  3432.             }
  3433.           if (!KindInTypeList((PSZ)kind,szType))
  3434.             return kODFalse;
  3435.     }
  3436.     else
  3437.     {
  3438.         if (!GetRMFForKind((PSZ)kind,szKindRMF))
  3439.             strcpy(szKindRMF,(PSZ)kind);
  3440.         if (!QueryRMF(szKindRMF,szMech,szFmt))
  3441.             return kODFalse;
  3442.         if (!DrgVerifyRMF(&DragItem,szMech,szFmt))
  3443.             return kODFalse;
  3444.     }
  3445.     if (dropSU->Exists(ev, kODPropContents, (ODValueType)kODSelectedRMF, 0))
  3446.     {
  3447.         dropSU->Focus(ev,
  3448.                       kODPropContents,
  3449.                       kODPosUndefined,
  3450.                       (ODValueType)kODSelectedRMF,
  3451.                       0,
  3452.                       kODPosUndefined);
  3453.         dropSU->Remove(ev);
  3454.     }
  3455.     dropSU->AddProperty(ev,kODPropContents)->AddValue(ev, kODSelectedRMF);
  3456.     StorageUnitSetValue(dropSU, ev, (ODULong) strlen(szKindRMF) + 1, szKindRMF);
  3457.     if (dropSU->Exists(ev, kODPropContents, (ODValueType)kODSelectedKind, 0))
  3458.     {
  3459.         dropSU->Focus(ev,
  3460.                       kODPropContents,
  3461.                       kODPosUndefined,
  3462.                       (ODValueType)kODSelectedKind,
  3463.                       0,
  3464.                       kODPosUndefined);
  3465.         dropSU->Remove(ev);
  3466.     }
  3467.     dropSU->AddProperty(ev,kODPropContents)->AddValue(ev, kODSelectedKind);
  3468.     StorageUnitSetValue(dropSU, ev, (ODULong) strlen((PSZ)kind) + 1, (PSZ)kind);
  3469.     return kODTrue;
  3470. }
  3471.  
  3472. /*---------------------------------------------------------------------------
  3473.         ODDragAndDrop::DraftClosing
  3474. ---------------------------------------------------------------------------*/
  3475. SOM_Scope void  SOMLINK ODDragAndDropDraftClosing(ODDragAndDrop *somSelf, 
  3476.                                                   Environment *ev, 
  3477.                                                   ODDraft* draft)
  3478. {
  3479.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  3480.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropDraftClosing");
  3481.  
  3482. #if ODDebug
  3483.     if (fDebugLogging)
  3484.         somPrintf("Entering ODDragAndDropDraftClosing:\n");
  3485. #endif
  3486.  
  3487.     SOM_TRY
  3488.  
  3489.         //  currently, we don't care what comes across in the draft pointer ...
  3490.         // if (draft) {
  3491.     
  3492.         //  clear our drag items
  3493.         somSelf->Clear(ev);
  3494.  
  3495.     SOM_CATCH_ALL
  3496.     SOM_ENDTRY
  3497.  
  3498.         return;
  3499. }
  3500.  
  3501. /*---------------------------------------------------------------------------
  3502.                            Local Functions
  3503. ---------------------------------------------------------------------------*/
  3504. /*---------------------------------------------------------------------------
  3505.         GetEAFromName
  3506.  
  3507.         Extract a specific EA from a given filename
  3508. ---------------------------------------------------------------------------*/
  3509. USHORT  GetEAFromName(PSZ    pszFilePath,
  3510.                       PSZ    pszEAName,
  3511.                       USHORT *pwEAType,
  3512.                       PSZ    pszEAValue)
  3513. {
  3514.    EAOP2           stEAOPBuf;
  3515.    GEA2LIST        *pstGEA2List;
  3516.    FEA2LIST        *pstFEA2List;
  3517.    USHORT          cbMem;
  3518.    BOOL            bSuccess = TRUE;
  3519.  
  3520.    // To set up GEA2LIST structure allocate memory for the structure
  3521.    // plus the size of the string to get.
  3522.  
  3523.    cbMem = (USHORT) (sizeof (GEA2LIST) + strlen(pszEAName));
  3524.    pstGEA2List = (GEA2LIST *) malloc(cbMem);
  3525.    if (!pstGEA2List)
  3526.       return FALSE;
  3527.  
  3528.    // Next set the values of cbList, oNextEntryOffset, cbName, and copy
  3529.    // the string to find to szName.
  3530.  
  3531.    pstGEA2List->cbList = cbMem;
  3532.    pstGEA2List->list->oNextEntryOffset = 0;
  3533.    pstGEA2List->list->cbName = (BYTE) strlen(pszEAName);
  3534.    strcpy(pstGEA2List->list->szName, pszEAName);
  3535.  
  3536.    // Now set up the FEA2LIST structure.
  3537.  
  3538.    pstFEA2List = (FEA2LIST *) malloc(0x10000);
  3539.    if (!pstFEA2List)
  3540.       {
  3541.       free((CHAR *) pstGEA2List);
  3542.       return FALSE;
  3543.       }
  3544.  
  3545.    pstFEA2List->cbList = 0xFFFF;
  3546.  
  3547.    // Now set up the EAOP2 structure.
  3548.  
  3549.    stEAOPBuf.fpGEA2List = pstGEA2List;
  3550.    stEAOPBuf.fpFEA2List = pstFEA2List;
  3551.    stEAOPBuf.oError     = 0;
  3552.  
  3553.    // Now make the call to DosQueryPathInfo
  3554.  
  3555.    DosError(FERR_DISABLEHARDERR);
  3556.  
  3557.    if (DosQueryPathInfo(pszFilePath, 3L, &stEAOPBuf, sizeof (stEAOPBuf))
  3558.       || !pstFEA2List->list[0].cbValue)
  3559.       {
  3560.       DosError(FERR_ENABLEHARDERR);
  3561.       free((CHAR *) pstGEA2List);
  3562.       free((CHAR *) pstFEA2List);
  3563.       return (FALSE);
  3564.       }
  3565.    DosError(FERR_ENABLEHARDERR);
  3566.  
  3567.    // Use our common routine to parse the EA string.
  3568.  
  3569.    if (pstFEA2List->cbList > sizeof(ULONG))
  3570.       {
  3571.       bSuccess = GetEAFromPFEA(pstFEA2List->list,pwEAType,pszEAValue);
  3572.       }
  3573.    else
  3574.       {
  3575.       bSuccess = FALSE;
  3576.       }
  3577.  
  3578.    // Make sure allocated memory is freed.
  3579.  
  3580.    free((CHAR *) pstGEA2List);
  3581.    free((CHAR *) pstFEA2List);
  3582.  
  3583.    // Return success flag.
  3584.  
  3585.    return (USHORT)bSuccess;
  3586. }
  3587.  
  3588. /*---------------------------------------------------------------------------
  3589.         GetEAFromPFEA
  3590.  
  3591.         Extract string ea data from EAT_ASCII or EAT_MVMT feas...
  3592. ---------------------------------------------------------------------------*/
  3593. BOOL GetEAFromPFEA(PFEA2  pFEA,
  3594.                     USHORT *pwEAType,
  3595.                     PSZ    pszEAValue)
  3596. {
  3597.    FEA2            *pstFEA2;
  3598.    FEA2VALUE       *pstFEA2Value;
  3599.    EASTASCII       *pstEASTAscii;
  3600.    char            *pszNextEAValue;
  3601.    USHORT          i;
  3602.    BOOL            bSuccess = TRUE;
  3603.  
  3604.    // Get the location and length of the EA value string.
  3605.  
  3606.    pstFEA2      = pFEA;
  3607.    pstFEA2Value = (FEA2VALUE *) (pstFEA2->szName + pstFEA2->cbName + 1);
  3608.  
  3609.    // If the user passed in a buffer for the EA type, return it.
  3610.  
  3611.    if (pwEAType)
  3612.      *pwEAType = pstFEA2Value->wEAType;
  3613.  
  3614.    // If the user passed in a buffer for the EA value, attempt to return it.
  3615.  
  3616.    if (pszEAValue)
  3617.       {
  3618.       // Check to see if this is an EAT_ASCII or an EAT_MVMT string
  3619.       // (types we can handle)
  3620.  
  3621.       switch (pstFEA2Value->wEAType)
  3622.          {
  3623.          // Handle EAT_ASCII EA type
  3624.          case EAT_ASCII:
  3625.             memcpy(pszEAValue,
  3626.                    pstFEA2Value->unEATypes.stEATAscii.bValue,
  3627.                    pstFEA2Value->unEATypes.stEATAscii.cbValue);
  3628.             pszEAValue[pstFEA2Value->unEATypes.stEATAscii.cbValue] = '\0';
  3629.             break;
  3630.  
  3631.          // Handle EAT_MVMT EA type
  3632.          case EAT_MVMT:
  3633.             pstEASTAscii = (EASTASCII *) (((char *) &(pstFEA2Value->unEATypes.stEATMvmt.cItem)) + 2);
  3634.             pszNextEAValue = pszEAValue;
  3635.             for (i = 0; i < pstFEA2Value->unEATypes.stEATMvmt.cItem; ++i)
  3636.                {
  3637.                if (pstEASTAscii->wEASType == EAT_ASCII)
  3638.                   {
  3639.                   memcpy(pszNextEAValue,
  3640.                          pstEASTAscii->bValue,
  3641.                          pstEASTAscii->cbValue);
  3642.                   pszNextEAValue[pstEASTAscii->cbValue] = ',';
  3643.                   pszNextEAValue += pstEASTAscii->cbValue + 1;
  3644.                   pstEASTAscii = (EASTASCII *) (pstEASTAscii->bValue + pstEASTAscii->cbValue);
  3645.                   }
  3646.                }
  3647.             // null terminate the EA string
  3648.             if (pszNextEAValue > pszEAValue)    // EA string in buffer
  3649.                {
  3650.                *(pszNextEAValue - 1) = '\0';
  3651.                }
  3652.             else                        // no EA string
  3653.                {
  3654.                *pszEAValue = '\0';
  3655.                bSuccess = FALSE;
  3656.                }
  3657.             break;
  3658.  
  3659.          // Handle default case (Unknown EA types)
  3660.          default:
  3661.             bSuccess = FALSE;
  3662.             break;
  3663.          }
  3664.       }
  3665.  
  3666.    // Return success flag.
  3667.  
  3668.    return (bSuccess);
  3669. }
  3670.  
  3671. /*---------------------------------------------------------------------------
  3672.         GetFileName
  3673. ---------------------------------------------------------------------------*/
  3674. BOOL GetFileName(PSZ szFullPath)
  3675. {
  3676.    FILEDLG fileDialog;
  3677.  
  3678.    memset(&fileDialog, '\0', sizeof(FILEDLG));
  3679.  
  3680.    fileDialog.cbSize = sizeof(FILEDLG);
  3681.    fileDialog.fl = FDS_HELPBUTTON |
  3682.                      FDS_CENTER | FDS_SAVEAS_DIALOG | FDS_ENABLEFILELB;
  3683.    fileDialog.ulUser = 0;
  3684.    fileDialog.lReturn = 0;
  3685.    fileDialog.lSRC = 0;
  3686.    fileDialog.pszIType = NULL;
  3687.    fileDialog.papszITypeList = NULL;
  3688.    fileDialog.pszIDrive = NULL;
  3689.    fileDialog.papszIDriveList = NULL;
  3690.    fileDialog.hMod = (HMODULE)0;
  3691.    strcpy(fileDialog.szFullFile, szFullPath);
  3692.    fileDialog.papszFQFilename = NULL;
  3693.    fileDialog.ulFQFCount = 0;
  3694.    fileDialog.x = 0;
  3695.    fileDialog.y = 0;
  3696.    fileDialog.sEAType = 0;
  3697.  
  3698.    // Get the file
  3699.  
  3700.    if (!WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, (PFILEDLG)&fileDialog))
  3701.       return FALSE;
  3702.  
  3703.    if (fileDialog.lReturn != DID_OK)
  3704.       return FALSE;
  3705.  
  3706.    // Copy file name and path returned into buffers
  3707.  
  3708.    strcpy(szFullPath, fileDialog.szFullFile);
  3709.  
  3710.    return TRUE;
  3711. }
  3712.  
  3713. /*---------------------------------------------------------------------------
  3714.         SetEAFromName
  3715. ---------------------------------------------------------------------------*/
  3716. USHORT SetEAFromName(PSZ pszFilePath, PSZ pszEAName, PSZ pszEAValue)
  3717. {
  3718.    USHORT       cbValue;
  3719.    USHORT       cbMem;
  3720.    USHORT       rc;
  3721.    PFEA2LIST    pfea2l;
  3722.    PSZ          ptr, ptrEnd;
  3723.    PBYTE        ptrValue, ptrCurrent;
  3724.    EAOP2        eaop;
  3725.  
  3726.    ptr = pszEAValue;
  3727.    cbValue = 0;
  3728.    while (ptr && *ptr)
  3729.       {
  3730.       ptrEnd = strchr(ptr, ',');
  3731.       if (!ptrEnd)
  3732.          {
  3733.          ptrEnd = &ptr[strlen(ptr)];
  3734.          }
  3735.       cbValue += ((USHORT)(ptrEnd - ptr)) + 2 * sizeof(USHORT);
  3736.       ptr = ptrEnd;
  3737.       if (ptr && *ptr == ',')
  3738.          {
  3739.          ptr++;
  3740.          }
  3741.       }
  3742.    if (cbValue)
  3743.       {
  3744.       cbValue += 3 * sizeof(USHORT);
  3745.       }
  3746.    cbMem = (USHORT)sizeof(FEA2LIST) + strlen(pszEAName) + (USHORT)cbValue;
  3747.    pfea2l = (PFEA2LIST) malloc((ULONG)cbMem);
  3748.    if (!pfea2l)
  3749.       {
  3750.       return FALSE;
  3751.       }
  3752.    memset((PCH)pfea2l,0,cbMem);
  3753.    pfea2l->cbList = cbMem;
  3754.    pfea2l->list[0].cbName = (BYTE)strlen(pszEAName);
  3755.    pfea2l->list[0].cbValue = cbValue;
  3756.    strcpy(pfea2l->list[0].szName, pszEAName);
  3757.    if (cbValue)
  3758.       {
  3759.       ptr = pszEAValue;
  3760.       ptrValue = (PBYTE) &pfea2l->list[0].szName[ strlen(pszEAName) + 1 ];
  3761.       ptrCurrent = (PBYTE)(&(((PUSHORT)ptrValue)[3]));
  3762.          ((PUSHORT)ptrValue)[0] = EAT_MVMT;
  3763.       while (ptr && *ptr)
  3764.          {
  3765.          ptrEnd = strchr(ptr, ',');
  3766.          if (!ptrEnd)
  3767.             {
  3768.             ptrEnd = &ptr[strlen(ptr)];
  3769.             }
  3770.          ((PUSHORT)ptrCurrent)[0] = EAT_ASCII;
  3771.          ((PUSHORT)ptrCurrent)[1] = (USHORT)(ptrEnd - ptr);
  3772.          memcpy(&ptrCurrent[4], ptr, ((PUSHORT)ptrCurrent)[1]);
  3773.          ptrCurrent += ((PUSHORT)ptrCurrent)[1] + 4;
  3774.          ptr = ptrEnd;
  3775.          if (ptr && *ptr == ',')
  3776.             {
  3777.             ptr++;
  3778.             }
  3779.          ((PUSHORT)ptrValue)[2] += 1;
  3780.          }
  3781.       }
  3782.  
  3783.    eaop.fpGEA2List = NULL;
  3784.    eaop.fpFEA2List = pfea2l;
  3785.    eaop.oError     = 0;
  3786.  
  3787.    rc = (USHORT)DosSetPathInfo(pszFilePath, 2L, &eaop, sizeof(eaop), 0L);
  3788.  
  3789.    free((CHAR *)pfea2l);
  3790.  
  3791.    return (USHORT)(rc);
  3792. }
  3793.  
  3794. /*---------------------------------------------------------------------------
  3795.         WriteDragItemtoFile
  3796. ---------------------------------------------------------------------------*/
  3797. ODBoolean WriteDragItemtoFile(ODDragAndDrop *somSelf,
  3798.                               Environment *ev,
  3799.                               ODPtr    theItem,
  3800.                               ODUByte  *pathName,
  3801.                               ODUByte  *fileName,
  3802.                               PSZ      type)
  3803. {
  3804.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  3805.  
  3806.     CHAR szFileName[CCHMAXPATH];
  3807.     APIRET rc;
  3808.     HFILE hFile;
  3809.     ULONG ulAction, ulBytes;
  3810.     ULONG dataSize;
  3811.     PBYTE pbData;
  3812.     ODBoolean fSuccess = kODTrue;
  3813.  
  3814.     ODMemDragItem *theDragItem = (ODMemDragItem *)theItem;
  3815.  
  3816.     if (fileName && fileName[0] != '\0')
  3817.     {
  3818.         szFileName[0] = '\0';
  3819.         if (pathName != 0)
  3820.         {
  3821.             strcpy(szFileName, (char*)pathName);
  3822.             strcat(szFileName, "\\");
  3823.         }
  3824.         strcat(szFileName, (char*)fileName);
  3825.     }
  3826.     else
  3827.     {
  3828.         szFileName[0] = '\0';
  3829.         if (pathName != 0)
  3830.         {
  3831.             strcpy(szFileName, (char*)pathName);
  3832.             strcat(szFileName, "\\");
  3833.         }
  3834.         if (!(fSuccess = GetFileName(szFileName)))
  3835.             return(fSuccess);
  3836.     }
  3837.  
  3838.     theDragItem->Close(ev);
  3839.  
  3840.     dataSize = ODGetHandleSize(theDragItem->fContainerHandle);
  3841. #if ODDebug
  3842.     if (fDebugLogging)
  3843.         somPrintf("WriteDragItemtoFile: size = %ld\n", dataSize);
  3844. #endif
  3845.     ODLockHandle(theDragItem->fContainerHandle);
  3846.     pbData = (PBYTE)*((ODHandle)theDragItem->fContainerHandle);
  3847.  
  3848.     rc = DosOpen(szFileName,
  3849.                  &hFile,
  3850.                  &ulAction,
  3851.                  0,
  3852.                  FILE_NORMAL,
  3853.                  OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
  3854.                  OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
  3855.                  0);
  3856.     if (rc)
  3857.     {
  3858. #if ODDebug
  3859.         if (fDebugLogging)
  3860.             somPrintf("WriteDragItemtoFile: open failed: %d\n", rc);
  3861. #endif
  3862.         fSuccess = kODFalse;
  3863.     }
  3864.     else
  3865.     {
  3866.         DosWrite(hFile, (PVOID)pbData, dataSize, &ulBytes);
  3867.         DosClose(hFile);
  3868.         SetEAFromName(szFileName, ".TYPE", "OpenDoc Document");
  3869.         if (type && type[0])                                        // [140007]
  3870.             SetEAFromName(szFileName, "OD.KIND", type);
  3871.     }
  3872.  
  3873. //    ODDisposeHandle(theDragItem->fContainerHandle);
  3874. //    theDragItem->fContainerHandle = (ODHandle)kODNULL;
  3875.  
  3876.     ODUnlockHandle(theDragItem->fContainerHandle);        //TDF: commented in Merlin
  3877.  
  3878.     theDragItem->Open(ev);                                //TDF: commented in Merlin
  3879.  
  3880.    return(fSuccess);
  3881. }
  3882.  
  3883. // [129057]
  3884. void GiveMemoryIfNecessary(HWND hwndTarget, HWND hwndSource, PBYTE pbData)
  3885. {
  3886.    PID myPid, pid;
  3887.    TID myTid, tid;
  3888.  
  3889.    WinQueryWindowProcess(hwndTarget, &pid, &tid);
  3890.    WinQueryWindowProcess(hwndSource, &myPid, &myTid);
  3891.  
  3892.    // if this is intra-process, no need to give memory
  3893.    if (myPid != pid)
  3894.       {
  3895.       DosGiveSharedMem(pbData, pid, PAG_WRITE | PAG_READ);
  3896.       // I think this is unneeded ???
  3897.       DosFreeMem(pbData);
  3898.       }
  3899. }
  3900.  
  3901. PBYTE AllocSharedMem(PDRAGTRANSFER pDragTransfer, ULONG dataSize)
  3902. {
  3903.    APIRET       rc;
  3904.    PBYTE        pbData;
  3905.    PULONG       pulData;
  3906.  
  3907.    rc = DosAllocSharedMem((PPVOID)&pbData, 0, dataSize + sizeof(ULONG),
  3908.                      PAG_READ | PAG_WRITE | PAG_COMMIT |
  3909.                      OBJ_GIVEABLE | OBJ_GETTABLE | OBJ_TILE);
  3910.  
  3911.    if (rc)
  3912.       {
  3913.       pbData = 0;
  3914.       pDragTransfer->fsReply |= DMFL_RENDERFAIL;
  3915. #if ODDebug
  3916.                 if (fDebugLogging)
  3917.                         somPrintf("AllocSharedMem: Out of memory.\n");
  3918. #endif
  3919.       }
  3920.    else
  3921.       {
  3922.       pulData = (PULONG)pbData;
  3923.       *pulData = dataSize;
  3924.       pDragTransfer->fsReply |= (DMFL_NATIVERENDER | DMFL_RENDEROK);
  3925.       pDragTransfer->hstrRenderToName = (ULONG)pbData;
  3926.       }
  3927.  
  3928.    return(pbData);
  3929. }
  3930.  
  3931. void AddRMF(PSZ buf, LinkedList* fRMFList)
  3932. {
  3933.          if (strstr(buf,"DRF_OPENDOCDOCUMENT")) return;
  3934.          ODDragRMF* newRMF = new ODDragRMF(buf);
  3935.          fRMFList->AddLast(newRMF);
  3936. }
  3937.  
  3938. PSZ GetToken(PSZ start, PSZ buf)
  3939. {
  3940.    PSZ p = start;
  3941.    PSZ q = buf;
  3942.    while(*p) {
  3943.       if (*p == ',' || *p == ')') {
  3944.         break;
  3945.       }
  3946.       *q++ = *p;
  3947.       p++;
  3948.    }
  3949.    if (*p == ',') p++;
  3950.    if (q > buf) {
  3951.       *q = 0;
  3952.       return p;
  3953.    }
  3954.    else return kODNULL;
  3955. }
  3956.  
  3957. void AddXProductRMF(PSZ buf, LinkedList* fRMFList)
  3958. {
  3959.    CHAR mech[CCHMAXPATH],fmt[CCHMAXPATH], szRMF[CCHMAXPATH];
  3960.    PSZ p, q, r;
  3961.    p = buf;
  3962.    if (*p != '(') return;
  3963.    p++;
  3964.    q = strchr(p, '(');
  3965.    if (!q) return;
  3966.    q++;
  3967.    while(q = GetToken(q,fmt)) {
  3968.          r = p;
  3969.          while(r = GetToken(r,mech)) {
  3970.             sprintf(szRMF,"<%s,%s>",mech,fmt);
  3971.             AddRMF(szRMF,fRMFList);
  3972.          }
  3973.    }
  3974. }
  3975.  
  3976. PSZ GetNextRMF(PSZ buf)
  3977. {
  3978.    PSZ p = buf;
  3979.    PSZ q, pszNextRMF;
  3980.  
  3981.    if (*p == '<') {
  3982.       // Find the end of the RMF pair
  3983.       if (!(q = strchr(p,'>'))) return kODNULL;
  3984.    }
  3985.    else if (*p == '(') {
  3986.       // Find the end of the RMF cross product
  3987.       // A cross product has the form (mechanism,...) X (format,...)
  3988.       if (!(q = strchr(p,')'))) return kODNULL;
  3989.       if (!(q = strchr(q,'('))) return kODNULL;
  3990.       if (!(q = strchr(q,')'))) return kODNULL;
  3991.    }
  3992.    else {
  3993.       // The string must start with '<' or '('
  3994.       return kODNULL;
  3995.    }
  3996.  
  3997.    // Set q to the character just after the first RMF.
  3998.    // Set pszNextRMF to point to the next RMF or to the end of the string.
  3999.    pszNextRMF = ++q;
  4000.    while(*pszNextRMF)
  4001.    {
  4002.       if ((*pszNextRMF == '<') || (*pszNextRMF == '(')) break;
  4003.       pszNextRMF++;
  4004.    }
  4005.  
  4006.    // Insert a NULL character to terminate the first RMF string
  4007.    *q = 0;
  4008.  
  4009.    return pszNextRMF;
  4010. }
  4011.  
  4012. void ParseRMF(PSZ pszRMF, LinkedList *fRMFList)
  4013. {
  4014.    CHAR tbuf[CCHMAXPATH];
  4015.    strcpy(tbuf,pszRMF);
  4016.    PSZ p;
  4017.    while(p = GetNextRMF(tbuf)) {
  4018.       if (tbuf[0] == '<') {
  4019.          AddRMF(tbuf,fRMFList);
  4020.       }
  4021.       else AddXProductRMF(tbuf,fRMFList);
  4022.       strcpy(tbuf,p);
  4023.    }
  4024. }
  4025.  
  4026. ODBoolean SupportedRMF(PSZ theRMF)
  4027. {
  4028.    if (strstr(theRMF, "DRF_OPENDOCDOCUMENT")) return kODTrue;
  4029.    if (strstr(theRMF, "DRM_OS2FILE")) return kODTrue;
  4030.    if (strstr(theRMF, "DRM_SHAREDMEM")) return kODTrue;
  4031.    return kODFalse;
  4032. }
  4033.  
  4034. PSZ GetFormatFromRMF(PSZ buf)
  4035. {
  4036. static CHAR tbuf[CCHMAXPATH];
  4037. PSZ p;
  4038.          if (strncmp(buf,"<DRM_OS2FILE",12)) return kODNULL;
  4039.          PSZ q = strchr(buf,',');
  4040.          if (q) {
  4041.             q++;
  4042.             strcpy(tbuf,q);
  4043.             if (q = strchr(tbuf,'>')) {
  4044.                *q = 0;
  4045.                return tbuf;
  4046.             }
  4047.          }
  4048.          return kODNULL;
  4049. }
  4050.  
  4051. ODBoolean QueryRMF(PSZ pszRMF, PSZ mech, PSZ fmt)
  4052. {
  4053.    CHAR tbuf[CCHMAXPATH];
  4054.    if (*pszRMF != '<') return kODFalse;
  4055.    strcpy(tbuf,pszRMF);
  4056.    PSZ p = tbuf+1;
  4057.    PSZ q = strchr(p,',');
  4058.    if (!q) return kODFalse;
  4059.    *q++ = 0;
  4060.    strcpy(mech,p);
  4061.    p = strchr(q,'>');
  4062.    if (!p) return kODFalse;
  4063.    *p = 0;
  4064.    strcpy(fmt,q);
  4065.    return kODTrue;
  4066. }
  4067.  
  4068. ODBoolean KindInTypeList(PSZ kind, PSZ typeList)
  4069. {
  4070.     PSZ p,q;
  4071.     p = typeList;
  4072.  
  4073.     USHORT len = strlen(kind);
  4074.     while(p && *p)
  4075.     {
  4076.         q = strchr(p,',');
  4077.         if (!q)
  4078.             q = p + strlen(p);
  4079.         if (len == q-p && !strncmp(kind,p,len))
  4080.             return kODTrue;
  4081.         if (*q == ',')
  4082.             q++;
  4083.         p = q;
  4084.     }
  4085.     return kODFalse;
  4086. }
  4087.  
  4088. /*---------------------------------------------------------------------------
  4089.                              End of File
  4090. ---------------------------------------------------------------------------*/
  4091.