Annotation of mstools/samples/sdktools/perfmon/grafdata.c, revision 1.1.1.1

1.1       root        1: /*****************************************************************************
                      2:  *
                      3:  *  Grafdata.c - This module handles the non-drawing functions of the graph,
                      4:  *      such as allocating linked structures and their memory, freeing it,
                      5:  *      unlinking, starting and stopping the timer,
                      6:  *      setting up the first graph (CPU), and all the numeric functions for
                      7:  *      the different counter types.
                      8:  *
                      9:  *  Microsoft Confidential
                     10:  *  Copyright (c) 1992-1993 Microsoft Corporation
                     11:  *
                     12:  *
                     13:  ****************************************************************************/
                     14: 
                     15: 
                     16: //==========================================================================//
                     17: //                                  Includes                                //
                     18: //==========================================================================//
                     19: 
                     20: #include <stdio.h>      // for sprintf
                     21: 
                     22: #include "perfmon.h"       // main perfmon declarations
                     23: #include "grafdata.h"      // external declarations for this file
                     24: #include <float.h>         // for FLT_MAX constant
                     25: 
                     26: #include "addline.h"       // for AddLine, EditLine
                     27: #include "counters.h"      // for Counter_Counter, et al.
                     28: #include "graph.h"         // for SizeGraphComponents
                     29: #include "pmemory.h"       // for MemoryXXX (mallloc-type) routines
                     30: #include "perfdata.h"      // for UpdateLines
                     31: #include "playback.h"      // for PlayingBackLog, PlaybackLines
                     32: #include "legend.h"
                     33: #include "system.h"        // for SystemGet
                     34: #include "utils.h"
                     35: #include "line.h"          // for LineFree
                     36: #include "valuebar.h"      // for StatusTimer
                     37: 
                     38: #include "fileopen.h"      // for FileGetName
                     39: #include "fileutil.h"      // for FileRead...
                     40: #include "menuids.h"       // for IDM_VIEWCHART
                     41: #include "perfmops.h"      // for ExportFileHeader
                     42: #include "status.h"        // for StatusLineReady
                     43: 
                     44: extern BOOL SaveFileHandler(HWND hWnd,DWORD type) ;
                     45: 
                     46: // this macro is used in doing a simple DDA (Digital Differential Analyzer)
                     47: // * 10 + 5 is to make the result round up with .5
                     48: #define DDA_DISTRIBUTE(TotalTics, numOfData) \
                     49:    ((TotalTics * 10 / numOfData) + 5) / 10
                     50: 
                     51: #define szSmallValueFormat         TEXT("%10.3f")
                     52: #define szLargeValueFormat         TEXT("%10.0f")
                     53: 
                     54: //==========================================================================//
                     55: //                                Local Data                                //
                     56: //==========================================================================//
                     57: 
                     58: 
                     59: 
                     60: 
                     61: //==========================================================================//
                     62: //                              Local Functions                             //
                     63: //==========================================================================//
                     64: 
                     65: 
                     66: /****************************************************************************
                     67:  * eUpdateMinMaxAve -
                     68:  ****************************************************************************/
                     69: void eUpdateMinMaxAve (FLOAT eValue, PLINESTRUCT pLineStruct, INT iValidValues,
                     70:    INT iTotalValidPoints, INT iDataPoint, INT gMaxPoints)
                     71: {
                     72: INT     i ;
                     73: INT     iDataNum = iTotalValidPoints ;
                     74: FLOAT   eMin,
                     75:         eMax,
                     76:         eSum,
                     77:         eNewValue ;
                     78: 
                     79: 
                     80:    eMax = eMin = eValue ;
                     81: 
                     82:    if (PlayingBackLog())
                     83:       {
                     84:       eSum = (FLOAT) 0.0 ;
                     85:       }
                     86:    else
                     87:       {
                     88:       eSum = eValue ;
                     89:       }
                     90: 
                     91:    if (iValidValues == iTotalValidPoints)
                     92:       {
                     93:       for (i=0 ; i < iValidValues ; i++)
                     94:          {
                     95:          if (i == iDataPoint)
                     96:             {
                     97:             // skip the data point we are going to replace
                     98:             continue ;
                     99:             }
                    100: 
                    101:          eNewValue = pLineStruct->lnValues[i] ;
                    102:          
                    103:          eSum += eNewValue ;
                    104: 
                    105:          if (eNewValue > eMax)
                    106:             {
                    107:             eMax = eNewValue ;
                    108:             }
                    109: 
                    110:          if (eNewValue < eMin)
                    111:             {
                    112:             eMin = eNewValue ;
                    113:             }
                    114:          }
                    115:       }
                    116:    else
                    117:       {
                    118:       // special case when we start the new line in the middle of the chart
                    119:       for (i = iDataPoint, iTotalValidPoints-- ;
                    120:           iTotalValidPoints > 0 ;
                    121:           iTotalValidPoints-- )
                    122:          {
                    123:          i-- ;
                    124:          if (i < 0)
                    125:             {
                    126:             // for the wrap-around case..
                    127:             i = gMaxPoints - 1 ;
                    128:             }
                    129: 
                    130:          if (i == iDataPoint)
                    131:             {
                    132:             // skip the data point we are going to replace
                    133:             continue ;
                    134:             }
                    135:          eNewValue = pLineStruct->lnValues[i] ;
                    136: 
                    137:          eSum += eNewValue ;
                    138: 
                    139:          if (eNewValue > eMax)
                    140:             {
                    141:             eMax = eNewValue ;
                    142:             }
                    143: 
                    144:          if (eNewValue < eMin)
                    145:             {
                    146:             eMin = eNewValue ;
                    147:             }
                    148:          }
                    149:       }
                    150: 
                    151:    pLineStruct->lnMinValue = eMin ;
                    152:    pLineStruct->lnMaxValue = eMax ;
                    153: 
                    154:    if (iDataNum)
                    155:       {
                    156:       pLineStruct->lnAveValue = eSum / (FLOAT) iDataNum ;
                    157:       }
                    158:    else
                    159:       {
                    160:       pLineStruct->lnAveValue = (FLOAT) 0.0 ;
                    161:       }
                    162: }
                    163: 
                    164: 
                    165: // UpdateValueBarData is used to update the value bar data
                    166: // It is called when the user switches to a diff. line from
                    167: // the legned window.
                    168: VOID UpdateValueBarData (PGRAPHSTRUCT pGraph)
                    169:    {
                    170:    PLINESTRUCT    pCurrentGraphLine ;   
                    171:    INT            KnownValue,
                    172:                   MaxValues,
                    173:                   iValidValues,
                    174:                   iDataPoint ;
                    175:    FLOAT          eValue ;
                    176:    pCurrentGraphLine = CurrentGraphLine (hWndGraph) ;
                    177: 
                    178:    if (!pCurrentGraphLine || pCurrentGraphLine->bFirstTime)
                    179:       {
                    180:       // we have not collect enough samples
                    181:       return ;
                    182:       }
                    183: 
                    184:    KnownValue = pGraph->gKnownValue ;
                    185:    MaxValues = pGraph->gMaxValues ;
                    186: 
                    187:    // The valid values is the number of valid entries in the
                    188:    // data buffer.  After we wrap the buffer, all the values are
                    189:    // valid.
                    190:    iValidValues = pGraph->gTimeLine.iValidValues ;
                    191: 
                    192:    // Get the index to the data point we are updating.
                    193: 
                    194:    iDataPoint = KnownValue % MaxValues ;
                    195:    eValue = pCurrentGraphLine->lnValues[iDataPoint] ;
                    196: 
                    197:    // get the statistical data for this line
                    198:    eUpdateMinMaxAve(eValue, pCurrentGraphLine,
                    199:       iValidValues, pCurrentGraphLine->lnValidValues,
                    200:       iDataPoint, MaxValues) ;
                    201:    }  // UpdateValueBarData
                    202: 
                    203: 
                    204: VOID UpdateLGData (PGRAPHSTRUCT pGraph)
                    205:    {
                    206:    PLINESTRUCT    pLine ;               
                    207:    PLINESTRUCT    pCurrentGraphLine ;   
                    208:    INT            KnownValue,
                    209:                   MaxValues,
                    210:                   iValidValues,
                    211:                   iDataPoint ;
                    212:    FLOAT          eValue ;
                    213:    // Known Value is the where data is placed in the buffer.
                    214:    pGraph->gKnownValue++;
                    215: 
                    216:    KnownValue = pGraph->gKnownValue ;
                    217: 
                    218:    // Update the high water mark for valid data in the lnValues
                    219:    // (aka DataPoint) buffer.
                    220: 
                    221: 
                    222:    MaxValues = pGraph->gMaxValues ;
                    223: 
                    224:    // The valid values is the number of valid entries in the
                    225:    // data buffer.  After we wrap the buffer, all the values are
                    226:    // valid.
                    227:    iValidValues = pGraph->gTimeLine.iValidValues ;
                    228: 
                    229:    if (iValidValues < MaxValues)
                    230:        iValidValues = (KnownValue % MaxValues) + 1 ;
                    231: 
                    232:    pGraph->gTimeLine.iValidValues = iValidValues ;
                    233: 
                    234:    // Get the index to the data point we are updating.
                    235: 
                    236:    iDataPoint = KnownValue % MaxValues ;
                    237: 
                    238:    // loop through lines,
                    239:    // If one of the lines is highlighted then do the calculations
                    240:    // for average, min, & max on that line.
                    241: 
                    242:    pCurrentGraphLine = CurrentGraphLine (hWndGraph) ;
                    243: 
                    244:    for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
                    245:      { // for
                    246: 
                    247:      if (pLine->bFirstTime)
                    248:          {
                    249:          // skip until we have collect enough samples to plot the first data
                    250:          continue ;
                    251:          }
                    252: 
                    253:      if (pLine->lnValidValues < MaxValues)
                    254:          {   
                    255:          (pLine->lnValidValues)++ ;
                    256:          }
                    257:    
                    258:      // Get the new value for this line.
                    259:      eValue = (*(pLine->valNext))(pLine) ;
                    260: 
                    261:      if (pLine == pCurrentGraphLine)
                    262:         {  // if
                    263:         // get the statistical data for this line
                    264:         eUpdateMinMaxAve (eValue, pLine, 
                    265:                                  iValidValues, pLine->lnValidValues,
                    266:                                  iDataPoint, MaxValues) ;
                    267:         }  // if
                    268:       
                    269:      // Now put the new value into the data array
                    270:      pLine->lnValues[iDataPoint] = eValue ;
                    271:      }
                    272:    
                    273:    GetLocalTime (&(pGraph->pDataTime[iDataPoint])) ; 
                    274:    }  // UpdateLGData
                    275: 
                    276: 
                    277: 
                    278: BOOL HandleGraphTimer (void)
                    279:    {
                    280:    PGRAPHSTRUCT pGraph;
                    281: 
                    282:    //NOTE: get a strategy for these "no-go" states
                    283:    if (!(pGraph = pGraphs) || !pGraphs->pSystemFirst)
                    284:        return(FALSE);
                    285: 
                    286: 
                    287:    if (!UpdateLines(&(pGraphs->pSystemFirst), pGraphs->pLineFirst))
                    288:         return (TRUE) ;
                    289: 
                    290:    UpdateLGData(pGraph);
                    291: 
                    292:    return(TRUE);
                    293:    }
                    294: 
                    295: 
                    296: VOID ClearGraphTimer(PGRAPHSTRUCT pGraph)
                    297:    {
                    298:    KillTimer(pGraph->hWnd, GRAPH_TIMER_ID);
                    299:    }
                    300: 
                    301: 
                    302: VOID SetGraphTimer(PGRAPHSTRUCT pGraph)
                    303:    {
                    304:    SetTimer(pGraph->hWnd, GRAPH_TIMER_ID, pGraph->gInterval, NULL) ;
                    305:    }
                    306: 
                    307: VOID ResetGraphTimer(PGRAPHSTRUCT pGraph)
                    308: {
                    309:     KillTimer(pGraph->hWnd, GRAPH_TIMER_ID);
                    310:     SetGraphTimer(pGraph);
                    311: }
                    312: 
                    313: 
                    314: VOID GetGraphConfig(PGRAPHSTRUCT pGraph)
                    315: {
                    316: 
                    317:     LoadRefreshSettings(pGraph);
                    318:     LoadLineGraphSettings(pGraph);
                    319: 
                    320: 
                    321:     // Init the structure
                    322:     pGraph->pLineFirst = NULL;
                    323: 
                    324:     //NOTE: put the rest of this in Config
                    325: 
                    326:     pGraph->gOptions.bLegendChecked    = TRUE;
                    327:     pGraph->gOptions.bMenuChecked      = TRUE;
                    328:     pGraph->gOptions.bLabelsChecked    = TRUE;
                    329:     pGraph->gOptions.bVertGridChecked  = FALSE;
                    330:     pGraph->gOptions.bHorzGridChecked  = FALSE;
                    331:     pGraph->gOptions.bStatusBarChecked = TRUE;
                    332:     pGraph->gOptions.GraphVGrid        = TRUE;
                    333:     pGraph->gOptions.GraphHGrid        = TRUE;
                    334:     pGraph->gOptions.HistVGrid         = TRUE;
                    335:     pGraph->gOptions.HistHGrid         = TRUE;
                    336: 
                    337:     pGraph->gOptions.iGraphOrHistogram = LINE_GRAPH;       // vs. BAR_GRAPH
                    338:     pGraph->gOptions.iVertMax = DEF_GRAPH_VMAX;
                    339: 
                    340:     return;
                    341: }
                    342: 
                    343: 
                    344: BOOL InsertGraph (HWND hWnd)
                    345:    {
                    346:    PGRAPHSTRUCT    pGraph;
                    347: 
                    348:    pGraph = MemoryAllocate (sizeof (GRAPHSTRUCT)) ;
                    349:    if (!pGraph)
                    350:       return (FALSE) ;
                    351: 
                    352: 
                    353:    pGraphs = pGraph;
                    354: 
                    355:    
                    356:    GetGraphConfig(pGraph);
                    357:    pGraph->bManualRefresh = FALSE ;
                    358: 
                    359:    pGraph->gMaxValues = DEFAULT_MAX_VALUES;
                    360:    pGraph->pptDataPoints = 
                    361:       (PPOINT) MemoryAllocate (sizeof (POINT) * pGraph->gMaxValues) ;
                    362: 
                    363:    pGraph->pDataTime =
                    364:       (SYSTEMTIME *) MemoryAllocate (sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
                    365: 
                    366:    pGraph->hWnd = hWnd ;
                    367:    pGraph->bModified = FALSE ;
                    368: 
                    369:    pGraph->Visual.iColorIndex = 0 ;
                    370:    pGraph->Visual.iWidthIndex = 0 ;
                    371:    pGraph->Visual.iStyleIndex = 0 ;
                    372: 
                    373:    return(TRUE) ;
                    374:    }
                    375: 
                    376: 
                    377: 
                    378: void PlaybackSetGraphLines (HWND hWndChart, 
                    379:                             PLINE pLineFirst, 
                    380:                             int iDisplayTic,
                    381:                             int iLogTic,
                    382:                             BOOL CalcData)
                    383:    {
                    384:    PLINE          pLine ;
                    385:    FLOAT          eValue ;
                    386: 
                    387:    for (pLine = pLineFirst ;
                    388:         pLine ;
                    389:         pLine = pLine->pLineNext)
                    390:       {  // for
                    391:       eValue = (*(pLine->valNext))(pLine) ;
                    392:       pLine->lnValues[iDisplayTic] = eValue ;
                    393:       pLine->aiLogIndexes[iDisplayTic] = iLogTic ;
                    394: 
                    395:       // only need to do this on request.
                    396:       if (CalcData)
                    397:          {
                    398:          eUpdateMinMaxAve (eValue, pLine, iDisplayTic, iDisplayTic,
                    399:             iDisplayTic, iDisplayTic) ;
                    400:          }  // if
                    401:       }  // for
                    402:    }  // PlaybackSetGraphLines
                    403: 
                    404: 
                    405: 
                    406: BOOL ChartInsertLine (PGRAPHSTRUCT pGraph, 
                    407:                       PLINE pLine)
                    408: /*
                    409:    Effect:        Insert the line pLine into the graph pGraph and 
                    410:                   allocate space for the graph's number of values.
                    411: 
                    412:    Returns:       Whether the line could be added and space allocated.
                    413: 
                    414:    See Also:      LineAllocate (line.c), ChartDeleteLine.
                    415: */
                    416:    {  // ChartInsertLine
                    417:    PLINE          pLineEquivalent ;
                    418:    INT            i ;
                    419:    FLOAT          *pTempPts;
                    420:    HPEN           tempPen ;
                    421: 
                    422:    pGraph->bModified = TRUE ;
                    423: 
                    424:    pLineEquivalent = FindEquivalentLine (pLine, pGraph->pLineFirst) ;
                    425:    if (pLineEquivalent)
                    426:       {
                    427:       pLineEquivalent->Visual = pLine->Visual ;
                    428:       pLineEquivalent->iScaleIndex = pLine->iScaleIndex ;
                    429:       pLineEquivalent->eScale = pLine->eScale ;
                    430: 
                    431:       tempPen = pLineEquivalent->hPen ;
                    432:       pLineEquivalent->hPen =  pLine->hPen ;
                    433:       pLine->hPen = tempPen ;
                    434:       return FALSE ;
                    435:       }
                    436:    else
                    437:       {
                    438:       if (!pGraph->pLineFirst && !PlayingBackLog())
                    439:          {
                    440:          SetGraphTimer (pGraph) ;
                    441:          }
                    442: 
                    443:       if (!SystemAdd (&pGraph->pSystemFirst, pLine->lnSystemName))
                    444:         return FALSE;
                    445: 
                    446:       LineAppend (&pGraph->pLineFirst, pLine) ;
                    447: 
                    448:       pLine->lnMinValue = FLT_MAX ;
                    449:       pLine->lnMaxValue = - FLT_MAX ;
                    450:       pLine->lnAveValue = 0.0F ;
                    451:       pLine->lnValidValues = 0 ;
                    452: 
                    453:       pLine->lnValues = 
                    454:          (FLOAT *) MemoryAllocate (sizeof (FLOAT) * pGraph->gMaxValues) ;
                    455:       
                    456:       for (i = pGraph->gMaxValues, pTempPts = pLine->lnValues ;
                    457:            i > 0 ;
                    458:            i-- )
                    459:          {
                    460:          *pTempPts++ = (FLOAT) 0.0 ;
                    461:          }
                    462: 
                    463:       if (PlayingBackLog ())
                    464:          {
                    465:          pLine->aiLogIndexes =
                    466:             (int *) MemoryAllocate (sizeof (LONG) * pGraph->gMaxValues) ;
                    467:          }
                    468: 
                    469:       // Add the line to the legend, resize the legend window, and then
                    470:       // select the new line as the current legend item. Do it in this 
                    471:       // sequence to avoid the legend scroll bar momentarily appearing and
                    472:       // then disappearing, since the resize will obviate the scroll bar.
                    473: 
                    474:       LegendAddItem (hWndGraphLegend, pLine) ;
                    475: 
                    476:       if (!bDelayAddAction)
                    477:          {
                    478:          SizeGraphComponents (hWndGraph) ;
                    479:          LegendSetSelection (hWndGraphLegend, 
                    480:                           LegendNumItems (hWndGraphLegend) - 1) ;
                    481: 
                    482:          if (PlayingBackLog ())
                    483:             PlaybackChart (pGraph->hWnd) ;
                    484:          }
                    485:       }
                    486: 
                    487:    return (TRUE) ;
                    488:    }  // ChartInsertLine
                    489: 
                    490: 
                    491: VOID ChartDeleteLine (PGRAPHSTRUCT pGraph, 
                    492:                       PLINESTRUCT pLine)
                    493:    {
                    494:    PLINESTRUCT npLine;
                    495: 
                    496: 
                    497:    pGraph->bModified = TRUE ;
                    498: 
                    499:    if (pGraph->pLineFirst == pLine)
                    500:        pGraph->pLineFirst = pLine->pLineNext;
                    501:    else
                    502:    {
                    503:        for (npLine = pGraph->pLineFirst; npLine; npLine = npLine->pLineNext)
                    504:        {
                    505:            if (npLine->pLineNext == pLine)
                    506:                npLine->pLineNext = pLine->pLineNext;
                    507:        }
                    508:    }
                    509: 
                    510:    if (!pGraph->pLineFirst)
                    511:       {
                    512:       ResetGraph (pGraph) ;
                    513:       }
                    514:    else
                    515:       {
                    516:       BuildNewValueListForGraph () ;
                    517:       }
                    518: 
                    519:    // Delete the legend entry for this line.
                    520:    // If the line was highlighted then this will undo the highlight.
                    521: 
                    522:    LegendDeleteItem (hWndGraphLegend, pLine) ;
                    523: 
                    524:    LineFree (pLine) ;
                    525: 
                    526:    SizeGraphComponents (hWndGraph) ;
                    527: 
                    528: 
                    529:    }
                    530: 
                    531: 
                    532: FLOAT Counter_Queuelen(PLINESTRUCT pLine)
                    533: {
                    534: 
                    535:     return((FLOAT)0.0);
                    536: //    pLine;
                    537: }
                    538: 
                    539: 
                    540: void ClearGraphDisplay (PGRAPHSTRUCT pGraph)
                    541:    {
                    542:    PLINESTRUCT    pLine;
                    543: 
                    544:    // reset the timeline data
                    545:    pGraph->gKnownValue = -1 ;
                    546:    pGraph->gTimeLine.iValidValues = 0 ;
                    547:    pGraph->gTimeLine.xLastTime = 0 ;
                    548:    memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
                    549: 
                    550:    // loop through lines,
                    551:    // If one of the lines is highlighted then do the calculations
                    552:    // for average, min, & max on that line.
                    553: 
                    554:    for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
                    555:       { // for
                    556: 
                    557:       pLine->bFirstTime = 2 ;
                    558:       pLine->lnMinValue = FLT_MAX ;
                    559:       pLine->lnMaxValue = - FLT_MAX ;
                    560:       pLine->lnAveValue = 0.0F ;
                    561:       pLine->lnValidValues = 0 ;
                    562:       memset (pLine->lnValues, 0, sizeof(FLOAT) * pGraph->gMaxValues) ;
                    563:       }
                    564: 
                    565:    StatusTimer (hWndGraphStatus, TRUE) ;
                    566:    WindowInvalidate (hWndGraphDisplay) ;
                    567:    }
                    568: 
                    569: void ResetGraphView (HWND hWndGraph)
                    570:    {
                    571:    PGRAPHSTRUCT      pGraph ;
                    572: 
                    573:    pGraph = GraphData (hWndGraph) ;
                    574: 
                    575: 
                    576:    if (!pGraph)
                    577:       {
                    578:       return ;
                    579:       }
                    580: 
                    581:    ChangeSaveFileName (NULL, IDM_VIEWCHART) ;
                    582: 
                    583:    if (pGraph->pSystemFirst)
                    584:       {
                    585:       ResetGraph (pGraph) ;
                    586:       }
                    587:    }  // ResetGraphView
                    588: 
                    589: void ResetGraph (PGRAPHSTRUCT pGraph)
                    590:    {
                    591:    ClearGraphTimer (pGraph) ;
                    592:    ClearLegend (hWndGraphLegend) ;
                    593:    if (pGraph->pLineFirst)
                    594:       {
                    595:       FreeLines (pGraph->pLineFirst) ;
                    596:       pGraph->pLineFirst = NULL ;
                    597:       }
                    598: 
                    599:    if (pGraph->pSystemFirst)
                    600:       {
                    601:       FreeSystems (pGraph->pSystemFirst) ;
                    602:       pGraph->pSystemFirst = NULL ;
                    603:       }
                    604: 
                    605:    pGraph->gKnownValue = -1 ;
                    606:    pGraph->gTimeLine.iValidValues = 0 ;
                    607:    pGraph->gTimeLine.xLastTime = 0 ;
                    608: 
                    609:    // reset visual data
                    610:    pGraph->Visual.iColorIndex = 0 ;
                    611:    pGraph->Visual.iWidthIndex = 0 ;
                    612:    pGraph->Visual.iStyleIndex = 0 ;
                    613: 
                    614:    memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
                    615: 
                    616:    SizeGraphComponents (hWndGraph) ;
                    617:    InvalidateRect(hWndGraph, NULL, TRUE) ;
                    618:    }
                    619: 
                    620: 
                    621: 
                    622: void PlaybackChart (HWND hWndChart)
                    623:    {  // PlaybackChart
                    624:    int            iDisplayTics ;       // num visual points to display
                    625:    int            iDisplayTic ;
                    626:    int            iLogTic ;
                    627:    int            iLogTicsMove ;
                    628:    BOOL           bFirstTime = TRUE;
                    629:    int            iLogTicsRemaining ;
                    630: 
                    631:    if (!pGraphs->pLineFirst)
                    632:       {
                    633:       // no line to playback
                    634:       return ;
                    635:       }
                    636: 
                    637:    iLogTicsRemaining = PlaybackLog.iSelectedTics ;
                    638: 
                    639: 
                    640:    // we only have iDisplayTics-1 points since
                    641:    // we have to use the first two sample points to
                    642:    // get the first data points.
                    643:    if (iLogTicsRemaining <= pGraphs->gMaxValues)
                    644:       {
                    645:       iDisplayTics = iLogTicsRemaining ;
                    646:       pGraphs->gTimeLine.iValidValues = iDisplayTics - 1 ;
                    647:       }
                    648:    else
                    649:       {
                    650:       iDisplayTics = pGraphs->gMaxValues ;
                    651:       pGraphs->gTimeLine.iValidValues = iDisplayTics ;
                    652:       }
                    653: 
                    654:    iDisplayTic = -1 ;
                    655:    iLogTic = PlaybackLog.StartIndexPos.iPosition ;
                    656: 
                    657:    while (iDisplayTics)
                    658:       {
                    659: 
                    660:       PlaybackLines (pGraphs->pSystemFirst, 
                    661:                      pGraphs->pLineFirst, 
                    662:                      iLogTic) ;
                    663: 
                    664:       if (bFirstTime)
                    665:          {
                    666:          bFirstTime = FALSE ;
                    667: 
                    668:          // get the second sample data to form the first data point
                    669:          iLogTic++ ;
                    670:          iLogTicsRemaining-- ;
                    671:          PlaybackLines (pGraphs->pSystemFirst, 
                    672:                         pGraphs->pLineFirst, 
                    673:                         iLogTic) ;
                    674:          }
                    675:       iDisplayTic++ ;
                    676:       PlaybackSetGraphLines (hWndChart, pGraphs->pLineFirst, 
                    677:          iDisplayTic, iLogTic, (iDisplayTics == 1)) ;
                    678: 
                    679:       // setup DDA to get the index of the next sample point
                    680:       iLogTicsMove = DDA_DISTRIBUTE (iLogTicsRemaining, iDisplayTics) ;
                    681:       iLogTicsRemaining -= iLogTicsMove ;
                    682:       iLogTic += iLogTicsMove ;
                    683: 
                    684:       iDisplayTics-- ;
                    685: 
                    686:       }  // while
                    687: 
                    688:    // point to the last value for valuebar display
                    689:    pGraphs->gKnownValue = iDisplayTic ;
                    690: 
                    691:    }  // PlaybackChart
                    692: 
                    693: 
                    694: 
                    695: #if 0
                    696: PLINESTRUCT CurrentGraphLine (HWND hWndGraph)
                    697:    {  // CurrentGraphLine
                    698:    UNREFERENCED_PARAMETER (hWndGraph) ;
                    699: 
                    700:    return (LegendCurrentLine (hWndGraphLegend)) ;
                    701:    }
                    702: #endif
                    703: 
                    704: 
                    705: BOOL AddChart (HWND hWndParent)
                    706:    {
                    707:    return (AddLine (hWndParent, 
                    708:                     &(pGraphs->pSystemFirst), 
                    709:                     &(pGraphs->Visual), 
                    710:                     LineTypeChart)) ;
                    711:    }
                    712: 
                    713: 
                    714: BOOL EditChart (HWND hWndParent)
                    715:    {  // EditChart
                    716:    return (EditLine (hWndParent, 
                    717:                      &(pGraphs->pSystemFirst), 
                    718:                      CurrentGraphLine (hWndGraph),
                    719:                      LineTypeChart)) ;
                    720:    }
                    721: 
                    722: 
                    723: BOOL QuerySaveChart (HWND hWndParent, PGRAPHSTRUCT pGraph)
                    724: /*
                    725:    Effect:        If the graph pGraph is modified, put up a message
                    726:                   box allowing the user to save the current graph.
                    727:                   
                    728:                   Return whether the caller should proceed to load in
                    729:                   a new or otherwise trash the current graph.
                    730: */
                    731:    {  // QuerySaveChart
                    732: #ifdef KEEP_QUERY
                    733:    int            iReturn ;
                    734: 
                    735:    if (!pGraph->bModified)
                    736:       return (TRUE) ;
                    737: 
                    738:    iReturn = MessageBoxResource (hWndParent, 
                    739:                                  IDS_SAVECHART, IDS_MODIFIEDCHART,
                    740:                                  MB_YESNOCANCEL | MB_ICONASTERISK) ;
                    741: 
                    742:    if (iReturn == IDCANCEL)
                    743:       return (FALSE) ;
                    744: 
                    745:    if (iReturn == IDYES)
                    746:       SaveChart (hWndGraphs, 0, 0) ;
                    747:    return (TRUE) ;
                    748: #endif
                    749:    return (TRUE) ;  // we don't want to query nor save change
                    750: 
                    751:    }  // QuerySaveChart
                    752: 
                    753: void GraphAddAction ()
                    754:    {
                    755:    PGRAPHSTRUCT      pGraph ;
                    756: 
                    757:    pGraph = GraphData (hWndGraph) ;
                    758: 
                    759:    SizeGraphComponents (hWndGraph) ;
                    760:    
                    761:    LegendSetSelection (hWndGraphLegend,
                    762:       LegendNumItems (hWndGraphLegend) - 1) ;
                    763: 
                    764:    if (PlayingBackLog ())
                    765:       PlaybackChart (pGraph->hWnd) ;
                    766:    }
                    767: 
                    768: BOOL OpenChartVer1 (HANDLE hFile,
                    769:                     DISKCHART *pDiskChart,
                    770:                     PGRAPHSTRUCT pGraph)
                    771:    {  // OpenChartVer1
                    772:    bDelayAddAction = TRUE ;
                    773:    pGraph->Visual = pDiskChart->Visual ;
                    774:    pGraph->gOptions = pDiskChart->gOptions ;
                    775:    pGraph->gMaxValues = pDiskChart->gMaxValues ;
                    776:    pGraph->bManualRefresh = pDiskChart->bManualRefresh ;
                    777:    pGraphs->gInterval = (INT) (pGraph->gOptions.eTimeInterval * (FLOAT) 1000.0) ;
                    778:    ReadLines (hFile, pDiskChart->dwNumLines,
                    779:                &(pGraph->pSystemFirst), &(pGraph->pLineFirst), IDM_VIEWCHART) ;
                    780:    
                    781:    bDelayAddAction = FALSE ;
                    782: 
                    783:    GraphAddAction () ;
                    784: 
                    785:    return (TRUE) ;
                    786:    }  // OpenChartVer1
                    787: 
                    788: 
                    789: 
                    790: BOOL OpenChart (HWND hWndGraph,
                    791:                 HANDLE hFile,
                    792:                 DWORD dwMajorVersion,
                    793:                 DWORD dwMinorVersion,
                    794:                 BOOL bChartFile)
                    795:    {  // OpenChart
                    796:    PGRAPHSTRUCT   pGraph ;
                    797:    DISKCHART      DiskChart ;
                    798:    BOOL           bSuccess = TRUE ;
                    799: 
                    800:    pGraph = pGraphs ;
                    801:    if (!pGraph)
                    802:       {
                    803:       bSuccess = FALSE ;
                    804:       goto Exit0 ;
                    805:       }
                    806: 
                    807:    if (!FileRead (hFile, &DiskChart, sizeof (DISKCHART)))
                    808:       {
                    809:       bSuccess = FALSE ;
                    810:       goto Exit0 ;
                    811:       }
                    812: 
                    813: 
                    814:    switch (dwMajorVersion)
                    815:       {
                    816:       case (1):
                    817: 
                    818:          SetHourglassCursor() ;
                    819:          
                    820:          ResetGraphView (hWndGraph) ;
                    821: 
                    822:          OpenChartVer1 (hFile, &DiskChart, pGraph) ;
                    823: 
                    824:          // change to chart view if we are opening a 
                    825:          // chart file
                    826:          if (bChartFile && iPerfmonView != IDM_VIEWCHART)
                    827:             {
                    828:             SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWCHART, 0L) ;
                    829:             }
                    830: 
                    831:          if (iPerfmonView == IDM_VIEWCHART)
                    832:             {
                    833:             SetPerfmonOptions (&DiskChart.perfmonOptions) ;
                    834:             }
                    835:          
                    836:          SetArrowCursor() ;
                    837: 
                    838:          break ;
                    839:       }  // switch
                    840: 
                    841: Exit0:
                    842: 
                    843:    if (bChartFile)
                    844:       {
                    845:       CloseHandle (hFile) ;
                    846:       }
                    847: 
                    848:    return (bSuccess) ;
                    849:    }  // OpenChart
                    850: 
                    851: BOOL SaveChart (HWND hWndGraph, HANDLE hInputFile, BOOL bGetFileName)
                    852:    {
                    853:    PGRAPHSTRUCT   pGraph ;
                    854:    PLINE          pLine ;
                    855:    HANDLE         hFile ;
                    856:    DISKCHART      DiskChart ;
                    857:    PERFFILEHEADER FileHeader ;
                    858:    TCHAR          szFileName [256] ;
                    859:    BOOL           newFileName = FALSE ;
                    860: 
                    861:    if (hInputFile)
                    862:       {
                    863:       // use the input file handle if it is available
                    864:       // this is the case for saving workspace data
                    865:       hFile = hInputFile ;
                    866:       }
                    867:    else
                    868:       {
                    869:       if (pChartFullFileName)
                    870:          {
                    871:          lstrcpy (szFileName, pChartFullFileName) ;
                    872:          }
                    873:       if (bGetFileName || pChartFullFileName == NULL)
                    874:          {
                    875: //         if (!pChartFullFileName)
                    876: //            {
                    877: //            StringLoad (IDS_GRAPH_FNAME, szFileName) ;
                    878: //            }
                    879: 
                    880:          if (!FileGetName (hWndGraph, IDS_CHARTFILE, szFileName))
                    881:             {
                    882:             return (FALSE) ;
                    883:             }
                    884:          newFileName = TRUE ;
                    885:          }
                    886: 
                    887:       hFile = FileHandleCreate (szFileName) ;
                    888: 
                    889:       if (hFile && newFileName)
                    890:          {
                    891:          ChangeSaveFileName (szFileName, IDM_VIEWCHART) ;
                    892:          }
                    893:       else if (!hFile)
                    894:          {
                    895:          DlgErrorBox (hWndGraph, ERR_CANT_OPEN, szFileName) ;
                    896:          }
                    897:       }
                    898: 
                    899:    if (!hFile)
                    900:       return (FALSE) ;
                    901: 
                    902:    pGraph = pGraphs ;
                    903:    if (!pGraph)
                    904:       {
                    905:       if (!hInputFile)
                    906:          {
                    907:          CloseHandle (hFile) ;
                    908:          }
                    909:       return (FALSE) ;
                    910:       }
                    911: 
                    912:    if (!hInputFile)
                    913:       {
                    914:       // only need to write file header if not workspace 
                    915:       memset (&FileHeader, 0, sizeof (FileHeader)) ;
                    916:       lstrcpy (FileHeader.szSignature, szPerfChartSignature) ;
                    917:       FileHeader.dwMajorVersion = ChartMajorVersion ;
                    918:       FileHeader.dwMinorVersion = ChartMinorVersion ;
                    919:    
                    920:       if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
                    921:          {
                    922:          goto Exit0 ;
                    923:          }
                    924:       }
                    925: 
                    926:    DiskChart.Visual = pGraph->Visual ;
                    927:    DiskChart.gOptions = pGraph->gOptions ;
                    928:    DiskChart.gMaxValues = pGraph->gMaxValues ;
                    929:    DiskChart.dwNumLines = NumLines (pGraph->pLineFirst) ;
                    930:    DiskChart.bManualRefresh = pGraph->bManualRefresh ;
                    931:    DiskChart.perfmonOptions = Options ;
                    932: 
                    933:    if (!FileWrite (hFile, &DiskChart, sizeof (DISKCHART)))
                    934:       {
                    935:       goto Exit0 ;
                    936:       }
                    937: 
                    938:    for (pLine = pGraph->pLineFirst ;
                    939:         pLine ;
                    940:         pLine = pLine->pLineNext)
                    941:       {  // for
                    942:       if (!WriteLine (pLine, hFile))
                    943:          {
                    944:          goto Exit0 ;
                    945:          }
                    946:       }  // for
                    947: 
                    948:    if (!hInputFile)
                    949:       {
                    950:       CloseHandle (hFile) ;
                    951:       }
                    952: 
                    953:    return (TRUE) ;
                    954: 
                    955: Exit0:
                    956:    if (!hInputFile)
                    957:       {
                    958:       CloseHandle (hFile) ;
                    959: 
                    960:       // only need to report error if not workspace 
                    961:       DlgErrorBox (hWndGraph, ERR_SETTING_FILE, szFileName) ;
                    962:       }
                    963:    return (FALSE) ;
                    964: 
                    965:    }  // SaveChart
                    966: 
                    967: #define TIME_TO_WRITE 6
                    968: BOOL ExportChartLabels (HANDLE hFile, PGRAPHSTRUCT pGraph)
                    969: {
                    970:    TCHAR          UnicodeBuff [MiscTextLen] ;
                    971:    CHAR           TempBuff [LongTextLen] ;
                    972:    int            StringLen ;
                    973:    PLINESTRUCT    pLine;
                    974:    int            TimeToWriteFile ;
                    975:    int            iIndex ;
                    976:    LPTSTR         lpItem ;
                    977: 
                    978:    for (iIndex = 0 ; iIndex < 5 ; iIndex++)
                    979:       {
                    980:       // for iIndex == 0, get counter name 
                    981:       // for iIndex == 1, get instance name
                    982:       // for iIndex == 2, get parent name
                    983:       // for iIndex == 3, get object name 
                    984:       // for iIndex == 4, get computer name
                    985:       if (iIndex == 4)
                    986:          {
                    987:          // the last label field, write date/time labels
                    988:          strcpy (TempBuff, LineEndStr) ;
                    989:          StringLen = strlen (TempBuff) ;
                    990:          StringLoad (IDS_EXPORT_DATE, UnicodeBuff) ;
                    991:          ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                    992:          strcat (TempBuff, pDelimiter) ;
                    993:          StringLen = strlen (TempBuff) ;
                    994:       
                    995:          StringLoad (IDS_EXPORT_TIME, UnicodeBuff) ;
                    996:          ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                    997:          strcat (TempBuff, pDelimiter) ;
                    998:          StringLen = strlen (TempBuff) ;
                    999:          }
                   1000:       else
                   1001:          {
                   1002:          strcpy (TempBuff, LineEndStr) ;
                   1003:          strcat (TempBuff, pDelimiter) ;
                   1004:          strcat (TempBuff, pDelimiter) ;
                   1005:          StringLen = strlen (TempBuff) ;
                   1006:          }
                   1007: 
                   1008:       TimeToWriteFile = 0 ;
                   1009: 
                   1010:       for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
                   1011:          {
                   1012:          switch (iIndex)
                   1013:             {
                   1014:             case 0:
                   1015:                lpItem = (LPTSTR) pLine->lnCounterName ;
                   1016:                break ;
                   1017: 
                   1018:             case 1:
                   1019:                lpItem = (LPTSTR) pLine->lnInstanceName ;
                   1020:                break ;
                   1021: 
                   1022:             case 2:
                   1023:                lpItem = (LPTSTR) pLine->lnPINName ;
                   1024:                break ;
                   1025: 
                   1026:             case 3:
                   1027:                lpItem = (LPTSTR) pLine->lnObjectName ;
                   1028:                break ;
                   1029: 
                   1030:             case 4:
                   1031:                lpItem = (LPTSTR) pLine->lnSystemName ;
                   1032:                break ;
                   1033:             }
                   1034: 
                   1035:          if (lpItem)
                   1036:             {
                   1037:             ConvertUnicodeStr (&TempBuff[StringLen], lpItem) ;
                   1038:             }
                   1039:          else
                   1040:             {
                   1041:             TempBuff[StringLen] = '\0' ;
                   1042:             }
                   1043:          strcat (TempBuff, pDelimiter);
                   1044:          StringLen = strlen (TempBuff) ;
                   1045:    
                   1046:          if (++TimeToWriteFile > TIME_TO_WRITE)
                   1047:             {
                   1048:             // better write the buffers before they overflow.
                   1049:             // there are better ways to check for overflow 
                   1050:             // but this is good enough
                   1051:    
                   1052:             if (!FileWrite (hFile, TempBuff, StringLen))
                   1053:                {
                   1054:                goto Exit0 ;
                   1055:                }
                   1056:             StringLen = TimeToWriteFile = 0 ;
                   1057:             }
                   1058:          }     // for each line
                   1059: 
                   1060:       if (StringLen)
                   1061:          {
                   1062:          // write the last block of data
                   1063:          if (!FileWrite (hFile, TempBuff, StringLen))
                   1064:             {
                   1065:             goto Exit0 ;
                   1066:             }
                   1067:          }
                   1068:       }     // for iIndex
                   1069: 
                   1070:    return (TRUE) ;
                   1071: 
                   1072: Exit0:
                   1073:    return (FALSE) ;
                   1074: 
                   1075: }  // ExportChartLabels
                   1076: 
                   1077: BOOL ExportLogChart (HANDLE hFile, PGRAPHSTRUCT pGraph)
                   1078: {
                   1079:    TCHAR          UnicodeBuff [MiscTextLen] ;
                   1080:    CHAR           TempBuff [LongTextLen] ;
                   1081:    int            StringLen ;
                   1082:    PLINESTRUCT    pLine;
                   1083:    int            TimeToWriteFile ;
                   1084:    FLOAT          eValue ;
                   1085:    int            iLogTic ;
                   1086:    BOOL           bFirstTime = TRUE ;
                   1087:    SYSTEMTIME     LogSystemTime ;
                   1088:    LOGPOSITION    LogPosition ;
                   1089: 
                   1090:    iLogTic = PlaybackLog.StartIndexPos.iPosition ;
                   1091: 
                   1092:    // we have to export every point from the log file 
                   1093: 
                   1094:    for ( ; iLogTic <= PlaybackLog.StopIndexPos.iPosition ; iLogTic++)
                   1095:       {
                   1096: 
                   1097:       PlaybackLines (pGraphs->pSystemFirst, 
                   1098:                      pGraphs->pLineFirst, 
                   1099:                      iLogTic) ;
                   1100: 
                   1101:       if (!bFirstTime)
                   1102:          {
                   1103:          // export the values
                   1104:          TimeToWriteFile = 0 ;
                   1105: 
                   1106:          
                   1107:          if (!LogPositionN (iLogTic, &LogPosition))
                   1108:             {
                   1109:             goto Exit0 ;
                   1110:             }
                   1111: 
                   1112:          LogPositionSystemTime (&LogPosition, &LogSystemTime) ;
                   1113: 
                   1114:          strcpy (TempBuff, LineEndStr) ;
                   1115:          StringLen = strlen (TempBuff) ;
                   1116: 
                   1117:          SystemTimeDateString (&LogSystemTime, UnicodeBuff) ;
                   1118:          ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                   1119:          strcat (TempBuff, pDelimiter) ;
                   1120:          StringLen = strlen (TempBuff) ;
                   1121: 
                   1122:          SystemTimeTimeString (&LogSystemTime, UnicodeBuff) ;
                   1123:          ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                   1124:          strcat (TempBuff, pDelimiter) ;
                   1125:          StringLen = strlen (TempBuff) ;
                   1126: 
                   1127:          for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
                   1128:             {
                   1129:       
                   1130:             eValue = (*(pLine->valNext))(pLine) ;
                   1131: 
                   1132:             TSPRINTF (UnicodeBuff,
                   1133:                       eValue > (FLOAT)999999.0 ?
                   1134:                            szLargeValueFormat : szSmallValueFormat,
                   1135:                       eValue) ;
                   1136:             ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                   1137:             strcat (TempBuff, pDelimiter) ;
                   1138:             StringLen = strlen (TempBuff) ;
                   1139: 
                   1140:             if (++TimeToWriteFile > TIME_TO_WRITE)
                   1141:                {
                   1142:                if (!FileWrite (hFile, TempBuff, StringLen))
                   1143:                   {
                   1144:                   goto Exit0 ;
                   1145:                   }
                   1146:                StringLen = TimeToWriteFile = 0 ;
                   1147:                TempBuff[0] = '\0' ;
                   1148:                }
                   1149:             }
                   1150: 
                   1151:          if (StringLen)
                   1152:             {
                   1153:             if (!FileWrite (hFile, TempBuff, StringLen))
                   1154:                {
                   1155:                goto Exit0 ;
                   1156:                }
                   1157:             }
                   1158:          }
                   1159:       else
                   1160:          {
                   1161:          // skip the first data point since we
                   1162:          // need 2 points to form the first value
                   1163:          bFirstTime = FALSE ;
                   1164:          }
                   1165:       }
                   1166: 
                   1167:    return (TRUE) ;
                   1168: 
                   1169: Exit0:
                   1170:    return (FALSE) ;
                   1171: 
                   1172: }  // ExportLogChart
                   1173: 
                   1174: BOOL ExportLineValue (HANDLE hFile, PGRAPHSTRUCT pGraph,
                   1175:    int CurrentIndex, int iDataPoint)
                   1176: {
                   1177:    TCHAR          UnicodeBuff [MiscTextLen] ;
                   1178:    CHAR           TempBuff [LongTextLen] ;
                   1179:    int            StringLen ;
                   1180:    PLINESTRUCT    pLine;
                   1181:    int            MaxValues ;
                   1182:    int            TimeToWriteFile ;
                   1183:    SYSTEMTIME     *pSystemTime ;
                   1184:    BOOL           ValidValue ;
                   1185: 
                   1186:    pSystemTime = pGraph->pDataTime ;
                   1187:    pSystemTime += CurrentIndex ;
                   1188: 
                   1189:    if (pSystemTime->wYear == 0 && pSystemTime->wYear == 0)
                   1190:       {
                   1191:       // ignore value that has 0 system time
                   1192:       return (TRUE) ;
                   1193:       }
                   1194: 
                   1195:    MaxValues = pGraph->gMaxValues ;
                   1196:    strcpy (TempBuff, LineEndStr) ;
                   1197:    StringLen = strlen (TempBuff) ;
                   1198: 
                   1199:    SystemTimeDateString (pSystemTime, UnicodeBuff) ;
                   1200:    ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                   1201:    strcat (TempBuff, pDelimiter) ;
                   1202:    StringLen = strlen (TempBuff) ;
                   1203: 
                   1204:    SystemTimeTimeString (pSystemTime, UnicodeBuff) ;
                   1205:    ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                   1206:    strcat (TempBuff, pDelimiter) ;
                   1207:    StringLen = strlen (TempBuff) ;
                   1208: 
                   1209:    TimeToWriteFile = 0 ;
                   1210:    for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
                   1211:       {
                   1212:       if (!pLine->bFirstTime)
                   1213:          {
                   1214:          ValidValue = FALSE ;
                   1215:          // check if this is a valid value
                   1216:          if (pLine->lnValidValues == MaxValues)
                   1217:             {
                   1218:             // this is the simple case where we have filled up 
                   1219:             // the whole buffer
                   1220:             ValidValue = TRUE ;
                   1221:             }
                   1222:          else if (pLine->lnValidValues <= iDataPoint)
                   1223:             {
                   1224:             if (CurrentIndex <= iDataPoint &&
                   1225:                CurrentIndex > iDataPoint - pLine->lnValidValues)
                   1226:                {
                   1227:                ValidValue = TRUE ;
                   1228:                }
                   1229:             }
                   1230:          else
                   1231:             {
                   1232:             if (CurrentIndex <= iDataPoint ||
                   1233:                CurrentIndex > (MaxValues - pLine->lnValidValues + iDataPoint))
                   1234:                {
                   1235:                // this is the case when we start the new line in the middle
                   1236:                // and data buffer has been wrap-around.
                   1237:                ValidValue = TRUE ;
                   1238:                }
                   1239:             }
                   1240: 
                   1241:          // only export the data when we determine it is valid
                   1242:          if (ValidValue)
                   1243:             {
                   1244:             TSPRINTF (UnicodeBuff,
                   1245:                pLine->lnValues[CurrentIndex] > (FLOAT)999999.0 ?
                   1246:                szLargeValueFormat : szSmallValueFormat,
                   1247:                pLine->lnValues[CurrentIndex]) ;
                   1248:             ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
                   1249:             }
                   1250:          }
                   1251:       strcat (TempBuff, pDelimiter) ;
                   1252:       StringLen = strlen (TempBuff) ;
                   1253: 
                   1254:       if (++TimeToWriteFile > TIME_TO_WRITE)
                   1255:          {
                   1256:          // better write the buffers before they overflow.
                   1257:          // there are better ways to check for overflow 
                   1258:          // but this is good enough
                   1259:    
                   1260:          if (!FileWrite (hFile, TempBuff, StringLen))
                   1261:             {
                   1262:             goto Exit0 ;
                   1263:             }
                   1264:          StringLen = TimeToWriteFile = 0 ;
                   1265:          TempBuff[0] = '\0' ;
                   1266:          }
                   1267:       }
                   1268: 
                   1269:    if (StringLen)
                   1270:       {
                   1271:       // write the last block of data
                   1272:       if (!FileWrite (hFile, TempBuff, StringLen))
                   1273:          {
                   1274:          goto Exit0 ;
                   1275:          }
                   1276:       }
                   1277: 
                   1278:    return (TRUE) ;
                   1279: 
                   1280: Exit0:
                   1281:    return (FALSE) ;
                   1282: 
                   1283: }     // ExportLineValue
                   1284: 
                   1285: BOOL ExportCurrentChart (HANDLE hFile, PGRAPHSTRUCT pGraph)
                   1286: {
                   1287:    int            KnownValue,
                   1288:                   MaxValues,
                   1289:                   iValidValues,
                   1290:                   iDataPoint ;
                   1291:    BOOL           SimpleCase = FALSE ;
                   1292:    int            iIndex ;
                   1293: 
                   1294:    MaxValues = pGraph->gMaxValues ;
                   1295:    KnownValue = pGraph->gKnownValue ;
                   1296:    iValidValues = pGraph->gTimeLine.iValidValues ;
                   1297: 
                   1298:    if (iValidValues < MaxValues)
                   1299:       {
                   1300:       // data have not wrapped around, so the oldest time
                   1301:       // is started at 0.
                   1302:       SimpleCase = TRUE ;
                   1303:       iValidValues = (KnownValue % MaxValues) + 1 ;
                   1304:       }
                   1305: 
                   1306:    iDataPoint = KnownValue % MaxValues ;
                   1307: 
                   1308:    if (!SimpleCase)
                   1309:       {
                   1310:       for (iIndex = iDataPoint+1 ; iIndex < MaxValues ; iIndex++)
                   1311:          {
                   1312:          if (!ExportLineValue (hFile, pGraph, iIndex, iDataPoint))
                   1313:             {
                   1314:             goto Exit0 ;
                   1315:             }
                   1316:          }
                   1317:       }
                   1318: 
                   1319:    for (iIndex = 0 ; iIndex <= iDataPoint ; iIndex++)
                   1320:       {
                   1321:       if (!ExportLineValue (hFile, pGraph, iIndex, iDataPoint))
                   1322:          {
                   1323:          goto Exit0 ;
                   1324:          }
                   1325:       }
                   1326: 
                   1327:    return (TRUE) ;
                   1328: 
                   1329: Exit0:
                   1330:    return (FALSE) ;
                   1331: 
                   1332: }  // ExportCurrentChart
                   1333: 
                   1334: 
                   1335: void ExportChart (void)
                   1336: {
                   1337: 
                   1338:    PGRAPHSTRUCT   pGraph ;
                   1339:    HANDLE         hFile = 0 ;
                   1340:    LPTSTR         pFileName = NULL ;
                   1341:    INT            ErrCode = 0 ;
                   1342: 
                   1343:    if (!(pGraph = pGraphs))
                   1344:       {
                   1345:       return ;
                   1346:       }
                   1347: 
                   1348:    // see if there is anything to export..
                   1349:    if (!(pGraph->pLineFirst))
                   1350:       {
                   1351:       return ;
                   1352:       }
                   1353: 
                   1354:    SetHourglassCursor() ;
                   1355:    
                   1356:    if (ErrCode = ExportFileOpen (hWndGraph, &hFile, pGraph->gInterval, &pFileName))
                   1357:       {
                   1358:       goto Exit0 ;
                   1359:       }
                   1360: 
                   1361:    if (!pFileName)
                   1362:       {
                   1363:       // this is the case when user cancel.
                   1364:       goto Exit0 ;
                   1365:       }
                   1366: 
                   1367:    // export the column labels
                   1368:    if (!ExportChartLabels (hFile, pGraph))
                   1369:       {
                   1370:    
                   1371:       ErrCode = ERR_EXPORT_FILE ;
                   1372:       goto Exit0 ;
                   1373:       }
                   1374: 
                   1375:    // export the lines
                   1376:    if (PlayingBackLog())
                   1377:       {
                   1378:       if (!ExportLogChart (hFile, pGraph))
                   1379:          {
                   1380:          ErrCode = ERR_EXPORT_FILE ;
                   1381:          goto Exit0 ;
                   1382:          }
                   1383:       }
                   1384:    else
                   1385:       {
                   1386:       if (!ExportCurrentChart (hFile, pGraph))
                   1387:          {
                   1388:          ErrCode = ERR_EXPORT_FILE ;
                   1389:          goto Exit0 ;
                   1390:          }
                   1391:       }
                   1392: Exit0:
                   1393: 
                   1394:    SetArrowCursor() ;
                   1395: 
                   1396:    if (hFile)
                   1397:       {
                   1398:       CloseHandle (hFile) ;
                   1399:       }
                   1400: 
                   1401:    if (pFileName)
                   1402:       {
                   1403:       if (ErrCode)
                   1404:          {
                   1405:          DlgErrorBox (hWndGraph, ErrCode, pFileName) ;
                   1406:          }
                   1407: 
                   1408:       MemoryFree (pFileName) ;
                   1409:       }
                   1410: 
                   1411: }     // ExportChart
                   1412: 
                   1413: 
                   1414: typedef struct CHARTDATAPOINTSTRUCT
                   1415:    {
                   1416:    int         iLogIndex ;
                   1417:    int         xDispDataPoint ;
                   1418:    } CHARTDATAPOINT, *PCHARTDATAPOINT ;
                   1419: 
                   1420: void PlaybackChartDataPoint (PCHARTDATAPOINT pChartDataPoint)
                   1421:    {  // PlaybackChartDataPoint
                   1422:    int            iDisplayTics ;       // num visual points to display
                   1423:    int            iDisplayTic ;
                   1424:    int            iLogTic ;
                   1425:    int            iLogTicsMove ;
                   1426:    BOOL           bFirstTime = TRUE;
                   1427:    int            iLogTicsRemaining ;
                   1428:    int            numOfData, xDispDataPoint, rectWidth, xPos ;
                   1429:    PGRAPHSTRUCT   pGraph ;
                   1430: 
                   1431:    pGraph = GraphData (hWndGraph) ;
                   1432: 
                   1433:    iLogTicsRemaining = PlaybackLog.iSelectedTics ;
                   1434: 
                   1435: 
                   1436:    // we only have iDisplayTics-1 points since
                   1437:    // we have to use the first two sample points to
                   1438:    // get the first data points.
                   1439:    if (iLogTicsRemaining <= pGraphs->gMaxValues)
                   1440:       {
                   1441:       iDisplayTics = iLogTicsRemaining ;
                   1442:       }
                   1443:    else
                   1444:       {
                   1445:       iDisplayTics = pGraphs->gMaxValues ;
                   1446:       }
                   1447: 
                   1448:    iDisplayTic = -1 ;
                   1449:    iLogTic = PlaybackLog.StartIndexPos.iPosition ;
                   1450: 
                   1451:    numOfData      = pGraph->gMaxValues - 1 ;
                   1452:    rectWidth      = pGraph->rectData.right - pGraph->rectData.left ;
                   1453:    xDispDataPoint = pGraph->rectData.left ;
                   1454: 
                   1455:    while (iDisplayTics && numOfData)
                   1456:       {
                   1457: 
                   1458:       if (!bFirstTime)
                   1459:          {
                   1460:          iDisplayTic++ ;
                   1461:          }
                   1462:       else
                   1463:          {
                   1464:          bFirstTime = FALSE ;
                   1465: 
                   1466:          // get the second sample data to form the first data point
                   1467:          iLogTic++ ;
                   1468:          iLogTicsRemaining-- ;
                   1469: 
                   1470:          iDisplayTic++ ;
                   1471:          }
                   1472: 
                   1473:       pChartDataPoint[iDisplayTic].iLogIndex = iLogTic ;
                   1474:       pChartDataPoint[iDisplayTic].xDispDataPoint = xDispDataPoint ;
                   1475: 
                   1476:       // setup DDA to get the index of the next sample point
                   1477:       iLogTicsMove = DDA_DISTRIBUTE (iLogTicsRemaining, iDisplayTics) ;
                   1478:       iLogTicsRemaining -= iLogTicsMove ;
                   1479:       iLogTic += iLogTicsMove ;
                   1480: 
                   1481: 
                   1482:       xPos = DDA_DISTRIBUTE (rectWidth, numOfData) ;
                   1483:       xDispDataPoint += xPos ;
                   1484:       numOfData-- ;
                   1485:       rectWidth -= xPos ;
                   1486: 
                   1487:       iDisplayTics-- ;
                   1488: 
                   1489:       }  // while
                   1490: 
                   1491:    }  // PlaybackChartDataPoint
                   1492: 
                   1493: 
                   1494: BOOL
                   1495: BuildNewValueListForGraph (
                   1496: )
                   1497: {
                   1498:     PGRAPHSTRUCT    pGraph;
                   1499: 
                   1500:     pGraph = pGraphs;   // set local pointer to global pointer
                   1501:     
                   1502:     return BuildValueListForSystems (
                   1503:         pGraphs->pSystemFirst,
                   1504:         pGraphs->pLineFirst);
                   1505: 
                   1506: }
                   1507: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.