1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <hintids.hxx>
23 #include <vcl/errinf.hxx>
24 #include <basegfx/vector/b2dvector.hxx>
25 #include <editeng/protitem.hxx>
26 #include <editeng/brushitem.hxx>
27 #include <editeng/frmdiritem.hxx>
28 #include <svtools/ruler.hxx>
30 #include <fmtfsize.hxx>
31 #include <fmtornt.hxx>
35 #include <IDocumentState.hxx>
36 #include <IDocumentLayoutAccess.hxx>
39 #include <notxtfrm.hxx>
40 #include <rootfrm.hxx>
41 #include <pagefrm.hxx>
44 #include <cellfrm.hxx>
46 #include <swtable.hxx>
47 #include <swddetbl.hxx>
50 #include <dialoghelp.hxx>
52 #include <tblafmt.hxx>
53 #include <cellatr.hxx>
59 #include <frmtool.hxx>
60 #include <fmtrowsplt.hxx>
62 #include <sortedobjs.hxx>
64 using namespace ::com::sun::star
;
66 // also see swtable.cxx
69 static bool IsSame( tools::Long nA
, tools::Long nB
) { return std::abs(nA
-nB
) <= COLFUZZY
; }
75 const std::unique_ptr
<SwWait
> m_pWait
;
76 // this seems really fishy: do some locking, if an arbitrary number of lines is exceeded
77 static const size_t our_kLineLimit
= 20;
78 static bool ShouldWait(size_t nCnt
, SwFrame
*pFrame
, size_t nCnt2
)
79 { return our_kLineLimit
< nCnt
|| our_kLineLimit
< nCnt2
|| (pFrame
&& our_kLineLimit
< pFrame
->ImplFindTabFrame()->GetTable()->GetTabLines().size()); }
81 TableWait(size_t nCnt
, SwFrame
*pFrame
, SwDocShell
&rDocShell
, size_t nCnt2
= 0)
82 : m_pWait( ShouldWait(nCnt
, pFrame
, nCnt2
) ? std::make_unique
<SwWait
>( rDocShell
, true ) : nullptr )
88 void SwFEShell::ParkCursorInTab()
90 SwCursor
* pSwCursor
= GetSwCursor();
92 OSL_ENSURE(pSwCursor
, "no SwCursor");
94 SwPosition aStartPos
= *pSwCursor
->GetPoint(), aEndPos
= aStartPos
;
96 /* Search least and greatest position in current cursor ring.
98 for(SwPaM
& rTmpCursor
: pSwCursor
->GetRingContainer())
100 SwCursor
* pTmpCursor
= static_cast<SwCursor
*>(&rTmpCursor
);
101 const SwPosition
* pPt
= pTmpCursor
->GetPoint(),
102 * pMk
= pTmpCursor
->GetMark();
104 if (*pPt
< aStartPos
)
110 if (*pMk
< aStartPos
)
120 /* @@@ semantic: SwCursor::operator=() is not implemented @@@ */
122 /* Set cursor to end of selection to ensure IsLastCellInRow works
125 SwCursor
aTmpCursor( aEndPos
, nullptr );
126 *pSwCursor
= aTmpCursor
;
129 /* Move the cursor out of the columns to delete and stay in the
130 same row. If the table has only one column the cursor will
131 stay in the row and the shell will take care of it. */
132 if (IsLastCellInRow())
134 /* If the cursor is in the last row of the table, first
135 try to move it to the previous cell. If that fails move
136 it to the next cell. */
139 SwCursor
aTmpCursor( aStartPos
, nullptr );
140 *pSwCursor
= aTmpCursor
;
143 if (! pSwCursor
->GoPrevCell())
145 SwCursor
aTmpCursor( aEndPos
, nullptr );
146 *pSwCursor
= aTmpCursor
;
147 pSwCursor
->GoNextCell();
152 /* If the cursor is not in the last row of the table, first
153 try to move it to the next cell. If that fails move it
154 to the previous cell. */
157 SwCursor
aTmpCursor( aEndPos
, nullptr );
158 *pSwCursor
= aTmpCursor
;
161 if (! pSwCursor
->GoNextCell())
163 SwCursor
aTmpCursor( aStartPos
, nullptr );
164 *pSwCursor
= aTmpCursor
;
165 pSwCursor
->GoPrevCell();
170 void SwFEShell::InsertRow( sal_uInt16 nCnt
, bool bBehind
)
172 // check if Point/Mark of current cursor are in a table
173 SwFrame
*pFrame
= GetCurrFrame();
174 if( !pFrame
|| !pFrame
->IsInTab() )
177 if( dynamic_cast< const SwDDETable
* >(pFrame
->ImplFindTabFrame()->GetTable()) != nullptr )
179 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
180 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
184 CurrShell
aCurr( this );
187 // search boxes via the layout
189 bool bSelectAll
= StartsWithTable() && ExtendedSelectedAll();
192 // Set the end of the selection to the last paragraph of the last cell of the table.
193 SwPaM
* pPaM
= getShellCursor(false);
194 SwNode
* pNode
= pPaM
->Start()->nNode
.GetNode().FindTableNode()->EndOfSectionNode();
195 // pNode is the end node of the table, we want the last node before the end node of the last cell.
196 pPaM
->End()->nNode
= pNode
->GetIndex() - 2;
197 pPaM
->End()->nContent
.Assign(pPaM
->End()->nNode
.GetNode().GetContentNode(), 0);
199 GetTableSel( *this, aBoxes
, SwTableSearchType::Row
);
201 TableWait
aWait( nCnt
, pFrame
, *GetDoc()->GetDocShell(), aBoxes
.size() );
203 if ( !aBoxes
.empty() )
204 GetDoc()->InsertRow( aBoxes
, nCnt
, bBehind
);
206 EndAllActionAndCall();
209 void SwFEShell::InsertCol( sal_uInt16 nCnt
, bool bBehind
)
211 // check if Point/Mark of current cursor are in a table
212 SwFrame
*pFrame
= GetCurrFrame();
213 if( !pFrame
|| !pFrame
->IsInTab() )
216 if( dynamic_cast< const SwDDETable
* >(pFrame
->ImplFindTabFrame()->GetTable()) != nullptr )
218 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
219 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
223 CurrShell
aCurr( this );
225 if( !CheckSplitCells( *this, nCnt
+ 1, SwTableSearchType::Col
) )
227 ErrorHandler::HandleError( ERR_TBLINSCOL_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
228 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
233 // search boxes via the layout
235 GetTableSel( *this, aBoxes
, SwTableSearchType::Col
);
237 TableWait
aWait( nCnt
, pFrame
, *GetDoc()->GetDocShell(), aBoxes
.size() );
239 if( !aBoxes
.empty() )
240 GetDoc()->InsertCol( aBoxes
, nCnt
, bBehind
);
242 EndAllActionAndCall();
245 // Determines if the current cursor is in the last row of the table.
246 bool SwFEShell::IsLastCellInRow() const
249 GetTabCols( aTabCols
);
250 bool bResult
= false;
252 if (IsTableRightToLeft())
253 /* If the table is right-to-left the last row is the most left one. */
254 bResult
= 0 == GetCurTabColNum();
256 /* If the table is left-to-right the last row is the most right one. */
257 bResult
= aTabCols
.Count() == GetCurTabColNum();
262 bool SwFEShell::DeleteCol()
264 // check if Point/Mark of current cursor are in a table
265 SwFrame
*pFrame
= GetCurrFrame();
266 if( !pFrame
|| !pFrame
->IsInTab() )
269 if( dynamic_cast< const SwDDETable
* >(pFrame
->ImplFindTabFrame()->GetTable()) != nullptr )
271 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
272 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
276 CurrShell
aCurr( this );
279 // search boxes via the layout
282 GetTableSel( *this, aBoxes
, SwTableSearchType::Col
);
283 if ( !aBoxes
.empty() )
285 TableWait
aWait( aBoxes
.size(), pFrame
, *GetDoc()->GetDocShell() );
287 // remove crsr from the deletion area.
288 // Put them behind/on the table; via the
289 // document position they will be put to the old position
290 while( !pFrame
->IsCellFrame() )
291 pFrame
= pFrame
->GetUpper();
295 // then delete the column
296 StartUndo(SwUndoId::COL_DELETE
);
297 bRet
= GetDoc()->DeleteRowCol( aBoxes
, true );
298 EndUndo(SwUndoId::COL_DELETE
);
304 EndAllActionAndCall();
308 void SwFEShell::DeleteTable()
313 bool SwFEShell::DeleteRow(bool bCompleteTable
)
315 // check if Point/Mark of current cursor are in a table
316 SwFrame
*pFrame
= GetCurrFrame();
317 if( !pFrame
|| !pFrame
->IsInTab() )
320 if( dynamic_cast< const SwDDETable
* >(pFrame
->ImplFindTabFrame()->GetTable()) != nullptr )
322 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
323 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
327 CurrShell
aCurr( this );
330 // search for boxes via the layout
333 GetTableSel( *this, aBoxes
, SwTableSearchType::Row
);
335 if( !aBoxes
.empty() )
337 TableWait
aWait( aBoxes
.size(), pFrame
, *GetDoc()->GetDocShell() );
339 // Delete cursors from the deletion area.
340 // Then the cursor is:
341 // 1. the following row, if there is another row after this
342 // 2. the preceding row, if there is another row before this
343 // 3. otherwise below the table
345 SwTableNode
* pTableNd
= pFrame
->IsTextFrame()
346 ? static_cast<SwTextFrame
*>(pFrame
)->GetTextNodeFirst()->FindTableNode()
347 : static_cast<SwNoTextFrame
*>(pFrame
)->GetNode()->FindTableNode();
349 // search all boxes / lines
350 FndBox_
aFndBox( nullptr, nullptr );
352 FndPara
aPara( aBoxes
, &aFndBox
);
353 ForEach_FndLineCopyCol( pTableNd
->GetTable().GetTabLines(), &aPara
);
356 if( aFndBox
.GetLines().empty() )
358 EndAllActionAndCall();
364 FndBox_
* pFndBox
= &aFndBox
;
365 while( 1 == pFndBox
->GetLines().size() &&
366 1 == pFndBox
->GetLines().front()->GetBoxes().size())
368 FndBox_
*const pTmp
= pFndBox
->GetLines().front()->GetBoxes()[0].get();
369 if( pTmp
->GetBox()->GetSttNd() )
370 break; // otherwise too far
374 SwTableLine
* pDelLine
= pFndBox
->GetLines().back()->GetLine();
375 SwTableBox
* pDelBox
= pDelLine
->GetTabBoxes().back();
376 while( !pDelBox
->GetSttNd() )
378 SwTableLine
* pLn
= pDelBox
->GetTabLines().back();
379 pDelBox
= pLn
->GetTabBoxes().back();
381 SwTableBox
* pNextBox
= pDelLine
->FindNextBox( pTableNd
->GetTable(),
384 pNextBox
->GetFrameFormat()->GetProtect().IsContentProtected() )
385 pNextBox
= pNextBox
->FindNextBox( pTableNd
->GetTable(), pNextBox
);
387 if( !pNextBox
) // no next? then the previous
389 pDelLine
= pFndBox
->GetLines().front()->GetLine();
390 pDelBox
= pDelLine
->GetTabBoxes()[ 0 ];
391 while( !pDelBox
->GetSttNd() )
392 pDelBox
= pDelBox
->GetTabLines()[0]->GetTabBoxes()[0];
393 pNextBox
= pDelLine
->FindPreviousBox( pTableNd
->GetTable(),
396 pNextBox
->GetFrameFormat()->GetProtect().IsContentProtected() )
397 pNextBox
= pNextBox
->FindPreviousBox( pTableNd
->GetTable(), pNextBox
);
401 if( pNextBox
) // put cursor here
402 nIdx
= pNextBox
->GetSttIdx() + 1;
403 else // otherwise below the table
404 nIdx
= pTableNd
->EndOfSectionIndex() + 1;
406 SwNodeIndex
aIdx( GetDoc()->GetNodes(), nIdx
);
407 SwContentNode
* pCNd
= aIdx
.GetNode().GetContentNode();
409 pCNd
= GetDoc()->GetNodes().GoNext( &aIdx
);
413 SwPaM
* pPam
= GetCursor();
414 pPam
->GetPoint()->nNode
= aIdx
;
415 pPam
->GetPoint()->nContent
.Assign( pCNd
, 0 );
416 pPam
->SetMark(); // both want something
421 // now delete the lines
422 StartUndo(bCompleteTable
? SwUndoId::UI_TABLE_DELETE
: SwUndoId::ROW_DELETE
);
423 bRet
= GetDoc()->DeleteRowCol( aBoxes
);
424 EndUndo(bCompleteTable
? SwUndoId::UI_TABLE_DELETE
: SwUndoId::ROW_DELETE
);
429 EndAllActionAndCall();
433 TableMergeErr
SwFEShell::MergeTab()
435 // check if Point/Mark of current cursor are in a table
436 TableMergeErr nRet
= TableMergeErr::NoSelection
;
439 SwShellTableCursor
* pTableCursor
= GetTableCursor();
440 const SwTableNode
* pTableNd
= pTableCursor
->GetNode().FindTableNode();
441 if( dynamic_cast< const SwDDETable
* >(&pTableNd
->GetTable()) != nullptr )
443 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
444 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
448 CurrShell
aCurr( this );
451 TableWait
aWait(pTableCursor
->GetSelectedBoxesCount(), nullptr,
452 *GetDoc()->GetDocShell(),
453 pTableNd
->GetTable().GetTabLines().size() );
455 nRet
= GetDoc()->MergeTable( *pTableCursor
);
459 EndAllActionAndCall();
465 void SwFEShell::SplitTab( bool bVert
, sal_uInt16 nCnt
, bool bSameHeight
)
467 // check if Point/Mark of current cursor are in a table
468 SwFrame
*pFrame
= GetCurrFrame();
469 if( !pFrame
|| !pFrame
->IsInTab() )
472 if( dynamic_cast< const SwDDETable
* >(pFrame
->ImplFindTabFrame()->GetTable()) != nullptr )
474 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
475 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
479 CurrShell
aCurr( this );
481 if( bVert
&& !CheckSplitCells( *this, nCnt
+ 1, SwTableSearchType::NONE
) )
483 ErrorHandler::HandleError( ERR_TBLSPLIT_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
484 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
488 // search boxes via the layout
490 GetTableSel( *this, aBoxes
);
491 if( !aBoxes
.empty() )
493 TableWait
aWait( nCnt
, pFrame
, *GetDoc()->GetDocShell(), aBoxes
.size() );
495 // now delete the columns
496 GetDoc()->SplitTable( aBoxes
, bVert
, nCnt
, bSameHeight
);
498 ClearFEShellTabCols(*GetDoc(), nullptr);
500 EndAllActionAndCall();
503 void SwFEShell::GetTabCols_(SwTabCols
&rToFill
, const SwFrame
*pBox
) const
505 const SwTabFrame
*pTab
= pBox
->FindTabFrame();
509 if (m_pColumnCache
->pLastTable
== pTab
->GetTable())
512 SwRectFnSet
aRectFnSet(pTab
);
514 const SwPageFrame
* pPage
= pTab
->FindPageFrame();
515 const sal_uLong nLeftMin
= aRectFnSet
.GetLeft(pTab
->getFrameArea()) -
516 aRectFnSet
.GetLeft(pPage
->getFrameArea());
517 const sal_uLong nRightMax
= aRectFnSet
.GetRight(pTab
->getFrameArea()) -
518 aRectFnSet
.GetLeft(pPage
->getFrameArea());
520 if (m_pColumnCache
->pLastTabFrame
!= pTab
)
522 // if TabFrame was changed, we only shift a little bit
523 // as the width is the same
524 SwRectFnSet
fnRectX(m_pColumnCache
->pLastTabFrame
);
525 if (fnRectX
.GetWidth(m_pColumnCache
->pLastTabFrame
->getFrameArea()) ==
526 aRectFnSet
.GetWidth(pTab
->getFrameArea()) )
528 m_pColumnCache
->pLastCols
->SetLeftMin( nLeftMin
);
530 m_pColumnCache
->pLastTabFrame
= pTab
;
537 m_pColumnCache
->pLastCols
->GetLeftMin () == static_cast<sal_uInt16
>(nLeftMin
) &&
538 m_pColumnCache
->pLastCols
->GetLeft () == static_cast<sal_uInt16
>(aRectFnSet
.GetLeft(pTab
->getFramePrintArea())) &&
539 m_pColumnCache
->pLastCols
->GetRight () == static_cast<sal_uInt16
>(aRectFnSet
.GetRight(pTab
->getFramePrintArea()))&&
540 m_pColumnCache
->pLastCols
->GetRightMax() == static_cast<sal_uInt16
>(nRightMax
) - m_pColumnCache
->pLastCols
->GetLeftMin() )
542 if (m_pColumnCache
->pLastCellFrame
!= pBox
)
544 pTab
->GetTable()->GetTabCols( *m_pColumnCache
->pLastCols
,
545 static_cast<const SwCellFrame
*>(pBox
)->GetTabBox(), true);
546 m_pColumnCache
->pLastCellFrame
= pBox
;
548 rToFill
= *m_pColumnCache
->pLastCols
;
554 m_pColumnCache
.reset();
558 SwDoc::GetTabCols( rToFill
, static_cast<const SwCellFrame
*>(pBox
) );
560 m_pColumnCache
.reset(new SwColCache
);
561 m_pColumnCache
->pLastCols
.reset(new SwTabCols(rToFill
));
562 m_pColumnCache
->pLastTable
= pTab
->GetTable();
563 m_pColumnCache
->pLastTabFrame
= pTab
;
564 m_pColumnCache
->pLastCellFrame
= pBox
;
568 void SwFEShell::GetTabRows_(SwTabCols
&rToFill
, const SwFrame
*pBox
) const
570 const SwTabFrame
*pTab
= pBox
->FindTabFrame();
574 if (m_pRowCache
->pLastTable
== pTab
->GetTable())
577 SwRectFnSet
aRectFnSet(pTab
);
578 const SwPageFrame
* pPage
= pTab
->FindPageFrame();
579 const tools::Long nLeftMin
= ( aRectFnSet
.IsVert() ?
580 pTab
->GetPrtLeft() - pPage
->getFrameArea().Left() :
581 pTab
->GetPrtTop() - pPage
->getFrameArea().Top() );
582 const tools::Long nLeft
= aRectFnSet
.IsVert() ? LONG_MAX
: 0;
583 const tools::Long nRight
= aRectFnSet
.GetHeight(pTab
->getFramePrintArea());
584 const tools::Long nRightMax
= aRectFnSet
.IsVert() ? nRight
: LONG_MAX
;
586 if (m_pRowCache
->pLastTabFrame
!= pTab
|| m_pRowCache
->pLastCellFrame
!= pBox
)
590 m_pRowCache
->pLastCols
->GetLeftMin () == nLeftMin
&&
591 m_pRowCache
->pLastCols
->GetLeft () == nLeft
&&
592 m_pRowCache
->pLastCols
->GetRight () == nRight
&&
593 m_pRowCache
->pLastCols
->GetRightMax() == nRightMax
)
595 rToFill
= *m_pRowCache
->pLastCols
;
605 SwDoc::GetTabRows( rToFill
, static_cast<const SwCellFrame
*>(pBox
) );
607 m_pRowCache
.reset(new SwColCache
);
608 m_pRowCache
->pLastCols
.reset(new SwTabCols(rToFill
));
609 m_pRowCache
->pLastTable
= pTab
->GetTable();
610 m_pRowCache
->pLastTabFrame
= pTab
;
611 m_pRowCache
->pLastCellFrame
= pBox
;
615 void SwFEShell::SetTabCols( const SwTabCols
&rNew
, bool bCurRowOnly
)
617 SwFrame
*pBox
= GetCurrFrame();
618 if( !pBox
|| !pBox
->IsInTab() )
621 CurrShell
aCurr( this );
626 pBox
= pBox
->GetUpper();
627 } while (pBox
&& !pBox
->IsCellFrame());
629 GetDoc()->SetTabCols( rNew
, bCurRowOnly
, static_cast<SwCellFrame
*>(pBox
) );
630 EndAllActionAndCall();
633 void SwFEShell::GetTabCols( SwTabCols
&rToFill
) const
635 const SwFrame
*pFrame
= GetCurrFrame();
636 if( !pFrame
|| !pFrame
->IsInTab() )
640 pFrame
= pFrame
->GetUpper();
642 while (pFrame
&& !pFrame
->IsCellFrame());
647 GetTabCols_( rToFill
, pFrame
);
650 void SwFEShell::GetTabRows( SwTabCols
&rToFill
) const
652 const SwFrame
*pFrame
= GetCurrFrame();
653 if( !pFrame
|| !pFrame
->IsInTab() )
657 pFrame
= pFrame
->GetUpper();
658 } while (pFrame
&& !pFrame
->IsCellFrame());
663 GetTabRows_( rToFill
, pFrame
);
666 void SwFEShell::SetTabRows( const SwTabCols
&rNew
, bool bCurColOnly
)
668 SwFrame
*pBox
= GetCurrFrame();
669 if( !pBox
|| !pBox
->IsInTab() )
672 CurrShell
aCurr( this );
677 pBox
= pBox
->GetUpper();
678 } while (pBox
&& !pBox
->IsCellFrame());
680 GetDoc()->SetTabRows( rNew
, bCurColOnly
, static_cast<SwCellFrame
*>(pBox
) );
681 EndAllActionAndCall();
684 void SwFEShell::GetMouseTabRows( SwTabCols
&rToFill
, const Point
&rPt
) const
686 const SwFrame
*pBox
= GetBox( rPt
);
688 GetTabRows_( rToFill
, pBox
);
691 void SwFEShell::SetMouseTabRows( const SwTabCols
&rNew
, bool bCurColOnly
, const Point
&rPt
)
693 const SwFrame
*pBox
= GetBox( rPt
);
696 CurrShell
aCurr( this );
698 GetDoc()->SetTabRows( rNew
, bCurColOnly
, static_cast<const SwCellFrame
*>(pBox
) );
699 EndAllActionAndCall();
703 void SwFEShell::SetRowSplit( const SwFormatRowSplit
& rNew
)
705 CurrShell
aCurr( this );
707 GetDoc()->SetRowSplit( *getShellCursor( false ), rNew
);
708 EndAllActionAndCall();
711 std::unique_ptr
<SwFormatRowSplit
> SwFEShell::GetRowSplit() const
713 return SwDoc::GetRowSplit( *getShellCursor( false ) );
716 void SwFEShell::SetRowHeight( const SwFormatFrameSize
&rNew
)
718 CurrShell
aCurr( this );
720 GetDoc()->SetRowHeight( *getShellCursor( false ), rNew
);
721 EndAllActionAndCall();
724 std::unique_ptr
<SwFormatFrameSize
> SwFEShell::GetRowHeight() const
726 return SwDoc::GetRowHeight( *getShellCursor( false ) );
729 bool SwFEShell::BalanceRowHeight( bool bTstOnly
, const bool bOptimize
)
731 CurrShell
aCurr( this );
734 bool bRet
= GetDoc()->BalanceRowHeight( *getShellCursor( false ), bTstOnly
, bOptimize
);
736 EndAllActionAndCall();
740 void SwFEShell::SetRowBackground( const SvxBrushItem
&rNew
)
742 CurrShell
aCurr( this );
744 GetDoc()->SetRowBackground( *getShellCursor( false ), rNew
);
745 EndAllActionAndCall();
748 bool SwFEShell::GetRowBackground( std::unique_ptr
<SvxBrushItem
>& rToFill
) const
750 return SwDoc::GetRowBackground( *getShellCursor( false ), rToFill
);
753 void SwFEShell::SetTabBorders( const SfxItemSet
& rSet
)
755 CurrShell
aCurr( this );
757 GetDoc()->SetTabBorders( *getShellCursor( false ), rSet
);
758 EndAllActionAndCall();
761 void SwFEShell::SetTabLineStyle( const Color
* pColor
, bool bSetLine
,
762 const editeng::SvxBorderLine
* pBorderLine
)
764 CurrShell
aCurr( this );
766 GetDoc()->SetTabLineStyle( *getShellCursor( false ),
767 pColor
, bSetLine
, pBorderLine
);
768 EndAllActionAndCall();
771 void SwFEShell::GetTabBorders( SfxItemSet
& rSet
) const
773 SwDoc::GetTabBorders( *getShellCursor( false ), rSet
);
776 void SwFEShell::SetBoxBackground( const SvxBrushItem
&rNew
)
778 CurrShell
aCurr( this );
780 GetDoc()->SetBoxAttr( *getShellCursor( false ), rNew
);
781 EndAllActionAndCall();
784 bool SwFEShell::GetBoxBackground( std::unique_ptr
<SvxBrushItem
>& rToFill
) const
786 std::unique_ptr
<SfxPoolItem
> aTemp
= std::move(rToFill
);
787 bool bRetval(SwDoc::GetBoxAttr(*getShellCursor( false ), aTemp
));
788 rToFill
.reset(static_cast<SvxBrushItem
*>(aTemp
.release()));
792 void SwFEShell::SetBoxDirection( const SvxFrameDirectionItem
& rNew
)
794 CurrShell
aCurr( this );
796 GetDoc()->SetBoxAttr( *getShellCursor( false ), rNew
);
797 EndAllActionAndCall();
800 bool SwFEShell::GetBoxDirection( std::unique_ptr
<SvxFrameDirectionItem
>& rToFill
) const
802 std::unique_ptr
<SfxPoolItem
> aTemp
= std::move(rToFill
);
803 bool bRetval(SwDoc::GetBoxAttr(*getShellCursor( false ), aTemp
));
804 rToFill
.reset(static_cast<SvxFrameDirectionItem
*>(aTemp
.release()));
808 void SwFEShell::SetBoxAlign( sal_uInt16 nAlign
)
810 CurrShell
aCurr( this );
812 GetDoc()->SetBoxAlign( *getShellCursor( false ), nAlign
);
813 EndAllActionAndCall();
816 sal_uInt16
SwFEShell::GetBoxAlign() const
818 return SwDoc::GetBoxAlign( *getShellCursor( false ) );
821 void SwFEShell::SetTabBackground( const SvxBrushItem
&rNew
)
823 SwFrame
*pFrame
= GetCurrFrame();
824 if( !pFrame
|| !pFrame
->IsInTab() )
827 CurrShell
aCurr( this );
829 GetDoc()->SetAttr( rNew
, *pFrame
->ImplFindTabFrame()->GetFormat() );
830 EndAllAction(); // no call, nothing changes!
831 GetDoc()->getIDocumentState().SetModified();
834 void SwFEShell::GetTabBackground( std::unique_ptr
<SvxBrushItem
>& rToFill
) const
836 SwFrame
*pFrame
= GetCurrFrame();
837 if( pFrame
&& pFrame
->IsInTab() )
838 rToFill
= pFrame
->ImplFindTabFrame()->GetFormat()->makeBackgroundBrushItem();
841 bool SwFEShell::HasWholeTabSelection() const
843 // whole table selected?
847 ::GetTableSelCrs( *this, aBoxes
);
848 if( !aBoxes
.empty() )
850 const SwTableNode
*pTableNd
= IsCursorInTable();
852 aBoxes
[0]->GetSttIdx() - 1 == pTableNd
->EndOfSectionNode()->StartOfSectionIndex() &&
853 aBoxes
.back()->GetSttNd()->EndOfSectionIndex() + 1 == pTableNd
->EndOfSectionIndex();
859 bool SwFEShell::HasBoxSelection() const
861 if(!IsCursorInTable())
863 // whole table selected?
866 SwPaM
* pPam
= GetCursor();
867 // empty boxes are also selected as the absence of selection
869 if( pPam
->GetPoint() == pPam
->End())
875 if( pPam
->GetPoint()->nNode
.GetIndex() -1 ==
876 ( pNd
= &pPam
->GetNode())->StartOfSectionIndex() &&
877 !pPam
->GetPoint()->nContent
.GetIndex() &&
878 pPam
->GetMark()->nNode
.GetIndex() + 1 ==
879 pNd
->EndOfSectionIndex())
881 SwNodeIndex
aIdx( *pNd
->EndOfSectionNode(), -1 );
882 SwContentNode
* pCNd
= aIdx
.GetNode().GetContentNode();
885 pCNd
= SwNodes::GoPrevious( &aIdx
);
886 OSL_ENSURE( pCNd
, "no ContentNode in box ??" );
888 if( pPam
->GetMark()->nContent
== pCNd
->Len() )
900 void SwFEShell::ProtectCells()
902 SvxProtectItem
aProt( RES_PROTECT
);
903 aProt
.SetContentProtect( true );
905 CurrShell
aCurr( this );
908 GetDoc()->SetBoxAttr( *getShellCursor( false ), aProt
);
910 if( !IsCursorReadonly() )
916 EndAllActionAndCall();
919 // cancel table selection
920 void SwFEShell::UnProtectCells()
922 CurrShell
aCurr( this );
927 ::GetTableSelCrs( *this, aBoxes
);
930 SwFrame
*pFrame
= GetCurrFrame();
932 pFrame
= pFrame
->GetUpper();
933 } while ( pFrame
&& !pFrame
->IsCellFrame() );
936 SwTableBox
*pBox
= const_cast<SwTableBox
*>(static_cast<SwCellFrame
*>(pFrame
)->GetTabBox());
937 aBoxes
.insert( pBox
);
941 if( !aBoxes
.empty() )
942 GetDoc()->UnProtectCells( aBoxes
);
944 EndAllActionAndCall();
947 void SwFEShell::UnProtectTables()
949 CurrShell
aCurr( this );
951 GetDoc()->UnProtectTables( *GetCursor() );
952 EndAllActionAndCall();
955 bool SwFEShell::HasTableAnyProtection( const OUString
* pTableName
,
956 bool* pFullTableProtection
)
958 return GetDoc()->HasTableAnyProtection( GetCursor()->GetPoint(), pTableName
,
959 pFullTableProtection
);
962 bool SwFEShell::CanUnProtectCells() const
964 bool bUnProtectAvailable
= false;
965 const SwTableNode
*pTableNd
= IsCursorInTable();
966 if( pTableNd
&& !pTableNd
->IsProtect() )
970 ::GetTableSelCrs( *this, aBoxes
);
973 SwFrame
*pFrame
= GetCurrFrame();
975 pFrame
= pFrame
->GetUpper();
976 } while ( pFrame
&& !pFrame
->IsCellFrame() );
979 SwTableBox
*pBox
= const_cast<SwTableBox
*>(static_cast<SwCellFrame
*>(pFrame
)->GetTabBox());
980 aBoxes
.insert( pBox
);
983 if( !aBoxes
.empty() )
984 bUnProtectAvailable
= ::HasProtectedCells( aBoxes
);
986 return bUnProtectAvailable
;
989 sal_uInt16
SwFEShell::GetRowsToRepeat() const
991 const SwFrame
*pFrame
= GetCurrFrame();
992 const SwTabFrame
*pTab
= pFrame
? pFrame
->FindTabFrame() : nullptr;
994 return pTab
->GetTable()->GetRowsToRepeat();
998 void SwFEShell::SetRowsToRepeat( sal_uInt16 nSet
)
1000 SwFrame
*pFrame
= GetCurrFrame();
1001 SwTabFrame
*pTab
= pFrame
? pFrame
->FindTabFrame() : nullptr;
1002 if( pTab
&& pTab
->GetTable()->GetRowsToRepeat() != nSet
)
1004 SwWait
aWait( *GetDoc()->GetDocShell(), true );
1005 CurrShell
aCurr( this );
1007 GetDoc()->SetRowsToRepeat( *pTab
->GetTable(), nSet
);
1008 EndAllActionAndCall();
1012 // returns the number of rows consecutively selected from top
1013 static sal_uInt16
lcl_GetRowNumber( const SwPosition
& rPos
)
1016 const SwContentNode
*pNd
;
1017 const SwContentFrame
*pFrame
;
1019 std::pair
<Point
, bool> const tmp(aTmpPt
, false);
1020 pNd
= rPos
.nNode
.GetNode().GetContentNode();
1021 if( nullptr != pNd
)
1022 pFrame
= pNd
->getLayoutFrame(pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), &rPos
, &tmp
);
1026 const SwFrame
* pRow
= (pFrame
&& pFrame
->IsInTab()) ? pFrame
->GetUpper() : nullptr;
1028 while (pRow
&& (!pRow
->GetUpper() || !pRow
->GetUpper()->IsTabFrame()))
1029 pRow
= pRow
->GetUpper();
1034 const SwTabFrame
* pTabFrame
= static_cast<const SwTabFrame
*>(pRow
->GetUpper());
1035 const SwTableLine
* pTabLine
= static_cast<const SwRowFrame
*>(pRow
)->GetTabLine();
1036 sal_uInt16 nRet
= USHRT_MAX
;
1038 while ( sal::static_int_cast
<SwTableLines::size_type
>(nI
) < pTabFrame
->GetTable()->GetTabLines().size() )
1040 if ( pTabFrame
->GetTable()->GetTabLines()[ nI
] == pTabLine
)
1051 sal_uInt16
SwFEShell::GetRowSelectionFromTop() const
1053 sal_uInt16 nRet
= 0;
1054 const SwPaM
* pPaM
= IsTableMode() ? GetTableCursor() : GetCursor_();
1055 const sal_uInt16 nPtLine
= lcl_GetRowNumber( *pPaM
->GetPoint() );
1057 if ( !IsTableMode() )
1059 nRet
= 0 == nPtLine
? 1 : 0;
1063 const sal_uInt16 nMkLine
= lcl_GetRowNumber( *pPaM
->GetMark() );
1065 if ( ( nPtLine
== 0 && nMkLine
!= USHRT_MAX
) ||
1066 ( nMkLine
== 0 && nPtLine
!= USHRT_MAX
) )
1068 nRet
= std::max( nPtLine
, nMkLine
) + 1;
1076 * 1. case: bRepeat = true
1077 * returns true if the current frame is located inside a table headline in
1080 * 2. case: bRepeat = false
1081 * returns true if the current frame is located inside a table headline OR
1082 * inside the first line of a table!!!
1084 bool SwFEShell::CheckHeadline( bool bRepeat
) const
1087 if ( !IsTableMode() )
1089 SwFrame
*pFrame
= GetCurrFrame(); // DONE MULTIIHEADER
1090 SwTabFrame
* pTab
= (pFrame
&& pFrame
->IsInTab()) ? pFrame
->FindTabFrame() : nullptr;
1095 bRet
= pTab
->IsFollow() && pTab
->IsInHeadline( *pFrame
);
1099 bRet
= static_cast<SwLayoutFrame
*>(pTab
->Lower())->IsAnLower( pFrame
) ||
1100 pTab
->IsInHeadline( *pFrame
);
1107 void SwFEShell::AdjustCellWidth( const bool bBalance
, const bool bNoShrink
)
1109 CurrShell
aCurr( this );
1112 // switch on wait-cursor, as we do not know how
1113 // much content is affected
1114 TableWait
aWait(std::numeric_limits
<size_t>::max(), nullptr,
1115 *GetDoc()->GetDocShell());
1117 GetDoc()->AdjustCellWidth( *getShellCursor( false ), bBalance
, bNoShrink
);
1118 EndAllActionAndCall();
1121 bool SwFEShell::IsAdjustCellWidthAllowed( bool bBalance
) const
1123 // at least one row with content should be contained in the selection
1125 SwFrame
*pFrame
= GetCurrFrame();
1126 if( !pFrame
|| !pFrame
->IsInTab() )
1130 ::GetTableSelCrs( *this, aBoxes
);
1133 return aBoxes
.size() > 1;
1135 if ( aBoxes
.empty() )
1139 pFrame
= pFrame
->GetUpper();
1141 while (pFrame
&& !pFrame
->IsCellFrame());
1146 SwTableBox
*pBox
= const_cast<SwTableBox
*>(static_cast<SwCellFrame
*>(pFrame
)->GetTabBox());
1147 aBoxes
.insert( pBox
);
1150 for (size_t i
= 0; i
< aBoxes
.size(); ++i
)
1152 SwTableBox
*pBox
= aBoxes
[i
];
1153 if ( pBox
->GetSttNd() )
1155 SwNodeIndex
aIdx( *pBox
->GetSttNd(), 1 );
1156 SwTextNode
* pCNd
= aIdx
.GetNode().GetTextNode();
1158 pCNd
= static_cast<SwTextNode
*>(GetDoc()->GetNodes().GoNext( &aIdx
));
1162 if (!pCNd
->GetText().isEmpty())
1165 pCNd
= aIdx
.GetNode().GetTextNode();
1172 bool SwFEShell::SetTableStyle(const OUString
& rStyleName
)
1174 // make sure SwDoc has the style
1175 SwTableAutoFormat
*pTableFormat
= GetDoc()->GetTableStyles().FindAutoFormat(rStyleName
);
1179 SwTableNode
*pTableNode
= const_cast<SwTableNode
*>(IsCursorInTable());
1183 // set the name & update
1184 return UpdateTableStyleFormatting(pTableNode
, false, &rStyleName
);
1187 // AutoFormat for the table/table selection
1188 bool SwFEShell::SetTableStyle(const SwTableAutoFormat
& rStyle
)
1190 // make sure SwDoc has the style
1191 GetDoc()->GetTableStyles().AddAutoFormat(rStyle
);
1193 SwTableNode
*pTableNode
= const_cast<SwTableNode
*>(IsCursorInTable());
1197 // set the name & update
1198 return UpdateTableStyleFormatting(pTableNode
, false, &rStyle
.GetName());
1201 bool SwFEShell::UpdateTableStyleFormatting(SwTableNode
*pTableNode
,
1202 bool bResetDirect
, OUString
const*const pStyleName
)
1206 pTableNode
= const_cast<SwTableNode
*>(IsCursorInTable());
1207 if (!pTableNode
|| pTableNode
->GetTable().IsTableComplex())
1211 OUString
const aTableStyleName(pStyleName
1213 : pTableNode
->GetTable().GetTableStyleName());
1214 SwTableAutoFormat
* pTableStyle
= GetDoc()->GetTableStyles().FindAutoFormat(aTableStyleName
);
1220 // whole table or only current selection
1222 ::GetTableSelCrs( *this, aBoxes
);
1225 const SwTableSortBoxes
& rTBoxes
= pTableNode
->GetTable().GetTabSortBoxes();
1226 for (size_t n
= 0; n
< rTBoxes
.size(); ++n
)
1228 SwTableBox
* pBox
= rTBoxes
[ n
];
1229 aBoxes
.insert( pBox
);
1234 if( !aBoxes
.empty() )
1236 CurrShell
aCurr( this );
1238 bRet
= GetDoc()->SetTableAutoFormat(
1239 aBoxes
, *pTableStyle
, bResetDirect
, pStyleName
!= nullptr);
1240 ClearFEShellTabCols(*GetDoc(), nullptr);
1241 EndAllActionAndCall();
1248 bool SwFEShell::GetTableAutoFormat( SwTableAutoFormat
& rGet
)
1250 const SwTableNode
*pTableNd
= IsCursorInTable();
1251 if( !pTableNd
|| pTableNd
->GetTable().IsTableComplex() )
1256 if ( !IsTableMode() ) // if cursor are not current
1259 // whole table or only current selection
1261 ::GetTableSelCrs( *this, aBoxes
);
1264 const SwTableSortBoxes
& rTBoxes
= pTableNd
->GetTable().GetTabSortBoxes();
1265 for (size_t n
= 0; n
< rTBoxes
.size(); ++n
)
1267 SwTableBox
* pBox
= rTBoxes
[ n
];
1268 aBoxes
.insert( pBox
);
1272 return GetDoc()->GetTableAutoFormat( aBoxes
, rGet
);
1275 bool SwFEShell::DeleteTableSel()
1277 // check if SPoint/Mark of current cursor are in a table
1278 SwFrame
*pFrame
= GetCurrFrame();
1279 if( !pFrame
|| !pFrame
->IsInTab() )
1282 if( dynamic_cast< const SwDDETable
* >(pFrame
->ImplFindTabFrame()->GetTable()) != nullptr )
1284 ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR
, GetFrameWeld(GetDoc()->GetDocShell()),
1285 DialogMask::MessageInfo
| DialogMask::ButtonsOk
);
1289 CurrShell
aCurr( this );
1292 // search boxes via the layout
1295 GetTableSelCrs( *this, aBoxes
);
1296 if( !aBoxes
.empty() )
1298 TableWait
aWait( aBoxes
.size(), pFrame
, *GetDoc()->GetDocShell() );
1300 // cursor should be removed from deletion area.
1301 // Put them behind/on the table; via the document
1302 // position they'll be set to the old position
1303 while( !pFrame
->IsCellFrame() )
1304 pFrame
= pFrame
->GetUpper();
1305 ParkCursor( SwNodeIndex( *static_cast<SwCellFrame
*>(pFrame
)->GetTabBox()->GetSttNd() ));
1307 bRet
= GetDoc()->DeleteRowCol( aBoxes
);
1309 ClearFEShellTabCols(*GetDoc(), nullptr);
1313 EndAllActionAndCall();
1317 size_t SwFEShell::GetCurTabColNum() const
1319 //!!!GetCurMouseTabColNum() mitpflegen!!!!
1320 SwFrame
*pFrame
= GetCurrFrame();
1321 OSL_ENSURE( pFrame
, "Cursor parked?" );
1323 // check if SPoint/Mark of current cursor are in a table
1324 if (!pFrame
|| !pFrame
->IsInTab())
1329 // JP 26.09.95: why compare with ContentFrame
1330 // and not with CellFrame ????
1331 pFrame
= pFrame
->GetUpper();
1332 } while (pFrame
&& !pFrame
->IsCellFrame());
1339 SwRectFnSet
aRectFnSet(pFrame
);
1341 const SwPageFrame
* pPage
= pFrame
->FindPageFrame();
1343 // get TabCols, as only via these we get to the position
1345 GetTabCols( aTabCols
);
1347 if( pFrame
->FindTabFrame()->IsRightToLeft() )
1349 tools::Long nX
= aRectFnSet
.GetRight(pFrame
->getFrameArea()) - aRectFnSet
.GetLeft(pPage
->getFrameArea());
1351 const tools::Long nRight
= aTabCols
.GetLeftMin() + aTabCols
.GetRight();
1353 if ( !::IsSame( nX
, nRight
) )
1355 nX
= nRight
- nX
+ aTabCols
.GetLeft();
1356 for ( size_t i
= 0; i
< aTabCols
.Count(); ++i
)
1357 if ( ::IsSame( nX
, aTabCols
[i
] ) )
1366 const tools::Long nX
= aRectFnSet
.GetLeft(pFrame
->getFrameArea()) -
1367 aRectFnSet
.GetLeft(pPage
->getFrameArea());
1369 const tools::Long nLeft
= aTabCols
.GetLeftMin();
1371 if ( !::IsSame( nX
, nLeft
+ aTabCols
.GetLeft() ) )
1373 for ( size_t i
= 0; i
< aTabCols
.Count(); ++i
)
1374 if ( ::IsSame( nX
, nLeft
+ aTabCols
[i
] ) )
1384 static const SwFrame
*lcl_FindFrameInTab( const SwLayoutFrame
*pLay
, const Point
&rPt
, SwTwips nFuzzy
)
1386 const SwFrame
*pFrame
= pLay
->Lower();
1388 while( pFrame
&& pLay
->IsAnLower( pFrame
) )
1390 if ( pFrame
->getFrameArea().IsNear( rPt
, nFuzzy
) )
1392 if ( pFrame
->IsLayoutFrame() )
1394 const SwFrame
*pTmp
= ::lcl_FindFrameInTab( static_cast<const SwLayoutFrame
*>(pFrame
), rPt
, nFuzzy
);
1402 pFrame
= pFrame
->FindNext();
1408 static const SwCellFrame
*lcl_FindFrame( const SwLayoutFrame
*pLay
, const Point
&rPt
,
1409 SwTwips nFuzzy
, bool* pbRow
, bool* pbCol
)
1411 // bMouseMoveRowCols :
1412 // Method is called for
1413 // - Moving columns/rows with the mouse or
1414 // - Enhanced table selection
1415 const bool bMouseMoveRowCols
= nullptr == pbCol
;
1417 bool bCloseToRow
= false;
1418 bool bCloseToCol
= false;
1420 const SwFrame
*pFrame
= pLay
->ContainsContent();
1421 const SwFrame
* pRet
= nullptr;
1427 if ( pFrame
->IsInTab() )
1428 pFrame
= const_cast<SwFrame
*>(pFrame
)->ImplFindTabFrame();
1433 if ( pFrame
->IsTabFrame() )
1436 bool bSearchForFrameInTab
= true;
1437 SwTwips nTmpFuzzy
= nFuzzy
;
1439 if ( !bMouseMoveRowCols
)
1441 // We ignore nested tables for the enhanced table selection:
1442 while ( pFrame
->GetUpper()->IsInTab() )
1443 pFrame
= pFrame
->GetUpper()->FindTabFrame();
1445 // We first check if the given point is 'close' to the left or top
1446 // border of the table frame:
1447 OSL_ENSURE( pFrame
, "Nested table frame without outer table" );
1448 SwRectFnSet
aRectFnSet(pFrame
);
1449 const bool bRTL
= pFrame
->IsRightToLeft();
1451 SwRect aTabRect
= pFrame
->getFramePrintArea();
1452 aTabRect
.Pos() += pFrame
->getFrameArea().Pos();
1454 const SwTwips nLeft
= bRTL
?
1455 aRectFnSet
.GetRight(aTabRect
) :
1456 aRectFnSet
.GetLeft(aTabRect
);
1457 const SwTwips nTop
= aRectFnSet
.GetTop(aTabRect
);
1459 SwTwips
const rPointX
= aRectFnSet
.IsVert() ? aPt
.Y() : aPt
.X();
1460 SwTwips
const rPointY
= aRectFnSet
.IsVert() ? aPt
.X() : aPt
.Y();
1462 const SwTwips nXDiff
= aRectFnSet
.XDiff( nLeft
, rPointX
) * ( bRTL
? -1 : 1 );
1463 const SwTwips nYDiff
= aRectFnSet
.YDiff( nTop
, rPointY
);
1465 bCloseToRow
= nXDiff
>= 0 && nXDiff
< nFuzzy
;
1466 bCloseToCol
= nYDiff
>= 0 && nYDiff
< nFuzzy
;
1468 if ( bCloseToCol
&& 2 * nYDiff
> nFuzzy
)
1470 const SwFrame
* pPrev
= pFrame
->GetPrev();
1473 SwRect aPrevRect
= pPrev
->getFramePrintArea();
1474 aPrevRect
.Pos() += pPrev
->getFrameArea().Pos();
1476 if( aPrevRect
.IsInside( rPt
) )
1478 bCloseToCol
= false;
1484 // If we found the point to be 'close' to the left or top border
1485 // of the table frame, we adjust the point to be on that border:
1486 if ( bCloseToRow
&& bCloseToCol
)
1487 aPt
= bRTL
? aTabRect
.TopRight() : aRectFnSet
.GetPos(aTabRect
);
1488 else if ( bCloseToRow
)
1489 aRectFnSet
.IsVert() ? aPt
.setY(nLeft
) : aPt
.setX(nLeft
);
1490 else if ( bCloseToCol
)
1491 aRectFnSet
.IsVert() ? aPt
.setX(nTop
) : aPt
.setY(nTop
);
1493 if ( !bCloseToRow
&& !bCloseToCol
)
1494 bSearchForFrameInTab
= false;
1496 // Since the point has been adjusted, we call lcl_FindFrameInTab()
1497 // with a fuzzy value of 1:
1501 const SwFrame
* pTmp
= bSearchForFrameInTab
?
1502 ::lcl_FindFrameInTab( static_cast<const SwLayoutFrame
*>(pFrame
), aPt
, nTmpFuzzy
) :
1511 pFrame
= pFrame
->FindNextCnt();
1513 } while ( pFrame
&& pLay
->IsAnLower( pFrame
) );
1516 if ( pFrame
&& pFrame
->IsInTab() && pLay
->IsAnLower( pFrame
) )
1520 // We allow mouse drag of table borders within nested tables,
1521 // but disallow hotspot selection of nested tables.
1522 if ( bMouseMoveRowCols
)
1524 // find the next cell frame
1525 while ( pFrame
&& !pFrame
->IsCellFrame() )
1526 pFrame
= pFrame
->GetUpper();
1530 // find the most upper cell frame:
1532 ( !pFrame
->IsCellFrame() ||
1533 !pFrame
->GetUpper()->GetUpper()->IsTabFrame() ||
1534 pFrame
->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
1535 pFrame
= pFrame
->GetUpper();
1538 if ( pFrame
) // Note: this condition should be the same like the while condition!!!
1540 // #i32329# Enhanced table selection
1541 // used for hotspot selection of tab/cols/rows
1542 if ( !bMouseMoveRowCols
)
1545 OSL_ENSURE( pbCol
&& pbRow
, "pbCol or pbRow missing" );
1547 if ( bCloseToRow
|| bCloseToCol
)
1549 *pbRow
= bCloseToRow
;
1550 *pbCol
= bCloseToCol
;
1557 // used for mouse move of columns/rows
1558 const SwTabFrame
* pTabFrame
= pFrame
->FindTabFrame();
1559 SwRect aTabRect
= pTabFrame
->getFramePrintArea();
1560 aTabRect
.Pos() += pTabFrame
->getFrameArea().Pos();
1562 SwRectFnSet
aRectFnSet(pTabFrame
);
1564 const SwTwips nTabTop
= aRectFnSet
.GetTop(aTabRect
);
1565 const SwTwips nMouseTop
= aRectFnSet
.IsVert() ? rPt
.X() : rPt
.Y();
1567 // Do not allow to drag upper table border:
1568 if ( !::IsSame( nTabTop
, nMouseTop
) )
1570 if ( ::IsSame( pFrame
->getFrameArea().Left(), rPt
.X() ) ||
1571 ::IsSame( pFrame
->getFrameArea().Right(),rPt
.X() ) )
1573 if ( pbRow
) *pbRow
= false;
1577 if ( ::IsSame( pFrame
->getFrameArea().Top(), rPt
.Y() ) ||
1578 ::IsSame( pFrame
->getFrameArea().Bottom(),rPt
.Y() ) )
1580 if ( pbRow
) *pbRow
= true;
1587 pFrame
= pFrame
->GetUpper();
1593 OSL_ENSURE( !pRet
|| pRet
->IsCellFrame(), "lcl_FindFrame() is supposed to find a cell frame!" );
1594 return pRet
&& pRet
->IsCellFrame() ? static_cast<const SwCellFrame
*>(pRet
) : nullptr;
1597 // pbCol = 0 => Used for moving table rows/cols with mouse
1598 // pbCol != 0 => Used for selecting table/rows/cols
1600 #define ENHANCED_TABLE_SELECTION_FUZZY 10
1602 const SwFrame
* SwFEShell::GetBox( const Point
&rPt
, bool* pbRow
, bool* pbCol
) const
1604 const SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(GetLayout()->Lower());
1605 vcl::Window
* pOutWin
= GetWin();
1606 SwTwips nFuzzy
= COLFUZZY
;
1609 // #i32329# Enhanced table selection
1610 SwTwips nSize
= pbCol
? ENHANCED_TABLE_SELECTION_FUZZY
: RULER_MOUSE_MARGINWIDTH
;
1611 Size
aTmp( nSize
, nSize
);
1612 aTmp
= pOutWin
->PixelToLogic( aTmp
);
1613 nFuzzy
= aTmp
.Width();
1616 while ( pPage
&& !pPage
->getFrameArea().IsNear( rPt
, nFuzzy
) )
1617 pPage
= static_cast<const SwPageFrame
*>(pPage
->GetNext());
1619 const SwCellFrame
*pFrame
= nullptr;
1622 // We cannot search the box by GetModelPositionForViewPoint or GetContentPos.
1623 // This would lead to a performance collapse for documents
1624 // with a lot of paragraphs/tables on one page
1628 if ( pPage
->GetSortedObjs() )
1630 for ( size_t i
= 0; !pFrame
&& i
< pPage
->GetSortedObjs()->size(); ++i
)
1632 SwAnchoredObject
* pObj
= (*pPage
->GetSortedObjs())[i
];
1633 if ( auto pFlyFrame
= dynamic_cast<SwFlyFrame
*>( pObj
) )
1635 pFrame
= lcl_FindFrame( pFlyFrame
, rPt
, nFuzzy
, pbRow
, pbCol
);
1639 const SwLayoutFrame
*pLay
= static_cast<const SwLayoutFrame
*>(pPage
->Lower());
1640 while ( pLay
&& !pFrame
)
1642 pFrame
= lcl_FindFrame( pLay
, rPt
, nFuzzy
, pbRow
, pbCol
);
1643 pLay
= static_cast<const SwLayoutFrame
*>(pLay
->GetNext());
1649 /* Helper function*/
1650 /* calculated the distance between Point rC and Line Segment (rA, rB) */
1651 static double lcl_DistancePoint2Segment( const Point
& rA
, const Point
& rB
, const Point
& rC
)
1655 const basegfx::B2DVector
aBC( rC
.X() - rB
.X(), rC
.Y() - rB
.Y() );
1656 const basegfx::B2DVector
aAB( rB
.X() - rA
.X(), rB
.Y() - rA
.Y() );
1657 const double nDot1
= aBC
.scalar( aAB
);
1659 if ( nDot1
> 0 ) // check outside case 1
1660 nRet
= aBC
.getLength();
1663 const basegfx::B2DVector
aAC( rC
.X() - rA
.X(), rC
.Y() - rA
.Y() );
1664 const basegfx::B2DVector
aBA( rA
.X() - rB
.X(), rA
.Y() - rB
.Y() );
1665 const double nDot2
= aAC
.scalar( aBA
);
1667 if ( nDot2
> 0 ) // check outside case 2
1668 nRet
= aAC
.getLength();
1671 const double nDiv
= aAB
.getLength();
1672 nRet
= nDiv
? aAB
.cross( aAC
) / nDiv
: 0;
1676 return std::abs(nRet
);
1679 /* Helper function*/
1680 static Point
lcl_ProjectOntoClosestTableFrame( const SwTabFrame
& rTab
, const Point
& rPoint
, bool bRowDrag
)
1682 Point
aRet( rPoint
);
1683 const SwTabFrame
* pCurrentTab
= &rTab
;
1684 const bool bVert
= pCurrentTab
->IsVertical();
1685 const bool bRTL
= pCurrentTab
->IsRightToLeft();
1688 // bRowDrag = true => compare to left border of table
1689 // bRowDrag = false => compare to top border of table
1692 // bRowDrag = true => compare to right border of table
1693 // bRowDrag = false => compare to top border of table
1696 // bRowDrag = true => compare to right border of table
1697 // bRowDrag = false => compare to top border of table
1699 bool bRight
= false;
1703 if ( bVert
|| bRTL
)
1709 // used to find the minimal distance
1717 while ( pCurrentTab
)
1719 SwRect
aTabRect( pCurrentTab
->getFramePrintArea() );
1720 aTabRect
+= pCurrentTab
->getFrameArea().Pos();
1724 // distance to left table border
1725 aS1
= aTabRect
.TopLeft();
1726 aS2
= aTabRect
.BottomLeft();
1730 // distance to right table border
1731 aS1
= aTabRect
.TopRight();
1732 aS2
= aTabRect
.BottomRight();
1736 // distance to top table border
1737 aS1
= aTabRect
.TopLeft();
1738 aS2
= aTabRect
.TopRight();
1741 const double nDist
= lcl_DistancePoint2Segment( aS1
, aS2
, rPoint
);
1743 if ( nDist
< nMin
|| -1 == nMin
)
1750 pCurrentTab
= pCurrentTab
->GetFollow();
1753 // project onto closest line:
1754 if ( bLeft
|| bRight
)
1756 aRet
.setX(aMin1
.getX());
1757 if ( aRet
.getY() > aMin2
.getY() )
1758 aRet
.setY(aMin2
.getY());
1759 else if ( aRet
.getY() < aMin1
.getY() )
1760 aRet
.setY(aMin1
.getY());
1764 aRet
.setY(aMin1
.getY());
1765 if ( aRet
.getX() > aMin2
.getX() )
1766 aRet
.setX(aMin2
.getX());
1767 else if ( aRet
.getX() < aMin1
.getX() )
1768 aRet
.setX(aMin1
.getX());
1774 // #i32329# Enhanced table selection
1775 bool SwFEShell::SelTableRowCol( const Point
& rPt
, const Point
* pEnd
, bool bRowDrag
)
1782 SwPosition
* ppPos
[2] = { nullptr, nullptr };
1783 Point paPt
[2] = { rPt
, aEndPt
};
1784 bool pbRow
[2] = { false, false };
1785 bool pbCol
[2] = { false, false };
1787 // pEnd is set during dragging.
1788 for ( sal_uInt16 i
= 0; i
< ( pEnd
? 2 : 1 ); ++i
)
1790 const SwCellFrame
* pFrame
=
1791 static_cast<const SwCellFrame
*>(GetBox( paPt
[i
], &pbRow
[i
], &pbCol
[i
] ) );
1795 while( pFrame
&& pFrame
->Lower() && pFrame
->Lower()->IsRowFrame() )
1796 pFrame
= static_cast<const SwCellFrame
*>( static_cast<const SwLayoutFrame
*>( pFrame
->Lower() )->Lower() );
1797 if( pFrame
&& pFrame
->GetTabBox()->GetSttNd() &&
1798 pFrame
->GetTabBox()->GetSttNd()->IsInProtectSect() )
1804 const SwContentFrame
* pContent
= ::GetCellContent( *pFrame
);
1806 if ( pContent
&& pContent
->IsTextFrame() )
1809 ppPos
[i
] = new SwPosition(static_cast<SwTextFrame
const*>(pContent
)->MapViewToModelPos(TextFrameIndex(0)));
1811 // paPt[i] will not be used any longer, now we use it to store
1812 // a position inside the content frame
1813 paPt
[i
] = pContent
->getFrameArea().Center();
1817 // no calculation of end frame if start frame has not been found.
1818 if ( 1 == i
|| !ppPos
[0] || !pEnd
|| !pFrame
)
1821 // find 'closest' table frame to pEnd:
1822 const SwTabFrame
* pCurrentTab
= pFrame
->FindTabFrame();
1823 if ( pCurrentTab
->IsFollow() )
1824 pCurrentTab
= pCurrentTab
->FindMaster( true );
1826 const Point aProjection
= lcl_ProjectOntoClosestTableFrame( *pCurrentTab
, *pEnd
, bRowDrag
);
1827 paPt
[1] = aProjection
;
1832 SwShellCursor
* pCursor
= GetCursor_();
1833 SwCursorSaveState
aSaveState( *pCursor
);
1834 SwPosition
aOldPos( *pCursor
->GetPoint() );
1836 pCursor
->DeleteMark();
1837 *pCursor
->GetPoint() = *ppPos
[0];
1838 pCursor
->GetPtPos() = paPt
[0];
1840 if ( !pCursor
->IsInProtectTable() )
1842 bool bNewSelection
= true;
1846 if ( ppPos
[1]->nNode
.GetNode().StartOfSectionNode() !=
1847 aOldPos
.nNode
.GetNode().StartOfSectionNode() )
1850 SwCursorSaveState
aSaveState2( *pCursor
);
1851 *pCursor
->GetPoint() = *ppPos
[1];
1852 pCursor
->GetPtPos() = paPt
[1];
1854 if ( pCursor
->IsInProtectTable( false, false ) )
1856 pCursor
->RestoreSavePos();
1857 bNewSelection
= false;
1862 pCursor
->RestoreSavePos();
1863 bNewSelection
= false;
1867 if ( bNewSelection
)
1869 // #i35543# SelTableRowCol should remove any existing
1871 if ( IsTableMode() )
1872 TableCursorToCursor();
1874 if ( pbRow
[0] && pbCol
[0] )
1875 bRet
= SwCursorShell::SelTable();
1876 else if ( pbRow
[0] )
1877 bRet
= SwCursorShell::SelTableRowOrCol( true, true );
1878 else if ( pbCol
[0] )
1879 bRet
= SwCursorShell::SelTableRowOrCol( false, true );
1892 SwTab
SwFEShell::WhichMouseTabCol( const Point
&rPt
) const
1894 SwTab nRet
= SwTab::COL_NONE
;
1897 bool bSelect
= false;
1899 // First try: Do we get the row/col move cursor?
1900 const SwCellFrame
* pFrame
= static_cast<const SwCellFrame
*>(GetBox( rPt
, &bRow
));
1904 // Second try: Do we get the row/col/tab selection cursor?
1905 pFrame
= static_cast<const SwCellFrame
*>(GetBox( rPt
, &bRow
, &bCol
));
1911 while( pFrame
&& pFrame
->Lower() && pFrame
->Lower()->IsRowFrame() )
1912 pFrame
= static_cast<const SwCellFrame
*>(static_cast<const SwLayoutFrame
*>(pFrame
->Lower())->Lower());
1913 if( pFrame
&& pFrame
->GetTabBox()->GetSttNd() &&
1914 pFrame
->GetTabBox()->GetSttNd()->IsInProtectSect() )
1922 if ( pFrame
->IsVertical() )
1923 nRet
= bRow
? SwTab::COL_VERT
: SwTab::ROW_VERT
;
1925 nRet
= bRow
? SwTab::ROW_HORI
: SwTab::COL_HORI
;
1929 const SwTabFrame
* pTabFrame
= pFrame
->FindTabFrame();
1930 if ( pTabFrame
->IsVertical() )
1934 nRet
= SwTab::SEL_VERT
;
1938 nRet
= SwTab::ROWSEL_VERT
;
1942 nRet
= SwTab::COLSEL_VERT
;
1949 nRet
= pTabFrame
->IsRightToLeft() ?
1950 SwTab::SEL_HORI_RTL
:
1955 nRet
= pTabFrame
->IsRightToLeft() ?
1956 SwTab::ROWSEL_HORI_RTL
:
1961 nRet
= SwTab::COLSEL_HORI
;
1971 SwTextNode
* SwFEShell::GetNumRuleNodeAtPos( const Point
&rPt
)
1973 SwTextNode
* pResult
= nullptr;
1975 SwContentAtPos
aContentAtPos(IsAttrAtPos::NumLabel
);
1977 if( GetContentAtPos(rPt
, aContentAtPos
) && aContentAtPos
.aFnd
.pNode
)
1978 pResult
= aContentAtPos
.aFnd
.pNode
->GetTextNode();
1983 bool SwFEShell::IsNumLabel( const Point
&rPt
, int nMaxOffset
)
1985 bool bResult
= false;
1987 SwContentAtPos
aContentAtPos(IsAttrAtPos::NumLabel
);
1989 if( GetContentAtPos(rPt
, aContentAtPos
))
1991 if ((nMaxOffset
>= 0 && aContentAtPos
.nDist
<= nMaxOffset
) ||
2001 bool SwFEShell::IsVerticalModeAtNdAndPos( const SwTextNode
& _rTextNode
,
2002 const Point
& _rDocPos
)
2006 const SvxFrameDirection nTextDir
=
2007 _rTextNode
.GetTextDirection( SwPosition(_rTextNode
), &_rDocPos
);
2010 case SvxFrameDirection::Unknown
:
2011 case SvxFrameDirection::Horizontal_RL_TB
:
2012 case SvxFrameDirection::Horizontal_LR_TB
:
2017 case SvxFrameDirection::Vertical_LR_TB
:
2018 case SvxFrameDirection::Vertical_RL_TB
:
2029 void SwFEShell::GetMouseTabCols( SwTabCols
&rToFill
, const Point
&rPt
) const
2031 const SwFrame
*pBox
= GetBox( rPt
);
2033 GetTabCols_( rToFill
, pBox
);
2036 void SwFEShell::SetMouseTabCols( const SwTabCols
&rNew
, bool bCurRowOnly
,
2039 const SwFrame
*pBox
= GetBox( rPt
);
2042 CurrShell
aCurr( this );
2044 GetDoc()->SetTabCols( rNew
, bCurRowOnly
, static_cast<const SwCellFrame
*>(pBox
) );
2045 EndAllActionAndCall();
2049 sal_uInt16
SwFEShell::GetCurMouseColNum( const Point
&rPt
) const
2051 return GetCurColNum_( GetBox( rPt
), nullptr );
2054 size_t SwFEShell::GetCurMouseTabColNum( const Point
&rPt
) const
2056 //!!!GetCurTabColNum() mitpflegen!!!!
2059 const SwFrame
*pFrame
= GetBox( rPt
);
2060 OSL_ENSURE( pFrame
, "Table not found" );
2063 const tools::Long nX
= pFrame
->getFrameArea().Left();
2065 // get TabCols, only via these we get the position
2067 GetMouseTabCols( aTabCols
, rPt
);
2069 const tools::Long nLeft
= aTabCols
.GetLeftMin();
2071 if ( !::IsSame( nX
, nLeft
+ aTabCols
.GetLeft() ) )
2073 for ( size_t i
= 0; i
< aTabCols
.Count(); ++i
)
2074 if ( ::IsSame( nX
, nLeft
+ aTabCols
[i
] ) )
2084 void ClearFEShellTabCols(SwDoc
& rDoc
, SwTabFrame
const*const pFrame
)
2086 auto const pShell(rDoc
.getIDocumentLayoutAccess().GetCurrentViewShell());
2089 for (SwViewShell
& rCurrentShell
: pShell
->GetRingContainer())
2091 if (auto const pFE
= dynamic_cast<SwFEShell
*>(&rCurrentShell
))
2093 pFE
->ClearColumnRowCache(pFrame
);
2099 void SwFEShell::ClearColumnRowCache(SwTabFrame
const*const pFrame
)
2103 if (pFrame
== nullptr || pFrame
== m_pColumnCache
->pLastTabFrame
)
2105 m_pColumnCache
.reset();
2110 if (pFrame
== nullptr || pFrame
== m_pRowCache
->pLastTabFrame
)
2112 m_pRowCache
.reset();
2117 void SwFEShell::GetTableAttr( SfxItemSet
&rSet
) const
2119 SwFrame
*pFrame
= GetCurrFrame();
2120 if( pFrame
&& pFrame
->IsInTab() )
2121 rSet
.Put( pFrame
->ImplFindTabFrame()->GetFormat()->GetAttrSet() );
2124 void SwFEShell::SetTableAttr( const SfxItemSet
&rNew
)
2126 SwFrame
*pFrame
= GetCurrFrame();
2127 if( pFrame
&& pFrame
->IsInTab() )
2129 CurrShell
aCurr( this );
2131 SwTabFrame
*pTab
= pFrame
->FindTabFrame();
2132 pTab
->GetTable()->SetHTMLTableLayout(std::shared_ptr
<SwHTMLTableLayout
>());
2133 GetDoc()->SetAttr( rNew
, *pTab
->GetFormat() );
2134 GetDoc()->getIDocumentState().SetModified();
2135 EndAllActionAndCall();
2139 // change a cell width/cell height/column width/row height
2140 void SwFEShell::SetColRowWidthHeight( TableChgWidthHeightType eType
, sal_uInt16 nDiff
)
2142 SwFrame
*pFrame
= GetCurrFrame();
2143 if( !pFrame
|| !pFrame
->IsInTab() )
2146 CurrShell
aCurr( this );
2150 pFrame
= pFrame
->GetUpper();
2151 } while( !pFrame
->IsCellFrame() );
2153 SwTabFrame
*pTab
= pFrame
->ImplFindTabFrame();
2155 // if the table is in relative values (USHRT_MAX)
2156 // then it should be recalculated to absolute values now
2157 const SwFormatFrameSize
& rTableFrameSz
= pTab
->GetFormat()->GetFrameSize();
2158 SwRectFnSet
aRectFnSet(pTab
);
2159 tools::Long nPrtWidth
= aRectFnSet
.GetWidth(pTab
->getFramePrintArea());
2160 TableChgWidthHeightType eTypePos
= extractPosition(eType
);
2161 if( TableChgMode::VarWidthChangeAbs
== pTab
->GetTable()->GetTableChgMode() &&
2162 ( eTypePos
== TableChgWidthHeightType::ColLeft
|| eTypePos
== TableChgWidthHeightType::ColRight
) &&
2163 text::HoriOrientation::NONE
== pTab
->GetFormat()->GetHoriOrient().GetHoriOrient() &&
2164 nPrtWidth
!= rTableFrameSz
.GetWidth() )
2166 SwFormatFrameSize
aSz( rTableFrameSz
);
2167 aSz
.SetWidth( pTab
->getFramePrintArea().Width() );
2168 pTab
->GetFormat()->SetFormatAttr( aSz
);
2171 SwTwips nLogDiff
= nDiff
;
2172 nLogDiff
*= pTab
->GetFormat()->GetFrameSize().GetWidth();
2173 nLogDiff
/= nPrtWidth
;
2175 /** The cells are destroyed in here */
2176 GetDoc()->SetColRowWidthHeight(
2177 *const_cast<SwTableBox
*>(static_cast<SwCellFrame
*>(pFrame
)->GetTabBox()),
2178 eType
, nDiff
, nLogDiff
);
2180 ClearFEShellTabCols(*GetDoc(), nullptr);
2181 EndAllActionAndCall();
2184 static bool lcl_IsFormulaSelBoxes( const SwTable
& rTable
, const SwTableBoxFormula
& rFormula
,
2185 SwCellFrames
& rCells
)
2187 SwTableBoxFormula
aTmp( rFormula
);
2189 aTmp
.GetBoxesOfFormula(rTable
, aBoxes
);
2190 for (size_t nSelBoxes
= aBoxes
.size(); nSelBoxes
; )
2192 SwTableBox
* pBox
= aBoxes
[ --nSelBoxes
];
2194 if( std::none_of(rCells
.begin(), rCells
.end(), [&pBox
](SwCellFrame
* pFrame
) { return pFrame
->GetTabBox() == pBox
; }) )
2201 // ask formula for auto-sum
2202 void SwFEShell::GetAutoSum( OUString
& rFormula
) const
2204 SwFrame
*pFrame
= GetCurrFrame();
2205 SwTabFrame
*pTab
= pFrame
? pFrame
->ImplFindTabFrame() : nullptr;
2209 SwCellFrames aCells
;
2211 if( ::GetAutoSumSel( *this, aCells
))
2214 for( size_t n
= aCells
.size(); n
; )
2216 SwCellFrame
* pCFrame
= aCells
[ --n
];
2217 sal_uInt16 nBoxW
= pCFrame
->GetTabBox()->IsFormulaOrValueBox();
2223 if( USHRT_MAX
== nBoxW
)
2224 continue; // skip space at beginning
2226 // formula only if box is contained
2227 if( RES_BOXATR_FORMULA
== nBoxW
&&
2228 !::lcl_IsFormulaSelBoxes( *pTab
->GetTable(), pCFrame
->
2229 GetTabBox()->GetFrameFormat()->GetTableBoxFormula(), aCells
))
2231 nW
= RES_BOXATR_VALUE
;
2232 // restore previous spaces!
2233 for( size_t i
= aCells
.size(); n
+1 < i
; )
2235 sFields
= "|<" + aCells
[--i
]->GetTabBox()->GetName() + ">"
2242 else if( RES_BOXATR_VALUE
== nW
)
2244 // search for values, Value/Formula/Text found -> include
2245 if( RES_BOXATR_FORMULA
== nBoxW
&&
2246 ::lcl_IsFormulaSelBoxes( *pTab
->GetTable(), pCFrame
->
2247 GetTabBox()->GetFrameFormat()->GetTableBoxFormula(), aCells
))
2249 else if( USHRT_MAX
!= nBoxW
)
2250 sFields
= OUStringChar(cListDelim
) + sFields
;
2254 else if( RES_BOXATR_FORMULA
== nW
)
2256 // only continue search when the current formula points to
2257 // all boxes contained in the selection
2258 if( RES_BOXATR_FORMULA
== nBoxW
)
2260 if( !::lcl_IsFormulaSelBoxes( *pTab
->GetTable(), pCFrame
->
2261 GetTabBox()->GetFrameFormat()->GetTableBoxFormula(), aCells
))
2263 // redo only for values!
2265 nW
= RES_BOXATR_VALUE
;
2267 // restore previous spaces!
2268 for( size_t i
= aCells
.size(); n
+1 < i
; )
2270 sFields
= "|<" + aCells
[--i
]->GetTabBox()->GetName() + ">"
2275 sFields
= OUStringChar(cListDelim
) + sFields
;
2277 else if( USHRT_MAX
== nBoxW
)
2280 continue; // ignore this box
2283 // all other stuff terminates the loop
2284 // possibly allow texts??
2287 sFields
= "<" + pCFrame
->GetTabBox()->GetName() + ">" + sFields
;
2291 rFormula
= OUString::createFromAscii( sCalc_Sum
);
2292 if (!sFields
.isEmpty())
2294 rFormula
+= "(" + sFields
+ ")";
2298 bool SwFEShell::IsTableRightToLeft() const
2300 SwFrame
*pFrame
= GetCurrFrame();
2301 SwTabFrame
*pTab
= (pFrame
&& pFrame
->IsInTab()) ? pFrame
->ImplFindTabFrame() : nullptr;
2304 return pTab
->IsRightToLeft();
2307 bool SwFEShell::IsMouseTableRightToLeft(const Point
&rPt
) const
2309 SwFrame
*pFrame
= const_cast<SwFrame
*>(GetBox( rPt
));
2310 const SwTabFrame
* pTabFrame
= pFrame
? pFrame
->ImplFindTabFrame() : nullptr;
2311 OSL_ENSURE( pTabFrame
, "Table not found" );
2312 return pTabFrame
&& pTabFrame
->IsRightToLeft();
2315 bool SwFEShell::IsTableVertical() const
2317 SwFrame
*pFrame
= GetCurrFrame();
2318 SwTabFrame
*pTab
= (pFrame
&& pFrame
->IsInTab()) ? pFrame
->ImplFindTabFrame() : nullptr;
2321 return pTab
->IsVertical();
2324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */