home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Files / Standard File / SelectMultipleFiles / StdFile.cp < prev    next >
Encoding:
Text File  |  2000-09-28  |  10.9 KB  |  363 lines  |  [TEXT/CWIE]

  1. /************************************************************************************    
  2.             Apple Macintosh Developer Technical Support
  3.     
  4.             Standard File Sample Application
  5.     
  6.             StdFile
  7.     
  8.             StdFile.p            -            Pascal Source
  9.     
  10.             Copyright © 1989 Apple Computer, Inc.
  11.             All rights reserved.
  12.     
  13.         Versions:        
  14.                     1.00                    04/89
  15.                     2.00                    05/90
  16.                     2.01                    06/92
  17.                     
  18.                     3/17/98    AB    Removed all System 6 compatibility code
  19.                                 Removed all A/UX compatibility code
  20.     
  21.         Components:
  22.                     StdFile.p                April 1, 1989
  23.                     StdFile.h                April 1, 1988
  24.                     StdFile.r                April 1, 1988
  25.                     PStdFile.make            April 1, 1988
  26.     
  27.     ----------
  28.     OBJECTIVES
  29.     ----------
  30.     This program attempts to demonstrate the following techniques:
  31.     
  32.     - Normal use of SFGetFile and SFPutFile
  33.     - Normal use of SFPGetFile and SFPPutFile.    This includes use of Custom
  34.         Dialogs with handling of extra items through the implementation of a
  35.         Standard File Dialog Hook.
  36.         - First time initialization
  37.         - Extra Simple buttons (Disory/ThisDir/Options)
  38.         - Radio buttons (file format, types of files to show)
  39.         - Aliasing click on some buttons to clicks on other buttons
  40.         - Regenerating the list of files displayed
  41.     - Creating a full pathname from the reply record (using Working Directories
  42.         or DirID)
  43.     - Selecting a directory (ala MPW's "GetFileName -d")
  44.     - Simple file filter (checks file type)
  45.     - Complex file filter (looking inside the file)
  46.     - Adding and deleting and extra List Manager lists.        This is shown for both
  47.         SFGetFile and SFPutFile.
  48.     - Select multiple files by adding a second list to the Dialog Box.
  49.     - Setting the starting Directory/Volume
  50.     - Describe pending update event clogging
  51.     - Ask the user to select a file, and then remember where it is the next
  52.         time the application is launched.
  53.     
  54.     --------------------------
  55.     Standard File Generalities
  56.     --------------------------
  57.     
  58.     The prompt string of SFGetFile is ignored in all calls.        As noted on page
  59.     I-523 of Inside Mac, it is there for historical reasons only.  The
  60.     Standard File package is built around a modal dialog window.  Standard
  61.     File repeatedly calls ModalDialog waiting for user events.    It is
  62.     possible for an application to hook into the dialog event loop by using
  63.     the following methods.
  64.     
  65.     File Filter
  66.     -----------
  67.     The file filter is called to give the application opportunity to filter
  68.     out files that is wishes not to be shown in the dialog.        This file filter
  69.     is called before displaying the dialog, which is also before the Dialog
  70.     Hook or Dialog Filter are called.  If this function returns TRUE, this
  71.     means the file should not be shown in the list.        In other words the file
  72.     is to be filtered from the user.
  73.     
  74.     Dialog Hook
  75.     -----------
  76.     The dialog hook is called after Standard File calls ModalDialog.  The
  77.     hook is a function that requires that an item number be passed back from
  78.     it.        Normally, this is the same item number that was passed to us, but
  79.     not necessarily.  For instance, we could return values that cause the
  80.     file names to be re-drawn or have the whole event ignored.    Before the
  81.     dialog is drawn, our dialog hook gets called with a -1.        This gives us
  82.     the opportunity to change things like Button titles, etc.  It's in
  83.     important to note that Standard File seems to ignore the item returned by
  84.     the dialog hook when it is called the first time.  The dialog hook will
  85.     also be passed a fake item of 100, which is used to mean a nullEvent.
  86.     This can be used as an idle event for the dialog hook.
  87.     
  88.     Dialog Filter
  89.     -------------
  90.     This is used in the SFPGetFile and SFPPutFile routines.        It is for the
  91.     advanced versions of calling Standard File for programmers that desire a
  92.     custom dialog window.  The dialog filter is the same filter procedure
  93.     used by the Dialog Manager.        In the call to ModalDialog, you can supply a
  94.     filter.        The dialog filter used by Standard File is passed to
  95.     ModalDialog.  This filter is called by the Dialog Manager after it calls
  96.     GetNextEvent.  This gives the filter the first opportunity to handle the
  97.     event.    If the dialog filter returns TRUE, this tells the Dialog Manager
  98.     that the filter has handled the event.    You will use the dialog filter to
  99.     handle items you've added to your custom dialog.
  100.     
  101. ************************************************************************************/
  102. /*
  103. #include <stddef.h>
  104. #include <types.h>
  105. #include <limits.h>
  106. #include <Builtins.h>
  107. #include <PStrings.h>
  108. #include <PSets.h>
  109.  
  110. #include <Types.h>
  111. #include <QuickDraw.h>
  112. #include <ToolUtils.h>
  113. #include <Controls.h>
  114. #include <Devices.h>
  115. #include <Traps.h>
  116. #include <Resources.h>
  117. #include <Packages.h>
  118. #include <Lists.h>
  119. #include <DiskInit.h>
  120. #include <Script.h>
  121. #include <LowMem.h>
  122. #include <CursorCtl.h>
  123. #include <Errors.h>
  124. #include <FixMath.h>
  125. #include <GestaltEqu.h>
  126. #include <StandardFile.h>
  127. */
  128.  
  129.  
  130. //    ****************    Universal Headers            ****************
  131.  
  132. #include <Dialogs.h>
  133. #include <Events.h>
  134. #include <Files.h>
  135. #include <Fonts.h>
  136. #include <Memory.h>
  137. #include <Menus.h>
  138. #include <SegLoad.h>
  139. #include <Windows.h>
  140.                     
  141. #include "StdFile.h"
  142.  
  143.  
  144. //    ****************            Globals                ****************
  145.  
  146. //    gInBackground is maintained by the osEvent handling routines. Any part of
  147. //    the program can check it to find out if it is currently in the background.
  148.  
  149. Boolean        gInBackground;            //    maintained by Initialize and EventLoop
  150.  
  151. FSSpec        gAppFSSpec;                //    The FSSpec for the application
  152. //Str255        gAppName;                //application's name
  153. //long        gAppParID;                //dirID of application's folder
  154. //short        gAppVRefNum;            //volume containing application
  155.  
  156.  
  157.  
  158.  
  159. //    ****************************************************************
  160.  
  161. void    EventLoop( void );
  162. void    Initialize( void );
  163. void    EmergencyExit( short message );
  164. Boolean    FailLowMemory(long memRequest);
  165.  
  166.  
  167. //    ****************************************************************
  168.  
  169. void main( void )
  170. {  
  171.   //If you have stack requirements that differ from the default, then you
  172.   //could use SetApplLimit to increase StackSpace at this point, before
  173.   //calling MaxApplZone.
  174.   
  175.     MaxApplZone();                //expand the heap so code segments load at the top
  176.     Initialize();                //initialize the program
  177.     UnloadSeg(Initialize);        //note: Initialize must not be in Main!
  178.     EventLoop();                //call the main event loop
  179. }//end main
  180.                     
  181. //    ****************************************************************
  182.  
  183. void Initialize( void )
  184. {
  185.     /*
  186.     The pentultimate thing is to save the default directory and volume 
  187.     that the application is launched from in two globals and create a 
  188.     temporary file.    This file is only used for demonstration purposes.
  189.     Finally, we check if the file we last remembered can be found.
  190.     */
  191.     
  192.     Str63            fName;
  193.     EventRecord        event;
  194.     Handle            menuBar;
  195.     Handle            apParam;
  196.     OSErr            ignoreError;
  197.     short            count;
  198.     short            auxVersion;
  199.     short            appResRef;
  200.     OSErr            err;
  201.     Boolean            ignoreResult;
  202.     Str63            Temp_Str63_1;
  203.     FSSpec            fss;
  204.     
  205.     gInBackground = false;                            //    we’ll be in the foreground soon
  206.     
  207.     for ( count = 0; count < kNumberOfMasters; ++count ) //    allocate master pointer blocks
  208.     {
  209.         MoreMasters();
  210.     }
  211.     InitGraf( &qd.thePort );
  212.     InitFonts();
  213.     InitWindows();
  214.     InitMenus();
  215.     TEInit();
  216.     InitDialogs( nil );
  217.     InitCursor();
  218.     
  219.     menuBar = GetNewMBar( rMenuBar );                    //    read menus into menu bar
  220.     if (menuBar == NULL)
  221.     {
  222.         EmergencyExit( sNoMenus );
  223.     }
  224.     
  225.     SetMenuBar( menuBar );                                //    install menus
  226.     DisposeHandle( menuBar );
  227.     AppendResMenu( GetMenuHandle(mApple), 'DRVR' );        //    add DA names to Apple menu
  228.     DrawMenuBar();
  229.     
  230.     if ( FailLowMemory( kMinSpace ) )
  231.     {
  232.         EmergencyExit( sLowMemory );
  233.     }
  234.     
  235.     anErr = GetCurrentProcessFSSpec( &gAppFSSpec );
  236.     if ( anErr == noErr )
  237.     {
  238.         gAppVRefNum = fss.vRefNum;
  239.         gAppParID = fss.parID;
  240.     }
  241.     err = HCreate( gAppVRefNum, gAppParID, GetTempFileName((Str63 *)Temp_Str63_1), 
  242.                 rAppSignature, 'TEMP');
  243.     
  244.     RecallFile();                                        //what was that file?
  245. }//end Initialize
  246.                     
  247. //    ****************************************************************
  248.  
  249. void EventLoop( void )
  250. {
  251.     //Chances are, you've seen an event loop before so I'm not going to
  252.     //comment about it.
  253.     
  254.     const char    osEvt = app4Evt;                        //defined in post MPW 3.0 Events.p
  255.     const char    suspendResumeMessage = 1;                //defined in post MPW 3.0 Events.p
  256.     const char    kGetHighByte = 24;                        //24 bits (three bytes) to shift right
  257.     const char    kResumeMask = 1;                        //resume event is low bit of message
  258.     
  259.     EventRecord evt;
  260.     WindowPtr whichWindow;                            //used for FindWindow
  261.     short deskPart;                                    //result from FindWindow
  262.     OSErr err;
  263.     Boolean haveEvent;                                //TRUE if interesting event
  264.  
  265.     do {
  266.     if (gHasWaitNextEvent) 
  267.         haveEvent = WaitNextEvent(everyEvent, &evt, LONG_MAX, NULL);
  268.     else {
  269.         SystemTask();
  270.         haveEvent = GetNextEvent(everyEvent, &evt);
  271.     }
  272.     
  273.     deskPart = FindWindow(evt.where, &whichWindow);
  274.     if (deskPart != inSysWindow) 
  275.         SetCursor(&qd.arrow);
  276.     
  277.     if (haveEvent) {
  278.         switch (evt.what) { 
  279.         
  280.         case mouseDown:
  281.             switch (deskPart) { 
  282.             case inSysWindow:
  283.                 SystemClick(&evt, whichWindow);
  284.                 break;
  285.             case inMenuBar:
  286.                 DoCommand(MenuSelect(evt.where));
  287.                 break;
  288.             }
  289.             break;
  290.         
  291.         case keyDown:
  292.         case autoKey:
  293.             if (BAnd(evt.modifiers, cmdKey) != 0) 
  294.             DoCommand(MenuKey((char)BAnd(evt.message, charCodeMask)));
  295.             break;
  296.         
  297.         case diskEvt:
  298.             //Call DIBadMount in response to a diskEvt
  299.             if (HiWord(evt.message) != noErr) 
  300.             err = DIBadMount((Point)kSFTopLeft, evt.message);
  301.             break;
  302.         
  303.         case osEvt:
  304.             switch (BSR(evt.message, kGetHighByte)) { 
  305.             case suspendResumeMessage:
  306.                 if (BAnd(evt.message, kResumeMask) != 0) {
  307.                 gInBackground = false;
  308.                 } else 
  309.                 gInBackground = true;                //suspend event
  310.                 break;                                //suspendResumeMessage
  311.             }
  312.             break;
  313.         }
  314.         
  315.         //CASE
  316.     }
  317.     } while (true);                                    //loop forever, quit through Terminate
  318. }
  319.                     
  320. //    ****************************************************************
  321.  
  322. void EmergencyExit( short message )
  323. {
  324.     //Display an alert that tells the user an error occurred, then exit the
  325.     //program.    This routine is used as an ultimate bail-out for serious errors
  326.     //that prohibit the continuation of the application.    Errors that do not
  327.     //require the termination of the application are handled with AlertUser.
  328.     //Error checking and reporting has a place even in the simplest application.
  329.     
  330.     //BUG NOTE: GetIndString will return a bogus String if the index is not
  331.     //positive.
  332.     
  333.     Str255 msg1;
  334.     short theItem;
  335.  
  336.     SetCursor(&qd.arrow);
  337.     if (message > 0) 
  338.     GetIndString(msg1, rErrStrings, message);
  339.     else 
  340.     PStr_Set(msg1, "\p");                            //in case there is no message
  341.     ParamText(msg1, "\p", "\p", "\p");
  342.     theItem = CenteredAlert(rExitAlert);
  343.     ExitToShell();                                    //we're out of here
  344. }
  345.                     
  346. //    ****************************************************************
  347.  
  348. Boolean FailLowMemory(long memRequest)
  349. {
  350.     //Call PurgeSpace and see if the requested amount of memory exists in the
  351.     //heap including a minimal amount of heap space.    Also, if my grow zone’s
  352.     //reserve has been release, that’s considered a failure.    I don’t perform
  353.     //any purging here.     The Memory Manager will do this if it needs the space.
  354.     //This routine can be called with a memRequest = 0.     This checks if the heap
  355.     //space is getting critical.
  356.     
  357.     long total;
  358.     long contig;
  359.  
  360.     PurgeSpace(&total, &contig);
  361.     return total < memRequest + kMinSpace;
  362. }
  363.