home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Frameworks / Hsoi's App Shell 1.0a4 / Hsoi's App Shell Source / HASDragNDrop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-28  |  10.2 KB  |  397 lines  |  [TEXT/CWIE]

  1. /*    
  2.     HASDragNDrop.c from Hsoi's App Shell © 1995-1997 John C. Daub.  All rights reserved.
  3.  
  4.     This file contains fun stuff and junk dealing with ways to support drag-and-drop
  5.     text editing.
  6.     
  7.     Parts (if not all) of this file were based upon the WEDemoDrags.c file from the
  8.     WASTE Demo app (by Marco Piovanelli), and sample code from Michael Kamprath
  9.     from his WASTE Object Handler's library.
  10. */
  11.  
  12.  
  13. #pragma mark ••• #includes •••
  14.  
  15. #ifndef _WASTE_
  16. #include "WASTE.h"
  17. #endif
  18. #include "HASGlobals.h"
  19. #ifndef __HSOIS_APP_SHELL__
  20. #include "HASMain.h"
  21. #endif
  22. #include "HASWindows.h"
  23. #include "HASDragNDrop.h"
  24. #include "HASUtilities.h"
  25.  
  26. #include "WASTE_Objects.h"
  27.  
  28. #if HAS_DEBUG
  29. #include "HASUtilTest.h"
  30. #endif
  31.  
  32. #pragma mark -
  33. #pragma mark ••• Drag Handlers •••
  34.  
  35.  
  36. /*
  37.  *    This function is called repeatedly by the Drag Manager (cause we installed it elsewhere
  38.  *    in the code to do this) as our application's method for tracking drags
  39.  */
  40. pascal OSErr    HsoiMyTrackingHandler( DragTrackingMessage message, WindowRef window, void *refCon, DragReference drag )
  41. {
  42. #pragma unused ( refCon )
  43.  
  44.     OSErr            reply = noErr;
  45.     GrafPtr            oldPort;
  46.     
  47.     // if we don't have any windows, what's the point..
  48.         
  49.     if ( window == nil )
  50.         return noErr;
  51.         
  52.     // if by chance we have a sound playing, stop it
  53.     
  54.     if ( SoundIsPlaying() )
  55.         StopCurrentSound();
  56.     
  57.     // we don't do drag and drop for dialogs (tho it is possible, it's just not in the scope
  58.     // of this app shell, at least at the moment)
  59.     
  60.     if ( HsoiIsDialogWindow( window ) )
  61.         return noErr;
  62.     
  63.     // the clipboard window shouldn't recieve drags..that'd be silly.
  64.         
  65.     if ( HsoiIsClipboardWindow( window ) )
  66.         return noErr;
  67.  
  68. #if HAS_DEBUG
  69.  
  70.     // no drags to the test window
  71.     
  72.     if ( HsoiIsTestWindow( window ) )
  73.         return noErr;
  74.  
  75. #endif
  76.  
  77.     // and finally, all's cool, let's do something!
  78.     
  79.     if ( HsoiIsDocumentWindow( window ) )
  80.     {        
  81.         // save the old graphics port and set the graphics port to our window
  82.     
  83.         GetPort( &oldPort );
  84.         SetPortWindowPort( window );
  85.                 
  86.         // track the drag...since the only windows in this app shell that can take a
  87.         // drag are windows with WASTE instances, we'll just call a WASTE routine to
  88.         // handle stuff...no need to write my own thing...
  89.  
  90.         reply = WETrackDrag( message, drag, (*HsoiGetWindowDocument(window))->we );
  91.         
  92.         // restore the graphics port...
  93.         
  94.         SetPort( oldPort );
  95.         
  96.         return reply;
  97.     }
  98.     else // it's not an app window
  99.     {
  100.         reply = noErr;
  101.         
  102.         return reply;
  103.     }
  104. }
  105.  
  106.  
  107. /*
  108.  *    this function is called when a drag is to be received (pretty much after the drag has
  109.  *    been tracked, and the mouse has been released).  What will happen is that if it's a
  110.  *    kosher drag and a kosher window to receive the drag, if the item being dragged is a file
  111.  *    type that we recognize (in this case, 'TEXT' and 'ttro' files), let's open it up and
  112.  *    insert that text into the file (as opposed to other HFS types, like a disk or a folder
  113.  *    or a file type that's not TEXT...in which case, Michael Kamprath's WASTE Object Handlers
  114.  *    will insert a HFS object.  Also, this code was based on some sample code that Kamprath wrote.
  115.  */
  116.  
  117. pascal    OSErr    HsoiMyReceiveHandler( WindowRef window, void *refCon, DragReference drag )
  118. {
  119. #pragma unused ( refCon )
  120.  
  121.     OSErr            reply = noErr;
  122.     GrafPtr            oldPort;
  123.     long            oldNLines, newNLines;
  124.     ItemReference    theItem;
  125.     Size            itemSize;
  126.     Ptr                textP;
  127.     StScrpHandle    styleH;
  128.     WESoupHandle    soupH;
  129.     HFSFlavor        **theHFS;
  130.     long            insertionOffset, curEOF;
  131.     unsigned short    items, index;
  132.     short            fRefNum;
  133.     Point            zeroPoint = {0,0};
  134.     Point            mouse;
  135.     LongPt            dropLocation;
  136.     WEEdge            dropEdge;
  137.     
  138.     // if there's no window, what's the point?
  139.     
  140.     if ( window == nil )
  141.         return noErr;
  142.         
  143.     // if by chance a sound is playing, stop it
  144.     
  145.     if ( SoundIsPlaying() )
  146.         StopCurrentSound();
  147.     
  148.     // we don't deal with drags over dialog boxes...
  149.     
  150.     if ( HsoiIsDialogWindow( window ) )
  151.         return noErr;
  152.     
  153.     // and drags over the clipboard window shouldn't be accepted...that'd be silly
  154.         
  155.     if ( HsoiIsClipboardWindow( window ) )
  156.         return noErr;
  157.         
  158. #if HAS_DEUBG
  159.  
  160.     // and why drag over the test window?
  161.     
  162.     if ( HsoiIsTestWindow( window ) )
  163.         return noErr;
  164.  
  165. #endif
  166.         
  167.     // all's good...let's receive it!
  168.     
  169.     if ( HsoiIsDocumentWindow( window ) )
  170.     {        
  171.     
  172.         // save the old graphics port and set the current port to our window.
  173.         
  174.         GetPort( &oldPort );
  175.         SetPortWindowPort( window );
  176.         
  177.         // count how many lines of text are currently in the window (necessary for updating)
  178.         
  179.         oldNLines = WECountLines( (*HsoiGetWindowDocument(window))->we );
  180.         
  181.         // see how many items are in the drag
  182.         
  183.         CountDragItems( drag, &items );
  184.         
  185.         // step through each drag item and check for text files
  186.         
  187.         for ( index = 1; index <= items; index++ )
  188.         {
  189.             // get the refnum for each dragged item
  190.             
  191.             GetDragItemReferenceNumber( drag, index, &theItem );
  192.             
  193.             // check the drag item for it's size and to make sure it's kosher.
  194.             
  195.             if ( !( reply = GetFlavorDataSize( drag, theItem, flavorTypeHFS, &itemSize )))
  196.             {
  197.                 // found a text file, now import it to the WASTE instance
  198.                 
  199.                 
  200.                 // create a handle to hold our text file's text.
  201.                 
  202.                 theHFS = (HFSFlavor **)NewHandleClear( sizeof(HFSFlavor));
  203.                 
  204.                 // if we successfully get a handle...
  205.                 
  206.                 if ( theHFS )
  207.                 {
  208.                     // ...lock it down in memory
  209.                     
  210.                     HLockHi( (Handle)theHFS );
  211.                     
  212.                     // find out the flavor of the drag.
  213.                     
  214.                     GetFlavorData( drag, theItem, flavorTypeHFS, *theHFS, &itemSize, 0L );
  215.                     
  216.                     // if it's a TEXT or ttro flavor...
  217.                     
  218.                     if (( (*theHFS)->fileType == TYPE_TEXT ) || ( (*theHFS)->fileType == TYPE_TEXT_READ_ONLY ))
  219.                     {
  220.                         // ...load the text file into memory
  221.                         // this is pretty much just like reading in any old file....
  222.                         
  223.                         // oh, and there should be better error checking/handling in here...
  224.                         
  225.                         // open the data fork of the file
  226.                         
  227.                         reply = FSpOpenDF( &(*theHFS)->fileSpec, fsCurPerm, &fRefNum );
  228.                         
  229.                         // get the end-of-file marker (to find out the size of the text)
  230.                         
  231.                         reply = GetEOF( fRefNum, &curEOF );
  232.                         
  233.                         // get a place in memory to hold our text.
  234.                         
  235.                         textP = NewPtrClear( curEOF );
  236.                         
  237.                         // start reading the file from the beginning
  238.                         
  239.                         reply = SetFPos( fRefNum, fsFromStart, 0 );
  240.                         
  241.                         // read the file in.
  242.                         
  243.                         reply = FSRead( fRefNum, &curEOF, textP );
  244.                         
  245.                         // close the file
  246.                         
  247.                         reply = FSClose( fRefNum );
  248.                         
  249.                         // let's open the resource fork
  250.                         
  251.                         fRefNum = FSpOpenResFile( &(*theHFS)->fileSpec, fsCurPerm );
  252.                         
  253.                         // if there is a resource fork (FSpOpenResFile returns -1 if no res fork)
  254.                         
  255.                         if ( fRefNum != -1 )
  256.                         {
  257.                             // has a resource fork, so look for style and soup
  258.                             
  259.                             // the "128" is arbitrary really...
  260.                             
  261.                             styleH = (StScrpHandle)Get1Resource( TYPE_STYLE, 128 );
  262.                             
  263.                             // check for errors (mostly check to see if we got a resource)
  264.                             
  265.                             reply = ResError();
  266.                             
  267.                             if ( reply ) // didn't get anything, so make the handle nil
  268.                                 styleH = nil;
  269.                             else // got something, so detach it for proper handling.
  270.                                 DetachResource( (Handle)styleH );
  271.                             
  272.                             // repeat the same for the SOUP resource
  273.                             
  274.                             soupH = (WESoupHandle)Get1Resource( TYPE_SOUP, 128 );
  275.                             reply = ResError();
  276.                             if ( reply )
  277.                                 soupH = nil;
  278.                             else
  279.                                 DetachResource( (Handle)soupH );
  280.                             
  281.                             // close the resource fork.
  282.                             
  283.                             CloseResFile( fRefNum );
  284.                         }
  285.                         else
  286.                         {
  287.                             // does not have resource fork, so no style or soup
  288.                             
  289.                             styleH = nil;
  290.                             soupH = nil;
  291.                         }
  292.                         
  293.                         // insert the text file into the current position
  294.                         
  295.                         reply = GetDragMouse( drag, &mouse, &zeroPoint );
  296.                         if ( reply != noErr )
  297.                             goto cleanup;
  298.                         
  299.                         // find out where the mouse is relative to our current graphic's port
  300.                         // (our window)
  301.                         
  302.                         GlobalToLocal( &mouse );
  303.                         
  304.                         // convert this point to a long-point data structure for WASTE's sake
  305.                         
  306.                         WEPointToLongPoint( mouse, &dropLocation );
  307.                         
  308.                         // find where the insertion offset is
  309.                         
  310.                         insertionOffset = WEGetOffset( &dropLocation, &dropEdge, (*HsoiGetWindowDocument(window))->we );
  311.                         
  312.                         // set the selection range
  313.                         
  314.                         WESetSelection( insertionOffset, insertionOffset, (*HsoiGetWindowDocument(window))->we );
  315.                         
  316.                         // insert the text file into the current window/text
  317.                         
  318.                         reply = WEInsert( textP, curEOF, styleH, soupH, (*HsoiGetWindowDocument(window))->we );
  319.                         
  320.                         // reset the selection range with the new text
  321.                         
  322.                         WESetSelection( insertionOffset, insertionOffset + curEOF, (*HsoiGetWindowDocument(window))->we );
  323.                         
  324.                         // dispose of memory
  325. cleanup:
  326.                         HUnlock( (Handle)theHFS );
  327.                         HsoiForgetHandle( (Handle *)&theHFS );
  328.                         DisposePtr( textP );
  329.                         
  330.                         if ( styleH )
  331.                             HsoiForgetHandle( (Handle *)&styleH );
  332.                         if (soupH )
  333.                             HsoiForgetHandle( (Handle *)&soupH );
  334.                             
  335.                         
  336.                         // update the WASTE instance if need be                        
  337.                         newNLines = WECountLines( (*HsoiGetWindowDocument(window))->we );
  338.  
  339.                         if ( newNLines != oldNLines )
  340.                         {
  341.                             HsoiViewChanged( window );
  342.                         }
  343.                         
  344.                         // restore the old graphic's port
  345.                         
  346.                         SetPort( oldPort );
  347.                         
  348.                         return ( reply );
  349.                     }
  350.                     // either it's not a text file (so we just skip right to this) or it was
  351.                     // a text file so we're cleaning up.  either way, we're just cleaning things
  352.                     // up
  353.                     
  354.                     HUnlock( (Handle)theHFS );
  355.                     HsoiForgetHandle( (Handle *) &theHFS );
  356.                 }
  357.             }
  358.             
  359.             // if the code got to here, that means there was no text file item
  360.             // in the drag, let WASTE handle the drag then.
  361.             
  362.             HideDragHilite( drag ); // somtimes necessary for cosmetic purposes
  363.         
  364.             // and here we go...
  365.  
  366.             reply = WEReceiveDrag( drag, (*HsoiGetWindowDocument(window))->we );
  367.                 
  368.             // check for a need to update things, and if so, update the window.
  369.             
  370.             newNLines = WECountLines( (*HsoiGetWindowDocument(window))->we );
  371.  
  372.             if ( newNLines != oldNLines )
  373.             {
  374.                 HsoiViewChanged( window );
  375.             }
  376.         }
  377.  
  378.         // if we get here, simply enough, the drag isn't accepted, so other things elsewhere
  379.         // in the code must be called to possibly handle the drag.
  380.         
  381.         reply = dragNotAcceptedErr;
  382.         
  383.         // restore the old graphic's port
  384.             
  385.         SetPort( oldPort );
  386.         
  387.     }
  388.     else // all's not good, so we're not gonna receive it
  389.     {
  390.         reply = noErr;
  391.         
  392.         return reply;
  393.     }
  394.             
  395.     return noErr;
  396. }
  397.