Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1686 lines
51 KiB

  1. /*****************************************************************************
  2. *
  3. * RptFct.c - This file contains support routines for the Report view.
  4. * They are moved here because Report.c is getting too big.
  5. *
  6. * Microsoft Confidential
  7. * Copyright (c) 1992-1993 Microsoft Corporation
  8. *
  9. * Author -
  10. *
  11. * Hon-Wah Chan
  12. *
  13. ****************************************************************************/
  14. #include "perfmon.h"
  15. #include <stdio.h> // for sprintf
  16. #include "report.h" // Exported declarations for this file
  17. #include "line.h" // for LineAppend
  18. #include "pmemory.h" // for MemoryXXX (mallloc-type) routines
  19. #include "system.h" // for SystemGet
  20. #include "utils.h"
  21. #include "perfmops.h" // for BuildValueListForSystems
  22. // extern defined in Report.c
  23. extern TCHAR szSystemFormat [] ;
  24. extern TCHAR szObjectFormat [] ;
  25. #define szValuePlaceholder TEXT("-999999999.999")
  26. #define szLargeValueFormat TEXT("%12.0f")
  27. #define eStatusLargeValueMax ((FLOAT) 999999999.0)
  28. #define szValueFormat TEXT("%12.3f")
  29. //========================
  30. // Local routines prototypes
  31. //========================
  32. void ColumnRemoveOne (PREPORT pReport,
  33. POBJECTGROUP pObjectGroup,
  34. int iColumnNumber) ;
  35. BOOL CounterGroupRemove (PCOUNTERGROUP *ppCounterGroupFirst,
  36. PCOUNTERGROUP pCounterGroupRemove) ;
  37. BOOL ObjectGroupRemove (POBJECTGROUP *ppObjectGroupFirst,
  38. POBJECTGROUP pObjectGroupRemove) ;
  39. BOOL SystemGroupRemove (PSYSTEMGROUP *ppSystemGroupFirst,
  40. PSYSTEMGROUP pSystemGroupRemove) ;
  41. PCOUNTERGROUP GetNextCounter (PSYSTEMGROUP pSystemGroup,
  42. POBJECTGROUP pObjectGroup,
  43. PCOUNTERGROUP pCounterGroup) ;
  44. BOOL ReportLineRemove (PREPORT pReport,
  45. PLINE pLineRemove)
  46. {
  47. PLINE pLine ;
  48. if (pReport->pLineFirst == pLineRemove)
  49. {
  50. pReport->pLineFirst = (pReport->pLineFirst)->pLineNext ;
  51. return (TRUE) ;
  52. }
  53. for (pLine = pReport->pLineFirst ;
  54. pLine->pLineNext ;
  55. pLine = pLine->pLineNext)
  56. { // for
  57. if (pLine->pLineNext == pLineRemove)
  58. {
  59. pLine->pLineNext = pLineRemove->pLineNext ;
  60. if (pLineRemove == pReport->pLineLast) {
  61. pReport->pLineLast = pLine;
  62. }
  63. return (TRUE) ;
  64. } // if
  65. } // for
  66. return (FALSE) ;
  67. } // ReportLineRemove
  68. // CheckColumnGroupRemove is used to check if the given
  69. // column is empty. If it is empty, it is removed from
  70. // the column link list
  71. void CheckColumnGroupRemove (PREPORT pReport,
  72. POBJECTGROUP pObjectGroup,
  73. int iReportColumn)
  74. {
  75. // check if we need to remove the this column
  76. PLINE pCounterLine ;
  77. PCOUNTERGROUP pCounterGrp ;
  78. BOOL bColumnFound = FALSE ;
  79. if (iReportColumn < 0 || pObjectGroup->pCounterGroupFirst == NULL)
  80. {
  81. // no column for this Counter group, forget it
  82. return ;
  83. }
  84. // go thru each Counter group and check if any line in the
  85. // group matches the given column number
  86. for (pCounterGrp = pObjectGroup->pCounterGroupFirst ;
  87. pCounterGrp ;
  88. pCounterGrp = pCounterGrp->pCounterGroupNext )
  89. {
  90. for (pCounterLine = pCounterGrp->pLineFirst ;
  91. pCounterLine ;
  92. pCounterLine = pCounterLine->pLineCounterNext)
  93. {
  94. if (pCounterLine->iReportColumn == iReportColumn)
  95. {
  96. // found one, this column is not empty
  97. bColumnFound = TRUE ;
  98. break ;
  99. }
  100. } // for pCounterLine
  101. if (bColumnFound)
  102. {
  103. break ;
  104. }
  105. } // for pCounterGrp
  106. if (bColumnFound == FALSE)
  107. {
  108. // we have deleted the last column item, remove this column
  109. ColumnRemoveOne (pReport,
  110. pObjectGroup,
  111. iReportColumn) ;
  112. }
  113. } // CheckColumnGroupRemove
  114. //================================
  115. // Line routine
  116. //================================
  117. void ReportLineValueRect (PREPORT pReport,
  118. PLINE pLine,
  119. LPRECT lpRect)
  120. { // ReportLineValueRect
  121. lpRect->left = ValueMargin (pReport) + pLine->xReportPos ;
  122. lpRect->top = pLine->yReportPos ;
  123. lpRect->right = lpRect->left + pReport->xValueWidth ;
  124. lpRect->bottom = lpRect->top + pReport->yLineHeight ;
  125. } // ReportLineValueRect
  126. PLINE LineRemoveItem (PREPORT pReport,
  127. enum REPORT_ITEM_TYPE *pNewItemType)
  128. {
  129. PLINE pLine ;
  130. PLINE pNextLine = NULL ;
  131. PLINE pReturnLine = NULL ;
  132. PLINE pLeftLine = NULL ;
  133. PSYSTEMGROUP pSystemGroup ;
  134. POBJECTGROUP pObjectGroup ;
  135. PCOUNTERGROUP pCounterGroup ;
  136. PCOUNTERGROUP pNextCounterGroup ;
  137. BOOL bCreatNewCounterGroup ;
  138. //=============================//
  139. // Remove line, line's system //
  140. //=============================//
  141. pLine = pReport->CurrentItem.pLine ;
  142. ReportLineRemove (pReport, pLine) ;
  143. // no more line, no more timer...
  144. if (!pReport->pLineFirst)
  145. {
  146. pReport->xWidth = 0 ;
  147. pReport->yHeight = 0 ;
  148. pReport->xMaxCounterWidth = 0 ;
  149. ClearReportTimer (pReport) ;
  150. }
  151. //=============================//
  152. // Get correct spot; remove line //
  153. //=============================//
  154. pSystemGroup = GetSystemGroup (pReport, pLine->lnSystemName) ;
  155. pObjectGroup = GetObjectGroup (pSystemGroup, pLine->lnObjectName) ;
  156. pCounterGroup = GetCounterGroup (pObjectGroup,
  157. pLine->lnCounterDef.CounterNameTitleIndex,
  158. &bCreatNewCounterGroup,
  159. pLine->lnCounterName,
  160. TRUE) ;
  161. if (!pCounterGroup)
  162. return (NULL) ;
  163. LineCounterRemove (pCounterGroup, pLine) ;
  164. // check which line to get the focus
  165. if (pCounterGroup->pLineFirst)
  166. {
  167. // simple case, we still have line in the same counter group
  168. // get the one right after this delete line.
  169. for (pNextLine = pCounterGroup->pLineFirst ;
  170. pNextLine ;
  171. pNextLine = pNextLine->pLineCounterNext)
  172. {
  173. if (pNextLine->xReportPos > pLine->xReportPos)
  174. {
  175. if (pReturnLine == NULL ||
  176. pReturnLine->xReportPos > pNextLine->xReportPos)
  177. {
  178. pReturnLine = pNextLine ;
  179. }
  180. }
  181. else
  182. {
  183. if (pLeftLine == NULL ||
  184. pLeftLine->xReportPos < pNextLine->xReportPos)
  185. {
  186. pLeftLine = pNextLine ;
  187. }
  188. }
  189. }
  190. if (!pReturnLine && pLeftLine)
  191. {
  192. // the delete line is the last column, then use the line
  193. // to its left
  194. pReturnLine = pLeftLine ;
  195. }
  196. }
  197. else
  198. {
  199. pNextCounterGroup = GetNextCounter (
  200. pSystemGroup,
  201. pObjectGroup,
  202. pCounterGroup) ;
  203. if (pNextCounterGroup)
  204. {
  205. pLeftLine = NULL ;
  206. for (pNextLine = pNextCounterGroup->pLineFirst ;
  207. pNextLine ;
  208. pNextLine = pNextLine->pLineCounterNext)
  209. {
  210. // get the line in the first column
  211. if (pLeftLine == NULL ||
  212. pNextLine->xReportPos < pLeftLine->xReportPos)
  213. {
  214. pLeftLine = pNextLine ;
  215. }
  216. }
  217. pReturnLine = pLeftLine ;
  218. }
  219. // remove this counter group if there is no line
  220. CounterGroupRemove (&pObjectGroup->pCounterGroupFirst, pCounterGroup) ;
  221. }
  222. // check if we need to remove any empty column
  223. CheckColumnGroupRemove (pReport, pObjectGroup, pLine->iReportColumn) ;
  224. if (!(pObjectGroup->pCounterGroupFirst))
  225. ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
  226. if (!(pSystemGroup->pObjectGroupFirst))
  227. SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ;
  228. LineFree (pLine) ;
  229. if (pReturnLine && pNewItemType)
  230. {
  231. *pNewItemType = REPORT_TYPE_LINE ;
  232. }
  233. return (pReturnLine) ;
  234. } // LineRemoveItem
  235. //======================================//
  236. // Column Group routines //
  237. //======================================//
  238. void ReportColumnRect (PREPORT pReport,
  239. PCOLUMNGROUP pColumnGroup,
  240. LPRECT lpRect)
  241. { // ReportColumnRect
  242. lpRect->left = ValueMargin (pReport) + pColumnGroup->xPos ;
  243. lpRect->top = pColumnGroup->yFirstLine ;
  244. lpRect->right = lpRect->left + pColumnGroup->xWidth ;
  245. lpRect->bottom = lpRect->top + pReport->yLineHeight ;
  246. if (pColumnGroup->lpszParentName)
  247. {
  248. lpRect->top -= pReport->yLineHeight ;
  249. }
  250. } // ReportColumnRect
  251. BOOL ColumnSame (PCOLUMNGROUP pColumnGroup,
  252. LPTSTR lpszParentName,
  253. LPTSTR lpszInstanceName,
  254. DWORD dwIndex)
  255. { // ColumnSame
  256. BOOL bReturn = FALSE;
  257. if (dwIndex == pColumnGroup->dwInstanceIndex) {
  258. if ((!lpszParentName && !pColumnGroup->lpszParentName) ||
  259. strsame (lpszParentName, pColumnGroup->lpszParentName)) {
  260. if ((!lpszInstanceName && !pColumnGroup->lpszInstanceName) ||
  261. strsame (lpszInstanceName, pColumnGroup->lpszInstanceName)) {
  262. bReturn = TRUE;
  263. }
  264. }
  265. }
  266. return bReturn;
  267. } // ColumnSame
  268. PCOLUMNGROUP ColumnGroupCreate (PREPORT pReport,
  269. int xPos,
  270. LPTSTR lpszParentName,
  271. LPTSTR lpszInstanceName,
  272. int PreviousColumnNumber,
  273. int yFirstLine,
  274. DWORD dwIndex)
  275. { // ColumnGroupCreate
  276. PCOLUMNGROUP pColumnGroup ;
  277. HDC hDC ;
  278. hDC = GetDC (pReport->hWnd) ;
  279. if (!hDC)
  280. return NULL;
  281. pColumnGroup = MemoryAllocate (sizeof (COLUMNGROUP)) ;
  282. if (pColumnGroup)
  283. {
  284. pColumnGroup->pColumnGroupNext = NULL ;
  285. pColumnGroup->lpszParentName = StringAllocate (lpszParentName) ;
  286. pColumnGroup->lpszInstanceName = StringAllocate (lpszInstanceName) ;
  287. pColumnGroup->ParentNameTextWidth = TextWidth (hDC, lpszParentName) ;
  288. pColumnGroup->InstanceNameTextWidth = TextWidth (hDC, lpszInstanceName) ;
  289. pColumnGroup->xPos = xPos ;
  290. pColumnGroup->yFirstLine = yFirstLine ;
  291. pColumnGroup->ColumnNumber = PreviousColumnNumber + 1 ;
  292. pColumnGroup->xWidth = max (max (pColumnGroup->ParentNameTextWidth,
  293. pColumnGroup->InstanceNameTextWidth),
  294. pReport->xValueWidth) ;
  295. pColumnGroup->dwInstanceIndex = dwIndex;
  296. pReport->xWidth = max (pReport->xWidth,
  297. RightHandMargin +
  298. ValueMargin (pReport) +
  299. pColumnGroup->xPos + pColumnGroup->xWidth +
  300. xColumnMargin) ;
  301. } // if
  302. ReleaseDC (pReport->hWnd, hDC) ;
  303. return (pColumnGroup) ;
  304. } // ColumnGroupCreate
  305. PCOLUMNGROUP GetColumnGroup (PREPORT pReport,
  306. POBJECTGROUP pObjectGroup,
  307. PLINE pLine)
  308. /*
  309. Effect: Return a pointer to the appropriate column group from
  310. within the groups of pObject. If the line is a counter
  311. without instances, return NULL. Otherwise, determine
  312. if the counter's parent/instance pair is already found
  313. in an existing column and return a pointer to that column.
  314. If a column with the appropriate parent/instance isn't
  315. found, add a new column *at the end*, and return that
  316. column.
  317. Note: This function has multiple return points.
  318. */
  319. { // GetColumnGroup
  320. PCOLUMNGROUP pColumnGroup ;
  321. LPTSTR lpszParentName ;
  322. LPTSTR lpszInstanceName ;
  323. DWORD dwIndex;
  324. if (!LineInstanceName (pLine))
  325. return (NULL) ;
  326. lpszParentName = LineParentName (pLine) ;
  327. lpszInstanceName = LineInstanceName (pLine) ;
  328. dwIndex = pLine->dwInstanceIndex;
  329. if (!pObjectGroup->pColumnGroupFirst)
  330. {
  331. pObjectGroup->pColumnGroupFirst =
  332. ColumnGroupCreate (pReport,
  333. 0,
  334. lpszParentName,
  335. lpszInstanceName,
  336. -1,
  337. pObjectGroup->yFirstLine,
  338. dwIndex) ;
  339. if (pObjectGroup->pColumnGroupFirst)
  340. {
  341. pObjectGroup->pColumnGroupFirst->pParentObject =
  342. pObjectGroup ;
  343. }
  344. return (pObjectGroup->pColumnGroupFirst) ;
  345. }
  346. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  347. pColumnGroup ;
  348. pColumnGroup = pColumnGroup->pColumnGroupNext)
  349. { // for
  350. if (ColumnSame (pColumnGroup, lpszParentName, lpszInstanceName, dwIndex))
  351. return (pColumnGroup) ;
  352. else if (!pColumnGroup->pColumnGroupNext)
  353. { // if
  354. pColumnGroup->pColumnGroupNext =
  355. ColumnGroupCreate (pReport,
  356. pColumnGroup->xPos + pColumnGroup->xWidth +
  357. xColumnMargin,
  358. lpszParentName,
  359. lpszInstanceName,
  360. pColumnGroup->ColumnNumber,
  361. pObjectGroup->yFirstLine,
  362. dwIndex) ;
  363. if (pColumnGroup->pColumnGroupNext)
  364. {
  365. (pColumnGroup->pColumnGroupNext)->pParentObject =
  366. pObjectGroup ;
  367. // build the double link-list
  368. (pColumnGroup->pColumnGroupNext)->pColumnGroupPrevious =
  369. pColumnGroup ;
  370. }
  371. return (pColumnGroup->pColumnGroupNext) ;
  372. } // if
  373. } // for
  374. return (NULL) ;
  375. } // GetColumnGroup
  376. // ColumnRemoveOne removes the column with the specified column number
  377. void ColumnRemoveOne (PREPORT pReport,
  378. POBJECTGROUP pObjectGroup,
  379. int iColumnNumber)
  380. {
  381. PCOLUMNGROUP pColumnGroup ;
  382. PCOLUMNGROUP pNextColumnGroup ;
  383. if (pObjectGroup->pColumnGroupFirst == NULL)
  384. {
  385. // no column group, forget it
  386. return ;
  387. }
  388. // Find the head list
  389. if (pObjectGroup->pColumnGroupFirst->ColumnNumber == iColumnNumber)
  390. {
  391. pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  392. pObjectGroup->pColumnGroupFirst = pColumnGroup->pColumnGroupNext ;
  393. if (pColumnGroup->pColumnGroupNext)
  394. {
  395. // set up head of backward link list
  396. (pColumnGroup->pColumnGroupNext)->pColumnGroupPrevious = NULL ;
  397. }
  398. // free memory for this column group
  399. MemoryFree (pColumnGroup->lpszParentName) ;
  400. MemoryFree (pColumnGroup->lpszInstanceName) ;
  401. MemoryFree (pColumnGroup) ;
  402. return ;
  403. }
  404. // go thru the double link list to look for the right column
  405. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  406. pColumnGroup ;
  407. pColumnGroup = pNextColumnGroup)
  408. {
  409. pNextColumnGroup = pColumnGroup->pColumnGroupNext ;
  410. if (pNextColumnGroup == NULL)
  411. {
  412. // forget it if we can't find this column for some reson.
  413. break ;
  414. }
  415. if (pNextColumnGroup->ColumnNumber == iColumnNumber)
  416. {
  417. pColumnGroup->pColumnGroupNext = pNextColumnGroup->pColumnGroupNext ;
  418. // build backward link iff it is not the end of list
  419. if (pColumnGroup->pColumnGroupNext)
  420. {
  421. (pColumnGroup->pColumnGroupNext)->pColumnGroupPrevious =
  422. pColumnGroup ;
  423. }
  424. // free memory for this column group
  425. MemoryFree (pNextColumnGroup->lpszParentName) ;
  426. MemoryFree (pNextColumnGroup->lpszInstanceName) ;
  427. MemoryFree (pNextColumnGroup) ;
  428. // Done
  429. break ;
  430. }
  431. }
  432. } // ColumnRemoveOne
  433. // ColumnGroupRemove removes all the columns for a given column list
  434. void ColumnGroupRemove (PCOLUMNGROUP pColumnGroupFirst)
  435. {
  436. PCOLUMNGROUP pColumnGroup ;
  437. PCOLUMNGROUP pNextColumnGroup ;
  438. for (pColumnGroup = pColumnGroupFirst ;
  439. pColumnGroup ;
  440. pColumnGroup = pNextColumnGroup)
  441. {
  442. pNextColumnGroup = pColumnGroup->pColumnGroupNext ;
  443. // free memory for this column group
  444. MemoryFree (pColumnGroup->lpszParentName) ;
  445. MemoryFree (pColumnGroup->lpszInstanceName) ;
  446. MemoryFree (pColumnGroup) ;
  447. }
  448. } // ColumnGroupRemove
  449. // ColumnRemoveItem is called when user wants to delete a
  450. // selected column.
  451. PCOLUMNGROUP ColumnRemoveItem (PREPORT pReport,
  452. PCOLUMNGROUP pColumnGroup,
  453. BOOL bCleanUpLink,
  454. enum REPORT_ITEM_TYPE *pNewItemType)
  455. {
  456. PLINE pLine, pNextLine ;
  457. PSYSTEMGROUP pSystemGroup ;
  458. POBJECTGROUP pObjectGroup ;
  459. PCOUNTERGROUP pCounterGroup, pNextCounterGroup ;
  460. BOOL bColumnFound ;
  461. PCOLUMNGROUP pRetColumnGroup = NULL ;
  462. pObjectGroup = pColumnGroup->pParentObject ;
  463. pSystemGroup = pObjectGroup->pParentSystem ;
  464. // first, get rid of all the counter lines with this column number
  465. // Note - each Counter group has only 1 line (or 0) with this
  466. // column number
  467. for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  468. pCounterGroup ;
  469. pCounterGroup = pNextCounterGroup )
  470. {
  471. pNextCounterGroup = pCounterGroup->pCounterGroupNext ;
  472. bColumnFound = FALSE ;
  473. for (pLine = pCounterGroup->pLineFirst ;
  474. pLine ;
  475. pLine = pNextLine)
  476. {
  477. pNextLine = pLine->pLineCounterNext ;
  478. if (pLine->iReportColumn == pColumnGroup->ColumnNumber)
  479. {
  480. bColumnFound = TRUE ;
  481. // delete this line
  482. ReportLineRemove (pReport, pLine) ;
  483. LineCounterRemove (pCounterGroup, pLine) ;
  484. LineFree (pLine) ;
  485. break ;
  486. }
  487. }
  488. if (bColumnFound)
  489. {
  490. // check if we need delete this counter group
  491. if (!(pCounterGroup->pLineFirst))
  492. {
  493. CounterGroupRemove (&pObjectGroup->pCounterGroupFirst, pCounterGroup) ;
  494. }
  495. }
  496. }
  497. // determine which column group to go after deleting this
  498. if (pColumnGroup->pColumnGroupNext)
  499. {
  500. // get the Column group after this delete one
  501. pRetColumnGroup = pColumnGroup->pColumnGroupNext ;
  502. }
  503. else
  504. {
  505. // get the Counter group before this delete one
  506. pRetColumnGroup = pColumnGroup->pColumnGroupPrevious ;
  507. }
  508. if (pNewItemType)
  509. {
  510. if (pRetColumnGroup)
  511. {
  512. *pNewItemType = REPORT_TYPE_COLUMN ;
  513. }
  514. else
  515. {
  516. // get next counter group
  517. pNextCounterGroup = GetNextCounter (
  518. pSystemGroup,
  519. pObjectGroup,
  520. NULL) ;
  521. if (pNextCounterGroup)
  522. {
  523. // we have to return Counter group, so we have to do the
  524. // dirty casting..
  525. *pNewItemType = REPORT_TYPE_COUNTER ;
  526. pRetColumnGroup = (PCOLUMNGROUP) pNextCounterGroup ;
  527. }
  528. }
  529. }
  530. // remove this column group
  531. ColumnRemoveOne (pReport, pObjectGroup, pColumnGroup->ColumnNumber) ;
  532. // check for further cleanup
  533. if (bCleanUpLink)
  534. {
  535. if (!(pObjectGroup->pCounterGroupFirst))
  536. ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
  537. if (!(pSystemGroup->pObjectGroupFirst))
  538. SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ;
  539. }
  540. return (pRetColumnGroup) ;
  541. } // ColumnRemoveItem
  542. //======================================//
  543. // Counter Group routines //
  544. //======================================//
  545. void ReportCounterRect (PREPORT pReport,
  546. PCOUNTERGROUP pCounterGroup,
  547. LPRECT lpRect)
  548. { // ReportCounterRect
  549. lpRect->left = xCounterMargin ;
  550. lpRect->top = pCounterGroup->yLine ;
  551. lpRect->right = lpRect->left + pCounterGroup->xWidth + yScrollHeight / 2 ;
  552. lpRect->bottom = lpRect->top + pReport->yLineHeight ;
  553. } // ReportCounterRect
  554. PCOUNTERGROUP CounterGroupCreate (DWORD dwCounterIndex,
  555. LPTSTR pCounterName)
  556. { // CounterGroupCreate
  557. PCOUNTERGROUP pCounterGroup ;
  558. HDC hDC ;
  559. PREPORT pReport ;
  560. pCounterGroup = MemoryAllocate (sizeof (COUNTERGROUP)) ;
  561. if (pCounterGroup)
  562. {
  563. pCounterGroup->pCounterGroupNext = NULL ;
  564. pCounterGroup->pLineFirst = NULL ;
  565. pCounterGroup->dwCounterIndex = dwCounterIndex ;
  566. if (pCounterName)
  567. {
  568. hDC = GetDC (hWndReport) ;
  569. pReport = ReportData (hWndReport) ;
  570. if (hDC && pReport) {
  571. SelectFont (hDC, pReport->hFont) ;
  572. pCounterGroup->xWidth = TextWidth (hDC, pCounterName) ;
  573. }
  574. if (hDC) {
  575. ReleaseDC (hWndReport, hDC) ;
  576. }
  577. }
  578. } // if
  579. return (pCounterGroup) ;
  580. } // CounterGroupCreate
  581. PCOUNTERGROUP GetCounterGroup (POBJECTGROUP pObjectGroup,
  582. DWORD dwCounterIndex,
  583. BOOL *pbCounterGroupCreated,
  584. LPTSTR pCounterName,
  585. BOOL bCreateNewGroup)
  586. { // GetCounterGroup
  587. PCOUNTERGROUP pCounterGroup ;
  588. *pbCounterGroupCreated = FALSE ;
  589. if (!pObjectGroup)
  590. return (FALSE) ;
  591. if (!pObjectGroup->pCounterGroupFirst) {
  592. if (bCreateNewGroup) {
  593. pObjectGroup->pCounterGroupFirst =
  594. CounterGroupCreate (dwCounterIndex, pCounterName) ;
  595. if (pObjectGroup->pCounterGroupFirst)
  596. {
  597. *pbCounterGroupCreated = TRUE ;
  598. pObjectGroup->pCounterGroupFirst->pParentObject =
  599. pObjectGroup ;
  600. }
  601. return (pObjectGroup->pCounterGroupFirst) ;
  602. }
  603. } else {
  604. for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  605. pCounterGroup ;
  606. pCounterGroup = pCounterGroup->pCounterGroupNext) {
  607. if (dwCounterIndex && pCounterGroup->dwCounterIndex == dwCounterIndex)
  608. {
  609. return (pCounterGroup) ;
  610. }
  611. else if (!dwCounterIndex &&
  612. pCounterGroup->pLineFirst &&
  613. pstrsame (pCounterGroup->pLineFirst->lnCounterName, pCounterName))
  614. {
  615. return (pCounterGroup) ;
  616. }
  617. else if (!pCounterGroup->pCounterGroupNext)
  618. { // if
  619. if (bCreateNewGroup) {
  620. pCounterGroup->pCounterGroupNext =
  621. CounterGroupCreate (dwCounterIndex, pCounterName) ;
  622. if (pCounterGroup->pCounterGroupNext)
  623. {
  624. *pbCounterGroupCreated = TRUE ;
  625. (pCounterGroup->pCounterGroupNext)->pParentObject =
  626. pObjectGroup ;
  627. // build backward link
  628. (pCounterGroup->pCounterGroupNext)->pCounterGroupPrevious =
  629. pCounterGroup ;
  630. }
  631. return (pCounterGroup->pCounterGroupNext) ;
  632. }
  633. } // if
  634. } // for
  635. }
  636. return (NULL) ;
  637. } // GetCounterGroup
  638. BOOL CounterGroupRemove (PCOUNTERGROUP *ppCounterGroupFirst,
  639. PCOUNTERGROUP pCounterGroupRemove)
  640. {
  641. PCOUNTERGROUP pCounterGroup ;
  642. if (*ppCounterGroupFirst == pCounterGroupRemove)
  643. {
  644. *ppCounterGroupFirst = (*ppCounterGroupFirst)->pCounterGroupNext ;
  645. if (*ppCounterGroupFirst)
  646. {
  647. // set up head of backward link list
  648. (*ppCounterGroupFirst)->pCounterGroupPrevious = NULL ;
  649. }
  650. MemoryFree (pCounterGroupRemove) ;
  651. return (TRUE) ;
  652. }
  653. for (pCounterGroup = *ppCounterGroupFirst ;
  654. pCounterGroup->pCounterGroupNext ;
  655. pCounterGroup = pCounterGroup->pCounterGroupNext)
  656. { // for
  657. if (pCounterGroup->pCounterGroupNext == pCounterGroupRemove)
  658. {
  659. pCounterGroup->pCounterGroupNext = pCounterGroupRemove->pCounterGroupNext ;
  660. if (pCounterGroup->pCounterGroupNext)
  661. {
  662. (pCounterGroup->pCounterGroupNext)->pCounterGroupPrevious
  663. = pCounterGroup ;
  664. }
  665. MemoryFree (pCounterGroupRemove) ;
  666. return (TRUE) ;
  667. } // if
  668. } // for
  669. return (FALSE) ;
  670. } // CounterGroupRemove
  671. // CounterRemoveItem is called when user wants to delete a
  672. // selected counter (row)
  673. PCOUNTERGROUP CounterRemoveItem (PREPORT pReport,
  674. PCOUNTERGROUP pCounterGroup,
  675. BOOL bCleanUpLink,
  676. enum REPORT_ITEM_TYPE *pNewItemType)
  677. {
  678. PLINE pLine, pNextLine ;
  679. POBJECTGROUP pObjectGroup ;
  680. PSYSTEMGROUP pSystemGroup ;
  681. PCOLUMNGROUP pColumnGroup ;
  682. PCOLUMNGROUP pNextColumnGroup ;
  683. PCOUNTERGROUP pRetCounterGroup = NULL ;
  684. pObjectGroup = pCounterGroup->pParentObject ;
  685. pSystemGroup = pObjectGroup->pParentSystem ;
  686. // first, remove all the counter lines from this counter group
  687. // and from the Report line link-list
  688. for (pLine = pCounterGroup->pLineFirst ;
  689. pLine ;
  690. pLine = pNextLine)
  691. {
  692. pNextLine = pLine->pLineCounterNext ;
  693. ReportLineRemove (pReport, pLine) ;
  694. LineFree (pLine) ;
  695. }
  696. // we only need to delete the counter group iff we are deleting
  697. // this selected Counter.
  698. if (bCleanUpLink)
  699. {
  700. // determine which counter group to go after deleting this
  701. pRetCounterGroup = GetNextCounter (
  702. pSystemGroup ,
  703. pObjectGroup,
  704. pCounterGroup) ;
  705. // remove this counter group from its parent object group
  706. CounterGroupRemove (&pObjectGroup->pCounterGroupFirst, pCounterGroup) ;
  707. if (!(pObjectGroup->pCounterGroupFirst))
  708. ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
  709. else
  710. {
  711. // Object group not empty, check for any empty column
  712. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  713. pColumnGroup ;
  714. pColumnGroup = pNextColumnGroup)
  715. {
  716. pNextColumnGroup = pColumnGroup->pColumnGroupNext ;
  717. CheckColumnGroupRemove (pReport, pObjectGroup, pColumnGroup->ColumnNumber) ;
  718. }
  719. }
  720. if (!(pSystemGroup->pObjectGroupFirst))
  721. {
  722. SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ;
  723. }
  724. }
  725. else
  726. {
  727. // get rid of this counter's memory
  728. MemoryFree (pCounterGroup) ;
  729. }
  730. if (pRetCounterGroup && pNewItemType)
  731. {
  732. *pNewItemType = REPORT_TYPE_COUNTER ;
  733. }
  734. return (pRetCounterGroup) ;
  735. } // CounterRemoveItem
  736. // GetNextCounter is used to get:
  737. // If the current system is not empty, then get the
  738. // (next object first counter) or
  739. // (previous object last counter. )
  740. // If the current system is empty, then get the
  741. // (next system first object first counter) or
  742. // (previous system last object last counter)
  743. // Note - Any of the input pointers could be NULL pointer.
  744. PCOUNTERGROUP GetNextCounter (PSYSTEMGROUP pSystemGroup,
  745. POBJECTGROUP pObjectGroup,
  746. PCOUNTERGROUP pCounterGroup)
  747. {
  748. PCOUNTERGROUP pRetCounter = NULL ;
  749. PCOUNTERGROUP pCounterGrp ;
  750. POBJECTGROUP pObjectGrp ;
  751. if (pCounterGroup && pCounterGroup->pCounterGroupNext)
  752. {
  753. pRetCounter = pCounterGroup->pCounterGroupNext ;
  754. }
  755. else if (pCounterGroup && pCounterGroup->pCounterGroupPrevious)
  756. {
  757. pRetCounter = pCounterGroup->pCounterGroupPrevious ;
  758. }
  759. else if (pObjectGroup && pObjectGroup->pObjectGroupNext)
  760. {
  761. // get the next Object first Counter
  762. pRetCounter = pObjectGroup->pObjectGroupNext->pCounterGroupFirst ;
  763. }
  764. else if (pObjectGroup && pObjectGroup->pObjectGroupPrevious)
  765. {
  766. // get the previous object last counter
  767. pCounterGrp = (pObjectGroup->pObjectGroupPrevious)->pCounterGroupFirst ;
  768. if (pCounterGrp)
  769. {
  770. // get the last counter group of this object
  771. for (;
  772. pCounterGrp->pCounterGroupNext ;
  773. pCounterGrp = pCounterGrp->pCounterGroupNext )
  774. {
  775. ;
  776. }
  777. }
  778. pRetCounter = pCounterGrp ;
  779. }
  780. else if (pSystemGroup && pSystemGroup->pSystemGroupNext)
  781. {
  782. // get next system first object first counter
  783. pObjectGrp = pSystemGroup->pSystemGroupNext->pObjectGroupFirst ;
  784. pRetCounter = pObjectGrp->pCounterGroupFirst ;
  785. }
  786. else if (pSystemGroup && pSystemGroup->pSystemGroupPrevious)
  787. {
  788. // get previous system last object last counter
  789. pObjectGrp = pSystemGroup->pSystemGroupPrevious->pObjectGroupFirst ;
  790. if (pObjectGrp)
  791. {
  792. // get the last object group of this system
  793. for (;
  794. pObjectGrp->pObjectGroupNext ;
  795. pObjectGrp = pObjectGrp->pObjectGroupNext )
  796. {
  797. ;
  798. }
  799. }
  800. if (pObjectGrp)
  801. {
  802. pCounterGrp = pObjectGrp->pCounterGroupFirst ;
  803. if (pCounterGrp)
  804. {
  805. // get the last counter group of this object
  806. for (;
  807. pCounterGrp->pCounterGroupNext ;
  808. pCounterGrp = pCounterGrp->pCounterGroupNext )
  809. {
  810. ;
  811. }
  812. }
  813. pRetCounter = pCounterGrp ;
  814. }
  815. }
  816. return (pRetCounter) ;
  817. } // GetNextCounter
  818. //======================================//
  819. // Object Group routines //
  820. //======================================//
  821. void ReportObjectRect (PREPORT pReport,
  822. POBJECTGROUP pObjectGroup,
  823. LPRECT lpRect)
  824. { // ReportObjectRect
  825. lpRect->left = xObjectMargin ;
  826. lpRect->top = pObjectGroup->yFirstLine ;
  827. lpRect->right = lpRect->left + pObjectGroup->xWidth ;
  828. lpRect->bottom = lpRect->top + pReport->yLineHeight ;
  829. } // ReportObjectRect
  830. POBJECTGROUP ObjectGroupCreate (LPTSTR lpszObjectName)
  831. { // ObjectGroupCreate
  832. POBJECTGROUP pObjectGroup ;
  833. HDC hDC ;
  834. PREPORT pReport ;
  835. int OldCounterWidth ;
  836. TCHAR szLine [LongTextLen] ;
  837. pObjectGroup = MemoryAllocate (sizeof (OBJECTGROUP)) ;
  838. if (pObjectGroup)
  839. {
  840. pObjectGroup->pObjectGroupNext = NULL ;
  841. pObjectGroup->pCounterGroupFirst = NULL ;
  842. pObjectGroup->pColumnGroupFirst = NULL ;
  843. pObjectGroup->lpszObjectName = StringAllocate (lpszObjectName) ;
  844. hDC = GetDC (hWndReport) ;
  845. pReport = ReportData (hWndReport) ;
  846. if (hDC && pReport) {
  847. SelectFont (hDC, pReport->hFontHeaders) ;
  848. TSPRINTF (szLine, szObjectFormat, lpszObjectName) ;
  849. pObjectGroup->xWidth = TextWidth (hDC, szLine) ;
  850. // re-calc. the max. counter group width
  851. OldCounterWidth = pReport->xMaxCounterWidth ;
  852. pReport->xMaxCounterWidth =
  853. max (pReport->xMaxCounterWidth,
  854. pObjectGroup->xWidth + xObjectMargin) ;
  855. if (OldCounterWidth < pReport->xMaxCounterWidth)
  856. {
  857. // adjust the report width with the new counter width
  858. pReport->xWidth +=
  859. (pReport->xMaxCounterWidth - OldCounterWidth);
  860. }
  861. } // if
  862. if (hDC) {
  863. ReleaseDC (hWndReport, hDC) ;
  864. }
  865. }
  866. return (pObjectGroup) ;
  867. } // ObjectGroupCreate
  868. POBJECTGROUP GetObjectGroup (PSYSTEMGROUP pSystemGroup,
  869. LPTSTR lpszObjectName)
  870. {
  871. POBJECTGROUP pObjectGroup ;
  872. if (!pSystemGroup)
  873. return (FALSE) ;
  874. if (!pSystemGroup->pObjectGroupFirst)
  875. {
  876. pSystemGroup->pObjectGroupFirst = ObjectGroupCreate (lpszObjectName) ;
  877. if (pSystemGroup->pObjectGroupFirst)
  878. {
  879. pSystemGroup->pObjectGroupFirst->pParentSystem =
  880. pSystemGroup ;
  881. }
  882. return (pSystemGroup->pObjectGroupFirst) ;
  883. }
  884. for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  885. pObjectGroup ;
  886. pObjectGroup = pObjectGroup->pObjectGroupNext)
  887. { // for
  888. if (strsame (pObjectGroup->lpszObjectName, lpszObjectName))
  889. {
  890. return (pObjectGroup) ;
  891. }
  892. else if (!pObjectGroup->pObjectGroupNext)
  893. { // if
  894. pObjectGroup->pObjectGroupNext =
  895. ObjectGroupCreate (lpszObjectName) ;
  896. if (pObjectGroup->pObjectGroupNext)
  897. {
  898. (pObjectGroup->pObjectGroupNext)->pParentSystem =
  899. pSystemGroup ;
  900. (pObjectGroup->pObjectGroupNext)->pObjectGroupPrevious =
  901. pObjectGroup ;
  902. }
  903. return (pObjectGroup->pObjectGroupNext) ;
  904. } // if
  905. } // for
  906. // if it falls through (which it shouldn't) at least return a
  907. // reasonable value
  908. return (pSystemGroup->pObjectGroupFirst) ;
  909. } // GetObjectGroup
  910. // ObjectGroupRemove removes the specified Object group
  911. // from the Object double link list
  912. BOOL ObjectGroupRemove (POBJECTGROUP *ppObjectGroupFirst,
  913. POBJECTGROUP pObjectGroupRemove)
  914. {
  915. POBJECTGROUP pObjectGroup ;
  916. if (*ppObjectGroupFirst == pObjectGroupRemove)
  917. {
  918. *ppObjectGroupFirst = (*ppObjectGroupFirst)->pObjectGroupNext ;
  919. if (*ppObjectGroupFirst)
  920. {
  921. // set up head of backward link list
  922. (*ppObjectGroupFirst)->pObjectGroupPrevious = NULL ;
  923. }
  924. // clean up the allocated memory
  925. ColumnGroupRemove (pObjectGroupRemove->pColumnGroupFirst) ;
  926. MemoryFree (pObjectGroupRemove->lpszObjectName) ;
  927. MemoryFree (pObjectGroupRemove) ;
  928. return (TRUE) ;
  929. }
  930. for (pObjectGroup = *ppObjectGroupFirst ;
  931. pObjectGroup->pObjectGroupNext ;
  932. pObjectGroup = pObjectGroup->pObjectGroupNext)
  933. { // for
  934. if (pObjectGroup->pObjectGroupNext == pObjectGroupRemove)
  935. {
  936. pObjectGroup->pObjectGroupNext = pObjectGroupRemove->pObjectGroupNext ;
  937. if (pObjectGroup->pObjectGroupNext)
  938. {
  939. (pObjectGroup->pObjectGroupNext)->pObjectGroupPrevious =
  940. pObjectGroup ;
  941. }
  942. // clean up this object allocated memory and its column groups
  943. ColumnGroupRemove (pObjectGroupRemove->pColumnGroupFirst) ;
  944. MemoryFree (pObjectGroupRemove->lpszObjectName) ;
  945. MemoryFree (pObjectGroupRemove) ;
  946. return (TRUE) ;
  947. } // if
  948. } // for
  949. return (FALSE) ;
  950. } // ObjectGroupRemove
  951. // ObjectRemoveItem is called when user delete the selected object
  952. PCOUNTERGROUP ObjectRemoveItem (PREPORT pReport,
  953. POBJECTGROUP pObjectGroup,
  954. BOOL bCleanUpLink,
  955. enum REPORT_ITEM_TYPE *pNewItemType)
  956. {
  957. PCOUNTERGROUP pCounterGroup, pNextCounterGroup ;
  958. PSYSTEMGROUP pSystemGroup ;
  959. PCOUNTERGROUP pRetCounterGroup = NULL ;
  960. pSystemGroup = pObjectGroup->pParentSystem ;
  961. // remove all counter groups from this object
  962. for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  963. pCounterGroup ;
  964. pCounterGroup = pNextCounterGroup )
  965. {
  966. pNextCounterGroup = pCounterGroup->pCounterGroupNext ;
  967. CounterRemoveItem (pReport, pCounterGroup, FALSE, NULL) ;
  968. }
  969. // remove all column groups from this group
  970. ColumnGroupRemove (pObjectGroup->pColumnGroupFirst) ;
  971. pObjectGroup->pColumnGroupFirst = NULL;
  972. if (bCleanUpLink)
  973. {
  974. // get next counter group to get the focus
  975. if (pNewItemType)
  976. {
  977. pRetCounterGroup = GetNextCounter (
  978. pSystemGroup,
  979. pObjectGroup,
  980. NULL) ;
  981. if (pRetCounterGroup)
  982. {
  983. *pNewItemType = REPORT_TYPE_COUNTER ;
  984. }
  985. }
  986. // remove this object from its parent system group
  987. ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
  988. if (!(pSystemGroup->pObjectGroupFirst))
  989. {
  990. SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ;
  991. }
  992. }
  993. else
  994. {
  995. // get rid of this object
  996. MemoryFree (pObjectGroup->lpszObjectName) ;
  997. MemoryFree (pObjectGroup) ;
  998. }
  999. return (pRetCounterGroup) ;
  1000. } // ObjectRemoveItem
  1001. //======================================//
  1002. // System Group routines //
  1003. //======================================//
  1004. void ReportSystemRect (PREPORT pReport,
  1005. PSYSTEMGROUP pSystemGroup,
  1006. LPRECT lpRect)
  1007. { // ReportSystemRect
  1008. lpRect->left = xSystemMargin ;
  1009. lpRect->top = pSystemGroup->yFirstLine ;
  1010. lpRect->right = lpRect->left + pSystemGroup->xWidth ;
  1011. lpRect->bottom = lpRect->top + pReport->yLineHeight ;
  1012. } // ReportSystemRect
  1013. PSYSTEMGROUP SystemGroupCreate (LPTSTR lpszSystemName)
  1014. { // SystemGroupCreate
  1015. PSYSTEMGROUP pSystemGroup ;
  1016. HDC hDC ;
  1017. PREPORT pReport ;
  1018. TCHAR szLine [LongTextLen] ;
  1019. pSystemGroup = MemoryAllocate (sizeof (SYSTEMGROUP)) ;
  1020. if (pSystemGroup)
  1021. {
  1022. pSystemGroup->pSystemGroupNext = NULL ;
  1023. pSystemGroup->pObjectGroupFirst = NULL ;
  1024. pSystemGroup->lpszSystemName = StringAllocate (lpszSystemName) ;
  1025. // get width of system name
  1026. hDC = GetDC (hWndReport) ;
  1027. if (hDC) {
  1028. pReport = ReportData (hWndReport) ;
  1029. SelectFont (hDC, pReport->hFontHeaders) ;
  1030. TSPRINTF (szLine, szSystemFormat, lpszSystemName) ;
  1031. pSystemGroup->xWidth = TextWidth (hDC, szLine) ;
  1032. ReleaseDC (hWndReport, hDC) ;
  1033. }
  1034. } // if
  1035. return (pSystemGroup) ;
  1036. } // SystemGroupCreate
  1037. PSYSTEMGROUP GetSystemGroup (PREPORT pReport,
  1038. LPTSTR lpszSystemName)
  1039. /*
  1040. Effect; Return a pointer to the system group of pReport with
  1041. a system name of lpszSystemName. If no system group
  1042. has that name, add a new system group.
  1043. */
  1044. { // GetSystemGroup
  1045. PSYSTEMGROUP pSystemGroup ;
  1046. if (!pReport->pSystemGroupFirst)
  1047. {
  1048. // add this system to the global system list
  1049. SystemAdd (&pReport->pSystemFirst, lpszSystemName, pReport->hWnd) ;
  1050. // now add it to the report
  1051. pReport->pSystemGroupFirst = SystemGroupCreate (lpszSystemName) ;
  1052. return (pReport->pSystemGroupFirst) ;
  1053. }
  1054. for (pSystemGroup = pReport->pSystemGroupFirst ;
  1055. pSystemGroup ;
  1056. pSystemGroup = pSystemGroup->pSystemGroupNext)
  1057. { // for
  1058. if (strsamei (pSystemGroup->lpszSystemName, lpszSystemName))
  1059. return (pSystemGroup) ;
  1060. else if (!pSystemGroup->pSystemGroupNext)
  1061. { // if
  1062. // add this system to the global system list
  1063. SystemAdd (&pReport->pSystemFirst, lpszSystemName, pReport->hWnd) ;
  1064. // and add it to the report list
  1065. pSystemGroup->pSystemGroupNext =
  1066. SystemGroupCreate (lpszSystemName) ;
  1067. if (pSystemGroup->pSystemGroupNext)
  1068. {
  1069. (pSystemGroup->pSystemGroupNext)->pSystemGroupPrevious =
  1070. pSystemGroup ;
  1071. }
  1072. return (pSystemGroup->pSystemGroupNext) ;
  1073. } // if
  1074. } // for
  1075. //if it falls through (which it shouldn't) at least return a
  1076. // reasonable value
  1077. return (pReport->pSystemGroupFirst) ;
  1078. } // GetSystemGroup
  1079. BOOL SystemGroupRemove (PSYSTEMGROUP *ppSystemGroupFirst,
  1080. PSYSTEMGROUP pSystemGroupRemove)
  1081. {
  1082. PSYSTEMGROUP pSystemGroup ;
  1083. if (*ppSystemGroupFirst == pSystemGroupRemove)
  1084. {
  1085. *ppSystemGroupFirst = (*ppSystemGroupFirst)->pSystemGroupNext ;
  1086. if (*ppSystemGroupFirst)
  1087. {
  1088. (*ppSystemGroupFirst)->pSystemGroupPrevious = NULL ;
  1089. }
  1090. MemoryFree (pSystemGroupRemove->lpszSystemName) ;
  1091. MemoryFree (pSystemGroupRemove) ;
  1092. return (TRUE) ;
  1093. }
  1094. for (pSystemGroup = *ppSystemGroupFirst ;
  1095. pSystemGroup->pSystemGroupNext ;
  1096. pSystemGroup = pSystemGroup->pSystemGroupNext)
  1097. { // for
  1098. if (pSystemGroup->pSystemGroupNext == pSystemGroupRemove)
  1099. {
  1100. pSystemGroup->pSystemGroupNext = pSystemGroupRemove->pSystemGroupNext ;
  1101. if (pSystemGroup->pSystemGroupNext)
  1102. {
  1103. (pSystemGroup->pSystemGroupNext)->pSystemGroupPrevious =
  1104. pSystemGroup ;
  1105. }
  1106. MemoryFree (pSystemGroupRemove->lpszSystemName) ;
  1107. MemoryFree (pSystemGroupRemove) ;
  1108. return (TRUE) ;
  1109. } // if
  1110. } // for
  1111. return (FALSE) ;
  1112. } // SystemGroupRemove
  1113. // SystemRemoveItem is called when user deletes the selected System
  1114. PCOUNTERGROUP SystemRemoveItem (PREPORT pReport,
  1115. PSYSTEMGROUP pSystemGroup,
  1116. BOOL bCleanUpLink,
  1117. enum REPORT_ITEM_TYPE *pNewItemType)
  1118. {
  1119. POBJECTGROUP pObjectGroup, pNextObjectGroup ;
  1120. PCOUNTERGROUP pRetCounterGroup = NULL ;
  1121. // remove all object groups from this system
  1122. for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  1123. pObjectGroup ;
  1124. pObjectGroup = pNextObjectGroup )
  1125. {
  1126. pNextObjectGroup = pObjectGroup->pObjectGroupNext ;
  1127. ObjectRemoveItem (pReport, pObjectGroup, FALSE, NULL) ;
  1128. }
  1129. if (bCleanUpLink)
  1130. {
  1131. if (pNewItemType)
  1132. {
  1133. pRetCounterGroup = GetNextCounter (
  1134. pSystemGroup,
  1135. NULL,
  1136. NULL) ;
  1137. if (pRetCounterGroup)
  1138. {
  1139. *pNewItemType = REPORT_TYPE_COUNTER ;
  1140. }
  1141. }
  1142. SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ;
  1143. }
  1144. else
  1145. {
  1146. // delete data from this system
  1147. MemoryFree (pSystemGroup->lpszSystemName) ;
  1148. MemoryFree (pSystemGroup) ;
  1149. }
  1150. return (pRetCounterGroup) ;
  1151. } // SystemRemoveItem
  1152. BOOL ReportChangeFocus (HWND hWnd,
  1153. PREPORT pReport,
  1154. REPORT_ITEM SelectedItem,
  1155. enum REPORT_ITEM_TYPE SelectedItemType,
  1156. int xOffset,
  1157. int yOffset,
  1158. RECT *pRect)
  1159. {
  1160. HDC hDC ;
  1161. BOOL RetCode = FALSE ; // FALSE ==> same item being hit
  1162. RECT Rect ;
  1163. REPORT_ITEM PreviousItem ;
  1164. enum REPORT_ITEM_TYPE PreviousItemType ;
  1165. if (pReport->CurrentItem.pLine != SelectedItem.pLine)
  1166. {
  1167. // not the same item
  1168. RetCode = TRUE ;
  1169. PreviousItemType = pReport->CurrentItemType ;
  1170. PreviousItem.pLine = pReport->CurrentItem.pLine ;
  1171. pReport->CurrentItemType = SelectedItemType ;
  1172. pReport->CurrentItem.pLine = SelectedItem.pLine ;
  1173. hDC = GetDC (hWnd) ;
  1174. if (!hDC)
  1175. return FALSE;
  1176. if (SelectedItemType == REPORT_TYPE_LINE)
  1177. {
  1178. SetWindowOrgEx (hDC, xOffset, yOffset, NULL) ;
  1179. SelectFont (hDC, pReport->hFont) ;
  1180. SetTextAlign (hDC, TA_RIGHT) ;
  1181. SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  1182. DrawReportValue (hDC, pReport, SelectedItem.pLine) ;
  1183. SetWindowOrgEx (hDC, -xOffset, -yOffset, NULL) ;
  1184. }
  1185. else
  1186. {
  1187. Rect = *pRect ;
  1188. Rect.top -= yOffset ;
  1189. Rect.bottom -= yOffset ;
  1190. Rect.right -= xOffset ;
  1191. Rect.left -= xOffset ;
  1192. InvalidateRect (hWnd, &Rect, TRUE) ;
  1193. }
  1194. if (PreviousItemType == REPORT_TYPE_LINE)
  1195. {
  1196. SetWindowOrgEx (hDC, xOffset, yOffset, NULL) ;
  1197. SelectFont (hDC, pReport->hFont) ;
  1198. SetTextAlign (hDC, TA_RIGHT) ;
  1199. SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  1200. DrawReportValue (hDC, pReport, PreviousItem.pLine) ;
  1201. }
  1202. else if (PreviousItemType != REPORT_TYPE_NOTHING)
  1203. {
  1204. if (PreviousItemType == REPORT_TYPE_SYSTEM)
  1205. {
  1206. ReportSystemRect (pReport, PreviousItem.pSystem, &Rect) ;
  1207. }
  1208. else if (PreviousItemType == REPORT_TYPE_OBJECT)
  1209. {
  1210. ReportObjectRect (pReport, PreviousItem.pObject, &Rect) ;
  1211. }
  1212. else if (PreviousItemType == REPORT_TYPE_COUNTER)
  1213. {
  1214. ReportCounterRect (pReport, PreviousItem.pCounter, &Rect) ;
  1215. }
  1216. else if (PreviousItemType == REPORT_TYPE_COLUMN)
  1217. {
  1218. ReportColumnRect (pReport, PreviousItem.pColumn, &Rect) ;
  1219. }
  1220. Rect.top -= yOffset ;
  1221. Rect.bottom -= yOffset ;
  1222. Rect.right -= xOffset ;
  1223. Rect.left -= xOffset ;
  1224. InvalidateRect (hWnd, &Rect, TRUE) ;
  1225. }
  1226. ReleaseDC (hWnd, hDC) ;
  1227. }
  1228. return (RetCode) ;
  1229. } // ReportChangeFocus
  1230. BOOL OnReportLButtonDown (HWND hWnd,
  1231. WORD xPos,
  1232. WORD yPos)
  1233. {
  1234. PREPORT pReport ;
  1235. PLINE pLine ;
  1236. REPORT_ITEM PreviousItem ;
  1237. REPORT_ITEM CurrentSelectedItem ;
  1238. enum REPORT_ITEM_TYPE PreviousItemType ;
  1239. RECT rect ;
  1240. POINT pt ;
  1241. int xOffset, yOffset ;
  1242. PSYSTEMGROUP pSystemGroup ;
  1243. POBJECTGROUP pObjectGroup ;
  1244. PCOUNTERGROUP pCounterGroup ;
  1245. PCOLUMNGROUP pColumnGroup ;
  1246. pReport = ReportData (hWnd) ;
  1247. if (!pReport)
  1248. return (FALSE) ;
  1249. xOffset = GetScrollPos (hWnd, SB_HORZ) ;
  1250. yOffset = GetScrollPos (hWnd, SB_VERT) ;
  1251. pt.x = xPos + xOffset ;
  1252. pt.y = yPos + yOffset ;
  1253. PreviousItem = pReport->CurrentItem ;
  1254. PreviousItemType = pReport->CurrentItemType ;
  1255. for (pLine = pReport->pLineFirst ;
  1256. pLine ;
  1257. pLine = pLine->pLineNext)
  1258. { // for
  1259. ReportLineValueRect (pReport, pLine, &rect) ;
  1260. if (PtInRect (&rect, pt))
  1261. {
  1262. CurrentSelectedItem.pLine = pLine ;
  1263. return (ReportChangeFocus (
  1264. hWnd,
  1265. pReport,
  1266. CurrentSelectedItem,
  1267. REPORT_TYPE_LINE,
  1268. xOffset,
  1269. yOffset,
  1270. &rect)) ;
  1271. }
  1272. } // for
  1273. // check on hit on system, object, counter, column (parent+isntance names)
  1274. for (pSystemGroup = pReport->pSystemGroupFirst ;
  1275. pSystemGroup ;
  1276. pSystemGroup = pSystemGroup->pSystemGroupNext)
  1277. { // for System...
  1278. ReportSystemRect (pReport, pSystemGroup, &rect) ;
  1279. if (PtInRect (&rect, pt))
  1280. {
  1281. CurrentSelectedItem.pSystem = pSystemGroup ;
  1282. return (ReportChangeFocus (
  1283. hWnd,
  1284. pReport,
  1285. CurrentSelectedItem,
  1286. REPORT_TYPE_SYSTEM,
  1287. xOffset,
  1288. yOffset,
  1289. &rect)) ;
  1290. }
  1291. for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  1292. pObjectGroup ;
  1293. pObjectGroup = pObjectGroup->pObjectGroupNext)
  1294. { // for Object...
  1295. ReportObjectRect (pReport, pObjectGroup, &rect) ;
  1296. if (PtInRect (&rect, pt))
  1297. {
  1298. CurrentSelectedItem.pObject = pObjectGroup ;
  1299. return (ReportChangeFocus (
  1300. hWnd,
  1301. pReport,
  1302. CurrentSelectedItem,
  1303. REPORT_TYPE_OBJECT,
  1304. xOffset,
  1305. yOffset,
  1306. &rect)) ;
  1307. }
  1308. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  1309. pColumnGroup ;
  1310. pColumnGroup = pColumnGroup->pColumnGroupNext)
  1311. { // for Column...
  1312. ReportColumnRect (pReport, pColumnGroup, &rect) ;
  1313. if (PtInRect (&rect, pt))
  1314. {
  1315. CurrentSelectedItem.pColumn = pColumnGroup ;
  1316. return (ReportChangeFocus (
  1317. hWnd,
  1318. pReport,
  1319. CurrentSelectedItem,
  1320. REPORT_TYPE_COLUMN,
  1321. xOffset,
  1322. yOffset,
  1323. &rect)) ;
  1324. }
  1325. } // for Column
  1326. for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  1327. pCounterGroup ;
  1328. pCounterGroup = pCounterGroup->pCounterGroupNext)
  1329. { // for Counter...
  1330. ReportCounterRect (pReport, pCounterGroup, &rect) ;
  1331. if (PtInRect (&rect, pt))
  1332. {
  1333. CurrentSelectedItem.pCounter = pCounterGroup ;
  1334. return (ReportChangeFocus (
  1335. hWnd,
  1336. pReport,
  1337. CurrentSelectedItem,
  1338. REPORT_TYPE_COUNTER,
  1339. xOffset,
  1340. yOffset,
  1341. &rect)) ;
  1342. }
  1343. } // for Counter...
  1344. } // for Object...
  1345. } // for System...
  1346. // nothing hit
  1347. return (FALSE) ;
  1348. } // OnReportLButtonDown
  1349. BOOL ReportDeleteItem (HWND hWnd)
  1350. /*
  1351. Effect: Delete the current selected item.
  1352. */
  1353. { // ReportDeleteItem
  1354. HDC hDC ;
  1355. PREPORT pReport ;
  1356. REPORT_ITEM NextItem ;
  1357. enum REPORT_ITEM_TYPE NextItemType ;
  1358. NextItemType = REPORT_TYPE_NOTHING ;
  1359. NextItem.pLine = NULL ;
  1360. pReport = ReportData (hWnd) ;
  1361. if (pReport->CurrentItemType == REPORT_TYPE_NOTHING)
  1362. {
  1363. // nothing to delete...
  1364. return (TRUE) ;
  1365. }
  1366. else if (pReport->CurrentItemType == REPORT_TYPE_LINE)
  1367. {
  1368. NextItem.pLine = LineRemoveItem (pReport, &NextItemType) ;
  1369. }
  1370. else if (pReport->CurrentItemType == REPORT_TYPE_SYSTEM)
  1371. {
  1372. NextItem.pCounter = SystemRemoveItem (
  1373. pReport,
  1374. pReport->CurrentItem.pSystem,
  1375. TRUE,
  1376. &NextItemType) ;
  1377. }
  1378. else if (pReport->CurrentItemType == REPORT_TYPE_OBJECT)
  1379. {
  1380. NextItem.pCounter = ObjectRemoveItem (
  1381. pReport,
  1382. pReport->CurrentItem.pObject,
  1383. TRUE,
  1384. &NextItemType) ;
  1385. }
  1386. else if (pReport->CurrentItemType == REPORT_TYPE_COUNTER)
  1387. {
  1388. NextItem.pCounter = CounterRemoveItem (
  1389. pReport,
  1390. pReport->CurrentItem.pCounter,
  1391. TRUE,
  1392. &NextItemType) ;
  1393. }
  1394. else if (pReport->CurrentItemType == REPORT_TYPE_COLUMN)
  1395. {
  1396. NextItem.pColumn = ColumnRemoveItem (
  1397. pReport,
  1398. pReport->CurrentItem.pColumn,
  1399. TRUE,
  1400. &NextItemType) ;
  1401. }
  1402. if (NextItemType != REPORT_TYPE_NOTHING)
  1403. {
  1404. pReport->CurrentItem.pLine = NextItem.pLine ;
  1405. pReport->CurrentItemType = NextItemType ;
  1406. }
  1407. else
  1408. {
  1409. pReport->CurrentItem.pLine = pReport->pLineFirst ;
  1410. pReport->CurrentItemType = REPORT_TYPE_LINE ;
  1411. }
  1412. if (pReport->pLineFirst)
  1413. {
  1414. BuildValueListForSystems (
  1415. pReport->pSystemFirst,
  1416. pReport->pLineFirst) ;
  1417. }
  1418. else
  1419. {
  1420. // no more line, no more timer...
  1421. pReport->xWidth = 0 ;
  1422. pReport->yHeight = 0 ;
  1423. pReport->xMaxCounterWidth = 0 ;
  1424. ClearReportTimer (pReport) ;
  1425. FreeSystems (pReport->pSystemFirst) ;
  1426. pReport->pSystemFirst = NULL ;
  1427. pReport->pSystemGroupFirst = NULL ;
  1428. pReport->CurrentItemType = REPORT_TYPE_NOTHING ;
  1429. pReport->CurrentItem.pLine = NULL ;
  1430. }
  1431. //=============================//
  1432. // Calculate report positions //
  1433. //=============================//
  1434. hDC = GetDC (hWnd) ;
  1435. if (hDC) {
  1436. SetReportPositions (hDC, pReport) ;
  1437. if (!pReport->pLineFirst)
  1438. {
  1439. SelectFont (hDC, pReport->hFont) ;
  1440. pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  1441. }
  1442. ReleaseDC (hWnd, hDC) ;
  1443. }
  1444. WindowInvalidate (hWnd) ;
  1445. return (TRUE) ;
  1446. } // ReportDeleteItem