merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / frmedt / fetab.cxx
blob202f22375488a4def7ba04a7dec37dd29069771c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fetab.cxx,v $
10 * $Revision: 1.48 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
37 #include <tools/errinf.hxx>
38 #include <vcl/svapp.hxx>
39 #include <basegfx/vector/b2dvector.hxx>
40 #ifndef _SVX_SVXIDS_HRC
41 #include <svx/svxids.hrc>
42 #endif
43 #include <svx/protitem.hxx>
44 #include <svx/brshitem.hxx>
45 #include <svx/frmdiritem.hxx>
46 #include <svtools/ruler.hxx>
47 #include <swwait.hxx>
48 #include <fmtfsize.hxx>
49 #include <fmtornt.hxx>
50 #include <frmatr.hxx>
51 #include <docary.hxx>
52 #include <fesh.hxx>
53 #include <doc.hxx>
54 #include <cntfrm.hxx>
55 #include <rootfrm.hxx>
56 #include <pagefrm.hxx>
57 #include <tabfrm.hxx>
58 #include <rowfrm.hxx>
59 #include <cellfrm.hxx>
60 #include <flyfrm.hxx>
61 #include <dflyobj.hxx>
62 #include <swtable.hxx>
63 #include <swddetbl.hxx>
64 #include <ndtxt.hxx>
65 #include <calc.hxx>
66 #include <tabcol.hxx>
67 #include <cellatr.hxx>
68 #include <pam.hxx>
69 #include <viscrs.hxx>
70 #include <tblsel.hxx>
71 #include <swtblfmt.hxx>
72 #include <swerror.h>
73 #include <swundo.hxx>
74 #include <frmtool.hxx>
76 #include <node.hxx> // #i23726#
77 // OD 2004-05-24 #i28701#
78 #include <sortedobjs.hxx>
80 using namespace ::com::sun::star;
83 //siehe auch swtable.cxx
84 #define COLFUZZY 20L
86 inline BOOL IsSame( long nA, long nB ) { return Abs(nA-nB) <= COLFUZZY; }
87 inline BOOL IsNear( long nA, long nB, long nTolerance ) { return Abs( nA - nB ) <= nTolerance; }
89 // table column cache
90 SwTabCols *pLastCols = 0;
91 const SwTable *pColumnCacheLastTable = 0;
92 const SwTabFrm *pColumnCacheLastTabFrm = 0;
93 const SwFrm *pColumnCacheLastCellFrm = 0;
95 // table row cache
96 SwTabCols *pLastRows = 0;
97 const SwTable *pRowCacheLastTable = 0;
98 const SwTabFrm *pRowCacheLastTabFrm = 0;
99 const SwFrm *pRowCacheLastCellFrm = 0;
102 class TblWait
104 SwWait *pWait;
105 public:
106 TblWait( USHORT nCnt, SwFrm *pFrm, SwDocShell &rDocShell, USHORT nCnt2 = 0);
107 ~TblWait() { delete pWait; }
110 TblWait::TblWait( USHORT nCnt, SwFrm *pFrm, SwDocShell &rDocShell, USHORT nCnt2):
111 pWait( 0 )
113 BOOL bWait = 20 < nCnt || 20 < nCnt2 || (pFrm &&
114 20 < pFrm->ImplFindTabFrm()->GetTable()->GetTabLines().Count());
115 if( bWait )
116 pWait = new SwWait( rDocShell, TRUE );
120 void SwFEShell::ParkCursorInTab()
122 SwCursor * pSwCrsr = GetSwCrsr();
124 ASSERT(pSwCrsr, "no SwCursor");
126 SwPosition aStartPos = *pSwCrsr->GetPoint(), aEndPos = aStartPos;
128 SwCursor * pTmpCrsr = (SwCursor *) pSwCrsr;
130 /* Search least and greatest position in current cursor ring.
134 const SwPosition * pPt = pTmpCrsr->GetPoint(),
135 * pMk = pTmpCrsr->GetMark();
137 if (*pPt < aStartPos)
138 aStartPos = *pPt;
140 if (*pPt > aEndPos)
141 aEndPos = *pPt;
143 if (*pMk < aStartPos)
144 aStartPos = *pMk;
146 if (*pMk > aEndPos)
147 aEndPos = *pMk;
149 pTmpCrsr = (SwCursor *) pTmpCrsr->GetNext();
151 while (pTmpCrsr != pSwCrsr);
153 KillPams();
155 /* @@@ semantic: SwCursor::operator=() is not implemented @@@ */
157 /* Set cursor to end of selection to ensure IsLastCellInRow works
158 properly. */
160 SwCursor aTmpCrsr( aEndPos, 0, false );
161 *pSwCrsr = aTmpCrsr;
164 /* Move the cursor out of the columns to delete and stay in the
165 same row. If the table has only one column the cursor will
166 stay in the row and the shell will take care of it. */
167 if (IsLastCellInRow())
169 /* If the cursor is in the last row of the table, first
170 try to move it to the previous cell. If that fails move
171 it to the next cell. */
174 SwCursor aTmpCrsr( aStartPos, 0, false );
175 *pSwCrsr = aTmpCrsr;
178 if (! pSwCrsr->GoPrevCell())
180 SwCursor aTmpCrsr( aEndPos, 0, false );
181 *pSwCrsr = aTmpCrsr;
182 pSwCrsr->GoNextCell();
185 else
187 /* If the cursor is not in the last row of the table, first
188 try to move it to the next cell. If that fails move it
189 to the previous cell. */
192 SwCursor aTmpCrsr( aEndPos, 0, false );
193 *pSwCrsr = aTmpCrsr;
196 if (! pSwCrsr->GoNextCell())
198 SwCursor aTmpCrsr( aStartPos, 0, false );
199 *pSwCrsr = aTmpCrsr;
200 pSwCrsr->GoPrevCell();
205 /***********************************************************************
206 #* Class : SwFEShell
207 #* Methoden : InsertRow(), InsertCol
208 #* Datum : MA 03. May. 93
209 #* Update : MA 19. Apr. 95
210 #***********************************************************************/
211 BOOL SwFEShell::InsertRow( USHORT nCnt, BOOL bBehind )
213 // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
214 SwFrm *pFrm = GetCurrFrm();
215 if( !pFrm || !pFrm->IsInTab() )
216 return FALSE;
218 if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
220 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
221 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
222 return FALSE;
225 SET_CURR_SHELL( this );
226 StartAllAction();
228 // lasse ueber das Layout die Boxen suchen
229 SwSelBoxes aBoxes;
230 GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
232 TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
234 BOOL bRet = FALSE;
235 if ( aBoxes.Count() )
236 bRet = GetDoc()->InsertRow( aBoxes, nCnt, bBehind );
238 EndAllActionAndCall();
239 return bRet;
242 BOOL SwFEShell::InsertCol( USHORT nCnt, BOOL bBehind )
244 // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
245 SwFrm *pFrm = GetCurrFrm();
246 if( !pFrm || !pFrm->IsInTab() )
247 return FALSE;
249 if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
251 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
252 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
253 return FALSE;
256 SET_CURR_SHELL( this );
258 if( !CheckSplitCells( *this, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) )
260 ErrorHandler::HandleError( ERR_TBLINSCOL_ERROR,
261 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
262 return FALSE;
265 StartAllAction();
266 // lasse ueber das Layout die Boxen suchen
267 SwSelBoxes aBoxes;
268 GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
270 TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
272 BOOL bRet = FALSE;
273 if( aBoxes.Count() )
274 bRet = GetDoc()->InsertCol( aBoxes, nCnt, bBehind );
276 EndAllActionAndCall();
277 return bRet;
280 /***********************************************************************
281 #* Class : SwFEShell
282 #* Methoden : DeleteRow(), DeleteCol()
283 #* Datum : MA 03. May. 93
284 #* Update : MA 19. Apr. 95
285 #***********************************************************************/
288 Determines if the current cursor is in the last row of the table.
290 BOOL SwFEShell::IsLastCellInRow() const
292 SwTabCols aTabCols;
293 GetTabCols( aTabCols );
294 BOOL bResult = FALSE;
296 if (IsTableRightToLeft())
297 /* If the table is right-to-left the last row is the most left one. */
298 bResult = 0 == GetCurTabColNum();
299 else
300 /* If the table is left-to-right the last row is the most right one. */
301 bResult = aTabCols.Count() == GetCurTabColNum();
303 return bResult;
306 BOOL SwFEShell::DeleteCol()
308 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
309 SwFrm *pFrm = GetCurrFrm();
310 if( !pFrm || !pFrm->IsInTab() )
311 return FALSE;
313 if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
315 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
316 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
317 return FALSE;
320 SET_CURR_SHELL( this );
321 StartAllAction();
323 // lasse ueber das Layout die Boxen suchen
324 BOOL bRet;
325 SwSelBoxes aBoxes;
326 GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
327 if ( aBoxes.Count() )
329 TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
331 // die Crsr muessen noch aus dem Loesch Bereich entfernt
332 // werden. Setze sie immer hinter/auf die Tabelle; ueber die
333 // Dokument-Position werden sie dann immer an die alte Position gesetzt.
334 while( !pFrm->IsCellFrm() )
335 pFrm = pFrm->GetUpper();
337 ParkCursorInTab();
339 // dann loesche doch die Spalten
340 StartUndo(UNDO_COL_DELETE);
341 bRet = GetDoc()->DeleteRowCol( aBoxes, true );
342 EndUndo(UNDO_COL_DELETE);
345 else
346 bRet = FALSE;
348 EndAllActionAndCall();
349 return bRet;
352 BOOL SwFEShell::DeleteRow()
354 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
355 SwFrm *pFrm = GetCurrFrm();
356 if( !pFrm || !pFrm->IsInTab() )
357 return FALSE;
359 if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
361 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
362 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
363 return FALSE;
366 SET_CURR_SHELL( this );
367 StartAllAction();
369 // lasse ueber das Layout die Boxen suchen
370 BOOL bRet;
371 SwSelBoxes aBoxes;
372 GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
374 if( aBoxes.Count() )
376 TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
378 // die Crsr aus dem Loeschbereich entfernen.
379 // Der Cursor steht danach:
380 // - es folgt noch eine Zeile, in dieser
381 // - vorher steht noch eine Zeile, in dieser
382 // - sonst immer dahinter
384 SwTableNode* pTblNd = ((SwCntntFrm*)pFrm)->GetNode()->FindTableNode();
386 // suche alle Boxen / Lines
387 _FndBox aFndBox( 0, 0 );
389 _FndPara aPara( aBoxes, &aFndBox );
390 pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
393 if( !aFndBox.GetLines().Count() )
395 EndAllActionAndCall();
396 return FALSE;
399 KillPams();
401 _FndBox* pFndBox = &aFndBox;
402 while( 1 == pFndBox->GetLines().Count() &&
403 1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
405 _FndBox* pTmp = pFndBox->GetLines()[0]->GetBoxes()[0];
406 if( pTmp->GetBox()->GetSttNd() )
407 break; // das ist sonst zu weit
408 pFndBox = pTmp;
411 SwTableLine* pDelLine = pFndBox->GetLines()[
412 pFndBox->GetLines().Count()-1 ]->GetLine();
413 SwTableBox* pDelBox = pDelLine->GetTabBoxes()[
414 pDelLine->GetTabBoxes().Count() - 1 ];
415 while( !pDelBox->GetSttNd() )
417 SwTableLine* pLn = pDelBox->GetTabLines()[
418 pDelBox->GetTabLines().Count()-1 ];
419 pDelBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ];
421 SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(),
422 pDelBox, TRUE );
423 while( pNextBox &&
424 pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
425 pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox );
427 if( !pNextBox ) // keine nachfolgende? dann die vorhergehende
429 pDelLine = pFndBox->GetLines()[ 0 ]->GetLine();
430 pDelBox = pDelLine->GetTabBoxes()[ 0 ];
431 while( !pDelBox->GetSttNd() )
432 pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
433 pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(),
434 pDelBox, TRUE );
435 while( pNextBox &&
436 pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
437 pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox );
440 ULONG nIdx;
441 if( pNextBox ) // dann den Cursor hier hinein
442 nIdx = pNextBox->GetSttIdx() + 1;
443 else // ansonsten hinter die Tabelle
444 nIdx = pTblNd->EndOfSectionIndex() + 1;
446 SwNodeIndex aIdx( GetDoc()->GetNodes(), nIdx );
447 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
448 if( !pCNd )
449 pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
451 if( pCNd )
453 SwPaM* pPam = GetCrsr();
454 pPam->GetPoint()->nNode = aIdx;
455 pPam->GetPoint()->nContent.Assign( pCNd, 0 );
456 pPam->SetMark(); // beide wollen etwas davon haben
457 pPam->DeleteMark();
461 // dann loesche doch die Zeilen
462 StartUndo(UNDO_ROW_DELETE);
463 bRet = GetDoc()->DeleteRowCol( aBoxes );
464 EndUndo(UNDO_ROW_DELETE);
466 else
467 bRet = FALSE;
469 EndAllActionAndCall();
470 return bRet;
473 /***********************************************************************
474 #* Class : SwFEShell
475 #* Methoden : MergeTab(), SplitTab()
476 #* Datum : MA 03. May. 93
477 #* Update : MA 19. Apr. 95
478 #***********************************************************************/
480 USHORT SwFEShell::MergeTab()
482 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
483 USHORT nRet = TBLMERGE_NOSELECTION;
484 if( IsTableMode() )
486 SwShellTableCrsr* pTableCrsr = GetTableCrsr();
487 const SwTableNode* pTblNd = pTableCrsr->GetNode()->FindTableNode();
488 if( pTblNd->GetTable().ISA( SwDDETable ))
490 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
491 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
493 else
495 SET_CURR_SHELL( this );
496 StartAllAction();
498 TblWait( pTableCrsr->GetBoxesCount(), 0, *GetDoc()->GetDocShell(),
499 pTblNd->GetTable().GetTabLines().Count() );
501 nRet = GetDoc()->MergeTbl( *pTableCrsr );
503 KillPams();
505 EndAllActionAndCall();
508 return nRet;
511 BOOL SwFEShell::SplitTab( BOOL bVert, USHORT nCnt, BOOL bSameHeight )
513 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
514 SwFrm *pFrm = GetCurrFrm();
515 if( !pFrm || !pFrm->IsInTab() )
516 return FALSE;
518 if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
520 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
521 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
522 return FALSE;
525 SET_CURR_SHELL( this );
527 if( bVert && !CheckSplitCells( *this, nCnt + 1 ) )
529 ErrorHandler::HandleError( ERR_TBLSPLIT_ERROR,
530 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
531 return FALSE;
533 StartAllAction();
534 // lasse ueber das Layout die Boxen suchen
535 BOOL bRet;
536 SwSelBoxes aBoxes;
537 GetTblSel( *this, aBoxes );
538 if( aBoxes.Count() )
540 TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.Count() );
542 // dann loesche doch die Spalten
543 bRet = GetDoc()->SplitTbl( aBoxes, bVert, nCnt, bSameHeight );
545 DELETEZ( pLastCols );
546 DELETEZ( pLastRows );
548 else
549 bRet = FALSE;
550 EndAllActionAndCall();
551 return bRet;
555 /***********************************************************************
556 #* Class : SwFEShell
557 #* Methoden : _GetTabCols
558 #* Datum : MA 30. Nov. 95
559 #* Update : MA 08. Jan. 97
560 #***********************************************************************/
561 void SwFEShell::_GetTabCols( SwTabCols &rToFill, const SwFrm *pBox ) const
563 const SwTabFrm *pTab = pBox->FindTabFrm();
564 if ( pLastCols )
566 //Paar Kleinigkeiten muessen wir schon noch sicherstellen
567 BOOL bDel = TRUE;
568 if ( pColumnCacheLastTable == pTab->GetTable() )
570 bDel = FALSE;
571 SWRECTFN( pTab )
573 const SwPageFrm* pPage = pTab->FindPageFrm();
574 const ULONG nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
575 (pPage->Frm().*fnRect->fnGetLeft)();
576 const ULONG nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
577 (pPage->Frm().*fnRect->fnGetLeft)();
579 if ( pColumnCacheLastTabFrm != pTab )
581 //Wenn der TabFrm gewechselt hat, brauchen wir bei gleicher
582 //Breite nur ein wenig shiften.
583 SWRECTFNX( pColumnCacheLastTabFrm )
584 if( (pColumnCacheLastTabFrm->Frm().*fnRectX->fnGetWidth)() ==
585 (pTab->Frm().*fnRect->fnGetWidth)() )
587 pLastCols->SetLeftMin( nLeftMin );
589 //ASSERT( bVert ||
590 // pLastCols->GetLeftMin() == (pTab->Frm().*fnRect->fnGetLeft)(),
591 // "GetTabCols: wrong result" )
593 pColumnCacheLastTabFrm = pTab;
595 else
596 bDel = TRUE;
599 if ( !bDel &&
600 pLastCols->GetLeftMin () == (USHORT)nLeftMin &&
601 pLastCols->GetLeft () == (USHORT)(pTab->Prt().*fnRect->fnGetLeft)() &&
602 pLastCols->GetRight () == (USHORT)(pTab->Prt().*fnRect->fnGetRight)()&&
603 pLastCols->GetRightMax() == (USHORT)nRightMax - pLastCols->GetLeftMin() )
605 if ( pColumnCacheLastCellFrm != pBox )
607 pTab->GetTable()->GetTabCols( *pLastCols,
608 ((SwCellFrm*)pBox)->GetTabBox(), TRUE);
609 pColumnCacheLastCellFrm = pBox;
611 rToFill = *pLastCols;
613 else
614 bDel = TRUE;
616 if ( bDel )
617 DELETEZ(pLastCols);
619 if ( !pLastCols )
621 GetDoc()->GetTabCols( rToFill, 0, (SwCellFrm*)pBox );
623 pLastCols = new SwTabCols( rToFill );
624 pColumnCacheLastTable = pTab->GetTable();
625 pColumnCacheLastTabFrm = pTab;
626 pColumnCacheLastCellFrm= pBox;
629 #if OSL_DEBUG_LEVEL > 1
630 SwTabColsEntry aEntry;
631 for ( USHORT i = 0; i < rToFill.Count(); ++i )
633 aEntry = rToFill.GetEntry( i );
634 (void)aEntry;
636 #endif
639 /***********************************************************************
640 #* Class : SwFEShell
641 #* Methoden : _GetTabRows
642 #* Datum : FME 2004-01-14
643 #* Update :
644 #***********************************************************************/
645 void SwFEShell::_GetTabRows( SwTabCols &rToFill, const SwFrm *pBox ) const
647 const SwTabFrm *pTab = pBox->FindTabFrm();
648 if ( pLastRows )
650 //Paar Kleinigkeiten muessen wir schon noch sicherstellen
651 BOOL bDel = TRUE;
652 if ( pRowCacheLastTable == pTab->GetTable() )
654 bDel = FALSE;
655 SWRECTFN( pTab )
656 const SwPageFrm* pPage = pTab->FindPageFrm();
657 const long nLeftMin = ( bVert ?
658 pTab->GetPrtLeft() - pPage->Frm().Left() :
659 pTab->GetPrtTop() - pPage->Frm().Top() );
660 const long nLeft = bVert ? LONG_MAX : 0;
661 const long nRight = (pTab->Prt().*fnRect->fnGetHeight)();
662 const long nRightMax = bVert ? nRight : LONG_MAX;
664 if ( pRowCacheLastTabFrm != pTab ||
665 pRowCacheLastCellFrm != pBox )
666 bDel = TRUE;
668 if ( !bDel &&
669 pLastRows->GetLeftMin () == nLeftMin &&
670 pLastRows->GetLeft () == nLeft &&
671 pLastRows->GetRight () == nRight &&
672 pLastRows->GetRightMax() == nRightMax )
674 rToFill = *pLastRows;
676 else
677 bDel = TRUE;
679 if ( bDel )
680 DELETEZ(pLastRows);
682 if ( !pLastRows )
684 GetDoc()->GetTabRows( rToFill, 0, (SwCellFrm*)pBox );
686 pLastRows = new SwTabCols( rToFill );
687 pRowCacheLastTable = pTab->GetTable();
688 pRowCacheLastTabFrm = pTab;
689 pRowCacheLastCellFrm= pBox;
693 /***********************************************************************
694 #* Class : SwFEShell
695 #* Methoden : SetTabCols(), GetTabCols()
696 #* Datum : MA 03. May. 93
697 #* Update : MA 18. May. 93
698 #***********************************************************************/
699 void SwFEShell::SetTabCols( const SwTabCols &rNew, BOOL bCurRowOnly )
701 SwFrm *pBox = GetCurrFrm();
702 if( !pBox || !pBox->IsInTab() )
703 return;
705 SET_CURR_SHELL( this );
706 StartAllAction();
708 do {
709 pBox = pBox->GetUpper();
710 } while ( !pBox->IsCellFrm() );
712 GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
713 EndAllActionAndCall();
716 void SwFEShell::GetTabCols( SwTabCols &rToFill ) const
718 const SwFrm *pFrm = GetCurrFrm();
719 if( !pFrm || !pFrm->IsInTab() )
720 return;
722 { pFrm = pFrm->GetUpper();
723 } while ( !pFrm->IsCellFrm() );
725 _GetTabCols( rToFill, pFrm );
728 /*-- 19.01.2004 08:56:42---------------------------------------------------
730 -----------------------------------------------------------------------*/
731 void SwFEShell::GetTabRows( SwTabCols &rToFill ) const
733 const SwFrm *pFrm = GetCurrFrm();
734 if( !pFrm || !pFrm->IsInTab() )
735 return;
737 { pFrm = pFrm->GetUpper();
738 } while ( !pFrm->IsCellFrm() );
740 _GetTabRows( rToFill, pFrm );
742 /*-- 19.01.2004 08:56:44---------------------------------------------------
744 -----------------------------------------------------------------------*/
745 void SwFEShell::SetTabRows( const SwTabCols &rNew, BOOL bCurColOnly )
747 SwFrm *pBox = GetCurrFrm();
748 if( !pBox || !pBox->IsInTab() )
749 return;
751 SET_CURR_SHELL( this );
752 StartAllAction();
754 do {
755 pBox = pBox->GetUpper();
756 } while ( !pBox->IsCellFrm() );
758 GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
759 EndAllActionAndCall();
761 /*-- 19.01.2004 08:59:45---------------------------------------------------
763 -----------------------------------------------------------------------*/
764 void SwFEShell::GetMouseTabRows( SwTabCols &rToFill, const Point &rPt ) const
766 const SwFrm *pBox = GetBox( rPt );
767 if ( pBox )
768 _GetTabRows( rToFill, pBox );
770 /*-- 19.01.2004 08:59:45---------------------------------------------------
772 -----------------------------------------------------------------------*/
773 void SwFEShell::SetMouseTabRows( const SwTabCols &rNew, BOOL bCurColOnly, const Point &rPt )
775 const SwFrm *pBox = GetBox( rPt );
776 if( pBox )
778 SET_CURR_SHELL( this );
779 StartAllAction();
780 GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
781 EndAllActionAndCall();
785 /***********************************************************************
786 * Class : SwFEShell
787 * Methoden : SetRowSplit(), GetRowSplit()
788 * Datum : FME 13.11.2003
789 ***********************************************************************/
791 void SwFEShell::SetRowSplit( const SwFmtRowSplit& rNew )
793 SET_CURR_SHELL( this );
794 StartAllAction();
795 GetDoc()->SetRowSplit( *getShellCrsr( false ), rNew );
796 EndAllActionAndCall();
799 void SwFEShell::GetRowSplit( SwFmtRowSplit*& rpSz ) const
801 GetDoc()->GetRowSplit( *getShellCrsr( false ), rpSz );
805 /***********************************************************************
806 #* Class : SwFEShell
807 #* Methoden : SetRowHeight(), GetRowHeight()
808 #* Datum : MA 17. May. 93
809 #* Update : JP 29.04.98
810 #***********************************************************************/
812 void SwFEShell::SetRowHeight( const SwFmtFrmSize &rNew )
814 SET_CURR_SHELL( this );
815 StartAllAction();
816 GetDoc()->SetRowHeight( *getShellCrsr( false ), rNew );
817 EndAllActionAndCall();
820 /******************************************************************************
821 * SwTwips SwFEShell::GetRowHeight() const
822 ******************************************************************************/
823 void SwFEShell::GetRowHeight( SwFmtFrmSize *& rpSz ) const
825 GetDoc()->GetRowHeight( *getShellCrsr( false ), rpSz );
828 BOOL SwFEShell::BalanceRowHeight( BOOL bTstOnly )
830 SET_CURR_SHELL( this );
831 if( !bTstOnly )
832 StartAllAction();
833 BOOL bRet = GetDoc()->BalanceRowHeight( *getShellCrsr( false ), bTstOnly );
834 if( !bTstOnly )
835 EndAllActionAndCall();
836 return bRet;
839 /******************************************************************************
840 * void SwFEShell::SetRowBackground()
841 ******************************************************************************/
842 void SwFEShell::SetRowBackground( const SvxBrushItem &rNew )
844 SET_CURR_SHELL( this );
845 StartAllAction();
846 GetDoc()->SetRowBackground( *getShellCrsr( false ), rNew );
847 EndAllActionAndCall();
850 /******************************************************************************
851 * SwTwips SwFEShell::GetRowBackground() const
852 ******************************************************************************/
853 BOOL SwFEShell::GetRowBackground( SvxBrushItem &rToFill ) const
855 return GetDoc()->GetRowBackground( *getShellCrsr( false ), rToFill );
858 /***********************************************************************
859 #* Class : SwFEShell
860 #* Methoden : SetTabBorders(), GetTabBorders()
861 #* Datum : MA 18. May. 93
862 #* Update : JP 29.04.98
863 #***********************************************************************/
865 void SwFEShell::SetTabBorders( const SfxItemSet& rSet )
867 SET_CURR_SHELL( this );
868 StartAllAction();
869 GetDoc()->SetTabBorders( *getShellCrsr( false ), rSet );
870 EndAllActionAndCall();
873 void SwFEShell::SetTabLineStyle( const Color* pColor, BOOL bSetLine,
874 const SvxBorderLine* pBorderLine )
876 SET_CURR_SHELL( this );
877 StartAllAction();
878 GetDoc()->SetTabLineStyle( *getShellCrsr( false ),
879 pColor, bSetLine, pBorderLine );
880 EndAllActionAndCall();
883 void SwFEShell::GetTabBorders( SfxItemSet& rSet ) const
885 GetDoc()->GetTabBorders( *getShellCrsr( false ), rSet );
889 /***********************************************************************
890 #* Class : SwFEShell
891 #* Methoden : SetBoxBackground(), GetBoxBackground()
892 #* Datum : MA 01. Jun. 93
893 #* Update : MA 03. Jul. 96
894 #***********************************************************************/
895 void SwFEShell::SetBoxBackground( const SvxBrushItem &rNew )
897 SET_CURR_SHELL( this );
898 StartAllAction();
899 GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
900 EndAllActionAndCall();
903 BOOL SwFEShell::GetBoxBackground( SvxBrushItem &rToFill ) const
905 return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
908 /***********************************************************************
909 #* Class : SwFEShell
910 #* Methoden : SetBoxDirection(), GetBoxDirection()
911 #* Datum : FME 2004-02-03
912 #* Update : FME 2004-02-03
913 #***********************************************************************/
914 void SwFEShell::SetBoxDirection( const SvxFrameDirectionItem& rNew )
916 SET_CURR_SHELL( this );
917 StartAllAction();
918 GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
919 EndAllActionAndCall();
922 BOOL SwFEShell::GetBoxDirection( SvxFrameDirectionItem& rToFill ) const
924 return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
927 /***********************************************************************
928 #* Class : SwFEShell
929 #* Methoden : SetBoxAlign, SetBoxAlign
930 #* Datum : MA 18. Dec. 96
931 #* Update : JP 29.04.98
932 #***********************************************************************/
933 void SwFEShell::SetBoxAlign( USHORT nAlign )
935 SET_CURR_SHELL( this );
936 StartAllAction();
937 GetDoc()->SetBoxAlign( *getShellCrsr( false ), nAlign );
938 EndAllActionAndCall();
941 USHORT SwFEShell::GetBoxAlign() const
943 return GetDoc()->GetBoxAlign( *getShellCrsr( false ) );
946 /***********************************************************************
947 #* Class : SwFEShell
948 #* Methoden : SetTabBackground(), GetTabBackground()
949 #* Datum : MA 08. Jul. 96
950 #* Update : MA 08. Jul. 96
951 #***********************************************************************/
952 void SwFEShell::SetTabBackground( const SvxBrushItem &rNew )
954 SwFrm *pFrm = GetCurrFrm();
955 if( !pFrm || !pFrm->IsInTab() )
956 return;
958 SET_CURR_SHELL( this );
959 StartAllAction();
960 GetDoc()->SetAttr( rNew, *pFrm->ImplFindTabFrm()->GetFmt() );
961 EndAllAction(); //Kein Call, denn es veraendert sich nichts!
962 GetDoc()->SetModified();
965 void SwFEShell::GetTabBackground( SvxBrushItem &rToFill ) const
967 SwFrm *pFrm = GetCurrFrm();
968 if( pFrm && pFrm->IsInTab() )
969 rToFill = pFrm->ImplFindTabFrm()->GetFmt()->GetBackground();
973 /***********************************************************************
974 #* Class : SwFEShell
975 #* Methoden : HasWholeTabSelection()
976 #* Datum : MA 18. May. 93
977 #* Update : MA 20. Jul. 93
978 #***********************************************************************/
979 BOOL SwFEShell::HasWholeTabSelection() const
981 //Ist die ganze Tabelle Selektiert?
982 if ( IsTableMode() )
984 SwSelBoxes aBoxes;
985 ::GetTblSelCrs( *this, aBoxes );
986 if( aBoxes.Count() )
988 const SwTableNode *pTblNd = IsCrsrInTbl();
989 return ( pTblNd && aBoxes[0]->GetSttIdx()-1 == pTblNd->
990 EndOfSectionNode()->StartOfSectionIndex() &&
991 aBoxes[aBoxes.Count()-1]->GetSttNd()->EndOfSectionIndex()+1
992 == pTblNd->EndOfSectionIndex() );
995 return FALSE;
998 BOOL SwFEShell::HasBoxSelection() const
1000 if(!IsCrsrInTbl())
1001 return FALSE;
1002 //Ist die ganze Tabelle Selektiert?
1003 if( IsTableMode() )
1004 return TRUE;
1005 SwPaM* pPam = GetCrsr();
1006 // leere Boxen gelten auch ohne Selektion als selektiert
1007 // if( !pPam->HasMark() )
1008 // return FALSE;
1009 BOOL bChg = FALSE;
1010 if( pPam->GetPoint() == pPam->End())
1012 bChg = TRUE;
1013 pPam->Exchange();
1015 SwNode* pNd;
1016 if( pPam->GetPoint()->nNode.GetIndex() -1 ==
1017 ( pNd = pPam->GetNode())->StartOfSectionIndex() &&
1018 !pPam->GetPoint()->nContent.GetIndex() &&
1019 pPam->GetMark()->nNode.GetIndex() + 1 ==
1020 pNd->EndOfSectionIndex())
1022 SwNodeIndex aIdx( *pNd->EndOfSectionNode(), -1 );
1023 SwCntntNode* pCNd = GetDoc()->GetNodes()[ aIdx ]->GetCntntNode();
1024 if( !pCNd )
1026 pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
1027 ASSERT( pCNd, "kein ContentNode in der Box ??" );
1029 if( pPam->GetMark()->nContent == pCNd->Len() )
1031 if( bChg )
1032 pPam->Exchange();
1033 return TRUE;
1036 if( bChg )
1037 pPam->Exchange();
1038 return FALSE;
1041 /***********************************************************************
1042 #* Class : SwFEShell
1043 #* Methoden : ProtectCells(), UnProtectCells()
1044 #* Datum : MA 20. Jul. 93
1045 #* Update : JP 25. Sep. 93
1046 #***********************************************************************/
1047 void SwFEShell::ProtectCells()
1049 SvxProtectItem aProt( RES_PROTECT );
1050 aProt.SetCntntProtect( TRUE );
1052 SET_CURR_SHELL( this );
1053 StartAllAction();
1055 GetDoc()->SetBoxAttr( *getShellCrsr( false ), aProt );
1057 if( !IsCrsrReadonly() )
1059 if( IsTableMode() )
1060 ClearMark();
1061 ParkCursorInTab();
1063 EndAllActionAndCall();
1066 // die Tabellenselektion aufheben
1067 void SwFEShell::UnProtectCells()
1069 SET_CURR_SHELL( this );
1070 StartAllAction();
1072 SwSelBoxes aBoxes;
1073 if( IsTableMode() )
1074 ::GetTblSelCrs( *this, aBoxes );
1075 else
1077 SwFrm *pFrm = GetCurrFrm();
1078 do {
1079 pFrm = pFrm->GetUpper();
1080 } while ( pFrm && !pFrm->IsCellFrm() );
1081 if( pFrm )
1083 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1084 aBoxes.Insert( pBox );
1088 if( aBoxes.Count() )
1089 GetDoc()->UnProtectCells( aBoxes );
1091 EndAllActionAndCall();
1094 void SwFEShell::UnProtectTbls()
1096 SET_CURR_SHELL( this );
1097 StartAllAction();
1098 GetDoc()->UnProtectTbls( *GetCrsr() );
1099 EndAllActionAndCall();
1102 BOOL SwFEShell::HasTblAnyProtection( const String* pTblName,
1103 BOOL* pFullTblProtection )
1105 return GetDoc()->HasTblAnyProtection( GetCrsr()->GetPoint(), pTblName,
1106 pFullTblProtection );
1109 BOOL SwFEShell::CanUnProtectCells() const
1111 BOOL bUnProtectAvailable = FALSE;
1112 const SwTableNode *pTblNd = IsCrsrInTbl();
1113 if( pTblNd && !pTblNd->IsProtect() )
1115 SwSelBoxes aBoxes;
1116 if( IsTableMode() )
1117 ::GetTblSelCrs( *this, aBoxes );
1118 else
1120 SwFrm *pFrm = GetCurrFrm();
1121 do {
1122 pFrm = pFrm->GetUpper();
1123 } while ( pFrm && !pFrm->IsCellFrm() );
1124 if( pFrm )
1126 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1127 aBoxes.Insert( pBox );
1130 if( aBoxes.Count() )
1131 bUnProtectAvailable = ::HasProtectedCells( aBoxes );
1133 return bUnProtectAvailable;
1136 /***********************************************************************
1137 #* Class : SwFEShell
1138 #* Methoden : GetRowsToRepeat(), SetRowsToRepeat()
1139 #***********************************************************************/
1140 USHORT SwFEShell::GetRowsToRepeat() const
1142 const SwFrm *pFrm = GetCurrFrm();
1143 const SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
1144 if( pTab )
1145 return pTab->GetTable()->GetRowsToRepeat();
1146 return 0;
1149 void SwFEShell::SetRowsToRepeat( USHORT nSet )
1151 SwFrm *pFrm = GetCurrFrm();
1152 SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
1153 if( pTab && pTab->GetTable()->GetRowsToRepeat() != nSet )
1155 SwWait aWait( *GetDoc()->GetDocShell(), TRUE );
1156 SET_CURR_SHELL( this );
1157 StartAllAction();
1158 GetDoc()->SetRowsToRepeat( *pTab->GetTable(), nSet );
1159 EndAllActionAndCall();
1162 /*-- 30.06.2004 08:46:35---------------------------------------------------
1163 returns the number of rows consecutively selected from top
1164 -----------------------------------------------------------------------*/
1165 USHORT lcl_GetRowNumber( const SwPosition& rPos )
1167 USHORT nRet = USHRT_MAX;
1168 Point aTmpPt;
1169 const SwCntntNode *pNd;
1170 const SwCntntFrm *pFrm;
1172 if( 0 != ( pNd = rPos.nNode.GetNode().GetCntntNode() ))
1173 pFrm = pNd->GetFrm( &aTmpPt, &rPos, FALSE );
1174 else
1175 pFrm = 0;
1177 if ( pFrm && pFrm->IsInTab() )
1179 const SwFrm* pRow = pFrm->GetUpper();
1180 while ( !pRow->GetUpper()->IsTabFrm() )
1181 pRow = pRow->GetUpper();
1183 const SwTabFrm* pTabFrm = (const SwTabFrm*)pRow->GetUpper();
1184 const SwTableLine* pTabLine = static_cast<const SwRowFrm*>(pRow)->GetTabLine();
1186 USHORT nI = 0;
1187 while ( nI < pTabFrm->GetTable()->GetTabLines().Count() )
1189 if ( pTabFrm->GetTable()->GetTabLines()[ nI ] == pTabLine )
1191 nRet = nI;
1192 break;
1194 ++nI;
1198 return nRet;
1200 USHORT SwFEShell::GetRowSelectionFromTop() const
1202 USHORT nRet = 0;
1203 const SwPaM* pPaM = IsTableMode() ? GetTableCrsr() : _GetCrsr();
1204 const USHORT nPtLine = lcl_GetRowNumber( *pPaM->GetPoint() );
1206 if ( !IsTableMode() )
1208 nRet = 0 == nPtLine ? 1 : 0;
1210 else
1212 const USHORT nMkLine = lcl_GetRowNumber( *pPaM->GetMark() );
1214 if ( ( nPtLine == 0 && nMkLine != USHRT_MAX ) ||
1215 ( nMkLine == 0 && nPtLine != USHRT_MAX ) )
1217 nRet = Max( nPtLine, nMkLine ) + 1;
1221 return nRet;
1225 * 1. case: bRepeat = true
1226 * returns true if the current frame is located inside a table headline in
1227 * a follow frame
1229 * 2. case: bRepeat = false
1230 * returns true if the current frame is localed inside a table headline OR
1231 * inside the first line of a table!!!
1233 BOOL SwFEShell::CheckHeadline( bool bRepeat ) const
1235 BOOL bRet = FALSE;
1236 if ( !IsTableMode() )
1238 SwFrm *pFrm = GetCurrFrm(); // DONE MULTIIHEADER
1239 if ( pFrm && pFrm->IsInTab() )
1241 SwTabFrm* pTab = pFrm->FindTabFrm();
1242 if ( bRepeat )
1244 bRet = pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
1246 else
1248 bRet = ((SwLayoutFrm*)pTab->Lower())->IsAnLower( pFrm ) ||
1249 pTab->IsInHeadline( *pFrm );
1253 return bRet;
1256 /***********************************************************************
1257 #* Class : SwFEShell
1258 #* Methoden : AdjustCellWidth()
1259 #* Datum : MA 20. Feb. 95
1260 #* Update : MA 27. Jul. 95
1261 #***********************************************************************/
1263 void SwFEShell::AdjustCellWidth( BOOL bBalance )
1265 SET_CURR_SHELL( this );
1266 StartAllAction();
1268 //WarteCrsr immer einschalten, weil sich im vorraus nicht so recht
1269 //ermitteln laesst wieviel Inhalt betroffen ist.
1270 TblWait aWait( USHRT_MAX, 0, *GetDoc()->GetDocShell() );
1272 GetDoc()->AdjustCellWidth( *getShellCrsr( false ), bBalance );
1273 EndAllActionAndCall();
1276 BOOL SwFEShell::IsAdjustCellWidthAllowed( BOOL bBalance ) const
1278 //Es muss mindestens eine Zelle mit Inhalt in der Selektion enthalten
1279 //sein.
1281 SwFrm *pFrm = GetCurrFrm();
1282 if( !pFrm || !pFrm->IsInTab() )
1283 return FALSE;
1285 SwSelBoxes aBoxes;
1286 ::GetTblSelCrs( *this, aBoxes );
1288 if ( bBalance )
1289 return aBoxes.Count() > 1;
1291 if ( !aBoxes.Count() )
1294 { pFrm = pFrm->GetUpper();
1295 } while ( !pFrm->IsCellFrm() );
1296 SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1297 aBoxes.Insert( pBox );
1300 for ( USHORT i = 0; i < aBoxes.Count(); ++i )
1302 SwTableBox *pBox = aBoxes[i];
1303 if ( pBox->GetSttNd() )
1305 SwNodeIndex aIdx( *pBox->GetSttNd(), 1 );
1306 SwTxtNode* pCNd = aIdx.GetNode().GetTxtNode();
1307 if( !pCNd )
1308 pCNd = (SwTxtNode*)GetDoc()->GetNodes().GoNext( &aIdx );
1310 while ( pCNd )
1312 if ( pCNd->GetTxt().Len() )
1313 return TRUE;
1314 ++aIdx;
1315 pCNd = GetDoc()->GetNodes()[ aIdx ]->GetTxtNode();
1319 return FALSE;
1322 // AutoFormat fuer die Tabelle/TabellenSelection
1323 BOOL SwFEShell::SetTableAutoFmt( const SwTableAutoFmt& rNew )
1325 SwTableNode *pTblNd = (SwTableNode*)IsCrsrInTbl();
1326 if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
1327 return FALSE;
1329 SwSelBoxes aBoxes;
1331 if ( !IsTableMode() ) // falls Crsr noch nicht akt. sind
1332 GetCrsr();
1334 // gesamte Tabelle oder nur auf die akt. Selektion
1335 if( IsTableMode() )
1336 ::GetTblSelCrs( *this, aBoxes );
1337 else
1339 const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
1340 for( USHORT n = 0; n < rTBoxes.Count(); ++n )
1342 SwTableBox* pBox = rTBoxes[ n ];
1343 aBoxes.Insert( pBox );
1347 BOOL bRet;
1348 if( aBoxes.Count() )
1350 SET_CURR_SHELL( this );
1351 StartAllAction();
1352 bRet = GetDoc()->SetTableAutoFmt( aBoxes, rNew );
1353 DELETEZ( pLastCols );
1354 DELETEZ( pLastRows );
1355 EndAllActionAndCall();
1357 else
1358 bRet = FALSE;
1359 return bRet;
1362 BOOL SwFEShell::GetTableAutoFmt( SwTableAutoFmt& rGet )
1364 const SwTableNode *pTblNd = IsCrsrInTbl();
1365 if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
1366 return FALSE;
1368 SwSelBoxes aBoxes;
1370 if ( !IsTableMode() ) // falls Crsr noch nicht akt. sind
1371 GetCrsr();
1373 // gesamte Tabelle oder nur auf die akt. Selektion
1374 if( IsTableMode() )
1375 ::GetTblSelCrs( *this, aBoxes );
1376 else
1378 const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
1379 for( USHORT n = 0; n < rTBoxes.Count(); ++n )
1381 SwTableBox* pBox = rTBoxes[ n ];
1382 aBoxes.Insert( pBox );
1386 return GetDoc()->GetTableAutoFmt( aBoxes, rGet );
1389 /***********************************************************************
1390 #* Class : SwFEShell
1391 #* Methoden : DeleteTblSel()
1392 #* Datum : MA 03. May. 93
1393 #* Update : MA 19. Apr. 95
1394 #***********************************************************************/
1395 BOOL SwFEShell::DeleteTblSel()
1397 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
1398 SwFrm *pFrm = GetCurrFrm();
1399 if( !pFrm || !pFrm->IsInTab() )
1400 return FALSE;
1402 if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
1404 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
1405 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
1406 return FALSE;
1409 SET_CURR_SHELL( this );
1410 StartAllAction();
1412 // lasse ueber das Layout die Boxen suchen
1413 BOOL bRet;
1414 SwSelBoxes aBoxes;
1415 GetTblSelCrs( *this, aBoxes );
1416 if( aBoxes.Count() )
1418 TblWait( aBoxes.Count(), pFrm, *GetDoc()->GetDocShell() );
1420 // die Crsr muessen noch aus dem Loesch Bereich entfernt
1421 // werden. Setze sie immer hinter/auf die Tabelle; ueber die
1422 // Dokument-Position werden sie dann immer an die alte Position gesetzt.
1423 while( !pFrm->IsCellFrm() )
1424 pFrm = pFrm->GetUpper();
1425 ParkCrsr( SwNodeIndex( *((SwCellFrm*)pFrm)->GetTabBox()->GetSttNd() ));
1427 bRet = GetDoc()->DeleteRowCol( aBoxes );
1429 DELETEZ( pLastCols );
1430 DELETEZ( pLastRows );
1432 else
1433 bRet = FALSE;
1434 EndAllActionAndCall();
1435 return bRet;
1438 /*************************************************************************
1440 |* SwFEShell::GetCurTabColNum()
1442 |* Ersterstellung MA 03. Feb. 95
1443 |* Letzte Aenderung MA 21. May. 95
1445 |*************************************************************************/
1446 USHORT SwFEShell::GetCurTabColNum() const
1448 //!!!GetCurMouseTabColNum() mitpflegen!!!!
1449 USHORT nRet = 0;
1451 SwFrm *pFrm = GetCurrFrm();
1452 ASSERT( pFrm, "Crsr geparkt?" );
1454 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
1455 if( pFrm && pFrm->IsInTab() )
1457 do { // JP 26.09.95: warum mit dem CntntFrame und nicht mit
1458 // dem CellFrame vergleichen????
1459 pFrm = pFrm->GetUpper();
1460 } while ( !pFrm->IsCellFrm() );
1461 SWRECTFN( pFrm )
1463 const SwPageFrm* pPage = pFrm->FindPageFrm();
1465 //TabCols besorgen, den nur ueber diese erreichen wir die Position.
1466 SwTabCols aTabCols;
1467 GetTabCols( aTabCols );
1469 if( pFrm->FindTabFrm()->IsRightToLeft() )
1471 long nX = (pFrm->Frm().*fnRect->fnGetRight)() - (pPage->Frm().*fnRect->fnGetLeft)();
1473 const long nRight = aTabCols.GetLeftMin() + aTabCols.GetRight();;
1475 if ( !::IsSame( nX, nRight ) )
1477 nX = nRight - nX + aTabCols.GetLeft();
1478 for ( USHORT i = 0; i < aTabCols.Count(); ++i )
1479 if ( ::IsSame( nX, aTabCols[i] ) )
1481 nRet = i + 1;
1482 break;
1486 else
1488 const long nX = (pFrm->Frm().*fnRect->fnGetLeft)() -
1489 (pPage->Frm().*fnRect->fnGetLeft)();
1491 const long nLeft = aTabCols.GetLeftMin();
1493 if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
1495 for ( USHORT i = 0; i < aTabCols.Count(); ++i )
1496 if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
1498 nRet = i + 1;
1499 break;
1504 return nRet;
1507 /*************************************************************************
1509 |* SwFEShell::GetBox()
1511 |* Ersterstellung MA 22. Jun. 95
1512 |* Letzte Aenderung MA 21. Nov. 96
1514 |*************************************************************************/
1516 const SwFrm *lcl_FindFrmInTab( const SwLayoutFrm *pLay, const Point &rPt, SwTwips nFuzzy )
1518 const SwFrm *pFrm = pLay->Lower();
1520 while( pFrm && pLay->IsAnLower( pFrm ) )
1522 if ( pFrm->Frm().IsNear( rPt, nFuzzy ) )
1524 if ( pFrm->IsLayoutFrm() )
1526 const SwFrm *pTmp = ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, rPt, nFuzzy );
1527 if ( pTmp )
1528 return pTmp;
1531 return pFrm;
1534 pFrm = pFrm->FindNext();
1537 return 0;
1540 const SwCellFrm *lcl_FindFrm( const SwLayoutFrm *pLay, const Point &rPt,
1541 SwTwips nFuzzy, bool* pbRow, bool* pbCol )
1543 // bMouseMoveRowCols :
1544 // Method is called for
1545 // - Moving columns/rows with the mouse or
1546 // - Enhanced table selection
1547 const bool bMouseMoveRowCols = 0 == pbCol;
1549 bool bCloseToRow = false;
1550 bool bCloseToCol = false;
1552 const SwFrm *pFrm = pLay->ContainsCntnt();
1553 const SwFrm* pRet = 0;
1555 if ( pFrm )
1559 if ( pFrm->IsInTab() )
1560 pFrm = ((SwFrm*)pFrm)->ImplFindTabFrm();
1562 if ( pFrm->IsTabFrm() )
1564 Point aPt( rPt );
1565 bool bSearchForFrmInTab = true;
1566 SwTwips nTmpFuzzy = nFuzzy;
1568 if ( !bMouseMoveRowCols )
1570 // We ignore nested tables for the enhanced table selection:
1571 while ( pFrm->GetUpper()->IsInTab() )
1572 pFrm = pFrm->GetUpper()->FindTabFrm();
1574 // We first check if the given point is 'close' to the left or top
1575 // border of the table frame:
1576 ASSERT( pFrm, "Nested table frame without outer table" )
1577 SWRECTFN( pFrm )
1578 const bool bRTL = pFrm->IsRightToLeft();
1580 SwRect aTabRect = pFrm->Prt();
1581 aTabRect.Pos() += pFrm->Frm().Pos();
1583 const SwTwips nLeft = bRTL ?
1584 (aTabRect.*fnRect->fnGetRight)() :
1585 (aTabRect.*fnRect->fnGetLeft)();
1586 const SwTwips nTop = (aTabRect.*fnRect->fnGetTop)();
1588 SwTwips& rPointX = bVert ? aPt.Y() : aPt.X();
1589 SwTwips& rPointY = bVert ? aPt.X() : aPt.Y();
1591 const SwTwips nXDiff = (*fnRect->fnXDiff)( nLeft, rPointX ) * ( bRTL ? (-1) : 1 );
1592 const SwTwips nYDiff = (*fnRect->fnYDiff)( nTop, rPointY );
1594 bCloseToRow = nXDiff >= 0 && nXDiff < nFuzzy;
1595 bCloseToCol = nYDiff >= 0 && nYDiff < nFuzzy;
1597 if ( bCloseToCol && 2 * nYDiff > nFuzzy )
1599 const SwFrm* pPrev = pFrm->GetPrev();
1600 if ( pPrev )
1602 SwRect aPrevRect = pPrev->Prt();
1603 aPrevRect.Pos() += pPrev->Frm().Pos();
1605 if( aPrevRect.IsInside( rPt ) )
1607 bCloseToCol = false;
1613 // If we found the point to be 'close' to the left or top border
1614 // of the table frame, we adjust the point to be on that border:
1615 if ( bCloseToRow && bCloseToCol )
1616 aPt = bRTL ? aTabRect.TopRight() : (aTabRect.*fnRect->fnGetPos)();
1617 else if ( bCloseToRow )
1618 rPointX = nLeft;
1619 else if ( bCloseToCol )
1620 rPointY = nTop;
1622 if ( !bCloseToRow && !bCloseToCol )
1623 bSearchForFrmInTab = false;
1625 // Since the point has been adjusted, we call lcl_FindFrmInTab()
1626 // with a fuzzy value of 1:
1627 nTmpFuzzy = 1;
1630 const SwFrm* pTmp = bSearchForFrmInTab ?
1631 ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, aPt, nTmpFuzzy ) :
1634 if ( pTmp )
1636 pFrm = pTmp;
1637 break;
1640 pFrm = pFrm->FindNextCnt();
1642 } while ( pFrm && pLay->IsAnLower( pFrm ) );
1645 if ( pFrm && pFrm->IsInTab() && pLay->IsAnLower( pFrm ) )
1649 // We allow mouse drag of table borders within nested tables,
1650 // but disallow hotspot selection of nested tables.
1651 if ( bMouseMoveRowCols )
1653 // find the next cell frame
1654 while ( pFrm && !pFrm->IsCellFrm() )
1655 pFrm = pFrm->GetUpper();
1657 else
1659 // find the most upper cell frame:
1660 while ( pFrm &&
1661 ( !pFrm->IsCellFrm() ||
1662 !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
1663 pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
1664 pFrm = pFrm->GetUpper();
1667 if ( pFrm ) // Note: this condition should be the same like the while condition!!!
1669 // --> FME 2004-07-30 #i32329# Enhanced table selection
1670 // used for hotspot selection of tab/cols/rows
1671 if ( !bMouseMoveRowCols )
1674 ASSERT( pbCol && pbRow, "pbCol or pbRow missing" )
1676 if ( bCloseToRow || bCloseToCol )
1678 *pbRow = bCloseToRow;
1679 *pbCol = bCloseToCol;
1680 pRet = pFrm;
1681 break;
1684 // <--
1685 else
1687 // used for mouse move of columns/rows
1688 const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
1689 SwRect aTabRect = pTabFrm->Prt();
1690 aTabRect.Pos() += pTabFrm->Frm().Pos();
1692 SWRECTFN( pTabFrm )
1694 const SwTwips nTabTop = (aTabRect.*fnRect->fnGetTop)();
1695 const SwTwips nMouseTop = bVert ? rPt.X() : rPt.Y();
1697 // Do not allow to drag upper table border:
1698 if ( !::IsSame( nTabTop, nMouseTop ) )
1700 if ( ::IsSame( pFrm->Frm().Left(), rPt.X() ) ||
1701 ::IsSame( pFrm->Frm().Right(),rPt.X() ) )
1703 if ( pbRow ) *pbRow = false;
1704 pRet = pFrm;
1705 break;
1707 if ( ::IsSame( pFrm->Frm().Top(), rPt.Y() ) ||
1708 ::IsSame( pFrm->Frm().Bottom(),rPt.Y() ) )
1710 if ( pbRow ) *pbRow = true;
1711 pRet = pFrm;
1712 break;
1717 pFrm = pFrm->GetUpper();
1719 } while ( pFrm );
1722 // robust:
1723 ASSERT( !pRet || pRet->IsCellFrm(), "lcl_FindFrm() is supposed to find a cell frame!" )
1724 return pRet && pRet->IsCellFrm() ? static_cast<const SwCellFrm*>(pRet) : 0;
1728 // pbCol = 0 => Used for moving table rows/cols with mouse
1729 // pbCol != 0 => Used for selecting table/rows/cols
1731 #define ENHANCED_TABLE_SELECTION_FUZZY 10
1733 const SwFrm* SwFEShell::GetBox( const Point &rPt, bool* pbRow, bool* pbCol ) const
1735 const SwPageFrm *pPage = (SwPageFrm*)GetLayout()->Lower();
1736 Window* pOutWin = GetWin();
1737 SwTwips nFuzzy = COLFUZZY;
1738 if( pOutWin )
1740 // --> FME 2004-07-30 #i32329# Enhanced table selection
1741 SwTwips nSize = pbCol ? ENHANCED_TABLE_SELECTION_FUZZY : RULER_MOUSE_MARGINWIDTH;
1742 // <--
1743 Size aTmp( nSize, nSize );
1744 aTmp = pOutWin->PixelToLogic( aTmp );
1745 nFuzzy = aTmp.Width();
1748 while ( pPage && !pPage->Frm().IsNear( rPt, nFuzzy ) )
1749 pPage = (SwPageFrm*)pPage->GetNext();
1751 const SwCellFrm *pFrm = 0;
1752 if ( pPage )
1754 //Per GetCrsrOfst oder GetCntntPos koennen wir hier die Box leider
1755 //nicht suchen. Das wuerde zu einem Performance-Zusammenbruch bei
1756 //Dokumenten mit vielen Absaetzen/Tabellen auf einer Seite fuehren
1757 //(BrowseMode!)
1759 //Erst die Flys checken.
1760 if ( pPage->GetSortedObjs() )
1762 for ( USHORT i = 0; !pFrm && i < pPage->GetSortedObjs()->Count(); ++i )
1764 SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
1765 if ( pObj->ISA(SwFlyFrm) )
1767 pFrm = lcl_FindFrm( static_cast<SwFlyFrm*>(pObj),
1768 rPt, nFuzzy, pbRow, pbCol );
1772 const SwLayoutFrm *pLay = (SwLayoutFrm*)pPage->Lower();
1773 while ( pLay && !pFrm )
1775 pFrm = lcl_FindFrm( pLay, rPt, nFuzzy, pbRow, pbCol );
1776 pLay = (SwLayoutFrm*)pLay->GetNext();
1779 return pFrm;
1782 /* Helper function*/
1783 /* calculated the distance between Point rC and Line Segment (rA, rB) */
1784 double lcl_DistancePoint2Segment( const Point& rA, const Point& rB, const Point& rC )
1786 double nRet = 0;
1788 const basegfx::B2DVector aBC( rC.X() - rB.X(), rC.Y() - rB.Y() );
1789 const basegfx::B2DVector aAB( rB.X() - rA.X(), rB.Y() - rA.Y() );
1790 const double nDot1 = aBC.scalar( aAB );
1792 if ( nDot1 > 0 ) // check outside case 1
1793 nRet = aBC.getLength();
1794 else
1796 const basegfx::B2DVector aAC( rC.X() - rA.X(), rC.Y() - rA.Y() );
1797 const basegfx::B2DVector aBA( rA.X() - rB.X(), rA.Y() - rB.Y() );
1798 const double nDot2 = aAC.scalar( aBA );
1800 if ( nDot2 > 0 ) // check outside case 2
1801 nRet = aAC.getLength();
1802 else
1804 const double nDiv = aAB.getLength();
1805 nRet = nDiv ? aAB.cross( aAC ) / nDiv : 0;
1809 return Abs(nRet);
1812 /* Helper function*/
1813 Point lcl_ProjectOntoClosestTableFrm( const SwTabFrm& rTab, const Point& rPoint, bool bRowDrag )
1815 Point aRet( rPoint );
1816 const SwTabFrm* pCurrentTab = &rTab;
1817 const bool bVert = pCurrentTab->IsVertical();
1818 const bool bRTL = pCurrentTab->IsRightToLeft();
1820 // Western Layout:
1821 // bRowDrag = true => compare to left border of table
1822 // bRowDrag = false => compare to top border of table
1824 // Asian Layout:
1825 // bRowDrag = true => compare to right border of table
1826 // bRowDrag = false => compare to top border of table
1828 // RTL Layout:
1829 // bRowDrag = true => compare to right border of table
1830 // bRowDrag = false => compare to top border of table
1831 bool bLeft = false;
1832 bool bRight = false;
1834 if ( bRowDrag )
1836 if ( bVert || bRTL )
1837 bRight = true;
1838 else
1839 bLeft = true;
1842 // used to find the minimal distance
1843 double nMin = -1;
1844 Point aMin1;
1845 Point aMin2;
1847 Point aS1;
1848 Point aS2;
1850 while ( pCurrentTab )
1852 SwRect aTabRect( pCurrentTab->Prt() );
1853 aTabRect += pCurrentTab->Frm().Pos();
1855 if ( bLeft )
1857 // distance to left table border
1858 aS1 = aTabRect.TopLeft();
1859 aS2 = aTabRect.BottomLeft();
1861 else if ( bRight )
1863 // distance to right table border
1864 aS1 = aTabRect.TopRight();
1865 aS2 = aTabRect.BottomRight();
1867 else //if ( bTop )
1869 // distance to top table border
1870 aS1 = aTabRect.TopLeft();
1871 aS2 = aTabRect.TopRight();
1874 const double nDist = lcl_DistancePoint2Segment( aS1, aS2, rPoint );
1876 if ( nDist < nMin || -1 == nMin )
1878 aMin1 = aS1;
1879 aMin2 = aS2;
1880 nMin = nDist;
1883 pCurrentTab = pCurrentTab->GetFollow();
1886 // project onto closest line:
1887 if ( bLeft || bRight )
1889 aRet.X() = aMin1.X();
1890 if ( aRet.Y() > aMin2.Y() )
1891 aRet.Y() = aMin2.Y();
1892 else if ( aRet.Y() < aMin1.Y() )
1893 aRet.Y() = aMin1.Y();
1895 else //if ( bTop )
1897 aRet.Y() = aMin1.Y();
1898 if ( aRet.X() > aMin2.X() )
1899 aRet.X() = aMin2.X();
1900 else if ( aRet.X() < aMin1.X() )
1901 aRet.X() = aMin1.X();
1904 return aRet;
1907 // --> FME 2004-07-30 #i32329# Enhanced table selection
1908 bool SwFEShell::SelTblRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag )
1910 bool bRet = false;
1911 Point aEndPt;
1912 if ( pEnd )
1913 aEndPt = *pEnd;
1915 SwPosition* ppPos[2] = { 0, 0 };
1916 Point paPt [2] = { rPt, aEndPt };
1917 bool pbRow[2] = { 0, 0 };
1918 bool pbCol[2] = { 0, 0 };
1920 // pEnd is set during dragging.
1921 for ( USHORT i = 0; i < ( pEnd ? 2 : 1 ); ++i )
1923 const SwCellFrm* pFrm =
1924 static_cast<const SwCellFrm*>(GetBox( paPt[i], &pbRow[i], &pbCol[i] ) );
1926 if( pFrm )
1928 while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
1929 pFrm = static_cast<const SwCellFrm*>( static_cast<const SwLayoutFrm*>( pFrm->Lower() )->Lower() );
1930 if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
1931 pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
1932 pFrm = 0;
1935 if ( pFrm )
1937 const SwCntntFrm* pCntnt = ::GetCellCntnt( *pFrm );
1939 if ( pCntnt && pCntnt->IsTxtFrm() )
1941 ppPos[i] = new SwPosition( *pCntnt->GetNode() );
1942 ppPos[i]->nContent.Assign( const_cast<SwCntntNode*>(pCntnt->GetNode()), 0 );
1944 // paPt[i] will not be used any longer, now we use it to store
1945 // a position inside the content frame
1946 paPt[i] = pCntnt->Frm().Center();
1950 // no calculation of end frame if start frame has not been found.
1951 if ( 1 == i || !ppPos[0] || !pEnd )
1952 break;
1954 // find 'closest' table frame to pEnd:
1955 const SwTabFrm* pCurrentTab = pFrm->FindTabFrm();
1956 if ( pCurrentTab->IsFollow() )
1957 pCurrentTab = pCurrentTab->FindMaster( true );
1959 const Point aProjection = lcl_ProjectOntoClosestTableFrm( *pCurrentTab, *pEnd, bRowDrag );
1960 paPt[1] = aProjection;
1963 if ( ppPos[0] )
1965 SwShellCrsr* pCrsr = _GetCrsr();
1966 SwCrsrSaveState aSaveState( *pCrsr );
1967 SwPosition aOldPos( *pCrsr->GetPoint() );
1969 pCrsr->DeleteMark();
1970 *pCrsr->GetPoint() = *ppPos[0];
1971 pCrsr->GetPtPos() = paPt[0];
1973 if ( !pCrsr->IsInProtectTable( FALSE, TRUE ) )
1975 bool bNewSelection = true;
1977 if ( ppPos[1] )
1979 if ( ppPos[1]->nNode.GetNode().StartOfSectionNode() !=
1980 aOldPos.nNode.GetNode().StartOfSectionNode() )
1982 pCrsr->SetMark();
1983 SwCrsrSaveState aSaveState2( *pCrsr );
1984 *pCrsr->GetPoint() = *ppPos[1];
1985 pCrsr->GetPtPos() = paPt[1];
1987 if ( pCrsr->IsInProtectTable( FALSE, FALSE ) )
1989 pCrsr->RestoreSavePos();
1990 bNewSelection = false;
1993 else
1995 pCrsr->RestoreSavePos();
1996 bNewSelection = false;
2000 if ( bNewSelection )
2002 // --> FME 2004-10-20 #i35543# SelTblRowCol should remove any existing
2003 // table cursor:
2004 if ( IsTableMode() )
2005 TblCrsrToCursor();
2006 // <--
2008 if ( pbRow[0] && pbCol[0] )
2009 bRet = SwCrsrShell::SelTbl();
2010 else if ( pbRow[0] )
2011 bRet = SwCrsrShell::_SelTblRowOrCol( true, true );
2012 else if ( pbCol[0] )
2013 bRet = SwCrsrShell::_SelTblRowOrCol( false, true );
2015 else
2016 bRet = true;
2019 delete ppPos[0];
2020 delete ppPos[1];
2023 return bRet;
2025 // <--
2028 /*************************************************************************
2030 |* SwFEShell::WhichMouseTabCol()
2032 |* Ersterstellung MA 22. Jun. 95
2033 |* Last change AMA 12. Jun. 02
2035 |*************************************************************************/
2036 BYTE SwFEShell::WhichMouseTabCol( const Point &rPt ) const
2038 BYTE nRet = SW_TABCOL_NONE;
2039 bool bRow = false;
2040 bool bCol = false;
2041 bool bSelect = false;
2043 // First try: Do we get the row/col move cursor?
2044 SwCellFrm* pFrm = (SwCellFrm*)GetBox( rPt, &bRow, 0 );
2046 if ( !pFrm )
2048 // Second try: Do we get the row/col/tab selection cursor?
2049 pFrm = (SwCellFrm*)GetBox( rPt, &bRow, &bCol );
2050 bSelect = true;
2053 if( pFrm )
2055 while( pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
2056 pFrm = (SwCellFrm*)((SwLayoutFrm*)pFrm->Lower())->Lower();
2057 if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
2058 pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
2059 pFrm = 0;
2062 if( pFrm )
2064 if ( !bSelect )
2066 if ( pFrm->IsVertical() )
2067 nRet = bRow ? SW_TABCOL_VERT : SW_TABROW_VERT;
2068 else
2069 nRet = bRow ? SW_TABROW_HORI : SW_TABCOL_HORI;
2071 else
2073 const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
2074 if ( pTabFrm->IsVertical() )
2076 if ( bRow && bCol )
2078 nRet = SW_TABSEL_VERT;
2080 else if ( bRow )
2082 nRet = SW_TABROWSEL_VERT;
2084 else if ( bCol )
2086 nRet = SW_TABCOLSEL_VERT;
2089 else
2091 if ( bRow && bCol )
2093 nRet = pTabFrm->IsRightToLeft() ?
2094 SW_TABSEL_HORI_RTL :
2095 SW_TABSEL_HORI;
2097 else if ( bRow )
2099 nRet = pTabFrm->IsRightToLeft() ?
2100 SW_TABROWSEL_HORI_RTL :
2101 SW_TABROWSEL_HORI;
2103 else if ( bCol )
2105 nRet = SW_TABCOLSEL_HORI;
2111 return nRet;
2114 // -> #i23726#
2115 SwTxtNode * SwFEShell::GetNumRuleNodeAtPos( const Point &rPt)
2117 SwTxtNode * pResult = NULL;
2119 SwContentAtPos aCntntAtPos
2120 (SwContentAtPos::SW_NUMLABEL);
2122 if( GetContentAtPos(rPt, aCntntAtPos) && aCntntAtPos.aFnd.pNode)
2123 pResult = aCntntAtPos.aFnd.pNode->GetTxtNode();
2125 return pResult;
2128 BOOL SwFEShell::IsNumLabel( const Point &rPt, int nMaxOffset )
2130 BOOL bResult = FALSE;
2132 SwContentAtPos aCntntAtPos
2133 (SwContentAtPos::SW_NUMLABEL);
2135 if( GetContentAtPos(rPt, aCntntAtPos))
2137 if ((nMaxOffset >= 0 && aCntntAtPos.nDist <= nMaxOffset) ||
2138 (nMaxOffset < 0))
2139 bResult = TRUE;
2142 return bResult;
2144 // <- #i23726#
2146 // --> OD 2005-02-21 #i42921#
2147 bool SwFEShell::IsVerticalModeAtNdAndPos( const SwTxtNode& _rTxtNode,
2148 const Point& _rDocPos ) const
2150 bool bRet( false );
2152 const short nTextDir =
2153 _rTxtNode.GetTextDirection( SwPosition(_rTxtNode), &_rDocPos );
2154 switch ( nTextDir )
2156 case -1:
2157 case FRMDIR_HORI_RIGHT_TOP:
2158 case FRMDIR_HORI_LEFT_TOP:
2160 bRet = false;
2162 break;
2163 case FRMDIR_VERT_TOP_LEFT:
2164 case FRMDIR_VERT_TOP_RIGHT:
2166 bRet = true;
2168 break;
2171 return bRet;
2173 // <--
2175 /*************************************************************************
2177 |* SwFEShell::GetMouseTabCols()
2179 |* Ersterstellung MA 22. Jun. 95
2180 |* Letzte Aenderung MA 27. Aug. 96
2182 |*************************************************************************/
2183 void SwFEShell::GetMouseTabCols( SwTabCols &rToFill, const Point &rPt ) const
2185 const SwFrm *pBox = GetBox( rPt );
2186 if ( pBox )
2187 _GetTabCols( rToFill, pBox );
2190 void SwFEShell::SetMouseTabCols( const SwTabCols &rNew, BOOL bCurRowOnly,
2191 const Point &rPt )
2193 const SwFrm *pBox = GetBox( rPt );
2194 if( pBox )
2196 SET_CURR_SHELL( this );
2197 StartAllAction();
2198 GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
2199 EndAllActionAndCall();
2203 /*************************************************************************
2205 |* SwFEShell::GetMouseColNum(), GetMouseTabColNum()
2207 |* Ersterstellung MA 04. Jul. 95
2208 |* Letzte Aenderung MA 04. Jul. 95
2210 |*************************************************************************/
2211 USHORT SwFEShell::GetCurMouseColNum( const Point &rPt,
2212 SwGetCurColNumPara* pPara ) const
2214 return _GetCurColNum( GetBox( rPt ), pPara );
2217 USHORT SwFEShell::GetCurMouseTabColNum( const Point &rPt ) const
2219 //!!!GetCurTabColNum() mitpflegen!!!!
2220 USHORT nRet = 0;
2222 const SwFrm *pFrm = GetBox( rPt );
2223 ASSERT( pFrm, "Table not found" );
2224 if( pFrm )
2226 const long nX = pFrm->Frm().Left();
2228 //TabCols besorgen, den nur ueber diese erreichen wir die Position.
2229 SwTabCols aTabCols;
2230 GetMouseTabCols( aTabCols, rPt );
2232 const long nLeft = aTabCols.GetLeftMin();
2234 if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
2236 for ( USHORT i = 0; i < aTabCols.Count(); ++i )
2237 if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
2239 nRet = i + 1;
2240 break;
2244 return nRet;
2247 void ClearFEShellTabCols()
2249 DELETEZ( pLastCols );
2250 DELETEZ( pLastRows );
2253 /*************************************************************************
2255 |* SwFEShell::GetTblAttr(), SetTblAttr()
2257 |* Ersterstellung MA 09. Dec. 96
2258 |* Letzte Aenderung MA 09. Dec. 96
2260 |*************************************************************************/
2261 void SwFEShell::GetTblAttr( SfxItemSet &rSet ) const
2263 SwFrm *pFrm = GetCurrFrm();
2264 if( pFrm && pFrm->IsInTab() )
2265 rSet.Put( pFrm->ImplFindTabFrm()->GetFmt()->GetAttrSet() );
2268 void SwFEShell::SetTblAttr( const SfxItemSet &rNew )
2270 SwFrm *pFrm = GetCurrFrm();
2271 if( pFrm && pFrm->IsInTab() )
2273 SET_CURR_SHELL( this );
2274 StartAllAction();
2275 SwTabFrm *pTab = pFrm->FindTabFrm();
2276 pTab->GetTable()->SetHTMLTableLayout( 0 );
2277 GetDoc()->SetAttr( rNew, *pTab->GetFmt() );
2278 GetDoc()->SetModified();
2279 EndAllActionAndCall();
2283 /** move cursor within a table into previous/next row (same column)
2284 * @param pShell cursor shell whose cursor is to be moved
2285 * @param bUp true: move up, false: move down
2286 * @returns true if successful
2288 bool lcl_GoTableRow( SwCrsrShell* pShell, bool bUp )
2290 ASSERT( pShell != NULL, "need shell" );
2292 bool bRet = false;
2294 SwPaM* pPam = pShell->GetCrsr();
2295 const SwStartNode* pTableBox = pPam->GetNode()->FindTableBoxStartNode();
2296 ASSERT( pTableBox != NULL, "I'm living in a box... NOT!" );
2298 // move cursor to start node of table box
2299 pPam->GetPoint()->nNode = pTableBox->GetIndex();
2300 pPam->GetPoint()->nContent.Assign( NULL, 0 );
2301 GoInCntnt( *pPam, fnMoveForward );
2303 // go to beginning end of table box
2304 SwPosSection fnPosSect = bUp ? fnSectionStart : fnSectionEnd;
2305 pShell->MoveSection( fnSectionCurr, fnPosSect );
2307 // and go up/down into next content
2308 bRet = bUp ? pShell->Up() : pShell->Down();
2310 return bRet;
2313 // aender eine Zellenbreite/-Hoehe/Spaltenbreite/Zeilenhoehe
2314 BOOL SwFEShell::SetColRowWidthHeight( USHORT eType, USHORT nDiff )
2316 SwFrm *pFrm = GetCurrFrm();
2317 if( !pFrm || !pFrm->IsInTab() )
2318 return FALSE;
2320 if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType &&
2321 pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
2323 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
2324 ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
2325 return FALSE;
2328 SET_CURR_SHELL( this );
2329 StartAllAction();
2331 do {
2332 pFrm = pFrm->GetUpper();
2333 } while( !pFrm->IsCellFrm() );
2335 SwTabFrm *pTab = pFrm->ImplFindTabFrm();
2337 // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2338 // dann muss es jetzt auf absolute umgerechnet werden.
2339 const SwFmtFrmSize& rTblFrmSz = pTab->GetFmt()->GetFrmSize();
2340 SWRECTFN( pTab )
2341 long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
2342 if( TBLVAR_CHGABS == pTab->GetTable()->GetTblChgMode() &&
2343 ( eType & nsTblChgWidthHeightType::WH_COL_LEFT || eType & nsTblChgWidthHeightType::WH_COL_RIGHT ) &&
2344 text::HoriOrientation::NONE == pTab->GetFmt()->GetHoriOrient().GetHoriOrient() &&
2345 nPrtWidth != rTblFrmSz.GetWidth() )
2347 SwFmtFrmSize aSz( rTblFrmSz );
2348 aSz.SetWidth( pTab->Prt().Width() );
2349 pTab->GetFmt()->SetFmtAttr( aSz );
2352 if( (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) ==
2353 (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL) )
2355 nDiff = USHORT((pFrm->Frm().*fnRect->fnGetWidth)());
2357 // we must move the cursor outside the current cell before
2358 // deleting the cells.
2359 TblChgWidthHeightType eTmp =
2360 static_cast<TblChgWidthHeightType>( eType & 0xfff );
2361 switch( eTmp )
2363 case nsTblChgWidthHeightType::WH_ROW_TOP:
2364 lcl_GoTableRow( this, true );
2365 break;
2366 case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
2367 lcl_GoTableRow( this, false );
2368 break;
2369 case nsTblChgWidthHeightType::WH_COL_LEFT:
2370 GoPrevCell();
2371 break;
2372 case nsTblChgWidthHeightType::WH_COL_RIGHT:
2373 GoNextCell();
2374 break;
2375 default:
2376 break;
2380 SwTwips nLogDiff = nDiff;
2381 nLogDiff *= pTab->GetFmt()->GetFrmSize().GetWidth();
2382 nLogDiff /= nPrtWidth;
2384 /** The cells are destroyed in here */
2385 BOOL bRet = GetDoc()->SetColRowWidthHeight(
2386 *(SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(),
2387 eType, nDiff, nLogDiff );
2389 delete pLastCols, pLastCols = 0;
2390 EndAllActionAndCall();
2392 if( bRet && (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) == nsTblChgWidthHeightType::WH_FLAG_INSDEL )
2394 switch(eType & ~(nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL))
2396 case nsTblChgWidthHeightType::WH_CELL_LEFT:
2397 case nsTblChgWidthHeightType::WH_COL_LEFT:
2398 GoPrevCell();
2399 break;
2401 case nsTblChgWidthHeightType::WH_CELL_RIGHT:
2402 case nsTblChgWidthHeightType::WH_COL_RIGHT:
2403 GoNextCell();
2404 break;
2406 case nsTblChgWidthHeightType::WH_CELL_TOP:
2407 case nsTblChgWidthHeightType::WH_ROW_TOP:
2408 lcl_GoTableRow( this, true );
2409 break;
2411 case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
2412 case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
2413 lcl_GoTableRow( this, false );
2414 break;
2418 return bRet;
2421 BOOL lcl_IsFormulaSelBoxes( const SwTable& rTbl, const SwTblBoxFormula& rFml,
2422 SwCellFrms& rCells )
2424 SwTblBoxFormula aTmp( rFml );
2425 SwSelBoxes aBoxes;
2426 for( USHORT nSelBoxes = aTmp.GetBoxesOfFormula( rTbl,aBoxes ); nSelBoxes; )
2428 SwTableBox* pBox = aBoxes[ --nSelBoxes ];
2429 USHORT i;
2430 for( i = 0; i < rCells.Count(); ++i )
2431 if( rCells[ i ]->GetTabBox() == pBox )
2432 break; // gefunden
2434 if( i == rCells.Count() )
2435 return FALSE;
2438 return TRUE;
2441 // erfrage die Formel fuer die Autosumme
2442 BOOL SwFEShell::GetAutoSum( String& rFml ) const
2444 SwFrm *pFrm = GetCurrFrm();
2445 SwTabFrm *pTab = pFrm ? pFrm->ImplFindTabFrm() : 0;
2446 if( !pTab )
2447 return FALSE;
2449 rFml = String::CreateFromAscii( sCalc_Sum );
2451 SwCellFrms aCells;
2452 if( ::GetAutoSumSel( *this, aCells ))
2454 USHORT nW = 0, nInsPos = 0;
2455 for( USHORT n = aCells.Count(); n; )
2457 SwCellFrm* pCFrm = aCells[ --n ];
2458 USHORT nBoxW = pCFrm->GetTabBox()->IsFormulaOrValueBox();
2459 if( !nBoxW )
2460 break;
2462 if( !nW )
2464 if( USHRT_MAX == nBoxW )
2465 continue; // leere am Anfang ueberspringen
2467 rFml += '(';
2468 nInsPos = rFml.Len();
2470 // Formeln nur wenn diese Boxen enthalten
2471 if( RES_BOXATR_FORMULA == nBoxW &&
2472 !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2473 GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells))
2475 nW = RES_BOXATR_VALUE;
2476 // alle vorhierigen Leere wieder mit aufnehmen !
2477 for( USHORT i = aCells.Count(); n+1 < i; )
2479 String sTmp( String::CreateFromAscii(
2480 RTL_CONSTASCII_STRINGPARAM( "|<" )) );
2481 sTmp += aCells[ --i ]->GetTabBox()->GetName();
2482 sTmp += '>';
2483 rFml.Insert( sTmp, nInsPos );
2486 else
2487 nW = nBoxW;
2489 else if( RES_BOXATR_VALUE == nW )
2491 // values werden gesucht, Value/Formel/Text gefunden -> aufn.
2492 if( RES_BOXATR_FORMULA == nBoxW &&
2493 ::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2494 GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
2495 break;
2496 else if( USHRT_MAX != nBoxW )
2497 rFml.Insert( cListDelim, nInsPos );
2498 else
2499 break;
2501 else if( RES_BOXATR_FORMULA == nW )
2503 // bei Formeln nur weiter suchen, wenn die akt. Formel auf
2504 // alle Boxen verweist, die sich in der Selektion befinden
2505 if( RES_BOXATR_FORMULA == nBoxW )
2507 if( !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2508 GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
2510 // dann noch mal von vorne und nur die Values!
2512 nW = RES_BOXATR_VALUE;
2513 rFml.Erase( nInsPos );
2514 // alle vorhierigen Leere wieder mit aufnehmen !
2515 for( USHORT i = aCells.Count(); n+1 < i; )
2517 String sTmp( String::CreateFromAscii(
2518 RTL_CONSTASCII_STRINGPARAM( "|<" )) );
2519 sTmp += aCells[ --i ]->GetTabBox()->GetName();
2520 sTmp += '>';
2521 rFml.Insert( sTmp, nInsPos );
2524 else
2525 rFml.Insert( cListDelim, nInsPos );
2527 else if( USHRT_MAX == nBoxW )
2528 break;
2529 else
2530 continue; // diese Boxen ignorieren
2532 else
2533 // alles andere beendet die Schleife
2534 // evt. Texte noch zu lassen??
2535 break;
2537 String sTmp( '<' );
2538 sTmp += pCFrm->GetTabBox()->GetName();
2539 sTmp += '>';
2540 rFml.Insert( sTmp, nInsPos );
2542 if( nW )
2544 rFml += ')';
2547 // TabellenSelektion erzeugen??
2548 SwTblBoxFormula aTmp( rFml );
2549 SwSelBoxes aBoxes;
2550 for( USHORT nSelBoxes = aTmp.GetBoxesOfFormula( rTbl,aBoxes );
2551 nSelBoxes; )
2558 return TRUE;
2560 /* -----------------------------22.08.2002 12:50------------------------------
2562 ---------------------------------------------------------------------------*/
2563 BOOL SwFEShell::IsTableRightToLeft() const
2565 SwFrm *pFrm = GetCurrFrm();
2566 if( !pFrm || !pFrm->IsInTab() )
2567 return FALSE;
2569 return pFrm->ImplFindTabFrm()->IsRightToLeft();
2572 /* -----------------------------22.08.2002 12:50------------------------------
2574 ---------------------------------------------------------------------------*/
2575 BOOL SwFEShell::IsMouseTableRightToLeft(const Point &rPt) const
2577 SwFrm *pFrm = (SwFrm *)GetBox( rPt );
2578 const SwTabFrm* pTabFrm = pFrm ? pFrm->ImplFindTabFrm() : 0;
2579 ASSERT( pTabFrm, "Table not found" );
2580 return pTabFrm ? pTabFrm->IsRightToLeft() : FALSE;
2583 /* -----------------------------11.02.2004 12:50------------------------------
2585 ---------------------------------------------------------------------------*/
2586 BOOL SwFEShell::IsTableVertical() const
2588 SwFrm *pFrm = GetCurrFrm();
2589 if( !pFrm || !pFrm->IsInTab() )
2590 return FALSE;
2592 return pFrm->ImplFindTabFrm()->IsVertical();