Пример #1
0
BOOL NodeSimpleShape::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
						Spread* pSpread )
{
	PORTNOTETRACE("other","NodeSimpleShape::OnClick - do nothing");

#if !defined(EXCLUDE_FROM_RALPH)
	// we only handle the click if we can confirm that object blobs are being displayed.
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
	if (pBlobMgr == NULL)
		return FALSE;
	if (!pBlobMgr->GetCurrentInterest().Object)
		return FALSE;

	INT32 ClickCorner;

	if (IsNearControlHandle(PointerPos, &ClickCorner))
	{
		// The click was over a control point, so start the drag and tell it the opposite corner
		if (Click==CLICKTYPE_DRAG)
			HandleBlobDrag(Parallel[ClickCorner], pSpread, (ClickCorner+2)%4 ); 
			
		// we have used that click up, so tell the world
		return TRUE;
	}
#endif
	// did not use the click
	return FALSE;
}
Пример #2
0
BOOL NodeSimpleShape::IsNearControlHandle(DocCoord Coord, INT32* CoordNum)
{
#if !defined(EXCLUDE_FROM_RALPH)
	// Find the blob manager
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
	if (pBlobMgr==NULL)
		return FALSE;

	// Find out about the size of a blob
	DocRect BlobRect;
	pBlobMgr->GetBlobRect(Coord, &BlobRect);

	// Check to see if it is near any of the blobs
	for (INT32 i=0; i<4; i++)
	{
		// Check for collision with the control points
		if (BlobRect.ContainsCoord(Parallel[i]))
		{
			// Tell them which control point it waas over
			*CoordNum = i;

			// we have used that click up, so tell the world
			return TRUE;
		}
	}
#endif	
	// was not over any of the control points
	return FALSE;
}
Пример #3
0
    void replaceWithSmallTest(void)
    {
        ham_u8_t buffer[128], buffer2[64];
        ham_offset_t blobid, blobid2;
        ham_record_t record;
        ::memset(&record,  0, sizeof(record));
        ::memset(&buffer,  0x12, sizeof(buffer));
        ::memset(&buffer2, 0x15, sizeof(buffer2));

        record.data=buffer;
        record.size=sizeof(buffer);
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->allocate((Database *)m_db, &record,
                                0, &blobid));
        BFC_ASSERT(blobid!=0);

        BFC_ASSERT_EQUAL(0,
                m_blob_manager->read((Database *)m_db, 0, blobid, &record, 0));
        BFC_ASSERT_EQUAL(record.size, (ham_size_t)sizeof(buffer));
        BFC_ASSERT(0==::memcmp(buffer, record.data, record.size));

        record.size=sizeof(buffer2);
        record.data=buffer2;
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->overwrite((Database *)m_db,
                                blobid, &record, 0, &blobid2));
        BFC_ASSERT(blobid2!=0);

        BFC_ASSERT_EQUAL(0,
                m_blob_manager->read((Database *)m_db, 0, blobid2, &record, 0));
        BFC_ASSERT_EQUAL(record.size, (ham_size_t)sizeof(buffer2));
        BFC_ASSERT(0==::memcmp(buffer2, record.data, record.size));

        /* make sure that at least 64bit are in the freelist */
        if (!m_inmemory) {
            ham_offset_t addr;
            Environment *e=(Environment *)m_env;
            BFC_ASSERT_EQUAL(0, e->get_freelist()->alloc_area(&addr,
                                        (Database *)m_db, 64));
            BFC_ASSERT(addr!=0);
        }

        BFC_ASSERT_EQUAL(0,
                m_blob_manager->free((Database *)m_db, blobid2, 0));

        /* and now another 64bit should be in the freelist */
        if (!m_inmemory) {
            ham_offset_t addr;
            Environment *e=(Environment *)m_env;
            BFC_ASSERT_EQUAL(0, e->get_freelist()->alloc_area(&addr,
                                        (Database *)m_db, 64));
            BFC_ASSERT(addr!=0);
        }
    }
