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