xref: /aoo41x/main/sw/source/core/frmedt/fetab.cxx (revision cdf0e10c)
1  /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <hintids.hxx>
33 
34 #include <tools/errinf.hxx>
35 #include <vcl/svapp.hxx>
36 #include <basegfx/vector/b2dvector.hxx>
37 #ifndef _SVX_SVXIDS_HRC
38 #include <svx/svxids.hrc>
39 #endif
40 #include <editeng/protitem.hxx>
41 #include <editeng/brshitem.hxx>
42 #include <editeng/frmdiritem.hxx>
43 #include <svtools/ruler.hxx>
44 #include <swwait.hxx>
45 #include <fmtfsize.hxx>
46 #include <fmtornt.hxx>
47 #include <frmatr.hxx>
48 #include <docary.hxx>
49 #include <fesh.hxx>
50 #include <doc.hxx>
51 #include <cntfrm.hxx>
52 #include <rootfrm.hxx>
53 #include <pagefrm.hxx>
54 #include <tabfrm.hxx>
55 #include <rowfrm.hxx>
56 #include <cellfrm.hxx>
57 #include <flyfrm.hxx>
58 #include <dflyobj.hxx>
59 #include <swtable.hxx>
60 #include <swddetbl.hxx>
61 #include <ndtxt.hxx>
62 #include <calc.hxx>
63 #include <tabcol.hxx>
64 #include <cellatr.hxx>
65 #include <pam.hxx>
66 #include <viscrs.hxx>
67 #include <tblsel.hxx>
68 #include <swtblfmt.hxx>
69 #include <swerror.h>
70 #include <swundo.hxx>
71 #include <frmtool.hxx>
72 
73 #include <node.hxx> // #i23726#
74 // OD 2004-05-24 #i28701#
75 #include <sortedobjs.hxx>
76 
77 using namespace ::com::sun::star;
78 
79 
80 //siehe auch swtable.cxx
81 #define COLFUZZY 20L
82 
83 inline sal_Bool IsSame( long nA, long nB ) { return  Abs(nA-nB) <= COLFUZZY; }
84 inline sal_Bool IsNear( long nA, long nB, long nTolerance ) { return Abs( nA - nB ) <= nTolerance; }
85 
86 // table column cache
87 SwTabCols *pLastCols   = 0;
88 const SwTable   *pColumnCacheLastTable  = 0;
89 const SwTabFrm  *pColumnCacheLastTabFrm = 0;
90 const SwFrm     *pColumnCacheLastCellFrm = 0;
91 
92 // table row cache
93 SwTabCols *pLastRows   = 0;
94 const SwTable   *pRowCacheLastTable  = 0;
95 const SwTabFrm  *pRowCacheLastTabFrm = 0;
96 const SwFrm     *pRowCacheLastCellFrm = 0;
97 
98 
99 class TblWait
100 {
101 	SwWait *pWait;
102 public:
103 	TblWait( sal_uInt16 nCnt, SwFrm *pFrm, SwDocShell &rDocShell, sal_uInt16 nCnt2 = 0);
104 	~TblWait() { delete pWait; }
105 };
106 
107 TblWait::TblWait( sal_uInt16 nCnt, SwFrm *pFrm, SwDocShell &rDocShell, sal_uInt16 nCnt2):
108 	pWait( 0 )
109 {
110 	sal_Bool bWait = 20 < nCnt || 20 < nCnt2 || (pFrm &&
111 				 20 < pFrm->ImplFindTabFrm()->GetTable()->GetTabLines().Count());
112 	if( bWait )
113 		pWait = new SwWait( rDocShell, sal_True );
114 }
115 
116 
117 void SwFEShell::ParkCursorInTab()
118 {
119     SwCursor * pSwCrsr = GetSwCrsr();
120 
121     ASSERT(pSwCrsr, "no SwCursor");
122 
123     SwPosition aStartPos = *pSwCrsr->GetPoint(), aEndPos = aStartPos;
124 
125     SwCursor * pTmpCrsr = (SwCursor *) pSwCrsr;
126 
127     /* Search least and greatest position in current cursor ring.
128      */
129     do
130     {
131         const SwPosition * pPt = pTmpCrsr->GetPoint(),
132             * pMk = pTmpCrsr->GetMark();
133 
134         if (*pPt < aStartPos)
135             aStartPos = *pPt;
136 
137         if (*pPt > aEndPos)
138             aEndPos = *pPt;
139 
140         if (*pMk < aStartPos)
141             aStartPos = *pMk;
142 
143         if (*pMk > aEndPos)
144             aEndPos = *pMk;
145 
146         pTmpCrsr = (SwCursor *) pTmpCrsr->GetNext();
147     }
148     while (pTmpCrsr != pSwCrsr);
149 
150     KillPams();
151 
152 	/* @@@ semantic: SwCursor::operator=() is not implemented @@@ */
153 
154     /* Set cursor to end of selection to ensure IsLastCellInRow works
155        properly. */
156     {
157         SwCursor aTmpCrsr( aEndPos, 0, false );
158         *pSwCrsr = aTmpCrsr;
159     }
160 
161     /* Move the cursor out of the columns to delete and stay in the
162        same row. If the table has only one column the cursor will
163        stay in the row and the shell will take care of it. */
164     if (IsLastCellInRow())
165     {
166         /* If the cursor is in the last row of the table, first
167            try to move it to the previous cell. If that fails move
168            it to the next cell. */
169 
170         {
171             SwCursor aTmpCrsr( aStartPos, 0, false );
172             *pSwCrsr = aTmpCrsr;
173         }
174 
175         if (! pSwCrsr->GoPrevCell())
176         {
177             SwCursor aTmpCrsr( aEndPos, 0, false );
178             *pSwCrsr = aTmpCrsr;
179             pSwCrsr->GoNextCell();
180         }
181     }
182     else
183     {
184         /* If the cursor is not in the last row of the table, first
185            try to move it to the next cell. If that fails move it
186            to the previous cell. */
187 
188         {
189             SwCursor aTmpCrsr( aEndPos, 0, false );
190             *pSwCrsr = aTmpCrsr;
191         }
192 
193         if (! pSwCrsr->GoNextCell())
194         {
195             SwCursor aTmpCrsr( aStartPos, 0, false );
196             *pSwCrsr = aTmpCrsr;
197             pSwCrsr->GoPrevCell();
198         }
199     }
200 }
201 
202 /***********************************************************************
203 #*	Class	   :  SwFEShell
204 #*	Methoden   :  InsertRow(), InsertCol
205 #*	Datum	   :  MA 03. May. 93
206 #*	Update	   :  MA 19. Apr. 95
207 #***********************************************************************/
208 sal_Bool SwFEShell::InsertRow( sal_uInt16 nCnt, sal_Bool bBehind )
209 {
210 	// pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
211 	SwFrm *pFrm = GetCurrFrm();
212 	if( !pFrm || !pFrm->IsInTab() )
213 		return sal_False;
214 
215 	if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
216 	{
217 		ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
218 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
219 		return sal_False;
220 	}
221 
222 	SET_CURR_SHELL( this );
223 	StartAllAction();
224 
225 	// lasse ueber das Layout die Boxen suchen
226 	SwSelBoxes aBoxes;
227 	GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
228 
229 	TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
230 
231 	sal_Bool bRet = sal_False;
232 	if ( aBoxes.Count() )
233 		bRet = GetDoc()->InsertRow( aBoxes, nCnt, bBehind );
234 
235 	EndAllActionAndCall();
236 	return bRet;
237 }
238 
239 sal_Bool SwFEShell::InsertCol( sal_uInt16 nCnt, sal_Bool bBehind )
240 {
241 	// pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
242 	SwFrm *pFrm = GetCurrFrm();
243 	if( !pFrm || !pFrm->IsInTab() )
244 		return sal_False;
245 
246 	if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
247 	{
248 		ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
249 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
250 		return sal_False;
251 	}
252 
253 	SET_CURR_SHELL( this );
254 
255 	if( !CheckSplitCells( *this, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) )
256 	{
257 		ErrorHandler::HandleError( ERR_TBLINSCOL_ERROR,
258 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
259 		return sal_False;
260 	}
261 
262 	StartAllAction();
263 	// lasse ueber das Layout die Boxen suchen
264 	SwSelBoxes aBoxes;
265 	GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
266 
267 	TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
268 
269 	sal_Bool bRet = sal_False;
270 	if( aBoxes.Count() )
271 		bRet = GetDoc()->InsertCol( aBoxes, nCnt, bBehind );
272 
273 	EndAllActionAndCall();
274 	return bRet;
275 }
276 
277 /***********************************************************************
278 #*	Class	   :  SwFEShell
279 #*	Methoden   :  DeleteRow(), DeleteCol()
280 #*	Datum	   :  MA 03. May. 93
281 #*	Update	   :  MA 19. Apr. 95
282 #***********************************************************************/
283 
284 /**
285    Determines if the current cursor is in the last row of the table.
286 */
287 sal_Bool SwFEShell::IsLastCellInRow() const
288 {
289     SwTabCols aTabCols;
290     GetTabCols( aTabCols );
291     sal_Bool bResult = sal_False;
292 
293     if (IsTableRightToLeft())
294         /* If the table is right-to-left the last row is the most left one. */
295         bResult = 0 == GetCurTabColNum();
296     else
297         /* If the table is left-to-right the last row is the most right one. */
298         bResult = aTabCols.Count() == GetCurTabColNum();
299 
300     return bResult;
301 }
302 
303 sal_Bool SwFEShell::DeleteCol()
304 {
305 	// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
306 	SwFrm *pFrm = GetCurrFrm();
307 	if( !pFrm || !pFrm->IsInTab() )
308 		return sal_False;
309 
310 	if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
311 	{
312 		ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
313 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
314 		return sal_False;
315 	}
316 
317 	SET_CURR_SHELL( this );
318 	StartAllAction();
319 
320 	// lasse ueber das Layout die Boxen suchen
321 	sal_Bool bRet;
322 	SwSelBoxes aBoxes;
323 	GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
324 	if ( aBoxes.Count() )
325 	{
326 		TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
327 
328 		// die Crsr muessen noch aus dem Loesch Bereich entfernt
329 		// werden. Setze sie immer hinter/auf die Tabelle; ueber die
330 		// Dokument-Position werden sie dann immer an die alte Position gesetzt.
331 		while( !pFrm->IsCellFrm() )
332 			pFrm = pFrm->GetUpper();
333 
334         ParkCursorInTab();
335 
336 		// dann loesche doch die Spalten
337         StartUndo(UNDO_COL_DELETE);
338 		bRet = GetDoc()->DeleteRowCol( aBoxes, true );
339         EndUndo(UNDO_COL_DELETE);
340 
341 	}
342 	else
343 		bRet = sal_False;
344 
345 	EndAllActionAndCall();
346 	return bRet;
347 }
348 
349 sal_Bool SwFEShell::DeleteRow()
350 {
351 	// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
352 	SwFrm *pFrm = GetCurrFrm();
353 	if( !pFrm || !pFrm->IsInTab() )
354 		return sal_False;
355 
356 	if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
357 	{
358 		ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
359 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
360 		return sal_False;
361 	}
362 
363 	SET_CURR_SHELL( this );
364 	StartAllAction();
365 
366 	// lasse ueber das Layout die Boxen suchen
367 	sal_Bool bRet;
368 	SwSelBoxes aBoxes;
369 	GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
370 
371 	if( aBoxes.Count() )
372 	{
373 		TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
374 
375 		// die Crsr aus dem Loeschbereich entfernen.
376 		// Der Cursor steht danach:
377 		//	- es folgt noch eine Zeile, in dieser
378 		//	- vorher steht noch eine Zeile, in dieser
379 		//	- sonst immer dahinter
380 		{
381 			SwTableNode* pTblNd = ((SwCntntFrm*)pFrm)->GetNode()->FindTableNode();
382 
383 			// suche alle Boxen / Lines
384 			_FndBox aFndBox( 0, 0 );
385 			{
386 				_FndPara aPara( aBoxes, &aFndBox );
387 				pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
388 			}
389 
390 			if( !aFndBox.GetLines().Count() )
391 			{
392 				EndAllActionAndCall();
393 				return sal_False;
394 			}
395 
396 			KillPams();
397 
398 			_FndBox* pFndBox = &aFndBox;
399 			while( 1 == pFndBox->GetLines().Count() &&
400 					1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
401 			{
402 				_FndBox* pTmp = pFndBox->GetLines()[0]->GetBoxes()[0];
403 				if( pTmp->GetBox()->GetSttNd() )
404 					break;		// das ist sonst zu weit
405 				pFndBox = pTmp;
406 			}
407 
408 			SwTableLine* pDelLine = pFndBox->GetLines()[
409 							pFndBox->GetLines().Count()-1 ]->GetLine();
410 			SwTableBox* pDelBox = pDelLine->GetTabBoxes()[
411 								pDelLine->GetTabBoxes().Count() - 1 ];
412 			while( !pDelBox->GetSttNd() )
413 			{
414 				SwTableLine* pLn = pDelBox->GetTabLines()[
415 							pDelBox->GetTabLines().Count()-1 ];
416 				pDelBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ];
417 			}
418 			SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(),
419 															pDelBox, sal_True );
420 			while( pNextBox &&
421 					pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
422 				pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox );
423 
424 			if( !pNextBox )			// keine nachfolgende? dann die vorhergehende
425 			{
426 				pDelLine = pFndBox->GetLines()[ 0 ]->GetLine();
427 				pDelBox = pDelLine->GetTabBoxes()[ 0 ];
428 				while( !pDelBox->GetSttNd() )
429 					pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
430 				pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(),
431 															pDelBox, sal_True );
432 				while( pNextBox &&
433 						pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
434 					pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox );
435 			}
436 
437 			sal_uLong nIdx;
438 			if( pNextBox )		// dann den Cursor hier hinein
439 				nIdx = pNextBox->GetSttIdx() + 1;
440 			else				// ansonsten hinter die Tabelle
441 				nIdx = pTblNd->EndOfSectionIndex() + 1;
442 
443 			SwNodeIndex aIdx( GetDoc()->GetNodes(), nIdx );
444 			SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
445 			if( !pCNd )
446 				pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
447 
448 			if( pCNd )
449 			{
450 				SwPaM* pPam = GetCrsr();
451 				pPam->GetPoint()->nNode = aIdx;
452 				pPam->GetPoint()->nContent.Assign( pCNd, 0 );
453 				pPam->SetMark();			// beide wollen etwas davon haben
454 				pPam->DeleteMark();
455 			}
456 		}
457 
458 		// dann loesche doch die Zeilen
459         StartUndo(UNDO_ROW_DELETE);
460 		bRet = GetDoc()->DeleteRowCol( aBoxes );
461         EndUndo(UNDO_ROW_DELETE);
462 	}
463 	else
464 		bRet = sal_False;
465 
466 	EndAllActionAndCall();
467 	return bRet;
468 }
469 
470 /***********************************************************************
471 #*	Class	   :  SwFEShell
472 #*	Methoden   :  MergeTab(), SplitTab()
473 #*	Datum	   :  MA 03. May. 93
474 #*	Update	   :  MA 19. Apr. 95
475 #***********************************************************************/
476 
477 sal_uInt16 SwFEShell::MergeTab()
478 {
479 	// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
480 	sal_uInt16 nRet = TBLMERGE_NOSELECTION;
481 	if( IsTableMode() )
482 	{
483         SwShellTableCrsr* pTableCrsr = GetTableCrsr();
484         const SwTableNode* pTblNd = pTableCrsr->GetNode()->FindTableNode();
485 		if( pTblNd->GetTable().ISA( SwDDETable ))
486 		{
487 			ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
488 							ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
489 		}
490 		else
491 		{
492 			SET_CURR_SHELL( this );
493 			StartAllAction();
494 
495             TblWait( pTableCrsr->GetBoxesCount(), 0, *GetDoc()->GetDocShell(),
496 					 pTblNd->GetTable().GetTabLines().Count() );
497 
498             nRet = GetDoc()->MergeTbl( *pTableCrsr );
499 
500 			KillPams();
501 
502 			EndAllActionAndCall();
503 		}
504 	}
505 	return nRet;
506 }
507 
508 sal_Bool SwFEShell::SplitTab( sal_Bool bVert, sal_uInt16 nCnt, sal_Bool bSameHeight )
509 {
510 	// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
511 	SwFrm *pFrm = GetCurrFrm();
512 	if( !pFrm || !pFrm->IsInTab() )
513 		return sal_False;
514 
515 	if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
516 	{
517 		ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
518 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
519 		return sal_False;
520 	}
521 
522 	SET_CURR_SHELL( this );
523 
524 	if( bVert && !CheckSplitCells( *this, nCnt + 1 ) )
525 	{
526 		ErrorHandler::HandleError( ERR_TBLSPLIT_ERROR,
527 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
528 		return sal_False;
529 	}
530 	StartAllAction();
531 	// lasse ueber das Layout die Boxen suchen
532 	sal_Bool bRet;
533 	SwSelBoxes aBoxes;
534 	GetTblSel( *this, aBoxes );
535 	if( aBoxes.Count() )
536 	{
537 		TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
538 
539 		// dann loesche doch die Spalten
540         bRet = GetDoc()->SplitTbl( aBoxes, bVert, nCnt, bSameHeight );
541 
542 		DELETEZ( pLastCols );
543         DELETEZ( pLastRows );
544 	}
545 	else
546 		bRet = sal_False;
547 	EndAllActionAndCall();
548 	return bRet;
549 }
550 
551 
552 /***********************************************************************
553 #*	Class	   :  SwFEShell
554 #*	Methoden   :  _GetTabCols
555 #*	Datum	   :  MA 30. Nov. 95
556 #*	Update	   :  MA 08. Jan. 97
557 #***********************************************************************/
558 void SwFEShell::_GetTabCols( SwTabCols &rToFill, const SwFrm *pBox ) const
559 {
560 	const SwTabFrm *pTab = pBox->FindTabFrm();
561 	if ( pLastCols )
562 	{
563 		//Paar Kleinigkeiten muessen wir schon noch sicherstellen
564 		sal_Bool bDel = sal_True;
565         if ( pColumnCacheLastTable == pTab->GetTable() )
566 		{
567 			bDel = sal_False;
568             SWRECTFN( pTab )
569 
570             const SwPageFrm* pPage = pTab->FindPageFrm();
571             const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
572                                    (pPage->Frm().*fnRect->fnGetLeft)();
573             const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
574                                     (pPage->Frm().*fnRect->fnGetLeft)();
575 
576             if ( pColumnCacheLastTabFrm != pTab )
577 			{
578 				//Wenn der TabFrm gewechselt hat, brauchen wir bei gleicher
579 				//Breite nur ein wenig shiften.
580                 SWRECTFNX( pColumnCacheLastTabFrm )
581                 if( (pColumnCacheLastTabFrm->Frm().*fnRectX->fnGetWidth)() ==
582                     (pTab->Frm().*fnRect->fnGetWidth)() )
583 				{
584                     pLastCols->SetLeftMin( nLeftMin );
585 
586                     //ASSERT( bVert ||
587                     //        pLastCols->GetLeftMin() == (pTab->Frm().*fnRect->fnGetLeft)(),
588                     //        "GetTabCols: wrong result" )
589 
590                     pColumnCacheLastTabFrm = pTab;
591 				}
592 				else
593 					bDel = sal_True;
594 			}
595 
596 			if ( !bDel &&
597                  pLastCols->GetLeftMin () == (sal_uInt16)nLeftMin &&
598                  pLastCols->GetLeft    () == (sal_uInt16)(pTab->Prt().*fnRect->fnGetLeft)() &&
599                  pLastCols->GetRight   () == (sal_uInt16)(pTab->Prt().*fnRect->fnGetRight)()&&
600                  pLastCols->GetRightMax() == (sal_uInt16)nRightMax - pLastCols->GetLeftMin() )
601 			{
602                 if ( pColumnCacheLastCellFrm != pBox )
603 				{
604 					pTab->GetTable()->GetTabCols( *pLastCols,
605 										((SwCellFrm*)pBox)->GetTabBox(), sal_True);
606                     pColumnCacheLastCellFrm = pBox;
607 				}
608 				rToFill = *pLastCols;
609 			}
610 			else
611 				bDel = sal_True;
612 		}
613 		if ( bDel )
614 			DELETEZ(pLastCols);
615 	}
616 	if ( !pLastCols )
617 	{
618 		GetDoc()->GetTabCols( rToFill, 0, (SwCellFrm*)pBox );
619 
620 		pLastCols   = new SwTabCols( rToFill );
621         pColumnCacheLastTable  = pTab->GetTable();
622         pColumnCacheLastTabFrm = pTab;
623         pColumnCacheLastCellFrm= pBox;
624 	}
625 
626 #if OSL_DEBUG_LEVEL > 1
627     SwTabColsEntry aEntry;
628     for ( sal_uInt16 i = 0; i < rToFill.Count(); ++i )
629     {
630         aEntry = rToFill.GetEntry( i );
631         (void)aEntry;
632     }
633 #endif
634 }
635 
636 /***********************************************************************
637 #*	Class	   :  SwFEShell
638 #*	Methoden   :  _GetTabRows
639 #*	Datum	   :  FME 2004-01-14
640 #*	Update	   :
641 #***********************************************************************/
642 void SwFEShell::_GetTabRows( SwTabCols &rToFill, const SwFrm *pBox ) const
643 {
644 	const SwTabFrm *pTab = pBox->FindTabFrm();
645 	if ( pLastRows )
646 	{
647 		//Paar Kleinigkeiten muessen wir schon noch sicherstellen
648 		sal_Bool bDel = sal_True;
649         if ( pRowCacheLastTable == pTab->GetTable() )
650 		{
651 			bDel = sal_False;
652             SWRECTFN( pTab )
653             const SwPageFrm* pPage = pTab->FindPageFrm();
654             const long nLeftMin  = ( bVert ?
655                                      pTab->GetPrtLeft() - pPage->Frm().Left() :
656                                      pTab->GetPrtTop() - pPage->Frm().Top() );
657             const long nLeft     = bVert ? LONG_MAX : 0;
658             const long nRight    = (pTab->Prt().*fnRect->fnGetHeight)();
659             const long nRightMax = bVert ? nRight : LONG_MAX;
660 
661             if ( pRowCacheLastTabFrm != pTab ||
662                  pRowCacheLastCellFrm != pBox )
663                 bDel = sal_True;
664 
665             if ( !bDel &&
666                  pLastRows->GetLeftMin () == nLeftMin &&
667                  pLastRows->GetLeft    () == nLeft &&
668                  pLastRows->GetRight   () == nRight &&
669                  pLastRows->GetRightMax() == nRightMax )
670             {
671                 rToFill = *pLastRows;
672             }
673             else
674                 bDel = sal_True;
675         }
676 		if ( bDel )
677 			DELETEZ(pLastRows);
678 	}
679 	if ( !pLastRows )
680 	{
681         GetDoc()->GetTabRows( rToFill, 0, (SwCellFrm*)pBox );
682 
683         pLastRows   = new SwTabCols( rToFill );
684         pRowCacheLastTable  = pTab->GetTable();
685         pRowCacheLastTabFrm = pTab;
686         pRowCacheLastCellFrm= pBox;
687 	}
688 }
689 
690 /***********************************************************************
691 #*	Class	   :  SwFEShell
692 #*	Methoden   :  SetTabCols(), GetTabCols()
693 #*	Datum	   :  MA 03. May. 93
694 #*	Update	   :  MA 18. May. 93
695 #***********************************************************************/
696 void SwFEShell::SetTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly )
697 {
698 	SwFrm *pBox = GetCurrFrm();
699 	if( !pBox || !pBox->IsInTab() )
700 		return;
701 
702 	SET_CURR_SHELL( this );
703 	StartAllAction();
704 
705 	do {
706 		pBox = pBox->GetUpper();
707 	} while ( !pBox->IsCellFrm() );
708 
709 	GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
710 	EndAllActionAndCall();
711 }
712 
713 void SwFEShell::GetTabCols( SwTabCols &rToFill ) const
714 {
715 	const SwFrm *pFrm = GetCurrFrm();
716 	if( !pFrm || !pFrm->IsInTab() )
717 		return;
718 	do
719 	{	pFrm = pFrm->GetUpper();
720 	} while ( !pFrm->IsCellFrm() );
721 
722 	_GetTabCols( rToFill, pFrm );
723 }
724 
725 /*-- 19.01.2004 08:56:42---------------------------------------------------
726 
727   -----------------------------------------------------------------------*/
728 void SwFEShell::GetTabRows( SwTabCols &rToFill ) const
729 {
730 	const SwFrm *pFrm = GetCurrFrm();
731 	if( !pFrm || !pFrm->IsInTab() )
732 		return;
733 	do
734 	{	pFrm = pFrm->GetUpper();
735 	} while ( !pFrm->IsCellFrm() );
736 
737 	_GetTabRows( rToFill, pFrm );
738 }
739 /*-- 19.01.2004 08:56:44---------------------------------------------------
740 
741   -----------------------------------------------------------------------*/
742 void SwFEShell::SetTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly )
743 {
744 	SwFrm *pBox = GetCurrFrm();
745 	if( !pBox || !pBox->IsInTab() )
746 		return;
747 
748 	SET_CURR_SHELL( this );
749 	StartAllAction();
750 
751 	do {
752 		pBox = pBox->GetUpper();
753 	} while ( !pBox->IsCellFrm() );
754 
755     GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
756 	EndAllActionAndCall();
757 }
758 /*-- 19.01.2004 08:59:45---------------------------------------------------
759 
760   -----------------------------------------------------------------------*/
761 void SwFEShell::GetMouseTabRows( SwTabCols &rToFill, const Point &rPt ) const
762 {
763     const SwFrm *pBox = GetBox( rPt );
764 	if ( pBox )
765 		_GetTabRows( rToFill, pBox );
766 }
767 /*-- 19.01.2004 08:59:45---------------------------------------------------
768 
769   -----------------------------------------------------------------------*/
770 void SwFEShell::SetMouseTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly, const Point &rPt )
771 {
772 	const SwFrm *pBox = GetBox( rPt );
773 	if( pBox )
774 	{
775 		SET_CURR_SHELL( this );
776 		StartAllAction();
777         GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
778 		EndAllActionAndCall();
779 	}
780 }
781 
782 /***********************************************************************
783  *  Class      :  SwFEShell
784  *  Methoden   :  SetRowSplit(), GetRowSplit()
785  *  Datum      :  FME 13.11.2003
786  ***********************************************************************/
787 
788 void SwFEShell::SetRowSplit( const SwFmtRowSplit& rNew )
789 {
790     SET_CURR_SHELL( this );
791     StartAllAction();
792     GetDoc()->SetRowSplit( *getShellCrsr( false ), rNew );
793     EndAllActionAndCall();
794 }
795 
796 void SwFEShell::GetRowSplit( SwFmtRowSplit*& rpSz ) const
797 {
798     GetDoc()->GetRowSplit( *getShellCrsr( false ), rpSz );
799 }
800 
801 
802 /***********************************************************************
803 #*	Class	   :  SwFEShell
804 #*	Methoden   :  SetRowHeight(), GetRowHeight()
805 #*	Datum	   :  MA 17. May. 93
806 #*	Update	   :  JP 29.04.98
807 #***********************************************************************/
808 
809 void SwFEShell::SetRowHeight( const SwFmtFrmSize &rNew )
810 {
811 	SET_CURR_SHELL( this );
812 	StartAllAction();
813     GetDoc()->SetRowHeight( *getShellCrsr( false ), rNew );
814 	EndAllActionAndCall();
815 }
816 
817 /******************************************************************************
818  *				 SwTwips SwFEShell::GetRowHeight() const
819  ******************************************************************************/
820 void SwFEShell::GetRowHeight( SwFmtFrmSize *& rpSz ) const
821 {
822     GetDoc()->GetRowHeight( *getShellCrsr( false ), rpSz );
823 }
824 
825 sal_Bool SwFEShell::BalanceRowHeight( sal_Bool bTstOnly )
826 {
827 	SET_CURR_SHELL( this );
828 	if( !bTstOnly )
829 		StartAllAction();
830     sal_Bool bRet = GetDoc()->BalanceRowHeight( *getShellCrsr( false ), bTstOnly );
831 	if( !bTstOnly )
832 		EndAllActionAndCall();
833 	return bRet;
834 }
835 
836 /******************************************************************************
837  *				void SwFEShell::SetRowBackground()
838  ******************************************************************************/
839 void SwFEShell::SetRowBackground( const SvxBrushItem &rNew )
840 {
841 	SET_CURR_SHELL( this );
842 	StartAllAction();
843     GetDoc()->SetRowBackground( *getShellCrsr( false ), rNew );
844 	EndAllActionAndCall();
845 }
846 
847 /******************************************************************************
848  *				 SwTwips SwFEShell::GetRowBackground() const
849  ******************************************************************************/
850 sal_Bool SwFEShell::GetRowBackground( SvxBrushItem &rToFill ) const
851 {
852     return GetDoc()->GetRowBackground( *getShellCrsr( false ), rToFill );
853 }
854 
855 /***********************************************************************
856 #*	Class	   :  SwFEShell
857 #*	Methoden   :  SetTabBorders(), GetTabBorders()
858 #*	Datum	   :  MA 18. May. 93
859 #*	Update	   :  JP 29.04.98
860 #***********************************************************************/
861 
862 void SwFEShell::SetTabBorders( const SfxItemSet& rSet )
863 {
864 	SET_CURR_SHELL( this );
865 	StartAllAction();
866     GetDoc()->SetTabBorders( *getShellCrsr( false ), rSet );
867 	EndAllActionAndCall();
868 }
869 
870 void SwFEShell::SetTabLineStyle( const Color* pColor, sal_Bool bSetLine,
871 								 const SvxBorderLine* pBorderLine )
872 {
873 	SET_CURR_SHELL( this );
874 	StartAllAction();
875     GetDoc()->SetTabLineStyle( *getShellCrsr( false ),
876 								pColor, bSetLine, pBorderLine );
877 	EndAllActionAndCall();
878 }
879 
880 void SwFEShell::GetTabBorders( SfxItemSet& rSet ) const
881 {
882     GetDoc()->GetTabBorders( *getShellCrsr( false ), rSet );
883 }
884 
885 
886 /***********************************************************************
887 #*	Class	   :  SwFEShell
888 #*	Methoden   :  SetBoxBackground(), GetBoxBackground()
889 #*	Datum	   :  MA 01. Jun. 93
890 #*	Update	   :  MA 03. Jul. 96
891 #***********************************************************************/
892 void SwFEShell::SetBoxBackground( const SvxBrushItem &rNew )
893 {
894 	SET_CURR_SHELL( this );
895 	StartAllAction();
896     GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
897 	EndAllActionAndCall();
898 }
899 
900 sal_Bool SwFEShell::GetBoxBackground( SvxBrushItem &rToFill ) const
901 {
902     return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
903 }
904 
905 /***********************************************************************
906 #*	Class	   :  SwFEShell
907 #*	Methoden   :  SetBoxDirection(), GetBoxDirection()
908 #*  Datum      :  FME 2004-02-03
909 #*  Update     :  FME 2004-02-03
910 #***********************************************************************/
911 void SwFEShell::SetBoxDirection( const SvxFrameDirectionItem& rNew )
912 {
913 	SET_CURR_SHELL( this );
914 	StartAllAction();
915     GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
916 	EndAllActionAndCall();
917 }
918 
919 sal_Bool SwFEShell::GetBoxDirection( SvxFrameDirectionItem&  rToFill ) const
920 {
921     return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
922 }
923 
924 /***********************************************************************
925 #*	Class	   :  SwFEShell
926 #*	Methoden   :  SetBoxAlign, SetBoxAlign
927 #*	Datum	   :  MA 18. Dec. 96
928 #*	Update	   :  JP 29.04.98
929 #***********************************************************************/
930 void SwFEShell::SetBoxAlign( sal_uInt16 nAlign )
931 {
932 	SET_CURR_SHELL( this );
933 	StartAllAction();
934     GetDoc()->SetBoxAlign( *getShellCrsr( false ), nAlign );
935 	EndAllActionAndCall();
936 }
937 
938 sal_uInt16 SwFEShell::GetBoxAlign() const
939 {
940     return GetDoc()->GetBoxAlign( *getShellCrsr( false ) );
941 }
942 
943 /***********************************************************************
944 #*	Class	   :  SwFEShell
945 #*	Methoden   :  SetTabBackground(), GetTabBackground()
946 #*	Datum	   :  MA 08. Jul. 96
947 #*	Update	   :  MA 08. Jul. 96
948 #***********************************************************************/
949 void SwFEShell::SetTabBackground( const SvxBrushItem &rNew )
950 {
951 	SwFrm *pFrm = GetCurrFrm();
952 	if( !pFrm || !pFrm->IsInTab() )
953 		return;
954 
955 	SET_CURR_SHELL( this );
956 	StartAllAction();
957 	GetDoc()->SetAttr( rNew, *pFrm->ImplFindTabFrm()->GetFmt() );
958 	EndAllAction();	//Kein Call, denn es veraendert sich nichts!
959 	GetDoc()->SetModified();
960 }
961 
962 void SwFEShell::GetTabBackground( SvxBrushItem &rToFill ) const
963 {
964 	SwFrm *pFrm = GetCurrFrm();
965 	if( pFrm && pFrm->IsInTab() )
966 		rToFill = pFrm->ImplFindTabFrm()->GetFmt()->GetBackground();
967 }
968 
969 
970 /***********************************************************************
971 #*	Class	   :  SwFEShell
972 #*	Methoden   :  HasWholeTabSelection()
973 #*	Datum	   :  MA 18. May. 93
974 #*	Update	   :  MA 20. Jul. 93
975 #***********************************************************************/
976 sal_Bool SwFEShell::HasWholeTabSelection() const
977 {
978 	//Ist die ganze Tabelle Selektiert?
979 	if ( IsTableMode() )
980 	{
981 		SwSelBoxes aBoxes;
982 		::GetTblSelCrs( *this, aBoxes );
983 		if( aBoxes.Count() )
984 		{
985 			const SwTableNode *pTblNd = IsCrsrInTbl();
986 			return ( pTblNd && aBoxes[0]->GetSttIdx()-1 == pTblNd->
987 				EndOfSectionNode()->StartOfSectionIndex() &&
988 				aBoxes[aBoxes.Count()-1]->GetSttNd()->EndOfSectionIndex()+1
989 				==  pTblNd->EndOfSectionIndex() );
990 		}
991 	}
992 	return sal_False;
993 }
994 
995 sal_Bool SwFEShell::HasBoxSelection() const
996 {
997 	if(!IsCrsrInTbl())
998 		return sal_False;
999 	//Ist die ganze Tabelle Selektiert?
1000 	if( IsTableMode() )
1001 		return sal_True;
1002 	SwPaM* pPam = GetCrsr();
1003 		// leere Boxen gelten auch ohne Selektion als selektiert
1004 //	if( !pPam->HasMark() )
1005 //		return sal_False;
1006 	sal_Bool bChg = sal_False;
1007 	if( pPam->GetPoint() == pPam->End())
1008 	{
1009 		bChg = sal_True;
1010 		pPam->Exchange();
1011 	}
1012 	SwNode* pNd;
1013 	if( pPam->GetPoint()->nNode.GetIndex() -1 ==
1014 		( pNd = pPam->GetNode())->StartOfSectionIndex() &&
1015 		!pPam->GetPoint()->nContent.GetIndex() &&
1016 		pPam->GetMark()->nNode.GetIndex() + 1 ==
1017 		pNd->EndOfSectionIndex())
1018 	{
1019 			SwNodeIndex aIdx( *pNd->EndOfSectionNode(), -1 );
1020 			SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
1021 			if( !pCNd )
1022 			{
1023 				pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
1024 				ASSERT( pCNd, "kein ContentNode in der Box ??" );
1025 			}
1026 			if( pPam->GetMark()->nContent == pCNd->Len() )
1027 			{
1028 				if( bChg )
1029 					pPam->Exchange();
1030 				return sal_True;
1031 			}
1032 	}
1033 	if( bChg )
1034 		pPam->Exchange();
1035 	return sal_False;
1036 }
1037 
1038 /***********************************************************************
1039 #*	Class	   :  SwFEShell
1040 #*	Methoden   :  ProtectCells(), UnProtectCells()
1041 #*	Datum	   :  MA 20. Jul. 93
1042 #*	Update	   :  JP 25. Sep. 93
1043 #***********************************************************************/
1044 void SwFEShell::ProtectCells()
1045 {
1046     SvxProtectItem aProt( RES_PROTECT );
1047 	aProt.SetCntntProtect( sal_True );
1048 
1049 	SET_CURR_SHELL( this );
1050 	StartAllAction();
1051 
1052     GetDoc()->SetBoxAttr( *getShellCrsr( false ), aProt );
1053 
1054 	if( !IsCrsrReadonly() )
1055 	{
1056 		if( IsTableMode() )
1057 			ClearMark();
1058 		ParkCursorInTab();
1059 	}
1060 	EndAllActionAndCall();
1061 }
1062 
1063 // die Tabellenselektion aufheben
1064 void SwFEShell::UnProtectCells()
1065 {
1066 	SET_CURR_SHELL( this );
1067 	StartAllAction();
1068 
1069 	SwSelBoxes aBoxes;
1070 	if( IsTableMode() )
1071 		::GetTblSelCrs( *this, aBoxes );
1072 	else
1073 	{
1074 		SwFrm *pFrm = GetCurrFrm();
1075 		do {
1076 			pFrm = pFrm->GetUpper();
1077 		} while ( pFrm && !pFrm->IsCellFrm() );
1078 		if( pFrm )
1079 		{
1080 			SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1081 			aBoxes.Insert( pBox );
1082 		}
1083 	}
1084 
1085 	if( aBoxes.Count() )
1086 		GetDoc()->UnProtectCells( aBoxes );
1087 
1088 	EndAllActionAndCall();
1089 }
1090 
1091 void SwFEShell::UnProtectTbls()
1092 {
1093 	SET_CURR_SHELL( this );
1094 	StartAllAction();
1095 	GetDoc()->UnProtectTbls( *GetCrsr() );
1096 	EndAllActionAndCall();
1097 }
1098 
1099 sal_Bool SwFEShell::HasTblAnyProtection( const String* pTblName,
1100 									sal_Bool* pFullTblProtection )
1101 {
1102 	return GetDoc()->HasTblAnyProtection( GetCrsr()->GetPoint(), pTblName,
1103 										pFullTblProtection );
1104 }
1105 
1106 sal_Bool SwFEShell::CanUnProtectCells() const
1107 {
1108 	sal_Bool bUnProtectAvailable = sal_False;
1109 	const SwTableNode *pTblNd = IsCrsrInTbl();
1110 	if( pTblNd && !pTblNd->IsProtect() )
1111 	{
1112 		SwSelBoxes aBoxes;
1113 		if( IsTableMode() )
1114 			::GetTblSelCrs( *this, aBoxes );
1115 		else
1116 		{
1117 			SwFrm *pFrm = GetCurrFrm();
1118 			do {
1119 				pFrm = pFrm->GetUpper();
1120 			} while ( pFrm && !pFrm->IsCellFrm() );
1121 			if( pFrm )
1122 			{
1123 				SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1124 				aBoxes.Insert( pBox );
1125 			}
1126 		}
1127 		if( aBoxes.Count() )
1128 			bUnProtectAvailable = ::HasProtectedCells( aBoxes );
1129 	}
1130 	return bUnProtectAvailable;
1131 }
1132 
1133 /***********************************************************************
1134 #*  Class      :  SwFEShell
1135 #*  Methoden   :  GetRowsToRepeat(), SetRowsToRepeat()
1136 #***********************************************************************/
1137 sal_uInt16 SwFEShell::GetRowsToRepeat() const
1138 {
1139     const SwFrm *pFrm = GetCurrFrm();
1140     const SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
1141     if( pTab )
1142         return pTab->GetTable()->GetRowsToRepeat();
1143     return 0;
1144 }
1145 
1146 void SwFEShell::SetRowsToRepeat( sal_uInt16 nSet )
1147 {
1148     SwFrm    *pFrm = GetCurrFrm();
1149     SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
1150     if( pTab && pTab->GetTable()->GetRowsToRepeat() != nSet )
1151     {
1152         SwWait aWait( *GetDoc()->GetDocShell(), sal_True );
1153         SET_CURR_SHELL( this );
1154         StartAllAction();
1155         GetDoc()->SetRowsToRepeat( *pTab->GetTable(), nSet );
1156         EndAllActionAndCall();
1157     }
1158 }
1159 /*-- 30.06.2004 08:46:35---------------------------------------------------
1160     returns the number of rows consecutively selected from top
1161   -----------------------------------------------------------------------*/
1162 sal_uInt16 lcl_GetRowNumber( const SwPosition& rPos )
1163 {
1164     sal_uInt16 nRet = USHRT_MAX;
1165     Point aTmpPt;
1166     const SwCntntNode *pNd;
1167     const SwCntntFrm *pFrm;
1168 
1169     if( 0 != ( pNd = rPos.nNode.GetNode().GetCntntNode() ))
1170         pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, &rPos, sal_False );
1171     else
1172         pFrm = 0;
1173 
1174     if ( pFrm && pFrm->IsInTab() )
1175     {
1176         const SwFrm* pRow = pFrm->GetUpper();
1177         while ( !pRow->GetUpper()->IsTabFrm() )
1178             pRow = pRow->GetUpper();
1179 
1180         const SwTabFrm* pTabFrm = (const SwTabFrm*)pRow->GetUpper();
1181         const SwTableLine* pTabLine = static_cast<const SwRowFrm*>(pRow)->GetTabLine();
1182 
1183         sal_uInt16 nI = 0;
1184         while ( nI < pTabFrm->GetTable()->GetTabLines().Count() )
1185         {
1186             if ( pTabFrm->GetTable()->GetTabLines()[ nI ] == pTabLine )
1187             {
1188                 nRet = nI;
1189                 break;
1190             }
1191             ++nI;
1192         }
1193     }
1194 
1195     return nRet;
1196 }
1197 sal_uInt16 SwFEShell::GetRowSelectionFromTop() const
1198 {
1199     sal_uInt16 nRet = 0;
1200     const SwPaM* pPaM = IsTableMode() ? GetTableCrsr() : _GetCrsr();
1201     const sal_uInt16 nPtLine = lcl_GetRowNumber( *pPaM->GetPoint() );
1202 
1203     if ( !IsTableMode() )
1204     {
1205         nRet = 0 == nPtLine ? 1 : 0;
1206     }
1207     else
1208     {
1209         const sal_uInt16 nMkLine = lcl_GetRowNumber( *pPaM->GetMark() );
1210 
1211         if ( ( nPtLine == 0 && nMkLine != USHRT_MAX ) ||
1212              ( nMkLine == 0 && nPtLine != USHRT_MAX ) )
1213         {
1214             nRet = Max( nPtLine, nMkLine ) + 1;
1215         }
1216     }
1217 
1218     return nRet;
1219 }
1220 
1221 /*
1222  * 1. case: bRepeat = true
1223  * returns true if the current frame is located inside a table headline in
1224  * a follow frame
1225  *
1226  * 2. case: bRepeat = false
1227  * returns true if the current frame is localed inside a table headline OR
1228  * inside the first line of a table!!!
1229  */
1230 sal_Bool SwFEShell::CheckHeadline( bool bRepeat ) const
1231 {
1232 	sal_Bool bRet = sal_False;
1233 	if ( !IsTableMode() )
1234 	{
1235         SwFrm *pFrm = GetCurrFrm();  // DONE MULTIIHEADER
1236         if ( pFrm && pFrm->IsInTab() )
1237         {
1238             SwTabFrm* pTab = pFrm->FindTabFrm();
1239             if ( bRepeat )
1240             {
1241                 bRet = pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
1242             }
1243             else
1244             {
1245                 bRet =  ((SwLayoutFrm*)pTab->Lower())->IsAnLower( pFrm ) ||
1246                         pTab->IsInHeadline( *pFrm );
1247             }
1248         }
1249 	}
1250 	return bRet;
1251 }
1252 
1253 /***********************************************************************
1254 #*	Class	   :  SwFEShell
1255 #*	Methoden   :  AdjustCellWidth()
1256 #*	Datum	   :  MA 20. Feb. 95
1257 #*	Update	   :  MA 27. Jul. 95
1258 #***********************************************************************/
1259 
1260 void SwFEShell::AdjustCellWidth( sal_Bool bBalance )
1261 {
1262 	SET_CURR_SHELL( this );
1263 	StartAllAction();
1264 
1265 	//WarteCrsr immer einschalten, weil sich im vorraus nicht so recht
1266 	//ermitteln laesst wieviel Inhalt betroffen ist.
1267 	TblWait aWait( USHRT_MAX, 0, *GetDoc()->GetDocShell() );
1268 
1269     GetDoc()->AdjustCellWidth( *getShellCrsr( false ), bBalance );
1270 	EndAllActionAndCall();
1271 }
1272 
1273 sal_Bool SwFEShell::IsAdjustCellWidthAllowed( sal_Bool bBalance ) const
1274 {
1275 	//Es muss mindestens eine Zelle mit Inhalt in der Selektion enthalten
1276 	//sein.
1277 
1278 	SwFrm *pFrm = GetCurrFrm();
1279 	if( !pFrm || !pFrm->IsInTab() )
1280 		return sal_False;
1281 
1282 	SwSelBoxes aBoxes;
1283 	::GetTblSelCrs( *this, aBoxes );
1284 
1285 	if ( bBalance )
1286 		return aBoxes.Count() > 1;
1287 
1288 	if ( !aBoxes.Count() )
1289 	{
1290 		do
1291 		{	pFrm = pFrm->GetUpper();
1292 		} while ( !pFrm->IsCellFrm() );
1293 		SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1294 		aBoxes.Insert( pBox );
1295 	}
1296 
1297 	for ( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
1298 	{
1299 		SwTableBox *pBox = aBoxes[i];
1300 		if ( pBox->GetSttNd() )
1301 		{
1302 			SwNodeIndex aIdx( *pBox->GetSttNd(), 1 );
1303 			SwTxtNode* pCNd = aIdx.GetNode().GetTxtNode();
1304 			if( !pCNd )
1305 				pCNd = (SwTxtNode*)GetDoc()->GetNodes().GoNext( &aIdx );
1306 
1307 			while ( pCNd )
1308 			{
1309 				if ( pCNd->GetTxt().Len() )
1310 					return sal_True;
1311 				++aIdx;
1312                 pCNd = aIdx.GetNode().GetTxtNode();
1313             }
1314         }
1315     }
1316 	return sal_False;
1317 }
1318 
1319 	// AutoFormat fuer die Tabelle/TabellenSelection
1320 sal_Bool SwFEShell::SetTableAutoFmt( const SwTableAutoFmt& rNew )
1321 {
1322 	SwTableNode *pTblNd = (SwTableNode*)IsCrsrInTbl();
1323 	if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
1324 		return sal_False;
1325 
1326 	SwSelBoxes aBoxes;
1327 
1328 	if ( !IsTableMode() )		// falls Crsr noch nicht akt. sind
1329 		GetCrsr();
1330 
1331 	// gesamte Tabelle oder nur auf die akt. Selektion
1332 	if( IsTableMode() )
1333 		::GetTblSelCrs( *this, aBoxes );
1334 	else
1335 	{
1336 		const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
1337 		for( sal_uInt16 n = 0; n < rTBoxes.Count(); ++n )
1338 		{
1339 			SwTableBox* pBox = rTBoxes[ n ];
1340 			aBoxes.Insert( pBox );
1341 		}
1342 	}
1343 
1344 	sal_Bool bRet;
1345 	if( aBoxes.Count() )
1346 	{
1347 		SET_CURR_SHELL( this );
1348 		StartAllAction();
1349 		bRet = GetDoc()->SetTableAutoFmt( aBoxes, rNew );
1350 		DELETEZ( pLastCols );
1351         DELETEZ( pLastRows );
1352         EndAllActionAndCall();
1353 	}
1354 	else
1355 		bRet = sal_False;
1356 	return bRet;
1357 }
1358 
1359 sal_Bool SwFEShell::GetTableAutoFmt( SwTableAutoFmt& rGet )
1360 {
1361 	const SwTableNode *pTblNd = IsCrsrInTbl();
1362 	if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
1363 		return sal_False;
1364 
1365 	SwSelBoxes aBoxes;
1366 
1367 	if ( !IsTableMode() )		// falls Crsr noch nicht akt. sind
1368 		GetCrsr();
1369 
1370 	// gesamte Tabelle oder nur auf die akt. Selektion
1371 	if( IsTableMode() )
1372 		::GetTblSelCrs( *this, aBoxes );
1373 	else
1374 	{
1375 		const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
1376 		for( sal_uInt16 n = 0; n < rTBoxes.Count(); ++n )
1377 		{
1378 			SwTableBox* pBox = rTBoxes[ n ];
1379 			aBoxes.Insert( pBox );
1380 		}
1381 	}
1382 
1383 	return GetDoc()->GetTableAutoFmt( aBoxes, rGet );
1384 }
1385 
1386 /***********************************************************************
1387 #*	Class	   :  SwFEShell
1388 #*	Methoden   :  DeleteTblSel()
1389 #*	Datum	   :  MA 03. May. 93
1390 #*	Update	   :  MA 19. Apr. 95
1391 #***********************************************************************/
1392 sal_Bool SwFEShell::DeleteTblSel()
1393 {
1394 	// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
1395 	SwFrm *pFrm = GetCurrFrm();
1396 	if( !pFrm || !pFrm->IsInTab() )
1397 		return sal_False;
1398 
1399 	if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
1400 	{
1401 		ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
1402 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
1403 		return sal_False;
1404 	}
1405 
1406 	SET_CURR_SHELL( this );
1407 	StartAllAction();
1408 
1409 	// lasse ueber das Layout die Boxen suchen
1410 	sal_Bool bRet;
1411 	SwSelBoxes aBoxes;
1412 	GetTblSelCrs( *this, aBoxes );
1413 	if( aBoxes.Count() )
1414 	{
1415 		TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
1416 
1417 		// die Crsr muessen noch aus dem Loesch Bereich entfernt
1418 		// werden. Setze sie immer hinter/auf die Tabelle; ueber die
1419 		// Dokument-Position werden sie dann immer an die alte Position gesetzt.
1420 		while( !pFrm->IsCellFrm() )
1421 			pFrm = pFrm->GetUpper();
1422 		ParkCrsr( SwNodeIndex( *((SwCellFrm*)pFrm)->GetTabBox()->GetSttNd() ));
1423 
1424 		bRet = GetDoc()->DeleteRowCol( aBoxes );
1425 
1426 		DELETEZ( pLastCols );
1427         DELETEZ( pLastRows );
1428     }
1429 	else
1430 		bRet = sal_False;
1431 	EndAllActionAndCall();
1432 	return bRet;
1433 }
1434 
1435 /*************************************************************************
1436 |*
1437 |*	SwFEShell::GetCurTabColNum()
1438 |*
1439 |*	Ersterstellung		MA 03. Feb. 95
1440 |*	Letzte Aenderung	MA 21. May. 95
1441 |
1442 |*************************************************************************/
1443 sal_uInt16 SwFEShell::GetCurTabColNum() const
1444 {
1445 	//!!!GetCurMouseTabColNum() mitpflegen!!!!
1446 	sal_uInt16 nRet = 0;
1447 
1448 	SwFrm *pFrm = GetCurrFrm();
1449 	ASSERT( pFrm, "Crsr geparkt?" );
1450 
1451 	// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
1452 	if( pFrm && pFrm->IsInTab() )
1453 	{
1454 		do {			// JP 26.09.95: warum mit dem CntntFrame und nicht mit
1455 						// 				dem CellFrame vergleichen????
1456 			pFrm = pFrm->GetUpper();
1457 		} while ( !pFrm->IsCellFrm() );
1458         SWRECTFN( pFrm )
1459 
1460         const SwPageFrm* pPage = pFrm->FindPageFrm();
1461 
1462 		//TabCols besorgen, den nur ueber diese erreichen wir die Position.
1463 		SwTabCols aTabCols;
1464 		GetTabCols( aTabCols );
1465 
1466         if( pFrm->FindTabFrm()->IsRightToLeft() )
1467 		{
1468             long nX = (pFrm->Frm().*fnRect->fnGetRight)() - (pPage->Frm().*fnRect->fnGetLeft)();
1469 
1470 			const long nRight = aTabCols.GetLeftMin() + aTabCols.GetRight();;
1471 
1472             if ( !::IsSame( nX, nRight ) )
1473 			{
1474                 nX = nRight - nX + aTabCols.GetLeft();
1475 				for ( sal_uInt16 i = 0; i < aTabCols.Count(); ++i )
1476                     if ( ::IsSame( nX, aTabCols[i] ) )
1477 					{
1478 						nRet = i + 1;
1479 						break;
1480 					}
1481 			}
1482 		}
1483 		else
1484 		{
1485             const long nX = (pFrm->Frm().*fnRect->fnGetLeft)() -
1486                             (pPage->Frm().*fnRect->fnGetLeft)();
1487 
1488             const long nLeft = aTabCols.GetLeftMin();
1489 
1490 			if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
1491 			{
1492 				for ( sal_uInt16 i = 0; i < aTabCols.Count(); ++i )
1493 					if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
1494 					{
1495 						nRet = i + 1;
1496 						break;
1497 					}
1498 			}
1499 		}
1500 	}
1501 	return nRet;
1502 }
1503 
1504 /*************************************************************************
1505 |*
1506 |*	SwFEShell::GetBox()
1507 |*
1508 |*	Ersterstellung		MA 22. Jun. 95
1509 |*	Letzte Aenderung	MA 21. Nov. 96
1510 |*
1511 |*************************************************************************/
1512 
1513 const SwFrm *lcl_FindFrmInTab( const SwLayoutFrm *pLay, const Point &rPt, SwTwips nFuzzy )
1514 {
1515 	const SwFrm *pFrm = pLay->Lower();
1516 
1517     while( pFrm && pLay->IsAnLower( pFrm ) )
1518 	{
1519         if ( pFrm->Frm().IsNear( rPt, nFuzzy ) )
1520 		{
1521 			if ( pFrm->IsLayoutFrm() )
1522 			{
1523 				const SwFrm *pTmp = ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, rPt, nFuzzy );
1524 				if ( pTmp )
1525 					return pTmp;
1526 			}
1527 
1528             return pFrm;
1529         }
1530 
1531 		pFrm = pFrm->FindNext();
1532     }
1533 
1534 	return 0;
1535 }
1536 
1537 const SwCellFrm *lcl_FindFrm( const SwLayoutFrm *pLay, const Point &rPt,
1538                               SwTwips nFuzzy, bool* pbRow, bool* pbCol )
1539 {
1540     // bMouseMoveRowCols :
1541     // Method is called for
1542     // - Moving columns/rows with the mouse or
1543     // - Enhanced table selection
1544     const bool bMouseMoveRowCols = 0 == pbCol;
1545 
1546     bool bCloseToRow = false;
1547     bool bCloseToCol = false;
1548 
1549     const SwFrm *pFrm = pLay->ContainsCntnt();
1550     const SwFrm* pRet = 0;
1551 
1552     if ( pFrm )
1553 	{
1554 		do
1555 		{
1556 			if ( pFrm->IsInTab() )
1557 				pFrm = ((SwFrm*)pFrm)->ImplFindTabFrm();
1558 
1559             if ( pFrm->IsTabFrm() )
1560 			{
1561                 Point aPt( rPt );
1562                 bool bSearchForFrmInTab = true;
1563                 SwTwips nTmpFuzzy = nFuzzy;
1564 
1565                 if ( !bMouseMoveRowCols )
1566                 {
1567                     // We ignore nested tables for the enhanced table selection:
1568                     while ( pFrm->GetUpper()->IsInTab() )
1569                         pFrm = pFrm->GetUpper()->FindTabFrm();
1570 
1571                     // We first check if the given point is 'close' to the left or top
1572                     // border of the table frame:
1573                     ASSERT( pFrm, "Nested table frame without outer table" )
1574                     SWRECTFN( pFrm )
1575                     const bool bRTL = pFrm->IsRightToLeft();
1576 
1577                     SwRect aTabRect = pFrm->Prt();
1578                     aTabRect.Pos() += pFrm->Frm().Pos();
1579 
1580                     const SwTwips nLeft = bRTL ?
1581                                           (aTabRect.*fnRect->fnGetRight)() :
1582                                           (aTabRect.*fnRect->fnGetLeft)();
1583                     const SwTwips nTop  = (aTabRect.*fnRect->fnGetTop)();
1584 
1585                     SwTwips& rPointX = bVert ? aPt.Y() : aPt.X();
1586                     SwTwips& rPointY = bVert ? aPt.X() : aPt.Y();
1587 
1588                     const SwTwips nXDiff = (*fnRect->fnXDiff)( nLeft, rPointX ) * ( bRTL ? (-1) : 1 );
1589                     const SwTwips nYDiff = (*fnRect->fnYDiff)( nTop, rPointY );
1590 
1591                     bCloseToRow = nXDiff >= 0 && nXDiff < nFuzzy;
1592                     bCloseToCol = nYDiff >= 0 && nYDiff < nFuzzy;
1593 
1594                     if ( bCloseToCol && 2 * nYDiff > nFuzzy )
1595                     {
1596                         const SwFrm* pPrev = pFrm->GetPrev();
1597                         if ( pPrev )
1598                         {
1599                             SwRect aPrevRect = pPrev->Prt();
1600                             aPrevRect.Pos() += pPrev->Frm().Pos();
1601 
1602                             if( aPrevRect.IsInside( rPt ) )
1603                             {
1604                                 bCloseToCol = false;
1605                             }
1606                         }
1607 
1608                     }
1609 
1610                     // If we found the point to be 'close' to the left or top border
1611                     // of the table frame, we adjust the point to be on that border:
1612                     if ( bCloseToRow && bCloseToCol )
1613                         aPt = bRTL ? aTabRect.TopRight() : (aTabRect.*fnRect->fnGetPos)();
1614                     else if ( bCloseToRow )
1615                         rPointX = nLeft;
1616                     else if ( bCloseToCol )
1617                         rPointY = nTop;
1618 
1619                     if ( !bCloseToRow && !bCloseToCol )
1620                         bSearchForFrmInTab = false;
1621 
1622                     // Since the point has been adjusted, we call lcl_FindFrmInTab()
1623                     // with a fuzzy value of 1:
1624                     nTmpFuzzy = 1;
1625                 }
1626 
1627                 const SwFrm* pTmp = bSearchForFrmInTab ?
1628                                     ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, aPt, nTmpFuzzy ) :
1629                                     0;
1630 
1631                 if ( pTmp )
1632                 {
1633                     pFrm = pTmp;
1634                     break;
1635                 }
1636 			}
1637 			pFrm = pFrm->FindNextCnt();
1638 
1639 		} while ( pFrm && pLay->IsAnLower( pFrm ) );
1640 	}
1641 
1642     if ( pFrm && pFrm->IsInTab() && pLay->IsAnLower( pFrm ) )
1643 	{
1644 		do
1645         {
1646             // We allow mouse drag of table borders within nested tables,
1647             // but disallow hotspot selection of nested tables.
1648             if ( bMouseMoveRowCols )
1649             {
1650                 // find the next cell frame
1651                 while ( pFrm && !pFrm->IsCellFrm() )
1652                     pFrm = pFrm->GetUpper();
1653             }
1654             else
1655             {
1656                 // find the most upper cell frame:
1657                 while ( pFrm &&
1658                         ( !pFrm->IsCellFrm() ||
1659                           !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
1660                            pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
1661                     pFrm = pFrm->GetUpper();
1662             }
1663 
1664             if ( pFrm ) // Note: this condition should be the same like the while condition!!!
1665 			{
1666                 // --> FME 2004-07-30 #i32329# Enhanced table selection
1667                 // used for hotspot selection of tab/cols/rows
1668                 if ( !bMouseMoveRowCols )
1669                 {
1670 
1671                     ASSERT( pbCol && pbRow, "pbCol or pbRow missing" )
1672 
1673                     if ( bCloseToRow || bCloseToCol )
1674                     {
1675                         *pbRow = bCloseToRow;
1676                         *pbCol = bCloseToCol;
1677                         pRet = pFrm;
1678                         break;
1679                     }
1680                 }
1681                 // <--
1682                 else
1683                 {
1684                     // used for mouse move of columns/rows
1685                     const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
1686                     SwRect aTabRect = pTabFrm->Prt();
1687                     aTabRect.Pos() += pTabFrm->Frm().Pos();
1688 
1689                     SWRECTFN( pTabFrm )
1690 
1691                     const SwTwips nTabTop  = (aTabRect.*fnRect->fnGetTop)();
1692                     const SwTwips nMouseTop  = bVert ? rPt.X() : rPt.Y();
1693 
1694                     // Do not allow to drag upper table border:
1695                     if ( !::IsSame( nTabTop, nMouseTop ) )
1696                     {
1697                         if ( ::IsSame( pFrm->Frm().Left(), rPt.X() ) ||
1698                              ::IsSame( pFrm->Frm().Right(),rPt.X() ) )
1699                         {
1700                             if ( pbRow ) *pbRow = false;
1701                             pRet = pFrm;
1702                             break;
1703                         }
1704                         if ( ::IsSame( pFrm->Frm().Top(), rPt.Y() ) ||
1705                              ::IsSame( pFrm->Frm().Bottom(),rPt.Y() ) )
1706                         {
1707                             if ( pbRow ) *pbRow = true;
1708                             pRet = pFrm;
1709                             break;
1710                         }
1711                     }
1712                 }
1713 
1714                 pFrm = pFrm->GetUpper();
1715 			}
1716 		} while ( pFrm );
1717 	}
1718 
1719     // robust:
1720     ASSERT( !pRet || pRet->IsCellFrm(), "lcl_FindFrm() is supposed to find a cell frame!" )
1721     return pRet && pRet->IsCellFrm() ? static_cast<const SwCellFrm*>(pRet) : 0;
1722 }
1723 
1724 //
1725 // pbCol  = 0 => Used for moving table rows/cols with mouse
1726 // pbCol != 0 => Used for selecting table/rows/cols
1727 //
1728 #define ENHANCED_TABLE_SELECTION_FUZZY 10
1729 
1730 const SwFrm* SwFEShell::GetBox( const Point &rPt, bool* pbRow, bool* pbCol ) const
1731 {
1732 	const SwPageFrm *pPage = (SwPageFrm*)GetLayout()->Lower();
1733 	Window* pOutWin = GetWin();
1734     SwTwips nFuzzy = COLFUZZY;
1735 	if( pOutWin )
1736 	{
1737         // --> FME 2004-07-30 #i32329# Enhanced table selection
1738         SwTwips nSize = pbCol ? ENHANCED_TABLE_SELECTION_FUZZY : RULER_MOUSE_MARGINWIDTH;
1739         // <--
1740         Size aTmp( nSize, nSize );
1741         aTmp = pOutWin->PixelToLogic( aTmp );
1742         nFuzzy = aTmp.Width();
1743 	}
1744 
1745     while ( pPage && !pPage->Frm().IsNear( rPt, nFuzzy ) )
1746 		pPage = (SwPageFrm*)pPage->GetNext();
1747 
1748     const SwCellFrm *pFrm = 0;
1749 	if ( pPage )
1750 	{
1751 		//Per GetCrsrOfst oder GetCntntPos koennen wir hier die Box leider
1752 		//nicht suchen. Das wuerde zu einem Performance-Zusammenbruch bei
1753 		//Dokumenten mit vielen Absaetzen/Tabellen auf einer Seite fuehren
1754 		//(BrowseMode!)
1755 
1756 		//Erst die Flys checken.
1757 		if ( pPage->GetSortedObjs() )
1758 		{
1759 			for ( sal_uInt16 i = 0; !pFrm && i < pPage->GetSortedObjs()->Count(); ++i )
1760 			{
1761                 SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
1762                 if ( pObj->ISA(SwFlyFrm) )
1763 				{
1764                     pFrm = lcl_FindFrm( static_cast<SwFlyFrm*>(pObj),
1765                                         rPt, nFuzzy, pbRow, pbCol );
1766 				}
1767             }
1768 		}
1769 		const SwLayoutFrm *pLay = (SwLayoutFrm*)pPage->Lower();
1770 		while ( pLay && !pFrm )
1771 		{
1772             pFrm = lcl_FindFrm( pLay, rPt, nFuzzy, pbRow, pbCol );
1773             pLay = (SwLayoutFrm*)pLay->GetNext();
1774 		}
1775 	}
1776 	return pFrm;
1777 }
1778 
1779 /* Helper function*/
1780 /* calculated the distance between Point rC and Line Segment (rA, rB) */
1781 double lcl_DistancePoint2Segment( const Point& rA, const Point& rB, const Point& rC )
1782 {
1783     double nRet = 0;
1784 
1785     const basegfx::B2DVector aBC( rC.X() - rB.X(), rC.Y() - rB.Y() );
1786     const basegfx::B2DVector aAB( rB.X() - rA.X(), rB.Y() - rA.Y() );
1787     const double nDot1 = aBC.scalar( aAB );
1788 
1789     if ( nDot1 > 0 ) // check outside case 1
1790         nRet = aBC.getLength();
1791     else
1792     {
1793         const basegfx::B2DVector aAC( rC.X() - rA.X(), rC.Y() - rA.Y() );
1794         const basegfx::B2DVector aBA( rA.X() - rB.X(), rA.Y() - rB.Y() );
1795         const double nDot2 = aAC.scalar( aBA );
1796 
1797         if ( nDot2 > 0 ) // check outside case 2
1798             nRet = aAC.getLength();
1799         else
1800         {
1801             const double nDiv = aAB.getLength();
1802             nRet = nDiv ? aAB.cross( aAC ) / nDiv : 0;
1803         }
1804     }
1805 
1806     return Abs(nRet);
1807 }
1808 
1809 /* Helper function*/
1810 Point lcl_ProjectOntoClosestTableFrm( const SwTabFrm& rTab, const Point& rPoint, bool bRowDrag )
1811 {
1812     Point aRet( rPoint );
1813     const SwTabFrm* pCurrentTab = &rTab;
1814     const bool bVert = pCurrentTab->IsVertical();
1815     const bool bRTL = pCurrentTab->IsRightToLeft();
1816 
1817     // Western Layout:
1818     // bRowDrag = true => compare to left border of table
1819     // bRowDrag = false => compare to top border of table
1820 
1821     // Asian Layout:
1822     // bRowDrag = true => compare to right border of table
1823     // bRowDrag = false => compare to top border of table
1824 
1825     // RTL Layout:
1826     // bRowDrag = true => compare to right border of table
1827     // bRowDrag = false => compare to top border of table
1828     bool bLeft = false;
1829     bool bRight = false;
1830 
1831     if ( bRowDrag )
1832     {
1833         if ( bVert || bRTL )
1834             bRight = true;
1835         else
1836             bLeft = true;
1837     }
1838 
1839     // used to find the minimal distance
1840     double nMin = -1;
1841     Point aMin1;
1842     Point aMin2;
1843 
1844     Point aS1;
1845     Point aS2;
1846 
1847     while ( pCurrentTab )
1848     {
1849         SwRect aTabRect( pCurrentTab->Prt() );
1850         aTabRect += pCurrentTab->Frm().Pos();
1851 
1852         if ( bLeft )
1853         {
1854             // distance to left table border
1855             aS1 = aTabRect.TopLeft();
1856             aS2 = aTabRect.BottomLeft();
1857         }
1858         else if ( bRight )
1859         {
1860             // distance to right table border
1861             aS1 = aTabRect.TopRight();
1862             aS2 = aTabRect.BottomRight();
1863         }
1864         else //if ( bTop )
1865         {
1866             // distance to top table border
1867             aS1 = aTabRect.TopLeft();
1868             aS2 = aTabRect.TopRight();
1869         }
1870 
1871         const double nDist = lcl_DistancePoint2Segment( aS1, aS2, rPoint );
1872 
1873         if ( nDist < nMin || -1 == nMin )
1874         {
1875             aMin1 = aS1;
1876             aMin2 = aS2;
1877             nMin = nDist;
1878         }
1879 
1880         pCurrentTab = pCurrentTab->GetFollow();
1881     }
1882 
1883     // project onto closest line:
1884     if ( bLeft || bRight )
1885     {
1886         aRet.X() = aMin1.X();
1887         if ( aRet.Y() > aMin2.Y() )
1888             aRet.Y() = aMin2.Y();
1889         else if ( aRet.Y() < aMin1.Y() )
1890             aRet.Y() = aMin1.Y();
1891     }
1892     else //if ( bTop )
1893     {
1894         aRet.Y() = aMin1.Y();
1895         if ( aRet.X() > aMin2.X() )
1896             aRet.X() = aMin2.X();
1897         else if ( aRet.X() < aMin1.X() )
1898             aRet.X() = aMin1.X();
1899     }
1900 
1901     return aRet;
1902 }
1903 
1904 // --> FME 2004-07-30 #i32329# Enhanced table selection
1905 bool SwFEShell::SelTblRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag )
1906 {
1907     bool bRet = false;
1908     Point aEndPt;
1909     if ( pEnd )
1910         aEndPt = *pEnd;
1911 
1912     SwPosition*  ppPos[2] = { 0, 0 };
1913     Point        paPt [2] = { rPt, aEndPt };
1914     bool         pbRow[2] = { 0, 0 };
1915     bool         pbCol[2] = { 0, 0 };
1916 
1917     // pEnd is set during dragging.
1918     for ( sal_uInt16 i = 0; i < ( pEnd ? 2 : 1 ); ++i )
1919     {
1920         const SwCellFrm* pFrm =
1921              static_cast<const SwCellFrm*>(GetBox( paPt[i], &pbRow[i], &pbCol[i] ) );
1922 
1923         if( pFrm )
1924         {
1925             while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
1926                 pFrm = static_cast<const SwCellFrm*>( static_cast<const SwLayoutFrm*>( pFrm->Lower() )->Lower() );
1927             if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
1928                 pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
1929                 pFrm = 0;
1930         }
1931 
1932         if ( pFrm )
1933         {
1934             const SwCntntFrm* pCntnt = ::GetCellCntnt( *pFrm );
1935 
1936             if ( pCntnt && pCntnt->IsTxtFrm() )
1937             {
1938                 ppPos[i] = new SwPosition( *pCntnt->GetNode() );
1939                 ppPos[i]->nContent.Assign( const_cast<SwCntntNode*>(pCntnt->GetNode()), 0 );
1940 
1941                 // paPt[i] will not be used any longer, now we use it to store
1942                 // a position inside the content frame
1943                 paPt[i] = pCntnt->Frm().Center();
1944             }
1945         }
1946 
1947         // no calculation of end frame if start frame has not been found.
1948         if ( 1 == i || !ppPos[0] || !pEnd )
1949             break;
1950 
1951         // find 'closest' table frame to pEnd:
1952         const SwTabFrm* pCurrentTab = pFrm->FindTabFrm();
1953         if ( pCurrentTab->IsFollow() )
1954             pCurrentTab = pCurrentTab->FindMaster( true );
1955 
1956         const Point aProjection = lcl_ProjectOntoClosestTableFrm( *pCurrentTab, *pEnd, bRowDrag );
1957         paPt[1] = aProjection;
1958     }
1959 
1960     if ( ppPos[0] )
1961     {
1962         SwShellCrsr* pCrsr = _GetCrsr();
1963         SwCrsrSaveState aSaveState( *pCrsr );
1964         SwPosition aOldPos( *pCrsr->GetPoint() );
1965 
1966         pCrsr->DeleteMark();
1967         *pCrsr->GetPoint() = *ppPos[0];
1968         pCrsr->GetPtPos() = paPt[0];
1969 
1970         if ( !pCrsr->IsInProtectTable( sal_False, sal_True ) )
1971         {
1972             bool bNewSelection = true;
1973 
1974             if ( ppPos[1] )
1975             {
1976                 if ( ppPos[1]->nNode.GetNode().StartOfSectionNode() !=
1977                      aOldPos.nNode.GetNode().StartOfSectionNode() )
1978                 {
1979                     pCrsr->SetMark();
1980                     SwCrsrSaveState aSaveState2( *pCrsr );
1981                     *pCrsr->GetPoint() = *ppPos[1];
1982                     pCrsr->GetPtPos() = paPt[1];
1983 
1984                     if ( pCrsr->IsInProtectTable( sal_False, sal_False ) )
1985                     {
1986                         pCrsr->RestoreSavePos();
1987                         bNewSelection = false;
1988                     }
1989                 }
1990                 else
1991                 {
1992                     pCrsr->RestoreSavePos();
1993                     bNewSelection = false;
1994                 }
1995             }
1996 
1997             if ( bNewSelection )
1998             {
1999                 // --> FME 2004-10-20 #i35543# SelTblRowCol should remove any existing
2000                 // table cursor:
2001                 if ( IsTableMode() )
2002                     TblCrsrToCursor();
2003                 // <--
2004 
2005                 if ( pbRow[0] && pbCol[0] )
2006                     bRet = SwCrsrShell::SelTbl();
2007                 else if ( pbRow[0] )
2008                     bRet = SwCrsrShell::_SelTblRowOrCol( true, true );
2009                 else if ( pbCol[0] )
2010                     bRet = SwCrsrShell::_SelTblRowOrCol( false, true );
2011             }
2012             else
2013                 bRet = true;
2014         }
2015 
2016         delete ppPos[0];
2017         delete ppPos[1];
2018     }
2019 
2020     return bRet;
2021 }
2022 // <--
2023 
2024 
2025 /*************************************************************************
2026 |*
2027 |*  SwFEShell::WhichMouseTabCol()
2028 |*
2029 |*	Ersterstellung		MA 22. Jun. 95
2030 |*  Last change         AMA 12. Jun. 02
2031 |
2032 |*************************************************************************/
2033 sal_uInt8 SwFEShell::WhichMouseTabCol( const Point &rPt ) const
2034 {
2035     sal_uInt8 nRet = SW_TABCOL_NONE;
2036     bool bRow = false;
2037     bool bCol = false;
2038     bool bSelect = false;
2039 
2040     // First try: Do we get the row/col move cursor?
2041     SwCellFrm* pFrm = (SwCellFrm*)GetBox( rPt, &bRow, 0 );
2042 
2043     if ( !pFrm )
2044     {
2045         // Second try: Do we get the row/col/tab selection cursor?
2046         pFrm = (SwCellFrm*)GetBox( rPt, &bRow, &bCol );
2047         bSelect = true;
2048     }
2049 
2050     if( pFrm )
2051 	{
2052 		while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
2053 			pFrm = (SwCellFrm*)((SwLayoutFrm*)pFrm->Lower())->Lower();
2054 		if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
2055 			pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
2056 			pFrm = 0;
2057 	}
2058 
2059     if( pFrm )
2060     {
2061         if ( !bSelect )
2062         {
2063             if ( pFrm->IsVertical() )
2064                 nRet = bRow ? SW_TABCOL_VERT : SW_TABROW_VERT;
2065             else
2066                 nRet = bRow ? SW_TABROW_HORI : SW_TABCOL_HORI;
2067         }
2068         else
2069         {
2070             const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
2071             if ( pTabFrm->IsVertical() )
2072             {
2073                 if ( bRow && bCol )
2074                 {
2075                     nRet = SW_TABSEL_VERT;
2076                 }
2077                 else if ( bRow )
2078                 {
2079                     nRet = SW_TABROWSEL_VERT;
2080                 }
2081                 else if ( bCol )
2082                 {
2083                     nRet = SW_TABCOLSEL_VERT;
2084                 }
2085             }
2086             else
2087             {
2088                 if ( bRow && bCol )
2089                 {
2090                     nRet =  pTabFrm->IsRightToLeft() ?
2091                             SW_TABSEL_HORI_RTL :
2092                             SW_TABSEL_HORI;
2093                 }
2094                 else if ( bRow )
2095                 {
2096                     nRet = pTabFrm->IsRightToLeft() ?
2097                            SW_TABROWSEL_HORI_RTL :
2098                            SW_TABROWSEL_HORI;
2099                 }
2100                 else if ( bCol )
2101                 {
2102                     nRet = SW_TABCOLSEL_HORI;
2103                 }
2104             }
2105         }
2106     }
2107 
2108     return nRet;
2109 }
2110 
2111 // -> #i23726#
2112 SwTxtNode * SwFEShell::GetNumRuleNodeAtPos( const Point &rPt)
2113 {
2114     SwTxtNode * pResult = NULL;
2115 
2116     SwContentAtPos aCntntAtPos
2117         (SwContentAtPos::SW_NUMLABEL);
2118 
2119     if( GetContentAtPos(rPt, aCntntAtPos) && aCntntAtPos.aFnd.pNode)
2120         pResult = aCntntAtPos.aFnd.pNode->GetTxtNode();
2121 
2122     return pResult;
2123 }
2124 
2125 sal_Bool SwFEShell::IsNumLabel( const Point &rPt, int nMaxOffset )
2126 {
2127     sal_Bool bResult = sal_False;
2128 
2129     SwContentAtPos aCntntAtPos
2130         (SwContentAtPos::SW_NUMLABEL);
2131 
2132     if( GetContentAtPos(rPt, aCntntAtPos))
2133     {
2134         if ((nMaxOffset >= 0 && aCntntAtPos.nDist <= nMaxOffset) ||
2135             (nMaxOffset < 0))
2136             bResult = sal_True;
2137     }
2138 
2139     return bResult;
2140 }
2141 // <- #i23726#
2142 
2143 // --> OD 2005-02-21 #i42921#
2144 bool SwFEShell::IsVerticalModeAtNdAndPos( const SwTxtNode& _rTxtNode,
2145                                           const Point& _rDocPos ) const
2146 {
2147     bool bRet( false );
2148 
2149     const short nTextDir =
2150         _rTxtNode.GetTextDirection( SwPosition(_rTxtNode), &_rDocPos );
2151     switch ( nTextDir )
2152     {
2153         case -1:
2154         case FRMDIR_HORI_RIGHT_TOP:
2155         case FRMDIR_HORI_LEFT_TOP:
2156         {
2157             bRet = false;
2158         }
2159         break;
2160         case FRMDIR_VERT_TOP_LEFT:
2161         case FRMDIR_VERT_TOP_RIGHT:
2162         {
2163             bRet = true;
2164         }
2165         break;
2166     }
2167 
2168     return bRet;
2169 }
2170 // <--
2171 
2172 /*************************************************************************
2173 |*
2174 |*	SwFEShell::GetMouseTabCols()
2175 |*
2176 |*	Ersterstellung		MA 22. Jun. 95
2177 |*	Letzte Aenderung	MA 27. Aug. 96
2178 |
2179 |*************************************************************************/
2180 void SwFEShell::GetMouseTabCols( SwTabCols &rToFill, const Point &rPt ) const
2181 {
2182 	const SwFrm *pBox = GetBox( rPt );
2183 	if ( pBox )
2184 		_GetTabCols( rToFill, pBox );
2185 }
2186 
2187 void SwFEShell::SetMouseTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly,
2188 								 const Point &rPt )
2189 {
2190 	const SwFrm *pBox = GetBox( rPt );
2191 	if( pBox )
2192 	{
2193 		SET_CURR_SHELL( this );
2194 		StartAllAction();
2195 		GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
2196 		EndAllActionAndCall();
2197 	}
2198 }
2199 
2200 /*************************************************************************
2201 |*
2202 |*	SwFEShell::GetMouseColNum(), GetMouseTabColNum()
2203 |*
2204 |*	Ersterstellung		MA 04. Jul. 95
2205 |*	Letzte Aenderung	MA 04. Jul. 95
2206 |
2207 |*************************************************************************/
2208 sal_uInt16 SwFEShell::GetCurMouseColNum( const Point &rPt,
2209 									SwGetCurColNumPara* pPara ) const
2210 {
2211 	return _GetCurColNum( GetBox( rPt ), pPara );
2212 }
2213 
2214 sal_uInt16 SwFEShell::GetCurMouseTabColNum( const Point &rPt ) const
2215 {
2216 	//!!!GetCurTabColNum() mitpflegen!!!!
2217 	sal_uInt16 nRet = 0;
2218 
2219 	const SwFrm *pFrm = GetBox( rPt );
2220 	ASSERT( pFrm, "Table not found" );
2221 	if( pFrm )
2222 	{
2223 		const long nX = pFrm->Frm().Left();
2224 
2225 		//TabCols besorgen, den nur ueber diese erreichen wir die Position.
2226 		SwTabCols aTabCols;
2227 		GetMouseTabCols( aTabCols, rPt );
2228 
2229 		const long nLeft = aTabCols.GetLeftMin();
2230 
2231 		if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
2232 		{
2233 			for ( sal_uInt16 i = 0; i < aTabCols.Count(); ++i )
2234 				if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
2235 				{
2236 					nRet = i + 1;
2237 					break;
2238 				}
2239 		}
2240 	}
2241 	return nRet;
2242 }
2243 
2244 void ClearFEShellTabCols()
2245 {
2246 	DELETEZ( pLastCols );
2247     DELETEZ( pLastRows );
2248 }
2249 
2250 /*************************************************************************
2251 |*
2252 |*	SwFEShell::GetTblAttr(), SetTblAttr()
2253 |*
2254 |*	Ersterstellung		MA 09. Dec. 96
2255 |*	Letzte Aenderung	MA 09. Dec. 96
2256 |
2257 |*************************************************************************/
2258 void SwFEShell::GetTblAttr( SfxItemSet &rSet ) const
2259 {
2260 	SwFrm *pFrm = GetCurrFrm();
2261 	if( pFrm && pFrm->IsInTab() )
2262 		rSet.Put( pFrm->ImplFindTabFrm()->GetFmt()->GetAttrSet() );
2263 }
2264 
2265 void SwFEShell::SetTblAttr( const SfxItemSet &rNew )
2266 {
2267 	SwFrm *pFrm = GetCurrFrm();
2268 	if( pFrm && pFrm->IsInTab() )
2269 	{
2270 		SET_CURR_SHELL( this );
2271 		StartAllAction();
2272 		SwTabFrm *pTab = pFrm->FindTabFrm();
2273 		pTab->GetTable()->SetHTMLTableLayout( 0 );
2274 		GetDoc()->SetAttr( rNew, *pTab->GetFmt() );
2275 		GetDoc()->SetModified();
2276 		EndAllActionAndCall();
2277 	}
2278 }
2279 
2280 /** move cursor within a table into previous/next row (same column)
2281  * @param pShell cursor shell whose cursor is to be moved
2282  * @param bUp true: move up, false: move down
2283  * @returns true if successful
2284  */
2285 bool lcl_GoTableRow( SwCrsrShell* pShell, bool bUp )
2286 {
2287     ASSERT( pShell != NULL, "need shell" );
2288 
2289     bool bRet = false;
2290 
2291     SwPaM* pPam = pShell->GetCrsr();
2292     const SwStartNode* pTableBox = pPam->GetNode()->FindTableBoxStartNode();
2293     ASSERT( pTableBox != NULL, "I'm living in a box... NOT!" );
2294 
2295     // move cursor to start node of table box
2296     pPam->GetPoint()->nNode = pTableBox->GetIndex();
2297     pPam->GetPoint()->nContent.Assign( NULL, 0 );
2298     GoInCntnt( *pPam, fnMoveForward );
2299 
2300     // go to beginning end of table box
2301     SwPosSection fnPosSect = bUp ? fnSectionStart : fnSectionEnd;
2302     pShell->MoveSection( fnSectionCurr, fnPosSect );
2303 
2304     // and go up/down into next content
2305     bRet = bUp ? pShell->Up() : pShell->Down();
2306 
2307     return bRet;
2308 }
2309 
2310 	// aender eine  Zellenbreite/-Hoehe/Spaltenbreite/Zeilenhoehe
2311 sal_Bool SwFEShell::SetColRowWidthHeight( sal_uInt16 eType, sal_uInt16 nDiff )
2312 {
2313 	SwFrm *pFrm = GetCurrFrm();
2314 	if( !pFrm || !pFrm->IsInTab() )
2315 		return sal_False;
2316 
2317 	if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType &&
2318 		pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
2319 	{
2320 		ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
2321 						ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
2322 		return sal_False;
2323 	}
2324 
2325 	SET_CURR_SHELL( this );
2326 	StartAllAction();
2327 
2328 	do {
2329 		pFrm = pFrm->GetUpper();
2330 	} while( !pFrm->IsCellFrm() );
2331 
2332 	SwTabFrm *pTab = pFrm->ImplFindTabFrm();
2333 
2334 	// sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2335 	// dann muss es jetzt auf absolute umgerechnet werden.
2336 	const SwFmtFrmSize& rTblFrmSz = pTab->GetFmt()->GetFrmSize();
2337     SWRECTFN( pTab )
2338     long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
2339 	if( TBLVAR_CHGABS == pTab->GetTable()->GetTblChgMode() &&
2340 		( eType & nsTblChgWidthHeightType::WH_COL_LEFT || eType & nsTblChgWidthHeightType::WH_COL_RIGHT ) &&
2341         text::HoriOrientation::NONE == pTab->GetFmt()->GetHoriOrient().GetHoriOrient() &&
2342         nPrtWidth != rTblFrmSz.GetWidth() )
2343     {
2344         SwFmtFrmSize aSz( rTblFrmSz );
2345         aSz.SetWidth( pTab->Prt().Width() );
2346         pTab->GetFmt()->SetFmtAttr( aSz );
2347 	}
2348 
2349 	if( (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) ==
2350 		(nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL) )
2351     {
2352         nDiff = sal_uInt16((pFrm->Frm().*fnRect->fnGetWidth)());
2353 
2354         // we must move the cursor outside the current cell before
2355         // deleting the cells.
2356         TblChgWidthHeightType eTmp =
2357             static_cast<TblChgWidthHeightType>( eType & 0xfff );
2358         switch( eTmp )
2359         {
2360         case nsTblChgWidthHeightType::WH_ROW_TOP:
2361             lcl_GoTableRow( this, true );
2362             break;
2363         case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
2364             lcl_GoTableRow( this, false );
2365             break;
2366         case nsTblChgWidthHeightType::WH_COL_LEFT:
2367             GoPrevCell();
2368             break;
2369         case nsTblChgWidthHeightType::WH_COL_RIGHT:
2370             GoNextCell();
2371             break;
2372         default:
2373             break;
2374         }
2375     }
2376 
2377 	SwTwips nLogDiff = nDiff;
2378 	nLogDiff *= pTab->GetFmt()->GetFrmSize().GetWidth();
2379     nLogDiff /= nPrtWidth;
2380 
2381     /** The cells are destroyed in here */
2382 	sal_Bool bRet = GetDoc()->SetColRowWidthHeight(
2383 					*(SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(),
2384 					eType, nDiff, nLogDiff );
2385 
2386 	delete pLastCols, pLastCols = 0;
2387 	EndAllActionAndCall();
2388 
2389 	if( bRet && (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) == nsTblChgWidthHeightType::WH_FLAG_INSDEL )
2390 	{
2391 		switch(eType & ~(nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL))
2392 		{
2393 		case nsTblChgWidthHeightType::WH_CELL_LEFT:
2394 		case nsTblChgWidthHeightType::WH_COL_LEFT:
2395 				GoPrevCell();
2396 				break;
2397 
2398 		case nsTblChgWidthHeightType::WH_CELL_RIGHT:
2399 		case nsTblChgWidthHeightType::WH_COL_RIGHT:
2400 				GoNextCell();
2401 				break;
2402 
2403 		case nsTblChgWidthHeightType::WH_CELL_TOP:
2404 		case nsTblChgWidthHeightType::WH_ROW_TOP:
2405                 lcl_GoTableRow( this, true );
2406 				break;
2407 
2408 		case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
2409 		case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
2410                 lcl_GoTableRow( this, false );
2411 				break;
2412 		}
2413 	}
2414 
2415 	return bRet;
2416 }
2417 
2418 sal_Bool lcl_IsFormulaSelBoxes( const SwTable& rTbl, const SwTblBoxFormula& rFml,
2419 							SwCellFrms& rCells )
2420 {
2421 	SwTblBoxFormula aTmp( rFml );
2422 	SwSelBoxes aBoxes;
2423 	for( sal_uInt16 nSelBoxes = aTmp.GetBoxesOfFormula( rTbl,aBoxes ); nSelBoxes; )
2424 	{
2425 		SwTableBox* pBox = aBoxes[ --nSelBoxes ];
2426 		sal_uInt16 i;
2427 		for( i = 0; i < rCells.Count(); ++i )
2428 			if( rCells[ i ]->GetTabBox() == pBox )
2429 				break;		// gefunden
2430 
2431 		if( i == rCells.Count() )
2432 			return sal_False;
2433 	}
2434 
2435 	return sal_True;
2436 }
2437 
2438 	// erfrage die Formel fuer die Autosumme
2439 sal_Bool SwFEShell::GetAutoSum( String& rFml ) const
2440 {
2441 	SwFrm *pFrm = GetCurrFrm();
2442 	SwTabFrm *pTab = pFrm ? pFrm->ImplFindTabFrm() : 0;
2443 	if( !pTab )
2444 		return sal_False;
2445 
2446 	rFml = String::CreateFromAscii( sCalc_Sum );
2447 
2448 	SwCellFrms aCells;
2449 	if( ::GetAutoSumSel( *this, aCells ))
2450 	{
2451 		sal_uInt16 nW = 0, nInsPos = 0;
2452 		for( sal_uInt16 n = aCells.Count(); n; )
2453 		{
2454 			SwCellFrm* pCFrm = aCells[ --n ];
2455 			sal_uInt16 nBoxW = pCFrm->GetTabBox()->IsFormulaOrValueBox();
2456 			if( !nBoxW )
2457 				break;
2458 
2459 			if( !nW )
2460 			{
2461 				if( USHRT_MAX == nBoxW )
2462 					continue;		// leere am Anfang ueberspringen
2463 
2464 				rFml += '(';
2465 				nInsPos = rFml.Len();
2466 
2467 				// Formeln nur wenn diese Boxen enthalten
2468 				if( RES_BOXATR_FORMULA == nBoxW &&
2469 					!::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2470 					GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells))
2471 				{
2472 					nW = RES_BOXATR_VALUE;
2473 					// alle vorhierigen Leere wieder mit aufnehmen !
2474 					for( sal_uInt16 i = aCells.Count(); n+1 < i; )
2475 					{
2476 						String sTmp( String::CreateFromAscii(
2477 								RTL_CONSTASCII_STRINGPARAM( "|<" )) );
2478 						sTmp += aCells[ --i ]->GetTabBox()->GetName();
2479 						sTmp += '>';
2480 						rFml.Insert( sTmp, nInsPos );
2481 					}
2482 				}
2483 				else
2484 					nW = nBoxW;
2485 			}
2486 			else if( RES_BOXATR_VALUE == nW )
2487 			{
2488 				// values werden gesucht, Value/Formel/Text gefunden -> aufn.
2489 				if( RES_BOXATR_FORMULA == nBoxW &&
2490 					::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2491 						GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
2492 					break;
2493 				else if( USHRT_MAX != nBoxW )
2494 					rFml.Insert( cListDelim, nInsPos );
2495 				else
2496 					break;
2497 			}
2498 			else if( RES_BOXATR_FORMULA == nW )
2499 			{
2500 				// bei Formeln nur weiter suchen, wenn die akt. Formel auf
2501 				// alle Boxen verweist, die sich in der Selektion befinden
2502 				if( RES_BOXATR_FORMULA == nBoxW )
2503 				{
2504 					if( !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2505 						GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
2506 					{
2507 						// dann noch mal von vorne und nur die Values!
2508 
2509 						nW = RES_BOXATR_VALUE;
2510 						rFml.Erase( nInsPos );
2511 						// alle vorhierigen Leere wieder mit aufnehmen !
2512 						for( sal_uInt16 i = aCells.Count(); n+1 < i; )
2513 						{
2514 							String sTmp( String::CreateFromAscii(
2515 									RTL_CONSTASCII_STRINGPARAM( "|<" )) );
2516 							sTmp += aCells[ --i ]->GetTabBox()->GetName();
2517 							sTmp += '>';
2518 							rFml.Insert( sTmp, nInsPos );
2519 						}
2520 					}
2521 					else
2522 						rFml.Insert( cListDelim, nInsPos );
2523 				}
2524 				else if( USHRT_MAX == nBoxW )
2525 					break;
2526 				else
2527 					continue;		// diese Boxen ignorieren
2528 			}
2529 			else
2530 				// alles andere beendet die Schleife
2531 // evt. Texte noch zu lassen??
2532 				break;
2533 
2534 			String sTmp( '<' );
2535 			sTmp += pCFrm->GetTabBox()->GetName();
2536 			sTmp += '>';
2537 			rFml.Insert( sTmp, nInsPos );
2538 		}
2539 		if( nW )
2540 		{
2541 			rFml += ')';
2542 
2543 /*
2544 			// TabellenSelektion erzeugen??
2545 			SwTblBoxFormula aTmp( rFml );
2546 			SwSelBoxes aBoxes;
2547 			for( sal_uInt16 nSelBoxes = aTmp.GetBoxesOfFormula( rTbl,aBoxes );
2548 					nSelBoxes; )
2549 			{
2550 			}
2551 */
2552 		}
2553 	}
2554 
2555 	return sal_True;
2556 }
2557 /* -----------------------------22.08.2002 12:50------------------------------
2558 
2559  ---------------------------------------------------------------------------*/
2560 sal_Bool SwFEShell::IsTableRightToLeft() const
2561 {
2562 	SwFrm *pFrm = GetCurrFrm();
2563 	if( !pFrm || !pFrm->IsInTab() )
2564 		return sal_False;
2565 
2566     return pFrm->ImplFindTabFrm()->IsRightToLeft();
2567 }
2568 
2569 /* -----------------------------22.08.2002 12:50------------------------------
2570 
2571  ---------------------------------------------------------------------------*/
2572 sal_Bool SwFEShell::IsMouseTableRightToLeft(const Point &rPt) const
2573 {
2574     SwFrm *pFrm = (SwFrm *)GetBox( rPt );
2575     const SwTabFrm*  pTabFrm = pFrm ? pFrm->ImplFindTabFrm() : 0;
2576     ASSERT( pTabFrm, "Table not found" );
2577     return pTabFrm ? pTabFrm->IsRightToLeft() : sal_False;
2578 }
2579 
2580 /* -----------------------------11.02.2004 12:50------------------------------
2581 
2582  ---------------------------------------------------------------------------*/
2583 sal_Bool SwFEShell::IsTableVertical() const
2584 {
2585     SwFrm *pFrm = GetCurrFrm();
2586     if( !pFrm || !pFrm->IsInTab() )
2587         return sal_False;
2588 
2589     return pFrm->ImplFindTabFrm()->IsVertical();
2590 }
2591 
2592 
2593 
2594