Пример #4
0
    void loopInsert(int loops, int factor)
    {
        ham_u8_t *buffer;
        ham_offset_t *blobid;
        ham_record_t record;
        ham_txn_t *txn = 0; /* need a txn object for the blob routines */
        ::memset(&record, 0, sizeof(record));
        ::memset(&buffer, 0x12, sizeof(buffer));

        blobid=(ham_offset_t *)::malloc(sizeof(ham_offset_t)*loops);
        BFC_ASSERT(blobid!=0);
        if (!m_inmemory && m_use_txn)
            BFC_ASSERT(ham_txn_begin(&txn, m_env, 0, 0, 0)==HAM_SUCCESS);

        for (int i=0; i<loops; i++) {
            buffer=(ham_u8_t *)::malloc((i+1)*factor);
            BFC_ASSERT_I(buffer!=0, i);
            ::memset(buffer, (char)i, (i+1)*factor);

            ham_record_t rec={0};
            rec.data=buffer;
            rec.size=(ham_size_t)((i+1)*factor);
            BFC_ASSERT_EQUAL(0,
                        m_blob_manager->allocate((Database *)m_db, &rec,
                                    0, &blobid[i]));
            BFC_ASSERT_I(blobid[i]!=0, i);

            ::free(buffer);
        }

        for (int i=0; i<loops; i++) {
            buffer=(ham_u8_t *)::malloc((i+1)*factor);
            BFC_ASSERT_I(buffer!=0, i);
            ::memset(buffer, (char)i, (i+1)*factor);

            BFC_ASSERT_EQUAL_I(0,
                    m_blob_manager->read((Database *)m_db, 0, blobid[i],
                            &record, 0), i);
            BFC_ASSERT_EQUAL_I(record.size, (ham_size_t)(i+1)*factor, i);
            BFC_ASSERT_I(0==::memcmp(buffer, record.data, record.size), i);

            ::free(buffer);
        }

        for (int i=0; i<loops; i++) {
            BFC_ASSERT_EQUAL_I(0,
                m_blob_manager->free((Database *)m_db, blobid[i], 0), i);
        }

        ::free(blobid);
        if (!m_inmemory && m_use_txn)
            BFC_ASSERT(ham_txn_commit(txn, 0)==HAM_SUCCESS);
    }
