home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 August: Tool Chest / Apple_Developer_Group_August_1996_Tool_Chest.iso / Sample Code / Snippets / Files / SettingUpStdFile / SettingUpStdFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-04  |  7.0 KB  |  255 lines  |  [TEXT/MPS ]

  1. /*
  2.  * Setting Up StandardFile
  3.  *  
  4.  *  This snippet demonstrates how to make Standard File
  5.  *  select an initial file under both System 6 and System 7.
  6.  *  (In this example, the System file will be selected.)
  7.  *
  8.  *  "An exhilirating snippet"
  9.  *             - Nitin Ganatra
  10.  *
  11.  *  Greg Robbins   August 1993
  12.  *
  13.  * Changes:
  14.  * =======
  15.  * • sfScript is reset in the System 7 DialogHook (below) to work  
  16.  *   around a gotcha in Standard File that's incorrectly documented in  
  17.  *   a New Inside Macintosh: Files sample.  See the DialogHook() function 
  18.  *   for details.
  19.  *
  20.  *
  21.  * • Compatible with the Universal Interfaces.
  22.  *
  23.  *  Nitin Ganatra, 2/94
  24.  *
  25.  */
  26.  
  27. #include <QuickDraw.h>
  28. #include <StandardFile.h>
  29. #include <Fonts.h>
  30. #include <Menus.h>
  31. #include <Dialogs.h>
  32. #include <Events.h>
  33. #include <GestaltEqu.h>
  34. #include <TextEdit.h>
  35. #include <Errors.h>
  36. #include <OSEvents.h>
  37. #include <Folders.h>
  38. #include <Memory.h>
  39. #include <Script.h>
  40. #include <LowMem.h>
  41.  
  42. #ifdef __powerc
  43. QDGlobals qd;
  44. #endif
  45.  
  46. // prototypes
  47. pascal short DialogHook(short, DialogPtr , void *);
  48. pascal short OldDlgHook(short, DialogPtr);
  49. OSErr GetSystemFileSpec(FSSpecPtr);
  50.  
  51. // global struct for System 7 Std File dialog hook
  52. typedef struct {
  53.     StandardFileReply *theSFR;
  54.     FSSpec *itemSpec;
  55. } HookRecord, *HookRecordPtr;
  56.  
  57. // globals for System 6 Std File stuff
  58. StringPtr    gSelectFileName;
  59. short        gSelectFileCounter;
  60.  
  61.  
  62.  
  63.  
  64. void main(void)
  65. {
  66.     Point dialogPt;
  67.     SFTypeList mySFTypeList;
  68.     StandardFileReply mySFR;
  69.     SFReply oldSFR;
  70.     long procID;
  71.     FSSpec systemSpec;
  72.     HookRecord hookRec;
  73.     Boolean hasNewStdFileCallsFlag;
  74.     long gestResponse;
  75.     
  76.     OSErr retCode;
  77.     DlgHookYDUPP    myDlgHookUPP;
  78.  
  79.  
  80.     // initialize the toolbox
  81.     InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus();
  82.     TEInit(); InitDialogs(nil); InitCursor(); FlushEvents(everyEvent,0);
  83.  
  84.     // determine if the System 7 std file calls are available
  85.     retCode = Gestalt(gestaltStandardFileAttr, &gestResponse);
  86.     if (retCode == noErr && ((gestResponse >> gestaltStandardFile58) & 1) != 0)
  87.         hasNewStdFileCallsFlag = true;
  88.     else
  89.         hasNewStdFileCallsFlag = false;
  90.  
  91.     SetPt(&dialogPt, -1, -1);
  92.         
  93.     // get the FSSpec of the system file
  94.     retCode = GetSystemFileSpec(&systemSpec);
  95.     if (retCode != noErr) DebugStr((StringPtr)"\p GetSystemFileSpec failed");
  96.     
  97.     if (hasNewStdFileCallsFlag) {
  98.     
  99.         // System 7 method
  100.         
  101.         // point my hook data record at the reply record and at
  102.         // the file spec for the system file
  103.         
  104.         hookRec.itemSpec = &systemSpec;
  105.         hookRec.theSFR = &mySFR;
  106.  
  107.  
  108.         // Set up the universal proc pointer to your hook routine with this 
  109.         // macro defined in StandardFile.h.  **NOTE** This is different
  110.         // from the macro used for System 6 dialog hooks, and you should get
  111.         // a compiler error if you try to use the wrong UPP with the wrong call.
  112.         myDlgHookUPP = NewDlgHookYDProc(DialogHook);
  113.         
  114.         // call Std File
  115.         CustomGetFile(nil, -1, mySFTypeList, &mySFR, 0, dialogPt, myDlgHookUPP,
  116.             nil, nil, nil, &hookRec);
  117.             
  118.         // Dispose of the routine descriptor, since they do allocate memory..
  119.         DisposeRoutineDescriptor(myDlgHookUPP);
  120.  
  121.  
  122.     }
  123.     
  124.     else {
  125.         // System 6 method
  126.     
  127.         // stuff low memory to display the proper initial directory; 
  128.         // see Inside Mac:Files 3-31
  129.         
  130.         DlgHookUPP    myOldDlgHookUPP;
  131.         
  132.         // Throw out your SysEqu.h file and start using the low memory 
  133.         // accessor functions provided in LowMem.h.
  134.         LMSetSFSaveDisk(-systemSpec.vRefNum);
  135.         LMSetCurDirStore(systemSpec.parID);
  136.  
  137.         // set up the string for the system file name
  138.         gSelectFileName = systemSpec.name;
  139.  
  140.         // Set up the universal proc pointer to your hook routine with this 
  141.         // macro defined in StandardFile.h.  **NOTE** This is different
  142.         // from the macro used for System 7 dialog hooks, and you should get
  143.         // a compiler error if you try to use the wrong UPP with the wrong call.
  144.         myOldDlgHookUPP = NewDlgHookProc(OldDlgHook);
  145.         
  146.         // call Std File
  147.         SFGetFile(dialogPt, nil, nil, -1, mySFTypeList, myOldDlgHookUPP, &oldSFR);
  148.  
  149.         // Dispose of the routine descriptor, since they do allocate memory..
  150.         DisposeRoutineDescriptor(myOldDlgHookUPP);
  151.         
  152.         // store the result in a new reply record
  153.         mySFR.sfGood = oldSFR.good;
  154.         if (oldSFR.good) {
  155.         
  156.             // convert the WDRefNum and copy the name string
  157.             retCode = GetWDInfo(oldSFR.vRefNum, 
  158.                 &mySFR.sfFile.vRefNum, &mySFR.sfFile.parID, &procID);
  159.             BlockMove(oldSFR.fName, mySFR.sfFile.name, 1 + oldSFR.fName[0]);
  160.         }
  161.     }
  162. }
  163.  
  164. // this dialog hook for System 7 std file selects
  165. // the file specified by the hookRecord supplied as userData
  166.  
  167. pascal short DialogHook(short item, DialogPtr theDialog, 
  168.     void *userData)
  169. {
  170.     HookRecordPtr hookRecPtr;
  171.     
  172.     hookRecPtr = (HookRecordPtr) userData;
  173.     
  174.     // hookRecPtr->itemSpec points to the FSSpec of the item to be selected
  175.     // hookRecPtr->theSFR points to the standard file reply record
  176.  
  177.     // make sure we're dealing with the proper dialog
  178.     if (GetWRefCon(theDialog) == sfMainDialogRefCon) {
  179.     
  180.         // just when opening the dialog...
  181.         if (item == sfHookFirstCall) {
  182.     
  183.             // make the reply record hold the spec of the specified item
  184.             hookRecPtr->theSFR->sfFile = *hookRecPtr->itemSpec;
  185.             
  186.             // There’s a gotcha in Standard File when using sfHookChangeSelection. 
  187.             // Even though New Inside Macintosh: Files has a sample that doesn't set
  188.             // the sfScript field, it should be set, or the last object in the
  189.             // selected directory  will always be selected.
  190.             hookRecPtr->theSFR->sfScript = smSystemScript;
  191.  
  192.             // tell std file to change the selection to that item
  193.             item = sfHookChangeSelection;
  194.         }
  195.     }            
  196.         
  197.     return item;
  198. }
  199.  
  200.  
  201. // this std file dialog hook for System 6 selects the file
  202. // name in the global gSelectFileName
  203.  
  204. pascal short OldDlgHook(short item, DialogPtr theDialog)
  205. {
  206. #pragma unused (theDialog)
  207.     
  208.     // the idea here is to post keydown events, one per
  209.     // null hook-event, until the entire file name
  210.     // has been "typed" in (remember that the event queue
  211.     // is shorter than the maximum file name so we only post
  212.     // one key per null event)
  213.  
  214.     // reset the character counter initially
  215.     
  216.     if (item == sfHookFirstCall)
  217.         gSelectFileCounter = 0;
  218.         
  219.     // post one keyDown per null event until the string is exhausted
  220.     // This may not be a good idea for international software since 
  221.     // different input methods may be used.
  222.     // Instead, you may want to check the System version and temporarily 
  223.     // set the KeyScript to zero before doing these PostEvents.  
  224.     // Afterwards, set KeyScript back to its original mode.
  225.     else if (item == sfHookNullEvent) {
  226.         if (gSelectFileCounter < *gSelectFileName) {
  227.             gSelectFileCounter++;
  228.             PostEvent(keyDown, *(gSelectFileName+gSelectFileCounter));
  229.         }
  230.     }
  231.  
  232.     return item;
  233. }
  234.  
  235.  
  236. OSErr GetSystemFileSpec(FSSpecPtr systemSpec)
  237. {
  238.     // the System folder location is returned by FindFolder (or under
  239.     // System 6 by the compiler's FindFolder glue)
  240.     //
  241.     // the System file name is available in low-memory
  242.     
  243.     OSErr         retCode;
  244.     StringPtr    systemName;
  245.     
  246.     systemName = LMGetSysResName();        // Get the name of the System resource file
  247.  
  248.     retCode = FindFolder(kOnSystemDisk, kSystemFolderType, kCreateFolder,
  249.         &systemSpec->vRefNum, &systemSpec->parID);
  250.     if (retCode == noErr)
  251.         BlockMove((Ptr)systemName, systemSpec->name, systemName[0] + 1);
  252.     
  253.     return retCode;
  254. }
  255.