home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / System / Swatch / Development / swatch 1.2 / swatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-26  |  39.7 KB  |  1,555 lines  |  [TEXT/KAHL]

  1. /**
  2.  
  3.     swatch.c
  4.     Copyright (c) 1990,1991, joe holt
  5.  
  6.  **/
  7.  
  8.  
  9. /**-----------------------------------------------------------------------------
  10.  **
  11.  **    Headers
  12.  **
  13.  **/
  14.  
  15. #include <GestaltEqu.h>
  16. #include <Processes.h>
  17. #include <pstring.h>
  18.  
  19. #include "swatch.resources.h"
  20. #include "swatch.types.h"
  21. #include "swatch.prefs.h"
  22. #include "swatch.heap.h"
  23. #include "swatch.about.h"
  24. #include "swatch.h"
  25.  
  26.  
  27. /**-----------------------------------------------------------------------------
  28.  **
  29.  ** Private Macros
  30.  **
  31.  **/
  32.  
  33. #define TRAP_MFTempMemory        0xA88F
  34. #define TRAP_Unimplemented        0xA89F
  35.  
  36. #define MacJmp                    0x120
  37.  
  38.  
  39. /**-----------------------------------------------------------------------------
  40.  **
  41.  ** Private Constants
  42.  **
  43.  **/
  44.  
  45. #define MIN_DEPTH_FOR_COLOR                4
  46. #define COLOR8                            0
  47. #define COLOR4                            1
  48. #define GRAY8                            2
  49. #define GRAY4                            3
  50.  
  51. #define JUST_LOCK_MEMORY_MASK            0
  52. #define RESIZE_PROCESS_LIST_MASK        1
  53. #define RESIZE_DISPLAY_LIST_MASK        2
  54.  
  55. #define CHECK_ALL_SIZES_START            -1
  56. #define CHECK_ALL_SIZES_END                0
  57.  
  58. #define FORCE_UPDATE_NAME_MASK            1
  59. #define FORCE_UPDATE_SIZE_MASK            2
  60. #define FORCE_UPDATE_FREE_MASK            4
  61. #define FORCE_UPDATE_HEAP_MASK            8
  62. #define FORCE_UPDATE_HEADER_MASK        16
  63. #define FORCE_UPDATE_HEAP_SCALE_MASK    32
  64. #define FORCE_UPDATE_BOTTOM_MASK        64
  65.  
  66. #define NO_UPDATE                        0
  67. #define FORCE_UPDATE_FIELDS                15
  68. #define FORCE_UPDATE_FIELDS_AND_BORDER    63
  69. #define FORCE_UPDATE_EVERYTHING_MASK    127
  70.  
  71. #define HORIZ_ARROW_DELTA                8
  72.  
  73. #define MBOX_HEAP_ADDRESS                1
  74. #define MBOX_ADDRESS                    2
  75.  
  76. #define MBOX_ERASE                        1
  77. #define MBOX_FRAME_AND_CONTENTS            2
  78. #define MBOX_CONTENTS                    3
  79.  
  80. #define MIN_DISPLAY_LIST_SIZE            4
  81.  
  82.  
  83. /**-----------------------------------------------------------------------------
  84.  **
  85.  ** Private Variables
  86.  **
  87.  **/
  88.  
  89. char system_heap_name[] = "\pSystem";
  90. char multifinder_name[] = "\pMultiFinder";
  91. char swatch_name[] = "\pSystem Watch";
  92.  
  93. Swatch_globals_t *Globals_P;
  94. Display_stat_t **display_list_h, *display_list;
  95. int16 display_list_elems;
  96. ProcessSerialNumber **process_list_h;
  97. int16 process_list_elems;
  98. Boolean too_many_apps;
  99.  
  100. WindowPtr App_window;
  101. ControlHandle horiz_scroll, vert_scroll;
  102. int16 num_display_lines;
  103. Boolean partial_display_line;
  104.  
  105. int32 display_heap_bytes, horiz_scroll_scale;
  106. int32 heap_offset_pixels, heap_right_pixels;
  107. int32 max_heap_size = 0;
  108. int16 heap_cursor;
  109.  
  110. Boolean in_foreground;
  111. Boolean Process_heaps_are_32_bit;
  112. MenuHandle Apple_menu, File_menu, Edit_menu;
  113.  
  114. EventRecord the_event;
  115.  
  116. int16 mbox_type = 0;
  117. char mbox_text[256] = {0};
  118. int32 mbox_value1;
  119. int32 mbox_value2;
  120.  
  121. CTabHandle cluts[4];
  122. CTabHandle current_clut;
  123. int16 clut_index;
  124. Handle patterns;    /* PAT# resource */
  125. Boolean color_is_dead;
  126.  
  127.  
  128. /**-----------------------------------------------------------------------------
  129.  **
  130.  ** Private Functions
  131.  **
  132.  **/
  133.  
  134. int main( void );
  135.  
  136. OSErr resize_lists( int16 resize_mask );
  137. Boolean process_list_changed( void );
  138. void update_display_list( int16 update_mask );
  139. void check_sizes( int16 update_mask, int16 line_start, int16 line_end );
  140.  
  141. void display_header( int16 update_mask );
  142. void display_heap( Display_stat_t *d, Rect *display_rect, int16 update_mask );
  143. void display_appname( Display_stat_t *d, Rect *display_rect, int16 update_mask );
  144. void display_current_size( Display_stat_t *d, Rect *display_rect, int16 update_mask );
  145. void display_current_free( Display_stat_t *d, Rect *display_rect, int16 update_mask );
  146. void add_commas( register char *num );
  147.  
  148. void draw_grow_icon( WindowPtr the_window, Boolean active_state, Boolean rgn_state );
  149. void activate_window( WindowPtr the_window, Boolean active_state );
  150. Boolean handle_menu_select( uns32 menu_long );
  151. void check_color_usage( Boolean first_thru );
  152.  
  153. void mouse_down_in_names( void );
  154. void mouse_down_in_heap( void );
  155. void set_cursor( void );
  156.  
  157. void clip_with_controls( void );
  158. void clip_without_controls( void );
  159. void size_controls( void );
  160. void reset_vert_scroll( void );
  161. void reset_horiz_scroll( void );
  162. void draw_mbox( int16 what );
  163.  
  164. pascal void vert_scroll_proc( ControlHandle the_control, int16 part );
  165. pascal void horiz_scroll_proc( ControlHandle the_control, int16 part );
  166.  
  167.  
  168. /*******************************************************************************
  169.  **
  170.  **    Public Variables
  171.  **
  172.  **/
  173.  
  174. SysEnvRec This_mac;
  175. Boolean Pre_system_7;
  176. Boolean Use_color;
  177. Boolean Debugger_installed;
  178.  
  179.  
  180. /*******************************************************************************
  181.  **
  182.  **    Public Functions
  183.  **
  184.  **/
  185.  
  186. /*******************************************************************************
  187.  ***
  188.  *** prototype
  189.  ***
  190.  *** summary
  191.  ***
  192.  *** History:
  193.  ***
  194.  *** To Do:
  195.  ***
  196.  ***/
  197.  
  198. int main( void )
  199. {
  200.     register int16 i;
  201.     register boolean done;
  202.     ParamBlockRec open_PB, control_PB;
  203.     Rect bounds;
  204.     int16 wne_in_foreground, wne_in_background;
  205.     int16 **wne;
  206.  
  207.     MaxApplZone();
  208.     InitGraf( &thePort );
  209.     InitFonts();
  210.     InitWindows();
  211.     InitDialogs( NULL );
  212.     TEInit();
  213.     InitMenus();
  214.     InitCursor();
  215.     MoreMasters();
  216.  
  217.     SysEnvirons( 1, &This_mac );
  218.     if ( This_mac.systemVersion < 0x0603 ) {
  219.         StopAlert( BAD_SYSTEM_VERSION_ALRT, NULL );
  220.         return;
  221.     }
  222.  
  223.     Debugger_installed = *(uns32 *) MacJmp != 0;
  224.  
  225.     for ( i = 5; i; --i )
  226.         EventAvail( 0, &the_event );
  227.     in_foreground = true;
  228.  
  229.     if ( ( Pre_system_7 = This_mac.systemVersion < 0x0700 ) ) {
  230.         open_PB.ioParam.ioNamePtr = (StringPtr) "\p._swatch";
  231.         open_PB.ioParam.ioPermssn = 0;
  232.         if ( PBOpen( &open_PB, false ) ) {
  233.             StopAlert( NO_INIT_ALRT, NULL );
  234.             return;
  235.         }
  236.     
  237.         control_PB.cntrlParam.ioCRefNum = open_PB.ioParam.ioRefNum;
  238.         control_PB.cntrlParam.csCode = csGetGlobals;
  239.         if ( PBControl( &control_PB, false ) ) {
  240.             StopAlert( INIT_PROBLEMS_ALRT, NULL );
  241.             return;
  242.         }
  243.         Globals_P = (Swatch_globals_t *) control_PB.cntrlParam.ioNamePtr;
  244.     
  245.         if ( Globals_P->version != VERSION ) {
  246.             StopAlert( INIT_INCOMPATIBLE_ALRT, NULL );
  247.             return;
  248.         }
  249.  
  250.         if ( NGetTrapAddress( TRAP_MFTempMemory, ToolTrap ) ==
  251.                 NGetTrapAddress( TRAP_Unimplemented, ToolTrap ) ) {
  252.             StopAlert( NOT_MULTIFINDER_ALRT, NULL );
  253.             return;
  254.         }
  255.     }
  256.  
  257.     process_list_h = (ProcessSerialNumber **) NewHandle( 0 );
  258.     process_list_elems = 0;
  259.     display_list_h = (Display_stat_t **) NewHandle( sizeof( Display_stat_t ) );
  260.     display_list_elems = 1;
  261.     if ( !process_list_h || !display_list_h ) {
  262.         StopAlert( OUT_OF_MEMORY_ALRT, NULL );
  263.         return;
  264.     }
  265.     resize_lists( JUST_LOCK_MEMORY_MASK );
  266.     pstrcopy( system_heap_name, display_list[0].app.appname );
  267.     display_list[0].app.zone = *(THz *) SysZone;
  268.     display_list[0].heap_is_32_bit = false;
  269.     Process_heaps_are_32_bit = false;
  270.     if ( !Pre_system_7 ) {
  271.         int32 response;
  272.  
  273.         if ( !Gestalt( gestaltAddressingModeAttr, &response ) ) {
  274.             display_list[0].heap_is_32_bit = (response & (1 << gestalt32BitSysZone)) != 0;
  275.             Process_heaps_are_32_bit = (response & (1 << gestalt32BitAddressing)) != 0;
  276.         }
  277.     }
  278.     display_list[0].last_size = display_list[0].last_free = 0;
  279.     display_list[0].last_heap_ok = true;
  280.     display_list[0].last_heap_transitions = 0;
  281.  
  282.     patterns = GetResource( 'PAT#', BLACK_WHITE_PAT_ );
  283.     if ( !patterns ) {
  284.         StopAlert( OUT_OF_MEMORY_ALRT, NULL );
  285.         return;
  286.     }
  287.  
  288.     Read_prefs();
  289.     if ( !( wne = (int16 **) GetResource( 'WNE ', 1000 ) ) ) {
  290.         StopAlert( WNE_DAMAGED_ALRT, NULL );
  291.         return;
  292.     }
  293.     wne_in_foreground = (*wne)[0];
  294.     wne_in_background = (*wne)[1];
  295.  
  296.     if ( This_mac.hasColorQD )
  297.         App_window = NewCWindow( NULL, &Swatch_prefs.window_rect, (StringPtr) swatch_name, true,
  298.                 documentProc, (WindowPtr) -1, true, 0 );
  299.     else
  300.         App_window = NewWindow( NULL, &Swatch_prefs.window_rect, (StringPtr) swatch_name, true,
  301.                 documentProc, (WindowPtr) -1, true, 0 );
  302.  
  303.     SetPort( App_window );
  304.     clip_with_controls();
  305.     SetRect( &bounds, 0, 0, 0, 0 );
  306.     vert_scroll = NewControl( App_window, &bounds, NULL, true, 0, 0, 0, scrollBarProc, 0 );
  307.     horiz_scroll = NewControl( App_window, &bounds, NULL, true, 0, 0, 0, scrollBarProc, 0 );
  308.     size_controls();
  309.  
  310.     TextFont( geneva );
  311.     TextSize( 9 );
  312.     check_color_usage( true );
  313.  
  314.     Apple_menu = GetMenu( APPLE_MENU );
  315.     AddResMenu( (Apple_menu = GetMenu( APPLE_MENU )), 'DRVR' );
  316.     InsertMenu( Apple_menu, 0 );
  317.     InsertMenu( (File_menu = GetMenu( FILE_MENU )), 0 );
  318.     InsertMenu( (Edit_menu = GetMenu( EDIT_MENU )), 0 );
  319.     DrawMenuBar();
  320.  
  321.     if ( process_list_changed() )
  322.         update_display_list( NO_UPDATE );
  323.  
  324.     for ( done = false; !done; ) {
  325.         WaitNextEvent( everyEvent, &the_event, ( in_foreground ? wne_in_foreground :
  326.                 wne_in_background ), NULL );
  327.         SetPort( App_window );
  328.         if ( FrontWindow() == App_window ) {
  329.             DisableItem( Edit_menu, 1 );
  330.             DisableItem( Edit_menu, 3 );
  331.             if ( mbox_text[0] )
  332.                 EnableItem( Edit_menu, 4 );
  333.             else
  334.                 DisableItem( Edit_menu, 4 );
  335.             DisableItem( Edit_menu, 5 );
  336.             DisableItem( Edit_menu, 6 );
  337.         }
  338.         else {
  339.             EnableItem( Edit_menu, 1 );
  340.             EnableItem( Edit_menu, 3 );
  341.             EnableItem( Edit_menu, 4 );
  342.             EnableItem( Edit_menu, 5 );
  343.             EnableItem( Edit_menu, 6 );
  344.         }
  345.         check_color_usage( false );
  346.  
  347.         switch ( the_event.what ) {
  348.         case nullEvent:
  349.             GlobalToLocal( &the_event.where );
  350.             set_cursor();
  351.             if ( process_list_changed() )
  352.                 update_display_list( FORCE_UPDATE_EVERYTHING_MASK );
  353.             else
  354.                 check_sizes( NO_UPDATE, CHECK_ALL_SIZES_START, CHECK_ALL_SIZES_END );
  355.             break;
  356.  
  357.         case mouseDown:
  358.             i = FindWindow( the_event.where, (WindowPtr *) &the_event.message );
  359.             if ( i != inContent )
  360.                 InitCursor();
  361.             if ( i == inMenuBar )
  362.                 done = handle_menu_select( MenuSelect( the_event.where ) );
  363.             else if ( (WindowPtr) the_event.message == App_window ) {
  364.                 switch ( i ) {
  365.                 case inDrag:
  366.                     DragWindow( App_window, the_event.where, &(***(RgnHandle *)GrayRgn).rgnBBox );
  367.                     break;
  368.  
  369.                 case inContent: {
  370.                     ControlHandle the_control;
  371.                     register int16 i, j;
  372.  
  373.                     GlobalToLocal( &the_event.where );
  374.                     set_cursor();
  375.                     i = FindControl( the_event.where, App_window, &the_control );
  376.                     if ( the_control == vert_scroll ) {
  377.                         if ( i == inThumb ) {
  378.                             i = GetCtlValue( the_control );
  379.                             TrackControl( the_control, the_event.where, NULL );
  380.                             if ( GetCtlValue( the_control ) != i )
  381.                                 check_sizes( FORCE_UPDATE_FIELDS | FORCE_UPDATE_BOTTOM_MASK,
  382.                                         CHECK_ALL_SIZES_START, CHECK_ALL_SIZES_END );
  383.                         }
  384.                         else
  385.                             TrackControl( the_control, the_event.where,
  386.                                     (ProcPtr) vert_scroll_proc );
  387.                     }
  388.                     else if ( the_control == horiz_scroll ) {
  389.                         if ( i == inThumb ) {
  390.                             i = GetCtlValue( the_control );
  391.                             TrackControl( the_control, the_event.where, NULL );
  392.                             if ( ( j = GetCtlValue( the_control ) ) != i ) {
  393.                                 heap_offset_pixels = (int32) j * horiz_scroll_scale;
  394.                                 check_sizes( FORCE_UPDATE_HEAP_MASK, CHECK_ALL_SIZES_START,
  395.                                         CHECK_ALL_SIZES_END );
  396.                             }
  397.                         }
  398.                         else
  399.                             TrackControl( the_control, the_event.where,
  400.                                     (ProcPtr) horiz_scroll_proc );
  401.                     }
  402.                     else if ( the_event.where.h <= FREE_FIELD_RIGHT )
  403.                         mouse_down_in_names();
  404.                     else if ( the_event.where.h >= HEAP_FIELD_LEFT )
  405.                         mouse_down_in_heap();
  406.                     break;
  407.                 }
  408.  
  409.                 case inGrow: {
  410.                     register uns32 new_size;
  411.                     Rect size_rect;
  412.  
  413.                     SetRect( &size_rect, HEAP_FIELD_LEFT + 64, CELL_HEIGHT + 64,
  414.                             32767, 32767 );
  415.                     new_size = GrowWindow( App_window, the_event.where, &size_rect );
  416.                     if ( new_size ) {
  417.                         draw_grow_icon( App_window, false, false );
  418.                         HideControl( horiz_scroll );
  419.                         HideControl( vert_scroll );
  420.                         draw_mbox( MBOX_ERASE );
  421.                         SizeWindow( App_window, (int16) new_size, new_size >> 16, true );
  422.                         clip_with_controls();
  423.                         size_controls();
  424.                         draw_mbox( MBOX_FRAME_AND_CONTENTS );
  425.                         draw_grow_icon( App_window, true, true );
  426.                     }
  427.                     break;
  428.                 }
  429.  
  430.                 case inGoAway:
  431.                     if ( TrackGoAway( App_window, the_event.where ) )
  432.                         done = true;
  433.                     break;
  434.  
  435.                 default:
  436.                     break;
  437.                 }
  438.             }
  439.             break;
  440.  
  441.         case keyDown:
  442.         case autoKey: {
  443.             char key;
  444.  
  445.             key = the_event.message & charCodeMask;
  446.             if ( the_event.modifiers & cmdKey )
  447.                 done = handle_menu_select( MenuKey( key ) );
  448.             break;
  449.         }
  450.  
  451.         case updateEvt:
  452.             if ( (WindowPtr) the_event.message == App_window ) {
  453.                 BeginUpdate( App_window );
  454.                 UpdtControl( App_window, App_window->visRgn );
  455.                 draw_mbox( MBOX_FRAME_AND_CONTENTS );
  456.                 draw_grow_icon( App_window, in_foreground, true );
  457.                 check_sizes( FORCE_UPDATE_FIELDS_AND_BORDER, CHECK_ALL_SIZES_START,
  458.                         CHECK_ALL_SIZES_END );
  459.                 EndUpdate( App_window );
  460.             }
  461.             break;
  462.  
  463.         case activateEvt:
  464.             if ( (WindowPtr) the_event.message == App_window )
  465.                 activate_window( App_window, the_event.modifiers & activeFlag );
  466.             break;
  467.  
  468.         case app4Evt:
  469.             if ( *(unsigned char *) &the_event.message == 1 /* suspend/resume */ ) {
  470.                 if ( the_event.message & 1 /* resume */ )
  471.                     in_foreground = true;
  472.                 else
  473.                     in_foreground = false;
  474.                 HiliteWindow( App_window, in_foreground );
  475.                 activate_window( App_window, in_foreground );
  476.             }
  477.             break;
  478.  
  479.         default:
  480.             break;
  481.         }
  482.     }
  483.  
  484.     Swatch_prefs.window_rect = App_window->portRect;
  485.     LocalToGlobal( (Point *)&Swatch_prefs.window_rect );
  486.     LocalToGlobal( (Point *)&Swatch_prefs.window_rect.bottom );
  487.     Write_prefs();
  488.  
  489.     CloseWindow( App_window );
  490. }
  491.  
  492.  
  493. OSErr resize_lists( int16 resize_mask )
  494. {
  495.     OSErr err;
  496.  
  497.     err = noErr;
  498.     HUnlock( (Handle) process_list_h );
  499.     HUnlock( (Handle) display_list_h );
  500.     if ( resize_mask & RESIZE_PROCESS_LIST_MASK ) {
  501.         SetHandleSize( (Handle) process_list_h,
  502.                 process_list_elems * sizeof( ProcessSerialNumber ) );
  503.         if ( (err = MemError()) )
  504.             process_list_elems = 0;
  505.     }
  506.     if ( (resize_mask & RESIZE_DISPLAY_LIST_MASK) && !err ) {
  507.         SetHandleSize( (Handle) display_list_h,
  508.                 display_list_elems * sizeof( Display_stat_t ) );
  509.         if ( (err = MemError()) )
  510.             display_list_elems = 1;
  511.     }
  512.     MoveHHi( (Handle) process_list_h );
  513.     HLock( (Handle) process_list_h );
  514.     MoveHHi( (Handle) display_list_h );
  515.     HLock( (Handle) display_list_h );
  516.     display_list = (Display_stat_t *) StripAddress( *display_list_h );
  517.     too_many_apps = err != noErr;
  518.     return err;
  519. }
  520.  
  521.  
  522. Boolean process_list_changed( void )
  523. {
  524.     register Boolean need_major_update;
  525.     Boolean same;
  526.     ProcessSerialNumber psn;
  527.     ProcessInfoRec info;
  528.     register int16 old_process_list_elems, i;
  529.  
  530.     if ( Pre_system_7 ) {
  531.         need_major_update = Globals_P->apps_need_updating;
  532.         Globals_P->apps_need_updating = false;
  533.         return ( need_major_update );
  534.     }
  535.  
  536.     need_major_update = false;
  537.     old_process_list_elems = process_list_elems;
  538.     process_list_elems = 0;
  539.     for ( psn.highLongOfPSN = psn.lowLongOfPSN = 0; !GetNextProcess( &psn );
  540.             ++process_list_elems );
  541.  
  542.     if ( old_process_list_elems != process_list_elems ) {
  543.         need_major_update = true;
  544.         if ( resize_lists( RESIZE_PROCESS_LIST_MASK ) )
  545.             return true;
  546.     }
  547.  
  548.     for ( psn.highLongOfPSN = psn.lowLongOfPSN = 0, i = 0; i < process_list_elems; ++i ) {
  549.         if ( GetNextProcess( &psn ) ) {
  550.             process_list_elems = 0;
  551.             return true;
  552.         }
  553.         if ( !need_major_update ) {
  554.             SameProcess( &psn, &(*process_list_h)[i], &same );
  555.             if ( !same )
  556.                 need_major_update = true;
  557.         }
  558.         if ( need_major_update )
  559.             (*process_list_h)[i] = psn;
  560.     }
  561.     return need_major_update;
  562. }
  563.  
  564.  
  565. void update_display_list( int16 update_mask )
  566. {
  567.     register App_stat_t *a;
  568.     register Display_stat_t *d;
  569.     register int16 i, old_display_list_elems;
  570.     ProcessInfoRec info;
  571.     register OSErr err;
  572.  
  573.     old_display_list_elems = display_list_elems;
  574.     display_list_elems = 1;
  575.     if ( Pre_system_7 ) {
  576.         for ( a = Globals_P->apps, i = Globals_P->max_apps; i; --i, ++a ) {
  577.             if ( !a->free && !pstrequal( a->appname, multifinder_name ) )
  578.                 ++display_list_elems;
  579.         }
  580.         if ( !resize_lists( RESIZE_DISPLAY_LIST_MASK ) ) {
  581.             d = &display_list[1];
  582.             for ( a = Globals_P->apps, i = display_list_elems - 1; i; ++a ) {
  583.                 if ( !a->free && !pstrequal( a->appname, multifinder_name ) ) {
  584.                     d->app = *a;
  585.                     d->heap_is_32_bit = false;
  586.                     d->last_size = d->last_free = 0;
  587.                     d->last_heap_ok = true;
  588.                     d->last_heap_transitions = 0;
  589.                     ++d;
  590.                     --i;
  591.                 }
  592.             }
  593.         }
  594.     }
  595.  
  596.     /*** System 7 Process Manager stuff ***/
  597.  
  598.     else {
  599.         display_list_elems += process_list_elems;
  600.         if ( !resize_lists( RESIZE_DISPLAY_LIST_MASK ) ) {
  601.             d = &display_list[1];
  602.             for ( display_list_elems = 1, i = 0; i < process_list_elems; ++i ) {
  603.                 info.processInfoLength = sizeof( ProcessInfoRec );
  604.                 info.processName = (StringPtr) d->app.appname;
  605.                 info.processAppSpec = NULL;
  606.                 if ( !GetProcessInformation( &(*process_list_h)[i], &info ) ) {
  607.                     d->app.zone = (THz) info.processLocation;
  608.                     d->heap_is_32_bit = Process_heaps_are_32_bit;
  609.                     d->last_size = d->last_free = 0;
  610.                     d->last_heap_ok = true;
  611.                     d->last_heap_transitions = 0;
  612.                     ++d;
  613.                     ++display_list_elems;
  614.                 }
  615.             }
  616.         }
  617.     }
  618.  
  619.     if ( old_display_list_elems != display_list_elems && display_list_elems > num_display_lines )
  620.         SetCtlMax( vert_scroll, display_list_elems - num_display_lines );
  621.     if ( update_mask )
  622.         check_sizes( update_mask, CHECK_ALL_SIZES_START, CHECK_ALL_SIZES_END );
  623. }
  624.  
  625.  
  626. void check_sizes( int16 update_mask, int16 line_start, int16 line_end )
  627. {
  628.     register Display_stat_t *d;
  629.     register int16 i;
  630.     register int32 temp_max_heap_size;
  631.     Rect display_rect;
  632.  
  633.     clip_without_controls();
  634.     if ( line_start == -1 ) {
  635.         display_header( update_mask );
  636.         line_start = 0;
  637.         line_end = num_display_lines - 1;
  638.         if ( partial_display_line )
  639.             ++line_end;
  640.     }
  641.  
  642.     display_rect.top = CELL_HEIGHT + CELL_HEIGHT * line_start;
  643.     display_rect.bottom = display_rect.top + CELL_HEIGHT;
  644.  
  645.     line_start += GetCtlValue( vert_scroll );
  646.     line_end += GetCtlValue( vert_scroll );
  647.  
  648.     temp_max_heap_size = 0;
  649.     for ( d = display_list, i = 0; i < display_list_elems; ++i, ++d ) {
  650.         d->current_size = (int32) d->app.zone->bkLim -
  651.                 (int32) &d->app.zone->bkLim - 52 /* MF bytes */;
  652.         if ( d->current_size > temp_max_heap_size )
  653.             temp_max_heap_size = d->current_size;
  654.  
  655.         if ( i < line_start || i > line_end )
  656.             continue;
  657.  
  658.         display_rect.left = NAME_FIELD_LEFT;
  659.         display_rect.right = HEAP_FIELD_RIGHT;
  660.  
  661.         d->current_free = d->app.zone->zcbFree;
  662.  
  663.         if ( update_mask & FORCE_UPDATE_NAME_MASK ) {
  664.             display_rect.left = NAME_FIELD_LEFT;
  665.             display_rect.right = NAME_FIELD_RIGHT;
  666.             display_appname( d, &display_rect, update_mask );
  667.         }
  668.  
  669.         if ( (update_mask & FORCE_UPDATE_SIZE_MASK) || d->current_size != d->last_size ) {
  670.             display_rect.left = SIZE_FIELD_LEFT;
  671.             display_rect.right = SIZE_FIELD_RIGHT;
  672.             display_current_size( d, &display_rect, update_mask );
  673.             d->last_size = d->current_size;
  674.         }
  675.  
  676.         if ( (update_mask & FORCE_UPDATE_FREE_MASK) || d->current_free != d->last_free ) {
  677.             display_rect.left = FREE_FIELD_LEFT;
  678.             display_rect.right = FREE_FIELD_RIGHT;
  679.             display_current_free( d, &display_rect, update_mask );
  680.             d->last_free = d->current_free;
  681.         }
  682.  
  683.         display_rect.left = HEAP_FIELD_LEFT;
  684.         display_rect.right = App_window->portRect.right - 15;
  685.         make_current_heap( d );
  686.         display_heap( d, &display_rect, update_mask );
  687.  
  688.         display_rect.top += CELL_HEIGHT;
  689.         display_rect.bottom += CELL_HEIGHT;
  690.     }
  691.  
  692.     if ( update_mask & FORCE_UPDATE_BOTTOM_MASK ) {
  693.         display_rect.bottom = App_window->portRect.bottom;
  694.         if ( display_rect.bottom > display_rect.top ) {
  695.             display_rect.left = NAME_FIELD_LEFT;
  696.             display_rect.right = FREE_FIELD_RIGHT;
  697.             EraseRect( &display_rect );
  698.             display_rect.left = HEAP_FIELD_LEFT;
  699.             display_rect.right = HEAP_FIELD_RIGHT;
  700.             EraseRect( &display_rect );
  701.         }
  702.     }
  703.     clip_with_controls();
  704.     if ( temp_max_heap_size != max_heap_size ) {
  705.         max_heap_size = temp_max_heap_size;
  706.         reset_horiz_scroll();
  707.     }
  708. }
  709.  
  710.  
  711. void display_header( int16 update_mask )
  712. {
  713.     static char size_title[] = "\pHeap Size";
  714.     static char free_title[] = "\pFree";
  715.     static char heap_title1[] = "\p1 pixel : ";
  716.     static char heap_title2[] = "\p bytes";
  717.  
  718.     if ( update_mask & (FORCE_UPDATE_HEADER_MASK | FORCE_UPDATE_HEAP_SCALE_MASK) ) {
  719.         char num[20];
  720.         Rect erase;
  721.  
  722.         MoveTo( 0, CELL_HEIGHT - 1 );
  723.         set_fore_color_or_pattern( HEADER_BORDER_COLOR );
  724.         Line( 16384, 0 );
  725.         set_fore_color_or_pattern( BLACK_COLOR );
  726.     
  727.         erase.left = HEAP_FIELD_LEFT + 10 + StringWidth( (StringPtr) heap_title1 );
  728.         erase.right = HEAP_FIELD_RIGHT;
  729.         erase.top = 0;
  730.         erase.bottom = CELL_HEIGHT - 1;
  731.         pnumcopy( Swatch_prefs.heap_scale, num );
  732.         add_commas( num );
  733.         EraseRect( &erase );
  734.         MoveTo( HEAP_FIELD_LEFT + 10, CELL_HEIGHT - 2 );
  735.         set_fore_color( HEADER_COLOR );
  736.         DrawString( (StringPtr) heap_title1 );
  737.         DrawString( (StringPtr) num );
  738.         DrawString( (StringPtr) heap_title2 );
  739.         set_fore_color( BLACK_COLOR );
  740.     }
  741.  
  742.     if ( update_mask & FORCE_UPDATE_HEADER_MASK ) {
  743.         set_fore_color( HEADER_COLOR );
  744.         MoveTo( SIZE_FIELD_RIGHT - StringWidth( (StringPtr) size_title ), CELL_HEIGHT - 2 );
  745.         DrawString( (StringPtr) size_title );
  746.  
  747.         set_fore_color( FREE_COLOR );
  748.         MoveTo( FREE_FIELD_RIGHT - StringWidth( (StringPtr) free_title ), CELL_HEIGHT - 2 );
  749.         DrawString( (StringPtr) free_title );
  750.         set_fore_color( BLACK_COLOR );
  751.     }
  752. }
  753.  
  754.  
  755. void display_appname( register Display_stat_t *d, register Rect *display_rect,
  756.         int16 update_mask )
  757. {
  758.     char name[32];
  759.     Rect field;
  760.     register int16 len;
  761.     register char *p;
  762.  
  763.     field.left = NAME_FIELD_LEFT;
  764.     field.right = NAME_FIELD_RIGHT;
  765.     field.top = display_rect->top + NAME_TOP_DELTA;
  766.     field.bottom = field.top + TEXT_HEIGHT;
  767.  
  768.     pstrcopy( d->app.appname, name );
  769.     if ( ( len = StringWidth( (StringPtr) name ) ) > NAME_FIELD_RIGHT - NAME_FIELD_LEFT ) {
  770.         p = name + *name;
  771.         do {
  772.             len -= CharWidth( *p );
  773.             --p;
  774.             --*name;
  775.         } while ( len > NAME_FIELD_RIGHT - NAME_FIELD_LEFT );
  776.         *p = '…';
  777.     }
  778.     MoveTo( field.left, field.bottom - 2 );
  779.     EraseRect( &field );
  780.     set_fore_color( NAME_COLOR );
  781.     DrawString( (StringPtr) name );
  782.     set_fore_color( BLACK_COLOR );
  783. }
  784.  
  785.  
  786. void display_current_size( register Display_stat_t *d, register Rect *display_rect,
  787.         int16 update_mask )
  788. {
  789.     char num[20];
  790.     Rect field;
  791.  
  792.     field.left = SIZE_FIELD_LEFT;
  793.     field.right = SIZE_FIELD_RIGHT;
  794.     field.top = display_rect->top + SIZE_TOP_DELTA;
  795.     field.bottom = field.top + TEXT_HEIGHT;
  796.  
  797.     pnumcopy( d->current_size, num );
  798.     add_commas( num );
  799.     MoveTo( field.right - StringWidth( (StringPtr) num ), field.bottom - 2 );
  800.     EraseRect( &field );
  801.     set_fore_color( SIZE_COLOR );
  802.     DrawString( (StringPtr) num );
  803.     set_fore_color( BLACK_COLOR );
  804. }
  805.  
  806.  
  807. void display_current_free( register Display_stat_t *d, register Rect *display_rect,
  808.         int16 update_mask )
  809. {
  810.     char num[20];
  811.     Rect field;
  812.  
  813.     field.left = FREE_FIELD_LEFT;
  814.     field.right = FREE_FIELD_RIGHT;
  815.     field.top = display_rect->top + FREE_TOP_DELTA;
  816.     field.bottom = field.top + TEXT_HEIGHT;
  817.  
  818.     pnumcopy( d->current_free, num );
  819.     add_commas( num );
  820.     MoveTo( field.right - StringWidth( (StringPtr) num), field.bottom - 2 );
  821.     EraseRect( &field );
  822.     set_fore_color( FREE_COLOR );
  823.     DrawString( (StringPtr) num );
  824.     set_fore_color( BLACK_COLOR );
  825. }
  826.  
  827.  
  828. void add_commas( register char *num )
  829. {
  830.     register int16 num_commas, len;
  831.     register char *p;
  832.  
  833.     if ( ( len = *(unsigned char *) num ) < 4 )
  834.         return;
  835.  
  836.     num_commas = (len - 1) / 3;
  837.     *(unsigned char *) num += num_commas;
  838.     p = num + len - 2;
  839.     for ( ; num_commas; --num_commas, p-= 3 ) {
  840.         BlockMove( p, p + num_commas, 3 );
  841.         *(p + num_commas - 1) = ',';
  842.     }
  843. }
  844.  
  845.  
  846. void display_heap( register Display_stat_t *d, Rect *display_rect, int16 update_mask )
  847. {
  848.     register int32 *p, *q;
  849.     register int16 i;
  850.     register int32 right, offset;
  851.     register unsigned char run;
  852.     Boolean update;
  853.     Rect field;
  854.  
  855.     update = false;
  856.     if ( d->current_heap_ok != d->last_heap_ok ) {
  857.         d->last_heap_ok = d->current_heap_ok;
  858.         update = true;
  859.     }
  860.     if ( d->current_heap_transitions != d->last_heap_transitions ) {
  861.         d->last_heap_transitions = d->current_heap_transitions;
  862.         update = true;
  863.     }
  864.     for ( i = d->current_heap_transitions, p = d->current_heap, q = d->last_heap; i; --i ) {
  865.         if ( !update && *p != *q )
  866.             update = true;
  867.         *q++ = *p++;
  868.     }
  869.  
  870.     if ( !update && !(update_mask & FORCE_UPDATE_HEAP_MASK) )
  871.         return;
  872.  
  873.     field = *display_rect;
  874.     field.left = HEAP_FIELD_LEFT;
  875.     field.top += 2;
  876.     field.bottom -= 2;
  877.  
  878.     if ( !d->current_heap_ok ) {
  879.         EraseRect( &field );
  880.         MoveTo( field.left, field.bottom - 2 );
  881.         TextFace( bold );
  882.         DrawString( (StringPtr) "\pBAD   BAD   BAD   BAD" );
  883.         TextFace( 0 );
  884.         return;
  885.     }
  886.  
  887.     offset = 0;
  888.     i = d->current_heap_transitions;
  889.     p = d->current_heap;
  890.     do {
  891.         offset += *p++ & 0x00FFFFFF;
  892.     } while ( offset < heap_offset_pixels && --i );
  893.     if ( !i ) {
  894.         EraseRect( &field );
  895.         return;
  896.     }
  897.  
  898.     set_fore_color_or_pattern( ( !heap_offset_pixels ? HEAP_BORDER_COLOR : BACK_COLOR ) );
  899.     MoveTo( HEAP_FIELD_LEFT, field.top );
  900.     Line( 0, CELL_HEIGHT - 5 );
  901.  
  902.     InsetRect( &field, 1, 1 );
  903.     offset -= heap_offset_pixels;
  904.     run = *(unsigned char *) (p - 1);
  905.     for ( ;; ) {
  906.  
  907.         switch ( run ) {
  908.         case HEAP_FREE_RUN:
  909.             set_fore_color_or_pattern( HEAP_FREE_COLOR );
  910.             break;
  911.         case HEAP_LOCKED_RUN:
  912.             set_fore_color_or_pattern( HEAP_LOCKED_COLOR );
  913.             break;
  914.         case HEAP_UNLOCKED_RUN:
  915.             set_fore_color_or_pattern( HEAP_UNLOCKED_COLOR );
  916.             break;
  917.         case HEAP_PURGEABLE_RUN:
  918.             set_fore_color_or_pattern( HEAP_PURGEABLE_COLOR );
  919.             break;
  920.         default:
  921.             set_fore_color_or_pattern( BLACK_COLOR );
  922.             break;
  923.         }
  924.  
  925.         if ( offset < 16384 )
  926.             field.right = field.left + offset;
  927.         else
  928.             field.right = display_rect->right;
  929.         PaintRect( &field );
  930.         field.left = field.right;
  931.         if ( field.left > display_rect->right || !--i )
  932.             break;
  933.  
  934.         run = *(unsigned char *) p;
  935.         offset = *p++ & 0x00FFFFFF;
  936.     }
  937.     InsetRect( &field, 0, -1 );
  938.     if ( field.right < display_rect->right ) {
  939.         set_fore_color_or_pattern( HEAP_BORDER_COLOR );
  940.         MoveTo( field.right, field.top );
  941.         Line( 0, CELL_HEIGHT - 5 );
  942.     }
  943.     set_fore_color_or_pattern( BLACK_COLOR );
  944.  
  945.     MoveTo( HEAP_FIELD_LEFT + 1, field.top );
  946.     LineTo( field.right, field.top );
  947.     MoveTo( HEAP_FIELD_LEFT + 1, field.bottom - 1 );
  948.     LineTo( field.right, field.bottom - 1 );
  949.  
  950.     if ( update_mask & FORCE_UPDATE_HEAP_MASK ) {
  951.         ++field.left;
  952.         field.right = display_rect->right;
  953.         if ( field.left < field.right )
  954.             EraseRect( &field );
  955.     }
  956. }
  957.  
  958.  
  959. void draw_grow_icon( WindowPtr the_window, Boolean active_state, Boolean rgn_state )
  960. {
  961.     Boolean save_hilited;
  962.     Rect r;
  963.  
  964.     r = the_window->portRect;
  965.     r.top += CELL_HEIGHT;
  966.     ClipRect( &r );
  967.     save_hilited = ((WindowPeek) the_window)->hilited;
  968.     ((WindowPeek) the_window)->hilited = active_state;
  969.     DrawGrowIcon( the_window );
  970.     ((WindowPeek) the_window)->hilited = save_hilited;
  971.     r.top = r.bottom - 15;
  972.     r.left = r.right - 15;
  973.     if ( rgn_state )
  974.         ValidRect( &r );
  975.     else
  976.         InvalRect( &r );
  977.     clip_with_controls();
  978. }
  979.  
  980.  
  981. void activate_window( WindowPtr the_window, Boolean active_state )
  982. {
  983.     int16 control_state;
  984.  
  985.     draw_grow_icon( the_window, active_state, true );
  986.     control_state = active_state ? 0 : 255;
  987.     HiliteControl( vert_scroll, control_state );
  988.     HiliteControl( horiz_scroll, control_state );
  989.     heap_cursor = 0;
  990. }
  991.  
  992.  
  993. Boolean handle_menu_select( uns32 menu_long )
  994. {
  995.     switch ( menu_long >> 16 ) {
  996.     case APPLE_MENU:
  997.         if ( (int16) menu_long == 1 ) {
  998.             Do_about( App_window );
  999.             UnloadSeg( Do_about );
  1000.         }
  1001.         else {
  1002.             char DA_name[256];
  1003.  
  1004.             GetItem( Apple_menu, (int16) menu_long, (StringPtr) DA_name );
  1005.             OpenDeskAcc( (StringPtr) DA_name );
  1006.         }
  1007.         HiliteMenu( 0 );
  1008.         return false;
  1009.  
  1010.     case FILE_MENU:
  1011.         return true;
  1012.  
  1013.     case EDIT_MENU:
  1014.         ZeroScrap();
  1015.         PutScrap( *(unsigned char *) mbox_text, 'TEXT', &mbox_text[1] );
  1016.         HiliteMenu( 0 );
  1017.         return false;
  1018.  
  1019.     default:
  1020.         return false;
  1021.     }
  1022. }
  1023.  
  1024.  
  1025. void check_color_usage( Boolean first_thru )
  1026. {
  1027.     Rect window_rect, t_rect;
  1028.     register int16 min_depth, t_depth, t_index;
  1029.     register GDHandle gdevice;
  1030.     register PixMapHandle pmap;
  1031.     register CTabHandle clut;
  1032.     register Boolean use_gray;
  1033.  
  1034.     if ( !This_mac.hasColorQD || color_is_dead )
  1035.         Use_color = false;
  1036.     else {
  1037.         window_rect = App_window->portRect;
  1038.         LocalToGlobal( (Point *) &window_rect );
  1039.         LocalToGlobal( (Point *) &window_rect.bottom );
  1040.         for ( min_depth = 32, use_gray = false, gdevice = GetDeviceList(); gdevice;
  1041.                 gdevice = GetNextDevice( gdevice ) ) {
  1042.             if ( TestDeviceAttribute( gdevice, screenDevice ) &&
  1043.                     TestDeviceAttribute( gdevice, screenActive ) ) {
  1044.                 pmap = (**gdevice).gdPMap;
  1045.                 if ( SectRect( &(**pmap).bounds, &window_rect, &t_rect ) ) {
  1046.                     if ( !TestDeviceAttribute( gdevice, gdDevType ) )
  1047.                         use_gray = true;
  1048.                     if ( (t_depth = (**pmap).pixelSize) < min_depth )
  1049.                         min_depth = t_depth;
  1050.                 }
  1051.             }
  1052.         }
  1053.  
  1054.  
  1055.         if ( ( Use_color = (min_depth >= MIN_DEPTH_FOR_COLOR) ) ) {
  1056. /**
  1057.     clut indexes are:
  1058.         0    8-bit color
  1059.         1    4-bit color
  1060.         2    8-bit gray
  1061.         3    4-bit gray
  1062.  **/
  1063.             if ( use_gray )
  1064.                 t_index = 2;
  1065.             else
  1066.                 t_index = 0;
  1067.             if ( min_depth == 4 /* 4-bit color */)
  1068.                 ++t_index;
  1069.         }
  1070.         else
  1071.             t_index = -1;
  1072.  
  1073.         if ( first_thru || t_index != clut_index ) {
  1074.             if ( !first_thru ) {
  1075.                 InvalRect( &App_window->portRect );
  1076.                 if ( current_clut )
  1077.                     HPurge( (Handle) current_clut );
  1078.             }
  1079.             clut_index = t_index;
  1080.             if ( t_index == -1 )
  1081.                 current_clut = NULL;
  1082.             else {
  1083.                 current_clut = cluts[t_index];
  1084.                 if ( !current_clut ) {
  1085.                     current_clut = cluts[t_index] =
  1086.                             (CTabHandle) GetResource( 'clut', COLOR8_clut + t_index );
  1087.                     LoadResource( (Handle) current_clut );    /* make sure we've got it */
  1088.                     if ( !current_clut || !*current_clut ) {
  1089.                         color_is_dead = true;
  1090.                         Use_color = false;
  1091.                     }
  1092.                     else
  1093.                         HNoPurge( (Handle) current_clut );
  1094.                 }
  1095.             }
  1096.         }
  1097.     }
  1098. }
  1099.  
  1100.  
  1101. void set_fore_color_or_pattern( int16 color )
  1102. {
  1103.     if ( Use_color ) {
  1104.         HLock( (Handle) current_clut );
  1105.         RGBForeColor( &(**current_clut).ctTable[color].rgb );
  1106.         HUnlock( (Handle) current_clut );
  1107.     }
  1108.     else
  1109.         PenPat( (ConstPatternParam) ( (Ptr) (*patterns) + color * 8 + 2 ) );
  1110. }
  1111.  
  1112.  
  1113. void set_fore_color( int16 color )
  1114. {
  1115.     if ( Use_color )
  1116.         set_fore_color_or_pattern( color );
  1117. }
  1118.  
  1119.  
  1120. void set_back_color( int16 color )
  1121. {
  1122.     if ( Use_color ) {
  1123.         HLock( (Handle) current_clut );
  1124.         RGBBackColor( &(**current_clut).ctTable[color].rgb );
  1125.         HUnlock( (Handle) current_clut );
  1126.     }
  1127. }
  1128.  
  1129.  
  1130. void mouse_down_in_names( void )
  1131. {
  1132.     register int16 i, old_i;
  1133.     register Display_stat_t *d;
  1134.     char str[256];
  1135.     boolean in_bomb, mouse_in_bomb;
  1136.     Rect r;
  1137.  
  1138.     if ( the_event.where.v >= App_window->portRect.bottom - 15 ) {
  1139.         if ( Debugger_installed && the_event.where.h < 19 ) {
  1140.             SetRect( &r, 0, App_window->portRect.bottom - 14, 20,
  1141.                     App_window->portRect.bottom );
  1142.             in_bomb = false;
  1143.             while ( StillDown() ) {
  1144.                 GetMouse( &the_event.where );
  1145.                 mouse_in_bomb = PtInRect( the_event.where, &r );
  1146.                 if ( ( mouse_in_bomb && !in_bomb ) || ( !mouse_in_bomb && in_bomb ) ) {
  1147.                     in_bomb ^= 1;
  1148.                     InvertRect( &r );
  1149.                 }
  1150.             }
  1151.             if ( in_bomb ) {
  1152.                 if ( mbox_type == MBOX_HEAP_ADDRESS ) {
  1153.                     pstrcopy( "\p;hx ", str );
  1154.                     phexappend( mbox_value1, 8, str );
  1155.                     DebugStr( (StringPtr) str );
  1156.                 }
  1157.                 else if ( mbox_type == MBOX_ADDRESS ) {
  1158.                     pstrcopy( "\p;hx ", str );
  1159.                     phexappend( mbox_value1, 8, str );
  1160.                     pstrappend( "\p;wh ", str );
  1161.                     phexappend( mbox_value2, 8, str );
  1162.                     DebugStr( (StringPtr) str );
  1163.                 }
  1164.                 else
  1165.                     Debugger();
  1166.                 InvertRect( &r );
  1167.             }
  1168.         }
  1169.     }
  1170.     else {
  1171.         old_i = -1;
  1172.         while ( StillDown() ) {
  1173.             GetMouse( &the_event.where );
  1174.             i = the_event.where.v / CELL_HEIGHT;
  1175.             if ( i ) {
  1176.                 i += GetCtlValue( vert_scroll ) - 1;
  1177.                 if ( i < display_list_elems && i != old_i ) {
  1178.                     old_i = i;
  1179.                     d = display_list + i;
  1180.                     mbox_type = MBOX_HEAP_ADDRESS;
  1181.                     mbox_value1 = (int32) d->app.zone;
  1182.                     pstrcopy( "\pHeap is at $", mbox_text );
  1183.                     phexappend( mbox_value1, 8, mbox_text );
  1184.                     pstrappend( "\p (", mbox_text );
  1185.                     pstrappend( d->app.appname, mbox_text );
  1186.                     pchappend( ')', mbox_text );
  1187.                     draw_mbox( MBOX_CONTENTS );
  1188.                 }
  1189.             }
  1190.         }
  1191.         if ( old_i >= 0 ) {
  1192.             THz save_zone;
  1193.  
  1194.             save_zone = *(THz *) TheZone;
  1195.             *(THz *) TheZone = display_list[old_i].app.zone;
  1196.             PurgeMem( 0x7FFFFFFF );
  1197.             CompactMem( 0x7FFFFFFF );
  1198.             *(THz *) TheZone = save_zone;
  1199.         }
  1200.     }
  1201. }
  1202.  
  1203.  
  1204. void mouse_down_in_heap( void )
  1205. {
  1206.     register int16 i;
  1207.     register int32 address, old_address;
  1208.     register Display_stat_t *d;
  1209.     char str[256];
  1210.     Rect r;
  1211.  
  1212.     if ( the_event.where.v >= App_window->portRect.bottom - 15 ||
  1213.             the_event.where.v < CELL_HEIGHT )
  1214.         return;
  1215.  
  1216.     switch ( heap_cursor ) {
  1217.     case ZOOM_IN_CURS:
  1218.     case ZOOM_OUT_CURS:
  1219.         if ( heap_cursor == ZOOM_IN_CURS ) {
  1220.             Swatch_prefs.heap_scale >>= 1;
  1221.             --Swatch_prefs.heap_scale_2n;
  1222.             reset_horiz_scroll();
  1223.     /* pin heap to left edge if clicking close enough to start */
  1224.             if ( the_event.where.h - HEAP_FIELD_LEFT > 35 || heap_offset_pixels)
  1225.                 heap_offset_pixels = (heap_offset_pixels << 1) +
  1226.                         the_event.where.h - HEAP_FIELD_LEFT - 2;
  1227.         }
  1228.         else {
  1229.             Swatch_prefs.heap_scale <<= 1;
  1230.             ++Swatch_prefs.heap_scale_2n;
  1231.             reset_horiz_scroll();
  1232.     /* pin heap to left edge if clicking close enough to start */
  1233.             if ( the_event.where.h - HEAP_FIELD_LEFT > 35 || heap_offset_pixels)
  1234.                 heap_offset_pixels = (heap_offset_pixels - (the_event.where.h -
  1235.                         HEAP_FIELD_LEFT - 1)) >> 1;
  1236.         }
  1237.         if ( heap_offset_pixels < 0 )
  1238.             heap_offset_pixels = 0;
  1239.         else if ( heap_offset_pixels > heap_right_pixels )
  1240.             heap_offset_pixels = heap_right_pixels;
  1241.         SetCtlValue( horiz_scroll, heap_offset_pixels / horiz_scroll_scale );
  1242.         check_sizes( FORCE_UPDATE_HEAP_MASK | FORCE_UPDATE_HEAP_SCALE_MASK,
  1243.                 CHECK_ALL_SIZES_START, CHECK_ALL_SIZES_END );
  1244.         break;
  1245.  
  1246.     case INFO_CURS:
  1247.         old_address = 0;
  1248.         SetRect( &r, HEAP_FIELD_LEFT + 1, CELL_HEIGHT, App_window->portRect.right - 15,
  1249.                  App_window->portRect.bottom - 15 );
  1250.         while ( StillDown() ) {
  1251.             GetMouse( &the_event.where );
  1252.             if ( PtInRect( the_event.where, &r ) ) {
  1253.                 i = the_event.where.v / CELL_HEIGHT + GetCtlValue( vert_scroll ) - 1;
  1254.                 if ( i < display_list_elems ) {
  1255.                     d = display_list + i;
  1256.                     address = ( (heap_offset_pixels + the_event.where.h - HEAP_FIELD_LEFT - 2) <<
  1257.                             Swatch_prefs.heap_scale_2n ) + (int32) &d->app.zone->bkLim +
  1258.                                     60 /* MF bytes and block header */;
  1259.                     if ( address != old_address && address <= (int32) d->app.zone->bkLim ) {
  1260.                         old_address = address;
  1261.                         mbox_type = MBOX_ADDRESS;
  1262.                         mbox_value1 = (int32) d->app.zone;
  1263.                         mbox_value2 = address;
  1264.                         pchcopy( '$', mbox_text );
  1265.                         phexappend( address, 8, mbox_text );
  1266.                         draw_mbox( MBOX_CONTENTS );
  1267.                     }
  1268.                 }
  1269.             }
  1270.         }
  1271.         break;
  1272.  
  1273.     default:
  1274.         break;
  1275.     }
  1276. }
  1277.  
  1278.  
  1279. void set_cursor( void )
  1280. {
  1281.     Rect r;
  1282.     unsigned char keys[16];
  1283.     register int16 new_heap_cursor;
  1284.     Handle h;
  1285.  
  1286.     SetRect( &r, HEAP_FIELD_LEFT, CELL_HEIGHT, App_window->portRect.right - 15,
  1287.              App_window->portRect.bottom - 15 );
  1288.     if ( PtInRect( the_event.where, &r ) ) {
  1289.         GetKeys( (KeyMap *) keys );
  1290.         if ( keys[6] & 0x80 )
  1291.             new_heap_cursor = INFO_CURS;
  1292.         else if ( keys[7] & 0x04 ) {
  1293.             if ( Swatch_prefs.heap_scale < MAX_HEAP_SCALE )
  1294.                 new_heap_cursor = ZOOM_OUT_CURS;
  1295.             else
  1296.                 new_heap_cursor = NO_ZOOM_CURS;
  1297.         }
  1298.         else {
  1299.             if ( Swatch_prefs.heap_scale > MIN_HEAP_SCALE )
  1300.                 new_heap_cursor = ZOOM_IN_CURS;
  1301.             else
  1302.                 new_heap_cursor = NO_ZOOM_CURS;
  1303.         }
  1304.     }
  1305.     else
  1306.         new_heap_cursor = ARROW_CURS;
  1307.  
  1308.     if ( new_heap_cursor != heap_cursor ) {
  1309.         heap_cursor = new_heap_cursor;
  1310.         if ( heap_cursor == ARROW_CURS )
  1311.             InitCursor();
  1312.         else {
  1313.             SetResLoad( true );
  1314.             h = GetResource( 'CURS', new_heap_cursor );
  1315.             if ( h ) {
  1316.                 SetCursor( (Cursor *) *h );
  1317.                 HPurge( h );
  1318.             }
  1319.         }
  1320.     }
  1321. }
  1322.  
  1323.  
  1324. /*----------------------------------------*/
  1325.  
  1326.  
  1327. void draw_mbox( int16 what )
  1328. {
  1329.     Rect r;
  1330.     RgnHandle save_clipRgn;
  1331.     BitMap bm;
  1332.     Handle h;
  1333.     Point pen;
  1334.  
  1335.     r.left = 0;
  1336.     r.right = HEAP_FIELD_LEFT - 3;
  1337.     r.top = App_window->portRect.bottom - 15;
  1338.     r.bottom = App_window->portRect.bottom;
  1339.  
  1340.     if ( what == MBOX_FRAME_AND_CONTENTS ) {
  1341.         set_fore_color_or_pattern( HEADER_BORDER_COLOR );
  1342.         EraseRect( &r );
  1343.         MoveTo( r.right, CELL_HEIGHT );
  1344.         LineTo( r.right, r.top - 1 );
  1345.         set_fore_color_or_pattern( BLACK_COLOR );
  1346.  
  1347.         if ( Debugger_installed ) {
  1348.             bm.bounds.right = (bm.bounds.left = 3) + 16;
  1349.             bm.bounds.top = (bm.bounds.bottom = r.bottom - 1) - 12;
  1350.             bm.rowBytes = 2;
  1351.             h = GetResource( 'SICN', MACSBUG_SICN );
  1352.             HLock( h );
  1353.             bm.baseAddr = *h + 8;
  1354.             CopyBits( &bm, &App_window->portBits, &bm.bounds, &bm.bounds,
  1355.                     srcCopy, NULL );
  1356.             HUnlock( h );
  1357.             HPurge( h );
  1358.         }
  1359.     }
  1360.     if ( what == MBOX_CONTENTS || what == MBOX_FRAME_AND_CONTENTS ) {
  1361.         ValidRect( &r );
  1362.         save_clipRgn = NewRgn();
  1363.         GetClip( save_clipRgn );
  1364.         InsetRect( &r, 2, 2 );
  1365.         ClipRect( &r );
  1366.  
  1367.         MoveTo( 24, r.bottom - 2 );
  1368.         TextMode( srcCopy );
  1369.         TextFont( monaco );
  1370.         DrawString( (StringPtr) mbox_text );
  1371.         TextMode( srcOr );
  1372.         TextFont( geneva );
  1373.         ++r.top;
  1374.         GetPen( &pen );
  1375.         r.left = pen.h;
  1376.         EraseRect( &r );
  1377.  
  1378.         SetClip( save_clipRgn );
  1379.         DisposeRgn( save_clipRgn );
  1380.     }
  1381.     else if ( what == MBOX_ERASE ) {
  1382.         EraseRect( &r );
  1383.         InvalRect( &r );
  1384.     }
  1385. }
  1386.  
  1387.  
  1388. void clip_with_controls( void )
  1389. {
  1390.     ClipRect( &App_window->portRect );
  1391. }
  1392.  
  1393.  
  1394. void clip_without_controls( void )
  1395. {
  1396.     Rect r;
  1397.  
  1398.     r = App_window->portRect;
  1399.     r.right -= 15;
  1400.     r.bottom -= 15;
  1401.     ClipRect( &r );
  1402. }
  1403.  
  1404.  
  1405. void size_controls( void )
  1406. {
  1407.     register int16 top, left, bottom, right;
  1408.  
  1409.     reset_horiz_scroll();
  1410.     reset_vert_scroll();
  1411.  
  1412.     left = App_window->portRect.right - 15;
  1413.     right = App_window->portRect.right + 1;
  1414.     top = CELL_HEIGHT - 1;
  1415.     bottom = App_window->portRect.bottom - 14;
  1416.     HideControl( vert_scroll );
  1417.     MoveControl( vert_scroll, left, top );
  1418.     SizeControl( vert_scroll, right - left, bottom - top );
  1419.     ShowControl( vert_scroll );
  1420.  
  1421.     left = HEAP_FIELD_LEFT - 3;
  1422.     right = App_window->portRect.right - 14;
  1423.     top = App_window->portRect.bottom - 15;
  1424.     bottom = App_window->portRect.bottom + 1;
  1425.     HideControl( horiz_scroll );
  1426.     MoveControl( horiz_scroll, left, top );
  1427.     SizeControl( horiz_scroll, right - left, bottom - top );
  1428.     ShowControl( horiz_scroll );
  1429. }
  1430.  
  1431.  
  1432. void reset_vert_scroll( void )
  1433. {
  1434.     register int16 ti;
  1435.     register int16 old_num_display_lines, old_value;
  1436.     Rect r;
  1437.  
  1438.     old_num_display_lines = num_display_lines;
  1439.     old_value = GetCtlValue( vert_scroll );
  1440.     ti = App_window->portRect.bottom - 15 - CELL_HEIGHT;
  1441.     partial_display_line = (ti % CELL_HEIGHT) != 0;
  1442.     num_display_lines = ti / CELL_HEIGHT;
  1443.  
  1444.     SetCtlMax( vert_scroll, ( (ti = display_list_elems - num_display_lines) > 0 ? ti : 0 ) );
  1445.  
  1446.     if ( old_value && num_display_lines > old_num_display_lines ) {
  1447.         old_value -= num_display_lines - old_num_display_lines;
  1448.         SetCtlValue( vert_scroll, ( old_value < 0 ? 0 : old_value ) );
  1449.         r = App_window->portRect;
  1450.         r.top += CELL_HEIGHT;
  1451.         r.right -= 15;
  1452.         r.bottom -= 15;
  1453.         InvalRect( &r );
  1454.     }
  1455. }
  1456.  
  1457.  
  1458. void reset_horiz_scroll( void )
  1459. {
  1460.     register int32 t;
  1461.  
  1462.     display_heap_bytes = (int32) (App_window->portRect.right - 15 - HEAP_FIELD_LEFT) *
  1463.             Swatch_prefs.heap_scale;
  1464.     if ( ( t = max_heap_size - display_heap_bytes ) > 0 ) {
  1465.         heap_right_pixels = ( t >> Swatch_prefs.heap_scale_2n ) +
  1466.                 ( (t & (Swatch_prefs.heap_scale-1)) ? 1 : 0 ) + 20;
  1467.         horiz_scroll_scale = heap_right_pixels / 32768L + 1;
  1468.     }
  1469.     else {
  1470.         heap_right_pixels = 0;
  1471.         horiz_scroll_scale = 1;
  1472.     }
  1473.     SetCtlMax( horiz_scroll, heap_right_pixels / horiz_scroll_scale +
  1474.             ( ( heap_right_pixels % horiz_scroll_scale ) ? 1 : 0 ) );
  1475. }
  1476.  
  1477.  
  1478. pascal void vert_scroll_proc( ControlHandle the_control, int16 part )
  1479. {
  1480.     Rect r;
  1481.     register int16 old, new;
  1482.     RgnHandle aRgn;
  1483.  
  1484.     aRgn = NewRgn();
  1485.     r = App_window->portRect;
  1486.     r.right -= 15;
  1487.     r.top = CELL_HEIGHT;
  1488.     r.bottom -= 15;
  1489.     old = GetCtlValue( the_control );
  1490.  
  1491.     if ( part == inUpButton ) {
  1492.         if ( old ) {
  1493.             SetCtlValue( the_control, old - 1 );
  1494.             ScrollRect( &r, 0, CELL_HEIGHT, aRgn );
  1495.             check_sizes( FORCE_UPDATE_FIELDS, 0, 0 );
  1496.         }
  1497.     }
  1498.     else if ( part == inDownButton ) {
  1499.         if ( old < display_list_elems - num_display_lines ) {
  1500.             SetCtlValue( the_control, old + 1 );
  1501.             ScrollRect( &r, 0, -CELL_HEIGHT, aRgn );
  1502.             check_sizes( FORCE_UPDATE_FIELDS | FORCE_UPDATE_BOTTOM_MASK, num_display_lines - 1,
  1503.                     num_display_lines + partial_display_line - 1 );
  1504.         }
  1505.     }
  1506.     else if ( part == inPageUp ) {
  1507.         new = old - ( num_display_lines - 1 );
  1508.         if ( new < 0 )
  1509.             new = 0;
  1510.         if ( new != old ) {
  1511.             SetCtlValue( the_control, new );
  1512.             check_sizes( FORCE_UPDATE_FIELDS, CHECK_ALL_SIZES_START, CHECK_ALL_SIZES_END );
  1513.         }
  1514.     }
  1515.     else if ( part == inPageDown ) {
  1516.         new = old + ( num_display_lines - 1 );
  1517.         if ( new > display_list_elems - num_display_lines )
  1518.             new = display_list_elems - num_display_lines;
  1519.         if ( new != old ) {
  1520.             SetCtlValue( the_control, new );
  1521.             check_sizes( FORCE_UPDATE_FIELDS, CHECK_ALL_SIZES_START, CHECK_ALL_SIZES_END );
  1522.         }
  1523.     }
  1524.     DisposeRgn( aRgn );
  1525. }
  1526.  
  1527.  
  1528. pascal void horiz_scroll_proc( ControlHandle the_control, int16 part )
  1529. {
  1530.     int32 delta, old_heap_offset_pixels;
  1531.  
  1532.     old_heap_offset_pixels = heap_offset_pixels;
  1533.     if ( part == inUpButton )
  1534.         delta = -HORIZ_ARROW_DELTA;
  1535.     else if ( part == inDownButton )
  1536.         delta = HORIZ_ARROW_DELTA;
  1537.     else if ( part == inPageUp )
  1538.         delta = -( (display_heap_bytes >> Swatch_prefs.heap_scale_2n) - HORIZ_ARROW_DELTA );
  1539.     else if ( part == inPageDown )
  1540.         delta = (display_heap_bytes >> Swatch_prefs.heap_scale_2n) - HORIZ_ARROW_DELTA;
  1541.     else
  1542.         return;
  1543.  
  1544.     heap_offset_pixels += delta;
  1545.     if ( heap_offset_pixels < 0 )
  1546.         heap_offset_pixels = 0;
  1547.     else if ( heap_offset_pixels > heap_right_pixels )
  1548.         heap_offset_pixels = heap_right_pixels;
  1549.     
  1550.     if ( heap_offset_pixels != old_heap_offset_pixels ) {
  1551.         SetCtlValue( horiz_scroll, heap_offset_pixels / horiz_scroll_scale );
  1552.         check_sizes( FORCE_UPDATE_HEAP_MASK, CHECK_ALL_SIZES_START, CHECK_ALL_SIZES_END );
  1553.     }
  1554. }
  1555.