windows-nt/Source/XPSP1/NT/sdktools/setedit/grafdata.c
2020-09-26 16:20:57 +08:00

703 lines
17 KiB
C

/*****************************************************************************
*
* Grafdata.c - This module handles the non-drawing functions of the graph,
* such as allocating linked structures and their memory, freeing it,
* unlinking, starting and stopping the timer,
* setting up the first graph (CPU), and all the numeric functions for
* the different counter types.
*
* Microsoft Confidential
* Copyright (c) 1992-1993 Microsoft Corporation
*
*
****************************************************************************/
//==========================================================================//
// Includes //
//==========================================================================//
#include <stdio.h> // for sprintf
#include "setedit.h" // main perfmon declarations
#include "grafdata.h" // external declarations for this file
#include <float.h> // for FLT_MAX constant
#include "addline.h" // for AddLine, EditLine
#include "counters.h" // for Counter_Counter, et al.
#include "graph.h" // for SizeGraphComponents
#include "pmemory.h" // for MemoryXXX (mallloc-type) routines
#include "perfdata.h" // for UpdateLines
#include "legend.h"
#include "system.h" // for SystemGet
#include "utils.h"
#include "line.h" // for LineFree
// #include "valuebar.h" // for StatusTimer
#include "fileopen.h" // for FileGetName
#include "fileutil.h" // for FileRead...
#include "menuids.h" // for IDM_VIEWCHART
#include "perfmops.h" // for ExportFileHeader
#include "status.h" // for StatusLineReady
extern BOOL SaveFileHandler(HWND hWnd,DWORD type) ;
// this macro is used in doing a simple DDA (Digital Differential Analyzer)
// * 10 + 5 is to make the result round up with .5
#define DDA_DISTRIBUTE(TotalTics, numOfData) \
((TotalTics * 10 / numOfData) + 5) / 10
#define szSmallValueFormat TEXT("%10.3f")
#define szLargeValueFormat TEXT("%10.0f")
//==========================================================================//
// Local Data //
//==========================================================================//
//==========================================================================//
// Local Functions //
//==========================================================================//
/****************************************************************************
* eUpdateMinMaxAve -
****************************************************************************/
void eUpdateMinMaxAve (FLOAT eValue, PLINESTRUCT pLineStruct, INT iValidValues,
INT iTotalValidPoints, INT iDataPoint, INT gMaxPoints)
{
INT i ;
INT iDataNum = iTotalValidPoints ;
FLOAT eMin,
eMax,
eSum,
eNewValue ;
eMax = eMin = eValue ;
eSum = eValue ;
if (iValidValues == iTotalValidPoints)
{
for (i=0 ; i < iValidValues ; i++)
{
if (i == iDataPoint)
{
// skip the data point we are going to replace
continue ;
}
eNewValue = pLineStruct->lnValues[i] ;
eSum += eNewValue ;
if (eNewValue > eMax)
{
eMax = eNewValue ;
}
if (eNewValue < eMin)
{
eMin = eNewValue ;
}
}
}
else
{
// special case when we start the new line in the middle of the chart
for (i = iDataPoint, iTotalValidPoints-- ;
iTotalValidPoints > 0 ;
iTotalValidPoints-- )
{
i-- ;
if (i < 0)
{
// for the wrap-around case..
i = gMaxPoints - 1 ;
}
if (i == iDataPoint)
{
// skip the data point we are going to replace
continue ;
}
eNewValue = pLineStruct->lnValues[i] ;
eSum += eNewValue ;
if (eNewValue > eMax)
{
eMax = eNewValue ;
}
if (eNewValue < eMin)
{
eMin = eNewValue ;
}
}
}
pLineStruct->lnMinValue = eMin ;
pLineStruct->lnMaxValue = eMax ;
if (iDataNum)
{
pLineStruct->lnAveValue = eSum / (FLOAT) iDataNum ;
}
else
{
pLineStruct->lnAveValue = (FLOAT) 0.0 ;
}
}
BOOL HandleGraphTimer (void)
{
return(TRUE);
}
VOID GetGraphConfig(PGRAPHSTRUCT pGraph)
{
LoadRefreshSettings(pGraph);
LoadLineGraphSettings(pGraph);
// Init the structure
pGraph->pLineFirst = NULL;
//NOTE: put the rest of this in Config
pGraph->gOptions.bLegendChecked = TRUE;
pGraph->gOptions.bMenuChecked = TRUE;
pGraph->gOptions.bLabelsChecked = TRUE;
pGraph->gOptions.bVertGridChecked = FALSE;
pGraph->gOptions.bHorzGridChecked = FALSE;
pGraph->gOptions.bStatusBarChecked = TRUE;
pGraph->gOptions.GraphVGrid = TRUE;
pGraph->gOptions.GraphHGrid = TRUE;
pGraph->gOptions.HistVGrid = TRUE;
pGraph->gOptions.HistHGrid = TRUE;
pGraph->gOptions.iGraphOrHistogram = LINE_GRAPH; // vs. BAR_GRAPH
pGraph->gOptions.iVertMax = DEF_GRAPH_VMAX;
return;
}
BOOL InsertGraph (HWND hWnd)
{
PGRAPHSTRUCT pGraph;
pGraph = MemoryAllocate (sizeof (GRAPHSTRUCT)) ;
if (!pGraph)
return (FALSE) ;
pGraphs = pGraph;
GetGraphConfig(pGraph);
pGraph->bManualRefresh = FALSE ;
pGraph->gMaxValues = DEFAULT_MAX_VALUES;
pGraph->pptDataPoints = NULL ;
pGraph->pDataTime = NULL ;
pGraph->hWnd = hWnd ;
pGraph->bModified = TRUE ; // creating a graph means it's been modified
pGraph->Visual.iColorIndex = 0 ;
pGraph->Visual.iWidthIndex = 0 ;
pGraph->Visual.iStyleIndex = 0 ;
return(TRUE) ;
}
BOOL ChartInsertLine (PGRAPHSTRUCT pGraph,
PLINE pLine)
/*
Effect: Insert the line pLine into the graph pGraph and
allocate space for the graph's number of values.
Returns: Whether the line could be added and space allocated.
See Also: LineAllocate (line.c), ChartDeleteLine.
*/
{ // ChartInsertLine
PLINE pLineEquivalent ;
INT i ;
FLOAT *pTempPts;
HPEN tempPen ;
pGraph->bModified = TRUE ;
pLineEquivalent = FindEquivalentLine (pLine, pGraph->pLineFirst) ;
if (pLineEquivalent)
{
if (bMonitorDuplicateInstances) {
pLine->dwInstanceIndex = pLineEquivalent->dwInstanceIndex + 1;
} else {
pLineEquivalent->Visual = pLine->Visual ;
pLineEquivalent->iScaleIndex = pLine->iScaleIndex ;
pLineEquivalent->eScale = pLine->eScale ;
tempPen = pLineEquivalent->hPen ;
pLineEquivalent->hPen = pLine->hPen ;
pLine->hPen = tempPen ;
return FALSE ;
}
}
LineAppend (&pGraph->pLineFirst, pLine) ;
// Add the line to the legend, resize the legend window, and then
// select the new line as the current legend item. Do it in this
// sequence to avoid the legend scroll bar momentarily appearing and
// then disappearing, since the resize will obviate the scroll bar.
LegendAddItem (hWndGraphLegend, pLine) ;
if (!bDelayAddAction)
{
SizeGraphComponents (hWndGraph) ;
LegendSetSelection (hWndGraphLegend,
LegendNumItems (hWndGraphLegend) - 1) ;
}
return (TRUE) ;
} // ChartInsertLine
VOID ChartDeleteLine (PGRAPHSTRUCT pGraph,
PLINESTRUCT pLine)
{
PLINESTRUCT npLine;
pGraph->bModified = TRUE ;
if (pGraph->pLineFirst == pLine)
pGraph->pLineFirst = pLine->pLineNext;
else
{
for (npLine = pGraph->pLineFirst; npLine; npLine = npLine->pLineNext)
{
if (npLine->pLineNext == pLine)
npLine->pLineNext = pLine->pLineNext;
}
}
if (!pGraph->pLineFirst)
{
ResetGraph (pGraph) ;
}
else
{
// BuildNewValueListForGraph () ;
}
// Delete the legend entry for this line.
// If the line was highlighted then this will undo the highlight.
LegendDeleteItem (hWndGraphLegend, pLine) ;
LineFree (pLine) ;
SizeGraphComponents (hWndGraph) ;
}
FLOAT Counter_Queuelen(PLINESTRUCT pLine)
{
return((FLOAT)0.0);
// pLine;
}
void ClearGraphDisplay (PGRAPHSTRUCT pGraph)
{
PLINESTRUCT pLine;
// reset the timeline data
// pGraph->gKnownValue = -1 ;
// pGraph->gTimeLine.iValidValues = 0 ;
// pGraph->gTimeLine.xLastTime = 0 ;
// memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
// loop through lines,
// If one of the lines is highlighted then do the calculations
// for average, min, & max on that line.
// for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
// { // for
// pLine->bFirstTime = 2 ;
// pLine->lnMinValue = FLT_MAX ;
// pLine->lnMaxValue = - FLT_MAX ;
// pLine->lnAveValue = 0.0F ;
// pLine->lnValidValues = 0 ;
// memset (pLine->lnValues, 0, sizeof(FLOAT) * pGraph->gMaxValues) ;
// }
// StatusTimer (hWndGraphStatus, TRUE) ;
}
void ResetGraphView (HWND hWndGraph)
{
PGRAPHSTRUCT pGraph ;
pGraph = GraphData (hWndGraph) ;
if (!pGraph)
{
return ;
}
ChangeSaveFileName (NULL, IDM_VIEWCHART) ;
if (pGraph->pSystemFirst)
{
ResetGraph (pGraph) ;
}
} // ResetGraphView
void ResetGraph (PGRAPHSTRUCT pGraph)
{
ClearLegend (hWndGraphLegend) ;
if (pGraph->pLineFirst)
{
FreeLines (pGraph->pLineFirst) ;
pGraph->pLineFirst = NULL ;
}
if (pGraph->pSystemFirst)
{
FreeSystems (pGraph->pSystemFirst) ;
pGraph->pSystemFirst = NULL ;
}
pGraph->gKnownValue = -1 ;
pGraph->gTimeLine.iValidValues = 0 ;
pGraph->gTimeLine.xLastTime = 0 ;
// reset visual data
pGraph->Visual.iColorIndex = 0 ;
pGraph->Visual.iWidthIndex = 0 ;
pGraph->Visual.iStyleIndex = 0 ;
// memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
SizeGraphComponents (hWndGraph) ;
InvalidateRect(hWndGraph, NULL, TRUE) ;
}
BOOL AddChart (HWND hWndParent)
{
PLINE pCurrentLine = CurrentGraphLine (hWndGraph) ;
return (AddLine (hWndParent,
&(pGraphs->pSystemFirst),
&(pGraphs->Visual),
pCurrentLine ? pCurrentLine->lnSystemName : NULL,
LineTypeChart)) ;
}
BOOL EditChart (HWND hWndParent)
{ // EditChart
return (EditLine (hWndParent,
&(pGraphs->pSystemFirst),
CurrentGraphLine (hWndGraph),
LineTypeChart)) ;
}
BOOL QuerySaveChart (HWND hWndParent, PGRAPHSTRUCT pGraph)
/*
Effect: If the graph pGraph is modified, put up a message
box allowing the user to save the current graph.
Return whether the caller should proceed to load in
a new or otherwise trash the current graph.
*/
{ // QuerySaveChart
#ifdef KEEP_QUERY
int iReturn ;
if (!pGraph->bModified)
return (TRUE) ;
iReturn = MessageBoxResource (hWndParent,
IDS_SAVECHART, IDS_MODIFIEDCHART,
MB_YESNOCANCEL | MB_ICONASTERISK) ;
if (iReturn == IDCANCEL)
return (FALSE) ;
if (iReturn == IDYES)
SaveChart (hWndGraph, 0, 0) ;
return (TRUE) ;
#endif
return (TRUE) ; // we don't want to query nor save change
} // QuerySaveChart
void GraphAddAction ()
{
PGRAPHSTRUCT pGraph ;
pGraph = GraphData (hWndGraph) ;
SizeGraphComponents (hWndGraph) ;
LegendSetSelection (hWndGraphLegend,
LegendNumItems (hWndGraphLegend) - 1) ;
}
BOOL OpenChartVer1 (HANDLE hFile,
DISKCHART *pDiskChart,
PGRAPHSTRUCT pGraph)
{ // OpenChartVer1
bDelayAddAction = TRUE ;
pGraph->Visual = pDiskChart->Visual ;
pGraph->gOptions = pDiskChart->gOptions ;
pGraph->gMaxValues = pDiskChart->gMaxValues ;
pGraph->bManualRefresh = pDiskChart->bManualRefresh ;
pGraphs->gInterval = (INT) (pGraph->gOptions.eTimeInterval * (FLOAT) 1000.0) ;
ReadLines (hFile, pDiskChart->dwNumLines,
&(pGraph->pSystemFirst), &(pGraph->pLineFirst), IDM_VIEWCHART) ;
bDelayAddAction = FALSE ;
GraphAddAction () ;
return (TRUE) ;
} // OpenChartVer1
BOOL OpenChart (HWND hWndGraph,
HANDLE hFile,
DWORD dwMajorVersion,
DWORD dwMinorVersion,
BOOL bChartFile)
{ // OpenChart
PGRAPHSTRUCT pGraph ;
DISKCHART DiskChart ;
BOOL bSuccess = TRUE ;
pGraph = pGraphs ;
if (!pGraph)
{
bSuccess = FALSE ;
goto Exit0 ;
}
if (!FileRead (hFile, &DiskChart, sizeof (DISKCHART)))
{
bSuccess = FALSE ;
goto Exit0 ;
}
switch (dwMajorVersion)
{
case (1):
SetHourglassCursor() ;
ResetGraphView (hWndGraph) ;
OpenChartVer1 (hFile, &DiskChart, pGraph) ;
// change to chart view if we are opening a
// chart file
if (bChartFile && iPerfmonView != IDM_VIEWCHART)
{
SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWCHART, 0L) ;
}
if (iPerfmonView == IDM_VIEWCHART)
{
SetPerfmonOptions (&DiskChart.perfmonOptions) ;
}
SetArrowCursor() ;
break ;
} // switch
Exit0:
if (bChartFile)
{
CloseHandle (hFile) ;
}
return (bSuccess) ;
} // OpenChart
BOOL SaveChart (HWND hWndGraph, HANDLE hInputFile, BOOL bGetFileName)
{
PGRAPHSTRUCT pGraph ;
PLINE pLine ;
HANDLE hFile ;
DISKCHART DiskChart ;
PERFFILEHEADER FileHeader ;
TCHAR szFileName [256] ;
BOOL newFileName = FALSE ;
if (hInputFile)
{
// use the input file handle if it is available
// this is the case for saving workspace data
hFile = hInputFile ;
}
else
{
if (pChartFullFileName)
{
lstrcpy (szFileName, pChartFullFileName) ;
}
if (bGetFileName || pChartFullFileName == NULL)
{
// if (!pChartFullFileName)
// {
// StringLoad (IDS_GRAPH_FNAME, szFileName) ;
// }
if (!FileGetName (hWndGraph, IDS_CHARTFILE, szFileName))
{
return (FALSE) ;
}
newFileName = TRUE ;
}
hFile = FileHandleCreate (szFileName) ;
if (hFile && hFile != INVALID_HANDLE_VALUE && newFileName)
{
ChangeSaveFileName (szFileName, IDM_VIEWCHART) ;
}
else if (!hFile || hFile == INVALID_HANDLE_VALUE)
{
DlgErrorBox (hWndGraph, ERR_CANT_OPEN, szFileName) ;
}
}
if (!hFile || hFile == INVALID_HANDLE_VALUE)
return (FALSE) ;
pGraph = pGraphs ;
if (!pGraph)
{
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
{
CloseHandle (hFile) ;
}
return (FALSE) ;
}
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
{
// only need to write file header if not workspace
memset (&FileHeader, 0, sizeof (FileHeader)) ;
lstrcpy (FileHeader.szSignature, szPerfChartSignature) ;
FileHeader.dwMajorVersion = ChartMajorVersion ;
FileHeader.dwMinorVersion = ChartMinorVersion ;
if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
{
goto Exit0 ;
}
}
DiskChart.Visual = pGraph->Visual ;
DiskChart.gOptions = pGraph->gOptions ;
DiskChart.gMaxValues = pGraph->gMaxValues ;
DiskChart.dwNumLines = NumLines (pGraph->pLineFirst) ;
DiskChart.bManualRefresh = pGraph->bManualRefresh ;
DiskChart.perfmonOptions = Options ;
if (!FileWrite (hFile, &DiskChart, sizeof (DISKCHART)))
{
goto Exit0 ;
}
for (pLine = pGraph->pLineFirst ;
pLine ;
pLine = pLine->pLineNext)
{ // for
if (!WriteLine (pLine, hFile))
{
goto Exit0 ;
}
} // for
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
{
CloseHandle (hFile) ;
}
return (TRUE) ;
Exit0:
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
{
CloseHandle (hFile) ;
// only need to report error if not workspace
DlgErrorBox (hWndGraph, ERR_SETTING_FILE, szFileName) ;
}
return (FALSE) ;
} // SaveChart
#define TIME_TO_WRITE 6
typedef struct CHARTDATAPOINTSTRUCT
{
int iLogIndex ;
int xDispDataPoint ;
} CHARTDATAPOINT, *PCHARTDATAPOINT ;
BOOL ToggleGraphRefresh (HWND hWnd)
{ // ToggleGraphRefresh
PGRAPHSTRUCT pGraph ;
pGraph = GraphData (hWnd) ;
pGraph->bManualRefresh = !pGraph->bManualRefresh ;
return (pGraph->bManualRefresh) ;
} // ToggleGraphRefresh
BOOL GraphRefresh (HWND hWnd)
{ // GraphRefresh
PGRAPHSTRUCT pGraph ;
pGraph = GraphData (hWnd) ;
return (pGraph->bManualRefresh) ;
} // GraphRefresh