home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / sys / mac / programm / 22096 < prev    next >
Encoding:
Text File  |  1993-01-24  |  4.9 KB  |  189 lines

  1. Newsgroups: comp.sys.mac.programmer
  2. Path: sparky!uunet!cs.utexas.edu!sun-barr!ames!data.nas.nasa.gov!taligent!kip-50.taligent.com!user
  3. From: keith@taligent.com (Keith Rollin)
  4. Subject: Re: Keeping a resource file open forever from an INIT
  5. Message-ID: <keith-240193180424@kip-50.taligent.com>
  6. Followup-To: comp.sys.mac.programmer
  7. Sender: usenet@taligent.com (More Bytes Than You Can Read)
  8. Organization: Taligent
  9. References: <2L9WB4WS@cc.swarthmore.edu>
  10. Date: Mon, 25 Jan 1993 02:21:29 GMT
  11. Lines: 176
  12.  
  13. In article <2L9WB4WS@cc.swarthmore.edu>, pbrande1@cc.swarthmore.edu (Philip
  14. Brandenberger) wrote:
  15. > Hello all-- I hope this is blatantly FAQ.
  16. > I am working on an INIT in which I'd like to keep my resource file open
  17. > forever much as Suitcase/MasterJuggler does for itself and its suitcases and
  18. > as Carpetbag does also.  
  19. > I gather that the way to do this is to hack at the FCBs, but the whole
  20. > process is a bit cloudy.  If anyone has sample code or a basic description
  21. > that would be great.
  22.  
  23. Here's how I do it:
  24.  
  25. // --------------------
  26. // A macro for patching traps. Follows my own naming conventions, so it
  27. // may not be useful for you. But I include it for completeness.
  28.  
  29. #define PatchTheTrap(trapName, type) \
  30.     old##trapName = (trapName##Proc) Get##type##TrapAddress(_##trapName); \
  31.     Set##type##TrapAddress((long) My##trapName, _##trapName)
  32.  
  33. // --------------------
  34. // The relevent parts of my INIT's startup code. I strip the PC according
  35. // to Technote #245 (I don't know its name under the new TN scheme). I then
  36. // roll my own RememberA0/SetUpA4, since it saves a few bytes. Next, I
  37. patch
  38. // InitAllPacks and remember what file I came from for later. Finally, I
  39. // restore A4 and leave.
  40.  
  41. void    main()
  42. {
  43.     Ptr            ourAddress;
  44.     Handle        ourHandle;
  45.     Handle        show;
  46.     
  47.     asm {
  48.         lea        @continue,A0        ; Fix up the PC (TN #245)
  49.         move.l    A0,D0
  50.         StripAddress                ; clean the PC
  51.         move.l    D0,A0
  52.         jmp        (A0)                ; use the new PC
  53.     @continue
  54.  
  55.         move.l    A4,-(sp)            ; save orig A4
  56.         bsr        __GetA4                ; get pointer to save location into A1
  57.         lea        main,A4                ; get our A4
  58.         move.l    A4,(A1)                ; save it so SetUpA4() will work
  59.         move.l    A4, ourAddress        ; for the RecoverHandle, later
  60.     }
  61.  
  62.     PatchTheTrap(InitAllPacks, Tool);
  63.     RememberMe();
  64.  
  65.     RestoreA4();
  66. }
  67.  
  68. // --------------------
  69. // Remembers the name and location of the file owning the currently active
  70. // resource map. This is stored in a global variable, which is a snap under
  71. // THINK C. If you are using MPW, read Technote #256 or develop #12.
  72.  
  73. static void    RememberMe()
  74. {
  75.     FCBPBRec    pb;
  76.     OSErr        err;
  77.  
  78.     pb.ioCompletion = nil;
  79.     pb.ioNamePtr = gOurName;
  80.     pb.ioVRefNum = 0;
  81.     pb.ioRefNum = CurResFile();
  82.     pb.ioFCBIndx = 0;
  83.     
  84.     err = PBGetFCBInfoSync(&pb);
  85.     
  86.     gOurVRefNum = pb.ioFCBVRefNum;
  87.     gOurDirID = pb.ioFCBParID;
  88. }
  89.  
  90. // --------------------
  91. // InitAllPacks is called during the launching of an application. I take
  92. this
  93. // opportunity to re-open my INIT (since the system closes it after it was
  94. // called during boot-up time).
  95.  
  96. static pascal void    MyInitAllPacks(void)
  97. {
  98.     SetUpA4();
  99.     
  100.     oldInitAllPacks();
  101.     
  102.     if (gMyRefNum == 0)
  103.         OpenAndAddMe();
  104.         
  105.     RestoreA4();
  106. }
  107.  
  108. // --------------------
  109. // Tricky routine that opens a resource file and places the resource map
  110. // BEHIND the system's. I want it behind the system resource file because I
  111. // want it available even if the program calls UseResFile(0). Doing it this
  112. // way also means that I only have to open the resource file once instead
  113. of
  114. // once per application.
  115.  
  116. pascal short InlineHOpenResFile(short vRefNum,long dirID,ConstStr255Param
  117. fileName,
  118.     char permission) = 0xA81A; 
  119.  
  120. static void    OpenAndAddMe()
  121. {
  122.     THz                currentZone;
  123.  
  124.     short            oldFile;
  125.     short            refNum;
  126.     ResMapHandle    current = nil;
  127.     ResMapHandle    previous = nil;
  128.     ResMapHandle    ourParent = nil;
  129.     ResMapHandle    us = nil;
  130.     ResMapHandle    system = nil;
  131.     
  132.     currentZone = GetZone();
  133.     SetZone(SystemZone());
  134.  
  135.     oldFile = CurResFile();
  136.     refNum = InlineHOpenResFile(gOurVRefNum, gOurDirID, gOurName, fsRdPerm);
  137.     UseResFile(oldFile);
  138.     
  139.     if (refNum != -1) {
  140.  
  141.         current = (ResMapHandle) TopMapHndl;
  142.         
  143.         // First, find us (we should be on top)
  144.  
  145.         while ((current != nil) && ((**current).refNum != refNum)) {
  146.             previous = current;
  147.             current = (**current).nextMap;
  148.         }
  149.         if (current != nil) {
  150.             ourParent = previous;
  151.             us = current;
  152.         }
  153.         
  154.         // Second, find the System
  155.         
  156.         system = (ResMapHandle) SysMapHndl;
  157.         
  158.         if ((us == nil) || (system == nil)) {
  159.             CloseResFile(refNum);
  160.         } else {
  161.             if (ourParent != system) {
  162.             
  163.             //
  164.             // Be sure to perform all these steps so that the
  165.             // resource chain is never inconsistant or circular.
  166.             // If that happens, debuggers like TMON will detonate.
  167.             //
  168.                 if ((ResMapHandle) TopMapHndl == us)
  169.                     TopMapHndl = (void*) (**us).nextMap;
  170.                 if (ourParent)
  171.                     (**ourParent).nextMap = (**us).nextMap;
  172.                 (**us).nextMap = (**system).nextMap;
  173.                 (**system).nextMap = us;
  174.             }
  175.             gMyRefNum = refNum;
  176.         }
  177.     }
  178.     SetZone(currentZone);
  179. }
  180.  
  181.  
  182. -----
  183. Keith Rollin
  184. Phantom Programmer
  185. Taligent, Inc.
  186.