summaryrefslogtreecommitdiffstats
path: root/sw/source/core
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core')
-rw-r--r--sw/source/core/access/AccessibilityCheck.cxx5
-rw-r--r--sw/source/core/doc/docfly.cxx19
-rw-r--r--sw/source/core/edit/eddel.cxx8
-rw-r--r--sw/source/core/fields/expfld.cxx2
-rw-r--r--sw/source/core/layout/layact.cxx12
-rw-r--r--sw/source/core/layout/paintfrm.cxx3
-rw-r--r--sw/source/core/layout/tabfrm.cxx15
-rw-r--r--sw/source/core/text/frmform.cxx101
-rw-r--r--sw/source/core/undo/untbl.cxx15
-rw-r--r--sw/source/core/unocore/unoframe.cxx13
-rw-r--r--sw/source/core/unocore/unoobj.cxx12
-rw-r--r--sw/source/core/unocore/unoportenum.cxx3
12 files changed, 171 insertions, 37 deletions
diff --git a/sw/source/core/access/AccessibilityCheck.cxx b/sw/source/core/access/AccessibilityCheck.cxx
index e515b5cae7..dfa94c3ed9 100644
--- a/sw/source/core/access/AccessibilityCheck.cxx
+++ b/sw/source/core/access/AccessibilityCheck.cxx
@@ -901,6 +901,11 @@ public:
}
case '\t':
{
+ // Don't warn about tabs in ToC
+ auto pSection = SwDoc::GetCurrSection(SwPosition(*pTextNode, 0));
+ if (pSection && pSection->GetTOXBase())
+ continue;
+
if (bPreviousWasChar)
{
++nTabCount;
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index c492212487..2038941230 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -149,6 +149,25 @@ SwFrameFormat* SwDoc::GetFlyNum( size_t nIdx, FlyCntType eType, bool bIgnoreText
return pRetFormat;
}
+SwFrameFormat* SwDoc::GetFlyFrameFormatByName( const OUString& rFrameFormatName )
+{
+ auto pFrameFormats = GetSpzFrameFormats();
+ auto it = pFrameFormats->findByTypeAndName( RES_FLYFRMFMT, rFrameFormatName );
+ auto endIt = pFrameFormats->typeAndNameEnd();
+ for ( ; it != endIt; ++it)
+ {
+ sw::SpzFrameFormat* pFlyFormat = *it;
+ const SwNodeIndex* pIdx = pFlyFormat->GetContent().GetContentIdx();
+ if( !pIdx || !pIdx->GetNodes().IsDocNodes() )
+ continue;
+
+ const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
+ if( !pNd->IsNoTextNode())
+ return pFlyFormat;
+ }
+ return nullptr;
+}
+
std::vector<SwFrameFormat const*> SwDoc::GetFlyFrameFormats(
FlyCntType const eType, bool const bIgnoreTextBoxes)
{
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
index 9eb51da617..b8d6b0e395 100644
--- a/sw/source/core/edit/eddel.cxx
+++ b/sw/source/core/edit/eddel.cxx
@@ -33,7 +33,8 @@
#include <strings.hrc>
#include <vector>
-void SwEditShell::DeleteSel(SwPaM& rPam, bool const isArtificialSelection, bool *const pUndo)
+void SwEditShell::DeleteSel(SwPaM& rPam, bool const isArtificialSelection, bool goLeft,
+ bool* const pUndo)
{
auto const oSelectAll(StartsWith_() != SwCursorShell::StartsWith::None
? ExtendedSelectedAll()
@@ -127,11 +128,12 @@ void SwEditShell::DeleteSel(SwPaM& rPam, bool const isArtificialSelection, bool
}
}
+ rPam.Normalize(goLeft); // change tracking case: will make sure to end up in the correct point
// Selection is not needed anymore
rPam.DeleteMark();
}
-bool SwEditShell::Delete(bool const isArtificialSelection)
+bool SwEditShell::Delete(bool const isArtificialSelection, bool goLeft)
{
CurrShell aCurr( this );
bool bRet = false;
@@ -159,7 +161,7 @@ bool SwEditShell::Delete(bool const isArtificialSelection)
for(SwPaM& rPaM : GetCursor()->GetRingContainer())
{
- DeleteSel(rPaM, isArtificialSelection, &bUndo);
+ DeleteSel(rPaM, isArtificialSelection, goLeft, &bUndo);
}
// If undo container then close here
diff --git a/sw/source/core/fields/expfld.cxx b/sw/source/core/fields/expfld.cxx
index 6ed4cdb7c1..47c675cc42 100644
--- a/sw/source/core/fields/expfld.cxx
+++ b/sw/source/core/fields/expfld.cxx
@@ -233,7 +233,7 @@ const SwTextNode* GetBodyTextNode( const SwDoc& rDoc, SwPosition& rPos,
else
pContentFrame = pPgFrame->FindLastBodyContent();
- if( pContentFrame )
+ if( pContentFrame && !pContentFrame->IsInFootnote() )
{
assert(pContentFrame->IsTextFrame());
SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pContentFrame));
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index a705ef2511..1a0a1260a1 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -809,6 +809,12 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext)
unlockPositionOfObjects( pPg );
pPg = static_cast<SwPageFrame*>(pPg->GetNext());
}
+ if (m_pRoot->IsSuperfluous()) // could be newly set now!
+ {
+ bool bOld = IsAgain();
+ m_pRoot->RemoveSuperfluous();
+ SetAgain(bOld);
+ }
// reset flag for special interrupt content formatting.
mbFormatContentOnInterrupt = false;
}
@@ -1433,7 +1439,11 @@ bool SwLayAction::FormatLayout( OutputDevice *pRenderContext, SwLayoutFrame *pLa
PopFormatLayout();
}
}
- // else: don't calc content frames any more
+ else if (pLay->IsSctFrame() && pLow->IsTextFrame() && pLow == pLay->GetLastLower())
+ {
+ // else: only calc the last text lower of sections
+ pLow->OptCalc();
+ }
if ( IsAgain() )
return false;
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 0f048c4e80..5472695e97 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -7012,7 +7012,8 @@ void SwPageFrame::RefreshSubsidiary( const SwRect &rRect ) const
void SwLayoutFrame::RefreshLaySubsidiary( const SwPageFrame *pPage,
const SwRect &rRect ) const
{
- const bool bSubsOpt = isSubsidiaryLinesEnabled() || isSubsidiaryLinesForSectionsEnabled();
+ const bool bSubsOpt
+ = isSubsidiaryLinesEnabled() || (IsSctFrame() && isSubsidiaryLinesForSectionsEnabled());
if ( bSubsOpt )
PaintSubsidiaryLines( pPage, rRect );
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index c4a742c037..adffbba177 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -1165,7 +1165,13 @@ bool SwTabFrame::Split(const SwTwips nCutPos, bool bTryToSplit,
OSL_ENSURE( !GetIndPrev(), "Table is supposed to be at beginning" );
if ( !IsInSct() )
{
- m_pTable->SetRowsToRepeat(0);
+ // This would mean the layout modifies the doc model, so RowsToRepeat drops to 0 while
+ // there are existing row frames with RepeatedHeadline == true. Avoid this at least
+ // inside split flys, it would lead to a crash in SwTabFrame::MakeAll().
+ if (!pFly || !pFly->IsFlySplitAllowed())
+ {
+ m_pTable->SetRowsToRepeat(0);
+ }
return false;
}
else
@@ -1517,7 +1523,8 @@ namespace
}
}
}
- if (rTab.IsCollapsingBorders() && !rCell.Lower()->IsRowFrame())
+ assert(rCell.Lower());
+ if (rTab.IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrame())
{
if (rRow.GetTopMarginForLowers() != 0
|| rRow.GetBottomMarginForLowers() != 0)
@@ -6371,6 +6378,10 @@ void SwTabFrame::dumpAsXml(xmlTextWriterPtr writer) const
{
(void)xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>("tab"));
SwFrame::dumpAsXmlAttributes( writer );
+
+ (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("has-follow-flow-line"),
+ BAD_CAST(OString::boolean(m_bHasFollowFlowLine).getStr()));
+
if ( HasFollow() )
(void)xmlTextWriterWriteFormatAttribute( writer, BAD_CAST( "follow" ), "%" SAL_PRIuUINT32, GetFollow()->GetFrameId() );
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index e19b834a56..97eff3e607 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -1081,6 +1081,54 @@ void SwTextFrame::ChangeOffset( SwTextFrame* pFrame, TextFrameIndex nNew )
MoveFlyInCnt( pFrame, nNew, TextFrameIndex(COMPLETE_STRING) );
}
+static bool isFirstVisibleFrameInBody(const SwTextFrame* pFrame)
+{
+ const SwFrame* pBodyFrame = pFrame->FindBodyFrame();
+ if (!pBodyFrame)
+ return false;
+ for (const SwFrame* pCur = pFrame;;)
+ {
+ for (const SwFrame* pPrev = pCur->GetPrev(); pPrev; pPrev = pPrev->GetPrev())
+ if (!pPrev->IsHiddenNow())
+ return false;
+ pCur = pCur->GetUpper();
+ assert(pCur); // We found pBodyFrame, right?
+ if (pCur->IsBodyFrame())
+ return true;
+ }
+}
+
+static bool hasFly(const SwTextFrame* pFrame)
+{
+ if (auto pDrawObjs = pFrame->GetDrawObjs(); pDrawObjs && pDrawObjs->size())
+ {
+ auto anchorId = (*pDrawObjs)[0]->GetFrameFormat()->GetAnchor().GetAnchorId();
+ if (anchorId == RndStdIds::FLY_AT_PARA || anchorId == RndStdIds::FLY_AT_CHAR)
+ return true;
+ }
+ return false;
+}
+
+static bool hasAtPageFly(const SwFrame* pFrame)
+{
+ auto pPageFrame = pFrame->FindPageFrame();
+ if (!pPageFrame)
+ return false;
+ auto pPageDrawObjs = pPageFrame->GetDrawObjs();
+ if (pPageDrawObjs)
+ {
+ for (const auto pObject : *pPageDrawObjs)
+ if (pObject->GetFrameFormat()->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+ return true;
+ }
+ return false;
+}
+
+static bool isReallyEmptyMaster(const SwTextFrame* pFrame)
+{
+ return pFrame->IsEmptyMaster() && (!pFrame->GetDrawObjs() || !pFrame->GetDrawObjs()->size());
+}
+
void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
WidowsAndOrphans &rFrameBreak,
TextFrameIndex const nStrLen,
@@ -1108,27 +1156,55 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
? 1 : 0;
SwTextFormatInfo& rInf = rLine.GetInfo();
+ bool bEmptyWithSplitFly = false;
if (nNew == 0 && !nStrLen && !rInf.GetTextFly().IsOn() && IsEmptyWithSplitFly())
{
// Empty paragraph, so IsBreakNow() is not called, but we should split the fly portion and
// the paragraph marker.
nNew = 1;
+ bEmptyWithSplitFly = true;
}
+ const SwFrame *pBodyFrame = FindBodyFrame();
+
// i#84870
// no split of text frame, which only contains an as-character anchored object
- bool bOnlyContainsAsCharAnchoredObj =
+ bool bLoneAsCharAnchoredObj =
+ pBodyFrame &&
!IsFollow() && nStrLen == TextFrameIndex(1) &&
GetDrawObjs() && GetDrawObjs()->size() == 1 &&
(*GetDrawObjs())[0]->GetFrameFormat()->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR;
- // Still try split text frame if we have columns.
- if (FindColFrame())
- bOnlyContainsAsCharAnchoredObj = false;
-
- if ( nNew && bOnlyContainsAsCharAnchoredObj )
+ if (bLoneAsCharAnchoredObj)
{
- nNew = 0;
+ // Still try split text frame if we have columns.
+ if (FindColFrame())
+ bLoneAsCharAnchoredObj = false;
+ // tdf#160526: only no split if there is no preceding frames on same page
+ else if (!isFirstVisibleFrameInBody(this))
+ bLoneAsCharAnchoredObj = false;
+ else
+ nNew = 0;
+ }
+ else if (nNew)
+ {
+ if (IsFollow())
+ {
+ // tdf#160549: do not split the frame at the very beginning again, if its master was empty
+ auto precede = static_cast<SwTextFrame*>(GetPrecede());
+ assert(precede);
+ auto precedeText = precede->DynCastTextFrame();
+ assert(precedeText);
+ if (isReallyEmptyMaster(precedeText))
+ nNew = 0;
+ }
+ else if (!bEmptyWithSplitFly)
+ {
+ // Do not split immediately in the beginning of page (unless there is an at-para or
+ // at-char or at-page fly, which pushes the rest down)
+ if (isFirstVisibleFrameInBody(this) && !hasFly(this) && !hasAtPageFly(pBodyFrame))
+ nNew = 0;
+ }
}
if ( nNew )
@@ -1136,8 +1212,6 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
SplitFrame( nEnd );
}
- const SwFrame *pBodyFrame = FindBodyFrame();
-
const tools::Long nBodyHeight = pBodyFrame ? ( IsVertical() ?
pBodyFrame->getFrameArea().Width() :
pBodyFrame->getFrameArea().Height() ) : 0;
@@ -1239,9 +1313,10 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
// content or contains no content, but has a numbering.
// i#84870 - No split, if text frame only contains one
// as-character anchored object.
- if ( !bOnlyContainsAsCharAnchoredObj &&
- (nStrLen > TextFrameIndex(0) ||
- bHasVisibleNumRule )
+ if (!bLoneAsCharAnchoredObj
+ && (bHasVisibleNumRule
+ || (nStrLen > TextFrameIndex(0)
+ && (nEnd != rLine.GetStart() || rInf.GetRest())))
)
{
SplitFrame( nEnd );
@@ -1265,7 +1340,7 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
SwTwips nChg = rLine.CalcBottomLine() - nDocPrtTop - nOldHeight;
//#i84870# - no shrink of text frame, if it only contains one as-character anchored object.
- if ( nChg < 0 && !bDelta && bOnlyContainsAsCharAnchoredObj )
+ if (nChg < 0 && !bDelta && bLoneAsCharAnchoredObj)
{
nChg = 0;
}
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index 72f1c809e2..52157df0ca 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -2599,11 +2599,17 @@ void SwUndoTableCpyTable::AddBoxBefore( const SwTableBox& rBox, bool bDelContent
if( bDelContent )
{
SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
- pDoc->GetNodes().MakeTextNode( aInsIdx.GetNode(), pDoc->GetDfltTextFormatColl() );
+ SwTextNode *const pNewNode(pDoc->GetNodes().MakeTextNode(aInsIdx.GetNode(), pDoc->GetDfltTextFormatColl()));
SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
if( !pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
+ {
+ { // move cursors to new node which precedes aPam
+ SwPosition const pos(*pNewNode, 0);
+ ::PaMCorrAbs(aPam, pos);
+ }
pEntry->pUndo = std::make_unique<SwUndoDelete>(aPam, SwDeleteFlags::Default, true);
+ }
}
pEntry->pBoxNumAttr = std::make_unique<SfxItemSetFixed<
@@ -2627,6 +2633,13 @@ void SwUndoTableCpyTable::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex
SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
DEBUG_REDLINE( pDoc )
+ { // move cursors to first node which was inserted
+ SwPaM pam(SwNodeIndex(*rBox.GetSttNd(), 1));
+ assert(pam.GetPoint()->GetNode().IsTextNode());
+ pam.SetMark();
+ pam.Move(fnMoveForward, GoInContent);
+ ::PaMCorrAbs(pam, *pam.GetPoint());
+ }
if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
{
SwPosition aTmpPos( rIdx );
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index 7880a749b9..62c4c76ac3 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -1713,18 +1713,7 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any&
}
else
{
- const size_t nCount = pDoc->GetFlyCount(FLYCNTTYPE_FRM);
-
- SwFrameFormat* pChain = nullptr;
- for( size_t i = 0; i < nCount; ++i )
- {
- SwFrameFormat* pFormat2 = pDoc->GetFlyNum(i, FLYCNTTYPE_FRM);
- if(sChainName == pFormat2->GetName() )
- {
- pChain = pFormat2;
- break;
- }
- }
+ SwFrameFormat* pChain = pDoc->GetFlyFrameFormatByName(sChainName);
if(pChain)
{
SwFrameFormat* pSource = bNextFrame ? pFormat : pChain;
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index 49562c1d02..df02c4773a 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -752,13 +752,19 @@ void SwXTextCursor::DeleteAndInsert(std::u16string_view aText,
}
if(nTextLen)
{
+ // Store node and content indexes prior to insertion: to select the inserted text,
+ // we need to account for possible surrogate pairs, combining characters, etc.; it
+ // is easier to just restore the correct position from the indexes.
+ const auto start = pCurrent->Start();
+ const auto nodeIndex = start->GetNodeIndex();
+ const auto contentIndex = start->GetContentIndex();
const bool bSuccess(
SwUnoCursorHelper::DocInsertStringSplitCR(
- rDoc, *pCurrent, aText, bool(eMode & ::sw::DeleteAndInsertMode::ForceExpandHints)));
+ rDoc, SwPaM(*start, pCurrent), aText, bool(eMode & ::sw::DeleteAndInsertMode::ForceExpandHints)));
OSL_ENSURE( bSuccess, "Doc->Insert(Str) failed." );
- SwUnoCursorHelper::SelectPam(*pUnoCursor, true);
- pCurrent->Left(aText.size());
+ pCurrent->SetMark();
+ pCurrent->GetPoint()->Assign(nodeIndex, contentIndex);
}
pCurrent = pCurrent->GetNext();
} while (pCurrent != pUnoCursor);
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
index 494cec7468..709d79ef4d 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -150,8 +150,11 @@ namespace
bool const hasOther = isExpanded && rStartPos != rEndPos;
bool const bStartPosInNode = rStartPos.GetNode() == rOwnNode;
bool const bEndPosInNode = rEndPos.GetNode() == rOwnNode;
+ // tdf#160700: Crossrefbookmarks only need separate start and end, when the start
+ // isn't in the end position (so in empty nodes, no need to handle them specially)
sw::mark::CrossRefBookmark* const pCrossRefMark
= !isExpanded && bStartPosInNode
+ && rStartPos.GetContentIndex() < rStartPos.GetContentNode()->Len()
? dynamic_cast<sw::mark::CrossRefBookmark*>(pBkmk)
: nullptr;