Revert "tdf#43100 tdf#104683 tdf#120715 sw: cursor on spaces over margin"
This reverts commit 7ef9c3ef30023cc40068e1f735aa4bec4811288b (plus relevant part
of c08d71a0e0015ec7857335b68a354df04fa04a0c "Fix typos" follow-up). It started
to cause <https://ci.libreoffice.org/job/lo_ubsan/2441/> to fail with
> /sw/source/core/text/itrcrsr.cxx:1659:50: runtime error: downcast of address 0x60700059b250 which does not point to an object of type 'SwTextPortion'
> 0x60700059b250: note: object is of type 'SwHolePortion'
> 00 00 00 00 90 23 40 a7 6f 7f 00 00 e1 03 00 00 00 00 00 00 0d 01 00 00 00 00 00 00 00 00 00 00
> ^~~~~~~~~~~~~~~~~~~~~~~
> vptr for 'SwHolePortion'
> #0 0x7f6f9f1777f0 in SwTextCursor::GetModelPositionForViewPoint(SwPosition*, Point const&, bool, SwCursorMoveState*) const /sw/source/core/text/itrcrsr.cxx:1659:50
> #1 0x7f6f9efc2b39 in SwTextFrame::UnitDown_(SwPaM*, long, bool) const /sw/source/core/text/frmcrsr.cxx:1200:49
> #2 0x7f6f9efc5b50 in SwTextFrame::UnitDown(SwPaM*, long, bool) const /sw/source/core/text/frmcrsr.cxx:1298:31
> #3 0x7f6f9be4bac8 in SwCursor::UpDown(bool, unsigned short, Point const*, long, SwRootFrame&) /sw/source/core/crsr/swcrsr.cxx:2062:31
> #4 0x7f6f9bf0692b in SwShellCursor::UpDown(bool, unsigned short) /sw/source/core/crsr/viscrs.cxx:1025:22
> #5 0x7f6f9bb840c0 in SwCursorShell::UpDown(bool, unsigned short) /sw/source/core/crsr/crsrsh.cxx:511:29
> #6 0x7f6fa37f131d in SwCursorShell::Down(unsigned short) /sw/inc/crsrsh.hxx:359:50
> #7 0x7f6fa37dcfc9 in SwWrtShell::Down(bool, unsigned short, bool) /sw/source/uibase/wrtsh/move.cxx:171:27
> #8 0x7f6fb6aa1325 in testTdf43100_CursorMoveToSpacesOverMargin::TestBody() /sw/qa/core/text/text.cxx:532:20
during CppunitTest_sw_core_text
CPPUNIT_TEST_NAME=testTdf43100_CursorMoveToSpacesOverMargin::TestBody
Change-Id: I37947825ec9db826446ed28fa87a23ee60749b82
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136549
Reviewed-by: László Németh <nemeth@numbertext.org>
Tested-by: Jenkins
diff --git a/sw/qa/core/text/data/tdf43100_tdf120715_cursorOnSpacesOverMargin.docx b/sw/qa/core/text/data/tdf43100_tdf120715_cursorOnSpacesOverMargin.docx
deleted file mode 100644
index 474d805..0000000
--- a/sw/qa/core/text/data/tdf43100_tdf120715_cursorOnSpacesOverMargin.docx
+++ /dev/null
Binary files differ
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 99d80f6..2db4d6d 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -470,74 +470,6 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testRedlineDelete)
pDoc->getIDocumentRedlineAccess().GetRedlineTable().size());
}
CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testTdf120715_CursorMoveWhenTypingSpaceAtCenteredLineEnd)
{
SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf43100_tdf120715_cursorOnSpacesOverMargin.docx");
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
// Make a paint to force the call of AddExtraBlankWidth, that calculate width for holePortions.
pDoc->GetDocShell()->GetPreviewBitmap();
// Move the cursor to the last character of the document.
pWrtShell->EndOfSection();
//Press space and check if the cursor move right with the additional space.
sal_Int32 nOldCursorPos = pWrtShell->GetCharRect().Left();
pWrtShell->Insert(" ");
sal_Int32 nNewCursorPos = pWrtShell->GetCharRect().Left();
CPPUNIT_ASSERT_GREATER(nOldCursorPos, nNewCursorPos);
}
CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testTdf43100_CursorMoveToSpacesOverMargin)
{
// Test the cursor movement over the right margin in several different paragraphs.
// These differences are based on its paragraphs
// - alignment (left, center, right, justified),
// - line count (1 line, 2 lines, blank line containing only spaces)
SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf43100_tdf120715_cursorOnSpacesOverMargin.docx");
SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
// Make a paint to force the call of AddExtraBlankWidth, that calculate width for holePortions.
pDoc->GetDocShell()->GetPreviewBitmap();
// Move the cursor to the 2. line.
pWrtShell->Down(/*bSelect=*/false, 1, /*bBasicCall=*/false);
// Move the cursor to the right margin.
pWrtShell->RightMargin(false, false);
sal_Int32 nMarginPos = pWrtShell->GetCharRect().Left();
sal_Int32 nLastCursorPos = nMarginPos;
// Move the cursor right 5 times, every step should increase the cursor x position.
// Before this fix, the cursor stopped at the margin.
for (int i = 0; i < 5; i++)
{
pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false);
sal_Int32 nNewCursorPos = pWrtShell->GetCharRect().Left();
CPPUNIT_ASSERT_GREATER(nLastCursorPos, nNewCursorPos);
nLastCursorPos = nNewCursorPos;
}
// Move down the cursor several lines, and check if it will keep nearly its horizontal position.
// Some of the lines are not reach beyond the margin, there the cursor won't be able to keep its
// original position.
bool aLineReachOverMargin[] = { false, true, true, false, false, true, true, false, true,
true, true, true, false, true, true, false, false };
// Cursor position can be a bit inaccurate, because it can only be positioned on characters,
// that is based on the actual line layout, therefore the actual cursor position
// is checked against a more distinct position instead of the nMarginPos.
sal_Int32 nAvgLeft = (nMarginPos + nLastCursorPos) / 2;
for (int i = 2; i < 17; i++)
{
pWrtShell->Down(/*bSelect=*/false, 1, /*bBasicCall=*/false);
sal_Int32 nNewCursorPos = pWrtShell->GetCharRect().Left();
if (aLineReachOverMargin[i])
CPPUNIT_ASSERT_GREATER(nAvgLeft, nNewCursorPos);
else
CPPUNIT_ASSERT_LESS(nAvgLeft, nNewCursorPos);
}
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index 34681c1..d469083 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -100,9 +100,6 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
TextFrameIndex nCharsCnt = nMaxLen - nSpaceCnt;
if ( nSpaceCnt && nCharsCnt < rPor.GetLen() )
{
if (nSpaceCnt)
rInf.GetTextSize( &rSI, rInf.GetIdx() + nCharsCnt, nSpaceCnt,
nMaxComp, m_nExtraBlankWidth, nMaxSizeDiff );
nMaxLen = nCharsCnt;
if ( !nMaxLen )
return true;
@@ -614,13 +611,6 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
else
m_nBreakWidth = 0;
if (m_nBreakStart > rInf.GetIdx() + nPorLen + m_nFieldDiff)
{
rInf.GetTextSize(&rSI, rInf.GetIdx() + nPorLen,
m_nBreakStart - rInf.GetIdx() - nPorLen - m_nFieldDiff, nMaxComp,
m_nExtraBlankWidth, nMaxSizeDiff, rInf.GetCachedVclData().get());
}
if( m_pHanging )
{
m_nBreakPos = m_nCutPos;
diff --git a/sw/source/core/text/guess.hxx b/sw/source/core/text/guess.hxx
index f83c7e2..696a09f 100644
--- a/sw/source/core/text/guess.hxx
+++ b/sw/source/core/text/guess.hxx
@@ -38,10 +38,9 @@ class SwTextGuess
TextFrameIndex m_nFieldDiff; // absolute positions can be wrong if we
// a field in the text has been expanded
sal_uInt16 m_nBreakWidth; // width of the broken portion
sal_uInt16 m_nExtraBlankWidth; // width of spaces after the break
public:
SwTextGuess(): m_nCutPos(0), m_nBreakStart(0),
m_nBreakPos(0), m_nFieldDiff(0), m_nBreakWidth(0), m_nExtraBlankWidth(0)
m_nBreakPos(0), m_nFieldDiff(0), m_nBreakWidth(0)
{ }
// true, if current portion still fits to current line
@@ -52,7 +51,6 @@ public:
SwHangingPortion* GetHangingPortion() const { return m_pHanging.get(); }
SwHangingPortion* ReleaseHangingPortion() { return m_pHanging.release(); }
sal_uInt16 BreakWidth() const { return m_nBreakWidth; }
sal_uInt16 ExtraBlankWidth() const { return m_nExtraBlankWidth; }
TextFrameIndex CutPos() const { return m_nCutPos; }
TextFrameIndex BreakStart() const { return m_nBreakStart; }
TextFrameIndex BreakPos() const {return m_nBreakPos; }
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 8867929..546d91b 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -401,26 +401,6 @@ void SwTextCursor::CtorInitTextCursor( SwTextFrame *pNewFrame, SwTextSizeInfo *p
// GetInfo().SetOut( GetInfo().GetWin() );
}
// tdf#120715 tdf#43100: Make width for some HolePortions, so cursor will be able to move into it.
// It should not change the layout, so this should be called after the layout is calculated.
void SwTextCursor::AddExtraBlankWidth()
{
SwLinePortion* pPos = m_pCurr->GetNextPortion();
SwLinePortion* pNextPos;
while (pPos)
{
pNextPos = pPos->GetNextPortion();
// Do it only if it is the last portion that able to handle the cursor,
// else the next portion would misscalculate the cursor position
if (pPos->ExtraBlankWidth() && (!pNextPos || pNextPos->IsMarginPortion()))
{
pPos->Width(pPos->Width() + pPos->ExtraBlankWidth());
pPos->ExtraBlankWidth(0);
}
pPos = pNextPos;
}
}
// 1170: Ancient bug: Shift-End forgets the last character ...
void SwTextCursor::GetEndCharRect(SwRect* pOrig, const TextFrameIndex nOfst,
SwCursorMoveState* pCMS, const tools::Long nMax )
@@ -1233,6 +1213,10 @@ void SwTextCursor::GetCharRect( SwRect* pOrig, TextFrameIndex const nOfst,
GetCharRect_( pOrig, nFindOfst, pCMS );
// This actually would have to be "-1 LogicToPixel", but that seems too
// expensive, so it's a value (-12), that should hopefully be OK.
const SwTwips nTmpRight = Right() - 12;
pOrig->Pos().AdjustX(aCharPos.X() );
pOrig->Pos().AdjustY(aCharPos.Y() );
@@ -1244,6 +1228,13 @@ void SwTextCursor::GetCharRect( SwRect* pOrig, TextFrameIndex const nOfst,
pCMS->m_p2Lines->aPortion.Pos().AdjustY(aCharPos.Y() );
}
const IDocumentSettingAccess& rIDSA = GetTextFrame()->GetDoc().getIDocumentSettingAccess();
const bool bTabOverMargin = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN)
|| rIDSA.get(DocumentSettingId::TAB_OVER_SPACING);
// Make sure the cursor respects the right margin, unless in compat mode, where the tab size has priority over the margin size.
if( pOrig->Left() > nTmpRight && !bTabOverMargin)
pOrig->Pos().setX( nTmpRight );
if( nMax )
{
if( pOrig->Top() + pOrig->Height() > nMax )
@@ -1264,6 +1255,16 @@ void SwTextCursor::GetCharRect( SwRect* pOrig, TextFrameIndex const nOfst,
pCMS->m_aRealHeight.setY( nMax - nTmp );
}
}
tools::Long nOut = pOrig->Right() - GetTextFrame()->getFrameArea().Right();
if( nOut > 0 )
{
if( GetTextFrame()->getFrameArea().Width() < GetTextFrame()->getFramePrintArea().Left()
+ GetTextFrame()->getFramePrintArea().Width() )
nOut += GetTextFrame()->getFrameArea().Width() - GetTextFrame()->getFramePrintArea().Left()
- GetTextFrame()->getFramePrintArea().Width();
if( nOut > 0 )
pOrig->Pos().AdjustX( -(nOut + 10) );
}
}
/**
@@ -1319,6 +1320,9 @@ TextFrameIndex SwTextCursor::GetModelPositionForViewPoint( SwPosition *pPos, con
if( bLeftOver )
x = nLeftMargin;
const bool bRightOver = x > nRightMargin;
if( bRightOver )
x = nRightMargin;
const bool bRightAllowed = pCMS && ( pCMS->m_eState == CursorMoveState::NONE );
// Until here everything in document coordinates.
@@ -1643,7 +1647,7 @@ TextFrameIndex SwTextCursor::GetModelPositionForViewPoint( SwPosition *pPos, con
return GetModelPositionForViewPoint( pPos, Point( GetLineStart() + nX, rPoint.Y() ),
bChgNode, pCMS );
}
if( pPor->InTextGrp() || pPor->IsHolePortion() )
if( pPor->InTextGrp() )
{
sal_uInt8 nOldProp;
if( GetPropFont() )
diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx
index a66d358..3935630 100644
--- a/sw/source/core/text/itrpaint.cxx
+++ b/sw/source/core/text/itrpaint.cxx
@@ -127,7 +127,6 @@ void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
// maybe catch-up adjustment
GetAdjusted();
AddExtraBlankWidth();
GetInfo().SetpSpaceAdd( m_pCurr->GetpLLSpaceAdd() );
GetInfo().ResetSpaceIdx();
GetInfo().SetKanaComp( m_pCurr->GetpKanaComp() );
diff --git a/sw/source/core/text/itrtxt.hxx b/sw/source/core/text/itrtxt.hxx
index 0b48e3b..f36932d 100644
--- a/sw/source/core/text/itrtxt.hxx
+++ b/sw/source/core/text/itrtxt.hxx
@@ -270,7 +270,6 @@ class SwTextCursor : public SwTextAdjuster
protected:
void CtorInitTextCursor( SwTextFrame *pFrame, SwTextSizeInfo *pInf );
explicit SwTextCursor(SwTextNode const * pTextNode) : SwTextAdjuster(pTextNode) { }
void AddExtraBlankWidth();
public:
SwTextCursor( SwTextFrame *pTextFrame, SwTextSizeInfo *pTextSizeInf )
: SwTextAdjuster(pTextFrame->GetTextNodeFirst())
diff --git a/sw/source/core/text/porlin.hxx b/sw/source/core/text/porlin.hxx
index 5ce25a3..3cd1d9f 100644
--- a/sw/source/core/text/porlin.hxx
+++ b/sw/source/core/text/porlin.hxx
@@ -63,7 +63,6 @@ private:
PortionType mnWhichPor; // Who's who?
bool m_bJoinBorderWithPrev;
bool m_bJoinBorderWithNext;
SwTwips m_nExtraBlankWidth = 0; // width of spaces after the break
void Truncate_();
@@ -84,8 +83,6 @@ public:
SwTwips PrtWidth() const { return Width(); }
void AddPrtWidth( const SwTwips nNew ) { Width( Width() + nNew ); }
void SubPrtWidth( const SwTwips nNew ) { Width( Width() - nNew ); }
SwTwips ExtraBlankWidth() const { return m_nExtraBlankWidth; }
void ExtraBlankWidth(const SwTwips nNew) { m_nExtraBlankWidth = nNew; }
SwTwips GetHangingBaseline() const { return mnHangingBaseline; }
void SetHangingBaseline( const SwTwips nNewBaseline ) { mnHangingBaseline = nNewBaseline; }
@@ -194,7 +191,6 @@ inline SwLinePortion &SwLinePortion::operator=(const SwLinePortion &rPortion)
mnWhichPor = rPortion.mnWhichPor;
m_bJoinBorderWithPrev = rPortion.m_bJoinBorderWithPrev;
m_bJoinBorderWithNext = rPortion.m_bJoinBorderWithNext;
m_nExtraBlankWidth = rPortion.m_nExtraBlankWidth;
return *this;
}
@@ -206,8 +202,7 @@ inline SwLinePortion::SwLinePortion(const SwLinePortion &rPortion) :
mnHangingBaseline( rPortion.mnHangingBaseline ),
mnWhichPor( rPortion.mnWhichPor ),
m_bJoinBorderWithPrev( rPortion.m_bJoinBorderWithPrev ),
m_bJoinBorderWithNext( rPortion.m_bJoinBorderWithNext ),
m_nExtraBlankWidth(rPortion.m_nExtraBlankWidth)
m_bJoinBorderWithNext( rPortion.m_bJoinBorderWithNext )
{
}
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index c0f6649..a5ae0ea 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -321,7 +321,6 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
if ( !bFull )
{
Width( aGuess.BreakWidth() );
ExtraBlankWidth(aGuess.ExtraBlankWidth());
// Caution!
if( !InExpGrp() || InFieldGrp() )
SetLen( rInf.GetLen() );
@@ -410,8 +409,6 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
{
SwHolePortion *pNew = new SwHolePortion( *this );
pNew->SetLen( nRealStart - aGuess.BreakPos() );
pNew->Width(0);
pNew->ExtraBlankWidth( aGuess.ExtraBlankWidth() );
Insert( pNew );
}
}
@@ -752,29 +749,12 @@ SwHolePortion::SwHolePortion( const SwTextPortion &rPor )
{
SetLen( TextFrameIndex(1) );
Height( rPor.Height() );
Width(0);
SetAscent( rPor.GetAscent() );
SetWhichPor( PortionType::Hole );
}
SwLinePortion *SwHolePortion::Compress() { return this; }
// The GetTextSize() assumes that the own length is correct
SwPosSize SwHolePortion::GetTextSize(const SwTextSizeInfo& rInf) const
{
SwPosSize aSize = rInf.GetTextSize();
if (!GetJoinBorderWithPrev())
aSize.Width(aSize.Width() + rInf.GetFont()->GetLeftBorderSpace());
if (!GetJoinBorderWithNext())
aSize.Width(aSize.Width() + rInf.GetFont()->GetRightBorderSpace());
aSize.Height(aSize.Height() +
rInf.GetFont()->GetTopBorderSpace() +
rInf.GetFont()->GetBottomBorderSpace());
return aSize;
}
void SwHolePortion::Paint( const SwTextPaintInfo &rInf ) const
{
if( !rInf.GetOut() )
diff --git a/sw/source/core/text/portxt.hxx b/sw/source/core/text/portxt.hxx
index a30f6f0..77ec0a9 100644
--- a/sw/source/core/text/portxt.hxx
+++ b/sw/source/core/text/portxt.hxx
@@ -69,7 +69,6 @@ public:
void SetBlankWidth( const sal_uInt16 nNew ) { m_nBlankWidth = nNew; }
virtual SwLinePortion *Compress() override;
virtual bool Format( SwTextFormatInfo &rInf ) override;
virtual SwPosSize GetTextSize(const SwTextSizeInfo& rInfo) const override;
virtual void Paint( const SwTextPaintInfo &rInf ) const override;
// Accessibility: pass information about this portion to the PortionHandler