sw_redlinehide_4b: surprising discoveries

It turns out that there was a small problem in the interpretation of
sw_JoinText(), or rather, its caller,
SwRangeRedline::DelCopyOfSection(), which, since about OOo 3.2 and
i#100466, passes in bForceJoinNext, so the result is that the first node
wins always, not just for RES_BREAK/RES_PAGEDESC items.

This means that pParaPropsNode and pFirstNode are the same thing really.

Another little problem is that the SwAttrIter was initing the font
wrongly: the relevant items are the items in the *current* node's item
set on top of the item set of the paragraph style, i.e. the *first*
node's style.

Simple reproducer: ooo79457-1.odt

Change-Id: I06ef3c1695b8f3cdbded238864a60d5eb9ce4c44
This commit is contained in:
Michael Stahl
2018-12-18 17:55:29 +01:00
parent 8c708b6b1a
commit c20308f1b9
8 changed files with 35 additions and 19 deletions
+1
View File
@@ -437,6 +437,7 @@ public:
/// Returns the text portion we want to edit (for inline see underneath)
const OUString& GetText() const;
SwTextNode const* GetTextNodeForParaProps() const;
SwTextNode const* GetTextNodeForFirstText() const;
SwTextNode * GetTextNodeFirst()
{ return const_cast<SwTextNode*>(const_cast<SwTextFrame const*>(this)->GetTextNodeFirst()); };
SwTextNode const* GetTextNodeFirst() const;
-4
View File
@@ -1170,10 +1170,6 @@ void AppendObjs(const SwFrameFormats *const pTable, sal_uLong const nIndex,
{
AppendObjsOfNode(pTable, pNode->GetIndex(), pFrame, pPage, pDoc, &iterFirst, &iter);
}
else
{
assert(pMerged->pParaPropsNode == iter->pNode); // first iteration
}
pNode = iter->pNode;
iterFirst = iter;
}
+4 -5
View File
@@ -204,7 +204,7 @@ bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const bool bParaFo
{
assert(m_pMergedPara);
m_pTextNode = m_pMergedPara->pFirstNode;
InitFontAndAttrHandler(*m_pTextNode, m_pMergedPara->mergedText, nullptr);
InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *m_pTextNode, m_pMergedPara->mergedText, nullptr);
}
// reset font to its original state
@@ -338,7 +338,7 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
// items at all; it can only apply a previously effective item.
// So do this by recreating the font from scratch.
// Apply new para items:
InitFontAndAttrHandler(*newPos.first, m_pMergedPara->mergedText, nullptr);
InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *newPos.first, m_pMergedPara->mergedText, nullptr);
// reset to next
m_pTextNode = newPos.first;
m_nStartIndex = 0;
@@ -360,7 +360,7 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
m_pTextNode = newPos.first;
// sw_redlinehide: hope it's okay to use the current text node
// here; the AttrHandler shouldn't care about non-char items
InitFontAndAttrHandler(*m_pTextNode, m_pMergedPara->mergedText, nullptr);
InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *m_pTextNode, m_pMergedPara->mergedText, nullptr);
}
}
if (m_pMergedPara || m_pTextNode->GetpSwpHints())
@@ -1417,8 +1417,7 @@ SwTwips SwTextNode::GetWidthOfLeadingTabs() const
{
// Only consider master frames:
if (!pFrame->IsFollow() &&
// sw_redlinehide: paraPropsNode has the first text of the frame
(!pFrame->GetMergedPara() || pFrame->GetMergedPara()->pParaPropsNode == this))
pFrame->GetTextNodeForFirstText() == this)
{
SwRectFnSet aRectFnSet(pFrame);
SwRect aRect;
+2 -1
View File
@@ -65,7 +65,8 @@ private:
void SeekFwd(sal_Int32 nOldPos, sal_Int32 nNewPos);
void SetFnt( SwFont* pNew ) { m_pFont = pNew; }
void InitFontAndAttrHandler(SwTextNode const& rTextNode,
void InitFontAndAttrHandler(
SwTextNode const& rPropsNode, SwTextNode const& rTextNode,
OUString const& rText, bool const* pbVertLayout);
protected:
+10 -5
View File
@@ -218,13 +218,14 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
if (extents.empty()) // there was no text anywhere
{
assert(mergedText.isEmpty());
pParaPropsNode = &rTextNode; // if every node is empty, the first one wins
// pParaPropsNode = &rTextNode; // if every node is empty, the first one wins
}
else
{
assert(!mergedText.isEmpty());
pParaPropsNode = extents.begin()->pNode; // para props from first node that isn't empty
// pParaPropsNode = extents.begin()->pNode; // para props from first node that isn't empty
}
pParaPropsNode = &rTextNode; // well, actually...
// keep lists up to date with visible nodes
if (pParaPropsNode->IsInList() && !pParaPropsNode->GetNum(rFrame.getRootFrame()))
{
@@ -299,12 +300,14 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
} // namespace sw
void SwAttrIter::InitFontAndAttrHandler(SwTextNode const& rTextNode,
void SwAttrIter::InitFontAndAttrHandler(
SwTextNode const& rPropsNode,
SwTextNode const& rTextNode,
OUString const& rText,
bool const*const pbVertLayout)
{
// Build a font matching the default paragraph style:
SwFontAccess aFontAccess( &rTextNode.GetAnyFormatColl(), m_pViewShell );
SwFontAccess aFontAccess( &rPropsNode.GetAnyFormatColl(), m_pViewShell );
// It is possible that Init is called more than once, e.g., in a
// SwTextFrame::FormatOnceMore situation or (since sw_redlinehide)
// from SwAttrIter::Seek(); in the latter case SwTextSizeInfo::m_pFnt
@@ -395,7 +398,9 @@ void SwAttrIter::CtorInitAttrIter(SwTextNode & rTextNode,
if (m_pScriptInfo->GetInvalidityA() != TextFrameIndex(COMPLETE_STRING))
m_pScriptInfo->InitScriptInfo(rTextNode, m_pMergedPara, bRTL);
InitFontAndAttrHandler(rTextNode,
InitFontAndAttrHandler(
m_pMergedPara ? *m_pMergedPara->pParaPropsNode : rTextNode,
rTextNode,
m_pMergedPara ? m_pMergedPara->mergedText : rTextNode.GetText(),
& bVertLayout);
+1 -2
View File
@@ -249,8 +249,7 @@ bool SwTextNode::GetDropSize(int& rFontHeight, int& rDropHeight, int& rDropDesce
{
// Only (master-) text frames can have a drop cap.
if (!pLastFrame->IsFollow() &&
// sw_redlinehide: paraPropsNode has the first text of the frame
(!pLastFrame->GetMergedPara() || pLastFrame->GetMergedPara()->pParaPropsNode == this))
pLastFrame->GetTextNodeForFirstText() == this)
{
if( !pLastFrame->HasPara() )
+16
View File
@@ -1061,6 +1061,7 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
// pFirstNode is never updated
if (nErased && nErased == nFoundNode)
{ // all visible text from node was erased
#if 0
if (rMerged.pParaPropsNode == &rNode)
{
rMerged.pParaPropsNode->RemoveFromListRLHidden();
@@ -1069,6 +1070,7 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
: rMerged.extents.front().pNode;
rMerged.pParaPropsNode->AddToListRLHidden();
}
#endif
// NOPE must listen on all non-hidden nodes; particularly on pLastNode rMerged.listener.EndListening(&const_cast<SwTextNode&>(rNode));
}
rMerged.mergedText = text.makeStringAndClear();
@@ -1219,7 +1221,21 @@ SwTextNode const* SwTextFrame::GetTextNodeForParaProps() const
//nope assert(GetPara());
sw::MergedPara const*const pMerged(GetMergedPara());
if (pMerged)
{
assert(pMerged->pFirstNode == pMerged->pParaPropsNode); // surprising news!
return pMerged->pParaPropsNode;
}
else
return static_cast<SwTextNode const*>(SwFrame::GetDep());
}
SwTextNode const* SwTextFrame::GetTextNodeForFirstText() const
{
sw::MergedPara const*const pMerged(GetMergedPara());
if (pMerged)
return pMerged->extents.empty()
? pMerged->pFirstNode
: pMerged->extents.front().pNode;
else
return static_cast<SwTextNode const*>(SwFrame::GetDep());
}
+1 -2
View File
@@ -4291,8 +4291,7 @@ void SwTextNode::AddToList()
{
if (pFrame->getRootFrame()->IsHideRedlines())
{
sw::MergedPara const*const pMerged = pFrame->GetMergedPara();
if (!pMerged || this == pMerged->pParaPropsNode)
if (pFrame->GetTextNodeForParaProps() == this)
{
AddToListRLHidden();
}