home *** CD-ROM | disk | FTP | other *** search
- #include "GifScan.h"
- #include "GSDrag.h"
- #include "DSUtils.h"
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
-
- // === Function Prototypes ===
-
- pascal OSErr DragTrackingFunc(
- DragTrackingMessage theMessage,
- WindowPtr theWindow,
- void *theRefCon,
- DragReference theDragRef);
-
- pascal OSErr DragReceiveFunc(
- WindowPtr theWindow,
- void *theRefCon,
- DragReference theDragRef);
-
- Boolean DragItemsAreAcceptable(
- DragReference theDragRef,
- DragInfoHandle dragInfo);
-
-
- // === Static Global Variables ===
-
- static Boolean currentDragIsAcceptable;
- static Boolean currentDragWasInReceiveRgn;
- static Boolean dragInitiatedInWindow;
-
- extern Boolean gHasDrag;
-
-
- // ------------------------------------------------------------------------
- // IsDragManagerInstalled
- // ------------------------------------------------------------------------
- /*
- * Return whether the Drag Manager is present on the current System
- */
-
- Boolean IsDragManagerInstalled(void)
- {
- long response;
- return ( (Gestalt(gestaltDragMgrAttr, &response) == noErr) &&
- ((response & (1L << gestaltDragMgrPresent)) != 0) );
- }
-
-
- // ------------------------------------------------------------------------
- // InitDragInfo
- // ------------------------------------------------------------------------
- /*
- * Installs Drag Manager tracking and receive handler functions for
- * a particular window
- *
- * Call this function to set up a window for receiving dragged items.
- *
- * The caller must fill in the following fields of the DragInfoRecord,
- * a Handle to which is passed to this function:
- *
- * window Mac WindowPtr
- * flavor Type of data that can be receive (4-charcter code)
- * receiveRgn Region, in local coordinates of window, that can
- * accept dragged items
- * receiveFunc Pointer to function to be called for each item
- * dragged and dropped in the receiveRgn
- *
- * Returns a Drag Manager error code if there was a problem installing
- * the handler functions
- */
-
- OSErr InitDragInfo( DragInfoHandle dragInfo )
- {
- OSErr err = noErr;
- DragTrackingHandlerUPP trackingProc;
- DragReceiveHandlerUPP receiveProc;
-
- if (!gHasDrag) return noErr;
-
- trackingProc = NewDragTrackingHandlerProc(DragTrackingFunc);
- (**dragInfo).dragTrackingProc = trackingProc;
- err = InstallTrackingHandler(trackingProc, (**dragInfo).window, dragInfo);
- if (err != noErr) return err;
-
- receiveProc = NewDragReceiveHandlerProc(DragReceiveFunc);
- (**dragInfo).dragReceiveProc = receiveProc;
- err = InstallReceiveHandler(receiveProc, (**dragInfo).window, dragInfo);
-
- return err;
- }
-
-
- // ------------------------------------------------------------------------
- // KillDragInfo
- // ------------------------------------------------------------------------
- /*
- * Removes Drag Manager tracking and receive handler functions
- *
- * Call this function before disposing of a window, passing the same
- * DragInfoHandle as was passed to InitDragInfo()
- */
-
- void KillDragInfo( DragInfoHandle dragInfo )
- {
- OSErr err;
-
- if (!gHasDrag) return;
-
- err = RemoveTrackingHandler((**dragInfo).dragTrackingProc,
- (**dragInfo).window);
- err = RemoveReceiveHandler((**dragInfo).dragReceiveProc,
- (**dragInfo).window);
- }
-
-
- // ------------------------------------------------------------------------
- // DragTrackingFunc
- // ------------------------------------------------------------------------
- /*
- * Tracking Handler for the Drag Manager
- *
- * This handler function is installed by InitDragInfo() and removed
- * by KillDragInfo()
- *
- * The Drag Manager calls this function while items are being dragged
- * inside one of our windows
- */
-
- pascal OSErr DragTrackingFunc(
- DragTrackingMessage theMessage,
- WindowPtr theWindow,
- void *theRefCon,
- DragReference theDragRef)
- {
- OSErr err = noErr;
- DragInfoHandle dragInfo = (DragInfoHandle) theRefCon;
- DragAttributes attributes;
-
- GetDragAttributes(theDragRef, &attributes);
-
- switch (theMessage)
- {
- case dragTrackingEnterWindow:
- // Items have just been dragged into one of our windows
- // Find out if the items being dragged are acceptable
- // by our Window.
- currentDragIsAcceptable = DragItemsAreAcceptable(theDragRef, dragInfo);
- currentDragWasInReceiveRgn = false;
- break;
-
- case dragTrackingInWindow:
- // Items are being dragged in one of our windows
- if (currentDragIsAcceptable)
- {
- // Find out where the mouse is in our window
- Point mouseLocation;
- GetDragMouse(theDragRef, &mouseLocation, nil);
- GlobalToLocal(&mouseLocation);
-
- // According to the Drag Manager Human Interface
- // Guidelines, the area that can receive the
- // drag is hilited while the mouse is inside it.
- // However, no hiliting occurs until the mouse
- // leaves the area in which the drag started.
-
- if (attributes & dragHasLeftSenderWindow)
- {
- if (PtInRgn(mouseLocation, (**dragInfo).receiveRgn))
- {
- // Drag is now inside our receive region
- if (!currentDragWasInReceiveRgn)
- {
- // Previously, it was not inside, so
- // we must show the hiliting
- ShowDragHilite(theDragRef, (**dragInfo).receiveRgn,
- true);
- currentDragWasInReceiveRgn = true;
- }
-
- } else
- {
- // Drag is now outside of our receive region
- if (currentDragWasInReceiveRgn)
- {
- // Previously, it was inside, so we
- // must hide the hiliting
- HideDragHilite(theDragRef);
- currentDragWasInReceiveRgn = false;
- }
- }
- }
- }
- break;
-
- case dragTrackingLeaveWindow:
- // Items have been dragged out of one of our windows,
- // or a drag has been completed. We must remove the
- // hiliting of the receive region.
- if (currentDragIsAcceptable && currentDragWasInReceiveRgn)
- {
- SetPort((**dragInfo).window);
- HideDragHilite(theDragRef);
- }
- currentDragIsAcceptable = false;
- break;
- }
-
- return err;
- }
-
-
- // ------------------------------------------------------------------------
- // DragReceiveFunc
- // ------------------------------------------------------------------------
- /*
- * Receive Handler for the Drag Manager
- *
- * This handler function is installed by InitDragInfo() and removed
- * by KillDragInfo()
- *
- * The Drag Manager calls this function when acceptable items have been
- * dragged and dropped into the receive region of one of our windows
- */
-
- pascal OSErr DragReceiveFunc( WindowRef theWindow, void *theRefCon, DragReference theDragRef)
- {
- OSErr err = noErr;
- unsigned short itemCount;
- unsigned short itemIndex;
-
- // Loop thru each item in the Drag, and call the
- // user-supplied callback function. A pointer to
- // the callback function must be passed in the
- // DragInfoHandle passed to InitDragInfo()
-
- DragItemReceiveFunc receiveFunc =
- (**((DragInfoHandle)theRefCon)).receiveFunc;
-
- CountDragItems(theDragRef, &itemCount);
- for (itemIndex = 1; itemIndex <= itemCount; itemIndex++)
- {
- ItemReference theItem;
-
- GetDragItemReferenceNumber(theDragRef, itemIndex, &theItem);
- err = (*receiveFunc)(theWindow, theDragRef, theItem);
- if (err != noErr) break;
- }
-
- return err;
- }
-
-
- // ------------------------------------------------------------------------
- // DragItemsAreAcceptable
- // ------------------------------------------------------------------------
- /*
- * Return whether all the items in a particular Drag can be accepted.
- *
- * An item is acceptable if it contains data of the Flavor specified in
- * the DragInfoHandle passed to InitDragInfo()
- */
-
- Boolean DragItemsAreAcceptable( DragReference theDragRef, DragInfoHandle dragInfo)
- {
- unsigned short itemCount;
- unsigned short itemIndex;
- ItemReference theItem;
- OSErr err;
- FlavorFlags theFlags;
- FlavorType theFlavor = (**dragInfo).flavor;
-
- // Check whether each item contains data with the
- // acceptable flavor
-
- CountDragItems(theDragRef, &itemCount);
-
- for (itemIndex = 1; itemIndex <= itemCount; itemIndex++)
- {
- GetDragItemReferenceNumber(theDragRef, itemIndex, &theItem);
-
- err = GetFlavorFlags(theDragRef, theItem, theFlavor, &theFlags);
-
- // GetFlavorFlags will return an error if the item
- // does not contain data with the specified Flavor
- if ( err != noErr ) return false;
- }
-
- return true;
- }
-
- OSErr ReceiveHFSDrag(WindowRef theWindow, DragReference theDrag, ItemReference theItem)
- {
- OSErr err = nil;
- HFSFlavor hfsData;
- Size dataSize = sizeof(HFSFlavor);
-
- // The data associated with items of flavorTypeHFS is
- // a HFSFlavor record, which contains, among other
- // things, the FSSpec for the file
-
- GetFlavorData(theDrag, theItem, flavorTypeHFS, (Ptr)&hfsData, &dataSize, 0);
-
- if ( !dragInitiatedInWindow && currentDragIsAcceptable)
- SendODOCToSelf(&(hfsData.fileSpec));
- return err;
- }
-
-
- // Next stuff handles drag out the window
- static Ptr GetSelectedTextPtr(TEHandle teh)
- {
- return( *(*teh)->hText + (*teh)->selStart );
- }
-
- static short GetSelectionSize(TEHandle teh)
- {
- return( (*teh)->selEnd - (*teh)->selStart );
- }
-
- Boolean HandleDragSelection(EventRecord *event, RgnHandle dragRegion)
- {
- RgnHandle tempRgn;
- Point localMPt;
- DragReference theDrag;
- Point theLoc;
- TEHandle teh;
- short result;
- DragAttributes attributes;
- AEDesc dropLocation;
- short mouseDownModifiers, mouseUpModifiers;
- Boolean succes = true;
- Rect srcRect;
-
- SetPt(&theLoc, 0, 0);
- LocalToGlobal(&theLoc);
- OffsetRgn(dragRegion, theLoc.h, theLoc.v);
-
- teh = ((DocumentPeek)gOutWindow)->docTE;
- localMPt = event->where;
- GlobalToLocal(&localMPt);
- dragInitiatedInWindow = true;
- while ( StillDown() )
- {
- if ( WaitMouseMoved(event->where) )
- {
- srcRect = (*dragRegion)->rgnBBox;
- NewDrag(&theDrag);
- AddDragItemFlavor(theDrag, 1, 'TEXT', GetSelectedTextPtr(teh), GetSelectionSize(teh), 0);
- SetDragSendProc(theDrag, nil, (void *)teh);
- SetDragItemBounds(theDrag, 1, &(**dragRegion).rgnBBox);
- tempRgn = NewRgn();
- CopyRgn(dragRegion, tempRgn);
- InsetRgn(tempRgn, 1, 1);
- DiffRgn(dragRegion, tempRgn, dragRegion);
- DisposeRgn(tempRgn);
- result = TrackDrag(theDrag, event, dragRegion);
- if ( ( result != noErr ) && ( result != userCanceledErr ) )
- {
- return(succes);
- }
- GetDragAttributes(theDrag, &attributes);
- if ( !(attributes & dragInsideSenderApplication) )
- {
- GetDropLocation(theDrag, &dropLocation);
- GetDragModifiers(theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers);
- AEDisposeDesc(&dropLocation);
- }
- }
- else
- // User did not initiate a drag
- DoContentClick(gOutWindow, event);
- }
-
- dragInitiatedInWindow = false;
- return(succes);
- }
-