home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
- #include <string.h> // strcat & strlen
- #include <dos.h> // FP_OFF macro
- #include "hp2.h"
-
-
- /* brush colors */
- #define BLACK 0x000000L
- #define MAGENTA 0xFF00FFL
- #define BLUE 0xFF0000L
- #define YELLOW 0x00FFFFL
- #define RED 0x0000FFL
-
- static HBRUSH hbr [7] ,
- hbrMAGENTA ,
- hbrBLUE ,
- hbrRED ,
- hbrYELLOW ;
-
- static HFONT hfont ;
-
-
- typedef struct tagDEFAULTDATASEGMENT
- {
- HANDLE hinstActive; // instance handle of active app
- HWND hwndActive, // window handle of active app
- hwndClient; // window we draw bar graph in.
- WORD wSize, // size (bytes) of Data Segment.
- wStaticData, // size (bytes) of static data.
- wStackMax, // size (bytes) of stack size defined in .DEF
- wStackUsed, // size (bytes) of stack actually used.
- wHeapMoveable, // size (bytes) of heap allocation (moveable).
- wHeapFixed, // size (bytes) of heap allocation (fixed).
- wHeapFree, // size (bytes) of free space in heap.
- wOther, // size (bytes) of remaining allocated space in DS.
- wUnused; // size (bytes) of heap unused.
- } DEFAULTDATASEGMENT;
-
- static DEFAULTDATASEGMENT DDS ;
-
-
-
-
- void dds_create (HWND hwndClient)
- {
- HDC hdc = GetDC (hwndClient);
-
-
- // Create brushes.
- //
- if (GetDeviceCaps (hdc, NUMCOLORS) == 2)
- {
- // create pattern brushes for monochrome display
- //
- hbrMAGENTA = CreateHatchBrush (HS_DIAGCROSS ,BLACK);
- hbrBLUE = CreateHatchBrush (HS_BDIAGONAL ,BLACK);
- hbrYELLOW = CreateHatchBrush (HS_FDIAGONAL ,BLACK);
- hbrRED = CreateHatchBrush (HS_BDIAGONAL ,BLACK);
- }
- else
- {
- // create color brushes for color display
- //
- hbrMAGENTA = CreateSolidBrush (MAGENTA);
- hbrBLUE = CreateSolidBrush (BLUE) ;
- hbrYELLOW = CreateSolidBrush (YELLOW) ;
- hbrRED = CreateSolidBrush (RED) ;
- }
-
- hbr [0] = (HBRUSH)GetStockObject (BLACK_BRUSH) ;
- hbr [1] = (HBRUSH)GetStockObject (LTGRAY_BRUSH);
- hbr [2] = hbrMAGENTA ;
- hbr [3] = hbrBLUE ;
- hbr [4] = hbrYELLOW ;
- hbr [5] = hbrRED ;
- hbr [6] = (HBRUSH)GetStockObject (WHITE_BRUSH);
-
- // Create nice display font
- //
- {
- static LOGFONT lf;
- lf.lfHeight = 8;
- lf.lfWeight = 700;
- lf.lfCharSet = ANSI_CHARSET ;
- lf.lfQuality = PROOF_QUALITY;
-
- lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
-
- hfont = CreateFontIndirect (&lf);
- }
-
- ReleaseDC (hwndClient, hdc);
- DDS.hwndClient = hwndClient;
- }
-
-
-
- void dds_destroy (void)
- {
- DeleteObject (hbrBLUE) ;
- DeleteObject (hbrMAGENTA);
- DeleteObject (hbrYELLOW) ;
- DeleteObject (hbrRED) ;
-
- DeleteObject (hfont) ;
- }
-
-
-
- void dds_paint ()
- {
- RECT rcClient;
- long lTextExt;
- WORD wTextWidth;
- PAINTSTRUCT ps;
-
- BeginPaint (DDS.hwndClient, &ps);
-
- SelectObject (ps.hdc, hfont) ;
-
- SetMapMode (ps.hdc, MM_ANISOTROPIC);
- SetWindowOrg (ps.hdc, 0, 0) ;
- SetWindowExt (ps.hdc, 1300, 130) ;
-
- /*
- * Set viewport to be the entire client area.
- *
- */
- GetClientRect (DDS.hwndClient, &rcClient);
- SetViewportOrg (ps.hdc, 0, 0);
- SetViewportExt (ps.hdc, rcClient.right, rcClient.bottom);
-
- /*
- * Draw bar : StaticData = BLACK
- * Stack = LTGRAY
- * Fixed = MAGENTA
- * Moveable = YELLOW
- * Free = BLUE
- * Other = RED
- * Unused = WHITE
- *
- */
- {
- int xBar[8] ,
- yBar[2] ,
- i ,
- nMinWidth ;
-
- POINT pt[2];
-
- double dPercentStaticData ,
- dPercentStackMax ,
- dPercentFixed ,
- dPercentMoveable ,
- dPercentFree ,
- dPercentOther ,
- dPercentUnused ,
- dDiv = 0xFFFF/1000.; // makes bar 1000 logical units wide
- // eg, each 1% is represented by
- // 10 logical units.
-
- dPercentStaticData = (double)DDS.wStaticData /dDiv ;
- dPercentStackMax = (double)DDS.wStackMax /dDiv ;
- dPercentFixed = (double)DDS.wHeapFixed /dDiv ;
- dPercentMoveable = (double)DDS.wHeapMoveable /dDiv ;
- dPercentFree = (double)DDS.wHeapFree /dDiv ;
- dPercentOther = (double)DDS.wOther /dDiv ;
- dPercentUnused = (double)DDS.wUnused /dDiv ;
-
- // Compute a logical width that corresponds to a 2 pixel width.
- // This will be used as a minimum width for any bar section, and will
- // ensure that a section is always displayed at least 1 pixel wide.
- // (FillRect will output 1 pixel less than the rect's width)
- //
- pt[0].x = 0 ;
- pt[0].y = 0 ;
- pt[1].x = 1 ;
- pt[1].y = 0 ;
- DPtoLP (ps.hdc, &pt[0], 2) ;
- nMinWidth = max ((pt[1].x - pt[0].x), 1) ;
-
- xBar[0] = 50;
- xBar[1] = xBar[0] + max ( (int)dPercentStaticData, nMinWidth);
- xBar[2] = xBar[1] + max ( (int)dPercentStackMax , nMinWidth);
- xBar[3] = xBar[2] + max ( (int)dPercentFixed , nMinWidth);
- xBar[4] = xBar[3] + max ( (int)dPercentMoveable , nMinWidth);
- xBar[5] = xBar[4] + max ( (int)dPercentFree , nMinWidth);
- xBar[6] = xBar[5] + max ( (int)dPercentOther , nMinWidth);
- xBar[7] = xBar[6] + max ( (int)dPercentUnused , nMinWidth);
-
- yBar[0] = 20;
- yBar[1] = 30;
-
- /* Active window's Caption */
- if (IsWindow (DDS.hwndActive))
- {
- char szText [65],
- szCaption [40];
- BOOL bTruncate = (GetWindowTextLength (DDS.hwndActive) > 39);
- int cch;
-
- cch = GetWindowText (DDS.hwndActive, szCaption, 39);
- szCaption [cch] = '\0';
-
- if (bTruncate) strcpy (&szCaption [36], "...");
-
- wsprintf (szText, "%.39s [hInstance = %4.4X]", (LPSTR) szCaption,
- DDS.hinstActive);
- SetTextAlign (ps.hdc, TA_BOTTOM);
- TextOut (ps.hdc, 250, 18, szText, strlen (szText) );
- SetTextAlign (ps.hdc, TA_TOP);
- }
-
- /* label at left end */
- lTextExt = GetTextExtent (ps.hdc,"0", 1);
- wTextWidth = LOWORD (lTextExt);
- TextOut (ps.hdc, (xBar[0]-wTextWidth-10), yBar[0] + 2, "0", strlen("0") );
-
- /* label at right end */
- TextOut (ps.hdc, (xBar[7]+10), yBar[0] + 2, "64K", 3);
-
- for (i=0; i<=6; i++)
- {
- POINT ptA, ptB, ptC, ptD;
- RECT rect;
- char sz [40];
-
- ptA.x = (xBar[i+1] + xBar[i])/2 ;
- if ((xBar[i+1] - xBar[i]) <= (3*nMinWidth)/2 ) ptA.x = xBar[i] ;
-
- ptA.y = yBar[1] ;
- ptB.x = ptA.x ;
- ptB.y = 120 - (10*i) ;
- ptC.x = ptB.x + 20 ;
- ptC.y = ptB.y ;
- ptD.x = ptC.x + 10 ;
- ptD.y = ptC.y - 4 ;
-
- rect.left = xBar [i] ;
- rect.top = yBar [0] ;
- rect.right = xBar [i+1];
- rect.bottom = yBar [1] ;
- FillRect (ps.hdc, &rect, hbr[i]);
-
- MoveTo (ps.hdc, ptA.x, ptA.y);
- LineTo (ps.hdc, ptB.x, ptB.y);
- LineTo (ps.hdc, ptC.x, ptC.y);
-
- switch (i)
- {
- case 0: wsprintf (sz, "static data (%u)", DDS.wStaticData); break;
- case 1: wsprintf (sz, "stack allocated (%u), used (%u)",
- DDS.wStackMax, DDS.wStackUsed); break;
- case 2: wsprintf (sz, "fixed heap (%u)", DDS.wHeapFixed); break;
- case 3: wsprintf (sz, "moveable heap (%u)", DDS.wHeapMoveable);break;
- case 4: wsprintf (sz, "free heap (%u)", DDS.wHeapFree); break;
- case 5: wsprintf (sz, "other (%u)", DDS.wOther); break;
- case 6: wsprintf (sz, "room to grow (%u)", DDS.wUnused); break;
- }
-
- TextOut (ps.hdc, ptD.x, ptD.y, sz, strlen(sz));
- }
-
- SelectObject (ps.hdc, (HBRUSH)GetStockObject (NULL_BRUSH));
- Rectangle (ps.hdc, xBar[0], yBar[0], xBar[7], yBar[1]);
- }
-
- EndPaint (DDS.hwndClient, &ps);
- }
-
-
-
-
-
- void dds_walk ()
- {
- static DEFAULTDATASEGMENT OldDDS;
-
- WORD wRecordSize, // size in bytes of heap record.
- wStatus; // type of heap record.
-
- LPSTR lpInstance, // far pointer to Default Data Segment.
- lpHeapRecord, // far pointer to heap record.
- lpNextHeapRecord; // far pointer to next heap record.
-
- #define PREV_POINTER (*(WORD FAR*) lpHeapRecord) // Backward "pointer"
- #define NEXT_POINTER (*(WORD FAR*)(lpHeapRecord+2)) // Forward "pointer"
-
- #define PSTACKBOTTOM (*(WORD FAR*)(lpInstance+14))
- #define PSTACKMIN (*(WORD FAR*)(lpInstance+12))
- #define PSTACKTOP (*(WORD FAR*)(lpInstance+10))
- #define PLOCALHEAP (*(WORD FAR*)(lpInstance+ 6))
-
-
-
- // First, initialize the data segment values.
- //
- //
- DDS.wSize = 0;
- DDS.wStaticData = 0;
- DDS.wStackMax = 0;
- DDS.wStackUsed = 0;
- DDS.wHeapMoveable = 0;
- DDS.wHeapFixed = 0;
- DDS.wHeapFree = 0;
- DDS.wOther = 0;
- DDS.wUnused = 0;
-
-
- // Now, get the window that has the focus.
- //
- //
- DDS.hwndActive = GetActiveWindow ();
-
-
- // Is it a valid window?
- //
- //
- if ( !IsWindow (DDS.hwndActive) ) return;
-
-
- // If this is a different window than before,
- // get a new instance handle.
- //
- //
- if (DDS.hwndActive != OldDDS.hwndActive)
- {
- DDS.hinstActive = (HANDLE) GetWindowWord (DDS.hwndActive,
- GWW_HINSTANCE);
- if (!DDS.hinstActive) return;
- }
-
-
- // Lock down the Data Segment
- //
- //
- if ( !(lpInstance = GlobalLock (DDS.hinstActive))) return;
-
- /*
- * The Data Segment is a global memory object - created by WINDOWS
- * with a GlobalAlloc. It's comprised of 4 components: header,
- * Static, stack, and local heap. All 4 components are offset
- * into the segment, with the header at DS:0000.
- *
- *
- * The header occupies the first 16 bytes of a Default Data Segment.
- * Within the Header area are 3 pointers to the stack:
- *
- * pStackBottom - (highest physical address) beginning of stack.
- * pStackMin - High-Water mark of actual stack use.
- * pStackTop - (lowest physical address) end of stack.
- *
- * Remember, the stack grows "down" (higher to lower address), so
- * to compute the stack sizes, we use these equations:
- *
- * wStackMax = pStackBottom - pStackTop ;
- * wStackUsed = pStackBottom - pStackMin ;
- *
- *
- */
- DDS.wStackMax = PSTACKBOTTOM - PSTACKTOP ;
- DDS.wStackUsed = PSTACKBOTTOM - PSTACKMIN ;
- DDS.wStaticData = PSTACKTOP ;
-
- /*
- * First test for a heap. (It's possible there isn't one.)
- *
- */
- if (PLOCALHEAP == 0)
- {
- GlobalUnlock (DDS.hinstActive);
- return;
- }
-
- /*
- * The heap begins where the
- * stack ends. The offset that represents the
- * beginning of the heap is stored in the header area, 6 bytes from
- * DS:0000. Actually, the heap begins 4 bytes before this offset.
- *
- * Now we'll get a far pointer (lpHeapRecord) to the 1st record in the
- * heap.
- */
- lpHeapRecord = lpInstance + PLOCALHEAP - 4;
-
-
- /*
- * Traverse the local heap. The heap is implemented as a doubly-linked
- * list. The 1st WORD is a backward "pointer" (ie, offset) to the
- * previous record. The 2nd WORD is the forward pointer to the next
- * record. When the forward pointer points to itself we are done.
- *
- */
- DDS.wSize = GlobalSize (DDS.hinstActive);
-
- while (FP_OFF(lpHeapRecord) < DDS.wSize)
- {
- lpNextHeapRecord = (lpInstance + NEXT_POINTER);
- if (lpNextHeapRecord == lpHeapRecord) break;
-
- wRecordSize = lpNextHeapRecord - lpHeapRecord; //includes ptr overhead
- wStatus = (PREV_POINTER & 0x0003);
-
- switch (wStatus)
- {
- case 0: DDS.wHeapFree += wRecordSize; break;
- case 1: DDS.wHeapFixed += wRecordSize; break;
-
- case 2:
- case 3: DDS.wHeapMoveable += wRecordSize; break;
- }
-
- lpHeapRecord = lpNextHeapRecord;
- }
-
- /*
- * At this point, heap traversal is done.
- * However, the heap can grow until the size of DS is 64K (0xFFFF).
- * Determine how many additional bytes the heap can grow.
- *
- */
- DDS.wUnused = 0xFFFF - DDS.wSize;
-
-
- /*
- * Anything else we didn't account for?
- *
- */
- DDS.wOther = DDS.wSize - DDS.wStaticData
- - DDS.wStackMax
- - DDS.wHeapFixed
- - DDS.wHeapFree
- - DDS.wHeapMoveable ;
-
- GlobalUnlock (DDS.hinstActive);
-
-
- // If anything has changed since last walk, update client window.
- //
-
- if (DDS.hwndActive != OldDDS.hwndActive ||
- DDS.wHeapFree != OldDDS.wHeapFree ||
- DDS.wHeapFixed != OldDDS.wHeapFixed ||
- DDS.wHeapMoveable != OldDDS.wHeapMoveable ||
- DDS.wOther != OldDDS.wOther ||
- DDS.wSize != OldDDS.wSize ||
- DDS.wStackUsed != OldDDS.wStackUsed)
- {
- InvalidateRect (DDS.hwndClient, NULL, TRUE);
- UpdateWindow (DDS.hwndClient);
-
- OldDDS = DDS;
- }
- }