Пример #5
0
void SelectionState::DeselectAll(BOOL RenderBlobs)
{
	// Find the selected objects in the tree;
	SelRange* Selected = GetApplication()->FindSelection();
	ERROR3IF( Selected==NULL, "Selection object is null in DeselectAll()");

	// Get the selected spread
 	Spread* pSpread = Document::GetSelectedSpread();
	ERROR3IF(pSpread == NULL,"NULL selected spread");

	// Make sure that we have a spread and a selection
	if (pSpread == NULL || Selected == NULL)
		return;

	// Find first selected node

#if !defined(EXCLUDE_FROM_RALPH)
	Node* pFirstSelectedNode = Selected->FindFirst();
	// If there is a selection, EOR blobs off, deselect nodes, and inform everybody
	if (pFirstSelectedNode != NULL && RenderBlobs)
	{
		// Go though and render all the EOR blobs off the screen

		// Find the Blob Manager
		BlobManager* BlobMgr = GetApplication()->GetBlobManager();
		ENSURE( BlobMgr!=NULL, "Blob Manager unexpectedly not there.");

		// Render all the blobs
		BlobMgr->RenderOff(NULL, pFirstSelectedNode->FindParentSpread());

		Tool* pTool = Tool::GetCurrent();
			
		// Get the tool to remove all its blobs before we deselect the nodes.
		// Only do this if the current tool dosent update itself on sel changed messages
		if (pSpread!=NULL && pTool!=NULL && !pTool->AreToolBlobsRenderedOnSelection())
			pTool->RenderToolBlobs(pSpread,NULL);
	}
#endif

	DeselectAll(pSpread->FindFirstChild());

	// Selection cache is no longer valid, so update and tell everyone that it has changed

	// *Note*, This used to be 'Selected->Update(TRUE)', but I (Will) removed the TRUE, so
	// that a message is NOT broadcast.  This should only be called from an operation,
	// and the op will send a message when it ends.

	Selected->Update();
}
Пример #6
0
void LiveEffectsTool::OnMouseMove(DocCoord Coord, Spread* pSpread, ClickModifiers mods)
{
// Stub out this function if the tool isn't wanted
#ifndef NO_ADVANCED_TOOLS		

	// We are interested in any selected paths that the cursor is over
	// we will also be needing the current docview
	SelRange* Selected = GetApplication()->FindSelection();
	Node* pNode = Selected->FindFirst();

	// Check to see if the selection is on the same spread as the mouse
	if (pNode!=NULL)
	{
		// Get the spread and return if it is different from the one with the cursor
		Spread* pNodeSpread = pNode->FindParentSpread();
		if (pNodeSpread!=pSpread)
			return;
	}

	// Find the Blob manager, so we can find out how big a rect to use
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
	if (pBlobMgr==NULL)
		return;
	
	// Find the Rect round the mouse pos that counts as a hit
	DocRect BlobRect;
	pBlobMgr->GetBlobRect(Coord, &BlobRect);
	
	// Work out the square of the distance that we will count as 'close' to the line
	INT32 Range = BlobRect.Width() / 2;
	Range *= Range;

//	// loop through the selection
//	while (pNode!=NULL)
//	{
//		// Now find the next selected node
//		pNode = Selected->FindNext(pNode);
//	}

	// We did not find anything good, so set the cursor to the normal one
	ChangeCursor(pNormalCursor);

	// And set the status bar text
	StatusMsg.Load(_R(IDS_LIVEEFFECTSTART), Tool::GetModuleID(GetID()));
	GetApplication()->UpdateStatusBarText(&StatusMsg);

#endif	// NO_ADVANCED_TOOLS
}
Пример #7
0
BOOL ViewContextMenu::AskBlobsForItems( Spread* pSpread,
										DocCoord ClickPos,
										ClickModifiers ClickMods
										)
{
	// Test for a click on a fill attribute first, as they aren't NodeRenderableInks, and so
	// won't be included in the tests below.
//	if (AttrFillGeometry::CheckAttrClick(ClickStart, TypeOfClick, ClickMods, StartSpread))
//	{
//		return TRUE;
//	}

	// Look for a selected object to pass the click to.
	SelRange* pSel = GetApplication()->FindSelection();
	if (pSel==NULL)
		return FALSE;

	Node* pNode = pSel->FindFirst();
	if (pNode == NULL)
		return FALSE;

	// Providing we are displaying object blobs, try passing the click on to each object
	// in the selection.
	BlobManager* pBlobs = GetApplication()->GetBlobManager();
	if (pBlobs && pBlobs->GetCurrentInterest().Object)
	{
		// For all selected objects . . .
		while (pNode != NULL)
		{
			// Is this node ink-renderable?
			if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
			{
				// Yes.  Does it want the click?
				if (((NodeRenderableInk*) pNode)->OnBlobPopUp(pSpread, ClickPos, this))
				{
					// An object processed the click, so indicate that there's no more to do.
					return TRUE;
				}
			}

			// Try the next object in the selection.
			pNode = pSel->FindNext(pNode);
		}
	}

	return FALSE;
}
Пример #8
0
DocRect NodeSimpleShape::GetBlobBoundingRect()
{
#if !defined(EXCLUDE_FROM_RALPH)
	// Find the Shapes bounding rectangle
	DocRect Rect = GetBoundingRect();

	// Find the blob manager
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();

	// And if we can find the current view, add on the size of a selection blob
	if (pBlobMgr!= NULL)
	{
		// Wee need to add in each of the blobs. there is a blob on each corner
		// of the parallelogram
		DocRect BlobSize;
		pBlobMgr->GetBlobRect(Parallel[0], &BlobSize);
		Rect = Rect.Union(BlobSize);
		
		// Next corner of the parallelogram
		pBlobMgr->GetBlobRect(Parallel[1], &BlobSize);
		Rect = Rect.Union(BlobSize);

		// and the next
		pBlobMgr->GetBlobRect(Parallel[2], &BlobSize);
		Rect = Rect.Union(BlobSize);

		// and the last one
		pBlobMgr->GetBlobRect(Parallel[3], &BlobSize);
		Rect = Rect.Union(BlobSize);
	}

	// Make sure we include the Bounds of our children
	IncludeChildrensBoundingRects(&Rect);

	// return the rectangle with the blobs included
	return Rect;
#else
	return DocRect(0,0,0,0);
#endif
}
Пример #9
0
DocRect NodeEllipse::GetBlobBoundingRect()
{
#if !defined(EXCLUDE_FROM_RALPH)
	// Find the paths bounding rectangle
	DocRect ShapeRect = GetBoundingRect();
	DocRect Rect(Parallel[0], Parallel[0]);
	Rect.IncludePoint(Parallel[1]);
	Rect.IncludePoint(Parallel[2]);
	Rect.IncludePoint(Parallel[3]);

	// Find the blob manager
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
	
	// Get a rect to put the extra rectangle on
	DocRect BlobRect;

	// Get the rect round a blob in the corner of the ellipse and add it to the total
	DocCoord Corner = Rect.HighCorner();
	pBlobMgr->GetBlobRect(Corner, &BlobRect);
	Rect = Rect.Union(BlobRect);

	// and the same with the other corner
	Corner = Rect.LowCorner();
	pBlobMgr->GetBlobRect(Corner, &BlobRect);
	Rect = Rect.Union(BlobRect);

	// and union it with the rect of the shape or things like Linewidth get in the way
	Rect = Rect.Union(ShapeRect);

	// Make sure we include the Bounds of our children
	IncludeChildrensBoundingRects(&Rect);

	// return the rectangle with the blobs included
	return Rect;
#else
	return DocRect(0,0,0,0);
#endif
}
Пример #10
0
    void replaceTest(void)
    {
        ham_u8_t buffer[64], buffer2[64];
        ham_offset_t blobid, blobid2;
        ham_record_t record;
        ::memset(&record,  0, sizeof(record));
        ::memset(&buffer,  0x12, sizeof(buffer));
        ::memset(&buffer2, 0x15, sizeof(buffer2));

        record.size=sizeof(buffer);
        record.data=buffer;
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->allocate((Database *)m_db,
                                &record, 0, &blobid));
        BFC_ASSERT(blobid!=0);

        BFC_ASSERT_EQUAL(0,
                m_blob_manager->read((Database *)m_db, 0,
                                blobid, &record, 0));
        BFC_ASSERT_EQUAL(record.size, (ham_size_t)sizeof(buffer));
        BFC_ASSERT(0==::memcmp(buffer, record.data, record.size));

        record.size=sizeof(buffer2);
        record.data=buffer2;
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->overwrite((Database *)m_db,
                                blobid, &record, 0, &blobid2));
        BFC_ASSERT(blobid2!=0);

        BFC_ASSERT_EQUAL(0,
                m_blob_manager->read((Database *)m_db, 0, blobid2, &record, 0));
        BFC_ASSERT_EQUAL(record.size, (ham_size_t)sizeof(buffer2));
        BFC_ASSERT(0==::memcmp(buffer2, record.data, record.size));

        BFC_ASSERT_EQUAL(0,
                m_blob_manager->free((Database *)m_db, blobid2, 0));
    }
