|
|
/*****************************************************************************
* * RptFct.c - This file contains support routines for the Report view. * They are moved here because Report.c is getting too big. * * Microsoft Confidential * Copyright (c) 1992-1993 Microsoft Corporation * * Author - * * Hon-Wah Chan * ****************************************************************************/
#include "perfmon.h"
#include <stdio.h> // for sprintf
#include "report.h" // Exported declarations for this file
#include "line.h" // for LineAppend
#include "pmemory.h" // for MemoryXXX (mallloc-type) routines
#include "system.h" // for SystemGet
#include "utils.h"
#include "perfmops.h" // for BuildValueListForSystems
// extern defined in Report.c
extern TCHAR szSystemFormat [] ; extern TCHAR szObjectFormat [] ;
#define szValuePlaceholder TEXT("-999999999.999")
#define szLargeValueFormat TEXT("%12.0f")
#define eStatusLargeValueMax ((FLOAT) 999999999.0)
#define szValueFormat TEXT("%12.3f")
//========================
// Local routines prototypes
//========================
void ColumnRemoveOne (PREPORT pReport, POBJECTGROUP pObjectGroup, int iColumnNumber) ;
BOOL CounterGroupRemove (PCOUNTERGROUP *ppCounterGroupFirst, PCOUNTERGROUP pCounterGroupRemove) ;
BOOL ObjectGroupRemove (POBJECTGROUP *ppObjectGroupFirst, POBJECTGROUP pObjectGroupRemove) ;
BOOL SystemGroupRemove (PSYSTEMGROUP *ppSystemGroupFirst, PSYSTEMGROUP pSystemGroupRemove) ;
PCOUNTERGROUP GetNextCounter (PSYSTEMGROUP pSystemGroup, POBJECTGROUP pObjectGroup, PCOUNTERGROUP pCounterGroup) ;
BOOL ReportLineRemove (PREPORT pReport, PLINE pLineRemove) { PLINE pLine ;
if (pReport->pLineFirst == pLineRemove) { pReport->pLineFirst = (pReport->pLineFirst)->pLineNext ; return (TRUE) ; }
for (pLine = pReport->pLineFirst ; pLine->pLineNext ; pLine = pLine->pLineNext) { // for
if (pLine->pLineNext == pLineRemove) { pLine->pLineNext = pLineRemove->pLineNext ; if (pLineRemove == pReport->pLineLast) { pReport->pLineLast = pLine; } return (TRUE) ; } // if
} // for
return (FALSE) ; } // ReportLineRemove
// CheckColumnGroupRemove is used to check if the given
// column is empty. If it is empty, it is removed from
// the column link list
void CheckColumnGroupRemove (PREPORT pReport, POBJECTGROUP pObjectGroup, int iReportColumn) { // check if we need to remove the this column
PLINE pCounterLine ; PCOUNTERGROUP pCounterGrp ; BOOL bColumnFound = FALSE ;
if (iReportColumn < 0 || pObjectGroup->pCounterGroupFirst == NULL) { // no column for this Counter group, forget it
return ; }
// go thru each Counter group and check if any line in the
// group matches the given column number
for (pCounterGrp = pObjectGroup->pCounterGroupFirst ; pCounterGrp ; pCounterGrp = pCounterGrp->pCounterGroupNext ) { for (pCounterLine = pCounterGrp->pLineFirst ; pCounterLine ; pCounterLine = pCounterLine->pLineCounterNext) { if (pCounterLine->iReportColumn == iReportColumn) { // found one, this column is not empty
bColumnFound = TRUE ; break ; } } // for pCounterLine
if (bColumnFound) { break ; } } // for pCounterGrp
if (bColumnFound == FALSE) { // we have deleted the last column item, remove this column
ColumnRemoveOne (pReport, pObjectGroup, iReportColumn) ; } } // CheckColumnGroupRemove
//================================
// Line routine
//================================
void ReportLineValueRect (PREPORT pReport, PLINE pLine, LPRECT lpRect) { // ReportLineValueRect
lpRect->left = ValueMargin (pReport) + pLine->xReportPos ; lpRect->top = pLine->yReportPos ; lpRect->right = lpRect->left + pReport->xValueWidth ; lpRect->bottom = lpRect->top + pReport->yLineHeight ; } // ReportLineValueRect
PLINE LineRemoveItem (PREPORT pReport, enum REPORT_ITEM_TYPE *pNewItemType) { PLINE pLine ; PLINE pNextLine = NULL ; PLINE pReturnLine = NULL ; PLINE pLeftLine = NULL ; PSYSTEMGROUP pSystemGroup ; POBJECTGROUP pObjectGroup ; PCOUNTERGROUP pCounterGroup ; PCOUNTERGROUP pNextCounterGroup ; BOOL bCreatNewCounterGroup ;
//=============================//
// Remove line, line's system //
//=============================//
pLine = pReport->CurrentItem.pLine ; ReportLineRemove (pReport, pLine) ;
// no more line, no more timer...
if (!pReport->pLineFirst) { pReport->xWidth = 0 ; pReport->yHeight = 0 ; pReport->xMaxCounterWidth = 0 ; ClearReportTimer (pReport) ; }
//=============================//
// Get correct spot; remove line //
//=============================//
pSystemGroup = GetSystemGroup (pReport, pLine->lnSystemName) ; pObjectGroup = GetObjectGroup (pSystemGroup, pLine->lnObjectName) ; pCounterGroup = GetCounterGroup (pObjectGroup, pLine->lnCounterDef.CounterNameTitleIndex, &bCreatNewCounterGroup, pLine->lnCounterName, TRUE) ;
if (!pCounterGroup) return (NULL) ;
LineCounterRemove (pCounterGroup, pLine) ;
// check which line to get the focus
if (pCounterGroup->pLineFirst) { // simple case, we still have line in the same counter group
// get the one right after this delete line.
for (pNextLine = pCounterGroup->pLineFirst ; pNextLine ; pNextLine = pNextLine->pLineCounterNext) { if (pNextLine->xReportPos > pLine->xReportPos) { if (pReturnLine == NULL || pReturnLine->xReportPos > pNextLine->xReportPos) { pReturnLine = pNextLine ; } } else { if (pLeftLine == NULL || pLeftLine->xReportPos < pNextLine->xReportPos) { pLeftLine = pNextLine ; } } }
if (!pReturnLine && pLeftLine) { // the delete line is the last column, then use the line
// to its left
pReturnLine = pLeftLine ; } } else { pNextCounterGroup = GetNextCounter ( pSystemGroup, pObjectGroup, pCounterGroup) ;
if (pNextCounterGroup) { pLeftLine = NULL ; for (pNextLine = pNextCounterGroup->pLineFirst ; pNextLine ; pNextLine = pNextLine->pLineCounterNext) { // get the line in the first column
if (pLeftLine == NULL || pNextLine->xReportPos < pLeftLine->xReportPos) { pLeftLine = pNextLine ; } } pReturnLine = pLeftLine ; }
// remove this counter group if there is no line
CounterGroupRemove (&pObjectGroup->pCounterGroupFirst, pCounterGroup) ; }
// check if we need to remove any empty column
CheckColumnGroupRemove (pReport, pObjectGroup, pLine->iReportColumn) ;
if (!(pObjectGroup->pCounterGroupFirst)) ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
if (!(pSystemGroup->pObjectGroupFirst)) SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ;
LineFree (pLine) ;
if (pReturnLine && pNewItemType) { *pNewItemType = REPORT_TYPE_LINE ; }
return (pReturnLine) ; } // LineRemoveItem
//======================================//
// Column Group routines //
//======================================//
void ReportColumnRect (PREPORT pReport, PCOLUMNGROUP pColumnGroup, LPRECT lpRect) { // ReportColumnRect
lpRect->left = ValueMargin (pReport) + pColumnGroup->xPos ; lpRect->top = pColumnGroup->yFirstLine ; lpRect->right = lpRect->left + pColumnGroup->xWidth ; lpRect->bottom = lpRect->top + pReport->yLineHeight ; if (pColumnGroup->lpszParentName) { lpRect->top -= pReport->yLineHeight ; } } // ReportColumnRect
BOOL ColumnSame (PCOLUMNGROUP pColumnGroup, LPTSTR lpszParentName, LPTSTR lpszInstanceName, DWORD dwIndex) { // ColumnSame
BOOL bReturn = FALSE;
if (dwIndex == pColumnGroup->dwInstanceIndex) { if ((!lpszParentName && !pColumnGroup->lpszParentName) || strsame (lpszParentName, pColumnGroup->lpszParentName)) { if ((!lpszInstanceName && !pColumnGroup->lpszInstanceName) || strsame (lpszInstanceName, pColumnGroup->lpszInstanceName)) { bReturn = TRUE; } } } return bReturn; } // ColumnSame
PCOLUMNGROUP ColumnGroupCreate (PREPORT pReport, int xPos, LPTSTR lpszParentName, LPTSTR lpszInstanceName, int PreviousColumnNumber, int yFirstLine, DWORD dwIndex) { // ColumnGroupCreate
PCOLUMNGROUP pColumnGroup ; HDC hDC ;
hDC = GetDC (pReport->hWnd) ; if (!hDC) return NULL; pColumnGroup = MemoryAllocate (sizeof (COLUMNGROUP)) ;
if (pColumnGroup) { pColumnGroup->pColumnGroupNext = NULL ; pColumnGroup->lpszParentName = StringAllocate (lpszParentName) ; pColumnGroup->lpszInstanceName = StringAllocate (lpszInstanceName) ; pColumnGroup->ParentNameTextWidth = TextWidth (hDC, lpszParentName) ; pColumnGroup->InstanceNameTextWidth = TextWidth (hDC, lpszInstanceName) ; pColumnGroup->xPos = xPos ; pColumnGroup->yFirstLine = yFirstLine ; pColumnGroup->ColumnNumber = PreviousColumnNumber + 1 ; pColumnGroup->xWidth = max (max (pColumnGroup->ParentNameTextWidth, pColumnGroup->InstanceNameTextWidth), pReport->xValueWidth) ; pColumnGroup->dwInstanceIndex = dwIndex;
pReport->xWidth = max (pReport->xWidth, RightHandMargin + ValueMargin (pReport) + pColumnGroup->xPos + pColumnGroup->xWidth + xColumnMargin) ; } // if
ReleaseDC (pReport->hWnd, hDC) ; return (pColumnGroup) ; } // ColumnGroupCreate
PCOLUMNGROUP GetColumnGroup (PREPORT pReport, POBJECTGROUP pObjectGroup, PLINE pLine) /*
Effect: Return a pointer to the appropriate column group from within the groups of pObject. If the line is a counter without instances, return NULL. Otherwise, determine if the counter's parent/instance pair is already found in an existing column and return a pointer to that column.
If a column with the appropriate parent/instance isn't found, add a new column *at the end*, and return that column.
Note: This function has multiple return points. */ { // GetColumnGroup
PCOLUMNGROUP pColumnGroup ; LPTSTR lpszParentName ; LPTSTR lpszInstanceName ; DWORD dwIndex;
if (!LineInstanceName (pLine)) return (NULL) ;
lpszParentName = LineParentName (pLine) ; lpszInstanceName = LineInstanceName (pLine) ; dwIndex = pLine->dwInstanceIndex;
if (!pObjectGroup->pColumnGroupFirst) { pObjectGroup->pColumnGroupFirst = ColumnGroupCreate (pReport, 0, lpszParentName, lpszInstanceName, -1, pObjectGroup->yFirstLine, dwIndex) ;
if (pObjectGroup->pColumnGroupFirst) { pObjectGroup->pColumnGroupFirst->pParentObject = pObjectGroup ; }
return (pObjectGroup->pColumnGroupFirst) ; }
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ; pColumnGroup ; pColumnGroup = pColumnGroup->pColumnGroupNext) { // for
if (ColumnSame (pColumnGroup, lpszParentName, lpszInstanceName, dwIndex)) return (pColumnGroup) ;
else if (!pColumnGroup->pColumnGroupNext) { // if
pColumnGroup->pColumnGroupNext = ColumnGroupCreate (pReport, pColumnGroup->xPos + pColumnGroup->xWidth + xColumnMargin, lpszParentName, lpszInstanceName, pColumnGroup->ColumnNumber, pObjectGroup->yFirstLine, dwIndex) ;
if (pColumnGroup->pColumnGroupNext) { (pColumnGroup->pColumnGroupNext)->pParentObject = pObjectGroup ;
// build the double link-list
(pColumnGroup->pColumnGroupNext)->pColumnGroupPrevious = pColumnGroup ; }
return (pColumnGroup->pColumnGroupNext) ; } // if
} // for
return (NULL) ; } // GetColumnGroup
// ColumnRemoveOne removes the column with the specified column number
void ColumnRemoveOne (PREPORT pReport, POBJECTGROUP pObjectGroup, int iColumnNumber) { PCOLUMNGROUP pColumnGroup ; PCOLUMNGROUP pNextColumnGroup ;
if (pObjectGroup->pColumnGroupFirst == NULL) { // no column group, forget it
return ; }
// Find the head list
if (pObjectGroup->pColumnGroupFirst->ColumnNumber == iColumnNumber) { pColumnGroup = pObjectGroup->pColumnGroupFirst ; pObjectGroup->pColumnGroupFirst = pColumnGroup->pColumnGroupNext ; if (pColumnGroup->pColumnGroupNext) { // set up head of backward link list
(pColumnGroup->pColumnGroupNext)->pColumnGroupPrevious = NULL ; }
// free memory for this column group
MemoryFree (pColumnGroup->lpszParentName) ; MemoryFree (pColumnGroup->lpszInstanceName) ; MemoryFree (pColumnGroup) ;
return ; }
// go thru the double link list to look for the right column
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ; pColumnGroup ; pColumnGroup = pNextColumnGroup) { pNextColumnGroup = pColumnGroup->pColumnGroupNext ;
if (pNextColumnGroup == NULL) { // forget it if we can't find this column for some reson.
break ; }
if (pNextColumnGroup->ColumnNumber == iColumnNumber) { pColumnGroup->pColumnGroupNext = pNextColumnGroup->pColumnGroupNext ;
// build backward link iff it is not the end of list
if (pColumnGroup->pColumnGroupNext) { (pColumnGroup->pColumnGroupNext)->pColumnGroupPrevious = pColumnGroup ; }
// free memory for this column group
MemoryFree (pNextColumnGroup->lpszParentName) ; MemoryFree (pNextColumnGroup->lpszInstanceName) ; MemoryFree (pNextColumnGroup) ;
// Done
break ; } } } // ColumnRemoveOne
// ColumnGroupRemove removes all the columns for a given column list
void ColumnGroupRemove (PCOLUMNGROUP pColumnGroupFirst) { PCOLUMNGROUP pColumnGroup ; PCOLUMNGROUP pNextColumnGroup ;
for (pColumnGroup = pColumnGroupFirst ; pColumnGroup ; pColumnGroup = pNextColumnGroup) { pNextColumnGroup = pColumnGroup->pColumnGroupNext ;
// free memory for this column group
MemoryFree (pColumnGroup->lpszParentName) ; MemoryFree (pColumnGroup->lpszInstanceName) ; MemoryFree (pColumnGroup) ; } } // ColumnGroupRemove
// ColumnRemoveItem is called when user wants to delete a
// selected column.
PCOLUMNGROUP ColumnRemoveItem (PREPORT pReport, PCOLUMNGROUP pColumnGroup, BOOL bCleanUpLink, enum REPORT_ITEM_TYPE *pNewItemType) { PLINE pLine, pNextLine ; PSYSTEMGROUP pSystemGroup ; POBJECTGROUP pObjectGroup ; PCOUNTERGROUP pCounterGroup, pNextCounterGroup ; BOOL bColumnFound ; PCOLUMNGROUP pRetColumnGroup = NULL ;
pObjectGroup = pColumnGroup->pParentObject ; pSystemGroup = pObjectGroup->pParentSystem ;
// first, get rid of all the counter lines with this column number
// Note - each Counter group has only 1 line (or 0) with this
// column number
for (pCounterGroup = pObjectGroup->pCounterGroupFirst ; pCounterGroup ; pCounterGroup = pNextCounterGroup ) { pNextCounterGroup = pCounterGroup->pCounterGroupNext ; bColumnFound = FALSE ;
for (pLine = pCounterGroup->pLineFirst ; pLine ; pLine = pNextLine) { pNextLine = pLine->pLineCounterNext ; if (pLine->iReportColumn == pColumnGroup->ColumnNumber) { bColumnFound = TRUE ; // delete this line
ReportLineRemove (pReport, pLine) ; LineCounterRemove (pCounterGroup, pLine) ; LineFree (pLine) ; break ; } }
if (bColumnFound) { // check if we need delete this counter group
if (!(pCounterGroup->pLineFirst)) { CounterGroupRemove (&pObjectGroup->pCounterGroupFirst, pCounterGroup) ; } } }
// determine which column group to go after deleting this
if (pColumnGroup->pColumnGroupNext) { // get the Column group after this delete one
pRetColumnGroup = pColumnGroup->pColumnGroupNext ; } else { // get the Counter group before this delete one
pRetColumnGroup = pColumnGroup->pColumnGroupPrevious ; }
if (pNewItemType) { if (pRetColumnGroup) { *pNewItemType = REPORT_TYPE_COLUMN ; } else { // get next counter group
pNextCounterGroup = GetNextCounter ( pSystemGroup, pObjectGroup, NULL) ;
if (pNextCounterGroup) { // we have to return Counter group, so we have to do the
// dirty casting..
*pNewItemType = REPORT_TYPE_COUNTER ; pRetColumnGroup = (PCOLUMNGROUP) pNextCounterGroup ; } } }
// remove this column group
ColumnRemoveOne (pReport, pObjectGroup, pColumnGroup->ColumnNumber) ;
// check for further cleanup
if (bCleanUpLink) { if (!(pObjectGroup->pCounterGroupFirst)) ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
if (!(pSystemGroup->pObjectGroupFirst)) SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ; } return (pRetColumnGroup) ; } // ColumnRemoveItem
//======================================//
// Counter Group routines //
//======================================//
void ReportCounterRect (PREPORT pReport, PCOUNTERGROUP pCounterGroup, LPRECT lpRect) { // ReportCounterRect
lpRect->left = xCounterMargin ; lpRect->top = pCounterGroup->yLine ; lpRect->right = lpRect->left + pCounterGroup->xWidth + yScrollHeight / 2 ; lpRect->bottom = lpRect->top + pReport->yLineHeight ; } // ReportCounterRect
PCOUNTERGROUP CounterGroupCreate (DWORD dwCounterIndex, LPTSTR pCounterName) { // CounterGroupCreate
PCOUNTERGROUP pCounterGroup ; HDC hDC ; PREPORT pReport ;
pCounterGroup = MemoryAllocate (sizeof (COUNTERGROUP)) ;
if (pCounterGroup) { pCounterGroup->pCounterGroupNext = NULL ; pCounterGroup->pLineFirst = NULL ; pCounterGroup->dwCounterIndex = dwCounterIndex ;
if (pCounterName) { hDC = GetDC (hWndReport) ; pReport = ReportData (hWndReport) ; if (hDC && pReport) { SelectFont (hDC, pReport->hFont) ; pCounterGroup->xWidth = TextWidth (hDC, pCounterName) ; } if (hDC) { ReleaseDC (hWndReport, hDC) ; } } } // if
return (pCounterGroup) ; } // CounterGroupCreate
PCOUNTERGROUP GetCounterGroup (POBJECTGROUP pObjectGroup, DWORD dwCounterIndex, BOOL *pbCounterGroupCreated, LPTSTR pCounterName, BOOL bCreateNewGroup) { // GetCounterGroup
PCOUNTERGROUP pCounterGroup ;
*pbCounterGroupCreated = FALSE ; if (!pObjectGroup) return (FALSE) ;
if (!pObjectGroup->pCounterGroupFirst) { if (bCreateNewGroup) { pObjectGroup->pCounterGroupFirst = CounterGroupCreate (dwCounterIndex, pCounterName) ;
if (pObjectGroup->pCounterGroupFirst) { *pbCounterGroupCreated = TRUE ; pObjectGroup->pCounterGroupFirst->pParentObject = pObjectGroup ; }
return (pObjectGroup->pCounterGroupFirst) ; } } else {
for (pCounterGroup = pObjectGroup->pCounterGroupFirst ; pCounterGroup ; pCounterGroup = pCounterGroup->pCounterGroupNext) { if (dwCounterIndex && pCounterGroup->dwCounterIndex == dwCounterIndex) { return (pCounterGroup) ; } else if (!dwCounterIndex && pCounterGroup->pLineFirst && pstrsame (pCounterGroup->pLineFirst->lnCounterName, pCounterName)) { return (pCounterGroup) ; } else if (!pCounterGroup->pCounterGroupNext) { // if
if (bCreateNewGroup) { pCounterGroup->pCounterGroupNext = CounterGroupCreate (dwCounterIndex, pCounterName) ; if (pCounterGroup->pCounterGroupNext) { *pbCounterGroupCreated = TRUE ; (pCounterGroup->pCounterGroupNext)->pParentObject = pObjectGroup ;
// build backward link
(pCounterGroup->pCounterGroupNext)->pCounterGroupPrevious = pCounterGroup ; } return (pCounterGroup->pCounterGroupNext) ;
} } // if
} // for
}
return (NULL) ; } // GetCounterGroup
BOOL CounterGroupRemove (PCOUNTERGROUP *ppCounterGroupFirst, PCOUNTERGROUP pCounterGroupRemove) { PCOUNTERGROUP pCounterGroup ;
if (*ppCounterGroupFirst == pCounterGroupRemove) { *ppCounterGroupFirst = (*ppCounterGroupFirst)->pCounterGroupNext ;
if (*ppCounterGroupFirst) { // set up head of backward link list
(*ppCounterGroupFirst)->pCounterGroupPrevious = NULL ; }
MemoryFree (pCounterGroupRemove) ; return (TRUE) ; }
for (pCounterGroup = *ppCounterGroupFirst ; pCounterGroup->pCounterGroupNext ; pCounterGroup = pCounterGroup->pCounterGroupNext) { // for
if (pCounterGroup->pCounterGroupNext == pCounterGroupRemove) { pCounterGroup->pCounterGroupNext = pCounterGroupRemove->pCounterGroupNext ; if (pCounterGroup->pCounterGroupNext) { (pCounterGroup->pCounterGroupNext)->pCounterGroupPrevious = pCounterGroup ; } MemoryFree (pCounterGroupRemove) ; return (TRUE) ; } // if
} // for
return (FALSE) ; } // CounterGroupRemove
// CounterRemoveItem is called when user wants to delete a
// selected counter (row)
PCOUNTERGROUP CounterRemoveItem (PREPORT pReport, PCOUNTERGROUP pCounterGroup, BOOL bCleanUpLink, enum REPORT_ITEM_TYPE *pNewItemType) { PLINE pLine, pNextLine ; POBJECTGROUP pObjectGroup ; PSYSTEMGROUP pSystemGroup ; PCOLUMNGROUP pColumnGroup ; PCOLUMNGROUP pNextColumnGroup ; PCOUNTERGROUP pRetCounterGroup = NULL ;
pObjectGroup = pCounterGroup->pParentObject ; pSystemGroup = pObjectGroup->pParentSystem ;
// first, remove all the counter lines from this counter group
// and from the Report line link-list
for (pLine = pCounterGroup->pLineFirst ; pLine ; pLine = pNextLine) { pNextLine = pLine->pLineCounterNext ; ReportLineRemove (pReport, pLine) ; LineFree (pLine) ; }
// we only need to delete the counter group iff we are deleting
// this selected Counter.
if (bCleanUpLink) { // determine which counter group to go after deleting this
pRetCounterGroup = GetNextCounter ( pSystemGroup , pObjectGroup, pCounterGroup) ;
// remove this counter group from its parent object group
CounterGroupRemove (&pObjectGroup->pCounterGroupFirst, pCounterGroup) ;
if (!(pObjectGroup->pCounterGroupFirst)) ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ; else { // Object group not empty, check for any empty column
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ; pColumnGroup ; pColumnGroup = pNextColumnGroup) { pNextColumnGroup = pColumnGroup->pColumnGroupNext ; CheckColumnGroupRemove (pReport, pObjectGroup, pColumnGroup->ColumnNumber) ; } }
if (!(pSystemGroup->pObjectGroupFirst)) { SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ; } } else { // get rid of this counter's memory
MemoryFree (pCounterGroup) ; }
if (pRetCounterGroup && pNewItemType) { *pNewItemType = REPORT_TYPE_COUNTER ; } return (pRetCounterGroup) ; } // CounterRemoveItem
// GetNextCounter is used to get:
// If the current system is not empty, then get the
// (next object first counter) or
// (previous object last counter. )
// If the current system is empty, then get the
// (next system first object first counter) or
// (previous system last object last counter)
// Note - Any of the input pointers could be NULL pointer.
PCOUNTERGROUP GetNextCounter (PSYSTEMGROUP pSystemGroup, POBJECTGROUP pObjectGroup, PCOUNTERGROUP pCounterGroup) { PCOUNTERGROUP pRetCounter = NULL ; PCOUNTERGROUP pCounterGrp ; POBJECTGROUP pObjectGrp ;
if (pCounterGroup && pCounterGroup->pCounterGroupNext) { pRetCounter = pCounterGroup->pCounterGroupNext ; } else if (pCounterGroup && pCounterGroup->pCounterGroupPrevious) { pRetCounter = pCounterGroup->pCounterGroupPrevious ; } else if (pObjectGroup && pObjectGroup->pObjectGroupNext) { // get the next Object first Counter
pRetCounter = pObjectGroup->pObjectGroupNext->pCounterGroupFirst ; } else if (pObjectGroup && pObjectGroup->pObjectGroupPrevious) { // get the previous object last counter
pCounterGrp = (pObjectGroup->pObjectGroupPrevious)->pCounterGroupFirst ; if (pCounterGrp) { // get the last counter group of this object
for (; pCounterGrp->pCounterGroupNext ; pCounterGrp = pCounterGrp->pCounterGroupNext ) { ; } } pRetCounter = pCounterGrp ;
} else if (pSystemGroup && pSystemGroup->pSystemGroupNext) { // get next system first object first counter
pObjectGrp = pSystemGroup->pSystemGroupNext->pObjectGroupFirst ; pRetCounter = pObjectGrp->pCounterGroupFirst ; } else if (pSystemGroup && pSystemGroup->pSystemGroupPrevious) { // get previous system last object last counter
pObjectGrp = pSystemGroup->pSystemGroupPrevious->pObjectGroupFirst ; if (pObjectGrp) { // get the last object group of this system
for (; pObjectGrp->pObjectGroupNext ; pObjectGrp = pObjectGrp->pObjectGroupNext ) { ; } }
if (pObjectGrp) { pCounterGrp = pObjectGrp->pCounterGroupFirst ; if (pCounterGrp) { // get the last counter group of this object
for (; pCounterGrp->pCounterGroupNext ; pCounterGrp = pCounterGrp->pCounterGroupNext ) { ; } } pRetCounter = pCounterGrp ; } }
return (pRetCounter) ;
} // GetNextCounter
//======================================//
// Object Group routines //
//======================================//
void ReportObjectRect (PREPORT pReport, POBJECTGROUP pObjectGroup, LPRECT lpRect) { // ReportObjectRect
lpRect->left = xObjectMargin ; lpRect->top = pObjectGroup->yFirstLine ; lpRect->right = lpRect->left + pObjectGroup->xWidth ; lpRect->bottom = lpRect->top + pReport->yLineHeight ; } // ReportObjectRect
POBJECTGROUP ObjectGroupCreate (LPTSTR lpszObjectName) { // ObjectGroupCreate
POBJECTGROUP pObjectGroup ; HDC hDC ; PREPORT pReport ; int OldCounterWidth ; TCHAR szLine [LongTextLen] ;
pObjectGroup = MemoryAllocate (sizeof (OBJECTGROUP)) ;
if (pObjectGroup) { pObjectGroup->pObjectGroupNext = NULL ; pObjectGroup->pCounterGroupFirst = NULL ; pObjectGroup->pColumnGroupFirst = NULL ; pObjectGroup->lpszObjectName = StringAllocate (lpszObjectName) ;
hDC = GetDC (hWndReport) ; pReport = ReportData (hWndReport) ; if (hDC && pReport) { SelectFont (hDC, pReport->hFontHeaders) ;
TSPRINTF (szLine, szObjectFormat, lpszObjectName) ; pObjectGroup->xWidth = TextWidth (hDC, szLine) ;
// re-calc. the max. counter group width
OldCounterWidth = pReport->xMaxCounterWidth ; pReport->xMaxCounterWidth = max (pReport->xMaxCounterWidth, pObjectGroup->xWidth + xObjectMargin) ;
if (OldCounterWidth < pReport->xMaxCounterWidth) { // adjust the report width with the new counter width
pReport->xWidth += (pReport->xMaxCounterWidth - OldCounterWidth); }
} // if
if (hDC) { ReleaseDC (hWndReport, hDC) ; } } return (pObjectGroup) ; } // ObjectGroupCreate
POBJECTGROUP GetObjectGroup (PSYSTEMGROUP pSystemGroup, LPTSTR lpszObjectName) { POBJECTGROUP pObjectGroup ;
if (!pSystemGroup) return (FALSE) ;
if (!pSystemGroup->pObjectGroupFirst) { pSystemGroup->pObjectGroupFirst = ObjectGroupCreate (lpszObjectName) ; if (pSystemGroup->pObjectGroupFirst) { pSystemGroup->pObjectGroupFirst->pParentSystem = pSystemGroup ; } return (pSystemGroup->pObjectGroupFirst) ; }
for (pObjectGroup = pSystemGroup->pObjectGroupFirst ; pObjectGroup ; pObjectGroup = pObjectGroup->pObjectGroupNext) { // for
if (strsame (pObjectGroup->lpszObjectName, lpszObjectName)) { return (pObjectGroup) ; } else if (!pObjectGroup->pObjectGroupNext) { // if
pObjectGroup->pObjectGroupNext = ObjectGroupCreate (lpszObjectName) ;
if (pObjectGroup->pObjectGroupNext) { (pObjectGroup->pObjectGroupNext)->pParentSystem = pSystemGroup ; (pObjectGroup->pObjectGroupNext)->pObjectGroupPrevious = pObjectGroup ; }
return (pObjectGroup->pObjectGroupNext) ; } // if
} // for
// if it falls through (which it shouldn't) at least return a
// reasonable value
return (pSystemGroup->pObjectGroupFirst) ; } // GetObjectGroup
// ObjectGroupRemove removes the specified Object group
// from the Object double link list
BOOL ObjectGroupRemove (POBJECTGROUP *ppObjectGroupFirst, POBJECTGROUP pObjectGroupRemove) { POBJECTGROUP pObjectGroup ;
if (*ppObjectGroupFirst == pObjectGroupRemove) { *ppObjectGroupFirst = (*ppObjectGroupFirst)->pObjectGroupNext ; if (*ppObjectGroupFirst) { // set up head of backward link list
(*ppObjectGroupFirst)->pObjectGroupPrevious = NULL ; }
// clean up the allocated memory
ColumnGroupRemove (pObjectGroupRemove->pColumnGroupFirst) ; MemoryFree (pObjectGroupRemove->lpszObjectName) ; MemoryFree (pObjectGroupRemove) ; return (TRUE) ; }
for (pObjectGroup = *ppObjectGroupFirst ; pObjectGroup->pObjectGroupNext ; pObjectGroup = pObjectGroup->pObjectGroupNext) { // for
if (pObjectGroup->pObjectGroupNext == pObjectGroupRemove) { pObjectGroup->pObjectGroupNext = pObjectGroupRemove->pObjectGroupNext ; if (pObjectGroup->pObjectGroupNext) { (pObjectGroup->pObjectGroupNext)->pObjectGroupPrevious = pObjectGroup ; }
// clean up this object allocated memory and its column groups
ColumnGroupRemove (pObjectGroupRemove->pColumnGroupFirst) ; MemoryFree (pObjectGroupRemove->lpszObjectName) ; MemoryFree (pObjectGroupRemove) ; return (TRUE) ; } // if
} // for
return (FALSE) ; } // ObjectGroupRemove
// ObjectRemoveItem is called when user delete the selected object
PCOUNTERGROUP ObjectRemoveItem (PREPORT pReport, POBJECTGROUP pObjectGroup, BOOL bCleanUpLink, enum REPORT_ITEM_TYPE *pNewItemType) { PCOUNTERGROUP pCounterGroup, pNextCounterGroup ; PSYSTEMGROUP pSystemGroup ; PCOUNTERGROUP pRetCounterGroup = NULL ;
pSystemGroup = pObjectGroup->pParentSystem ;
// remove all counter groups from this object
for (pCounterGroup = pObjectGroup->pCounterGroupFirst ; pCounterGroup ; pCounterGroup = pNextCounterGroup ) { pNextCounterGroup = pCounterGroup->pCounterGroupNext ; CounterRemoveItem (pReport, pCounterGroup, FALSE, NULL) ; }
// remove all column groups from this group
ColumnGroupRemove (pObjectGroup->pColumnGroupFirst) ; pObjectGroup->pColumnGroupFirst = NULL;
if (bCleanUpLink) {
// get next counter group to get the focus
if (pNewItemType) { pRetCounterGroup = GetNextCounter ( pSystemGroup, pObjectGroup, NULL) ;
if (pRetCounterGroup) { *pNewItemType = REPORT_TYPE_COUNTER ; } }
// remove this object from its parent system group
ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
if (!(pSystemGroup->pObjectGroupFirst)) { SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ; } } else { // get rid of this object
MemoryFree (pObjectGroup->lpszObjectName) ; MemoryFree (pObjectGroup) ; }
return (pRetCounterGroup) ;
} // ObjectRemoveItem
//======================================//
// System Group routines //
//======================================//
void ReportSystemRect (PREPORT pReport, PSYSTEMGROUP pSystemGroup, LPRECT lpRect) { // ReportSystemRect
lpRect->left = xSystemMargin ; lpRect->top = pSystemGroup->yFirstLine ; lpRect->right = lpRect->left + pSystemGroup->xWidth ; lpRect->bottom = lpRect->top + pReport->yLineHeight ; } // ReportSystemRect
PSYSTEMGROUP SystemGroupCreate (LPTSTR lpszSystemName) { // SystemGroupCreate
PSYSTEMGROUP pSystemGroup ; HDC hDC ; PREPORT pReport ; TCHAR szLine [LongTextLen] ;
pSystemGroup = MemoryAllocate (sizeof (SYSTEMGROUP)) ;
if (pSystemGroup) { pSystemGroup->pSystemGroupNext = NULL ; pSystemGroup->pObjectGroupFirst = NULL ; pSystemGroup->lpszSystemName = StringAllocate (lpszSystemName) ;
// get width of system name
hDC = GetDC (hWndReport) ; if (hDC) { pReport = ReportData (hWndReport) ; SelectFont (hDC, pReport->hFontHeaders) ;
TSPRINTF (szLine, szSystemFormat, lpszSystemName) ; pSystemGroup->xWidth = TextWidth (hDC, szLine) ; ReleaseDC (hWndReport, hDC) ; } } // if
return (pSystemGroup) ; } // SystemGroupCreate
PSYSTEMGROUP GetSystemGroup (PREPORT pReport, LPTSTR lpszSystemName) /*
Effect; Return a pointer to the system group of pReport with a system name of lpszSystemName. If no system group has that name, add a new system group. */ { // GetSystemGroup
PSYSTEMGROUP pSystemGroup ;
if (!pReport->pSystemGroupFirst) { // add this system to the global system list
SystemAdd (&pReport->pSystemFirst, lpszSystemName, pReport->hWnd) ; // now add it to the report
pReport->pSystemGroupFirst = SystemGroupCreate (lpszSystemName) ; return (pReport->pSystemGroupFirst) ; }
for (pSystemGroup = pReport->pSystemGroupFirst ; pSystemGroup ; pSystemGroup = pSystemGroup->pSystemGroupNext) { // for
if (strsamei (pSystemGroup->lpszSystemName, lpszSystemName)) return (pSystemGroup) ; else if (!pSystemGroup->pSystemGroupNext) { // if
// add this system to the global system list
SystemAdd (&pReport->pSystemFirst, lpszSystemName, pReport->hWnd) ; // and add it to the report list
pSystemGroup->pSystemGroupNext = SystemGroupCreate (lpszSystemName) ; if (pSystemGroup->pSystemGroupNext) { (pSystemGroup->pSystemGroupNext)->pSystemGroupPrevious = pSystemGroup ; } return (pSystemGroup->pSystemGroupNext) ; } // if
} // for
//if it falls through (which it shouldn't) at least return a
// reasonable value
return (pReport->pSystemGroupFirst) ; } // GetSystemGroup
BOOL SystemGroupRemove (PSYSTEMGROUP *ppSystemGroupFirst, PSYSTEMGROUP pSystemGroupRemove) { PSYSTEMGROUP pSystemGroup ;
if (*ppSystemGroupFirst == pSystemGroupRemove) { *ppSystemGroupFirst = (*ppSystemGroupFirst)->pSystemGroupNext ; if (*ppSystemGroupFirst) { (*ppSystemGroupFirst)->pSystemGroupPrevious = NULL ; } MemoryFree (pSystemGroupRemove->lpszSystemName) ; MemoryFree (pSystemGroupRemove) ; return (TRUE) ; }
for (pSystemGroup = *ppSystemGroupFirst ; pSystemGroup->pSystemGroupNext ; pSystemGroup = pSystemGroup->pSystemGroupNext) { // for
if (pSystemGroup->pSystemGroupNext == pSystemGroupRemove) { pSystemGroup->pSystemGroupNext = pSystemGroupRemove->pSystemGroupNext ; if (pSystemGroup->pSystemGroupNext) { (pSystemGroup->pSystemGroupNext)->pSystemGroupPrevious = pSystemGroup ; } MemoryFree (pSystemGroupRemove->lpszSystemName) ; MemoryFree (pSystemGroupRemove) ; return (TRUE) ; } // if
} // for
return (FALSE) ; } // SystemGroupRemove
// SystemRemoveItem is called when user deletes the selected System
PCOUNTERGROUP SystemRemoveItem (PREPORT pReport, PSYSTEMGROUP pSystemGroup, BOOL bCleanUpLink, enum REPORT_ITEM_TYPE *pNewItemType) { POBJECTGROUP pObjectGroup, pNextObjectGroup ; PCOUNTERGROUP pRetCounterGroup = NULL ;
// remove all object groups from this system
for (pObjectGroup = pSystemGroup->pObjectGroupFirst ; pObjectGroup ; pObjectGroup = pNextObjectGroup ) { pNextObjectGroup = pObjectGroup->pObjectGroupNext ; ObjectRemoveItem (pReport, pObjectGroup, FALSE, NULL) ; }
if (bCleanUpLink) { if (pNewItemType) { pRetCounterGroup = GetNextCounter ( pSystemGroup, NULL, NULL) ;
if (pRetCounterGroup) { *pNewItemType = REPORT_TYPE_COUNTER ; } }
SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ; } else { // delete data from this system
MemoryFree (pSystemGroup->lpszSystemName) ; MemoryFree (pSystemGroup) ; }
return (pRetCounterGroup) ;
} // SystemRemoveItem
BOOL ReportChangeFocus (HWND hWnd, PREPORT pReport, REPORT_ITEM SelectedItem, enum REPORT_ITEM_TYPE SelectedItemType, int xOffset, int yOffset, RECT *pRect) { HDC hDC ; BOOL RetCode = FALSE ; // FALSE ==> same item being hit
RECT Rect ; REPORT_ITEM PreviousItem ; enum REPORT_ITEM_TYPE PreviousItemType ;
if (pReport->CurrentItem.pLine != SelectedItem.pLine) { // not the same item
RetCode = TRUE ;
PreviousItemType = pReport->CurrentItemType ; PreviousItem.pLine = pReport->CurrentItem.pLine ;
pReport->CurrentItemType = SelectedItemType ; pReport->CurrentItem.pLine = SelectedItem.pLine ;
hDC = GetDC (hWnd) ; if (!hDC) return FALSE;
if (SelectedItemType == REPORT_TYPE_LINE) { SetWindowOrgEx (hDC, xOffset, yOffset, NULL) ; SelectFont (hDC, pReport->hFont) ; SetTextAlign (hDC, TA_RIGHT) ; SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ; DrawReportValue (hDC, pReport, SelectedItem.pLine) ; SetWindowOrgEx (hDC, -xOffset, -yOffset, NULL) ; } else { Rect = *pRect ; Rect.top -= yOffset ; Rect.bottom -= yOffset ; Rect.right -= xOffset ; Rect.left -= xOffset ; InvalidateRect (hWnd, &Rect, TRUE) ; }
if (PreviousItemType == REPORT_TYPE_LINE) { SetWindowOrgEx (hDC, xOffset, yOffset, NULL) ; SelectFont (hDC, pReport->hFont) ; SetTextAlign (hDC, TA_RIGHT) ; SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ; DrawReportValue (hDC, pReport, PreviousItem.pLine) ; } else if (PreviousItemType != REPORT_TYPE_NOTHING) { if (PreviousItemType == REPORT_TYPE_SYSTEM) { ReportSystemRect (pReport, PreviousItem.pSystem, &Rect) ; } else if (PreviousItemType == REPORT_TYPE_OBJECT) { ReportObjectRect (pReport, PreviousItem.pObject, &Rect) ; } else if (PreviousItemType == REPORT_TYPE_COUNTER) { ReportCounterRect (pReport, PreviousItem.pCounter, &Rect) ; } else if (PreviousItemType == REPORT_TYPE_COLUMN) { ReportColumnRect (pReport, PreviousItem.pColumn, &Rect) ; } Rect.top -= yOffset ; Rect.bottom -= yOffset ; Rect.right -= xOffset ; Rect.left -= xOffset ; InvalidateRect (hWnd, &Rect, TRUE) ; } ReleaseDC (hWnd, hDC) ; }
return (RetCode) ; } // ReportChangeFocus
BOOL OnReportLButtonDown (HWND hWnd, WORD xPos, WORD yPos) { PREPORT pReport ; PLINE pLine ; REPORT_ITEM PreviousItem ; REPORT_ITEM CurrentSelectedItem ; enum REPORT_ITEM_TYPE PreviousItemType ; RECT rect ; POINT pt ; int xOffset, yOffset ; PSYSTEMGROUP pSystemGroup ; POBJECTGROUP pObjectGroup ; PCOUNTERGROUP pCounterGroup ; PCOLUMNGROUP pColumnGroup ;
pReport = ReportData (hWnd) ; if (!pReport) return (FALSE) ;
xOffset = GetScrollPos (hWnd, SB_HORZ) ; yOffset = GetScrollPos (hWnd, SB_VERT) ; pt.x = xPos + xOffset ; pt.y = yPos + yOffset ; PreviousItem = pReport->CurrentItem ; PreviousItemType = pReport->CurrentItemType ;
for (pLine = pReport->pLineFirst ; pLine ; pLine = pLine->pLineNext) { // for
ReportLineValueRect (pReport, pLine, &rect) ; if (PtInRect (&rect, pt)) { CurrentSelectedItem.pLine = pLine ; return (ReportChangeFocus ( hWnd, pReport, CurrentSelectedItem, REPORT_TYPE_LINE, xOffset, yOffset, &rect)) ; } } // for
// check on hit on system, object, counter, column (parent+isntance names)
for (pSystemGroup = pReport->pSystemGroupFirst ; pSystemGroup ; pSystemGroup = pSystemGroup->pSystemGroupNext) { // for System...
ReportSystemRect (pReport, pSystemGroup, &rect) ; if (PtInRect (&rect, pt)) { CurrentSelectedItem.pSystem = pSystemGroup ; return (ReportChangeFocus ( hWnd, pReport, CurrentSelectedItem, REPORT_TYPE_SYSTEM, xOffset, yOffset, &rect)) ; }
for (pObjectGroup = pSystemGroup->pObjectGroupFirst ; pObjectGroup ; pObjectGroup = pObjectGroup->pObjectGroupNext) { // for Object...
ReportObjectRect (pReport, pObjectGroup, &rect) ; if (PtInRect (&rect, pt)) { CurrentSelectedItem.pObject = pObjectGroup ; return (ReportChangeFocus ( hWnd, pReport, CurrentSelectedItem, REPORT_TYPE_OBJECT, xOffset, yOffset, &rect)) ; }
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ; pColumnGroup ; pColumnGroup = pColumnGroup->pColumnGroupNext) { // for Column...
ReportColumnRect (pReport, pColumnGroup, &rect) ; if (PtInRect (&rect, pt)) { CurrentSelectedItem.pColumn = pColumnGroup ; return (ReportChangeFocus ( hWnd, pReport, CurrentSelectedItem, REPORT_TYPE_COLUMN, xOffset, yOffset, &rect)) ; } } // for Column
for (pCounterGroup = pObjectGroup->pCounterGroupFirst ; pCounterGroup ; pCounterGroup = pCounterGroup->pCounterGroupNext) { // for Counter...
ReportCounterRect (pReport, pCounterGroup, &rect) ; if (PtInRect (&rect, pt)) { CurrentSelectedItem.pCounter = pCounterGroup ; return (ReportChangeFocus ( hWnd, pReport, CurrentSelectedItem, REPORT_TYPE_COUNTER, xOffset, yOffset, &rect)) ;
} } // for Counter...
} // for Object...
} // for System...
// nothing hit
return (FALSE) ; } // OnReportLButtonDown
BOOL ReportDeleteItem (HWND hWnd) /*
Effect: Delete the current selected item.
*/ { // ReportDeleteItem
HDC hDC ; PREPORT pReport ; REPORT_ITEM NextItem ; enum REPORT_ITEM_TYPE NextItemType ;
NextItemType = REPORT_TYPE_NOTHING ; NextItem.pLine = NULL ;
pReport = ReportData (hWnd) ; if (pReport->CurrentItemType == REPORT_TYPE_NOTHING) { // nothing to delete...
return (TRUE) ; } else if (pReport->CurrentItemType == REPORT_TYPE_LINE) { NextItem.pLine = LineRemoveItem (pReport, &NextItemType) ; } else if (pReport->CurrentItemType == REPORT_TYPE_SYSTEM) { NextItem.pCounter = SystemRemoveItem ( pReport, pReport->CurrentItem.pSystem, TRUE, &NextItemType) ; } else if (pReport->CurrentItemType == REPORT_TYPE_OBJECT) { NextItem.pCounter = ObjectRemoveItem ( pReport, pReport->CurrentItem.pObject, TRUE, &NextItemType) ; } else if (pReport->CurrentItemType == REPORT_TYPE_COUNTER) { NextItem.pCounter = CounterRemoveItem ( pReport, pReport->CurrentItem.pCounter, TRUE, &NextItemType) ; } else if (pReport->CurrentItemType == REPORT_TYPE_COLUMN) { NextItem.pColumn = ColumnRemoveItem ( pReport, pReport->CurrentItem.pColumn, TRUE, &NextItemType) ; }
if (NextItemType != REPORT_TYPE_NOTHING) { pReport->CurrentItem.pLine = NextItem.pLine ; pReport->CurrentItemType = NextItemType ; } else { pReport->CurrentItem.pLine = pReport->pLineFirst ; pReport->CurrentItemType = REPORT_TYPE_LINE ; }
if (pReport->pLineFirst) { BuildValueListForSystems ( pReport->pSystemFirst, pReport->pLineFirst) ; } else { // no more line, no more timer...
pReport->xWidth = 0 ; pReport->yHeight = 0 ; pReport->xMaxCounterWidth = 0 ; ClearReportTimer (pReport) ;
FreeSystems (pReport->pSystemFirst) ; pReport->pSystemFirst = NULL ; pReport->pSystemGroupFirst = NULL ; pReport->CurrentItemType = REPORT_TYPE_NOTHING ; pReport->CurrentItem.pLine = NULL ;
}
//=============================//
// Calculate report positions //
//=============================//
hDC = GetDC (hWnd) ; if (hDC) { SetReportPositions (hDC, pReport) ;
if (!pReport->pLineFirst) { SelectFont (hDC, pReport->hFont) ; pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ; }
ReleaseDC (hWnd, hDC) ; } WindowInvalidate (hWnd) ;
return (TRUE) ; } // ReportDeleteItem
|