summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-05-11 09:29:05 +0200
committerMiklos Vajna <vmiklos@collabora.com>2022-05-11 12:22:48 +0200
commit1e9416fac497a58be04011cfa0ffce9c74a9e397 (patch)
tree1cfacf7409e2e111d5f99fab864635bc6b600f19 /sw
parent35dec195a1f0a7a3aa8fab893698e512f5851d19 (diff)
sw content controls: introduce a word breaking dummy char at the end
- this way double-clicking on the last word of a content control or the first word after the content control selects the correct text range, similar to how the same at the start of content control already worked - this allows not touching the expand flag in the SwTextContentControl ctor, which was overwritten by the ODT import (when the content control was at the end of the paragraph) anyway - hide this dummy character when accessing the paragraph content via the UNO API or the text export - still need to audit a few more places in follow-up commits to maintain the invariant that content controls have the same dummy char at the attribute start and end -- somwhat similar to how SwTextInputField does it with CH_TXT_ATR_INPUTFIELDSTART/END Change-Id: I88763d6db84afedbb865b680f040994c4d6ab7d5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134151 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/core/unocore/unocore.cxx14
-rw-r--r--sw/qa/uibase/wrtsh/wrtsh.cxx10
-rw-r--r--sw/source/core/crsr/crstrvl.cxx4
-rw-r--r--sw/source/core/crsr/viscrs.cxx6
-rw-r--r--sw/source/core/txtnode/attrcontentcontrol.cxx4
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx1
-rw-r--r--sw/source/core/txtnode/thints.cxx21
-rw-r--r--sw/source/core/unocore/unocontentcontrol.cxx3
-rw-r--r--sw/source/filter/ascii/ascatr.cxx3
-rw-r--r--sw/source/uibase/wrtsh/wrtsh3.cxx4
10 files changed, 47 insertions, 23 deletions
diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index 405c279f315f..ee058645c951 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -373,7 +373,7 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testImageTooltip)
CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlTextPortionEnum)
{
// Given a document with a content control around one or more text portions:
- createSwDoc();
+ SwDoc* pDoc = createSwDoc();
uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XText> xText = xTextDocument->getText();
@@ -414,7 +414,17 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlTextPortionEnum)
// portion.
assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/SwLinePortion", "type",
"PortionType::ContentControl");
- assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/SwLinePortion", "portion", "test");
+ assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/SwLinePortion", "portion", "test*");
+
+ // Also test the doc model, make sure that there is a dummy character at the start and end, so
+ // the user can explicitly decide if they want to expand the content control or not:
+ SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+ OUString aText = pWrtShell->GetCursor()->GetNode().GetTextNode()->GetText();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: ^Atest^A
+ // - Actual : ^Atest
+ // i.e. there was no dummy character at the end.
+ CPPUNIT_ASSERT_EQUAL(OUString("\x0001test\x0001"), aText);
}
CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlCheckbox)
diff --git a/sw/qa/uibase/wrtsh/wrtsh.cxx b/sw/qa/uibase/wrtsh/wrtsh.cxx
index 1bce34fb8a53..72d8e7060de6 100644
--- a/sw/qa/uibase/wrtsh/wrtsh.cxx
+++ b/sw/qa/uibase/wrtsh/wrtsh.cxx
@@ -125,9 +125,8 @@ CPPUNIT_TEST_FIXTURE(Test, testTickCheckboxContentControl)
// Without the accompanying fix in place, this test would have failed:
// - Expected: ☐
// - Actual : ☒
- // i.e. the text node's text was CH_TXTATR_BREAKWORD + "Ballot Box with X", not just
- // CH_TXTATR_BREAKWORD + "Ballot Box".
- CPPUNIT_ASSERT_EQUAL(OUString(u"\x0001☐"), pTextNode->GetText());
+ // i.e. the text node's text was "Ballot Box with X", not just "Ballot Box".
+ CPPUNIT_ASSERT_EQUAL(OUString(u"☐"), pTextNode->GetExpandText(pWrtShell->GetLayout()));
}
CPPUNIT_TEST_FIXTURE(Test, testInsertContentControl)
@@ -214,9 +213,8 @@ CPPUNIT_TEST_FIXTURE(Test, testSelectDropdownContentControl)
// Without the accompanying fix in place, this test would have failed:
// - Expected: red
// - Actual : choose an item
- // i.e. the document text was unchanged instead of CH_TXTATR_BREAKWORD + display text of the
- // first list item.
- CPPUNIT_ASSERT_EQUAL(OUString(u"\x0001red"), pTextNode->GetText());
+ // i.e. the document text was unchanged instead of display text of the first list item.
+ CPPUNIT_ASSERT_EQUAL(OUString("red"), pTextNode->GetExpandText(pWrtShell->GetLayout()));
}
}
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
index 14ed1026f4d7..ac48ef29b9c6 100644
--- a/sw/source/core/crsr/crstrvl.cxx
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -879,7 +879,9 @@ bool SwCursorShell::GotoFormatContentControl(const SwFormatContentControl& rCont
sal_Int32 nStart = pTextContentControl->GetStart() + 1;
pCursor->GetPoint()->nContent.Assign(pTextNode, nStart);
pCursor->GetMark()->nNode = *pTextNode;
- pCursor->GetMark()->nContent.Assign(pTextNode, *(pTextContentControl->End()));
+ // Don't select the CH_TXTATR_BREAKWORD itself at the end.
+ sal_Int32 nEnd = *pTextContentControl->End() - 1;
+ pCursor->GetMark()->nContent.Assign(pTextNode, nEnd);
// Assume that once the placeholder is selected, the content is no longer the placeholder.
pContentControl->SetShowingPlaceHolder(false);
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 12dae9ceda13..2cf7052553ac 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -649,10 +649,10 @@ void SwSelPaintRects::HighlightContentControl()
SwTextContentControl* pCurContentControlAtCursor = nullptr;
if (pTextNode)
{
- // SwTextNode::EXPAND because the LHS of the dummy character doesn't count, the RHS of
- // the start of the LHS of the end counts.
+ // SwTextNode::PARENT because this way we highlight when the user will type inside the
+ // content control, not outside of it.
SwTextAttr* pAttr = pTextNode->GetTextAttrAt(
- pStart->nContent.GetIndex(), RES_TXTATR_CONTENTCONTROL, SwTextNode::EXPAND);
+ pStart->nContent.GetIndex(), RES_TXTATR_CONTENTCONTROL, SwTextNode::PARENT);
if (pAttr)
{
pCurContentControlAtCursor = static_txtattr_cast<SwTextContentControl*>(pAttr);
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx b/sw/source/core/txtnode/attrcontentcontrol.cxx
index c28e686ce6fb..8704221a9a3b 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -318,10 +318,6 @@ SwTextContentControl::SwTextContentControl(SwFormatContentControl& rAttr, sal_In
{
rAttr.SetTextAttr(this);
SetHasDummyChar(true);
-
- // If the user types at the end of the content control, expand the text attr to the right.
- SetLockExpandFlag(false);
- SetDontExpand(false);
}
SwTextContentControl::~SwTextContentControl()
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index d9905fce33cc..1a3d53c4b4aa 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -3412,6 +3412,7 @@ OUString SwTextNode::GetExpandText(SwRootFrame const*const pLayout,
// remove dummy characters of Input Fields
comphelper::string::remove(aText, CH_TXT_ATR_INPUTFIELDSTART);
comphelper::string::remove(aText, CH_TXT_ATR_INPUTFIELDEND);
+ comphelper::string::remove(aText, CH_TXTATR_BREAKWORD);
if( bWithNum )
{
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index b15667ec6fcc..f71db22d3fb7 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -1566,11 +1566,30 @@ bool SwTextNode::InsertHint( SwTextAttr * const pAttr, const SetAttrMode nMode )
}
// adjust end of hint to account for inserted CH_TXTATR
- const sal_Int32 * const pEnd(pAttr->GetEnd());
+ const sal_Int32* pEnd(pAttr->GetEnd());
if (pEnd)
{
pAttr->SetEnd(*pEnd + 1);
}
+
+ if (pAttr->Which() == RES_TXTATR_CONTENTCONTROL)
+ {
+ // Content controls have a dummy character at their end as well.
+ SwIndex aEndIdx(this, *pAttr->GetEnd());
+ OUString aEnd
+ = InsertText(OUString(GetCharOfTextAttr(*pAttr)), aEndIdx, nInsertFlags);
+ if (aEnd.isEmpty())
+ {
+ DestroyAttr(pAttr);
+ return false;
+ }
+
+ pEnd = pAttr->GetEnd();
+ if (pEnd)
+ {
+ pAttr->SetEnd(*pEnd + 1);
+ }
+ }
}
}
diff --git a/sw/source/core/unocore/unocontentcontrol.cxx b/sw/source/core/unocore/unocontentcontrol.cxx
index 19e5e60176d3..5c01ae826acf 100644
--- a/sw/source/core/unocore/unocontentcontrol.cxx
+++ b/sw/source/core/unocore/unocontentcontrol.cxx
@@ -316,7 +316,8 @@ bool SwXContentControl::SetContentRange(SwTextNode*& rpNode, sal_Int32& rStart,
{
// rStart points at the first position within the content control.
rStart = pTextAttr->GetStart() + 1;
- rEnd = *pTextAttr->End();
+ // rEnd points at the last position within the content control.
+ rEnd = *pTextAttr->End() - 1;
return true;
}
}
diff --git a/sw/source/filter/ascii/ascatr.cxx b/sw/source/filter/ascii/ascatr.cxx
index 97e98784afc8..42d16c7eed1a 100644
--- a/sw/source/filter/ascii/ascatr.cxx
+++ b/sw/source/filter/ascii/ascatr.cxx
@@ -342,7 +342,7 @@ static Writer& OutASC_SwTextNode( Writer& rWrt, SwContentNode& rNode )
if ( !bExportSoftHyphens )
aOutStr = aOutStr.replaceAll(OUStringChar(CHAR_SOFTHYPHEN), "");
- // all INWORD/BREAKWORD should be already removed by OutAttr
+ // all INWORD should be already removed by OutAttr
// but the field-marks are not attributes so filter those
static sal_Unicode const forbidden [] = {
CH_TXT_ATR_INPUTFIELDSTART,
@@ -351,6 +351,7 @@ static Writer& OutASC_SwTextNode( Writer& rWrt, SwContentNode& rNode )
CH_TXT_ATR_FIELDSTART,
CH_TXT_ATR_FIELDSEP,
CH_TXT_ATR_FIELDEND,
+ CH_TXTATR_BREAKWORD,
0
};
aOutStr = comphelper::string::removeAny(aOutStr, forbidden);
diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx b/sw/source/uibase/wrtsh/wrtsh3.cxx
index aa0badb54e61..573ea4a9752d 100644
--- a/sw/source/uibase/wrtsh/wrtsh3.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh3.cxx
@@ -140,10 +140,6 @@ bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentContro
GetIDocumentUndoRedo().StartUndo(SwUndoId::REPLACE, &aRewriter);
// Update the content.
- SwTextContentControl* pTextContentControl
- = const_cast<SwFormatContentControl&>(rContentControl).GetTextAttr();
- // If the content control is at the end of the line, then expand is false by default.
- pTextContentControl->SetDontExpand(false);
DelLeft();
pContentControl->SetSelectedListItem(std::nullopt);
Insert(aNewState);