Пример #11
0
    void replaceBiggerAndBiggerTest(void)
    {
        const int BLOCKS=32;
        unsigned ps=((Environment *)m_env)->get_pagesize();
        ham_u8_t *buffer=(ham_u8_t *)malloc(ps*BLOCKS*2);
        ham_offset_t blobid, blobid2;
        ham_record_t record;
        ::memset(&record, 0, sizeof(record));
        ::memset(buffer,  0, ps*BLOCKS*2);

        /* first: create a big blob and erase it - we want to use the
         * space from the freelist */
        record.data=buffer;
        record.size=ps*BLOCKS*2;
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->allocate((Database *)m_db, &record,
                                0, &blobid));
        BFC_ASSERT(blobid!=0);

        /* verify it */
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->read((Database *)m_db, 0, blobid, &record, 0));
        BFC_ASSERT_EQUAL(record.size, (ham_size_t)ps*BLOCKS*2);

        /* and erase it */
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->free((Database *)m_db, blobid, 0));

        /* now use a loop to allocate the buffer, and make it bigger and
         * bigger */
        for (int i=1; i<32; i++) {
            record.size=i*ps;
            record.data=(void *)buffer;
            ::memset(buffer, i, record.size);
            if (i==1) {
                BFC_ASSERT_EQUAL(0,
                        m_blob_manager->allocate((Database *)m_db, &record,
                                0, &blobid2));
            }
            else {
                BFC_ASSERT_EQUAL(0,
                m_blob_manager->overwrite((Database *)m_db, blobid,
                                    &record, 0, &blobid2));
            }
            blobid=blobid2;
            BFC_ASSERT(blobid!=0);
        }
        BFC_ASSERT_EQUAL(0,
                m_blob_manager->free((Database *)m_db, blobid, 0));
        ::free(buffer);
    }
