|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.