xref: /trunk/main/sw/source/core/frmedt/fetab.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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