diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 05:03:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 05:09:28 +0000 |
commit | 97ac77f067910fa5e8206d75160fa63546a9358d (patch) | |
tree | e6fa64b43e8150ef65578afa4f1f40f3e19f7fa3 /sw/source/core | |
parent | Releasing progress-linux version 4:24.2.2-3~progress7.99u1. (diff) | |
download | libreoffice-97ac77f067910fa5e8206d75160fa63546a9358d.tar.xz libreoffice-97ac77f067910fa5e8206d75160fa63546a9358d.zip |
Merging upstream version 4:24.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core')
-rw-r--r-- | sw/source/core/access/AccessibilityCheck.cxx | 5 | ||||
-rw-r--r-- | sw/source/core/doc/docfly.cxx | 19 | ||||
-rw-r--r-- | sw/source/core/edit/eddel.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/fields/expfld.cxx | 2 | ||||
-rw-r--r-- | sw/source/core/layout/layact.cxx | 12 | ||||
-rw-r--r-- | sw/source/core/layout/paintfrm.cxx | 3 | ||||
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 15 | ||||
-rw-r--r-- | sw/source/core/text/frmform.cxx | 101 | ||||
-rw-r--r-- | sw/source/core/undo/untbl.cxx | 15 | ||||
-rw-r--r-- | sw/source/core/unocore/unoframe.cxx | 13 | ||||
-rw-r--r-- | sw/source/core/unocore/unoobj.cxx | 12 | ||||
-rw-r--r-- | sw/source/core/unocore/unoportenum.cxx | 3 |
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; |