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