home *** CD-ROM | disk | FTP | other *** search
- /*
- HASDragNDrop.c from Hsoi's App Shell © 1995-1997 John C. Daub. All rights reserved.
-
- This file contains fun stuff and junk dealing with ways to support drag-and-drop
- text editing.
-
- Parts (if not all) of this file were based upon the WEDemoDrags.c file from the
- WASTE Demo app (by Marco Piovanelli), and sample code from Michael Kamprath
- from his WASTE Object Handler's library.
- */
-
-
- #pragma mark ••• #includes •••
-
- #ifndef _WASTE_
- #include "WASTE.h"
- #endif
- #include "HASGlobals.h"
- #ifndef __HSOIS_APP_SHELL__
- #include "HASMain.h"
- #endif
- #include "HASWindows.h"
- #include "HASDragNDrop.h"
- #include "HASUtilities.h"
-
- #include "WASTE_Objects.h"
-
- #if HAS_DEBUG
- #include "HASUtilTest.h"
- #endif
-
- #pragma mark -
- #pragma mark ••• Drag Handlers •••
-
-
- /*
- * This function is called repeatedly by the Drag Manager (cause we installed it elsewhere
- * in the code to do this) as our application's method for tracking drags
- */
- pascal OSErr HsoiMyTrackingHandler( DragTrackingMessage message, WindowRef window, void *refCon, DragReference drag )
- {
- #pragma unused ( refCon )
-
- OSErr reply = noErr;
- GrafPtr oldPort;
-
- // if we don't have any windows, what's the point..
-
- if ( window == nil )
- return noErr;
-
- // if by chance we have a sound playing, stop it
-
- if ( SoundIsPlaying() )
- StopCurrentSound();
-
- // we don't do drag and drop for dialogs (tho it is possible, it's just not in the scope
- // of this app shell, at least at the moment)
-
- if ( HsoiIsDialogWindow( window ) )
- return noErr;
-
- // the clipboard window shouldn't recieve drags..that'd be silly.
-
- if ( HsoiIsClipboardWindow( window ) )
- return noErr;
-
- #if HAS_DEBUG
-
- // no drags to the test window
-
- if ( HsoiIsTestWindow( window ) )
- return noErr;
-
- #endif
-
- // and finally, all's cool, let's do something!
-
- if ( HsoiIsDocumentWindow( window ) )
- {
- // save the old graphics port and set the graphics port to our window
-
- GetPort( &oldPort );
- SetPortWindowPort( window );
-
- // track the drag...since the only windows in this app shell that can take a
- // drag are windows with WASTE instances, we'll just call a WASTE routine to
- // handle stuff...no need to write my own thing...
-
- reply = WETrackDrag( message, drag, (*HsoiGetWindowDocument(window))->we );
-
- // restore the graphics port...
-
- SetPort( oldPort );
-
- return reply;
- }
- else // it's not an app window
- {
- reply = noErr;
-
- return reply;
- }
- }
-
-
- /*
- * this function is called when a drag is to be received (pretty much after the drag has
- * been tracked, and the mouse has been released). What will happen is that if it's a
- * kosher drag and a kosher window to receive the drag, if the item being dragged is a file
- * type that we recognize (in this case, 'TEXT' and 'ttro' files), let's open it up and
- * insert that text into the file (as opposed to other HFS types, like a disk or a folder
- * or a file type that's not TEXT...in which case, Michael Kamprath's WASTE Object Handlers
- * will insert a HFS object. Also, this code was based on some sample code that Kamprath wrote.
- */
-
- pascal OSErr HsoiMyReceiveHandler( WindowRef window, void *refCon, DragReference drag )
- {
- #pragma unused ( refCon )
-
- OSErr reply = noErr;
- GrafPtr oldPort;
- long oldNLines, newNLines;
- ItemReference theItem;
- Size itemSize;
- Ptr textP;
- StScrpHandle styleH;
- WESoupHandle soupH;
- HFSFlavor **theHFS;
- long insertionOffset, curEOF;
- unsigned short items, index;
- short fRefNum;
- Point zeroPoint = {0,0};
- Point mouse;
- LongPt dropLocation;
- WEEdge dropEdge;
-
- // if there's no window, what's the point?
-
- if ( window == nil )
- return noErr;
-
- // if by chance a sound is playing, stop it
-
- if ( SoundIsPlaying() )
- StopCurrentSound();
-
- // we don't deal with drags over dialog boxes...
-
- if ( HsoiIsDialogWindow( window ) )
- return noErr;
-
- // and drags over the clipboard window shouldn't be accepted...that'd be silly
-
- if ( HsoiIsClipboardWindow( window ) )
- return noErr;
-
- #if HAS_DEUBG
-
- // and why drag over the test window?
-
- if ( HsoiIsTestWindow( window ) )
- return noErr;
-
- #endif
-
- // all's good...let's receive it!
-
- if ( HsoiIsDocumentWindow( window ) )
- {
-
- // save the old graphics port and set the current port to our window.
-
- GetPort( &oldPort );
- SetPortWindowPort( window );
-
- // count how many lines of text are currently in the window (necessary for updating)
-
- oldNLines = WECountLines( (*HsoiGetWindowDocument(window))->we );
-
- // see how many items are in the drag
-
- CountDragItems( drag, &items );
-
- // step through each drag item and check for text files
-
- for ( index = 1; index <= items; index++ )
- {
- // get the refnum for each dragged item
-
- GetDragItemReferenceNumber( drag, index, &theItem );
-
- // check the drag item for it's size and to make sure it's kosher.
-
- if ( !( reply = GetFlavorDataSize( drag, theItem, flavorTypeHFS, &itemSize )))
- {
- // found a text file, now import it to the WASTE instance
-
-
- // create a handle to hold our text file's text.
-
- theHFS = (HFSFlavor **)NewHandleClear( sizeof(HFSFlavor));
-
- // if we successfully get a handle...
-
- if ( theHFS )
- {
- // ...lock it down in memory
-
- HLockHi( (Handle)theHFS );
-
- // find out the flavor of the drag.
-
- GetFlavorData( drag, theItem, flavorTypeHFS, *theHFS, &itemSize, 0L );
-
- // if it's a TEXT or ttro flavor...
-
- if (( (*theHFS)->fileType == TYPE_TEXT ) || ( (*theHFS)->fileType == TYPE_TEXT_READ_ONLY ))
- {
- // ...load the text file into memory
- // this is pretty much just like reading in any old file....
-
- // oh, and there should be better error checking/handling in here...
-
- // open the data fork of the file
-
- reply = FSpOpenDF( &(*theHFS)->fileSpec, fsCurPerm, &fRefNum );
-
- // get the end-of-file marker (to find out the size of the text)
-
- reply = GetEOF( fRefNum, &curEOF );
-
- // get a place in memory to hold our text.
-
- textP = NewPtrClear( curEOF );
-
- // start reading the file from the beginning
-
- reply = SetFPos( fRefNum, fsFromStart, 0 );
-
- // read the file in.
-
- reply = FSRead( fRefNum, &curEOF, textP );
-
- // close the file
-
- reply = FSClose( fRefNum );
-
- // let's open the resource fork
-
- fRefNum = FSpOpenResFile( &(*theHFS)->fileSpec, fsCurPerm );
-
- // if there is a resource fork (FSpOpenResFile returns -1 if no res fork)
-
- if ( fRefNum != -1 )
- {
- // has a resource fork, so look for style and soup
-
- // the "128" is arbitrary really...
-
- styleH = (StScrpHandle)Get1Resource( TYPE_STYLE, 128 );
-
- // check for errors (mostly check to see if we got a resource)
-
- reply = ResError();
-
- if ( reply ) // didn't get anything, so make the handle nil
- styleH = nil;
- else // got something, so detach it for proper handling.
- DetachResource( (Handle)styleH );
-
- // repeat the same for the SOUP resource
-
- soupH = (WESoupHandle)Get1Resource( TYPE_SOUP, 128 );
- reply = ResError();
- if ( reply )
- soupH = nil;
- else
- DetachResource( (Handle)soupH );
-
- // close the resource fork.
-
- CloseResFile( fRefNum );
- }
- else
- {
- // does not have resource fork, so no style or soup
-
- styleH = nil;
- soupH = nil;
- }
-
- // insert the text file into the current position
-
- reply = GetDragMouse( drag, &mouse, &zeroPoint );
- if ( reply != noErr )
- goto cleanup;
-
- // find out where the mouse is relative to our current graphic's port
- // (our window)
-
- GlobalToLocal( &mouse );
-
- // convert this point to a long-point data structure for WASTE's sake
-
- WEPointToLongPoint( mouse, &dropLocation );
-
- // find where the insertion offset is
-
- insertionOffset = WEGetOffset( &dropLocation, &dropEdge, (*HsoiGetWindowDocument(window))->we );
-
- // set the selection range
-
- WESetSelection( insertionOffset, insertionOffset, (*HsoiGetWindowDocument(window))->we );
-
- // insert the text file into the current window/text
-
- reply = WEInsert( textP, curEOF, styleH, soupH, (*HsoiGetWindowDocument(window))->we );
-
- // reset the selection range with the new text
-
- WESetSelection( insertionOffset, insertionOffset + curEOF, (*HsoiGetWindowDocument(window))->we );
-
- // dispose of memory
- cleanup:
- HUnlock( (Handle)theHFS );
- HsoiForgetHandle( (Handle *)&theHFS );
- DisposePtr( textP );
-
- if ( styleH )
- HsoiForgetHandle( (Handle *)&styleH );
- if (soupH )
- HsoiForgetHandle( (Handle *)&soupH );
-
-
- // update the WASTE instance if need be
- newNLines = WECountLines( (*HsoiGetWindowDocument(window))->we );
-
- if ( newNLines != oldNLines )
- {
- HsoiViewChanged( window );
- }
-
- // restore the old graphic's port
-
- SetPort( oldPort );
-
- return ( reply );
- }
- // either it's not a text file (so we just skip right to this) or it was
- // a text file so we're cleaning up. either way, we're just cleaning things
- // up
-
- HUnlock( (Handle)theHFS );
- HsoiForgetHandle( (Handle *) &theHFS );
- }
- }
-
- // if the code got to here, that means there was no text file item
- // in the drag, let WASTE handle the drag then.
-
- HideDragHilite( drag ); // somtimes necessary for cosmetic purposes
-
- // and here we go...
-
- reply = WEReceiveDrag( drag, (*HsoiGetWindowDocument(window))->we );
-
- // check for a need to update things, and if so, update the window.
-
- newNLines = WECountLines( (*HsoiGetWindowDocument(window))->we );
-
- if ( newNLines != oldNLines )
- {
- HsoiViewChanged( window );
- }
- }
-
- // if we get here, simply enough, the drag isn't accepted, so other things elsewhere
- // in the code must be called to possibly handle the drag.
-
- reply = dragNotAcceptedErr;
-
- // restore the old graphic's port
-
- SetPort( oldPort );
-
- }
- else // all's not good, so we're not gonna receive it
- {
- reply = noErr;
-
- return reply;
- }
-
- return noErr;
- }
-