//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1998. // // File: winsplit.cxx // // Contents: Contains the code to do a window split. // // Classes: CTableWindowSplit // // Functions: // // History: 1-08-95 srikants Created // //---------------------------------------------------------------------------- #include "pch.cxx" #pragma hdrstop #include "winsplit.hxx" #include "tabledbg.hxx" //+--------------------------------------------------------------------------- // // Function: CTableWindowSplit ~ctor // // Synopsis: Constructor for the CTableWindowSplit class. // // Arguments: [srcWindow] - The source window that needs to be // split // [iSplitVisibleRowIndex] - Index in the source window's visible // row index which is the split index. All rows <= // iSplitVisibleRowIndex will be in the left hand window and the rest // in the right hand window after the split. // // History: 1-09-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- CTableWindowSplit::CTableWindowSplit( CTableWindow & srcWindow, ULONG iSplitQueryRowIndex, ULONG segIdLeft, ULONG segIdRight, BOOL fIsLastSegment ) : _srcWindow(srcWindow), _pLeftWindow(0), _pRightWindow(0), _srcQueryRowIndex(srcWindow._GetInvisibleRowIndex()), _srcClientRowIndex(srcWindow._GetVisibleRowIndex()), _iSplitQueryRowIndex(iSplitQueryRowIndex), _iSplitClientRowIndex(-1), _segIdLeft(segIdLeft), _segIdRight(segIdRight), _fIsLastSegment(fIsLastSegment) { Win4Assert( _srcQueryRowIndex.RowCount() >= 2 ); Win4Assert( iSplitQueryRowIndex < _srcQueryRowIndex.RowCount()-1 ); if ( _srcWindow.IsWatched() ) { // // The source window has watch regions. The dynamic rowindex must // also be split. // TBL_OFF oQuerySplitRow = _srcQueryRowIndex.GetRow( iSplitQueryRowIndex ); _iSplitClientRowIndex = _srcClientRowIndex.FindSplitPoint( oQuerySplitRow )-1; } } //+--------------------------------------------------------------------------- // // Function: ~CTableWindowSplit ~dtor for the CTableWindowSplit class // // Synopsis: Frees up the resources // // History: 1-09-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- CTableWindowSplit::~CTableWindowSplit() { delete _pLeftWindow; delete _pRightWindow; } //+--------------------------------------------------------------------------- // // Function: CreateTargetWindows // // Synopsis: Creates the target windows and initializes their // notification region based on the source window notification // region. // // History: 1-09-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- void CTableWindowSplit::CreateTargetWindows() { // // First create the left and right windows // Win4Assert( 0 == _pLeftWindow ); Win4Assert( 0 == _pRightWindow ); _pLeftWindow = new CTableWindow( _srcWindow, _segIdLeft ); _pRightWindow = new CTableWindow( _srcWindow, _segIdRight ); } //+--------------------------------------------------------------------------- // // Function: TransferTargetWindows // // Synopsis: Transfers the control of the target windows to the caller. // // Arguments: [ppLeftWindow] - (output) The pointer to the left window. // [ppRightWindow] - (output) The pointer to the right window. // // History: 1-09-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- void CTableWindowSplit::TransferTargetWindows( CTableWindow ** ppLeftWindow, CTableWindow ** ppRightWindow ) { Win4Assert( 0 != ppLeftWindow && 0 != ppRightWindow ); *ppLeftWindow = _pLeftWindow; _pLeftWindow = 0; *ppRightWindow = _pRightWindow; _pRightWindow = 0; } //+--------------------------------------------------------------------------- // // Function: _CopyWithoutNotifications // // Synopsis: Copies rows from the source window to the destination window. Only // the rows in the "srcRowIndex" will be copied to the // destination. // // Arguments: [destWindow] - Target window to copy to. // [srcRowIndex] - The source row index. // [iStartRowIndex] - Starting offset in the row index to start // copying rows from. // [iEndRowIndex] - Ending offset in the row index to stop // copying. // // History: 1-09-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- void CTableWindowSplit::_CopyWithoutNotifications( CTableWindow & destWindow, CRowIndex & srcRowIndex, ULONG iStartRowIndex, ULONG iEndRowIndex ) { Win4Assert( iEndRowIndex < srcRowIndex.RowCount() ); for ( ULONG i = iStartRowIndex; i <= iEndRowIndex; i++ ) { destWindow._PutRowToVisibleRowIndex( _srcWindow, srcRowIndex.GetRow(i) ); } } //+--------------------------------------------------------------------------- // // Function: _SimpleSplit // // Synopsis: Does a simple split in which the first half of the rows from // the source row index will be copied to the left window and the // second half to the right window. // // History: 1-31-95 srikants Created // // Notes: This must be called only when there is no notification region // in the source window. // //---------------------------------------------------------------------------- void CTableWindowSplit::_SimpleSplit() { Win4Assert( !_srcWindow.IsWatched() ); // // The source notifcation region is completely empty. We have to copy from // the visible row index only. // tbDebugOut(( DEB_WINSPLIT, "CTableWindowSplit::Simple Split\n" )); _CopyWithoutNotifications( *_pLeftWindow, _srcQueryRowIndex, 0, _iSplitQueryRowIndex ); _CopyWithoutNotifications( *_pRightWindow, _srcQueryRowIndex, _iSplitQueryRowIndex+1, _srcQueryRowIndex.RowCount()-1 ); } //+--------------------------------------------------------------------------- // // Function: DoSplit // // Synopsis: Splits the source window into left and right windows. // // History: 1-09-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- void CTableWindowSplit::DoSplit() { Win4Assert( 0 != _pLeftWindow && 0 != _pRightWindow ); _pLeftWindow->_SetSplitInProgress(); _pRightWindow->_SetSplitInProgress(); if ( !_srcWindow.IsWatched() ) { // // The source notifcation region is completely empty. We have to copy from // the visible row index only. // Win4Assert( -1 == _iSplitClientRowIndex ); _SimpleSplit(); _pLeftWindow->_SetSplitDone(); _pRightWindow->_SetSplitDone(); } else { // // If notifications are enabled in the target window, then we must copy // both the client row index and the query row index. O/W, just copy // the contents of the query row index. // // // Copy the contents to the target left window. // tbDebugOut(( DEB_WINSPLIT, "Left Window with Notifications\n" )); _CopyWithNotifications( *_pLeftWindow, 0, _iSplitQueryRowIndex, 0, _iSplitClientRowIndex ); // // Copy the contents to the target right window. // tbDebugOut(( DEB_WINSPLIT, "Right Window with Notifications\n" )); _CopyWithNotifications( *_pRightWindow, _iSplitQueryRowIndex+1, _srcQueryRowIndex.RowCount()-1, _iSplitClientRowIndex+1, _srcClientRowIndex.RowCount()-1 ); // // Now apply the watch regions on the new windows. // _CopyWatchRegions(); // // Indicate that the split is done. // _pLeftWindow->_SetSplitDone(); _pRightWindow->_SetSplitDone(); // // If any of the windows doesn't have any watch regions, we have to // do a state change to delete the dynamic/static split. // Win4Assert( _pLeftWindow->IsWatched() || _pRightWindow->IsWatched() ); if ( !_pLeftWindow->IsWatched() ) { _pLeftWindow->_EndStaticDynamicSplit(); } if ( !_pRightWindow->IsWatched() ) { _pRightWindow->_EndStaticDynamicSplit(); } } // // Setup the lowest & highest keys for the left and right windows. // _srcWindow.GetSortKey( 0, _pLeftWindow->GetLowestKey() ); _srcWindow.GetSortKey( _iSplitQueryRowIndex+1, _pRightWindow->GetLowestKey() ); _srcWindow.GetSortKey( _iSplitQueryRowIndex, _pLeftWindow->GetHighestKey() ); _srcWindow.GetSortKey( (ULONG) _srcWindow.RowCount()-1, _pRightWindow->GetHighestKey() ); } //+--------------------------------------------------------------------------- // // Function: _CopyWithNotifications // // Synopsis: Copies contents of both the "visible" and "dynamic" row index // from the source window to the destination window. // // Arguments: [destWindow] - Destination window to copy to. // [iStartVisRowIndex] - Starting offset in the visible rowindex. // [iEndVisRowIndex] - Ending offset in the visible rowindex. // [iStartDynRowIndex] - Starting offset in the dynamic rowindex. // [iEndDynRowIndex] - Ending offset in the dynamic rowindex. // // History: 1-09-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- void CTableWindowSplit::_CopyWithNotifications( CTableWindow & destWindow, ULONG iStartQueryRowIndex, ULONG iEndQueryRowIndex, LONG iStartClientRowIndex, LONG iEndClientRowIndex ) { Win4Assert( _srcWindow.IsWatched() ); Win4Assert( iStartQueryRowIndex < _srcQueryRowIndex.RowCount() ); Win4Assert( iEndQueryRowIndex >= iStartQueryRowIndex && iEndQueryRowIndex < _srcQueryRowIndex.RowCount() ); // // Copy the rows from the client row index. // for ( LONG j = iStartClientRowIndex; j <= iEndClientRowIndex; j++ ) { destWindow._PutRowToVisibleRowIndex( _srcWindow, _srcClientRowIndex.GetRow(j) ); } // // Copy the rows from the query row index. // for ( ULONG i = iStartQueryRowIndex; i <= iEndQueryRowIndex; i++ ) { destWindow._PutRowToDynRowIndex( _srcWindow, _srcQueryRowIndex.GetRow(i) ); } } //+--------------------------------------------------------------------------- // // Member: CTableWindowSplit::_IsOffsetInLeftWindow // // Synopsis: // // Arguments: [iOffset] - // // Returns: // // Modifies: // // History: 7-27-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- inline BOOL CTableWindowSplit::_IsOffsetInLeftWindow( long iOffset ) { return iOffset <= _iSplitClientRowIndex; } //+--------------------------------------------------------------------------- // // Member: CTableWindowSplit::_CopyWatchRegions // // Synopsis: // // Modifies: // // History: 7-27-95 srikants Created // // Notes: // //---------------------------------------------------------------------------- void CTableWindowSplit::_CopyWatchRegions() { Win4Assert( _srcWindow.IsWatched() ); for ( unsigned i = 0; i < _srcWindow._aWindowWatch.Count(); i++ ) { CWindowWatch & watch = _srcWindow._aWindowWatch.Get(i); long cResidual = watch._cRowsLeft; if ( _IsOffsetInLeftWindow( watch._iRowStart ) ) { cResidual -= _pLeftWindow->AddWatch( watch._hRegion, watch._iRowStart, cResidual, FALSE ); if ( cResidual > 0 ) { _pRightWindow->AddWatch( watch._hRegion, 0, cResidual, _fIsLastSegment ); } } else { // // The offset must be in the right hand side window. // Win4Assert( watch._iRowStart > _iSplitClientRowIndex && watch._iRowStart < (long) _srcWindow.RowCount() ); Win4Assert( (long) _pLeftWindow->RowCount() == _iSplitClientRowIndex+1 ); _pRightWindow->AddWatch( watch._hRegion, (LONG) (watch._iRowStart - _pLeftWindow->RowCount()), cResidual, _fIsLastSegment ); } } }