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_svx.hxx"
30 
31 #include "tablecontroller.hxx"
32 
33 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/table/XMergeableCellRange.hpp>
38 #include <com/sun/star/table/XMergeableCell.hpp>
39 
40 #include <sal/config.h>
41 
42 #include <vcl/svapp.hxx>
43 #include <svl/whiter.hxx>
44 
45 #include <sfx2/request.hxx>
46 
47 #include <editeng/scripttypeitem.hxx>
48 #include <svx/svdotable.hxx>
49 #include <svx/sdr/overlay/overlayobjectcell.hxx>
50 #include <svx/sdr/overlay/overlaymanager.hxx>
51 #include <svx/svxids.hrc>
52 #include <editeng/outlobj.hxx>
53 #include <svx/svdoutl.hxx>
54 #include <svx/svdpagv.hxx>
55 #include <svx/svdetc.hxx>
56 #include <editeng/editobj.hxx>
57 #include "editeng/editstat.hxx"
58 #include "editeng/unolingu.hxx"
59 #include "svx/sdrpagewindow.hxx"
60 #include <svx/selectioncontroller.hxx>
61 #include <svx/svdmodel.hxx>
62 #include "svx/sdrpaintwindow.hxx"
63 #include <svx/svxdlg.hxx>
64 #include <editeng/boxitem.hxx>
65 #include "cell.hxx"
66 #include <editeng/borderline.hxx>
67 #include <editeng/colritem.hxx>
68 #include "editeng/bolnitem.hxx"
69 #include "svx/svdstr.hrc"
70 #include "svx/svdglob.hxx"
71 #include "svx/svdpage.hxx"
72 #include "tableundo.hxx"
73 #include "tablelayouter.hxx"
74 
75 using ::rtl::OUString;
76 using namespace ::sdr::table;
77 using namespace ::com::sun::star;
78 using namespace ::com::sun::star::uno;
79 using namespace ::com::sun::star::table;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::container;
82 using namespace ::com::sun::star::text;
83 using namespace ::com::sun::star::style;
84 
85 namespace sdr { namespace table {
86 
87 // --------------------------------------------------------------------
88 // class SvxTableControllerModifyListener
89 // --------------------------------------------------------------------
90 
91 class SvxTableControllerModifyListener : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XModifyListener >
92 {
93 public:
94 	SvxTableControllerModifyListener( SvxTableController* pController )
95 		: mpController( pController ) {}
96 
97 	// XModifyListener
98     virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
99 
100     // XEventListener
101     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
102 
103 	SvxTableController* mpController;
104 };
105 
106 // --------------------------------------------------------------------
107 // XModifyListener
108 // --------------------------------------------------------------------
109 
110 void SAL_CALL SvxTableControllerModifyListener::modified( const ::com::sun::star::lang::EventObject&  ) throw (::com::sun::star::uno::RuntimeException)
111 {
112 	if( mpController )
113 		mpController->onTableModified();
114 }
115 
116 // --------------------------------------------------------------------
117 // XEventListener
118 // --------------------------------------------------------------------
119 
120 void SAL_CALL SvxTableControllerModifyListener::disposing( const ::com::sun::star::lang::EventObject&  ) throw (::com::sun::star::uno::RuntimeException)
121 {
122 	mpController = 0;
123 }
124 
125 // --------------------------------------------------------------------
126 // class SvxTableController
127 // --------------------------------------------------------------------
128 
129 rtl::Reference< sdr::SelectionController > CreateTableController( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
130 {
131 	return SvxTableController::create( pView, pObj, xRefController );
132 }
133 
134 // --------------------------------------------------------------------
135 
136 rtl::Reference< sdr::SelectionController > SvxTableController::create( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
137 {
138 	if( xRefController.is() )
139 	{
140 		SvxTableController* pController = dynamic_cast< SvxTableController* >( xRefController.get() );
141 		if( pController && (pController->mxTableObj.get() == pObj) && (pController->mpView == pView)  )
142 			return xRefController;
143 	}
144 	return new SvxTableController( pView, pObj );
145 }
146 
147 // --------------------------------------------------------------------
148 
149 SvxTableController::SvxTableController( SdrObjEditView* pView, const SdrObject* pObj )
150 : mbCellSelectionMode(false)
151 , mbLeftButtonDown(false)
152 , mpSelectionOverlay(0)
153 , mpView( dynamic_cast< SdrView* >( pView ) )
154 , mxTableObj( dynamic_cast< SdrTableObj* >( const_cast< SdrObject* >( pObj ) ) )
155 , mpModel( 0 )
156 , mnUpdateEvent( 0 )
157 {
158 	if( pObj )
159 		mpModel = pObj->GetModel();
160 
161 	if( mxTableObj.is() )
162 	{
163 		static_cast< const SdrTableObj* >( pObj )->getActiveCellPos( maCursorFirstPos );
164 		maCursorLastPos = maCursorFirstPos;
165 
166 		Reference< XTable > xTable( static_cast< const SdrTableObj* >( pObj )->getTable() );
167 		if( xTable.is() )
168 		{
169 			mxModifyListener = new SvxTableControllerModifyListener( this );
170 			xTable->addModifyListener( mxModifyListener );
171 
172 			mxTable.set( dynamic_cast< TableModel* >( xTable.get() ) );
173 		}
174 	}
175 }
176 
177 // --------------------------------------------------------------------
178 
179 SvxTableController::~SvxTableController()
180 {
181 	if( mnUpdateEvent )
182 	{
183 		Application::RemoveUserEvent( mnUpdateEvent );
184 	}
185 
186 	if( mxModifyListener.is() && mxTableObj.get() )
187 	{
188 		Reference< XTable > xTable( static_cast< SdrTableObj* >( mxTableObj.get() )->getTable() );
189 		if( xTable.is() )
190 		{
191 			xTable->removeModifyListener( mxModifyListener );
192 			mxModifyListener.clear();
193 		}
194 	}
195 }
196 
197 // --------------------------------------------------------------------
198 
199 const sal_uInt16 ACTION_NONE = 0;
200 const sal_uInt16 ACTION_GOTO_FIRST_CELL = 1;
201 const sal_uInt16 ACTION_GOTO_FIRST_COLUMN = 2;
202 const sal_uInt16 ACTION_GOTO_FIRST_ROW = 3;
203 const sal_uInt16 ACTION_GOTO_LEFT_CELL = 4;
204 const sal_uInt16 ACTION_GOTO_UP_CELL = 5;
205 const sal_uInt16 ACTION_GOTO_RIGHT_CELL = 6;
206 const sal_uInt16 ACTION_GOTO_DOWN_CELL = 7;
207 const sal_uInt16 ACTION_GOTO_LAST_CELL = 8;
208 const sal_uInt16 ACTION_GOTO_LAST_COLUMN = 9;
209 const sal_uInt16 ACTION_GOTO_LAST_ROW = 10;
210 const sal_uInt16 ACTION_EDIT_CELL = 11;
211 const sal_uInt16 ACTION_STOP_TEXT_EDIT = 12;
212 const sal_uInt16 ACTION_REMOVE_SELECTION = 13;
213 const sal_uInt16 ACTION_START_SELECTION = 14;
214 const sal_uInt16 ACTION_HANDLED_BY_VIEW = 15;
215 const sal_uInt16 ACTION_TAB = 18;
216 
217 bool SvxTableController::onKeyInput(const KeyEvent& rKEvt, Window* pWindow )
218 {
219 	if( !checkTableObject() )
220 		return false;
221 
222 	// check if we are read only
223 	if( mpModel && mpModel->IsReadOnly())
224 	{
225 		switch( rKEvt.GetKeyCode().GetCode() )
226 		{
227 		case awt::Key::DOWN:
228 		case awt::Key::UP:
229 		case awt::Key::LEFT:
230 		case awt::Key::RIGHT:
231 		case awt::Key::TAB:
232 		case awt::Key::HOME:
233 		case awt::Key::END:
234 		case awt::Key::NUM2:
235 		case awt::Key::NUM4:
236 		case awt::Key::NUM6:
237 		case awt::Key::NUM8:
238 		case awt::Key::ESCAPE:
239 		case awt::Key::F2:
240 			break;
241 		default:
242 			// tell the view we eat the event, no further processing needed
243 			return true;
244 		}
245 	}
246 
247 	sal_uInt16 nAction = getKeyboardAction( rKEvt, pWindow );
248 
249 	return executeAction( nAction, ( rKEvt.GetKeyCode().IsShift() ) ? sal_True : sal_False, pWindow );
250 }
251 
252 // --------------------------------------------------------------------
253 // ::com::sun::star::awt::XMouseClickHandler:
254 // --------------------------------------------------------------------
255 
256 bool SvxTableController::onMouseButtonDown(const MouseEvent& rMEvt, Window* pWindow )
257 {
258 	if( !pWindow || !checkTableObject() )
259 		return false;
260 
261 	SdrViewEvent aVEvt;
262 	if( !rMEvt.IsRight() && mpView->PickAnything(rMEvt,SDRMOUSEBUTTONDOWN, aVEvt) == SDRHIT_HANDLE )
263 		return false;
264 
265 	TableHitKind eHit = static_cast< SdrTableObj* >(mxTableObj.get())->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), maMouseDownPos.mnCol, maMouseDownPos.mnRow, 0 );
266 
267 	mbLeftButtonDown = (rMEvt.GetClicks() == 1) && rMEvt.IsLeft();
268 
269 	if( eHit == SDRTABLEHIT_CELL )
270 	{
271 		StartSelection( maMouseDownPos );
272 		return true;
273 	}
274 
275 	if( rMEvt.IsRight() && eHit != SDRTABLEHIT_NONE )
276 		return true; // right click will become context menu
277 
278 	// for cell selektion with the mouse remember our first hit
279 	if( mbLeftButtonDown )
280 	{
281 		RemoveSelection();
282 
283 		Point aPnt(rMEvt.GetPosPixel());
284 		if (pWindow!=NULL)
285 			aPnt=pWindow->PixelToLogic(aPnt);
286 
287 		SdrHdl* pHdl = mpView->PickHandle(aPnt);
288 
289 		if( pHdl )
290 		{
291 			mbLeftButtonDown = false;
292 		}
293 		else
294 		{
295 			::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
296 
297 			if( !pWindow || !pTableObj || eHit  == SDRTABLEHIT_NONE)
298 			{
299 				mbLeftButtonDown = false;
300 			}
301 		}
302 	}
303 
304 	return false;
305 }
306 
307 // --------------------------------------------------------------------
308 
309 bool SvxTableController::onMouseButtonUp(const MouseEvent& rMEvt, Window* /*pWin*/)
310 {
311 	if( !checkTableObject() )
312 		return false;
313 
314 	mbLeftButtonDown = false;
315 
316 	if( rMEvt.GetClicks() == 2 )
317 		return true;
318 
319 	return false;
320 }
321 
322 // --------------------------------------------------------------------
323 
324 bool SvxTableController::onMouseMove(const MouseEvent& rMEvt, Window* pWindow )
325 {
326 	if( !checkTableObject() )
327 		return false;
328 
329 	if( rMEvt.IsLeft() )
330 	{
331 		int i = 0;
332 		i++;
333 	}
334 
335 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
336 	CellPos aPos;
337 	if( mbLeftButtonDown && pTableObj && pTableObj->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), aPos.mnCol, aPos.mnRow, 0 ) != SDRTABLEHIT_NONE )
338 	{
339 		if(aPos != maMouseDownPos)
340 		{
341 			if( mbCellSelectionMode )
342 			{
343 				setSelectedCells( maMouseDownPos, aPos );
344 				return true;
345 			}
346 			else
347 			{
348 				StartSelection( maMouseDownPos );
349 			}
350 		}
351 		else if( mbCellSelectionMode )
352 		{
353 			UpdateSelection( aPos );
354 			return true;
355 		}
356 	}
357     return false;
358 }
359 
360 // --------------------------------------------------------------------
361 
362 void SvxTableController::onSelectionHasChanged()
363 {
364 	bool bSelected = false;
365 
366 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
367 	if( pTableObj && pTableObj->IsTextEditActive() )
368 	{
369 		pTableObj->getActiveCellPos( maCursorFirstPos );
370 		maCursorLastPos = maCursorFirstPos;
371 		mbCellSelectionMode = false;
372 	}
373 	else
374 	{
375 		const SdrMarkList& rMarkList= mpView->GetMarkedObjectList();
376 		if( rMarkList.GetMarkCount() == 1 )
377 			bSelected = mxTableObj.get() == rMarkList.GetMark(0)->GetMarkedSdrObj();
378 	}
379 
380 	if( bSelected )
381 	{
382 		updateSelectionOverlay();
383 	}
384 	else
385 	{
386 		destroySelectionOverlay();
387 	}
388 }
389 
390 // --------------------------------------------------------------------
391 
392 void SvxTableController::GetState( SfxItemSet& rSet )
393 {
394 	if( !mxTable.is() || !mxTableObj.is() || !mxTableObj->GetModel() )
395 		return;
396 
397 	SfxItemSet* pSet = 0;
398 
399 	bool bVertDone = false;
400 
401     // Iterate over all requested items in the set.
402 	SfxWhichIter aIter( rSet );
403 	sal_uInt16 nWhich = aIter.FirstWhich();
404 	while (nWhich)
405 	{
406 		switch (nWhich)
407 		{
408 			case SID_TABLE_VERT_BOTTOM:
409 			case SID_TABLE_VERT_CENTER:
410 			case SID_TABLE_VERT_NONE:
411 				{
412 					if( !mxTable.is() || !mxTableObj->GetModel() )
413 					{
414 						rSet.DisableItem(nWhich);
415 					}
416 					else if(!bVertDone)
417 					{
418 						if( !pSet )
419 						{
420 							pSet = new SfxItemSet( mxTableObj->GetModel()->GetItemPool() );
421 							MergeAttrFromSelectedCells(*pSet, sal_False);
422 						}
423 
424 						SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_BLOCK;
425 
426 						if( pSet->GetItemState( SDRATTR_TEXT_VERTADJUST ) != SFX_ITEM_DONTCARE )
427 							eAdj = ((SdrTextVertAdjustItem&)(pSet->Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
428 
429 						rSet.Put(SfxBoolItem(SID_TABLE_VERT_BOTTOM, eAdj == SDRTEXTVERTADJUST_BOTTOM));
430 						rSet.Put(SfxBoolItem(SID_TABLE_VERT_CENTER, eAdj == SDRTEXTVERTADJUST_CENTER));
431 						rSet.Put(SfxBoolItem(SID_TABLE_VERT_NONE, eAdj == SDRTEXTVERTADJUST_TOP));
432 						bVertDone = true;
433 					}
434 					break;
435 				}
436 			case SID_TABLE_DELETE_ROW:
437 				if( !mxTable.is() || !hasSelectedCells() || (mxTable->getRowCount() <= 1) )
438 					rSet.DisableItem(SID_TABLE_DELETE_ROW);
439 				break;
440 			case SID_TABLE_DELETE_COL:
441 				if( !mxTable.is() || !hasSelectedCells() || (mxTable->getColumnCount() <= 1) )
442 					rSet.DisableItem(SID_TABLE_DELETE_COL);
443 				break;
444 			case SID_TABLE_MERGE_CELLS:
445 				if( !mxTable.is() || !hasSelectedCells() )
446 					rSet.DisableItem(SID_TABLE_MERGE_CELLS);
447 				break;
448 			case SID_TABLE_SPLIT_CELLS:
449 				if( !hasSelectedCells() || !mxTable.is() )
450 					rSet.DisableItem(SID_TABLE_SPLIT_CELLS);
451 				break;
452 
453 			case SID_OPTIMIZE_TABLE:
454 			case SID_TABLE_DISTRIBUTE_COLUMNS:
455 			case SID_TABLE_DISTRIBUTE_ROWS:
456 			{
457 				bool bDistributeColumns = false;
458 				bool bDistributeRows = false;
459 				if( mxTable.is() )
460 				{
461 					CellPos aStart, aEnd;
462 					getSelectedCells( aStart, aEnd );
463 
464 					bDistributeColumns = aStart.mnCol != aEnd.mnCol;
465 					bDistributeRows = aStart.mnRow != aEnd.mnRow;
466 				}
467 				if( !bDistributeColumns && !bDistributeRows )
468 					rSet.DisableItem(SID_OPTIMIZE_TABLE);
469 				if( !bDistributeColumns )
470 					rSet.DisableItem(SID_TABLE_DISTRIBUTE_COLUMNS);
471 				if( !bDistributeRows )
472 					rSet.DisableItem(SID_TABLE_DISTRIBUTE_ROWS);
473 				break;
474 			}
475 
476 			case SID_AUTOFORMAT:
477 			case SID_TABLE_SORT_DIALOG:
478 			case SID_TABLE_AUTOSUM:
479 //				if( !mxTable.is() )
480 //					rSet.DisableItem( nWhich );
481 				break;
482 			default:
483 				break;
484         }
485 		nWhich = aIter.NextWhich();
486 	}
487 	if( pSet )
488 		delete pSet;
489 }
490 
491 // --------------------------------------------------------------------
492 
493 void SvxTableController::onInsert( sal_uInt16 nSId, const SfxItemSet* pArgs )
494 {
495 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
496 	if( !pTableObj )
497 		return;
498 
499 	if( mxTable.is() ) try
500 	{
501 		//
502 		bool bInsertAfter = true;
503 		sal_uInt16 nCount = 0;
504     	if( pArgs )
505     	{
506     	    const SfxPoolItem* pItem = 0;
507     	    pArgs->GetItemState(nSId, sal_False, &pItem);
508 			if (pItem)
509 			{
510 				nCount = ((const SfxInt16Item* )pItem)->GetValue();
511 				if(SFX_ITEM_SET == pArgs->GetItemState(SID_TABLE_PARAM_INSERT_AFTER, sal_True, &pItem))
512 					bInsertAfter = ((const SfxBoolItem* )pItem)->GetValue();
513 			}
514     	}
515 
516 		CellPos aStart, aEnd;
517 		if( hasSelectedCells() )
518 		{
519 			getSelectedCells( aStart, aEnd );
520 		}
521 		else
522 		{
523 		    if( bInsertAfter )
524 		    {
525 			    aStart.mnCol = mxTable->getColumnCount() - 1;
526 			    aStart.mnRow = mxTable->getRowCount() - 1;
527 			    aEnd = aStart;
528 		    }
529 		}
530 
531 		if( pTableObj->IsTextEditActive() )
532 			mpView->SdrEndTextEdit(sal_True);
533 
534 		RemoveSelection();
535 
536 		const OUString sSize( RTL_CONSTASCII_USTRINGPARAM( "Size" ) );
537 
538 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
539 
540 		switch( nSId )
541 		{
542 		case SID_TABLE_INSERT_COL:
543 		{
544 			TableModelNotifyGuard aGuard( mxTable.get() );
545 
546 			if( bUndo )
547 			{
548 				mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
549 				mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
550 			}
551 
552 			Reference< XTableColumns > xCols( mxTable->getColumns() );
553 			const sal_Int32 nNewColumns = (nCount == 0) ? (aEnd.mnCol - aStart.mnCol + 1) : nCount;
554 			const sal_Int32 nNewStartColumn = aEnd.mnCol + (bInsertAfter ? 1 : 0);
555 			xCols->insertByIndex( nNewStartColumn, nNewColumns );
556 
557 			for( sal_Int32 nOffset = 0; nOffset < nNewColumns; nOffset++ )
558 			{
559 				Reference< XPropertySet >( xCols->getByIndex( aEnd.mnCol + nOffset + 1 ), UNO_QUERY_THROW )->
560 					setPropertyValue( sSize,
561 						Reference< XPropertySet >( xCols->getByIndex( aStart.mnCol + nOffset ), UNO_QUERY_THROW )->
562 							getPropertyValue( sSize ) );
563 			}
564 
565 			if( bUndo )
566 				mpModel->EndUndo();
567 
568 			aStart.mnCol = nNewStartColumn;
569 			aStart.mnRow = 0;
570 			aEnd.mnCol = aStart.mnCol + nNewColumns - 1;
571 			aEnd.mnRow = mxTable->getRowCount() - 1;
572 			break;
573 		}
574 
575 		case SID_TABLE_INSERT_ROW:
576 		{
577 			TableModelNotifyGuard aGuard( mxTable.get() );
578 
579 			if( bUndo )
580 			{
581 				mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW ) );
582 				mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
583 			}
584 
585 			Reference< XTableRows > xRows( mxTable->getRows() );
586 			const sal_Int32 nNewRows = (nCount == 0) ? (aEnd.mnRow - aStart.mnRow + 1) : nCount;
587 			const sal_Int32 nNewRowStart = aEnd.mnRow + (bInsertAfter ? 1 : 0);
588 			xRows->insertByIndex( nNewRowStart, nNewRows );
589 
590 			for( sal_Int32 nOffset = 0; nOffset < nNewRows; nOffset++ )
591 			{
592 				Reference< XPropertySet >( xRows->getByIndex( aEnd.mnRow + nOffset + 1 ), UNO_QUERY_THROW )->
593 					setPropertyValue( sSize,
594 						Reference< XPropertySet >( xRows->getByIndex( aStart.mnRow + nOffset ), UNO_QUERY_THROW )->
595 							getPropertyValue( sSize ) );
596 			}
597 
598 			if( bUndo )
599 				mpModel->EndUndo();
600 
601 			aStart.mnCol = 0;
602 			aStart.mnRow = nNewRowStart;
603 			aEnd.mnCol = mxTable->getColumnCount() - 1;
604 			aEnd.mnRow = aStart.mnRow + nNewRows - 1;
605 			break;
606 		}
607 		}
608 
609 		StartSelection( aStart );
610 		UpdateSelection( aEnd );
611 	}
612 	catch( Exception& e )
613 	{
614 		(void)e;
615 		DBG_ERROR("svx::SvxTableController::onInsert(), exception caught!");
616 	}
617 }
618 
619 // --------------------------------------------------------------------
620 
621 void SvxTableController::onDelete( sal_uInt16 nSId )
622 {
623 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
624 	if( !pTableObj )
625 		return;
626 
627 	if( mxTable.is() && hasSelectedCells() )
628 	{
629 		CellPos aStart, aEnd;
630 		getSelectedCells( aStart, aEnd );
631 
632 		if( pTableObj->IsTextEditActive() )
633 			mpView->SdrEndTextEdit(sal_True);
634 
635 		RemoveSelection();
636 
637 		bool bDeleteTable = false;
638 		switch( nSId )
639 		{
640 		case SID_TABLE_DELETE_COL:
641 		{
642 			const sal_Int32 nRemovedColumns = aEnd.mnCol - aStart.mnCol + 1;
643 			if( nRemovedColumns == mxTable->getColumnCount() )
644 			{
645 				bDeleteTable = true;
646 			}
647 			else
648 			{
649 				Reference< XTableColumns > xCols( mxTable->getColumns() );
650 				xCols->removeByIndex( aStart.mnCol, nRemovedColumns );
651 			}
652 			break;
653 		}
654 
655 		case SID_TABLE_DELETE_ROW:
656 		{
657 			const sal_Int32 nRemovedRows = aEnd.mnRow - aStart.mnRow + 1;
658 			if( nRemovedRows == mxTable->getRowCount() )
659 			{
660 				bDeleteTable = true;
661 			}
662 			else
663 			{
664 				Reference< XTableRows > xRows( mxTable->getRows() );
665 				xRows->removeByIndex( aStart.mnRow, nRemovedRows );
666 			}
667 			break;
668 		}
669 		}
670 
671 		if( bDeleteTable )
672 			mpView->DeleteMarkedObj();
673 		else
674 			UpdateTableShape();
675 	}
676 }
677 
678 // --------------------------------------------------------------------
679 
680 void SvxTableController::onSelect( sal_uInt16 nSId )
681 {
682 	if( mxTable.is() )
683 	{
684 		const sal_Int32 nRowCount = mxTable->getRowCount();
685 		const sal_Int32 nColCount = mxTable->getColumnCount();
686 		if( nRowCount && nColCount )
687 		{
688 			CellPos aStart, aEnd;
689 			getSelectedCells( aStart, aEnd );
690 
691 			switch( nSId )
692 			{
693 			case SID_TABLE_SELECT_ALL:
694 				aEnd.mnCol = 0; aEnd.mnRow = 0;
695 				aStart.mnCol = nColCount - 1; aStart.mnRow = nRowCount - 1;
696 				break;
697 			case SID_TABLE_SELECT_COL:
698 				aEnd.mnRow = nRowCount - 1;
699 				aStart.mnRow = 0;
700 				break;
701 			case SID_TABLE_SELECT_ROW:
702 				aEnd.mnCol = nColCount - 1;
703 				aStart.mnCol = 0;
704 				break;
705 			}
706 
707 			StartSelection( aEnd );
708 			gotoCell( aStart, true, 0 );
709 		}
710 	}
711 }
712 
713 // --------------------------------------------------------------------
714 void SvxTableController::onFormatTable( SfxRequest& rReq )
715 {
716 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
717 	if( !pTableObj )
718 		return;
719 
720 	const SfxItemSet* pArgs = rReq.GetArgs();
721 
722 	if( !pArgs && pTableObj->GetModel() )
723 	{
724 		SfxItemSet aNewAttr( pTableObj->GetModel()->GetItemPool() );
725 		MergeAttrFromSelectedCells(aNewAttr, sal_False);
726 
727 		// merge drawing layer text distance items into SvxBoxItem used by the dialog
728 		SvxBoxItem aBoxItem( static_cast< const SvxBoxItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER ) ) );
729 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLeftDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LEFTDIST))).GetValue()), BOX_LINE_LEFT );
730 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextRightDistItem&)(aNewAttr.Get(SDRATTR_TEXT_RIGHTDIST))).GetValue()), BOX_LINE_RIGHT );
731 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextUpperDistItem&)(aNewAttr.Get(SDRATTR_TEXT_UPPERDIST))).GetValue()), BOX_LINE_TOP );
732 		aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLowerDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LOWERDIST))).GetValue()), BOX_LINE_BOTTOM );
733 		aNewAttr.Put( aBoxItem );
734 
735 		SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
736 		std::auto_ptr< SfxAbstractTabDialog > pDlg( pFact ? pFact->CreateSvxFormatCellsDialog( NULL, &aNewAttr, pTableObj->GetModel(), pTableObj) : 0 );
737 		if( pDlg.get() && pDlg->Execute() )
738 		{
739 			SfxItemSet aNewSet( *(pDlg->GetOutputItemSet ()) );
740 
741 			SvxBoxItem aNewBoxItem( static_cast< const SvxBoxItem& >( aNewSet.Get( SDRATTR_TABLE_BORDER ) ) );
742 
743 			if( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) != aBoxItem.GetDistance( BOX_LINE_LEFT ) )
744 				aNewSet.Put(SdrTextLeftDistItem( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) ) );
745 
746 			if( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) != aBoxItem.GetDistance( BOX_LINE_RIGHT ) )
747 				aNewSet.Put(SdrTextRightDistItem( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) ) );
748 
749 			if( aNewBoxItem.GetDistance( BOX_LINE_TOP ) != aBoxItem.GetDistance( BOX_LINE_TOP ) )
750 				aNewSet.Put(SdrTextUpperDistItem( aNewBoxItem.GetDistance( BOX_LINE_TOP ) ) );
751 
752 			if( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) != aBoxItem.GetDistance( BOX_LINE_BOTTOM ) )
753 				aNewSet.Put(SdrTextLowerDistItem( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) ) );
754 
755 			SetAttrToSelectedCells(aNewSet, sal_False);
756 		}
757 		UpdateTableShape();
758 	}
759 }
760 
761 // --------------------------------------------------------------------
762 
763 void SvxTableController::Execute( SfxRequest& rReq )
764 {
765 	const sal_uInt16 nSId = rReq.GetSlot();
766 	switch( nSId )
767 	{
768 	case SID_TABLE_INSERT_ROW:
769 	case SID_TABLE_INSERT_COL:
770 		onInsert( nSId, rReq.GetArgs() );
771 		break;
772 	case SID_TABLE_DELETE_ROW:
773 	case SID_TABLE_DELETE_COL:
774 		onDelete( nSId );
775 		break;
776 	case SID_TABLE_SELECT_ALL:
777 	case SID_TABLE_SELECT_COL:
778 	case SID_TABLE_SELECT_ROW:
779 		onSelect( nSId );
780 		break;
781 	case SID_FORMAT_TABLE_DLG:
782 		onFormatTable( rReq );
783 		break;
784 
785 	case SID_FRAME_LINESTYLE:
786 	case SID_FRAME_LINECOLOR:
787 	case SID_ATTR_BORDER:
788 		{
789 			const SfxItemSet* pArgs = rReq.GetArgs();
790 			if( pArgs )
791 				ApplyBorderAttr( *pArgs );
792 		}
793 		break;
794 
795 	case SID_ATTR_FILL_STYLE:
796 		{
797 			const SfxItemSet* pArgs = rReq.GetArgs();
798 			if( pArgs )
799 				SetAttributes( *pArgs, false );
800 		}
801 		break;
802 
803 	case SID_TABLE_MERGE_CELLS:
804 		MergeMarkedCells();
805 		break;
806 
807 	case SID_TABLE_SPLIT_CELLS:
808 		SplitMarkedCells();
809 		break;
810 
811 	case SID_TABLE_DISTRIBUTE_COLUMNS:
812 		DistributeColumns();
813 		break;
814 
815 	case SID_TABLE_DISTRIBUTE_ROWS:
816 		DistributeRows();
817 		break;
818 
819 	case SID_TABLE_VERT_BOTTOM:
820 	case SID_TABLE_VERT_CENTER:
821 	case SID_TABLE_VERT_NONE:
822 		SetVertical( nSId );
823 		break;
824 
825 	case SID_AUTOFORMAT:
826 	case SID_TABLE_SORT_DIALOG:
827 	case SID_TABLE_AUTOSUM:
828 	default:
829 		break;
830 
831 	case SID_TABLE_STYLE:
832 		SetTableStyle( rReq.GetArgs() );
833 		break;
834 
835 	case SID_TABLE_STYLE_SETTINGS:
836 		SetTableStyleSettings( rReq.GetArgs() );
837 		break;
838 	}
839 }
840 
841 void SvxTableController::SetTableStyle( const SfxItemSet* pArgs )
842 {
843 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
844 	SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
845 
846 	if( !pTableObj || !pModel || !pArgs || (SFX_ITEM_SET != pArgs->GetItemState(SID_TABLE_STYLE, sal_False)) )
847 		return;
848 
849 	const SfxStringItem* pArg = dynamic_cast< const SfxStringItem* >( &pArgs->Get( SID_TABLE_STYLE ) );
850 	if( pArg && mxTable.is() ) try
851 	{
852 		Reference< XStyleFamiliesSupplier > xSFS( pModel->getUnoModel(), UNO_QUERY_THROW );
853 		Reference< XNameAccess > xFamilyNameAccess( xSFS->getStyleFamilies(), UNO_QUERY_THROW );
854 		const OUString sFamilyName( RTL_CONSTASCII_USTRINGPARAM( "table" ) );
855 		Reference< XNameAccess > xTableFamilyAccess( xFamilyNameAccess->getByName( sFamilyName ), UNO_QUERY_THROW );
856 
857 		if( xTableFamilyAccess->hasByName( pArg->GetValue() ) )
858 		{
859 			// found table style with the same name
860 			Reference< XIndexAccess > xNewTableStyle( xTableFamilyAccess->getByName( pArg->GetValue() ), UNO_QUERY_THROW );
861 
862 			const bool bUndo = pModel->IsUndoEnabled();
863 
864 			if( bUndo )
865 			{
866 				pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE) );
867 				pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
868 			}
869 
870 			pTableObj->setTableStyle( xNewTableStyle );
871 
872 			const sal_Int32 nRowCount = mxTable->getRowCount();
873 			const sal_Int32 nColCount = mxTable->getColumnCount();
874 			for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
875 			{
876 				for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ ) try
877 				{
878 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
879 					if( xCell.is() )
880 					{
881                         SfxItemSet aSet( xCell->GetItemSet() );
882                         bool bChanges = false;
883 	                    const SfxItemSet& rStyleAttribs = xCell->GetStyleSheet()->GetItemSet();
884 
885 	                    for ( sal_uInt16 nWhich = SDRATTR_START; nWhich <= SDRATTR_TABLE_LAST; nWhich++ )
886 	                    {
887 		                    if( (rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON) && (aSet.GetItemState( nWhich ) == SFX_ITEM_ON) )
888 		                    {
889 			                    aSet.ClearItem( nWhich );
890 			                    bChanges = true;
891 			                }
892 	                    }
893 
894 	                    if( bChanges )
895 	                    {
896 						    if( bUndo )
897 							    xCell->AddUndo();
898 
899 							xCell->SetMergedItemSetAndBroadcast( aSet, sal_True );
900 	                    }
901                     }
902 				}
903 				catch( Exception& e )
904 				{
905 					(void)e;
906 					DBG_ERROR( "svx::SvxTableController::SetTableStyle(), exception caught!" );
907 				}
908 			}
909 
910 			if( bUndo )
911 				pModel->EndUndo();
912 		}
913 	}
914 	catch( Exception& e )
915 	{
916 		(void)e;
917 		DBG_ERROR( "svx::SvxTableController::SetTableStyle(), exception caught!" );
918 	}
919 }
920 
921 void SvxTableController::SetTableStyleSettings( const SfxItemSet* pArgs )
922 {
923 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
924 	SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
925 
926 	if( !pTableObj || !pModel )
927 		return;
928 
929 	TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
930 
931 	const SfxPoolItem *pPoolItem=NULL;
932 
933 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTROWSTYLE, sal_False,&pPoolItem)) )
934 		aSettings.mbUseFirstRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
935 
936 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTROWSTYLE, sal_False,&pPoolItem)) )
937 		aSettings.mbUseLastRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
938 
939 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGROWSTYLE, sal_False,&pPoolItem)) )
940 		aSettings.mbUseRowBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
941 
942 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTCOLUMNSTYLE, sal_False,&pPoolItem)) )
943 		aSettings.mbUseFirstColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
944 
945 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTCOLUMNSTYLE, sal_False,&pPoolItem)) )
946 		aSettings.mbUseLastColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
947 
948 	if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGCOLUMNSTYLE, sal_False,&pPoolItem)) )
949 		aSettings.mbUseColumnBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
950 
951 	if( aSettings == pTableObj->getTableStyleSettings() )
952 		return;
953 
954 	const bool bUndo = pModel->IsUndoEnabled();
955 
956 	if( bUndo )
957 	{
958 		pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE_SETTINGS) );
959 		pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
960 	}
961 
962 	pTableObj->setTableStyleSettings( aSettings );
963 
964 	if( bUndo )
965 		pModel->EndUndo();
966 }
967 
968 void SvxTableController::SetVertical( sal_uInt16 nSId )
969 {
970 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
971 	if( mxTable.is() && pTableObj )
972 	{
973 		TableModelNotifyGuard aGuard( mxTable.get() );
974 
975 		CellPos aStart, aEnd;
976 		getSelectedCells( aStart, aEnd );
977 
978 		SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_TOP;
979 
980 		switch( nSId )
981 		{
982 			case SID_TABLE_VERT_BOTTOM:
983 				eAdj = SDRTEXTVERTADJUST_BOTTOM;
984 				break;
985 			case SID_TABLE_VERT_CENTER:
986 				eAdj = SDRTEXTVERTADJUST_CENTER;
987 				break;
988 			//case SID_TABLE_VERT_NONE:
989 			default:
990 				break;
991 		}
992 
993 		SdrTextVertAdjustItem aItem( eAdj );
994 
995 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
996 		{
997 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
998 			{
999 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1000 				if( xCell.is() )
1001 					xCell->SetMergedItem(aItem);
1002 			}
1003 		}
1004 
1005 		UpdateTableShape();
1006 	}
1007 }
1008 
1009 void SvxTableController::MergeMarkedCells()
1010 {
1011 	CellPos aStart, aEnd;
1012 	getSelectedCells( aStart, aEnd );
1013 	SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1014 	if( pTableObj )
1015 	{
1016 	    if( pTableObj->IsTextEditActive() )
1017 		    mpView->SdrEndTextEdit(sal_True);
1018 
1019         TableModelNotifyGuard aGuard( mxTable.get() );
1020 		MergeRange( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow );
1021 	}
1022 }
1023 
1024 void SvxTableController::SplitMarkedCells()
1025 {
1026 	if( mxTable.is() )
1027 	{
1028 		CellPos aStart, aEnd;
1029 		getSelectedCells( aStart, aEnd );
1030 
1031 		SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1032 		std::auto_ptr< SvxAbstractSplittTableDialog > xDlg( pFact ? pFact->CreateSvxSplittTableDialog( NULL, false, 99, 99 ) : 0 );
1033 		if( xDlg.get() && xDlg->Execute() )
1034 		{
1035 			const sal_Int32 nCount = xDlg->GetCount() - 1;
1036 			if( nCount < 1 )
1037 				return;
1038 
1039 			getSelectedCells( aStart, aEnd );
1040 
1041 			Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) ), UNO_QUERY_THROW );
1042 
1043 			const sal_Int32 nRowCount = mxTable->getRowCount();
1044 			const sal_Int32 nColCount = mxTable->getColumnCount();
1045 
1046 
1047 			SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1048 			if( pTableObj )
1049 			{
1050         	    if( pTableObj->IsTextEditActive() )
1051 		            mpView->SdrEndTextEdit(sal_True);
1052 
1053                 TableModelNotifyGuard aGuard( mxTable.get() );
1054 
1055 				const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1056 				if( bUndo )
1057 				{
1058 					mpModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
1059 					mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1060 				}
1061 
1062 				if( xDlg->IsHorizontal() )
1063 				{
1064 					xRange->split( 0, nCount );
1065 				}
1066 				else
1067 				{
1068 					xRange->split( nCount, 0 );
1069 				}
1070 
1071 				if( bUndo )
1072 					mpModel->EndUndo();
1073 			}
1074 			aEnd.mnRow += mxTable->getRowCount() - nRowCount;
1075 			aEnd.mnCol += mxTable->getColumnCount() - nColCount;
1076 
1077 			setSelectedCells( aStart, aEnd );
1078 		}
1079 	}
1080 }
1081 
1082 void SvxTableController::DistributeColumns()
1083 {
1084 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1085 	if( pTableObj )
1086 	{
1087 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1088 		if( bUndo )
1089 		{
1090 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_COLUMNS) );
1091 			mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1092 		}
1093 
1094 		CellPos aStart, aEnd;
1095 		getSelectedCells( aStart, aEnd );
1096 		pTableObj->DistributeColumns( aStart.mnCol, aEnd.mnCol );
1097 
1098 		if( bUndo )
1099 			mpModel->EndUndo();
1100 	}
1101 }
1102 
1103 void SvxTableController::DistributeRows()
1104 {
1105 	SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1106 	if( pTableObj )
1107 	{
1108 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1109 		if( bUndo )
1110 		{
1111 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_ROWS) );
1112 			mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1113 		}
1114 
1115 		CellPos aStart, aEnd;
1116 		getSelectedCells( aStart, aEnd );
1117 		pTableObj->DistributeRows( aStart.mnRow, aEnd.mnRow );
1118 
1119 		if( bUndo )
1120 			mpModel->EndUndo();
1121 	}
1122 }
1123 
1124 bool SvxTableController::DeleteMarked()
1125 {
1126 	if( mbCellSelectionMode )
1127 	{
1128 		if( mxTable.is() )
1129 		{
1130 			CellPos aStart, aEnd;
1131 			getSelectedCells( aStart, aEnd );
1132 			for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1133 			{
1134 				for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1135 				{
1136 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1137 					if( xCell.is() )
1138 						xCell->SetOutlinerParaObject( 0 );
1139 				}
1140 			}
1141 
1142 			UpdateTableShape();
1143 			return true;
1144 		}
1145 	}
1146 
1147 	return false;
1148 }
1149 
1150 bool SvxTableController::GetStyleSheet( SfxStyleSheet*& rpStyleSheet ) const
1151 {
1152 	if( hasSelectedCells() )
1153 	{
1154 		rpStyleSheet = 0;
1155 
1156 		if( mxTable.is() )
1157 		{
1158 			SfxStyleSheet* pRet=0;
1159 			bool b1st=true;
1160 
1161 			CellPos aStart, aEnd;
1162 			const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
1163 
1164 			for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1165 			{
1166 				for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1167 				{
1168 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1169 					if( xCell.is() )
1170 					{
1171 						SfxStyleSheet* pSS=xCell->GetStyleSheet();
1172 						if(b1st)
1173 						{
1174 							pRet=pSS;
1175 						}
1176 						else if(pRet != pSS)
1177 						{
1178 							return true;
1179 						}
1180 						b1st=false;
1181 					}
1182 				}
1183 			}
1184 			rpStyleSheet = pRet;
1185 			return true;
1186 		}
1187 	}
1188 	return false;
1189 }
1190 
1191 bool SvxTableController::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr )
1192 {
1193 	if( hasSelectedCells() && (!pStyleSheet || pStyleSheet->GetFamily() == SFX_STYLE_FAMILY_FRAME) )
1194 	{
1195 		if( mxTable.is() )
1196 		{
1197 			CellPos aStart, aEnd;
1198 			getSelectedCells( aStart, aEnd );
1199 
1200 			for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1201 			{
1202 				for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1203 				{
1204 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1205 					if( xCell.is() )
1206 						xCell->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1207 				}
1208 			}
1209 
1210 			UpdateTableShape();
1211 			return true;
1212 		}
1213 	}
1214 	return false;
1215 }
1216 
1217 // --------------------------------------------------------------------
1218 // internals
1219 // --------------------------------------------------------------------
1220 
1221 bool SvxTableController::checkTableObject()
1222 {
1223 	return mxTableObj.is();
1224 }
1225 
1226 // --------------------------------------------------------------------
1227 
1228 sal_uInt16 SvxTableController::getKeyboardAction( const KeyEvent& rKEvt, Window* /*pWindow*/ )
1229 {
1230 	const bool bMod1 = rKEvt.GetKeyCode().IsMod1(); // ctrl
1231 	const bool bMod2 = rKEvt.GetKeyCode().IsMod2() != 0; // Alt
1232 
1233 	const bool bTextEdit = mpView->IsTextEdit();
1234 
1235 	sal_uInt16 nAction = ACTION_HANDLED_BY_VIEW;
1236 
1237 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1238 	if( !pTableObj )
1239 		return nAction;
1240 
1241 	// handle special keys
1242 	const sal_Int16 nCode = rKEvt.GetKeyCode().GetCode();
1243 	switch( nCode )
1244 	{
1245 	case awt::Key::ESCAPE:			// handle escape
1246 	{
1247 		if( bTextEdit )
1248 		{
1249 			// escape during text edit ends text edit
1250 			nAction = ACTION_STOP_TEXT_EDIT;
1251 		}
1252 		if( mbCellSelectionMode )
1253 		{
1254 			// escape with selected cells removes selection
1255 			nAction = ACTION_REMOVE_SELECTION;
1256 		}
1257 		break;
1258 	}
1259 	case awt::Key::RETURN:		// handle return
1260 	{
1261 		if( !bMod1 && !bMod2 && !bTextEdit )
1262 		{
1263 			// when not already editing, return starts text edit
1264 			setSelectionStart( pTableObj->getFirstCell() );
1265 			nAction = ACTION_EDIT_CELL;
1266 		}
1267 		break;
1268 	}
1269 	case awt::Key::F2:			// f2 toggles text edit
1270 	{
1271 		if( bMod1 || bMod2 )	// f2 with modifiers is handled by the view
1272 		{
1273 		}
1274 		else if( bTextEdit )
1275 		{
1276 			// f2 during text edit stops text edit
1277 			nAction = ACTION_STOP_TEXT_EDIT;
1278 		}
1279 		else if( mbCellSelectionMode )
1280 		{
1281 			// f2 with selected cells removes selection
1282 			nAction = ACTION_REMOVE_SELECTION;
1283 		}
1284 		else
1285 		{
1286 			// f2 with no selection and no text edit starts text edit
1287 			setSelectionStart( pTableObj->getFirstCell() );
1288 			nAction = ACTION_EDIT_CELL;
1289 		}
1290 		break;
1291 	}
1292 	case awt::Key::HOME:
1293 	case awt::Key::NUM7:
1294 	{
1295 		if( (bMod1 ||  bMod2) && (bTextEdit || mbCellSelectionMode) )
1296 		{
1297 			if( bMod1 && !bMod2 )
1298 			{
1299 				// strg + home jumps to first cell
1300 				nAction = ACTION_GOTO_FIRST_CELL;
1301 			}
1302 			else if( !bMod1 && bMod2 )
1303 			{
1304 				// alt + home jumps to first column
1305 				nAction = ACTION_GOTO_FIRST_COLUMN;
1306 			}
1307 		}
1308 		break;
1309 	}
1310 	case awt::Key::END:
1311 	case awt::Key::NUM1:
1312 	{
1313 		if( (bMod1 ||  bMod2) && (bTextEdit || mbCellSelectionMode) )
1314 		{
1315 			if( bMod1 && !bMod2 )
1316 			{
1317 				// strg + end jumps to last cell
1318 				nAction = ACTION_GOTO_LAST_CELL;
1319 			}
1320 			else if( !bMod1 && bMod2 )
1321 			{
1322 				// alt + home jumps to last column
1323 				nAction = ACTION_GOTO_LAST_COLUMN;
1324 			}
1325 		}
1326 		break;
1327 	}
1328 
1329 	case awt::Key::TAB:
1330 	{
1331 		if( bTextEdit || mbCellSelectionMode )
1332 			nAction = ACTION_TAB;
1333 		break;
1334 	}
1335 
1336 	case awt::Key::UP:
1337 	case awt::Key::NUM8:
1338 	case awt::Key::DOWN:
1339 	case awt::Key::NUM2:
1340 	case awt::Key::LEFT:
1341 	case awt::Key::NUM4:
1342 	case awt::Key::RIGHT:
1343 	case awt::Key::NUM6:
1344 	{
1345 		bool bTextMove = false;
1346 
1347 		if( !bMod1 && bMod2 )
1348 		{
1349 			if( (nCode == awt::Key::UP) || (nCode == awt::Key::NUM8) )
1350 			{
1351 				nAction = ACTION_GOTO_LEFT_CELL;
1352 			}
1353 			else if( (nCode == awt::Key::DOWN) || (nCode == awt::Key::NUM2) )
1354 			{
1355 				nAction = ACTION_GOTO_RIGHT_CELL;
1356 			}
1357 			break;
1358 		}
1359 
1360 		if( !bTextMove )
1361 		{
1362 			OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1363 			if( pOLV )
1364 			{
1365 				RemoveSelection();
1366 				// during text edit, check if we navigate out of the cell
1367 				ESelection aOldSelection = pOLV->GetSelection();
1368 				pOLV->PostKeyEvent(rKEvt);
1369 				bTextMove = pOLV && ( aOldSelection.IsEqual(pOLV->GetSelection()) );
1370 				if( !bTextMove )
1371 				{
1372 					nAction = ACTION_NONE;
1373 				}
1374 			}
1375 		}
1376 
1377 		if( mbCellSelectionMode || bTextMove )
1378 		{
1379 			// no text edit, navigate in cells if selection active
1380 			switch( nCode )
1381 			{
1382 			case awt::Key::LEFT:
1383 			case awt::Key::NUM4:
1384 				nAction = ACTION_GOTO_LEFT_CELL;
1385 				break;
1386 			case awt::Key::RIGHT:
1387 			case awt::Key::NUM6:
1388 				nAction = ACTION_GOTO_RIGHT_CELL;
1389 				break;
1390 			case awt::Key::DOWN:
1391 			case awt::Key::NUM2:
1392 				nAction = ACTION_GOTO_DOWN_CELL;
1393 				break;
1394 			case awt::Key::UP:
1395 			case awt::Key::NUM8:
1396 				nAction = ACTION_GOTO_UP_CELL;
1397 				break;
1398 			}
1399 		}
1400 		break;
1401 	}
1402 	case awt::Key::PAGEUP:
1403 		if( bMod2 )
1404 			nAction = ACTION_GOTO_FIRST_ROW;
1405 		break;
1406 
1407 	case awt::Key::PAGEDOWN:
1408 		if( bMod2 )
1409 			nAction = ACTION_GOTO_LAST_ROW;
1410 		break;
1411 	}
1412 	return nAction;
1413 }
1414 
1415 bool SvxTableController::executeAction( sal_uInt16 nAction, bool bSelect, Window* pWindow )
1416 {
1417 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1418 	if( !pTableObj )
1419 		return false;
1420 
1421 	switch( nAction )
1422 	{
1423 	case ACTION_GOTO_FIRST_CELL:
1424 	{
1425 		gotoCell( pTableObj->getFirstCell(), bSelect, pWindow, nAction );
1426 		break;
1427 	}
1428 
1429 	case ACTION_GOTO_LEFT_CELL:
1430 	{
1431 		gotoCell( pTableObj->getLeftCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction );
1432 		break;
1433 	}
1434 
1435 	case ACTION_GOTO_RIGHT_CELL:
1436 	{
1437 		gotoCell( pTableObj->getRightCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction);
1438 		break;
1439 	}
1440 
1441 	case ACTION_GOTO_LAST_CELL:
1442 	{
1443 		gotoCell( pTableObj->getLastCell(), bSelect, pWindow, nAction );
1444 		break;
1445 	}
1446 
1447 	case ACTION_GOTO_FIRST_COLUMN:
1448 	{
1449 		CellPos aPos( pTableObj->getFirstCell().mnCol, getSelectionEnd().mnRow );
1450 		gotoCell( aPos, bSelect, pWindow, nAction );
1451 		break;
1452 	}
1453 
1454 	case ACTION_GOTO_LAST_COLUMN:
1455 	{
1456 		CellPos aPos( pTableObj->getLastCell().mnCol, getSelectionEnd().mnRow );
1457 		gotoCell( aPos, bSelect, pWindow, nAction );
1458 		break;
1459 	}
1460 
1461 	case ACTION_GOTO_FIRST_ROW:
1462 	{
1463 		CellPos aPos( getSelectionEnd().mnCol, pTableObj->getFirstCell().mnRow );
1464 		gotoCell( aPos, bSelect, pWindow, nAction );
1465 		break;
1466 	}
1467 
1468 	case ACTION_GOTO_UP_CELL:
1469 	{
1470 		gotoCell( pTableObj->getUpCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1471 		break;
1472 	}
1473 
1474 	case ACTION_GOTO_DOWN_CELL:
1475 	{
1476 		gotoCell( pTableObj->getDownCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1477 		break;
1478 	}
1479 
1480 	case ACTION_GOTO_LAST_ROW:
1481 	{
1482 		CellPos aPos( getSelectionEnd().mnCol, pTableObj->getLastCell().mnRow );
1483 		gotoCell( aPos, bSelect, pWindow, nAction );
1484 		break;
1485 	}
1486 
1487 	case ACTION_EDIT_CELL:
1488 		EditCell( getSelectionStart(), pWindow, 0, nAction );
1489 		break;
1490 
1491 	case ACTION_STOP_TEXT_EDIT:
1492 		StopTextEdit();
1493 		break;
1494 
1495 	case ACTION_REMOVE_SELECTION:
1496 		RemoveSelection();
1497 		break;
1498 
1499 	case ACTION_START_SELECTION:
1500 		StartSelection( getSelectionStart() );
1501 		break;
1502 
1503 	case ACTION_TAB:
1504 	{
1505 		if( bSelect )
1506 			gotoCell( pTableObj->getPreviousCell( getSelectionEnd(), true ), false, pWindow, nAction );
1507 		else
1508         {
1509             CellPos aSelectionEnd( getSelectionEnd() );
1510             CellPos aNextCell( pTableObj->getNextCell( aSelectionEnd, true ) );
1511             if( aSelectionEnd == aNextCell )
1512             {
1513                 onInsert( SID_TABLE_INSERT_ROW, 0 );
1514                 aNextCell = pTableObj->getNextCell( aSelectionEnd, true );
1515             }
1516 			gotoCell( aNextCell, false, pWindow, nAction );
1517         }
1518 		break;
1519 	}
1520 	}
1521 
1522 	return nAction != ACTION_HANDLED_BY_VIEW;
1523 }
1524 
1525 // --------------------------------------------------------------------
1526 
1527 void SvxTableController::gotoCell( const CellPos& rPos, bool bSelect, Window* pWindow, sal_uInt16 nAction )
1528 {
1529 	if( mxTableObj.is() && static_cast<SdrTableObj*>(mxTableObj.get())->IsTextEditActive() )
1530 		mpView->SdrEndTextEdit(sal_True);
1531 
1532 	if( bSelect )
1533 	{
1534 		maCursorLastPos = rPos;
1535 		if( mxTableObj.is() )
1536 			static_cast< SdrTableObj* >( mxTableObj.get() )->setActiveCell( rPos );
1537 
1538 		if( !mbCellSelectionMode )
1539 		{
1540 			setSelectedCells( maCursorFirstPos, rPos );
1541 		}
1542 		else
1543 		{
1544 			UpdateSelection( rPos );
1545 		}
1546 	}
1547 	else
1548 	{
1549 		RemoveSelection();
1550 		EditCell( rPos, pWindow, 0, nAction );
1551 	}
1552 }
1553 
1554 // --------------------------------------------------------------------
1555 
1556 const CellPos& SvxTableController::getSelectionStart()
1557 {
1558 	checkCell( maCursorFirstPos );
1559 	return maCursorFirstPos;
1560 }
1561 
1562 // --------------------------------------------------------------------
1563 
1564 void SvxTableController::setSelectionStart( const CellPos& rPos )
1565 {
1566 	maCursorFirstPos = rPos;
1567 }
1568 
1569 // --------------------------------------------------------------------
1570 
1571 const CellPos& SvxTableController::getSelectionEnd()
1572 {
1573 	checkCell( maCursorLastPos );
1574 	return maCursorLastPos;
1575 }
1576 
1577 // --------------------------------------------------------------------
1578 
1579 Reference< XCellCursor > SvxTableController::getSelectionCursor()
1580 {
1581 	Reference< XCellCursor > xCursor;
1582 
1583 	if( mxTable.is() )
1584 	{
1585 		if( hasSelectedCells() )
1586 		{
1587 			CellPos aStart, aEnd;
1588 			getSelectedCells( aStart, aEnd );
1589 			xCursor = mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) );
1590 		}
1591 		else
1592 		{
1593 			xCursor = mxTable->createCursor();
1594 		}
1595 	}
1596 
1597 	return xCursor;
1598 }
1599 
1600 void SvxTableController::MergeRange( sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow )
1601 {
1602 	if( mxTable.is() ) try
1603 	{
1604 		Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( nFirstCol, nFirstRow,nLastCol, nLastRow ) ), UNO_QUERY_THROW );
1605 		if( xRange->isMergeable() )
1606 		{
1607 			const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1608 			if( bUndo )
1609 			{
1610 				mpModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
1611 				mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*mxTableObj.get()) );
1612 			}
1613 
1614 			xRange->merge();
1615 
1616 			if( bUndo )
1617 				mpModel->EndUndo();
1618 		}
1619 	}
1620 	catch( Exception& )
1621 	{
1622 		DBG_ASSERT( false, "sdr::table::SvxTableController::MergeRange(), exception caught!" );
1623 	}
1624 }
1625 
1626 
1627 
1628 // --------------------------------------------------------------------
1629 
1630 void SvxTableController::checkCell( CellPos& rPos )
1631 {
1632 	if( mxTable.is() ) try
1633 	{
1634 		if( rPos.mnCol >= mxTable->getColumnCount() )
1635 			rPos.mnCol = mxTable->getColumnCount()-1;
1636 
1637 		if( rPos.mnRow >= mxTable->getRowCount() )
1638 			rPos.mnRow = mxTable->getRowCount()-1;
1639 	}
1640 	catch( Exception& e )
1641 	{
1642 		(void)e;
1643 		DBG_ERROR("sdr::table::SvxTableController::checkCell(), exception caught!" );
1644 	}
1645 }
1646 
1647 // --------------------------------------------------------------------
1648 
1649 void SvxTableController::findMergeOrigin( CellPos& rPos )
1650 {
1651 	if( mxTable.is() ) try
1652 	{
1653 		Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ), UNO_QUERY_THROW );
1654 		if( xCell.is() && xCell->isMerged() )
1655 		{
1656 			::findMergeOrigin( mxTable, rPos.mnCol, rPos.mnRow, rPos.mnCol, rPos.mnRow );
1657 		}
1658 	}
1659 	catch( Exception& e )
1660 	{
1661 		(void)e;
1662 		DBG_ERROR("sdr::table::SvxTableController::findMergeOrigin(), exception caught!" );
1663 	}
1664 }
1665 
1666 // --------------------------------------------------------------------
1667 
1668 void SvxTableController::EditCell( const CellPos& rPos, ::Window* pWindow, const awt::MouseEvent* pMouseEvent /*= 0*/, sal_uInt16 nAction /*= ACTION_NONE */ )
1669 {
1670 	SdrPageView* pPV = mpView->GetSdrPageView();
1671 
1672 	::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1673 	if( pTableObj && pTableObj->GetPage() == pPV->GetPage() )
1674 	{
1675 		bool bEmptyOutliner = false;
1676 
1677 		if(!pTableObj->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
1678 		{
1679 			::Outliner* pOutl = mpView->GetTextEditOutliner();
1680 			sal_uIntPtr nParaAnz = pOutl->GetParagraphCount();
1681 			Paragraph* p1stPara = pOutl->GetParagraph( 0 );
1682 
1683 			if(nParaAnz==1 && p1stPara)
1684 			{
1685 				// Bei nur einem Pararaph
1686 				if (pOutl->GetText(p1stPara).Len() == 0)
1687 				{
1688 					bEmptyOutliner = true;
1689 				}
1690 			}
1691 		}
1692 
1693 		CellPos aPos( rPos );
1694 		findMergeOrigin( aPos );
1695 
1696 		if( pTableObj != mpView->GetTextEditObject() || bEmptyOutliner || !pTableObj->IsTextEditActive( aPos ) )
1697 		{
1698 			if( pTableObj->IsTextEditActive() )
1699 				mpView->SdrEndTextEdit(sal_True);
1700 
1701 			pTableObj->setActiveCell( aPos );
1702 
1703 			// create new outliner, owner will be the SdrObjEditView
1704 			SdrOutliner* pOutl = SdrMakeOutliner( OUTLINERMODE_OUTLINEOBJECT, mpModel );
1705 			if( pTableObj->IsVerticalWriting() )
1706 				pOutl->SetVertical( sal_True );
1707 
1708 			if(mpView->SdrBeginTextEdit(pTableObj, pPV, pWindow, sal_True, pOutl))
1709 			{
1710 				maCursorLastPos = maCursorFirstPos = rPos;
1711 
1712 				OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1713 
1714 				bool bNoSel = true;
1715 
1716 				if( pMouseEvent )
1717 				{
1718 					::MouseEvent aMEvt( *pMouseEvent );
1719 
1720 					SdrViewEvent aVEvt;
1721 					SdrHitKind eHit = mpView->PickAnything(aMEvt, SDRMOUSEBUTTONDOWN, aVEvt);
1722 
1723 					if (eHit == SDRHIT_TEXTEDIT)
1724 					{
1725 						// Text getroffen
1726 						pOLV->MouseButtonDown(aMEvt);
1727 						pOLV->MouseMove(aMEvt);
1728 						pOLV->MouseButtonUp(aMEvt);
1729 //						pOLV->MouseButtonDown(aMEvt);
1730 						bNoSel = false;
1731 					}
1732 					else
1733 					{
1734 						nAction = ACTION_GOTO_LEFT_CELL;
1735 					}
1736 				}
1737 
1738 				if( bNoSel )
1739 				{
1740 					// Move cursor to end of text
1741 					ESelection aNewSelection;
1742 
1743 					const WritingMode eMode = pTableObj->GetWritingMode();
1744 					if( ((nAction == ACTION_GOTO_LEFT_CELL) || (nAction == ACTION_GOTO_RIGHT_CELL)) && (eMode != WritingMode_TB_RL) )
1745 					{
1746 						const bool bLast = ((nAction == ACTION_GOTO_LEFT_CELL) && (eMode == WritingMode_LR_TB)) ||
1747 											 ((nAction == ACTION_GOTO_RIGHT_CELL) && (eMode == WritingMode_RL_TB));
1748 
1749 						if( bLast )
1750 							aNewSelection = ESelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
1751 					}
1752 					pOLV->SetSelection(aNewSelection);
1753 				}
1754 			}
1755 		}
1756 	}
1757 }
1758 
1759 // --------------------------------------------------------------------
1760 
1761 bool SvxTableController::StopTextEdit()
1762 {
1763 	if(mpView->IsTextEdit())
1764 	{
1765 		mpView->SdrEndTextEdit();
1766 		mpView->SetCurrentObj(OBJ_TABLE);
1767 		mpView->SetEditMode(SDREDITMODE_EDIT);
1768 		return true;
1769 	}
1770 	else
1771 	{
1772 		return false;
1773 	}
1774 }
1775 
1776 // --------------------------------------------------------------------
1777 
1778 void SvxTableController::DeleteTable()
1779 {
1780 	//
1781 }
1782 
1783 // --------------------------------------------------------------------
1784 
1785 void SvxTableController::getSelectedCells( CellPos& rFirst, CellPos& rLast )
1786 {
1787 	if( mbCellSelectionMode )
1788 	{
1789 		checkCell( maCursorFirstPos );
1790 		checkCell( maCursorLastPos );
1791 
1792 		rFirst.mnCol = std::min( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1793 		rFirst.mnRow = std::min( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1794 		rLast.mnCol = std::max( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1795 		rLast.mnRow = std::max( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1796 
1797 		bool bExt = false;
1798 		if( mxTable.is() ) do
1799 		{
1800 			bExt = false;
1801 			for( sal_Int32 nRow = rFirst.mnRow; nRow <= rLast.mnRow && !bExt; nRow++ )
1802 			{
1803 				for( sal_Int32 nCol = rFirst.mnCol; nCol <= rLast.mnCol && !bExt; nCol++ )
1804 				{
1805 					Reference< XMergeableCell > xCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
1806 					if( !xCell.is() )
1807 						continue;
1808 
1809 					if( xCell->isMerged() )
1810 					{
1811 						CellPos aPos( nCol, nRow );
1812 						findMergeOrigin( aPos );
1813 						if( (aPos.mnCol < rFirst.mnCol) || (aPos.mnRow < rFirst.mnRow) )
1814 						{
1815 							rFirst.mnCol = std::min( rFirst.mnCol, aPos.mnCol );
1816 							rFirst.mnRow = std::min( rFirst.mnRow, aPos.mnRow );
1817 							bExt = true;
1818 						}
1819 					}
1820 					else
1821 					{
1822 						if( ((nCol + xCell->getColumnSpan() - 1) > rLast.mnCol) || (nRow + xCell->getRowSpan() - 1 ) > rLast.mnRow )
1823 						{
1824 							rLast.mnCol = std::max( rLast.mnCol, nCol + xCell->getColumnSpan() - 1 );
1825 							rLast.mnRow = std::max( rLast.mnRow, nRow + xCell->getRowSpan() - 1 );
1826 							bExt = true;
1827 						}
1828 					}
1829 				}
1830 			}
1831 		}
1832 		while(bExt);
1833 	}
1834 	else if( mpView && mpView->IsTextEdit() )
1835 	{
1836 		rFirst = getSelectionStart();
1837 		findMergeOrigin( rFirst );
1838 		rLast = rFirst;
1839 
1840 		if( mxTable.is() )
1841 		{
1842 			Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rLast.mnCol, rLast.mnRow ), UNO_QUERY );
1843 			if( xCell.is() )
1844 			{
1845 				rLast.mnCol += xCell->getColumnSpan() - 1;
1846 				rLast.mnRow += xCell->getRowSpan() - 1;
1847 			}
1848 		}
1849 	}
1850 	else
1851 	{
1852 		rFirst.mnCol = 0;
1853 		rFirst.mnRow = 0;
1854 		if( mxTable.is() )
1855 		{
1856 			rLast.mnRow = mxTable->getRowCount()-1;
1857 			rLast.mnCol = mxTable->getColumnCount()-1;
1858 		}
1859 		else
1860 		{
1861 			rLast.mnRow = 0;
1862 			rLast.mnCol = 0;
1863 		}
1864 	}
1865 }
1866 
1867 // --------------------------------------------------------------------
1868 
1869 void SvxTableController::StartSelection( const CellPos& rPos )
1870 {
1871 	StopTextEdit();
1872 	mbCellSelectionMode = true;
1873 	maCursorLastPos = maCursorFirstPos = rPos;
1874 	mpView->MarkListHasChanged();
1875 }
1876 
1877 // --------------------------------------------------------------------
1878 
1879 void SvxTableController::setSelectedCells( const CellPos& rStart, const CellPos& rEnd )
1880 {
1881 	StopTextEdit();
1882 	mbCellSelectionMode = true;
1883 	maCursorFirstPos = rStart;
1884 	UpdateSelection( rEnd );
1885 }
1886 
1887 // --------------------------------------------------------------------
1888 
1889 void SvxTableController::UpdateSelection( const CellPos& rPos )
1890 {
1891 	maCursorLastPos = rPos;
1892 	mpView->MarkListHasChanged();
1893 }
1894 
1895 // --------------------------------------------------------------------
1896 
1897 void SvxTableController::clearSelection()
1898 {
1899 	RemoveSelection();
1900 }
1901 
1902 // --------------------------------------------------------------------
1903 
1904 void SvxTableController::selectAll()
1905 {
1906 	if( mxTable.is() )
1907 	{
1908 		CellPos aPos1, aPos2( mxTable->getColumnCount()-1, mxTable->getRowCount()-1 );
1909 		if( (aPos2.mnCol >= 0) && (aPos2.mnRow >= 0) )
1910 		{
1911 			setSelectedCells( aPos1, aPos2 );
1912 		}
1913 	}
1914 }
1915 
1916 // --------------------------------------------------------------------
1917 
1918 void SvxTableController::RemoveSelection()
1919 {
1920 	if( mbCellSelectionMode )
1921 	{
1922 		mbCellSelectionMode = false;
1923 		mpView->MarkListHasChanged();
1924 	}
1925 }
1926 
1927 // --------------------------------------------------------------------
1928 
1929 void SvxTableController::onTableModified()
1930 {
1931 	if( mnUpdateEvent == 0 )
1932 		mnUpdateEvent = Application::PostUserEvent( LINK( this, SvxTableController, UpdateHdl ) );
1933 }
1934 // --------------------------------------------------------------------
1935 
1936 void SvxTableController::updateSelectionOverlay()
1937 {
1938 	destroySelectionOverlay();
1939 	if( mbCellSelectionMode )
1940 	{
1941 		::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1942 		if( pTableObj )
1943 		{
1944 			sdr::overlay::OverlayObjectCell::RangeVector aRanges;
1945 
1946 			Rectangle aRect;
1947 			CellPos aStart,aEnd;
1948 			getSelectedCells( aStart, aEnd );
1949 			pTableObj->getCellBounds( aStart, aRect );
1950 
1951 			basegfx::B2DRange a2DRange( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1952 			a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1953 
1954 			findMergeOrigin( aEnd );
1955 			pTableObj->getCellBounds( aEnd, aRect );
1956 			a2DRange.expand( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1957 			a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1958 			aRanges.push_back( a2DRange );
1959 
1960 			::Color aHighlight( COL_BLUE );
1961 			OutputDevice* pOutDev = mpView->GetFirstOutputDevice();
1962 			if( pOutDev )
1963 				aHighlight = pOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
1964 
1965 			const sal_uInt32 nCount = mpView->PaintWindowCount();
1966 			for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
1967 			{
1968 				SdrPaintWindow* pPaintWindow = mpView->GetPaintWindow(nIndex);
1969 				if( pPaintWindow )
1970 				{
1971 					::sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager();
1972 					if( pOverlayManager )
1973 					{
1974 						// sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_INVERT;
1975 						sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_TRANSPARENT;
1976 
1977 						sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
1978 
1979 						pOverlayManager->add(*pOverlay);
1980 						mpSelectionOverlay = new ::sdr::overlay::OverlayObjectList;
1981 						mpSelectionOverlay->append(*pOverlay);
1982 					}
1983 				}
1984 			}
1985 		}
1986 	}
1987 }
1988 
1989 // --------------------------------------------------------------------
1990 
1991 void SvxTableController::destroySelectionOverlay()
1992 {
1993 	if( mpSelectionOverlay )
1994 	{
1995 		delete mpSelectionOverlay;
1996 		mpSelectionOverlay = 0;
1997 	}
1998 }
1999 
2000 // --------------------------------------------------------------------
2001 
2002 void SvxTableController::MergeAttrFromSelectedCells(SfxItemSet& rAttr, bool bOnlyHardAttr) const
2003 {
2004 	if( mxTable.is() )
2005 	{
2006 		CellPos aStart, aEnd;
2007 		const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
2008 
2009 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2010 		{
2011 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2012 			{
2013 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2014 				if( xCell.is() && !xCell->isMerged() )
2015 				{
2016 					const SfxItemSet& rSet = xCell->GetItemSet();
2017 					SfxWhichIter aIter(rSet);
2018 					sal_uInt16 nWhich(aIter.FirstWhich());
2019 					while(nWhich)
2020 					{
2021 						if(!bOnlyHardAttr)
2022 						{
2023 							if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, sal_False))
2024 								rAttr.InvalidateItem(nWhich);
2025 							else
2026 								rAttr.MergeValue(rSet.Get(nWhich), sal_True);
2027 						}
2028 						else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, sal_False))
2029 						{
2030 							const SfxPoolItem& rItem = rSet.Get(nWhich);
2031 							rAttr.MergeValue(rItem, sal_True);
2032 						}
2033 
2034 						nWhich = aIter.NextWhich();
2035 					}
2036 				}
2037 			}
2038 		}
2039 	}
2040 
2041 	if( mpView->IsTextEdit() )
2042 	{
2043 	}
2044 }
2045 
2046 // --------------------------------------------------------------------
2047 
2048 const sal_uInt16 CELL_BEFORE = 0x0001;
2049 const sal_uInt16 CELL_LEFT   = 0x0002;
2050 const sal_uInt16 CELL_RIGHT  = 0x0004;
2051 const sal_uInt16 CELL_AFTER  = 0x0008;
2052 
2053 const sal_uInt16 CELL_UPPER  = 0x0010;
2054 const sal_uInt16 CELL_TOP    = 0x0020;
2055 const sal_uInt16 CELL_BOTTOM = 0x0040;
2056 const sal_uInt16 CELL_LOWER  = 0x0080;
2057 
2058 // --------------------------------------------------------------------
2059 
2060 static void ImplSetLinePreserveColor( SvxBoxItem& rNewFrame, const SvxBorderLine* pNew, sal_uInt16 nLine )
2061 {
2062 	if( pNew )
2063 	{
2064 		const SvxBorderLine* pOld = rNewFrame.GetLine(nLine);
2065 		if( pOld )
2066 		{
2067 			SvxBorderLine aNewLine( *pNew );
2068 			aNewLine.SetColor( pOld->GetColor() );
2069 			rNewFrame.SetLine( &aNewLine, nLine );
2070 			return;
2071 		}
2072 	}
2073 	rNewFrame.SetLine( pNew, nLine );
2074 }
2075 
2076 // --------------------------------------------------------------------
2077 
2078 static void ImplApplyBoxItem( sal_uInt16 nCellFlags, const SvxBoxItem* pBoxItem, const SvxBoxInfoItem* pBoxInfoItem, SvxBoxItem& rNewFrame )
2079 {
2080 	if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2081 	{
2082 		// current cell is outside the selection
2083 
2084 		if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2085 		{
2086 			if( nCellFlags & CELL_UPPER )
2087 			{
2088 				if( pBoxInfoItem->IsValid(VALID_TOP) )
2089 					rNewFrame.SetLine(0, BOX_LINE_BOTTOM );
2090 			}
2091 			else if( nCellFlags & CELL_LOWER )
2092 			{
2093 				if( pBoxInfoItem->IsValid(VALID_BOTTOM) )
2094 					rNewFrame.SetLine( 0, BOX_LINE_TOP );
2095 			}
2096 		}
2097 		else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2098 		{
2099 			if( nCellFlags & CELL_BEFORE )
2100 			{
2101 				if( pBoxInfoItem->IsValid(VALID_LEFT) )
2102 					rNewFrame.SetLine( 0, BOX_LINE_RIGHT );
2103 			}
2104 			else if( nCellFlags & CELL_AFTER )
2105 			{
2106 				if( pBoxInfoItem->IsValid(VALID_RIGHT) )
2107 					rNewFrame.SetLine( 0, BOX_LINE_LEFT );
2108 			}
2109 		}
2110 	}
2111 	else
2112 	{
2113 		// current cell is inside the selection
2114 
2115 		if( (nCellFlags & CELL_LEFT) ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
2116 			rNewFrame.SetLine( (nCellFlags & CELL_LEFT) ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(), BOX_LINE_LEFT );
2117 
2118 		if( (nCellFlags & CELL_RIGHT) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
2119 			rNewFrame.SetLine( (nCellFlags & CELL_RIGHT) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(), BOX_LINE_RIGHT );
2120 
2121 		if( (nCellFlags & CELL_TOP) ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
2122 			rNewFrame.SetLine( (nCellFlags & CELL_TOP) ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(), BOX_LINE_TOP );
2123 
2124 		if( (nCellFlags & CELL_BOTTOM) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
2125 			rNewFrame.SetLine( (nCellFlags & CELL_BOTTOM) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(), BOX_LINE_BOTTOM );
2126 
2127 		// apply distance to borders
2128 		if( pBoxInfoItem->IsValid( VALID_DISTANCE ) )
2129 			for( sal_uInt16 nLine = 0; nLine < 4; ++nLine )
2130 				rNewFrame.SetDistance( pBoxItem->GetDistance( nLine ), nLine );
2131 	}
2132 }
2133 
2134 // --------------------------------------------------------------------
2135 
2136 static void ImplSetLineColor( SvxBoxItem& rNewFrame, sal_uInt16 nLine, const Color& rColor )
2137 {
2138 	const SvxBorderLine* pSourceLine = rNewFrame.GetLine( nLine );
2139 	if( pSourceLine )
2140 	{
2141 		SvxBorderLine aLine( *pSourceLine );
2142 		aLine.SetColor( rColor );
2143 		rNewFrame.SetLine( &aLine, nLine );
2144 	}
2145 }
2146 
2147 // --------------------------------------------------------------------
2148 
2149 static void ImplApplyLineColorItem( sal_uInt16 nCellFlags, const SvxColorItem* pLineColorItem, SvxBoxItem& rNewFrame )
2150 {
2151 	const Color aColor( pLineColorItem->GetValue() );
2152 
2153 	if( (nCellFlags & (CELL_LOWER|CELL_BEFORE|CELL_AFTER)) == 0 )
2154 		ImplSetLineColor( rNewFrame, BOX_LINE_BOTTOM, aColor );
2155 
2156 	if( (nCellFlags & (CELL_UPPER|CELL_BEFORE|CELL_AFTER)) == 0 )
2157 		ImplSetLineColor( rNewFrame, BOX_LINE_TOP, aColor );
2158 
2159 	if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_AFTER)) == 0 )
2160 		ImplSetLineColor( rNewFrame, BOX_LINE_RIGHT, aColor );
2161 
2162 	if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_BEFORE)) == 0 )
2163 		ImplSetLineColor( rNewFrame, BOX_LINE_LEFT, aColor );
2164 }
2165 
2166 // --------------------------------------------------------------------
2167 
2168 static void ImplApplyBorderLineItem( sal_uInt16 nCellFlags, const SvxBorderLine* pBorderLineItem, SvxBoxItem& rNewFrame )
2169 {
2170 	if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2171 	{
2172 		if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2173 		{
2174 			if( nCellFlags & CELL_UPPER )
2175 			{
2176 				if( rNewFrame.GetBottom() )
2177 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2178 			}
2179 			else if( nCellFlags & CELL_LOWER )
2180 			{
2181 				if( rNewFrame.GetTop() )
2182 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2183 			}
2184 		}
2185 		else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2186 		{
2187 			if( nCellFlags & CELL_BEFORE )
2188 			{
2189 				if( rNewFrame.GetRight() )
2190 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2191 			}
2192 			else if( nCellFlags & CELL_AFTER )
2193 			{
2194 				if( rNewFrame.GetLeft() )
2195 					ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2196 			}
2197 		}
2198 	}
2199 	else
2200 	{
2201 		if( rNewFrame.GetBottom() )
2202 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2203 		if( rNewFrame.GetTop() )
2204 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2205 		if( rNewFrame.GetRight() )
2206 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2207 		if( rNewFrame.GetLeft() )
2208 			ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2209 	}
2210 }
2211 
2212 // --------------------------------------------------------------------
2213 
2214 void SvxTableController::ApplyBorderAttr( const SfxItemSet& rAttr )
2215 {
2216 	if( mxTable.is() )
2217 	{
2218 		const sal_Int32 nRowCount = mxTable->getRowCount();
2219 		const sal_Int32 nColCount = mxTable->getColumnCount();
2220 		if( nRowCount && nColCount )
2221 		{
2222 			const SvxBoxItem* pBoxItem = 0;
2223 			if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER, sal_False) )
2224 				pBoxItem = dynamic_cast< const SvxBoxItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER ) );
2225 
2226 			const SvxBoxInfoItem* pBoxInfoItem = 0;
2227 			if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER_INNER, sal_False) )
2228 				pBoxInfoItem = dynamic_cast< const SvxBoxInfoItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER_INNER ) );
2229 
2230 			const SvxColorItem* pLineColorItem = 0;
2231 			if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINECOLOR, sal_False) )
2232 				pLineColorItem = dynamic_cast< const SvxColorItem* >( &rAttr.Get( SID_FRAME_LINECOLOR ) );
2233 
2234 			const SvxBorderLine* pBorderLineItem = 0;
2235 			if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINESTYLE, sal_False) )
2236 				pBorderLineItem = ((const SvxLineItem&)rAttr.Get( SID_FRAME_LINESTYLE )).GetLine();
2237 
2238 			if( pBoxInfoItem && !pBoxItem )
2239 			{
2240 				const static SvxBoxItem gaEmptyBoxItem( SDRATTR_TABLE_BORDER );
2241 				pBoxItem = &gaEmptyBoxItem;
2242 			}
2243 			else if( pBoxItem && !pBoxInfoItem )
2244 			{
2245 				const static SvxBoxInfoItem gaEmptyBoxInfoItem( SDRATTR_TABLE_BORDER_INNER );
2246 				pBoxInfoItem = &gaEmptyBoxInfoItem;
2247 			}
2248 
2249 			CellPos aStart, aEnd;
2250 			getSelectedCells( aStart, aEnd );
2251 
2252 			const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
2253 			const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
2254 
2255 			for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
2256 			{
2257 				sal_uInt16 nRowFlags = 0;
2258 				nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
2259 				nRowFlags |= (nRow == aEnd.mnRow)   ? CELL_BOTTOM : 0;
2260 				nRowFlags |= (nRow < aStart.mnRow)  ? CELL_UPPER : 0;
2261 				nRowFlags |= (nRow > aEnd.mnRow)    ? CELL_LOWER : 0;
2262 
2263 				for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
2264 				{
2265 					CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2266 					if( !xCell.is() )
2267 						continue;
2268 
2269 					const SfxItemSet& rSet = xCell->GetItemSet();
2270 					const SvxBoxItem* pOldOuter = (const SvxBoxItem*)	  &rSet.Get( SDRATTR_TABLE_BORDER );
2271 
2272 					SvxBoxItem aNewFrame( *pOldOuter );
2273 
2274 					sal_uInt16 nCellFlags = nRowFlags;
2275 					nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
2276 					nCellFlags |= (nCol == aEnd.mnCol)   ? CELL_RIGHT : 0;
2277 					nCellFlags |= (nCol < aStart.mnCol)  ? CELL_BEFORE : 0;
2278 					nCellFlags |= (nCol > aEnd.mnCol)    ? CELL_AFTER : 0;
2279 
2280 					if( pBoxItem && pBoxInfoItem )
2281 						ImplApplyBoxItem( nCellFlags, pBoxItem, pBoxInfoItem, aNewFrame );
2282 
2283 					if( pLineColorItem )
2284 						ImplApplyLineColorItem( nCellFlags, pLineColorItem, aNewFrame );
2285 
2286 					if( pBorderLineItem )
2287 						ImplApplyBorderLineItem( nCellFlags, pBorderLineItem, aNewFrame );
2288 
2289 					if (aNewFrame != *pOldOuter)
2290 					{
2291 						SfxItemSet aAttr(*rSet.GetPool(), rSet.GetRanges());
2292 						aAttr.Put(aNewFrame);
2293 						xCell->SetMergedItemSetAndBroadcast( aAttr, false );
2294 					}
2295 				}
2296 			}
2297 		}
2298 	}
2299 }
2300 
2301 // --------------------------------------------------------------------
2302 
2303 void SvxTableController::UpdateTableShape()
2304 {
2305 	SdrObject* pTableObj = mxTableObj.get();
2306 	if( pTableObj )
2307 	{
2308 		pTableObj->ActionChanged();
2309 		pTableObj->BroadcastObjectChange();
2310 	}
2311 	updateSelectionOverlay();
2312 }
2313 
2314 
2315 // --------------------------------------------------------------------
2316 
2317 void SvxTableController::SetAttrToSelectedCells(const SfxItemSet& rAttr, bool bReplaceAll)
2318 {
2319 	if( mxTable.is() )
2320 	{
2321 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2322 
2323 		if( bUndo )
2324 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2325 
2326 		CellPos aStart, aEnd;
2327 		getSelectedCells( aStart, aEnd );
2328 
2329 		SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
2330 		aAttr.Put(rAttr, sal_True);
2331 
2332 		const bool bFrame = (rAttr.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rAttr.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2333 
2334 		if( bFrame )
2335 		{
2336 			aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2337 			aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2338 		}
2339 
2340 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2341 		{
2342 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2343 			{
2344 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2345 				if( xCell.is() )
2346 				{
2347 					if( bUndo )
2348 						xCell->AddUndo();
2349 					xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2350 				}
2351 			}
2352 		}
2353 
2354 		if( bFrame )
2355 		{
2356 			ApplyBorderAttr( rAttr );
2357 		}
2358 
2359 		UpdateTableShape();
2360 
2361 		if( bUndo )
2362 			mpModel->EndUndo();
2363 
2364 	}
2365 }
2366 
2367 // --------------------------------------------------------------------
2368 
2369 bool SvxTableController::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
2370 {
2371 	if( mxTableObj.is() && hasSelectedCells() )
2372 	{
2373 		MergeAttrFromSelectedCells( rTargetSet, bOnlyHardAttr );
2374 
2375 		if( mpView->IsTextEdit() )
2376 		{
2377 			if( mxTableObj->GetOutlinerParaObject() )
2378 				rTargetSet.Put( SvxScriptTypeItem( mxTableObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) );
2379 
2380 			OutlinerView* pTextEditOutlinerView = mpView->GetTextEditOutlinerView();
2381 			if(pTextEditOutlinerView)
2382 			{
2383 				// FALSE= InvalidItems nicht al Default, sondern als "Loecher" betrachten
2384 				rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), sal_False);
2385 				rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ), sal_False );
2386 			}
2387 		}
2388 
2389 		return true;
2390 	}
2391 	else
2392 	{
2393 		return false;
2394 	}
2395 }
2396 
2397 // --------------------------------------------------------------------
2398 
2399 bool SvxTableController::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
2400 {
2401 	if( mbCellSelectionMode || mpView->IsTextEdit()  )
2402 	{
2403 		SetAttrToSelectedCells( rSet, bReplaceAll );
2404 		return true;
2405 	}
2406 	return false;
2407 }
2408 
2409 // --------------------------------------------------------------------
2410 
2411 bool SvxTableController::GetMarkedObjModel( SdrPage* pNewPage )
2412 {
2413 	if( mxTableObj.is() && mbCellSelectionMode && pNewPage ) try
2414 	{
2415 		::sdr::table::SdrTableObj& rTableObj = *static_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
2416 
2417 		CellPos aStart, aEnd;
2418 		getSelectedCells( aStart, aEnd );
2419 
2420 		SdrTableObj* pNewTableObj = rTableObj.CloneRange( aStart, aEnd );
2421 
2422 		pNewTableObj->SetPage( pNewPage );
2423 		pNewTableObj->SetModel( pNewPage->GetModel() );
2424 
2425 		SdrInsertReason aReason(SDRREASON_VIEWCALL);
2426 		pNewPage->InsertObject(pNewTableObj,CONTAINER_APPEND,&aReason);
2427 
2428 		return true;
2429 	}
2430 	catch( Exception& )
2431 	{
2432 		DBG_ERROR( "svx::SvxTableController::GetMarkedObjModel(), exception caught!" );
2433 	}
2434 	return false;
2435 }
2436 
2437 // --------------------------------------------------------------------
2438 
2439 bool SvxTableController::PasteObjModel( const SdrModel& rModel )
2440 {
2441 	if( mxTableObj.is() && mpView && (rModel.GetPageCount() >= 1) )
2442 	{
2443 		const SdrPage* pPastePage = rModel.GetPage(0);
2444 		if( pPastePage && pPastePage->GetObjCount() == 1 )
2445 		{
2446 			SdrTableObj* pPasteTableObj = dynamic_cast< SdrTableObj* >( pPastePage->GetObj(0) );
2447 			if( pPasteTableObj )
2448 			{
2449 				return PasteObject( pPasteTableObj );
2450 			}
2451 		}
2452 	}
2453 
2454 	return false;
2455 }
2456 
2457 // --------------------------------------------------------------------
2458 
2459 bool SvxTableController::PasteObject( SdrTableObj* pPasteTableObj )
2460 {
2461 	if( !pPasteTableObj )
2462 		return false;
2463 
2464 	Reference< XTable > xPasteTable( pPasteTableObj->getTable() );
2465 	if( !xPasteTable.is() )
2466 		return false;
2467 
2468 	if( !mxTable.is() )
2469 		return false;
2470 
2471 	sal_Int32 nPasteColumns = xPasteTable->getColumnCount();
2472 	sal_Int32 nPasteRows = xPasteTable->getRowCount();
2473 
2474 	CellPos aStart, aEnd;
2475 	getSelectedCells( aStart, aEnd );
2476 
2477 	if( mpView->IsTextEdit() )
2478 		mpView->SdrEndTextEdit(sal_True);
2479 
2480 	sal_Int32 nColumns = mxTable->getColumnCount();
2481 	sal_Int32 nRows = mxTable->getRowCount();
2482 
2483 	const sal_Int32 nMissing = nPasteRows - ( nRows - aStart.mnRow );
2484 	if( nMissing > 0 )
2485 	{
2486 		Reference< XTableRows > xRows( mxTable->getRows() );
2487 		xRows->insertByIndex( nRows, nMissing );
2488 		nRows = mxTable->getRowCount();
2489 	}
2490 
2491 	nPasteRows = std::min( nPasteRows, nRows - aStart.mnRow );
2492 	nPasteColumns = std::min( nPasteColumns, nColumns - aStart.mnCol );
2493 
2494 	// copy cell contents
2495 	for( sal_Int32 nRow = 0; nRow < nPasteRows; ++nRow )
2496 	{
2497 		for( sal_Int32 nCol = 0; nCol < nPasteColumns; ++nCol )
2498 		{
2499 			CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( aStart.mnCol + nCol, aStart.mnRow + nRow ).get() ) );
2500 			if( xTargetCell.is() && !xTargetCell->isMerged() )
2501 			{
2502 				xTargetCell->AddUndo();
2503 				xTargetCell->cloneFrom( dynamic_cast< Cell* >( xPasteTable->getCellByPosition( nCol, nRow ).get() ) );
2504 				nCol += xTargetCell->getColumnSpan() - 1;
2505 			}
2506 		}
2507 	}
2508 
2509 	UpdateTableShape();
2510 
2511 	return true;
2512 }
2513 
2514 bool SvxTableController::TakeFormatPaintBrush( boost::shared_ptr< SfxItemSet >& /*rFormatSet*/  )
2515 {
2516     // SdrView::TakeFormatPaintBrush() is enough
2517     return false;
2518 }
2519 
2520 bool SvxTableController::ApplyFormatPaintBrush( SfxItemSet& rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats )
2521 {
2522 	if( mbCellSelectionMode )
2523 	{
2524     	SdrTextObj* pTableObj = dynamic_cast<SdrTextObj*>( mxTableObj.get() );
2525     	if( !pTableObj )
2526     	    return false;
2527 
2528 		const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2529 
2530 		if( bUndo )
2531 			mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2532 
2533 		CellPos aStart, aEnd;
2534 		getSelectedCells( aStart, aEnd );
2535 
2536 		SfxItemSet aAttr(*rFormatSet.GetPool(), rFormatSet.GetRanges());
2537 		aAttr.Put(rFormatSet, sal_True);
2538 
2539 		const bool bFrame = (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2540 
2541 		if( bFrame )
2542 		{
2543 			aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2544 			aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2545 		}
2546 
2547         const sal_uInt16* pRanges = rFormatSet.GetRanges();
2548         bool bTextOnly = true;
2549 
2550         while( *pRanges )
2551         {
2552             if( (*pRanges != EE_PARA_START) && (*pRanges != EE_CHAR_START) )
2553             {
2554                 bTextOnly = true;
2555                 break;
2556             }
2557             pRanges += 2;
2558         }
2559 
2560         const bool bReplaceAll = false;
2561 		for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2562 		{
2563 			for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2564 			{
2565 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2566 				if( xCell.is() )
2567 				{
2568 					if( bUndo )
2569 						xCell->AddUndo();
2570 				    if( !bTextOnly )
2571 					    xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2572 
2573                     SdrText* pText = static_cast< SdrText* >( xCell.get() );
2574                     mpView->ApplyFormatPaintBrushToText( rFormatSet, *pTableObj, pText, bNoCharacterFormats, bNoParagraphFormats );
2575 				}
2576 			}
2577 		}
2578 
2579 		if( bFrame )
2580 		{
2581 			ApplyBorderAttr( rFormatSet );
2582 		}
2583 
2584 		UpdateTableShape();
2585 
2586 		if( bUndo )
2587 			mpModel->EndUndo();
2588 
2589 	    return true;
2590 
2591 	}
2592     return false;
2593 }
2594 
2595 
2596 // --------------------------------------------------------------------
2597 
2598 IMPL_LINK( SvxTableController, UpdateHdl, void *, EMPTYARG )
2599 {
2600 	mnUpdateEvent = 0;
2601 
2602 	if( mbCellSelectionMode )
2603 	{
2604 		CellPos aStart( maCursorFirstPos );
2605 		CellPos aEnd( maCursorLastPos );
2606 		checkCell(aStart);
2607 		checkCell(aEnd);
2608 		if( aStart != maCursorFirstPos  || aEnd != maCursorLastPos )
2609 		{
2610 			setSelectedCells( aStart, aEnd );
2611 		}
2612 	}
2613 	updateSelectionOverlay();
2614 
2615 	return 0;
2616 }
2617 
2618 } }
2619