xref: /aoo42x/main/svtools/source/brwbox/brwbox1.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 #include <svtools/brwbox.hxx>
31 #include <svtools/brwhead.hxx>
32 #include "datwin.hxx"
33 #include <tools/debug.hxx>
34 #include <tools/stream.hxx>
35 
36 #include <functional>
37 #include <algorithm>
38 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
39 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
40 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
41 #include <com/sun/star/accessibility/XAccessible.hpp>
42 #include <tools/multisel.hxx>
43 #include "brwimpl.hxx"
44 
45 DBG_NAME(BrowseBox)
46 
47 extern const char* BrowseBoxCheckInvariants( const void* pVoid );
48 
49 DECLARE_LIST( BrowserColumns, BrowserColumn* )
50 
51 #define SCROLL_FLAGS (SCROLL_CLIP | SCROLL_NOCHILDREN)
52 #define getDataWindow() ((BrowserDataWin*)pDataWin)
53 
54 using namespace com::sun::star::accessibility::AccessibleEventId;
55 using namespace com::sun::star::accessibility::AccessibleTableModelChangeType;
56 using com::sun::star::accessibility::AccessibleTableModelChange;
57 using com::sun::star::lang::XComponent;
58 using namespace ::com::sun::star::uno;
59 using namespace svt;
60 
61 //-------------------------------------------------------------------
62 
63 #ifdef DBG_MI
64 void DoLog_Impl( const BrowseBox *pThis, const char *pWhat, const char *pWho )
65 {
66 	SvFileStream aLog( "d:\\cursor.log", STREAM_WRITE|STREAM_NOCREATE );
67 	if ( aLog.IsOpen() )
68 	{
69 		aLog.Seek( STREAM_SEEK_TO_END );
70 		String aEntry( (long) pThis );
71 		aEntry += "(row=";
72 		aEntry += pThis->GetCurRow();
73 		aEntry += "): ";
74 		aEntry += pWhat;
75 		aEntry += " from ";
76 		aEntry += pWho;
77 		aEntry += " => ";
78 		aEntry += pThis->GetCursorHideCount();
79 		aLog.WriteLine( aEntry );
80 	}
81 }
82 #endif
83 
84 namespace
85 {
86 	void disposeAndClearHeaderCell(::svt::BrowseBoxImpl::THeaderCellMap& _rHeaderCell)
87 	{
88 		::std::for_each(
89 						_rHeaderCell.begin(),
90 						_rHeaderCell.end(),
91 						::svt::BrowseBoxImpl::THeaderCellMapFunctorDispose()
92 							);
93 		_rHeaderCell.clear();
94 	}
95 }
96 
97 //===================================================================
98 
99 void BrowseBox::ConstructImpl( BrowserMode nMode )
100 {
101 	DBG_TRACE1( "BrowseBox: %p->ConstructImpl", this );
102 	bMultiSelection = sal_False;
103 	pColSel = 0;
104 	pDataWin = 0;
105 	pVScroll = 0;
106 
107 	pDataWin = new BrowserDataWin( this );
108 	pCols = new BrowserColumns;
109 	m_pImpl.reset( new ::svt::BrowseBoxImpl() );
110 
111 	aGridLineColor = Color( COL_LIGHTGRAY );
112 	InitSettings_Impl( this );
113 	InitSettings_Impl( pDataWin );
114 
115 	bBootstrapped = sal_False;
116 	nDataRowHeight = 0;
117 	nTitleLines = 1;
118 	nFirstCol = 0;
119 	nTopRow = 0;
120 	nCurRow = BROWSER_ENDOFSELECTION;
121 	nCurColId = 0;
122 	bResizing = sal_False;
123 	bSelect = sal_False;
124 	bSelecting = sal_False;
125 	bScrolling = sal_False;
126 	bSelectionIsVisible = sal_False;
127 	bNotToggleSel = sal_False;
128 	bRowDividerDrag = sal_False;
129 	bHit = sal_False;
130 	mbInteractiveRowHeight = sal_False;
131 	bHideSelect = sal_False;
132 	bHideCursor = NO_CURSOR_HIDE;
133 	nRowCount = 0;
134 	m_bFocusOnlyCursor = sal_True;
135 	m_aCursorColor = COL_TRANSPARENT;
136 	m_nCurrentMode = 0;
137     nControlAreaWidth = USHRT_MAX;
138 	uRow.nSel = BROWSER_ENDOFSELECTION;
139 
140 	aHScroll.SetLineSize(1);
141 	aHScroll.SetScrollHdl( LINK( this, BrowseBox, ScrollHdl ) );
142 	aHScroll.SetEndScrollHdl( LINK( this, BrowseBox, EndScrollHdl ) );
143 	pDataWin->Show();
144 
145 	SetMode( nMode );
146 	bSelectionIsVisible = bKeepHighlight;
147 	bHasFocus = HasChildPathFocus();
148 	getDataWindow()->nCursorHidden =
149 				( bHasFocus ? 0 : 1 ) + ( GetUpdateMode() ? 0 : 1 );
150 	LOG( this, "ConstructImpl", "*" );
151 }
152 
153 //-------------------------------------------------------------------
154 
155 BrowseBox::BrowseBox( Window* pParent, WinBits nBits, BrowserMode nMode )
156 	:Control( pParent, nBits | WB_3DLOOK )
157 	,DragSourceHelper( this )
158 	,DropTargetHelper( this )
159 	,aHScroll( this, WinBits( WB_HSCROLL ) )
160 {
161 	DBG_CTOR( BrowseBox, NULL );
162 	ConstructImpl( nMode );
163 }
164 
165 //-------------------------------------------------------------------
166 
167 BrowseBox::BrowseBox( Window* pParent, const ResId& rId, BrowserMode nMode )
168 	:Control( pParent, rId )
169 	,DragSourceHelper( this )
170 	,DropTargetHelper( this )
171 	,aHScroll( this, WinBits(WB_HSCROLL) )
172 {
173 	DBG_CTOR( BrowseBox, NULL );
174 	ConstructImpl(nMode);
175 }
176 //-------------------------------------------------------------------
177 
178 BrowseBox::~BrowseBox()
179 {
180 	DBG_DTOR(BrowseBox,BrowseBoxCheckInvariants);
181 	DBG_TRACE1( "BrowseBox: %p~", this );
182 
183 	if ( m_pImpl->m_pAccessible )
184 	{
185 		disposeAndClearHeaderCell(m_pImpl->m_aColHeaderCellMap);
186 		disposeAndClearHeaderCell(m_pImpl->m_aRowHeaderCellMap);
187 		m_pImpl->m_pAccessible->dispose();
188 	}
189 
190 	Hide();
191 	delete getDataWindow()->pHeaderBar;
192 	delete getDataWindow()->pCornerWin;
193 	delete pDataWin;
194 	delete pVScroll;
195 
196 	// free columns-space
197 	for ( sal_uInt16 n = 0; n < pCols->Count(); ++n )
198 		delete pCols->GetObject(n);
199 	delete pCols;
200 	delete pColSel;
201 	if ( bMultiSelection )
202 		delete uRow.pSel;
203 }
204 
205 //-------------------------------------------------------------------
206 
207 short BrowseBox::GetCursorHideCount() const
208 {
209 	return getDataWindow()->nCursorHidden;
210 }
211 
212 //-------------------------------------------------------------------
213 
214 void BrowseBox::DoShowCursor( const char *
215 #ifdef DBG_MI
216 pWhoLogs
217 #endif
218 )
219 {
220 	short nHiddenCount = --getDataWindow()->nCursorHidden;
221 	if (PaintCursorIfHiddenOnce())
222 	{
223 		if (1 == nHiddenCount)
224 			DrawCursor();
225 	}
226 	else
227 	{
228 		if (0 == nHiddenCount)
229 			DrawCursor();
230 	}
231 	LOG( this, "DoShowCursor", pWhoLogs );
232 }
233 
234 //-------------------------------------------------------------------
235 
236 void BrowseBox::DoHideCursor( const char *
237 #ifdef DBG_MI
238 pWhoLogs
239 #endif
240 )
241 {
242 	short nHiddenCount = ++getDataWindow()->nCursorHidden;
243 	if (PaintCursorIfHiddenOnce())
244 	{
245 		if (2 == nHiddenCount)
246 			DrawCursor();
247 	}
248 	else
249 	{
250 		if (1 == nHiddenCount)
251 			DrawCursor();
252 	}
253 	LOG( this, "DoHideCursor", pWhoLogs );
254 }
255 
256 //-------------------------------------------------------------------
257 
258 void BrowseBox::SetRealRowCount( const String &rRealRowCount )
259 {
260 	getDataWindow()->aRealRowCount = rRealRowCount;
261 }
262 
263 //-------------------------------------------------------------------
264 
265 void BrowseBox::SetFont( const Font& rNewFont )
266 {
267 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
268 	pDataWin->SetFont( rNewFont );
269 	ImpGetDataRowHeight();
270 }
271 
272 //-------------------------------------------------------------------
273 
274 sal_uLong BrowseBox::GetDefaultColumnWidth( const String& _rText ) const
275 {
276 	return GetDataWindow().GetTextWidth( _rText ) + GetDataWindow().GetTextWidth( '0' ) * 4;
277 }
278 
279 //-------------------------------------------------------------------
280 
281 void BrowseBox::InsertHandleColumn( sal_uLong nWidth )
282 {
283 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
284 
285 	pCols->Insert( new BrowserColumn( 0, Image(), String(), nWidth, GetZoom(), 0 ), (sal_uLong) 0 );
286 	FreezeColumn( 0 );
287 
288 	// Headerbar anpassen
289 	if ( getDataWindow()->pHeaderBar )
290 	{
291 		getDataWindow()->pHeaderBar->SetPosSizePixel(
292 					Point(nWidth, 0),
293                     Size( GetOutputSizePixel().Width() - nWidth, GetTitleHeight() )
294                     );
295 	}
296 
297 	/*if ( getDataWindow()->pHeaderBar )
298 		getDataWindow()->pHeaderBar->InsertItem( USHRT_MAX - 1,
299 				"", nWidth, HIB_FIXEDPOS|HIB_FIXED, 0 );*/
300 	ColumnInserted( 0 );
301 }
302 
303 //-------------------------------------------------------------------
304 void BrowseBox::InsertDataColumn( sal_uInt16 nItemId, const Image& rImage,
305 		long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos )
306 {
307 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
308 
309 	pCols->Insert( new BrowserColumn( nItemId, rImage, String(), nWidth, GetZoom(), nBits ),
310 						   Min( nPos, (sal_uInt16)(pCols->Count()) ) );
311 	if ( nCurColId == 0 )
312 		nCurColId = nItemId;
313 	if ( getDataWindow()->pHeaderBar )
314 	{
315 		// Handlecolumn nicht in der Headerbar
316 		sal_uInt16 nHeaderPos = nPos;
317 		if (nHeaderPos != HEADERBAR_APPEND && !GetColumnId(0))
318 			nHeaderPos--;
319 		getDataWindow()->pHeaderBar->InsertItem(
320 				nItemId, rImage, nWidth, nBits, nHeaderPos );
321 	}
322 	ColumnInserted( nPos );
323 }
324 
325 //-------------------------------------------------------------------
326 
327 void BrowseBox::InsertDataColumn( sal_uInt16 nItemId, const XubString& rText,
328 		long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos )
329 {
330 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
331 
332 	pCols->Insert( new BrowserColumn( nItemId, Image(), rText, nWidth, GetZoom(), nBits ),
333 						   Min( nPos, (sal_uInt16)(pCols->Count()) ) );
334 	if ( nCurColId == 0 )
335 		nCurColId = nItemId;
336 
337 	if ( getDataWindow()->pHeaderBar )
338 	{
339 		// Handlecolumn nicht in der Headerbar
340 		sal_uInt16 nHeaderPos = nPos;
341 		if (nHeaderPos != HEADERBAR_APPEND && !GetColumnId(0))
342 			nHeaderPos--;
343 		getDataWindow()->pHeaderBar->InsertItem(
344 				nItemId, rText, nWidth, nBits, nHeaderPos );
345 	}
346 	ColumnInserted( nPos );
347 }
348 
349 //-------------------------------------------------------------------
350 
351 void BrowseBox::InsertDataColumn( sal_uInt16 nItemId,
352 		const Image& rImage, const XubString& rText,
353 		long nWidth, HeaderBarItemBits nBits, sal_uInt16 nPos,
354 		const String* pHelpText )
355 {
356 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
357 
358 	pCols->Insert( new BrowserColumn( nItemId, rImage, rText, nWidth, GetZoom(), nBits ),
359 						   Min( nPos, (sal_uInt16)(pCols->Count()) ) );
360 	if ( nCurColId == 0 )
361 		nCurColId = nItemId;
362 	if ( getDataWindow()->pHeaderBar )
363 	{
364 		// Handlecolumn nicht in der Headerbar
365 		sal_uInt16 nHeaderPos = nPos;
366 		if (nHeaderPos != HEADERBAR_APPEND && !GetColumnId(0))
367 			nHeaderPos--;
368 
369 		getDataWindow()->pHeaderBar->InsertItem(
370 				nItemId, rImage, rText, nWidth, nBits, nHeaderPos );
371 		if( pHelpText && !rText.Len() )
372 		{
373 			getDataWindow()->pHeaderBar->SetHelpText(
374 				nItemId, *pHelpText );
375 		}
376 	}
377 	ColumnInserted( nPos );
378 }
379 //-------------------------------------------------------------------
380 sal_uInt16 BrowseBox::ToggleSelectedColumn()
381 {
382 	sal_uInt16 nSelectedColId = USHRT_MAX;
383 	if ( pColSel && pColSel->GetSelectCount() )
384 	{
385 		DoHideCursor( "ToggleSelectedColumn" );
386 		ToggleSelection();
387 		nSelectedColId = pCols->GetObject(pColSel->FirstSelected())->GetId();
388 		pColSel->SelectAll(sal_False);
389 	}
390 	return nSelectedColId;
391 }
392 // -----------------------------------------------------------------------------
393 void BrowseBox::SetToggledSelectedColumn(sal_uInt16 _nSelectedColumnId)
394 {
395 	if ( pColSel && _nSelectedColumnId != USHRT_MAX )
396 	{
397 		pColSel->Select( GetColumnPos( _nSelectedColumnId ) );
398 		ToggleSelection();
399 		DBG_TRACE1( "BrowseBox: %p->SetToggledSelectedColumn", this );
400 		DoShowCursor( "SetToggledSelectedColumn" );
401 	}
402 }
403 // -----------------------------------------------------------------------------
404 void BrowseBox::FreezeColumn( sal_uInt16 nItemId, sal_Bool bFreeze )
405 {
406 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
407 
408 	// never unfreeze the handle-column
409 	if ( nItemId == 0 && !bFreeze )
410 		return;
411 
412 	// get the position in the current array
413 	sal_uInt16 nItemPos = GetColumnPos( nItemId );
414 	if ( nItemPos >= pCols->Count() )
415 		// not available!
416 		return;
417 
418 	// doesn't the state change?
419 	if ( pCols->GetObject(nItemPos)->IsFrozen() == bFreeze )
420 		return;
421 
422 	// remark the column selection
423 	sal_uInt16 nSelectedColId = ToggleSelectedColumn();
424 
425 	// freeze or unfreeze?
426 	if ( bFreeze )
427 	{
428 		// to be moved?
429 		if ( nItemPos != 0 && !pCols->GetObject(nItemPos-1)->IsFrozen() )
430 		{
431 			// move to the right of the last frozen column
432 			sal_uInt16 nFirstScrollable = FrozenColCount();
433 			BrowserColumn *pColumn = pCols->GetObject(nItemPos);
434 			pCols->Remove( (sal_uLong) nItemPos );
435 			nItemPos = nFirstScrollable;
436 			pCols->Insert( pColumn, (sal_uLong) nItemPos );
437 		}
438 
439 		// adjust the number of the first scrollable and visible column
440 		if ( nFirstCol <= nItemPos )
441 			nFirstCol = nItemPos + 1;
442 	}
443 	else
444 	{
445 		// to be moved?
446 		if ( nItemPos != FrozenColCount()-1 )
447 		{
448 			// move to the leftmost scrollable colum
449 			sal_uInt16 nFirstScrollable = FrozenColCount();
450 			BrowserColumn *pColumn = pCols->GetObject(nItemPos);
451 			pCols->Remove( (sal_uLong) nItemPos );
452 			nItemPos = nFirstScrollable;
453 			pCols->Insert( pColumn, (sal_uLong) nItemPos );
454 		}
455 
456 		// adjust the number of the first scrollable and visible column
457 		nFirstCol = nItemPos;
458 	}
459 
460 	// toggle the freeze-state of the column
461 	pCols->GetObject(nItemPos)->Freeze( bFreeze );
462 
463 	// align the scrollbar-range
464 	UpdateScrollbars();
465 
466 	// repaint
467 	Control::Invalidate();
468 	getDataWindow()->Invalidate();
469 
470 	// remember the column selection
471 	SetToggledSelectedColumn(nSelectedColId);
472 }
473 
474 //-------------------------------------------------------------------
475 
476 void BrowseBox::SetColumnPos( sal_uInt16 nColumnId, sal_uInt16 nPos )
477 {
478 	// never set pos of the handle-column
479 	if ( nColumnId == 0 )
480 		return;
481 
482 	// do not move handle column
483 	if (nPos == 0 && !pCols->GetObject(0)->GetId())
484 		return;
485 
486 	// get the position in the current array
487 	sal_uInt16 nOldPos = GetColumnPos( nColumnId );
488 	if ( nOldPos >= pCols->Count() )
489 		// not available!
490 		return;
491 
492 	// does the state change?
493 	if (nOldPos != nPos)
494 	{
495 		// remark the column selection
496 		sal_uInt16 nSelectedColId = ToggleSelectedColumn();
497 
498 		// determine old column area
499 		Size aDataWinSize( pDataWin->GetSizePixel() );
500 		if ( getDataWindow()->pHeaderBar )
501 			aDataWinSize.Height() += getDataWindow()->pHeaderBar->GetSizePixel().Height();
502 
503 		Rectangle aFromRect( GetFieldRect( nColumnId) );
504 		aFromRect.Right() += 2*MIN_COLUMNWIDTH;
505 
506 		sal_uInt16 nNextPos = nOldPos + 1;
507 		if ( nOldPos > nPos )
508 			nNextPos = nOldPos - 1;
509 
510 		BrowserColumn *pNextCol = pCols->GetObject(nNextPos);
511 		Rectangle aNextRect(GetFieldRect( pNextCol->GetId() ));
512 
513 		// move column internally
514 		pCols->Insert( pCols->Remove( nOldPos ), nPos );
515 
516 		// determine new column area
517 		Rectangle aToRect( GetFieldRect( nColumnId ) );
518 		aToRect.Right() += 2*MIN_COLUMNWIDTH;
519 
520 		// do scroll, let redraw
521 		if( pDataWin->GetBackground().IsScrollable() )
522 		{
523 			long nScroll = -aFromRect.GetWidth();
524 			Rectangle aScrollArea;
525 			if ( nOldPos > nPos )
526 			{
527 				long nFrozenWidth = GetFrozenWidth();
528 				if ( aToRect.Left() < nFrozenWidth )
529 					aToRect.Left() = nFrozenWidth;
530 				aScrollArea = Rectangle(Point(aToRect.Left(),0),
531 									    Point(aNextRect.Right(),aDataWinSize.Height()));
532 				nScroll *= -1; // reverse direction
533 			}
534 			else
535 				aScrollArea = Rectangle(Point(aNextRect.Left(),0),
536 									    Point(aToRect.Right(),aDataWinSize.Height()));
537 
538 			pDataWin->Scroll( nScroll, 0, aScrollArea );
539 			aToRect.Top() = 0;
540 			aToRect.Bottom() = aScrollArea.Bottom();
541 			Invalidate( aToRect );
542 		}
543 		else
544 			pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
545 
546 		// adjust header bar positions
547 		if ( getDataWindow()->pHeaderBar )
548 		{
549 			sal_uInt16 nNewPos = nPos;
550 			if ( !GetColumnId(0) )
551 				--nNewPos;
552 			getDataWindow()->pHeaderBar->MoveItem(nColumnId,nNewPos);
553 		}
554 		// remember the column selection
555 		SetToggledSelectedColumn(nSelectedColId);
556 
557         if ( isAccessibleAlive() )
558 		{
559 			commitTableEvent(
560                 TABLE_MODEL_CHANGED,
561 				makeAny( AccessibleTableModelChange(
562                             DELETE,
563 							0,
564 							GetRowCount(),
565 							nOldPos,
566 							nOldPos
567                         )
568                 ),
569                 Any()
570             );
571 
572 			commitTableEvent(
573                 TABLE_MODEL_CHANGED,
574 			    makeAny( AccessibleTableModelChange(
575                             INSERT,
576 							0,
577 							GetRowCount(),
578 							nPos,
579 							nPos
580                         )
581                 ),
582 				Any()
583             );
584 		}
585 	}
586 
587 }
588 
589 //-------------------------------------------------------------------
590 
591 void BrowseBox::SetColumnMode( sal_uInt16 nColumnId, BrowserColumnMode nFlags )
592 {
593 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
594 
595 	// never set mode of the handle-column
596 	if ( nColumnId == 0 )
597 		return;
598 
599 	// get the position in the current array
600 	sal_uInt16 nColumnPos = GetColumnPos( nColumnId );
601 	if ( nColumnPos >= pCols->Count() )
602 		// not available!
603 		return;
604 
605 	// does the state change?
606 	BrowserColumn *pCol = pCols->GetObject(nColumnPos);
607 	if ( pCol->Flags() != nFlags )
608 	{
609 		pCol->Flags() = sal::static_int_cast< HeaderBarItemBits >(nFlags);
610 
611 		// redraw visible colums
612 		if ( GetUpdateMode() && ( pCol->IsFrozen() || nColumnPos > nFirstCol ) )
613 			Invalidate( Rectangle( Point(0,0),
614 				Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
615 	}
616 }
617 
618 //-------------------------------------------------------------------
619 
620 void BrowseBox::SetColumnTitle( sal_uInt16 nItemId, const String& rTitle )
621 {
622 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
623 
624 	// never set title of the handle-column
625 	if ( nItemId == 0 )
626 		return;
627 
628 	// get the position in the current array
629 	sal_uInt16 nItemPos = GetColumnPos( nItemId );
630 	if ( nItemPos >= pCols->Count() )
631 		// not available!
632 		return;
633 
634 	// does the state change?
635 	BrowserColumn *pCol = pCols->GetObject(nItemPos);
636 	if ( pCol->Title() != rTitle )
637 	{
638 		::rtl::OUString sNew(rTitle);
639 		::rtl::OUString sOld(pCol->Title());
640 
641 		pCol->Title() = rTitle;
642 
643 		// Headerbar-Column anpassen
644 		if ( getDataWindow()->pHeaderBar )
645 			getDataWindow()->pHeaderBar->SetItemText(
646 					nItemId ? nItemId : USHRT_MAX - 1, rTitle );
647 		else
648 		{
649 			// redraw visible colums
650 			if ( GetUpdateMode() && ( pCol->IsFrozen() || nItemPos > nFirstCol ) )
651 				Invalidate( Rectangle( Point(0,0),
652 					Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
653 		}
654 
655         if ( isAccessibleAlive() )
656 		{
657 			commitTableEvent(	TABLE_COLUMN_DESCRIPTION_CHANGED,
658 			    makeAny( sNew ),
659 			    makeAny( sOld )
660             );
661 		}
662 	}
663 }
664 
665 //-------------------------------------------------------------------
666 
667 void BrowseBox::SetColumnWidth( sal_uInt16 nItemId, sal_uLong nWidth )
668 {
669 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
670 
671 	// get the position in the current array
672 	sal_uInt16 nItemPos = GetColumnPos( nItemId );
673 	if ( nItemPos >= pCols->Count() )
674 		return;
675 
676 	// does the state change?
677 	nWidth = QueryColumnResize( nItemId, nWidth );
678 	if ( nWidth >= LONG_MAX || pCols->GetObject(nItemPos)->Width() != nWidth )
679 	{
680 		long nOldWidth = pCols->GetObject(nItemPos)->Width();
681 
682 		// ggf. letzte Spalte anpassen
683 		if ( IsVisible() && nItemPos == pCols->Count() - 1 )
684 		{
685 			long nMaxWidth = pDataWin->GetSizePixel().Width();
686 			nMaxWidth -= getDataWindow()->bAutoSizeLastCol
687 					? GetFieldRect(nItemId).Left()
688 					: GetFrozenWidth();
689 			if ( ( (BrowserDataWin*)pDataWin )->bAutoSizeLastCol || nWidth > (sal_uLong)nMaxWidth )
690 			{
691 				nWidth = nMaxWidth > 16 ? nMaxWidth : nOldWidth;
692 				nWidth = QueryColumnResize( nItemId, nWidth );
693 			}
694 		}
695 
696 		// OV
697 		// In AutoSizeLastColumn() wird SetColumnWidth mit nWidth==0xffff
698 		// gerufen. Deshalb muss hier nochmal geprueft werden, ob sich die
699 		// Breite tatsaechlich geaendert hat.
700 		if( (sal_uLong)nOldWidth == nWidth )
701 			return;
702 
703 		// soll die Aenderung sofort dargestellt werden?
704 		sal_Bool bUpdate = GetUpdateMode() &&
705 					   ( pCols->GetObject(nItemPos)->IsFrozen() || nItemPos >= nFirstCol );
706 
707 		if ( bUpdate )
708 		{
709 			// Selection hiden
710 			DoHideCursor( "SetColumnWidth" );
711 			ToggleSelection();
712 			//!getDataWindow()->Update();
713 			//!Control::Update();
714 		}
715 
716 		// Breite setzen
717 		pCols->GetObject(nItemPos)->SetWidth(nWidth, GetZoom());
718 #if 0
719 		if ( nItemPos != pCols->Count() - 1 )
720 		{
721 			long nLastColMaxWidth = pDataWin->GetSizePixel().Width() -
722 						GetFieldRect(GetColumnId(pCols->Count()-1)).Left();
723 			pCols->GetObject(pCols->Count()-1)->Width() = nLastColMaxWidth;
724 		}
725 #endif
726 
727 		// scroll and invalidate
728 		if ( bUpdate )
729 		{
730 			// X-Pos der veraenderten Spalte ermitteln
731 			long nX = 0;
732 			for ( sal_uInt16 nCol = 0; nCol < nItemPos; ++nCol )
733 			{
734 				BrowserColumn *pCol = pCols->GetObject(nCol);
735 				if ( pCol->IsFrozen() || nCol >= nFirstCol )
736 					nX += pCol->Width();
737 			}
738 
739 			// eigentliches scroll+invalidate
740 			pDataWin->SetClipRegion();
741 			sal_Bool bSelVis = bSelectionIsVisible;
742 			bSelectionIsVisible = sal_False;
743 			if( GetBackground().IsScrollable() )
744 			{
745 
746 				Rectangle aScrRect( nX + std::min( (sal_uLong)nOldWidth, nWidth ), 0,
747 									GetSizePixel().Width() , // the header is longer than the datawin
748 									pDataWin->GetPosPixel().Y() - 1 );
749 				Control::Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
750 				aScrRect.Bottom() = pDataWin->GetSizePixel().Height();
751 				getDataWindow()->Scroll( nWidth-nOldWidth, 0, aScrRect, SCROLL_FLAGS );
752 				Rectangle aInvRect( nX, 0, nX + std::max( nWidth, (sal_uLong)nOldWidth ), USHRT_MAX );
753 				Control::Invalidate( aInvRect, INVALIDATE_NOCHILDREN );
754 				( (BrowserDataWin*)pDataWin )->Invalidate( aInvRect );
755 			}
756 			else
757 			{
758 				Control::Invalidate( INVALIDATE_NOCHILDREN );
759 				getDataWindow()->Window::Invalidate( INVALIDATE_NOCHILDREN );
760 			}
761 
762 
763 			//!getDataWindow()->Update();
764 			//!Control::Update();
765 			bSelectionIsVisible = bSelVis;
766 			ToggleSelection();
767 			DoShowCursor( "SetColumnWidth" );
768 		}
769 		UpdateScrollbars();
770 
771 		// Headerbar-Column anpassen
772 		if ( getDataWindow()->pHeaderBar )
773 			getDataWindow()->pHeaderBar->SetItemSize(
774 					nItemId ? nItemId : USHRT_MAX - 1, nWidth );
775 
776 		// adjust last column
777 		if ( nItemPos != pCols->Count() - 1 )
778 			AutoSizeLastColumn();
779 
780 	}
781 }
782 
783 //-------------------------------------------------------------------
784 
785 void BrowseBox::AutoSizeLastColumn()
786 {
787 	if ( getDataWindow()->bAutoSizeLastCol &&
788 		 getDataWindow()->GetUpdateMode() )
789 	{
790 		sal_uInt16 nId = GetColumnId( (sal_uInt16)pCols->Count() - 1 );
791 		SetColumnWidth( nId, LONG_MAX );
792 		ColumnResized( nId );
793 	}
794 }
795 
796 //-------------------------------------------------------------------
797 
798 void BrowseBox::RemoveColumn( sal_uInt16 nItemId )
799 {
800 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
801 
802 	// Spaltenposition ermitteln
803 	sal_uInt16 nPos = GetColumnPos(nItemId);
804 	if ( nPos >= ColCount() )
805 		// nicht vorhanden
806 		return;
807 
808 	// Spaltenselektion korrigieren
809 	if ( pColSel )
810 		pColSel->Remove( nPos );
811 
812 	// Spaltencursor korrigieren
813 	if ( nCurColId == nItemId )
814 		nCurColId = 0;
815 
816 	// Spalte entfernen
817 	delete( pCols->Remove( (sal_uLong) nPos ));
818 	// OJ #93534#
819 	if ( nFirstCol >= nPos && nFirstCol > FrozenColCount() )
820 	{
821 		OSL_ENSURE(nFirstCol > 0,"FirstCol must be greater zero!");
822 		--nFirstCol;
823 	}
824 
825 	// Handlecolumn nicht in der Headerbar
826 	if (nItemId)
827 	{
828 		if ( getDataWindow()->pHeaderBar )
829 			getDataWindow()->pHeaderBar->RemoveItem( nItemId );
830 	}
831 	else
832 	{
833 		// Headerbar anpassen
834 		if ( getDataWindow()->pHeaderBar )
835 		{
836 			getDataWindow()->pHeaderBar->SetPosSizePixel(
837 						Point(0, 0),
838                         Size( GetOutputSizePixel().Width(), GetTitleHeight() )
839                         );
840 		}
841 	}
842 
843 	// vertikalen Scrollbar korrigieren
844 	UpdateScrollbars();
845 
846 	// ggf. Repaint ausl"osen
847 	if ( GetUpdateMode() )
848 	{
849 		getDataWindow()->Invalidate();
850 		Control::Invalidate();
851 		if ( getDataWindow()->bAutoSizeLastCol && nPos ==ColCount() )
852 			SetColumnWidth( GetColumnId( nPos - 1 ), LONG_MAX );
853 	}
854 
855     if ( isAccessibleAlive() )
856 	{
857 		commitTableEvent(
858             TABLE_MODEL_CHANGED,
859 			makeAny( AccessibleTableModelChange(	DELETE,
860 													0,
861 													GetRowCount(),
862 													nPos,
863 													nPos
864                                                )
865             ),
866             Any()
867         );
868 
869 		commitHeaderBarEvent(
870             CHILD,
871 			Any(),
872 			makeAny( CreateAccessibleColumnHeader( nPos ) ),
873             sal_True
874         );
875 	}
876 }
877 
878 //-------------------------------------------------------------------
879 
880 void BrowseBox::RemoveColumns()
881 {
882 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
883 
884 	unsigned int nOldCount = pCols->Count();
885 	// alle Spalten entfernen
886 	while ( pCols->Count() )
887 		delete ( pCols->Remove( (sal_uLong) 0 ));
888 
889 	// Spaltenselektion korrigieren
890 	if ( pColSel )
891 	{
892 		pColSel->SelectAll(sal_False);
893 		pColSel->SetTotalRange( Range( 0, 0 ) );
894 	}
895 
896 	// Spaltencursor korrigieren
897 	nCurColId = 0;
898 	nFirstCol = 0;
899 
900 	if ( getDataWindow()->pHeaderBar )
901 		getDataWindow()->pHeaderBar->Clear( );
902 
903 	// vertikalen Scrollbar korrigieren
904 	UpdateScrollbars();
905 
906 	// ggf. Repaint ausl"osen
907 	if ( GetUpdateMode() )
908 	{
909 		getDataWindow()->Invalidate();
910 		Control::Invalidate();
911 	}
912 
913     if ( isAccessibleAlive() )
914 	{
915         if ( pCols->Count() != nOldCount )
916         {
917 		    // all columns should be removed, so we remove the column header bar and append it again
918 		    // to avoid to notify every column remove
919 		    commitBrowseBoxEvent(
920                 CHILD,
921                 Any(),
922                 makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_COLUMNHEADERBAR))
923             );
924 
925             // and now append it again
926 		    commitBrowseBoxEvent(
927                 CHILD,
928 				makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_COLUMNHEADERBAR)),
929 				Any()
930             );
931 
932             // notify a table model change
933             commitTableEvent(
934                 TABLE_MODEL_CHANGED,
935 				makeAny ( AccessibleTableModelChange( DELETE,
936                                 0,
937 					            GetRowCount(),
938 					            0,
939 					            nOldCount
940                             )
941                         ),
942 				Any()
943             );
944         }
945 	}
946 }
947 
948 //-------------------------------------------------------------------
949 
950 String BrowseBox::GetColumnTitle( sal_uInt16 nId ) const
951 {
952 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
953 
954 	sal_uInt16 nItemPos = GetColumnPos( nId );
955 	if ( nItemPos >= pCols->Count() )
956 		return String();
957 	return pCols->GetObject(nItemPos)->Title();
958 }
959 
960 //-------------------------------------------------------------------
961 
962 long BrowseBox::GetRowCount() const
963 {
964 	return nRowCount;
965 }
966 
967 //-------------------------------------------------------------------
968 
969 sal_uInt16 BrowseBox::ColCount() const
970 {
971 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
972 
973 	return (sal_uInt16) pCols->Count();
974 }
975 
976 //-------------------------------------------------------------------
977 
978 long BrowseBox::ImpGetDataRowHeight() const
979 {
980 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
981 
982 	BrowseBox *pThis = (BrowseBox*)this;
983 	pThis->nDataRowHeight = pThis->CalcReverseZoom(pDataWin->GetTextHeight() + 2);
984 	pThis->Resize();
985 	getDataWindow()->Invalidate();
986 	return nDataRowHeight;
987 }
988 
989 //-------------------------------------------------------------------
990 
991 void BrowseBox::SetDataRowHeight( long nPixel )
992 {
993 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
994 
995 	nDataRowHeight = CalcReverseZoom(nPixel);
996 	Resize();
997 	getDataWindow()->Invalidate();
998 }
999 
1000 //-------------------------------------------------------------------
1001 
1002 void BrowseBox::SetTitleLines( sal_uInt16 nLines )
1003 {
1004 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1005 
1006 	nTitleLines = nLines;
1007 }
1008 
1009 //-------------------------------------------------------------------
1010 
1011 long BrowseBox::ScrollColumns( long nCols )
1012 {
1013 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1014 
1015 	if ( nFirstCol + nCols < 0 ||
1016 		 nFirstCol + nCols >= (long)pCols->Count() )
1017 		 //?MI: pCols->GetObject( nFirstCol + nCols )->IsFrozen() )
1018 		return 0;
1019 
1020 	// implicitly hides cursor while scrolling
1021 	StartScroll();
1022 	bScrolling = sal_True;
1023 	sal_Bool bScrollable = pDataWin->GetBackground().IsScrollable();
1024 	sal_Bool bInvalidateView = sal_False;
1025 
1026 	// scrolling one column to the right?
1027 	if ( nCols == 1 )
1028 	{
1029 		// update internal value and scrollbar
1030 		++nFirstCol;
1031 		aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
1032 
1033 		if ( !bScrollable )
1034         {
1035             bInvalidateView = sal_True;
1036         }
1037         else
1038         {
1039 		    long nDelta = pCols->GetObject(nFirstCol-1)->Width();
1040 		    long nFrozenWidth = GetFrozenWidth();
1041 
1042             Rectangle aScrollRect(  Point( nFrozenWidth + nDelta, 0 ),
1043                                     Size ( GetOutputSizePixel().Width() - nFrozenWidth - nDelta,
1044                                            GetTitleHeight() - 1
1045                                          ) );
1046 
1047 		    // scroll the header bar area (if there is no dedicated HeaderBar control)
1048 		    if ( !getDataWindow()->pHeaderBar && nTitleLines )
1049 		    {
1050                 // actually scroll
1051                 Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
1052 
1053                 // invalidate the area of the column which was scrolled out to the left hand side
1054                 Rectangle aInvalidateRect( aScrollRect );
1055                 aInvalidateRect.Left() = nFrozenWidth;
1056                 aInvalidateRect.Right() = nFrozenWidth + nDelta - 1;
1057                 Invalidate( aInvalidateRect );
1058 		    }
1059 
1060 		    // scroll the data-area
1061             aScrollRect.Bottom() = pDataWin->GetOutputSizePixel().Height();
1062 
1063             // actually scroll
1064 		    pDataWin->Scroll( -nDelta, 0, aScrollRect, SCROLL_FLAGS );
1065 
1066             // invalidate the area of the column which was scrolled out to the left hand side
1067 	        aScrollRect.Left() = nFrozenWidth;
1068 	        aScrollRect.Right() = nFrozenWidth + nDelta - 1;
1069 	        getDataWindow()->Invalidate( aScrollRect );
1070         }
1071 	}
1072 
1073 	// scrolling one column to the left?
1074 	else if ( nCols == -1 )
1075 	{
1076 		--nFirstCol;
1077 		aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
1078 
1079 		if ( !bScrollable )
1080 		{
1081 			bInvalidateView = sal_True;
1082         }
1083         else
1084         {
1085 		    long nDelta = pCols->GetObject(nFirstCol)->Width();
1086 		    long nFrozenWidth = GetFrozenWidth();
1087 
1088             Rectangle aScrollRect(  Point(  nFrozenWidth, 0 ),
1089 			                        Size (  GetOutputSizePixel().Width() - nFrozenWidth,
1090 				                            GetTitleHeight() - 1
1091                                          ) );
1092 
1093 		    // scroll the header bar area (if there is no dedicated HeaderBar control)
1094 		    if ( !getDataWindow()->pHeaderBar && nTitleLines )
1095 		    {
1096 			    Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
1097 		    }
1098 
1099 		    // scroll the data-area
1100             aScrollRect.Bottom() = pDataWin->GetOutputSizePixel().Height();
1101 		    pDataWin->Scroll( nDelta, 0, aScrollRect, SCROLL_FLAGS );
1102         }
1103 	}
1104 	else
1105 	{
1106 		if ( GetUpdateMode() )
1107 		{
1108 			Invalidate( Rectangle(
1109 				Point( GetFrozenWidth(), 0 ),
1110 				Size( GetOutputSizePixel().Width(), GetTitleHeight() ) ) );
1111 			getDataWindow()->Invalidate( Rectangle(
1112 				Point( GetFrozenWidth(), 0 ),
1113 				pDataWin->GetSizePixel() ) );
1114 		}
1115 
1116 		nFirstCol = nFirstCol + (sal_uInt16)nCols;
1117 		aHScroll.SetThumbPos( nFirstCol - FrozenColCount() );
1118 	}
1119 
1120 	// ggf. externe Headerbar anpassen
1121 	if ( getDataWindow()->pHeaderBar )
1122 	{
1123 		long nWidth = 0;
1124 		for ( sal_uInt16 nCol = 0;
1125 			  nCol < pCols->Count() && nCol < nFirstCol;
1126 			  ++nCol )
1127 		{
1128 			// HandleColumn nicht
1129 			if ( pCols->GetObject(nCol)->GetId() )
1130 				nWidth += pCols->GetObject(nCol)->Width();
1131 		}
1132 
1133 		getDataWindow()->pHeaderBar->SetOffset( nWidth );
1134 	}
1135 
1136 	if( bInvalidateView )
1137 	{
1138 		Control::Invalidate( INVALIDATE_NOCHILDREN );
1139 		pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1140 	}
1141 
1142 	// implicitly show cursor after scrolling
1143 	if ( nCols )
1144 	{
1145 		getDataWindow()->Update();
1146 		Update();
1147 	}
1148 	bScrolling = sal_False;
1149 	EndScroll();
1150 
1151 	return nCols;
1152 }
1153 
1154 //-------------------------------------------------------------------
1155 
1156 long BrowseBox::ScrollRows( long nRows )
1157 {
1158 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1159 
1160 	// out of range?
1161 	if ( getDataWindow()->bNoScrollBack && nRows < 0 )
1162 		return 0;
1163 
1164 	// compute new top row
1165 	long nTmpMin = Min( (long)(nTopRow + nRows), (long)(nRowCount - 1) );
1166 
1167 	long nNewTopRow = Max( (long)nTmpMin, (long)0 );
1168 
1169 	if ( nNewTopRow == nTopRow )
1170 		return 0;
1171 
1172 	sal_uInt16 nVisibleRows =
1173 		(sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1174 
1175 	VisibleRowsChanged(nNewTopRow, nVisibleRows);
1176 
1177 	// compute new top row again (nTopRow might have changed!)
1178 	nTmpMin = Min( (long)(nTopRow + nRows), (long)(nRowCount - 1) );
1179 
1180 	nNewTopRow = Max( (long)nTmpMin, (long)0 );
1181 
1182 	StartScroll();
1183 
1184 	// scroll area on screen and/or repaint
1185 	long nDeltaY = GetDataRowHeight() * ( nNewTopRow - nTopRow );
1186 	long nOldTopRow = nTopRow;
1187 	nTopRow = nNewTopRow;
1188 
1189 	if ( GetUpdateMode() )
1190 	{
1191 		pVScroll->SetRange( Range( 0L, nRowCount ) );
1192 		pVScroll->SetThumbPos( nTopRow );
1193 
1194 		if( pDataWin->GetBackground().IsScrollable() &&
1195 			Abs( nDeltaY ) > 0 &&
1196 			Abs( nDeltaY ) < pDataWin->GetSizePixel().Height() )
1197 		{
1198 			pDataWin->Scroll( 0, (short)-nDeltaY, SCROLL_FLAGS );
1199 		}
1200 		else
1201 			getDataWindow()->Invalidate();
1202 
1203 		if ( nTopRow - nOldTopRow )
1204 			getDataWindow()->Update();
1205 	}
1206 
1207 	EndScroll();
1208 
1209 	return nTopRow - nOldTopRow;
1210 }
1211 
1212 //-------------------------------------------------------------------
1213 
1214 long BrowseBox::ScrollPages( long )
1215 {
1216 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1217 
1218 	return ScrollRows( pDataWin->GetSizePixel().Height() / GetDataRowHeight() );
1219 }
1220 
1221 //-------------------------------------------------------------------
1222 
1223 void BrowseBox::RowModified( long nRow, sal_uInt16 nColId )
1224 {
1225 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1226 
1227 	if ( !GetUpdateMode() )
1228 		return;
1229 
1230 	Rectangle aRect;
1231 	if ( nColId == USHRT_MAX )
1232 		// invalidate the whole row
1233 		aRect = Rectangle( Point( 0, (nRow-nTopRow) * GetDataRowHeight() ),
1234 					Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1235 	else
1236 	{
1237 		// invalidate the specific field
1238 		aRect = GetFieldRectPixel( nRow, nColId, sal_False );
1239 	}
1240 	getDataWindow()->Invalidate( aRect );
1241 }
1242 
1243 //-------------------------------------------------------------------
1244 
1245 void BrowseBox::Clear()
1246 {
1247 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1248 
1249 	// adjust the total number of rows
1250 	DoHideCursor( "Clear" );
1251 	long nOldRowCount = nRowCount;
1252 	nRowCount = 0;
1253 	nCurRow = BROWSER_ENDOFSELECTION;
1254 	nTopRow = 0;
1255 	nCurColId = 0;
1256 
1257 	// nFirstCol darf nicht zurueckgesetzt werden, da ansonsten das Scrollen
1258 	// total durcheinander kommt
1259 	// nFirstCol darf nur beim Hinzufuegen oder Loeschen von Spalten geaendert werden
1260 	// nFirstCol = 0; ->Falsch!!!!
1261 	aHScroll.SetThumbPos( 0 );
1262 	pVScroll->SetThumbPos( 0 );
1263 
1264 	Invalidate();
1265 	UpdateScrollbars();
1266 	SetNoSelection();
1267 	DoShowCursor( "Clear" );
1268 	CursorMoved();
1269 
1270     if ( isAccessibleAlive() )
1271 	{
1272 		// all rows should be removed, so we remove the row header bar and append it again
1273 		// to avoid to notify every row remove
1274         if ( nOldRowCount != nRowCount )
1275         {
1276 		    commitBrowseBoxEvent(
1277                 CHILD,
1278 				Any(),
1279 				makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) )
1280             );
1281 
1282 		    // and now append it again
1283 		    commitBrowseBoxEvent(
1284                 CHILD,
1285 				makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) ),
1286 				Any()
1287             );
1288 
1289             // notify a table model change
1290             commitTableEvent(
1291                 TABLE_MODEL_CHANGED,
1292 				makeAny( AccessibleTableModelChange( DELETE,
1293                     0,
1294 					nOldRowCount,
1295 					0,
1296 					GetColumnCount())
1297                 ),
1298 				Any()
1299             );
1300         }
1301 	}
1302 }
1303 // -----------------------------------------------------------------------------
1304 void BrowseBox::RowInserted( long nRow, long nNumRows, sal_Bool bDoPaint, sal_Bool bKeepSelection )
1305 {
1306 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1307 
1308 	if (nRow < 0)
1309 		nRow = 0;
1310 	else if (nRow > nRowCount) // maximal = nRowCount
1311 		nRow = nRowCount;
1312 
1313 	if ( nNumRows <= 0 )
1314 		return;
1315 
1316 #if 0
1317 	// Zerlegung in einzelne RowInserted-Aufrufe:
1318 	if (nNumRows > 1)
1319 	{
1320 		for (long i = 0; i < nNumRows; i++)
1321 			RowInserted(nRow + i,1,bDoPaint);
1322 		return;
1323 	}
1324 #endif
1325 
1326 	// adjust total row count
1327 	sal_Bool bLastRow = nRow >= nRowCount;
1328 	nRowCount += nNumRows;
1329 
1330 	DoHideCursor( "RowInserted" );
1331 
1332 	// must we paint the new rows?
1333 	long nOldCurRow = nCurRow;
1334 	Size aSz = pDataWin->GetOutputSizePixel();
1335 	if ( bDoPaint && nRow >= nTopRow &&
1336 		 nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1337 	{
1338 		long nY = (nRow-nTopRow) * GetDataRowHeight();
1339 		if ( !bLastRow )
1340 		{
1341 			// scroll down the rows behind the new row
1342 			pDataWin->SetClipRegion();
1343 			if( pDataWin->GetBackground().IsScrollable() )
1344 			{
1345 				pDataWin->Scroll( 0, GetDataRowHeight() * nNumRows,
1346 								Rectangle( Point( 0, nY ),
1347 										Size( aSz.Width(), aSz.Height() - nY ) ),
1348 								SCROLL_FLAGS );
1349 			}
1350 			else
1351 				pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1352 		}
1353 		else
1354 			// scroll would cause a repaint, so we must explicitly invalidate
1355 			pDataWin->Invalidate( Rectangle( Point( 0, nY ),
1356 						 Size( aSz.Width(), nNumRows * GetDataRowHeight() ) ) );
1357 	}
1358 
1359 	// ggf. Top-Row korrigieren
1360 	if ( nRow < nTopRow )
1361 		nTopRow += nNumRows;
1362 
1363 	// adjust the selection
1364 	if ( bMultiSelection )
1365 		uRow.pSel->Insert( nRow, nNumRows );
1366 	else if ( uRow.nSel != BROWSER_ENDOFSELECTION && nRow <= uRow.nSel )
1367 		uRow.nSel += nNumRows;
1368 
1369 	// adjust the cursor
1370 	if ( nCurRow == BROWSER_ENDOFSELECTION )
1371 		GoToRow( 0, sal_False, bKeepSelection );
1372 	else if ( nRow <= nCurRow )
1373 		GoToRow( nCurRow += nNumRows, sal_False, bKeepSelection );
1374 
1375 	// adjust the vertical scrollbar
1376 	if ( bDoPaint )
1377 	{
1378 		UpdateScrollbars();
1379 		AutoSizeLastColumn();
1380 	}
1381 
1382 	DoShowCursor( "RowInserted" );
1383 	// notify accessible that rows were inserted
1384     if ( isAccessibleAlive() )
1385 	{
1386 		commitTableEvent(
1387             TABLE_MODEL_CHANGED,
1388 			makeAny( AccessibleTableModelChange(
1389                         INSERT,
1390 						nRow,
1391 						nRow + nNumRows,
1392 						0,
1393 						GetColumnCount()
1394                     )
1395             ),
1396 			Any()
1397         );
1398 
1399 		for (sal_Int32 i = nRow+1 ; i <= nRowCount ; ++i)
1400 		{
1401 			commitHeaderBarEvent(
1402                 CHILD,
1403 				makeAny( CreateAccessibleRowHeader( i ) ),
1404 				Any(),
1405 				sal_False
1406             );
1407 		}
1408 	}
1409 
1410 	if ( nCurRow != nOldCurRow )
1411 		CursorMoved();
1412 
1413 	DBG_ASSERT(nRowCount > 0,"BrowseBox: nRowCount <= 0");
1414 	DBG_ASSERT(nCurRow >= 0,"BrowseBox: nCurRow < 0");
1415 	DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1416 }
1417 
1418 //-------------------------------------------------------------------
1419 
1420 void BrowseBox::RowRemoved( long nRow, long nNumRows, sal_Bool bDoPaint )
1421 {
1422 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1423 
1424 	if ( nRow < 0 )
1425 		nRow = 0;
1426 	else if ( nRow >= nRowCount )
1427 		nRow = nRowCount - 1;
1428 
1429 	if ( nNumRows <= 0 )
1430 		return;
1431 
1432 	if ( nRowCount <= 0 )
1433 		return;
1434 
1435 	if ( bDoPaint )
1436 	{
1437 		// hide cursor and selection
1438 		DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1439 		ToggleSelection();
1440 		DoHideCursor( "RowRemoved" );
1441 	}
1442 
1443 	// adjust total row count
1444 	nRowCount -= nNumRows;
1445 	if (nRowCount < 0) nRowCount = 0;
1446 	long nOldCurRow = nCurRow;
1447 
1448 	// adjust the selection
1449 	if ( bMultiSelection )
1450 		// uRow.pSel->Remove( nRow, nNumRows );
1451 		for ( long i = 0; i < nNumRows; i++ )
1452 			uRow.pSel->Remove( nRow );
1453 	else if ( nRow < uRow.nSel && uRow.nSel >= nNumRows )
1454 		uRow.nSel -= nNumRows;
1455 	else if ( nRow <= uRow.nSel )
1456 		uRow.nSel = BROWSER_ENDOFSELECTION;
1457 
1458 	// adjust the cursor
1459 	if ( nRowCount == 0 )	// don't compare nRowCount with nNumRows as nNumRows already was subtracted from nRowCount
1460 		nCurRow = BROWSER_ENDOFSELECTION;
1461 	else if ( nRow < nCurRow )
1462 	{
1463 		nCurRow -= Min( nCurRow - nRow, nNumRows );
1464 		// with the above nCurRow points a) to the first row after the removed block or b) to the same line
1465 		// as before, but moved up nNumRows
1466 		// case a) needs an additional correction if the last n lines were deleted, as 'the first row after the
1467 		// removed block' is an invalid position then
1468 		// FS - 09/28/99 - 68429
1469 		if (nCurRow == nRowCount)
1470 			--nCurRow;
1471 	}
1472 	else if( nRow == nCurRow && nCurRow == nRowCount )
1473 		nCurRow = nRowCount-1;
1474 
1475 	// is the deleted row visible?
1476 	Size aSz = pDataWin->GetOutputSizePixel();
1477 	if ( nRow >= nTopRow &&
1478 		 nRow <= nTopRow + aSz.Height() / GetDataRowHeight() )
1479 	{
1480 		if ( bDoPaint )
1481 		{
1482 			// scroll up the rows behind the deleted row
1483 			// if there are Rows behind
1484 			if (nRow < nRowCount)
1485 			{
1486 				long nY = (nRow-nTopRow) * GetDataRowHeight();
1487 				pDataWin->SetClipRegion();
1488 				if( pDataWin->GetBackground().IsScrollable() )
1489 				{
1490 					pDataWin->Scroll( 0, - (short) GetDataRowHeight() * nNumRows,
1491 						Rectangle( Point( 0, nY ), Size( aSz.Width(),
1492 							aSz.Height() - nY + nNumRows*GetDataRowHeight() ) ),
1493 							SCROLL_FLAGS );
1494 				}
1495 				else
1496 					pDataWin->Window::Invalidate( INVALIDATE_NOCHILDREN );
1497 			}
1498 			else
1499 			{
1500 				// Repaint the Rect of the deleted row
1501 				Rectangle aRect(
1502 						Point( 0, (nRow-nTopRow)*GetDataRowHeight() ),
1503 						Size( pDataWin->GetSizePixel().Width(),
1504 							  nNumRows * GetDataRowHeight() ) );
1505 				pDataWin->Invalidate( aRect );
1506 			}
1507 		}
1508 	}
1509 	// is the deleted row above of the visible area?
1510 	else if ( nRow < nTopRow )
1511 		nTopRow = nTopRow >= nNumRows ? nTopRow-nNumRows : 0;
1512 
1513 	if ( bDoPaint )
1514 	{
1515 		// reshow cursor and selection
1516 		ToggleSelection();
1517 		DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1518 		DoShowCursor( "RowRemoved" );
1519 
1520 		// adjust the vertical scrollbar
1521 		UpdateScrollbars();
1522 		AutoSizeLastColumn();
1523 	}
1524 
1525     if ( isAccessibleAlive() )
1526 	{
1527 		if ( nRowCount == 0 )
1528 		{
1529 			// all columns should be removed, so we remove the column header bar and append it again
1530 			// to avoid to notify every column remove
1531 			commitBrowseBoxEvent(
1532                 CHILD,
1533 				Any(),
1534 				makeAny( m_pImpl->getAccessibleHeaderBar( BBTYPE_ROWHEADERBAR ) )
1535             );
1536 
1537             // and now append it again
1538 			commitBrowseBoxEvent(
1539                 CHILD,
1540 				makeAny(m_pImpl->getAccessibleHeaderBar(BBTYPE_ROWHEADERBAR)),
1541 				Any()
1542             );
1543 			commitBrowseBoxEvent(
1544                 CHILD,
1545 				Any(),
1546 				makeAny( m_pImpl->getAccessibleTable() )
1547             );
1548 
1549             // and now append it again
1550 			commitBrowseBoxEvent(
1551                 CHILD,
1552 				makeAny( m_pImpl->getAccessibleTable() ),
1553 				Any()
1554             );
1555 		}
1556 		else
1557 		{
1558 			commitTableEvent(
1559                 TABLE_MODEL_CHANGED,
1560 				makeAny( AccessibleTableModelChange(
1561                             DELETE,
1562 							nRow,
1563 							nRow + nNumRows,
1564 							0,
1565 							GetColumnCount()
1566                             )
1567                 ),
1568 				Any()
1569             );
1570 
1571             for (sal_Int32 i = nRow+1 ; i <= (nRow+nNumRows) ; ++i)
1572 			{
1573 				commitHeaderBarEvent(
1574                     CHILD,
1575 					Any(),
1576 					makeAny( CreateAccessibleRowHeader( i ) ),
1577                     sal_False
1578                 );
1579 			}
1580 		}
1581 	}
1582 
1583 	if ( nOldCurRow != nCurRow )
1584 		CursorMoved();
1585 
1586 	DBG_ASSERT(nRowCount >= 0,"BrowseBox: nRowCount < 0");
1587 	DBG_ASSERT(nCurRow >= 0 || nRowCount == 0,"BrowseBox: nCurRow < 0 && nRowCount != 0");
1588 	DBG_ASSERT(nCurRow < nRowCount,"nCurRow >= nRowCount");
1589 }
1590 
1591 //-------------------------------------------------------------------
1592 
1593 sal_Bool BrowseBox::GoToRow( long nRow)
1594 {
1595 	return GoToRow(nRow, sal_False, sal_False);
1596 }
1597 
1598 //-------------------------------------------------------------------
1599 
1600 sal_Bool BrowseBox::GoToRowAndDoNotModifySelection( long nRow )
1601 {
1602 	return GoToRow( nRow, sal_False, sal_True );
1603 }
1604 
1605 //-------------------------------------------------------------------
1606 sal_Bool BrowseBox::GoToRow( long nRow, sal_Bool bRowColMove, sal_Bool bKeepSelection )
1607 {
1608 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1609 
1610 	long nOldCurRow = nCurRow;
1611 
1612 	// nothing to do?
1613 	if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) )
1614 		return sal_True;
1615 
1616 	// out of range?
1617 	if ( nRow < 0 || nRow >= nRowCount )
1618 		return sal_False;
1619 
1620 	// nicht erlaubt?
1621 	if ( ( !bRowColMove && !IsCursorMoveAllowed( nRow, nCurColId ) ) )
1622 		return sal_False;
1623 
1624 	if ( getDataWindow()->bNoScrollBack && nRow < nTopRow )
1625 		nRow = nTopRow;
1626 
1627 	// compute the last visible row
1628 	Size aSz( pDataWin->GetSizePixel() );
1629 	sal_uInt16 nVisibleRows = sal_uInt16( aSz.Height() / GetDataRowHeight() - 1 );
1630 	long nLastRow = nTopRow + nVisibleRows;
1631 
1632 	// suspend Updates
1633 	getDataWindow()->EnterUpdateLock();
1634 
1635 	// ggf. altes Highlight weg
1636 	if ( !bMultiSelection && !bKeepSelection )
1637 		ToggleSelection();
1638 	DoHideCursor( "GoToRow" );
1639 
1640 	// must we scroll?
1641 	sal_Bool bWasVisible = bSelectionIsVisible;
1642 	if (! bMultiSelection)
1643 	{
1644 		if( !bKeepSelection )
1645 			bSelectionIsVisible = sal_False;
1646 	}
1647 	if ( nRow < nTopRow )
1648 		ScrollRows( nRow - nTopRow );
1649 	else if ( nRow > nLastRow )
1650 		ScrollRows( nRow - nLastRow );
1651 	bSelectionIsVisible = bWasVisible;
1652 
1653 	// adjust cursor (selection) and thumb
1654 	if ( GetUpdateMode() )
1655 		pVScroll->SetThumbPos( nTopRow );
1656 
1657 	// relative positioning (because nCurRow might have changed in the meantime)!
1658 	if (nCurRow != BROWSER_ENDOFSELECTION )
1659 		nCurRow = nCurRow + (nRow - nOldCurRow);
1660 
1661 	// make sure that the current position is valid
1662 	if (nCurRow == BROWSER_ENDOFSELECTION && nRowCount > 0)
1663 		nCurRow = 0;
1664 	else if ( nCurRow >= nRowCount )
1665 		nCurRow = nRowCount - 1;
1666 	aSelRange = Range( nCurRow, nCurRow );
1667 
1668 	// ggf. neues Highlight anzeigen
1669 	if ( !bMultiSelection && !bKeepSelection )
1670 		uRow.nSel = nRow;
1671 
1672 	// resume Updates
1673 	getDataWindow()->LeaveUpdateLock();
1674 
1675 	// Cursor+Highlight
1676 	if ( !bMultiSelection && !bKeepSelection)
1677 		ToggleSelection();
1678 	DoShowCursor( "GoToRow" );
1679 	if ( !bRowColMove  && nOldCurRow != nCurRow )
1680 		CursorMoved();
1681 
1682 	if ( !bMultiSelection && !bKeepSelection )
1683 	{
1684 		if ( !bSelecting )
1685 			Select();
1686 		else
1687 			bSelect = sal_True;
1688 	}
1689 	return sal_True;
1690 }
1691 
1692 //-------------------------------------------------------------------
1693 
1694 sal_Bool BrowseBox::GoToColumnId( sal_uInt16 nColId)
1695 {
1696 	return GoToColumnId(nColId,sal_True,sal_False);
1697 }
1698 
1699 
1700 sal_Bool BrowseBox::GoToColumnId( sal_uInt16 nColId, sal_Bool bMakeVisible, sal_Bool bRowColMove)
1701 {
1702 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1703 
1704 	if (!bColumnCursor)
1705 		return sal_False;
1706 
1707 	// erlaubt?
1708 	if (!bRowColMove && !IsCursorMoveAllowed( nCurRow, nColId ) )
1709 		return sal_False;
1710 
1711 	if ( nColId != nCurColId || (bMakeVisible && !IsFieldVisible(nCurRow, nColId, sal_True)))
1712 	{
1713         sal_uInt16 nNewPos = GetColumnPos(nColId);
1714         BrowserColumn* pColumn = pCols->GetObject( nNewPos );
1715         DBG_ASSERT( pColumn, "no column object - invalid id?" );
1716         if ( !pColumn )
1717             return sal_False;
1718 
1719 		DoHideCursor( "GoToColumnId" );
1720 		nCurColId = nColId;
1721 
1722 		sal_uInt16 nFirstPos = nFirstCol;
1723         sal_uInt16 nWidth = (sal_uInt16)pColumn->Width();
1724 		sal_uInt16 nLastPos = GetColumnAtXPosPixel(
1725 							pDataWin->GetSizePixel().Width()-nWidth, sal_False );
1726 		sal_uInt16 nFrozen = FrozenColCount();
1727 		if ( bMakeVisible && nLastPos &&
1728 			 nNewPos >= nFrozen && ( nNewPos < nFirstPos || nNewPos > nLastPos ) )
1729 		{
1730 			if ( nNewPos < nFirstPos )
1731 				ScrollColumns( nNewPos-nFirstPos );
1732 			else if ( nNewPos > nLastPos )
1733 				ScrollColumns( nNewPos-nLastPos );
1734 		}
1735 
1736 		DoShowCursor( "GoToColumnId" );
1737 		if (!bRowColMove)
1738 			CursorMoved();
1739 		return sal_True;
1740 	}
1741 	return sal_True;
1742 }
1743 
1744 //-------------------------------------------------------------------
1745 
1746 sal_Bool BrowseBox::GoToRowColumnId( long nRow, sal_uInt16 nColId )
1747 {
1748 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1749 
1750 	// out of range?
1751 	if ( nRow < 0 || nRow >= nRowCount )
1752 		return sal_False;
1753 
1754 	if (!bColumnCursor)
1755 		return sal_False;
1756 
1757 	// nothing to do ?
1758 	if ( nRow == nCurRow && ( bMultiSelection || uRow.nSel == nRow ) &&
1759 		 nColId == nCurColId && IsFieldVisible(nCurRow, nColId, sal_True))
1760 		return sal_True;
1761 
1762 	// erlaubt?
1763 	if (!IsCursorMoveAllowed(nRow, nColId))
1764 		return sal_False;
1765 
1766 	DoHideCursor( "GoToRowColumnId" );
1767 	sal_Bool bMoved = GoToRow(nRow, sal_True) && GoToColumnId(nColId, sal_True, sal_True);
1768 	DoShowCursor( "GoToRowColumnId" );
1769 
1770 	if (bMoved)
1771 		CursorMoved();
1772 
1773 	return bMoved;
1774 }
1775 
1776 //-------------------------------------------------------------------
1777 
1778 void BrowseBox::SetNoSelection()
1779 {
1780 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1781 
1782 	// is there no selection
1783 	if ( ( !pColSel || !pColSel->GetSelectCount() ) &&
1784 		 ( ( !bMultiSelection && uRow.nSel == BROWSER_ENDOFSELECTION ) ||
1785 		   ( bMultiSelection && !uRow.pSel->GetSelectCount() ) ) )
1786 		// nothing to do
1787 		return;
1788 
1789 	DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1790 	ToggleSelection();
1791 
1792 	// unselect all
1793 	if ( bMultiSelection )
1794 		uRow.pSel->SelectAll(sal_False);
1795 	else
1796 		uRow.nSel = BROWSER_ENDOFSELECTION;
1797 	if ( pColSel )
1798 		pColSel->SelectAll(sal_False);
1799 	if ( !bSelecting )
1800 		Select();
1801 	else
1802 		bSelect = sal_True;
1803 
1804 	// restore screen
1805 	DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1806 
1807     if ( isAccessibleAlive() )
1808 	{
1809 		commitTableEvent(
1810             SELECTION_CHANGED,
1811 			Any(),
1812 			Any()
1813         );
1814 	}
1815 }
1816 
1817 //-------------------------------------------------------------------
1818 
1819 void BrowseBox::SetSelection( const MultiSelection &rSel )
1820 {
1821 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1822 	DBG_ASSERT( bMultiSelection, "SetSelection only allowed with Multi-Selection-Mode" );
1823 
1824 	// prepare inverted areas
1825 	DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1826 	ToggleSelection();
1827 
1828 	// assign Selection
1829 	*uRow.pSel = rSel;
1830 
1831 	// only highlight painted areas
1832 	pDataWin->Update();
1833 
1834 	// notify derived class
1835 	if ( !bSelecting )
1836 		Select();
1837 	else
1838 		bSelect = sal_True;
1839 
1840 	// restore screen
1841 	ToggleSelection();
1842 	DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1843 
1844     if ( isAccessibleAlive() )
1845 	{
1846 		commitTableEvent(
1847             SELECTION_CHANGED,
1848 			Any(),
1849 			Any()
1850         );
1851 	}
1852 }
1853 
1854 //-------------------------------------------------------------------
1855 
1856 void BrowseBox::SelectAll()
1857 {
1858 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1859 
1860 	if ( !bMultiSelection )
1861 		return;
1862 
1863 	DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1864 	ToggleSelection();
1865 
1866 	// select all rows
1867 	if ( pColSel )
1868 		pColSel->SelectAll(sal_False);
1869 	uRow.pSel->SelectAll(sal_True);
1870 
1871 	// Handle-Column nicht highlighten
1872 	BrowserColumn *pFirstCol = pCols->GetObject(0);
1873 	long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1874 
1875 	// highlight the row selection
1876 	if ( !bHideSelect )
1877 	{
1878 		Rectangle aHighlightRect;
1879 		sal_uInt16 nVisibleRows =
1880 			(sal_uInt16)(pDataWin->GetOutputSizePixel().Height() / GetDataRowHeight() + 1);
1881 		for ( long nRow = Max( nTopRow, uRow.pSel->FirstSelected() );
1882 			  nRow != BROWSER_ENDOFSELECTION && nRow < nTopRow + nVisibleRows;
1883 			  nRow = uRow.pSel->NextSelected() )
1884 			aHighlightRect.Union( Rectangle(
1885 				Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1886 				Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) ) );
1887 		pDataWin->Invalidate( aHighlightRect );
1888 	}
1889 
1890 	if ( !bSelecting )
1891 		Select();
1892 	else
1893 		bSelect = sal_True;
1894 
1895 	// restore screen
1896 	DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1897 
1898     if ( isAccessibleAlive() )
1899 	{
1900 		commitTableEvent(
1901             SELECTION_CHANGED,
1902 			Any(),
1903 			Any()
1904         );
1905 		commitHeaderBarEvent(
1906             SELECTION_CHANGED,
1907 			Any(),
1908 			Any(),
1909 			sal_True
1910         ); // column header event
1911 
1912         commitHeaderBarEvent(
1913             SELECTION_CHANGED,
1914 			Any(),
1915 			Any(),
1916 			sal_False
1917         ); // row header event
1918 	}
1919 }
1920 
1921 //-------------------------------------------------------------------
1922 
1923 void BrowseBox::SelectRow( long nRow, sal_Bool _bSelect, sal_Bool bExpand )
1924 {
1925 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
1926 
1927 	if ( !bMultiSelection )
1928 	{
1929 		// deselecting is impossible, selecting via cursor
1930 		if ( _bSelect )
1931 			GoToRow(nRow, sal_False);
1932 		return;
1933 	}
1934 
1935 	DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
1936 
1937 	// remove old selection?
1938 	if ( !bExpand || !bMultiSelection )
1939 	{
1940 		ToggleSelection();
1941 		if ( bMultiSelection )
1942 			uRow.pSel->SelectAll(sal_False);
1943 		else
1944 			uRow.nSel = BROWSER_ENDOFSELECTION;
1945 		if ( pColSel )
1946 			pColSel->SelectAll(sal_False);
1947 	}
1948 
1949 	// set new selection
1950 	if	(	!bHideSelect
1951 		&&	(	(	bMultiSelection
1952 				&&	uRow.pSel->GetTotalRange().Max() >= nRow
1953 				&&	uRow.pSel->Select( nRow, _bSelect )
1954 				)
1955 			||	(	!bMultiSelection
1956 				&&	( uRow.nSel = nRow ) != BROWSER_ENDOFSELECTION )
1957 				)
1958 			)
1959 	{
1960 		// Handle-Column nicht highlighten
1961 		BrowserColumn *pFirstCol = pCols->GetObject(0);
1962 		long nOfsX = pFirstCol->GetId() ? 0 : pFirstCol->Width();
1963 
1964 		// highlight only newly selected part
1965 		Rectangle aRect(
1966 			Point( nOfsX, (nRow-nTopRow)*GetDataRowHeight() ),
1967 			Size( pDataWin->GetSizePixel().Width(), GetDataRowHeight() ) );
1968 		pDataWin->Invalidate( aRect );
1969 	}
1970 
1971 	if ( !bSelecting )
1972 		Select();
1973 	else
1974 		bSelect = sal_True;
1975 
1976 	// restore screen
1977 	DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
1978 
1979     if ( isAccessibleAlive() )
1980 	{
1981 		commitTableEvent(
1982             SELECTION_CHANGED,
1983 			Any(),
1984 			Any()
1985         );
1986 		commitHeaderBarEvent(
1987             SELECTION_CHANGED,
1988 			Any(),
1989 			Any(),
1990 			sal_False
1991         ); // row header event
1992 	}
1993 }
1994 
1995 //-------------------------------------------------------------------
1996 
1997 long BrowseBox::GetSelectRowCount() const
1998 {
1999 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2000 
2001 	return bMultiSelection ? uRow.pSel->GetSelectCount() :
2002 		   uRow.nSel == BROWSER_ENDOFSELECTION ? 0 : 1;
2003 }
2004 
2005 //-------------------------------------------------------------------
2006 
2007 void BrowseBox::SelectColumnPos( sal_uInt16 nNewColPos, sal_Bool _bSelect, sal_Bool bMakeVisible )
2008 {
2009 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2010 
2011 	if ( !bColumnCursor || nNewColPos == BROWSER_INVALIDID )
2012 		return;
2013 
2014 	if ( !bMultiSelection )
2015 	{
2016 		if ( _bSelect )
2017 			GoToColumnId( pCols->GetObject(nNewColPos)->GetId(), bMakeVisible );
2018 		return;
2019 	}
2020 	else
2021 	{
2022 		if ( !GoToColumnId( pCols->GetObject( nNewColPos )->GetId(), bMakeVisible ) )
2023 			return;
2024 	}
2025 
2026 	DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
2027 	ToggleSelection();
2028 	if ( bMultiSelection )
2029 		uRow.pSel->SelectAll(sal_False);
2030 	else
2031 		uRow.nSel = BROWSER_ENDOFSELECTION;
2032 	pColSel->SelectAll(sal_False);
2033 
2034 	if ( pColSel->Select( nNewColPos, _bSelect ) )
2035 	{
2036 		// GoToColumnId( pCols->GetObject(nNewColPos)->GetId(), bMakeVisible );
2037 
2038 		// only highlight painted areas
2039 		pDataWin->Update();
2040 		Rectangle aFieldRectPix( GetFieldRectPixel( nCurRow, nCurColId, sal_False ) );
2041 		Rectangle aRect(
2042 			Point( aFieldRectPix.Left() - MIN_COLUMNWIDTH, 0 ),
2043 			Size( pCols->GetObject(nNewColPos)->Width(),
2044 				  pDataWin->GetOutputSizePixel().Height() ) );
2045 		pDataWin->Invalidate( aRect );
2046 		if ( !bSelecting )
2047 			Select();
2048 		else
2049 			bSelect = sal_True;
2050 
2051         if ( isAccessibleAlive() )
2052 		{
2053 			commitTableEvent(
2054                 SELECTION_CHANGED,
2055 				Any(),
2056 				Any()
2057             );
2058 			commitHeaderBarEvent(
2059                 SELECTION_CHANGED,
2060 				Any(),
2061 				Any(),
2062 				sal_True
2063             ); // column header event
2064 		}
2065 	}
2066 
2067 	// restore screen
2068 	DBG_TRACE1( "BrowseBox: %p->ShowCursor", this );
2069 }
2070 
2071 //-------------------------------------------------------------------
2072 
2073 sal_uInt16 BrowseBox::GetSelectColumnCount() const
2074 {
2075 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2076 
2077 	// while bAutoSelect (==!pColSel), 1 if any rows (yes rows!) else none
2078 	return pColSel ? (sal_uInt16) pColSel->GetSelectCount() :
2079 		   nCurRow >= 0 ? 1 : 0;
2080 }
2081 
2082 //-------------------------------------------------------------------
2083 long BrowseBox::FirstSelectedColumn( ) const
2084 {
2085 	return pColSel ? pColSel->FirstSelected() : BROWSER_ENDOFSELECTION;
2086 }
2087 
2088 //-------------------------------------------------------------------
2089 long BrowseBox::NextSelectedColumn( ) const
2090 {
2091 	return pColSel ? pColSel->NextSelected() : BROWSER_ENDOFSELECTION;
2092 }
2093 
2094 //-------------------------------------------------------------------
2095 
2096 long BrowseBox::FirstSelectedRow( sal_Bool bInverse )
2097 {
2098 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2099 
2100 	return bMultiSelection ? uRow.pSel->FirstSelected(bInverse) : uRow.nSel;
2101 }
2102 
2103 //-------------------------------------------------------------------
2104 
2105 long BrowseBox::NextSelectedRow()
2106 {
2107 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2108 
2109 	return bMultiSelection ? uRow.pSel->NextSelected() : BROWSER_ENDOFSELECTION;
2110 }
2111 
2112 //-------------------------------------------------------------------
2113 
2114 long BrowseBox::PrevSelectedRow()
2115 {
2116 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2117 
2118 	return bMultiSelection ? uRow.pSel->PrevSelected() : BROWSER_ENDOFSELECTION;
2119 }
2120 
2121 //-------------------------------------------------------------------
2122 
2123 long BrowseBox::LastSelectedRow()
2124 {
2125 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2126 
2127 	return bMultiSelection ? uRow.pSel->LastSelected() : uRow.nSel;
2128 }
2129 
2130 //-------------------------------------------------------------------
2131 
2132 bool BrowseBox::IsRowSelected( long nRow ) const
2133 {
2134 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2135 
2136 	return bMultiSelection ? uRow.pSel->IsSelected(nRow) : nRow == uRow.nSel;
2137 }
2138 
2139 //-------------------------------------------------------------------
2140 
2141 bool BrowseBox::IsColumnSelected( sal_uInt16 nColumnId ) const
2142 {
2143 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2144 
2145 	return pColSel ? pColSel->IsSelected( GetColumnPos(nColumnId) ) :
2146 					 nCurColId == nColumnId;
2147 }
2148 
2149 //-------------------------------------------------------------------
2150 
2151 sal_Bool BrowseBox::IsAllSelected() const
2152 {
2153 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2154 
2155     return bMultiSelection && uRow.pSel->IsAllSelected();
2156 }
2157 
2158 //-------------------------------------------------------------------
2159 
2160 sal_Bool BrowseBox::MakeFieldVisible
2161 (
2162 	long	nRow,		// Zeilen-Nr des Feldes (beginnend mit 0)
2163 	sal_uInt16	nColId, 	// Spalten-Id des Feldes
2164 	sal_Bool	bComplete	// (== sal_False), sal_True => vollst"andig sichtbar machen
2165 )
2166 
2167 /*	[Beschreibung]
2168 
2169 	Macht das durch 'nRow' und 'nColId' beschriebene Feld durch
2170 	entsprechendes scrollen sichtbar. Ist 'bComplete' gesetzt, dann wird
2171 	gefordert, da\s das Feld ganz sichtbar wird.
2172 
2173 	[R"uckgabewert]
2174 
2175 	sal_Bool			sal_True
2176 					Das angegebene Feld wurde sichtbar gemacht, bzw. war
2177 					bereits sichtbar.
2178 
2179 					sal_False
2180 					Das angegebene Feld konnte nicht sichtbar bzw. bei
2181 					'bComplete' nicht vollst"andig sichtbar gemacht werden.
2182 */
2183 
2184 {
2185 	Size aTestSize = pDataWin->GetSizePixel();
2186 
2187 	if ( !bBootstrapped ||
2188 		 ( aTestSize.Width() == 0 && aTestSize.Height() == 0 ) )
2189 		return sal_False;
2190 
2191 	// ist es schon sichtbar?
2192 	sal_Bool bVisible = IsFieldVisible( nRow, nColId, bComplete );
2193 	if ( bVisible )
2194 		return sal_True;
2195 
2196 	// Spaltenposition und Feld-Rechteck und Ausgabebereich berechnen
2197 	sal_uInt16 nColPos = GetColumnPos( nColId );
2198 	Rectangle aFieldRect = GetFieldRectPixel( nRow, nColId, sal_False );
2199 	Rectangle aDataRect = Rectangle( Point(0, 0), pDataWin->GetSizePixel() );
2200 
2201 	// links au\serhalb?
2202 	if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
2203 		// => nach rechts scrollen
2204 		ScrollColumns( nColPos - nFirstCol );
2205 
2206 	// solange rechts au\serhalb
2207 	while ( aDataRect.Right() < ( bComplete
2208 				? aFieldRect.Right()
2209 				: aFieldRect.Left()+aFieldRect.GetWidth()/2 ) )
2210 	{
2211 		// => nach links scrollen
2212 		if ( ScrollColumns( 1 ) != 1 )
2213 			// nichts mehr zu scrollen
2214 			break;
2215 		aFieldRect = GetFieldRectPixel( nRow, nColId, sal_False );
2216 	}
2217 
2218 	// oben au\serhalb?
2219 	if ( nRow < nTopRow )
2220 		// nach unten scrollen
2221 		ScrollRows( nRow - nTopRow );
2222 
2223 	// unten au\serhalb?
2224 	long nBottomRow = nTopRow + GetVisibleRows();
2225 	// OV: damit nBottomRow die Nummer der letzten sichtbaren Zeile ist
2226 	// (Zaehlung ab Null!), muss sie dekrementiert werden.
2227 	// Beispiel: BrowseBox enthaelt genau einen Eintrag. nBottomRow := 0 + 1 - 1
2228 	if( nBottomRow )
2229 		nBottomRow--;
2230 
2231 	if ( nRow > nBottomRow )
2232 		// nach oben scrollen
2233 		ScrollRows( nRow - nBottomRow );
2234 
2235 	// jetzt kann es immer noch nicht passen, z.B. weil Window zu klein
2236 	return IsFieldVisible( nRow, nColId, bComplete );
2237 }
2238 
2239 //-------------------------------------------------------------------
2240 
2241 sal_Bool BrowseBox::IsFieldVisible( long nRow, sal_uInt16 nColumnId,
2242 								sal_Bool bCompletely ) const
2243 {
2244 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2245 
2246 	// durch frozen-Column verdeckt?
2247 	sal_uInt16 nColPos = GetColumnPos( nColumnId );
2248 	if ( nColPos >= FrozenColCount() && nColPos < nFirstCol )
2249 		return sal_False;
2250 
2251 	Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2252 	if ( aRect.IsEmpty() )
2253 		return sal_False;
2254 
2255 	// get the visible area
2256 	Rectangle aOutRect( Point(0, 0), pDataWin->GetOutputSizePixel() );
2257 
2258 	if ( bCompletely )
2259 		// test if the field is completely visible
2260 		return aOutRect.IsInside( aRect );
2261 	else
2262 		// test if the field is partly of completely visible
2263 		return !aOutRect.Intersection( aRect ).IsEmpty();
2264 }
2265 
2266 //-------------------------------------------------------------------
2267 
2268 Rectangle BrowseBox::GetFieldRectPixel( long nRow, sal_uInt16 nColumnId,
2269 										sal_Bool bRelToBrowser) const
2270 {
2271 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2272 
2273 	// get the rectangle relative to DataWin
2274 	Rectangle aRect( ImplFieldRectPixel( nRow, nColumnId ) );
2275 	if ( aRect.IsEmpty() )
2276 		return aRect;
2277 
2278 	// adjust relative to BrowseBox's output area
2279 	Point aTopLeft( aRect.TopLeft() );
2280 	if ( bRelToBrowser )
2281 	{
2282 		aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2283 		aTopLeft = ScreenToOutputPixel( aTopLeft );
2284 	}
2285 
2286 	return Rectangle( aTopLeft, aRect.GetSize() );
2287 }
2288 
2289 //-------------------------------------------------------------------
2290 
2291 Rectangle BrowseBox::GetRowRectPixel( long nRow, sal_Bool bRelToBrowser  ) const
2292 {
2293 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2294 
2295 	// get the rectangle relative to DataWin
2296 	Rectangle aRect;
2297 	if ( nTopRow > nRow )
2298 		// row is above visible area
2299 		return aRect;
2300 	aRect = Rectangle(
2301 		Point( 0, GetDataRowHeight() * (nRow-nTopRow) ),
2302 		Size( pDataWin->GetOutputSizePixel().Width(), GetDataRowHeight() ) );
2303 	if ( aRect.TopLeft().Y() > pDataWin->GetOutputSizePixel().Height() )
2304 		// row is below visible area
2305 		return aRect;
2306 
2307 	// adjust relative to BrowseBox's output area
2308 	Point aTopLeft( aRect.TopLeft() );
2309 	if ( bRelToBrowser )
2310 	{
2311 		aTopLeft = pDataWin->OutputToScreenPixel( aTopLeft );
2312 		aTopLeft = ScreenToOutputPixel( aTopLeft );
2313 	}
2314 
2315 	return Rectangle( aTopLeft, aRect.GetSize() );
2316 }
2317 
2318 //-------------------------------------------------------------------
2319 
2320 Rectangle BrowseBox::ImplFieldRectPixel( long nRow, sal_uInt16 nColumnId ) const
2321 {
2322 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2323 
2324 	// compute the X-coordinte realtiv to DataWin by accumulation
2325 	long nColX = 0;
2326 	sal_uInt16 nFrozenCols = FrozenColCount();
2327 	sal_uInt16 nCol;
2328 	for ( nCol = 0;
2329 		  nCol < pCols->Count() && pCols->GetObject(nCol)->GetId() != nColumnId;
2330 		  ++nCol )
2331 		if ( pCols->GetObject(nCol)->IsFrozen() || nCol >= nFirstCol )
2332 			nColX += pCols->GetObject(nCol)->Width();
2333 
2334 	if ( nCol >= pCols->Count() || ( nCol >= nFrozenCols && nCol < nFirstCol ) )
2335 		return Rectangle();
2336 
2337 	// compute the Y-coordinate relative to DataWin
2338 	long nRowY = GetDataRowHeight();
2339 	if ( nRow != BROWSER_ENDOFSELECTION ) // #105497# OJ
2340 		nRowY = ( nRow - nTopRow ) * GetDataRowHeight();
2341 
2342 	// assemble the Rectangle relative to DataWin
2343 	return Rectangle(
2344 		Point( nColX + MIN_COLUMNWIDTH, nRowY ),
2345 		Size( pCols->GetObject(nCol)->Width() - 2*MIN_COLUMNWIDTH,
2346 			  GetDataRowHeight() - 1 ) );
2347 }
2348 
2349 //-------------------------------------------------------------------
2350 
2351 long BrowseBox::GetRowAtYPosPixel( long nY, sal_Bool bRelToBrowser ) const
2352 {
2353 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2354 
2355 	// compute the Y-coord
2356 	if ( bRelToBrowser )
2357 	{
2358 		Point aDataTopLeft = pDataWin->OutputToScreenPixel( Point(0, 0) );
2359 		Point aTopLeft = OutputToScreenPixel( Point(0, 0) );
2360 		nY -= aDataTopLeft.Y() - aTopLeft.Y();
2361 	}
2362 
2363 	// no row there (e.g. in the header)
2364 	if ( nY < 0 || nY >= pDataWin->GetOutputSizePixel().Height() )
2365 		return -1;
2366 
2367 	return nY / GetDataRowHeight() + nTopRow;
2368 }
2369 
2370 //-------------------------------------------------------------------
2371 
2372 Rectangle BrowseBox::GetFieldRect( sal_uInt16 nColumnId ) const
2373 {
2374 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2375 
2376 	return GetFieldRectPixel( nCurRow, nColumnId );
2377 }
2378 
2379 //-------------------------------------------------------------------
2380 
2381 sal_uInt16 BrowseBox::GetColumnAtXPosPixel( long nX, sal_Bool ) const
2382 {
2383 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2384 
2385 	// accumulate the withds of the visible columns
2386 	long nColX = 0;
2387 	sal_uInt16 nCol;
2388 	for ( nCol = 0; nCol < sal_uInt16(pCols->Count()); ++nCol )
2389 	{
2390 		BrowserColumn *pCol = pCols->GetObject(nCol);
2391 		if ( pCol->IsFrozen() || nCol >= nFirstCol )
2392 			nColX += pCol->Width();
2393 
2394 		if ( nColX > nX )
2395 			return nCol;
2396 	}
2397 
2398 	return BROWSER_INVALIDID;
2399 }
2400 
2401 //-------------------------------------------------------------------
2402 
2403 void BrowseBox::ReserveControlArea( sal_uInt16 nWidth )
2404 {
2405 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2406 
2407 	if ( nWidth != nControlAreaWidth )
2408 	{
2409         OSL_ENSURE(nWidth,"Control aera of 0 is not allowed, Use USHRT_MAX instead!");
2410 		nControlAreaWidth = nWidth;
2411 		UpdateScrollbars();
2412 	}
2413 }
2414 
2415 //-------------------------------------------------------------------
2416 
2417 Rectangle BrowseBox::GetControlArea() const
2418 {
2419 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2420 
2421 	return Rectangle(
2422 		Point( 0, GetOutputSizePixel().Height() - aHScroll.GetSizePixel().Height() ),
2423 		Size( GetOutputSizePixel().Width() - aHScroll.GetSizePixel().Width(),
2424 			 aHScroll.GetSizePixel().Height() ) );
2425 }
2426 
2427 //-------------------------------------------------------------------
2428 
2429 void BrowseBox::SetMode( BrowserMode nMode )
2430 {
2431 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2432 
2433 #ifdef DBG_MIx
2434 	Sound::Beep();
2435 	nMode =
2436 //  		BROWSER_COLUMNSELECTION |
2437 //  		BROWSER_MULTISELECTION |
2438 			BROWSER_THUMBDRAGGING |
2439 			BROWSER_KEEPHIGHLIGHT |
2440 			BROWSER_HLINES |
2441 			BROWSER_VLINES |
2442 // 			BROWSER_HIDECURSOR |
2443 //  		BROWSER_NO_HSCROLL |
2444 //  		BROWSER_NO_SCROLLBACK |
2445 			BROWSER_AUTO_VSCROLL |
2446 			BROWSER_AUTO_HSCROLL |
2447 			BROWSER_TRACKING_TIPS |
2448 //  		BROWSER_HIGHLIGHT_NONE |
2449 			BROWSER_HEADERBAR_NEW |
2450 //			BROWSER_AUTOSIZE_LASTCOL |
2451 			0;
2452 #endif
2453 
2454 	getDataWindow()->bAutoHScroll = BROWSER_AUTO_HSCROLL == ( nMode & BROWSER_AUTO_HSCROLL );
2455 	getDataWindow()->bAutoVScroll = BROWSER_AUTO_VSCROLL == ( nMode & BROWSER_AUTO_VSCROLL );
2456 	getDataWindow()->bNoHScroll   = BROWSER_NO_HSCROLL   == ( nMode & BROWSER_NO_HSCROLL );
2457     getDataWindow()->bNoVScroll   = BROWSER_NO_VSCROLL   == ( nMode & BROWSER_NO_VSCROLL );
2458 
2459     DBG_ASSERT( !( getDataWindow()->bAutoHScroll && getDataWindow()->bNoHScroll ),
2460         "BrowseBox::SetMode: AutoHScroll *and* NoHScroll?" );
2461     DBG_ASSERT( !( getDataWindow()->bAutoVScroll && getDataWindow()->bNoVScroll ),
2462         "BrowseBox::SetMode: AutoVScroll *and* NoVScroll?" );
2463     if ( getDataWindow()->bAutoHScroll )
2464         getDataWindow()->bNoHScroll = sal_False;
2465     if ( getDataWindow()->bAutoVScroll )
2466         getDataWindow()->bNoVScroll = sal_False;
2467 
2468     if ( getDataWindow()->bNoHScroll )
2469 		aHScroll.Hide();
2470 
2471     nControlAreaWidth = USHRT_MAX;
2472 
2473 	getDataWindow()->bNoScrollBack =
2474 			BROWSER_NO_SCROLLBACK == ( nMode & BROWSER_NO_SCROLLBACK);
2475 
2476 	long nOldRowSel = bMultiSelection ? uRow.pSel->FirstSelected() : uRow.nSel;
2477 	MultiSelection *pOldRowSel = bMultiSelection ? uRow.pSel : 0;
2478 	MultiSelection *pOldColSel = pColSel;
2479 
2480 	delete pVScroll;
2481 
2482 	bThumbDragging = ( nMode & BROWSER_THUMBDRAGGING ) == BROWSER_THUMBDRAGGING;
2483 	bMultiSelection = ( nMode & BROWSER_MULTISELECTION ) == BROWSER_MULTISELECTION;
2484 	bColumnCursor = ( nMode & BROWSER_COLUMNSELECTION ) == BROWSER_COLUMNSELECTION;
2485 	bKeepHighlight = ( nMode & BROWSER_KEEPSELECTION ) == BROWSER_KEEPSELECTION;
2486 
2487 	bHideSelect = ((nMode & BROWSER_HIDESELECT) == BROWSER_HIDESELECT);
2488 	// default: do not hide the cursor at all (untaken scrolling and such)
2489 	bHideCursor = NO_CURSOR_HIDE;
2490 
2491 	if ( BROWSER_SMART_HIDECURSOR == ( nMode & BROWSER_SMART_HIDECURSOR ) )
2492 	{	// smart cursor hide overrules hard cursor hide
2493 		bHideCursor = SMART_CURSOR_HIDE;
2494 	}
2495 	else if ( BROWSER_HIDECURSOR == ( nMode & BROWSER_HIDECURSOR ) )
2496 	{
2497 		bHideCursor = HARD_CURSOR_HIDE;
2498 	}
2499 
2500 	m_bFocusOnlyCursor = ((nMode & BROWSER_CURSOR_WO_FOCUS) == 0);
2501 
2502 	bHLines = ( nMode & BROWSER_HLINESFULL ) == BROWSER_HLINESFULL;
2503 	bVLines = ( nMode & BROWSER_VLINESFULL ) == BROWSER_VLINESFULL;
2504 	bHDots  = ( nMode & BROWSER_HLINESDOTS ) == BROWSER_HLINESDOTS;
2505 	bVDots  = ( nMode & BROWSER_VLINESDOTS ) == BROWSER_VLINESDOTS;
2506 
2507 	WinBits nVScrollWinBits =
2508 		WB_VSCROLL | ( ( nMode & BROWSER_THUMBDRAGGING ) ? WB_DRAG : 0 );
2509 	pVScroll = ( nMode & BROWSER_TRACKING_TIPS ) == BROWSER_TRACKING_TIPS
2510 				? new BrowserScrollBar( this, nVScrollWinBits,
2511 										(BrowserDataWin*) pDataWin )
2512 				: new ScrollBar( this, nVScrollWinBits );
2513 	pVScroll->SetLineSize( 1 );
2514 	pVScroll->SetPageSize(1);
2515 	pVScroll->SetScrollHdl( LINK( this, BrowseBox, ScrollHdl ) );
2516 	pVScroll->SetEndScrollHdl( LINK( this, BrowseBox, EndScrollHdl ) );
2517 
2518 	getDataWindow()->bAutoSizeLastCol =
2519 			BROWSER_AUTOSIZE_LASTCOL == ( nMode & BROWSER_AUTOSIZE_LASTCOL );
2520 	getDataWindow()->bOwnDataChangedHdl =
2521 			BROWSER_OWN_DATACHANGED == ( nMode & BROWSER_OWN_DATACHANGED );
2522 
2523 	// Headerbar erzeugen, was passiert, wenn eine erzeugt werden mu� und schon Spalten bestehen ?
2524 	if ( BROWSER_HEADERBAR_NEW == ( nMode & BROWSER_HEADERBAR_NEW ) )
2525 	{
2526 		if (!getDataWindow()->pHeaderBar)
2527 			getDataWindow()->pHeaderBar = CreateHeaderBar( this );
2528 	}
2529 	else
2530 	{
2531 		DELETEZ(getDataWindow()->pHeaderBar);
2532 	}
2533 
2534 
2535 
2536 	if ( bColumnCursor )
2537 	{
2538 		pColSel = pOldColSel ? pOldColSel : new MultiSelection;
2539 		pColSel->SetTotalRange( Range( 0, pCols->Count()-1 ) );
2540 	}
2541 	else
2542 	{
2543 		pColSel = 0;
2544 		delete pColSel;
2545 	}
2546 
2547 	if ( bMultiSelection )
2548 	{
2549 		if ( pOldRowSel )
2550 			uRow.pSel = pOldRowSel;
2551 		else
2552 			uRow.pSel = new MultiSelection;
2553 	}
2554 	else
2555 	{
2556 		uRow.nSel = nOldRowSel;
2557 		delete pOldRowSel;
2558 	}
2559 
2560 	if ( bBootstrapped )
2561 	{
2562 		StateChanged( STATE_CHANGE_INITSHOW );
2563 		if ( bMultiSelection && !pOldRowSel &&
2564 			 nOldRowSel != BROWSER_ENDOFSELECTION )
2565 			uRow.pSel->Select( nOldRowSel );
2566 	}
2567 
2568 	if ( pDataWin )
2569 		pDataWin->Invalidate();
2570 
2571 	// kein Cursor auf Handle-Column
2572 	if ( nCurColId == 0 )
2573 		nCurColId = GetColumnId( 1 );
2574 
2575 	m_nCurrentMode = nMode;
2576 }
2577 
2578 //-------------------------------------------------------------------
2579 
2580 void BrowseBox::VisibleRowsChanged( long, sal_uInt16 )
2581 {
2582 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2583 
2584 	// Das alte Verhalten: NumRows automatisch korrigieren:
2585 	if ( nRowCount < GetRowCount() )
2586 	{
2587 		RowInserted(nRowCount,GetRowCount() - nRowCount,sal_False);
2588 	}
2589 	else if ( nRowCount > GetRowCount() )
2590 	{
2591 		RowRemoved(nRowCount-(nRowCount - GetRowCount()),nRowCount - GetRowCount(),sal_False);
2592 	}
2593 }
2594 
2595 //-------------------------------------------------------------------
2596 
2597 sal_Bool BrowseBox::IsCursorMoveAllowed( long, sal_uInt16 ) const
2598 
2599 /*	[Beschreibung]
2600 
2601 	Diese virtuelle Methode wird immer gerufen bevor der Cursor direkt
2602 	bewegt werden soll. Durch 'return sal_False' kann verhindert werden, da\s
2603 	dies geschieht, wenn z.B. ein Datensatz irgendwelchen Rules widerspricht.
2604 
2605 	Diese Methode wird nicht gerufen, wenn die Cursorbewegung durch
2606 	ein L"oschen oder Einf"ugen (einer Zeile/Spalte) ausgel"ost wird, also
2607 	genaugenommen nur eine Cursor-Korrektur vorliegt.
2608 
2609 	Die Basisimplementierung liefert derzeit immer sal_True.
2610 */
2611 
2612 {
2613 	return sal_True;
2614 }
2615 
2616 //-------------------------------------------------------------------
2617 
2618 long BrowseBox::GetDataRowHeight() const
2619 {
2620 	return CalcZoom(nDataRowHeight ? nDataRowHeight : ImpGetDataRowHeight());
2621 }
2622 
2623 //-------------------------------------------------------------------
2624 
2625 Window& BrowseBox::GetEventWindow() const
2626 {
2627 	return *getDataWindow()->pEventWin;
2628 }
2629 
2630 //-------------------------------------------------------------------
2631 
2632 BrowserHeader* BrowseBox::CreateHeaderBar( BrowseBox* pParent )
2633 {
2634 	BrowserHeader* pNewBar = new BrowserHeader( pParent );
2635 	pNewBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2636 	return pNewBar;
2637 }
2638 
2639 void BrowseBox::SetHeaderBar( BrowserHeader* pHeaderBar )
2640 {
2641 	delete ( (BrowserDataWin*)pDataWin )->pHeaderBar;
2642 	( (BrowserDataWin*)pDataWin )->pHeaderBar = pHeaderBar;
2643 	( (BrowserDataWin*)pDataWin )->pHeaderBar->SetStartDragHdl( LINK( this, BrowseBox, StartDragHdl ) );
2644 }
2645 //-------------------------------------------------------------------
2646 
2647 #ifdef DBG_UTIL
2648 const char* BrowseBoxCheckInvariants( const void * pVoid )
2649 {
2650 	const BrowseBox * p = (const BrowseBox *)pVoid;
2651 
2652 	if (p->nRowCount < 0) return "BrowseBox: nRowCount < 0";
2653 	if (p->nTopRow < 0) return "BrowseBox: nTopRow < 0";
2654 	if (p->nTopRow >= p->nRowCount && p->nRowCount != 0) return "BrowseBox: nTopRow >= nRowCount && nRowCount != 0";
2655 	if (p->nCurRow < -1) return "BrowseBox: nCurRow < -1";
2656 	if (p->nCurRow > p->nRowCount) return "BrowseBox: nCurRow > nRowCount";
2657 
2658 	// Leider waehrend der Bearbeitung nicht immer der Fall:
2659 	//if (p->nCurRow < 0 && p->nRowCount != 0) return "nCurRow < 0 && nRowCount != 0";
2660 	//if (p->nCurRow >= p->nRowCount && p->nRowCount != 0) return "nCurRow >= nRowCount && nRowCount != 0";
2661 
2662 	return NULL;
2663 }
2664 #endif
2665 
2666 //-------------------------------------------------------------------
2667 long BrowseBox::GetTitleHeight() const
2668 {
2669 	long nHeight;
2670 	// ask the header bar for the text height (if possible), as the header bar's font is adjusted with
2671 	// our (and the header's) zoom factor
2672 	HeaderBar* pHeaderBar = ( (BrowserDataWin*)pDataWin )->pHeaderBar;
2673 	if ( pHeaderBar )
2674 		nHeight = pHeaderBar->GetTextHeight();
2675 	else
2676 		nHeight = GetTextHeight();
2677 
2678 	return nTitleLines ? nTitleLines * nHeight + 4 : 0;
2679 }
2680 
2681 //-------------------------------------------------------------------
2682 long BrowseBox::CalcReverseZoom(long nVal)
2683 {
2684 	if (IsZoom())
2685 	{
2686 		const Fraction& rZoom = GetZoom();
2687 		double n = (double)nVal;
2688 		n *= (double)rZoom.GetDenominator();
2689 		n /= (double)rZoom.GetNumerator();
2690 		nVal = n>0 ? (long)(n + 0.5) : -(long)(-n + 0.5);
2691 	}
2692 
2693 	return nVal;
2694 }
2695 
2696 //-------------------------------------------------------------------
2697 HeaderBar* BrowseBox::GetHeaderBar() const
2698 {
2699 	return getDataWindow()->pHeaderBar;
2700 }
2701 //-------------------------------------------------------------------
2702 
2703 void BrowseBox::CursorMoved()
2704 {
2705 	// before implementing more here, please adjust the EditBrowseBox
2706 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2707 
2708     if ( isAccessibleAlive() && HasFocus() )
2709 		commitTableEvent(
2710             ACTIVE_DESCENDANT_CHANGED,
2711             makeAny( CreateAccessibleCell( GetCurRow(),GetColumnPos( GetCurColumnId() ) ) ),
2712             Any()
2713         );
2714 }
2715 
2716 //-------------------------------------------------------------------
2717 
2718 void BrowseBox::LoseFocus()
2719 {
2720 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2721 	DBG_TRACE1( "BrowseBox: %p->LoseFocus", this );
2722 
2723 	if ( bHasFocus )
2724 	{
2725 		DBG_TRACE1( "BrowseBox: %p->HideCursor", this );
2726 		DoHideCursor( "LoseFocus" );
2727 
2728 		if ( !bKeepHighlight )
2729 		{
2730 			ToggleSelection();
2731 			bSelectionIsVisible = sal_False;
2732 		}
2733 
2734 		bHasFocus = sal_False;
2735 	}
2736 	Control::LoseFocus();
2737 }
2738 
2739 //-------------------------------------------------------------------
2740 
2741 void BrowseBox::GetFocus()
2742 {
2743 	DBG_CHKTHIS(BrowseBox,BrowseBoxCheckInvariants);
2744 	DBG_TRACE1( "BrowseBox: %p->GetFocus", this );
2745 
2746 	if ( !bHasFocus )
2747 	{
2748 		if ( !bSelectionIsVisible )
2749 		{
2750 			bSelectionIsVisible = sal_True;
2751 			if ( bBootstrapped )
2752 				ToggleSelection();
2753 		}
2754 
2755 		bHasFocus = sal_True;
2756 		DoShowCursor( "GetFocus" );
2757 	}
2758 	Control::GetFocus();
2759 }
2760 
2761 
2762