sw: delete bookmark if paragraph is fully selected
testTdf96479 requires inserting with absorb=true to be treated as Replace, and there is of course no string in insertTextContent(). testDeleteFlyAtCharAtStart requires setString("") to be treated as Delete. Annoyingly this requires API setString() call to be replaced with internal call, do this for SwXTextRange and SwXTextCursor which are the 2 classes typically used in practice. Change-Id: I87caa1aa11abe298cdd3d9a9bbb602e547c7b443 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137370 Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> Tested-by: Jenkins
This commit is contained in:
parent
316e4c01f4
commit
baf8d2c1c1
8 changed files with 59 additions and 16 deletions
|
@ -24,6 +24,9 @@
|
|||
#include <com/sun/star/container/XEnumeration.hpp>
|
||||
|
||||
#include <cppuhelper/implbase.hxx>
|
||||
|
||||
#include <o3tl/typed_flags_set.hxx>
|
||||
|
||||
#include <vcl/svapp.hxx>
|
||||
|
||||
class SfxPoolItem;
|
||||
|
@ -53,6 +56,22 @@ enum class CursorType
|
|||
ContentControl,
|
||||
};
|
||||
|
||||
namespace sw {
|
||||
|
||||
enum class DeleteAndInsertMode
|
||||
{
|
||||
Default = 0,
|
||||
ForceExpandHints = (1<<0),
|
||||
ForceReplace = (1<<1),
|
||||
};
|
||||
|
||||
} // namespace sw
|
||||
|
||||
namespace o3tl
|
||||
{
|
||||
template<> struct typed_flags<::sw::DeleteAndInsertMode> : is_typed_flags<::sw::DeleteAndInsertMode, 0x03> {};
|
||||
}
|
||||
|
||||
/*
|
||||
Start/EndAction or Start/EndAllAction
|
||||
*/
|
||||
|
|
|
@ -102,9 +102,7 @@ public:
|
|||
bool IsAtEndOfMeta() const;
|
||||
bool IsAtEndOfContentControl() const;
|
||||
|
||||
void DeleteAndInsert(OUString const& rText,
|
||||
const bool bForceExpandHints);
|
||||
|
||||
void DeleteAndInsert(OUString const& rText, ::sw::DeleteAndInsertMode eMode);
|
||||
// OTextCursorHelper
|
||||
virtual const SwPaM* GetPaM() const override;
|
||||
virtual SwPaM* GetPaM() override;
|
||||
|
|
|
@ -109,7 +109,7 @@ private:
|
|||
//TODO: new exception type for protected content
|
||||
/// @throws css::uno::RuntimeException
|
||||
void DeleteAndInsert(
|
||||
const OUString& rText, const bool bForceExpandHints);
|
||||
const OUString& rText, ::sw::DeleteAndInsertMode eMode);
|
||||
void Invalidate();
|
||||
|
||||
virtual ~SwXTextRange() override;
|
||||
|
|
|
@ -1306,6 +1306,7 @@ void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
|
|||
rDoc.getIDocumentContentOperations().DelFullPara( rPam );
|
||||
}
|
||||
else
|
||||
// FIXME: this ends up calling DeleteBookmarks() on the entire rPam which deletes too many!
|
||||
rDoc.getIDocumentContentOperations().DeleteAndJoin(rPam, m_DeleteFlags);
|
||||
}
|
||||
|
||||
|
|
|
@ -1136,7 +1136,12 @@ void SwUndoSaveContent::DelContentIndex( const SwPosition& rMark,
|
|||
&& ( type == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK
|
||||
|| type == IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK
|
||||
|| type == IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK
|
||||
|| type == IDocumentMarkAccess::MarkType::DATE_FIELDMARK)))
|
||||
|| type == IDocumentMarkAccess::MarkType::DATE_FIELDMARK))
|
||||
|| (bMaybe
|
||||
&& !(nDelContentType & DelContentType::Replace)
|
||||
&& type == IDocumentMarkAccess::MarkType::BOOKMARK
|
||||
&& pStt->nContent == 0 // entire paragraph deleted?
|
||||
&& pEnd->nContent == pEnd->nNode.GetNode().GetTextNode()->Len()))
|
||||
{
|
||||
if( bMaybe )
|
||||
bSavePos = true;
|
||||
|
|
|
@ -705,7 +705,7 @@ SwXTextCursor::~SwXTextCursor()
|
|||
}
|
||||
|
||||
void SwXTextCursor::DeleteAndInsert(const OUString& rText,
|
||||
const bool bForceExpandHints)
|
||||
::sw::DeleteAndInsertMode const eMode)
|
||||
{
|
||||
auto pUnoCursor = static_cast<SwCursor*>(m_pUnoCursor.get());
|
||||
if (!pUnoCursor)
|
||||
|
@ -721,13 +721,16 @@ void SwXTextCursor::DeleteAndInsert(const OUString& rText,
|
|||
{
|
||||
if (pCurrent->HasMark())
|
||||
{
|
||||
rDoc.getIDocumentContentOperations().DeleteAndJoin(*pCurrent);
|
||||
rDoc.getIDocumentContentOperations().DeleteAndJoin(*pCurrent,
|
||||
// is it "delete" or "replace"?
|
||||
// FIXME still test failure because insertTextContent calls with empty string
|
||||
(nTextLen != 0 || eMode & ::sw::DeleteAndInsertMode::ForceReplace) ? SwDeleteFlags::ArtificialSelection : SwDeleteFlags::Default);
|
||||
}
|
||||
if(nTextLen)
|
||||
{
|
||||
const bool bSuccess(
|
||||
SwUnoCursorHelper::DocInsertStringSplitCR(
|
||||
rDoc, *pCurrent, rText, bForceExpandHints ) );
|
||||
rDoc, *pCurrent, rText, bool(eMode & ::sw::DeleteAndInsertMode::ForceExpandHints)));
|
||||
OSL_ENSURE( bSuccess, "Doc->Insert(Str) failed." );
|
||||
|
||||
SwUnoCursorHelper::SelectPam(*pUnoCursor, true);
|
||||
|
@ -1724,7 +1727,7 @@ SwXTextCursor::setString(const OUString& aString)
|
|||
const bool bForceExpandHints( (CursorType::Meta == m_eType)
|
||||
&& dynamic_cast<SwXMeta&>(*m_xParentText)
|
||||
.CheckForOwnMemberMeta(*GetPaM(), true) );
|
||||
DeleteAndInsert(aString, bForceExpandHints);
|
||||
DeleteAndInsert(aString, bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default);
|
||||
}
|
||||
|
||||
uno::Any SwUnoCursorHelper::GetPropertyValue(
|
||||
|
|
|
@ -800,7 +800,7 @@ static void DeleteTable(SwDoc & rDoc, SwTable& rTable)
|
|||
}
|
||||
|
||||
void SwXTextRange::DeleteAndInsert(
|
||||
const OUString& rText, const bool bForceExpandHints)
|
||||
const OUString& rText, ::sw::DeleteAndInsertMode const eMode)
|
||||
{
|
||||
if (RANGE_IS_TABLE == m_pImpl->m_eRangePosition)
|
||||
{
|
||||
|
@ -887,13 +887,14 @@ void SwXTextRange::DeleteAndInsert(
|
|||
|
||||
if (aCursor.HasMark())
|
||||
{
|
||||
m_pImpl->m_rDoc.getIDocumentContentOperations().DeleteAndJoin(aCursor);
|
||||
m_pImpl->m_rDoc.getIDocumentContentOperations().DeleteAndJoin(aCursor,
|
||||
(!rText.isEmpty() || eMode & ::sw::DeleteAndInsertMode::ForceReplace) ? SwDeleteFlags::ArtificialSelection : SwDeleteFlags::Default);
|
||||
}
|
||||
|
||||
if (!rText.isEmpty())
|
||||
{
|
||||
SwUnoCursorHelper::DocInsertStringSplitCR(
|
||||
m_pImpl->m_rDoc, aCursor, rText, bForceExpandHints);
|
||||
m_pImpl->m_rDoc, aCursor, rText, bool(eMode & ::sw::DeleteAndInsertMode::ForceExpandHints));
|
||||
|
||||
SwUnoCursorHelper::SelectPam(aCursor, true);
|
||||
aCursor.Left(rText.getLength());
|
||||
|
@ -1060,7 +1061,7 @@ void SAL_CALL SwXTextRange::setString(const OUString& rString)
|
|||
{
|
||||
SolarMutexGuard aGuard;
|
||||
|
||||
DeleteAndInsert(rString, false);
|
||||
DeleteAndInsert(rString, ::sw::DeleteAndInsertMode::Default);
|
||||
}
|
||||
|
||||
bool SwXTextRange::GetPositions(SwPaM& rToFill, ::sw::TextRangeMode const eMode) const
|
||||
|
|
|
@ -364,7 +364,8 @@ SwXText::insertString(const uno::Reference< text::XTextRange >& xTextRange,
|
|||
dynamic_cast<SwXTextCursor*>(pCursor) );
|
||||
if (pTextCursor)
|
||||
{
|
||||
pTextCursor->DeleteAndInsert(rString, bForceExpandHints);
|
||||
pTextCursor->DeleteAndInsert(rString, ::sw::DeleteAndInsertMode::ForceReplace
|
||||
| (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -373,7 +374,8 @@ SwXText::insertString(const uno::Reference< text::XTextRange >& xTextRange,
|
|||
}
|
||||
else
|
||||
{
|
||||
pRange->DeleteAndInsert(rString, bForceExpandHints);
|
||||
pRange->DeleteAndInsert(rString, ::sw::DeleteAndInsertMode::ForceReplace
|
||||
| (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -605,9 +607,23 @@ SwXText::insertTextContent(
|
|||
|| pSection || pReferenceMark || pMeta || pContentControl || pTextField;
|
||||
|
||||
if (bAbsorb && !bAttribute)
|
||||
{
|
||||
uno::Reference<lang::XUnoTunnel> const xRangeTunnel(xRange, uno::UNO_QUERY);
|
||||
if (SwXTextRange *const pRange = comphelper::getFromUnoTunnel<SwXTextRange>(xRangeTunnel))
|
||||
{
|
||||
pRange->DeleteAndInsert(OUString(), ::sw::DeleteAndInsertMode::ForceReplace
|
||||
| (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
|
||||
}
|
||||
else if (SwXTextCursor *const pCursor = dynamic_cast<SwXTextCursor*>(comphelper::getFromUnoTunnel<OTextCursorHelper>(xRangeTunnel)))
|
||||
{
|
||||
pCursor->DeleteAndInsert(OUString(), ::sw::DeleteAndInsertMode::ForceReplace
|
||||
| (bForceExpandHints ? ::sw::DeleteAndInsertMode::ForceExpandHints : ::sw::DeleteAndInsertMode::Default));
|
||||
}
|
||||
else
|
||||
{
|
||||
xRange->setString(OUString());
|
||||
}
|
||||
}
|
||||
uno::Reference< text::XTextRange > xTempRange =
|
||||
(bAttribute && bAbsorb) ? xRange : xRange->getStart();
|
||||
if (bForceExpandHints)
|
||||
|
|
Loading…
Reference in a new issue