home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / PowerPlant / CSpinner / CSpinner.cp next >
Encoding:
Text File  |  1995-11-02  |  4.3 KB  |  93 lines  |  [TEXT/CWIE]

  1. // Author: François Pottier (pottier@clipper.ens.fr)
  2. // Release: November 2, 1995
  3. // This code may be used freely. Please drop me a note in email if you find bugs, possible enhancements, or just to say you like it.
  4.  
  5. // View this file as Geneva 9pt on a 17" monitor for best appearance.
  6.  
  7. // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  8.  
  9. #include "CSpinner.h"
  10. #include "PowerMacros.h"
  11. #include <UException.h>                                                                                // Include PowerPlant's exception handling headers
  12. #include <UDebugging.h>
  13.  
  14. // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  15. // Construction & destruction
  16. // Note that if a problem occurs, memory is not properly freed. I find it too much of a bother to unload the resources which have already been loaded.
  17.  
  18. CSpinner::CSpinner (short inAcurID)
  19. {
  20.     SAcurPtr            theAcurPtr;
  21.     short            theIndex;
  22.     CursHandle        theCursor;
  23.         
  24.     ThrowIfResFail_(mAcurHandle = (SAcurHandle) ::GetResource ('acur', inAcurID));                                // Get the main resource
  25.     ::DetachResource((Handle) mAcurHandle);                                                                // Detach it because we will modify its contents
  26.     ::HLock ((Handle) mAcurHandle);                                                                    // Lock it down before dereferencing it
  27.     theAcurPtr = *mAcurHandle;
  28.     
  29.     for (theIndex = 0; theIndex < theAcurPtr->itsFrameCount; theIndex++) {                                        // Walk the frame list
  30.         ThrowIfResFail_(theCursor = (CursHandle) ::GetCursor(HiWord(theAcurPtr->itsFrame[theIndex])));                // At first each entry contains the ID of a 'CURS' resource
  31.         ::HLock((Handle) theCursor);                                                                    // Which we now load and lock
  32.         theAcurPtr->itsFrame[theIndex] = theCursor;                                                        // And write into the entry
  33.     }
  34.     
  35.     mTickInterval = theAcurPtr->itsCurrentFrame;                                                            // Read the tick interval from the 'acur' resource
  36.     mTaskInstalled = false;
  37. }
  38.  
  39. // If the destructor is called because an exception has been raised, the user probably hasn't been able to call Stop. We'll do that for him.
  40. // We release mAcurHandle. We do not release the 'CURS' resources, though. This isn't a leak since the next calls to GetCursor will retrieve the same copies of the cursors.
  41.  
  42. CSpinner::~CSpinner ()
  43. {
  44.     if (mTaskInstalled)
  45.         Stop();
  46.     
  47.     ::DisposeHandle((Handle) mAcurHandle);
  48. }
  49.  
  50. // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  51. // The VBL task itself.
  52. // This routine assumes that the address of the VBLTask structure is the same as the address of the CSpinner object. This hack allows us not to mess with A5 at all.
  53.  
  54. VBLTASKPROTOTYPE
  55. {
  56.     CSpinner                *theSpinner;
  57.     register SAcurPtr        theAcurPtr;
  58.     
  59.     theSpinner = (CSpinner*) inTaskPtr;                                                                    // Retrieve the address of the CSpinner object (skanky hack)
  60.     theAcurPtr = *theSpinner->mAcurHandle;                                                                // Retrieve the address of the SAcurRec structure
  61.     ::SetCursor(*theAcurPtr->itsFrame[theAcurPtr->itsCurrentFrame++]);                                        // Set the cursor to the next frame
  62.     if (theAcurPtr->itsCurrentFrame == theAcurPtr->itsFrameCount)                                            // If the last frame was just used, cycle
  63.         theAcurPtr->itsCurrentFrame = 0;
  64.     inTaskPtr->vblCount = theSpinner->mTickInterval;                                                        // Reset the VBL task
  65. }
  66.  
  67. // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  68. // Installing and removing the VBL task.
  69.  
  70. void CSpinner::Spin (void)
  71. {
  72.     MakeStaticRoutineDesc(MyTask, uppVBLProcInfo)
  73.     
  74.     Assert_(!mTaskInstalled);                                                                            // Sanity check
  75.     
  76.     (*mAcurHandle)->itsCurrentFrame = 0;
  77.     
  78.     mTask.qType = 1;                                                                                // Set up the VBL task
  79.     mTask.vblAddr = (VBLUPP) ConditionalRD(MyTask);
  80.     mTask.vblCount = mTickInterval;
  81.     mTask.vblPhase = 0;
  82.     ThrowIfOSErr_(::VInstall ((QElemPtr) &mTask));                                                        // Install it
  83.     
  84.     mTaskInstalled = true;
  85. }
  86.  
  87. void CSpinner::Stop (void)
  88. {
  89.     Assert_(mTaskInstalled);                                                                            // Sanity check
  90.     ThrowIfOSErr_(::VRemove ((QElemPtr) &mTask));                                                        // Remove the VBL task
  91.     mTaskInstalled = false;
  92.     ::InitCursor();                                                                                    // Restore the standard cursor
  93. }