summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorJustin Luth <jluth@mail.com>2023-12-25 20:23:52 -0500
committerMiklos Vajna <vmiklos@collabora.com>2024-01-03 08:45:34 +0100
commite73dfbf860b977f3b862fb75a87a7ad726d9a4c7 (patch)
tree57fd897b02cf5f57e0ec0229ffefb1ad7116b87f /sw
parenta01a642ebbdb8c16f1b54b4634c277b9f665192f (diff)
tdf#111969 sw: acknowledge field start/end for context menu
This fixes the right-click menu building missing out on the edit/update field option about half-a-character too soon at the end. It also fixes itrcrsr adding field actions to the menu half-a-char too soon in the edge case of a 1-len portion. This edge case is not limited to fields - it fixes it for redlines (and hyperlinks if other bugs are fixed). make CppunitTest_sw_uiwriter9 CPPUNIT_TEST_NAME=testTdf111969 Change-Id: I469ec75d18d4dce0bb62ebb63b661b60e35f9e1b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161295 Tested-by: Jenkins Reviewed-by: Justin Luth <jluth@mail.com>
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/crsrsh.hxx10
-rw-r--r--sw/inc/crstate.hxx4
-rw-r--r--sw/qa/extras/uiwriter/data/tdf111969_field.fodt10
-rw-r--r--sw/qa/extras/uiwriter/data/tdf111969_fieldB.fodt10
-rw-r--r--sw/qa/extras/uiwriter/uiwriter9.cxx86
-rw-r--r--sw/source/core/crsr/crsrsh.cxx3
-rw-r--r--sw/source/uibase/docvw/edtwin.cxx4
7 files changed, 122 insertions, 5 deletions
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 20636648c794..db0667002ee2 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -401,7 +401,15 @@ public:
// return values:
// CRSR_POSCHG: when cursor was corrected from SPoint by the layout
// CRSR_POSOLD: when the cursor was not changed
- int SetCursor( const Point &rPt, bool bOnlyText = false, bool bBlock = true );
+ /**
+ * @param bFieldInfo
+ * false: Over the last half of the character, place cursor behind it. This is used when
+ * the cursor is actually being moved by the user to the closest valid point.
+ * true: Place the cursor at the start of the character/field. This is used when setting
+ * the cursor is done in order to get at the properties under the mouse pointer.
+ */
+ int SetCursor(const Point& rPt, bool bOnlyText = false, bool bBlock = true,
+ bool bFieldInfo = false);
/*
* Notification that the visible area was changed. m_aVisArea is reset, then
diff --git a/sw/inc/crstate.hxx b/sw/inc/crstate.hxx
index acf13bfe45d7..018106514714 100644
--- a/sw/inc/crstate.hxx
+++ b/sw/inc/crstate.hxx
@@ -139,7 +139,7 @@ struct SwCursorMoveState
sal_uInt8 m_nCursorBidiLevel;
bool m_bStop;
bool m_bRealHeight; ///< should the real height be calculated?
- bool m_bFieldInfo; ///< should be fields recognized?
+ bool m_bFieldInfo; ///< should fields be recognized? (get position of field start)
bool m_bPosCorr; ///< Point had to be corrected
bool m_bFootnoteNoInfo; ///< recognized footnote numbering
bool m_bExactOnly; /**< let GetModelPositionForViewPoint look for exact matches only,
@@ -151,7 +151,7 @@ struct SwCursorMoveState
bool m_bNoScroll; ///< No scrolling of undersized textframes
bool m_bPosMatchesBounds; /**< GetModelPositionForViewPoint should not return the next
position if screen position is inside second
- have of bound rect */
+ half of bound rect */
bool m_bContentCheck; // #i43742# Cursor position over content?
diff --git a/sw/qa/extras/uiwriter/data/tdf111969_field.fodt b/sw/qa/extras/uiwriter/data/tdf111969_field.fodt
new file mode 100644
index 000000000000..4048fa03c42b
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/tdf111969_field.fodt
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+ <office:text>
+ <text:p>–<text:time text:time-value="1899-12-30T12:34:56" text:fixed="true"/>–</text:p>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/uiwriter/data/tdf111969_fieldB.fodt b/sw/qa/extras/uiwriter/data/tdf111969_fieldB.fodt
new file mode 100644
index 000000000000..18de3f586a94
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/tdf111969_fieldB.fodt
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:body>
+ <office:text>
+ <text:p>––<text:time text:time-value="1899-12-30T12:34:56" text:fixed="true"/>––</text:p>
+ </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/uiwriter/uiwriter9.cxx b/sw/qa/extras/uiwriter/uiwriter9.cxx
index c12be545512d..8febc2f2145e 100644
--- a/sw/qa/extras/uiwriter/uiwriter9.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter9.cxx
@@ -68,6 +68,92 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf158785)
CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
}
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf111969)
+{
+ // given a document with a field surrounded by N-dashes (–date–)
+ createSwDoc("tdf111969_field.fodt");
+ SwDoc& rDoc = *getSwDoc();
+ SwWrtShell* pWrtShell = rDoc.GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+
+ // go to the end of the field
+ pWrtShell->SttEndDoc(/*bStart=*/false);
+ pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ // get last point that will be part of the field (current position 1pt wide).
+ Point aLogicL(pWrtShell->GetCharRect().Center());
+ Point aLogicR(aLogicL);
+
+ // sanity check - we really are at the right edge of the field
+ aLogicR.AdjustX(1);
+ SwContentAtPos aContentAtPos(IsAttrAtPos::Field);
+ pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
+ CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
+ aLogicL.AdjustX(-1);
+ aContentAtPos = IsAttrAtPos::Field;
+ pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
+ CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::Field, aContentAtPos.eContentAtPos);
+
+ // the test: simulate a right-click of a mouse which sets the cursor and then acts on that pos.
+ pWrtShell->SwCursorShell::SetCursor(aLogicL, false, /*Block=*/false, /*FieldInfo=*/true);
+ CPPUNIT_ASSERT(pWrtShell->GetCurField(true));
+
+ /*
+ * An edge case at the start of a field - don't start the field menu on the first N-dash
+ */
+ // go to the start of the field
+ pWrtShell->SttEndDoc(/*bStart=*/true);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ // get first point that will be part of the field (current position 1pt wide).
+ aLogicL = pWrtShell->GetCharRect().Center();
+ aLogicR = aLogicL;
+
+ // sanity check - we really are at the left edge of the field
+ aLogicR.AdjustX(1);
+ aContentAtPos = IsAttrAtPos::Field;
+ pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
+ CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::Field, aContentAtPos.eContentAtPos);
+ aLogicL.AdjustX(-1);
+ aContentAtPos = IsAttrAtPos::Field;
+ pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
+ CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
+
+ // the test: simulate a right-click of a mouse (at the end-edge of the N-dash)
+ // which sets the cursor and then acts on that pos.
+ pWrtShell->SwCursorShell::SetCursor(aLogicL, false, /*Block=*/false, /*FieldInfo=*/true);
+ CPPUNIT_ASSERT(!pWrtShell->GetCurField(true));
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest9, testTdf111969B)
+{
+ // given a document with a field surrounded by two N-dashes (––date––)
+ createSwDoc("tdf111969_fieldB.fodt");
+ SwDoc& rDoc = *getSwDoc();
+ SwWrtShell* pWrtShell = rDoc.GetDocShell()->GetWrtShell();
+ CPPUNIT_ASSERT(pWrtShell);
+
+ // go to the start of the field
+ pWrtShell->SttEndDoc(/*bStart=*/true);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 2, /*bBasicCall=*/false);
+ // get first point that will be part of the field (current position 1pt wide).
+ Point aLogicL(pWrtShell->GetCharRect().Center());
+ Point aLogicR(aLogicL);
+
+ // sanity check - we really are at the left edge of the field
+ aLogicR.AdjustX(1);
+ SwContentAtPos aContentAtPos(IsAttrAtPos::Field);
+ pWrtShell->GetContentAtPos(aLogicR, aContentAtPos);
+ CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::Field, aContentAtPos.eContentAtPos);
+ aLogicL.AdjustX(-1);
+ aContentAtPos = IsAttrAtPos::Field;
+ pWrtShell->GetContentAtPos(aLogicL, aContentAtPos);
+ CPPUNIT_ASSERT_EQUAL(IsAttrAtPos::NONE, aContentAtPos.eContentAtPos);
+
+ // the test: simulate a right-click of a mouse (at the end-edge of the second N-dash)
+ // which sets the cursor and then acts on that pos.
+ pWrtShell->SwCursorShell::SetCursor(aLogicL, false, /*Block=*/false, /*FieldInfo=*/true);
+ //CPPUNIT_ASSERT(!pWrtShell->GetCurField(true));
+}
+
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 449b074194bc..ed9f47dc81c5 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -1045,7 +1045,7 @@ bool SwCursorShell::IsInHeaderFooter( bool* pbInHeader ) const
return nullptr != pFrame;
}
-int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
+int SwCursorShell::SetCursor(const Point& rLPt, bool bOnlyText, bool bBlock, bool bFieldInfo)
{
CurrShell aCurr( this );
@@ -1056,6 +1056,7 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock )
SwCursorMoveState aTmpState( IsTableMode() ? CursorMoveState::TableSel :
bOnlyText ? CursorMoveState::SetOnlyText : CursorMoveState::NONE );
aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable();
+ aTmpState.m_bFieldInfo = bFieldInfo; // always set cursor at field-start if point is over field
SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode());
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 4d9750a98602..e89614319903 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -6160,7 +6160,9 @@ void SwEditWin::SelectMenuPosition(SwWrtShell& rSh, const Point& rMousePos )
// create only temporary move context because otherwise
// the query against the content form doesn't work!!!
SwMvContext aMvContext( &rSh );
- rSh.CallSetCursor(&aDocPos, false);
+ if (rSh.HasSelection())
+ rSh.ResetSelect(&aDocPos, false);
+ rSh.SwCursorShell::SetCursor(aDocPos, false, /*Block=*/false, /*FieldInfo=*/true);
}
if( !bOverURLGrf )
{