|
|
//+---------------------------------------------------------------------------
//
// 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 ); }
} }
|