summaryrefslogtreecommitdiffstats
path: root/editeng/source/uno
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /editeng/source/uno
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'editeng/source/uno')
-rw-r--r--editeng/source/uno/UnoForbiddenCharsTable.cxx132
-rw-r--r--editeng/source/uno/unoedhlp.cxx250
-rw-r--r--editeng/source/uno/unoedprx.cxx1209
-rw-r--r--editeng/source/uno/unoedsrc.cxx77
-rw-r--r--editeng/source/uno/unofdesc.cxx229
-rw-r--r--editeng/source/uno/unofield.cxx941
-rw-r--r--editeng/source/uno/unofored.cxx520
-rw-r--r--editeng/source/uno/unofored_internal.hxx28
-rw-r--r--editeng/source/uno/unoforou.cxx582
-rw-r--r--editeng/source/uno/unoipset.cxx333
-rw-r--r--editeng/source/uno/unonrule.cxx544
-rw-r--r--editeng/source/uno/unopracc.cxx92
-rw-r--r--editeng/source/uno/unotext.cxx2561
-rw-r--r--editeng/source/uno/unotext2.cxx629
-rw-r--r--editeng/source/uno/unoviwou.cxx128
15 files changed, 8255 insertions, 0 deletions
diff --git a/editeng/source/uno/UnoForbiddenCharsTable.cxx b/editeng/source/uno/UnoForbiddenCharsTable.cxx
new file mode 100644
index 0000000000..5e77a9252f
--- /dev/null
+++ b/editeng/source/uno/UnoForbiddenCharsTable.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <editeng/UnoForbiddenCharsTable.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::i18n;
+using namespace ::cppu;
+
+SvxUnoForbiddenCharsTable::SvxUnoForbiddenCharsTable(std::shared_ptr<SvxForbiddenCharactersTable> xForbiddenChars)
+ : mxForbiddenChars(std::move(xForbiddenChars))
+{
+}
+
+SvxUnoForbiddenCharsTable::~SvxUnoForbiddenCharsTable()
+{
+}
+
+void SvxUnoForbiddenCharsTable::onChange()
+{
+}
+
+ForbiddenCharacters SvxUnoForbiddenCharsTable::getForbiddenCharacters( const lang::Locale& rLocale )
+{
+ SolarMutexGuard aGuard;
+
+ if (!mxForbiddenChars)
+ throw RuntimeException("No Forbidden Characters present");
+
+ const LanguageType eLang = LanguageTag::convertToLanguageType( rLocale );
+ const ForbiddenCharacters* pForbidden = mxForbiddenChars->GetForbiddenCharacters( eLang, false );
+ if(!pForbidden)
+ throw NoSuchElementException();
+
+ return *pForbidden;
+}
+
+sal_Bool SvxUnoForbiddenCharsTable::hasForbiddenCharacters( const lang::Locale& rLocale )
+{
+ SolarMutexGuard aGuard;
+
+ if (!mxForbiddenChars)
+ return false;
+
+ const LanguageType eLang = LanguageTag::convertToLanguageType( rLocale );
+ const ForbiddenCharacters* pForbidden = mxForbiddenChars->GetForbiddenCharacters( eLang, false );
+
+ return nullptr != pForbidden;
+}
+
+void SvxUnoForbiddenCharsTable::setForbiddenCharacters(const lang::Locale& rLocale, const ForbiddenCharacters& rForbiddenCharacters )
+{
+ SolarMutexGuard aGuard;
+
+ if (!mxForbiddenChars)
+ throw RuntimeException("No Forbidden Characters present");
+
+ const LanguageType eLang = LanguageTag::convertToLanguageType( rLocale );
+ mxForbiddenChars->SetForbiddenCharacters( eLang, rForbiddenCharacters );
+
+ onChange();
+}
+
+void SvxUnoForbiddenCharsTable::removeForbiddenCharacters( const lang::Locale& rLocale )
+{
+ SolarMutexGuard aGuard;
+
+ if (!mxForbiddenChars)
+ throw RuntimeException("No Forbidden Characters present");
+
+ const LanguageType eLang = LanguageTag::convertToLanguageType( rLocale );
+ mxForbiddenChars->ClearForbiddenCharacters( eLang );
+
+ onChange();
+}
+
+// XSupportedLocales
+Sequence< lang::Locale > SAL_CALL SvxUnoForbiddenCharsTable::getLocales()
+{
+ SolarMutexGuard aGuard;
+
+ const sal_Int32 nCount = mxForbiddenChars ? mxForbiddenChars->GetMap().size() : 0;
+
+ Sequence< lang::Locale > aLocales( nCount );
+ if( nCount )
+ {
+ lang::Locale* pLocales = aLocales.getArray();
+
+ for (auto const& elem : mxForbiddenChars->GetMap())
+ {
+ const LanguageType nLanguage = elem.first;
+ *pLocales++ = LanguageTag( nLanguage ).getLocale();
+ }
+ }
+
+ return aLocales;
+}
+
+sal_Bool SAL_CALL SvxUnoForbiddenCharsTable::hasLocale( const lang::Locale& aLocale )
+{
+ SolarMutexGuard aGuard;
+
+ return hasForbiddenCharacters( aLocale );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unoedhlp.cxx b/editeng/source/uno/unoedhlp.cxx
new file mode 100644
index 0000000000..2a1b1e2bd5
--- /dev/null
+++ b/editeng/source/uno/unoedhlp.cxx
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <editeng/unoedhlp.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/editeng.hxx>
+#include <svl/itemset.hxx>
+
+#include <osl/diagnose.h>
+
+
+SvxEditSourceHint::SvxEditSourceHint( SfxHintId _nId ) :
+ TextHint( _nId ),
+ mnStart( 0 ),
+ mnEnd( 0 )
+{
+}
+
+SvxEditSourceHint::SvxEditSourceHint( SfxHintId _nId, sal_Int32 nValue, sal_Int32 nStart, sal_Int32 nEnd ) :
+ TextHint( _nId, nValue ),
+ mnStart( nStart),
+ mnEnd( nEnd )
+{
+}
+
+
+std::unique_ptr<SfxHint> SvxEditSourceHelper::EENotification2Hint( EENotify const * aNotify )
+{
+ if( aNotify )
+ {
+ switch( aNotify->eNotificationType )
+ {
+ case EE_NOTIFY_TEXTMODIFIED:
+ return std::unique_ptr<SfxHint>( new TextHint( SfxHintId::TextModified, aNotify->nParagraph ) );
+
+ case EE_NOTIFY_PARAGRAPHINSERTED:
+ return std::unique_ptr<SfxHint>( new TextHint( SfxHintId::TextParaInserted, aNotify->nParagraph ) );
+
+ case EE_NOTIFY_PARAGRAPHREMOVED:
+ return std::unique_ptr<SfxHint>( new TextHint( SfxHintId::TextParaRemoved, aNotify->nParagraph ) );
+
+ case EE_NOTIFY_PARAGRAPHSMOVED:
+ return std::unique_ptr<SfxHint>( new SvxEditSourceHint( SfxHintId::EditSourceParasMoved, aNotify->nParagraph, aNotify->nParam1, aNotify->nParam2 ) );
+
+ case EE_NOTIFY_TextHeightChanged:
+ return std::unique_ptr<SfxHint>( new TextHint( SfxHintId::TextHeightChanged, aNotify->nParagraph ) );
+
+ case EE_NOTIFY_TEXTVIEWSCROLLED:
+ return std::unique_ptr<SfxHint>( new TextHint( SfxHintId::TextViewScrolled ) );
+
+ case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED:
+ return std::unique_ptr<SfxHint>( new SvxEditSourceHint( SfxHintId::EditSourceSelectionChanged ) );
+
+ case EE_NOTIFY_PROCESSNOTIFICATIONS:
+ return std::unique_ptr<SfxHint>( new TextHint( SfxHintId::TextProcessNotifications ));
+
+ case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED_ENDD_PARA:
+ return std::unique_ptr<SfxHint>( new SvxEditSourceHintEndPara );
+ default:
+ OSL_FAIL( "SvxEditSourceHelper::EENotification2Hint unknown notification" );
+ break;
+ }
+ }
+
+ return std::make_unique<SfxHint>( );
+}
+
+void SvxEditSourceHelper::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, const EditEngine& rEE, sal_Int32 nPara, sal_Int32 nIndex, bool bInCell )
+{
+ // IA2 CWS introduced bInCell, but also did many other changes here.
+ // Need to verify implementation with AT (IA2 and ATK)
+ // Old implementation at the end of the method for reference...
+
+ //added dummy attributes for the default text
+ std::vector<EECharAttrib> aCharAttribs, aTempCharAttribs;
+ rEE.GetCharAttribs( nPara, aTempCharAttribs );
+
+ if (!aTempCharAttribs.empty())
+ {
+ sal_Int32 nIndex2 = 0;
+ sal_Int32 nParaLen = rEE.GetTextLen(nPara);
+ for (size_t nAttr = 0; nAttr < aTempCharAttribs.size(); ++nAttr)
+ {
+ if (nIndex2 < aTempCharAttribs[nAttr].nStart)
+ {
+ EECharAttrib aEEAttr(nIndex2, aTempCharAttribs[nAttr].nStart);
+ aCharAttribs.insert(aCharAttribs.begin() + nAttr, aEEAttr);
+ }
+ nIndex2 = aTempCharAttribs[nAttr].nEnd;
+ aCharAttribs.push_back(aTempCharAttribs[nAttr]);
+ }
+ if ( nIndex2 != nParaLen )
+ {
+ EECharAttrib aEEAttr(nIndex2, nParaLen);
+ aCharAttribs.push_back(aEEAttr);
+ }
+ }
+ // find closest index in front of nIndex
+ sal_Int32 nCurrIndex;
+ sal_Int32 nClosestStartIndex_s = 0, nClosestStartIndex_e = 0;
+ for (auto const& charAttrib : aCharAttribs)
+ {
+ nCurrIndex = charAttrib.nStart;
+
+ if( nCurrIndex > nClosestStartIndex_s &&
+ nCurrIndex <= nIndex)
+ {
+ nClosestStartIndex_s = nCurrIndex;
+ }
+ nCurrIndex = charAttrib.nEnd;
+ if ( nCurrIndex > nClosestStartIndex_e &&
+ nCurrIndex < nIndex )
+ {
+ nClosestStartIndex_e = nCurrIndex;
+ }
+ }
+ sal_Int32 nClosestStartIndex = std::max(nClosestStartIndex_s, nClosestStartIndex_e);
+
+ // find closest index behind of nIndex
+ sal_Int32 nClosestEndIndex_s, nClosestEndIndex_e;
+ nClosestEndIndex_s = nClosestEndIndex_e = rEE.GetTextLen(nPara);
+ for (auto const& charAttrib : aCharAttribs)
+ {
+ nCurrIndex = charAttrib.nEnd;
+
+ if( nCurrIndex > nIndex &&
+ nCurrIndex < nClosestEndIndex_e )
+ {
+ nClosestEndIndex_e = nCurrIndex;
+ }
+ nCurrIndex = charAttrib.nStart;
+ if ( nCurrIndex > nIndex &&
+ nCurrIndex < nClosestEndIndex_s)
+ {
+ nClosestEndIndex_s = nCurrIndex;
+ }
+ }
+ sal_Int32 nClosestEndIndex = std::min(nClosestEndIndex_s, nClosestEndIndex_e);
+
+ nStartIndex = nClosestStartIndex;
+ nEndIndex = nClosestEndIndex;
+
+ if ( !bInCell )
+ return;
+
+ EPosition aStartPos( nPara, nStartIndex ), aEndPos( nPara, nEndIndex );
+ sal_Int32 nParaCount = rEE.GetParagraphCount();
+ sal_Int32 nCrrntParaLen = rEE.GetTextLen(nPara);
+ //need to find closest index in front of nIndex in the previous paragraphs
+ if ( aStartPos.nIndex == 0 )
+ {
+ SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, 0, 1, GetAttribsFlags::CHARATTRIBS );
+ for ( sal_Int32 nParaIdx = nPara-1; nParaIdx >= 0; nParaIdx-- )
+ {
+ sal_uInt32 nLen = rEE.GetTextLen(nParaIdx);
+ if ( nLen )
+ {
+ sal_Int32 nStartIdx, nEndIdx;
+ GetAttributeRun( nStartIdx, nEndIdx, rEE, nParaIdx, nLen );
+ SfxItemSet aSet = rEE.GetAttribs( nParaIdx, nLen-1, nLen, GetAttribsFlags::CHARATTRIBS );
+ if ( aSet == aCrrntSet )
+ {
+ aStartPos.nPara = nParaIdx;
+ aStartPos.nIndex = nStartIdx;
+ if ( aStartPos.nIndex != 0 )
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ //need find closest index behind nIndex in the following paragraphs
+ if ( aEndPos.nIndex == nCrrntParaLen )
+ {
+ SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, nCrrntParaLen-1, nCrrntParaLen, GetAttribsFlags::CHARATTRIBS );
+ for ( sal_Int32 nParaIdx = nPara+1; nParaIdx < nParaCount; nParaIdx++ )
+ {
+ sal_Int32 nLen = rEE.GetTextLen( nParaIdx );
+ if ( nLen )
+ {
+ sal_Int32 nStartIdx, nEndIdx;
+ GetAttributeRun( nStartIdx, nEndIdx, rEE, nParaIdx, 0 );
+ SfxItemSet aSet = rEE.GetAttribs( nParaIdx, 0, 1, GetAttribsFlags::CHARATTRIBS );
+ if ( aSet == aCrrntSet )
+ {
+ aEndPos.nPara = nParaIdx;
+ aEndPos.nIndex = nEndIdx;
+ if ( aEndPos.nIndex != nLen )
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ nStartIndex = 0;
+ if ( aStartPos.nPara > 0 )
+ {
+ for ( sal_Int32 i = 0; i < aStartPos.nPara; i++ )
+ {
+ nStartIndex += rEE.GetTextLen(i)+1;
+ }
+ }
+ nStartIndex += aStartPos.nIndex;
+ nEndIndex = 0;
+ if ( aEndPos.nPara > 0 )
+ {
+ for ( sal_Int32 i = 0; i < aEndPos.nPara; i++ )
+ {
+ nEndIndex += rEE.GetTextLen(i)+1;
+ }
+ }
+ nEndIndex += aEndPos.nIndex;
+}
+
+Point SvxEditSourceHelper::EEToUserSpace( const Point& rPoint, const Size& rEESize, bool bIsVertical )
+{
+ return bIsVertical ? Point( -rPoint.Y() + rEESize.Height(), rPoint.X() ) : rPoint;
+}
+
+Point SvxEditSourceHelper::UserSpaceToEE( const Point& rPoint, const Size& rEESize, bool bIsVertical )
+{
+ return bIsVertical ? Point( rPoint.Y(), -rPoint.X() + rEESize.Height() ) : rPoint;
+}
+
+tools::Rectangle SvxEditSourceHelper::EEToUserSpace( const tools::Rectangle& rRect, const Size& rEESize, bool bIsVertical )
+{
+ return bIsVertical ? tools::Rectangle( EEToUserSpace(rRect.BottomLeft(), rEESize, bIsVertical),
+ EEToUserSpace(rRect.TopRight(), rEESize, bIsVertical) ) : rRect;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unoedprx.cxx b/editeng/source/uno/unoedprx.cxx
new file mode 100644
index 0000000000..20d5df281b
--- /dev/null
+++ b/editeng/source/uno/unoedprx.cxx
@@ -0,0 +1,1209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+// Global header
+
+
+#include <utility>
+#include <memory>
+#include <vector>
+#include <algorithm>
+#include <osl/diagnose.h>
+#include <svl/itemset.hxx>
+#include <tools/debug.hxx>
+
+
+// Project-local header
+
+
+#include <editeng/unoedprx.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/editeng.hxx>
+#include <AccessibleStringWrap.hxx>
+#include <editeng/outliner.hxx>
+
+using namespace ::com::sun::star;
+
+namespace {
+
+class SvxAccessibleTextIndex
+{
+public:
+ SvxAccessibleTextIndex() :
+ mnPara(0),
+ mnIndex(0),
+ mnEEIndex(0),
+ mnFieldOffset(0),
+ mnFieldLen(0),
+ mnBulletOffset(0),
+ mnBulletLen(0),
+ mbInField(false),
+ mbInBullet(false) {};
+
+ // Get/Set current paragraph
+ void SetParagraph( sal_Int32 nPara )
+ {
+ mnPara = nPara;
+ }
+ sal_Int32 GetParagraph() const { return mnPara; }
+
+ /** Set the index in the UAA semantic
+
+ @param nIndex
+ The index from the UA API (fields and bullets are expanded)
+
+ @param rTF
+ The text forwarder to use in the calculations
+ */
+ void SetIndex( sal_Int32 nIndex, const SvxTextForwarder& rTF );
+ void SetIndex( sal_Int32 nPara, sal_Int32 nIndex, const SvxTextForwarder& rTF ) { SetParagraph(nPara); SetIndex(nIndex, rTF); }
+ sal_Int32 GetIndex() const { return mnIndex; }
+
+ /** Set the index in the edit engine semantic
+
+ Update the object state to reflect the given index position in
+ EditEngine/Outliner index values
+
+ @param nEEIndex
+ The index from the edit engine (fields span exactly one index increment)
+
+ @param rTF
+ The text forwarder to use in the calculations
+ */
+ void SetEEIndex( sal_Int32 nEEIndex, const SvxTextForwarder& rTF );
+ void SetEEIndex( sal_Int32 nPara, sal_Int32 nEEIndex, const SvxTextForwarder& rTF ) { SetParagraph(nPara); SetEEIndex(nEEIndex, rTF); }
+ sal_Int32 GetEEIndex() const;
+
+ void SetFieldOffset( sal_Int32 nOffset, sal_Int32 nLen ) { mnFieldOffset = nOffset; mnFieldLen = nLen; }
+ sal_Int32 GetFieldOffset() const { return mnFieldOffset; }
+ sal_Int32 GetFieldLen() const { return mnFieldLen; }
+ void AreInField() { mbInField = true; }
+ bool InField() const { return mbInField; }
+
+ void SetBulletOffset( sal_Int32 nOffset, sal_Int32 nLen ) { mnBulletOffset = nOffset; mnBulletLen = nLen; }
+ sal_Int32 GetBulletOffset() const { return mnBulletOffset; }
+ sal_Int32 GetBulletLen() const { return mnBulletLen; }
+ bool InBullet() const { return mbInBullet; }
+
+ /// returns false if the given range is non-editable (e.g. contains bullets or _parts_ of fields)
+ bool IsEditableRange( const SvxAccessibleTextIndex& rEnd ) const;
+
+private:
+ sal_Int32 mnPara;
+ sal_Int32 mnIndex;
+ sal_Int32 mnEEIndex;
+ sal_Int32 mnFieldOffset;
+ sal_Int32 mnFieldLen;
+ sal_Int32 mnBulletOffset;
+ sal_Int32 mnBulletLen;
+ bool mbInField;
+ bool mbInBullet;
+};
+
+}
+
+static ESelection MakeEESelection( const SvxAccessibleTextIndex& rStart, const SvxAccessibleTextIndex& rEnd )
+{
+ // deal with field special case: to really get a field contained
+ // within a selection, the start index must be before or on the
+ // field, the end index after it.
+
+ // The SvxAccessibleTextIndex.GetEEIndex method gives the index on
+ // the field, as long the input index is on the field. Thus,
+ // correction necessary for the end index
+
+ // Therefore, for _ranges_, if part of the field is touched, all
+ // of the field must be selected
+ if( rStart.GetParagraph() <= rEnd.GetParagraph() ||
+ (rStart.GetParagraph() == rEnd.GetParagraph() &&
+ rStart.GetEEIndex() <= rEnd.GetEEIndex()) )
+ {
+ if( rEnd.InField() && rEnd.GetFieldOffset() )
+ return ESelection( rStart.GetParagraph(), rStart.GetEEIndex(),
+ rEnd.GetParagraph(), rEnd.GetEEIndex()+1 );
+ }
+ else if( rStart.GetParagraph() > rEnd.GetParagraph() ||
+ (rStart.GetParagraph() == rEnd.GetParagraph() &&
+ rStart.GetEEIndex() > rEnd.GetEEIndex()) )
+ {
+ if( rStart.InField() && rStart.GetFieldOffset() )
+ return ESelection( rStart.GetParagraph(), rStart.GetEEIndex()+1,
+ rEnd.GetParagraph(), rEnd.GetEEIndex() );
+ }
+
+ return ESelection( rStart.GetParagraph(), rStart.GetEEIndex(),
+ rEnd.GetParagraph(), rEnd.GetEEIndex() );
+}
+
+static ESelection MakeEESelection( const SvxAccessibleTextIndex& rIndex )
+{
+ return ESelection( rIndex.GetParagraph(), rIndex.GetEEIndex(),
+ rIndex.GetParagraph(), rIndex.GetEEIndex() + 1 );
+}
+
+sal_Int32 SvxAccessibleTextIndex::GetEEIndex() const
+{
+ DBG_ASSERT(mnEEIndex >= 0,
+ "SvxAccessibleTextIndex::GetEEIndex: index value overflow");
+
+ return mnEEIndex;
+}
+
+void SvxAccessibleTextIndex::SetEEIndex( sal_Int32 nEEIndex, const SvxTextForwarder& rTF )
+{
+ // reset
+ mnFieldOffset = 0;
+ mbInField = false;
+ mnFieldLen = 0;
+ mnBulletOffset = 0;
+ mbInBullet = false;
+ mnBulletLen = 0;
+
+ // set known values
+ mnEEIndex = nEEIndex;
+
+ // calculate unknowns
+ sal_Int32 nCurrField, nFieldCount = rTF.GetFieldCount( GetParagraph() );
+
+ mnIndex = nEEIndex;
+
+ EBulletInfo aBulletInfo = rTF.GetBulletInfo( GetParagraph() );
+
+ // any text bullets?
+ if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
+ aBulletInfo.bVisible &&
+ aBulletInfo.nType != SVX_NUM_BITMAP )
+ {
+ mnIndex += aBulletInfo.aText.getLength();
+ }
+
+ for( nCurrField=0; nCurrField < nFieldCount; ++nCurrField )
+ {
+ EFieldInfo aFieldInfo( rTF.GetFieldInfo( GetParagraph(), nCurrField ) );
+
+ if( aFieldInfo.aPosition.nIndex > nEEIndex )
+ break;
+
+ if( aFieldInfo.aPosition.nIndex == nEEIndex )
+ {
+ AreInField();
+ break;
+ }
+
+ mnIndex += std::max(aFieldInfo.aCurrentText.getLength()-1, sal_Int32(0));
+ }
+}
+
+void SvxAccessibleTextIndex::SetIndex( sal_Int32 nIndex, const SvxTextForwarder& rTF )
+{
+ // reset
+ mnFieldOffset = 0;
+ mbInField = false;
+ mnFieldLen = 0;
+ mnBulletOffset = 0;
+ mbInBullet = false;
+ mnBulletLen = 0;
+
+ // set known values
+ mnIndex = nIndex;
+
+ // calculate unknowns
+ sal_Int32 nCurrField, nFieldCount = rTF.GetFieldCount( GetParagraph() );
+
+ DBG_ASSERT(nIndex >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ mnEEIndex = nIndex;
+
+ EBulletInfo aBulletInfo = rTF.GetBulletInfo( GetParagraph() );
+
+ // any text bullets?
+ if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
+ aBulletInfo.bVisible &&
+ aBulletInfo.nType != SVX_NUM_BITMAP )
+ {
+ sal_Int32 nBulletLen = aBulletInfo.aText.getLength();
+
+ if( nIndex < nBulletLen )
+ {
+ mbInBullet = true;
+ SetBulletOffset( nIndex, nBulletLen );
+ mnEEIndex = 0;
+ return;
+ }
+
+ mnEEIndex = mnEEIndex - nBulletLen;
+ }
+
+ for( nCurrField=0; nCurrField < nFieldCount; ++nCurrField )
+ {
+ EFieldInfo aFieldInfo( rTF.GetFieldInfo( GetParagraph(), nCurrField ) );
+
+ // we're before a field
+ if( aFieldInfo.aPosition.nIndex > mnEEIndex )
+ break;
+
+ mnEEIndex -= std::max(aFieldInfo.aCurrentText.getLength()-1, sal_Int32(0));
+
+ // we're within a field
+ if( aFieldInfo.aPosition.nIndex >= mnEEIndex )
+ {
+ AreInField();
+ SetFieldOffset( std::max(aFieldInfo.aCurrentText.getLength()-1, sal_Int32(0)) - (aFieldInfo.aPosition.nIndex - mnEEIndex),
+ aFieldInfo.aCurrentText.getLength() );
+ mnEEIndex = aFieldInfo.aPosition.nIndex ;
+ break;
+ }
+ }
+}
+
+bool SvxAccessibleTextIndex::IsEditableRange( const SvxAccessibleTextIndex& rEnd ) const
+{
+ if( GetIndex() > rEnd.GetIndex() )
+ return rEnd.IsEditableRange( *this );
+
+ if( InBullet() || rEnd.InBullet() )
+ return false;
+
+ if( InField() && GetFieldOffset() )
+ return false; // within field
+
+ if( rEnd.InField() && rEnd.GetFieldOffset() >= rEnd.GetFieldLen() - 1 )
+ return false; // within field
+
+ return true;
+}
+
+
+SvxEditSourceAdapter::SvxEditSourceAdapter() : mbEditSourceValid( false )
+{
+}
+
+SvxEditSourceAdapter::~SvxEditSourceAdapter()
+{
+}
+
+std::unique_ptr<SvxEditSource> SvxEditSourceAdapter::Clone() const
+{
+ if( mbEditSourceValid && mpAdaptee )
+ {
+ std::unique_ptr< SvxEditSource > pClonedAdaptee( mpAdaptee->Clone() );
+
+ if (pClonedAdaptee)
+ {
+ std::unique_ptr<SvxEditSourceAdapter> pClone(new SvxEditSourceAdapter());
+ pClone->SetEditSource( std::move(pClonedAdaptee) );
+ return std::unique_ptr< SvxEditSource >(pClone.release());
+ }
+ }
+
+ return nullptr;
+}
+
+SvxAccessibleTextAdapter* SvxEditSourceAdapter::GetTextForwarderAdapter()
+{
+ if( mbEditSourceValid && mpAdaptee )
+ {
+ SvxTextForwarder* pTextForwarder = mpAdaptee->GetTextForwarder();
+
+ if( pTextForwarder )
+ {
+ maTextAdapter.SetForwarder(*pTextForwarder);
+
+ return &maTextAdapter;
+ }
+ }
+
+ return nullptr;
+}
+
+SvxTextForwarder* SvxEditSourceAdapter::GetTextForwarder()
+{
+ return GetTextForwarderAdapter();
+}
+
+SvxViewForwarder* SvxEditSourceAdapter::GetViewForwarder()
+{
+ if( mbEditSourceValid && mpAdaptee )
+ return mpAdaptee->GetViewForwarder();
+
+ return nullptr;
+}
+
+SvxAccessibleTextEditViewAdapter* SvxEditSourceAdapter::GetEditViewForwarderAdapter( bool bCreate )
+{
+ if( mbEditSourceValid && mpAdaptee )
+ {
+ SvxEditViewForwarder* pEditViewForwarder = mpAdaptee->GetEditViewForwarder(bCreate);
+
+ if( pEditViewForwarder )
+ {
+ SvxAccessibleTextAdapter* pTextAdapter = GetTextForwarderAdapter();
+
+ if( pTextAdapter )
+ {
+ maEditViewAdapter.SetForwarder(*pEditViewForwarder, *pTextAdapter);
+
+ return &maEditViewAdapter;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+SvxEditViewForwarder* SvxEditSourceAdapter::GetEditViewForwarder( bool bCreate )
+{
+ return GetEditViewForwarderAdapter( bCreate );
+}
+
+void SvxEditSourceAdapter::UpdateData()
+{
+ if( mbEditSourceValid && mpAdaptee )
+ mpAdaptee->UpdateData();
+}
+
+SfxBroadcaster& SvxEditSourceAdapter::GetBroadcaster() const
+{
+ if( mbEditSourceValid && mpAdaptee )
+ return mpAdaptee->GetBroadcaster();
+
+ return maDummyBroadcaster;
+}
+
+void SvxEditSourceAdapter::SetEditSource( std::unique_ptr< SvxEditSource > && pAdaptee )
+{
+ if (pAdaptee)
+ {
+ mpAdaptee = std::move(pAdaptee);
+ mbEditSourceValid = true;
+ }
+ else
+ {
+ // do a lazy delete (prevents us from deleting the broadcaster
+ // from within a broadcast in
+ // AccessibleTextHelper_Impl::Notify)
+ mbEditSourceValid = false;
+ }
+}
+
+SvxAccessibleTextAdapter::SvxAccessibleTextAdapter()
+ : mpTextForwarder(nullptr)
+{
+}
+
+SvxAccessibleTextAdapter::~SvxAccessibleTextAdapter()
+{
+}
+
+sal_Int32 SvxAccessibleTextAdapter::GetParagraphCount() const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetParagraphCount();
+}
+
+sal_Int32 SvxAccessibleTextAdapter::GetTextLen( sal_Int32 nParagraph ) const
+{
+ SvxAccessibleTextIndex aIndex;
+ aIndex.SetEEIndex( nParagraph, mpTextForwarder->GetTextLen( nParagraph ), *this );
+
+ return aIndex.GetIndex();
+}
+
+OUString SvxAccessibleTextAdapter::GetText( const ESelection& rSel ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ // normalize selection
+ if( rSel.nStartPara > rSel.nEndPara ||
+ (rSel.nStartPara == rSel.nEndPara && rSel.nStartPos > rSel.nEndPos) )
+ {
+ std::swap( aStartIndex, aEndIndex );
+ }
+
+ OUString sStr = mpTextForwarder->GetText( MakeEESelection(aStartIndex, aEndIndex) );
+
+ // trim field text, if necessary
+ if( aStartIndex.InField() )
+ {
+ DBG_ASSERT(aStartIndex.GetFieldOffset() >= 0,
+ "SvxAccessibleTextIndex::GetText: index value overflow");
+
+ sStr = sStr.copy( aStartIndex.GetFieldOffset() );
+ }
+ if( aEndIndex.InField() && aEndIndex.GetFieldOffset() )
+ {
+ DBG_ASSERT(sStr.getLength() - (aEndIndex.GetFieldLen() - aEndIndex.GetFieldOffset()) >= 0,
+ "SvxAccessibleTextIndex::GetText: index value overflow");
+
+ sStr = sStr.copy(0, sStr.getLength() - (aEndIndex.GetFieldLen() - aEndIndex.GetFieldOffset()) );
+ }
+
+ EBulletInfo aBulletInfo2 = GetBulletInfo( aEndIndex.GetParagraph() );
+
+ if( aEndIndex.InBullet() )
+ {
+ // append trailing bullet
+ sStr += aBulletInfo2.aText;
+
+ DBG_ASSERT(sStr.getLength() - (aEndIndex.GetBulletLen() - aEndIndex.GetBulletOffset()) >= 0,
+ "SvxAccessibleTextIndex::GetText: index value overflow");
+
+ sStr = sStr.copy(0, sStr.getLength() - (aEndIndex.GetBulletLen() - aEndIndex.GetBulletOffset()) );
+ }
+ else if( aStartIndex.GetParagraph() != aEndIndex.GetParagraph() &&
+ HaveTextBullet( aEndIndex.GetParagraph() ) )
+ {
+ OUString sBullet = aBulletInfo2.aText;
+
+ DBG_ASSERT(sBullet.getLength() - (aEndIndex.GetBulletLen() - aEndIndex.GetBulletOffset()) >= 0,
+ "SvxAccessibleTextIndex::GetText: index value overflow");
+
+ sBullet = sBullet.copy(0, sBullet.getLength() - (aEndIndex.GetBulletLen() - aEndIndex.GetBulletOffset()) );
+
+ // insert bullet
+ sStr = sStr.replaceAt( GetTextLen(aStartIndex.GetParagraph()) - aStartIndex.GetIndex(), 0, sBullet );
+ }
+
+ return sStr;
+}
+
+SfxItemSet SvxAccessibleTextAdapter::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ return mpTextForwarder->GetAttribs( MakeEESelection(aStartIndex, aEndIndex), nOnlyHardAttrib );
+}
+
+SfxItemSet SvxAccessibleTextAdapter::GetParaAttribs( sal_Int32 nPara ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetParaAttribs( nPara );
+}
+
+void SvxAccessibleTextAdapter::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ mpTextForwarder->SetParaAttribs( nPara, rSet );
+}
+
+void SvxAccessibleTextAdapter::RemoveAttribs( const ESelection& )
+{
+}
+
+void SvxAccessibleTextAdapter::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ mpTextForwarder->GetPortions( nPara, rList );
+}
+
+OUString SvxAccessibleTextAdapter::GetStyleSheet(sal_Int32 nPara) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetStyleSheet(nPara);
+}
+
+void SvxAccessibleTextAdapter::SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName)
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ mpTextForwarder->SetStyleSheet(nPara, rStyleName);
+}
+
+SfxItemState SvxAccessibleTextAdapter::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ return mpTextForwarder->GetItemState( MakeEESelection(aStartIndex, aEndIndex),
+ nWhich );
+}
+
+SfxItemState SvxAccessibleTextAdapter::GetItemState( sal_Int32 nPara, sal_uInt16 nWhich ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetItemState( nPara, nWhich );
+}
+
+void SvxAccessibleTextAdapter::QuickInsertText( const OUString& rText, const ESelection& rSel )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ mpTextForwarder->QuickInsertText( rText,
+ MakeEESelection(aStartIndex, aEndIndex) );
+}
+
+void SvxAccessibleTextAdapter::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ mpTextForwarder->QuickInsertField( rFld,
+ MakeEESelection(aStartIndex, aEndIndex) );
+}
+
+void SvxAccessibleTextAdapter::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ mpTextForwarder->QuickSetAttribs( rSet,
+ MakeEESelection(aStartIndex, aEndIndex) );
+}
+
+void SvxAccessibleTextAdapter::QuickInsertLineBreak( const ESelection& rSel )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ mpTextForwarder->QuickInsertLineBreak( MakeEESelection(aStartIndex, aEndIndex) );
+}
+
+SfxItemPool* SvxAccessibleTextAdapter::GetPool() const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetPool();
+}
+
+OUString SvxAccessibleTextAdapter::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle );
+}
+
+void SvxAccessibleTextAdapter::FieldClicked( const SvxFieldItem& rField )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ mpTextForwarder->FieldClicked( rField );
+}
+
+sal_Int32 SvxAccessibleTextAdapter::CalcEditEngineIndex( sal_Int32 nPara, sal_Int32 nLogicalIndex )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aIndex;
+ aIndex.SetIndex(nPara, nLogicalIndex, *mpTextForwarder);
+ return aIndex.GetEEIndex();
+}
+
+bool SvxAccessibleTextAdapter::IsValid() const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ if( mpTextForwarder )
+ return mpTextForwarder->IsValid();
+ else
+ return false;
+}
+
+LanguageType SvxAccessibleTextAdapter::GetLanguage( sal_Int32 nPara, sal_Int32 nPos ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aIndex;
+
+ aIndex.SetIndex( nPara, nPos, *this );
+
+ return mpTextForwarder->GetLanguage( nPara, aIndex.GetEEIndex() );
+}
+
+sal_Int32 SvxAccessibleTextAdapter::GetFieldCount( sal_Int32 nPara ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetFieldCount( nPara );
+}
+
+EFieldInfo SvxAccessibleTextAdapter::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetFieldInfo( nPara, nField );
+}
+
+EBulletInfo SvxAccessibleTextAdapter::GetBulletInfo( sal_Int32 nPara ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetBulletInfo( nPara );
+}
+
+tools::Rectangle SvxAccessibleTextAdapter::GetCharBounds( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aIndex;
+ aIndex.SetIndex( nPara, nIndex, *this );
+
+ // preset if anything goes wrong below
+ // n-th char in GetParagraphIndex's paragraph
+ tools::Rectangle aRect = mpTextForwarder->GetCharBounds( nPara, aIndex.GetEEIndex() );
+
+ if( aIndex.InBullet() )
+ {
+ EBulletInfo aBulletInfo = GetBulletInfo( nPara );
+
+ OutputDevice* pOutDev = GetRefDevice();
+
+ DBG_ASSERT(pOutDev!=nullptr, "SvxAccessibleTextAdapter::GetCharBounds: No ref device");
+
+ // preset if anything goes wrong below
+ aRect = aBulletInfo.aBounds; // better than nothing
+ if( pOutDev )
+ {
+ AccessibleStringWrap aStringWrap( *pOutDev, aBulletInfo.aFont, aBulletInfo.aText );
+
+ aStringWrap.GetCharacterBounds( aIndex.GetBulletOffset(), aRect );
+ aRect.Move( aBulletInfo.aBounds.Left(), aBulletInfo.aBounds.Top() );
+ }
+ }
+ else
+ {
+ // handle field content manually
+ if( aIndex.InField() )
+ {
+ OutputDevice* pOutDev = GetRefDevice();
+
+ DBG_ASSERT(pOutDev!=nullptr, "SvxAccessibleTextAdapter::GetCharBounds: No ref device");
+
+ if( pOutDev )
+ {
+ ESelection aSel = MakeEESelection( aIndex );
+
+ SvxFont aFont = EditEngine::CreateSvxFontFromItemSet( mpTextForwarder->GetAttribs( aSel ) );
+ AccessibleStringWrap aStringWrap( *pOutDev,
+ aFont,
+ mpTextForwarder->GetText( aSel ) );
+
+ tools::Rectangle aStartRect = mpTextForwarder->GetCharBounds( nPara, aIndex.GetEEIndex() );
+
+ aStringWrap.GetCharacterBounds( aIndex.GetFieldOffset(), aRect );
+ aRect.Move( aStartRect.Left(), aStartRect.Top() );
+ }
+ }
+ }
+
+ return aRect;
+}
+
+tools::Rectangle SvxAccessibleTextAdapter::GetParaBounds( sal_Int32 nPara ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ EBulletInfo aBulletInfo = GetBulletInfo( nPara );
+
+ if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
+ aBulletInfo.bVisible &&
+ aBulletInfo.nType != SVX_NUM_BITMAP )
+ {
+ // include bullet in para bounding box
+ tools::Rectangle aRect( mpTextForwarder->GetParaBounds( nPara ) );
+
+ aRect.Union( aBulletInfo.aBounds );
+
+ return aRect;
+ }
+
+ return mpTextForwarder->GetParaBounds( nPara );
+}
+
+MapMode SvxAccessibleTextAdapter::GetMapMode() const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetMapMode();
+}
+
+OutputDevice* SvxAccessibleTextAdapter::GetRefDevice() const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetRefDevice();
+}
+
+bool SvxAccessibleTextAdapter::GetIndexAtPoint( const Point& rPoint, sal_Int32& nPara, sal_Int32& nIndex ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ if( !mpTextForwarder->GetIndexAtPoint( rPoint, nPara, nIndex ) )
+ return false;
+
+ SvxAccessibleTextIndex aIndex;
+ aIndex.SetEEIndex(nPara, nIndex, *this);
+
+ DBG_ASSERT(aIndex.GetIndex() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ nIndex = aIndex.GetIndex();
+
+ EBulletInfo aBulletInfo = GetBulletInfo( nPara );
+
+ // any text bullets?
+ if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
+ aBulletInfo.bVisible &&
+ aBulletInfo.nType != SVX_NUM_BITMAP )
+ {
+ if( aBulletInfo.aBounds.Contains( rPoint) )
+ {
+ OutputDevice* pOutDev = GetRefDevice();
+
+ DBG_ASSERT(pOutDev!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device");
+
+ if( !pOutDev )
+ return false;
+
+ AccessibleStringWrap aStringWrap( *pOutDev, aBulletInfo.aFont, aBulletInfo.aText );
+
+ Point aPoint = rPoint;
+ aPoint.Move( -aBulletInfo.aBounds.Left(), -aBulletInfo.aBounds.Top() );
+
+ DBG_ASSERT(aStringWrap.GetIndexAtPoint( aPoint ) >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ nIndex = aStringWrap.GetIndexAtPoint( aPoint );
+ return true;
+ }
+ }
+
+ if( !aIndex.InField() )
+ return true;
+
+ OutputDevice* pOutDev = GetRefDevice();
+
+ DBG_ASSERT(pOutDev!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device");
+
+ if( !pOutDev )
+ return false;
+
+ ESelection aSelection = MakeEESelection( aIndex );
+ SvxFont aFont = EditEngine::CreateSvxFontFromItemSet( mpTextForwarder->GetAttribs( aSelection ) );
+ AccessibleStringWrap aStringWrap( *pOutDev,
+ aFont,
+ mpTextForwarder->GetText( aSelection ) );
+
+ tools::Rectangle aRect = mpTextForwarder->GetCharBounds( nPara, aIndex.GetEEIndex() );
+ Point aPoint = rPoint;
+ aPoint.Move( -aRect.Left(), -aRect.Top() );
+
+ DBG_ASSERT(aIndex.GetIndex() + aStringWrap.GetIndexAtPoint( rPoint ) >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ nIndex = (aIndex.GetIndex() + aStringWrap.GetIndexAtPoint( aPoint ));
+ return true;
+}
+
+bool SvxAccessibleTextAdapter::GetWordIndices( sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart, sal_Int32& nEnd ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aIndex;
+ aIndex.SetIndex(nPara, nIndex, *this);
+ nIndex = aIndex.GetEEIndex();
+
+ if( aIndex.InBullet() )
+ {
+ DBG_ASSERT(aIndex.GetBulletLen() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ // always treat bullet as separate word
+ nStart = 0;
+ nEnd = aIndex.GetBulletLen();
+
+ return true;
+ }
+
+ if( aIndex.InField() )
+ {
+ DBG_ASSERT(aIndex.GetIndex() - aIndex.GetFieldOffset() >= 0 &&
+ nStart + aIndex.GetFieldLen() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ // always treat field as separate word
+ // TODO: to circumvent this, _we_ would have to do the break iterator stuff!
+ nStart = aIndex.GetIndex() - aIndex.GetFieldOffset();
+ nEnd = nStart + aIndex.GetFieldLen();
+
+ return true;
+ }
+
+ if( !mpTextForwarder->GetWordIndices( nPara, nIndex, nStart, nEnd ) )
+ return false;
+
+ aIndex.SetEEIndex( nPara, nStart, *this );
+ DBG_ASSERT(aIndex.GetIndex() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+ nStart = aIndex.GetIndex();
+
+ aIndex.SetEEIndex( nPara, nEnd, *this );
+ DBG_ASSERT(aIndex.GetIndex() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+ nEnd = aIndex.GetIndex();
+
+ return true;
+}
+
+bool SvxAccessibleTextAdapter::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara, sal_Int32 nIndex, bool /* bInCell */ ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aIndex;
+ aIndex.SetIndex(nPara, nIndex, *this);
+ nIndex = aIndex.GetEEIndex();
+
+ if( aIndex.InBullet() )
+ {
+ DBG_ASSERT(aIndex.GetBulletLen() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ // always treat bullet as distinct attribute
+ nStartIndex = 0;
+ nEndIndex = aIndex.GetBulletLen();
+
+ return true;
+ }
+
+ if( aIndex.InField() )
+ {
+ DBG_ASSERT(aIndex.GetIndex() - aIndex.GetFieldOffset() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+
+ // always treat field as distinct attribute
+ nStartIndex = aIndex.GetIndex() - aIndex.GetFieldOffset();
+ nEndIndex = nStartIndex + aIndex.GetFieldLen();
+
+ return true;
+ }
+
+ if( !mpTextForwarder->GetAttributeRun( nStartIndex, nEndIndex, nPara, nIndex ) )
+ return false;
+
+ aIndex.SetEEIndex( nPara, nStartIndex, *this );
+ DBG_ASSERT(aIndex.GetIndex() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+ nStartIndex = aIndex.GetIndex();
+
+ aIndex.SetEEIndex( nPara, nEndIndex, *this );
+ DBG_ASSERT(aIndex.GetIndex() >= 0,
+ "SvxAccessibleTextIndex::SetIndex: index value overflow");
+ nEndIndex = aIndex.GetIndex();
+
+ return true;
+}
+
+sal_Int32 SvxAccessibleTextAdapter::GetLineCount( sal_Int32 nPara ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetLineCount( nPara );
+}
+
+sal_Int32 SvxAccessibleTextAdapter::GetLineLen( sal_Int32 nPara, sal_Int32 nLine ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aEndIndex;
+ sal_Int32 nCurrLine;
+ sal_Int32 nCurrIndex, nLastIndex;
+ for( nCurrLine=0, nCurrIndex=0, nLastIndex=0; nCurrLine<=nLine; ++nCurrLine )
+ {
+ nLastIndex = nCurrIndex;
+ nCurrIndex =
+ nCurrIndex + mpTextForwarder->GetLineLen( nPara, nCurrLine );
+ }
+
+ aEndIndex.SetEEIndex( nPara, nCurrIndex, *this );
+ if( nLine > 0 )
+ {
+ SvxAccessibleTextIndex aStartIndex;
+ aStartIndex.SetEEIndex( nPara, nLastIndex, *this );
+
+ return aEndIndex.GetIndex() - aStartIndex.GetIndex();
+ }
+ else
+ return aEndIndex.GetIndex();
+}
+
+void SvxAccessibleTextAdapter::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const
+{
+ mpTextForwarder->GetLineBoundaries( rStart, rEnd, nParagraph, nLine );
+}
+
+sal_Int32 SvxAccessibleTextAdapter::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ return mpTextForwarder->GetLineNumberAtIndex( nPara, nIndex );
+}
+
+bool SvxAccessibleTextAdapter::Delete( const ESelection& rSel )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ return mpTextForwarder->Delete( MakeEESelection(aStartIndex, aEndIndex ) );
+}
+
+bool SvxAccessibleTextAdapter::InsertText( const OUString& rStr, const ESelection& rSel )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ return mpTextForwarder->InsertText( rStr, MakeEESelection(aStartIndex, aEndIndex) );
+}
+
+bool SvxAccessibleTextAdapter::QuickFormatDoc( bool bFull )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->QuickFormatDoc( bFull );
+}
+
+sal_Int16 SvxAccessibleTextAdapter::GetDepth( sal_Int32 nPara ) const
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->GetDepth( nPara );
+}
+
+bool SvxAccessibleTextAdapter::SetDepth( sal_Int32 nPara, sal_Int16 nNewDepth )
+{
+ assert(mpTextForwarder && "SvxAccessibleTextAdapter: no forwarder");
+
+ return mpTextForwarder->SetDepth( nPara, nNewDepth );
+}
+
+void SvxAccessibleTextAdapter::SetForwarder( SvxTextForwarder& rForwarder )
+{
+ mpTextForwarder = &rForwarder;
+}
+
+bool SvxAccessibleTextAdapter::HaveImageBullet( sal_Int32 nPara ) const
+{
+ EBulletInfo aBulletInfo = GetBulletInfo( nPara );
+
+ return ( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
+ aBulletInfo.bVisible &&
+ aBulletInfo.nType == SVX_NUM_BITMAP );
+}
+
+bool SvxAccessibleTextAdapter::HaveTextBullet( sal_Int32 nPara ) const
+{
+ EBulletInfo aBulletInfo = GetBulletInfo( nPara );
+
+ return ( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
+ aBulletInfo.bVisible &&
+ aBulletInfo.nType != SVX_NUM_BITMAP );
+}
+
+bool SvxAccessibleTextAdapter::IsEditable( const ESelection& rSel ) const
+{
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *this );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *this );
+
+ // normalize selection
+ if( rSel.nStartPara > rSel.nEndPara ||
+ (rSel.nStartPara == rSel.nEndPara && rSel.nStartPos > rSel.nEndPos) )
+ {
+ std::swap( aStartIndex, aEndIndex );
+ }
+
+ return aStartIndex.IsEditableRange( aEndIndex );
+}
+
+const SfxItemSet * SvxAccessibleTextAdapter::GetEmptyItemSetPtr()
+{
+ OSL_FAIL( "not implemented" );
+ return nullptr;
+}
+
+void SvxAccessibleTextAdapter::AppendParagraph()
+{
+ OSL_FAIL( "not implemented" );
+}
+
+sal_Int32 SvxAccessibleTextAdapter::AppendTextPortion( sal_Int32, const OUString &, const SfxItemSet & )
+{
+ OSL_FAIL( "not implemented" );
+ return 0;
+}
+void SvxAccessibleTextAdapter::CopyText(const SvxTextForwarder&)
+{
+ OSL_FAIL( "not implemented" );
+}
+
+SvxAccessibleTextEditViewAdapter::SvxAccessibleTextEditViewAdapter()
+ : mpViewForwarder(nullptr)
+ , mpTextForwarder(nullptr)
+{
+}
+
+SvxAccessibleTextEditViewAdapter::~SvxAccessibleTextEditViewAdapter()
+{
+}
+
+bool SvxAccessibleTextEditViewAdapter::IsValid() const
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ if( mpViewForwarder )
+ return mpViewForwarder->IsValid();
+ else
+ return false;
+}
+
+Point SvxAccessibleTextEditViewAdapter::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ return mpViewForwarder->LogicToPixel(rPoint, rMapMode);
+}
+
+Point SvxAccessibleTextEditViewAdapter::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ return mpViewForwarder->PixelToLogic(rPoint, rMapMode);
+}
+
+bool SvxAccessibleTextEditViewAdapter::GetSelection( ESelection& rSel ) const
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ ESelection aSelection;
+
+ if( !mpViewForwarder->GetSelection( aSelection ) )
+ return false;
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetEEIndex( aSelection.nStartPara, aSelection.nStartPos, *mpTextForwarder );
+ aEndIndex.SetEEIndex( aSelection.nEndPara, aSelection.nEndPos, *mpTextForwarder );
+
+ DBG_ASSERT(aStartIndex.GetIndex() >= 0 &&
+ aEndIndex.GetIndex() >= 0,
+ "SvxAccessibleTextEditViewAdapter::GetSelection: index value overflow");
+
+ rSel = ESelection( aStartIndex.GetParagraph(), aStartIndex.GetIndex(),
+ aEndIndex.GetParagraph(), aEndIndex.GetIndex() );
+
+ return true;
+}
+
+bool SvxAccessibleTextEditViewAdapter::SetSelection( const ESelection& rSel )
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ SvxAccessibleTextIndex aStartIndex;
+ SvxAccessibleTextIndex aEndIndex;
+
+ aStartIndex.SetIndex( rSel.nStartPara, rSel.nStartPos, *mpTextForwarder );
+ aEndIndex.SetIndex( rSel.nEndPara, rSel.nEndPos, *mpTextForwarder );
+
+ return mpViewForwarder->SetSelection( MakeEESelection(aStartIndex, aEndIndex) );
+}
+
+bool SvxAccessibleTextEditViewAdapter::Copy()
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ return mpViewForwarder->Copy();
+}
+
+bool SvxAccessibleTextEditViewAdapter::Cut()
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ return mpViewForwarder->Cut();
+}
+
+bool SvxAccessibleTextEditViewAdapter::Paste()
+{
+ DBG_ASSERT(mpViewForwarder, "SvxAccessibleTextEditViewAdapter: no forwarder");
+
+ return mpViewForwarder->Paste();
+}
+
+void SvxAccessibleTextEditViewAdapter::SetForwarder( SvxEditViewForwarder& rForwarder,
+ SvxAccessibleTextAdapter& rTextForwarder )
+{
+ mpViewForwarder = &rForwarder;
+ mpTextForwarder = &rTextForwarder;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unoedsrc.cxx b/editeng/source/uno/unoedsrc.cxx
new file mode 100644
index 0000000000..1c827472d1
--- /dev/null
+++ b/editeng/source/uno/unoedsrc.cxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svl/SfxBroadcaster.hxx>
+
+#include <editeng/unoedsrc.hxx>
+
+#include <osl/diagnose.h>
+
+
+void SvxEditSource::addRange( SvxUnoTextRangeBase* )
+{
+}
+
+
+void SvxEditSource::removeRange( SvxUnoTextRangeBase* )
+{
+}
+
+
+const SvxUnoTextRangeBaseVec& SvxEditSource::getRanges() const
+{
+ static SvxUnoTextRangeBaseVec gList;
+ return gList;
+}
+
+
+SvxTextForwarder::~SvxTextForwarder() COVERITY_NOEXCEPT_FALSE
+{
+}
+
+
+SvxViewForwarder::~SvxViewForwarder()
+{
+}
+
+
+SvxEditSource::~SvxEditSource()
+{
+}
+
+SvxViewForwarder* SvxEditSource::GetViewForwarder()
+{
+ return nullptr;
+}
+
+SvxEditViewForwarder* SvxEditSource::GetEditViewForwarder( bool )
+{
+ return nullptr;
+}
+
+SfxBroadcaster& SvxEditSource::GetBroadcaster() const
+{
+ OSL_FAIL("SvxEditSource::GetBroadcaster called for implementation missing this feature!");
+
+ static SfxBroadcaster aBroadcaster;
+
+ return aBroadcaster;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unofdesc.cxx b/editeng/source/uno/unofdesc.cxx
new file mode 100644
index 0000000000..722ae7d7f9
--- /dev/null
+++ b/editeng/source/uno/unofdesc.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <editeng/eeitem.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/memberids.h>
+#include <svl/itempool.hxx>
+#include <vcl/font.hxx>
+#include <vcl/unohelp.hxx>
+#include <tools/gen.hxx>
+
+#include <editeng/unofdesc.hxx>
+
+using namespace ::com::sun::star;
+
+
+void SvxUnoFontDescriptor::ConvertToFont( const awt::FontDescriptor& rDesc, vcl::Font& rFont )
+{
+ rFont.SetFamilyName( rDesc.Name );
+ rFont.SetStyleName( rDesc.StyleName );
+ rFont.SetFontSize( Size( rDesc.Width, rDesc.Height ) );
+ rFont.SetFamily( static_cast<FontFamily>(rDesc.Family) );
+ rFont.SetCharSet( static_cast<rtl_TextEncoding>(rDesc.CharSet) );
+ rFont.SetPitch( static_cast<FontPitch>(rDesc.Pitch) );
+ rFont.SetOrientation( Degree10(static_cast<sal_Int16>(rDesc.Orientation*10)) );
+ rFont.SetKerning( rDesc.Kerning ? FontKerning::FontSpecific : FontKerning::NONE );
+ rFont.SetWeight( vcl::unohelper::ConvertFontWeight(rDesc.Weight) );
+ rFont.SetItalic( static_cast<FontItalic>(rDesc.Slant) );
+ rFont.SetUnderline( static_cast<FontLineStyle>(rDesc.Underline) );
+ rFont.SetStrikeout( static_cast<FontStrikeout>(rDesc.Strikeout) );
+ rFont.SetWordLineMode( rDesc.WordLineMode );
+}
+
+void SvxUnoFontDescriptor::ConvertFromFont( const vcl::Font& rFont, awt::FontDescriptor& rDesc )
+{
+ rDesc.Name = rFont.GetFamilyName();
+ rDesc.StyleName = rFont.GetStyleName();
+ rDesc.Width = sal::static_int_cast< sal_Int16 >(rFont.GetFontSize().Width());
+ rDesc.Height = sal::static_int_cast< sal_Int16 >(rFont.GetFontSize().Height());
+ rDesc.Family = sal::static_int_cast< sal_Int16 >(rFont.GetFamilyType());
+ rDesc.CharSet = rFont.GetCharSet();
+ rDesc.Pitch = sal::static_int_cast< sal_Int16 >(rFont.GetPitch());
+ rDesc.Orientation = static_cast< float >(rFont.GetOrientation().get() / 10);
+ rDesc.Kerning = rFont.IsKerning();
+ rDesc.Weight = vcl::unohelper::ConvertFontWeight( rFont.GetWeight() );
+ rDesc.Slant = vcl::unohelper::ConvertFontSlant( rFont.GetItalic() );
+ rDesc.Underline = sal::static_int_cast< sal_Int16 >(rFont.GetUnderline());
+ rDesc.Strikeout = sal::static_int_cast< sal_Int16 >(rFont.GetStrikeout());
+ rDesc.WordLineMode = rFont.IsWordLineMode();
+}
+
+void SvxUnoFontDescriptor::FillItemSet( const awt::FontDescriptor& rDesc, SfxItemSet& rSet )
+{
+ uno::Any aTemp;
+
+ {
+ SvxFontItem aFontItem( EE_CHAR_FONTINFO );
+ aFontItem.SetFamilyName( rDesc.Name);
+ aFontItem.SetStyleName( rDesc.StyleName);
+ aFontItem.SetFamily( static_cast<FontFamily>(rDesc.Family));
+ aFontItem.SetCharSet( rDesc.CharSet );
+ aFontItem.SetPitch( static_cast<FontPitch>(rDesc.Pitch));
+ rSet.Put(aFontItem);
+ }
+
+ {
+ SvxFontHeightItem aFontHeightItem( 0, 100, EE_CHAR_FONTHEIGHT );
+ aTemp <<= static_cast<float>(rDesc.Height);
+ static_cast<SfxPoolItem*>(&aFontHeightItem)->PutValue( aTemp, MID_FONTHEIGHT|CONVERT_TWIPS );
+ rSet.Put(aFontHeightItem);
+ }
+
+ {
+ SvxPostureItem aPostureItem( ITALIC_NONE, EE_CHAR_ITALIC );
+ aTemp <<= rDesc.Slant;
+ static_cast<SfxPoolItem*>(&aPostureItem)->PutValue( aTemp, MID_POSTURE );
+ rSet.Put(aPostureItem);
+ }
+
+ {
+ SvxUnderlineItem aUnderlineItem( LINESTYLE_NONE, EE_CHAR_UNDERLINE );
+ aTemp <<= rDesc.Underline;
+ static_cast<SfxPoolItem*>(&aUnderlineItem)->PutValue( aTemp, MID_TL_STYLE );
+ rSet.Put( aUnderlineItem );
+ }
+
+ {
+ SvxWeightItem aWeightItem( WEIGHT_DONTKNOW, EE_CHAR_WEIGHT );
+ aTemp <<= rDesc.Weight;
+ static_cast<SfxPoolItem*>(&aWeightItem)->PutValue( aTemp, MID_WEIGHT );
+ rSet.Put( aWeightItem );
+ }
+
+ {
+ SvxCrossedOutItem aCrossedOutItem( STRIKEOUT_NONE, EE_CHAR_STRIKEOUT );
+ aTemp <<= rDesc.Strikeout;
+ static_cast<SfxPoolItem*>(&aCrossedOutItem)->PutValue( aTemp, MID_CROSS_OUT );
+ rSet.Put( aCrossedOutItem );
+ }
+
+ {
+ SvxWordLineModeItem aWLMItem( rDesc.WordLineMode, EE_CHAR_WLM );
+ rSet.Put( aWLMItem );
+ }
+}
+
+void SvxUnoFontDescriptor::FillFromItemSet( const SfxItemSet& rSet, awt::FontDescriptor& rDesc )
+{
+ const SfxPoolItem* pItem = nullptr;
+ {
+ const SvxFontItem* pFontItem = &rSet.Get( EE_CHAR_FONTINFO );
+ rDesc.Name = pFontItem->GetFamilyName();
+ rDesc.StyleName = pFontItem->GetStyleName();
+ rDesc.Family = sal::static_int_cast< sal_Int16 >(
+ pFontItem->GetFamily());
+ rDesc.CharSet = pFontItem->GetCharSet();
+ rDesc.Pitch = sal::static_int_cast< sal_Int16 >(
+ pFontItem->GetPitch());
+ }
+ {
+ pItem = &rSet.Get( EE_CHAR_FONTHEIGHT );
+ uno::Any aHeight;
+ if( pItem->QueryValue( aHeight, MID_FONTHEIGHT ) )
+ aHeight >>= rDesc.Height;
+ }
+ {
+ pItem = &rSet.Get( EE_CHAR_ITALIC );
+ uno::Any aFontSlant;
+ if(pItem->QueryValue( aFontSlant, MID_POSTURE ))
+ aFontSlant >>= rDesc.Slant;
+ }
+ {
+ pItem = &rSet.Get( EE_CHAR_UNDERLINE );
+ uno::Any aUnderline;
+ if(pItem->QueryValue( aUnderline, MID_TL_STYLE ))
+ aUnderline >>= rDesc.Underline;
+ }
+ {
+ pItem = &rSet.Get( EE_CHAR_WEIGHT );
+ uno::Any aWeight;
+ if(pItem->QueryValue( aWeight, MID_WEIGHT ))
+ aWeight >>= rDesc.Weight;
+ }
+ {
+ pItem = &rSet.Get( EE_CHAR_STRIKEOUT );
+ uno::Any aStrikeOut;
+ if(pItem->QueryValue( aStrikeOut, MID_CROSS_OUT ))
+ aStrikeOut >>= rDesc.Strikeout;
+ }
+ {
+ const SvxWordLineModeItem* pWLMItem = &rSet.Get( EE_CHAR_WLM );
+ rDesc.WordLineMode = pWLMItem->GetValue();
+ }
+}
+
+void SvxUnoFontDescriptor::setPropertyToDefault( SfxItemSet& rSet )
+{
+ rSet.InvalidateItem( EE_CHAR_FONTINFO );
+ rSet.InvalidateItem( EE_CHAR_FONTHEIGHT );
+ rSet.InvalidateItem( EE_CHAR_ITALIC );
+ rSet.InvalidateItem( EE_CHAR_UNDERLINE );
+ rSet.InvalidateItem( EE_CHAR_WEIGHT );
+ rSet.InvalidateItem( EE_CHAR_STRIKEOUT );
+ rSet.InvalidateItem( EE_CHAR_WLM );
+}
+
+uno::Any SvxUnoFontDescriptor::getPropertyDefault( SfxItemPool* pPool )
+{
+ SfxItemSetFixed<
+ EE_CHAR_FONTINFO, EE_CHAR_FONTHEIGHT,
+ EE_CHAR_WEIGHT, EE_CHAR_ITALIC,
+ EE_CHAR_WLM, EE_CHAR_WLM> aSet(*pPool);
+
+ uno::Any aAny;
+
+ if(!SfxItemPool::IsWhich(EE_CHAR_FONTINFO)||
+ !SfxItemPool::IsWhich(EE_CHAR_FONTHEIGHT)||
+ !SfxItemPool::IsWhich(EE_CHAR_ITALIC)||
+ !SfxItemPool::IsWhich(EE_CHAR_UNDERLINE)||
+ !SfxItemPool::IsWhich(EE_CHAR_WEIGHT)||
+ !SfxItemPool::IsWhich(EE_CHAR_STRIKEOUT)||
+ !SfxItemPool::IsWhich(EE_CHAR_WLM))
+ return aAny;
+
+ aSet.Put(pPool->GetDefaultItem(EE_CHAR_FONTINFO));
+ aSet.Put(pPool->GetDefaultItem(EE_CHAR_FONTHEIGHT));
+ aSet.Put(pPool->GetDefaultItem(EE_CHAR_ITALIC));
+ aSet.Put(pPool->GetDefaultItem(EE_CHAR_UNDERLINE));
+ aSet.Put(pPool->GetDefaultItem(EE_CHAR_WEIGHT));
+ aSet.Put(pPool->GetDefaultItem(EE_CHAR_STRIKEOUT));
+ aSet.Put(pPool->GetDefaultItem(EE_CHAR_WLM));
+
+ awt::FontDescriptor aDesc;
+
+ FillFromItemSet( aSet, aDesc );
+
+ aAny <<= aDesc;
+
+ return aAny;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unofield.cxx b/editeng/source/uno/unofield.cxx
new file mode 100644
index 0000000000..6f2e84a957
--- /dev/null
+++ b/editeng/source/uno/unofield.cxx
@@ -0,0 +1,941 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/text/FilenameDisplayFormat.hpp>
+#include <o3tl/string_view.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <tools/debug.hxx>
+#include <svl/itemprop.hxx>
+
+#include <editeng/flditem.hxx>
+#include <editeng/CustomPropertyField.hxx>
+#include <editeng/measfld.hxx>
+#include <editeng/unofield.hxx>
+#include <editeng/unotext.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+
+#include <editeng/unonames.hxx>
+
+using namespace ::cppu;
+using namespace ::com::sun::star;
+
+#define QUERYINT( xint ) \
+ if( rType == cppu::UnoType<xint>::get() ) \
+ aAny <<= uno::Reference< xint >(this)
+
+
+#define WID_DATE 0
+#define WID_BOOL1 1
+#define WID_BOOL2 2
+#define WID_INT32 3
+#define WID_INT16 4
+#define WID_STRING1 5
+#define WID_STRING2 6
+#define WID_STRING3 7
+
+class SvxUnoFieldData_Impl
+{
+public:
+ bool mbBoolean1;
+ bool mbBoolean2;
+ sal_Int32 mnInt32;
+ sal_Int16 mnInt16;
+ OUString msString1;
+ OUString msString2;
+ OUString msString3;
+ util::DateTime maDateTime;
+
+ OUString msPresentation;
+};
+
+static const SfxItemPropertySet* ImplGetFieldItemPropertySet( sal_Int32 mnId )
+{
+ static const SfxItemPropertyMapEntry aExDateTimeFieldPropertyMap_Impl[] =
+ {
+ { UNO_TC_PROP_DATE_TIME, WID_DATE, ::cppu::UnoType<util::DateTime>::get(), 0, 0 },
+ { UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 },
+ { UNO_TC_PROP_IS_DATE, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 },
+ { UNO_TC_PROP_NUMFORMAT, WID_INT32, ::cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ };
+ static const SfxItemPropertySet aExDateTimeFieldPropertySet_Impl(aExDateTimeFieldPropertyMap_Impl);
+
+ static const SfxItemPropertyMapEntry aDateTimeFieldPropertyMap_Impl[] =
+ {
+ { UNO_TC_PROP_IS_DATE, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 },
+ };
+ static const SfxItemPropertySet aDateTimeFieldPropertySet_Impl(aDateTimeFieldPropertyMap_Impl);
+
+ static const SfxItemPropertyMapEntry aUrlFieldPropertyMap_Impl[] =
+ {
+ { UNO_TC_PROP_URL_FORMAT, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { UNO_TC_PROP_URL_REPRESENTATION, WID_STRING1, ::cppu::UnoType<OUString>::get(), 0, 0 },
+ { UNO_TC_PROP_URL_TARGET, WID_STRING2, ::cppu::UnoType<OUString>::get(), 0, 0 },
+ { UNO_TC_PROP_URL, WID_STRING3, ::cppu::UnoType<OUString>::get(), 0, 0 },
+ };
+ static const SfxItemPropertySet aUrlFieldPropertySet_Impl(aUrlFieldPropertyMap_Impl);
+
+ static const SfxItemPropertySet aEmptyPropertySet_Impl({});
+
+ static const SfxItemPropertyMapEntry aExtFileFieldPropertyMap_Impl[] =
+ {
+ { UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 },
+ { UNO_TC_PROP_FILE_FORMAT, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { UNO_TC_PROP_CURRENT_PRESENTATION, WID_STRING1, ::cppu::UnoType<OUString>::get(), 0, 0 },
+ };
+ static const SfxItemPropertySet aExtFileFieldPropertySet_Impl(aExtFileFieldPropertyMap_Impl);
+
+ static const SfxItemPropertyMapEntry aAuthorFieldPropertyMap_Impl[] =
+ {
+ { UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 },
+ { UNO_TC_PROP_CURRENT_PRESENTATION, WID_STRING1,::cppu::UnoType<OUString>::get(), 0, 0 },
+ { UNO_TC_PROP_AUTHOR_CONTENT, WID_STRING2,::cppu::UnoType<OUString>::get(), 0, 0 },
+ { UNO_TC_PROP_AUTHOR_FORMAT, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ { UNO_TC_PROP_AUTHOR_FULLNAME, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 },
+ };
+ static const SfxItemPropertySet aAuthorFieldPropertySet_Impl(aAuthorFieldPropertyMap_Impl);
+
+ static const SfxItemPropertyMapEntry aMeasureFieldPropertyMap_Impl[] =
+ {
+ { UNO_TC_PROP_MEASURE_KIND, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 },
+ };
+ static const SfxItemPropertySet aMeasureFieldPropertySet_Impl(aMeasureFieldPropertyMap_Impl);
+
+ static const SfxItemPropertyMapEntry aDocInfoCustomFieldPropertyMap_Impl[] =
+ {
+ { UNO_TC_PROP_NAME, WID_STRING1, cppu::UnoType<OUString>::get(), 0, 0 },
+ { UNO_TC_PROP_CURRENT_PRESENTATION, WID_STRING2, cppu::UnoType<OUString>::get(), 0, 0 },
+ { UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 },
+ { UNO_TC_PROP_NUMFORMAT, WID_INT32, cppu::UnoType<sal_Int32>::get(), 0, 0 },
+ { UNO_TC_PROP_IS_FIXED_LANGUAGE, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 },
+ };
+ static const SfxItemPropertySet aDocInfoCustomFieldPropertySet_Impl(aDocInfoCustomFieldPropertyMap_Impl);
+
+ switch( mnId )
+ {
+ case text::textfield::Type::EXTENDED_TIME:
+ case text::textfield::Type::DATE:
+ return &aExDateTimeFieldPropertySet_Impl;
+ case text::textfield::Type::URL:
+ return &aUrlFieldPropertySet_Impl;
+ case text::textfield::Type::TIME:
+ return &aDateTimeFieldPropertySet_Impl;
+ case text::textfield::Type::EXTENDED_FILE:
+ return &aExtFileFieldPropertySet_Impl;
+ case text::textfield::Type::AUTHOR:
+ return &aAuthorFieldPropertySet_Impl;
+ case text::textfield::Type::MEASURE:
+ return &aMeasureFieldPropertySet_Impl;
+ case text::textfield::Type::DOCINFO_CUSTOM:
+ return &aDocInfoCustomFieldPropertySet_Impl;
+ default:
+ return &aEmptyPropertySet_Impl;
+ }
+}
+
+/* conversion routines */
+
+static sal_Int16 getFileNameDisplayFormat( SvxFileFormat nFormat )
+{
+ switch( nFormat )
+ {
+ case SvxFileFormat::NameAndExt: return text::FilenameDisplayFormat::NAME_AND_EXT;
+ case SvxFileFormat::PathFull: return text::FilenameDisplayFormat::FULL;
+ case SvxFileFormat::PathOnly: return text::FilenameDisplayFormat::PATH;
+// case SvxFileFormat::NameOnly:
+ default: return text::FilenameDisplayFormat::NAME;
+ }
+}
+
+static SvxFileFormat setFileNameDisplayFormat( sal_Int16 nFormat )
+{
+ switch( nFormat )
+ {
+ case text::FilenameDisplayFormat::FULL: return SvxFileFormat::PathFull;
+ case text::FilenameDisplayFormat::PATH: return SvxFileFormat::PathOnly;
+ case text::FilenameDisplayFormat::NAME: return SvxFileFormat::NameOnly;
+// case text::FilenameDisplayFormat::NAME_AND_EXT:
+ default:
+ return SvxFileFormat::NameAndExt;
+ }
+}
+
+static util::DateTime getDate( sal_Int32 nDate )
+{
+ util::DateTime aDate;
+
+ Date aTempDate( nDate );
+
+ aDate.Day = aTempDate.GetDay();
+ aDate.Month = aTempDate.GetMonth();
+ aDate.Year = aTempDate.GetYear();
+
+ return aDate;
+}
+
+static Date setDate( util::DateTime const & rDate )
+{
+ return Date( rDate.Day, rDate.Month, rDate.Year );
+}
+
+static util::DateTime getTime(sal_Int64 const nTime)
+{
+ util::DateTime aTime;
+
+ tools::Time aTempTime( nTime );
+
+ aTime.NanoSeconds = aTempTime.GetNanoSec();
+ aTime.Seconds = aTempTime.GetSec();
+ aTime.Minutes = aTempTime.GetMin();
+ aTime.Hours = aTempTime.GetHour();
+
+ return aTime;
+}
+
+static tools::Time setTime( util::DateTime const & rDate )
+{
+ return tools::Time( rDate );
+}
+
+
+
+SvxUnoTextField::SvxUnoTextField( sal_Int32 nServiceId ) noexcept
+: OComponentHelper( m_aMutex )
+, mpPropSet(nullptr)
+, mnServiceId(nServiceId)
+, mpImpl( new SvxUnoFieldData_Impl )
+{
+ mpPropSet = ImplGetFieldItemPropertySet(mnServiceId);
+
+ mpImpl->maDateTime.NanoSeconds = 0;
+ mpImpl->maDateTime.Seconds = 0;
+ mpImpl->maDateTime.Minutes = 0;
+ mpImpl->maDateTime.Hours = 0;
+ mpImpl->maDateTime.Day = 0;
+ mpImpl->maDateTime.Month = 0;
+ mpImpl->maDateTime.Year = 0;
+ mpImpl->maDateTime.IsUTC = false;
+
+ switch( nServiceId )
+ {
+ case text::textfield::Type::DATE:
+ mpImpl->mbBoolean2 = true;
+ mpImpl->mnInt32 = static_cast<sal_Int32>(SvxDateFormat::StdSmall);
+ mpImpl->mbBoolean1 = false;
+ break;
+
+ case text::textfield::Type::EXTENDED_TIME:
+ case text::textfield::Type::TIME:
+ mpImpl->mbBoolean2 = false;
+ mpImpl->mbBoolean1 = false;
+ mpImpl->mnInt32 = static_cast<sal_Int32>(SvxTimeFormat::Standard);
+ break;
+
+ case text::textfield::Type::URL:
+ mpImpl->mnInt16 = static_cast<sal_uInt16>(SvxURLFormat::Repr);
+ break;
+
+ case text::textfield::Type::EXTENDED_FILE:
+ mpImpl->mbBoolean1 = false;
+ mpImpl->mnInt16 = text::FilenameDisplayFormat::FULL;
+ break;
+
+ case text::textfield::Type::AUTHOR:
+ mpImpl->mnInt16 = static_cast<sal_uInt16>(SvxAuthorFormat::FullName);
+ mpImpl->mbBoolean1 = false;
+ mpImpl->mbBoolean2 = true;
+ break;
+
+ case text::textfield::Type::MEASURE:
+ mpImpl->mnInt16 = static_cast<sal_uInt16>(SdrMeasureFieldKind::Value);
+ break;
+
+ case text::textfield::Type::DOCINFO_CUSTOM:
+ mpImpl->mbBoolean1 = true;
+ mpImpl->mbBoolean2 = true;
+ mpImpl->mnInt32 = 0;
+ break;
+
+ default:
+ mpImpl->mbBoolean1 = false;
+ mpImpl->mbBoolean2 = false;
+ mpImpl->mnInt32 = 0;
+ mpImpl->mnInt16 = 0;
+
+ }
+}
+
+SvxUnoTextField::SvxUnoTextField( uno::Reference< text::XTextRange > xAnchor, const OUString& rPresentation, const SvxFieldData* pData ) noexcept
+: OComponentHelper( m_aMutex )
+, mxAnchor(std::move( xAnchor ))
+, mpPropSet(nullptr)
+, mnServiceId(text::textfield::Type::UNSPECIFIED)
+, mpImpl( new SvxUnoFieldData_Impl )
+{
+ DBG_ASSERT(pData, "pFieldData == NULL! [CL]" );
+
+ mpImpl->msPresentation = rPresentation;
+
+ if(pData)
+ {
+ mnServiceId = pData->GetClassId();
+ DBG_ASSERT(mnServiceId != text::textfield::Type::UNSPECIFIED, "unknown SvxFieldData! [CL]");
+ if (mnServiceId != text::textfield::Type::UNSPECIFIED)
+ {
+ // extract field properties from data class
+ switch( mnServiceId )
+ {
+ case text::textfield::Type::DATE:
+ {
+ mpImpl->mbBoolean2 = true;
+ // #i35416# for variable date field, don't use invalid "0000-00-00" date,
+ // use current date instead
+ bool bFixed = static_cast<const SvxDateField*>(pData)->GetType() == SvxDateType::Fix;
+ mpImpl->maDateTime = getDate( bFixed ?
+ static_cast<const SvxDateField*>(pData)->GetFixDate() :
+ Date( Date::SYSTEM ).GetDate() );
+ mpImpl->mnInt32 = static_cast<sal_Int32>(static_cast<const SvxDateField*>(pData)->GetFormat());
+ mpImpl->mbBoolean1 = bFixed;
+ }
+ break;
+
+ case text::textfield::Type::TIME:
+ mpImpl->mbBoolean2 = false;
+ mpImpl->mbBoolean1 = false;
+ mpImpl->mnInt32 = static_cast<sal_Int32>(SvxTimeFormat::Standard);
+ break;
+
+ case text::textfield::Type::EXTENDED_TIME:
+ mpImpl->mbBoolean2 = false;
+ mpImpl->maDateTime = getTime( static_cast<const SvxExtTimeField*>(pData)->GetFixTime() );
+ mpImpl->mbBoolean1 = static_cast<const SvxExtTimeField*>(pData)->GetType() == SvxTimeType::Fix;
+ mpImpl->mnInt32 = static_cast<sal_Int32>(static_cast<const SvxExtTimeField*>(pData)->GetFormat());
+ break;
+
+ case text::textfield::Type::URL:
+ mpImpl->msString1 = static_cast<const SvxURLField*>(pData)->GetRepresentation();
+ mpImpl->msString2 = static_cast<const SvxURLField*>(pData)->GetTargetFrame();
+ mpImpl->msString3 = static_cast<const SvxURLField*>(pData)->GetURL();
+ mpImpl->mnInt16 = sal::static_int_cast< sal_Int16 >(
+ static_cast<const SvxURLField*>(pData)->GetFormat());
+ break;
+
+ case text::textfield::Type::EXTENDED_FILE:
+ mpImpl->msString1 = static_cast<const SvxExtFileField*>(pData)->GetFile();
+ mpImpl->mbBoolean1 = static_cast<const SvxExtFileField*>(pData)->GetType() == SvxFileType::Fix;
+ mpImpl->mnInt16 = getFileNameDisplayFormat(static_cast<const SvxExtFileField*>(pData)->GetFormat());
+ break;
+
+ case text::textfield::Type::AUTHOR:
+ mpImpl->msString1 = static_cast<const SvxAuthorField*>(pData)->GetFormatted();
+ mpImpl->msString2 = static_cast<const SvxAuthorField*>(pData)->GetFormatted();
+ mpImpl->mnInt16 = sal::static_int_cast< sal_Int16 >(
+ static_cast<const SvxAuthorField*>(pData)->GetFormat());
+ mpImpl->mbBoolean1 = static_cast<const SvxAuthorField*>(pData)->GetType() == SvxAuthorType::Fix;
+ mpImpl->mbBoolean2 = static_cast<const SvxAuthorField*>(pData)->GetFormat() != SvxAuthorFormat::ShortName;
+ break;
+
+ case text::textfield::Type::MEASURE:
+ mpImpl->mnInt16 = sal::static_int_cast< sal_Int16 >(static_cast<const SdrMeasureField*>(pData)->GetMeasureFieldKind());
+ break;
+
+ case text::textfield::Type::DOCINFO_CUSTOM:
+ mpImpl->msString1 = static_cast<const editeng::CustomPropertyField*>(pData)->GetName();
+ mpImpl->msString2 = static_cast<const editeng::CustomPropertyField*>(pData)->GetCurrentPresentation();
+ mpImpl->mbBoolean1 = false;
+ mpImpl->mbBoolean2 = false;
+ mpImpl->mnInt32 = 0;
+ break;
+
+ default:
+ SAL_INFO("editeng", "Id service unknown: " << mnServiceId);
+ break;
+ }
+ }
+ }
+
+ mpPropSet = ImplGetFieldItemPropertySet(mnServiceId);
+}
+
+SvxUnoTextField::~SvxUnoTextField() noexcept
+{
+}
+
+std::unique_ptr<SvxFieldData> SvxUnoTextField::CreateFieldData() const noexcept
+{
+ std::unique_ptr<SvxFieldData> pData;
+
+ switch( mnServiceId )
+ {
+ case text::textfield::Type::TIME:
+ case text::textfield::Type::EXTENDED_TIME:
+ case text::textfield::Type::DATE:
+ {
+ if( mpImpl->mbBoolean2 ) // IsDate?
+ {
+ Date aDate( setDate( mpImpl->maDateTime ) );
+ pData.reset( new SvxDateField( aDate, mpImpl->mbBoolean1?SvxDateType::Fix:SvxDateType::Var ) );
+ if( mpImpl->mnInt32 >= static_cast<sal_Int32>(SvxDateFormat::AppDefault) &&
+ mpImpl->mnInt32 <= static_cast<sal_Int32>(SvxDateFormat::F) )
+ static_cast<SvxDateField*>(pData.get())->SetFormat( static_cast<SvxDateFormat>(mpImpl->mnInt32) );
+ }
+ else
+ {
+ if( mnServiceId != text::textfield::Type::TIME && mnServiceId != text::textfield::Type::DATE )
+ {
+ tools::Time aTime( setTime( mpImpl->maDateTime ) );
+ pData.reset( new SvxExtTimeField( aTime, mpImpl->mbBoolean1?SvxTimeType::Fix:SvxTimeType::Var ) );
+
+ if( static_cast<SvxTimeFormat>(mpImpl->mnInt32) >= SvxTimeFormat::AppDefault &&
+ static_cast<SvxTimeFormat>(mpImpl->mnInt32) <= SvxTimeFormat::HH12_MM_SS_00_AMPM )
+ static_cast<SvxExtTimeField*>(pData.get())->SetFormat( static_cast<SvxTimeFormat>(mpImpl->mnInt32) );
+ }
+ else
+ {
+ pData.reset( new SvxTimeField() );
+ }
+ }
+
+ }
+ break;
+
+ case text::textfield::Type::URL:
+ pData.reset( new SvxURLField( mpImpl->msString3, mpImpl->msString1, !mpImpl->msString1.isEmpty() ? SvxURLFormat::Repr : SvxURLFormat::Url ) );
+ static_cast<SvxURLField*>(pData.get())->SetTargetFrame( mpImpl->msString2 );
+ if( static_cast<SvxURLFormat>(mpImpl->mnInt16) >= SvxURLFormat::AppDefault &&
+ static_cast<SvxURLFormat>(mpImpl->mnInt16) <= SvxURLFormat::Repr )
+ static_cast<SvxURLField*>(pData.get())->SetFormat( static_cast<SvxURLFormat>(mpImpl->mnInt16) );
+ break;
+
+ case text::textfield::Type::PAGE:
+ pData.reset( new SvxPageField() );
+ break;
+
+ case text::textfield::Type::PAGES:
+ pData.reset( new SvxPagesField() );
+ break;
+
+ case text::textfield::Type::DOCINFO_TITLE:
+ pData.reset( new SvxFileField() );
+ break;
+
+ case text::textfield::Type::TABLE:
+ pData.reset( new SvxTableField() );
+ break;
+
+ case text::textfield::Type::EXTENDED_FILE:
+ {
+ // #92009# pass fixed attribute to constructor
+ pData.reset( new SvxExtFileField( mpImpl->msString1,
+ mpImpl->mbBoolean1 ? SvxFileType::Fix : SvxFileType::Var,
+ setFileNameDisplayFormat(mpImpl->mnInt16 ) ) );
+ break;
+ }
+
+ case text::textfield::Type::AUTHOR:
+ {
+ OUString aContent;
+ OUString aFirstName;
+ OUString aLastName;
+
+ // do we have CurrentPresentation given?
+ // mimic behaviour of writer, which means:
+ // prefer CurrentPresentation over Content
+ // if both are given.
+ if( !mpImpl->msString1.isEmpty() )
+ aContent = mpImpl->msString1;
+ else
+ aContent = mpImpl->msString2;
+
+ sal_Int32 nPos = aContent.lastIndexOf( ' ', 0 );
+ if( nPos > 0 )
+ {
+ aFirstName = aContent.copy( 0, nPos );
+ aLastName = aContent.copy( nPos + 1 );
+ }
+ else
+ {
+ aLastName = aContent;
+ }
+
+ // #92009# pass fixed attribute to constructor
+ pData.reset( new SvxAuthorField( aFirstName, aLastName, "",
+ mpImpl->mbBoolean1 ? SvxAuthorType::Fix : SvxAuthorType::Var ) );
+
+ if( !mpImpl->mbBoolean2 )
+ {
+ static_cast<SvxAuthorField*>(pData.get())->SetFormat( SvxAuthorFormat::ShortName );
+ }
+ else if( static_cast<SvxAuthorFormat>(mpImpl->mnInt16) >= SvxAuthorFormat::FullName &&
+ static_cast<SvxAuthorFormat>(mpImpl->mnInt16) <= SvxAuthorFormat::ShortName )
+ {
+ static_cast<SvxAuthorField*>(pData.get())->SetFormat( static_cast<SvxAuthorFormat>(mpImpl->mnInt16) );
+ }
+
+ break;
+ }
+
+ case text::textfield::Type::MEASURE:
+ {
+ SdrMeasureFieldKind eKind = SdrMeasureFieldKind::Value;
+ if( mpImpl->mnInt16 == sal_Int16(SdrMeasureFieldKind::Unit) || mpImpl->mnInt16 == sal_Int16(SdrMeasureFieldKind::Rotate90Blanks) )
+ eKind = static_cast<SdrMeasureFieldKind>(mpImpl->mnInt16);
+ pData.reset( new SdrMeasureField( eKind) );
+ break;
+ }
+ case text::textfield::Type::PRESENTATION_HEADER:
+ pData.reset( new SvxHeaderField() );
+ break;
+ case text::textfield::Type::PRESENTATION_FOOTER:
+ pData.reset( new SvxFooterField() );
+ break;
+ case text::textfield::Type::PRESENTATION_DATE_TIME:
+ pData.reset( new SvxDateTimeField() );
+ break;
+ case text::textfield::Type::PAGE_NAME:
+ pData.reset( new SvxPageTitleField() );
+ break;
+ case text::textfield::Type::DOCINFO_CUSTOM:
+ pData.reset( new editeng::CustomPropertyField(mpImpl->msString1, mpImpl->msString2) );
+ break;
+ }
+
+ return pData;
+}
+
+// uno::XInterface
+uno::Any SAL_CALL SvxUnoTextField::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aAny;
+
+ QUERYINT( beans::XPropertySet );
+ else QUERYINT( text::XTextContent );
+ else QUERYINT( text::XTextField );
+ else QUERYINT( lang::XServiceInfo );
+ else
+ return OComponentHelper::queryAggregation( rType );
+
+ return aAny;
+}
+
+// XTypeProvider
+
+uno::Sequence< uno::Type > SAL_CALL SvxUnoTextField::getTypes()
+{
+ if( !maTypeSequence.hasElements() )
+ {
+ maTypeSequence = comphelper::concatSequences(
+ OComponentHelper::getTypes(),
+ uno::Sequence {
+ cppu::UnoType<text::XTextField>::get(),
+ cppu::UnoType<beans::XPropertySet>::get(),
+ cppu::UnoType<lang::XServiceInfo>::get(),
+ cppu::UnoType<lang::XUnoTunnel>::get() });
+ }
+ return maTypeSequence;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SvxUnoTextField::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+uno::Any SAL_CALL SvxUnoTextField::queryInterface( const uno::Type & rType )
+{
+ return OComponentHelper::queryInterface(rType);
+}
+
+void SAL_CALL SvxUnoTextField::acquire() noexcept
+{
+ OComponentHelper::acquire();
+}
+
+void SAL_CALL SvxUnoTextField::release() noexcept
+{
+ OComponentHelper::release();
+}
+
+// Interface text::XTextField
+OUString SAL_CALL SvxUnoTextField::getPresentation( sal_Bool bShowCommand )
+{
+ SolarMutexGuard aGuard;
+ if (bShowCommand)
+ {
+ switch (mnServiceId)
+ {
+ case text::textfield::Type::DATE:
+ return "Date";
+ case text::textfield::Type::URL:
+ return "URL";
+ case text::textfield::Type::PAGE:
+ return "Page";
+ case text::textfield::Type::PAGES:
+ return "Pages";
+ case text::textfield::Type::TIME:
+ return "Time";
+ case text::textfield::Type::DOCINFO_TITLE:
+ return "File";
+ case text::textfield::Type::TABLE:
+ return "Table";
+ case text::textfield::Type::EXTENDED_TIME:
+ return "ExtTime";
+ case text::textfield::Type::EXTENDED_FILE:
+ return "ExtFile";
+ case text::textfield::Type::AUTHOR:
+ return "Author";
+ case text::textfield::Type::MEASURE:
+ return "Measure";
+ case text::textfield::Type::PRESENTATION_HEADER:
+ return "Header";
+ case text::textfield::Type::PRESENTATION_FOOTER:
+ return "Footer";
+ case text::textfield::Type::PRESENTATION_DATE_TIME:
+ return "DateTime";
+ case text::textfield::Type::PAGE_NAME:
+ return "PageName";
+ case text::textfield::Type::DOCINFO_CUSTOM:
+ return "Custom";
+ default:
+ return "Unknown";
+ }
+ }
+ else
+ {
+ return mpImpl->msPresentation;
+ }
+}
+
+// Interface text::XTextContent
+void SAL_CALL SvxUnoTextField::attach( const uno::Reference< text::XTextRange >& xTextRange )
+{
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xTextRange );
+ if(pRange == nullptr)
+ throw lang::IllegalArgumentException();
+
+ std::unique_ptr<SvxFieldData> pData = CreateFieldData();
+ if( pData )
+ pRange->attachField( std::move(pData) );
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextField::getAnchor()
+{
+ return mxAnchor;
+}
+
+// lang::XComponent
+void SAL_CALL SvxUnoTextField::dispose()
+{
+ OComponentHelper::dispose();
+ mxAnchor.clear();
+}
+
+void SAL_CALL SvxUnoTextField::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
+{
+ OComponentHelper::addEventListener(xListener);
+}
+
+void SAL_CALL SvxUnoTextField::removeEventListener( const uno::Reference< lang::XEventListener >& aListener )
+{
+ OComponentHelper::removeEventListener(aListener);
+}
+
+
+// Interface beans::XPropertySet
+uno::Reference< beans::XPropertySetInfo > SAL_CALL SvxUnoTextField::getPropertySetInfo( )
+{
+ SolarMutexGuard aGuard;
+ return mpPropSet->getPropertySetInfo();
+}
+
+void SAL_CALL SvxUnoTextField::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpImpl == nullptr )
+ throw uno::RuntimeException();
+
+ if (aPropertyName == UNO_TC_PROP_ANCHOR)
+ {
+ aValue >>= mxAnchor;
+ return;
+ }
+
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMap().getByName( aPropertyName );
+ if ( !pMap )
+ throw beans::UnknownPropertyException(aPropertyName);
+
+ switch( pMap->nWID )
+ {
+ case WID_DATE:
+ if(aValue >>= mpImpl->maDateTime)
+ return;
+ break;
+ case WID_BOOL1:
+ if(aValue >>= mpImpl->mbBoolean1)
+ return;
+ break;
+ case WID_BOOL2:
+ if(aValue >>= mpImpl->mbBoolean2)
+ return;
+ break;
+ case WID_INT16:
+ if(aValue >>= mpImpl->mnInt16)
+ return;
+ break;
+ case WID_INT32:
+ if(aValue >>= mpImpl->mnInt32)
+ return;
+ break;
+ case WID_STRING1:
+ if(aValue >>= mpImpl->msString1)
+ return;
+ break;
+ case WID_STRING2:
+ if(aValue >>= mpImpl->msString2)
+ return;
+ break;
+ case WID_STRING3:
+ if(aValue >>= mpImpl->msString3)
+ return;
+ break;
+ }
+
+ throw lang::IllegalArgumentException();
+}
+
+uno::Any SAL_CALL SvxUnoTextField::getPropertyValue( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ if (PropertyName == UNO_TC_PROP_ANCHOR)
+ return uno::Any(mxAnchor);
+
+ if (PropertyName == UNO_TC_PROP_TEXTFIELD_TYPE)
+ return uno::Any(mnServiceId);
+
+ uno::Any aValue;
+
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMap().getByName( PropertyName );
+ if ( !pMap )
+ throw beans::UnknownPropertyException(PropertyName);
+
+ switch( pMap->nWID )
+ {
+ case WID_DATE:
+ aValue <<= mpImpl->maDateTime;
+ break;
+ case WID_BOOL1:
+ aValue <<= mpImpl->mbBoolean1;
+ break;
+ case WID_BOOL2:
+ aValue <<= mpImpl->mbBoolean2;
+ break;
+ case WID_INT16:
+ aValue <<= mpImpl->mnInt16;
+ break;
+ case WID_INT32:
+ aValue <<= mpImpl->mnInt32;
+ break;
+ case WID_STRING1:
+ aValue <<= mpImpl->msString1;
+ break;
+ case WID_STRING2:
+ aValue <<= mpImpl->msString2;
+ break;
+ case WID_STRING3:
+ aValue <<= mpImpl->msString3;
+ break;
+ }
+
+ return aValue;
+}
+
+void SAL_CALL SvxUnoTextField::addPropertyChangeListener( const OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) {}
+void SAL_CALL SvxUnoTextField::removePropertyChangeListener( const OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) {}
+void SAL_CALL SvxUnoTextField::addVetoableChangeListener( const OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) {}
+void SAL_CALL SvxUnoTextField::removeVetoableChangeListener( const OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) {}
+
+// OComponentHelper
+void SvxUnoTextField::disposing()
+{
+ // nothing to do
+}
+
+// lang::XServiceInfo
+OUString SAL_CALL SvxUnoTextField::getImplementationName()
+{
+ return "SvxUnoTextField";
+}
+
+uno::Sequence< OUString > SAL_CALL SvxUnoTextField::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aSeq(4);
+ OUString* pServices = aSeq.getArray();
+ pServices[0] = "com.sun.star.text.TextContent";
+ pServices[1] = "com.sun.star.text.TextField";
+
+ switch (mnServiceId)
+ {
+ case text::textfield::Type::DATE:
+ pServices[2] = "com.sun.star.text.TextField.DateTime";
+ pServices[3] = "com.sun.star.text.textfield.DateTime";
+ break;
+ case text::textfield::Type::URL:
+ pServices[2] = "com.sun.star.text.TextField.URL";
+ pServices[3] = "com.sun.star.text.textfield.URL";
+ break;
+ case text::textfield::Type::PAGE:
+ pServices[2] = "com.sun.star.text.TextField.PageNumber";
+ pServices[3] = "com.sun.star.text.textfield.PageNumber";
+ break;
+ case text::textfield::Type::PAGES:
+ pServices[2] = "com.sun.star.text.TextField.PageCount";
+ pServices[3] = "com.sun.star.text.textfield.PageCount";
+ break;
+ case text::textfield::Type::TIME:
+ pServices[2] = "com.sun.star.text.TextField.DateTime";
+ pServices[3] = "com.sun.star.text.textfield.DateTime";
+ break;
+ case text::textfield::Type::DOCINFO_TITLE:
+ pServices[2] = "com.sun.star.text.TextField.docinfo.Title";
+ pServices[3] = "com.sun.star.text.textfield.docinfo.Title";
+ break;
+ case text::textfield::Type::TABLE:
+ pServices[2] = "com.sun.star.text.TextField.SheetName";
+ pServices[3] = "com.sun.star.text.textfield.SheetName";
+ break;
+ case text::textfield::Type::EXTENDED_TIME:
+ pServices[2] = "com.sun.star.text.TextField.DateTime";
+ pServices[3] = "com.sun.star.text.textfield.DateTime";
+ break;
+ case text::textfield::Type::EXTENDED_FILE:
+ pServices[2] = "com.sun.star.text.TextField.FileName";
+ pServices[3] = "com.sun.star.text.textfield.FileName";
+ break;
+ case text::textfield::Type::AUTHOR:
+ pServices[2] = "com.sun.star.text.TextField.Author";
+ pServices[3] = "com.sun.star.text.textfield.Author";
+ break;
+ case text::textfield::Type::MEASURE:
+ pServices[2] = "com.sun.star.text.TextField.Measure";
+ pServices[3] = "com.sun.star.text.textfield.Measure";
+ break;
+ case text::textfield::Type::PRESENTATION_HEADER:
+ pServices[2] = "com.sun.star.presentation.TextField.Header";
+ pServices[3] = "com.sun.star.presentation.textfield.Header";
+ break;
+ case text::textfield::Type::PRESENTATION_FOOTER:
+ pServices[2] = "com.sun.star.presentation.TextField.Footer";
+ pServices[3] = "com.sun.star.presentation.textfield.Footer";
+ break;
+ case text::textfield::Type::PRESENTATION_DATE_TIME:
+ pServices[2] = "com.sun.star.presentation.TextField.DateTime";
+ pServices[3] = "com.sun.star.presentation.textfield.DateTime";
+ break;
+ case text::textfield::Type::PAGE_NAME:
+ pServices[2] = "com.sun.star.text.TextField.PageName";
+ pServices[3] = "com.sun.star.text.textfield.PageName";
+ break;
+ case text::textfield::Type::DOCINFO_CUSTOM:
+ pServices[2] = "com.sun.star.text.TextField.DocInfo.Custom";
+ pServices[3] = "com.sun.star.text.textfield.DocInfo.Custom";
+ break;
+ default:
+ aSeq.realloc(0);
+ }
+
+ return aSeq;
+}
+
+sal_Bool SAL_CALL SvxUnoTextField::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+uno::Reference< uno::XInterface > SvxUnoTextCreateTextField( std::u16string_view ServiceSpecifier )
+{
+ uno::Reference< uno::XInterface > xRet;
+
+ // #i93308# up to OOo 3.2 we used this wrong namespace name with the capital T & F. This is
+ // fixed since OOo 3.2 but for compatibility we will still provide support for the wrong notation.
+
+ std::u16string_view aFieldType;
+ if( (o3tl::starts_with( ServiceSpecifier, u"com.sun.star.text.textfield.", &aFieldType )) ||
+ (o3tl::starts_with( ServiceSpecifier, u"com.sun.star.text.TextField.", &aFieldType )) )
+ {
+ sal_Int32 nId = text::textfield::Type::UNSPECIFIED;
+
+ if ( aFieldType == u"DateTime" )
+ {
+ nId = text::textfield::Type::DATE;
+ }
+ else if ( aFieldType == u"URL" )
+ {
+ nId = text::textfield::Type::URL;
+ }
+ else if ( aFieldType == u"PageNumber" )
+ {
+ nId = text::textfield::Type::PAGE;
+ }
+ else if ( aFieldType == u"PageCount" )
+ {
+ nId = text::textfield::Type::PAGES;
+ }
+ else if ( aFieldType == u"SheetName" )
+ {
+ nId = text::textfield::Type::TABLE;
+ }
+ else if ( aFieldType == u"FileName" )
+ {
+ nId = text::textfield::Type::EXTENDED_FILE;
+ }
+ else if (aFieldType == u"docinfo.Title" ||
+ aFieldType == u"DocInfo.Title" )
+ {
+ nId = text::textfield::Type::DOCINFO_TITLE;
+ }
+ else if ( aFieldType == u"Author" )
+ {
+ nId = text::textfield::Type::AUTHOR;
+ }
+ else if ( aFieldType == u"Measure" )
+ {
+ nId = text::textfield::Type::MEASURE;
+ }
+ else if (aFieldType == u"DocInfo.Custom")
+ {
+ nId = text::textfield::Type::DOCINFO_CUSTOM;
+ }
+
+ if (nId != text::textfield::Type::UNSPECIFIED)
+ xRet = getXWeak(new SvxUnoTextField( nId ));
+ }
+
+ return xRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unofored.cxx b/editeng/source/uno/unofored.cxx
new file mode 100644
index 0000000000..66f4fde2bf
--- /dev/null
+++ b/editeng/source/uno/unofored.cxx
@@ -0,0 +1,520 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <osl/diagnose.h>
+#include <tools/debug.hxx>
+#include <editeng/eeitem.hxx>
+#include <com/sun/star/i18n/WordType.hpp>
+
+#include <svl/itemset.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/unoedhlp.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/editobj.hxx>
+
+#include <editeng/unofored.hxx>
+#include "unofored_internal.hxx"
+
+using namespace ::com::sun::star;
+
+
+SvxEditEngineForwarder::SvxEditEngineForwarder( EditEngine& rEngine ) :
+ rEditEngine( rEngine )
+{
+}
+
+SvxEditEngineForwarder::~SvxEditEngineForwarder()
+{
+ // the EditEngine may need to be deleted from the outside
+}
+
+sal_Int32 SvxEditEngineForwarder::GetParagraphCount() const
+{
+ return rEditEngine.GetParagraphCount();
+}
+
+sal_Int32 SvxEditEngineForwarder::GetTextLen( sal_Int32 nParagraph ) const
+{
+ return rEditEngine.GetTextLen( nParagraph );
+}
+
+OUString SvxEditEngineForwarder::GetText( const ESelection& rSel ) const
+{
+ return convertLineEnd(rEditEngine.GetText(rSel), GetSystemLineEnd());
+}
+
+SfxItemSet SvxEditEngineForwarder::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const
+{
+ if( rSel.nStartPara == rSel.nEndPara )
+ {
+ GetAttribsFlags nFlags = GetAttribsFlags::NONE;
+ switch( nOnlyHardAttrib )
+ {
+ case EditEngineAttribs::All:
+ nFlags = GetAttribsFlags::ALL;
+ break;
+ case EditEngineAttribs::OnlyHard:
+ nFlags = GetAttribsFlags::CHARATTRIBS;
+ break;
+ default:
+ OSL_FAIL("unknown flags for SvxOutlinerForwarder::GetAttribs");
+ }
+
+ return rEditEngine.GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
+ }
+ else
+ {
+ return rEditEngine.GetAttribs( rSel, nOnlyHardAttrib );
+ }
+}
+
+SfxItemSet SvxEditEngineForwarder::GetParaAttribs( sal_Int32 nPara ) const
+{
+ SfxItemSet aSet( rEditEngine.GetParaAttribs( nPara ) );
+
+ sal_uInt16 nWhich = EE_PARA_START;
+ while( nWhich <= EE_PARA_END )
+ {
+ if( aSet.GetItemState( nWhich ) != SfxItemState::SET )
+ {
+ if( rEditEngine.HasParaAttrib( nPara, nWhich ) )
+ aSet.Put( rEditEngine.GetParaAttrib( nPara, nWhich ) );
+ }
+ nWhich++;
+ }
+
+ return aSet;
+}
+
+void SvxEditEngineForwarder::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
+{
+ rEditEngine.SetParaAttribs( nPara, rSet );
+}
+
+void SvxEditEngineForwarder::RemoveAttribs( const ESelection& rSelection )
+{
+ rEditEngine.RemoveAttribs( rSelection, false/*bRemoveParaAttribs*/, 0 );
+}
+
+SfxItemPool* SvxEditEngineForwarder::GetPool() const
+{
+ return rEditEngine.GetEmptyItemSet().GetPool();
+}
+
+void SvxEditEngineForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) const
+{
+ rEditEngine.GetPortions( nPara, rList );
+}
+
+OUString SvxEditEngineForwarder::GetStyleSheet(sal_Int32 nPara) const
+{
+ if (auto pStyle = rEditEngine.GetStyleSheet(nPara))
+ return pStyle->GetName();
+ return OUString();
+}
+
+void SvxEditEngineForwarder::SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName)
+{
+ auto pStyleSheetPool = rEditEngine.GetStyleSheetPool();
+ if (auto pStyle = pStyleSheetPool ? pStyleSheetPool->Find(rStyleName, SfxStyleFamily::Para) : nullptr)
+ rEditEngine.SetStyleSheet(nPara, static_cast<SfxStyleSheet*>(pStyle));
+}
+
+void SvxEditEngineForwarder::QuickInsertText( const OUString& rText, const ESelection& rSel )
+{
+ rEditEngine.QuickInsertText( rText, rSel );
+}
+
+void SvxEditEngineForwarder::QuickInsertLineBreak( const ESelection& rSel )
+{
+ rEditEngine.QuickInsertLineBreak( rSel );
+}
+
+void SvxEditEngineForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
+{
+ rEditEngine.QuickInsertField( rFld, rSel );
+}
+
+void SvxEditEngineForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
+{
+ rEditEngine.QuickSetAttribs( rSet, rSel );
+}
+
+bool SvxEditEngineForwarder::IsValid() const
+{
+ // cannot reliably query EditEngine state
+ // while in the middle of an update
+ return rEditEngine.IsUpdateLayout();
+}
+
+OUString SvxEditEngineForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle )
+{
+ return rEditEngine.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle );
+}
+
+void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem& rField )
+{
+ rEditEngine.FieldClicked( rField );
+}
+
+SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ESelection& rSel, sal_uInt16 nWhich )
+{
+ std::vector<EECharAttrib> aAttribs;
+
+ const SfxPoolItem* pLastItem = nullptr;
+
+ SfxItemState eState = SfxItemState::DEFAULT;
+
+ // check all paragraphs inside the selection
+ for( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
+ {
+ SfxItemState eParaState = SfxItemState::DEFAULT;
+
+ // calculate start and endpos for this paragraph
+ sal_Int32 nPos = 0;
+ if( rSel.nStartPara == nPara )
+ nPos = rSel.nStartPos;
+
+ sal_Int32 nEndPos = rSel.nEndPos;
+ if( rSel.nEndPara != nPara )
+ nEndPos = rEditEngine.GetTextLen( nPara );
+
+
+ // get list of char attribs
+ rEditEngine.GetCharAttribs( nPara, aAttribs );
+
+ bool bEmpty = true; // we found no item inside the selection of this paragraph
+ bool bGaps = false; // we found items but there are gaps between them
+ sal_Int32 nLastEnd = nPos;
+
+ const SfxPoolItem* pParaItem = nullptr;
+
+ for (auto const& attrib : aAttribs)
+ {
+ DBG_ASSERT(attrib.pAttr, "GetCharAttribs gives corrupt data");
+
+ const bool bEmptyPortion = attrib.nStart == attrib.nEnd;
+ if((!bEmptyPortion && attrib.nStart >= nEndPos) ||
+ (bEmptyPortion && attrib.nStart > nEndPos))
+ break; // break if we are already behind our selection
+
+ if((!bEmptyPortion && attrib.nEnd <= nPos) ||
+ (bEmptyPortion && attrib.nEnd < nPos))
+ continue; // or if the attribute ends before our selection
+
+ if(attrib.pAttr->Which() != nWhich)
+ continue; // skip if is not the searched item
+
+ // if we already found an item
+ if( pParaItem )
+ {
+ // ... and its different to this one than the state is don't care
+ if(*pParaItem != *(attrib.pAttr))
+ return SfxItemState::DONTCARE;
+ }
+ else
+ pParaItem = attrib.pAttr;
+
+ if( bEmpty )
+ bEmpty = false;
+
+ if(!bGaps && attrib.nStart > nLastEnd)
+ bGaps = true;
+
+ nLastEnd = attrib.nEnd;
+ }
+
+ if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) )
+ bGaps = true;
+
+ if( bEmpty )
+ eParaState = SfxItemState::DEFAULT;
+ else if( bGaps )
+ eParaState = SfxItemState::DONTCARE;
+ else
+ eParaState = SfxItemState::SET;
+
+ // if we already found an item check if we found the same
+ if( pLastItem )
+ {
+ if( (pParaItem == nullptr) || (*pLastItem != *pParaItem) )
+ return SfxItemState::DONTCARE;
+ }
+ else
+ {
+ pLastItem = pParaItem;
+ eState = eParaState;
+ }
+ }
+
+ return eState;
+}
+
+SfxItemState SvxEditEngineForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
+{
+ return GetSvxEditEngineItemState( rEditEngine, rSel, nWhich );
+}
+
+SfxItemState SvxEditEngineForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 nWhich ) const
+{
+ const SfxItemSet& rSet = rEditEngine.GetParaAttribs( nPara );
+ return rSet.GetItemState( nWhich );
+}
+
+LanguageType SvxEditEngineForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ return rEditEngine.GetLanguage(nPara, nIndex).nLang;
+}
+
+sal_Int32 SvxEditEngineForwarder::GetFieldCount( sal_Int32 nPara ) const
+{
+ return rEditEngine.GetFieldCount(nPara);
+}
+
+EFieldInfo SvxEditEngineForwarder::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
+{
+ return rEditEngine.GetFieldInfo( nPara, nField );
+}
+
+EBulletInfo SvxEditEngineForwarder::GetBulletInfo( sal_Int32 ) const
+{
+ return EBulletInfo();
+}
+
+tools::Rectangle SvxEditEngineForwarder::GetCharBounds( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ // EditEngine's 'internal' methods like GetCharacterBounds()
+ // don't rotate for vertical text.
+ Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() );
+ // swap width and height
+ tools::Long tmp = aSize.Width();
+ aSize.setWidth(aSize.Height());
+ aSize.setHeight(tmp);
+ bool bIsVertical( rEditEngine.IsEffectivelyVertical() );
+
+ // #108900# Handle virtual position one-past-the end of the string
+ if( nIndex >= rEditEngine.GetTextLen(nPara) )
+ {
+ tools::Rectangle aLast;
+
+ if( nIndex )
+ {
+ // use last character, if possible
+ aLast = rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex-1) );
+
+ // move at end of this last character, make one pixel wide
+ aLast.Move( aLast.Right() - aLast.Left(), 0 );
+ aLast.SetSize( Size(1, aLast.GetHeight()) );
+
+ // take care for CTL
+ aLast = SvxEditSourceHelper::EEToUserSpace( aLast, aSize, bIsVertical );
+ }
+ else
+ {
+ // #109864# Bounds must lie within the paragraph
+ aLast = GetParaBounds( nPara );
+
+ // #109151# Don't use paragraph height, but line height
+ // instead. aLast is already CTL-correct
+ if( bIsVertical)
+ aLast.SetSize( Size( rEditEngine.GetLineHeight(nPara), 1 ) );
+ else
+ aLast.SetSize( Size( 1, rEditEngine.GetLineHeight(nPara) ) );
+ }
+
+ return aLast;
+ }
+ else
+ {
+ return SvxEditSourceHelper::EEToUserSpace( rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex) ),
+ aSize, bIsVertical );
+ }
+}
+
+tools::Rectangle SvxEditEngineForwarder::GetParaBounds( sal_Int32 nPara ) const
+{
+ const Point aPnt = rEditEngine.GetDocPosTopLeft( nPara );
+ sal_uInt32 nWidth;
+ sal_uInt32 nHeight;
+
+ if( rEditEngine.IsEffectivelyVertical() )
+ {
+ // Hargl. EditEngine's 'external' methods return the rotated
+ // dimensions, 'internal' methods like GetTextHeight( n )
+ // don't rotate.
+ nWidth = rEditEngine.GetTextHeight( nPara );
+ nHeight = rEditEngine.GetTextHeight();
+ sal_uInt32 nTextWidth = rEditEngine.GetTextHeight();
+
+ return tools::Rectangle( nTextWidth - aPnt.Y() - nWidth, 0, nTextWidth - aPnt.Y(), nHeight );
+ }
+ else
+ {
+ nWidth = rEditEngine.CalcTextWidth();
+ nHeight = rEditEngine.GetTextHeight( nPara );
+
+ return tools::Rectangle( 0, aPnt.Y(), nWidth, aPnt.Y() + nHeight );
+ }
+}
+
+MapMode SvxEditEngineForwarder::GetMapMode() const
+{
+ return rEditEngine.GetRefMapMode();
+}
+
+OutputDevice* SvxEditEngineForwarder::GetRefDevice() const
+{
+ return rEditEngine.GetRefDevice();
+}
+
+bool SvxEditEngineForwarder::GetIndexAtPoint( const Point& rPos, sal_Int32& nPara, sal_Int32& nIndex ) const
+{
+ Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() );
+ // swap width and height
+ tools::Long tmp = aSize.Width();
+ aSize.setWidth(aSize.Height());
+ aSize.setHeight(tmp);
+ Point aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos,
+ aSize,
+ rEditEngine.IsEffectivelyVertical() ));
+
+ EPosition aDocPos = rEditEngine.FindDocPosition( aEEPos );
+
+ nPara = aDocPos.nPara;
+ nIndex = aDocPos.nIndex;
+
+ return true;
+}
+
+bool SvxEditEngineForwarder::GetWordIndices( sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart, sal_Int32& nEnd ) const
+{
+ ESelection aRes = rEditEngine.GetWord( ESelection(nPara, nIndex, nPara, nIndex), css::i18n::WordType::DICTIONARY_WORD );
+
+ if( aRes.nStartPara == nPara &&
+ aRes.nStartPara == aRes.nEndPara )
+ {
+ nStart = aRes.nStartPos;
+ nEnd = aRes.nEndPos;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool SvxEditEngineForwarder::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara, sal_Int32 nIndex, bool bInCell ) const
+{
+ SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, rEditEngine, nPara, nIndex, bInCell );
+ return true;
+}
+
+sal_Int32 SvxEditEngineForwarder::GetLineCount( sal_Int32 nPara ) const
+{
+ return rEditEngine.GetLineCount(nPara);
+}
+
+sal_Int32 SvxEditEngineForwarder::GetLineLen( sal_Int32 nPara, sal_Int32 nLine ) const
+{
+ return rEditEngine.GetLineLen(nPara, nLine);
+}
+
+void SvxEditEngineForwarder::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nPara, sal_Int32 nLine ) const
+{
+ rEditEngine.GetLineBoundaries(rStart, rEnd, nPara, nLine);
+}
+
+sal_Int32 SvxEditEngineForwarder::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ return rEditEngine.GetLineNumberAtIndex(nPara, nIndex);
+}
+
+
+bool SvxEditEngineForwarder::QuickFormatDoc( bool )
+{
+ rEditEngine.QuickFormatDoc();
+
+ return true;
+}
+
+bool SvxEditEngineForwarder::Delete( const ESelection& rSelection )
+{
+ rEditEngine.QuickDelete( rSelection );
+ rEditEngine.QuickFormatDoc();
+
+ return true;
+}
+
+bool SvxEditEngineForwarder::InsertText( const OUString& rStr, const ESelection& rSelection )
+{
+ rEditEngine.QuickInsertText( rStr, rSelection );
+ rEditEngine.QuickFormatDoc();
+
+ return true;
+}
+
+sal_Int16 SvxEditEngineForwarder::GetDepth( sal_Int32 ) const
+{
+ // EditEngine does not support outline depth
+ return -1;
+}
+
+bool SvxEditEngineForwarder::SetDepth( sal_Int32, sal_Int16 nNewDepth )
+{
+ // EditEngine does not support outline depth
+ return nNewDepth == -1;
+}
+
+const SfxItemSet * SvxEditEngineForwarder::GetEmptyItemSetPtr()
+{
+ return &rEditEngine.GetEmptyItemSet();
+}
+
+void SvxEditEngineForwarder::AppendParagraph()
+{
+ rEditEngine.InsertParagraph( rEditEngine.GetParagraphCount(), OUString() );
+}
+
+sal_Int32 SvxEditEngineForwarder::AppendTextPortion( sal_Int32 nPara, const OUString &rText, const SfxItemSet & /*rSet*/ )
+{
+ sal_Int32 nLen = 0;
+
+ sal_Int32 nParaCount = rEditEngine.GetParagraphCount();
+ DBG_ASSERT( nPara < nParaCount, "paragraph index out of bounds" );
+ if (0 <= nPara && nPara < nParaCount)
+ {
+ nLen = rEditEngine.GetTextLen( nPara );
+ rEditEngine.QuickInsertText( rText, ESelection( nPara, nLen, nPara, nLen ) );
+ }
+
+ return nLen;
+}
+
+void SvxEditEngineForwarder::CopyText(const SvxTextForwarder& rSource)
+{
+ const SvxEditEngineForwarder* pSourceForwarder = dynamic_cast< const SvxEditEngineForwarder* >( &rSource );
+ if( !pSourceForwarder )
+ return;
+ std::unique_ptr<EditTextObject> pNewTextObject = pSourceForwarder->rEditEngine.CreateTextObject();
+ rEditEngine.SetText( *pNewTextObject );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unofored_internal.hxx b/editeng/source/uno/unofored_internal.hxx
new file mode 100644
index 0000000000..cadb194159
--- /dev/null
+++ b/editeng/source/uno/unofored_internal.hxx
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <editeng/editeng.hxx>
+#include <svl/poolitem.hxx>
+
+SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ESelection& rSel, sal_uInt16 nWhich );
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unoforou.cxx b/editeng/source/uno/unoforou.cxx
new file mode 100644
index 0000000000..8772ff9a77
--- /dev/null
+++ b/editeng/source/uno/unoforou.cxx
@@ -0,0 +1,582 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <osl/diagnose.h>
+#include <tools/debug.hxx>
+#include <svl/style.hxx>
+#include <com/sun/star/i18n/WordType.hpp>
+
+#include <svl/itemset.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/unoedhlp.hxx>
+#include <svl/poolitem.hxx>
+
+#include <editeng/unoforou.hxx>
+#include <editeng/outlobj.hxx>
+#include "unofored_internal.hxx"
+
+using namespace ::com::sun::star;
+
+
+SvxOutlinerForwarder::SvxOutlinerForwarder( Outliner& rOutl, bool bOutlText /* = false */ ) :
+ rOutliner( rOutl ),
+ bOutlinerText( bOutlText ),
+ mnParaAttribsCache( 0 )
+{
+}
+
+SvxOutlinerForwarder::~SvxOutlinerForwarder()
+{
+ flushCache();
+}
+
+sal_Int32 SvxOutlinerForwarder::GetParagraphCount() const
+{
+ return rOutliner.GetParagraphCount();
+}
+
+sal_Int32 SvxOutlinerForwarder::GetTextLen( sal_Int32 nParagraph ) const
+{
+ return rOutliner.GetEditEngine().GetTextLen( nParagraph );
+}
+
+OUString SvxOutlinerForwarder::GetText( const ESelection& rSel ) const
+{
+ //! GetText (ESelection) should probably also be in the Outliner
+ // in the time being use as the hack for the EditEngine:
+ EditEngine* pEditEngine = const_cast<EditEngine*>(&rOutliner.GetEditEngine());
+ return pEditEngine->GetText( rSel );
+}
+
+static SfxItemSet ImplOutlinerForwarderGetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib, EditEngine& rEditEngine )
+{
+ if( rSel.nStartPara == rSel.nEndPara )
+ {
+ GetAttribsFlags nFlags = GetAttribsFlags::NONE;
+
+ switch( nOnlyHardAttrib )
+ {
+ case EditEngineAttribs::All:
+ nFlags = GetAttribsFlags::ALL;
+ break;
+ case EditEngineAttribs::OnlyHard:
+ nFlags = GetAttribsFlags::CHARATTRIBS;
+ break;
+ default:
+ OSL_FAIL("unknown flags for SvxOutlinerForwarder::GetAttribs");
+ }
+ return rEditEngine.GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
+ }
+ else
+ {
+ return rEditEngine.GetAttribs( rSel, nOnlyHardAttrib );
+ }
+}
+
+SfxItemSet SvxOutlinerForwarder::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const
+{
+ if( moAttribsCache && ( EditEngineAttribs::All == nOnlyHardAttrib ) )
+ {
+ // have we the correct set in cache?
+ if( maAttribCacheSelection == rSel )
+ {
+ // yes! just return the cache
+ return *moAttribsCache;
+ }
+ else
+ {
+ // no, we need delete the old cache
+ moAttribsCache.reset();
+ }
+ }
+
+ //! Does it not exist on the Outliner?
+ //! and why is the GetAttribs on the EditEngine not a const?
+ EditEngine& rEditEngine = const_cast<EditEngine&>(rOutliner.GetEditEngine());
+
+ SfxItemSet aSet( ImplOutlinerForwarderGetAttribs( rSel, nOnlyHardAttrib, rEditEngine ) );
+
+ if( EditEngineAttribs::All == nOnlyHardAttrib )
+ {
+ moAttribsCache.emplace( aSet );
+ maAttribCacheSelection = rSel;
+ }
+
+ SfxStyleSheet* pStyle = rEditEngine.GetStyleSheet( rSel.nStartPara );
+ if( pStyle )
+ aSet.SetParent( &(pStyle->GetItemSet() ) );
+
+ return aSet;
+}
+
+SfxItemSet SvxOutlinerForwarder::GetParaAttribs( sal_Int32 nPara ) const
+{
+ if( moParaAttribsCache )
+ {
+ // have we the correct set in cache?
+ if( nPara == mnParaAttribsCache )
+ {
+ // yes! just return the cache
+ return *moParaAttribsCache;
+ }
+ else
+ {
+ // no, we need delete the old cache
+ moParaAttribsCache.reset();
+ }
+ }
+
+ moParaAttribsCache.emplace( rOutliner.GetParaAttribs( nPara ) );
+ mnParaAttribsCache = nPara;
+
+ EditEngine& rEditEngine = const_cast<EditEngine&>(rOutliner.GetEditEngine());
+
+ SfxStyleSheet* pStyle = rEditEngine.GetStyleSheet( nPara );
+ if( pStyle )
+ moParaAttribsCache->SetParent( &(pStyle->GetItemSet() ) );
+
+ return *moParaAttribsCache;
+}
+
+void SvxOutlinerForwarder::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
+{
+ flushCache();
+
+ const SfxItemSet* pOldParent = rSet.GetParent();
+ if( pOldParent )
+ const_cast<SfxItemSet*>(&rSet)->SetParent( nullptr );
+
+ rOutliner.SetParaAttribs( nPara, rSet );
+
+ if( pOldParent )
+ const_cast<SfxItemSet*>(&rSet)->SetParent( pOldParent );
+}
+
+void SvxOutlinerForwarder::RemoveAttribs( const ESelection& rSelection )
+{
+ rOutliner.RemoveAttribs( rSelection, false/*bRemoveParaAttribs*/, 0 );
+}
+
+SfxItemPool* SvxOutlinerForwarder::GetPool() const
+{
+ return rOutliner.GetEmptyItemSet().GetPool();
+}
+
+void SvxOutlinerForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) const
+{
+ const_cast<EditEngine&>(rOutliner.GetEditEngine()).GetPortions( nPara, rList );
+}
+
+OUString SvxOutlinerForwarder::GetStyleSheet(sal_Int32 nPara) const
+{
+ if (auto pStyle = rOutliner.GetStyleSheet(nPara))
+ return pStyle->GetName();
+ return OUString();
+}
+
+void SvxOutlinerForwarder::SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName)
+{
+ auto pStyleSheetPool = rOutliner.GetStyleSheetPool();
+ if (auto pStyle = pStyleSheetPool ? pStyleSheetPool->Find(rStyleName, SfxStyleFamily::Para) : nullptr)
+ rOutliner.SetStyleSheet(nPara, static_cast<SfxStyleSheet*>(pStyle));
+}
+
+void SvxOutlinerForwarder::QuickInsertText( const OUString& rText, const ESelection& rSel )
+{
+ flushCache();
+ if( rText.isEmpty() )
+ {
+ rOutliner.QuickDelete( rSel );
+ }
+ else
+ {
+ rOutliner.QuickInsertText( rText, rSel );
+ }
+}
+
+void SvxOutlinerForwarder::QuickInsertLineBreak( const ESelection& rSel )
+{
+ flushCache();
+ rOutliner.QuickInsertLineBreak( rSel );
+}
+
+void SvxOutlinerForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
+{
+ flushCache();
+ rOutliner.QuickInsertField( rFld, rSel );
+}
+
+void SvxOutlinerForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
+{
+ flushCache();
+ rOutliner.QuickSetAttribs( rSet, rSel );
+}
+
+OUString SvxOutlinerForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle )
+{
+ return rOutliner.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle );
+}
+
+void SvxOutlinerForwarder::FieldClicked( const SvxFieldItem& /*rField*/ )
+{
+}
+
+bool SvxOutlinerForwarder::IsValid() const
+{
+ // cannot reliably query outliner state
+ // while in the middle of an update
+ return rOutliner.IsUpdateLayout();
+}
+
+SfxItemState SvxOutlinerForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
+{
+ return GetSvxEditEngineItemState( rOutliner.GetEditEngine(), rSel, nWhich );
+}
+
+SfxItemState SvxOutlinerForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 nWhich ) const
+{
+ const SfxItemSet& rSet = rOutliner.GetParaAttribs( nPara );
+ return rSet.GetItemState( nWhich );
+}
+
+
+void SvxOutlinerForwarder::flushCache()
+{
+ moAttribsCache.reset();
+ moParaAttribsCache.reset();
+}
+
+LanguageType SvxOutlinerForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ return rOutliner.GetLanguage(nPara, nIndex);
+}
+
+sal_Int32 SvxOutlinerForwarder::GetFieldCount( sal_Int32 nPara ) const
+{
+ return rOutliner.GetEditEngine().GetFieldCount(nPara);
+}
+
+EFieldInfo SvxOutlinerForwarder::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
+{
+ return rOutliner.GetEditEngine().GetFieldInfo( nPara, nField );
+}
+
+EBulletInfo SvxOutlinerForwarder::GetBulletInfo( sal_Int32 nPara ) const
+{
+ return rOutliner.GetBulletInfo( nPara );
+}
+
+tools::Rectangle SvxOutlinerForwarder::GetCharBounds( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ // EditEngine's 'internal' methods like GetCharacterBounds()
+ // don't rotate for vertical text.
+ Size aSize( rOutliner.CalcTextSize() );
+ // swap width and height
+ tools::Long tmp = aSize.Width();
+ aSize.setWidth(aSize.Height());
+ aSize.setHeight(tmp);
+ bool bIsVertical( rOutliner.IsVertical() );
+
+ // #108900# Handle virtual position one-past-the end of the string
+ if( nIndex >= GetTextLen(nPara) )
+ {
+ tools::Rectangle aLast;
+
+ if( nIndex )
+ {
+ // use last character, if possible
+ aLast = rOutliner.GetEditEngine().GetCharacterBounds( EPosition(nPara, nIndex-1) );
+
+ // move at end of this last character, make one pixel wide
+ aLast.Move( aLast.Right() - aLast.Left(), 0 );
+ aLast.SetSize( Size(1, aLast.GetHeight()) );
+
+ // take care for CTL
+ aLast = SvxEditSourceHelper::EEToUserSpace( aLast, aSize, bIsVertical );
+ }
+ else
+ {
+ // #109864# Bounds must lie within the paragraph
+ aLast = GetParaBounds( nPara );
+
+ // #109151# Don't use paragraph height, but line height
+ // instead. aLast is already CTL-correct
+ if( bIsVertical)
+ aLast.SetSize( Size( rOutliner.GetLineHeight(nPara), 1 ) );
+ else
+ aLast.SetSize( Size( 1, rOutliner.GetLineHeight(nPara) ) );
+ }
+
+ return aLast;
+ }
+ else
+ {
+ return SvxEditSourceHelper::EEToUserSpace( rOutliner.GetEditEngine().GetCharacterBounds( EPosition(nPara, nIndex) ),
+ aSize, bIsVertical );
+ }
+}
+
+tools::Rectangle SvxOutlinerForwarder::GetParaBounds( sal_Int32 nPara ) const
+{
+ return rOutliner.GetParaBounds( nPara );
+}
+
+MapMode SvxOutlinerForwarder::GetMapMode() const
+{
+ return rOutliner.GetRefMapMode();
+}
+
+OutputDevice* SvxOutlinerForwarder::GetRefDevice() const
+{
+ return rOutliner.GetRefDevice();
+}
+
+bool SvxOutlinerForwarder::GetIndexAtPoint( const Point& rPos, sal_Int32& nPara, sal_Int32& nIndex ) const
+{
+ Size aSize( rOutliner.CalcTextSize() );
+ // swap width and height
+ tools::Long tmp = aSize.Width();
+ aSize.setWidth(aSize.Height());
+ aSize.setHeight(tmp);
+ Point aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos,
+ aSize,
+ rOutliner.IsVertical() ));
+
+ EPosition aDocPos = rOutliner.GetEditEngine().FindDocPosition( aEEPos );
+
+ nPara = aDocPos.nPara;
+ nIndex = aDocPos.nIndex;
+
+ return true;
+}
+
+bool SvxOutlinerForwarder::GetWordIndices( sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart, sal_Int32& nEnd ) const
+{
+ ESelection aRes = rOutliner.GetEditEngine().GetWord( ESelection(nPara, nIndex, nPara, nIndex), css::i18n::WordType::DICTIONARY_WORD );
+
+ if( aRes.nStartPara == nPara &&
+ aRes.nStartPara == aRes.nEndPara )
+ {
+ nStart = aRes.nStartPos;
+ nEnd = aRes.nEndPos;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool SvxOutlinerForwarder::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara, sal_Int32 nIndex, bool bInCell ) const
+{
+ SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, rOutliner.GetEditEngine(), nPara, nIndex, bInCell );
+ return true;
+}
+
+sal_Int32 SvxOutlinerForwarder::GetLineCount( sal_Int32 nPara ) const
+{
+ return rOutliner.GetLineCount(nPara);
+}
+
+sal_Int32 SvxOutlinerForwarder::GetLineLen( sal_Int32 nPara, sal_Int32 nLine ) const
+{
+ return rOutliner.GetLineLen(nPara, nLine);
+}
+
+void SvxOutlinerForwarder::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nPara, sal_Int32 nLine ) const
+{
+ return rOutliner.GetEditEngine().GetLineBoundaries( rStart, rEnd, nPara, nLine );
+}
+
+sal_Int32 SvxOutlinerForwarder::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
+{
+ return rOutliner.GetEditEngine().GetLineNumberAtIndex( nPara, nIndex );
+}
+
+bool SvxOutlinerForwarder::QuickFormatDoc( bool )
+{
+ rOutliner.QuickFormatDoc();
+
+ return true;
+}
+
+bool SvxOutlinerForwarder::Delete( const ESelection& rSelection )
+{
+ flushCache();
+ rOutliner.QuickDelete( rSelection );
+ rOutliner.QuickFormatDoc();
+
+ return true;
+}
+
+bool SvxOutlinerForwarder::InsertText( const OUString& rStr, const ESelection& rSelection )
+{
+ flushCache();
+ rOutliner.QuickInsertText( rStr, rSelection );
+ rOutliner.QuickFormatDoc();
+
+ return true;
+}
+
+sal_Int16 SvxOutlinerForwarder::GetDepth( sal_Int32 nPara ) const
+{
+ DBG_ASSERT( 0 <= nPara && nPara < GetParagraphCount(), "SvxOutlinerForwarder::GetDepth: Invalid paragraph index");
+
+ Paragraph* pPara = rOutliner.GetParagraph( nPara );
+
+ sal_Int16 nLevel = -1;
+
+ if( pPara )
+ nLevel = rOutliner.GetDepth( nPara );
+
+ return nLevel;
+}
+
+bool SvxOutlinerForwarder::SetDepth( sal_Int32 nPara, sal_Int16 nNewDepth )
+{
+ DBG_ASSERT( 0 <= nPara && nPara < GetParagraphCount(), "SvxOutlinerForwarder::SetDepth: Invalid paragraph index");
+
+ if( (nNewDepth >= -1) && (nNewDepth <= 9) && (0 <= nPara && nPara < GetParagraphCount()) )
+ {
+ Paragraph* pPara = rOutliner.GetParagraph( nPara );
+ if( pPara )
+ {
+ rOutliner.SetDepth( pPara, nNewDepth );
+
+// const bool bOutlinerText = pSdrObject && (pSdrObject->GetObjInventor() == SdrInventor::Default) && (pSdrObject->GetObjIdentifier() == OBJ_OUTLINETEXT);
+ if( bOutlinerText )
+ rOutliner.SetLevelDependentStyleSheet( nPara );
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+sal_Int32 SvxOutlinerForwarder::GetNumberingStartValue( sal_Int32 nPara )
+{
+ if( 0 <= nPara && nPara < GetParagraphCount() )
+ {
+ return rOutliner.GetNumberingStartValue( nPara );
+ }
+ else
+ {
+ OSL_FAIL( "SvxOutlinerForwarder::GetNumberingStartValue)(), Invalid paragraph index");
+ return -1;
+ }
+}
+
+void SvxOutlinerForwarder::SetNumberingStartValue( sal_Int32 nPara, sal_Int32 nNumberingStartValue )
+{
+ if( 0 <= nPara && nPara < GetParagraphCount() )
+ {
+ rOutliner.SetNumberingStartValue( nPara, nNumberingStartValue );
+ }
+ else
+ {
+ OSL_FAIL( "SvxOutlinerForwarder::SetNumberingStartValue)(), Invalid paragraph index");
+ }
+}
+
+bool SvxOutlinerForwarder::IsParaIsNumberingRestart( sal_Int32 nPara )
+{
+ if( 0 <= nPara && nPara < GetParagraphCount() )
+ {
+ return rOutliner.IsParaIsNumberingRestart( nPara );
+ }
+ else
+ {
+ OSL_FAIL( "SvxOutlinerForwarder::IsParaIsNumberingRestart)(), Invalid paragraph index");
+ return false;
+ }
+}
+
+void SvxOutlinerForwarder::SetParaIsNumberingRestart( sal_Int32 nPara, bool bParaIsNumberingRestart )
+{
+ if( 0 <= nPara && nPara < GetParagraphCount() )
+ {
+ rOutliner.SetParaIsNumberingRestart( nPara, bParaIsNumberingRestart );
+ }
+ else
+ {
+ OSL_FAIL( "SvxOutlinerForwarder::SetParaIsNumberingRestart)(), Invalid paragraph index");
+ }
+}
+
+const SfxItemSet * SvxOutlinerForwarder::GetEmptyItemSetPtr()
+{
+ EditEngine& rEditEngine = const_cast< EditEngine& >( rOutliner.GetEditEngine() );
+ return &rEditEngine.GetEmptyItemSet();
+}
+
+void SvxOutlinerForwarder::AppendParagraph()
+{
+ EditEngine& rEditEngine = const_cast< EditEngine& >( rOutliner.GetEditEngine() );
+ rEditEngine.InsertParagraph( rEditEngine.GetParagraphCount(), OUString() );
+}
+
+sal_Int32 SvxOutlinerForwarder::AppendTextPortion( sal_Int32 nPara, const OUString &rText, const SfxItemSet & /*rSet*/ )
+{
+ sal_Int32 nLen = 0;
+
+ EditEngine& rEditEngine = const_cast< EditEngine& >( rOutliner.GetEditEngine() );
+ sal_Int32 nParaCount = rEditEngine.GetParagraphCount();
+ DBG_ASSERT( 0 <= nPara && nPara < nParaCount, "paragraph index out of bounds" );
+ if (0 <= nPara && nPara < nParaCount)
+ {
+ nLen = rEditEngine.GetTextLen( nPara );
+ rEditEngine.QuickInsertText( rText, ESelection( nPara, nLen, nPara, nLen ) );
+ }
+
+ return nLen;
+}
+
+void SvxOutlinerForwarder::CopyText(const SvxTextForwarder& rSource)
+{
+ const SvxOutlinerForwarder* pSourceForwarder = dynamic_cast< const SvxOutlinerForwarder* >( &rSource );
+ if( !pSourceForwarder )
+ return;
+ std::optional<OutlinerParaObject> pNewOutlinerParaObject = pSourceForwarder->rOutliner.CreateParaObject();
+ rOutliner.SetText( *pNewOutlinerParaObject );
+}
+
+
+sal_Int32 SvxTextForwarder::GetNumberingStartValue( sal_Int32 )
+{
+ return -1;
+}
+
+void SvxTextForwarder::SetNumberingStartValue( sal_Int32, sal_Int32 )
+{
+}
+
+bool SvxTextForwarder::IsParaIsNumberingRestart( sal_Int32 )
+{
+ return false;
+}
+
+void SvxTextForwarder::SetParaIsNumberingRestart( sal_Int32, bool )
+{
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unoipset.cxx b/editeng/source/uno/unoipset.cxx
new file mode 100644
index 0000000000..4a4dd9f5e5
--- /dev/null
+++ b/editeng/source/uno/unoipset.cxx
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <svl/itemprop.hxx>
+#include <tools/UnitConversion.hxx>
+#include <editeng/unoipset.hxx>
+#include <svl/itempool.hxx>
+#include <svl/solar.hrc>
+#include <o3tl/any.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+
+SvxItemPropertySet::SvxItemPropertySet( std::span<const SfxItemPropertyMapEntry> pMap, SfxItemPool& rItemPool )
+: m_aPropertyMap( pMap ),
+ mrItemPool( rItemPool )
+{
+}
+
+
+SvxItemPropertySet::~SvxItemPropertySet()
+{
+}
+
+
+static bool SvxUnoCheckForPositiveValue( const uno::Any& rVal )
+{
+ bool bConvert = true; // the default is that all metric items must be converted
+ sal_Int32 nValue = 0;
+ if( rVal >>= nValue )
+ bConvert = (nValue > 0);
+ return bConvert;
+}
+
+
+uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pMap, const SfxItemSet& rSet, bool bSearchInParent, bool bDontConvertNegativeValues )
+{
+ uno::Any aVal;
+ if(!pMap || !pMap->nWID)
+ return aVal;
+
+ const SfxPoolItem* pItem = nullptr;
+ SfxItemPool* pPool = rSet.GetPool();
+ (void)rSet.GetItemState( pMap->nWID, bSearchInParent, &pItem );
+ if( nullptr == pItem && pPool )
+ pItem = &(pPool->GetDefaultItem( pMap->nWID ));
+
+ const MapUnit eMapUnit = pPool ? pPool->GetMetric(pMap->nWID) : MapUnit::Map100thMM;
+ sal_uInt8 nMemberId = pMap->nMemberId;
+ if( eMapUnit == MapUnit::Map100thMM )
+ nMemberId &= (~CONVERT_TWIPS);
+
+ if(pItem)
+ {
+ pItem->QueryValue( aVal, nMemberId );
+ if( pMap->nMoreFlags & PropertyMoreFlags::METRIC_ITEM )
+ {
+ if( eMapUnit != MapUnit::Map100thMM )
+ {
+ if ( !bDontConvertNegativeValues || SvxUnoCheckForPositiveValue( aVal ) )
+ SvxUnoConvertToMM( eMapUnit, aVal );
+ }
+ }
+ else if ( pMap->aType.getTypeClass() == uno::TypeClass_ENUM &&
+ aVal.getValueType() == ::cppu::UnoType<sal_Int32>::get() )
+ {
+ // convert typeless SfxEnumItem to enum type
+ sal_Int32 nEnum;
+ aVal >>= nEnum;
+ aVal.setValue( &nEnum, pMap->aType );
+ }
+ }
+ else
+ {
+ OSL_FAIL( "No SfxPoolItem found for property!" );
+ }
+
+ return aVal;
+}
+
+
+void SvxItemPropertySet::setPropertyValue( const SfxItemPropertyMapEntry* pMap, const uno::Any& rVal, SfxItemSet& rSet, bool bDontConvertNegativeValues )
+{
+ if(!pMap || !pMap->nWID)
+ return;
+
+ // Get item
+ const SfxPoolItem* pItem = nullptr;
+ SfxItemState eState = rSet.GetItemState( pMap->nWID, true, &pItem );
+ SfxItemPool* pPool = rSet.GetPool();
+
+ // Put UnoAny in the item value
+ if(eState < SfxItemState::DEFAULT || pItem == nullptr)
+ {
+ if( pPool == nullptr )
+ {
+ OSL_FAIL( "No default item and no pool?" );
+ return;
+ }
+
+ pItem = &pPool->GetDefaultItem( pMap->nWID );
+ }
+
+ uno::Any aValue(rVal);
+
+ const MapUnit eMapUnit = pPool ? pPool->GetMetric(pMap->nWID) : MapUnit::Map100thMM;
+
+ // check for needed metric translation
+ if ((pMap->nMoreFlags & PropertyMoreFlags::METRIC_ITEM) && eMapUnit != MapUnit::Map100thMM)
+ {
+ if (!bDontConvertNegativeValues || SvxUnoCheckForPositiveValue(aValue))
+ SvxUnoConvertFromMM(eMapUnit, aValue);
+ }
+
+ std::unique_ptr<SfxPoolItem> pNewItem(pItem->Clone());
+
+ sal_uInt8 nMemberId = pMap->nMemberId;
+ if (eMapUnit == MapUnit::Map100thMM)
+ nMemberId &= (~CONVERT_TWIPS);
+
+ if (pNewItem->PutValue(aValue, nMemberId))
+ {
+ // Set new item in item set
+ pNewItem->SetWhich(pMap->nWID);
+ rSet.Put(std::move(pNewItem));
+ }
+}
+
+
+uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pMap, SvxItemPropertySetUsrAnys& rAnys ) const
+{
+ // Already entered a value? Then finish quickly
+ uno::Any* pUsrAny = rAnys.GetUsrAnyForID(*pMap);
+ if(pUsrAny)
+ return *pUsrAny;
+
+ // No UsrAny detected yet, generate Default entry and return this
+ const MapUnit eMapUnit = mrItemPool.GetMetric(pMap->nWID);
+ sal_uInt8 nMemberId = pMap->nMemberId;
+ if( eMapUnit == MapUnit::Map100thMM )
+ nMemberId &= (~CONVERT_TWIPS);
+ uno::Any aVal;
+ SfxItemSet aSet( mrItemPool, pMap->nWID, pMap->nWID);
+
+ if( (pMap->nWID < OWN_ATTR_VALUE_START) || (pMap->nWID > OWN_ATTR_VALUE_END ) )
+ {
+ // Get Default from ItemPool
+ if(SfxItemPool::IsWhich(pMap->nWID))
+ aSet.Put(mrItemPool.GetDefaultItem(pMap->nWID));
+ }
+
+ if(aSet.Count())
+ {
+ const SfxPoolItem* pItem = nullptr;
+ SfxItemState eState = aSet.GetItemState( pMap->nWID, true, &pItem );
+ if(eState >= SfxItemState::DEFAULT && pItem)
+ {
+ pItem->QueryValue( aVal, nMemberId );
+ rAnys.AddUsrAnyForID(aVal, *pMap);
+ }
+ }
+
+ // check for needed metric translation
+ if(pMap->nMoreFlags & PropertyMoreFlags::METRIC_ITEM && eMapUnit != MapUnit::Map100thMM)
+ {
+ SvxUnoConvertToMM( eMapUnit, aVal );
+ }
+
+ if ( pMap->aType.getTypeClass() == uno::TypeClass_ENUM &&
+ aVal.getValueType() == ::cppu::UnoType<sal_Int32>::get() )
+ {
+ sal_Int32 nEnum;
+ aVal >>= nEnum;
+
+ aVal.setValue( &nEnum, pMap->aType );
+ }
+
+ return aVal;
+}
+
+
+void SvxItemPropertySet::setPropertyValue( const SfxItemPropertyMapEntry* pMap, const uno::Any& rVal, SvxItemPropertySetUsrAnys& rAnys )
+{
+ uno::Any* pUsrAny = rAnys.GetUsrAnyForID(*pMap);
+ if(!pUsrAny)
+ rAnys.AddUsrAnyForID(rVal, *pMap);
+ else
+ *pUsrAny = rVal;
+}
+
+
+const SfxItemPropertyMapEntry* SvxItemPropertySet::getPropertyMapEntry(std::u16string_view rName) const
+{
+ return m_aPropertyMap.getByName( rName );
+ }
+
+
+uno::Reference< beans::XPropertySetInfo > const & SvxItemPropertySet::getPropertySetInfo() const
+{
+ if( !m_xInfo.is() )
+ m_xInfo = new SfxItemPropertySetInfo( m_aPropertyMap );
+ return m_xInfo;
+}
+
+
+/** converts the given any with a metric to 100th/mm if needed */
+void SvxUnoConvertToMM( const MapUnit eSourceMapUnit, uno::Any & rMetric ) noexcept
+{
+ // map the metric of the itempool to 100th mm
+ switch(eSourceMapUnit)
+ {
+ case MapUnit::MapTwip :
+ {
+ switch( rMetric.getValueTypeClass() )
+ {
+ case uno::TypeClass_BYTE:
+ rMetric <<= static_cast<sal_Int8>(convertTwipToMm100(*o3tl::forceAccess<sal_Int8>(rMetric)));
+ break;
+ case uno::TypeClass_SHORT:
+ rMetric <<= static_cast<sal_Int16>(convertTwipToMm100(*o3tl::forceAccess<sal_Int16>(rMetric)));
+ break;
+ case uno::TypeClass_UNSIGNED_SHORT:
+ rMetric <<= static_cast<sal_uInt16>(convertTwipToMm100(*o3tl::forceAccess<sal_uInt16>(rMetric)));
+ break;
+ case uno::TypeClass_LONG:
+ rMetric <<= static_cast<sal_Int32>(convertTwipToMm100(*o3tl::forceAccess<sal_Int32>(rMetric)));
+ break;
+ case uno::TypeClass_UNSIGNED_LONG:
+ rMetric <<= static_cast<sal_uInt32>(convertTwipToMm100(*o3tl::forceAccess<sal_uInt32>(rMetric)));
+ break;
+ default:
+ SAL_WARN("editeng", "AW: Missing unit translation to 100th mm, " << OString::number(static_cast<sal_Int32>(rMetric.getValueTypeClass())));
+ assert(false);
+ }
+ break;
+ }
+ default:
+ {
+ OSL_FAIL("AW: Missing unit translation to 100th mm!");
+ }
+ }
+}
+
+
+/** converts the given any with a metric from 100th/mm to the given metric if needed */
+void SvxUnoConvertFromMM( const MapUnit eDestinationMapUnit, uno::Any & rMetric ) noexcept
+{
+ switch(eDestinationMapUnit)
+ {
+ case MapUnit::MapTwip :
+ {
+ switch( rMetric.getValueTypeClass() )
+ {
+ case uno::TypeClass_BYTE:
+ rMetric <<= static_cast<sal_Int8>(sanitiseMm100ToTwip(*o3tl::forceAccess<sal_Int8>(rMetric)));
+ break;
+ case uno::TypeClass_SHORT:
+ rMetric <<= static_cast<sal_Int16>(sanitiseMm100ToTwip(*o3tl::forceAccess<sal_Int16>(rMetric)));
+ break;
+ case uno::TypeClass_UNSIGNED_SHORT:
+ rMetric <<= static_cast<sal_uInt16>(sanitiseMm100ToTwip(*o3tl::forceAccess<sal_uInt16>(rMetric)));
+ break;
+ case uno::TypeClass_LONG:
+ rMetric <<= static_cast<sal_Int32>(sanitiseMm100ToTwip(*o3tl::forceAccess<sal_Int32>(rMetric)));
+ break;
+ case uno::TypeClass_UNSIGNED_LONG:
+ rMetric <<= static_cast<sal_uInt32>(sanitiseMm100ToTwip(*o3tl::forceAccess<sal_uInt32>(rMetric)));
+ break;
+ default:
+ OSL_FAIL("AW: Missing unit translation to 100th mm!");
+ }
+ break;
+ }
+ default:
+ {
+ OSL_FAIL("AW: Missing unit translation to PoolMetrics!");
+ }
+ }
+}
+
+SvxItemPropertySetUsrAnys::SvxItemPropertySetUsrAnys() = default;
+
+SvxItemPropertySetUsrAnys::~SvxItemPropertySetUsrAnys()
+{
+ ClearAllUsrAny();
+}
+
+uno::Any* SvxItemPropertySetUsrAnys::GetUsrAnyForID(SfxItemPropertyMapEntry const & entry) const
+{
+ for (auto const & rActual : aCombineList)
+ {
+ if( rActual.nWID == entry.nWID && rActual.memberId == entry.nMemberId )
+ return const_cast<uno::Any*>(&rActual.aAny);
+ }
+ return nullptr;
+}
+
+void SvxItemPropertySetUsrAnys::AddUsrAnyForID(
+ const uno::Any& rAny, SfxItemPropertyMapEntry const & entry)
+{
+ SvxIDPropertyCombine aNew;
+ aNew.nWID = entry.nWID;
+ aNew.memberId = entry.nMemberId;
+ aNew.aAny = rAny;
+ aCombineList.push_back( std::move(aNew) );
+}
+
+void SvxItemPropertySetUsrAnys::ClearAllUsrAny()
+{
+ aCombineList.clear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unonrule.cxx b/editeng/source/uno/unonrule.cxx
new file mode 100644
index 0000000000..5083f4d8e8
--- /dev/null
+++ b/editeng/source/uno/unonrule.cxx
@@ -0,0 +1,544 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <utility>
+#include <vcl/font.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/GraphicObject.hxx>
+#include <vcl/GraphicLoader.hxx>
+#include <tools/debug.hxx>
+
+#include <editeng/brushitem.hxx>
+#include <editeng/unoprnms.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/unofdesc.hxx>
+#include <editeng/unonrule.hxx>
+#include <editeng/editids.hrc>
+#include <o3tl/enumarray.hxx>
+#include <o3tl/temporary.hxx>
+#include <memory>
+
+using ::com::sun::star::util::XCloneable;
+using ::com::sun::star::ucb::XAnyCompare;
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+
+const SvxAdjust aUnoToSvxAdjust[] =
+{
+ SvxAdjust::Left,
+ SvxAdjust::Right,
+ SvxAdjust::Center,
+ SvxAdjust::Left,
+ SvxAdjust::Left,
+ SvxAdjust::Left,
+ SvxAdjust::Block
+};
+
+const o3tl::enumarray<SvxAdjust, sal_Int16> aSvxToUnoAdjust
+{
+ text::HoriOrientation::LEFT,
+ text::HoriOrientation::RIGHT,
+ text::HoriOrientation::FULL,
+ text::HoriOrientation::CENTER,
+ text::HoriOrientation::FULL,
+ text::HoriOrientation::LEFT
+};
+
+static SvxAdjust ConvertUnoAdjust( unsigned short nAdjust )
+{
+ DBG_ASSERT( nAdjust <= 7, "Enum has changed! [CL]" );
+ return aUnoToSvxAdjust[nAdjust];
+}
+
+static unsigned short ConvertUnoAdjust( SvxAdjust eAdjust )
+{
+ DBG_ASSERT( static_cast<int>(eAdjust) <= 6, "Enum has changed! [CL]" );
+ return aSvxToUnoAdjust[eAdjust];
+}
+
+SvxUnoNumberingRules::SvxUnoNumberingRules(SvxNumRule aRule)
+: maRule(std::move( aRule ))
+{
+}
+
+SvxUnoNumberingRules::~SvxUnoNumberingRules() noexcept
+{
+}
+
+//XIndexReplace
+void SAL_CALL SvxUnoNumberingRules::replaceByIndex( sal_Int32 Index, const uno::Any& Element )
+{
+ SolarMutexGuard aGuard;
+
+ if( Index < 0 || Index >= maRule.GetLevelCount() )
+ throw IndexOutOfBoundsException();
+
+ Sequence< beans::PropertyValue > aSeq;
+
+ if( !( Element >>= aSeq) )
+ throw IllegalArgumentException();
+ setNumberingRuleByIndex( aSeq, Index );
+}
+
+// XIndexAccess
+sal_Int32 SAL_CALL SvxUnoNumberingRules::getCount()
+{
+ SolarMutexGuard aGuard;
+
+ return maRule.GetLevelCount();
+}
+
+Any SAL_CALL SvxUnoNumberingRules::getByIndex( sal_Int32 Index )
+{
+ SolarMutexGuard aGuard;
+
+ if( Index < 0 || Index >= maRule.GetLevelCount() )
+ throw IndexOutOfBoundsException();
+
+ return Any( getNumberingRuleByIndex(Index) );
+}
+
+//XElementAccess
+Type SAL_CALL SvxUnoNumberingRules::getElementType()
+{
+ return cppu::UnoType<Sequence< beans::PropertyValue >>::get();
+}
+
+sal_Bool SAL_CALL SvxUnoNumberingRules::hasElements()
+{
+ return true;
+}
+
+// XAnyCompare
+sal_Int16 SAL_CALL SvxUnoNumberingRules::compare( const Any& rAny1, const Any& rAny2 )
+{
+ return SvxUnoNumberingRules::Compare( rAny1, rAny2 );
+}
+
+// XCloneable
+Reference< XCloneable > SAL_CALL SvxUnoNumberingRules::createClone( )
+{
+ return new SvxUnoNumberingRules(maRule);
+}
+
+OUString SAL_CALL SvxUnoNumberingRules::getImplementationName( )
+{
+ return "SvxUnoNumberingRules";
+}
+
+sal_Bool SAL_CALL SvxUnoNumberingRules::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL SvxUnoNumberingRules::getSupportedServiceNames( )
+{
+ return { "com.sun.star.text.NumberingRules" };
+}
+
+Sequence<beans::PropertyValue> SvxUnoNumberingRules::getNumberingRuleByIndex(sal_Int32 nIndex) const
+{
+ // NumberingRule aRule;
+ const SvxNumberFormat& rFmt = maRule.GetLevel(static_cast<sal_uInt16>(nIndex));
+ sal_uInt16 nIdx = 0;
+
+ const int nProps = 15;
+ std::unique_ptr<beans::PropertyValue[]> pArray(new beans::PropertyValue[nProps]);
+
+ Any aVal;
+ {
+ aVal <<= static_cast<sal_uInt16>(rFmt.GetNumberingType());
+ beans::PropertyValue aAlignProp( UNO_NAME_NRULE_NUMBERINGTYPE, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ pArray[nIdx++] = aAlignProp;
+ }
+
+ {
+ SvxAdjust eAdj = rFmt.GetNumAdjust();
+ aVal <<= ConvertUnoAdjust(eAdj);
+ pArray[nIdx++] = beans::PropertyValue( UNO_NAME_NRULE_ADJUST, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ }
+
+ {
+ aVal <<= rFmt.GetPrefix();
+ beans::PropertyValue aPrefixProp( UNO_NAME_NRULE_PREFIX, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ pArray[nIdx++] = aPrefixProp;
+ }
+
+ {
+ aVal <<= rFmt.GetSuffix();
+ beans::PropertyValue aSuffixProp( UNO_NAME_NRULE_SUFFIX, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ pArray[nIdx++] = aSuffixProp;
+ }
+
+ if(SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType())
+ {
+ sal_UCS4 nCode = rFmt.GetBulletChar();
+ OUString aStr( &nCode, 1 );
+ aVal <<= aStr;
+ pArray[nIdx++] = beans::PropertyValue("BulletChar", -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ }
+
+ if( rFmt.GetBulletFont() )
+ {
+ awt::FontDescriptor aDesc;
+ SvxUnoFontDescriptor::ConvertFromFont( *rFmt.GetBulletFont(), aDesc );
+ aVal <<= aDesc;
+ pArray[nIdx++] = beans::PropertyValue( UNO_NAME_NRULE_BULLET_FONT, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ }
+
+ {
+ const SvxBrushItem* pBrush = rFmt.GetBrush();
+ const Graphic* pGraphic = nullptr;
+ if (pBrush)
+ pGraphic = pBrush->GetGraphic();
+ if (pGraphic)
+ {
+ uno::Reference<awt::XBitmap> xBitmap(pGraphic->GetXGraphic(), uno::UNO_QUERY);
+ aVal <<= xBitmap;
+
+ const beans::PropertyValue aGraphicProp("GraphicBitmap", -1, aVal, beans::PropertyState_DIRECT_VALUE);
+ pArray[nIdx++] = aGraphicProp;
+ }
+ }
+
+ {
+ const Size aSize( rFmt.GetGraphicSize() );
+ const awt::Size aUnoSize( aSize.Width(), aSize.Height() );
+ aVal <<= aUnoSize;
+ const beans::PropertyValue aGraphicSizeProp("GraphicSize", -1, aVal, beans::PropertyState_DIRECT_VALUE );
+ pArray[nIdx++] = aGraphicSizeProp;
+ }
+
+ aVal <<= static_cast<sal_Int16>(rFmt.GetStart());
+ pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_START_WITH, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+
+ aVal <<= rFmt.GetAbsLSpace();
+ pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_LEFT_MARGIN, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+
+ aVal <<= rFmt.GetFirstLineOffset();
+ pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_FIRST_LINE_OFFSET, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+
+ pArray[nIdx++] = beans::PropertyValue("SymbolTextDistance", -1, aVal, beans::PropertyState_DIRECT_VALUE);
+
+ aVal <<= rFmt.GetBulletColor();
+ pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_BULLET_COLOR, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+
+ aVal <<= static_cast<sal_Int16>(rFmt.GetBulletRelSize());
+ pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_BULLET_RELSIZE, -1, aVal, beans::PropertyState_DIRECT_VALUE);
+
+ DBG_ASSERT( nIdx <= nProps, "FixMe: overflow in Array!!! [CL]" );
+ Sequence< beans::PropertyValue> aSeq(pArray.get(), nIdx);
+
+ return aSeq;
+}
+
+void SvxUnoNumberingRules::setNumberingRuleByIndex(const Sequence<beans::PropertyValue >& rProperties, sal_Int32 nIndex)
+{
+ SvxNumberFormat aFmt(maRule.GetLevel( static_cast<sal_uInt16>(nIndex) ));
+ for(const beans::PropertyValue& rProp : rProperties)
+ {
+ const OUString& rPropName = rProp.Name;
+ const Any& aVal = rProp.Value;
+
+ if ( rPropName == UNO_NAME_NRULE_NUMBERINGTYPE )
+ {
+ sal_Int16 nSet = sal_Int16();
+ aVal >>= nSet;
+
+ // There is no reason to limit numbering types.
+ if ( nSet>=0 )
+ {
+ aFmt.SetNumberingType(static_cast<SvxNumType>(nSet));
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_PREFIX )
+ {
+ OUString aPrefix;
+ if( aVal >>= aPrefix )
+ {
+ aFmt.SetPrefix(aPrefix);
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_SUFFIX )
+ {
+ OUString aSuffix;
+ if( aVal >>= aSuffix )
+ {
+ aFmt.SetSuffix(aSuffix);
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_BULLETID )
+ {
+ sal_Int16 nSet = sal_Int16();
+ if( aVal >>= nSet )
+ {
+ if(nSet < 0x100)
+ {
+ aFmt.SetBulletChar(nSet);
+ continue;
+ }
+ }
+ }
+ else if ( rPropName == "BulletChar" )
+ {
+ OUString aStr;
+ if( aVal >>= aStr )
+ {
+ if(!aStr.isEmpty())
+ {
+ aFmt.SetBulletChar(aStr.iterateCodePoints(&o3tl::temporary(sal_Int32(0))));
+ }
+ else
+ {
+ aFmt.SetBulletChar(0);
+ }
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_ADJUST )
+ {
+ sal_Int16 nAdjust = sal_Int16();
+ if( aVal >>= nAdjust )
+ {
+ aFmt.SetNumAdjust(ConvertUnoAdjust( static_cast<unsigned short>(nAdjust) ));
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_BULLET_FONT )
+ {
+ awt::FontDescriptor aDesc;
+ if( aVal >>= aDesc )
+ {
+ vcl::Font aFont;
+ SvxUnoFontDescriptor::ConvertToFont( aDesc, aFont );
+ aFmt.SetBulletFont(&aFont);
+ continue;
+ }
+ }
+ else if ( rPropName == "GraphicURL" )
+ {
+ OUString aURL;
+ if (aVal >>= aURL)
+ {
+ Graphic aGraphic = vcl::graphic::loadFromURL(aURL);
+ if (!aGraphic.IsNone())
+ {
+ SvxBrushItem aBrushItem(aGraphic, GPOS_AREA, SID_ATTR_BRUSH);
+ aFmt.SetGraphicBrush(&aBrushItem);
+ }
+ continue;
+ }
+ }
+ else if ( rPropName == "GraphicBitmap" )
+ {
+ uno::Reference<awt::XBitmap> xBitmap;
+ if (aVal >>= xBitmap)
+ {
+ uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY);
+ Graphic aGraphic(xGraphic);
+ SvxBrushItem aBrushItem(aGraphic, GPOS_AREA, SID_ATTR_BRUSH);
+ aFmt.SetGraphicBrush( &aBrushItem );
+ continue;
+ }
+ }
+ else if ( rPropName == "GraphicSize" )
+ {
+ awt::Size aUnoSize;
+ if( aVal >>= aUnoSize )
+ {
+ aFmt.SetGraphicSize( Size( aUnoSize.Width, aUnoSize.Height ) );
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_START_WITH )
+ {
+ sal_Int16 nStart = sal_Int16();
+ if( aVal >>= nStart )
+ {
+ aFmt.SetStart( nStart );
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_LEFT_MARGIN )
+ {
+ sal_Int32 nMargin = 0;
+ if( aVal >>= nMargin )
+ {
+ aFmt.SetAbsLSpace(nMargin);
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_FIRST_LINE_OFFSET )
+ {
+ sal_Int32 nMargin = 0;
+ if( aVal >>= nMargin )
+ {
+ aFmt.SetFirstLineOffset(nMargin);
+ continue;
+ }
+ }
+ else if ( rPropName == "SymbolTextDistance" )
+ {
+ sal_Int32 nTextDistance = 0;
+ if( aVal >>= nTextDistance )
+ {
+ aFmt.SetCharTextDistance(static_cast<sal_uInt16>(nTextDistance));
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_BULLET_COLOR )
+ {
+ Color aColor;
+ if( aVal >>= aColor )
+ {
+ aFmt.SetBulletColor( aColor );
+ continue;
+ }
+ }
+ else if ( rPropName == UNO_NAME_NRULE_BULLET_RELSIZE )
+ {
+ sal_Int16 nSize = sal_Int16();
+ if( aVal >>= nSize )
+ {
+ // [AOO Bug 120650] the slide content corrupt when open in Aoo
+ // [TDF# 126234] when MS Office document being imported, the value of the relative size
+ // of the bullet could be as high as 400%
+ if ((nSize>400)||(nSize<=0))
+ {
+ nSize = 100;
+ }
+
+ aFmt.SetBulletRelSize( static_cast<short>(nSize) );
+ continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+
+ throw IllegalArgumentException();
+ }
+
+ // check that we always have a brush item for bitmap numbering
+ if( aFmt.GetNumberingType() == SVX_NUM_BITMAP )
+ {
+ if( nullptr == aFmt.GetBrush() )
+ {
+ GraphicObject aGrafObj;
+ SvxBrushItem aBrushItem( aGrafObj, GPOS_AREA, SID_ATTR_BRUSH );
+ aFmt.SetGraphicBrush( &aBrushItem );
+ }
+ }
+ maRule.SetLevel( static_cast<sal_uInt16>(nIndex), aFmt );
+}
+
+const SvxNumRule& SvxGetNumRule( Reference< XIndexReplace > const & xRule )
+{
+ SvxUnoNumberingRules* pRule = dynamic_cast<SvxUnoNumberingRules*>( xRule.get() );
+ if( pRule == nullptr )
+ throw IllegalArgumentException();
+
+ return pRule->getNumRule();
+}
+
+css::uno::Reference< css::container::XIndexReplace > SvxCreateNumRule(const SvxNumRule& rRule)
+{
+ return new SvxUnoNumberingRules( rRule );
+}
+
+namespace {
+
+class SvxUnoNumberingRulesCompare : public ::cppu::WeakImplHelper< XAnyCompare >
+{
+public:
+ virtual sal_Int16 SAL_CALL compare( const Any& Any1, const Any& Any2 ) override;
+};
+
+}
+
+sal_Int16 SAL_CALL SvxUnoNumberingRulesCompare::compare( const Any& Any1, const Any& Any2 )
+{
+ return SvxUnoNumberingRules::Compare( Any1, Any2 );
+}
+
+sal_Int16 SvxUnoNumberingRules::Compare( const Any& Any1, const Any& Any2 )
+{
+ Reference< XIndexReplace > x1( Any1, UNO_QUERY ), x2( Any2, UNO_QUERY );
+ if( !x1 || !x2 )
+ return -1;
+
+ if( x1.get() == x2.get() )
+ return 0;
+
+ SvxUnoNumberingRules* pRule1 = dynamic_cast<SvxUnoNumberingRules*>( x1.get() );
+ if( !pRule1 )
+ return -1;
+ SvxUnoNumberingRules* pRule2 = dynamic_cast<SvxUnoNumberingRules*>( x2.get() );
+ if( !pRule2 )
+ return -1;
+
+ const SvxNumRule& rRule1 = pRule1->getNumRule();
+ const SvxNumRule& rRule2 = pRule2->getNumRule();
+
+ const sal_uInt16 nLevelCount1 = rRule1.GetLevelCount();
+ const sal_uInt16 nLevelCount2 = rRule2.GetLevelCount();
+
+ if( nLevelCount1 == 0 || nLevelCount2 == 0 )
+ return -1;
+
+ for( sal_uInt16 i = 0; (i < nLevelCount1) && (i < nLevelCount2); i++ )
+ {
+ if( rRule1.GetLevel(i) != rRule2.GetLevel(i) )
+ return -1;
+ }
+ return 0;
+}
+
+Reference< XAnyCompare > SvxCreateNumRuleCompare() noexcept
+{
+ return new SvxUnoNumberingRulesCompare;
+}
+
+css::uno::Reference< css::container::XIndexReplace > SvxCreateNumRule()
+{
+ SvxNumRule aTempRule( SvxNumRuleFlags::NONE, 10, false );
+ return SvxCreateNumRule( aTempRule );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unopracc.cxx b/editeng/source/uno/unopracc.cxx
new file mode 100644
index 0000000000..c36fc152e2
--- /dev/null
+++ b/editeng/source/uno/unopracc.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <cppuhelper/typeprovider.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <unopracc.hxx>
+#include <editeng/unoedsrc.hxx>
+
+using namespace ::com::sun::star;
+
+
+SvxAccessibleTextPropertySet::SvxAccessibleTextPropertySet( const SvxEditSource* pEditSrc, const SvxItemPropertySet* pPropSet )
+ : SvxUnoTextRangeBase( pEditSrc, pPropSet )
+{
+}
+
+SvxAccessibleTextPropertySet::~SvxAccessibleTextPropertySet() noexcept
+{
+}
+
+uno::Reference< text::XText > SAL_CALL SvxAccessibleTextPropertySet::getText()
+{
+ // TODO (empty?)
+ return uno::Reference< text::XText > ();
+}
+
+uno::Any SAL_CALL SvxAccessibleTextPropertySet::queryInterface( const uno::Type & rType )
+{
+ return OWeakObject::queryInterface(rType);
+}
+
+void SAL_CALL SvxAccessibleTextPropertySet::acquire()
+ noexcept
+{
+ OWeakObject::acquire();
+}
+
+void SAL_CALL SvxAccessibleTextPropertySet::release()
+ noexcept
+{
+ OWeakObject::release();
+}
+
+// XTypeProvider
+uno::Sequence< uno::Type > SAL_CALL SvxAccessibleTextPropertySet::getTypes()
+{
+ static ::cppu::OTypeCollection ourTypeCollection(
+ ::cppu::UnoType<beans::XPropertySet>::get(),
+ ::cppu::UnoType<beans::XMultiPropertySet>::get(),
+ ::cppu::UnoType<beans::XPropertyState>::get(),
+ ::cppu::UnoType<lang::XServiceInfo>::get(),
+ ::cppu::UnoType<lang::XTypeProvider>::get() );
+
+ return ourTypeCollection.getTypes() ;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SvxAccessibleTextPropertySet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XServiceInfo
+OUString SAL_CALL SAL_CALL SvxAccessibleTextPropertySet::getImplementationName()
+{
+ return "SvxAccessibleTextPropertySet";
+}
+
+sal_Bool SAL_CALL SvxAccessibleTextPropertySet::supportsService (const OUString& sServiceName)
+{
+ return cppu::supportsService(this, sServiceName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unotext.cxx b/editeng/source/uno/unotext.cxx
new file mode 100644
index 0000000000..f74d7f67c3
--- /dev/null
+++ b/editeng/source/uno/unotext.cxx
@@ -0,0 +1,2561 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/svapp.hxx>
+#include <com/sun/star/text/ControlCharacter.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/TextRangeSelection.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+
+#include <svl/itemset.hxx>
+#include <svl/itempool.hxx>
+#include <svl/eitem.hxx>
+#include <tools/debug.hxx>
+
+#include <editeng/unoprnms.hxx>
+#include <editeng/unotext.hxx>
+#include <editeng/unoedsrc.hxx>
+#include <editeng/unonrule.hxx>
+#include <editeng/unofdesc.hxx>
+#include <editeng/unofield.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/unoipset.hxx>
+#include <editeng/colritem.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <editeng/unonames.hxx>
+
+#include <initializer_list>
+#include <memory>
+#include <string_view>
+
+using namespace ::cppu;
+using namespace ::com::sun::star;
+
+namespace {
+
+ESelection toESelection(const text::TextRangeSelection& rSel)
+{
+ ESelection aESel;
+ aESel.nStartPara = rSel.Start.Paragraph;
+ aESel.nStartPos = rSel.Start.PositionInParagraph;
+ aESel.nEndPara = rSel.End.Paragraph;
+ aESel.nEndPos = rSel.End.PositionInParagraph;
+ return aESel;
+}
+
+}
+
+#define QUERYINT( xint ) \
+ if( rType == cppu::UnoType<xint>::get() ) \
+ return uno::Any(uno::Reference< xint >(this))
+
+const SvxItemPropertySet* ImplGetSvxUnoOutlinerTextCursorSvxPropertySet()
+{
+ static SvxItemPropertySet aTextCursorSvxPropertySet( ImplGetSvxUnoOutlinerTextCursorPropertyMap(), EditEngine::GetGlobalItemPool() );
+ return &aTextCursorSvxPropertySet;
+}
+
+std::span<const SfxItemPropertyMapEntry> ImplGetSvxTextPortionPropertyMap()
+{
+ // Propertymap for an Outliner Text
+ static const SfxItemPropertyMapEntry aSvxTextPortionPropertyMap[] =
+ {
+ SVX_UNOEDIT_CHAR_PROPERTIES,
+ SVX_UNOEDIT_FONT_PROPERTIES,
+ SVX_UNOEDIT_OUTLINER_PROPERTIES,
+ SVX_UNOEDIT_PARA_PROPERTIES,
+ { u"TextField"_ustr, EE_FEATURE_FIELD, cppu::UnoType<text::XTextField>::get(), beans::PropertyAttribute::READONLY, 0 },
+ { u"TextPortionType"_ustr, WID_PORTIONTYPE, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 },
+ { u"TextUserDefinedAttributes"_ustr, EE_CHAR_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0},
+ { u"ParaUserDefinedAttributes"_ustr, EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0},
+ };
+ return aSvxTextPortionPropertyMap;
+}
+const SvxItemPropertySet* ImplGetSvxTextPortionSvxPropertySet()
+{
+ static SvxItemPropertySet aSvxTextPortionPropertySet( ImplGetSvxTextPortionPropertyMap(), EditEngine::GetGlobalItemPool() );
+ return &aSvxTextPortionPropertySet;
+}
+
+static const SfxItemPropertySet* ImplGetSvxTextPortionSfxPropertySet()
+{
+ static SfxItemPropertySet aSvxTextPortionSfxPropertySet( ImplGetSvxTextPortionPropertyMap() );
+ return &aSvxTextPortionSfxPropertySet;
+}
+
+std::span<const SfxItemPropertyMapEntry> ImplGetSvxUnoOutlinerTextCursorPropertyMap()
+{
+ // Propertymap for an Outliner Text
+ static const SfxItemPropertyMapEntry aSvxUnoOutlinerTextCursorPropertyMap[] =
+ {
+ SVX_UNOEDIT_CHAR_PROPERTIES,
+ SVX_UNOEDIT_FONT_PROPERTIES,
+ SVX_UNOEDIT_OUTLINER_PROPERTIES,
+ SVX_UNOEDIT_PARA_PROPERTIES,
+ { u"TextUserDefinedAttributes"_ustr, EE_CHAR_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0},
+ { u"ParaUserDefinedAttributes"_ustr, EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0},
+ };
+
+ return aSvxUnoOutlinerTextCursorPropertyMap;
+}
+static const SfxItemPropertySet* ImplGetSvxUnoOutlinerTextCursorSfxPropertySet()
+{
+ static SfxItemPropertySet aTextCursorSfxPropertySet( ImplGetSvxUnoOutlinerTextCursorPropertyMap() );
+ return &aTextCursorSfxPropertySet;
+}
+
+
+// helper for Item/Property conversion
+
+
+void GetSelection( struct ESelection& rSel, SvxTextForwarder const * pForwarder ) noexcept
+{
+ DBG_ASSERT( pForwarder, "I need a valid SvxTextForwarder!" );
+ if( pForwarder )
+ {
+ sal_Int32 nParaCount = pForwarder->GetParagraphCount();
+ if(nParaCount>0)
+ nParaCount--;
+
+ rSel = ESelection( 0,0, nParaCount, pForwarder->GetTextLen( nParaCount ));
+ }
+}
+
+void CheckSelection( struct ESelection& rSel, SvxTextForwarder const * pForwarder ) noexcept
+{
+ DBG_ASSERT( pForwarder, "I need a valid SvxTextForwarder!" );
+ if( !pForwarder )
+ return;
+
+ if( rSel.nStartPara == EE_PARA_MAX_COUNT )
+ {
+ ::GetSelection( rSel, pForwarder );
+ }
+ else
+ {
+ ESelection aMaxSelection;
+ GetSelection( aMaxSelection, pForwarder );
+
+ // check start position
+ if( rSel.nStartPara < aMaxSelection.nStartPara )
+ {
+ rSel.nStartPara = aMaxSelection.nStartPara;
+ rSel.nStartPos = aMaxSelection.nStartPos;
+ }
+ else if( rSel.nStartPara > aMaxSelection.nEndPara )
+ {
+ rSel.nStartPara = aMaxSelection.nEndPara;
+ rSel.nStartPos = aMaxSelection.nEndPos;
+ }
+ else if( rSel.nStartPos > pForwarder->GetTextLen( rSel.nStartPara ) )
+ {
+ rSel.nStartPos = pForwarder->GetTextLen( rSel.nStartPara );
+ }
+
+ // check end position
+ if( rSel.nEndPara < aMaxSelection.nStartPara )
+ {
+ rSel.nEndPara = aMaxSelection.nStartPara;
+ rSel.nEndPos = aMaxSelection.nStartPos;
+ }
+ else if( rSel.nEndPara > aMaxSelection.nEndPara )
+ {
+ rSel.nEndPara = aMaxSelection.nEndPara;
+ rSel.nEndPos = aMaxSelection.nEndPos;
+ }
+ else if( rSel.nEndPos > pForwarder->GetTextLen( rSel.nEndPara ) )
+ {
+ rSel.nEndPos = pForwarder->GetTextLen( rSel.nEndPara );
+ }
+ }
+}
+
+static void CheckSelection( struct ESelection& rSel, SvxEditSource *pEdit ) noexcept
+{
+ if (!pEdit)
+ return;
+ CheckSelection( rSel, pEdit->GetTextForwarder() );
+}
+
+
+
+
+UNO3_GETIMPLEMENTATION_IMPL( SvxUnoTextRangeBase );
+
+SvxUnoTextRangeBase::SvxUnoTextRangeBase(const SvxItemPropertySet* _pSet)
+ : mpPropSet(_pSet)
+{
+}
+
+SvxUnoTextRangeBase::SvxUnoTextRangeBase(const SvxEditSource* pSource, const SvxItemPropertySet* _pSet)
+: mpPropSet(_pSet)
+{
+ SolarMutexGuard aGuard;
+
+ DBG_ASSERT(pSource,"SvxUnoTextRangeBase: I need a valid SvxEditSource!");
+
+ mpEditSource = pSource->Clone();
+ if (mpEditSource != nullptr)
+ {
+ ESelection aSelection;
+ ::GetSelection( aSelection, mpEditSource->GetTextForwarder() );
+ SetSelection( aSelection );
+
+ mpEditSource->addRange( this );
+ }
+}
+
+SvxUnoTextRangeBase::SvxUnoTextRangeBase(const SvxUnoTextRangeBase& rRange)
+: text::XTextRange()
+, beans::XPropertySet()
+, beans::XMultiPropertySet()
+, beans::XMultiPropertyStates()
+, beans::XPropertyState()
+, lang::XServiceInfo()
+, text::XTextRangeCompare()
+, lang::XUnoTunnel()
+, osl::DebugBase<SvxUnoTextRangeBase>()
+, mpPropSet(rRange.getPropertySet())
+{
+ SolarMutexGuard aGuard;
+
+ if (rRange.mpEditSource)
+ mpEditSource = rRange.mpEditSource->Clone();
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ maSelection = rRange.maSelection;
+ CheckSelection( maSelection, pForwarder );
+ }
+
+ if( mpEditSource )
+ mpEditSource->addRange( this );
+}
+
+SvxUnoTextRangeBase::~SvxUnoTextRangeBase() noexcept
+{
+ if( mpEditSource )
+ mpEditSource->removeRange( this );
+}
+
+void SvxUnoTextRangeBase::SetEditSource( SvxEditSource* pSource ) noexcept
+{
+ DBG_ASSERT(pSource,"SvxUnoTextRangeBase: I need a valid SvxEditSource!");
+ DBG_ASSERT(mpEditSource==nullptr,"SvxUnoTextRangeBase::SetEditSource called while SvxEditSource already set" );
+
+ mpEditSource.reset( pSource );
+
+ maSelection.nStartPara = EE_PARA_MAX_COUNT;
+
+ if( mpEditSource )
+ mpEditSource->addRange( this );
+}
+
+/** puts a field item with a copy of the given FieldData into the itemset
+ corresponding with this range */
+void SvxUnoTextRangeBase::attachField( std::unique_ptr<SvxFieldData> pData ) noexcept
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ SvxFieldItem aField( std::move(pData), EE_FEATURE_FIELD );
+ pForwarder->QuickInsertField( std::move(aField), maSelection );
+ }
+}
+
+void SvxUnoTextRangeBase::SetSelection( const ESelection& rSelection ) noexcept
+{
+ SolarMutexGuard aGuard;
+
+ maSelection = rSelection;
+ CheckSelection( maSelection, mpEditSource.get() );
+}
+
+// Interface XTextRange ( XText )
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextRangeBase::getStart()
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextRange > xRange;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ CheckSelection( maSelection, pForwarder );
+
+ SvxUnoTextBase* pText = comphelper::getFromUnoTunnel<SvxUnoTextBase>( getText() );
+
+ if(pText == nullptr)
+ throw uno::RuntimeException();
+
+ rtl::Reference<SvxUnoTextRange> pRange = new SvxUnoTextRange( *pText );
+ xRange = pRange;
+
+ ESelection aNewSel = maSelection;
+ aNewSel.nEndPara = aNewSel.nStartPara;
+ aNewSel.nEndPos = aNewSel.nStartPos;
+ pRange->SetSelection( aNewSel );
+ }
+
+ return xRange;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextRangeBase::getEnd()
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextRange > xRet;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ CheckSelection( maSelection, pForwarder );
+
+ SvxUnoTextBase* pText = comphelper::getFromUnoTunnel<SvxUnoTextBase>( getText() );
+
+ if(pText == nullptr)
+ throw uno::RuntimeException();
+
+ rtl::Reference<SvxUnoTextRange> pNew = new SvxUnoTextRange( *pText );
+ xRet = pNew;
+
+ ESelection aNewSel = maSelection;
+ aNewSel.nStartPara = aNewSel.nEndPara;
+ aNewSel.nStartPos = aNewSel.nEndPos;
+ pNew->SetSelection( aNewSel );
+ }
+ return xRet;
+}
+
+OUString SAL_CALL SvxUnoTextRangeBase::getString()
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ CheckSelection( maSelection, pForwarder );
+
+ return pForwarder->GetText( maSelection );
+ }
+ else
+ {
+ return OUString();
+ }
+}
+
+void SAL_CALL SvxUnoTextRangeBase::setString(const OUString& aString)
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( !pForwarder )
+ return;
+
+ CheckSelection( maSelection, pForwarder );
+
+ OUString aConverted(convertLineEnd(aString, LINEEND_LF)); // Simply count the number of line endings
+
+ pForwarder->QuickInsertText( aConverted, maSelection );
+ mpEditSource->UpdateData();
+
+ // Adapt selection
+ //! It would be easier if the EditEngine would return the selection
+ //! on QuickInsertText...
+ CollapseToStart();
+
+ sal_Int32 nLen = aConverted.getLength();
+ if (nLen)
+ GoRight( nLen, true );
+}
+
+// Interface beans::XPropertySet
+uno::Reference< beans::XPropertySetInfo > SAL_CALL SvxUnoTextRangeBase::getPropertySetInfo()
+{
+ return mpPropSet->getPropertySetInfo();
+}
+
+void SAL_CALL SvxUnoTextRangeBase::setPropertyValue(const OUString& PropertyName, const uno::Any& aValue)
+{
+ if (PropertyName == UNO_TR_PROP_SELECTION)
+ {
+ text::TextRangeSelection aSel = aValue.get<text::TextRangeSelection>();
+ SetSelection(toESelection(aSel));
+
+ return;
+ }
+
+ _setPropertyValue( PropertyName, aValue );
+}
+
+void SvxUnoTextRangeBase::_setPropertyValue( const OUString& PropertyName, const uno::Any& aValue, sal_Int32 nPara )
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ CheckSelection( maSelection, pForwarder );
+
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName );
+ if ( pMap )
+ {
+ ESelection aSel( GetSelection() );
+ bool bParaAttrib = (pMap->nWID >= EE_PARA_START) && ( pMap->nWID <= EE_PARA_END );
+
+ if (pMap->nWID == WID_PARASTYLENAME)
+ {
+ OUString aStyle = aValue.get<OUString>();
+
+ sal_Int32 nEndPara;
+
+ if( nPara == -1 )
+ {
+ nPara = aSel.nStartPara;
+ nEndPara = aSel.nEndPara;
+ }
+ else
+ {
+ // only one paragraph
+ nEndPara = nPara;
+ }
+
+ while( nPara <= nEndPara )
+ {
+ pForwarder->SetStyleSheet(nPara, aStyle);
+ nPara++;
+ }
+ }
+ else if ( nPara == -1 && !bParaAttrib )
+ {
+ SfxItemSet aOldSet( pForwarder->GetAttribs( aSel ) );
+ // we have a selection and no para attribute
+ SfxItemSet aNewSet( *aOldSet.GetPool(), aOldSet.GetRanges() );
+
+ setPropertyValue( pMap, aValue, maSelection, aOldSet, aNewSet );
+
+
+ pForwarder->QuickSetAttribs( aNewSet, GetSelection() );
+ }
+ else
+ {
+ sal_Int32 nEndPara;
+
+ if( nPara == -1 )
+ {
+ nPara = aSel.nStartPara;
+ nEndPara = aSel.nEndPara;
+ }
+ else
+ {
+ // only one paragraph
+ nEndPara = nPara;
+ }
+
+ while( nPara <= nEndPara )
+ {
+ // we have a paragraph
+ SfxItemSet aSet( pForwarder->GetParaAttribs( nPara ) );
+ setPropertyValue( pMap, aValue, maSelection, aSet, aSet );
+ pForwarder->SetParaAttribs( nPara, aSet );
+ nPara++;
+ }
+ }
+
+ GetEditSource()->UpdateData();
+ return;
+ }
+ }
+
+ throw beans::UnknownPropertyException(PropertyName);
+}
+
+void SvxUnoTextRangeBase::setPropertyValue( const SfxItemPropertyMapEntry* pMap, const uno::Any& rValue, const ESelection& rSelection, const SfxItemSet& rOldSet, SfxItemSet& rNewSet )
+{
+ if(!SetPropertyValueHelper( pMap, rValue, rNewSet, &rSelection, GetEditSource() ))
+ {
+ // For parts of composite items with multiple properties (eg background)
+ // must be taken from the document before the old item.
+ rNewSet.Put(rOldSet.Get(pMap->nWID)); // Old Item in new Set
+ SvxItemPropertySet::setPropertyValue(pMap, rValue, rNewSet, false );
+ }
+}
+
+bool SvxUnoTextRangeBase::SetPropertyValueHelper( const SfxItemPropertyMapEntry* pMap, const uno::Any& aValue, SfxItemSet& rNewSet, const ESelection* pSelection /* = NULL */, SvxEditSource* pEditSource /* = NULL*/ )
+{
+ switch( pMap->nWID )
+ {
+ case WID_FONTDESC:
+ {
+ awt::FontDescriptor aDesc;
+ if(aValue >>= aDesc)
+ {
+ SvxUnoFontDescriptor::FillItemSet( aDesc, rNewSet );
+ return true;
+ }
+ }
+ break;
+
+ case EE_PARA_NUMBULLET:
+ {
+ uno::Reference< container::XIndexReplace > xRule;
+ return !aValue.hasValue() || ((aValue >>= xRule) && !xRule.is());
+ }
+
+ case EE_PARA_OUTLLEVEL:
+ {
+ SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
+ if(pForwarder && pSelection)
+ {
+ sal_Int16 nLevel = sal_Int16();
+ if( aValue >>= nLevel )
+ {
+ // #101004# Call interface method instead of unsafe cast
+ if(! pForwarder->SetDepth( pSelection->nStartPara, nLevel ) )
+ throw lang::IllegalArgumentException();
+
+ // If valid, then not yet finished. Also needs to be added to paragraph props.
+ return nLevel < -1 || nLevel > 9;
+ }
+ }
+ }
+ break;
+ case WID_NUMBERINGSTARTVALUE:
+ {
+ SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
+ if(pForwarder && pSelection)
+ {
+ sal_Int16 nStartValue = -1;
+ if( aValue >>= nStartValue )
+ {
+ pForwarder->SetNumberingStartValue( pSelection->nStartPara, nStartValue );
+ return true;
+ }
+ }
+ }
+ break;
+ case WID_PARAISNUMBERINGRESTART:
+ {
+ SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
+ if(pForwarder && pSelection)
+ {
+ bool bParaIsNumberingRestart = false;
+ if( aValue >>= bParaIsNumberingRestart )
+ {
+ pForwarder->SetParaIsNumberingRestart( pSelection->nStartPara, bParaIsNumberingRestart );
+ return true;
+ }
+ }
+ }
+ break;
+ case EE_PARA_BULLETSTATE:
+ {
+ bool bBullet = true;
+ if( aValue >>= bBullet )
+ {
+ SfxBoolItem aItem( EE_PARA_BULLETSTATE, bBullet );
+ rNewSet.Put(aItem);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ throw lang::IllegalArgumentException();
+}
+
+uno::Any SAL_CALL SvxUnoTextRangeBase::getPropertyValue(const OUString& PropertyName)
+{
+ if (PropertyName == UNO_TR_PROP_SELECTION)
+ {
+ const ESelection& rSel = GetSelection();
+ text::TextRangeSelection aSel;
+ aSel.Start.Paragraph = rSel.nStartPara;
+ aSel.Start.PositionInParagraph = rSel.nStartPos;
+ aSel.End.Paragraph = rSel.nEndPara;
+ aSel.End.PositionInParagraph = rSel.nEndPos;
+ return uno::Any(aSel);
+ }
+
+ return _getPropertyValue( PropertyName );
+}
+
+uno::Any SvxUnoTextRangeBase::_getPropertyValue(const OUString& PropertyName, sal_Int32 nPara )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Any aAny;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName );
+ if( pMap )
+ {
+ std::optional<SfxItemSet> oAttribs;
+ if( nPara != -1 )
+ oAttribs.emplace(pForwarder->GetParaAttribs( nPara ).CloneAsValue());
+ else
+ oAttribs.emplace(pForwarder->GetAttribs( GetSelection() ).CloneAsValue());
+
+ // Replace Dontcare with Default, so that one always has a mirror
+ oAttribs->ClearInvalidItems();
+
+ getPropertyValue( pMap, aAny, *oAttribs );
+
+ return aAny;
+ }
+ }
+
+ throw beans::UnknownPropertyException(PropertyName);
+}
+
+void SvxUnoTextRangeBase::getPropertyValue( const SfxItemPropertyMapEntry* pMap, uno::Any& rAny, const SfxItemSet& rSet )
+{
+ switch( pMap->nWID )
+ {
+ case EE_FEATURE_FIELD:
+ if ( rSet.GetItemState( EE_FEATURE_FIELD, false ) == SfxItemState::SET )
+ {
+ const SvxFieldItem* pItem = rSet.GetItem<SvxFieldItem>( EE_FEATURE_FIELD );
+ const SvxFieldData* pData = pItem->GetField();
+ uno::Reference< text::XTextRange > xAnchor( this );
+
+ // get presentation string for field
+ std::optional<Color> pTColor;
+ std::optional<Color> pFColor;
+ std::optional<FontLineStyle> pFldLineStyle;
+
+ SvxTextForwarder* pForwarder = mpEditSource->GetTextForwarder();
+ OUString aPresentation( pForwarder->CalcFieldValue( SvxFieldItem(*pData, EE_FEATURE_FIELD), maSelection.nStartPara, maSelection.nStartPos, pTColor, pFColor, pFldLineStyle ) );
+
+ uno::Reference< text::XTextField > xField( new SvxUnoTextField( xAnchor, aPresentation, pData ) );
+ rAny <<= xField;
+ }
+ break;
+
+ case WID_PORTIONTYPE:
+ if ( rSet.GetItemState( EE_FEATURE_FIELD, false ) == SfxItemState::SET )
+ {
+ rAny <<= OUString("TextField");
+ }
+ else
+ {
+ rAny <<= OUString("Text");
+ }
+ break;
+
+ case WID_PARASTYLENAME:
+ {
+ rAny <<= GetEditSource()->GetTextForwarder()->GetStyleSheet(maSelection.nStartPara);
+ }
+ break;
+
+ default:
+ if(!GetPropertyValueHelper( *const_cast<SfxItemSet*>(&rSet), pMap, rAny, &maSelection, GetEditSource() ))
+ rAny = SvxItemPropertySet::getPropertyValue(pMap, rSet, true, false );
+ }
+}
+
+bool SvxUnoTextRangeBase::GetPropertyValueHelper( SfxItemSet const & rSet, const SfxItemPropertyMapEntry* pMap, uno::Any& aAny, const ESelection* pSelection /* = NULL */, SvxEditSource* pEditSource /* = NULL */ )
+{
+ switch( pMap->nWID )
+ {
+ case WID_FONTDESC:
+ {
+ awt::FontDescriptor aDesc;
+ SvxUnoFontDescriptor::FillFromItemSet( rSet, aDesc );
+ aAny <<= aDesc;
+ }
+ break;
+
+ case EE_PARA_NUMBULLET:
+ {
+ SfxItemState eState = rSet.GetItemState( EE_PARA_NUMBULLET );
+ if( eState != SfxItemState::SET && eState != SfxItemState::DEFAULT)
+ throw uno::RuntimeException();
+
+ const SvxNumBulletItem* pBulletItem = rSet.GetItem( EE_PARA_NUMBULLET );
+
+ if( pBulletItem == nullptr )
+ throw uno::RuntimeException();
+
+ aAny <<= SvxCreateNumRule( pBulletItem->GetNumRule() );
+ }
+ break;
+
+ case EE_PARA_OUTLLEVEL:
+ {
+ SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
+ if(pForwarder && pSelection)
+ {
+ sal_Int16 nLevel = pForwarder->GetDepth( pSelection->nStartPara );
+ if( nLevel >= 0 )
+ aAny <<= nLevel;
+ }
+ }
+ break;
+ case WID_NUMBERINGSTARTVALUE:
+ {
+ SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
+ if(pForwarder && pSelection)
+ aAny <<= pForwarder->GetNumberingStartValue( pSelection->nStartPara );
+ }
+ break;
+ case WID_PARAISNUMBERINGRESTART:
+ {
+ SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
+ if(pForwarder && pSelection)
+ aAny <<= pForwarder->IsParaIsNumberingRestart( pSelection->nStartPara );
+ }
+ break;
+
+ case EE_PARA_BULLETSTATE:
+ {
+ bool bState = false;
+ SfxItemState eState = rSet.GetItemState( EE_PARA_BULLETSTATE );
+ if( eState == SfxItemState::SET || eState == SfxItemState::DEFAULT )
+ {
+ const SfxBoolItem* pItem = rSet.GetItem<SfxBoolItem>( EE_PARA_BULLETSTATE );
+ bState = pItem->GetValue();
+ }
+
+ aAny <<= bState;
+ }
+ break;
+ default:
+
+ return false;
+ }
+
+ return true;
+}
+
+// is not (yet) supported
+void SAL_CALL SvxUnoTextRangeBase::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {}
+void SAL_CALL SvxUnoTextRangeBase::removePropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {}
+void SAL_CALL SvxUnoTextRangeBase::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {}
+void SAL_CALL SvxUnoTextRangeBase::removeVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {}
+
+// XMultiPropertySet
+void SAL_CALL SvxUnoTextRangeBase::setPropertyValues( const uno::Sequence< OUString >& aPropertyNames, const uno::Sequence< uno::Any >& aValues )
+{
+ _setPropertyValues( aPropertyNames, aValues );
+}
+
+void SvxUnoTextRangeBase::_setPropertyValues( const uno::Sequence< OUString >& aPropertyNames, const uno::Sequence< uno::Any >& aValues, sal_Int32 nPara )
+{
+ if (aPropertyNames.getLength() != aValues.getLength())
+ throw lang::IllegalArgumentException("lengths do not match",
+ static_cast<css::beans::XPropertySet*>(this), -1);
+
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( !pForwarder )
+ return;
+
+ CheckSelection( maSelection, pForwarder );
+
+ ESelection aSel( GetSelection() );
+
+ const OUString* pPropertyNames = aPropertyNames.getConstArray();
+ const uno::Any* pValues = aValues.getConstArray();
+ sal_Int32 nCount = aPropertyNames.getLength();
+
+ sal_Int32 nEndPara = nPara;
+ sal_Int32 nTempPara = nPara;
+
+ if( nTempPara == -1 )
+ {
+ nTempPara = aSel.nStartPara;
+ nEndPara = aSel.nEndPara;
+ }
+
+ std::optional<SfxItemSet> pOldAttrSet;
+ std::optional<SfxItemSet> pNewAttrSet;
+
+ std::optional<SfxItemSet> pOldParaSet;
+ std::optional<SfxItemSet> pNewParaSet;
+
+ std::optional<OUString> aStyleName;
+
+ for( ; nCount; nCount--, pPropertyNames++, pValues++ )
+ {
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( *pPropertyNames );
+
+ if( pMap )
+ {
+ bool bParaAttrib = (pMap->nWID >= EE_PARA_START) && ( pMap->nWID <= EE_PARA_END );
+
+ if (pMap->nWID == WID_PARASTYLENAME)
+ {
+ aStyleName.emplace((*pValues).get<OUString>());
+ }
+ else if( (nPara == -1) && !bParaAttrib )
+ {
+ if( !pNewAttrSet )
+ {
+ pOldAttrSet.emplace( pForwarder->GetAttribs( aSel ) );
+ pNewAttrSet.emplace( *pOldAttrSet->GetPool(), pOldAttrSet->GetRanges() );
+ }
+
+ setPropertyValue( pMap, *pValues, GetSelection(), *pOldAttrSet, *pNewAttrSet );
+
+ if( pMap->nWID >= EE_ITEMS_START && pMap->nWID <= EE_ITEMS_END )
+ {
+ const SfxPoolItem* pItem;
+ if( pNewAttrSet->GetItemState( pMap->nWID, true, &pItem ) == SfxItemState::SET )
+ {
+ pOldAttrSet->Put( *pItem );
+ }
+ }
+ }
+ else
+ {
+ if( !pNewParaSet )
+ {
+ const SfxItemSet & rSet = pForwarder->GetParaAttribs( nTempPara );
+ pOldParaSet.emplace( rSet );
+ pNewParaSet.emplace( *pOldParaSet->GetPool(), pOldParaSet->GetRanges() );
+ }
+
+ setPropertyValue( pMap, *pValues, GetSelection(), *pOldParaSet, *pNewParaSet );
+
+ if( pMap->nWID >= EE_ITEMS_START && pMap->nWID <= EE_ITEMS_END )
+ {
+ const SfxPoolItem* pItem;
+ if( pNewParaSet->GetItemState( pMap->nWID, true, &pItem ) == SfxItemState::SET )
+ {
+ pOldParaSet->Put( *pItem );
+ }
+ }
+
+ }
+ }
+ }
+
+ bool bNeedsUpdate = false;
+
+ if( pNewParaSet || aStyleName )
+ {
+ if( pNewParaSet->Count() )
+ {
+ while( nTempPara <= nEndPara )
+ {
+ SfxItemSet aSet( pForwarder->GetParaAttribs( nTempPara ) );
+ aSet.Put( *pNewParaSet );
+ pForwarder->SetParaAttribs( nTempPara, aSet );
+ if (aStyleName)
+ pForwarder->SetStyleSheet(nTempPara, *aStyleName);
+ nTempPara++;
+ }
+ bNeedsUpdate = true;
+ }
+
+ pNewParaSet.reset();
+ pOldParaSet.reset();
+ }
+
+ if( pNewAttrSet )
+ {
+ if( pNewAttrSet->Count() )
+ {
+ pForwarder->QuickSetAttribs( *pNewAttrSet, GetSelection() );
+ bNeedsUpdate = true;
+ }
+ pNewAttrSet.reset();
+ pOldAttrSet.reset();
+ }
+
+ if( bNeedsUpdate )
+ GetEditSource()->UpdateData();
+}
+
+uno::Sequence< uno::Any > SAL_CALL SvxUnoTextRangeBase::getPropertyValues( const uno::Sequence< OUString >& aPropertyNames )
+{
+ return _getPropertyValues( aPropertyNames );
+}
+
+uno::Sequence< uno::Any > SvxUnoTextRangeBase::_getPropertyValues( const uno::Sequence< OUString >& aPropertyNames, sal_Int32 nPara )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nCount = aPropertyNames.getLength();
+
+
+ uno::Sequence< uno::Any > aValues( nCount );
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ std::optional<SfxItemSet> oAttribs;
+ if( nPara != -1 )
+ oAttribs.emplace(pForwarder->GetParaAttribs( nPara ).CloneAsValue());
+ else
+ oAttribs.emplace(pForwarder->GetAttribs( GetSelection() ).CloneAsValue() );
+
+ oAttribs->ClearInvalidItems();
+
+ const OUString* pPropertyNames = aPropertyNames.getConstArray();
+ uno::Any* pValues = aValues.getArray();
+
+ for( ; nCount; nCount--, pPropertyNames++, pValues++ )
+ {
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( *pPropertyNames );
+ if( pMap )
+ {
+ getPropertyValue( pMap, *pValues, *oAttribs );
+ }
+ }
+ }
+
+ return aValues;
+}
+
+void SAL_CALL SvxUnoTextRangeBase::addPropertiesChangeListener( const uno::Sequence< OUString >& , const uno::Reference< beans::XPropertiesChangeListener >& )
+{
+}
+
+void SAL_CALL SvxUnoTextRangeBase::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& )
+{
+}
+
+void SAL_CALL SvxUnoTextRangeBase::firePropertiesChangeEvent( const uno::Sequence< OUString >& , const uno::Reference< beans::XPropertiesChangeListener >& )
+{
+}
+
+// beans::XPropertyState
+beans::PropertyState SAL_CALL SvxUnoTextRangeBase::getPropertyState( const OUString& PropertyName )
+{
+ return _getPropertyState( PropertyName );
+}
+
+const sal_uInt16 aSvxUnoFontDescriptorWhichMap[] = { EE_CHAR_FONTINFO, EE_CHAR_FONTHEIGHT, EE_CHAR_ITALIC,
+ EE_CHAR_UNDERLINE, EE_CHAR_WEIGHT, EE_CHAR_STRIKEOUT, EE_CHAR_CASEMAP,
+ EE_CHAR_WLM, 0 };
+
+beans::PropertyState SvxUnoTextRangeBase::_getPropertyState(const SfxItemPropertyMapEntry* pMap, sal_Int32 nPara)
+{
+ if ( pMap )
+ {
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ SfxItemState eItemState(SfxItemState::DEFAULT);
+ bool bItemStateSet(false);
+
+ switch( pMap->nWID )
+ {
+ case WID_FONTDESC:
+ {
+ const sal_uInt16* pWhichId = aSvxUnoFontDescriptorWhichMap;
+ while( *pWhichId )
+ {
+ const SfxItemState eTempItemState(nPara != -1
+ ? pForwarder->GetItemState( nPara, *pWhichId )
+ : pForwarder->GetItemState( GetSelection(), *pWhichId ));
+
+ switch( eTempItemState )
+ {
+ case SfxItemState::DISABLED:
+ case SfxItemState::DONTCARE:
+ eItemState = SfxItemState::DONTCARE;
+ bItemStateSet = true;
+ break;
+
+ case SfxItemState::DEFAULT:
+ if( !bItemStateSet )
+ {
+ eItemState = SfxItemState::DEFAULT;
+ bItemStateSet = true;
+ }
+ break;
+
+ case SfxItemState::SET:
+ if( !bItemStateSet )
+ {
+ eItemState = SfxItemState::SET;
+ bItemStateSet = true;
+ }
+ break;
+ default:
+ throw beans::UnknownPropertyException();
+ }
+
+ pWhichId++;
+ }
+ }
+ break;
+
+ case WID_NUMBERINGSTARTVALUE:
+ case WID_PARAISNUMBERINGRESTART:
+ case WID_PARASTYLENAME:
+ eItemState = SfxItemState::SET;
+ bItemStateSet = true;
+ break;
+
+ default:
+ if(0 != pMap->nWID)
+ {
+ if( nPara != -1 )
+ eItemState = pForwarder->GetItemState( nPara, pMap->nWID );
+ else
+ eItemState = pForwarder->GetItemState( GetSelection(), pMap->nWID );
+
+ bItemStateSet = true;
+ }
+ break;
+ }
+
+ if(bItemStateSet)
+ {
+ switch( eItemState )
+ {
+ case SfxItemState::DONTCARE:
+ case SfxItemState::DISABLED:
+ return beans::PropertyState_AMBIGUOUS_VALUE;
+ case SfxItemState::SET:
+ return beans::PropertyState_DIRECT_VALUE;
+ case SfxItemState::DEFAULT:
+ return beans::PropertyState_DEFAULT_VALUE;
+ default: break;
+ }
+ }
+ }
+ }
+ throw beans::UnknownPropertyException();
+}
+
+beans::PropertyState SvxUnoTextRangeBase::_getPropertyState(std::u16string_view PropertyName, sal_Int32 nPara /* = -1 */)
+{
+ SolarMutexGuard aGuard;
+
+ return _getPropertyState( mpPropSet->getPropertyMapEntry( PropertyName ), nPara);
+}
+
+uno::Sequence< beans::PropertyState > SAL_CALL SvxUnoTextRangeBase::getPropertyStates( const uno::Sequence< OUString >& aPropertyName )
+{
+ return _getPropertyStates( aPropertyName );
+}
+
+uno::Sequence< beans::PropertyState > SvxUnoTextRangeBase::_getPropertyStates(const uno::Sequence< OUString >& PropertyName, sal_Int32 nPara /* = -1 */)
+{
+ uno::Sequence< beans::PropertyState > aRet( PropertyName.getLength() );
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ std::optional<SfxItemSet> pSet;
+ if( nPara != -1 )
+ {
+ pSet.emplace( pForwarder->GetParaAttribs( nPara ) );
+ }
+ else
+ {
+ ESelection aSel( GetSelection() );
+ CheckSelection( aSel, pForwarder );
+ pSet.emplace( pForwarder->GetAttribs( aSel, EditEngineAttribs::OnlyHard ) );
+ }
+
+ beans::PropertyState* pState = aRet.getArray();
+ for( const OUString& rName : PropertyName )
+ {
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( rName );
+ if( !_getOnePropertyStates(*pSet, pMap, *pState++) )
+ {
+ throw beans::UnknownPropertyException(rName);
+ }
+ }
+ }
+
+ return aRet;
+}
+
+bool SvxUnoTextRangeBase::_getOnePropertyStates(const SfxItemSet& rSet, const SfxItemPropertyMapEntry* pMap, beans::PropertyState& rState)
+{
+ if (!pMap)
+ return true;
+ SfxItemState eItemState = SfxItemState::DEFAULT;
+ bool bItemStateSet(false);
+
+ bool bUnknownPropertyFound = false;
+ switch( pMap->nWID )
+ {
+ case WID_FONTDESC:
+ {
+ const sal_uInt16* pWhichId = aSvxUnoFontDescriptorWhichMap;
+ while( *pWhichId )
+ {
+ const SfxItemState eTempItemState(rSet.GetItemState( *pWhichId ));
+
+ switch( eTempItemState )
+ {
+ case SfxItemState::DISABLED:
+ case SfxItemState::DONTCARE:
+ eItemState = SfxItemState::DONTCARE;
+ bItemStateSet = true;
+ break;
+
+ case SfxItemState::DEFAULT:
+ if( !bItemStateSet )
+ {
+ eItemState = SfxItemState::DEFAULT;
+ bItemStateSet = true;
+ }
+ break;
+
+ case SfxItemState::SET:
+ if( !bItemStateSet )
+ {
+ eItemState = SfxItemState::SET;
+ bItemStateSet = true;
+ }
+ break;
+ default:
+ bUnknownPropertyFound = true;
+ break;
+ }
+
+ pWhichId++;
+ }
+ }
+ break;
+
+ case WID_NUMBERINGSTARTVALUE:
+ case WID_PARAISNUMBERINGRESTART:
+ case WID_PARASTYLENAME:
+ eItemState = SfxItemState::SET;
+ bItemStateSet = true;
+ break;
+
+ default:
+ if(0 != pMap->nWID)
+ {
+ eItemState = rSet.GetItemState( pMap->nWID, false );
+ bItemStateSet = true;
+ }
+ break;
+ }
+
+ if( bUnknownPropertyFound )
+ return false;
+
+ if(bItemStateSet)
+ {
+ if (pMap->nWID == EE_CHAR_COLOR)
+ {
+ // Theme & effects can be DEFAULT_VALUE, even if the same pool item has a color
+ // which is a DIRECT_VALUE.
+ const SvxColorItem* pColor = rSet.GetItem<SvxColorItem>(EE_CHAR_COLOR);
+ if (!pColor)
+ {
+ SAL_WARN("editeng", "Missing EE_CHAR_COLOR SvxColorItem");
+ return false;
+ }
+ switch (pMap->nMemberId)
+ {
+ case MID_COLOR_THEME_INDEX:
+ if (!pColor->getComplexColor().isValidThemeType())
+ {
+ eItemState = SfxItemState::DEFAULT;
+ }
+ break;
+ case MID_COLOR_LUM_MOD:
+ {
+ sal_Int16 nLumMod = 10000;
+ for (auto const& rTransform : pColor->getComplexColor().getTransformations())
+ {
+ if (rTransform.meType == model::TransformationType::LumMod)
+ nLumMod = rTransform.mnValue;
+ }
+ if (nLumMod == 10000)
+ {
+ eItemState = SfxItemState::DEFAULT;
+ }
+ break;
+ }
+ case MID_COLOR_LUM_OFF:
+ {
+ sal_Int16 nLumOff = 0;
+ for (auto const& rTransform : pColor->getComplexColor().getTransformations())
+ {
+ if (rTransform.meType == model::TransformationType::LumOff)
+ nLumOff = rTransform.mnValue;
+ }
+ if (nLumOff == 0)
+ {
+ eItemState = SfxItemState::DEFAULT;
+ }
+ break;
+ }
+ case MID_COMPLEX_COLOR:
+ if (pColor->getComplexColor().getType() == model::ColorType::Unused)
+ {
+ eItemState = SfxItemState::DEFAULT;
+ }
+ break;
+ }
+ }
+
+ switch( eItemState )
+ {
+ case SfxItemState::SET:
+ rState = beans::PropertyState_DIRECT_VALUE;
+ break;
+ case SfxItemState::DEFAULT:
+ rState = beans::PropertyState_DEFAULT_VALUE;
+ break;
+// case SfxItemState::DONTCARE:
+// case SfxItemState::DISABLED:
+ default:
+ rState = beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ }
+ else
+ {
+ rState = beans::PropertyState_AMBIGUOUS_VALUE;
+ }
+ return true;
+}
+
+void SAL_CALL SvxUnoTextRangeBase::setPropertyToDefault( const OUString& PropertyName )
+{
+ _setPropertyToDefault( PropertyName );
+}
+
+void SvxUnoTextRangeBase::_setPropertyToDefault(const OUString& PropertyName, sal_Int32 nPara /* = -1 */)
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+
+ if( pForwarder )
+ {
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( PropertyName );
+ if ( pMap )
+ {
+ CheckSelection( maSelection, mpEditSource->GetTextForwarder() );
+ _setPropertyToDefault( pForwarder, pMap, nPara );
+ return;
+ }
+ }
+
+ throw beans::UnknownPropertyException(PropertyName);
+}
+
+void SvxUnoTextRangeBase::_setPropertyToDefault(SvxTextForwarder* pForwarder, const SfxItemPropertyMapEntry* pMap, sal_Int32 nPara )
+{
+ do
+ {
+ SfxItemSet aSet(*pForwarder->GetPool());
+
+ if( pMap->nWID == WID_FONTDESC )
+ {
+ SvxUnoFontDescriptor::setPropertyToDefault( aSet );
+ }
+ else if( pMap->nWID == WID_NUMBERINGSTARTVALUE )
+ {
+ pForwarder->SetNumberingStartValue( maSelection.nStartPara, -1 );
+ }
+ else if( pMap->nWID == WID_PARAISNUMBERINGRESTART )
+ {
+ pForwarder->SetParaIsNumberingRestart( maSelection.nStartPara, false );
+ }
+ else
+ {
+ aSet.InvalidateItem( pMap->nWID );
+ }
+
+ if(nPara != -1)
+ pForwarder->SetParaAttribs( nPara, aSet );
+ else
+ pForwarder->QuickSetAttribs( aSet, GetSelection() );
+
+ GetEditSource()->UpdateData();
+
+ return;
+ }
+ while(false);
+}
+
+uno::Any SAL_CALL SvxUnoTextRangeBase::getPropertyDefault( const OUString& aPropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( aPropertyName );
+ if( pMap )
+ {
+ SfxItemPool* pPool = pForwarder->GetPool();
+
+ switch( pMap->nWID )
+ {
+ case WID_FONTDESC:
+ return SvxUnoFontDescriptor::getPropertyDefault( pPool );
+
+ case EE_PARA_OUTLLEVEL:
+ {
+ uno::Any aAny;
+ return aAny;
+ }
+
+ case WID_NUMBERINGSTARTVALUE:
+ return uno::Any( sal_Int16(-1) );
+
+ case WID_PARAISNUMBERINGRESTART:
+ return uno::Any( false );
+
+ default:
+ {
+ // Get Default from ItemPool
+ if(SfxItemPool::IsWhich(pMap->nWID))
+ {
+ SfxItemSet aSet( *pPool, pMap->nWID, pMap->nWID );
+ aSet.Put(pPool->GetDefaultItem(pMap->nWID));
+ return SvxItemPropertySet::getPropertyValue(pMap, aSet, true, false );
+ }
+ }
+ }
+ }
+ }
+ throw beans::UnknownPropertyException(aPropertyName);
+}
+
+// beans::XMultiPropertyStates
+void SAL_CALL SvxUnoTextRangeBase::setAllPropertiesToDefault()
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+
+ if( pForwarder )
+ {
+ for (const SfxItemPropertyMapEntry* entry : mpPropSet->getPropertyMap().getPropertyEntries())
+ {
+ _setPropertyToDefault( pForwarder, entry, -1 );
+ }
+ }
+}
+
+void SAL_CALL SvxUnoTextRangeBase::setPropertiesToDefault( const uno::Sequence< OUString >& aPropertyNames )
+{
+ for( const OUString& rName : aPropertyNames )
+ {
+ setPropertyToDefault( rName );
+ }
+}
+
+uno::Sequence< uno::Any > SAL_CALL SvxUnoTextRangeBase::getPropertyDefaults( const uno::Sequence< OUString >& aPropertyNames )
+{
+ uno::Sequence< uno::Any > ret( aPropertyNames.getLength() );
+ uno::Any* pDefaults = ret.getArray();
+
+ for( const OUString& rName : aPropertyNames )
+ {
+ *pDefaults++ = getPropertyDefault( rName );
+ }
+
+ return ret;
+}
+
+// internal
+void SvxUnoTextRangeBase::CollapseToStart() noexcept
+{
+ CheckSelection( maSelection, mpEditSource.get() );
+
+ maSelection.nEndPara = maSelection.nStartPara;
+ maSelection.nEndPos = maSelection.nStartPos;
+}
+
+void SvxUnoTextRangeBase::CollapseToEnd() noexcept
+{
+ CheckSelection( maSelection, mpEditSource.get() );
+
+ maSelection.nStartPara = maSelection.nEndPara;
+ maSelection.nStartPos = maSelection.nEndPos;
+}
+
+bool SvxUnoTextRangeBase::IsCollapsed() noexcept
+{
+ CheckSelection( maSelection, mpEditSource.get() );
+
+ return ( maSelection.nStartPara == maSelection.nEndPara &&
+ maSelection.nStartPos == maSelection.nEndPos );
+}
+
+bool SvxUnoTextRangeBase::GoLeft(sal_Int32 nCount, bool Expand) noexcept
+{
+ CheckSelection( maSelection, mpEditSource.get() );
+
+ // #75098# use end position, as in Writer (start is anchor, end is cursor)
+ sal_Int32 nNewPos = maSelection.nEndPos;
+ sal_Int32 nNewPar = maSelection.nEndPara;
+
+ bool bOk = true;
+ SvxTextForwarder* pForwarder = nullptr;
+ while ( nCount > nNewPos && bOk )
+ {
+ if ( nNewPar == 0 )
+ bOk = false;
+ else
+ {
+ if ( !pForwarder )
+ pForwarder = mpEditSource->GetTextForwarder(); // first here, it is necessary...
+
+ --nNewPar;
+ nCount -= nNewPos + 1;
+ nNewPos = pForwarder->GetTextLen( nNewPar );
+ }
+ }
+
+ if ( bOk )
+ {
+ nNewPos = nNewPos - nCount;
+ maSelection.nStartPara = nNewPar;
+ maSelection.nStartPos = nNewPos;
+ }
+
+ if (!Expand)
+ CollapseToStart();
+
+ return bOk;
+}
+
+bool SvxUnoTextRangeBase::GoRight(sal_Int32 nCount, bool Expand) noexcept
+{
+ if (!mpEditSource)
+ return false;
+ SvxTextForwarder* pForwarder = mpEditSource->GetTextForwarder();
+ if( !pForwarder )
+ return false;
+
+ CheckSelection( maSelection, pForwarder );
+
+ sal_Int32 nNewPos = maSelection.nEndPos + nCount;
+ sal_Int32 nNewPar = maSelection.nEndPara;
+
+ bool bOk = true;
+ sal_Int32 nParCount = pForwarder->GetParagraphCount();
+ sal_Int32 nThisLen = pForwarder->GetTextLen( nNewPar );
+ while ( nNewPos > nThisLen && bOk )
+ {
+ if ( nNewPar + 1 >= nParCount )
+ bOk = false;
+ else
+ {
+ nNewPos -= nThisLen+1;
+ ++nNewPar;
+ nThisLen = pForwarder->GetTextLen( nNewPar );
+ }
+ }
+
+ if (bOk)
+ {
+ maSelection.nEndPara = nNewPar;
+ maSelection.nEndPos = nNewPos;
+ }
+
+ if (!Expand)
+ CollapseToEnd();
+
+ return bOk;
+}
+
+void SvxUnoTextRangeBase::GotoStart(bool Expand) noexcept
+{
+ maSelection.nStartPara = 0;
+ maSelection.nStartPos = 0;
+
+ if (!Expand)
+ CollapseToStart();
+}
+
+void SvxUnoTextRangeBase::GotoEnd(bool Expand) noexcept
+{
+ CheckSelection( maSelection, mpEditSource.get() );
+
+ SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
+ if( !pForwarder )
+ return;
+
+ sal_Int32 nPar = pForwarder->GetParagraphCount();
+ if (nPar)
+ --nPar;
+
+ maSelection.nEndPara = nPar;
+ maSelection.nEndPos = pForwarder->GetTextLen( nPar );
+
+ if (!Expand)
+ CollapseToEnd();
+}
+
+// lang::XServiceInfo
+sal_Bool SAL_CALL SvxUnoTextRangeBase::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+uno::Sequence< OUString > SAL_CALL SvxUnoTextRangeBase::getSupportedServiceNames()
+{
+ return getSupportedServiceNames_Static();
+}
+
+uno::Sequence< OUString > SvxUnoTextRangeBase::getSupportedServiceNames_Static()
+{
+ return { "com.sun.star.style.CharacterProperties",
+ "com.sun.star.style.CharacterPropertiesComplex",
+ "com.sun.star.style.CharacterPropertiesAsian" };
+}
+
+// XTextRangeCompare
+sal_Int16 SAL_CALL SvxUnoTextRangeBase::compareRegionStarts( const uno::Reference< text::XTextRange >& xR1, const uno::Reference< text::XTextRange >& xR2 )
+{
+ SvxUnoTextRangeBase* pR1 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR1 );
+ SvxUnoTextRangeBase* pR2 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR2 );
+
+ if( (pR1 == nullptr) || (pR2 == nullptr) )
+ throw lang::IllegalArgumentException();
+
+ const ESelection& r1 = pR1->maSelection;
+ const ESelection& r2 = pR2->maSelection;
+
+ if( r1.nStartPara == r2.nStartPara )
+ {
+ if( r1.nStartPos == r2.nStartPos )
+ return 0;
+ else
+ return r1.nStartPos < r2.nStartPos ? 1 : -1;
+ }
+ else
+ {
+ return r1.nStartPara < r2.nStartPara ? 1 : -1;
+ }
+}
+
+sal_Int16 SAL_CALL SvxUnoTextRangeBase::compareRegionEnds( const uno::Reference< text::XTextRange >& xR1, const uno::Reference< text::XTextRange >& xR2 )
+{
+ SvxUnoTextRangeBase* pR1 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR1 );
+ SvxUnoTextRangeBase* pR2 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR2 );
+
+ if( (pR1 == nullptr) || (pR2 == nullptr) )
+ throw lang::IllegalArgumentException();
+
+ const ESelection& r1 = pR1->maSelection;
+ const ESelection& r2 = pR2->maSelection;
+
+ if( r1.nEndPara == r2.nEndPara )
+ {
+ if( r1.nEndPos == r2.nEndPos )
+ return 0;
+ else
+ return r1.nEndPos < r2.nEndPos ? 1 : -1;
+ }
+ else
+ {
+ return r1.nEndPara < r2.nEndPara ? 1 : -1;
+ }
+}
+
+SvxUnoTextRange::SvxUnoTextRange(const SvxUnoTextBase& rParent, bool bPortion /* = false */)
+:SvxUnoTextRangeBase( rParent.GetEditSource(), bPortion ? ImplGetSvxTextPortionSvxPropertySet() : rParent.getPropertySet() ),
+ mbPortion( bPortion )
+{
+ xParentText = static_cast<text::XText*>(const_cast<SvxUnoTextBase *>(&rParent));
+}
+
+SvxUnoTextRange::~SvxUnoTextRange() noexcept
+{
+}
+
+uno::Any SAL_CALL SvxUnoTextRange::queryAggregation( const uno::Type & rType )
+{
+ QUERYINT( text::XTextRange );
+ else if( rType == cppu::UnoType<beans::XMultiPropertyStates>::get())
+ return uno::Any(uno::Reference< beans::XMultiPropertyStates >(this));
+ else if( rType == cppu::UnoType<beans::XPropertySet>::get())
+ return uno::Any(uno::Reference< beans::XPropertySet >(this));
+ else QUERYINT( beans::XPropertyState );
+ else QUERYINT( text::XTextRangeCompare );
+ else if( rType == cppu::UnoType<beans::XMultiPropertySet>::get())
+ return uno::Any(uno::Reference< beans::XMultiPropertySet >(this));
+ else QUERYINT( lang::XServiceInfo );
+ else QUERYINT( lang::XTypeProvider );
+ else QUERYINT( lang::XUnoTunnel );
+ else
+ return OWeakAggObject::queryAggregation( rType );
+}
+
+uno::Any SAL_CALL SvxUnoTextRange::queryInterface( const uno::Type & rType )
+{
+ return OWeakAggObject::queryInterface(rType);
+}
+
+void SAL_CALL SvxUnoTextRange::acquire()
+ noexcept
+{
+ OWeakAggObject::acquire();
+}
+
+void SAL_CALL SvxUnoTextRange::release()
+ noexcept
+{
+ OWeakAggObject::release();
+}
+
+// XTypeProvider
+
+uno::Sequence< uno::Type > SAL_CALL SvxUnoTextRange::getTypes()
+{
+ static const uno::Sequence< uno::Type > TYPES {
+ cppu::UnoType<text::XTextRange>::get(),
+ cppu::UnoType<beans::XPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertyStates>::get(),
+ cppu::UnoType<beans::XPropertyState>::get(),
+ cppu::UnoType<lang::XServiceInfo>::get(),
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<lang::XUnoTunnel>::get(),
+ cppu::UnoType<text::XTextRangeCompare>::get() };
+ return TYPES;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SvxUnoTextRange::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XTextRange
+uno::Reference< text::XText > SAL_CALL SvxUnoTextRange::getText()
+{
+ return xParentText;
+}
+
+// lang::XServiceInfo
+OUString SAL_CALL SvxUnoTextRange::getImplementationName()
+{
+ return "SvxUnoTextRange";
+}
+
+
+
+
+SvxUnoTextBase::SvxUnoTextBase(const SvxItemPropertySet* _pSet)
+ : SvxUnoTextRangeBase(_pSet)
+{
+}
+
+SvxUnoTextBase::SvxUnoTextBase(const SvxEditSource* pSource, const SvxItemPropertySet* _pSet, uno::Reference < text::XText > const & xParent)
+ : SvxUnoTextRangeBase(pSource, _pSet)
+{
+ xParentText = xParent;
+ ESelection aSelection;
+ ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
+ SetSelection( aSelection );
+}
+
+SvxUnoTextBase::SvxUnoTextBase(const SvxUnoTextBase& rText)
+: SvxUnoTextRangeBase( rText )
+, text::XTextAppend()
+, text::XTextCopy()
+, container::XEnumerationAccess()
+, text::XTextRangeMover()
+, lang::XTypeProvider()
+{
+ xParentText = rText.xParentText;
+}
+
+SvxUnoTextBase::~SvxUnoTextBase() noexcept
+{
+}
+
+// XInterface
+uno::Any SAL_CALL SvxUnoTextBase::queryAggregation( const uno::Type & rType )
+{
+ QUERYINT( text::XText );
+ QUERYINT( text::XSimpleText );
+ if( rType == cppu::UnoType<text::XTextRange>::get())
+ return uno::Any(uno::Reference< text::XTextRange >(static_cast<text::XText*>(this)));
+ QUERYINT(container::XEnumerationAccess );
+ QUERYINT( container::XElementAccess );
+ QUERYINT( beans::XMultiPropertyStates );
+ QUERYINT( beans::XPropertySet );
+ QUERYINT( beans::XMultiPropertySet );
+ QUERYINT( beans::XPropertyState );
+ QUERYINT( text::XTextRangeCompare );
+ QUERYINT( lang::XServiceInfo );
+ QUERYINT( text::XTextRangeMover );
+ QUERYINT( text::XTextCopy );
+ QUERYINT( text::XTextAppend );
+ QUERYINT( text::XParagraphAppend );
+ QUERYINT( text::XTextPortionAppend );
+ QUERYINT( lang::XTypeProvider );
+ QUERYINT( lang::XUnoTunnel );
+
+ return uno::Any();
+}
+
+// XTypeProvider
+
+uno::Sequence< uno::Type > SAL_CALL SvxUnoTextBase::getTypes()
+{
+ static const uno::Sequence< uno::Type > TYPES {
+ cppu::UnoType<text::XText>::get(),
+ cppu::UnoType<container::XEnumerationAccess>::get(),
+ cppu::UnoType<beans::XPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertyStates>::get(),
+ cppu::UnoType<beans::XPropertyState>::get(),
+ cppu::UnoType<text::XTextRangeMover>::get(),
+ cppu::UnoType<text::XTextAppend>::get(),
+ cppu::UnoType<text::XTextCopy>::get(),
+ cppu::UnoType<text::XParagraphAppend>::get(),
+ cppu::UnoType<text::XTextPortionAppend>::get(),
+ cppu::UnoType<lang::XServiceInfo>::get(),
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<lang::XUnoTunnel>::get(),
+ cppu::UnoType<text::XTextRangeCompare>::get() };
+ return TYPES;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SvxUnoTextBase::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+uno::Reference< text::XTextCursor > SvxUnoTextBase::createTextCursorBySelection( const ESelection& rSel )
+{
+ rtl::Reference<SvxUnoTextCursor> pCursor = new SvxUnoTextCursor( *this );
+ pCursor->SetSelection( rSel );
+ return pCursor;
+}
+
+// XSimpleText
+
+uno::Reference< text::XTextCursor > SAL_CALL SvxUnoTextBase::createTextCursor()
+{
+ SolarMutexGuard aGuard;
+ return new SvxUnoTextCursor( *this );
+}
+
+uno::Reference< text::XTextCursor > SAL_CALL SvxUnoTextBase::createTextCursorByRange( const uno::Reference< text::XTextRange >& aTextPosition )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextCursor > xCursor;
+
+ if( aTextPosition.is() )
+ {
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( aTextPosition );
+ if(pRange)
+ xCursor = createTextCursorBySelection( pRange->GetSelection() );
+ }
+
+ return xCursor;
+}
+
+void SAL_CALL SvxUnoTextBase::insertString( const uno::Reference< text::XTextRange >& xRange, const OUString& aString, sal_Bool bAbsorb )
+{
+ SolarMutexGuard aGuard;
+
+ if( !xRange.is() )
+ return;
+
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange );
+ if(!pRange)
+ return;
+
+ // setString on SvxUnoTextRangeBase instead of itself QuickInsertText
+ // and UpdateData, so that the selection will be adjusted to
+ // SvxUnoTextRangeBase. Actually all cursor objects of this Text must
+ // to be statement to be adapted!
+
+ if (!bAbsorb) // do not replace -> append on tail
+ pRange->CollapseToEnd();
+
+ pRange->setString( aString );
+
+ pRange->CollapseToEnd();
+
+ if (GetEditSource())
+ {
+ ESelection aSelection;
+ ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
+ SetSelection( aSelection );
+ }
+}
+
+void SAL_CALL SvxUnoTextBase::insertControlCharacter( const uno::Reference< text::XTextRange >& xRange, sal_Int16 nControlCharacter, sal_Bool bAbsorb )
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = GetEditSource() ? GetEditSource()->GetTextForwarder() : nullptr;
+
+ if( !pForwarder )
+ return;
+
+ ESelection aSelection;
+ ::GetSelection( aSelection, pForwarder );
+ SetSelection( aSelection );
+
+ switch( nControlCharacter )
+ {
+ case text::ControlCharacter::PARAGRAPH_BREAK:
+ {
+ insertString( xRange, "\x0D", bAbsorb );
+
+ return;
+ }
+ case text::ControlCharacter::LINE_BREAK:
+ {
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange );
+ if(pRange)
+ {
+ ESelection aRange = pRange->GetSelection();
+
+ if( bAbsorb )
+ {
+ pForwarder->QuickInsertText( "", aRange );
+
+ aRange.nEndPos = aRange.nStartPos;
+ aRange.nEndPara = aRange.nStartPara;
+ }
+ else
+ {
+ aRange.nStartPara = aRange.nEndPara;
+ aRange.nStartPos = aRange.nEndPos;
+ }
+
+ pForwarder->QuickInsertLineBreak( aRange );
+ GetEditSource()->UpdateData();
+
+ aRange.nEndPos += 1;
+ if( !bAbsorb )
+ aRange.nStartPos += 1;
+
+ pRange->SetSelection( aRange );
+ }
+ return;
+ }
+ case text::ControlCharacter::APPEND_PARAGRAPH:
+ {
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange );
+ if(pRange)
+ {
+ ESelection aRange = pRange->GetSelection();
+// ESelection aOldSelection = aRange;
+
+ aRange.nStartPos = pForwarder->GetTextLen( aRange.nStartPara );
+
+ aRange.nEndPara = aRange.nStartPara;
+ aRange.nEndPos = aRange.nStartPos;
+
+ pRange->SetSelection( aRange );
+ static constexpr OUStringLiteral CR = u"\x0D";
+ pRange->setString( CR );
+
+ aRange.nStartPos = 0;
+ aRange.nStartPara += 1;
+ aRange.nEndPos = 0;
+ aRange.nEndPara += 1;
+
+ pRange->SetSelection( aRange );
+
+ return;
+ }
+ [[fallthrough]];
+ }
+ default:
+ throw lang::IllegalArgumentException();
+ }
+}
+
+// XText
+void SAL_CALL SvxUnoTextBase::insertTextContent( const uno::Reference< text::XTextRange >& xRange, const uno::Reference< text::XTextContent >& xContent, sal_Bool bAbsorb )
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = GetEditSource() ? GetEditSource()->GetTextForwarder() : nullptr;
+ if (!pForwarder)
+ return;
+
+ uno::Reference<beans::XPropertySet> xPropSet(xRange, uno::UNO_QUERY);
+ if (!xPropSet.is())
+ throw lang::IllegalArgumentException();
+
+ uno::Any aAny = xPropSet->getPropertyValue(UNO_TR_PROP_SELECTION);
+ text::TextRangeSelection aSel = aAny.get<text::TextRangeSelection>();
+ if (!bAbsorb)
+ aSel.Start = aSel.End;
+
+ std::unique_ptr<SvxFieldData> pFieldData(SvxFieldData::Create(xContent));
+ if (!pFieldData)
+ throw lang::IllegalArgumentException();
+
+ SvxFieldItem aField( *pFieldData, EE_FEATURE_FIELD );
+ pForwarder->QuickInsertField(aField, toESelection(aSel));
+ GetEditSource()->UpdateData();
+
+ uno::Reference<beans::XPropertySet> xPropSetContent(xContent, uno::UNO_QUERY);
+ if (!xPropSetContent.is())
+ throw lang::IllegalArgumentException();
+
+ xPropSetContent->setPropertyValue(UNO_TC_PROP_ANCHOR, uno::Any(xRange));
+
+ aSel.End.PositionInParagraph += 1;
+ aSel.Start.PositionInParagraph = aSel.End.PositionInParagraph;
+ xPropSet->setPropertyValue(UNO_TR_PROP_SELECTION, uno::Any(aSel));
+}
+
+void SAL_CALL SvxUnoTextBase::removeTextContent( const uno::Reference< text::XTextContent >& )
+{
+}
+
+// XTextRange
+
+uno::Reference< text::XText > SAL_CALL SvxUnoTextBase::getText()
+{
+ SolarMutexGuard aGuard;
+
+ if (GetEditSource())
+ {
+ ESelection aSelection;
+ ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
+ SetSelection( aSelection );
+ }
+
+ return static_cast<text::XText*>(this);
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::getStart()
+{
+ return SvxUnoTextRangeBase::getStart();
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::getEnd()
+{
+ return SvxUnoTextRangeBase::getEnd();
+}
+
+OUString SAL_CALL SvxUnoTextBase::getString()
+{
+ return SvxUnoTextRangeBase::getString();
+}
+
+void SAL_CALL SvxUnoTextBase::setString( const OUString& aString )
+{
+ SvxUnoTextRangeBase::setString(aString);
+}
+
+
+// XEnumerationAccess
+uno::Reference< container::XEnumeration > SAL_CALL SvxUnoTextBase::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+
+ if (!GetEditSource())
+ return uno::Reference< container::XEnumeration >();
+
+ if( maSelection == ESelection(0,0,0,0) || maSelection == ESelection(EE_PARA_MAX_COUNT,0,0,0) )
+ {
+ ESelection aSelection;
+ ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
+ return new SvxUnoTextContentEnumeration(*this, aSelection);
+ }
+ else
+ {
+ return new SvxUnoTextContentEnumeration(*this, maSelection);
+ }
+}
+
+// XElementAccess ( container::XEnumerationAccess )
+uno::Type SAL_CALL SvxUnoTextBase::getElementType( )
+{
+ return cppu::UnoType<text::XTextRange>::get();
+}
+
+sal_Bool SAL_CALL SvxUnoTextBase::hasElements( )
+{
+ SolarMutexGuard aGuard;
+
+ if(GetEditSource())
+ {
+ SvxTextForwarder* pForwarder = GetEditSource()->GetTextForwarder();
+ if(pForwarder)
+ return pForwarder->GetParagraphCount() != 0;
+ }
+
+ return false;
+}
+
+// text::XTextRangeMover
+void SAL_CALL SvxUnoTextBase::moveTextRange( const uno::Reference< text::XTextRange >&, sal_Int16 )
+{
+}
+
+/// @throws lang::IllegalArgumentException
+/// @throws beans::UnknownPropertyException
+/// @throws uno::RuntimeException
+static void SvxPropertyValuesToItemSet(
+ SfxItemSet &rItemSet,
+ const uno::Sequence< beans::PropertyValue >& rPropertyValues,
+ const SfxItemPropertySet *pPropSet,
+ SvxTextForwarder *pForwarder,
+ sal_Int32 nPara)
+{
+ for (const beans::PropertyValue& rProp : rPropertyValues)
+ {
+ const SfxItemPropertyMapEntry *pEntry = pPropSet->getPropertyMap().getByName( rProp.Name );
+ if (!pEntry)
+ throw beans::UnknownPropertyException( "Unknown property: " + rProp.Name );
+ // Note: there is no need to take special care of the properties
+ // TextField (EE_FEATURE_FIELD) and
+ // TextPortionType (WID_PORTIONTYPE)
+ // since they are read-only and thus are already taken care of below.
+
+ if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ // should be PropertyVetoException which is not yet defined for the new import API's functions
+ throw uno::RuntimeException("Property is read-only: " + rProp.Name );
+ //throw PropertyVetoException ("Property is read-only: " + rProp.Name );
+
+ if (pEntry->nWID == WID_FONTDESC)
+ {
+ awt::FontDescriptor aDesc;
+ if (rProp.Value >>= aDesc)
+ SvxUnoFontDescriptor::FillItemSet( aDesc, rItemSet );
+ }
+ else if (pEntry->nWID == WID_NUMBERINGSTARTVALUE )
+ {
+ if( pForwarder )
+ {
+ sal_Int16 nStartValue = -1;
+ if( !(rProp.Value >>= nStartValue) )
+ throw lang::IllegalArgumentException();
+
+ pForwarder->SetNumberingStartValue( nPara, nStartValue );
+ }
+ }
+ else if (pEntry->nWID == WID_PARAISNUMBERINGRESTART )
+ {
+ if( pForwarder )
+ {
+ bool bParaIsNumberingRestart = false;
+ if( !(rProp.Value >>= bParaIsNumberingRestart) )
+ throw lang::IllegalArgumentException();
+
+ pForwarder->SetParaIsNumberingRestart( nPara, bParaIsNumberingRestart );
+ }
+ }
+ else
+ pPropSet->setPropertyValue( rProp.Name, rProp.Value, rItemSet );
+ }
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::finishParagraphInsert(
+ const uno::Sequence< beans::PropertyValue >& /*rCharAndParaProps*/,
+ const uno::Reference< text::XTextRange >& /*rTextRange*/ )
+{
+ uno::Reference< text::XTextRange > xRet;
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::finishParagraph(
+ const uno::Sequence< beans::PropertyValue >& rCharAndParaProps )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextRange > xRet;
+ SvxEditSource *pEditSource = GetEditSource();
+ SvxTextForwarder *pTextForwarder = pEditSource ? pEditSource->GetTextForwarder() : nullptr;
+ if (pTextForwarder)
+ {
+ sal_Int32 nParaCount = pTextForwarder->GetParagraphCount();
+ DBG_ASSERT( nParaCount > 0, "paragraph count is 0 or negative" );
+ pTextForwarder->AppendParagraph();
+
+ // set properties for the previously last paragraph
+ sal_Int32 nPara = nParaCount - 1;
+ ESelection aSel( nPara, 0, nPara, 0 );
+ SfxItemSet aItemSet( *pTextForwarder->GetEmptyItemSetPtr() );
+ SvxPropertyValuesToItemSet( aItemSet, rCharAndParaProps,
+ ImplGetSvxUnoOutlinerTextCursorSfxPropertySet(), pTextForwarder, nPara );
+ pTextForwarder->QuickSetAttribs( aItemSet, aSel );
+ pEditSource->UpdateData();
+ rtl::Reference<SvxUnoTextRange> pRange = new SvxUnoTextRange( *this );
+ xRet = pRange;
+ pRange->SetSelection( aSel );
+ }
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::insertTextPortion(
+ const OUString& rText,
+ const uno::Sequence< beans::PropertyValue >& rCharAndParaProps,
+ const uno::Reference< text::XTextRange>& rTextRange )
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XTextRange > xRet;
+
+ if (!rTextRange.is())
+ return xRet;
+
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>(rTextRange);
+ if (!pRange)
+ return xRet;
+
+ SvxEditSource *pEditSource = GetEditSource();
+ SvxTextForwarder *pTextForwarder = pEditSource ? pEditSource->GetTextForwarder() : nullptr;
+
+ if (pTextForwarder)
+ {
+ pRange->setString(rText);
+
+ ESelection aSelection(pRange->GetSelection());
+
+ pTextForwarder->RemoveAttribs(aSelection);
+ pEditSource->UpdateData();
+
+ SfxItemSet aItemSet( *pTextForwarder->GetEmptyItemSetPtr() );
+ SvxPropertyValuesToItemSet( aItemSet, rCharAndParaProps,
+ ImplGetSvxTextPortionSfxPropertySet(), pTextForwarder, aSelection.nStartPara );
+ pTextForwarder->QuickSetAttribs( aItemSet, aSelection);
+ rtl::Reference<SvxUnoTextRange> pNewRange = new SvxUnoTextRange( *this );
+ xRet = pNewRange;
+ pNewRange->SetSelection(aSelection);
+ for( const beans::PropertyValue& rProp : rCharAndParaProps )
+ pNewRange->setPropertyValue( rProp.Name, rProp.Value );
+ }
+ return xRet;
+}
+
+// css::text::XTextPortionAppend (new import API)
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::appendTextPortion(
+ const OUString& rText,
+ const uno::Sequence< beans::PropertyValue >& rCharAndParaProps )
+{
+ SolarMutexGuard aGuard;
+
+ SvxEditSource *pEditSource = GetEditSource();
+ SvxTextForwarder *pTextForwarder = pEditSource ? pEditSource->GetTextForwarder() : nullptr;
+ uno::Reference< text::XTextRange > xRet;
+ if (pTextForwarder)
+ {
+ sal_Int32 nParaCount = pTextForwarder->GetParagraphCount();
+ DBG_ASSERT( nParaCount > 0, "paragraph count is 0 or negative" );
+ sal_Int32 nPara = nParaCount - 1;
+ SfxItemSet aSet( pTextForwarder->GetParaAttribs( nPara ) );
+ sal_Int32 nStart = pTextForwarder->AppendTextPortion( nPara, rText, aSet );
+ pEditSource->UpdateData();
+ sal_Int32 nEnd = pTextForwarder->GetTextLen( nPara );
+
+ // set properties for the new text portion
+ ESelection aSel( nPara, nStart, nPara, nEnd );
+ pTextForwarder->RemoveAttribs( aSel );
+ pEditSource->UpdateData();
+
+ SfxItemSet aItemSet( *pTextForwarder->GetEmptyItemSetPtr() );
+ SvxPropertyValuesToItemSet( aItemSet, rCharAndParaProps,
+ ImplGetSvxTextPortionSfxPropertySet(), pTextForwarder, nPara );
+ pTextForwarder->QuickSetAttribs( aItemSet, aSel );
+ rtl::Reference<SvxUnoTextRange> pRange = new SvxUnoTextRange( *this );
+ xRet = pRange;
+ pRange->SetSelection( aSel );
+ for( const beans::PropertyValue& rProp : rCharAndParaProps )
+ pRange->setPropertyValue( rProp.Name, rProp.Value );
+ }
+ return xRet;
+}
+
+void SvxUnoTextBase::copyText(
+ const uno::Reference< text::XTextCopy >& xSource )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< lang::XUnoTunnel > xUT( xSource, uno::UNO_QUERY );
+ SvxEditSource *pEditSource = GetEditSource();
+ SvxTextForwarder *pTextForwarder = pEditSource ? pEditSource->GetTextForwarder() : nullptr;
+ if( !pTextForwarder )
+ return;
+ if (auto pSource = comphelper::getFromUnoTunnel<SvxUnoTextBase>(xUT))
+ {
+ SvxEditSource *pSourceEditSource = pSource->GetEditSource();
+ SvxTextForwarder *pSourceTextForwarder = pSourceEditSource ? pSourceEditSource->GetTextForwarder() : nullptr;
+ if( pSourceTextForwarder )
+ {
+ pTextForwarder->CopyText( *pSourceTextForwarder );
+ pEditSource->UpdateData();
+ }
+ }
+ else
+ {
+ uno::Reference< text::XText > xSourceText( xSource, uno::UNO_QUERY );
+ if( xSourceText.is() )
+ {
+ setString( xSourceText->getString() );
+ }
+ }
+}
+
+// lang::XServiceInfo
+OUString SAL_CALL SvxUnoTextBase::getImplementationName()
+{
+ return "SvxUnoTextBase";
+}
+
+uno::Sequence< OUString > SAL_CALL SvxUnoTextBase::getSupportedServiceNames( )
+{
+ return getSupportedServiceNames_Static();
+}
+
+uno::Sequence< OUString > SAL_CALL SvxUnoTextBase::getSupportedServiceNames_Static( )
+{
+ return comphelper::concatSequences(
+ SvxUnoTextRangeBase::getSupportedServiceNames_Static(),
+ std::initializer_list<std::u16string_view>{ u"com.sun.star.text.Text" });
+}
+
+const uno::Sequence< sal_Int8 > & SvxUnoTextBase::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theSvxUnoTextBaseUnoTunnelId;
+ return theSvxUnoTextBaseUnoTunnelId.getSeq();
+}
+
+sal_Int64 SAL_CALL SvxUnoTextBase::getSomething( const uno::Sequence< sal_Int8 >& rId )
+{
+ return comphelper::getSomethingImpl(
+ rId, this, comphelper::FallbackToGetSomethingOf<SvxUnoTextRangeBase>{});
+}
+
+SvxUnoText::SvxUnoText( const SvxItemPropertySet* _pSet ) noexcept
+: SvxUnoTextBase( _pSet )
+{
+}
+
+SvxUnoText::SvxUnoText( const SvxEditSource* pSource, const SvxItemPropertySet* _pSet, uno::Reference < text::XText > const & xParent ) noexcept
+: SvxUnoTextBase( pSource, _pSet, xParent )
+{
+}
+
+SvxUnoText::SvxUnoText( const SvxUnoText& rText ) noexcept
+: SvxUnoTextBase( rText )
+, cppu::OWeakAggObject()
+{
+}
+
+SvxUnoText::~SvxUnoText() noexcept
+{
+}
+
+// uno::XInterface
+uno::Any SAL_CALL SvxUnoText::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aAny( SvxUnoTextBase::queryAggregation( rType ) );
+ if( !aAny.hasValue() )
+ aAny = OWeakAggObject::queryAggregation( rType );
+
+ return aAny;
+}
+
+uno::Any SAL_CALL SvxUnoText::queryInterface( const uno::Type & rType )
+{
+ return OWeakAggObject::queryInterface( rType );
+}
+
+void SAL_CALL SvxUnoText::acquire() noexcept
+{
+ OWeakAggObject::acquire();
+}
+
+void SAL_CALL SvxUnoText::release() noexcept
+{
+ OWeakAggObject::release();
+}
+
+// lang::XTypeProvider
+uno::Sequence< uno::Type > SAL_CALL SvxUnoText::getTypes( )
+{
+ return SvxUnoTextBase::getTypes();
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SvxUnoText::getImplementationId( )
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+const uno::Sequence< sal_Int8 > & SvxUnoText::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theSvxUnoTextUnoTunnelId;
+ return theSvxUnoTextUnoTunnelId.getSeq();
+}
+
+sal_Int64 SAL_CALL SvxUnoText::getSomething( const uno::Sequence< sal_Int8 >& rId )
+{
+ return comphelper::getSomethingImpl(rId, this,
+ comphelper::FallbackToGetSomethingOf<SvxUnoTextBase>{});
+}
+
+
+SvxDummyTextSource::~SvxDummyTextSource()
+{
+};
+
+std::unique_ptr<SvxEditSource> SvxDummyTextSource::Clone() const
+{
+ return std::unique_ptr<SvxEditSource>(new SvxDummyTextSource);
+}
+
+SvxTextForwarder* SvxDummyTextSource::GetTextForwarder()
+{
+ return this;
+}
+
+void SvxDummyTextSource::UpdateData()
+{
+}
+
+sal_Int32 SvxDummyTextSource::GetParagraphCount() const
+{
+ return 0;
+}
+
+sal_Int32 SvxDummyTextSource::GetTextLen( sal_Int32 ) const
+{
+ return 0;
+}
+
+OUString SvxDummyTextSource::GetText( const ESelection& ) const
+{
+ return OUString();
+}
+
+SfxItemSet SvxDummyTextSource::GetAttribs( const ESelection&, EditEngineAttribs ) const
+{
+ // Very dangerous: The former implementation used a SfxItemPool created on the
+ // fly which of course was deleted again ASAP. Thus, the returned SfxItemSet was using
+ // a deleted Pool by design.
+ return SfxItemSet(EditEngine::GetGlobalItemPool());
+}
+
+SfxItemSet SvxDummyTextSource::GetParaAttribs( sal_Int32 ) const
+{
+ return GetAttribs(ESelection());
+}
+
+void SvxDummyTextSource::SetParaAttribs( sal_Int32, const SfxItemSet& )
+{
+}
+
+void SvxDummyTextSource::RemoveAttribs( const ESelection& )
+{
+}
+
+void SvxDummyTextSource::GetPortions( sal_Int32, std::vector<sal_Int32>& ) const
+{
+}
+
+OUString SvxDummyTextSource::GetStyleSheet(sal_Int32) const
+{
+ return OUString();
+}
+
+void SvxDummyTextSource::SetStyleSheet(sal_Int32, const OUString&)
+{
+}
+
+SfxItemState SvxDummyTextSource::GetItemState( const ESelection&, sal_uInt16 ) const
+{
+ return SfxItemState::UNKNOWN;
+}
+
+SfxItemState SvxDummyTextSource::GetItemState( sal_Int32, sal_uInt16 ) const
+{
+ return SfxItemState::UNKNOWN;
+}
+
+SfxItemPool* SvxDummyTextSource::GetPool() const
+{
+ return nullptr;
+}
+
+void SvxDummyTextSource::QuickInsertText( const OUString&, const ESelection& )
+{
+}
+
+void SvxDummyTextSource::QuickInsertField( const SvxFieldItem&, const ESelection& )
+{
+}
+
+void SvxDummyTextSource::QuickSetAttribs( const SfxItemSet&, const ESelection& )
+{
+}
+
+void SvxDummyTextSource::QuickInsertLineBreak( const ESelection& )
+{
+};
+
+OUString SvxDummyTextSource::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>&, std::optional<FontLineStyle>& )
+{
+ return OUString();
+}
+
+void SvxDummyTextSource::FieldClicked( const SvxFieldItem& )
+{
+}
+
+bool SvxDummyTextSource::IsValid() const
+{
+ return false;
+}
+
+LanguageType SvxDummyTextSource::GetLanguage( sal_Int32, sal_Int32 ) const
+{
+ return LANGUAGE_DONTKNOW;
+}
+
+sal_Int32 SvxDummyTextSource::GetFieldCount( sal_Int32 ) const
+{
+ return 0;
+}
+
+EFieldInfo SvxDummyTextSource::GetFieldInfo( sal_Int32, sal_uInt16 ) const
+{
+ return EFieldInfo();
+}
+
+EBulletInfo SvxDummyTextSource::GetBulletInfo( sal_Int32 ) const
+{
+ return EBulletInfo();
+}
+
+tools::Rectangle SvxDummyTextSource::GetCharBounds( sal_Int32, sal_Int32 ) const
+{
+ return tools::Rectangle();
+}
+
+tools::Rectangle SvxDummyTextSource::GetParaBounds( sal_Int32 ) const
+{
+ return tools::Rectangle();
+}
+
+MapMode SvxDummyTextSource::GetMapMode() const
+{
+ return MapMode();
+}
+
+OutputDevice* SvxDummyTextSource::GetRefDevice() const
+{
+ return nullptr;
+}
+
+bool SvxDummyTextSource::GetIndexAtPoint( const Point&, sal_Int32&, sal_Int32& ) const
+{
+ return false;
+}
+
+bool SvxDummyTextSource::GetWordIndices( sal_Int32, sal_Int32, sal_Int32&, sal_Int32& ) const
+{
+ return false;
+}
+
+bool SvxDummyTextSource::GetAttributeRun( sal_Int32&, sal_Int32&, sal_Int32, sal_Int32, bool ) const
+{
+ return false;
+}
+
+sal_Int32 SvxDummyTextSource::GetLineCount( sal_Int32 ) const
+{
+ return 0;
+}
+
+sal_Int32 SvxDummyTextSource::GetLineLen( sal_Int32, sal_Int32 ) const
+{
+ return 0;
+}
+
+void SvxDummyTextSource::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 /*nParagraph*/, sal_Int32 /*nLine*/ ) const
+{
+ rStart = rEnd = 0;
+}
+
+sal_Int32 SvxDummyTextSource::GetLineNumberAtIndex( sal_Int32 /*nPara*/, sal_Int32 /*nIndex*/ ) const
+{
+ return 0;
+}
+
+bool SvxDummyTextSource::QuickFormatDoc( bool )
+{
+ return false;
+}
+
+sal_Int16 SvxDummyTextSource::GetDepth( sal_Int32 ) const
+{
+ return -1;
+}
+
+bool SvxDummyTextSource::SetDepth( sal_Int32, sal_Int16 nNewDepth )
+{
+ return nNewDepth == 0;
+}
+
+bool SvxDummyTextSource::Delete( const ESelection& )
+{
+ return false;
+}
+
+bool SvxDummyTextSource::InsertText( const OUString&, const ESelection& )
+{
+ return false;
+}
+
+const SfxItemSet * SvxDummyTextSource::GetEmptyItemSetPtr()
+{
+ return nullptr;
+}
+
+void SvxDummyTextSource::AppendParagraph()
+{
+}
+
+sal_Int32 SvxDummyTextSource::AppendTextPortion( sal_Int32, const OUString &, const SfxItemSet & )
+{
+ return 0;
+}
+
+void SvxDummyTextSource::CopyText(const SvxTextForwarder& )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unotext2.cxx b/editeng/source/uno/unotext2.cxx
new file mode 100644
index 0000000000..54714027b3
--- /dev/null
+++ b/editeng/source/uno/unotext2.cxx
@@ -0,0 +1,629 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <initializer_list>
+#include <string_view>
+
+#include <o3tl/safeint.hxx>
+#include <vcl/svapp.hxx>
+
+#include <editeng/unotext.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::cppu;
+using namespace ::com::sun::star;
+
+#define QUERYINT( xint ) \
+ if( rType == cppu::UnoType<xint>::get() ) \
+ return uno::Any(uno::Reference< xint >(this))
+
+
+// SvxUnoTextContentEnumeration
+
+
+SvxUnoTextContentEnumeration::SvxUnoTextContentEnumeration( const SvxUnoTextBase& rText, const ESelection& rSel ) noexcept
+{
+ mxParentText = const_cast<SvxUnoTextBase*>(&rText);
+ if( rText.GetEditSource() )
+ mpEditSource = rText.GetEditSource()->Clone();
+ mnNextParagraph = 0;
+
+ if (!mpEditSource)
+ return;
+
+ const SvxTextForwarder* pTextForwarder = rText.GetEditSource()->GetTextForwarder();
+ const sal_Int32 maxParaIndex = std::min( rSel.nEndPara + 1, pTextForwarder->GetParagraphCount() );
+
+ for( sal_Int32 currentPara = rSel.nStartPara; currentPara < maxParaIndex; currentPara++ )
+ {
+ const SvxUnoTextRangeBaseVec& rRanges( mpEditSource->getRanges() );
+ rtl::Reference<SvxUnoTextContent> pContent;
+ sal_Int32 nStartPos = 0;
+ sal_Int32 nEndPos = pTextForwarder->GetTextLen( currentPara );
+ if( currentPara == rSel.nStartPara )
+ nStartPos = std::max(nStartPos, rSel.nStartPos);
+ if( currentPara == rSel.nEndPara )
+ nEndPos = std::min(nEndPos, rSel.nEndPos);
+ ESelection aCurrentParaSel( currentPara, nStartPos, currentPara, nEndPos );
+ for (auto const& elemRange : rRanges)
+ {
+ if (pContent)
+ break;
+ SvxUnoTextContent* pIterContent = dynamic_cast< SvxUnoTextContent* >( elemRange );
+ if( pIterContent && (pIterContent->mnParagraph == currentPara) )
+ {
+ ESelection aIterSel = pIterContent->GetSelection();
+ if( aIterSel == aCurrentParaSel )
+ {
+ pContent = pIterContent;
+ maContents.emplace_back(pContent );
+ }
+ }
+ }
+ if( pContent == nullptr )
+ {
+ pContent = new SvxUnoTextContent( rText, currentPara );
+ pContent->SetSelection( aCurrentParaSel );
+ maContents.emplace_back(pContent );
+ }
+ }
+}
+
+SvxUnoTextContentEnumeration::~SvxUnoTextContentEnumeration() noexcept
+{
+}
+
+// container::XEnumeration
+sal_Bool SAL_CALL SvxUnoTextContentEnumeration::hasMoreElements()
+{
+ SolarMutexGuard aGuard;
+ if( mpEditSource && !maContents.empty() )
+ return o3tl::make_unsigned(mnNextParagraph) < maContents.size();
+ else
+ return false;
+}
+
+uno::Any SvxUnoTextContentEnumeration::nextElement()
+{
+ SolarMutexGuard aGuard;
+
+ if(!hasMoreElements())
+ throw container::NoSuchElementException();
+
+ uno::Reference< text::XTextContent > xRef( maContents.at(mnNextParagraph) );
+ mnNextParagraph++;
+ return uno::Any( xRef );
+}
+
+
+
+
+SvxUnoTextContent::SvxUnoTextContent( const SvxUnoTextBase& rText, sal_Int32 nPara ) noexcept
+: SvxUnoTextRangeBase(rText)
+, mnParagraph(nPara)
+, mrParentText(rText)
+, mbDisposing( false )
+{
+ mxParentText = const_cast<SvxUnoTextBase*>(&rText);
+}
+
+SvxUnoTextContent::SvxUnoTextContent( const SvxUnoTextContent& rContent ) noexcept
+: SvxUnoTextRangeBase(rContent)
+, text::XTextContent()
+, container::XEnumerationAccess()
+, lang::XTypeProvider()
+, cppu::OWeakAggObject()
+, mrParentText(rContent.mrParentText)
+, mbDisposing( false )
+{
+ mxParentText = rContent.mxParentText;
+ mnParagraph = rContent.mnParagraph;
+ SetSelection( rContent.GetSelection() );
+}
+
+SvxUnoTextContent::~SvxUnoTextContent() noexcept
+{
+}
+
+// uno::XInterface
+uno::Any SAL_CALL SvxUnoTextContent::queryAggregation( const uno::Type & rType )
+{
+ QUERYINT( text::XTextRange );
+ else QUERYINT( beans::XMultiPropertyStates );
+ else QUERYINT( beans::XPropertySet );
+ else QUERYINT( beans::XMultiPropertySet );
+ else QUERYINT( beans::XPropertyState );
+ else QUERYINT( text::XTextContent );
+ else QUERYINT( text::XTextRangeCompare );
+ else QUERYINT( lang::XComponent );
+ else QUERYINT( container::XEnumerationAccess );
+ else QUERYINT( container::XElementAccess );
+ else QUERYINT( lang::XServiceInfo );
+ else QUERYINT( lang::XTypeProvider );
+ else QUERYINT( lang::XUnoTunnel );
+ else
+ return OWeakAggObject::queryAggregation( rType );
+}
+
+uno::Any SAL_CALL SvxUnoTextContent::queryInterface( const uno::Type & rType )
+{
+ return OWeakAggObject::queryInterface(rType);
+}
+
+void SAL_CALL SvxUnoTextContent::acquire() noexcept
+{
+ OWeakAggObject::acquire();
+}
+
+void SAL_CALL SvxUnoTextContent::release() noexcept
+{
+ OWeakAggObject::release();
+}
+
+// XTypeProvider
+
+uno::Sequence< uno::Type > SAL_CALL SvxUnoTextContent::getTypes()
+{
+ static const uno::Sequence< uno::Type > TYPES {
+ cppu::UnoType<text::XTextRange>::get(),
+ cppu::UnoType<beans::XPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertyStates>::get(),
+ cppu::UnoType<beans::XPropertyState>::get(),
+ cppu::UnoType<text::XTextRangeCompare>::get(),
+ cppu::UnoType<text::XTextContent>::get(),
+ cppu::UnoType<container::XEnumerationAccess>::get(),
+ cppu::UnoType<lang::XServiceInfo>::get(),
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<lang::XUnoTunnel>::get() };
+ return TYPES;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SvxUnoTextContent::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// text::XTextRange
+
+uno::Reference< text::XText > SAL_CALL SvxUnoTextContent::getText()
+{
+ return mxParentText;
+}
+
+// text::XTextContent
+void SAL_CALL SvxUnoTextContent::attach( const uno::Reference< text::XTextRange >& )
+{
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextContent::getAnchor()
+{
+ return mxParentText;
+}
+
+// XComponent
+
+void SAL_CALL SvxUnoTextContent::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ if( mbDisposing )
+ return; // caught a recursion
+
+ mbDisposing = true;
+
+ lang::EventObject aEvt;
+ aEvt.Source = *static_cast<OWeakAggObject*>(this);
+ {
+ std::unique_lock aMutexGuard(maDisposeContainerMutex);
+ maDisposeListeners.disposeAndClear(aMutexGuard, aEvt);
+ }
+
+ if( mxParentText.is() )
+ {
+ mxParentText->removeTextContent( this );
+ mxParentText.clear();
+ }
+}
+
+void SAL_CALL SvxUnoTextContent::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock aGuard(maDisposeContainerMutex);
+ maDisposeListeners.addInterface(aGuard, xListener);
+}
+
+void SAL_CALL SvxUnoTextContent::removeEventListener( const uno::Reference< lang::XEventListener >& aListener )
+{
+ std::unique_lock aGuard(maDisposeContainerMutex);
+ maDisposeListeners.removeInterface(aGuard, aListener);
+}
+
+// XEnumerationAccess
+
+uno::Reference< container::XEnumeration > SAL_CALL SvxUnoTextContent::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+
+ return new SvxUnoTextRangeEnumeration( mrParentText, mnParagraph, maSelection );
+}
+
+// XElementAccess ( container::XEnumerationAccess )
+
+uno::Type SAL_CALL SvxUnoTextContent::getElementType()
+{
+ return cppu::UnoType<text::XTextRange>::get();
+}
+
+sal_Bool SAL_CALL SvxUnoTextContent::hasElements()
+{
+ SolarMutexGuard aGuard;
+
+ SvxTextForwarder* pForwarder = GetEditSource() ? GetEditSource()->GetTextForwarder() : nullptr;
+ if( pForwarder )
+ {
+ std::vector<sal_Int32> aPortions;
+ pForwarder->GetPortions( mnParagraph, aPortions );
+ return !aPortions.empty();
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// XPropertySet
+
+void SAL_CALL SvxUnoTextContent::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
+{
+ _setPropertyValue( aPropertyName, aValue, mnParagraph );
+}
+
+uno::Any SAL_CALL SvxUnoTextContent::getPropertyValue( const OUString& PropertyName )
+{
+ return _getPropertyValue( PropertyName, mnParagraph );
+}
+
+// XMultiPropertySet
+void SAL_CALL SvxUnoTextContent::setPropertyValues( const uno::Sequence< OUString >& aPropertyNames, const uno::Sequence< uno::Any >& aValues )
+{
+ _setPropertyValues( aPropertyNames, aValues, mnParagraph );
+}
+
+uno::Sequence< uno::Any > SAL_CALL SvxUnoTextContent::getPropertyValues( const uno::Sequence< OUString >& aPropertyNames )
+{
+ return _getPropertyValues( aPropertyNames, mnParagraph );
+}
+
+/*// XTolerantMultiPropertySet
+uno::Sequence< beans::SetPropertyTolerantFailed > SAL_CALL SvxUnoTextContent::setPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames, const uno::Sequence< uno::Any >& aValues ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ return _setPropertyValuesTolerant(aPropertyNames, aValues, mnParagraph);
+}
+
+uno::Sequence< beans::GetPropertyTolerantResult > SAL_CALL SvxUnoTextContent::getPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames ) throw (uno::RuntimeException)
+{
+ return _getPropertyValuesTolerant(aPropertyNames, mnParagraph);
+}
+
+uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL SvxUnoTextContent::getDirectPropertyValuesTolerant( const uno::Sequence< OUString >& aPropertyNames )
+ throw (uno::RuntimeException)
+{
+ return _getDirectPropertyValuesTolerant(aPropertyNames, mnParagraph);
+}*/
+
+// beans::XPropertyState
+beans::PropertyState SAL_CALL SvxUnoTextContent::getPropertyState( const OUString& PropertyName )
+{
+ return _getPropertyState( PropertyName, mnParagraph );
+}
+
+uno::Sequence< beans::PropertyState > SAL_CALL SvxUnoTextContent::getPropertyStates( const uno::Sequence< OUString >& aPropertyName )
+{
+ return _getPropertyStates( aPropertyName, mnParagraph );
+}
+
+void SAL_CALL SvxUnoTextContent::setPropertyToDefault( const OUString& PropertyName )
+{
+ _setPropertyToDefault( PropertyName, mnParagraph );
+}
+
+// lang::XServiceInfo
+
+OUString SAL_CALL SvxUnoTextContent::getImplementationName()
+{
+ return "SvxUnoTextContent";
+}
+
+uno::Sequence< OUString > SAL_CALL SvxUnoTextContent::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(
+ SvxUnoTextRangeBase::getSupportedServiceNames(),
+ std::initializer_list<std::u16string_view>{ u"com.sun.star.style.ParagraphProperties",
+ u"com.sun.star.style.ParagraphPropertiesComplex",
+ u"com.sun.star.style.ParagraphPropertiesAsian",
+ u"com.sun.star.text.TextContent",
+ u"com.sun.star.text.Paragraph" });
+}
+
+
+
+
+SvxUnoTextRangeEnumeration::SvxUnoTextRangeEnumeration(const SvxUnoTextBase& rParentText, sal_Int32 nParagraph, const ESelection& rSel)
+: mxParentText( const_cast<SvxUnoTextBase*>(&rParentText) ),
+ mnNextPortion( 0 )
+{
+ if (rParentText.GetEditSource())
+ mpEditSource = rParentText.GetEditSource()->Clone();
+
+ if( !(mpEditSource && mpEditSource->GetTextForwarder() && (nParagraph == rSel.nStartPara && nParagraph == rSel.nEndPara)) )
+ return;
+
+ std::vector<sal_Int32> aPortions;
+ mpEditSource->GetTextForwarder()->GetPortions( nParagraph, aPortions );
+ for( size_t aPortionIndex = 0; aPortionIndex < aPortions.size(); aPortionIndex++ )
+ {
+ sal_uInt16 nStartPos = 0;
+ if ( aPortionIndex > 0 )
+ nStartPos = aPortions.at( aPortionIndex - 1 );
+ if( nStartPos > rSel.nEndPos )
+ continue;
+ sal_uInt16 nEndPos = aPortions.at( aPortionIndex );
+ if( nEndPos < rSel.nStartPos )
+ continue;
+
+ nStartPos = std::max<int>(nStartPos, rSel.nStartPos);
+ nEndPos = std::min<sal_uInt16>(nEndPos, rSel.nEndPos);
+ ESelection aSel( nParagraph, nStartPos, nParagraph, nEndPos );
+
+ const SvxUnoTextRangeBaseVec& rRanges( mpEditSource->getRanges() );
+ rtl::Reference<SvxUnoTextRange> pRange;
+ for (auto const& elemRange : rRanges)
+ {
+ if (pRange)
+ break;
+ SvxUnoTextRange* pIterRange = dynamic_cast< SvxUnoTextRange* >( elemRange );
+ if( pIterRange && pIterRange->mbPortion && (aSel == pIterRange->maSelection) )
+ pRange = pIterRange;
+ }
+ if( pRange == nullptr )
+ {
+ pRange = new SvxUnoTextRange( rParentText, true );
+ pRange->SetSelection( aSel );
+ }
+ maPortions.emplace_back(pRange );
+ }
+}
+
+SvxUnoTextRangeEnumeration::~SvxUnoTextRangeEnumeration() noexcept
+{
+}
+
+// container::XEnumeration
+
+sal_Bool SAL_CALL SvxUnoTextRangeEnumeration::hasMoreElements()
+{
+ SolarMutexGuard aGuard;
+
+ return !maPortions.empty() && mnNextPortion < maPortions.size();
+}
+
+uno::Any SAL_CALL SvxUnoTextRangeEnumeration::nextElement()
+{
+ SolarMutexGuard aGuard;
+
+ if( maPortions.empty() || mnNextPortion >= maPortions.size() )
+ throw container::NoSuchElementException();
+
+ uno::Reference< text::XTextRange > xRange = maPortions.at(mnNextPortion);
+ mnNextPortion++;
+ return uno::Any( xRange );
+}
+
+SvxUnoTextCursor::SvxUnoTextCursor( const SvxUnoTextBase& rText ) noexcept
+: SvxUnoTextRangeBase(rText),
+ mxParentText( const_cast<SvxUnoTextBase*>(&rText) )
+{
+}
+
+SvxUnoTextCursor::SvxUnoTextCursor( const SvxUnoTextCursor& rCursor ) noexcept
+: SvxUnoTextRangeBase(rCursor)
+, text::XTextCursor()
+, lang::XTypeProvider()
+, cppu::OWeakAggObject()
+, mxParentText(rCursor.mxParentText)
+{
+}
+
+SvxUnoTextCursor::~SvxUnoTextCursor() noexcept
+{
+}
+
+// Comment out automatically - [getIdlClass(es) or queryInterface]
+// Please use the XTypeProvider!
+//sal_Bool SvxUnoTextCursor::queryInterface( uno::Uik aUIK, Reference< uno::XInterface > & xRef)
+uno::Any SAL_CALL SvxUnoTextCursor::queryAggregation( const uno::Type & rType )
+{
+ if( rType == cppu::UnoType<text::XTextRange>::get())
+ return uno::Any(uno::Reference< text::XTextRange >(static_cast<SvxUnoTextRangeBase *>(this)));
+ else QUERYINT( text::XTextCursor );
+ else QUERYINT( beans::XMultiPropertyStates );
+ else QUERYINT( beans::XPropertySet );
+ else QUERYINT( beans::XMultiPropertySet );
+ else QUERYINT( beans::XPropertyState );
+ else QUERYINT( text::XTextRangeCompare );
+ else QUERYINT( lang::XServiceInfo );
+ else QUERYINT( lang::XTypeProvider );
+ else QUERYINT( lang::XUnoTunnel );
+ else
+ return OWeakAggObject::queryAggregation( rType );
+}
+
+uno::Any SAL_CALL SvxUnoTextCursor::queryInterface( const uno::Type & rType )
+{
+ return OWeakAggObject::queryInterface(rType);
+}
+
+void SAL_CALL SvxUnoTextCursor::acquire() noexcept
+{
+ OWeakAggObject::acquire();
+}
+
+void SAL_CALL SvxUnoTextCursor::release() noexcept
+{
+ OWeakAggObject::release();
+}
+
+// XTypeProvider
+uno::Sequence< uno::Type > SAL_CALL SvxUnoTextCursor::getTypes()
+{
+ static const uno::Sequence< uno::Type > TYPES {
+ cppu::UnoType<text::XTextRange>::get(),
+ cppu::UnoType<text::XTextCursor>::get(),
+ cppu::UnoType<beans::XPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertySet>::get(),
+ cppu::UnoType<beans::XMultiPropertyStates>::get(),
+ cppu::UnoType<beans::XPropertyState>::get(),
+ cppu::UnoType<text::XTextRangeCompare>::get(),
+ cppu::UnoType<lang::XServiceInfo>::get(),
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<lang::XUnoTunnel>::get() };
+ return TYPES;
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL SvxUnoTextCursor::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// text::XTextCursor
+void SAL_CALL SvxUnoTextCursor::collapseToStart()
+{
+ SolarMutexGuard aGuard;
+ CollapseToStart();
+}
+
+void SAL_CALL SvxUnoTextCursor::collapseToEnd()
+{
+ SolarMutexGuard aGuard;
+ CollapseToEnd();
+}
+
+sal_Bool SAL_CALL SvxUnoTextCursor::isCollapsed()
+{
+ SolarMutexGuard aGuard;
+ return IsCollapsed();
+}
+
+sal_Bool SAL_CALL SvxUnoTextCursor::goLeft( sal_Int16 nCount, sal_Bool bExpand )
+{
+ SolarMutexGuard aGuard;
+ return GoLeft( nCount, bExpand );
+}
+
+sal_Bool SAL_CALL SvxUnoTextCursor::goRight( sal_Int16 nCount, sal_Bool bExpand )
+{
+ SolarMutexGuard aGuard;
+ return GoRight( nCount, bExpand );
+}
+
+void SAL_CALL SvxUnoTextCursor::gotoStart( sal_Bool bExpand )
+{
+ SolarMutexGuard aGuard;
+ GotoStart( bExpand );
+}
+
+void SAL_CALL SvxUnoTextCursor::gotoEnd( sal_Bool bExpand )
+{
+ SolarMutexGuard aGuard;
+ GotoEnd( bExpand );
+}
+
+void SAL_CALL SvxUnoTextCursor::gotoRange( const uno::Reference< text::XTextRange >& xRange, sal_Bool bExpand )
+{
+ if( !xRange.is() )
+ return;
+
+ SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xRange );
+
+ if( !pRange )
+ return;
+
+ ESelection aNewSel = pRange->GetSelection();
+
+ if( bExpand )
+ {
+ const ESelection& rOldSel = GetSelection();
+ aNewSel.nStartPara = rOldSel.nStartPara;
+ aNewSel.nStartPos = rOldSel.nStartPos;
+ }
+
+ SetSelection( aNewSel );
+}
+
+// text::XTextRange (rest in SvxTextRange)
+uno::Reference< text::XText > SAL_CALL SvxUnoTextCursor::getText()
+{
+ return mxParentText;
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextCursor::getStart()
+{
+ return SvxUnoTextRangeBase::getStart();
+}
+
+uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextCursor::getEnd()
+{
+ return SvxUnoTextRangeBase::getEnd();
+}
+
+OUString SAL_CALL SvxUnoTextCursor::getString()
+{
+ return SvxUnoTextRangeBase::getString();
+}
+
+void SAL_CALL SvxUnoTextCursor::setString( const OUString& aString )
+{
+ SvxUnoTextRangeBase::setString(aString);
+}
+// lang::XServiceInfo
+OUString SAL_CALL SvxUnoTextCursor::getImplementationName()
+{
+ return "SvxUnoTextCursor";
+}
+
+sal_Bool SAL_CALL SvxUnoTextCursor::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+uno::Sequence< OUString > SAL_CALL SvxUnoTextCursor::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(
+ SvxUnoTextRangeBase::getSupportedServiceNames(),
+ std::initializer_list<std::u16string_view>{ u"com.sun.star.style.ParagraphProperties",
+ u"com.sun.star.style.ParagraphPropertiesComplex",
+ u"com.sun.star.style.ParagraphPropertiesAsian",
+ u"com.sun.star.text.TextCursor" });
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/uno/unoviwou.cxx b/editeng/source/uno/unoviwou.cxx
new file mode 100644
index 0000000000..19f38794e8
--- /dev/null
+++ b/editeng/source/uno/unoviwou.cxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+
+#include <editeng/unoviwou.hxx>
+#include <editeng/outliner.hxx>
+
+SvxDrawOutlinerViewForwarder::SvxDrawOutlinerViewForwarder( OutlinerView& rOutl ) :
+ mrOutlinerView ( rOutl )
+{
+}
+
+SvxDrawOutlinerViewForwarder::SvxDrawOutlinerViewForwarder( OutlinerView& rOutl, const Point& rShapePosTopLeft ) :
+ mrOutlinerView ( rOutl ), maTextShapeTopLeft( rShapePosTopLeft )
+{
+}
+
+SvxDrawOutlinerViewForwarder::~SvxDrawOutlinerViewForwarder()
+{
+}
+
+Point SvxDrawOutlinerViewForwarder::GetTextOffset() const
+{
+ // calc text offset from shape anchor
+ tools::Rectangle aOutputRect( mrOutlinerView.GetOutputArea() );
+
+ return aOutputRect.TopLeft() - maTextShapeTopLeft;
+}
+
+bool SvxDrawOutlinerViewForwarder::IsValid() const
+{
+ return true;
+}
+
+Point SvxDrawOutlinerViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ OutputDevice* pOutDev = mrOutlinerView.GetWindow()->GetOutDev();
+
+ if( pOutDev )
+ {
+ Point aPoint1( rPoint );
+ Point aTextOffset( GetTextOffset() );
+
+ aPoint1.AdjustX(aTextOffset.X() );
+ aPoint1.AdjustY(aTextOffset.Y() );
+
+ MapMode aMapMode(pOutDev->GetMapMode());
+ Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode,
+ MapMode(aMapMode.GetMapUnit())));
+ aMapMode.SetOrigin(Point());
+ return pOutDev->LogicToPixel( aPoint2, aMapMode );
+ }
+
+ return Point();
+}
+
+Point SvxDrawOutlinerViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ OutputDevice* pOutDev = mrOutlinerView.GetWindow()->GetOutDev();
+
+ if( pOutDev )
+ {
+ MapMode aMapMode(pOutDev->GetMapMode());
+ aMapMode.SetOrigin(Point());
+ Point aPoint1( pOutDev->PixelToLogic( rPoint, aMapMode ) );
+ Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
+ MapMode(aMapMode.GetMapUnit()),
+ rMapMode ) );
+ Point aTextOffset( GetTextOffset() );
+
+ aPoint2.AdjustX( -(aTextOffset.X()) );
+ aPoint2.AdjustY( -(aTextOffset.Y()) );
+
+ return aPoint2;
+ }
+
+ return Point();
+}
+
+bool SvxDrawOutlinerViewForwarder::GetSelection( ESelection& rSelection ) const
+{
+ rSelection = mrOutlinerView.GetSelection();
+ return true;
+}
+
+bool SvxDrawOutlinerViewForwarder::SetSelection( const ESelection& rSelection )
+{
+ mrOutlinerView.SetSelection( rSelection );
+ return true;
+}
+
+bool SvxDrawOutlinerViewForwarder::Copy()
+{
+ mrOutlinerView.Copy();
+ return true;
+}
+
+bool SvxDrawOutlinerViewForwarder::Cut()
+{
+ mrOutlinerView.Cut();
+ return true;
+}
+
+bool SvxDrawOutlinerViewForwarder::Paste()
+{
+ mrOutlinerView.PasteSpecial();
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */