home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / fonts / fontshow.sit / MemHandler.Pas < prev    next >
Pascal/Delphi Source File  |  1988-09-09  |  8KB  |  143 lines

  1. UNIT MemHandler(3);
  2. (* This unit contains memory management routines for the FontShow program *)
  3. (* Version 1.0 by Richard Clark, September 1988 *)
  4. {$U-}
  5. {$D+}
  6.  
  7. INTERFACE
  8.  
  9.   {$U Globals}
  10.   {$U Windows}
  11.  
  12.   USES
  13.     MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf,
  14.     Globals, Windows;
  15.  
  16.   PROCEDURE InitMemoryHandler;                      (* Set up our "watchdog" routine *)
  17.      PROCEDURE PreAllocate;                            (* Allocate a new window record at the BOTTOM of the heap *)
  18.      PROCEDURE MemStatus;                              (* Report if we've reached a low memory condition *)
  19.   PROCEDURE UpdateUsage;                            (* Check the free space left, and update the "About" window *)
  20.                                                     (* if the value changes *)
  21.  
  22.   FUNCTION MyGrowZoneProc (cbNeeded: Size):LONGINT; (* This routine scavenges up some memory when we are running low *)
  23.  
  24. IMPLEMENTATION
  25.  
  26.      CONST
  27.           aLowMemory = 128;                               (* Alert for the low memory condition *)
  28.  
  29.      VAR
  30.           ErrLevel : INTEGER;                             (* Flag which shows if we've had a memory error *)
  31.  
  32.  
  33.      PROCEDURE MemStatus;
  34.   (* This procedure reports if the application has detected a low memory condition. It should be called at the START *)
  35.   (* of the main loop, after the other handlers have been unloaded. That way, if we're really low on memory, calling *)
  36.   (* this won't put us over the edge.                                                                                *)
  37.      VAR
  38.     itemHit :  INTEGER;
  39.   
  40.   BEGIN
  41.           IF (ErrLevel > 0) THEN                          (* If the low memory flag is set, put up an alert *)
  42.             itemHit := CautionAlert(ErrLevel, NIL);
  43.           ErrLevel := 0;                                  (* Reset the flag *)
  44.      END; (* MemStatus *)
  45.  
  46.  
  47.      PROCEDURE PreAllocate;
  48.   (* This procedure allocates a spare window record on the bottom of the heap.  It should be called *)
  49.   (* from within the main loop AFTER all of the other segments have been unloaded.  In this way,    *)
  50.   (* windows will be allocated from the bottom of the heap upwards, while code segments are loaded  *)
  51.   (* from the top downwards.  This helps avoid fragmenting the heap.                                *)
  52.   (*                                                                                                *)
  53.   (* The global variable WindowReserve contains a pointer to the currently reserved block.  To get  *)
  54.   (* a new block, just set this to NIL, and PreAllocate will allocate a replacement.                *)
  55.      BEGIN
  56.           IF (windowReserve = NIL) THEN
  57.                   WindowReserve := NewPtr(sizeof(WindowRecord));
  58.      END; (* PreAllocate *)
  59.  
  60.  
  61.      PROCEDURE LowMemory;
  62.   (* This procedure sets a flag if we are running out of memory.  Several of these procedures  *)
  63.   (* could be set up to signal varying levels of memory problems, but we'll only use one level *)
  64.   (* of reporting here.                                                                        *)
  65.      BEGIN
  66.           IF ErrLevel < aLowMemory THEN                   (* If the flag's not set, then set it *)
  67.                ErrLevel := aLowMemory;
  68.      END; (* LowMemory *)
  69.  
  70.  
  71.      PROCEDURE UpdateUsage;
  72.   (* This procedure checks the amount of memory left, and updates the value in the About window *)
  73.   (* if the free memory value changes.                                                          *)
  74.         VAR
  75.               oldFreeMem : LONGINT;
  76.  
  77.      BEGIN
  78.           oldFreeMem := currFreeMem;                      (* Save the old value *)
  79.           currFreeMem := FreeMem;                         (* get the new value *)
  80.           IF (currFreeMem <> oldFreeMem) THEN             (* and update the display if the value changes *)
  81.               UpdateAboutWindow;
  82.      END; (* UpdateUsage *)
  83.  
  84.  
  85.      FUNCTION MyGrowZoneProc;
  86.   (* This function is called by the system if we've requested a block of memory and the system cannot *)
  87.   (* find an empty block that's large enough.  (The system has already purged out as many resources   *)
  88.   (* as it can at this point. It calls us in the hope that we can supply some memory.)  Normally, if  *)
  89.   (* we didn't supply this procedure, System Error 25 ("Out of Memory") would result, which is pretty *)
  90.   (* unfriendly.  So, since we could do without the "Automatic Update" pictures on our windows, (it's *)
  91.   (* not too hard to update them normally, it's just a shade slower than using the automatic updates) *)
  92.   (* we'll try getting rid of window pictures until we either run out of windows or until the system  *)
  93.   (* is satisfied.                                                                                    *)
  94.   (*                                                                                                  *)
  95.   (* We're expected to return 0 if no memory could be found (forcing a System Error 25), or any other *)
  96.   (* number if some memory could be found.  The system will call us again if it needs more help.      *)
  97.   (*                                                                                                  *)
  98.   (* This procedure needs to be in memory ALL of the time, so it's in the same segment as our main    *)
  99.   (* loop.                                                                                            *)
  100.         VAR
  101.              testWindow  : WindowPeek;                       (* One of the windows in the list *)
  102.              MemReleased : Boolean;                          (* Were we able to free up some memory *)
  103.  
  104.   BEGIN
  105.        MemReleased := FALSE;
  106.  
  107.           testWindow := WindowPeek(FrontWindow);
  108.           REPEAT                                          (* Scan down the window list, looking for the *)
  109.                                                     (* first font window with an attached picture.*)
  110.                IF (testWindow <> NIL) THEN
  111.                     IF (testWindow^.windowKind < 0) OR (testWindow^.refCon <> wFont) THEN
  112.                          testWindow := testWindow^.nextWindow      (* If it's a DA or not a font window, skip it *)
  113.                     ELSE IF (testWindow^.windowPic <> NIL) THEN (* If there's a picture, get rid of it *)
  114.                        BEGIN
  115.                             DisposHandle(Handle(testWindow^.windowPic));
  116.                             testWindow^.windowPic := NIL;
  117.                             testWindow := NIL;                        (* Mark this window as having no picture *)
  118.                             MemReleased := TRUE;                      (* Set the flag to show that we released some memory *)
  119.                       END ELSE
  120.                          testWindow := testWindow^.nextWindow;     (* This Font window has no picture, so try the next one *)
  121.           UNTIL (testWindow = NIL);
  122.  
  123.           IF (MemReleased) THEN                           (* Okay, we scavenged some memory. *)
  124.              BEGIN
  125.                   LowMemory;                                    (* Warn the user *)
  126.                   MyGrowZoneProc := 1;                          (* Ask the system to try again *)
  127.              END ELSE                                        (* We gave everything -- there's nothing left *)
  128.              MyGrowZoneProc := 0;                            (* Force a System Error 25 *)
  129.      END; (* MyGrowZoneProc *)
  130.  
  131.  
  132.   PROCEDURE InitMemoryHandler;
  133.   (* This procedure sets up our special "Low Memory" watchdog procedure *)
  134.      BEGIN
  135.           currFreeMem := 0;
  136.           ErrLevel := 0;                                  (* No low memory errors yet *)
  137.           MaxApplZone;                                    (* Expand the Application Heap to full size, *)
  138.                                                     (* so we get more accurate free memory reports *)
  139.                                                     (* (and possibly less fragmentation).        *)
  140.     SetGrowZone(@MyGrowZoneProc);                   (* Install the watchdog procedure *)
  141.      END; (* InitMemoryHandler *)
  142.  
  143. END.