diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-05-11 09:29:05 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-05-11 12:22:48 +0200 |
commit | 1e9416fac497a58be04011cfa0ffce9c74a9e397 (patch) | |
tree | 1cfacf7409e2e111d5f99fab864635bc6b600f19 /sw | |
parent | 35dec195a1f0a7a3aa8fab893698e512f5851d19 (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.cxx | 14 | ||||
-rw-r--r-- | sw/qa/uibase/wrtsh/wrtsh.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/crsr/crstrvl.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/crsr/viscrs.cxx | 6 | ||||
-rw-r--r-- | sw/source/core/txtnode/attrcontentcontrol.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/txtnode/ndtxt.cxx | 1 | ||||
-rw-r--r-- | sw/source/core/txtnode/thints.cxx | 21 | ||||
-rw-r--r-- | sw/source/core/unocore/unocontentcontrol.cxx | 3 | ||||
-rw-r--r-- | sw/source/filter/ascii/ascatr.cxx | 3 | ||||
-rw-r--r-- | sw/source/uibase/wrtsh/wrtsh3.cxx | 4 |
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); |