Пример #12
0
void SelectionState::Restore(BOOL RestoreSelBlobs, BOOL RemoveBlobs) 	     	
{
	DeselectAll(RemoveBlobs); // Deselect all selections

	#ifdef _DEBUG
	UINT32 NumRestored = 0; 	 
	#endif

	 
    // ----------------------------------------------------------------------------------
	// Restore all nodes in the SelNdList
	
	UINT32 i; 

	for (i=0; i < NumNd; i++)
	{
		// Only NodeRenderableInk nodes should be selected
		ENSURE(SelNdList[i]->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), 
			   "Node to be selected is not a NodeRenderableInk");
			    
		// Ensure node to be selected is not already selected                                
		//ENSURE(!(SelNdList[i]->IsSelected()), "Invalid selected node"); 

		// Select the node 
		SelNdList[i]->SetSelected(TRUE); 
		#ifdef _DEBUG
		NumRestored++; 	 
		#endif	
	}
	   
	// ----------------------------------------------------------------------------------
	// Restore all nodes in the SelNdRngList	  

	Node* Current; 
	   
	for (i=0; i < NumNdRng; i++) 
	{  
		// A SelNdRng shold represent at least two contiguous selected nodes
		ENSURE(SelNdRngList[i].NumSelected >= 2, "Number of nodes in SelNdRng < 2");    

		UINT32 NumNodesSelected = 0; 
		Current = SelNdRngList[i].FirstNode; // First node in range 
		
		// Select the next SelNdRng->NumSelected nodes
		do  
		{   
			ENSURE((Current != NULL), "Node in a SelNdRng is NULL, Has tree changed ?" );  
			// Only NodeRenderableInk nodes should be selected   
			
			ENSURE(Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), 
				   "Selected node is not a NodeRenderableInk"); 

			// [Phil, 11/10/2005] The Current node may be a Caret node
			// because Carets are included in the selection, even when
			// a sub-selection of characters is present, so that attributes
			// optimise correctly within the text story
			// However, the Record function treats them as single selected
			// nodes, not part of a contiguous run of selected nodes to
			// allow for them moving around...
			// So we should ignore carets here
			if (!IS_A(Current, CaretNode))
			{
				// Ensure SelNode not already selected  
				ENSURE(!(Current->IsSelected()), "Invalid selected node");

				Current->SetSelected(TRUE); 	// Set the nodes selected flag
				NumNodesSelected++;
#ifdef _DEBUG
				NumRestored++; 	 
#endif	
			}
			Current = Current->FindNextNonHidden();  
		}
		while (NumNodesSelected != SelNdRngList[i].NumSelected); 
	}

