home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / TEMPLATE / HP2.C < prev    next >
Text File  |  1993-12-01  |  15KB  |  455 lines

  1. #include <windows.h>
  2. #include <string.h> // strcat & strlen
  3. #include <dos.h>    // FP_OFF macro
  4. #include "hp2.h"
  5.  
  6.  
  7. /* brush colors */
  8. #define BLACK   0x000000L
  9. #define MAGENTA 0xFF00FFL
  10. #define BLUE    0xFF0000L
  11. #define YELLOW  0x00FFFFL
  12. #define RED     0x0000FFL
  13.  
  14. static HBRUSH hbr [7]    ,
  15.               hbrMAGENTA ,
  16.               hbrBLUE    ,
  17.               hbrRED     ,
  18.               hbrYELLOW  ;
  19.  
  20. static HFONT  hfont      ;
  21.  
  22.  
  23. typedef struct tagDEFAULTDATASEGMENT
  24.     {
  25.     HANDLE hinstActive; // instance handle of active app
  26.     HWND   hwndActive,  // window   handle of active app
  27.            hwndClient;  // window we draw bar graph in.
  28.     WORD wSize,         // size (bytes) of Data Segment.
  29.          wStaticData,   // size (bytes) of static data.
  30.          wStackMax,     // size (bytes) of stack size defined in .DEF
  31.          wStackUsed,    // size (bytes) of stack actually used.
  32.          wHeapMoveable, // size (bytes) of heap allocation (moveable).
  33.          wHeapFixed,    // size (bytes) of heap allocation (fixed).
  34.          wHeapFree,     // size (bytes) of free space in heap.
  35.          wOther,        // size (bytes) of remaining allocated space in DS.
  36.          wUnused;       // size (bytes) of heap unused.
  37.     } DEFAULTDATASEGMENT;
  38.  
  39. static DEFAULTDATASEGMENT DDS ;
  40.  
  41.  
  42.  
  43.  
  44. void dds_create (HWND hwndClient)
  45.      {
  46.      HDC hdc = GetDC (hwndClient);
  47.  
  48.  
  49.      //      Create brushes.
  50.      //
  51.      if (GetDeviceCaps (hdc, NUMCOLORS) == 2)
  52.           {
  53.           //   create pattern brushes for monochrome display
  54.           //
  55.           hbrMAGENTA = CreateHatchBrush (HS_DIAGCROSS ,BLACK);
  56.           hbrBLUE    = CreateHatchBrush (HS_BDIAGONAL ,BLACK);
  57.           hbrYELLOW  = CreateHatchBrush (HS_FDIAGONAL ,BLACK);
  58.           hbrRED     = CreateHatchBrush (HS_BDIAGONAL ,BLACK);
  59.           }
  60.      else
  61.           {
  62.           //   create color brushes for color display
  63.           //
  64.           hbrMAGENTA = CreateSolidBrush (MAGENTA);
  65.           hbrBLUE    = CreateSolidBrush (BLUE)   ;
  66.           hbrYELLOW  = CreateSolidBrush (YELLOW) ;
  67.           hbrRED     = CreateSolidBrush (RED)    ;
  68.           }
  69.  
  70.      hbr [0] = (HBRUSH)GetStockObject (BLACK_BRUSH) ;
  71.      hbr [1] = (HBRUSH)GetStockObject (LTGRAY_BRUSH);
  72.      hbr [2] = hbrMAGENTA ;
  73.      hbr [3] = hbrBLUE    ;
  74.      hbr [4] = hbrYELLOW  ;
  75.      hbr [5] = hbrRED     ;
  76.      hbr [6] = (HBRUSH)GetStockObject (WHITE_BRUSH);
  77.  
  78.      //   Create nice display font
  79.      //
  80.      {
  81.      static LOGFONT lf;
  82.      lf.lfHeight  =   8;
  83.      lf.lfWeight  = 700;
  84.      lf.lfCharSet = ANSI_CHARSET ;
  85.      lf.lfQuality = PROOF_QUALITY;
  86.  
  87.      lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
  88.  
  89.      hfont = CreateFontIndirect (&lf);
  90.      }
  91.  
  92.      ReleaseDC (hwndClient, hdc);
  93.      DDS.hwndClient = hwndClient;
  94.      }
  95.  
  96.  
  97.  
  98. void dds_destroy (void)
  99.      {
  100.      DeleteObject (hbrBLUE)   ;
  101.      DeleteObject (hbrMAGENTA);
  102.      DeleteObject (hbrYELLOW) ;
  103.      DeleteObject (hbrRED)    ;
  104.  
  105.      DeleteObject (hfont)     ;
  106.      }
  107.  
  108.  
  109.  
  110. void dds_paint ()
  111.      {
  112.      RECT rcClient;
  113.      long lTextExt;
  114.      WORD wTextWidth;
  115.      PAINTSTRUCT ps;
  116.  
  117.      BeginPaint (DDS.hwndClient, &ps);
  118.  
  119.      SelectObject (ps.hdc, hfont)    ;
  120.  
  121.      SetMapMode   (ps.hdc, MM_ANISOTROPIC);
  122.      SetWindowOrg (ps.hdc,    0,   0)     ;
  123.      SetWindowExt (ps.hdc, 1300, 130)     ;
  124.  
  125.      /*
  126.       *  Set viewport to be the entire client area.
  127.       *
  128.       */
  129.      GetClientRect (DDS.hwndClient, &rcClient);
  130.      SetViewportOrg (ps.hdc, 0, 0);
  131.      SetViewportExt (ps.hdc, rcClient.right, rcClient.bottom);
  132.  
  133.      /*
  134.       *  Draw bar : StaticData = BLACK
  135.       *             Stack      = LTGRAY
  136.       *             Fixed      = MAGENTA
  137.       *             Moveable   = YELLOW
  138.       *             Free       = BLUE
  139.       *             Other      = RED
  140.       *             Unused     = WHITE
  141.       *
  142.       */
  143.      {
  144.      int    xBar[8]   ,
  145.             yBar[2]   ,
  146.             i         ,
  147.             nMinWidth ;
  148.  
  149.      POINT  pt[2];
  150.  
  151.      double dPercentStaticData ,
  152.             dPercentStackMax   ,
  153.             dPercentFixed      ,
  154.             dPercentMoveable   ,
  155.             dPercentFree       ,
  156.             dPercentOther      ,
  157.             dPercentUnused     ,
  158.             dDiv = 0xFFFF/1000.; // makes bar 1000 logical units wide
  159.                                  //   eg, each 1% is represented by
  160.                                  //   10 logical units.
  161.  
  162.      dPercentStaticData = (double)DDS.wStaticData   /dDiv ;
  163.      dPercentStackMax   = (double)DDS.wStackMax     /dDiv ;
  164.      dPercentFixed      = (double)DDS.wHeapFixed    /dDiv ;
  165.      dPercentMoveable   = (double)DDS.wHeapMoveable /dDiv ;
  166.      dPercentFree       = (double)DDS.wHeapFree     /dDiv ;
  167.      dPercentOther      = (double)DDS.wOther        /dDiv ;
  168.      dPercentUnused     = (double)DDS.wUnused       /dDiv ;
  169.  
  170.      //   Compute a logical width that corresponds to a 2 pixel width.
  171.      //   This will be used as a minimum width for any bar section, and will
  172.      //   ensure that a section is always displayed at least 1 pixel wide.
  173.      //   (FillRect will output 1 pixel less than the rect's width)
  174.      //
  175.      pt[0].x = 0 ;
  176.      pt[0].y = 0 ;
  177.      pt[1].x = 1 ;
  178.      pt[1].y = 0 ;
  179.      DPtoLP (ps.hdc, &pt[0], 2)    ;
  180.      nMinWidth = max ((pt[1].x - pt[0].x), 1) ;
  181.  
  182.      xBar[0]  = 50;
  183.      xBar[1]  = xBar[0] + max ( (int)dPercentStaticData, nMinWidth);
  184.      xBar[2]  = xBar[1] + max ( (int)dPercentStackMax  , nMinWidth);
  185.      xBar[3]  = xBar[2] + max ( (int)dPercentFixed     , nMinWidth);
  186.      xBar[4]  = xBar[3] + max ( (int)dPercentMoveable  , nMinWidth);
  187.      xBar[5]  = xBar[4] + max ( (int)dPercentFree      , nMinWidth);
  188.      xBar[6]  = xBar[5] + max ( (int)dPercentOther     , nMinWidth);
  189.      xBar[7]  = xBar[6] + max ( (int)dPercentUnused    , nMinWidth);
  190.  
  191.      yBar[0]  = 20;
  192.      yBar[1]  = 30;
  193.  
  194.      /* Active window's Caption */
  195.      if (IsWindow (DDS.hwndActive))
  196.           {
  197.           char szText    [65],
  198.                szCaption [40];
  199.           BOOL bTruncate = (GetWindowTextLength (DDS.hwndActive) > 39);
  200.           int  cch;
  201.  
  202.           cch = GetWindowText (DDS.hwndActive, szCaption, 39);
  203.           szCaption [cch] = '\0';
  204.  
  205.           if (bTruncate) strcpy (&szCaption [36], "...");
  206.  
  207.           wsprintf (szText, "%.39s   [hInstance = %4.4X]", (LPSTR) szCaption,
  208.                                                             DDS.hinstActive);
  209.           SetTextAlign (ps.hdc, TA_BOTTOM);
  210.           TextOut      (ps.hdc, 250, 18, szText, strlen (szText) );
  211.           SetTextAlign (ps.hdc, TA_TOP);
  212.           }
  213.  
  214.      /* label at left end */
  215.      lTextExt   = GetTextExtent (ps.hdc,"0", 1);
  216.      wTextWidth = LOWORD (lTextExt);
  217.      TextOut (ps.hdc, (xBar[0]-wTextWidth-10), yBar[0] + 2, "0", strlen("0") );
  218.  
  219.      /* label at right end */
  220.      TextOut (ps.hdc, (xBar[7]+10), yBar[0] + 2, "64K", 3);
  221.  
  222.      for (i=0; i<=6; i++)
  223.          {
  224.          POINT ptA, ptB, ptC, ptD;
  225.          RECT rect;
  226.          char sz [40];
  227.  
  228.          ptA.x = (xBar[i+1] + xBar[i])/2 ;
  229.          if ((xBar[i+1] - xBar[i]) <= (3*nMinWidth)/2 ) ptA.x = xBar[i] ;
  230.  
  231.          ptA.y = yBar[1]      ;
  232.          ptB.x = ptA.x        ;
  233.          ptB.y = 120 - (10*i) ;
  234.          ptC.x = ptB.x + 20   ;
  235.          ptC.y = ptB.y        ;
  236.          ptD.x = ptC.x + 10   ;
  237.          ptD.y = ptC.y - 4    ;
  238.  
  239.          rect.left   = xBar [i]  ;
  240.          rect.top    = yBar [0]  ;
  241.          rect.right  = xBar [i+1];
  242.          rect.bottom = yBar [1]  ;
  243.          FillRect (ps.hdc, &rect, hbr[i]);
  244.  
  245.          MoveTo (ps.hdc, ptA.x, ptA.y);
  246.          LineTo (ps.hdc, ptB.x, ptB.y);
  247.          LineTo (ps.hdc, ptC.x, ptC.y);
  248.  
  249.          switch (i)
  250.            {
  251.            case 0: wsprintf (sz, "static data (%u)",   DDS.wStaticData);  break;
  252.            case 1: wsprintf (sz, "stack allocated (%u), used (%u)",
  253.                                           DDS.wStackMax, DDS.wStackUsed); break;
  254.            case 2: wsprintf (sz, "fixed heap (%u)",    DDS.wHeapFixed);   break;
  255.            case 3: wsprintf (sz, "moveable heap (%u)", DDS.wHeapMoveable);break;
  256.            case 4: wsprintf (sz, "free heap (%u)",     DDS.wHeapFree);    break;
  257.            case 5: wsprintf (sz, "other (%u)",         DDS.wOther);       break;
  258.            case 6: wsprintf (sz, "room to grow (%u)",  DDS.wUnused);      break;
  259.            }
  260.  
  261.          TextOut (ps.hdc, ptD.x, ptD.y, sz, strlen(sz));
  262.          }
  263.  
  264.      SelectObject (ps.hdc, (HBRUSH)GetStockObject (NULL_BRUSH));
  265.      Rectangle (ps.hdc, xBar[0], yBar[0], xBar[7], yBar[1]);
  266.      }
  267.  
  268.      EndPaint  (DDS.hwndClient, &ps);
  269.      }
  270.  
  271.  
  272.  
  273.  
  274.  
  275. void dds_walk ()
  276.      {
  277.      static DEFAULTDATASEGMENT OldDDS;
  278.  
  279.      WORD  wRecordSize,          // size in bytes of heap record.
  280.            wStatus;              // type of heap record.
  281.  
  282.      LPSTR lpInstance,           // far pointer to Default Data Segment.
  283.            lpHeapRecord,         // far pointer to heap record.
  284.            lpNextHeapRecord;     // far pointer to next heap record.
  285.  
  286.      #define PREV_POINTER (*(WORD FAR*) lpHeapRecord)     // Backward "pointer"
  287.      #define NEXT_POINTER (*(WORD FAR*)(lpHeapRecord+2))  // Forward "pointer"
  288.  
  289.      #define PSTACKBOTTOM (*(WORD FAR*)(lpInstance+14))
  290.      #define PSTACKMIN    (*(WORD FAR*)(lpInstance+12))
  291.      #define PSTACKTOP    (*(WORD FAR*)(lpInstance+10))
  292.      #define PLOCALHEAP   (*(WORD FAR*)(lpInstance+ 6))
  293.  
  294.  
  295.  
  296.      //   First, initialize the data segment values.
  297.      //
  298.      //
  299.      DDS.wSize         = 0;
  300.      DDS.wStaticData   = 0;
  301.      DDS.wStackMax     = 0;
  302.      DDS.wStackUsed    = 0;
  303.      DDS.wHeapMoveable = 0;
  304.      DDS.wHeapFixed    = 0;
  305.      DDS.wHeapFree     = 0;
  306.      DDS.wOther        = 0;
  307.      DDS.wUnused       = 0;
  308.  
  309.  
  310.      //   Now, get the window that has the focus.
  311.      //
  312.      //
  313.      DDS.hwndActive = GetActiveWindow ();
  314.  
  315.  
  316.      //   Is it a valid window?
  317.      //
  318.      //
  319.      if ( !IsWindow (DDS.hwndActive) )  return;
  320.  
  321.  
  322.      //   If this is a different window than before,
  323.      //   get a new instance handle.
  324.      //
  325.      //
  326.      if (DDS.hwndActive != OldDDS.hwndActive)
  327.           {
  328.           DDS.hinstActive = (HANDLE) GetWindowWord (DDS.hwndActive,
  329.                                                     GWW_HINSTANCE);
  330.           if (!DDS.hinstActive) return;
  331.           }
  332.  
  333.  
  334.      //    Lock down the Data Segment
  335.      //
  336.      //
  337.      if ( !(lpInstance = GlobalLock (DDS.hinstActive))) return;
  338.  
  339.      /*
  340.       *  The Data Segment is a global memory object - created by WINDOWS
  341.       *  with a GlobalAlloc. It's comprised of 4 components: header,
  342.       *  Static, stack, and local heap. All 4 components are offset
  343.       *  into the segment, with the header at DS:0000.
  344.       *
  345.       *
  346.       *  The header occupies the first 16 bytes of a Default Data Segment.
  347.       *  Within the Header area are 3 pointers to the stack:
  348.       *
  349.       *  pStackBottom - (highest physical address) beginning of stack.
  350.       *  pStackMin    - High-Water mark of actual stack use.
  351.       *  pStackTop    - (lowest physical address) end of stack.
  352.       *
  353.       *  Remember, the stack grows "down" (higher to lower address), so
  354.       *  to compute the stack sizes, we use these equations:
  355.       *
  356.       *   wStackMax  = pStackBottom - pStackTop ;
  357.       *   wStackUsed = pStackBottom - pStackMin ;
  358.       *
  359.       *
  360.       */
  361.      DDS.wStackMax   = PSTACKBOTTOM - PSTACKTOP ;
  362.      DDS.wStackUsed  = PSTACKBOTTOM - PSTACKMIN ;
  363.      DDS.wStaticData = PSTACKTOP ;
  364.  
  365.      /*
  366.       *   First test for a heap. (It's possible there isn't one.)
  367.       *
  368.       */
  369.      if (PLOCALHEAP == 0)
  370.         {
  371.         GlobalUnlock (DDS.hinstActive);
  372.         return;
  373.         }
  374.  
  375.      /*
  376.       *  The heap begins where the
  377.       *  stack ends. The offset that represents the
  378.       *  beginning of the heap is stored in the header area, 6 bytes from
  379.       *  DS:0000. Actually, the heap begins 4 bytes before this offset.
  380.       *
  381.       *  Now we'll get a far pointer (lpHeapRecord) to the 1st record in the
  382.       *  heap.
  383.       */
  384.      lpHeapRecord = lpInstance + PLOCALHEAP - 4;
  385.  
  386.  
  387.      /*
  388.       *  Traverse the local heap. The heap is implemented as a doubly-linked
  389.       *  list. The 1st WORD is a backward "pointer" (ie, offset) to the
  390.       *  previous record. The 2nd WORD is the forward pointer to the next
  391.       *  record. When the forward pointer points to itself we are done.
  392.       *
  393.       */
  394.      DDS.wSize = GlobalSize (DDS.hinstActive);
  395.  
  396.      while (FP_OFF(lpHeapRecord) < DDS.wSize)
  397.           {
  398.           lpNextHeapRecord = (lpInstance + NEXT_POINTER);
  399.           if (lpNextHeapRecord == lpHeapRecord) break;
  400.  
  401.           wRecordSize = lpNextHeapRecord - lpHeapRecord; //includes ptr overhead
  402.           wStatus     = (PREV_POINTER & 0x0003);
  403.  
  404.      switch (wStatus)
  405.           {
  406.           case 0: DDS.wHeapFree     += wRecordSize; break;
  407.           case 1: DDS.wHeapFixed    += wRecordSize; break;
  408.  
  409.           case 2:
  410.           case 3: DDS.wHeapMoveable += wRecordSize; break;
  411.           }
  412.  
  413.      lpHeapRecord = lpNextHeapRecord;
  414.      }
  415.  
  416.      /*
  417.       *  At this point, heap traversal is done.
  418.       *  However, the heap can grow until the size of DS is 64K (0xFFFF).
  419.       *  Determine how many additional bytes the heap can grow.
  420.       *
  421.       */
  422.      DDS.wUnused = 0xFFFF   - DDS.wSize;
  423.  
  424.  
  425.      /*
  426.       *  Anything else we didn't account for?
  427.       *
  428.       */
  429.      DDS.wOther  = DDS.wSize - DDS.wStaticData
  430.                              - DDS.wStackMax
  431.                              - DDS.wHeapFixed
  432.                              - DDS.wHeapFree
  433.                              - DDS.wHeapMoveable ;
  434.  
  435.      GlobalUnlock (DDS.hinstActive);
  436.  
  437.  
  438.      //   If anything has changed since last walk, update client window.
  439.      //
  440.  
  441.      if (DDS.hwndActive    != OldDDS.hwndActive    ||
  442.          DDS.wHeapFree     != OldDDS.wHeapFree     ||
  443.          DDS.wHeapFixed    != OldDDS.wHeapFixed    ||
  444.          DDS.wHeapMoveable != OldDDS.wHeapMoveable ||
  445.          DDS.wOther        != OldDDS.wOther        ||
  446.          DDS.wSize         != OldDDS.wSize         ||
  447.          DDS.wStackUsed    != OldDDS.wStackUsed)
  448.              {
  449.              InvalidateRect (DDS.hwndClient, NULL, TRUE);
  450.              UpdateWindow   (DDS.hwndClient);
  451.  
  452.              OldDDS = DDS;
  453.              }
  454.      }
  455.