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.

525 lines
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 2000.
  5. //
  6. // File: wregion.cxx
  7. //
  8. // Contents: Watch region list
  9. //
  10. // Classes: CWatchRegion
  11. //
  12. // History: 20-Jun-95 BartoszM Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <wregion.hxx>
  18. #include <seglist.hxx>
  19. #include "tblwindo.hxx"
  20. //+-------------------------------------------------------------------------
  21. //
  22. // Member: CWatchRegion::CWatchRegion
  23. //
  24. // Synopsis: Assign default values
  25. //
  26. // History: 20-Jun-95 BartoszM Created
  27. //
  28. //--------------------------------------------------------------------------
  29. CWatchRegion::CWatchRegion ( ULONG mode)
  30. : _mode (mode),
  31. _chapter(0),
  32. _bookmark(0),
  33. _cRows(0),
  34. _pSegment (0)
  35. {
  36. }
  37. //+-------------------------------------------------------------------------
  38. //
  39. // Member: CWatchList::CWatchList
  40. //
  41. // Synopsis: Initialize
  42. //
  43. // History: 20-Jun-95 BartoszM Created
  44. //
  45. //--------------------------------------------------------------------------
  46. CWatchList::CWatchList(CTableSegList& segList)
  47. : _segList(segList)
  48. {
  49. }
  50. //+-------------------------------------------------------------------------
  51. //
  52. // Member: CWatchList::~CWatchList
  53. //
  54. // Synopsis: Deletes all watch regions
  55. //
  56. // History: 20-Jun-95 BartoszM Created
  57. //
  58. //--------------------------------------------------------------------------
  59. CWatchList::~CWatchList ()
  60. {
  61. CWatchRegion* p;
  62. while ( (p = _list.Pop()) != 0)
  63. delete p;
  64. }
  65. //+-------------------------------------------------------------------------
  66. //
  67. // Member: CWatchList::NewRegion
  68. //
  69. // Synopsis: Create new empty region
  70. //
  71. // History: 20-Jun-95 BartoszM Created
  72. //
  73. //--------------------------------------------------------------------------
  74. HWATCHREGION CWatchList::NewRegion (ULONG mode)
  75. {
  76. CWatchRegion* pRegion = new CWatchRegion(mode);
  77. _list.Add (pRegion);
  78. return (HWATCHREGION) pRegion;
  79. }
  80. //+-------------------------------------------------------------------------
  81. //
  82. // Member: CWatchList::ChangeMode
  83. //
  84. // Synopsis: Change region mode
  85. //
  86. // History: 20-Jun-95 BartoszM Created
  87. //
  88. //--------------------------------------------------------------------------
  89. void CWatchList::ChangeMode ( HWATCHREGION hRegion, ULONG mode )
  90. {
  91. CWatchRegion* pRegion = FindVerify (hRegion);
  92. pRegion->SetMode (mode);
  93. }
  94. //+-------------------------------------------------------------------------
  95. //
  96. // Member: CWatchList::GetInfo, private
  97. //
  98. // Synopsis: GetInfo about a watch region
  99. //
  100. // History: 20-Jun-95 BartoszM Created
  101. //
  102. //--------------------------------------------------------------------------
  103. void CWatchList::GetInfo (HWATCHREGION hRegion,
  104. CI_TBL_CHAPT* pChapter,
  105. CI_TBL_BMK* pBookmark,
  106. DBCOUNTITEM* pcRows)
  107. {
  108. CWatchRegion* pRegion = FindVerify (hRegion);
  109. *pChapter = pRegion->Chapter();
  110. *pBookmark = pRegion->Bookmark();
  111. *pcRows = pRegion->RowCount();
  112. }
  113. //+-------------------------------------------------------------------------
  114. //
  115. // Member: CWatchList::BuildRegion
  116. //
  117. // Synopsis: Build watch region
  118. //
  119. // History: 22-Jun-95 BartoszM Created
  120. //
  121. //--------------------------------------------------------------------------
  122. void CWatchList::BuildRegion ( HWATCHREGION hRegion,
  123. CTableSegment* pSegment,
  124. CI_TBL_CHAPT chapter,
  125. CI_TBL_BMK bookmark,
  126. LONG cRows )
  127. {
  128. Win4Assert (cRows > 0);
  129. CWatchRegion* pRegion = FindVerify (hRegion);
  130. pRegion->SetSegment(pSegment);
  131. pRegion->Set (chapter, bookmark, cRows);
  132. CDoubleTableSegIter iter (pSegment);
  133. CTableWindow* pWindow = iter.GetWindow();
  134. // Add watch to the first window in series
  135. int cRowsAdded;
  136. if (bookmark == WORKID_TBLFIRST)
  137. {
  138. cRowsAdded = pWindow->AddWatch (hRegion, 0, cRows, _segList.IsLast(iter));
  139. }
  140. else
  141. {
  142. TBL_OFF off;
  143. ULONG uiStart;
  144. if ( !pWindow->FindBookMark( bookmark, off, uiStart))
  145. {
  146. Win4Assert (!"CWatchList::BuildRegion, bookmark not found" );
  147. }
  148. cRowsAdded = pWindow->AddWatch (hRegion, (long)uiStart, cRows, _segList.IsLast(iter));
  149. }
  150. while (cRowsAdded < cRows)
  151. {
  152. // continue through another segment
  153. _segList.Advance(iter);
  154. Win4Assert ( iter.GetSegment()->IsWindow());
  155. pWindow = iter.GetWindow();
  156. cRowsAdded += pWindow->AddWatch (hRegion, 0, cRows - cRowsAdded, _segList.IsLast(iter));
  157. }
  158. }
  159. //+-------------------------------------------------------------------------
  160. //
  161. // Member: CWatchList::DeleteRegion
  162. //
  163. // Synopsis: Delete watch region
  164. //
  165. // History: 20-Jun-95 BartoszM Created
  166. //
  167. //--------------------------------------------------------------------------
  168. void CWatchList::DeleteRegion (HWATCHREGION hRegion)
  169. {
  170. ShrinkRegionToZero (hRegion);
  171. CWatchRegion* pRegion = GetRegion(hRegion);
  172. pRegion->Unlink();
  173. delete pRegion;
  174. }
  175. //+-------------------------------------------------------------------------
  176. //
  177. // Member: CWatchList::ShrinkRegionToZero
  178. //
  179. // Synopsis: Shrink watch region to zero but don't delete it
  180. // (e.g., prepare to move the region discontinuously)
  181. //
  182. // History: 27-Jun-95 BartoszM Created
  183. //
  184. //--------------------------------------------------------------------------
  185. void CWatchList::ShrinkRegionToZero (HWATCHREGION hRegion)
  186. {
  187. CWatchRegion* pRegion = FindVerify (hRegion);
  188. if (pRegion->Segment())
  189. {
  190. CDoubleTableSegIter iter (pRegion->Segment());
  191. long cRowsLeft = pRegion->RowCount();
  192. do
  193. {
  194. CTableWindow* pWindow = iter.GetWindow();
  195. cRowsLeft -= pWindow->DeleteWatch (pRegion->Handle());
  196. if (cRowsLeft <= 0 )
  197. break;
  198. _segList.Advance(iter);
  199. } while (!_segList.AtEnd(iter));
  200. }
  201. pRegion->SetSegment(0);
  202. }
  203. //+-------------------------------------------------------------------------
  204. //
  205. // Member: CWatchList::ShrinkRegion
  206. //
  207. // Synopsis: Shrink watch region
  208. //
  209. // History: 20-Jun-95 BartoszM Created
  210. //
  211. //--------------------------------------------------------------------------
  212. void CWatchList::ShrinkRegion ( HWATCHREGION hRegion,
  213. CI_TBL_CHAPT chapter,
  214. CI_TBL_BMK bookmark,
  215. LONG cRows )
  216. {
  217. // Werify arguments
  218. if (cRows < 0)
  219. {
  220. THROW (CException(E_INVALIDARG));
  221. }
  222. else if ( cRows == 0)
  223. {
  224. DeleteRegion (hRegion);
  225. return;
  226. }
  227. // BROKENCODE: verify validity of chapter / bookmark
  228. CWatchRegion* pRegion = FindVerify (hRegion);
  229. long cRowsLeft = pRegion->RowCount();
  230. if (cRows > cRowsLeft)
  231. {
  232. THROW (CException(DB_E_NOTASUBREGION));
  233. }
  234. // Find starting window of the old region
  235. if (pRegion->Segment() == 0)
  236. THROW (CException(E_INVALIDARG));
  237. CDoubleTableSegIter iter (pRegion->Segment());
  238. // find starting window of the new region
  239. CTableWindow* pWindowBmk = 0;
  240. if (bookmark == WORKID_TBLFIRST)
  241. {
  242. CTableSegment* pSeg = _segList.GetTop();
  243. if (!pSeg->IsWindow())
  244. {
  245. THROW (CException(DB_E_NOTASUBREGION));
  246. }
  247. pWindowBmk = (CTableWindow*) pSeg;
  248. }
  249. else
  250. {
  251. CDoubleTableSegIter iter2 (iter.GetSegment()); // clone it
  252. do
  253. {
  254. if ( iter2.GetSegment()->IsRowInSegment( bookmark ) )
  255. break;
  256. _segList.Advance(iter2);
  257. } while (!_segList.AtEnd(iter2));
  258. if (_segList.AtEnd(iter2))
  259. {
  260. THROW (CException(DB_E_NOTASUBREGION));
  261. }
  262. pWindowBmk = iter2.GetWindow();
  263. if (!pWindowBmk->IsWatched (hRegion, bookmark))
  264. {
  265. THROW (CException(DB_E_NOTASUBREGION));
  266. }
  267. }
  268. // Real work starts here
  269. // we know that the bookmark is within the old watch region
  270. // delete watch regions before the bookmark
  271. CTableWindow* pWindow = iter.GetWindow();
  272. while ( pWindow != pWindowBmk)
  273. {
  274. cRowsLeft -= pWindow->DeleteWatch (hRegion);
  275. Win4Assert (cRowsLeft > 0);
  276. _segList.Advance(iter);
  277. Win4Assert (!_segList.AtEnd(iter));
  278. pWindow = iter.GetWindow();
  279. }
  280. // Beginning of new region
  281. pRegion->SetSegment (pWindow);
  282. // Shrink the watch in the first window in series
  283. long cRowsInRegion = 0;
  284. cRowsInRegion = pWindow->ShrinkWatch( hRegion, bookmark, cRows );
  285. // continue through windows that will stay in the watch region
  286. while (cRowsInRegion < cRows)
  287. {
  288. _segList.Advance(iter);
  289. if (_segList.AtEnd(iter)
  290. || !iter.GetSegment()->IsWindow()
  291. || !iter.GetWindow()->HasWatch(hRegion))
  292. {
  293. // Leave in consistent state
  294. pRegion->Set (chapter, bookmark, cRowsInRegion);
  295. THROW (CException(DB_E_NOTASUBREGION));
  296. }
  297. // the watch continues in this window
  298. pWindow = iter.GetWindow();
  299. cRowsInRegion += pWindow->RowsWatched (hRegion);
  300. }
  301. // Shrink the last segment of the new watch region
  302. if (cRowsInRegion > cRows)
  303. {
  304. long cDelta = cRowsInRegion-cRows;
  305. long cRowsRemaining = pWindow->RowsWatched(hRegion) - cDelta;
  306. Win4Assert( cRowsRemaining > 0 );
  307. pWindow->ShrinkWatch( hRegion, cRowsRemaining);
  308. }
  309. pRegion->Set (chapter, bookmark, cRows);
  310. // delete the rest of the old watch region
  311. for ( _segList.Advance(iter);
  312. !_segList.AtEnd(iter)
  313. && iter.GetSegment()->IsWindow()
  314. && iter.GetWindow()->HasWatch(hRegion);
  315. _segList.Advance(iter) )
  316. {
  317. // the watch continues in this window
  318. iter.GetWindow()->DeleteWatch (hRegion);
  319. }
  320. #if CIDBG==1
  321. CheckRegionConsistency( pRegion );
  322. #endif // CIDBG==1
  323. }
  324. //+---------------------------------------------------------------------------
  325. //
  326. // Function: FindRegion
  327. //
  328. // Synopsis:
  329. //
  330. // Arguments: [hRegion] -
  331. //
  332. // Returns:
  333. //
  334. // Modifies:
  335. //
  336. // History: 7-05-95 srikants Created
  337. //
  338. // Notes:
  339. //
  340. //----------------------------------------------------------------------------
  341. CWatchRegion * CWatchList::FindRegion(HWATCHREGION hRegion)
  342. {
  343. for (CWatchIter iter(_list); !_list.AtEnd(iter); _list.Advance(iter))
  344. {
  345. if (iter->IsEqual(hRegion))
  346. break;
  347. }
  348. if (_list.AtEnd(iter))
  349. {
  350. return 0;
  351. }
  352. else
  353. {
  354. return iter.Get();
  355. }
  356. }
  357. //+-------------------------------------------------------------------------
  358. //
  359. // Member: CWatchList::FindVerify
  360. //
  361. // Synopsis: Find watch region, throw if not found
  362. //
  363. // History: 20-Jun-95 BartoszM Created
  364. //
  365. //--------------------------------------------------------------------------
  366. CWatchRegion* CWatchList::FindVerify (HWATCHREGION hRegion)
  367. {
  368. CWatchRegion * pRegion = FindRegion( hRegion );
  369. if ( 0 != pRegion )
  370. {
  371. return pRegion;
  372. }
  373. else
  374. {
  375. THROW (CException(DB_E_BADREGIONHANDLE));
  376. }
  377. return 0; // Keep the compiler happy
  378. }
  379. //+---------------------------------------------------------------------------
  380. //
  381. // Member: CWatchRegion::UpdateSegment
  382. //
  383. // Synopsis: Updates the segment in the region to point to the new one
  384. // if the current one is same as pOld.
  385. //
  386. // Arguments: [pOld] -
  387. // [pNew] -
  388. //
  389. // History: 8-16-95 srikants Created
  390. //
  391. // Notes:
  392. //
  393. //----------------------------------------------------------------------------
  394. void CWatchRegion::UpdateSegment( CTableSegment * pOld,
  395. CTableWindow *pNew,
  396. CI_TBL_BMK bmkNew )
  397. {
  398. Win4Assert( 0 != pNew );
  399. if ( _pSegment == pOld )
  400. {
  401. Win4Assert( pNew->HasWatch( Handle()) );
  402. _pSegment = pNew;
  403. // NEWFEATURE - how about chapter ??
  404. _bookmark = bmkNew;
  405. }
  406. }
  407. #if CIDBG == 1
  408. //+---------------------------------------------------------------------------
  409. //
  410. // Member: CWatchList::CheckRegionConsistency
  411. //
  412. // Synopsis: Checks that the length of the region as stored in the
  413. // region is same as the cumulative length of all the watch
  414. // in the windows.
  415. //
  416. // Arguments: [pRegion] - Region which must be checked.
  417. //
  418. // History: 8-16-95 srikants Created
  419. //
  420. // Notes:
  421. //
  422. //----------------------------------------------------------------------------
  423. void CWatchList::CheckRegionConsistency( CWatchRegion * pRegion )
  424. {
  425. if ( 0 != pRegion && 0 != pRegion->Segment() )
  426. {
  427. HWATCHREGION hRegion = pRegion->Handle();
  428. CDoubleTableSegIter iter( pRegion->Segment() );
  429. for ( long cRegionLen = 0;
  430. !_segList.AtEnd(iter) &&
  431. iter.GetSegment()->IsWindow() &&
  432. iter.GetWindow()->HasWatch(hRegion);
  433. _segList.Advance(iter) )
  434. {
  435. CTableWindow * pWindow = iter.GetWindow();
  436. long cRowsInWindow = pWindow->RowsWatched(hRegion);
  437. Win4Assert( cRowsInWindow >= 0 );
  438. cRegionLen += cRowsInWindow;
  439. }
  440. Win4Assert( cRegionLen == pRegion->RowCount() );
  441. }
  442. }
  443. #endif // CIDBG==1