#if !defined(EXCLUDE_FROM_RALPH)
	// Only restore the blobs if any selections have been restored
	if (((NumNdRng != 0) || (NumNd !=0)) && RestoreSelBlobs)	// We need to restore the selection blobs 
	{
		// Find the current selections 
		SelRange* pSel; 
		pSel = GetApplication()->FindSelection();
 
		Current = pSel->FindFirst(); // The first selected node 

		Spread *pSpread = NULL;
		if (Current != NULL)
			pSpread = Current->FindParentSpread();

//		ENSURE(pSpread != NULL, "First selected node does not have a parent spread");
		// It's a legal state to not find a selected node - the layers may all be locked.
		if (pSpread == NULL)
		{
			AttrFillGeometry::LastRenderedMesh = NULL;
			return;
		}

		// Go get the blob manager
		BlobManager* BlobMgr = GetApplication()->GetBlobManager();
		ENSURE( BlobMgr!=NULL, "Blob Manger was not there when we needed him!");
		if (BlobMgr==NULL)
			return;

	    Current = pSel->FindFirst();   // The first selected node 

		while (Current != NULL)
		{
			ENSURE(Current->IsSelected(), "Node not selected"); 
			ENSURE(Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderable)), 
					"Selected Node not a NodeRenderable"); 

			// Tell the node to add selection blobs
			BlobMgr->RenderMyBlobsOn(NULL, pSpread, (NodeRenderable*)Current);
			
			Current = pSel->FindNext(Current); 	// Get next selected node 
		}

		Tool* pTool = Tool::GetCurrent();
			
		// Get the tool to remove all its blobs before we deselect the nodes.
		// Only do this if the current tool dosent update itself on sel changed messages
		if (pSpread!=NULL && pTool!=NULL && !pTool->AreToolBlobsRenderedOnSelection())
			pTool->RenderToolBlobs(pSpread,NULL);

		AttrFillGeometry::LastRenderedMesh = NULL;
	}
#endif
	
	#ifdef _DEBUG
	//if (IsUserName("Simon"))
	//	TRACE( _T(" Num Restored = %lu\n"), NumRestored);  
	#endif	
	 
}  
Пример #13
0
void LiveEffectsTool::SelectChange(BOOL isSelected)
{
// Stub out this function if the tool isn't wanted
#ifndef NO_ADVANCED_TOOLS		

	if (isSelected)
	{
//MessageBox(NULL, "SelectChange 1", "Debug", MB_OK);
		// Load the cursors
		if (!LoadCursors())
			InformError();

		// Update the list of plug-ins
//MessageBox(NULL, "SelectChange 2", "Debug", MB_OK);
		XPEHost::UpdateEditorsList();
//MessageBox(NULL, "SelectChange 3", "Debug", MB_OK);
SelRange* pSelRange = GetApplication()->FindSelection();
if (pSelRange) pSelRange->MakePartialSelectionWhole(TRUE, FALSE, TRUE);
		ScreenChanged(FALSE);
//MessageBox(NULL, "SelectChange 4", "Debug", MB_OK);
		
		// Find the blob manager ready for later
		BlobManager* BlobMgr = GetApplication()->GetBlobManager();

		// Create and display my info bar please
		if (m_pInfoBarOp != NULL)
		{
			m_pInfoBarOp->Create();
			m_pInfoBarOp->SetToolActiveState(TRUE);
		}

		// Make sure that Objects blobs are on
		if (BlobMgr != NULL)
		{
			// Decide which blobs to display
			BlobStyle MyBlobs;
			MyBlobs.Object = TRUE;

			// tell the blob manager
			BlobMgr->ToolInterest(MyBlobs);
		}
//MessageBox(NULL, "SelectChange 5", "Debug", MB_OK);

	}
	else
	{
		// Deselection of the tool
		// Get rid of all the tools cursors
		RemoveCursors();

		// Close any open XPE editing
		XPEHost::EndEditLiveEffect();

		// Hide and destroy my info bar please
		if (m_pInfoBarOp != NULL)
		{
			m_pInfoBarOp->SetToolActiveState(FALSE);
			
			// Close any open dialogs related to the info bar here

			m_pInfoBarOp->Delete();
		}

		// ensure that the colour picker is working
//		SetColourEditorProcessing(TRUE);

		// ensure any tool object blobs are removed.
		BlobManager* BlobMgr = GetApplication()->GetBlobManager();
		if (BlobMgr != NULL)
		{
			BlobStyle bsRemoves;
			bsRemoves.ToolObject = TRUE;
			BlobMgr->RemoveInterest(bsRemoves);
		}
	}
#endif	// NO_ADVANCED_TOOLS
}