home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Games / Showwit! 1.0 / source code / Source / CShApp.p next >
Encoding:
Text File  |  1996-02-11  |  24.8 KB  |  846 lines  |  [TEXT/PJMM]

  1. {****************************************************}
  2. {}
  3. {        CShApp.p                                                                                                                                                                                                                }
  4. {}
  5. {        Application class for the Showwit application.                                                                                                    }
  6. {}
  7. {****************************************************}
  8.  
  9.  
  10. unit CShApp;
  11.  
  12. interface
  13.  
  14.     uses
  15.         TCL, ShIntf;
  16.  
  17. implementation
  18.  
  19.     const
  20.         kExtraMasters = 32;  (* number of extra master pointer blocks *)
  21.         kRainyDay = 32000;            (* total rainy day memory reserve size     *)
  22.         kCriticalBalance = 30000;    (* portion of rainy day for critical operations *)
  23.         kToolboxBalance = 20000;    (* portion of rainy day for toolbox reserve *)
  24.  
  25.     const
  26.         kNumAppHelpMenuItems = 1;
  27.  
  28. {****************************************************}
  29. {}
  30. {        IShApp                                                                                                                                                                                                                        }
  31. {}
  32. {        Construction of the application object, and initialization of the sounds.                            }
  33. {        The other initializations are from the Starter project.                                                                            }
  34. {}
  35. {****************************************************}
  36.  
  37.     procedure CShApp.IShApp;
  38.  
  39.         var
  40.             theAppLevelsDirector: CShAppLevelsDirector;
  41.             thePrefsFile: CHandlePrefs;
  42.             theGameDirector: CShGameDirector;
  43.  
  44.         { We have a number of particular sounds to look for, and an }
  45.         { unknown number of flipping sounds. }
  46.         procedure InitSATSounds;
  47.  
  48.             var
  49.                 theCounter, theLoadCount: Integer;
  50.                 rHandle: Handle;
  51.                 rID: Integer;
  52.                 rType: ResType;
  53.                 rName: Str255;
  54.  
  55.         begin { InitSATSounds }
  56.             SATSoundInit;
  57.  
  58.             { If there are resource errors in the following, the handles are set to nil. }
  59.             { This is a safe condition. }
  60.  
  61.             gSoundGameStarting := Get1Resource('snd ', sndGameStarting);
  62.             gSoundGameComplete := Get1Resource('snd ', sndGameComplete);
  63.             gSoundGameAborted := Get1Resource('snd ', sndGameAborted);
  64.             gSoundNewBestPlayer := Get1Resource('snd ', sndNewBestPlayer);
  65.             gSoundWelcome := Get1Resource('snd ', sndWelcome);    { Disposed of early, so load last. }
  66.  
  67.             SetResLoad(FALSE);    { Do not need resource, just information. }
  68.  
  69.             gNumFlipSounds := 0;
  70.  
  71.             { Go 1-deep, just into the application resource. }
  72.  
  73.             for theCounter := 1 to Count1Resources('snd ') do begin
  74.                 rHandle := Get1IndResource('snd ', theCounter);
  75.                 GetResInfo(rHandle, rID, rType, rName);
  76.                 if rID >= sndFlipBase then begin
  77.                     gNumFlipSounds := gNumFlipSounds + 1;
  78.                 end; { if }
  79.             end; { for }
  80.  
  81.             SetResLoad(TRUE);
  82.  
  83.             if gNumFlipSounds > 0 then begin
  84.                 gFlipSoundHandles := HandleArrayH(NewHandleCanFail(SizeOf(Handle) * gNumFlipSounds));
  85.                 FailNIL(gFlipSoundHandles);
  86.  
  87.                 theLoadCount := 1;
  88.                 for theCounter := 1 to Count1Resources('snd ') do begin
  89.                     rHandle := Get1IndResource('snd ', theCounter);
  90.                     GetResInfo(rHandle, rID, rType, rName);
  91.                     if rID >= sndFlipBase then begin
  92. {$PUSH}
  93. {$R-}
  94.                         gFlipSoundHandles^^[theLoadCount] := rHandle;
  95. {$POP}
  96.                         theLoadCount := theLoadCount + 1;
  97.                     end; { if }
  98.                 end; { for }
  99.             end { if }
  100.             else begin
  101.                 gFlipSoundHandles := nil;
  102.             end; { else }
  103.         end; { InitSATSounds }
  104.  
  105.     begin { IShApp }
  106.         itsAppLevelsDirector := nil;
  107.         itsGameDirector := nil;
  108.         itsPrefsFile := nil;
  109.         itsLevelsDoc := nil;
  110.  
  111.         IApplication(kExtraMasters, kRainyDay, kCriticalBalance, kToolboxBalance);
  112.  
  113.         { The parameters to IApplication are the number of times to call MoreMasters,    }
  114.         { the number of bytes of heap space to reserve for monitoring }
  115.         { low memory situations, and the credit limit for memory requests. }
  116.         {   Four (4) is a reasonable number of MoreMasters calls, }
  117.         { but you should determine a good number for your application }
  118.         { by observing the heap using Lightsbug, }
  119.         { TMON, or Macsbug. Set this parameter to zero, give your }
  120.         { program a rigorous work-out, then look at the heap and count }
  121.         { how many master pointer blocks have been allocated. Master }
  122.         { pointer blocks are nonrelocatable and have a size of $100 }
  123.         { (hex). You should call MoreMasters at least this many }
  124.         { times -- add a few extra just to be safe. The purpose of all }
  125.         { this preflighting is to prevent heap fragmentation. You }
  126.         { don't want the Memory Manager to call MoreMasters and }
  127.         { create a nonrelocatable block in the middle of your heap. By }
  128.         { calling MoreMasters at the very beginning of the program, }
  129.         { you ensure that these blocks are allocated in a group at the }
  130.         { bottom of the heap. }
  131.         { 10 Feb 1996 - Counted 25 such blocks. }
  132.         {   The memory reserve is a safeguard for handling low memory }
  133.         { conditions and is used by the GrowMemory method in }
  134.         { CApplication (check there for more comments). In general, }
  135.         { your program should never request a memory block greater }
  136.         { than this reserve size without explicitly checking in }
  137.         { advance whether there is enough free memory to satisfy the }
  138.         { the request. }
  139.         {   The credit limit specifies a cut-off level for memory    }
  140.         { requests which can tap the memory reserve. Requests larger }
  141.         { than this size will not use the memory reserve when the    }
  142.         { system pleads for more memory. }
  143.  
  144.         { Initialize the SAT Sound stuff, and load the sounds which we shall use. }
  145.         { We have to do this here, because the preference file will change the resource.}
  146.  
  147.         InitSATSounds;
  148.  
  149.         { Create the application levels director. }
  150.  
  151.         new(theAppLevelsDirector);
  152.         theAppLevelsDirector.IShAppLevelsDirector(SELF, CurResFile);
  153.         itsAppLevelsDirector := theAppLevelsDirector;
  154.  
  155.         { Now create the preferences file. }
  156.  
  157.         new(thePrefsFile);
  158.         thePrefsFile.IHandlePrefs(STRlistPrefMessages, kSignaturePreferencesFile, TRUE, kNumberOfPrefs);
  159.         itsPrefsFile := thePrefsFile;
  160.  
  161.         { The game director. }
  162.  
  163.         new(theGameDirector);
  164.         itsGameDirector := theGameDirector;
  165.         itsGameDirector.IShGameDirector(SELF);
  166.     end; { IShApp }
  167.  
  168.  
  169. {****************************************************}
  170. {}
  171. {        MakeBartender                                                                                                                                                                                                }
  172. {}
  173. {        Build a bartender which can handle the application help menu.                                                     }
  174. {}
  175. {****************************************************}
  176.  
  177.     procedure CShApp.MakeBartender;
  178.  
  179.         var
  180.             theBartenderHM: CBartenderHelpMenu;
  181.  
  182.     begin { MakeBartender }
  183.         new(theBartenderHM);
  184.         gBartender := theBartenderHM;
  185.         theBartenderHM.IBartenderHelpMenu(MBARapp);
  186.     end; { MakeBartender }
  187.  
  188.  
  189. {****************************************************}
  190. {}
  191. {        SetUpFileParameters                                                                                                                                                                                }
  192. {}
  193. {        Recognized file types and the application signature.                                                                                     }
  194. {}
  195. {****************************************************}
  196.  
  197.     procedure CShApp.SetUpFileParameters;
  198.  
  199.     begin { SetUpFileParameters }
  200.         inherited SetUpFileParameters;    { Be sure to call the default method }
  201.  
  202.         {    sfNumTypes is the number of file types your application knows about. }
  203.         {    sfFileTypes[] is an array of file types. }
  204.         {    You can define up to 4 file types in sfFileTypes[]. }
  205.  
  206.         { The application knows about both levels and it preferences file. }
  207.         { However we don't want to be able to open the preferences file }
  208.         { from the Open… dialog. }
  209.         sfNumTypes := 1;
  210.         sfFileTypes[0] := kSignatureLevelsFiles;
  211.  
  212.         { We still have to check elsewhere for filetype, since we want to }
  213.         { be able to context switch (from the Finder) if we double click }
  214.         { on the preferences file. }
  215.  
  216.         {    Although it's not an instance variable, this method is a good place to set the}
  217.         {    gSignature global variable. Set this global to your application 's signature. }
  218.         {    You' ll use it to create a file (see CFile.CreateNew). }
  219.  
  220.         gSignature := kSignatureApplication;
  221.     end; { SetUpFileParameters }
  222.  
  223.  
  224. {****************************************************}
  225. {}
  226. {        SetUpMenus                                                                                                                                                                                                        }
  227. {}
  228. {        Insert the items into the application help menu.                                                                                                 }
  229. {}
  230. {****************************************************}
  231.  
  232.     procedure CShApp.SetUpMenus;
  233.  
  234.     begin { SetUpMenus }
  235.         inherited SetUpMenus;
  236.         CBartenderHelpMenu(gBartender).AddHelpMenuItems(STRlistAppHelpMenu, kNumAppHelpMenuItems);
  237.     end; { SetUpMenus }
  238.  
  239.  
  240. {****************************************************}
  241. {}
  242. {        DoCommand                                                                                                                                                                                                            }
  243. {}
  244. {     The application is responsible for calling up the about/help dialog,                                         }
  245. {     for calling the default levels reader, and for communicating with                                         }
  246. {     the levels document or preferences file about the best players.                                                 }
  247. {}
  248. {****************************************************}
  249.  
  250.     procedure CShApp.DoCommand (theCommand: longint);
  251.  
  252.         { Create and call the about/help director with the appropriate first screen. }
  253.         procedure DoAboutAndHelp;
  254.  
  255.             var
  256.                 theAboutDirector: CShHelpDirector;
  257.  
  258.         begin { DoAbout }
  259.             new(theAboutDirector);
  260.             theAboutDirector.IShHelpDirector(SELF);
  261.             if theCommand = cmdAbout then begin
  262.                 theAboutDirector.DoAboutAndHelp(AboutScreen);
  263.             end { if }
  264.             else begin
  265.                 theAboutDirector.DoAboutAndHelp(HelpScreen);
  266.             end; { else }
  267.             ForgetObject(theAboutDirector);
  268.         end; { DoAbout }
  269.  
  270.         { If there is no active levels document, clear the preferences file. }
  271.         { Otherwise call the active document. }
  272.         procedure DoClearBestPlayers;
  273.  
  274.         begin { DoClearBestPlayers }
  275.             if itsLevelsDoc = nil then begin
  276.                 itsPrefsFile.SetPref(kPrefBestPlayers, nil);
  277.                 itsPrefsFile.SetPref(kPrefNumBest, nil);
  278.             end { if }
  279.             else begin
  280.                 itsLevelsDoc.ClearBestPlayers;
  281.             end; { else }
  282.         end; { DoClearBestPlayers }
  283.  
  284.     begin { DoCommand }
  285.         case theCommand of
  286.  
  287.             cmdAbout, cmdHelp:  begin
  288.                 DoAboutAndHelp;
  289.             end; { cmdAbout, cmdHelp }
  290.  
  291.             cmdReadDefLevels:  begin
  292.                 ReadDefaultLevels;
  293.             end; { cmdReadDefLevels }
  294.  
  295.             cmdClearBestPlayers:  begin
  296.                 { Upon entry, the game director will have already cleared it from its visible levels. }
  297.                 { Now update the document/ pref file. }
  298.                 DoClearBestPlayers;
  299.             end; { cmdClearBestPlayers }
  300.  
  301.             otherwise begin
  302.                 inherited DoCommand(theCommand);
  303.             end; { otherwise }
  304.         end; { case }
  305.     end; { DoCommand }
  306.  
  307.  
  308. {****************************************************}
  309. {}
  310. {        DoAppleEvent                                                                                                                                                                                                    }
  311. {}
  312. {        Handle the core apple events. The way in which we do so is                                                             }
  313. {        different to that for a conventional application.                                                                                                }
  314. {}
  315. {****************************************************}
  316.  
  317.     procedure CShApp.DoAppleEvent (anAppleEvent: CAppleEvent);
  318.  
  319.         var
  320.             eventClass: DescType;
  321.             eventID: DescType;
  322.             err: Integer;
  323.  
  324.     begin { DoAppleEvent }
  325.         eventClass := anAppleEvent.GetEventClass;
  326.         eventID := DescType(anAppleEvent.GetEventID);
  327.  
  328.         if eventClass = kCoreEventClass then begin
  329.             if eventID = kAEOpenApplication then begin
  330.                 DoOpenAppEvent(anAppleEvent);
  331.             end { if }
  332.             else if eventID = kAEOpenDocuments then begin
  333.                 DoOpenOrPrintDocEvent(anAppleEvent);
  334.             end { else if }
  335.             else if eventID = kAEQuitApplication then begin
  336.                 if anAppleEvent.GotRequiredParams then begin
  337.                     err := anAppleEvent.RequestInteraction(MAXLONGINT);
  338.                 end; { if }
  339.                 if err = noErr then begin
  340.                     if Quit then begin
  341.                     end; { if }
  342.                             (* if we're still running then Quit didn't succeed    *)
  343.                             (* but we don't know what error to report!            *)
  344.  
  345.                     anAppleEvent.SetErrorResult(err);
  346.                 end; { if }
  347.             end { else if }
  348.             else begin
  349.                     { Don't know how to handle any other kind of core event. }
  350.                     { No printing, or publish and subscribe! :) }
  351.                 anAppleEvent.SetErrorResult(errAEEventNotHandled);
  352.             end; { else }
  353.         end; { if }
  354.  
  355.     end; { DoAppleEvent }
  356.  
  357.  
  358. {****************************************************}
  359. {}
  360. {        DoOpenAppEvent                                                                                                                                                                                            }
  361. {}
  362. {        Handle the kAEOpenApplication AppleEvent, by loading the default                                            }
  363. {        levels.                                                                                                                                                                                                                        }
  364. {}
  365. {****************************************************}
  366.  
  367.     procedure CShApp.DoOpenAppEvent (anAppleEvent: CAppleEvent);
  368.  
  369.         var
  370.             ignore: Integer;
  371.  
  372.     begin { DoOpenWithNoDocs }
  373.         { We ignore any attempts to read in levels if we are playing a game. }
  374.         { This might happen, for instance, if we switch to the Finder and }
  375.         { double click on application icon. }
  376.         if GameDirector.IsPlaying then begin
  377.             PositionDialog('ALRT', ALRTGamePlayingSoCannotOpen);
  378.             InitCursor;
  379.             ignore := NoteAlert(ALRTGamePlayingSoCannotOpen, nil);
  380.         end { if }
  381.         else begin
  382.             { Upon opening, with no other documents, load the default levels. }
  383.             if anAppleEvent.GotRequiredParams then begin
  384.                 SetCursor(gWatchCursor^^);
  385.  
  386.                 ReadDefaultLevels;
  387.                 anAppleEvent.SetErrorResult(noErr);
  388.             end; { if }
  389.         end; { else }
  390.     end; { DoOpenAppEvent }
  391.  
  392.  
  393. {****************************************************}
  394. {}
  395. {        DoOpenOrPrintDocEvent                                                                                                                                                                        }
  396. {}
  397. {        Handle the kAEOpenDocuments AppleEvent, by the loading the first                                        }
  398. {        of any levels files. We only load the first, because only one file                                                }
  399. {        is open at any time.                                                                                                                                                                                    }
  400. {}
  401. {****************************************************}
  402.  
  403.     procedure CShApp.DoOpenOrPrintDocEvent (theEvent: CAppleEvent);
  404.  
  405.         var
  406.             ignore: Integer;
  407.  
  408.             docList: CArray;
  409.             numDocs: Longint;
  410.             currDoc: FSSpec;
  411.             eventID: DescType;
  412.             fi: FailInfo;
  413.             wdRefNum: Integer;
  414.             reply: SFReply;
  415.             fileInfo: FInfo;
  416.  
  417.             theCounter: LongInt;
  418.             foundLevelsFile: Boolean;
  419.  
  420.         procedure AEExceptionHandler (error: Integer;
  421.                                         message: Longint);
  422.  
  423.         begin { AEExceptionHandler }
  424.             ForgetObject(docList);
  425.         end; { AEExceptionHandler }
  426.  
  427.     begin { DoOpenOrPrintDocEvent }
  428.         { We ignore any attempts to read in levels if we are playing a game. }
  429.         { This might happen, for instance, if we switch to the Finder and }
  430.         { double click on some levels files. }
  431.         if GameDirector.IsPlaying then begin
  432.             PositionDialog('ALRT', ALRTGamePlayingSoCannotOpen);
  433.             InitCursor;
  434.             ignore := NoteAlert(ALRTGamePlayingSoCannotOpen, nil);
  435.         end { if }
  436.         else begin
  437.             docList := nil;
  438.             CatchFailures(fi, AEExceptionHandler);
  439.  
  440.             SetCursor(gWatchCursor^^);
  441.  
  442.             docList := theEvent.ExtractFromDescList(keyDirectObject, typeFSS, SIZEOF(FSSpec));
  443.             if theEvent.GotRequiredParams then begin
  444.                 eventID := theEvent.GetEventID;
  445.                 numDocs := docList.GetNumItems;
  446.  
  447.                 theCounter := 1;
  448.                 foundLevelsFile := FALSE;
  449.                 while (theCounter <= numDocs) and not foundLevelsFile do begin
  450.                     docList.GetItem(@currDoc, theCounter);
  451.                     FailOSErr(OpenWD(currDoc.vRefNum, currDoc.parID, Longint(gSignature), wdRefNum));
  452.                     FailOSErr(FSpGetFInfo(currDoc, fileInfo));
  453.  
  454.                     if fileInfo.fdType = kSignatureLevelsFiles then begin
  455.                         reply.good := TRUE;
  456.                         reply.vRefNum := wdRefNum;
  457.                         reply.fType := fileInfo.fdType;
  458.                         reply.version := 0;
  459.                         reply.copy := FALSE;
  460.                         reply.fName := currDoc.name;
  461.  
  462.                         OpenDocument(reply);
  463.  
  464.                         foundLevelsFile := TRUE;
  465.                     end { if }
  466.                     else begin
  467.                         theCounter := theCounter + 1;
  468.                     end; { else }
  469.                 end; { while }
  470.  
  471.                 if not foundLevelsFile then begin
  472.                 { This could happen if you launch the application by opening the preferences file. }
  473.                     ReadDefaultLevels;
  474.                 end; { if }
  475.  
  476.         (* event was handled successfully*)
  477.  
  478.                 theEvent.SetErrorResult(noErr);
  479.                 ForgetObject(docList);
  480.                 Success;
  481.             end; { if }
  482.         end; { else }
  483.     end; { DoOpenOrPrintDocEvent }
  484.  
  485.  
  486. {****************************************************}
  487. {}
  488. {        UpdateMenus                                                                                                                                                                                                        }
  489. {}
  490. {     The application is responsible for file commands, including the use of default        }
  491. {        levels. It also handles the help command.                                                                                                                     }
  492. {}
  493. {****************************************************}
  494.  
  495.     procedure CShApp.UpdateMenus;
  496.  
  497.     begin { UpdateMenus }
  498.         inherited UpdateMenus;
  499.  
  500.         { We could make the game director responsible for deactivating the Open… }
  501.         { or Use Default Levels commands, based on whether it is playing, however }
  502.         { activation of the Open… command is the responsibility of the application, }
  503.         { and is performed in the inherited method. }
  504.  
  505.         if GameDirector.IsPlaying then begin
  506.             gBartender.DisableCmd(cmdOpen);
  507.         end { if }
  508.         else begin
  509.             if itsLevelsDoc <> nil then begin
  510.                 gBartender.EnableCmd(cmdReadDefLevels);
  511.             end; { else }
  512.         end; { else }
  513.  
  514.         { The help command is always available. }
  515.         gBartender.EnableCmd(cmdHelp);
  516.     end; { UpdateMenus }
  517.  
  518.  
  519. {****************************************************}
  520. {}
  521. {        Preload                                                                                                                                                                                                                        }
  522. {}
  523. {     Loads the first of any preloaded levels files, then call StartUpAction.                             }
  524. {     We only load the first, because only one file is open at any time.                                             }
  525. {}
  526. {****************************************************}
  527.  
  528.     procedure CShApp.Preload;
  529.  
  530.         var
  531.             openOrPrint: Integer; { Type of action requested. }
  532.             numPreloads: Integer;    { No. of files to process. }
  533.             macAppFile: AppFile;     { Info about file. }
  534.             macSFReply: SFReply;    { Standard File info record. }
  535.  
  536.             theCounter: Integer;
  537.             foundLevelsFile: Boolean;
  538.  
  539.     begin { Preload }
  540.         CountAppFiles(openOrPrint, numPreloads);
  541.  
  542.         if numPreloads > 0 then begin
  543.  
  544.             SetCursor(gWatchCursor^^);
  545.  
  546.             { Scan the preload candidates for a levels file. }
  547.             { Remember that we must ignore the preferences file. }
  548.             theCounter := 1;
  549.             foundLevelsFile := FALSE;
  550.             while (theCounter <= numPreloads) and not foundLevelsFile do begin
  551.                 { Get info about the file. }
  552.                 GetAppFiles(theCounter, macAppFile);
  553.  
  554.                 if macAppFile.fType = kSignatureLevelsFiles then begin
  555.  
  556.                     { Copy information into our record. }
  557.                     macSFReply.fType := macAppFile.fType;
  558.                     macSFReply.vRefNum := macAppFile.vRefNum;
  559.                     macSFReply.version := macAppFile.versNum;
  560.                     macSFReply.fName := macAppFile.fName;
  561.  
  562.                     OpenDocument(macSFReply);
  563.  
  564.                     foundLevelsFile := TRUE;
  565.                 end { if }
  566.                 else begin
  567.                     theCounter := theCounter + 1;
  568.                 end; { else }
  569.             end; { while }
  570.  
  571.             if not foundLevelsFile then begin
  572.                 { Set the count to zero, so that we know to open the default levels. }
  573.                 numPreloads := 0;
  574.             end; { if }
  575.  
  576.             { Now tell the Finder that we're done. }
  577.  
  578.             for theCounter := 1 to numPreloads do begin
  579.                 ClrAppFiles(theCounter);
  580.             end; { for }
  581.  
  582.         end; { if }
  583.  
  584.         StartUpAction(numPreloads);
  585.     end; { Preload }
  586.  
  587.  
  588. {****************************************************}
  589. {}
  590. {        StartUpAction                                                                                                                                                                                                    }
  591. {}
  592. {     If there were no preloaded files, load the default levels.                                                                     }
  593. {}
  594. {****************************************************}
  595.  
  596.     procedure CShApp.StartUpAction (numPreloads: Integer);
  597.  
  598.         var
  599.             waitForOAPP: Boolean;
  600.  
  601.     begin { StartupAction }
  602.         FlushEvents(everyEvent, 0);
  603.  
  604.         (* Only read the default levels if there are no AppleEvents.*)
  605.         (* If there are, we anticipate getting the open app event*)
  606.         (* Under the THINK Pascal environment, we don't get an    *)
  607.         (* initial oapp. We use the compiler variable TCL_DEBUG *)
  608.         (* to determine if we're running the debug version.        *)
  609.         (* If we are, we don't wait for the oapp event.            *)
  610.  
  611.         waitForOAPP := gSystem.hasAppleEvents;
  612.  
  613. {$IFC TCL_DEBUG}
  614.         waitForOAPP := FALSE;
  615.  {$ENDC}
  616.  
  617.         if (not waitForOAPP) and (numPreloads = 0) then begin
  618.             SetCursor(gWatchCursor^^);
  619.  
  620.             ReadDefaultLevels;
  621.         end; { if }
  622.  
  623.         { The game director's screen is updated, either by the ReadDefaultLevels call, }
  624.         { or by the document sending a screen update message. }
  625.     end; { StartupAction }
  626.  
  627.  
  628. {****************************************************}
  629. {}
  630. {        ExitApp                                                                                                                                                                                                                        }
  631. {}
  632. {     We set our pointers to nil before exiting the application. The objects                                 }
  633. {        to which they were pointing will be disposed of in inherited methods    .                                }
  634. {     Also dispose of the sounds and close the preferences file.                                                                 }
  635. {}
  636. {****************************************************}
  637.  
  638.     procedure CShApp.ExitApp;
  639.  
  640.         { Shut up the sounds which are playing, then dispose of them. }
  641.         procedure DisposeSATSounds;
  642.  
  643.             var
  644.                 theCounter: Integer;
  645.  
  646.         begin { DisposeSATSounds }
  647.             SATSoundShutup;
  648.  
  649.             if gFlipSoundHandles <> nil then begin
  650.                 for theCounter := 1 to gNumFlipSounds do begin
  651. {$PUSH}
  652. {$R-}
  653.                     SATDisposeSound(gFlipSoundHandles^^[theCounter]);
  654.                     gFlipSoundHandles^^[theCounter] := nil;
  655. {$POP}
  656.                 end; { for }
  657.                 ForgetHandle(gFlipSoundHandles);
  658.                 gFlipSoundHandles := nil;
  659.             end; { if }
  660.  
  661.             { The welcoming sound was disposed of after it was first played. }
  662.  
  663.             SATDisposeSound(gSoundGameStarting);
  664.             gSoundGameStarting := nil;
  665.             SATDisposeSound(gSoundGameComplete);
  666.             gSoundGameComplete := nil;
  667.             SATDisposeSound(gSoundGameAborted);
  668.             gSoundGameAborted := nil;
  669.             SATDisposeSound(gSoundNewBestPlayer);
  670.             gSoundNewBestPlayer := nil;
  671.         end; { DisposeSATSounds }
  672.  
  673.     begin { ExitApp }
  674.         { Stop SAT sounds. }
  675.         DisposeSATSounds;
  676.  
  677.         { Close the preferences file. }
  678.  
  679.         itsPrefsFile.Free;
  680.         itsPrefsFile := nil;
  681.  
  682.         { Because the application levels director, the game director and level documents }
  683.         { are installed in the supervision heirarchy, the default methods handle disposal.  }
  684.         { All we need to do is reset our own pointers. }
  685.  
  686.         itsAppLevelsDirector := nil;
  687.         itsGameDirector := nil;
  688.         itsLevelsDoc := nil;
  689.  
  690.         inherited ExitApp;
  691.     end; { ExitApp }
  692.  
  693.  
  694. {****************************************************}
  695. {}
  696. {        OpenDocument                                                                                                                                                                                                    }
  697. {}
  698. {     Opens the given levels document. If a previous document is open,                                         }
  699. {        it needs to be closed first.                                                                                                                                                              }
  700. {}
  701. {****************************************************}
  702.  
  703.     procedure CShApp.OpenDocument (macSFReply: SFReply);
  704.  
  705.         var
  706.             theDocument: CShLevelsDoc;
  707.             fi: FailInfo;
  708.  
  709.         { If something goes wrong, dispose of the document }
  710.         { and let the failure propagate. }
  711.         procedure HandleFailure (error: Integer;
  712.                                         message: Longint);
  713.  
  714.         begin { HandleFailure }
  715.             ForgetObject(theDocument);
  716.         end; { HandleFailure }
  717.  
  718.     begin { OpenDocument }
  719.         theDocument := nil;
  720.  
  721.         if itsLevelsDoc <> nil then begin
  722.  
  723.         { If we have a levels document open already, then close it. }
  724.  
  725.             itsLevelsDoc.DoCommand(cmdClose);
  726.             itsLevelsDoc := nil;
  727.         end;
  728.  
  729.         CatchFailures(fi, HandleFailure);
  730.  
  731.         new(theDocument);
  732.         theDocument.IShLevelsDoc(SELF);
  733.         theDocument.OpenFile(macSFReply);
  734.  
  735.         itsLevelsDoc := theDocument;
  736.  
  737.         Success;
  738.  
  739.         { The game director's screen has to be updated. Note that we only }
  740.         { allow files to be open at the title screen, not while a game is being played. }
  741.  
  742.         itsGameDirector.DisplayTitleScreen(FALSE);
  743.     end; { OpenDocument }
  744.  
  745.  
  746. {****************************************************}
  747. {}
  748. {        GameDirector                                                                                                                                                                                                    }
  749. {}
  750. {     Returns the director of the main game window. This is to allow documents to        }
  751. {        send the list of levels to the game director.                                                                                                          }
  752. {}
  753. {****************************************************}
  754.  
  755.     function CShApp.GameDirector: CShGameDirector;
  756.  
  757.     begin { GameDirector }
  758.         GameDirector := itsGameDirector;
  759.     end; { GameDirector }
  760.  
  761.  
  762. {****************************************************}
  763. {}
  764. {        PreferencesFile                                                                                                                                                                                                }
  765. {}
  766. {     Returns the preferences file object. This allows access by both the                                    }
  767. {        application and the reader of the default application levels.                                                             }
  768. {}
  769. {****************************************************}
  770.  
  771.     function CShApp.PreferencesFile: CHandlePrefs;
  772.  
  773.     begin { GameDirector }
  774.         PreferencesFile := itsPrefsFile;
  775.     end; { GameDirector }
  776.  
  777.  
  778. {****************************************************}
  779. {}
  780. {        ReadDefaultLevels                                                                                                                                                                                        }
  781. {}
  782. {     The default levels have been read from the application resource, and sent                 }
  783. {        to the game director. This is called at startup if necessary, or as a menu                    }
  784. {        command.                                                                                                                                                                                                                }
  785. {}
  786. {****************************************************}
  787.  
  788.     procedure CShApp.ReadDefaultLevels;
  789.  
  790.     begin { ReadDefaultLevels }
  791.         if itsLevelsDoc <> nil then begin
  792.  
  793.             { If we have a levels document open already, then close it. }
  794.             { Note that here we have to nil the pointer, ready for opening }
  795.             { another document. }
  796.  
  797.             itsLevelsDoc.DoCommand(cmdClose);
  798.             itsLevelsDoc := nil;
  799.         end; { if }
  800.  
  801.         if itsAppLevelsDirector.GetWindow = nil then begin
  802.             itsAppLevelsDirector.BuildWindow;
  803.         end { if }
  804.         else begin
  805.             itsAppLevelsDirector.GetWindow.Show;
  806.         end; { else }
  807.  
  808.         itsGameDirector.SetLevels(itsAppLevelsDirector.AppLevels);
  809.  
  810.         { Bring the game director's window to the front. Then hide our reader. }
  811.         { The order is important! }
  812.  
  813.         itsGameDirector.GetWindow.Select;
  814.         itsAppLevelsDirector.GetWindow.Hide;
  815.  
  816.         { The game director's screen has to be updated. }
  817.  
  818.         itsGameDirector.DisplayTitleScreen(FALSE);
  819.     end; { ReadDefaultLevels }
  820.  
  821.  
  822. {****************************************************}
  823. {}
  824. {        StoreBestPlayer                                                                                                                                                                                            }
  825. {}
  826. {        Tells the application levels director, or the active document, to store the                 }
  827. {        best player.                                                                                                                                                                                                         }
  828. {}
  829. {****************************************************}
  830.  
  831.     procedure CShApp.StoreBestPlayer (aLevelNum: LevelsRange;
  832.                                     aPlayer: Str15;
  833.                                     aMoves: Integer;
  834.                                     aTime: LongInt);
  835.  
  836.     begin { StoreBestPlayer }
  837.         if itsLevelsDoc = nil then begin
  838.             itsAppLevelsDirector.StoreBestPlayer(aLevelNum, aPlayer, aMoves, aTime);
  839.         end { if }
  840.         else begin
  841.             itsLevelsDoc.StoreBestPlayer(aLevelNum, aPlayer, aMoves, aTime);
  842.         end; { else }
  843.     end; { StoreBestPlayer }
  844.  
  845.  
  846. end. { CShApp }