home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 January / macformat-033.iso / mac / Shareware City / Graphics / GifScan 1.6 / Sources / GSDragStuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-08  |  10.5 KB  |  380 lines  |  [TEXT/MMCC]

  1. #include "GifScan.h"
  2. #include "GSDrag.h"
  3. #include "DSUtils.h"
  4.  
  5. #ifndef __GESTALTEQU__
  6. #include <GestaltEqu.h>
  7. #endif
  8.  
  9.  
  10. // === Function  Prototypes === 
  11.  
  12. pascal OSErr DragTrackingFunc(
  13.     DragTrackingMessage        theMessage,
  14.     WindowPtr                theWindow,
  15.     void                    *theRefCon,
  16.     DragReference            theDragRef);
  17.     
  18. pascal OSErr DragReceiveFunc(
  19.     WindowPtr        theWindow,
  20.     void            *theRefCon,
  21.     DragReference    theDragRef);
  22.     
  23. Boolean    DragItemsAreAcceptable(
  24.     DragReference    theDragRef,
  25.     DragInfoHandle    dragInfo);
  26.     
  27.  
  28. // === Static Global Variables === 
  29.  
  30. static Boolean    currentDragIsAcceptable;
  31. static Boolean    currentDragWasInReceiveRgn;
  32. static Boolean    dragInitiatedInWindow;
  33.  
  34. extern Boolean gHasDrag;
  35.  
  36.  
  37. // ------------------------------------------------------------------------ 
  38. //    IsDragManagerInstalled                                                    
  39. // ------------------------------------------------------------------------ 
  40. /*
  41.  *    Return whether the Drag Manager is present on the current System
  42.  */
  43.  
  44. Boolean    IsDragManagerInstalled(void)
  45. {
  46.     long    response;
  47.     return ( (Gestalt(gestaltDragMgrAttr, &response) == noErr) &&
  48.              ((response & (1L << gestaltDragMgrPresent)) != 0) );
  49. }
  50.  
  51.  
  52. // ------------------------------------------------------------------------ 
  53. //    InitDragInfo                                                            
  54. // ------------------------------------------------------------------------ 
  55. /*
  56.  *    Installs Drag Manager tracking and receive handler functions for
  57.  *    a particular window
  58.  *
  59.  *    Call this function to set up a window for receiving dragged items.
  60.  *
  61.  *    The caller must fill in the following fields of the DragInfoRecord,
  62.  *    a Handle to which is passed to this function:
  63.  *
  64.  *        window            Mac WindowPtr
  65.  *        flavor            Type of data that can be receive (4-charcter code)
  66.  *        receiveRgn        Region, in local coordinates of window, that can
  67.  *                            accept dragged items
  68.  *        receiveFunc        Pointer to function to be called for each item
  69.  *                            dragged and dropped in the receiveRgn
  70.  *
  71.  *    Returns a Drag Manager error code if there was a problem installing
  72.  *        the handler functions
  73.  */
  74.  
  75. OSErr InitDragInfo( DragInfoHandle dragInfo )
  76. {
  77.     OSErr    err = noErr;
  78.     DragTrackingHandlerUPP    trackingProc;
  79.     DragReceiveHandlerUPP    receiveProc;
  80.     
  81.     if (!gHasDrag) return noErr;
  82.     
  83.     trackingProc = NewDragTrackingHandlerProc(DragTrackingFunc);
  84.     (**dragInfo).dragTrackingProc = trackingProc;
  85.     err = InstallTrackingHandler(trackingProc, (**dragInfo).window, dragInfo);
  86.     if (err != noErr) return err;
  87.     
  88.     receiveProc = NewDragReceiveHandlerProc(DragReceiveFunc);
  89.     (**dragInfo).dragReceiveProc = receiveProc;
  90.     err = InstallReceiveHandler(receiveProc, (**dragInfo).window, dragInfo);
  91.     
  92.     return err;
  93. }
  94.  
  95.  
  96. // ------------------------------------------------------------------------ 
  97. //    KillDragInfo                                                            
  98. // ------------------------------------------------------------------------ 
  99. /*
  100.  *    Removes Drag Manager tracking and receive handler functions
  101.  *
  102.  *    Call this function before disposing of a window, passing the same
  103.  *    DragInfoHandle as was passed to InitDragInfo()
  104.  */
  105.  
  106. void KillDragInfo( DragInfoHandle dragInfo )
  107. {
  108.     OSErr    err;
  109.     
  110.     if (!gHasDrag) return;
  111.     
  112.     err = RemoveTrackingHandler((**dragInfo).dragTrackingProc,
  113.                                     (**dragInfo).window);
  114.     err = RemoveReceiveHandler((**dragInfo).dragReceiveProc,
  115.                                     (**dragInfo).window);
  116. }
  117.  
  118.  
  119. // ------------------------------------------------------------------------ 
  120. //    DragTrackingFunc                                                        
  121. // ------------------------------------------------------------------------ 
  122. /*
  123.  *    Tracking Handler for the Drag Manager
  124.  *
  125.  *    This handler function is installed by InitDragInfo() and removed
  126.  *    by KillDragInfo()
  127.  *
  128.  *    The Drag Manager calls this function while items are being dragged
  129.  *    inside one of our windows
  130.  */
  131.  
  132. pascal OSErr DragTrackingFunc(
  133.     DragTrackingMessage        theMessage,
  134.     WindowPtr                theWindow,
  135.     void                    *theRefCon,
  136.     DragReference            theDragRef)
  137. {
  138.     OSErr            err = noErr;
  139.     DragInfoHandle    dragInfo = (DragInfoHandle) theRefCon;
  140.     DragAttributes    attributes;
  141.     
  142.     GetDragAttributes(theDragRef, &attributes);
  143.     
  144.     switch (theMessage) 
  145.     {        
  146.         case dragTrackingEnterWindow:
  147.                 // Items have just been dragged into one of our windows 
  148.                 // Find out if the items being dragged are acceptable     
  149.                 // by our Window.                                          
  150.             currentDragIsAcceptable = DragItemsAreAcceptable(theDragRef, dragInfo);
  151.             currentDragWasInReceiveRgn = false;
  152.             break;
  153.             
  154.         case dragTrackingInWindow:
  155.                 // Items are being dragged in one of our windows 
  156.             if (currentDragIsAcceptable) 
  157.             {
  158.                     // Find out where the mouse is in our window 
  159.                 Point    mouseLocation;
  160.                 GetDragMouse(theDragRef, &mouseLocation, nil);
  161.                 GlobalToLocal(&mouseLocation);
  162.  
  163.                     // According to the Drag Manager Human Interface 
  164.                     // Guidelines, the area that can receive the     
  165.                     // drag is hilited while the mouse is inside it. 
  166.                     // However, no hiliting occurs until the mouse     
  167.                     // leaves the area in which the drag started.     
  168.                 
  169.                 if (attributes & dragHasLeftSenderWindow) 
  170.                 {
  171.                     if (PtInRgn(mouseLocation, (**dragInfo).receiveRgn)) 
  172.                     {
  173.                             // Drag is now inside our receive region 
  174.                         if (!currentDragWasInReceiveRgn) 
  175.                         {
  176.                                 // Previously, it was not inside, so 
  177.                                 // we must show the hiliting         
  178.                             ShowDragHilite(theDragRef, (**dragInfo).receiveRgn,
  179.                                                 true);
  180.                             currentDragWasInReceiveRgn = true;
  181.                         }
  182.                         
  183.                     } else 
  184.                     {
  185.                             // Drag is now outside of our receive region 
  186.                         if (currentDragWasInReceiveRgn) 
  187.                         {
  188.                                 // Previously, it was inside, so we 
  189.                                 // must hide the hiliting            
  190.                             HideDragHilite(theDragRef);
  191.                             currentDragWasInReceiveRgn = false;
  192.                         }
  193.                     }
  194.                 }
  195.             }
  196.             break;
  197.             
  198.         case dragTrackingLeaveWindow:
  199.                 // Items have been dragged out of one of our windows, 
  200.                 // or a drag has been completed. We must remove the      
  201.                 // hiliting of the receive region.                      
  202.             if (currentDragIsAcceptable && currentDragWasInReceiveRgn) 
  203.             {
  204.                 SetPort((**dragInfo).window);
  205.                 HideDragHilite(theDragRef);
  206.             }
  207.             currentDragIsAcceptable = false;
  208.             break;
  209.     }
  210.     
  211.     return err;
  212. }
  213.  
  214.  
  215. // ------------------------------------------------------------------------ 
  216. //    DragReceiveFunc                                                            
  217. // ------------------------------------------------------------------------ 
  218. /*
  219.  *    Receive Handler for the Drag Manager
  220.  *
  221.  *    This handler function is installed by InitDragInfo() and removed
  222.  *    by KillDragInfo()
  223.  *
  224.  *    The Drag Manager calls this function when acceptable items have been
  225.  *    dragged and dropped into the receive region of one of our windows
  226.  */
  227.  
  228. pascal OSErr DragReceiveFunc( WindowRef    theWindow, void    *theRefCon, DragReference theDragRef)
  229. {
  230.     OSErr    err = noErr;
  231.     unsigned short    itemCount;
  232.     unsigned short    itemIndex;
  233.     
  234.         // Loop thru each item in the Drag, and call the 
  235.         // user-supplied callback function. A pointer to 
  236.         // the callback function must be passed in the     
  237.         // DragInfoHandle passed to InitDragInfo()         
  238.     
  239.         DragItemReceiveFunc    receiveFunc =
  240.         (**((DragInfoHandle)theRefCon)).receiveFunc;
  241.     
  242.     CountDragItems(theDragRef, &itemCount);
  243.     for (itemIndex = 1; itemIndex <= itemCount; itemIndex++) 
  244.     {
  245.         ItemReference    theItem;
  246.         
  247.         GetDragItemReferenceNumber(theDragRef, itemIndex, &theItem);
  248.         err = (*receiveFunc)(theWindow, theDragRef, theItem);
  249.         if (err != noErr) break;
  250.     }
  251.     
  252.     return err;
  253. }
  254.  
  255.  
  256. // ------------------------------------------------------------------------ 
  257. //    DragItemsAreAcceptable                                                    
  258. // ------------------------------------------------------------------------ 
  259. /*
  260.  *    Return whether all the items in a particular Drag can be accepted.
  261.  *
  262.  *    An item is acceptable if it contains data of the Flavor specified in
  263.  *    the DragInfoHandle passed to InitDragInfo()
  264.  */
  265.  
  266. Boolean    DragItemsAreAcceptable( DragReference theDragRef, DragInfoHandle dragInfo)
  267. {
  268.     unsigned short    itemCount;
  269.     unsigned short    itemIndex;
  270.     ItemReference    theItem;
  271.     OSErr            err;
  272.     FlavorFlags        theFlags;
  273.     FlavorType        theFlavor = (**dragInfo).flavor;
  274.     
  275.     // Check whether each item contains data with the 
  276.     // acceptable flavor                              
  277.     
  278.     CountDragItems(theDragRef, &itemCount);
  279.     
  280.     for (itemIndex = 1; itemIndex <= itemCount; itemIndex++) 
  281.     {
  282.         GetDragItemReferenceNumber(theDragRef, itemIndex, &theItem);
  283.         
  284.         err = GetFlavorFlags(theDragRef, theItem, theFlavor, &theFlags);
  285.         
  286.             // GetFlavorFlags will return an error if the item 
  287.             // does not contain data with the specified Flavor 
  288.         if ( err != noErr ) return false;
  289.     }
  290.     
  291.     return true;
  292. }
  293.  
  294. OSErr ReceiveHFSDrag(WindowRef theWindow, DragReference theDrag, ItemReference theItem)
  295. {
  296.     OSErr        err = nil;
  297.     HFSFlavor    hfsData;
  298.     Size        dataSize = sizeof(HFSFlavor);
  299.     
  300.         // The data associated with items of flavorTypeHFS is 
  301.         // a HFSFlavor record, which contains, among other      
  302.         // things, the FSSpec for the file                      
  303.  
  304.     GetFlavorData(theDrag, theItem, flavorTypeHFS, (Ptr)&hfsData, &dataSize, 0);
  305.     
  306.     if ( !dragInitiatedInWindow && currentDragIsAcceptable) 
  307.         SendODOCToSelf(&(hfsData.fileSpec));
  308.     return err;
  309. }
  310.  
  311.  
  312. // Next stuff handles drag out the window
  313. static Ptr GetSelectedTextPtr(TEHandle teh)
  314. {
  315.     return( *(*teh)->hText + (*teh)->selStart );
  316. }
  317.  
  318. static short GetSelectionSize(TEHandle teh)
  319. {
  320.     return( (*teh)->selEnd - (*teh)->selStart );
  321. }
  322.  
  323. Boolean HandleDragSelection(EventRecord *event, RgnHandle dragRegion)
  324. {
  325.     RgnHandle            tempRgn;
  326.     Point                localMPt;
  327.     DragReference        theDrag;
  328.     Point                theLoc;
  329.     TEHandle            teh;
  330.     short                result;
  331.     DragAttributes        attributes;
  332.     AEDesc                dropLocation;
  333.     short                mouseDownModifiers, mouseUpModifiers;
  334.     Boolean                succes = true;
  335.     Rect                srcRect;
  336.  
  337.     SetPt(&theLoc, 0, 0);
  338.     LocalToGlobal(&theLoc);
  339.     OffsetRgn(dragRegion, theLoc.h, theLoc.v);
  340.     
  341.     teh = ((DocumentPeek)gOutWindow)->docTE;
  342.     localMPt = event->where;
  343.     GlobalToLocal(&localMPt);
  344.     dragInitiatedInWindow = true;
  345.     while ( StillDown() )
  346.     {
  347.         if ( WaitMouseMoved(event->where) )
  348.         {
  349.             srcRect = (*dragRegion)->rgnBBox;
  350.             NewDrag(&theDrag);
  351.             AddDragItemFlavor(theDrag, 1, 'TEXT', GetSelectedTextPtr(teh), GetSelectionSize(teh), 0);
  352.             SetDragSendProc(theDrag, nil, (void *)teh);
  353.             SetDragItemBounds(theDrag, 1, &(**dragRegion).rgnBBox);
  354.             tempRgn = NewRgn();
  355.             CopyRgn(dragRegion, tempRgn);
  356.             InsetRgn(tempRgn, 1, 1);
  357.             DiffRgn(dragRegion, tempRgn, dragRegion);
  358.             DisposeRgn(tempRgn);
  359.             result = TrackDrag(theDrag, event, dragRegion);
  360.             if ( ( result != noErr ) && ( result != userCanceledErr ) )
  361.             {
  362.                 return(succes);
  363.             }
  364.             GetDragAttributes(theDrag, &attributes);
  365.             if ( !(attributes & dragInsideSenderApplication) ) 
  366.             {
  367.                 GetDropLocation(theDrag, &dropLocation);
  368.                 GetDragModifiers(theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers);
  369.                 AEDisposeDesc(&dropLocation);
  370.             }
  371.         }
  372.         else
  373.             // User did not initiate a drag
  374.             DoContentClick(gOutWindow, event);
  375.     }
  376.  
  377.     dragInitiatedInWindow = false;
  378.     return(succes);
  379. }
  380.