diff options
Diffstat (limited to 'editeng/source')
87 files changed, 12018 insertions, 9647 deletions
diff --git a/editeng/source/accessibility/AccessibleContextBase.cxx b/editeng/source/accessibility/AccessibleContextBase.cxx index 6683d7eec29d..df52b70e78a4 100644 --- a/editeng/source/accessibility/AccessibleContextBase.cxx +++ b/editeng/source/accessibility/AccessibleContextBase.cxx @@ -26,7 +26,6 @@ #include <com/sun/star/accessibility/AccessibleEventId.hpp> #include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp> -#include <unotools/accessiblestatesethelper.hxx> #include <unotools/accessiblerelationsethelper.hxx> #include <comphelper/accessibleeventnotifier.hxx> #include <cppuhelper/supportsservice.hxx> @@ -43,29 +42,26 @@ namespace accessibility { // internal AccessibleContextBase::AccessibleContextBase ( - const uno::Reference<XAccessible>& rxParent, + uno::Reference<XAccessible> xParent, const sal_Int16 aRole) - : WeakComponentImplHelper(MutexOwner::maMutex), - mxParent(rxParent), - msDescription(), + : WeakComponentImplHelper(m_aMutex), + mxParent(std::move(xParent)), meDescriptionOrigin(NotSet), - msName(), meNameOrigin(NotSet), mnClientId(0), maRole(aRole) { // Create the state set. - rtl::Reference<::utl::AccessibleStateSetHelper> pStateSet = new ::utl::AccessibleStateSetHelper (); - mxStateSet = pStateSet; + mnStateSet = 0; // Set some states. Don't use the SetState method because no events // shall be broadcasted (that is not yet initialized anyway). - pStateSet->AddState (AccessibleStateType::ENABLED); - pStateSet->AddState (AccessibleStateType::SENSITIVE); - pStateSet->AddState (AccessibleStateType::SHOWING); - pStateSet->AddState (AccessibleStateType::VISIBLE); - pStateSet->AddState (AccessibleStateType::FOCUSABLE); - pStateSet->AddState (AccessibleStateType::SELECTABLE); + mnStateSet |= AccessibleStateType::ENABLED; + mnStateSet |= AccessibleStateType::SENSITIVE; + mnStateSet |= AccessibleStateType::SHOWING; + mnStateSet |= AccessibleStateType::VISIBLE; + mnStateSet |= AccessibleStateType::FOCUSABLE; + mnStateSet |= AccessibleStateType::SELECTABLE; // Create the relation set. mxRelationSet = new ::utl::AccessibleRelationSetHelper (); @@ -75,14 +71,12 @@ AccessibleContextBase::~AccessibleContextBase() { } -bool AccessibleContextBase::SetState (sal_Int16 aState) +bool AccessibleContextBase::SetState (sal_Int64 aState) { - ::osl::ClearableMutexGuard aGuard (maMutex); - ::utl::AccessibleStateSetHelper* pStateSet = - static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if ((pStateSet != nullptr) && !pStateSet->contains(aState)) + ::osl::ClearableMutexGuard aGuard (m_aMutex); + if (!(mnStateSet & aState)) { - pStateSet->AddState (aState); + mnStateSet |= aState; // Clear the mutex guard so that it is not locked during calls to // listeners. aGuard.clear(); @@ -95,7 +89,7 @@ bool AccessibleContextBase::SetState (sal_Int16 aState) CommitChange( AccessibleEventId::STATE_CHANGED, aNewValue, - uno::Any()); + uno::Any(), -1); } return true; } @@ -104,14 +98,12 @@ bool AccessibleContextBase::SetState (sal_Int16 aState) } -bool AccessibleContextBase::ResetState (sal_Int16 aState) +bool AccessibleContextBase::ResetState (sal_Int64 aState) { - ::osl::ClearableMutexGuard aGuard (maMutex); - ::utl::AccessibleStateSetHelper* pStateSet = - static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if ((pStateSet != nullptr) && pStateSet->contains(aState)) + ::osl::ClearableMutexGuard aGuard (m_aMutex); + if (mnStateSet & aState) { - pStateSet->RemoveState (aState); + mnStateSet &= ~aState; // Clear the mutex guard so that it is not locked during calls to listeners. aGuard.clear(); @@ -120,7 +112,7 @@ bool AccessibleContextBase::ResetState (sal_Int16 aState) CommitChange( AccessibleEventId::STATE_CHANGED, uno::Any(), - aOldValue); + aOldValue, -1); return true; } else @@ -128,21 +120,15 @@ bool AccessibleContextBase::ResetState (sal_Int16 aState) } -bool AccessibleContextBase::GetState (sal_Int16 aState) +bool AccessibleContextBase::GetState (sal_Int64 aState) { - ::osl::MutexGuard aGuard (maMutex); - ::utl::AccessibleStateSetHelper* pStateSet = - static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if (pStateSet != nullptr) - return pStateSet->contains(aState); - else - // If there is no state set then return false as a default value. - return false; + ::osl::MutexGuard aGuard (m_aMutex); + return mnStateSet & aState; } void AccessibleContextBase::SetRelationSet ( - const uno::Reference<XAccessibleRelationSet>& rxNewRelationSet) + const rtl::Reference<utl::AccessibleRelationSetHelper>& rxNewRelationSet) { // Try to emit some meaningful events indicating differing relations in // both sets. @@ -158,7 +144,7 @@ void AccessibleContextBase::SetRelationSet ( for (int i=0; aRelationDescriptors[i].first!=AccessibleRelationType::INVALID; i++) if (mxRelationSet->containsRelation(aRelationDescriptors[i].first) != rxNewRelationSet->containsRelation(aRelationDescriptors[i].first)) - CommitChange (aRelationDescriptors[i].second, uno::Any(), uno::Any()); + CommitChange (aRelationDescriptors[i].second, uno::Any(), uno::Any(), -1); mxRelationSet = rxNewRelationSet; } @@ -177,7 +163,7 @@ uno::Reference< XAccessibleContext> SAL_CALL /** No children. */ -sal_Int32 SAL_CALL +sal_Int64 SAL_CALL AccessibleContextBase::getAccessibleChildCount() { return 0; @@ -188,7 +174,7 @@ sal_Int32 SAL_CALL an exception for a wrong index. */ uno::Reference<XAccessible> SAL_CALL - AccessibleContextBase::getAccessibleChild (sal_Int32 nIndex) + AccessibleContextBase::getAccessibleChild (sal_Int64 nIndex) { ThrowIfDisposed (); throw lang::IndexOutOfBoundsException ( @@ -205,29 +191,31 @@ uno::Reference<XAccessible> SAL_CALL } -sal_Int32 SAL_CALL +sal_Int64 SAL_CALL AccessibleContextBase::getAccessibleIndexInParent() { ThrowIfDisposed (); // Use a simple but slow solution for now. Optimize later. // Iterate over all the parent's children and search for this object. - if (mxParent.is()) + if (!mxParent.is()) + // Return -1 to indicate that this object's parent does not know about the + // object. + return -1; + + uno::Reference<XAccessibleContext> xParentContext ( + mxParent->getAccessibleContext()); + if (xParentContext.is()) { - uno::Reference<XAccessibleContext> xParentContext ( - mxParent->getAccessibleContext()); - if (xParentContext.is()) + sal_Int64 nChildCount = xParentContext->getAccessibleChildCount(); + for (sal_Int64 i=0; i<nChildCount; i++) { - sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); - for (sal_Int32 i=0; i<nChildCount; i++) + uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i)); + if (xChild.is()) { - uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i)); - if (xChild.is()) - { - uno::Reference<XAccessibleContext> xChildContext = xChild->getAccessibleContext(); - if (xChildContext == static_cast<XAccessibleContext*>(this)) - return i; - } + uno::Reference<XAccessibleContext> xChildContext = xChild->getAccessibleContext(); + if (xChildContext == static_cast<XAccessibleContext*>(this)) + return i; } } } @@ -280,12 +268,9 @@ uno::Reference<XAccessibleRelationSet> SAL_CALL ThrowIfDisposed (); // Create a copy of the relation set and return it. - ::utl::AccessibleRelationSetHelper* pRelationSet = - static_cast< ::utl::AccessibleRelationSetHelper*>(mxRelationSet.get()); - if (pRelationSet != nullptr) + if (mxRelationSet) { - return uno::Reference<XAccessibleRelationSet> ( - new ::utl::AccessibleRelationSetHelper (*pRelationSet)); + return new ::utl::AccessibleRelationSetHelper(*mxRelationSet); } else return uno::Reference<XAccessibleRelationSet>(nullptr); @@ -298,28 +283,19 @@ uno::Reference<XAccessibleRelationSet> SAL_CALL SHOWING VISIBLE */ -uno::Reference<XAccessibleStateSet> SAL_CALL +sal_Int64 SAL_CALL AccessibleContextBase::getAccessibleStateSet() { - rtl::Reference<::utl::AccessibleStateSetHelper> pStateSet; - if (rBHelper.bDisposed) { // We are already disposed! // Create a new state set that has only set the DEFUNC state. - pStateSet = new ::utl::AccessibleStateSetHelper (); - pStateSet->AddState (AccessibleStateType::DEFUNC); + return AccessibleStateType::DEFUNC; } else { - // Create a copy of the state set and return it. - pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - - if (pStateSet != nullptr) - pStateSet = new ::utl::AccessibleStateSetHelper (*pStateSet); + return mnStateSet; } - - return pStateSet; } @@ -417,7 +393,7 @@ void SAL_CALL AccessibleContextBase::disposing() { SetState (AccessibleStateType::DEFUNC); - ::osl::MutexGuard aGuard (maMutex); + ::osl::MutexGuard aGuard (m_aMutex); // Send a disposing to all listeners. if ( mnClientId ) @@ -425,6 +401,8 @@ void SAL_CALL AccessibleContextBase::disposing() comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this ); mnClientId = 0; } + mxParent.clear(); + mxRelationSet.clear(); } @@ -446,7 +424,7 @@ void AccessibleContextBase::SetAccessibleDescription ( CommitChange( AccessibleEventId::DESCRIPTION_CHANGED, aNewValue, - aOldValue); + aOldValue, -1); } @@ -468,7 +446,7 @@ void AccessibleContextBase::SetAccessibleName ( CommitChange( AccessibleEventId::NAME_CHANGED, aNewValue, - aOldValue); + aOldValue, -1); } @@ -481,7 +459,8 @@ OUString AccessibleContextBase::CreateAccessibleName() void AccessibleContextBase::CommitChange ( sal_Int16 nEventId, const uno::Any& rNewValue, - const uno::Any& rOldValue) + const uno::Any& rOldValue, + sal_Int32 nValueIndex) { // Do not call FireEvent and do not even create the event object when no // listener has been registered yet. Creating the event object can @@ -492,7 +471,8 @@ void AccessibleContextBase::CommitChange ( static_cast<XAccessibleContext*>(this), nEventId, rNewValue, - rOldValue); + rOldValue, + nValueIndex); FireEvent (aEvent); } @@ -511,7 +491,7 @@ void AccessibleContextBase::ThrowIfDisposed() if (rBHelper.bDisposed || rBHelper.bInDispose) { throw lang::DisposedException ("object has been already disposed", - static_cast<uno::XWeak*>(this)); + getXWeak()); } } diff --git a/editeng/source/accessibility/AccessibleEditableTextPara.cxx b/editeng/source/accessibility/AccessibleEditableTextPara.cxx index 624227a5f64e..2f727cb7669d 100644 --- a/editeng/source/accessibility/AccessibleEditableTextPara.cxx +++ b/editeng/source/accessibility/AccessibleEditableTextPara.cxx @@ -22,10 +22,10 @@ #include <algorithm> -#include <vcl/window.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <tools/debug.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <sal/log.hxx> #include <editeng/flditem.hxx> #include <com/sun/star/uno/Any.hxx> @@ -42,7 +42,6 @@ #include <comphelper/accessibleeventnotifier.hxx> #include <comphelper/sequenceashashmap.hxx> #include <cppuhelper/supportsservice.hxx> -#include <unotools/accessiblestatesethelper.hxx> #include <unotools/accessiblerelationsethelper.hxx> #include <com/sun/star/accessibility/AccessibleRelationType.hpp> #include <vcl/unohelp.hxx> @@ -69,7 +68,6 @@ #include "AccessibleImageBullet.hxx" #include <svtools/colorcfg.hxx> -using namespace std; #include <editeng/editrids.hrc> #include <editeng/eerdll.hxx> #include <editeng/numitem.hxx> @@ -93,10 +91,9 @@ namespace accessibility SVX_UNOEDIT_OUTLINER_PROPERTIES, SVX_UNOEDIT_CHAR_PROPERTIES, SVX_UNOEDIT_PARA_PROPERTIES, - SVX_UNOEDIT_NUMBERING_PROPERTIE, - { u"TextUserDefinedAttributes", EE_CHAR_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, - { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, - { u"", 0, css::uno::Type(), 0, 0 } + SVX_UNOEDIT_NUMBERING_PROPERTY, + { 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}, }; static SvxItemPropertySet aPropSet( aPropMap, EditEngine::GetGlobalItemPool() ); return &aPropSet; @@ -104,14 +101,13 @@ namespace accessibility // #i27138# - add parameter <_pParaManager> AccessibleEditableTextPara::AccessibleEditableTextPara( - const uno::Reference< XAccessible >& rParent, + uno::Reference< XAccessible > xParent, const AccessibleParaManager* _pParaManager ) - : AccessibleTextParaInterfaceBase( m_aMutex ), - mnParagraphIndex( 0 ), + : mnParagraphIndex( 0 ), mnIndexInParent( 0 ), mpEditSource( nullptr ), maEEOffset( 0, 0 ), - mxParent( rParent ), + mxParent(std::move( xParent )), // well, that's strictly (UNO) exception safe, though not // really robust. We rely on the fact that this member is // constructed last, and that the constructor body catches @@ -122,23 +118,16 @@ namespace accessibility mpParaManager( _pParaManager ) { - try - { - // Create the state set. - rtl::Reference<::utl::AccessibleStateSetHelper> pStateSet = new ::utl::AccessibleStateSetHelper (); - mxStateSet = pStateSet; + // Create the state set. + mnStateSet = 0; - // these are always on - pStateSet->AddState( AccessibleStateType::MULTI_LINE ); - pStateSet->AddState( AccessibleStateType::FOCUSABLE ); - pStateSet->AddState( AccessibleStateType::VISIBLE ); - pStateSet->AddState( AccessibleStateType::SHOWING ); - pStateSet->AddState( AccessibleStateType::ENABLED ); - pStateSet->AddState( AccessibleStateType::SENSITIVE ); - } - catch (const uno::Exception&) - { - } + // these are always on + mnStateSet |= AccessibleStateType::MULTI_LINE; + mnStateSet |= AccessibleStateType::FOCUSABLE; + mnStateSet |= AccessibleStateType::VISIBLE; + mnStateSet |= AccessibleStateType::SHOWING; + mnStateSet |= AccessibleStateType::ENABLED; + mnStateSet |= AccessibleStateType::SENSITIVE; } AccessibleEditableTextPara::~AccessibleEditableTextPara() @@ -274,8 +263,8 @@ namespace accessibility { } // index and therefore description changed - FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::makeAny( getAccessibleDescription() ), aOldDesc ); - FireEvent( AccessibleEventId::NAME_CHANGED, uno::makeAny( getAccessibleName() ), aOldName ); + FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::Any( getAccessibleDescription() ), aOldDesc ); + FireEvent( AccessibleEventId::NAME_CHANGED, uno::Any( getAccessibleName() ), aOldName ); } } catch (const uno::Exception&) // optional behaviour @@ -362,16 +351,14 @@ namespace accessibility { if( nIndex < 0 || nIndex >= getCharacterCount() ) throw lang::IndexOutOfBoundsException("AccessibleEditableTextPara: character index out of bounds", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy + getXWeak() ); } void AccessibleEditableTextPara::CheckPosition( sal_Int32 nIndex ) { if( nIndex < 0 || nIndex > getCharacterCount() ) throw lang::IndexOutOfBoundsException("AccessibleEditableTextPara: character position out of bounds", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy + getXWeak() ); } void AccessibleEditableTextPara::CheckRange( sal_Int32 nStart, sal_Int32 nEnd ) @@ -437,9 +424,7 @@ namespace accessibility { if( !mpEditSource ) throw uno::RuntimeException("No edit source, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); return *mpEditSource; } @@ -450,15 +435,11 @@ namespace accessibility if( !pTextForwarder ) throw uno::RuntimeException("Unable to fetch text forwarder, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); if( !pTextForwarder->IsValid() ) throw uno::RuntimeException("Text forwarder is invalid, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); return *pTextForwarder; } @@ -470,16 +451,12 @@ namespace accessibility if( !pViewForwarder ) { throw uno::RuntimeException("Unable to fetch view forwarder, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); } if( !pViewForwarder->IsValid() ) throw uno::RuntimeException("View forwarder is invalid, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); return *pViewForwarder; } @@ -492,14 +469,10 @@ namespace accessibility { if( bCreate ) throw uno::RuntimeException("Unable to fetch view forwarder, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); else throw uno::RuntimeException("No view forwarder, object not in edit mode", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); } if( pTextEditViewForwarder->IsValid() ) @@ -508,14 +481,10 @@ namespace accessibility { if( bCreate ) throw uno::RuntimeException("View forwarder is invalid, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); else throw uno::RuntimeException("View forwarder is invalid, object not in edit mode", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); } } @@ -562,11 +531,7 @@ namespace accessibility { uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleEditableTextPara* > (this)->getAccessibleContext() ); - AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue); - - // #102261# Call global queue for focus events - if( nEventId == AccessibleEventId::STATE_CHANGED ) - vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent ); + AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue, -1); // #106234# Delegate to EventNotifier if( getNotifierClientId() != -1 ) @@ -574,25 +539,21 @@ namespace accessibility aEvent ); } - void AccessibleEditableTextPara::SetState( const sal_Int16 nStateId ) + void AccessibleEditableTextPara::SetState( const sal_Int64 nStateId ) { - ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if( pStateSet != nullptr && - !pStateSet->contains(nStateId) ) + if( !(mnStateSet & nStateId) ) { - pStateSet->AddState( nStateId ); - FireEvent( AccessibleEventId::STATE_CHANGED, uno::makeAny( nStateId ) ); + mnStateSet |= nStateId; + FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any( nStateId ) ); } } - void AccessibleEditableTextPara::UnSetState( const sal_Int16 nStateId ) + void AccessibleEditableTextPara::UnSetState( const sal_Int64 nStateId ) { - ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if( pStateSet != nullptr && - pStateSet->contains(nStateId) ) + if( mnStateSet & nStateId ) { - pStateSet->RemoveState( nStateId ); - FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), uno::makeAny( nStateId ) ); + mnStateSet &= ~nStateId; + FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), uno::Any( nStateId ) ); } } @@ -659,26 +620,24 @@ namespace accessibility } // XAccessibleContext - sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleChildCount() + sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleChildCount() { SolarMutexGuard aGuard; return HaveChildren() ? 1 : 0; } - uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleChild( sal_Int32 i ) + uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleChild( sal_Int64 i ) { SolarMutexGuard aGuard; if( !HaveChildren() ) throw lang::IndexOutOfBoundsException("No children available", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + getXWeak() ); if( i != 0 ) throw lang::IndexOutOfBoundsException("Invalid child index", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + getXWeak() ); auto aChild( maImageBullet.get() ); @@ -704,7 +663,7 @@ namespace accessibility return mxParent; } - sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent() + sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent() { return mnIndexInParent; } @@ -777,8 +736,8 @@ namespace accessibility if ( nMyParaIndex > 0 && mpParaManager->IsReferencable( nMyParaIndex - 1 ) ) { - uno::Sequence<uno::Reference<XInterface> > aSequence - { static_cast<cppu::OWeakObject *>(mpParaManager->GetChild( nMyParaIndex - 1 ).first.get().get()) }; + uno::Sequence<uno::Reference<XAccessible>> aSequence + { mpParaManager->GetChild( nMyParaIndex - 1 ).first.get() }; AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM, aSequence ); pAccRelSetHelper->AddRelation( aAccRel ); @@ -788,8 +747,8 @@ namespace accessibility if ( (nMyParaIndex + 1) < mpParaManager->GetNum() && mpParaManager->IsReferencable( nMyParaIndex + 1 ) ) { - uno::Sequence<uno::Reference<XInterface> > aSequence - { static_cast<cppu::OWeakObject *>(mpParaManager->GetChild( nMyParaIndex + 1 ).first.get().get()) }; + uno::Sequence<uno::Reference<XAccessible>> aSequence + { mpParaManager->GetChild( nMyParaIndex + 1 ).first.get() }; AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO, aSequence ); pAccRelSetHelper->AddRelation( aAccRel ); @@ -939,26 +898,23 @@ namespace accessibility return OUString(); } - uno::Reference< XAccessibleStateSet > SAL_CALL AccessibleEditableTextPara::getAccessibleStateSet() + sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleStateSet() { SolarMutexGuard aGuard; // Create a copy of the state set and return it. - ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if( !pStateSet ) - return uno::Reference<XAccessibleStateSet>(); - uno::Reference<XAccessibleStateSet> xParentStates; + sal_Int64 nParentStates = 0; if (getAccessibleParent().is()) { uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); - xParentStates = xParentContext->getAccessibleStateSet(); + nParentStates = xParentContext->getAccessibleStateSet(); } - if (xParentStates.is() && xParentStates->contains(AccessibleStateType::EDITABLE) ) + if (nParentStates & AccessibleStateType::EDITABLE) { - pStateSet->AddState(AccessibleStateType::EDITABLE); + mnStateSet |= AccessibleStateType::EDITABLE; } - return uno::Reference<XAccessibleStateSet>( new ::utl::AccessibleStateSetHelper (*pStateSet) ); + return mnStateSet; } lang::Locale SAL_CALL AccessibleEditableTextPara::getLocale() @@ -1004,7 +960,7 @@ namespace accessibility tools::Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) ); Point aPoint( aTmpPoint.X, aTmpPoint.Y ); - return aRect.IsInside( aPoint ); + return aRect.Contains( aPoint ); } uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleAtPoint( const awt::Point& _aPoint ) @@ -1031,7 +987,7 @@ namespace accessibility { tools::Rectangle aRect = aBulletInfo.aBounds; - if( aRect.IsInside( aLogPoint ) ) + if( aRect.Contains( aLogPoint ) ) return getAccessibleChild(0); } } @@ -1231,7 +1187,7 @@ namespace accessibility // since SequenceAsHashMap ignores property handles and property state // we have to restore the property state here (property handles are // of no use to the accessibility API). - for (beans::PropertyValue & rRes : aRes) + for (beans::PropertyValue & rRes : asNonConstRange(aRes)) { bool bIsDirectVal = false; for (auto const& rRunAttrib : aRunAttribs) @@ -1249,7 +1205,7 @@ namespace accessibility // NumberingPrefix sal_Int32 nRes = aRes.getLength(); aRes.realloc( nRes + 1 ); - beans::PropertyValue &rRes = aRes[nRes]; + beans::PropertyValue &rRes = aRes.getArray()[nRes]; rRes.Name = "NumberingPrefix"; OUString numStr; if (aBulletInfo.nType != SVX_NUM_CHAR_SPECIAL && aBulletInfo.nType != SVX_NUM_BITMAP) @@ -1263,7 +1219,7 @@ namespace accessibility { nRes = aRes.getLength(); aRes.realloc( nRes + 1 ); - beans::PropertyValue &rResField = aRes[nRes]; + beans::PropertyValue &rResField = aRes.getArray()[nRes]; rResField.Name = "FieldType"; rResField.Value <<= strFieldType.toAsciiLowerCase(); rResField.Handle = -1; @@ -1277,7 +1233,7 @@ namespace accessibility sal_Int32 i = 0; for( i = 0; i < nLength; i++ ) pIndices[i] = i; - sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) ); + std::sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) ); // create sorted sequences according to index array uno::Sequence<beans::PropertyValue> aNewValues( nLength ); beans::PropertyValue* pNewValues = aNewValues.getArray(); @@ -1362,7 +1318,7 @@ namespace accessibility awt::Rectangle aRect1( getCharacterBounds(nIndex) ); tools::Rectangle aRect2( aRect1.X, aRect1.Y, aRect1.Width + aRect1.X, aRect1.Height + aRect1.Y ); - if( aRect2.IsInside( Point( rPoint.X, rPoint.Y ) ) ) + if( aRect2.Contains( Point( rPoint.X, rPoint.Y ) ) ) return nIndex; else return -1; @@ -1527,8 +1483,7 @@ namespace accessibility // NumberingLevel if (rRes.Name == "NumberingLevel") { - const SvxNumBulletItem& rNumBullet = rCacheTF.GetParaAttribs(GetParagraphIndex()).Get(EE_PARA_NUMBULLET); - if(rNumBullet.GetNumRule().GetLevelCount()==0) + if(rCacheTF.GetParaAttribs(GetParagraphIndex()).Get(EE_PARA_NUMBULLET).GetNumRule().GetLevelCount()==0) { rRes.Value <<= sal_Int16(-1); rRes.Handle = -1; @@ -1923,7 +1878,7 @@ namespace accessibility //while ( preWordStart > 0 && aBoundary.startPos == curWordStart) while ( (preWordStart >= 0 && !bWord ) || ( aBoundary.endPos > curWordStart ) ) - { + { preWordStart--; bWord = implGetWordBoundary( sText, aBoundary, preWordStart ); } @@ -2429,7 +2384,7 @@ namespace accessibility uno::Sequence< beans::PropertyValue > aOutSequence( aProperties.getLength() ); beans::PropertyValue* pOutSequence = aOutSequence.getArray(); sal_Int32 nOutLen = 0; - for (const beans::Property& rProperty : std::as_const(aProperties)) + for (const beans::Property& rProperty : aProperties) { // calling implementation functions: // _getPropertyState and _getPropertyValue (see below) to provide @@ -2515,7 +2470,7 @@ namespace accessibility uno::Sequence< beans::PropertyValue > aOutSequence( aProperties.getLength() ); beans::PropertyValue* pOutSequence = aOutSequence.getArray(); sal_Int32 nOutLen = 0; - for (const beans::Property& rProperty : std::as_const(aProperties)) + for (const beans::Property& rProperty : aProperties) { // calling 'regular' functions that will operate on the selection PropertyState eState = xPropSet->getPropertyState( rProperty.Name ); diff --git a/editeng/source/accessibility/AccessibleImageBullet.cxx b/editeng/source/accessibility/AccessibleImageBullet.cxx index a5dc2b66bd92..c3a051cf01fd 100644 --- a/editeng/source/accessibility/AccessibleImageBullet.cxx +++ b/editeng/source/accessibility/AccessibleImageBullet.cxx @@ -19,6 +19,7 @@ #include <tools/gen.hxx> #include <tools/debug.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <vcl/settings.hxx> #include <rtl/ustring.hxx> @@ -30,7 +31,6 @@ #include <com/sun/star/accessibility/AccessibleEventId.hpp> #include <comphelper/accessibleeventnotifier.hxx> #include <cppuhelper/supportsservice.hxx> -#include <unotools/accessiblestatesethelper.hxx> #include <i18nlangtag/languagetag.hxx> #include <editeng/AccessibleEditableTextPara.hxx> #include <editeng/eerdll.hxx> @@ -49,12 +49,12 @@ using namespace ::com::sun::star::accessibility; namespace accessibility { - AccessibleImageBullet::AccessibleImageBullet ( const uno::Reference< XAccessible >& rParent ) : + AccessibleImageBullet::AccessibleImageBullet ( uno::Reference< XAccessible > xParent ) : mnParagraphIndex( 0 ), mnIndexInParent( 0 ), mpEditSource( nullptr ), maEEOffset( 0, 0 ), - mxParent( rParent ), + mxParent(std::move( xParent )), // well, that's strictly (UNO) exception safe, though not // really robust. We rely on the fact that this member is // constructed last, and that the constructor body catches @@ -65,14 +65,13 @@ namespace accessibility try { // Create the state set. - rtl::Reference<::utl::AccessibleStateSetHelper> pStateSet = new ::utl::AccessibleStateSetHelper (); - mxStateSet = pStateSet; + mnStateSet = 0; // these are always on - pStateSet->AddState( AccessibleStateType::VISIBLE ); - pStateSet->AddState( AccessibleStateType::SHOWING ); - pStateSet->AddState( AccessibleStateType::ENABLED ); - pStateSet->AddState( AccessibleStateType::SENSITIVE ); + mnStateSet |= AccessibleStateType::VISIBLE; + mnStateSet |= AccessibleStateType::SHOWING; + mnStateSet |= AccessibleStateType::ENABLED; + mnStateSet |= AccessibleStateType::SENSITIVE; } catch( const uno::Exception& ) {} } @@ -98,17 +97,16 @@ namespace accessibility return uno::Reference< XAccessibleContext > ( this ); } - sal_Int32 SAL_CALL AccessibleImageBullet::getAccessibleChildCount() + sal_Int64 SAL_CALL AccessibleImageBullet::getAccessibleChildCount() { return 0; } - uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleChild( sal_Int32 ) + uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleChild( sal_Int64 ) { throw lang::IndexOutOfBoundsException("No children available", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + getXWeak() ); } uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleParent() @@ -117,7 +115,7 @@ namespace accessibility return mxParent; } - sal_Int32 SAL_CALL AccessibleImageBullet::getAccessibleIndexInParent() + sal_Int64 SAL_CALL AccessibleImageBullet::getAccessibleIndexInParent() { return mnIndexInParent; @@ -131,18 +129,12 @@ namespace accessibility OUString SAL_CALL AccessibleImageBullet::getAccessibleDescription() { - - SolarMutexGuard aGuard; - // Get the string from the resource for the specified id. return EditResId(RID_SVXSTR_A11Y_IMAGEBULLET_DESCRIPTION); } OUString SAL_CALL AccessibleImageBullet::getAccessibleName() { - - SolarMutexGuard aGuard; - // Get the string from the resource for the specified id. return EditResId(RID_SVXSTR_A11Y_IMAGEBULLET_NAME); } @@ -154,18 +146,13 @@ namespace accessibility return uno::Reference< XAccessibleRelationSet >(); } - uno::Reference< XAccessibleStateSet > SAL_CALL AccessibleImageBullet::getAccessibleStateSet() + sal_Int64 SAL_CALL AccessibleImageBullet::getAccessibleStateSet() { - SolarMutexGuard aGuard; // Create a copy of the state set and return it. - ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - - if( !pStateSet ) - return uno::Reference<XAccessibleStateSet>(); - return uno::Reference<XAccessibleStateSet>( new ::utl::AccessibleStateSetHelper (*pStateSet) ); + return mnStateSet; } lang::Locale SAL_CALL AccessibleImageBullet::getLocale() @@ -218,7 +205,7 @@ namespace accessibility tools::Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) ); Point aPoint( rPoint.X, rPoint.Y ); - return aRect.IsInside( aPoint ); + return aRect.Contains( aPoint ); } uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleAtPoint( const awt::Point& /*aPoint*/ ) @@ -420,34 +407,28 @@ namespace accessibility uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleImageBullet* > (this)->getAccessibleContext() ); - AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue); + AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue, -1); // #106234# Delegate to EventNotifier ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(), aEvent ); } - void AccessibleImageBullet::SetState( const sal_Int16 nStateId ) + void AccessibleImageBullet::SetState( const sal_Int64 nStateId ) { - - ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if( pStateSet != nullptr && - !pStateSet->contains(nStateId) ) + if( !(mnStateSet & nStateId) ) { - pStateSet->AddState( nStateId ); - FireEvent( AccessibleEventId::STATE_CHANGED, uno::makeAny( nStateId ) ); + mnStateSet |= nStateId; + FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any( nStateId ) ); } } - void AccessibleImageBullet::UnSetState( const sal_Int16 nStateId ) + void AccessibleImageBullet::UnSetState( const sal_Int64 nStateId ) { - - ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); - if( pStateSet != nullptr && - pStateSet->contains(nStateId) ) + if( mnStateSet & nStateId ) { - pStateSet->RemoveState( nStateId ); - FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), uno::makeAny( nStateId ) ); + mnStateSet &= ~nStateId; + FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), uno::Any( nStateId ) ); } } @@ -474,8 +455,8 @@ namespace accessibility if( nOldIndex != nIndex ) { // index and therefore description changed - FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::makeAny( getAccessibleDescription() ), aOldDesc ); - FireEvent( AccessibleEventId::NAME_CHANGED, uno::makeAny( getAccessibleName() ), aOldName ); + FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::Any( getAccessibleDescription() ), aOldDesc ); + FireEvent( AccessibleEventId::NAME_CHANGED, uno::Any( getAccessibleName() ), aOldName ); } } catch( const uno::Exception& ) {} // optional behaviour @@ -487,9 +468,8 @@ namespace accessibility if( !mpEditSource ) throw uno::RuntimeException("No edit source, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + cppu::getXWeak + ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy return *mpEditSource; } @@ -501,15 +481,13 @@ namespace accessibility if( !pTextForwarder ) throw uno::RuntimeException("Unable to fetch text forwarder, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + cppu::getXWeak + ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy if( !pTextForwarder->IsValid() ) throw uno::RuntimeException("Text forwarder is invalid, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + cppu::getXWeak + ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy return *pTextForwarder; } @@ -522,16 +500,14 @@ namespace accessibility if( !pViewForwarder ) { throw uno::RuntimeException("Unable to fetch view forwarder, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + cppu::getXWeak + ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy } if( !pViewForwarder->IsValid() ) throw uno::RuntimeException("View forwarder is invalid, object is defunct", - uno::Reference< uno::XInterface > - ( static_cast< ::cppu::OWeakObject* > - ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + cppu::getXWeak + ( const_cast< AccessibleImageBullet* > (this) ) ); // disambiguate hierarchy return *pViewForwarder; } diff --git a/editeng/source/accessibility/AccessibleImageBullet.hxx b/editeng/source/accessibility/AccessibleImageBullet.hxx index b1041ce4aa56..97fd98cae796 100644 --- a/editeng/source/accessibility/AccessibleImageBullet.hxx +++ b/editeng/source/accessibility/AccessibleImageBullet.hxx @@ -19,6 +19,7 @@ #pragma once +#include <rtl/ref.hxx> #include <tools/gen.hxx> #include <cppuhelper/implbase.hxx> @@ -48,7 +49,7 @@ namespace accessibility public: /// Create accessible object for given parent - AccessibleImageBullet ( const css::uno::Reference< css::accessibility::XAccessible >& rParent ); + AccessibleImageBullet ( css::uno::Reference< css::accessibility::XAccessible > xParent ); virtual ~AccessibleImageBullet () override; @@ -56,15 +57,15 @@ namespace accessibility virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) override; // XAccessibleContext - virtual sal_Int32 SAL_CALL getAccessibleChildCount() override; - virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override; + virtual sal_Int64 SAL_CALL getAccessibleChildCount() override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override; virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override; - virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override; + virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override; virtual sal_Int16 SAL_CALL getAccessibleRole() override; virtual OUString SAL_CALL getAccessibleDescription() override; virtual OUString SAL_CALL getAccessibleName() override; virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override; - virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override; + virtual sal_Int64 SAL_CALL getAccessibleStateSet() override; virtual css::lang::Locale SAL_CALL getLocale() override; // XAccessibleEventBroadcaster @@ -146,8 +147,8 @@ namespace accessibility AccessibleImageBullet& operator= ( const AccessibleImageBullet& ) = delete; // maintain state set and send STATE_CHANGE events - void SetState( const sal_Int16 nStateId ); - void UnSetState( const sal_Int16 nStateId ); + void SetState( const sal_Int64 nStateId ); + void UnSetState( const sal_Int64 nStateId ); SvxEditSource& GetEditSource() const; @@ -186,7 +187,7 @@ namespace accessibility Point maEEOffset; // the current state set (updated from SetState/UnSetState and guarded by solar mutex) - css::uno::Reference< css::accessibility::XAccessibleStateSet > mxStateSet; + sal_Int64 mnStateSet = 0; /// The shape we're the accessible for (unguarded) css::uno::Reference< css::accessibility::XAccessible > mxParent; diff --git a/editeng/source/accessibility/AccessibleParaManager.cxx b/editeng/source/accessibility/AccessibleParaManager.cxx index 2fb3006da7b7..aae8c5817f36 100644 --- a/editeng/source/accessibility/AccessibleParaManager.cxx +++ b/editeng/source/accessibility/AccessibleParaManager.cxx @@ -17,10 +17,9 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <cassert> // Global header - - #include <com/sun/star/uno/Any.hxx> #include <com/sun/star/uno/Reference.hxx> #include <o3tl/safeint.hxx> @@ -29,10 +28,7 @@ #include <com/sun/star/accessibility/XAccessible.hpp> #include <com/sun/star/accessibility/AccessibleStateType.hpp> - // Project-local header - - #include <editeng/AccessibleParaManager.hxx> #include <editeng/AccessibleEditableTextPara.hxx> @@ -45,6 +41,7 @@ namespace accessibility { AccessibleParaManager::AccessibleParaManager() : maChildren(1), + mnChildStates( 0 ), maEEOffset( 0, 0 ), mnFocusedChild( -1 ), mbActive( false ) @@ -56,9 +53,9 @@ namespace accessibility // owner is responsible for possible child death } - void AccessibleParaManager::SetAdditionalChildStates( const VectorOfStates& rChildStates ) + void AccessibleParaManager::SetAdditionalChildStates( sal_Int64 nChildStates ) { - maChildStates = rChildStates; + mnChildStates = nChildStates; } void AccessibleParaManager::SetNum( sal_Int32 nNumParas ) @@ -115,8 +112,8 @@ namespace accessibility bool AccessibleParaManager::IsReferencable( sal_Int32 nChild ) const { - DBG_ASSERT( 0 <= nChild && maChildren.size() > o3tl::make_unsigned(nChild), - "AccessibleParaManager::IsReferencable: invalid index" ); + assert(0 <= nChild && maChildren.size() > o3tl::make_unsigned(nChild) + && "AccessibleParaManager::IsReferencable: invalid index"); if( 0 <= nChild && maChildren.size() > o3tl::make_unsigned(nChild) ) { @@ -144,6 +141,17 @@ namespace accessibility } } + bool AccessibleParaManager::HasCreatedChild( sal_Int32 nParagraphIndex ) const + { + if( 0 <= nParagraphIndex && maChildren.size() > o3tl::make_unsigned(nParagraphIndex) ) + { + auto const & rChild = maChildren[ nParagraphIndex ]; + return rChild.second.Width != 0 || rChild.second.Height != 0; + } + else + return false; + } + AccessibleParaManager::Child AccessibleParaManager::CreateChild( sal_Int32 nChild, const uno::Reference< XAccessible >& xFrontEnd, SvxEditSourceAdapter& rEditSource, @@ -232,35 +240,39 @@ namespace accessibility rChild.SetState( AccessibleStateType::FOCUSED ); // add states passed from outside - for( const auto& rState : maChildStates ) - rChild.SetState( rState ); + for (int i=0; i<63; i++) + { + sal_Int64 nState = sal_Int64(1) << i; + if ( nState & mnChildStates ) + rChild.SetState( nState ); + } } - void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int16 nStateId ) + void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int64 nStateId ) { - MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::SetState, + MemFunAdapter< const sal_Int64 > aFunc( &AccessibleEditableTextPara::SetState, nStateId ); aFunc( GetChild(nChild) ); } - void AccessibleParaManager::SetState( const sal_Int16 nStateId ) + void AccessibleParaManager::SetState( const sal_Int64 nStateId ) { std::for_each( begin(), end(), - MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::SetState, + MemFunAdapter< const sal_Int64 >( &AccessibleEditableTextPara::SetState, nStateId ) ); } - void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int16 nStateId ) + void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int64 nStateId ) { - MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::UnSetState, + MemFunAdapter< const sal_Int64 > aFunc( &AccessibleEditableTextPara::UnSetState, nStateId ); aFunc( GetChild(nChild) ); } - void AccessibleParaManager::UnSetState( const sal_Int16 nStateId ) + void AccessibleParaManager::UnSetState( const sal_Int64 nStateId ) { std::for_each( begin(), end(), - MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::UnSetState, + MemFunAdapter< const sal_Int64 >( &AccessibleEditableTextPara::UnSetState, nStateId ) ); } diff --git a/editeng/source/accessibility/AccessibleSelectionBase.cxx b/editeng/source/accessibility/AccessibleSelectionBase.cxx index 09975c9ecab0..e70b61840822 100644 --- a/editeng/source/accessibility/AccessibleSelectionBase.cxx +++ b/editeng/source/accessibility/AccessibleSelectionBase.cxx @@ -39,14 +39,14 @@ namespace accessibility } - void SAL_CALL AccessibleSelectionBase::selectAccessibleChild( sal_Int32 nChildIndex ) + void SAL_CALL AccessibleSelectionBase::selectAccessibleChild( sal_Int64 nChildIndex ) { ::osl::MutexGuard aGuard( implGetMutex() ); OCommonAccessibleSelection::selectAccessibleChild( nChildIndex ); } - sal_Bool SAL_CALL AccessibleSelectionBase::isAccessibleChildSelected( sal_Int32 nChildIndex ) + sal_Bool SAL_CALL AccessibleSelectionBase::isAccessibleChildSelected( sal_Int64 nChildIndex ) { ::osl::MutexGuard aGuard( implGetMutex() ); return OCommonAccessibleSelection::isAccessibleChildSelected( nChildIndex ); @@ -67,21 +67,21 @@ namespace accessibility } - sal_Int32 SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChildCount( ) + sal_Int64 SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChildCount( ) { ::osl::MutexGuard aGuard( implGetMutex() ); return OCommonAccessibleSelection::getSelectedAccessibleChildCount(); } - uno::Reference< XAccessible > SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + uno::Reference< XAccessible > SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex ) { ::osl::MutexGuard aGuard( implGetMutex() ); return OCommonAccessibleSelection::getSelectedAccessibleChild( nSelectedChildIndex ); } - void SAL_CALL AccessibleSelectionBase::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) + void SAL_CALL AccessibleSelectionBase::deselectAccessibleChild( sal_Int64 nSelectedChildIndex ) { ::osl::MutexGuard aGuard( implGetMutex() ); OCommonAccessibleSelection::deselectAccessibleChild( nSelectedChildIndex ); diff --git a/editeng/source/accessibility/AccessibleStaticTextBase.cxx b/editeng/source/accessibility/AccessibleStaticTextBase.cxx index 1dcf37b8d54a..f7fd934dfc90 100644 --- a/editeng/source/accessibility/AccessibleStaticTextBase.cxx +++ b/editeng/source/accessibility/AccessibleStaticTextBase.cxx @@ -27,7 +27,6 @@ #include <algorithm> #include <rtl/ustrbuf.hxx> #include <tools/debug.hxx> -#include <vcl/window.hxx> #include <vcl/svapp.hxx> #include <comphelper/sequence.hxx> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> @@ -122,8 +121,7 @@ namespace accessibility void SetEventSource( const uno::Reference< XAccessible >& rInterface ) { - - mxThis = rInterface; + mpThis = rInterface.get(); } void SetOffset( const Point& ); @@ -164,8 +162,8 @@ namespace accessibility // our frontend class (the one implementing the actual // interface). That's not necessarily the one containing the impl - // pointer - uno::Reference< XAccessible > mxThis; + // pointer. Note that this is not an uno::Reference to prevent ref-counting cycles and leaks. + XAccessible* mpThis; // implements our functionality, we're just an adapter (guarded by solar mutex) mutable rtl::Reference<AccessibleEditableTextPara> mxTextParagraph; @@ -178,9 +176,9 @@ namespace accessibility // AccessibleStaticTextBase_Impl implementation - AccessibleStaticTextBase_Impl::AccessibleStaticTextBase_Impl() : - mxTextParagraph( new AccessibleEditableTextPara(nullptr) ), - maEditSource() + AccessibleStaticTextBase_Impl::AccessibleStaticTextBase_Impl() + : mpThis(nullptr) + , mxTextParagraph(new AccessibleEditableTextPara(nullptr)) { // TODO: this is still somewhat of a hack, all the more since @@ -209,7 +207,7 @@ namespace accessibility mxTextParagraph->Dispose(); // drop references - mxThis = nullptr; + mpThis = nullptr; mxTextParagraph.clear(); } @@ -217,7 +215,7 @@ namespace accessibility { if( !mxTextParagraph.is() ) - throw lang::DisposedException ("object has been already disposed", mxThis ); + throw lang::DisposedException ("object has been already disposed", mpThis ); // TODO: Have a different method on AccessibleEditableTextPara // that does not care about state changes @@ -275,7 +273,7 @@ namespace accessibility if( nFlatIndex < 0 ) throw lang::IndexOutOfBoundsException("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds", - mxThis); + mpThis); // gratuitously accepting larger indices here, AccessibleEditableTextPara will throw eventually sal_Int32 nCurrPara, nCurrIndex, nParas, nCurrCount; @@ -307,7 +305,7 @@ namespace accessibility // not found? Out of bounds throw lang::IndexOutOfBoundsException("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds", - mxThis); + mpThis); } bool AccessibleStaticTextBase_Impl::SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, @@ -467,13 +465,13 @@ namespace accessibility } // XAccessibleContext - sal_Int32 AccessibleStaticTextBase::getAccessibleChildCount() + sal_Int64 AccessibleStaticTextBase::getAccessibleChildCount() { // no children at all return 0; } - uno::Reference< XAccessible > AccessibleStaticTextBase::getAccessibleChild( sal_Int32 /*i*/ ) + uno::Reference< XAccessible > AccessibleStaticTextBase::getAccessibleChild( sal_Int64 /*i*/ ) { // no children at all return uno::Reference< XAccessible >(); @@ -703,8 +701,7 @@ namespace accessibility // paragraphs inbetween are fully included for( ; i<aEndIndex.nPara; ++i ) { - aRes.append(cNewLine); - aRes.append(mpImpl->GetParagraph(i).getText()); + aRes.append(OUStringChar(cNewLine) + mpImpl->GetParagraph(i).getText()); } if( i<=aEndIndex.nPara ) diff --git a/editeng/source/accessibility/AccessibleStringWrap.cxx b/editeng/source/accessibility/AccessibleStringWrap.cxx index 77149d1df70d..5461aad9f4c8 100644 --- a/editeng/source/accessibility/AccessibleStringWrap.cxx +++ b/editeng/source/accessibility/AccessibleStringWrap.cxx @@ -22,6 +22,7 @@ #include <cstdlib> #include <tools/debug.hxx> +#include <utility> #include <vcl/outdev.hxx> #include <editeng/svxfont.hxx> @@ -31,10 +32,10 @@ // AccessibleStringWrap implementation -AccessibleStringWrap::AccessibleStringWrap( OutputDevice& rDev, SvxFont& rFont, const OUString& rText ) : +AccessibleStringWrap::AccessibleStringWrap( OutputDevice& rDev, SvxFont& rFont, OUString aText ) : mrDev( rDev ), mrFont( rFont ), - maText( rText ) + maText(std::move( aText )) { } @@ -56,12 +57,11 @@ void AccessibleStringWrap::GetCharacterBounds( sal_Int32 nIndex, tools::Rectangl } else { - tools::Long aXArray[2]; - mrDev.GetCaretPositions( maText, aXArray, nIndex, 1 ); + KernArray aDXArray; + mrDev.GetTextArray(maText, &aDXArray, nIndex, 1); rRect.SetLeft( 0 ); rRect.SetTop( 0 ); - rRect.SetSize( Size(mrDev.GetTextHeight(), std::abs(aXArray[0] - aXArray[1])) ); - rRect.Move( std::min(aXArray[0], aXArray[1]), 0 ); + rRect.SetSize(Size(mrDev.GetTextHeight(), aDXArray[0])); } if( mrFont.IsVertical() ) @@ -80,7 +80,7 @@ sal_Int32 AccessibleStringWrap::GetIndexAtPoint( const Point& rPoint ) for( i=0; i<nLen; ++i ) { GetCharacterBounds(i, aRect); - if( aRect.IsInside(rPoint) ) + if( aRect.Contains(rPoint) ) return i; } diff --git a/editeng/source/editeng/ContentNode.cxx b/editeng/source/editeng/ContentNode.cxx new file mode 100644 index 000000000000..08bf250b6c86 --- /dev/null +++ b/editeng/source/editeng/ContentNode.cxx @@ -0,0 +1,1029 @@ +/* -*- 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 <ContentNode.hxx> +#include <editeng/tstpitem.hxx> +#include "impedit.hxx" + +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <libxml/xmlwriter.h> + +#include <memory> +#include <set> + +ContentNode::ContentNode( SfxItemPool& rPool ) + : maContentAttribs( rPool ) +{ +} + +ContentNode::ContentNode( const OUString& rStr, const ContentAttribs& rContentAttribs ) + : maString(rStr) + , maContentAttribs(rContentAttribs) +{ +} + +void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew ) +{ + if ( !nNew ) + return; + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif + + // Since features are treated differently than normal character attributes, + // but can also affect the order of the start list. // In every if ..., in the next (n) opportunities due to bFeature or + // an existing special case, must (n-1) opportunities be provided with + // bResort. The most likely possibility receives no bResort, so that is + // not sorted anew when all attributes are the same. + bool bResort = false; + bool bExpandedEmptyAtIndexNull = false; + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rAttribs = maCharAttribList.GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); + while ( pAttrib ) + { + if ( pAttrib->GetEnd() >= nIndex ) + { + // Move all attributes behind the insertion point... + if ( pAttrib->GetStart() > nIndex ) + { + pAttrib->MoveForward( nNew ); + } + // 0: Expand empty attribute, if at insertion point + else if ( pAttrib->IsEmpty() ) + { + // Do not check Index, an empty one could only be there + // When later checking it anyhow: + // Special case: Start == 0; AbsLen == 1, nNew = 1 + // => Expand, because of paragraph break! + // Start <= nIndex, End >= nIndex => Start=End=nIndex! +// if ( pAttrib->GetStart() == nIndex ) + pAttrib->Expand( nNew ); + bResort = true; + if ( pAttrib->GetStart() == 0 ) + bExpandedEmptyAtIndexNull = true; + } + // 1: Attribute starts before, goes to index ... + else if ( pAttrib->GetEnd() == nIndex ) // Start must be before + { + // Only expand when there is no feature + // and if not in exclude list! + // Otherwise, a UL will go on until a new ULDB, expanding both +// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) + if ( !pAttrib->IsFeature() && !maCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) + { + if ( !pAttrib->IsEdge() ) + pAttrib->Expand( nNew ); + } + else + bResort = true; + } + // 2: Attribute starts before, goes past the Index... + else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) + { + DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" ); + pAttrib->Expand( nNew ); + } + // 3: Attribute starts on index... + else if ( pAttrib->GetStart() == nIndex ) + { + if ( pAttrib->IsFeature() ) + { + pAttrib->MoveForward( nNew ); + bResort = true; + } + else + { + bool bExpand = false; + if ( nIndex == 0 ) + { + bExpand = true; + if( bExpandedEmptyAtIndexNull ) + { + // Check if this kind of attribute was empty and expanded here... + sal_uInt16 nW = pAttrib->GetItem()->Which(); + for ( std::size_t nA = 0; nA < nAttr; nA++ ) + { + const EditCharAttrib& r = *maCharAttribList.GetAttribs()[nA]; + if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) ) + { + bExpand = false; + break; + } + } + + } + } + if ( bExpand ) + { + pAttrib->Expand( nNew ); + bResort = true; + } + else + { + pAttrib->MoveForward( nNew ); + } + } + } + } + + if ( pAttrib->IsEdge() ) + pAttrib->SetEdge(false); + + DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); + + DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" ); + DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" ); + if ( pAttrib->IsEmpty() ) + { + OSL_FAIL( "Empty Attribute after ExpandAttribs?" ); + bResort = true; + rAttribs.erase(rAttribs.begin()+nAttr); + } + else + { + ++nAttr; + } + pAttrib = GetAttrib(rAttribs, nAttr); + } + + if ( bResort ) + maCharAttribList.ResortAttribs(); + + if (mpWrongList) + { + bool bSep = ( maString[ nIndex ] == ' ' ) || IsFeature( nIndex ); + mpWrongList->TextInserted( nIndex, nNew, bSep ); + } + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif +} + +void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted ) +{ + if ( !nDeleted ) + return; + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif + + // Since features are treated differently than normal character attributes, + // but can also affect the order of the start list + bool bResort = false; + sal_Int32 nEndChanges = nIndex+nDeleted; + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rAttribs = maCharAttribList.GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); + while ( pAttrib ) + { + bool bDelAttr = false; + if ( pAttrib->GetEnd() >= nIndex ) + { + // Move all Attribute behind the insert point... + if ( pAttrib->GetStart() >= nEndChanges ) + { + pAttrib->MoveBackward( nDeleted ); + } + // 1. Delete Internal attributes... + else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) + { + // Special case: Attribute covers the area exactly + // => keep as empty Attribute. + if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) + { + pAttrib->GetEnd() = nIndex; // empty + bResort = true; + } + else + bDelAttr = true; + } + // 2. Attribute starts earlier, ends inside or behind it ... + else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) + { + DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); + if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside + pAttrib->GetEnd() = nIndex; + else + pAttrib->Collaps( nDeleted ); // ends behind + } + // 3. Attribute starts inside, ending behind ... + else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) + { + // Features not allowed to expand! + if ( pAttrib->IsFeature() ) + { + pAttrib->MoveBackward( nDeleted ); + bResort = true; + } + else + { + pAttrib->GetStart() = nEndChanges; + pAttrib->MoveBackward( nDeleted ); + } + } + } + DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); + + DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collapse: Attribute distorted!" ); + DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collapse: Attribute larger than paragraph!" ); + if ( bDelAttr ) + { + bResort = true; + rAttribs.erase(rAttribs.begin()+nAttr); + } + else + { + if ( pAttrib->IsEmpty() ) + maCharAttribList.SetHasEmptyAttribs(true); + nAttr++; + } + + pAttrib = GetAttrib(rAttribs, nAttr); + } + + if ( bResort ) + maCharAttribList.ResortAttribs(); + + if (mpWrongList) + mpWrongList->TextDeleted(nIndex, nDeleted); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif +} + +void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs ) +{ + assert(pPrevNode); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pPrevNode->maCharAttribList); +#endif + + sal_Int32 nCut = pPrevNode->Len(); + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr); + while ( pAttrib ) + { + if ( pAttrib->GetEnd() < nCut ) + { + // remain unchanged... + nAttr++; + } + else if ( pAttrib->GetEnd() == nCut ) + { + // must be copied as an empty attributes. + if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !maCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) + { + EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); + assert(pNewAttrib); + maCharAttribList.InsertAttrib( pNewAttrib ); + } + nAttr++; + } + else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) + { + // If cut is done right at the front then the attribute must be + // kept! Has to be copied and changed. + EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); + assert(pNewAttrib); + maCharAttribList.InsertAttrib( pNewAttrib ); + pAttrib->GetEnd() = nCut; + nAttr++; + } + else + { + // Move all attributes in the current node (this) + CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr; + maCharAttribList.InsertAttrib(it->release()); + rPrevAttribs.erase(it); + pAttrib->MoveBackward( nCut ); + } + pAttrib = GetAttrib(rPrevAttribs, nAttr); + } + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pPrevNode->maCharAttribList); +#endif +} + +void ContentNode::AppendAttribs( ContentNode* pNextNode ) +{ + assert(pNextNode); + + sal_Int32 nNewStart = maString.getLength(); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pNextNode->maCharAttribList); +#endif + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr); + while ( pAttrib ) + { + // Move all attributes in the current node (this) + bool bMelted = false; + if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) + { + // Attributes can possibly be summarized as: + std::size_t nTmpAttr = 0; + EditCharAttrib* pTmpAttrib = GetAttrib( maCharAttribList.GetAttribs(), nTmpAttr ); + while ( !bMelted && pTmpAttrib ) + { + ++nTmpAttr; + if ( pTmpAttrib->GetEnd() == nNewStart ) + { + if (pTmpAttrib->Which() == pAttrib->Which()) + { + // prevent adding 2 0-length attributes at same position + if ((*(pTmpAttrib->GetItem()) == *(pAttrib->GetItem())) + || (0 == pAttrib->GetLen())) + { + pTmpAttrib->GetEnd() = + pTmpAttrib->GetEnd() + pAttrib->GetLen(); + rNextAttribs.erase(rNextAttribs.begin()+nAttr); + // Unsubscribe from the pool?! + bMelted = true; + } + else if (0 == pTmpAttrib->GetLen()) + { + --nTmpAttr; // to cancel earlier increment... + maCharAttribList.Remove(nTmpAttr); + } + } + } + pTmpAttrib = GetAttrib( maCharAttribList.GetAttribs(), nTmpAttr ); + } + } + + if ( !bMelted ) + { + pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; + pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; + CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr; + maCharAttribList.InsertAttrib(it->release()); + rNextAttribs.erase(it); + } + pAttrib = GetAttrib(rNextAttribs, nAttr); + } + // For the Attributes that just moved over: + rNextAttribs.clear(); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pNextNode->maCharAttribList); +#endif +} + +void ContentNode::CreateDefFont() +{ + // First use the information from the style ... + SfxStyleSheet* pS = maContentAttribs.GetStyleSheet(); + if ( pS ) + CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); + + // ... then iron out the hard paragraph formatting... + CreateFont( GetCharAttribs().GetDefFont(), + GetContentAttribs().GetItems(), pS == nullptr ); +} + +void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) +{ + maContentAttribs.SetStyleSheet( pS ); + + + // First use the information from the style ... + GetCharAttribs().GetDefFont() = rFontFromStyle; + // ... then iron out the hard paragraph formatting... + CreateFont( GetCharAttribs().GetDefFont(), + GetContentAttribs().GetItems(), pS == nullptr ); +} + +void ContentNode::SetStyleSheet( SfxStyleSheet* pS, bool bRecalcFont ) +{ + maContentAttribs.SetStyleSheet( pS ); + if ( bRecalcFont ) + CreateDefFont(); +} + +bool ContentNode::IsFeature( sal_Int32 nPos ) const +{ + return maString[nPos] == CH_FEATURE; +} + +sal_Int32 ContentNode::Len() const +{ + return maString.getLength(); +} + +sal_Int32 ContentNode::GetExpandedLen() const +{ + sal_Int32 nLen = maString.getLength(); + + // Fields can be longer than the placeholder in the Node + const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); + for (sal_Int32 nAttr = rAttrs.size(); nAttr; ) + { + const EditCharAttrib& rAttr = *rAttrs[--nAttr]; + if (rAttr.Which() == EE_FEATURE_FIELD) + { + nLen += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); + --nLen; // Standalone, to avoid corner cases when previous getLength() returns 0 + } + } + + return nLen; +} + +OUString ContentNode::GetExpandedText(sal_Int32 nStartPos, sal_Int32 nEndPos) const +{ + if ( nEndPos < 0 || nEndPos > Len() ) + nEndPos = Len(); + + DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" ); + + sal_Int32 nIndex = nStartPos; + OUStringBuffer aStr(256); + const EditCharAttrib* pNextFeature = GetCharAttribs().FindFeature( nIndex ); + while ( nIndex < nEndPos ) + { + sal_Int32 nEnd = nEndPos; + if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) + nEnd = pNextFeature->GetStart(); + else + pNextFeature = nullptr; // Feature does not interest the below + + DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" ); + //!! beware of sub string length of -1 + if (nEnd > nIndex) + aStr.append( GetString().subView(nIndex, nEnd - nIndex) ); + + if ( pNextFeature ) + { + switch ( pNextFeature->GetItem()->Which() ) + { + case EE_FEATURE_TAB: aStr.append( "\t" ); + break; + case EE_FEATURE_LINEBR: aStr.append( "\x0A" ); + break; + case EE_FEATURE_FIELD: + aStr.append( static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue() ); + break; + default: OSL_FAIL( "What feature?" ); + } + pNextFeature = GetCharAttribs().FindFeature( ++nEnd ); + } + nIndex = nEnd; + } + return aStr.makeStringAndClear(); +} + +void ContentNode::UnExpandPosition( sal_Int32 &rPos, bool bBiasStart ) +{ + sal_Int32 nOffset = 0; + + const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); + for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr ) + { + const EditCharAttrib& rAttr = *rAttrs[nAttr]; + assert (!(nAttr < rAttrs.size() - 1) || + rAttrs[nAttr]->GetStart() <= rAttrs[nAttr + 1]->GetStart()); + + nOffset = rAttr.GetStart(); + + if (nOffset >= rPos) // happens after the position + return; + + if (rAttr.Which() == EE_FEATURE_FIELD) + { + sal_Int32 nChunk = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); + nChunk--; // Character representing the field in the string + + if (nOffset + nChunk >= rPos) // we're inside the field + { + if (bBiasStart) + rPos = rAttr.GetStart(); + else + rPos = rAttr.GetEnd(); + return; + } + // Adjust for the position + rPos -= nChunk; + } + } + assert (rPos <= Len()); +} + +/* + * Fields are represented by a single character in the underlying string + * and/or selection, however, they can be expanded to the full value of + * the field. When we're dealing with selection / offsets however we need + * to deal in character positions inside the real (unexpanded) string. + * This method maps us back to character offsets. + */ +void ContentNode::UnExpandPositions( sal_Int32 &rStartPos, sal_Int32 &rEndPos ) +{ + UnExpandPosition( rStartPos, true ); + UnExpandPosition( rEndPos, false ); +} + +void ContentNode::SetChar(sal_Int32 nPos, sal_Unicode c) +{ + maString = maString.replaceAt(nPos, 1, rtl::OUStringChar(c)); +} + +void ContentNode::Insert(std::u16string_view rStr, sal_Int32 nPos) +{ + maString = maString.replaceAt(nPos, 0, rStr); +} + +void ContentNode::Append(std::u16string_view rStr) +{ + maString += rStr; +} + +void ContentNode::Erase(sal_Int32 nPos) +{ + maString = maString.copy(0, nPos); +} + +void ContentNode::Erase(sal_Int32 nPos, sal_Int32 nCount) +{ + maString = maString.replaceAt(nPos, nCount, u""); +} + +OUString ContentNode::Copy(sal_Int32 nPos) const +{ + return maString.copy(nPos); +} + +OUString ContentNode::Copy(sal_Int32 nPos, sal_Int32 nCount) const +{ + return maString.copy(nPos, nCount); +} + +sal_Unicode ContentNode::GetChar(sal_Int32 nPos) const +{ + return maString[nPos]; +} + +void ContentNode::EnsureWrongList() +{ + if (!mpWrongList) + CreateWrongList(); +} + +WrongList* ContentNode::GetWrongList() +{ + return mpWrongList.get(); +} + +const WrongList* ContentNode::GetWrongList() const +{ + return mpWrongList.get(); +} + +void ContentNode::SetWrongList( WrongList* p ) +{ + mpWrongList.reset(p); +} + +void ContentNode::CreateWrongList() +{ + SAL_WARN_IF( mpWrongList && !mpWrongList->empty(), "editeng", "WrongList already exist!"); + if (!mpWrongList || !mpWrongList->empty()) + mpWrongList.reset(new WrongList); +} + +void ContentNode::DestroyWrongList() +{ + mpWrongList.reset(); +} + +void ContentNode::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentNode")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("maString"), BAD_CAST(maString.toUtf8().getStr())); + maContentAttribs.dumpAsXml(pWriter); + maCharAttribList.dumpAsXml(pWriter); + (void)xmlTextWriterEndElement(pWriter); +} + +void ContentNode::checkAndDeleteEmptyAttribs() const +{ + // Delete empty attributes, but only if paragraph is not empty! + if (GetCharAttribs().HasEmptyAttribs() && Len()) + { + const_cast<ContentNode*>(this)->GetCharAttribs().DeleteEmptyAttribs(); + } +} + +ContentAttribs::ContentAttribs( SfxItemPool& rPool ) + : maAttribSet(rPool) +{ +} + +SvxTabStop ContentAttribs::FindTabStop( sal_Int32 nCurPos, sal_uInt16 nDefTab ) +{ + const SvxTabStopItem& rTabs = GetItem( EE_PARA_TABS ); + for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) + { + const SvxTabStop& rTab = rTabs[i]; + if ( rTab.GetTabPos() > nCurPos ) + return rTab; + } + + // if there's a default tab size defined for this item use that instead + if (rTabs.GetDefaultDistance()) + nDefTab = rTabs.GetDefaultDistance(); + + // Determine DefTab ... + SvxTabStop aTabStop; + const sal_Int32 x = nCurPos / nDefTab + 1; + aTabStop.GetTabPos() = nDefTab * x; + return aTabStop; +} + +void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) +{ + bool bStyleChanged = ( mpStyle != pS ); + mpStyle = pS; + // Only when other style sheet, not when current style sheet modified + if ( !(mpStyle && bStyleChanged) ) + return; + + // Selectively remove the attributes from the paragraph formatting + // which are specified in the style, so that the attributes of the + // style can have an affect. + const SfxItemSet& rStyleAttribs = mpStyle->GetItemSet(); + for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) + { + // Don't change bullet on/off + if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET ) ) + maAttribSet.ClearItem( nWhich ); + } +} + +const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const +{ + // Hard paragraph attributes take precedence! + const SfxItemSet* pTakeFrom = &maAttribSet; + if ( mpStyle && ( maAttribSet.GetItemState( nWhich, false ) != SfxItemState::SET ) ) + pTakeFrom = &mpStyle->GetItemSet(); + + return pTakeFrom->Get( nWhich ); +} + +bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const +{ + bool bHasItem = false; + if ( maAttribSet.GetItemState( nWhich, false ) == SfxItemState::SET ) + bHasItem = true; + else if ( mpStyle && mpStyle->GetItemSet().GetItemState( nWhich ) == SfxItemState::SET ) + bHasItem = true; + + return bHasItem; +} + +void ContentAttribs::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentAttribs")); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("style"), "%s", mpStyle->GetName().toUtf8().getStr()); + maAttribSet.dumpAsXml(pWriter); + (void)xmlTextWriterEndElement(pWriter); +} + +namespace { + +struct LessByStart +{ + bool operator() (const std::unique_ptr<EditCharAttrib>& left, const std::unique_ptr<EditCharAttrib>& right) const + { + return left->GetStart() < right->GetStart(); + } +}; + +} + +void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) +{ +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// optimize: binary search? ! +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + // Maybe just simply iterate backwards: + // The most common and critical case: Attributes are already sorted + // (InsertTextObject!) binary search would not be optimal here. + // => Would bring something! + + const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt. + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif + + if ( pAttrib->IsEmpty() ) + mbHasEmptyAttribs = true; + + bool bInsert(true); + for (sal_Int32 i = 0, n = maAttribs.size(); i < n; ++i) + { + const EditCharAttrib& rCurAttrib = *maAttribs[i]; + if (rCurAttrib.GetStart() > nStart) + { + maAttribs.insert(maAttribs.begin()+i, std::unique_ptr<EditCharAttrib>(pAttrib)); + bInsert = false; + break; + } + } + + if (bInsert) maAttribs.push_back(std::unique_ptr<EditCharAttrib>(pAttrib)); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif +} + +void CharAttribList::ResortAttribs() +{ + std::sort(maAttribs.begin(), maAttribs.end(), LessByStart()); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif +} + +void CharAttribList::OptimizeRanges() +{ +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif + for (sal_Int32 i = 0; i < static_cast<sal_Int32>(maAttribs.size()); ++i) + { + EditCharAttrib& rAttr = *maAttribs[i]; + for (sal_Int32 nNext = i+1; nNext < static_cast<sal_Int32>(maAttribs.size()); ++nNext) + { + EditCharAttrib& rNext = *maAttribs[nNext]; + if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which()) + { + if (*rNext.GetItem() == *rAttr.GetItem()) + { + rAttr.GetEnd() = rNext.GetEnd(); + maAttribs.erase(maAttribs.begin()+nNext); + } + break; // only 1 attr with same which can start here. + } + else if (rNext.GetStart() > rAttr.GetEnd()) + { + break; + } + } + } +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif +} + +sal_Int32 CharAttribList::Count() const +{ + return maAttribs.size(); +} + +const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const +{ + // Backwards, if one ends where the next starts. + // => The starting one is the valid one ... + AttribsType::const_reverse_iterator it = std::find_if(maAttribs.rbegin(), maAttribs.rend(), + [&nWhich, &nPos](const AttribsType::value_type& rxAttr) { + return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); + if (it != maAttribs.rend()) + { + const EditCharAttrib& rAttr = **it; + return &rAttr; + } + return nullptr; +} + +EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) +{ + // Backwards, if one ends where the next starts. + // => The starting one is the valid one ... + AttribsType::reverse_iterator it = std::find_if(maAttribs.rbegin(), maAttribs.rend(), + [&nWhich, &nPos](AttribsType::value_type& rxAttr) { + return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); + if (it != maAttribs.rend()) + { + EditCharAttrib& rAttr = **it; + return &rAttr; + } + return nullptr; +} + +EditCharAttrib* CharAttribList::FindAttribRightOpen( sal_uInt16 nWhich, sal_Int32 nPos ) +{ + AttribsType::reverse_iterator it = std::find_if(maAttribs.rbegin(), maAttribs.rend(), + [&nWhich, &nPos](AttribsType::value_type& rxAttr) { + return rxAttr->Which() == nWhich && rxAttr->IsInLeftClosedRightOpen(nPos); }); + if (it != maAttribs.rend()) + { + EditCharAttrib& rAttr = **it; + return &rAttr; + } + return nullptr; +} + +const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_Int32 nFromPos ) const +{ + assert(nWhich); + for (auto const& attrib : maAttribs) + { + const EditCharAttrib& rAttr = *attrib; + if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich) + return &rAttr; + } + return nullptr; +} + +bool CharAttribList::HasAttrib( sal_Int32 nStartPos, sal_Int32 nEndPos ) const +{ + return std::any_of(maAttribs.rbegin(), maAttribs.rend(), + [&nStartPos, &nEndPos](const AttribsType::value_type& rxAttr) { + return rxAttr->GetStart() < nEndPos && rxAttr->GetEnd() > nStartPos; }); +} + + +namespace { + +class FindByAddress +{ + const EditCharAttrib* mpAttr; +public: + explicit FindByAddress(const EditCharAttrib* p) : mpAttr(p) {} + bool operator() (const std::unique_ptr<EditCharAttrib>& r) const + { + return r.get() == mpAttr; + } +}; + +} + +void CharAttribList::Remove(const EditCharAttrib* p) +{ + AttribsType::iterator it = std::find_if(maAttribs.begin(), maAttribs.end(), FindByAddress(p)); + if (it != maAttribs.end()) + maAttribs.erase(it); +} + +void CharAttribList::Remove(sal_Int32 nPos) +{ + if (nPos >= static_cast<sal_Int32>(maAttribs.size())) + return; + + maAttribs.erase(maAttribs.begin()+nPos); +} + +void CharAttribList::SetHasEmptyAttribs(bool b) +{ + mbHasEmptyAttribs = b; +} + +bool CharAttribList::HasBoundingAttrib( sal_Int32 nBound ) const +{ + // Backwards, if one ends where the next starts. + // => The starting one is the valid one ... + AttribsType::const_reverse_iterator it = maAttribs.rbegin(), itEnd = maAttribs.rend(); + for (; it != itEnd; ++it) + { + const EditCharAttrib& rAttr = **it; + if (rAttr.GetEnd() < nBound) + return false; + + if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound) + return true; + } + return false; +} + +EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) +{ + if ( !mbHasEmptyAttribs ) + return nullptr; + + for (const std::unique_ptr<EditCharAttrib>& rAttr : maAttribs) + { + if (rAttr->GetStart() == nPos && rAttr->GetEnd() == nPos && rAttr->Which() == nWhich) + return rAttr.get(); + } + return nullptr; +} + +namespace +{ + +class FindByStartPos +{ + sal_Int32 mnPos; +public: + explicit FindByStartPos(sal_Int32 nPos) + : mnPos(nPos) + {} + + bool operator() (std::unique_ptr<EditCharAttrib> const& pCharAttrib) const + { + return pCharAttrib->GetStart() >= mnPos; + } +}; + +} + +const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const +{ + // First, find the first attribute that starts at or after specified position. + AttribsType::const_iterator iterator = + std::find_if(maAttribs.begin(), maAttribs.end(), FindByStartPos(nPos)); + + if (iterator == maAttribs.end()) + { + // All attributes are before the specified position. + return nullptr; + } + + // And find the first attribute with feature. + iterator = std::find_if(iterator, maAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { + return aAttrib->IsFeature(); + }); + + if (iterator == maAttribs.end()) + { + // Couldn't find the feature + return nullptr; + } + + // Found + return iterator->get(); +} + +void CharAttribList::DeleteEmptyAttribs() +{ + std::erase_if(maAttribs, [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsEmpty(); } ); + mbHasEmptyAttribs = false; +} + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG +void CharAttribList::DbgCheckAttribs(CharAttribList const& rAttribs) +{ + std::set<std::pair<sal_Int32, sal_uInt16>> zero_set; + for (const std::unique_ptr<EditCharAttrib>& rAttr : rAttribs.maAttribs) + { + assert(rAttr->GetStart() <= rAttr->GetEnd()); + assert(!rAttr->IsFeature() || rAttr->GetLen() == 1); + if (0 == rAttr->GetLen()) + { + // not sure if 0-length attributes allowed at all in non-empty para? + assert(zero_set.insert(std::make_pair(rAttr->GetStart(), rAttr->Which())).second && "duplicate 0-length attribute detected"); + } + } + CheckOrderedList(rAttribs.GetAttribs()); +} +#endif + +void CharAttribList::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("CharAttribList")); + for (auto const & i : maAttribs) { + i->dumpAsXml(pWriter); + } + (void)xmlTextWriterEndElement(pWriter); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/EditLine.cxx b/editeng/source/editeng/EditLine.cxx new file mode 100644 index 000000000000..b43cf0a84f11 --- /dev/null +++ b/editeng/source/editeng/EditLine.cxx @@ -0,0 +1,96 @@ +/* -*- 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 <EditLine.hxx> +#include <editdoc.hxx> +#include <algorithm> + +EditLine* EditLine::Clone() const +{ + EditLine* pLine = new EditLine; + pLine->maPositions = maPositions; + pLine->mnStartPosX = mnStartPosX; + pLine->mnNextLinePosXDiff = mnNextLinePosXDiff; + pLine->mnStart = mnStart; + pLine->mnEnd = mnEnd; + pLine->mnStartPortion = mnStartPortion; + pLine->mnEndPortion = mnEndPortion; + pLine->mnHeight = mnHeight; + pLine->mnTextWidth = mnTextWidth; + pLine->mnTextHeight = mnTextHeight; + pLine->mnMaxAscent = mnMaxAscent; + + return pLine; +} + +Size EditLine::CalcTextSize(ParaPortion& rParaPortion) +{ + Size aSize; + + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !"); + + for (sal_Int32 nPosition = mnStartPortion; nPosition <= mnEndPortion; nPosition++) + { + TextPortion& rPortion = rParaPortion.GetTextPortions()[nPosition]; + switch (rPortion.GetKind()) + { + case PortionKind::TEXT: + case PortionKind::FIELD: + case PortionKind::HYPHENATOR: + { + Size aTmpSize = rPortion.GetSize(); + aSize.AdjustWidth(aTmpSize.Width()); + if (aSize.Height() < aTmpSize.Height() ) + aSize.setHeight( aTmpSize.Height() ); + } + break; + case PortionKind::TAB: + { + aSize.AdjustWidth(rPortion.GetSize().Width()); + } + break; + case PortionKind::LINEBREAK: + break; + } + } + + SetHeight(sal_uInt16(aSize.Height())); + return aSize; +} + +void EditLine::SetHeight(sal_uInt16 nHeight, sal_uInt16 nTextHeight) +{ + mnHeight = nHeight; + + if (nTextHeight != 0) + mnTextHeight = nTextHeight; + else + mnTextHeight = nHeight; +} + +void EditLine::SetStartPosX(sal_Int32 nStart) +{ + if (nStart > 0) + mnStartPosX = nStart; + else + mnStartPosX = 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/TextPortionList.cxx b/editeng/source/editeng/TextPortionList.cxx new file mode 100644 index 000000000000..ca9d68159a5a --- /dev/null +++ b/editeng/source/editeng/TextPortionList.cxx @@ -0,0 +1,95 @@ +/* -*- 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 <TextPortionList.hxx> + +#include <EditLine.hxx> +#include <osl/diagnose.h> + + +void TextPortionList::DeleteFromPortion(sal_Int32 nDelFrom) +{ + assert((nDelFrom < static_cast<sal_Int32>(maPortions.size())) || ((nDelFrom == 0) && maPortions.empty())); + PortionsType::iterator it = maPortions.begin(); + std::advance(it, nDelFrom); + maPortions.erase(it, maPortions.end()); +} + +namespace { + +class FindTextPortionByAddress +{ + const TextPortion* mp; +public: + explicit FindTextPortionByAddress(const TextPortion* p) : mp(p) {} + bool operator() (const std::unique_ptr<TextPortion>& v) const + { + return v.get() == mp; + } +}; + +} + +sal_Int32 TextPortionList::GetPos(const TextPortion* p) const +{ + PortionsType::const_iterator it = + std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p)); + + if (it == maPortions.end()) + return std::numeric_limits<sal_Int32>::max(); // not found. + + return std::distance(maPortions.begin(), it); +} + +sal_Int32 TextPortionList::FindPortion( + sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion) const +{ + // When nCharPos at portion limit, the left portion is found + sal_Int32 nTmpPos = 0; + sal_Int32 n = maPortions.size(); + for (sal_Int32 i = 0; i < n; ++i) + { + const TextPortion& rPortion = *maPortions[i]; + nTmpPos = nTmpPos + rPortion.GetLen(); + if ( nTmpPos >= nCharPos ) + { + // take this one if we don't prefer the starting portion, or if it's the last one + if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) ) + { + nPortionStart = nTmpPos - rPortion.GetLen(); + return i; + } + } + } + OSL_FAIL( "FindPortion: Not found!" ); + return n - 1; +} + +sal_Int32 TextPortionList::GetStartPos(sal_Int32 nPortion) +{ + sal_Int32 nPos = 0; + for (sal_Int32 i = 0; i < nPortion; ++i) + { + const TextPortion& rPortion = *maPortions[i]; + nPos = nPos + rPortion.GetLen(); + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editattr.cxx b/editeng/source/editeng/editattr.cxx index 5d7da53de477..75bbcabc5a66 100644 --- a/editeng/source/editeng/editattr.cxx +++ b/editeng/source/editeng/editattr.cxx @@ -20,6 +20,7 @@ #include <vcl/outdev.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <libxml/xmlwriter.h> #include <editeng/svxfont.hxx> #include <editeng/flditem.hxx> @@ -45,14 +46,15 @@ #include <editattr.hxx> - -EditCharAttrib::EditCharAttrib( const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) : - nStart(nS), nEnd(nE), bFeature(false), bEdge(false) +EditCharAttrib::EditCharAttrib(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nS, sal_Int32 nE ) +: maItemHolder(rPool, &rItem) +, nStart(nS) +, nEnd(nE) +, bFeature(false) +, bEdge(false) { - pItem = &rAttr; - - assert((rAttr.Which() >= EE_ITEMS_START) && (rAttr.Which() <= EE_ITEMS_END)); - assert((rAttr.Which() < EE_FEATURE_START) || (rAttr.Which() > EE_FEATURE_END) || (nE == (nS+1))); + assert((rItem.Which() >= EE_ITEMS_START) && (rItem.Which() <= EE_ITEMS_END)); + assert((rItem.Which() < EE_FEATURE_START) || (rItem.Which() > EE_FEATURE_END) || (nE == (nS+1))); } EditCharAttrib::~EditCharAttrib() @@ -70,16 +72,16 @@ void EditCharAttrib::dumpAsXml(xmlTextWriterPtr pWriter) const pWriter, BAD_CAST("nStart"), "%" SAL_PRIdINT32, nStart); (void)xmlTextWriterWriteFormatAttribute( pWriter, BAD_CAST("nEnd"), "%" SAL_PRIdINT32, nEnd); - pItem->dumpAsXml(pWriter); + GetItem()->dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } -EditCharAttribFont::EditCharAttribFont( const SvxFontItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribFont::EditCharAttribFont(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_FONTINFO || rAttr.Which() == EE_CHAR_FONTINFO_CJK || rAttr.Which() == EE_CHAR_FONTINFO_CTL); + assert(rItem.Which() == EE_CHAR_FONTINFO || rItem.Which() == EE_CHAR_FONTINFO_CJK || rItem.Which() == EE_CHAR_FONTINFO_CTL); } void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* ) @@ -94,10 +96,10 @@ void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribItalic::EditCharAttribItalic( const SvxPostureItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribItalic::EditCharAttribItalic(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_ITALIC || rAttr.Which() == EE_CHAR_ITALIC_CJK || rAttr.Which() == EE_CHAR_ITALIC_CTL); + assert(rItem.Which() == EE_CHAR_ITALIC || rItem.Which() == EE_CHAR_ITALIC_CJK || rItem.Which() == EE_CHAR_ITALIC_CTL); } void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* ) @@ -107,10 +109,10 @@ void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribWeight::EditCharAttribWeight( const SvxWeightItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribWeight::EditCharAttribWeight(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_WEIGHT || rAttr.Which() == EE_CHAR_WEIGHT_CJK || rAttr.Which() == EE_CHAR_WEIGHT_CTL); + assert(rItem.Which() == EE_CHAR_WEIGHT || rItem.Which() == EE_CHAR_WEIGHT_CJK || rItem.Which() == EE_CHAR_WEIGHT_CTL); } void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* ) @@ -120,10 +122,10 @@ void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribUnderline::EditCharAttribUnderline( const SvxUnderlineItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribUnderline::EditCharAttribUnderline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_UNDERLINE); + assert(rItem.Which() == EE_CHAR_UNDERLINE); } void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) @@ -137,10 +139,10 @@ void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) -EditCharAttribOverline::EditCharAttribOverline( const SvxOverlineItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribOverline::EditCharAttribOverline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_OVERLINE); + assert(rItem.Which() == EE_CHAR_OVERLINE); } void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) @@ -152,10 +154,10 @@ void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) -EditCharAttribFontHeight::EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribFontHeight::EditCharAttribFontHeight(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_FONTHEIGHT || rAttr.Which() == EE_CHAR_FONTHEIGHT_CJK || rAttr.Which() == EE_CHAR_FONTHEIGHT_CTL); + assert(rItem.Which() == EE_CHAR_FONTHEIGHT || rItem.Which() == EE_CHAR_FONTHEIGHT_CJK || rItem.Which() == EE_CHAR_FONTHEIGHT_CTL); } void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* ) @@ -166,10 +168,10 @@ void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribFontWidth::EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribFontWidth::EditCharAttribFontWidth(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_FONTWIDTH); + assert(rItem.Which() == EE_CHAR_FONTWIDTH); } void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* ) @@ -179,10 +181,10 @@ void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* ) -EditCharAttribStrikeout::EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribStrikeout::EditCharAttribStrikeout(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_STRIKEOUT); + assert(rItem.Which() == EE_CHAR_STRIKEOUT); } void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* ) @@ -192,10 +194,10 @@ void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribCaseMap::EditCharAttribCaseMap( const SvxCaseMapItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribCaseMap::EditCharAttribCaseMap(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_CASEMAP); + assert(rItem.Which() == EE_CHAR_CASEMAP); } void EditCharAttribCaseMap::SetFont( SvxFont& rFont, OutputDevice* ) @@ -205,10 +207,10 @@ void EditCharAttribCaseMap::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribColor::EditCharAttribColor( const SvxColorItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribColor::EditCharAttribColor(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_COLOR); + assert(rItem.Which() == EE_CHAR_COLOR); } void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* ) @@ -218,26 +220,23 @@ void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* ) } -EditCharAttribBackgroundColor::EditCharAttribBackgroundColor( - const SvxColorItem& rAttr, - sal_Int32 _nStart, - sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribBackgroundColor::EditCharAttribBackgroundColor(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_BKGCOLOR); + assert(rItem.Which() == EE_CHAR_BKGCOLOR); } void EditCharAttribBackgroundColor::SetFont( SvxFont& rFont, OutputDevice* ) { Color aColor = static_cast<const SvxColorItem*>(GetItem())->GetValue(); - rFont.SetTransparent(false); + rFont.SetTransparent(aColor.IsTransparent()); rFont.SetFillColor(aColor); } -EditCharAttribLanguage::EditCharAttribLanguage( const SvxLanguageItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribLanguage::EditCharAttribLanguage(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert((rAttr.Which() == EE_CHAR_LANGUAGE) || (rAttr.Which() == EE_CHAR_LANGUAGE_CJK) || (rAttr.Which() == EE_CHAR_LANGUAGE_CTL)); + assert((rItem.Which() == EE_CHAR_LANGUAGE) || (rItem.Which() == EE_CHAR_LANGUAGE_CJK) || (rItem.Which() == EE_CHAR_LANGUAGE_CTL)); } void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* ) @@ -247,10 +246,10 @@ void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribShadow::EditCharAttribShadow( const SvxShadowedItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribShadow::EditCharAttribShadow(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_SHADOW); + assert(rItem.Which() == EE_CHAR_SHADOW); } void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* ) @@ -260,10 +259,10 @@ void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribEscapement::EditCharAttribEscapement( const SvxEscapementItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribEscapement::EditCharAttribEscapement(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_ESCAPEMENT); + assert(rItem.Which() == EE_CHAR_ESCAPEMENT); } void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) @@ -277,10 +276,10 @@ void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) -EditCharAttribOutline::EditCharAttribOutline( const SvxContourItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribOutline::EditCharAttribOutline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_OUTLINE); + assert(rItem.Which() == EE_CHAR_OUTLINE); } void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* ) @@ -290,8 +289,8 @@ void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribTab::EditCharAttribTab( const SfxVoidItem& rAttr, sal_Int32 nPos ) - : EditCharAttrib( rAttr, nPos, nPos+1 ) +EditCharAttribTab::EditCharAttribTab(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos) +: EditCharAttrib(rPool, rItem, nPos, nPos+1) { SetFeature( true ); } @@ -302,8 +301,8 @@ void EditCharAttribTab::SetFont( SvxFont&, OutputDevice* ) -EditCharAttribLineBreak::EditCharAttribLineBreak( const SfxVoidItem& rAttr, sal_Int32 nPos ) - : EditCharAttrib( rAttr, nPos, nPos+1 ) +EditCharAttribLineBreak::EditCharAttribLineBreak(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos) +: EditCharAttrib(rPool, rItem, nPos, nPos+1) { SetFeature( true ); } @@ -314,8 +313,8 @@ void EditCharAttribLineBreak::SetFont( SvxFont&, OutputDevice* ) -EditCharAttribField::EditCharAttribField( const SvxFieldItem& rAttr, sal_Int32 nPos ) - : EditCharAttrib( rAttr, nPos, nPos+1 ) +EditCharAttribField::EditCharAttribField(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos) +: EditCharAttrib(rPool, rItem, nPos, nPos+1) { SetFeature( true ); // !!! } @@ -329,6 +328,8 @@ void EditCharAttribField::SetFont( SvxFont& rFont, OutputDevice* ) } if ( mxTxtColor ) rFont.SetColor( *mxTxtColor ); + if ( mxFldLineStyle ) + rFont.SetUnderline( *mxFldLineStyle ); } @@ -342,15 +343,17 @@ void EditCharAttribField::Reset() aFieldValue.clear(); mxTxtColor.reset(); mxFldColor.reset(); + mxFldLineStyle.reset(); } -EditCharAttribField::EditCharAttribField( const EditCharAttribField& rAttr ) - : EditCharAttrib( *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd() ), - aFieldValue( rAttr.aFieldValue ) +EditCharAttribField::EditCharAttribField(const EditCharAttribField& rAttr) +: EditCharAttrib(rAttr.GetHolder().getPool(), *rAttr.GetHolder().getItem(), rAttr.GetStart(), rAttr.GetEnd()) +, aFieldValue( rAttr.aFieldValue ) { // Use this constructor only for temporary Objects, Item is not pooled. mxTxtColor = rAttr.mxTxtColor; mxFldColor = rAttr.mxFldColor; + mxFldLineStyle = rAttr.mxFldLineStyle; } EditCharAttribField::~EditCharAttribField() @@ -373,15 +376,20 @@ bool EditCharAttribField::operator == ( const EditCharAttribField& rAttr ) const if ( ( mxFldColor && rAttr.mxFldColor ) && ( *mxFldColor != *rAttr.mxFldColor ) ) return false; + if ( ( mxFldLineStyle && !rAttr.mxFldLineStyle ) || ( !mxFldLineStyle && rAttr.mxFldLineStyle ) ) + return false; + if ( ( mxFldLineStyle && rAttr.mxFldLineStyle ) && ( *mxFldLineStyle != *rAttr.mxFldLineStyle ) ) + return false; + return true; } -EditCharAttribPairKerning::EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) -: EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribPairKerning::EditCharAttribPairKerning(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_PAIRKERNING); + assert(rItem.Which() == EE_CHAR_PAIRKERNING); } void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* ) @@ -391,10 +399,10 @@ void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribKerning::EditCharAttribKerning( const SvxKerningItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) -: EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribKerning::EditCharAttribKerning(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_KERNING); + assert(rItem.Which() == EE_CHAR_KERNING); } void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* ) @@ -404,10 +412,10 @@ void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribWordLineMode::EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) -: EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribWordLineMode::EditCharAttribWordLineMode(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_WLM); + assert(rItem.Which() == EE_CHAR_WLM); } void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* ) @@ -417,10 +425,10 @@ void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribEmphasisMark::EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribEmphasisMark::EditCharAttribEmphasisMark(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_EMPHASISMARK); + assert(rItem.Which() == EE_CHAR_EMPHASISMARK); } void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* ) @@ -430,10 +438,10 @@ void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribRelief::EditCharAttribRelief( const SvxCharReliefItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribRelief::EditCharAttribRelief(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_RELIEF); + assert(rItem.Which() == EE_CHAR_RELIEF); } void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* ) @@ -442,10 +450,10 @@ void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* ) } -EditCharAttribGrabBag::EditCharAttribGrabBag( const SfxGrabBagItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribGrabBag::EditCharAttribGrabBag(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_GRABBAG); + assert(rItem.Which() == EE_CHAR_GRABBAG); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editdbg.cxx b/editeng/source/editeng/editdbg.cxx index d2a97cdb0efa..f94bc2c7ea14 100644 --- a/editeng/source/editeng/editdbg.cxx +++ b/editeng/source/editeng/editdbg.cxx @@ -58,241 +58,253 @@ #if defined( DBG_UTIL ) || ( OSL_DEBUG_LEVEL > 1 ) +namespace +{ +struct DebOutBuffer +{ + OStringBuffer str; + void append(std::string_view descr, const SfxEnumItemInterface& rItem) + { + str.append(descr + OString::number(rItem.GetEnumValue())); + } + void append(std::string_view descr, const SvxLRSpaceItem& rItem) + { + str.append(OString::Concat(descr) + "FI=" + OString::number(rItem.GetTextFirstLineOffset()) + + ", LI=" + OString::number(rItem.GetTextLeft()) + + ", RI=" + OString::number(rItem.GetRight())); + } + void append(std::string_view descr, const SvxNumBulletItem& rItem) + { + str.append(descr); + for (sal_uInt16 nLevel = 0; nLevel < 3; nLevel++) + { + str.append("Level" + OString::number(nLevel) + "="); + const SvxNumberFormat* pFmt = rItem.GetNumRule().Get(nLevel); + if (pFmt) + { + str.append("(" + OString::number(pFmt->GetFirstLineOffset()) + "," + + OString::number(pFmt->GetAbsLSpace()) + ","); + if (pFmt->GetNumberingType() == SVX_NUM_BITMAP) + str.append("Bitmap"); + else if (pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL) + str.append("Number"); + else + { + str.append("Char=[" + OString::number(pFmt->GetBulletChar()) + "]"); + } + str.append(") "); + } + } + } + void append(std::string_view descr, const SfxBoolItem& rItem) + { + str.append(descr + OString::number(static_cast<int>(rItem.GetValue()))); + } + void append(std::string_view descr, const SfxInt16Item& rItem) + { + str.append(descr + OString::number(rItem.GetValue())); + } + void append(std::string_view descr, const SfxUInt16Item& rItem) + { + str.append(descr + OString::number(rItem.GetValue())); + } + void append(const SvxULSpaceItem& rItem) + { + str.append("SB=" + OString::number(rItem.GetUpper()) + + ", SA=" + OString::number(rItem.GetLower())); + } + void append(std::string_view descr, const SvxLineSpacingItem& rItem) + { + str.append(descr); + if (rItem.GetLineSpaceRule() == SvxLineSpaceRule::Min) + { + str.append("Min: " + OString::number(rItem.GetInterLineSpace())); + } + else if (rItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop) + { + str.append("Prop: " + OString::number(rItem.GetPropLineSpace())); + } + else + str.append("Unsupported Type!"); + } + void append(const SvxTabStopItem& rTabs) + { + str.append("Tabs: " + OString::number(rTabs.Count())); + if (rTabs.Count()) + { + str.append("( "); + for (sal_uInt16 i = 0; i < rTabs.Count(); ++i) + { + const SvxTabStop& rTab = rTabs[i]; + str.append(OString::number(rTab.GetTabPos()) + " "); + } + str.append(')'); + } + } + void append(std::string_view descr, const SvxColorItem& rItem) + { + Color aColor(rItem.GetValue()); + str.append(descr + OString::number(aColor.GetRed()) + ", " + + OString::number(aColor.GetGreen()) + ", " + OString::number(aColor.GetBlue())); + } + void append(std::string_view descr, const SvxFontItem& rItem) + { + str.append(descr + OUStringToOString(rItem.GetFamilyName(), RTL_TEXTENCODING_ASCII_US) + + " (CharSet: " + OString::number(rItem.GetCharSet()) + ")"); + } + void append(std::string_view descr, const SvxEscapementItem& rItem) + { + str.append(descr + OString::number(rItem.GetEsc()) + ", " + + OString::number(rItem.GetProportionalHeight())); + } + void appendHeightAndPts(std::string_view descr, tools::Long h, MapUnit eUnit) + { + MapMode aItemMapMode(eUnit); + MapMode aPntMap(MapUnit::MapPoint); + Size aSz = OutputDevice::LogicToLogic(Size(0, h), aItemMapMode, aPntMap); + str.append(descr + OString::number(h) + " Points=" + OString::number(aSz.Height())); + } + void append(std::string_view descr, const SvxFontHeightItem& rItem, const SfxItemPool& rPool) + { + appendHeightAndPts(descr, rItem.GetHeight(), rPool.GetMetric(rItem.Which())); + } + void append(std::string_view descr, const SvxKerningItem& rItem, const SfxItemPool& rPool) + { + appendHeightAndPts(descr, rItem.GetValue(), rPool.GetMetric(rItem.Which())); + } +}; +} + static OString DbgOutItem(const SfxItemPool& rPool, const SfxPoolItem& rItem) { - OStringBuffer aDebStr; + DebOutBuffer buffer; switch ( rItem.Which() ) { case EE_PARA_WRITINGDIR: - aDebStr.append("WritingDir="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxFrameDirectionItem&>(rItem).GetValue())); + buffer.append("WritingDir=", rItem.StaticWhichCast(EE_PARA_WRITINGDIR)); break; case EE_PARA_OUTLLRSPACE: + buffer.append("Outline ", rItem.StaticWhichCast(EE_PARA_OUTLLRSPACE)); + break; case EE_PARA_LRSPACE: - aDebStr.append("FI="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLRSpaceItem&>(rItem).GetTextFirstLineOffset())); - aDebStr.append(", LI="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLRSpaceItem&>(rItem).GetTextLeft())); - aDebStr.append(", RI="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLRSpaceItem&>(rItem).GetRight())); + buffer.append("", rItem.StaticWhichCast(EE_PARA_LRSPACE)); break; case EE_PARA_NUMBULLET: - aDebStr.append("NumItem "); - for ( sal_uInt16 nLevel = 0; nLevel < 3; nLevel++ ) - { - aDebStr.append("Level"); - aDebStr.append(static_cast<sal_Int32>(nLevel)); - aDebStr.append('='); - const SvxNumberFormat* pFmt = static_cast<const SvxNumBulletItem&>(rItem).GetNumRule().Get( nLevel ); - if ( pFmt ) - { - aDebStr.append('('); - aDebStr.append(pFmt->GetFirstLineOffset()); - aDebStr.append(','); - aDebStr.append(pFmt->GetAbsLSpace()); - aDebStr.append(','); - if ( pFmt->GetNumberingType() == SVX_NUM_BITMAP ) - aDebStr.append("Bitmap"); - else if( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) - aDebStr.append("Number"); - else - { - aDebStr.append("Char=["); - aDebStr.append(static_cast<sal_Int32>(pFmt->GetBulletChar())); - aDebStr.append(']'); - } - aDebStr.append(") "); - } - } + buffer.append("NumItem ", rItem.StaticWhichCast(EE_PARA_NUMBULLET)); break; case EE_PARA_BULLETSTATE: - aDebStr.append("ShowBullet="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SfxBoolItem&>(rItem).GetValue())); + buffer.append("ShowBullet=", rItem.StaticWhichCast(EE_PARA_BULLETSTATE)); break; case EE_PARA_HYPHENATE: - aDebStr.append("Hyphenate="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SfxBoolItem&>(rItem).GetValue())); + buffer.append("Hyphenate=", rItem.StaticWhichCast(EE_PARA_HYPHENATE)); break; case EE_PARA_OUTLLEVEL: - aDebStr.append("Level="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SfxInt16Item&>(rItem).GetValue())); + buffer.append("Level=", rItem.StaticWhichCast(EE_PARA_OUTLLEVEL)); break; case EE_PARA_ULSPACE: - aDebStr.append("SB="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxULSpaceItem&>(rItem).GetUpper())); - aDebStr.append(", SA="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxULSpaceItem&>(rItem).GetLower())); + buffer.append(rItem.StaticWhichCast(EE_PARA_ULSPACE)); break; case EE_PARA_SBL: - aDebStr.append("SBL="); - if ( static_cast<const SvxLineSpacingItem&>(rItem).GetLineSpaceRule() == SvxLineSpaceRule::Min ) - { - aDebStr.append("Min: "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLineSpacingItem&>(rItem).GetInterLineSpace())); - } - else if ( static_cast<const SvxLineSpacingItem&>(rItem).GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop ) - { - aDebStr.append("Prop: "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLineSpacingItem&>(rItem).GetPropLineSpace())); - } - else - aDebStr.append("Unsupported Type!"); + buffer.append("SBL=", rItem.StaticWhichCast(EE_PARA_SBL)); break; case EE_PARA_JUST: - aDebStr.append("SvxAdust="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxAdjustItem&>(rItem).GetAdjust())); + buffer.append("SvxAdust=", rItem.StaticWhichCast(EE_PARA_JUST)); break; case EE_PARA_TABS: - { - aDebStr.append("Tabs: "); - const SvxTabStopItem& rTabs = static_cast<const SvxTabStopItem&>(rItem); - aDebStr.append(static_cast<sal_Int32>(rTabs.Count())); - if ( rTabs.Count() ) - { - aDebStr.append("( "); - for (sal_uInt16 i = 0; i < rTabs.Count(); ++i) - { - const SvxTabStop& rTab = rTabs[i]; - aDebStr.append(rTab.GetTabPos()); - aDebStr.append(' '); - } - aDebStr.append(')'); - } - } + buffer.append(rItem.StaticWhichCast(EE_PARA_TABS)); break; case EE_CHAR_LANGUAGE: + buffer.append("Language=", rItem.StaticWhichCast(EE_CHAR_LANGUAGE)); + break; case EE_CHAR_LANGUAGE_CJK: + buffer.append("LanguageCJK=", rItem.StaticWhichCast(EE_CHAR_LANGUAGE_CJK)); + break; case EE_CHAR_LANGUAGE_CTL: - aDebStr.append("Language="); - aDebStr.append(static_cast<sal_Int32>(static_cast<sal_uInt16>(static_cast<const SvxLanguageItem&>(rItem).GetLanguage()))); + buffer.append("LanguageCTL=", rItem.StaticWhichCast(EE_CHAR_LANGUAGE_CTL)); break; case EE_CHAR_COLOR: - { - aDebStr.append("Color= "); - Color aColor( static_cast<const SvxColorItem&>(rItem).GetValue() ); - aDebStr.append(static_cast<sal_Int32>(aColor.GetRed())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetGreen())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetBlue())); - } + buffer.append("Color= ", rItem.StaticWhichCast(EE_CHAR_COLOR)); break; case EE_CHAR_BKGCOLOR: - { - aDebStr.append("FillColor= "); - Color aColor( static_cast<const SvxColorItem&>(rItem).GetValue() ); - aDebStr.append(static_cast<sal_Int32>(aColor.GetRed())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetGreen())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetBlue())); - } + buffer.append("FillColor= ", rItem.StaticWhichCast(EE_CHAR_BKGCOLOR)); break; case EE_CHAR_FONTINFO: + buffer.append("Font=", rItem.StaticWhichCast(EE_CHAR_FONTINFO)); + break; case EE_CHAR_FONTINFO_CJK: + buffer.append("FontCJK=", rItem.StaticWhichCast(EE_CHAR_FONTINFO_CJK)); + break; case EE_CHAR_FONTINFO_CTL: - { - aDebStr.append("Font="); - aDebStr.append(OUStringToOString(static_cast<const SvxFontItem&>(rItem).GetFamilyName(), RTL_TEXTENCODING_ASCII_US)); - aDebStr.append(" (CharSet: "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxFontItem&>(rItem).GetCharSet())); - aDebStr.append(')'); - } + buffer.append("FontCTL=", rItem.StaticWhichCast(EE_CHAR_FONTINFO_CTL)); break; case EE_CHAR_FONTHEIGHT: + buffer.append("Size=", rItem.StaticWhichCast(EE_CHAR_FONTHEIGHT), rPool); + break; case EE_CHAR_FONTHEIGHT_CJK: + buffer.append("SizeCJK=", rItem.StaticWhichCast(EE_CHAR_FONTHEIGHT_CJK), rPool); + break; case EE_CHAR_FONTHEIGHT_CTL: - { - aDebStr.append("Groesse="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxFontHeightItem&>(rItem).GetHeight())); - Size aSz( 0, static_cast<const SvxFontHeightItem&>(rItem).GetHeight() ); - MapUnit eUnit = rPool.GetMetric( rItem.Which() ); - MapMode aItemMapMode(eUnit); - MapMode aPntMap( MapUnit::MapPoint ); - aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap ); - aDebStr.append(" Points="); - aDebStr.append(static_cast<sal_Int32>(aSz.Height())); - } + buffer.append("SizeCTL=", rItem.StaticWhichCast(EE_CHAR_FONTHEIGHT_CTL), rPool); break; case EE_CHAR_FONTWIDTH: - { - aDebStr.append("Breite="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxCharScaleWidthItem&>(rItem).GetValue())); - aDebStr.append('%'); - } + buffer.append("Width=", rItem.StaticWhichCast(EE_CHAR_FONTWIDTH)); break; case EE_CHAR_WEIGHT: + buffer.append("FontWeight=", rItem.StaticWhichCast(EE_CHAR_WEIGHT)); + break; case EE_CHAR_WEIGHT_CJK: + buffer.append("FontWeightCJK=", rItem.StaticWhichCast(EE_CHAR_WEIGHT_CJK)); + break; case EE_CHAR_WEIGHT_CTL: - aDebStr.append("FontWeight="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxWeightItem&>(rItem).GetWeight())); + buffer.append("FontWeightCTL=", rItem.StaticWhichCast(EE_CHAR_WEIGHT_CTL)); break; case EE_CHAR_UNDERLINE: - aDebStr.append("FontUnderline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxUnderlineItem&>(rItem).GetLineStyle())); + buffer.append("FontUnderline=", rItem.StaticWhichCast(EE_CHAR_UNDERLINE)); break; case EE_CHAR_OVERLINE: - aDebStr.append("FontOverline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxOverlineItem&>(rItem).GetLineStyle())); + buffer.append("FontOverline=", rItem.StaticWhichCast(EE_CHAR_OVERLINE)); break; case EE_CHAR_EMPHASISMARK: - aDebStr.append("FontUnderline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxEmphasisMarkItem&>(rItem).GetEmphasisMark())); + buffer.append("FontEmphasisMark=", rItem.StaticWhichCast(EE_CHAR_EMPHASISMARK)); break; case EE_CHAR_RELIEF: - aDebStr.append("FontRelief="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxCharReliefItem&>(rItem).GetValue())); + buffer.append("FontRelief=", rItem.StaticWhichCast(EE_CHAR_RELIEF)); break; case EE_CHAR_STRIKEOUT: - aDebStr.append("FontStrikeout="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxCrossedOutItem&>(rItem).GetStrikeout())); + buffer.append("FontStrikeout=", rItem.StaticWhichCast(EE_CHAR_STRIKEOUT)); break; case EE_CHAR_ITALIC: + buffer.append("FontPosture=", rItem.StaticWhichCast(EE_CHAR_ITALIC)); + break; case EE_CHAR_ITALIC_CJK: + buffer.append("FontPostureCJK=", rItem.StaticWhichCast(EE_CHAR_ITALIC_CJK)); + break; case EE_CHAR_ITALIC_CTL: - aDebStr.append("FontPosture="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxPostureItem&>(rItem).GetPosture())); + buffer.append("FontPostureCTL=", rItem.StaticWhichCast(EE_CHAR_ITALIC_CTL)); break; case EE_CHAR_OUTLINE: - aDebStr.append("FontOutline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxContourItem&>(rItem).GetValue())); + buffer.append("FontOutline=", rItem.StaticWhichCast(EE_CHAR_OUTLINE)); break; case EE_CHAR_SHADOW: - aDebStr.append("FontShadowed="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxShadowedItem&>(rItem).GetValue())); + buffer.append("FontShadowed=", rItem.StaticWhichCast(EE_CHAR_SHADOW)); break; case EE_CHAR_ESCAPEMENT: - aDebStr.append("Escape="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxEscapementItem&>(rItem).GetEsc())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxEscapementItem&>(rItem).GetProportionalHeight())); + buffer.append("Escape=", rItem.StaticWhichCast(EE_CHAR_ESCAPEMENT)); break; case EE_CHAR_PAIRKERNING: - aDebStr.append("PairKerning="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxAutoKernItem&>(rItem).GetValue())); + buffer.append("PairKerning=", rItem.StaticWhichCast(EE_CHAR_PAIRKERNING)); break; case EE_CHAR_KERNING: - { - aDebStr.append("Kerning="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxKerningItem&>(rItem).GetValue())); - Size aSz( 0, static_cast<short>(static_cast<const SvxKerningItem&>(rItem).GetValue()) ); - MapUnit eUnit = rPool.GetMetric( rItem.Which() ); - MapMode aItemMapMode(eUnit); - MapMode aPntMap( MapUnit::MapPoint ); - aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap ); - aDebStr.append(" Points="); - aDebStr.append(static_cast<sal_Int32>(aSz.Height())); - } + buffer.append("Kerning=", rItem.StaticWhichCast(EE_CHAR_KERNING), rPool); break; case EE_CHAR_WLM: - aDebStr.append("WordLineMode="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxWordLineModeItem&>(rItem).GetValue())); + buffer.append("WordLineMode=", rItem.StaticWhichCast(EE_CHAR_WLM)); break; case EE_CHAR_XMLATTRIBS: - aDebStr.append("XMLAttribs=..."); + buffer.str.append("XMLAttribs=..."); break; } - return aDebStr.makeStringAndClear(); + return buffer.str.makeStringAndClear(); } static void DbgOutItemSet(FILE* fp, const SfxItemSet& rSet, bool bSearchInParent, bool bShowALL) @@ -302,7 +314,7 @@ static void DbgOutItemSet(FILE* fp, const SfxItemSet& rSet, bool bSearchInParent fprintf( fp, "\nWhich: %i\t", nWhich ); if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::DEFAULT ) fprintf( fp, "ITEM_OFF " ); - else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::DONTCARE ) + else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::INVALID ) fprintf( fp, "ITEM_DC " ); else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::SET ) fprintf( fp, "ITEM_ON *" ); @@ -333,9 +345,9 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "================================================================================" ); fprintf( fp, "\n================== Document ================================================" ); fprintf( fp, "\n================================================================================" ); - for ( sal_Int32 nPortion = 0; nPortion < pEE->pImpEditEngine->GetParaPortions().Count(); nPortion++) + for ( sal_Int32 nPortion = 0; nPortion < pEE->getImpl().GetParaPortions().Count(); nPortion++) { - ParaPortion& rPPortion = pEE->pImpEditEngine->GetParaPortions()[nPortion]; + ParaPortion const& rPPortion = pEE->getImpl().GetParaPortions().getRef(nPortion); fprintf( fp, "\nParagraph %" SAL_PRIdINT32 ": Length = %" SAL_PRIdINT32 ", Invalid = %i\nText = '%s'", nPortion, rPPortion.GetNode()->Len(), rPPortion.IsInvalid(), OUStringToOString(rPPortion.GetNode()->GetString(), RTL_TEXTENCODING_UTF8).getStr() ); @@ -351,15 +363,15 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) for ( sal_Int32 z = 0; z < rPPortion.GetNode()->GetCharAttribs().Count(); ++z ) { const std::unique_ptr<EditCharAttrib>& rAttr = rPPortion.GetNode()->GetCharAttribs().GetAttribs()[z]; - OStringBuffer aCharAttribs; - aCharAttribs.append("\nA"); - aCharAttribs.append(nPortion); - aCharAttribs.append(": "); - aCharAttribs.append(static_cast<sal_Int32>(rAttr->GetItem()->Which())); - aCharAttribs.append('\t'); - aCharAttribs.append(rAttr->GetStart()); - aCharAttribs.append('\t'); - aCharAttribs.append(rAttr->GetEnd()); + OString aCharAttribs = + "\nA" + + OString::number(nPortion) + + ": " + + OString::number(rAttr->GetItem()->Which()) + + "\t" + + OString::number(rAttr->GetStart()) + + "\t" + + OString::number(rAttr->GetEnd()); if ( rAttr->IsEmpty() ) bZeroAttr = true; fprintf(fp, "%s => ", aCharAttribs.getStr()); @@ -371,34 +383,33 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "\nNULL-Attribute!" ); const sal_Int32 nTextPortions = rPPortion.GetTextPortions().Count(); - OStringBuffer aPortionStr("\nText portions: #"); - aPortionStr.append(nTextPortions); - aPortionStr.append(" \nA"); - aPortionStr.append(nPortion); - aPortionStr.append(": Paragraph Length = "); - aPortionStr.append(rPPortion.GetNode()->Len()); - aPortionStr.append("\nA"); - aPortionStr.append(nPortion); - aPortionStr.append(": "); + OStringBuffer aPortionStr("\nText portions: #" + + OString::number(nTextPortions) + + " \nA" + + OString::number(nPortion) + + ": Paragraph Length = " + + OString::number(rPPortion.GetNode()->Len()) + + "\nA" + + OString::number(nPortion) + + ": "); sal_Int32 n = 0; for ( sal_Int32 z = 0; z < nTextPortions; ++z ) { - TextPortion& rPortion = rPPortion.GetTextPortions()[z]; - aPortionStr.append(' '); - aPortionStr.append(rPortion.GetLen()); - aPortionStr.append('('); - aPortionStr.append(static_cast<sal_Int32>(rPortion.GetSize().Width())); - aPortionStr.append(')'); - aPortionStr.append('['); - aPortionStr.append(static_cast<sal_Int32>(rPortion.GetKind())); - aPortionStr.append(']'); - aPortionStr.append(';'); + TextPortion const& rPortion = rPPortion.GetTextPortions()[z]; + aPortionStr.append(" " + + OString::number(rPortion.GetLen()) + + "(" + + OString::number(rPortion.GetSize().Width()) + + ")" + "[" + + OString::number(static_cast<sal_Int32>(rPortion.GetKind())) + + "];"); n += rPortion.GetLen(); } - aPortionStr.append("\nA"); - aPortionStr.append(nPortion); - aPortionStr.append(": Total length: "); - aPortionStr.append(n); + aPortionStr.append("\nA" + + OString::number(nPortion) + + ": Total length: " + + OString::number(n)); if ( rPPortion.GetNode()->Len() != n ) aPortionStr.append(" => Error !!!"); fprintf(fp, "%s", aPortionStr.getStr()); @@ -407,7 +418,7 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) // First the content ... for ( sal_Int32 nLine = 0; nLine < rPPortion.GetLines().Count(); nLine++ ) { - EditLine& rLine = rPPortion.GetLines()[nLine]; + EditLine const& rLine = rPPortion.GetLines()[nLine]; OString aLine(OUStringToOString(rPPortion.GetNode()->Copy(rLine.GetStart(), rLine.GetEnd() - rLine.GetStart()), RTL_TEXTENCODING_ASCII_US)); fprintf( fp, "\nLine %" SAL_PRIdINT32 "\t>%s<", nLine, aLine.getStr() ); @@ -415,7 +426,7 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) // then the internal data ... for ( sal_Int32 nLine = 0; nLine < rPPortion.GetLines().Count(); nLine++ ) { - EditLine& rLine = rPPortion.GetLines()[nLine]; + EditLine const& rLine = rPPortion.GetLines()[nLine]; fprintf( fp, "\nLine %" SAL_PRIdINT32 ":\tStart: %" SAL_PRIdINT32 ",\tEnd: %" SAL_PRIdINT32, nLine, rLine.GetStart(), rLine.GetEnd() ); fprintf( fp, "\t\tPortions: %" SAL_PRIdINT32 " - %" SAL_PRIdINT32 ".\tHight: %i, Ascent=%i", rLine.GetStartPortion(), rLine.GetEndPortion(), rLine.GetHeight(), rLine.GetMaxAscent() ); } @@ -423,9 +434,9 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "\n-----------------------------------------------------------------------------" ); } - if ( pEE->pImpEditEngine->GetStyleSheetPool() ) + if (pEE->getImpl().GetStyleSheetPool()) { - SfxStyleSheetIterator aIter( pEE->pImpEditEngine->GetStyleSheetPool(), SfxStyleFamily::All ); + SfxStyleSheetIterator aIter(pEE->getImpl().GetStyleSheetPool(), SfxStyleFamily::All); sal_uInt16 nStyles = aIter.Count(); fprintf( fp, "\n\n================================================================================" ); fprintf( fp, "\n================== Stylesheets =============================================" ); @@ -447,17 +458,17 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "\n\n================================================================================" ); fprintf( fp, "\n================== Defaults ================================================" ); fprintf( fp, "\n================================================================================" ); - DbgOutItemSet( fp, pEE->pImpEditEngine->GetEmptyItemSet(), true, true ); + DbgOutItemSet(fp, pEE->getImpl().GetEmptyItemSet(), true, true); fprintf( fp, "\n\n================================================================================" ); fprintf( fp, "\n================== EditEngine & Views ======================================" ); fprintf( fp, "\n================================================================================" ); fprintf( fp, "\nControl: %x", unsigned( pEE->GetControlWord() ) ); - fprintf( fp, "\nRefMapMode: %i", int( pEE->pImpEditEngine->pRefDev->GetMapMode().GetMapUnit() ) ); + fprintf( fp, "\nRefMapMode: %i", int( pEE->getImpl().mpRefDev->GetMapMode().GetMapUnit())); fprintf( fp, "\nPaperSize: %" SAL_PRIdINT64 " x %" SAL_PRIdINT64, sal_Int64(pEE->GetPaperSize().Width()), sal_Int64(pEE->GetPaperSize().Height()) ); fprintf( fp, "\nMaxAutoPaperSize: %" SAL_PRIdINT64 " x %" SAL_PRIdINT64, sal_Int64(pEE->GetMaxAutoPaperSize().Width()), sal_Int64(pEE->GetMaxAutoPaperSize().Height()) ); fprintf( fp, "\nMinAutoPaperSize: %" SAL_PRIdINT64 " x %" SAL_PRIdINT64 , sal_Int64(pEE->GetMinAutoPaperSize().Width()), sal_Int64(pEE->GetMinAutoPaperSize().Height()) ); - fprintf( fp, "\nUpdate: %i", pEE->GetUpdateMode() ); + fprintf( fp, "\nCalculateLayout: %i", pEE->IsUpdateLayout() ); fprintf( fp, "\nNumber of Views: %" SAL_PRI_SIZET "i", pEE->GetViewCount() ); for ( size_t nView = 0; nView < pEE->GetViewCount(); nView++ ) { @@ -496,11 +507,12 @@ bool ParaPortion::DbgCheckTextPortions(ParaPortion const& rPara) { // check, if Portion length ok: sal_uInt16 nXLen = 0; - for (sal_Int32 nPortion = 0; nPortion < rPara.aTextPortionList.Count(); nPortion++) + + for (sal_Int32 nPortion = 0; nPortion < rPara.maTextPortionList.Count(); nPortion++) { - nXLen = nXLen + rPara.aTextPortionList[nPortion].GetLen(); + nXLen = nXLen + rPara.maTextPortionList[nPortion].GetLen(); } - return nXLen == rPara.pNode->Len(); + return nXLen == rPara.mpNode->Len(); } #endif diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx index 2a7f43032245..e482eea38652 100644 --- a/editeng/source/editeng/editdoc.cxx +++ b/editeng/source/editeng/editdoc.cxx @@ -50,19 +50,23 @@ #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <tools/debug.hxx> #include <com/sun/star/i18n/ScriptType.hpp> #include <libxml/xmlwriter.h> #include <algorithm> #include <cassert> +#include <cstddef> #include <limits> #include <memory> #include <set> #include <string_view> +#include <utility> using namespace ::com::sun::star; @@ -153,455 +157,230 @@ bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType ) return bValid; } -const SfxItemInfo aItemInfos[EDITITEMCOUNT] = { - { SID_ATTR_FRAMEDIRECTION, true }, // EE_PARA_WRITINGDIR - { 0, true }, // EE_PARA_XMLATTRIBS - { SID_ATTR_PARA_HANGPUNCTUATION, true }, // EE_PARA_HANGINGPUNCTUATION - { SID_ATTR_PARA_FORBIDDEN_RULES, true }, // EE_PARA_FORBIDDENRULES - { SID_ATTR_PARA_SCRIPTSPACE, true }, // EE_PARA_ASIANCJKSPACING - { SID_ATTR_NUMBERING_RULE, true }, // EE_PARA_NUMBULL - { 0, true }, // EE_PARA_HYPHENATE - { 0, true }, // EE_PARA_HYPHENATE_NO_CAPS - { 0, true }, // EE_PARA_BULLETSTATE - { 0, true }, // EE_PARA_OUTLLRSPACE - { SID_ATTR_PARA_OUTLLEVEL, true }, // EE_PARA_OUTLLEVEL - { SID_ATTR_PARA_BULLET, true }, // EE_PARA_BULLET - { SID_ATTR_LRSPACE, true }, // EE_PARA_LRSPACE - { SID_ATTR_ULSPACE, true }, // EE_PARA_ULSPACE - { SID_ATTR_PARA_LINESPACE, true }, // EE_PARA_SBL - { SID_ATTR_PARA_ADJUST, true }, // EE_PARA_JUST - { SID_ATTR_TABSTOP, true }, // EE_PARA_TABS - { SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, true }, // EE_PARA_JUST_METHOD - { SID_ATTR_ALIGN_VER_JUSTIFY, true }, // EE_PARA_VER_JUST - { SID_ATTR_CHAR_COLOR, true }, // EE_CHAR_COLOR - { SID_ATTR_CHAR_FONT, true }, // EE_CHAR_FONTINFO - { SID_ATTR_CHAR_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT - { SID_ATTR_CHAR_SCALEWIDTH, true }, // EE_CHAR_FONTWIDTH - { SID_ATTR_CHAR_WEIGHT, true }, // EE_CHAR_WEIGHT - { SID_ATTR_CHAR_UNDERLINE, true }, // EE_CHAR_UNDERLINE - { SID_ATTR_CHAR_STRIKEOUT, true }, // EE_CHAR_STRIKEOUT - { SID_ATTR_CHAR_POSTURE, true }, // EE_CHAR_ITALIC - { SID_ATTR_CHAR_CONTOUR, true }, // EE_CHAR_OUTLINE - { SID_ATTR_CHAR_SHADOWED, true }, // EE_CHAR_SHADOW - { SID_ATTR_CHAR_ESCAPEMENT, true }, // EE_CHAR_ESCAPEMENT - { SID_ATTR_CHAR_AUTOKERN, true }, // EE_CHAR_PAIRKERNING - { SID_ATTR_CHAR_KERNING, true }, // EE_CHAR_KERNING - { SID_ATTR_CHAR_WORDLINEMODE, true }, // EE_CHAR_WLM - { SID_ATTR_CHAR_LANGUAGE, true }, // EE_CHAR_LANGUAGE - { SID_ATTR_CHAR_CJK_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CJK - { SID_ATTR_CHAR_CTL_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CTL - { SID_ATTR_CHAR_CJK_FONT, true }, // EE_CHAR_FONTINFO_CJK - { SID_ATTR_CHAR_CTL_FONT, true }, // EE_CHAR_FONTINFO_CTL - { SID_ATTR_CHAR_CJK_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CJK - { SID_ATTR_CHAR_CTL_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CTL - { SID_ATTR_CHAR_CJK_WEIGHT, true }, // EE_CHAR_WEIGHT_CJK - { SID_ATTR_CHAR_CTL_WEIGHT, true }, // EE_CHAR_WEIGHT_CTL - { SID_ATTR_CHAR_CJK_POSTURE, true }, // EE_CHAR_ITALIC_CJK - { SID_ATTR_CHAR_CTL_POSTURE, true }, // EE_CHAR_ITALIC_CTL - { SID_ATTR_CHAR_EMPHASISMARK, true }, // EE_CHAR_EMPHASISMARK - { SID_ATTR_CHAR_RELIEF, true }, // EE_CHAR_RELIEF - { 0, true }, // EE_CHAR_RUBI_DUMMY - { 0, true }, // EE_CHAR_XMLATTRIBS - { SID_ATTR_CHAR_OVERLINE, true }, // EE_CHAR_OVERLINE - { SID_ATTR_CHAR_CASEMAP, true }, // EE_CHAR_CASEMAP - { SID_ATTR_CHAR_GRABBAG, true }, // EE_CHAR_GRABBAG - { SID_ATTR_CHAR_BACK_COLOR, true }, // EE_CHAR_BKGCOLOR - { 0, true }, // EE_FEATURE_TAB - { 0, true }, // EE_FEATURE_LINEBR - { SID_ATTR_CHAR_CHARSETCOLOR, true }, // EE_FEATURE_NOTCONV - { SID_FIELD, false }, // EE_FEATURE_FIELD -}; - EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) { // Create a new attribute in the pool - const SfxPoolItem& rNew = rPool.Put( rAttr ); - - EditCharAttrib* pNew = nullptr; - switch( rNew.Which() ) + switch( rAttr.Which() ) { case EE_CHAR_LANGUAGE: case EE_CHAR_LANGUAGE_CJK: case EE_CHAR_LANGUAGE_CTL: { - pNew = new EditCharAttribLanguage( static_cast<const SvxLanguageItem&>(rNew), nS, nE ); + return new EditCharAttribLanguage(rPool, rAttr, nS, nE); } break; case EE_CHAR_COLOR: { - pNew = new EditCharAttribColor( static_cast<const SvxColorItem&>(rNew), nS, nE ); + return new EditCharAttribColor(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTINFO: case EE_CHAR_FONTINFO_CJK: case EE_CHAR_FONTINFO_CTL: { - pNew = new EditCharAttribFont( static_cast<const SvxFontItem&>(rNew), nS, nE ); + return new EditCharAttribFont(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTHEIGHT: case EE_CHAR_FONTHEIGHT_CJK: case EE_CHAR_FONTHEIGHT_CTL: { - pNew = new EditCharAttribFontHeight( static_cast<const SvxFontHeightItem&>(rNew), nS, nE ); + return new EditCharAttribFontHeight(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTWIDTH: { - pNew = new EditCharAttribFontWidth( static_cast<const SvxCharScaleWidthItem&>(rNew), nS, nE ); + return new EditCharAttribFontWidth(rPool, rAttr, nS, nE ); } break; case EE_CHAR_WEIGHT: case EE_CHAR_WEIGHT_CJK: case EE_CHAR_WEIGHT_CTL: { - pNew = new EditCharAttribWeight( static_cast<const SvxWeightItem&>(rNew), nS, nE ); + return new EditCharAttribWeight(rPool, rAttr, nS, nE ); } break; case EE_CHAR_UNDERLINE: { - pNew = new EditCharAttribUnderline( static_cast<const SvxUnderlineItem&>(rNew), nS, nE ); + return new EditCharAttribUnderline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_OVERLINE: { - pNew = new EditCharAttribOverline( static_cast<const SvxOverlineItem&>(rNew), nS, nE ); + return new EditCharAttribOverline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_EMPHASISMARK: { - pNew = new EditCharAttribEmphasisMark( static_cast<const SvxEmphasisMarkItem&>(rNew), nS, nE ); + return new EditCharAttribEmphasisMark(rPool, rAttr, nS, nE ); } break; case EE_CHAR_RELIEF: { - pNew = new EditCharAttribRelief( static_cast<const SvxCharReliefItem&>(rNew), nS, nE ); + return new EditCharAttribRelief(rPool, rAttr, nS, nE ); } break; case EE_CHAR_STRIKEOUT: { - pNew = new EditCharAttribStrikeout( static_cast<const SvxCrossedOutItem&>(rNew), nS, nE ); + return new EditCharAttribStrikeout(rPool, rAttr, nS, nE ); } break; case EE_CHAR_ITALIC: case EE_CHAR_ITALIC_CJK: case EE_CHAR_ITALIC_CTL: { - pNew = new EditCharAttribItalic( static_cast<const SvxPostureItem&>(rNew), nS, nE ); + return new EditCharAttribItalic(rPool, rAttr, nS, nE ); } break; case EE_CHAR_OUTLINE: { - pNew = new EditCharAttribOutline( static_cast<const SvxContourItem&>(rNew), nS, nE ); + return new EditCharAttribOutline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_SHADOW: { - pNew = new EditCharAttribShadow( static_cast<const SvxShadowedItem&>(rNew), nS, nE ); + return new EditCharAttribShadow(rPool, rAttr, nS, nE ); } break; case EE_CHAR_ESCAPEMENT: { - pNew = new EditCharAttribEscapement( static_cast<const SvxEscapementItem&>(rNew), nS, nE ); + return new EditCharAttribEscapement(rPool, rAttr, nS, nE ); } break; case EE_CHAR_PAIRKERNING: { - pNew = new EditCharAttribPairKerning( static_cast<const SvxAutoKernItem&>(rNew), nS, nE ); + return new EditCharAttribPairKerning(rPool, rAttr, nS, nE ); } break; case EE_CHAR_KERNING: { - pNew = new EditCharAttribKerning( static_cast<const SvxKerningItem&>(rNew), nS, nE ); + return new EditCharAttribKerning(rPool, rAttr, nS, nE ); } break; case EE_CHAR_WLM: { - pNew = new EditCharAttribWordLineMode( static_cast<const SvxWordLineModeItem&>(rNew), nS, nE ); + return new EditCharAttribWordLineMode(rPool, rAttr, nS, nE ); } break; case EE_CHAR_XMLATTRIBS: { - pNew = new EditCharAttrib( rNew, nS, nE ); // Attribute is only for holding XML information... + return new EditCharAttrib(rPool, rAttr, nS, nE); // Attribute is only for holding XML information... } break; case EE_CHAR_CASEMAP: { - pNew = new EditCharAttribCaseMap( static_cast<const SvxCaseMapItem&>(rNew), nS, nE ); + return new EditCharAttribCaseMap(rPool, rAttr, nS, nE ); } break; case EE_CHAR_GRABBAG: { - pNew = new EditCharAttribGrabBag( static_cast<const SfxGrabBagItem&>(rNew), nS, nE ); + return new EditCharAttribGrabBag(rPool, rAttr, nS, nE ); } break; case EE_FEATURE_TAB: { - pNew = new EditCharAttribTab( static_cast<const SfxVoidItem&>(rNew), nS ); + return new EditCharAttribTab(rPool, rAttr, nS ); } break; case EE_FEATURE_LINEBR: { - pNew = new EditCharAttribLineBreak( static_cast<const SfxVoidItem&>(rNew), nS ); + return new EditCharAttribLineBreak(rPool, rAttr, nS ); } break; case EE_FEATURE_FIELD: { - pNew = new EditCharAttribField( static_cast<const SvxFieldItem&>(rNew), nS ); + return new EditCharAttribField(rPool, rAttr, nS ); } break; case EE_CHAR_BKGCOLOR: { - pNew = new EditCharAttribBackgroundColor( static_cast<const SvxColorItem&>(rNew), nS, nE ); + return new EditCharAttribBackgroundColor(rPool, rAttr, nS, nE ); } break; default: - { - OSL_FAIL( "Invalid Attribute!" ); - } - } - return pNew; -} - -TextPortionList::TextPortionList() -{ -} - -TextPortionList::~TextPortionList() -{ -} - -void TextPortionList::Reset() -{ - maPortions.clear(); -} - -void TextPortionList::DeleteFromPortion(sal_Int32 nDelFrom) -{ - assert((nDelFrom < static_cast<sal_Int32>(maPortions.size())) || ((nDelFrom == 0) && maPortions.empty())); - PortionsType::iterator it = maPortions.begin(); - std::advance(it, nDelFrom); - maPortions.erase(it, maPortions.end()); -} - -sal_Int32 TextPortionList::Count() const -{ - return static_cast<sal_Int32>(maPortions.size()); -} - -const TextPortion& TextPortionList::operator[](sal_Int32 nPos) const -{ - return *maPortions[nPos]; -} - -TextPortion& TextPortionList::operator[](sal_Int32 nPos) -{ - return *maPortions[nPos]; -} - -void TextPortionList::Append(TextPortion* p) -{ - maPortions.push_back(std::unique_ptr<TextPortion>(p)); -} - -void TextPortionList::Insert(sal_Int32 nPos, TextPortion* p) -{ - maPortions.insert(maPortions.begin()+nPos, std::unique_ptr<TextPortion>(p)); -} - -void TextPortionList::Remove(sal_Int32 nPos) -{ - maPortions.erase(maPortions.begin()+nPos); -} - -namespace { - -class FindTextPortionByAddress -{ - const TextPortion* mp; -public: - explicit FindTextPortionByAddress(const TextPortion* p) : mp(p) {} - bool operator() (const std::unique_ptr<TextPortion>& v) const - { - return v.get() == mp; - } -}; - -} - -sal_Int32 TextPortionList::GetPos(const TextPortion* p) const -{ - PortionsType::const_iterator it = - std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p)); - - if (it == maPortions.end()) - return std::numeric_limits<sal_Int32>::max(); // not found. - - return std::distance(maPortions.begin(), it); -} - -sal_Int32 TextPortionList::FindPortion( - sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion) const -{ - // When nCharPos at portion limit, the left portion is found - sal_Int32 nTmpPos = 0; - sal_Int32 n = maPortions.size(); - for (sal_Int32 i = 0; i < n; ++i) - { - const TextPortion& rPortion = *maPortions[i]; - nTmpPos = nTmpPos + rPortion.GetLen(); - if ( nTmpPos >= nCharPos ) - { - // take this one if we don't prefer the starting portion, or if it's the last one - if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) ) - { - nPortionStart = nTmpPos - rPortion.GetLen(); - return i; - } - } - } - OSL_FAIL( "FindPortion: Not found!" ); - return n - 1; -} - -sal_Int32 TextPortionList::GetStartPos(sal_Int32 nPortion) -{ - sal_Int32 nPos = 0; - for (sal_Int32 i = 0; i < nPortion; ++i) - { - const TextPortion& rPortion = *maPortions[i]; - nPos = nPos + rPortion.GetLen(); - } - return nPos; -} - -ExtraPortionInfo::ExtraPortionInfo() -: nOrgWidth(0) -, nWidthFullCompression(0) -, nPortionOffsetX(0) -, nMaxCompression100thPercent(0) -, nAsianCompressionTypes(AsianCompressionFlags::Normal) -, bFirstCharIsRightPunktuation(false) -, bCompressed(false) -, lineBreaksList() -{ -} - -ExtraPortionInfo::~ExtraPortionInfo() -{ -} - -void ExtraPortionInfo::SaveOrgDXArray( const tools::Long* pDXArray, sal_Int32 nLen ) -{ - if (pDXArray) - { - pOrgDXArray.reset(new tools::Long[nLen]); - memcpy( pOrgDXArray.get(), pDXArray, nLen * sizeof(tools::Long) ); + break; } - else - pOrgDXArray.reset(); -} - -ParaPortion::ParaPortion( ContentNode* pN ) : - pNode(pN), - nHeight(0), - nInvalidPosStart(0), - nFirstLineOffset(0), - nBulletX(0), - nInvalidDiff(0), - bInvalid(true), - bSimple(false), - bVisible(true), - bForceRepaint(false) -{ -} -ParaPortion::~ParaPortion() -{ + OSL_FAIL( "Invalid Attribute!" ); + return nullptr; } -void ParaPortion::MarkInvalid( sal_Int32 nStart, sal_Int32 nDiff ) +void ParaPortion::MarkInvalid(sal_Int32 nStart, sal_Int32 nDiff) { - if ( !bInvalid ) + if (!mbInvalid) { -// nInvalidPosEnd = nStart; // ??? => CreateLines - nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff ); - nInvalidDiff = nDiff; +// mnInvalidPosEnd = nStart; // ??? => CreateLines + mnInvalidPosStart = nDiff >= 0 ? nStart : nStart + nDiff; + mnInvalidDiff = nDiff; } else { // Simple tap in succession - if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) && - ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) ) + if (nDiff > 0 && mnInvalidDiff > 0 && (mnInvalidPosStart + mnInvalidDiff) == nStart) { - nInvalidDiff = nInvalidDiff + nDiff; + mnInvalidDiff = mnInvalidDiff + nDiff; } // Simple delete in succession - else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) ) + else if (nDiff < 0 && mnInvalidDiff < 0 && mnInvalidPosStart == nStart) { - nInvalidPosStart = nInvalidPosStart + nDiff; - nInvalidDiff = nInvalidDiff + nDiff; + mnInvalidPosStart = mnInvalidPosStart + nDiff; + mnInvalidDiff = mnInvalidDiff + nDiff; } else { -// nInvalidPosEnd = pNode->Len(); - DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" ); - nInvalidPosStart = std::min( nInvalidPosStart, ( nDiff < 0 ? nStart+nDiff : nDiff ) ); - nInvalidDiff = 0; - bSimple = false; +// mnInvalidPosEnd = pNode->Len(); + DBG_ASSERT(nDiff >= 0 || (nStart + nDiff) >= 0, "MarkInvalid: Diff out of Range"); + mnInvalidPosStart = std::min(mnInvalidPosStart, nDiff < 0 ? nStart + nDiff : nDiff); + mnInvalidDiff = 0; + mbSimple = false; } } - bInvalid = true; - aScriptInfos.clear(); - aWritingDirectionInfos.clear(); + mbInvalid = true; + maScriptInfos.clear(); + maWritingDirectionInfos.clear(); } -void ParaPortion::MarkSelectionInvalid( sal_Int32 nStart ) +void ParaPortion::MarkSelectionInvalid(sal_Int32 nStart) { - if ( !bInvalid ) + if ( !mbInvalid ) { - nInvalidPosStart = nStart; + mnInvalidPosStart = nStart; } else { - nInvalidPosStart = std::min( nInvalidPosStart, nStart ); + mnInvalidPosStart = std::min(mnInvalidPosStart, nStart); } - nInvalidDiff = 0; - bInvalid = true; - bSimple = false; - aScriptInfos.clear(); - aWritingDirectionInfos.clear(); + mnInvalidDiff = 0; + mbInvalid = true; + mbSimple = false; + maScriptInfos.clear(); + maWritingDirectionInfos.clear(); } sal_Int32 ParaPortion::GetLineNumber( sal_Int32 nIndex ) const { - SAL_WARN_IF( !aLineList.Count(), "editeng", "Empty ParaPortion in GetLine!" ); - DBG_ASSERT( bVisible, "Why GetLine() on an invisible paragraph?" ); + SAL_WARN_IF(!maLineList.Count(), "editeng", "Empty ParaPortion in GetLine!"); + DBG_ASSERT(mbVisible, "Why GetLine() on an invisible paragraph?"); - for ( sal_Int32 nLine = 0; nLine < aLineList.Count(); nLine++ ) + for ( sal_Int32 nLine = 0; nLine < maLineList.Count(); nLine++ ) { - if ( aLineList[nLine].IsIn( nIndex ) ) + if (maLineList[nLine].IsIn(nIndex)) return nLine; } // Then it should be at the end of the last line! - DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ].GetEnd(), "Index dead wrong!" ); - return (aLineList.Count()-1); -} - -void ParaPortion::SetVisible( bool bMakeVisible ) -{ - bVisible = bMakeVisible; + DBG_ASSERT(nIndex == maLineList[maLineList.Count() - 1].GetEnd(), "Index dead wrong!"); + return (maLineList.Count() - 1); } void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormattedLine ) { - sal_Int32 nLines = aLineList.Count(); + sal_Int32 nLines = maLineList.Count(); DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Empty Portion?" ); if ( nLastFormattedLine < ( nLines - 1 ) ) { - const EditLine& rLastFormatted = aLineList[ nLastFormattedLine ]; - const EditLine& rUnformatted = aLineList[ nLastFormattedLine+1 ]; + const EditLine& rLastFormatted = maLineList[ nLastFormattedLine ]; + const EditLine& rUnformatted = maLineList[ nLastFormattedLine+1 ]; sal_Int32 nPortionDiff = rUnformatted.GetStartPortion() - rLastFormatted.GetEndPortion(); sal_Int32 nTextDiff = rUnformatted.GetStart() - rLastFormatted.GetEnd(); nTextDiff++; // LastFormatted->GetEnd() was included => 1 deducted too much! @@ -616,7 +395,7 @@ void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormatted { for ( sal_Int32 nL = nLastFormattedLine+1; nL < nLines; nL++ ) { - EditLine& rLine = aLineList[ nL ]; + EditLine& rLine = maLineList[ nL ]; rLine.GetStartPortion() = rLine.GetStartPortion() + nPDiff; rLine.GetEndPortion() = rLine.GetEndPortion() + nPDiff; @@ -628,7 +407,7 @@ void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormatted } } } - DBG_ASSERT( aLineList[ aLineList.Count()-1 ].GetEnd() == pNode->Len(), "CorrectLines: The end is not right!" ); + DBG_ASSERT(maLineList[maLineList.Count() - 1].GetEnd() == mpNode->Len(), "CorrectLines: The end is not right!"); } // Shared reverse lookup acceleration pieces ... @@ -674,75 +453,44 @@ sal_Int32 FastGetPos(const Array& rArray, const Val* p, sal_Int32& rLastPos) } -ParaPortionList::ParaPortionList() : nLastCache( 0 ) -{ -} - -ParaPortionList::~ParaPortionList() +sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const { + return FastGetPos(maPortions, p, nLastCache); } -sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const +std::unique_ptr<ParaPortion> ParaPortionList::Release(sal_Int32 nPos) { - sal_Int32 nArrayLen = maPortions.size(); - - // Through certain filter code-paths we do a lot of appends, which in - // turn call GetPos - creating some N^2 nightmares. If we have a - // non-trivially large list, do a few checks from the end first. - if (nLastCache > 16 && nArrayLen > 16) + if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos)) { - sal_Int32 nEnd; - if (nLastCache > nArrayLen - 2) - nEnd = nArrayLen; - else - nEnd = nLastCache + 2; - - for (sal_Int32 nIdx = nLastCache - 2; nIdx < nEnd; ++nIdx) - { - if (&maPortions.at(nIdx) == p) - { - nLastCache = nIdx; - return nIdx; - } - } + SAL_WARN( "editeng", "ParaPortionList::Release - out of bounds pos " << nPos); + return nullptr; } - // The world's lamest linear search from svarray... - for (sal_Int32 nIdx = 0; nIdx < nArrayLen; ++nIdx) - if (&maPortions.at(nIdx) == p) - { - nLastCache = nIdx; - return nLastCache; - } - - // XXX "not found" condition for sal_Int32 indexes - return EE_PARA_NOT_FOUND; -} - -ParaPortion& ParaPortionList::operator [](sal_Int32 nPos) -{ - return maPortions[nPos]; -} - -const ParaPortion& ParaPortionList::operator [](sal_Int32 nPos) const -{ - return maPortions[nPos]; + std::unique_ptr<ParaPortion> p = std::move(maPortions[nPos]); + maPortions.erase(maPortions.begin()+nPos); + return p; } -ParaPortion ParaPortionList::Remove(sal_Int32 nPos) +void ParaPortionList::Remove(sal_Int32 nPos) { - auto it = maPortions.begin()+nPos; - ParaPortion val = std::move(*it); - maPortions.erase(it); - return val; + if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos)) + { + SAL_WARN( "editeng", "ParaPortionList::Remove - out of bounds pos " << nPos); + return; + } + maPortions.erase(maPortions.begin()+nPos); } -ParaPortion& ParaPortionList::Insert(sal_Int32 nPos, ParaPortion&& p) +void ParaPortionList::Insert(sal_Int32 nPos, std::unique_ptr<ParaPortion> p) { + if (nPos < 0 || maPortions.size() < o3tl::make_unsigned(nPos)) + { + SAL_WARN( "editeng", "ParaPortionList::Insert - out of bounds pos " << nPos); + return; + } maPortions.insert(maPortions.begin()+nPos, std::move(p)); - return maPortions[nPos]; } -void ParaPortionList::Append(ParaPortion&& p) +void ParaPortionList::Append(std::unique_ptr<ParaPortion> p) { maPortions.push_back(std::move(p)); } @@ -768,9 +516,10 @@ tools::Long ParaPortionList::GetYOffset(const ParaPortion* pPPortion) const tools::Long nHeight = 0; for (const auto & rPortion : maPortions) { - if ( pPPortion == &rPortion ) + const ParaPortion* pTmpPortion = rPortion.get(); + if ( pTmpPortion == pPPortion ) return nHeight; - nHeight += rPortion.GetHeight(); + nHeight += pTmpPortion->GetHeight(); } OSL_FAIL( "GetYOffset: Portion not found" ); return nHeight; @@ -781,23 +530,13 @@ sal_Int32 ParaPortionList::FindParagraph(tools::Long nYOffset) const tools::Long nY = 0; for (size_t i = 0, n = maPortions.size(); i < n; ++i) { - nY += maPortions[i].GetHeight(); // should also be correct even in bVisible! + nY += maPortions[i]->GetHeight(); // should also be correct even in bVisible! if ( nY > nYOffset ) return i <= SAL_MAX_INT32 ? static_cast<sal_Int32>(i) : SAL_MAX_INT32; } return EE_PARA_NOT_FOUND; } -const ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) const -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? &maPortions[nPos] : nullptr; -} - -ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? &maPortions[nPos] : nullptr; -} - #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG void ParaPortionList::DbgCheck(ParaPortionList const& rParas, EditDoc const& rDoc) @@ -812,15 +551,9 @@ ParaPortionList::DbgCheck(ParaPortionList const& rParas, EditDoc const& rDoc) } #endif -ContentAttribsInfo::ContentAttribsInfo( const SfxItemSet& rParaAttribs ) : - aPrevParaAttribs( rParaAttribs) -{ -} - -void ContentAttribsInfo::RemoveAllCharAttribsFromPool(SfxItemPool& rPool) const +ContentAttribsInfo::ContentAttribsInfo( SfxItemSet aParaAttribs ) : + aPrevParaAttribs(std::move( aParaAttribs)) { - for (const std::unique_ptr<EditCharAttrib>& rAttrib : aPrevCharAttribs) - rPool.Remove(*rAttrib->GetItem()); } void ContentAttribsInfo::AppendCharAttrib(EditCharAttrib* pNew) @@ -865,6 +598,13 @@ void ConvertItem( std::unique_ptr<SfxPoolItem>& rPoolItem, MapUnit eSourceUnit, assert(dynamic_cast<const SvxTabStopItem *>(rPoolItem.get()) != nullptr); SvxTabStopItem& rItem = static_cast<SvxTabStopItem&>(*rPoolItem); SvxTabStopItem* pNewItem(new SvxTabStopItem(EE_PARA_TABS)); + + if (sal_Int32 nDefTabDistance = rItem.GetDefaultDistance()) + { + pNewItem->SetDefaultDistance( + OutputDevice::LogicToLogic(nDefTabDistance, eSourceUnit, eDestUnit)); + } + for ( sal_uInt16 i = 0; i < rItem.Count(); i++ ) { const SvxTabStop& rTab = rItem[i]; @@ -899,7 +639,7 @@ void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const Map sal_uInt16 nSlot = pDestPool->GetTrueSlotId( nWhich ); if ( nSlot ) { - sal_uInt16 nW = pSourcePool->GetTrueWhich( nSlot ); + sal_uInt16 nW = pSourcePool->GetTrueWhichIDFromSlotID( nSlot ); if ( nW ) nSourceWhich = nW; } @@ -923,179 +663,6 @@ void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const Map } } -EditLine::EditLine() : - nTxtWidth(0), - nStartPosX(0), - nStart(0), - nEnd(0), - nStartPortion(0), // to be able to tell the difference between a line - // without Portions from one with the Portion number 0 - nEndPortion(0), - nHeight(0), - nTxtHeight(0), - nMaxAscent(0), - bHangingPunctuation(false), - bInvalid(true) -{ -} - -EditLine* EditLine::Clone() const -{ - EditLine* pL = new EditLine; - pL->aPositions = aPositions; - pL->nStartPosX = nStartPosX; - pL->nStart = nStart; - pL->nEnd = nEnd; - pL->nStartPortion = nStartPortion; - pL->nEndPortion = nEndPortion; - pL->nHeight = nHeight; - pL->nTxtWidth = nTxtWidth; - pL->nTxtHeight = nTxtHeight; - pL->nMaxAscent = nMaxAscent; - - return pL; -} - -bool operator == ( const EditLine& r1, const EditLine& r2 ) -{ - if ( r1.nStart != r2.nStart ) - return false; - - if ( r1.nEnd != r2.nEnd ) - return false; - - if ( r1.nStartPortion != r2.nStartPortion ) - return false; - - if ( r1.nEndPortion != r2.nEndPortion ) - return false; - - return true; -} - - -void EditLine::SetHeight( sal_uInt16 nH, sal_uInt16 nTxtH ) -{ - nHeight = nH; - nTxtHeight = ( nTxtH ? nTxtH : nH ); -} - -void EditLine::SetStartPosX( tools::Long start ) -{ - if (start > 0) - nStartPosX = start; - else - nStartPosX = 0; -} - -Size EditLine::CalcTextSize( ParaPortion& rParaPortion ) -{ - Size aSz; - Size aTmpSz; - - DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !" ); - - for ( sal_Int32 n = nStartPortion; n <= nEndPortion; n++ ) - { - TextPortion& rPortion = rParaPortion.GetTextPortions()[n]; - switch ( rPortion.GetKind() ) - { - case PortionKind::TEXT: - case PortionKind::FIELD: - case PortionKind::HYPHENATOR: - { - aTmpSz = rPortion.GetSize(); - aSz.AdjustWidth(aTmpSz.Width() ); - if ( aSz.Height() < aTmpSz.Height() ) - aSz.setHeight( aTmpSz.Height() ); - } - break; - case PortionKind::TAB: - { - aSz.AdjustWidth(rPortion.GetSize().Width() ); - } - break; - case PortionKind::LINEBREAK: break; - } - } - - SetHeight( static_cast<sal_uInt16>(aSz.Height()) ); - return aSz; -} - -EditLineList::EditLineList() -{ -} - -EditLineList::~EditLineList() -{ - Reset(); -} - -void EditLineList::Reset() -{ - maLines.clear(); -} - -void EditLineList::DeleteFromLine(sal_Int32 nDelFrom) -{ - assert(nDelFrom <= (static_cast<sal_Int32>(maLines.size()) - 1)); - LinesType::iterator it = maLines.begin(); - std::advance(it, nDelFrom); - maLines.erase(it, maLines.end()); -} - -sal_Int32 EditLineList::FindLine(sal_Int32 nChar, bool bInclEnd) -{ - sal_Int32 n = maLines.size(); - for (sal_Int32 i = 0; i < n; ++i) - { - const EditLine& rLine = *maLines[i]; - if ( (bInclEnd && (rLine.GetEnd() >= nChar)) || - (rLine.GetEnd() > nChar) ) - { - return i; - } - } - - DBG_ASSERT( !bInclEnd, "Line not found: FindLine" ); - return n - 1; -} - -sal_Int32 EditLineList::Count() const -{ - return maLines.size(); -} - -const EditLine& EditLineList::operator[](sal_Int32 nPos) const -{ - return *maLines[nPos]; -} - -EditLine& EditLineList::operator[](sal_Int32 nPos) -{ - return *maLines[nPos]; -} - -void EditLineList::Append(EditLine* p) -{ - maLines.push_back(std::unique_ptr<EditLine>(p)); -} - -void EditLineList::Insert(sal_Int32 nPos, EditLine* p) -{ - maLines.insert(maLines.begin()+nPos, std::unique_ptr<EditLine>(p)); -} - -EditPaM::EditPaM() : pNode(nullptr), nIndex(0) {} -EditPaM::EditPaM(ContentNode* p, sal_Int32 n) : pNode(p), nIndex(n) {} - - -void EditPaM::SetNode(ContentNode* p) -{ - pNode = p; -} - bool EditPaM::DbgIsBuggy( EditDoc const & rDoc ) const { return !pNode || @@ -1108,29 +675,6 @@ bool EditSelection::DbgIsBuggy( EditDoc const & rDoc ) const return aStartPaM.DbgIsBuggy( rDoc ) || aEndPaM.DbgIsBuggy( rDoc ); } -EditSelection::EditSelection() -{ -} - -EditSelection::EditSelection( const EditPaM& rStartAndAnd ) : - aStartPaM(rStartAndAnd), - aEndPaM(rStartAndAnd) -{ -} - -EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd ) : - aStartPaM(rStart), - aEndPaM(rEnd) -{ -} - -EditSelection& EditSelection::operator = ( const EditPaM& rPaM ) -{ - aStartPaM = rPaM; - aEndPaM = rPaM; - return *this; -} - void EditSelection::Adjust( const EditDoc& rNodes ) { DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in Adjust(1)" ); @@ -1157,790 +701,28 @@ void EditSelection::Adjust( const EditDoc& rNodes ) } } -bool operator == ( const EditPaM& r1, const EditPaM& r2 ) -{ - return ( r1.GetNode() == r2.GetNode() ) && - ( r1.GetIndex() == r2.GetIndex() ); -} - -bool operator != ( const EditPaM& r1, const EditPaM& r2 ) -{ - return !( r1 == r2 ); -} - -ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool ) -{ -} - -ContentNode::ContentNode( const OUString& rStr, const ContentAttribs& rContentAttribs ) : - maString(rStr), aContentAttribs(rContentAttribs) -{ -} - -ContentNode::~ContentNode() -{ -} - -void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& rItemPool ) -{ - if ( !nNew ) - return; - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif - - // Since features are treated differently than normal character attributes, - // but can also affect the order of the start list. // In every if ..., in the next (n) opportunities due to bFeature or - // an existing special case, must (n-1) opportunities be provided with - // bResort. The most likely possibility receives no bResort, so that is - // not sorted anew when all attributes are the same. - bool bResort = false; - bool bExpandedEmptyAtIndexNull = false; - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); - while ( pAttrib ) - { - if ( pAttrib->GetEnd() >= nIndex ) - { - // Move all attributes behind the insertion point... - if ( pAttrib->GetStart() > nIndex ) - { - pAttrib->MoveForward( nNew ); - } - // 0: Expand empty attribute, if at insertion point - else if ( pAttrib->IsEmpty() ) - { - // Do not check Index, an empty one could only be there - // When later checking it anyhow: - // Special case: Start == 0; AbsLen == 1, nNew = 1 - // => Expand, because of paragraph break! - // Start <= nIndex, End >= nIndex => Start=End=nIndex! -// if ( pAttrib->GetStart() == nIndex ) - pAttrib->Expand( nNew ); - bResort = true; - if ( pAttrib->GetStart() == 0 ) - bExpandedEmptyAtIndexNull = true; - } - // 1: Attribute starts before, goes to index ... - else if ( pAttrib->GetEnd() == nIndex ) // Start must be before - { - // Only expand when there is no feature - // and if not in exclude list! - // Otherwise, a UL will go on until a new ULDB, expanding both -// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) - if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) - { - if ( !pAttrib->IsEdge() ) - pAttrib->Expand( nNew ); - } - else - bResort = true; - } - // 2: Attribute starts before, goes past the Index... - else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" ); - pAttrib->Expand( nNew ); - } - // 3: Attribute starts on index... - else if ( pAttrib->GetStart() == nIndex ) - { - if ( pAttrib->IsFeature() ) - { - pAttrib->MoveForward( nNew ); - bResort = true; - } - else - { - bool bExpand = false; - if ( nIndex == 0 ) - { - bExpand = true; - if( bExpandedEmptyAtIndexNull ) - { - // Check if this kind of attribute was empty and expanded here... - sal_uInt16 nW = pAttrib->GetItem()->Which(); - for ( sal_Int32 nA = 0; nA < nAttr; nA++ ) - { - const EditCharAttrib& r = *aCharAttribList.GetAttribs()[nA]; - if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) ) - { - bExpand = false; - break; - } - } - - } - } - if ( bExpand ) - { - pAttrib->Expand( nNew ); - bResort = true; - } - else - { - pAttrib->MoveForward( nNew ); - } - } - } - } - - if ( pAttrib->IsEdge() ) - pAttrib->SetEdge(false); - - DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" ); - if ( pAttrib->IsEmpty() ) - { - OSL_FAIL( "Empty Attribute after ExpandAttribs?" ); - bResort = true; - rItemPool.Remove( *pAttrib->GetItem() ); - rAttribs.erase(rAttribs.begin()+nAttr); - --nAttr; - } - ++nAttr; - pAttrib = GetAttrib(rAttribs, nAttr); - } - - if ( bResort ) - aCharAttribList.ResortAttribs(); - - if (mpWrongList) - { - bool bSep = ( maString[ nIndex ] == ' ' ) || IsFeature( nIndex ); - mpWrongList->TextInserted( nIndex, nNew, bSep ); - } - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif -} - -void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted, SfxItemPool& rItemPool ) -{ - if ( !nDeleted ) - return; - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif - - // Since features are treated differently than normal character attributes, - // but can also affect the order of the start list - bool bResort = false; - sal_Int32 nEndChanges = nIndex+nDeleted; - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); - while ( pAttrib ) - { - bool bDelAttr = false; - if ( pAttrib->GetEnd() >= nIndex ) - { - // Move all Attribute behind the insert point... - if ( pAttrib->GetStart() >= nEndChanges ) - { - pAttrib->MoveBackward( nDeleted ); - } - // 1. Delete Internal attributes... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) - { - // Special case: Attribute covers the area exactly - // => keep as empty Attribute. - if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) - { - pAttrib->GetEnd() = nIndex; // empty - bResort = true; - } - else - bDelAttr = true; - } - // 2. Attribute starts earlier, ends inside or behind it ... - else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); - if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside - pAttrib->GetEnd() = nIndex; - else - pAttrib->Collaps( nDeleted ); // ends behind - } - // 3. Attribute starts inside, ending behind ... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) - { - // Features not allowed to expand! - if ( pAttrib->IsFeature() ) - { - pAttrib->MoveBackward( nDeleted ); - bResort = true; - } - else - { - pAttrib->GetStart() = nEndChanges; - pAttrib->MoveBackward( nDeleted ); - } - } - } - DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collapse: Attribute distorted!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collapse: Attribute larger than paragraph!" ); - if ( bDelAttr ) - { - bResort = true; - rItemPool.Remove( *pAttrib->GetItem() ); - rAttribs.erase(rAttribs.begin()+nAttr); - nAttr--; - } - else if ( pAttrib->IsEmpty() ) - aCharAttribList.SetHasEmptyAttribs(true); - - nAttr++; - pAttrib = GetAttrib(rAttribs, nAttr); - } - - if ( bResort ) - aCharAttribList.ResortAttribs(); - - if (mpWrongList) - mpWrongList->TextDeleted(nIndex, nDeleted); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif -} - -void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs ) -{ - assert(pPrevNode); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList); -#endif - - sal_Int32 nCut = pPrevNode->Len(); - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr); - while ( pAttrib ) - { - if ( pAttrib->GetEnd() < nCut ) - { - // remain unchanged... - ; - } - else if ( pAttrib->GetEnd() == nCut ) - { - // must be copied as an empty attributes. - if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) - { - EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); - assert(pNewAttrib); - aCharAttribList.InsertAttrib( pNewAttrib ); - } - } - else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) - { - // If cut is done right at the front then the attribute must be - // kept! Has to be copied and changed. - EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); - assert(pNewAttrib); - aCharAttribList.InsertAttrib( pNewAttrib ); - pAttrib->GetEnd() = nCut; - } - else - { - // Move all attributes in the current node (this) - CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr; - aCharAttribList.InsertAttrib(it->release()); - rPrevAttribs.erase(it); - pAttrib->MoveBackward( nCut ); - nAttr--; - } - nAttr++; - pAttrib = GetAttrib(rPrevAttribs, nAttr); - } - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList); -#endif -} - -void ContentNode::AppendAttribs( ContentNode* pNextNode ) -{ - assert(pNextNode); - - sal_Int32 nNewStart = maString.getLength(); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList); -#endif - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr); - while ( pAttrib ) - { - // Move all attributes in the current node (this) - bool bMelted = false; - if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) - { - // Attributes can possibly be summarized as: - sal_Int32 nTmpAttr = 0; - EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); - while ( !bMelted && pTmpAttrib ) - { - if ( pTmpAttrib->GetEnd() == nNewStart ) - { - if (pTmpAttrib->Which() == pAttrib->Which()) - { - // prevent adding 2 0-length attributes at same position - if ((*(pTmpAttrib->GetItem()) == *(pAttrib->GetItem())) - || (0 == pAttrib->GetLen())) - { - pTmpAttrib->GetEnd() = - pTmpAttrib->GetEnd() + pAttrib->GetLen(); - rNextAttribs.erase(rNextAttribs.begin()+nAttr); - // Unsubscribe from the pool?! - bMelted = true; - } - else if (0 == pTmpAttrib->GetLen()) - { - aCharAttribList.Remove(nTmpAttr); - --nTmpAttr; // to cancel later increment... - } - } - } - ++nTmpAttr; - pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); - } - } - - if ( !bMelted ) - { - pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; - pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; - CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr; - aCharAttribList.InsertAttrib(it->release()); - rNextAttribs.erase(it); - } - pAttrib = GetAttrib(rNextAttribs, nAttr); - } - // For the Attributes that just moved over: - rNextAttribs.clear(); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList); -#endif -} - -void ContentNode::CreateDefFont() -{ - // First use the information from the style ... - SfxStyleSheet* pS = aContentAttribs.GetStyleSheet(); - if ( pS ) - CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); - - // ... then iron out the hard paragraph formatting... - CreateFont( GetCharAttribs().GetDefFont(), - GetContentAttribs().GetItems(), pS == nullptr ); -} - -void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) -{ - aContentAttribs.SetStyleSheet( pS ); - - - // First use the information from the style ... - GetCharAttribs().GetDefFont() = rFontFromStyle; - // ... then iron out the hard paragraph formatting... - CreateFont( GetCharAttribs().GetDefFont(), - GetContentAttribs().GetItems(), pS == nullptr ); -} - -void ContentNode::SetStyleSheet( SfxStyleSheet* pS, bool bRecalcFont ) -{ - aContentAttribs.SetStyleSheet( pS ); - if ( bRecalcFont ) - CreateDefFont(); -} - -bool ContentNode::IsFeature( sal_Int32 nPos ) const -{ - return maString[nPos] == CH_FEATURE; -} - -sal_Int32 ContentNode::Len() const -{ - return maString.getLength(); -} - -sal_uLong ContentNode::GetExpandedLen() const -{ - sal_uLong nLen = maString.getLength(); - - // Fields can be longer than the placeholder in the Node - const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); - for (sal_Int32 nAttr = rAttrs.size(); nAttr; ) - { - const EditCharAttrib& rAttr = *rAttrs[--nAttr]; - if (rAttr.Which() == EE_FEATURE_FIELD) - { - nLen += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); - --nLen; // Standalone, to avoid corner cases when previous getLength() returns 0 - } - } - - return nLen; -} - -OUString ContentNode::GetExpandedText(sal_Int32 nStartPos, sal_Int32 nEndPos) const -{ - if ( nEndPos < 0 || nEndPos > Len() ) - nEndPos = Len(); - - DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" ); - - sal_Int32 nIndex = nStartPos; - OUStringBuffer aStr(256); - const EditCharAttrib* pNextFeature = GetCharAttribs().FindFeature( nIndex ); - while ( nIndex < nEndPos ) - { - sal_Int32 nEnd = nEndPos; - if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) - nEnd = pNextFeature->GetStart(); - else - pNextFeature = nullptr; // Feature does not interest the below - - DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" ); - //!! beware of sub string length of -1 - if (nEnd > nIndex) - aStr.append( GetString().subView(nIndex, nEnd - nIndex) ); - - if ( pNextFeature ) - { - switch ( pNextFeature->GetItem()->Which() ) - { - case EE_FEATURE_TAB: aStr.append( "\t" ); - break; - case EE_FEATURE_LINEBR: aStr.append( "\x0A" ); - break; - case EE_FEATURE_FIELD: - aStr.append( static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue() ); - break; - default: OSL_FAIL( "What feature?" ); - } - pNextFeature = GetCharAttribs().FindFeature( ++nEnd ); - } - nIndex = nEnd; - } - return aStr.makeStringAndClear(); -} - -void ContentNode::UnExpandPosition( sal_Int32 &rPos, bool bBiasStart ) -{ - sal_Int32 nOffset = 0; - - const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); - for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr ) - { - const EditCharAttrib& rAttr = *rAttrs[nAttr]; - assert (!(nAttr < rAttrs.size() - 1) || - rAttrs[nAttr]->GetStart() <= rAttrs[nAttr + 1]->GetStart()); - - nOffset = rAttr.GetStart(); - - if (nOffset >= rPos) // happens after the position - return; - - if (rAttr.Which() == EE_FEATURE_FIELD) - { - sal_Int32 nChunk = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); - nChunk--; // Character representing the field in the string - - if (nOffset + nChunk >= rPos) // we're inside the field - { - if (bBiasStart) - rPos = rAttr.GetStart(); - else - rPos = rAttr.GetEnd(); - return; - } - // Adjust for the position - rPos -= nChunk; - } - } - assert (rPos <= Len()); -} - -/* - * Fields are represented by a single character in the underlying string - * and/or selection, however, they can be expanded to the full value of - * the field. When we're dealing with selection / offsets however we need - * to deal in character positions inside the real (unexpanded) string. - * This method maps us back to character offsets. - */ -void ContentNode::UnExpandPositions( sal_Int32 &rStartPos, sal_Int32 &rEndPos ) -{ - UnExpandPosition( rStartPos, true ); - UnExpandPosition( rEndPos, false ); -} - -void ContentNode::SetChar(sal_Int32 nPos, sal_Unicode c) -{ - maString = maString.replaceAt(nPos, 1, OUString(c)); -} - -void ContentNode::Insert(const OUString& rStr, sal_Int32 nPos) -{ - maString = maString.replaceAt(nPos, 0, rStr); -} - -void ContentNode::Append(std::u16string_view rStr) -{ - maString += rStr; -} - -void ContentNode::Erase(sal_Int32 nPos) -{ - maString = maString.copy(0, nPos); -} - -void ContentNode::Erase(sal_Int32 nPos, sal_Int32 nCount) -{ - maString = maString.replaceAt(nPos, nCount, ""); -} - -OUString ContentNode::Copy(sal_Int32 nPos) const -{ - return maString.copy(nPos); -} - -OUString ContentNode::Copy(sal_Int32 nPos, sal_Int32 nCount) const -{ - return maString.copy(nPos, nCount); -} - -sal_Unicode ContentNode::GetChar(sal_Int32 nPos) const -{ - return maString[nPos]; -} - -void ContentNode::EnsureWrongList() -{ - if (!mpWrongList) - CreateWrongList(); -} - -WrongList* ContentNode::GetWrongList() -{ - return mpWrongList.get(); -} - -const WrongList* ContentNode::GetWrongList() const -{ - return mpWrongList.get(); -} - -void ContentNode::SetWrongList( WrongList* p ) -{ - mpWrongList.reset(p); -} - -void ContentNode::CreateWrongList() -{ - SAL_WARN_IF( mpWrongList && !mpWrongList->empty(), "editeng", "WrongList already exist!"); - if (!mpWrongList || !mpWrongList->empty()) - mpWrongList.reset(new WrongList); -} - -void ContentNode::DestroyWrongList() -{ - mpWrongList.reset(); -} - -void ContentNode::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentNode")); - (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("maString"), BAD_CAST(maString.toUtf8().getStr())); - aContentAttribs.dumpAsXml(pWriter); - aCharAttribList.dumpAsXml(pWriter); - (void)xmlTextWriterEndElement(pWriter); -} - - -ContentAttribs::ContentAttribs( SfxItemPool& rPool ) -: pStyle(nullptr) -, aAttribSet( rPool, svl::Items<EE_PARA_START, EE_CHAR_END>{} ) -{ -} - - -SvxTabStop ContentAttribs::FindTabStop( sal_Int32 nCurPos, sal_uInt16 nDefTab ) -{ - const SvxTabStopItem& rTabs = GetItem( EE_PARA_TABS ); - for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) - { - const SvxTabStop& rTab = rTabs[i]; - if ( rTab.GetTabPos() > nCurPos ) - return rTab; - } - - // Determine DefTab ... - SvxTabStop aTabStop; - const sal_Int32 x = nCurPos / nDefTab + 1; - aTabStop.GetTabPos() = nDefTab * x; - return aTabStop; -} - -void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) -{ - bool bStyleChanged = ( pStyle != pS ); - pStyle = pS; - // Only when other style sheet, not when current style sheet modified - if ( !(pStyle && bStyleChanged) ) - return; - - // Selectively remove the attributes from the paragraph formatting - // which are specified in the style, so that the attributes of the - // style can have an affect. - const SfxItemSet& rStyleAttribs = pStyle->GetItemSet(); - for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) - { - // Don't change bullet on/off - if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET ) ) - aAttribSet.ClearItem( nWhich ); - } -} - -const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const -{ - // Hard paragraph attributes take precedence! - const SfxItemSet* pTakeFrom = &aAttribSet; - if ( pStyle && ( aAttribSet.GetItemState( nWhich, false ) != SfxItemState::SET ) ) - pTakeFrom = &pStyle->GetItemSet(); - - return pTakeFrom->Get( nWhich ); -} - -bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const -{ - bool bHasItem = false; - if ( aAttribSet.GetItemState( nWhich, false ) == SfxItemState::SET ) - bHasItem = true; - else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SfxItemState::SET ) - bHasItem = true; - - return bHasItem; -} - -void ContentAttribs::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentAttribs")); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("style"), "%s", pStyle->GetName().toUtf8().getStr()); - aAttribSet.dumpAsXml(pWriter); - (void)xmlTextWriterEndElement(pWriter); -} - - -ItemList::ItemList() : CurrentItem( 0 ) -{ -} - -const SfxPoolItem* ItemList::First() -{ - CurrentItem = 0; - return aItemPool.empty() ? nullptr : aItemPool[ 0 ]; -} - -const SfxPoolItem* ItemList::Next() -{ - if ( CurrentItem + 1 < static_cast<sal_Int32>(aItemPool.size()) ) - { - ++CurrentItem; - return aItemPool[ CurrentItem ]; - } - return nullptr; -} - -void ItemList::Insert( const SfxPoolItem* pItem ) -{ - aItemPool.push_back( pItem ); - CurrentItem = aItemPool.size() - 1; -} - - EditDoc::EditDoc( SfxItemPool* pPool ) : - nLastCache(0), - pItemPool(pPool ? pPool : new EditEngineItemPool()), - nDefTab(DEFTAB), - bIsVertical(false), + mnLastCache(0), + mpItemPool(pPool ? pPool : new EditEngineItemPool()), + mnDefTab(DEFTAB), + mbIsVertical(false), mnRotation(TextRotation::NONE), - bIsFixedCellHeight(false), - bModified(false), - bDisableAttributeExpanding(false) + mbIsFixedCellHeight(false), + mbModified(false), + mbDisableAttributeExpanding(false) { // Don't create an empty node, Clear() will be called in EditEngine-CTOR }; EditDoc::~EditDoc() { - ImplDestroyContents(); -} - -namespace { - -class RemoveEachItemFromPool -{ - EditDoc& mrDoc; -public: - explicit RemoveEachItemFromPool(EditDoc& rDoc) : mrDoc(rDoc) {} - void operator() (const std::unique_ptr<ContentNode>& rNode) - { - mrDoc.RemoveItemsFromPool(*rNode); - } -}; - -struct ClearSpellErrorsHandler -{ - void operator() (std::unique_ptr<ContentNode> const & rNode) - { - rNode->DestroyWrongList(); - } -}; - -} - -void EditDoc::ImplDestroyContents() -{ - std::for_each(maContents.begin(), maContents.end(), RemoveEachItemFromPool(*this)); maContents.clear(); } -void EditDoc::RemoveItemsFromPool(const ContentNode& rNode) -{ - for (sal_Int32 nAttr = 0; nAttr < rNode.GetCharAttribs().Count(); ++nAttr) - { - const EditCharAttrib& rAttr = *rNode.GetCharAttribs().GetAttribs()[nAttr]; - GetItemPool().Remove(*rAttr.GetItem()); - } -} - void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, SvtScriptType nScriptType ) { vcl::Font aPrevFont( rFont ); rFont.SetAlignment( ALIGN_BASELINE ); - rFont.SetTransparent( true ); sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ); sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); @@ -1961,7 +743,11 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SfxItemState::SET ) ) rFont.SetColor( rSet.Get( EE_CHAR_COLOR ).GetValue() ); if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_BKGCOLOR ) == SfxItemState::SET ) ) - rFont.SetFillColor( rSet.Get( EE_CHAR_BKGCOLOR ).GetValue() ); + { + auto& aColor = rSet.Get( EE_CHAR_BKGCOLOR ).GetValue(); + rFont.SetTransparent(aColor.IsTransparent()); + rFont.SetFillColor(aColor); + } if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SfxItemState::SET ) ) rFont.SetFontSize( Size( rFont.GetFontSize().Width(), static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich_FontHeight ) ).GetHeight() ) ); if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SfxItemState::SET ) ) @@ -2013,75 +799,64 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S void EditDoc::CreateDefFont( bool bUseStyles ) { - SfxItemSet aTmpSet( GetItemPool(), svl::Items<EE_PARA_START, EE_CHAR_END>{} ); - CreateFont( aDefFont, aTmpSet ); - aDefFont.SetVertical( IsVertical() ); - aDefFont.SetOrientation( Degree10(IsVertical() ? (IsTopToBottom() ? 2700 : 900) : 0) ); + SfxItemSetFixed<EE_PARA_START, EE_CHAR_END> aTmpSet( GetItemPool() ); + CreateFont(maDefFont, aTmpSet); + maDefFont.SetVertical( IsEffectivelyVertical() ); + maDefFont.SetOrientation( Degree10(IsEffectivelyVertical() ? (IsTopToBottom() ? 2700 : 900) : 0) ); - for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ ) + for (std::unique_ptr<ContentNode>& pNode : maContents) { - ContentNode* pNode = GetObject( nNode ); - pNode->GetCharAttribs().GetDefFont() = aDefFont; - if ( bUseStyles ) + pNode->GetCharAttribs().GetDefFont() = maDefFont; + if (bUseStyles) pNode->CreateDefFont(); } } -bool EditDoc::IsVertical() const +bool EditDoc::IsEffectivelyVertical() const { - return (bIsVertical && mnRotation == TextRotation::NONE) || - (!bIsVertical && mnRotation != TextRotation::NONE); + return (mbIsVertical && mnRotation == TextRotation::NONE) || + (!mbIsVertical && mnRotation != TextRotation::NONE); } bool EditDoc::IsTopToBottom() const { - return (bIsVertical && mnRotation == TextRotation::NONE) || - (!bIsVertical && mnRotation == TextRotation::TOPTOBOTTOM); + return (mbIsVertical && mnRotation == TextRotation::NONE) || + (!mbIsVertical && mnRotation == TextRotation::TOPTOBOTTOM); } -bool EditDoc::GetDirectVertical() const +bool EditDoc::GetVertical() const { - return bIsVertical; + return mbIsVertical; } -sal_Int32 EditDoc::GetPos(const ContentNode* p) const +sal_Int32 EditDoc::GetPos(const ContentNode* pContentNode) const { - return FastGetPos(maContents, p, nLastCache); + return FastGetPos(maContents, pContentNode, mnLastCache); } const ContentNode* EditDoc::GetObject(sal_Int32 nPos) const { - return 0 <= nPos && nPos < static_cast<sal_Int32>(maContents.size()) ? maContents[nPos].get() : nullptr; + return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr; } ContentNode* EditDoc::GetObject(sal_Int32 nPos) { - return 0 <= nPos && nPos < static_cast<sal_Int32>(maContents.size()) ? maContents[nPos].get() : nullptr; -} - -const ContentNode* EditDoc::operator[](sal_Int32 nPos) const -{ - return GetObject(nPos); -} - -ContentNode* EditDoc::operator[](sal_Int32 nPos) -{ - return GetObject(nPos); + return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr; } -void EditDoc::Insert(sal_Int32 nPos, ContentNode* p) +void EditDoc::Insert(sal_Int32 nPos, std::unique_ptr<ContentNode> pNode) { if (nPos < 0 || nPos == SAL_MAX_INT32) { SAL_WARN( "editeng", "EditDoc::Insert - overflow pos " << nPos); return; } - maContents.insert(maContents.begin()+nPos, std::unique_ptr<ContentNode>(p)); + maContents.insert(maContents.begin()+nPos, std::move(pNode)); } void EditDoc::Remove(sal_Int32 nPos) { - if (nPos < 0 || nPos >= static_cast<sal_Int32>(maContents.size())) + if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size()) { SAL_WARN( "editeng", "EditDoc::Remove - out of bounds pos " << nPos); return; @@ -2089,15 +864,17 @@ void EditDoc::Remove(sal_Int32 nPos) maContents.erase(maContents.begin() + nPos); } -void EditDoc::Release(sal_Int32 nPos) +std::unique_ptr<ContentNode> EditDoc::Release(sal_Int32 nPos) { - if (nPos < 0 || nPos >= static_cast<sal_Int32>(maContents.size())) + if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size()) { SAL_WARN( "editeng", "EditDoc::Release - out of bounds pos " << nPos); - return; + return nullptr; } - (void)maContents[nPos].release(); + + std::unique_ptr<ContentNode> pNode = std::move(maContents[nPos]); maContents.erase(maContents.begin() + nPos); + return pNode; } sal_Int32 EditDoc::Count() const @@ -2128,7 +905,7 @@ OUString EditDoc::GetText( LineEnd eEnd ) const const OUString aSep = EditDoc::GetSepStr( eEnd ); const sal_Int32 nSepSize = aSep.getLength(); - const sal_uInt32 nLen = GetTextLen() + (nNodes - 1)*nSepSize; + const sal_Int32 nLen = GetTextLen() + (nNodes - 1)*nSepSize; OUStringBuffer aBuffer(nLen + 16); // leave some slack @@ -2167,23 +944,22 @@ EditPaM EditDoc::GetEndPaM() const return EditPaM( pLastNode, pLastNode->Len() ); } -sal_uLong EditDoc::GetTextLen() const +sal_Int32 EditDoc::GetTextLen() const { - sal_uLong nLen = 0; - for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ ) + sal_Int32 nLength = 0; + for (auto const& pContent : maContents) { - const ContentNode* pNode = GetObject( nNode ); - nLen += pNode->GetExpandedLen(); + nLength += pContent->GetExpandedLen(); } - return nLen; + return nLength; } EditPaM EditDoc::Clear() { - ImplDestroyContents(); + maContents.clear(); - ContentNode* pNode = new ContentNode( GetItemPool() ); - Insert(0, pNode); + ContentNode* pNode = new ContentNode(GetItemPool()); + Insert(0, std::unique_ptr<ContentNode>(pNode)); CreateDefFont(false); @@ -2192,6 +968,17 @@ EditPaM EditDoc::Clear() return EditPaM( pNode, 0 ); } +namespace +{ +struct ClearSpellErrorsHandler +{ + void operator() (std::unique_ptr<ContentNode> const & rNode) + { + rNode->DestroyWrongList(); + } +}; +} + void EditDoc::ClearSpellErrors() { std::for_each(maContents.begin(), maContents.end(), ClearSpellErrorsHandler()); @@ -2199,11 +986,9 @@ void EditDoc::ClearSpellErrors() void EditDoc::SetModified( bool b ) { - bModified = b; - if ( bModified ) - { - aModifyHdl.Call( nullptr ); - } + mbModified = b; + if (mbModified) + maModifyHdl.Call(nullptr); } EditPaM EditDoc::RemoveText() @@ -2214,10 +999,10 @@ EditPaM EditDoc::RemoveText() SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() ); vcl::Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() ); - ImplDestroyContents(); + maContents.clear(); - ContentNode* pNode = new ContentNode( GetItemPool() ); - Insert(0, pNode); + ContentNode* pNode = new ContentNode(GetItemPool()); + Insert(0, std::unique_ptr<ContentNode>(pNode)); pNode->SetStyleSheet(pPrevStyle, false); pNode->GetContentAttribs().GetItems().Set( aPrevSet ); @@ -2225,19 +1010,19 @@ EditPaM EditDoc::RemoveText() SetModified(true); - return EditPaM( pNode, 0 ); + return EditPaM(pNode, 0); } -EditPaM EditDoc::InsertText( EditPaM aPaM, const OUString& rStr ) +EditPaM EditDoc::InsertText( EditPaM aPaM, std::u16string_view rStr ) { - DBG_ASSERT( rStr.indexOf( 0x0A ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); - DBG_ASSERT( rStr.indexOf( 0x0D ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); - DBG_ASSERT( rStr.indexOf( '\t' ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( 0x0A ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( 0x0D ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( '\t' ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); assert(aPaM.GetNode()); aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() ); - aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.getLength(), GetItemPool() ); - aPaM.SetIndex( aPaM.GetIndex() + rStr.getLength() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.size() ); + aPaM.SetIndex( aPaM.GetIndex() + rStr.size() ); SetModified( true ); @@ -2259,7 +1044,7 @@ EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs ) aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, true) ); // ContentNode constructor copies also the paragraph attributes - ContentNode* pNode = new ContentNode( aStr, aContentAttribs ); + ContentNode* pNode = new ContentNode(aStr, std::move(aContentAttribs)); // Copy the Default Font pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont(); @@ -2277,7 +1062,7 @@ EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs ) // Character attributes may need to be copied or trimmed: pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs ); - Insert(nPos+1, pNode); + Insert(nPos+1, std::unique_ptr<ContentNode>(pNode)); SetModified(true); @@ -2290,8 +1075,8 @@ EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem ) { assert(aPaM.GetNode()); - aPaM.GetNode()->Insert( OUString(CH_FEATURE), aPaM.GetIndex() ); - aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() ); + aPaM.GetNode()->Insert( rtl::OUStringChar(CH_FEATURE), aPaM.GetIndex() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1 ); // Create a feature-attribute for the feature... EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 ); @@ -2314,7 +1099,6 @@ EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight ) pLeft->Append(pRight->GetString()); // the one to the right disappears. - RemoveItemsFromPool(*pRight); sal_Int32 nRight = GetPos( pRight ); Remove( nRight ); @@ -2327,7 +1111,7 @@ void EditDoc::RemoveChars( EditPaM aPaM, sal_Int32 nChars ) { // Maybe remove Features! aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars ); - aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars, GetItemPool() ); + aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars ); SetModified( true ); } @@ -2350,7 +1134,7 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal // tdf#132288 By default inserting an attribute beside another that is of // the same type expands the original instead of inserting another. But the // spell check dialog doesn't want that behaviour - if (bDisableAttributeExpanding) + if (mbDisableAttributeExpanding) { pStartingAttrib = nullptr; pEndingAttrib = nullptr; @@ -2362,7 +1146,6 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal { // Will become a large Attribute. pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd(); - GetItemPool().Remove( *(pStartingAttrib->GetItem()) ); pNode->GetCharAttribs().Remove(pStartingAttrib); } else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) ) @@ -2406,7 +1189,7 @@ bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEn #endif // iterate over the attributes ... - sal_Int32 nAttr = 0; + std::size_t nAttr = 0; CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs(); EditCharAttrib* pAttr = GetAttrib(rAttribs, nAttr); while ( pAttr ) @@ -2484,11 +1267,12 @@ bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEn { DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Delete and retain the same attribute?" ); DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" ); - GetItemPool().Remove( *pAttr->GetItem() ); rAttribs.erase(rAttribs.begin()+nAttr); - nAttr--; } - nAttr++; + else + { + nAttr++; + } pAttr = GetAttrib(rAttribs, nAttr); } @@ -2566,7 +1350,7 @@ void EditDoc::FindAttribs( ContentNode* pNode, sal_Int32 nStartPos, sal_Int32 nE assert(pNode); DBG_ASSERT( nStartPos <= nEndPos, "Invalid region!" ); - sal_uInt16 nAttr = 0; + std::size_t nAttr = 0; EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); // No Selection... if ( nStartPos == nEndPos ) @@ -2693,321 +1477,14 @@ void EditDoc::dumpAsXml(xmlTextWriterPtr pWriter) const } } - -namespace { - -struct LessByStart -{ - bool operator() (const std::unique_ptr<EditCharAttrib>& left, const std::unique_ptr<EditCharAttrib>& right) const - { - return left->GetStart() < right->GetStart(); - } -}; - -} - -CharAttribList::CharAttribList() -: aAttribs() -, aDefFont() -, bHasEmptyAttribs(false) -{ -} - -CharAttribList::~CharAttribList() -{ -} - -void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) -{ -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// optimize: binary search? ! -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - // Maybe just simply iterate backwards: - // The most common and critical case: Attributes are already sorted - // (InsertBinTextObject!) binary search would not be optimal here. - // => Would bring something! - - const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt. - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif - - if ( pAttrib->IsEmpty() ) - bHasEmptyAttribs = true; - - bool bInsert(true); - for (sal_Int32 i = 0, n = aAttribs.size(); i < n; ++i) - { - const EditCharAttrib& rCurAttrib = *aAttribs[i]; - if (rCurAttrib.GetStart() > nStart) - { - aAttribs.insert(aAttribs.begin()+i, std::unique_ptr<EditCharAttrib>(pAttrib)); - bInsert = false; - break; - } - } - - if (bInsert) aAttribs.push_back(std::unique_ptr<EditCharAttrib>(pAttrib)); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -void CharAttribList::ResortAttribs() -{ - std::sort(aAttribs.begin(), aAttribs.end(), LessByStart()); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool ) -{ -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif - for (sal_Int32 i = 0; i < static_cast<sal_Int32>(aAttribs.size()); ++i) - { - EditCharAttrib& rAttr = *aAttribs[i]; - for (sal_Int32 nNext = i+1; nNext < static_cast<sal_Int32>(aAttribs.size()); ++nNext) - { - EditCharAttrib& rNext = *aAttribs[nNext]; - if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which()) - { - if (*rNext.GetItem() == *rAttr.GetItem()) - { - rAttr.GetEnd() = rNext.GetEnd(); - rItemPool.Remove(*rNext.GetItem()); - aAttribs.erase(aAttribs.begin()+nNext); - } - break; // only 1 attr with same which can start here. - } - else if (rNext.GetStart() > rAttr.GetEnd()) - { - break; - } - } - } -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -sal_Int32 CharAttribList::Count() const -{ - return aAttribs.size(); -} - -const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::const_reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(), - [&nWhich, &nPos](const AttribsType::value_type& rxAttr) { - return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); - if (it != aAttribs.rend()) - { - const EditCharAttrib& rAttr = **it; - return &rAttr; - } - return nullptr; -} - -EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(), - [&nWhich, &nPos](AttribsType::value_type& rxAttr) { - return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); - if (it != aAttribs.rend()) - { - EditCharAttrib& rAttr = **it; - return &rAttr; - } - return nullptr; -} - -const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_Int32 nFromPos ) const -{ - assert(nWhich); - for (auto const& attrib : aAttribs) - { - const EditCharAttrib& rAttr = *attrib; - if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich) - return &rAttr; - } - return nullptr; -} - -bool CharAttribList::HasAttrib( sal_Int32 nStartPos, sal_Int32 nEndPos ) const -{ - return std::any_of(aAttribs.rbegin(), aAttribs.rend(), - [&nStartPos, &nEndPos](const AttribsType::value_type& rxAttr) { - return rxAttr->GetStart() < nEndPos && rxAttr->GetEnd() > nStartPos; }); -} - - -namespace { - -class FindByAddress -{ - const EditCharAttrib* mpAttr; -public: - explicit FindByAddress(const EditCharAttrib* p) : mpAttr(p) {} - bool operator() (const std::unique_ptr<EditCharAttrib>& r) const - { - return r.get() == mpAttr; - } -}; - -} - -void CharAttribList::Remove(const EditCharAttrib* p) -{ - AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p)); - if (it != aAttribs.end()) - aAttribs.erase(it); -} - -void CharAttribList::Remove(sal_Int32 nPos) -{ - if (nPos >= static_cast<sal_Int32>(aAttribs.size())) - return; - - aAttribs.erase(aAttribs.begin()+nPos); -} - -void CharAttribList::SetHasEmptyAttribs(bool b) -{ - bHasEmptyAttribs = b; -} - -bool CharAttribList::HasBoundingAttrib( sal_Int32 nBound ) const -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend(); - for (; it != itEnd; ++it) - { - const EditCharAttrib& rAttr = **it; - if (rAttr.GetEnd() < nBound) - return false; - - if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound) - return true; - } - return false; -} - -EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) -{ - if ( !bHasEmptyAttribs ) - return nullptr; - - for (const std::unique_ptr<EditCharAttrib>& rAttr : aAttribs) - { - if (rAttr->GetStart() == nPos && rAttr->GetEnd() == nPos && rAttr->Which() == nWhich) - return rAttr.get(); - } - return nullptr; -} - -namespace { - -class FindByStartPos -{ - sal_Int32 mnPos; -public: - explicit FindByStartPos(sal_Int32 nPos) : mnPos(nPos) {} - bool operator() (const std::unique_ptr<EditCharAttrib>& r) const - { - return r->GetStart() >= mnPos; - } -}; - -} - -const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const -{ - // First, find the first attribute that starts at or after specified position. - AttribsType::const_iterator it = - std::find_if(aAttribs.begin(), aAttribs.end(), FindByStartPos(nPos)); - - if (it == aAttribs.end()) - // All attributes are before the specified position. - return nullptr; - - // And find the first attribute with feature. - it = std::find_if(it, aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsFeature(); } ); - return it == aAttribs.end() ? nullptr : it->get(); -} - -namespace { - -class RemoveEmptyAttrItem -{ - SfxItemPool& mrItemPool; -public: - explicit RemoveEmptyAttrItem(SfxItemPool& rPool) : mrItemPool(rPool) {} - void operator() (const std::unique_ptr<EditCharAttrib>& r) - { - if (r->IsEmpty()) - mrItemPool.Remove(*r->GetItem()); - } -}; - -} - -void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool ) -{ - std::for_each(aAttribs.begin(), aAttribs.end(), RemoveEmptyAttrItem(rItemPool)); - aAttribs.erase( std::remove_if(aAttribs.begin(), aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsEmpty(); } ), aAttribs.end() ); - bHasEmptyAttribs = false; -} - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG -void CharAttribList::DbgCheckAttribs(CharAttribList const& rAttribs) -{ - std::set<std::pair<sal_Int32, sal_uInt16>> zero_set; - for (const std::unique_ptr<EditCharAttrib>& rAttr : rAttribs.aAttribs) - { - assert(rAttr->GetStart() <= rAttr->GetEnd()); - assert(!rAttr->IsFeature() || rAttr->GetLen() == 1); - if (0 == rAttr->GetLen()) - { - // not sure if 0-length attributes allowed at all in non-empty para? - assert(zero_set.insert(std::make_pair(rAttr->GetStart(), rAttr->Which())).second && "duplicate 0-length attribute detected"); - } - } - CheckOrderedList(rAttribs.GetAttribs()); -} -#endif - -void CharAttribList::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("CharAttribList")); - for (auto const & i : aAttribs) { - i->dumpAsXml(pWriter); - } - (void)xmlTextWriterEndElement(pWriter); -} - EditEngineItemPool::EditEngineItemPool() - : SfxItemPool( "EditEngineItemPool", EE_ITEMS_START, EE_ITEMS_END, - aItemInfos, nullptr ) +: SfxItemPool("EditEngineItemPool") { - m_xDefItems = EditDLL::Get().GetGlobalData()->GetDefItems(); - SetDefaults(&m_xDefItems->getDefaults()); + registerItemInfoPackage(getItemInfoPackageEditEngine()); } EditEngineItemPool::~EditEngineItemPool() { - ClearDefaults(); SetSecondaryPool(nullptr); } diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index b90ad3127fee..ce9b182c0f54 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -23,6 +23,7 @@ #include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> #include <config_global.h> +#include <o3tl/safeint.hxx> #include <vcl/svapp.hxx> #include <vcl/weld.hxx> #include <vcl/window.hxx> @@ -84,120 +85,122 @@ using namespace ::com::sun::star::linguistic2; static bool bDebugPaint = false; #endif - static rtl::Reference<SfxItemPool> pGlobalPool; -EditEngine::EditEngine( SfxItemPool* pItemPool ) +ImpEditEngine& EditEngine::getImpl() const { - pImpEditEngine.reset( new ImpEditEngine( this, pItemPool ) ); + return *mpImpEditEngine; } -EditEngine::~EditEngine() +EditEngine::EditEngine(SfxItemPool* pItemPool) + : mpImpEditEngine(new ImpEditEngine(this, pItemPool)) { } +EditEngine::~EditEngine() = default; + void EditEngine::EnableUndo( bool bEnable ) { - pImpEditEngine->EnableUndo( bEnable ); + getImpl().EnableUndo(bEnable); } bool EditEngine::IsUndoEnabled() const { - return pImpEditEngine->IsUndoEnabled(); + return getImpl().IsUndoEnabled(); } bool EditEngine::IsInUndo() const { - return pImpEditEngine->IsInUndo(); + return getImpl().IsInUndo(); } -SfxUndoManager& EditEngine::GetUndoManager() +EditUndoManager& EditEngine::GetUndoManager() { - return pImpEditEngine->GetUndoManager(); + return getImpl().GetUndoManager(); } -SfxUndoManager* EditEngine::SetUndoManager(SfxUndoManager* pNew) +EditUndoManager* EditEngine::SetUndoManager(EditUndoManager* pNew) { - return pImpEditEngine->SetUndoManager(pNew); + return getImpl().SetUndoManager(pNew); } void EditEngine::UndoActionStart( sal_uInt16 nId ) { - DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Calling UndoActionStart in Undomode!" ); - if ( !pImpEditEngine->IsInUndo() ) - pImpEditEngine->UndoActionStart( nId ); + DBG_ASSERT(!getImpl().IsInUndo(), "Calling UndoActionStart in Undomode!"); + if (!getImpl().IsInUndo()) + getImpl().UndoActionStart(nId); } void EditEngine::UndoActionStart(sal_uInt16 nId, const ESelection& rSel) { - pImpEditEngine->UndoActionStart(nId, rSel); + getImpl().UndoActionStart(nId, rSel); } void EditEngine::UndoActionEnd() { - DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Calling UndoActionEnd in Undomode!" ); - if ( !pImpEditEngine->IsInUndo() ) - pImpEditEngine->UndoActionEnd(); + DBG_ASSERT(!getImpl().IsInUndo(), "Calling UndoActionEnd in Undomode!"); + if (!getImpl().IsInUndo()) + getImpl().UndoActionEnd(); } bool EditEngine::HasTriedMergeOnLastAddUndo() const { - return pImpEditEngine->mbLastTryMerge; + return getImpl().mbLastTryMerge; } void EditEngine::SetRefDevice( OutputDevice* pRefDev ) { - pImpEditEngine->SetRefDevice( pRefDev ); + getImpl().SetRefDevice(pRefDev); } OutputDevice* EditEngine::GetRefDevice() const { - return pImpEditEngine->GetRefDevice(); + return getImpl().GetRefDevice(); } void EditEngine::SetRefMapMode( const MapMode& rMapMode ) { - pImpEditEngine->SetRefMapMode( rMapMode ); + getImpl().SetRefMapMode(rMapMode); } MapMode const & EditEngine::GetRefMapMode() const { - return pImpEditEngine->GetRefMapMode(); + return getImpl().GetRefMapMode(); } void EditEngine::SetBackgroundColor( const Color& rColor ) { - pImpEditEngine->SetBackgroundColor( rColor ); + getImpl().SetBackgroundColor(rColor); } Color const & EditEngine::GetBackgroundColor() const { - return pImpEditEngine->GetBackgroundColor(); + return getImpl().GetBackgroundColor(); } Color EditEngine::GetAutoColor() const { - return pImpEditEngine->GetAutoColor(); + return getImpl().GetAutoColor(); } void EditEngine::EnableAutoColor( bool b ) { - pImpEditEngine->EnableAutoColor( b ); + getImpl().EnableAutoColor( b ); } void EditEngine::ForceAutoColor( bool b ) { - pImpEditEngine->ForceAutoColor( b ); + getImpl().ForceAutoColor( b ); } bool EditEngine::IsForceAutoColor() const { - return pImpEditEngine->IsForceAutoColor(); + return getImpl().IsForceAutoColor(); } const SfxItemSet& EditEngine::GetEmptyItemSet() const { - return pImpEditEngine->GetEmptyItemSet(); + return getImpl().GetEmptyItemSet(); } void EditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect ) @@ -213,13 +216,13 @@ void EditEngine::Draw( OutputDevice& rOutDev, const Point& rStartPos, Degree10 n if( rOutDev.GetConnectMetaFile() ) rOutDev.Push(); Point aStartPos( rStartPos ); - if ( IsVertical() ) + if ( IsEffectivelyVertical() ) { aStartPos.AdjustX(GetPaperSize().Width() ); - aStartPos = Rotate( aStartPos, nOrientation, rStartPos ); + rStartPos.RotateAround(aStartPos, nOrientation); } - pImpEditEngine->Paint(rOutDev, aBigRect, aStartPos, false, nOrientation); - if( rOutDev.GetConnectMetaFile() ) + getImpl().Paint(rOutDev, aBigRect, aStartPos, false, nOrientation); + if (rOutDev.GetConnectMetaFile()) rOutDev.Pop(); } @@ -241,7 +244,7 @@ void EditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect, aOutRect = rOutDev.PixelToLogic( aOutRect ); Point aStartPos; - if ( !IsVertical() ) + if ( !IsEffectivelyVertical() ) { aStartPos.setX( aOutRect.Left() - rStartDocPos.X() ); aStartPos.setY( aOutRect.Top() - rStartDocPos.Y() ); @@ -283,7 +286,7 @@ void EditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect, } } - pImpEditEngine->Paint( rOutDev, aOutRect, aStartPos ); + getImpl().Paint(rOutDev, aOutRect, aStartPos); if ( bMetafile ) rOutDev.Pop(); @@ -295,27 +298,25 @@ void EditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect, void EditEngine::InsertView(EditView* pEditView, size_t nIndex) { + if (nIndex > getImpl().GetEditViews().size()) + nIndex = getImpl().GetEditViews().size(); - if ( nIndex > pImpEditEngine->GetEditViews().size() ) - nIndex = pImpEditEngine->GetEditViews().size(); - - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType& rViews = getImpl().GetEditViews(); rViews.insert(rViews.begin()+nIndex, pEditView); - EditSelection aStartSel = pImpEditEngine->GetEditDoc().GetStartPaM(); - pEditView->pImpEditView->SetEditSelection( aStartSel ); - if ( !pImpEditEngine->GetActiveView() ) - pImpEditEngine->SetActiveView( pEditView ); + EditSelection aStartSel = getImpl().GetEditDoc().GetStartPaM(); + pEditView->getImpl().SetEditSelection( aStartSel ); + if (!getImpl().GetActiveView()) + getImpl().SetActiveView(pEditView); - pEditView->pImpEditView->AddDragAndDropListeners(); + pEditView->getImpl().AddDragAndDropListeners(); } EditView* EditEngine::RemoveView( EditView* pView ) { - pView->HideCursor(); EditView* pRemoved = nullptr; - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType& rViews = getImpl().GetEditViews(); ImpEditEngine::ViewsType::iterator it = std::find(rViews.begin(), rViews.end(), pView); DBG_ASSERT( it != rViews.end(), "RemoveView with invalid index" ); @@ -323,12 +324,12 @@ EditView* EditEngine::RemoveView( EditView* pView ) { pRemoved = *it; rViews.erase(it); - if ( pImpEditEngine->GetActiveView() == pView ) + if (getImpl().GetActiveView() == pView) { - pImpEditEngine->SetActiveView( nullptr ); - pImpEditEngine->GetSelEngine().SetCurView( nullptr ); + getImpl().SetActiveView(nullptr); + getImpl().GetSelEngine().SetCurView(nullptr); } - pView->pImpEditView->RemoveDragAndDropListeners(); + pView->getImpl().RemoveDragAndDropListeners(); } return pRemoved; @@ -336,7 +337,7 @@ EditView* EditEngine::RemoveView( EditView* pView ) void EditEngine::RemoveView(size_t nIndex) { - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType& rViews = getImpl().GetEditViews(); if (nIndex >= rViews.size()) return; @@ -347,173 +348,171 @@ void EditEngine::RemoveView(size_t nIndex) EditView* EditEngine::GetView(size_t nIndex) const { - return pImpEditEngine->GetEditViews()[nIndex]; + return getImpl().GetEditViews()[nIndex]; } size_t EditEngine::GetViewCount() const { - return pImpEditEngine->GetEditViews().size(); + return getImpl().GetEditViews().size(); } bool EditEngine::HasView( EditView* pView ) const { - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType const& rViews = getImpl().GetEditViews(); return std::find(rViews.begin(), rViews.end(), pView) != rViews.end(); } EditView* EditEngine::GetActiveView() const { - return pImpEditEngine->GetActiveView(); + return getImpl().GetActiveView(); } void EditEngine::SetActiveView(EditView* pView) { - pImpEditEngine->SetActiveView(pView); + getImpl().SetActiveView(pView); } void EditEngine::SetDefTab( sal_uInt16 nDefTab ) { - pImpEditEngine->GetEditDoc().SetDefTab( nDefTab ); - if ( pImpEditEngine->IsFormatted() ) + getImpl().GetEditDoc().SetDefTab(nDefTab); + if (getImpl().IsFormatted()) { - pImpEditEngine->FormatFullDoc(); - pImpEditEngine->UpdateViews(); + getImpl().FormatFullDoc(); + getImpl().UpdateViews(); } } -void EditEngine::SetPaperSize( const Size& rNewSize ) +void EditEngine::SetPaperSize(const Size& rNewSize) { + Size aOldSize = getImpl().GetPaperSize(); + getImpl().SetValidPaperSize(rNewSize); + Size aNewSize = getImpl().GetPaperSize(); - Size aOldSize( pImpEditEngine->GetPaperSize() ); - pImpEditEngine->SetValidPaperSize( rNewSize ); - Size aNewSize( pImpEditEngine->GetPaperSize() ); - - bool bAutoPageSize = pImpEditEngine->GetStatus().AutoPageSize(); + bool bAutoPageSize = getImpl().GetStatus().AutoPageSize(); if ( !(bAutoPageSize || ( aNewSize.Width() != aOldSize.Width() )) ) return; - for (EditView* pView : pImpEditEngine->aEditViews) + for (EditView* pView : getImpl().maEditViews) { if ( bAutoPageSize ) - pView->pImpEditView->RecalcOutputArea(); - else if ( pView->pImpEditView->DoAutoSize() ) + pView->getImpl().RecalcOutputArea(); + else if (pView->getImpl().DoAutoSize()) { - pView->pImpEditView->ResetOutputArea( tools::Rectangle( - pView->pImpEditView->GetOutputArea().TopLeft(), aNewSize ) ); + pView->getImpl().ResetOutputArea(tools::Rectangle(pView->getImpl().GetOutputArea().TopLeft(), aNewSize)); } } - if ( bAutoPageSize || pImpEditEngine->IsFormatted() ) + if ( bAutoPageSize || getImpl().IsFormatted() ) { // Changing the width has no effect for AutoPageSize, as this is // determined by the text width. // Optimization first after Vobis delivery was enabled ... - pImpEditEngine->FormatFullDoc(); + getImpl().FormatFullDoc(); - pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() ); + getImpl().UpdateViews(getImpl().GetActiveView()); - if ( pImpEditEngine->GetUpdateMode() && pImpEditEngine->GetActiveView() ) - pImpEditEngine->pActiveView->ShowCursor( false, false ); + if (getImpl().IsUpdateLayout() && getImpl().GetActiveView()) + getImpl().mpActiveView->ShowCursor(false, false); } } const Size& EditEngine::GetPaperSize() const { - return pImpEditEngine->GetPaperSize(); + return getImpl().GetPaperSize(); } void EditEngine::SetVertical(bool bVertical) { - pImpEditEngine->SetVertical(bVertical); + getImpl().SetVertical(bVertical); } void EditEngine::SetRotation(TextRotation nRotation) { - pImpEditEngine->SetRotation(nRotation); + getImpl().SetRotation(nRotation); } TextRotation EditEngine::GetRotation() const { - return pImpEditEngine->GetRotation(); + return getImpl().GetRotation(); } -bool EditEngine::IsVertical() const +bool EditEngine::IsEffectivelyVertical() const { - return pImpEditEngine->IsVertical(); + return getImpl().IsEffectivelyVertical(); } bool EditEngine::IsTopToBottom() const { - return pImpEditEngine->IsTopToBottom(); + return getImpl().IsTopToBottom(); } -bool EditEngine::GetDirectVertical() const +bool EditEngine::GetVertical() const { - return pImpEditEngine->GetDirectVertical(); + return getImpl().GetVertical(); } void EditEngine::SetTextColumns(sal_Int16 nColumns, sal_Int32 nSpacing) { - pImpEditEngine->SetTextColumns(nColumns, nSpacing); + getImpl().SetTextColumns(nColumns, nSpacing); } void EditEngine::SetFixedCellHeight( bool bUseFixedCellHeight ) { - pImpEditEngine->SetFixedCellHeight( bUseFixedCellHeight ); + getImpl().SetFixedCellHeight(bUseFixedCellHeight); } void EditEngine::SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) { - pImpEditEngine->SetDefaultHorizontalTextDirection( eHTextDir ); + getImpl().SetDefaultHorizontalTextDirection(eHTextDir); } EEHorizontalTextDirection EditEngine::GetDefaultHorizontalTextDirection() const { - return pImpEditEngine->GetDefaultHorizontalTextDirection(); + return getImpl().GetDefaultHorizontalTextDirection(); } SvtScriptType EditEngine::GetScriptType( const ESelection& rSelection ) const { - EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) ); - return pImpEditEngine->GetItemScriptType( aSel ); + EditSelection aSel(getImpl().CreateSel(rSelection)); + return getImpl().GetItemScriptType( aSel ); } -LanguageType EditEngine::GetLanguage(const EditPaM& rPaM) const +editeng::LanguageSpan EditEngine::GetLanguage(const EditPaM& rPaM) const { - return pImpEditEngine->GetLanguage(rPaM); + return getImpl().GetLanguage(rPaM); } -LanguageType EditEngine::GetLanguage( sal_Int32 nPara, sal_Int32 nPos ) const +editeng::LanguageSpan EditEngine::GetLanguage( sal_Int32 nPara, sal_Int32 nPos ) const { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject( nPara ); DBG_ASSERT( pNode, "GetLanguage - nPara is invalid!" ); - return pNode ? pImpEditEngine->GetLanguage( EditPaM( pNode, nPos ) ) : LANGUAGE_DONTKNOW; + return pNode ? getImpl().GetLanguage( EditPaM( pNode, nPos ) ) : editeng::LanguageSpan{}; } void EditEngine::TransliterateText( const ESelection& rSelection, TransliterationFlags nTransliterationMode ) { - pImpEditEngine->TransliterateText( pImpEditEngine->CreateSel( rSelection ), nTransliterationMode ); + getImpl().TransliterateText(getImpl().CreateSel( rSelection ), nTransliterationMode); } EditSelection EditEngine::TransliterateText(const EditSelection& rSelection, TransliterationFlags nTransliterationMode) { - return pImpEditEngine->TransliterateText(rSelection, nTransliterationMode); + return getImpl().TransliterateText(rSelection, nTransliterationMode); } void EditEngine::SetAsianCompressionMode( CharCompressType n ) { - pImpEditEngine->SetAsianCompressionMode( n ); + getImpl().SetAsianCompressionMode( n ); } void EditEngine::SetKernAsianPunctuation( bool b ) { - pImpEditEngine->SetKernAsianPunctuation( b ); + getImpl().SetKernAsianPunctuation( b ); } void EditEngine::SetAddExtLeading( bool b ) { - pImpEditEngine->SetAddExtLeading( b ); + getImpl().SetAddExtLeading( b ); } void EditEngine::SetPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ) @@ -535,116 +534,115 @@ void EditEngine::SetPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, const b } TextRanger* pRanger = new TextRanger( rPolyPolygon, pLinePolyPolygon, 30, 2, 2, bSimple, true ); - pImpEditEngine->SetTextRanger( std::unique_ptr<TextRanger>(pRanger) ); - pImpEditEngine->SetPaperSize( pRanger->GetBoundRect().GetSize() ); + getImpl().SetTextRanger( std::unique_ptr<TextRanger>(pRanger) ); + getImpl().SetPaperSize( pRanger->GetBoundRect().GetSize() ); } void EditEngine::ClearPolygon() { - pImpEditEngine->SetTextRanger( nullptr ); + getImpl().SetTextRanger( nullptr ); } const Size& EditEngine::GetMinAutoPaperSize() const { - return pImpEditEngine->GetMinAutoPaperSize(); + return getImpl().GetMinAutoPaperSize(); } void EditEngine::SetMinAutoPaperSize( const Size& rSz ) { - pImpEditEngine->SetMinAutoPaperSize( rSz ); + getImpl().SetMinAutoPaperSize( rSz ); } const Size& EditEngine::GetMaxAutoPaperSize() const { - return pImpEditEngine->GetMaxAutoPaperSize(); + return getImpl().GetMaxAutoPaperSize(); } -void EditEngine::SetMaxAutoPaperSize( const Size& rSz ) +void EditEngine::SetMaxAutoPaperSize(const Size& rSize) { - pImpEditEngine->SetMaxAutoPaperSize( rSz ); + getImpl().SetMaxAutoPaperSize(rSize); } void EditEngine::SetMinColumnWrapHeight(tools::Long nVal) { - pImpEditEngine->SetMinColumnWrapHeight(nVal); + getImpl().SetMinColumnWrapHeight(nVal); } OUString EditEngine::GetText( LineEnd eEnd ) const { - return pImpEditEngine->GetEditDoc().GetText( eEnd ); + return getImpl().GetEditDoc().GetText(eEnd); } OUString EditEngine::GetText( const ESelection& rESelection ) const { - EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) ); - return pImpEditEngine->GetSelected( aSel ); + EditSelection aSel = getImpl().CreateSel(rESelection); + return getImpl().GetSelected(aSel); } -sal_uInt32 EditEngine::GetTextLen() const +sal_Int32 EditEngine::GetTextLen() const { - return pImpEditEngine->GetEditDoc().GetTextLen(); + return getImpl().GetEditDoc().GetTextLen(); } sal_Int32 EditEngine::GetParagraphCount() const { - return pImpEditEngine->aEditDoc.Count(); + return getImpl().maEditDoc.Count(); +} + +void EditEngine::ensureDocumentFormatted() const +{ + if (!getImpl().IsFormatted()) + getImpl().FormatDoc(); } sal_Int32 EditEngine::GetLineCount( sal_Int32 nParagraph ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineCount( nParagraph ); + ensureDocumentFormatted(); + return getImpl().GetLineCount(nParagraph); } sal_Int32 EditEngine::GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineLen( nParagraph, nLine ); + ensureDocumentFormatted(); + return getImpl().GetLineLen(nParagraph, nLine); } void EditEngine::GetLineBoundaries( /*out*/sal_Int32& rStart, /*out*/sal_Int32& rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineBoundaries( rStart, rEnd, nParagraph, nLine ); + ensureDocumentFormatted(); + return getImpl().GetLineBoundaries(rStart, rEnd, nParagraph, nLine); } sal_Int32 EditEngine::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineNumberAtIndex( nPara, nIndex ); + ensureDocumentFormatted(); + return getImpl().GetLineNumberAtIndex(nPara, nIndex); } sal_uInt32 EditEngine::GetLineHeight( sal_Int32 nParagraph ) { // If someone calls GetLineHeight() with an empty Engine. - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineHeight( nParagraph, 0 ); + ensureDocumentFormatted(); + return getImpl().GetLineHeight( nParagraph, 0 ); } tools::Rectangle EditEngine::GetParaBounds( sal_Int32 nPara ) { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - + ensureDocumentFormatted(); Point aPnt = GetDocPosTopLeft( nPara ); - if( IsVertical() ) + if( IsEffectivelyVertical() ) { - sal_Int32 nTextHeight = pImpEditEngine->GetTextHeight(); - sal_Int32 nParaWidth = pImpEditEngine->CalcParaWidth( nPara, true ); - sal_uLong nParaHeight = pImpEditEngine->GetParaHeight( nPara ); + sal_Int32 nTextHeight = getImpl().GetTextHeight(); + sal_Int32 nParaWidth = getImpl().CalcParaWidth(nPara, true); + sal_Int32 nParaHeight = getImpl().GetParaHeight(nPara); return tools::Rectangle( nTextHeight - aPnt.Y() - nParaHeight, 0, nTextHeight - aPnt.Y(), nParaWidth ); } else { - sal_Int32 nParaWidth = pImpEditEngine->CalcParaWidth( nPara, true ); - sal_uLong nParaHeight = pImpEditEngine->GetParaHeight( nPara ); + sal_Int32 nParaWidth = getImpl().CalcParaWidth( nPara, true ); + sal_Int32 nParaHeight = getImpl().GetParaHeight( nPara ); return tools::Rectangle( 0, aPnt.Y(), nParaWidth, aPnt.Y() + nParaHeight ); } @@ -652,119 +650,112 @@ tools::Rectangle EditEngine::GetParaBounds( sal_Int32 nPara ) sal_uInt32 EditEngine::GetTextHeight( sal_Int32 nParagraph ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - sal_uInt32 nHeight = pImpEditEngine->GetParaHeight( nParagraph ); + ensureDocumentFormatted(); + sal_uInt32 nHeight = getImpl().GetParaHeight(nParagraph); return nHeight; } OUString EditEngine::GetWord( sal_Int32 nPara, sal_Int32 nIndex ) { ESelection aESel( nPara, nIndex, nPara, nIndex ); - EditSelection aSel( pImpEditEngine->CreateSel( aESel ) ); - aSel = pImpEditEngine->SelectWord( aSel ); - return pImpEditEngine->GetSelected( aSel ); + EditSelection aSel(getImpl().CreateSel(aESel)); + aSel = getImpl().SelectWord(aSel); + return getImpl().GetSelected(aSel); } ESelection EditEngine::GetWord( const ESelection& rSelection, sal_uInt16 nWordType ) const { // ImpEditEngine-Iteration-Methods should be const! - EditEngine* pE = const_cast<EditEngine*>(this); + EditEngine* pNonConstEditEngine = const_cast<EditEngine*>(this); - EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) ); - aSel = pE->pImpEditEngine->SelectWord( aSel, nWordType ); - return pE->pImpEditEngine->CreateESel( aSel ); -} - -void EditEngine::CursorMoved(const ContentNode* pPrevNode) -{ - pImpEditEngine->CursorMoved(pPrevNode); + EditSelection aSel(pNonConstEditEngine->getImpl().CreateSel( rSelection ) ); + aSel = pNonConstEditEngine->getImpl().SelectWord( aSel, nWordType ); + return pNonConstEditEngine->getImpl().CreateESel( aSel ); } void EditEngine::CheckIdleFormatter() { - pImpEditEngine->CheckIdleFormatter(); + getImpl().CheckIdleFormatter(); } bool EditEngine::IsIdleFormatterActive() const { - return pImpEditEngine->aIdleFormatter.IsActive(); + return getImpl().maIdleFormatter.IsActive(); } ParaPortion* EditEngine::FindParaPortion(ContentNode const * pNode) { - return &pImpEditEngine->FindParaPortion(pNode); + return getImpl().FindParaPortion(pNode); } const ParaPortion* EditEngine::FindParaPortion(ContentNode const * pNode) const { - return &pImpEditEngine->FindParaPortion(pNode); + return getImpl().FindParaPortion(pNode); } const ParaPortion* EditEngine::GetPrevVisPortion(const ParaPortion* pCurPortion) const { - return pImpEditEngine->GetPrevVisPortion(pCurPortion); + return getImpl().GetPrevVisPortion(pCurPortion); } SvtScriptType EditEngine::GetScriptType(const EditSelection& rSel) const { - return pImpEditEngine->GetItemScriptType(rSel); + return getImpl().GetItemScriptType(rSel); } void EditEngine::RemoveParaPortion(sal_Int32 nNode) { - pImpEditEngine->GetParaPortions().Remove(nNode); + getImpl().GetParaPortions().Remove(nNode); } void EditEngine::SetCallParaInsertedOrDeleted(bool b) { - pImpEditEngine->SetCallParaInsertedOrDeleted(b); + getImpl().SetCallParaInsertedOrDeleted(b); } bool EditEngine::IsCallParaInsertedOrDeleted() const { - return pImpEditEngine->IsCallParaInsertedOrDeleted(); + return getImpl().IsCallParaInsertedOrDeleted(); } void EditEngine::AppendDeletedNodeInfo(DeletedNodeInfo* pInfo) { - pImpEditEngine->aDeletedNodes.push_back(std::unique_ptr<DeletedNodeInfo>(pInfo)); + getImpl().maDeletedNodes.push_back(std::unique_ptr<DeletedNodeInfo>(pInfo)); } void EditEngine::UpdateSelections() { - pImpEditEngine->UpdateSelections(); + getImpl().UpdateSelections(); } -void EditEngine::InsertContent(ContentNode* pNode, sal_Int32 nPos) +void EditEngine::InsertContent(std::unique_ptr<ContentNode> pNode, sal_Int32 nPos) { - pImpEditEngine->InsertContent(pNode, nPos); + getImpl().InsertContent(std::move(pNode), nPos); } EditPaM EditEngine::SplitContent(sal_Int32 nNode, sal_Int32 nSepPos) { - return pImpEditEngine->SplitContent(nNode, nSepPos); + return getImpl().SplitContent(nNode, nSepPos); } EditPaM EditEngine::ConnectContents(sal_Int32 nLeftNode, bool bBackward) { - return pImpEditEngine->ConnectContents(nLeftNode, bBackward); + return getImpl().ConnectContents(nLeftNode, bBackward); } void EditEngine::InsertFeature(const EditSelection& rEditSelection, const SfxPoolItem& rItem) { - pImpEditEngine->ImpInsertFeature(rEditSelection, rItem); + getImpl().ImpInsertFeature(rEditSelection, rItem); } EditSelection EditEngine::MoveParagraphs(const Range& rParagraphs, sal_Int32 nNewPos) { - return pImpEditEngine->MoveParagraphs(rParagraphs, nNewPos, nullptr); + return getImpl().MoveParagraphs(rParagraphs, nNewPos, nullptr); } void EditEngine::RemoveCharAttribs(sal_Int32 nPara, sal_uInt16 nWhich, bool bRemoveFeatures) { - pImpEditEngine->RemoveCharAttribs(nPara, nWhich, bRemoveFeatures); + getImpl().RemoveCharAttribs(nPara, nWhich, bRemoveFeatures); } void EditEngine::RemoveCharAttribs(const EditSelection& rSel, bool bRemoveParaAttribs, sal_uInt16 nWhich) @@ -772,228 +763,226 @@ void EditEngine::RemoveCharAttribs(const EditSelection& rSel, bool bRemoveParaAt const EERemoveParaAttribsMode eMode = bRemoveParaAttribs? EERemoveParaAttribsMode::RemoveAll : EERemoveParaAttribsMode::RemoveCharItems; - pImpEditEngine->RemoveCharAttribs(rSel, eMode, nWhich); + getImpl().RemoveCharAttribs(rSel, eMode, nWhich); } void EditEngine::RemoveCharAttribs(const EditSelection& rSel, EERemoveParaAttribsMode eMode, sal_uInt16 nWhich) { - pImpEditEngine->RemoveCharAttribs(rSel, eMode, nWhich); + getImpl().RemoveCharAttribs(rSel, eMode, nWhich); } EditEngine::ViewsType& EditEngine::GetEditViews() { - return pImpEditEngine->GetEditViews(); + return getImpl().GetEditViews(); } const EditEngine::ViewsType& EditEngine::GetEditViews() const { - return pImpEditEngine->GetEditViews(); + return getImpl().GetEditViews(); } void EditEngine::SetUndoMode(bool b) { - pImpEditEngine->SetUndoMode(b); + getImpl().SetUndoMode(b); } -void EditEngine::FormatAndUpdate(EditView* pCurView, bool bCalledFromUndo) +void EditEngine::FormatAndLayout(EditView* pCurView, bool bCalledFromUndo) { - pImpEditEngine->FormatAndUpdate(pCurView, bCalledFromUndo); + getImpl().FormatAndLayout(pCurView, bCalledFromUndo); } void EditEngine::Undo(EditView* pView) { - pImpEditEngine->Undo(pView); + getImpl().Undo(pView); } void EditEngine::Redo(EditView* pView) { - pImpEditEngine->Redo(pView); + getImpl().Redo(pView); } uno::Reference<datatransfer::XTransferable> EditEngine::CreateTransferable(const EditSelection& rSelection) { - return pImpEditEngine->CreateTransferable(rSelection); + return getImpl().CreateTransferable(rSelection); } void EditEngine::ParaAttribsToCharAttribs(ContentNode* pNode) { - pImpEditEngine->ParaAttribsToCharAttribs(pNode); + getImpl().ParaAttribsToCharAttribs(pNode); } EditPaM EditEngine::CreateEditPaM(const EPaM& rEPaM) { - return pImpEditEngine->CreateEditPaM(rEPaM); + return getImpl().CreateEditPaM(rEPaM); } EditPaM EditEngine::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward) { - return pImpEditEngine->ImpConnectParagraphs(pLeft, pRight, bBackward); + return getImpl().ImpConnectParagraphs(pLeft, pRight, bBackward); } EditPaM EditEngine::InsertField(const EditSelection& rEditSelection, const SvxFieldItem& rFld) { - return pImpEditEngine->InsertField(rEditSelection, rFld); + return getImpl().InsertField(rEditSelection, rFld); } EditPaM EditEngine::InsertText(const EditSelection& aCurEditSelection, const OUString& rStr) { - return pImpEditEngine->InsertText(aCurEditSelection, rStr); + return getImpl().InsertText(aCurEditSelection, rStr); } EditSelection EditEngine::InsertText(const EditTextObject& rTextObject, const EditSelection& rSel) { - return pImpEditEngine->InsertText(rTextObject, rSel); + return getImpl().InsertText(rTextObject, rSel); } EditSelection EditEngine::InsertText( uno::Reference<datatransfer::XTransferable > const & rxDataObj, - const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial) + const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial, SotClipboardFormatId format) { - return pImpEditEngine->PasteText(rxDataObj, rBaseURL, rPaM, bUseSpecial); + return getImpl().PasteText(rxDataObj, rBaseURL, rPaM, bUseSpecial, format); } EditPaM EditEngine::EndOfWord(const EditPaM& rPaM) { - return pImpEditEngine->EndOfWord(rPaM); + return getImpl().EndOfWord(rPaM); } EditPaM EditEngine::GetPaM(const Point& aDocPos, bool bSmart) { - return pImpEditEngine->GetPaM(aDocPos, bSmart); + return getImpl().GetPaM(aDocPos, bSmart); } EditSelection EditEngine::SelectWord( const EditSelection& rCurSelection, sal_Int16 nWordType) { - return pImpEditEngine->SelectWord(rCurSelection, nWordType); + return getImpl().SelectWord(rCurSelection, nWordType); } -tools::Long EditEngine::GetXPos( - const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart) const +tools::Long EditEngine::GetXPos(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nIndex, bool bPreferPortionStart) const { - return pImpEditEngine->GetXPos(pParaPortion, pLine, nIndex, bPreferPortionStart); + return getImpl().GetXPos(rParaPortion, rLine, nIndex, bPreferPortionStart); } -Range EditEngine::GetLineXPosStartEnd( - const ParaPortion* pParaPortion, const EditLine* pLine) const +Range EditEngine::GetLineXPosStartEnd(ParaPortion const& rParaPortion, EditLine const& rLine) const { - return pImpEditEngine->GetLineXPosStartEnd(pParaPortion, pLine); + return getImpl().GetLineXPosStartEnd(rParaPortion, rLine); } bool EditEngine::IsFormatted() const { - return pImpEditEngine->IsFormatted(); + return getImpl().IsFormatted(); } EditPaM EditEngine::CursorLeft(const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode) { - return pImpEditEngine->CursorLeft(rPaM, nCharacterIteratorMode); + return getImpl().CursorLeft(rPaM, nCharacterIteratorMode); } EditPaM EditEngine::CursorRight(const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode) { - return pImpEditEngine->CursorRight(rPaM, nCharacterIteratorMode); + return getImpl().CursorRight(rPaM, nCharacterIteratorMode); } InternalEditStatus& EditEngine::GetInternalEditStatus() { - return pImpEditEngine->GetStatus(); + return getImpl().GetStatus(); } EditDoc& EditEngine::GetEditDoc() { - return pImpEditEngine->GetEditDoc(); + return getImpl().GetEditDoc(); } const EditDoc& EditEngine::GetEditDoc() const { - return pImpEditEngine->GetEditDoc(); + return getImpl().GetEditDoc(); } void EditEngine::dumpAsXmlEditDoc(xmlTextWriterPtr pWriter) const { - pImpEditEngine->GetEditDoc().dumpAsXml(pWriter); + getImpl().GetEditDoc().dumpAsXml(pWriter); } ParaPortionList& EditEngine::GetParaPortions() { - return pImpEditEngine->GetParaPortions(); + return getImpl().GetParaPortions(); } const ParaPortionList& EditEngine::GetParaPortions() const { - return pImpEditEngine->GetParaPortions(); + return getImpl().GetParaPortions(); } void EditEngine::SeekCursor(ContentNode* pNode, sal_Int32 nPos, SvxFont& rFont) { - pImpEditEngine->SeekCursor(pNode, nPos, rFont); + getImpl().SeekCursor(pNode, nPos, rFont); } EditPaM EditEngine::DeleteSelection(const EditSelection& rSel) { - return pImpEditEngine->ImpDeleteSelection(rSel); + return getImpl().ImpDeleteSelection(rSel); } -ESelection EditEngine::CreateESelection(const EditSelection& rSel) +ESelection EditEngine::CreateESelection(const EditSelection& rSel) const { - return pImpEditEngine->CreateESel(rSel); + return getImpl().CreateESel(rSel); } EditSelection EditEngine::CreateSelection(const ESelection& rSel) { - return pImpEditEngine->CreateSel(rSel); + return getImpl().CreateSel(rSel); } const SfxItemSet& EditEngine::GetBaseParaAttribs(sal_Int32 nPara) const { - return pImpEditEngine->GetParaAttribs(nPara); + return getImpl().GetParaAttribs(nPara); } void EditEngine::SetParaAttribsOnly(sal_Int32 nPara, const SfxItemSet& rSet) { - pImpEditEngine->SetParaAttribs(nPara, rSet); + getImpl().SetParaAttribs(nPara, rSet); } void EditEngine::SetAttribs(const EditSelection& rSel, const SfxItemSet& rSet, SetAttribsMode nSpecial) { - pImpEditEngine->SetAttribs(rSel, rSet, nSpecial); + getImpl().SetAttribs(rSel, rSet, nSpecial); } OUString EditEngine::GetSelected(const EditSelection& rSel) const { - return pImpEditEngine->GetSelected(rSel); + return getImpl().GetSelected(rSel); } EditPaM EditEngine::DeleteSelected(const EditSelection& rSel) { - return pImpEditEngine->DeleteSelected(rSel); + return getImpl().DeleteSelected(rSel); } void EditEngine::HandleBeginPasteOrDrop(PasteOrDropInfos& rInfos) { - pImpEditEngine->aBeginPasteOrDropHdl.Call(rInfos); + getImpl().maBeginPasteOrDropHdl.Call(rInfos); } void EditEngine::HandleEndPasteOrDrop(PasteOrDropInfos& rInfos) { - pImpEditEngine->aEndPasteOrDropHdl.Call(rInfos); + getImpl().maEndPasteOrDropHdl.Call(rInfos); } bool EditEngine::HasText() const { - return pImpEditEngine->ImplHasText(); + return getImpl().ImplHasText(); } const EditSelectionEngine& EditEngine::GetSelectionEngine() const { - return pImpEditEngine->aSelEngine; + return getImpl().maSelEngine; } void EditEngine::SetInSelectionMode(bool b) { - pImpEditEngine->bInSelection = b; + getImpl().mbInSelection = b; } bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, vcl::Window const * pFrameWin ) @@ -1007,15 +996,15 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v bool bAllowIdle = true; bool bReadOnly = pEditView->IsReadOnly(); - GetCursorFlags nNewCursorFlags = GetCursorFlags::NONE; + CursorFlags aNewCursorFlags; bool bSetCursorFlags = true; - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); DBG_ASSERT( !aCurSel.IsInvalid(), "Blinde Selection in EditEngine::PostKeyEvent" ); - OUString aAutoText( pImpEditEngine->GetAutoCompleteText() ); - if (!pImpEditEngine->GetAutoCompleteText().isEmpty()) - pImpEditEngine->SetAutoCompleteText(OUString(), true); + OUString aAutoText(getImpl().GetAutoCompleteText()); + if (!getImpl().GetAutoCompleteText().isEmpty()) + getImpl().SetAutoCompleteText(OUString(), true); sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction(); @@ -1053,7 +1042,7 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v sal_Int32 nParas = GetParagraphCount(); Point aPos; Point aViewStart( pEditView->GetOutputArea().TopLeft() ); - tools::Long n20 = 40 * pImpEditEngine->nOnePixelInRef; + tools::Long n20 = 40 * getImpl().mnOnePixelInRef; for ( sal_Int32 n = 0; n < nParas; n++ ) { tools::Long nH = GetTextHeight( n ); @@ -1079,7 +1068,7 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v aInfo.append(bDebugPaint ? "On" : "Off"); std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pEditView->GetWindow()->GetFrameWeld(), VclMessageType::Info, VclButtonsType::Ok, - OStringToOUString(aInfo.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US))); + OStringToOUString(aInfo, RTL_TEXTENCODING_ASCII_US))); xInfoBox->run(); } @@ -1121,25 +1110,25 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { if ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ) { - if ( pImpEditEngine->DoVisualCursorTraveling() && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) ) + if ( ImpEditEngine::DoVisualCursorTraveling() && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) ) bSetCursorFlags = false; // Will be manipulated within visual cursor move - aCurSel = pImpEditEngine->MoveCursor( rKeyEvent, pEditView ); + aCurSel = getImpl().MoveCursor( rKeyEvent, pEditView ); if ( aCurSel.HasRange() ) { Reference<css::datatransfer::clipboard::XClipboard> aSelection(GetSystemPrimarySelection()); - pEditView->pImpEditView->CutCopy( aSelection, false ); + pEditView->getImpl().CutCopy( aSelection, false ); } bMoved = true; if ( nCode == KEY_HOME ) - nNewCursorFlags |= GetCursorFlags::StartOfLine; + aNewCursorFlags.bStartOfLine = true; else if ( nCode == KEY_END ) - nNewCursorFlags |= GetCursorFlags::EndOfLine; + aNewCursorFlags.bEndOfLine = true; } #if OSL_DEBUG_LEVEL > 1 - GetLanguage( pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex() ); + GetLanguage(getImpl().GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex()); #endif } break; @@ -1154,7 +1143,7 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { // check if we are behind a bullet and using the backspace key ContentNode *pNode = aCurSel.Min().GetNode(); - const SvxNumberFormat *pFmt = pImpEditEngine->GetNumberFormat( pNode ); + const SvxNumberFormat *pFmt = getImpl().GetNumberFormat( pNode ); if (pFmt && nCode == KEY_BACKSPACE && !aCurSel.HasRange() && aCurSel.Min().GetIndex() == 0) { @@ -1162,22 +1151,22 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v // Otherwise continue as usual. - sal_Int32 nPara = pImpEditEngine->GetEditDoc().GetPos( pNode ); - SfxBoolItem aBulletState( pImpEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) ); + sal_Int32 nPara = getImpl().GetEditDoc().GetPos( pNode ); + SfxBoolItem aBulletState(getImpl().GetParaAttrib(nPara, EE_PARA_BULLETSTATE)); if ( aBulletState.GetValue() ) { aBulletState.SetValue( false ); - SfxItemSet aSet( pImpEditEngine->GetParaAttribs( nPara ) ); + SfxItemSet aSet( getImpl().GetParaAttribs( nPara ) ); aSet.Put( aBulletState ); - pImpEditEngine->SetParaAttribs( nPara, aSet ); + getImpl().SetParaAttribs( nPara, aSet ); // have this and the following paragraphs formatted and repainted. // (not painting a numbering in the list may cause the following // numberings to have different numbers than before and thus the // length may have changed as well ) - pImpEditEngine->FormatAndUpdate( pImpEditEngine->GetActiveView() ); + getImpl().FormatAndLayout(getImpl().GetActiveView()); break; } @@ -1211,10 +1200,10 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v break; } - pEditView->pImpEditView->DrawSelectionXOR(); - pImpEditEngine->UndoActionStart( EDITUNDO_DELETE ); - aCurSel = pImpEditEngine->DeleteLeftOrRight( aCurSel, nDel, nMode ); - pImpEditEngine->UndoActionEnd(); + pEditView->getImpl().DrawSelectionXOR(); + getImpl().UndoActionStart( EDITUNDO_DELETE ); + aCurSel = getImpl().DeleteLeftOrRight( aCurSel, nDel, nMode ); + getImpl().UndoActionEnd(); bModified = true; bAllowIdle = false; } @@ -1229,12 +1218,12 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { bool bSel = pEditView->HasSelection(); if ( bSel ) - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); - if ( pImpEditEngine->GetStatus().DoAutoCorrect() ) - aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = pImpEditEngine->InsertTab( aCurSel ); + getImpl().UndoActionStart( EDITUNDO_INSERT ); + if ( getImpl().GetStatus().DoAutoCorrect() ) + aCurSel = getImpl().AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); + aCurSel = getImpl().InsertTab( aCurSel ); if ( bSel ) - pImpEditEngine->UndoActionEnd(); + getImpl().UndoActionEnd(); bModified = true; } } @@ -1246,33 +1235,33 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { if ( !bReadOnly ) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) { - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + getImpl().UndoActionStart( EDITUNDO_INSERT ); if ( rKeyEvent.GetKeyCode().IsShift() ) { - aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = pImpEditEngine->InsertLineBreak( aCurSel ); + aCurSel = getImpl().AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); + aCurSel = getImpl().InsertLineBreak( aCurSel ); } else { if (aAutoText.isEmpty()) { - if ( pImpEditEngine->GetStatus().DoAutoCorrect() ) - aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = pImpEditEngine->InsertParaBreak( aCurSel ); + if (getImpl().GetStatus().DoAutoCorrect()) + aCurSel = getImpl().AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); + aCurSel = getImpl().InsertParaBreak( aCurSel ); } else { DBG_ASSERT( !aCurSel.HasRange(), "Selection on complete?!" ); - EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) ); - aCurSel = pImpEditEngine->InsertText( - EditSelection( aStart, aCurSel.Max() ), aAutoText ); - pImpEditEngine->SetAutoCompleteText( OUString(), true ); + EditPaM aStart = getImpl().WordLeft(aCurSel.Max()); + EditSelection aSelection(aStart, aCurSel.Max()); + aCurSel = getImpl().InsertText(aSelection, aAutoText); + getImpl().SetAutoCompleteText( OUString(), true ); } } - pImpEditEngine->UndoActionEnd(); + getImpl().UndoActionEnd(); bModified = true; } } @@ -1301,50 +1290,50 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v if ( !bReadOnly && IsSimpleCharInput( rKeyEvent ) ) { sal_Unicode nCharCode = rKeyEvent.GetCharCode(); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); // Autocorrection? - if ( ( pImpEditEngine->GetStatus().DoAutoCorrect() ) && - ( SvxAutoCorrect::IsAutoCorrectChar( nCharCode ) || - pImpEditEngine->IsNbspRunNext() ) ) + if ((getImpl().GetStatus().DoAutoCorrect()) && + (SvxAutoCorrect::IsAutoCorrectChar(nCharCode) || + getImpl().IsNbspRunNext())) { - aCurSel = pImpEditEngine->AutoCorrect( + aCurSel = getImpl().AutoCorrect( aCurSel, nCharCode, !pEditView->IsInsertMode(), pFrameWin ); } else { - aCurSel = pImpEditEngine->InsertTextUserInput( aCurSel, nCharCode, !pEditView->IsInsertMode() ); + aCurSel = getImpl().InsertTextUserInput( aCurSel, nCharCode, !pEditView->IsInsertMode() ); } // AutoComplete ??? - if ( pImpEditEngine->GetStatus().DoAutoComplete() && ( nCharCode != ' ' ) ) + if ( getImpl().GetStatus().DoAutoComplete() && ( nCharCode != ' ' ) ) { // Only at end of word... sal_Int32 nIndex = aCurSel.Max().GetIndex(); - if ( ( nIndex >= aCurSel.Max().GetNode()->Len() ) || - ( pImpEditEngine->aWordDelimiters.indexOf( aCurSel.Max().GetNode()->GetChar( nIndex ) ) != -1 ) ) + if ((nIndex >= aCurSel.Max().GetNode()->Len()) || + (getImpl().maWordDelimiters.indexOf(aCurSel.Max().GetNode()->GetChar(nIndex)) != -1)) { - EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) ); - OUString aWord = pImpEditEngine->GetSelected( EditSelection( aStart, aCurSel.Max() ) ); + EditPaM aStart(getImpl().WordLeft(aCurSel.Max())); + OUString aWord = getImpl().GetSelected(EditSelection(aStart, aCurSel.Max())); if ( aWord.getLength() >= 3 ) { OUString aComplete; - LanguageType eLang = pImpEditEngine->GetLanguage( EditPaM( aStart.GetNode(), aStart.GetIndex()+1)); + LanguageType eLang = getImpl().GetLanguage(EditPaM( aStart.GetNode(), aStart.GetIndex()+1)).nLang; LanguageTag aLanguageTag( eLang); - if (!pImpEditEngine->xLocaleDataWrapper.isInitialized()) - pImpEditEngine->xLocaleDataWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), aLanguageTag); + if (!getImpl().mxLocaleDataWrapper.isInitialized()) + getImpl().mxLocaleDataWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), aLanguageTag); else - pImpEditEngine->xLocaleDataWrapper.changeLocale( aLanguageTag); + getImpl().mxLocaleDataWrapper.changeLocale( aLanguageTag); - if (!pImpEditEngine->xTransliterationWrapper.isInitialized()) - pImpEditEngine->xTransliterationWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), eLang); + if (!getImpl().mxTransliterationWrapper.isInitialized()) + getImpl().mxTransliterationWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), eLang); else - pImpEditEngine->xTransliterationWrapper.changeLocale( eLang); + getImpl().mxTransliterationWrapper.changeLocale( eLang); - const ::utl::TransliterationWrapper* pTransliteration = pImpEditEngine->xTransliterationWrapper.get(); - Sequence< i18n::CalendarItem2 > xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarDays(); + const ::utl::TransliterationWrapper* pTransliteration = getImpl().mxTransliterationWrapper.get(); + Sequence< i18n::CalendarItem2 > xItem = getImpl().mxLocaleDataWrapper->getDefaultCalendarDays(); sal_Int32 nCount = xItem.getLength(); - const i18n::CalendarItem2* pArr = xItem.getArray(); + const i18n::CalendarItem2* pArr = xItem.getConstArray(); for( sal_Int32 n = 0; n <= nCount; ++n ) { const OUString& rDay = pArr[n].FullName; @@ -1357,9 +1346,9 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v if ( aComplete.isEmpty() ) { - xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarMonths(); + xItem = getImpl().mxLocaleDataWrapper->getDefaultCalendarMonths(); sal_Int32 nMonthCount = xItem.getLength(); - const i18n::CalendarItem2* pMonthArr = xItem.getArray(); + const i18n::CalendarItem2* pMonthArr = xItem.getConstArray(); for( sal_Int32 n = 0; n <= nMonthCount; ++n ) { const OUString& rMon = pMonthArr[n].FullName; @@ -1373,10 +1362,10 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v if( !aComplete.isEmpty() && ( ( aWord.getLength() + 1 ) < aComplete.getLength() ) ) { - pImpEditEngine->SetAutoCompleteText( aComplete, false ); - Point aPos = pImpEditEngine->PaMtoEditCursor( aCurSel.Max() ).TopLeft(); - aPos = pEditView->pImpEditView->GetWindowPos( aPos ); - aPos = pEditView->pImpEditView->GetWindow()->LogicToPixel( aPos ); + getImpl().SetAutoCompleteText( aComplete, false ); + Point aPos = getImpl().PaMtoEditCursor( aCurSel.Max() ).TopLeft(); + aPos = pEditView->getImpl().GetWindowPos( aPos ); + aPos = pEditView->getImpl().GetWindow()->LogicToPixel( aPos ); aPos = pEditView->GetWindow()->OutputToScreenPixel( aPos ); aPos.AdjustY( -3 ); Help::ShowQuickHelp( pEditView->GetWindow(), tools::Rectangle( aPos, Size( 1, 1 ) ), aComplete, QuickHelpFlags::Bottom|QuickHelpFlags::Left ); @@ -1392,44 +1381,44 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v } } - pEditView->pImpEditView->SetEditSelection( aCurSel ); + pEditView->getImpl().SetEditSelection( aCurSel ); if (comphelper::LibreOfficeKit::isActive()) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); } - pImpEditEngine->UpdateSelections(); + getImpl().UpdateSelections(); - if ( ( !IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) || - ( IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) )) + if ( ( !IsEffectivelyVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) || + ( IsEffectivelyVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) )) { - pEditView->pImpEditView->nTravelXPos = TRAVEL_X_DONTKNOW; + pEditView->getImpl().mnTravelXPos = TRAVEL_X_DONTKNOW; } if ( /* ( nCode != KEY_HOME ) && ( nCode != KEY_END ) && */ - ( !IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ) || - ( IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) )) + ( !IsEffectivelyVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ) || + ( IsEffectivelyVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) )) { - pEditView->pImpEditView->SetCursorBidiLevel( CURSOR_BIDILEVEL_DONTKNOW ); + pEditView->getImpl().SetCursorBidiLevel( CURSOR_BIDILEVEL_DONTKNOW ); } - if ( bSetCursorFlags ) - pEditView->pImpEditView->nExtraCursorFlags = nNewCursorFlags; + if (bSetCursorFlags) + pEditView->getImpl().maExtraCursorFlags = aNewCursorFlags; if ( bModified ) { DBG_ASSERT( !bReadOnly, "ReadOnly but modified???" ); // Idle-Formatter only when AnyInput. - if ( bAllowIdle && pImpEditEngine->GetStatus().UseIdleFormatter() + if ( bAllowIdle && getImpl().GetStatus().UseIdleFormatter() && Application::AnyInput( VclInputFlags::KEYBOARD) ) - pImpEditEngine->IdleFormatAndUpdate( pEditView ); + getImpl().IdleFormatAndLayout( pEditView ); else - pImpEditEngine->FormatAndUpdate( pEditView ); + getImpl().FormatAndLayout( pEditView ); } else if ( bMoved ) { - bool bGotoCursor = pEditView->pImpEditView->DoAutoScroll(); - pEditView->pImpEditView->ShowCursor( bGotoCursor, true ); - pImpEditEngine->CallStatusHdl(); + bool bGotoCursor = pEditView->getImpl().DoAutoScroll(); + pEditView->getImpl().ShowCursor( bGotoCursor, true ); + getImpl().CallStatusHdl(); } return bDone; @@ -1437,177 +1426,169 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v sal_uInt32 EditEngine::GetTextHeight() const { - - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - sal_uInt32 nHeight = !IsVertical() ? pImpEditEngine->GetTextHeight() : pImpEditEngine->CalcTextWidth( true ); + ensureDocumentFormatted(); + sal_uInt32 nHeight = !IsEffectivelyVertical() ? getImpl().GetTextHeight() : getImpl().CalcTextWidth( true ); return nHeight; } sal_uInt32 EditEngine::GetTextHeightNTP() const { + ensureDocumentFormatted(); - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - if ( IsVertical() ) - return pImpEditEngine->CalcTextWidth( true ); + if (IsEffectivelyVertical()) + return getImpl().CalcTextWidth(true); - return pImpEditEngine->GetTextHeightNTP(); + return getImpl().GetTextHeightNTP(); } sal_uInt32 EditEngine::CalcTextWidth() { - - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - sal_uInt32 nWidth = !IsVertical() ? pImpEditEngine->CalcTextWidth( true ) : pImpEditEngine->GetTextHeight(); + ensureDocumentFormatted(); + sal_uInt32 nWidth = !IsEffectivelyVertical() ? getImpl().CalcTextWidth(true) : getImpl().GetTextHeight(); return nWidth; } -void EditEngine::SetUpdateMode(bool bUpdate, bool bRestoring) +bool EditEngine::SetUpdateLayout(bool bUpdate, bool bRestoring) { - pImpEditEngine->SetUpdateMode( bUpdate ); - if (pImpEditEngine->pActiveView) + bool bPrevUpdateLayout = getImpl().SetUpdateLayout(bUpdate); + if (getImpl().mpActiveView) { // Not an activation if we are restoring the previous update mode. - pImpEditEngine->pActiveView->ShowCursor(false, false, /*bActivate=*/!bRestoring); + getImpl().mpActiveView->ShowCursor(false, false, /*bActivate=*/!bRestoring); } + return bPrevUpdateLayout; } -bool EditEngine::GetUpdateMode() const +bool EditEngine::IsUpdateLayout() const { - return pImpEditEngine->GetUpdateMode(); + return getImpl().IsUpdateLayout(); } void EditEngine::Clear() { - pImpEditEngine->Clear(); + getImpl().Clear(); } void EditEngine::SetText( const OUString& rText ) { - pImpEditEngine->SetText( rText ); - if ( !rText.isEmpty() ) - pImpEditEngine->FormatAndUpdate(); + getImpl().SetText(rText); + if (!rText.isEmpty() && getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } ErrCode EditEngine::Read( SvStream& rInput, const OUString& rBaseURL, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs /* = NULL */ ) { - bool bUndoEnabled = pImpEditEngine->IsUndoEnabled(); - pImpEditEngine->EnableUndo( false ); - pImpEditEngine->SetText( OUString() ); - EditPaM aPaM( pImpEditEngine->GetEditDoc().GetStartPaM() ); - pImpEditEngine->Read( rInput, rBaseURL, eFormat, EditSelection( aPaM, aPaM ), pHTTPHeaderAttrs ); - pImpEditEngine->EnableUndo( bUndoEnabled ); + bool bUndoEnabled = getImpl().IsUndoEnabled(); + getImpl().EnableUndo(false); + getImpl().SetText(OUString()); + EditPaM aPaM(getImpl().GetEditDoc().GetStartPaM()); + getImpl().Read(rInput, rBaseURL, eFormat, EditSelection(aPaM, aPaM), pHTTPHeaderAttrs); + getImpl().EnableUndo(bUndoEnabled); return rInput.GetError(); } void EditEngine::Write( SvStream& rOutput, EETextFormat eFormat ) { - EditPaM aStartPaM( pImpEditEngine->GetEditDoc().GetStartPaM() ); - EditPaM aEndPaM( pImpEditEngine->GetEditDoc().GetEndPaM() ); - pImpEditEngine->Write( rOutput, eFormat, EditSelection( aStartPaM, aEndPaM ) ); + EditPaM aStartPaM(getImpl().GetEditDoc().GetStartPaM()); + EditPaM aEndPaM(getImpl().GetEditDoc().GetEndPaM()); + getImpl().Write(rOutput, eFormat, EditSelection(aStartPaM, aEndPaM)); } std::unique_ptr<EditTextObject> EditEngine::CreateTextObject() { - return pImpEditEngine->CreateTextObject(); + return getImpl().CreateTextObject(); } std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( const ESelection& rESelection ) { - EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) ); - return pImpEditEngine->CreateTextObject( aSel ); + EditSelection aSel(getImpl().CreateSel(rESelection)); + return getImpl().CreateTextObject(aSel); } -std::unique_ptr<EditTextObject> EditEngine::GetEmptyTextObject() const +std::unique_ptr<EditTextObject> EditEngine::GetEmptyTextObject() { - return pImpEditEngine->GetEmptyTextObject(); + return getImpl().GetEmptyTextObject(); } - void EditEngine::SetText( const EditTextObject& rTextObject ) { - pImpEditEngine->SetText( rTextObject ); - pImpEditEngine->FormatAndUpdate(); + getImpl().SetText(rTextObject); + getImpl().FormatAndLayout(); } void EditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow ) { - pImpEditEngine->ShowParagraph( nParagraph, bShow ); + getImpl().ShowParagraph(nParagraph, bShow); } void EditEngine::SetNotifyHdl( const Link<EENotify&,void>& rLink ) { - pImpEditEngine->SetNotifyHdl( rLink ); + getImpl().SetNotifyHdl(rLink); } Link<EENotify&,void> const & EditEngine::GetNotifyHdl() const { - return pImpEditEngine->GetNotifyHdl(); + return getImpl().GetNotifyHdl(); } void EditEngine::SetStatusEventHdl( const Link<EditStatus&, void>& rLink ) { - pImpEditEngine->SetStatusEventHdl( rLink ); + getImpl().SetStatusEventHdl(rLink); } Link<EditStatus&, void> const & EditEngine::GetStatusEventHdl() const { - return pImpEditEngine->GetStatusEventHdl(); + return getImpl().GetStatusEventHdl(); } void EditEngine::SetHtmlImportHdl( const Link<HtmlImportInfo&,void>& rLink ) { - pImpEditEngine->aHtmlImportHdl = rLink; + getImpl().maHtmlImportHdl = rLink; } const Link<HtmlImportInfo&,void>& EditEngine::GetHtmlImportHdl() const { - return pImpEditEngine->aHtmlImportHdl; + return getImpl().maHtmlImportHdl; } void EditEngine::SetRtfImportHdl( const Link<RtfImportInfo&,void>& rLink ) { - pImpEditEngine->aRtfImportHdl = rLink; + getImpl().maRtfImportHdl = rLink; } const Link<RtfImportInfo&,void>& EditEngine::GetRtfImportHdl() const { - return pImpEditEngine->aRtfImportHdl; + return getImpl().maRtfImportHdl; } void EditEngine::SetBeginMovingParagraphsHdl( const Link<MoveParagraphsInfo&,void>& rLink ) { - pImpEditEngine->aBeginMovingParagraphsHdl = rLink; + getImpl().maBeginMovingParagraphsHdl = rLink; } void EditEngine::SetEndMovingParagraphsHdl( const Link<MoveParagraphsInfo&,void>& rLink ) { - pImpEditEngine->aEndMovingParagraphsHdl = rLink; + getImpl().maEndMovingParagraphsHdl = rLink; } void EditEngine::SetBeginPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink ) { - pImpEditEngine->aBeginPasteOrDropHdl = rLink; + getImpl().maBeginPasteOrDropHdl = rLink; } void EditEngine::SetEndPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink ) { - pImpEditEngine->aEndPasteOrDropHdl = rLink; + getImpl().maEndPasteOrDropHdl = rLink; } std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( sal_Int32 nPara, sal_Int32 nParas ) { - DBG_ASSERT( 0 <= nPara && nPara < pImpEditEngine->GetEditDoc().Count(), "CreateTextObject: Startpara out of Range" ); - DBG_ASSERT( nParas <= pImpEditEngine->GetEditDoc().Count() - nPara, "CreateTextObject: Endpara out of Range" ); + DBG_ASSERT(0 <= nPara && nPara < getImpl().GetEditDoc().Count(), "CreateTextObject: Startpara out of Range"); + DBG_ASSERT(nParas <= getImpl().GetEditDoc().Count() - nPara, "CreateTextObject: Endpara out of Range"); - ContentNode* pStartNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); - ContentNode* pEndNode = pImpEditEngine->GetEditDoc().GetObject( nPara+nParas-1 ); + ContentNode* pStartNode = getImpl().GetEditDoc().GetObject(nPara); + ContentNode* pEndNode = getImpl().GetEditDoc().GetObject(nPara + nParas - 1); DBG_ASSERT( pStartNode, "Start-Paragraph does not exist: CreateTextObject" ); DBG_ASSERT( pEndNode, "End-Paragraph does not exist: CreateTextObject" ); @@ -1616,33 +1597,34 @@ std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( sal_Int32 nPara, s EditSelection aTmpSel; aTmpSel.Min() = EditPaM( pStartNode, 0 ); aTmpSel.Max() = EditPaM( pEndNode, pEndNode->Len() ); - return pImpEditEngine->CreateTextObject( aTmpSel ); + return getImpl().CreateTextObject(aTmpSel); } return nullptr; } void EditEngine::RemoveParagraph( sal_Int32 nPara ) { - DBG_ASSERT( pImpEditEngine->GetEditDoc().Count() > 1, "The first paragraph should not be deleted!" ); - if( pImpEditEngine->GetEditDoc().Count() <= 1 ) + DBG_ASSERT(getImpl().GetEditDoc().Count() > 1, "The first paragraph should not be deleted!"); + if (getImpl().GetEditDoc().Count() <= 1) return; - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); - const ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); + const ParaPortion* pPortion = getImpl().GetParaPortions().SafeGetObject(nPara); DBG_ASSERT( pPortion && pNode, "Paragraph not found: RemoveParagraph" ); if ( pNode && pPortion ) { // No Undo encapsulation needed. - pImpEditEngine->ImpRemoveParagraph( nPara ); - pImpEditEngine->InvalidateFromParagraph( nPara ); - pImpEditEngine->UpdateSelections(); - pImpEditEngine->FormatAndUpdate(); + getImpl().ImpRemoveParagraph(nPara); + getImpl().InvalidateFromParagraph(nPara); + getImpl().UpdateSelections(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } } sal_Int32 EditEngine::GetTextLen( sal_Int32 nPara ) const { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); DBG_ASSERT( pNode, "Paragraph not found: GetTextLen" ); if ( pNode ) return pNode->Len(); @@ -1652,41 +1634,34 @@ sal_Int32 EditEngine::GetTextLen( sal_Int32 nPara ) const OUString EditEngine::GetText( sal_Int32 nPara ) const { OUString aStr; - if ( 0 <= nPara && nPara < pImpEditEngine->GetEditDoc().Count() ) - aStr = pImpEditEngine->GetEditDoc().GetParaAsString( nPara ); + if (0 <= nPara && nPara < getImpl().GetEditDoc().Count()) + aStr = getImpl().GetEditDoc().GetParaAsString(nPara); return aStr; } void EditEngine::SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) { - pImpEditEngine->SetModifyHdl( rLink ); -} - -Link<LinkParamNone*,void> const & EditEngine::GetModifyHdl() const -{ - return pImpEditEngine->GetModifyHdl(); + getImpl().SetModifyHdl(rLink); } - void EditEngine::ClearModifyFlag() { - pImpEditEngine->SetModifyFlag( false ); + getImpl().SetModifyFlag(false); } void EditEngine::SetModified() { - pImpEditEngine->SetModifyFlag( true ); + getImpl().SetModifyFlag(true); } bool EditEngine::IsModified() const { - return pImpEditEngine->IsModified(); + return getImpl().IsModified(); } bool EditEngine::IsInSelectionMode() const { - return ( pImpEditEngine->IsInSelectionMode() || - pImpEditEngine->GetSelEngine().IsInSelection() ); + return getImpl().IsInSelectionMode() || getImpl().GetSelEngine().IsInSelection(); } void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj, bool bAppend ) @@ -1697,21 +1672,22 @@ void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj nPara = GetParagraphCount(); } - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + getImpl().UndoActionStart(EDITUNDO_INSERT); // No Undo compounding needed. - EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) ); + EditPaM aPaM(getImpl().InsertParagraph(nPara)); // When InsertParagraph from the outside, no hard attributes // should be taken over! - pImpEditEngine->RemoveCharAttribs( nPara ); - pImpEditEngine->InsertText( rTxtObj, EditSelection( aPaM, aPaM ) ); + getImpl().RemoveCharAttribs(nPara); + getImpl().InsertText(rTxtObj, EditSelection(aPaM, aPaM)); if ( bAppend && nPara ) - pImpEditEngine->ConnectContents( nPara-1, /*bBackwards=*/false ); + getImpl().ConnectContents(nPara - 1, /*bBackwards=*/false); - pImpEditEngine->UndoActionEnd(); + getImpl().UndoActionEnd(); - pImpEditEngine->FormatAndUpdate(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } void EditEngine::InsertParagraph(sal_Int32 nPara, const OUString& rTxt) @@ -1722,71 +1698,76 @@ void EditEngine::InsertParagraph(sal_Int32 nPara, const OUString& rTxt) nPara = GetParagraphCount(); } - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); - EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) ); + getImpl().UndoActionStart(EDITUNDO_INSERT); + EditPaM aPaM(getImpl().InsertParagraph(nPara)); // When InsertParagraph from the outside, no hard attributes // should be taken over! - pImpEditEngine->RemoveCharAttribs( nPara ); - pImpEditEngine->UndoActionEnd(); - pImpEditEngine->ImpInsertText( EditSelection( aPaM, aPaM ), rTxt ); - pImpEditEngine->FormatAndUpdate(); + getImpl().RemoveCharAttribs(nPara); + getImpl().UndoActionEnd(); + getImpl().ImpInsertText(EditSelection(aPaM, aPaM), rTxt); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } void EditEngine::SetText(sal_Int32 nPara, const OUString& rTxt) { - std::unique_ptr<EditSelection> pSel = pImpEditEngine->SelectParagraph( nPara ); + std::optional<EditSelection> pSel = getImpl().SelectParagraph(nPara); if ( pSel ) { - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); - pImpEditEngine->ImpInsertText( *pSel, rTxt ); - pImpEditEngine->UndoActionEnd(); - pImpEditEngine->FormatAndUpdate(); + getImpl().UndoActionStart(EDITUNDO_INSERT); + getImpl().ImpInsertText(*pSel, rTxt); + getImpl().UndoActionEnd(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } } void EditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) { - pImpEditEngine->SetParaAttribs( nPara, rSet ); - pImpEditEngine->FormatAndUpdate(); + getImpl().SetParaAttribs(nPara, rSet); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } const SfxItemSet& EditEngine::GetParaAttribs( sal_Int32 nPara ) const { - return pImpEditEngine->GetParaAttribs( nPara ); + return getImpl().GetParaAttribs(nPara); } bool EditEngine::HasParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - return pImpEditEngine->HasParaAttrib( nPara, nWhich ); + return getImpl().HasParaAttrib(nPara, nWhich); } -const SfxPoolItem& EditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) +const SfxPoolItem& EditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - return pImpEditEngine->GetParaAttrib( nPara, nWhich ); + return getImpl().GetParaAttrib(nPara, nWhich); } void EditEngine::SetCharAttribs(sal_Int32 nPara, const SfxItemSet& rSet) { - EditSelection aSel(pImpEditEngine->ConvertSelection(nPara, 0, nPara, GetTextLen(nPara))); - pImpEditEngine->SetAttribs(aSel, rSet); - pImpEditEngine->FormatAndUpdate(); + EditSelection aSel(getImpl().ConvertSelection(nPara, 0, nPara, GetTextLen(nPara))); + // This is called by sd::View::OnBeginPasteOrDrop(), updating the cursor position on undo is not + // wanted. + getImpl().SetAttribs(aSel, rSet, /*nSpecial=*/SetAttribsMode::NONE, /*bSetSelection=*/false); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } -void EditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const +void EditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rList ) const { - pImpEditEngine->GetCharAttribs( nPara, rLst ); + getImpl().GetCharAttribs(nPara, rList); } SfxItemSet EditEngine::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) { - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - return pImpEditEngine->GetAttribs( aSel, nOnlyHardAttrib ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + return getImpl().GetAttribs(aSel, nOnlyHardAttrib); } SfxItemSet EditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags ) const { - return pImpEditEngine->GetAttribs( nPara, nStart, nEnd, nFlags ); + return getImpl().GetAttribs(nPara, nStart, nEnd, nFlags); } void EditEngine::RemoveAttribs( const ESelection& rSelection, bool bRemoveParaAttribs, sal_uInt16 nWhich ) @@ -1795,11 +1776,12 @@ void EditEngine::RemoveAttribs( const ESelection& rSelection, bool bRemoveParaAt EERemoveParaAttribsMode::RemoveAll : EERemoveParaAttribsMode::RemoveCharItems; - pImpEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - EditSelection aSel( pImpEditEngine->ConvertSelection( rSelection.nStartPara, rSelection.nStartPos, rSelection.nEndPara, rSelection.nEndPos ) ); - pImpEditEngine->RemoveCharAttribs( aSel, eMode, nWhich ); - pImpEditEngine->UndoActionEnd(); - pImpEditEngine->FormatAndUpdate(); + getImpl().UndoActionStart(EDITUNDO_RESETATTRIBS); + EditSelection aSel(getImpl().ConvertSelection(rSelection.nStartPara, rSelection.nStartPos, rSelection.nEndPara, rSelection.nEndPos)); + getImpl().RemoveCharAttribs(aSel, eMode, nWhich); + getImpl().UndoActionEnd(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } vcl::Font EditEngine::GetStandardFont( sal_Int32 nPara ) @@ -1809,7 +1791,7 @@ vcl::Font EditEngine::GetStandardFont( sal_Int32 nPara ) SvxFont EditEngine::GetStandardSvxFont( sal_Int32 nPara ) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject( nPara ); return pNode->GetCharAttribs().GetDefFont(); } @@ -1817,7 +1799,7 @@ void EditEngine::StripPortions() { ScopedVclPtrInstance< VirtualDevice > aTmpDev; tools::Rectangle aBigRect( Point( 0, 0 ), Size( 0x7FFFFFFF, 0x7FFFFFFF ) ); - if ( IsVertical() ) + if ( IsEffectivelyVertical() ) { if( IsTopToBottom() ) { @@ -1830,15 +1812,15 @@ void EditEngine::StripPortions() aBigRect.SetBottom( 0 ); } } - pImpEditEngine->Paint(*aTmpDev, aBigRect, Point(), true); + getImpl().Paint(*aTmpDev, aBigRect, Point(), true); } void EditEngine::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatFullDoc(); + if (!getImpl().IsFormatted()) + getImpl().FormatFullDoc(); - const ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + const ParaPortion* pParaPortion = getImpl().GetParaPortions().SafeGetObject(nPara); if ( pParaPortion ) { sal_Int32 nEnd = 0; @@ -1853,25 +1835,36 @@ void EditEngine::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) void EditEngine::SetFlatMode( bool bFlat) { - pImpEditEngine->SetFlatMode( bFlat ); + getImpl().SetFlatMode(bFlat); } bool EditEngine::IsFlatMode() const { - return !( pImpEditEngine->aStatus.UseCharAttribs() ); + return !getImpl().GetStatus().UseCharAttribs(); +} + +void EditEngine::SetSingleLine(bool bValue) +{ + if (bValue == getImpl().GetStatus().IsSingleLine()) + return; + + if (bValue) + getImpl().GetStatus().TurnOnFlags(EEControlBits::SINGLELINE); + else + getImpl().GetStatus().TurnOffFlags(EEControlBits::SINGLELINE); } void EditEngine::SetControlWord( EEControlBits nWord ) { - if ( nWord == pImpEditEngine->aStatus.GetControlWord() ) + if (nWord == getImpl().GetStatus().GetControlWord()) return; - EEControlBits nPrev = pImpEditEngine->aStatus.GetControlWord(); - pImpEditEngine->aStatus.GetControlWord() = nWord; + EEControlBits nPrev = getImpl().GetStatus().GetControlWord(); + getImpl().GetStatus().GetControlWord() = nWord; EEControlBits nChanges = nPrev ^ nWord; - if ( pImpEditEngine->IsFormatted() ) + if (getImpl().IsFormatted()) { // possibly reformat: if ( ( nChanges & EEControlBits::USECHARATTRIBS ) || @@ -1883,11 +1876,11 @@ void EditEngine::SetControlWord( EEControlBits nWord ) { if ( nChanges & EEControlBits::USECHARATTRIBS ) { - pImpEditEngine->GetEditDoc().CreateDefFont( true ); + getImpl().GetEditDoc().CreateDefFont(true); } - pImpEditEngine->FormatFullDoc(); - pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() ); + getImpl().FormatFullDoc(); + getImpl().UpdateViews(getImpl().GetActiveView()); } } @@ -1896,38 +1889,38 @@ void EditEngine::SetControlWord( EEControlBits nWord ) if ( !bSpellingChanged ) return; - pImpEditEngine->StopOnlineSpellTimer(); + getImpl().StopOnlineSpellTimer(); if (nWord & EEControlBits::ONLINESPELLING) { // Create WrongList, start timer... - sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count(); - for ( sal_Int32 n = 0; n < nNodes; n++ ) + sal_Int32 nNodes = getImpl().GetEditDoc().Count(); + for (sal_Int32 nNode = 0; nNode < nNodes; nNode++) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nNode); pNode->CreateWrongList(); } - if (pImpEditEngine->IsFormatted()) - pImpEditEngine->StartOnlineSpellTimer(); + if (getImpl().IsFormatted()) + getImpl().StartOnlineSpellTimer(); } else { tools::Long nY = 0; - sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count(); - for ( sal_Int32 n = 0; n < nNodes; n++ ) + sal_Int32 nNodes = getImpl().GetEditDoc().Count(); + for ( sal_Int32 nNode = 0; nNode < nNodes; nNode++) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); - const ParaPortion& rPortion = pImpEditEngine->GetParaPortions()[n]; + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nNode); + ParaPortion const& rPortion = getImpl().GetParaPortions().getRef(nNode); bool bWrongs = false; if (pNode->GetWrongList() != nullptr) bWrongs = !pNode->GetWrongList()->empty(); pNode->DestroyWrongList(); if ( bWrongs ) { - pImpEditEngine->aInvalidRect.SetLeft( 0 ); - pImpEditEngine->aInvalidRect.SetRight( pImpEditEngine->GetPaperSize().Width() ); - pImpEditEngine->aInvalidRect.SetTop( nY+1 ); - pImpEditEngine->aInvalidRect.SetBottom( nY + rPortion.GetHeight()-1 ); - pImpEditEngine->UpdateViews( pImpEditEngine->pActiveView ); + getImpl().maInvalidRect.SetLeft(0); + getImpl().maInvalidRect.SetRight(getImpl().GetPaperSize().Width()); + getImpl().maInvalidRect.SetTop(nY + 1); + getImpl().maInvalidRect.SetBottom(nY + rPortion.GetHeight() - 1); + getImpl().UpdateViews(getImpl().mpActiveView); } nY += rPortion.GetHeight(); } @@ -1936,19 +1929,18 @@ void EditEngine::SetControlWord( EEControlBits nWord ) EEControlBits EditEngine::GetControlWord() const { - return pImpEditEngine->aStatus.GetControlWord(); + return getImpl().GetStatus().GetControlWord(); } tools::Long EditEngine::GetFirstLineStartX( sal_Int32 nParagraph ) { tools::Long nX = 0; - const ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nParagraph ); + const ParaPortion* pPPortion = getImpl().GetParaPortions().SafeGetObject(nParagraph); if ( pPPortion ) { - DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetFirstLineStartX: Doc not formatted - unable to format!" ); - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); + DBG_ASSERT(getImpl().IsFormatted() || !getImpl().IsFormatting(), "GetFirstLineStartX: Doc not formatted - unable to format!"); + ensureDocumentFormatted(); const EditLine& rFirstLine = pPPortion->GetLines()[0]; nX = rFirstLine.GetStartPosX(); } @@ -1958,7 +1950,7 @@ tools::Long EditEngine::GetFirstLineStartX( sal_Int32 nParagraph ) Point EditEngine::GetDocPos( const Point& rPaperPos ) const { Point aDocPos( rPaperPos ); - if ( IsVertical() ) + if ( IsEffectivelyVertical() ) { if ( IsTopToBottom() ) { @@ -1976,17 +1968,16 @@ Point EditEngine::GetDocPos( const Point& rPaperPos ) const Point EditEngine::GetDocPosTopLeft( sal_Int32 nParagraph ) { - const ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nParagraph ); + const ParaPortion* pPPortion = getImpl().GetParaPortions().SafeGetObject(nParagraph); DBG_ASSERT( pPPortion, "Paragraph not found: GetWindowPosTopLeft" ); Point aPoint; if ( pPPortion ) { - // If someone calls GetLineHeight() with an empty Engine. - DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetDocPosTopLeft: Doc not formatted - unable to format!" ); - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatAndUpdate(); - if ( pPPortion->GetLines().Count() ) + DBG_ASSERT(getImpl().IsFormatted() || !getImpl().IsFormatting(), "GetDocPosTopLeft: Doc not formatted - unable to format!"); + if (!getImpl().IsFormatted()) + getImpl().FormatAndLayout(); + if (pPPortion->GetLines().Count()) { // Correct it if large Bullet. const EditLine& rFirstLine = pPPortion->GetLines()[0]; @@ -1994,17 +1985,16 @@ Point EditEngine::GetDocPosTopLeft( sal_Int32 nParagraph ) } else { - const SvxLRSpaceItem& rLRItem = pImpEditEngine->GetLRSpaceItem( pPPortion->GetNode() ); -// TL_NF_LR aPoint.X() = pImpEditEngine->GetXValue( (short)(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset()) ); + const SvxLRSpaceItem& rLRItem = getImpl().GetLRSpaceItem(pPPortion->GetNode()); sal_Int32 nSpaceBefore = 0; - pImpEditEngine->GetSpaceBeforeAndMinLabelWidth( pPPortion->GetNode(), &nSpaceBefore ); + getImpl().GetSpaceBeforeAndMinLabelWidth(pPPortion->GetNode(), &nSpaceBefore); short nX = static_cast<short>(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore); - aPoint.setX( pImpEditEngine->GetXValue( nX - ) ); + + aPoint.setX(getImpl().scaleXSpacingValue(nX)); } - aPoint.setY( pImpEditEngine->GetParaPortions().GetYOffset( pPPortion ) ); + aPoint.setY(getImpl().GetParaPortions().GetYOffset(pPPortion)); } return aPoint; } @@ -2018,49 +2008,44 @@ const SvxNumberFormat* EditEngine::GetNumberFormat( sal_Int32 ) const bool EditEngine::IsRightToLeft( sal_Int32 nPara ) const { - return pImpEditEngine->IsRightToLeft( nPara ); + return getImpl().IsRightToLeft(nPara); } bool EditEngine::IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder ) { - - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); + ensureDocumentFormatted(); // take unrotated positions for calculation here Point aDocPos = GetDocPos( rPaperPos ); - if ( ( aDocPos.Y() > 0 ) && ( aDocPos.Y() < static_cast<tools::Long>(pImpEditEngine->GetTextHeight()) ) ) - return pImpEditEngine->IsTextPos(aDocPos, nBorder); + if ((aDocPos.Y() > 0) && (o3tl::make_unsigned(aDocPos.Y()) < getImpl().GetTextHeight())) + return getImpl().IsTextPos(aDocPos, nBorder); return false; } void EditEngine::SetEditTextObjectPool( SfxItemPool* pPool ) { - pImpEditEngine->SetEditTextObjectPool( pPool ); + getImpl().SetEditTextObjectPool(pPool); } SfxItemPool* EditEngine::GetEditTextObjectPool() const { - return pImpEditEngine->GetEditTextObjectPool(); + return getImpl().GetEditTextObjectPool(); } void EditEngine::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->SetAttribs( aSel, rSet ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().SetAttribs(aSel, rSet); } void EditEngine::QuickMarkInvalid( const ESelection& rSel ) { - DBG_ASSERT( rSel.nStartPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: Start out of Range!" ); - DBG_ASSERT( rSel.nEndPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: End out of Range!" ); - for ( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ ) + DBG_ASSERT(rSel.nStartPara < getImpl().GetEditDoc().Count(), "MarkInvalid: Start out of Range!"); + DBG_ASSERT(rSel.nEndPara < getImpl().GetEditDoc().Count(), "MarkInvalid: End out of Range!"); + for (sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++) { - ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + ParaPortion* pPortion = getImpl().GetParaPortions().SafeGetObject(nPara); if ( pPortion ) pPortion->MarkSelectionInvalid( 0 ); } @@ -2068,128 +2053,117 @@ void EditEngine::QuickMarkInvalid( const ESelection& rSel ) void EditEngine::QuickInsertText(const OUString& rText, const ESelection& rSel) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->ImpInsertText( aSel, rText ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().ImpInsertText(aSel, rText); } void EditEngine::QuickDelete( const ESelection& rSel ) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->ImpDeleteSelection( aSel ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().ImpDeleteSelection( aSel ); } void EditEngine::QuickMarkToBeRepainted( sal_Int32 nPara ) { - ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + ParaPortion* pPortion = getImpl().GetParaPortions().SafeGetObject(nPara); if ( pPortion ) pPortion->SetMustRepaint( true ); } void EditEngine::QuickInsertLineBreak( const ESelection& rSel ) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->InsertLineBreak( aSel ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().InsertLineBreak( aSel ); } void EditEngine::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ) { - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->ImpInsertFeature( aSel, rFld ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().ImpInsertFeature(aSel, rFld); } void EditEngine::QuickFormatDoc( bool bFull ) { - if ( bFull ) - pImpEditEngine->FormatFullDoc(); + if (bFull) + getImpl().FormatFullDoc(); else - pImpEditEngine->FormatDoc(); + getImpl().FormatDoc(); // Don't pass active view, maybe selection is not updated yet... - pImpEditEngine->UpdateViews(); + getImpl().UpdateViews(); } void EditEngine::SetStyleSheet(const EditSelection& aSel, SfxStyleSheet* pStyle) { - pImpEditEngine->SetStyleSheet(aSel, pStyle); + getImpl().SetStyleSheet(aSel, pStyle); } void EditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ) { - pImpEditEngine->SetStyleSheet( nPara, pStyle ); + getImpl().SetStyleSheet(nPara, pStyle); } const SfxStyleSheet* EditEngine::GetStyleSheet( sal_Int32 nPara ) const { - return pImpEditEngine->GetStyleSheet( nPara ); + return getImpl().GetStyleSheet(nPara); } SfxStyleSheet* EditEngine::GetStyleSheet( sal_Int32 nPara ) { - return pImpEditEngine->GetStyleSheet( nPara ); + return getImpl().GetStyleSheet(nPara); } void EditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) { - pImpEditEngine->SetStyleSheetPool( pSPool ); + getImpl().SetStyleSheetPool(pSPool); } SfxStyleSheetPool* EditEngine::GetStyleSheetPool() { - return pImpEditEngine->GetStyleSheetPool(); + return getImpl().GetStyleSheetPool(); } void EditEngine::SetWordDelimiters( const OUString& rDelimiters ) { - pImpEditEngine->aWordDelimiters = rDelimiters; - if (pImpEditEngine->aWordDelimiters.indexOf(CH_FEATURE) == -1) - pImpEditEngine->aWordDelimiters += OUStringChar(CH_FEATURE); + getImpl().maWordDelimiters = rDelimiters; + if (getImpl().maWordDelimiters.indexOf(CH_FEATURE) == -1) + getImpl().maWordDelimiters += OUStringChar(CH_FEATURE); } const OUString& EditEngine::GetWordDelimiters() const { - return pImpEditEngine->aWordDelimiters; + return getImpl().maWordDelimiters; } void EditEngine::EraseVirtualDevice() { - pImpEditEngine->EraseVirtualDevice(); + getImpl().EraseVirtualDevice(); } void EditEngine::SetSpeller( Reference< XSpellChecker1 > const &xSpeller ) { - pImpEditEngine->SetSpeller( xSpeller ); + getImpl().SetSpeller(xSpeller); } Reference< XSpellChecker1 > const & EditEngine::GetSpeller() { - return pImpEditEngine->GetSpeller(); + return getImpl().GetSpeller(); } void EditEngine::SetHyphenator( Reference< XHyphenator > const & xHyph ) { - pImpEditEngine->SetHyphenator( xHyph ); + getImpl().SetHyphenator(xHyph); } void EditEngine::GetAllMisspellRanges( std::vector<editeng::MisspellRanges>& rRanges ) const { - pImpEditEngine->GetAllMisspellRanges(rRanges); + getImpl().GetAllMisspellRanges(rRanges); } void EditEngine::SetAllMisspellRanges( const std::vector<editeng::MisspellRanges>& rRanges ) { - pImpEditEngine->SetAllMisspellRanges(rRanges); + getImpl().SetAllMisspellRanges(rRanges); } void EditEngine::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars) @@ -2199,12 +2173,12 @@ void EditEngine::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharac void EditEngine::SetDefaultLanguage( LanguageType eLang ) { - pImpEditEngine->SetDefaultLanguage( eLang ); + getImpl().SetDefaultLanguage(eLang); } LanguageType EditEngine::GetDefaultLanguage() const { - return pImpEditEngine->GetDefaultLanguage(); + return getImpl().GetDefaultLanguage(); } bool EditEngine::SpellNextDocument() @@ -2214,35 +2188,35 @@ bool EditEngine::SpellNextDocument() EESpellState EditEngine::HasSpellErrors() { - if ( !pImpEditEngine->GetSpeller().is() ) + if (!getImpl().GetSpeller().is()) return EESpellState::NoSpeller; - return pImpEditEngine->HasSpellErrors(); + return getImpl().HasSpellErrors(); } void EditEngine::ClearSpellErrors() { - pImpEditEngine->ClearSpellErrors(); + getImpl().ClearSpellErrors(); } bool EditEngine::SpellSentence(EditView const & rView, svx::SpellPortions& rToFill ) { - return pImpEditEngine->SpellSentence( rView, rToFill ); + return getImpl().SpellSentence(rView, rToFill); } void EditEngine::PutSpellingToSentenceStart( EditView const & rEditView ) { - pImpEditEngine->PutSpellingToSentenceStart( rEditView ); + getImpl().PutSpellingToSentenceStart(rEditView); } void EditEngine::ApplyChangedSentence(EditView const & rEditView, const svx::SpellPortions& rNewPortions, bool bRecheck ) { - pImpEditEngine->ApplyChangedSentence( rEditView, rNewPortions, bRecheck ); + getImpl().ApplyChangedSentence(rEditView, rNewPortions, bRecheck); } bool EditEngine::HasConvertibleTextPortion( LanguageType nLang ) { - return pImpEditEngine->HasConvertibleTextPortion( nLang ); + return getImpl().HasConvertibleTextPortion(nLang); } bool EditEngine::ConvertNextDocument() @@ -2252,35 +2226,40 @@ bool EditEngine::ConvertNextDocument() bool EditEngine::HasText( const SvxSearchItem& rSearchItem ) { - return pImpEditEngine->HasText( rSearchItem ); + return getImpl().HasText(rSearchItem); +} + +ScalingParameters EditEngine::getScalingParameters() const +{ + return getImpl().getScalingParameters(); } -void EditEngine::SetGlobalCharStretching( sal_uInt16 nX, sal_uInt16 nY ) +void EditEngine::setScalingParameters(ScalingParameters const& rScalingParameters) { - pImpEditEngine->SetCharStretching( nX, nY ); + getImpl().setScalingParameters(rScalingParameters); } -void EditEngine::GetGlobalCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const +void EditEngine::setRoundFontSizeToPt(bool bRound) { - pImpEditEngine->GetCharStretching( rX, rY ); + getImpl().setRoundToNearestPt(bRound); } bool EditEngine::ShouldCreateBigTextObject() const { sal_Int32 nTextPortions = 0; - sal_Int32 nParas = pImpEditEngine->GetEditDoc().Count(); - for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ ) + sal_Int32 nParas = getImpl().GetEditDoc().Count(); + for (sal_Int32 nPara = 0; nPara < nParas; nPara++) { - ParaPortion& rParaPortion = pImpEditEngine->GetParaPortions()[nPara]; + ParaPortion& rParaPortion = getImpl().GetParaPortions().getRef(nPara); nTextPortions = nTextPortions + rParaPortion.GetTextPortions().Count(); } - return nTextPortions >= pImpEditEngine->GetBigTextObjectStart(); + return nTextPortions >= getImpl().GetBigTextObjectStart(); } sal_uInt16 EditEngine::GetFieldCount( sal_Int32 nPara ) const { sal_uInt16 nFields = 0; - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); if ( pNode ) { for (auto const& attrib : pNode->GetCharAttribs().GetAttribs()) @@ -2295,7 +2274,7 @@ sal_uInt16 EditEngine::GetFieldCount( sal_Int32 nPara ) const EFieldInfo EditEngine::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); if ( pNode ) { sal_uInt16 nCurrentField = 0; @@ -2322,25 +2301,25 @@ EFieldInfo EditEngine::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const bool EditEngine::UpdateFields() { - bool bChanges = pImpEditEngine->UpdateFields(); - if ( bChanges ) - pImpEditEngine->FormatAndUpdate(); + bool bChanges = getImpl().UpdateFields(); + if (bChanges && getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); return bChanges; } bool EditEngine::UpdateFieldsOnly() { - return pImpEditEngine->UpdateFields(); + return getImpl().UpdateFields(); } void EditEngine::RemoveFields( const std::function<bool ( const SvxFieldData* )>& isFieldData ) { - pImpEditEngine->UpdateFields(); + getImpl().UpdateFields(); - sal_Int32 nParas = pImpEditEngine->GetEditDoc().Count(); + sal_Int32 nParas = getImpl().GetEditDoc().Count(); for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ ) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs(); for (size_t nAttr = rAttrs.size(); nAttr; ) { @@ -2353,7 +2332,7 @@ void EditEngine::RemoveFields( const std::function<bool ( const SvxFieldData* )> DBG_ASSERT( dynamic_cast<const SvxFieldItem*>(rAttr.GetItem()), "no field item..." ); EditSelection aSel( EditPaM(pNode, rAttr.GetStart()), EditPaM(pNode, rAttr.GetEnd()) ); OUString aFieldText = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue(); - pImpEditEngine->ImpInsertText( aSel, aFieldText ); + getImpl().ImpInsertText(aSel, aFieldText); } } } @@ -2362,10 +2341,10 @@ void EditEngine::RemoveFields( const std::function<bool ( const SvxFieldData* )> bool EditEngine::HasOnlineSpellErrors() const { - sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count(); + sal_Int32 nNodes = getImpl().GetEditDoc().Count(); for ( sal_Int32 n = 0; n < nNodes; n++ ) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(n); if ( pNode->GetWrongList() && !pNode->GetWrongList()->empty() ) return true; } @@ -2374,29 +2353,29 @@ bool EditEngine::HasOnlineSpellErrors() const void EditEngine::CompleteOnlineSpelling() { - if ( pImpEditEngine->GetStatus().DoOnlineSpelling() ) + if (getImpl().GetStatus().DoOnlineSpelling()) { - if( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatAndUpdate(); + if (!getImpl().IsFormatted()) + getImpl().FormatAndLayout(); - pImpEditEngine->StopOnlineSpellTimer(); - pImpEditEngine->DoOnlineSpelling( nullptr, true, false ); + getImpl().StopOnlineSpellTimer(); + getImpl().DoOnlineSpelling(nullptr, true, false); } } sal_Int32 EditEngine::FindParagraph( tools::Long nDocPosY ) { - return pImpEditEngine->GetParaPortions().FindParagraph( nDocPosY ); + return getImpl().GetParaPortions().FindParagraph(nDocPosY); } EPosition EditEngine::FindDocPosition( const Point& rDocPos ) const { EPosition aPos; // From the point of the API, this is const... - EditPaM aPaM = const_cast<EditEngine*>(this)->pImpEditEngine->GetPaM( rDocPos, false ); + EditPaM aPaM = getImpl().GetPaM(rDocPos, false); if ( aPaM.GetNode() ) { - aPos.nPara = pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() ); + aPos.nPara = getImpl().maEditDoc.GetPos(aPaM.GetNode()); aPos.nIndex = aPaM.GetIndex(); } return aPos; @@ -2405,13 +2384,14 @@ EPosition EditEngine::FindDocPosition( const Point& rDocPos ) const tools::Rectangle EditEngine::GetCharacterBounds( const EPosition& rPos ) const { tools::Rectangle aBounds; - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( rPos.nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(rPos.nPara); // Check against index, not paragraph if ( pNode && ( rPos.nIndex < pNode->Len() ) ) { - aBounds = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex ), GetCursorFlags::TextOnly ); - tools::Rectangle aR2 = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex+1 ), GetCursorFlags::TextOnly|GetCursorFlags::EndOfLine ); + aBounds = getImpl().PaMtoEditCursor(EditPaM(pNode, rPos.nIndex), CursorFlags{.bTextOnly = true}); + CursorFlags aFlags { .bTextOnly = true, .bEndOfLine = true}; + tools::Rectangle aR2 = getImpl().PaMtoEditCursor(EditPaM(pNode, rPos.nIndex + 1), aFlags); if ( aR2.Right() > aBounds.Right() ) aBounds.SetRight( aR2.Right() ); } @@ -2420,20 +2400,17 @@ tools::Rectangle EditEngine::GetCharacterBounds( const EPosition& rPos ) const ParagraphInfos EditEngine::GetParagraphInfos( sal_Int32 nPara ) { - // This only works if not already in the format ... - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); + ensureDocumentFormatted(); ParagraphInfos aInfos; - aInfos.bValid = pImpEditEngine->IsFormatted(); - if ( pImpEditEngine->IsFormatted() ) + aInfos.bValid = getImpl().IsFormatted(); + if (getImpl().IsFormatted() && getImpl().GetParaPortions().exists(nPara)) { - const ParaPortion& rParaPortion = pImpEditEngine->GetParaPortions()[nPara]; - const EditLine* pLine = rParaPortion.GetLines().Count() ? - &rParaPortion.GetLines()[0] : nullptr; - DBG_ASSERT( pLine, "GetParagraphInfos - Paragraph out of range" ); - if ( pLine ) + ParaPortion const& rParaPortion = getImpl().GetParaPortions().getRef(nPara); + const EditLine* pLine = (rParaPortion.GetLines().Count()) ? &rParaPortion.GetLines()[0] : nullptr; + DBG_ASSERT(pLine, "GetParagraphInfos - Paragraph out of range"); + if (pLine) { aInfos.nFirstLineHeight = pLine->GetHeight(); aInfos.nFirstLineTextHeight = pLine->GetTxtHeight(); @@ -2443,18 +2420,19 @@ ParagraphInfos EditEngine::GetParagraphInfos( sal_Int32 nPara ) return aInfos; } -css::uno::Reference< css::datatransfer::XTransferable > - EditEngine::CreateTransferable( const ESelection& rSelection ) const +uno::Reference<datatransfer::XTransferable> +EditEngine::CreateTransferable(const ESelection& rSelection) { - EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) ); - return pImpEditEngine->CreateTransferable( aSel ); + EditSelection aSel(getImpl().CreateSel(rSelection)); + return getImpl().CreateTransferable(aSel); } // ====================== Virtual Methods ======================== void EditEngine::DrawingText( const Point&, const OUString&, sal_Int32, sal_Int32, - const tools::Long*, const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/, + std::span<const sal_Int32>, std::span<const sal_Bool>, + const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/, const EEngineData::WrongSpellVector*, const SvxFieldData*, bool, bool, const css::lang::Locale*, const Color&, const Color&) @@ -2475,25 +2453,24 @@ void EditEngine::PaintingFirstLine(sal_Int32, const Point&, const Point&, Degree void EditEngine::ParagraphInserted( sal_Int32 nPara ) { - if ( GetNotifyHdl().IsSet() ) { EENotify aNotify( EE_NOTIFY_PARAGRAPHINSERTED ); aNotify.nParagraph = nPara; - pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpl().GetNotifyHdl().Call(aNotify); } } void EditEngine::ParagraphDeleted( sal_Int32 nPara ) { - if ( GetNotifyHdl().IsSet() ) { EENotify aNotify( EE_NOTIFY_PARAGRAPHREMOVED ); aNotify.nParagraph = nPara; - pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpl().GetNotifyHdl().Call(aNotify); } } + void EditEngine::ParagraphConnected( sal_Int32 /*nLeftParagraph*/, sal_Int32 /*nRightParagraph*/ ) { } @@ -2512,11 +2489,11 @@ void EditEngine::ParagraphHeightChanged( sal_Int32 nPara ) { EENotify aNotify( EE_NOTIFY_TextHeightChanged ); aNotify.nParagraph = nPara; - pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpl().GetNotifyHdl().Call(aNotify); } - for (EditView* pView : pImpEditEngine->aEditViews) - pView->pImpEditView->ScrollStateChange(); + for (EditView* pView : getImpl().maEditViews) + pView->getImpl().ScrollStateChange(); } OUString EditEngine::GetUndoComment( sal_uInt16 nId ) const @@ -2573,13 +2550,14 @@ tools::Rectangle EditEngine::GetBulletArea( sal_Int32 ) return tools::Rectangle( Point(), Point() ); } -OUString EditEngine::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>& ) +OUString EditEngine::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>&, std::optional<FontLineStyle>& ) { return OUString(' '); } -void EditEngine::FieldClicked( const SvxFieldItem& ) +bool EditEngine::FieldClicked( const SvxFieldItem& ) { + return false; } @@ -2612,9 +2590,14 @@ SfxItemPool& EditEngine::GetGlobalItemPool() if ( !pGlobalPool ) { pGlobalPool = CreatePool(); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) + // TerminateListener option not available, force it to leak + pGlobalPool->acquire(); +#else uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(comphelper::getProcessComponentContext()); uno::Reference< frame::XTerminateListener > xListener( new TerminateListener ); xDesktop->addTerminateListener( xListener ); +#endif } return *pGlobalPool; } @@ -2752,6 +2735,13 @@ bool EditEngine::HasValidData( const css::uno::Reference< css::datatransfer::XTr datatransfer::DataFlavor aFlavor; SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor ); bValidData = rTransferable->isDataFlavorSupported( aFlavor ); + + if (!bValidData) + { + // Allow HTML-only clipboard, i.e. without plain text. + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML, aFlavor); + bValidData = rTransferable->isDataFlavorSupported(aFlavor); + } } return bValidData; @@ -2760,99 +2750,104 @@ bool EditEngine::HasValidData( const css::uno::Reference< css::datatransfer::XTr /** sets a link that is called at the beginning of a drag operation at an edit view */ void EditEngine::SetBeginDropHdl( const Link<EditView*,void>& rLink ) { - pImpEditEngine->SetBeginDropHdl( rLink ); + getImpl().SetBeginDropHdl(rLink); } Link<EditView*,void> const & EditEngine::GetBeginDropHdl() const { - return pImpEditEngine->GetBeginDropHdl(); + return getImpl().GetBeginDropHdl(); } /** sets a link that is called at the end of a drag operation at an edit view */ void EditEngine::SetEndDropHdl( const Link<EditView*,void>& rLink ) { - pImpEditEngine->SetEndDropHdl( rLink ); + getImpl().SetEndDropHdl(rLink); } Link<EditView*,void> const & EditEngine::GetEndDropHdl() const { - return pImpEditEngine->GetEndDropHdl(); + return getImpl().GetEndDropHdl(); } void EditEngine::SetFirstWordCapitalization( bool bCapitalize ) { - pImpEditEngine->SetFirstWordCapitalization( bCapitalize ); + getImpl().SetFirstWordCapitalization(bCapitalize); } void EditEngine::SetReplaceLeadingSingleQuotationMark( bool bReplace ) { - pImpEditEngine->SetReplaceLeadingSingleQuotationMark( bReplace ); + getImpl().SetReplaceLeadingSingleQuotationMark(bReplace); } bool EditEngine::IsHtmlImportHandlerSet() const { - return pImpEditEngine->aHtmlImportHdl.IsSet(); + return getImpl().maHtmlImportHdl.IsSet(); } bool EditEngine::IsRtfImportHandlerSet() const { - return pImpEditEngine->aRtfImportHdl.IsSet(); + return getImpl().maRtfImportHdl.IsSet(); } bool EditEngine::IsImportRTFStyleSheetsSet() const { - return pImpEditEngine->GetStatus().DoImportRTFStyleSheets(); + return getImpl().GetStatus().DoImportRTFStyleSheets(); } void EditEngine::CallHtmlImportHandler(HtmlImportInfo& rInfo) { - pImpEditEngine->aHtmlImportHdl.Call(rInfo); + getImpl().maHtmlImportHdl.Call(rInfo); } void EditEngine::CallRtfImportHandler(RtfImportInfo& rInfo) { - pImpEditEngine->aRtfImportHdl.Call(rInfo); + getImpl().maRtfImportHdl.Call(rInfo); } EditPaM EditEngine::InsertParaBreak(const EditSelection& rEditSelection) { - return pImpEditEngine->ImpInsertParaBreak(rEditSelection); + return getImpl().ImpInsertParaBreak(rEditSelection); } EditPaM EditEngine::InsertLineBreak(const EditSelection& rEditSelection) { - return pImpEditEngine->InsertLineBreak(rEditSelection); + return getImpl().InsertLineBreak(rEditSelection); } sal_Int32 EditEngine::GetOverflowingParaNum() const { - return pImpEditEngine->GetOverflowingParaNum(); + return getImpl().GetOverflowingParaNum(); } sal_Int32 EditEngine::GetOverflowingLineNum() const { - return pImpEditEngine->GetOverflowingLineNum(); + return getImpl().GetOverflowingLineNum(); } void EditEngine::ClearOverflowingParaNum() { - pImpEditEngine->ClearOverflowingParaNum(); + getImpl().ClearOverflowingParaNum(); } bool EditEngine::IsPageOverflow() { - pImpEditEngine->CheckPageOverflow(); - return pImpEditEngine->IsPageOverflow(); + getImpl().CheckPageOverflow(); + return getImpl().IsPageOverflow(); } void EditEngine::DisableAttributeExpanding() { - pImpEditEngine->GetEditDoc().DisableAttributeExpanding(); + getImpl().GetEditDoc().DisableAttributeExpanding(); +} + +void EditEngine::EnableSkipOutsideFormat(bool bValue) +{ + getImpl().EnableSkipOutsideFormat(bValue); } void EditEngine::SetLOKSpecialPaperSize(const Size& rSize) { - pImpEditEngine->SetLOKSpecialPaperSize(rSize); + getImpl().SetLOKSpecialPaperSize(rSize); } const Size& EditEngine::GetLOKSpecialPaperSize() const { - return pImpEditEngine->GetLOKSpecialPaperSize(); + return getImpl().GetLOKSpecialPaperSize(); } EFieldInfo::EFieldInfo() diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx index e5c5cbdf4760..9b17e434e53d 100644 --- a/editeng/source/editeng/editobj.cxx +++ b/editeng/source/editeng/editobj.cxx @@ -22,12 +22,10 @@ #include <o3tl/safeint.hxx> #include <sal/log.hxx> -#include <editeng/fieldupdater.hxx> #include <editeng/macros.hxx> #include <editeng/section.hxx> #include "editobj2.hxx" #include <editeng/editdata.hxx> -#include <editattr.hxx> #include <editeng/editeng.hxx> #include <editeng/flditem.hxx> @@ -46,37 +44,32 @@ using std::endl; using namespace com::sun::star; -static XEditAttribute MakeXEditAttribute( SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ) -{ - // Create the new attribute in the pool - const SfxPoolItem& rNew = rPool.Put( rItem ); - - return XEditAttribute( rNew, nStart, nEnd ); -} - -XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) - : pItem(&rAttr) - , nStart(nS) - , nEnd(nE) +XEditAttribute::XEditAttribute(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nS, sal_Int32 nE) +: maItemHolder(rPool, &rItem) +, nStart(nS) +, nEnd(nE) { } bool XEditAttribute::IsFeature() const { - sal_uInt16 nWhich = pItem->Which(); + sal_uInt16 nWhich = GetItem()->Which(); return ((nWhich >= EE_FEATURE_START) && (nWhich <= EE_FEATURE_END)); } -void XEditAttribute::SetItem(const SfxPoolItem& rNew) +void XEditAttribute::SetItem(SfxItemPool& rPool, const SfxPoolItem& rItem) { - pItem = &rNew; + maItemHolder = SfxPoolItemHolder(rPool, &rItem); } -XParaPortionList::XParaPortionList( - OutputDevice* pRefDev, sal_uInt32 nPW, sal_uInt16 _nStretchX, sal_uInt16 _nStretchY) +XParaPortionList::XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, + double fFontScaleX, double fFontScaleY, + double fSpacingScaleX, double fSpacingScaleY) : pRefDevPtr(pRefDev) - , nStretchX(_nStretchX) - , nStretchY(_nStretchY) + , mfFontScaleX(fFontScaleX) + , mfFontScaleY(fFontScaleY) + , mfSpacingScaleX(fSpacingScaleX) + , mfSpacingScaleY(fSpacingScaleY) , nPaperWidth(nPW) { } @@ -93,7 +86,7 @@ const XParaPortion& XParaPortionList::operator [](size_t i) const ContentInfo::ContentInfo( SfxItemPool& rPool ) : eFamily(SfxStyleFamily::Para), - aParaAttribs(rPool, svl::Items<EE_PARA_START, EE_CHAR_END>{}) + aParaAttribs(rPool) { } @@ -102,16 +95,14 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse maText(rCopyFrom.maText), aStyle(rCopyFrom.aStyle), eFamily(rCopyFrom.eFamily), - aParaAttribs(rPoolToUse, svl::Items<EE_PARA_START, EE_CHAR_END>{}) + aParaAttribs(rPoolToUse) { // this should ensure that the Items end up in the correct Pool! aParaAttribs.Set( rCopyFrom.GetParaAttribs() ); for (const XEditAttribute & rAttr : rCopyFrom.maCharAttribs) { - XEditAttribute aMyAttr = MakeXEditAttribute( - rPoolToUse, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd()); - maCharAttribs.push_back(aMyAttr); + maCharAttribs.emplace_back(rPoolToUse, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd()); } if ( rCopyFrom.GetWrongList() ) @@ -120,8 +111,6 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse ContentInfo::~ContentInfo() { - for (auto const& charAttrib : maCharAttribs) - aParaAttribs.GetPool()->Remove(*charAttrib.GetItem()); maCharAttribs.clear(); } @@ -137,6 +126,12 @@ OUString ContentInfo::GetText() const return OUString(p); } +sal_Int32 ContentInfo::GetTextLen() const +{ + const rtl_uString* p = maText.getData(); + return p->length; +} + void ContentInfo::SetText( const OUString& rStr ) { maText = svl::SharedString(rStr.pData, nullptr); @@ -147,15 +142,17 @@ void ContentInfo::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentInfo")); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("style"), BAD_CAST(aStyle.toUtf8().getStr())); (void)xmlTextWriterStartElement(pWriter, BAD_CAST("text")); - (void)xmlTextWriterWriteString(pWriter, BAD_CAST(GetText().toUtf8().getStr())); + OUString aText = GetText(); + // TODO share code with sax_fastparser::FastSaxSerializer::write(). + (void)xmlTextWriterWriteString(pWriter, BAD_CAST(aText.replaceAll("\x01", "").toUtf8().getStr())); (void)xmlTextWriterEndElement(pWriter); aParaAttribs.dumpAsXml(pWriter); - for (size_t i=0; i<maCharAttribs.size(); ++i) + for (auto const& rCharAttribs : maCharAttribs) { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("attribs")); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("start"), "%" SAL_PRIdINT32, maCharAttribs[i].GetStart()); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("end"), "%" SAL_PRIdINT32, maCharAttribs[i].GetEnd()); - maCharAttribs[i].GetItem()->dumpAsXml(pWriter); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("start"), "%" SAL_PRIdINT32, rCharAttribs.GetStart()); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("end"), "%" SAL_PRIdINT32, rCharAttribs.GetEnd()); + rCharAttribs.GetItem()->dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } (void)xmlTextWriterEndElement(pWriter); @@ -206,197 +203,19 @@ bool ContentInfo::Equals(const ContentInfo& rCompare, bool bComparePool) const && maCharAttribs == rCompare.maCharAttribs; } -EditTextObject::EditTextObject( SfxItemPool* pPool ) : - mpImpl(new EditTextObjectImpl(this, pPool)) -{ -} - -EditTextObject::EditTextObject( const EditTextObject& r ) : - mpImpl(new EditTextObjectImpl(this, *r.mpImpl)) -{ -} - -EditTextObject::~EditTextObject() -{ -} - -sal_Int32 EditTextObject::GetParagraphCount() const -{ - return mpImpl->GetParagraphCount(); -} - -OUString EditTextObject::GetText(sal_Int32 nPara) const -{ - return mpImpl->GetText(nPara); -} - -void EditTextObject::ClearPortionInfo() -{ - mpImpl->ClearPortionInfo(); -} - -bool EditTextObject::HasOnlineSpellErrors() const -{ - return mpImpl->HasOnlineSpellErrors(); -} - -void EditTextObject::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const -{ - mpImpl->GetCharAttribs(nPara, rLst); -} - -bool EditTextObject::IsFieldObject() const -{ - return mpImpl->IsFieldObject(); -} - -const SvxFieldItem* EditTextObject::GetField() const -{ - return mpImpl->GetField(); -} - -const SvxFieldData* EditTextObject::GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const -{ - return mpImpl->GetFieldData(nPara, nPos, nType); -} - -bool EditTextObject::HasField( sal_Int32 nType ) const -{ - return mpImpl->HasField(nType); -} - -const SfxItemSet& EditTextObject::GetParaAttribs(sal_Int32 nPara) const -{ - return mpImpl->GetParaAttribs(nPara); -} - -bool EditTextObject::RemoveCharAttribs( sal_uInt16 nWhich ) -{ - return mpImpl->RemoveCharAttribs(nWhich); -} - -void EditTextObject::GetAllSections( std::vector<editeng::Section>& rAttrs ) const -{ - mpImpl->GetAllSections(rAttrs); -} - -void EditTextObject::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const -{ - mpImpl->GetStyleSheet(nPara, rName, eFamily); -} - -void EditTextObject::SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& eFamily) -{ - mpImpl->SetStyleSheet(nPara, rName, eFamily); -} - -bool EditTextObject::ChangeStyleSheets( - std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily) -{ - return mpImpl->ChangeStyleSheets(rOldName, eOldFamily, rNewName, eNewFamily); -} - -void EditTextObject::ChangeStyleSheetName( - SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName) -{ - mpImpl->ChangeStyleSheetName(eFamily, rOldName, rNewName); -} - -editeng::FieldUpdater EditTextObject::GetFieldUpdater() const -{ - return mpImpl->GetFieldUpdater(); -} - -void EditTextObject::NormalizeString( svl::SharedStringPool& rPool ) -{ - mpImpl->NormalizeString(rPool); -} - -std::vector<svl::SharedString> EditTextObject::GetSharedStrings() const -{ - return mpImpl->GetSharedStrings(); -} - -const SfxItemPool* EditTextObject::GetPool() const -{ - return mpImpl->GetPool(); -} - -OutlinerMode EditTextObject::GetUserType() const -{ - return mpImpl->GetUserType(); -} - -void EditTextObject::SetUserType( OutlinerMode n ) -{ - mpImpl->SetUserType(n); -} - -bool EditTextObject::IsVertical() const -{ - return mpImpl->IsVertical(); -} - -bool EditTextObject::GetDirectVertical() const -{ - return mpImpl->GetDirectVertical(); -} - -bool EditTextObject::IsTopToBottom() const -{ - return mpImpl->IsTopToBottom(); -} - -void EditTextObject::SetVertical( bool bVertical ) -{ - return mpImpl->SetVertical(bVertical); -} - -void EditTextObject::SetRotation( TextRotation nRotation ) -{ - mpImpl->SetRotation(nRotation); -} - -TextRotation EditTextObject::GetRotation() const -{ - return mpImpl->GetRotation(); -} - -SvtScriptType EditTextObject::GetScriptType() const -{ - return mpImpl->GetScriptType(); -} - - -std::unique_ptr<EditTextObject> EditTextObject::Clone() const -{ - return std::unique_ptr<EditTextObject>(new EditTextObject(*this)); -} +EditTextObject::~EditTextObject() = default; -bool EditTextObject::operator==( const EditTextObject& rCompare ) const +std::unique_ptr<EditTextObject> EditTextObjectImpl::Clone() const { - return mpImpl->operator==(*rCompare.mpImpl); + return std::make_unique<EditTextObjectImpl>(*this); } bool EditTextObject::Equals( const EditTextObject& rCompare ) const { - return mpImpl->Equals(*rCompare.mpImpl, false/*bComparePool*/); -} - -// #i102062# -bool EditTextObject::isWrongListEqual(const EditTextObject& rCompare) const -{ - return mpImpl->isWrongListEqual(*rCompare.mpImpl); + return toImpl(*this).Equals(toImpl(rCompare), false /*bComparePool*/); } -#if DEBUG_EDIT_ENGINE -void EditTextObject::Dump() const -{ - mpImpl->Dump(); -} -#endif - -void EditTextObject::dumpAsXml(xmlTextWriterPtr pWriter) const +void EditTextObjectImpl::dumpAsXml(xmlTextWriterPtr pWriter) const { bool bOwns = false; if (!pWriter) @@ -412,7 +231,7 @@ void EditTextObject::dumpAsXml(xmlTextWriterPtr pWriter) const sal_Int32 nCount = GetParagraphCount(); for (sal_Int32 i = 0; i < nCount; ++i) { - mpImpl->aContents[i]->dumpAsXml(pWriter); + maContents[i]->dumpAsXml(pWriter); } (void)xmlTextWriterEndElement(pWriter); @@ -426,86 +245,51 @@ void EditTextObject::dumpAsXml(xmlTextWriterPtr pWriter) const #if DEBUG_EDIT_ENGINE void EditTextObjectImpl::Dump() const { - for (auto const& content : aContents) + for (auto const& content : maContents) content.Dump(); } #endif -static EditEngineItemPool* getEditEngineItemPool(SfxItemPool* pPool) +static rtl::Reference<SfxItemPool> getEditEngineItemPool(SfxItemPool* pPool, MapUnit eDefaultMetric) { - EditEngineItemPool* pRetval = dynamic_cast< EditEngineItemPool* >(pPool); - - while(!pRetval && pPool && pPool->GetSecondaryPool()) - { - pPool = pPool->GetSecondaryPool(); - - if(pPool) - { - pRetval = dynamic_cast< EditEngineItemPool* >(pPool); - } - } - - return pRetval; -} - -EditTextObjectImpl::EditTextObjectImpl( EditTextObject* pFront, SfxItemPool* pP ) - : mpFront(pFront) - , nMetric(0xFFFF) - , nUserType(OutlinerMode::DontKnow) - , nScriptType(SvtScriptType::NONE) - , bVertical(false) - , mnRotation(TextRotation::NONE) -{ - // #i101239# ensure target is an EditEngineItemPool, else - // fallback to pool ownership. This is needed to ensure that at + // #i101239# ensure target is an EditEngineItemPool, so that at // pool destruction time of an alien pool, the pool is still alive. // When registering would happen at an alien pool which just uses an // EditEngineItemPool as some sub-pool, that pool could already // be decoupled and deleted which would lead to crashes. - pPool = getEditEngineItemPool(pP); + for (; pPool; pPool = pPool->GetSecondaryPool()) + if (dynamic_cast<EditEngineItemPool*>(pPool)) + return pPool; - if ( pPool ) - { - bOwnerOfPool = false; - } - else - { - pPool = EditEngine::CreatePool(); - bOwnerOfPool = true; - } + auto pRetval = EditEngine::CreatePool(); + pRetval->SetDefaultMetric(eDefaultMetric); + return pRetval; } -EditTextObjectImpl::EditTextObjectImpl( EditTextObject* pFront, const EditTextObjectImpl& r ) - : mpFront(pFront) - , nMetric(r.nMetric) - , nUserType(r.nUserType) - , nScriptType(r.nScriptType) - , bVertical(r.bVertical) - , mnRotation(r.mnRotation) +EditTextObjectImpl::EditTextObjectImpl(SfxItemPool* pP, MapUnit eDefaultMetric, bool bVertical, + TextRotation eRotation, SvtScriptType eScriptType) + : mpPool(getEditEngineItemPool(pP, eDefaultMetric)) + , meUserType(OutlinerMode::DontKnow) + , meScriptType(eScriptType) + , meRotation(eRotation) + , meMetric(eDefaultMetric) + , mbVertical(bVertical) { - // Do not copy PortionInfo - - if ( !r.bOwnerOfPool ) - { - // reuse alien pool; this must be an EditEngineItemPool - // since there is no other way to construct a BinTextObject - // than it's regular constructor where that is ensured - pPool = r.pPool; - bOwnerOfPool = false; - } - else - { - pPool = EditEngine::CreatePool(); - bOwnerOfPool = true; - - } +} - if (bOwnerOfPool && r.pPool) - pPool->SetDefaultMetric( r.pPool->GetMetric( DEF_METRIC ) ); +EditTextObjectImpl::EditTextObjectImpl( const EditTextObjectImpl& r ) + : mpPool(r.mpPool) + , meUserType(r.meUserType) + , meScriptType(r.meScriptType) + , meRotation(r.meRotation) + , meMetric(r.meMetric) + , mbVertical(r.mbVertical) +{ + // Do not copy PortionInfo - aContents.reserve(r.aContents.size()); - for (auto const& content : r.aContents) - aContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*content, *pPool))); + maContents.reserve(r.maContents.size()); + for (auto const& content : r.maContents) + maContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*content, *mpPool))); } EditTextObjectImpl::~EditTextObjectImpl() @@ -514,18 +298,18 @@ EditTextObjectImpl::~EditTextObjectImpl() // Remove contents before deleting the pool instance since each content // has to access the pool instance in its destructor. - aContents.clear(); + maContents.clear(); } void EditTextObjectImpl::SetUserType( OutlinerMode n ) { - nUserType = n; + meUserType = n; } void EditTextObjectImpl::NormalizeString( svl::SharedStringPool& rPool ) { - for (auto const& content : aContents) + for (auto const& content : maContents) { ContentInfo& rInfo = *content; rInfo.NormalizeString(rPool); @@ -535,8 +319,8 @@ void EditTextObjectImpl::NormalizeString( svl::SharedStringPool& rPool ) std::vector<svl::SharedString> EditTextObjectImpl::GetSharedStrings() const { std::vector<svl::SharedString> aSSs; - aSSs.reserve(aContents.size()); - for (auto const& content : aContents) + aSSs.reserve(maContents.size()); + for (auto const& content : maContents) { const ContentInfo& rInfo = *content; aSSs.push_back(rInfo.GetSharedString()); @@ -544,72 +328,60 @@ std::vector<svl::SharedString> EditTextObjectImpl::GetSharedStrings() const return aSSs; } -bool EditTextObjectImpl::IsVertical() const +bool EditTextObjectImpl::IsEffectivelyVertical() const { - return (bVertical && mnRotation == TextRotation::NONE) || - (!bVertical && mnRotation != TextRotation::NONE); + return (mbVertical && meRotation == TextRotation::NONE) || + (!mbVertical && meRotation != TextRotation::NONE); } bool EditTextObjectImpl::IsTopToBottom() const { - return (bVertical && mnRotation == TextRotation::NONE) || - (!bVertical && mnRotation == TextRotation::TOPTOBOTTOM); + return (mbVertical && meRotation == TextRotation::NONE) || + (!mbVertical && meRotation == TextRotation::TOPTOBOTTOM); } void EditTextObjectImpl::SetVertical( bool bVert) { - if (bVert != bVertical) + if (bVert != mbVertical) { - bVertical = bVert; + mbVertical = bVert; ClearPortionInfo(); } } -bool EditTextObjectImpl::GetDirectVertical() const +bool EditTextObjectImpl::GetVertical() const { - return bVertical; + return mbVertical; } void EditTextObjectImpl::SetRotation(TextRotation nRotation) { - if (mnRotation != nRotation) + if (meRotation != nRotation) { - mnRotation = nRotation; + meRotation = nRotation; ClearPortionInfo(); } } TextRotation EditTextObjectImpl::GetRotation() const { - return mnRotation; -} - - -void EditTextObjectImpl::SetScriptType( SvtScriptType nType ) -{ - nScriptType = nType; + return meRotation; } XEditAttribute EditTextObjectImpl::CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ) { - return MakeXEditAttribute( *pPool, rItem, nStart, nEnd ); + return XEditAttribute(*mpPool, rItem, nStart, nEnd); } -void EditTextObjectImpl::DestroyAttrib( const XEditAttribute& rAttr ) -{ - pPool->Remove( *rAttr.GetItem() ); -} - - ContentInfo* EditTextObjectImpl::CreateAndInsertContent() { - aContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*pPool))); - return aContents.back().get(); + maContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*mpPool))); + return maContents.back().get(); } sal_Int32 EditTextObjectImpl::GetParagraphCount() const { - size_t nSize = aContents.size(); + size_t nSize = maContents.size(); if (nSize > EE_PARA_MAX_COUNT) { SAL_WARN( "editeng", "EditTextObjectImpl::GetParagraphCount - overflow " << nSize); @@ -620,20 +392,28 @@ sal_Int32 EditTextObjectImpl::GetParagraphCount() const OUString EditTextObjectImpl::GetText(sal_Int32 nPara) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= aContents.size()) + if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) return OUString(); - return aContents[nPara]->GetText(); + return maContents[nPara]->GetText(); +} + +sal_Int32 EditTextObjectImpl::GetTextLen(sal_Int32 nPara ) const +{ + if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) + return 0; + + return maContents[nPara]->GetTextLen(); } void EditTextObjectImpl::ClearPortionInfo() { - pPortionInfo.reset(); + mpPortionInfo.reset(); } bool EditTextObjectImpl::HasOnlineSpellErrors() const { - for (auto const& content : aContents) + for (auto const& content : maContents) { if ( content->GetWrongList() && !content->GetWrongList()->empty() ) return true; @@ -643,11 +423,11 @@ bool EditTextObjectImpl::HasOnlineSpellErrors() const void EditTextObjectImpl::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= aContents.size()) + if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) return; rLst.clear(); - const ContentInfo& rC = *aContents[nPara]; + const ContentInfo& rC = *maContents[nPara]; for (const XEditAttribute & rAttr : rC.maCharAttribs) { EECharAttrib aEEAttr(rAttr.GetStart(), rAttr.GetEnd(), rAttr.GetItem()); @@ -662,9 +442,9 @@ bool EditTextObjectImpl::IsFieldObject() const const SvxFieldItem* EditTextObjectImpl::GetField() const { - if (aContents.size() == 1) + if (maContents.size() == 1) { - const ContentInfo& rC = *aContents[0]; + const ContentInfo& rC = *maContents[0]; if (rC.GetText().getLength() == 1) { size_t nAttribs = rC.maCharAttribs.size(); @@ -681,10 +461,10 @@ const SvxFieldItem* EditTextObjectImpl::GetField() const const SvxFieldData* EditTextObjectImpl::GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= aContents.size()) + if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) return nullptr; - const ContentInfo& rC = *aContents[nPara]; + const ContentInfo& rC = *maContents[nPara]; if (nPos >= rC.maCharAttribs.size()) // URL position is out-of-bound. return nullptr; @@ -714,10 +494,10 @@ const SvxFieldData* EditTextObjectImpl::GetFieldData(sal_Int32 nPara, size_t nPo bool EditTextObjectImpl::HasField( sal_Int32 nType ) const { - size_t nParagraphs = aContents.size(); + size_t nParagraphs = maContents.size(); for (size_t nPara = 0; nPara < nParagraphs; ++nPara) { - const ContentInfo& rC = *aContents[nPara]; + const ContentInfo& rC = *maContents[nPara]; size_t nAttrs = rC.maCharAttribs.size(); for (size_t nAttr = 0; nAttr < nAttrs; ++nAttr) { @@ -739,7 +519,7 @@ bool EditTextObjectImpl::HasField( sal_Int32 nType ) const const SfxItemSet& EditTextObjectImpl::GetParaAttribs(sal_Int32 nPara) const { - const ContentInfo& rC = *aContents[nPara]; + const ContentInfo& rC = *maContents[nPara]; return rC.GetParaAttribs(); } @@ -747,16 +527,15 @@ bool EditTextObjectImpl::RemoveCharAttribs( sal_uInt16 _nWhich ) { bool bChanged = false; - for ( size_t nPara = aContents.size(); nPara; ) + for ( size_t nPara = maContents.size(); nPara; ) { - ContentInfo& rC = *aContents[--nPara]; + ContentInfo& rC = *maContents[--nPara]; for (size_t nAttr = rC.maCharAttribs.size(); nAttr; ) { XEditAttribute& rAttr = rC.maCharAttribs[--nAttr]; if ( !_nWhich || (rAttr.GetItem()->Which() == _nWhich) ) { - pPool->Remove(*rAttr.GetItem()); rC.maCharAttribs.erase(rC.maCharAttribs.begin()+nAttr); bChanged = true; } @@ -799,13 +578,13 @@ public: void EditTextObjectImpl::GetAllSections( std::vector<editeng::Section>& rAttrs ) const { std::vector<editeng::Section> aAttrs; - aAttrs.reserve(aContents.size()); + aAttrs.reserve(maContents.size()); std::vector<size_t> aBorders; - for (size_t nPara = 0; nPara < aContents.size(); ++nPara) + for (size_t nPara = 0; nPara < maContents.size(); ++nPara) { aBorders.clear(); - const ContentInfo& rC = *aContents[nPara]; + const ContentInfo& rC = *maContents[nPara]; aBorders.push_back(0); aBorders.push_back(rC.GetText().getLength()); for (const XEditAttribute & rAttr : rC.maCharAttribs) @@ -849,9 +628,9 @@ void EditTextObjectImpl::GetAllSections( std::vector<editeng::Section>& rAttrs ) // Go through all formatted paragraphs, and store format items. std::vector<editeng::Section>::iterator itAttr = aAttrs.begin(); - for (sal_Int32 nPara = 0; nPara < static_cast<sal_Int32>(aContents.size()); ++nPara) + for (sal_Int32 nPara = 0; nPara < static_cast<sal_Int32>(maContents.size()); ++nPara) { - const ContentInfo& rC = *aContents[nPara]; + const ContentInfo& rC = *maContents[nPara]; itAttr = std::find_if(itAttr, aAttrs.end(), FindByParagraph(nPara)); if (itAttr == aAttrs.end()) @@ -901,20 +680,20 @@ void EditTextObjectImpl::GetAllSections( std::vector<editeng::Section>& rAttrs ) void EditTextObjectImpl::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& rFamily) const { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= aContents.size()) + if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) return; - const ContentInfo& rC = *aContents[nPara]; + const ContentInfo& rC = *maContents[nPara]; rName = rC.GetStyle(); rFamily = rC.GetFamily(); } void EditTextObjectImpl::SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& rFamily) { - if (nPara < 0 || o3tl::make_unsigned(nPara) >= aContents.size()) + if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) return; - ContentInfo& rC = *aContents[nPara]; + ContentInfo& rC = *maContents[nPara]; rC.SetStyle(rName); rC.SetFamily(rFamily); } @@ -923,12 +702,12 @@ bool EditTextObjectImpl::ImpChangeStyleSheets( std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily ) { - const size_t nParagraphs = aContents.size(); + const size_t nParagraphs = maContents.size(); bool bChanges = false; for (size_t nPara = 0; nPara < nParagraphs; ++nPara) { - ContentInfo& rC = *aContents[nPara]; + ContentInfo& rC = *maContents[nPara]; if ( rC.GetFamily() == eOldFamily ) { if ( rC.GetStyle() == rOldName ) @@ -959,9 +738,9 @@ void EditTextObjectImpl::ChangeStyleSheetName( SfxStyleFamily eFamily, ImpChangeStyleSheets( rOldName, eFamily, rNewName, eFamily ); } -bool EditTextObjectImpl::operator==( const EditTextObjectImpl& rCompare ) const +bool EditTextObjectImpl::operator==( const EditTextObject& rCompare ) const { - return Equals( rCompare, true); + return Equals(toImpl(rCompare), true); } bool EditTextObjectImpl::Equals( const EditTextObjectImpl& rCompare, bool bComparePool ) const @@ -969,44 +748,26 @@ bool EditTextObjectImpl::Equals( const EditTextObjectImpl& rCompare, bool bCompa if( this == &rCompare ) return true; - if( ( aContents.size() != rCompare.aContents.size() ) || - ( bComparePool && pPool != rCompare.pPool ) || - ( nMetric != rCompare.nMetric ) || - ( nUserType!= rCompare.nUserType ) || - ( nScriptType != rCompare.nScriptType ) || - ( bVertical != rCompare.bVertical ) || - ( mnRotation != rCompare.mnRotation ) ) + if( ( bComparePool && mpPool != rCompare.mpPool ) || + ( meMetric != rCompare.meMetric ) || + ( meUserType!= rCompare.meUserType ) || + ( meScriptType != rCompare.meScriptType ) || + ( mbVertical != rCompare.mbVertical ) || + ( meRotation != rCompare.meRotation ) ) return false; - for (size_t i = 0, n = aContents.size(); i < n; ++i) - { - if (!(aContents[i]->Equals( *(rCompare.aContents[i]), bComparePool))) - return false; - } - - return true; + return std::equal( + maContents.begin(), maContents.end(), rCompare.maContents.begin(), rCompare.maContents.end(), + [bComparePool](const auto& c1, const auto& c2) { return c1->Equals(*c2, bComparePool); }); } // #i102062# -bool EditTextObjectImpl::isWrongListEqual(const EditTextObjectImpl& rCompare) const +bool EditTextObjectImpl::isWrongListEqual(const EditTextObject& rComp) const { - if (aContents.size() != rCompare.aContents.size()) - { - return false; - } - - for (size_t i = 0, n = aContents.size(); i < n; ++i) - { - const ContentInfo& rCandA = *aContents[i]; - const ContentInfo& rCandB = *rCompare.aContents[i]; - - if(!rCandA.isWrongListEqual(rCandB)) - { - return false; - } - } - - return true; + const EditTextObjectImpl& rCompare = toImpl(rComp); + return std::equal( + maContents.begin(), maContents.end(), rCompare.maContents.begin(), rCompare.maContents.end(), + [](const auto& c1, const auto& c2) { return c1->isWrongListEqual(*c2); }); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx index 3c7f171d2da5..4392022b77a3 100644 --- a/editeng/source/editeng/editobj2.hxx +++ b/editeng/source/editeng/editobj2.hxx @@ -26,6 +26,8 @@ #include <svl/sharedstring.hxx> #include <svl/languageoptions.hxx> +#include <tools/long.hxx> +#include <tools/mapunit.hxx> #include <memory> #include <vector> @@ -45,14 +47,14 @@ class SharedStringPool; class XEditAttribute { private: - const SfxPoolItem* pItem; + SfxPoolItemHolder maItemHolder; sal_Int32 nStart; sal_Int32 nEnd; public: - XEditAttribute( const SfxPoolItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd ); + XEditAttribute(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd ); - const SfxPoolItem* GetItem() const { return pItem; } + const SfxPoolItem* GetItem() const { return maItemHolder.getItem(); } sal_Int32& GetStart() { return nStart; } sal_Int32& GetEnd() { return nEnd; } @@ -63,7 +65,7 @@ public: sal_Int32 GetLen() const { return nEnd-nStart; } bool IsFeature() const; - void SetItem(const SfxPoolItem& rNew); + void SetItem(SfxItemPool&, const SfxPoolItem&); inline bool operator==( const XEditAttribute& rCompare ) const; }; @@ -72,9 +74,7 @@ inline bool XEditAttribute::operator==( const XEditAttribute& rCompare ) const { return (nStart == rCompare.nStart) && (nEnd == rCompare.nEnd) && - ((pItem == rCompare.pItem) || - ((pItem->Which() == rCompare.pItem->Which()) && - (*pItem == *rCompare.pItem))); + SfxPoolItem::areSame(GetItem(), rCompare.GetItem()); } struct XParaPortion @@ -92,12 +92,14 @@ class XParaPortionList ListType maList; VclPtr<OutputDevice> pRefDevPtr; - sal_uInt16 nStretchX; - sal_uInt16 nStretchY; + double mfFontScaleX; + double mfFontScaleY; + double mfSpacingScaleX; + double mfSpacingScaleY; sal_uInt32 nPaperWidth; public: - XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, sal_uInt16 _nStretchX, sal_uInt16 _nStretchY); + XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY); void push_back(XParaPortion* p); const XParaPortion& operator[](size_t i) const; @@ -106,8 +108,10 @@ public: sal_uInt32 GetPaperWidth() const { return nPaperWidth; } bool RefDevIsVirtual() const {return pRefDevPtr->IsVirtual();} const MapMode& GetRefMapMode() const { return pRefDevPtr->GetMapMode(); } - sal_uInt16 GetStretchX() const { return nStretchX; } - sal_uInt16 GetStretchY() const { return nStretchY; } + double getFontScaleX() const { return mfFontScaleX; } + double getFontScaleY() const { return mfFontScaleY; } + double getSpacingScaleX() const { return mfSpacingScaleX; } + double getSpacingScaleY() const { return mfSpacingScaleY; } }; class ContentInfo @@ -120,7 +124,7 @@ private: std::vector<XEditAttribute> maCharAttribs; SfxStyleFamily eFamily; - SfxItemSet aParaAttribs; + SfxItemSetFixed<EE_PARA_START, EE_CHAR_END> aParaAttribs; std::unique_ptr<WrongList> mpWrongs; @@ -136,6 +140,7 @@ public: const svl::SharedString& GetSharedString() const { return maText;} OUString GetText() const; void SetText( const OUString& rStr ); + sal_Int32 GetTextLen() const; void dumpAsXml(xmlTextWriterPtr pWriter) const; @@ -163,109 +168,117 @@ public: #endif }; -class EditTextObjectImpl +class EditTextObjectImpl final : public EditTextObject { -friend class EditTextObject; public: typedef std::vector<std::unique_ptr<ContentInfo> > ContentInfosType; private: - EditTextObject* mpFront; + ContentInfosType maContents; + rtl::Reference<SfxItemPool> mpPool; + std::unique_ptr<XParaPortionList> mpPortionInfo; - ContentInfosType aContents; - rtl::Reference<SfxItemPool> pPool; - std::unique_ptr<XParaPortionList> pPortionInfo; + OutlinerMode meUserType; + SvtScriptType meScriptType; + TextRotation meRotation; + MapUnit meMetric; - sal_uInt16 nMetric; - OutlinerMode nUserType; - SvtScriptType nScriptType; - - bool bOwnerOfPool:1; - bool bVertical:1; - TextRotation mnRotation; + bool mbVertical; bool ImpChangeStyleSheets( std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily ); public: - EditTextObjectImpl( EditTextObject* pFront, SfxItemPool* pPool ); - EditTextObjectImpl( EditTextObject* pFront, const EditTextObjectImpl& r ); - ~EditTextObjectImpl(); + EditTextObjectImpl(SfxItemPool* pPool, MapUnit eDefaultMetric, bool bVertical, + TextRotation eRotation, SvtScriptType eScriptType); + EditTextObjectImpl( const EditTextObjectImpl& r ); + virtual ~EditTextObjectImpl() override; - EditTextObjectImpl(const EditTextObjectImpl&) = delete; EditTextObjectImpl& operator=(const EditTextObjectImpl&) = delete; - OutlinerMode GetUserType() const { return nUserType;} - void SetUserType( OutlinerMode n ); + virtual OutlinerMode GetUserType() const override { return meUserType;} + virtual void SetUserType( OutlinerMode n ) override; - void NormalizeString( svl::SharedStringPool& rPool ); - std::vector<svl::SharedString> GetSharedStrings() const; + virtual void NormalizeString( svl::SharedStringPool& rPool ) override; + virtual std::vector<svl::SharedString> GetSharedStrings() const override; + + virtual bool IsEffectivelyVertical() const override; + virtual bool GetVertical() const override; + virtual bool IsTopToBottom() const override; + virtual void SetVertical( bool bVert) override; + virtual void SetRotation(TextRotation nRotation) override; + virtual TextRotation GetRotation() const override; - bool IsVertical() const; - bool GetDirectVertical() const; - bool IsTopToBottom() const; - void SetVertical( bool bVert); - void SetRotation(TextRotation nRotation); - TextRotation GetRotation() const; + virtual SvtScriptType GetScriptType() const override { return meScriptType;} - SvtScriptType GetScriptType() const { return nScriptType;} - void SetScriptType( SvtScriptType nType ); + virtual std::unique_ptr<EditTextObject> Clone() const override; ContentInfo* CreateAndInsertContent(); XEditAttribute CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ); - void DestroyAttrib( const XEditAttribute& rAttr ); - ContentInfosType& GetContents() { return aContents;} - const ContentInfosType& GetContents() const { return aContents;} - SfxItemPool* GetPool() const { return pPool.get(); } - XParaPortionList* GetPortionInfo() const { return pPortionInfo.get(); } + ContentInfosType& GetContents() { return maContents;} + const ContentInfosType& GetContents() const { return maContents;} + SfxItemPool* GetPool() { return mpPool.get(); } + virtual const SfxItemPool* GetPool() const override { return mpPool.get(); } + XParaPortionList* GetPortionInfo() const { return mpPortionInfo.get(); } void SetPortionInfo( std::unique_ptr<XParaPortionList> pP ) - { pPortionInfo = std::move(pP); } + { mpPortionInfo = std::move(pP); } - sal_Int32 GetParagraphCount() const; - OUString GetText(sal_Int32 nParagraph) const; + virtual sal_Int32 GetParagraphCount() const override; + virtual OUString GetText(sal_Int32 nParagraph) const override; + virtual sal_Int32 GetTextLen(sal_Int32 nParagraph) const override; - void ClearPortionInfo(); + virtual void ClearPortionInfo() override; - bool HasOnlineSpellErrors() const; + virtual bool HasOnlineSpellErrors() const override; - void GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const; + virtual void GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const override; - bool RemoveCharAttribs( sal_uInt16 nWhich ); + virtual bool RemoveCharAttribs( sal_uInt16 nWhich ) override; - void GetAllSections( std::vector<editeng::Section>& rAttrs ) const; + virtual void GetAllSections( std::vector<editeng::Section>& rAttrs ) const override; - bool IsFieldObject() const; - const SvxFieldItem* GetField() const; - const SvxFieldData* GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const; + virtual bool IsFieldObject() const override; + virtual const SvxFieldItem* GetField() const override; + virtual const SvxFieldData* GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const override; - bool HasField( sal_Int32 nType ) const; + virtual bool HasField( sal_Int32 nType = css::text::textfield::Type::UNSPECIFIED ) const override; - const SfxItemSet& GetParaAttribs(sal_Int32 nPara) const; + virtual const SfxItemSet& GetParaAttribs(sal_Int32 nPara) const override; - void GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const; - void SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& eFamily); - bool ChangeStyleSheets( - std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily); - void ChangeStyleSheetName(SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName); + virtual void GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const override; + virtual void SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& eFamily) override; + virtual bool ChangeStyleSheets( + std::u16string_view rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily) override; + virtual void ChangeStyleSheetName(SfxStyleFamily eFamily, std::u16string_view rOldName, const OUString& rNewName) override; - editeng::FieldUpdater GetFieldUpdater() const { return editeng::FieldUpdater(*mpFront);} + virtual editeng::FieldUpdater GetFieldUpdater() override { return editeng::FieldUpdater(*this); } - bool HasMetric() const { return nMetric != 0xFFFF; } - sal_uInt16 GetMetric() const { return nMetric; } - void SetMetric( sal_uInt16 n ) { nMetric = n; } + bool HasMetric() const { return meMetric != MapUnit::LASTENUMDUMMY; } + MapUnit GetMetric() const { return meMetric; } - bool IsOwnerOfPool() const { return bOwnerOfPool; } - - bool operator==( const EditTextObjectImpl& rCompare ) const; + virtual bool operator==( const EditTextObject& rCompare ) const override; bool Equals( const EditTextObjectImpl& rCompare, bool bComparePool ) const; // #i102062# - bool isWrongListEqual(const EditTextObjectImpl& rCompare) const; + virtual bool isWrongListEqual(const EditTextObject& rCompare) const override; #if DEBUG_EDIT_ENGINE - void Dump() const; + virtual void Dump() const override; #endif + virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; +inline EditTextObjectImpl& toImpl(EditTextObject& rObj) +{ + assert(dynamic_cast<EditTextObjectImpl*>(&rObj)); + return static_cast<EditTextObjectImpl&>(rObj); +} + +inline const EditTextObjectImpl& toImpl(const EditTextObject& rObj) +{ + assert(dynamic_cast<const EditTextObjectImpl*>(&rObj)); + return static_cast<const EditTextObjectImpl&>(rObj); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editsel.cxx b/editeng/source/editeng/editsel.cxx index 3aeed7a6e357..4bdfff88155b 100644 --- a/editeng/source/editeng/editsel.cxx +++ b/editeng/source/editeng/editsel.cxx @@ -31,7 +31,7 @@ EditSelFunctionSet::EditSelFunctionSet() void EditSelFunctionSet::CreateAnchor() { if ( pCurView ) - pCurView->pImpEditView->CreateAnchor(); + pCurView->getImpl().CreateAnchor(); } void EditSelFunctionSet::DestroyAnchor() @@ -42,13 +42,13 @@ void EditSelFunctionSet::DestroyAnchor() void EditSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool ) { if ( pCurView ) - pCurView->pImpEditView->SetCursorAtPoint( rPointPixel ); + pCurView->getImpl().SetCursorAtPoint( rPointPixel ); } bool EditSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) { if ( pCurView ) - return pCurView->pImpEditView->IsSelectionAtPoint( rPointPixel ); + return pCurView->getImpl().IsSelectionAtPoint( rPointPixel ); return false; } @@ -69,7 +69,7 @@ void EditSelFunctionSet::BeginDrag() void EditSelFunctionSet::DeselectAll() { if ( pCurView ) - pCurView->pImpEditView->DeselectAll(); + pCurView->getImpl().DeselectAll(); } diff --git a/editeng/source/editeng/editstt2.hxx b/editeng/source/editeng/editstt2.hxx index 4474df8b429b..8cc09ff5dbe0 100644 --- a/editeng/source/editeng/editstt2.hxx +++ b/editeng/source/editeng/editstt2.hxx @@ -47,7 +47,9 @@ public: { return bool( nControlBits & EEControlBits::UNDOATTRIBS ); } bool OneCharPerLine() const - { return bool( nControlBits & EEControlBits::ONECHARPERLINE ); } + { + return bool(nControlBits & (EEControlBits::ONECHARPERLINE | EEControlBits::STACKED)); + } bool IsOutliner() const { return bool( nControlBits & EEControlBits::OUTLINER ); } @@ -86,11 +88,11 @@ public: bool DoAutoComplete() const { return bool( nControlBits & EEControlBits::AUTOCOMPLETE ); } - bool DoFormat100() const - { return bool( nControlBits & EEControlBits::FORMAT100 ); } - bool ULSpaceSummation() const { return bool( nControlBits & EEControlBits::ULSPACESUMMATION ); } + + bool IsSingleLine() const + { return bool( nControlBits & EEControlBits::SINGLELINE ); } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editundo.cxx b/editeng/source/editeng/editundo.cxx index 714dd1b682ed..7ff299e7efbd 100644 --- a/editeng/source/editeng/editundo.cxx +++ b/editeng/source/editeng/editundo.cxx @@ -22,16 +22,17 @@ #include "editundo.hxx" #include <editeng/editview.hxx> #include <editeng/editeng.hxx> +#include <utility> #include <osl/diagnose.h> static void lcl_DoSetSelection( EditView const * pView, sal_uInt16 nPara ) { EPaM aEPaM( nPara, 0 ); - EditPaM aPaM( pView->GetImpEditEngine()->CreateEditPaM( aEPaM ) ); + EditPaM aPaM = pView->getImpEditEngine().CreateEditPaM(aEPaM); aPaM.SetIndex( aPaM.GetNode()->Len() ); EditSelection aSel( aPaM, aPaM ); - pView->GetImpEditView()->SetEditSelection( aSel ); + pView->getImpl().SetEditSelection( aSel ); } EditUndoManager::EditUndoManager(sal_uInt16 nMaxUndoActionCount ) @@ -63,19 +64,20 @@ bool EditUndoManager::Undo() } } - mpEditEngine->GetActiveView()->GetImpEditView()->DrawSelectionXOR(); // Remove the old selection + mpEditEngine->GetActiveView()->getImpl().DrawSelectionXOR(); // Remove the old selection mpEditEngine->SetUndoMode( true ); bool bDone = SfxUndoManager::Undo(); mpEditEngine->SetUndoMode( false ); - EditSelection aNewSel( mpEditEngine->GetActiveView()->GetImpEditView()->GetEditSelection() ); + EditSelection aNewSel( mpEditEngine->GetActiveView()->getImpl().GetEditSelection() ); DBG_ASSERT( !aNewSel.IsInvalid(), "Invalid selection after Undo () "); DBG_ASSERT( !aNewSel.DbgIsBuggy( mpEditEngine->GetEditDoc() ), "Broken selection afte Undo () "); aNewSel.Min() = aNewSel.Max(); - mpEditEngine->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); - mpEditEngine->FormatAndUpdate( mpEditEngine->GetActiveView(), true ); + mpEditEngine->GetActiveView()->getImpl().SetEditSelection( aNewSel ); + if (mpEditEngine->IsUpdateLayout()) + mpEditEngine->FormatAndLayout( mpEditEngine->GetActiveView(), true ); return bDone; } @@ -98,19 +100,20 @@ bool EditUndoManager::Redo() } } - mpEditEngine->GetActiveView()->GetImpEditView()->DrawSelectionXOR(); // Remove the old selection + mpEditEngine->GetActiveView()->getImpl().DrawSelectionXOR(); // Remove the old selection mpEditEngine->SetUndoMode( true ); bool bDone = SfxUndoManager::Redo(); mpEditEngine->SetUndoMode( false ); - EditSelection aNewSel( mpEditEngine->GetActiveView()->GetImpEditView()->GetEditSelection() ); + EditSelection aNewSel( mpEditEngine->GetActiveView()->getImpl().GetEditSelection() ); DBG_ASSERT( !aNewSel.IsInvalid(), "Invalid selection after Undo () "); DBG_ASSERT( !aNewSel.DbgIsBuggy( mpEditEngine->GetEditDoc() ), "Broken selection afte Undo () "); aNewSel.Min() = aNewSel.Max(); - mpEditEngine->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); - mpEditEngine->FormatAndUpdate( mpEditEngine->GetActiveView() ); + mpEditEngine->GetActiveView()->getImpl().SetEditSelection( aNewSel ); + if (mpEditEngine->IsUpdateLayout()) + mpEditEngine->FormatAndLayout( mpEditEngine->GetActiveView() ); return bDone; } @@ -119,7 +122,7 @@ EditUndo::EditUndo(sal_uInt16 nI, EditEngine* pEE) : nId(nI), mnViewShellId(-1), mpEditEngine(pEE) { const EditView* pEditView = mpEditEngine ? mpEditEngine->GetActiveView() : nullptr; - const OutlinerViewShell* pViewShell = pEditView ? pEditView->GetImpEditView()->GetViewShell() : nullptr; + const OutlinerViewShell* pViewShell = pEditView ? pEditView->getImpl().GetViewShell() : nullptr; if (pViewShell) mnViewShellId = pViewShell->GetViewShellId(); } @@ -154,26 +157,23 @@ ViewShellId EditUndo::GetViewShellId() const return mnViewShellId; } -EditUndoDelContent::EditUndoDelContent( - EditEngine* pEE, ContentNode* pNode, sal_Int32 nPortion) : - EditUndo(EDITUNDO_DELCONTENT, pEE), - bDelObject(true), - nNode(nPortion), - pContentNode(pNode) {} +EditUndoDelContent::EditUndoDelContent(EditEngine* pEE, std::unique_ptr<ContentNode> pNode, sal_Int32 nPortion) + : EditUndo(EDITUNDO_DELCONTENT, pEE) + , nNode(nPortion) + , mpContentNode(std::move(pNode)) +{} EditUndoDelContent::~EditUndoDelContent() { - if ( bDelObject ) - delete pContentNode; } void EditUndoDelContent::Undo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); - GetEditEngine()->InsertContent( pContentNode, nNode ); - bDelObject = false; // belongs to the Engine again - EditSelection aSel( EditPaM( pContentNode, 0 ), EditPaM( pContentNode, pContentNode->Len() ) ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + ContentNode* pNode = mpContentNode.get(); + GetEditEngine()->InsertContent(std::move(mpContentNode), nNode); + EditSelection aSel(EditPaM(pNode, 0), EditPaM(pNode, pNode->Len())); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } void EditUndoDelContent::Redo() @@ -184,40 +184,42 @@ void EditUndoDelContent::Redo() // pNode is no longer correct, if the paragraphs where merged // in between Undos - pContentNode = pEE->GetEditDoc().GetObject( nNode ); - DBG_ASSERT( pContentNode, "EditUndoDelContent::Redo(): Node?!" ); + ContentNode* pNode = pEE->GetEditDoc().GetObject(nNode); + DBG_ASSERT(pNode, "EditUndoDelContent::Redo(): Node?!"); pEE->RemoveParaPortion(nNode); // Do not delete node, depends on the undo! - pEE->GetEditDoc().Release( nNode ); + mpContentNode = pEE->GetEditDoc().Release(nNode); + assert(mpContentNode.get() == pNode); + if (pEE->IsCallParaInsertedOrDeleted()) - pEE->ParagraphDeleted( nNode ); + pEE->ParagraphDeleted(nNode); - DeletedNodeInfo* pInf = new DeletedNodeInfo( pContentNode, nNode ); - pEE->AppendDeletedNodeInfo(pInf); + DeletedNodeInfo* pDeletedNodeInfo = new DeletedNodeInfo(pNode, nNode); + pEE->AppendDeletedNodeInfo(pDeletedNodeInfo); pEE->UpdateSelections(); - ContentNode* pN = ( nNode < pEE->GetEditDoc().Count() ) - ? pEE->GetEditDoc().GetObject( nNode ) - : pEE->GetEditDoc().GetObject( nNode-1 ); - DBG_ASSERT( pN && ( pN != pContentNode ), "?! RemoveContent !? " ); - EditPaM aPaM( pN, pN->Len() ); + ContentNode* pCheckNode = (nNode < pEE->GetEditDoc().Count()) + ? pEE->GetEditDoc().GetObject(nNode) + : pEE->GetEditDoc().GetObject(nNode - 1); + + DBG_ASSERT(pCheckNode && pCheckNode != mpContentNode.get(), "?! RemoveContent !? "); - bDelObject = true; // belongs to the Engine again + EditPaM aPaM(pCheckNode, pCheckNode->Len()); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + pEE->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } EditUndoConnectParas::EditUndoConnectParas( EditEngine* pEE, sal_Int32 nN, sal_uInt16 nSP, - const SfxItemSet& rLeftParaAttribs, const SfxItemSet& rRightParaAttribs, + SfxItemSet _aLeftParaAttribs, SfxItemSet _aRightParaAttribs, const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, bool bBkwrd) : EditUndo(EDITUNDO_CONNECTPARAS, pEE), nNode(nN), nSepPos(nSP), - aLeftParaAttribs(rLeftParaAttribs), - aRightParaAttribs(rRightParaAttribs), + aLeftParaAttribs(std::move(_aLeftParaAttribs)), + aRightParaAttribs(std::move(_aRightParaAttribs)), eLeftStyleFamily(SfxStyleFamily::All), eRightStyleFamily(SfxStyleFamily::All), bBackward(bBkwrd) @@ -268,7 +270,7 @@ void EditUndoConnectParas::Undo() GetEditEngine()->SetStyleSheet( nNode+1, static_cast<SfxStyleSheet*>(GetEditEngine()->GetStyleSheetPool()->Find( aRightStyleName, eRightStyleFamily )) ); } - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } void EditUndoConnectParas::Redo() @@ -276,7 +278,7 @@ void EditUndoConnectParas::Redo() DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: Np Active View!" ); EditPaM aPaM = GetEditEngine()->ConnectContents( nNode, bBackward ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } EditUndoSplitPara::EditUndoSplitPara( @@ -290,21 +292,21 @@ void EditUndoSplitPara::Undo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); EditPaM aPaM = GetEditEngine()->ConnectContents(nNode, false); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } void EditUndoSplitPara::Redo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); EditPaM aPaM = GetEditEngine()->SplitContent(nNode, nSepPos); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } EditUndoInsertChars::EditUndoInsertChars( - EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr) : + EditEngine* pEE, const EPaM& rEPaM, OUString aStr) : EditUndo(EDITUNDO_INSERTCHARS, pEE), aEPaM(rEPaM), - aText(rStr) {} + aText(std::move(aStr)) {} void EditUndoInsertChars::Undo() { @@ -313,7 +315,7 @@ void EditUndoInsertChars::Undo() EditSelection aSel( aPaM, aPaM ); aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() ); EditPaM aNewPaM( GetEditEngine()->DeleteSelection(aSel) ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aNewPaM, aNewPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aNewPaM, aNewPaM ) ); } void EditUndoInsertChars::Redo() @@ -323,7 +325,7 @@ void EditUndoInsertChars::Redo() GetEditEngine()->InsertText(EditSelection(aPaM, aPaM), aText); EditPaM aNewPaM( aPaM ); aNewPaM.SetIndex( aNewPaM.GetIndex() + aText.getLength() ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aNewPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aNewPaM ) ); } bool EditUndoInsertChars::Merge( SfxUndoAction* pNextAction ) @@ -344,9 +346,9 @@ bool EditUndoInsertChars::Merge( SfxUndoAction* pNextAction ) } EditUndoRemoveChars::EditUndoRemoveChars( - EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr) : + EditEngine* pEE, const EPaM& rEPaM, OUString aStr) : EditUndo(EDITUNDO_REMOVECHARS, pEE), - aEPaM(rEPaM), aText(rStr) {} + aEPaM(rEPaM), aText(std::move(aStr)) {} void EditUndoRemoveChars::Undo() { @@ -355,7 +357,7 @@ void EditUndoRemoveChars::Undo() EditSelection aSel( aPaM, aPaM ); GetEditEngine()->InsertText(aSel, aText); aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } void EditUndoRemoveChars::Redo() @@ -365,7 +367,7 @@ void EditUndoRemoveChars::Redo() EditSelection aSel( aPaM, aPaM ); aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() ); EditPaM aNewPaM = GetEditEngine()->DeleteSelection(aSel); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aNewPaM); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aNewPaM); } EditUndoInsertFeature::EditUndoInsertFeature( @@ -390,7 +392,7 @@ void EditUndoInsertFeature::Undo() aSel.Max().SetIndex( aSel.Max().GetIndex()+1 ); GetEditEngine()->DeleteSelection(aSel); aSel.Max().SetIndex( aSel.Max().GetIndex()-1 ); // For Selection - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } void EditUndoInsertFeature::Redo() @@ -402,7 +404,7 @@ void EditUndoInsertFeature::Redo() if ( pFeature->Which() == EE_FEATURE_FIELD ) GetEditEngine()->UpdateFieldsOnly(); aSel.Max().SetIndex( aSel.Max().GetIndex()+1 ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } EditUndoMoveParagraphs::EditUndoMoveParagraphs( @@ -431,26 +433,26 @@ void EditUndoMoveParagraphs::Undo() nTmpDest += aTmpRange.Len(); EditSelection aNewSel = GetEditEngine()->MoveParagraphs(aTmpRange, nTmpDest); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } void EditUndoMoveParagraphs::Redo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); EditSelection aNewSel = GetEditEngine()->MoveParagraphs(nParagraphs, nDest); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } EditUndoSetStyleSheet::EditUndoSetStyleSheet( - EditEngine* pEE, sal_Int32 nP, const OUString& rPrevName, SfxStyleFamily ePrevFam, - const OUString& rNewName, SfxStyleFamily eNewFam, const SfxItemSet& rPrevParaAttribs) : + EditEngine* pEE, sal_Int32 nP, OUString _aPrevName, SfxStyleFamily ePrevFam, + OUString _aNewName, SfxStyleFamily eNewFam, SfxItemSet _aPrevParaAttribs) : EditUndo(EDITUNDO_STYLESHEET, pEE), nPara(nP), - aPrevName(rPrevName), - aNewName(rNewName), + aPrevName(std::move(_aPrevName)), + aNewName(std::move(_aNewName)), ePrevFamily(ePrevFam), eNewFamily(eNewFam), - aPrevParaAttribs(rPrevParaAttribs) + aPrevParaAttribs(std::move(_aPrevParaAttribs)) { } @@ -474,11 +476,11 @@ void EditUndoSetStyleSheet::Redo() } EditUndoSetParaAttribs::EditUndoSetParaAttribs( - EditEngine* pEE, sal_Int32 nP, const SfxItemSet& rPrevItems, const SfxItemSet& rNewItems) : + EditEngine* pEE, sal_Int32 nP, SfxItemSet _aPrevItems, SfxItemSet _aNewItems) : EditUndo(EDITUNDO_PARAATTRIBS, pEE), nPara(nP), - aPrevItems(rPrevItems), - aNewItems(rNewItems) {} + aPrevItems(std::move(_aPrevItems)), + aNewItems(std::move(_aNewItems)) {} EditUndoSetParaAttribs::~EditUndoSetParaAttribs() {} @@ -496,11 +498,12 @@ void EditUndoSetParaAttribs::Redo() lcl_DoSetSelection( GetEditEngine()->GetActiveView(), nPara ); } -EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, const SfxItemSet& rNewItems) : +EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, SfxItemSet aNewItems) : EditUndo(EDITUNDO_ATTRIBS, pEE), aESel(rESel), - aNewAttribs(rNewItems), + aNewAttribs(std::move(aNewItems)), nSpecial(SetAttribsMode::NONE), + m_bSetSelection(true), // When EditUndoSetAttribs actually is a RemoveAttribs this could be // recognize by the empty itemset, but then it would have to be caught in // its own place, which possible a setAttribs does with an empty itemset. @@ -510,26 +513,8 @@ EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, { } -namespace { - -struct RemoveAttribsFromPool -{ - SfxItemPool& mrPool; -public: - explicit RemoveAttribsFromPool(SfxItemPool& rPool) : mrPool(rPool) {} - void operator() (std::unique_ptr<ContentAttribsInfo> const & rInfo) - { - rInfo->RemoveAllCharAttribsFromPool(mrPool); - } -}; - -} - EditUndoSetAttribs::~EditUndoSetAttribs() { - // Get Items from Pool... - SfxItemPool* pPool = aNewAttribs.GetPool(); - std::for_each(aPrevAttribs.begin(), aPrevAttribs.end(), RemoveAttribsFromPool(*pPool)); } void EditUndoSetAttribs::Undo() @@ -560,7 +545,10 @@ void EditUndoSetAttribs::Undo() } if ( bFields ) pEE->UpdateFieldsOnly(); - ImpSetSelection(); + if (m_bSetSelection) + { + ImpSetSelection(); + } } void EditUndoSetAttribs::Redo() @@ -574,7 +562,10 @@ void EditUndoSetAttribs::Redo() else pEE->RemoveCharAttribs( aSel, bRemoveParaAttribs, nRemoveWhich ); - ImpSetSelection(); + if (m_bSetSelection) + { + ImpSetSelection(); + } } void EditUndoSetAttribs::AppendContentInfo(ContentAttribsInfo* pNew) @@ -586,7 +577,7 @@ void EditUndoSetAttribs::ImpSetSelection() { EditEngine* pEE = GetEditEngine(); EditSelection aSel = pEE->CreateSelection(aESel); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + pEE->GetActiveView()->getImpl().SetEditSelection(aSel); } EditUndoTransliteration::EditUndoTransliteration(EditEngine* pEE, const ESelection& rESel, TransliterationFlags nM) : @@ -610,7 +601,7 @@ void EditUndoTransliteration::Undo() EditSelection aDelSel( aSel ); aSel = pEE->InsertParaBreak( aSel ); aDelSel.Max() = aSel.Min(); - aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs( pEE->GetEditDoc().GetItemPool() ); + aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs(); EditSelection aNewSel; if ( pTxtObj ) { @@ -631,7 +622,7 @@ void EditUndoTransliteration::Undo() aNewSel.Max().SetIndex( aNewSel.Max().GetIndex() + aDelSel.Min().GetIndex() ); } pEE->DeleteSelected( aDelSel ); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + pEE->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } void EditUndoTransliteration::Redo() @@ -641,7 +632,7 @@ void EditUndoTransliteration::Redo() EditSelection aSel = pEE->CreateSelection(aOldESel); EditSelection aNewSel = pEE->TransliterateText( aSel, nMode ); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + pEE->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } EditUndoMarkSelection::EditUndoMarkSelection(EditEngine* pEE, const ESelection& rSel) : @@ -657,7 +648,7 @@ void EditUndoMarkSelection::Undo() if ( GetEditEngine()->IsFormatted() ) GetEditEngine()->GetActiveView()->SetSelection( aSelection ); else - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( GetEditEngine()->CreateSelection(aSelection) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(GetEditEngine()->CreateSelection(aSelection)); } } diff --git a/editeng/source/editeng/editundo.hxx b/editeng/source/editeng/editundo.hxx index 43d2a0d3b911..d43ba9553a39 100644 --- a/editeng/source/editeng/editundo.hxx +++ b/editeng/source/editeng/editundo.hxx @@ -36,13 +36,10 @@ enum class TransliterationFlags; class EditUndoDelContent : public EditUndo { private: - bool bDelObject; - sal_Int32 nNode; - ContentNode* pContentNode; // Points to the valid, - // undestroyed object! - + sal_Int32 nNode; + std::unique_ptr<ContentNode> mpContentNode; // Points to the valid, undestroyed object! public: - EditUndoDelContent(EditEngine* pEE, ContentNode* pNode, sal_Int32 nPortion); + EditUndoDelContent(EditEngine* pEE, std::unique_ptr<ContentNode> pNode, sal_Int32 nPortion); virtual ~EditUndoDelContent() override; virtual void Undo() override; @@ -70,7 +67,7 @@ private: public: EditUndoConnectParas(EditEngine* pEE, sal_Int32 nNode, sal_uInt16 nSepPos, - const SfxItemSet& rLeftParaAttribs, const SfxItemSet& rRightParaAttribs, + SfxItemSet aLeftParaAttribs, SfxItemSet aRightParaAttribs, const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, bool bBackward); virtual ~EditUndoConnectParas() override; @@ -105,7 +102,7 @@ private: OUString aText; public: - EditUndoInsertChars(EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr); + EditUndoInsertChars(EditEngine* pEE, const EPaM& rEPaM, OUString aStr); virtual void Undo() override; virtual void Redo() override; @@ -123,7 +120,7 @@ private: OUString aText; public: - EditUndoRemoveChars(EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr); + EditUndoRemoveChars(EditEngine* pEE, const EPaM& rEPaM, OUString aStr); virtual void Undo() override; virtual void Redo() override; @@ -178,9 +175,9 @@ private: public: EditUndoSetStyleSheet(EditEngine* pEE, sal_Int32 nPara, - const OUString& rPrevName, SfxStyleFamily ePrevFamily, - const OUString& rNewName, SfxStyleFamily eNewFamily, - const SfxItemSet& rPrevParaAttribs); + OUString aPrevName, SfxStyleFamily ePrevFamily, + OUString aNewName, SfxStyleFamily eNewFamily, + SfxItemSet aPrevParaAttribs); virtual ~EditUndoSetStyleSheet() override; virtual void Undo() override; @@ -198,7 +195,7 @@ private: SfxItemSet aNewItems; public: - EditUndoSetParaAttribs(EditEngine* pEE, sal_Int32 nPara, const SfxItemSet& rPrevItems, const SfxItemSet& rNewItems); + EditUndoSetParaAttribs(EditEngine* pEE, sal_Int32 nPara, SfxItemSet aPrevItems, SfxItemSet aNewItems); virtual ~EditUndoSetParaAttribs() override; virtual void Undo() override; @@ -218,6 +215,8 @@ private: InfoArrayType aPrevAttribs; SetAttribsMode nSpecial; + /// Once the attributes are set / unset, set the selection to the end of the formatted range? + bool m_bSetSelection; bool bSetIsRemove; bool bRemoveParaAttribs; sal_uInt16 nRemoveWhich; @@ -226,12 +225,13 @@ private: public: - EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, const SfxItemSet& rNewItems); + EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, SfxItemSet aNewItems); virtual ~EditUndoSetAttribs() override; SfxItemSet& GetNewAttribs() { return aNewAttribs; } void SetSpecial( SetAttribsMode n ) { nSpecial = n; } + void SetUpdateSelection( bool bSetSelection ) { m_bSetSelection = bSetSelection; } void SetRemoveAttribs( bool b ) { bSetIsRemove = b; } void SetRemoveParaAttribs( bool b ) { bRemoveParaAttribs = b; } void SetRemoveWhich( sal_uInt16 n ) { nRemoveWhich = n; } diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx index 512a3bf54915..81fbd2d10b39 100644 --- a/editeng/source/editeng/editview.cxx +++ b/editeng/source/editeng/editview.cxx @@ -19,12 +19,10 @@ #include <memory> -#include <sal/macros.h> #include <vcl/image.hxx> #include <com/sun/star/i18n/WordType.hpp> #include <com/sun/star/i18n/ScriptType.hpp> -#include <vcl/metric.hxx> #include <i18nlangtag/languagetag.hxx> #include <i18nlangtag/mslangid.hxx> @@ -36,6 +34,7 @@ #include <svl/srchitem.hxx> #include "impedit.hxx" +#include <comphelper/propertyvalue.hxx> #include <editeng/editeng.hxx> #include <editeng/editview.hxx> #include <editeng/flditem.hxx> @@ -50,7 +49,6 @@ #include <vcl/window.hxx> #include <editeng/acorrcfg.hxx> #include <editeng/unolingu.hxx> -#include <editeng/fontitem.hxx> #include <unotools/lingucfg.hxx> #include <com/sun/star/frame/XStorable.hpp> @@ -62,9 +60,9 @@ #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <comphelper/lok.hxx> #include <sfx2/viewsh.hxx> +#include <sfx2/lokhelper.hxx> #include <osl/diagnose.h> #include <boost/property_tree/json_parser.hpp> -#include <sfx2/dispatch.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> @@ -90,7 +88,7 @@ LanguageType EditView::CheckLanguage( // If the result from language guessing does not provide a 'Country' // part, try to get it by looking up the locale setting of the office, - // "Tools/Options - Language Settings - Languages: Locale setting", if + // "Tools/Options - Languages and Locales - General: Locale setting", if // the language matches. if ( aGuessTag.getCountry().isEmpty() ) { @@ -117,16 +115,16 @@ LanguageType EditView::CheckLanguage( const AllSettings& rSettings = Application::GetSettings(); SvtLinguOptions aLinguOpt; SvtLinguConfig().GetOptions( aLinguOpt ); - // The default document language from "Tools/Options - Language Settings - Languages: Western" + // The default document language from "Tools/Options - Languages and Locales - General: Western" aLangList[0] = MsLangId::resolveSystemLanguageByScriptType( aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN); - // The one from "Tools/Options - Language Settings - Languages: User interface" + // The one from "Tools/Options - Languages and Locales - General: User interface" aLangList[1] = rSettings.GetUILanguageTag().getLanguageType(); - // The one from "Tools/Options - Language Settings - Languages: Locale setting" + // The one from "Tools/Options - Languages and Locales - General: Locale setting" aLangList[2] = rSettings.GetLanguageTag().getLanguageType(); // en-US aLangList[3] = LANGUAGE_ENGLISH_US; -#ifdef DEBUG +#if OSL_DEBUG_LEVEL >= 2 lang::Locale a0( LanguageTag::convertToLocale( aLangList[0] ) ); lang::Locale a1( LanguageTag::convertToLocale( aLangList[1] ) ); lang::Locale a2( LanguageTag::convertToLocale( aLangList[2] ) ); @@ -154,9 +152,11 @@ EditViewCallbacks::~EditViewCallbacks() { } -EditView::EditView( EditEngine* pEng, vcl::Window* pWindow ) +EditView::EditView(EditEngine* pEditEngine, vcl::Window* pWindow) + : mpImpEditView(new ImpEditView(this, pEditEngine, pWindow)) { - pImpEditView.reset( new ImpEditView( this, pEng, pWindow ) ); + assert(pEditEngine); + getImpl().mbReadOnly = getImpl().mbReadOnly || SfxViewShell::IsCurrentLokViewReadOnly(); } EditView::~EditView() @@ -165,32 +165,32 @@ EditView::~EditView() void EditView::setEditViewCallbacks(EditViewCallbacks* pEditViewCallbacks) { - pImpEditView->setEditViewCallbacks(pEditViewCallbacks); + getImpl().setEditViewCallbacks(pEditViewCallbacks); } EditViewCallbacks* EditView::getEditViewCallbacks() const { - return pImpEditView->getEditViewCallbacks(); + return getImpl().getEditViewCallbacks(); } -ImpEditEngine* EditView::GetImpEditEngine() const +ImpEditEngine& EditView::getImpEditEngine() const { - return pImpEditView->pEditEngine->pImpEditEngine.get(); + return getImpl().getImpEditEngine(); } -EditEngine* EditView::GetEditEngine() const +EditEngine& EditView::getEditEngine() const { - return pImpEditView->pEditEngine; + return getImpl().getEditEngine(); } tools::Rectangle EditView::GetInvalidateRect() const { - if ( !pImpEditView->DoInvalidateMore() ) - return pImpEditView->aOutArea; + if (!getImpl().DoInvalidateMore()) + return getImpl().maOutputArea; else { - tools::Rectangle aRect( pImpEditView->aOutArea ); - tools::Long nMore = pImpEditView->GetOutputDevice().PixelToLogic( Size( pImpEditView->GetInvalidateMore(), 0 ) ).Width(); + tools::Rectangle aRect(getImpl().maOutputArea); + tools::Long nMore = getImpl().GetOutputDevice().PixelToLogic( Size( getImpl().GetInvalidateMore(), 0 ) ).Width(); aRect.AdjustLeft( -nMore ); aRect.AdjustRight(nMore ); aRect.AdjustTop( -nMore ); @@ -199,20 +199,31 @@ tools::Rectangle EditView::GetInvalidateRect() const } } +namespace { + +tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) +{ + return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()); +} + +} + void EditView::InvalidateWindow(const tools::Rectangle& rClipRect) { - if (EditViewCallbacks* pEditViewCallbacks = pImpEditView->getEditViewCallbacks()) + LOKEditViewHistory::Update(); + bool bNegativeX = IsNegativeX(); + if (EditViewCallbacks* pEditViewCallbacks = getImpl().getEditViewCallbacks()) { // do not invalidate and trigger a global repaint, but forward // the need for change to the applied EditViewCallback, can e.g. // be used to visualize the active edit text in an OverlayObject - pEditViewCallbacks->EditViewInvalidate(rClipRect); + pEditViewCallbacks->EditViewInvalidate(bNegativeX ? lcl_negateRectX(rClipRect) : rClipRect); } else { // classic mode: invalidate and trigger full repaint // of the changed area - GetWindow()->Invalidate(rClipRect); + GetWindow()->Invalidate(bNegativeX ? lcl_negateRectX(rClipRect) : rClipRect); } } @@ -220,10 +231,14 @@ void EditView::InvalidateOtherViewWindows( const tools::Rectangle& rInvRect ) { if (comphelper::LibreOfficeKit::isActive()) { - for (auto& pWin : pImpEditView->aOutWindowSet) + bool bNegativeX = IsNegativeX(); + for (auto& pWin : getImpl().maOutWindowSet) { if (pWin) - pWin->Invalidate( rInvRect ); + { + if (!pWin->InvalidateByForeignEditView(this)) + pWin->Invalidate( bNegativeX ? lcl_negateRectX(rInvRect) : rInvRect ); + } } } } @@ -231,18 +246,20 @@ void EditView::InvalidateOtherViewWindows( const tools::Rectangle& rInvRect ) void EditView::Invalidate() { const tools::Rectangle& rInvRect = GetInvalidateRect(); - pImpEditView->InvalidateAtWindow(rInvRect); + + LOKEditViewHistory::Update(); + getImpl().InvalidateAtWindow(rInvRect); InvalidateOtherViewWindows(rInvRect); } void EditView::SetReadOnly( bool bReadOnly ) { - pImpEditView->bReadOnly = bReadOnly; + getImpl().mbReadOnly = bReadOnly || SfxViewShell::IsCurrentLokViewReadOnly(); } bool EditView::IsReadOnly() const { - return pImpEditView->bReadOnly; + return getImpl().mbReadOnly; } void EditView::SetSelection( const ESelection& rESel ) @@ -253,102 +270,119 @@ void EditView::SetSelection( const ESelection& rESel ) { // tdf#113591 Get node from EditDoc, as the selection might have a pointer to an // already deleted node. - const ContentNode* pNode = pImpEditView->pEditEngine->GetEditDoc().GetEndPaM().GetNode(); - pImpEditView->pEditEngine->CursorMoved( pNode ); + const ContentNode* pNode(getEditEngine().GetEditDoc().GetEndPaM().GetNode()); + if (nullptr != pNode) + pNode->checkAndDeleteEmptyAttribs(); } - EditSelection aNewSelection( pImpEditView->pEditEngine->pImpEditEngine->ConvertSelection( - rESel.nStartPara, rESel.nStartPos, rESel.nEndPara, rESel.nEndPos ) ); + EditSelection aNewSelection(getImpEditEngine().ConvertSelection(rESel.nStartPara, rESel.nStartPos, rESel.nEndPara, rESel.nEndPos)); // If the selection is manipulated after a KeyInput: - pImpEditView->pEditEngine->CheckIdleFormatter(); + getEditEngine().CheckIdleFormatter(); // Selection may not start/end at an invisible paragraph: - const ParaPortion* pPortion = pImpEditView->pEditEngine->FindParaPortion( aNewSelection.Min().GetNode() ); + const ParaPortion* pPortion = getEditEngine().FindParaPortion( aNewSelection.Min().GetNode() ); if ( !pPortion->IsVisible() ) { - pPortion = pImpEditView->pEditEngine->GetPrevVisPortion( pPortion ); - ContentNode* pNode = pPortion ? pPortion->GetNode() : pImpEditView->pEditEngine->GetEditDoc().GetObject( 0 ); + pPortion = getEditEngine().GetPrevVisPortion( pPortion ); + ContentNode* pNode = pPortion ? pPortion->GetNode() : getEditEngine().GetEditDoc().GetObject( 0 ); aNewSelection.Min() = EditPaM( pNode, pNode->Len() ); } - pPortion = pImpEditView->pEditEngine->FindParaPortion( aNewSelection.Max().GetNode() ); + pPortion = getEditEngine().FindParaPortion( aNewSelection.Max().GetNode() ); if ( !pPortion->IsVisible() ) { - pPortion = pImpEditView->pEditEngine->GetPrevVisPortion( pPortion ); - ContentNode* pNode = pPortion ? pPortion->GetNode() : pImpEditView->pEditEngine->GetEditDoc().GetObject( 0 ); + pPortion = getEditEngine().GetPrevVisPortion( pPortion ); + ContentNode* pNode = pPortion ? pPortion->GetNode() : getEditEngine().GetEditDoc().GetObject( 0 ); aNewSelection.Max() = EditPaM( pNode, pNode->Len() ); } - pImpEditView->DrawSelectionXOR(); - pImpEditView->SetEditSelection( aNewSelection ); - pImpEditView->DrawSelectionXOR(); - bool bGotoCursor = pImpEditView->DoAutoScroll(); - ShowCursor( bGotoCursor ); + getImpl().DrawSelectionXOR(); + getImpl().SetEditSelection( aNewSelection ); + getImpl().DrawSelectionXOR(); + bool bGotoCursor = getImpl().DoAutoScroll(); + + // comments section in Writer: + // don't scroll to the selection if it is + // out of visible area of comment canvas. + if (HasSelection()) + ShowCursor( bGotoCursor ); } ESelection EditView::GetSelection() const { ESelection aSelection; - aSelection.nStartPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( pImpEditView->GetEditSelection().Min().GetNode() ); - aSelection.nEndPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( pImpEditView->GetEditSelection().Max().GetNode() ); + aSelection.nStartPara = getEditEngine().GetEditDoc().GetPos( getImpl().GetEditSelection().Min().GetNode() ); + aSelection.nEndPara = getEditEngine().GetEditDoc().GetPos( getImpl().GetEditSelection().Max().GetNode() ); - aSelection.nStartPos = pImpEditView->GetEditSelection().Min().GetIndex(); - aSelection.nEndPos = pImpEditView->GetEditSelection().Max().GetIndex(); + aSelection.nStartPos = getImpl().GetEditSelection().Min().GetIndex(); + aSelection.nEndPos = getImpl().GetEditSelection().Max().GetIndex(); return aSelection; } bool EditView::HasSelection() const { - return pImpEditView->HasSelection(); + return getImpl().HasSelection(); +} + +bool EditView::IsSelectionFullPara() const +{ + return getImpl().IsSelectionFullPara(); +} + +bool EditView::IsSelectionWithinSinglePara() const +{ + return getImpl().IsSelectionInSinglePara(); } bool EditView::IsSelectionAtPoint(const Point& rPointPixel) { - return pImpEditView->IsSelectionAtPoint(rPointPixel); + return getImpl().IsSelectionAtPoint(rPointPixel); } void EditView::DeleteSelected() { - pImpEditView->DeleteSelected(); + getImpl().DeleteSelected(); } SvtScriptType EditView::GetSelectedScriptType() const { - return pImpEditView->pEditEngine->GetScriptType( pImpEditView->GetEditSelection() ); + return getEditEngine().GetScriptType( getImpl().GetEditSelection() ); } void EditView::GetSelectionRectangles(std::vector<tools::Rectangle>& rLogicRects) const { - return pImpEditView->GetSelectionRectangles(pImpEditView->GetEditSelection(), rLogicRects); + return getImpl().GetSelectionRectangles(getImpl().GetEditSelection(), rLogicRects); } void EditView::Paint( const tools::Rectangle& rRect, OutputDevice* pTargetDevice ) { - pImpEditView->pEditEngine->pImpEditEngine->Paint( pImpEditView.get(), rRect, pTargetDevice ); + getImpEditEngine().Paint(&getImpl(), rRect, pTargetDevice); } -void EditView::SetEditEngine( EditEngine* pEditEng ) +void EditView::setEditEngine(EditEngine* pEditEngine) { - pImpEditView->pEditEngine = pEditEng; - EditSelection aStartSel = pImpEditView->pEditEngine->GetEditDoc().GetStartPaM(); - pImpEditView->SetEditSelection( aStartSel ); + assert(pEditEngine); + + getImpl().mpEditEngine = pEditEngine; + EditSelection aStartSel = getEditEngine().GetEditDoc().GetStartPaM(); + getImpl().SetEditSelection( aStartSel ); } -void EditView::SetWindow( vcl::Window* pWin ) +void EditView::SetWindow(vcl::Window* pWindow) { - pImpEditView->pOutWin = pWin; - pImpEditView->pEditEngine->pImpEditEngine->GetSelEngine().Reset(); + getImpl().mpOutputWindow = pWindow; + getImpEditEngine().GetSelEngine().Reset(); } vcl::Window* EditView::GetWindow() const { - return pImpEditView->pOutWin; + return getImpl().mpOutputWindow; } OutputDevice& EditView::GetOutputDevice() const { - return pImpEditView->GetOutputDevice(); + return getImpl().GetOutputDevice(); } LanguageType EditView::GetInputLanguage() const @@ -361,7 +395,7 @@ LanguageType EditView::GetInputLanguage() const bool EditView::HasOtherViewWindow( vcl::Window* pWin ) { - OutWindowSet& rOutWindowSet = pImpEditView->aOutWindowSet; + OutWindowSet& rOutWindowSet = getImpl().maOutWindowSet; auto found = std::find(rOutWindowSet.begin(), rOutWindowSet.end(), pWin); return (found != rOutWindowSet.end()); } @@ -370,13 +404,13 @@ bool EditView::AddOtherViewWindow( vcl::Window* pWin ) { if (HasOtherViewWindow(pWin)) return false; - pImpEditView->aOutWindowSet.emplace_back(pWin); + getImpl().maOutWindowSet.emplace_back(pWin); return true; } bool EditView::RemoveOtherViewWindow( vcl::Window* pWin ) { - OutWindowSet& rOutWindowSet = pImpEditView->aOutWindowSet; + OutWindowSet& rOutWindowSet = getImpl().maOutWindowSet; auto found = std::find(rOutWindowSet.begin(), rOutWindowSet.end(), pWin); if (found == rOutWindowSet.end()) return false; @@ -386,179 +420,180 @@ bool EditView::RemoveOtherViewWindow( vcl::Window* pWin ) void EditView::SetVisArea( const tools::Rectangle& rRect ) { - pImpEditView->SetVisDocStartPos( rRect.TopLeft() ); + getImpl().SetVisDocStartPos( rRect.TopLeft() ); } tools::Rectangle EditView::GetVisArea() const { - return pImpEditView->GetVisDocArea(); + return getImpl().GetVisDocArea(); } void EditView::SetOutputArea( const tools::Rectangle& rRect ) { - pImpEditView->SetOutputArea( rRect ); + getImpl().SetOutputArea( rRect ); // the rest here only if it is an API call: - pImpEditView->CalcAnchorPoint(); - if ( pImpEditView->pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) - pImpEditView->RecalcOutputArea(); - pImpEditView->ShowCursor( false, false ); + getImpl().CalcAnchorPoint(); + if (getImpEditEngine().GetStatus().AutoPageSize() ) + getImpl().RecalcOutputArea(); + getImpl().ShowCursor( false, false ); } const tools::Rectangle& EditView::GetOutputArea() const { - return pImpEditView->GetOutputArea(); + return getImpl().GetOutputArea(); } PointerStyle EditView::GetPointer() const { - return pImpEditView->GetPointer(); + return getImpl().GetPointer(); } vcl::Cursor* EditView::GetCursor() const { - return pImpEditView->pCursor.get(); + return getImpl().GetCursor(); } void EditView::InsertText( const OUString& rStr, bool bSelect, bool bLOKShowSelect ) { - EditEngine* pEE = pImpEditView->pEditEngine; + EditEngine& rEditEngine = getEditEngine(); if (bLOKShowSelect) - pImpEditView->DrawSelectionXOR(); + getImpl().DrawSelectionXOR(); EditPaM aPaM1; if ( bSelect ) { - EditSelection aTmpSel( pImpEditView->GetEditSelection() ); - aTmpSel.Adjust( pEE->GetEditDoc() ); + EditSelection aTmpSel( getImpl().GetEditSelection() ); + aTmpSel.Adjust(rEditEngine.GetEditDoc()); aPaM1 = aTmpSel.Min(); } - pEE->UndoActionStart( EDITUNDO_INSERT ); - EditPaM aPaM2( pEE->InsertText( pImpEditView->GetEditSelection(), rStr ) ); - pEE->UndoActionEnd(); + rEditEngine.UndoActionStart( EDITUNDO_INSERT ); + EditPaM aPaM2(rEditEngine.InsertText( getImpl().GetEditSelection(), rStr ) ); + rEditEngine.UndoActionEnd(); if ( bSelect ) { - DBG_ASSERT( !aPaM1.DbgIsBuggy( pEE->GetEditDoc() ), "Insert: PaM broken" ); - pImpEditView->SetEditSelection( EditSelection( aPaM1, aPaM2 ) ); + DBG_ASSERT( !aPaM1.DbgIsBuggy(rEditEngine.GetEditDoc()), "Insert: PaM broken" ); + getImpl().SetEditSelection( EditSelection( aPaM1, aPaM2 ) ); } else - pImpEditView->SetEditSelection( EditSelection( aPaM2, aPaM2 ) ); + getImpl().SetEditSelection( EditSelection( aPaM2, aPaM2 ) ); if (bLOKShowSelect) - pEE->FormatAndUpdate( this ); + rEditEngine.FormatAndLayout( this ); } bool EditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * pFrameWin ) { - return pImpEditView->PostKeyEvent( rKeyEvent, pFrameWin ); + return getImpl().PostKeyEvent( rKeyEvent, pFrameWin ); } bool EditView::MouseButtonUp( const MouseEvent& rMouseEvent ) { - return pImpEditView->MouseButtonUp( rMouseEvent ); + return getImpl().MouseButtonUp( rMouseEvent ); } void EditView::ReleaseMouse() { - return pImpEditView->ReleaseMouse(); + return getImpl().ReleaseMouse(); } bool EditView::MouseButtonDown( const MouseEvent& rMouseEvent ) { - return pImpEditView->MouseButtonDown( rMouseEvent ); + return getImpl().MouseButtonDown( rMouseEvent ); } bool EditView::MouseMove( const MouseEvent& rMouseEvent ) { - return pImpEditView->MouseMove( rMouseEvent ); + return getImpl().MouseMove( rMouseEvent ); } bool EditView::Command(const CommandEvent& rCEvt) { - return pImpEditView->Command(rCEvt); + return getImpl().Command(rCEvt); } void EditView::SetBroadcastLOKViewCursor(bool bSet) { - pImpEditView->SetBroadcastLOKViewCursor(bSet); + getImpl().SetBroadcastLOKViewCursor(bSet); } tools::Rectangle EditView::GetEditCursor() const { - return pImpEditView->GetEditCursor(); + return getImpl().GetEditCursor(); } void EditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor, bool bActivate ) { - if ( !pImpEditView->pEditEngine->HasView( this ) ) + if (!getEditEngine().HasView(this)) return; // The control word is more important: - if ( !pImpEditView->DoAutoScroll() ) + if ( !getImpl().DoAutoScroll() ) bGotoCursor = false; - pImpEditView->ShowCursor( bGotoCursor, bForceVisCursor ); + getImpl().ShowCursor( bGotoCursor, bForceVisCursor ); - if (pImpEditView->mpViewShell && !bActivate) + if (getImpl().mpViewShell && !bActivate) { - if (!pImpEditView->pOutWin) + if (!getImpl().mpOutputWindow) return; - VclPtr<vcl::Window> pParent = pImpEditView->pOutWin->GetParentWithLOKNotifier(); + VclPtr<vcl::Window> pParent = getImpl().mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId() != 0) return; static const OString aPayload = OString::boolean(true); - pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); - pImpEditView->mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); + getImpl().mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload); + getImpl().mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible"_ostr, aPayload); } } void EditView::HideCursor(bool bDeactivate) { - pImpEditView->GetCursor()->Hide(); + getImpl().GetCursor()->Hide(); - if (pImpEditView->mpViewShell && !bDeactivate) + if (getImpl().mpViewShell && !bDeactivate) { - if (!pImpEditView->pOutWin) + if (!getImpl().mpOutputWindow) return; - VclPtr<vcl::Window> pParent = pImpEditView->pOutWin->GetParentWithLOKNotifier(); + VclPtr<vcl::Window> pParent = getImpl().mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId() != 0) return; OString aPayload = OString::boolean(false); - pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); - pImpEditView->mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); + getImpl().mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload); + getImpl().mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible"_ostr, aPayload); } } Pair EditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRangeCheck ) { - return pImpEditView->Scroll( ndX, ndY, nRangeCheck ); + return getImpl().Scroll( ndX, ndY, nRangeCheck ); } const SfxItemSet& EditView::GetEmptyItemSet() const { - return pImpEditView->pEditEngine->GetEmptyItemSet(); + return getEditEngine().GetEmptyItemSet(); } void EditView::SetAttribs( const SfxItemSet& rSet ) { - DBG_ASSERT( !pImpEditView->aEditSelection.IsInvalid(), "Blind Selection in..." ); + DBG_ASSERT(!getImpl().maEditSelection.IsInvalid(), "Blind Selection in..."); - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->SetAttribs( pImpEditView->GetEditSelection(), rSet, SetAttribsMode::WholeWord ); - pImpEditView->pEditEngine->FormatAndUpdate( this ); + getImpl().DrawSelectionXOR(); + getEditEngine().SetAttribs( getImpl().GetEditSelection(), rSet, SetAttribsMode::WholeWord ); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::RemoveAttribsKeepLanguages( bool bRemoveParaAttribs ) { - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - EditSelection aSelection( pImpEditView->GetEditSelection() ); + getImpl().DrawSelectionXOR(); + getEditEngine().UndoActionStart( EDITUNDO_RESETATTRIBS ); + EditSelection aSelection( getImpl().GetEditSelection() ); for (sal_uInt16 nWID = EE_ITEMS_START; nWID <= EE_ITEMS_END; ++nWID) { @@ -566,11 +601,12 @@ void EditView::RemoveAttribsKeepLanguages( bool bRemoveParaAttribs ) EE_CHAR_LANGUAGE_CJK == nWID || EE_CHAR_LANGUAGE_CTL == nWID; if (!bIsLang) - pImpEditView->pEditEngine->RemoveCharAttribs( aSelection, bRemoveParaAttribs, nWID ); + getEditEngine().RemoveCharAttribs( aSelection, bRemoveParaAttribs, nWID ); } - pImpEditView->pEditEngine->UndoActionEnd(); - pImpEditView->pEditEngine->FormatAndUpdate( this ); + getEditEngine().UndoActionEnd(); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::RemoveAttribs( bool bRemoveParaAttribs, sal_uInt16 nWhich ) @@ -581,48 +617,50 @@ void EditView::RemoveAttribs( bool bRemoveParaAttribs, sal_uInt16 nWhich ) void EditView::RemoveAttribs( EERemoveParaAttribsMode eMode, sal_uInt16 nWhich ) { - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - pImpEditView->pEditEngine->RemoveCharAttribs( pImpEditView->GetEditSelection(), eMode, nWhich ); - pImpEditView->pEditEngine->UndoActionEnd(); - pImpEditView->pEditEngine->FormatAndUpdate( this ); + getImpl().DrawSelectionXOR(); + getEditEngine().UndoActionStart( EDITUNDO_RESETATTRIBS ); + getEditEngine().RemoveCharAttribs( getImpl().GetEditSelection(), eMode, nWhich ); + getEditEngine().UndoActionEnd(); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich ) { - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - pImpEditView->pEditEngine->RemoveCharAttribs( nPara, nWhich ); - pImpEditView->pEditEngine->UndoActionEnd(); - pImpEditView->pEditEngine->FormatAndUpdate( this ); + getEditEngine().UndoActionStart( EDITUNDO_RESETATTRIBS ); + getEditEngine().RemoveCharAttribs( nPara, nWhich ); + getEditEngine().UndoActionEnd(); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } SfxItemSet EditView::GetAttribs() { - DBG_ASSERT( !pImpEditView->aEditSelection.IsInvalid(), "Blind Selection in..." ); - return pImpEditView->pEditEngine->pImpEditEngine->GetAttribs( pImpEditView->GetEditSelection() ); + DBG_ASSERT(!getImpl().maEditSelection.IsInvalid(), "Blind Selection in..."); + return getImpEditEngine().GetAttribs( getImpl().GetEditSelection() ); } void EditView::Undo() { - pImpEditView->pEditEngine->Undo( this ); + getEditEngine().Undo( this ); } void EditView::Redo() { - pImpEditView->pEditEngine->Redo( this ); + getEditEngine().Redo( this ); } ErrCode EditView::Read( SvStream& rInput, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs ) { - EditSelection aOldSel( pImpEditView->GetEditSelection() ); - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_READ ); - EditPaM aEndPaM = pImpEditView->pEditEngine->pImpEditEngine->Read( rInput, "", eFormat, aOldSel, pHTTPHeaderAttrs ); - pImpEditView->pEditEngine->pImpEditEngine->UndoActionEnd(); + EditSelection aOldSel( getImpl().GetEditSelection() ); + getImpl().DrawSelectionXOR(); + getImpEditEngine().UndoActionStart( EDITUNDO_READ ); + EditPaM aEndPaM = getImpEditEngine().Read( rInput, "", eFormat, aOldSel, pHTTPHeaderAttrs ); + getImpEditEngine().UndoActionEnd(); EditSelection aNewSel( aEndPaM, aEndPaM ); - pImpEditView->SetEditSelection( aNewSel ); - bool bGotoCursor = pImpEditView->DoAutoScroll(); + getImpl().SetEditSelection( aNewSel ); + bool bGotoCursor = getImpl().DoAutoScroll(); ShowCursor( bGotoCursor ); return rInput.GetError(); @@ -631,156 +669,158 @@ ErrCode EditView::Read( SvStream& rInput, EETextFormat eFormat, SvKeyValueIterat void EditView::Cut() { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->CutCopy( aClipBoard, true ); + getImpl().CutCopy( aClipBoard, true ); } Reference<css::datatransfer::clipboard::XClipboard> EditView::GetClipboard() const { - return pImpEditView->GetClipboard(); + return getImpl().GetClipboard(); } css::uno::Reference< css::datatransfer::XTransferable > EditView::GetTransferable() const { - uno::Reference< datatransfer::XTransferable > xData = - GetEditEngine()->CreateTransferable( pImpEditView->GetEditSelection() ); + uno::Reference< datatransfer::XTransferable > xData = getEditEngine().CreateTransferable( getImpl().GetEditSelection() ); return xData; } void EditView::Copy() { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->CutCopy( aClipBoard, false ); + getImpl().CutCopy( aClipBoard, false ); } void EditView::Paste() { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->Paste( aClipBoard ); + getImpl().Paste( aClipBoard ); } -void EditView::PasteSpecial() +void EditView::PasteSpecial(SotClipboardFormatId format) { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->Paste(aClipBoard, true ); + getImpl().Paste(aClipBoard, true, format ); } Point EditView::GetWindowPosTopLeft( sal_Int32 nParagraph ) { - Point aDocPos( pImpEditView->pEditEngine->GetDocPosTopLeft( nParagraph ) ); - return pImpEditView->GetWindowPos( aDocPos ); + Point aDocPos(getEditEngine().GetDocPosTopLeft(nParagraph)); + return getImpl().GetWindowPos( aDocPos ); } void EditView::SetSelectionMode( EESelectionMode eMode ) { - pImpEditView->SetSelectionMode( eMode ); + getImpl().SetSelectionMode( eMode ); } OUString EditView::GetSelected() const { - return pImpEditView->pEditEngine->pImpEditEngine->GetSelected( pImpEditView->GetEditSelection() ); + return getImpEditEngine().GetSelected( getImpl().GetEditSelection() ); } void EditView::MoveParagraphs( Range aParagraphs, sal_Int32 nNewPos ) { - pImpEditView->pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_MOVEPARAS ); - pImpEditView->pEditEngine->pImpEditEngine->MoveParagraphs( aParagraphs, nNewPos, this ); - pImpEditView->pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionStart( EDITUNDO_MOVEPARAS ); + getImpEditEngine().MoveParagraphs( aParagraphs, nNewPos, this ); + getImpEditEngine().UndoActionEnd(); } void EditView::MoveParagraphs( tools::Long nDiff ) { ESelection aSel = GetSelection(); Range aRange( aSel.nStartPara, aSel.nEndPara ); - aRange.Justify(); + aRange.Normalize(); tools::Long nDest = ( nDiff > 0 ? aRange.Max() : aRange.Min() ) + nDiff; if ( nDiff > 0 ) nDest++; - DBG_ASSERT( ( nDest >= 0 ) && ( nDest <= pImpEditView->pEditEngine->GetParagraphCount() ), "MoveParagraphs - wrong Parameters!" ); + DBG_ASSERT( ( nDest >= 0 ) && ( nDest <= getEditEngine().GetParagraphCount() ), "MoveParagraphs - wrong Parameters!" ); MoveParagraphs( aRange, sal::static_int_cast< sal_Int32 >( nDest ) ); } void EditView::SetBackgroundColor( const Color& rColor ) { - pImpEditView->SetBackgroundColor( rColor ); + getImpl().SetBackgroundColor( rColor ); + getEditEngine().SetBackgroundColor( rColor ); } Color const & EditView::GetBackgroundColor() const { - return pImpEditView->GetBackgroundColor(); + return getImpl().GetBackgroundColor(); } void EditView::RegisterViewShell(OutlinerViewShell* pViewShell) { - pImpEditView->RegisterViewShell(pViewShell); + getImpl().RegisterViewShell(pViewShell); } void EditView::RegisterOtherShell(OutlinerViewShell* pOtherShell) { - pImpEditView->RegisterOtherShell(pOtherShell); + getImpl().RegisterOtherShell(pOtherShell); } void EditView::SetControlWord( EVControlBits nWord ) { - pImpEditView->nControl = nWord; + getImpl().mnControl = nWord; } EVControlBits EditView::GetControlWord() const { - return pImpEditView->nControl; + return getImpl().mnControl; } std::unique_ptr<EditTextObject> EditView::CreateTextObject() { - return pImpEditView->pEditEngine->pImpEditEngine->CreateTextObject( pImpEditView->GetEditSelection() ); + return getImpEditEngine().CreateTextObject( getImpl().GetEditSelection() ); } void EditView::InsertText( const EditTextObject& rTextObject ) { - pImpEditView->DrawSelectionXOR(); + getImpl().DrawSelectionXOR(); - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_INSERT ); - EditSelection aTextSel( pImpEditView->pEditEngine->InsertText( rTextObject, pImpEditView->GetEditSelection() ) ); - pImpEditView->pEditEngine->UndoActionEnd(); + getEditEngine().UndoActionStart( EDITUNDO_INSERT ); + EditSelection aTextSel(getEditEngine().InsertText(rTextObject, getImpl().GetEditSelection())); + getEditEngine().UndoActionEnd(); aTextSel.Min() = aTextSel.Max(); // Selection not retained. - pImpEditView->SetEditSelection( aTextSel ); - pImpEditView->pEditEngine->FormatAndUpdate( this ); + getImpl().SetEditSelection( aTextSel ); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::InsertText( css::uno::Reference< css::datatransfer::XTransferable > const & xDataObj, const OUString& rBaseURL, bool bUseSpecial ) { - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_INSERT ); - pImpEditView->DeleteSelected(); + getEditEngine().UndoActionStart( EDITUNDO_INSERT ); + getImpl().DeleteSelected(); EditSelection aTextSel = - pImpEditView->pEditEngine->InsertText(xDataObj, rBaseURL, pImpEditView->GetEditSelection().Max(), bUseSpecial); - pImpEditView->pEditEngine->UndoActionEnd(); + getEditEngine().InsertText(xDataObj, rBaseURL, getImpl().GetEditSelection().Max(), bUseSpecial); + getEditEngine().UndoActionEnd(); aTextSel.Min() = aTextSel.Max(); // Selection not retained. - pImpEditView->SetEditSelection( aTextSel ); - pImpEditView->pEditEngine->FormatAndUpdate( this ); + getImpl().SetEditSelection( aTextSel ); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } -void EditView::SetEditEngineUpdateMode( bool bUpdate ) +bool EditView::SetEditEngineUpdateLayout( bool bUpdate ) { - pImpEditView->pEditEngine->pImpEditEngine->SetUpdateMode( bUpdate, this ); + return getImpEditEngine().SetUpdateLayout( bUpdate, this ); } -void EditView::ForceUpdate() +void EditView::ForceLayoutCalculation() { - pImpEditView->pEditEngine->pImpEditEngine->SetUpdateMode( true, this, true ); + getImpEditEngine().SetUpdateLayout( true, this, true ); } SfxStyleSheet* EditView::GetStyleSheet() { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); - sal_Int32 nStartPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() ); + EditSelection aSel( getImpl().GetEditSelection() ); + aSel.Adjust(getEditEngine().GetEditDoc()); + sal_Int32 nStartPara = getEditEngine().GetEditDoc().GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndPara = getEditEngine().GetEditDoc().GetPos( aSel.Max().GetNode() ); SfxStyleSheet* pStyle = nullptr; for ( sal_Int32 n = nStartPara; n <= nEndPara; n++ ) { - SfxStyleSheet* pTmpStyle = pImpEditView->pEditEngine->GetStyleSheet( n ); + SfxStyleSheet* pTmpStyle = getEditEngine().GetStyleSheet( n ); if ( ( n != nStartPara ) && ( pStyle != pTmpStyle ) ) return nullptr; // Not unique. pStyle = pTmpStyle; @@ -795,76 +835,76 @@ const SfxStyleSheet* EditView::GetStyleSheet() const bool EditView::IsInsertMode() const { - return pImpEditView->IsInsertMode(); + return getImpl().IsInsertMode(); } void EditView::SetInsertMode( bool bInsert ) { - pImpEditView->SetInsertMode( bInsert ); + getImpl().SetInsertMode( bInsert ); } void EditView::SetAnchorMode( EEAnchorMode eMode ) { - pImpEditView->SetAnchorMode( eMode ); + getImpl().SetAnchorMode( eMode ); } EEAnchorMode EditView::GetAnchorMode() const { - return pImpEditView->GetAnchorMode(); + return getImpl().GetAnchorMode(); } void EditView::TransliterateText( TransliterationFlags nTransliterationMode ) { - EditSelection aOldSel( pImpEditView->GetEditSelection() ); - EditSelection aNewSel = pImpEditView->pEditEngine->TransliterateText( pImpEditView->GetEditSelection(), nTransliterationMode ); + EditSelection aOldSel( getImpl().GetEditSelection() ); + EditSelection aNewSel = getEditEngine().TransliterateText( getImpl().GetEditSelection(), nTransliterationMode ); if ( aNewSel != aOldSel ) { - pImpEditView->DrawSelectionXOR(); - pImpEditView->SetEditSelection( aNewSel ); - pImpEditView->DrawSelectionXOR(); + getImpl().DrawSelectionXOR(); + getImpl().SetEditSelection( aNewSel ); + getImpl().DrawSelectionXOR(); } } void EditView::CompleteAutoCorrect( vcl::Window const * pFrameWin ) { - if ( !HasSelection() && pImpEditView->pEditEngine->pImpEditEngine->GetStatus().DoAutoCorrect() ) + if ( !HasSelection() && getImpEditEngine().GetStatus().DoAutoCorrect() ) { - pImpEditView->DrawSelectionXOR(); - EditSelection aSel = pImpEditView->GetEditSelection(); - aSel = pImpEditView->pEditEngine->EndOfWord( aSel.Max() ); - aSel = pImpEditView->pEditEngine->pImpEditEngine->AutoCorrect( aSel, 0, !IsInsertMode(), pFrameWin ); - pImpEditView->SetEditSelection( aSel ); - if ( pImpEditView->pEditEngine->IsModified() ) - pImpEditView->pEditEngine->FormatAndUpdate( this ); + getImpl().DrawSelectionXOR(); + EditSelection aSel = getImpl().GetEditSelection(); + aSel = getEditEngine().EndOfWord( aSel.Max() ); + aSel = getImpEditEngine().AutoCorrect( aSel, 0, !IsInsertMode(), pFrameWin ); + getImpl().SetEditSelection( aSel ); + if (getEditEngine().IsModified()) + getEditEngine().FormatAndLayout( this ); } } EESpellState EditView::StartSpeller(weld::Widget* pDialogParent, bool bMultipleDoc) { - if ( !pImpEditView->pEditEngine->pImpEditEngine->GetSpeller().is() ) + if (!getImpEditEngine().GetSpeller().is()) return EESpellState::NoSpeller; - return pImpEditView->pEditEngine->pImpEditEngine->Spell(this, pDialogParent, bMultipleDoc); + return getImpEditEngine().Spell(this, pDialogParent, bMultipleDoc); } EESpellState EditView::StartThesaurus(weld::Widget* pDialogParent) { - if ( !pImpEditView->pEditEngine->pImpEditEngine->GetSpeller().is() ) + if (!getImpEditEngine().GetSpeller().is()) return EESpellState::NoSpeller; - return pImpEditView->pEditEngine->pImpEditEngine->StartThesaurus(this, pDialogParent); + return getImpEditEngine().StartThesaurus(this, pDialogParent); } void EditView::StartTextConversion(weld::Widget* pDialogParent, LanguageType nSrcLang, LanguageType nDestLang, const vcl::Font *pDestFont, sal_Int32 nOptions, bool bIsInteractive, bool bMultipleDoc ) { - pImpEditView->pEditEngine->pImpEditEngine->Convert(this, pDialogParent, nSrcLang, nDestLang, pDestFont, nOptions, bIsInteractive, bMultipleDoc); + getImpEditEngine().Convert(this, pDialogParent, nSrcLang, nDestLang, pDestFont, nOptions, bIsInteractive, bMultipleDoc); } sal_Int32 EditView::StartSearchAndReplace( const SvxSearchItem& rSearchItem ) { - return pImpEditView->pEditEngine->pImpEditEngine->StartSearchAndReplace( this, rSearchItem ); + return getImpEditEngine().StartSearchAndReplace( this, rSearchItem ); } bool EditView::IsCursorAtWrongSpelledWord() @@ -872,18 +912,18 @@ bool EditView::IsCursorAtWrongSpelledWord() bool bIsWrong = false; if ( !HasSelection() ) { - EditPaM aPaM = pImpEditView->GetEditSelection().Max(); - bIsWrong = pImpEditView->IsWrongSpelledWord( aPaM, false/*bMarkIfWrong*/ ); + EditPaM aPaM = getImpl().GetEditSelection().Max(); + bIsWrong = getImpl().IsWrongSpelledWord( aPaM, false/*bMarkIfWrong*/ ); } return bIsWrong; } bool EditView::IsWrongSpelledWordAtPos( const Point& rPosPixel, bool bMarkIfWrong ) { - Point aPos(pImpEditView->GetOutputDevice().PixelToLogic(rPosPixel)); - aPos = pImpEditView->GetDocPos( aPos ); - EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aPos, false); - return pImpEditView->IsWrongSpelledWord( aPaM , bMarkIfWrong ); + Point aPos(getImpl().GetOutputDevice().PixelToLogic(rPosPixel)); + aPos = getImpl().GetDocPos( aPos ); + EditPaM aPaM = getEditEngine().GetPaM(aPos, false); + return getImpl().IsWrongSpelledWord( aPaM , bMarkIfWrong ); } static void LOKSendSpellPopupMenu(const weld::Menu& rMenu, LanguageType nGuessLangWord, @@ -904,7 +944,7 @@ static void LOKSendSpellPopupMenu(const weld::Menu& rMenu, LanguageType nGuessLa { for(int i = 0; i < nSuggestions; ++i) { - OString sItemId = OString::number(MN_ALTSTART + i); + OUString sItemId = OUString::number(MN_ALTSTART + i); OUString sText = rMenu.get_label(sItemId); aItemTree.put("text", sText.toUtf8().getStr()); aItemTree.put("type", "command"); @@ -956,28 +996,28 @@ static void LOKSendSpellPopupMenu(const weld::Menu& rMenu, LanguageType nGuessLa std::stringstream aStream; boost::property_tree::write_json(aStream, aRoot, true); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, aStream.str().c_str()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, OString(aStream.str())); } -void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbackInfo&,void> &rCallBack) +bool EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbackInfo&,void> &rCallBack) { - OutputDevice& rDevice = pImpEditView->GetOutputDevice(); + OutputDevice& rDevice = getImpl().GetOutputDevice(); Point aPos(rDevice.PixelToLogic(rPosPixel)); - aPos = pImpEditView->GetDocPos( aPos ); - EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aPos, false); - Reference< linguistic2::XSpellChecker1 > xSpeller( pImpEditView->pEditEngine->pImpEditEngine->GetSpeller() ); + aPos = getImpl().GetDocPos( aPos ); + EditPaM aPaM = getEditEngine().GetPaM(aPos, false); + Reference< linguistic2::XSpellChecker1 > xSpeller(getImpEditEngine().GetSpeller()); ESelection aOldSel = GetSelection(); - if ( !(xSpeller.is() && pImpEditView->IsWrongSpelledWord( aPaM, true )) ) - return; + if ( !(xSpeller.is() && getImpl().IsWrongSpelledWord( aPaM, true )) ) + return false; // PaMtoEditCursor returns Logical units - tools::Rectangle aTempRect = pImpEditView->pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GetCursorFlags::TextOnly ); + tools::Rectangle aTempRect = getImpEditEngine().PaMtoEditCursor(aPaM, CursorFlags{ .bTextOnly = true }); // GetWindowPos works in Logical units - aTempRect = pImpEditView->GetWindowPos(aTempRect); + aTempRect = getImpl().GetWindowPos(aTempRect); // Convert to pixels aTempRect = rDevice.LogicToPixel(aTempRect); - weld::Widget* pPopupParent = pImpEditView->GetPopupParent(aTempRect); + weld::Widget* pPopupParent = getImpl().GetPopupParent(aTempRect); std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "editeng/ui/spellmenu.ui")); std::unique_ptr<weld::Menu> xPopupMenu(xBuilder->weld_menu("editviewspellmenu")); std::unique_ptr<weld::Menu> xInsertMenu(xBuilder->weld_menu("insertmenu")); // add word to user-dictionaries @@ -999,14 +1039,11 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac // than returning e.g. 16 suggestions and using only the // first 7. Thus we hand down the value to use to that // implementation here by providing an additional parameter. - Sequence< PropertyValue > aPropVals(1); - PropertyValue &rVal = aPropVals.getArray()[0]; - rVal.Name = UPN_MAX_NUMBER_OF_SUGGESTIONS; - rVal.Value <<= sal_Int16(7); + Sequence< PropertyValue > aPropVals { comphelper::makePropertyValue(UPN_MAX_NUMBER_OF_SUGGESTIONS, sal_Int16(7)) }; // Are there any replace suggestions? Reference< linguistic2::XSpellAlternatives > xSpellAlt = - xSpeller->spell( aSelected, static_cast<sal_uInt16>(pImpEditView->pEditEngine->pImpEditEngine->GetLanguage( aPaM2 )), aPropVals ); + xSpeller->spell( aSelected, static_cast<sal_uInt16>(getImpEditEngine().GetLanguage( aPaM2 ).nLang), aPropVals ); Reference< linguistic2::XLanguageGuessing > xLangGuesser( EditDLL::Get().GetGlobalData()->GetLanguageGuesser() ); @@ -1059,10 +1096,11 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac for ( sal_uInt16 nW = 0; nW < nWords; nW++ ) { OUString aAlternate( pAlt[nW] ); - xPopupMenu->append(OUString::number(MN_ALTSTART + nW), aAlternate); - xAutoMenu->append(OUString::number(MN_AUTOSTART + nW), aAlternate); + OUString sId(OUString::number(MN_ALTSTART + nW)); + xPopupMenu->insert(nW, sId, aAlternate, nullptr, nullptr, nullptr, TRISTATE_INDET); + xAutoMenu->append(sId, aAlternate); } - xPopupMenu->append_separator("separator2"); + xPopupMenu->insert_separator(nWords, "separator2"); } else { @@ -1086,7 +1124,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac aDics = xDicList->getDictionaries(); pDic = aDics.getConstArray(); - LanguageType nCheckedLanguage = pImpEditView->pEditEngine->pImpEditEngine->GetLanguage( aPaM2 ); + LanguageType nCheckedLanguage = getImpEditEngine().GetLanguage( aPaM2 ).nLang; sal_uInt16 nDicCount = static_cast<sal_uInt16>(aDics.getLength()); for (sal_uInt16 i = 0; i < nDicCount; i++) { @@ -1142,32 +1180,26 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac //because the loss of focus in the current editeng causes writer //annotations to save their contents, making the pContent of the //current EditPams invalid - EPaM aP = pImpEditView->pEditEngine->pImpEditEngine->CreateEPaM(aPaM); - EPaM aP2 = pImpEditView->pEditEngine->pImpEditEngine->CreateEPaM(aPaM2); + EPaM aP = getImpEditEngine().CreateEPaM(aPaM); + EPaM aP2 = getImpEditEngine().CreateEPaM(aPaM2); if (comphelper::LibreOfficeKit::isActive()) { xPopupMenu->remove("autocorrect"); xPopupMenu->remove("autocorrectdlg"); - // For mobile phones, send the context menu structure - const SfxViewShell* pViewShell = SfxViewShell::Current(); - if (pViewShell && pViewShell->isLOKMobilePhone()) - { - LOKSendSpellPopupMenu(*xPopupMenu, nGuessLangWord, nGuessLangPara, nWords); - return; - } - // note, there is special handling of this menu 'editviewspellmenu' by vcl's PopupMenu::ImplExecute + LOKSendSpellPopupMenu(*xPopupMenu, nGuessLangWord, nGuessLangPara, nWords); + return true; } - OString sId = xPopupMenu->popup_at_rect(pPopupParent, aTempRect); + OUString sId = xPopupMenu->popup_at_rect(pPopupParent, aTempRect); - aPaM2 = pImpEditView->pEditEngine->pImpEditEngine->CreateEditPaM(aP2); - aPaM = pImpEditView->pEditEngine->pImpEditEngine->CreateEditPaM(aP); + aPaM2 = getImpEditEngine().CreateEditPaM(aP2); + aPaM = getImpEditEngine().CreateEditPaM(aP); if (sId == "ignore") { - OUString aWord = pImpEditView->SpellIgnoreWord(); + OUString aWord = getImpl().SpellIgnoreWord(); SpellCallbackInfo aInf( SpellCallbackCommand::IGNOREWORD, aWord ); rCallBack.Call(aInf); SetSelection( aOldSel ); @@ -1177,7 +1209,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac LanguageType nLangToUse = (sId == "wordlanguage") ? nGuessLangWord : nGuessLangPara; SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse ); - SfxItemSet aAttrs = GetEditEngine()->GetEmptyItemSet(); + SfxItemSet aAttrs = getEditEngine().GetEmptyItemSet(); if (nScriptType == SvtScriptType::LATIN) aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) ); if (nScriptType == SvtScriptType::COMPLEX) @@ -1192,7 +1224,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac SetSelection( aSel ); } SetAttribs( aAttrs ); - pImpEditView->pEditEngine->pImpEditEngine->StartOnlineSpellTimer(); + getImpEditEngine().StartOnlineSpellTimer(); SpellCallbackInfo aInf((sId == "wordlanguage") ? SpellCallbackCommand::WORDLANGUAGE : SpellCallbackCommand::PARALANGUAGE); rCallBack.Call(aInf); @@ -1213,6 +1245,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac OUString aDicName; if (sId.toInt32() >= MN_DICTSTART) { + assert(xInsertMenu && "this case only occurs when xInsertMenu exists"); // strip_mnemonic is necessary to retrieve the correct dictionary name aDicName = pPopupParent->strip_mnemonic(xInsertMenu->get_label(sId)); } @@ -1231,7 +1264,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac xSavDic->store(); aPaM.GetNode()->GetWrongList()->ResetInvalidRange(0, aPaM.GetNode()->Len()); - pImpEditView->pEditEngine->pImpEditEngine->StartOnlineSpellTimer(); + getImpEditEngine().StartOnlineSpellTimer(); SpellCallbackInfo aInf( SpellCallbackCommand::ADDTODICTIONARY, aSelected ); rCallBack.Call(aInf); @@ -1243,7 +1276,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac OUString aWord = pAlt[sId.toInt32() - MN_AUTOSTART]; SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); if ( pAutoCorrect ) - pAutoCorrect->PutText( aSelected, aWord, pImpEditView->pEditEngine->pImpEditEngine->GetLanguage( aPaM2 ) ); + pAutoCorrect->PutText( aSelected, aWord, getImpEditEngine().GetLanguage( aPaM2 ).nLang ); InsertText( aWord ); } else if ( sId.toInt32() >= MN_ALTSTART ) // Replace @@ -1256,43 +1289,46 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac { SetSelection( aOldSel ); } + return true; } OUString EditView::SpellIgnoreWord() { - return pImpEditView->SpellIgnoreWord(); + return getImpl().SpellIgnoreWord(); } void EditView::SelectCurrentWord( sal_Int16 nWordType ) { - EditSelection aCurSel( pImpEditView->GetEditSelection() ); - pImpEditView->DrawSelectionXOR(); - aCurSel = pImpEditView->pEditEngine->SelectWord(aCurSel.Max(), nWordType); - pImpEditView->SetEditSelection( aCurSel ); - pImpEditView->DrawSelectionXOR(); + EditSelection aCurSel( getImpl().GetEditSelection() ); + getImpl().DrawSelectionXOR(); + aCurSel = getEditEngine().SelectWord(aCurSel.Max(), nWordType); + getImpl().SetEditSelection( aCurSel ); + getImpl().DrawSelectionXOR(); ShowCursor( true, false ); } void EditView::InsertParaBreak() { - pImpEditView->pEditEngine->UndoActionStart(EDITUNDO_INSERT); - pImpEditView->DeleteSelected(); - EditPaM aPaM(pImpEditView->pEditEngine->InsertParaBreak(pImpEditView->GetEditSelection())); - pImpEditView->pEditEngine->UndoActionEnd(); - pImpEditView->SetEditSelection(EditSelection(aPaM, aPaM)); - pImpEditView->pEditEngine->FormatAndUpdate(this); + getEditEngine().UndoActionStart(EDITUNDO_INSERT); + getImpl().DeleteSelected(); + EditPaM aPaM(getEditEngine().InsertParaBreak(getImpl().GetEditSelection())); + getEditEngine().UndoActionEnd(); + getImpl().SetEditSelection(EditSelection(aPaM, aPaM)); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout(this); } void EditView::InsertField( const SvxFieldItem& rFld ) { - EditEngine* pEE = pImpEditView->pEditEngine; - pImpEditView->DrawSelectionXOR(); - pEE->UndoActionStart( EDITUNDO_INSERT ); - EditPaM aPaM( pEE->InsertField( pImpEditView->GetEditSelection(), rFld ) ); - pEE->UndoActionEnd(); - pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) ); - pEE->UpdateFields(); - pEE->FormatAndUpdate( this ); + EditEngine& rEditEngine = getImpl().getEditEngine(); + getImpl().DrawSelectionXOR(); + rEditEngine.UndoActionStart( EDITUNDO_INSERT ); + EditPaM aPaM(rEditEngine.InsertField(getImpl().GetEditSelection(), rFld)); + rEditEngine.UndoActionEnd(); + getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); + rEditEngine.UpdateFields(); + if (rEditEngine.IsUpdateLayout()) + rEditEngine.FormatAndLayout( this ); } const SvxFieldItem* EditView::GetFieldUnderMousePointer() const @@ -1304,90 +1340,161 @@ const SvxFieldItem* EditView::GetFieldUnderMousePointer() const const SvxFieldItem* EditView::GetField( const Point& rPos, sal_Int32* pPara, sal_Int32* pPos ) const { - return pImpEditView->GetField( rPos, pPara, pPos ); + return getImpl().GetField( rPos, pPara, pPos ); } const SvxFieldItem* EditView::GetFieldUnderMousePointer( sal_Int32& nPara, sal_Int32& nPos ) const { Point aPos; - if (EditViewCallbacks* pEditViewCallbacks = pImpEditView->getEditViewCallbacks()) + if (EditViewCallbacks* pEditViewCallbacks = getImpl().getEditViewCallbacks()) aPos = pEditViewCallbacks->EditViewPointerPosPixel(); else - aPos = pImpEditView->GetWindow()->GetPointerPosPixel(); - OutputDevice& rDevice = pImpEditView->GetOutputDevice(); + aPos = getImpl().GetWindow()->GetPointerPosPixel(); + OutputDevice& rDevice = getImpl().GetOutputDevice(); aPos = rDevice.PixelToLogic(aPos); return GetField( aPos, &nPara, &nPos ); } -const SvxFieldItem* EditView::GetFieldAtSelection() const +const SvxFieldItem* EditView::GetFieldAtSelection(bool bAlsoCheckBeforeCursor) const +{ + bool* pIsBeforeCursor = bAlsoCheckBeforeCursor ? &bAlsoCheckBeforeCursor : nullptr; + return GetFieldAtSelection(pIsBeforeCursor); +} + +// If pIsBeforeCursor != nullptr, the position before the cursor will also be checked for a field +// and pIsBeforeCursor will return true if that fallback field is returned. +// If no field is returned, the value in pIsBeforeCursor is meaningless. +const SvxFieldItem* EditView::GetFieldAtSelection(bool* pIsBeforeCursor) const { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); + // a field is a dummy character - so it cannot span nodes or be a selection larger than 1 + EditSelection aSel( getImpl().GetEditSelection() ); + if (aSel.Min().GetNode() != aSel.Max().GetNode()) + return nullptr; + + // normalize: min < max + aSel.Adjust(getEditEngine().GetEditDoc()); + + const sal_Int32 nMinIndex = aSel.Min().GetIndex(); + const sal_Int32 nMaxIndex = aSel.Max().GetIndex(); + if (nMaxIndex > nMinIndex + 1) + return nullptr; + // Only when cursor is in font of field, no selection, // or only selecting field - if ( ( aSel.Min().GetNode() == aSel.Max().GetNode() ) && - ( ( aSel.Max().GetIndex() == aSel.Min().GetIndex() ) || - ( aSel.Max().GetIndex() == aSel.Min().GetIndex()+1 ) ) ) + bool bAlsoCheckBeforeCursor = false; + if (pIsBeforeCursor) { - EditPaM aPaM = aSel.Min(); - const CharAttribList::AttribsType& rAttrs = aPaM.GetNode()->GetCharAttribs().GetAttribs(); - const sal_Int32 nXPos = aPaM.GetIndex(); - for (size_t nAttr = rAttrs.size(); nAttr; ) + *pIsBeforeCursor = false; + bAlsoCheckBeforeCursor = nMaxIndex == nMinIndex; + } + const SvxFieldItem* pFoundBeforeCursor = nullptr; + const CharAttribList::AttribsType& rAttrs = aSel.Min().GetNode()->GetCharAttribs().GetAttribs(); + for (const auto& rAttr: rAttrs) + { + if (rAttr->Which() == EE_FEATURE_FIELD) { - const EditCharAttrib& rAttr = *rAttrs[--nAttr]; - if (rAttr.GetStart() == nXPos) - if (rAttr.Which() == EE_FEATURE_FIELD) - { - DBG_ASSERT(dynamic_cast<const SvxFieldItem* >(rAttr.GetItem() ) != nullptr, "No FieldItem..."); - return static_cast<const SvxFieldItem*>(rAttr.GetItem()); - } + DBG_ASSERT(dynamic_cast<const SvxFieldItem*>(rAttr->GetItem()), "No FieldItem..."); + if (rAttr->GetStart() == nMinIndex) + return static_cast<const SvxFieldItem*>(rAttr->GetItem()); + + // perhaps the cursor is behind the field? + if (nMinIndex && rAttr->GetStart() == nMinIndex - 1) + pFoundBeforeCursor = static_cast<const SvxFieldItem*>(rAttr->GetItem()); } } + if (bAlsoCheckBeforeCursor) + { + *pIsBeforeCursor = /*(bool)*/pFoundBeforeCursor; + return pFoundBeforeCursor; + } return nullptr; } void EditView::SelectFieldAtCursor() { - const SvxFieldItem* pFieldItem = GetFieldAtSelection(); - if (pFieldItem) + bool bIsBeforeCursor = false; + const SvxFieldItem* pFieldItem = GetFieldAtSelection(&bIsBeforeCursor); + if (!pFieldItem) + return; + + // Make sure the whole field is selected + // A field is represented by a dummy character - so it cannot be a selection larger than 1 + ESelection aSel = GetSelection(); + if (aSel.nStartPos == aSel.nEndPos) // not yet selected { - // Make sure the whole field is selected - ESelection aSel = GetSelection(); - if (aSel.nStartPos == aSel.nEndPos) + if (bIsBeforeCursor) { - aSel.nEndPos++; - SetSelection(aSel); + assert (aSel.nStartPos); + --aSel.nStartPos; } + else + aSel.nEndPos++; + SetSelection(aSel); } + else + assert(std::abs(aSel.nStartPos - aSel.nEndPos) == 1); +} + +const SvxFieldData* EditView::GetFieldUnderMouseOrInSelectionOrAtCursor(bool bAlsoCheckBeforeCursor) const +{ + const SvxFieldItem* pFieldItem = GetFieldUnderMousePointer(); if (!pFieldItem) + pFieldItem = GetFieldAtSelection(bAlsoCheckBeforeCursor); + + return pFieldItem ? pFieldItem->GetField() : nullptr; +} + +sal_Int32 EditView::countFieldsOffsetSum(sal_Int32 nPara, sal_Int32 nPos, bool bCanOverflow) const +{ + int nOffset = 0; + + for (int nCurrentPara = 0; nCurrentPara <= nPara; nCurrentPara++) { - // Cursor probably behind the field - extend selection to select the field - ESelection aSel = GetSelection(); - if (aSel.nStartPos > 0 && aSel.nStartPos == aSel.nEndPos) + int nFields = getEditEngine().GetFieldCount( nCurrentPara ); + for (int nField = 0; nField < nFields; nField++) { - aSel.nStartPos--; - SetSelection(aSel); + EFieldInfo aFieldInfo = getEditEngine().GetFieldInfo( nCurrentPara, nField ); + + bool bLastPara = nCurrentPara == nPara; + sal_Int32 nFieldPos = aFieldInfo.aPosition.nIndex; + + if (bLastPara && nFieldPos >= nPos) + break; + + sal_Int32 nFieldLen = aFieldInfo.aCurrentText.getLength(); + + // position in the middle of a field + if (!bCanOverflow && bLastPara && nFieldPos + nFieldLen > nPos) + nFieldLen = nPos - nFieldPos; + + nOffset += nFieldLen - 1; } } + + return nOffset; } -const SvxFieldData* EditView::GetFieldAtCursor() const +sal_Int32 EditView::GetPosNoField(sal_Int32 nPara, sal_Int32 nPos) const { - const SvxFieldItem* pFieldItem = GetFieldUnderMousePointer(); - if (!pFieldItem) - pFieldItem = GetFieldAtSelection(); + sal_Int32 nOffset = countFieldsOffsetSum(nPara, nPos, false); + assert(nPos >= nOffset); + return nPos - nOffset; +} - return pFieldItem ? pFieldItem->GetField() : nullptr; +sal_Int32 EditView::GetPosWithField(sal_Int32 nPara, sal_Int32 nPos) const +{ + sal_Int32 nOffset = countFieldsOffsetSum(nPara, nPos, true); + return nPos + nOffset; } void EditView::SetInvalidateMore( sal_uInt16 nPixel ) { - pImpEditView->SetInvalidateMore( nPixel ); + getImpl().SetInvalidateMore( nPixel ); } sal_uInt16 EditView::GetInvalidateMore() const { - return pImpEditView->GetInvalidateMore(); + return getImpl().GetInvalidateMore(); } static void ChangeFontSizeImpl( EditView* pEditView, bool bGrow, const ESelection& rSel, const FontList* pFontList ) @@ -1408,7 +1515,7 @@ static void ChangeFontSizeImpl( EditView* pEditView, bool bGrow, const ESelectio void EditView::ChangeFontSize( bool bGrow, const FontList* pFontList ) { - EditEngine& rEditEngine = *pImpEditView->pEditEngine; + EditEngine& rEditEngine = getEditEngine(); ESelection aSel( GetSelection() ); ESelection aOldSelection( aSel ); @@ -1467,7 +1574,6 @@ bool EditView::ChangeFontSize( bool bGrow, SfxItemSet& rSet, const FontList* pFo return false; static const sal_uInt16 gFontSizeWichMap[] = { EE_CHAR_FONTHEIGHT, EE_CHAR_FONTHEIGHT_CJK, EE_CHAR_FONTHEIGHT_CTL, 0 }; - const SvxFontItem& rFontItem = rSet.Get(EE_CHAR_FONTINFO); bool bRet = false; const sal_uInt16* pWhich = gFontSizeWichMap; @@ -1478,8 +1584,7 @@ bool EditView::ChangeFontSize( bool bGrow, SfxItemSet& rSet, const FontList* pFo const MapUnit eUnit = rSet.GetPool()->GetMetric( *pWhich ); nHeight = OutputDevice::LogicToLogic(nHeight * 10, eUnit, MapUnit::MapPoint); - FontMetric aFontMetric = pFontList->Get( rFontItem.GetFamilyName(), rFontItem.GetStyleName() ); - const int* pAry = pFontList->GetSizeAry( aFontMetric ); + const int* pAry = FontList::GetStdSizeAry(); if( bGrow ) { @@ -1545,12 +1650,12 @@ bool EditView::ChangeFontSize( bool bGrow, SfxItemSet& rSet, const FontList* pFo OUString EditView::GetSurroundingText() const { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); + EditSelection aSel( getImpl().GetEditSelection() ); + aSel.Adjust(getEditEngine().GetEditDoc()); if( HasSelection() ) { - OUString aStr = pImpEditView->pEditEngine->GetSelected(aSel); + OUString aStr = getEditEngine().GetSelected(aSel); // Stop reconversion if the selected text includes a line break. if ( aStr.indexOf( 0x0A ) == -1 ) @@ -1562,7 +1667,7 @@ OUString EditView::GetSurroundingText() const { aSel.Min().SetIndex( 0 ); aSel.Max().SetIndex( aSel.Max().GetNode()->Len() ); - return pImpEditView->pEditEngine->GetSelected(aSel); + return getEditEngine().GetSelected(aSel); } } @@ -1573,9 +1678,9 @@ Selection EditView::GetSurroundingTextSelection() const if( HasSelection() ) { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); - OUString aStr = pImpEditView->pEditEngine->GetSelected(aSel); + EditSelection aSel( getImpl().GetEditSelection() ); + aSel.Adjust(getEditEngine().GetEditDoc()); + OUString aStr = getEditEngine().GetSelected(aSel); // Stop reconversion if the selected text includes a line break. if ( aStr.indexOf( 0x0A ) == -1 ) @@ -1602,79 +1707,99 @@ bool EditView::DeleteSurroundingText(const Selection& rRange) void EditView::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark) { - Point aDocPos(pImpEditView->GetDocPos(rPosition)); - EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aDocPos); - EditSelection aSelection(pImpEditView->GetEditSelection()); + Point aDocPos(getImpl().GetDocPos(rPosition)); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos); + EditSelection aSelection(getImpl().GetEditSelection()); // Explicitly create or delete the selection. if (bClearMark) { - pImpEditView->DeselectAll(); - aSelection = pImpEditView->GetEditSelection(); + getImpl().DeselectAll(); + aSelection = getImpl().GetEditSelection(); } else - pImpEditView->CreateAnchor(); + getImpl().CreateAnchor(); if (bPoint) aSelection.Max() = aPaM; else aSelection.Min() = aPaM; - if (pImpEditView->GetEditSelection().Min() != aSelection.Min()) - pImpEditView->pEditEngine->CursorMoved(pImpEditView->GetEditSelection().Min().GetNode()); - pImpEditView->DrawSelectionXOR(aSelection); - if (pImpEditView->GetEditSelection() != aSelection) - pImpEditView->SetEditSelection(aSelection); + if (getImpl().GetEditSelection().Min() != aSelection.Min()) + { + const ContentNode* pNode(getImpl().GetEditSelection().Min().GetNode()); + if (nullptr != pNode) + pNode->checkAndDeleteEmptyAttribs(); + } + + getImpl().DrawSelectionXOR(aSelection); + if (getImpl().GetEditSelection() != aSelection) + getImpl().SetEditSelection(aSelection); ShowCursor(/*bGotoCursor=*/false); } void EditView::DrawSelectionXOR(OutlinerViewShell* pOtherShell) { - pImpEditView->RegisterOtherShell(pOtherShell); - pImpEditView->DrawSelectionXOR(); - pImpEditView->RegisterOtherShell(nullptr); + getImpl().RegisterOtherShell(pOtherShell); + getImpl().DrawSelectionXOR(); + getImpl().RegisterOtherShell(nullptr); } void EditView::InitLOKSpecialPositioning(MapUnit eUnit, const tools::Rectangle& rOutputArea, const Point& rVisDocStartPos) { - pImpEditView->InitLOKSpecialPositioning(eUnit, rOutputArea, rVisDocStartPos); + getImpl().InitLOKSpecialPositioning(eUnit, rOutputArea, rVisDocStartPos); } void EditView::SetLOKSpecialOutputArea(const tools::Rectangle& rOutputArea) { - pImpEditView->SetLOKSpecialOutputArea(rOutputArea); + getImpl().SetLOKSpecialOutputArea(rOutputArea); } const tools::Rectangle & EditView::GetLOKSpecialOutputArea() const { - return pImpEditView->GetLOKSpecialOutputArea(); + return getImpl().GetLOKSpecialOutputArea(); } void EditView::SetLOKSpecialVisArea(const tools::Rectangle& rVisArea) { - pImpEditView->SetLOKSpecialVisArea(rVisArea); + getImpl().SetLOKSpecialVisArea(rVisArea); } tools::Rectangle EditView::GetLOKSpecialVisArea() const { - return pImpEditView->GetLOKSpecialVisArea(); + return getImpl().GetLOKSpecialVisArea(); } bool EditView::HasLOKSpecialPositioning() const { - return pImpEditView->HasLOKSpecialPositioning(); + return getImpl().HasLOKSpecialPositioning(); +} + +void EditView::SetLOKSpecialFlags(LOKSpecialFlags eFlags) +{ + getImpl().SetLOKSpecialFlags(eFlags); } void EditView::SuppressLOKMessages(bool bSet) { - pImpEditView->SuppressLOKMessages(bSet); + getImpl().SuppressLOKMessages(bSet); } bool EditView::IsSuppressLOKMessages() const { - return pImpEditView->IsSuppressLOKMessages(); + return getImpl().IsSuppressLOKMessages(); +} + +void EditView::SetNegativeX(bool bSet) +{ + getImpl().SetNegativeX(bSet); +} + +bool EditView::IsNegativeX() const +{ + return getImpl().IsNegativeX(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/edtspell.cxx b/editeng/source/editeng/edtspell.cxx index f3aa07e25c1e..b989755d8be4 100644 --- a/editeng/source/editeng/edtspell.cxx +++ b/editeng/source/editeng/edtspell.cxx @@ -32,7 +32,6 @@ #include <com/sun/star/linguistic2/XDictionary.hpp> using namespace com::sun::star::uno; -using namespace com::sun::star::beans; using namespace com::sun::star::linguistic2; @@ -49,9 +48,9 @@ EditSpellWrapper::EditSpellWrapper(weld::Widget* pWindow, void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) { - EditEngine* pEE = pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); - SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); + EditEngine& rEditEngine = pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = pEditView->getImpEditEngine(); + SpellInfo* pSpellInfo = rImpEditEngine.GetSpellInfo(); if ( eArea == SvxSpellArea::BodyStart ) { @@ -62,14 +61,13 @@ void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) { pSpellInfo->bSpellToEnd = false; pSpellInfo->aSpellTo = pSpellInfo->aSpellStart; - pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + pEditView->getImpl().SetEditSelection(rEditEngine.GetEditDoc().GetStartPaM()); } else { pSpellInfo->bSpellToEnd = true; - pSpellInfo->aSpellTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetStartPaM() ); + pSpellInfo->aSpellTo = rImpEditEngine.CreateEPaM( + rEditEngine.GetEditDoc().GetStartPaM() ); } } else if ( eArea == SvxSpellArea::BodyEnd ) @@ -80,15 +78,14 @@ void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) if ( !IsStartDone() ) { pSpellInfo->bSpellToEnd = true; - pSpellInfo->aSpellTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetEndPaM() ); + pSpellInfo->aSpellTo = rImpEditEngine.CreateEPaM( + rEditEngine.GetEditDoc().GetEndPaM() ); } else { pSpellInfo->bSpellToEnd = false; pSpellInfo->aSpellTo = pSpellInfo->aSpellStart; - pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetEndPaM() ); + pEditView->getImpl().SetEditSelection(rEditEngine.GetEditDoc().GetEndPaM()); } } else if ( eArea == SvxSpellArea::Body ) @@ -103,24 +100,23 @@ void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) void EditSpellWrapper::SpellContinue() { - SetLast( pEditView->GetImpEditEngine()->ImpSpell( pEditView ) ); + SetLast(pEditView->getImpEditEngine().ImpSpell(pEditView)); } bool EditSpellWrapper::SpellMore() { - EditEngine* pEE = pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); - SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); + EditEngine& rEditEngine = pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = pEditView->getImpEditEngine(); + SpellInfo* pSpellInfo = rImpEditEngine.GetSpellInfo(); bool bMore = false; if ( pSpellInfo->bMultipleDoc ) { - bMore = pEE->SpellNextDocument(); + bMore = rEditEngine.SpellNextDocument(); if ( bMore ) { // The text has been entered into the engine, when backwards then // it must be behind the selection. - pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + pEditView->getImpl().SetEditSelection(rEditEngine.GetEditDoc().GetStartPaM()); } } return bMore; @@ -135,10 +131,10 @@ void EditSpellWrapper::ReplaceAll( const OUString &rNewText ) void EditSpellWrapper::CheckSpellTo() { - ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); - SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); - EditPaM aPaM( pEditView->GetImpEditView()->GetEditSelection().Max() ); - EPaM aEPaM = pImpEE->CreateEPaM( aPaM ); + ImpEditEngine& rImpEditEngine = pEditView->getImpEditEngine(); + SpellInfo* pSpellInfo = rImpEditEngine.GetSpellInfo(); + EditPaM aPaM( pEditView->getImpl().GetEditSelection().Max() ); + EPaM aEPaM = rImpEditEngine.CreateEPaM( aPaM ); if ( aEPaM.nPara == pSpellInfo->aSpellTo.nPara ) { // Check if SpellToEnd still has a valid Index, if replace has been @@ -150,9 +146,9 @@ void EditSpellWrapper::CheckSpellTo() WrongList::WrongList() : mnInvalidStart(0), mnInvalidEnd(Valid) {} -void WrongList::SetRanges( const std::vector<editeng::MisspellRange>& rRanges ) +void WrongList::SetRanges( std::vector<editeng::MisspellRange>&&rRanges ) { - maRanges = rRanges; + maRanges = std::move(rRanges); } bool WrongList::IsValid() const @@ -572,7 +568,7 @@ void EdtAutoCorrDoc::SetAttr(sal_Int32 nStt, sal_Int32 nEnd, pPool = pPool->GetSecondaryPool(); } - sal_uInt16 nWhich = pPool->GetWhich( nSlotId ); + sal_uInt16 nWhich = pPool->GetWhichIDFromSlotID( nSlotId ); if ( nWhich ) { rItem.SetWhich( nWhich ); @@ -613,8 +609,8 @@ OUString const* EdtAutoCorrDoc::GetPrevPara(bool const) bAllowUndoAction = false; // Not anymore ... - EditDoc& rNodes = mpEditEngine->GetEditDoc(); - sal_Int32 nPos = rNodes.GetPos( pCurNode ); + EditDoc& rEditDoc = mpEditEngine->GetEditDoc(); + sal_Int32 nPos = rEditDoc.GetPos( pCurNode ); // Special case: Bullet => Paragraph start => simply return NULL... const SfxBoolItem& rBulletState = mpEditEngine->GetParaAttrib( nPos, EE_PARA_BULLETSTATE ); @@ -632,7 +628,7 @@ OUString const* EdtAutoCorrDoc::GetPrevPara(bool const) for ( sal_Int32 n = nPos; n; ) { n--; - ContentNode* pNode = rNodes[n]; + ContentNode* pNode = rEditDoc.GetObject(n); if ( pNode->Len() ) return & pNode->GetString(); } @@ -654,7 +650,7 @@ bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_Int32& rSttPos, if( aShort.isEmpty() ) return bRet; - LanguageTag aLanguageTag( mpEditEngine->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) )); + LanguageTag aLanguageTag( mpEditEngine->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) ).nLang ); const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList( pCurNode->GetString(), rSttPos, nEndPos, *this, aLanguageTag); if( pFnd && pFnd->IsTextOnly() ) @@ -681,7 +677,7 @@ bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_Int32& rSttPos, } bool EdtAutoCorrDoc::TransliterateRTLWord( sal_Int32& /*rSttPos*/, - sal_Int32 /*nEndPos*/ ) + sal_Int32 /*nEndPos*/, bool /*bApply*/ ) { // Paragraph-start or a blank found, search for the word // shortcut in Auto @@ -693,7 +689,7 @@ bool EdtAutoCorrDoc::TransliterateRTLWord( sal_Int32& /*rSttPos*/, LanguageType EdtAutoCorrDoc::GetLanguage( sal_Int32 nPos ) const { - return mpEditEngine->GetLanguage( EditPaM( pCurNode, nPos+1 ) ); + return mpEditEngine->GetLanguage( EditPaM( pCurNode, nPos+1 ) ).nLang; } void EdtAutoCorrDoc::ImplStartUndoAction() diff --git a/editeng/source/editeng/eehtml.cxx b/editeng/source/editeng/eehtml.cxx index d83b5410d14f..b3ed28395506 100644 --- a/editeng/source/editeng/eehtml.cxx +++ b/editeng/source/editeng/eehtml.cxx @@ -31,12 +31,13 @@ #include <tools/tenccvt.hxx> #include <editeng/editeng.hxx> +#include <utility> #define STYLE_PRE 101 -EditHTMLParser::EditHTMLParser( SvStream& rIn, const OUString& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs ) +EditHTMLParser::EditHTMLParser( SvStream& rIn, OUString _aBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs ) : HTMLParser( rIn, true ), - aBaseURL( rBaseURL ), + aBaseURL(std::move( _aBaseURL )), mpEditEngine(nullptr), bInPara(false), bWasInPara(false), @@ -179,26 +180,19 @@ void EditHTMLParser::NextToken( HtmlTokenId nToken ) if ( !bInPara ) StartPara( false ); - OUString aText = aToken; + OUString aText = aToken.toString(); if ( aText.startsWith(" ") && ThrowAwayBlank() && !IsReadPRE() ) aText = aText.copy( 1 ); - if ( pCurAnchor ) + if ( moCurAnchor ) { - pCurAnchor->aText += aText; + moCurAnchor->aText += aText; } else { // Only written until HTML with 319? if ( IsReadPRE() ) - { - sal_Int32 nTabPos = aText.indexOf( '\t'); - while ( nTabPos != -1 ) - { - aText = aText.replaceAt( nTabPos, 1, " " ); - nTabPos = aText.indexOf( '\t', nTabPos+8 ); - } - } + aText = aText.replaceAll(u"\t", u" "); ImpInsertText( aText ); } } @@ -745,7 +739,7 @@ bool EditHTMLParser::HasTextInCurrentPara() void EditHTMLParser::AnchorStart() { // ignore anchor in anchor - if ( pCurAnchor ) + if ( moCurAnchor ) return; const HTMLOptions& aOptions = GetOptions(); @@ -768,20 +762,20 @@ void EditHTMLParser::AnchorStart() aRootURL.GetNewAbsURL( aRef, &aTargetURL ); aURL = aTargetURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); } - pCurAnchor.reset( new AnchorInfo ); - pCurAnchor->aHRef = aURL; + moCurAnchor.emplace(); + moCurAnchor->aHRef = aURL; } void EditHTMLParser::AnchorEnd() { - if ( !pCurAnchor ) + if ( !moCurAnchor ) return; // Insert as URL-Field... - SvxFieldItem aFld( SvxURLField( pCurAnchor->aHRef, pCurAnchor->aText, SvxURLFormat::Repr ), EE_FEATURE_FIELD ); + SvxFieldItem aFld( SvxURLField( moCurAnchor->aHRef, moCurAnchor->aText, SvxURLFormat::Repr ), EE_FEATURE_FIELD ); aCurSel = mpEditEngine->InsertField(aCurSel, aFld); bFieldsInserted = true; - pCurAnchor.reset(); + moCurAnchor.reset(); if (mpEditEngine->IsHtmlImportHandlerSet()) { diff --git a/editeng/source/editeng/eehtml.hxx b/editeng/source/editeng/eehtml.hxx index a2aa0e0448af..fddd567ac6ba 100644 --- a/editeng/source/editeng/eehtml.hxx +++ b/editeng/source/editeng/eehtml.hxx @@ -20,6 +20,7 @@ #pragma once #include <memory> +#include <optional> #include <editdoc.hxx> #include <rtl/ustrbuf.hxx> #include <svtools/parhtml.hxx> @@ -40,8 +41,7 @@ private: EditSelection aCurSel; OUString aBaseURL; EditEngine* mpEditEngine; - std::unique_ptr<AnchorInfo> - pCurAnchor; + std::optional<AnchorInfo> moCurAnchor; bool bInPara:1; bool bWasInPara:1; // Remember bInPara before HeadingStart, because afterwards it will be gone. @@ -71,7 +71,7 @@ protected: virtual void NextToken( HtmlTokenId nToken ) override; public: - EditHTMLParser(SvStream& rIn, const OUString& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs); + EditHTMLParser(SvStream& rIn, OUString aBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs); virtual ~EditHTMLParser() override; SvParserState CallParser(EditEngine* pEE, const EditPaM& rPaM); diff --git a/editeng/source/editeng/eerdll.cxx b/editeng/source/editeng/eerdll.cxx index 8141c6481f86..732c85ee18cd 100644 --- a/editeng/source/editeng/eerdll.cxx +++ b/editeng/source/editeng/eerdll.cxx @@ -35,8 +35,8 @@ #include <editeng/scriptspaceitem.hxx> #include <editeng/hngpnctitem.hxx> #include <editeng/forbiddenruleitem.hxx> -#include <svl/itempool.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <vcl/svapp.hxx> #include <vcl/virdev.hxx> @@ -64,112 +64,152 @@ #include <editeng/xmlcnitm.hxx> #include <editeng/forbiddencharacterstable.hxx> #include <editeng/justifyitem.hxx> -#include <rtl/instance.hxx> #include <tools/mapunit.hxx> +#include <vcl/lazydelete.hxx> +#include <svl/itempool.hxx> +#include <editeng/editids.hrc> using namespace ::com::sun::star; -namespace -{ - class theEditDLL : public rtl::Static<EditDLL, theEditDLL> {}; -} - EditDLL& EditDLL::Get() { - return theEditDLL::get(); + /** + Prevent use-after-free errors during application shutdown. + Previously this data was function-static, but then data in i18npool would + be torn down before the destructor here ran, causing a crash. + */ + static vcl::DeleteOnDeinit< EditDLL > gaEditDll; + return *gaEditDll.get(); } -DefItems::DefItems() - : mvDefItems(EDITITEMCOUNT) +ItemInfoPackage& getItemInfoPackageEditEngine() { - std::vector<SfxPoolItem*>& rDefItems = mvDefItems; - - // Paragraph attributes: - SvxNumRule aDefaultNumRule( SvxNumRuleFlags::NONE, 0, false ); - - rDefItems[0] = new SvxFrameDirectionItem( SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ); - rDefItems[1] = new SvXMLAttrContainerItem( EE_PARA_XMLATTRIBS ); - rDefItems[2] = new SvxHangingPunctuationItem(false, EE_PARA_HANGINGPUNCTUATION); - rDefItems[3] = new SvxForbiddenRuleItem(true, EE_PARA_FORBIDDENRULES); - rDefItems[4] = new SvxScriptSpaceItem( true, EE_PARA_ASIANCJKSPACING ); - rDefItems[5] = new SvxNumBulletItem( aDefaultNumRule, EE_PARA_NUMBULLET ); - rDefItems[6] = new SfxBoolItem( EE_PARA_HYPHENATE, false ); - rDefItems[7] = new SfxBoolItem( EE_PARA_HYPHENATE_NO_CAPS, false ); - rDefItems[8] = new SfxBoolItem( EE_PARA_BULLETSTATE, true ); - rDefItems[9] = new SvxLRSpaceItem( EE_PARA_OUTLLRSPACE ); - rDefItems[10] = new SfxInt16Item( EE_PARA_OUTLLEVEL, -1 ); - rDefItems[11] = new SvxBulletItem( EE_PARA_BULLET ); - rDefItems[12] = new SvxLRSpaceItem( EE_PARA_LRSPACE ); - rDefItems[13] = new SvxULSpaceItem( EE_PARA_ULSPACE ); - rDefItems[14] = new SvxLineSpacingItem( 0, EE_PARA_SBL ); - rDefItems[15] = new SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ); - rDefItems[16] = new SvxTabStopItem( 0, 0, SvxTabAdjust::Left, EE_PARA_TABS ); - rDefItems[17] = new SvxJustifyMethodItem( SvxCellJustifyMethod::Auto, EE_PARA_JUST_METHOD ); - rDefItems[18] = new SvxVerJustifyItem( SvxCellVerJustify::Standard, EE_PARA_VER_JUST ); - - // Character attributes: - rDefItems[19] = new SvxColorItem( COL_AUTO, EE_CHAR_COLOR ); - rDefItems[20] = new SvxFontItem( EE_CHAR_FONTINFO ); - rDefItems[21] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ); - rDefItems[22] = new SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH ); - rDefItems[23] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ); - rDefItems[24] = new SvxUnderlineItem( LINESTYLE_NONE, EE_CHAR_UNDERLINE ); - rDefItems[25] = new SvxCrossedOutItem( STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ); - rDefItems[26] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ); - rDefItems[27] = new SvxContourItem( false, EE_CHAR_OUTLINE ); - rDefItems[28] = new SvxShadowedItem( false, EE_CHAR_SHADOW ); - rDefItems[29] = new SvxEscapementItem( 0, 100, EE_CHAR_ESCAPEMENT ); - rDefItems[30] = new SvxAutoKernItem( false, EE_CHAR_PAIRKERNING ); - rDefItems[31] = new SvxKerningItem( 0, EE_CHAR_KERNING ); - rDefItems[32] = new SvxWordLineModeItem( false, EE_CHAR_WLM ); - rDefItems[33] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE ); - rDefItems[34] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CJK ); - rDefItems[35] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CTL ); - rDefItems[36] = new SvxFontItem( EE_CHAR_FONTINFO_CJK ); - rDefItems[37] = new SvxFontItem( EE_CHAR_FONTINFO_CTL ); - rDefItems[38] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CJK ); - rDefItems[39] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CTL ); - rDefItems[40] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ); - rDefItems[41] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ); - rDefItems[42] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ); - rDefItems[43] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ); - rDefItems[44] = new SvxEmphasisMarkItem( FontEmphasisMark::NONE, EE_CHAR_EMPHASISMARK ); - rDefItems[45] = new SvxCharReliefItem( FontRelief::NONE, EE_CHAR_RELIEF ); - rDefItems[46] = new SfxVoidItem( EE_CHAR_RUBI_DUMMY ); - rDefItems[47] = new SvXMLAttrContainerItem( EE_CHAR_XMLATTRIBS ); - rDefItems[48] = new SvxOverlineItem( LINESTYLE_NONE, EE_CHAR_OVERLINE ); - rDefItems[49] = new SvxCaseMapItem( SvxCaseMap::NotMapped, EE_CHAR_CASEMAP ); - rDefItems[50] = new SfxGrabBagItem( EE_CHAR_GRABBAG ); - rDefItems[51] = new SvxColorItem( COL_AUTO, EE_CHAR_BKGCOLOR ); - // Features - rDefItems[52] = new SfxVoidItem( EE_FEATURE_TAB ); - rDefItems[53] = new SfxVoidItem( EE_FEATURE_LINEBR ); - rDefItems[54] = new SvxColorItem( COL_RED, EE_FEATURE_NOTCONV ); - rDefItems[55] = new SvxFieldItem( SvxFieldData(), EE_FEATURE_FIELD ); - - assert(EDITITEMCOUNT == 56 && "ITEMCOUNT changed, adjust DefItems!"); - - // Init DefFonts: - GetDefaultFonts( *static_cast<SvxFontItem*>(rDefItems[EE_CHAR_FONTINFO - EE_ITEMS_START]), - *static_cast<SvxFontItem*>(rDefItems[EE_CHAR_FONTINFO_CJK - EE_ITEMS_START]), - *static_cast<SvxFontItem*>(rDefItems[EE_CHAR_FONTINFO_CTL - EE_ITEMS_START]) ); -} + class ItemInfoPackageEditEngine : public ItemInfoPackage + { + typedef std::array<ItemInfoStatic, EE_ITEMS_END - EE_ITEMS_START + 1> ItemInfoArrayEditEngine; + ItemInfoArrayEditEngine maItemInfos {{ + // m_nWhich, m_pItem, m_nSlotID, m_nItemInfoFlags + { EE_PARA_WRITINGDIR, new SvxFrameDirectionItem( SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ), SID_ATTR_FRAMEDIRECTION, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_XMLATTRIBS, new SvXMLAttrContainerItem( EE_PARA_XMLATTRIBS ), 0, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + { EE_PARA_HANGINGPUNCTUATION, new SvxHangingPunctuationItem(false, EE_PARA_HANGINGPUNCTUATION), SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_FORBIDDENRULES, new SvxForbiddenRuleItem(true, EE_PARA_FORBIDDENRULES), SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_ASIANCJKSPACING, new SvxScriptSpaceItem( true, EE_PARA_ASIANCJKSPACING ), SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEMINFOFLAG_NONE }, -DefItems::~DefItems() -{ - for (auto& rItem : mvDefItems) - delete rItem; -} + // need to use dynamic default for this Item, the office tends to crash at shutdown + // due to static stuff/cleanup at ~SvxNumRule (pStdNumFmt/pStdOutlineNumFmt) + { EE_PARA_NUMBULLET, nullptr, SID_ATTR_NUMBERING_RULE, SFX_ITEMINFOFLAG_NONE }, -std::shared_ptr<DefItems> GlobalEditData::GetDefItems() -{ - auto xDefItems = m_xDefItems.lock(); - if (!xDefItems) - { - xDefItems = std::make_shared<DefItems>(); - m_xDefItems = xDefItems; - } - return xDefItems; + { EE_PARA_HYPHENATE, new SfxBoolItem( EE_PARA_HYPHENATE, false ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_HYPHENATE_NO_CAPS, new SfxBoolItem( EE_PARA_HYPHENATE_NO_CAPS, false ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_HYPHENATE_NO_LAST_WORD, new SfxBoolItem( EE_PARA_HYPHENATE_NO_LAST_WORD, false ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_BULLETSTATE, new SfxBoolItem( EE_PARA_BULLETSTATE, true ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_OUTLLRSPACE, new SvxLRSpaceItem( EE_PARA_OUTLLRSPACE ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_OUTLLEVEL, new SfxInt16Item( EE_PARA_OUTLLEVEL, -1 ), SID_ATTR_PARA_OUTLLEVEL, SFX_ITEMINFOFLAG_NONE }, + + // needs on-demand initialization + { EE_PARA_BULLET, nullptr, SID_ATTR_PARA_BULLET, SFX_ITEMINFOFLAG_NONE }, + + { EE_PARA_LRSPACE, new SvxLRSpaceItem( EE_PARA_LRSPACE ), SID_ATTR_LRSPACE, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_ULSPACE, new SvxULSpaceItem( EE_PARA_ULSPACE ), SID_ATTR_ULSPACE, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_SBL, new SvxLineSpacingItem( 0, EE_PARA_SBL ), SID_ATTR_PARA_LINESPACE, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_JUST, new SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ), SID_ATTR_PARA_ADJUST, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_TABS, new SvxTabStopItem( 0, 0, SvxTabAdjust::Left, EE_PARA_TABS ), SID_ATTR_TABSTOP, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_JUST_METHOD, new SvxJustifyMethodItem( SvxCellJustifyMethod::Auto, EE_PARA_JUST_METHOD ), SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_VER_JUST, new SvxVerJustifyItem( SvxCellVerJustify::Standard, EE_PARA_VER_JUST ), SID_ATTR_ALIGN_VER_JUSTIFY, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_COLOR, new SvxColorItem( COL_AUTO, EE_CHAR_COLOR ), SID_ATTR_CHAR_COLOR, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + + // EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK and EE_CHAR_FONTINFO_CTL need on-demand initialization + { EE_CHAR_FONTINFO, nullptr, SID_ATTR_CHAR_FONT, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + + { EE_CHAR_FONTHEIGHT, new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ), SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_FONTWIDTH, new SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH ), SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WEIGHT, new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ), SID_ATTR_CHAR_WEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_UNDERLINE, new SvxUnderlineItem( LINESTYLE_NONE, EE_CHAR_UNDERLINE ), SID_ATTR_CHAR_UNDERLINE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_STRIKEOUT, new SvxCrossedOutItem( STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ), SID_ATTR_CHAR_STRIKEOUT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ITALIC, new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ), SID_ATTR_CHAR_POSTURE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_OUTLINE, new SvxContourItem( false, EE_CHAR_OUTLINE ), SID_ATTR_CHAR_CONTOUR, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_SHADOW, new SvxShadowedItem( false, EE_CHAR_SHADOW ), SID_ATTR_CHAR_SHADOWED, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ESCAPEMENT, new SvxEscapementItem( 0, 100, EE_CHAR_ESCAPEMENT ), SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_PAIRKERNING, new SvxAutoKernItem( false, EE_CHAR_PAIRKERNING ), SID_ATTR_CHAR_AUTOKERN, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_KERNING, new SvxKerningItem( 0, EE_CHAR_KERNING ), SID_ATTR_CHAR_KERNING, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WLM, new SvxWordLineModeItem( false, EE_CHAR_WLM ), SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_LANGUAGE, new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE ), SID_ATTR_CHAR_LANGUAGE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_LANGUAGE_CJK, new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CJK ), SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_LANGUAGE_CTL, new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CTL ), SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEMINFOFLAG_NONE }, + + // see EE_CHAR_FONTINFO above + { EE_CHAR_FONTINFO_CJK, nullptr, SID_ATTR_CHAR_CJK_FONT, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + { EE_CHAR_FONTINFO_CTL, nullptr, SID_ATTR_CHAR_CTL_FONT, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + + { EE_CHAR_FONTHEIGHT_CJK, new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CJK ), SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_FONTHEIGHT_CTL, new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CTL ), SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WEIGHT_CJK, new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ), SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WEIGHT_CTL, new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ), SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ITALIC_CJK, new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ), SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ITALIC_CTL, new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ), SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_EMPHASISMARK, new SvxEmphasisMarkItem( FontEmphasisMark::NONE, EE_CHAR_EMPHASISMARK ), SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_RELIEF, new SvxCharReliefItem( FontRelief::NONE, EE_CHAR_RELIEF ), SID_ATTR_CHAR_RELIEF, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_XMLATTRIBS, new SvXMLAttrContainerItem( EE_CHAR_XMLATTRIBS ), 0, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + { EE_CHAR_OVERLINE, new SvxOverlineItem( LINESTYLE_NONE, EE_CHAR_OVERLINE ), SID_ATTR_CHAR_OVERLINE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_CASEMAP, new SvxCaseMapItem( SvxCaseMap::NotMapped, EE_CHAR_CASEMAP ), SID_ATTR_CHAR_CASEMAP, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_GRABBAG, new SfxGrabBagItem( EE_CHAR_GRABBAG ), SID_ATTR_CHAR_GRABBAG, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_BKGCOLOR, new SvxColorItem( COL_AUTO, EE_CHAR_BKGCOLOR ), SID_ATTR_CHAR_BACK_COLOR, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_TAB, new SfxVoidItem( EE_FEATURE_TAB ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_LINEBR, new SfxVoidItem( EE_FEATURE_LINEBR ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_NOTCONV, new SvxColorItem( COL_RED, EE_FEATURE_NOTCONV ), SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_FIELD, new SvxFieldItem( SvxFieldData(), EE_FEATURE_FIELD ), SID_FIELD, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE } + }}; + + virtual const ItemInfoStatic& getItemInfoStatic(size_t nIndex) const override { return maItemInfos[nIndex]; } + + public: + ItemInfoPackageEditEngine() + { + // on-demand (but only once) as static defaults - above (and also + // in constructor) the needed OutputDevice::Font stuff is not yet + // initialized + setItemAtItemInfoStatic( + new SvxBulletItem(EE_PARA_BULLET), + maItemInfos[EE_PARA_BULLET - EE_ITEMS_START]); + + // same for EE_CHAR_FONTINFO/EE_CHAR_FONTINFO_CJK/EE_CHAR_FONTINFO_CTL + // doing here as static default will be done only once for LO runtime + SvxFontItem* pFont(new SvxFontItem(EE_CHAR_FONTINFO)); + SvxFontItem* pFontCJK(new SvxFontItem(EE_CHAR_FONTINFO_CJK)); + SvxFontItem* pFontCTL(new SvxFontItem(EE_CHAR_FONTINFO_CTL)); + + // Init DefFonts: + GetDefaultFonts(*pFont, *pFontCJK, *pFontCTL); + + setItemAtItemInfoStatic(pFont, maItemInfos[EE_CHAR_FONTINFO - EE_ITEMS_START]); + setItemAtItemInfoStatic(pFontCJK, maItemInfos[EE_CHAR_FONTINFO_CJK - EE_ITEMS_START]); + setItemAtItemInfoStatic(pFontCTL, maItemInfos[EE_CHAR_FONTINFO_CTL - EE_ITEMS_START]); + } + + virtual size_t size() const override { return maItemInfos.size(); } + virtual const ItemInfo& getItemInfo(size_t nIndex, SfxItemPool& /*rPool*/) override + { + const ItemInfo& rRetval(maItemInfos[nIndex]); + + // return immediately if we have the static entry and Item + if (nullptr != rRetval.getItem()) + return rRetval; + + // check for dynamic ItemInfo creation, needed here for SvxNumBulletItem + if (EE_PARA_NUMBULLET == rRetval.getWhich()) + return *new ItemInfoDynamic( + rRetval, + new SvxNumBulletItem( SvxNumRule( SvxNumRuleFlags::NONE, 0, false ), EE_PARA_NUMBULLET )); + + // return in any case + return rRetval; + } + }; + + static std::unique_ptr<ItemInfoPackageEditEngine> g_aItemInfoPackageEditEngine; + if (!g_aItemInfoPackageEditEngine) + g_aItemInfoPackageEditEngine.reset(new ItemInfoPackageEditEngine); + return *g_aItemInfoPackageEditEngine; } std::shared_ptr<SvxForbiddenCharactersTable> const & GlobalEditData::GetForbiddenCharsTable() @@ -188,7 +228,7 @@ uno::Reference< linguistic2::XLanguageGuessing > const & GlobalEditData::GetLang return xLanguageGuesser; } -OUString EditResId(std::string_view aId) +OUString EditResId(TranslateId aId) { return Translate::get(aId, Translate::Create("editeng")); } diff --git a/editeng/source/editeng/eertfpar.cxx b/editeng/source/editeng/eertfpar.cxx index 278699dbfcb1..557081f8496f 100644 --- a/editeng/source/editeng/eertfpar.cxx +++ b/editeng/source/editeng/eertfpar.cxx @@ -31,6 +31,7 @@ #include <svtools/rtftoken.h> #include <svtools/htmltokn.h> +#include <comphelper/configuration.hxx> using namespace com::sun::star; @@ -55,10 +56,6 @@ RtfImportInfo::RtfImportInfo( RtfImportState eSt, SvParser<int>* pPrsrs, const E nTokenValue = 0; } -RtfImportInfo::~RtfImportInfo() -{ -} - constexpr MapUnit gRTFMapUnit = MapUnit::MapTwip; EditRTFParser::EditRTFParser( @@ -206,7 +203,6 @@ void EditRTFParser::NextToken( int nToken ) SkipGroup(); } break; - case RTF_PGDSCTBL: // #i29453# ignore \*\pgdsctbl destination case RTF_LISTTEXT: { SkipGroup(); @@ -307,7 +303,6 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) EditPaM aEndPaM( pEndNode, rSet.GetEndCnt() ); // If possible adjust the Escapement-Item: - const SfxPoolItem* pItem; // #i66167# adapt font heights to destination MapUnit if necessary const MapUnit eDestUnit = mpEditEngine->GetEditDoc().GetItemPool().GetMetric(0); @@ -316,6 +311,7 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) sal_uInt16 const aFntHeightIems[3] = { EE_CHAR_FONTHEIGHT, EE_CHAR_FONTHEIGHT_CJK, EE_CHAR_FONTHEIGHT_CTL }; for (unsigned short aFntHeightIem : aFntHeightIems) { + const SfxPoolItem* pItem; if (SfxItemState::SET == rSet.GetAttrSet().GetItemState( aFntHeightIem, false, &pItem )) { sal_uInt32 nHeight = static_cast<const SvxFontHeightItem*>(pItem)->GetHeight(); @@ -331,23 +327,29 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) } } - if( SfxItemState::SET == rSet.GetAttrSet().GetItemState( EE_CHAR_ESCAPEMENT, false, &pItem )) + if( const SvxEscapementItem* pItem = rSet.GetAttrSet().GetItemIfSet( EE_CHAR_ESCAPEMENT, false ) ) { // the correct one - tools::Long nEsc = static_cast<const SvxEscapementItem*>(pItem)->GetEsc(); + tools::Long nEsc = pItem->GetEsc(); tools::Long nEscFontHeight = 0; if( ( DFLT_ESC_AUTO_SUPER != nEsc ) && ( DFLT_ESC_AUTO_SUB != nEsc ) ) { nEsc *= 10; //HalfPoints => Twips was embezzled in RTFITEM.CXX! SvxFont aFont; - mpEditEngine->SeekCursor(aStartPaM.GetNode(), aStartPaM.GetIndex()+1, aFont); + if (comphelper::IsFuzzing()) + { + // ofz#24932 detecting RTL vs LTR is slow + aFont = aStartPaM.GetNode()->GetCharAttribs().GetDefFont(); + } + else + mpEditEngine->SeekCursor(aStartPaM.GetNode(), aStartPaM.GetIndex()+1, aFont); nEscFontHeight = aFont.GetFontSize().Height(); } if (nEscFontHeight) { nEsc = nEsc * 100 / nEscFontHeight; - SvxEscapementItem aEscItem( static_cast<short>(nEsc), static_cast<const SvxEscapementItem*>(pItem)->GetProportionalHeight(), EE_CHAR_ESCAPEMENT ); + SvxEscapementItem aEscItem( static_cast<short>(nEsc), pItem->GetProportionalHeight(), EE_CHAR_ESCAPEMENT ); rSet.GetAttrSet().Put( aEscItem ); } } @@ -374,8 +376,8 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) auto const& pS = it->second; mpEditEngine->SetStyleSheet( EditSelection(aStartPaM, aEndPaM), - static_cast<SfxStyleSheet*>(mpEditEngine->GetStyleSheetPool()->Find(pS->sName, SfxStyleFamily::All))); - nOutlLevel = pS->nOutlineNo; + static_cast<SfxStyleSheet*>(mpEditEngine->GetStyleSheetPool()->Find(pS.sName, SfxStyleFamily::All))); + nOutlLevel = pS.nOutlineNo; } } @@ -436,10 +438,10 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) SvxRTFStyleType* EditRTFParser::FindStyleSheet( std::u16string_view rName ) { SvxRTFStyleTbl& rTable = GetStyleTbl(); - for (auto const& iter : rTable) + for (auto & iter : rTable) { - if (iter.second->sName == rName) - return iter.second.get(); + if (iter.second.sName == rName) + return &iter.second; } return nullptr; } @@ -458,9 +460,9 @@ SfxStyleSheet* EditRTFParser::CreateStyleSheet( SvxRTFStyleType const * pRTFStyl SvxRTFStyleTbl::iterator it = GetStyleTbl().find( pRTFStyle->nBasedOn ); if ( it != GetStyleTbl().end()) { - SvxRTFStyleType *const pS = it->second.get(); - if ( pS && ( pS !=pRTFStyle ) ) - aParent = pS->sName; + SvxRTFStyleType const& rS = it->second; + if ( &rS != pRTFStyle ) + aParent = rS.sName; } } @@ -492,10 +494,10 @@ void EditRTFParser::CreateStyleSheets() // the SvxRTFParser has now created the template... if (mpEditEngine->GetStyleSheetPool() && mpEditEngine->IsImportRTFStyleSheetsSet()) { - for (auto const& elem : GetStyleTbl()) + for (auto & elem : GetStyleTbl()) { - SvxRTFStyleType* pRTFStyle = elem.second.get(); - CreateStyleSheet( pRTFStyle ); + SvxRTFStyleType& rRTFStyle = elem.second; + CreateStyleSheet( &rRTFStyle ); } } } @@ -510,20 +512,20 @@ void EditRTFParser::CalcValue() void EditRTFParser::ReadField() { // From SwRTFParser::ReadField() - int _nOpenBrakets = 1; // the first was already detected earlier + int _nOpenBrackets = 1; // the first was already detected earlier bool bFldInst = false; bool bFldRslt = false; OUString aFldInst; OUString aFldRslt; - while( _nOpenBrakets && IsParserWorking() ) + while( _nOpenBrackets && IsParserWorking() ) { switch( GetNextToken() ) { case '}': { - _nOpenBrakets--; - if ( _nOpenBrakets == 1 ) + _nOpenBrackets--; + if ( _nOpenBrackets == 1 ) { bFldInst = false; bFldRslt = false; @@ -531,7 +533,7 @@ void EditRTFParser::ReadField() } break; - case '{': _nOpenBrakets++; + case '{': _nOpenBrackets++; break; case RTF_FIELD: SkipGroup(); @@ -578,21 +580,21 @@ void EditRTFParser::ReadField() void EditRTFParser::SkipGroup() { - int _nOpenBrakets = 1; // the first was already detected earlier + int _nOpenBrackets = 1; // the first was already detected earlier - while( _nOpenBrakets && IsParserWorking() ) + while( _nOpenBrackets && IsParserWorking() ) { switch( GetNextToken() ) { case '}': { - _nOpenBrakets--; + _nOpenBrackets--; } break; case '{': { - _nOpenBrakets++; + _nOpenBrackets++; } break; } diff --git a/editeng/source/editeng/fieldupdater.cxx b/editeng/source/editeng/fieldupdater.cxx index b342aacca48b..05eca4575590 100644 --- a/editeng/source/editeng/fieldupdater.cxx +++ b/editeng/source/editeng/fieldupdater.cxx @@ -22,7 +22,7 @@ class FieldUpdaterImpl { EditTextObjectImpl& mrObj; public: - explicit FieldUpdaterImpl(EditTextObject const & rObj) : mrObj(*rObj.mpImpl) {} + explicit FieldUpdaterImpl(EditTextObject& rObj) : mrObj(toImpl(rObj)) {} void updateTableFields(int nTab) { @@ -47,13 +47,13 @@ public: // Create a new table field with the new ID, and set it to the // attribute object. SvxFieldItem aNewItem(SvxTableField(nTab), EE_FEATURE_FIELD); - rAttr.SetItem(pPool->Put(aNewItem)); + rAttr.SetItem(*pPool, aNewItem); } } } }; -FieldUpdater::FieldUpdater(EditTextObject const & rObj) : mpImpl(new FieldUpdaterImpl(rObj)) {} +FieldUpdater::FieldUpdater(EditTextObject& rObj) : mpImpl(new FieldUpdaterImpl(rObj)) {} FieldUpdater::FieldUpdater(const FieldUpdater& r) : mpImpl(new FieldUpdaterImpl(*r.mpImpl)) {} FieldUpdater::~FieldUpdater() diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx index 9fb5ce8d8897..94d707cf902e 100644 --- a/editeng/source/editeng/impedit.cxx +++ b/editeng/source/editeng/impedit.cxx @@ -22,6 +22,7 @@ #include <editeng/editeng.hxx> #include <editeng/editview.hxx> #include <editeng/outliner.hxx> +#include <editeng/urlfieldhelper.hxx> #include <tools/poly.hxx> #include <editeng/unolingu.hxx> #include <com/sun/star/linguistic2/XDictionary.hpp> @@ -45,9 +46,7 @@ #include <sfx2/lokhelper.hxx> #include <boost/property_tree/ptree.hpp> -using namespace ::com::sun::star; -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::linguistic2; +using namespace css; #define SCRLRANGE 20 // Scroll 1/20 of the width/height, when in QueryDrop @@ -69,7 +68,8 @@ LOKSpecialPositioning::LOKSpecialPositioning(const ImpEditView& rImpEditView, Ma mrImpEditView(rImpEditView), maOutArea(rOutputArea), maVisDocStartPos(rVisDocStartPos), - meUnit(eUnit) + meUnit(eUnit), + meFlags(LOKSpecialFlags::NONE) { } @@ -178,30 +178,30 @@ Point LOKSpecialPositioning::GetRefPoint() const // class ImpEditView -ImpEditView::ImpEditView( EditView* pView, EditEngine* pEng, vcl::Window* pWindow ) : - pEditView(pView), - mpViewShell(nullptr), - mpOtherShell(nullptr), - pEditEngine(pEng), - pOutWin(pWindow), - nInvMore(1), - nControl(EVControlBits::AUTOSCROLL | EVControlBits::ENABLEPASTE), - nTravelXPos(TRAVEL_X_DONTKNOW), - nExtraCursorFlags(GetCursorFlags::NONE), - nCursorBidiLevel(CURSOR_BIDILEVEL_DONTKNOW), - nScrollDiffX(0), - bReadOnly(false), - bClickedInSelection(false), - bActiveDragAndDropListener(false), - aOutArea( Point(), pEng->GetPaperSize() ), - eSelectionMode(EESelectionMode::Std), - eAnchorMode(EEAnchorMode::TopLeft), - mpEditViewCallbacks(nullptr), - mbBroadcastLOKViewCursor(comphelper::LibreOfficeKit::isActive()), - mbSuppressLOKMessages(false) -{ - aEditSelection.Min() = pEng->GetEditDoc().GetStartPaM(); - aEditSelection.Max() = pEng->GetEditDoc().GetEndPaM(); +ImpEditView::ImpEditView(EditView* pView, EditEngine* pEditEngine, vcl::Window* pWindow) + : mpEditView(pView) + , mpViewShell(nullptr) + , mpOtherShell(nullptr) + , mpEditEngine(pEditEngine) + , mpOutputWindow(pWindow) + , mnInvalidateMore(1) + , mnControl(EVControlBits::AUTOSCROLL | EVControlBits::ENABLEPASTE) + , mnTravelXPos(TRAVEL_X_DONTKNOW) + , mnCursorBidiLevel(CURSOR_BIDILEVEL_DONTKNOW) + , mnScrollDiffX(0) + , mbReadOnly(false) + , mbClickedInSelection(false) + , mbActiveDragAndDropListener(false) + , maOutputArea(Point(), mpEditEngine->GetPaperSize()) + , meSelectionMode(EESelectionMode::Std) + , meAnchorMode(EEAnchorMode::TopLeft) + , mpEditViewCallbacks(nullptr) + , mbBroadcastLOKViewCursor(comphelper::LibreOfficeKit::isActive()) + , mbSuppressLOKMessages(false) + , mbNegativeX(false) +{ + maEditSelection.Min() = mpEditEngine->GetEditDoc().GetStartPaM(); + maEditSelection.Max() = mpEditEngine->GetEditDoc().GetEndPaM(); SelectionChanged(); } @@ -210,8 +210,8 @@ ImpEditView::~ImpEditView() { RemoveDragAndDropListeners(); - if ( pOutWin && ( pOutWin->GetCursor() == pCursor.get() ) ) - pOutWin->SetCursor( nullptr ); + if (mpOutputWindow && (mpOutputWindow->GetCursor() == mpCursor.get())) + mpOutputWindow->SetCursor( nullptr ); } void ImpEditView::SetBackgroundColor( const Color& rColor ) @@ -242,17 +242,19 @@ const OutlinerViewShell* ImpEditView::GetViewShell() const void ImpEditView::SetEditSelection( const EditSelection& rEditSelection ) { // set state before notification - aEditSelection = rEditSelection; + maEditSelection = rEditSelection; SelectionChanged(); if (comphelper::LibreOfficeKit::isActive()) + { // Tiled rendering: selections are only painted when we are in selection mode. - pEditEngine->SetInSelectionMode(aEditSelection.HasRange()); + getEditEngine().SetInSelectionMode(maEditSelection.HasRange()); + } - if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() ) + if (getImpEditEngine().GetNotifyHdl().IsSet() ) { - const EditDoc& rDoc = pEditEngine->GetEditDoc(); + const EditDoc& rDoc = getEditEngine().GetEditDoc(); const EditPaM pmEnd = rDoc.GetEndPaM(); EENotifyType eNotifyType; if (rDoc.Count() > 1 && @@ -266,17 +268,18 @@ void ImpEditView::SetEditSelection( const EditSelection& rEditSelection ) eNotifyType = EE_NOTIFY_TEXTVIEWSELECTIONCHANGED; } EENotify aNotify( eNotifyType ); - pEditEngine->pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpEditEngine().GetNotifyHdl().Call( aNotify ); } - if(pEditEngine->pImpEditEngine->IsFormatted()) + + if (getImpEditEngine().IsFormatted()) { EENotify aNotify(EE_NOTIFY_PROCESSNOTIFICATIONS); - pEditEngine->pImpEditEngine->GetNotifyHdl().Call(aNotify); + getImpEditEngine().GetNotifyHdl().Call(aNotify); } } /// Translate absolute <-> relative twips: LOK wants absolute coordinates as output and gives absolute coordinates as input. -static void lcl_translateTwips(vcl::Window const & rParent, vcl::Window& rChild) +static void lcl_translateTwips(const OutputDevice& rParent, OutputDevice& rChild) { // Don't translate if we already have a non-zero origin. // This prevents multiple translate calls that negate @@ -319,14 +322,14 @@ void ImpEditView::SelectionChanged() } // This function is also called when a text's font || size is changed. Because its highlight rectangle must be updated. -void ImpEditView::lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> &pPolyPoly, bool bStartHandleVisible, bool bEndHandleVisible) { - VclPtr<vcl::Window> pParent = pOutWin->GetParentWithLOKNotifier(); +void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> &pPolyPoly, bool bStartHandleVisible, bool bEndHandleVisible) { + VclPtr<vcl::Window> pParent = mpOutputWindow->GetParentWithLOKNotifier(); vcl::Region aRegion( *pPolyPoly ); if (pParent && pParent->GetLOKWindowId() != 0) { - const tools::Long nX = pOutWin->GetOutOffXPixel() - pParent->GetOutOffXPixel(); - const tools::Long nY = pOutWin->GetOutOffYPixel() - pParent->GetOutOffYPixel(); + const tools::Long nX = mpOutputWindow->GetOutOffXPixel() - pParent->GetOutOffXPixel(); + const tools::Long nY = mpOutputWindow->GetOutOffYPixel() - pParent->GetOutOffYPixel(); std::vector<tools::Rectangle> aRectangles; aRegion.GetRegionRectangles(aRectangles); @@ -334,7 +337,7 @@ void ImpEditView::lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> std::vector<OString> v; for (tools::Rectangle & rRectangle : aRectangles) { - rRectangle = pOutWin->LogicToPixel(rRectangle); + rRectangle = mpOutputWindow->LogicToPixel(rRectangle); rRectangle.Move(nX, nY); v.emplace_back(rRectangle.toString().getStr()); } @@ -347,34 +350,33 @@ void ImpEditView::lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> aItems.emplace_back("endHandleVisible", OString::boolean(bEndHandleVisible)); pNotifier->notifyWindow(pParent->GetLOKWindowId(), "text_selection", aItems); } - else + else if (mpViewShell) { - pOutWin->GetOutDev()->Push(PushFlags::MAPMODE); - if (pOutWin->GetMapMode().GetMapUnit() == MapUnit::MapTwip) + mpOutputWindow->GetOutDev()->Push(vcl::PushFlags::MAPMODE); + if (mpOutputWindow->GetMapMode().GetMapUnit() == MapUnit::MapTwip) { // Find the parent that is not right // on top of us to use its offset. - vcl::Window* parent = pOutWin->GetParent(); + vcl::Window* parent = mpOutputWindow->GetParent(); while (parent && - parent->GetOutOffXPixel() == pOutWin->GetOutOffXPixel() && - parent->GetOutOffYPixel() == pOutWin->GetOutOffYPixel()) + parent->GetOutOffXPixel() == mpOutputWindow->GetOutOffXPixel() && + parent->GetOutOffYPixel() == mpOutputWindow->GetOutOffYPixel()) { parent = parent->GetParent(); } if (parent) { - lcl_translateTwips(*parent, *pOutWin); + lcl_translateTwips(*parent->GetOutDev(), *mpOutputWindow->GetOutDev()); } } - bool bMm100ToTwip = !mpLOKSpecialPositioning && - (pOutWin->GetMapMode().GetMapUnit() == MapUnit::Map100thMM); + bool bMm100ToTwip = !mpLOKSpecialPositioning && (mpOutputWindow->GetMapMode().GetMapUnit() == MapUnit::Map100thMM); Point aOrigin; - if (pOutWin->GetMapMode().GetMapUnit() == MapUnit::MapTwip) + if (mpOutputWindow->GetMapMode().GetMapUnit() == MapUnit::MapTwip) // Writer comments: they use editeng, but are separate widgets. - aOrigin = pOutWin->GetMapMode().GetOrigin(); + aOrigin = mpOutputWindow->GetMapMode().GetOrigin(); OString sRectangle; OString sRefPoint; @@ -386,13 +388,13 @@ void ImpEditView::lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> if (!aRectangles.empty()) { - if (pOutWin->IsChart()) + if (mpOutputWindow->IsChart()) { const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj(); - if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin)) + if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*mpOutputWindow)) { - Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow); - Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx); + Point aOffsetPx = mpOutputWindow->GetOffsetPixelFrom(*pViewShellWindow); + Point aLogicOffset = mpOutputWindow->PixelToLogic(aOffsetPx); for (tools::Rectangle& rRect : aRectangles) rRect.Move(aLogicOffset.getX(), aLogicOffset.getY()); } @@ -402,7 +404,9 @@ void ImpEditView::lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> for (tools::Rectangle & rRectangle : aRectangles) { if (bMm100ToTwip) - rRectangle = OutputDevice::LogicToLogic(rRectangle, MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip)); + { + rRectangle = o3tl::convert(rRectangle, o3tl::Length::mm100, o3tl::Length::twip); + } rRectangle.Move(aOrigin.getX(), aOrigin.getY()); v.emplace_back(rRectangle.toString().getStr()); } @@ -418,7 +422,7 @@ void ImpEditView::lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> if (mpLOKSpecialPositioning) aPayload += ":: " + sRefPoint; - mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, aPayload.getStr()); + mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, aPayload); tools::Rectangle& rEnd = aRectangles.back(); tools::Rectangle aEnd(rEnd.Right() - 1, rEnd.Top(), rEnd.Right(), rEnd.Bottom()); @@ -427,22 +431,22 @@ void ImpEditView::lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> if (mpLOKSpecialPositioning) aPayload += ":: " + sRefPoint; - mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, aPayload.getStr()); + mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, aPayload); } if (mpOtherShell) { // Another shell wants to know about our existing selection. if (mpViewShell != mpOtherShell) - mpViewShell->NotifyOtherView(mpOtherShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRectangle); + mpViewShell->NotifyOtherView(mpOtherShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection"_ostr, sRectangle); } else { - mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRectangle.getStr()); - mpViewShell->NotifyOtherViews(LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRectangle); + mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRectangle); + mpViewShell->NotifyOtherViews(LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection"_ostr, sRectangle); } - pOutWin->GetOutDev()->Pop(); + mpOutputWindow->GetOutDev()->Pop(); } } @@ -467,7 +471,7 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, return; } - if ( eSelectionMode == EESelectionMode::Hidden ) + if (meSelectionMode == EESelectionMode::Hidden) return; // It must be ensured before rendering the selection, that the contents of @@ -482,13 +486,13 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, bool bClipRegion = rTarget.IsClipRegion(); vcl::Region aOldRegion = rTarget.GetClipRegion(); - std::unique_ptr<tools::PolyPolygon> pPolyPoly; + std::optional<tools::PolyPolygon> pPolyPoly; if ( !pRegion && !comphelper::LibreOfficeKit::isActive()) { - if ( !pEditEngine->pImpEditEngine->GetUpdateMode() ) + if (!getImpEditEngine().IsUpdateLayout()) return; - if ( pEditEngine->pImpEditEngine->IsInUndo() ) + if (getImpEditEngine().IsInUndo()) return; if ( !aTmpSel.HasRange() ) @@ -496,30 +500,32 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, // aTmpOutArea: if OutputArea > Paper width and // Text > Paper width ( over large fields ) - tools::Rectangle aTmpOutArea( aOutArea ); - if ( aTmpOutArea.GetWidth() > pEditEngine->pImpEditEngine->GetPaperSize().Width() ) - aTmpOutArea.SetRight( aTmpOutArea.Left() + pEditEngine->pImpEditEngine->GetPaperSize().Width() ); + tools::Rectangle aTmpOutArea(maOutputArea); + if ( aTmpOutArea.GetWidth() > getImpEditEngine().GetPaperSize().Width() ) + aTmpOutArea.SetRight( aTmpOutArea.Left() + getImpEditEngine().GetPaperSize().Width() ); rTarget.IntersectClipRegion( aTmpOutArea ); - if (pOutWin && pOutWin->GetCursor()) - pOutWin->GetCursor()->Hide(); + if (mpOutputWindow && mpOutputWindow->GetCursor()) + mpOutputWindow->GetCursor()->Hide(); } if (comphelper::LibreOfficeKit::isActive() || pRegion) - pPolyPoly.reset(new tools::PolyPolygon); + pPolyPoly = tools::PolyPolygon(); - DBG_ASSERT( !pEditEngine->IsIdleFormatterActive(), "DrawSelectionXOR: Not formatted!" ); - aTmpSel.Adjust( pEditEngine->GetEditDoc() ); + DBG_ASSERT(!getEditEngine().IsIdleFormatterActive(), "DrawSelectionXOR: Not formatted!"); + aTmpSel.Adjust(getEditEngine().GetEditDoc()); ContentNode* pStartNode = aTmpSel.Min().GetNode(); ContentNode* pEndNode = aTmpSel.Max().GetNode(); - const sal_Int32 nStartPara = pEditEngine->GetEditDoc().GetPos(pStartNode); - const sal_Int32 nEndPara = pEditEngine->GetEditDoc().GetPos(pEndNode); + const sal_Int32 nStartPara = getEditEngine().GetEditDoc().GetPos(pStartNode); + const sal_Int32 nEndPara = getEditEngine().GetEditDoc().GetPos(pEndNode); if (nStartPara == EE_PARA_NOT_FOUND || nEndPara == EE_PARA_NOT_FOUND) return; bool bStartHandleVisible = false; bool bEndHandleVisible = false; + bool bLOKCalcRTL = mpLOKSpecialPositioning && + (mpLOKSpecialPositioning->IsLayoutRTL() || getEditEngine().IsRightToLeft(nStartPara)); auto DrawHighlight = [&, nStartLine = sal_Int32(0), nEndLine = sal_Int32(0)]( const ImpEditEngine::LineAreaInfo& rInfo) mutable { @@ -570,9 +576,9 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, if (nEndIndex < nStartIndex) nEndIndex = nStartIndex; - tools::Rectangle aTmpRect(pEditEngine->pImpEditEngine->GetEditCursor( - &rInfo.rPortion, rInfo.pLine, nStartIndex, GetCursorFlags::NONE)); - aTmpRect.Move(0, pEditEngine->pImpEditEngine->getTopDirectionAware(rInfo.aArea)); + tools::Rectangle aTmpRect(getImpEditEngine().GetEditCursor(rInfo.rPortion, *rInfo.pLine, nStartIndex, CursorFlags())); + const Size aLineOffset = getImpEditEngine().getTopLeftDocOffset(rInfo.aArea); + aTmpRect.Move(0, aLineOffset.Height()); // Only paint if in the visible range ... if (aTmpRect.Top() > GetVisDocBottom()) @@ -589,50 +595,45 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, // Now that we have Bidi, the first/last index doesn't have to be the 'most outside' position if (!bPartOfLine) { - Range aLineXPosStartEnd - = pEditEngine->GetLineXPosStartEnd(&rInfo.rPortion, rInfo.pLine); + Range aLineXPosStartEnd = getEditEngine().GetLineXPosStartEnd(rInfo.rPortion, *rInfo.pLine); aTmpRect.SetLeft(aLineXPosStartEnd.Min()); aTmpRect.SetRight(aLineXPosStartEnd.Max()); - aTmpRect.Move(pEditEngine->pImpEditEngine->getLeftDirectionAware(rInfo.aArea), 0); + aTmpRect.Move(aLineOffset.Width(), 0); ImplDrawHighlightRect(rTarget, aTmpRect.TopLeft(), aTmpRect.BottomRight(), - pPolyPoly.get()); + pPolyPoly ? &*pPolyPoly : nullptr, bLOKCalcRTL); } else { sal_Int32 nTmpStartIndex = nStartIndex; sal_Int32 nWritingDirStart, nTmpEndIndex; - const sal_Int32 nLeftOffset - = pEditEngine->pImpEditEngine->getLeftDirectionAware(rInfo.aArea); while (nTmpStartIndex < nEndIndex) { - pEditEngine->pImpEditEngine->GetRightToLeft(rInfo.nPortion, nTmpStartIndex + 1, + getImpEditEngine().GetRightToLeft(rInfo.nPortion, nTmpStartIndex + 1, &nWritingDirStart, &nTmpEndIndex); if (nTmpEndIndex > nEndIndex) nTmpEndIndex = nEndIndex; DBG_ASSERT(nTmpEndIndex > nTmpStartIndex, "DrawSelectionXOR, Start >= End?"); - tools::Long nX1 - = pEditEngine->GetXPos(&rInfo.rPortion, rInfo.pLine, nTmpStartIndex, true); - tools::Long nX2 - = pEditEngine->GetXPos(&rInfo.rPortion, rInfo.pLine, nTmpEndIndex); + tools::Long nX1 = getEditEngine().GetXPos(rInfo.rPortion, *rInfo.pLine, nTmpStartIndex, true); + tools::Long nX2 = getEditEngine().GetXPos(rInfo.rPortion, *rInfo.pLine, nTmpEndIndex); aTmpRect.SetLeft(std::min(nX1, nX2)); aTmpRect.SetRight(std::max(nX1, nX2)); - aTmpRect.Move(nLeftOffset, 0); + aTmpRect.Move(aLineOffset.Width(), 0); ImplDrawHighlightRect(rTarget, aTmpRect.TopLeft(), aTmpRect.BottomRight(), - pPolyPoly.get()); + pPolyPoly ? &*pPolyPoly : nullptr, bLOKCalcRTL); nTmpStartIndex = nTmpEndIndex; } } } return ImpEditEngine::CallbackResult::Continue; }; - pEditEngine->pImpEditEngine->IterateLineAreas(DrawHighlight, ImpEditEngine::IterFlag::none); + getImpEditEngine().IterateLineAreas(DrawHighlight, ImpEditEngine::IterFlag::none); - if (comphelper::LibreOfficeKit::isActive() && mpViewShell && pOutWin) + if (comphelper::LibreOfficeKit::isActive() && mpViewShell && mpOutputWindow) lokSelectionCallback(pPolyPoly, bStartHandleVisible, bEndHandleVisible); if (pRegion || comphelper::LibreOfficeKit::isActive()) @@ -643,8 +644,8 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, } else { - if (pOutWin && pOutWin->GetCursor()) - pOutWin->GetCursor()->Show(); + if (mpOutputWindow && mpOutputWindow->GetCursor()) + mpOutputWindow->GetCursor()->Show(); if (bClipRegion) rTarget.SetClipRegion(aOldRegion); @@ -660,7 +661,7 @@ void ImpEditView::GetSelectionRectangles(EditSelection aTmpSel, std::vector<tool aRegion.GetRegionRectangles(rLogicRects); } -void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly ) +void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly, bool bLOKCalcRTL ) { if ( rDocPosTopLeft.X() == rDocPosBottomRight.X() ) return; @@ -673,6 +674,13 @@ void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDo Point aRefPointLogical = GetOutputArea().TopLeft(); // Get the relative coordinates w.r.t refpoint in display units. aSelRect.Move(-aRefPointLogical.X(), -aRefPointLogical.Y()); + if (bLOKCalcRTL) + { + tools::Long nMirrorW = GetOutputArea().GetWidth(); + tools::Long nLeft = aSelRect.Left(), nRight = aSelRect.Right(); + aSelRect.SetLeft(nMirrorW - nRight); + aSelRect.SetRight(nMirrorW - nLeft); + } // Convert from display unit to twips. aSelRect = OutputDevice::LogicToLogic(aSelRect, MapMode(eDevUnit), MapMode(MapUnit::MapTwip)); @@ -721,7 +729,7 @@ void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDo } else { - rTarget.Push(PushFlags::LINECOLOR|PushFlags::FILLCOLOR|PushFlags::RASTEROP); + rTarget.Push(vcl::PushFlags::LINECOLOR|vcl::PushFlags::FILLCOLOR|vcl::PushFlags::RASTEROP); rTarget.SetLineColor(); rTarget.SetFillColor(COL_BLACK); rTarget.SetRasterOp(RasterOp::Invert); @@ -734,12 +742,12 @@ void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDo bool ImpEditView::IsVertical() const { - return pEditEngine->pImpEditEngine->IsVertical(); + return getImpEditEngine().IsEffectivelyVertical(); } bool ImpEditView::IsTopToBottom() const { - return pEditEngine->pImpEditEngine->IsTopToBottom(); + return getImpEditEngine().IsTopToBottom(); } tools::Rectangle ImpEditView::GetVisDocArea() const @@ -752,22 +760,22 @@ Point ImpEditView::GetDocPos( const Point& rWindowPos ) const // Window Position => Position Document Point aPoint; - if ( !pEditEngine->pImpEditEngine->IsVertical() ) + if (!getImpEditEngine().IsEffectivelyVertical()) { - aPoint.setX( rWindowPos.X() - aOutArea.Left() + GetVisDocLeft() ); - aPoint.setY( rWindowPos.Y() - aOutArea.Top() + GetVisDocTop() ); + aPoint.setX( rWindowPos.X() - maOutputArea.Left() + GetVisDocLeft() ); + aPoint.setY( rWindowPos.Y() - maOutputArea.Top() + GetVisDocTop() ); } else { - if (pEditEngine->pImpEditEngine->IsTopToBottom()) + if (getImpEditEngine().IsTopToBottom()) { - aPoint.setX( rWindowPos.Y() - aOutArea.Top() + GetVisDocLeft() ); - aPoint.setY( aOutArea.Right() - rWindowPos.X() + GetVisDocTop() ); + aPoint.setX( rWindowPos.Y() - maOutputArea.Top() + GetVisDocLeft() ); + aPoint.setY( maOutputArea.Right() - rWindowPos.X() + GetVisDocTop() ); } else { - aPoint.setX( aOutArea.Bottom() - rWindowPos.Y() + GetVisDocLeft() ); - aPoint.setY( rWindowPos.X() - aOutArea.Left() + GetVisDocTop() ); + aPoint.setX( maOutputArea.Bottom() - rWindowPos.Y() + GetVisDocLeft() ); + aPoint.setY( rWindowPos.X() - maOutputArea.Left() + GetVisDocTop() ); } } @@ -779,22 +787,22 @@ Point ImpEditView::GetWindowPos( const Point& rDocPos ) const // Document position => window position Point aPoint; - if ( !pEditEngine->pImpEditEngine->IsVertical() ) + if (!getImpEditEngine().IsEffectivelyVertical()) { - aPoint.setX( rDocPos.X() + aOutArea.Left() - GetVisDocLeft() ); - aPoint.setY( rDocPos.Y() + aOutArea.Top() - GetVisDocTop() ); + aPoint.setX( rDocPos.X() + maOutputArea.Left() - GetVisDocLeft() ); + aPoint.setY( rDocPos.Y() + maOutputArea.Top() - GetVisDocTop() ); } else { - if (pEditEngine->pImpEditEngine->IsTopToBottom()) + if (getImpEditEngine().IsTopToBottom()) { - aPoint.setX( aOutArea.Right() - rDocPos.Y() + GetVisDocTop() ); - aPoint.setY( rDocPos.X() + aOutArea.Top() - GetVisDocLeft() ); + aPoint.setX( maOutputArea.Right() - rDocPos.Y() + GetVisDocTop() ); + aPoint.setY( rDocPos.X() + maOutputArea.Top() - GetVisDocLeft() ); } else { - aPoint.setX( aOutArea.Left() + rDocPos.Y() - GetVisDocTop() ); - aPoint.setY( aOutArea.Bottom() - rDocPos.X() + GetVisDocLeft() ); + aPoint.setX( maOutputArea.Left() + rDocPos.Y() - GetVisDocTop() ); + aPoint.setY( maOutputArea.Bottom() - rDocPos.X() + GetVisDocLeft() ); } } @@ -807,7 +815,7 @@ tools::Rectangle ImpEditView::GetWindowPos( const tools::Rectangle& rDocRect ) c Point aPos( GetWindowPos( rDocRect.TopLeft() ) ); Size aSz = rDocRect.GetSize(); tools::Rectangle aRect; - if ( !pEditEngine->pImpEditEngine->IsVertical() ) + if (!getImpEditEngine().IsEffectivelyVertical()) { aRect = tools::Rectangle( aPos, aSz ); } @@ -822,10 +830,10 @@ tools::Rectangle ImpEditView::GetWindowPos( const tools::Rectangle& rDocRect ) c void ImpEditView::SetSelectionMode( EESelectionMode eNewMode ) { - if ( eSelectionMode != eNewMode ) + if (meSelectionMode != eNewMode) { DrawSelectionXOR(); - eSelectionMode = eNewMode; + meSelectionMode = eNewMode; DrawSelectionXOR(); // redraw } } @@ -834,7 +842,7 @@ OutputDevice& ImpEditView::GetOutputDevice() const { if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) return pCallbacks->EditViewOutputDevice(); - return *pOutWin->GetOutDev(); + return *mpOutputWindow->GetOutDev(); } weld::Widget* ImpEditView::GetPopupParent(tools::Rectangle& rRect) const @@ -845,7 +853,7 @@ weld::Widget* ImpEditView::GetPopupParent(tools::Rectangle& rRect) const if (pParent) return pParent; } - return weld::GetPopupParent(*pOutWin, rRect); + return weld::GetPopupParent(*mpOutputWindow, rRect); } void ImpEditView::SetOutputArea( const tools::Rectangle& rRect ) @@ -854,13 +862,22 @@ void ImpEditView::SetOutputArea( const tools::Rectangle& rRect ) // should be better be aligned on pixels! tools::Rectangle aNewRect(rOutDev.LogicToPixel(rRect)); aNewRect = rOutDev.PixelToLogic(aNewRect); - aOutArea = aNewRect; - if ( !aOutArea.IsWidthEmpty() && aOutArea.Right() < aOutArea.Left() ) - aOutArea.SetRight( aOutArea.Left() ); - if ( !aOutArea.IsHeightEmpty() && aOutArea.Bottom() < aOutArea.Top() ) - aOutArea.SetBottom( aOutArea.Top() ); + maOutputArea = aNewRect; + if (!maOutputArea.IsWidthEmpty() && maOutputArea.Right() < maOutputArea.Left()) + maOutputArea.SetRight(maOutputArea.Left()); + if (!maOutputArea.IsHeightEmpty() && maOutputArea.Bottom() < maOutputArea.Top()) + maOutputArea.SetBottom(maOutputArea.Top()); + + SetScrollDiffX( static_cast<sal_uInt16>(maOutputArea.GetWidth()) * 2 / 10 ); +} + +namespace { + +tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) +{ + return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()); +} - SetScrollDiffX( static_cast<sal_uInt16>(aOutArea.GetWidth()) * 2 / 10 ); } void ImpEditView::InvalidateAtWindow(const tools::Rectangle& rRect) @@ -870,107 +887,107 @@ void ImpEditView::InvalidateAtWindow(const tools::Rectangle& rRect) // do not invalidate and trigger a global repaint, but forward // the need for change to the applied EditViewCallback, can e.g. // be used to visualize the active edit text in an OverlayObject - pCallbacks->EditViewInvalidate(rRect); + pCallbacks->EditViewInvalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect); } else { // classic mode: invalidate and trigger full repaint // of the changed area - GetWindow()->Invalidate(rRect); + GetWindow()->Invalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect); } } void ImpEditView::ResetOutputArea( const tools::Rectangle& rRect ) { // remember old out area - const tools::Rectangle aOldArea(aOutArea); + const tools::Rectangle aOldArea(maOutputArea); // apply new one SetOutputArea(rRect); // invalidate surrounding areas if update is true - if(aOldArea.IsEmpty() || !pEditEngine->pImpEditEngine->GetUpdateMode()) + if(aOldArea.IsEmpty() || !getImpEditEngine().IsUpdateLayout()) return; // #i119885# use grown area if needed; do when getting bigger OR smaller - const sal_Int32 nMore(DoInvalidateMore() ? GetOutputDevice().PixelToLogic(Size(nInvMore, 0)).Width() : 0); + const sal_Int32 nMore(DoInvalidateMore() ? GetOutputDevice().PixelToLogic(Size(mnInvalidateMore, 0)).Width() : 0); - if(aOldArea.Left() > aOutArea.Left()) + if (aOldArea.Left() > maOutputArea.Left()) { - const tools::Rectangle aRect(aOutArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Left(), aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(maOutputArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Left(), aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - else if(aOldArea.Left() < aOutArea.Left()) + else if (aOldArea.Left() < maOutputArea.Left()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOutArea.Left(), aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, maOutputArea.Left(), aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - if(aOldArea.Right() > aOutArea.Right()) + if (aOldArea.Right() > maOutputArea.Right()) { - const tools::Rectangle aRect(aOutArea.Right(), aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(maOutputArea.Right(), aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - else if(aOldArea.Right() < aOutArea.Right()) + else if (aOldArea.Right() < maOutputArea.Right()) { - const tools::Rectangle aRect(aOldArea.Right(), aOldArea.Top() - nMore, aOutArea.Right() + nMore, aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Right(), aOldArea.Top() - nMore, maOutputArea.Right() + nMore, aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - if(aOldArea.Top() > aOutArea.Top()) + if (aOldArea.Top() > maOutputArea.Top()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOutArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Top()); + const tools::Rectangle aRect(aOldArea.Left() - nMore, maOutputArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Top()); InvalidateAtWindow(aRect); } - else if(aOldArea.Top() < aOutArea.Top()) + else if (aOldArea.Top() < maOutputArea.Top()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOutArea.Top()); + const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Right() + nMore, maOutputArea.Top()); InvalidateAtWindow(aRect); } - if(aOldArea.Bottom() > aOutArea.Bottom()) + if (aOldArea.Bottom() > maOutputArea.Bottom()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOutArea.Bottom(), aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Left() - nMore, maOutputArea.Bottom(), aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - else if(aOldArea.Bottom() < aOutArea.Bottom()) + else if (aOldArea.Bottom() < maOutputArea.Bottom()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Bottom(), aOldArea.Right() + nMore, aOutArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Bottom(), aOldArea.Right() + nMore, maOutputArea.Bottom() + nMore); InvalidateAtWindow(aRect); } } void ImpEditView::RecalcOutputArea() { - Point aNewTopLeft( aOutArea.TopLeft() ); - Size aNewSz( aOutArea.GetSize() ); + Point aNewTopLeft(maOutputArea.TopLeft()); + Size aNewSz(maOutputArea.GetSize()); // X: if ( DoAutoWidth() ) { - if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageWidth() ) - aNewSz.setWidth( pEditEngine->pImpEditEngine->GetPaperSize().Width() ); - switch ( eAnchorMode ) + if (getImpEditEngine().GetStatus().AutoPageWidth()) + aNewSz.setWidth(getImpEditEngine().GetPaperSize().Width()); + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::VCenterLeft: case EEAnchorMode::BottomLeft: { - aNewTopLeft.setX( aAnchorPoint.X() ); + aNewTopLeft.setX(maAnchorPoint.X()); } break; case EEAnchorMode::TopHCenter: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::BottomHCenter: { - aNewTopLeft.setX( aAnchorPoint.X() - aNewSz.Width() / 2 ); + aNewTopLeft.setX(maAnchorPoint.X() - aNewSz.Width() / 2); } break; case EEAnchorMode::TopRight: case EEAnchorMode::VCenterRight: case EEAnchorMode::BottomRight: { - aNewTopLeft.setX( aAnchorPoint.X() - aNewSz.Width() - 1 ); + aNewTopLeft.setX(maAnchorPoint.X() - aNewSz.Width() - 1); } break; } @@ -979,29 +996,29 @@ void ImpEditView::RecalcOutputArea() // Y: if ( DoAutoHeight() ) { - if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageHeight() ) - aNewSz.setHeight( pEditEngine->pImpEditEngine->GetPaperSize().Height() ); - switch ( eAnchorMode ) + if (getImpEditEngine().GetStatus().AutoPageHeight()) + aNewSz.setHeight(getImpEditEngine().GetPaperSize().Height()); + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::TopHCenter: case EEAnchorMode::TopRight: { - aNewTopLeft.setY( aAnchorPoint.Y() ); + aNewTopLeft.setY(maAnchorPoint.Y()); } break; case EEAnchorMode::VCenterLeft: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::VCenterRight: { - aNewTopLeft.setY( aAnchorPoint.Y() - aNewSz.Height() / 2 ); + aNewTopLeft.setY(maAnchorPoint.Y() - aNewSz.Height() / 2); } break; case EEAnchorMode::BottomLeft: case EEAnchorMode::BottomHCenter: case EEAnchorMode::BottomRight: { - aNewTopLeft.setY( aAnchorPoint.Y() - aNewSz.Height() - 1 ); + aNewTopLeft.setY(maAnchorPoint.Y() - aNewSz.Height() - 1); } break; } @@ -1009,9 +1026,9 @@ void ImpEditView::RecalcOutputArea() ResetOutputArea( tools::Rectangle( aNewTopLeft, aNewSz ) ); } -void ImpEditView::SetAnchorMode( EEAnchorMode eMode ) +void ImpEditView::SetAnchorMode(EEAnchorMode eMode) { - eAnchorMode = eMode; + meAnchorMode = eMode; CalcAnchorPoint(); } @@ -1020,53 +1037,53 @@ void ImpEditView::CalcAnchorPoint() // GetHeight() and GetWidth() -1, because rectangle calculation not preferred. // X: - switch ( eAnchorMode ) + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::VCenterLeft: case EEAnchorMode::BottomLeft: { - aAnchorPoint.setX( aOutArea.Left() ); + maAnchorPoint.setX(maOutputArea.Left()); } break; case EEAnchorMode::TopHCenter: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::BottomHCenter: { - aAnchorPoint.setX( aOutArea.Left() + (aOutArea.GetWidth()-1) / 2 ); + maAnchorPoint.setX(maOutputArea.Left() + (maOutputArea.GetWidth() - 1) / 2); } break; case EEAnchorMode::TopRight: case EEAnchorMode::VCenterRight: case EEAnchorMode::BottomRight: { - aAnchorPoint.setX( aOutArea.Right() ); + maAnchorPoint.setX(maOutputArea.Right()); } break; } // Y: - switch ( eAnchorMode ) + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::TopHCenter: case EEAnchorMode::TopRight: { - aAnchorPoint.setY( aOutArea.Top() ); + maAnchorPoint.setY(maOutputArea.Top()); } break; case EEAnchorMode::VCenterLeft: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::VCenterRight: { - aAnchorPoint.setY( aOutArea.Top() + (aOutArea.GetHeight()-1) / 2 ); + maAnchorPoint.setY(maOutputArea.Top() + (maOutputArea.GetHeight() - 1) / 2); } break; case EEAnchorMode::BottomLeft: case EEAnchorMode::BottomHCenter: case EEAnchorMode::BottomRight: { - aAnchorPoint.setY( aOutArea.Bottom() - 1 ); + maAnchorPoint.setY(maOutputArea.Bottom() - 1); } break; } @@ -1086,36 +1103,35 @@ boost::property_tree::ptree getHyperlinkPropTree(const OUString& sText, const OU } // End of anon namespace -tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nShowCursorFlags, sal_Int32& nTextPortionStart, - const ParaPortion* pParaPortion) const +tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, CursorFlags aShowCursorFlags, sal_Int32& nTextPortionStart, ParaPortion const& rParaPortion) const { - tools::Rectangle aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, nShowCursorFlags ); - if ( !IsInsertMode() && !aEditSelection.HasRange() ) + tools::Rectangle aEditCursor = getImpEditEngine().PaMtoEditCursor(aPaM, aShowCursorFlags); + if (!IsInsertMode() && !maEditSelection.HasRange()) { if ( aPaM.GetNode()->Len() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) ) { // If we are behind a portion, and the next portion has other direction, we must change position... - aEditCursor.SetLeft( pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GetCursorFlags::TextOnly|GetCursorFlags::PreferPortionStart ).Left() ); + aEditCursor.SetLeft(getImpEditEngine().PaMtoEditCursor(aPaM, CursorFlags{.bTextOnly = true, .bPreferPortionStart = true}).Left()); aEditCursor.SetRight( aEditCursor.Left() ); - sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true ); - const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[nTextPortion]; + sal_Int32 nTextPortion = rParaPortion.GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true ); + const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[nTextPortion]; if ( rTextPortion.GetKind() == PortionKind::TAB ) { aEditCursor.AdjustRight(rTextPortion.GetSize().Width() ); } else { - EditPaM aNext = pEditEngine->CursorRight( aPaM ); - tools::Rectangle aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly ); + EditPaM aNext = getEditEngine().CursorRight( aPaM ); + tools::Rectangle aTmpRect = getImpEditEngine().PaMtoEditCursor(aNext, CursorFlags{ .bTextOnly = true }); if ( aTmpRect.Top() != aEditCursor.Top() ) - aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly|GetCursorFlags::EndOfLine ); + aTmpRect = getImpEditEngine().PaMtoEditCursor(aNext, CursorFlags{ .bTextOnly = true, .bEndOfLine = true }); aEditCursor.SetRight( aTmpRect.Left() ); } } } - tools::Long nMaxHeight = !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth(); + tools::Long nMaxHeight = !IsVertical() ? maOutputArea.GetHeight() : maOutputArea.GetWidth(); if ( aEditCursor.GetHeight() > nMaxHeight ) { aEditCursor.SetBottom( aEditCursor.Top() + nMaxHeight - 1 ); @@ -1126,16 +1142,17 @@ tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nS tools::Rectangle ImpEditView::GetEditCursor() const { - EditPaM aPaM( aEditSelection.Max() ); + EditPaM aPaM(maEditSelection.Max()); sal_Int32 nTextPortionStart = 0; - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); if (nPara == EE_PARA_NOT_FOUND) // #i94322 return tools::Rectangle(); - const ParaPortion& rParaPortion = pEditEngine->GetParaPortions()[nPara]; + ParaPortion const& rParaPortion = getEditEngine().GetParaPortions().getRef(nPara); - GetCursorFlags nShowCursorFlags = nExtraCursorFlags | GetCursorFlags::TextOnly; + CursorFlags aShowCursorFlags = maExtraCursorFlags; + aShowCursorFlags.bTextOnly = true; // Use CursorBidiLevel 0/1 in meaning of // 0: prefer portion end, normal mode @@ -1143,46 +1160,47 @@ tools::Rectangle ImpEditView::GetEditCursor() const if ( ( GetCursorBidiLevel() != CURSOR_BIDILEVEL_DONTKNOW ) && GetCursorBidiLevel() ) { - nShowCursorFlags |= GetCursorFlags::PreferPortionStart; + aShowCursorFlags.bPreferPortionStart = true; } - return ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, &rParaPortion); + return ImplGetEditCursor(aPaM, aShowCursorFlags, nTextPortionStart, rParaPortion); } void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) { // No ShowCursor in an empty View ... - if (aOutArea.IsEmpty()) + if (maOutputArea.IsEmpty()) return; - if ( ( aOutArea.Left() >= aOutArea.Right() ) && ( aOutArea.Top() >= aOutArea.Bottom() ) ) + if ( (maOutputArea.Left() >= maOutputArea.Right() ) && ( maOutputArea.Top() >= maOutputArea.Bottom() ) ) return; - pEditEngine->CheckIdleFormatter(); - if (!pEditEngine->IsFormatted()) - pEditEngine->pImpEditEngine->FormatDoc(); + getEditEngine().CheckIdleFormatter(); + if (!getEditEngine().IsFormatted()) + getImpEditEngine().FormatDoc(); // For some reasons I end up here during the formatting, if the Outliner // is initialized in Paint, because no SetPool(); - if ( pEditEngine->pImpEditEngine->IsFormatting() ) + if (getImpEditEngine().IsFormatting()) return; - if ( !pEditEngine->pImpEditEngine->GetUpdateMode() ) + if (!getImpEditEngine().IsUpdateLayout()) return; - if ( pEditEngine->pImpEditEngine->IsInUndo() ) + if (getImpEditEngine().IsInUndo()) return; - if (pOutWin && pOutWin->GetCursor() != GetCursor()) - pOutWin->SetCursor(GetCursor()); + if (mpOutputWindow && mpOutputWindow->GetCursor() != GetCursor()) + mpOutputWindow->SetCursor(GetCursor()); - EditPaM aPaM( aEditSelection.Max() ); + EditPaM aPaM(maEditSelection.Max()); sal_Int32 nTextPortionStart = 0; - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); if (nPara == EE_PARA_NOT_FOUND) // #i94322 return; - const ParaPortion& rParaPortion = pEditEngine->GetParaPortions()[nPara]; + ParaPortion const& rParaPortion = getEditEngine().GetParaPortions().getRef(nPara); - GetCursorFlags nShowCursorFlags = nExtraCursorFlags | GetCursorFlags::TextOnly; + CursorFlags aShowCursorFlags = maExtraCursorFlags; + aShowCursorFlags.bTextOnly = true; // Use CursorBidiLevel 0/1 in meaning of // 0: prefer portion end, normal mode @@ -1190,12 +1208,12 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) if ( ( GetCursorBidiLevel() != CURSOR_BIDILEVEL_DONTKNOW ) && GetCursorBidiLevel() ) { - nShowCursorFlags |= GetCursorFlags::PreferPortionStart; + aShowCursorFlags.bPreferPortionStart = true; } - tools::Rectangle aEditCursor = ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, &rParaPortion); + tools::Rectangle aEditCursor = ImplGetEditCursor(aPaM, aShowCursorFlags, nTextPortionStart, rParaPortion); - if ( bGotoCursor ) // && (!pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) ) + if ( bGotoCursor ) // && (!getImpEditEngine().GetStatus().AutoPageSize() ) ) { // check if scrolling is necessary... // if scrolling, then update () and Scroll ()! @@ -1205,7 +1223,7 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) tools::Rectangle aTmpVisArea( GetVisDocArea() ); // aTmpOutArea: if OutputArea > Paper width and // Text > Paper width ( over large fields ) - tools::Long nMaxTextWidth = !IsVertical() ? pEditEngine->pImpEditEngine->GetPaperSize().Width() : pEditEngine->pImpEditEngine->GetPaperSize().Height(); + tools::Long nMaxTextWidth = !IsVertical() ? getImpEditEngine().GetPaperSize().Width() : getImpEditEngine().GetPaperSize().Height(); if ( aTmpVisArea.GetWidth() > nMaxTextWidth ) aTmpVisArea.SetRight( aTmpVisArea.Left() + nMaxTextWidth ); @@ -1259,11 +1277,11 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) tools::Long nDiffY = !IsVertical() ? nDocDiffY : (IsTopToBottom() ? nDocDiffX : -nDocDiffX); if ( nDiffX ) - pEditEngine->GetInternalEditStatus().GetStatusWord() = pEditEngine->GetInternalEditStatus().GetStatusWord() | EditStatusFlags::HSCROLL; + getEditEngine().GetInternalEditStatus().GetStatusWord() = getEditEngine().GetInternalEditStatus().GetStatusWord() | EditStatusFlags::HSCROLL; if ( nDiffY ) - pEditEngine->GetInternalEditStatus().GetStatusWord() = pEditEngine->GetInternalEditStatus().GetStatusWord() | EditStatusFlags::VSCROLL; + getEditEngine().GetInternalEditStatus().GetStatusWord() = getEditEngine().GetInternalEditStatus().GetStatusWord() | EditStatusFlags::VSCROLL; Scroll( -nDiffX, -nDiffY ); - pEditEngine->pImpEditEngine->DelayedCallStatusHdl(); + getImpEditEngine().DelayedCallStatusHdl(); } } @@ -1335,6 +1353,13 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) Point aRefPointLogical = GetOutputArea().TopLeft(); // Get the relative coordinates w.r.t refpoint in display hmm. aCursorRectPureLogical.Move(-aRefPointLogical.X(), -aRefPointLogical.Y()); + if (getEditEngine().IsRightToLeft(nPara) || mpLOKSpecialPositioning->IsLayoutRTL()) + { + tools::Long nMirrorW = GetOutputArea().GetWidth(); + tools::Long nLeft = aCursorRectPureLogical.Left(), nRight = aCursorRectPureLogical.Right(); + aCursorRectPureLogical.SetLeft(nMirrorW - nRight); + aCursorRectPureLogical.SetRight(nMirrorW - nLeft); + } // Convert to twips. aCursorRectPureLogical = OutputDevice::LogicToLogic(aCursorRectPureLogical, MapMode(eDevUnit), MapMode(MapUnit::MapTwip)); // "refpoint" in print twips. @@ -1343,13 +1368,13 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) aMessageParams.put("refpoint", aRefPoint.toString()); } - if (pOutWin && pOutWin->IsChart()) + if (mpOutputWindow && mpOutputWindow->IsChart()) { const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj(); - if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin)) + if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*mpOutputWindow)) { - Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow); - Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx); + Point aOffsetPx = mpOutputWindow->GetOffsetPixelFrom(*pViewShellWindow); + Point aLogicOffset = mpOutputWindow->PixelToLogic(aOffsetPx); aPos.Move(aLogicOffset.getX(), aLogicOffset.getY()); } } @@ -1358,7 +1383,9 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) // LOK output is always in twips, convert from mm100 if necessary. if (rOutDev.GetMapMode().GetMapUnit() == MapUnit::Map100thMM) - aRect = OutputDevice::LogicToLogic(aRect, MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip)); + { + aRect = o3tl::convert(aRect, o3tl::Length::mm100, o3tl::Length::twip); + } else if (rOutDev.GetMapMode().GetMapUnit() == MapUnit::MapTwip) { // Writer comments: they use editeng, but are separate widgets. @@ -1385,21 +1412,19 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) else { // is cursor at a misspelled word ? - Reference< linguistic2::XSpellChecker1 > xSpeller( pEditEngine->pImpEditEngine->GetSpeller() ); + uno::Reference<linguistic2::XSpellChecker1> xSpeller(getImpEditEngine().GetSpeller()); bool bIsWrong = xSpeller.is() && IsWrongSpelledWord(aPaM, /*bMarkIfWrong*/ false); + EditView* pActiveView = GetEditViewPtr(); boost::property_tree::ptree aHyperlinkTree; - if (const SvxFieldItem* pFld = GetField(aPos, nullptr, nullptr)) + if (pActiveView && URLFieldHelper::IsCursorAtURLField(*pActiveView)) { - if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) - { - aHyperlinkTree = getHyperlinkPropTree(pUrlField->GetRepresentation(), pUrlField->GetURL()); - } + if (const SvxFieldItem* pFld = GetField(aPos, nullptr, nullptr)) + if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) + aHyperlinkTree = getHyperlinkPropTree(pUrlField->GetRepresentation(), pUrlField->GetURL()); } else if (GetEditSelection().HasRange()) { - EditView* pActiveView = GetEditViewPtr(); - if (pActiveView) { const SvxFieldItem* pFieldItem = pActiveView->GetFieldAtSelection(); @@ -1426,14 +1451,14 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, aMessageParams); else pThisShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, - aMessageParams.get<std::string>("rectangle").c_str()); + OString(aMessageParams.get<std::string>("rectangle"))); } } CursorDirection nCursorDir = CursorDirection::NONE; - if ( IsInsertMode() && !aEditSelection.HasRange() && ( pEditEngine->pImpEditEngine->HasDifferentRTLLevels( aPaM.GetNode() ) ) ) + if ( IsInsertMode() && !maEditSelection.HasRange() && (getImpEditEngine().HasDifferentRTLLevels(aPaM.GetNode()) ) ) { - sal_uInt16 nTextPortion = rParaPortion.GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, bool(nShowCursorFlags & GetCursorFlags::PreferPortionStart) ); + sal_uInt16 nTextPortion = rParaPortion.GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, aShowCursorFlags.bPreferPortionStart); const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[nTextPortion]; if (rTextPortion.IsRightToLeft()) nCursorDir = CursorDirection::RTL; @@ -1447,9 +1472,9 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) GetCursor()->Show(); { SvxFont aFont; - pEditEngine->SeekCursor( aPaM.GetNode(), aPaM.GetIndex()+1, aFont ); + getEditEngine().SeekCursor( aPaM.GetNode(), aPaM.GetIndex()+1, aFont ); - InputContext aInputContext(aFont, InputContextFlags::Text | InputContextFlags::ExtText); + InputContext aInputContext(std::move(aFont), InputContextFlags::Text | InputContextFlags::ExtText); if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) pCallbacks->EditViewInputContext(aInputContext); else if (auto xWindow = GetWindow()) @@ -1458,7 +1483,7 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) } else { - pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() = pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() | EditStatusFlags::CURSOROUT; + getImpEditEngine().GetStatus().GetStatusWord() = getImpEditEngine().GetStatus().GetStatusWord() | EditStatusFlags::CURSOROUT; GetCursor()->Hide(); GetCursor()->SetPos( Point( -1, -1 ) ); GetCursor()->SetSize( Size( 0, 0 ) ); @@ -1476,17 +1501,17 @@ void ImpEditView::ScrollStateChange() Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRangeCheck ) { - DBG_ASSERT( pEditEngine->pImpEditEngine->IsFormatted(), "Scroll: Not formatted!" ); + DBG_ASSERT(getImpEditEngine().IsFormatted(), "Scroll: Not formatted!"); if ( !ndX && !ndY ) return Pair( 0, 0 ); const OutputDevice& rOutDev = GetOutputDevice(); #ifdef DBG_UTIL - tools::Rectangle aR( aOutArea ); + tools::Rectangle aR(maOutputArea); aR = rOutDev.LogicToPixel( aR ); aR = rOutDev.PixelToLogic( aR ); - SAL_WARN_IF( aR != aOutArea, "editeng", "OutArea before Scroll not aligned" ); + SAL_WARN_IF(aR != maOutputArea, "editeng", "OutArea before Scroll not aligned"); #endif tools::Rectangle aNewVisArea( GetVisDocArea() ); @@ -1510,10 +1535,10 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa aNewVisArea.AdjustBottom( -ndX ); } } - if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Bottom() > static_cast<tools::Long>(pEditEngine->pImpEditEngine->GetTextHeight()) ) ) + if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Bottom() > static_cast<tools::Long>(getImpEditEngine().GetTextHeight()) ) ) { // GetTextHeight still optimizing! - tools::Long nDiff = pEditEngine->pImpEditEngine->GetTextHeight() - aNewVisArea.Bottom(); // negative + tools::Long nDiff = getImpEditEngine().GetTextHeight() - aNewVisArea.Bottom(); // negative aNewVisArea.Move( 0, nDiff ); // could end up in the negative area... } if ( aNewVisArea.Top() < 0 ) @@ -1538,9 +1563,9 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa aNewVisArea.AdjustRight(ndY ); } } - if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Right() > static_cast<tools::Long>(pEditEngine->pImpEditEngine->CalcTextWidth( false )) ) ) + if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Right() > static_cast<tools::Long>(getImpEditEngine().CalcTextWidth( false )) ) ) { - tools::Long nDiff = pEditEngine->pImpEditEngine->CalcTextWidth( false ) - aNewVisArea.Right(); // negative + tools::Long nDiff = getImpEditEngine().CalcTextWidth( false ) - aNewVisArea.Right(); // negative aNewVisArea.Move( nDiff, 0 ); // could end up in the negative area... } if ( aNewVisArea.Left() < 0 ) @@ -1563,48 +1588,48 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa vcl::Cursor* pCrsr = GetCursor(); bool bVisCursor = pCrsr->IsVisible(); pCrsr->Hide(); - if (pOutWin) - pOutWin->PaintImmediately(); - if ( !IsVertical() ) - aVisDocStartPos.Move( -nRealDiffX, -nRealDiffY ); + if (mpOutputWindow) + mpOutputWindow->PaintImmediately(); + if (!IsVertical()) + maVisDocStartPos.Move(-nRealDiffX, -nRealDiffY); else { if (IsTopToBottom()) - aVisDocStartPos.Move(-nRealDiffY, nRealDiffX); + maVisDocStartPos.Move(-nRealDiffY, nRealDiffX); else - aVisDocStartPos.Move(nRealDiffY, -nRealDiffX); + maVisDocStartPos.Move(nRealDiffY, -nRealDiffX); } // Move by aligned value does not necessarily result in aligned // rectangle ... - aVisDocStartPos = rOutDev.LogicToPixel( aVisDocStartPos ); - aVisDocStartPos = rOutDev.PixelToLogic( aVisDocStartPos ); - tools::Rectangle aRect( aOutArea ); + maVisDocStartPos = rOutDev.LogicToPixel(maVisDocStartPos); + maVisDocStartPos = rOutDev.PixelToLogic(maVisDocStartPos); + tools::Rectangle aRect(maOutputArea); - if (pOutWin) + if (mpOutputWindow) { - pOutWin->Scroll( nRealDiffX, nRealDiffY, aRect, ScrollFlags::Clip ); + mpOutputWindow->Scroll( nRealDiffX, nRealDiffY, aRect, ScrollFlags::Clip ); } if (comphelper::LibreOfficeKit::isActive() || getEditViewCallbacks()) { // Need to invalidate the window, otherwise no tile will be re-painted. - pEditView->Invalidate(); + GetEditViewPtr()->Invalidate(); } - if (pOutWin) - pOutWin->PaintImmediately(); + if (mpOutputWindow) + mpOutputWindow->PaintImmediately(); pCrsr->SetPos( pCrsr->GetPos() + Point( nRealDiffX, nRealDiffY ) ); if ( bVisCursor ) { tools::Rectangle aCursorRect( pCrsr->GetPos(), pCrsr->GetSize() ); - if ( aOutArea.IsInside( aCursorRect ) ) + if (maOutputArea.Contains(aCursorRect)) pCrsr->Show(); } - if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() ) + if (getImpEditEngine().GetNotifyHdl().IsSet()) { EENotify aNotify( EE_NOTIFY_TEXTVIEWSCROLLED ); - pEditEngine->pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpEditEngine().GetNotifyHdl().Call( aNotify ); } if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) @@ -1619,7 +1644,7 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa return Pair( nRealDiffX, nRealDiffY ); } -Reference<css::datatransfer::clipboard::XClipboard> ImpEditView::GetClipboard() const +uno::Reference<datatransfer::clipboard::XClipboard> ImpEditView::GetClipboard() const { if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) return pCallbacks->GetClipboard(); @@ -1640,9 +1665,9 @@ bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * p { case KeyFuncType::CUT: { - if ( !bReadOnly ) + if (!mbReadOnly) { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); CutCopy( aClipBoard, true ); bDone = true; } @@ -1650,19 +1675,19 @@ bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * p break; case KeyFuncType::COPY: { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); CutCopy( aClipBoard, false ); bDone = true; } break; case KeyFuncType::PASTE: { - if ( !bReadOnly && IsPasteEnabled() ) + if (!mbReadOnly && IsPasteEnabled()) { - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE ); - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - Paste( aClipBoard, pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() ); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionStart( EDITUNDO_PASTE ); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); + Paste( aClipBoard, getImpEditEngine().GetStatus().AllowPasteSpecial() ); + getImpEditEngine().UndoActionEnd(); bDone = true; } } @@ -1673,57 +1698,60 @@ bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * p } if( !bDone ) - bDone = pEditEngine->PostKeyEvent( rKeyEvent, GetEditViewPtr(), pFrameWin ); + bDone = getEditEngine().PostKeyEvent( rKeyEvent, GetEditViewPtr(), pFrameWin ); return bDone; } bool ImpEditView::MouseButtonUp( const MouseEvent& rMouseEvent ) { - nTravelXPos = TRAVEL_X_DONTKNOW; - nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; - nExtraCursorFlags = GetCursorFlags::NONE; - bClickedInSelection = false; + mnTravelXPos = TRAVEL_X_DONTKNOW; + mnCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; + maExtraCursorFlags = CursorFlags(); + mbClickedInSelection = false; - if ( rMouseEvent.IsMiddle() && !bReadOnly && + if ( rMouseEvent.IsMiddle() && !mbReadOnly && Application::GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection ) { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); Paste( aClipBoard ); } else if ( rMouseEvent.IsLeft() && GetEditSelection().HasRange() ) { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); CutCopy( aClipBoard, false ); } - return pEditEngine->pImpEditEngine->MouseButtonUp( rMouseEvent, GetEditViewPtr() ); + return getImpEditEngine().MouseButtonUp( rMouseEvent, GetEditViewPtr() ); } void ImpEditView::ReleaseMouse() { - pEditEngine->pImpEditEngine->ReleaseMouse(); + getImpEditEngine().ReleaseMouse(); } bool ImpEditView::MouseButtonDown( const MouseEvent& rMouseEvent ) { - pEditEngine->CheckIdleFormatter(); // If fast typing and mouse button downs - nTravelXPos = TRAVEL_X_DONTKNOW; - nExtraCursorFlags = GetCursorFlags::NONE; - nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; - bClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); - return pEditEngine->pImpEditEngine->MouseButtonDown( rMouseEvent, GetEditViewPtr() ); + getEditEngine().CheckIdleFormatter(); // If fast typing and mouse button downs + mnTravelXPos = TRAVEL_X_DONTKNOW; + maExtraCursorFlags = CursorFlags(); + mnCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; + bool bPrevUpdateLayout = getImpEditEngine().SetUpdateLayout(true); + mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); + bool bRet = getImpEditEngine().MouseButtonDown( rMouseEvent, GetEditViewPtr() ); + getImpEditEngine().SetUpdateLayout(bPrevUpdateLayout); + return bRet; } bool ImpEditView::MouseMove( const MouseEvent& rMouseEvent ) { - return pEditEngine->pImpEditEngine->MouseMove( rMouseEvent, GetEditViewPtr() ); + return getImpEditEngine().MouseMove( rMouseEvent, GetEditViewPtr() ); } bool ImpEditView::Command(const CommandEvent& rCEvt) { - pEditEngine->CheckIdleFormatter(); // If fast typing and mouse button down - return pEditEngine->pImpEditEngine->Command(rCEvt, GetEditViewPtr()); + getEditEngine().CheckIdleFormatter(); // If fast typing and mouse button down + return getImpEditEngine().Command(rCEvt, GetEditViewPtr()); } @@ -1731,7 +1759,7 @@ void ImpEditView::SetInsertMode( bool bInsert ) { if ( bInsert != IsInsertMode() ) { - SetFlags( nControl, EVControlBits::OVERWRITE, !bInsert ); + SetFlags(mnControl, EVControlBits::OVERWRITE, !bInsert); ShowCursor( DoAutoScroll(), false ); } } @@ -1741,7 +1769,7 @@ bool ImpEditView::IsWrongSpelledWord( const EditPaM& rPaM, bool bMarkIfWrong ) bool bIsWrong = false; if ( rPaM.GetNode()->GetWrongList() ) { - EditSelection aSel = pEditEngine->SelectWord( rPaM, css::i18n::WordType::DICTIONARY_WORD ); + EditSelection aSel = getEditEngine().SelectWord( rPaM, css::i18n::WordType::DICTIONARY_WORD ); bIsWrong = rPaM.GetNode()->GetWrongList()->HasWrong( aSel.Min().GetIndex(), aSel.Max().GetIndex() ); if ( bIsWrong && bMarkIfWrong ) { @@ -1756,17 +1784,17 @@ bool ImpEditView::IsWrongSpelledWord( const EditPaM& rPaM, bool bMarkIfWrong ) OUString ImpEditView::SpellIgnoreWord() { OUString aWord; - if ( pEditEngine->pImpEditEngine->GetSpeller().is() ) + if (getImpEditEngine().GetSpeller().is()) { EditPaM aPaM = GetEditSelection().Max(); if ( !HasSelection() ) { - EditSelection aSel = pEditEngine->SelectWord(aPaM); - aWord = pEditEngine->pImpEditEngine->GetSelected( aSel ); + EditSelection aSel = getEditEngine().SelectWord(aPaM); + aWord = getImpEditEngine().GetSelected( aSel ); } else { - aWord = pEditEngine->pImpEditEngine->GetSelected( GetEditSelection() ); + aWord = getImpEditEngine().GetSelected( GetEditSelection() ); // And deselect DrawSelectionXOR(); SetEditSelection( EditSelection( aPaM, aPaM ) ); @@ -1775,18 +1803,18 @@ OUString ImpEditView::SpellIgnoreWord() if ( !aWord.isEmpty() ) { - Reference< XDictionary > xDic = LinguMgr::GetIgnoreAllList(); + uno::Reference<linguistic2::XDictionary> xDic = LinguMgr::GetIgnoreAllList(); if (xDic.is()) xDic->add( aWord, false, OUString() ); - EditDoc& rDoc = pEditEngine->GetEditDoc(); + EditDoc& rDoc = getEditEngine().GetEditDoc(); sal_Int32 nNodes = rDoc.Count(); for ( sal_Int32 n = 0; n < nNodes; n++ ) { ContentNode* pNode = rDoc.GetObject( n ); pNode->GetWrongList()->MarkWrongsInvalid(); } - pEditEngine->pImpEditEngine->DoOnlineSpelling( aPaM.GetNode() ); - pEditEngine->pImpEditEngine->StartOnlineSpellTimer(); + getImpEditEngine().DoOnlineSpelling( aPaM.GetNode() ); + getImpEditEngine().StartOnlineSpellTimer(); } } return aWord; @@ -1796,27 +1824,27 @@ void ImpEditView::DeleteSelected() { DrawSelectionXOR(); - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DELETE ); + getImpEditEngine().UndoActionStart( EDITUNDO_DELETE ); - EditPaM aPaM = pEditEngine->pImpEditEngine->DeleteSelected( GetEditSelection() ); + EditPaM aPaM = getImpEditEngine().DeleteSelected( GetEditSelection() ); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionEnd(); SetEditSelection( EditSelection( aPaM, aPaM ) ); DrawSelectionXOR(); - pEditEngine->pImpEditEngine->FormatAndUpdate( GetEditViewPtr() ); + getImpEditEngine().FormatAndLayout( GetEditViewPtr() ); ShowCursor( DoAutoScroll(), true ); } const SvxFieldItem* ImpEditView::GetField( const Point& rPos, sal_Int32* pPara, sal_Int32* pPos ) const { - if( !GetOutputArea().IsInside( rPos ) ) + if( !GetOutputArea().Contains( rPos ) ) return nullptr; Point aDocPos( GetDocPos( rPos ) ); - EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos, false); if (!aPaM) return nullptr; @@ -1837,7 +1865,7 @@ const SvxFieldItem* ImpEditView::GetField( const Point& rPos, sal_Int32* pPara, { DBG_ASSERT(dynamic_cast<const SvxFieldItem*>(rAttr.GetItem()), "No FieldItem..."); if ( pPara ) - *pPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); + *pPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); if ( pPos ) *pPos = rAttr.GetStart(); return static_cast<const SvxFieldItem*>(rAttr.GetItem()); @@ -1852,20 +1880,20 @@ bool ImpEditView::IsBulletArea( const Point& rPos, sal_Int32* pPara ) if ( pPara ) *pPara = EE_PARA_NOT_FOUND; - if( !GetOutputArea().IsInside( rPos ) ) + if( !GetOutputArea().Contains( rPos ) ) return false; Point aDocPos( GetDocPos( rPos ) ); - EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos, false); if (!aPaM) return false; if ( aPaM.GetIndex() == 0 ) { - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - tools::Rectangle aBulletArea = pEditEngine->GetBulletArea( nPara ); - tools::Long nY = pEditEngine->GetDocPosTopLeft( nPara ).Y(); - const ParaPortion& rParaPortion = pEditEngine->GetParaPortions()[nPara]; + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + tools::Rectangle aBulletArea = getEditEngine().GetBulletArea( nPara ); + tools::Long nY = getEditEngine().GetDocPosTopLeft( nPara ).Y(); + ParaPortion const& rParaPortion = getEditEngine().GetParaPortions().getRef(nPara); nY += rParaPortion.GetFirstLineOffset(); if ( ( aDocPos.Y() > ( nY + aBulletArea.Top() ) ) && ( aDocPos.Y() < ( nY + aBulletArea.Bottom() ) ) && @@ -1881,12 +1909,12 @@ bool ImpEditView::IsBulletArea( const Point& rPos, sal_Int32* pPara ) return false; } -void ImpEditView::CutCopy( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bCut ) +void ImpEditView::CutCopy(uno::Reference<datatransfer::clipboard::XClipboard> const & rxClipboard, bool bCut ) { if ( !(rxClipboard.is() && HasSelection()) ) return; - uno::Reference<datatransfer::XTransferable> xData = pEditEngine->CreateTransferable( GetEditSelection() ); + uno::Reference<datatransfer::XTransferable> xData = getEditEngine().CreateTransferable( GetEditSelection() ); { SolarMutexReleaser aReleaser; @@ -1908,18 +1936,18 @@ void ImpEditView::CutCopy( css::uno::Reference< css::datatransfer::clipboard::XC if (bCut) { - pEditEngine->pImpEditEngine->UndoActionStart(EDITUNDO_CUT); + getImpEditEngine().UndoActionStart(EDITUNDO_CUT); DeleteSelected(); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionEnd(); } } -void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bUseSpecial ) +void ImpEditView::Paste(uno::Reference<datatransfer::clipboard::XClipboard> const & rxClipboard, bool bUseSpecial, SotClipboardFormatId format) { if ( !rxClipboard.is() ) return; - uno::Reference< datatransfer::XTransferable > xDataObj; + uno::Reference<datatransfer::XTransferable> xDataObj; try { @@ -1933,18 +1961,18 @@ void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XCli if ( !xDataObj.is() || !EditEngine::HasValidData( xDataObj ) ) return; - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE ); + getImpEditEngine().UndoActionStart( EDITUNDO_PASTE ); EditSelection aSel( GetEditSelection() ); if ( aSel.HasRange() ) { DrawSelectionXOR(); - aSel = pEditEngine->DeleteSelection(aSel); + aSel = getEditEngine().DeleteSelection(aSel); } PasteOrDropInfos aPasteOrDropInfos; - aPasteOrDropInfos.nStartPara = pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() ); - pEditEngine->HandleBeginPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nStartPara = getEditEngine().GetEditDoc().GetPos( aSel.Min().GetNode() ); + getEditEngine().HandleBeginPasteOrDrop(aPasteOrDropInfos); if ( DoSingleLinePaste() ) { @@ -1959,7 +1987,7 @@ void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XCli aData >>= aTmpText; OUString aText(convertLineEnd(aTmpText, LINEEND_LF)); aText = aText.replaceAll( OUStringChar(LINE_SEP), " " ); - aSel = pEditEngine->InsertText(aSel, aText); + aSel = getEditEngine().InsertText(aSel, aText); } catch( ... ) { @@ -1972,18 +2000,18 @@ void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XCli // Prevent notifications of paragraph inserts et al that would trigger // a11y to format content in a half-ready state when obtaining // paragraphs. Collect and broadcast when done instead. - aSel = pEditEngine->InsertText( + aSel = getEditEngine().InsertText( xDataObj, OUString(), aSel.Min(), - bUseSpecial && pEditEngine->GetInternalEditStatus().AllowPasteSpecial()); + bUseSpecial && getEditEngine().GetInternalEditStatus().AllowPasteSpecial(), format); } - aPasteOrDropInfos.nEndPara = pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() ); - pEditEngine->HandleEndPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nEndPara = getEditEngine().GetEditDoc().GetPos( aSel.Max().GetNode() ); + getEditEngine().HandleEndPasteOrDrop(aPasteOrDropInfos); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionEnd(); SetEditSelection( aSel ); - pEditEngine->pImpEditEngine->UpdateSelections(); - pEditEngine->pImpEditEngine->FormatAndUpdate( GetEditViewPtr() ); + getImpEditEngine().UpdateSelections(); + getImpEditEngine().FormatAndLayout( GetEditViewPtr() ); ShowCursor( DoAutoScroll(), true ); } @@ -1994,11 +2022,11 @@ bool ImpEditView::IsInSelection( const EditPaM& rPaM ) if ( !aSel.HasRange() ) return false; - aSel.Adjust( pEditEngine->GetEditDoc() ); + aSel.Adjust(getEditEngine().GetEditDoc()); - sal_Int32 nStartNode = pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() ); - sal_Int32 nCurNode = pEditEngine->GetEditDoc().GetPos( rPaM.GetNode() ); + sal_Int32 nStartNode = getEditEngine().GetEditDoc().GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = getEditEngine().GetEditDoc().GetPos( aSel.Max().GetNode() ); + sal_Int32 nCurNode = getEditEngine().GetEditDoc().GetPos( rPaM.GetNode() ); if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) ) return true; @@ -2017,9 +2045,32 @@ bool ImpEditView::IsInSelection( const EditPaM& rPaM ) return false; } +bool ImpEditView::IsSelectionFullPara() const +{ + if (!IsSelectionInSinglePara()) + return false; + + sal_Int32 nSelectionStartPos = GetEditSelection().Min().GetIndex(); + sal_Int32 nSelectionEndPos = GetEditSelection().Max().GetIndex(); + + if (nSelectionStartPos > nSelectionEndPos) + std::swap(nSelectionStartPos, nSelectionEndPos); + + if (nSelectionStartPos != 0) + return false; + + const ContentNode* pNode = GetEditSelection().Min().GetNode(); + return pNode->Len() == nSelectionEndPos; +} + +bool ImpEditView::IsSelectionInSinglePara() const +{ + return GetEditSelection().Min().GetNode() == GetEditSelection().Max().GetNode(); +} + void ImpEditView::CreateAnchor() { - pEditEngine->SetInSelectionMode(true); + getEditEngine().SetInSelectionMode(true); EditSelection aNewSelection(GetEditSelection()); aNewSelection.Min() = aNewSelection.Max(); SetEditSelection(aNewSelection); @@ -2028,16 +2079,16 @@ void ImpEditView::CreateAnchor() void ImpEditView::DeselectAll() { - pEditEngine->SetInSelectionMode(false); + getEditEngine().SetInSelectionMode(false); DrawSelectionXOR(); EditSelection aNewSelection(GetEditSelection()); aNewSelection.Min() = aNewSelection.Max(); SetEditSelection(aNewSelection); // const_cast<EditPaM&>(GetEditSelection().Min()) = GetEditSelection().Max(); - if (comphelper::LibreOfficeKit::isActive() && mpViewShell) + if (comphelper::LibreOfficeKit::isActive() && mpViewShell && mpOutputWindow) { - VclPtr<vcl::Window> pParent = pOutWin->GetParentWithLOKNotifier(); + VclPtr<vcl::Window> pParent = mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId()) { const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier(); @@ -2050,26 +2101,26 @@ void ImpEditView::DeselectAll() bool ImpEditView::IsSelectionAtPoint( const Point& rPosPixel ) { - if ( pDragAndDropInfo && pDragAndDropInfo->pField ) + if (mpDragAndDropInfo && mpDragAndDropInfo->pField) return true; // Logical units ... const OutputDevice& rOutDev = GetOutputDevice(); Point aMousePos = rOutDev.PixelToLogic(rPosPixel); - if ( ( !GetOutputArea().IsInside( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() ) + if ( ( !GetOutputArea().Contains( aMousePos ) ) && !getImpEditEngine().IsInSelectionMode() ) { return false; } Point aDocPos( GetDocPos( aMousePos ) ); - EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos, false); return IsInSelection( aPaM ); } bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) { - pEditEngine->CheckIdleFormatter(); + getEditEngine().CheckIdleFormatter(); Point aMousePos( rPointPixel ); @@ -2077,7 +2128,7 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) const OutputDevice& rOutDev = GetOutputDevice(); aMousePos = rOutDev.PixelToLogic( aMousePos ); - if ( ( !GetOutputArea().IsInside( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() ) + if ( ( !GetOutputArea().Contains( aMousePos ) ) && !getImpEditEngine().IsInSelectionMode() ) { return false; } @@ -2087,7 +2138,7 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) // Can be optimized: first go through the lines within a paragraph for PAM, // then again with the PaM for the Rect, even though the line is already // known... This must not be, though! - EditPaM aPaM = pEditEngine->GetPaM(aDocPos); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos); bool bGotoCursor = DoAutoScroll(); // aTmpNewSel: Diff between old and new, not the new selection, unless for tiled rendering @@ -2098,10 +2149,14 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) EditSelection aNewEditSelection( GetEditSelection() ); aNewEditSelection.Max() = aPaM; - if (!pEditEngine->GetSelectionEngine().HasAnchor()) + if (!getEditEngine().GetSelectionEngine().HasAnchor()) { if ( aNewEditSelection.Min() != aPaM ) - pEditEngine->CursorMoved(aNewEditSelection.Min().GetNode()); + { + const ContentNode* pNode(aNewEditSelection.Min().GetNode()); + if (nullptr != pNode) + pNode->checkAndDeleteEmptyAttribs(); + } aNewEditSelection.Min() = aPaM; } else @@ -2115,29 +2170,29 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) SetEditSelection( aNewEditSelection ); } - bool bForceCursor = pDragAndDropInfo == nullptr && !pEditEngine->pImpEditEngine->IsInSelectionMode(); + bool bForceCursor = mpDragAndDropInfo == nullptr && !getImpEditEngine().IsInSelectionMode(); ShowCursor( bGotoCursor, bForceCursor ); return true; } void ImpEditView::HideDDCursor() { - if ( pDragAndDropInfo && pDragAndDropInfo->bVisCursor ) + if (mpDragAndDropInfo && mpDragAndDropInfo->bVisCursor) { OutputDevice& rOutDev = GetOutputDevice(); - rOutDev.DrawOutDev( pDragAndDropInfo->aCurSavedCursor.TopLeft(), pDragAndDropInfo->aCurSavedCursor.GetSize(), - Point(0,0), pDragAndDropInfo->aCurSavedCursor.GetSize(),*pDragAndDropInfo->pBackground ); - pDragAndDropInfo->bVisCursor = false; + rOutDev.DrawOutDev(mpDragAndDropInfo->aCurSavedCursor.TopLeft(), mpDragAndDropInfo->aCurSavedCursor.GetSize(), + Point(0,0), mpDragAndDropInfo->aCurSavedCursor.GetSize(),*mpDragAndDropInfo->pBackground); + mpDragAndDropInfo->bVisCursor = false; } } void ImpEditView::ShowDDCursor( const tools::Rectangle& rRect ) { - if ( !pDragAndDropInfo || pDragAndDropInfo->bVisCursor ) + if (!mpDragAndDropInfo || mpDragAndDropInfo->bVisCursor) return; - if (pOutWin && pOutWin->GetCursor()) - pOutWin->GetCursor()->Hide(); + if (mpOutputWindow && mpOutputWindow->GetCursor()) + mpOutputWindow->GetCursor()->Hide(); OutputDevice& rOutDev = GetOutputDevice(); Color aOldFillColor = rOutDev.GetFillColor(); @@ -2149,58 +2204,54 @@ void ImpEditView::ShowDDCursor( const tools::Rectangle& rRect ) aSaveRect.AdjustRight(1 ); aSaveRect.AdjustBottom(1 ); -#ifdef DBG_UTIL - Size aNewSzPx( aSaveRect.GetSize() ); -#endif - if ( !pDragAndDropInfo->pBackground ) + if (!mpDragAndDropInfo->pBackground) { - pDragAndDropInfo->pBackground = VclPtr<VirtualDevice>::Create(rOutDev); + mpDragAndDropInfo->pBackground = VclPtr<VirtualDevice>::Create(rOutDev); MapMode aMapMode( rOutDev.GetMapMode() ); aMapMode.SetOrigin( Point( 0, 0 ) ); - pDragAndDropInfo->pBackground->SetMapMode( aMapMode ); + mpDragAndDropInfo->pBackground->SetMapMode( aMapMode ); } -#ifdef DBG_UTIL - Size aCurSzPx( pDragAndDropInfo->pBackground->GetOutputSizePixel() ); + Size aNewSzPx( aSaveRect.GetSize() ); + Size aCurSzPx(mpDragAndDropInfo->pBackground->GetOutputSizePixel()); if ( ( aCurSzPx.Width() < aNewSzPx.Width() ) ||( aCurSzPx.Height() < aNewSzPx.Height() ) ) { - bool bDone = pDragAndDropInfo->pBackground->SetOutputSizePixel( aNewSzPx ); + bool bDone = mpDragAndDropInfo->pBackground->SetOutputSizePixel( aNewSzPx ); DBG_ASSERT( bDone, "Virtual Device broken?" ); } -#endif aSaveRect = rOutDev.PixelToLogic( aSaveRect ); - pDragAndDropInfo->pBackground->DrawOutDev( Point(0,0), aSaveRect.GetSize(), + mpDragAndDropInfo->pBackground->DrawOutDev( Point(0,0), aSaveRect.GetSize(), aSaveRect.TopLeft(), aSaveRect.GetSize(), rOutDev ); - pDragAndDropInfo->aCurSavedCursor = aSaveRect; + mpDragAndDropInfo->aCurSavedCursor = aSaveRect; // Draw Cursor... rOutDev.DrawRect( rRect ); - pDragAndDropInfo->bVisCursor = true; - pDragAndDropInfo->aCurCursor = rRect; + mpDragAndDropInfo->bVisCursor = true; + mpDragAndDropInfo->aCurCursor = rRect; rOutDev.SetFillColor( aOldFillColor ); } void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestureEvent& rDGE) { - DBG_ASSERT( !pDragAndDropInfo, "dragGestureRecognized - DragAndDropInfo exist!" ); + DBG_ASSERT(!mpDragAndDropInfo, "dragGestureRecognized - DragAndDropInfo exist!"); SolarMutexGuard aVclGuard; - pDragAndDropInfo.reset(); + mpDragAndDropInfo.reset(); Point aMousePosPixel( rDGE.DragOriginX, rDGE.DragOriginY ); EditSelection aCopySel( GetEditSelection() ); - aCopySel.Adjust( pEditEngine->GetEditDoc() ); + aCopySel.Adjust(getEditEngine().GetEditDoc()); - if ( HasSelection() && bClickedInSelection ) + if (HasSelection() && mbClickedInSelection) { - pDragAndDropInfo.reset(new DragAndDropInfo()); + mpDragAndDropInfo.reset(new DragAndDropInfo); } else { @@ -2211,9 +2262,9 @@ void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestur const SvxFieldItem* pField = GetField( aMousePos, &nPara, &nPos ); if ( pField ) { - pDragAndDropInfo.reset(new DragAndDropInfo()); - pDragAndDropInfo->pField = pField; - ContentNode* pNode = pEditEngine->GetEditDoc().GetObject( nPara ); + mpDragAndDropInfo.reset(new DragAndDropInfo); + mpDragAndDropInfo->pField = pField; + ContentNode* pNode = getEditEngine().GetEditDoc().GetObject( nPara ); aCopySel = EditSelection( EditPaM( pNode, nPos ), EditPaM( pNode, nPos+1 ) ); SetEditSelection(aCopySel); DrawSelectionXOR(); @@ -2222,17 +2273,17 @@ void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestur } else if ( IsBulletArea( aMousePos, &nPara ) ) { - pDragAndDropInfo.reset(new DragAndDropInfo()); - pDragAndDropInfo->bOutlinerMode = true; - EditPaM aStartPaM( pEditEngine->GetEditDoc().GetObject( nPara ), 0 ); + mpDragAndDropInfo.reset(new DragAndDropInfo); + mpDragAndDropInfo->bOutlinerMode = true; + EditPaM aStartPaM(getEditEngine().GetEditDoc().GetObject(nPara), 0); EditPaM aEndPaM( aStartPaM ); - const SfxInt16Item& rLevel = pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); - for ( sal_Int32 n = nPara +1; n < pEditEngine->GetEditDoc().Count(); n++ ) + const SfxInt16Item& rLevel = getEditEngine().GetParaAttrib(nPara, EE_PARA_OUTLLEVEL); + for ( sal_Int32 n = nPara +1; n < getEditEngine().GetEditDoc().Count(); n++ ) { - const SfxInt16Item& rL = pEditEngine->GetParaAttrib( n, EE_PARA_OUTLLEVEL ); + const SfxInt16Item& rL = getEditEngine().GetParaAttrib( n, EE_PARA_OUTLLEVEL ); if ( rL.GetValue() > rLevel.GetValue() ) { - aEndPaM.SetNode( pEditEngine->GetEditDoc().GetObject( n ) ); + aEndPaM.SetNode( getEditEngine().GetEditDoc().GetObject( n ) ); } else { @@ -2244,22 +2295,22 @@ void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestur } } - if ( !pDragAndDropInfo ) + if (!mpDragAndDropInfo) return; - pDragAndDropInfo->bStarterOfDD = true; + mpDragAndDropInfo->bStarterOfDD = true; // Sensitive area to be scrolled. Size aSz( 5, 0 ); aSz = GetOutputDevice().PixelToLogic( aSz ); - pDragAndDropInfo->nSensibleRange = static_cast<sal_uInt16>(aSz.Width()); - pDragAndDropInfo->nCursorWidth = static_cast<sal_uInt16>(aSz.Width()) / 2; - pDragAndDropInfo->aBeginDragSel = pEditEngine->pImpEditEngine->CreateESel( aCopySel ); + mpDragAndDropInfo->nSensibleRange = static_cast<sal_uInt16>(aSz.Width()); + mpDragAndDropInfo->nCursorWidth = static_cast<sal_uInt16>(aSz.Width()) / 2; + mpDragAndDropInfo->aBeginDragSel = getImpEditEngine().CreateESel( aCopySel ); - uno::Reference<datatransfer::XTransferable> xData = pEditEngine->CreateTransferable(aCopySel); + uno::Reference<datatransfer::XTransferable> xData = getEditEngine().CreateTransferable(aCopySel); - sal_Int8 nActions = bReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE; + sal_Int8 nActions = mbReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE; rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, xData, mxDnDListener ); // If Drag&Move in an Engine, then Copy&Del has to be optional! @@ -2270,37 +2321,37 @@ void ImpEditView::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent { SolarMutexGuard aVclGuard; - DBG_ASSERT( pDragAndDropInfo, "ImpEditView::dragDropEnd: pDragAndDropInfo is NULL!" ); + DBG_ASSERT(mpDragAndDropInfo, "ImpEditView::dragDropEnd: mpDragAndDropInfo is NULL!"); // #123688# Shouldn't happen, but seems to happen... - if ( !pDragAndDropInfo ) + if (!mpDragAndDropInfo) return; - if ( !bReadOnly && rDSDE.DropSuccess && !pDragAndDropInfo->bOutlinerMode && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) ) + if (!mbReadOnly && rDSDE.DropSuccess && !mpDragAndDropInfo->bOutlinerMode && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) ) { - if ( pDragAndDropInfo->bStarterOfDD && pDragAndDropInfo->bDroppedInMe ) + if (mpDragAndDropInfo->bStarterOfDD && mpDragAndDropInfo->bDroppedInMe ) { // DropPos: Where was it dropped, irrespective of length. - ESelection aDropPos( pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos, pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos ); - ESelection aToBeDelSel = pDragAndDropInfo->aBeginDragSel; - ESelection aNewSel( pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos, - pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos ); - bool bBeforeSelection = aDropPos < pDragAndDropInfo->aBeginDragSel; - sal_Int32 nParaDiff = pDragAndDropInfo->aBeginDragSel.nEndPara - pDragAndDropInfo->aBeginDragSel.nStartPara; + ESelection aDropPos(mpDragAndDropInfo->aDropSel.nStartPara, mpDragAndDropInfo->aDropSel.nStartPos, mpDragAndDropInfo->aDropSel.nStartPara, mpDragAndDropInfo->aDropSel.nStartPos ); + ESelection aToBeDelSel = mpDragAndDropInfo->aBeginDragSel; + ESelection aNewSel( mpDragAndDropInfo->aDropSel.nEndPara, mpDragAndDropInfo->aDropSel.nEndPos, + mpDragAndDropInfo->aDropSel.nEndPara, mpDragAndDropInfo->aDropSel.nEndPos ); + bool bBeforeSelection = aDropPos < mpDragAndDropInfo->aBeginDragSel; + sal_Int32 nParaDiff = mpDragAndDropInfo->aBeginDragSel.nEndPara - mpDragAndDropInfo->aBeginDragSel.nStartPara; if ( bBeforeSelection ) { // Adjust aToBeDelSel. - DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara >= pDragAndDropInfo->aDropSel.nStartPara, "But not before? "); + DBG_ASSERT(mpDragAndDropInfo->aBeginDragSel.nStartPara >= mpDragAndDropInfo->aDropSel.nStartPara, "But not before? "); aToBeDelSel.nStartPara = aToBeDelSel.nStartPara + nParaDiff; aToBeDelSel.nEndPara = aToBeDelSel.nEndPara + nParaDiff; // To correct the character? - if ( aToBeDelSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara ) + if ( aToBeDelSel.nStartPara == mpDragAndDropInfo->aDropSel.nEndPara ) { sal_uInt16 nMoreChars; - if ( pDragAndDropInfo->aDropSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara ) - nMoreChars = pDragAndDropInfo->aDropSel.nEndPos - pDragAndDropInfo->aDropSel.nStartPos; + if (mpDragAndDropInfo->aDropSel.nStartPara == mpDragAndDropInfo->aDropSel.nEndPara ) + nMoreChars = mpDragAndDropInfo->aDropSel.nEndPos - mpDragAndDropInfo->aDropSel.nStartPos; else - nMoreChars = pDragAndDropInfo->aDropSel.nEndPos; + nMoreChars = mpDragAndDropInfo->aDropSel.nEndPos; aToBeDelSel.nStartPos = aToBeDelSel.nStartPos + nMoreChars; if ( aToBeDelSel.nStartPara == aToBeDelSel.nEndPara ) @@ -2312,17 +2363,17 @@ void ImpEditView::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent { // aToBeDelSel is ok, but the selection of the View // has to be adapted, if it was deleted before! - DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara <= pDragAndDropInfo->aDropSel.nStartPara, "But not before? "); + DBG_ASSERT(mpDragAndDropInfo->aBeginDragSel.nStartPara <= mpDragAndDropInfo->aDropSel.nStartPara, "But not before? "); aNewSel.nStartPara = aNewSel.nStartPara - nParaDiff; aNewSel.nEndPara = aNewSel.nEndPara - nParaDiff; // To correct the character? - if ( pDragAndDropInfo->aBeginDragSel.nEndPara == pDragAndDropInfo->aDropSel.nStartPara ) + if (mpDragAndDropInfo->aBeginDragSel.nEndPara == mpDragAndDropInfo->aDropSel.nStartPara ) { sal_uInt16 nLessChars; - if ( pDragAndDropInfo->aBeginDragSel.nStartPara == pDragAndDropInfo->aBeginDragSel.nEndPara ) - nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos - pDragAndDropInfo->aBeginDragSel.nStartPos; + if (mpDragAndDropInfo->aBeginDragSel.nStartPara == mpDragAndDropInfo->aBeginDragSel.nEndPara ) + nLessChars = mpDragAndDropInfo->aBeginDragSel.nEndPos - mpDragAndDropInfo->aBeginDragSel.nStartPos; else - nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos; + nLessChars = mpDragAndDropInfo->aBeginDragSel.nEndPos; aNewSel.nStartPos = aNewSel.nStartPos - nLessChars; if ( aNewSel.nStartPara == aNewSel.nEndPara ) aNewSel.nEndPos = aNewSel.nEndPos - nLessChars; @@ -2330,89 +2381,89 @@ void ImpEditView::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent } DrawSelectionXOR(); - EditSelection aDelSel( pEditEngine->pImpEditEngine->CreateSel( aToBeDelSel ) ); - DBG_ASSERT( !aDelSel.DbgIsBuggy( pEditEngine->GetEditDoc() ), "ToBeDel is buggy!" ); - pEditEngine->DeleteSelection(aDelSel); + EditSelection aDelSel(getImpEditEngine().CreateSel(aToBeDelSel)); + DBG_ASSERT( !aDelSel.DbgIsBuggy(getEditEngine().GetEditDoc()), "ToBeDel is buggy!"); + getEditEngine().DeleteSelection(aDelSel); if ( !bBeforeSelection ) { - DBG_ASSERT( !pEditEngine->pImpEditEngine->CreateSel( aNewSel ).DbgIsBuggy(pEditEngine->GetEditDoc()), "Bad" ); - SetEditSelection( pEditEngine->pImpEditEngine->CreateSel( aNewSel ) ); + DBG_ASSERT(!getImpEditEngine().CreateSel(aNewSel).DbgIsBuggy(getEditEngine().GetEditDoc()), "Bad"); + SetEditSelection(getImpEditEngine().CreateSel(aNewSel)); } - pEditEngine->pImpEditEngine->FormatAndUpdate( pEditEngine->pImpEditEngine->GetActiveView() ); + getImpEditEngine().FormatAndLayout(getImpEditEngine().GetActiveView()); DrawSelectionXOR(); } else { // other EditEngine ... - if (pEditEngine->HasText()) // #88630# SC is removing the content when switching the task + if (getEditEngine().HasText()) // #88630# SC is removing the content when switching the task DeleteSelected(); } } - if ( pDragAndDropInfo->bUndoAction ) - pEditEngine->pImpEditEngine->UndoActionEnd(); + if (mpDragAndDropInfo->bUndoAction) + getImpEditEngine().UndoActionEnd(); HideDDCursor(); ShowCursor( DoAutoScroll(), true ); - pDragAndDropInfo.reset(); - pEditEngine->GetEndDropHdl().Call(GetEditViewPtr()); + mpDragAndDropInfo.reset(); + getEditEngine().GetEndDropHdl().Call(GetEditViewPtr()); } void ImpEditView::drop( const css::datatransfer::dnd::DropTargetDropEvent& rDTDE ) { SolarMutexGuard aVclGuard; - DBG_ASSERT( pDragAndDropInfo, "Drop - No Drag&Drop info?!" ); + DBG_ASSERT(mpDragAndDropInfo, "Drop - No Drag&Drop info?!"); - if ( !(pDragAndDropInfo && pDragAndDropInfo->bDragAccepted) ) + if (!(mpDragAndDropInfo && mpDragAndDropInfo->bDragAccepted)) return; - pEditEngine->GetBeginDropHdl().Call(GetEditViewPtr()); + getEditEngine().GetBeginDropHdl().Call(GetEditViewPtr()); bool bChanges = false; HideDDCursor(); - if ( pDragAndDropInfo->bStarterOfDD ) + if (mpDragAndDropInfo->bStarterOfDD) { - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DRAGANDDROP ); - pDragAndDropInfo->bUndoAction = true; + getImpEditEngine().UndoActionStart( EDITUNDO_DRAGANDDROP ); + mpDragAndDropInfo->bUndoAction = true; } - if ( pDragAndDropInfo->bOutlinerMode ) + if (mpDragAndDropInfo->bOutlinerMode) { bChanges = true; - GetEditViewPtr()->MoveParagraphs( Range( pDragAndDropInfo->aBeginDragSel.nStartPara, pDragAndDropInfo->aBeginDragSel.nEndPara ), pDragAndDropInfo->nOutlinerDropDest ); + GetEditViewPtr()->MoveParagraphs(Range(mpDragAndDropInfo->aBeginDragSel.nStartPara, mpDragAndDropInfo->aBeginDragSel.nEndPara ), mpDragAndDropInfo->nOutlinerDropDest); } else { - uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable; + uno::Reference<datatransfer::XTransferable> xDataObj = rDTDE.Transferable; if ( xDataObj.is() ) { bChanges = true; // remove Selection ... DrawSelectionXOR(); - EditPaM aPaM( pDragAndDropInfo->aDropDest ); + EditPaM aPaM(mpDragAndDropInfo->aDropDest); PasteOrDropInfos aPasteOrDropInfos; - aPasteOrDropInfos.nStartPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - pEditEngine->HandleBeginPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nStartPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + getEditEngine().HandleBeginPasteOrDrop(aPasteOrDropInfos); - EditSelection aNewSel = pEditEngine->InsertText( - xDataObj, OUString(), aPaM, pEditEngine->GetInternalEditStatus().AllowPasteSpecial()); + EditSelection aNewSel = getEditEngine().InsertText( + xDataObj, OUString(), aPaM, getEditEngine().GetInternalEditStatus().AllowPasteSpecial()); - aPasteOrDropInfos.nEndPara = pEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() ); - pEditEngine->HandleEndPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nEndPara = getEditEngine().GetEditDoc().GetPos( aNewSel.Max().GetNode() ); + getEditEngine().HandleEndPasteOrDrop(aPasteOrDropInfos); SetEditSelection( aNewSel ); - pEditEngine->pImpEditEngine->FormatAndUpdate( pEditEngine->pImpEditEngine->GetActiveView() ); - if ( pDragAndDropInfo->bStarterOfDD ) + getImpEditEngine().FormatAndLayout(getImpEditEngine().GetActiveView()); + if (mpDragAndDropInfo->bStarterOfDD) { // Only set if the same engine! - pDragAndDropInfo->aDropSel.nStartPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - pDragAndDropInfo->aDropSel.nStartPos = aPaM.GetIndex(); - pDragAndDropInfo->aDropSel.nEndPara = pEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() ); - pDragAndDropInfo->aDropSel.nEndPos = aNewSel.Max().GetIndex(); - pDragAndDropInfo->bDroppedInMe = true; + mpDragAndDropInfo->aDropSel.nStartPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + mpDragAndDropInfo->aDropSel.nStartPos = aPaM.GetIndex(); + mpDragAndDropInfo->aDropSel.nEndPara = getEditEngine().GetEditDoc().GetPos( aNewSel.Max().GetNode() ); + mpDragAndDropInfo->aDropSel.nEndPos = aNewSel.Max().GetIndex(); + mpDragAndDropInfo->bDroppedInMe = true; } } } @@ -2422,9 +2473,9 @@ void ImpEditView::drop( const css::datatransfer::dnd::DropTargetDropEvent& rDTDE rDTDE.Context->acceptDrop( rDTDE.DropAction ); } - if ( !pDragAndDropInfo->bStarterOfDD ) + if (!mpDragAndDropInfo->bStarterOfDD) { - pDragAndDropInfo.reset(); + mpDragAndDropInfo.reset(); } rDTDE.Context->dropComplete( bChanges ); @@ -2434,10 +2485,10 @@ void ImpEditView::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEv { SolarMutexGuard aVclGuard; - if ( !pDragAndDropInfo ) - pDragAndDropInfo.reset(new DragAndDropInfo()); + if (!mpDragAndDropInfo) + mpDragAndDropInfo.reset(new DragAndDropInfo); - pDragAndDropInfo->bHasValidData = false; + mpDragAndDropInfo->bHasValidData = false; // Check for supported format... // Only check for text, will also be there if bin or rtf @@ -2449,7 +2500,7 @@ void ImpEditView::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEv { if( TransferableDataHelper::IsEqual( pFlavors[n], aTextFlavor ) ) { - pDragAndDropInfo->bHasValidData = true; + mpDragAndDropInfo->bHasValidData = true; break; } } @@ -2463,9 +2514,9 @@ void ImpEditView::dragExit( const css::datatransfer::dnd::DropTargetEvent& ) HideDDCursor(); - if ( pDragAndDropInfo && !pDragAndDropInfo->bStarterOfDD ) + if (mpDragAndDropInfo && !mpDragAndDropInfo->bStarterOfDD) { - pDragAndDropInfo.reset(); + mpDragAndDropInfo.reset(); } } @@ -2480,9 +2531,9 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD bool bAccept = false; - if ( GetOutputArea().IsInside( aMousePos ) && !bReadOnly ) + if (GetOutputArea().Contains( aMousePos ) && !mbReadOnly) { - if ( pDragAndDropInfo && pDragAndDropInfo->bHasValidData ) + if (mpDragAndDropInfo && mpDragAndDropInfo->bHasValidData) { bAccept = true; @@ -2492,14 +2543,14 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD tools::Long nScrollX = 0; tools::Long nScrollY = 0; // Check if in the sensitive area - if ( ( (aMousePos.X()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Left() ) && ( ( aMousePos.X() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Left() ) ) + if ( ( (aMousePos.X() - mpDragAndDropInfo->nSensibleRange) < GetOutputArea().Left() ) && ( ( aMousePos.X() + mpDragAndDropInfo->nSensibleRange ) > GetOutputArea().Left() ) ) nScrollX = GetOutputArea().GetWidth() / SCRLRANGE; - else if ( ( (aMousePos.X()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Right() ) && ( ( aMousePos.X() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Right() ) ) + else if ( ( (aMousePos.X() + mpDragAndDropInfo->nSensibleRange) > GetOutputArea().Right() ) && ( ( aMousePos.X() - mpDragAndDropInfo->nSensibleRange ) < GetOutputArea().Right() ) ) nScrollX = -( GetOutputArea().GetWidth() / SCRLRANGE ); - if ( ( (aMousePos.Y()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Top() ) && ( ( aMousePos.Y() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Top() ) ) + if ( ( (aMousePos.Y() - mpDragAndDropInfo->nSensibleRange) < GetOutputArea().Top() ) && ( ( aMousePos.Y() + mpDragAndDropInfo->nSensibleRange ) > GetOutputArea().Top() ) ) nScrollY = GetOutputArea().GetHeight() / SCRLRANGE; - else if ( ( (aMousePos.Y()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Bottom() ) && ( ( aMousePos.Y() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Bottom() ) ) + else if ( ( (aMousePos.Y() + mpDragAndDropInfo->nSensibleRange) > GetOutputArea().Bottom() ) && ( ( aMousePos.Y() - mpDragAndDropInfo->nSensibleRange ) < GetOutputArea().Bottom() ) ) nScrollY = -( GetOutputArea().GetHeight() / SCRLRANGE ); if ( nScrollX || nScrollY ) @@ -2510,27 +2561,27 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD } Point aDocPos( GetDocPos( aMousePos ) ); - EditPaM aPaM = pEditEngine->GetPaM( aDocPos ); - pDragAndDropInfo->aDropDest = aPaM; - if ( pDragAndDropInfo->bOutlinerMode ) + EditPaM aPaM = getEditEngine().GetPaM( aDocPos ); + mpDragAndDropInfo->aDropDest = aPaM; + if (mpDragAndDropInfo->bOutlinerMode) { - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( nPara ); + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + ParaPortion* pPPortion = getEditEngine().GetParaPortions().SafeGetObject( nPara ); if (pPPortion) { - tools::Long nDestParaStartY = pEditEngine->GetParaPortions().GetYOffset( pPPortion ); + tools::Long nDestParaStartY = getEditEngine().GetParaPortions().GetYOffset( pPPortion ); tools::Long nRel = aDocPos.Y() - nDestParaStartY; if ( nRel < ( pPPortion->GetHeight() / 2 ) ) { - pDragAndDropInfo->nOutlinerDropDest = nPara; + mpDragAndDropInfo->nOutlinerDropDest = nPara; } else { - pDragAndDropInfo->nOutlinerDropDest = nPara+1; + mpDragAndDropInfo->nOutlinerDropDest = nPara+1; } - if( ( pDragAndDropInfo->nOutlinerDropDest >= pDragAndDropInfo->aBeginDragSel.nStartPara ) && - ( pDragAndDropInfo->nOutlinerDropDest <= (pDragAndDropInfo->aBeginDragSel.nEndPara+1) ) ) + if ((mpDragAndDropInfo->nOutlinerDropDest >= mpDragAndDropInfo->aBeginDragSel.nStartPara) && + (mpDragAndDropInfo->nOutlinerDropDest <= (mpDragAndDropInfo->aBeginDragSel.nEndPara + 1))) { bAccept = false; } @@ -2539,9 +2590,9 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD else if ( HasSelection() ) { // it must not be dropped into a selection - EPaM aP = pEditEngine->pImpEditEngine->CreateEPaM( aPaM ); + EPaM aP = getImpEditEngine().CreateEPaM( aPaM ); ESelection aDestSel( aP.nPara, aP.nIndex, aP.nPara, aP.nIndex); - ESelection aCurSel = pEditEngine->pImpEditEngine->CreateESel( GetEditSelection() ); + ESelection aCurSel = getImpEditEngine().CreateESel( GetEditSelection() ); aCurSel.Adjust(); if ( !(aDestSel < aCurSel) && !(aDestSel > aCurSel) ) { @@ -2551,25 +2602,25 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD if ( bAccept ) { tools::Rectangle aEditCursor; - if ( pDragAndDropInfo->bOutlinerMode ) + if (mpDragAndDropInfo->bOutlinerMode) { tools::Long nDDYPos(0); - if ( pDragAndDropInfo->nOutlinerDropDest < pEditEngine->GetEditDoc().Count() ) + if (mpDragAndDropInfo->nOutlinerDropDest < getEditEngine().GetEditDoc().Count()) { - ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( pDragAndDropInfo->nOutlinerDropDest ); + ParaPortion* pPPortion = getEditEngine().GetParaPortions().SafeGetObject(mpDragAndDropInfo->nOutlinerDropDest); if (pPPortion) - nDDYPos = pEditEngine->GetParaPortions().GetYOffset( pPPortion ); + nDDYPos = getEditEngine().GetParaPortions().GetYOffset( pPPortion ); } else { - nDDYPos = pEditEngine->pImpEditEngine->GetTextHeight(); + nDDYPos = getImpEditEngine().GetTextHeight(); } Point aStartPos( 0, nDDYPos ); aStartPos = GetWindowPos( aStartPos ); Point aEndPos( GetOutputArea().GetWidth(), nDDYPos ); aEndPos = GetWindowPos( aEndPos ); aEditCursor = rOutDev.LogicToPixel( tools::Rectangle( aStartPos, aEndPos ) ); - if ( !pEditEngine->IsVertical() ) + if (!getEditEngine().IsEffectivelyVertical()) { aEditCursor.AdjustTop( -1 ); aEditCursor.AdjustBottom( 1 ); @@ -2591,21 +2642,21 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD } else { - aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM ); + aEditCursor = getImpEditEngine().PaMtoEditCursor( aPaM ); Point aTopLeft( GetWindowPos( aEditCursor.TopLeft() ) ); aEditCursor.SetPos( aTopLeft ); - aEditCursor.SetRight( aEditCursor.Left() + pDragAndDropInfo->nCursorWidth ); + aEditCursor.SetRight(aEditCursor.Left() + mpDragAndDropInfo->nCursorWidth); aEditCursor = rOutDev.LogicToPixel( aEditCursor ); aEditCursor = rOutDev.PixelToLogic( aEditCursor ); } - bool bCursorChanged = !pDragAndDropInfo->bVisCursor || ( pDragAndDropInfo->aCurCursor != aEditCursor ); + bool bCursorChanged = !mpDragAndDropInfo->bVisCursor || (mpDragAndDropInfo->aCurCursor != aEditCursor); if ( bCursorChanged ) { HideDDCursor(); ShowDDCursor(aEditCursor ); } - pDragAndDropInfo->bDragAccepted = true; + mpDragAndDropInfo->bDragAccepted = true; rDTDE.Context->acceptDrag( rDTDE.DropAction ); } } @@ -2614,18 +2665,18 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD if ( !bAccept ) { HideDDCursor(); - if (pDragAndDropInfo) - pDragAndDropInfo->bDragAccepted = false; + if (mpDragAndDropInfo) + mpDragAndDropInfo->bDragAccepted = false; rDTDE.Context->rejectDrag(); } } void ImpEditView::AddDragAndDropListeners() { - if (bActiveDragAndDropListener) + if (mbActiveDragAndDropListener) return; - css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget; + uno::Reference<datatransfer::dnd::XDropTarget> xDropTarget; if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) xDropTarget = pCallbacks->GetDropTarget(); else if (auto xWindow = GetWindow()) @@ -2636,7 +2687,7 @@ void ImpEditView::AddDragAndDropListeners() mxDnDListener = new vcl::unohelper::DragAndDropWrapper(this); - css::uno::Reference<css::datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); + uno::Reference<datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); if (xDragGestureRecognizer.is()) { uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY); @@ -2648,32 +2699,32 @@ void ImpEditView::AddDragAndDropListeners() xDropTarget->setActive(true); xDropTarget->setDefaultActions(datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE); - bActiveDragAndDropListener = true; + mbActiveDragAndDropListener = true; } void ImpEditView::RemoveDragAndDropListeners() { - if (!bActiveDragAndDropListener) + if (!mbActiveDragAndDropListener) return; - css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget; + uno::Reference<datatransfer::dnd::XDropTarget> xDropTarget; if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) xDropTarget = pCallbacks->GetDropTarget(); else if (auto xWindow = GetWindow()) xDropTarget = xWindow->GetDropTarget(); - if (!xDropTarget.is()) - return; - - css::uno::Reference<css::datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); - if (xDragGestureRecognizer.is()) + if (xDropTarget.is()) { - uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY); - xDragGestureRecognizer->removeDragGestureListener(xDGL); - } + uno::Reference<datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); + if (xDragGestureRecognizer.is()) + { + uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY); + xDragGestureRecognizer->removeDragGestureListener(xDGL); + } - uno::Reference<datatransfer::dnd::XDropTargetListener> xDTL(mxDnDListener, uno::UNO_QUERY); - xDropTarget->removeDropTargetListener(xDTL); + uno::Reference<datatransfer::dnd::XDropTargetListener> xDTL(mxDnDListener, uno::UNO_QUERY); + xDropTarget->removeDropTargetListener(xDTL); + } if ( mxDnDListener.is() ) { @@ -2681,7 +2732,7 @@ void ImpEditView::RemoveDragAndDropListeners() mxDnDListener.clear(); } - bActiveDragAndDropListener = false; + mbActiveDragAndDropListener = false; } void ImpEditView::InitLOKSpecialPositioning(MapUnit eUnit, @@ -2723,4 +2774,10 @@ bool ImpEditView::HasLOKSpecialPositioning() const return bool(mpLOKSpecialPositioning); } +void ImpEditView::SetLOKSpecialFlags(LOKSpecialFlags eFlags) +{ + assert(mpLOKSpecialPositioning); + mpLOKSpecialPositioning->SetFlags(eFlags); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index 2c17b0882631..07f6af002358 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -58,6 +58,7 @@ #include <optional> #include <memory> #include <tuple> +#include <string_view> #include <vector> class EditView; @@ -69,7 +70,6 @@ class SvxLRSpaceItem; class TextRanger; class SvKeyValueIterator; class SvxForbiddenCharactersTable; -class SvtCTLOptions; namespace vcl { class Window; } class SvxNumberFormat; namespace com::sun::star::datatransfer::clipboard { @@ -90,63 +90,65 @@ namespace editeng { #define ATTRSPECIAL_WHOLEWORD 1 #define ATTRSPECIAL_EDGE 2 -enum class GetCursorFlags { - NONE = 0x0000, - TextOnly = 0x0001, - StartOfLine = 0x0002, - EndOfLine = 0x0004, - PreferPortionStart = 0x0008, +struct CursorFlags +{ + bool bTextOnly : 1 = false; + bool bStartOfLine : 1 = false; + bool bEndOfLine : 1 = false; + bool bPreferPortionStart : 1 = false; }; -namespace o3tl { - template<> struct typed_flags<GetCursorFlags> : is_typed_flags<GetCursorFlags, 0x0f> {}; -} - struct DragAndDropInfo { - tools::Rectangle aCurCursor; - tools::Rectangle aCurSavedCursor; - sal_uInt16 nSensibleRange; - sal_uInt16 nCursorWidth; - ESelection aBeginDragSel; - EditPaM aDropDest; - sal_Int32 nOutlinerDropDest; - ESelection aDropSel; - VclPtr<VirtualDevice> pBackground; - const SvxFieldItem* pField; - bool bVisCursor : 1; - bool bDroppedInMe : 1; - bool bStarterOfDD : 1; - bool bHasValidData : 1; - bool bUndoAction : 1; - bool bOutlinerMode : 1; - bool bDragAccepted : 1; - - DragAndDropInfo() - : nSensibleRange(0), nCursorWidth(0), nOutlinerDropDest(0), pBackground(nullptr), - pField(nullptr), bVisCursor(false), bDroppedInMe(false), bStarterOfDD(false), - bHasValidData(false), bUndoAction(false), bOutlinerMode(false), bDragAccepted(false) - { - } + tools::Rectangle aCurCursor; + tools::Rectangle aCurSavedCursor; + sal_uInt16 nSensibleRange = 0; + sal_uInt16 nCursorWidth = 0; + ESelection aBeginDragSel; + EditPaM aDropDest; + sal_Int32 nOutlinerDropDest = 0; + ESelection aDropSel; + VclPtr<VirtualDevice> pBackground = nullptr; + const SvxFieldItem* pField = nullptr; + bool bVisCursor : 1 = false; + bool bDroppedInMe : 1 = false; + bool bStarterOfDD : 1 = false; + bool bHasValidData : 1 = false; + bool bUndoAction : 1 = false; + bool bOutlinerMode : 1 = false; + bool bDragAccepted : 1 = false; + ~DragAndDropInfo() { - pBackground.disposeAndClear(); + pBackground.disposeAndClear(); } }; struct ImplIMEInfos { - OUString aOldTextAfterStartPos; + OUString aOldTextAfterStartPos; std::unique_ptr<ExtTextInputAttr[]> pAttribs; - EditPaM aPos; - sal_Int32 nLen; - bool bWasCursorOverwrite; + EditPaM aPos; + sal_Int32 nLen = 0; + bool bWasCursorOverwrite = false; - ImplIMEInfos( const EditPaM& rPos, const OUString& rOldTextAfterStartPos ); - ~ImplIMEInfos(); + ImplIMEInfos(const EditPaM& rPos, OUString _aOldTextAfterStartPos) + : aOldTextAfterStartPos(std::move(_aOldTextAfterStartPos)) + , aPos(rPos) + {} - void CopyAttribs( const ExtTextInputAttr* pA, sal_uInt16 nL ); - void DestroyAttribs(); + void CopyAttribs(const ExtTextInputAttr* pInputAttributes, sal_uInt16 nInputLength) + { + nLen = nInputLength; + pAttribs.reset(new ExtTextInputAttr[nInputLength]); + memcpy(pAttribs.get(), pInputAttributes, nInputLength * sizeof(ExtTextInputAttr)); + } + + void DestroyAttribs() + { + pAttribs.reset(); + nLen = 0; + } }; // #i18881# to be able to identify the positions of changed words @@ -155,56 +157,55 @@ typedef std::vector<EditSelection> SpellContentSelections; struct SpellInfo { - EESpellState eState; - EPaM aSpellStart; - EPaM aSpellTo; - EditPaM aCurSentenceStart; - bool bSpellToEnd; - bool bMultipleDoc; - svx::SpellPortions aLastSpellPortions; - SpellContentSelections aLastSpellContentSelections; - SpellInfo() : eState(EESpellState::Ok), bSpellToEnd(true), bMultipleDoc(false) - { } + EditPaM aCurSentenceStart; + svx::SpellPortions aLastSpellPortions; + SpellContentSelections aLastSpellContentSelections; + EESpellState eState = EESpellState::Ok; + EPaM aSpellStart; + EPaM aSpellTo; + bool bSpellToEnd : 1 = true; + bool bMultipleDoc : 1 = false; }; // used for text conversion struct ConvInfo { - EPaM aConvStart; - EPaM aConvTo; - EPaM aConvContinue; // position to start search for next text portion (word) with - bool bConvToEnd; - bool bMultipleDoc; - - ConvInfo() : bConvToEnd(true), bMultipleDoc(false) {} + EPaM aConvStart; + EPaM aConvTo; + EPaM aConvContinue; // position to start search for next text portion (word) with + bool bConvToEnd : 1 = true; + bool bMultipleDoc : 1 = false; }; struct FormatterFontMetric { - sal_uInt16 nMaxAscent; - sal_uInt16 nMaxDescent; + sal_uInt16 nMaxAscent = 0; + sal_uInt16 nMaxDescent = 0; - FormatterFontMetric() : nMaxAscent(0), nMaxDescent(0) { /* nMinLeading = 0xFFFF; */ } - sal_uInt16 GetHeight() const { return nMaxAscent+nMaxDescent; } + sal_uInt16 GetHeight() const + { + return nMaxAscent + nMaxDescent; + } }; class IdleFormattter : public Idle { private: - EditView* pView; - int nRestarts; + EditView* mpView = nullptr; + int mnRestarts = 0; public: - IdleFormattter(); - virtual ~IdleFormattter() override; + IdleFormattter(); + virtual ~IdleFormattter() override; - void DoIdleFormat( EditView* pV ); - void ForceTimeout(); - void ResetRestarts() { nRestarts = 0; } - EditView* GetView() { return pView; } + void DoIdleFormat(EditView* pView); + void ForceTimeout(); + void ResetRestarts() { mnRestarts = 0; } + EditView* GetView() { return mpView; } }; class ImpEditView; + /// This is meant just for Calc, where all positions in logical units (twips for LOK) are computed by /// doing independent pixel-alignment for each cell's size. LOKSpecialPositioning stores /// both 'output-area' and 'visible-doc-position' in pure logical unit (twips for LOK). @@ -233,6 +234,9 @@ public: Point GetWindowPos(const Point& rDocPos, MapUnit eDocPosUnit) const; tools::Rectangle GetWindowPos(const tools::Rectangle& rDocRect, MapUnit eDocRectUnit) const; + void SetFlags(LOKSpecialFlags eFlags) { meFlags = eFlags; } + bool IsLayoutRTL() { return bool(meFlags & LOKSpecialFlags::LayoutRTL); } + Point GetRefPoint() const; private: @@ -243,6 +247,7 @@ private: tools::Rectangle maOutArea; Point maVisDocStartPos; MapUnit meUnit; + LOKSpecialFlags meFlags; }; @@ -257,38 +262,37 @@ class ImpEditView : public vcl::unohelper::DragAndDropClient using vcl::unohelper::DragAndDropClient::dragOver; private: - EditView* pEditView; - std::unique_ptr<vcl::Cursor, o3tl::default_delete<vcl::Cursor>> pCursor; - std::optional<Color> mxBackgroundColor; + EditView* mpEditView; + std::unique_ptr<vcl::Cursor, o3tl::default_delete<vcl::Cursor>> mpCursor; + std::optional<Color> mxBackgroundColor; /// Containing view shell, if any. - OutlinerViewShell* mpViewShell; + OutlinerViewShell* mpViewShell; /// Another shell, just listening to our state, if any. - OutlinerViewShell* mpOtherShell; - EditEngine* pEditEngine; - VclPtr<vcl::Window> pOutWin; - EditView::OutWindowSet aOutWindowSet; - std::optional<PointerStyle> mxPointer; - std::unique_ptr<DragAndDropInfo> pDragAndDropInfo; - - css::uno::Reference< css::datatransfer::dnd::XDragSourceListener > mxDnDListener; - - - tools::Long nInvMore; - EVControlBits nControl; - sal_uInt32 nTravelXPos; - GetCursorFlags nExtraCursorFlags; - sal_uInt16 nCursorBidiLevel; - sal_uInt16 nScrollDiffX; - bool bReadOnly; - bool bClickedInSelection; - bool bActiveDragAndDropListener; - - Point aAnchorPoint; - tools::Rectangle aOutArea; - Point aVisDocStartPos; - EESelectionMode eSelectionMode; - EditSelection aEditSelection; - EEAnchorMode eAnchorMode; + OutlinerViewShell* mpOtherShell; + EditEngine* mpEditEngine; + VclPtr<vcl::Window> mpOutputWindow; + EditView::OutWindowSet maOutWindowSet; + std::optional<PointerStyle> mxPointer; + std::unique_ptr<DragAndDropInfo> mpDragAndDropInfo; + + css::uno::Reference<css::datatransfer::dnd::XDragSourceListener> mxDnDListener; + + tools::Long mnInvalidateMore; + EVControlBits mnControl; + sal_uInt32 mnTravelXPos; + CursorFlags maExtraCursorFlags; + sal_uInt16 mnCursorBidiLevel; + sal_uInt16 mnScrollDiffX; + bool mbReadOnly; + bool mbClickedInSelection; + bool mbActiveDragAndDropListener; + + Point maAnchorPoint; + tools::Rectangle maOutputArea; + Point maVisDocStartPos; + EESelectionMode meSelectionMode; + EditSelection maEditSelection; + EEAnchorMode meAnchorMode; /// mechanism to change from the classic refresh mode that simply // invalidates the area where text was changed. When set, the invalidate @@ -301,13 +305,14 @@ private: std::unique_ptr<LOKSpecialPositioning> mpLOKSpecialPositioning; bool mbBroadcastLOKViewCursor:1; bool mbSuppressLOKMessages:1; + bool mbNegativeX:1; EditViewCallbacks* getEditViewCallbacks() const { return mpEditViewCallbacks; } - void lokSelectionCallback(const std::unique_ptr<tools::PolyPolygon> &pPolyPoly, bool bStartHandleVisible, bool bEndHandleVisible); + void lokSelectionCallback(const std::optional<tools::PolyPolygon> &pPolyPoly, bool bStartHandleVisible, bool bEndHandleVisible); void setEditViewCallbacks(EditViewCallbacks* pEditViewCallbacks) { @@ -336,21 +341,24 @@ protected: void ShowDDCursor( const tools::Rectangle& rRect ); void HideDDCursor(); - void ImplDrawHighlightRect(OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly); - tools::Rectangle ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nShowCursorFlags, - sal_Int32& nTextPortionStart, const ParaPortion* pParaPortion) const; + void ImplDrawHighlightRect(OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly, bool bLOKCalcRTL); + tools::Rectangle ImplGetEditCursor(EditPaM& aPaM, CursorFlags aShowCursorFlags, sal_Int32& nTextPortionStart, ParaPortion const& rParaPortion) const; public: - ImpEditView( EditView* pView, EditEngine* pEng, vcl::Window* pWindow ); - virtual ~ImpEditView() override; + ImpEditView(EditView* pView, EditEngine* pEditEngine, vcl::Window* pWindow); + virtual ~ImpEditView() override; + + EditView* GetEditViewPtr() { return mpEditView; } - EditView* GetEditViewPtr() { return pEditView; } + EditEngine& getEditEngine() const { return *mpEditEngine; } + ImpEditEngine& getImpEditEngine() const { return getEditEngine().getImpl(); } - sal_uInt16 GetScrollDiffX() const { return nScrollDiffX; } - void SetScrollDiffX( sal_uInt16 n ) { nScrollDiffX = n; } - sal_uInt16 GetCursorBidiLevel() const { return nCursorBidiLevel; } - void SetCursorBidiLevel( sal_uInt16 n ) { nCursorBidiLevel = n; } + sal_uInt16 GetScrollDiffX() const { return mnScrollDiffX; } + void SetScrollDiffX(sal_uInt16 n) { mnScrollDiffX = n; } + + sal_uInt16 GetCursorBidiLevel() const { return mnCursorBidiLevel; } + void SetCursorBidiLevel(sal_uInt16 n) { mnCursorBidiLevel = n; } Point GetDocPos( const Point& rWindowPos ) const; Point GetWindowPos( const Point& rDocPos ) const; @@ -358,7 +366,7 @@ public: void SetOutputArea( const tools::Rectangle& rRect ); void ResetOutputArea( const tools::Rectangle& rRect ); - const tools::Rectangle& GetOutputArea() const { return aOutArea; } + const tools::Rectangle& GetOutputArea() const { return maOutputArea; } bool IsVertical() const; bool IsTopToBottom() const; @@ -372,22 +380,31 @@ public: bool Command(const CommandEvent& rCEvt); void CutCopy( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bCut ); - void Paste( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bUseSpecial = false ); + void Paste( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bUseSpecial = false, SotClipboardFormatId format = SotClipboardFormatId::NONE); - void SetVisDocStartPos( const Point& rPos ) { aVisDocStartPos = rPos; } + void SetVisDocStartPos(const Point& rPos) { maVisDocStartPos = rPos; } - tools::Long GetVisDocLeft() const { return aVisDocStartPos.X(); } - tools::Long GetVisDocTop() const { return aVisDocStartPos.Y(); } - tools::Long GetVisDocRight() const { return aVisDocStartPos.X() + ( !IsVertical() ? aOutArea.GetWidth() : aOutArea.GetHeight() ); } - tools::Long GetVisDocBottom() const { return aVisDocStartPos.Y() + ( !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth() ); } + tools::Long GetVisDocLeft() const { return maVisDocStartPos.X(); } + tools::Long GetVisDocTop() const { return maVisDocStartPos.Y(); } + tools::Long GetVisDocRight() const + { + return maVisDocStartPos.X() + ( !IsVertical() ? maOutputArea.GetWidth() : maOutputArea.GetHeight() ); + } + tools::Long GetVisDocBottom() const + { + return maVisDocStartPos.Y() + ( !IsVertical() ? maOutputArea.GetHeight() : maOutputArea.GetWidth() ); + } tools::Rectangle GetVisDocArea() const; - const EditSelection& GetEditSelection() const { return aEditSelection; } - void SetEditSelection( const EditSelection& rEditSelection ); - bool HasSelection() const { return aEditSelection.HasRange(); } + const EditSelection& GetEditSelection() const { return maEditSelection; } + void SetEditSelection(const EditSelection& rEditSelection); + bool HasSelection() const { return maEditSelection.HasRange(); } void SelectionChanged(); - void DrawSelectionXOR() { DrawSelectionXOR( aEditSelection ); } + void DrawSelectionXOR() + { + DrawSelectionXOR(maEditSelection); + } void DrawSelectionXOR( EditSelection, vcl::Region* pRegion = nullptr, OutputDevice* pTargetDevice = nullptr ); void GetSelectionRectangles(EditSelection aTmpSel, std::vector<tools::Rectangle>& rLogicRects); @@ -395,13 +412,36 @@ public: OutputDevice& GetOutputDevice() const; weld::Widget* GetPopupParent(tools::Rectangle& rRect) const; - vcl::Window* GetWindow() const { return pOutWin; } + vcl::Window* GetWindow() const { return mpOutputWindow; } void SetSelectionMode( EESelectionMode eMode ); - inline PointerStyle GetPointer(); + PointerStyle GetPointer() + { + if ( !mxPointer ) + { + mxPointer = IsVertical() ? PointerStyle::TextVertical : PointerStyle::Text; + return *mxPointer; + } + + if(PointerStyle::Text == *mxPointer && IsVertical()) + { + mxPointer = PointerStyle::TextVertical; + } + else if(PointerStyle::TextVertical == *mxPointer && !IsVertical()) + { + mxPointer = PointerStyle::Text; + } + + return *mxPointer; + } - inline vcl::Cursor* GetCursor(); + vcl::Cursor* GetCursor() + { + if (!mpCursor) + mpCursor.reset(new vcl::Cursor); + return mpCursor.get(); + } void AddDragAndDropListeners(); void RemoveDragAndDropListeners(); @@ -415,9 +455,11 @@ public: bool IsSelectionAtPoint( const Point& rPosPixel ); bool IsInSelection( const EditPaM& rPaM ); + bool IsSelectionFullPara() const; + bool IsSelectionInSinglePara() const; void SetAnchorMode( EEAnchorMode eMode ); - EEAnchorMode GetAnchorMode() const { return eAnchorMode; } + EEAnchorMode GetAnchorMode() const { return meAnchorMode; } void CalcAnchorPoint(); void RecalcOutputArea(); @@ -426,17 +468,17 @@ public: void ShowCursor( bool bGotoCursor, bool bForceVisCursor ); Pair Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRangeCheck = ScrollRangeCheck::NoNegative ); - void SetInsertMode( bool bInsert ); - bool IsInsertMode() const { return !( nControl & EVControlBits::OVERWRITE ); } + void SetInsertMode( bool bInsert ); + bool IsInsertMode() const { return !(mnControl & EVControlBits::OVERWRITE); } - bool IsPasteEnabled() const { return bool( nControl & EVControlBits::ENABLEPASTE ); } + bool IsPasteEnabled() const { return bool(mnControl & EVControlBits::ENABLEPASTE); } - bool DoSingleLinePaste() const { return bool( nControl & EVControlBits::SINGLELINEPASTE ); } - bool DoAutoScroll() const { return bool( nControl & EVControlBits::AUTOSCROLL ); } - bool DoAutoSize() const { return bool( nControl & EVControlBits::AUTOSIZE ); } - bool DoAutoWidth() const { return bool( nControl & EVControlBits::AUTOSIZEX); } - bool DoAutoHeight() const { return bool( nControl & EVControlBits::AUTOSIZEY); } - bool DoInvalidateMore() const { return bool( nControl & EVControlBits::INVONEMORE ); } + bool DoSingleLinePaste() const { return bool(mnControl & EVControlBits::SINGLELINEPASTE); } + bool DoAutoScroll() const { return bool(mnControl & EVControlBits::AUTOSCROLL); } + bool DoAutoSize() const { return bool(mnControl & EVControlBits::AUTOSIZE); } + bool DoAutoWidth() const { return bool(mnControl & EVControlBits::AUTOSIZEX); } + bool DoAutoHeight() const { return bool(mnControl & EVControlBits::AUTOSIZEY); } + bool DoInvalidateMore() const { return bool(mnControl & EVControlBits::INVONEMORE ); } void SetBackgroundColor( const Color& rColor ); const Color& GetBackgroundColor() const; @@ -454,8 +496,14 @@ public: void DeleteSelected(); // If possible invalidate more than OutputArea, for the DrawingEngine text frame - void SetInvalidateMore( sal_uInt16 nPixel ) { nInvMore = nPixel; } - sal_uInt16 GetInvalidateMore() const { return static_cast<sal_uInt16>(nInvMore); } + void SetInvalidateMore(sal_uInt16 nPixel) + { + mnInvalidateMore = nPixel; + } + sal_uInt16 GetInvalidateMore() const + { + return sal_uInt16(mnInvalidateMore); + } void InitLOKSpecialPositioning(MapUnit eUnit, const tools::Rectangle& rOutputArea, const Point& rVisDocStartPos); @@ -465,15 +513,20 @@ public: tools::Rectangle GetLOKSpecialVisArea() const; bool HasLOKSpecialPositioning() const; + void SetLOKSpecialFlags(LOKSpecialFlags eFlags); + void SuppressLOKMessages(bool bSet) { mbSuppressLOKMessages = bSet; } bool IsSuppressLOKMessages() const { return mbSuppressLOKMessages; } + + void SetNegativeX(bool bSet) { mbNegativeX = bSet; } + bool IsNegativeX() const { return mbNegativeX; } }; // ImpEditEngine -class ImpEditEngine : public SfxListener +class ImpEditEngine : public SfxListener, public svl::StyleSheetUser { friend class EditEngine; @@ -482,82 +535,77 @@ class ImpEditEngine : public SfxListener private: std::shared_ptr<editeng::SharedVclResources> pSharedVCL; - - // Data ... - - // Document Specific data ... - ParaPortionList aParaPortionList; // Formatting - Size aPaperSize; // Layout - Size aMinAutoPaperSize; // Layout ? - Size aMaxAutoPaperSize; // Layout ? + ParaPortionList maParaPortionList; // Formatting + Size maPaperSize; // Layout + Size maMinAutoPaperSize; // Layout ? + Size maMaxAutoPaperSize; // Layout ? tools::Long mnMinColumnWrapHeight = 0; // Corresponds to graphic object height - EditDoc aEditDoc; // Document content + EditDoc maEditDoc; // Document content // Engine Specific data ... - EditEngine* pEditEngine; - ViewsType aEditViews; - EditView* pActiveView; - std::unique_ptr<TextRanger> pTextRanger; + EditEngine* mpEditEngine; + ViewsType maEditViews; + EditView* mpActiveView; + std::unique_ptr<TextRanger> mpTextRanger; - SfxStyleSheetPool* pStylePool; - SfxItemPool* pTextObjectPool; + SfxStyleSheetPool* mpStylePool; + SfxItemPool* mpTextObjectPool; - VclPtr< VirtualDevice> pVirtDev; - VclPtr< OutputDevice > pRefDev; + VclPtr<VirtualDevice> mpVirtDev; + VclPtr<OutputDevice> mpRefDev; VclPtr<VirtualDevice> mpOwnDev; svtools::ColorConfig maColorConfig; - mutable std::unique_ptr<SvtCTLOptions> pCTLOptions; mutable std::unique_ptr<SfxItemSet> pEmptyItemSet; - EditUndoManager* pUndoManager; - std::unique_ptr<ESelection> pUndoMarkSelection; + EditUndoManager* mpUndoManager; + std::optional<ESelection> moUndoMarkSelection; std::unique_ptr<ImplIMEInfos> mpIMEInfos; - OUString aWordDelimiters; + OUString maWordDelimiters; - EditSelFunctionSet aSelFuncSet; - EditSelectionEngine aSelEngine; + EditSelFunctionSet maSelFuncSet; + EditSelectionEngine maSelEngine; Color maBackgroundColor; - sal_uInt16 nStretchX; - sal_uInt16 nStretchY; + ScalingParameters maCustomScalingParameters; + ScalingParameters maScalingParameters; + bool mbRoundToNearestPt; - CharCompressType nAsianCompressionMode; + CharCompressType mnAsianCompressionMode; - EEHorizontalTextDirection eDefaultHorizontalTextDirection; + EEHorizontalTextDirection meDefaultHorizontalTextDirection; - sal_Int32 nBigTextObjectStart; - css::uno::Reference< css::linguistic2::XSpellChecker1 > xSpeller; - css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator; - std::unique_ptr<SpellInfo> pSpellInfo; - mutable css::uno::Reference < css::i18n::XBreakIterator > xBI; - mutable css::uno::Reference < css::i18n::XExtendedInputSequenceChecker > xISC; + sal_Int32 mnBigTextObjectStart; + css::uno::Reference<css::linguistic2::XSpellChecker1> mxSpeller; + css::uno::Reference<css::linguistic2::XHyphenator> mxHyphenator; + std::unique_ptr<SpellInfo> mpSpellInfo; + mutable css::uno::Reference <css::i18n::XBreakIterator> mxBI; + mutable css::uno::Reference <css::i18n::XExtendedInputSequenceChecker> mxISC; - std::unique_ptr<ConvInfo> pConvInfo; + std::unique_ptr<ConvInfo> mpConvInfo; - OUString aAutoCompleteText; + OUString maAutoCompleteText; - InternalEditStatus aStatus; + InternalEditStatus maStatus; - LanguageType eDefLanguage; + LanguageType meDefLanguage; - OnDemandLocaleDataWrapper xLocaleDataWrapper; - OnDemandTransliterationWrapper xTransliterationWrapper; + OnDemandLocaleDataWrapper mxLocaleDataWrapper; + OnDemandTransliterationWrapper mxTransliterationWrapper; // For Formatting / Update... - std::vector<std::unique_ptr<DeletedNodeInfo> > aDeletedNodes; - tools::Rectangle aInvalidRect; - tools::Long nCurTextHeight; - tools::Long nCurTextHeightNTP; // without trailing empty paragraphs - sal_uInt16 nOnePixelInRef; - - IdleFormattter aIdleFormatter; + std::vector<std::unique_ptr<DeletedNodeInfo>> maDeletedNodes; + tools::Rectangle maInvalidRect; + tools::Long mnCurTextHeight; + tools::Long mnCurTextHeightNTP; // without trailing empty paragraphs + sal_uInt16 mnOnePixelInRef; - Timer aOnlineSpellTimer; + IdleFormattter maIdleFormatter; + Timer maOnlineSpellTimer; // For Chaining sal_Int32 mnOverflowingPara = -1; @@ -569,51 +617,52 @@ private: // If it is detected at one point that the StatusHdl has to be called, but // this should not happen immediately (critical section): - Timer aStatusTimer; - Size aLOKSpecialPaperSize; - - Link<EditStatus&,void> aStatusHdlLink; - Link<EENotify&,void> aNotifyHdl; - Link<HtmlImportInfo&,void> aHtmlImportHdl; - Link<RtfImportInfo&,void> aRtfImportHdl; - Link<MoveParagraphsInfo&,void> aBeginMovingParagraphsHdl; - Link<MoveParagraphsInfo&,void> aEndMovingParagraphsHdl; - Link<PasteOrDropInfos&,void> aBeginPasteOrDropHdl; - Link<PasteOrDropInfos&,void> aEndPasteOrDropHdl; - Link<LinkParamNone*,void> aModifyHdl; + Timer maStatusTimer; + Size maLOKSpecialPaperSize; + + Link<EditStatus&,void> maStatusHdlLink; + Link<EENotify&,void> maNotifyHdl; + Link<HtmlImportInfo&,void> maHtmlImportHdl; + Link<RtfImportInfo&,void> maRtfImportHdl; + Link<MoveParagraphsInfo&,void> maBeginMovingParagraphsHdl; + Link<MoveParagraphsInfo&,void> maEndMovingParagraphsHdl; + Link<PasteOrDropInfos&,void> maBeginPasteOrDropHdl; + Link<PasteOrDropInfos&,void> maEndPasteOrDropHdl; + Link<LinkParamNone*,void> maModifyHdl; Link<EditView*,void> maBeginDropHdl; Link<EditView*,void> maEndDropHdl; - bool bKernAsianPunctuation:1; - bool bAddExtLeading:1; - bool bIsFormatting:1; - bool bFormatted:1; - bool bInSelection:1; - bool bIsInUndo:1; - bool bUpdate:1; - bool bUndoEnabled:1; - bool bDowning:1; - bool bUseAutoColor:1; - bool bForceAutoColor:1; - bool bCallParaInsertedOrDeleted:1; - bool bFirstWordCapitalization:1; // specifies if auto-correction should capitalize the first word or not - bool mbLastTryMerge:1; - bool mbReplaceLeadingSingleQuotationMark:1; - - bool mbNbspRunNext; // can't be a bitfield as it is passed as bool& - + bool mbKernAsianPunctuation : 1; + bool mbAddExtLeading : 1; + bool mbIsFormatting : 1; + bool mbFormatted : 1; + bool mbInSelection : 1; + bool mbIsInUndo : 1; + bool mbUpdateLayout : 1; + bool mbUndoEnabled : 1; + bool mbDowning : 1; + bool mbUseAutoColor : 1; + bool mbForceAutoColor : 1; + bool mbCallParaInsertedOrDeleted : 1; + bool mbFirstWordCapitalization : 1; // specifies if auto-correction should capitalize the first word or not + bool mbLastTryMerge : 1; + bool mbReplaceLeadingSingleQuotationMark : 1; + bool mbSkipOutsideFormat : 1; + bool mbFuzzing : 1; + + bool mbNbspRunNext; // can't be a bitfield as it is passed as bool& // Methods... - void CursorMoved( const ContentNode* pPrevNode ); void ParaAttribsChanged( ContentNode const * pNode, bool bIgnoreUndoCheck = false ); void TextModified(); - void CalcHeight( ParaPortion* pPortion ); + void CalcHeight(ParaPortion& rParaPortion); + bool isInEmptyClusterAtTheEnd(ParaPortion& rParaPortion); void InsertUndo( std::unique_ptr<EditUndo> pUndo, bool bTryMerge = false ); void ResetUndoManager(); - bool HasUndoManager() const { return pUndoManager != nullptr; } + bool HasUndoManager() const { return mpUndoManager != nullptr; } std::unique_ptr<EditUndoSetAttribs> CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet ); @@ -622,10 +671,10 @@ private: std::tuple<const ParaPortion*, const EditLine*, tools::Long> GetPortionAndLine(Point aDocPos); EditPaM GetPaM( Point aDocPos, bool bSmart = true ); bool IsTextPos(const Point& rDocPos, sal_uInt16 nBorder); - tools::Long GetXPos(const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart = false) const; - tools::Long GetPortionXOffset(const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nTextPortion) const; - sal_Int32 GetChar(const ParaPortion* pParaPortion, const EditLine* pLine, tools::Long nX, bool bSmart = true); - Range GetLineXPosStartEnd( const ParaPortion* pParaPortion, const EditLine* pLine ) const; + tools::Long GetXPos(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nIndex, bool bPreferPortionStart = false) const; + tools::Long GetPortionXOffset(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nTextPortion) const; + sal_Int32 GetChar(ParaPortion const& rParaPortion, EditLine const& rLine, tools::Long nX, bool bSmart = true); + Range GetLineXPosStartEnd(ParaPortion const& rParaPortion, EditLine const& rLine) const; void ParaAttribsToCharAttribs( ContentNode* pNode ); void GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const; @@ -633,24 +682,28 @@ private: std::unique_ptr<EditTextObject> CreateTextObject(EditSelection aSelection, SfxItemPool*, bool bAllowBigObjects = false, sal_Int32 nBigObjStart = 0); EditSelection InsertTextObject( const EditTextObject&, EditPaM aPaM ); - EditSelection PasteText( css::uno::Reference< css::datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial ); + EditSelection PasteText( css::uno::Reference< css::datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial, SotClipboardFormatId format = SotClipboardFormatId::NONE); void CheckPageOverflow(); void Clear(); EditPaM RemoveText(); - bool CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ); - void CreateAndInsertEmptyLine( ParaPortion* pParaPortion ); - bool FinishCreateLines( ParaPortion* pParaPortion ); - void CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rStartPos /*, sal_Bool bCreateBlockPortions */ ); - void RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars ); - sal_Int32 SplitTextPortion( ParaPortion* pParaPortion, sal_Int32 nPos, EditLine* pCurLine = nullptr ); + + bool createLinesForEmptyParagraph(ParaPortion& rParaPortion); + tools::Long calculateMaxLineWidth(tools::Long nStartX, SvxLRSpaceItem const& rLRItem); + bool CreateLines(sal_Int32 nPara, sal_uInt32 nStartPosY); + + void CreateAndInsertEmptyLine(ParaPortion& rParaPortion); + bool FinishCreateLines(ParaPortion& rParaPortion); + void CreateTextPortions(ParaPortion& rParaPortion, sal_Int32& rStartPos); + void RecalcTextPortion(ParaPortion& rParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars); + sal_Int32 SplitTextPortion(ParaPortion& rParaPortion, sal_Int32 nPos, EditLine* pCurLine = nullptr); void SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFont, OutputDevice* pOut = nullptr ); void RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics, SvxFont& rFont ); void CheckAutoPageSize(); - void ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate ); - void ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, tools::Long nRemainingSpace ); + void ImpBreakLine(ParaPortion& rParaPortion, EditLine& rLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate); + void ImpAdjustBlocks(ParaPortion& rParaPortion, EditLine& rLine, tools::Long nRemainingSpace ); EditPaM ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward = false ); EditPaM ImpDeleteSelection(const EditSelection& rCurSel); EditPaM ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttribs = true ); @@ -664,13 +717,11 @@ private: EditPaM ImpFastInsertText( EditPaM aPaM, const OUString& rStr ); EditPaM ImpFastInsertParagraph( sal_Int32 nPara ); - bool ImpCheckRefMapMode(); - bool ImplHasText() const; void ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, std::vector<sal_Int32>& rArray ); - void InsertContent( ContentNode* pNode, sal_Int32 nPos ); + void InsertContent(std::unique_ptr<ContentNode> pNode, sal_Int32 nPos); EditPaM SplitContent( sal_Int32 nNode, sal_Int32 nSepPos ); EditPaM ConnectContents( sal_Int32 nLeftNode, bool bBackward ); @@ -692,7 +743,7 @@ private: EditPaM WordRight( const EditPaM& rPaM, sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES ); EditPaM StartOfWord( const EditPaM& rPaM ); EditPaM EndOfWord( const EditPaM& rPaM ); - EditSelection SelectWord( const EditSelection& rCurSelection, sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, bool bAcceptStartOfWord = true ); + EditSelection SelectWord( const EditSelection& rCurSelection, sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, bool bAcceptStartOfWord = true, bool bAcceptEndOfWord = false ); EditSelection SelectSentence( const EditSelection& rCurSel ) const; EditPaM CursorVisualLeftRight( EditView const * pEditView, const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode, bool bToLeft ); EditPaM CursorVisualStartEnd( EditView const * pEditView, const EditPaM& rPaM, bool bStart ); @@ -705,13 +756,13 @@ private: bool HasScriptType( sal_Int32 nPara, sal_uInt16 nType ) const; bool ImplCalcAsianCompression( ContentNode* pNode, TextPortion* pTextPortion, sal_Int32 nStartPos, - tools::Long* pDXArray, sal_uInt16 n100thPercentFromMax, bool bManipulateDXArray ); - void ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* pParaPortion, tools::Long nRemainingWidth ); + sal_Int32* pDXArray, sal_uInt16 n100thPercentFromMax, bool bManipulateDXArray ); + void ImplExpandCompressedPortions(EditLine& rLine, ParaPortion& rParaPortion, tools::Long nRemainingWidth); void ImplInitLayoutMode(OutputDevice& rOutDev, sal_Int32 nPara, sal_Int32 nIndex); - LanguageType ImplCalcDigitLang(LanguageType eCurLang) const; - void ImplInitDigitMode(OutputDevice& rOutDev, LanguageType eLang); - static OUString convertDigits(const OUString &rString, sal_Int32 nStt, sal_Int32 nLen, LanguageType eDigitLang); + static LanguageType ImplCalcDigitLang(LanguageType eCurLang); + static void ImplInitDigitMode(OutputDevice& rOutDev, LanguageType eLang); + static OUString convertDigits(std::u16string_view rString, sal_Int32 nStt, sal_Int32 nLen, LanguageType eDigitLang); EditPaM ReadText( SvStream& rInput, EditSelection aSel ); EditPaM ReadRTF( SvStream& rInput, EditSelection aSel ); @@ -727,11 +778,40 @@ private: std::vector<std::unique_ptr<SvxFontItem>>& rFontTable, SvxColorList& rColorList ); sal_Int32 LogicToTwips( sal_Int32 n ); - inline short GetXValue( short nXValue ) const; - inline tools::Long GetXValue( tools::Long nXValue ) const; + double scaleXSpacingValue(tools::Long nXValue) const + { + if (!maStatus.DoStretch() || maScalingParameters.fSpacingX == 1.0) + return nXValue; + + return double(nXValue) * maScalingParameters.fSpacingX; + } + + double scaleYSpacingValue(sal_uInt16 nYValue) const + { + if (!maStatus.DoStretch() || maScalingParameters.fSpacingY == 1.0) + return nYValue; + + return double(nYValue) * maScalingParameters.fSpacingY; + } + + double scaleXFontValue(tools::Long nXValue) const + { + if (!maStatus.DoStretch() || (maScalingParameters.fFontX == 1.0)) + return nXValue; + + return double(nXValue) * maScalingParameters.fFontX; + } + + double scaleYFontValue(sal_uInt16 nYValue) const + { + if (!maStatus.DoStretch() || (maScalingParameters.fFontY == 1.0)) + return nYValue; + + return double(nYValue) * maScalingParameters.fFontY; + } - inline short GetYValue( short nYValue ) const; - inline sal_uInt16 GetYValue( sal_uInt16 nYValue ) const; + void setRoundToNearestPt(bool bRound) { mbRoundToNearestPt = bRound; } + double roundToNearestPt(double fInput) const; ContentNode* GetPrevVisNode( ContentNode const * pCurNode ); ContentNode* GetNextVisNode( ContentNode const * pCurNode ); @@ -745,13 +825,31 @@ private: tools::Long CalcVertLineSpacing(Point& rStartPos) const; Color GetAutoColor() const; - void EnableAutoColor( bool b ) { bUseAutoColor = b; } - bool IsAutoColorEnabled() const { return bUseAutoColor; } - void ForceAutoColor( bool b ) { bForceAutoColor = b; } - bool IsForceAutoColor() const { return bForceAutoColor; } + void EnableAutoColor( bool b ) { mbUseAutoColor = b; } + bool IsAutoColorEnabled() const { return mbUseAutoColor; } + void ForceAutoColor( bool b ) { mbForceAutoColor = b; } + bool IsForceAutoColor() const { return mbForceAutoColor; } + + VirtualDevice* GetVirtualDevice(const MapMode& rMapMode, DrawModeFlags nDrawMode) + { + if (!mpVirtDev) + mpVirtDev = VclPtr<VirtualDevice>::Create(); + + if ((mpVirtDev->GetMapMode().GetMapUnit() != rMapMode.GetMapUnit()) || + (mpVirtDev->GetMapMode().GetScaleX() != rMapMode.GetScaleX()) || + (mpVirtDev->GetMapMode().GetScaleY() != rMapMode.GetScaleY()) ) + { + MapMode aMapMode(rMapMode); + aMapMode.SetOrigin(Point(0, 0)); + mpVirtDev->SetMapMode(aMapMode); + } + + mpVirtDev->SetDrawMode(nDrawMode); + + return mpVirtDev; + } - inline VirtualDevice* GetVirtualDevice( const MapMode& rMapMode, DrawModeFlags nDrawMode ); - void EraseVirtualDevice() { pVirtDev.disposeAndClear(); } + void EraseVirtualDevice() { mpVirtDev.disposeAndClear(); } DECL_LINK( StatusTimerHdl, Timer *, void); DECL_LINK( IdleFormatHdl, Timer *, void); @@ -760,8 +858,19 @@ private: void CheckIdleFormatter(); - inline const ParaPortion& FindParaPortion( const ContentNode* pNode ) const; - inline ParaPortion& FindParaPortion( ContentNode const * pNode ); + const ParaPortion* FindParaPortion(const ContentNode* pNode) const + { + sal_Int32 nPos = maEditDoc.GetPos( pNode ); + DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); + return GetParaPortions().SafeGetObject(nPos); + } + + ParaPortion* FindParaPortion(ContentNode const * pNode) + { + sal_Int32 nPos = maEditDoc.GetPos( pNode ); + DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); + return GetParaPortions().SafeGetObject(nPos); + } css::uno::Reference< css::datatransfer::XTransferable > CreateTransferable( const EditSelection& rSelection ); @@ -779,14 +888,16 @@ private: ImpEditEngine(EditEngine* pEditEngine, SfxItemPool* pPool); void InitDoc(bool bKeepParaAttribs); - EditDoc& GetEditDoc() { return aEditDoc; } - const EditDoc& GetEditDoc() const { return aEditDoc; } + EditDoc& GetEditDoc() { return maEditDoc; } + const EditDoc& GetEditDoc() const { return maEditDoc; } - const ParaPortionList& GetParaPortions() const { return aParaPortionList; } - ParaPortionList& GetParaPortions() { return aParaPortionList; } + const ParaPortionList& GetParaPortions() const { return maParaPortionList; } + ParaPortionList& GetParaPortions() { return maParaPortionList; } tools::Long Calc1ColumnTextHeight(tools::Long* pHeightNTP); + void IdleFormatAndLayout(EditView* pCurView) { maIdleFormatter.DoIdleFormat(pCurView); } + protected: virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; @@ -795,22 +906,49 @@ public: ImpEditEngine(const ImpEditEngine&) = delete; ImpEditEngine& operator=(const ImpEditEngine&) = delete; - inline EditUndoManager& GetUndoManager(); - inline SfxUndoManager* SetUndoManager(SfxUndoManager* pNew); + EditUndoManager& GetUndoManager() + { + if (!mpUndoManager) + { + mpUndoManager = new EditUndoManager(); + mpUndoManager->SetEditEngine(mpEditEngine); + } + return *mpUndoManager; + } + + EditUndoManager* SetUndoManager(EditUndoManager* pNew) + { + EditUndoManager* pRetval = mpUndoManager; + + if (mpUndoManager) + { + mpUndoManager->SetEditEngine(nullptr); + } - void SetUpdateMode( bool bUp, EditView* pCurView = nullptr, bool bForceUpdate = false ); - bool GetUpdateMode() const { return bUpdate; } + mpUndoManager = pNew; - ViewsType& GetEditViews() { return aEditViews; } - const ViewsType& GetEditViews() const { return aEditViews; } + if (mpUndoManager) + { + mpUndoManager->SetEditEngine(mpEditEngine); + } - const Size& GetPaperSize() const { return aPaperSize; } - void SetPaperSize( const Size& rSz ) { aPaperSize = rSz; } + return pRetval; + } + + // @return the previous bUpdateLayout state + bool SetUpdateLayout( bool bUpdate, EditView* pCurView = nullptr, bool bForceUpdate = false ); + bool IsUpdateLayout() const { return mbUpdateLayout; } + + ViewsType& GetEditViews() { return maEditViews; } + const ViewsType& GetEditViews() const { return maEditViews; } + + const Size& GetPaperSize() const { return maPaperSize; } + void SetPaperSize(const Size& rSize) { maPaperSize = rSize; } void SetVertical( bool bVertical); - bool IsVertical() const { return GetEditDoc().IsVertical(); } + bool IsEffectivelyVertical() const { return GetEditDoc().IsEffectivelyVertical(); } bool IsTopToBottom() const { return GetEditDoc().IsTopToBottom(); } - bool GetDirectVertical() const { return GetEditDoc().GetDirectVertical(); } + bool GetVertical() const { return GetEditDoc().GetVertical(); } void SetRotation( TextRotation nRotation); TextRotation GetRotation() const { return GetEditDoc().GetRotation(); } @@ -821,8 +959,8 @@ public: void SetFixedCellHeight( bool bUseFixedCellHeight ); bool IsFixedCellHeight() const { return GetEditDoc().IsFixedCellHeight(); } - void SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) { eDefaultHorizontalTextDirection = eHTextDir; } - EEHorizontalTextDirection GetDefaultHorizontalTextDirection() const { return eDefaultHorizontalTextDirection; } + void SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) { meDefaultHorizontalTextDirection = eHTextDir; } + EEHorizontalTextDirection GetDefaultHorizontalTextDirection() const { return meDefaultHorizontalTextDirection; } void InitWritingDirections( sal_Int32 nPara ); @@ -831,18 +969,21 @@ public: bool HasDifferentRTLLevels( const ContentNode* pNode ); void SetTextRanger( std::unique_ptr<TextRanger> pRanger ); - TextRanger* GetTextRanger() const { return pTextRanger.get(); } + TextRanger* GetTextRanger() const { return mpTextRanger.get(); } - const Size& GetMinAutoPaperSize() const { return aMinAutoPaperSize; } - void SetMinAutoPaperSize( const Size& rSz ) { aMinAutoPaperSize = rSz; } + const Size& GetMinAutoPaperSize() const { return maMinAutoPaperSize; } + void SetMinAutoPaperSize(const Size& rSize) { maMinAutoPaperSize = rSize; } - const Size& GetMaxAutoPaperSize() const { return aMaxAutoPaperSize; } - void SetMaxAutoPaperSize( const Size& rSz ) { aMaxAutoPaperSize = rSz; } + const Size& GetMaxAutoPaperSize() const { return maMaxAutoPaperSize; } + void SetMaxAutoPaperSize(const Size& rSize) { maMaxAutoPaperSize = rSize; } void SetMinColumnWrapHeight(tools::Long nVal) { mnMinColumnWrapHeight = nVal; } - void FormatDoc(); - void FormatFullDoc(); + tools::Long FormatParagraphs(o3tl::sorted_vector<sal_Int32>& rRepaintParagraphs); + void ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& rRepaintParagraphs); + void FormatDoc(); + void FormatFullDoc(); + void UpdateViews( EditView* pCurView = nullptr ); void Paint( ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice ); void Paint(OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly = false, Degree10 nOrientation = 0_deg10); @@ -853,7 +994,7 @@ public: bool MouseMove( const MouseEvent& rMouseEvent, EditView* pView ); bool Command(const CommandEvent& rCEvt, EditView* pView); - EditSelectionEngine& GetSelEngine() { return aSelEngine; } + EditSelectionEngine& GetSelEngine() { return maSelEngine; } OUString GetSelected( const EditSelection& rSel ) const; const SfxItemSet& GetEmptyItemSet() const; @@ -861,15 +1002,15 @@ public: void UpdateSelections(); void EnableUndo( bool bEnable ); - bool IsUndoEnabled() const { return bUndoEnabled; } - void SetUndoMode( bool b ) { bIsInUndo = b; } - bool IsInUndo() const { return bIsInUndo; } + bool IsUndoEnabled() const { return mbUndoEnabled; } + void SetUndoMode( bool b ) { mbIsInUndo = b; } + bool IsInUndo() const { return mbIsInUndo; } - void SetCallParaInsertedOrDeleted( bool b ) { bCallParaInsertedOrDeleted = b; } - bool IsCallParaInsertedOrDeleted() const { return bCallParaInsertedOrDeleted; } + void SetCallParaInsertedOrDeleted( bool b ) { mbCallParaInsertedOrDeleted = b; } + bool IsCallParaInsertedOrDeleted() const { return mbCallParaInsertedOrDeleted; } - bool IsFormatted() const { return bFormatted; } - bool IsFormatting() const { return bIsFormatting; } + bool IsFormatted() const { return mbFormatted; } + bool IsFormatting() const { return mbIsFormatting; } void SetText(const OUString& rText); EditPaM DeleteSelected(const EditSelection& rEditSelection); @@ -900,17 +1041,17 @@ public: sal_uInt32 GetTextHeightNTP() const; sal_uInt32 CalcTextWidth( bool bIgnoreExtraSpace); sal_uInt32 CalcParaWidth( sal_Int32 nParagraph, bool bIgnoreExtraSpace ); - sal_uInt32 CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, bool bIgnoreExtraSpace); + sal_uInt32 CalcLineWidth(ParaPortion const& rPortion, EditLine const& rLine, bool bIgnoreExtraSpace); sal_Int32 GetLineCount( sal_Int32 nParagraph ) const; sal_Int32 GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) const; void GetLineBoundaries( /*out*/sal_Int32& rStart, /*out*/sal_Int32& rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const; sal_Int32 GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const; sal_uInt16 GetLineHeight( sal_Int32 nParagraph, sal_Int32 nLine ); - sal_uInt32 GetParaHeight( sal_Int32 nParagraph ); + sal_uInt32 GetParaHeight(sal_Int32 nParagraph) const; SfxItemSet GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags = GetAttribsFlags::ALL ) const; SfxItemSet GetAttribs( EditSelection aSel, EditEngineAttribs nOnlyHardAttrib = EditEngineAttribs::All ); - void SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetAttribsMode nSpecial = SetAttribsMode::NONE ); + void SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetAttribsMode nSpecial = SetAttribsMode::NONE, bool bSetSelection = true ); void RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMode eMode, sal_uInt16 nWhich ); void RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich = 0, bool bRemoveFeatures = false ); void SetFlatMode( bool bFlat ); @@ -926,16 +1067,14 @@ public: return static_cast<const T&>(GetParaAttrib(nPara, sal_uInt16(nWhich))); } - tools::Rectangle PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nFlags = GetCursorFlags::NONE ); - tools::Rectangle GetEditCursor(const ParaPortion* pPortion, const EditLine* pLine, - sal_Int32 nIndex, GetCursorFlags nFlags); + tools::Rectangle PaMtoEditCursor(EditPaM aPaM, CursorFlags aFlags = CursorFlags()); + tools::Rectangle GetEditCursor(ParaPortion const& rPortion, EditLine const& rLine, sal_Int32 nIndex, CursorFlags aFlags); - bool IsModified() const { return aEditDoc.IsModified(); } - void SetModifyFlag( bool b ) { aEditDoc.SetModified( b ); } - void SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) { aModifyHdl = rLink; } - const Link<LinkParamNone*,void>& GetModifyHdl() const { return aModifyHdl; } + bool IsModified() const { return maEditDoc.IsModified(); } + void SetModifyFlag(bool b) { maEditDoc.SetModified( b ); } + void SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) { maModifyHdl = rLink; } - bool IsInSelectionMode() const { return bInSelection; } + bool IsInSelectionMode() const { return mbInSelection; } // For Undo/Redo void Undo( EditView* pView ); @@ -944,29 +1083,63 @@ public: // OV-Special void InvalidateFromParagraph( sal_Int32 nFirstInvPara ); EditPaM InsertParagraph( sal_Int32 nPara ); - std::unique_ptr<EditSelection> SelectParagraph( sal_Int32 nPara ); + std::optional<EditSelection> SelectParagraph( sal_Int32 nPara ); - void SetStatusEventHdl( const Link<EditStatus&, void>& rLink ) { aStatusHdlLink = rLink; } - const Link<EditStatus&,void>& GetStatusEventHdl() const { return aStatusHdlLink; } + void SetStatusEventHdl( const Link<EditStatus&, void>& rLink ) { maStatusHdlLink = rLink; } + const Link<EditStatus&,void>& GetStatusEventHdl() const { return maStatusHdlLink; } - void SetNotifyHdl( const Link<EENotify&,void>& rLink ) { aNotifyHdl = rLink; } - const Link<EENotify&,void>& GetNotifyHdl() const { return aNotifyHdl; } + void SetNotifyHdl( const Link<EENotify&,void>& rLink ) { maNotifyHdl = rLink; } + const Link<EENotify&,void>& GetNotifyHdl() const { return maNotifyHdl; } - void FormatAndUpdate( EditView* pCurView = nullptr, bool bCalledFromUndo = false ); - inline void IdleFormatAndUpdate( EditView* pCurView ); + void FormatAndLayout( EditView* pCurView = nullptr, bool bCalledFromUndo = false ); const svtools::ColorConfig& GetColorConfig() const { return maColorConfig; } - bool IsVisualCursorTravelingEnabled(); - bool DoVisualCursorTraveling(); + static bool IsVisualCursorTravelingEnabled(); + static bool DoVisualCursorTraveling(); EditSelection ConvertSelection( sal_Int32 nStartPara, sal_Int32 nStartPos, sal_Int32 nEndPara, sal_Int32 nEndPos ); - inline EPaM CreateEPaM( const EditPaM& rPaM ); - inline EditPaM CreateEditPaM( const EPaM& rEPaM ); - inline ESelection CreateESel( const EditSelection& rSel ); - inline EditSelection CreateSel( const ESelection& rSel ); + + EPaM CreateEPaM( const EditPaM& rPaM ) const + { + const ContentNode* pNode = rPaM.GetNode(); + return EPaM(maEditDoc.GetPos(pNode), rPaM.GetIndex()); + } + + EditPaM CreateEditPaM( const EPaM& rEPaM ) + { + DBG_ASSERT( rEPaM.nPara < maEditDoc.Count(), "CreateEditPaM: invalid paragraph" ); + DBG_ASSERT(maEditDoc.GetObject(rEPaM.nPara)->Len() >= rEPaM.nIndex, "CreateEditPaM: invalid Index"); + return EditPaM(maEditDoc.GetObject(rEPaM.nPara), rEPaM.nIndex); + } + + ESelection CreateESel(const EditSelection& rSel) const + { + const ContentNode* pStartNode = rSel.Min().GetNode(); + const ContentNode* pEndNode = rSel.Max().GetNode(); + ESelection aESel; + aESel.nStartPara = maEditDoc.GetPos( pStartNode ); + aESel.nStartPos = rSel.Min().GetIndex(); + aESel.nEndPara = maEditDoc.GetPos( pEndNode ); + aESel.nEndPos = rSel.Max().GetIndex(); + return aESel; + } + + EditSelection CreateSel(const ESelection& rSel) + { + DBG_ASSERT( rSel.nStartPara < maEditDoc.Count(), "CreateSel: invalid start paragraph" ); + DBG_ASSERT( rSel.nEndPara < maEditDoc.Count(), "CreateSel: invalid end paragraph" ); + EditSelection aSel; + aSel.Min().SetNode(maEditDoc.GetObject(rSel.nStartPara)); + aSel.Min().SetIndex( rSel.nStartPos ); + aSel.Max().SetNode(maEditDoc.GetObject(rSel.nEndPara)); + aSel.Max().SetIndex( rSel.nEndPos ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "CreateSel: incorrect selection!" ); + return aSel; + + } void SetStyleSheetPool( SfxStyleSheetPool* pSPool ); - SfxStyleSheetPool* GetStyleSheetPool() const { return pStylePool; } + SfxStyleSheetPool* GetStyleSheetPool() const { return mpStylePool; } void SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle ); void SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ); @@ -976,41 +1149,45 @@ public: void UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle ); void RemoveStyleFromParagraphs( SfxStyleSheet const * pStyle ); - OutputDevice* GetRefDevice() const { return pRefDev.get(); } - void SetRefDevice( OutputDevice* pRefDef ); + bool isUsedByModel() const override { return true; } - const MapMode& GetRefMapMode() const { return pRefDev->GetMapMode(); } - void SetRefMapMode( const MapMode& rMapMode ); + OutputDevice* GetRefDevice() const { return mpRefDev.get(); } + void SetRefDevice(OutputDevice* mpRefDef); + + const MapMode& GetRefMapMode() const { return mpRefDev->GetMapMode(); } + void SetRefMapMode(const MapMode& rMapMode); + + InternalEditStatus& GetStatus() { return maStatus; } + InternalEditStatus const& GetStatus() const{ return maStatus; } - InternalEditStatus& GetStatus() { return aStatus; } void CallStatusHdl(); - void DelayedCallStatusHdl() { aStatusTimer.Start(); } + void DelayedCallStatusHdl() { maStatusTimer.Start(); } void UndoActionStart( sal_uInt16 nId ); void UndoActionStart( sal_uInt16 nId, const ESelection& rSel ); void UndoActionEnd(); - EditView* GetActiveView() const { return pActiveView; } + EditView* GetActiveView() const { return mpActiveView; } void SetActiveView( EditView* pView ); css::uno::Reference< css::linguistic2::XSpellChecker1 > const & GetSpeller(); void SetSpeller( css::uno::Reference< css::linguistic2::XSpellChecker1 > const &xSpl ) - { xSpeller = xSpl; } + { mxSpeller = xSpl; } const css::uno::Reference< css::linguistic2::XHyphenator >& - GetHyphenator() const { return xHyphenator; } + GetHyphenator() const { return mxHyphenator; } void SetHyphenator( css::uno::Reference< css::linguistic2::XHyphenator > const &xHyph ) - { xHyphenator = xHyph; } + { mxHyphenator = xHyph; } void GetAllMisspellRanges( std::vector<editeng::MisspellRanges>& rRanges ) const; void SetAllMisspellRanges( const std::vector<editeng::MisspellRanges>& rRanges ); - SpellInfo* GetSpellInfo() const { return pSpellInfo.get(); } + SpellInfo* GetSpellInfo() const { return mpSpellInfo.get(); } - void SetDefaultLanguage( LanguageType eLang ) { eDefLanguage = eLang; } - LanguageType GetDefaultLanguage() const { return eDefLanguage; } + void SetDefaultLanguage(LanguageType eLang) { meDefLanguage = eLang; } + LanguageType GetDefaultLanguage() const { return meDefLanguage; } - LanguageType GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos = nullptr ) const; + editeng::LanguageSpan GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos = nullptr ) const; css::lang::Locale GetLocale( const EditPaM& rPaM ) const; void DoOnlineSpelling( ContentNode* pThisNodeOnly = nullptr, bool bSpellAtCursorPos = false, bool bInterruptible = true ); @@ -1025,7 +1202,7 @@ public: void Convert(EditView* pEditView, weld::Widget* pDialogParent, LanguageType nSrcLang, LanguageType nDestLang, const vcl::Font *pDestFont, sal_Int32 nOptions, bool bIsInteractive, bool bMultipleDoc); void ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, EditView* pEditView, LanguageType nSrcLang, const ESelection &rConvRange, bool bAllowImplicitChangesForNotConvertibleText, LanguageType nTargetLang, const vcl::Font *pTargetFont ); - ConvInfo * GetConvInfo() const { return pConvInfo.get(); } + ConvInfo * GetConvInfo() const { return mpConvInfo.get(); } bool HasConvertibleTextPortion( LanguageType nLang ); void SetLanguageAndFont( const ESelection &rESel, LanguageType nLang, sal_uInt16 nLangWhichId, @@ -1061,8 +1238,8 @@ public: sal_Int32 StartSearchAndReplace( EditView* pEditView, const SvxSearchItem& rSearchItem ); bool HasText( const SvxSearchItem& rSearchItem ); - void SetEditTextObjectPool( SfxItemPool* pP ) { pTextObjectPool = pP; } - SfxItemPool* GetEditTextObjectPool() const { return pTextObjectPool; } + void SetEditTextObjectPool( SfxItemPool* pP ) { mpTextObjectPool = pP; } + SfxItemPool* GetEditTextObjectPool() const { return mpTextObjectPool; } const SvxNumberFormat * GetNumberFormat( const ContentNode* pNode ) const; sal_Int32 GetSpaceBeforeAndMinLabelWidth( const ContentNode *pNode, sal_Int32 *pnSpaceBefore = nullptr, sal_Int32 *pnMinLabelWidth = nullptr ) const; @@ -1072,27 +1249,36 @@ public: SvxCellJustifyMethod GetJustifyMethod( sal_Int32 nPara ) const; SvxCellVerJustify GetVerJustification( sal_Int32 nPara ) const; - void SetCharStretching( sal_uInt16 nX, sal_uInt16 nY ); - inline void GetCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const; + void setScalingParameters(ScalingParameters const& rScalingParameters); + + void resetScalingParameters() + { + setScalingParameters(ScalingParameters()); + } + + ScalingParameters getScalingParameters() + { + return maScalingParameters; + } - sal_Int32 GetBigTextObjectStart() const { return nBigTextObjectStart; } + sal_Int32 GetBigTextObjectStart() const { return mnBigTextObjectStart; } - EditEngine* GetEditEnginePtr() const { return pEditEngine; } + EditEngine* GetEditEnginePtr() const { return mpEditEngine; } - void StartOnlineSpellTimer() { aOnlineSpellTimer.Start(); } - void StopOnlineSpellTimer() { aOnlineSpellTimer.Stop(); } + void StartOnlineSpellTimer() { maOnlineSpellTimer.Start(); } + void StopOnlineSpellTimer() { maOnlineSpellTimer.Stop(); } - const OUString& GetAutoCompleteText() const { return aAutoCompleteText; } + const OUString& GetAutoCompleteText() const { return maAutoCompleteText; } void SetAutoCompleteText(const OUString& rStr, bool bUpdateTipWindow); EditSelection TransliterateText( const EditSelection& rSelection, TransliterationFlags nTransliterationMode ); short ReplaceTextOnly( ContentNode* pNode, sal_Int32 nCurrentStart, std::u16string_view rText, const css::uno::Sequence< sal_Int32 >& rOffsets ); void SetAsianCompressionMode( CharCompressType n ); - CharCompressType GetAsianCompressionMode() const { return nAsianCompressionMode; } + CharCompressType GetAsianCompressionMode() const { return mnAsianCompressionMode; } void SetKernAsianPunctuation( bool b ); - bool IsKernAsianPunctuation() const { return bKernAsianPunctuation; } + bool IsKernAsianPunctuation() const { return mbKernAsianPunctuation; } sal_Int32 GetOverflowingParaNum() const { return mnOverflowingPara; } sal_Int32 GetOverflowingLineNum() const { return mnOverflowingLine; } @@ -1100,7 +1286,7 @@ public: void SetAddExtLeading( bool b ); - bool IsAddExtLeading() const { return bAddExtLeading; } + bool IsAddExtLeading() const { return mbAddExtLeading; } static std::shared_ptr<SvxForbiddenCharactersTable> const & GetForbiddenCharsTable(); static void SetForbiddenCharsTable( const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars ); @@ -1114,8 +1300,8 @@ public: const Link<EditView*,void>& GetEndDropHdl() const { return maEndDropHdl; } /// specifies if auto-correction should capitalize the first word or not (default is on) - void SetFirstWordCapitalization( bool bCapitalize ) { bFirstWordCapitalization = bCapitalize; } - bool IsFirstWordCapitalization() const { return bFirstWordCapitalization; } + void SetFirstWordCapitalization( bool bCapitalize ) { mbFirstWordCapitalization = bCapitalize; } + bool IsFirstWordCapitalization() const { return mbFirstWordCapitalization; } /** specifies if auto-correction should replace a leading single quotation mark (apostrophe) or not (default is on) */ @@ -1125,9 +1311,11 @@ public: /** Whether last AutoCorrect inserted a NO-BREAK SPACE that may need to be removed again. */ bool IsNbspRunNext() const { return mbNbspRunNext; } + void EnableSkipOutsideFormat(bool set) { mbSkipOutsideFormat = set; } + void Dispose(); - void SetLOKSpecialPaperSize(const Size& rSize) { aLOKSpecialPaperSize = rSize; } - const Size& GetLOKSpecialPaperSize() const { return aLOKSpecialPaperSize; } + void SetLOKSpecialPaperSize(const Size& rSize) { maLOKSpecialPaperSize = rSize; } + const Size& GetLOKSpecialPaperSize() const { return maLOKSpecialPaperSize; } enum class CallbackResult { @@ -1137,13 +1325,14 @@ public: }; struct LineAreaInfo { - sal_Int32 nColumn; // Column number; when overflowing, equal to total number of columns ParaPortion& rPortion; // Current ParaPortion - sal_Int32 nPortion; EditLine* pLine; // Current line, or nullptr for paragraph start - sal_Int32 nLine; - tools::Rectangle aArea; // The area for the line (or for rPortion's first line offset) tools::Long nHeightNeededToNotWrap; + tools::Rectangle aArea; // The area for the line (or for rPortion's first line offset) + // Bottom coordinate *does not* belong to the area + sal_Int32 nPortion; + sal_Int32 nLine; + sal_Int16 nColumn; // Column number; when overflowing, equal to total number of columns }; using IterateLinesAreasFunc = std::function<CallbackResult(const LineAreaInfo&)>; enum IterFlag // bitmask @@ -1155,200 +1344,25 @@ public: void IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eOptions); tools::Long GetColumnWidth(const Size& rPaperSize) const; - Point MoveToNextLine(Point& rMovePos, tools::Long nLineHeight, sal_Int32& nColumn, + Point MoveToNextLine(Point& rMovePos, tools::Long nLineHeight, sal_Int16& nColumn, Point aOrigin, tools::Long* pnHeightNeededToNotWrap = nullptr) const; - tools::Long getXDirectionAware(const Point& pt) const; - tools::Long getYDirectionAware(const Point& pt) const; tools::Long getWidthDirectionAware(const Size& sz) const; tools::Long getHeightDirectionAware(const Size& sz) const; void adjustXDirectionAware(Point& pt, tools::Long x) const; void adjustYDirectionAware(Point& pt, tools::Long y) const; - void setXDirectionAware(Point& pt, tools::Long x) const; - void setYDirectionAware(Point& pt, tools::Long y) const; + void setXDirectionAwareFrom(Point& ptDest, const Point& ptSrc) const; + void setYDirectionAwareFrom(Point& ptDest, const Point& ptSrc) const; tools::Long getYOverflowDirectionAware(const Point& pt, const tools::Rectangle& rectMax) const; bool isXOverflowDirectionAware(const Point& pt, const tools::Rectangle& rectMax) const; - tools::Long getLeftDirectionAware(const tools::Rectangle& rect) const; - tools::Long getRightDirectionAware(const tools::Rectangle& rect) const; - tools::Long getTopDirectionAware(const tools::Rectangle& rect) const; - tools::Long getBottomDirectionAware(const tools::Rectangle& rect) const; + // Offset of the rectangle's direction-aware corners in document coordinates + tools::Long getBottomDocOffset(const tools::Rectangle& rect) const; + Size getTopLeftDocOffset(const tools::Rectangle& rect) const; }; -inline EPaM ImpEditEngine::CreateEPaM( const EditPaM& rPaM ) -{ - const ContentNode* pNode = rPaM.GetNode(); - return EPaM( aEditDoc.GetPos( pNode ), rPaM.GetIndex() ); -} - -inline EditPaM ImpEditEngine::CreateEditPaM( const EPaM& rEPaM ) -{ - DBG_ASSERT( rEPaM.nPara < aEditDoc.Count(), "CreateEditPaM: invalid paragraph" ); - DBG_ASSERT( aEditDoc[ rEPaM.nPara ]->Len() >= rEPaM.nIndex, "CreateEditPaM: invalid Index" ); - return EditPaM( aEditDoc[ rEPaM.nPara], rEPaM.nIndex ); -} - -inline ESelection ImpEditEngine::CreateESel( const EditSelection& rSel ) -{ - const ContentNode* pStartNode = rSel.Min().GetNode(); - const ContentNode* pEndNode = rSel.Max().GetNode(); - ESelection aESel; - aESel.nStartPara = aEditDoc.GetPos( pStartNode ); - aESel.nStartPos = rSel.Min().GetIndex(); - aESel.nEndPara = aEditDoc.GetPos( pEndNode ); - aESel.nEndPos = rSel.Max().GetIndex(); - return aESel; -} - -inline EditSelection ImpEditEngine::CreateSel( const ESelection& rSel ) -{ - DBG_ASSERT( rSel.nStartPara < aEditDoc.Count(), "CreateSel: invalid start paragraph" ); - DBG_ASSERT( rSel.nEndPara < aEditDoc.Count(), "CreateSel: invalid end paragraph" ); - EditSelection aSel; - aSel.Min().SetNode( aEditDoc[ rSel.nStartPara ] ); - aSel.Min().SetIndex( rSel.nStartPos ); - aSel.Max().SetNode( aEditDoc[ rSel.nEndPara ] ); - aSel.Max().SetIndex( rSel.nEndPos ); - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateSel: incorrect selection!" ); - return aSel; -} - -inline VirtualDevice* ImpEditEngine::GetVirtualDevice( const MapMode& rMapMode, DrawModeFlags nDrawMode ) -{ - if ( !pVirtDev ) - pVirtDev = VclPtr<VirtualDevice>::Create(); - - if ( ( pVirtDev->GetMapMode().GetMapUnit() != rMapMode.GetMapUnit() ) || - ( pVirtDev->GetMapMode().GetScaleX() != rMapMode.GetScaleX() ) || - ( pVirtDev->GetMapMode().GetScaleY() != rMapMode.GetScaleY() ) ) - { - MapMode aMapMode( rMapMode ); - aMapMode.SetOrigin( Point( 0, 0 ) ); - pVirtDev->SetMapMode( aMapMode ); - } - - pVirtDev->SetDrawMode( nDrawMode ); - - return pVirtDev; -} - -inline void ImpEditEngine::IdleFormatAndUpdate( EditView* pCurView ) -{ - aIdleFormatter.DoIdleFormat( pCurView ); -} - -inline EditUndoManager& ImpEditEngine::GetUndoManager() -{ - if ( !pUndoManager ) - { - pUndoManager = new EditUndoManager(); - pUndoManager->SetEditEngine(pEditEngine); - } - return *pUndoManager; -} - -inline SfxUndoManager* ImpEditEngine::SetUndoManager(SfxUndoManager* pNew) -{ - SfxUndoManager* pRetval = pUndoManager; - - if(pUndoManager) - { - pUndoManager->SetEditEngine(nullptr); - } - - pUndoManager = dynamic_cast< EditUndoManager* >(pNew); - - if(pUndoManager) - { - pUndoManager->SetEditEngine(pEditEngine); - } - - return pRetval; -} - -inline const ParaPortion& ImpEditEngine::FindParaPortion( const ContentNode* pNode ) const -{ - sal_Int32 nPos = aEditDoc.GetPos( pNode ); - DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); - return GetParaPortions()[ nPos ]; -} - -inline ParaPortion& ImpEditEngine::FindParaPortion( ContentNode const * pNode ) -{ - sal_Int32 nPos = aEditDoc.GetPos( pNode ); - DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); - return GetParaPortions()[ nPos ]; -} - -inline void ImpEditEngine::GetCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const -{ - rX = nStretchX; - rY = nStretchY; -} - -inline short ImpEditEngine::GetXValue( short nXValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchX == 100 ) ) - return nXValue; - - return static_cast<short>(static_cast<tools::Long>(nXValue)*nStretchX/100); -} - - -inline tools::Long ImpEditEngine::GetXValue( tools::Long nXValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchX == 100 ) ) - return nXValue; - - return nXValue*nStretchX/100; -} - -inline short ImpEditEngine::GetYValue( short nYValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchY == 100 ) ) - return nYValue; - - return static_cast<short>(static_cast<tools::Long>(nYValue)*nStretchY/100); -} - -inline sal_uInt16 ImpEditEngine::GetYValue( sal_uInt16 nYValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchY == 100 ) ) - return nYValue; - - return static_cast<sal_uInt16>(static_cast<tools::Long>(nYValue)*nStretchY/100); -} - -inline PointerStyle ImpEditView::GetPointer() -{ - if ( !mxPointer ) - { - mxPointer = IsVertical() ? PointerStyle::TextVertical : PointerStyle::Text; - return *mxPointer; - } - - if(PointerStyle::Text == *mxPointer && IsVertical()) - { - mxPointer = PointerStyle::TextVertical; - } - else if(PointerStyle::TextVertical == *mxPointer && !IsVertical()) - { - mxPointer = PointerStyle::Text; - } - - return *mxPointer; -} - -inline vcl::Cursor* ImpEditView::GetCursor() -{ - if ( !pCursor ) - pCursor.reset( new vcl::Cursor ); - return pCursor.get(); -} - void ConvertItem( std::unique_ptr<SfxPoolItem>& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit ); void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit = nullptr, const MapUnit* pDestUnit = nullptr ); AsianCompressionFlags GetCharTypeForCompression( sal_Unicode cChar ); -Point Rotate( const Point& rPoint, Degree10 nOrientation, const Point& rOrigin ); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index 4bc8a570b9c3..da4d851b3315 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -30,6 +30,8 @@ #include "eeobj.hxx" #include <editeng/txtrange.hxx> #include <sfx2/app.hxx> +#include <sfx2/mieclip.hxx> +#include <sfx2/viewsh.hxx> #include <svtools/colorcfg.hxx> #include <svl/ctloptions.hxx> #include <unotools/securityoptions.hxx> @@ -39,6 +41,7 @@ #include <editeng/adjustitem.hxx> #include <editeng/frmdiritem.hxx> #include <editeng/justifyitem.hxx> +#include <editeng/udlnitem.hxx> #include <com/sun/star/i18n/CharacterIteratorMode.hpp> #include <com/sun/star/i18n/WordType.hpp> @@ -48,6 +51,7 @@ #include <com/sun/star/system/SystemShellExecute.hpp> #include <com/sun/star/system/SystemShellExecuteFlags.hpp> #include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/i18n/UnicodeType.hpp> #include <rtl/character.hxx> @@ -57,12 +61,13 @@ #include <sot/exchange.hxx> #include <sot/formats.hxx> #include <svl/asiancfg.hxx> +#include <svl/voiditem.hxx> #include <i18nutil/unicode.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <comphelper/flagguard.hxx> #include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> -#include <unotools/configmgr.hxx> +#include <comphelper/configuration.hxx> #include <unicode/ubidi.h> #include <algorithm> @@ -84,70 +89,71 @@ static sal_uInt16 lcl_CalcExtraSpace( const SvxLineSpacingItem& rLSItem ) return nExtra; } +constexpr tools::Long constMaxPaperSize = 0x7FFFFFFF; + ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) : pSharedVCL(EditDLL::Get().GetSharedVclResources()), - aPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ), - aMinAutoPaperSize( 0x0, 0x0 ), - aMaxAutoPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ), - aEditDoc( pItemPool ), - pEditEngine(pEE), - pActiveView(nullptr), - pStylePool(nullptr), - pTextObjectPool(nullptr), - pUndoManager(nullptr), - aWordDelimiters(" .,;:-`'?!_=\"{}()[]"), + maPaperSize(constMaxPaperSize, constMaxPaperSize), + maMinAutoPaperSize(0, 0), + maMaxAutoPaperSize(constMaxPaperSize, constMaxPaperSize), + maEditDoc( pItemPool ), + mpEditEngine(pEE), + mpActiveView(nullptr), + mpStylePool(nullptr), + mpTextObjectPool(nullptr), + mpUndoManager(nullptr), + maWordDelimiters(" .,;:-`'?!_=\"{}()[]"), maBackgroundColor(COL_AUTO), - nStretchX(100), - nStretchY(100), - nAsianCompressionMode(CharCompressType::NONE), - eDefaultHorizontalTextDirection(EEHorizontalTextDirection::Default), - nBigTextObjectStart(20), - eDefLanguage(LANGUAGE_DONTKNOW), - nCurTextHeight(0), - nCurTextHeightNTP(0), - bKernAsianPunctuation(false), - bAddExtLeading(false), - bIsFormatting(false), - bFormatted(false), - bInSelection(false), - bIsInUndo(false), - bUpdate(true), - bUndoEnabled(true), - bDowning(false), - bUseAutoColor(true), - bForceAutoColor(false), - bCallParaInsertedOrDeleted(false), - bFirstWordCapitalization(true), + mbRoundToNearestPt(false), + mnAsianCompressionMode(CharCompressType::NONE), + meDefaultHorizontalTextDirection(EEHorizontalTextDirection::Default), + mnBigTextObjectStart(20), + meDefLanguage(LANGUAGE_DONTKNOW), + mnCurTextHeight(0), + mnCurTextHeightNTP(0), + maOnlineSpellTimer("editeng::ImpEditEngine aOnlineSpellTimer"), + maStatusTimer("editeng::ImpEditEngine aStatusTimer"), + mbKernAsianPunctuation(false), + mbAddExtLeading(false), + mbIsFormatting(false), + mbFormatted(false), + mbInSelection(false), + mbIsInUndo(false), + mbUpdateLayout(true), + mbUndoEnabled(true), + mbDowning(false), + mbUseAutoColor(true), + mbForceAutoColor(false), + mbCallParaInsertedOrDeleted(false), + mbFirstWordCapitalization(true), mbLastTryMerge(false), mbReplaceLeadingSingleQuotationMark(true), + mbSkipOutsideFormat(false), + mbFuzzing(comphelper::IsFuzzing()), mbNbspRunNext(false) { - aStatus.GetControlWord() = EEControlBits::USECHARATTRIBS | EEControlBits::DOIDLEFORMAT | + maStatus.GetControlWord() = EEControlBits::USECHARATTRIBS | EEControlBits::DOIDLEFORMAT | EEControlBits::PASTESPECIAL | EEControlBits::UNDOATTRIBS | - EEControlBits::ALLOWBIGOBJS | EEControlBits::RTFSTYLESHEETS | - EEControlBits::FORMAT100; + EEControlBits::ALLOWBIGOBJS | EEControlBits::RTFSTYLESHEETS; - aSelEngine.SetFunctionSet( &aSelFuncSet ); + maSelEngine.SetFunctionSet(&maSelFuncSet); - aStatusTimer.SetTimeout( 200 ); - aStatusTimer.SetInvokeHandler( LINK( this, ImpEditEngine, StatusTimerHdl ) ); - aStatusTimer.SetDebugName( "editeng::ImpEditEngine aStatusTimer" ); + maStatusTimer.SetTimeout(200); + maStatusTimer.SetInvokeHandler(LINK(this, ImpEditEngine, StatusTimerHdl)); - aIdleFormatter.SetPriority( TaskPriority::REPAINT ); - aIdleFormatter.SetInvokeHandler( LINK( this, ImpEditEngine, IdleFormatHdl ) ); - aIdleFormatter.SetDebugName( "editeng::ImpEditEngine aIdleFormatter" ); + maIdleFormatter.SetPriority(TaskPriority::REPAINT); + maIdleFormatter.SetInvokeHandler(LINK(this, ImpEditEngine, IdleFormatHdl)); - aOnlineSpellTimer.SetTimeout( 100 ); - aOnlineSpellTimer.SetInvokeHandler( LINK( this, ImpEditEngine, OnlineSpellHdl ) ); - aOnlineSpellTimer.SetDebugName( "editeng::ImpEditEngine aOnlineSpellTimer" ); + maOnlineSpellTimer.SetTimeout(100); + maOnlineSpellTimer.SetInvokeHandler(LINK( this, ImpEditEngine, OnlineSpellHdl)); // Access data already from here on! SetRefDevice( nullptr ); InitDoc( false ); - bCallParaInsertedOrDeleted = true; + mbCallParaInsertedOrDeleted = true; - aEditDoc.SetModifyHdl( LINK( this, ImpEditEngine, DocModified ) ); + maEditDoc.SetModifyHdl( LINK( this, ImpEditEngine, DocModified ) ); StartListening(*SfxGetpApp()); } @@ -157,43 +163,42 @@ void ImpEditEngine::Dispose() auto pApp = SfxApplication::Get(); if(pApp) EndListening(*pApp); - pVirtDev.disposeAndClear(); + mpVirtDev.disposeAndClear(); mpOwnDev.disposeAndClear(); pSharedVCL.reset(); } ImpEditEngine::~ImpEditEngine() { - aStatusTimer.Stop(); - aOnlineSpellTimer.Stop(); - aIdleFormatter.Stop(); + maStatusTimer.Stop(); + maOnlineSpellTimer.Stop(); + maIdleFormatter.Stop(); // Destroying templates may otherwise cause unnecessary formatting, // when a parent template is destroyed. // And this after the destruction of the data! - bDowning = true; - SetUpdateMode( false ); + mbDowning = true; + SetUpdateLayout( false ); Dispose(); - // it's only legal to delete the pUndoManager if it was created by + // it's only legal to delete the mpUndoManager if it was created by // ImpEditEngine; if it was set by SetUndoManager() it must be cleared // before destroying the ImpEditEngine! - assert(!pUndoManager || typeid(*pUndoManager) == typeid(EditUndoManager)); - delete pUndoManager; - pTextRanger.reset(); + assert(!mpUndoManager || typeid(*mpUndoManager) == typeid(EditUndoManager)); + delete mpUndoManager; + mpTextRanger.reset(); mpIMEInfos.reset(); - pCTLOptions.reset(); - pSpellInfo.reset(); + mpSpellInfo.reset(); } -void ImpEditEngine::SetRefDevice( OutputDevice* pRef ) +void ImpEditEngine::SetRefDevice(OutputDevice* pRef) { if (pRef) - pRefDev = pRef; + mpRefDev = pRef; else - pRefDev = pSharedVCL->GetVirtualDevice(); + mpRefDev = pSharedVCL->GetVirtualDevice(); - nOnePixelInRef = static_cast<sal_uInt16>(pRefDev->PixelToLogic( Size( 1, 0 ) ).Width()); + mnOnePixelInRef = static_cast<sal_uInt16>(mpRefDev->PixelToLogic( Size( 1, 0 ) ).Width()); if ( IsFormatted() ) { @@ -209,12 +214,12 @@ void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode ) mpOwnDev.disposeAndClear(); mpOwnDev = VclPtr<VirtualDevice>::Create(); - pRefDev = mpOwnDev; - pRefDev->SetMapMode(MapMode(MapUnit::MapTwip)); - SetRefDevice( pRefDev ); + mpRefDev = mpOwnDev; + mpRefDev->SetMapMode(MapMode(MapUnit::MapTwip)); + SetRefDevice(mpRefDev); - pRefDev->SetMapMode( rMapMode ); - nOnePixelInRef = static_cast<sal_uInt16>(pRefDev->PixelToLogic( Size( 1, 0 ) ).Width()); + mpRefDev->SetMapMode( rMapMode ); + mnOnePixelInRef = static_cast<sal_uInt16>(mpRefDev->PixelToLogic(Size(1, 0)).Width()); if ( IsFormatted() ) { FormatFullDoc(); @@ -224,23 +229,23 @@ void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode ) void ImpEditEngine::InitDoc(bool bKeepParaAttribs) { - sal_Int32 nParas = aEditDoc.Count(); + sal_Int32 nParas = maEditDoc.Count(); for ( sal_Int32 n = bKeepParaAttribs ? 1 : 0; n < nParas; n++ ) { - if ( aEditDoc[n]->GetStyleSheet() ) - EndListening( *aEditDoc[n]->GetStyleSheet() ); + if (maEditDoc.GetObject(n)->GetStyleSheet()) + EndListening( *maEditDoc.GetObject(n)->GetStyleSheet() ); } if ( bKeepParaAttribs ) - aEditDoc.RemoveText(); + maEditDoc.RemoveText(); else - aEditDoc.Clear(); + maEditDoc.Clear(); GetParaPortions().Reset(); - GetParaPortions().Insert(0, ParaPortion( aEditDoc[0] )); + GetParaPortions().Insert(0, std::make_unique<ParaPortion>(maEditDoc.GetObject(0))); - bFormatted = false; + mbFormatted = false; if ( IsCallParaInsertedOrDeleted() ) { @@ -249,7 +254,7 @@ void ImpEditEngine::InitDoc(bool bKeepParaAttribs) } if ( GetStatus().DoOnlineSpelling() ) - aEditDoc.GetObject( 0 )->CreateWrongList(); + maEditDoc.GetObject( 0 )->CreateWrongList(); } EditPaM ImpEditEngine::DeleteSelected(const EditSelection& rSel) @@ -264,12 +269,12 @@ OUString ImpEditEngine::GetSelected( const EditSelection& rSel ) const return OUString(); EditSelection aSel( rSel ); - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); ContentNode* pStartNode = aSel.Min().GetNode(); ContentNode* pEndNode = aSel.Max().GetNode(); - sal_Int32 nStartNode = aEditDoc.GetPos( pStartNode ); - sal_Int32 nEndNode = aEditDoc.GetPos( pEndNode ); + sal_Int32 nStartNode = maEditDoc.GetPos( pStartNode ); + sal_Int32 nEndNode = maEditDoc.GetPos( pEndNode ); OSL_ENSURE( nStartNode <= nEndNode, "Selection not sorted ?" ); @@ -279,8 +284,8 @@ OUString ImpEditEngine::GetSelected( const EditSelection& rSel ) const // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - OSL_ENSURE( aEditDoc.GetObject( nNode ), "Node not found: GetSelected" ); - const ContentNode* pNode = aEditDoc.GetObject( nNode ); + const ContentNode* pNode = maEditDoc.GetObject( nNode ); + assert(pNode); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart! @@ -302,33 +307,33 @@ bool ImpEditEngine::MouseButtonDown( const MouseEvent& rMEvt, EditView* pView ) GetSelEngine().SelMouseButtonDown( rMEvt ); // Special treatment - EditSelection aCurSel( pView->pImpEditView->GetEditSelection() ); - if ( !rMEvt.IsShift() ) + EditSelection aCurSel( pView->getImpl().GetEditSelection() ); + if ( rMEvt.IsShift() ) + return true; + + if ( rMEvt.GetClicks() == 2 ) { - if ( rMEvt.GetClicks() == 2 ) - { - // So that the SelectionEngine knows about the anchor. - aSelEngine.CursorPosChanging( true, false ); - - EditSelection aNewSelection( SelectWord( aCurSel ) ); - pView->pImpEditView->DrawSelectionXOR(); - pView->pImpEditView->SetEditSelection( aNewSelection ); - pView->pImpEditView->DrawSelectionXOR(); - pView->ShowCursor(); - } - else if ( rMEvt.GetClicks() == 3 ) - { - // So that the SelectionEngine knows about the anchor. - aSelEngine.CursorPosChanging( true, false ); - - EditSelection aNewSelection( aCurSel ); - aNewSelection.Min().SetIndex( 0 ); - aNewSelection.Max().SetIndex( aCurSel.Min().GetNode()->Len() ); - pView->pImpEditView->DrawSelectionXOR(); - pView->pImpEditView->SetEditSelection( aNewSelection ); - pView->pImpEditView->DrawSelectionXOR(); - pView->ShowCursor(); - } + // So that the SelectionEngine knows about the anchor. + maSelEngine.CursorPosChanging( true, false ); + + EditSelection aNewSelection( SelectWord( aCurSel ) ); + pView->getImpl().DrawSelectionXOR(); + pView->getImpl().SetEditSelection( aNewSelection ); + pView->getImpl().DrawSelectionXOR(); + pView->ShowCursor(); + } + else if ( rMEvt.GetClicks() == 3 ) + { + // So that the SelectionEngine knows about the anchor. + maSelEngine.CursorPosChanging( true, false ); + + EditSelection aNewSelection( aCurSel ); + aNewSelection.Min().SetIndex( 0 ); + aNewSelection.Max().SetIndex( aCurSel.Min().GetNode()->Len() ); + pView->getImpl().DrawSelectionXOR(); + pView->getImpl().SetEditSelection( aNewSelection ); + pView->getImpl().DrawSelectionXOR(); + pView->ShowCursor(); } return true; } @@ -341,61 +346,69 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) SetActiveView( pView ); if ( rCEvt.GetCommand() == CommandEventId::StartExtTextInput ) { - pView->DeleteSelected(); - mpIMEInfos.reset(); - EditPaM aPaM = pView->GetImpEditView()->GetEditSelection().Max(); - OUString aOldTextAfterStartPos = aPaM.GetNode()->Copy( aPaM.GetIndex() ); - sal_Int32 nMax = aOldTextAfterStartPos.indexOf( CH_FEATURE ); - if ( nMax != -1 ) // don't overwrite features! - aOldTextAfterStartPos = aOldTextAfterStartPos.copy( 0, nMax ); - mpIMEInfos.reset( new ImplIMEInfos( aPaM, aOldTextAfterStartPos ) ); - mpIMEInfos->bWasCursorOverwrite = !pView->IsInsertMode(); - UndoActionStart( EDITUNDO_INSERT ); + if (!pView->IsReadOnly()) + { + pView->DeleteSelected(); + mpIMEInfos.reset(); + EditPaM aPaM = pView->getImpl().GetEditSelection().Max(); + OUString aOldTextAfterStartPos = aPaM.GetNode()->Copy( aPaM.GetIndex() ); + sal_Int32 nMax = aOldTextAfterStartPos.indexOf( CH_FEATURE ); + if ( nMax != -1 ) // don't overwrite features! + aOldTextAfterStartPos = aOldTextAfterStartPos.copy( 0, nMax ); + mpIMEInfos.reset( new ImplIMEInfos( aPaM, aOldTextAfterStartPos ) ); + mpIMEInfos->bWasCursorOverwrite = !pView->IsInsertMode(); + UndoActionStart( EDITUNDO_INSERT ); + } } else if ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput ) { - OSL_ENSURE( mpIMEInfos, "CommandEventId::EndExtTextInput => No start ?" ); - if( mpIMEInfos ) + if (!pView->IsReadOnly()) { - // #102812# convert quotes in IME text - // works on the last input character, this is especially in Korean text often done - // quotes that are inside of the string are not replaced! - // Borrowed from sw: edtwin.cxx - if ( mpIMEInfos->nLen ) + OSL_ENSURE( mpIMEInfos, "CommandEventId::EndExtTextInput => No start ?" ); + if( mpIMEInfos ) { - EditSelection aSel( mpIMEInfos->aPos ); - aSel.Min().SetIndex( aSel.Min().GetIndex() + mpIMEInfos->nLen-1 ); - aSel.Max().SetIndex( aSel.Max().GetIndex() + mpIMEInfos->nLen ); // #102812# convert quotes in IME text // works on the last input character, this is especially in Korean text often done // quotes that are inside of the string are not replaced! - const sal_Unicode nCharCode = aSel.Min().GetNode()->GetChar( aSel.Min().GetIndex() ); - if ( ( GetStatus().DoAutoCorrect() ) && ( ( nCharCode == '\"' ) || ( nCharCode == '\'' ) ) ) + // Borrowed from sw: edtwin.cxx + if ( mpIMEInfos->nLen ) { - aSel = DeleteSelected( aSel ); - aSel = AutoCorrect( aSel, nCharCode, mpIMEInfos->bWasCursorOverwrite ); - pView->pImpEditView->SetEditSelection( aSel ); + EditSelection aSel( mpIMEInfos->aPos ); + aSel.Min().SetIndex( aSel.Min().GetIndex() + mpIMEInfos->nLen-1 ); + aSel.Max().SetIndex( aSel.Max().GetIndex() + mpIMEInfos->nLen ); + // #102812# convert quotes in IME text + // works on the last input character, this is especially in Korean text often done + // quotes that are inside of the string are not replaced! + // See also tdf#155350 + const sal_Unicode nCharCode = aSel.Min().GetNode()->GetChar( aSel.Min().GetIndex() ); + if ( ( GetStatus().DoAutoCorrect() ) && SvxAutoCorrect::IsAutoCorrectChar(nCharCode) ) + { + aSel = DeleteSelected( aSel ); + aSel = AutoCorrect( aSel, nCharCode, mpIMEInfos->bWasCursorOverwrite ); + pView->getImpl().SetEditSelection( aSel ); + } } - } - ParaPortion& rPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); - rPortion.MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); + ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); + if (pPortion) + pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); - bool bWasCursorOverwrite = mpIMEInfos->bWasCursorOverwrite; + bool bWasCursorOverwrite = mpIMEInfos->bWasCursorOverwrite; - mpIMEInfos.reset(); + mpIMEInfos.reset(); - FormatAndUpdate( pView ); + FormatAndLayout( pView ); - pView->SetInsertMode( !bWasCursorOverwrite ); + pView->SetInsertMode( !bWasCursorOverwrite ); + } + UndoActionEnd(); } - UndoActionEnd(); } else if ( rCEvt.GetCommand() == CommandEventId::ExtTextInput ) { - OSL_ENSURE( mpIMEInfos, "CommandEventId::ExtTextInput => No Start ?" ); - if( mpIMEInfos ) + if( mpIMEInfos && !pView->IsReadOnly()) { + OSL_ENSURE( mpIMEInfos, "CommandEventId::ExtTextInput => No Start ?" ); const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData(); if ( !pData->IsOnlyCursorChanged() ) @@ -444,9 +457,9 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) mpIMEInfos->nLen = pData->GetText().getLength(); } - ParaPortion& rPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); - rPortion.MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); - FormatAndUpdate( pView ); + ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); + pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); + FormatAndLayout( pView ); } EditSelection aNewSel = EditPaM( mpIMEInfos->aPos.GetNode(), mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() ); @@ -466,7 +479,7 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) { if (mpIMEInfos) { - EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() ); + EditPaM aPaM( pView->getImpl().GetEditSelection().Max() ); tools::Rectangle aR1 = PaMtoEditCursor( aPaM ); sal_Int32 nInputEnd = mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen; @@ -481,8 +494,8 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) const EditLine& rLine = pParaPortion->GetLines()[nLine]; if ( nInputEnd > rLine.GetEnd() ) nInputEnd = rLine.GetEnd(); - tools::Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), GetCursorFlags::EndOfLine ); - tools::Rectangle aRect = pView->GetImpEditView()->GetWindowPos( aR1 ); + tools::Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), CursorFlags{ .bEndOfLine = true }); + tools::Rectangle aRect = pView->getImpl().GetWindowPos( aR1 ); auto nExtTextInputWidth = aR2.Left() - aR1.Right(); if (EditViewCallbacks* pEditViewCallbacks = pView->getEditViewCallbacks()) pEditViewCallbacks->EditViewCursorRect(aRect, nExtTextInputWidth); @@ -525,7 +538,7 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) if ( aSelection.nStartPara != aSelection.nEndPara ) { - sal_Int32 aParaLen = pEditEngine->GetTextLen( aSelection.nStartPara ); + sal_Int32 aParaLen = mpEditEngine->GetTextLen( aSelection.nStartPara ); aSelection.nEndPara = aSelection.nStartPara; aSelection.nEndPos = aParaLen; pView->SetSelection( aSelection ); @@ -536,7 +549,7 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) { if (mpIMEInfos) { - EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() ); + EditPaM aPaM( pView->getImpl().GetEditSelection().Max() ); if ( !IsFormatted() ) FormatDoc(); @@ -567,11 +580,9 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) { if (rInfo.pLine->IsIn(n)) { - tools::Rectangle aR = GetEditCursor(pParaPortion, rInfo.pLine, n, - GetCursorFlags::NONE); - aR.Move(getLeftDirectionAware(rInfo.aArea), - getTopDirectionAware(rInfo.aArea)); - aRects[n - nMinPos] = pView->GetImpEditView()->GetWindowPos(aR); + tools::Rectangle aR = GetEditCursor(*pParaPortion, *rInfo.pLine, n, CursorFlags()); + aR.Move(getTopLeftDocOffset(rInfo.aArea)); + aRects[n - nMinPos] = pView->getImpl().GetWindowPos(aR); } } } @@ -601,37 +612,40 @@ bool ImpEditEngine::MouseButtonUp( const MouseEvent& rMEvt, EditView* pView ) // non-tiled-rendering case, but it has been here since 2000 (and before) // so who knows what corner case it was supposed to solve back then if (!comphelper::LibreOfficeKit::isActive()) - bInSelection = false; + mbInSelection = false; // Special treatments - EditSelection aCurSel( pView->pImpEditView->GetEditSelection() ); - if ( !aCurSel.HasRange() ) + EditSelection aCurSel( pView->getImpl().GetEditSelection() ); + if ( aCurSel.HasRange() ) + return true; + + if ( ( rMEvt.GetClicks() != 1 ) || !rMEvt.IsLeft() || rMEvt.IsMod2() ) + return true; + + const OutputDevice& rOutDev = pView->getEditViewCallbacks() ? pView->getEditViewCallbacks()->EditViewOutputDevice() : *pView->GetWindow()->GetOutDev(); + Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel()); + const SvxFieldItem* pFld = pView->GetField(aLogicClick); + if (!pFld) + return true; + + // tdf#121039 When in edit mode, editeng is responsible for opening the URL on mouse click + bool bUrlOpened = GetEditEnginePtr()->FieldClicked( *pFld ); + if (bUrlOpened) + return true; + + if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) { - if ( ( rMEvt.GetClicks() == 1 ) && rMEvt.IsLeft() && !rMEvt.IsMod2() ) + bool bCtrlClickHappened = rMEvt.IsMod1(); + bool bCtrlClickSecOption + = SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink); + if ((bCtrlClickHappened && bCtrlClickSecOption) + || (!bCtrlClickHappened && !bCtrlClickSecOption)) { - const OutputDevice& rOutDev = pView->getEditViewCallbacks() ? pView->getEditViewCallbacks()->EditViewOutputDevice() : *pView->GetWindow()->GetOutDev(); - Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel()); - if (const SvxFieldItem* pFld = pView->GetField(aLogicClick)) - { - // tdf#121039 When in edit mode, editeng is responsible for opening the URL on mouse click - if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) - { - SvtSecurityOptions aSecOpt; - bool bCtrlClickHappened = rMEvt.IsMod1(); - bool bCtrlClickSecOption - = aSecOpt.IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink); - if ((bCtrlClickHappened && bCtrlClickSecOption) - || (!bCtrlClickHappened && !bCtrlClickSecOption)) - { - css::uno::Reference<css::system::XSystemShellExecute> exec( - css::system::SystemShellExecute::create( - comphelper::getProcessComponentContext())); - exec->execute(pUrlField->GetURL(), OUString(), - css::system::SystemShellExecuteFlags::DEFAULTS); - } - } - GetEditEnginePtr()->FieldClicked( *pFld ); - } + css::uno::Reference<css::system::XSystemShellExecute> exec( + css::system::SystemShellExecute::create( + comphelper::getProcessComponentContext())); + exec->execute(pUrlField->GetURL(), OUString(), + css::system::SystemShellExecuteFlags::DEFAULTS); } } return true; @@ -660,33 +674,39 @@ void ImpEditEngine::Clear() { InitDoc( false ); - EditPaM aPaM = aEditDoc.GetStartPaM(); + EditPaM aPaM = maEditDoc.GetStartPaM(); EditSelection aSel( aPaM ); - nCurTextHeight = 0; - nCurTextHeightNTP = 0; + mnCurTextHeight = 0; + mnCurTextHeightNTP = 0; ResetUndoManager(); - for (size_t nView = aEditViews.size(); nView; ) + for (size_t nView = maEditViews.size(); nView; ) { - EditView* pView = aEditViews[--nView]; - pView->pImpEditView->SetEditSelection( aSel ); + EditView* pView = maEditViews[--nView]; + pView->getImpl().SetEditSelection( aSel ); } + + // Related: tdf#82115 Fix crash when handling input method events. + // The nodes in mpIMEInfos may be deleted in ImpEditEngine::Clear() which + // causes a crash in the CommandEventId::ExtTextInput and + // CommandEventId::EndExtTextInput event handlers. + mpIMEInfos.reset(); } EditPaM ImpEditEngine::RemoveText() { InitDoc( true ); - EditPaM aStartPaM = aEditDoc.GetStartPaM(); + EditPaM aStartPaM = maEditDoc.GetStartPaM(); EditSelection aEmptySel( aStartPaM, aStartPaM ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - pView->pImpEditView->SetEditSelection( aEmptySel ); + pView->getImpl().SetEditSelection( aEmptySel ); } ResetUndoManager(); - return aEditDoc.GetStartPaM(); + return maEditDoc.GetStartPaM(); } @@ -703,22 +723,23 @@ void ImpEditEngine::SetText(const OUString& rText) if (!rText.isEmpty()) aPaM = ImpInsertText( aEmptySel, rText ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - pView->pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) ); + pView->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); // If no text then also no Format&Update // => The text remains. - if (rText.isEmpty() && GetUpdateMode()) + if (rText.isEmpty() && IsUpdateLayout()) { tools::Rectangle aTmpRect( pView->GetOutputArea().TopLeft(), - Size( aPaperSize.Width(), nCurTextHeight ) ); + Size( maPaperSize.Width(), mnCurTextHeight ) ); aTmpRect.Intersection( pView->GetOutputArea() ); pView->InvalidateWindow( aTmpRect ); } } - if (rText.isEmpty()) { // otherwise it must be invalidated later, !bFormatted is enough. - nCurTextHeight = 0; - nCurTextHeightNTP = 0; + if (rText.isEmpty()) // otherwise it must be invalidated later, !bFormatted is enough. + { + mnCurTextHeight = 0; + mnCurTextHeightNTP = 0; } EnableUndo( bUndoCurrentlyEnabled ); OSL_ENSURE( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo after SetText?" ); @@ -729,7 +750,7 @@ const SfxItemSet& ImpEditEngine::GetEmptyItemSet() const { if ( !pEmptyItemSet ) { - pEmptyItemSet = std::make_unique<SfxItemSet>(const_cast<SfxItemPool&>(aEditDoc.GetItemPool()), svl::Items<EE_ITEMS_START, EE_ITEMS_END>{}); + pEmptyItemSet = std::make_unique<SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END>>(const_cast<SfxItemPool&>(maEditDoc.GetItemPool())); for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++) { pEmptyItemSet->ClearItem( nWhich ); @@ -741,18 +762,9 @@ const SfxItemSet& ImpEditEngine::GetEmptyItemSet() const // MISC -void ImpEditEngine::CursorMoved( const ContentNode* pPrevNode ) -{ - // Delete empty attributes, but only if paragraph is not empty! - if (pPrevNode->GetCharAttribs().HasEmptyAttribs() && pPrevNode->Len()) - { - const_cast<ContentNode*>(pPrevNode)->GetCharAttribs().DeleteEmptyAttribs(aEditDoc.GetItemPool()); - } -} - void ImpEditEngine::TextModified() { - bFormatted = false; + mbFormatted = false; if ( GetNotifyHdl().IsSet() ) { @@ -766,20 +778,21 @@ void ImpEditEngine::ParaAttribsChanged( ContentNode const * pNode, bool bIgnoreU { assert(pNode && "ParaAttribsChanged: Which one?"); - aEditDoc.SetModified( true ); - bFormatted = false; + maEditDoc.SetModified( true ); + mbFormatted = false; - ParaPortion& rPortion = FindParaPortion( pNode ); - rPortion.MarkSelectionInvalid( 0 ); + ParaPortion* pPortion = FindParaPortion( pNode ); + assert(pPortion); + pPortion->MarkSelectionInvalid( 0 ); - sal_Int32 nPara = aEditDoc.GetPos( pNode ); - if ( bIgnoreUndoCheck || pEditEngine->IsInUndo() ) - pEditEngine->ParaAttribsChanged( nPara ); + sal_Int32 nPara = maEditDoc.GetPos( pNode ); + if (bIgnoreUndoCheck || mpEditEngine->IsInUndo()) + mpEditEngine->ParaAttribsChanged( nPara ); ParaPortion* pNextPortion = GetParaPortions().SafeGetObject( nPara+1 ); // => is formatted again anyway, if Invalid. if ( pNextPortion && !pNextPortion->IsInvalid() ) - CalcHeight( pNextPortion ); + CalcHeight(*pNextPortion); } @@ -791,14 +804,14 @@ EditSelection const & ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, Edit // Actually, only necessary for up/down, but whatever. CheckIdleFormatter(); - EditPaM aPaM( pEditView->pImpEditView->GetEditSelection().Max() ); + EditPaM aPaM(pEditView->getImpl().GetEditSelection().Max()); EditPaM aOldPaM( aPaM ); TextDirectionality eTextDirection = TextDirectionality::LeftToRight_TopToBottom; - if (IsVertical() && IsTopToBottom()) + if (IsEffectivelyVertical() && IsTopToBottom()) eTextDirection = TextDirectionality::TopToBottom_RightToLeft; - else if (IsVertical() && !IsTopToBottom()) + else if (IsEffectivelyVertical() && !IsTopToBottom()) eTextDirection = TextDirectionality::BottomToTop_LeftToRight; else if ( IsRightToLeft( GetEditDoc().GetPos( aPaM.GetNode() ) ) ) eTextDirection = TextDirectionality::RightToLeft_TopToBottom; @@ -931,41 +944,41 @@ EditSelection const & ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, Edit break; } - if ( aOldPaM != aPaM ) + if ( aOldPaM != aPaM && nullptr != aOldPaM.GetNode() ) { - CursorMoved( aOldPaM.GetNode() ); + aOldPaM.GetNode()->checkAndDeleteEmptyAttribs(); } // May cause, a CreateAnchor or deselection all - aSelEngine.SetCurView( pEditView ); - aSelEngine.CursorPosChanging( bKeyModifySelection, aTranslatedKeyEvent.GetKeyCode().IsMod1() ); - EditPaM aOldEnd( pEditView->pImpEditView->GetEditSelection().Max() ); + maSelEngine.SetCurView(pEditView); + maSelEngine.CursorPosChanging( bKeyModifySelection, aTranslatedKeyEvent.GetKeyCode().IsMod1() ); + EditPaM aOldEnd(pEditView->getImpl().GetEditSelection().Max()); { - EditSelection aNewSelection(pEditView->pImpEditView->GetEditSelection()); + EditSelection aNewSelection(pEditView->getImpl().GetEditSelection()); aNewSelection.Max() = aPaM; - pEditView->pImpEditView->SetEditSelection(aNewSelection); - // const_cast<EditPaM&>(pEditView->pImpEditView->GetEditSelection().Max()) = aPaM; + pEditView->getImpl().SetEditSelection(aNewSelection); + // const_cast<EditPaM&>(pEditView->getImpl().GetEditSelection().Max()) = aPaM; } if ( bKeyModifySelection ) { // Then the selection is expanded ... or the whole selection is painted in case of tiled rendering. - EditSelection aTmpNewSel( comphelper::LibreOfficeKit::isActive() ? pEditView->pImpEditView->GetEditSelection().Min() : aOldEnd, aPaM ); - pEditView->pImpEditView->DrawSelectionXOR( aTmpNewSel ); + EditSelection aTmpNewSel( comphelper::LibreOfficeKit::isActive() ? pEditView->getImpl().GetEditSelection().Min() : aOldEnd, aPaM ); + pEditView->getImpl().DrawSelectionXOR( aTmpNewSel ); } else { - EditSelection aNewSelection(pEditView->pImpEditView->GetEditSelection()); + EditSelection aNewSelection(pEditView->getImpl().GetEditSelection()); aNewSelection.Min() = aPaM; - pEditView->pImpEditView->SetEditSelection(aNewSelection); - // const_cast<EditPaM&>(pEditView->pImpEditView->GetEditSelection().Min()) = aPaM; + pEditView->getImpl().SetEditSelection(aNewSelection); + // const_cast<EditPaM&>(pEditView->getImpl().GetEditSelection().Min()) = aPaM; } - return pEditView->pImpEditView->GetEditSelection(); + return pEditView->getImpl().GetEditSelection(); } -EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * pEditView, const EditPaM& rPaM, bool bStart ) +EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * mpEditView, const EditPaM& rPaM, bool bStart ) { EditPaM aPaM( rPaM ); @@ -978,7 +991,7 @@ EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * pEditView, const E const EditLine& rLine = pParaPortion->GetLines()[nLine]; bool bEmptyLine = rLine.GetStart() == rLine.GetEnd(); - pEditView->pImpEditView->nExtraCursorFlags = GetCursorFlags::NONE; + mpEditView->getImpl().maExtraCursorFlags = CursorFlags(); if ( !bEmptyLine ) { @@ -1004,15 +1017,15 @@ EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * pEditView, const E if ( bStart ) { - pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 0 : 1 ); + mpEditView->getImpl().SetCursorBidiLevel( bPortionRTL ? 0 : 1 ); // Maybe we must be *behind* the character - if ( bPortionRTL && pEditView->IsInsertMode() ) + if (bPortionRTL && mpEditView->IsInsertMode()) aPaM.SetIndex( aPaM.GetIndex()+1 ); } else { - pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 1 : 0 ); - if ( !bPortionRTL && pEditView->IsInsertMode() ) + mpEditView->getImpl().SetCursorBidiLevel( bPortionRTL ? 1 : 0 ); + if ( !bPortionRTL && mpEditView->IsInsertMode() ) aPaM.SetIndex( aPaM.GetIndex()+1 ); } } @@ -1033,7 +1046,7 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const const EditLine& rLine = pParaPortion->GetLines()[nLine]; bool bEmptyLine = rLine.GetStart() == rLine.GetEnd(); - pEditView->pImpEditView->nExtraCursorFlags = GetCursorFlags::NONE; + pEditView->getImpl().maExtraCursorFlags = CursorFlags(); bool bParaRTL = IsRightToLeft( nPara ); @@ -1084,12 +1097,12 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const if (bVisualToLeft != bool(nRTLLevel % 2)) { aPaM = CursorLeft( aPaM, nCharacterIteratorMode ); - pEditView->pImpEditView->SetCursorBidiLevel( 1 ); + pEditView->getImpl().SetCursorBidiLevel( 1 ); } else { aPaM = CursorRight( aPaM, nCharacterIteratorMode ); - pEditView->pImpEditView->SetCursorBidiLevel( 0 ); + pEditView->getImpl().SetCursorBidiLevel( 0 ); } bDone = true; } @@ -1129,13 +1142,13 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine ) { aPaM.SetIndex( rLine.GetStart() + ubidi_getLogicalIndex( pBidi, nVisPos, &nError ) ); - pEditView->pImpEditView->SetCursorBidiLevel( 0 ); + pEditView->getImpl().SetCursorBidiLevel( 0 ); } } else { bool bWasBehind = false; - bool bBeforePortion = !nPosInLine || pEditView->pImpEditView->GetCursorBidiLevel() == 1; + bool bBeforePortion = !nPosInLine || pEditView->getImpl().GetCursorBidiLevel() == 1; if ( nPosInLine && ( !bBeforePortion ) ) // before the next portion bWasBehind = true; // step one back, otherwise visual will be unusable when rtl portion follows. @@ -1174,7 +1187,7 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const else if ( !bVisualToLeft && bRTLPortion && ( bWasBehind || !_rTextPortion.IsRightToLeft() ) ) aPaM.SetIndex( aPaM.GetIndex()+1 ); - pEditView->pImpEditView->SetCursorBidiLevel( _nPortionStart ); + pEditView->getImpl().SetCursorBidiLevel( _nPortionStart ); } } @@ -1255,24 +1268,25 @@ EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView const * pView ) { assert(pView && "No View - No Cursor Movement!"); - const ParaPortion& rPPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rPPortion.GetLineNumber( rPaM.GetIndex() ); - const EditLine& rLine = rPPortion.GetLines()[nLine]; + const ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() ); + assert(pPPortion); + sal_Int32 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() ); + const EditLine& rLine = pPPortion->GetLines()[nLine]; tools::Long nX; - if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW ) + if ( pView->getImpl().mnTravelXPos == TRAVEL_X_DONTKNOW ) { - nX = GetXPos( &rPPortion, &rLine, rPaM.GetIndex() ); - pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef; + nX = GetXPos(*pPPortion, rLine, rPaM.GetIndex()); + pView->getImpl().mnTravelXPos = nX + mnOnePixelInRef; } else - nX = pView->pImpEditView->nTravelXPos; + nX = pView->getImpl().mnTravelXPos; EditPaM aNewPaM( rPaM ); if ( nLine ) // same paragraph { - const EditLine& rPrevLine = rPPortion.GetLines()[nLine-1]; - aNewPaM.SetIndex( GetChar( &rPPortion, &rPrevLine, nX ) ); + const EditLine& rPrevLine = pPPortion->GetLines()[nLine-1]; + aNewPaM.SetIndex(GetChar(*pPPortion, rPrevLine, nX)); // If a previous automatically wrapped line, and one has to be exactly // at the end of this line, the cursor lands on the current line at the // beginning. See Problem: Last character of an automatically wrapped @@ -1282,12 +1296,12 @@ EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView const * pView ) } else // previous paragraph { - const ParaPortion* pPrevPortion = GetPrevVisPortion( &rPPortion ); + const ParaPortion* pPrevPortion = GetPrevVisPortion( pPPortion ); if ( pPrevPortion ) { const EditLine& rLine2 = pPrevPortion->GetLines()[pPrevPortion->GetLines().Count()-1]; aNewPaM.SetNode( pPrevPortion->GetNode() ); - aNewPaM.SetIndex( GetChar( pPrevPortion, &rLine2, nX+nOnePixelInRef ) ); + aNewPaM.SetIndex(GetChar(*pPrevPortion, rLine2, nX + mnOnePixelInRef)); } } @@ -1296,40 +1310,41 @@ EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView const * pView ) EditPaM ImpEditEngine::CursorDown( const EditPaM& rPaM, EditView const * pView ) { - OSL_ENSURE( pView, "No View - No Cursor Movement!" ); + assert(pView); - const ParaPortion& rPPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rPPortion.GetLineNumber( rPaM.GetIndex() ); + const ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() ); + assert(pPPortion); + sal_Int32 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() ); tools::Long nX; - if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW ) + if ( pView->getImpl().mnTravelXPos == TRAVEL_X_DONTKNOW ) { - const EditLine& rLine = rPPortion.GetLines()[nLine]; - nX = GetXPos( &rPPortion, &rLine, rPaM.GetIndex() ); - pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef; + const EditLine& rLine = pPPortion->GetLines()[nLine]; + nX = GetXPos(*pPPortion, rLine, rPaM.GetIndex()); + pView->getImpl().mnTravelXPos = nX + mnOnePixelInRef; } else - nX = pView->pImpEditView->nTravelXPos; + nX = pView->getImpl().mnTravelXPos; EditPaM aNewPaM( rPaM ); - if ( nLine < rPPortion.GetLines().Count()-1 ) + if ( nLine < pPPortion->GetLines().Count()-1 ) { - const EditLine& rNextLine = rPPortion.GetLines()[nLine+1]; - aNewPaM.SetIndex( GetChar( &rPPortion, &rNextLine, nX ) ); + const EditLine& rNextLine = pPPortion->GetLines()[nLine+1]; + aNewPaM.SetIndex(GetChar(*pPPortion, rNextLine, nX)); // Special treatment, see CursorUp ... - if ( ( aNewPaM.GetIndex() == rNextLine.GetEnd() ) && ( aNewPaM.GetIndex() > rNextLine.GetStart() ) && ( aNewPaM.GetIndex() < rPPortion.GetNode()->Len() ) ) + if ( ( aNewPaM.GetIndex() == rNextLine.GetEnd() ) && ( aNewPaM.GetIndex() > rNextLine.GetStart() ) && ( aNewPaM.GetIndex() < pPPortion->GetNode()->Len() ) ) aNewPaM = CursorLeft( aNewPaM ); } else // next paragraph { - const ParaPortion* pNextPortion = GetNextVisPortion( &rPPortion ); + const ParaPortion* pNextPortion = GetNextVisPortion( pPPortion ); if ( pNextPortion ) { const EditLine& rLine = pNextPortion->GetLines()[0]; aNewPaM.SetNode( pNextPortion->GetNode() ); // Never at the very end when several lines, because then a line // below the cursor appears. - aNewPaM.SetIndex( GetChar( pNextPortion, &rLine, nX+nOnePixelInRef ) ); + aNewPaM.SetIndex(GetChar(*pNextPortion, rLine, nX + mnOnePixelInRef)); if ( ( aNewPaM.GetIndex() == rLine.GetEnd() ) && ( aNewPaM.GetIndex() > rLine.GetStart() ) && ( pNextPortion->GetLines().Count() > 1 ) ) aNewPaM = CursorLeft( aNewPaM ); } @@ -1340,9 +1355,10 @@ EditPaM ImpEditEngine::CursorDown( const EditPaM& rPaM, EditView const * pView ) EditPaM ImpEditEngine::CursorStartOfLine( const EditPaM& rPaM ) { - const ParaPortion& rCurPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rCurPortion.GetLineNumber( rPaM.GetIndex() ); - const EditLine& rLine = rCurPortion.GetLines()[nLine]; + const ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() ); + assert(pCurPortion); + sal_Int32 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() ); + const EditLine& rLine = pCurPortion->GetLines()[nLine]; EditPaM aNewPaM( rPaM ); aNewPaM.SetIndex( rLine.GetStart() ); @@ -1351,9 +1367,10 @@ EditPaM ImpEditEngine::CursorStartOfLine( const EditPaM& rPaM ) EditPaM ImpEditEngine::CursorEndOfLine( const EditPaM& rPaM ) { - const ParaPortion& rCurPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rCurPortion.GetLineNumber( rPaM.GetIndex() ); - const EditLine& rLine = rCurPortion.GetLines()[nLine]; + const ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() ); + assert(pCurPortion); + sal_Int32 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() ); + const EditLine& rLine = pCurPortion->GetLines()[nLine]; EditPaM aNewPaM( rPaM ); aNewPaM.SetIndex( rLine.GetEnd() ); @@ -1393,14 +1410,14 @@ EditPaM ImpEditEngine::CursorEndOfParagraph( const EditPaM& rPaM ) EditPaM ImpEditEngine::CursorStartOfDoc() { - EditPaM aPaM( aEditDoc.GetObject( 0 ), 0 ); + EditPaM aPaM( maEditDoc.GetObject( 0 ), 0 ); return aPaM; } EditPaM ImpEditEngine::CursorEndOfDoc() { - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 ); - ParaPortion* pLastPortion = GetParaPortions().SafeGetObject( aEditDoc.Count()-1 ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1 ); + ParaPortion* pLastPortion = GetParaPortions().SafeGetObject( maEditDoc.Count()-1 ); OSL_ENSURE( pLastNode && pLastPortion, "CursorEndOfDoc: Node or Portion not found" ); if (!(pLastNode && pLastPortion)) return EditPaM(); @@ -1410,7 +1427,7 @@ EditPaM ImpEditEngine::CursorEndOfDoc() pLastNode = GetPrevVisNode( pLastPortion->GetNode() ); OSL_ENSURE( pLastNode, "No visible paragraph?" ); if ( !pLastNode ) - pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 ); + pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1 ); } EditPaM aPaM( pLastNode, pLastNode->Len() ); @@ -1422,7 +1439,7 @@ EditPaM ImpEditEngine::PageUp( const EditPaM& rPaM, EditView const * pView ) tools::Rectangle aRect = PaMtoEditCursor( rPaM ); Point aTopLeft = aRect.TopLeft(); aTopLeft.AdjustY( -(pView->GetVisArea().GetHeight() *9/10) ); - aTopLeft.AdjustX(nOnePixelInRef ); + aTopLeft.AdjustX(mnOnePixelInRef); if ( aTopLeft.Y() < 0 ) { aTopLeft.setY( 0 ); @@ -1435,7 +1452,7 @@ EditPaM ImpEditEngine::PageDown( const EditPaM& rPaM, EditView const * pView ) tools::Rectangle aRect = PaMtoEditCursor( rPaM ); Point aBottomRight = aRect.BottomRight(); aBottomRight.AdjustY(pView->GetVisArea().GetHeight() *9/10 ); - aBottomRight.AdjustX(nOnePixelInRef ); + aBottomRight.AdjustX(mnOnePixelInRef); tools::Long nHeight = GetTextHeight(); if ( aBottomRight.Y() > nHeight ) { @@ -1451,8 +1468,8 @@ EditPaM ImpEditEngine::WordLeft( const EditPaM& rPaM ) if ( nCurrentPos == 0 ) { // Previous paragraph... - sal_Int32 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() ); - ContentNode* pPrevNode = aEditDoc.GetObject( --nCurPara ); + sal_Int32 nCurPara = maEditDoc.GetPos( aNewPaM.GetNode() ); + ContentNode* pPrevNode = maEditDoc.GetObject( --nCurPara ); if ( pPrevNode ) { aNewPaM.SetNode( pPrevNode ); @@ -1501,8 +1518,8 @@ EditPaM ImpEditEngine::WordRight( const EditPaM& rPaM, sal_Int16 nWordType ) if ( aNewPaM.GetIndex() >= nMax ) { // Next paragraph ... - sal_Int32 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() ); - ContentNode* pNextNode = aEditDoc.GetObject( ++nCurPara ); + sal_Int32 nCurPara = maEditDoc.GetPos( aNewPaM.GetNode() ); + ContentNode* pNextNode = maEditDoc.GetObject( ++nCurPara ); if ( pNextNode ) { aNewPaM.SetNode( pNextNode ); @@ -1524,8 +1541,11 @@ EditPaM ImpEditEngine::StartOfWord( const EditPaM& rPaM ) lang::Locale aLocale( GetLocale( aTmpPaM ) ); uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() ); + // tdf#135761 - since this function is only used when a selection is deleted at the left, + // change the search preference of the word boundary from forward to backward. + // For further details of a deletion of a selection check ImpEditEngine::DeleteLeftOrRight. i18n::Boundary aBoundary = _xBI->getWordBoundary( - rPaM.GetNode()->GetString(), rPaM.GetIndex(), aLocale, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, true); + rPaM.GetNode()->GetString(), rPaM.GetIndex(), aLocale, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, false); aNewPaM.SetIndex( aBoundary.startPos ); return aNewPaM; @@ -1550,7 +1570,7 @@ EditPaM ImpEditEngine::EndOfWord( const EditPaM& rPaM ) return aNewPaM; } -EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, bool bAcceptStartOfWord ) +EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, bool bAcceptStartOfWord, bool bAcceptEndOfWord ) { EditSelection aNewSel( rCurSel ); EditPaM aPaM( rCurSel.Max() ); @@ -1572,7 +1592,7 @@ EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 aPaM.GetNode()->GetString(), aPaM.GetIndex(), aLocale, nWordType, true); // don't select when cursor at end of word - if ( ( aBoundary.endPos > aPaM.GetIndex() ) && + if ( ( aBoundary.endPos > aPaM.GetIndex() || ( bAcceptEndOfWord && aBoundary.endPos == aPaM.GetIndex() ) ) && ( ( aBoundary.startPos < aPaM.GetIndex() ) || ( bAcceptStartOfWord && ( aBoundary.startPos == aPaM.GetIndex() ) ) ) ) { aNewSel.Min().SetIndex( aBoundary.startPos ); @@ -1608,15 +1628,13 @@ EditSelection ImpEditEngine::SelectSentence( const EditSelection& rCurSel ) bool ImpEditEngine::IsInputSequenceCheckingRequired( sal_Unicode nChar, const EditSelection& rCurSel ) const { uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() ); - if (!pCTLOptions) - pCTLOptions.reset( new SvtCTLOptions ); // get the index that really is first const sal_Int32 nFirstPos = std::min(rCurSel.Min().GetIndex(), rCurSel.Max().GetIndex()); bool bIsSequenceChecking = - pCTLOptions->IsCTLFontEnabled() && - pCTLOptions->IsCTLSequenceChecking() && + SvtCTLOptions::IsCTLFontEnabled() && + SvtCTLOptions::IsCTLSequenceChecking() && nFirstPos != 0 && /* first char needs not to be checked */ _xBI.is() && i18n::ScriptType::COMPLEX == _xBI->getScriptType( OUString( nChar ), 0 ); @@ -1643,7 +1661,7 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) if (!pParaPortion) return; - ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; + ScriptTypePosInfos& rTypes = pParaPortion->getScriptTypePosInfos(); rTypes.clear(); ContentNode* pNode = pParaPortion->GetNode(); @@ -1662,7 +1680,7 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) const OUString aFldText = static_cast<const EditCharAttribField*>(pField)->GetFieldValue(); if ( !aFldText.isEmpty() ) { - aText = aText.replaceAt( pField->GetStart(), 1, aFldText.copy(0,1) ); + aText = aText.replaceAt( pField->GetStart(), 1, aFldText.subView(0,1) ); short nFldScriptType = _xBI->getScriptType( aFldText, 0 ); for ( sal_Int32 nCharInField = 1; nCharInField < aFldText.getLength(); nCharInField++ ) @@ -1673,14 +1691,14 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) if ( nFldScriptType == i18n::ScriptType::WEAK ) { nFldScriptType = nTmpType; - aText = aText.replaceAt( pField->GetStart(), 1, aFldText.copy(nCharInField,1) ); + aText = aText.replaceAt( pField->GetStart(), 1, aFldText.subView(nCharInField,1) ); } // ... but if the first one is LATIN, and there are CJK or CTL chars too, // we prefer that ScriptType because we need another font. if ( ( nTmpType == i18n::ScriptType::ASIAN ) || ( nTmpType == i18n::ScriptType::COMPLEX ) ) { - aText = aText.replaceAt( pField->GetStart(), 1, aFldText.copy(nCharInField,1) ); + aText = aText.replaceAt( pField->GetStart(), 1, aFldText.subView(nCharInField,1) ); break; } } @@ -1709,14 +1727,19 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) } else { - if ( _xBI->getScriptType( aText, nPos - 1 ) == i18n::ScriptType::WEAK ) + auto nPrevPos = nPos; + auto nPrevChar = aText.iterateCodePoints(&nPrevPos, -1); + if (_xBI->getScriptType(aText, nPrevPos) == i18n::ScriptType::WEAK) { - switch ( u_charType(aText.iterateCodePoints(&nPos, 0) ) ) { - case U_NON_SPACING_MARK: - case U_ENCLOSING_MARK: - case U_COMBINING_SPACING_MARK: - --nPos; - rTypes.back().nEndPos--; + auto nChar = aText.iterateCodePoints(&nPos, 0); + auto nType = unicode::getUnicodeType(nChar); + if (nType == css::i18n::UnicodeType::NON_SPACING_MARK || + nType == css::i18n::UnicodeType::ENCLOSING_MARK || + nType == css::i18n::UnicodeType::COMBINING_SPACING_MARK || + (nPrevChar == 0x202F /* NNBSP, tdf#112594 */ && + u_getIntPropertyValue(nChar, UCHAR_SCRIPT) == USCRIPT_MONGOLIAN)) + { + rTypes.back().nEndPos = nPos = nPrevPos; break; } } @@ -1730,11 +1753,11 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) rTypes[0].nScriptType = ( rTypes.size() > 1 ) ? rTypes[1].nScriptType : SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetDefaultLanguage() ); // create writing direction information: - if ( pParaPortion->aWritingDirectionInfos.empty() ) + WritingDirectionInfos& rDirInfos = pParaPortion->getWritingDirectionInfos(); + if (rDirInfos.empty()) InitWritingDirections( nPara ); // i89825: Use CTL font for numbers embedded into an RTL run: - WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos; for (const WritingDirectionInfo & rDirInfo : rDirInfos) { const sal_Int32 nStart = rDirInfo.nStartPos; @@ -1809,10 +1832,10 @@ sal_uInt16 ImpEditEngine::GetI18NScriptType( const EditPaM& rPaM, sal_Int32* pEn const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aScriptInfos.empty() ) - const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); + const ScriptTypePosInfos& rTypes = pParaPortion->getScriptTypePosInfos(); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; + if (rTypes.empty()) + const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); const sal_Int32 nPos = rPaM.GetIndex(); ScriptTypePosInfos::const_iterator itr = std::find_if(rTypes.begin(), rTypes.end(), FindByPos(nPos)); @@ -1830,7 +1853,7 @@ sal_uInt16 ImpEditEngine::GetI18NScriptType( const EditPaM& rPaM, sal_Int32* pEn SvtScriptType ImpEditEngine::GetItemScriptType( const EditSelection& rSel ) const { EditSelection aSel( rSel ); - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); SvtScriptType nScriptType = SvtScriptType::NONE; @@ -1843,10 +1866,10 @@ SvtScriptType ImpEditEngine::GetItemScriptType( const EditSelection& rSel ) cons if (!pParaPortion) continue; - if ( pParaPortion->aScriptInfos.empty() ) - const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); + ScriptTypePosInfos const& rTypes = pParaPortion->getScriptTypePosInfos(); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; + if (rTypes.empty()) + const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); // find all the scripts of this range sal_Int32 nS = ( nPara == nStartPara ) ? aSel.Min().GetIndex() : 0; @@ -1889,10 +1912,11 @@ bool ImpEditEngine::IsScriptChange( const EditPaM& rPaM ) const const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aScriptInfos.empty() ) + ScriptTypePosInfos const& rTypes = pParaPortion->getScriptTypePosInfos(); + + if (rTypes.empty()) const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; const sal_Int32 nPos = rPaM.GetIndex(); for (const ScriptTypePosInfo & rType : rTypes) { @@ -1914,10 +1938,11 @@ bool ImpEditEngine::HasScriptType( sal_Int32 nPara, sal_uInt16 nType ) const const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aScriptInfos.empty() ) + const ScriptTypePosInfos& rTypes = pParaPortion->getScriptTypePosInfos(); + + if (rTypes.empty()) const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; for ( size_t n = rTypes.size(); n && !bTypeFound; ) { if ( rTypes[--n].nScriptType == nType ) @@ -1933,10 +1958,10 @@ void ImpEditEngine::InitWritingDirections( sal_Int32 nPara ) if (!pParaPortion) return; - WritingDirectionInfos& rInfos = pParaPortion->aWritingDirectionInfos; + WritingDirectionInfos& rInfos = pParaPortion->getWritingDirectionInfos(); rInfos.clear(); - if (pParaPortion->GetNode()->Len()) + if (pParaPortion->GetNode()->Len() && !mbFuzzing) { const OUString aText = pParaPortion->GetNode()->GetString(); @@ -1981,7 +2006,7 @@ bool ImpEditEngine::IsRightToLeft( sal_Int32 nPara ) const bool bR2L = false; const SvxFrameDirectionItem* pFrameDirItem = nullptr; - if ( !IsVertical() ) + if ( !IsEffectivelyVertical() ) { bR2L = GetDefaultHorizontalTextDirection() == EEHorizontalTextDirection::R2L; pFrameDirItem = &GetParaAttrib( nPara, EE_PARA_WRITINGDIR ); @@ -2033,16 +2058,16 @@ sal_uInt8 ImpEditEngine::GetRightToLeft( sal_Int32 nPara, sal_Int32 nPos, sal_In { sal_uInt8 nRightToLeft = 0; - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); if ( pNode && pNode->Len() ) { ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aWritingDirectionInfos.empty() ) + WritingDirectionInfos& rDirInfos = pParaPortion->getWritingDirectionInfos(); + if (rDirInfos.empty()) InitWritingDirections( nPara ); - WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos; for (const WritingDirectionInfo & rDirInfo : rDirInfos) { if ( ( rDirInfo.nStartPos <= nPos ) && ( rDirInfo.nEndPos >= nPos ) ) @@ -2064,7 +2089,7 @@ SvxAdjust ImpEditEngine::GetJustification( sal_Int32 nPara ) const { SvxAdjust eJustification = SvxAdjust::Left; - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { eJustification = GetParaAttrib( nPara, EE_PARA_JUST ).GetAdjust(); @@ -2113,15 +2138,15 @@ void ImpEditEngine::ImpRemoveChars( const EditPaM& rPaM, sal_Int32 nChars ) break; // for } } - InsertUndo(std::make_unique<EditUndoRemoveChars>(pEditEngine, CreateEPaM(rPaM), aStr)); + InsertUndo(std::make_unique<EditUndoRemoveChars>(mpEditEngine, CreateEPaM(rPaM), aStr)); } - aEditDoc.RemoveChars( rPaM, nChars ); + maEditDoc.RemoveChars( rPaM, nChars ); } EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 nNewPos ) { - aOldPositions.Justify(); + aOldPositions.Normalize(); bool bValidAction = ( static_cast<tools::Long>(nNewPos) < aOldPositions.Min() ) || ( static_cast<tools::Long>(nNewPos) > aOldPositions.Max() ); OSL_ENSURE( bValidAction, "Move in itself?" ); OSL_ENSURE( aOldPositions.Max() <= static_cast<tools::Long>(GetParaPortions().Count()), "totally over it: MoveParagraphs" ); @@ -2130,7 +2155,7 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n if ( !bValidAction ) { - aSelection = aEditDoc.GetStartPaM(); + aSelection = maEditDoc.GetStartPaM(); return aSelection; } @@ -2145,68 +2170,83 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n ParaPortion* pRecalc3 = nullptr; ParaPortion* pRecalc4 = nullptr; - if ( nNewPos == 0 ) // Move to Start + if (nNewPos == 0) // Move to Start { - pRecalc1 = &GetParaPortions()[0]; - pRecalc2 = &GetParaPortions()[aOldPositions.Min()]; + if (GetParaPortions().exists(0)) + pRecalc1 = &GetParaPortions().getRef(0); + if (GetParaPortions().exists(aOldPositions.Min())) + pRecalc2 = &GetParaPortions().getRef(aOldPositions.Min()); } - else if ( nNewPos == nParaCount ) + else if (nNewPos == nParaCount) { - pRecalc1 = &GetParaPortions()[nParaCount-1]; - pRecalc2 = &GetParaPortions()[aOldPositions.Max()]; + if (GetParaPortions().exists(nParaCount - 1)) + pRecalc1 = &GetParaPortions().getRef(nParaCount - 1); + if (GetParaPortions().exists(aOldPositions.Max())) + pRecalc2 = &GetParaPortions().getRef(aOldPositions.Max()); } - if ( aOldPositions.Min() == 0 ) // Move from Start + if (aOldPositions.Min() == 0) // Move from Start { - pRecalc3 = &GetParaPortions()[0]; - pRecalc4 = &GetParaPortions()[aOldPositions.Max()+1]; + if (GetParaPortions().exists(0)) + pRecalc3 = &GetParaPortions().getRef(0); + if (GetParaPortions().exists(aOldPositions.Max() + 1)) + pRecalc4 = &GetParaPortions().getRef(aOldPositions.Max() + 1); } - else if ( aOldPositions.Max() == (nParaCount-1) ) + else if (aOldPositions.Max() == nParaCount - 1) { - pRecalc3 = &GetParaPortions()[aOldPositions.Max()]; - pRecalc4 = &GetParaPortions()[aOldPositions.Min()-1]; + if (GetParaPortions().exists(aOldPositions.Max())) + pRecalc3 = &GetParaPortions().getRef(aOldPositions.Max()); + if (GetParaPortions().exists(aOldPositions.Min() - 1)) + pRecalc4 = &GetParaPortions().getRef(aOldPositions.Min() - 1); } MoveParagraphsInfo aMoveParagraphsInfo( aOldPositions.Min(), aOldPositions.Max(), nNewPos ); - aBeginMovingParagraphsHdl.Call( aMoveParagraphsInfo ); + maBeginMovingParagraphsHdl.Call( aMoveParagraphsInfo ); if ( IsUndoEnabled() && !IsInUndo()) - InsertUndo(std::make_unique<EditUndoMoveParagraphs>(pEditEngine, aOldPositions, nNewPos)); + InsertUndo(std::make_unique<EditUndoMoveParagraphs>(mpEditEngine, aOldPositions, nNewPos)); // do not lose sight of the Position ! ParaPortion* pDestPortion = GetParaPortions().SafeGetObject( nNewPos ); - ParaPortionList aTmpPortionList; + // Temporary containers used for moving the paragraph portions and content nodes to a new location + std::vector<std::unique_ptr<ParaPortion>> aParagraphPortionVector; + std::vector<std::unique_ptr<ContentNode>> aContentNodeVector; + + // Take the paragraph portions and content nodes out of its containers for (tools::Long i = aOldPositions.Min(); i <= aOldPositions.Max(); i++ ) { - // always aOldPositions.Min(), since Remove(). - ParaPortion aTmpPortion = GetParaPortions().Remove(aOldPositions.Min()); - aEditDoc.Release( aOldPositions.Min() ); - aTmpPortionList.Append(std::move(aTmpPortion)); + // always aOldPositions.Min() as the index, since we remove and the elements from the containers and the + // other elements shift to the left. + std::unique_ptr<ParaPortion> pPortion = GetParaPortions().Release(aOldPositions.Min()); + aParagraphPortionVector.push_back(std::move(pPortion)); + + std::unique_ptr<ContentNode> pContentNode = maEditDoc.Release(aOldPositions.Min()); + aContentNodeVector.push_back(std::move(pContentNode)); } + // Determine the new location for paragraphs sal_Int32 nRealNewPos = pDestPortion ? GetParaPortions().GetPos( pDestPortion ) : GetParaPortions().Count(); - OSL_ENSURE( nRealNewPos != EE_PARA_NOT_FOUND, "ImpMoveParagraphs: Invalid Position!" ); + assert( nRealNewPos != EE_PARA_NOT_FOUND && "ImpMoveParagraphs: Invalid Position!" ); + // Add the paragraph portions and content nodes to a new position sal_Int32 i = 0; - while( aTmpPortionList.Count() > 0 ) + for (auto& pPortion : aParagraphPortionVector) { - ParaPortion aTmpPortion = aTmpPortionList.Remove(0); - if ( i == 0 ) - aSelection.Min().SetNode( aTmpPortion.GetNode() ); + if (i == 0) + aSelection.Min().SetNode(pPortion->GetNode()); + aSelection.Max().SetNode(pPortion->GetNode()); + aSelection.Max().SetIndex(pPortion->GetNode()->Len()); - aSelection.Max().SetNode( aTmpPortion.GetNode() ); - aSelection.Max().SetIndex( aTmpPortion.GetNode()->Len() ); + maEditDoc.Insert(nRealNewPos + i, std::move(aContentNodeVector[i])); + GetParaPortions().Insert(nRealNewPos + i, std::move(pPortion)); - ContentNode* pN = aTmpPortion.GetNode(); - aEditDoc.Insert(nRealNewPos+i, pN); - - GetParaPortions().Insert(nRealNewPos+i, std::move(aTmpPortion)); ++i; } - aEndMovingParagraphsHdl.Call( aMoveParagraphsInfo ); + // Signal end of paragraph moving + maEndMovingParagraphsHdl.Call( aMoveParagraphsInfo ); if ( GetNotifyHdl().IsSet() ) { @@ -2217,19 +2257,19 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n GetNotifyHdl().Call( aNotify ); } - aEditDoc.SetModified( true ); + maEditDoc.SetModified( true ); - if ( pRecalc1 ) - CalcHeight( pRecalc1 ); - if ( pRecalc2 ) - CalcHeight( pRecalc2 ); - if ( pRecalc3 ) - CalcHeight( pRecalc3 ); - if ( pRecalc4 ) - CalcHeight( pRecalc4 ); + if (pRecalc1) + CalcHeight(*pRecalc1); + if (pRecalc2) + CalcHeight(*pRecalc2); + if (pRecalc3) + CalcHeight(*pRecalc3); + if (pRecalc4) + CalcHeight(*pRecalc4); #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - ParaPortionList::DbgCheck(GetParaPortions(), aEditDoc); + ParaPortionList::DbgCheck(GetParaPortions(), maEditDoc); #endif return aSelection; } @@ -2238,28 +2278,28 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward ) { OSL_ENSURE( pLeft != pRight, "Join together the same paragraph ?" ); - OSL_ENSURE( aEditDoc.GetPos( pLeft ) != EE_PARA_NOT_FOUND, "Inserted node not found (1)" ); - OSL_ENSURE( aEditDoc.GetPos( pRight ) != EE_PARA_NOT_FOUND, "Inserted node not found (2)" ); + OSL_ENSURE( maEditDoc.GetPos( pLeft ) != EE_PARA_NOT_FOUND, "Inserted node not found (1)" ); + OSL_ENSURE( maEditDoc.GetPos( pRight ) != EE_PARA_NOT_FOUND, "Inserted node not found (2)" ); // #i120020# it is possible that left and right are *not* in the desired order (left/right) // so correct it. This correction is needed, else an invalid SfxLinkUndoAction will be // created from ConnectParagraphs below. Assert this situation, it should be corrected by the // caller. - if(aEditDoc.GetPos( pLeft ) > aEditDoc.GetPos( pRight )) + if (maEditDoc.GetPos( pLeft ) > maEditDoc.GetPos( pRight )) { OSL_ENSURE(false, "ImpConnectParagraphs with wrong order of pLeft/pRight nodes (!)"); std::swap(pLeft, pRight); } - sal_Int32 nParagraphTobeDeleted = aEditDoc.GetPos( pRight ); - aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pRight, nParagraphTobeDeleted )); + sal_Int32 nParagraphTobeDeleted = maEditDoc.GetPos( pRight ); + maDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pRight, nParagraphTobeDeleted )); - GetEditEnginePtr()->ParagraphConnected( aEditDoc.GetPos( pLeft ), aEditDoc.GetPos( pRight ) ); + GetEditEnginePtr()->ParagraphConnected( maEditDoc.GetPos( pLeft ), maEditDoc.GetPos( pRight ) ); if ( IsUndoEnabled() && !IsInUndo() ) { - InsertUndo( std::make_unique<EditUndoConnectParas>(pEditEngine, - aEditDoc.GetPos( pLeft ), pLeft->Len(), + InsertUndo( std::make_unique<EditUndoConnectParas>(mpEditEngine, + maEditDoc.GetPos( pLeft ), pLeft->Len(), pLeft->GetContentAttribs().GetItems(), pRight->GetContentAttribs().GetItems(), pLeft->GetStyleSheet(), pRight->GetStyleSheet(), bBackward ) ); } @@ -2276,7 +2316,8 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR ParaAttribsChanged( pLeft, true ); // First search for Portions since pRight is gone after ConnectParagraphs. - ParaPortion& rLeftPortion = FindParaPortion( pLeft ); + ParaPortion* pLeftPortion = FindParaPortion( pLeft ); + assert(pLeftPortion); if ( GetStatus().DoOnlineSpelling() ) { @@ -2300,10 +2341,10 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphDeleted( nParagraphTobeDeleted ); - EditPaM aPaM = aEditDoc.ConnectParagraphs( pLeft, pRight ); + EditPaM aPaM = maEditDoc.ConnectParagraphs( pLeft, pRight ); GetParaPortions().Remove( nParagraphTobeDeleted ); - rLeftPortion.MarkSelectionInvalid( aPaM.GetIndex() ); + pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex() ); // the right node is deleted by EditDoc:ConnectParagraphs(). if ( GetTextRanger() ) @@ -2313,9 +2354,9 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR // the change of the total text height too late... for ( sal_Int32 n = nParagraphTobeDeleted; n < GetParaPortions().Count(); n++ ) { - ParaPortion& rPP = GetParaPortions()[n]; - rPP.MarkSelectionInvalid( 0 ); - rPP.GetLines().Reset(); + ParaPortion& rParaPortion = GetParaPortions().getRef(n); + rParaPortion.MarkSelectionInvalid(0); + rParaPortion.GetLines().Reset(); } } @@ -2326,7 +2367,7 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR EditPaM ImpEditEngine::DeleteLeftOrRight( const EditSelection& rSel, sal_uInt8 nMode, DeleteMode nDelMode ) { - OSL_ENSURE( !rSel.DbgIsBuggy( aEditDoc ), "Index out of range in DeleteLeftOrRight" ); + OSL_ENSURE( !rSel.DbgIsBuggy( maEditDoc ), "Index out of range in DeleteLeftOrRight" ); if ( rSel.HasRange() ) // only then Delete Selection return ImpDeleteSelection( rSel ); @@ -2339,17 +2380,15 @@ EditPaM ImpEditEngine::DeleteLeftOrRight( const EditSelection& rSel, sal_uInt8 n if ( nDelMode == DeleteMode::Simple ) { sal_uInt16 nCharMode = i18n::CharacterIteratorMode::SKIPCHARACTER; - // Check if we are deleting a CJK ideograph variance sequence (IVS). + // If we are deleting a variation selector, we want to delete the + // whole sequence (cell). sal_Int32 nIndex = aCurPos.GetIndex(); if (nIndex > 0) { const OUString& rString = aCurPos.GetNode()->GetString(); sal_Int32 nCode = rString.iterateCodePoints(&nIndex, -1); - if (unicode::isIVSSelector(nCode) && nIndex > 0 && - unicode::isCJKIVSCharacter(rString.iterateCodePoints(&nIndex, -1))) - { + if (unicode::isVariationSelector(nCode)) nCharMode = i18n::CharacterIteratorMode::SKIPCELL; - } } aDelStart = CursorLeft(aCurPos, nCharMode); } @@ -2423,18 +2462,20 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel) return rCurSel.Min(); EditSelection aCurSel(rCurSel); - aCurSel.Adjust( aEditDoc ); + aCurSel.Adjust( maEditDoc ); EditPaM aStartPaM(aCurSel.Min()); EditPaM aEndPaM(aCurSel.Max()); - CursorMoved( aStartPaM.GetNode() ); // only so that newly set Attributes disappear... - CursorMoved( aEndPaM.GetNode() ); // only so that newly set Attributes disappear... + if( nullptr != aStartPaM.GetNode() ) + aStartPaM.GetNode()->checkAndDeleteEmptyAttribs(); // only so that newly set Attributes disappear... + if( nullptr != aEndPaM.GetNode() ) + aEndPaM.GetNode()->checkAndDeleteEmptyAttribs(); // only so that newly set Attributes disappear... OSL_ENSURE( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" ); OSL_ENSURE( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" ); - sal_Int32 nStartNode = aEditDoc.GetPos( aStartPaM.GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aEndPaM.GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aStartPaM.GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aEndPaM.GetNode() ); OSL_ENSURE( nEndNode != EE_PARA_NOT_FOUND, "Start > End ?!" ); OSL_ENSURE( nStartNode <= nEndNode, "Start > End ?!" ); @@ -2450,23 +2491,26 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel) { // The Rest of the StartNodes... ImpRemoveChars( aStartPaM, aStartPaM.GetNode()->Len() - aStartPaM.GetIndex() ); - ParaPortion& rPortion = FindParaPortion( aStartPaM.GetNode() ); - rPortion.MarkSelectionInvalid( aStartPaM.GetIndex() ); + ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() ); + assert(pPortion); + pPortion->MarkSelectionInvalid( aStartPaM.GetIndex() ); // The beginning of the EndNodes... const sal_Int32 nChars = aEndPaM.GetIndex(); aEndPaM.SetIndex( 0 ); ImpRemoveChars( aEndPaM, nChars ); - ParaPortion& rPortion2 = FindParaPortion( aEndPaM.GetNode() ); - rPortion2.MarkSelectionInvalid( 0 ); + pPortion = FindParaPortion( aEndPaM.GetNode() ); + assert(pPortion); + pPortion->MarkSelectionInvalid( 0 ); // Join together... aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() ); } else { ImpRemoveChars( aStartPaM, aEndPaM.GetIndex() - aStartPaM.GetIndex() ); - ParaPortion& rPortion = FindParaPortion( aStartPaM.GetNode() ); - rPortion.MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() ); + ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() ); } UpdateSelections(); @@ -2476,15 +2520,15 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel) void ImpEditEngine::ImpRemoveParagraph( sal_Int32 nPara ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); - ContentNode* pNextNode = aEditDoc.GetObject( nPara+1 ); + assert(maEditDoc.GetObject(nPara)); - OSL_ENSURE( pNode, "Blind Node in ImpRemoveParagraph" ); + ContentNode* pNextNode = maEditDoc.GetObject( nPara+1 ); - aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pNode, nPara )); + std::unique_ptr<ContentNode> pNode = maEditDoc.Release(nPara); + maDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>(pNode.get(), nPara)); // The node is managed by the undo and possibly destroyed! - aEditDoc.Release( nPara ); + GetParaPortions().Remove( nPara ); if ( IsCallParaInsertedOrDeleted() ) @@ -2498,14 +2542,15 @@ void ImpEditEngine::ImpRemoveParagraph( sal_Int32 nPara ) if ( pNextNode ) ParaAttribsChanged( pNextNode ); - if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoDelContent>(pEditEngine, pNode, nPara)); + if (IsUndoEnabled() && !IsInUndo()) + { + InsertUndo(std::make_unique<EditUndoDelContent>(mpEditEngine, std::move(pNode), nPara)); + } else { - aEditDoc.RemoveItemsFromPool(*pNode); if ( pNode->GetStyleSheet() ) - EndListening( *pNode->GetStyleSheet() ); - delete pNode; + EndListening(*pNode->GetStyleSheet()); + pNode.reset(); } } @@ -2566,7 +2611,7 @@ EditPaM ImpEditEngine::AutoCorrect( const EditSelection& rCurSel, sal_Unicode c, ContentNode* pNode = aSel.Max().GetNode(); const sal_Int32 nIndex = aSel.Max().GetIndex(); - EdtAutoCorrDoc aAuto(pEditEngine, pNode, nIndex, c); + EdtAutoCorrDoc aAuto(mpEditEngine, pNode, nIndex, c); // FIXME: this _must_ be called with reference to the actual node text! OUString const& rNodeString(pNode->GetString()); pAutoCorrect->DoAutoCorrect( @@ -2606,7 +2651,7 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel, // If selected, then do not also overwrite a character! EditSelection aTmpSel( aPaM ); aTmpSel.Max().SetIndex( aTmpSel.Max().GetIndex()+1 ); - OSL_ENSURE( !aTmpSel.DbgIsBuggy( aEditDoc ), "Overwrite: Wrong selection! "); + OSL_ENSURE( !aTmpSel.DbgIsBuggy( maEditDoc ), "Overwrite: Wrong selection! "); ImpDeleteSelection( aTmpSel ); } @@ -2615,20 +2660,18 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel, if (IsInputSequenceCheckingRequired( c, rCurSel )) { uno::Reference < i18n::XExtendedInputSequenceChecker > _xISC( ImplGetInputSequenceChecker() ); - if (!pCTLOptions) - pCTLOptions.reset( new SvtCTLOptions ); if (_xISC) { const sal_Int32 nTmpPos = aPaM.GetIndex(); - sal_Int16 nCheckMode = pCTLOptions->IsCTLSequenceCheckingRestricted() ? + sal_Int16 nCheckMode = SvtCTLOptions::IsCTLSequenceCheckingRestricted() ? i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC; // the text that needs to be checked is only the one // before the current cursor position const OUString aOldText( aPaM.GetNode()->Copy(0, nTmpPos) ); OUString aNewText( aOldText ); - if (pCTLOptions->IsCTLSequenceCheckingTypeAndReplace()) + if (SvtCTLOptions::IsCTLSequenceCheckingTypeAndReplace()) { _xISC->correctInputSequence(aNewText, nTmpPos - 1, c, nCheckMode); @@ -2665,14 +2708,15 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel, if ( IsUndoEnabled() && !IsInUndo() ) { - std::unique_ptr<EditUndoInsertChars> pNewUndo(new EditUndoInsertChars(pEditEngine, CreateEPaM(aPaM), OUString(c))); + std::unique_ptr<EditUndoInsertChars> pNewUndo(new EditUndoInsertChars(mpEditEngine, CreateEPaM(aPaM), OUString(c))); bool bTryMerge = !bDoOverwrite && ( c != ' ' ); InsertUndo( std::move(pNewUndo), bTryMerge ); } - aEditDoc.InsertText( aPaM, OUString(c) ); - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); - rPortion.MarkInvalid( aPaM.GetIndex(), 1 ); + maEditDoc.InsertText( aPaM, OUStringChar(c) ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( aPaM.GetIndex(), 1 ); aPaM.SetIndex( aPaM.GetIndex()+1 ); // does not do EditDoc-Method anymore } @@ -2705,7 +2749,7 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin aCurWord = SelectWord( aCurPaM, i18n::WordType::DICTIONARY_WORD ); OUString aText(convertLineEnd(rStr, LINEEND_LF)); - if (utl::ConfigManager::IsFuzzing()) //tab expansion performance in editeng is appalling + if (mbFuzzing) //tab expansion performance in editeng is appalling aText = aText.replaceAll("\t","-"); SfxVoidItem aTabItem( EE_FEATURE_TAB ); @@ -2716,7 +2760,8 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin sal_Int32 nStart = 0; while ( nStart < aText.getLength() ) { - sal_Int32 nEnd = aText.indexOf( LINE_SEP, nStart ); + sal_Int32 nEnd = !maStatus.IsSingleLine() ? + aText.indexOf( LINE_SEP, nStart ) : -1; if ( nEnd == -1 ) nEnd = aText.getLength(); // not dereference! @@ -2729,14 +2774,64 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin if (nChars > MAXCHARSINPARA) { sal_Int32 nMaxNewChars = std::max<sal_Int32>(0, MAXCHARSINPARA - nExistingChars); - nEnd -= ( aLine.getLength() - nMaxNewChars ); // Then the characters end up in the next paragraph. - aLine = aLine.copy( 0, nMaxNewChars ); // Delete the Rest... + // Wherever we break, it may be wrong. However, try to find the + // previous non-alnum/non-letter character. Note this is only + // in the to be appended data, otherwise already existing + // characters would have to be moved and PaM to be updated. + // Restrict to 2*42, if not found by then assume other data or + // language-script uses only letters or idiographs. + sal_Int32 nPos = nMaxNewChars; + while (nPos-- > 0 && (nMaxNewChars - nPos) <= 84) + { + auto nNextPos = nPos; + const auto c = aLine.iterateCodePoints(&nNextPos); + switch (unicode::getUnicodeType(c)) + { + case css::i18n::UnicodeType::UPPERCASE_LETTER: + case css::i18n::UnicodeType::LOWERCASE_LETTER: + case css::i18n::UnicodeType::TITLECASE_LETTER: + case css::i18n::UnicodeType::MODIFIER_LETTER: + case css::i18n::UnicodeType::OTHER_LETTER: + case css::i18n::UnicodeType::DECIMAL_DIGIT_NUMBER: + case css::i18n::UnicodeType::LETTER_NUMBER: + case css::i18n::UnicodeType::OTHER_NUMBER: + case css::i18n::UnicodeType::CURRENCY_SYMBOL: + break; + default: + { + // Ignore NO-BREAK spaces, NBSP, NNBSP, ZWNBSP. + if (c == 0x00A0 || c == 0x202F || c == 0xFEFF) + break; + const auto n = aLine.iterateCodePoints(&nNextPos, 0); + if (c == '-' && nNextPos < nMaxNewChars) + { + // Keep HYPHEN-MINUS with a number to the right. + const sal_Int16 t = unicode::getUnicodeType(n); + if ( t == css::i18n::UnicodeType::DECIMAL_DIGIT_NUMBER || + t == css::i18n::UnicodeType::LETTER_NUMBER || + t == css::i18n::UnicodeType::OTHER_NUMBER) + nMaxNewChars = nPos; // line break before + else + nMaxNewChars = nNextPos; // line break after + } + else + { + nMaxNewChars = nNextPos; // line break after + } + nPos = 0; // will break loop + } + } + } + // Remaining characters end up in the next paragraph. Note that + // new nStart will be nEnd+1 below so decrement by one more. + nEnd -= (aLine.getLength() - nMaxNewChars + 1); + aLine = aLine.copy( 0, nMaxNewChars ); // Delete the Rest... } if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoInsertChars>(pEditEngine, CreateEPaM(aPaM), aLine)); + InsertUndo(std::make_unique<EditUndoInsertChars>(mpEditEngine, CreateEPaM(aPaM), aLine)); // Tabs ? if ( aLine.indexOf( '\t' ) == -1 ) - aPaM = aEditDoc.InsertText( aPaM, aLine ); + aPaM = maEditDoc.InsertText( aPaM, aLine ); else { sal_Int32 nStart2 = 0; @@ -2747,15 +2842,16 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin nEnd2 = aLine.getLength(); // not dereference! if ( nEnd2 > nStart2 ) - aPaM = aEditDoc.InsertText( aPaM, aLine.copy( nStart2, nEnd2-nStart2 ) ); + aPaM = maEditDoc.InsertText( aPaM, aLine.subView( nStart2, nEnd2-nStart2 ) ); if ( nEnd2 < aLine.getLength() ) { - aPaM = aEditDoc.InsertFeature( aPaM, aTabItem ); + aPaM = maEditDoc.InsertFeature( aPaM, aTabItem ); } nStart2 = nEnd2+1; } } - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + assert(pPortion); if ( GetStatus().DoOnlineSpelling() ) { @@ -2764,10 +2860,10 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin if (pWrongs && !pWrongs->empty()) pWrongs->ClearWrongs( aCurWord.Min().GetIndex(), aPaM.GetIndex(), aPaM.GetNode() ); // ... and mark both words as 'to be checked again' - rPortion.MarkInvalid( aCurWord.Min().GetIndex(), aLine.getLength() ); + pPortion->MarkInvalid( aCurWord.Min().GetIndex(), aLine.getLength() ); } else - rPortion.MarkInvalid( aCurPaM.GetIndex(), aLine.getLength() ); + pPortion->MarkInvalid( aCurPaM.GetIndex(), aLine.getLength() ); } if ( nEnd < aText.getLength() ) aPaM = ImpInsertParaBreak( aPaM ); @@ -2790,9 +2886,9 @@ EditPaM ImpEditEngine::ImpFastInsertText( EditPaM aPaM, const OUString& rStr ) if ( ( aPaM.GetNode()->Len() + rStr.getLength() ) < MAXCHARSINPARA ) { if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoInsertChars>(pEditEngine, CreateEPaM(aPaM), rStr)); + InsertUndo(std::make_unique<EditUndoInsertChars>(mpEditEngine, CreateEPaM(aPaM), rStr)); - aPaM = aEditDoc.InsertText( aPaM, rStr ); + aPaM = maEditDoc.InsertText( aPaM, rStr ); TextModified(); } else @@ -2815,12 +2911,13 @@ EditPaM ImpEditEngine::ImpInsertFeature(const EditSelection& rCurSel, const SfxP return aPaM; if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoInsertFeature>(pEditEngine, CreateEPaM(aPaM), rItem)); - aPaM = aEditDoc.InsertFeature( aPaM, rItem ); + InsertUndo(std::make_unique<EditUndoInsertFeature>(mpEditEngine, CreateEPaM(aPaM), rItem)); + aPaM = maEditDoc.InsertFeature( aPaM, rItem ); UpdateFields(); - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); - rPortion.MarkInvalid( aPaM.GetIndex()-1, 1 ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 ); TextModified(); @@ -2840,7 +2937,7 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( const EditSelection& rCurSel ) EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttribs ) { - if ( aEditDoc.Count() >= EE_PARA_MAX_COUNT ) + if ( maEditDoc.Count() >= EE_PARA_MAX_COUNT ) { SAL_WARN( "editeng", "ImpEditEngine::ImpInsertParaBreak - can't process more than " << EE_PARA_MAX_COUNT << " paragraphs!"); @@ -2848,9 +2945,11 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttrib } if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, aEditDoc.GetPos(rPaM.GetNode()), rPaM.GetIndex())); + InsertUndo(std::make_unique<EditUndoSplitPara>(mpEditEngine, maEditDoc.GetPos(rPaM.GetNode()), rPaM.GetIndex())); - EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) ); + EditPaM aPaM( maEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) ); + if (auto pStyle = aPaM.GetNode()->GetStyleSheet()) + StartListening(*pStyle, DuplicateHandling::Allow); if ( GetStatus().DoOnlineSpelling() ) { @@ -2882,18 +2981,22 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttrib pRWrongs->SetInvalidRange(0, 1); // Only test the first word } - ParaPortion& rPortion = FindParaPortion( rPaM.GetNode() ); - rPortion.MarkInvalid( rPaM.GetIndex(), 0 ); + ParaPortion* pPortion = FindParaPortion( rPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( rPaM.GetIndex(), 0 ); // Optimization: Do not place unnecessarily many getPos to Listen! // Here, as in undo, but also in all other methods. - sal_Int32 nPos = GetParaPortions().GetPos( &rPortion ); - ParaPortion& rNewPortion = GetParaPortions().Insert(nPos+1, ParaPortion(aPaM.GetNode())); - ParaAttribsChanged( rNewPortion.GetNode() ); + sal_Int32 nPos = GetParaPortions().GetPos( pPortion ); + ParaPortion* pNewPortion = new ParaPortion( aPaM.GetNode() ); + GetParaPortions().Insert(nPos+1, std::unique_ptr<ParaPortion>(pNewPortion)); + ParaAttribsChanged( pNewPortion->GetNode() ); if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphInserted( nPos+1 ); - CursorMoved( rPaM.GetNode() ); // if empty Attributes have emerged. + if( nullptr != rPaM.GetNode() ) + rPaM.GetNode()->checkAndDeleteEmptyAttribs(); // if empty Attributes have emerged. + TextModified(); return aPaM; } @@ -2904,23 +3007,23 @@ EditPaM ImpEditEngine::ImpFastInsertParagraph( sal_Int32 nPara ) { if ( nPara ) { - OSL_ENSURE( aEditDoc.GetObject( nPara-1 ), "FastInsertParagraph: Prev does not exist" ); - InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, nPara-1, aEditDoc.GetObject( nPara-1 )->Len())); + assert(maEditDoc.GetObject(nPara - 1)); + InsertUndo(std::make_unique<EditUndoSplitPara>(mpEditEngine, nPara-1, maEditDoc.GetObject(nPara - 1)->Len())); } else - InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, 0, 0)); + InsertUndo(std::make_unique<EditUndoSplitPara>(mpEditEngine, 0, 0)); } - ContentNode* pNode = new ContentNode( aEditDoc.GetItemPool() ); + ContentNode* pNode = new ContentNode( maEditDoc.GetItemPool() ); // If flat mode, then later no Font is set: - pNode->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont(); + pNode->GetCharAttribs().GetDefFont() = maEditDoc.GetDefFont(); if ( GetStatus().DoOnlineSpelling() ) pNode->CreateWrongList(); - aEditDoc.Insert(nPara, pNode); + maEditDoc.Insert(nPara, std::unique_ptr<ContentNode>(pNode)); - GetParaPortions().Insert(nPara, ParaPortion( pNode )); + GetParaPortions().Insert(nPara, std::make_unique<ParaPortion>( pNode )); if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphInserted( nPara ); @@ -2930,9 +3033,9 @@ EditPaM ImpEditEngine::ImpFastInsertParagraph( sal_Int32 nPara ) EditPaM ImpEditEngine::InsertParaBreak(const EditSelection& rCurSel) { EditPaM aPaM(ImpInsertParaBreak(rCurSel)); - if ( aStatus.DoAutoIndenting() ) + if ( maStatus.DoAutoIndenting() ) { - sal_Int32 nPara = aEditDoc.GetPos( aPaM.GetNode() ); + sal_Int32 nPara = maEditDoc.GetPos( aPaM.GetNode() ); OSL_ENSURE( nPara > 0, "AutoIndenting: Error!" ); const OUString aPrevParaText( GetEditDoc().GetParaAsString( nPara-1 ) ); sal_Int32 n = 0; @@ -2969,7 +3072,7 @@ bool ImpEditEngine::UpdateFields() { bool bChangesInPara = false; ContentNode* pNode = GetEditDoc().GetObject( nPara ); - OSL_ENSURE( pNode, "NULL-Pointer in Doc" ); + assert(pNode); CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs(); for (std::unique_ptr<EditCharAttrib> & rAttrib : rAttribs) { @@ -2980,10 +3083,10 @@ bool ImpEditEngine::UpdateFields() EditCharAttribField aCurrent(rField); rField.Reset(); - if (!aStatus.MarkNonUrlFields() && !aStatus.MarkUrlFields()) + if (!maStatus.MarkNonUrlFields() && !maStatus.MarkUrlFields()) ; // nothing marked - else if (aStatus.MarkNonUrlFields() && aStatus.MarkUrlFields()) - rField.GetFieldColor() = GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor; + else if (maStatus.MarkNonUrlFields() && maStatus.MarkUrlFields()) + rField.GetFieldColor() = GetColorConfig().GetColorValue(svtools::WRITERFIELDSHADINGS).nColor; else { bool bURL = false; @@ -2992,14 +3095,14 @@ bool ImpEditEngine::UpdateFields() if (const SvxFieldData* pFieldData = pFieldItem->GetField()) bURL = (dynamic_cast<const SvxURLField* >(pFieldData) != nullptr); } - if ((bURL && aStatus.MarkUrlFields()) || (!bURL && aStatus.MarkNonUrlFields())) + if ((bURL && maStatus.MarkUrlFields()) || (!bURL && maStatus.MarkNonUrlFields())) rField.GetFieldColor() = GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor; } const OUString aFldValue = GetEditEnginePtr()->CalcFieldValue( static_cast<const SvxFieldItem&>(*rField.GetItem()), - nPara, rField.GetStart(), rField.GetTextColor(), rField.GetFieldColor()); + nPara, rField.GetStart(), rField.GetTextColor(), rField.GetFieldColor(), rField.GetFldLineStyle() ); rField.SetFieldValue(aFldValue); if (rField != aCurrent) @@ -3012,7 +3115,8 @@ bool ImpEditEngine::UpdateFields() if ( bChangesInPara ) { // If possible be more precise when invalidate. - ParaPortion& rPortion = GetParaPortions()[nPara]; + assert(GetParaPortions().exists(nPara)); + ParaPortion& rPortion = GetParaPortions().getRef(nPara); rPortion.MarkSelectionInvalid( 0 ); } } @@ -3028,47 +3132,45 @@ EditPaM ImpEditEngine::InsertLineBreak(const EditSelection& aCurSel) // Helper functions -tools::Rectangle ImpEditEngine::GetEditCursor(const ParaPortion* pPortion, const EditLine* pLine, - sal_Int32 nIndex, GetCursorFlags nFlags) +tools::Rectangle ImpEditEngine::GetEditCursor(ParaPortion const& rPortion, EditLine const& rLine, + sal_Int32 nIndex, CursorFlags aFlags) { - assert(pPortion && pLine); // nIndex might be not in the line // Search within the line... tools::Long nX; - if ((nIndex == pLine->GetStart()) && (nFlags & GetCursorFlags::StartOfLine)) + if (nIndex == rLine.GetStart() && aFlags.bStartOfLine) { - Range aXRange = GetLineXPosStartEnd(pPortion, pLine); - nX = !IsRightToLeft(GetEditDoc().GetPos(pPortion->GetNode())) ? aXRange.Min() + Range aXRange = GetLineXPosStartEnd(rPortion, rLine); + nX = !IsRightToLeft(GetEditDoc().GetPos(rPortion.GetNode())) ? aXRange.Min() : aXRange.Max(); } - else if ((nIndex == pLine->GetEnd()) && (nFlags & GetCursorFlags::EndOfLine)) + else if (nIndex == rLine.GetEnd() && aFlags.bEndOfLine) { - Range aXRange = GetLineXPosStartEnd(pPortion, pLine); - nX = !IsRightToLeft(GetEditDoc().GetPos(pPortion->GetNode())) ? aXRange.Max() + Range aXRange = GetLineXPosStartEnd(rPortion, rLine); + nX = !IsRightToLeft(GetEditDoc().GetPos(rPortion.GetNode())) ? aXRange.Max() : aXRange.Min(); } else { - nX = GetXPos(pPortion, pLine, nIndex, bool(nFlags & GetCursorFlags::PreferPortionStart)); + nX = GetXPos(rPortion, rLine, nIndex, aFlags.bPreferPortionStart); } tools::Rectangle aEditCursor; aEditCursor.SetLeft(nX); aEditCursor.SetRight(nX); - aEditCursor.SetBottom(pLine->GetHeight() - 1); - if (nFlags & GetCursorFlags::TextOnly) - aEditCursor.SetTop(aEditCursor.Bottom() - pLine->GetTxtHeight() + 1); + aEditCursor.SetBottom(rLine.GetHeight() - 1); + if (aFlags.bTextOnly) + aEditCursor.SetTop(aEditCursor.Bottom() - rLine.GetTxtHeight() + 1); else - aEditCursor.SetTop(aEditCursor.Bottom() - - std::min(pLine->GetTxtHeight(), pLine->GetHeight()) + 1); + aEditCursor.SetTop(aEditCursor.Bottom() - std::min(rLine.GetTxtHeight(), rLine.GetHeight()) + 1); return aEditCursor; } -tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nFlags ) +tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, CursorFlags aFlags) { - OSL_ENSURE( GetUpdateMode(), "Must not be reached when Update=FALSE: PaMtoEditCursor" ); + assert( IsUpdateLayout() && "Must not be reached when Update=FALSE: PaMtoEditCursor" ); tools::Rectangle aEditCursor; const sal_Int32 nIndex = aPaM.GetIndex(); @@ -3076,8 +3178,8 @@ tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nF const EditLine* pLastLine = nullptr; tools::Rectangle aLineArea; - auto FindPortionLineAndArea - = [&, bEOL(bool(nFlags & GetCursorFlags::EndOfLine))](const LineAreaInfo& rInfo) { + auto FindPortionLineAndArea = [&, bEOL(aFlags.bEndOfLine)](const LineAreaInfo& rInfo) + { if (!rInfo.pLine) // start of ParaPortion { ContentNode* pNode = rInfo.rPortion.GetNode(); @@ -3097,10 +3199,10 @@ tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nF }; IterateLineAreas(FindPortionLineAndArea, IterFlag::none); - if (pLastLine) + if (pLastLine && pPortion) { - aEditCursor = GetEditCursor(pPortion, pLastLine, nIndex, nFlags); - aEditCursor.Move(getLeftDirectionAware(aLineArea), getTopDirectionAware(aLineArea)); + aEditCursor = GetEditCursor(*pPortion, *pLastLine, nIndex, aFlags); + aEditCursor.Move(getTopLeftDocOffset(aLineArea)); } else OSL_FAIL("Line not found!"); @@ -3113,11 +3215,11 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO const Point aOrigin(0, 0); Point aLineStart(aOrigin); const tools::Long nVertLineSpacing = CalcVertLineSpacing(aLineStart); - const tools::Long nColumnWidth = GetColumnWidth(aPaperSize); - sal_Int32 nColumn = 0; + const tools::Long nColumnWidth = GetColumnWidth(maPaperSize); + sal_Int16 nColumn = 0; for (sal_Int32 n = 0, nPortions = GetParaPortions().Count(); n < nPortions; ++n) { - ParaPortion& rPortion = GetParaPortions()[n]; + ParaPortion& rPortion = GetParaPortions().getRef(n); bool bSkipThis = true; if (rPortion.IsVisible()) { @@ -3126,13 +3228,13 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO return; LineAreaInfo aInfo{ - nColumn, // nColumn - rPortion, // rPortion - n, // nPortion + rPortion, nullptr, // pLine - 0, // nLine + 0, // nHeightNeededToNotWrap { aLineStart, Size{ nColumnWidth, rPortion.GetFirstLineOffset() } }, // aArea - 0 // nHeightNeededToNotWrap + n, // nPortion + 0, // nLine + nColumn // nColumn }; auto eResult = f(aInfo); if (eResult == CallbackResult::Stop) @@ -3140,12 +3242,12 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO bSkipThis = eResult == CallbackResult::SkipThisPortion; sal_uInt16 nSBL = 0; - if (!aStatus.IsOutliner()) + if (!maStatus.IsOutliner()) { const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); nSBL = (rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix) - ? GetYValue(rLSItem.GetInterLineSpace()) + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; } @@ -3159,7 +3261,7 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO MoveToNextLine(aLineStart, nLineHeight, nColumn, aOrigin, &aInfo.nHeightNeededToNotWrap); const bool bInclILS = eOptions & IterFlag::inclILS; - if (bInclILS && (nLine != nLines - 1) && !aStatus.IsOutliner()) + if (bInclILS && (nLine != nLines - 1) && !maStatus.IsOutliner()) { adjustYDirectionAware(aLineStart, nSBL); nLineHeight += nSBL; @@ -3175,21 +3277,20 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO aInfo.nColumn = nColumn; aInfo.pLine = &rLine; aInfo.nLine = nLine; - aInfo.aArea = tools::Rectangle::Justify(aLineStart, aOtherCorner); + aInfo.aArea = tools::Rectangle::Normalize(aLineStart, aOtherCorner); eResult = f(aInfo); if (eResult == CallbackResult::Stop) return; bSkipThis = eResult == CallbackResult::SkipThisPortion; } - if (!bInclILS && (nLine != nLines - 1) && !aStatus.IsOutliner()) + if (!bInclILS && (nLine != nLines - 1) && !maStatus.IsOutliner()) adjustYDirectionAware(aLineStart, nSBL); } - if (!aStatus.IsOutliner()) + if (!maStatus.IsOutliner()) { - const SvxULSpaceItem& rULItem - = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); - tools::Long nUL = GetYValue(rULItem.GetLower()); + const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); adjustYDirectionAware(aLineStart, nUL); } } @@ -3202,7 +3303,7 @@ ImpEditEngine::GetPortionAndLine(Point aDocPos) { // First find the column from the point sal_Int32 nClickColumn = 0; - for (tools::Long nColumnStart = 0, nColumnWidth = GetColumnWidth(aPaperSize);; + for (tools::Long nColumnStart = 0, nColumnWidth = GetColumnWidth(maPaperSize);; nColumnStart += mnColumnSpacing + nColumnWidth, ++nClickColumn) { if (aDocPos.X() <= nColumnStart + nColumnWidth + mnColumnSpacing / 2) @@ -3214,6 +3315,8 @@ ImpEditEngine::GetPortionAndLine(Point aDocPos) const ParaPortion* pLastPortion = nullptr; const EditLine* pLastLine = nullptr; tools::Long nLineStartX = 0; + Point aPos; + adjustYDirectionAware(aPos, aDocPos.Y()); auto FindLastMatchingPortionAndLine = [&](const LineAreaInfo& rInfo) { if (rInfo.pLine) // Only handle lines, not ParaPortion starts @@ -3222,8 +3325,8 @@ ImpEditEngine::GetPortionAndLine(Point aDocPos) return CallbackResult::Stop; pLastPortion = &rInfo.rPortion; // Candidate paragraph pLastLine = rInfo.pLine; // Last visible line not later than click position - nLineStartX = getLeftDirectionAware(rInfo.aArea); - if (rInfo.nColumn == nClickColumn && getBottomDirectionAware(rInfo.aArea) > aDocPos.Y()) + nLineStartX = getTopLeftDocOffset(rInfo.aArea).Width(); + if (rInfo.nColumn == nClickColumn && getYOverflowDirectionAware(aPos, rInfo.aArea) == 0) return CallbackResult::Stop; // Found it } return CallbackResult::Continue; @@ -3235,12 +3338,13 @@ ImpEditEngine::GetPortionAndLine(Point aDocPos) EditPaM ImpEditEngine::GetPaM( Point aDocPos, bool bSmart ) { - OSL_ENSURE( GetUpdateMode(), "Must not be reached when Update=FALSE: GetPaM" ); + assert( IsUpdateLayout() && "Must not be reached when Update=FALSE: GetPaM" ); if (const auto& [pPortion, pLine, nLineStartX] = GetPortionAndLine(aDocPos); pPortion) { - sal_Int32 nCurIndex - = GetChar(pPortion, pLine, aDocPos.X() - nLineStartX, bSmart); + assert(pLine); + assert(pPortion); + sal_Int32 nCurIndex = GetChar(*pPortion, *pLine, aDocPos.X() - nLineStartX, bSmart); EditPaM aPaM(pPortion->GetNode(), nCurIndex); if (nCurIndex && (nCurIndex == pLine->GetEnd()) @@ -3258,7 +3362,9 @@ bool ImpEditEngine::IsTextPos(const Point& rDocPos, sal_uInt16 nBorder) { if (const auto& [pPortion, pLine, nLineStartX] = GetPortionAndLine(rDocPos); pPortion) { - Range aLineXPosStartEnd = GetLineXPosStartEnd(pPortion, pLine); + assert(pLine); + assert(pPortion); + Range aLineXPosStartEnd = GetLineXPosStartEnd(*pPortion, *pLine); if ((rDocPos.X() >= nLineStartX + aLineXPosStartEnd.Min() - nBorder) && (rDocPos.X() <= nLineStartX + aLineXPosStartEnd.Max() + nBorder)) return true; @@ -3268,9 +3374,9 @@ bool ImpEditEngine::IsTextPos(const Point& rDocPos, sal_uInt16 nBorder) sal_uInt32 ImpEditEngine::GetTextHeight() const { - OSL_ENSURE( GetUpdateMode(), "Should not be used for Update=FALSE: GetTextHeight" ); + assert( IsUpdateLayout() && "Should not be used for Update=FALSE: GetTextHeight" ); OSL_ENSURE( IsFormatted() || IsFormatting(), "GetTextHeight: Not formatted" ); - return nCurTextHeight; + return mnCurTextHeight; } sal_uInt32 ImpEditEngine::CalcTextWidth( bool bIgnoreExtraSpace ) @@ -3304,38 +3410,39 @@ sal_uInt32 ImpEditEngine::CalcParaWidth( sal_Int32 nPara, bool bIgnoreExtraSpace // Over all the paragraphs ... - ParaPortion& rPortion = GetParaPortions()[nPara]; - if ( rPortion.IsVisible() ) + OSL_ENSURE(GetParaPortions().exists(nPara), "CalcParaWidth: Out of range"); + ParaPortion* pPortion = GetParaPortions().SafeGetObject(nPara); + if ( pPortion && pPortion->IsVisible() ) { - const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( rPortion.GetNode() ); - sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( rPortion.GetNode() ); + const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pPortion->GetNode() ); + sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pPortion->GetNode() ); // On the lines of the paragraph ... - sal_Int32 nLines = rPortion.GetLines().Count(); + sal_Int32 nLines = pPortion->GetLines().Count(); for ( sal_Int32 nLine = 0; nLine < nLines; nLine++ ) { - EditLine& rLine = rPortion.GetLines()[nLine]; + EditLine const& rLine = pPortion->GetLines()[nLine]; // nCurWidth = pLine->GetStartPosX(); // For Center- or Right- alignment it depends on the paper // width, here not preferred. I general, it is best not leave it // to StartPosX, also the right indents have to be taken into // account! - tools::Long nCurWidth = GetXValue( rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth ); + tools::Long nCurWidth = scaleXSpacingValue(rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth); if ( nLine == 0 ) { - tools::Long nFI = GetXValue( rLRItem.GetTextFirstLineOffset() ); + tools::Long nFI = scaleXSpacingValue(rLRItem.GetTextFirstLineOffset()); nCurWidth -= nFI; - if ( rPortion.GetBulletX() > nCurWidth ) + if ( pPortion->GetBulletX() > nCurWidth ) { nCurWidth += nFI; // LI? - if ( rPortion.GetBulletX() > nCurWidth ) - nCurWidth = rPortion.GetBulletX(); + if ( pPortion->GetBulletX() > nCurWidth ) + nCurWidth = pPortion->GetBulletX(); } } - nCurWidth += GetXValue( rLRItem.GetRight() ); - nCurWidth += CalcLineWidth( &rPortion, &rLine, bIgnoreExtraSpace ); + nCurWidth += scaleXSpacingValue(rLRItem.GetRight()); + nCurWidth += CalcLineWidth(*pPortion, rLine, bIgnoreExtraSpace); if ( nCurWidth > nMaxWidth ) { nMaxWidth = nCurWidth; @@ -3347,13 +3454,13 @@ sal_uInt32 ImpEditEngine::CalcParaWidth( sal_Int32 nPara, bool bIgnoreExtraSpace return static_cast<sal_uInt32>(nMaxWidth); } -sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, bool bIgnoreExtraSpace ) +sal_uInt32 ImpEditEngine::CalcLineWidth(ParaPortion const& rPortion, EditLine const& rLine, bool bIgnoreExtraSpace) { - sal_Int32 nPara = GetEditDoc().GetPos( pPortion->GetNode() ); + sal_Int32 nPara = GetEditDoc().GetPos(rPortion.GetNode()); // #114278# Saving both layout mode and language (since I'm // potentially changing both) - GetRefDevice()->Push( PushFlags::TEXTLAYOUTMODE|PushFlags::TEXTLANGUAGE ); + GetRefDevice()->Push( vcl::PushFlags::TEXTLAYOUTMODE|vcl::PushFlags::TEXTLANGUAGE ); ImplInitLayoutMode(*GetRefDevice(), nPara, -1); @@ -3361,10 +3468,10 @@ sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, // Calculation of the width without the Indents ... sal_uInt32 nWidth = 0; - sal_Int32 nPos = pLine->GetStart(); - for ( sal_Int32 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ ) + sal_Int32 nPos = rLine.GetStart(); + for ( sal_Int32 nTP = rLine.GetStartPortion(); nTP <= rLine.GetEndPortion(); nTP++ ) { - const TextPortion& rTextPortion = pPortion->GetTextPortions()[nTP]; + const TextPortion& rTextPortion = rPortion.GetTextPortions()[nTP]; switch ( rTextPortion.GetKind() ) { case PortionKind::FIELD: @@ -3382,11 +3489,12 @@ sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, } else { - SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() ); - SeekCursor( pPortion->GetNode(), nPos+1, aTmpFont ); + SvxFont aTmpFont(rPortion.GetNode()->GetCharAttribs().GetDefFont()); + SeekCursor(rPortion.GetNode(), nPos + 1, aTmpFont); aTmpFont.SetPhysFont(*GetRefDevice()); ImplInitDigitMode(*GetRefDevice(), aTmpFont.GetLanguage()); - nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), pPortion->GetNode()->GetString(), nPos, rTextPortion.GetLen() ).Width(); + nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), + rPortion.GetNode()->GetString(), nPos, rTextPortion.GetLen(), nullptr ).Width(); } } break; @@ -3402,9 +3510,9 @@ sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, sal_uInt32 ImpEditEngine::GetTextHeightNTP() const { - DBG_ASSERT( GetUpdateMode(), "Should not be used for Update=FALSE: GetTextHeight" ); + assert( IsUpdateLayout() && "Should not be used for Update=FALSE: GetTextHeight" ); DBG_ASSERT( IsFormatted() || IsFormatting(), "GetTextHeight: Not formatted" ); - return nCurTextHeightNTP; + return mnCurTextHeightNTP; } tools::Long ImpEditEngine::Calc1ColumnTextHeight(tools::Long* pHeightNTP) @@ -3413,13 +3521,13 @@ tools::Long ImpEditEngine::Calc1ColumnTextHeight(tools::Long* pHeightNTP) if (pHeightNTP) *pHeightNTP = 0; // Pretend that we have ~infinite height to get total height - comphelper::ValueRestorationGuard aGuard(nCurTextHeight, - std::numeric_limits<tools::Long>::max()); + comphelper::ValueRestorationGuard aGuard(mnCurTextHeight, std::numeric_limits<tools::Long>::max()); - auto FindLastLineBottom = [&](const LineAreaInfo& rInfo) { + IterateLinesAreasFunc FindLastLineBottom = [&](const LineAreaInfo& rInfo) { if (rInfo.pLine) { - nHeight = getBottomDirectionAware(rInfo.aArea) + 1; + // bottom coordinate does not belong to area, so no need to do +1 + nHeight = getBottomDocOffset(rInfo.aArea); if (pHeightNTP && !rInfo.rPortion.IsEmpty()) *pHeightNTP = nHeight; } @@ -3431,7 +3539,7 @@ tools::Long ImpEditEngine::Calc1ColumnTextHeight(tools::Long* pHeightNTP) tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) { - OSL_ENSURE( GetUpdateMode(), "Should not be used when Update=FALSE: CalcTextHeight" ); + assert( IsUpdateLayout() && "Should not be used when Update=FALSE: CalcTextHeight" ); if (mnColumns <= 1) return Calc1ColumnTextHeight(pHeightNTP); // All text fits into a single column - done! @@ -3442,11 +3550,9 @@ tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) tools::Long nTentativeColHeight = mnMinColumnWrapHeight; tools::Long nWantedIncrease = 0; tools::Long nCurrentTextHeight; - if (pHeightNTP) - *pHeightNTP = 0; // This does the necessary column balancing for the case when the text does not fit min height. - // When the height of column (taken from nCurTextHeight) is too small, the last column will + // When the height of column (taken from mnCurTextHeight) is too small, the last column will // overflow, so the resulting height of the text will exceed the set column height. Increasing // the column height step by step by the minimal value that allows one of columns to accommodate // one line more, we finally get to the point where all the text fits. At each iteration, the @@ -3492,7 +3598,9 @@ tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) nTentativeColHeight += nWantedIncrease; nWantedIncrease = std::numeric_limits<tools::Long>::max(); nCurrentTextHeight = 0; - auto GetHeightAndWantedIncrease = [&, minHeight = tools::Long(0), lastCol = sal_Int32(0)]( + if (pHeightNTP) + *pHeightNTP = 0; + auto GetHeightAndWantedIncrease = [&, minHeight = tools::Long(0), lastCol = sal_Int16(0)]( const LineAreaInfo& rInfo) mutable { if (rInfo.pLine) { @@ -3501,13 +3609,13 @@ tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) minHeight = std::max(nCurrentTextHeight, minHeight); // total height can't be less than previous columns nWantedIncrease = std::min(rInfo.nHeightNeededToNotWrap, nWantedIncrease); + lastCol = rInfo.nColumn; } - lastCol = rInfo.nColumn; - nCurrentTextHeight = std::max(getBottomDirectionAware(rInfo.aArea) + 1, minHeight); + // bottom coordinate does not belong to area, so no need to do +1 + nCurrentTextHeight = std::max(getBottomDocOffset(rInfo.aArea), minHeight); if (pHeightNTP) { if (rInfo.rPortion.IsEmpty()) - *pHeightNTP = std::max(*pHeightNTP, minHeight); else *pHeightNTP = nCurrentTextHeight; @@ -3515,16 +3623,17 @@ tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) } return CallbackResult::Continue; }; - comphelper::ValueRestorationGuard aGuard(nCurTextHeight, nTentativeColHeight); + comphelper::ValueRestorationGuard aGuard(mnCurTextHeight, nTentativeColHeight); IterateLineAreas(GetHeightAndWantedIncrease, IterFlag::none); - } while (nCurrentTextHeight > nTentativeColHeight && nWantedIncrease > 0); + } while (nCurrentTextHeight > nTentativeColHeight && nWantedIncrease > 0 + && nWantedIncrease != std::numeric_limits<tools::Long>::max()); return nCurrentTextHeight; } sal_Int32 ImpEditEngine::GetLineCount( sal_Int32 nParagraph ) const { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" ); - const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineCount: Out of range"); + const ParaPortion* pPPortion = GetParaPortions().SafeGetObject(nParagraph); OSL_ENSURE( pPPortion, "Paragraph not found: GetLineCount" ); if ( pPPortion ) return pPPortion->GetLines().Count(); @@ -3534,9 +3643,9 @@ sal_Int32 ImpEditEngine::GetLineCount( sal_Int32 nParagraph ) const sal_Int32 ImpEditEngine::GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) const { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineLen: Out of range" ); - const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); - OSL_ENSURE( pPPortion, "Paragraph not found: GetLineLen" ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineLen: Out of range"); + const ParaPortion* pPPortion = GetParaPortions().SafeGetObject(nParagraph); + OSL_ENSURE(pPPortion, "Paragraph not found: GetLineLen"); if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) ) { const EditLine& rLine = pPPortion->GetLines()[nLine]; @@ -3548,7 +3657,7 @@ sal_Int32 ImpEditEngine::GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) con void ImpEditEngine::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineCount: Out of range"); const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); OSL_ENSURE( pPPortion, "Paragraph not found: GetLineBoundaries" ); rStart = rEnd = -1; // default values in case of error @@ -3589,7 +3698,7 @@ sal_Int32 ImpEditEngine::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex sal_uInt16 ImpEditEngine::GetLineHeight( sal_Int32 nParagraph, sal_Int32 nLine ) { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineCount: Out of range"); ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); OSL_ENSURE( pPPortion, "Paragraph not found: GetLineHeight" ); if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) ) @@ -3601,11 +3710,11 @@ sal_uInt16 ImpEditEngine::GetLineHeight( sal_Int32 nParagraph, sal_Int32 nLine ) return 0xFFFF; } -sal_uInt32 ImpEditEngine::GetParaHeight( sal_Int32 nParagraph ) +sal_uInt32 ImpEditEngine::GetParaHeight(sal_Int32 nParagraph) const { sal_uInt32 nHeight = 0; - ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); + ParaPortion const* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); OSL_ENSURE( pPPortion, "Paragraph not found: GetParaHeight" ); if ( pPPortion ) @@ -3618,11 +3727,11 @@ void ImpEditEngine::UpdateSelections() { // Check whether one of the selections is at a deleted node... // If the node is valid, the index has yet to be examined! - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - EditSelection aCurSel( pView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pView->getImpl().GetEditSelection() ); bool bChanged = false; - for (const std::unique_ptr<DeletedNodeInfo> & aDeletedNode : aDeletedNodes) + for (const std::unique_ptr<DeletedNodeInfo> & aDeletedNode : maDeletedNodes) { const DeletedNodeInfo& rInf = *aDeletedNode; if ( ( aCurSel.Min().GetNode() == rInf.GetNode() ) || @@ -3631,26 +3740,27 @@ void ImpEditEngine::UpdateSelections() // Use ParaPortions, as now also hidden paragraphs have to be // taken into account! sal_Int32 nPara = rInf.GetPosition(); - if (!GetParaPortions().SafeGetObject(nPara)) // Last paragraph + if (!GetParaPortions().exists(nPara)) // Last paragraph { - nPara = GetParaPortions().Count()-1; + nPara = GetParaPortions().lastIndex(); } + assert(GetParaPortions().exists(nPara) && "Empty Document in UpdateSelections ?"); // Do not end up from a hidden paragraph: - sal_Int32 nCurPara = nPara; - sal_Int32 nLastPara = GetParaPortions().Count()-1; - while ( nPara <= nLastPara && !GetParaPortions()[nPara].IsVisible() ) + sal_Int32 nCurrentPara = nPara; + sal_Int32 nLastParaIndex = GetParaPortions().lastIndex(); + while (nPara <= nLastParaIndex && !GetParaPortions().getRef(nPara).IsVisible()) nPara++; - if ( nPara > nLastPara ) // then also backwards ... + if (nPara > nLastParaIndex) // then also backwards ... { - nPara = nCurPara; - while ( nPara && !GetParaPortions()[nPara].IsVisible() ) + nPara = nCurrentPara; + while ( nPara && !GetParaPortions().getRef(nPara).IsVisible() ) nPara--; } - OSL_ENSURE( GetParaPortions()[nPara].IsVisible(), "No visible paragraph found: UpdateSelections" ); + OSL_ENSURE(GetParaPortions().getRef(nPara).IsVisible(), "No visible paragraph found: UpdateSelections" ); - ParaPortion& rParaPortion = GetParaPortions()[nPara]; - EditSelection aTmpSelection( EditPaM( rParaPortion.GetNode(), 0 ) ); - pView->pImpEditView->SetEditSelection( aTmpSelection ); + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); + EditSelection aTmpSelection(EditPaM(rParaPortion.GetNode(), 0)); + pView->getImpl().SetEditSelection( aTmpSelection ); bChanged=true; break; // for loop } @@ -3661,16 +3771,16 @@ void ImpEditEngine::UpdateSelections() if ( aCurSel.Min().GetIndex() > aCurSel.Min().GetNode()->Len() ) { aCurSel.Min().SetIndex( aCurSel.Min().GetNode()->Len() ); - pView->pImpEditView->SetEditSelection( aCurSel ); + pView->getImpl().SetEditSelection( aCurSel ); } if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() ) { aCurSel.Max().SetIndex( aCurSel.Max().GetNode()->Len() ); - pView->pImpEditView->SetEditSelection( aCurSel ); + pView->getImpl().SetEditSelection( aCurSel ); } } } - aDeletedNodes.clear(); + maDeletedNodes.clear(); } EditSelection ImpEditEngine::ConvertSelection( @@ -3679,11 +3789,11 @@ EditSelection ImpEditEngine::ConvertSelection( EditSelection aNewSelection; // Start... - ContentNode* pNode = aEditDoc.GetObject( nStartPara ); + ContentNode* pNode = maEditDoc.GetObject( nStartPara ); sal_Int32 nIndex = nStartPos; if ( !pNode ) { - pNode = aEditDoc[ aEditDoc.Count()-1 ]; + pNode = maEditDoc.GetObject(maEditDoc.Count() - 1); nIndex = pNode->Len(); } else if ( nIndex > pNode->Len() ) @@ -3693,11 +3803,11 @@ EditSelection ImpEditEngine::ConvertSelection( aNewSelection.Min().SetIndex( nIndex ); // End... - pNode = aEditDoc.GetObject( nEndPara ); + pNode = maEditDoc.GetObject( nEndPara ); nIndex = nEndPos; if ( !pNode ) { - pNode = aEditDoc[ aEditDoc.Count()-1 ]; + pNode = maEditDoc.GetObject(maEditDoc.Count() - 1); nIndex = pNode->Len(); } else if ( nIndex > pNode->Len() ) @@ -3714,16 +3824,16 @@ void ImpEditEngine::SetActiveView( EditView* pView ) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Actually, now bHasVisSel and HideSelection would be necessary !!! - if ( pView == pActiveView ) + if (pView == mpActiveView) return; - if ( pActiveView && pActiveView->HasSelection() ) - pActiveView->pImpEditView->DrawSelectionXOR(); + if (mpActiveView && mpActiveView->HasSelection()) + mpActiveView->getImpl().DrawSelectionXOR(); - pActiveView = pView; + mpActiveView = pView; - if ( pActiveView && pActiveView->HasSelection() ) - pActiveView->pImpEditView->DrawSelectionXOR(); + if (mpActiveView && mpActiveView->HasSelection()) + mpActiveView->getImpl().DrawSelectionXOR(); // NN: Quick fix for #78668#: // When editing of a cell in Calc is ended, the edit engine is not deleted, @@ -3786,7 +3896,7 @@ uno::Reference< datatransfer::XTransferable > ImpEditEngine::CreateTransferable( return pDataObj; } -EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial ) +EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial, SotClipboardFormatId format) { EditSelection aNewSelection( rPaM ); @@ -3800,7 +3910,7 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera { // XML SotExchange::GetFormatDataFlavor( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT, aFlavor ); - if ( rxDataObj->isDataFlavorSupported( aFlavor ) ) + if ( rxDataObj->isDataFlavorSupported( aFlavor ) && (SotClipboardFormatId::NONE == format || SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT == format)) { try { @@ -3828,7 +3938,7 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera SotExchange::GetFormatDataFlavor( SotClipboardFormatId::RICHTEXT, aFlavorRichtext ); bool bRtfSupported = rxDataObj->isDataFlavorSupported( aFlavor ); bool bRichtextSupported = rxDataObj->isDataFlavorSupported( aFlavorRichtext ); - if ( bRtfSupported || bRichtextSupported ) + if ( (bRtfSupported || bRichtextSupported) && (SotClipboardFormatId::NONE == format || SotClipboardFormatId::RICHTEXT == format || SotClipboardFormatId::RTF == format)) { if(bRichtextSupported) { @@ -3850,6 +3960,55 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera } } } + if (!bDone) { + // HTML_SIMPLE + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML_SIMPLE, aFlavor); + bool bHtmlSupported = rxDataObj->isDataFlavorSupported(aFlavor); + if (bHtmlSupported && (SotClipboardFormatId::NONE == format || SotClipboardFormatId::HTML_SIMPLE == format)) { + MSE40HTMLClipFormatObj aMSE40HTMLClipFormatObj; + try + { + uno::Any aData = rxDataObj->getTransferData(aFlavor); + uno::Sequence< sal_Int8 > aSeq; + aData >>= aSeq; + { + SvMemoryStream aHtmlStream(aSeq.getArray(), aSeq.getLength(), StreamMode::READ); + SvStream* pHtmlStream = aMSE40HTMLClipFormatObj.IsValid(aHtmlStream); + if (pHtmlStream != nullptr) { + aNewSelection = Read(*pHtmlStream, rBaseURL, EETextFormat::Html, rPaM); + } + } + bDone = true; + } + catch (const css::uno::Exception&) + { + } + } + } + + if (!bDone) + { + // HTML + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML, aFlavor); + bool bHtmlSupported = rxDataObj->isDataFlavorSupported(aFlavor); + if (bHtmlSupported + && (format == SotClipboardFormatId::NONE || format == SotClipboardFormatId::HTML)) + { + try + { + uno::Any aData = rxDataObj->getTransferData(aFlavor); + uno::Sequence<sal_Int8> aSeq; + aData >>= aSeq; + SvMemoryStream aHtmlStream(aSeq.getArray(), aSeq.getLength(), StreamMode::READ); + aNewSelection = Read(aHtmlStream, rBaseURL, EETextFormat::Html, rPaM); + bDone = true; + } + catch (const css::uno::Exception&) + { + TOOLS_WARN_EXCEPTION("editeng", "HTML paste failed"); + } + } + } } if ( !bDone ) { @@ -3873,20 +4032,17 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera return aNewSelection; } -sal_Int32 ImpEditEngine::GetChar( - const ParaPortion* pParaPortion, const EditLine* pLine, tools::Long nXPos, bool bSmart) +sal_Int32 ImpEditEngine::GetChar(ParaPortion const& rParaPortion, EditLine const& rLine, tools::Long nXPos, bool bSmart) { - OSL_ENSURE( pLine, "No line received: GetChar" ); - sal_Int32 nChar = -1; - sal_Int32 nCurIndex = pLine->GetStart(); + sal_Int32 nCurIndex = rLine.GetStart(); // Search best matching portion with GetPortionXOffset() - for ( sal_Int32 i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ ) + for ( sal_Int32 i = rLine.GetStartPortion(); i <= rLine.GetEndPortion(); i++ ) { - const TextPortion& rPortion = pParaPortion->GetTextPortions()[i]; - tools::Long nXLeft = GetPortionXOffset( pParaPortion, pLine, i ); + const TextPortion& rPortion = rParaPortion.GetTextPortions()[i]; + tools::Long nXLeft = GetPortionXOffset(rParaPortion, rLine, i); tools::Long nXRight = nXLeft + rPortion.GetSize().Width(); if ( ( nXLeft <= nXPos ) && ( nXRight >= nXPos ) ) { @@ -3910,7 +4066,7 @@ sal_Int32 ImpEditEngine::GetChar( { sal_Int32 nMax = rPortion.GetLen(); sal_Int32 nOffset = -1; - sal_Int32 nTmpCurIndex = nChar - pLine->GetStart(); + sal_Int32 nTmpCurIndex = nChar - rLine.GetStart(); tools::Long nXInPortion = nXPos - nXLeft; if ( rPortion.IsRightToLeft() ) @@ -3919,25 +4075,26 @@ sal_Int32 ImpEditEngine::GetChar( // Search in Array... for ( sal_Int32 x = 0; x < nMax; x++ ) { - tools::Long nTmpPosMax = pLine->GetCharPosArray()[nTmpCurIndex+x]; + tools::Long nTmpPosMax = rLine.GetCharPosArray()[nTmpCurIndex+x]; if ( nTmpPosMax > nXInPortion ) { // Check whether this or the previous... - tools::Long nTmpPosMin = x ? pLine->GetCharPosArray()[nTmpCurIndex+x-1] : 0; + tools::Long nTmpPosMin = x ? rLine.GetCharPosArray()[nTmpCurIndex+x-1] : 0; tools::Long nDiffLeft = nXInPortion - nTmpPosMin; tools::Long nDiffRight = nTmpPosMax - nXInPortion; OSL_ENSURE( nDiffLeft >= 0, "DiffLeft negative" ); OSL_ENSURE( nDiffRight >= 0, "DiffRight negative" ); - nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? x+1 : x; - // I18N: If there are character position with the length of 0, - // they belong to the same character, we can not use this position as an index. - // Skip all 0-positions, cheaper than using XBreakIterator: - if ( nOffset < nMax ) + + if (bSmart && nDiffRight < nDiffLeft) { - const tools::Long nX = pLine->GetCharPosArray()[nOffset]; - while ( ( (nOffset+1) < nMax ) && ( pLine->GetCharPosArray()[nOffset+1] == nX ) ) - nOffset++; + // I18N: If there are character position with the length of 0, + // they belong to the same character, we can not use this position as an index. + // Skip all 0-positions, cheaper than using XBreakIterator: + tools::Long nX = rLine.GetCharPosArray()[nTmpCurIndex + x]; + while(x < nMax && rLine.GetCharPosArray()[nTmpCurIndex + x] == nX) + ++x; } + nOffset = x; break; } } @@ -3953,9 +4110,9 @@ sal_Int32 ImpEditEngine::GetChar( nChar = nChar + nOffset; // Check if index is within a cell: - if ( nChar && ( nChar < pParaPortion->GetNode()->Len() ) ) + if ( nChar && ( nChar < rParaPortion.GetNode()->Len() ) ) { - EditPaM aPaM( pParaPortion->GetNode(), nChar+1 ); + EditPaM aPaM( rParaPortion.GetNode(), nChar+1 ); sal_uInt16 nScriptType = GetI18NScriptType( aPaM ); if ( nScriptType == i18n::ScriptType::COMPLEX ) { @@ -3963,9 +4120,9 @@ sal_Int32 ImpEditEngine::GetChar( sal_Int32 nCount = 1; lang::Locale aLocale = GetLocale( aPaM ); sal_Int32 nRight = _xBI->nextCharacters( - pParaPortion->GetNode()->GetString(), nChar, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); + rParaPortion.GetNode()->GetString(), nChar, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); sal_Int32 nLeft = _xBI->previousCharacters( - pParaPortion->GetNode()->GetString(), nRight, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); + rParaPortion.GetNode()->GetString(), nRight, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); if ( ( nLeft != nChar ) && ( nRight != nChar ) ) { nChar = ( std::abs( nRight - nChar ) < std::abs( nLeft - nChar ) ) ? nRight : nLeft; @@ -3973,7 +4130,7 @@ sal_Int32 ImpEditEngine::GetChar( } else { - OUString aStr(pParaPortion->GetNode()->GetString()); + OUString aStr(rParaPortion.GetNode()->GetString()); // tdf#102625: don't select middle of a pair of surrogates with mouse cursor if (rtl::isSurrogate(aStr[nChar])) --nChar; @@ -3987,40 +4144,38 @@ sal_Int32 ImpEditEngine::GetChar( if ( nChar == -1 ) { - nChar = ( nXPos <= pLine->GetStartPosX() ) ? pLine->GetStart() : pLine->GetEnd(); + nChar = ( nXPos <= rLine.GetStartPosX() ) ? rLine.GetStart() : rLine.GetEnd(); } return nChar; } -Range ImpEditEngine::GetLineXPosStartEnd( const ParaPortion* pParaPortion, const EditLine* pLine ) const +Range ImpEditEngine::GetLineXPosStartEnd(ParaPortion const& rParaPortion, EditLine const& rLine) const { Range aLineXPosStartEnd; - sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() ); + sal_Int32 nPara = GetEditDoc().GetPos(rParaPortion.GetNode()); if ( !IsRightToLeft( nPara ) ) { - aLineXPosStartEnd.Min() = pLine->GetStartPosX(); - aLineXPosStartEnd.Max() = pLine->GetStartPosX() + pLine->GetTextWidth(); + aLineXPosStartEnd.Min() = rLine.GetStartPosX(); + aLineXPosStartEnd.Max() = rLine.GetStartPosX() + rLine.GetTextWidth(); } else { - aLineXPosStartEnd.Min() = GetPaperSize().Width() - ( pLine->GetStartPosX() + pLine->GetTextWidth() ); - aLineXPosStartEnd.Max() = GetPaperSize().Width() - pLine->GetStartPosX(); + aLineXPosStartEnd.Min() = GetPaperSize().Width() - (rLine.GetStartPosX() + rLine.GetTextWidth()); + aLineXPosStartEnd.Max() = GetPaperSize().Width() - rLine.GetStartPosX(); } - return aLineXPosStartEnd; } -tools::Long ImpEditEngine::GetPortionXOffset( - const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nTextPortion) const +tools::Long ImpEditEngine::GetPortionXOffset(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nTextPortion) const { - tools::Long nX = pLine->GetStartPosX(); + tools::Long nX = rLine.GetStartPosX(); - for ( sal_Int32 i = pLine->GetStartPortion(); i < nTextPortion; i++ ) + for ( sal_Int32 i = rLine.GetStartPortion(); i < nTextPortion; i++ ) { - const TextPortion& rPortion = pParaPortion->GetTextPortions()[i]; + const TextPortion& rPortion = rParaPortion.GetTextPortions()[i]; switch ( rPortion.GetKind() ) { case PortionKind::FIELD: @@ -4035,19 +4190,19 @@ tools::Long ImpEditEngine::GetPortionXOffset( } } - sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() ); + sal_Int32 nPara = GetEditDoc().GetPos(rParaPortion.GetNode()); bool bR2LPara = IsRightToLeft( nPara ); - const TextPortion& rDestPortion = pParaPortion->GetTextPortions()[nTextPortion]; + const TextPortion& rDestPortion = rParaPortion.GetTextPortions()[nTextPortion]; if ( rDestPortion.GetKind() != PortionKind::TAB ) { if ( !bR2LPara && rDestPortion.GetRightToLeftLevel() ) { // Portions behind must be added, visual before this portion sal_Int32 nTmpPortion = nTextPortion+1; - while ( nTmpPortion <= pLine->GetEndPortion() ) + while ( nTmpPortion <= rLine.GetEndPortion() ) { - const TextPortion& rNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rNextTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( rNextTextPortion.GetRightToLeftLevel() && ( rNextTextPortion.GetKind() != PortionKind::TAB ) ) nX += rNextTextPortion.GetSize().Width(); else @@ -4056,10 +4211,10 @@ tools::Long ImpEditEngine::GetPortionXOffset( } // Portions before must be removed, visual behind this portion nTmpPortion = nTextPortion; - while ( nTmpPortion > pLine->GetStartPortion() ) + while ( nTmpPortion > rLine.GetStartPortion() ) { --nTmpPortion; - const TextPortion& rPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rPrevTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( rPrevTextPortion.GetRightToLeftLevel() && ( rPrevTextPortion.GetKind() != PortionKind::TAB ) ) nX -= rPrevTextPortion.GetSize().Width(); else @@ -4070,9 +4225,9 @@ tools::Long ImpEditEngine::GetPortionXOffset( { // Portions behind must be removed, visual behind this portion sal_Int32 nTmpPortion = nTextPortion+1; - while ( nTmpPortion <= pLine->GetEndPortion() ) + while ( nTmpPortion <= rLine.GetEndPortion() ) { - const TextPortion& rNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rNextTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( !rNextTextPortion.IsRightToLeft() && ( rNextTextPortion.GetKind() != PortionKind::TAB ) ) nX += rNextTextPortion.GetSize().Width(); else @@ -4081,10 +4236,10 @@ tools::Long ImpEditEngine::GetPortionXOffset( } // Portions before must be added, visual before this portion nTmpPortion = nTextPortion; - while ( nTmpPortion > pLine->GetStartPortion() ) + while ( nTmpPortion > rLine.GetStartPortion() ) { --nTmpPortion; - const TextPortion& rPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rPrevTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( !rPrevTextPortion.IsRightToLeft() && ( rPrevTextPortion.GetKind() != PortionKind::TAB ) ) nX -= rPrevTextPortion.GetSize().Width(); else @@ -4104,33 +4259,31 @@ tools::Long ImpEditEngine::GetPortionXOffset( return nX; } -tools::Long ImpEditEngine::GetXPos( - const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart) const +tools::Long ImpEditEngine::GetXPos(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nIndex, bool bPreferPortionStart) const { - OSL_ENSURE( pLine, "No line received: GetXPos" ); - OSL_ENSURE( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "GetXPos has to be called properly!" ); + OSL_ENSURE( ( nIndex >= rLine.GetStart() ) && ( nIndex <= rLine.GetEnd() ) , "GetXPos has to be called properly!" ); bool bDoPreferPortionStart = bPreferPortionStart; // Assure that the portion belongs to this line: - if ( nIndex == pLine->GetStart() ) + if ( nIndex == rLine.GetStart() ) bDoPreferPortionStart = true; - else if ( nIndex == pLine->GetEnd() ) + else if ( nIndex == rLine.GetEnd() ) bDoPreferPortionStart = false; sal_Int32 nTextPortionStart = 0; - sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart ); + sal_Int32 nTextPortion = rParaPortion.GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart ); - OSL_ENSURE( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " ); + OSL_ENSURE( ( nTextPortion >= rLine.GetStartPortion() ) && ( nTextPortion <= rLine.GetEndPortion() ), "GetXPos: Portion not in current line! " ); - const TextPortion& rPortion = pParaPortion->GetTextPortions()[nTextPortion]; + const TextPortion& rPortion = rParaPortion.GetTextPortions()[nTextPortion]; - tools::Long nX = GetPortionXOffset( pParaPortion, pLine, nTextPortion ); + tools::Long nX = GetPortionXOffset(rParaPortion, rLine, nTextPortion); // calc text width, portion size may include CJK/CTL spacing... // But the array might not be init yet, if using text ranger this method is called within CreateLines()... tools::Long nPortionTextWidth = rPortion.GetSize().Width(); if ( ( rPortion.GetKind() == PortionKind::TEXT ) && rPortion.GetLen() && !GetTextRanger() ) - nPortionTextWidth = pLine->GetCharPosArray()[nTextPortionStart + rPortion.GetLen() - 1 - pLine->GetStart()]; + nPortionTextWidth = rLine.GetCharPosArray()[nTextPortionStart + rPortion.GetLen() - 1 - rLine.GetStart()]; if ( nTextPortionStart != nIndex ) { @@ -4140,18 +4293,18 @@ tools::Long ImpEditEngine::GetXPos( // End of Portion if ( rPortion.GetKind() == PortionKind::TAB ) { - if ( nTextPortion+1 < pParaPortion->GetTextPortions().Count() ) + if ( nTextPortion+1 < rParaPortion.GetTextPortions().Count() ) { - const TextPortion& rNextPortion = pParaPortion->GetTextPortions()[nTextPortion+1]; + const TextPortion& rNextPortion = rParaPortion.GetTextPortions()[nTextPortion+1]; if ( rNextPortion.GetKind() != PortionKind::TAB ) { if ( !bPreferPortionStart ) - nX = GetXPos( pParaPortion, pLine, nIndex, true ); - else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) ) + nX = GetXPos(rParaPortion, rLine, nIndex, true ); + else if ( !IsRightToLeft( GetEditDoc().GetPos(rParaPortion.GetNode()) ) ) nX += nPortionTextWidth; } } - else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) ) + else if ( !IsRightToLeft( GetEditDoc().GetPos(rParaPortion.GetNode()) ) ) { nX += nPortionTextWidth; } @@ -4163,20 +4316,20 @@ tools::Long ImpEditEngine::GetXPos( } else if ( rPortion.GetKind() == PortionKind::TEXT ) { - OSL_ENSURE( nIndex != pLine->GetStart(), "Strange behavior in new GetXPos()" ); - OSL_ENSURE( pLine && !pLine->GetCharPosArray().empty(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?" ); + OSL_ENSURE( nIndex != rLine.GetStart(), "Strange behavior in new GetXPos()" ); + OSL_ENSURE( !rLine.GetCharPosArray().empty(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?" ); - if( !pLine->GetCharPosArray().empty() ) + if( !rLine.GetCharPosArray().empty() ) { - sal_Int32 nPos = nIndex - 1 - pLine->GetStart(); - if (nPos < 0 || nPos >= static_cast<sal_Int32>(pLine->GetCharPosArray().size())) + sal_Int32 nPos = nIndex - 1 - rLine.GetStart(); + if (nPos < 0 || o3tl::make_unsigned(nPos) >= rLine.GetCharPosArray().size()) { - nPos = pLine->GetCharPosArray().size()-1; + nPos = rLine.GetCharPosArray().size()-1; OSL_FAIL("svx::ImpEditEngine::GetXPos(), index out of range!"); } // old code restored see #i112788 (which leaves #i74188 unfixed again) - tools::Long nPosInPortion = pLine->GetCharPosArray()[nPos]; + tools::Long nPosInPortion = rLine.GetCharPosArray()[nPos]; if ( !rPortion.IsRightToLeft() ) { @@ -4192,17 +4345,17 @@ tools::Long ImpEditEngine::GetXPos( nX += rPortion.GetExtraInfos()->nPortionOffsetX; if ( rPortion.GetExtraInfos()->nAsianCompressionTypes & AsianCompressionFlags::PunctuationRight ) { - AsianCompressionFlags nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex ) ); - if ( nType == AsianCompressionFlags::PunctuationRight && !pLine->GetCharPosArray().empty() ) + AsianCompressionFlags nType = GetCharTypeForCompression(rParaPortion.GetNode()->GetChar(nIndex)); + if ( nType == AsianCompressionFlags::PunctuationRight && !rLine.GetCharPosArray().empty() ) { sal_Int32 n = nIndex - nTextPortionStart; - const tools::Long* pDXArray = pLine->GetCharPosArray().data()+( nTextPortionStart-pLine->GetStart() ); + const sal_Int32* pDXArray = rLine.GetCharPosArray().data() + (nTextPortionStart - rLine.GetStart()); sal_Int32 nCharWidth = ( ( (n+1) < rPortion.GetLen() ) ? pDXArray[n] : rPortion.GetSize().Width() ) - ( n ? pDXArray[n-1] : 0 ); if ( (n+1) < rPortion.GetLen() ) { // smaller, when char behind is AsianCompressionFlags::PunctuationRight also - nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex+1 ) ); + nType = GetCharTypeForCompression(rParaPortion.GetNode()->GetChar(nIndex + 1)); if ( nType == AsianCompressionFlags::PunctuationRight ) { sal_Int32 nNextCharWidth = ( ( (n+2) < rPortion.GetLen() ) ? pDXArray[n+1] : rPortion.GetSize().Width() ) @@ -4224,7 +4377,7 @@ tools::Long ImpEditEngine::GetXPos( } } } - else // if ( nIndex == pLine->GetStart() ) + else // if ( nIndex == rLine.GetStart() ) { if ( rPortion.IsRightToLeft() ) { @@ -4235,48 +4388,66 @@ tools::Long ImpEditEngine::GetXPos( return nX; } -void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) +/** Is true if paragraph is in the empty cluster of paragraphs at the end */ +bool ImpEditEngine::isInEmptyClusterAtTheEnd(ParaPortion& rPortion) { - pPortion->nHeight = 0; - pPortion->nFirstLineOffset = 0; + sal_Int32 nPortion = GetParaPortions().GetPos(&rPortion); - if ( !pPortion->IsVisible() ) + auto& rParagraphs = GetParaPortions(); + if (rParagraphs.Count() <= 0) + return false; + + sal_Int32 nCurrent = rParagraphs.lastIndex(); + while (nCurrent > 0 && rParagraphs.getRef(nCurrent).IsEmpty()) + { + if (nCurrent == nPortion) + return true; + nCurrent--; + } + return false; +} + +void ImpEditEngine::CalcHeight(ParaPortion& rPortion) +{ + rPortion.mnHeight = 0; + rPortion.mnFirstLineOffset = 0; + + if (!rPortion.IsVisible() || isInEmptyClusterAtTheEnd(rPortion)) return; - OSL_ENSURE( pPortion->GetLines().Count(), "Paragraph with no lines in ParaPortion::CalcHeight" ); - for (sal_Int32 nLine = 0; nLine < pPortion->GetLines().Count(); ++nLine) - pPortion->nHeight += pPortion->GetLines()[nLine].GetHeight(); + OSL_ENSURE(rPortion.GetLines().Count(), "Paragraph with no lines in ParaPortion::CalcHeight"); + for (sal_Int32 nLine = 0; nLine < rPortion.GetLines().Count(); ++nLine) + rPortion.mnHeight += rPortion.GetLines()[nLine].GetHeight(); - if ( aStatus.IsOutliner() ) + if (maStatus.IsOutliner()) return; - const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); - const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); - sal_Int32 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); + const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); + sal_Int32 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; if ( nSBL ) { - if ( pPortion->GetLines().Count() > 1 ) - pPortion->nHeight += ( pPortion->GetLines().Count() - 1 ) * nSBL; - if ( aStatus.ULSpaceSummation() ) - pPortion->nHeight += nSBL; + if (rPortion.GetLines().Count() > 1) + rPortion.mnHeight += (rPortion.GetLines().Count() - 1) * nSBL; + if (maStatus.ULSpaceSummation()) + rPortion.mnHeight += nSBL; } - sal_Int32 nPortion = GetParaPortions().GetPos( pPortion ); + sal_Int32 nPortion = GetParaPortions().GetPos(&rPortion); if ( nPortion ) { - sal_uInt16 nUpper = GetYValue( rULItem.GetUpper() ); - pPortion->nHeight += nUpper; - pPortion->nFirstLineOffset = nUpper; + sal_uInt16 nUpper = scaleYSpacingValue(rULItem.GetUpper()); + rPortion.mnHeight += nUpper; + rPortion.mnFirstLineOffset = nUpper; } - if ( nPortion != (GetParaPortions().Count()-1) ) + if (nPortion != GetParaPortions().lastIndex()) { - pPortion->nHeight += GetYValue( rULItem.GetLower() ); // not in the last + rPortion.mnHeight += scaleYSpacingValue(rULItem.GetLower()); // not in the last } - - if ( !nPortion || aStatus.ULSpaceSummation() ) + if ( !nPortion || maStatus.ULSpaceSummation() ) return; ParaPortion* pPrev = GetParaPortions().SafeGetObject( nPortion-1 ); @@ -4292,30 +4463,29 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) // Only Writer3: Do not add up, but minimum distance. // check if distance by LineSpacing > Upper: - sal_uInt16 nExtraSpace = GetYValue( lcl_CalcExtraSpace( rLSItem ) ); - if ( nExtraSpace > pPortion->nFirstLineOffset ) + sal_uInt16 nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rLSItem)); + if (nExtraSpace > rPortion.mnFirstLineOffset) { // Paragraph becomes 'bigger': - pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset ); - pPortion->nFirstLineOffset = nExtraSpace; + rPortion.mnHeight += (nExtraSpace - rPortion.mnFirstLineOffset); + rPortion.mnFirstLineOffset = nExtraSpace; } // Determine nFirstLineOffset now f(pNode) => now f(pNode, pPrev): - sal_uInt16 nPrevLower = GetYValue( rPrevULItem.GetLower() ); + sal_uInt16 nPrevLower = scaleYSpacingValue(rPrevULItem.GetLower()); // This PrevLower is still in the height of PrevPortion ... - if ( nPrevLower > pPortion->nFirstLineOffset ) + if (nPrevLower > rPortion.mnFirstLineOffset) { // Paragraph is 'small': - pPortion->nHeight -= pPortion->nFirstLineOffset; - pPortion->nFirstLineOffset = 0; + rPortion.mnHeight -= rPortion.mnFirstLineOffset; + rPortion.mnFirstLineOffset = 0; } else if ( nPrevLower ) { // Paragraph becomes 'somewhat smaller': - pPortion->nHeight -= nPrevLower; - pPortion->nFirstLineOffset = - pPortion->nFirstLineOffset - nPrevLower; + rPortion.mnHeight -= nPrevLower; + rPortion.mnFirstLineOffset = rPortion.mnFirstLineOffset - nPrevLower; } // I find it not so good, but Writer3 feature: // Check if distance by LineSpacing > Lower: this value is not @@ -4323,39 +4493,39 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) if ( pPrev->IsInvalid() ) return; - nExtraSpace = GetYValue( lcl_CalcExtraSpace( rPrevLSItem ) ); + nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rPrevLSItem)); if ( nExtraSpace > nPrevLower ) { sal_uInt16 nMoreLower = nExtraSpace - nPrevLower; // Paragraph becomes 'bigger', 'grows' downwards: - if ( nMoreLower > pPortion->nFirstLineOffset ) + if ( nMoreLower > rPortion.mnFirstLineOffset ) { - pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset ); - pPortion->nFirstLineOffset = nMoreLower; + rPortion.mnHeight += (nMoreLower - rPortion.mnFirstLineOffset); + rPortion.mnFirstLineOffset = nMoreLower; } } } void ImpEditEngine::SetValidPaperSize( const Size& rNewSz ) { - aPaperSize = rNewSz; + maPaperSize = rNewSz; - tools::Long nMinWidth = aStatus.AutoPageWidth() ? aMinAutoPaperSize.Width() : 0; - tools::Long nMaxWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : 0x7FFFFFFF; - tools::Long nMinHeight = aStatus.AutoPageHeight() ? aMinAutoPaperSize.Height() : 0; - tools::Long nMaxHeight = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : 0x7FFFFFFF; + tools::Long nMinWidth = maStatus.AutoPageWidth() ? maMinAutoPaperSize.Width() : 0; + tools::Long nMaxWidth = maStatus.AutoPageWidth() ? maMaxAutoPaperSize.Width() : 0x7FFFFFFF; + tools::Long nMinHeight = maStatus.AutoPageHeight() ? maMinAutoPaperSize.Height() : 0; + tools::Long nMaxHeight = maStatus.AutoPageHeight() ? maMaxAutoPaperSize.Height() : 0x7FFFFFFF; // Minimum/Maximum width: - if ( aPaperSize.Width() < nMinWidth ) - aPaperSize.setWidth( nMinWidth ); - else if ( aPaperSize.Width() > nMaxWidth ) - aPaperSize.setWidth( nMaxWidth ); + if ( maPaperSize.Width() < nMinWidth ) + maPaperSize.setWidth( nMinWidth ); + else if ( maPaperSize.Width() > nMaxWidth ) + maPaperSize.setWidth( nMaxWidth ); // Minimum/Maximum height: - if ( aPaperSize.Height() < nMinHeight ) - aPaperSize.setHeight( nMinHeight ); - else if ( aPaperSize.Height() > nMaxHeight ) - aPaperSize.setHeight( nMaxHeight ); + if ( maPaperSize.Height() < nMinHeight ) + maPaperSize.setHeight( nMinHeight ); + else if ( maPaperSize.Height() > nMaxHeight ) + maPaperSize.setHeight( nMaxHeight ); } std::shared_ptr<SvxForbiddenCharactersTable> const & ImpEditEngine::GetForbiddenCharsTable() @@ -4372,10 +4542,7 @@ bool ImpEditEngine::IsVisualCursorTravelingEnabled() { bool bVisualCursorTravaling = false; - if( !pCTLOptions ) - pCTLOptions.reset( new SvtCTLOptions ); - - if ( pCTLOptions->IsCTLFontEnabled() && ( pCTLOptions->GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) ) + if ( SvtCTLOptions::IsCTLFontEnabled() && ( SvtCTLOptions::GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) ) { bVisualCursorTravaling = true; } @@ -4392,7 +4559,7 @@ bool ImpEditEngine::DoVisualCursorTraveling() IMPL_LINK_NOARG(ImpEditEngine, DocModified, LinkParamNone*, void) { - aModifyHdl.Call( nullptr /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner + maModifyHdl.Call( nullptr /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index c33db07b2a6b..c0a8b1fc734c 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -24,6 +24,7 @@ #include <vcl/settings.hxx> #include <vcl/window.hxx> +#include <editeng/outliner.hxx> #include <editeng/tstpitem.hxx> #include <editeng/lspcitem.hxx> #include <editeng/flditem.hxx> @@ -41,18 +42,24 @@ #include <editeng/wghtitem.hxx> #include <editeng/postitem.hxx> #include <editeng/langitem.hxx> +#include <editeng/frmdiritem.hxx> #include <editeng/scriptspaceitem.hxx> #include <editeng/charscaleitem.hxx> #include <editeng/numitem.hxx> +#include <outleeng.hxx> +#include <TextPortion.hxx> #include <svtools/colorcfg.hxx> #include <svl/ctloptions.hxx> #include <svl/asiancfg.hxx> +#include <svx/compatflags.hxx> +#include <sfx2/viewsh.hxx> + #include <editeng/hngpnctitem.hxx> #include <editeng/forbiddencharacterstable.hxx> -#include <unotools/configmgr.hxx> +#include <comphelper/configuration.hxx> #include <math.h> #include <vcl/metric.hxx> @@ -63,25 +70,29 @@ #include <i18nlangtag/mslangid.hxx> #include <comphelper/processfactory.hxx> +#include <comphelper/lok.hxx> #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> #include <o3tl/safeint.hxx> #include <o3tl/sorted_vector.hxx> #include <osl/diagnose.h> #include <comphelper/string.hxx> +#include <cstddef> #include <memory> #include <set> #include <vcl/outdev/ScopedStates.hxx> +#include <unicode/uchar.h> + using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::linguistic2; -#define CH_HYPH "-" +constexpr OUString CH_HYPH = u"-"_ustr; -#define WRONG_SHOW_MIN 5 +constexpr tools::Long WRONG_SHOW_MIN = 5; namespace { @@ -105,42 +116,22 @@ struct TabInfo } -Point Rotate( const Point& rPoint, Degree10 nOrientation, const Point& rOrigin ) -{ - double nRealOrientation = nOrientation.get() * F_PI1800; - double nCos = cos( nRealOrientation ); - double nSin = sin( nRealOrientation ); - - Point aRotatedPos; - Point aTranslatedPos( rPoint ); - - // Translation - aTranslatedPos -= rOrigin; - - // Rotation... - aRotatedPos.setX( static_cast<tools::Long>( nCos*aTranslatedPos.X() + nSin*aTranslatedPos.Y() ) ); - aRotatedPos.setY( static_cast<tools::Long>(- ( nSin*aTranslatedPos.X() - nCos*aTranslatedPos.Y() )) ); - aTranslatedPos = aRotatedPos; - - // Translation... - aTranslatedPos += rOrigin; - return aTranslatedPos; -} - AsianCompressionFlags GetCharTypeForCompression( sal_Unicode cChar ) { switch ( cChar ) { case 0x3008: case 0x300A: case 0x300C: case 0x300E: case 0x3010: case 0x3014: case 0x3016: case 0x3018: - case 0x301A: case 0x301D: + case 0x301A: case 0x301D: case 0xFF09: case 0xFF3D: + case 0xFF5D: { return AsianCompressionFlags::PunctuationRight; } case 0x3001: case 0x3002: case 0x3009: case 0x300B: case 0x300D: case 0x300F: case 0x3011: case 0x3015: case 0x3017: case 0x3019: case 0x301B: case 0x301E: - case 0x301F: + case 0x301F: case 0xFF08: case 0xFF0C: case 0xFF0E: + case 0xFF1A: case 0xFF1B: case 0xFF3B: case 0xFF5B: { return AsianCompressionFlags::PunctuationLeft; } @@ -156,7 +147,7 @@ static void lcl_DrawRedLines( OutputDevice& rOutDev, const Point& rPoint, size_t nIndex, size_t nMaxEnd, - const tools::Long* pDXArray, + std::span<const sal_Int32> pDXArray, WrongList const * pWrongs, Degree10 nOrientation, const Point& rOrigin, @@ -220,8 +211,8 @@ static void lcl_DrawRedLines( OutputDevice& rOutDev, if (nOrientation) { - aPoint1 = Rotate(aPoint1, nOrientation, rOrigin); - aPoint2 = Rotate(aPoint2, nOrientation, rOrigin); + rOrigin.RotateAround(aPoint1, nOrientation); + rOrigin.RotateAround(aPoint2, nOrientation); } { @@ -237,35 +228,83 @@ static void lcl_DrawRedLines( OutputDevice& rOutDev, } } -static Point lcl_ImplCalcRotatedPos( Point rPos, Point rOrigin, double nSin, double nCos ) +// For Kashidas from sw/source/core/text/porlay.cxx + +#define IS_JOINING_GROUP(c, g) ( u_getIntPropertyValue( (c), UCHAR_JOINING_GROUP ) == U_JG_##g ) +#define isAinChar(c) IS_JOINING_GROUP((c), AIN) +#define isAlefChar(c) IS_JOINING_GROUP((c), ALEF) +#define isDalChar(c) IS_JOINING_GROUP((c), DAL) +#define isFehChar(c) (IS_JOINING_GROUP((c), FEH) || IS_JOINING_GROUP((c), AFRICAN_FEH)) +#define isGafChar(c) IS_JOINING_GROUP((c), GAF) +#define isHehChar(c) IS_JOINING_GROUP((c), HEH) +#define isKafChar(c) IS_JOINING_GROUP((c), KAF) +#define isLamChar(c) IS_JOINING_GROUP((c), LAM) +#define isQafChar(c) (IS_JOINING_GROUP((c), QAF) || IS_JOINING_GROUP((c), AFRICAN_QAF)) +#define isRehChar(c) IS_JOINING_GROUP((c), REH) +#define isTahChar(c) IS_JOINING_GROUP((c), TAH) +#define isTehMarbutaChar(c) IS_JOINING_GROUP((c), TEH_MARBUTA) +#define isWawChar(c) IS_JOINING_GROUP((c), WAW) +#define isSeenOrSadChar(c) (IS_JOINING_GROUP((c), SAD) || IS_JOINING_GROUP((c), SEEN)) + +// Beh and characters that behave like Beh in medial form. +static bool isBehChar(sal_Unicode cCh) +{ + bool bRet = false; + switch (u_getIntPropertyValue(cCh, UCHAR_JOINING_GROUP)) + { + case U_JG_BEH: + case U_JG_NOON: + case U_JG_AFRICAN_NOON: + case U_JG_NYA: + case U_JG_YEH: + case U_JG_FARSI_YEH: + case U_JG_BURUSHASKI_YEH_BARREE: + bRet = true; + break; + default: + bRet = false; + break; + } + + return bRet; +} + +// Yeh and characters that behave like Yeh in final form. +static bool isYehChar(sal_Unicode cCh) +{ + bool bRet = false; + switch (u_getIntPropertyValue(cCh, UCHAR_JOINING_GROUP)) + { + case U_JG_YEH: + case U_JG_FARSI_YEH: + case U_JG_YEH_BARREE: + case U_JG_BURUSHASKI_YEH_BARREE: + case U_JG_YEH_WITH_TAIL: + bRet = true; + break; + default: + bRet = false; + break; + } + + return bRet; +} + +static bool isTransparentChar ( sal_Unicode cCh ) { - Point aRotatedPos; - // Translation... - Point aTranslatedPos( rPos); - aTranslatedPos -= rOrigin; - - aRotatedPos.setX( static_cast<tools::Long>( nCos*aTranslatedPos.X() + nSin*aTranslatedPos.Y() ) ); - aRotatedPos.setY( static_cast<tools::Long>(- ( nSin*aTranslatedPos.X() - nCos*aTranslatedPos.Y() )) ); - aTranslatedPos = aRotatedPos; - // Translation... - aTranslatedPos += rOrigin; - - return aTranslatedPos; + return u_getIntPropertyValue( cCh, UCHAR_JOINING_TYPE ) == U_JT_TRANSPARENT; } -static bool lcl_IsLigature( sal_Unicode cCh, sal_Unicode cNextCh ) // For Kashidas from sw/source/core/text/porlay.txt +static bool lcl_IsLigature( sal_Unicode cCh, sal_Unicode cNextCh ) { // Lam + Alef - return ( 0x644 == cCh && 0x627 == cNextCh ) || - // Beh + Reh - ( 0x628 == cCh && 0x631 == cNextCh ); + return ( isLamChar ( cCh ) && isAlefChar ( cNextCh )); } -static bool lcl_ConnectToPrev( sal_Unicode cCh, sal_Unicode cPrevCh ) // For Kashidas from sw/source/core/text/porlay.txt +static bool lcl_ConnectToPrev( sal_Unicode cCh, sal_Unicode cPrevCh ) { - // Alef, Dal, Thal, Reh, Zain, and Waw do not connect to the left - bool bRet = 0x627 != cPrevCh && 0x62F != cPrevCh && 0x630 != cPrevCh && - 0x631 != cPrevCh && 0x632 != cPrevCh && 0x648 != cPrevCh; + const int32_t nJoiningType = u_getIntPropertyValue( cPrevCh, UCHAR_JOINING_TYPE ); + bool bRet = nJoiningType != U_JT_RIGHT_JOINING && nJoiningType != U_JT_NON_JOINING; // check for ligatures cPrevChar + cChar if ( bRet ) @@ -278,23 +317,23 @@ static bool lcl_ConnectToPrev( sal_Unicode cCh, sal_Unicode cPrevCh ) // For Ka void ImpEditEngine::UpdateViews( EditView* pCurView ) { - if ( !GetUpdateMode() || IsFormatting() || aInvalidRect.IsEmpty() ) + if ( !IsUpdateLayout() || IsFormatting() || maInvalidRect.IsEmpty() ) return; DBG_ASSERT( IsFormatted(), "UpdateViews: Doc not formatted!" ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { pView->HideCursor(); - tools::Rectangle aClipRect( aInvalidRect ); + tools::Rectangle aClipRect(maInvalidRect); tools::Rectangle aVisArea( pView->GetVisArea() ); aClipRect.Intersection( aVisArea ); if ( !aClipRect.IsEmpty() ) { // convert to window coordinates... - aClipRect = pView->pImpEditView->GetWindowPos( aClipRect ); + aClipRect = pView->getImpl().GetWindowPos( aClipRect ); // moved to one executing method to allow finer control pView->InvalidateWindow(aClipRect); @@ -305,35 +344,35 @@ void ImpEditEngine::UpdateViews( EditView* pCurView ) if ( pCurView ) { - bool bGotoCursor = pCurView->pImpEditView->DoAutoScroll(); + bool bGotoCursor = pCurView->getImpl().DoAutoScroll(); pCurView->ShowCursor( bGotoCursor ); } - aInvalidRect = tools::Rectangle(); + maInvalidRect = tools::Rectangle(); CallStatusHdl(); } IMPL_LINK_NOARG(ImpEditEngine, OnlineSpellHdl, Timer *, void) { - if ( !Application::AnyInput( VclInputFlags::KEYBOARD ) && GetUpdateMode() && IsFormatted() ) + if ( !Application::AnyInput( VclInputFlags::KEYBOARD ) && IsUpdateLayout() && IsFormatted() ) DoOnlineSpelling(); else - aOnlineSpellTimer.Start(); + maOnlineSpellTimer.Start(); } IMPL_LINK_NOARG(ImpEditEngine, IdleFormatHdl, Timer *, void) { - aIdleFormatter.ResetRestarts(); + maIdleFormatter.ResetRestarts(); // #i97146# check if that view is still available // else probably the idle format timer fired while we're already // downing - EditView* pView = aIdleFormatter.GetView(); - for (EditView* aEditView : aEditViews) + EditView* pView = maIdleFormatter.GetView(); + for (EditView* aEditView : maEditViews) { if( aEditView == pView ) { - FormatAndUpdate( pView ); + FormatAndLayout( pView ); break; } } @@ -341,7 +380,7 @@ IMPL_LINK_NOARG(ImpEditEngine, IdleFormatHdl, Timer *, void) void ImpEditEngine::CheckIdleFormatter() { - aIdleFormatter.ForceTimeout(); + maIdleFormatter.ForceTimeout(); // If not idle, but still not formatted: if ( !IsFormatted() ) FormatDoc(); @@ -355,206 +394,238 @@ bool ImpEditEngine::IsPageOverflow( ) const void ImpEditEngine::FormatFullDoc() { - for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ ) - GetParaPortions()[nPortion].MarkSelectionInvalid( 0 ); + GetParaPortions().MarkAllSelectionsInvalid(0); FormatDoc(); } -void ImpEditEngine::FormatDoc() +tools::Long ImpEditEngine::FormatParagraphs(o3tl::sorted_vector<sal_Int32>& aRepaintParagraphList) { - if (!GetUpdateMode() || IsFormatting()) - return; - - bIsFormatting = true; - - // Then I can also start the spell-timer... - if ( GetStatus().DoOnlineSpelling() ) - StartOnlineSpellTimer(); - + sal_Int32 nParaCount = GetParaPortions().Count(); tools::Long nY = 0; bool bGrow = false; - // Here already, so that not always in CreateLines... - bool bMapChanged = ImpCheckRefMapMode(); - std::set<sal_Int32> aRepaintParas; - - for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) + for (sal_Int32 nParagraph = 0; nParagraph < nParaCount; nParagraph++) { - ParaPortion& rParaPortion = GetParaPortions()[nPara]; - if ( rParaPortion.MustRepaint() || ( rParaPortion.IsInvalid() && rParaPortion.IsVisible() ) ) + ParaPortion& rParaPortion = GetParaPortions().getRef(nParagraph); + if (rParaPortion.MustRepaint() || (rParaPortion.IsInvalid() && rParaPortion.IsVisible())) { // No formatting should be necessary for MustRepaint()! - if ( !rParaPortion.IsInvalid() || CreateLines( nPara, nY ) ) + if (CreateLines(nParagraph, nY)) { - if ( !bGrow && GetTextRanger() ) + if (!bGrow && GetTextRanger()) { // For a change in height all below must be reformatted... - for ( sal_Int32 n = nPara+1; n < GetParaPortions().Count(); n++ ) + for (sal_Int32 n = nParagraph + 1; n < nParaCount; n++) { - ParaPortion& rPP = GetParaPortions()[n]; - rPP.MarkSelectionInvalid( 0 ); - rPP.GetLines().Reset(); + ParaPortion& rParaPortionToInvalidate = GetParaPortions().getRef(n); + rParaPortionToInvalidate.MarkSelectionInvalid(0); + rParaPortionToInvalidate.GetLines().Reset(); } } bGrow = true; - if ( IsCallParaInsertedOrDeleted() ) + if (IsCallParaInsertedOrDeleted()) { - GetEditEnginePtr()->ParagraphHeightChanged( nPara ); + GetEditEnginePtr()->ParagraphHeightChanged(nParagraph); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - ImpEditView* pImpView = pView->pImpEditView.get(); - pImpView->ScrollStateChange(); + pView->getImpl().ScrollStateChange(); } } - rParaPortion.SetMustRepaint( false ); + rParaPortion.SetMustRepaint(false); } - aRepaintParas.insert(nPara); + aRepaintParagraphList.insert(nParagraph); } nY += rParaPortion.GetHeight(); } + return nY; +} + +namespace +{ +constexpr std::array<ScalingParameters, 13> constScaleLevels = +{ + ScalingParameters{ 1.000, 1.000, 1.0, 0.9 }, + ScalingParameters{ 0.925, 0.925, 1.0, 0.9 }, + ScalingParameters{ 0.925, 0.925, 1.0, 0.8 }, + ScalingParameters{ 0.850, 0.850, 1.0, 0.9 }, + ScalingParameters{ 0.850, 0.850, 1.0, 0.8 }, + ScalingParameters{ 0.775, 0.775, 1.0, 0.8 }, + ScalingParameters{ 0.700, 0.700, 1.0, 0.8 }, + ScalingParameters{ 0.625, 0.625, 1.0, 0.8 }, + ScalingParameters{ 0.550, 0.550, 1.0, 0.8 }, + ScalingParameters{ 0.475, 0.475, 1.0, 0.8 }, + ScalingParameters{ 0.400, 0.400, 1.0, 0.8 }, + ScalingParameters{ 0.325, 0.325, 1.0, 0.8 }, + ScalingParameters{ 0.250, 0.250, 1.0, 0.8 }, +}; + +} // end anonymous ns + +void ImpEditEngine::ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& aRepaintParagraphList) +{ + if (!maCustomScalingParameters.areValuesDefault()) + maScalingParameters = maCustomScalingParameters; + + tools::Long nHeight = FormatParagraphs(aRepaintParagraphList); + bool bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns); + + size_t nCurrentScaleLevel = 0; + while (bOverflow && nCurrentScaleLevel < constScaleLevels.size()) + { + // Clean-up and reset paragraphs + aRepaintParagraphList.clear(); + for (auto& pParaPortionToInvalidate : GetParaPortions()) + { + pParaPortionToInvalidate->GetLines().Reset(); + pParaPortionToInvalidate->MarkSelectionInvalid(0); + pParaPortionToInvalidate->SetMustRepaint(true); + } + + // Get new scaling parameters + maScalingParameters = constScaleLevels[nCurrentScaleLevel]; + + // Try again with different scaling factor + nHeight = FormatParagraphs(aRepaintParagraphList); + bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns); + + // Increase scale level + nCurrentScaleLevel++; + } +} + +void ImpEditEngine::FormatDoc() +{ + if (!IsUpdateLayout() || IsFormatting()) + return; + + mbIsFormatting = true; + + // Then I can also start the spell-timer... + if (GetStatus().DoOnlineSpelling()) + StartOnlineSpellTimer(); + + // Reserve, as it should match the current number of paragraphs + o3tl::sorted_vector<sal_Int32> aRepaintParagraphList; + aRepaintParagraphList.reserve(GetParaPortions().Count()); + + if (maStatus.DoStretch()) + ScaleContentToFitWindow(aRepaintParagraphList); + else + FormatParagraphs(aRepaintParagraphList); - aInvalidRect = tools::Rectangle(); // make empty + maInvalidRect = tools::Rectangle(); // make empty // One can also get into the formatting through UpdateMode ON=>OFF=>ON... // enable optimization first after Vobis delivery... { tools::Long nNewHeightNTP; tools::Long nNewHeight = CalcTextHeight(&nNewHeightNTP); - tools::Long nDiff = nNewHeight - nCurTextHeight; + tools::Long nDiff = nNewHeight - mnCurTextHeight; if ( nDiff ) - aStatus.GetStatusWord() |= !IsVertical() ? EditStatusFlags::TextHeightChanged : EditStatusFlags::TEXTWIDTHCHANGED; + { + maInvalidRect.Union(tools::Rectangle::Normalize( + { 0, nNewHeight }, { getWidthDirectionAware(maPaperSize), mnCurTextHeight })); + maStatus.GetStatusWord() |= !IsEffectivelyVertical() ? EditStatusFlags::TextHeightChanged : EditStatusFlags::TEXTWIDTHCHANGED; + } - nCurTextHeight = nNewHeight; - nCurTextHeightNTP = nNewHeightNTP; + mnCurTextHeight = nNewHeight; + mnCurTextHeightNTP = nNewHeightNTP; - if ( aStatus.AutoPageSize() ) + if ( maStatus.AutoPageSize() ) CheckAutoPageSize(); else if ( nDiff ) { - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - ImpEditView* pImpView = pView->pImpEditView.get(); - if ( pImpView->DoAutoHeight() ) + ImpEditView& rImpView = pView->getImpl(); + if (rImpView.DoAutoHeight()) { - Size aSz( pImpView->GetOutputArea().GetWidth(), nCurTextHeight ); - if ( aSz.Height() > aMaxAutoPaperSize.Height() ) - aSz.setHeight( aMaxAutoPaperSize.Height() ); - else if ( aSz.Height() < aMinAutoPaperSize.Height() ) - aSz.setHeight( aMinAutoPaperSize.Height() ); - pImpView->ResetOutputArea( tools::Rectangle( - pImpView->GetOutputArea().TopLeft(), aSz ) ); + Size aSz(rImpView.GetOutputArea().GetWidth(), mnCurTextHeight); + if ( aSz.Height() > maMaxAutoPaperSize.Height() ) + aSz.setHeight( maMaxAutoPaperSize.Height() ); + else if ( aSz.Height() < maMinAutoPaperSize.Height() ) + aSz.setHeight( maMinAutoPaperSize.Height() ); + rImpView.ResetOutputArea( tools::Rectangle(rImpView.GetOutputArea().TopLeft(), aSz)); } } } - if (nDiff) - aInvalidRect.Union(tools::Rectangle::Justify( - { 0, nNewHeight }, { getWidthDirectionAware(aPaperSize), nCurTextHeight })); - - if (!aRepaintParas.empty()) + if (!aRepaintParagraphList.empty()) { auto CombineRepaintParasAreas = [&](const LineAreaInfo& rInfo) { - if (aRepaintParas.count(rInfo.nPortion)) - aInvalidRect.Union(rInfo.aArea); + if (aRepaintParagraphList.count(rInfo.nPortion)) + maInvalidRect.Union(rInfo.aArea); return CallbackResult::Continue; }; IterateLineAreas(CombineRepaintParasAreas, IterFlag::inclILS); } } - bIsFormatting = false; - bFormatted = true; - - if ( bMapChanged ) - GetRefDevice()->Pop(); + mbIsFormatting = false; + mbFormatted = true; CallStatusHdl(); // If Modified... } -bool ImpEditEngine::ImpCheckRefMapMode() -{ - bool bChange = false; - - if ( aStatus.DoFormat100() ) - { - MapMode aMapMode( GetRefDevice()->GetMapMode() ); - if ( aMapMode.GetScaleX().GetNumerator() != aMapMode.GetScaleX().GetDenominator() ) - bChange = true; - else if ( aMapMode.GetScaleY().GetNumerator() != aMapMode.GetScaleY().GetDenominator() ) - bChange = true; - - if ( bChange ) - { - Fraction Scale1( 1, 1 ); - aMapMode.SetScaleX( Scale1 ); - aMapMode.SetScaleY( Scale1 ); - GetRefDevice()->Push(); - GetRefDevice()->SetMapMode( aMapMode ); - } - } - - return bChange; -} - void ImpEditEngine::CheckAutoPageSize() { Size aPrevPaperSize( GetPaperSize() ); if ( GetStatus().AutoPageWidth() ) - aPaperSize.setWidth( !IsVertical() ? CalcTextWidth( true ) : GetTextHeight() ); + maPaperSize.setWidth( !IsEffectivelyVertical() ? CalcTextWidth( true ) : GetTextHeight() ); if ( GetStatus().AutoPageHeight() ) - aPaperSize.setHeight( !IsVertical() ? GetTextHeight() : CalcTextWidth( true ) ); + maPaperSize.setHeight( !IsEffectivelyVertical() ? GetTextHeight() : CalcTextWidth( true ) ); - SetValidPaperSize( aPaperSize ); // consider Min, Max + SetValidPaperSize( maPaperSize ); // consider Min, Max - if ( aPaperSize == aPrevPaperSize ) + if ( maPaperSize == aPrevPaperSize ) return; - if ( ( !IsVertical() && ( aPaperSize.Width() != aPrevPaperSize.Width() ) ) - || ( IsVertical() && ( aPaperSize.Height() != aPrevPaperSize.Height() ) ) ) + if ( ( !IsEffectivelyVertical() && ( maPaperSize.Width() != aPrevPaperSize.Width() ) ) + || ( IsEffectivelyVertical() && ( maPaperSize.Height() != aPrevPaperSize.Height() ) ) ) { // If ahead is centered / right or tabs... - aStatus.GetStatusWord() |= !IsVertical() ? EditStatusFlags::TEXTWIDTHCHANGED : EditStatusFlags::TextHeightChanged; + maStatus.GetStatusWord() |= !IsEffectivelyVertical() ? EditStatusFlags::TEXTWIDTHCHANGED : EditStatusFlags::TextHeightChanged; for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) { // Only paragraphs which are not aligned to the left need to be // reformatted, the height can not be changed here anymore. - ParaPortion& rParaPortion = GetParaPortions()[nPara]; + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); SvxAdjust eJustification = GetJustification( nPara ); if ( eJustification != SvxAdjust::Left ) { - rParaPortion.MarkSelectionInvalid( 0 ); + rParaPortion.MarkSelectionInvalid(0); CreateLines( nPara, 0 ); // 0: For AutoPageSize no TextRange! } } } - Size aInvSize = aPaperSize; - if ( aPaperSize.Width() < aPrevPaperSize.Width() ) + Size aInvSize = maPaperSize; + if ( maPaperSize.Width() < aPrevPaperSize.Width() ) aInvSize.setWidth( aPrevPaperSize.Width() ); - if ( aPaperSize.Height() < aPrevPaperSize.Height() ) + if ( maPaperSize.Height() < aPrevPaperSize.Height() ) aInvSize.setHeight( aPrevPaperSize.Height() ); Size aSz( aInvSize ); - if ( IsVertical() ) + if ( IsEffectivelyVertical() ) { aSz.setWidth( aInvSize.Height() ); aSz.setHeight( aInvSize.Width() ); } - aInvalidRect = tools::Rectangle( Point(), aSz ); + maInvalidRect = tools::Rectangle( Point(), aSz ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - pView->pImpEditView->RecalcOutputArea(); + pView->getImpl().RecalcOutputArea(); } } void ImpEditEngine::CheckPageOverflow() { - SAL_INFO("editeng.chaining", "[CONTROL_STATUS] AutoPageSize is " << (( aStatus.GetControlWord() & EEControlBits::AUTOPAGESIZE ) ? "ON" : "OFF") ); + SAL_INFO("editeng.chaining", "[CONTROL_STATUS] AutoPageSize is " << (( maStatus.GetControlWord() & EEControlBits::AUTOPAGESIZE ) ? "ON" : "OFF") ); tools::Long nBoxHeight = GetMaxAutoPaperSize().Height(); SAL_INFO("editeng.chaining", "[OVERFLOW-CHECK] Current MaxAutoPaperHeight is " << nBoxHeight); @@ -572,12 +643,12 @@ void ImpEditEngine::CheckPageOverflow() { // which paragraph is the first to cause higher size of the box? ImplUpdateOverflowingParaNum( nBoxHeight); // XXX: currently only for horizontal text - //aStatus.SetPageOverflow(true); + //maStatus.SetPageOverflow(true); mbNeedsChainingHandling = true; } else { // No overflow if within box boundaries - //aStatus.SetPageOverflow(false); + //maStatus.SetPageOverflow(false); mbNeedsChainingHandling = false; } @@ -585,56 +656,93 @@ void ImpEditEngine::CheckPageOverflow() static sal_Int32 ImplCalculateFontIndependentLineSpacing( const sal_Int32 nFontHeight ) { - return ( nFontHeight * 12 ) / 10; // + 20% + constexpr const double f120Percent = 12.0 / 10.0; + return basegfx::fround(nFontHeight * f120Percent); // + 20% } tools::Long ImpEditEngine::GetColumnWidth(const Size& rPaperSize) const { assert(mnColumns >= 1); - tools::Long nWidth = IsVertical() ? rPaperSize.Height() : rPaperSize.Width(); + tools::Long nWidth = IsEffectivelyVertical() ? rPaperSize.Height() : rPaperSize.Width(); return (nWidth - mnColumnSpacing * (mnColumns - 1)) / mnColumns; } +bool ImpEditEngine::createLinesForEmptyParagraph(ParaPortion& rParaPortion) +{ + // fast special treatment... + if (rParaPortion.GetTextPortions().Count()) + rParaPortion.GetTextPortions().Reset(); + if (rParaPortion.GetLines().Count()) + rParaPortion.GetLines().Reset(); + + CreateAndInsertEmptyLine(rParaPortion); + return FinishCreateLines(rParaPortion); +} + +tools::Long ImpEditEngine::calculateMaxLineWidth(tools::Long nStartX, SvxLRSpaceItem const& rLRItem) +{ + const bool bAutoSize = IsEffectivelyVertical() ? maStatus.AutoPageHeight() : maStatus.AutoPageWidth(); + tools::Long nMaxLineWidth = GetColumnWidth(bAutoSize ? maMaxAutoPaperSize : maPaperSize); + + nMaxLineWidth -= scaleXSpacingValue(rLRItem.GetRight()); + nMaxLineWidth -= nStartX; + + // If PaperSize == long_max, one cannot take away any negative + // first line indent. (Overflow) + if (nMaxLineWidth < 0 && nStartX < 0) + nMaxLineWidth = GetColumnWidth(maPaperSize) - scaleXSpacingValue(rLRItem.GetRight()); + + // If still less than 0, it may be just the right edge. + if (nMaxLineWidth <= 0) + nMaxLineWidth = 1; + + return nMaxLineWidth; +} + bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { - ParaPortion& rParaPortion = GetParaPortions()[nPara]; + assert(GetParaPortions().exists(nPara) && "Portion paragraph index is not valid"); + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); // sal_Bool: Changes in the height of paragraph Yes / No - sal_True/sal_False - assert( rParaPortion.GetNode() && "Portion without Node in CreateLines" ); + assert(rParaPortion.GetNode() && "Portion without Node in CreateLines" ); DBG_ASSERT( rParaPortion.IsVisible(), "Invisible paragraphs not formatted!" ); DBG_ASSERT( rParaPortion.IsInvalid(), "CreateLines: Portion not invalid!" ); - bool bProcessingEmptyLine = ( rParaPortion.GetNode()->Len() == 0 ); - bool bEmptyNodeWithPolygon = ( rParaPortion.GetNode()->Len() == 0 ) && GetTextRanger(); + bool bProcessingEmptyLine = rParaPortion.GetNode()->Len() == 0 ; + bool bEmptyNodeWithPolygon = rParaPortion.GetNode()->Len() == 0 && GetTextRanger(); // Fast special treatment for empty paragraphs... - - if ( ( rParaPortion.GetNode()->Len() == 0 ) && !GetTextRanger() ) + bool bEmptyParagraph = rParaPortion.GetNode()->Len() == 0 && !GetTextRanger(); + if (bEmptyParagraph) + return createLinesForEmptyParagraph(rParaPortion); + + sal_Int64 nCurrentPosY = nStartPosY; + // If we're allowed to skip parts outside and this cannot possibly fit in the given height, + // bail out to avoid possibly formatting a lot of text that will not be used. For the first + // paragraph still format at least a bit. + if( mbSkipOutsideFormat && nPara != 0 + && !maStatus.AutoPageHeight() && maPaperSize.Height() < nCurrentPosY ) { - // fast special treatment... - if ( rParaPortion.GetTextPortions().Count() ) - rParaPortion.GetTextPortions().Reset(); - if ( rParaPortion.GetLines().Count() ) - rParaPortion.GetLines().Reset(); - CreateAndInsertEmptyLine( &rParaPortion ); - return FinishCreateLines( &rParaPortion ); + return false; } + //If the paragraph SvxFrameDirection is Stacked, use STACKED + const SvxFrameDirectionItem* pFrameDirItem = &GetParaAttrib(nPara, EE_PARA_WRITINGDIR); + bool bStacked = pFrameDirItem->GetValue() == SvxFrameDirection::Stacked; + if (bStacked) + maStatus.TurnOnFlags(EEControlBits::STACKED); + else + maStatus.TurnOffFlags(EEControlBits::STACKED); // Initialization... - - // Always format for 100%: - bool bMapChanged = ImpCheckRefMapMode(); - - if ( rParaPortion.GetLines().Count() == 0 ) + if (rParaPortion.GetLines().Count() == 0) { - EditLine* pL = new EditLine; - rParaPortion.GetLines().Append(pL); + rParaPortion.GetLines().Append(std::make_unique<EditLine>()); } - // Get Paragraph attributes... ContentNode* const pNode = rParaPortion.GetNode(); @@ -655,27 +763,28 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) const sal_Int32 nInvalidEnd = nInvalidStart + std::abs( nInvalidDiff ); bool bQuickFormat = false; - if ( !bEmptyNodeWithPolygon && !HasScriptType( nPara, i18n::ScriptType::COMPLEX ) ) + + // Determine if quick format should be used + if (!bEmptyNodeWithPolygon && !HasScriptType(nPara, i18n::ScriptType::COMPLEX)) { - if ( ( rParaPortion.IsSimpleInvalid() ) && ( nInvalidDiff > 0 ) && - ( pNode->GetString().indexOf( CH_FEATURE, nInvalidStart ) > nInvalidEnd ) ) + if (rParaPortion.IsSimpleInvalid() && + rParaPortion.GetInvalidDiff() > 0 && + pNode->GetString().indexOf(CH_FEATURE, nInvalidStart) > nInvalidEnd) { bQuickFormat = true; } - else if ( ( rParaPortion.IsSimpleInvalid() ) && ( nInvalidDiff < 0 ) ) + else if (rParaPortion.IsSimpleInvalid() && nInvalidDiff < 0) { // check if delete over the portion boundaries was done... sal_Int32 nStart = nInvalidStart; // DOUBLE !!!!!!!!!!!!!!! sal_Int32 nEnd = nStart - nInvalidDiff; // negative bQuickFormat = true; sal_Int32 nPos = 0; - sal_Int32 nPortions = rParaPortion.GetTextPortions().Count(); - for ( sal_Int32 nTP = 0; nTP < nPortions; nTP++ ) + for (auto const& pTextPortion : rParaPortion.GetTextPortions()) { // There must be no start / end in the deleted area. - const TextPortion& rTP = rParaPortion.GetTextPortions()[ nTP ]; - nPos = nPos + rTP.GetLen(); - if ( ( nPos > nStart ) && ( nPos < nEnd ) ) + nPos = nPos + pTextPortion->GetLen(); + if (nPos > nStart && nPos < nEnd) { bQuickFormat = false; break; @@ -685,13 +794,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } // Saving both layout mode and language (since I'm potentially changing both) - GetRefDevice()->Push( PushFlags::TEXTLAYOUTMODE|PushFlags::TEXTLANGUAGE ); + GetRefDevice()->Push( vcl::PushFlags::TEXTLAYOUTMODE|vcl::PushFlags::TEXTLANGUAGE ); ImplInitLayoutMode(*GetRefDevice(), nPara, -1); sal_Int32 nRealInvalidStart = nInvalidStart; - if ( bEmptyNodeWithPolygon ) + if (bEmptyNodeWithPolygon) { TextPortion* pDummyPortion = new TextPortion( 0 ); rParaPortion.GetTextPortions().Reset(); @@ -700,14 +809,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) else if ( bQuickFormat ) { // faster Method: - RecalcTextPortion( &rParaPortion, nInvalidStart, nInvalidDiff ); + RecalcTextPortion(rParaPortion, nInvalidStart, nInvalidDiff); } else // nRealInvalidStart can be before InvalidStart, since Portions were deleted... { - CreateTextPortions( &rParaPortion, nRealInvalidStart ); + CreateTextPortions(rParaPortion, nRealInvalidStart); } - // Search for line with InvalidPos, start one line before // Flag the line => do not remove it ! @@ -725,35 +833,38 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } // Begin one line before... // If it is typed at the end, the line in front cannot change. - if ( nLine && ( !rParaPortion.IsSimpleInvalid() || ( nInvalidEnd < pNode->Len() ) || ( nInvalidDiff <= 0 ) ) ) + if (nLine && (!rParaPortion.IsSimpleInvalid() || + (nInvalidEnd < pNode->Len()) || + (nInvalidDiff <= 0))) + { nLine--; + } - EditLine* pLine = &rParaPortion.GetLines()[nLine]; + tools::Rectangle aBulletArea{Point(), Point()}; - static tools::Rectangle aZeroArea { Point(), Point() }; - tools::Rectangle aBulletArea( aZeroArea ); - if ( !nLine ) + if (!nLine) { - aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( &rParaPortion ) ); + aBulletArea = GetEditEnginePtr()->GetBulletArea(GetParaPortions().GetPos(&rParaPortion)); if ( !aBulletArea.IsWidthEmpty() && aBulletArea.Right() > 0 ) - rParaPortion.SetBulletX( static_cast<sal_Int32>(GetXValue( aBulletArea.Right() )) ); + rParaPortion.SetBulletX(sal_Int32(scaleXSpacingValue(aBulletArea.Right()))); else rParaPortion.SetBulletX( 0 ); // if Bullet is set incorrectly } - // Reformat all lines from here... + int nStartNextLineAfterMultiLineField = 0; + sal_Int32 nDelFromLine = -1; bool bLineBreak = false; + EditLine* pLine = &rParaPortion.GetLines()[nLine]; sal_Int32 nIndex = pLine->GetStart(); EditLine aSaveLine( *pLine ); - SvxFont aTmpFont( pNode->GetCharAttribs().GetDefFont() ); - ImplInitLayoutMode(*GetRefDevice(), nPara, nIndex); + SvxFont aTmpFont( pNode->GetCharAttribs().GetDefFont() ); - std::unique_ptr<tools::Long[]> pBuf(new tools::Long[ pNode->Len() ]); + KernArray aCharPositionArray; bool bSameLineAgain = false; // For TextRanger, if the height changes. TabInfo aCurrentTab; @@ -763,39 +874,33 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) while ( ( nIndex < pNode->Len() ) || bForceOneRun ) { + assert(pLine); + bForceOneRun = false; + bool bFieldStartNextLine = false; bool bEOL = false; bool bEOC = false; sal_Int32 nPortionStart = 0; sal_Int32 nPortionEnd = 0; - tools::Long nStartX = GetXValue( rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth ); + tools::Long nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth); + // Multiline hyperlink may need to know if the next line is bigger. + tools::Long nStartXNextLine = nStartX; if ( nIndex == 0 ) { - tools::Long nFI = GetXValue( rLRItem.GetTextFirstLineOffset() ); + tools::Long nFI = scaleXSpacingValue(rLRItem.GetTextFirstLineOffset()); nStartX += nFI; - if ( !nLine && ( rParaPortion.GetBulletX() > nStartX ) ) + if (!nLine && rParaPortion.GetBulletX() > nStartX) { - nStartX = rParaPortion.GetBulletX(); + nStartX = rParaPortion.GetBulletX(); } } - const bool bAutoSize = IsVertical() ? aStatus.AutoPageHeight() : aStatus.AutoPageWidth(); - tools::Long nMaxLineWidth = GetColumnWidth(bAutoSize ? aMaxAutoPaperSize : aPaperSize); - - nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); - nMaxLineWidth -= nStartX; - - // If PaperSize == long_max, one cannot take away any negative - // first line indent. (Overflow) - if ( ( nMaxLineWidth < 0 ) && ( nStartX < 0 ) ) - nMaxLineWidth = GetColumnWidth(aPaperSize) - GetXValue(rLRItem.GetRight()); - - // If still less than 0, it may be just the right edge. - if ( nMaxLineWidth <= 0 ) - nMaxLineWidth = 1; + nStartX += nStartNextLineAfterMultiLineField; + nStartNextLineAfterMultiLineField = 0; + tools::Long nMaxLineWidth = calculateMaxLineWidth(nStartX, rLRItem); // Problem: // Since formatting starts a line _before_ the invalid position, @@ -816,9 +921,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nTextLineHeight = 0; if ( GetTextRanger() ) { - GetTextRanger()->SetVertical( IsVertical() ); + GetTextRanger()->SetVertical( IsEffectivelyVertical() ); - tools::Long nTextY = nStartPosY + GetEditCursor( &rParaPortion, pLine, pLine->GetStart(), GetCursorFlags::NONE ).Top(); + tools::Long nTextY = nStartPosY + GetEditCursor(rParaPortion, *pLine, pLine->GetStart(), CursorFlags()).Top(); if ( !bSameLineAgain ) { SeekCursor( pNode, nTmpPos+1, aTmpFont ); @@ -844,7 +949,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { tools::Long nYOff = nTextY + nTextExtraYOffset; tools::Long nYDiff = nTextLineHeight; - if ( IsVertical() ) + if ( IsEffectivelyVertical() ) { tools::Long nMaxPolygonX = GetTextRanger()->GetBoundRect().Right(); nYOff = nMaxPolygonX-nYOff; @@ -871,7 +976,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } nXWidth = nMaxRangeWidth; if ( nXWidth ) - nMaxLineWidth = nXWidth - nStartX - GetXValue( rLRItem.GetRight() ); + nMaxLineWidth = nXWidth - nStartX - scaleXSpacingValue(rLRItem.GetRight()); else { // Try further down in the polygon. @@ -929,10 +1034,10 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nTmpWidth -= rPrev.GetSize().Width(); nTmpPos = nTmpPos - rPrev.GetLen(); rPrev.SetLen(rPrev.GetLen() + nTmpLen); - rPrev.GetSize().setWidth( -1 ); + rPrev.setWidth(-1); } - assert( nTmpPortion < rParaPortion.GetTextPortions().Count() && "No more Portions left!" ); + assert(nTmpPortion < rParaPortion.GetTextPortions().Count() && "No more Portions left!"); pPortion = &rParaPortion.GetTextPortions()[nTmpPortion]; } @@ -961,14 +1066,15 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nOldTmpWidth = nTmpWidth; // Search for Tab-Pos... - tools::Long nCurPos = nTmpWidth+nStartX; + tools::Long nCurPos = nTmpWidth + nStartX; // consider scaling - if ( aStatus.DoStretch() && ( nStretchX != 100 ) ) - nCurPos = nCurPos*100/std::max(static_cast<sal_Int32>(nStretchX), static_cast<sal_Int32>(1)); + double fFontScalingX = maScalingParameters.fFontX; + if (maStatus.DoStretch() && (fFontScalingX != 1.0)) + nCurPos = basegfx::fround<tools::Long>(double(nCurPos) / std::max(fFontScalingX, 0.01)); - short nAllSpaceBeforeText = static_cast< short >(rLRItem.GetTextLeft()/* + rLRItem.GetTextLeft()*/ + nSpaceBeforeAndMinLabelWidth); - aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText /*rLRItem.GetTextLeft()*/, aEditDoc.GetDefTab() ); - aCurrentTab.nTabPos = GetXValue( static_cast<tools::Long>( aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText /*rLRItem.GetTextLeft()*/ ) ); + short nAllSpaceBeforeText = short(rLRItem.GetTextLeft()); + aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText , maEditDoc.GetDefTab() ); + aCurrentTab.nTabPos = tools::Long(aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText); aCurrentTab.bValid = false; // Switch direction in R2L para... @@ -990,25 +1096,28 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) aCurrentTab.nTabPortion = nTmpPortion; } + if (nMaxLineWidth < aCurrentTab.nTabPos && nTmpWidth != nMaxLineWidth - 1) + aCurrentTab.nTabPos = nMaxLineWidth - 1; + pPortion->SetKind(PortionKind::TAB); pPortion->SetExtraValue( aCurrentTab.aTabStop.GetFill() ); - pPortion->GetSize().setWidth( aCurrentTab.nTabPos - (nTmpWidth+nStartX) ); + pPortion->setWidth( aCurrentTab.nTabPos - (nTmpWidth+nStartX) ); // Height needed... SeekCursor( pNode, nTmpPos+1, aTmpFont ); - pPortion->GetSize().setHeight( aTmpFont.QuickGetTextSize( GetRefDevice(), OUString(), 0, 0 ).Height() ); + pPortion->setHeight( GetRefDevice()->GetTextHeight() ); DBG_ASSERT( pPortion->GetSize().Width() >= 0, "Tab incorrectly calculated!" ); nTmpWidth = aCurrentTab.nTabPos-nStartX; // If this is the first token on the line, - // and nTmpWidth > aPaperSize.Width, => infinite loop! + // and nTmpWidth > maPaperSize.Width, => infinite loop! if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->GetStartPortion() ) ) { // What now? // make the tab fitting - pPortion->GetSize().setWidth( nXWidth-nOldTmpWidth ); + pPortion->setWidth( nXWidth-nOldTmpWidth ); nTmpWidth = nXWidth-1; bEOL = true; bBrokenLine = true; @@ -1022,7 +1131,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) case EE_FEATURE_LINEBR: { assert( pPortion ); - pPortion->GetSize().setWidth( 0 ); + pPortion->setWidth(0); bEOL = true; bLineBreak = true; pPortion->SetKind( PortionKind::LINEBREAK ); @@ -1040,12 +1149,12 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) OUString aFieldValue = static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue(); // get size, but also DXArray to allow length information in line breaking below - const sal_Int32 nLength(aFieldValue.getLength()); - std::unique_ptr<tools::Long[]> pTmpDXArray(new tools::Long[nLength]); - pPortion->GetSize() = aTmpFont.QuickGetTextSize(GetRefDevice(), aFieldValue, 0, aFieldValue.getLength(), pTmpDXArray.get()); + KernArray aTmpDXArray; + pPortion->SetSize(aTmpFont.QuickGetTextSize(GetRefDevice(), + aFieldValue, 0, aFieldValue.getLength(), &aTmpDXArray)); // So no scrolling for oversized fields - if ( pPortion->GetSize().Width() > nXWidth ) + if (pPortion->GetSize().Width() > nXWidth - nTmpWidth) { // create ExtraPortionInfo on-demand, flush lineBreaksList ExtraPortionInfo *pExtraInfo = pPortion->GetExtraInfos(); @@ -1077,6 +1186,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nDone)); sal_Int32 nLastCellBreak(0); sal_Int32 nLineStartX(0); + nLineStartX = -nTmpWidth; // always add 1st line break (safe, we already know we are larger than nXWidth) pExtraInfo->lineBreaksList.push_back(0); @@ -1086,7 +1196,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) if(a == nNextCellBreak) { // check width - if(pTmpDXArray[a] - nLineStartX > nXWidth) + if(aTmpDXArray[a] - nLineStartX > nXWidth) { // new CellBreak does not fit in current line, need to // create a break at LastCellBreak - but do not add 1st @@ -1094,10 +1204,26 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) if(0 != a) { pExtraInfo->lineBreaksList.push_back(a); + // the following lines may be different sized + if (nStartX > nStartXNextLine) + { + nXWidth += nStartX - nStartXNextLine; + pLine->SetNextLinePosXDiff(nStartX + - nStartXNextLine); + nStartXNextLine = nStartX; + } + } + else + { + //even the 1. char does not fit.. + //this means the field should start on next line + //except if the actual line is a full line already + if (nLineStartX < 0 || nStartX > nStartXNextLine) + bFieldStartNextLine = true; } // moveLineStart forward in X - nLineStartX = pTmpDXArray[nLastCellBreak]; + nLineStartX = aTmpDXArray[nLastCellBreak]; } // update CellBreak iteration values @@ -1111,6 +1237,17 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nDone); } } + //next Line should start here... after this field end + if (!bFieldStartNextLine) + nStartNextLineAfterMultiLineField + = aTmpDXArray[nTextLength - 1] - nLineStartX; + else if (pExtraInfo) + { + // if the 1. character does not fit, + // but there is pExtraInfo, then delete it + pPortion->SetExtraInfos(nullptr); + pExtraInfo = nullptr; + } } nTmpWidth += pPortion->GetSize().Width(); EditLine::CharPosArrayType& rArray = pLine->GetCharPosArray(); @@ -1118,7 +1255,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) rArray.insert(rArray.begin()+nPos, pPortion->GetSize().Width()); pPortion->SetKind(PortionKind::FIELD); // If this is the first token on the line, - // and nTmpWidth > aPaperSize.Width, => infinite loop! + // and nTmpWidth > maPaperSize.Width, => infinite loop! if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->GetStartPortion() ) ) { nTmpWidth = nXWidth-1; @@ -1146,33 +1283,36 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) if (bContinueLastPortion) { - Size aSize( aTmpFont.QuickGetTextSize( GetRefDevice(), - rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, pBuf.get() )); - pPortion->GetSize().AdjustWidth(aSize.Width() ); + Size aSize = aTmpFont.QuickGetTextSize( GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aCharPositionArray, bStacked); + pPortion->adjustSize(aSize.Width(), 0); if (pPortion->GetSize().Height() < aSize.Height()) - pPortion->GetSize().setHeight( aSize.Height() ); + pPortion->setHeight(aSize.Height()); } else { - pPortion->GetSize() = aTmpFont.QuickGetTextSize( GetRefDevice(), - rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, pBuf.get() ); + Size aSize = aTmpFont.QuickGetTextSize(GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aCharPositionArray, bStacked); + pPortion->SetSize(aSize); } // #i9050# Do Kerning also behind portions... if ( ( aTmpFont.GetFixKerning() > 0 ) && ( ( nTmpPos + nPortionLen ) < pNode->Len() ) ) - pPortion->GetSize().AdjustWidth(aTmpFont.GetFixKerning() ); + pPortion->adjustSize(aTmpFont.GetFixKerning(), 0); if ( IsFixedCellHeight() ) - pPortion->GetSize().setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); + { + pPortion->setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); + } // The array is generally flattened at the beginning // => Always simply quick inserts. size_t nPos = nTmpPos - pLine->GetStart(); EditLine::CharPosArrayType& rArray = pLine->GetCharPosArray(); - rArray.insert( rArray.begin() + nPos, pBuf.get(), pBuf.get() + nPortionLen); + assert(aCharPositionArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aCharPositionArray.get_subunit_array(); + rArray.insert( rArray.begin() + nPos, rKernArray.data(), rKernArray.data() + nPortionLen); // And now check for Compression: if ( !bContinueLastPortion && nPortionLen && GetAsianCompressionMode() != CharCompressType::NONE ) { - tools::Long* pDXArray = rArray.data() + nTmpPos - pLine->GetStart(); + sal_Int32* pDXArray = rArray.data() + nTmpPos - pLine->GetStart(); bCompressedChars |= ImplCalcAsianCompression( pNode, pPortion, nTmpPos, pDXArray, 10000, false); } @@ -1191,9 +1331,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // No spacing within L2R/R2L nesting if ( bAllow ) { - tools::Long nExtraSpace = pPortion->GetSize().Height()/5; - nExtraSpace = GetXValue( nExtraSpace ); - pPortion->GetSize().AdjustWidth(nExtraSpace ); + tools::Long nExtraSpace = pPortion->GetSize().Height() / 5; + nExtraSpace = scaleXSpacingValue(nExtraSpace); + pPortion->adjustSize(nExtraSpace, 0); nTmpWidth += nExtraSpace; } } @@ -1204,12 +1344,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nWidthAfterTab = 0; for ( sal_Int32 n = aCurrentTab.nTabPortion+1; n <= nTmpPortion; n++ ) { - const TextPortion& rTP = rParaPortion.GetTextPortions()[n]; - nWidthAfterTab += rTP.GetSize().Width(); + const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[n]; + nWidthAfterTab += rTextPortion.GetSize().Width(); } tools::Long nW = nWidthAfterTab; // Length before tab position if ( aCurrentTab.aTabStop.GetAdjustment() == SvxTabAdjust::Right ) { + // Do nothing } else if ( aCurrentTab.aTabStop.GetAdjustment() == SvxTabAdjust::Center ) { @@ -1217,13 +1358,16 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } else if ( aCurrentTab.aTabStop.GetAdjustment() == SvxTabAdjust::Decimal ) { - OUString aText = GetSelected( EditSelection( EditPaM( rParaPortion.GetNode(), nTmpPos ), - EditPaM( rParaPortion.GetNode(), nTmpPos + nPortionLen ) ) ); + EditPaM aSelectionStart(rParaPortion.GetNode(), nTmpPos); + EditPaM aSelectionEnd(rParaPortion.GetNode(), nTmpPos + nPortionLen); + EditSelection aSelection(aSelectionStart, aSelectionEnd); + OUString aText = GetSelected(aSelection); + sal_Int32 nDecPos = aText.indexOf( aCurrentTab.aTabStop.GetDecimal() ); if ( nDecPos != -1 ) { nW -= rParaPortion.GetTextPortions()[nTmpPortion].GetSize().Width(); - nW += aTmpFont.QuickGetTextSize( GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nDecPos ).Width(); + nW += aTmpFont.QuickGetTextSize(GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nDecPos, nullptr).Width(); aCurrentTab.bValid = false; } } @@ -1238,14 +1382,14 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) aCurrentTab.bValid = false; } TextPortion& rTabPortion = rParaPortion.GetTextPortions()[aCurrentTab.nTabPortion]; - rTabPortion.GetSize().setWidth( aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nW - nStartX ); + rTabPortion.setWidth( aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nW - nStartX ); nTmpWidth = aCurrentTab.nStartPosX + rTabPortion.GetSize().Width() + nWidthAfterTab; } nTmpPos = nTmpPos + nPortionLen; nPortionEnd = nTmpPos; nTmpPortion++; - if ( aStatus.OneCharPerLine() ) + if (maStatus.OneCharPerLine()) bEOL = true; } @@ -1257,7 +1401,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // this was possibly a portion too far: bool bFixedEnd = false; - if ( aStatus.OneCharPerLine() ) + if (maStatus.OneCharPerLine()) { // State before Portion (apart from nTmpWidth): nTmpPos -= pPortion ? nPortionLen : 0; @@ -1276,7 +1420,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { DBG_ASSERT( pPortion->GetKind() == PortionKind::TEXT, "Len>1, but no TextPortion?" ); nTmpWidth -= pPortion->GetSize().Width(); - sal_Int32 nP = SplitTextPortion( &rParaPortion, nTmpPos, pLine ); + sal_Int32 nP = SplitTextPortion(rParaPortion, nTmpPos, pLine); nTmpWidth += rParaPortion.GetTextPortions()[nP].GetSize().Width(); } } @@ -1317,41 +1461,57 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) bEOL = true; bEOC = true; pLine->SetEnd( nPortionEnd ); - assert( rParaPortion.GetTextPortions().Count() && "No TextPortions?" ); - pLine->SetEndPortion( rParaPortion.GetTextPortions().Count() - 1 ); + assert(rParaPortion.GetTextPortions().Count() && "No TextPortions?"); + pLine->SetEndPortion(rParaPortion.GetTextPortions().Count() - 1); } - if ( aStatus.OneCharPerLine() ) + if (maStatus.OneCharPerLine()) { pLine->SetEnd( nPortionEnd ); pLine->SetEndPortion( nTmpPortion-1 ); } else if ( bFixedEnd ) { - pLine->SetEnd( nPortionStart ); - pLine->SetEndPortion( nTmpPortion-1 ); + if (bFieldStartNextLine) + { + pLine->SetEnd(nPortionStart); + pLine->SetEndPortion(nTmpPortion - 1); + } + else + { + pLine->SetEnd(nPortionStart + 1); + pLine->SetEndPortion(nTmpPortion); + } } else if ( bLineBreak || bBrokenLine ) { - pLine->SetEnd( nPortionStart+1 ); - pLine->SetEndPortion( nTmpPortion-1 ); + if (bFieldStartNextLine) + { + pLine->SetEnd(nPortionStart); + pLine->SetEndPortion(nTmpPortion - 2); + } + else + { + pLine->SetEnd(nPortionStart + 1); + pLine->SetEndPortion(nTmpPortion - 1); + } bEOC = false; // was set above, maybe change the sequence of the if's? } else if ( !bEOL && !bContinueLastPortion ) { DBG_ASSERT( pPortion && ((nPortionEnd-nPortionStart) == pPortion->GetLen()), "However, another portion?!" ); - tools::Long nRemainingWidth = nMaxLineWidth - nTmpWidth; + tools::Long nRemainingWidth = !maStatus.IsSingleLine() ? + nMaxLineWidth - nTmpWidth : pLine->GetCharPosArray()[pLine->GetCharPosArray().size() - 1] + 1; bool bCanHyphenate = ( aTmpFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ); if ( bCompressedChars && pPortion && ( pPortion->GetLen() > 1 ) && pPortion->GetExtraInfos() && pPortion->GetExtraInfos()->bCompressed ) { // I need the manipulated DXArray for determining the break position... - tools::Long* pDXArray = pLine->GetCharPosArray().data() + (nPortionStart - pLine->GetStart()); + sal_Int32* pDXArray = pLine->GetCharPosArray().data() + (nPortionStart - pLine->GetStart()); ImplCalcAsianCompression( pNode, pPortion, nPortionStart, pDXArray, 10000, true); } if( pPortion ) - ImpBreakLine( &rParaPortion, pLine, pPortion, nPortionStart, - nRemainingWidth, bCanHyphenate && bHyphenatePara ); + ImpBreakLine(rParaPortion, *pLine, pPortion, nPortionStart, nRemainingWidth, bCanHyphenate && bHyphenatePara); } @@ -1359,18 +1519,18 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // CalcTextSize should be replaced by a continuous registering! - Size aTextSize = pLine->CalcTextSize( rParaPortion ); + Size aTextSize = pLine->CalcTextSize(rParaPortion); if ( aTextSize.Height() == 0 ) { SeekCursor( pNode, pLine->GetStart()+1, aTmpFont ); - aTmpFont.SetPhysFont(*pRefDev); - ImplInitDigitMode(*pRefDev, aTmpFont.GetLanguage()); + aTmpFont.SetPhysFont(*mpRefDev); + ImplInitDigitMode(*mpRefDev, aTmpFont.GetLanguage()); if ( IsFixedCellHeight() ) aTextSize.setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); else - aTextSize.setHeight( aTmpFont.GetPhysTxtSize( pRefDev ).Height() ); + aTextSize.setHeight( aTmpFont.GetPhysTxtSize(mpRefDev).Height() ); pLine->SetHeight( static_cast<sal_uInt16>(aTextSize.Height()) ); } @@ -1404,12 +1564,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) bSameLineAgain = true; } - - if ( !bSameLineAgain && !aStatus.IsOutliner() ) + if (!bSameLineAgain && !maStatus.IsOutliner()) { if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Min ) { - sal_uInt16 nMinHeight = GetYValue( rLSItem.GetLineHeight() ); + double fMinHeight = scaleYSpacingValue(rLSItem.GetLineHeight()); + sal_uInt16 nMinHeight = basegfx::fround(fMinHeight); + sal_uInt16 nTxtHeight = pLine->GetHeight(); if ( nTxtHeight < nMinHeight ) { @@ -1421,7 +1582,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } else if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Fix ) { - sal_uInt16 nFixHeight = GetYValue( rLSItem.GetLineHeight() ); + double fFixHeight = scaleYSpacingValue(rLSItem.GetLineHeight()); + sal_uInt16 nFixHeight = basegfx::fround(fFixHeight); + sal_uInt16 nTxtHeight = pLine->GetHeight(); pLine->SetMaxAscent( static_cast<sal_uInt16>(pLine->GetMaxAscent() + ( nFixHeight - nTxtHeight ) ) ); pLine->SetHeight( nFixHeight, nTxtHeight ); @@ -1430,40 +1593,61 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { // There are documents with PropLineSpace 0, why? // (cmc: re above question :-) such documents can be seen by importing a .ppt - if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() < 100 ) ) + sal_uInt16 nPropLineSpace = rLSItem.GetPropLineSpace(); + double fProportionalScale = double(nPropLineSpace) / 100.0; + constexpr const double f80Percent = 8.0 / 10.0; + double fSpacingFactor = maScalingParameters.fSpacingY; + if (nPropLineSpace && nPropLineSpace < 100) { // Adapted code from sw/source/core/text/itrform2.cxx - sal_uInt16 nPropLineSpace = rLSItem.GetPropLineSpace(); sal_uInt16 nAscent = pLine->GetMaxAscent(); - sal_uInt16 nNewAscent = pLine->GetTxtHeight() * nPropLineSpace / 100 * 4 / 5; // 80% - if ( !nAscent || nAscent > nNewAscent ) - { - pLine->SetMaxAscent( nNewAscent ); - } - sal_uInt16 nHeight = pLine->GetHeight() * nPropLineSpace / 100; - pLine->SetHeight( nHeight, pLine->GetTxtHeight() ); + sal_uInt16 nNewAscent = basegfx::fround(pLine->GetTxtHeight() * fSpacingFactor * fProportionalScale * f80Percent); + if (!nAscent || nAscent > nNewAscent) + pLine->SetMaxAscent(nNewAscent); + sal_uInt16 nHeight = basegfx::fround(pLine->GetHeight() * fProportionalScale * fSpacingFactor); + + pLine->SetHeight(nHeight, pLine->GetTxtHeight()); } - else if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() != 100 ) ) + else if (nPropLineSpace && nPropLineSpace != 100) { sal_uInt16 nTxtHeight = pLine->GetHeight(); - sal_Int32 nPropTextHeight = nTxtHeight * rLSItem.GetPropLineSpace() / 100; + sal_Int32 nPropTextHeight = nTxtHeight * fProportionalScale * fSpacingFactor; // The Ascent has to be adjusted for the difference: tools::Long nDiff = pLine->GetHeight() - nPropTextHeight; pLine->SetMaxAscent( static_cast<sal_uInt16>( pLine->GetMaxAscent() - nDiff ) ); pLine->SetHeight( static_cast<sal_uInt16>( nPropTextHeight ), nTxtHeight ); } } + else if (rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Off) + { + if (maScalingParameters.fSpacingY < 1.0) + { + double fSpacingFactor = maScalingParameters.fSpacingY; + sal_uInt16 nPropLineSpace = basegfx::fround(100.0 * fSpacingFactor); + if (nPropLineSpace && nPropLineSpace < 100) + { + // Adapted code from sw/source/core/text/itrform2.cxx + sal_uInt16 nAscent = pLine->GetMaxAscent(); + sal_uInt16 nNewAscent = basegfx::fround(pLine->GetTxtHeight() * fSpacingFactor); + if (!nAscent || nAscent > nNewAscent) + pLine->SetMaxAscent(nNewAscent); + sal_uInt16 nHeight = basegfx::fround(pLine->GetHeight() * fSpacingFactor); + + pLine->SetHeight(nHeight, pLine->GetTxtHeight()); + } + + } + } } - if ( ( !IsVertical() && aStatus.AutoPageWidth() ) || - ( IsVertical() && aStatus.AutoPageHeight() ) ) + if ( ( !IsEffectivelyVertical() && maStatus.AutoPageWidth() ) || + ( IsEffectivelyVertical() && maStatus.AutoPageHeight() ) ) { // If the row fits within the current paper width, then this width // has to be used for the Alignment. If it does not fit or if it // will change the paper width, it will be formatted again for // Justification! = LEFT anyway. - tools::Long nMaxLineWidthFix = GetColumnWidth(aPaperSize) - - GetXValue( rLRItem.GetRight() ) - nStartX; + tools::Long nMaxLineWidthFix = GetColumnWidth(maPaperSize) - scaleXSpacingValue(rLRItem.GetRight()) - nStartX; if ( aTextSize.Width() < nMaxLineWidthFix ) nMaxLineWidth = nMaxLineWidthFix; } @@ -1473,8 +1657,8 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nRemainingWidth = nMaxLineWidth - aTextSize.Width(); if ( nRemainingWidth > 0 ) { - ImplExpandCompressedPortions( pLine, &rParaPortion, nRemainingWidth ); - aTextSize = pLine->CalcTextSize( rParaPortion ); + ImplExpandCompressedPortions(*pLine, rParaPortion, nRemainingWidth); + aTextSize = pLine->CalcTextSize(rParaPortion); } } @@ -1486,8 +1670,11 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) TextPortion& rTP = rParaPortion.GetTextPortions()[pLine->GetEndPortion()]; sal_Int32 nPosInArray = pLine->GetEnd()-1-pLine->GetStart(); tools::Long nNewValue = ( nPosInArray ? pLine->GetCharPosArray()[ nPosInArray-1 ] : 0 ) + n; - pLine->GetCharPosArray()[ nPosInArray ] = nNewValue; - rTP.GetSize().AdjustWidth(n ); + if (o3tl::make_unsigned(nPosInArray) < pLine->GetCharPosArray().size()) + { + pLine->GetCharPosArray()[ nPosInArray ] = nNewValue; + } + rTP.adjustSize(n, 0); } pLine->SetTextWidth( aTextSize.Width() ); @@ -1515,7 +1702,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nRemainingSpace = nMaxLineWidth - aTextSize.Width(); pLine->SetStartPosX( nStartX ); if ( nRemainingSpace > 0 && (!bEOC || bDistLastLine) ) - ImpAdjustBlocks( &rParaPortion, pLine, nRemainingSpace ); + ImpAdjustBlocks(rParaPortion, *pLine, nRemainingSpace); } break; default: @@ -1549,7 +1736,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } // for <0 think over ! - if ( rParaPortion.IsSimpleInvalid() ) + if (rParaPortion.IsSimpleInvalid()) { // Change through simple Text changes... // Do not cancel formatting since Portions possibly have to be split @@ -1602,6 +1789,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // as nEnd points to the last character! sal_Int32 nEndPortion = pLine->GetEndPortion(); + nCurrentPosY += pLine->GetHeight(); // Next line or maybe a new line... pLine = nullptr; @@ -1612,12 +1800,22 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nDelFromLine = nLine; break; } + // Stop processing if allowed and this is outside of the paper size height. + // Format at least two lines though, in case something detects whether + // the text has been wrapped or something similar. + if( mbSkipOutsideFormat && nLine > 2 + && !maStatus.AutoPageHeight() && maPaperSize.Height() < nCurrentPosY ) + { + if ( pLine && ( nIndex >= pNode->Len()) ) + nDelFromLine = nLine; + break; + } if ( !pLine ) { if ( nIndex < pNode->Len() ) { pLine = new EditLine; - rParaPortion.GetLines().Insert(++nLine, pLine); + rParaPortion.GetLines().Insert(++nLine, std::unique_ptr<EditLine>(pLine)); } else if ( nIndex && bLineBreak && GetTextRanger() ) { @@ -1626,7 +1824,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) TextPortion* pDummyPortion = new TextPortion( 0 ); rParaPortion.GetTextPortions().Append(pDummyPortion); pLine = new EditLine; - rParaPortion.GetLines().Insert(++nLine, pLine); + rParaPortion.GetLines().Insert(++nLine, std::unique_ptr<EditLine>(pLine)); bForceOneRun = true; bProcessingEmptyLine = true; } @@ -1645,68 +1843,63 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) if ( nDelFromLine >= 0 ) rParaPortion.GetLines().DeleteFromLine( nDelFromLine ); - DBG_ASSERT( rParaPortion.GetLines().Count(), "No line after CreateLines!" ); + DBG_ASSERT(rParaPortion.GetLines().Count(), "No line after CreateLines!"); if ( bLineBreak ) - CreateAndInsertEmptyLine( &rParaPortion ); - - pBuf.reset(); + CreateAndInsertEmptyLine(rParaPortion); - bool bHeightChanged = FinishCreateLines( &rParaPortion ); - - if ( bMapChanged ) - GetRefDevice()->Pop(); + bool bHeightChanged = FinishCreateLines(rParaPortion); GetRefDevice()->Pop(); return bHeightChanged; } -void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) +void ImpEditEngine::CreateAndInsertEmptyLine(ParaPortion& rParaPortion) { DBG_ASSERT( !GetTextRanger(), "Don't use CreateAndInsertEmptyLine with a polygon!" ); EditLine* pTmpLine = new EditLine; - pTmpLine->SetStart( pParaPortion->GetNode()->Len() ); - pTmpLine->SetEnd( pParaPortion->GetNode()->Len() ); - pParaPortion->GetLines().Append(pTmpLine); + pTmpLine->SetStart(rParaPortion.GetNode()->Len()); + pTmpLine->SetEnd(rParaPortion.GetNode()->Len()); + rParaPortion.GetLines().Append(std::unique_ptr<EditLine>(pTmpLine)); - bool bLineBreak = pParaPortion->GetNode()->Len() > 0; + bool bLineBreak = rParaPortion.GetNode()->Len() > 0; sal_Int32 nSpaceBefore = 0; - sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pParaPortion->GetNode(), &nSpaceBefore ); - const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pParaPortion->GetNode() ); - const SvxLineSpacingItem& rLSItem = pParaPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); - tools::Long nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore ); + sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth(rParaPortion.GetNode(), &nSpaceBefore); + const SvxLRSpaceItem& rLRItem = GetLRSpaceItem(rParaPortion.GetNode()); + const SvxLineSpacingItem& rLSItem = rParaPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); + tools::Long nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore); tools::Rectangle aBulletArea { Point(), Point() }; if ( bLineBreak ) { - nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth ); + nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth); } else { - aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( pParaPortion ) ); + aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos(&rParaPortion)); if ( !aBulletArea.IsEmpty() && aBulletArea.Right() > 0 ) - pParaPortion->SetBulletX( static_cast<sal_Int32>(GetXValue( aBulletArea.Right() )) ); + rParaPortion.SetBulletX(sal_Int32(scaleXSpacingValue(aBulletArea.Right()))); else - pParaPortion->SetBulletX( 0 ); // If Bullet set incorrectly. - if ( pParaPortion->GetBulletX() > nStartX ) + rParaPortion.SetBulletX( 0 ); // If Bullet set incorrectly. + if (rParaPortion.GetBulletX() > nStartX) { - nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth ); - if ( pParaPortion->GetBulletX() > nStartX ) - nStartX = pParaPortion->GetBulletX(); + nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth); + if (rParaPortion.GetBulletX() > nStartX) + nStartX = rParaPortion.GetBulletX(); } } SvxFont aTmpFont; - SeekCursor( pParaPortion->GetNode(), bLineBreak ? pParaPortion->GetNode()->Len() : 0, aTmpFont ); - aTmpFont.SetPhysFont(*pRefDev); + SeekCursor(rParaPortion.GetNode(), bLineBreak ? rParaPortion.GetNode()->Len() : 0, aTmpFont ); + aTmpFont.SetPhysFont(*mpRefDev); TextPortion* pDummyPortion = new TextPortion( 0 ); - pDummyPortion->GetSize() = aTmpFont.GetPhysTxtSize( pRefDev ); + pDummyPortion->SetSize(aTmpFont.GetPhysTxtSize(mpRefDev)); if ( IsFixedCellHeight() ) - pDummyPortion->GetSize().setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); - pParaPortion->GetTextPortions().Append(pDummyPortion); + pDummyPortion->setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); + rParaPortion.GetTextPortions().Append(pDummyPortion); FormatterFontMetric aFormatterMetrics; RecalcFormatterFontMetrics( aFormatterMetrics, aTmpFont ); pTmpLine->SetMaxAscent( aFormatterMetrics.nMaxAscent ); @@ -1715,12 +1908,12 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) if ( nLineHeight > pTmpLine->GetHeight() ) pTmpLine->SetHeight( nLineHeight ); - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { - sal_Int32 nPara = GetParaPortions().GetPos( pParaPortion ); + sal_Int32 nPara = GetParaPortions().GetPos(&rParaPortion); SvxAdjust eJustification = GetJustification( nPara ); - tools::Long nMaxLineWidth = GetColumnWidth(aPaperSize); - nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); + tools::Long nMaxLineWidth = GetColumnWidth(maPaperSize); + nMaxLineWidth -= scaleXSpacingValue(rLRItem.GetRight()); if ( nMaxLineWidth < 0 ) nMaxLineWidth = 1; if ( eJustification == SvxAdjust::Center ) @@ -1731,7 +1924,7 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) pTmpLine->SetStartPosX( nStartX ); - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Min ) { @@ -1755,7 +1948,7 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) } else if ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop ) { - sal_Int32 nPara = GetParaPortions().GetPos( pParaPortion ); + sal_Int32 nPara = GetParaPortions().GetPos(&rParaPortion); if ( nPara || pTmpLine->GetStartPortion() ) // Not the very first line { // There are documents with PropLineSpace 0, why? @@ -1792,37 +1985,37 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) { // -2: The new one is already inserted. #ifdef DBG_UTIL - EditLine& rLastLine = pParaPortion->GetLines()[pParaPortion->GetLines().Count()-2]; - DBG_ASSERT( rLastLine.GetEnd() == pParaPortion->GetNode()->Len(), "different anyway?" ); + EditLine& rLastLine = rParaPortion.GetLines()[rParaPortion.GetLines().Count()-2]; + DBG_ASSERT( rLastLine.GetEnd() == rParaPortion.GetNode()->Len(), "different anyway?" ); #endif - sal_Int32 nPos = pParaPortion->GetTextPortions().Count() - 1 ; + sal_Int32 nPos = rParaPortion.GetTextPortions().Count() - 1 ; pTmpLine->SetStartPortion( nPos ); pTmpLine->SetEndPortion( nPos ); } } -bool ImpEditEngine::FinishCreateLines( ParaPortion* pParaPortion ) +bool ImpEditEngine::FinishCreateLines(ParaPortion& rParaPortion) { // CalcCharPositions( pParaPortion ); - pParaPortion->SetValid(); - tools::Long nOldHeight = pParaPortion->GetHeight(); - CalcHeight( pParaPortion ); + rParaPortion.SetValid(); + tools::Long nOldHeight = rParaPortion.GetHeight(); + CalcHeight(rParaPortion); - DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "FinishCreateLines: No Text-Portion?" ); - bool bRet = ( pParaPortion->GetHeight() != nOldHeight ); + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "FinishCreateLines: No Text-Portion?"); + bool bRet = rParaPortion.GetHeight() != nOldHeight; return bRet; } -void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate ) +void ImpEditEngine::ImpBreakLine(ParaPortion& rParaPortion, EditLine& rLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate) { - ContentNode* const pNode = pParaPortion->GetNode(); + ContentNode* const pNode = rParaPortion.GetNode(); - sal_Int32 nBreakInLine = nPortionStart - pLine->GetStart(); + sal_Int32 nBreakInLine = nPortionStart - rLine.GetStart(); sal_Int32 nMax = nBreakInLine + pPortion->GetLen(); - while ( ( nBreakInLine < nMax ) && ( pLine->GetCharPosArray()[nBreakInLine] < nRemainingWidth ) ) + while ( ( nBreakInLine < nMax ) && ( rLine.GetCharPosArray()[nBreakInLine] < nRemainingWidth ) ) nBreakInLine++; - sal_Int32 nMaxBreakPos = nBreakInLine + pLine->GetStart(); + sal_Int32 nMaxBreakPos = nBreakInLine + rLine.GetStart(); sal_Int32 nBreakPos = SAL_MAX_INT32; bool bCompressBlank = false; @@ -1834,7 +2027,7 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te bool bAltFullRight = false; sal_uInt32 nAltDelChar = 0; - if ( ( nMaxBreakPos < ( nMax + pLine->GetStart() ) ) && ( pNode->GetChar( nMaxBreakPos ) == ' ' ) ) + if ( ( nMaxBreakPos < ( nMax + rLine.GetStart() ) ) && ( pNode->GetChar( nMaxBreakPos ) == ' ' ) ) { // Break behind the blank, blank will be compressed... nBreakPos = nMaxBreakPos + 1; @@ -1842,7 +2035,7 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te } else { - sal_Int32 nMinBreakPos = pLine->GetStart(); + sal_Int32 nMinBreakPos = rLine.GetStart(); const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs(); for (size_t nAttr = rAttrs.size(); nAttr; ) { @@ -1880,9 +2073,20 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te aUserOptions.allowPunctuationOutsideMargin = bAllowPunctuationOutsideMargin; aUserOptions.allowHyphenateEnglish = false; - i18n::LineBreakResults aLBR = _xBI->getLineBreak( - pNode->GetString(), nMaxBreakPos, aLocale, nMinBreakPos, aHyphOptions, aUserOptions ); - nBreakPos = aLBR.breakIndex; + if (!maStatus.IsSingleLine()) + { + i18n::LineBreakResults aLBR = _xBI->getLineBreak( + pNode->GetString(), nMaxBreakPos, aLocale, nMinBreakPos, aHyphOptions, aUserOptions ); + nBreakPos = aLBR.breakIndex; + + // show soft hyphen + if ( nBreakPos && CH_SOFTHYPHEN == pNode->GetString()[ sal_Int32(nBreakPos) - 1 ] ) + bHyphenated = true; + } + else + { + nBreakPos = nMaxBreakPos; + } // BUG in I18N - under special condition (break behind field, #87327#) breakIndex is < nMinBreakPos if ( nBreakPos < nMinBreakPos ) @@ -1909,7 +2113,7 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te } bHangingPunctuation = nBreakPos > nMaxBreakPos; - pLine->SetHangingPunctuation( bHangingPunctuation ); + rLine.SetHangingPunctuation( bHangingPunctuation ); // Whether a separator or not, push the word after the separator through // hyphenation... NMaxBreakPos is the last character that fits into @@ -1931,14 +2135,14 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te const OUString aWord = pNode->GetString().copy(nWordStart, nWordLen); sal_Int32 nMinTrail = nWordEnd-nMaxBreakPos+1; //+1: Before the dickey letter Reference< XHyphenatedWord > xHyphWord; - if (xHyphenator.is()) - xHyphWord = xHyphenator->hyphenate( aWord, aLocale, aWord.getLength() - nMinTrail, Sequence< PropertyValue >() ); + if (mxHyphenator.is()) + xHyphWord = mxHyphenator->hyphenate( aWord, aLocale, aWord.getLength() - nMinTrail, Sequence< PropertyValue >() ); if (xHyphWord.is()) { bool bAlternate = xHyphWord->isAlternativeSpelling(); sal_Int32 _nWordLen = 1 + xHyphWord->getHyphenPos(); - if ( ( _nWordLen >= 2 ) && ( (nWordStart+_nWordLen) >= (pLine->GetStart() + 2 ) ) ) + if ( ( _nWordLen >= 2 ) && ( (nWordStart+_nWordLen) >= (rLine.GetStart() + 2 ) ) ) { if ( !bAlternate ) { @@ -1949,8 +2153,8 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te { // TODO: handle all alternative hyphenations (see hyphen-1.2.8/tests/unicode.*) OUString aAlt( xHyphWord->getHyphenatedWord() ); - OUString aAltLeft(aAlt.copy(0, _nWordLen)); - OUString aAltRight(aAlt.copy(_nWordLen)); + std::u16string_view aAltLeft(aAlt.subView(0, _nWordLen)); + std::u16string_view aAltRight(aAlt.subView(_nWordLen)); bAltFullLeft = aWord.startsWith(aAltLeft); bAltFullRight = aWord.endsWith(aAltRight); nAltDelChar = aWord.getLength() - aAlt.getLength() + static_cast<int>(!bAltFullLeft) + static_cast<int>(!bAltFullRight); @@ -2009,39 +2213,42 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te } } - if ( nBreakPos <= pLine->GetStart() ) + if ( nBreakPos <= rLine.GetStart() ) { // No separator in line => Chop! nBreakPos = nMaxBreakPos; // I18N nextCharacters ! - if ( nBreakPos <= pLine->GetStart() ) - nBreakPos = pLine->GetStart() + 1; // Otherwise infinite loop! + if ( nBreakPos <= rLine.GetStart() ) + nBreakPos = rLine.GetStart() + 1; // Otherwise infinite loop! } } // the dickey portion is the end portion - pLine->SetEnd( nBreakPos ); + rLine.SetEnd( nBreakPos ); - sal_Int32 nEndPortion = SplitTextPortion( pParaPortion, nBreakPos, pLine ); + sal_Int32 nEndPortion = SplitTextPortion(rParaPortion, nBreakPos, &rLine); if ( !bCompressBlank && !bHangingPunctuation ) { // When justification is not SvxAdjust::Left, it's important to compress // the trailing space even if there is enough room for the space... // Don't check for SvxAdjust::Left, doesn't matter to compress in this case too... - assert( nBreakPos > pLine->GetStart() && "ImpBreakLines - BreakPos not expected!" ); + assert( nBreakPos > rLine.GetStart() && "ImpBreakLines - BreakPos not expected!" ); if ( pNode->GetChar( nBreakPos-1 ) == ' ' ) bCompressBlank = true; } if ( bCompressBlank || bHangingPunctuation ) { - TextPortion& rTP = pParaPortion->GetTextPortions()[nEndPortion]; + TextPortion& rTP = rParaPortion.GetTextPortions()[nEndPortion]; DBG_ASSERT( rTP.GetKind() == PortionKind::TEXT, "BlankRubber: No TextPortion!" ); - DBG_ASSERT( nBreakPos > pLine->GetStart(), "SplitTextPortion at the beginning of the line?" ); - sal_Int32 nPosInArray = nBreakPos - 1 - pLine->GetStart(); - rTP.GetSize().setWidth( ( nPosInArray && ( rTP.GetLen() > 1 ) ) ? pLine->GetCharPosArray()[ nPosInArray-1 ] : 0 ); - pLine->GetCharPosArray()[ nPosInArray ] = rTP.GetSize().Width(); + DBG_ASSERT( nBreakPos > rLine.GetStart(), "SplitTextPortion at the beginning of the line?" ); + sal_Int32 nPosInArray = nBreakPos - 1 - rLine.GetStart(); + rTP.setWidth( ( nPosInArray && ( rTP.GetLen() > 1 ) ) ? rLine.GetCharPosArray()[ nPosInArray-1 ] : 0 ); + if (o3tl::make_unsigned(nPosInArray) < rLine.GetCharPosArray().size()) + { + rLine.GetCharPosArray()[ nPosInArray ] = rTP.GetSize().Width(); + } } else if ( bHyphenated ) { @@ -2050,51 +2257,55 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te pHyphPortion->SetKind( PortionKind::HYPHENATOR ); if ( (cAlternateReplChar || cAlternateExtraChar) && bAltFullRight ) // alternation after the break doesn't supported { - TextPortion& rPrev = pParaPortion->GetTextPortions()[nEndPortion]; + TextPortion& rPrev = rParaPortion.GetTextPortions()[nEndPortion]; DBG_ASSERT( rPrev.GetLen(), "Hyphenate: Prev portion?!" ); rPrev.SetLen( rPrev.GetLen() - nAltDelChar ); pHyphPortion->SetLen( nAltDelChar ); if (cAlternateReplChar && !bAltFullLeft) pHyphPortion->SetExtraValue( cAlternateReplChar ); // Correct width of the portion above: - rPrev.GetSize().setWidth( - pLine->GetCharPosArray()[ nBreakPos-1 - pLine->GetStart() - nAltDelChar ] ); + rPrev.setWidth( + rLine.GetCharPosArray()[ nBreakPos-1 - rLine.GetStart() - nAltDelChar ] ); } // Determine the width of the Hyph-Portion: SvxFont aFont; - SeekCursor( pParaPortion->GetNode(), nBreakPos, aFont ); + SeekCursor(rParaPortion.GetNode(), nBreakPos, aFont); aFont.SetPhysFont(*GetRefDevice()); - pHyphPortion->GetSize().setHeight( GetRefDevice()->GetTextHeight() ); - pHyphPortion->GetSize().setWidth( GetRefDevice()->GetTextWidth( CH_HYPH ) ); + pHyphPortion->SetSize(Size(GetRefDevice()->GetTextWidth(CH_HYPH), GetRefDevice()->GetTextHeight())); - pParaPortion->GetTextPortions().Insert(++nEndPortion, pHyphPortion); + rParaPortion.GetTextPortions().Insert(++nEndPortion, pHyphPortion); } - pLine->SetEndPortion( nEndPortion ); + rLine.SetEndPortion( nEndPortion ); } -void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, tools::Long nRemainingSpace ) +void ImpEditEngine::ImpAdjustBlocks(ParaPortion& rParaPortion, EditLine& rLine, tools::Long nRemainingSpace ) { DBG_ASSERT( nRemainingSpace > 0, "AdjustBlocks: Somewhat too little..." ); - assert( pLine && "AdjustBlocks: Line ?!" ); - if ( ( nRemainingSpace < 0 ) || pLine->IsEmpty() ) + + if ( ( nRemainingSpace < 0 ) || rLine.IsEmpty() ) return ; - const sal_Int32 nFirstChar = pLine->GetStart(); - const sal_Int32 nLastChar = pLine->GetEnd() -1; // Last points behind - ContentNode* pNode = pParaPortion->GetNode(); + const sal_Int32 nFirstChar = rLine.GetStart(); + const sal_Int32 nLastChar = rLine.GetEnd() -1; // Last points behind + ContentNode* pNode = rParaPortion.GetNode(); DBG_ASSERT( nLastChar < pNode->Len(), "AdjustBlocks: Out of range!" ); // Search blanks or Kashidas... std::vector<sal_Int32> aPositions; + + // Kashidas ? + ImpFindKashidas( pNode, nFirstChar, nLastChar, aPositions ); + auto nKashidas = aPositions.size(); + sal_uInt16 nLastScript = i18n::ScriptType::LATIN; for ( sal_Int32 nChar = nFirstChar; nChar <= nLastChar; nChar++ ) { EditPaM aPaM( pNode, nChar+1 ); - LanguageType eLang = GetLanguage(aPaM); + LanguageType eLang = GetLanguage(aPaM).nLang; sal_uInt16 nScript = GetI18NScriptType(aPaM); - if ( MsLangId::getPrimaryLanguage( eLang) == LANGUAGE_ARABIC_PRIMARY_ONLY ) - // Arabic script is handled later. + // Arabic script is handled above, but if no Kashida positions are found, use blanks. + if (MsLangId::getPrimaryLanguage(eLang) == LANGUAGE_ARABIC_PRIMARY_ONLY && nKashidas) continue; if ( pNode->GetChar(nChar) == ' ' ) @@ -2120,9 +2331,6 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, nLastScript = nScript; } - // Kashidas ? - ImpFindKashidas( pNode, nFirstChar, nLastChar, aPositions ); - if ( aPositions.empty() ) return; @@ -2130,26 +2338,26 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, // The width must be distributed to the blockers in front... // But not if it is the only one. if ( ( pNode->GetChar( nLastChar ) == ' ' ) && ( aPositions.size() > 1 ) && - ( MsLangId::getPrimaryLanguage( GetLanguage( EditPaM( pNode, nLastChar ) ) ) != LANGUAGE_ARABIC_PRIMARY_ONLY ) ) + ( MsLangId::getPrimaryLanguage( GetLanguage( EditPaM( pNode, nLastChar ) ).nLang ) != LANGUAGE_ARABIC_PRIMARY_ONLY ) ) { aPositions.pop_back(); sal_Int32 nPortionStart, nPortion; - nPortion = pParaPortion->GetTextPortions().FindPortion( nLastChar+1, nPortionStart ); - TextPortion& rLastPortion = pParaPortion->GetTextPortions()[ nPortion ]; - tools::Long nRealWidth = pLine->GetCharPosArray()[nLastChar-nFirstChar]; + nPortion = rParaPortion.GetTextPortions().FindPortion( nLastChar+1, nPortionStart ); + TextPortion& rLastPortion = rParaPortion.GetTextPortions()[ nPortion ]; + tools::Long nRealWidth = rLine.GetCharPosArray()[nLastChar-nFirstChar]; tools::Long nBlankWidth = nRealWidth; if ( nLastChar > nPortionStart ) - nBlankWidth -= pLine->GetCharPosArray()[nLastChar-nFirstChar-1]; + nBlankWidth -= rLine.GetCharPosArray()[nLastChar-nFirstChar-1]; // Possibly the blank has already been deducted in ImpBreakLine: if ( nRealWidth == rLastPortion.GetSize().Width() ) { // For the last character the portion must stop behind the blank // => Simplify correction: DBG_ASSERT( ( nPortionStart + rLastPortion.GetLen() ) == ( nLastChar+1 ), "Blank actually not at the end of the portion!?"); - rLastPortion.GetSize().AdjustWidth( -nBlankWidth ); + rLastPortion.adjustSize(-nBlankWidth, 0); nRemainingSpace += nBlankWidth; } - pLine->GetCharPosArray()[nLastChar-nFirstChar] -= nBlankWidth; + rLine.GetCharPosArray()[nLastChar-nFirstChar] -= nBlankWidth; } size_t nGaps = aPositions.size(); @@ -2159,6 +2367,19 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, DBG_ASSERT( nSomeExtraSpace < static_cast<tools::Long>(nGaps), "AdjustBlocks: ExtraSpace too large" ); DBG_ASSERT( nSomeExtraSpace >= 0, "AdjustBlocks: ExtraSpace < 0 " ); + // Mark Kashida positions, so that VCL knows where to insert Kashida and + // where to only expand the width. + if (nKashidas) + { + rLine.GetKashidaArray().resize(rLine.GetCharPosArray().size(), false); + for (size_t i = 0; i < nKashidas; i++) + { + auto nChar = aPositions[i]; + if ( nChar < nLastChar ) + rLine.GetKashidaArray()[nChar-nFirstChar] = 1 /*sal_True*/; + } + } + // Correct the positions in the Array and the portion widths: // Last character won't be considered... for (auto const& nChar : aPositions) @@ -2166,22 +2387,23 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, if ( nChar < nLastChar ) { sal_Int32 nPortionStart, nPortion; - nPortion = pParaPortion->GetTextPortions().FindPortion( nChar, nPortionStart, true ); - TextPortion& rLastPortion = pParaPortion->GetTextPortions()[ nPortion ]; + nPortion = rParaPortion.GetTextPortions().FindPortion( nChar, nPortionStart, true ); + TextPortion& rLastPortion = rParaPortion.GetTextPortions()[ nPortion ]; // The width of the portion: - rLastPortion.GetSize().AdjustWidth(nMore4Everyone ); - if ( nSomeExtraSpace ) - rLastPortion.GetSize().AdjustWidth( 1 ); + rLastPortion.adjustSize(nMore4Everyone, 0); + if (nSomeExtraSpace) + { + rLastPortion.adjustSize(1, 0); + } // Correct positions in array - // Even for kashidas just change positions, VCL will then draw the kashida automatically sal_Int32 nPortionEnd = nPortionStart + rLastPortion.GetLen(); for ( sal_Int32 _n = nChar; _n < nPortionEnd; _n++ ) { - pLine->GetCharPosArray()[_n-nFirstChar] += nMore4Everyone; + rLine.GetCharPosArray()[_n-nFirstChar] += nMore4Everyone; if ( nSomeExtraSpace ) - pLine->GetCharPosArray()[_n-nFirstChar]++; + rLine.GetCharPosArray()[_n-nFirstChar]++; } if ( nSomeExtraSpace ) @@ -2190,11 +2412,18 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, } // Now the text width contains the extra width... - pLine->SetTextWidth( pLine->GetTextWidth() + nRemainingSpace ); + rLine.SetTextWidth(rLine.GetTextWidth() + nRemainingSpace); } +// For Kashidas from sw/source/core/text/porlay.cxx void ImpEditEngine::ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, std::vector<sal_Int32>& rArray ) { + // Kashida glyph looks suspicious, skip Kashida justification + if (GetRefDevice()->GetMinKashida() <= 0) + return; + + std::vector<sal_Int32> aKashidaArray; + // the search has to be performed on a per word base EditSelection aWordSel( EditPaM( pNode, nStart ) ); @@ -2213,12 +2442,20 @@ void ImpEditEngine::ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_I // restore selection for proper iteration at the end of the function aWordSel.Max().SetIndex( nSavPos ); - sal_Int32 nIdx = 0; + sal_Int32 nIdx = 0, nPrevIdx = 0; sal_Int32 nKashidaPos = -1; - sal_Unicode cCh; - sal_Unicode cPrevCh = 0; + sal_Unicode cCh, cPrevCh = 0; - while ( nIdx < aWord.getLength() ) + int nPriorityLevel = 7; // 0..6 = level found + // 7 not found + + sal_Int32 nWordLen = aWord.getLength(); + + // ignore trailing vowel chars + while( nWordLen && isTransparentChar( aWord[ nWordLen - 1 ] )) + --nWordLen; + + while ( nIdx < nWordLen ) { cCh = aWord[ nIdx ]; @@ -2227,104 +2464,163 @@ void ImpEditEngine::ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_I if ( 0x640 == cCh ) { nKashidaPos = aWordSel.Min().GetIndex() + nIdx; - break; + nPriorityLevel = 0; } // 2. Priority: // after a Seen or Sad - if ( nIdx + 1 < aWord.getLength() && - ( 0x633 == cCh || 0x635 == cCh ) ) + if (nPriorityLevel >= 1 && nIdx < nWordLen - 1) { - nKashidaPos = aWordSel.Min().GetIndex() + nIdx; - break; + if( isSeenOrSadChar( cCh ) + && (aWord[ nIdx+1 ] != 0x200C) ) // #i98410#: prevent ZWNJ expansion + { + nKashidaPos = aWordSel.Min().GetIndex() + nIdx; + nPriorityLevel = 1; + } } // 3. Priority: - // before final form of the Marbuta, Hah, Dal - // 4. Priority: - // before final form of Alef, Lam or Kaf - if ( nIdx && nIdx + 1 == aWord.getLength() && - ( 0x629 == cCh || 0x62D == cCh || 0x62F == cCh || - 0x627 == cCh || 0x644 == cCh || 0x643 == cCh ) ) + // before final form of Teh Marbuta, Heh, Dal + if ( nPriorityLevel >= 2 && nIdx > 0 ) { - DBG_ASSERT( 0 != cPrevCh, "No previous character" ); + if ( isTehMarbutaChar ( cCh ) || // Teh Marbuta (right joining) + isDalChar ( cCh ) || // Dal (right joining) final form may appear in the middle of word + ( isHehChar ( cCh ) && nIdx == nWordLen - 1)) // Heh (dual joining) only at end of word + { - // check if character is connectable to previous character, - if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 2; + } + } + } + + // 4. Priority: + // before final form of Alef, Tah, Lam, Kaf or Gaf + if ( nPriorityLevel >= 3 && nIdx > 0 ) + { + if ( isAlefChar ( cCh ) || // Alef (right joining) final form may appear in the middle of word + (( isLamChar ( cCh ) || // Lam, + isTahChar ( cCh ) || // Tah, + isKafChar ( cCh ) || // Kaf (all dual joining) + isGafChar ( cCh ) ) + && nIdx == nWordLen - 1)) // only at end of word { - nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1; - break; + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 3; + } } } // 5. Priority: - // before media Bah - if ( nIdx && nIdx + 1 < aWord.getLength() && 0x628 == cCh ) + // before medial Beh-like + if ( nPriorityLevel >= 4 && nIdx > 0 && nIdx < nWordLen - 1 ) { - DBG_ASSERT( 0 != cPrevCh, "No previous character" ); - - // check if next character is Reh, Yeh or Alef Maksura - sal_Unicode cNextCh = aWord[ nIdx + 1 ]; + if ( isBehChar ( cCh ) ) + { + // check if next character is Reh or Yeh-like + sal_Unicode cNextCh = aWord[ nIdx + 1 ]; + if ( isRehChar ( cNextCh ) || isYehChar ( cNextCh )) + { + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 4; + } + } + } + } - if ( 0x631 == cNextCh || 0x64A == cNextCh || - 0x649 == cNextCh ) + // 6. Priority: + // before the final form of Waw, Ain, Qaf and Feh + if ( nPriorityLevel >= 5 && nIdx > 0 ) + { + if ( isWawChar ( cCh ) || // Wav (right joining) + // final form may appear in the middle of word + (( isAinChar ( cCh ) || // Ain (dual joining) + isQafChar ( cCh ) || // Qaf (dual joining) + isFehChar ( cCh ) ) // Feh (dual joining) + && nIdx == nWordLen - 1)) // only at end of word { + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); // check if character is connectable to previous character, if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) - nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1; + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 5; + } } } - // 6. Priority: // other connecting possibilities - if ( nIdx && nIdx + 1 == aWord.getLength() && - 0x60C <= cCh && 0x6FE >= cCh ) + if ( nPriorityLevel >= 6 && nIdx > 0 ) { - DBG_ASSERT( 0 != cPrevCh, "No previous character" ); - - // check if character is connectable to previous character, - if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + // Reh, Zain + if ( isRehChar ( cCh ) ) { - // only choose this position if we did not find - // a better one: - if ( nKashidaPos<0 ) - nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1; - break; + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 6; + } } } - // Do not consider Fathatan, Dammatan, Kasratan, Fatha, - // Damma, Kasra, Shadda and Sukun when checking if - // a character can be connected to previous character. - if ( cCh < 0x64B || cCh > 0x652 ) + // Do not consider vowel marks when checking if a character + // can be connected to previous character. + if ( !isTransparentChar ( cCh) ) + { cPrevCh = cCh; + nPrevIdx = nIdx; + } ++nIdx; } // end of current word if ( nKashidaPos>=0 ) - rArray.push_back( nKashidaPos ); + aKashidaArray.push_back( nKashidaPos ); aWordSel = WordRight( aWordSel.Max(), css::i18n::WordType::DICTIONARY_WORD ); aWordSel = SelectWord( aWordSel, css::i18n::WordType::DICTIONARY_WORD ); } + + // Validate + std::vector<sal_Int32> aDropped(aKashidaArray.size()); + auto nOldLayout = GetRefDevice()->GetLayoutMode(); + GetRefDevice()->SetLayoutMode(nOldLayout | vcl::text::ComplexTextLayoutFlags::BiDiRtl); + GetRefDevice()->ValidateKashidas(pNode->GetString(), nStart, nEnd - nStart, + aKashidaArray.size(), aKashidaArray.data(), aDropped.data()); + GetRefDevice()->SetLayoutMode(nOldLayout); + + for (auto const& pos : aKashidaArray) + if (std::find(aDropped.begin(), aDropped.end(), pos) == aDropped.end()) + rArray.push_back(pos); } -sal_Int32 ImpEditEngine::SplitTextPortion( ParaPortion* pPortion, sal_Int32 nPos, EditLine* pCurLine ) +sal_Int32 ImpEditEngine::SplitTextPortion(ParaPortion& rParaPortion, sal_Int32 nPos, EditLine* pCurLine) { // The portion at nPos is split, if there is not a transition at nPos anyway if ( nPos == 0 ) return 0; - assert( pPortion && "SplitTextPortion: Which ?" ); - sal_Int32 nSplitPortion; sal_Int32 nTmpPos = 0; TextPortion* pTextPortion = nullptr; - sal_Int32 nPortions = pPortion->GetTextPortions().Count(); + sal_Int32 nPortions = rParaPortion.GetTextPortions().Count(); for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ ) { - TextPortion& rTP = pPortion->GetTextPortions()[nSplitPortion]; + TextPortion& rTP = rParaPortion.GetTextPortions()[nSplitPortion]; nTmpPos = nTmpPos + rTP.GetLen(); if ( nTmpPos >= nPos ) { @@ -2347,44 +2643,45 @@ sal_Int32 ImpEditEngine::SplitTextPortion( ParaPortion* pPortion, sal_Int32 nPos sal_Int32 nOverlapp = nTmpPos - nPos; pTextPortion->SetLen( pTextPortion->GetLen() - nOverlapp ); TextPortion* pNewPortion = new TextPortion( nOverlapp ); - pPortion->GetTextPortions().Insert(nSplitPortion+1, pNewPortion); + rParaPortion.GetTextPortions().Insert(nSplitPortion+1, pNewPortion); // Set sizes if ( pCurLine ) { // No new GetTextSize, instead use values from the Array: assert( nPos > pCurLine->GetStart() && "SplitTextPortion at the beginning of the line?" ); - pTextPortion->GetSize().setWidth( pCurLine->GetCharPosArray()[ nPos-pCurLine->GetStart()-1 ] ); + pTextPortion->setWidth(pCurLine->GetCharPosArray()[nPos - pCurLine->GetStart() - 1]); if ( pTextPortion->GetExtraInfos() && pTextPortion->GetExtraInfos()->bCompressed ) { // We need the original size from the portion - sal_Int32 nTxtPortionStart = pPortion->GetTextPortions().GetStartPos( nSplitPortion ); - SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() ); - SeekCursor( pPortion->GetNode(), nTxtPortionStart+1, aTmpFont ); + sal_Int32 nTxtPortionStart = rParaPortion.GetTextPortions().GetStartPos( nSplitPortion ); + SvxFont aTmpFont = rParaPortion.GetNode()->GetCharAttribs().GetDefFont(); + SeekCursor(rParaPortion.GetNode(), nTxtPortionStart + 1, aTmpFont); aTmpFont.SetPhysFont(*GetRefDevice()); - GetRefDevice()->Push( PushFlags::TEXTLANGUAGE ); + GetRefDevice()->Push( vcl::PushFlags::TEXTLANGUAGE ); ImplInitDigitMode(*GetRefDevice(), aTmpFont.GetLanguage()); - Size aSz = aTmpFont.QuickGetTextSize( GetRefDevice(), pPortion->GetNode()->GetString(), nTxtPortionStart, pTextPortion->GetLen() ); + Size aSz = aTmpFont.QuickGetTextSize( GetRefDevice(), rParaPortion.GetNode()->GetString(), + nTxtPortionStart, pTextPortion->GetLen(), nullptr ); GetRefDevice()->Pop(); pTextPortion->GetExtraInfos()->nOrgWidth = aSz.Width(); } } else - pTextPortion->GetSize().setWidth( -1 ); + pTextPortion->setWidth(-1); return nSplitPortion; } -void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rStart ) +void ImpEditEngine::CreateTextPortions(ParaPortion& rParaPortion, sal_Int32& rStart) { sal_Int32 nStartPos = rStart; - ContentNode* pNode = pParaPortion->GetNode(); + ContentNode* pNode = rParaPortion.GetNode(); DBG_ASSERT( pNode->Len(), "CreateTextPortions should not be used for empty paragraphs!" ); o3tl::sorted_vector< sal_Int32 > aPositions; aPositions.insert( 0 ); - for (sal_uInt16 nAttr = 0;; ++nAttr) + for (std::size_t nAttr = 0;; ++nAttr) { // Insert Start and End into the Array... // The Insert method does not allow for duplicate values... @@ -2396,15 +2693,13 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS } aPositions.insert( pNode->Len() ); - if ( pParaPortion->aScriptInfos.empty() ) - InitScriptTypes( GetParaPortions().GetPos( pParaPortion ) ); + if (rParaPortion.getScriptTypePosInfos().empty()) + InitScriptTypes(GetParaPortions().GetPos(&rParaPortion)); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; - for (const ScriptTypePosInfo& rType : rTypes) + for (const ScriptTypePosInfo& rType : rParaPortion.getScriptTypePosInfos()) aPositions.insert( rType.nStartPos ); - const WritingDirectionInfos& rWritingDirections = pParaPortion->aWritingDirectionInfos; - for (const WritingDirectionInfo & rWritingDirection : rWritingDirections) + for (const WritingDirectionInfo& rWritingDirection : rParaPortion.getWritingDirectionInfos()) aPositions.insert( rWritingDirection.nStartPos ); if ( mpIMEInfos && mpIMEInfos->nLen && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetNode() == pNode ) ) @@ -2427,9 +2722,9 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS sal_Int32 nPortionStart = 0; sal_Int32 nInvPortion = 0; sal_Int32 nP; - for ( nP = 0; nP < pParaPortion->GetTextPortions().Count(); nP++ ) + for ( nP = 0; nP < rParaPortion.GetTextPortions().Count(); nP++ ) { - const TextPortion& rTmpPortion = pParaPortion->GetTextPortions()[nP]; + const TextPortion& rTmpPortion = rParaPortion.GetTextPortions()[nP]; nPortionStart = nPortionStart + rTmpPortion.GetLen(); if ( nPortionStart >= nStartPos ) { @@ -2439,16 +2734,16 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS break; } } - DBG_ASSERT( nP < pParaPortion->GetTextPortions().Count() || !pParaPortion->GetTextPortions().Count(), "Nothing to delete: CreateTextPortions" ); - if ( nInvPortion && ( nPortionStart+pParaPortion->GetTextPortions()[nInvPortion].GetLen() > nStartPos ) ) + DBG_ASSERT( nP < rParaPortion.GetTextPortions().Count() || !rParaPortion.GetTextPortions().Count(), "Nothing to delete: CreateTextPortions" ); + if ( nInvPortion && ( nPortionStart + rParaPortion.GetTextPortions()[nInvPortion].GetLen() > nStartPos ) ) { // prefer one in front... // But only if it was in the middle of the portion of, otherwise it // might be the only one in the row in front! nInvPortion--; - nPortionStart = nPortionStart - pParaPortion->GetTextPortions()[nInvPortion].GetLen(); + nPortionStart = nPortionStart - rParaPortion.GetTextPortions()[nInvPortion].GetLen(); } - pParaPortion->GetTextPortions().DeleteFromPortion( nInvPortion ); + rParaPortion.GetTextPortions().DeleteFromPortion( nInvPortion ); // A portion may also have been formed by a line break: aPositions.insert( nPortionStart ); @@ -2461,21 +2756,21 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS while ( i != aPositions.end() ) { TextPortion* pNew = new TextPortion( (*i++) - *nInvPos++ ); - pParaPortion->GetTextPortions().Append(pNew); + rParaPortion.GetTextPortions().Append(pNew); } - DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "No Portions?!" ); + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "No Portions?!"); #if OSL_DEBUG_LEVEL > 0 - OSL_ENSURE( ParaPortion::DbgCheckTextPortions(*pParaPortion), "Portion is broken?" ); + OSL_ENSURE( ParaPortion::DbgCheckTextPortions(rParaPortion), "Portion is broken?" ); #endif } -void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars ) +void ImpEditEngine::RecalcTextPortion(ParaPortion& rParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars) { - DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "No Portions!" ); + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "No Portions!"); DBG_ASSERT( nNewChars, "RecalcTextPortion with Diff == 0" ); - ContentNode* const pNode = pParaPortion->GetNode(); + ContentNode* const pNode = rParaPortion.GetNode(); if ( nNewChars > 0 ) { // If an Attribute begins/ends at nStartPos, then a new portion starts @@ -2484,31 +2779,30 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta { sal_Int32 nNewPortionPos = 0; if ( nStartPos ) - nNewPortionPos = SplitTextPortion( pParaPortion, nStartPos ) + 1; + nNewPortionPos = SplitTextPortion(rParaPortion, nStartPos) + 1; // A blank portion may be here, if the paragraph was empty, // or if a line was created by a hard line break. - if ( ( nNewPortionPos < pParaPortion->GetTextPortions().Count() ) && - !pParaPortion->GetTextPortions()[nNewPortionPos].GetLen() ) + if ( ( nNewPortionPos < rParaPortion.GetTextPortions().Count() ) && + !rParaPortion.GetTextPortions()[nNewPortionPos].GetLen() ) { - TextPortion& rTP = pParaPortion->GetTextPortions()[nNewPortionPos]; + TextPortion& rTP = rParaPortion.GetTextPortions()[nNewPortionPos]; DBG_ASSERT( rTP.GetKind() == PortionKind::TEXT, "the empty portion was no TextPortion!" ); rTP.SetLen( rTP.GetLen() + nNewChars ); } else { TextPortion* pNewPortion = new TextPortion( nNewChars ); - pParaPortion->GetTextPortions().Insert(nNewPortionPos, pNewPortion); + rParaPortion.GetTextPortions().Insert(nNewPortionPos, pNewPortion); } } else { sal_Int32 nPortionStart; - const sal_Int32 nTP = pParaPortion->GetTextPortions(). - FindPortion( nStartPos, nPortionStart ); - TextPortion& rTP = pParaPortion->GetTextPortions()[ nTP ]; + const sal_Int32 nTP = rParaPortion.GetTextPortions().FindPortion( nStartPos, nPortionStart ); + TextPortion& rTP = rParaPortion.GetTextPortions()[ nTP ]; rTP.SetLen( rTP.GetLen() + nNewChars ); - rTP.GetSize().setWidth( -1 ); + rTP.setWidth(-1); } } else @@ -2523,11 +2817,11 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta sal_Int32 nPortion = 0; sal_Int32 nPos = 0; sal_Int32 nEnd = nStartPos-nNewChars; - sal_Int32 nPortions = pParaPortion->GetTextPortions().Count(); + sal_Int32 nPortions = rParaPortion.GetTextPortions().Count(); TextPortion* pTP = nullptr; for ( nPortion = 0; nPortion < nPortions; nPortion++ ) { - pTP = &pParaPortion->GetTextPortions()[ nPortion ]; + pTP = &rParaPortion.GetTextPortions()[ nPortion ]; if ( ( nPos+pTP->GetLen() ) > nStartPos ) { DBG_ASSERT( nPos <= nStartPos, "Wrong Start!" ); @@ -2541,14 +2835,14 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta { // Remove portion; PortionKind nType = pTP->GetKind(); - pParaPortion->GetTextPortions().Remove( nPortion ); + rParaPortion.GetTextPortions().Remove( nPortion ); if ( nType == PortionKind::LINEBREAK ) { - TextPortion& rNext = pParaPortion->GetTextPortions()[ nPortion ]; + TextPortion& rNext = rParaPortion.GetTextPortions()[ nPortion ]; if ( !rNext.GetLen() ) { // Remove dummy portion - pParaPortion->GetTextPortions().Remove( nPortion ); + rParaPortion.GetTextPortions().Remove( nPortion ); } } } @@ -2558,56 +2852,55 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta pTP->SetLen( pTP->GetLen() + nNewChars ); } - sal_Int32 nPortionCount = pParaPortion->GetTextPortions().Count(); + sal_Int32 nPortionCount = rParaPortion.GetTextPortions().Count(); assert( nPortionCount ); if (nPortionCount) { // No HYPHENATOR portion is allowed to get stuck right at the end... sal_Int32 nLastPortion = nPortionCount - 1; - pTP = &pParaPortion->GetTextPortions()[nLastPortion]; + pTP = &rParaPortion.GetTextPortions()[nLastPortion]; if ( pTP->GetKind() == PortionKind::HYPHENATOR ) { // Discard portion; if possible, correct the ones before, // if the Hyphenator portion has swallowed one character... if ( nLastPortion && pTP->GetLen() ) { - TextPortion& rPrev = pParaPortion->GetTextPortions()[nLastPortion - 1]; + TextPortion& rPrev = rParaPortion.GetTextPortions()[nLastPortion - 1]; DBG_ASSERT( rPrev.GetKind() == PortionKind::TEXT, "Portion?!" ); rPrev.SetLen( rPrev.GetLen() + pTP->GetLen() ); - rPrev.GetSize().setWidth( -1 ); + rPrev.setWidth(-1); } - pParaPortion->GetTextPortions().Remove( nLastPortion ); + rParaPortion.GetTextPortions().Remove( nLastPortion ); } } } #if OSL_DEBUG_LEVEL > 0 - OSL_ENSURE( ParaPortion::DbgCheckTextPortions(*pParaPortion), "Portions are broken?" ); + OSL_ENSURE( ParaPortion::DbgCheckTextPortions(rParaPortion), "Portions are broken?" ); #endif } void ImpEditEngine::SetTextRanger( std::unique_ptr<TextRanger> pRanger ) { - pTextRanger = std::move(pRanger); + mpTextRanger = std::move(pRanger); - for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) + for (auto& pParaPortion : GetParaPortions()) { - ParaPortion& rParaPortion = GetParaPortions()[nPara]; - rParaPortion.MarkSelectionInvalid( 0 ); - rParaPortion.GetLines().Reset(); + pParaPortion->MarkSelectionInvalid( 0 ); + pParaPortion->GetLines().Reset(); } FormatFullDoc(); UpdateViews( GetActiveView() ); - if ( GetUpdateMode() && GetActiveView() ) - pActiveView->ShowCursor(false, false); + if ( IsUpdateLayout() && GetActiveView() ) + mpActiveView->ShowCursor(false, false); } void ImpEditEngine::SetVertical( bool bVertical) { - if ( IsVertical() != bVertical) + if ( IsEffectivelyVertical() != bVertical) { GetEditDoc().SetVertical(bVertical); - bool bUseCharAttribs = bool(aStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); + bool bUseCharAttribs = bool(maStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); GetEditDoc().CreateDefFont( bUseCharAttribs ); if ( IsFormatted() ) { @@ -2619,8 +2912,10 @@ void ImpEditEngine::SetVertical( bool bVertical) void ImpEditEngine::SetRotation(TextRotation nRotation) { + if (GetEditDoc().GetRotation() == nRotation) + return; // not modified GetEditDoc().SetRotation(nRotation); - bool bUseCharAttribs = bool(aStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); + bool bUseCharAttribs = bool(maStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); GetEditDoc().CreateDefFont( bUseCharAttribs ); if ( IsFormatted() ) { @@ -2631,8 +2926,14 @@ void ImpEditEngine::SetRotation(TextRotation nRotation) void ImpEditEngine::SetTextColumns(sal_Int16 nColumns, sal_Int32 nSpacing) { + assert(nColumns >= 1); if (mnColumns != nColumns || mnColumnSpacing != nSpacing) { + if (nColumns == 0) + { + SAL_WARN("editeng", "bad nColumns value, ignoring"); + nColumns = 1; + } mnColumns = nColumns; mnColumnSpacing = nSpacing; if (IsFormatted()) @@ -2713,7 +3014,7 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo /* * Scan through char attributes of pNode */ - if ( aStatus.UseCharAttribs() ) + if (maStatus.UseCharAttribs()) { CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs(); size_t nAttr = 0; @@ -2735,7 +3036,11 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo // #i1550# hard color attrib should win over text color from field if ( pAttrib->Which() == EE_FEATURE_FIELD ) { - EditCharAttrib* pColorAttr = pNode->GetCharAttribs().FindAttrib( EE_CHAR_COLOR, nPos ); + // These Attribs positions come from PaMs, so their interval is right-open and left-closed + // when SeekCursor is called, nPos is incremented by 1. I do not know why... + // probably designed to be a nEndPos, and like in a PaM, it is the position after the actual character. + sal_Int32 nPosActual = nPos > 0 ? nPos - 1 : 0; + EditCharAttrib* pColorAttr = pNode->GetCharAttribs().FindAttribRightOpen( EE_CHAR_COLOR, nPosActual ); if ( pColorAttr ) pColorAttr->SetFont( rFont, pOut ); } @@ -2757,12 +3062,12 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo if ( (rFont.GetKerning() != FontKerning::NONE) && IsKernAsianPunctuation() && ( nScriptTypeI18N == i18n::ScriptType::ASIAN ) ) rFont.SetKerning( rFont.GetKerning() | FontKerning::Asian ); - if ( aStatus.DoNotUseColors() ) + if (maStatus.DoNotUseColors()) { rFont.SetColor( /* rColorItem.GetValue() */ COL_BLACK ); } - if ( aStatus.DoStretch() || ( nRelWidth != 100 ) ) + if (maStatus.DoStretch() || ( nRelWidth != 100 )) { // For the current Output device, because otherwise if RefDev=Printer its looks // ugly on the screen! @@ -2781,24 +3086,29 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo Size aRealSz( aMetric.GetFontSize() ); rFont.SetPropr( 100 ); - if ( aStatus.DoStretch() ) + if (maStatus.DoStretch()) { - if ( nStretchY != 100 ) + if (maScalingParameters.fFontY != 1.0) { - aRealSz.setHeight( aRealSz.Height() * nStretchY ); - aRealSz.setHeight( aRealSz.Height() / 100 ); + double fHeightRounded = roundToNearestPt(aRealSz.Height()); + double fNewHeight = fHeightRounded * maScalingParameters.fFontY; + fNewHeight = roundToNearestPt(fNewHeight); + aRealSz.setHeight(basegfx::fround<tools::Long>(fNewHeight)); } - if ( nStretchX != 100 ) + if (maScalingParameters.fFontX != 1.0) { - if ( nStretchX == nStretchY && - nRelWidth == 100 ) + auto fFontX = maScalingParameters.fFontX; + auto fFontY = maScalingParameters.fFontY; + if (fFontX == fFontY && nRelWidth == 100 ) { aRealSz.setWidth( 0 ); } else { - aRealSz.setWidth( aRealSz.Width() * nStretchX ); - aRealSz.setWidth( aRealSz.Width() / 100 ); + double fWidthRounded = roundToNearestPt(aRealSz.Width()); + double fNewWidth = fWidthRounded * fFontX; + fNewWidth = roundToNearestPt(fNewWidth); + aRealSz.setWidth(basegfx::fround<tools::Long>(fNewWidth)); // Also the Kerning: (long due to handle Interim results) tools::Long nKerning = rFont.GetFixKerning(); @@ -2813,17 +3123,15 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo >0 >100 > (Proportional) <0 >100 < (The amount, thus disproportional) */ - if ( ( nKerning < 0 ) && ( nStretchX > 100 ) ) + if (nKerning < 0 && fFontX > 1.0) { // disproportional - nKerning *= 100; - nKerning /= nStretchX; + nKerning = basegfx::fround(nKerning / fFontX); } else if ( nKerning ) { // Proportional - nKerning *= nStretchX; - nKerning /= 100; + nKerning = basegfx::fround(nKerning * fFontX); } rFont.SetFixKerning( static_cast<short>(nKerning) ); } @@ -2865,6 +3173,8 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo ExtTextInputAttr nAttr = mpIMEInfos->pAttribs[ nPos - mpIMEInfos->aPos.GetIndex() - 1 ]; if ( nAttr & ExtTextInputAttr::Underline ) rFont.SetUnderline( LINESTYLE_SINGLE ); + else if ( nAttr & ExtTextInputAttr::DoubleUnderline ) + rFont.SetUnderline( LINESTYLE_DOUBLE ); else if ( nAttr & ExtTextInputAttr::BoldUnderline ) rFont.SetUnderline( LINESTYLE_BOLD ); else if ( nAttr & ExtTextInputAttr::DottedUnderline ) @@ -2898,11 +3208,11 @@ void ImpEditEngine::RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics if ( nPropr != 100 ) { rFont.SetPropr( 100 ); - rFont.SetPhysFont(*pRefDev); + rFont.SetPhysFont(*mpRefDev); } sal_uInt16 nAscent, nDescent; - FontMetric aMetric( pRefDev->GetFontMetric() ); + FontMetric aMetric(mpRefDev->GetFontMetric()); nAscent = static_cast<sal_uInt16>(aMetric.GetAscent()); if ( IsAddExtLeading() ) nAscent = sal::static_int_cast< sal_uInt16 >( @@ -2918,10 +3228,10 @@ void ImpEditEngine::RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics { sal_uInt16 nIntLeading = ( aMetric.GetInternalLeading() > 0 ) ? static_cast<sal_uInt16>(aMetric.GetInternalLeading()) : 0; // Fonts without leading cause problems - if ( ( nIntLeading == 0 ) && ( pRefDev->GetOutDevType() == OUTDEV_PRINTER ) ) + if ( ( nIntLeading == 0 ) && (mpRefDev->GetOutDevType() == OUTDEV_PRINTER)) { // Lets see what Leading one gets on the screen - VclPtr<VirtualDevice> pVDev = GetVirtualDevice( pRefDev->GetMapMode(), pRefDev->GetDrawMode() ); + VclPtr<VirtualDevice> pVDev = GetVirtualDevice(mpRefDev->GetMapMode(), mpRefDev->GetDrawMode()); rFont.SetPhysFont(*pVDev); aMetric = pVDev->GetFontMetric(); @@ -2956,35 +3266,19 @@ void ImpEditEngine::RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics } } -tools::Long ImpEditEngine::getXDirectionAware(const Point& pt) const -{ - if (!IsVertical()) - return pt.X(); - else - return pt.Y(); -} - -tools::Long ImpEditEngine::getYDirectionAware(const Point& pt) const -{ - if (!IsVertical()) - return pt.Y(); - else - return pt.X(); -} - tools::Long ImpEditEngine::getWidthDirectionAware(const Size& sz) const { - return !IsVertical() ? sz.Width() : sz.Height(); + return !IsEffectivelyVertical() ? sz.Width() : sz.Height(); } tools::Long ImpEditEngine::getHeightDirectionAware(const Size& sz) const { - return !IsVertical() ? sz.Height() : sz.Width(); + return !IsEffectivelyVertical() ? sz.Height() : sz.Width(); } void ImpEditEngine::adjustXDirectionAware(Point& pt, tools::Long x) const { - if (!IsVertical()) + if (!IsEffectivelyVertical()) pt.AdjustX(x); else pt.AdjustY(IsTopToBottom() ? x : -x); @@ -2992,33 +3286,33 @@ void ImpEditEngine::adjustXDirectionAware(Point& pt, tools::Long x) const void ImpEditEngine::adjustYDirectionAware(Point& pt, tools::Long y) const { - if (!IsVertical()) + if (!IsEffectivelyVertical()) pt.AdjustY(y); else pt.AdjustX(IsTopToBottom() ? -y : y); } -void ImpEditEngine::setXDirectionAware(Point& pt, tools::Long x) const +void ImpEditEngine::setXDirectionAwareFrom(Point& ptDest, const Point& ptSrc) const { - if (!IsVertical()) - pt.setX(x); + if (!IsEffectivelyVertical()) + ptDest.setX(ptSrc.X()); else - pt.setY(x); + ptDest.setY(ptSrc.Y()); } -void ImpEditEngine::setYDirectionAware(Point& pt, tools::Long y) const +void ImpEditEngine::setYDirectionAwareFrom(Point& ptDest, const Point& ptSrc) const { - if (!IsVertical()) - pt.setY(y); + if (!IsEffectivelyVertical()) + ptDest.setY(ptSrc.Y()); else - pt.setX(y); + ptDest.setX(ptSrc.Y()); } tools::Long ImpEditEngine::getYOverflowDirectionAware(const Point& pt, const tools::Rectangle& rectMax) const { tools::Long nRes; - if (!IsVertical()) + if (!IsEffectivelyVertical()) nRes = pt.Y() - rectMax.Bottom(); else if (IsTopToBottom()) nRes = rectMax.Left() - pt.X(); @@ -3029,7 +3323,7 @@ tools::Long ImpEditEngine::getYOverflowDirectionAware(const Point& pt, bool ImpEditEngine::isXOverflowDirectionAware(const Point& pt, const tools::Rectangle& rectMax) const { - if (!IsVertical()) + if (!IsEffectivelyVertical()) return pt.X() > rectMax.Right(); if (IsTopToBottom()) @@ -3038,55 +3332,33 @@ bool ImpEditEngine::isXOverflowDirectionAware(const Point& pt, const tools::Rect return pt.Y() < rectMax.Top(); } -tools::Long ImpEditEngine::getLeftDirectionAware(const tools::Rectangle& rect) const +tools::Long ImpEditEngine::getBottomDocOffset(const tools::Rectangle& rect) const { - if (!IsVertical()) - return rect.Left(); - - if (IsTopToBottom()) - return rect.Top(); - else + if (!IsEffectivelyVertical()) return rect.Bottom(); -} - -tools::Long ImpEditEngine::getRightDirectionAware(const tools::Rectangle& rect) const -{ - if (!IsVertical()) - return rect.Right(); if (IsTopToBottom()) - return rect.Bottom(); + return -rect.Left(); else - return rect.Top(); -} - -tools::Long ImpEditEngine::getTopDirectionAware(const tools::Rectangle& rect) const -{ - if (!IsVertical()) - return rect.Top(); - - if (IsTopToBottom()) return rect.Right(); - else - return rect.Left(); } -tools::Long ImpEditEngine::getBottomDirectionAware(const tools::Rectangle& rect) const +Size ImpEditEngine::getTopLeftDocOffset(const tools::Rectangle& rect) const { - if (!IsVertical()) - return rect.Bottom(); + if (!IsEffectivelyVertical()) + return { rect.Left(), rect.Top() }; if (IsTopToBottom()) - return rect.Left(); + return { rect.Top(), -rect.Right() }; else - return rect.Right(); + return { -rect.Bottom(), rect.Left() }; } // Returns the resulting shift for the point; allows to apply the same shift to other points Point ImpEditEngine::MoveToNextLine( Point& rMovePos, // [in, out] Point that will move to the next line tools::Long nLineHeight, // [in] Y-direction move distance (direction-aware) - sal_Int32& rColumn, // [in, out] current column number + sal_Int16& rColumn, // [in, out] current column number Point aOrigin, // [in] Origin point to calculate limits and initial Y position in a new column tools::Long* pnHeightNeededToNotWrap // On column wrap, returns how much more height is needed ) const @@ -3096,14 +3368,13 @@ Point ImpEditEngine::MoveToNextLine( // Move the point by the requested distance in Y direction adjustYDirectionAware(rMovePos, nLineHeight); // Check if the resulting position has moved beyond the limits, and more columns left. - // The limits are defined by a rectangle starting from aOrigin with width of aPaperSize - // and height of nCurTextHeight - Size aActPaperSize(aPaperSize); - if (IsVertical()) - aActPaperSize.setWidth(nCurTextHeight); - else - aActPaperSize.setHeight(nCurTextHeight); - tools::Long nNeeded = getYOverflowDirectionAware(rMovePos, { aOrigin, aActPaperSize }); + // The limits are defined by a rectangle starting from aOrigin with width of maPaperSize + // and height of mnCurTextHeight + Point aOtherCorner = aOrigin; + adjustXDirectionAware(aOtherCorner, getWidthDirectionAware(maPaperSize)); + adjustYDirectionAware(aOtherCorner, mnCurTextHeight); + tools::Long nNeeded + = getYOverflowDirectionAware(rMovePos, tools::Rectangle::Normalize(aOrigin, aOtherCorner)); if (pnHeightNeededToNotWrap) *pnHeightNeededToNotWrap = nNeeded; if (nNeeded && rColumn < mnColumns) @@ -3114,11 +3385,11 @@ Point ImpEditEngine::MoveToNextLine( if (rColumn < mnColumns) { // Set Y position of the point to that of aOrigin - setYDirectionAware(rMovePos, getYDirectionAware(aOrigin)); + setYDirectionAwareFrom(rMovePos, aOrigin); // Move the point by the requested distance in Y direction adjustYDirectionAware(rMovePos, nLineHeight); // Move the point by the column+spacing distance in X direction - adjustXDirectionAware(rMovePos, GetColumnWidth(aPaperSize) + mnColumnSpacing); + adjustXDirectionAware(rMovePos, GetColumnWidth(maPaperSize) + mnColumnSpacing); } } @@ -3126,10 +3397,9 @@ Point ImpEditEngine::MoveToNextLine( } // TODO: use IterateLineAreas in ImpEditEngine::Paint, to avoid algorithm duplication - void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly, Degree10 nOrientation ) { - if ( !GetUpdateMode() && !bStripOnly ) + if ( !IsUpdateLayout() && !bStripOnly ) return; if ( !IsFormatted() ) @@ -3139,7 +3409,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po tools::Long nFirstVisYPos = - rOutDev.GetMapMode().GetOrigin().Y(); DBG_ASSERT( GetParaPortions().Count(), "No ParaPortion?!" ); - SvxFont aTmpFont( GetParaPortions()[0].GetNode()->GetCharAttribs().GetDefFont() ); + SvxFont aTmpFont = GetParaPortions().getRef(0).GetNode()->GetCharAttribs().GetDefFont(); vcl::PDFExtOutDevData* const pPDFExtOutDevData = dynamic_cast< vcl::PDFExtOutDevData* >( rOutDev.GetExtOutDevData() ); // In the case of rotated text is aStartPos considered TopLeft because @@ -3147,13 +3417,6 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // un-scrolled. // The rectangle is infinite. const Point aOrigin( aStartPos ); - double nCos = 0.0, nSin = 0.0; - if ( nOrientation ) - { - double nRealOrientation = nOrientation.get()*F_PI1800; - nCos = cos( nRealOrientation ); - nSin = sin( nRealOrientation ); - } // #110496# Added some more optional metafile comments. This // change: factored out some duplicated code. @@ -3162,48 +3425,47 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const tools::Long nVertLineSpacing = CalcVertLineSpacing(aStartPos); - sal_Int32 nColumn = 0; + sal_Int16 nColumn = 0; // Over all the paragraphs... - for ( sal_Int32 n = 0; n < GetParaPortions().Count(); n++ ) + for (sal_Int32 nParaPortion = 0; nParaPortion < GetParaPortions().Count(); nParaPortion++) { - const ParaPortion& rPortion = GetParaPortions()[n]; + ParaPortion const& rParaPortion = GetParaPortions().getRef(nParaPortion); // if when typing idle formatting, asynchronous Paint. // Invisible Portions may be invalid. - if ( rPortion.IsVisible() && rPortion.IsInvalid() ) + if (rParaPortion.IsVisible() && rParaPortion.IsInvalid()) return; if ( pPDFExtOutDevData ) - pPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph ); + pPDFExtOutDevData->WrapBeginStructureElement(vcl::PDFWriter::Paragraph); - const tools::Long nParaHeight = rPortion.GetHeight(); - if ( rPortion.IsVisible() && ( - ( !IsVertical() && ( ( aStartPos.Y() + nParaHeight ) > aClipRect.Top() ) ) || - ( IsVertical() && IsTopToBottom() && ( ( aStartPos.X() - nParaHeight ) < aClipRect.Right() ) ) || - ( IsVertical() && !IsTopToBottom() && ( ( aStartPos.X() + nParaHeight ) > aClipRect.Left() ) ) ) ) + const tools::Long nParaHeight = rParaPortion.GetHeight(); + if (rParaPortion.IsVisible() && ( + ( !IsEffectivelyVertical() && ( ( aStartPos.Y() + nParaHeight ) > aClipRect.Top() ) ) || + ( IsEffectivelyVertical() && IsTopToBottom() && ( ( aStartPos.X() - nParaHeight ) < aClipRect.Right() ) ) || + ( IsEffectivelyVertical() && !IsTopToBottom() && ( ( aStartPos.X() + nParaHeight ) > aClipRect.Left() ) ) ) ) { Point aTmpPos; // Over the lines of the paragraph... - const sal_Int32 nLines = rPortion.GetLines().Count(); + const sal_Int32 nLines = rParaPortion.GetLines().Count(); const sal_Int32 nLastLine = nLines-1; bool bEndOfParagraphWritten(false); - adjustYDirectionAware(aStartPos, rPortion.GetFirstLineOffset()); + adjustYDirectionAware(aStartPos, rParaPortion.GetFirstLineOffset()); - const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); + const SvxLineSpacingItem& rLSItem = rParaPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) - ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; bool bPaintBullet (false); for ( sal_Int32 nLine = 0; nLine < nLines; nLine++ ) { - const EditLine* const pLine = &rPortion.GetLines()[nLine]; - assert( pLine && "NULL-Pointer in the line iterator in UpdateViews" ); + EditLine* pLine = &GetParaPortions().getRef(nParaPortion).GetLines()[nLine]; sal_Int32 nIndex = pLine->GetStart(); tools::Long nLineHeight = pLine->GetHeight(); if (nLine != nLastLine) @@ -3213,9 +3475,9 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po adjustXDirectionAware(aTmpPos, pLine->GetStartPosX()); adjustYDirectionAware(aTmpPos, pLine->GetMaxAscent() - nLineHeight); - if ( ( !IsVertical() && ( aStartPos.Y() > aClipRect.Top() ) ) - || ( IsVertical() && IsTopToBottom() && aStartPos.X() < aClipRect.Right() ) - || ( IsVertical() && !IsTopToBottom() && aStartPos.X() > aClipRect.Left() ) ) + if ( ( !IsEffectivelyVertical() && ( aStartPos.Y() > aClipRect.Top() ) ) + || ( IsEffectivelyVertical() && IsTopToBottom() && aStartPos.X() < aClipRect.Right() ) + || ( IsEffectivelyVertical() && !IsTopToBottom() && aStartPos.X() > aClipRect.Left() ) ) { bPaintBullet = false; @@ -3227,10 +3489,10 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po { Point aLineStart(aStartPos); adjustYDirectionAware(aLineStart, -nLineHeight); - GetEditEnginePtr()->PaintingFirstLine(n, aLineStart, aOrigin, nOrientation, rOutDev); + GetEditEnginePtr()->PaintingFirstLine(nParaPortion, aLineStart, aOrigin, nOrientation, rOutDev); // Remember whether a bullet was painted. - const SfxBoolItem& rBulletState = pEditEngine->GetParaAttrib(n, EE_PARA_BULLETSTATE); + const SfxBoolItem& rBulletState = mpEditEngine->GetParaAttrib(nParaPortion, EE_PARA_BULLETSTATE); bPaintBullet = rBulletState.GetValue(); } @@ -3239,15 +3501,24 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po bool bParsingFields = false; std::vector< sal_Int32 >::iterator itSubLines; + tools::Long nFirstPortionXOffset = 0; for ( sal_Int32 nPortion = pLine->GetStartPortion(); nPortion <= pLine->GetEndPortion(); nPortion++ ) { - DBG_ASSERT( rPortion.GetTextPortions().Count(), "Line without Textportion in Paint!" ); - const TextPortion& rTextPortion = rPortion.GetTextPortions()[nPortion]; + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "Line without Textportion in Paint!"); + const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[nPortion]; + + const tools::Long nPortionXOffset = GetPortionXOffset(rParaPortion, *pLine, nPortion); + setXDirectionAwareFrom(aTmpPos, aStartPos); + + if (nPortion == pLine->GetStartPortion()) + nFirstPortionXOffset = nPortionXOffset; + + if (!bParsingFields) + adjustXDirectionAware(aTmpPos, nPortionXOffset); + else + adjustXDirectionAware(aTmpPos, nFirstPortionXOffset); - const tools::Long nPortionXOffset = GetPortionXOffset( &rPortion, pLine, nPortion ); - setXDirectionAware(aTmpPos, getXDirectionAware(aStartPos)); - adjustXDirectionAware(aTmpPos, nPortionXOffset); if (isXOverflowDirectionAware(aTmpPos, aClipRect)) break; // No further output in line necessary @@ -3257,7 +3528,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po case PortionKind::FIELD: case PortionKind::HYPHENATOR: { - SeekCursor( rPortion.GetNode(), nIndex+1, aTmpFont, &rOutDev ); + SeekCursor(rParaPortion.GetNode(), nIndex + 1, aTmpFont, &rOutDev); bool bDrawFrame = false; @@ -3283,7 +3554,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetFillColor( COL_LIGHTGRAY ); aTmpFont.SetTransparent( sal_False ); } - else if ( GetI18NScriptType( EditPaM( pPortion->GetNode(), nIndex+1 ) ) == i18n::ScriptType::COMPLEX ) + else if (GetI18NScriptType(EditPaM(rParaPortion.GetNode(), nIndex + 1)) == i18n::ScriptType::COMPLEX) { aTmpFont.SetFillColor( COL_LIGHTCYAN ); aTmpFont.SetTransparent( sal_False ); @@ -3293,22 +3564,30 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // #114278# Saving both layout mode and language (since I'm // potentially changing both) - rOutDev.Push( PushFlags::TEXTLAYOUTMODE|PushFlags::TEXTLANGUAGE ); - ImplInitLayoutMode(rOutDev, n, nIndex); + rOutDev.Push( vcl::PushFlags::TEXTLAYOUTMODE|vcl::PushFlags::TEXTLANGUAGE ); + ImplInitLayoutMode(rOutDev, nParaPortion, nIndex); ImplInitDigitMode(rOutDev, aTmpFont.GetLanguage()); OUString aText; sal_Int32 nTextStart = 0; sal_Int32 nTextLen = 0; - const tools::Long* pDXArray = nullptr; - std::unique_ptr<tools::Long[]> pTmpDXArray; + std::span<const sal_Int32> pDXArray; + std::span<const sal_Bool> pKashidaArray; + KernArray aTmpDXArray; if ( rTextPortion.GetKind() == PortionKind::TEXT ) { - aText = rPortion.GetNode()->GetString(); + aText = rParaPortion.GetNode()->GetString(); nTextStart = nIndex; nTextLen = rTextPortion.GetLen(); - pDXArray = pLine->GetCharPosArray().data() + (nIndex - pLine->GetStart()); + pDXArray = std::span(pLine->GetCharPosArray().data() + (nIndex - pLine->GetStart()), + pLine->GetCharPosArray().size() - (nIndex - pLine->GetStart())); + + if (!pLine->GetKashidaArray().empty()) + { + pKashidaArray = std::span(pLine->GetKashidaArray().data() + (nIndex - pLine->GetStart()), + pLine->GetKashidaArray().size() - (nIndex - pLine->GetStart())); + } // Paint control characters (#i55716#) /* XXX: Given that there's special handling @@ -3316,7 +3595,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po * (U+200B ZERO WIDTH SPACE and U+2060 WORD * JOINER) it is assumed to be not relevant * for MarkUrlFields(). */ - if ( aStatus.MarkNonUrlFields() ) + if (maStatus.MarkNonUrlFields()) { sal_Int32 nTmpIdx; const sal_Int32 nTmpEnd = nTextStart + rTextPortion.GetLen(); @@ -3329,7 +3608,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if ( 0x200B == cChar || 0x2060 == cChar ) { - tools::Long nHalfBlankWidth = aTmpFont.QuickGetTextSize( &rOutDev, " ", 0, 1 ).Width() / 2; + tools::Long nHalfBlankWidth = aTmpFont.QuickGetTextSize( &rOutDev, + " ", 0, 1, nullptr ).Width() / 2; const tools::Long nAdvanceX = ( nTmpIdx == nTmpEnd ? rTextPortion.GetSize().Width() : @@ -3344,8 +3624,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po adjustXDirectionAware(aBottomRightRectPos, 2 * nHalfBlankWidth); adjustYDirectionAware(aBottomRightRectPos, pLine->GetHeight()); - rOutDev.Push( PushFlags::FILLCOLOR ); - rOutDev.Push( PushFlags::LINECOLOR ); + rOutDev.Push( vcl::PushFlags::FILLCOLOR ); + rOutDev.Push( vcl::PushFlags::LINECOLOR ); rOutDev.SetFillColor( COL_LIGHTGRAY ); rOutDev.SetLineColor( COL_LIGHTGRAY ); @@ -3365,13 +3645,14 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetPropr( 25 ); aTmpFont.SetPhysFont(rOutDev); - const Size aSlashSize = aTmpFont.QuickGetTextSize( &rOutDev, aSlash, 0, 1 ); + const Size aSlashSize = aTmpFont.QuickGetTextSize( &rOutDev, + aSlash, 0, 1, nullptr ); Point aSlashPos( aTmpPos ); const tools::Long nAddX = nHalfBlankWidth - aSlashSize.Width() / 2; - setXDirectionAware(aSlashPos, getXDirectionAware(aTopLeftRectPos)); + setXDirectionAwareFrom(aSlashPos, aTopLeftRectPos); adjustXDirectionAware(aSlashPos, nAddX); - aTmpFont.QuickDrawText( &rOutDev, aSlashPos, aSlash, 0, 1 ); + aTmpFont.QuickDrawText( &rOutDev, aSlashPos, aSlash, 0, 1, {} ); aTmpFont.SetEscapement( nOldEscapement ); aTmpFont.SetPropr( nOldPropr ); @@ -3383,22 +3664,19 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po } else if ( rTextPortion.GetKind() == PortionKind::FIELD ) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); assert( pAttr && "Field not found"); DBG_ASSERT( dynamic_cast< const SvxFieldItem* >( pAttr->GetItem() ) != nullptr, "Field of the wrong type! "); aText = static_cast<const EditCharAttribField*>(pAttr)->GetFieldValue(); nTextStart = 0; nTextLen = aText.getLength(); ExtraPortionInfo *pExtraInfo = rTextPortion.GetExtraInfos(); - // Do not split the Fields into different lines while editing - // With EditView on Overlay bStripOnly is now set for stripping to - // primitives. To stay compatible in EditMode use pActiveView to detect - // when we are in EditMode. For whatever reason URLs are drawn as single - // line in edit mode, originally clipped against edit area (which is no - // longer done in Overlay mode and allows to *read* the URL). - // It would be difficult to change this due to needed adaptations in - // EditEngine (look for lineBreaksList creation) - if( nullptr == pActiveView && bStripOnly && !bParsingFields && pExtraInfo && !pExtraInfo->lineBreaksList.empty() ) + //For historical reasons URLs was drawn as single line in edit mode + //but now we changed it, so it wraps similar as simple text. + //It is not perfect, it still use lineBreaksList, so it won’t seek + //word ends to wrap text there, but it would be difficult to change + //this due to needed adaptations in EditEngine + if (bStripOnly && !bParsingFields && pExtraInfo && !pExtraInfo->lineBreaksList.empty()) { bParsingFields = true; itSubLines = pExtraInfo->lineBreaksList.begin(); @@ -3415,6 +3693,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpPos += MoveToNextLine(aStartPos, nMaxAscent, nColumn, aOrigin); + adjustXDirectionAware(aTmpPos, -pLine->GetNextLinePosXDiff()); } std::vector< sal_Int32 >::iterator curIt = itSubLines; ++itSubLines; @@ -3428,13 +3707,43 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po nTextStart = *curIt; nTextLen = nTextLen - nTextStart; bParsingFields = false; + + if (nLine + 1 < nLines) + { + // tdf#148966 don't paint the line break following a + // multiline field based on a compat flag + OutlinerEditEng* pOutlEditEng{ dynamic_cast<OutlinerEditEng*>(mpEditEngine)}; + int nStartNextLine = rParaPortion.GetLines()[nLine + 1].GetStartPortion(); + const TextPortion& rNextTextPortion = rParaPortion.GetTextPortions()[nStartNextLine]; + if (pOutlEditEng + && pOutlEditEng->GetCompatFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField) + .value_or(false)) + { + if (rNextTextPortion.GetKind() == PortionKind::LINEBREAK) + ++nLine; //ignore the following linebreak + } + else if (mpActiveView && rNextTextPortion.GetKind() == PortionKind::LINEBREAK) + { + // if we are at edit mode, the compat flag does not work + // here we choose to work if compat flag is true, + // this is better for newer documents + nLine++; + } + if (rNextTextPortion.GetKind() != PortionKind::LINEBREAK) + { + nLine++; + pLine = &GetParaPortions().getRef(nParaPortion).GetLines()[nLine]; + } + } } } - pTmpDXArray.reset(new tools::Long[ aText.getLength() ]); - pDXArray = pTmpDXArray.get(); aTmpFont.SetPhysFont(*GetRefDevice()); - aTmpFont.QuickGetTextSize( GetRefDevice(), aText, nTextStart, nTextLen, pTmpDXArray.get() ); + aTmpFont.QuickGetTextSize( GetRefDevice(), aText, nTextStart, nTextLen, + &aTmpDXArray ); + assert(aTmpDXArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aTmpDXArray.get_subunit_array(); + pDXArray = rKernArray; // add a meta file comment if we record to a metafile if( bMetafileValid ) @@ -3458,10 +3767,12 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po nTextLen = aText.getLength(); // crash when accessing 0 pointer in pDXArray - pTmpDXArray.reset(new tools::Long[ aText.getLength() ]); - pDXArray = pTmpDXArray.get(); aTmpFont.SetPhysFont(*GetRefDevice()); - aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.getLength(), pTmpDXArray.get() ); + aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.getLength(), + &aTmpDXArray ); + assert(aTmpDXArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aTmpDXArray.get_subunit_array(); + pDXArray = rKernArray; } tools::Long nTxtWidth = rTextPortion.GetSize().Width(); @@ -3479,7 +3790,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if(GetStatus().DoOnlineSpelling() && rTextPortion.GetLen()) { - WrongList* pWrongs = rPortion.GetNode()->GetWrongList(); + WrongList* pWrongs = rParaPortion.GetNode()->GetWrongList(); if(pWrongs && !pWrongs->empty()) { @@ -3526,7 +3837,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if(PortionKind::FIELD == rTextPortion.GetKind()) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); if(pFieldItem) @@ -3538,7 +3849,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // support for EOC, EOW, EOS TEXT comments. To support that, // the locale is needed. With the locale and a XBreakIterator it is // possible to re-create the text marking info on primitive level - const lang::Locale aLocale(GetLocale(EditPaM(rPortion.GetNode(), nIndex + 1))); + const lang::Locale aLocale(GetLocale(EditPaM(rParaPortion.GetNode(), nIndex + 1))); // create EOL and EOP bools const bool bEndOfLine(nPortion == pLine->GetEndPortion()); @@ -3557,8 +3868,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po ImplCalcDigitLang(aTmpFont.GetLanguage())); // StripPortions() data callback - GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray, - aTmpFont, n, rTextPortion.GetRightToLeftLevel(), + GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray, + aTmpFont, nParaPortion, rTextPortion.GetRightToLeftLevel(), !aWrongSpellVector.empty() ? &aWrongSpellVector : nullptr, pFieldData, bEndOfLine, bEndOfParagraph, // support for EOL/EOP TEXT comments @@ -3586,7 +3897,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetEscapement( 0 ); } - aOutPos = lcl_ImplCalcRotatedPos( aOutPos, aOrigin, nSin, nCos ); + aOrigin.RotateAround(aOutPos, nOrientation); aTmpFont.SetOrientation( aTmpFont.GetOrientation()+nOrientation ); aTmpFont.SetPhysFont(rOutDev); @@ -3595,8 +3906,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // Take only what begins in the visible range: // Important, because of a bug in some graphic cards // when transparent font, output when negative - if ( nOrientation || ( !IsVertical() && ( ( aTmpPos.X() + nTxtWidth ) >= nFirstVisXPos ) ) - || ( IsVertical() && ( ( aTmpPos.Y() + nTxtWidth ) >= nFirstVisYPos ) ) ) + if ( nOrientation || ( !IsEffectivelyVertical() && ( ( aTmpPos.X() + nTxtWidth ) >= nFirstVisXPos ) ) + || ( IsEffectivelyVertical() && ( ( aTmpPos.Y() + nTxtWidth ) >= nFirstVisYPos ) ) ) { if ( nEsc && ( aTmpFont.GetUnderline() != LINESTYLE_NONE ) ) { @@ -3605,20 +3916,20 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // base line of the original font height... // But only if there was something underlined before! bool bSpecialUnderline = false; - EditCharAttrib* pPrev = rPortion.GetNode()->GetCharAttribs().FindAttrib( EE_CHAR_ESCAPEMENT, nIndex ); + EditCharAttrib* pPrev = rParaPortion.GetNode()->GetCharAttribs().FindAttrib( EE_CHAR_ESCAPEMENT, nIndex ); if ( pPrev ) { SvxFont aDummy; // Underscore in front? if ( pPrev->GetStart() ) { - SeekCursor( rPortion.GetNode(), pPrev->GetStart(), aDummy ); + SeekCursor( rParaPortion.GetNode(), pPrev->GetStart(), aDummy ); if ( aDummy.GetUnderline() != LINESTYLE_NONE ) bSpecialUnderline = true; } - if ( !bSpecialUnderline && ( pPrev->GetEnd() < rPortion.GetNode()->Len() ) ) + if ( !bSpecialUnderline && ( pPrev->GetEnd() < rParaPortion.GetNode()->Len() ) ) { - SeekCursor( rPortion.GetNode(), pPrev->GetEnd()+1, aDummy ); + SeekCursor( rParaPortion.GetNode(), pPrev->GetEnd()+1, aDummy ); if ( aDummy.GetUnderline() != LINESTYLE_NONE ) bSpecialUnderline = true; } @@ -3630,11 +3941,14 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetEscapement( 0 ); aTmpFont.SetPropr( 100 ); aTmpFont.SetPhysFont(rOutDev); - OUStringBuffer aBlanks; + OUStringBuffer aBlanks(nTextLen); comphelper::string::padToLength( aBlanks, nTextLen, ' ' ); Point aUnderlinePos( aOutPos ); if ( nOrientation ) - aUnderlinePos = lcl_ImplCalcRotatedPos( aTmpPos, aOrigin, nSin, nCos ); + { + aUnderlinePos = aTmpPos; + aOrigin.RotateAround(aUnderlinePos, nOrientation); + } rOutDev.DrawStretchText( aUnderlinePos, aSz.Width(), aBlanks.makeStringAndClear(), 0, nTextLen ); aTmpFont.SetUnderline( LINESTYLE_NONE ); @@ -3660,47 +3974,63 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po ' ' == aText[nTextStart + nTextLen - 1] ) --nTextLen; + // PDF export: + const SvxFieldData* pFieldData = nullptr; + if (pPDFExtOutDevData) + { + if (rTextPortion.GetKind() == PortionKind::FIELD) + { + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); + if (pFieldItem) + { + pFieldData = pFieldItem->GetField(); + auto pUrlField = dynamic_cast<const SvxURLField*>(pFieldData); + if (pUrlField) + if (pPDFExtOutDevData->GetIsExportTaggedPDF()) + pPDFExtOutDevData->WrapBeginStructureElement(vcl::PDFWriter::Link, "Link"); + } + } + } + // output directly - aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray ); + aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray ); if ( bDrawFrame ) { Point aTopLeft( aTmpPos ); aTopLeft.AdjustY( -(pLine->GetMaxAscent()) ); if ( nOrientation ) - aTopLeft = lcl_ImplCalcRotatedPos( aTopLeft, aOrigin, nSin, nCos ); + aOrigin.RotateAround(aTopLeft, nOrientation); tools::Rectangle aRect( aTopLeft, rTextPortion.GetSize() ); rOutDev.DrawRect( aRect ); } // PDF export: - if ( pPDFExtOutDevData ) + if (pPDFExtOutDevData) { - if ( rTextPortion.GetKind() == PortionKind::FIELD ) + if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFieldData)) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); - const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); - if( pFieldItem ) + Point aTopLeft(aTmpPos); + aTopLeft.AdjustY(-(pLine->GetMaxAscent())); + + tools::Rectangle aRect(aTopLeft, rTextPortion.GetSize()); + vcl::PDFExtOutDevBookmarkEntry aBookmark; + aBookmark.nLinkId = pPDFExtOutDevData->CreateLink(aRect, pUrlField->GetRepresentation()); + aBookmark.aBookmark = pUrlField->GetURL(); + std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); + rBookmarks.push_back(aBookmark); + + if (pPDFExtOutDevData->GetIsExportTaggedPDF()) { - const SvxFieldData* pFieldData = pFieldItem->GetField(); - if ( auto pUrlField = dynamic_cast< const SvxURLField* >( pFieldData ) ) - { - Point aTopLeft( aTmpPos ); - aTopLeft.AdjustY( -(pLine->GetMaxAscent()) ); - - tools::Rectangle aRect( aTopLeft, rTextPortion.GetSize() ); - vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = pPDFExtOutDevData->CreateLink( aRect ); - aBookmark.aBookmark = pUrlField->GetURL(); - std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); - rBookmarks.push_back( aBookmark ); - } + pPDFExtOutDevData->SetStructureAttributeNumerical(vcl::PDFWriter::LinkAnnotation, aBookmark.nLinkId); + pPDFExtOutDevData->EndStructureElement(); } } } } - const WrongList* const pWrongList = rPortion.GetNode()->GetWrongList(); + const WrongList* const pWrongList = rParaPortion.GetNode()->GetWrongList(); if ( GetStatus().DoOnlineSpelling() && pWrongList && !pWrongList->empty() && rTextPortion.GetLen() ) { {//#105750# adjust LinePos for superscript or subscript text @@ -3713,21 +4043,22 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po } Color aOldColor( rOutDev.GetLineColor() ); rOutDev.SetLineColor( GetColorConfig().GetColorValue( svtools::SPELL ).nColor ); - lcl_DrawRedLines( rOutDev, aTmpFont.GetFontSize().Height(), aRedLineTmpPos, static_cast<size_t>(nIndex), static_cast<size_t>(nIndex) + rTextPortion.GetLen(), pDXArray, rPortion.GetNode()->GetWrongList(), nOrientation, aOrigin, IsVertical(), rTextPortion.IsRightToLeft() ); + lcl_DrawRedLines(rOutDev, aTmpFont.GetFontSize().Height(), aRedLineTmpPos, + static_cast<size_t>(nIndex), static_cast<size_t>(nIndex) + rTextPortion.GetLen(), + pDXArray, rParaPortion.GetNode()->GetWrongList(), nOrientation, + aOrigin, IsEffectivelyVertical(), rTextPortion.IsRightToLeft()); rOutDev.SetLineColor( aOldColor ); } } rOutDev.Pop(); - pTmpDXArray.reset(); - if ( rTextPortion.GetKind() == PortionKind::FIELD ) { // add a meta file comment if we record to a metafile if( bMetafileValid ) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); assert( pAttr && "Field not found" ); const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); @@ -3749,12 +4080,12 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po { if ( rTextPortion.GetExtraValue() && ( rTextPortion.GetExtraValue() != ' ' ) ) { - SeekCursor( rPortion.GetNode(), nIndex+1, aTmpFont, &rOutDev ); + SeekCursor(rParaPortion.GetNode(), nIndex+1, aTmpFont, &rOutDev); aTmpFont.SetTransparent( false ); aTmpFont.SetEscapement( 0 ); aTmpFont.SetPhysFont(rOutDev); tools::Long nCharWidth = aTmpFont.QuickGetTextSize( &rOutDev, - OUString(rTextPortion.GetExtraValue()), 0, 1 ).Width(); + OUString(rTextPortion.GetExtraValue()), 0, 1, {} ).Width(); sal_Int32 nChars = 2; if( nCharWidth ) nChars = rTextPortion.GetSize().Width() / nCharWidth; @@ -3763,10 +4094,10 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po else if ( nChars == 2 ) nChars = 3; // looks better - OUStringBuffer aBuf; + OUStringBuffer aBuf(nChars); comphelper::string::padToLength(aBuf, nChars, rTextPortion.GetExtraValue()); OUString aText(aBuf.makeStringAndClear()); - aTmpFont.QuickDrawText( &rOutDev, aTmpPos, aText, 0, aText.getLength() ); + aTmpFont.QuickDrawText( &rOutDev, aTmpPos, aText, 0, aText.getLength(), {} ); rOutDev.DrawStretchText( aTmpPos, rTextPortion.GetSize().Width(), aText ); if ( bStripOnly ) @@ -3782,7 +4113,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po GetEditEnginePtr()->DrawingTab( aTmpPos, rTextPortion.GetSize().Width(), OUString(rTextPortion.GetExtraValue()), - aTmpFont, n, rTextPortion.GetRightToLeftLevel(), + aTmpFont, nParaPortion, rTextPortion.GetRightToLeftLevel(), bEndOfLine, bEndOfParagraph, aOverlineColor, aTextLineColor); } @@ -3799,8 +4130,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const Color aTextLineColor(rOutDev.GetTextLineColor()); GetEditEnginePtr()->DrawingText( - aTmpPos, OUString(), 0, 0, nullptr, - aTmpFont, n, 0, + aTmpPos, OUString(), 0, 0, {}, {}, + aTmpFont, nParaPortion, 0, nullptr, nullptr, bEndOfLine, bEndOfParagraph, @@ -3820,7 +4151,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po } } - if ( ( nLine != nLastLine ) && !aStatus.IsOutliner() ) + if ((nLine != nLastLine ) && !maStatus.IsOutliner()) { adjustYDirectionAware(aStartPos, nSBL); } @@ -3830,10 +4161,10 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po break; } - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { - const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); - tools::Long nUL = GetYValue( rULItem.GetLower() ); + const SvxULSpaceItem& rULItem = rParaPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); adjustYDirectionAware(aStartPos, nUL); } @@ -3848,8 +4179,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const Color aTextLineColor(rOutDev.GetTextLineColor()); GetEditEnginePtr()->DrawingText( - aTmpPos, OUString(), 0, 0, nullptr, - aTmpFont, n, 0, + aTmpPos, OUString(), 0, 0, {}, {}, + aTmpFont, nParaPortion, 0, nullptr, nullptr, false, true, // support for EOL/EOP TEXT comments @@ -3874,7 +4205,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po void ImpEditEngine::Paint( ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice ) { - if ( !GetUpdateMode() || IsInUndo() ) + if ( !IsUpdateLayout() || IsInUndo() ) return; assert( pView && "No View - No Paint!" ); @@ -3886,7 +4217,7 @@ void ImpEditEngine::Paint( ImpEditView* pView, const tools::Rectangle& rRect, Ou OutputDevice& rTarget = pTargetDevice ? *pTargetDevice : *pView->GetWindow()->GetOutDev(); Point aStartPos; - if ( !IsVertical() ) + if ( !IsEffectivelyVertical() ) aStartPos = pView->GetOutputArea().TopLeft(); else { @@ -3902,7 +4233,7 @@ void ImpEditEngine::Paint( ImpEditView* pView, const tools::Rectangle& rRect, Ou // the fields usually protrude if > line. // (Not at the top, since there the Doc-width from formatting is already // there) - if ( !IsVertical() && ( pView->GetOutputArea().GetWidth() > GetPaperSize().Width() ) ) + if ( !IsEffectivelyVertical() && ( pView->GetOutputArea().GetWidth() > GetPaperSize().Width() ) ) { tools::Long nMaxX = pView->GetOutputArea().Left() + GetPaperSize().Width(); if ( aClipRect.Left() > nMaxX ) @@ -3925,19 +4256,21 @@ void ImpEditEngine::Paint( ImpEditView* pView, const tools::Rectangle& rRect, Ou pView->DrawSelectionXOR(pView->GetEditSelection(), nullptr, &rTarget); } -void ImpEditEngine::InsertContent( ContentNode* pNode, sal_Int32 nPos ) +void ImpEditEngine::InsertContent(std::unique_ptr<ContentNode> pNode, sal_Int32 nPos ) { DBG_ASSERT( pNode, "NULL-Pointer in InsertContent! " ); DBG_ASSERT( IsInUndo(), "InsertContent only for Undo()!" ); - GetParaPortions().Insert(nPos, ParaPortion( pNode )); - aEditDoc.Insert(nPos, pNode); + + GetParaPortions().Insert(nPos, std::make_unique<ParaPortion>(pNode.get())); + maEditDoc.Insert(nPos, std::move(pNode)); + if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphInserted( nPos ); } EditPaM ImpEditEngine::SplitContent( sal_Int32 nNode, sal_Int32 nSepPos ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Invalid Node in SplitContent" ); DBG_ASSERT( IsInUndo(), "SplitContent only for Undo()!" ); DBG_ASSERT( nSepPos <= pNode->Len(), "Index out of range: SplitContent" ); @@ -3947,16 +4280,17 @@ EditPaM ImpEditEngine::SplitContent( sal_Int32 nNode, sal_Int32 nSepPos ) EditPaM ImpEditEngine::ConnectContents( sal_Int32 nLeftNode, bool bBackward ) { - ContentNode* pLeftNode = aEditDoc.GetObject( nLeftNode ); - ContentNode* pRightNode = aEditDoc.GetObject( nLeftNode+1 ); + ContentNode* pLeftNode = maEditDoc.GetObject( nLeftNode ); + ContentNode* pRightNode = maEditDoc.GetObject( nLeftNode+1 ); DBG_ASSERT( pLeftNode, "Invalid left node in ConnectContents "); DBG_ASSERT( pRightNode, "Invalid right node in ConnectContents "); return ImpConnectParagraphs( pLeftNode, pRightNode, bBackward ); } -void ImpEditEngine::SetUpdateMode( bool bUp, EditView* pCurView, bool bForceUpdate ) +bool ImpEditEngine::SetUpdateLayout( bool bUp, EditView* pCurView, bool bForceUpdate ) { - const bool bChanged = (GetUpdateMode() != bUp); + const bool bPrevUpdateLayout = mbUpdateLayout; + const bool mbChanged = (mbUpdateLayout != bUp); // When switching from true to false, all selections were visible, // => paint over @@ -3964,9 +4298,10 @@ void ImpEditEngine::SetUpdateMode( bool bUp, EditView* pCurView, bool bForceUpda // If !bFormatted, e.g. after SetText, then if UpdateMode=true // formatting is not needed immediately, probably because more text is coming. // At latest it is formatted at a Paint/CalcTextWidth. - bUpdate = bUp; - if ( bUpdate && ( bChanged || bForceUpdate ) ) - FormatAndUpdate( pCurView ); + mbUpdateLayout = bUp; + if ( mbUpdateLayout && ( mbChanged || bForceUpdate ) ) + FormatAndLayout( pCurView ); + return bPrevUpdateLayout; } void ImpEditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow ) @@ -3982,13 +4317,13 @@ void ImpEditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow ) { // Mark as deleted, so that no selection will end or begin at // this paragraph... - aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pPPortion->GetNode(), nParagraph )); + maDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pPPortion->GetNode(), nParagraph )); UpdateSelections(); // The region below will not be invalidated if UpdateMode = sal_False! // If anyway, then save as sal_False before SetVisible ! } - if ( bShow && ( pPPortion->IsInvalid() || !pPPortion->nHeight ) ) + if (bShow && (pPPortion->IsInvalid() || !pPPortion->GetHeight())) { if ( !GetTextRanger() ) { @@ -3998,21 +4333,21 @@ void ImpEditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow ) } else { - CalcHeight( pPPortion ); + CalcHeight(*pPPortion); } - nCurTextHeight += pPPortion->GetHeight(); + mnCurTextHeight += pPPortion->GetHeight(); } else { - nCurTextHeight = 0x7fffffff; + mnCurTextHeight = 0x7fffffff; } } pPPortion->SetMustRepaint( true ); - if ( GetUpdateMode() && !IsInUndo() && !GetTextRanger() ) + if ( IsUpdateLayout() && !IsInUndo() && !GetTextRanger() ) { - aInvalidRect = tools::Rectangle( Point( 0, GetParaPortions().GetYOffset( pPPortion ) ), - Point( GetPaperSize().Width(), nCurTextHeight ) ); + maInvalidRect = tools::Rectangle( Point( 0, GetParaPortions().GetYOffset( pPPortion ) ), + Point( GetPaperSize().Width(), mnCurTextHeight ) ); UpdateViews( GetActiveView() ); } } @@ -4022,17 +4357,17 @@ EditSelection ImpEditEngine::MoveParagraphs( Range aOldPositions, sal_Int32 nNew DBG_ASSERT( GetParaPortions().Count() != 0, "No paragraphs found: MoveParagraphs" ); if ( GetParaPortions().Count() == 0 ) return EditSelection(); - aOldPositions.Justify(); + aOldPositions.Normalize(); EditSelection aSel( ImpMoveParagraphs( aOldPositions, nNewPos ) ); - if ( nNewPos >= GetParaPortions().Count() ) - nNewPos = GetParaPortions().Count() - 1; + if (nNewPos >= GetParaPortions().Count()) + nNewPos = GetParaPortions().lastIndex(); // Where the paragraph was inserted it has to be properly redrawn: // Where the paragraph was removed it has to be properly redrawn: // ( and correspondingly in between as well...) - if ( pCurView && GetUpdateMode() ) + if ( pCurView && IsUpdateLayout() ) { // in this case one can redraw directly without invalidating the // Portions @@ -4043,11 +4378,11 @@ EditSelection ImpEditEngine::MoveParagraphs( Range aOldPositions, sal_Int32 nNew ParaPortion* pLowerPortion = GetParaPortions().SafeGetObject( nLastPortion ); if (pUpperPortion && pLowerPortion) { - aInvalidRect = tools::Rectangle(); // make empty - aInvalidRect.SetLeft( 0 ); - aInvalidRect.SetRight(GetColumnWidth(aPaperSize)); - aInvalidRect.SetTop( GetParaPortions().GetYOffset( pUpperPortion ) ); - aInvalidRect.SetBottom( GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight() ); + maInvalidRect = tools::Rectangle(); // make empty + maInvalidRect.SetLeft( 0 ); + maInvalidRect.SetRight(GetColumnWidth(maPaperSize)); + maInvalidRect.SetTop( GetParaPortions().GetYOffset( pUpperPortion ) ); + maInvalidRect.SetBottom( GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight() ); UpdateViews( pCurView ); } @@ -4065,17 +4400,18 @@ void ImpEditEngine::InvalidateFromParagraph( sal_Int32 nFirstInvPara ) { // The following paragraphs are not invalidated, since ResetHeight() // => size change => all the following are re-issued anyway. - if ( nFirstInvPara != 0 ) + + if (nFirstInvPara != 0) { - ParaPortion& rTmpPortion = GetParaPortions()[nFirstInvPara-1]; - rTmpPortion.MarkInvalid( rTmpPortion.GetNode()->Len(), 0 ); - rTmpPortion.ResetHeight(); + ParaPortion& rPortion = GetParaPortions().getRef(nFirstInvPara - 1); + rPortion.MarkInvalid(rPortion.GetNode()->Len(), 0); + rPortion.ResetHeight(); } else { - ParaPortion& rTmpPortion = GetParaPortions()[0]; - rTmpPortion.MarkSelectionInvalid( 0 ); - rTmpPortion.ResetHeight(); + ParaPortion& rPortion = GetParaPortions().getRef(0); + rPortion.MarkSelectionInvalid(0); + rPortion.ResetHeight(); } } @@ -4086,41 +4422,45 @@ IMPL_LINK_NOARG(ImpEditEngine, StatusTimerHdl, Timer *, void) void ImpEditEngine::CallStatusHdl() { - if ( aStatusHdlLink.IsSet() && bool(aStatus.GetStatusWord()) ) + if (maStatusHdlLink.IsSet() && bool(maStatus.GetStatusWord())) { // The Status has to be reset before the Call, // since other Flags might be set in the handler... - EditStatus aTmpStatus( aStatus ); - aStatus.Clear(); - aStatusHdlLink.Call( aTmpStatus ); - aStatusTimer.Stop(); // If called by hand... + EditStatus aTmpStatus( maStatus ); + maStatus.Clear(); + maStatusHdlLink.Call( aTmpStatus ); + maStatusTimer.Stop(); // If called by hand... } } ContentNode* ImpEditEngine::GetPrevVisNode( ContentNode const * pCurNode ) { - const ParaPortion& rPortion1 = FindParaPortion( pCurNode ); - const ParaPortion* pPortion2 = GetPrevVisPortion( &rPortion1 ); - if ( pPortion2 ) - return pPortion2->GetNode(); + const ParaPortion* pPortion = FindParaPortion( pCurNode ); + DBG_ASSERT( pPortion, "GetPrevVisibleNode: No matching portion!" ); + pPortion = GetPrevVisPortion( pPortion ); + if ( pPortion ) + return pPortion->GetNode(); return nullptr; } ContentNode* ImpEditEngine::GetNextVisNode( ContentNode const * pCurNode ) { - const ParaPortion& rPortion = FindParaPortion( pCurNode ); - const ParaPortion* pPortion = GetNextVisPortion( &rPortion ); + const ParaPortion* pPortion = FindParaPortion( pCurNode ); + DBG_ASSERT( pPortion, "GetNextVisibleNode: No matching portion!" ); + pPortion = GetNextVisPortion( pPortion ); if ( pPortion ) return pPortion->GetNode(); return nullptr; } -const ParaPortion* ImpEditEngine::GetPrevVisPortion( const ParaPortion* pCurPortion ) const +const ParaPortion* ImpEditEngine::GetPrevVisPortion( const ParaPortion* pCurPortion) const { - sal_Int32 nPara = GetParaPortions().GetPos( pCurPortion ); - const ParaPortion* pPortion = nPara ? &GetParaPortions()[--nPara] : nullptr; - while ( pPortion && !pPortion->IsVisible() ) - pPortion = nPara ? &GetParaPortions()[--nPara] : nullptr; + sal_Int32 nPara = GetParaPortions().GetPos(pCurPortion); + DBG_ASSERT(GetParaPortions().exists(nPara) , "Portion not found: GetPrevVisPortion"); + + const ParaPortion* pPortion = nPara ? GetParaPortions().SafeGetObject(--nPara) : nullptr; + while (pPortion && !pPortion->IsVisible()) + pPortion = nPara ? GetParaPortions().SafeGetObject(--nPara) : nullptr; return pPortion; } @@ -4149,17 +4489,17 @@ tools::Long ImpEditEngine::CalcVertLineSpacing(Point& rStartPos) const // All paragraphs must have the block justification set. return 0; - const ParaPortion* pPortion = &rParaPortions[i]; - nTotalOccupiedHeight += pPortion->GetFirstLineOffset(); + ParaPortion const& rPortion = rParaPortions.getRef(i); + nTotalOccupiedHeight += rPortion.GetFirstLineOffset(); - const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); + const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) - ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; - const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); - tools::Long nUL = GetYValue( rULItem.GetLower() ); + const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); - const EditLineList& rLines = pPortion->GetLines(); + const EditLineList& rLines = rPortion.GetLines(); sal_Int32 nLineCount = rLines.Count(); nTotalLineCount += nLineCount; for (sal_Int32 j = 0; j < nLineCount; ++j) @@ -4172,13 +4512,13 @@ tools::Long ImpEditEngine::CalcVertLineSpacing(Point& rStartPos) const } } - tools::Long nTotalSpace = getHeightDirectionAware(aPaperSize); + tools::Long nTotalSpace = getHeightDirectionAware(maPaperSize); nTotalSpace -= nTotalOccupiedHeight; if (nTotalSpace <= 0 || nTotalLineCount <= 1) return 0; // Shift the text to the right for the asian layout mode. - if (IsVertical()) + if (IsEffectivelyVertical()) adjustYDirectionAware(rStartPos, -nTotalSpace); return nTotalSpace / (nTotalLineCount-1); @@ -4204,30 +4544,32 @@ EditPaM ImpEditEngine::InsertParagraph( sal_Int32 nPara ) return ImpInsertParaBreak( aPaM ); } -std::unique_ptr<EditSelection> ImpEditEngine::SelectParagraph( sal_Int32 nPara ) +std::optional<EditSelection> ImpEditEngine::SelectParagraph( sal_Int32 nPara ) { - std::unique_ptr<EditSelection> pSel; + std::optional<EditSelection> pSel; ContentNode* pNode = GetEditDoc().GetObject( nPara ); SAL_WARN_IF( !pNode, "editeng", "Paragraph does not exist: SelectParagraph" ); if ( pNode ) - pSel.reset(new EditSelection( EditPaM( pNode, 0 ), EditPaM( pNode, pNode->Len() ) )); + pSel.emplace( EditPaM( pNode, 0 ), EditPaM( pNode, pNode->Len() ) ); return pSel; } -void ImpEditEngine::FormatAndUpdate( EditView* pCurView, bool bCalledFromUndo ) +void ImpEditEngine::FormatAndLayout( EditView* pCurView, bool bCalledFromUndo ) { - if ( bDowning ) - return ; + if (mbDowning) + return; if ( IsInUndo() ) - IdleFormatAndUpdate( pCurView ); + IdleFormatAndLayout( pCurView ); else { if (bCalledFromUndo) + { // in order to make bullet points that have had their styles changed, redraw themselves - for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ ) - GetParaPortions()[nPortion].MarkInvalid( 0, 0 ); + for (auto& pParaPortion : GetParaPortions()) + pParaPortion->MarkInvalid(0, 0); + } FormatDoc(); UpdateViews( pCurView ); } @@ -4238,44 +4580,41 @@ void ImpEditEngine::FormatAndUpdate( EditView* pCurView, bool bCalledFromUndo ) void ImpEditEngine::SetFlatMode( bool bFlat ) { - if ( bFlat != aStatus.UseCharAttribs() ) + if ( bFlat != maStatus.UseCharAttribs() ) return; if ( !bFlat ) - aStatus.TurnOnFlags( EEControlBits::USECHARATTRIBS ); + maStatus.TurnOnFlags( EEControlBits::USECHARATTRIBS ); else - aStatus.TurnOffFlags( EEControlBits::USECHARATTRIBS ); + maStatus.TurnOffFlags( EEControlBits::USECHARATTRIBS ); - aEditDoc.CreateDefFont( !bFlat ); + maEditDoc.CreateDefFont( !bFlat ); FormatFullDoc(); UpdateViews(); - if ( pActiveView ) - pActiveView->ShowCursor(); + if (mpActiveView) + mpActiveView->ShowCursor(); } -void ImpEditEngine::SetCharStretching( sal_uInt16 nX, sal_uInt16 nY ) +void ImpEditEngine::setScalingParameters(ScalingParameters const& rScalingParameters) { - bool bChanged; - if ( !IsVertical() ) - { - bChanged = nStretchX!=nX || nStretchY!=nY; - nStretchX = nX; - nStretchY = nY; - } - else + ScalingParameters aNewScalingParameters(rScalingParameters); + + if (IsEffectivelyVertical()) { - bChanged = nStretchX!=nY || nStretchY!=nX; - nStretchX = nY; - nStretchY = nX; + std::swap(aNewScalingParameters.fFontX, aNewScalingParameters.fFontY); + std::swap(aNewScalingParameters.fSpacingX, aNewScalingParameters.fSpacingY); } - if (bChanged && aStatus.DoStretch()) + bool bScalingChanged = maScalingParameters != aNewScalingParameters; + maCustomScalingParameters = maScalingParameters = aNewScalingParameters; + + if (bScalingChanged && maStatus.DoStretch()) { FormatFullDoc(); // (potentially) need everything redrawn - aInvalidRect=tools::Rectangle(0,0,1000000,1000000); - UpdateViews( GetActiveView() ); + maInvalidRect = tools::Rectangle(0, 0, 1000000, 1000000); + UpdateViews(GetActiveView()); } } @@ -4294,7 +4633,7 @@ const SvxNumberFormat* ImpEditEngine::GetNumberFormat( const ContentNode *pNode // object to provide // access to the SvxNumberFormat of the Outliner. // The EditEngine implementation will just return 0. - pRes = pEditEngine->GetNumberFormat( nPara ); + pRes = mpEditEngine->GetNumberFormat( nPara ); } } @@ -4332,23 +4671,21 @@ sal_Int32 ImpEditEngine::GetSpaceBeforeAndMinLabelWidth( const SvxLRSpaceItem& ImpEditEngine::GetLRSpaceItem( ContentNode* pNode ) { - return pNode->GetContentAttribs().GetItem( aStatus.IsOutliner() ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ); + return pNode->GetContentAttribs().GetItem( maStatus.IsOutliner() ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ); } // select a representative text language for the digit type according to the // text numeral setting: -LanguageType ImpEditEngine::ImplCalcDigitLang(LanguageType eCurLang) const +LanguageType ImpEditEngine::ImplCalcDigitLang(LanguageType eCurLang) { - if (utl::ConfigManager::IsFuzzing()) + if (comphelper::IsFuzzing()) return LANGUAGE_ENGLISH_US; // #114278# Also setting up digit language from Svt options // (cannot reliably inherit the outdev's setting) - if( !pCTLOptions ) - pCTLOptions.reset( new SvtCTLOptions ); LanguageType eLang = eCurLang; - const SvtCTLOptions::TextNumerals nCTLTextNumerals = pCTLOptions->GetCTLTextNumerals(); + const SvtCTLOptions::TextNumerals nCTLTextNumerals = SvtCTLOptions::GetCTLTextNumerals(); if ( SvtCTLOptions::NUMERALS_HINDI == nCTLTextNumerals ) eLang = LANGUAGE_ARABIC_SAUDI_ARABIA; @@ -4360,7 +4697,7 @@ LanguageType ImpEditEngine::ImplCalcDigitLang(LanguageType eCurLang) const return eLang; } -OUString ImpEditEngine::convertDigits(const OUString &rString, sal_Int32 nStt, sal_Int32 nLen, LanguageType eDigitLang) +OUString ImpEditEngine::convertDigits(std::u16string_view rString, sal_Int32 nStt, sal_Int32 nLen, LanguageType eDigitLang) { OUStringBuffer aBuf(rString); for (sal_Int32 nIdx = nStt, nEnd = nStt + nLen; nIdx < nEnd; ++nIdx) @@ -4397,24 +4734,24 @@ void ImpEditEngine::ImplInitLayoutMode(OutputDevice& rOutDev, sal_Int32 nPara, s // it also works for issue 55927 } - ComplexTextLayoutFlags nLayoutMode = rOutDev.GetLayoutMode(); + vcl::text::ComplexTextLayoutFlags nLayoutMode = rOutDev.GetLayoutMode(); // We always use the left position for DrawText() - nLayoutMode &= ~ComplexTextLayoutFlags::BiDiRtl; + nLayoutMode &= ~vcl::text::ComplexTextLayoutFlags::BiDiRtl; if ( !bCTL && !bR2L) { // No Bidi checking necessary - nLayoutMode |= ComplexTextLayoutFlags::BiDiStrong; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiStrong; } else { // Bidi checking necessary // Don't use BIDI_STRONG, VCL must do some checks. - nLayoutMode &= ~ComplexTextLayoutFlags::BiDiStrong; + nLayoutMode &= ~vcl::text::ComplexTextLayoutFlags::BiDiStrong; if ( bR2L ) - nLayoutMode |= ComplexTextLayoutFlags::BiDiRtl|ComplexTextLayoutFlags::TextOriginLeft; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl|vcl::text::ComplexTextLayoutFlags::TextOriginLeft; } rOutDev.SetLayoutMode( nLayoutMode ); @@ -4427,42 +4764,56 @@ void ImpEditEngine::ImplInitLayoutMode(OutputDevice& rOutDev, sal_Int32 nPara, s Reference < i18n::XBreakIterator > const & ImpEditEngine::ImplGetBreakIterator() const { - if ( !xBI.is() ) + if (!mxBI.is()) { - Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); - xBI = i18n::BreakIterator::create( xContext ); + uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); + mxBI = i18n::BreakIterator::create(xContext); } - return xBI; + return mxBI; } Reference < i18n::XExtendedInputSequenceChecker > const & ImpEditEngine::ImplGetInputSequenceChecker() const { - if ( !xISC.is() ) + if (!mxISC.is()) { - Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); - xISC = i18n::InputSequenceChecker::create( xContext ); + uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); + mxISC = i18n::InputSequenceChecker::create(xContext); } - return xISC; + return mxISC; } Color ImpEditEngine::GetAutoColor() const { - Color aColor = GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; + Color aColor; - if ( GetBackgroundColor() != COL_AUTO ) + if (comphelper::LibreOfficeKit::isActive() && SfxViewShell::Current()) { - if ( GetBackgroundColor().IsDark() && aColor.IsDark() ) + // Get document background color from current view instead + aColor = SfxViewShell::Current()->GetColorConfigColor(svtools::DOCCOLOR); + if (aColor.IsDark()) aColor = COL_WHITE; - else if ( GetBackgroundColor().IsBright() && aColor.IsBright() ) + else aColor = COL_BLACK; } + else + { + aColor = GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; + + if ( GetBackgroundColor() != COL_AUTO ) + { + if ( GetBackgroundColor().IsDark() && aColor.IsDark() ) + aColor = COL_WHITE; + else if ( GetBackgroundColor().IsBright() && aColor.IsBright() ) + aColor = COL_BLACK; + } + } return aColor; } bool ImpEditEngine::ImplCalcAsianCompression(ContentNode* pNode, TextPortion* pTextPortion, sal_Int32 nStartPos, - tools::Long* pDXArray, sal_uInt16 n100thPercentFromMax, + sal_Int32* pDXArray, sal_uInt16 n100thPercentFromMax, bool bManipulateDXArray) { DBG_ASSERT( GetAsianCompressionMode() != CharCompressType::NONE, "ImplCalcAsianCompression - Why?" ); @@ -4572,7 +4923,7 @@ bool ImpEditEngine::ImplCalcAsianCompression(ContentNode* pNode, if ( bCompressed && ( n100thPercentFromMax == 10000 ) ) pTextPortion->GetExtraInfos()->nWidthFullCompression = nNewPortionWidth; - pTextPortion->GetSize().setWidth( nNewPortionWidth ); + pTextPortion->setWidth(nNewPortionWidth); if ( pTextPortion->GetExtraInfos() && ( n100thPercentFromMax != 10000 ) ) { @@ -4582,21 +4933,21 @@ bool ImpEditEngine::ImplCalcAsianCompression(ContentNode* pNode, nShrink /= 10000; tools::Long nNewWidth = pTextPortion->GetExtraInfos()->nOrgWidth - nShrink; if ( nNewWidth < pTextPortion->GetSize().Width() ) - pTextPortion->GetSize().setWidth( nNewWidth ); + pTextPortion->setWidth(nNewWidth); } } return bCompressed; } -void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* pParaPortion, tools::Long nRemainingWidth ) +void ImpEditEngine::ImplExpandCompressedPortions(EditLine& rLine, ParaPortion& rParaPortion, tools::Long nRemainingWidth) { bool bFoundCompressedPortion = false; tools::Long nCompressed = 0; std::vector<TextPortion*> aCompressedPortions; - sal_Int32 nPortion = pLine->GetEndPortion(); - TextPortion* pTP = &pParaPortion->GetTextPortions()[ nPortion ]; + sal_Int32 nPortion = rLine.GetEndPortion(); + TextPortion* pTP = &rParaPortion.GetTextPortions()[ nPortion ]; while ( pTP && ( pTP->GetKind() == PortionKind::TEXT ) ) { if ( pTP->GetExtraInfos() && pTP->GetExtraInfos()->bCompressed ) @@ -4605,7 +4956,7 @@ void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* nCompressed += pTP->GetExtraInfos()->nOrgWidth - pTP->GetSize().Width(); aCompressedPortions.push_back(pTP); } - pTP = ( nPortion > pLine->GetStartPortion() ) ? &pParaPortion->GetTextPortions()[ --nPortion ] : nullptr; + pTP = ( nPortion > rLine.GetStartPortion() ) ? &rParaPortion.GetTextPortions()[ --nPortion ] : nullptr; } if ( !bFoundCompressedPortion ) @@ -4624,16 +4975,16 @@ void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* { pTP = pTP2; pTP->GetExtraInfos()->bCompressed = false; - pTP->GetSize().setWidth( pTP->GetExtraInfos()->nOrgWidth ); + pTP->setWidth(pTP->GetExtraInfos()->nOrgWidth); if ( nCompressPercent ) { - sal_Int32 nTxtPortion = pParaPortion->GetTextPortions().GetPos( pTP ); - sal_Int32 nTxtPortionStart = pParaPortion->GetTextPortions().GetStartPos( nTxtPortion ); - DBG_ASSERT( nTxtPortionStart >= pLine->GetStart(), "Portion doesn't belong to the line!!!" ); - tools::Long* pDXArray = pLine->GetCharPosArray().data() + (nTxtPortionStart - pLine->GetStart()); + sal_Int32 nTxtPortion = rParaPortion.GetTextPortions().GetPos( pTP ); + sal_Int32 nTxtPortionStart = rParaPortion.GetTextPortions().GetStartPos( nTxtPortion ); + DBG_ASSERT( nTxtPortionStart >= rLine.GetStart(), "Portion doesn't belong to the line!!!" ); + sal_Int32* pDXArray = rLine.GetCharPosArray().data() + (nTxtPortionStart - rLine.GetStart()); if ( pTP->GetExtraInfos()->pOrgDXArray ) memcpy( pDXArray, pTP->GetExtraInfos()->pOrgDXArray.get(), (pTP->GetLen()-1)*sizeof(sal_Int32) ); - ImplCalcAsianCompression( pParaPortion->GetNode(), pTP, nTxtPortionStart, pDXArray, static_cast<sal_uInt16>(nCompressPercent), true ); + ImplCalcAsianCompression( rParaPortion.GetNode(), pTP, nTxtPortionStart, pDXArray, static_cast<sal_uInt16>(nCompressPercent), true ); } } } @@ -4643,15 +4994,16 @@ void ImpEditEngine::ImplUpdateOverflowingParaNum(tools::Long nPaperHeight) tools::Long nY = 0; tools::Long nPH; - for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) { - ParaPortion& rPara = GetParaPortions()[nPara]; - nPH = rPara.GetHeight(); + for (sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++) + { + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); + nPH = rParaPortion.GetHeight(); nY += nPH; - if ( nY > nPaperHeight /*nCurTextHeight*/ ) // found first paragraph overflowing + if ( nY > nPaperHeight /*mnCurTextHeight*/ ) // found first paragraph overflowing { mnOverflowingPara = nPara; SAL_INFO("editeng.chaining", "[CHAINING] Setting first overflowing #Para#: " << nPara); - ImplUpdateOverflowingLineNum( nPaperHeight, nPara, nY-nPH); + ImplUpdateOverflowingLineNum( nPaperHeight, nPara, nY - nPH); return; } } @@ -4661,21 +5013,26 @@ void ImpEditEngine::ImplUpdateOverflowingLineNum(tools::Long nPaperHeight, sal_uInt32 nOverflowingPara, tools::Long nHeightBeforeOverflowingPara) { + if (GetParaPortions().exists(nOverflowingPara)) + return; + tools::Long nY = nHeightBeforeOverflowingPara; tools::Long nLH; - ParaPortion& rPara = GetParaPortions()[nOverflowingPara]; + ParaPortion& rParaPortion = GetParaPortions().getRef(nOverflowingPara); // Like UpdateOverflowingParaNum but for each line in the first // overflowing paragraph. - for ( sal_Int32 nLine = 0; nLine < rPara.GetLines().Count(); nLine++ ) { + for (sal_Int32 nLine = 0; nLine < rParaPortion.GetLines().Count(); nLine++) + { // XXX: We must use a reference here because the copy constructor resets the height - EditLine &aLine = rPara.GetLines()[nLine]; + EditLine &aLine = rParaPortion.GetLines()[nLine]; nLH = aLine.GetHeight(); nY += nLH; // Debugging output - if (nLine == 0) { + if (nLine == 0) + { SAL_INFO("editeng.chaining", "[CHAINING] First line has height " << nLH); } diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index ee199b663855..121259f7e394 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -18,12 +18,10 @@ */ -#include <vcl/svapp.hxx> -#include <vcl/window.hxx> - #include <svl/srchitem.hxx> -#include <editeng/lspcitem.hxx> #include <editeng/adjustitem.hxx> +#include <editeng/cmapitem.hxx> +#include <editeng/lspcitem.hxx> #include <editeng/tstpitem.hxx> #include "eertfpar.hxx" @@ -36,6 +34,7 @@ #include <sal/log.hxx> #include <o3tl/safeint.hxx> #include <osl/diagnose.h> +#include <osl/thread.h> #include <editxml.hxx> @@ -74,6 +73,7 @@ #include <svtools/rtfkeywd.hxx> #include <editeng/edtdlg.hxx> +#include <cstddef> #include <memory> #include <unordered_map> #include <vector> @@ -86,8 +86,7 @@ using namespace ::com::sun::star::linguistic2; EditPaM ImpEditEngine::Read(SvStream& rInput, const OUString& rBaseURL, EETextFormat eFormat, const EditSelection& rSel, SvKeyValueIterator* pHTTPHeaderAttrs) { - bool _bUpdate = GetUpdateMode(); - SetUpdateMode( false ); + bool _bUpdate = SetUpdateLayout( false ); EditPaM aPaM; if ( eFormat == EETextFormat::Text ) aPaM = ReadText( rInput, rSel ); @@ -103,7 +102,7 @@ EditPaM ImpEditEngine::Read(SvStream& rInput, const OUString& rBaseURL, EETextFo } FormatFullDoc(); // perhaps a simple format is enough? - SetUpdateMode( _bUpdate ); + SetUpdateLayout( _bUpdate ); return aPaM; } @@ -118,10 +117,6 @@ EditPaM ImpEditEngine::ReadText( SvStream& rInput, EditSelection aSel ) bool bDone = rInput.ReadByteStringLine( aTmpStr, rInput.GetStreamCharSet() ); while ( bDone ) { - if (aTmpStr.getLength() > MAXCHARSINPARA) - { - aTmpStr = aTmpStr.copy(0, MAXCHARSINPARA); - } aPaM = ImpInsertText( EditSelection( aPaM, aPaM ), aTmpStr ); aPaM = ImpInsertParaBreak( aPaM ); bDone = rInput.ReadByteStringLine( aTmpStr, rInput.GetStreamCharSet() ); @@ -146,17 +141,16 @@ EditPaM ImpEditEngine::ReadRTF( SvStream& rInput, EditSelection aSel ) // The SvRTF parser expects the Which-mapping passed on in the pool, not // dependent on a secondary. - SfxItemPool* pPool = &aEditDoc.GetItemPool(); + SfxItemPool* pPool = &maEditDoc.GetItemPool(); while (pPool->GetSecondaryPool() && pPool->GetName() != "EditEngineItemPool") - { + { pPool = pPool->GetSecondaryPool(); - } DBG_ASSERT(pPool && pPool->GetName() == "EditEngineItemPool", "ReadRTF: no EditEnginePool!"); - EditRTFParserRef xPrsr = new EditRTFParser(rInput, aSel, *pPool, pEditEngine); + EditRTFParserRef xPrsr = new EditRTFParser(rInput, aSel, *pPool, mpEditEngine); SvParserState eState = xPrsr->CallParser(); if ( ( eState != SvParserState::Accepted ) && ( !rInput.GetError() ) ) { @@ -172,7 +166,7 @@ EditPaM ImpEditEngine::ReadHTML( SvStream& rInput, const OUString& rBaseURL, Edi aSel = ImpDeleteSelection( aSel ); EditHTMLParserRef xPrsr = new EditHTMLParser( rInput, rBaseURL, pHTTPHeaderAttrs ); - SvParserState eState = xPrsr->CallParser(pEditEngine, aSel.Max()); + SvParserState eState = xPrsr->CallParser(mpEditEngine, aSel.Max()); if ( ( eState != SvParserState::Accepted ) && ( !rInput.GetError() ) ) { rInput.SetError( EE_READWRITE_WRONGFORMAT ); @@ -209,20 +203,20 @@ ErrCode ImpEditEngine::WriteText( SvStream& rOutput, EditSelection aSel ) bool bRange = aSel.HasRange(); if ( bRange ) { - aSel.Adjust( aEditDoc ); - nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + aSel.Adjust( maEditDoc ); + nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); } else { nStartNode = 0; - nEndNode = aEditDoc.Count()-1; + nEndNode = maEditDoc.Count()-1; } // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Node not found: Search&Replace" ); sal_Int32 nStartPos = 0; @@ -255,7 +249,7 @@ bool ImpEditEngine::WriteItemListAsRTF( ItemList& rLst, SvStream& rOutput, sal_I static void lcl_FindValidAttribs( ItemList& rLst, ContentNode* pNode, sal_Int32 nIndex, sal_uInt16 nScriptType ) { - sal_uInt16 nAttr = 0; + std::size_t nAttr = 0; EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); while ( pAttr && ( pAttr->GetStart() <= nIndex ) ) { @@ -279,31 +273,31 @@ void ImpEditEngine::WriteXML(SvStream& rOutput, const EditSelection& rSel) ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) { - DBG_ASSERT( GetUpdateMode(), "WriteRTF for UpdateMode = sal_False!" ); + assert( IsUpdateLayout() && "WriteRTF for UpdateMode = sal_False!" ); CheckIdleFormatter(); if ( !IsFormatted() ) FormatDoc(); sal_Int32 nStartNode, nEndNode; - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); - nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); // RTF header ... rOutput.WriteChar( '{' ) ; - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RTF ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_RTF ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ANSI ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ANSI ); rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_MS_1252; // Generate and write out Font table ... std::vector<std::unique_ptr<SvxFontItem>> aFontTable; // default font must be up front, so DEF font in RTF - aFontTable.emplace_back( new SvxFontItem( aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO ) ) ); - aFontTable.emplace_back( new SvxFontItem( aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CJK ) ) ); - aFontTable.emplace_back( new SvxFontItem( aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CTL ) ) ); + aFontTable.emplace_back( new SvxFontItem( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( EE_CHAR_FONTINFO ) ) ); + aFontTable.emplace_back( new SvxFontItem( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( EE_CHAR_FONTINFO_CJK ) ) ); + aFontTable.emplace_back( new SvxFontItem( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( EE_CHAR_FONTINFO_CTL ) ) ); for ( sal_uInt16 nScriptType = 0; nScriptType < 3; nScriptType++ ) { sal_uInt16 nWhich = EE_CHAR_FONTINFO; @@ -312,12 +306,14 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) else if ( nScriptType == 2 ) nWhich = EE_CHAR_FONTINFO_CTL; - for (const SfxPoolItem* pItem : aEditDoc.GetItemPool().GetItemSurrogates(nWhich)) + ItemSurrogates aSurrogates; + maEditDoc.GetItemPool().GetItemSurrogates(aSurrogates, nWhich); + for (const SfxPoolItem* pItem : aSurrogates) { SvxFontItem const*const pFontItem = static_cast<const SvxFontItem*>(pItem); bool bAlreadyExist = false; - sal_uLong nTestMax = nScriptType ? aFontTable.size() : 1; - for ( sal_uLong nTest = 0; !bAlreadyExist && ( nTest < nTestMax ); nTest++ ) + size_t nTestMax = nScriptType ? aFontTable.size() : 1; + for ( size_t nTest = 0; !bAlreadyExist && ( nTest < nTestMax ); nTest++ ) { bAlreadyExist = *aFontTable[ nTest ] == *pFontItem; } @@ -328,31 +324,31 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) } rOutput << endl; - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FONTTBL ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_FONTTBL ); for ( std::vector<SvxFontItem*>::size_type j = 0; j < aFontTable.size(); j++ ) { SvxFontItem* pFontItem = aFontTable[ j ].get(); rOutput.WriteChar( '{' ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_F ); - rOutput.WriteUInt32AsString( j ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_F ); + rOutput.WriteNumberAsString( j ); switch ( pFontItem->GetFamily() ) { - case FAMILY_DONTKNOW: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FNIL ); + case FAMILY_DONTKNOW: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FNIL ); break; - case FAMILY_DECORATIVE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FDECOR ); + case FAMILY_DECORATIVE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FDECOR ); break; - case FAMILY_MODERN: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FMODERN ); + case FAMILY_MODERN: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FMODERN ); break; - case FAMILY_ROMAN: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FROMAN ); + case FAMILY_ROMAN: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FROMAN ); break; - case FAMILY_SCRIPT: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FSCRIPT ); + case FAMILY_SCRIPT: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FSCRIPT ); break; - case FAMILY_SWISS: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FSWISS ); + case FAMILY_SWISS: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FSWISS ); break; default: break; } - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FPRQ ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FPRQ ); sal_uInt16 nVal = 0; switch( pFontItem->GetPitch() ) { @@ -361,18 +357,28 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) default: break; } - rOutput.WriteUInt32AsString( nVal ); + rOutput.WriteNumberAsString( nVal ); rtl_TextEncoding eChrSet = pFontItem->GetCharSet(); + // tdf#47679 OpenSymbol is not encoded in Symbol Encoding + // and anyway we always attempt to write as eDestEnc + // of RTL_TEXTENCODING_MS_1252 and pay no attention + // on export what encoding we claim to use for these + // fonts. + if (IsOpenSymbol(pFontItem->GetFamilyName())) + { + SAL_WARN_IF(eChrSet == RTL_TEXTENCODING_SYMBOL, "editeng", "OpenSymbol should not have charset of RTL_TEXTENCODING_SYMBOL in new documents"); + eChrSet = RTL_TEXTENCODING_UTF8; + } DBG_ASSERT( eChrSet != 9, "SystemCharSet?!" ); if( RTL_TEXTENCODING_DONTKNOW == eChrSet ) eChrSet = osl_getThreadTextEncoding(); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FCHARSET ); - rOutput.WriteUInt32AsString( rtl_getBestWindowsCharsetFromTextEncoding( eChrSet ) ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FCHARSET ); + rOutput.WriteNumberAsString( rtl_getBestWindowsCharsetFromTextEncoding( eChrSet ) ); rOutput.WriteChar( ' ' ); RTFOutFuncs::Out_String( rOutput, pFontItem->GetFamilyName(), eDestEnc ); - rOutput.WriteCharPtr( ";}" ); + rOutput.WriteOString( ";}" ); } rOutput.WriteChar( '}' ); rOutput << endl; @@ -381,12 +387,14 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) SvxColorList aColorList; // COL_AUTO should be the default color, always put it first aColorList.emplace_back(COL_AUTO); - SvxColorItem const& rDefault(aEditDoc.GetItemPool().GetDefaultItem(EE_CHAR_COLOR)); + SvxColorItem const& rDefault(maEditDoc.GetItemPool().GetUserOrPoolDefaultItem(EE_CHAR_COLOR)); if (rDefault.GetValue() != COL_AUTO) // is the default always AUTO? { aColorList.push_back(rDefault.GetValue()); } - for (const SfxPoolItem* pItem : aEditDoc.GetItemPool().GetItemSurrogates(EE_CHAR_COLOR)) + ItemSurrogates aSurrogates; + maEditDoc.GetItemPool().GetItemSurrogates(aSurrogates, EE_CHAR_COLOR); + for (const SfxPoolItem* pItem : aSurrogates) { auto pColorItem(dynamic_cast<SvxColorItem const*>(pItem)); if (pColorItem && pColorItem->GetValue() != COL_AUTO) // may be null! @@ -395,18 +403,18 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) } } - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_COLORTBL ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_COLORTBL ); for ( SvxColorList::size_type j = 0; j < aColorList.size(); j++ ) { Color const color = aColorList[j]; if (color != COL_AUTO) // auto is represented by "empty" element { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RED ); - rOutput.WriteUInt32AsString( color.GetRed() ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_GREEN ); - rOutput.WriteUInt32AsString( color.GetGreen() ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_BLUE ); - rOutput.WriteUInt32AsString( color.GetBlue() ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_RED ); + rOutput.WriteNumberAsString( color.GetRed() ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_GREEN ); + rOutput.WriteNumberAsString( color.GetGreen() ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_BLUE ); + rOutput.WriteNumberAsString( color.GetBlue() ); } rOutput.WriteChar( ';' ); } @@ -432,16 +440,16 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) { sal_uInt32 nStyle = 0; - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STYLESHEET ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_STYLESHEET ); for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; pStyle = aSSSIterator->Next() ) { rOutput << endl; - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_S ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_S ); sal_uInt32 nNumber = nStyle + 1; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteNumberAsString( nNumber ); // Attribute, also from Parent! for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ ) @@ -458,9 +466,11 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) { SfxStyleSheet* pParent = static_cast<SfxStyleSheet*>(GetStyleSheetPool()->Find( pStyle->GetParent(), pStyle->GetFamily() )); DBG_ASSERT( pParent, "Parent not found!" ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SBASEDON ); - nNumber = aStyleSheetToIdMap.find(pParent)->second; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SBASEDON ); + auto iter = aStyleSheetToIdMap.find(pParent); + assert(iter != aStyleSheetToIdMap.end()); + nNumber = iter->second; + rOutput.WriteNumberAsString( nNumber ); } // Next Style... (more) @@ -470,14 +480,16 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) pNext = static_cast<SfxStyleSheet*>(GetStyleSheetPool()->Find( pStyle->GetFollow(), pStyle->GetFamily() )); DBG_ASSERT( pNext, "Next not found!" ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SNEXT ); - nNumber = aStyleSheetToIdMap.find(pNext)->second; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SNEXT ); + auto iter = aStyleSheetToIdMap.find(pNext); + assert(iter != aStyleSheetToIdMap.end()); + nNumber = iter->second; + rOutput.WriteNumberAsString( nNumber ); // Name of the template... - rOutput.WriteCharPtr( " " ); + rOutput.WriteOString( " " ); RTFOutFuncs::Out_String( rOutput, pStyle->GetName(), eDestEnc ); - rOutput.WriteCharPtr( ";}" ); + rOutput.WriteOString( ";}" ); nStyle++; } rOutput.WriteChar( '}' ); @@ -486,10 +498,10 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) } // Write the pool defaults in advance ... - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_IGNORE ).WriteCharPtr( "\\EditEnginePoolDefaults" ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_IGNORE ).WriteOString( "\\EditEnginePoolDefaults" ); for ( sal_uInt16 nPoolDefItem = EE_PARA_START; nPoolDefItem <= EE_CHAR_END; nPoolDefItem++) { - const SfxPoolItem& rItem = aEditDoc.GetItemPool().GetDefaultItem( nPoolDefItem ); + const SfxPoolItem& rItem = maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( nPoolDefItem ); WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList ); } rOutput.WriteChar( '}' ) << endl; @@ -497,17 +509,17 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) // DefTab: MapMode aTwpMode( MapUnit::MapTwip ); sal_uInt16 nDefTabTwps = static_cast<sal_uInt16>(GetRefDevice()->LogicToLogic( - Point( aEditDoc.GetDefTab(), 0 ), + Point( maEditDoc.GetDefTab(), 0 ), &GetRefMapMode(), &aTwpMode ).X()); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_DEFTAB ); - rOutput.WriteUInt32AsString( nDefTabTwps ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_DEFTAB ); + rOutput.WriteNumberAsString( nDefTabTwps ); rOutput << endl; // iterate over the paragraphs ... rOutput.WriteChar( '{' ) << endl; for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Node not found: Search&Replace" ); // The paragraph attributes in advance ... @@ -517,9 +529,11 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) if ( pNode->GetStyleSheet() ) { // Number of template - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_S ); - sal_uInt32 nNumber = aStyleSheetToIdMap.find(pNode->GetStyleSheet())->second; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_S ); + auto iter = aStyleSheetToIdMap.find(pNode->GetStyleSheet()); + assert(iter != aStyleSheetToIdMap.end()); + sal_uInt32 nNumber = iter->second; + rOutput.WriteNumberAsString( nNumber ); // All Attribute // Attribute, also from Parent! @@ -548,20 +562,21 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) rOutput.WriteChar( ' ' ); // Separator ItemList aAttribItems; - ParaPortion& rParaPortion = FindParaPortion( pNode ); + ParaPortion* pParaPortion = FindParaPortion( pNode ); + DBG_ASSERT( pParaPortion, "Portion not found: WriteRTF" ); sal_Int32 nIndex = 0; sal_Int32 nStartPos = 0; sal_Int32 nEndPos = pNode->Len(); sal_Int32 nStartPortion = 0; - sal_Int32 nEndPortion = rParaPortion.GetTextPortions().Count() - 1; + sal_Int32 nEndPortion = pParaPortion->GetTextPortions().Count() - 1; bool bFinishPortion = false; sal_Int32 nPortionStart; if ( nNode == nStartNode ) { nStartPos = aSel.Min().GetIndex(); - nStartPortion = rParaPortion.GetTextPortions().FindPortion( nStartPos, nPortionStart ); + nStartPortion = pParaPortion->GetTextPortions().FindPortion( nStartPos, nPortionStart ); if ( nStartPos != 0 ) { aAttribItems.Clear(); @@ -579,14 +594,14 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) if ( nNode == nEndNode ) // can also be == nStart! { nEndPos = aSel.Max().GetIndex(); - nEndPortion = rParaPortion.GetTextPortions().FindPortion( nEndPos, nPortionStart ); + nEndPortion = pParaPortion->GetTextPortions().FindPortion( nEndPos, nPortionStart ); } const EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature(nIndex); // start at 0, so the index is right ... for ( sal_Int32 n = 0; n <= nEndPortion; n++ ) { - const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[n]; + const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[n]; if ( n < nStartPortion ) { nIndex = nIndex + rTextPortion.GetLen(); @@ -639,12 +654,11 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) nIndex = nIndex + rTextPortion.GetLen(); } - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PAR ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PLAIN ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_PAR ).WriteOString( OOO_STRING_SVTOOLS_RTF_PARD ).WriteOString( OOO_STRING_SVTOOLS_RTF_PLAIN ); rOutput << endl; } // RTF-trailer ... - rOutput.WriteCharPtr( "}}" ); // 1xparentheses paragraphs, 1xparentheses RTF document - rOutput.Flush(); + rOutput.WriteOString( "}}" ); // 1xparentheses paragraphs, 1xparentheses RTF document aFontTable.clear(); @@ -662,9 +676,9 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, { const SvxFrameDirectionItem& rWritingMode = static_cast<const SvxFrameDirectionItem&>(rItem); if ( rWritingMode.GetValue() == SvxFrameDirection::Horizontal_RL_TB ) - rOutput.WriteCharPtr( "\\rtlpar" ); + rOutput.WriteOString( "\\rtlpar" ); else - rOutput.WriteCharPtr( "\\ltrpar" ); + rOutput.WriteOString( "\\ltrpar" ); } break; case EE_PARA_OUTLLEVEL: @@ -672,43 +686,43 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, sal_Int32 nLevel = static_cast<const SfxInt16Item&>(rItem).GetValue(); if( nLevel >= 0 ) { - rOutput.WriteCharPtr( "\\level" ); - rOutput.WriteInt32AsString( nLevel ); + rOutput.WriteOString( "\\level" ); + rOutput.WriteNumberAsString( nLevel ); } } break; case EE_PARA_OUTLLRSPACE: case EE_PARA_LRSPACE: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FI ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FI ); sal_Int32 nTxtFirst = static_cast<const SvxLRSpaceItem&>(rItem).GetTextFirstLineOffset(); nTxtFirst = LogicToTwips( nTxtFirst ); - rOutput.WriteInt32AsString( nTxtFirst ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_LI ); + rOutput.WriteNumberAsString( nTxtFirst ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_LI ); sal_uInt32 nTxtLeft = static_cast< sal_uInt32 >(static_cast<const SvxLRSpaceItem&>(rItem).GetTextLeft()); nTxtLeft = static_cast<sal_uInt32>(LogicToTwips( nTxtLeft )); - rOutput.WriteInt32AsString( nTxtLeft ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RI ); + rOutput.WriteNumberAsString( nTxtLeft ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_RI ); sal_uInt32 nTxtRight = static_cast<const SvxLRSpaceItem&>(rItem).GetRight(); nTxtRight = LogicToTwips( nTxtRight); - rOutput.WriteUInt32AsString( nTxtRight ); + rOutput.WriteNumberAsString( nTxtRight ); } break; case EE_PARA_ULSPACE: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SB ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SB ); sal_uInt32 nUpper = static_cast<const SvxULSpaceItem&>(rItem).GetUpper(); nUpper = static_cast<sal_uInt32>(LogicToTwips( nUpper )); - rOutput.WriteUInt32AsString( nUpper ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SA ); + rOutput.WriteNumberAsString( nUpper ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SA ); sal_uInt32 nLower = static_cast<const SvxULSpaceItem&>(rItem).GetLower(); nLower = LogicToTwips( nLower ); - rOutput.WriteUInt32AsString( nLower ); + rOutput.WriteNumberAsString( nLower ); } break; case EE_PARA_SBL: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SL ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SL ); sal_Int32 nVal = static_cast<const SvxLineSpacingItem&>(rItem).GetLineHeight(); char cMult = '0'; if ( static_cast<const SvxLineSpacingItem&>(rItem).GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop ) @@ -720,8 +734,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, nVal /= 100; cMult = '1'; } - rOutput.WriteInt32AsString( nVal ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SLMULT ).WriteChar( cMult ); + rOutput.WriteNumberAsString( nVal ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SLMULT ).WriteChar( cMult ); } break; case EE_PARA_JUST: @@ -729,11 +743,11 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, SvxAdjust eJustification = static_cast<const SvxAdjustItem&>(rItem).GetAdjust(); switch ( eJustification ) { - case SvxAdjust::Center: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QC ); + case SvxAdjust::Center: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_QC ); break; - case SvxAdjust::Right: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QR ); + case SvxAdjust::Right: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_QR ); break; - default: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QL ); + default: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_QL ); break; } } @@ -744,8 +758,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) { const SvxTabStop& rTab = rTabs[i]; - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TX ); - rOutput.WriteInt32AsString( LogicToTwips( rTab.GetTabPos() ) ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_TX ); + rOutput.WriteNumberAsString( LogicToTwips( rTab.GetTabPos() ) ); } } break; @@ -756,8 +770,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, static_cast<SvxColorItem const&>(rItem).GetValue()); assert(iter != rColorList.end()); sal_uInt32 const n = iter - rColorList.begin(); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CF ); - rOutput.WriteUInt32AsString( n ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_CF ); + rOutput.WriteNumberAsString( n ); } break; case EE_CHAR_FONTINFO: @@ -774,20 +788,20 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, } } - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_F ); - rOutput.WriteUInt32AsString( n ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_F ); + rOutput.WriteNumberAsString( n ); } break; case EE_CHAR_FONTHEIGHT: case EE_CHAR_FONTHEIGHT_CJK: case EE_CHAR_FONTHEIGHT_CTL: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FS ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FS ); sal_Int32 nHeight = static_cast<const SvxFontHeightItem&>(rItem).GetHeight(); nHeight = LogicToTwips( nHeight ); // Twips => HalfPoints nHeight /= 10; - rOutput.WriteInt32AsString( nHeight ); + rOutput.WriteNumberAsString( nHeight ); } break; case EE_CHAR_WEIGHT: @@ -797,8 +811,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, FontWeight e = static_cast<const SvxWeightItem&>(rItem).GetWeight(); switch ( e ) { - case WEIGHT_BOLD: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B ); break; - default: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B ).WriteChar( '0' ); break; + case WEIGHT_BOLD: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_B ); break; + default: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_B ).WriteChar( '0' ); break; } } break; @@ -809,10 +823,10 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, FontLineStyle e = static_cast<const SvxUnderlineItem&>(rItem).GetLineStyle(); switch ( e ) { - case LINESTYLE_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ULNONE ); break; - case LINESTYLE_SINGLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL ); break; - case LINESTYLE_DOUBLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ULDB ); break; - case LINESTYLE_DOTTED: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ULD ); break; + case LINESTYLE_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ULNONE ); break; + case LINESTYLE_SINGLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_UL ); break; + case LINESTYLE_DOUBLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ULDB ); break; + case LINESTYLE_DOTTED: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ULD ); break; default: break; } @@ -823,10 +837,10 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, FontLineStyle e = static_cast<const SvxOverlineItem&>(rItem).GetLineStyle(); switch ( e ) { - case LINESTYLE_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OLNONE ); break; - case LINESTYLE_SINGLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OL ); break; - case LINESTYLE_DOUBLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OLDB ); break; - case LINESTYLE_DOTTED: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OLD ); break; + case LINESTYLE_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OLNONE ); break; + case LINESTYLE_SINGLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OL ); break; + case LINESTYLE_DOUBLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OLDB ); break; + case LINESTYLE_DOTTED: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OLD ); break; default: break; } @@ -838,8 +852,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, switch ( e ) { case STRIKEOUT_SINGLE: - case STRIKEOUT_DOUBLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE ); break; - case STRIKEOUT_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE ).WriteChar( '0' ); break; + case STRIKEOUT_DOUBLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_STRIKE ); break; + case STRIKEOUT_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_STRIKE ).WriteChar( '0' ); break; default: break; } @@ -853,8 +867,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, switch ( e ) { case ITALIC_OBLIQUE: - case ITALIC_NORMAL: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I ); break; - case ITALIC_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I ).WriteChar( '0' ); break; + case ITALIC_NORMAL: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_I ); break; + case ITALIC_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_I ).WriteChar( '0' ); break; default: break; } @@ -862,7 +876,7 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, break; case EE_CHAR_OUTLINE: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OUTL ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OUTL ); if ( !static_cast<const SvxContourItem&>(rItem).GetValue() ) rOutput.WriteChar( '0' ); } @@ -871,56 +885,56 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, { FontRelief nRelief = static_cast<const SvxCharReliefItem&>(rItem).GetValue(); if ( nRelief == FontRelief::Embossed ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_EMBO ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_EMBO ); if ( nRelief == FontRelief::Engraved ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_IMPR ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_IMPR ); } break; case EE_CHAR_EMPHASISMARK: { FontEmphasisMark nMark = static_cast<const SvxEmphasisMarkItem&>(rItem).GetEmphasisMark(); if ( nMark == FontEmphasisMark::NONE ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ACCNONE ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ACCNONE ); else if ( nMark == (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove) ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ACCCOMMA ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ACCCOMMA ); else - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ACCDOT ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ACCDOT ); } break; case EE_CHAR_SHADOW: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SHAD ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SHAD ); if ( !static_cast<const SvxShadowedItem&>(rItem).GetValue() ) rOutput.WriteChar( '0' ); } break; case EE_FEATURE_TAB: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TAB ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_TAB ); } break; case EE_FEATURE_LINEBR: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SL ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_LINE ); } break; case EE_CHAR_KERNING: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_EXPNDTW ); - rOutput.WriteInt32AsString( LogicToTwips( + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_EXPNDTW ); + rOutput.WriteNumberAsString( LogicToTwips( static_cast<const SvxKerningItem&>(rItem).GetValue() ) ); } break; case EE_CHAR_PAIRKERNING: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_KERNING ); - rOutput.WriteUInt32AsString( static_cast<const SvxAutoKernItem&>(rItem).GetValue() ? 1 : 0 ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_KERNING ); + rOutput.WriteNumberAsString( static_cast<const SvxAutoKernItem&>(rItem).GetValue() ? 1 : 0 ); } break; case EE_CHAR_ESCAPEMENT: { SvxFont aFont; - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); SeekCursor( pNode, nPos, aFont ); MapMode aPntMode( MapUnit::MapPoint ); tools::Long nFontHeight = GetRefDevice()->LogicToLogic( @@ -951,15 +965,35 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, // SWG: if ( nEsc ) { - rOutput.WriteCharPtr( "{\\*\\updnprop" ).WriteCharPtr( OString::number( - nProp100).getStr() ).WriteChar( '}' ); + rOutput.WriteOString( "{\\*\\updnprop" ).WriteNumberAsString( + nProp100 ).WriteChar( '}' ); } tools::Long nUpDown = nFontHeight * std::abs( nEsc ) / 100; if ( nEsc < 0 ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_DN ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_DN ); else if ( nEsc > 0 ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UP ); - rOutput.WriteOString( OString::number(nUpDown) ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_UP ); + rOutput.WriteNumberAsString(nUpDown); + } + break; + case EE_CHAR_CASEMAP: + { + const SvxCaseMapItem& rCaseMap = static_cast<const SvxCaseMapItem&>(rItem); + switch (rCaseMap.GetValue()) + { + case SvxCaseMap::SmallCaps: + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_SCAPS); + break; + case SvxCaseMap::Uppercase: + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_CAPS); + break; + default: // Something that rtf does not support + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_SCAPS); + rOutput.WriteNumberAsString(0); + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_CAPS); + rOutput.WriteNumberAsString(0); + break; + } } break; } @@ -968,8 +1002,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, std::unique_ptr<EditTextObject> ImpEditEngine::GetEmptyTextObject() { EditSelection aEmptySel; - aEmptySel.Min() = aEditDoc.GetStartPaM(); - aEmptySel.Max() = aEditDoc.GetStartPaM(); + aEmptySel.Min() = maEditDoc.GetStartPaM(); + aEmptySel.Max() = maEditDoc.GetStartPaM(); return CreateTextObject( aEmptySel ); } @@ -977,52 +1011,46 @@ std::unique_ptr<EditTextObject> ImpEditEngine::GetEmptyTextObject() std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject() { EditSelection aCompleteSelection; - aCompleteSelection.Min() = aEditDoc.GetStartPaM(); - aCompleteSelection.Max() = aEditDoc.GetEndPaM(); + aCompleteSelection.Min() = maEditDoc.GetStartPaM(); + aCompleteSelection.Max() = maEditDoc.GetEndPaM(); return CreateTextObject( aCompleteSelection ); } std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject(const EditSelection& rSel) { - return CreateTextObject(rSel, GetEditTextObjectPool(), aStatus.AllowBigObjects(), nBigTextObjectStart); + return CreateTextObject(rSel, GetEditTextObjectPool(), maStatus.AllowBigObjects(), mnBigTextObjectStart); } std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection aSel, SfxItemPool* pPool, bool bAllowBigObjects, sal_Int32 nBigObjectStart ) { - std::unique_ptr<EditTextObject> pTxtObj(new EditTextObject(pPool)); - pTxtObj->SetVertical( GetDirectVertical() ); - pTxtObj->SetRotation( GetRotation() ); - MapUnit eMapUnit = aEditDoc.GetItemPool().GetMetric( DEF_METRIC ); - pTxtObj->mpImpl->SetMetric( static_cast<sal_uInt16>(eMapUnit) ); - if ( pTxtObj->mpImpl->IsOwnerOfPool() ) - pTxtObj->mpImpl->GetPool()->SetDefaultMetric( eMapUnit ); - sal_Int32 nStartNode, nEndNode; sal_Int32 nTextPortions = 0; - aSel.Adjust( aEditDoc ); - nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + aSel.Adjust( maEditDoc ); + nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); bool bOnlyFullParagraphs = !( aSel.Min().GetIndex() || ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() ) ); // Templates are not saved! // (Only the name and family, template itself must be in App!) - pTxtObj->mpImpl->SetScriptType(GetItemScriptType(aSel)); + + const MapUnit eMapUnit = maEditDoc.GetItemPool().GetMetric(DEF_METRIC); + auto pTxtObj(std::make_unique<EditTextObjectImpl>(pPool, eMapUnit, GetVertical(), GetRotation(), + GetItemScriptType(aSel))); // iterate over the paragraphs ... sal_Int32 nNode; for ( nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Node not found: Search&Replace" ); if ( bOnlyFullParagraphs ) { - const ParaPortion& rParaPortion = GetParaPortions()[nNode]; - nTextPortions += rParaPortion.GetTextPortions().Count(); + nTextPortions += GetParaPortions().getRef(nNode).GetTextPortions().Count(); } sal_Int32 nStartPos = 0; @@ -1036,7 +1064,7 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a nEndPos = aSel.Max().GetIndex(); - ContentInfo *pC = pTxtObj->mpImpl->CreateAndInsertContent(); + ContentInfo *pC = pTxtObj->CreateAndInsertContent(); // The paragraph attributes ... pC->GetParaAttribs().Set( pNode->GetContentAttribs().GetItems() ); @@ -1053,15 +1081,16 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a auto& rCAttriblist = pC->GetCharAttribs(); // and the Attribute... - sal_uInt16 nAttr = 0; + std::size_t nAttr = 0; EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); + rCAttriblist.reserve(rCAttriblist.size() + pNode->GetCharAttribs().GetAttribs().size()); while ( pAttr ) { // In a blank paragraph keep the attributes! if ( bEmptyPara || ( ( pAttr->GetEnd() > nStartPos ) && ( pAttr->GetStart() < nEndPos ) ) ) { - XEditAttribute aX = pTxtObj->mpImpl->CreateAttrib(*pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd()); + XEditAttribute aX = pTxtObj->CreateAttrib(*pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd()); // Possibly Correct ... if ( ( nNode == nStartNode ) && ( nStartPos != 0 ) ) { @@ -1074,10 +1103,8 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a if ( aX.GetEnd() > (nEndPos-nStartPos) ) aX.GetEnd() = nEndPos-nStartPos; } - DBG_ASSERT( aX.GetEnd() <= (nEndPos-nStartPos), "CreateBinTextObject: Attribute too long!" ); - if ( !aX.GetLen() && !bEmptyPara ) - pTxtObj->mpImpl->DestroyAttrib(aX); - else + DBG_ASSERT( aX.GetEnd() <= (nEndPos-nStartPos), "CreateTextObject: Attribute too long!" ); + if ( aX.GetLen() || bEmptyPara ) rCAttriblist.push_back(std::move(aX)); } nAttr++; @@ -1092,13 +1119,15 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a // Remember the portions info in case of large text objects: // sleeper set up when Olli paragraphs not hacked! - if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && GetUpdateMode() && ( nTextPortions >= nBigObjectStart ) ) + if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && IsUpdateLayout() && ( nTextPortions >= nBigObjectStart ) ) { - XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), GetColumnWidth(aPaperSize), nStretchX, nStretchY ); - pTxtObj->mpImpl->SetPortionInfo(std::unique_ptr<XParaPortionList>(pXList)); + XParaPortionList* pXList = new XParaPortionList(GetRefDevice(), GetColumnWidth(maPaperSize), + maScalingParameters.fFontX, maScalingParameters.fFontY, + maScalingParameters.fSpacingX, maScalingParameters.fSpacingY); + pTxtObj->SetPortionInfo(std::unique_ptr<XParaPortionList>(pXList)); for ( nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - const ParaPortion& rParaPortion = GetParaPortions()[nNode]; + ParaPortion const& rParaPortion = GetParaPortions().getRef(nNode); XParaPortion* pX = new XParaPortion; pXList->push_back(pX); @@ -1120,17 +1149,16 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a for ( n = 0; n < nCount; n++ ) { const EditLine& rLine = rParaPortion.GetLines()[n]; - EditLine* pNew = rLine.Clone(); - pX->aLines.Append(pNew); + pX->aLines.Append(std::unique_ptr<EditLine>(rLine.Clone())); } #ifdef DBG_UTIL sal_uInt16 nTest; int nTPLen = 0, nTxtLen = 0; - for ( nTest = rParaPortion.GetTextPortions().Count(); nTest; ) + for (nTest = rParaPortion.GetTextPortions().Count(); nTest;) nTPLen += rParaPortion.GetTextPortions()[--nTest].GetLen(); - for ( nTest = rParaPortion.GetLines().Count(); nTest; ) + for (nTest = rParaPortion.GetLines().Count(); nTest; ) nTxtLen += rParaPortion.GetLines()[--nTest].GetLen(); - DBG_ASSERT( ( nTPLen == rParaPortion.GetNode()->Len() ) && ( nTxtLen == rParaPortion.GetNode()->Len() ), "CreateBinTextObject: ParaPortion not completely formatted!" ); + DBG_ASSERT(nTPLen == rParaPortion.GetNode()->Len() && nTxtLen == rParaPortion.GetNode()->Len(), "CreateBinTextObject: ParaPortion not completely formatted!"); #endif } } @@ -1141,27 +1169,27 @@ void ImpEditEngine::SetText( const EditTextObject& rTextObject ) { // Since setting a text object is not undo-able! ResetUndoManager(); - bool _bUpdate = GetUpdateMode(); + bool _bUpdate = IsUpdateLayout(); bool _bUndo = IsUndoEnabled(); SetText( OUString() ); - EditPaM aPaM = aEditDoc.GetStartPaM(); + EditPaM aPaM = maEditDoc.GetStartPaM(); - SetUpdateMode( false ); + SetUpdateLayout( false ); EnableUndo( false ); InsertText( rTextObject, EditSelection( aPaM, aPaM ) ); - SetVertical(rTextObject.GetDirectVertical()); + SetVertical(rTextObject.GetVertical()); SetRotation(rTextObject.GetRotation()); DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "From where comes the Undo in SetText ?!" ); - SetUpdateMode( _bUpdate ); + SetUpdateLayout( _bUpdate ); EnableUndo( _bUndo ); } EditSelection ImpEditEngine::InsertText( const EditTextObject& rTextObject, EditSelection aSel ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); if ( aSel.HasRange() ) aSel = ImpDeleteSelection( aSel ); EditSelection aNewSel = InsertTextObject( rTextObject, aSel.Max() ); @@ -1172,15 +1200,18 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject { // Optimize: No getPos undFindParaportion, instead calculate index! EditSelection aSel( aPaM, aPaM ); - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); bool bUsePortionInfo = false; - XParaPortionList* pPortionInfo = rTextObject.mpImpl->GetPortionInfo(); + const EditTextObjectImpl& rTextObjectImpl = toImpl(rTextObject); + XParaPortionList* pPortionInfo = rTextObjectImpl.GetPortionInfo(); - if ( pPortionInfo && ( static_cast<tools::Long>(pPortionInfo->GetPaperWidth()) == GetColumnWidth(aPaperSize) ) - && ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() ) - && ( pPortionInfo->GetStretchX() == nStretchX ) - && ( pPortionInfo->GetStretchY() == nStretchY ) ) + if (pPortionInfo && ( static_cast<tools::Long>(pPortionInfo->GetPaperWidth()) == GetColumnWidth(maPaperSize)) + && pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() + && pPortionInfo->getFontScaleX() == maScalingParameters.fFontX + && pPortionInfo->getFontScaleY() == maScalingParameters.fFontY + && pPortionInfo->getSpacingScaleX() == maScalingParameters.fSpacingX + && pPortionInfo->getSpacingScaleY() == maScalingParameters.fSpacingY) { if ( (pPortionInfo->GetRefDevPtr() == GetRefDevice()) || (pPortionInfo->RefDevIsVirtual() && GetRefDevice()->IsVirtual()) ) @@ -1189,10 +1220,10 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject bool bConvertMetricOfItems = false; MapUnit eSourceUnit = MapUnit(), eDestUnit = MapUnit(); - if (rTextObject.mpImpl->HasMetric()) + if (rTextObjectImpl.HasMetric()) { - eSourceUnit = static_cast<MapUnit>(rTextObject.mpImpl->GetMetric()); - eDestUnit = aEditDoc.GetItemPool().GetMetric( DEF_METRIC ); + eSourceUnit = rTextObjectImpl.GetMetric(); + eDestUnit = maEditDoc.GetItemPool().GetMetric( DEF_METRIC ); if ( eSourceUnit != eDestUnit ) bConvertMetricOfItems = true; } @@ -1200,20 +1231,21 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject // Before, paragraph count was of type sal_uInt16 so if nContents exceeded // 0xFFFF this wouldn't have worked anyway, given that nPara is used to // number paragraphs and is fearlessly incremented. - sal_Int32 nContents = static_cast<sal_Int32>(rTextObject.mpImpl->GetContents().size()); + sal_Int32 nContents = static_cast<sal_Int32>(rTextObjectImpl.GetContents().size()); SAL_WARN_IF( nContents < 0, "editeng", "ImpEditEngine::InsertTextObject - contents overflow " << nContents); - sal_Int32 nPara = aEditDoc.GetPos( aPaM.GetNode() ); + sal_Int32 nPara = maEditDoc.GetPos( aPaM.GetNode() ); for (sal_Int32 n = 0; n < nContents; ++n, ++nPara) { - const ContentInfo* pC = rTextObject.mpImpl->GetContents()[n].get(); + const ContentInfo* pC = rTextObjectImpl.GetContents()[n].get(); bool bNewContent = aPaM.GetNode()->Len() == 0; const sal_Int32 nStartPos = aPaM.GetIndex(); aPaM = ImpFastInsertText( aPaM, pC->GetText() ); - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); - rPortion.MarkInvalid( nStartPos, pC->GetText().getLength() ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + DBG_ASSERT( pPortion, "Blind Portion in FastInsertText" ); + pPortion->MarkInvalid( nStartPos, pC->GetText().getLength() ); // Character attributes ... bool bAllreadyHasAttribs = aPaM.GetNode()->GetCharAttribs().Count() != 0; @@ -1237,12 +1269,12 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject DBG_ASSERT( rX.GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute too large!" ); EditCharAttrib* pAttr; if ( !bConvertMetricOfItems ) - pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *(rX.GetItem()), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); + pAttr = MakeCharAttrib( maEditDoc.GetItemPool(), *(rX.GetItem()), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); else { std::unique_ptr<SfxPoolItem> pNew(rX.GetItem()->Clone()); ConvertItem( pNew, eSourceUnit, eDestUnit ); - pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *pNew, rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); + pAttr = MakeCharAttrib( maEditDoc.GetItemPool(), *pNew, rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); } DBG_ASSERT( pAttr->GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute does not fit! (1)" ); aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttr ); @@ -1253,7 +1285,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject { DBG_ASSERT( rX.GetEnd()+nStartPos <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute does not fit! (2)" ); // Tabs and other Features can not be inserted through InsertAttrib: - aEditDoc.InsertAttrib( aPaM.GetNode(), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos, *rX.GetItem() ); + maEditDoc.InsertAttrib( aPaM.GetNode(), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos, *rX.GetItem() ); } } } @@ -1261,7 +1293,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject UpdateFields(); // Otherwise, quick format => no attributes! - rPortion.MarkSelectionInvalid( nStartPos ); + pPortion->MarkSelectionInvalid( nStartPos ); } #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG @@ -1281,57 +1313,58 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject SetStyleSheet( nPara, pStyle ); } if ( !bConvertMetricOfItems ) - SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), pC->GetParaAttribs() ); + SetParaAttribs( maEditDoc.GetPos( aPaM.GetNode() ), pC->GetParaAttribs() ); else { SfxItemSet aAttribs( GetEmptyItemSet() ); ConvertAndPutItems( aAttribs, pC->GetParaAttribs(), &eSourceUnit, &eDestUnit ); - SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), aAttribs ); + SetParaAttribs( maEditDoc.GetPos( aPaM.GetNode() ), aAttribs ); } if ( bNewContent && bUsePortionInfo ) { const XParaPortion& rXP = (*pPortionInfo)[n]; - ParaPortion& rParaPortion = GetParaPortions()[ nPara ]; - rParaPortion.nHeight = rXP.nHeight; - rParaPortion.nFirstLineOffset = rXP.nFirstLineOffset; - rParaPortion.bForceRepaint = true; - rParaPortion.SetValid(); // Do not format + ParaPortion* pParaPortion = GetParaPortions().SafeGetObject(nPara); + DBG_ASSERT( pParaPortion, "InsertBinTextObject: ParaPortion?" ); + pParaPortion->mnHeight = rXP.nHeight; + pParaPortion->mnFirstLineOffset = rXP.nFirstLineOffset; + pParaPortion->mbForceRepaint = true; + pParaPortion->SetValid(); // Do not format // The Text Portions - rParaPortion.GetTextPortions().Reset(); + pParaPortion->GetTextPortions().Reset(); sal_uInt16 nCount = rXP.aTextPortions.Count(); for ( sal_uInt16 _n = 0; _n < nCount; _n++ ) { const TextPortion& rTextPortion = rXP.aTextPortions[_n]; TextPortion* pNew = new TextPortion( rTextPortion ); - rParaPortion.GetTextPortions().Insert(_n, pNew); + pParaPortion->GetTextPortions().Append(pNew); } // The lines - rParaPortion.GetLines().Reset(); + pParaPortion->GetLines().Reset(); nCount = rXP.aLines.Count(); for ( sal_uInt16 m = 0; m < nCount; m++ ) { const EditLine& rLine = rXP.aLines[m]; EditLine* pNew = rLine.Clone(); pNew->SetInvalid(); // Paint again! - rParaPortion.GetLines().Insert(m, pNew); + pParaPortion->GetLines().Append(std::unique_ptr<EditLine>(pNew)); } #ifdef DBG_UTIL sal_uInt16 nTest; int nTPLen = 0, nTxtLen = 0; - for ( nTest = rParaPortion.GetTextPortions().Count(); nTest; ) - nTPLen += rParaPortion.GetTextPortions()[--nTest].GetLen(); - for ( nTest = rParaPortion.GetLines().Count(); nTest; ) - nTxtLen += rParaPortion.GetLines()[--nTest].GetLen(); - DBG_ASSERT( ( nTPLen == rParaPortion.GetNode()->Len() ) && ( nTxtLen == rParaPortion.GetNode()->Len() ), "InsertBinTextObject: ParaPortion not completely formatted!" ); + for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; ) + nTPLen += pParaPortion->GetTextPortions()[--nTest].GetLen(); + for ( nTest = pParaPortion->GetLines().Count(); nTest; ) + nTxtLen += pParaPortion->GetLines()[--nTest].GetLen(); + DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "InsertTextObject: ParaPortion not completely formatted!" ); #endif } } if ( !bParaAttribs ) // DefFont is not calculated for FastInsertParagraph { - aPaM.GetNode()->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont(); - if ( aStatus.UseCharAttribs() ) + aPaM.GetNode()->GetCharAttribs().GetDefFont() = maEditDoc.GetDefFont(); + if (maStatus.UseCharAttribs()) aPaM.GetNode()->CreateDefFont(); } @@ -1351,7 +1384,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject } aSel.Max() = aPaM; - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); return aSel; } @@ -1366,7 +1399,7 @@ void ImpEditEngine::GetAllMisspellRanges( std::vector<editeng::MisspellRanges>& if (!pWrongList) continue; - aRanges.emplace_back(i, pWrongList->GetRanges()); + aRanges.emplace_back(i, std::vector(pWrongList->GetRanges())); } aRanges.swap(rRanges); @@ -1383,77 +1416,86 @@ void ImpEditEngine::SetAllMisspellRanges( const std::vector<editeng::MisspellRan pNode->CreateWrongList(); WrongList* pWrongList = pNode->GetWrongList(); - pWrongList->SetRanges(rParaRanges.maRanges); + pWrongList->SetRanges(std::vector(rParaRanges.maRanges)); } } -LanguageType ImpEditEngine::GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos ) const +editeng::LanguageSpan ImpEditEngine::GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos ) const { short nScriptTypeI18N = GetI18NScriptType( rPaM, pEndPos ); // pEndPos will be valid now, pointing to ScriptChange or NodeLen SvtScriptType nScriptType = SvtLanguageOptions::FromI18NToSvtScriptType(nScriptTypeI18N); sal_uInt16 nLangId = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); const SvxLanguageItem* pLangItem = &static_cast<const SvxLanguageItem&>(rPaM.GetNode()->GetContentAttribs().GetItem( nLangId )); const EditCharAttrib* pAttr = rPaM.GetNode()->GetCharAttribs().FindAttrib( nLangId, rPaM.GetIndex() ); + + editeng::LanguageSpan aLang; + if ( pAttr ) + { pLangItem = static_cast<const SvxLanguageItem*>(pAttr->GetItem()); + aLang.nStart = pAttr->GetStart(); + aLang.nEnd = pAttr->GetEnd(); + } if ( pEndPos && pAttr && ( pAttr->GetEnd() < *pEndPos ) ) *pEndPos = pAttr->GetEnd(); - return pLangItem->GetLanguage(); + aLang.nLang = pLangItem->GetLanguage(); + + return aLang; } css::lang::Locale ImpEditEngine::GetLocale( const EditPaM& rPaM ) const { - return LanguageTag( GetLanguage( rPaM ) ).getLocale(); + return LanguageTag( GetLanguage( rPaM ).nLang ).getLocale(); } Reference< XSpellChecker1 > const & ImpEditEngine::GetSpeller() { - if ( !xSpeller.is() ) - xSpeller = LinguMgr::GetSpellChecker(); - return xSpeller; + if (!mxSpeller.is()) + mxSpeller = LinguMgr::GetSpellChecker(); + return mxSpeller; } void ImpEditEngine::CreateSpellInfo( bool bMultipleDocs ) { - if (!pSpellInfo) - pSpellInfo.reset( new SpellInfo ); + if (!mpSpellInfo) + mpSpellInfo.reset(new SpellInfo); else - *pSpellInfo = SpellInfo(); // reset to default values + *mpSpellInfo = SpellInfo(); // reset to default values - pSpellInfo->bMultipleDoc = bMultipleDocs; + mpSpellInfo->bMultipleDoc = bMultipleDocs; // always spell draw objects completely, starting at the top. // (spelling in only a selection or not starting with the top requires // further changes elsewhere to work properly) - pSpellInfo->aSpellStart = EPaM(); - pSpellInfo->aSpellTo = EPaM( EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND ); + mpSpellInfo->aSpellStart = EPaM(); + mpSpellInfo->aSpellTo = EPaM( EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND ); } EESpellState ImpEditEngine::Spell(EditView* pEditView, weld::Widget* pDialogParent, bool bMultipleDoc) { - SAL_WARN_IF( !xSpeller.is(), "editeng", "No Spell checker set!" ); + SAL_WARN_IF(!mxSpeller.is(), "editeng", "No Spell checker set!"); - if ( !xSpeller.is() ) + if (!mxSpeller.is()) return EESpellState::NoSpeller; - aOnlineSpellTimer.Stop(); + maOnlineSpellTimer.Stop(); // In MultipleDoc always from the front / rear ... if ( bMultipleDoc ) { - pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() ); + pEditView->getImpl().SetEditSelection( maEditDoc.GetStartPaM() ); } - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); CreateSpellInfo( bMultipleDoc ); bool bIsStart = false; if ( bMultipleDoc ) bIsStart = true; // Accessible from the front or from behind ... - else if ( CreateEPaM( aEditDoc.GetStartPaM() ) == pSpellInfo->aSpellStart ) + else if ( CreateEPaM( maEditDoc.GetStartPaM() ) == mpSpellInfo->aSpellStart ) bIsStart = true; { @@ -1463,16 +1505,16 @@ EESpellState ImpEditEngine::Spell(EditView* pEditView, weld::Widget* pDialogPare if ( !bMultipleDoc ) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() ) aCurSel.Max().SetIndex( aCurSel.Max().GetNode()->Len() ); aCurSel.Min() = aCurSel.Max(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); } - EESpellState eState = pSpellInfo->eState; - pSpellInfo.reset(); + EESpellState eState = mpSpellInfo->eState; + mpSpellInfo.reset(); return eState; } @@ -1481,11 +1523,11 @@ bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang ) { bool bHasConvTxt = false; - sal_Int32 nParas = pEditEngine->GetParagraphCount(); + sal_Int32 nParas = mpEditEngine->GetParagraphCount(); for (sal_Int32 k = 0; k < nParas; ++k) { std::vector<sal_Int32> aPortions; - pEditEngine->GetPortions( k, aPortions ); + mpEditEngine->GetPortions( k, aPortions ); for ( size_t nPos = 0; nPos < aPortions.size(); ++nPos ) { sal_Int32 nEnd = aPortions[ nPos ]; @@ -1496,8 +1538,8 @@ bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang ) // specified position is evaluated. if (nEnd > nStart) // empty para? ++nStart; - LanguageType nLangFound = pEditEngine->GetLanguage( k, nStart ); -#ifdef DEBUG + LanguageType nLangFound = mpEditEngine->GetLanguage( k, nStart ).nLang; +#if OSL_DEBUG_LEVEL >= 2 lang::Locale aLocale( LanguageTag::convertToLocale( nLangFound ) ); #endif bHasConvTxt = (nSrcLang == nLangFound) || @@ -1505,7 +1547,7 @@ bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang ) editeng::HangulHanjaConversion::IsChinese( nSrcLang )); if (bHasConvTxt) return bHasConvTxt; - } + } } return bHasConvTxt; @@ -1519,15 +1561,15 @@ void ImpEditEngine::Convert( EditView* pEditView, weld::Widget* pDialogParent, // In MultipleDoc always from the front / rear ... if ( bMultipleDoc ) - pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() ); + pEditView->getImpl().SetEditSelection( maEditDoc.GetStartPaM() ); // initialize pConvInfo - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); - aCurSel.Adjust( aEditDoc ); - pConvInfo.reset(new ConvInfo); - pConvInfo->bMultipleDoc = bMultipleDoc; - pConvInfo->aConvStart = CreateEPaM( aCurSel.Min() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); + aCurSel.Adjust( maEditDoc ); + mpConvInfo.reset(new ConvInfo); + mpConvInfo->bMultipleDoc = bMultipleDoc; + mpConvInfo->aConvStart = CreateEPaM( aCurSel.Min() ); // if it is not just a selection and we are about to begin // with the current conversion for the very first time @@ -1545,16 +1587,16 @@ void ImpEditEngine::Convert( EditView* pEditView, weld::Widget* pDialogParent, // not work. Thus since chinese conversion is not interactive we start // at the begin of the paragraph to solve the problem, i.e. have the // TextConversion service get those characters together in the same call. - pConvInfo->aConvStart.nIndex = editeng::HangulHanjaConversion::IsChinese( nSrcLang ) + mpConvInfo->aConvStart.nIndex = editeng::HangulHanjaConversion::IsChinese( nSrcLang ) ? 0 : aWordStartPaM.GetIndex(); } - pConvInfo->aConvContinue = pConvInfo->aConvStart; + mpConvInfo->aConvContinue = mpConvInfo->aConvStart; bool bIsStart = false; if ( bMultipleDoc ) bIsStart = true; // Accessible from the front or from behind ... - else if ( CreateEPaM( aEditDoc.GetStartPaM() ) == pConvInfo->aConvStart ) + else if ( CreateEPaM( maEditDoc.GetStartPaM() ) == mpConvInfo->aConvStart ) bIsStart = true; TextConvWrapper aWrp( pDialogParent, @@ -1584,15 +1626,15 @@ void ImpEditEngine::Convert( EditView* pEditView, weld::Widget* pDialogParent, if ( !bMultipleDoc ) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() ) aCurSel.Max().SetIndex( aCurSel.Max().GetNode()->Len() ); aCurSel.Min() = aCurSel.Max(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); } - pConvInfo.reset(); + mpConvInfo.reset(); } @@ -1601,11 +1643,11 @@ void ImpEditEngine::SetLanguageAndFont( LanguageType nLang, sal_uInt16 nLangWhichId, const vcl::Font *pFont, sal_uInt16 nFontWhichId ) { - ESelection aOldSel = pActiveView->GetSelection(); - pActiveView->SetSelection( rESel ); + ESelection aOldSel = mpActiveView->GetSelection(); + mpActiveView->SetSelection( rESel ); // set new language attribute - SfxItemSet aNewSet( pActiveView->GetEmptyItemSet() ); + SfxItemSet aNewSet(mpActiveView->GetEmptyItemSet()); aNewSet.Put( SvxLanguageItem( nLang, nLangWhichId ) ); // new font to be set? @@ -1623,9 +1665,8 @@ void ImpEditEngine::SetLanguageAndFont( } // apply new attributes - pActiveView->SetAttribs( aNewSet ); - - pActiveView->SetSelection( aOldSel ); + mpActiveView->SetAttribs(aNewSet); + mpActiveView->SetSelection(aOldSel); } @@ -1641,7 +1682,7 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, OUString aRes; LanguageType nResLang = LANGUAGE_NONE; - EditPaM aPos( CreateEditPaM( pConvInfo->aConvContinue ) ); + EditPaM aPos(CreateEditPaM(mpConvInfo->aConvContinue)); EditSelection aCurSel( aPos, aPos ); OUString aWord; @@ -1650,9 +1691,9 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, { // empty paragraph found that needs to have language and font set? if (bAllowImplicitChangesForNotConvertibleText && - pEditEngine->GetText( pConvInfo->aConvContinue.nPara ).isEmpty()) + mpEditEngine->GetText(mpConvInfo->aConvContinue.nPara).isEmpty()) { - sal_Int32 nPara = pConvInfo->aConvContinue.nPara; + sal_Int32 nPara = mpConvInfo->aConvContinue.nPara; ESelection aESel( nPara, 0, nPara, 0 ); // see comment for below same function call SetLanguageAndFont( aESel, @@ -1661,8 +1702,8 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, } - if (pConvInfo->aConvContinue.nPara == pConvInfo->aConvTo.nPara && - pConvInfo->aConvContinue.nIndex >= pConvInfo->aConvTo.nIndex) + if (mpConvInfo->aConvContinue.nPara == mpConvInfo->aConvTo.nPara && + mpConvInfo->aConvContinue.nIndex >= mpConvInfo->aConvTo.nIndex) break; sal_Int32 nAttribStart = -1; @@ -1670,7 +1711,7 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, sal_Int32 nCurPos = -1; EPaM aCurStart = CreateEPaM( aCurSel.Min() ); std::vector<sal_Int32> aPortions; - pEditEngine->GetPortions( aCurStart.nPara, aPortions ); + mpEditEngine->GetPortions(aCurStart.nPara, aPortions); for ( size_t nPos = 0; nPos < aPortions.size(); ++nPos ) { const sal_Int32 nEnd = aPortions[ nPos ]; @@ -1681,8 +1722,8 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, // thus we usually have to add 1 in order to get the language // of the text right to the cursor position const sal_Int32 nLangIdx = nEnd > nStart ? nStart + 1 : nStart; - LanguageType nLangFound = pEditEngine->GetLanguage( aCurStart.nPara, nLangIdx ); -#ifdef DEBUG + LanguageType nLangFound = mpEditEngine->GetLanguage( aCurStart.nPara, nLangIdx ).nLang; +#if OSL_DEBUG_LEVEL >= 2 lang::Locale aLocale( LanguageTag::convertToLocale( nLangFound ) ); #endif bool bLangOk = (nLangFound == nSrcLang) || @@ -1750,26 +1791,26 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, aCurSel.Max().SetIndex( nCurPos ); } - if ( !pConvInfo->bConvToEnd ) + if ( !mpConvInfo->bConvToEnd ) { EPaM aEPaM( CreateEPaM( aCurSel.Min() ) ); - if ( !( aEPaM < pConvInfo->aConvTo ) ) + if ( !( aEPaM < mpConvInfo->aConvTo ) ) break; } // clip selected word to the converted area // (main use when conversion starts/ends **within** a word) - EditPaM aPaM( CreateEditPaM( pConvInfo->aConvStart ) ); - if (pConvInfo->bConvToEnd && + EditPaM aPaM( CreateEditPaM( mpConvInfo->aConvStart ) ); + if (mpConvInfo->bConvToEnd && aCurSel.Min().GetNode() == aPaM.GetNode() && aCurSel.Min().GetIndex() < aPaM.GetIndex()) aCurSel.Min().SetIndex( aPaM.GetIndex() ); - aPaM = CreateEditPaM( pConvInfo->aConvContinue ); + aPaM = CreateEditPaM( mpConvInfo->aConvContinue ); if (aCurSel.Min().GetNode() == aPaM.GetNode() && aCurSel.Min().GetIndex() < aPaM.GetIndex()) aCurSel.Min().SetIndex( aPaM.GetIndex() ); - aPaM = CreateEditPaM( pConvInfo->aConvTo ); - if ((!pConvInfo->bConvToEnd || rConvRange.HasRange())&& + aPaM = CreateEditPaM( mpConvInfo->aConvTo ); + if ((!mpConvInfo->bConvToEnd || rConvRange.HasRange())&& aCurSel.Max().GetNode() == aPaM.GetNode() && aCurSel.Max().GetIndex() > aPaM.GetIndex()) aCurSel.Max().SetIndex( aPaM.GetIndex() ); @@ -1783,12 +1824,12 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, if ( aRes.isEmpty() ) aCurSel = WordRight( aCurSel.Min(), css::i18n::WordType::DICTIONARY_WORD ); - pConvInfo->aConvContinue = CreateEPaM( aCurSel.Max() ); + mpConvInfo->aConvContinue = CreateEPaM( aCurSel.Max() ); } - pEditView->pImpEditView->DrawSelectionXOR(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); rConvTxt = aRes; @@ -1799,10 +1840,10 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) { - DBG_ASSERT( xSpeller.is(), "No spell checker set!" ); + DBG_ASSERT(mxSpeller.is(), "No spell checker set!"); - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 ); - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1 ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); aCurSel.Min() = aCurSel.Max(); Reference< XSpellAlternatives > xSpellAlt; @@ -1812,7 +1853,7 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) // Known (most likely) bug: If SpellToCurrent, the current has to be // corrected at each replacement, otherwise it may not fit exactly in // the end ... - if ( pSpellInfo->bSpellToEnd || pSpellInfo->bMultipleDoc ) + if (mpSpellInfo->bSpellToEnd || mpSpellInfo->bMultipleDoc) { if ( aCurSel.Max().GetNode() == pLastNode ) { @@ -1820,10 +1861,10 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) break; } } - else if ( !pSpellInfo->bSpellToEnd ) + else if (!mpSpellInfo->bSpellToEnd) { EPaM aEPaM( CreateEPaM( aCurSel.Max() ) ); - if ( !( aEPaM < pSpellInfo->aSpellTo ) ) + if (!(aEPaM < mpSpellInfo->aSpellTo)) break; } @@ -1844,20 +1885,20 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) if ( !aWord.isEmpty() ) { - LanguageType eLang = GetLanguage( aCurSel.Max() ); - SvxSpellWrapper::CheckSpellLang( xSpeller, eLang ); - xSpellAlt = xSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); + LanguageType eLang = GetLanguage( aCurSel.Max() ).nLang; + SvxSpellWrapper::CheckSpellLang(mxSpeller, eLang); + xSpellAlt = mxSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); } if ( !xSpellAlt.is() ) aCurSel = WordRight( aCurSel.Min(), css::i18n::WordType::DICTIONARY_WORD ); else - pSpellInfo->eState = EESpellState::ErrorFound; + mpSpellInfo->eState = EESpellState::ErrorFound; } - pEditView->pImpEditView->DrawSelectionXOR(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); return xSpellAlt; } @@ -1893,13 +1934,13 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpFindNextError(EditSelection& r } if ( !aWord.isEmpty() ) - xSpellAlt = xSpeller->spell( aWord, static_cast<sal_uInt16>(GetLanguage( aCurSel.Max() )), aEmptySeq ); + xSpellAlt = mxSpeller->spell( aWord, static_cast<sal_uInt16>(GetLanguage( aCurSel.Max() ).nLang), aEmptySeq ); if ( !xSpellAlt.is() ) aCurSel = WordRight( aCurSel.Min(), css::i18n::WordType::DICTIONARY_WORD ); else { - pSpellInfo->eState = EESpellState::ErrorFound; + mpSpellInfo->eState = EESpellState::ErrorFound; rSelection = aCurSel; } } @@ -1910,18 +1951,18 @@ bool ImpEditEngine::SpellSentence(EditView const & rEditView, svx::SpellPortions& rToFill ) { bool bRet = false; - EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() ); - if(!pSpellInfo) + EditSelection aCurSel( rEditView.getImpl().GetEditSelection() ); + if (!mpSpellInfo) CreateSpellInfo( true ); - pSpellInfo->aCurSentenceStart = aCurSel.Min(); - DBG_ASSERT( xSpeller.is(), "No spell checker set!" ); - pSpellInfo->aLastSpellPortions.clear(); - pSpellInfo->aLastSpellContentSelections.clear(); + mpSpellInfo->aCurSentenceStart = aCurSel.Min(); + DBG_ASSERT(mxSpeller.is(), "No spell checker set!"); + mpSpellInfo->aLastSpellPortions.clear(); + mpSpellInfo->aLastSpellContentSelections.clear(); rToFill.clear(); //if no selection previously exists the range is extended to the end of the object if (!aCurSel.HasRange()) { - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1); aCurSel.Max() = EditPaM(pLastNode, pLastNode->Len()); } // check for next error in aCurSel and set aCurSel to that one if any was found @@ -1960,7 +2001,7 @@ bool ImpEditEngine::SpellSentence(EditView const & rEditView, while( xAlt.is() ); //set the selection to the end of the current sentence - rEditView.pImpEditView->SetEditSelection(aSentencePaM.Max()); + rEditView.getImpl().SetEditSelection(aSentencePaM.Max()); } return bRet; } @@ -1977,14 +2018,14 @@ void ImpEditEngine::AddPortion( svx::SpellPortion aPortion; aPortion.sText = GetSelected( rSel ); - aPortion.eLanguage = GetLanguage( rSel.Min() ); + aPortion.eLanguage = GetLanguage( rSel.Min() ).nLang; aPortion.xAlternatives = xAlt; aPortion.bIsField = bIsField; rToFill.push_back(aPortion); //save the spelled portions for later use - pSpellInfo->aLastSpellPortions.push_back(aPortion); - pSpellInfo->aLastSpellContentSelections.push_back(rSel); + mpSpellInfo->aLastSpellPortions.push_back(aPortion); + mpSpellInfo->aLastSpellContentSelections.push_back(rSel); } // Adds one or more portions of text to the SpellPortions depending on language changes @@ -2011,8 +2052,8 @@ void ImpEditEngine::AddPortionIterated( //iterate over the text to find changes in language //set the mark equal to the point EditPaM aCursor(aStart); - rEditView.pImpEditView->SetEditSelection( aCursor ); - LanguageType eStartLanguage = GetLanguage( aCursor ); + rEditView.getImpl().SetEditSelection( aCursor ); + LanguageType eStartLanguage = GetLanguage( aCursor ).nLang; //search for a field attribute at the beginning - only the end position //of this field is kept to end a portion at that position const EditCharAttrib* pFieldAttr = aCursor.GetNode()->GetCharAttribs(). @@ -2038,7 +2079,7 @@ void ImpEditEngine::AddPortionIterated( if (bIsField) nEndField = _pFieldAttr->GetEnd(); - LanguageType eCurLanguage = GetLanguage( aCursor ); + LanguageType eCurLanguage = GetLanguage( aCursor ).nLang; if(eCurLanguage != eStartLanguage || bIsField || bIsEndField) { eStartLanguage = eCurLanguage; @@ -2063,27 +2104,27 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, // Note: rNewPortions.size() == 0 is valid and happens when the whole // sentence got removed in the dialog - DBG_ASSERT(pSpellInfo, "pSpellInfo not initialized"); - if (!pSpellInfo || pSpellInfo->aLastSpellPortions.empty()) // no portions -> no text to be changed + DBG_ASSERT(mpSpellInfo, "mpSpellInfo not initialized"); + if (!mpSpellInfo || mpSpellInfo->aLastSpellPortions.empty()) // no portions -> no text to be changed return; // get current paragraph length to calculate later on how the sentence length changed, // in order to place the cursor at the end of the sentence again - EditSelection aOldSel( rEditView.pImpEditView->GetEditSelection() ); + EditSelection aOldSel( rEditView.getImpl().GetEditSelection() ); sal_Int32 nOldLen = aOldSel.Max().GetNode()->Len(); UndoActionStart( EDITUNDO_INSERT ); - if(pSpellInfo->aLastSpellPortions.size() == rNewPortions.size()) + if (mpSpellInfo->aLastSpellPortions.size() == rNewPortions.size()) { - DBG_ASSERT( !rNewPortions.empty(), "rNewPortions should not be empty here" ); - DBG_ASSERT( pSpellInfo->aLastSpellPortions.size() == pSpellInfo->aLastSpellContentSelections.size(), - "aLastSpellPortions and aLastSpellContentSelections size mismatch" ); + DBG_ASSERT(!rNewPortions.empty(), "rNewPortions should not be empty here"); + DBG_ASSERT(mpSpellInfo->aLastSpellPortions.size() == mpSpellInfo->aLastSpellContentSelections.size(), + "aLastSpellPortions and aLastSpellContentSelections size mismatch"); //the simple case: the same number of elements on both sides //each changed element has to be applied to the corresponding source element svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end(); - svx::SpellPortions::const_iterator aCurrentOldPortion = pSpellInfo->aLastSpellPortions.end(); - SpellContentSelections::const_iterator aCurrentOldPosition = pSpellInfo->aLastSpellContentSelections.end(); + svx::SpellPortions::const_iterator aCurrentOldPortion = mpSpellInfo->aLastSpellPortions.end(); + SpellContentSelections::const_iterator aCurrentOldPosition = mpSpellInfo->aLastSpellContentSelections.end(); bool bSetToEnd = false; do { @@ -2095,7 +2136,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, if(!bSetToEnd) { bSetToEnd = true; - rEditView.pImpEditView->SetEditSelection( aCurrentOldPosition->Max() ); + rEditView.getImpl().SetEditSelection( aCurrentOldPosition->Max() ); } SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( aCurrentNewPortion->eLanguage ); @@ -2109,7 +2150,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, if(aCurrentNewPortion->sText != aCurrentOldPortion->sText) { //change text and apply language - SfxItemSet aSet( aEditDoc.GetItemPool(), {{nLangWhichId, nLangWhichId}}); + SfxItemSet aSet( maEditDoc.GetItemPool(), nLangWhichId, nLangWhichId ); aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId)); SetAttribs( *aCurrentOldPosition, aSet ); ImpInsertText( *aCurrentOldPosition, aCurrentNewPortion->sText ); @@ -2117,7 +2158,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage) { //apply language - SfxItemSet aSet( aEditDoc.GetItemPool(), {{nLangWhichId, nLangWhichId}}); + SfxItemSet aSet( maEditDoc.GetItemPool(), nLangWhichId, nLangWhichId); aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId)); SetAttribs( *aCurrentOldPosition, aSet ); } @@ -2126,12 +2167,12 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, } else { - DBG_ASSERT( !pSpellInfo->aLastSpellContentSelections.empty(), "aLastSpellContentSelections should not be empty here" ); + DBG_ASSERT( !mpSpellInfo->aLastSpellContentSelections.empty(), "aLastSpellContentSelections should not be empty here" ); //select the complete sentence - SpellContentSelections::const_iterator aCurrentEndPosition = pSpellInfo->aLastSpellContentSelections.end(); + SpellContentSelections::const_iterator aCurrentEndPosition = mpSpellInfo->aLastSpellContentSelections.end(); --aCurrentEndPosition; - SpellContentSelections::const_iterator aCurrentStartPosition = pSpellInfo->aLastSpellContentSelections.begin(); + SpellContentSelections::const_iterator aCurrentStartPosition = mpSpellInfo->aLastSpellContentSelections.begin(); EditSelection aAllSentence(aCurrentStartPosition->Min(), aCurrentEndPosition->Max()); //delete the sentence completely @@ -2140,7 +2181,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, for(const auto& rCurrentNewPortion : rNewPortions) { //set the language attribute - LanguageType eCurLanguage = GetLanguage( aCurrentPaM ); + LanguageType eCurLanguage = GetLanguage( aCurrentPaM ).nLang; if(eCurLanguage != rCurrentNewPortion.eLanguage) { SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( rCurrentNewPortion.eLanguage ); @@ -2151,7 +2192,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, case SvtScriptType::COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; default: break; } - SfxItemSet aSet( aEditDoc.GetItemPool(), {{nLangWhichId, nLangWhichId}}); + SfxItemSet aSet( maEditDoc.GetItemPool(), nLangWhichId, nLangWhichId); aSet.Put(SvxLanguageItem(rCurrentNewPortion.eLanguage, nLangWhichId)); SetAttribs( aCurrentPaM, aSet ); } @@ -2163,27 +2204,28 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, EditPaM aNext; if (bRecheck) - aNext = pSpellInfo->aCurSentenceStart; + aNext = mpSpellInfo->aCurSentenceStart; else { // restore cursor position to the end of the modified sentence. // (This will define the continuation position for spell/grammar checking) // First: check if the sentence/para length changed - const sal_Int32 nDelta = rEditView.pImpEditView->GetEditSelection().Max().GetNode()->Len() - nOldLen; + const sal_Int32 nDelta = rEditView.getImpl().GetEditSelection().Max().GetNode()->Len() - nOldLen; const sal_Int32 nEndOfSentence = aOldSel.Max().GetIndex() + nDelta; aNext = EditPaM( aOldSel.Max().GetNode(), nEndOfSentence ); } - rEditView.pImpEditView->SetEditSelection( aNext ); + rEditView.getImpl().SetEditSelection( aNext ); - FormatAndUpdate(); - aEditDoc.SetModified(true); + if (IsUpdateLayout()) + FormatAndLayout(); + maEditDoc.SetModified(true); } void ImpEditEngine::PutSpellingToSentenceStart( EditView const & rEditView ) { - if( pSpellInfo && !pSpellInfo->aLastSpellContentSelections.empty() ) + if (mpSpellInfo && !mpSpellInfo->aLastSpellContentSelections.empty()) { - rEditView.pImpEditView->SetEditSelection( pSpellInfo->aLastSpellContentSelections.begin()->Min() ); + rEditView.getImpl().SetEditSelection(mpSpellInfo->aLastSpellContentSelections.begin()->Min()); } } @@ -2201,18 +2243,18 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC even out properly with VDev on transitions from wrong => right) */ - if ( !xSpeller.is() ) + if (!mxSpeller.is()) return; EditPaM aCursorPos; - if( pActiveView && !bSpellAtCursorPos ) + if (mpActiveView && !bSpellAtCursorPos) { - aCursorPos = pActiveView->pImpEditView->GetEditSelection().Max(); + aCursorPos = mpActiveView->getImpl().GetEditSelection().Max(); } bool bRestartTimer = false; - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count() - 1 ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count() - 1 ); sal_Int32 nNodes = GetEditDoc().Count(); sal_Int32 nInvalids = 0; Sequence< PropertyValue > aEmptySeq; @@ -2263,7 +2305,7 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC { const sal_Int32 nWStart = aSel.Min().GetIndex(); const sal_Int32 nWEnd = aSel.Max().GetIndex(); - if ( !xSpeller->isValid( aWord, static_cast<sal_uInt16>(GetLanguage( EditPaM( aSel.Min().GetNode(), nWStart+1 ) )), aEmptySeq ) ) + if (!mxSpeller->isValid( aWord, static_cast<sal_uInt16>(GetLanguage( EditPaM( aSel.Min().GetNode(), nWStart+1 ) ).nLang), aEmptySeq)) { // Check if already marked correctly... const sal_Int32 nXEnd = bDottAdded ? nWEnd -1 : nWEnd; @@ -2327,10 +2369,10 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC // Invalidate? if ( nPaintFrom>=0 ) { - aStatus.GetStatusWord() |= EditStatusFlags::WRONGWORDCHANGED; + maStatus.GetStatusWord() |= EditStatusFlags::WRONGWORDCHANGED; CallStatusHdl(); - if (!aEditViews.empty()) + if (!maEditViews.empty()) { // For SimpleRepaint one was painted over a range without // reaching VDEV, but then one would have to intersect, c @@ -2339,35 +2381,35 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC EditPaM aEndPaM( pNode, nPaintTo ); tools::Rectangle aStartCursor( PaMtoEditCursor( aStartPaM ) ); tools::Rectangle aEndCursor( PaMtoEditCursor( aEndPaM ) ); - DBG_ASSERT( aInvalidRect.IsEmpty(), "InvalidRect set!" ); - aInvalidRect.SetLeft( 0 ); - aInvalidRect.SetRight( GetPaperSize().Width() ); - aInvalidRect.SetTop( aStartCursor.Top() ); - aInvalidRect.SetBottom( aEndCursor.Bottom() ); - if ( pActiveView && pActiveView->HasSelection() ) + DBG_ASSERT(maInvalidRect.IsEmpty(), "InvalidRect set!"); + maInvalidRect.SetLeft( 0 ); + maInvalidRect.SetRight( GetPaperSize().Width() ); + maInvalidRect.SetTop( aStartCursor.Top() ); + maInvalidRect.SetBottom( aEndCursor.Bottom() ); + if (mpActiveView && mpActiveView->HasSelection()) { // Then no output through VDev. UpdateViews(); } else if ( bSimpleRepaint ) { - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - tools::Rectangle aClipRect( aInvalidRect ); + tools::Rectangle aClipRect(maInvalidRect); aClipRect.Intersection( pView->GetVisArea() ); if ( !aClipRect.IsEmpty() ) { // convert to window coordinates... - aClipRect.SetPos( pView->pImpEditView->GetWindowPos( aClipRect.TopLeft() ) ); - pView->pImpEditView->InvalidateAtWindow(aClipRect); + aClipRect.SetPos( pView->getImpl().GetWindowPos( aClipRect.TopLeft() ) ); + pView->getImpl().InvalidateAtWindow(aClipRect); } } } else { - UpdateViews( pActiveView ); + UpdateViews(mpActiveView); } - aInvalidRect = tools::Rectangle(); + maInvalidRect = tools::Rectangle(); } } // After two corrected nodes give up the control... @@ -2383,16 +2425,16 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC break; } if ( bRestartTimer ) - aOnlineSpellTimer.Start(); + maOnlineSpellTimer.Start(); } EESpellState ImpEditEngine::HasSpellErrors() { - DBG_ASSERT( xSpeller.is(), "No spell checker set!" ); + DBG_ASSERT(mxSpeller.is(), "No spell checker set!"); - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count() - 1 ); - EditSelection aCurSel( aEditDoc.GetStartPaM() ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count() - 1 ); + EditSelection aCurSel( maEditDoc.GetStartPaM() ); OUString aWord; Reference< XSpellAlternatives > xSpellAlt; @@ -2409,9 +2451,9 @@ EESpellState ImpEditEngine::HasSpellErrors() aWord = GetSelected( aCurSel ); if ( !aWord.isEmpty() ) { - LanguageType eLang = GetLanguage( aCurSel.Max() ); - SvxSpellWrapper::CheckSpellLang( xSpeller, eLang ); - xSpellAlt = xSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); + LanguageType eLang = GetLanguage( aCurSel.Max() ).nLang; + SvxSpellWrapper::CheckSpellLang(mxSpeller, eLang); + xSpellAlt = mxSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); } aCurSel = WordRight( aCurSel.Max(), css::i18n::WordType::DICTIONARY_WORD ); } @@ -2421,12 +2463,12 @@ EESpellState ImpEditEngine::HasSpellErrors() void ImpEditEngine::ClearSpellErrors() { - aEditDoc.ClearSpellErrors(); + maEditDoc.ClearSpellErrors(); } EESpellState ImpEditEngine::StartThesaurus(EditView* pEditView, weld::Widget* pDialogParent) { - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); if ( !aCurSel.HasRange() ) aCurSel = SelectWord( aCurSel, css::i18n::WordType::DICTIONARY_WORD ); OUString aWord( GetSelected( aCurSel ) ); @@ -2437,13 +2479,13 @@ EESpellState ImpEditEngine::StartThesaurus(EditView* pEditView, weld::Widget* pD EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create(); ScopedVclPtr<AbstractThesaurusDialog> xDlg(pFact->CreateThesaurusDialog(pDialogParent, xThes, - aWord, GetLanguage( aCurSel.Max() ) )); + aWord, GetLanguage( aCurSel.Max() ).nLang )); if (xDlg->Execute() == RET_OK) { // Replace Word... - pEditView->pImpEditView->DrawSelectionXOR(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->InsertText(xDlg->GetWord()); pEditView->ShowCursor(true, false); } @@ -2455,7 +2497,7 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe { sal_Int32 nFound = 0; - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); // FIND_ALL is not possible without multiple selection. if ( ( rSearchItem.GetCommand() == SvxSearchCmd::FIND ) || @@ -2483,10 +2525,10 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe SvxSearchItem aTmpItem( rSearchItem ); aTmpItem.SetBackward( false ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); - aCurSel.Adjust( aEditDoc ); - EditPaM aStartPaM = aTmpItem.GetSelection() ? aCurSel.Min() : aEditDoc.GetStartPaM(); + aCurSel.Adjust( maEditDoc ); + EditPaM aStartPaM = aTmpItem.GetSelection() ? aCurSel.Min() : maEditDoc.GetStartPaM(); EditSelection aFoundSel( aCurSel.Max() ); bool bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel ); if ( bFound ) @@ -2502,13 +2544,13 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe EditPaM aNewPaM( aFoundSel.Max() ); if ( aNewPaM.GetIndex() > aNewPaM.GetNode()->Len() ) aNewPaM.SetIndex( aNewPaM.GetNode()->Len() ); - pEditView->pImpEditView->SetEditSelection( aNewPaM ); - FormatAndUpdate( pEditView ); + pEditView->getImpl().SetEditSelection( aNewPaM ); + FormatAndLayout( pEditView ); UndoActionEnd(); } else { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); } } @@ -2517,8 +2559,8 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe bool ImpEditEngine::Search( const SvxSearchItem& rSearchItem, EditView* pEditView ) { - EditSelection aSel( pEditView->pImpEditView->GetEditSelection() ); - aSel.Adjust( aEditDoc ); + EditSelection aSel( pEditView->getImpl().GetEditSelection() ); + aSel.Adjust( maEditDoc ); EditPaM aStartPaM( aSel.Max() ); if ( rSearchItem.GetSelection() && !rSearchItem.GetBackward() ) aStartPaM = aSel.Min(); @@ -2531,18 +2573,18 @@ bool ImpEditEngine::Search( const SvxSearchItem& rSearchItem, EditView* pEditVie bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel ); } - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( bFound ) { // First, set the minimum, so the whole word is in the visible range. - pEditView->pImpEditView->SetEditSelection( aFoundSel.Min() ); + pEditView->getImpl().SetEditSelection( aFoundSel.Min() ); pEditView->ShowCursor( true, false ); - pEditView->pImpEditView->SetEditSelection( aFoundSel ); + pEditView->getImpl().SetEditSelection( aFoundSel ); } else - pEditView->pImpEditView->SetEditSelection( aSel.Max() ); + pEditView->getImpl().SetEditSelection( aSel.Max() ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); return bFound; } @@ -2555,15 +2597,15 @@ bool ImpEditEngine::ImpSearch( const SvxSearchItem& rSearchItem, bool bBack = rSearchItem.GetBackward(); bool bSearchInSelection = rSearchItem.GetSelection(); - sal_Int32 nStartNode = aEditDoc.GetPos( rStartPos.GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( rStartPos.GetNode() ); sal_Int32 nEndNode; if ( bSearchInSelection ) { - nEndNode = aEditDoc.GetPos( bBack ? rSearchSelection.Min().GetNode() : rSearchSelection.Max().GetNode() ); + nEndNode = maEditDoc.GetPos( bBack ? rSearchSelection.Min().GetNode() : rSearchSelection.Max().GetNode() ); } else { - nEndNode = bBack ? 0 : aEditDoc.Count()-1; + nEndNode = bBack ? 0 : maEditDoc.Count()-1; } utl::TextSearch aSearcher( aSearchOptions ); @@ -2577,7 +2619,7 @@ bool ImpEditEngine::ImpSearch( const SvxSearchItem& rSearchItem, if ( nNode < 0 ) return false; - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); sal_Int32 nStartPos = 0; sal_Int32 nEndPos = pNode->GetExpandedLen(); @@ -2632,7 +2674,7 @@ bool ImpEditEngine::HasText( const SvxSearchItem& rSearchItem ) aTmpItem.SetBackward( false ); aTmpItem.SetSelection( false ); - EditPaM aStartPaM( aEditDoc.GetStartPaM() ); + EditPaM aStartPaM( maEditDoc.GetStartPaM() ); EditSelection aDummySel( aStartPaM ); EditSelection aFoundSel; return ImpSearch( aTmpItem, aDummySel, aStartPaM, aFoundSel ); @@ -2640,9 +2682,9 @@ bool ImpEditEngine::HasText( const SvxSearchItem& rSearchItem ) void ImpEditEngine::SetAutoCompleteText(const OUString& rStr, bool bClearTipWindow) { - aAutoCompleteText = rStr; - if ( bClearTipWindow && pActiveView ) - Help::ShowQuickHelp( pActiveView->GetWindow(), tools::Rectangle(), OUString() ); + maAutoCompleteText = rStr; + if ( bClearTipWindow && mpActiveView ) + Help::ShowQuickHelp( mpActiveView->GetWindow(), tools::Rectangle(), OUString() ); } namespace @@ -2664,10 +2706,17 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, return rSelection; EditSelection aSel( rSelection ); - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); if ( !aSel.HasRange() ) - aSel = SelectWord( aSel ); + { + aSel = SelectWord( aSel, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, true, true ); + if (!aSel.HasRange() && aSel.Min().GetIndex() > 0 && + OUString(".!?").indexOf(aSel.Min().GetNode()->GetChar(aSel.Min().GetIndex() - 1)) > -1 ) + { + aSel = SelectSentence(aSel); + } + } // tdf#107176: if there's still no range, just return aSel if ( !aSel.HasRange() ) @@ -2675,8 +2724,8 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, EditSelection aNewSel( aSel ); - const sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - const sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + const sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + const sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); bool bChanges = false; bool bLenChanged = false; @@ -2687,7 +2736,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); const OUString& aNodeStr = pNode->GetString(); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : aNodeStr.getLength(); // can also be == nStart! @@ -2744,6 +2793,21 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, nWordType); } + /* Nothing to do if user selection lies entirely outside of word start and end boundary computed above. + * Skip this node, because otherwise the below logic for constraining to the selection will fail */ + if (aSttBndry.startPos >= aSel.Max().GetIndex() || aEndBndry.endPos <= aSel.Min().GetIndex()) { + continue; + } + + // prevent going outside of the user's selection, which may + // start or end in the middle of a word + if (nNode == nStartNode) { + aSttBndry.startPos = std::max(aSttBndry.startPos, aSel.Min().GetIndex()); + aSttBndry.endPos = std::min(aSttBndry.endPos, aSel.Max().GetIndex()); + aEndBndry.startPos = std::max(aEndBndry.startPos, aSttBndry.startPos); + aEndBndry.endPos = std::min(aEndBndry.endPos, aSel.Max().GetIndex()); + } + i18n::Boundary aCurWordBndry( aSttBndry ); while (aCurWordBndry.endPos && aCurWordBndry.startPos <= aEndBndry.startPos) { @@ -2754,7 +2818,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, Sequence< sal_Int32 > aOffsets; OUString aNewText( aTransliterationWrapper.transliterate(aNodeStr, - GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ), + GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ).nLang, nCurrentStart, nLen, &aOffsets )); if (aNodeStr != aNewText) @@ -2832,6 +2896,12 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, nCurrentEnd = nLastEnd; } + // prevent making any change outside of the user's selection + nCurrentStart = std::max(aSel.Min().GetIndex(), nCurrentStart); + nCurrentEnd = std::min(aSel.Max().GetIndex(), nCurrentEnd); + nLastStart = std::max(aSel.Min().GetIndex(), nLastStart); + nLastEnd = std::min(aSel.Max().GetIndex(), nLastEnd); + while (nCurrentStart < nLastEnd) { const sal_Int32 nLen = nCurrentEnd - nCurrentStart; @@ -2839,7 +2909,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, Sequence< sal_Int32 > aOffsets; OUString aNewText( aTransliterationWrapper.transliterate( aNodeStr, - GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ), + GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ).nLang, nCurrentStart, nLen, &aOffsets )); if (aNodeStr != aNewText) @@ -2869,7 +2939,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, { if ( bConsiderLanguage ) { - nLanguage = GetLanguage( EditPaM( pNode, nCurrentStart+1 ), &nCurrentEnd ); + nLanguage = GetLanguage( EditPaM( pNode, nCurrentStart+1 ), &nCurrentEnd ).nLang; if ( nCurrentEnd > nEndPos ) nCurrentEnd = nEndPos; } @@ -2912,7 +2982,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, aNewSel = aSel; ESelection aESel( CreateESel( aSel ) ); - pUndo.reset(new EditUndoTransliteration(pEditEngine, aESel, nTransliterationMode)); + pUndo.reset(new EditUndoTransliteration(mpEditEngine, aESel, nTransliterationMode)); const bool bSingleNode = aSel.Min().GetNode()== aSel.Max().GetNode(); const bool bHasAttribs = aSel.Min().GetNode()->GetCharAttribs().HasAttrib( aSel.Min().GetIndex(), aSel.Max().GetIndex() ); @@ -2941,9 +3011,9 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, if (aSel.Max().GetNode() == rData.aSelection.Max().GetNode()) aNewSel.Max().SetIndex( aNewSel.Max().GetIndex() + nDiffs ); - sal_Int32 nSelNode = aEditDoc.GetPos( rData.aSelection.Min().GetNode() ); - ParaPortion& rParaPortion = GetParaPortions()[nSelNode]; - rParaPortion.MarkSelectionInvalid( rData.nStart ); + sal_Int32 nSelNode = maEditDoc.GetPos( rData.aSelection.Min().GetNode() ); + ParaPortion& rParaPortion = GetParaPortions().getRef(nSelNode); + rParaPortion.MarkSelectionInvalid(rData.nStart); } } } @@ -2961,7 +3031,8 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, SetModifyFlag( true ); if ( bLenChanged ) UpdateSelections(); - FormatAndUpdate(); + if (IsUpdateLayout()) + FormatAndLayout(); } return aNewSel; @@ -3000,7 +3071,7 @@ short ImpEditEngine::ReplaceTextOnly( else { DBG_ASSERT( nDiff == 1, "TransliterateText - Diff other than expected! But should work..." ); - GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), OUString(rNewText[n]) ); + GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), OUStringChar(rNewText[n]) ); } nDiffs = sal::static_int_cast< short >(nDiffs + nDiff); @@ -3012,9 +3083,9 @@ short ImpEditEngine::ReplaceTextOnly( void ImpEditEngine::SetAsianCompressionMode( CharCompressType n ) { - if ( n != nAsianCompressionMode ) + if (n != mnAsianCompressionMode) { - nAsianCompressionMode = n; + mnAsianCompressionMode = n; if ( ImplHasText() ) { FormatFullDoc(); @@ -3025,9 +3096,9 @@ void ImpEditEngine::SetAsianCompressionMode( CharCompressType n ) void ImpEditEngine::SetKernAsianPunctuation( bool b ) { - if ( b != bKernAsianPunctuation ) + if ( b != mbKernAsianPunctuation ) { - bKernAsianPunctuation = b; + mbKernAsianPunctuation = b; if ( ImplHasText() ) { FormatFullDoc(); @@ -3040,7 +3111,7 @@ void ImpEditEngine::SetAddExtLeading( bool bExtLeading ) { if ( IsAddExtLeading() != bExtLeading ) { - bAddExtLeading = bExtLeading; + mbAddExtLeading = bExtLeading; if ( ImplHasText() ) { FormatFullDoc(); @@ -3059,8 +3130,21 @@ sal_Int32 ImpEditEngine::LogicToTwips(sal_Int32 n) { Size aSz(n, 0); MapMode aTwipsMode( MapUnit::MapTwip ); - aSz = pRefDev->LogicToLogic( aSz, nullptr, &aTwipsMode ); + aSz = mpRefDev->LogicToLogic( aSz, nullptr, &aTwipsMode ); return aSz.Width(); } +double ImpEditEngine::roundToNearestPt(double fInput) const +{ + if (mbRoundToNearestPt) + { + double fInputPt = o3tl::convert(fInput, o3tl::Length::mm100, o3tl::Length::pt); + return o3tl::convert(std::round(fInputPt), o3tl::Length::pt, o3tl::Length::mm100); + } + else + { + return fInput; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx index 02133496bb6b..396e529c514d 100644 --- a/editeng/source/editeng/impedit5.cxx +++ b/editeng/source/editeng/impedit5.cxx @@ -22,51 +22,49 @@ #include <editeng/editeng.hxx> #include <svl/hint.hxx> #include <sfx2/app.hxx> +#include <utility> void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) { - if ( pStylePool != pSPool ) - { - pStylePool = pSPool; - } + if (mpStylePool != pSPool) + mpStylePool = pSPool; } const SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_Int32 nPara ) const { - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); return pNode ? pNode->GetContentAttribs().GetStyleSheet() : nullptr; } SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_Int32 nPara ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); return pNode ? pNode->GetContentAttribs().GetStyleSheet() : nullptr; } void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); - sal_Int32 nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartPara = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndPara = maEditDoc.GetPos( aSel.Max().GetNode() ); - bool _bUpdate = GetUpdateMode(); - SetUpdateMode( false ); + bool _bUpdate = SetUpdateLayout( false ); for ( sal_Int32 n = nStartPara; n <= nEndPara; n++ ) SetStyleSheet( n, pStyle ); - SetUpdateMode( _bUpdate ); + SetUpdateLayout( _bUpdate ); } void ImpEditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ) { DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" ); - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); SfxStyleSheet* pCurStyle = pNode->GetStyleSheet(); if ( pStyle != pCurStyle ) { - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if ( IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs() ) { OUString aPrevStyleName; if ( pCurStyle ) @@ -77,19 +75,23 @@ void ImpEditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ) aNewStyleName = pStyle->GetName(); InsertUndo( - std::make_unique<EditUndoSetStyleSheet>(pEditEngine, aEditDoc.GetPos( pNode ), + std::make_unique<EditUndoSetStyleSheet>(mpEditEngine, maEditDoc.GetPos( pNode ), aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SfxStyleFamily::Para, aNewStyleName, pStyle ? pStyle->GetFamily() : SfxStyleFamily::Para, pNode->GetContentAttribs().GetItems() ) ); } if ( pCurStyle ) EndListening( *pCurStyle ); - pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() ); + pNode->SetStyleSheet( pStyle, maStatus.UseCharAttribs() ); if ( pStyle ) - StartListening(*pStyle, DuplicateHandling::Prevent); + StartListening(*pStyle, DuplicateHandling::Allow); + + if (pNode->GetWrongList()) + pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len()); ParaAttribsChanged( pNode ); } - FormatAndUpdate(); + if (IsUpdateLayout()) + FormatAndLayout(); } void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle ) @@ -98,110 +100,109 @@ void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle ) CreateFont( aFontFromStyle, pStyle->GetItemSet() ); bool bUsed = false; - for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ ) + for ( sal_Int32 nNode = 0; nNode < maEditDoc.Count(); nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); if ( pNode->GetStyleSheet() == pStyle ) { bUsed = true; - if ( aStatus.UseCharAttribs() ) + if (maStatus.UseCharAttribs()) pNode->SetStyleSheet( pStyle, aFontFromStyle ); else pNode->SetStyleSheet( pStyle, false ); + if (pNode->GetWrongList()) + pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len()); ParaAttribsChanged( pNode ); } } if ( bUsed ) { GetEditEnginePtr()->StyleSheetChanged( pStyle ); - FormatAndUpdate(); + if (IsUpdateLayout()) + FormatAndLayout(); } } void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet const * pStyle ) { - for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ ) + for ( sal_Int32 nNode = 0; nNode < maEditDoc.Count(); nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject(nNode); + ContentNode* pNode = maEditDoc.GetObject(nNode); if ( pNode->GetStyleSheet() == pStyle ) { pNode->SetStyleSheet( nullptr ); ParaAttribsChanged( pNode ); } } - FormatAndUpdate(); + if (IsUpdateLayout()) + FormatAndLayout(); } void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { // So that not a lot of unnecessary formatting is done when destructing: - if ( !bDowning ) + if (!mbDowning) { - - const SfxStyleSheetHint* pStyleSheetHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint); - if ( pStyleSheetHint ) + SfxHintId nId = rHint.GetId(); + if ( ( nId == SfxHintId::StyleSheetInDestruction ) || + ( nId == SfxHintId::StyleSheetErased ) ) { - DBG_ASSERT( dynamic_cast< const SfxStyleSheet* >(pStyleSheetHint->GetStyleSheet()) != nullptr, "No SfxStyleSheet!" ); + const SfxStyleSheetHint* pStyleSheetHint = static_cast<const SfxStyleSheetHint*>(&rHint); SfxStyleSheet* pStyle = static_cast<SfxStyleSheet*>( pStyleSheetHint->GetStyleSheet() ); - SfxHintId nId = pStyleSheetHint->GetId(); - if ( ( nId == SfxHintId::StyleSheetInDestruction ) || - ( nId == SfxHintId::StyleSheetErased ) ) - { - RemoveStyleFromParagraphs( pStyle ); - } - else if ( nId == SfxHintId::StyleSheetModified ) - { - UpdateParagraphsWithStyleSheet( pStyle ); - } + RemoveStyleFromParagraphs( pStyle ); } - else if ( auto pStyle = dynamic_cast< SfxStyleSheet* >(&rBC) ) + else if ( nId == SfxHintId::StyleSheetModified || nId == SfxHintId::StyleSheetModifiedExtended ) { - SfxHintId nId = rHint.GetId(); - if ( nId == SfxHintId::Dying ) - { - RemoveStyleFromParagraphs( pStyle ); - } - else if ( nId == SfxHintId::DataChanged ) - { - UpdateParagraphsWithStyleSheet( pStyle ); - } + const SfxStyleSheetHint* pStyleSheetHint = static_cast<const SfxStyleSheetHint*>(&rHint); + SfxStyleSheet* pStyle = static_cast<SfxStyleSheet*>( pStyleSheetHint->GetStyleSheet() ); + UpdateParagraphsWithStyleSheet( pStyle ); + } + else if ( nId == SfxHintId::Dying && rBC.IsSfxStyleSheet() ) + { + auto pStyle = static_cast< SfxStyleSheet* >(&rBC); + RemoveStyleFromParagraphs( pStyle ); + } + else if ( nId == SfxHintId::DataChanged && rBC.IsSfxStyleSheet()) + { + auto pStyle = static_cast< SfxStyleSheet* >(&rBC); + UpdateParagraphsWithStyleSheet( pStyle ); } } - if(dynamic_cast<const SfxApplication*>(&rBC) != nullptr && rHint.GetId() == SfxHintId::Dying) + if (rHint.GetId() == SfxHintId::Dying && dynamic_cast<const SfxApplication*>(&rBC)) Dispose(); } std::unique_ptr<EditUndoSetAttribs> ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet ) { - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Incorrect selection "); - aSel.Adjust( aEditDoc ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "CreateAttribUndo: Incorrect selection "); + aSel.Adjust( maEditDoc ); ESelection aESel( CreateESel( aSel ) ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" ); std::unique_ptr<EditUndoSetAttribs> pUndo; - if ( rSet.GetPool() != &aEditDoc.GetItemPool() ) + if ( rSet.GetPool() != &maEditDoc.GetItemPool() ) { SfxItemSet aTmpSet( GetEmptyItemSet() ); aTmpSet.Put( rSet ); - pUndo.reset( new EditUndoSetAttribs(pEditEngine, aESel, aTmpSet) ); + pUndo.reset( new EditUndoSetAttribs(mpEditEngine, aESel, std::move(aTmpSet)) ); } else { - pUndo.reset( new EditUndoSetAttribs(pEditEngine, aESel, rSet) ); + pUndo.reset( new EditUndoSetAttribs(mpEditEngine, aESel, rSet) ); } SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool(); for ( sal_Int32 nPara = nStartNode; nPara <= nEndNode; nPara++ ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); - DBG_ASSERT( aEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); + DBG_ASSERT( maEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" ); ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() ); pUndo->AppendContentInfo(pInf); @@ -222,8 +223,8 @@ ViewShellId ImpEditEngine::CreateViewShellId() { ViewShellId nRet(-1); - const EditView* pEditView = pEditEngine ? pEditEngine->GetActiveView() : nullptr; - const OutlinerViewShell* pViewShell = pEditView ? pEditView->GetImpEditView()->GetViewShell() : nullptr; + const EditView* pEditView = mpEditEngine ? mpEditEngine->GetActiveView() : nullptr; + const OutlinerViewShell* pViewShell = pEditView ? pEditView->getImpl().GetViewShell() : nullptr; if (pViewShell) nRet = pViewShell->GetViewShellId(); @@ -235,8 +236,8 @@ void ImpEditEngine::UndoActionStart( sal_uInt16 nId, const ESelection& aSel ) if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId, CreateViewShellId() ); - DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" ); - pUndoMarkSelection.reset(new ESelection( aSel )); + DBG_ASSERT( !moUndoMarkSelection, "UndoAction SelectionMarker?" ); + moUndoMarkSelection = aSel; } } @@ -245,7 +246,7 @@ void ImpEditEngine::UndoActionStart( sal_uInt16 nId ) if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId, CreateViewShellId() ); - DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" ); + DBG_ASSERT( !moUndoMarkSelection, "UndoAction SelectionMarker?" ); } } @@ -254,17 +255,17 @@ void ImpEditEngine::UndoActionEnd() if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().LeaveListAction(); - pUndoMarkSelection.reset(); + moUndoMarkSelection.reset(); } } void ImpEditEngine::InsertUndo( std::unique_ptr<EditUndo> pUndo, bool bTryMerge ) { DBG_ASSERT( !IsInUndo(), "InsertUndo in Undo mode!" ); - if ( pUndoMarkSelection ) + if ( moUndoMarkSelection ) { - GetUndoManager().AddUndoAction( std::make_unique<EditUndoMarkSelection>(pEditEngine, *pUndoMarkSelection) ); - pUndoMarkSelection.reset(); + GetUndoManager().AddUndoAction( std::make_unique<EditUndoMarkSelection>(mpEditEngine, *moUndoMarkSelection) ); + moUndoMarkSelection.reset(); } GetUndoManager().AddUndoAction( std::move(pUndo), bTryMerge ); @@ -283,7 +284,7 @@ void ImpEditEngine::EnableUndo( bool bEnable ) if ( bEnable != IsUndoEnabled() ) ResetUndoManager(); - bUndoEnabled = bEnable; + mbUndoEnabled = bEnable; } void ImpEditEngine::Undo( EditView* pView ) @@ -307,18 +308,18 @@ void ImpEditEngine::Redo( EditView* pView ) SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnlyHardAttrib ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); SfxItemSet aCurSet( GetEmptyItemSet() ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); - DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: GetAttrib" ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); + assert( pNode && "Node not found: GetAttrib" ); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // Can also be == nStart! @@ -329,7 +330,8 @@ SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnl // 2) Examine Style and paragraph attributes only when OFF... // First the very hard formatting... - EditDoc::FindAttribs( pNode, nStartPos, nEndPos, aCurSet ); + if (pNode) + EditDoc::FindAttribs( pNode, nStartPos, nEndPos, aCurSet ); if( nOnlyHardAttrib != EditEngineAttribs::OnlyHard ) { @@ -384,7 +386,7 @@ SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnl { if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT ) { - aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) ); + aCurSet.Put( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( nWhich ) ); } } } @@ -398,7 +400,7 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results! - ContentNode* pNode = const_cast<ContentNode*>(aEditDoc.GetObject(nPara)); + ContentNode* pNode = const_cast<ContentNode*>(maEditDoc.GetObject(nPara)); DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" ); DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" ); @@ -425,8 +427,7 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int if ( nFlags & GetAttribsFlags::CHARATTRIBS ) { // Make testing easier... - const SfxItemPool& rPool = GetEditDoc().GetItemPool(); - pNode->GetCharAttribs().OptimizeRanges(const_cast<SfxItemPool&>(rPool)); + pNode->GetCharAttribs().OptimizeRanges(); const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs(); for (const auto & nAttr : rAttrs) @@ -483,22 +484,23 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int } -void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetAttribsMode nSpecial ) +void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetAttribsMode nSpecial, bool bSetSelection ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); // When no selection => use the Attribute on the word. // ( the RTF-parser should actually never call the Method without a Range ) if ( nSpecial == SetAttribsMode::WholeWord && !aSel.HasRange() ) aSel = SelectWord( aSel, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, false ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if (IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs()) { std::unique_ptr<EditUndoSetAttribs> pUndo = CreateAttribUndo( aSel, rSet ); pUndo->SetSpecial( nSpecial ); + pUndo->SetUpdateSelection(bSetSelection); InsertUndo( std::move(pUndo) ); } @@ -516,11 +518,14 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA bool bParaAttribFound = false; bool bCharAttribFound = false; - DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); - DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" ); + DBG_ASSERT( maEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); + DBG_ASSERT(GetParaPortions().exists(nNode), "Portion not found: SetAttribs"); - ContentNode* pNode = aEditDoc.GetObject( nNode ); - ParaPortion& rPortion = GetParaPortions()[nNode]; + if (!GetParaPortions().exists(nNode)) + continue; + + ContentNode* pNode = maEditDoc.GetObject(nNode); + ParaPortion& rPortion = GetParaPortions().getRef(nNode); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart! @@ -538,7 +543,7 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA } else { - aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem ); + maEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem ); bCharAttribFound = true; if ( nSpecial == SetAttribsMode::Edge ) { @@ -562,14 +567,14 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA if ( bParaAttribFound ) { - ParaAttribsChanged( rPortion.GetNode() ); + ParaAttribsChanged(rPortion.GetNode()); } else if ( bCharAttribFound ) { - bFormatted = false; + mbFormatted = false; if ( !pNode->Len() || ( nStartPos != nEndPos ) ) { - rPortion.MarkSelectionInvalid( nStartPos ); + rPortion.MarkSelectionInvalid(nStartPos); if ( bCheckLanguage ) pNode->GetWrongList()->SetInvalidRange(nStartPos, nEndPos); } @@ -579,14 +584,14 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMode eMode, sal_uInt16 nWhich ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); bool bRemoveParaAttribs = eMode == EERemoveParaAttribsMode::RemoveAll; const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : nullptr; - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if (IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs()) { // Possibly a special Undo, or itemset* std::unique_ptr<EditUndoSetAttribs> pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() ); @@ -599,17 +604,21 @@ void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMo // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); - ParaPortion& rPortion = GetParaPortions()[nNode]; + ContentNode* pNode = maEditDoc.GetObject( nNode ); + + DBG_ASSERT( maEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); + DBG_ASSERT(GetParaPortions().exists(nNode), "Portion not found: SetAttribs"); - DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); - DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" ); + if (!GetParaPortions().exists(nNode)) + continue; + + ParaPortion& rPortion = GetParaPortions().getRef(nNode); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart! // Optimize: If whole paragraph, then RemoveCharAttribs (nPara)? - bool bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich ); + bool bChanged = maEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich ); if ( bRemoveParaAttribs ) { SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidated @@ -633,15 +642,15 @@ void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMo if ( bChanged && !bRemoveParaAttribs ) { - bFormatted = false; - rPortion.MarkSelectionInvalid( nStartPos ); + mbFormatted = false; + rPortion.MarkSelectionInvalid(nStartPos); } } } void ImpEditEngine::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich, bool bRemoveFeatures ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); ParaPortion* pPortion = GetParaPortions().SafeGetObject( nPara ); DBG_ASSERT( pNode, "Node not found: RemoveCharAttribs" ); @@ -674,7 +683,7 @@ void ImpEditEngine::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich, bool void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); if ( !pNode ) return; @@ -682,17 +691,17 @@ void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) if ( pNode->GetContentAttribs().GetItems() == rSet ) return; - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if (IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs()) { - if ( rSet.GetPool() != &aEditDoc.GetItemPool() ) + if ( rSet.GetPool() != &maEditDoc.GetItemPool() ) { SfxItemSet aTmpSet( GetEmptyItemSet() ); aTmpSet.Put( rSet ); - InsertUndo(std::make_unique<EditUndoSetParaAttribs>(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet)); + InsertUndo(std::make_unique<EditUndoSetParaAttribs>(mpEditEngine, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet)); } else { - InsertUndo(std::make_unique<EditUndoSetParaAttribs>(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet)); + InsertUndo(std::make_unique<EditUndoSetParaAttribs>(mpEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet)); } } @@ -705,7 +714,7 @@ void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) if ( bCheckLanguage && pNode->GetWrongList() ) pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len()); - if ( aStatus.UseCharAttribs() ) + if (maStatus.UseCharAttribs()) pNode->CreateDefFont(); ParaAttribsChanged( pNode ); @@ -713,21 +722,21 @@ void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) const SfxItemSet& ImpEditEngine::GetParaAttribs( sal_Int32 nPara ) const { - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); assert(pNode && "Node not found: GetParaAttribs"); return pNode->GetContentAttribs().GetItems(); } bool ImpEditEngine::HasParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); assert(pNode && "Node not found: HasParaAttrib"); return pNode->GetContentAttribs().HasItem( nWhich ); } const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - const ContentNode* pNode = aEditDoc.GetObject(nPara); + const ContentNode* pNode = maEditDoc.GetObject(nPara); assert(pNode && "Node not found: GetParaAttrib"); return pNode->GetContentAttribs().GetItem(nWhich); } @@ -735,7 +744,7 @@ const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWh void ImpEditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const { rLst.clear(); - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); if ( !pNode ) return; @@ -751,7 +760,7 @@ void ImpEditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode ) { - pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() ); + pNode->GetCharAttribs().DeleteEmptyAttribs(); sal_Int32 nEndPos = pNode->Len(); for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ ) { @@ -765,39 +774,38 @@ void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode ) { nLastEnd = pAttr->GetEnd(); if ( pAttr->GetStart() > nLastEnd ) - aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem ); + maEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem ); // #112831# Last Attr might go from 0xffff to 0x0000 pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : nullptr; } // And the Rest: if ( nLastEnd < nEndPos ) - aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem ); + maEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem ); } } - bFormatted = false; + mbFormatted = false; // Portion does not need to be invalidated here, happens elsewhere. } IdleFormattter::IdleFormattter() + : Idle("editeng::ImpEditEngine aIdleFormatter") { - pView = nullptr; - nRestarts = 0; } IdleFormattter::~IdleFormattter() { - pView = nullptr; + mpView = nullptr; } -void IdleFormattter::DoIdleFormat( EditView* pV ) +void IdleFormattter::DoIdleFormat(EditView* pView) { - pView = pV; + mpView = pView; - if ( IsActive() ) - nRestarts++; + if (IsActive()) + mnRestarts++; - if ( nRestarts > 4 ) + if (mnRestarts > 4) ForceTimeout(); else Start(); @@ -805,36 +813,12 @@ void IdleFormattter::DoIdleFormat( EditView* pV ) void IdleFormattter::ForceTimeout() { - if ( IsActive() ) + if (IsActive()) { Stop(); Invoke(); } } -ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const OUString& rOldTextAfterStartPos ) - : aOldTextAfterStartPos( rOldTextAfterStartPos ), - aPos(rPos), - nLen(0), - bWasCursorOverwrite(false) - { - } - -ImplIMEInfos::~ImplIMEInfos() -{ -} - -void ImplIMEInfos::CopyAttribs( const ExtTextInputAttr* pA, sal_uInt16 nL ) -{ - nLen = nL; - pAttribs.reset( new ExtTextInputAttr[ nL ] ); - memcpy( pAttribs.get(), pA, nL*sizeof(ExtTextInputAttr) ); -} - -void ImplIMEInfos::DestroyAttribs() -{ - pAttribs.reset(); - nLen = 0; -} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/misspellrange.cxx b/editeng/source/editeng/misspellrange.cxx index 40fe5dd1b76e..562a9905c27d 100644 --- a/editeng/source/editeng/misspellrange.cxx +++ b/editeng/source/editeng/misspellrange.cxx @@ -13,8 +13,8 @@ namespace editeng { MisspellRange::MisspellRange(size_t nStart, size_t nEnd) : mnStart(nStart), mnEnd(nEnd) {} -MisspellRanges::MisspellRanges(sal_Int32 nParagraph, const std::vector<MisspellRange>& rRanges) : - mnParagraph(nParagraph), maRanges(rRanges) {} +MisspellRanges::MisspellRanges(sal_Int32 nParagraph, std::vector<MisspellRange>&& rRanges) : + mnParagraph(nParagraph), maRanges(std::move(rRanges)) {} } diff --git a/editeng/source/editeng/textconv.cxx b/editeng/source/editeng/textconv.cxx index 7c4ed9ddd89d..3d4c03e1ddeb 100644 --- a/editeng/source/editeng/textconv.cxx +++ b/editeng/source/editeng/textconv.cxx @@ -29,8 +29,6 @@ using namespace com::sun::star; using namespace com::sun::star::uno; -using namespace com::sun::star::beans; -using namespace com::sun::star::linguistic2; TextConvWrapper::TextConvWrapper( weld::Widget* pWindow, const Reference< XComponentContext >& rxContext, @@ -122,17 +120,17 @@ bool TextConvWrapper::ConvMore_impl() // modified version of SvxSpellWrapper::SpellMore bool bMore = false; - EditEngine* pEE = m_pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = m_pEditView->GetImpEditEngine(); - ConvInfo* pConvInfo = pImpEE->GetConvInfo(); + EditEngine& rEditEngine = m_pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = m_pEditView->getImpEditEngine(); + ConvInfo* pConvInfo = rImpEditEngine.GetConvInfo(); if ( pConvInfo->bMultipleDoc ) { - bMore = pEE->ConvertNextDocument(); + bMore = rEditEngine.ConvertNextDocument(); if ( bMore ) { // The text has been entered in this engine ... - m_pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + m_pEditView->getImpl().SetEditSelection( + rEditEngine.GetEditDoc().GetStartPaM() ); } } return bMore; @@ -143,9 +141,9 @@ void TextConvWrapper::ConvStart_impl( SvxSpellArea eArea ) { // modified version of EditSpellWrapper::SpellStart - EditEngine* pEE = m_pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = m_pEditView->GetImpEditEngine(); - ConvInfo* pConvInfo = pImpEE->GetConvInfo(); + EditEngine& rEditEngine = m_pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = m_pEditView->getImpEditEngine(); + ConvInfo* pConvInfo = rImpEditEngine.GetConvInfo(); if ( eArea == SvxSpellArea::BodyStart ) { @@ -155,14 +153,13 @@ void TextConvWrapper::ConvStart_impl( SvxSpellArea eArea ) pConvInfo->bConvToEnd = false; pConvInfo->aConvTo = pConvInfo->aConvStart; pConvInfo->aConvContinue = EPaM( 0, 0 ); - m_pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + m_pEditView->getImpl().SetEditSelection( + rEditEngine.GetEditDoc().GetStartPaM() ); } else { pConvInfo->bConvToEnd = true; - pConvInfo->aConvTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetStartPaM() ); + pConvInfo->aConvTo = rImpEditEngine.CreateEPaM(rEditEngine.GetEditDoc().GetStartPaM() ); } } else if ( eArea == SvxSpellArea::BodyEnd ) @@ -179,16 +176,14 @@ void TextConvWrapper::ConvStart_impl( SvxSpellArea eArea ) else { // nothing selected: convert to end of document - pConvInfo->aConvTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetEndPaM() ); + pConvInfo->aConvTo = rImpEditEngine.CreateEPaM(rEditEngine.GetEditDoc().GetEndPaM() ); } } else if ( eArea == SvxSpellArea::Body ) { // called by ConvNext_impl... pConvInfo->aConvContinue = pConvInfo->aConvStart; - pConvInfo->aConvTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetEndPaM() ); + pConvInfo->aConvTo = rImpEditEngine.CreateEPaM(rEditEngine.GetEditDoc().GetEndPaM() ); } else { @@ -204,7 +199,7 @@ bool TextConvWrapper::ConvContinue_impl() // get next convertible text portion and its language m_aConvText.clear(); m_nConvTextLang = LANGUAGE_NONE; - m_pEditView->GetImpEditEngine()->ImpConvert( m_aConvText, m_nConvTextLang, + m_pEditView->getImpEditEngine().ImpConvert( m_aConvText, m_nConvTextLang, m_pEditView, GetSourceLanguage(), m_aConvSel, m_bAllowChange, GetTargetLanguage(), GetTargetFont() ); return !m_aConvText.isEmpty(); @@ -341,15 +336,15 @@ void TextConvWrapper::ReplaceUnit( m_nUnitOffset = m_nUnitOffset + nUnitStart + aNewTxt.getLength(); // remember current original language for later use - ImpEditEngine *pImpEditEng = m_pEditView->GetImpEditEngine(); + ImpEditEngine& rImpEditEngine = m_pEditView->getImpEditEngine(); ESelection aOldSel = m_pEditView->GetSelection(); - //EditSelection aOldEditSel = pEditView->GetImpEditView()->GetEditSelection(); + //EditSelection aOldEditSel = pEditView->getImpl().GetEditSelection(); #ifdef DBG_UTIL - LanguageType nOldLang = pImpEditEng->GetLanguage( pImpEditEng->CreateSel( aOldSel ).Min() ); + LanguageType nOldLang = rImpEditEngine.GetLanguage(rImpEditEngine.CreateSel( aOldSel ).Min() ).nLang; #endif - pImpEditEng->UndoActionStart( EDITUNDO_INSERT ); + rImpEditEngine.UndoActionStart( EDITUNDO_INSERT ); // according to FT we should currently not bother about keeping // attributes in Hangul/Hanja conversion and leave that untouched. @@ -380,11 +375,10 @@ void TextConvWrapper::ReplaceUnit( } } - pImpEditEng->UndoActionEnd(); + rImpEditEngine.UndoActionEnd(); // adjust ConvContinue / ConvTo if necessary - ImpEditEngine* pImpEE = m_pEditView->GetImpEditEngine(); - ConvInfo* pConvInfo = pImpEE->GetConvInfo(); + ConvInfo* pConvInfo = rImpEditEngine.GetConvInfo(); sal_Int32 nDelta = aNewTxt.getLength() - aOrigTxt.getLength(); if (nDelta != 0) { @@ -401,7 +395,7 @@ void TextConvWrapper::ReplaceUnit( void TextConvWrapper::ChangeText( const OUString &rNewText, - const OUString& rOrigText, + std::u16string_view rOrigText, const uno::Sequence< sal_Int32 > *pOffsets, ESelection *pESelection ) { @@ -443,7 +437,7 @@ void TextConvWrapper::ChangeText( const OUString &rNewText, else { nPos = nConvTextLen; - nIndex = rOrigText.getLength(); + nIndex = rOrigText.size(); } // end of string also terminates non-matching char sequence diff --git a/editeng/source/editeng/textconv.hxx b/editeng/source/editeng/textconv.hxx index 6afb20acf966..96525a98f530 100644 --- a/editeng/source/editeng/textconv.hxx +++ b/editeng/source/editeng/textconv.hxx @@ -61,7 +61,7 @@ class TextConvWrapper final : public editeng::HangulHanjaConversion const sal_Int32 nUnitEnd ); void ChangeText( const OUString &rNewText, - const OUString& rOrigText, + std::u16string_view rOrigText, const css::uno::Sequence< sal_Int32 > *pOffsets, ESelection *pESelection ); void ChangeText_impl( const OUString &rNewText, bool bKeepAttributes ); diff --git a/editeng/source/items/CustomPropertyField.cxx b/editeng/source/items/CustomPropertyField.cxx index b90c191a8587..eaad4c4c4db8 100644 --- a/editeng/source/items/CustomPropertyField.cxx +++ b/editeng/source/items/CustomPropertyField.cxx @@ -9,6 +9,7 @@ */ #include <editeng/CustomPropertyField.hxx> +#include <utility> #include <vcl/metaact.hxx> #include <com/sun/star/beans/XPropertyContainer.hpp> #include <com/sun/star/beans/XPropertySet.hpp> @@ -19,10 +20,9 @@ using namespace css; namespace editeng { -CustomPropertyField::CustomPropertyField(OUString const & rName, OUString const & rCurrentPresentation) - : SvxFieldData() - , msName(rName) - , msCurrentPresentation(rCurrentPresentation) +CustomPropertyField::CustomPropertyField(OUString aName, OUString aCurrentPresentation) + : msName(std::move(aName)) + , msCurrentPresentation(std::move(aCurrentPresentation)) {} CustomPropertyField::~CustomPropertyField() @@ -45,7 +45,7 @@ bool CustomPropertyField::operator==(const SvxFieldData& rOther) const MetaAction* CustomPropertyField::createBeginComment() const { - return new MetaCommentAction("FIELD_SEQ_BEGIN"); + return new MetaCommentAction("FIELD_SEQ_BEGIN"_ostr); } OUString CustomPropertyField::GetFormatted(uno::Reference<document::XDocumentProperties> const & xDocumentProperties) diff --git a/editeng/source/items/borderline.cxx b/editeng/source/items/borderline.cxx index 9037eeba9015..05742eb95131 100644 --- a/editeng/source/items/borderline.cxx +++ b/editeng/source/items/borderline.cxx @@ -30,7 +30,11 @@ #include <editeng/eerdll.hxx> #include <tools/bigint.hxx> +#include <docmodel/uno/UnoComplexColor.hxx> +#include <com/sun/star/util/XComplexColor.hpp> + using namespace ::com::sun::star::table::BorderLineStyle; +using namespace css; // class SvxBorderLine -------------------------------------------------- @@ -57,7 +61,22 @@ namespace { } } // Anonymous namespace -namespace editeng { +namespace editeng +{ + +bool SvxBorderLine::setComplexColorFromAny(css::uno::Any const& rValue) +{ + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rValue >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + { + auto aComplexColor = model::color::getFromXComplexColor(xComplexColor); + setComplexColor(aComplexColor); + } + return true; +} Color SvxBorderLine::darkColor( Color aMain ) { @@ -98,22 +117,21 @@ Color SvxBorderLine::threeDMediumColor( Color aMain ) SvxBorderLine::SvxBorderLine( const Color *pCol, tools::Long nWidth, SvxBorderLineStyle nStyle, Color (*pColorOutFn)( Color ), Color (*pColorInFn)( Color ) ) -: m_nWidth( nWidth ) -, m_bMirrorWidths( false ) -, m_aWidthImpl( SvxBorderLine::getWidthImpl( nStyle ) ) -, m_nMult( 1 ) -, m_nDiv( 1 ) -, m_nStyle( nStyle ) -, m_bUseLeftTop( false ) -, m_pColorOutFn( pColorOutFn ) -, m_pColorInFn( pColorInFn ) -, m_pColorGapFn( nullptr ) + : m_nWidth(nWidth) + , m_nMult(1) + , m_nDiv(1) + , m_pColorOutFn(pColorOutFn) + , m_pColorInFn(pColorInFn) + , m_pColorGapFn(nullptr) + , m_aWidthImpl(SvxBorderLine::getWidthImpl(nStyle)) + , m_nStyle(nStyle) + , m_bMirrorWidths(false) + , m_bUseLeftTop(false) { - if ( pCol ) - aColor = *pCol; + if (pCol) + m_aColor = *pCol; } - SvxBorderLineStyle ConvertBorderStyleFromWord(int const nWordLineStyle) { @@ -519,15 +537,16 @@ sal_uInt16 SvxBorderLine::GetDistance() const bool SvxBorderLine::operator==( const SvxBorderLine& rCmp ) const { - return ( ( aColor == rCmp.aColor ) && - ( m_nWidth == rCmp.m_nWidth ) && - ( m_bMirrorWidths == rCmp.m_bMirrorWidths ) && - ( m_aWidthImpl == rCmp.m_aWidthImpl ) && - ( m_nStyle == rCmp.GetBorderLineStyle()) && - ( m_bUseLeftTop == rCmp.m_bUseLeftTop ) && - ( m_pColorOutFn == rCmp.m_pColorOutFn ) && - ( m_pColorInFn == rCmp.m_pColorInFn ) && - ( m_pColorGapFn == rCmp.m_pColorGapFn ) ); + return (m_aColor == rCmp.m_aColor && + m_aComplexColor == rCmp.m_aComplexColor && + m_nWidth == rCmp.m_nWidth && + m_bMirrorWidths == rCmp.m_bMirrorWidths && + m_aWidthImpl == rCmp.m_aWidthImpl && + m_nStyle == rCmp.GetBorderLineStyle() && + m_bUseLeftTop == rCmp.m_bUseLeftTop && + m_pColorOutFn == rCmp.m_pColorOutFn && + m_pColorInFn == rCmp.m_pColorInFn && + m_pColorGapFn == rCmp.m_pColorGapFn); } void SvxBorderLine::SetBorderLineStyle( SvxBorderLineStyle nNew ) @@ -572,14 +591,14 @@ void SvxBorderLine::SetBorderLineStyle( SvxBorderLineStyle nNew ) Color SvxBorderLine::GetColorOut( bool bLeftOrTop ) const { - Color aResult = aColor; + Color aResult = m_aColor; if ( m_aWidthImpl.IsDouble() && m_pColorOutFn != nullptr ) { if ( !bLeftOrTop && m_bUseLeftTop ) - aResult = (*m_pColorInFn)( aColor ); + aResult = (*m_pColorInFn)(m_aColor); else - aResult = (*m_pColorOutFn)( aColor ); + aResult = (*m_pColorOutFn)(m_aColor); } return aResult; @@ -587,14 +606,14 @@ Color SvxBorderLine::GetColorOut( bool bLeftOrTop ) const Color SvxBorderLine::GetColorIn( bool bLeftOrTop ) const { - Color aResult = aColor; + Color aResult = m_aColor; if ( m_aWidthImpl.IsDouble() && m_pColorInFn != nullptr ) { if ( !bLeftOrTop && m_bUseLeftTop ) - aResult = (*m_pColorOutFn)( aColor ); + aResult = (*m_pColorOutFn)(m_aColor); else - aResult = (*m_pColorInFn)( aColor ); + aResult = (*m_pColorInFn)(m_aColor); } return aResult; @@ -602,11 +621,11 @@ Color SvxBorderLine::GetColorIn( bool bLeftOrTop ) const Color SvxBorderLine::GetColorGap( ) const { - Color aResult = aColor; + Color aResult = m_aColor; if ( m_aWidthImpl.IsDouble() && m_pColorGapFn != nullptr ) { - aResult = (*m_pColorGapFn)( aColor ); + aResult = (*m_pColorGapFn)(m_aColor); } return aResult; @@ -622,7 +641,7 @@ OUString SvxBorderLine::GetValueString(MapUnit eSrcUnit, const IntlWrapper* pIntl, bool bMetricStr) const { - static const char* aStyleIds[] = + static TranslateId aStyleIds[] = { RID_SOLID, RID_DOTTED, @@ -643,11 +662,11 @@ OUString SvxBorderLine::GetValueString(MapUnit eSrcUnit, RID_DASH_DOT, RID_DASH_DOT_DOT }; - OUString aStr = "(" + ::GetColorString( aColor ) + cpDelim; + OUString aStr = "(" + ::GetColorString(m_aColor) + cpDelim; if ( static_cast<int>(m_nStyle) < int(SAL_N_ELEMENTS(aStyleIds)) ) { - const char* pResId = aStyleIds[static_cast<int>(m_nStyle)]; + TranslateId pResId = aStyleIds[static_cast<int>(m_nStyle)]; aStr += EditResId(pResId); } else diff --git a/editeng/source/items/charhiddenitem.cxx b/editeng/source/items/charhiddenitem.cxx index 8d0753c91e68..ec2a0af3c703 100644 --- a/editeng/source/items/charhiddenitem.cxx +++ b/editeng/source/items/charhiddenitem.cxx @@ -20,6 +20,7 @@ #include <editeng/charhiddenitem.hxx> #include <editeng/editrids.hrc> #include <editeng/eerdll.hxx> +#include <unotools/resmgr.hxx> SvxCharHiddenItem::SvxCharHiddenItem( const bool bHidden, const sal_uInt16 nId ) : @@ -41,7 +42,7 @@ bool SvxCharHiddenItem::GetPresentation const IntlWrapper & /*rIntl*/ ) const { - const char* pId = RID_SVXITEMS_CHARHIDDEN_FALSE; + TranslateId pId = RID_SVXITEMS_CHARHIDDEN_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_CHARHIDDEN_TRUE; diff --git a/editeng/source/items/flditem.cxx b/editeng/source/items/flditem.cxx index dcb70605e8b6..b501d40ba968 100644 --- a/editeng/source/items/flditem.cxx +++ b/editeng/source/items/flditem.cxx @@ -18,7 +18,9 @@ */ #include <osl/file.hxx> +#include <utility> #include <vcl/metaact.hxx> +#include <svl/numformat.hxx> #include <svl/zforlist.hxx> #include <tools/urlobj.hxx> @@ -264,12 +266,12 @@ bool SvxFieldData::operator==( const SvxFieldData& rFld ) const MetaAction* SvxFieldData::createBeginComment() const { - return new MetaCommentAction( "FIELD_SEQ_BEGIN" ); + return new MetaCommentAction( "FIELD_SEQ_BEGIN"_ostr ); } MetaAction* SvxFieldData::createEndComment() { - return new MetaCommentAction( "FIELD_SEQ_END" ); + return new MetaCommentAction( "FIELD_SEQ_END"_ostr ); } @@ -426,7 +428,7 @@ OUString SvxDateField::GetFormatted( Date const & aDate, SvxDateFormat eFormat, MetaAction* SvxDateField::createBeginComment() const { - return new MetaCommentAction( "FIELD_SEQ_BEGIN" ); + return new MetaCommentAction( "FIELD_SEQ_BEGIN"_ostr ); } SvxURLField::SvxURLField() @@ -435,8 +437,8 @@ SvxURLField::SvxURLField() } -SvxURLField::SvxURLField( const OUString& rURL, const OUString& rRepres, SvxURLFormat eFmt ) - : aURL( rURL ), aRepresentation( rRepres ) +SvxURLField::SvxURLField( OUString _aURL, OUString aRepres, SvxURLFormat eFmt ) + : aURL(std::move( _aURL )), aRepresentation(std::move( aRepres )) { eFormat = eFmt; } @@ -464,7 +466,7 @@ bool SvxURLField::operator==( const SvxFieldData& rOther ) const MetaAction* SvxURLField::createBeginComment() const { // #i46618# Adding target URL to metafile comment - return new MetaCommentAction( "FIELD_SEQ_BEGIN", + return new MetaCommentAction( "FIELD_SEQ_BEGIN"_ostr, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()), 2*aURL.getLength() ); @@ -488,7 +490,7 @@ bool SvxPageTitleField::operator==( const SvxFieldData& rCmp ) const MetaAction* SvxPageTitleField::createBeginComment() const { - return new MetaCommentAction( "FIELD_SEQ_BEGIN;PageTitleField" ); + return new MetaCommentAction( "FIELD_SEQ_BEGIN;PageTitleField"_ostr ); } // @@ -511,7 +513,7 @@ bool SvxPageField::operator==( const SvxFieldData& rCmp ) const MetaAction* SvxPageField::createBeginComment() const { - return new MetaCommentAction( "FIELD_SEQ_BEGIN;PageField" ); + return new MetaCommentAction( "FIELD_SEQ_BEGIN;PageField"_ostr ); } @@ -541,7 +543,7 @@ bool SvxTimeField::operator==( const SvxFieldData& rCmp ) const MetaAction* SvxTimeField::createBeginComment() const { - return new MetaCommentAction( "FIELD_SEQ_BEGIN" ); + return new MetaCommentAction( "FIELD_SEQ_BEGIN"_ostr ); } SvxFileField::SvxFileField() {} @@ -689,7 +691,7 @@ OUString SvxExtTimeField::GetFormatted( tools::Time const & aTime, SvxTimeFormat MetaAction* SvxExtTimeField::createBeginComment() const { - return new MetaCommentAction( "FIELD_SEQ_BEGIN" ); + return new MetaCommentAction( "FIELD_SEQ_BEGIN"_ostr ); } diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx index d8e82beb40b9..fa393ff4ccd8 100644 --- a/editeng/source/items/frmitems.cxx +++ b/editeng/source/items/frmitems.cxx @@ -33,11 +33,13 @@ #include <com/sun/star/frame/status/LeftRightMarginScale.hpp> #include <com/sun/star/drawing/ShadingPattern.hpp> #include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/util/XComplexColor.hpp> #include <osl/diagnose.h> #include <i18nutil/unicode.hxx> #include <unotools/ucbstreamhelper.hxx> #include <comphelper/processfactory.hxx> +#include <utility> #include <vcl/GraphicObject.hxx> #include <tools/urlobj.hxx> #include <tools/bigint.hxx> @@ -71,7 +73,10 @@ #include <libxml/xmlwriter.h> #include <o3tl/enumrange.hxx> #include <o3tl/safeint.hxx> +#include <sal/log.hxx> #include <vcl/GraphicLoader.hxx> +#include <unotools/securityoptions.hxx> +#include <docmodel/uno/UnoComplexColor.hxx> #include <boost/property_tree/ptree.hpp> @@ -180,8 +185,8 @@ bool SvxSizeItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) { if(bConvert) { - aTmp.Height = convertMm100ToTwip(aTmp.Height); - aTmp.Width = convertMm100ToTwip(aTmp.Width); + aTmp.Height = o3tl::toTwips(aTmp.Height, o3tl::Length::mm100); + aTmp.Width = o3tl::toTwips(aTmp.Width, o3tl::Length::mm100); } m_aSize = Size( aTmp.Width, aTmp.Height ); } @@ -197,7 +202,7 @@ bool SvxSizeItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= nVal )) return false; - m_aSize.setWidth( bConvert ? convertMm100ToTwip(nVal) : nVal ); + m_aSize.setWidth( bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal ); } break; case MID_SIZE_HEIGHT: @@ -206,7 +211,7 @@ bool SvxSizeItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= nVal)) return true; - m_aSize.setHeight( bConvert ? convertMm100ToTwip(nVal) : nVal ); + m_aSize.setHeight( bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal ); } break; default: OSL_FAIL("Wrong MemberId!"); @@ -282,19 +287,16 @@ bool SvxSizeItem::HasMetrics() const } -SvxLRSpaceItem::SvxLRSpaceItem( const sal_uInt16 nId ) : - - SfxPoolItem( nId ), - - nTxtLeft ( 0 ), - nLeftMargin ( 0 ), - nRightMargin ( 0 ), - m_nGutterMargin(0), - m_nRightGutterMargin(0), +SvxLRSpaceItem::SvxLRSpaceItem(const sal_uInt16 nId) + : SfxPoolItem(nId) + , nFirstLineOffset(0) + , nLeftMargin(0) + , nRightMargin(0) + , m_nGutterMargin(0) + , m_nRightGutterMargin(0), nPropFirstLineOffset( 100 ), nPropLeftMargin( 100 ), nPropRightMargin( 100 ), - nFirstLineOffset ( 0 ), bAutoFirst ( false ), bExplicitZeroMarginValRight(false), bExplicitZeroMarginValLeft(false) @@ -303,19 +305,17 @@ SvxLRSpaceItem::SvxLRSpaceItem( const sal_uInt16 nId ) : SvxLRSpaceItem::SvxLRSpaceItem( const tools::Long nLeft, const tools::Long nRight, - const tools::Long nTLeft, const short nOfset, + const short nOfset, const sal_uInt16 nId ) -: SfxPoolItem( nId ), - - nTxtLeft ( nTLeft ), - nLeftMargin ( nLeft ), - nRightMargin ( nRight ), - m_nGutterMargin(0), - m_nRightGutterMargin(0), + : SfxPoolItem(nId) + , nFirstLineOffset(nOfset) + , nLeftMargin(nLeft) + , nRightMargin(nRight) + , m_nGutterMargin(0) + , m_nRightGutterMargin(0), nPropFirstLineOffset( 100 ), nPropLeftMargin( 100 ), nPropRightMargin( 100 ), - nFirstLineOffset ( nOfset ), bAutoFirst ( false ), bExplicitZeroMarginValRight(false), bExplicitZeroMarginValLeft(false) @@ -335,7 +335,7 @@ bool SvxLRSpaceItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const { css::frame::status::LeftRightMarginScale aLRSpace; aLRSpace.Left = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nLeftMargin) : nLeftMargin); - aLRSpace.TextLeft = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nTxtLeft) : nTxtLeft); + aLRSpace.TextLeft = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetTextLeft()) : GetTextLeft()); aLRSpace.Right = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nRightMargin) : nRightMargin); aLRSpace.ScaleLeft = static_cast<sal_Int16>(nPropLeftMargin); aLRSpace.ScaleRight = static_cast<sal_Int16>(nPropRightMargin); @@ -350,7 +350,7 @@ bool SvxLRSpaceItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const break; case MID_TXT_LMARGIN : - rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nTxtLeft) : nTxtLeft); + rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetTextLeft()) : GetTextLeft()); break; case MID_R_MARGIN: rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nRightMargin) : nRightMargin); @@ -406,26 +406,26 @@ bool SvxLRSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= aLRSpace)) return false; - SetLeft( bConvert ? convertMm100ToTwip(aLRSpace.Left) : aLRSpace.Left ); - SetTextLeft( bConvert ? convertMm100ToTwip(aLRSpace.TextLeft) : aLRSpace.TextLeft ); - SetRight(bConvert ? convertMm100ToTwip(aLRSpace.Right) : aLRSpace.Right); + SetLeft( bConvert ? o3tl::toTwips(aLRSpace.Left, o3tl::Length::mm100) : aLRSpace.Left ); + SetTextLeft( bConvert ? o3tl::toTwips(aLRSpace.TextLeft, o3tl::Length::mm100) : aLRSpace.TextLeft ); + SetRight(bConvert ? o3tl::toTwips(aLRSpace.Right, o3tl::Length::mm100) : aLRSpace.Right); nPropLeftMargin = aLRSpace.ScaleLeft; nPropRightMargin = aLRSpace.ScaleRight; - SetTextFirstLineOffset(static_cast<short>(bConvert ? convertMm100ToTwip(aLRSpace.FirstLine) : aLRSpace.FirstLine)); - SetPropTextFirstLineOffset ( static_cast<sal_uInt16>(aLRSpace.ScaleFirstLine) ); + SetTextFirstLineOffset(bConvert ? o3tl::toTwips(aLRSpace.FirstLine, o3tl::Length::mm100) : aLRSpace.FirstLine); + SetPropTextFirstLineOffset ( aLRSpace.ScaleFirstLine ); SetAutoFirst( aLRSpace.AutoFirstLine ); break; } case MID_L_MARGIN: - SetLeft( bConvert ? convertMm100ToTwip(nVal) : nVal ); + SetLeft( bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal ); break; case MID_TXT_LMARGIN : - SetTextLeft( bConvert ? convertMm100ToTwip(nVal) : nVal ); + SetTextLeft( bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal ); break; case MID_R_MARGIN: - SetRight(bConvert ? convertMm100ToTwip(nVal) : nVal); + SetRight(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); break; case MID_L_REL_MARGIN: case MID_R_REL_MARGIN: @@ -443,11 +443,11 @@ bool SvxLRSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) } break; case MID_FIRST_LINE_INDENT : - SetTextFirstLineOffset(static_cast<short>(bConvert ? convertMm100ToTwip(nVal) : nVal)); + SetTextFirstLineOffset(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); break; case MID_FIRST_LINE_REL_INDENT: - SetPropTextFirstLineOffset ( static_cast<sal_uInt16>(nVal) ); + SetPropTextFirstLineOffset ( nVal ); break; case MID_FIRST_AUTO: @@ -455,7 +455,7 @@ bool SvxLRSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) break; case MID_GUTTER_MARGIN: - SetGutterMargin(bConvert ? convertMm100ToTwip(nVal) : nVal); + SetGutterMargin(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); break; default: @@ -465,16 +465,1029 @@ bool SvxLRSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) return true; } +void SvxLeftMarginItem::SetLeft(const tools::Long nL, const sal_uInt16 nProp) +{ + m_nLeftMargin = (nL * nProp) / 100; + m_nPropLeftMargin = nProp; +} + +void SvxLRSpaceItem::SetLeft(const tools::Long nL, const sal_uInt16 nProp) +{ + nLeftMargin = (nL * nProp) / 100; + SAL_WARN_IF(nFirstLineOffset != 0, "editeng", "probably call SetTextLeft instead? looks inconsistent otherwise"); + nPropLeftMargin = nProp; +} + +void SvxRightMarginItem::SetRight(const tools::Long nR, const sal_uInt16 nProp) +{ + m_nRightMargin = (nR * nProp) / 100; + m_nPropRightMargin = nProp; +} + +void SvxLRSpaceItem::SetRight(const tools::Long nR, const sal_uInt16 nProp) +{ + if (0 == nR) + { + SetExplicitZeroMarginValRight(true); + } + nRightMargin = (nR * nProp) / 100; + nPropRightMargin = nProp; +} + +void SvxFirstLineIndentItem::SetTextFirstLineOffset( + const short nF, const sal_uInt16 nProp) +{ + m_nFirstLineOffset = short((tools::Long(nF) * nProp ) / 100); + m_nPropFirstLineOffset = nProp; +} -/// Adapt nLeftMargin and nTxtLeft. -void SvxLRSpaceItem::AdjustLeft() +void SvxLRSpaceItem::SetTextFirstLineOffset(const short nF, const sal_uInt16 nProp) { + // note: left margin contains any negative first line offset - preserve it! + if (nFirstLineOffset < 0) + { + nLeftMargin -= nFirstLineOffset; + } + nFirstLineOffset = short((tools::Long(nF) * nProp ) / 100); + nPropFirstLineOffset = nProp; + if (nFirstLineOffset < 0) + { + nLeftMargin += nFirstLineOffset; + } +} + +#if 0 +void SvxTextLeftMarginItem::SetLeft(SvxFirstLineIndentItem const& rFirstLine, + const tools::Long nL, const sal_uInt16 nProp) +{ + m_nTextLeftMargin = (nL * nProp) / 100; + m_nPropLeftMargin = nProp; + // note: text left margin contains any negative first line offset + if (rFirstLine.GetTextFirstLineOffset() < 0) + { + m_nTextLeftMargin += rFirstLine.GetTextFirstLineOffset(); + } +} +#endif + +void SvxTextLeftMarginItem::SetTextLeft(const tools::Long nL, const sal_uInt16 nProp) +{ + m_nTextLeftMargin = (nL * nProp) / 100; + m_nPropLeftMargin = nProp; +} + +void SvxLRSpaceItem::SetTextLeft(const tools::Long nL, const sal_uInt16 nProp) +{ + if (0 == nL) + { + SetExplicitZeroMarginValLeft(true); + } + auto const nTxtLeft = (nL * nProp) / 100; + nPropLeftMargin = nProp; + // note: left margin contains any negative first line offset if ( 0 > nFirstLineOffset ) nLeftMargin = nTxtLeft + nFirstLineOffset; else nLeftMargin = nTxtLeft; } +tools::Long SvxTextLeftMarginItem::GetTextLeft() const +{ + return m_nTextLeftMargin; +} + +tools::Long SvxTextLeftMarginItem::GetLeft(SvxFirstLineIndentItem const& rFirstLine) const +{ + // add any negative first line offset to text left margin to get left + return (rFirstLine.GetTextFirstLineOffset() < 0) + ? m_nTextLeftMargin + rFirstLine.GetTextFirstLineOffset() + : m_nTextLeftMargin; +} + +tools::Long SvxLRSpaceItem::GetTextLeft() const +{ + // remove any negative first line offset from left margin to get text-left + return (nFirstLineOffset < 0) + ? nLeftMargin - nFirstLineOffset + : nLeftMargin; +} + +SvxLeftMarginItem::SvxLeftMarginItem(const sal_uInt16 nId) + : SfxPoolItem(nId) +{ +} + +SvxLeftMarginItem::SvxLeftMarginItem(const tools::Long nLeft, const sal_uInt16 nId) + : SfxPoolItem(nId) + , m_nLeftMargin(nLeft) +{ +} + +bool SvxLeftMarginItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) const +{ + bool bRet = true; + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + switch (nMemberId) + { + case MID_L_MARGIN: + rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(m_nLeftMargin) : m_nLeftMargin); + break; + case MID_L_REL_MARGIN: + rVal <<= static_cast<sal_Int16>(m_nPropLeftMargin); + break; + default: + assert(false); + bRet = false; + // SfxDispatchController_Impl::StateChanged calls this with hardcoded 0 triggering this; there used to be a MID_LR_MARGIN 0 but what type would it have? + OSL_FAIL("unknown MemberId"); + } + return bRet; +} + +bool SvxLeftMarginItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId) +{ + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + + switch (nMemberId) + { + case MID_L_MARGIN: + { + sal_Int32 nVal = 0; + if (!(rVal >>= nVal)) + { + return false; + } + SetLeft(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); + break; + } + case MID_L_REL_MARGIN: + { + sal_Int32 nRel = 0; + if ((rVal >>= nRel) && nRel >= 0 && nRel < SAL_MAX_UINT16) + { + m_nPropLeftMargin = static_cast<sal_uInt16>(nRel); + } + else + { + return false; + } + } + break; + default: + assert(false); + OSL_FAIL("unknown MemberId"); + return false; + } + return true; +} + +bool SvxLeftMarginItem::operator==(const SfxPoolItem& rAttr) const +{ + assert(SfxPoolItem::operator==(rAttr)); + + const SvxLeftMarginItem& rOther = static_cast<const SvxLeftMarginItem&>(rAttr); + + return (m_nLeftMargin == rOther.GetLeft() + && m_nPropLeftMargin == rOther.GetPropLeft()); +} + +SvxLeftMarginItem* SvxLeftMarginItem::Clone(SfxItemPool *) const +{ + return new SvxLeftMarginItem(*this); +} + +bool SvxLeftMarginItem::GetPresentation +( + SfxItemPresentation ePres, + MapUnit eCoreUnit, + MapUnit ePresUnit, + OUString& rText, const IntlWrapper& rIntl +) const +{ + switch (ePres) + { + case SfxItemPresentation::Nameless: + { + if (100 != m_nPropLeftMargin) + { + rText = unicode::formatPercent(m_nPropLeftMargin, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText = GetMetricText(m_nLeftMargin, + eCoreUnit, ePresUnit, &rIntl); + } + return true; + } + case SfxItemPresentation::Complete: + { + rText = EditResId(RID_SVXITEMS_LRSPACE_LEFT); + if (100 != m_nPropLeftMargin) + { + rText += unicode::formatPercent(m_nPropLeftMargin, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText += GetMetricText(m_nLeftMargin, eCoreUnit, ePresUnit, &rIntl) + + " " + EditResId(GetMetricId(ePresUnit)); + } + return true; + } + default: ; // prevent warning + } + return false; +} + +void SvxLeftMarginItem::ScaleMetrics(tools::Long const nMult, tools::Long const nDiv) +{ + m_nLeftMargin = BigInt::Scale(m_nLeftMargin, nMult, nDiv); +} + +bool SvxLeftMarginItem::HasMetrics() const +{ + return true; +} + +void SvxLeftMarginItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxLeftMarginItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nLeftMargin"), BAD_CAST(OString::number(m_nLeftMargin).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nPropLeftMargin"), BAD_CAST(OString::number(m_nPropLeftMargin).getStr())); + (void)xmlTextWriterEndElement(pWriter); +} + +boost::property_tree::ptree SvxLeftMarginItem::dumpAsJSON() const +{ + boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON(); + + boost::property_tree::ptree aState; + + MapUnit eTargetUnit = MapUnit::MapInch; + + OUString sLeft = GetMetricText(GetLeft(), + MapUnit::MapTwip, eTargetUnit, nullptr); + + aState.put("left", sLeft); + aState.put("unit", "inch"); + + aTree.push_back(std::make_pair("state", aState)); + + return aTree; +} + +SvxTextLeftMarginItem::SvxTextLeftMarginItem(const sal_uInt16 nId) + : SfxPoolItem(nId) +{ +} + +SvxTextLeftMarginItem::SvxTextLeftMarginItem(const tools::Long nLeft, const sal_uInt16 nId) + : SfxPoolItem(nId) + , m_nTextLeftMargin(nLeft) +{ +} + +bool SvxTextLeftMarginItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) const +{ + bool bRet = true; + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + switch (nMemberId) + { + // tdf#154282 - return both values for the hardcoded 0 in SfxDispatchController_Impl::StateChanged + case 0: + { + css::frame::status::LeftRightMarginScale aLRSpace; + aLRSpace.TextLeft = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetTextLeft()) : GetTextLeft()); + aLRSpace.ScaleLeft = static_cast<sal_Int16>(m_nPropLeftMargin); + rVal <<= aLRSpace; + break; + } + case MID_TXT_LMARGIN : + rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetTextLeft()) : GetTextLeft()); + break; + case MID_L_REL_MARGIN: + rVal <<= static_cast<sal_Int16>(m_nPropLeftMargin); + break; + default: + assert(false); + bRet = false; + // SfxDispatchController_Impl::StateChanged calls this with hardcoded 0 triggering this; there used to be a MID_LR_MARGIN 0 but what type would it have? + OSL_FAIL("unknown MemberId"); + } + return bRet; +} + +bool SvxTextLeftMarginItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId) +{ + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + + switch (nMemberId) + { + case MID_TXT_LMARGIN: + { + sal_Int32 nVal = 0; + if (!(rVal >>= nVal)) + { + return false; + } + SetTextLeft(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); + } + break; + case MID_L_REL_MARGIN: + { + sal_Int32 nRel = 0; + if ((rVal >>= nRel) && nRel >= 0 && nRel < SAL_MAX_UINT16) + { + m_nPropLeftMargin = static_cast<sal_uInt16>(nRel); + } + else + { + return false; + } + } + break; + default: + assert(false); + OSL_FAIL("unknown MemberId"); + return false; + } + return true; +} + +bool SvxTextLeftMarginItem::operator==(const SfxPoolItem& rAttr) const +{ + assert(SfxPoolItem::operator==(rAttr)); + + const SvxTextLeftMarginItem& rOther = static_cast<const SvxTextLeftMarginItem&>(rAttr); + + return (m_nTextLeftMargin == rOther.GetTextLeft() + && m_nPropLeftMargin == rOther.GetPropLeft()); +} + +SvxTextLeftMarginItem* SvxTextLeftMarginItem::Clone(SfxItemPool *) const +{ + return new SvxTextLeftMarginItem(*this); +} + +bool SvxTextLeftMarginItem::GetPresentation +( + SfxItemPresentation ePres, + MapUnit eCoreUnit, + MapUnit ePresUnit, + OUString& rText, const IntlWrapper& rIntl +) const +{ + switch (ePres) + { + case SfxItemPresentation::Nameless: + { + if (100 != m_nPropLeftMargin) + { + rText = unicode::formatPercent(m_nPropLeftMargin, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText = GetMetricText(m_nTextLeftMargin, + eCoreUnit, ePresUnit, &rIntl); + } + return true; + } + case SfxItemPresentation::Complete: + { + rText = EditResId(RID_SVXITEMS_LRSPACE_LEFT); + if (100 != m_nPropLeftMargin) + { + rText += unicode::formatPercent(m_nPropLeftMargin, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText += GetMetricText(m_nTextLeftMargin, eCoreUnit, ePresUnit, &rIntl) + + " " + EditResId(GetMetricId(ePresUnit)); + } + return true; + } + default: ; // prevent warning + } + return false; +} + +void SvxTextLeftMarginItem::ScaleMetrics(tools::Long const nMult, tools::Long const nDiv) +{ + m_nTextLeftMargin = BigInt::Scale(m_nTextLeftMargin, nMult, nDiv); +} + +bool SvxTextLeftMarginItem::HasMetrics() const +{ + return true; +} + +void SvxTextLeftMarginItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxTextLeftMarginItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nTextLeftMargin"), BAD_CAST(OString::number(m_nTextLeftMargin).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nPropLeftMargin"), BAD_CAST(OString::number(m_nPropLeftMargin).getStr())); + (void)xmlTextWriterEndElement(pWriter); +} + +boost::property_tree::ptree SvxTextLeftMarginItem::dumpAsJSON() const +{ + boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON(); + + boost::property_tree::ptree aState; + + MapUnit eTargetUnit = MapUnit::MapInch; + + OUString sLeft = GetMetricText(GetTextLeft(), + MapUnit::MapTwip, eTargetUnit, nullptr); + + aState.put("left", sLeft); + aState.put("unit", "inch"); + + aTree.push_back(std::make_pair("state", aState)); + + return aTree; +} + +SvxFirstLineIndentItem::SvxFirstLineIndentItem(const sal_uInt16 nId) + : SfxPoolItem(nId) +{ +} + +SvxFirstLineIndentItem::SvxFirstLineIndentItem(const short nFirst, const sal_uInt16 nId) + : SfxPoolItem(nId) + , m_nFirstLineOffset(nFirst) +{ +} + +bool SvxFirstLineIndentItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) const +{ + bool bRet = true; + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + switch (nMemberId) + { + case MID_FIRST_LINE_INDENT: + rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(m_nFirstLineOffset) : m_nFirstLineOffset); + break; + case MID_FIRST_LINE_REL_INDENT: + rVal <<= static_cast<sal_Int16>(m_nPropFirstLineOffset); + break; + case MID_FIRST_AUTO: + rVal <<= IsAutoFirst(); + break; + default: + assert(false); + bRet = false; + // SfxDispatchController_Impl::StateChanged calls this with hardcoded 0 triggering this; there used to be a MID_LR_MARGIN 0 but what type would it have? + OSL_FAIL("unknown MemberId"); + } + return bRet; +} + +bool SvxFirstLineIndentItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId) +{ + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + + switch (nMemberId) + { + case MID_FIRST_LINE_INDENT: + { + sal_Int32 nVal = 0; + if (!(rVal >>= nVal)) + { + return false; + } + m_nFirstLineOffset = bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal; + m_nPropFirstLineOffset = 100; + break; + } + case MID_FIRST_LINE_REL_INDENT: + { + sal_Int32 nRel = 0; + if ((rVal >>= nRel) && nRel >= 0 && nRel < SAL_MAX_UINT16) + { + SetPropTextFirstLineOffset(nRel); + } + else + { + return false; + } + break; + } + case MID_FIRST_AUTO: + SetAutoFirst(Any2Bool(rVal)); + break; + default: + assert(false); + OSL_FAIL("unknown MemberId"); + return false; + } + return true; +} + +bool SvxFirstLineIndentItem::operator==(const SfxPoolItem& rAttr) const +{ + assert(SfxPoolItem::operator==(rAttr)); + + const SvxFirstLineIndentItem& rOther = static_cast<const SvxFirstLineIndentItem&>(rAttr); + + return (m_nFirstLineOffset == rOther.GetTextFirstLineOffset() + && m_nPropFirstLineOffset == rOther.GetPropTextFirstLineOffset() + && m_bAutoFirst == rOther.IsAutoFirst()); +} + +SvxFirstLineIndentItem* SvxFirstLineIndentItem::Clone(SfxItemPool *) const +{ + return new SvxFirstLineIndentItem(*this); +} + +bool SvxFirstLineIndentItem::GetPresentation +( + SfxItemPresentation ePres, + MapUnit eCoreUnit, + MapUnit ePresUnit, + OUString& rText, const IntlWrapper& rIntl +) const +{ + switch (ePres) + { + case SfxItemPresentation::Nameless: + { + if (100 != m_nPropFirstLineOffset) + { + rText += unicode::formatPercent(m_nPropFirstLineOffset, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText += GetMetricText(static_cast<tools::Long>(m_nFirstLineOffset), + eCoreUnit, ePresUnit, &rIntl); + } + return true; + } + case SfxItemPresentation::Complete: + { + rText += EditResId(RID_SVXITEMS_LRSPACE_FLINE); + if (100 != m_nPropFirstLineOffset) + { + rText += unicode::formatPercent(m_nPropFirstLineOffset, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText += GetMetricText(static_cast<tools::Long>(m_nFirstLineOffset), + eCoreUnit, ePresUnit, &rIntl) + + " " + EditResId(GetMetricId(ePresUnit)); + } + return true; + } + default: ; // prevent warning + } + return false; +} + +void SvxFirstLineIndentItem::ScaleMetrics(tools::Long const nMult, tools::Long const nDiv) +{ + m_nFirstLineOffset = static_cast<short>(BigInt::Scale(m_nFirstLineOffset, nMult, nDiv)); +} + +bool SvxFirstLineIndentItem::HasMetrics() const +{ + return true; +} + +void SvxFirstLineIndentItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxFirstLineIndentItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nFirstLineOffset"), BAD_CAST(OString::number(m_nFirstLineOffset).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nPropFirstLineOffset"), BAD_CAST(OString::number(m_nPropFirstLineOffset).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_bAutoFirst"), BAD_CAST(OString::number(int(m_bAutoFirst)).getStr())); + (void)xmlTextWriterEndElement(pWriter); +} + +boost::property_tree::ptree SvxFirstLineIndentItem::dumpAsJSON() const +{ + boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON(); + + boost::property_tree::ptree aState; + + MapUnit eTargetUnit = MapUnit::MapInch; + + OUString sFirstline = GetMetricText(GetTextFirstLineOffset(), + MapUnit::MapTwip, eTargetUnit, nullptr); + + aState.put("firstline", sFirstline); + aState.put("unit", "inch"); + + aTree.push_back(std::make_pair("state", aState)); + + return aTree; +} + +SvxRightMarginItem::SvxRightMarginItem(const sal_uInt16 nId) + : SfxPoolItem(nId) +{ +} + +SvxRightMarginItem::SvxRightMarginItem(const tools::Long nRight, const sal_uInt16 nId) + : SfxPoolItem(nId) + , m_nRightMargin(nRight) +{ +} + +bool SvxRightMarginItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) const +{ + bool bRet = true; + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + switch (nMemberId) + { + // tdf#154282 - return both values for the hardcoded 0 in SfxDispatchController_Impl::StateChanged + case 0: + { + css::frame::status::LeftRightMarginScale aLRSpace; + aLRSpace.Right = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(m_nRightMargin) : m_nRightMargin); + aLRSpace.ScaleRight = static_cast<sal_Int16>(m_nPropRightMargin); + rVal <<= aLRSpace; + break; + } + case MID_R_MARGIN: + rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(m_nRightMargin) : m_nRightMargin); + break; + case MID_R_REL_MARGIN: + rVal <<= static_cast<sal_Int16>(m_nPropRightMargin); + break; + default: + assert(false); + bRet = false; + // SfxDispatchController_Impl::StateChanged calls this with hardcoded 0 triggering this; there used to be a MID_LR_MARGIN 0 but what type would it have? + OSL_FAIL("unknown MemberId"); + } + return bRet; +} + +bool SvxRightMarginItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId) +{ + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + + switch (nMemberId) + { + case MID_R_MARGIN: + { + sal_Int32 nVal = 0; + if (!(rVal >>= nVal)) + { + return false; + } + SetRight(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); + break; + } + case MID_R_REL_MARGIN: + { + sal_Int32 nRel = 0; + if ((rVal >>= nRel) && nRel >= 0 && nRel < SAL_MAX_UINT16) + { + m_nPropRightMargin = static_cast<sal_uInt16>(nRel); + } + else + { + return false; + } + } + break; + default: + assert(false); + OSL_FAIL("unknown MemberId"); + return false; + } + return true; +} + +bool SvxRightMarginItem::operator==(const SfxPoolItem& rAttr) const +{ + assert(SfxPoolItem::operator==(rAttr)); + + const SvxRightMarginItem& rOther = static_cast<const SvxRightMarginItem&>(rAttr); + + return (m_nRightMargin == rOther.GetRight() + && m_nPropRightMargin == rOther.GetPropRight()); +} + +SvxRightMarginItem* SvxRightMarginItem::Clone(SfxItemPool *) const +{ + return new SvxRightMarginItem(*this); +} + +bool SvxRightMarginItem::GetPresentation +( + SfxItemPresentation ePres, + MapUnit eCoreUnit, + MapUnit ePresUnit, + OUString& rText, const IntlWrapper& rIntl +) const +{ + switch (ePres) + { + case SfxItemPresentation::Nameless: + { + if (100 != m_nRightMargin) + { + rText += unicode::formatPercent(m_nRightMargin, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText += GetMetricText(m_nRightMargin, + eCoreUnit, ePresUnit, &rIntl); + } + return true; + } + case SfxItemPresentation::Complete: + { + rText += EditResId(RID_SVXITEMS_LRSPACE_RIGHT); + if (100 != m_nPropRightMargin) + { + rText += unicode::formatPercent(m_nPropRightMargin, + Application::GetSettings().GetUILanguageTag()); + } + else + { + rText += GetMetricText(m_nRightMargin, + eCoreUnit, ePresUnit, &rIntl) + + " " + EditResId(GetMetricId(ePresUnit)); + } + return true; + } + default: ; // prevent warning + } + return false; +} + +void SvxRightMarginItem::ScaleMetrics(tools::Long const nMult, tools::Long const nDiv) +{ + m_nRightMargin = BigInt::Scale(m_nRightMargin, nMult, nDiv); +} + +bool SvxRightMarginItem::HasMetrics() const +{ + return true; +} + +void SvxRightMarginItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxRightMarginItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nRightMargin"), BAD_CAST(OString::number(m_nRightMargin).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nPropRightMargin"), BAD_CAST(OString::number(m_nPropRightMargin).getStr())); + (void)xmlTextWriterEndElement(pWriter); +} + +boost::property_tree::ptree SvxRightMarginItem::dumpAsJSON() const +{ + boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON(); + + boost::property_tree::ptree aState; + + MapUnit eTargetUnit = MapUnit::MapInch; + + OUString sRight = GetMetricText(GetRight(), + MapUnit::MapTwip, eTargetUnit, nullptr); + + aState.put("right", sRight); + aState.put("unit", "inch"); + + aTree.push_back(std::make_pair("state", aState)); + + return aTree; +} + +SvxGutterLeftMarginItem::SvxGutterLeftMarginItem(const sal_uInt16 nId) + : SfxPoolItem(nId) +{ +} + +bool SvxGutterLeftMarginItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) const +{ + bool bRet = true; + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + switch (nMemberId) + { + case MID_GUTTER_MARGIN: + rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(m_nGutterMargin) + : m_nGutterMargin); + break; + default: + assert(false); + bRet = false; + // SfxDispatchController_Impl::StateChanged calls this with hardcoded 0 triggering this; there used to be a MID_LR_MARGIN 0 but what type would it have? + OSL_FAIL("unknown MemberId"); + } + return bRet; +} + +bool SvxGutterLeftMarginItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId) +{ + bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + + switch (nMemberId) + { + case MID_GUTTER_MARGIN: + { + sal_Int32 nVal = 0; + if (!(rVal >>= nVal)) + { + return false; + } + SetGutterMargin(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); + break; + } + default: + assert(false); + OSL_FAIL("unknown MemberId"); + return false; + } + return true; +} + +bool SvxGutterLeftMarginItem::operator==(const SfxPoolItem& rAttr) const +{ + assert(SfxPoolItem::operator==(rAttr)); + + const SvxGutterLeftMarginItem& rOther = static_cast<const SvxGutterLeftMarginItem&>(rAttr); + + return (m_nGutterMargin == rOther.GetGutterMargin()); +} + +SvxGutterLeftMarginItem* SvxGutterLeftMarginItem::Clone(SfxItemPool * ) const +{ + return new SvxGutterLeftMarginItem(*this); +} + +bool SvxGutterLeftMarginItem::GetPresentation +( + SfxItemPresentation /*ePres*/, + MapUnit /*eCoreUnit*/, + MapUnit /*ePresUnit*/, + OUString& /*rText*/, const IntlWrapper& /*rIntl*/ +) const +{ + // TODO? + return false; +} + +void SvxGutterLeftMarginItem::ScaleMetrics(tools::Long const /*nMult*/, tools::Long const /*nDiv*/) +{ + // TODO? +} + +bool SvxGutterLeftMarginItem::HasMetrics() const +{ + return true; +} + +void SvxGutterLeftMarginItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxGutterLeftMarginItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nGutterMargin"), + BAD_CAST(OString::number(m_nGutterMargin).getStr())); + (void)xmlTextWriterEndElement(pWriter); +} + +boost::property_tree::ptree SvxGutterLeftMarginItem::dumpAsJSON() const +{ + boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON(); + + boost::property_tree::ptree aState; + + // TODO? + aState.put("unit", "inch"); + + aTree.push_back(std::make_pair("state", aState)); + + return aTree; +} + +SvxGutterRightMarginItem::SvxGutterRightMarginItem(const sal_uInt16 nId) + : SfxPoolItem(nId) +{ +} + +bool SvxGutterRightMarginItem::QueryValue(uno::Any& /*rVal*/, sal_uInt8 nMemberId) const +{ + bool bRet = true; + //bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; +#ifndef _MSC_VER + switch (nMemberId) + { + // TODO? + default: + assert(false); + bRet = false; + // SfxDispatchController_Impl::StateChanged calls this with hardcoded 0 triggering this; there used to be a MID_LR_MARGIN 0 but what type would it have? + OSL_FAIL("unknown MemberId"); + } +#else + (void) nMemberId; +#endif + return bRet; +} + +bool SvxGutterRightMarginItem::PutValue(const uno::Any& /*rVal*/, sal_uInt8 nMemberId) +{ + //bool bConvert = 0 != (nMemberId & CONVERT_TWIPS); + nMemberId &= ~CONVERT_TWIPS; + +#ifndef _MSC_VER + switch (nMemberId) + { + // TODO? + default: + assert(false); + OSL_FAIL("unknown MemberId"); + return false; + } +#else + (void) nMemberId; +#endif + return true; +} + + +bool SvxGutterRightMarginItem::operator==(const SfxPoolItem& rAttr) const +{ + assert(SfxPoolItem::operator==(rAttr)); + + const SvxGutterRightMarginItem& rOther = static_cast<const SvxGutterRightMarginItem&>(rAttr); + + return (m_nRightGutterMargin == rOther.GetRightGutterMargin()); +} + +SvxGutterRightMarginItem* SvxGutterRightMarginItem::Clone(SfxItemPool *) const +{ + return new SvxGutterRightMarginItem(*this); +} + +bool SvxGutterRightMarginItem::GetPresentation +( + SfxItemPresentation /*ePres*/, + MapUnit /*eCoreUnit*/, + MapUnit /*ePresUnit*/, + OUString& /*rText*/, const IntlWrapper& /*rIntl*/ +) const +{ + // TODO? + return false; +} + +void SvxGutterRightMarginItem::ScaleMetrics(tools::Long const /*nMult*/, tools::Long const /*nDiv*/) +{ + // TODO? +} + +bool SvxGutterRightMarginItem::HasMetrics() const +{ + return true; +} + +void SvxGutterRightMarginItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxGutterRightMarginItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nRightGutterMargin"), + BAD_CAST(OString::number(m_nRightGutterMargin).getStr())); + (void)xmlTextWriterEndElement(pWriter); +} + +boost::property_tree::ptree SvxGutterRightMarginItem::dumpAsJSON() const +{ + boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON(); + + boost::property_tree::ptree aState; + + // TODO? + aState.put("unit", "inch"); + + aTree.push_back(std::make_pair("state", aState)); + + return aTree; +} + bool SvxLRSpaceItem::operator==( const SfxPoolItem& rAttr ) const { @@ -484,7 +1497,6 @@ bool SvxLRSpaceItem::operator==( const SfxPoolItem& rAttr ) const return ( nFirstLineOffset == rOther.GetTextFirstLineOffset() && - nTxtLeft == rOther.GetTextLeft() && m_nGutterMargin == rOther.GetGutterMargin() && m_nRightGutterMargin == rOther.GetRightGutterMargin() && nLeftMargin == rOther.GetLeft() && @@ -589,7 +1601,6 @@ bool SvxLRSpaceItem::GetPresentation void SvxLRSpaceItem::ScaleMetrics( tools::Long nMult, tools::Long nDiv ) { nFirstLineOffset = static_cast<short>(BigInt::Scale( nFirstLineOffset, nMult, nDiv )); - nTxtLeft = BigInt::Scale( nTxtLeft, nMult, nDiv ); nLeftMargin = BigInt::Scale( nLeftMargin, nMult, nDiv ); nRightMargin = BigInt::Scale( nRightMargin, nMult, nDiv ); } @@ -606,7 +1617,6 @@ void SvxLRSpaceItem::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxLRSpaceItem")); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nFirstLineOffset"), BAD_CAST(OString::number(nFirstLineOffset).getStr())); - (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nTxtLeft"), BAD_CAST(OString::number(nTxtLeft).getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nLeftMargin"), BAD_CAST(OString::number(nLeftMargin).getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nRightMargin"), BAD_CAST(OString::number(nRightMargin).getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nGutterMargin"), @@ -715,8 +1725,8 @@ bool SvxULSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if ( !(rVal >>= aUpperLowerMarginScale )) return false; { - SetUpper(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip( aUpperLowerMarginScale.Upper ) : aUpperLowerMarginScale.Upper)); - SetLower(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip( aUpperLowerMarginScale.Lower ) : aUpperLowerMarginScale.Lower)); + SetUpper(bConvert ? o3tl::toTwips(aUpperLowerMarginScale.Upper, o3tl::Length::mm100) : aUpperLowerMarginScale.Upper); + SetLower(bConvert ? o3tl::toTwips(aUpperLowerMarginScale.Lower, o3tl::Length::mm100) : aUpperLowerMarginScale.Lower); if( aUpperLowerMarginScale.ScaleUpper > 1 ) nPropUpper = aUpperLowerMarginScale.ScaleUpper; if( aUpperLowerMarginScale.ScaleLower > 1 ) @@ -727,12 +1737,12 @@ bool SvxULSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) case MID_UP_MARGIN : if(!(rVal >>= nVal)) return false; - SetUpper(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip(nVal) : nVal)); + SetUpper(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); break; case MID_LO_MARGIN : if(!(rVal >>= nVal) || nVal < 0) return false; - SetLower(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip(nVal) : nVal)); + SetLower(bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal); break; case MID_CTX_MARGIN : if (!(rVal >>= bVal)) @@ -903,7 +1913,7 @@ bool SvxPrintItem::GetPresentation OUString& rText, const IntlWrapper& ) const { - const char* pId = RID_SVXITEMS_PRINT_FALSE; + TranslateId pId = RID_SVXITEMS_PRINT_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_PRINT_TRUE; @@ -924,7 +1934,7 @@ bool SvxOpaqueItem::GetPresentation OUString& rText, const IntlWrapper& ) const { - const char* pId = RID_SVXITEMS_OPAQUE_FALSE; + TranslateId pId = RID_SVXITEMS_OPAQUE_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_OPAQUE_TRUE; @@ -992,7 +2002,7 @@ bool SvxProtectItem::GetPresentation OUString& rText, const IntlWrapper& ) const { - const char* pId = RID_SVXITEMS_PROT_CONTENT_FALSE; + TranslateId pId = RID_SVXITEMS_PROT_CONTENT_FALSE; if ( bCntnt ) pId = RID_SVXITEMS_PROT_CONTENT_TRUE; @@ -1124,7 +2134,7 @@ bool SvxShadowItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) default: ; // prevent warning } - nWidth = bConvert ? convertMm100ToTwip(aShadow.ShadowWidth) : aShadow.ShadowWidth; + nWidth = bConvert ? o3tl::toTwips(aShadow.ShadowWidth, o3tl::Length::mm100) : aShadow.ShadowWidth; Color aSet(ColorTransparency, aShadow.Color); aShadowColor = aSet; } @@ -1184,7 +2194,7 @@ sal_uInt16 SvxShadowItem::CalcShadowSpace( SvxShadowItemSide nShadow ) const return nSpace; } -static const char* RID_SVXITEMS_SHADOW[] = +static TranslateId RID_SVXITEMS_SHADOW[] = { RID_SVXITEMS_SHADOW_NONE, RID_SVXITEMS_SHADOW_TOPLEFT, @@ -1206,7 +2216,7 @@ bool SvxShadowItem::GetPresentation case SfxItemPresentation::Nameless: { rText = ::GetColorString( aShadowColor ) + cpDelim; - const char* pId = RID_SVXITEMS_TRANSPARENT_FALSE; + TranslateId pId = RID_SVXITEMS_TRANSPARENT_FALSE; if ( aShadowColor.IsTransparent() ) pId = RID_SVXITEMS_TRANSPARENT_TRUE; @@ -1223,7 +2233,7 @@ bool SvxShadowItem::GetPresentation ::GetColorString( aShadowColor ) + cpDelim; - const char* pId = RID_SVXITEMS_TRANSPARENT_FALSE; + TranslateId pId = RID_SVXITEMS_TRANSPARENT_FALSE; if ( aShadowColor.IsTransparent() ) pId = RID_SVXITEMS_TRANSPARENT_TRUE; rText += EditResId(pId) + @@ -1281,29 +2291,24 @@ void SvxShadowItem::dumpAsXml(xmlTextWriterPtr pWriter) const // class SvxBoxItem ------------------------------------------------------ -SvxBoxItem::SvxBoxItem( const SvxBoxItem& rCpy ) : - - SfxPoolItem ( rCpy ), - pTop ( rCpy.pTop ? new SvxBorderLine( *rCpy.pTop ) : nullptr ), - pBottom ( rCpy.pBottom ? new SvxBorderLine( *rCpy.pBottom ) : nullptr ), - pLeft ( rCpy.pLeft ? new SvxBorderLine( *rCpy.pLeft ) : nullptr ), - pRight ( rCpy.pRight ? new SvxBorderLine( *rCpy.pRight ) : nullptr ), - nTopDist ( rCpy.nTopDist ), - nBottomDist ( rCpy.nBottomDist ), - nLeftDist ( rCpy.nLeftDist ), - nRightDist ( rCpy.nRightDist ), - bRemoveAdjCellBorder ( rCpy.bRemoveAdjCellBorder ) +SvxBoxItem::SvxBoxItem(const SvxBoxItem& rCopy) + : SfxPoolItem (rCopy) + , mpTopBorderLine(rCopy.mpTopBorderLine ? new SvxBorderLine(*rCopy.mpTopBorderLine) : nullptr) + , mpBottomBorderLine(rCopy.mpBottomBorderLine ? new SvxBorderLine(*rCopy.mpBottomBorderLine) : nullptr) + , mpLeftBorderLine(rCopy.mpLeftBorderLine ? new SvxBorderLine(*rCopy.mpLeftBorderLine) : nullptr) + , mpRightBorderLine(rCopy.mpRightBorderLine ? new SvxBorderLine(*rCopy.mpRightBorderLine) : nullptr) + , mnTopDistance(rCopy.mnTopDistance) + , mnBottomDistance(rCopy.mnBottomDistance) + , mnLeftDistance(rCopy.mnLeftDistance) + , mnRightDistance(rCopy.mnRightDistance) + , maTempComplexColors(rCopy.maTempComplexColors) + , mbRemoveAdjCellBorder(rCopy.mbRemoveAdjCellBorder) { } -SvxBoxItem::SvxBoxItem( const sal_uInt16 nId ) : - SfxPoolItem( nId ), - nTopDist ( 0 ), - nBottomDist ( 0 ), - nLeftDist ( 0 ), - nRightDist ( 0 ), - bRemoveAdjCellBorder ( false ) +SvxBoxItem::SvxBoxItem(const sal_uInt16 nId) + : SfxPoolItem(nId) { } @@ -1312,6 +2317,20 @@ SvxBoxItem::~SvxBoxItem() { } +void SvxBoxItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxBoxItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("top-dist"), + BAD_CAST(OString::number(mnTopDistance).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("bottom-dist"), + BAD_CAST(OString::number(mnBottomDistance).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("left-dist"), + BAD_CAST(OString::number(mnLeftDistance).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("right-dist"), + BAD_CAST(OString::number(mnRightDistance).getStr())); + SfxPoolItem::dumpAsXml(pWriter); + (void)xmlTextWriterEndElement(pWriter); +} boost::property_tree::ptree SvxBoxItem::dumpAsJSON() const { @@ -1330,7 +2349,7 @@ boost::property_tree::ptree SvxBoxItem::dumpAsJSON() const } -static bool CmpBrdLn( const std::unique_ptr<SvxBorderLine> & pBrd1, const SvxBorderLine* pBrd2 ) +static bool CompareBorderLine(const std::unique_ptr<SvxBorderLine> & pBrd1, const SvxBorderLine* pBrd2) { if( pBrd1.get() == pBrd2 ) return true; @@ -1346,15 +2365,16 @@ bool SvxBoxItem::operator==( const SfxPoolItem& rAttr ) const const SvxBoxItem& rBoxItem = static_cast<const SvxBoxItem&>(rAttr); return ( - ( nTopDist == rBoxItem.nTopDist ) && - ( nBottomDist == rBoxItem.nBottomDist ) && - ( nLeftDist == rBoxItem.nLeftDist ) && - ( nRightDist == rBoxItem.nRightDist ) && - ( bRemoveAdjCellBorder == rBoxItem.bRemoveAdjCellBorder ) && - CmpBrdLn( pTop, rBoxItem.GetTop() ) && - CmpBrdLn( pBottom, rBoxItem.GetBottom() ) && - CmpBrdLn( pLeft, rBoxItem.GetLeft() ) && - CmpBrdLn( pRight, rBoxItem.GetRight() ) ); + (mnTopDistance == rBoxItem.mnTopDistance) && + (mnBottomDistance == rBoxItem.mnBottomDistance) && + (mnLeftDistance == rBoxItem.mnLeftDistance) && + (mnRightDistance == rBoxItem.mnRightDistance) && + (mbRemoveAdjCellBorder == rBoxItem.mbRemoveAdjCellBorder ) && + (maTempComplexColors == rBoxItem.maTempComplexColors) && + CompareBorderLine(mpTopBorderLine, rBoxItem.GetTop()) && + CompareBorderLine(mpBottomBorderLine, rBoxItem.GetBottom()) && + CompareBorderLine(mpLeftBorderLine, rBoxItem.GetLeft()) && + CompareBorderLine(mpRightBorderLine, rBoxItem.GetRight())); } @@ -1371,7 +2391,10 @@ table::BorderLine2 SvxBoxItem::SvxLineToLine(const SvxBorderLine* pLine, bool bC aLine.LineWidth = sal_uInt32( bConvert ? convertTwipToMm100( pLine->GetWidth( ) ) : pLine->GetWidth( ) ); } else + { aLine.Color = aLine.InnerLineWidth = aLine.OuterLineWidth = aLine.LineDistance = 0; + aLine.LineStyle = table::BorderLineStyle::NONE; // 0 is SOLID! + } return aLine; } @@ -1379,7 +2402,7 @@ bool SvxBoxItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const { bool bConvert = 0!=(nMemberId&CONVERT_TWIPS); table::BorderLine2 aRetLine; - sal_uInt16 nDist = 0; + sal_Int16 nDist = 0; bool bDistMember = false; nMemberId &= ~CONVERT_TWIPS; switch(nMemberId) @@ -1387,16 +2410,17 @@ bool SvxBoxItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const case 0: { // 4 Borders and 5 distances - uno::Sequence< uno::Any > aSeq( 9 ); - aSeq[0] <<= SvxBoxItem::SvxLineToLine(GetLeft(), bConvert); - aSeq[1] <<= SvxBoxItem::SvxLineToLine(GetRight(), bConvert); - aSeq[2] <<= SvxBoxItem::SvxLineToLine(GetBottom(), bConvert); - aSeq[3] <<= SvxBoxItem::SvxLineToLine(GetTop(), bConvert); - aSeq[4] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( GetSmallestDistance()) : GetSmallestDistance()); - aSeq[5] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nTopDist ) : nTopDist ); - aSeq[6] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nBottomDist ) : nBottomDist ); - aSeq[7] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nLeftDist ) : nLeftDist ); - aSeq[8] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nRightDist ) : nRightDist ); + uno::Sequence< uno::Any > aSeq{ + uno::Any(SvxBoxItem::SvxLineToLine(GetLeft(), bConvert)), + uno::Any(SvxBoxItem::SvxLineToLine(GetRight(), bConvert)), + uno::Any(SvxBoxItem::SvxLineToLine(GetBottom(), bConvert)), + uno::Any(SvxBoxItem::SvxLineToLine(GetTop(), bConvert)), + uno::Any(static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetSmallestDistance()) : GetSmallestDistance())), + uno::Any(static_cast<sal_Int32>(bConvert ? convertTwipToMm100(mnTopDistance) : mnTopDistance)), + uno::Any(static_cast<sal_Int32>(bConvert ? convertTwipToMm100(mnBottomDistance) : mnBottomDistance)), + uno::Any(static_cast<sal_Int32>(bConvert ? convertTwipToMm100(mnLeftDistance) : mnLeftDistance)), + uno::Any(static_cast<sal_Int32>(bConvert ? convertTwipToMm100(mnRightDistance) : mnRightDistance)) + }; rVal <<= aSeq; return true; } @@ -1421,21 +2445,69 @@ bool SvxBoxItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const bDistMember = true; break; case TOP_BORDER_DISTANCE: - nDist = nTopDist; + nDist = mnTopDistance; bDistMember = true; break; case BOTTOM_BORDER_DISTANCE: - nDist = nBottomDist; + nDist = mnBottomDistance; bDistMember = true; break; case LEFT_BORDER_DISTANCE: - nDist = nLeftDist; + nDist = mnLeftDistance; bDistMember = true; break; case RIGHT_BORDER_DISTANCE: - nDist = nRightDist; + nDist = mnRightDistance; bDistMember = true; break; + case MID_BORDER_BOTTOM_COLOR: + { + if (mpBottomBorderLine) + { + rVal <<= model::color::createXComplexColor(mpBottomBorderLine->getComplexColor()); + } + else if (maTempComplexColors[size_t(SvxBoxItemLine::BOTTOM)].getType() != model::ColorType::Unused) + { + rVal <<= model::color::createXComplexColor(maTempComplexColors[size_t(SvxBoxItemLine::BOTTOM)]); + } + return true; + } + case MID_BORDER_LEFT_COLOR: + { + if (mpLeftBorderLine) + { + rVal <<= model::color::createXComplexColor(mpLeftBorderLine->getComplexColor()); + } + else if (maTempComplexColors[size_t(SvxBoxItemLine::LEFT)].getType() != model::ColorType::Unused) + { + rVal <<= model::color::createXComplexColor(maTempComplexColors[size_t(SvxBoxItemLine::LEFT)]); + } + return true; + } + case MID_BORDER_RIGHT_COLOR: + { + if (mpRightBorderLine) + { + rVal <<= model::color::createXComplexColor(mpRightBorderLine->getComplexColor()); + } + else if (maTempComplexColors[size_t(SvxBoxItemLine::RIGHT)].getType() != model::ColorType::Unused) + { + rVal <<= model::color::createXComplexColor(maTempComplexColors[size_t(SvxBoxItemLine::RIGHT)]); + } + return true; + } + case MID_BORDER_TOP_COLOR: + { + if (mpTopBorderLine) + { + rVal <<= model::color::createXComplexColor(mpTopBorderLine->getComplexColor()); + } + else if (maTempComplexColors[size_t(SvxBoxItemLine::TOP)].getType() != model::ColorType::Unused) + { + rVal <<= model::color::createXComplexColor(maTempComplexColors[size_t(SvxBoxItemLine::TOP)]); + } + return true; + } case LINE_STYLE: case LINE_WIDTH: // it doesn't make sense to return a value for these since it's @@ -1461,9 +2533,9 @@ lcl_lineToSvxLine(const table::BorderLine& rLine, SvxBorderLine& rSvxLine, bool if ( bGuessWidth ) { rSvxLine.GuessLinesWidths( rSvxLine.GetBorderLineStyle(), - sal_uInt16( bConvert ? convertMm100ToTwip(rLine.OuterLineWidth) : rLine.OuterLineWidth ), - sal_uInt16( bConvert ? convertMm100ToTwip(rLine.InnerLineWidth) : rLine.InnerLineWidth ), - sal_uInt16( bConvert ? convertMm100ToTwip(rLine.LineDistance ) : rLine.LineDistance )); + bConvert ? o3tl::toTwips(rLine.OuterLineWidth, o3tl::Length::mm100) : rLine.OuterLineWidth, + bConvert ? o3tl::toTwips(rLine.InnerLineWidth, o3tl::Length::mm100) : rLine.InnerLineWidth, + bConvert ? o3tl::toTwips(rLine.LineDistance, o3tl::Length::mm100) : rLine.LineDistance ); } bool bRet = !rSvxLine.isEmpty(); @@ -1491,7 +2563,7 @@ SvxBoxItem::LineToSvxLine(const css::table::BorderLine2& rLine, SvxBorderLine& r bool bGuessWidth = true; if ( rLine.LineWidth ) { - rSvxLine.SetWidth( bConvert? convertMm100ToTwip( rLine.LineWidth ) : rLine.LineWidth ); + rSvxLine.SetWidth( bConvert? o3tl::toTwips(rLine.LineWidth, o3tl::Length::mm100) : rLine.LineWidth ); // fdo#46112: double does not necessarily mean symmetric // for backwards compatibility bGuessWidth = (SvxBorderLineStyle::DOUBLE == nStyle || SvxBorderLineStyle::DOUBLE_THIN == nStyle) && @@ -1558,10 +2630,11 @@ bool SvxBoxItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) { // 4 Borders and 5 distances const SvxBoxItemLine aBorders[] = { SvxBoxItemLine::LEFT, SvxBoxItemLine::RIGHT, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::TOP }; - for (int n(0); n != SAL_N_ELEMENTS(aBorders); ++n) + for (size_t n(0); n != std::size(aBorders); ++n) { if (!lcl_setLine(aSeq[n], *this, aBorders[n], bConvert)) return false; + tryMigrateComplexColor(aBorders[n]); } // WTH are the borders and the distances saved in different order? @@ -1572,11 +2645,11 @@ bool SvxBoxItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if ( aSeq[n] >>= nDist ) { if( bConvert ) - nDist = convertMm100ToTwip(nDist); + nDist = o3tl::toTwips(nDist, o3tl::Length::mm100); if ( n == 4 ) - SetAllDistances(sal_uInt16(nDist)); + SetAllDistances(nDist); else - SetDistance( sal_uInt16( nDist ), nLines[n-5] ); + SetDistance( nDist, nLines[n-5] ); } else return false; @@ -1649,7 +2722,7 @@ bool SvxBoxItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) tools::Long nWidth(0); rVal >>= nWidth; if( bConvert ) - nWidth = convertMm100ToTwip( nWidth ); + nWidth = o3tl::toTwips(nWidth, o3tl::Length::mm100); // Set the line Width on all borders for( SvxBoxItemLine n : o3tl::enumrange<SvxBoxItemLine>() ) @@ -1660,6 +2733,66 @@ bool SvxBoxItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) } } return true; + case MID_BORDER_BOTTOM_COLOR: + { + if (mpBottomBorderLine) + return mpBottomBorderLine->setComplexColorFromAny(rVal); + else + { + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rVal >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + maTempComplexColors[size_t(SvxBoxItemLine::BOTTOM)] = model::color::getFromXComplexColor(xComplexColor); + } + return true; + } + case MID_BORDER_LEFT_COLOR: + { + if (mpLeftBorderLine) + return mpLeftBorderLine->setComplexColorFromAny(rVal); + else + { + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rVal >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + maTempComplexColors[size_t(SvxBoxItemLine::LEFT)] = model::color::getFromXComplexColor(xComplexColor); + } + return true; + } + case MID_BORDER_RIGHT_COLOR: + { + if (mpRightBorderLine) + return mpRightBorderLine->setComplexColorFromAny(rVal); + else + { + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rVal >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + maTempComplexColors[size_t(SvxBoxItemLine::RIGHT)] = model::color::getFromXComplexColor(xComplexColor); + } + return true; + } + case MID_BORDER_TOP_COLOR: + { + if (mpTopBorderLine) + return mpTopBorderLine->setComplexColorFromAny(rVal); + else + { + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rVal >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + maTempComplexColors[size_t(SvxBoxItemLine::TOP)] = model::color::getFromXComplexColor(xComplexColor); + } + return true; + } } if( bDistMember || nMemberId == BORDER_DISTANCE ) @@ -1668,14 +2801,13 @@ bool SvxBoxItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= nDist)) return false; - if(nDist >= 0) { if( bConvert ) - nDist = convertMm100ToTwip(nDist); + nDist = o3tl::toTwips(nDist, o3tl::Length::mm100); if( nMemberId == BORDER_DISTANCE ) - SetAllDistances(sal_uInt16(nDist)); + SetAllDistances(nDist); else - SetDistance( sal_uInt16( nDist ), nLine ); + SetDistance( nDist, nLine ); } } else @@ -1734,6 +2866,7 @@ bool SvxBoxItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) bool bSet = SvxBoxItem::LineToSvxLine(aBorderLine, aLine, bConvert); SetLine(bSet ? &aLine : nullptr, nLine); + tryMigrateComplexColor(nLine); } return true; @@ -1759,112 +2892,111 @@ bool SvxBoxItem::GetPresentation { rText.clear(); - if ( pTop ) + if (mpTopBorderLine) { - rText = pTop->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; + rText = mpTopBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; } - if( !(pTop && pBottom && pLeft && pRight && - *pTop == *pBottom && *pTop == *pLeft && *pTop == *pRight) ) + if ( !(mpTopBorderLine && mpBottomBorderLine && mpLeftBorderLine && mpRightBorderLine && + *mpTopBorderLine == *mpBottomBorderLine && + *mpTopBorderLine == *mpLeftBorderLine && + *mpTopBorderLine == *mpRightBorderLine)) { - if ( pBottom ) + if (mpBottomBorderLine) { - rText += pBottom->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; + rText += mpBottomBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; } - if ( pLeft ) + if (mpLeftBorderLine) { - rText += pLeft->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; + rText += mpLeftBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; } - if ( pRight ) + if (mpRightBorderLine) { - rText += pRight->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; + rText += mpRightBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp; } } - rText += GetMetricText( static_cast<tools::Long>(nTopDist), eCoreUnit, ePresUnit, &rIntl ); - if( nTopDist != nBottomDist || nTopDist != nLeftDist || - nTopDist != nRightDist ) + rText += GetMetricText( static_cast<tools::Long>(mnTopDistance), eCoreUnit, ePresUnit, &rIntl ); + if (mnTopDistance != mnBottomDistance || + mnTopDistance != mnLeftDistance || + mnTopDistance != mnRightDistance) { rText += cpDelimTmp + - GetMetricText( static_cast<tools::Long>(nBottomDist), eCoreUnit, - ePresUnit, &rIntl ) + + GetMetricText( tools::Long(mnBottomDistance), eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp + - GetMetricText( static_cast<tools::Long>(nLeftDist), eCoreUnit, ePresUnit, &rIntl ) + + GetMetricText( tools::Long(mnLeftDistance), eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp + - GetMetricText( static_cast<tools::Long>(nRightDist), eCoreUnit, - ePresUnit, &rIntl ); + GetMetricText( tools::Long(mnRightDistance), eCoreUnit, ePresUnit, &rIntl ); } return true; } case SfxItemPresentation::Complete: { - if( !(pTop || pBottom || pLeft || pRight) ) + if (!(mpTopBorderLine || mpBottomBorderLine || mpLeftBorderLine || mpRightBorderLine)) { rText = EditResId(RID_SVXITEMS_BORDER_NONE) + cpDelimTmp; } else { rText = EditResId(RID_SVXITEMS_BORDER_COMPLETE); - if( pTop && pBottom && pLeft && pRight && - *pTop == *pBottom && *pTop == *pLeft && *pTop == *pRight ) + if (mpTopBorderLine && mpBottomBorderLine && mpLeftBorderLine && mpRightBorderLine && + *mpTopBorderLine == *mpBottomBorderLine && + *mpTopBorderLine == *mpLeftBorderLine && + *mpTopBorderLine == *mpRightBorderLine) { - rText += pTop->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + cpDelimTmp; + rText += mpTopBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + cpDelimTmp; } else { - if ( pTop ) + if (mpTopBorderLine) { rText += EditResId(RID_SVXITEMS_BORDER_TOP) + - pTop->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + + mpTopBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + cpDelimTmp; } - if ( pBottom ) + if (mpBottomBorderLine) { rText += EditResId(RID_SVXITEMS_BORDER_BOTTOM) + - pBottom->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + + mpBottomBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + cpDelimTmp; } - if ( pLeft ) + if (mpLeftBorderLine) { rText += EditResId(RID_SVXITEMS_BORDER_LEFT) + - pLeft->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + + mpLeftBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + cpDelimTmp; } - if ( pRight ) + if (mpRightBorderLine) { rText += EditResId(RID_SVXITEMS_BORDER_RIGHT) + - pRight->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + + mpRightBorderLine->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + cpDelimTmp; } } } rText += EditResId(RID_SVXITEMS_BORDER_DISTANCE); - if( nTopDist == nBottomDist && nTopDist == nLeftDist && - nTopDist == nRightDist ) + if (mnTopDistance == mnBottomDistance && + mnTopDistance == mnLeftDistance && + mnTopDistance == mnRightDistance) { - rText += GetMetricText( static_cast<tools::Long>(nTopDist), eCoreUnit, - ePresUnit, &rIntl ) + + rText += GetMetricText(tools::Long(mnTopDistance), eCoreUnit, ePresUnit, &rIntl ) + " " + EditResId(GetMetricId(ePresUnit)); } else { rText += EditResId(RID_SVXITEMS_BORDER_TOP) + - GetMetricText( static_cast<tools::Long>(nTopDist), eCoreUnit, - ePresUnit, &rIntl ) + + GetMetricText(tools::Long(mnTopDistance), eCoreUnit, ePresUnit, &rIntl) + " " + EditResId(GetMetricId(ePresUnit)) + cpDelimTmp + EditResId(RID_SVXITEMS_BORDER_BOTTOM) + - GetMetricText( static_cast<tools::Long>(nBottomDist), eCoreUnit, - ePresUnit, &rIntl ) + + GetMetricText(tools::Long(mnBottomDistance), eCoreUnit, ePresUnit, &rIntl) + " " + EditResId(GetMetricId(ePresUnit)) + cpDelimTmp + EditResId(RID_SVXITEMS_BORDER_LEFT) + - GetMetricText( static_cast<tools::Long>(nLeftDist), eCoreUnit, - ePresUnit, &rIntl ) + + GetMetricText(tools::Long(mnLeftDistance), eCoreUnit, ePresUnit, &rIntl) + " " + EditResId(GetMetricId(ePresUnit)) + cpDelimTmp + EditResId(RID_SVXITEMS_BORDER_RIGHT) + - GetMetricText( static_cast<tools::Long>(nRightDist), eCoreUnit, - ePresUnit, &rIntl ) + + GetMetricText(tools::Long(mnRightDistance), eCoreUnit, ePresUnit, &rIntl) + " " + EditResId(GetMetricId(ePresUnit)); } return true; @@ -1877,14 +3009,19 @@ bool SvxBoxItem::GetPresentation void SvxBoxItem::ScaleMetrics( tools::Long nMult, tools::Long nDiv ) { - if ( pTop ) pTop->ScaleMetrics( nMult, nDiv ); - if ( pBottom ) pBottom->ScaleMetrics( nMult, nDiv ); - if ( pLeft ) pLeft->ScaleMetrics( nMult, nDiv ); - if ( pRight ) pRight->ScaleMetrics( nMult, nDiv ); - nTopDist = static_cast<sal_uInt16>(BigInt::Scale( nTopDist, nMult, nDiv )); - nBottomDist = static_cast<sal_uInt16>(BigInt::Scale( nBottomDist, nMult, nDiv )); - nLeftDist = static_cast<sal_uInt16>(BigInt::Scale( nLeftDist, nMult, nDiv )); - nRightDist = static_cast<sal_uInt16>(BigInt::Scale( nRightDist, nMult, nDiv )); + if (mpTopBorderLine) + mpTopBorderLine->ScaleMetrics( nMult, nDiv ); + if (mpBottomBorderLine) + mpBottomBorderLine->ScaleMetrics( nMult, nDiv ); + if (mpLeftBorderLine) + mpLeftBorderLine->ScaleMetrics( nMult, nDiv ); + if (mpRightBorderLine) + mpRightBorderLine->ScaleMetrics( nMult, nDiv ); + + mnTopDistance = static_cast<sal_Int16>(BigInt::Scale(mnTopDistance, nMult, nDiv)); + mnBottomDistance = static_cast<sal_Int16>(BigInt::Scale(mnBottomDistance, nMult, nDiv)); + mnLeftDistance = static_cast<sal_Int16>(BigInt::Scale(mnLeftDistance, nMult, nDiv)); + mnRightDistance = static_cast<sal_Int16>(BigInt::Scale(mnRightDistance, nMult, nDiv)); } @@ -1901,16 +3038,16 @@ const SvxBorderLine *SvxBoxItem::GetLine( SvxBoxItemLine nLine ) const switch ( nLine ) { case SvxBoxItemLine::TOP: - pRet = pTop.get(); + pRet = mpTopBorderLine.get(); break; case SvxBoxItemLine::BOTTOM: - pRet = pBottom.get(); + pRet = mpBottomBorderLine.get(); break; case SvxBoxItemLine::LEFT: - pRet = pLeft.get(); + pRet = mpLeftBorderLine.get(); break; case SvxBoxItemLine::RIGHT: - pRet = pRight.get(); + pRet = mpRightBorderLine.get(); break; default: OSL_FAIL( "wrong line" ); @@ -1928,16 +3065,16 @@ void SvxBoxItem::SetLine( const SvxBorderLine* pNew, SvxBoxItemLine nLine ) switch ( nLine ) { case SvxBoxItemLine::TOP: - pTop = std::move( pTmp ); + mpTopBorderLine = std::move(pTmp); break; case SvxBoxItemLine::BOTTOM: - pBottom = std::move( pTmp ); + mpBottomBorderLine = std::move(pTmp); break; case SvxBoxItemLine::LEFT: - pLeft = std::move( pTmp ); + mpLeftBorderLine = std::move(pTmp); break; case SvxBoxItemLine::RIGHT: - pRight = std::move( pTmp ); + mpRightBorderLine = std::move(pTmp); break; default: OSL_FAIL( "wrong line" ); @@ -1948,58 +3085,62 @@ void SvxBoxItem::SetLine( const SvxBorderLine* pNew, SvxBoxItemLine nLine ) sal_uInt16 SvxBoxItem::GetSmallestDistance() const { // The smallest distance that is not 0 will be returned. - sal_uInt16 nDist = nTopDist; - if( nBottomDist && (!nDist || nBottomDist < nDist) ) - nDist = nBottomDist; - if( nLeftDist && (!nDist || nLeftDist < nDist) ) - nDist = nLeftDist; - if( nRightDist && (!nDist || nRightDist < nDist) ) - nDist = nRightDist; + sal_uInt16 nDist = mnTopDistance; + if (mnBottomDistance && (!nDist || mnBottomDistance < nDist)) + nDist = mnBottomDistance; + if (mnLeftDistance && (!nDist || mnLeftDistance < nDist)) + nDist = mnLeftDistance; + if (mnRightDistance && (!nDist || mnRightDistance < nDist)) + nDist = mnRightDistance; return nDist; } -sal_uInt16 SvxBoxItem::GetDistance( SvxBoxItemLine nLine ) const +sal_Int16 SvxBoxItem::GetDistance( SvxBoxItemLine nLine, bool bAllowNegative ) const { - sal_uInt16 nDist = 0; + sal_Int16 nDist = 0; switch ( nLine ) { case SvxBoxItemLine::TOP: - nDist = nTopDist; + nDist = mnTopDistance; break; case SvxBoxItemLine::BOTTOM: - nDist = nBottomDist; + nDist = mnBottomDistance; break; case SvxBoxItemLine::LEFT: - nDist = nLeftDist; + nDist = mnLeftDistance; break; case SvxBoxItemLine::RIGHT: - nDist = nRightDist; + nDist = mnRightDistance; break; default: OSL_FAIL( "wrong line" ); } + if (!bAllowNegative && nDist < 0) + { + nDist = 0; + } return nDist; } -void SvxBoxItem::SetDistance( sal_uInt16 nNew, SvxBoxItemLine nLine ) +void SvxBoxItem::SetDistance( sal_Int16 nNew, SvxBoxItemLine nLine ) { switch ( nLine ) { case SvxBoxItemLine::TOP: - nTopDist = nNew; + mnTopDistance = nNew; break; case SvxBoxItemLine::BOTTOM: - nBottomDist = nNew; + mnBottomDistance = nNew; break; case SvxBoxItemLine::LEFT: - nLeftDist = nNew; + mnLeftDistance = nNew; break; case SvxBoxItemLine::RIGHT: - nRightDist = nNew; + mnRightDistance = nNew; break; default: OSL_FAIL( "wrong line" ); @@ -2013,16 +3154,16 @@ sal_uInt16 SvxBoxItem::CalcLineWidth( SvxBoxItemLine nLine ) const switch ( nLine ) { case SvxBoxItemLine::TOP: - pTmp = pTop.get(); + pTmp = mpTopBorderLine.get(); break; case SvxBoxItemLine::BOTTOM: - pTmp = pBottom.get(); + pTmp = mpBottomBorderLine.get(); break; case SvxBoxItemLine::LEFT: - pTmp = pLeft.get(); + pTmp = mpLeftBorderLine.get(); break; case SvxBoxItemLine::RIGHT: - pTmp = pRight.get(); + pTmp = mpRightBorderLine.get(); break; default: OSL_FAIL( "wrong line" ); @@ -2034,27 +3175,27 @@ sal_uInt16 SvxBoxItem::CalcLineWidth( SvxBoxItemLine nLine ) const return nWidth; } -sal_uInt16 SvxBoxItem::CalcLineSpace( SvxBoxItemLine nLine, bool bEvenIfNoLine ) const +sal_Int16 SvxBoxItem::CalcLineSpace( SvxBoxItemLine nLine, bool bEvenIfNoLine, bool bAllowNegative ) const { SvxBorderLine* pTmp = nullptr; - sal_uInt16 nDist = 0; + sal_Int16 nDist = 0; switch ( nLine ) { case SvxBoxItemLine::TOP: - pTmp = pTop.get(); - nDist = nTopDist; + pTmp = mpTopBorderLine.get(); + nDist = mnTopDistance; break; case SvxBoxItemLine::BOTTOM: - pTmp = pBottom.get(); - nDist = nBottomDist; + pTmp = mpBottomBorderLine.get(); + nDist = mnBottomDistance; break; case SvxBoxItemLine::LEFT: - pTmp = pLeft.get(); - nDist = nLeftDist; + pTmp = mpLeftBorderLine.get(); + nDist = mnLeftDistance; break; case SvxBoxItemLine::RIGHT: - pTmp = pRight.get(); - nDist = nRightDist; + pTmp = mpRightBorderLine.get(); + nDist = mnRightDistance; break; default: OSL_FAIL( "wrong line" ); @@ -2066,9 +3207,44 @@ sal_uInt16 SvxBoxItem::CalcLineSpace( SvxBoxItemLine nLine, bool bEvenIfNoLine ) } else if( !bEvenIfNoLine ) nDist = 0; + + if (!bAllowNegative && nDist < 0) + { + nDist = 0; + } + return nDist; } +void SvxBoxItem::tryMigrateComplexColor(SvxBoxItemLine eLine) +{ + if (!GetLine(eLine)) + return; + + auto nIndex = size_t(eLine); + + if (maTempComplexColors[nIndex].getType() == model::ColorType::Unused) + return; + + switch (eLine) + { + case SvxBoxItemLine::TOP: + mpTopBorderLine->setComplexColor(maTempComplexColors[nIndex]); + break; + case SvxBoxItemLine::BOTTOM: + mpBottomBorderLine->setComplexColor(maTempComplexColors[nIndex]); + break; + case SvxBoxItemLine::LEFT: + mpLeftBorderLine->setComplexColor(maTempComplexColors[nIndex]); + break; + case SvxBoxItemLine::RIGHT: + mpRightBorderLine->setComplexColor(maTempComplexColors[nIndex]); + break; + } + + maTempComplexColors[nIndex] = model::ComplexColor(); +} + bool SvxBoxItem::HasBorder( bool bTreatPaddingAsBorder ) const { return CalcLineSpace( SvxBoxItemLine::BOTTOM, bTreatPaddingAsBorder ) @@ -2079,27 +3255,25 @@ bool SvxBoxItem::HasBorder( bool bTreatPaddingAsBorder ) const // class SvxBoxInfoItem -------------------------------------------------- -SvxBoxInfoItem::SvxBoxInfoItem( const sal_uInt16 nId ) : - SfxPoolItem( nId ), - mbEnableHor( false ), - mbEnableVer( false ), - nDefDist( 0 ) +SvxBoxInfoItem::SvxBoxInfoItem(const sal_uInt16 nId) + : SfxPoolItem(nId) + , mbDistance(false) + , mbMinimumDistance(false) { - bDist = bMinDist = false; ResetFlags(); } -SvxBoxInfoItem::SvxBoxInfoItem( const SvxBoxInfoItem& rCpy ) : - SfxPoolItem( rCpy ), - pHori( rCpy.pHori ? new SvxBorderLine( *rCpy.pHori ) : nullptr ), - pVert( rCpy.pVert ? new SvxBorderLine( *rCpy.pVert ) : nullptr ), - mbEnableHor( rCpy.mbEnableHor ), - mbEnableVer( rCpy.mbEnableVer ), - bDist( rCpy.bDist ), - bMinDist ( rCpy.bMinDist ), - nValidFlags( rCpy.nValidFlags ), - nDefDist( rCpy.nDefDist ) +SvxBoxInfoItem::SvxBoxInfoItem( const SvxBoxInfoItem& rCopy ) + : SfxPoolItem(rCopy) + , mpHorizontalLine(rCopy.mpHorizontalLine ? new SvxBorderLine(*rCopy.mpHorizontalLine) : nullptr) + , mpVerticalLine(rCopy.mpVerticalLine ? new SvxBorderLine(*rCopy.mpVerticalLine) : nullptr) + , mbEnableHorizontalLine(rCopy.mbEnableHorizontalLine) + , mbEnableVerticalLine(rCopy.mbEnableVerticalLine) + , mbDistance(rCopy.mbDistance) + , mbMinimumDistance (rCopy.mbMinimumDistance) + , mnValidFlags(rCopy.mnValidFlags) + , mnDefaultMinimumDistance(rCopy.mnDefaultMinimumDistance) { } @@ -2129,29 +3303,28 @@ bool SvxBoxInfoItem::operator==( const SfxPoolItem& rAttr ) const const SvxBoxInfoItem& rBoxInfo = static_cast<const SvxBoxInfoItem&>(rAttr); - return ( mbEnableHor == rBoxInfo.mbEnableHor - && mbEnableVer == rBoxInfo.mbEnableVer - && bDist == rBoxInfo.IsDist() - && bMinDist == rBoxInfo.IsMinDist() - && nValidFlags == rBoxInfo.nValidFlags - && nDefDist == rBoxInfo.GetDefDist() - && CmpBrdLn( pHori, rBoxInfo.GetHori() ) - && CmpBrdLn( pVert, rBoxInfo.GetVert() ) - ); + return (mbEnableHorizontalLine == rBoxInfo.mbEnableHorizontalLine + && mbEnableVerticalLine == rBoxInfo.mbEnableVerticalLine + && mbDistance == rBoxInfo.mbDistance + && mbMinimumDistance == rBoxInfo.mbMinimumDistance + && mnValidFlags == rBoxInfo.mnValidFlags + && mnDefaultMinimumDistance == rBoxInfo.mnDefaultMinimumDistance + && CompareBorderLine(mpHorizontalLine, rBoxInfo.GetHori()) + && CompareBorderLine(mpVerticalLine, rBoxInfo.GetVert())); } void SvxBoxInfoItem::SetLine( const SvxBorderLine* pNew, SvxBoxInfoItemLine nLine ) { - std::unique_ptr<SvxBorderLine> pTmp( pNew ? new SvxBorderLine( *pNew ) : nullptr ); + std::unique_ptr<SvxBorderLine> pCopy(pNew ? new SvxBorderLine(*pNew) : nullptr); if ( SvxBoxInfoItemLine::HORI == nLine ) { - pHori = std::move(pTmp); + mpHorizontalLine = std::move(pCopy); } else if ( SvxBoxInfoItemLine::VERT == nLine ) { - pVert = std::move(pTmp); + mpVerticalLine = std::move(pCopy); } else { @@ -2179,9 +3352,11 @@ bool SvxBoxInfoItem::GetPresentation void SvxBoxInfoItem::ScaleMetrics( tools::Long nMult, tools::Long nDiv ) { - if ( pHori ) pHori->ScaleMetrics( nMult, nDiv ); - if ( pVert ) pVert->ScaleMetrics( nMult, nDiv ); - nDefDist = static_cast<sal_uInt16>(BigInt::Scale( nDefDist, nMult, nDiv )); + if (mpHorizontalLine) + mpHorizontalLine->ScaleMetrics(nMult, nDiv); + if (mpVerticalLine) + mpVerticalLine->ScaleMetrics(nMult, nDiv); + mnDefaultMinimumDistance = sal_uInt16(BigInt::Scale(mnDefaultMinimumDistance, nMult, nDiv)); } @@ -2193,7 +3368,7 @@ bool SvxBoxInfoItem::HasMetrics() const void SvxBoxInfoItem::ResetFlags() { - nValidFlags = static_cast<SvxBoxInfoItemValidFlags>(0x7F); // all valid except Disable + mnValidFlags = static_cast<SvxBoxInfoItemValidFlags>(0x7F); // all valid except Disable } bool SvxBoxInfoItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const @@ -2208,27 +3383,28 @@ bool SvxBoxInfoItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const case 0: { // 2 BorderLines, flags, valid flags and distance - css::uno::Sequence< css::uno::Any > aSeq( 5 ); - aSeq[0] <<= SvxBoxItem::SvxLineToLine( pHori.get(), bConvert); - aSeq[1] <<= SvxBoxItem::SvxLineToLine( pVert.get(), bConvert); if ( IsTable() ) nVal |= 0x01; if ( IsDist() ) nVal |= 0x02; if ( IsMinDist() ) nVal |= 0x04; - aSeq[2] <<= nVal; - aSeq[3] <<= static_cast<sal_Int16>(nValidFlags); - aSeq[4] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetDefDist()) : GetDefDist()); + css::uno::Sequence< css::uno::Any > aSeq{ + uno::Any(SvxBoxItem::SvxLineToLine(mpHorizontalLine.get(), bConvert)), + uno::Any(SvxBoxItem::SvxLineToLine(mpVerticalLine.get(), bConvert)), + uno::Any(nVal), + uno::Any(static_cast<sal_Int16>(mnValidFlags)), + uno::Any(static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetDefDist()) : GetDefDist())) + }; rVal <<= aSeq; return true; } case MID_HORIZONTAL: - aRetLine = SvxBoxItem::SvxLineToLine( pHori.get(), bConvert); + aRetLine = SvxBoxItem::SvxLineToLine(mpHorizontalLine.get(), bConvert); break; case MID_VERTICAL: - aRetLine = SvxBoxItem::SvxLineToLine( pVert.get(), bConvert); + aRetLine = SvxBoxItem::SvxLineToLine(mpVerticalLine.get(), bConvert); break; case MID_FLAGS: bIntMember = true; @@ -2242,7 +3418,7 @@ bool SvxBoxInfoItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const break; case MID_VALIDFLAGS: bIntMember = true; - rVal <<= static_cast<sal_Int16>(nValidFlags); + rVal <<= static_cast<sal_Int16>(mnValidFlags); break; case MID_DISTANCE: bIntMember = true; @@ -2287,14 +3463,14 @@ bool SvxBoxInfoItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) else return false; if ( aSeq[3] >>= nFlags ) - nValidFlags = static_cast<SvxBoxInfoItemValidFlags>(nFlags); + mnValidFlags = static_cast<SvxBoxInfoItemValidFlags>(nFlags); else return false; if (( aSeq[4] >>= nVal ) && ( nVal >= 0 )) { if( bConvert ) - nVal = convertMm100ToTwip(nVal); - SetDefDist( static_cast<sal_uInt16>(nVal) ); + nVal = o3tl::toTwips(nVal, o3tl::Length::mm100); + SetDefDist( nVal ); } } return true; @@ -2400,7 +3576,7 @@ bool SvxBoxInfoItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) sal_Int16 nFlags = sal_Int16(); bRet = (rVal >>= nFlags); if ( bRet ) - nValidFlags = static_cast<SvxBoxInfoItemValidFlags>(nFlags); + mnValidFlags = static_cast<SvxBoxInfoItemValidFlags>(nFlags); break; } case MID_DISTANCE: @@ -2410,7 +3586,7 @@ bool SvxBoxInfoItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if ( bRet && nVal>=0 ) { if( bConvert ) - nVal = convertMm100ToTwip(nVal); + nVal = o3tl::toTwips(nVal, o3tl::Length::mm100); SetDefDist( static_cast<sal_uInt16>(nVal) ); } break; @@ -2453,8 +3629,7 @@ void BorderDistanceFromWord(bool bFromEdge, sal_Int32& nMargin, sal_Int32& nBord } else if (nNewBorderDistance < 0) { - nNewMargin = std::max<sal_Int32>(nMargin - nBorderWidth, 0); - nNewBorderDistance = 0; + nNewMargin = nMargin; } nMargin = nNewMargin; @@ -2478,10 +3653,10 @@ void BorderDistancesToWord(const SvxBoxItem& rBox, const WordPageMargins& rMargi WordBorderDistances& rDistances) { // Use signed sal_Int32 that can hold sal_uInt16, to prevent overflow at subtraction below - const sal_Int32 nT = rBox.GetDistance(SvxBoxItemLine::TOP); - const sal_Int32 nL = rBox.GetDistance(SvxBoxItemLine::LEFT); - const sal_Int32 nB = rBox.GetDistance(SvxBoxItemLine::BOTTOM); - const sal_Int32 nR = rBox.GetDistance(SvxBoxItemLine::RIGHT); + const sal_Int32 nT = rBox.GetDistance(SvxBoxItemLine::TOP, /*bAllowNegative=*/true); + const sal_Int32 nL = rBox.GetDistance(SvxBoxItemLine::LEFT, /*bAllowNegative=*/true); + const sal_Int32 nB = rBox.GetDistance(SvxBoxItemLine::BOTTOM, /*bAllowNegative=*/true); + const sal_Int32 nR = rBox.GetDistance(SvxBoxItemLine::RIGHT, /*bAllowNegative=*/true); // Only take into account existing borders const SvxBorderLine* pLnT = rBox.GetLine(SvxBoxItemLine::TOP); @@ -2509,7 +3684,7 @@ void BorderDistancesToWord(const SvxBoxItem& rBox, const WordPageMargins& rMargi const sal_Int32 n32pt = 32 * 20; // 1. If all borders are in range of 31 pts from text - if (nT2BT < n32pt && nT2BL < n32pt && nT2BB < n32pt && nT2BR < n32pt) + if (nT2BT >= 0 && nT2BT < n32pt && nT2BL >= 0 && nT2BL < n32pt && nT2BB >= 0 && nT2BB < n32pt && nT2BR >= 0 && nT2BR < n32pt) { rDistances.bFromEdge = false; } @@ -2570,7 +3745,7 @@ bool SvxFormatBreakItem::GetPresentation OUString SvxFormatBreakItem::GetValueTextByPos( sal_uInt16 nPos ) { - static const char* RID_SVXITEMS_BREAK[] = + static TranslateId RID_SVXITEMS_BREAK[] = { RID_SVXITEMS_BREAK_NONE, RID_SVXITEMS_BREAK_COLUMN_BEFORE, @@ -2580,7 +3755,7 @@ OUString SvxFormatBreakItem::GetValueTextByPos( sal_uInt16 nPos ) RID_SVXITEMS_BREAK_PAGE_AFTER, RID_SVXITEMS_BREAK_PAGE_BOTH }; - static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_BREAK) == size_t(SvxBreak::End), "unexpected size"); + static_assert(std::size(RID_SVXITEMS_BREAK) == size_t(SvxBreak::End), "unexpected size"); assert(nPos < sal_uInt16(SvxBreak::End) && "enum overflow!"); return EditResId(RID_SVXITEMS_BREAK[nPos]); } @@ -2654,7 +3829,7 @@ bool SvxFormatKeepItem::GetPresentation OUString& rText, const IntlWrapper& ) const { - const char* pId = RID_SVXITEMS_FMTKEEP_FALSE; + TranslateId pId = RID_SVXITEMS_FMTKEEP_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_FMTKEEP_TRUE; @@ -2693,7 +3868,7 @@ bool SvxLineItem::operator==( const SfxPoolItem& rAttr ) const { assert(SfxPoolItem::operator==(rAttr)); - return CmpBrdLn( pLine, static_cast<const SvxLineItem&>(rAttr).GetLine() ); + return CompareBorderLine(pLine, static_cast<const SvxLineItem&>(rAttr).GetLine()); } SvxLineItem* SvxLineItem::Clone( SfxItemPool* ) const @@ -2803,9 +3978,16 @@ void SvxLineItem::SetLine( const SvxBorderLine* pNew ) pLine.reset( pNew ? new SvxBorderLine( *pNew ) : nullptr ); } +ItemInstanceManager* SvxBrushItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxBrushItem).hash_code()); + return &aInstanceManager; +} + SvxBrushItem::SvxBrushItem(sal_uInt16 _nWhich) : SfxPoolItem(_nWhich) , aColor(COL_TRANSPARENT) + , aFilterColor(COL_TRANSPARENT) , nShadingValue(ShadingPattern::CLEAR) , nGraphicTransparency(0) , eGraphicPos(GPOS_NONE) @@ -2816,6 +3998,19 @@ SvxBrushItem::SvxBrushItem(sal_uInt16 _nWhich) SvxBrushItem::SvxBrushItem(const Color& rColor, sal_uInt16 _nWhich) : SfxPoolItem(_nWhich) , aColor(rColor) + , aFilterColor(COL_TRANSPARENT) + , nShadingValue(ShadingPattern::CLEAR) + , nGraphicTransparency(0) + , eGraphicPos(GPOS_NONE) + , bLoadAgain(true) +{ +} + +SvxBrushItem::SvxBrushItem(Color const& rColor, model::ComplexColor const& rComplexColor, sal_uInt16 nWhich) + : SfxPoolItem(nWhich) + , aColor(rColor) + , maComplexColor(rComplexColor) + , aFilterColor(COL_TRANSPARENT) , nShadingValue(ShadingPattern::CLEAR) , nGraphicTransparency(0) , eGraphicPos(GPOS_NONE) @@ -2826,6 +4021,7 @@ SvxBrushItem::SvxBrushItem(const Color& rColor, sal_uInt16 _nWhich) SvxBrushItem::SvxBrushItem(const Graphic& rGraphic, SvxGraphicPosition ePos, sal_uInt16 _nWhich) : SfxPoolItem(_nWhich) , aColor(COL_TRANSPARENT) + , aFilterColor(COL_TRANSPARENT) , nShadingValue(ShadingPattern::CLEAR) , xGraphicObject(new GraphicObject(rGraphic)) , nGraphicTransparency(0) @@ -2838,6 +4034,7 @@ SvxBrushItem::SvxBrushItem(const Graphic& rGraphic, SvxGraphicPosition ePos, sal SvxBrushItem::SvxBrushItem(const GraphicObject& rGraphicObj, SvxGraphicPosition ePos, sal_uInt16 _nWhich) : SfxPoolItem(_nWhich) , aColor(COL_TRANSPARENT) + , aFilterColor(COL_TRANSPARENT) , nShadingValue(ShadingPattern::CLEAR) , xGraphicObject(new GraphicObject(rGraphicObj)) , nGraphicTransparency(0) @@ -2847,14 +4044,15 @@ SvxBrushItem::SvxBrushItem(const GraphicObject& rGraphicObj, SvxGraphicPosition DBG_ASSERT( GPOS_NONE != ePos, "SvxBrushItem-Ctor with GPOS_NONE == ePos" ); } -SvxBrushItem::SvxBrushItem(const OUString& rLink, const OUString& rFilter, +SvxBrushItem::SvxBrushItem(OUString aLink, OUString aFilter, SvxGraphicPosition ePos, sal_uInt16 _nWhich) : SfxPoolItem(_nWhich) , aColor(COL_TRANSPARENT) + , aFilterColor(COL_TRANSPARENT) , nShadingValue(ShadingPattern::CLEAR) , nGraphicTransparency(0) - , maStrLink(rLink) - , maStrFilter(rFilter) + , maStrLink(std::move(aLink)) + , maStrFilter(std::move(aFilter)) , eGraphicPos((GPOS_NONE != ePos) ? ePos : GPOS_MM) , bLoadAgain(true) { @@ -2864,6 +4062,8 @@ SvxBrushItem::SvxBrushItem(const OUString& rLink, const OUString& rFilter, SvxBrushItem::SvxBrushItem(const SvxBrushItem& rItem) : SfxPoolItem(rItem) , aColor(rItem.aColor) + , maComplexColor(rItem.maComplexColor) + , aFilterColor(rItem.aFilterColor) , nShadingValue(rItem.nShadingValue) , xGraphicObject(rItem.xGraphicObject ? new GraphicObject(*rItem.xGraphicObject) : nullptr) , nGraphicTransparency(rItem.nGraphicTransparency) @@ -2877,6 +4077,8 @@ SvxBrushItem::SvxBrushItem(const SvxBrushItem& rItem) SvxBrushItem::SvxBrushItem(SvxBrushItem&& rItem) : SfxPoolItem(std::move(rItem)) , aColor(std::move(rItem.aColor)) + , maComplexColor(std::move(rItem.maComplexColor)) + , aFilterColor(std::move(rItem.aFilterColor)) , nShadingValue(std::move(rItem.nShadingValue)) , xGraphicObject(std::move(rItem.xGraphicObject)) , nGraphicTransparency(std::move(rItem.nGraphicTransparency)) @@ -2935,6 +4137,15 @@ bool SvxBrushItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const case MID_BACK_COLOR_TRANSPARENCY: rVal <<= SvxBrushItem::TransparencyToPercent(255 - aColor.GetAlpha()); break; + + case MID_BACKGROUND_COMPLEX_COLOR: + { + auto xComplexColor = model::color::createXComplexColor(maComplexColor); + rVal <<= xComplexColor; + break; + } + break; + case MID_GRAPHIC_POSITION: rVal <<= static_cast<style::GraphicLocation>(static_cast<sal_Int16>(eGraphicPos)); break; @@ -2996,6 +4207,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) { aNewCol.SetAlpha(aColor.GetAlpha()); } + ASSERT_CHANGE_REFCOUNTED_ITEM; aColor = aNewCol; } break; @@ -3004,10 +4216,25 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) sal_Int32 nTrans = 0; if ( !( rVal >>= nTrans ) || nTrans < 0 || nTrans > 100 ) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; aColor.SetAlpha(255 - lcl_PercentToTransparency(nTrans)); } break; + case MID_BACKGROUND_COMPLEX_COLOR: + { + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rVal >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + { + ASSERT_CHANGE_REFCOUNTED_ITEM; + maComplexColor = model::color::getFromXComplexColor(xComplexColor); + } + } + break; + case MID_GRAPHIC_POSITION: { style::GraphicLocation eLocation; @@ -3018,11 +4245,13 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) return false; eLocation = static_cast<style::GraphicLocation>(nValue); } + ASSERT_CHANGE_REFCOUNTED_ITEM; SetGraphicPos( static_cast<SvxGraphicPosition>(static_cast<sal_uInt16>(eLocation)) ); } break; case MID_GRAPHIC_TRANSPARENT: + ASSERT_CHANGE_REFCOUNTED_ITEM; aColor.SetAlpha( Any2Bool( rVal ) ? 0 : 255 ); break; @@ -3046,6 +4275,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) { maStrLink.clear(); + ASSERT_CHANGE_REFCOUNTED_ITEM; std::unique_ptr<GraphicObject> xOldGrfObj(std::move(xGraphicObject)); xGraphicObject.reset(new GraphicObject(aGraphic)); ApplyGraphicTransparency_Impl(); @@ -3069,6 +4299,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) { OUString sLink; rVal >>= sLink; + ASSERT_CHANGE_REFCOUNTED_ITEM; SetGraphicFilter( sLink ); } } @@ -3079,6 +4310,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) rVal >>= nTmp; if(nTmp >= 0 && nTmp <= 100) { + ASSERT_CHANGE_REFCOUNTED_ITEM; nGraphicTransparency = sal_Int8(nTmp); if (xGraphicObject) ApplyGraphicTransparency_Impl(); @@ -3092,6 +4324,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if (!(rVal >>= nVal)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; nShadingValue = nVal; } break; @@ -3112,7 +4345,7 @@ bool SvxBrushItem::GetPresentation if ( GPOS_NONE == eGraphicPos ) { rText = ::GetColorString( aColor ) + cpDelim; - const char* pId = RID_SVXITEMS_TRANSPARENT_FALSE; + TranslateId pId = RID_SVXITEMS_TRANSPARENT_FALSE; if ( aColor.IsTransparent() ) pId = RID_SVXITEMS_TRANSPARENT_TRUE; @@ -3131,8 +4364,12 @@ bool SvxBrushItem::operator==( const SfxPoolItem& rAttr ) const assert(SfxPoolItem::operator==(rAttr)); const SvxBrushItem& rCmp = static_cast<const SvxBrushItem&>(rAttr); - bool bEqual = ( aColor == rCmp.aColor && eGraphicPos == rCmp.eGraphicPos && - nGraphicTransparency == rCmp.nGraphicTransparency); + bool bEqual = + aColor == rCmp.aColor && + maComplexColor == rCmp.maComplexColor && + aFilterColor == rCmp.aFilterColor && + eGraphicPos == rCmp.eGraphicPos && + nGraphicTransparency == rCmp.nGraphicTransparency; if ( bEqual ) { @@ -3174,7 +4411,7 @@ const GraphicObject* SvxBrushItem::GetGraphicObject(OUString const & referer) co if (bLoadAgain && !maStrLink.isEmpty() && !xGraphicObject) // when graphics already loaded, use as a cache { - if (maSecOptions.isUntrustedReferer(referer)) { + if (SvtSecurityOptions::isUntrustedReferer(referer)) { return nullptr; } @@ -3205,7 +4442,7 @@ const GraphicObject* SvxBrushItem::GetGraphicObject(OUString const & referer) co std::unique_ptr<SvMemoryStream> const xMemStream(aGraphicURL.getData()); if (xMemStream) { - if (ERRCODE_NONE == GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, "", *xMemStream)) + if (ERRCODE_NONE == GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, u"", *xMemStream)) { bGraphicLoaded = true; @@ -3237,6 +4474,7 @@ void SvxBrushItem::setGraphicTransparency(sal_Int8 nNew) { if (nNew != nGraphicTransparency) { + ASSERT_CHANGE_REFCOUNTED_ITEM; nGraphicTransparency = nNew; ApplyGraphicTransparency_Impl(); } @@ -3250,6 +4488,10 @@ const Graphic* SvxBrushItem::GetGraphic(OUString const & referer) const void SvxBrushItem::SetGraphicPos( SvxGraphicPosition eNew ) { + if (eGraphicPos == eNew) + return; + + ASSERT_CHANGE_REFCOUNTED_ITEM; eGraphicPos = eNew; if ( GPOS_NONE == eGraphicPos ) @@ -3271,6 +4513,7 @@ void SvxBrushItem::SetGraphic( const Graphic& rNew ) { if ( maStrLink.isEmpty() ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; if (xGraphicObject) xGraphicObject->SetGraphic(rNew); else @@ -3291,6 +4534,7 @@ void SvxBrushItem::SetGraphicObject( const GraphicObject& rNewObj ) { if ( maStrLink.isEmpty() ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; if (xGraphicObject) *xGraphicObject = rNewObj; else @@ -3309,6 +4553,7 @@ void SvxBrushItem::SetGraphicObject( const GraphicObject& rNewObj ) void SvxBrushItem::SetGraphicLink( const OUString& rNew ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; if ( rNew.isEmpty() ) maStrLink.clear(); else @@ -3320,6 +4565,7 @@ void SvxBrushItem::SetGraphicLink( const OUString& rNew ) void SvxBrushItem::SetGraphicFilter( const OUString& rNew ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; maStrFilter = rNew; } @@ -3340,6 +4586,7 @@ void SvxBrushItem::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxBrushItem")); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("color"), BAD_CAST(aColor.AsRGBHexString().toUtf8().getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("filtercolor"), BAD_CAST(aFilterColor.AsRGBHexString().toUtf8().getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("shadingValue"), BAD_CAST(OString::number(nShadingValue).getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("link"), BAD_CAST(maStrLink.toUtf8().getStr())); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("filter"), BAD_CAST(maStrFilter.toUtf8().getStr())); @@ -3349,6 +4596,12 @@ void SvxBrushItem::dumpAsXml(xmlTextWriterPtr pWriter) const } +ItemInstanceManager* SvxFrameDirectionItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxFrameDirectionItem).hash_code()); + return &aInstanceManager; +} + SvxFrameDirectionItem::SvxFrameDirectionItem( SvxFrameDirection nValue , sal_uInt16 _nWhich ) : SfxEnumItem<SvxFrameDirection>( _nWhich, nValue ) @@ -3365,16 +4618,17 @@ SvxFrameDirectionItem* SvxFrameDirectionItem::Clone( SfxItemPool * ) const return new SvxFrameDirectionItem( *this ); } -const char* getFrmDirResId(size_t nIndex) +TranslateId getFrmDirResId(size_t nIndex) { - const char* const RID_SVXITEMS_FRMDIR[] = + TranslateId const RID_SVXITEMS_FRMDIR[] = { RID_SVXITEMS_FRMDIR_HORI_LEFT_TOP, RID_SVXITEMS_FRMDIR_HORI_RIGHT_TOP, RID_SVXITEMS_FRMDIR_VERT_TOP_RIGHT, RID_SVXITEMS_FRMDIR_VERT_TOP_LEFT, RID_SVXITEMS_FRMDIR_ENVIRONMENT, - RID_SVXITEMS_FRMDIR_VERT_BOT_LEFT + RID_SVXITEMS_FRMDIR_VERT_BOT_LEFT, + RID_SVXITEMS_FRMDIR_VERT_TOP_RIGHT90 }; return RID_SVXITEMS_FRMDIR[nIndex]; } @@ -3396,6 +4650,7 @@ bool SvxFrameDirectionItem::PutValue( const css::uno::Any& rVal, bool bRet = ( rVal >>= nVal ); if( bRet ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; // translate WritingDirection2 constants into SvxFrameDirection switch( nVal ) { @@ -3414,9 +4669,15 @@ bool SvxFrameDirectionItem::PutValue( const css::uno::Any& rVal, case text::WritingMode2::BT_LR: SetValue( SvxFrameDirection::Vertical_LR_BT ); break; + case text::WritingMode2::TB_RL90: + SetValue(SvxFrameDirection::Vertical_RL_TB90); + break; case text::WritingMode2::PAGE: SetValue( SvxFrameDirection::Environment ); break; + case text::WritingMode2::STACKED: + SetValue(SvxFrameDirection::Stacked); + break; default: bRet = false; break; @@ -3450,9 +4711,15 @@ bool SvxFrameDirectionItem::QueryValue( css::uno::Any& rVal, case SvxFrameDirection::Vertical_LR_BT: nVal = text::WritingMode2::BT_LR; break; + case SvxFrameDirection::Vertical_RL_TB90: + nVal = text::WritingMode2::TB_RL90; + break; case SvxFrameDirection::Environment: nVal = text::WritingMode2::PAGE; break; + case SvxFrameDirection::Stacked: + nVal = text::WritingMode2::STACKED; + break; default: OSL_FAIL("Unknown SvxFrameDirection value!"); bRet = false; diff --git a/editeng/source/items/itemtype.cxx b/editeng/source/items/itemtype.cxx index 5cf463173063..cbb83c83be35 100644 --- a/editeng/source/items/itemtype.cxx +++ b/editeng/source/items/itemtype.cxx @@ -152,7 +152,7 @@ OUString GetColorString( const Color& rCol ) nColor += 1; } - static const char* RID_SVXITEMS_COLORS[] = + static TranslateId RID_SVXITEMS_COLORS[] = { RID_SVXITEMS_COLOR_BLACK, RID_SVXITEMS_COLOR_BLUE, @@ -188,9 +188,9 @@ OUString GetColorString( const Color& rCol ) return sStr; } -const char* GetMetricId( MapUnit eUnit ) +TranslateId GetMetricId( MapUnit eUnit ) { - const char* pId = RID_SVXITEMS_METRIC_MM; + TranslateId pId = RID_SVXITEMS_METRIC_MM; switch ( eUnit ) { diff --git a/editeng/source/items/legacyitem.cxx b/editeng/source/items/legacyitem.cxx index d630c4e5f0b3..96742f46fcae 100644 --- a/editeng/source/items/legacyitem.cxx +++ b/editeng/source/items/legacyitem.cxx @@ -107,7 +107,7 @@ namespace legacy SvStream& Store(const SvxFontItem& rItem, SvStream& rStrm, sal_uInt16) { - const bool bToBats(IsStarSymbol(rItem.GetFamilyName())); + const bool bToBats(IsOpenSymbol(rItem.GetFamilyName())); rStrm.WriteUChar(rItem.GetFamily()).WriteUChar(rItem.GetPitch()).WriteUChar(bToBats ? RTL_TEXTENCODING_SYMBOL : @@ -557,7 +557,7 @@ namespace legacy { Graphic aGraphic; aSerializer.readGraphic(aGraphic); - rItem.SetGraphicObject(GraphicObject(aGraphic)); + rItem.SetGraphicObject(GraphicObject(std::move(aGraphic))); if( SVSTREAM_FILEFORMAT_ERROR == rStrm.GetError() ) { @@ -573,7 +573,7 @@ namespace legacy // TODO/MBA: how can we get a BaseURL here?! OSL_FAIL("No BaseURL!"); - OUString aAbs = INetURLObject::GetAbsURL( "", aRel ); + OUString aAbs = INetURLObject::GetAbsURL( u"", aRel ); DBG_ASSERT( !aAbs.isEmpty(), "Invalid URL!" ); rItem.SetGraphicLink(aAbs); } @@ -616,7 +616,7 @@ namespace legacy { OSL_FAIL("No BaseURL!"); // TODO/MBA: how to get a BaseURL?! - OUString aRel = INetURLObject::GetRelURL( "", rItem.GetGraphicLink() ); + OUString aRel = INetURLObject::GetRelURL( u"", rItem.GetGraphicLink() ); // UNICODE: rStrm << aRel; rStrm.WriteUniOrByteString(aRel, rStrm.GetStreamCharSet()); } diff --git a/editeng/source/items/numitem.cxx b/editeng/source/items/numitem.cxx index 2dd03a1877cf..2a1e540c3cb7 100644 --- a/editeng/source/items/numitem.cxx +++ b/editeng/source/items/numitem.cxx @@ -24,6 +24,7 @@ #include <editeng/numitem.hxx> #include <com/sun/star/text/VertOrientation.hpp> +#include <comphelper/propertyvalue.hxx> #include <editeng/brushitem.hxx> #include <rtl/ustrbuf.hxx> #include <vcl/font.hxx> @@ -45,19 +46,18 @@ #include <tools/stream.hxx> #include <tools/debug.hxx> #include <tools/GenericTypeSerializer.hxx> -#include <tools/UnitConversion.hxx> -#include <unotools/configmgr.hxx> +#include <comphelper/configuration.hxx> #include <libxml/xmlwriter.h> #include <editeng/unonrule.hxx> #include <sal/log.hxx> #include <i18nlangtag/languagetag.hxx> #include <editeng/legacyitem.hxx> -#define DEF_WRITER_LSPACE 500 //Standard Indentation -#define DEF_DRAW_LSPACE 800 //Standard Indentation +constexpr sal_Int32 DEF_WRITER_LSPACE = 500; //Standard Indentation +constexpr sal_Int32 DEF_DRAW_LSPACE = 800; //Standard Indentation -#define NUMITEM_VERSION_03 0x03 -#define NUMITEM_VERSION_04 0x04 +constexpr sal_uInt16 NUMITEM_VERSION_03 = 0x03; +constexpr sal_uInt16 NUMITEM_VERSION_04 = 0x04; using namespace ::com::sun::star; using namespace ::com::sun::star::lang; @@ -107,13 +107,19 @@ SvxNumberType::~SvxNumberType() OUString SvxNumberType::GetNumStr( sal_Int32 nNo ) const { - LanguageTag aLang = utl::ConfigManager::IsFuzzing() ? + LanguageTag aLang = comphelper::IsFuzzing() ? LanguageTag("en-US") : Application::GetSettings().GetLanguageTag(); return GetNumStr( nNo, aLang.getLocale() ); } -OUString SvxNumberType::GetNumStr( sal_Int32 nNo, const css::lang::Locale& rLocale ) const +static bool isArabicNumberingType(SvxNumType t) +{ + return t == SVX_NUM_ARABIC || t == SVX_NUM_ARABIC_ZERO || t == SVX_NUM_ARABIC_ZERO3 + || t == SVX_NUM_ARABIC_ZERO4 || t == SVX_NUM_ARABIC_ZERO5; +} + +OUString SvxNumberType::GetNumStr( sal_Int32 nNo, const css::lang::Locale& rLocale, bool bIsLegal ) const { lcl_getFormatter(xFormatter); if(!xFormatter.is()) @@ -133,12 +139,14 @@ OUString SvxNumberType::GetNumStr( sal_Int32 nNo, const css::lang::Locale& rLoca return OUString('0'); else { - Sequence< PropertyValue > aProperties(2); - PropertyValue* pValues = aProperties.getArray(); - pValues[0].Name = "NumberingType"; - pValues[0].Value <<= static_cast<sal_uInt16>(nNumType); - pValues[1].Name = "Value"; - pValues[1].Value <<= nNo; + SvxNumType nActType = !bIsLegal || isArabicNumberingType(nNumType) ? nNumType : SVX_NUM_ARABIC; + static constexpr OUString sNumberingType = u"NumberingType"_ustr; + static constexpr OUString sValue = u"Value"_ustr; + Sequence< PropertyValue > aProperties + { + comphelper::makePropertyValue(sNumberingType, static_cast<sal_uInt16>(nActType)), + comphelper::makePropertyValue(sValue, nNo) + }; try { @@ -164,7 +172,7 @@ void SvxNumberType::dumpAsXml( xmlTextWriterPtr pWriter ) const SvxNumberFormat::SvxNumberFormat( SvxNumType eType ) : SvxNumberType(eType), eNumAdjust(SvxAdjust::Left), - nInclUpperLevels(0), + nInclUpperLevels(1), nStart(1), cBullet(SVX_DEF_BULLET), nBulletRelSize(100), @@ -233,10 +241,10 @@ SvxNumberFormat::SvxNumberFormat( SvStream &rStream ) rStream.ReadUInt16( hasBulletFont ); if ( hasBulletFont ) { - pBulletFont.reset( new vcl::Font() ); + pBulletFont.emplace(); ReadFont( rStream, *pBulletFont ); } - else pBulletFont = nullptr; + else pBulletFont.reset(); tools::GenericTypeSerializer aSerializer(rStream); aSerializer.readSize(aGraphicSize); @@ -364,7 +372,8 @@ SvxNumberFormat& SvxNumberFormat::operator=( const SvxNumberFormat& rFormat ) } pBulletFont.reset(); if(rFormat.pBulletFont) - pBulletFont.reset( new vcl::Font(*rFormat.pBulletFont) ); + pBulletFont = *rFormat.pBulletFont; + mbIsLegal = rFormat.mbIsLegal; return *this; } @@ -391,7 +400,8 @@ bool SvxNumberFormat::operator==( const SvxNumberFormat& rFormat) const nBulletColor != rFormat.nBulletColor || nBulletRelSize != rFormat.nBulletRelSize || IsShowSymbol() != rFormat.IsShowSymbol() || - sCharStyleName != rFormat.sCharStyleName + sCharStyleName != rFormat.sCharStyleName || + mbIsLegal != rFormat.mbIsLegal ) return false; if ( @@ -454,7 +464,10 @@ sal_Int16 SvxNumberFormat::GetVertOrient() const void SvxNumberFormat::SetBulletFont(const vcl::Font* pFont) { - pBulletFont.reset( pFont ? new vcl::Font(*pFont): nullptr ); + if (pFont) + pBulletFont = *pFont; + else + pBulletFont.reset(); } void SvxNumberFormat::SetPositionAndSpaceMode( SvxNumPositionAndSpaceMode ePositionAndSpaceMode ) @@ -483,6 +496,27 @@ void SvxNumberFormat::SetLabelFollowedBy( const LabelFollowedBy eLabelFollowedBy { meLabelFollowedBy = eLabelFollowedBy; } + +OUString SvxNumberFormat::GetLabelFollowedByAsString() const +{ + switch (meLabelFollowedBy) + { + case LISTTAB: + return "\t"; + case SPACE: + return " "; + case NEWLINE: + return "\n"; + case NOTHING: + // intentionally left blank. + return OUString(); + default: + SAL_WARN("editeng", "Unknown SvxNumberFormat::GetLabelFollowedBy() return value"); + assert(false); + } + return OUString(); +} + void SvxNumberFormat::SetListtabPos( const tools::Long nListtabPos ) { mnListtabPos = nListtabPos; @@ -516,48 +550,116 @@ Size SvxNumberFormat::GetGraphicSizeMM100(const Graphic* pGraphic) OUString SvxNumberFormat::CreateRomanString( sal_Int32 nNo, bool bUpper ) { - nNo %= 4000; // more can not be displayed -// i, ii, iii, iv, v, vi, vii, vii, viii, ix -// (Dummy),1000,500,100,50,10,5,1 - const char *cRomanArr = bUpper - ? "MDCLXVI--" // +2 Dummy entries! - : "mdclxvi--"; // +2 Dummy entries! - OUStringBuffer sRet; - sal_uInt16 nMask = 1000; - while( nMask ) - { - sal_uInt8 nNumber = sal_uInt8(nNo / nMask); - sal_uInt8 nDiff = 1; - nNo %= nMask; - if( 5 < nNumber ) - { - if( nNumber < 9 ) - sRet.append(*(cRomanArr-1)); - ++nDiff; - nNumber -= 5; - } - switch( nNumber ) + constexpr char romans[][13] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + constexpr sal_Int32 values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + + for (size_t i = 0; i < std::size(romans); ++i) + { + while(nNo - values[i] >= 0) { - case 3: { sRet.append(*cRomanArr); [[fallthrough]]; } - case 2: { sRet.append(*cRomanArr); [[fallthrough]]; } - case 1: { sRet.append(*cRomanArr); } - break; - - case 4: { - sRet.append(*cRomanArr); - sRet.append(*(cRomanArr-nDiff)); - } - break; - case 5: { sRet.append(*(cRomanArr-nDiff)); } - break; + sRet.appendAscii(romans[i]); + nNo -= values[i]; } + } + + return bUpper ? sRet.makeStringAndClear() + : sRet.makeStringAndClear().toAsciiLowerCase(); +} + +void SvxNumberFormat::SetPrefix(const OUString& rSet) +{ + // ListFormat manages the prefix. If badly changed via this function, sListFormat is invalidated + if (sListFormat && rSet.getLength() != sPrefix.getLength()) + sListFormat.reset(); - nMask /= 10; // for the next decade - cRomanArr += 2; + sPrefix = rSet; +} + +void SvxNumberFormat::SetSuffix(const OUString& rSet) +{ + // ListFormat manages the suffix. If badly changed via this function, sListFormat is invalidated + if (sListFormat && rSet.getLength() != sSuffix.getLength()) + sListFormat.reset(); + + sSuffix = rSet; +} + +void SvxNumberFormat::SetListFormat(const OUString& rPrefix, const OUString& rSuffix, int nLevel) +{ + sPrefix = rPrefix; + sSuffix = rSuffix; + + // Generate list format + sListFormat = std::make_optional(sPrefix); + + for (int i = 1; i <= nInclUpperLevels; i++) + { + int nLevelId = nLevel - nInclUpperLevels + i; + if (nLevelId < 0) + // There can be cases with current level 1, but request to show 10 upper levels. Trim it + continue; + + *sListFormat += "%"; + *sListFormat += OUString::number(nLevelId + 1); + *sListFormat += "%"; + if (i != nInclUpperLevels) + *sListFormat += "."; // Default separator for older ODT + } + + *sListFormat += sSuffix; +} + +void SvxNumberFormat::SetListFormat(std::optional<OUString> oSet) +{ + sPrefix.clear(); + sSuffix.clear(); + + sListFormat = oSet; + + if (!oSet.has_value()) + { + return; + } + + // For backward compatibility and UI we should create something looking like + // a prefix, suffix and included levels also. This is not possible in general case + // since level format string is much more flexible. But for most cases is okay + sal_Int32 nFirstReplacement = sListFormat->indexOf('%'); + sal_Int32 nLastReplacement = sListFormat->lastIndexOf('%') + 1; + if (nFirstReplacement > 0) + // Everything before first '%' will be prefix + sPrefix = sListFormat->copy(0, nFirstReplacement); + if (nLastReplacement >= 0 && nLastReplacement < sListFormat->getLength()) + // Everything beyond last '%' is a suffix + sSuffix = sListFormat->copy(nLastReplacement); + + sal_uInt8 nPercents = 0; + for (sal_Int32 i = 0; i < sListFormat->getLength(); i++) + { + if ((*sListFormat)[i] == '%') + nPercents++; } - return sRet.makeStringAndClear(); + nInclUpperLevels = nPercents/2; + if (nInclUpperLevels < 1) + { + // There should be always at least one level. This will be not required + // in future (when we get rid of prefix/suffix), but nowadays there + // are too many conversions "list format" <-> "prefix/suffix/inclUpperLevel" + nInclUpperLevels = 1; + } +} + +OUString SvxNumberFormat::GetListFormat(bool bIncludePrefixSuffix /*= true*/) const +{ + assert(sListFormat.has_value()); + + if (bIncludePrefixSuffix) + return *sListFormat; + + // Strip prefix & suffix from string + return sListFormat->copy(sPrefix.getLength(), sListFormat->getLength() - sPrefix.getLength() - sSuffix.getLength()); } OUString SvxNumberFormat::GetCharFormatName()const @@ -591,18 +693,18 @@ SvxNumRule::SvxNumRule( SvxNumRuleFlags nFeatures, if ( eDefaultNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) { - aFmts[i]->SetAbsLSpace( convertMm100ToTwip(DEF_WRITER_LSPACE * (i+1)) ); - aFmts[i]->SetFirstLineOffset(convertMm100ToTwip(-DEF_WRITER_LSPACE)); + aFmts[i]->SetAbsLSpace(o3tl::toTwips(DEF_WRITER_LSPACE * (i+1), o3tl::Length::mm100)); + aFmts[i]->SetFirstLineOffset(o3tl::toTwips(-DEF_WRITER_LSPACE, o3tl::Length::mm100)); } else if ( eDefaultNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT ) { // first line indent of general numbering in inch: -0,25 inch - const tools::Long cFirstLineIndent = -1440/4; + constexpr tools::Long cFirstLineIndent = o3tl::toTwips(-0.25, o3tl::Length::in); // indent values of general numbering in inch: // 0,5 0,75 1,0 1,25 1,5 // 1,75 2,0 2,25 2,5 2,75 - const tools::Long cIndentAt = 1440/4; + constexpr tools::Long cIndentAt = o3tl::toTwips(0.25, o3tl::Length::in); aFmts[i]->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT ); aFmts[i]->SetLabelFollowedBy( SvxNumberFormat::LISTTAB ); aFmts[i]->SetListtabPos( cIndentAt * (i+2) ); @@ -913,7 +1015,7 @@ OUString SvxNumRule::MakeNumString( const SvxNodeNum& rNum ) const if(SVX_NUM_BITMAP != rNFmt.GetNumberingType()) { const LanguageTag& rLang = Application::GetSettings().GetLanguageTag(); - aStr.append(rNFmt.GetNumStr( rNum.GetLevelVal()[ i ], rLang.getLocale() )); + aStr.append(rNFmt.GetNumStr( rNum.GetLevelVal()[ i ], rLang.getLocale(), rMyNFmt.GetIsLegal() )); } else bDot = false; @@ -964,12 +1066,24 @@ SvxNumBulletItem::SvxNumBulletItem(SvxNumRule const & rRule) : { } +SvxNumBulletItem::SvxNumBulletItem(SvxNumRule && rRule) : + SfxPoolItem(SID_ATTR_NUMBERING_RULE), + maNumRule(std::move(rRule)) +{ +} + SvxNumBulletItem::SvxNumBulletItem(SvxNumRule const & rRule, sal_uInt16 _nWhich ) : SfxPoolItem(_nWhich), maNumRule(rRule) { } +SvxNumBulletItem::SvxNumBulletItem(SvxNumRule && rRule, sal_uInt16 _nWhich ) : + SfxPoolItem(_nWhich), + maNumRule(std::move(rRule)) +{ +} + SvxNumBulletItem::SvxNumBulletItem(const SvxNumBulletItem& rCopy) : SfxPoolItem(rCopy), maNumRule(rCopy.maNumRule) diff --git a/editeng/source/items/paperinf.cxx b/editeng/source/items/paperinf.cxx index e8646bc55377..86401e63f387 100644 --- a/editeng/source/items/paperinf.cxx +++ b/editeng/source/items/paperinf.cxx @@ -93,9 +93,9 @@ Paper SvxPaperInfo::GetSvxPaper( const Size &rSize, MapUnit eUnit ) tools::Long SvxPaperInfo::GetSloppyPaperDimension( tools::Long nSize ) { - nSize = OutputDevice::LogicToLogic(nSize, MapUnit::MapTwip, MapUnit::Map100thMM); + nSize = o3tl::convert(nSize, o3tl::Length::twip, o3tl::Length::mm100); nSize = PaperInfo::sloppyFitPageDimension(nSize); - return OutputDevice::LogicToLogic(nSize, MapUnit::Map100thMM, MapUnit::MapTwip); + return o3tl::convert(nSize, o3tl::Length::mm100, o3tl::Length::twip); } diff --git a/editeng/source/items/paraitem.cxx b/editeng/source/items/paraitem.cxx index 9bc05843bd22..4b55fa49026e 100644 --- a/editeng/source/items/paraitem.cxx +++ b/editeng/source/items/paraitem.cxx @@ -20,6 +20,7 @@ #include <com/sun/star/style/TabStop.hpp> #include <com/sun/star/style/LineSpacing.hpp> #include <com/sun/star/style/LineSpacingMode.hpp> +#include <com/sun/star/text/ParagraphHyphenationKeepType.hpp> #include <com/sun/star/uno/Sequence.hxx> #include <libxml/xmlwriter.h> #include <comphelper/extract.hxx> @@ -60,8 +61,8 @@ SfxPoolItem* SvxOrphansItem::CreateDefault() { return new SvxOrphansItem(0, 0); SfxPoolItem* SvxHyphenZoneItem::CreateDefault() { return new SvxHyphenZoneItem(false, 0);} SfxPoolItem* SvxTabStopItem::CreateDefault() { return new SvxTabStopItem(0);} SfxPoolItem* SvxFormatSplitItem::CreateDefault() { return new SvxFormatSplitItem(false, 0);} -SfxPoolItem* SvxPageModelItem::CreateDefault() { return new SvxPageModelItem(0);} -SfxPoolItem* SvxParaVertAlignItem::CreateDefault() { return new SvxParaVertAlignItem(Align::Automatic, 0);} +SfxPoolItem* SvxPageModelItem::CreateDefault() { return new SvxPageModelItem(TypedWhichId<SvxPageModelItem>(0));} +SfxPoolItem* SvxParaVertAlignItem::CreateDefault() { return new SvxParaVertAlignItem(Align::Automatic, TypedWhichId<SvxParaVertAlignItem>(0));} namespace { @@ -188,7 +189,7 @@ bool SvxLineSpacingItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) eLineSpaceRule = SvxLineSpaceRule::Auto; nInterLineSpace = aLSp.Height; if(bConvert) - nInterLineSpace = static_cast<short>(convertMm100ToTwip(nInterLineSpace)); + nInterLineSpace = o3tl::toTwips(nInterLineSpace, o3tl::Length::mm100); } break; @@ -209,7 +210,7 @@ bool SvxLineSpacingItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) eLineSpaceRule = aLSp.Mode == style::LineSpacingMode::FIX ? SvxLineSpaceRule::Fix : SvxLineSpaceRule::Min; nLineHeight = aLSp.Height; if(bConvert) - nLineHeight = static_cast<sal_uInt16>(convertMm100ToTwip(nLineHeight)); + nLineHeight = o3tl::toTwips(nLineHeight, o3tl::Length::mm100); } break; } @@ -338,6 +339,12 @@ void SvxLineSpacingItem::SetEnumValue( sal_uInt16 nVal ) // class SvxAdjustItem --------------------------------------------------- +ItemInstanceManager* SvxAdjustItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxAdjustItem).hash_code()); + return &aInstanceManager; +} + SvxAdjustItem::SvxAdjustItem(const SvxAdjust eAdjst, const sal_uInt16 nId ) : SfxEnumItemInterface( nId ), bOneBlock( false ), bLastCenter( false ), bLastBlock( false ) @@ -397,6 +404,7 @@ bool SvxAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) } break; case MID_EXPAND_SINGLE : + ASSERT_CHANGE_REFCOUNTED_ITEM; bOneBlock = Any2Bool(rVal); break; } @@ -435,7 +443,7 @@ sal_uInt16 SvxAdjustItem::GetValueCount() const OUString SvxAdjustItem::GetValueTextByPos( sal_uInt16 nPos ) { - static const char* RID_SVXITEMS_ADJUST[] = + static TranslateId RID_SVXITEMS_ADJUST[] = { RID_SVXITEMS_ADJUST_LEFT, RID_SVXITEMS_ADJUST_RIGHT, @@ -553,11 +561,16 @@ bool SvxOrphansItem::GetPresentation SvxHyphenZoneItem::SvxHyphenZoneItem( const bool bHyph, const sal_uInt16 nId ) : SfxPoolItem( nId ), bHyphen(bHyph), - bPageEnd(true), + bKeep(false), bNoCapsHyphenation(false), + bNoLastWordHyphenation(false), nMinLead(0), nMinTrail(0), - nMaxHyphens(255) + nMaxHyphens(255), + nMinWordLength(0), + nTextHyphenZone(0), + nKeepType(css::text::ParagraphHyphenationKeepType::COLUMN), + nCompoundMinLead(0) { } @@ -570,6 +583,9 @@ bool SvxHyphenZoneItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) con case MID_IS_HYPHEN: rVal <<= bHyphen; break; + case MID_HYPHEN_KEEP: + rVal <<= bKeep; + break; case MID_HYPHEN_MIN_LEAD: rVal <<= static_cast<sal_Int16>(nMinLead); break; @@ -582,6 +598,21 @@ bool SvxHyphenZoneItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) con case MID_HYPHEN_NO_CAPS: rVal <<= bNoCapsHyphenation; break; + case MID_HYPHEN_NO_LAST_WORD: + rVal <<= bNoLastWordHyphenation; + break; + case MID_HYPHEN_MIN_WORD_LENGTH: + rVal <<= static_cast<sal_Int16>(nMinWordLength); + break; + case MID_HYPHEN_ZONE: + rVal <<= static_cast<sal_Int16>(nTextHyphenZone); + break; + case MID_HYPHEN_KEEP_TYPE: + rVal <<= static_cast<sal_Int16>(nKeepType); + break; + case MID_HYPHEN_COMPOUND_MIN_LEAD: + rVal <<= static_cast<sal_Int16>(nCompoundMinLead); + break; } return true; } @@ -589,17 +620,23 @@ bool SvxHyphenZoneItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) con bool SvxHyphenZoneItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) { nMemberId &= ~CONVERT_TWIPS; - sal_Int16 nNewVal = 0; + sal_Int32 nNewVal = 0; // sal_Int32 needs for MID_HYPHEN_KEEP_TYPE - if( nMemberId != MID_IS_HYPHEN && nMemberId != MID_HYPHEN_NO_CAPS ) + if( nMemberId != MID_IS_HYPHEN && nMemberId != MID_HYPHEN_NO_CAPS && + nMemberId != MID_HYPHEN_NO_LAST_WORD && nMemberId != MID_HYPHEN_KEEP ) + { if(!(rVal >>= nNewVal)) return false; + } switch(nMemberId) { case MID_IS_HYPHEN: bHyphen = Any2Bool(rVal); break; + case MID_HYPHEN_KEEP: + bKeep = Any2Bool(rVal); + break; case MID_HYPHEN_MIN_LEAD: nMinLead = static_cast<sal_uInt8>(nNewVal); break; @@ -612,6 +649,21 @@ bool SvxHyphenZoneItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) case MID_HYPHEN_NO_CAPS: bNoCapsHyphenation = Any2Bool(rVal); break; + case MID_HYPHEN_NO_LAST_WORD: + bNoLastWordHyphenation = Any2Bool(rVal); + break; + case MID_HYPHEN_MIN_WORD_LENGTH: + nMinWordLength = static_cast<sal_uInt8>(nNewVal); + break; + case MID_HYPHEN_ZONE: + nTextHyphenZone = nNewVal; + break; + case MID_HYPHEN_KEEP_TYPE: + nKeepType = static_cast<sal_uInt8>(nNewVal); + break; + case MID_HYPHEN_COMPOUND_MIN_LEAD: + nCompoundMinLead = static_cast<sal_uInt8>(nNewVal); + break; } return true; } @@ -624,10 +676,15 @@ bool SvxHyphenZoneItem::operator==( const SfxPoolItem& rAttr ) const const SvxHyphenZoneItem& rItem = static_cast<const SvxHyphenZoneItem&>(rAttr); return ( rItem.bHyphen == bHyphen && rItem.bNoCapsHyphenation == bNoCapsHyphenation - && rItem.bPageEnd == bPageEnd + && rItem.bNoLastWordHyphenation == bNoLastWordHyphenation + && rItem.bKeep == bKeep && rItem.nMinLead == nMinLead && rItem.nMinTrail == nMinTrail - && rItem.nMaxHyphens == nMaxHyphens ); + && rItem.nCompoundMinLead == nCompoundMinLead + && rItem.nMaxHyphens == nMaxHyphens + && rItem.nMinWordLength == nMinWordLength + && rItem.nTextHyphenZone == nTextHyphenZone + && rItem.nKeepType == nKeepType ); } SvxHyphenZoneItem* SvxHyphenZoneItem::Clone( SfxItemPool * ) const @@ -638,9 +695,9 @@ SvxHyphenZoneItem* SvxHyphenZoneItem::Clone( SfxItemPool * ) const bool SvxHyphenZoneItem::GetPresentation ( SfxItemPresentation ePres, - MapUnit /*eCoreUnit*/, - MapUnit /*ePresUnit*/, - OUString& rText, const IntlWrapper& + MapUnit eCoreUnit, + MapUnit ePresUnit, + OUString& rText, const IntlWrapper& rIntl ) const { OUString cpDelimTmp(cpDelim); @@ -648,39 +705,87 @@ bool SvxHyphenZoneItem::GetPresentation { case SfxItemPresentation::Nameless: { - const char* pId = RID_SVXITEMS_HYPHEN_FALSE; - + TranslateId pId = RID_SVXITEMS_HYPHEN_FALSE; if ( bHyphen ) pId = RID_SVXITEMS_HYPHEN_TRUE; - rText = EditResId(pId) + cpDelimTmp; - pId = RID_SVXITEMS_PAGE_END_FALSE; - - if ( bPageEnd ) - pId = RID_SVXITEMS_PAGE_END_TRUE; rText += EditResId(pId) + cpDelimTmp + OUString::number( nMinLead ) + cpDelimTmp + OUString::number( nMinTrail ) + cpDelimTmp + - OUString::number( nMaxHyphens ); + OUString::number( nCompoundMinLead ) + cpDelimTmp + + OUString::number( nMaxHyphens ) + cpDelimTmp + + OUString::number( nMinWordLength ) + cpDelimTmp + + GetMetricText( nTextHyphenZone, eCoreUnit, ePresUnit, &rIntl ) + + " " + EditResId(GetMetricId(ePresUnit)); + + if ( bNoCapsHyphenation ) + rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_NO_CAPS_TRUE); + + if ( bNoLastWordHyphenation ) + rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_LAST_WORD_TRUE); + + if ( bKeep ) + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_TRUE) + + cpDelimTmp + OUString::number( nKeepType ); + else + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_FALSE); return true; } case SfxItemPresentation::Complete: { - const char* pId = RID_SVXITEMS_HYPHEN_FALSE; + TranslateId pId = RID_SVXITEMS_HYPHEN_FALSE; if ( bHyphen ) pId = RID_SVXITEMS_HYPHEN_TRUE; - rText = EditResId(pId) + cpDelimTmp; - pId = RID_SVXITEMS_PAGE_END_FALSE; - - if ( bPageEnd ) - pId = RID_SVXITEMS_PAGE_END_TRUE; rText += EditResId(pId) + cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_MINLEAD).replaceAll("%1", OUString::number(nMinLead)) + cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_MINTRAIL).replaceAll("%1", OUString::number(nMinTrail)) + cpDelimTmp + - EditResId(RID_SVXITEMS_HYPHEN_MAX).replaceAll("%1", OUString::number(nMaxHyphens)); + EditResId(RID_SVXITEMS_HYPHEN_COMPOUND_MINLEAD).replaceAll("%1", OUString::number(nCompoundMinLead)) + + cpDelimTmp + + EditResId(RID_SVXITEMS_HYPHEN_MAX).replaceAll("%1", OUString::number(nMaxHyphens)) + + cpDelimTmp + + EditResId(RID_SVXITEMS_HYPHEN_MINWORDLEN).replaceAll("%1", OUString::number(nMinWordLength)); + + if ( nTextHyphenZone > 0 ) + { + rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_ZONE) + + GetMetricText( nTextHyphenZone, eCoreUnit, ePresUnit, &rIntl ) + + " " + EditResId(GetMetricId(ePresUnit)); + } + + if ( bNoCapsHyphenation ) + rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_NO_CAPS_TRUE); + + if ( bNoLastWordHyphenation ) + rText += cpDelimTmp + EditResId(RID_SVXITEMS_HYPHEN_LAST_WORD_TRUE); + + if ( bKeep ) + { + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_TRUE) + cpDelimTmp; + switch ( nKeepType ) + { + case 0: + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_AUTO); + break; + case 1: + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_SPREAD); + break; + case 2: + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_PAGE); + break; + case 3: + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_COLUMN); + break; + case 4: + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_ALWAYS); + break; + } + } + else + rText += EditResId(RID_SVXITEMS_HYPHEN_KEEP_FALSE); + return true; } default: ;//prevent warning @@ -728,8 +833,7 @@ void SvxTabStop::dumpAsXml(xmlTextWriterPtr pWriter) const // class SvxTabStopItem -------------------------------------------------- SvxTabStopItem::SvxTabStopItem( sal_uInt16 _nWhich ) : - SfxPoolItem( _nWhich ), - maTabStops() + SfxPoolItem( _nWhich ) { const sal_uInt16 nTabs = SVX_TAB_DEFCOUNT, nDist = SVX_TAB_DEFDIST; const SvxTabAdjust eAdjst= SvxTabAdjust::Default; @@ -746,8 +850,7 @@ SvxTabStopItem::SvxTabStopItem( const sal_uInt16 nTabs, const sal_uInt16 nDist, const SvxTabAdjust eAdjst, sal_uInt16 _nWhich ) : - SfxPoolItem( _nWhich ), - maTabStops() + SfxPoolItem( _nWhich ) { for ( sal_uInt16 i = 0; i < nTabs; ++i ) { @@ -770,6 +873,15 @@ sal_uInt16 SvxTabStopItem::GetPos( const sal_Int32 nPos ) const return it != maTabStops.end() ? it - maTabStops.begin() : SVX_TAB_NOTFOUND; } +void SvxTabStopItem::SetDefaultDistance(sal_Int32 nDefaultDistance) +{ + mnDefaultDistance = nDefaultDistance; +} + +sal_Int32 SvxTabStopItem::GetDefaultDistance() const +{ + return mnDefaultDistance; +} bool SvxTabStopItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const { @@ -808,6 +920,11 @@ bool SvxTabStopItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(rTab.GetTabPos()) : rTab.GetTabPos()); break; } + case MID_TABSTOP_DEFAULT_DISTANCE: + { + rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(mnDefaultDistance) : mnDefaultDistance); + break; + } } return true; } @@ -826,35 +943,37 @@ bool SvxTabStopItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) uno::Sequence < uno::Sequence < uno::Any > > aAnySeq; if (!(rVal >>= aAnySeq)) return false; + auto aAnySeqRange = asNonConstRange(aAnySeq); sal_Int32 nLength = aAnySeq.getLength(); aSeq.realloc( nLength ); + auto pSeq = aSeq.getArray(); for ( sal_Int32 n=0; n<nLength; n++ ) { - uno::Sequence < uno::Any >& rAnySeq = aAnySeq[n]; + uno::Sequence < uno::Any >& rAnySeq = aAnySeqRange[n]; if ( rAnySeq.getLength() == 4 ) { - if (!(rAnySeq[0] >>= aSeq[n].Position)) return false; - if (!(rAnySeq[1] >>= aSeq[n].Alignment)) + if (!(rAnySeq[0] >>= pSeq[n].Position)) return false; + if (!(rAnySeq[1] >>= pSeq[n].Alignment)) { sal_Int32 nVal = 0; if (rAnySeq[1] >>= nVal) - aSeq[n].Alignment = static_cast<css::style::TabAlign>(nVal); + pSeq[n].Alignment = static_cast<css::style::TabAlign>(nVal); else return false; } - if (!(rAnySeq[2] >>= aSeq[n].DecimalChar)) + if (!(rAnySeq[2] >>= pSeq[n].DecimalChar)) { OUString aVal; if ( (rAnySeq[2] >>= aVal) && aVal.getLength() == 1 ) - aSeq[n].DecimalChar = aVal.toChar(); + pSeq[n].DecimalChar = aVal.toChar(); else return false; } - if (!(rAnySeq[3] >>= aSeq[n].FillChar)) + if (!(rAnySeq[3] >>= pSeq[n].FillChar)) { OUString aVal; if ( (rAnySeq[3] >>= aVal) && aVal.getLength() == 1 ) - aSeq[n].FillChar = aVal.toChar(); + pSeq[n].FillChar = aVal.toChar(); else return false; } @@ -880,7 +999,7 @@ bool SvxTabStopItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) } sal_Unicode cFill = pArr[i].FillChar; sal_Unicode cDecimal = pArr[i].DecimalChar; - SvxTabStop aTab( bConvert ? convertMm100ToTwip(pArr[i].Position) : pArr[i].Position, + SvxTabStop aTab( bConvert ? o3tl::toTwips(pArr[i].Position, o3tl::Length::mm100) : pArr[i].Position, eAdjust, cDecimal, cFill ); @@ -894,7 +1013,7 @@ bool SvxTabStopItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if (!(rVal >>= nNewPos) ) return false; if (bConvert) - nNewPos = convertMm100ToTwip ( nNewPos ); + nNewPos = o3tl::toTwips(nNewPos, o3tl::Length::mm100); if (nNewPos <= 0) return false; const SvxTabStop& rTab = maTabStops.front(); @@ -903,6 +1022,18 @@ bool SvxTabStopItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) Insert( aNewTab ); break; } + case MID_TABSTOP_DEFAULT_DISTANCE: + { + sal_Int32 nNewDefaultDistance = 0; + if (!(rVal >>= nNewDefaultDistance)) + return false; + if (bConvert) + nNewDefaultDistance = o3tl::toTwips(nNewDefaultDistance, o3tl::Length::mm100); + if (nNewDefaultDistance < 0) + return false; + mnDefaultDistance = nNewDefaultDistance; + break; + } } return true; } @@ -914,6 +1045,9 @@ bool SvxTabStopItem::operator==( const SfxPoolItem& rAttr ) const const SvxTabStopItem& rTSI = static_cast<const SvxTabStopItem&>(rAttr); + if ( mnDefaultDistance != rTSI.GetDefaultDistance() ) + return false; + if ( Count() != rTSI.Count() ) return false; @@ -937,6 +1071,7 @@ bool SvxTabStopItem::GetPresentation ) const { rText.clear(); + // TODO also consider mnDefaultTabDistance here bool bComma = false; @@ -985,6 +1120,8 @@ void SvxTabStopItem::Insert( const SvxTabStopItem* pTabs ) void SvxTabStopItem::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxTabStopItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("mnDefaultDistance"), + BAD_CAST(OString::number(mnDefaultDistance).getStr())); for (const auto& rTabStop : maTabStops) rTabStop.dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); @@ -1008,7 +1145,7 @@ bool SvxFormatSplitItem::GetPresentation OUString& rText, const IntlWrapper& ) const { - const char* pId = RID_SVXITEMS_FMTSPLIT_FALSE; + TranslateId pId = RID_SVXITEMS_FMTSPLIT_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_FMTSPLIT_TRUE; @@ -1158,7 +1295,7 @@ bool SvxForbiddenRuleItem::GetPresentation( *************************************************************************/ SvxParaVertAlignItem::SvxParaVertAlignItem( Align nValue, - const sal_uInt16 nW ) + TypedWhichId<SvxParaVertAlignItem> nW ) : SfxUInt16Item( nW, static_cast<sal_uInt16>(nValue) ) { } @@ -1173,7 +1310,7 @@ bool SvxParaVertAlignItem::GetPresentation( MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/, OUString &rText, const IntlWrapper& ) const { - const char* pTmp; + TranslateId pTmp; switch( GetValue() ) { case Align::Automatic: pTmp = RID_SVXITEMS_PARAVERTALIGN_AUTO; break; diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx index f92c6851a8f3..db229190a403 100644 --- a/editeng/source/items/svxfont.cxx +++ b/editeng/source/items/svxfont.cxx @@ -17,6 +17,9 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <editeng/svxfont.hxx> + +#include <vcl/glyphitemcache.hxx> #include <vcl/metric.hxx> #include <vcl/outdev.hxx> #include <vcl/print.hxx> @@ -25,13 +28,22 @@ #include <tools/poly.hxx> #include <unotools/charclass.hxx> #include <com/sun/star/i18n/KCharacterType.hpp> -#include <editeng/svxfont.hxx> #include <editeng/escapementitem.hxx> +#include <editeng/smallcaps.hxx> #include <sal/log.hxx> +#include <limits> + +static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr, KernArray* pDXAry, + sal_Int32 nIndex, sal_Int32 nLen ) + +{ + const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen); + return basegfx::fround<tools::Long>(pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, true, nullptr, layoutGlyphs)); +} SvxFont::SvxFont() { - nKern = nEsc = 0; + nEsc = 0; nPropr = 100; eCaseMap = SvxCaseMap::NotMapped; SetLanguage(LANGUAGE_SYSTEM); @@ -40,7 +52,7 @@ SvxFont::SvxFont() SvxFont::SvxFont( const vcl::Font &rFont ) : Font( rFont ) { - nKern = nEsc = 0; + nEsc = 0; nPropr = 100; eCaseMap = SvxCaseMap::NotMapped; SetLanguage(LANGUAGE_SYSTEM); @@ -49,7 +61,6 @@ SvxFont::SvxFont( const vcl::Font &rFont ) SvxFont::SvxFont( const SvxFont &rFont ) : Font( rFont ) { - nKern = rFont.GetFixKerning(); nEsc = rFont.GetEscapement(); nPropr = rFont.GetPropr(); eCaseMap = rFont.GetCaseMap(); @@ -162,8 +173,7 @@ OUString SvxFont::CalcCaseMap(const OUString &rTxt) const const LanguageType eLang = LANGUAGE_DONTKNOW == GetLanguage() ? LANGUAGE_SYSTEM : GetLanguage(); - LanguageTag aLanguageTag(eLang); - CharClass aCharClass( aLanguageTag ); + CharClass aCharClass(( LanguageTag(eLang) )); switch( eCaseMap ) { @@ -211,40 +221,6 @@ OUString SvxFont::CalcCaseMap(const OUString &rTxt) const return aTxt; } -/************************************************************************* - * class SvxDoCapitals - * The virtual Method Do si called by SvxFont::DoOnCapitals alternately - * the uppercase and lowercase parts. The derivate of SvxDoCapitals fills - * this method with life. - *************************************************************************/ - -class SvxDoCapitals -{ -protected: - VclPtr<OutputDevice> pOut; - const OUString &rTxt; - const sal_Int32 nIdx; - const sal_Int32 nLen; - -public: - SvxDoCapitals( OutputDevice *_pOut, const OUString &_rTxt, - const sal_Int32 _nIdx, const sal_Int32 _nLen ) - : pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen) - { } - - virtual ~SvxDoCapitals() {} - - virtual void DoSpace( const bool bDraw ); - virtual void SetSpace(); - virtual void Do( const OUString &rTxt, - const sal_Int32 nIdx, const sal_Int32 nLen, - const bool bUpper ) = 0; - - const OUString &GetTxt() const { return rTxt; } - sal_Int32 GetIdx() const { return nIdx; } - sal_Int32 GetLen() const { return nLen; } -}; - void SvxDoCapitals::DoSpace( const bool /*bDraw*/ ) { } void SvxDoCapitals::SetSpace() { } @@ -272,8 +248,7 @@ void SvxFont::DoOnCapitals(SvxDoCapitals &rDo) const const LanguageType eLang = LANGUAGE_DONTKNOW == GetLanguage() ? LANGUAGE_SYSTEM : GetLanguage(); - LanguageTag aLanguageTag(eLang); - CharClass aCharClass( aLanguageTag ); + CharClass aCharClass(( LanguageTag(eLang) )); OUString aCharString; while( nPos < nTxtLen ) @@ -400,7 +375,7 @@ vcl::Font SvxFont::ChgPhysFont(OutputDevice& rOut) const Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt, const sal_Int32 nIdx, const sal_Int32 nLen ) const { - if ( !IsCaseMap() && !IsKern() ) + if ( !IsCaseMap() && !IsFixKerning() ) return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ), pOut->GetTextHeight() ); @@ -430,15 +405,30 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt, aTxtSize.setWidth(nWidth); } - if( IsKern() && ( nLen > 1 ) ) - aTxtSize.AdjustWidth( ( nLen-1 ) * tools::Long( nKern ) ); + if( IsFixKerning() && ( nLen > 1 ) ) + { + auto nKern = GetFixKerning(); + KernArray aDXArray; + GetTextArray(pOut, rTxt, &aDXArray, nIdx, nLen); + tools::Long nOldValue = aDXArray[0]; + sal_Int32 nSpaceCount = 0; + for(sal_Int32 i = 1; i < nLen; ++i) + { + if (aDXArray[i] != nOldValue) + { + nOldValue = aDXArray[i]; + ++nSpaceCount; + } + } + aTxtSize.AdjustWidth( nSpaceCount * tools::Long( nKern ) ); + } return aTxtSize; } Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut ) { - if ( !IsCaseMap() && !IsKern() ) + if ( !IsCaseMap() && !IsFixKerning() ) return Size( pOut->GetTextWidth( "" ), pOut->GetTextHeight() ); Size aTxtSize; @@ -452,32 +442,67 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut ) } Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, - const sal_Int32 nIdx, const sal_Int32 nLen, tools::Long* pDXArray ) const + const sal_Int32 nIdx, const sal_Int32 nLen, KernArray* pDXArray, bool bStacked ) const { - if ( !IsCaseMap() && !IsKern() ) - return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ), + if ( !IsCaseMap() && !IsFixKerning() ) + { + SAL_INFO( "editeng.quicktextsize", "SvxFont::QuickGetTextSize before GetTextArray(): Case map: " << IsCaseMap() << " Fix kerning: " << IsFixKerning()); + Size aTxtSize( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen ), pOut->GetTextHeight() ); + SAL_INFO( "editeng.quicktextsize", "SvxFont::QuickGetTextSize after GetTextArray(): Text length: " << nLen << " Text size: " << aTxtSize.Width() << "x" << aTxtSize.Height()); + return aTxtSize; + } + + KernArray aDXArray; + + // We always need pDXArray to count the number of kern spaces + if (!pDXArray && IsFixKerning() && nLen > 1) + { + pDXArray = &aDXArray; + aDXArray.reserve(nLen); + } Size aTxtSize; aTxtSize.setHeight( pOut->GetTextHeight() ); + SAL_INFO( "editeng.quicktextsize", "SvxFont::QuickGetTextSize before GetTextArray(): Case map: " << IsCaseMap() << " Fix kerning: " << IsFixKerning()); if ( !IsCaseMap() ) - aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) ); + aTxtSize.setWidth( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen ) ); else - aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ), - pDXArray, nIdx, nLen ) ); + { + if (IsCapital() && !rTxt.isEmpty()) + aTxtSize = GetCapitalSize(pOut, rTxt, pDXArray, nIdx, nLen); + else + aTxtSize.setWidth( GetTextArray( pOut, CalcCaseMap( rTxt ), + pDXArray, nIdx, nLen ) ); + } + SAL_INFO( "editeng.quicktextsize", "SvxFont::QuickGetTextSize after GetTextArray(): Text length: " << nLen << " Text size: " << aTxtSize.Width() << "x" << aTxtSize.Height()); - if( IsKern() && ( nLen > 1 ) ) + if( IsFixKerning() && ( nLen > 1 ) && !bStacked) { - aTxtSize.AdjustWidth( ( nLen-1 ) * tools::Long( nKern ) ); + auto nKern = GetFixKerning(); + tools::Long nOldValue = (*pDXArray)[0]; + tools::Long nSpaceSum = nKern; + pDXArray->adjust(0, nSpaceSum); - if ( pDXArray ) + for ( sal_Int32 i = 1; i < nLen; i++ ) { - for ( sal_Int32 i = 0; i < nLen; i++ ) - pDXArray[i] += ( (i+1) * tools::Long( nKern ) ); - // The last one is a nKern too big: - pDXArray[nLen-1] -= nKern; + if ( (*pDXArray)[i] != nOldValue ) + { + nOldValue = (*pDXArray)[i]; + nSpaceSum += nKern; + } + pDXArray->adjust(i, nSpaceSum); } + + // The last one is a nKern too big: + nOldValue = (*pDXArray)[nLen - 1]; + tools::Long nNewValue = nOldValue - nKern; + for ( sal_Int32 i = nLen - 1; i >= 0 && (*pDXArray)[i] == nOldValue; --i) + pDXArray->set(i, nNewValue); + + aTxtSize.AdjustWidth(nSpaceSum - nKern); } + return aTxtSize; } @@ -491,22 +516,33 @@ Size SvxFont::GetTextSize(const OutputDevice& rOut, const OUString &rTxt, Size aTxtSize; if( IsCapital() && !rTxt.isEmpty() ) { - aTxtSize = GetCapitalSize(&rOut, rTxt, nIdx, nTmp); + aTxtSize = GetCapitalSize(&rOut, rTxt, nullptr, nIdx, nTmp); } else aTxtSize = GetPhysTxtSize(&rOut,rTxt,nIdx,nTmp); const_cast<OutputDevice&>(rOut).SetFont(aOldFont); return aTxtSize; } +static void DrawTextArray( OutputDevice* pOut, const Point& rStartPt, const OUString& rStr, + std::span<const sal_Int32> pDXAry, + std::span<const sal_Bool> pKashidaAry, + sal_Int32 nIndex, sal_Int32 nLen ) +{ + const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen); + pOut->DrawTextArray(rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen, SalLayoutFlags::NONE, layoutGlyphs); +} + void SvxFont::QuickDrawText( OutputDevice *pOut, const Point &rPos, const OUString &rTxt, - const sal_Int32 nIdx, const sal_Int32 nLen, const tools::Long* pDXArray ) const + const sal_Int32 nIdx, const sal_Int32 nLen, + std::span<const sal_Int32> pDXArray, + std::span<const sal_Bool> pKashidaArray) const { // Font has to be selected in OutputDevice... - if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() ) + if ( !IsCaseMap() && !IsCapital() && !IsFixKerning() && !IsEsc() ) { - pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen ); + DrawTextArray( pOut, rPos, rTxt, pDXArray, pKashidaArray, nIdx, nLen ); return; } @@ -526,12 +562,11 @@ void SvxFont::QuickDrawText( OutputDevice *pOut, if( IsCapital() ) { - DBG_ASSERT( !pDXArray, "DrawCapital not for TextArray!" ); - DrawCapital( pOut, aPos, rTxt, nIdx, nLen ); + DrawCapital( pOut, aPos, rTxt, pDXArray, pKashidaArray, nIdx, nLen ); } else { - if ( IsKern() && !pDXArray ) + if ( IsFixKerning() && pDXArray.empty() ) { Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen ); @@ -543,9 +578,9 @@ void SvxFont::QuickDrawText( OutputDevice *pOut, else { if ( !IsCaseMap() ) - pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen ); + DrawTextArray( pOut, aPos, rTxt, pDXArray, pKashidaArray, nIdx, nLen ); else - pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen ); + DrawTextArray( pOut, aPos, CalcCaseMap( rTxt ), pDXArray, pKashidaArray, nIdx, nLen ); } } } @@ -587,7 +622,7 @@ void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter, Font aOldPrnFont( ChgPhysFont(*pPrinter) ); if ( IsCapital() ) - DrawCapital( pOut, aPos, rTxt, nIdx, nTmp ); + DrawCapital( pOut, aPos, rTxt, {}, {}, nIdx, nTmp ); else { Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp ); @@ -631,7 +666,6 @@ SvxFont& SvxFont::operator=( const SvxFont& rFont ) eCaseMap = rFont.eCaseMap; nEsc = rFont.nEsc; nPropr = rFont.nPropr; - nKern = rFont.nKern; return *this; } @@ -640,17 +674,27 @@ namespace { class SvxDoGetCapitalSize : public SvxDoCapitals { protected: + VclPtr<OutputDevice> pOut; SvxFont* pFont; Size aTxtSize; short nKern; + KernArray* pDXAry; public: SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut, - const OUString &_rTxt, const sal_Int32 _nIdx, + const OUString &_rTxt, KernArray* _pDXAry, const sal_Int32 _nIdx, const sal_Int32 _nLen, const short _nKrn ) - : SvxDoCapitals( const_cast<OutputDevice*>(_pOut), _rTxt, _nIdx, _nLen ), + : SvxDoCapitals( _rTxt, _nIdx, _nLen ), + pOut( const_cast<OutputDevice*>(_pOut) ), pFont( _pFnt ), - nKern( _nKrn ) - { } + nKern( _nKrn ), + pDXAry( _pDXAry ) + { + if (pDXAry) + { + pDXAry->clear(); + pDXAry->reserve(_nLen); + } + } virtual void Do( const OUString &rTxt, const sal_Int32 nIdx, const sal_Int32 nLen, const bool bUpper ) override; @@ -664,31 +708,50 @@ void SvxDoGetCapitalSize::Do( const OUString &_rTxt, const sal_Int32 _nIdx, const sal_Int32 _nLen, const bool bUpper ) { Size aPartSize; + sal_uInt8 nProp(0); if ( !bUpper ) { - sal_uInt8 nProp = pFont->GetPropr(); + nProp = pFont->GetPropr(); pFont->SetProprRel( SMALL_CAPS_PERCENTAGE ); pFont->SetPhysFont( *pOut ); - aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); - aPartSize.setHeight( pOut->GetTextHeight() ); - aTxtSize.setHeight( aPartSize.Height() ); - pFont->SetPropr( nProp ); - pFont->SetPhysFont( *pOut ); + } + + if (pDXAry) + { + KernArray aKernArray; + aPartSize.setWidth(basegfx::fround<tools::Long>(pOut->GetTextArray(_rTxt, &aKernArray, _nIdx, _nLen))); + assert(pDXAry->get_factor() == aKernArray.get_factor()); + auto& dest = pDXAry->get_subunit_array(); + sal_Int32 nStart = dest.empty() ? 0 : dest.back(); + size_t nSrcLen = aKernArray.size(); + dest.reserve(dest.size() + nSrcLen); + const auto& src = aKernArray.get_subunit_array(); + for (size_t i = 0; i < nSrcLen; ++i) + dest.push_back(src[i] + nStart); } else { aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); - aPartSize.setHeight( pOut->GetTextHeight() ); } + + aPartSize.setHeight( pOut->GetTextHeight() ); + + if ( !bUpper ) + { + aTxtSize.setHeight( aPartSize.Height() ); + pFont->SetPropr( nProp ); + pFont->SetPhysFont( *pOut ); + } + aTxtSize.AdjustWidth(aPartSize.Width() ); aTxtSize.AdjustWidth( _nLen * tools::Long( nKern ) ); } -Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const OUString &rTxt, +Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const OUString &rTxt, KernArray* pDXAry, const sal_Int32 nIdx, const sal_Int32 nLen) const { // Start: - SvxDoGetCapitalSize aDo( const_cast<SvxFont *>(this), pOut, rTxt, nIdx, nLen, nKern ); + SvxDoGetCapitalSize aDo( const_cast<SvxFont *>(this), pOut, rTxt, pDXAry, nIdx, nLen, GetFixKerning() ); DoOnCapitals( aDo ); Size aTxtSize( aDo.GetSize() ); @@ -706,19 +769,27 @@ namespace { class SvxDoDrawCapital : public SvxDoCapitals { protected: + VclPtr<OutputDevice> pOut; SvxFont *pFont; Point aPos; Point aSpacePos; short nKern; + std::span<const sal_Int32> pDXArray; + std::span<const sal_Bool> pKashidaArray; public: SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const OUString &_rTxt, + std::span<const sal_Int32> _pDXArray, + std::span<const sal_Bool> _pKashidaArray, const sal_Int32 _nIdx, const sal_Int32 _nLen, const Point &rPos, const short nKrn ) - : SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ), + : SvxDoCapitals( _rTxt, _nIdx, _nLen ), + pOut( _pOut ), pFont( pFnt ), aPos( rPos ), aSpacePos( rPos ), - nKern( nKrn ) + nKern( nKrn ), + pDXArray(_pDXArray), + pKashidaArray(_pKashidaArray) { } virtual void DoSpace( const bool bDraw ) override; virtual void SetSpace() override; @@ -733,7 +804,7 @@ void SvxDoDrawCapital::DoSpace( const bool bDraw ) if ( !(bDraw || pFont->IsWordLineMode()) ) return; - sal_uLong nDiff = static_cast<sal_uLong>(aPos.X() - aSpacePos.X()); + sal_Int32 nDiff = static_cast<sal_Int32>(aPos.X() - aSpacePos.X()); if ( nDiff ) { bool bWordWise = pFont->IsWordLineMode(); @@ -754,16 +825,17 @@ void SvxDoDrawCapital::SetSpace() aSpacePos.setX( aPos.X() ); } -void SvxDoDrawCapital::Do( const OUString &_rTxt, const sal_Int32 _nIdx, - const sal_Int32 _nLen, const bool bUpper) +void SvxDoDrawCapital::Do( const OUString &_rTxt, const sal_Int32 nSpanIdx, + const sal_Int32 nSpanLen, const bool bUpper) { sal_uInt8 nProp = 0; - Size aPartSize; // Set the desired font FontLineStyle eUnder = pFont->GetUnderline(); + FontLineStyle eOver = pFont->GetOverline(); FontStrikeout eStrike = pFont->GetStrikeout(); pFont->SetUnderline( LINESTYLE_NONE ); + pFont->SetOverline( LINESTYLE_NONE ); pFont->SetStrikeout( STRIKEOUT_NONE ); if ( !bUpper ) { @@ -772,24 +844,47 @@ void SvxDoDrawCapital::Do( const OUString &_rTxt, const sal_Int32 _nIdx, } pFont->SetPhysFont(*pOut); - aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); - aPartSize.setHeight( pOut->GetTextHeight() ); - tools::Long nWidth = aPartSize.Width(); - if ( nKern ) + if (pDXArray.empty()) { - aPos.AdjustX(nKern/2); - if ( _nLen ) nWidth += (_nLen*tools::Long(nKern)); + auto nWidth = pOut->GetTextWidth(_rTxt, nSpanIdx, nSpanLen); + if (nKern) + { + aPos.AdjustX(nKern/2); + if (nSpanLen) + nWidth += (nSpanLen * nKern); + } + pOut->DrawStretchText(aPos, nWidth-nKern, _rTxt, nSpanIdx, nSpanLen); + // in this case we move aPos along to be the start of each subspan + aPos.AdjustX(nWidth-(nKern/2) ); + } + else + { + const sal_Int32 nStartOffset = nSpanIdx - nIdx; + sal_Int32 nStartX = nStartOffset ? pDXArray[nStartOffset - 1] : 0; + + Point aStartPos(aPos.X() + nStartX, aPos.Y()); + + std::vector<sal_Int32> aDXArray; + aDXArray.reserve(nSpanLen); + for (sal_Int32 i = 0; i < nSpanLen; ++i) + aDXArray.push_back(pDXArray[nStartOffset + i] - nStartX); + + auto aKashidaArray = !pKashidaArray.empty() ? + std::span<const sal_Bool>(pKashidaArray.data() + nStartOffset, nSpanLen) : + std::span<const sal_Bool>(); + + DrawTextArray(pOut, aStartPos, _rTxt, aDXArray, aKashidaArray, nSpanIdx, nSpanLen); + // in this case we leave aPos at the start and use the DXArray to find the start + // of each subspan } - pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen); // Restore Font pFont->SetUnderline( eUnder ); + pFont->SetOverline( eOver ); pFont->SetStrikeout( eStrike ); if ( !bUpper ) pFont->SetPropr( nProp ); pFont->SetPhysFont(*pOut); - - aPos.AdjustX(nWidth-(nKern/2) ); } /************************************************************************* @@ -798,9 +893,13 @@ void SvxDoDrawCapital::Do( const OUString &_rTxt, const sal_Int32 _nIdx, void SvxFont::DrawCapital( OutputDevice *pOut, const Point &rPos, const OUString &rTxt, + std::span<const sal_Int32> pDXArray, + std::span<const sal_Bool> pKashidaArray, const sal_Int32 nIdx, const sal_Int32 nLen ) const { - SvxDoDrawCapital aDo( const_cast<SvxFont *>(this),pOut,rTxt,nIdx,nLen,rPos,nKern ); + SvxDoDrawCapital aDo(const_cast<SvxFont *>(this), pOut, + rTxt, pDXArray, pKashidaArray, + nIdx, nLen, rPos, GetFixKerning()); DoOnCapitals( aDo ); } diff --git a/editeng/source/items/textitem.cxx b/editeng/source/items/textitem.cxx index 53f5328890b2..b4fa77d59d6f 100644 --- a/editeng/source/items/textitem.cxx +++ b/editeng/source/items/textitem.cxx @@ -24,9 +24,11 @@ #include <sal/log.hxx> #include <o3tl/safeint.hxx> #include <osl/diagnose.h> +#include <comphelper/configuration.hxx> #include <unotools/fontdefs.hxx> #include <unotools/intlwrapper.hxx> #include <unotools/syslocale.hxx> +#include <utility> #include <vcl/outdev.hxx> #include <vcl/unohelp.hxx> #include <svtools/unitconv.hxx> @@ -76,7 +78,11 @@ #include <editeng/charreliefitem.hxx> #include <editeng/itemtype.hxx> #include <editeng/eerdll.hxx> +#include <docmodel/color/ComplexColorJSON.hxx> +#include <docmodel/uno/UnoComplexColor.hxx> +#include <docmodel/color/ComplexColor.hxx> #include <libxml/xmlwriter.h> +#include <unordered_map> using namespace ::com::sun::star; using namespace ::com::sun::star::text; @@ -97,12 +103,11 @@ SfxPoolItem* SvxKerningItem::CreateDefault() {return new SvxKerningItem(0, 0);} SfxPoolItem* SvxCaseMapItem::CreateDefault() {return new SvxCaseMapItem(SvxCaseMap::NotMapped, 0);} SfxPoolItem* SvxEscapementItem::CreateDefault() {return new SvxEscapementItem(0);} SfxPoolItem* SvxLanguageItem::CreateDefault() {return new SvxLanguageItem(LANGUAGE_GERMAN, 0);} -SfxPoolItem* SvxEmphasisMarkItem::CreateDefault() {return new SvxEmphasisMarkItem(FontEmphasisMark::NONE, 0);} -SfxPoolItem* SvxCharRotateItem::CreateDefault() {return new SvxCharRotateItem(0_deg10, false, 0);} -SfxPoolItem* SvxCharScaleWidthItem::CreateDefault() {return new SvxCharScaleWidthItem(100, 0);} +SfxPoolItem* SvxEmphasisMarkItem::CreateDefault() {return new SvxEmphasisMarkItem(FontEmphasisMark::NONE, TypedWhichId<SvxEmphasisMarkItem>(0));} +SfxPoolItem* SvxCharRotateItem::CreateDefault() {return new SvxCharRotateItem(0_deg10, false, TypedWhichId<SvxCharRotateItem>(0));} +SfxPoolItem* SvxCharScaleWidthItem::CreateDefault() {return new SvxCharScaleWidthItem(100, TypedWhichId<SvxCharScaleWidthItem>(0));} SfxPoolItem* SvxCharReliefItem::CreateDefault() {return new SvxCharReliefItem(FontRelief::NONE, 0);} - // class SvxFontListItem ------------------------------------------------- SvxFontListItem::SvxFontListItem( const FontList* pFontLst, @@ -114,9 +119,10 @@ SvxFontListItem::SvxFontListItem( const FontList* pFontLst, { sal_Int32 nCount = pFontList->GetFontNameCount(); aFontNameSeq.realloc( nCount ); + auto pFontNameSeq = aFontNameSeq.getArray(); for ( sal_Int32 i = 0; i < nCount; i++ ) - aFontNameSeq[i] = pFontList->GetFontName(i).GetFamilyName(); + pFontNameSeq[i] = pFontList->GetFontName(i).GetFamilyName(); } } @@ -153,29 +159,94 @@ bool SvxFontListItem::GetPresentation // class SvxFontItem ----------------------------------------------------- -SvxFontItem::SvxFontItem( const sal_uInt16 nId ) : - SfxPoolItem( nId ) +typedef std::unordered_map<size_t, const SfxPoolItem*> SvxFontItemMap; + +namespace { - eFamily = FAMILY_SWISS; - ePitch = PITCH_VARIABLE; - eTextEncoding = RTL_TEXTENCODING_DONTKNOW; -} + class SvxFontItemInstanceManager : public ItemInstanceManager + { + SvxFontItemMap maRegistered; + public: + SvxFontItemInstanceManager() + : ItemInstanceManager(typeid(SvxFontItem).hash_code()) + { + } -SvxFontItem::SvxFontItem( const FontFamily eFam, const OUString& aName, - const OUString& aStName, const FontPitch eFontPitch, - const rtl_TextEncoding eFontTextEncoding, const sal_uInt16 nId ) : + private: + static size_t hashCode(const SfxPoolItem&); - SfxPoolItem( nId ), + // standard interface, accessed exclusively + // by implCreateItemEntry/implCleanupItemEntry + virtual const SfxPoolItem* find(const SfxPoolItem&) const override; + virtual void add(const SfxPoolItem&) override; + virtual void remove(const SfxPoolItem&) override; + }; + + size_t SvxFontItemInstanceManager::hashCode(const SfxPoolItem& rItem) + { + const SvxFontItem& rFontItem(static_cast<const SvxFontItem&>(rItem)); + std::size_t seed(0); + o3tl::hash_combine(seed, rItem.Which()); + o3tl::hash_combine(seed, rFontItem.GetFamilyName().hashCode()); + o3tl::hash_combine(seed, rFontItem.GetStyleName().hashCode()); + o3tl::hash_combine(seed, rFontItem.GetFamily()); + o3tl::hash_combine(seed, rFontItem.GetPitch()); + o3tl::hash_combine(seed, rFontItem.GetCharSet()); + return seed; + } + + const SfxPoolItem* SvxFontItemInstanceManager::find(const SfxPoolItem& rItem) const + { + SvxFontItemMap::const_iterator aHit(maRegistered.find(hashCode(rItem))); + if (aHit != maRegistered.end()) + return aHit->second; + return nullptr; + } + + void SvxFontItemInstanceManager::add(const SfxPoolItem& rItem) + { + maRegistered.insert({hashCode(rItem), &rItem}); + } + + void SvxFontItemInstanceManager::remove(const SfxPoolItem& rItem) + { + maRegistered.erase(hashCode(rItem)); + } +} + +ItemInstanceManager* SvxFontItem::getItemInstanceManager() const +{ + static SvxFontItemInstanceManager aInstanceManager; + return &aInstanceManager; +} - aFamilyName(aName), - aStyleName(aStName) +SvxFontItem::SvxFontItem( + const sal_uInt16 nId) +: SfxPoolItem( nId ) +, aFamilyName() +, aStyleName() +, eFamily(FAMILY_SWISS) +, ePitch(PITCH_VARIABLE) +, eTextEncoding(RTL_TEXTENCODING_DONTKNOW) { - eFamily = eFam; - ePitch = eFontPitch; - eTextEncoding = eFontTextEncoding; } +SvxFontItem::SvxFontItem( + const FontFamily eFam, + OUString aName, + OUString aStName, + const FontPitch eFontPitch, + const rtl_TextEncoding eFontTextEncoding, + const sal_uInt16 nId) +: SfxPoolItem( nId ) +, aFamilyName(std::move(aName)) +, aStyleName(std::move(aStName)) +, eFamily(eFam) +, ePitch(eFontPitch) +, eTextEncoding(eFontTextEncoding) +{ +} bool SvxFontItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const { @@ -217,6 +288,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) if ( !( rVal >>= aFontDescriptor )) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; aFamilyName = aFontDescriptor.Name; aStyleName = aFontDescriptor.StyleName; eFamily = static_cast<FontFamily>(aFontDescriptor.Family); @@ -229,6 +301,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) OUString aStr; if(!(rVal >>= aStr)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; aFamilyName = aStr; } break; @@ -237,6 +310,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) OUString aStr; if(!(rVal >>= aStr)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; aStyleName = aStr; } break; @@ -245,6 +319,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) sal_Int16 nFamily = sal_Int16(); if(!(rVal >>= nFamily)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; eFamily = static_cast<FontFamily>(nFamily); } break; @@ -253,6 +328,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) sal_Int16 nSet = sal_Int16(); if(!(rVal >>= nSet)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; eTextEncoding = static_cast<rtl_TextEncoding>(nSet); } break; @@ -261,6 +337,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) sal_Int16 nPitch = sal_Int16(); if(!(rVal >>= nPitch)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; ePitch = static_cast<FontPitch>(nPitch); } break; @@ -268,13 +345,58 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) return true; } +void SvxFontItem::SetFamilyName(const OUString& rFamilyName) +{ + if (aFamilyName == rFamilyName) + return; -bool SvxFontItem::operator==( const SfxPoolItem& rAttr ) const + ASSERT_CHANGE_REFCOUNTED_ITEM; + aFamilyName = rFamilyName; +} + +void SvxFontItem::SetStyleName(const OUString &rStyleName) { - assert(SfxPoolItem::operator==(rAttr)); + if (aStyleName == rStyleName) + return; + + ASSERT_CHANGE_REFCOUNTED_ITEM; + aStyleName = rStyleName; +} - const SvxFontItem& rItem = static_cast<const SvxFontItem&>(rAttr); +void SvxFontItem::SetFamily(FontFamily _eFamily) +{ + if (eFamily == _eFamily) + return; + + ASSERT_CHANGE_REFCOUNTED_ITEM; + eFamily = _eFamily; +} + +void SvxFontItem::SetPitch(FontPitch _ePitch) +{ + if (ePitch == _ePitch) + return; + + ASSERT_CHANGE_REFCOUNTED_ITEM; + ePitch = _ePitch; +} + +void SvxFontItem::SetCharSet(rtl_TextEncoding _eEncoding) +{ + if (eTextEncoding == _eEncoding) + return; + + ASSERT_CHANGE_REFCOUNTED_ITEM; + eTextEncoding = _eEncoding; +} +bool SvxFontItem::operator==( const SfxPoolItem& rAttr ) const +{ + if (this == &rAttr) + return true; + + assert(SfxPoolItem::operator==(rAttr)); + const SvxFontItem& rItem(static_cast<const SvxFontItem&>(rAttr)); bool bRet = ( eFamily == rItem.eFamily && aFamilyName == rItem.aFamilyName && aStyleName == rItem.aStyleName ); @@ -287,6 +409,7 @@ bool SvxFontItem::operator==( const SfxPoolItem& rAttr ) const SAL_INFO( "editeng.items", "FontItem::operator==(): only pitch or rtl_TextEncoding different "); } } + return bRet; } @@ -322,6 +445,12 @@ void SvxFontItem::dumpAsXml(xmlTextWriterPtr pWriter) const // class SvxPostureItem -------------------------------------------------- +ItemInstanceManager* SvxPostureItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxPostureItem).hash_code()); + return &aInstanceManager; +} + SvxPostureItem::SvxPostureItem( const FontItalic ePosture, const sal_uInt16 nId ) : SfxEnumItem( nId, ePosture ) { @@ -356,7 +485,7 @@ OUString SvxPostureItem::GetValueTextByPos( sal_uInt16 nPos ) DBG_ASSERT( nPos <= sal_uInt16(ITALIC_NORMAL), "enum overflow!" ); FontItalic eItalic = static_cast<FontItalic>(nPos); - const char* pId = nullptr; + TranslateId pId; switch ( eItalic ) { @@ -390,6 +519,7 @@ bool SvxPostureItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) switch( nMemberId ) { case MID_ITALIC: + ASSERT_CHANGE_REFCOUNTED_ITEM; SetBoolValue(Any2Bool(rVal)); break; case MID_POSTURE: @@ -403,6 +533,7 @@ bool SvxPostureItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) eSlant = static_cast<awt::FontSlant>(nValue); } + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue(vcl::unohelper::ConvertFontSlant(eSlant)); } } @@ -421,6 +552,7 @@ bool SvxPostureItem::GetBoolValue() const void SvxPostureItem::SetBoolValue( bool bVal ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( bVal ? ITALIC_NORMAL : ITALIC_NONE ); } @@ -435,6 +567,12 @@ void SvxPostureItem::dumpAsXml(xmlTextWriterPtr pWriter) const // class SvxWeightItem --------------------------------------------------- +ItemInstanceManager* SvxWeightItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxWeightItem).hash_code()); + return &aInstanceManager; +} + SvxWeightItem::SvxWeightItem( const FontWeight eWght, const sal_uInt16 nId ) : SfxEnumItem( nId, eWght ) { @@ -455,6 +593,7 @@ bool SvxWeightItem::GetBoolValue() const void SvxWeightItem::SetBoolValue( bool bVal ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( bVal ? WEIGHT_BOLD : WEIGHT_NORMAL ); } @@ -483,7 +622,7 @@ bool SvxWeightItem::GetPresentation OUString SvxWeightItem::GetValueTextByPos( sal_uInt16 nPos ) { - static const char* RID_SVXITEMS_WEIGHTS[] = + static TranslateId RID_SVXITEMS_WEIGHTS[] = { RID_SVXITEMS_WEIGHT_DONTKNOW, RID_SVXITEMS_WEIGHT_THIN, @@ -498,7 +637,7 @@ OUString SvxWeightItem::GetValueTextByPos( sal_uInt16 nPos ) RID_SVXITEMS_WEIGHT_BLACK }; - static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_WEIGHTS) - 1 == WEIGHT_BLACK, "must match"); + static_assert(std::size(RID_SVXITEMS_WEIGHTS) - 1 == WEIGHT_BLACK, "must match"); assert(nPos <= sal_uInt16(WEIGHT_BLACK) && "enum overflow!" ); return EditResId(RID_SVXITEMS_WEIGHTS[nPos]); } @@ -526,6 +665,7 @@ bool SvxWeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) switch( nMemberId ) { case MID_BOLD : + ASSERT_CHANGE_REFCOUNTED_ITEM; SetBoolValue(Any2Bool(rVal)); break; case MID_WEIGHT: @@ -538,6 +678,7 @@ bool SvxWeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) return false; fValue = static_cast<float>(nValue); } + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( vcl::unohelper::ConvertFontWeight(static_cast<float>(fValue)) ); } break; @@ -556,6 +697,12 @@ void SvxWeightItem::dumpAsXml(xmlTextWriterPtr pWriter) const // class SvxFontHeightItem ----------------------------------------------- +ItemInstanceManager* SvxFontHeightItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxFontHeightItem).hash_code()); + return &aInstanceManager; +} + SvxFontHeightItem::SvxFontHeightItem( const sal_uInt32 nSz, const sal_uInt16 nPrp, const sal_uInt16 nId ) : @@ -594,33 +741,30 @@ bool SvxFontHeightItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const // CONVERT_TWIPS is not set. if( bConvert ) { - aFontHeight.Height = static_cast<float>( nHeight / 20.0 ); + aFontHeight.Height = o3tl::convert<double>(nHeight, o3tl::Length::twip, o3tl::Length::pt); } else { - double fPoints = convertMm100ToTwip(nHeight) / 20.0; - float fRoundPoints = - static_cast<float>(::rtl::math::round(fPoints, 1)); - aFontHeight.Height = fRoundPoints; + double fPoints = o3tl::convert<double>(nHeight, o3tl::Length::mm100, o3tl::Length::pt); + aFontHeight.Height = rtl::math::round(fPoints, 1); } - aFontHeight.Prop = static_cast<sal_Int16>(MapUnit::MapRelative == ePropUnit ? nProp : 100); + aFontHeight.Prop = MapUnit::MapRelative == ePropUnit ? nProp : 100; - float fRet = static_cast<float>(static_cast<short>(nProp)); + float fRet = nProp; switch( ePropUnit ) { case MapUnit::MapRelative: fRet = 0.; break; case MapUnit::Map100thMM: - fRet = convertMm100ToTwip(fRet); - fRet /= 20.; + fRet = o3tl::convert(fRet, o3tl::Length::mm100, o3tl::Length::pt); break; case MapUnit::MapPoint: break; case MapUnit::MapTwip: - fRet /= 20.; + fRet = o3tl::convert(fRet, o3tl::Length::twip, o3tl::Length::pt); break; default: ;//prevent warning } @@ -634,14 +778,12 @@ bool SvxFontHeightItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const // CONVERT_TWIPS is not set. if( bConvert ) { - rVal <<= static_cast<float>( nHeight / 20.0 ); + rVal <<= static_cast<float>(o3tl::convert<double>(nHeight, o3tl::Length::twip, o3tl::Length::pt)); } else { - double fPoints = convertMm100ToTwip(nHeight) / 20.0; - float fRoundPoints = - static_cast<float>(::rtl::math::round(fPoints, 1)); - rVal <<= fRoundPoints; + double fPoints = o3tl::convert<double>(nHeight, o3tl::Length::mm100, o3tl::Length::pt); + rVal <<= static_cast<float>(::rtl::math::round(fPoints, 1)); } } break; @@ -650,21 +792,20 @@ bool SvxFontHeightItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const break; case MID_FONTHEIGHT_DIFF: { - float fRet = static_cast<float>(static_cast<short>(nProp)); + float fRet = nProp; switch( ePropUnit ) { case MapUnit::MapRelative: fRet = 0.; break; case MapUnit::Map100thMM: - fRet = convertMm100ToTwip(fRet); - fRet /= 20.; + fRet = o3tl::convert(fRet, o3tl::Length::mm100, o3tl::Length::pt); break; case MapUnit::MapPoint: break; case MapUnit::MapTwip: - fRet /= 20.; + fRet = o3tl::convert(fRet, o3tl::Length::twip, o3tl::Length::pt); break; default: ;//prevent warning } @@ -739,6 +880,7 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if( fPoint < 0. || fPoint > 10000. ) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; nHeight = static_cast<tools::Long>( fPoint * 20.0 + 0.5 ); // Twips if (!bConvert) nHeight = convertTwipToMm100(nHeight); // Convert, if the item contains 1/100mm @@ -761,9 +903,17 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) return false; fPoint = static_cast<float>(nValue); } - if(fPoint < 0. || fPoint > 10000.) - return false; + if (fPoint < 0. || fPoint > 10000.) + return false; + static bool bFuzzing = comphelper::IsFuzzing(); + if (bFuzzing && fPoint > 120) + { + SAL_WARN("editeng.items", "SvxFontHeightItem ignoring font size of " << fPoint << " for performance"); + return false; + } + + ASSERT_CHANGE_REFCOUNTED_ITEM; nHeight = static_cast<tools::Long>( fPoint * 20.0 + 0.5 ); // Twips if (!bConvert) nHeight = convertTwipToMm100(nHeight); // Convert, if the item contains 1/100mm @@ -775,6 +925,7 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= nNew)) return true; + ASSERT_CHANGE_REFCOUNTED_ITEM; nHeight = lcl_GetRealHeight_Impl(nHeight, nProp, ePropUnit, bConvert); nHeight *= nNew; @@ -794,6 +945,7 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) return false; fValue = static_cast<float>(nValue); } + ASSERT_CHANGE_REFCOUNTED_ITEM; sal_Int16 nCoreDiffValue = static_cast<sal_Int16>(fValue * 20.); nHeight += bConvert ? nCoreDiffValue : convertTwipToMm100(nCoreDiffValue); nProp = static_cast<sal_uInt16>(static_cast<sal_Int16>(fValue)); @@ -834,6 +986,7 @@ bool SvxFontHeightItem::GetPresentation void SvxFontHeightItem::ScaleMetrics( tools::Long nMult, tools::Long nDiv ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; nHeight = static_cast<sal_uInt32>(BigInt::Scale( nHeight, nMult, nDiv )); } @@ -848,6 +1001,7 @@ void SvxFontHeightItem::SetHeight( sal_uInt32 nNewHeight, const sal_uInt16 nNewP { DBG_ASSERT( GetRefCount() == 0, "SetValue() with pooled item" ); + ASSERT_CHANGE_REFCOUNTED_ITEM; if( MapUnit::MapRelative != eUnit ) nHeight = nNewHeight + ::ItemToControl( short(nNewProp), eUnit, FieldUnit::TWIP ); @@ -865,6 +1019,7 @@ void SvxFontHeightItem::SetHeight( sal_uInt32 nNewHeight, sal_uInt16 nNewProp, { DBG_ASSERT( GetRefCount() == 0, "SetValue() with pooled item" ); + ASSERT_CHANGE_REFCOUNTED_ITEM; if( MapUnit::MapRelative != eMetric ) nHeight = nNewHeight + ::ControlToItem( ::ItemToControl(static_cast<short>(nNewProp), eMetric, @@ -892,7 +1047,8 @@ void SvxFontHeightItem::dumpAsXml(xmlTextWriterPtr pWriter) const // class SvxTextLineItem ------------------------------------------------ SvxTextLineItem::SvxTextLineItem( const FontLineStyle eSt, const sal_uInt16 nId ) - : SfxEnumItem( nId, eSt ), mColor( COL_TRANSPARENT ) + : SfxEnumItem(nId, eSt) + , maColor(COL_TRANSPARENT) { } @@ -911,6 +1067,7 @@ bool SvxTextLineItem::GetBoolValue() const void SvxTextLineItem::SetBoolValue( bool bVal ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( bVal ? LINESTYLE_SINGLE : LINESTYLE_NONE ); } @@ -934,8 +1091,8 @@ bool SvxTextLineItem::GetPresentation ) const { rText = GetValueTextByPos( GetValue() ); - if( !mColor.IsTransparent() ) - rText += cpDelim + ::GetColorString( mColor ); + if( !maColor.IsTransparent() ) + rText += cpDelim + ::GetColorString(maColor); return true; } @@ -958,14 +1115,19 @@ bool SvxTextLineItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const rVal <<= static_cast<sal_Int16>(GetValue()); break; case MID_TL_COLOR: - rVal <<= mColor; + rVal <<= maColor; break; + case MID_TL_COMPLEX_COLOR: + { + auto xComplexColor = model::color::createXComplexColor(maComplexColor); + rVal <<= xComplexColor; + break; + } case MID_TL_HASCOLOR: - rVal <<= mColor.GetAlpha() == 255; + rVal <<= maColor.GetAlpha() == 255; break; } return true; - } bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) @@ -975,6 +1137,7 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) switch(nMemberId) { case MID_TEXTLINED: + ASSERT_CHANGE_REFCOUNTED_ITEM; SetBoolValue(Any2Bool(rVal)); break; case MID_TL_STYLE: @@ -983,7 +1146,10 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= nValue)) bRet = false; else + { + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue(static_cast<FontLineStyle>(nValue)); + } } break; case MID_TL_COLOR: @@ -995,14 +1161,29 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) { // Keep transparence, because it contains the information // whether the font color or the stored color should be used - sal_uInt8 nAlpha = mColor.GetAlpha(); - mColor = nCol; - mColor.SetAlpha( nAlpha ); + ASSERT_CHANGE_REFCOUNTED_ITEM; + sal_uInt8 nAlpha = maColor.GetAlpha(); + maColor = nCol; + maColor.SetAlpha( nAlpha ); + } + } + break; + case MID_TL_COMPLEX_COLOR: + { + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rVal >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + { + ASSERT_CHANGE_REFCOUNTED_ITEM; + maComplexColor = model::color::getFromXComplexColor(xComplexColor); } } break; case MID_TL_HASCOLOR: - mColor.SetAlpha( Any2Bool( rVal ) ? 255 : 0 ); + ASSERT_CHANGE_REFCOUNTED_ITEM; + maColor.SetAlpha( Any2Bool( rVal ) ? 255 : 0 ); break; } return bRet; @@ -1011,11 +1192,17 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) bool SvxTextLineItem::operator==( const SfxPoolItem& rItem ) const { return SfxEnumItem::operator==( rItem ) && - GetColor() == static_cast<const SvxTextLineItem&>(rItem).GetColor(); + maColor == static_cast<const SvxTextLineItem&>(rItem).maColor && + maComplexColor == static_cast<const SvxTextLineItem&>(rItem).maComplexColor; } // class SvxUnderlineItem ------------------------------------------------ +ItemInstanceManager* SvxUnderlineItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxUnderlineItem).hash_code()); + return &aInstanceManager; +} SvxUnderlineItem::SvxUnderlineItem( const FontLineStyle eSt, const sal_uInt16 nId ) : SvxTextLineItem( eSt, nId ) @@ -1029,7 +1216,7 @@ SvxUnderlineItem* SvxUnderlineItem::Clone( SfxItemPool * ) const OUString SvxUnderlineItem::GetValueTextByPos( sal_uInt16 nPos ) const { - static const char* RID_SVXITEMS_UL[] = + static TranslateId RID_SVXITEMS_UL[] = { RID_SVXITEMS_UL_NONE, RID_SVXITEMS_UL_SINGLE, @@ -1051,13 +1238,19 @@ OUString SvxUnderlineItem::GetValueTextByPos( sal_uInt16 nPos ) const RID_SVXITEMS_UL_BOLDDASHDOTDOT, RID_SVXITEMS_UL_BOLDWAVE }; - static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_UL) - 1 == LINESTYLE_BOLDWAVE, "must match"); + static_assert(std::size(RID_SVXITEMS_UL) - 1 == LINESTYLE_BOLDWAVE, "must match"); assert(nPos <= sal_uInt16(LINESTYLE_BOLDWAVE) && "enum overflow!"); return EditResId(RID_SVXITEMS_UL[nPos]); } // class SvxOverlineItem ------------------------------------------------ +ItemInstanceManager* SvxOverlineItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxOverlineItem).hash_code()); + return &aInstanceManager; +} + SvxOverlineItem::SvxOverlineItem( const FontLineStyle eSt, const sal_uInt16 nId ) : SvxTextLineItem( eSt, nId ) { @@ -1070,7 +1263,7 @@ SvxOverlineItem* SvxOverlineItem::Clone( SfxItemPool * ) const OUString SvxOverlineItem::GetValueTextByPos( sal_uInt16 nPos ) const { - static const char* RID_SVXITEMS_OL[] = + static TranslateId RID_SVXITEMS_OL[] = { RID_SVXITEMS_OL_NONE, RID_SVXITEMS_OL_SINGLE, @@ -1092,13 +1285,19 @@ OUString SvxOverlineItem::GetValueTextByPos( sal_uInt16 nPos ) const RID_SVXITEMS_OL_BOLDDASHDOTDOT, RID_SVXITEMS_OL_BOLDWAVE }; - static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_OL) - 1 == LINESTYLE_BOLDWAVE, "must match"); + static_assert(std::size(RID_SVXITEMS_OL) - 1 == LINESTYLE_BOLDWAVE, "must match"); assert(nPos <= sal_uInt16(LINESTYLE_BOLDWAVE) && "enum overflow!"); return EditResId(RID_SVXITEMS_OL[nPos]); } // class SvxCrossedOutItem ----------------------------------------------- +ItemInstanceManager* SvxCrossedOutItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxCrossedOutItem).hash_code()); + return &aInstanceManager; +} + SvxCrossedOutItem::SvxCrossedOutItem( const FontStrikeout eSt, const sal_uInt16 nId ) : SfxEnumItem( nId, eSt ) { @@ -1119,6 +1318,7 @@ bool SvxCrossedOutItem::GetBoolValue() const void SvxCrossedOutItem::SetBoolValue( bool bVal ) { + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( bVal ? STRIKEOUT_SINGLE : STRIKEOUT_NONE ); } @@ -1147,7 +1347,7 @@ bool SvxCrossedOutItem::GetPresentation OUString SvxCrossedOutItem::GetValueTextByPos( sal_uInt16 nPos ) { - static const char* RID_SVXITEMS_STRIKEOUT[] = + static TranslateId RID_SVXITEMS_STRIKEOUT[] = { RID_SVXITEMS_STRIKEOUT_NONE, RID_SVXITEMS_STRIKEOUT_SINGLE, @@ -1157,7 +1357,7 @@ OUString SvxCrossedOutItem::GetValueTextByPos( sal_uInt16 nPos ) RID_SVXITEMS_STRIKEOUT_SLASH, RID_SVXITEMS_STRIKEOUT_X }; - static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_STRIKEOUT) - 1 == STRIKEOUT_X, "must match"); + static_assert(std::size(RID_SVXITEMS_STRIKEOUT) - 1 == STRIKEOUT_X, "must match"); assert(nPos <= sal_uInt16(STRIKEOUT_X) && "enum overflow!"); return EditResId(RID_SVXITEMS_STRIKEOUT[nPos]); } @@ -1190,6 +1390,7 @@ bool SvxCrossedOutItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) sal_Int32 nValue = 0; if(!(rVal >>= nValue)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue(static_cast<FontStrikeout>(nValue)); } break; @@ -1216,7 +1417,7 @@ bool SvxShadowedItem::GetPresentation OUString& rText, const IntlWrapper& /*rIntl*/ ) const { - const char* pId = RID_SVXITEMS_SHADOWED_FALSE; + TranslateId pId = RID_SVXITEMS_SHADOWED_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_SHADOWED_TRUE; @@ -1244,7 +1445,7 @@ bool SvxAutoKernItem::GetPresentation OUString& rText, const IntlWrapper& /*rIntl*/ ) const { - const char* pId = RID_SVXITEMS_AUTOKERN_FALSE; + TranslateId pId = RID_SVXITEMS_AUTOKERN_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_AUTOKERN_TRUE; @@ -1273,7 +1474,7 @@ bool SvxWordLineModeItem::GetPresentation OUString& rText, const IntlWrapper& /*rIntl*/ ) const { - const char* pId = RID_SVXITEMS_WORDLINE_FALSE; + TranslateId pId = RID_SVXITEMS_WORDLINE_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_WORDLINE_TRUE; @@ -1301,7 +1502,7 @@ bool SvxContourItem::GetPresentation OUString& rText, const IntlWrapper& /*rIntl*/ ) const { - const char* pId = RID_SVXITEMS_CONTOUR_FALSE; + TranslateId pId = RID_SVXITEMS_CONTOUR_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_CONTOUR_TRUE; @@ -1311,7 +1512,7 @@ bool SvxContourItem::GetPresentation // class SvxColorItem ---------------------------------------------------- SvxColorItem::SvxColorItem( const sal_uInt16 nId ) : - SfxPoolItem( nId ), + SfxPoolItem(nId), mColor( COL_BLACK ) { } @@ -1322,6 +1523,13 @@ SvxColorItem::SvxColorItem( const Color& rCol, const sal_uInt16 nId ) : { } +SvxColorItem::SvxColorItem(Color const& rColor, model::ComplexColor const& rComplexColor, const sal_uInt16 nId) + : SfxPoolItem(nId) + , mColor(rColor) + , maComplexColor(rComplexColor) +{ +} + SvxColorItem::~SvxColorItem() { } @@ -1329,8 +1537,10 @@ SvxColorItem::~SvxColorItem() bool SvxColorItem::operator==( const SfxPoolItem& rAttr ) const { assert(SfxPoolItem::operator==(rAttr)); + const SvxColorItem& rColorItem = static_cast<const SvxColorItem&>(rAttr); - return mColor == static_cast<const SvxColorItem&>( rAttr ).mColor; + return mColor == rColorItem.mColor && + maComplexColor == rColorItem.maComplexColor; } bool SvxColorItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const @@ -1349,6 +1559,58 @@ bool SvxColorItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const rVal <<= mColor.GetAlpha() == 0; break; } + case MID_COLOR_THEME_INDEX: + { + rVal <<= sal_Int16(maComplexColor.getThemeColorType()); + break; + } + case MID_COLOR_TINT_OR_SHADE: + { + sal_Int16 nValue = 0; + for (auto const& rTransform : maComplexColor.getTransformations()) + { + if (rTransform.meType == model::TransformationType::Tint) + nValue = rTransform.mnValue; + else if (rTransform.meType == model::TransformationType::Shade) + nValue = -rTransform.mnValue; + } + rVal <<= nValue; + break; + } + case MID_COLOR_LUM_MOD: + { + sal_Int16 nValue = 10000; + for (auto const& rTransform : maComplexColor.getTransformations()) + { + if (rTransform.meType == model::TransformationType::LumMod) + nValue = rTransform.mnValue; + } + rVal <<= nValue; + break; + } + case MID_COLOR_LUM_OFF: + { + sal_Int16 nValue = 0; + for (auto const& rTransform : maComplexColor.getTransformations()) + { + if (rTransform.meType == model::TransformationType::LumOff) + nValue = rTransform.mnValue; + } + rVal <<= nValue; + break; + } + case MID_COMPLEX_COLOR_JSON: + { + rVal <<= OStringToOUString(model::color::convertToJSON(maComplexColor), RTL_TEXTENCODING_UTF8); + break; + } + case MID_COMPLEX_COLOR: + { + auto xComplexColor = model::color::createXComplexColor(maComplexColor); + rVal <<= xComplexColor; + break; + } + case MID_COLOR_RGB: default: { rVal <<= mColor; @@ -1379,11 +1641,83 @@ bool SvxColorItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) mColor.SetAlpha( Any2Bool( rVal ) ? 0 : 255 ); return true; } + case MID_COLOR_THEME_INDEX: + { + sal_Int16 nIndex = -1; + if (!(rVal >>= nIndex)) + return false; + maComplexColor.setThemeColor(model::convertToThemeColorType(nIndex)); + } + break; + case MID_COLOR_TINT_OR_SHADE: + { + sal_Int16 nTintShade = 0; + if (!(rVal >>= nTintShade)) + return false; + + maComplexColor.removeTransformations(model::TransformationType::Tint); + maComplexColor.removeTransformations(model::TransformationType::Shade); + + if (nTintShade > 0) + maComplexColor.addTransformation({model::TransformationType::Tint, nTintShade}); + else if (nTintShade < 0) + { + sal_Int16 nShade = o3tl::narrowing<sal_Int16>(-nTintShade); + maComplexColor.addTransformation({model::TransformationType::Shade, nShade}); + } + } + break; + case MID_COLOR_LUM_MOD: + { + sal_Int16 nLumMod = 10000; + if (!(rVal >>= nLumMod)) + return false; + maComplexColor.removeTransformations(model::TransformationType::LumMod); + maComplexColor.addTransformation({model::TransformationType::LumMod, nLumMod}); + } + break; + case MID_COLOR_LUM_OFF: + { + sal_Int16 nLumOff = 0; + if (!(rVal >>= nLumOff)) + return false; + maComplexColor.removeTransformations(model::TransformationType::LumOff); + maComplexColor.addTransformation({model::TransformationType::LumOff, nLumOff}); + } + break; + case MID_COMPLEX_COLOR_JSON: + { + OUString sComplexColorJson; + if (!(rVal >>= sComplexColorJson)) + return false; + + if (sComplexColorJson.isEmpty()) + return false; + + OString aJSON = OUStringToOString(sComplexColorJson, RTL_TEXTENCODING_ASCII_US); + if (!model::color::convertFromJSON(aJSON, maComplexColor)) + return false; + } + break; + case MID_COMPLEX_COLOR: + { + css::uno::Reference<css::util::XComplexColor> xComplexColor; + if (!(rVal >>= xComplexColor)) + return false; + + if (xComplexColor.is()) + maComplexColor = model::color::getFromXComplexColor(xComplexColor); + } + break; + case MID_COLOR_RGB: default: { - return rVal >>= mColor; + if (!(rVal >>= mColor)) + return false; } + break; } + return true; } SvxColorItem* SvxColorItem::Clone( SfxItemPool * ) const @@ -1416,14 +1750,25 @@ void SvxColorItem::dumpAsXml(xmlTextWriterPtr pWriter) const IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag()); GetPresentation( SfxItemPresentation::Complete, MapUnit::Map100thMM, MapUnit::Map100thMM, aStr, aIntlWrapper); (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation"), BAD_CAST(OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr())); - (void)xmlTextWriterEndElement(pWriter); -} + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("complex-color")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("type"), + BAD_CAST(OString::number(sal_Int16(maComplexColor.getType())).getStr())); -void SvxColorItem::SetValue( const Color& rNewCol ) -{ - mColor = rNewCol; + for (auto const& rTransform : maComplexColor.getTransformations()) + { + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("transformation")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("type"), + BAD_CAST(OString::number(sal_Int16(rTransform.meType)).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), + BAD_CAST(OString::number(rTransform.mnValue).getStr())); + (void)xmlTextWriterEndElement(pWriter); + } + + (void)xmlTextWriterEndElement(pWriter); + + (void)xmlTextWriterEndElement(pWriter); } // class SvxKerningItem -------------------------------------------------- @@ -1467,7 +1812,7 @@ bool SvxKerningItem::GetPresentation case SfxItemPresentation::Complete: { rText = EditResId(RID_SVXITEMS_KERNING_COMPLETE); - const char* pId = nullptr; + TranslateId pId; if ( GetValue() > 0 ) pId = RID_SVXITEMS_KERNING_EXPANDED; @@ -1500,7 +1845,7 @@ bool SvxKerningItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId) if(!(rVal >>= nVal)) return false; if(nMemberId & CONVERT_TWIPS) - nVal = static_cast<sal_Int16>(convertMm100ToTwip(nVal)); + nVal = o3tl::toTwips(nVal, o3tl::Length::mm100); SetValue(nVal); return true; } @@ -1536,7 +1881,7 @@ bool SvxCaseMapItem::GetPresentation OUString SvxCaseMapItem::GetValueTextByPos( sal_uInt16 nPos ) { - static const char* RID_SVXITEMS_CASEMAP[] = + static TranslateId RID_SVXITEMS_CASEMAP[] = { RID_SVXITEMS_CASEMAP_NONE, RID_SVXITEMS_CASEMAP_UPPERCASE, @@ -1545,7 +1890,7 @@ OUString SvxCaseMapItem::GetValueTextByPos( sal_uInt16 nPos ) RID_SVXITEMS_CASEMAP_SMALLCAPS }; - static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_CASEMAP) == size_t(SvxCaseMap::End), "must match"); + static_assert(std::size(RID_SVXITEMS_CASEMAP) == size_t(SvxCaseMap::End), "must match"); assert(nPos < sal_uInt16(SvxCaseMap::End) && "enum overflow!"); return EditResId(RID_SVXITEMS_CASEMAP[nPos]); } @@ -1658,14 +2003,14 @@ bool SvxEscapementItem::GetPresentation OUString SvxEscapementItem::GetValueTextByPos( sal_uInt16 nPos ) { - static const char* RID_SVXITEMS_ESCAPEMENT[] = + static TranslateId RID_SVXITEMS_ESCAPEMENT[] = { RID_SVXITEMS_ESCAPEMENT_OFF, RID_SVXITEMS_ESCAPEMENT_SUPER, RID_SVXITEMS_ESCAPEMENT_SUB }; - static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_ESCAPEMENT) == size_t(SvxEscapement::End), "must match"); + static_assert(std::size(RID_SVXITEMS_ESCAPEMENT) == size_t(SvxEscapement::End), "must match"); assert(nPos < sal_uInt16(SvxEscapement::End) && "enum overflow!"); return EditResId(RID_SVXITEMS_ESCAPEMENT[nPos]); } @@ -1749,6 +2094,12 @@ bool SvxEscapementItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) // class SvxLanguageItem ------------------------------------------------- +ItemInstanceManager* SvxLanguageItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxLanguageItem).hash_code()); + return &aInstanceManager; +} + SvxLanguageItem::SvxLanguageItem( const LanguageType eLang, const sal_uInt16 nId ) : SvxLanguageItem_Base( nId , eLang ) { @@ -1808,6 +2159,7 @@ bool SvxLanguageItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= nValue)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue(LanguageType(nValue)); } break; @@ -1817,6 +2169,7 @@ bool SvxLanguageItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) if(!(rVal >>= aLocale)) return false; + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( LanguageTag::convertToLanguageType( aLocale, false)); } break; @@ -1826,8 +2179,8 @@ bool SvxLanguageItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) // class SvxNoHyphenItem ------------------------------------------------- -SvxNoHyphenItem::SvxNoHyphenItem( const sal_uInt16 nId ) : - SfxBoolItem( nId , true ) +SvxNoHyphenItem::SvxNoHyphenItem( const bool bNoHyphen, const sal_uInt16 nId ) : + SfxBoolItem( nId, bNoHyphen ) { } @@ -1844,8 +2197,12 @@ bool SvxNoHyphenItem::GetPresentation OUString& rText, const IntlWrapper& /*rIntl*/ ) const { - rText.clear(); - return false; + if ( GetValue() ) + rText = EditResId(RID_SVXITEMS_NOHYPHENATION_TRUE); + else + rText.clear(); + + return GetValue(); } /* @@ -1875,7 +2232,7 @@ bool SvxBlinkItem::GetPresentation OUString& rText, const IntlWrapper& /*rIntl*/ ) const { - const char* pId = RID_SVXITEMS_BLINK_FALSE; + TranslateId pId = RID_SVXITEMS_BLINK_FALSE; if ( GetValue() ) pId = RID_SVXITEMS_BLINK_TRUE; @@ -1885,8 +2242,14 @@ bool SvxBlinkItem::GetPresentation // class SvxEmphaisMarkItem --------------------------------------------------- +ItemInstanceManager* SvxEmphasisMarkItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxEmphasisMarkItem).hash_code()); + return &aInstanceManager; +} + SvxEmphasisMarkItem::SvxEmphasisMarkItem( const FontEmphasisMark nValue, - const sal_uInt16 nId ) + TypedWhichId<SvxEmphasisMarkItem> nId ) : SfxUInt16Item( nId, static_cast<sal_uInt16>(nValue) ) { } @@ -1905,7 +2268,7 @@ bool SvxEmphasisMarkItem::GetPresentation const IntlWrapper& /*rIntl*/ ) const { - static const char* RID_SVXITEMS_EMPHASIS[] = + static TranslateId RID_SVXITEMS_EMPHASIS[] = { RID_SVXITEMS_EMPHASIS_NONE_STYLE, RID_SVXITEMS_EMPHASIS_DOT_STYLE, @@ -1917,11 +2280,11 @@ bool SvxEmphasisMarkItem::GetPresentation FontEmphasisMark nVal = GetEmphasisMark(); rText = EditResId(RID_SVXITEMS_EMPHASIS[ static_cast<sal_uInt16>(static_cast<FontEmphasisMark>( nVal & FontEmphasisMark::Style ))]); - const char* pId = ( FontEmphasisMark::PosAbove & nVal ) + TranslateId pId = ( FontEmphasisMark::PosAbove & nVal ) ? RID_SVXITEMS_EMPHASIS_ABOVE_POS : ( FontEmphasisMark::PosBelow & nVal ) ? RID_SVXITEMS_EMPHASIS_BELOW_POS - : nullptr; + : TranslateId(); if( pId ) rText += EditResId( pId ); return true; @@ -1977,6 +2340,7 @@ bool SvxEmphasisMarkItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) case FontEmphasis::ACCENT_BELOW: nMark = FontEmphasisMark::Accent|FontEmphasisMark::PosBelow; break; default: return false; } + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( static_cast<sal_Int16>(nMark) ); } break; @@ -2097,7 +2461,7 @@ bool SvxTwoLinesItem::GetPresentation( SfxItemPresentation /*ePres*/, |* class SvxTextRotateItem *************************************************************************/ -SvxTextRotateItem::SvxTextRotateItem(Degree10 nValue, const sal_uInt16 nW) +SvxTextRotateItem::SvxTextRotateItem(Degree10 nValue, TypedWhichId<SvxTextRotateItem> nW) : SfxUInt16Item(nW, nValue.get()) { } @@ -2118,7 +2482,7 @@ bool SvxTextRotateItem::GetPresentation( { rText = EditResId(RID_SVXITEMS_TEXTROTATE); rText = rText.replaceFirst("$(ARG1)", - OUString::number(GetValue().get() / 10)); + OUString::number(toDegrees(GetValue()))); } return true; } @@ -2176,7 +2540,7 @@ void SvxTextRotateItem::dumpAsXml(xmlTextWriterPtr pWriter) const SvxCharRotateItem::SvxCharRotateItem( Degree10 nValue, bool bFitIntoLine, - const sal_uInt16 nW ) + TypedWhichId<SvxCharRotateItem> nW ) : SvxTextRotateItem(nValue, nW), bFitToLine( bFitIntoLine ) { } @@ -2197,7 +2561,7 @@ bool SvxCharRotateItem::GetPresentation( { rText = EditResId( RID_SVXITEMS_CHARROTATE ); rText = rText.replaceFirst( "$(ARG1)", - OUString::number( GetValue().get() / 10 )); + OUString::number( toDegrees(GetValue()) )); if( IsFitToLine() ) rText += EditResId( RID_SVXITEMS_CHARROTATE_FITLINE ); } @@ -2265,7 +2629,7 @@ void SvxCharRotateItem::dumpAsXml(xmlTextWriterPtr pWriter) const *************************************************************************/ SvxCharScaleWidthItem::SvxCharScaleWidthItem( sal_uInt16 nValue, - const sal_uInt16 nW ) + TypedWhichId<SvxCharScaleWidthItem> nW ) : SfxUInt16Item( nW, nValue ) { } @@ -2318,6 +2682,12 @@ bool SvxCharScaleWidthItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/ |* class SvxCharReliefItem *************************************************************************/ +ItemInstanceManager* SvxCharReliefItem::getItemInstanceManager() const +{ + static DefaultItemInstanceManager aInstanceManager(typeid(SvxCharReliefItem).hash_code()); + return &aInstanceManager; +} + SvxCharReliefItem::SvxCharReliefItem( FontRelief eValue, const sal_uInt16 nId ) : SfxEnumItem( nId, eValue ) @@ -2329,7 +2699,7 @@ SvxCharReliefItem* SvxCharReliefItem::Clone( SfxItemPool * ) const return new SvxCharReliefItem( *this ); } -static const char* RID_SVXITEMS_RELIEF[] = +static TranslateId RID_SVXITEMS_RELIEF[] = { RID_SVXITEMS_RELIEF_NONE, RID_SVXITEMS_RELIEF_EMBOSSED, @@ -2338,13 +2708,13 @@ static const char* RID_SVXITEMS_RELIEF[] = OUString SvxCharReliefItem::GetValueTextByPos(sal_uInt16 nPos) { - assert(nPos < SAL_N_ELEMENTS(RID_SVXITEMS_RELIEF) && "enum overflow"); + assert(nPos < std::size(RID_SVXITEMS_RELIEF) && "enum overflow"); return EditResId(RID_SVXITEMS_RELIEF[nPos]); } sal_uInt16 SvxCharReliefItem::GetValueCount() const { - return SAL_N_ELEMENTS(RID_SVXITEMS_RELIEF) - 1; + return std::size(RID_SVXITEMS_RELIEF) - 1; } bool SvxCharReliefItem::GetPresentation @@ -2371,7 +2741,10 @@ bool SvxCharReliefItem::PutValue( const css::uno::Any& rVal, sal_Int16 nVal = -1; rVal >>= nVal; if(nVal >= 0 && nVal <= sal_Int16(FontRelief::Engraved)) + { + ASSERT_CHANGE_REFCOUNTED_ITEM; SetValue( static_cast<FontRelief>(nVal) ); + } else bRet = false; } @@ -2405,8 +2778,8 @@ bool SvxCharReliefItem::QueryValue( css::uno::Any& rVal, *************************************************************************/ SvxScriptSetItem::SvxScriptSetItem( sal_uInt16 nSlotId, SfxItemPool& rPool ) - : SfxSetItem( nSlotId, std::make_unique<SfxItemSet>( rPool, - svl::Items<SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_FONT>{} )) + : SfxSetItem( nSlotId, SfxItemSet( rPool, + svl::Items<SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_FONT> )) { sal_uInt16 nLatin, nAsian, nComplex; GetWhichIds( nLatin, nAsian, nComplex ); @@ -2487,21 +2860,17 @@ void SvxScriptSetItem::PutItemForScriptType( SvtScriptType nScriptType, sal_uInt16 nLatin, nAsian, nComplex; GetWhichIds( nLatin, nAsian, nComplex ); - std::unique_ptr<SfxPoolItem> pCpy(rItem.Clone()); if( SvtScriptType::LATIN & nScriptType ) { - pCpy->SetWhich( nLatin ); - GetItemSet().Put( *pCpy ); + GetItemSet().Put( rItem.CloneSetWhich(nLatin) ); } if( SvtScriptType::ASIAN & nScriptType ) { - pCpy->SetWhich( nAsian ); - GetItemSet().Put( *pCpy ); + GetItemSet().Put( rItem.CloneSetWhich(nAsian) ); } if( SvtScriptType::COMPLEX & nScriptType ) { - pCpy->SetWhich( nComplex ); - GetItemSet().Put( *pCpy ); + GetItemSet().Put( rItem.CloneSetWhich(nComplex) ); } } @@ -2509,9 +2878,9 @@ void SvxScriptSetItem::GetWhichIds( sal_uInt16 nSlotId, const SfxItemSet& rSet, { const SfxItemPool& rPool = *rSet.GetPool(); GetSlotIds( nSlotId, rLatin, rAsian, rComplex ); - rLatin = rPool.GetWhich( rLatin ); - rAsian = rPool.GetWhich( rAsian ); - rComplex = rPool.GetWhich( rComplex ); + rLatin = rPool.GetWhichIDFromSlotID( rLatin ); + rAsian = rPool.GetWhichIDFromSlotID( rAsian ); + rComplex = rPool.GetWhichIDFromSlotID( rComplex ); } void SvxScriptSetItem::GetWhichIds( sal_uInt16& rLatin, sal_uInt16& rAsian, diff --git a/editeng/source/items/writingmodeitem.cxx b/editeng/source/items/writingmodeitem.cxx index 252c8c0556c0..35dbddabab2d 100644 --- a/editeng/source/items/writingmodeitem.cxx +++ b/editeng/source/items/writingmodeitem.cxx @@ -25,7 +25,7 @@ using namespace ::com::sun::star::uno; using namespace ::com::sun::star::text; -SvxWritingModeItem::SvxWritingModeItem( WritingMode eValue, sal_uInt16 _nWhich ) +SvxWritingModeItem::SvxWritingModeItem( WritingMode eValue, TypedWhichId<SvxWritingModeItem> _nWhich ) : SfxUInt16Item( _nWhich, static_cast<sal_uInt16>(eValue) ) { } diff --git a/editeng/source/items/xmlcnitm.cxx b/editeng/source/items/xmlcnitm.cxx index 5ee7c47e8d90..71f75a910246 100644 --- a/editeng/source/items/xmlcnitm.cxx +++ b/editeng/source/items/xmlcnitm.cxx @@ -18,30 +18,29 @@ */ #include <memory> + +#include <comphelper/servicehelper.hxx> #include <com/sun/star/xml/AttributeData.hpp> #include <com/sun/star/lang/XUnoTunnel.hpp> #include <o3tl/any.hxx> #include <xmloff/xmlcnimp.hxx> #include <xmloff/unoatrcn.hxx> #include <editeng/xmlcnitm.hxx> -#include <tools/solar.h> using namespace ::com::sun::star::uno; using namespace ::com::sun::star::container; -using namespace ::com::sun::star::lang; using namespace ::com::sun::star::xml; SvXMLAttrContainerItem::SvXMLAttrContainerItem( sal_uInt16 _nWhich ) : - SfxPoolItem( _nWhich ), - pImpl( new SvXMLAttrContainerData ) + SfxPoolItem( _nWhich ) { } SvXMLAttrContainerItem::SvXMLAttrContainerItem( const SvXMLAttrContainerItem& rItem ) : SfxPoolItem( rItem ), - pImpl( new SvXMLAttrContainerData( *rItem.pImpl ) ) + maContainerData( rItem.maContainerData ) { } @@ -52,7 +51,7 @@ SvXMLAttrContainerItem::~SvXMLAttrContainerItem() bool SvXMLAttrContainerItem::operator==( const SfxPoolItem& rItem ) const { return SfxPoolItem::operator==(rItem) && - *pImpl == *static_cast<const SvXMLAttrContainerItem&>(rItem).pImpl; + maContainerData == static_cast<const SvXMLAttrContainerItem&>(rItem).maContainerData; } bool SvXMLAttrContainerItem::GetPresentation( @@ -68,7 +67,7 @@ bool SvXMLAttrContainerItem::GetPresentation( bool SvXMLAttrContainerItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const { Reference<XNameContainer> xContainer - = new SvUnoAttributeContainer(std::make_unique<SvXMLAttrContainerData>(*pImpl)); + = new SvUnoAttributeContainer(std::make_unique<SvXMLAttrContainerData>(maContainerData)); rVal <<= xContainer; return true; @@ -76,19 +75,14 @@ bool SvXMLAttrContainerItem::QueryValue( css::uno::Any& rVal, sal_uInt8 /*nMembe bool SvXMLAttrContainerItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) { - SvUnoAttributeContainer* pContainer = nullptr; - - Reference<XUnoTunnel> xTunnel(rVal, UNO_QUERY); - if( xTunnel.is() ) - pContainer = reinterpret_cast<SvUnoAttributeContainer*>(static_cast<sal_uLong>(xTunnel->getSomething(SvUnoAttributeContainer::getUnoTunnelId()))); - - if( pContainer ) + Reference<XInterface> xTunnel(rVal, UNO_QUERY); + if (auto pContainer = dynamic_cast<SvUnoAttributeContainer*>(xTunnel.get())) { - pImpl.reset( new SvXMLAttrContainerData( * pContainer->GetContainerImpl() ) ); + maContainerData = *pContainer->GetContainerImpl(); } else { - std::unique_ptr<SvXMLAttrContainerData> pNewImpl(new SvXMLAttrContainerData); + SvXMLAttrContainerData aNewImpl; try { @@ -119,24 +113,24 @@ bool SvXMLAttrContainerItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nM if( pData->Namespace.isEmpty() ) { - if( !pNewImpl->AddAttr( aPrefix, aLName, pData->Value ) ) + if( !aNewImpl.AddAttr( aPrefix, aLName, pData->Value ) ) break; } else { - if( !pNewImpl->AddAttr( aPrefix, pData->Namespace, aLName, pData->Value ) ) + if( !aNewImpl.AddAttr( aPrefix, pData->Namespace, aLName, pData->Value ) ) break; } } else { - if( !pNewImpl->AddAttr( aName, pData->Value ) ) + if( !aNewImpl.AddAttr( aName, pData->Value ) ) break; } } if( nAttr == nCount ) - pImpl = std::move(pNewImpl); + maContainerData = std::move(aNewImpl); else return false; } @@ -152,60 +146,60 @@ bool SvXMLAttrContainerItem::PutValue( const css::uno::Any& rVal, sal_uInt8 /*nM bool SvXMLAttrContainerItem::AddAttr( const OUString& rLName, const OUString& rValue ) { - return pImpl->AddAttr( rLName, rValue ); + return maContainerData.AddAttr( rLName, rValue ); } bool SvXMLAttrContainerItem::AddAttr( const OUString& rPrefix, const OUString& rNamespace, const OUString& rLName, const OUString& rValue ) { - return pImpl->AddAttr( rPrefix, rNamespace, rLName, rValue ); + return maContainerData.AddAttr( rPrefix, rNamespace, rLName, rValue ); } sal_uInt16 SvXMLAttrContainerItem::GetAttrCount() const { - return static_cast<sal_uInt16>(pImpl->GetAttrCount()); + return static_cast<sal_uInt16>(maContainerData.GetAttrCount()); } OUString SvXMLAttrContainerItem::GetAttrNamespace( sal_uInt16 i ) const { - return pImpl->GetAttrNamespace( i ); + return maContainerData.GetAttrNamespace( i ); } OUString SvXMLAttrContainerItem::GetAttrPrefix( sal_uInt16 i ) const { - return pImpl->GetAttrPrefix( i ); + return maContainerData.GetAttrPrefix( i ); } const OUString& SvXMLAttrContainerItem::GetAttrLName( sal_uInt16 i ) const { - return pImpl->GetAttrLName( i ); + return maContainerData.GetAttrLName( i ); } const OUString& SvXMLAttrContainerItem::GetAttrValue( sal_uInt16 i ) const { - return pImpl->GetAttrValue( i ); + return maContainerData.GetAttrValue( i ); } sal_uInt16 SvXMLAttrContainerItem::GetFirstNamespaceIndex() const { - return pImpl->GetFirstNamespaceIndex(); + return maContainerData.GetFirstNamespaceIndex(); } sal_uInt16 SvXMLAttrContainerItem::GetNextNamespaceIndex( sal_uInt16 nIdx ) const { - return pImpl->GetNextNamespaceIndex( nIdx ); + return maContainerData.GetNextNamespaceIndex( nIdx ); } const OUString& SvXMLAttrContainerItem::GetNamespace( sal_uInt16 i ) const { - return pImpl->GetNamespace( i ); + return maContainerData.GetNamespace( i ); } const OUString& SvXMLAttrContainerItem::GetPrefix( sal_uInt16 i ) const { - return pImpl->GetPrefix( i ); + return maContainerData.GetPrefix( i ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/lookuptree/Trie.cxx b/editeng/source/lookuptree/Trie.cxx index 153fe01e1c6d..6505c00e43f9 100644 --- a/editeng/source/lookuptree/Trie.cxx +++ b/editeng/source/lookuptree/Trie.cxx @@ -16,8 +16,6 @@ namespace editeng { -using namespace std; - /* TrieNode */ struct TrieNode final @@ -33,10 +31,10 @@ struct TrieNode final void markWord(); TrieNode* findChild(sal_Unicode aCharacter); - TrieNode* traversePath(const OUString& sPath); + TrieNode* traversePath(std::u16string_view sPath); void addNewChild(TrieNode* pChild); void collectSuggestions(std::u16string_view sPath, std::vector<OUString>& rSuggestionList); - static void collectSuggestionsForCurrentNode(TrieNode* pCurrent, std::u16string_view sPath, vector<OUString>& rSuggestionList); + static void collectSuggestionsForCurrentNode(TrieNode* pCurrent, std::u16string_view sPath, std::vector<OUString>& rSuggestionList); }; TrieNode::TrieNode(sal_Unicode aCharacter) : @@ -84,7 +82,7 @@ TrieNode* TrieNode::findChild(sal_Unicode aInputCharacter) return nullptr; } -void TrieNode::collectSuggestions(std::u16string_view sPath, vector<OUString>& rSuggestionList) +void TrieNode::collectSuggestions(std::u16string_view sPath, std::vector<OUString>& rSuggestionList) { // first traverse nodes for alphabet characters for (auto const & pCurrent : mLatinArray) @@ -101,7 +99,7 @@ void TrieNode::collectSuggestions(std::u16string_view sPath, vector<OUString>& r } } -void TrieNode::collectSuggestionsForCurrentNode(TrieNode* pCurrent, std::u16string_view sPath, vector<OUString>& rSuggestionList) +void TrieNode::collectSuggestionsForCurrentNode(TrieNode* pCurrent, std::u16string_view sPath, std::vector<OUString>& rSuggestionList) { OUString aStringPath = sPath + OUStringChar(pCurrent->mCharacter); if(pCurrent->mMarker) @@ -112,13 +110,12 @@ void TrieNode::collectSuggestionsForCurrentNode(TrieNode* pCurrent, std::u16stri pCurrent->collectSuggestions(aStringPath, rSuggestionList); } -TrieNode* TrieNode::traversePath(const OUString& sPath) +TrieNode* TrieNode::traversePath(std::u16string_view sPath) { TrieNode* pCurrent = this; - for ( sal_Int32 i = 0; i < sPath.getLength(); i++ ) + for ( const auto aCurrentChar : sPath ) { - sal_Unicode aCurrentChar = sPath[i]; pCurrent = pCurrent->findChild(aCurrentChar); if ( pCurrent == nullptr ) return nullptr; @@ -136,10 +133,10 @@ Trie::Trie() : Trie::~Trie() {} -void Trie::insert(const OUString& sInputString) const +void Trie::insert(std::u16string_view sInputString) const { // adding an empty word is not allowed - if ( sInputString.isEmpty() ) + if ( sInputString.empty() ) { return; } @@ -147,11 +144,9 @@ void Trie::insert(const OUString& sInputString) const // traverse the input string and modify the tree with new nodes / characters TrieNode* pCurrent = mRoot.get(); - sal_Unicode aCurrentChar; - for ( sal_Int32 i = 0; i < sInputString.getLength(); i++ ) + for ( const auto aCurrentChar : sInputString ) { - aCurrentChar = sInputString[i]; TrieNode* pChild = pCurrent->findChild(aCurrentChar); if ( pChild == nullptr ) { @@ -168,7 +163,7 @@ void Trie::insert(const OUString& sInputString) const pCurrent->markWord(); } -void Trie::findSuggestions(const OUString& sWordPart, vector<OUString>& rSuggestionList) const +void Trie::findSuggestions(std::u16string_view sWordPart, std::vector<OUString>& rSuggestionList) const { TrieNode* pNode = mRoot->traversePath(sWordPart); diff --git a/editeng/source/misc/SvXMLAutoCorrectImport.cxx b/editeng/source/misc/SvXMLAutoCorrectImport.cxx index 957cb708562c..baeef8861289 100644 --- a/editeng/source/misc/SvXMLAutoCorrectImport.cxx +++ b/editeng/source/misc/SvXMLAutoCorrectImport.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <utility> + #include "SvXMLAutoCorrectImport.hxx" #include "SvXMLAutoCorrectTokenHandler.hxx" @@ -27,11 +29,11 @@ SvXMLAutoCorrectImport::SvXMLAutoCorrectImport( const uno::Reference< uno::XComponentContext > & xContext, SvxAutocorrWordList *pNewAutocorr_List, SvxAutoCorrect &rNewAutoCorrect, - const css::uno::Reference < css::embed::XStorage >& rNewStorage) + css::uno::Reference < css::embed::XStorage > xNewStorage) : SvXMLImport( xContext, "" ), pAutocorr_List (pNewAutocorr_List), rAutoCorrect ( rNewAutoCorrect ), - xStorage ( rNewStorage ) + xStorage (std::move( xNewStorage )) { } diff --git a/editeng/source/misc/SvXMLAutoCorrectImport.hxx b/editeng/source/misc/SvXMLAutoCorrectImport.hxx index 4b4b819c0711..961e6963d7df 100644 --- a/editeng/source/misc/SvXMLAutoCorrectImport.hxx +++ b/editeng/source/misc/SvXMLAutoCorrectImport.hxx @@ -41,7 +41,7 @@ public: const css::uno::Reference< css::uno::XComponentContext > & xContext, SvxAutocorrWordList *pNewAutocorr_List, SvxAutoCorrect &rNewAutoCorrect, - const css::uno::Reference < css::embed::XStorage >& rNewStorage); + css::uno::Reference < css::embed::XStorage > xNewStorage); virtual ~SvXMLAutoCorrectImport() noexcept override; }; diff --git a/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx b/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx index 352f77385a67..df913dbe6b01 100644 --- a/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx +++ b/editeng/source/misc/SvXMLAutoCorrectTokenHandler.hxx @@ -7,8 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef EDITENG_SOURCE_MISC_SVXMLAUTOCORRECTTOKENHANDLER_HXX -#define EDITENG_SOURCE_MISC_SVXMLAUTOCORRECTTOKENHANDLER_HXX +#pragma once #include <sal/types.h> #include <xmloff/xmltoken.hxx> @@ -43,7 +42,4 @@ public: virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const override; }; -#endif // EDITENG_SOURCE_MISC_SVXMLAUTOCORRECTTOKENHANDLER_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ - diff --git a/editeng/source/misc/acorrcfg.cxx b/editeng/source/misc/acorrcfg.cxx index 5489e7d5011f..49e48bb48be1 100644 --- a/editeng/source/misc/acorrcfg.cxx +++ b/editeng/source/misc/acorrcfg.cxx @@ -22,20 +22,92 @@ #include <o3tl/any.hxx> #include <tools/debug.hxx> #include <tools/urlobj.hxx> +#include <comphelper/diagnose_ex.hxx> #include <ucbhelper/content.hxx> #include <unotools/pathoptions.hxx> #include <unotools/ucbhelper.hxx> +#include <svtools/langtab.hxx> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> #include <editeng/svxacorr.hxx> #include <com/sun/star/uno/Sequence.hxx> -#include <rtl/instance.hxx> - using namespace utl; using namespace com::sun::star; using namespace com::sun::star::uno; +/** An autocorrection file dropped into such directory may create a language + list entry if one didn't exist already. + */ +static void scanAutoCorrectDirForLanguageTags( const OUString& rURL ) +{ + // Silently ignore all errors. + try + { + ::ucbhelper::Content aContent( rURL, + uno::Reference<ucb::XCommandEnvironment>(), comphelper::getProcessComponentContext()); + if (aContent.isFolder()) + { + // Title is file name here. + uno::Reference<sdbc::XResultSet> xResultSet = aContent.createCursor( + {"Title"}, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY); + uno::Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY); + if (xResultSet.is() && xRow.is()) + { + while (xResultSet->next()) + { + try + { + const OUString aTitle( xRow->getString(1)); + if (aTitle.getLength() <= 9 || !(aTitle.startsWith("acor_") && aTitle.endsWith(".dat"))) + continue; + + const OUString aBcp47( aTitle.copy( 5, aTitle.getLength() - 9)); + // Ignore invalid langtags and canonicalize for good, + // allow private-use tags. + const LanguageTag aLanguageTag (aBcp47, true); + if (!aLanguageTag.isValidBcp47()) + continue; + + if (SvtLanguageTable::HasLanguageType( aLanguageTag.getLanguageType())) + continue; + + // Insert language(-script)-only tags only if there is + // no known matching fallback locale, otherwise we'd + // end up with unwanted entries where a language + // autocorrection file covers several locales. We do + // know a few art-x-... though so exclude those and any + // other private-use tag (which should not fallback, + // but avoid). + if (aLanguageTag.getCountry().isEmpty() + && LanguageTag::isValidBcp47( aLanguageTag.getBcp47(), nullptr, + LanguageTag::PrivateUse::DISALLOW)) + { + LanguageTag aFallback( aLanguageTag); + aFallback.makeFallback(); + if (aFallback.getLanguageAndScript() == aLanguageTag.getLanguageAndScript()) + continue; + } + + // Finally add this one. + SvtLanguageTable::AddLanguageTag( aLanguageTag); + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("editeng", "Unable to get a directory entry from '" << rURL << "'"); + } + } + } + } + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION("editeng", "Unable to iterate directory '" << rURL << "'"); + } +} + SvxAutoCorrCfg::SvxAutoCorrCfg() : aBaseConfig(*this), aSwConfig(*this), @@ -62,6 +134,7 @@ SvxAutoCorrCfg::SvxAutoCorrCfg() : for( OUString* pS : { &sSharePath, &sUserPath } ) { INetURLObject aPath( *pS ); + scanAutoCorrectDirForLanguageTags( aPath.GetMainURL(INetURLObject::DecodeMechanism::ToIUri)); aPath.insertName(u"acor"); *pS = aPath.GetMainURL(INetURLObject::DecodeMechanism::ToIUri); } @@ -111,9 +184,10 @@ Sequence<OUString> SvxBaseAutoCorrCfg::GetPropertyNames() "DoubleQuoteAtEnd", // 16 "CorrectAccidentalCapsLock", // 17 "TransliterateRTL", // 18 - "ChangeAngleQuotes" // 19 + "ChangeAngleQuotes", // 19 + "SetDOIAttribute", // 20 }; - const int nCount = 20; + const int nCount = 21; Sequence<OUString> aNames(nCount); OUString* pNames = aNames.getArray(); for(int i = 0; i < nCount; i++) @@ -146,7 +220,7 @@ void SvxBaseAutoCorrCfg::Load(bool bInit) break;//"Exceptions/TwoCapitalsAtStart", case 1: if(*o3tl::doAccess<bool>(pValues[nProp])) - nFlags |= ACFlags::SaveWordWrdSttLst; + nFlags |= ACFlags::SaveWordWordStartLst; break;//"Exceptions/CapitalAtStartSentence", case 2: if(*o3tl::doAccess<bool>(pValues[nProp])) @@ -224,6 +298,10 @@ void SvxBaseAutoCorrCfg::Load(bool bInit) if(*o3tl::doAccess<bool>(pValues[nProp])) nFlags |= ACFlags::ChgAngleQuotes; break;//"ChangeAngleQuotes" + case 20: + if(*o3tl::doAccess<bool>(pValues[nProp])) + nFlags |= ACFlags::SetDOIAttr; + break;//"SetDOIAttr", } } } @@ -249,7 +327,7 @@ void SvxBaseAutoCorrCfg::ImplCommit() GetPropertyNames(), {css::uno::Any(bool(nFlags & ACFlags::SaveWordCplSttLst)), // "Exceptions/TwoCapitalsAtStart" - css::uno::Any(bool(nFlags & ACFlags::SaveWordWrdSttLst)), + css::uno::Any(bool(nFlags & ACFlags::SaveWordWordStartLst)), // "Exceptions/CapitalAtStartSentence" css::uno::Any(bool(nFlags & ACFlags::Autocorrect)), // "UseReplacementTable" css::uno::Any(bool(nFlags & ACFlags::CapitalStartWord)), @@ -279,9 +357,10 @@ void SvxBaseAutoCorrCfg::ImplCommit() // "CorrectAccidentalCapsLock" css::uno::Any(bool(nFlags & ACFlags::TransliterateRTL)), // "TransliterateRTL" - css::uno::Any(bool(nFlags & ACFlags::ChgAngleQuotes))}); + css::uno::Any(bool(nFlags & ACFlags::ChgAngleQuotes)), // "ChangeAngleQuotes" - + css::uno::Any(bool(nFlags & ACFlags::SetDOIAttr)), // "SetDOIAttribute" + }); } void SvxBaseAutoCorrCfg::Notify( const Sequence<OUString>& /* aPropertyNames */) @@ -340,8 +419,10 @@ Sequence<OUString> SvxSwAutoCorrCfg::GetPropertyNames() "Format/ByInput/ApplyNumbering/SpecialCharacter/FontFamily", //44 "Format/ByInput/ApplyNumbering/SpecialCharacter/FontCharset", //45 "Format/ByInput/ApplyNumbering/SpecialCharacter/FontPitch", //46 + "Format/Option/SetDOIAttribute", //47 + "Format/ByInput/ApplyBulletsAfterSpace", //48 }; - const int nCount = 47; + const int nCount = 49; Sequence<OUString> aNames(nCount); OUString* pNames = aNames.getArray(); for(int i = 0; i < nCount; i++) @@ -445,7 +526,7 @@ void SvxSwAutoCorrCfg::Load(bool bInit) { sal_Int32 nVal = 0; pValues[nProp] >>= nVal; rSwFlags.nAutoCmpltListLen = - sal::static_int_cast< sal_uInt16 >(nVal); + sal::static_int_cast< sal_uInt32 >(nVal); } break; // "Completion/MaxListLen", case 36: rSwFlags.bAutoCmpltCollectWords = *o3tl::doAccess<bool>(pValues[nProp]); break; // "Completion/CollectWords", @@ -491,6 +572,8 @@ void SvxSwAutoCorrCfg::Load(bool bInit) rSwFlags.aByInputBulletFont.SetPitch(FontPitch(nVal)); } break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/FontPitch", + case 47: rSwFlags.bSetDOIAttr = *o3tl::doAccess<bool>(pValues[nProp]); break; // "Format/Option/SetDOIAttribute", + case 48 : rSwFlags.bSetNumRuleAfterSpace = *o3tl::doAccess<bool>(pValues[nProp]); break; // "Format/ByInput/ApplyNumberingAfterSpace", } } } @@ -592,8 +675,12 @@ void SvxSwAutoCorrCfg::ImplCommit() // "Format/ByInput/ApplyNumbering/SpecialCharacter/FontFamily" css::uno::Any(sal_Int32(rSwFlags.aByInputBulletFont.GetCharSet())), // "Format/ByInput/ApplyNumbering/SpecialCharacter/FontCharset" - css::uno::Any(sal_Int32(rSwFlags.aByInputBulletFont.GetPitch()))}); + css::uno::Any(sal_Int32(rSwFlags.aByInputBulletFont.GetPitch())), // "Format/ByInput/ApplyNumbering/SpecialCharacter/FontPitch" + css::uno::Any(rSwFlags.bSetDOIAttr), + css::uno::Any(rSwFlags.bSetNumRuleAfterSpace), // "Format/ByInput/ApplyNumberingAfterSpace" + }); + // "Format/Option/SetDOIAttribute" } void SvxSwAutoCorrCfg::Notify( const Sequence<OUString>& /* aPropertyNames */ ) @@ -601,14 +688,10 @@ void SvxSwAutoCorrCfg::Notify( const Sequence<OUString>& /* aPropertyNames */ ) Load(false); } -namespace -{ - class theSvxAutoCorrCfg : public rtl::Static<SvxAutoCorrCfg, theSvxAutoCorrCfg>{}; -} - SvxAutoCorrCfg& SvxAutoCorrCfg::Get() { - return theSvxAutoCorrCfg::get(); + static SvxAutoCorrCfg theSvxAutoCorrCfg; + return theSvxAutoCorrCfg; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/misc/forbiddencharacterstable.cxx b/editeng/source/misc/forbiddencharacterstable.cxx index 942af2f04527..7276da584bd9 100644 --- a/editeng/source/misc/forbiddencharacterstable.cxx +++ b/editeng/source/misc/forbiddencharacterstable.cxx @@ -20,10 +20,11 @@ #include <editeng/forbiddencharacterstable.hxx> #include <unotools/localedatawrapper.hxx> +#include <utility> SvxForbiddenCharactersTable::SvxForbiddenCharactersTable( - const css::uno::Reference<css::uno::XComponentContext>& rxContext) - : m_xContext(rxContext) + css::uno::Reference<css::uno::XComponentContext> xContext) + : m_xContext(std::move(xContext)) { } diff --git a/editeng/source/misc/hangulhanja.cxx b/editeng/source/misc/hangulhanja.cxx index 1908586240e8..5a9a8c1034fe 100644 --- a/editeng/source/misc/hangulhanja.cxx +++ b/editeng/source/misc/hangulhanja.cxx @@ -36,7 +36,7 @@ #include <sal/log.hxx> #include <osl/diagnose.h> #include <tools/debug.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <editeng/edtdlg.hxx> @@ -131,6 +131,7 @@ namespace editeng bool IsValid() const { return m_xConverter.is(); } + weld::Widget* GetUIParent() const { return m_pUIParent; } LanguageType GetSourceLang() const { return m_nSourceLang; } LanguageType GetTargetLang() const { return m_nTargetLang; } const vcl::Font * GetTargetFont() const { return m_pTargetFont; } @@ -233,8 +234,7 @@ namespace editeng sal_Int32 _nOptions, bool _bIsInteractive, HangulHanjaConversion* _pAntiImpl ) - : m_pConversionDialog() - , m_pUIParent( pUIParent ) + : m_pUIParent( pUIParent ) , m_xContext( rxContext ) , m_aSourceLocale( _rSourceLocale ) , m_nSourceLang( LanguageTag::convertToLanguageType( _rSourceLocale ) ) @@ -407,13 +407,14 @@ namespace editeng { sal_Int32 nCount = m_aCurrentSuggestions.getLength(); Sequence< OUString > aTmp(nCount); - aTmp[0]=aRecentlyUsed->second; + auto pTmp = aTmp.getArray(); + pTmp[0]=aRecentlyUsed->second; sal_Int32 nDiff = 1; for( sal_Int32 n=1; n<nCount; n++)//we had 0 already { if( nDiff && m_aCurrentSuggestions[n-nDiff]==aRecentlyUsed->second ) nDiff=0; - aTmp[n]=m_aCurrentSuggestions[n-nDiff]; + pTmp[n]=m_aCurrentSuggestions[n-nDiff]; } m_aCurrentSuggestions = aTmp; } @@ -946,7 +947,7 @@ namespace editeng { } - HangulHanjaConversion::~HangulHanjaConversion( ) + HangulHanjaConversion::~HangulHanjaConversion() COVERITY_NOEXCEPT_FALSE { } @@ -960,6 +961,11 @@ namespace editeng return m_bUseSavedValues; } + weld::Widget* HangulHanjaConversion::GetUIParent() const + { + return m_pImpl->GetUIParent(); + } + LanguageType HangulHanjaConversion::GetSourceLanguage( ) const { return m_pImpl->GetSourceLang(); diff --git a/editeng/source/misc/splwrap.cxx b/editeng/source/misc/splwrap.cxx index b51c9c97b613..67c3dc28e64a 100644 --- a/editeng/source/misc/splwrap.cxx +++ b/editeng/source/misc/splwrap.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <config_wasm_strip.h> + #include <rtl/ustring.hxx> #include <i18nlangtag/languagetag.hxx> #include <vcl/svapp.hxx> @@ -44,13 +46,12 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::beans; using namespace ::com::sun::star::linguistic2; // misc functions --------------------------------------------- -void SvxPrepareAutoCorrect( OUString &rOldText, const OUString &rNewText ) +void SvxPrepareAutoCorrect( OUString &rOldText, std::u16string_view rNewText ) { // This function should be used to strip (or add) trailing '.' from // the strings before passing them on to the autocorrect function in @@ -62,7 +63,7 @@ void SvxPrepareAutoCorrect( OUString &rOldText, const OUString &rNewText ) // rNewText: replacement text sal_Int32 nOldLen = rOldText.getLength(); - sal_Int32 nNewLen = rNewText.getLength(); + sal_Int32 nNewLen = rNewText.size(); if (nOldLen && nNewLen) { bool bOldHasDot = '.' == rOldText[ nOldLen - 1 ], @@ -102,14 +103,14 @@ void SvxSpellWrapper::ShowLanguageErrors() { OUString aErr( SvtLanguageTable::GetLanguageString( nLang ) ); ErrorHandler::HandleError( - *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) ); + ErrCodeMsg( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) ); nTmpSpell = SVX_LANG_MISSING; } if (SVX_LANG_MISSING_DO_WARN == nTmpHyph) { OUString aErr( SvtLanguageTable::GetLanguageString( nLang ) ); ErrorHandler::HandleError( - *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) ); + ErrCodeMsg( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) ); nTmpHyph = SVX_LANG_MISSING; } @@ -249,6 +250,9 @@ void SvxSpellWrapper::InsertHyphen( const sal_Int32 ) // Testing of the document areas in the order specified by the flags void SvxSpellWrapper::SpellDocument( ) { +#if ENABLE_WASM_STRIP_HUNSPELL + return; +#else if ( bOtherCntnt ) { bReverse = false; @@ -275,6 +279,7 @@ void SvxSpellWrapper::SpellDocument( ) xHyph, this )); pDlg->Execute(); } +#endif } @@ -342,7 +347,7 @@ bool SvxSpellWrapper::SpellNext( ) // a BODY_area done, ask for the other BODY_area xWait.reset(); - const char* pResId = bReverse ? RID_SVXSTR_QUERY_BW_CONTINUE : RID_SVXSTR_QUERY_CONTINUE; + TranslateId pResId = bReverse ? RID_SVXSTR_QUERY_BW_CONTINUE : RID_SVXSTR_QUERY_CONTINUE; std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin, VclMessageType::Question, VclButtonsType::YesNo, EditResId(pResId))); diff --git a/editeng/source/misc/svxacorr.cxx b/editeng/source/misc/svxacorr.cxx index 4507cd5523b5..401dc9d8ff17 100644 --- a/editeng/source/misc/svxacorr.cxx +++ b/editeng/source/misc/svxacorr.cxx @@ -18,6 +18,8 @@ */ #include <memory> +#include <utility> +#include <algorithm> #include <string_view> #include <sal/config.h> @@ -43,7 +45,7 @@ #include <unotools/transliterationwrapper.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/storagehelper.hxx> -#include <comphelper/string.hxx> +#include <o3tl/string_view.hxx> #include <editeng/editids.hrc> #include <sot/storage.hxx> #include <editeng/udlnitem.hxx> @@ -67,7 +69,7 @@ #include <com/sun/star/ucb/XCommandEnvironment.hpp> #include <com/sun/star/ucb/TransferInfo.hpp> #include <com/sun/star/ucb/NameClash.hpp> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <xmloff/xmltoken.hxx> #include <unordered_map> #include <rtl/character.hxx> @@ -95,17 +97,19 @@ namespace o3tl { } const sal_Unicode cNonBreakingSpace = 0xA0; // UNICODE code for no break space -constexpr OUStringLiteral pXMLImplWrdStt_ExcptLstStr = u"WordExceptList.xml"; -constexpr OUStringLiteral pXMLImplCplStt_ExcptLstStr = u"SentenceExceptList.xml"; -constexpr OUStringLiteral pXMLImplAutocorr_ListStr = u"DocumentList.xml"; +constexpr OUString pXMLImplWordStart_ExcptLstStr = u"WordExceptList.xml"_ustr; +constexpr OUString pXMLImplCplStt_ExcptLstStr = u"SentenceExceptList.xml"_ustr; +constexpr OUString pXMLImplAutocorr_ListStr = u"DocumentList.xml"_ustr; -const char +// tdf#54409 check also typographical quotation marks in the case of skipped ASCII quotation marks +// Curious, why these \u0083\u0084\u0089\u0091\u0092\u0093\u0094 are handled as "begin characters"? +constexpr std::u16string_view /* also at these beginnings - Brackets and all kinds of begin characters */ - sImplSttSkipChars[] = "\"\'([{\x83\x84\x89\x91\x92\x93\x94", + sImplSttSkipChars = u"\"'([{\u2018\u2019\u201a\u201b\u201c\u201d\u201e\u201f\u0083\u0084\u0089\u0091\u0092\u0093\u0094", /* also at these ends - Brackets and all kinds of begin characters */ - sImplEndSkipChars[] = "\"\')]}\x83\x84\x89\x91\x92\x93\x94"; + sImplEndSkipChars = u"\"')]}\u2018\u2019\u201a\u201b\u201c\u201d\u201e\u201f\u0083\u0084\u0089\u0091\u0092\u0093\u0094"; -static OUString EncryptBlockName_Imp(const OUString& rName); +static OUString EncryptBlockName_Imp(std::u16string_view rName); static bool NonFieldWordDelim( const sal_Unicode c ) { @@ -147,7 +151,7 @@ static bool lcl_IsUnsupportedUnicodeChar( CharClass const & rCC, const OUString& case css::i18n::UnicodeScript_kHangulCompatibilityJamo: case css::i18n::UnicodeScript_kEnclosedCJKLetterMonth: case css::i18n::UnicodeScript_kCJKCompatibility: - case css::i18n::UnicodeScript_k_CJKUnifiedIdeographsExtensionA: + case css::i18n::UnicodeScript_kCJKUnifiedIdeographsExtensionA: case css::i18n::UnicodeScript_kCJKUnifiedIdeograph: case css::i18n::UnicodeScript_kHangulSyllable: case css::i18n::UnicodeScript_kCJKCompatibilityIdeograph: @@ -170,20 +174,9 @@ static bool lcl_IsSymbolChar( CharClass const & rCC, const OUString& rTxt, return false; } -static bool lcl_IsInAsciiArr( const char* pArr, const sal_Unicode c ) +static bool lcl_IsInArr(std::u16string_view arr, const sal_uInt32 c) { - // tdf#54409 check also typographical quotation marks in the case of skipped ASCII quotation marks - if ( 0x2018 <= c && c <= 0x201F && (pArr == sImplSttSkipChars || pArr == sImplEndSkipChars) ) - return true; - - bool bRet = false; - for( ; *pArr; ++pArr ) - if( *pArr == c ) - { - bRet = true; - break; - } - return bRet; + return std::any_of(arr.begin(), arr.end(), [c](const auto c1) { return c1 == c; }); } SvxAutoCorrDoc::~SvxAutoCorrDoc() @@ -224,7 +217,7 @@ static LocaleDataWrapper& GetLocaleDataWrapper( LanguageType nLang ) static std::unique_ptr<LocaleDataWrapper> xLclDtWrp; LanguageTag aLcl( nLang ); if (!xLclDtWrp || xLclDtWrp->getLoadedLanguageTag() != aLcl) - xLclDtWrp.reset(new LocaleDataWrapper(aLcl)); + xLclDtWrp.reset(new LocaleDataWrapper(std::move(aLcl))); return *xLclDtWrp; } static TransliterationWrapper& GetIgnoreTranslWrapper() @@ -242,7 +235,7 @@ static TransliterationWrapper& GetIgnoreTranslWrapper() } static CollatorWrapper& GetCollatorWrapper() { - static CollatorWrapper aCollWrp = [&]() + static CollatorWrapper aCollWrp = []() { CollatorWrapper tmp( ::comphelper::getProcessComponentContext() ); tmp.loadDefaultCollator( GetAppLang().getLocale(), 0 ); @@ -288,9 +281,10 @@ ACFlags SvxAutoCorrect::GetDefaultFlags() | ACFlags::ChgAngleQuotes | ACFlags::ChgWeightUnderl | ACFlags::SetINetAttr + | ACFlags::SetDOIAttr | ACFlags::ChgQuotes | ACFlags::SaveWordCplSttLst - | ACFlags::SaveWordWrdSttLst + | ACFlags::SaveWordWordStartLst | ACFlags::CorrectCapsLock; LanguageType eLang = GetAppLang().getLanguageType(); if( eLang.anyOf( @@ -310,6 +304,8 @@ ACFlags SvxAutoCorrect::GetDefaultFlags() constexpr sal_Unicode cEmDash = 0x2014; constexpr sal_Unicode cEnDash = 0x2013; +constexpr OUString sEmDash(u"\u2014"_ustr); +constexpr OUString sEnDash(u"\u2013"_ustr); constexpr sal_Unicode cApostrophe = 0x2019; constexpr sal_Unicode cLeftDoubleAngleQuote = 0xAB; constexpr sal_Unicode cRightDoubleAngleQuote = 0xBB; @@ -324,10 +320,10 @@ const sal_Unicode aStopDoubleAngleQuoteEndRo[] = { cLeftDoubleAngleQuote, cRight const sal_Unicode aStopSingleQuoteEnd[] = { 0x201A, 0x2018, 0x201C, 0x201E, 0 }; const sal_Unicode aStopSingleQuoteEndRuUa[] = { 0x201E, 0x201C, cRightDoubleAngleQuote, cLeftDoubleAngleQuote, 0 }; -SvxAutoCorrect::SvxAutoCorrect( const OUString& rShareAutocorrFile, - const OUString& rUserAutocorrFile ) - : sShareAutoCorrFile( rShareAutocorrFile ) - , sUserAutoCorrFile( rUserAutocorrFile ) +SvxAutoCorrect::SvxAutoCorrect( OUString aShareAutocorrFile, + OUString aUserAutocorrFile ) + : sShareAutoCorrFile(std::move( aShareAutocorrFile )) + , sUserAutoCorrFile(std::move( aUserAutocorrFile )) , eCharClassLang( LANGUAGE_DONTKNOW ) , nFlags(SvxAutoCorrect::GetDefaultFlags()) , cStartDQuote( 0 ) @@ -342,7 +338,7 @@ SvxAutoCorrect::SvxAutoCorrect( const SvxAutoCorrect& rCpy ) , sUserAutoCorrFile( rCpy.sUserAutoCorrFile ) , aSwFlags( rCpy.aSwFlags ) , eCharClassLang(rCpy.eCharClassLang) - , nFlags( rCpy.nFlags & ~ACFlags(ACFlags::ChgWordLstLoad|ACFlags::CplSttLstLoad|ACFlags::WrdSttLstLoad)) + , nFlags( rCpy.nFlags & ~ACFlags(ACFlags::ChgWordLstLoad|ACFlags::CplSttLstLoad|ACFlags::WordStartLstLoad)) , cStartDQuote( rCpy.cStartDQuote ) , cEndDQuote( rCpy.cEndDQuote ) , cStartSQuote( rCpy.cStartSQuote ) @@ -357,7 +353,7 @@ SvxAutoCorrect::~SvxAutoCorrect() void SvxAutoCorrect::GetCharClass_( LanguageType eLang ) { - pCharClass.reset( new CharClass( LanguageTag( eLang)) ); + moCharClass.emplace( LanguageTag( eLang) ); eCharClassLang = eLang; } @@ -372,7 +368,7 @@ void SvxAutoCorrect::SetAutoCorrFlag( ACFlags nFlag, bool bOn ) if( (nOld & ACFlags::CapitalStartSentence) != (nFlags & ACFlags::CapitalStartSentence) ) nFlags &= ~ACFlags::CplSttLstLoad; if( (nOld & ACFlags::CapitalStartWord) != (nFlags & ACFlags::CapitalStartWord) ) - nFlags &= ~ACFlags::WrdSttLstLoad; + nFlags &= ~ACFlags::WordStartLstLoad; if( (nOld & ACFlags::Autocorrect) != (nFlags & ACFlags::Autocorrect) ) nFlags &= ~ACFlags::ChgWordLstLoad; } @@ -438,7 +434,7 @@ void SvxAutoCorrect::FnCapitalStartWord( SvxAutoCorrDoc& rDoc, const OUString& r { // test if the word is in an exception list OUString sWord( rTxt.copy( nSttPos - 1, nEndPos - nSttPos + 1 )); - if( !FindInWrdSttExceptList(eLang, sWord) ) + if( !FindInWordStartExceptList(eLang, sWord) ) { // Check that word isn't correctly spelt before correcting: css::uno::Reference< css::linguistic2::XSpellChecker1 > xSpeller = @@ -455,7 +451,7 @@ void SvxAutoCorrect::FnCapitalStartWord( SvxAutoCorrDoc& rDoc, const OUString& r OUString sChar = rCC.lowercase( OUString(cSave) ); if( sChar[0] != cSave && rDoc.ReplaceRange( nSttPos, 1, sChar )) { - if( ACFlags::SaveWordWrdSttLst & nFlags ) + if( ACFlags::SaveWordWordStartLst & nFlags ) rDoc.SaveCpltSttWord( ACFlags::CapitalStartWord, nSttPos, sWord, cSave ); } } @@ -483,10 +479,10 @@ bool SvxAutoCorrect::FnChgOrdinalNumber( CharClass& rCC = GetCharClass(eLang); for (; nSttPos < nEndPos; ++nSttPos) - if (!lcl_IsInAsciiArr(sImplSttSkipChars, rTxt[nSttPos])) + if (!lcl_IsInArr(sImplSttSkipChars, rTxt[nSttPos])) break; for (; nSttPos < nEndPos; --nEndPos) - if (!lcl_IsInAsciiArr(sImplEndSkipChars, rTxt[nEndPos - 1])) + if (!lcl_IsInArr(sImplEndSkipChars, rTxt[nEndPos - 1])) break; @@ -510,7 +506,7 @@ bool SvxAutoCorrect::FnChgOrdinalNumber( } if (bFoundEnd && isValidNumber) { - sal_Int32 nNum = rTxt.copy(nSttPos, nNumEnd - nSttPos + 1).toInt32(); + sal_Int32 nNum = o3tl::toInt32(rTxt.subView(nSttPos, nNumEnd - nSttPos + 1)); // Check if the characters after that number correspond to the ordinal suffix uno::Reference< i18n::XOrdinalSuffix > xOrdSuffix @@ -519,7 +515,7 @@ bool SvxAutoCorrect::FnChgOrdinalNumber( const uno::Sequence< OUString > aSuffixes = xOrdSuffix->getOrdinalSuffix(nNum, rCC.getLanguageTag().getLocale()); for (OUString const & sSuffix : aSuffixes) { - OUString sEnd = rTxt.copy(nNumEnd + 1, nEndPos - nNumEnd - 1); + std::u16string_view sEnd = rTxt.subView(nNumEnd + 1, nEndPos - nNumEnd - 1); if (sSuffix == sEnd) { @@ -553,6 +549,11 @@ bool SvxAutoCorrect::FnChgToEnEmDash( eLang = GetAppLang().getLanguageType(); bool bAlwaysUseEmDash = (eLang == LANGUAGE_RUSSIAN || eLang == LANGUAGE_UKRAINIAN); + // rTxt may refer to the frame text that will change in the calls to rDoc.Delete / rDoc.Insert; + // keep a local copy for later use + OUString aOrigTxt = rTxt; + sal_Int32 nFirstReplacementTextLengthChange = 0; + // replace " - " or " --" with "enDash" if( 1 < nSttPos && 1 <= nEndPos - nSttPos ) { @@ -564,7 +565,7 @@ bool SvxAutoCorrect::FnChgToEnEmDash( '-' == rTxt[ nSttPos+1 ]) { sal_Int32 n; - for( n = nSttPos+2; n < nEndPos && lcl_IsInAsciiArr( + for( n = nSttPos+2; n < nEndPos && lcl_IsInArr( sImplSttSkipChars,(cCh = rTxt[ n ])); ++n ) ; @@ -572,7 +573,7 @@ bool SvxAutoCorrect::FnChgToEnEmDash( // found: " --[<AnySttChars>][A-z0-9] if( rCC.isLetterNumeric( OUString(cCh) ) ) { - for( n = nSttPos-1; n && lcl_IsInAsciiArr( + for( n = nSttPos-1; n && lcl_IsInArr( sImplEndSkipChars,(cCh = rTxt[ --n ])); ) ; @@ -580,7 +581,8 @@ bool SvxAutoCorrect::FnChgToEnEmDash( if( rCC.isLetterNumeric( OUString(cCh) )) { rDoc.Delete( nSttPos, nSttPos + 2 ); - rDoc.Insert( nSttPos, bAlwaysUseEmDash ? OUString(cEmDash) : OUString(cEnDash) ); + rDoc.Insert( nSttPos, bAlwaysUseEmDash ? sEmDash : sEnDash ); + nFirstReplacementTextLengthChange = -1; // 2 ch -> 1 ch bRet = true; } } @@ -599,7 +601,7 @@ bool SvxAutoCorrect::FnChgToEnEmDash( } if( ' ' == cCh ) { - for( n = nSttPos; n < nEndPos && lcl_IsInAsciiArr( + for( n = nSttPos; n < nEndPos && lcl_IsInArr( sImplSttSkipChars,(cCh = rTxt[ n ])); ++n ) ; @@ -608,14 +610,15 @@ bool SvxAutoCorrect::FnChgToEnEmDash( if( rCC.isLetterNumeric( OUString(cCh) ) ) { cCh = ' '; - for( n = nTmpPos-1; n && lcl_IsInAsciiArr( + for( n = nTmpPos-1; n && lcl_IsInArr( sImplEndSkipChars,(cCh = rTxt[ --n ])); ) ; // found: "[A-z0-9][<AnyEndChars>] - [<AnySttChars>][A-z0-9] - if( rCC.isLetterNumeric( OUString(cCh) )) + if (rCC.isLetterNumeric(OUString(cCh)) || lcl_IsInArr(u".!?", cCh)) { rDoc.Delete( nTmpPos, nTmpPos + nLen ); - rDoc.Insert( nTmpPos, bAlwaysUseEmDash ? OUString(cEmDash) : OUString(cEnDash) ); + rDoc.Insert( nTmpPos, bAlwaysUseEmDash ? sEmDash : sEnDash ); + nFirstReplacementTextLengthChange = 1 - nLen; // nLen ch -> 1 ch bRet = true; } } @@ -629,32 +632,47 @@ bool SvxAutoCorrect::FnChgToEnEmDash( bool bEnDash = (eLang == LANGUAGE_HUNGARIAN || eLang == LANGUAGE_FINNISH); if( 4 <= nEndPos - nSttPos ) { - OUString sTmp( rTxt.copy( nSttPos, nEndPos - nSttPos ) ); - sal_Int32 nFndPos = sTmp.indexOf("--"); - if( nFndPos != -1 && nFndPos && - nFndPos + 2 < sTmp.getLength() && - ( rCC.isLetterNumeric( sTmp, nFndPos - 1 ) || - lcl_IsInAsciiArr( sImplEndSkipChars, rTxt[ nFndPos - 1 ] )) && - ( rCC.isLetterNumeric( sTmp, nFndPos + 2 ) || - lcl_IsInAsciiArr( sImplSttSkipChars, rTxt[ nFndPos + 2 ] ))) + std::u16string_view sTmpView( aOrigTxt.subView( nSttPos, nEndPos - nSttPos ) ); + size_t nFndPos = sTmpView.find(u"--"); + if (nFndPos > 0 && nFndPos < sTmpView.size() - 2) { - nSttPos = nSttPos + nFndPos; - rDoc.Delete( nSttPos, nSttPos + 2 ); - rDoc.Insert( nSttPos, (bEnDash || (rCC.isDigit( sTmp, nFndPos - 1 ) && - rCC.isDigit( sTmp, nFndPos + 2 )) ? OUString(cEnDash) : OUString(cEmDash)) ); - bRet = true; + // Use proper codepoints. Currently, CharClass::isLetterNumeric is broken, it + // uses the index *both* as code unit index (when checking it as ASCII), *and* + // as code point index (when passes to css::i18n::XCharacterClassification). + // Oh well... Anyway, single-codepoint strings will workaround it. + sal_Int32 nStart = nSttPos + nFndPos; + sal_uInt32 chStart = aOrigTxt.iterateCodePoints(&nStart, -1); + OUString sStart(&chStart, 1); + // No idea why sImplEndSkipChars is checked at start + if (rCC.isLetterNumeric(sStart, 0) || lcl_IsInArr(sImplEndSkipChars, chStart)) + { + sal_Int32 nEnd = nSttPos + nFndPos + 2; + sal_uInt32 chEnd = aOrigTxt.iterateCodePoints(&nEnd, 1); + OUString sEnd(&chEnd, 1); + // No idea why sImplSttSkipChars is checked at end + if (rCC.isLetterNumeric(sEnd, 0) || lcl_IsInArr(sImplSttSkipChars, chEnd)) + { + nSttPos = nSttPos + nFndPos + nFirstReplacementTextLengthChange; + rDoc.Delete(nSttPos, nSttPos + 2); + rDoc.Insert(nSttPos, + (bEnDash || (rCC.isDigit(sStart, 0) && rCC.isDigit(sEnd, 0)) + ? sEnDash + : sEmDash)); + bRet = true; + } + } } } return bRet; } // Add non-breaking space before specific punctuation marks in French text -bool SvxAutoCorrect::FnAddNonBrkSpace( - SvxAutoCorrDoc& rDoc, const OUString& rTxt, +sal_Int32 SvxAutoCorrect::FnAddNonBrkSpace( + SvxAutoCorrDoc& rDoc, std::u16string_view rTxt, sal_Int32 nEndPos, LanguageType eLang, bool& io_bNbspRunNext ) { - bool bRet = false; + sal_Int32 nRet = -1; CharClass& rCC = GetCharClass( eLang ); @@ -683,17 +701,17 @@ bool SvxAutoCorrect::FnAddNonBrkSpace( //See if the text is the start of a protocol string, e.g. have text of //"http" see if it is the start of "http:" and if so leave it alone - sal_Int32 nIndex = nSttWdPos + (bWasWordDelim ? 1 : 0); - sal_Int32 nProtocolLen = nEndPos - nSttWdPos + 1; - if (nIndex + nProtocolLen <= rTxt.getLength()) + size_t nIndex = nSttWdPos + (bWasWordDelim ? 1 : 0); + size_t nProtocolLen = nEndPos - nSttWdPos + 1; + if (nIndex + nProtocolLen <= rTxt.size()) { - if (INetURLObject::CompareProtocolScheme(rTxt.copy(nIndex, nProtocolLen)) != INetProtocol::NotValid) - return false; + if (INetURLObject::CompareProtocolScheme(rTxt.substr(nIndex, nProtocolLen)) != INetProtocol::NotValid) + return -1; } // Check the presence of "://" in the word - sal_Int32 nStrPos = rTxt.indexOf( "://", nSttWdPos + 1 ); - if ( nStrPos == -1 && nEndPos > 0 ) + size_t nStrPos = rTxt.find( u"://", nSttWdPos + 1 ); + if ( nStrPos == std::u16string_view::npos && nEndPos > 0 ) { // Check the previous char sal_Unicode cPrevChar = rTxt[ nEndPos - 1 ]; @@ -716,13 +734,13 @@ bool SvxAutoCorrect::FnAddNonBrkSpace( if ( bHasSpace ) rDoc.Insert( nPos, OUString(cNonBreakingSpace) ); io_bNbspRunNext = true; - bRet = true; + nRet = nPos; } else if ( chars.indexOf( cPrevChar ) != -1 ) io_bNbspRunNext = true; } } - else if ( cChar == '/' && nEndPos > 1 && rTxt.getLength() > (nEndPos - 1) ) + else if ( cChar == '/' && nEndPos > 1 && static_cast<sal_Int32>(rTxt.size()) > (nEndPos - 1) ) { // Remove the hardspace right before to avoid formatting URLs sal_Unicode cPrevChar = rTxt[ nEndPos - 1 ]; @@ -730,12 +748,12 @@ bool SvxAutoCorrect::FnAddNonBrkSpace( if ( cPrevChar == ':' && cMaybeSpaceChar == cNonBreakingSpace ) { rDoc.Delete( nEndPos - 2, nEndPos - 1 ); - bRet = true; + nRet = nEndPos - 1; } } } - return bRet; + return nRet; } // URL recognition @@ -751,6 +769,18 @@ bool SvxAutoCorrect::FnSetINetAttr( SvxAutoCorrDoc& rDoc, const OUString& rTxt, return bRet; } +// DOI citation recognition +bool SvxAutoCorrect::FnSetDOIAttr( SvxAutoCorrDoc& rDoc, std::u16string_view rTxt, + sal_Int32 nSttPos, sal_Int32 nEndPos, + LanguageType eLang ) +{ + OUString sURL( URIHelper::FindFirstDOIInText( rTxt, nSttPos, nEndPos, GetCharClass( eLang ) )); + bool bRet = !sURL.isEmpty(); + if( bRet ) // so, set attribute: + rDoc.SetINetAttr( nSttPos, nEndPos, sURL ); + return bRet; +} + // Automatic *bold*, /italic/, -strikeout- and _underline_ bool SvxAutoCorrect::FnChgWeightUnderl( SvxAutoCorrDoc& rDoc, const OUString& rTxt, sal_Int32 nEndPos ) @@ -803,38 +833,39 @@ bool SvxAutoCorrect::FnChgWeightUnderl( SvxAutoCorrDoc& rDoc, const OUString& rT // of an empty hint in SetAttr which would be removed by Delete // (fdo#62536, AUTOFMT in Writer) rDoc.Delete( nEndPos, nEndPos + 1 ); - rDoc.Delete( nFndPos, nFndPos + 1 ); + // Span the Attribute over the area // the end. if( '*' == cInsChar ) // Bold { SvxWeightItem aSvxWeightItem( WEIGHT_BOLD, SID_ATTR_CHAR_WEIGHT ); - rDoc.SetAttr( nFndPos, nEndPos - 1, + rDoc.SetAttr( nFndPos + 1, nEndPos, SID_ATTR_CHAR_WEIGHT, aSvxWeightItem); } else if( '/' == cInsChar ) // Italic { SvxPostureItem aSvxPostureItem( ITALIC_NORMAL, SID_ATTR_CHAR_POSTURE ); - rDoc.SetAttr( nFndPos, nEndPos - 1, + rDoc.SetAttr( nFndPos + 1, nEndPos, SID_ATTR_CHAR_POSTURE, aSvxPostureItem); } else if( '-' == cInsChar ) // Strikeout { SvxCrossedOutItem aSvxCrossedOutItem( STRIKEOUT_SINGLE, SID_ATTR_CHAR_STRIKEOUT ); - rDoc.SetAttr( nFndPos, nEndPos - 1, + rDoc.SetAttr( nFndPos + 1, nEndPos, SID_ATTR_CHAR_STRIKEOUT, aSvxCrossedOutItem); } else // Underline { SvxUnderlineItem aSvxUnderlineItem( LINESTYLE_SINGLE, SID_ATTR_CHAR_UNDERLINE ); - rDoc.SetAttr( nFndPos, nEndPos - 1, + rDoc.SetAttr( nFndPos + 1, nEndPos, SID_ATTR_CHAR_UNDERLINE, aSvxUnderlineItem); } - } + rDoc.Delete( nFndPos, nFndPos + 1 ); + } return -1 != nFndPos; } @@ -867,7 +898,7 @@ void SvxAutoCorrect::FnCapitalStartSentence( SvxAutoCorrDoc& rDoc, } else if (pWordStt && !rCC.isDigit(aText, pStr - pStart)) { - if( (lcl_IsInAsciiArr( "-'", *pStr ) || *pStr == cApostrophe) && // These characters are allowed in words + if( (lcl_IsInArr( u"-'", *pStr ) || *pStr == cApostrophe) && // These characters are allowed in words pWordStt - 1 == pStr && // Installation at beginning of paragraph. Replaced < by <= (#i38971#) (pStart + 1) <= pStr && @@ -895,7 +926,7 @@ void SvxAutoCorrect::FnCapitalStartSentence( SvxAutoCorrDoc& rDoc, sal_Int32 nProtocolLen = pDelim - pWordStt + 1; if (nIndex + nProtocolLen <= rTxt.getLength()) { - if (INetURLObject::CompareProtocolScheme(rTxt.copy(nIndex, nProtocolLen)) != INetProtocol::NotValid) + if (INetURLObject::CompareProtocolScheme(rTxt.subView(nIndex, nProtocolLen)) != INetProtocol::NotValid) return; // already ok } @@ -904,7 +935,7 @@ void SvxAutoCorrect::FnCapitalStartSentence( SvxAutoCorrDoc& rDoc, // Only capitalize, if string before specified characters is long enough if( *pDelim && 2 >= pDelim - pWordStt && - lcl_IsInAsciiArr( ".-)>", *pDelim ) ) + lcl_IsInArr( u".-)>", *pDelim ) ) return; // tdf#59666 don't capitalize single Greek letters (except in Greek texts) @@ -930,7 +961,7 @@ void SvxAutoCorrect::FnCapitalStartSentence( SvxAutoCorrDoc& rDoc, } // No replacement for words in TWo INitial CApitals or sMALL iNITIAL list - if (FindInWrdSttExceptList(eLang, OUString(pWordStt, pDelim - pWordStt))) + if (FindInWordStartExceptList(eLang, OUString(pWordStt, pDelim - pWordStt))) return; if( bAtStart ) // at the beginning of a paragraph? @@ -1149,7 +1180,7 @@ bool SvxAutoCorrect::FnCorrectCapsLock( SvxAutoCorrDoc& rDoc, const OUString& rT aConverted.append( rCC.lowercase(OUString(rTxt[nSttPos+1])) ); // No replacement for words in TWo INitial CApitals or sMALL iNITIAL list - if (FindInWrdSttExceptList(eLang, rTxt.copy(nSttPos, nEndPos - nSttPos))) + if (FindInWordStartExceptList(eLang, rTxt.copy(nSttPos, nEndPos - nSttPos))) return false; for( sal_Int32 i = nSttPos+2; i < nEndPos; ++i ) @@ -1279,7 +1310,7 @@ OUString SvxAutoCorrect::GetQuote( SvxAutoCorrDoc const & rDoc, sal_Int32 nInsPo // search preceding opening quote in the paragraph before the insert position static bool lcl_HasPrecedingChar( std::u16string_view rTxt, sal_Int32 nPos, - const sal_Unicode sPrecedingChar, const sal_Unicode* aStopChars ) + const sal_Unicode sPrecedingChar, const sal_Unicode sStopChar, const sal_Unicode* aStopChars ) { sal_Unicode cTmpChar; @@ -1288,6 +1319,9 @@ static bool lcl_HasPrecedingChar( std::u16string_view rTxt, sal_Int32 nPos, if ( cTmpChar == sPrecedingChar ) return true; + if ( cTmpChar == sStopChar ) + return false; + for ( const sal_Unicode* pCh = aStopChars; *pCh; ++pCh ) if ( cTmpChar == *pCh ) return false; @@ -1329,7 +1363,7 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, { sal_Unicode cPrev = rTxt[ nInsPos-1 ]; bSttQuote = NonFieldWordDelim(cPrev) || - lcl_IsInAsciiArr( "([{", cPrev ) || + lcl_IsInArr( u"([{", cPrev ) || ( cEmDash == cPrev ) || ( cEnDash == cPrev ); // tdf#38394 use opening quotation mark << in French l'<<word>> @@ -1357,13 +1391,15 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, ( ( eLang == LANGUAGE_HUNGARIAN && lcl_HasPrecedingChar( rTxt, nInsPos, bSttQuote ? aStopDoubleAngleQuoteStart[0] : aStopDoubleAngleQuoteEnd[0], - bSttQuote ? aStopDoubleAngleQuoteStart + 1 : aStopDoubleAngleQuoteEnd + 1 ) ) || + bSttQuote ? aStopDoubleAngleQuoteStart[1] : aStopDoubleAngleQuoteEnd[1], + bSttQuote ? aStopDoubleAngleQuoteStart + 1 : aStopDoubleAngleQuoteEnd + 2 ) ) || ( eLang.anyOf( LANGUAGE_ROMANIAN, LANGUAGE_ROMANIAN_MOLDOVA ) && lcl_HasPrecedingChar( rTxt, nInsPos, bSttQuote ? aStopDoubleAngleQuoteStart[0] : aStopDoubleAngleQuoteEndRo[0], - bSttQuote ? aStopDoubleAngleQuoteStart + 1 : aStopDoubleAngleQuoteEndRo + 1 ) ) ) ) + bSttQuote ? aStopDoubleAngleQuoteStart[1] : aStopDoubleAngleQuoteEndRo[1], + bSttQuote ? aStopDoubleAngleQuoteStart + 1 : aStopDoubleAngleQuoteEndRo + 2 ) ) ) ) { LocaleDataWrapper& rLcl = GetLocaleDataWrapper( eLang ); // only if the opening double quotation mark is the default one @@ -1374,7 +1410,7 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, // tdf#128860 use apostrophe outside of second level quotation in Czech, German, Icelandic, // Slovak and Slovenian instead of the – in this case, bad – closing quotation mark U+2018. // tdf#123786 the same for Russian and Ukrainian - ( ( eLang.anyOf ( + ( eLang.anyOf ( LANGUAGE_CZECH, LANGUAGE_GERMAN, LANGUAGE_GERMAN_SWISS, @@ -1383,17 +1419,33 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, LANGUAGE_GERMAN_LIECHTENSTEIN, LANGUAGE_ICELANDIC, LANGUAGE_SLOVAK, - LANGUAGE_SLOVENIAN ) && - !lcl_HasPrecedingChar( rTxt, nInsPos, aStopSingleQuoteEnd[0], aStopSingleQuoteEnd + 1 ) ) || + LANGUAGE_SLOVENIAN ) ) ) + { + sal_Unicode sStartChar = GetStartSingleQuote(); + sal_Unicode sEndChar = GetEndSingleQuote(); + if ( !sStartChar || !sEndChar ) { + LocaleDataWrapper& rLcl = GetLocaleDataWrapper( eLang ); + if ( !sStartChar ) sStartChar = rLcl.getQuotationMarkStart()[0]; + if ( !sEndChar ) sEndChar = rLcl.getQuotationMarkStart()[0]; + } + if ( !lcl_HasPrecedingChar( rTxt, nInsPos, sStartChar, sEndChar, aStopSingleQuoteEnd + 1 ) ) + { + CharClass& rCC = GetCharClass( eLang ); + if ( rCC.isLetter(rTxt, nInsPos-1) ) + { + eType = ACQuotes::UseApostrophe; + } + } + } + else if ( bSingle && nInsPos && !bSttQuote && ( eLang.anyOf ( LANGUAGE_RUSSIAN, LANGUAGE_UKRAINIAN ) && - !lcl_HasPrecedingChar( rTxt, nInsPos, aStopSingleQuoteEndRuUa[0], aStopSingleQuoteEndRuUa + 1 ) ) ) ) + !lcl_HasPrecedingChar( rTxt, nInsPos, aStopSingleQuoteEndRuUa[0], aStopSingleQuoteEndRuUa[1], aStopSingleQuoteEndRuUa + 2 ) ) ) { LocaleDataWrapper& rLcl = GetLocaleDataWrapper( eLang ); CharClass& rCC = GetCharClass( eLang ); - if ( ( rLcl.getQuotationMarkStart() == OUStringChar(aStopSingleQuoteEnd[0]) || - rLcl.getQuotationMarkStart() == OUStringChar(aStopSingleQuoteEndRuUa[0]) ) && + if ( rLcl.getQuotationMarkStart() == OUStringChar(aStopSingleQuoteEndRuUa[0]) && // use apostrophe only after letters, not after digits or punctuation rCC.isLetter(rTxt, nInsPos-1) ) { @@ -1449,10 +1501,14 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, // Hardspaces autocorrection if ( IsAutoCorrFlag( ACFlags::AddNonBrkSpace ) ) { - if ( NeedsHardspaceAutocorr( cChar ) && - FnAddNonBrkSpace( rDoc, rTxt, nInsPos, GetDocLanguage( rDoc, nInsPos ), io_bNbspRunNext ) ) + // WARNING ATTENTION: rTxt is an alias of the text node's OUString + // and its length may change (even become shorter) if FnAddNonBrkSpace succeeds! + sal_Int32 nUpdatedPos = -1; + if (NeedsHardspaceAutocorr(cChar)) + nUpdatedPos = FnAddNonBrkSpace( rDoc, rTxt, nInsPos, GetDocLanguage( rDoc, nInsPos ), io_bNbspRunNext ); + if (nUpdatedPos >= 0) { - ; + nInsPos = nUpdatedPos; } else if ( bIsNextRun && !IsAutoCorrectChar( cChar ) ) { @@ -1531,11 +1587,11 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, { sal_Int32 nCapLttrPos1 = nCapLttrPos, nInsPos1 = nInsPos; while( nCapLttrPos1 < nInsPos && - lcl_IsInAsciiArr( sImplSttSkipChars, rTxt[ nCapLttrPos1 ] ) + lcl_IsInArr( sImplSttSkipChars, rTxt[ nCapLttrPos1 ] ) ) ++nCapLttrPos1; while( nCapLttrPos1 < nInsPos1 && nInsPos1 && - lcl_IsInAsciiArr( sImplEndSkipChars, rTxt[ nInsPos1-1 ] ) + lcl_IsInArr( sImplEndSkipChars, rTxt[ nInsPos1-1 ] ) ) --nInsPos1; @@ -1587,7 +1643,10 @@ void SvxAutoCorrect::DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, FnChgOrdinalNumber( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) || ( IsAutoCorrFlag( ACFlags::SetINetAttr ) && ( ' ' == cChar || '\t' == cChar || 0x0a == cChar || !cChar ) && - FnSetINetAttr( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) ) + FnSetINetAttr( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) || + ( IsAutoCorrFlag( ACFlags::SetDOIAttr ) && + ( ' ' == cChar || '\t' == cChar || 0x0a == cChar || !cChar ) && + FnSetDOIAttr( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) ) ; else { @@ -1632,25 +1691,27 @@ SvxAutoCorrectLanguageLists& SvxAutoCorrect::GetLanguageList_( LanguageTag aLanguageTag( eLang); if (m_aLangTable.find(aLanguageTag) == m_aLangTable.end()) (void)CreateLanguageFile(aLanguageTag); - return *(m_aLangTable.find(aLanguageTag)->second); + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end()); + return iter->second; } void SvxAutoCorrect::SaveCplSttExceptList( LanguageType eLang ) { auto const iter = m_aLangTable.find(LanguageTag(eLang)); - if (iter != m_aLangTable.end() && iter->second) - iter->second->SaveCplSttExceptList(); + if (iter != m_aLangTable.end()) + iter->second.SaveCplSttExceptList(); else { SAL_WARN("editeng", "Save an empty list? "); } } -void SvxAutoCorrect::SaveWrdSttExceptList(LanguageType eLang) +void SvxAutoCorrect::SaveWordStartExceptList(LanguageType eLang) { auto const iter = m_aLangTable.find(LanguageTag(eLang)); - if (iter != m_aLangTable.end() && iter->second) - iter->second->SaveWrdSttExceptList(); + if (iter != m_aLangTable.end()) + iter->second.SaveWordStartExceptList(); else { SAL_WARN("editeng", "Save an empty list? "); @@ -1665,40 +1726,48 @@ bool SvxAutoCorrect::AddCplSttException( const OUString& rNew, // either the right language is present or it will be this in the general list auto iter = m_aLangTable.find(LanguageTag(eLang)); if (iter != m_aLangTable.end()) - pLists = iter->second.get(); + pLists = &iter->second; else { LanguageTag aLangTagUndetermined( LANGUAGE_UNDETERMINED); iter = m_aLangTable.find(aLangTagUndetermined); if (iter != m_aLangTable.end()) - pLists = iter->second.get(); + pLists = &iter->second; else if(CreateLanguageFile(aLangTagUndetermined)) - pLists = m_aLangTable.find(aLangTagUndetermined)->second.get(); + { + iter = m_aLangTable.find(aLangTagUndetermined); + assert(iter != m_aLangTable.end()); + pLists = &iter->second; + } } OSL_ENSURE(pLists, "No auto correction data"); return pLists && pLists->AddToCplSttExceptList(rNew); } // Adds a single word. The list will immediately be written to the file! -bool SvxAutoCorrect::AddWrtSttException( const OUString& rNew, +bool SvxAutoCorrect::AddWordStartException( const OUString& rNew, LanguageType eLang ) { SvxAutoCorrectLanguageLists* pLists = nullptr; //either the right language is present or it is set in the general list auto iter = m_aLangTable.find(LanguageTag(eLang)); if (iter != m_aLangTable.end()) - pLists = iter->second.get(); + pLists = &iter->second; else { LanguageTag aLangTagUndetermined( LANGUAGE_UNDETERMINED); iter = m_aLangTable.find(aLangTagUndetermined); if (iter != m_aLangTable.end()) - pLists = iter->second.get(); + pLists = &iter->second; else if(CreateLanguageFile(aLangTagUndetermined)) - pLists = m_aLangTable.find(aLangTagUndetermined)->second.get(); + { + iter = m_aLangTable.find(aLangTagUndetermined); + assert(iter != m_aLangTable.end()); + pLists = &iter->second; + } } OSL_ENSURE(pLists, "No auto correction file!"); - return pLists && pLists->AddToWrdSttExceptList(rNew); + return pLists && pLists->AddToWordStartExceptList(rNew); } OUString SvxAutoCorrect::GetPrevAutoCorrWord(SvxAutoCorrDoc const& rDoc, const OUString& rTxt, @@ -1725,7 +1794,7 @@ OUString SvxAutoCorrect::GetPrevAutoCorrWord(SvxAutoCorrDoc const& rDoc, const O if( !nPos && !IsWordDelim( rTxt[ 0 ])) --nCapLttrPos; // Beginning of paragraph and no Blank! - while( lcl_IsInAsciiArr( sImplSttSkipChars, rTxt[ nCapLttrPos ]) ) + while( lcl_IsInArr( sImplSttSkipChars, rTxt[ nCapLttrPos ]) ) if( ++nCapLttrPos >= nEnd ) return sRet; @@ -1744,7 +1813,7 @@ OUString SvxAutoCorrect::GetPrevAutoCorrWord(SvxAutoCorrDoc const& rDoc, const O } // static -std::vector<OUString> SvxAutoCorrect::GetChunkForAutoText(const OUString& rTxt, +std::vector<OUString> SvxAutoCorrect::GetChunkForAutoText(std::u16string_view rTxt, const sal_Int32 nPos) { constexpr sal_Int32 nMinLen = 3; @@ -1761,7 +1830,7 @@ std::vector<OUString> SvxAutoCorrect::GetChunkForAutoText(const OUString& rTxt, } if (nBegin + nMinLen <= nPos) { - OUString sRes = rTxt.copy(nBegin, nPos - nBegin); + OUString sRes( rTxt.substr(nBegin, nPos - nBegin) ); aRes.push_back(sRes); bool bLastStartedWithDelim = IsWordDelim(sRes[0]); for (sal_Int32 i = 1; i <= sRes.getLength() - nMinLen; ++i) @@ -1798,9 +1867,10 @@ bool SvxAutoCorrect::CreateLanguageFile( const LanguageTag& rLanguageTag, bool b if( bNewFile ) { sShareDirFile = sUserDirFile; - pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile, sUserDirFile ); - LanguageTag aTmp(rLanguageTag); // this insert() needs a non-const reference - m_aLangTable.insert(std::make_pair(aTmp, std::unique_ptr<SvxAutoCorrectLanguageLists>(pLists))); + auto itBool = m_aLangTable.emplace(std::piecewise_construct, + std::forward_as_tuple(rLanguageTag), + std::forward_as_tuple(*this, sShareDirFile, sUserDirFile)); + pLists = &itBool.first->second; aLastFileTable.erase(nFndPos); } } @@ -1814,9 +1884,10 @@ bool SvxAutoCorrect::CreateLanguageFile( const LanguageTag& rLanguageTag, bool b ( sShareDirFile = sUserDirFile, bNewFile ) ) { - pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile, sUserDirFile ); - LanguageTag aTmp(rLanguageTag); // this insert() needs a non-const reference - m_aLangTable.insert(std::make_pair(aTmp, std::unique_ptr<SvxAutoCorrectLanguageLists>(pLists))); + auto itBool = m_aLangTable.emplace(std::piecewise_construct, + std::forward_as_tuple(rLanguageTag), + std::forward_as_tuple(*this, sShareDirFile, sUserDirFile)); + pLists = &itBool.first->second; if (nFndPos != aLastFileTable.end()) aLastFileTable.erase(nFndPos); } @@ -1831,11 +1902,14 @@ bool SvxAutoCorrect::PutText( const OUString& rShort, const OUString& rLong, LanguageType eLang ) { LanguageTag aLanguageTag( eLang); - auto const iter = m_aLangTable.find(aLanguageTag); - if (iter != m_aLangTable.end()) - return iter->second->PutText(rShort, rLong); - if(CreateLanguageFile(aLanguageTag)) - return m_aLangTable.find(aLanguageTag)->second->PutText(rShort, rLong); + if (auto const iter = m_aLangTable.find(aLanguageTag); iter != m_aLangTable.end()) + return iter->second.PutText(rShort, rLong); + if (CreateLanguageFile(aLanguageTag)) + { + auto const iter = m_aLangTable.find(aLanguageTag); + assert (iter != m_aLangTable.end()); + return iter->second.PutText(rShort, rLong); + } return false; } @@ -1844,14 +1918,16 @@ void SvxAutoCorrect::MakeCombinedChanges( std::vector<SvxAutocorrWord>& aNewEntr LanguageType eLang ) { LanguageTag aLanguageTag( eLang); - auto const iter = m_aLangTable.find(aLanguageTag); + auto iter = m_aLangTable.find(aLanguageTag); if (iter != m_aLangTable.end()) { - iter->second->MakeCombinedChanges( aNewEntries, aDeleteEntries ); + iter->second.MakeCombinedChanges( aNewEntries, aDeleteEntries ); } else if(CreateLanguageFile( aLanguageTag )) { - m_aLangTable.find( aLanguageTag )->second->MakeCombinedChanges( aNewEntries, aDeleteEntries ); + iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end()); + iter->second.MakeCombinedChanges( aNewEntries, aDeleteEntries ); } } @@ -1873,13 +1949,13 @@ bool SvxAutoCorrect::PutText( const css::uno::Reference < css::embed::XStorage > return false; } -OUString EncryptBlockName_Imp(const OUString& rName) +OUString EncryptBlockName_Imp(std::u16string_view rName) { OUStringBuffer aName; aName.append('#').append(rName); - for (sal_Int32 nLen = rName.getLength(), nPos = 1; nPos < nLen; ++nPos) + for (size_t nLen = rName.size(), nPos = 1; nPos < nLen; ++nPos) { - if (lcl_IsInAsciiArr( "!/:.\\", aName[nPos])) + if (lcl_IsInArr( u"!/:.\\", aName[nPos])) aName[nPos] &= 0x0f; } return aName.makeStringAndClear(); @@ -1900,6 +1976,8 @@ static void GeneratePackageName ( std::u16string_view rShort, OUString& rPackage case ':': case '.': case '\\': + // tdf#156769 - escape the question mark in the storage name + case '?': aBuf[nPos] = '_'; break; default: @@ -1911,7 +1989,7 @@ static void GeneratePackageName ( std::u16string_view rShort, OUString& rPackage } static const SvxAutocorrWord* lcl_SearchWordsInList( - SvxAutoCorrectLanguageLists* pList, const OUString& rTxt, + SvxAutoCorrectLanguageLists* pList, std::u16string_view rTxt, sal_Int32& rStt, sal_Int32 nEndPos) { const SvxAutocorrWordList* pAutoCorrWordList = pList->GetAutocorrWordList(); @@ -1920,13 +1998,13 @@ static const SvxAutocorrWord* lcl_SearchWordsInList( // the search for the words in the substitution table const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList( - const OUString& rTxt, sal_Int32& rStt, sal_Int32 nEndPos, + std::u16string_view rTxt, sal_Int32& rStt, sal_Int32 nEndPos, SvxAutoCorrDoc&, LanguageTag& rLang ) { const SvxAutocorrWord* pRet = nullptr; LanguageTag aLanguageTag( rLang); if( aLanguageTag.isSystemLocale() ) - aLanguageTag.reset( MsLangId::getSystemLanguage()); + aLanguageTag.reset( MsLangId::getConfiguredSystemLanguage()); /* TODO-BCP47: this is so ugly, should all maybe be a proper fallback * list instead? */ @@ -1936,8 +2014,10 @@ const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList( if (m_aLangTable.find(aLanguageTag) != m_aLangTable.end() || CreateLanguageFile(aLanguageTag, false)) { //the language is available - so bring it on - std::unique_ptr<SvxAutoCorrectLanguageLists> const& pList = m_aLangTable.find(aLanguageTag)->second; - pRet = lcl_SearchWordsInList( pList.get(), rTxt, rStt, nEndPos ); + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end()); + SvxAutoCorrectLanguageLists & rList = iter->second; + pRet = lcl_SearchWordsInList( &rList, rTxt, rStt, nEndPos ); if( pRet ) { rLang = aLanguageTag; @@ -1957,8 +2037,8 @@ const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList( CreateLanguageFile(aLanguageTag, false))) { //the language is available - so bring it on - std::unique_ptr<SvxAutoCorrectLanguageLists> const& pList = m_aLangTable.find(aLanguageTag)->second; - pRet = lcl_SearchWordsInList( pList.get(), rTxt, rStt, nEndPos ); + SvxAutoCorrectLanguageLists& rList = m_aLangTable.find(aLanguageTag)->second; + pRet = lcl_SearchWordsInList( &rList, rTxt, rStt, nEndPos ); if( pRet ) { rLang = aLanguageTag; @@ -1970,8 +2050,10 @@ const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList( CreateLanguageFile(aLanguageTag, false)) { //the language is available - so bring it on - std::unique_ptr<SvxAutoCorrectLanguageLists> const& pList = m_aLangTable.find(aLanguageTag)->second; - pRet = lcl_SearchWordsInList( pList.get(), rTxt, rStt, nEndPos ); + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end()); + SvxAutoCorrectLanguageLists& rList = iter->second; + pRet = lcl_SearchWordsInList( &rList, rTxt, rStt, nEndPos ); if( pRet ) { rLang = aLanguageTag; @@ -1981,7 +2063,7 @@ const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList( return nullptr; } -bool SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang, +bool SvxAutoCorrect::FindInWordStartExceptList( LanguageType eLang, const OUString& sWord ) { LanguageTag aLanguageTag( eLang); @@ -1994,8 +2076,10 @@ bool SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang, if (m_aLangTable.find(aLanguageTag) != m_aLangTable.end() || CreateLanguageFile(aLanguageTag, false)) { //the language is available - so bring it on - auto const& pList = m_aLangTable.find(aLanguageTag)->second; - if(pList->GetWrdSttExceptList()->find(sWord) != pList->GetWrdSttExceptList()->end() ) + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end() && "CreateLanguageFile can't fail"); + auto& rList = iter->second; + if(rList.GetWordStartExceptList()->find(sWord) != rList.GetWordStartExceptList()->end() ) return true; } @@ -2008,8 +2092,10 @@ bool SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang, CreateLanguageFile(aLanguageTag, false))) { //the language is available - so bring it on - auto const& pList = m_aLangTable.find(aLanguageTag)->second; - if(pList->GetWrdSttExceptList()->find(sWord) != pList->GetWrdSttExceptList()->end() ) + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end() && "CreateLanguageFile can't fail"); + auto& rList = iter->second; + if(rList.GetWordStartExceptList()->find(sWord) != rList.GetWordStartExceptList()->end() ) return true; } @@ -2017,8 +2103,10 @@ bool SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang, CreateLanguageFile(aLanguageTag, false)) { //the language is available - so bring it on - auto const& pList = m_aLangTable.find(aLanguageTag)->second; - if(pList->GetWrdSttExceptList()->find(sWord) != pList->GetWrdSttExceptList()->end() ) + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end()); + auto& rList = iter->second; + if(rList.GetWordStartExceptList()->find(sWord) != rList.GetWordStartExceptList()->end() ) return true; } return false; @@ -2026,7 +2114,7 @@ bool SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang, static bool lcl_FindAbbreviation(const SvStringsISortDtor* pList, const OUString& sWord) { - SvStringsISortDtor::const_iterator it = pList->find( "~" ); + SvStringsISortDtor::const_iterator it = pList->find(u"~"_ustr); SvStringsISortDtor::size_type nPos = it - pList->begin(); if( nPos < pList->size() ) { @@ -2070,7 +2158,9 @@ bool SvxAutoCorrect::FindInCplSttExceptList(LanguageType eLang, if (m_aLangTable.find(aLanguageTag) != m_aLangTable.end() || CreateLanguageFile(aLanguageTag, false)) { //the language is available - so bring it on - const SvStringsISortDtor* pList = m_aLangTable.find(aLanguageTag)->second->GetCplSttExceptList(); + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end() && "CreateLanguageFile can't fail"); + const SvStringsISortDtor* pList = iter->second.GetCplSttExceptList(); if(bAbbreviation ? lcl_FindAbbreviation(pList, sWord) : pList->find(sWord) != pList->end() ) return true; } @@ -2084,7 +2174,9 @@ bool SvxAutoCorrect::FindInCplSttExceptList(LanguageType eLang, CreateLanguageFile(aLanguageTag, false))) { //the language is available - so bring it on - const SvStringsISortDtor* pList = m_aLangTable.find(aLanguageTag)->second->GetCplSttExceptList(); + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end() && "CreateLanguageFile can't fail"); + const SvStringsISortDtor* pList = iter->second.GetCplSttExceptList(); if(bAbbreviation ? lcl_FindAbbreviation(pList, sWord) : pList->find(sWord) != pList->end() ) return true; } @@ -2093,7 +2185,9 @@ bool SvxAutoCorrect::FindInCplSttExceptList(LanguageType eLang, CreateLanguageFile(aLanguageTag, false)) { //the language is available - so bring it on - const SvStringsISortDtor* pList = m_aLangTable.find(aLanguageTag)->second->GetCplSttExceptList(); + const auto iter = m_aLangTable.find(aLanguageTag); + assert(iter != m_aLangTable.end() && "CreateLanguageFile can't fail"); + const SvStringsISortDtor* pList = iter->second.GetCplSttExceptList(); if(bAbbreviation ? lcl_FindAbbreviation(pList, sWord) : pList->find(sWord) != pList->end() ) return true; } @@ -2129,10 +2223,10 @@ OUString SvxAutoCorrect::GetAutoCorrFileName( const LanguageTag& rLanguageTag, SvxAutoCorrectLanguageLists::SvxAutoCorrectLanguageLists( SvxAutoCorrect& rParent, - const OUString& rShareAutoCorrectFile, - const OUString& rUserAutoCorrectFile) -: sShareAutoCorrFile( rShareAutoCorrectFile ), - sUserAutoCorrFile( rUserAutoCorrectFile ), + OUString aShareAutoCorrectFile, + OUString aUserAutoCorrectFile) +: sShareAutoCorrFile(std::move( aShareAutoCorrectFile )), + sUserAutoCorrFile(std::move( aUserAutoCorrectFile )), aModifiedDate( Date::EMPTY ), aModifiedTime( tools::Time::EMPTY ), aLastCheckTime( tools::Time::EMPTY ), @@ -2168,15 +2262,15 @@ bool SvxAutoCorrectLanguageLists::IsFileChanged_Imp() { pCplStt_ExcptLst.reset(); } - if( (ACFlags::WrdSttLstLoad & nFlags) && pWrdStt_ExcptLst ) + if( (ACFlags::WordStartLstLoad & nFlags) && pWordStart_ExcptLst ) { - pWrdStt_ExcptLst.reset(); + pWordStart_ExcptLst.reset(); } if( (ACFlags::ChgWordLstLoad & nFlags) && pAutocorr_List ) { pAutocorr_List.reset(); } - nFlags &= ~ACFlags(ACFlags::CplSttLstLoad | ACFlags::WrdSttLstLoad | ACFlags::ChgWordLstLoad ); + nFlags &= ~ACFlags(ACFlags::CplSttLstLoad | ACFlags::WordStartLstLoad | ACFlags::ChgWordLstLoad ); } aLastCheckTime = tools::Time( tools::Time::SYSTEM ); } @@ -2186,7 +2280,7 @@ bool SvxAutoCorrectLanguageLists::IsFileChanged_Imp() void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp( std::unique_ptr<SvStringsISortDtor>& rpLst, const OUString& sStrmName, - tools::SvRef<SotStorage>& rStg) + rtl::Reference<SotStorage>& rStg) { if( rpLst ) rpLst->clear(); @@ -2196,7 +2290,7 @@ void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp( { if( rStg.is() && rStg->IsStream( sStrmName ) ) { - tools::SvRef<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, + rtl::Reference<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, ( StreamMode::READ | StreamMode::SHARE_DENYWRITE | StreamMode::NOCREATE ) ); if( ERRCODE_NONE != xStrm->GetError()) { @@ -2257,7 +2351,7 @@ void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp( void SvxAutoCorrectLanguageLists::SaveExceptList_Imp( const SvStringsISortDtor& rLst, const OUString& sStrmName, - tools::SvRef<SotStorage> const &rStg, + rtl::Reference<SotStorage> const &rStg, bool bConvert ) { if( !rStg.is() ) @@ -2270,7 +2364,7 @@ void SvxAutoCorrectLanguageLists::SaveExceptList_Imp( } else { - tools::SvRef<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, + rtl::Reference<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, ( StreamMode::READ | StreamMode::WRITE | StreamMode::SHARE_DENYWRITE ) ); if( xStrm.is() ) { @@ -2389,7 +2483,7 @@ bool SvxAutoCorrectLanguageLists::AddToCplSttExceptList(const OUString& rNew) if( !rNew.isEmpty() && GetCplSttExceptList()->insert( rNew ).second ) { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); @@ -2403,16 +2497,15 @@ bool SvxAutoCorrectLanguageLists::AddToCplSttExceptList(const OUString& rNew) return bRet; } -bool SvxAutoCorrectLanguageLists::AddToWrdSttExceptList(const OUString& rNew) +bool SvxAutoCorrectLanguageLists::AddToWordStartExceptList(const OUString& rNew) { bool bRet = false; - SvStringsISortDtor* pExceptList = LoadWrdSttExceptList(); - if( !rNew.isEmpty() && pExceptList && pExceptList->insert( rNew ).second ) + if( !rNew.isEmpty() && GetWordStartExceptList()->insert( rNew ).second ) { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); - SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg ); + SaveExceptList_Imp( *pWordStart_ExcptLst, pXMLImplWordStart_ExcptLstStr, xStg ); xStg = nullptr; // Set time stamp @@ -2428,7 +2521,7 @@ SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadCplSttExceptList() { try { - tools::SvRef<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); + rtl::Reference<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); if( xStg.is() && xStg->IsContained( pXMLImplCplStt_ExcptLstStr ) ) LoadXMLExceptList_Imp( pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); } @@ -2441,7 +2534,7 @@ SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadCplSttExceptList() void SvxAutoCorrectLanguageLists::SaveCplSttExceptList() { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); @@ -2453,27 +2546,27 @@ void SvxAutoCorrectLanguageLists::SaveCplSttExceptList() aLastCheckTime = tools::Time( tools::Time::SYSTEM ); } -SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadWrdSttExceptList() +SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadWordStartExceptList() { try { - tools::SvRef<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); - if( xStg.is() && xStg->IsContained( pXMLImplWrdStt_ExcptLstStr ) ) - LoadXMLExceptList_Imp( pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg ); + rtl::Reference<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); + if( xStg.is() && xStg->IsContained( pXMLImplWordStart_ExcptLstStr ) ) + LoadXMLExceptList_Imp( pWordStart_ExcptLst, pXMLImplWordStart_ExcptLstStr, xStg ); } catch (const css::ucb::ContentCreationException &) { - TOOLS_WARN_EXCEPTION("editeng", "SvxAutoCorrectLanguageLists::LoadWrdSttExceptList"); + TOOLS_WARN_EXCEPTION("editeng", "SvxAutoCorrectLanguageLists::LoadWordStartExceptList"); } - return pWrdStt_ExcptLst.get(); + return pWordStart_ExcptLst.get(); } -void SvxAutoCorrectLanguageLists::SaveWrdSttExceptList() +void SvxAutoCorrectLanguageLists::SaveWordStartExceptList() { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); - SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg ); + SaveExceptList_Imp( *pWordStart_ExcptLst, pXMLImplWordStart_ExcptLstStr, xStg ); xStg = nullptr; // Set time stamp @@ -2482,26 +2575,26 @@ void SvxAutoCorrectLanguageLists::SaveWrdSttExceptList() aLastCheckTime = tools::Time( tools::Time::SYSTEM ); } -SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetWrdSttExceptList() +SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetWordStartExceptList() { - if( !( ACFlags::WrdSttLstLoad & nFlags ) || IsFileChanged_Imp() ) + if( !( ACFlags::WordStartLstLoad & nFlags ) || IsFileChanged_Imp() ) { - LoadWrdSttExceptList(); - if( !pWrdStt_ExcptLst ) + LoadWordStartExceptList(); + if( !pWordStart_ExcptLst ) { OSL_ENSURE( false, "No valid list" ); - pWrdStt_ExcptLst.reset( new SvStringsISortDtor ); + pWordStart_ExcptLst.reset( new SvStringsISortDtor ); } - nFlags |= ACFlags::WrdSttLstLoad; + nFlags |= ACFlags::WordStartLstLoad; } - return pWrdStt_ExcptLst.get(); + return pWordStart_ExcptLst.get(); } void SvxAutoCorrectLanguageLists::RemoveStream_Imp( const OUString& rName ) { if( sShareAutoCorrFile != sUserAutoCorrFile ) { - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); if( xStg.is() && ERRCODE_NONE == xStg->GetError() && xStg->IsStream( rName ) ) { @@ -2563,19 +2656,19 @@ void SvxAutoCorrectLanguageLists::MakeUserStorage_Impl() } if (bConvert && !bError) { - tools::SvRef<SotStorage> xSrcStg = new SotStorage( aDest.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ), StreamMode::READ ); - tools::SvRef<SotStorage> xDstStg = new SotStorage( sUserAutoCorrFile, StreamMode::WRITE ); + rtl::Reference<SotStorage> xSrcStg = new SotStorage( aDest.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ), StreamMode::READ ); + rtl::Reference<SotStorage> xDstStg = new SotStorage(sUserAutoCorrFile, StreamMode::WRITE); if( xSrcStg.is() && xDstStg.is() ) { std::unique_ptr<SvStringsISortDtor> pTmpWordList; - if (xSrcStg->IsContained( pXMLImplWrdStt_ExcptLstStr ) ) - LoadXMLExceptList_Imp( pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xSrcStg ); + if (xSrcStg->IsContained( pXMLImplWordStart_ExcptLstStr ) ) + LoadXMLExceptList_Imp( pTmpWordList, pXMLImplWordStart_ExcptLstStr, xSrcStg ); if (pTmpWordList) { - SaveExceptList_Imp( *pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xDstStg, true ); + SaveExceptList_Imp( *pTmpWordList, pXMLImplWordStart_ExcptLstStr, xDstStg, true ); pTmpWordList.reset(); } @@ -2596,7 +2689,7 @@ void SvxAutoCorrectLanguageLists::MakeUserStorage_Impl() try { ::ucbhelper::Content aContent ( aDest.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ), uno::Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() ); - aContent.executeCommand ( "delete", makeAny ( true ) ); + aContent.executeCommand ( "delete", Any ( true ) ); } catch (...) { @@ -2612,7 +2705,7 @@ bool SvxAutoCorrectLanguageLists::MakeBlocklist_Imp( SotStorage& rStg ) bool bRet = true, bRemove = !pAutocorr_List || pAutocorr_List->empty(); if( !bRemove ) { - tools::SvRef<SotStorageStream> refList = rStg.OpenSotStream( pXMLImplAutocorr_ListStr, + rtl::Reference<SotStorageStream> refList = rStg.OpenSotStream( pXMLImplAutocorr_ListStr, ( StreamMode::READ | StreamMode::WRITE | StreamMode::SHARE_DENYWRITE ) ); if( refList.is() ) { @@ -2663,7 +2756,7 @@ bool SvxAutoCorrectLanguageLists::MakeCombinedChanges( std::vector<SvxAutocorrWo GetAutocorrWordList(); MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStorage = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStorage = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); bool bRet = xStorage.is() && ERRCODE_NONE == xStorage->GetError(); @@ -2732,7 +2825,7 @@ bool SvxAutoCorrectLanguageLists::PutText( const OUString& rShort, const OUStrin GetAutocorrWordList(); MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); bool bRet = xStg.is() && ERRCODE_NONE == xStg->GetError(); @@ -2790,7 +2883,7 @@ void SvxAutoCorrectLanguageLists::PutText( const OUString& rShort, { if( pAutocorr_List->Insert( SvxAutocorrWord(rShort, sLong, false) ) ) { - tools::SvRef<SotStorage> xStor = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStor = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); MakeBlocklist_Imp( *xStor ); } } @@ -2930,7 +3023,7 @@ const SvxAutocorrWordList::AutocorrWordSetType& SvxAutocorrWordList::getSortedCo } const SvxAutocorrWord* SvxAutocorrWordList::WordMatches(const SvxAutocorrWord *pFnd, - const OUString &rTxt, + std::u16string_view rTxt, sal_Int32 &rStt, sal_Int32 nEndPos) const { @@ -2938,119 +3031,119 @@ const SvxAutocorrWord* SvxAutocorrWordList::WordMatches(const SvxAutocorrWord *p sal_Int32 left_wildcard = rChk.startsWith( ".*" ) ? 2 : 0; // ".*word" pattern? sal_Int32 right_wildcard = rChk.endsWith( ".*" ) ? 2 : 0; // "word.*" pattern? - sal_Int32 nSttWdPos = nEndPos; + assert(nEndPos >= 0); + size_t nSttWdPos = nEndPos; // direct replacement of keywords surrounded by colons (for example, ":name:") - bool bColonNameColon = rTxt.getLength() > nEndPos && + bool bColonNameColon = static_cast<sal_Int32>(rTxt.size()) > nEndPos && rTxt[nEndPos] == ':' && rChk[0] == ':' && rChk.endsWith(":"); - if ( nEndPos + (bColonNameColon ? 1 : 0) >= rChk.getLength() - left_wildcard - right_wildcard ) - { + if ( nEndPos + (bColonNameColon ? 1 : 0) < rChk.getLength() - left_wildcard - right_wildcard ) + return nullptr; - bool bWasWordDelim = false; - sal_Int32 nCalcStt = nEndPos - rChk.getLength() + left_wildcard; - if (bColonNameColon) - nCalcStt++; - if( !right_wildcard && ( !nCalcStt || nCalcStt == rStt || left_wildcard || bColonNameColon || - ( nCalcStt < rStt && - IsWordDelim( rTxt[ nCalcStt - 1 ] ))) ) + bool bWasWordDelim = false; + sal_Int32 nCalcStt = nEndPos - rChk.getLength() + left_wildcard; + if (bColonNameColon) + nCalcStt++; + if( !right_wildcard && ( !nCalcStt || nCalcStt == rStt || left_wildcard || bColonNameColon || + ( nCalcStt < rStt && + IsWordDelim( rTxt[ nCalcStt - 1 ] ))) ) + { + TransliterationWrapper& rCmp = GetIgnoreTranslWrapper(); + OUString sWord( rTxt.substr(nCalcStt, rChk.getLength() - left_wildcard) ); + if( (!left_wildcard && rCmp.isEqual( rChk, sWord )) || (left_wildcard && rCmp.isEqual( rChk.copy(left_wildcard), sWord) )) { - TransliterationWrapper& rCmp = GetIgnoreTranslWrapper(); - OUString sWord = rTxt.copy(nCalcStt, rChk.getLength() - left_wildcard); - if( (!left_wildcard && rCmp.isEqual( rChk, sWord )) || (left_wildcard && rCmp.isEqual( rChk.copy(left_wildcard), sWord) )) + rStt = nCalcStt; + if (!left_wildcard) { - rStt = nCalcStt; - if (!left_wildcard) - { - // fdo#33899 avoid "1/2", "1/3".. to be replaced by fractions in dates, eg. 1/2/14 - if (rTxt.getLength() > nEndPos && rTxt[nEndPos] == '/' && rChk.indexOf('/') != -1) - return nullptr; - return pFnd; - } - // get the first word delimiter position before the matching ".*word" pattern - while( rStt && !(bWasWordDelim = IsWordDelim( rTxt[ --rStt ]))) - ; - if (bWasWordDelim) rStt++; - OUString left_pattern = rTxt.copy(rStt, nEndPos - rStt - rChk.getLength() + left_wildcard); - // avoid double spaces before simple "word" replacement - left_pattern += (left_pattern.getLength() == 0 && pFnd->GetLong()[0] == 0x20) ? pFnd->GetLong().copy(1) : pFnd->GetLong(); - if( const SvxAutocorrWord* pNew = Insert( SvxAutocorrWord(rTxt.copy(rStt, nEndPos - rStt), left_pattern) ) ) - return pNew; + // fdo#33899 avoid "1/2", "1/3".. to be replaced by fractions in dates, eg. 1/2/14 + if (static_cast<sal_Int32>(rTxt.size()) > nEndPos && rTxt[nEndPos] == '/' && rChk.indexOf('/') != -1) + return nullptr; + return pFnd; } - } else - // match "word.*" or ".*word.*" patterns, eg. "i18n.*", ".*---.*", TODO: add transliteration support - if ( right_wildcard ) - { + // get the first word delimiter position before the matching ".*word" pattern + while( rStt && !(bWasWordDelim = IsWordDelim( rTxt[ --rStt ]))) + ; + if (bWasWordDelim) rStt++; + OUString left_pattern( rTxt.substr(rStt, nEndPos - rStt - rChk.getLength() + left_wildcard) ); + // avoid double spaces before simple "word" replacement + left_pattern += (left_pattern.getLength() == 0 && pFnd->GetLong()[0] == 0x20) ? pFnd->GetLong().subView(1) : pFnd->GetLong(); + if( const SvxAutocorrWord* pNew = Insert( SvxAutocorrWord(OUString(rTxt.substr(rStt, nEndPos - rStt)), left_pattern) ) ) + return pNew; + } + } else + // match "word.*" or ".*word.*" patterns, eg. "i18n.*", ".*---.*", TODO: add transliteration support + if ( right_wildcard ) + { - OUString sTmp( rChk.copy( left_wildcard, rChk.getLength() - left_wildcard - right_wildcard ) ); - // Get the last word delimiter position - bool not_suffix; + OUString sTmp( rChk.copy( left_wildcard, rChk.getLength() - left_wildcard - right_wildcard ) ); + // Get the last word delimiter position + bool not_suffix; - while( nSttWdPos && !(bWasWordDelim = IsWordDelim( rTxt[ --nSttWdPos ]))) - ; - // search the first occurrence (with a left word delimitation, if needed) - sal_Int32 nFndPos = -1; - do { - nFndPos = rTxt.indexOf( sTmp, nFndPos + 1); - if (nFndPos == -1) - break; - not_suffix = bWasWordDelim && (nSttWdPos >= (nFndPos + sTmp.getLength())); - } while ( (!left_wildcard && nFndPos && !IsWordDelim( rTxt[ nFndPos - 1 ])) || not_suffix ); + while( nSttWdPos && !(bWasWordDelim = IsWordDelim( rTxt[ --nSttWdPos ]))) + ; + // search the first occurrence (with a left word delimitation, if needed) + size_t nFndPos = std::u16string_view::npos; + do { + nFndPos = rTxt.find( sTmp, nFndPos + 1); + if (nFndPos == std::u16string_view::npos) + break; + not_suffix = bWasWordDelim && (nSttWdPos >= (nFndPos + sTmp.getLength())); + } while ( (!left_wildcard && nFndPos && !IsWordDelim( rTxt[ nFndPos - 1 ])) || not_suffix ); - if ( nFndPos != -1 ) - { - sal_Int32 extra_repl = nFndPos + sTmp.getLength() > nEndPos ? 1: 0; // for patterns with terminating characters, eg. "a:" + if ( nFndPos != std::u16string_view::npos ) + { + sal_Int32 extra_repl = static_cast<sal_Int32>(nFndPos) + sTmp.getLength() > nEndPos ? 1: 0; // for patterns with terminating characters, eg. "a:" - if ( left_wildcard ) - { - // get the first word delimiter position before the matching ".*word.*" pattern - while( nFndPos && !(bWasWordDelim = IsWordDelim( rTxt[ --nFndPos ]))) - ; - if (bWasWordDelim) nFndPos++; - } - if (nEndPos + extra_repl <= nFndPos) - { - return nullptr; - } - // store matching pattern and its replacement as a new list item, eg. "i18ns" -> "internationalizations" - OUString aShort = rTxt.copy(nFndPos, nEndPos - nFndPos + extra_repl); + if ( left_wildcard ) + { + // get the first word delimiter position before the matching ".*word.*" pattern + while( nFndPos && !(bWasWordDelim = IsWordDelim( rTxt[ --nFndPos ]))) + ; + if (bWasWordDelim) nFndPos++; + } + if (nEndPos + extra_repl <= static_cast<sal_Int32>(nFndPos)) + { + return nullptr; + } + // store matching pattern and its replacement as a new list item, eg. "i18ns" -> "internationalizations" + OUString aShort( rTxt.substr(nFndPos, nEndPos - nFndPos + extra_repl) ); - OUString aLong; - rStt = nFndPos; - if ( !left_wildcard ) - { - sal_Int32 siz = nEndPos - nFndPos - sTmp.getLength(); - aLong = pFnd->GetLong() + (siz > 0 ? rTxt.copy(nFndPos + sTmp.getLength(), siz) : ""); - } else { - OUStringBuffer buf; - do { - nSttWdPos = rTxt.indexOf( sTmp, nFndPos); - if (nSttWdPos != -1) - { - sal_Int32 nTmp(nFndPos); - while (nTmp < nSttWdPos && !IsWordDelim(rTxt[nTmp])) - nTmp++; - if (nTmp < nSttWdPos) - break; // word delimiter found - buf.append(rTxt.subView(nFndPos, nSttWdPos - nFndPos)).append(pFnd->GetLong()); - nFndPos = nSttWdPos + sTmp.getLength(); - } - } while (nSttWdPos != -1); - if (nEndPos - nFndPos > extra_repl) - buf.append(rTxt.subView(nFndPos, nEndPos - nFndPos)); - aLong = buf.makeStringAndClear(); - } - if ( const SvxAutocorrWord* pNew = Insert( SvxAutocorrWord(aShort, aLong) ) ) - { - if ( (rTxt.getLength() > nEndPos && IsWordDelim(rTxt[nEndPos])) || rTxt.getLength() == nEndPos ) - return pNew; - } + OUString aLong; + rStt = nFndPos; + if ( !left_wildcard ) + { + sal_Int32 siz = nEndPos - nFndPos - sTmp.getLength(); + aLong = pFnd->GetLong() + (siz > 0 ? rTxt.substr(nFndPos + sTmp.getLength(), siz) : u""); + } else { + OUStringBuffer buf; + do { + nSttWdPos = rTxt.find( sTmp, nFndPos); + if (nSttWdPos != std::u16string_view::npos) + { + sal_Int32 nTmp(nFndPos); + while (nTmp < static_cast<sal_Int32>(nSttWdPos) && !IsWordDelim(rTxt[nTmp])) + nTmp++; + if (nTmp < static_cast<sal_Int32>(nSttWdPos)) + break; // word delimiter found + buf.append(rTxt.substr(nFndPos, nSttWdPos - nFndPos)).append(pFnd->GetLong()); + nFndPos = nSttWdPos + sTmp.getLength(); + } + } while (nSttWdPos != std::u16string_view::npos); + if (static_cast<sal_Int32>(nEndPos - nFndPos) > extra_repl) + buf.append(rTxt.substr(nFndPos, nEndPos - nFndPos)); + aLong = buf.makeStringAndClear(); + } + if ( const SvxAutocorrWord* pNew = Insert( SvxAutocorrWord(aShort, aLong) ) ) + { + if ( (static_cast<sal_Int32>(rTxt.size()) > nEndPos && IsWordDelim(rTxt[nEndPos])) || static_cast<sal_Int32>(rTxt.size()) == nEndPos ) + return pNew; } } } return nullptr; } -const SvxAutocorrWord* SvxAutocorrWordList::SearchWordsInList(const OUString& rTxt, sal_Int32& rStt, +const SvxAutocorrWord* SvxAutocorrWordList::SearchWordsInList(std::u16string_view rTxt, sal_Int32& rStt, sal_Int32 nEndPos) const { for (auto const& elem : mpImpl->maHash) diff --git a/editeng/source/misc/swafopt.cxx b/editeng/source/misc/swafopt.cxx index 126a54bb1f90..25f3b1b466cc 100644 --- a/editeng/source/misc/swafopt.cxx +++ b/editeng/source/misc/swafopt.cxx @@ -22,12 +22,11 @@ #include <vcl/keycodes.hxx> SvxSwAutoFormatFlags::SvxSwAutoFormatFlags() - : aBulletFont( "StarSymbol", Size( 0, 14 ) ) + : aBulletFont( "OpenSymbol", Size( 0, 14 ) ) { bAutoCorrect = bCapitalStartSentence = bCapitalStartWord = - bChgUserColl = bChgEnumNum = bAddNonBrkSpace = bChgOrdinalNumber = @@ -36,15 +35,18 @@ SvxSwAutoFormatFlags::SvxSwAutoFormatFlags() bChgToEnEmDash = bChgWeightUnderl = bSetINetAttr = + bSetDOIAttr = bAFormatDelSpacesAtSttEnd = bAFormatDelSpacesBetweenLines = bAFormatByInpDelSpacesAtSttEnd = bAFormatByInpDelSpacesBetweenLines = true; + bChgUserColl = bReplaceStyles = bDelEmptyNode = bWithRedlining = bAutoCmpltEndless = + bSetNumRuleAfterSpace = bAutoCmpltAppendBlank = false; bAutoCmpltShowAsTip = diff --git a/editeng/source/misc/txtrange.cxx b/editeng/source/misc/txtrange.cxx index b8c46e0cdcba..2f02a1150f91 100644 --- a/editeng/source/misc/txtrange.cxx +++ b/editeng/source/misc/txtrange.cxx @@ -54,7 +54,7 @@ TextRanger::TextRanger( const basegfx::B2DPolyPolygon& rPolyPolygon, if( pLinePolyPolygon ) { nCount = pLinePolyPolygon->count(); - mpLinePolyPolygon.reset( new tools::PolyPolygon() ); + mpLinePolyPolygon = tools::PolyPolygon(nCount); for(sal_uInt32 i(0); i < nCount; i++) { @@ -64,7 +64,7 @@ TextRanger::TextRanger( const basegfx::B2DPolyPolygon& rPolyPolygon, } } else - mpLinePolyPolygon = nullptr; + mpLinePolyPolygon.reset(); } @@ -192,9 +192,13 @@ tools::Long SvxBoundArgs::CalcMax( const Point& rPt1, const Point& rPt2, } else nB = nStart; - nB *= nB; - nB += nDa * nDa; - nB = nRange + nDa * ( nFarRange - nRange ) / sqrt( nB ); + + nB = std::hypot(nB, nDa); + + if (nB == 0) // avoid div / 0 + return 0; + + nB = nRange + nDa * ( nFarRange - nRange ) / nB; bool bNote; if( nB < B(rPt2) ) @@ -644,7 +648,7 @@ std::deque<tools::Long>* TextRanger::GetTextRanges( const Range& rRange ) SvxBoundArgs aArg( this, &(rngCache.results), rRange ); aArg.Calc( maPolyPolygon ); if( mpLinePolyPolygon ) - aArg.Concat( mpLinePolyPolygon.get() ); + aArg.Concat( &*mpLinePolyPolygon ); //Add new result to the cache mRangeCache.push_back(std::move(rngCache)); if (mRangeCache.size() > nCacheSize) diff --git a/editeng/source/misc/unolingu.cxx b/editeng/source/misc/unolingu.cxx index b72fae9ebb67..e252dc3233e6 100644 --- a/editeng/source/misc/unolingu.cxx +++ b/editeng/source/misc/unolingu.cxx @@ -29,10 +29,12 @@ #include <com/sun/star/linguistic2/LinguProperties.hpp> #include <com/sun/star/linguistic2/XSpellChecker1.hpp> +#include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> #include <cppuhelper/implbase.hxx> #include <i18nlangtag/languagetag.hxx> #include <unotools/lingucfg.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <vcl/weld.hxx> #include <linguistic/misc.hxx> @@ -46,7 +48,6 @@ using namespace ::comphelper; using namespace ::linguistic; using namespace ::com::sun::star; -using namespace ::com::sun::star::util; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; @@ -594,7 +595,10 @@ uno::Reference< XDictionary > LinguMgr::GetIgnoreAll() uno::Reference< XSearchableDictionaryList > xTmpDicList( GetDictionaryList() ); if (xTmpDicList.is()) { - std::locale loc(Translate::Create("svt")); + const LanguageTag tag = comphelper::LibreOfficeKit::isActive() + ? LanguageTag("en-US") + : SvtSysLocale().GetUILanguageTag(); + std::locale loc(Translate::Create("svt", tag)); xIgnoreAll = xTmpDicList->getDictionaryByName( Translate::get(STR_DESCRIPTION_IGNOREALLLIST, loc) ); } @@ -632,7 +636,7 @@ uno::Reference< XDictionary > LinguMgr::GetStandard() if (!xTmpDicList.is()) return nullptr; - static const OUStringLiteral aDicName( u"standard.dic" ); + static constexpr OUString aDicName( u"standard.dic"_ustr ); uno::Reference< XDictionary > xDic = xTmpDicList->getDictionaryByName( aDicName ); if (!xDic.is()) { @@ -709,8 +713,8 @@ SvxAlternativeSpelling SvxGetAltSpelling( } -SvxDicListChgClamp::SvxDicListChgClamp( uno::Reference< XSearchableDictionaryList > const &rxDicList ) : - xDicList ( rxDicList ) +SvxDicListChgClamp::SvxDicListChgClamp( uno::Reference< XSearchableDictionaryList > _xDicList ) : + xDicList (std::move( _xDicList )) { if (xDicList.is()) { @@ -731,7 +735,7 @@ short SvxDicError(weld::Window *pParent, linguistic::DictionaryError nError) short nRes = 0; if (linguistic::DictionaryError::NONE != nError) { - const char* pRid; + TranslateId pRid; switch (nError) { case linguistic::DictionaryError::FULL : pRid = RID_SVXSTR_DIC_ERR_FULL; break; diff --git a/editeng/source/misc/urlfieldhelper.cxx b/editeng/source/misc/urlfieldhelper.cxx index 564bc54e781e..16303c064d50 100644 --- a/editeng/source/misc/urlfieldhelper.cxx +++ b/editeng/source/misc/urlfieldhelper.cxx @@ -16,16 +16,17 @@ void URLFieldHelper::RemoveURLField(EditView& pEditView) { pEditView.SelectFieldAtCursor(); - const SvxFieldData* pField = pEditView.GetFieldAtCursor(); + const SvxFieldItem* pFieldItem = pEditView.GetFieldAtSelection(); + const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr; if (auto pUrlField = dynamic_cast<const SvxURLField*>(pField)) { ESelection aSel = pEditView.GetSelection(); - pEditView.GetEditEngine()->QuickInsertText(pUrlField->GetRepresentation(), aSel); + pEditView.getEditEngine().QuickInsertText(pUrlField->GetRepresentation(), aSel); pEditView.Invalidate(); } } -bool URLFieldHelper::IsCursorAtURLField(const EditView& pEditView) +bool URLFieldHelper::IsCursorAtURLField(const EditView& pEditView, bool bAlsoCheckBeforeCursor) { // tdf#128666 Make sure only URL field (or nothing) is selected ESelection aSel = pEditView.GetSelection(); @@ -37,7 +38,8 @@ bool URLFieldHelper::IsCursorAtURLField(const EditView& pEditView) if (!bIsValidSelection) return false; - const SvxFieldData* pField = pEditView.GetFieldAtCursor(); + const SvxFieldData* pField + = pEditView.GetFieldUnderMouseOrInSelectionOrAtCursor(bAlsoCheckBeforeCursor); if (dynamic_cast<const SvxURLField*>(pField)) return true; diff --git a/editeng/source/outliner/outleeng.cxx b/editeng/source/outliner/outleeng.cxx index d9e1d0595a11..1136ef37b9e2 100644 --- a/editeng/source/outliner/outleeng.cxx +++ b/editeng/source/outliner/outleeng.cxx @@ -21,9 +21,10 @@ #include <editeng/eerdll.hxx> #include <editeng/outliner.hxx> -#include "outleeng.hxx" +#include <outleeng.hxx> #include "paralist.hxx" #include <editeng/editrids.hrc> +#include <optional> #include <svl/itemset.hxx> #include <editeng/editstat.hxx> #include "outlundo.hxx" @@ -69,6 +70,15 @@ tools::Rectangle OutlinerEditEng::GetBulletArea( sal_Int32 nPara ) return aBulletArea; } +std::optional<bool> OutlinerEditEng::GetCompatFlag(SdrCompatibilityFlag eFlag) const +{ + if(pOwner) + { + return pOwner->GetCompatFlag(eFlag); + } + return {}; +} + void OutlinerEditEng::ParagraphInserted( sal_Int32 nNewParagraph ) { pOwner->ParagraphInserted( nNewParagraph ); @@ -141,7 +151,8 @@ OUString OutlinerEditEng::GetUndoComment( sal_uInt16 nUndoId ) const } void OutlinerEditEng::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart, sal_Int32 nTextLen, - const tools::Long* pDXArray, const SvxFont& rFont, sal_Int32 nPara, sal_uInt8 nRightToLeft, + std::span<const sal_Int32> pDXArray, std::span<const sal_Bool> pKashidaArray, + const SvxFont& rFont, sal_Int32 nPara, sal_uInt8 nRightToLeft, const EEngineData::WrongSpellVector* pWrongSpellVector, const SvxFieldData* pFieldData, bool bEndOfLine, @@ -150,7 +161,7 @@ void OutlinerEditEng::DrawingText( const Point& rStartPos, const OUString& rText const Color& rOverlineColor, const Color& rTextLineColor) { - pOwner->DrawingText(rStartPos,rText,nTextStart,nTextLen,pDXArray,rFont,nPara,nRightToLeft, + pOwner->DrawingText(rStartPos,rText,nTextStart,nTextLen,pDXArray,pKashidaArray,rFont,nPara,nRightToLeft, pWrongSpellVector, pFieldData, bEndOfLine, bEndOfParagraph, false/*bEndOfBullet*/, pLocale, rOverlineColor, rTextLineColor); } @@ -163,9 +174,9 @@ void OutlinerEditEng::DrawingTab( const Point& rStartPos, tools::Long nWidth, co bEndOfLine, bEndOfParagraph, rOverlineColor, rTextLineColor ); } -OUString OutlinerEditEng::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor ) +OUString OutlinerEditEng::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle ) { - return pOwner->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor ); + return pOwner->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle ); } void OutlinerEditEng::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) diff --git a/editeng/source/outliner/outleeng.hxx b/editeng/source/outliner/outleeng.hxx deleted file mode 100644 index dcff4b9f8be0..000000000000 --- a/editeng/source/outliner/outleeng.hxx +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- 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/outliner.hxx> -#include <editeng/editeng.hxx> - -typedef std::vector<EENotify> NotifyList; - -class OutlinerEditEng : public EditEngine -{ - Outliner* pOwner; - -protected: - - // derived from EditEngine. Allows Outliner objects to provide - // bullet access to the EditEngine. - virtual const SvxNumberFormat* GetNumberFormat( sal_Int32 nPara ) const override; - -public: - OutlinerEditEng( Outliner* pOwner, SfxItemPool* pPool ); - virtual ~OutlinerEditEng() override; - - virtual void PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev) override; - - virtual void ParagraphInserted( sal_Int32 nNewParagraph ) override; - virtual void ParagraphDeleted( sal_Int32 nDeletedParagraph ) override; - virtual void ParagraphConnected( sal_Int32 nLeftParagraph, sal_Int32 nRightParagraph ) override; - - virtual void DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart, - sal_Int32 nTextLen, const tools::Long* pDXArray, const SvxFont& rFont, - sal_Int32 nPara, sal_uInt8 nRightToLeft, - const EEngineData::WrongSpellVector* pWrongSpellVector, - const SvxFieldData* pFieldData, - bool bEndOfLine, - bool bEndOfParagraph, - const css::lang::Locale* pLocale, - const Color& rOverlineColor, - const Color& rTextLineColor) override; - - virtual void DrawingTab( - const Point& rStartPos, tools::Long nWidth, const OUString& rChar, - const SvxFont& rFont, sal_Int32 nPara, sal_uInt8 nRightToLeft, - bool bEndOfLine, - bool bEndOfParagraph, - const Color& rOverlineColor, - const Color& rTextLineColor) override; - - virtual void StyleSheetChanged( SfxStyleSheet* pStyle ) override; - virtual void ParaAttribsChanged( sal_Int32 nPara ) override; - virtual bool SpellNextDocument() override; - virtual OUString GetUndoComment( sal_uInt16 nUndoId ) const override; - - // for text conversion - virtual bool ConvertNextDocument() override; - - virtual OUString CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rTxtColor, std::optional<Color>& rFldColor ) override; - - virtual tools::Rectangle GetBulletArea( sal_Int32 nPara ) override; - - virtual void SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) override; - - // belongs into class Outliner, move there before incompatible update! - Link<EENotify&,void> aOutlinerNotifyHdl; - NotifyList aNotifyCache; -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/outliner/outlin2.cxx b/editeng/source/outliner/outlin2.cxx index 789d5d54e061..ccd07199a60f 100644 --- a/editeng/source/outliner/outlin2.cxx +++ b/editeng/source/outliner/outlin2.cxx @@ -30,7 +30,7 @@ #include <editeng/outliner.hxx> #include "paralist.hxx" -#include "outleeng.hxx" +#include <outleeng.hxx> #include <editeng/editstat.hxx> @@ -41,15 +41,15 @@ using namespace ::com::sun::star::linguistic2; // ====================== Simple pass-through ======================= -void Outliner::SetUpdateMode( bool bUpdate ) +bool Outliner::SetUpdateLayout( bool bUpdate ) { - pEditEngine->SetUpdateMode( bUpdate ); + return pEditEngine->SetUpdateLayout( bUpdate ); } -bool Outliner::GetUpdateMode() const +bool Outliner::IsUpdateLayout() const { - return pEditEngine->GetUpdateMode(); + return pEditEngine->IsUpdateLayout(); } const SfxItemSet& Outliner::GetEmptyItemSet() const @@ -108,11 +108,6 @@ void Outliner::SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) pEditEngine->SetModifyHdl( rLink ); } -Link<LinkParamNone*,void> const & Outliner::GetModifyHdl() const -{ - return pEditEngine->GetModifyHdl(); -} - void Outliner::SetNotifyHdl( const Link<EENotify&,void>& rLink ) { pEditEngine->aOutlinerNotifyHdl = rLink; @@ -248,11 +243,6 @@ Size Outliner::CalcTextSize() return Size(pEditEngine->CalcTextWidth(),pEditEngine->GetTextHeight()); } -Size Outliner::CalcTextSizeNTP() -{ - return Size(pEditEngine->CalcTextWidth(),pEditEngine->GetTextHeightNTP()); -} - void Outliner::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) { pEditEngine->SetStyleSheetPool( pSPool ); @@ -436,7 +426,7 @@ bool Outliner::IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder, bool* pbBu if ( ( nPara != EE_PARA_NOT_FOUND ) && ImplHasNumberFormat( nPara ) ) { tools::Rectangle aBulArea = ImpCalcBulletArea( nPara, true, true ); - if ( aBulArea.IsInside( rPaperPos ) ) + if ( aBulArea.Contains( rPaperPos ) ) { bTextPos = true; if ( pbBullet) @@ -482,9 +472,13 @@ void Outliner::QuickFormatDoc() pEditEngine->QuickFormatDoc(); } -void Outliner::SetGlobalCharStretching( sal_uInt16 nX, sal_uInt16 nY ) +ScalingParameters Outliner::getScalingParameters() const { + return pEditEngine->getScalingParameters(); +} +void Outliner::setScalingParameters(ScalingParameters const& rScalingParameters) +{ // reset bullet size sal_Int32 nParagraphs = pParaList->GetParagraphCount(); for ( sal_Int32 nPara = 0; nPara < nParagraphs; nPara++ ) @@ -494,12 +488,12 @@ void Outliner::SetGlobalCharStretching( sal_uInt16 nX, sal_uInt16 nY ) pPara->aBulSize.setWidth( -1 ); } - pEditEngine->SetGlobalCharStretching( nX, nY ); + pEditEngine->setScalingParameters(rScalingParameters); } -void Outliner::GetGlobalCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const +void Outliner::setRoundFontSizeToPt(bool bRound) const { - pEditEngine->GetGlobalCharStretching( rX, rY ); + pEditEngine->setRoundFontSizeToPt(bRound); } void Outliner::EraseVirtualDevice() @@ -529,7 +523,7 @@ void Outliner::SetRotation(TextRotation nRotation) bool Outliner::IsVertical() const { - return pEditEngine->IsVertical(); + return pEditEngine->IsEffectivelyVertical(); } bool Outliner::IsTopToBottom() const @@ -559,7 +553,7 @@ EEHorizontalTextDirection Outliner::GetDefaultHorizontalTextDirection() const LanguageType Outliner::GetLanguage( sal_Int32 nPara, sal_Int32 nPos ) const { - return pEditEngine->GetLanguage( nPara, nPos ); + return pEditEngine->GetLanguage( nPara, nPos ).nLang; } void Outliner::RemoveAttribs( const ESelection& rSelection, bool bRemoveParaAttribs, sal_uInt16 nWhich ) diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index 9c474131352c..671ecd017cfd 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -30,7 +30,7 @@ #include <editeng/outliner.hxx> #include "paralist.hxx" #include <editeng/outlobj.hxx> -#include "outleeng.hxx" +#include <outleeng.hxx> #include "outlundo.hxx" #include <editeng/eeitem.hxx> #include <editeng/editstat.hxx> @@ -40,7 +40,6 @@ #include <vcl/metric.hxx> #include <editeng/numitem.hxx> #include <editeng/adjustitem.hxx> -#include <vcl/window.hxx> #include <vcl/GraphicObject.hxx> #include <editeng/svxfont.hxx> #include <editeng/brushitem.hxx> @@ -48,6 +47,8 @@ #include <libxml/xmlwriter.h> #include <sal/log.hxx> #include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <o3tl/temporary.hxx> #include <osl/diagnose.h> #include <memory> @@ -92,8 +93,7 @@ Paragraph* Outliner::Insert(const OUString& rText, sal_Int32 nAbsPos, sal_Int16 } else { - bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + bool bUpdate = pEditEngine->SetUpdateLayout( false ); ImplBlockInsertionCallbacks( true ); pPara = new Paragraph( nDepth ); pParaList->Insert( std::unique_ptr<Paragraph>(pPara), nAbsPos ); @@ -104,7 +104,7 @@ Paragraph* Outliner::Insert(const OUString& rText, sal_Int32 nAbsPos, sal_Int16 pPara->nFlags |= ParaFlag::HOLDDEPTH; SetText( rText, pPara ); ImplBlockInsertionCallbacks( false ); - pEditEngine->SetUpdateMode( bUpdate ); + pEditEngine->SetUpdateLayout( bUpdate ); } bFirstParaIsEmpty = false; DBG_ASSERT(pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(),"SetText failed"); @@ -124,7 +124,6 @@ void Outliner::ParagraphInserted( sal_Int32 nPara ) pParaList->Insert( std::unique_ptr<Paragraph>(pPara), nPara ); if( pEditEngine->IsInUndo() ) { - pPara->nFlags = ParaFlag::SETBULLETTEXT; pPara->bVisible = true; const SfxInt16Item& rLevel = pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); pPara->SetDepth( rLevel.GetValue() ); @@ -194,7 +193,7 @@ void Outliner::Init( OutlinerMode nMode ) SetMaxDepth( 9 ); - switch ( ImplGetOutlinerMode() ) + switch ( GetOutlinerMode() ) { case OutlinerMode::TextObject: case OutlinerMode::TitleObject: @@ -249,13 +248,13 @@ void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth ) ImplInitDepth( nPara, nNewDepth, true ); ImplCalcBulletText( nPara, false, false ); - if ( ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) + if ( GetOutlinerMode() == OutlinerMode::OutlineObject ) ImplSetLevelDependentStyleSheet( nPara ); DepthChangedHdl(pPara, nPrevFlags); } -sal_Int16 Outliner::GetNumberingStartValue( sal_Int32 nPara ) +sal_Int16 Outliner::GetNumberingStartValue( sal_Int32 nPara ) const { Paragraph* pPara = pParaList->GetParagraph( nPara ); DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" ); @@ -279,7 +278,7 @@ void Outliner::SetNumberingStartValue( sal_Int32 nPara, sal_Int16 nNumberingStar } } -bool Outliner::IsParaIsNumberingRestart( sal_Int32 nPara ) +bool Outliner::IsParaIsNumberingRestart( sal_Int32 nPara ) const { Paragraph* pPara = pParaList->GetParagraph( nPara ); DBG_ASSERT( pPara, "Outliner::IsParaIsNumberingRestart - Paragraph not found!" ); @@ -359,9 +358,9 @@ sal_Int32 Outliner::GetBulletsNumberingStatus() const : 2; } -std::unique_ptr<OutlinerParaObject> Outliner::CreateParaObject( sal_Int32 nStartPara, sal_Int32 nCount ) const +std::optional<OutlinerParaObject> Outliner::CreateParaObject( sal_Int32 nStartPara, sal_Int32 nCount ) const { - if ( static_cast<sal_uLong>(nStartPara) + nCount > + if ( static_cast<sal_uInt64>(nStartPara) + nCount > o3tl::make_unsigned(pParaList->GetParagraphCount()) ) nCount = pParaList->GetParagraphCount() - nStartPara; @@ -371,10 +370,10 @@ std::unique_ptr<OutlinerParaObject> Outliner::CreateParaObject( sal_Int32 nStart nCount = pEditEngine->GetParagraphCount() - nStartPara; if (nCount <= 0) - return nullptr; + return std::nullopt; std::unique_ptr<EditTextObject> xText = pEditEngine->CreateTextObject( nStartPara, nCount ); - const bool bIsEditDoc(OutlinerMode::TextObject == ImplGetOutlinerMode()); + const bool bIsEditDoc(OutlinerMode::TextObject == GetOutlinerMode()); ParagraphDataVector aParagraphDataVector(nCount); const sal_Int32 nLastPara(nStartPara + nCount - 1); @@ -383,16 +382,16 @@ std::unique_ptr<OutlinerParaObject> Outliner::CreateParaObject( sal_Int32 nStart aParagraphDataVector[nPara-nStartPara] = *GetParagraph(nPara); } - std::unique_ptr<OutlinerParaObject> pPObj(new OutlinerParaObject(std::move(xText), aParagraphDataVector, bIsEditDoc)); - pPObj->SetOutlinerMode(GetMode()); + xText->ClearPortionInfo(); // tdf#147166 the PortionInfo is unwanted here + OutlinerParaObject aPObj(std::move(xText), std::move(aParagraphDataVector), bIsEditDoc); + aPObj.SetOutlinerMode(GetOutlinerMode()); - return pPObj; + return aPObj; } void Outliner::SetToEmptyText() { - std::unique_ptr<OutlinerParaObject> pEmptyTxt = GetEmptyParaObject(); - SetText(*pEmptyTxt); + SetText(GetEmptyParaObject()); } void Outliner::SetText( const OUString& rText, Paragraph* pPara ) @@ -408,8 +407,7 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) return; } - const bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + const bool bUpdate = pEditEngine->SetUpdateLayout( false ); ImplBlockInsertionCallbacks( true ); if (rText.isEmpty()) @@ -430,7 +428,7 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) // handle empty strings. while( nIdx>=0 && nIdx<aText.getLength() ) { - OUString aStr = aText.getToken( 0, '\x0A', nIdx ); + std::u16string_view aStr = o3tl::getToken(aText, 0, '\x0A', nIdx ); sal_Int16 nCurDepth; if( nPos ) @@ -443,15 +441,15 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) // In the outliner mode, filter the tabs and set the indentation // about a LRSpaceItem. In EditEngine mode intend over old tabs - if( ( ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) || - ( ImplGetOutlinerMode() == OutlinerMode::OutlineView ) ) + if( ( GetOutlinerMode() == OutlinerMode::OutlineObject ) || + ( GetOutlinerMode() == OutlinerMode::OutlineView ) ) { // Extract Tabs - sal_Int32 nTabs = 0; - while ( ( nTabs < aStr.getLength() ) && ( aStr[nTabs] == '\t' ) ) + size_t nTabs = 0; + while ( ( nTabs < aStr.size() ) && ( aStr[nTabs] == '\t' ) ) nTabs++; if ( nTabs ) - aStr = aStr.copy(nTabs); + aStr = aStr.substr(nTabs); // Keep depth? (see Outliner::Insert) if( !(pPara->nFlags & ParaFlag::HOLDDEPTH) ) @@ -459,19 +457,18 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) nCurDepth = nTabs-1; //TODO: sal_Int32 -> sal_Int16! ImplCheckDepth( nCurDepth ); pPara->SetDepth( nCurDepth ); - pPara->nFlags &= ~ParaFlag::HOLDDEPTH; } } if( nPos ) // not with the first paragraph { pParaList->Insert( std::unique_ptr<Paragraph>(pPara), nInsPos ); - pEditEngine->InsertParagraph( nInsPos, aStr ); + pEditEngine->InsertParagraph( nInsPos, OUString(aStr) ); ParagraphInsertedHdl(pPara); } else { nInsPos--; - pEditEngine->SetText( nInsPos, aStr ); + pEditEngine->SetText( nInsPos, OUString(aStr) ); } ImplInitDepth( nInsPos, nCurDepth, false ); nInsPos++; @@ -483,7 +480,7 @@ void Outliner::SetText( const OUString& rText, Paragraph* pPara ) bFirstParaIsEmpty = false; ImplBlockInsertionCallbacks( false ); // Restore the update mode. - pEditEngine->SetUpdateMode(bUpdate, /*bRestoring=*/true); + pEditEngine->SetUpdateLayout(bUpdate, /*bRestoring=*/true); } // pView == 0 -> Ignore tabs @@ -526,8 +523,8 @@ bool Outliner::ImpConvertEdtToOut( sal_Int32 nPara ) } sal_Int32 nPos = nHeadingNumberStart ? nHeadingNumberStart : nNumberingNumberStart; - OUString aLevel = comphelper::string::stripStart(aName.subView(nPos), ' '); - nTabs = aLevel.toInt32(); + std::u16string_view aLevel = comphelper::string::stripStart(aName.subView(nPos), ' '); + nTabs = o3tl::toInt32(aLevel); if( nTabs ) nTabs--; // Level 0 = "heading 1" bConverted = true; @@ -561,9 +558,7 @@ bool Outliner::ImpConvertEdtToOut( sal_Int32 nPara ) void Outliner::SetText( const OutlinerParaObject& rPObj ) { - - bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + bool bUpdate = pEditEngine->SetUpdateLayout( false ); bool bUndo = pEditEngine->IsUndoEnabled(); EnableUndo( false ); @@ -589,7 +584,7 @@ void Outliner::SetText( const OutlinerParaObject& rPObj ) EnableUndo( bUndo ); ImplBlockInsertionCallbacks( false ); - pEditEngine->SetUpdateMode( bUpdate ); + pEditEngine->SetUpdateLayout( bUpdate ); DBG_ASSERT( pParaList->GetParagraphCount()==rPObj.Count(),"SetText failed"); DBG_ASSERT( pEditEngine->GetParagraphCount()==rPObj.Count(),"SetText failed"); @@ -597,9 +592,7 @@ void Outliner::SetText( const OutlinerParaObject& rPObj ) void Outliner::AddText( const OutlinerParaObject& rPObj, bool bAppend ) { - - bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + bool bUpdate = pEditEngine->SetUpdateLayout( false ); ImplBlockInsertionCallbacks( true ); sal_Int32 nPara; @@ -638,10 +631,10 @@ void Outliner::AddText( const OutlinerParaObject& rPObj, bool bAppend ) ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() ); ImplBlockInsertionCallbacks( false ); - pEditEngine->SetUpdateMode( bUpdate ); + pEditEngine->SetUpdateLayout( bUpdate ); } -OUString Outliner::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor ) +OUString Outliner::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle ) { if ( !aCalcFieldValueHdl.IsSet() ) return OUString( ' ' ); @@ -657,6 +650,11 @@ OUString Outliner::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, rpTxtColor = *aFldInfo.GetTextColor(); } + if ( aFldInfo.GetFontLineStyle() ) + { + rpFldLineStyle = *aFldInfo.GetFontLineStyle(); + } + if (aFldInfo.GetFieldColor()) rpFldColor = *aFldInfo.GetFieldColor(); else @@ -671,7 +669,6 @@ void Outliner::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ) if (pPara) { pEditEngine->SetStyleSheet( nPara, pStyle ); - pPara->nFlags |= ParaFlag::SETBULLETTEXT; ImplCheckNumBulletItem( nPara ); } } @@ -686,7 +683,7 @@ void Outliner::ImplCheckNumBulletItem( sal_Int32 nPara ) void Outliner::ImplSetLevelDependentStyleSheet( sal_Int32 nPara ) { - DBG_ASSERT( ( ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) || ( ImplGetOutlinerMode() == OutlinerMode::OutlineView ), "SetLevelDependentStyleSheet: Wrong Mode!" ); + DBG_ASSERT( ( GetOutlinerMode() == OutlinerMode::OutlineObject ) || ( GetOutlinerMode() == OutlinerMode::OutlineView ), "SetLevelDependentStyleSheet: Wrong Mode!" ); SfxStyleSheet* pStyle = GetStyleSheet( nPara ); @@ -731,8 +728,7 @@ void Outliner::ImplInitDepth( sal_Int32 nPara, sal_Int16 nDepth, bool bCreateUnd if( IsInUndo() ) return; - bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + bool bUpdate = pEditEngine->SetUpdateLayout( false ); bool bUndo = bCreateUndo && IsUndoEnabled(); @@ -747,7 +743,7 @@ void Outliner::ImplInitDepth( sal_Int32 nPara, sal_Int16 nDepth, bool bCreateUnd InsertUndo( std::make_unique<OutlinerUndoChangeDepth>( this, nPara, nOldDepth, nDepth ) ); } - pEditEngine->SetUpdateMode( bUpdate ); + pEditEngine->SetUpdateLayout( bUpdate ); } void Outliner::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) @@ -763,56 +759,53 @@ void Outliner::SetCharAttribs(sal_Int32 nPara, const SfxItemSet& rSet) bool Outliner::Expand( Paragraph const * pPara ) { - if ( pParaList->HasHiddenChildren( pPara ) ) + if ( !pParaList->HasHiddenChildren( pPara ) ) + return false; + + std::unique_ptr<OLUndoExpand> pUndo; + bool bUndo = IsUndoEnabled() && !IsInUndo(); + if( bUndo ) { - std::unique_ptr<OLUndoExpand> pUndo; - bool bUndo = IsUndoEnabled() && !IsInUndo(); - if( bUndo ) - { - UndoActionStart( OLUNDO_EXPAND ); - pUndo.reset( new OLUndoExpand( this, OLUNDO_EXPAND ) ); - pUndo->nCount = pParaList->GetAbsPos( pPara ); - } - pParaList->Expand( pPara ); - InvalidateBullet(pParaList->GetAbsPos(pPara)); - if( bUndo ) - { - InsertUndo( std::move(pUndo) ); - UndoActionEnd(); - } - return true; + UndoActionStart( OLUNDO_EXPAND ); + pUndo.reset( new OLUndoExpand( this, OLUNDO_EXPAND ) ); + pUndo->nCount = pParaList->GetAbsPos( pPara ); + } + pParaList->Expand( pPara ); + InvalidateBullet(pParaList->GetAbsPos(pPara)); + if( bUndo ) + { + InsertUndo( std::move(pUndo) ); + UndoActionEnd(); } - return false; + return true; } bool Outliner::Collapse( Paragraph const * pPara ) { - if ( pParaList->HasVisibleChildren( pPara ) ) // expanded - { - std::unique_ptr<OLUndoExpand> pUndo; - bool bUndo = false; + if ( !pParaList->HasVisibleChildren( pPara ) ) // collapsed + return false; - if( !IsInUndo() && IsUndoEnabled() ) - bUndo = true; - if( bUndo ) - { - UndoActionStart( OLUNDO_COLLAPSE ); - pUndo.reset( new OLUndoExpand( this, OLUNDO_COLLAPSE ) ); - pUndo->nCount = pParaList->GetAbsPos( pPara ); - } + std::unique_ptr<OLUndoExpand> pUndo; + bool bUndo = false; - pParaList->Collapse( pPara ); - InvalidateBullet(pParaList->GetAbsPos(pPara)); - if( bUndo ) - { - InsertUndo( std::move(pUndo) ); - UndoActionEnd(); - } - return true; + if( !IsInUndo() && IsUndoEnabled() ) + bUndo = true; + if( bUndo ) + { + UndoActionStart( OLUNDO_COLLAPSE ); + pUndo.reset( new OLUndoExpand( this, OLUNDO_COLLAPSE ) ); + pUndo->nCount = pParaList->GetAbsPos( pPara ); } - return false; -} + pParaList->Collapse( pPara ); + InvalidateBullet(pParaList->GetAbsPos(pPara)); + if( bUndo ) + { + InsertUndo( std::move(pUndo) ); + UndoActionEnd(); + } + return true; +} vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const { @@ -831,7 +824,7 @@ vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const } vcl::Font aBulletFont; - const vcl::Font *pSourceFont = nullptr; + std::optional<vcl::Font> pSourceFont; if ( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL ) { pSourceFont = pFmt->GetBulletFont(); @@ -852,16 +845,12 @@ vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const } // Use original scale... - sal_uInt16 nStretchX, nStretchY; - GetGlobalCharStretching(nStretchX, nStretchY); - sal_uInt16 nScale = pFmt->GetBulletRelSize() * nStretchY / 100; - sal_uLong nScaledLineHeight = aStdFont.GetFontSize().Height(); - nScaledLineHeight *= nScale*10; - nScaledLineHeight /= 1000; + double fFontScaleY = pFmt->GetBulletRelSize() / 100.0 * getScalingParameters().fFontY; + double fScaledLineHeight = aStdFont.GetFontSize().Height() * fFontScaleY; aBulletFont.SetAlignment( ALIGN_BOTTOM ); - aBulletFont.SetFontSize( Size( 0, nScaledLineHeight ) ); + aBulletFont.SetFontSize(Size(0, basegfx::fround(fScaledLineHeight))); bool bVertical = IsVertical(); aBulletFont.SetVertical( bVertical ); aBulletFont.SetOrientation( Degree10(bVertical ? (IsTopToBottom() ? 2700 : 900) : 0) ); @@ -899,12 +888,13 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& bool bRightToLeftPara = pEditEngine->IsRightToLeft( nPara ); tools::Rectangle aBulletArea( ImpCalcBulletArea( nPara, true, false ) ); - sal_uInt16 nStretchX, nStretchY; - GetGlobalCharStretching(nStretchX, nStretchY); - aBulletArea = tools::Rectangle( Point(aBulletArea.Left()*nStretchX/100, - aBulletArea.Top()), - Size(aBulletArea.GetWidth()*nStretchX/100, - aBulletArea.GetHeight()) ); + + double fSpacingFactorX = getScalingParameters().fSpacingX; + + tools::Long nStretchBulletX = basegfx::fround<tools::Long>(double(aBulletArea.Left()) * fSpacingFactorX); + tools::Long nStretchBulletWidth = basegfx::fround<tools::Long>(double(aBulletArea.GetWidth()) * fSpacingFactorX); + aBulletArea = tools::Rectangle(Point(nStretchBulletX, aBulletArea.Top()), + Size(nStretchBulletWidth, aBulletArea.GetHeight()) ); Paragraph* pPara = pParaList->GetParagraph( nPara ); const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); @@ -949,35 +939,25 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& { // Both TopLeft and bottom left is not quite correct, // since in EditEngine baseline ... - double nRealOrientation = nOrientation.get() * F_PI1800; - double nCos = cos( nRealOrientation ); - double nSin = sin( nRealOrientation ); - Point aRotatedPos; - // Translation... - aTextPos -= rOrigin; - // Rotation... - aRotatedPos.setX(static_cast<tools::Long>(nCos*aTextPos.X() + nSin*aTextPos.Y()) ); - aRotatedPos.setY(static_cast<tools::Long>(- (nSin*aTextPos.X() - nCos*aTextPos.Y())) ); - aTextPos = aRotatedPos; - // Translation... - aTextPos += rOrigin; + rOrigin.RotateAround(aTextPos, nOrientation); + vcl::Font aRotatedFont( aBulletFont ); aRotatedFont.SetOrientation( nOrientation ); rOutDev.SetFont( aRotatedFont ); } // VCL will take care of brackets and so on... - ComplexTextLayoutFlags nLayoutMode = rOutDev.GetLayoutMode(); - nLayoutMode &= ~ComplexTextLayoutFlags(ComplexTextLayoutFlags::BiDiRtl|ComplexTextLayoutFlags::BiDiStrong); + vcl::text::ComplexTextLayoutFlags nLayoutMode = rOutDev.GetLayoutMode(); + nLayoutMode &= ~vcl::text::ComplexTextLayoutFlags(vcl::text::ComplexTextLayoutFlags::BiDiRtl|vcl::text::ComplexTextLayoutFlags::BiDiStrong); if ( bRightToLeftPara ) - nLayoutMode |= ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::TextOriginLeft | ComplexTextLayoutFlags::BiDiStrong; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::TextOriginLeft | vcl::text::ComplexTextLayoutFlags::BiDiStrong; rOutDev.SetLayoutMode( nLayoutMode ); if(bStrippingPortions) { const vcl::Font& aSvxFont(rOutDev.GetFont()); - std::unique_ptr<tools::Long[]> pBuf(new tools::Long[ pPara->GetText().getLength() ]); - rOutDev.GetTextArray( pPara->GetText(), pBuf.get() ); + KernArray aBuf; + rOutDev.GetTextArray( pPara->GetText(), &aBuf ); if(bSymbol) { @@ -986,7 +966,8 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& aTextPos.AdjustY( -(aMetric.GetDescent()) ); } - DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), pBuf.get(), + assert(aBuf.get_factor() == 1); + DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), aBuf.get_subunit_array(), {}, aSvxFont, nPara, bRightToLeftPara ? 1 : 0, nullptr, nullptr, false, false, true, nullptr, Color(), Color()); } else @@ -1041,8 +1022,7 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& } else { - // Remove CAST when KA made the Draw-Method const - const_cast<GraphicObject*>(pFmt->GetBrush()->GetGraphicObject())->Draw(rOutDev, aBulletPos, pPara->aBulSize); + pFmt->GetBrush()->GetGraphicObject()->Draw(rOutDev, aBulletPos, pPara->aBulSize); } } } @@ -1102,8 +1082,7 @@ ErrCode Outliner::Read( SvStream& rInput, const OUString& rBaseURL, EETextFormat bool bOldUndo = pEditEngine->IsUndoEnabled(); EnableUndo( false ); - bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + bool bUpdate = pEditEngine->SetUpdateLayout( false ); Clear(); @@ -1123,7 +1102,7 @@ ErrCode Outliner::Read( SvStream& rInput, const OUString& rBaseURL, EETextFormat ImpFilterIndents( 0, nParas-1 ); ImplBlockInsertionCallbacks( false ); - pEditEngine->SetUpdateMode( bUpdate ); + pEditEngine->SetUpdateLayout( bUpdate ); EnableUndo( bOldUndo ); return nRet; @@ -1132,9 +1111,7 @@ ErrCode Outliner::Read( SvStream& rInput, const OUString& rBaseURL, EETextFormat void Outliner::ImpFilterIndents( sal_Int32 nFirstPara, sal_Int32 nLastPara ) { - - bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + bool bUpdate = pEditEngine->SetUpdateLayout( false ); Paragraph* pLastConverted = nullptr; for( sal_Int32 nPara = nFirstPara; nPara <= nLastPara; nPara++ ) @@ -1156,24 +1133,22 @@ void Outliner::ImpFilterIndents( sal_Int32 nFirstPara, sal_Int32 nLastPara ) } } - pEditEngine->SetUpdateMode( bUpdate ); + pEditEngine->SetUpdateLayout( bUpdate ); } -SfxUndoManager& Outliner::GetUndoManager() +EditUndoManager& Outliner::GetUndoManager() { return pEditEngine->GetUndoManager(); } -SfxUndoManager* Outliner::SetUndoManager(SfxUndoManager* pNew) +EditUndoManager* Outliner::SetUndoManager(EditUndoManager* pNew) { return pEditEngine->SetUndoManager(pNew); } void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount ) { - - bool bUpdate = pEditEngine->GetUpdateMode(); - pEditEngine->SetUpdateMode( false ); + bool bUpdate = pEditEngine->SetUpdateLayout( false ); const sal_Int32 nStart = nStartPara; @@ -1181,7 +1156,7 @@ void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount ) while( nCount && pPara ) { - if( ImplGetOutlinerMode() != OutlinerMode::TextObject ) + if( GetOutlinerMode() != OutlinerMode::TextObject ) { nDepthChangedHdlPrevDepth = pPara->GetDepth(); ParaFlag nPrevFlags = pPara->nFlags; @@ -1213,7 +1188,7 @@ void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount ) pPara = pParaList->GetParagraph( nStartPara ); } - pEditEngine->SetUpdateMode( bUpdate ); + pEditEngine->SetUpdateLayout( bUpdate ); DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"ImpTextPasted failed"); } @@ -1232,7 +1207,7 @@ bool Outliner::ImpCanIndentSelectedPages( OutlinerView* pCurView ) // If the first paragraph is on level 0 it can not indented in any case, // possible there might be indentations in the following on the 0 level. - if ( ( mnFirstSelPage == 0 ) && ( ImplGetOutlinerMode() != OutlinerMode::TextObject ) ) + if ( ( mnFirstSelPage == 0 ) && ( GetOutlinerMode() != OutlinerMode::TextObject ) ) { if ( nDepthChangedHdlPrevDepth == 1 ) // is the only page return false; @@ -1350,7 +1325,7 @@ void Outliner::DepthChangedHdl(Paragraph* pPara, ParaFlag nPrevFlags) } -sal_Int32 Outliner::GetAbsPos( Paragraph const * pPara ) +sal_Int32 Outliner::GetAbsPos( Paragraph const * pPara ) const { DBG_ASSERT(pPara,"GetAbsPos:No Para"); return pParaList->GetAbsPos( pPara ); @@ -1668,7 +1643,8 @@ void Outliner::StripPortions() } void Outliner::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart, - sal_Int32 nTextLen, const tools::Long* pDXArray,const SvxFont& rFont, + sal_Int32 nTextLen, std::span<const sal_Int32> pDXArray, + std::span<const sal_Bool> pKashidaArray, const SvxFont& rFont, sal_Int32 nPara, sal_uInt8 nRightToLeft, const EEngineData::WrongSpellVector* pWrongSpellVector, const SvxFieldData* pFieldData, @@ -1681,7 +1657,7 @@ void Outliner::DrawingText( const Point& rStartPos, const OUString& rText, sal_I { if(aDrawPortionHdl.IsSet()) { - DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, pDXArray, pWrongSpellVector, + DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, pDXArray, pKashidaArray, pWrongSpellVector, pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, false, 0, bEndOfLine, bEndOfParagraph, bEndOfBullet); aDrawPortionHdl.Call( &aInfo ); @@ -1694,7 +1670,7 @@ void Outliner::DrawingTab( const Point& rStartPos, tools::Long nWidth, const OUS { if(aDrawPortionHdl.IsSet()) { - DrawPortionInfo aInfo( rStartPos, rChar, 0, rChar.getLength(), rFont, nPara, nullptr, nullptr, + DrawPortionInfo aInfo( rStartPos, rChar, 0, rChar.getLength(), rFont, nPara, {}, {}, nullptr, nullptr, nullptr, rOverlineColor, rTextLineColor, nRightToLeft, true, nWidth, bEndOfLine, bEndOfParagraph, false); aDrawPortionHdl.Call( &aInfo ); @@ -1714,7 +1690,7 @@ bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView, sal_Int32 _nFi return RemovingPagesHdl( pCurView ); } -SfxItemSet const & Outliner::GetParaAttribs( sal_Int32 nPara ) +SfxItemSet const & Outliner::GetParaAttribs( sal_Int32 nPara ) const { return pEditEngine->GetParaAttribs( nPara ); } @@ -1852,8 +1828,6 @@ void Outliner::ImplCalcBulletText( sal_Int32 nPara, bool bRecalcLevel, bool bRec if (pPara->GetText() != aBulletText) pPara->SetText( aBulletText ); - pPara->nFlags &= ~ParaFlag::SETBULLETTEXT; - if ( bRecalcLevel ) { sal_Int16 nDepth = pPara->GetDepth(); @@ -1912,8 +1886,6 @@ OUString Outliner::ImplGetBulletText( sal_Int32 nPara ) Paragraph* pPara = pParaList->GetParagraph( nPara ); if (pPara) { - // Enable optimization again ... -// if( pPara->nFlags & ParaFlag::SETBULLETTEXT ) ImplCalcBulletText( nPara, false, false ); aRes = pPara->GetText(); } @@ -2006,7 +1978,7 @@ bool Outliner::IsPageOverflow() return pEditEngine->IsPageOverflow(); } -std::unique_ptr<NonOverflowingText> Outliner::GetNonOverflowingText() const +std::optional<NonOverflowingText> Outliner::GetNonOverflowingText() const { /* XXX: * nCount should be the number of paragraphs of the non overflowing text @@ -2014,7 +1986,7 @@ std::unique_ptr<NonOverflowingText> Outliner::GetNonOverflowingText() const */ if ( GetParagraphCount() < 1 ) - return nullptr; + return {}; // last non-overflowing paragraph is before the first overflowing one sal_Int32 nCount = pEditEngine->GetOverflowingParaNum(); @@ -2025,14 +1997,14 @@ std::unique_ptr<NonOverflowingText> Outliner::GetNonOverflowingText() const SAL_INFO("editeng.chaining", "[Overflowing] Ops, trying to retrieve para " << nCount << " when max index is " << GetParagraphCount()-1 ); - return nullptr; + return {}; } if (nCount < 0) { SAL_INFO("editeng.chaining", "[Overflowing] No Overflowing text but GetNonOverflowinText called?!"); - return nullptr; + return {}; } // NOTE: We want the selection of the overflowing text from here @@ -2070,7 +2042,7 @@ std::unique_ptr<NonOverflowingText> Outliner::GetNonOverflowingText() const ESelection aEmptySel(0,0,0,0); //EditTextObject *pTObj = pEditEngine->CreateTextObject(aEmptySel); bool const bLastParaInterrupted = true; // Last Para was interrupted since everything overflew - return std::make_unique<NonOverflowingText>(aEmptySel, bLastParaInterrupted); + return NonOverflowingText(aEmptySel, bLastParaInterrupted); } else { // Get the lines that of the overflowing para fit in the box sal_Int32 nOverflowingPara = nCount; @@ -2107,22 +2079,22 @@ std::unique_ptr<NonOverflowingText> Outliner::GetNonOverflowingText() const bool bLastParaInterrupted = pEditEngine->GetOverflowingLineNum() > 0; - return std::make_unique<NonOverflowingText>(aOverflowingTextSelection, bLastParaInterrupted); + return NonOverflowingText(aOverflowingTextSelection, bLastParaInterrupted); } } -std::unique_ptr<OutlinerParaObject> Outliner::GetEmptyParaObject() const +OutlinerParaObject Outliner::GetEmptyParaObject() const { std::unique_ptr<EditTextObject> pEmptyText = pEditEngine->GetEmptyTextObject(); - std::unique_ptr<OutlinerParaObject> pPObj( new OutlinerParaObject( std::move(pEmptyText) )); - pPObj->SetOutlinerMode(GetMode()); - return pPObj; + OutlinerParaObject aPObj( std::move(pEmptyText) ); + aPObj.SetOutlinerMode(GetOutlinerMode()); + return aPObj; } -std::unique_ptr<OverflowingText> Outliner::GetOverflowingText() const +std::optional<OverflowingText> Outliner::GetOverflowingText() const { if ( pEditEngine->GetOverflowingParaNum() < 0) - return nullptr; + return {}; // Defensive check: overflowing para index beyond actual # of paragraphs? @@ -2131,7 +2103,7 @@ std::unique_ptr<OverflowingText> Outliner::GetOverflowingText() const "[Overflowing] Ops, trying to retrieve para " << pEditEngine->GetOverflowingParaNum() << " when max index is " << GetParagraphCount()-1 ); - return nullptr; + return {}; } sal_Int32 nHeadPara = pEditEngine->GetOverflowingParaNum(); @@ -2150,7 +2122,7 @@ std::unique_ptr<OverflowingText> Outliner::GetOverflowingText() const sal_Int32 nLastParaLen = GetText(GetParagraph(nLastPara)).getLength(); aOverflowingTextSel = ESelection(nOverflowingPara, nLen, nLastPara, nLastParaLen); - return std::make_unique<OverflowingText>(pEditEngine->CreateTransferable(aOverflowingTextSel)); + return OverflowingText(pEditEngine->CreateTransferable(aOverflowingTextSel)); } diff --git a/editeng/source/outliner/outlobj.cxx b/editeng/source/outliner/outlobj.cxx index 373fca12c5f1..e6dc6e691c6c 100644 --- a/editeng/source/outliner/outlobj.cxx +++ b/editeng/source/outliner/outlobj.cxx @@ -29,9 +29,9 @@ #include <o3tl/safeint.hxx> #include <libxml/xmlwriter.h> -OutlinerParaObjData::OutlinerParaObjData( std::unique_ptr<EditTextObject> pEditTextObject, const ParagraphDataVector& rParagraphDataVector, bool bIsEditDoc ) : +OutlinerParaObjData::OutlinerParaObjData( std::unique_ptr<EditTextObject> pEditTextObject, ParagraphDataVector&& rParagraphDataVector, bool bIsEditDoc ) : mpEditTextObject(std::move(pEditTextObject)), - maParagraphDataVector(rParagraphDataVector), + maParagraphDataVector(std::move(rParagraphDataVector)), mbIsEditDoc(bIsEditDoc) { if( maParagraphDataVector.empty() && (mpEditTextObject->GetParagraphCount() != 0) ) @@ -62,8 +62,8 @@ bool OutlinerParaObjData::isWrongListEqual(const OutlinerParaObjData& rCompare) } OutlinerParaObject::OutlinerParaObject( - std::unique_ptr<EditTextObject> xTextObj, const ParagraphDataVector& rParagraphDataVector, bool bIsEditDoc ) : - mpImpl(OutlinerParaObjData(std::move(xTextObj), rParagraphDataVector, bIsEditDoc)) + std::unique_ptr<EditTextObject> xTextObj, ParagraphDataVector&& rParagraphDataVector, bool bIsEditDoc ) : + mpImpl(OutlinerParaObjData(std::move(xTextObj), std::move(rParagraphDataVector), bIsEditDoc)) { } @@ -77,6 +77,11 @@ OutlinerParaObject::OutlinerParaObject( const OutlinerParaObject& r ) : { } +OutlinerParaObject::OutlinerParaObject( OutlinerParaObject&& r ) noexcept : + mpImpl(std::move(r.mpImpl)) +{ +} + OutlinerParaObject::~OutlinerParaObject() { } @@ -87,6 +92,12 @@ OutlinerParaObject& OutlinerParaObject::operator=( const OutlinerParaObject& r ) return *this; } +OutlinerParaObject& OutlinerParaObject::operator=( OutlinerParaObject&& r ) noexcept +{ + mpImpl = std::move(r.mpImpl); + return *this; +} + bool OutlinerParaObject::operator==( const OutlinerParaObject& r ) const { return r.mpImpl == mpImpl; @@ -119,14 +130,14 @@ void OutlinerParaObject::SetOutlinerMode(OutlinerMode nNew) } } -bool OutlinerParaObject::IsVertical() const +bool OutlinerParaObject::IsEffectivelyVertical() const { - return mpImpl->mpEditTextObject->IsVertical(); + return mpImpl->mpEditTextObject->IsEffectivelyVertical(); } -bool OutlinerParaObject::GetDirectVertical() const +bool OutlinerParaObject::GetVertical() const { - return mpImpl->mpEditTextObject->GetDirectVertical(); + return mpImpl->mpEditTextObject->GetVertical(); } bool OutlinerParaObject::IsTopToBottom() const @@ -137,7 +148,7 @@ bool OutlinerParaObject::IsTopToBottom() const void OutlinerParaObject::SetVertical(bool bNew) { const ::o3tl::cow_wrapper< OutlinerParaObjData >* pImpl = &mpImpl; - if ( ( *pImpl )->mpEditTextObject->IsVertical() != bNew) + if ( ( *pImpl )->mpEditTextObject->IsEffectivelyVertical() != bNew) { mpImpl->mpEditTextObject->SetVertical(bNew); } diff --git a/editeng/source/outliner/outlvw.cxx b/editeng/source/outliner/outlvw.cxx index aabe51c9efd8..cd01503731eb 100644 --- a/editeng/source/outliner/outlvw.cxx +++ b/editeng/source/outliner/outlvw.cxx @@ -30,7 +30,7 @@ #include <i18nlangtag/languagetag.hxx> #include <editeng/outliner.hxx> -#include "outleeng.hxx" +#include <outleeng.hxx> #include "paralist.hxx" #include "outlundo.hxx" #include <editeng/outlobj.hxx> @@ -121,7 +121,7 @@ bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFra break; case KeyFuncType::DELETE: { - if( !bReadOnly && !bSelection && ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TextObject ) ) + if( !bReadOnly && !bSelection && ( pOwner->GetOutlinerMode() != OutlinerMode::TextObject ) ) { if( aSel.nEndPos == pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) ) { @@ -147,14 +147,14 @@ bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFra { if ( !bReadOnly && !aKeyCode.IsMod1() && !aKeyCode.IsMod2() ) { - if ( ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TextObject ) && - ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TitleObject ) && + if ( ( pOwner->GetOutlinerMode() != OutlinerMode::TextObject ) && + ( pOwner->GetOutlinerMode() != OutlinerMode::TitleObject ) && ( bSelection || !aSel.nStartPos ) ) { Indent( aKeyCode.IsShift() ? -1 : +1 ); bKeyProcessed = true; } - else if ( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) && + else if ( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) && !bSelection && !aSel.nEndPos && pOwner->ImplHasNumberFormat( aSel.nEndPara ) ) { Indent( aKeyCode.IsShift() ? -1 : +1 ); @@ -189,6 +189,13 @@ bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFra if( !aKeyCode.IsShift() ) { + // Don't let insert empty paragraph with numbering. Instead end numbering. + if (pPara->GetDepth() > -1 && + pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) == 0) + { + ToggleBullets(); + return true; + } // ImpGetCursor again??? if( !bSelection && aSel.nEndPos == pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) ) @@ -244,7 +251,7 @@ sal_Int32 OutlinerView::ImpCheckMousePos(const Point& rPosPix, MouseTarget& reTa sal_Int32 nPara = EE_PARA_NOT_FOUND; Point aMousePosWin = pEditView->GetOutputDevice().PixelToLogic( rPosPix ); - if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + if( !pEditView->GetOutputArea().Contains( aMousePosWin ) ) { reTarget = MouseTarget::Outside; } @@ -284,11 +291,11 @@ sal_Int32 OutlinerView::ImpCheckMousePos(const Point& rPosPix, MouseTarget& reTa bool OutlinerView::MouseMove( const MouseEvent& rMEvt ) { - if( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->GetEditEngine()->IsInSelectionMode()) + if( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->getEditEngine().IsInSelectionMode()) return pEditView->MouseMove( rMEvt ); Point aMousePosWin( pEditView->GetOutputDevice().PixelToLogic( rMEvt.GetPosPixel() ) ); - if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + if( !pEditView->GetOutputArea().Contains( aMousePosWin ) ) return false; PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() ); @@ -299,11 +306,11 @@ bool OutlinerView::MouseMove( const MouseEvent& rMEvt ) bool OutlinerView::MouseButtonDown( const MouseEvent& rMEvt ) { - if ( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->GetEditEngine()->IsInSelectionMode() ) + if ( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->getEditEngine().IsInSelectionMode() ) return pEditView->MouseButtonDown( rMEvt ); Point aMousePosWin( pEditView->GetOutputDevice().PixelToLogic( rMEvt.GetPosPixel() ) ); - if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + if( !pEditView->GetOutputArea().Contains( aMousePosWin ) ) return false; PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() ); @@ -331,7 +338,7 @@ bool OutlinerView::MouseButtonDown( const MouseEvent& rMEvt ) } // special case for outliner view in impress, check if double click hits the page icon for toggle - if( (nPara == EE_PARA_NOT_FOUND) && (pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineView) && (eTarget == MouseTarget::Text) && (rMEvt.GetClicks() == 2) ) + if( (nPara == EE_PARA_NOT_FOUND) && (pOwner->GetOutlinerMode() == OutlinerMode::OutlineView) && (eTarget == MouseTarget::Text) && (rMEvt.GetClicks() == 2) ) { ESelection aSel( pEditView->GetSelection() ); nPara = aSel.nStartPara; @@ -347,11 +354,11 @@ bool OutlinerView::MouseButtonDown( const MouseEvent& rMEvt ) bool OutlinerView::MouseButtonUp( const MouseEvent& rMEvt ) { - if ( ( pOwner->ImplGetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->GetEditEngine()->IsInSelectionMode() ) + if ( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->getEditEngine().IsInSelectionMode() ) return pEditView->MouseButtonUp( rMEvt ); Point aMousePosWin( pEditView->GetOutputDevice().PixelToLogic( rMEvt.GetPosPixel() ) ); - if( !pEditView->GetOutputArea().IsInside( aMousePosWin ) ) + if( !pEditView->GetOutputArea().Contains( aMousePosWin ) ) return false; PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() ); @@ -384,11 +391,28 @@ void OutlinerView::Select( Paragraph const * pParagraph, bool bSelect ) pEditView->SetSelection( aSel ); } +void OutlinerView::SetDepth(sal_Int32 nParagraph, sal_Int16 nDepth) +{ + Paragraph* pParagraph = pOwner->GetParagraph(nParagraph); + pOwner->SetDepth(pParagraph, nDepth); +} + +sal_Int16 OutlinerView::GetDepth() const +{ + ESelection aESelection = GetSelection(); + aESelection.Adjust(); + sal_Int16 nDepth = pOwner->GetDepth(aESelection.nStartPara); + for (sal_Int32 nPara = aESelection.nStartPara + 1; nPara <= aESelection.nEndPara; ++nPara) + { + if (nDepth != pOwner->GetDepth(nPara)) + return -2; + } + return nDepth; +} void OutlinerView::SetAttribs( const SfxItemSet& rAttrs ) { - bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); - pOwner->pEditEngine->SetUpdateMode( false ); + bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false ); if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() ) pOwner->UndoActionStart( OLUNDO_ATTR ); @@ -410,7 +434,7 @@ void OutlinerView::SetAttribs( const SfxItemSet& rAttrs ) if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() ) pOwner->UndoActionEnd(); - pEditView->SetEditEngineUpdateMode( bUpdate ); + pEditView->SetEditEngineUpdateLayout( bUpdate ); } ParaRange OutlinerView::ImpGetSelectedParagraphs( bool bIncludeHiddenChildren ) @@ -441,8 +465,7 @@ void OutlinerView::Indent( short nDiff ) return; const bool bOutlinerView = bool(pOwner->pEditEngine->GetControlWord() & EEControlBits::OUTLINER); - bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); - pOwner->pEditEngine->SetUpdateMode( false ); + bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false ); bool bUndo = !pOwner->IsInUndo() && pOwner->IsUndoEnabled(); @@ -503,7 +526,7 @@ void OutlinerView::Indent( short nDiff ) if( nOldDepth != nNewDepth ) { - if ( ( nPara == aSel.nStartPara ) && aSel.nStartPara && ( pOwner->ImplGetOutlinerMode() != OutlinerMode::TextObject )) + if ( ( nPara == aSel.nStartPara ) && aSel.nStartPara && ( pOwner->GetOutlinerMode() != OutlinerMode::TextObject )) { // Special case: the predecessor of an indented paragraph is // invisible and is now on the same level as the visible @@ -534,7 +557,7 @@ void OutlinerView::Indent( short nDiff ) pOwner->ImplInitDepth( nPara, nNewDepth, true ); pOwner->ImplCalcBulletText( nPara, false, false ); - if ( pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) + if ( pOwner->GetOutlinerMode() == OutlinerMode::OutlineObject ) pOwner->ImplSetLevelDependentStyleSheet( nPara ); // Notify App @@ -558,7 +581,7 @@ void OutlinerView::Indent( short nDiff ) if ( bUpdate ) { - pEditView->SetEditEngineUpdateMode( true ); + pEditView->SetEditEngineUpdateLayout( true ); pEditView->ShowCursor(); } @@ -603,8 +626,7 @@ void OutlinerView::CollapseAll() void OutlinerView::ImplExpandOrCollaps( sal_Int32 nStartPara, sal_Int32 nEndPara, bool bExpand ) { - bool bUpdate = pOwner->GetUpdateMode(); - pOwner->SetUpdateMode( false ); + bool bUpdate = pOwner->SetUpdateLayout( false ); bool bUndo = !pOwner->IsInUndo() && pOwner->IsUndoEnabled(); if( bUndo ) @@ -626,7 +648,7 @@ void OutlinerView::ImplExpandOrCollaps( sal_Int32 nStartPara, sal_Int32 nEndPara if ( bUpdate ) { - pOwner->SetUpdateMode( true ); + pOwner->SetUpdateLayout( true ); pEditView->ShowCursor(); } } @@ -647,13 +669,13 @@ void OutlinerView::InsertText( const OutlinerParaObject& rParaObj ) pOwner->UndoActionStart( OLUNDO_INSERT ); - pOwner->pEditEngine->SetUpdateMode( false ); + const bool bPrevUpdateLayout = pOwner->pEditEngine->SetUpdateLayout( false ); sal_Int32 nStart, nParaCount; nParaCount = pOwner->pEditEngine->GetParagraphCount(); sal_uInt16 nSize = ImpInitPaste( nStart ); pEditView->InsertText( rParaObj.GetTextObject() ); ImpPasted( nStart, nParaCount, nSize); - pEditView->SetEditEngineUpdateMode( true ); + pEditView->SetEditEngineUpdateLayout( bPrevUpdateLayout ); pOwner->UndoActionEnd(); @@ -670,27 +692,27 @@ void OutlinerView::Cut() } } -void OutlinerView::PasteSpecial() +void OutlinerView::PasteSpecial(SotClipboardFormatId format) { - Paste( true ); + Paste( true, format ); } -void OutlinerView::Paste( bool bUseSpecial ) +void OutlinerView::Paste( bool bUseSpecial, SotClipboardFormatId format) { if ( ImpCalcSelectedPages( false ) && !pOwner->ImpCanDeleteSelectedPages( this ) ) return; pOwner->UndoActionStart( OLUNDO_INSERT ); - pOwner->pEditEngine->SetUpdateMode( false ); + const bool bPrevUpdateLayout = pOwner->pEditEngine->SetUpdateLayout( false ); pOwner->bPasting = true; if ( bUseSpecial ) - pEditView->PasteSpecial(); + pEditView->PasteSpecial(format); else pEditView->Paste(); - if ( pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) + if ( pOwner->GetOutlinerMode() == OutlinerMode::OutlineObject ) { const sal_Int32 nParaCount = pOwner->pEditEngine->GetParagraphCount(); @@ -698,7 +720,7 @@ void OutlinerView::Paste( bool bUseSpecial ) pOwner->ImplSetLevelDependentStyleSheet( nPara ); } - pEditView->SetEditEngineUpdateMode( true ); + pEditView->SetEditEngineUpdateLayout( bPrevUpdateLayout ); pOwner->UndoActionEnd(); pEditView->ShowCursor(); @@ -718,6 +740,18 @@ void OutlinerView::CreateSelectionList (std::vector<Paragraph*> &aSelList) } } +void OutlinerView::SetStyleSheet(const OUString& rStyleName) +{ + ParaRange aParas = ImpGetSelectedParagraphs(false); + + auto pStyle = pOwner->GetStyleSheetPool()->Find(rStyleName, SfxStyleFamily::Para); + if (!pStyle) + return; + + for (sal_Int32 nPara = aParas.nStartPara; nPara <= aParas.nEndPara; nPara++) + pOwner->SetStyleSheet(nPara, static_cast<SfxStyleSheet*>(pStyle)); +} + const SfxStyleSheet* OutlinerView::GetStyleSheet() const { return pEditView->GetStyleSheet(); @@ -828,8 +862,7 @@ void OutlinerView::ToggleBullets() ESelection aSel( pEditView->GetSelection() ); aSel.Adjust(); - const bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); - pOwner->pEditEngine->SetUpdateMode( false ); + const bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false ); sal_Int16 nNewDepth = -2; const SvxNumRule* pDefaultBulletNumRule = nullptr; @@ -849,7 +882,7 @@ void OutlinerView::ToggleBullets() // determine default numbering rule for bullets const ESelection aSelection(nPara, 0); const SfxItemSet aTmpSet(pOwner->pEditEngine->GetAttribs(aSelection)); - const SfxPoolItem& rPoolItem = aTmpSet.GetPool()->GetDefaultItem( EE_PARA_NUMBULLET ); + const SfxPoolItem& rPoolItem = aTmpSet.GetPool()->GetUserOrPoolDefaultItem( EE_PARA_NUMBULLET ); const SvxNumBulletItem* pNumBulletItem = dynamic_cast< const SvxNumBulletItem* >(&rPoolItem); pDefaultBulletNumRule = pNumBulletItem ? &pNumBulletItem->GetNumRule() : nullptr; } @@ -878,7 +911,7 @@ void OutlinerView::ToggleBullets() { SfxItemSet aAttrs( pOwner->GetParaAttribs( nPara ) ); SvxNumRule aNewNumRule( *pDefaultBulletNumRule ); - aAttrs.Put( SvxNumBulletItem( aNewNumRule, EE_PARA_NUMBULLET ) ); + aAttrs.Put( SvxNumBulletItem( std::move(aNewNumRule), EE_PARA_NUMBULLET ) ); pOwner->SetParaAttribs( nPara, aAttrs ); } } @@ -892,7 +925,7 @@ void OutlinerView::ToggleBullets() sal_Int32 nEndPara = (nParaCount > 0) ? nParaCount-1 : nParaCount; pOwner->pEditEngine->QuickMarkInvalid( ESelection( aSel.nStartPara, 0, nEndPara, 0 ) ); - pOwner->pEditEngine->SetUpdateMode( bUpdate ); + pOwner->pEditEngine->SetUpdateLayout( bUpdate ); pOwner->UndoActionEnd(); } @@ -934,6 +967,35 @@ void OutlinerView::ToggleBulletsNumbering( } } +void OutlinerView::EnsureNumberingIsOn() +{ + pOwner->UndoActionStart(OLUNDO_DEPTH); + + ESelection aSel(pEditView->GetSelection()); + aSel.Adjust(); + + const bool bUpdate = pOwner->pEditEngine->IsUpdateLayout(); + pOwner->pEditEngine->SetUpdateLayout(false); + + for (sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++) + { + Paragraph* pPara = pOwner->pParaList->GetParagraph(nPara); + DBG_ASSERT(pPara, "OutlinerView::EnableBullets(), illegal selection?"); + + if (pPara && pOwner->GetDepth(nPara) == -1) + pOwner->SetDepth(pPara, 0); + } + + sal_Int32 nParaCount = pOwner->pParaList->GetParagraphCount(); + pOwner->ImplCheckParagraphs(aSel.nStartPara, nParaCount); + + const sal_Int32 nEndPara = (nParaCount > 0) ? nParaCount-1 : nParaCount; + pOwner->pEditEngine->QuickMarkInvalid(ESelection(aSel.nStartPara, 0, nEndPara, 0)); + + pOwner->pEditEngine->SetUpdateLayout(bUpdate); + + pOwner->UndoActionEnd(); +} void OutlinerView::ApplyBulletsNumbering( const bool bHandleBullets, @@ -947,8 +1009,7 @@ void OutlinerView::ApplyBulletsNumbering( } pOwner->UndoActionStart(OLUNDO_DEPTH); - const bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); - pOwner->pEditEngine->SetUpdateMode(false); + const bool bUpdate = pOwner->pEditEngine->SetUpdateLayout(false); sal_Int32 nStartPara = 0; sal_Int32 nEndPara = 0; @@ -1021,17 +1082,15 @@ void OutlinerView::ApplyBulletsNumbering( // Get old bullet space. { - const SfxPoolItem* pPoolItem=nullptr; - SfxItemState eState = rAttrs.GetItemState(EE_PARA_NUMBULLET, false, &pPoolItem); - if (eState != SfxItemState::SET) + const SvxNumBulletItem* pNumBulletItem = rAttrs.GetItemIfSet(EE_PARA_NUMBULLET, false); + if (pNumBulletItem) { // Use default value when has not contain bullet item. ESelection aSelection(nPara, 0); SfxItemSet aTmpSet(pOwner->pEditEngine->GetAttribs(aSelection)); - pPoolItem = aTmpSet.GetItem(EE_PARA_NUMBULLET); + pNumBulletItem = aTmpSet.GetItem(EE_PARA_NUMBULLET); } - const SvxNumBulletItem* pNumBulletItem = dynamic_cast< const SvxNumBulletItem* >(pPoolItem); if (pNumBulletItem) { const sal_uInt16 nLevelCnt = std::min(pNumBulletItem->GetNumRule().GetLevelCount(), aNewRule.GetLevelCount()); @@ -1050,7 +1109,7 @@ void OutlinerView::ApplyBulletsNumbering( } } - aAttrs.Put(SvxNumBulletItem(aNewRule, EE_PARA_NUMBULLET)); + aAttrs.Put(SvxNumBulletItem(std::move(aNewRule), EE_PARA_NUMBULLET)); } } pOwner->SetParaAttribs(nPara, aAttrs); @@ -1061,7 +1120,7 @@ void OutlinerView::ApplyBulletsNumbering( pOwner->ImplCheckParagraphs( nStartPara, nParaCount ); pOwner->pEditEngine->QuickMarkInvalid( ESelection( nStartPara, 0, nParaCount, 0 ) ); - pOwner->pEditEngine->SetUpdateMode( bUpdate ); + pOwner->pEditEngine->SetUpdateLayout( bUpdate ); pOwner->UndoActionEnd(); } @@ -1086,8 +1145,7 @@ void OutlinerView::SwitchOffBulletsNumbering( } pOwner->UndoActionStart( OLUNDO_DEPTH ); - const bool bUpdate = pOwner->pEditEngine->GetUpdateMode(); - pOwner->pEditEngine->SetUpdateMode( false ); + const bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false ); for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; ++nPara ) { @@ -1112,7 +1170,7 @@ void OutlinerView::SwitchOffBulletsNumbering( pOwner->ImplCheckParagraphs( nStartPara, nParaCount ); pOwner->pEditEngine->QuickMarkInvalid( ESelection( nStartPara, 0, nParaCount, 0 ) ); - pOwner->pEditEngine->SetUpdateMode( bUpdate ); + pOwner->pEditEngine->SetUpdateLayout( bUpdate ); pOwner->UndoActionEnd(); } @@ -1124,8 +1182,7 @@ void OutlinerView::RemoveAttribsKeepLanguages( bool bRemoveParaAttribs ) void OutlinerView::RemoveAttribs( bool bRemoveParaAttribs, bool bKeepLanguages ) { - bool bUpdate = pOwner->GetUpdateMode(); - pOwner->SetUpdateMode( false ); + bool bUpdate = pOwner->SetUpdateLayout( false ); pOwner->UndoActionStart( OLUNDO_ATTR ); if (bKeepLanguages) pEditView->RemoveAttribsKeepLanguages( bRemoveParaAttribs ); @@ -1143,7 +1200,7 @@ void OutlinerView::RemoveAttribs( bool bRemoveParaAttribs, bool bKeepLanguages ) } } pOwner->UndoActionEnd(); - pOwner->SetUpdateMode( bUpdate ); + pOwner->SetUpdateLayout( bUpdate ); } @@ -1308,14 +1365,9 @@ const SvxFieldItem* OutlinerView::GetFieldUnderMousePointer() const return pEditView->GetFieldUnderMousePointer(); } -const SvxFieldItem* OutlinerView::GetFieldAtSelection() const -{ - return pEditView->GetFieldAtSelection(); -} - -const SvxFieldData* OutlinerView::GetFieldAtCursor() const +const SvxFieldItem* OutlinerView::GetFieldAtSelection(bool bAlsoCheckBeforeCursor) const { - return pEditView->GetFieldAtCursor(); + return pEditView->GetFieldAtSelection(bAlsoCheckBeforeCursor); } void OutlinerView::SelectFieldAtCursor() @@ -1353,19 +1405,19 @@ void OutlinerView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCal void OutlinerView::Read( SvStream& rInput, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs ) { - sal_Int32 nOldParaCount = pEditView->GetEditEngine()->GetParagraphCount(); + sal_Int32 nOldParaCount = pEditView->getEditEngine().GetParagraphCount(); ESelection aOldSel = pEditView->GetSelection(); aOldSel.Adjust(); pEditView->Read( rInput, eFormat, pHTTPHeaderAttrs ); - tools::Long nParaDiff = pEditView->GetEditEngine()->GetParagraphCount() - nOldParaCount; + tools::Long nParaDiff = pEditView->getEditEngine().GetParagraphCount() - nOldParaCount; sal_Int32 nChangesStart = aOldSel.nStartPara; sal_Int32 nChangesEnd = nChangesStart + nParaDiff + (aOldSel.nEndPara-aOldSel.nStartPara); for ( sal_Int32 n = nChangesStart; n <= nChangesEnd; n++ ) { - if ( pOwner->ImplGetOutlinerMode() == OutlinerMode::OutlineObject ) + if ( pOwner->GetOutlinerMode() == OutlinerMode::OutlineObject ) pOwner->ImplSetLevelDependentStyleSheet( n ); } @@ -1441,17 +1493,17 @@ bool GetStatusValueForThesaurusFromContext( { // get text and locale for thesaurus look up OUString aText; - EditEngine *pEditEngine = rEditView.GetEditEngine(); + EditEngine& rEditEngine = rEditView.getEditEngine(); ESelection aTextSel( rEditView.GetSelection() ); if (!aTextSel.HasRange()) - aTextSel = pEditEngine->GetWord( aTextSel, i18n::WordType::DICTIONARY_WORD ); - aText = pEditEngine->GetText( aTextSel ); + aTextSel = rEditEngine.GetWord( aTextSel, i18n::WordType::DICTIONARY_WORD ); + aText = rEditEngine.GetText( aTextSel ); aTextSel.Adjust(); - if (!isSingleScriptType(pEditEngine->GetScriptType(aTextSel))) + if (!isSingleScriptType(rEditEngine.GetScriptType(aTextSel))) return false; - LanguageType nLang = pEditEngine->GetLanguage( aTextSel.nStartPara, aTextSel.nStartPos ); + LanguageType nLang = rEditEngine.GetLanguage( aTextSel.nStartPara, aTextSel.nStartPos ).nLang; OUString aLangText( LanguageTag::convertToBcp47( nLang ) ); // set word and locale to look up as status value diff --git a/editeng/source/outliner/overflowingtxt.cxx b/editeng/source/outliner/overflowingtxt.cxx index 16be74813704..0a17cd609100 100644 --- a/editeng/source/outliner/overflowingtxt.cxx +++ b/editeng/source/outliner/overflowingtxt.cxx @@ -28,9 +28,10 @@ #include <editeng/editdata.hxx> #include <editdoc.hxx> +#include <utility> -std::unique_ptr<OutlinerParaObject> TextChainingUtils::JuxtaposeParaObject( +std::optional<OutlinerParaObject> TextChainingUtils::JuxtaposeParaObject( css::uno::Reference< css::datatransfer::XTransferable > const & xOverflowingContent, Outliner *pOutl, OutlinerParaObject const *pNextPObj) @@ -44,7 +45,7 @@ std::unique_ptr<OutlinerParaObject> TextChainingUtils::JuxtaposeParaObject( // Special case: if only empty text remove it at the end bool bOnlyOneEmptyPara = !pNextPObj || (pOutl->GetParagraphCount() == 1 && - pNextPObj->GetTextObject().GetText(0).isEmpty()); + !pNextPObj->GetTextObject().HasText(0)); EditEngine &rEditEngine = const_cast<EditEngine &>(pOutl->GetEditEngine()); @@ -65,7 +66,7 @@ std::unique_ptr<OutlinerParaObject> TextChainingUtils::JuxtaposeParaObject( return pOutl->CreateParaObject(); } -std::unique_ptr<OutlinerParaObject> TextChainingUtils::DeeplyMergeParaObject( +std::optional<OutlinerParaObject> TextChainingUtils::DeeplyMergeParaObject( css::uno::Reference< css::datatransfer::XTransferable > const & xOverflowingContent, Outliner *pOutl, OutlinerParaObject const *pNextPObj) @@ -93,7 +94,7 @@ std::unique_ptr<OutlinerParaObject> TextChainingUtils::DeeplyMergeParaObject( css::uno::Reference< css::datatransfer::XTransferable > TextChainingUtils::CreateTransferableFromText(Outliner const *pOutl) { - const EditEngine &rEditEngine = pOutl->GetEditEngine(); + EditEngine& rEditEngine = const_cast<EditEngine &>(pOutl->GetEditEngine()); sal_Int32 nLastPara = pOutl->GetParagraphCount()-1; ESelection aWholeTextSel(0, 0, nLastPara, rEditEngine.GetTextLen(nLastPara)); @@ -102,8 +103,8 @@ css::uno::Reference< css::datatransfer::XTransferable > TextChainingUtils::Creat -OverflowingText::OverflowingText(css::uno::Reference< css::datatransfer::XTransferable > const & xOverflowingContent) : - mxOverflowingContent(xOverflowingContent) +OverflowingText::OverflowingText(css::uno::Reference< css::datatransfer::XTransferable > xOverflowingContent) : + mxOverflowingContent(std::move(xOverflowingContent)) { } @@ -122,7 +123,7 @@ bool NonOverflowingText::IsLastParaInterrupted() const } -std::unique_ptr<OutlinerParaObject> NonOverflowingText::RemoveOverflowingText(Outliner *pOutliner) const +std::optional<OutlinerParaObject> NonOverflowingText::RemoveOverflowingText(Outliner *pOutliner) const { pOutliner->QuickDelete(maContentSel); SAL_INFO("editeng.chaining", "Deleting selection from (Para: " << maContentSel.nStartPara @@ -141,12 +142,12 @@ ESelection NonOverflowingText::GetOverflowPointSel() const // The equivalent of ToParaObject for OverflowingText. Here we are prepending the overflowing text to the old dest box's text // XXX: In a sense a better name for OverflowingText and NonOverflowingText are respectively DestLinkText and SourceLinkText -std::unique_ptr<OutlinerParaObject> OverflowingText::JuxtaposeParaObject(Outliner *pOutl, OutlinerParaObject const *pNextPObj) +std::optional<OutlinerParaObject> OverflowingText::JuxtaposeParaObject(Outliner *pOutl, OutlinerParaObject const *pNextPObj) { return TextChainingUtils::JuxtaposeParaObject(mxOverflowingContent, pOutl, pNextPObj); } -std::unique_ptr<OutlinerParaObject> OverflowingText::DeeplyMergeParaObject(Outliner *pOutl, OutlinerParaObject const *pNextPObj) +std::optional<OutlinerParaObject> OverflowingText::DeeplyMergeParaObject(Outliner *pOutl, OutlinerParaObject const *pNextPObj) { return TextChainingUtils::DeeplyMergeParaObject(mxOverflowingContent, pOutl, pNextPObj); } @@ -170,11 +171,11 @@ ESelection OFlowChainedText::GetOverflowPointSel() const return mpNonOverflowingTxt->GetOverflowPointSel(); } -std::unique_ptr<OutlinerParaObject> OFlowChainedText::InsertOverflowingText(Outliner *pOutliner, OutlinerParaObject const *pTextToBeMerged) +std::optional<OutlinerParaObject> OFlowChainedText::InsertOverflowingText(Outliner *pOutliner, OutlinerParaObject const *pTextToBeMerged) { // Just return the roughly merged paras for now - if (mpOverflowingTxt == nullptr) - return nullptr; + if (!mpOverflowingTxt) + return std::nullopt; if (mbIsDeepMerge) { SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - OF] Deep merging paras" ); @@ -186,10 +187,10 @@ std::unique_ptr<OutlinerParaObject> OFlowChainedText::InsertOverflowingText(Outl } -std::unique_ptr<OutlinerParaObject> OFlowChainedText::RemoveOverflowingText(Outliner *pOutliner) +std::optional<OutlinerParaObject> OFlowChainedText::RemoveOverflowingText(Outliner *pOutliner) { - if (mpNonOverflowingTxt == nullptr) - return nullptr; + if (!mpNonOverflowingTxt) + return std::nullopt; return mpNonOverflowingTxt->RemoveOverflowingText(pOutliner); } @@ -207,9 +208,9 @@ UFlowChainedText::UFlowChainedText(Outliner const *pOutl, bool bIsDeepMerge) mbIsDeepMerge = bIsDeepMerge; } -std::unique_ptr<OutlinerParaObject> UFlowChainedText::CreateMergedUnderflowParaObject(Outliner *pOutl, OutlinerParaObject const *pNextLinkWholeText) +std::optional<OutlinerParaObject> UFlowChainedText::CreateMergedUnderflowParaObject(Outliner *pOutl, OutlinerParaObject const *pNextLinkWholeText) { - std::unique_ptr<OutlinerParaObject> pNewText; + std::optional<OutlinerParaObject> pNewText; if (mbIsDeepMerge) { SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - UF] Deep merging paras" ); diff --git a/editeng/source/rtf/rtfitem.cxx b/editeng/source/rtf/rtfitem.cxx index b6e0a93adee6..a5cfd41efae9 100644 --- a/editeng/source/rtf/rtfitem.cxx +++ b/editeng/source/rtf/rtfitem.cxx @@ -77,37 +77,39 @@ using namespace editeng; void SvxRTFParser::SetScriptAttr( RTF_CharTypeDef eType, SfxItemSet& rSet, SfxPoolItem& rItem ) { - const sal_uInt16 *pNormal = nullptr, *pCJK = nullptr, *pCTL = nullptr; + std::optional<sal_uInt16> pNormal; + std::optional<sal_uInt16> pCJK; + std::optional<sal_uInt16> pCTL; switch( rItem.Which() ) { case SID_ATTR_CHAR_FONT: - pNormal = &aPlainMap.nFont; - pCJK = &aPlainMap.nCJKFont; - pCTL = &aPlainMap.nCTLFont; + pNormal = aPlainMap[SID_ATTR_CHAR_FONT]; + pCJK = aPlainMap[SID_ATTR_CHAR_CJK_FONT]; + pCTL = aPlainMap[SID_ATTR_CHAR_CTL_FONT]; break; case SID_ATTR_CHAR_FONTHEIGHT: - pNormal = &aPlainMap.nFontHeight; - pCJK = &aPlainMap.nCJKFontHeight; - pCTL = &aPlainMap.nCTLFontHeight; + pNormal = aPlainMap[SID_ATTR_CHAR_FONTHEIGHT]; + pCJK = aPlainMap[SID_ATTR_CHAR_CJK_FONTHEIGHT]; + pCTL = aPlainMap[SID_ATTR_CHAR_CTL_FONTHEIGHT]; break; case SID_ATTR_CHAR_POSTURE: - pNormal = &aPlainMap.nPosture; - pCJK = &aPlainMap.nCJKPosture; - pCTL = &aPlainMap.nCTLPosture; + pNormal = aPlainMap[SID_ATTR_CHAR_POSTURE]; + pCJK = aPlainMap[SID_ATTR_CHAR_CJK_POSTURE]; + pCTL = aPlainMap[SID_ATTR_CHAR_CTL_POSTURE]; break; case SID_ATTR_CHAR_WEIGHT: - pNormal = &aPlainMap.nWeight; - pCJK = &aPlainMap.nCJKWeight; - pCTL = &aPlainMap.nCTLWeight; + pNormal = aPlainMap[SID_ATTR_CHAR_WEIGHT]; + pCJK = aPlainMap[SID_ATTR_CHAR_CJK_WEIGHT]; + pCTL = aPlainMap[SID_ATTR_CHAR_CTL_WEIGHT]; break; case SID_ATTR_CHAR_LANGUAGE: - pNormal = &aPlainMap.nLanguage; - pCJK = &aPlainMap.nCJKLanguage; - pCTL = &aPlainMap.nCTLLanguage; + pNormal = aPlainMap[SID_ATTR_CHAR_LANGUAGE]; + pCJK = aPlainMap[SID_ATTR_CHAR_CJK_LANGUAGE]; + pCTL = aPlainMap[SID_ATTR_CHAR_CTL_LANGUAGE]; break; case 0: @@ -214,7 +216,7 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) if( RTF_PARD == nLastToken || RTF_PLAIN == nLastToken ) break; - if (pCurrent->aAttrSet.Count() || pCurrent->m_pChildList || + if (pCurrent->aAttrSet.Count() || !pCurrent->maChildList.empty() || pCurrent->nStyleNo ) { // Open a new Group @@ -267,57 +269,55 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) break; case RTF_KEEP: - if( aPardMap.nSplit ) + if (const TypedWhichId<SvxFormatSplitItem> wid = aPardMap[SID_ATTR_PARA_SPLIT]) { - pSet->Put( SvxFormatSplitItem( false, aPardMap.nSplit )); + pSet->Put(SvxFormatSplitItem(false, wid)); } break; case RTF_KEEPN: - if( aPardMap.nKeep ) + if (const TypedWhichId<SvxFormatKeepItem> wid = aPardMap[SID_ATTR_PARA_KEEP]) { - pSet->Put( SvxFormatKeepItem( true, aPardMap.nKeep )); + pSet->Put(SvxFormatKeepItem(true, wid)); } break; case RTF_LEVEL: - if( aPardMap.nOutlineLvl ) + if (const TypedWhichId<SfxInt16Item> wid = aPardMap[SID_ATTR_PARA_OUTLLEVEL]) { - pSet->Put( SfxInt16Item( aPardMap.nOutlineLvl, - static_cast<sal_uInt16>(nTokenValue) )); + pSet->Put(SfxInt16Item(wid, static_cast<sal_uInt16>(nTokenValue))); } break; case RTF_QL: - if( aPardMap.nAdjust ) + if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST]) { - pSet->Put( SvxAdjustItem( SvxAdjust::Left, aPardMap.nAdjust )); + pSet->Put(SvxAdjustItem(SvxAdjust::Left, wid)); } break; case RTF_QR: - if( aPardMap.nAdjust ) + if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST]) { - pSet->Put( SvxAdjustItem( SvxAdjust::Right, aPardMap.nAdjust )); + pSet->Put(SvxAdjustItem(SvxAdjust::Right, wid)); } break; case RTF_QJ: - if( aPardMap.nAdjust ) + if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST]) { - pSet->Put( SvxAdjustItem( SvxAdjust::Block, aPardMap.nAdjust )); + pSet->Put(SvxAdjustItem(SvxAdjust::Block, wid)); } break; case RTF_QC: - if( aPardMap.nAdjust ) + if (const TypedWhichId<SvxAdjustItem> wid = aPardMap[SID_ATTR_PARA_ADJUST]) { - pSet->Put( SvxAdjustItem( SvxAdjust::Center, aPardMap.nAdjust )); + pSet->Put(SvxAdjustItem(SvxAdjust::Center, wid)); } break; case RTF_FI: - if( aPardMap.nLRSpace ) + if (const TypedWhichId<SvxLRSpaceItem> wid = aPardMap[SID_ATTR_LRSPACE]) { - SvxLRSpaceItem aLR( - static_cast<const SvxLRSpaceItem&>(pSet->Get(aPardMap.nLRSpace))); + SvxLRSpaceItem aLR(pSet->Get(wid)); sal_uInt16 nSz = 0; if( -1 != nTokenValue ) { @@ -332,10 +332,9 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) case RTF_LI: case RTF_LIN: - if( aPardMap.nLRSpace ) + if (const TypedWhichId<SvxLRSpaceItem> wid = aPardMap[SID_ATTR_LRSPACE]) { - SvxLRSpaceItem aLR( - static_cast<const SvxLRSpaceItem&>(pSet->Get(aPardMap.nLRSpace))); + SvxLRSpaceItem aLR(pSet->Get(wid)); sal_uInt16 nSz = 0; if( 0 < nTokenValue ) { @@ -350,10 +349,9 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) case RTF_RI: case RTF_RIN: - if( aPardMap.nLRSpace ) + if (const TypedWhichId<SvxLRSpaceItem> wid = aPardMap[SID_ATTR_LRSPACE]) { - SvxLRSpaceItem aLR( - static_cast<const SvxLRSpaceItem&>(pSet->Get(aPardMap.nLRSpace))); + SvxLRSpaceItem aLR(pSet->Get(wid)); sal_uInt16 nSz = 0; if( 0 < nTokenValue ) { @@ -367,10 +365,9 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) break; case RTF_SB: - if( aPardMap.nULSpace ) + if (const TypedWhichId<SvxULSpaceItem> wid = aPardMap[SID_ATTR_ULSPACE]) { - SvxULSpaceItem aUL( - static_cast<const SvxULSpaceItem&>(pSet->Get(aPardMap.nULSpace))); + SvxULSpaceItem aUL(pSet->Get(wid)); sal_uInt16 nSz = 0; if( 0 < nTokenValue ) { @@ -384,10 +381,9 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) break; case RTF_SA: - if( aPardMap.nULSpace ) + if (const TypedWhichId<SvxULSpaceItem> wid = aPardMap[SID_ATTR_ULSPACE]) { - SvxULSpaceItem aUL( - static_cast<const SvxULSpaceItem&>(pSet->Get(aPardMap.nULSpace))); + SvxULSpaceItem aUL(pSet->Get(wid)); sal_uInt16 nSz = 0; if( 0 < nTokenValue ) { @@ -401,11 +397,11 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) break; case RTF_SLMULT: - if( aPardMap.nLinespacing && 1 == nTokenValue ) + if (const TypedWhichId<SvxLineSpacingItem> wid = aPardMap[SID_ATTR_PARA_LINESPACE]; + wid && 1 == nTokenValue) { // then switches to multi-line! - SvxLineSpacingItem aLSpace( - static_cast<const SvxLineSpacingItem&>(pSet->Get( aPardMap.nLinespacing,false))); + SvxLineSpacingItem aLSpace(pSet->Get(wid, false)); // how much do you get from the line height value? @@ -426,12 +422,12 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) break; case RTF_SL: - if( aPardMap.nLinespacing ) + if (const TypedWhichId<SvxLineSpacingItem> wid = aPardMap[SID_ATTR_PARA_LINESPACE]) { // Calculate the ratio between the default font and the // specified size. The distance consists of the line height // (100%) and the space above the line (20%). - SvxLineSpacingItem aLSpace(0, aPardMap.nLinespacing); + SvxLineSpacingItem aLSpace(0, wid); nTokenValue = !bTokenHasValue ? 0 : nTokenValue; if (1000 == nTokenValue ) @@ -464,25 +460,22 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) break; case RTF_NOCWRAP: - if( aPardMap.nForbRule ) + if (const TypedWhichId<SvxForbiddenRuleItem> wid = aPardMap[SID_ATTR_PARA_FORBIDDEN_RULES]) { - pSet->Put( SvxForbiddenRuleItem( false, - aPardMap.nForbRule )); + pSet->Put(SvxForbiddenRuleItem(false, wid)); } break; case RTF_NOOVERFLOW: - if( aPardMap.nHangPunct ) + if (const TypedWhichId<SvxHangingPunctuationItem> wid = aPardMap[SID_ATTR_PARA_HANGPUNCTUATION]) { - pSet->Put( SvxHangingPunctuationItem( false, - aPardMap.nHangPunct )); + pSet->Put(SvxHangingPunctuationItem(false, wid)); } break; case RTF_ASPALPHA: - if( aPardMap.nScriptSpace ) + if (const TypedWhichId<SvxScriptSpaceItem> wid = aPardMap[SID_ATTR_PARA_SCRIPTSPACE]) { - pSet->Put( SvxScriptSpaceItem( true, - aPardMap.nScriptSpace )); + pSet->Put(SvxScriptSpaceItem(true, wid)); } break; @@ -498,10 +491,9 @@ void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet ) case RTF_FAROMAN: nFontAlign = SvxParaVertAlignItem::Align::Baseline; goto SET_FONTALIGNMENT; SET_FONTALIGNMENT: - if( aPardMap.nFontAlign ) + if (const TypedWhichId<SvxParaVertAlignItem> wid = aPardMap[SID_PARA_VERTALIGN]) { - pSet->Put( SvxParaVertAlignItem( nFontAlign, - aPardMap.nFontAlign )); + pSet->Put(SvxParaVertAlignItem(nFontAlign, wid)); } break; @@ -519,8 +511,8 @@ SET_FONTALIGNMENT: case RTF_CAPS: case RTF_SCAPS: - if( aPlainMap.nCaseMap && - IsAttrSttPos() ) // not in the text flow? + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_CASEMAP]; + wid && IsAttrSttPos()) // not in the text flow? { SvxCaseMap eCaseMap; if( !nTokenValue ) @@ -530,15 +522,14 @@ SET_FONTALIGNMENT: else eCaseMap = SvxCaseMap::SmallCaps; - pSet->Put( SvxCaseMapItem( eCaseMap, aPlainMap.nCaseMap )); + pSet->Put(SvxCaseMapItem(eCaseMap, wid)); } break; case RTF_DN: case RTF_SUB: - if( aPlainMap.nEscapement ) + if (const sal_uInt16 nEsc = aPlainMap[SID_ATTR_CHAR_ESCAPEMENT]) { - const sal_uInt16 nEsc = aPlainMap.nEscapement; if( -1 == nTokenValue ) nTokenValue = 6; //RTF default \dn value in half-points if( IsCalcValue() ) @@ -562,15 +553,14 @@ SET_FONTALIGNMENT: break; case RTF_NOSUPERSUB: - if( aPlainMap.nEscapement ) + if (const sal_uInt16 nEsc = aPlainMap[SID_ATTR_CHAR_ESCAPEMENT]) { - const sal_uInt16 nEsc = aPlainMap.nEscapement; pSet->Put( SvxEscapementItem( nEsc )); } break; case RTF_EXPND: - if( aPlainMap.nKering ) + if (TypedWhichId<SvxKerningItem> wid = aPlainMap[SID_ATTR_CHAR_KERNING]) { if( -1 == nTokenValue ) nTokenValue = 0; @@ -578,12 +568,12 @@ SET_FONTALIGNMENT: nTokenValue *= 5; if( IsCalcValue() ) CalcValue(); - pSet->Put( SvxKerningItem( static_cast<short>(nTokenValue), aPlainMap.nKering )); + pSet->Put(SvxKerningItem(static_cast<short>(nTokenValue), wid)); } break; case RTF_KERNING: - if( aPlainMap.nAutoKerning ) + if (const TypedWhichId<SvxAutoKernItem> wid = aPlainMap[SID_ATTR_CHAR_AUTOKERN]) { if( -1 == nTokenValue ) nTokenValue = 0; @@ -591,19 +581,18 @@ SET_FONTALIGNMENT: nTokenValue *= 10; if( IsCalcValue() ) CalcValue(); - pSet->Put( SvxAutoKernItem( 0 != nTokenValue, - aPlainMap.nAutoKerning )); + pSet->Put(SvxAutoKernItem(0 != nTokenValue, wid)); } break; case RTF_EXPNDTW: - if( aPlainMap.nKering ) + if (TypedWhichId<SvxKerningItem> wid = aPlainMap[SID_ATTR_CHAR_KERNING]) { if( -1 == nTokenValue ) nTokenValue = 0; if( IsCalcValue() ) CalcValue(); - pSet->Put( SvxKerningItem( static_cast<short>(nTokenValue), aPlainMap.nKering )); + pSet->Put(SvxKerningItem(static_cast<short>(nTokenValue), wid)); } break; @@ -656,39 +645,37 @@ SET_FONTALIGNMENT: break; case RTF_OUTL: - if( aPlainMap.nContour && - IsAttrSttPos() ) // not in the text flow? + if (const TypedWhichId<SvxContourItem> wid = aPlainMap[SID_ATTR_CHAR_CONTOUR]; + wid && IsAttrSttPos()) // not in the text flow? { - pSet->Put( SvxContourItem(nTokenValue != 0, - aPlainMap.nContour )); + pSet->Put(SvxContourItem(nTokenValue != 0, wid)); } break; case RTF_SHAD: - if( aPlainMap.nShadowed && - IsAttrSttPos() ) // not in the text flow? + if (const TypedWhichId<SvxShadowedItem> wid = aPlainMap[SID_ATTR_CHAR_SHADOWED]; + wid && IsAttrSttPos()) // not in the text flow? { - pSet->Put( SvxShadowedItem(nTokenValue != 0, - aPlainMap.nShadowed )); + pSet->Put(SvxShadowedItem(nTokenValue != 0, wid)); } break; case RTF_STRIKE: - if( aPlainMap.nCrossedOut && - IsAttrSttPos() ) // not in the text flow? + if (const TypedWhichId<SvxCrossedOutItem> wid = aPlainMap[SID_ATTR_CHAR_STRIKEOUT]; + wid && IsAttrSttPos()) // not in the text flow? { pSet->Put( SvxCrossedOutItem( nTokenValue ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, - aPlainMap.nCrossedOut )); + wid )); } break; case RTF_STRIKED: - if( aPlainMap.nCrossedOut ) // not in the text flow? + if (const TypedWhichId<SvxCrossedOutItem> wid = aPlainMap[SID_ATTR_CHAR_STRIKEOUT]) // not in the text flow? { pSet->Put( SvxCrossedOutItem( nTokenValue ? STRIKEOUT_DOUBLE : STRIKEOUT_NONE, - aPlainMap.nCrossedOut )); + wid )); } break; @@ -750,26 +737,26 @@ SET_FONTALIGNMENT: case RTF_ULW: eUnderline = LINESTYLE_SINGLE; - if( aPlainMap.nWordlineMode ) + if (const TypedWhichId<SvxWordLineModeItem> wid = aPlainMap[SID_ATTR_CHAR_WORDLINEMODE]) { - pSet->Put( SvxWordLineModeItem( true, aPlainMap.nWordlineMode )); + pSet->Put(SvxWordLineModeItem(true, wid)); } goto ATTR_SETUNDERLINE; ATTR_SETUNDERLINE: - if( aPlainMap.nUnderline ) + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_UNDERLINE]) { - pSet->Put( SvxUnderlineItem( eUnderline, aPlainMap.nUnderline )); + pSet->Put(SvxUnderlineItem(eUnderline, wid)); } break; case RTF_ULC: - if( aPlainMap.nUnderline ) + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_UNDERLINE]) { - std::unique_ptr<SvxUnderlineItem> aUL(std::make_unique<SvxUnderlineItem>(LINESTYLE_SINGLE, aPlainMap.nUnderline)); + std::unique_ptr<SvxUnderlineItem> aUL(std::make_unique<SvxUnderlineItem>(LINESTYLE_SINGLE, wid)); const SfxPoolItem* pItem(nullptr); - if( SfxItemState::SET == pSet->GetItemState(aPlainMap.nUnderline, false, &pItem ) ) + if (SfxItemState::SET == pSet->GetItemState(wid, false, &pItem)) { // is switched off ? if( LINESTYLE_NONE == static_cast<const SvxUnderlineItem*>(pItem)->GetLineStyle() ) @@ -779,7 +766,7 @@ ATTR_SETUNDERLINE: } else { - aUL.reset(static_cast<SvxUnderlineItem*>(pSet->Get( aPlainMap.nUnderline, false).Clone())); + aUL.reset(static_cast<SvxUnderlineItem*>(pSet->Get(wid, false).Clone())); } if(LINESTYLE_NONE == aUL->GetLineStyle()) @@ -789,7 +776,7 @@ ATTR_SETUNDERLINE: aUL->SetColor(GetColor(sal_uInt16(nTokenValue))); - pSet->Put(*aUL); + pSet->Put(std::move(aUL)); } break; @@ -851,26 +838,26 @@ ATTR_SETUNDERLINE: case RTF_OLW: eOverline = LINESTYLE_SINGLE; - if( aPlainMap.nWordlineMode ) + if (const TypedWhichId<SvxWordLineModeItem> wid = aPlainMap[SID_ATTR_CHAR_WORDLINEMODE]) { - pSet->Put( SvxWordLineModeItem( true, aPlainMap.nWordlineMode )); + pSet->Put(SvxWordLineModeItem(true, wid)); } goto ATTR_SETOVERLINE; ATTR_SETOVERLINE: - if( aPlainMap.nUnderline ) + if (const TypedWhichId<SvxOverlineItem> wid = aPlainMap[SID_ATTR_CHAR_OVERLINE]) { - pSet->Put( SvxOverlineItem( eOverline, aPlainMap.nOverline )); + pSet->Put(SvxOverlineItem(eOverline, wid)); } break; case RTF_OLC: - if( aPlainMap.nOverline ) + if (const TypedWhichId<SvxOverlineItem> wid = aPlainMap[SID_ATTR_CHAR_OVERLINE]) { - std::unique_ptr<SvxOverlineItem> aOL(std::make_unique<SvxOverlineItem>(LINESTYLE_SINGLE, aPlainMap.nOverline)); + std::unique_ptr<SvxOverlineItem> aOL(std::make_unique<SvxOverlineItem>(LINESTYLE_SINGLE, wid)); const SfxPoolItem* pItem(nullptr); - if( SfxItemState::SET == pSet->GetItemState(aPlainMap.nOverline, false, &pItem ) ) + if (SfxItemState::SET == pSet->GetItemState(wid, false, &pItem)) { // is switched off ? if( LINESTYLE_NONE == static_cast<const SvxOverlineItem*>(pItem)->GetLineStyle() ) @@ -880,7 +867,7 @@ ATTR_SETOVERLINE: } else { - aOL.reset(static_cast<SvxOverlineItem*>(pSet->Get( aPlainMap.nOverline, false).Clone())); + aOL.reset(pSet->Get(wid, false).Clone()); } if(LINESTYLE_NONE == aOL->GetLineStyle()) @@ -890,15 +877,14 @@ ATTR_SETOVERLINE: aOL->SetColor(GetColor(sal_uInt16(nTokenValue))); - pSet->Put(*aOL); + pSet->Put(std::move(aOL)); } break; case RTF_UP: case RTF_SUPER: - if( aPlainMap.nEscapement ) + if (const sal_uInt16 nEsc = aPlainMap[SID_ATTR_CHAR_ESCAPEMENT]) { - const sal_uInt16 nEsc = aPlainMap.nEscapement; if( -1 == nTokenValue ) nTokenValue = 6; //RTF default \up value in half-points if( IsCalcValue() ) @@ -922,37 +908,33 @@ ATTR_SETOVERLINE: break; case RTF_CF: - if( aPlainMap.nColor ) + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_COLOR]) { - pSet->Put( SvxColorItem( GetColor( sal_uInt16(nTokenValue) ), - aPlainMap.nColor )); + pSet->Put(SvxColorItem(GetColor(sal_uInt16(nTokenValue)), wid)); } break; //#i12501# While cb is clearly documented in the rtf spec, word //doesn't accept it at all #if 0 case RTF_CB: - if( aPlainMap.nBgColor ) + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_BRUSH_CHAR]) { - pSet->Put( SvxBrushItem( GetColor( sal_uInt16(nTokenValue) ), - aPlainMap.nBgColor )); + pSet->Put(SvxBrushItem(GetColor(sal_uInt16(nTokenValue)), wid)); } break; #endif case RTF_LANG: - if( aPlainMap.nLanguage ) + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_LANGUAGE]) { - pSet->Put( SvxLanguageItem( LanguageType(nTokenValue), - aPlainMap.nLanguage )); + pSet->Put(SvxLanguageItem(LanguageType(nTokenValue), wid)); } break; case RTF_LANGFE: - if( aPlainMap.nCJKLanguage ) + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_CJK_LANGUAGE]) { - pSet->Put( SvxLanguageItem( LanguageType(nTokenValue), - aPlainMap.nCJKLanguage )); + pSet->Put(SvxLanguageItem(LanguageType(nTokenValue), wid)); } break; case RTF_ALANG: @@ -970,17 +952,15 @@ ATTR_SETOVERLINE: bIsLeftToRightDef = true; break; case RTF_RTLPAR: - if (aPardMap.nDirection) + if (const TypedWhichId<SvxFrameDirectionItem> wid = aPardMap[SID_ATTR_FRAMEDIRECTION]) { - pSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_RL_TB, - aPardMap.nDirection)); + pSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_RL_TB, wid)); } break; case RTF_LTRPAR: - if (aPardMap.nDirection) + if (const TypedWhichId<SvxFrameDirectionItem> wid = aPardMap[SID_ATTR_FRAMEDIRECTION]) { - pSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB, - aPardMap.nDirection)); + pSet->Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB, wid)); } break; case RTF_LOCH: eCharType = LOW_CHARTYPE; break; @@ -998,15 +978,14 @@ ATTR_SETOVERLINE: case RTF_ACCCOMMA: eEmphasis = (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove); ATTR_SETEMPHASIS: - if( aPlainMap.nEmphasis ) + if (const TypedWhichId<SvxEmphasisMarkItem> wid = aPlainMap[SID_ATTR_CHAR_EMPHASISMARK]) { - pSet->Put( SvxEmphasisMarkItem( eEmphasis, - aPlainMap.nEmphasis )); + pSet->Put(SvxEmphasisMarkItem(eEmphasis, wid)); } break; case RTF_TWOINONE: - if( aPlainMap.nTwoLines ) + if (const TypedWhichId<SvxTwoLinesItem> wid = aPlainMap[SID_ATTR_CHAR_TWO_LINES]) { sal_Unicode cStt, cEnd; switch ( nTokenValue ) @@ -1018,50 +997,44 @@ ATTR_SETEMPHASIS: default: cStt = 0; cEnd = 0; break; } - pSet->Put( SvxTwoLinesItem( true, cStt, cEnd, - aPlainMap.nTwoLines )); + pSet->Put(SvxTwoLinesItem(true, cStt, cEnd, wid)); } break; case RTF_CHARSCALEX : - if (aPlainMap.nCharScaleX) + if (const TypedWhichId<SvxCharScaleWidthItem> wid = aPlainMap[SID_ATTR_CHAR_SCALEWIDTH]) { //i21372 if (nTokenValue < 1 || nTokenValue > 600) nTokenValue = 100; - pSet->Put( SvxCharScaleWidthItem( sal_uInt16(nTokenValue), - aPlainMap.nCharScaleX )); + pSet->Put(SvxCharScaleWidthItem(sal_uInt16(nTokenValue), wid)); } break; case RTF_HORZVERT: - if( aPlainMap.nHorzVert ) + if (const TypedWhichId<SvxCharRotateItem> wid = aPlainMap[SID_ATTR_CHAR_ROTATED]) { // RTF knows only 90deg - pSet->Put( SvxCharRotateItem( 900_deg10, 1 == nTokenValue, - aPlainMap.nHorzVert )); + pSet->Put(SvxCharRotateItem(900_deg10, 1 == nTokenValue, wid)); } break; case RTF_EMBO: - if (aPlainMap.nRelief) + if (const TypedWhichId<SvxCharReliefItem> wid = aPlainMap[SID_ATTR_CHAR_RELIEF]) { - pSet->Put(SvxCharReliefItem(FontRelief::Embossed, - aPlainMap.nRelief)); + pSet->Put(SvxCharReliefItem(FontRelief::Embossed, wid)); } break; case RTF_IMPR: - if (aPlainMap.nRelief) + if (const TypedWhichId<SvxCharReliefItem> wid = aPlainMap[SID_ATTR_CHAR_RELIEF]) { - pSet->Put(SvxCharReliefItem(FontRelief::Engraved, - aPlainMap.nRelief)); + pSet->Put(SvxCharReliefItem(FontRelief::Engraved, wid)); } break; case RTF_V: - if (aPlainMap.nHidden) + if (const TypedWhichId<SvxCharHiddenItem> wid = aPlainMap[SID_ATTR_CHAR_HIDDEN]) { - pSet->Put(SvxCharHiddenItem(nTokenValue != 0, - aPlainMap.nHidden)); + pSet->Put(SvxCharHiddenItem(nTokenValue != 0, wid)); } break; case RTF_CHBGFDIAG: @@ -1079,7 +1052,7 @@ ATTR_SETEMPHASIS: case RTF_CHCBPAT: case RTF_CHCFPAT: case RTF_CHSHDNG: - if( aPlainMap.nBgColor ) + if (aPlainMap[SID_ATTR_BRUSH_CHAR]) ReadBackgroundAttr( nToken, *pSet ); break; @@ -1111,9 +1084,8 @@ ATTR_SETEMPHASIS: // Recognize own auto-flags! nEsc = DFLT_ESC_AUTO_SUPER; - if( aPlainMap.nEscapement ) - pSet->Put( SvxEscapementItem( nEsc, nProp, - aPlainMap.nEscapement )); + if (const sal_uInt16 wid = aPlainMap[SID_ATTR_CHAR_ESCAPEMENT]) + pSet->Put(SvxEscapementItem(nEsc, nProp, wid)); } break; @@ -1121,10 +1093,10 @@ ATTR_SETEMPHASIS: { SvxHyphenZoneItem aHypenZone( (nTokenValue & 1) != 0, - aPardMap.nHyphenzone ); - aHypenZone.SetPageEnd((nTokenValue & 2) != 0); + aPardMap[SID_ATTR_PARA_HYPHENZONE]); + aHypenZone.SetKeep((nTokenValue & 2) != 0); - if( aPardMap.nHyphenzone && + if( aPardMap[SID_ATTR_PARA_HYPHENZONE] && RTF_HYPHLEAD == GetNextToken() && RTF_HYPHTRAIL == GetNextToken() && RTF_HYPHMAX == GetNextToken() ) @@ -1143,6 +1115,16 @@ ATTR_SETEMPHASIS: } break; + // We expect these to be preceded by a RTF_HYPHEN and + // so normally are handled by the RTF_HYPHEN case, but + // if they appear 'bare' in a document then safely skip + // them here + case RTF_HYPHLEAD: + case RTF_HYPHTRAIL: + case RTF_HYPHMAX: + SkipGroup(); + break; + case RTF_SHADOW: { bool bSkip = true; @@ -1164,9 +1146,8 @@ ATTR_SETEMPHASIS: Color aColor = GetColor( nCol ); - if( aPardMap.nShadow ) - pSet->Put( SvxShadowItem( aPardMap.nShadow, - &aColor, nDist, eSL ) ); + if (const TypedWhichId<SvxShadowItem> wid = aPardMap[SID_ATTR_BORDER_SHADOW]) + pSet->Put(SvxShadowItem(wid, &aColor, nDist, eSL)); bSkip = false; } while( false ); @@ -1266,7 +1247,7 @@ void SvxRTFParser::ReadTabAttr( int nToken, SfxItemSet& rSet ) bool bMethodOwnsToken = false; // #i52542# patch from cmc. // then read all the TabStops SvxTabStop aTabStop; - SvxTabStopItem aAttr( 0, 0, SvxTabAdjust::Default, aPardMap.nTabStop ); + SvxTabStopItem aAttr(0, 0, SvxTabAdjust::Default, aPardMap[SID_ATTR_TABSTOP]); bool bContinue = true; do { switch( nToken ) @@ -1372,15 +1353,15 @@ void SvxRTFParser::ReadBorderAttr( int nToken, SfxItemSet& rSet, bool bTableDef ) { // then read the border attribute - std::unique_ptr<SvxBoxItem> aAttr(std::make_unique<SvxBoxItem>(aPardMap.nBox)); + std::unique_ptr<SvxBoxItem> aAttr(std::make_unique<SvxBoxItem>(aPardMap[SID_ATTR_BORDER_OUTER])); const SfxPoolItem* pItem(nullptr); - if( SfxItemState::SET == rSet.GetItemState( aPardMap.nBox, false, &pItem ) ) + if (SfxItemState::SET == rSet.GetItemState(aPardMap[SID_ATTR_BORDER_OUTER], false, &pItem)) { aAttr.reset(static_cast<SvxBoxItem*>(pItem->Clone())); } - SvxBorderLine aBrd( nullptr, DEF_LINE_WIDTH_0 ); // Simple plain line + SvxBorderLine aBrd( nullptr, SvxBorderLineWidth::Hairline ); bool bContinue = true; int nBorderTyp = 0; @@ -1448,7 +1429,7 @@ void SvxRTFParser::ReadBorderAttr( int nToken, SfxItemSet& rSet, case RTF_BRDRHAIR: // hairline border { aBrd.SetBorderLineStyle( SvxBorderLineStyle::SOLID); - aBrd.SetWidth( DEF_LINE_WIDTH_0 ); + aBrd.SetWidth( SvxBorderLineWidth::Hairline ); } break; case RTF_BRDRDB: // Double border @@ -1500,7 +1481,7 @@ void SvxRTFParser::ReadBorderAttr( int nToken, SfxItemSet& rSet, break; case RTF_BRDRSH: // Shadowed border - rSet.Put( SvxShadowItem( aPardMap.nShadow, nullptr, 60 /*3pt*/, + rSet.Put( SvxShadowItem( aPardMap[SID_ATTR_BORDER_SHADOW], nullptr, 60 /*3pt*/, SvxShadowLocation::BottomRight ) ); break; @@ -1549,7 +1530,7 @@ void SvxRTFParser::ReadBorderAttr( int nToken, SfxItemSet& rSet, SetBorderLine( nBorderTyp, *aAttr, aBrd ); - rSet.Put( *aAttr ); + rSet.Put( std::move(aAttr) ); SkipToken(); } @@ -1569,8 +1550,8 @@ void SvxRTFParser::ReadBackgroundAttr( int nToken, SfxItemSet& rSet, sal_uInt8 nFillValue = 0; sal_uInt16 nWh = ( nToken & ~0xff ) == RTF_CHRFMT - ? aPlainMap.nBgColor - : aPardMap.nBrush; + ? aPlainMap[SID_ATTR_BRUSH_CHAR] + : aPardMap[SID_ATTR_BRUSH]; do { switch( nToken ) @@ -1700,7 +1681,7 @@ void SvxRTFParser::RTFPardPlain( bool const bPard, SfxItemSet** ppSet ) RTF_PLAIN != nLastToken && BRACELEFT != nLastToken ) { - if (pCurrent->aAttrSet.Count() || pCurrent->m_pChildList || pCurrent->nStyleNo) + if (pCurrent->aAttrSet.Count() || !pCurrent->maChildList.empty() || pCurrent->nStyleNo) { // open a new group auto xNew(std::make_unique<SvxRTFItemStackType>(*pCurrent, *mxInsertPosition, true)); @@ -1726,49 +1707,48 @@ void SvxRTFParser::RTFPardPlain( bool const bPard, SfxItemSet** ppSet ) ( pCurrent->aAttrSet.GetParent() || pCurrent->aAttrSet.Count() )) { const SfxPoolItem *pItem, *pDef; - const sal_uInt16* pPtr; - sal_uInt16 nCnt; + std::map<sal_uInt16, sal_uInt16>::const_iterator aIt; + std::map<sal_uInt16, sal_uInt16>::const_iterator aEnd; const SfxItemSet* pDfltSet = &GetRTFDefaults(); if( bPard ) { pCurrent->nStyleNo = 0; - pPtr = reinterpret_cast<sal_uInt16*>(&aPardMap); - nCnt = sizeof(aPardMap) / sizeof(sal_uInt16); + aIt = aPardMap.data.begin(); + aEnd = aPardMap.data.end(); } else { - pPtr = reinterpret_cast<sal_uInt16*>(&aPlainMap); - nCnt = sizeof(aPlainMap) / sizeof(sal_uInt16); + aIt = aPlainMap.data.begin(); + aEnd = aPlainMap.data.end(); } - for( sal_uInt16 n = 0; n < nCnt; ++n, ++pPtr ) + for (; aIt != aEnd; ++aIt) { + const sal_uInt16 wid = aIt->second; // Item set and different -> Set the Default Pool - if( !*pPtr ) + if (!wid) ; - else if (SfxItemPool::IsSlot(*pPtr)) - pCurrent->aAttrSet.ClearItem( *pPtr ); + else if (SfxItemPool::IsSlot(wid)) + pCurrent->aAttrSet.ClearItem(wid); else if( IsChkStyleAttr() ) - pCurrent->aAttrSet.Put( pDfltSet->Get( *pPtr ) ); + pCurrent->aAttrSet.Put(pDfltSet->Get(wid)); else if( !pCurrent->aAttrSet.GetParent() ) { - if( SfxItemState::SET == - pDfltSet->GetItemState( *pPtr, false, &pDef )) + if (SfxItemState::SET == pDfltSet->GetItemState(wid, false, &pDef)) pCurrent->aAttrSet.Put( *pDef ); else - pCurrent->aAttrSet.ClearItem( *pPtr ); + pCurrent->aAttrSet.ClearItem(wid); } else if( SfxItemState::SET == pCurrent->aAttrSet.GetParent()-> - GetItemState( *pPtr, true, &pItem ) && - *( pDef = &pDfltSet->Get( *pPtr )) != *pItem ) + GetItemState(wid, true, &pItem) && + *( pDef = &pDfltSet->Get(wid)) != *pItem ) pCurrent->aAttrSet.Put( *pDef ); else { - if( SfxItemState::SET == - pDfltSet->GetItemState( *pPtr, false, &pDef )) + if (SfxItemState::SET == pDfltSet->GetItemState(wid, false, &pDef)) pCurrent->aAttrSet.Put( *pDef ); else - pCurrent->aAttrSet.ClearItem( *pPtr ); + pCurrent->aAttrSet.ClearItem(wid); } } } @@ -1797,7 +1777,7 @@ void SvxRTFParser::SetDefault( int nToken, int nValue ) if( !bNewDoc ) return; - SfxItemSet aTmp( *pAttrPool, aWhichMap.data() ); + SfxItemSet aTmp(*pAttrPool, aWhichMap); bool bOldFlag = bIsLeftToRightDef; bIsLeftToRightDef = true; switch( nToken ) @@ -1831,7 +1811,7 @@ void SvxRTFParser::SetDefault( int nToken, int nValue ) break; case RTF_DEFTAB: - if( aPardMap.nTabStop ) + if (const sal_uInt16 wid = aPardMap[SID_ATTR_TABSTOP]) { // RTF defines 720 twips as default bIsSetDfltTab = true; @@ -1858,12 +1838,11 @@ void SvxRTFParser::SetDefault( int nToken, int nValue ) nTabCount = 1; // we want Defaulttabs - SvxTabStopItem aNewTab( nTabCount, sal_uInt16(nValue), - SvxTabAdjust::Default, aPardMap.nTabStop ); + SvxTabStopItem aNewTab(nTabCount, sal_uInt16(nValue), SvxTabAdjust::Default, wid); while( nTabCount ) const_cast<SvxTabStop&>(aNewTab[ --nTabCount ]).GetAdjustment() = SvxTabAdjust::Default; - pAttrPool->SetPoolDefaultItem( aNewTab ); + pAttrPool->SetUserDefaultItem( aNewTab ); } break; } @@ -1875,7 +1854,7 @@ void SvxRTFParser::SetDefault( int nToken, int nValue ) const SfxPoolItem* pItem = aIter.GetCurItem(); do { - pAttrPool->SetPoolDefaultItem( *pItem ); + pAttrPool->SetUserDefaultItem( *pItem ); pItem = aIter.NextItem(); } while (pItem); } diff --git a/editeng/source/rtf/svxrtf.cxx b/editeng/source/rtf/svxrtf.cxx index fe1f18adcb0d..f24b61b0b4f6 100644 --- a/editeng/source/rtf/svxrtf.cxx +++ b/editeng/source/rtf/svxrtf.cxx @@ -19,7 +19,7 @@ #include <memory> #include <queue> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <rtl/tencinfo.h> #include <svl/itemiter.hxx> #include <svl/whiter.hxx> @@ -27,6 +27,7 @@ #include <svl/itempool.hxx> #include <i18nlangtag/languagetag.hxx> #include <tools/debug.hxx> +#include <comphelper/configuration.hxx> #include <comphelper/string.hxx> @@ -59,8 +60,6 @@ static rtl_TextEncoding lcl_GetDefaultTextEncodingForRTF() SvxRTFParser::SvxRTFParser( SfxItemPool& rPool, SvStream& rIn ) : SvRTFParser( rIn, 5 ) - , aPlainMap(rPool) - , aPardMap(rPool) , pAttrPool( &rPool ) , nDfltFont( 0) , bNewDoc( true ) @@ -71,8 +70,11 @@ SvxRTFParser::SvxRTFParser( SfxItemPool& rPool, SvStream& rIn ) , bIsLeftToRightDef( true) , bIsInReadStyleTab( false) { - pDfltFont.reset( new vcl::Font ); + pDfltFont.emplace(); mxDefaultColor = Color(); + + // generate the correct WhichId table from the set WhichIds. + BuildWhichTable(); } SvxRTFParser::~SvxRTFParser() @@ -104,9 +106,6 @@ SvParserState SvxRTFParser::CallParser() bNewGroup = false; nDfltFont = 0; - // generate the correct WhichId table from the set WhichIds. - BuildWhichTable(); - return SvRTFParser::CallParser(); } @@ -167,7 +166,7 @@ void SvxRTFParser::NextToken( int nToken ) case RTF_LDBLQUOTE: cCh = 0x201C; goto INSINGLECHAR; case RTF_RDBLQUOTE: cCh = 0x201D; goto INSINGLECHAR; INSINGLECHAR: - aToken = OUString(cCh); + aToken = OUStringChar(cCh); [[fallthrough]]; // aToken is set as Text case RTF_TEXTTOKEN: { @@ -274,20 +273,19 @@ void SvxRTFParser::ReadStyleTable() int bSaveChkStyleAttr = bChkStyleAttr ? 1 : 0; sal_uInt16 nStyleNo = 0; bool bHasStyleNo = false; - int _nOpenBrakets = 1; // the first was already detected earlier!! - std::unique_ptr<SvxRTFStyleType> pStyle( - new SvxRTFStyleType( *pAttrPool, aWhichMap.data() )); - pStyle->aAttrSet.Put( GetRTFDefaults() ); + int _nOpenBrackets = 1; // the first was already detected earlier!! + std::optional<SvxRTFStyleType> xStyle(SvxRTFStyleType(*pAttrPool, aWhichMap)); + xStyle->aAttrSet.Put( GetRTFDefaults() ); bIsInReadStyleTab = true; bChkStyleAttr = false; // Do not check Attribute against the Styles - while( _nOpenBrakets && IsParserWorking() ) + while( _nOpenBrackets && IsParserWorking() ) { int nToken = GetNextToken(); switch( nToken ) { - case '}': if( --_nOpenBrakets && IsParserWorking() ) + case '}': if( --_nOpenBrackets && IsParserWorking() ) // Style has been completely read, // so this is still a stable status SaveState( RTF_STYLESHEET ); @@ -308,14 +306,14 @@ void SvxRTFParser::ReadStyleTable() eState = SvParserState::Error; break; } - ++_nOpenBrakets; + ++_nOpenBrackets; } break; - case RTF_SBASEDON: pStyle->nBasedOn = sal_uInt16(nTokenValue); break; + case RTF_SBASEDON: xStyle->nBasedOn = sal_uInt16(nTokenValue); break; case RTF_SNEXT: break; case RTF_OUTLINELEVEL: - case RTF_SOUTLVL: pStyle->nOutlineNo = sal_uInt8(nTokenValue); break; + case RTF_SOUTLVL: xStyle->nOutlineNo = sal_uInt8(nTokenValue); break; case RTF_S: nStyleNo = static_cast<short>(nTokenValue); bHasStyleNo = true; break; @@ -326,16 +324,17 @@ void SvxRTFParser::ReadStyleTable() case RTF_TEXTTOKEN: if (bHasStyleNo) { - pStyle->sName = DelCharAtEnd( aToken, ';' ); + DelCharAtEnd( aToken, ';' ); + xStyle->sName = aToken.toString(); if (!m_StyleTable.empty()) { m_StyleTable.erase(nStyleNo); } // All data from the font is available, so off to the table - m_StyleTable.insert(std::make_pair(nStyleNo, std::move(pStyle))); - pStyle.reset(new SvxRTFStyleType( *pAttrPool, aWhichMap.data() )); - pStyle->aAttrSet.Put( GetRTFDefaults() ); + m_StyleTable.emplace(nStyleNo, std::move(*xStyle)); + xStyle.emplace(*pAttrPool, aWhichMap); + xStyle->aAttrSet.Put( GetRTFDefaults() ); nStyleNo = 0; bHasStyleNo = false; } @@ -344,7 +343,7 @@ void SvxRTFParser::ReadStyleTable() switch( nToken & ~(0xff | RTF_SWGDEFS) ) { case RTF_PARFMT: // here are no SWGDEFS - ReadAttr( nToken, &pStyle->aAttrSet ); + ReadAttr( nToken, &xStyle->aAttrSet ); break; case RTF_CHRFMT: @@ -367,7 +366,7 @@ void SvxRTFParser::ReadStyleTable() ++nSkippedTokens; } } - ReadAttr( nToken, &pStyle->aAttrSet ); + ReadAttr( nToken, &xStyle->aAttrSet ); if (nSkippedTokens && m_nTokenIndex == nEnteringIndex - nSkippedTokens) { // we called SkipToken to go back one or two, but ReadAttrs @@ -383,7 +382,7 @@ void SvxRTFParser::ReadStyleTable() break; } } - pStyle.reset(); // Delete the Last Style + xStyle.reset(); // Delete the Last Style SkipToken(); // the closing brace is evaluated "above" // Flag back to old state @@ -441,7 +440,7 @@ void SvxRTFParser::ReadColorTable() void SvxRTFParser::ReadFontTable() { - int _nOpenBrakets = 1; // the first was already detected earlier!! + int _nOpenBrackets = 1; // the first was already detected earlier!! vcl::Font aFont; short nFontNo(0), nInsFontNo (0); OUString sAltNm, sFntNm; @@ -451,7 +450,7 @@ void SvxRTFParser::ReadFontTable() aFont.SetCharSet( nSystemChar ); SetEncoding( nSystemChar ); - while( _nOpenBrakets && IsParserWorking() ) + while( _nOpenBrackets && IsParserWorking() ) { bool bCheckNewFont = false; int nToken = GetNextToken(); @@ -461,7 +460,7 @@ void SvxRTFParser::ReadFontTable() bIsAltFntNm = false; // Style has been completely read, // so this is still a stable status - if( --_nOpenBrakets <= 1 && IsParserWorking() ) + if( --_nOpenBrackets <= 1 && IsParserWorking() ) SaveState( RTF_FONTTBL ); bCheckNewFont = true; nInsFontNo = nFontNo; @@ -484,7 +483,7 @@ void SvxRTFParser::ReadFontTable() eState = SvParserState::Error; break; } - ++_nOpenBrakets; + ++_nOpenBrackets; break; case RTF_FROMAN: aFont.SetFamily( FAMILY_ROMAN ); @@ -552,7 +551,7 @@ void SvxRTFParser::ReadFontTable() break; } - if( bCheckNewFont && 1 >= _nOpenBrakets && !sFntNm.isEmpty() ) // one font is ready + if( bCheckNewFont && 1 >= _nOpenBrackets && !sFntNm.isEmpty() ) // one font is ready { // All data from the font is available, so off to the table if (!sAltNm.isEmpty()) @@ -583,15 +582,11 @@ void SvxRTFParser::ClearAttrStack() aAttrStack.clear(); } -OUString& SvxRTFParser::DelCharAtEnd( OUString& rStr, const sal_Unicode cDel ) +void SvxRTFParser::DelCharAtEnd( OUStringBuffer& rStr, const sal_Unicode cDel ) { - if( !rStr.isEmpty() && ' ' == rStr[ 0 ]) - rStr = comphelper::string::stripStart(rStr, ' '); - if( !rStr.isEmpty() && ' ' == rStr[ rStr.getLength()-1 ]) - rStr = comphelper::string::stripEnd(rStr, ' '); + rStr.strip(' '); if( !rStr.isEmpty() && cDel == rStr[ rStr.getLength()-1 ]) - rStr = rStr.copy( 0, rStr.getLength()-1 ); - return rStr; + rStr.setLength( rStr.getLength()-1 ); } @@ -602,19 +597,19 @@ const vcl::Font& SvxRTFParser::GetFont( sal_uInt16 nId ) { return it->second; } - const SvxFontItem& rDfltFont = static_cast<const SvxFontItem&>( - pAttrPool->GetDefaultItem( aPlainMap.nFont )); + const SvxFontItem& rDfltFont = + pAttrPool->GetUserOrPoolDefaultItem(aPlainMap[SID_ATTR_CHAR_FONT]); pDfltFont->SetFamilyName( rDfltFont.GetStyleName() ); pDfltFont->SetFamily( rDfltFont.GetFamily() ); return *pDfltFont; } std::unique_ptr<SvxRTFItemStackType> SvxRTFItemStackType::createSvxRTFItemStackType( - SfxItemPool& rPool, const sal_uInt16* pWhichRange, const EditPosition& rEditPosition) + SfxItemPool& rPool, const WhichRangesContainer& pWhichRange, const EditPosition& rEditPosition) { struct MakeUniqueEnabler : public SvxRTFItemStackType { - MakeUniqueEnabler(SfxItemPool& rPool, const sal_uInt16* pWhichRange, const EditPosition& rEditPosition) + MakeUniqueEnabler(SfxItemPool& rPool, const WhichRangesContainer& pWhichRange, const EditPosition& rEditPosition) : SvxRTFItemStackType(rPool, pWhichRange, rEditPosition) { } @@ -629,10 +624,14 @@ SvxRTFItemStackType* SvxRTFParser::GetAttrSet_() if( pCurrent ) xNew = std::make_unique<SvxRTFItemStackType>(*pCurrent, *mxInsertPosition, false/*bCopyAttr*/); else - xNew = SvxRTFItemStackType::createSvxRTFItemStackType(*pAttrPool, aWhichMap.data(), *mxInsertPosition); + xNew = SvxRTFItemStackType::createSvxRTFItemStackType(*pAttrPool, aWhichMap, *mxInsertPosition); xNew->SetRTFDefaults( GetRTFDefaults() ); aAttrStack.push_back( std::move(xNew) ); + + if (aAttrStack.size() > 96 && comphelper::IsFuzzing()) + throw std::range_error("ecStackOverflow"); + bNewGroup = false; return aAttrStack.back().get(); } @@ -653,29 +652,29 @@ void SvxRTFParser::ClearStyleAttr_( SvxRTFItemStackType& rStkType ) for( sal_uInt16 nWhich = aIter.GetCurWhich(); nWhich; nWhich = aIter.NextWhich() ) { if (SfxItemPool::IsWhich(nWhich) && - SfxItemState::SET == rSet.GetItemState( nWhich, false, &pItem ) && - rPool.GetDefaultItem( nWhich ) == *pItem ) - rSet.ClearItem( nWhich ); // delete + SfxItemState::SET == aIter.GetItemState( false, &pItem ) && + rPool.GetUserOrPoolDefaultItem( nWhich ) == *pItem ) + aIter.ClearItem(); // delete } } else { // Delete all Attributes, which are already defined in the Style, // from the current AttrSet. - auto const& pStyle = m_StyleTable.find(rStkType.nStyleNo)->second; - SfxItemSet &rStyleSet = pStyle->aAttrSet; + auto & rStyle = m_StyleTable.find(rStkType.nStyleNo)->second; + SfxItemSet &rStyleSet = rStyle.aAttrSet; const SfxPoolItem* pSItem; for( sal_uInt16 nWhich = aIter.GetCurWhich(); nWhich; nWhich = aIter.NextWhich() ) { if( SfxItemState::SET == rStyleSet.GetItemState( nWhich, true, &pSItem )) { - if( SfxItemState::SET == rSet.GetItemState( nWhich, false, &pItem ) + if( SfxItemState::SET == aIter.GetItemState( false, &pItem ) && *pItem == *pSItem ) rSet.ClearItem( nWhich ); // delete } else if (SfxItemPool::IsWhich(nWhich) && - SfxItemState::SET == rSet.GetItemState( nWhich, false, &pItem ) && - rPool.GetDefaultItem( nWhich ) == *pItem ) + SfxItemState::SET == aIter.GetItemState( false, &pItem ) && + rPool.GetUserOrPoolDefaultItem( nWhich ) == *pItem ) rSet.ClearItem( nWhich ); // delete } } @@ -692,7 +691,7 @@ void SvxRTFParser::AttrGroupEnd() // process the current, delete from Stack do { // middle check loop sal_Int32 nOldSttNdIdx = pOld->mxStartNodeIdx->GetIdx(); - if (!pOld->m_pChildList && + if (pOld->maChildList.empty() && ((!pOld->aAttrSet.Count() && !pOld->nStyleNo ) || (nOldSttNdIdx == mxInsertPosition->GetNodeIdx() && pOld->nSttCnt == mxInsertPosition->GetCntIdx() ))) @@ -708,12 +707,12 @@ void SvxRTFParser::AttrGroupEnd() // process the current, delete from Stack if( SfxItemState::SET == pCurrent->aAttrSet.GetItemState( pItem->Which(), false, &pGet ) && *pItem == *pGet ) - pOld->aAttrSet.ClearItem( pItem->Which() ); + aIter.ClearItem(); pItem = aIter.NextItem(); } while (pItem); - if (!pOld->aAttrSet.Count() && !pOld->m_pChildList && + if (!pOld->aAttrSet.Count() && pOld->maChildList.empty() && !pOld->nStyleNo ) break; } @@ -750,10 +749,9 @@ void SvxRTFParser::AttrGroupEnd() // process the current, delete from Stack xNew->aAttrSet.SetParent( pOld->aAttrSet.GetParent() ); // Delete all paragraph attributes from xNew - for( sal_uInt16 n = 0; n < (sizeof(aPardMap) / sizeof(sal_uInt16)) && - xNew->aAttrSet.Count(); ++n ) - if( reinterpret_cast<sal_uInt16*>(&aPardMap)[n] ) - xNew->aAttrSet.ClearItem( reinterpret_cast<sal_uInt16*>(&aPardMap)[n] ); + for (const auto& pair : aPardMap.data) + if (sal_uInt16 wid = pair.second) + xNew->aAttrSet.ClearItem(wid); xNew->SetRTFDefaults( GetRTFDefaults() ); // Were there any? @@ -814,7 +812,7 @@ void SvxRTFParser::AttrGroupEnd() // process the current, delete from Stack pCurrent->Add(std::move(pOld)); // split up and create new entry, because it makes no sense // to create a "so long" depend list. Bug 95010 - if (bCrsrBack && 50 < pCurrent->m_pChildList->size()) + if (bCrsrBack && 50 < pCurrent->maChildList.size()) { // at the beginning of a paragraph? Move back one position MovePos(); @@ -868,15 +866,14 @@ void SvxRTFParser::SetAttrSet( SvxRTFItemStackType &rSet ) if( !bIsSetDfltTab ) SetDefault( RTF_DEFTAB, 720 ); - if (rSet.m_pChildList) + if (!rSet.maChildList.empty()) rSet.Compress( *this ); if( rSet.aAttrSet.Count() || rSet.nStyleNo ) SetAttrInDoc( rSet ); // then process all the children - if (rSet.m_pChildList) - for (size_t n = 0; n < rSet.m_pChildList->size(); ++n) - SetAttrSet( *(*rSet.m_pChildList)[ n ] ); + for (size_t n = 0; n < rSet.maChildList.size(); ++n) + SetAttrSet( *(rSet.maChildList[ n ]) ); } // Has no text been inserted yet? (SttPos from the top Stack entry!) @@ -894,27 +891,75 @@ void SvxRTFParser::SetAttrInDoc( SvxRTFItemStackType & ) void SvxRTFParser::BuildWhichTable() { - aWhichMap.clear(); - aWhichMap.push_back( 0 ); - - // Building a Which-Map 'rWhichMap' from an array of - // 'pWhichIds' from Which-Ids. It has the long 'nWhichIds'. - // The Which-Map is not going to be deleted. - ::BuildWhichTable( aWhichMap, reinterpret_cast<sal_uInt16*>(&aPardMap), sizeof(aPardMap) / sizeof(sal_uInt16) ); - ::BuildWhichTable( aWhichMap, reinterpret_cast<sal_uInt16*>(&aPlainMap), sizeof(aPlainMap) / sizeof(sal_uInt16) ); + aWhichMap.reset(); + + // Here are the IDs for all paragraph attributes, which can be detected by + // SvxParser and can be set in a SfxItemSet. The IDs are set correctly through + // the SlotIds from POOL. + static constexpr sal_uInt16 WIDS1[] { + SID_ATTR_PARA_LINESPACE, + SID_ATTR_PARA_ADJUST, + SID_ATTR_TABSTOP, + SID_ATTR_PARA_HYPHENZONE, + SID_ATTR_LRSPACE, + SID_ATTR_ULSPACE, + SID_ATTR_BRUSH, + SID_ATTR_BORDER_OUTER, + SID_ATTR_BORDER_SHADOW, + SID_ATTR_PARA_OUTLLEVEL, + SID_ATTR_PARA_SPLIT, + SID_ATTR_PARA_KEEP, + SID_PARA_VERTALIGN, + SID_ATTR_PARA_SCRIPTSPACE, + SID_ATTR_PARA_HANGPUNCTUATION, + SID_ATTR_PARA_FORBIDDEN_RULES, + SID_ATTR_FRAMEDIRECTION, + }; + for (sal_uInt16 nWid : WIDS1) + { + sal_uInt16 nTrueWid = pAttrPool->GetTrueWhichIDFromSlotID(nWid, false); + aPardMap.data[nWid] = nTrueWid; + if (nTrueWid == 0) + continue; + aWhichMap = aWhichMap.MergeRange(nTrueWid, nTrueWid); + } + + // Here are the IDs for all character attributes, which can be detected by + // SvxParser and can be set in a SfxItemSet. The IDs are set correctly through + // the SlotIds from POOL. + static constexpr sal_uInt16 WIDS[] { + SID_ATTR_CHAR_CASEMAP, SID_ATTR_BRUSH_CHAR, SID_ATTR_CHAR_COLOR, + SID_ATTR_CHAR_CONTOUR, SID_ATTR_CHAR_STRIKEOUT, SID_ATTR_CHAR_ESCAPEMENT, + SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_KERNING, + SID_ATTR_CHAR_LANGUAGE, SID_ATTR_CHAR_POSTURE, SID_ATTR_CHAR_SHADOWED, + SID_ATTR_CHAR_UNDERLINE, SID_ATTR_CHAR_OVERLINE, SID_ATTR_CHAR_WEIGHT, + SID_ATTR_CHAR_WORDLINEMODE, SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_CJK_FONT, + SID_ATTR_CHAR_CJK_FONTHEIGHT, sal_uInt16(SID_ATTR_CHAR_CJK_LANGUAGE), SID_ATTR_CHAR_CJK_POSTURE, + SID_ATTR_CHAR_CJK_WEIGHT, SID_ATTR_CHAR_CTL_FONT, SID_ATTR_CHAR_CTL_FONTHEIGHT, + SID_ATTR_CHAR_CTL_LANGUAGE, SID_ATTR_CHAR_CTL_POSTURE, SID_ATTR_CHAR_CTL_WEIGHT, + SID_ATTR_CHAR_EMPHASISMARK, SID_ATTR_CHAR_TWO_LINES, SID_ATTR_CHAR_SCALEWIDTH, + SID_ATTR_CHAR_ROTATED, SID_ATTR_CHAR_RELIEF, SID_ATTR_CHAR_HIDDEN, + }; + for (sal_uInt16 nWid : WIDS) + { + sal_uInt16 nTrueWid = pAttrPool->GetTrueWhichIDFromSlotID(nWid, false); + aPlainMap.data[nWid] = nTrueWid; + if (nTrueWid == 0) + continue; + aWhichMap = aWhichMap.MergeRange(nTrueWid, nTrueWid); + } } const SfxItemSet& SvxRTFParser::GetRTFDefaults() { if( !pRTFDefaults ) { - pRTFDefaults.reset( new SfxItemSet( *pAttrPool, aWhichMap.data() ) ); - sal_uInt16 nId; - if( 0 != ( nId = aPardMap.nScriptSpace )) + pRTFDefaults.reset(new SfxItemSet(*pAttrPool, aWhichMap)); + if (const sal_uInt16 nId = aPardMap[SID_ATTR_PARA_SCRIPTSPACE]) { SvxScriptSpaceItem aItem( false, nId ); if( bNewDoc ) - pAttrPool->SetPoolDefaultItem( aItem ); + pAttrPool->SetUserDefaultItem( aItem ); else pRTFDefaults->Put( aItem ); } @@ -923,7 +968,7 @@ const SfxItemSet& SvxRTFParser::GetRTFDefaults() } -SvxRTFStyleType::SvxRTFStyleType( SfxItemPool& rPool, const sal_uInt16* pWhichRange ) +SvxRTFStyleType::SvxRTFStyleType(SfxItemPool& rPool, const WhichRangesContainer& pWhichRange) : aAttrSet(rPool, pWhichRange) , nBasedOn(0) , nOutlineNo(sal_uInt8(-1)) // not set @@ -931,7 +976,7 @@ SvxRTFStyleType::SvxRTFStyleType( SfxItemPool& rPool, const sal_uInt16* pWhichRa } SvxRTFItemStackType::SvxRTFItemStackType( - SfxItemPool& rPool, const sal_uInt16* pWhichRange, + SfxItemPool& rPool, const WhichRangesContainer& pWhichRange, const EditPosition& rPos ) : aAttrSet( rPool, pWhichRange ) , mxStartNodeIdx(rPos.MakeNodeIdx()) @@ -976,7 +1021,7 @@ SvxRTFItemStackType::SvxRTFItemStackType( */ void SvxRTFItemStackType::DropChildList() { - if (!m_pChildList || m_pChildList->empty()) + if (maChildList.empty()) return; std::vector<SvxRTFItemStackType*> bfs; @@ -987,9 +1032,9 @@ void SvxRTFItemStackType::DropChildList() { auto* front = aQueue.front(); aQueue.pop(); - if (front->m_pChildList) + if (!front->maChildList.empty()) { - for (const auto& a : *front->m_pChildList) + for (const auto& a : front->maChildList) aQueue.push(a.get()); bfs.push_back(front); } @@ -998,7 +1043,7 @@ void SvxRTFItemStackType::DropChildList() for (auto it = bfs.rbegin(); it != bfs.rend(); ++it) { SvxRTFItemStackType* pNode = *it; - pNode->m_pChildList.reset(); + pNode->maChildList.clear(); } } @@ -1008,9 +1053,7 @@ SvxRTFItemStackType::~SvxRTFItemStackType() void SvxRTFItemStackType::Add(std::unique_ptr<SvxRTFItemStackType> pIns) { - if (!m_pChildList) - m_pChildList.reset( new SvxRTFItemStackList ); - m_pChildList->push_back(std::move(pIns)); + maChildList.push_back(std::move(pIns)); } void SvxRTFItemStackType::SetStartPos( const EditPosition& rPos ) @@ -1022,10 +1065,9 @@ void SvxRTFItemStackType::SetStartPos( const EditPosition& rPos ) void SvxRTFItemStackType::Compress( const SvxRTFParser& rParser ) { - ENSURE_OR_RETURN_VOID(m_pChildList, "Compress: no ChildList" ); - ENSURE_OR_RETURN_VOID(!m_pChildList->empty(), "Compress: ChildList empty"); + ENSURE_OR_RETURN_VOID(!maChildList.empty(), "Compress: ChildList empty"); - SvxRTFItemStackType* pTmp = (*m_pChildList)[0].get(); + SvxRTFItemStackType* pTmp = maChildList[0].get(); if( !pTmp->aAttrSet.Count() || mxStartNodeIdx->GetIdx() != pTmp->mxStartNodeIdx->GetIdx() || @@ -1036,10 +1078,10 @@ void SvxRTFItemStackType::Compress( const SvxRTFParser& rParser ) sal_Int32 nLastCnt = pTmp->nEndCnt; SfxItemSet aMrgSet( pTmp->aAttrSet ); - for (size_t n = 1; n < m_pChildList->size(); ++n) + for (size_t n = 1; n < maChildList.size(); ++n) { - pTmp = (*m_pChildList)[n].get(); - if (pTmp->m_pChildList) + pTmp = maChildList[n].get(); + if (!pTmp->maChildList.empty()) pTmp->Compress( rParser ); if( !pTmp->nSttCnt @@ -1048,10 +1090,10 @@ void SvxRTFItemStackType::Compress( const SvxRTFParser& rParser ) : ( pTmp->nSttCnt != nLastCnt || aLastNd.GetIdx() != pTmp->mxStartNodeIdx->GetIdx() )) { - while (++n < m_pChildList->size()) + while (++n < maChildList.size()) { - pTmp = (*m_pChildList)[n].get(); - if (pTmp->m_pChildList) + pTmp = maChildList[n].get(); + if (!pTmp->maChildList.empty()) pTmp->Compress( rParser ); } return; @@ -1067,7 +1109,7 @@ void SvxRTFItemStackType::Compress( const SvxRTFParser& rParser ) sal_uInt16 nWhich = pIterItem->Which(); if( SfxItemState::SET != pTmp->aAttrSet.GetItemState( nWhich, false, &pItem ) || *pItem != *pIterItem) - aMrgSet.ClearItem( nWhich ); + aIter.ClearItem(); pIterItem = aIter.NextItem(); } while(pIterItem); @@ -1086,24 +1128,20 @@ void SvxRTFItemStackType::Compress( const SvxRTFParser& rParser ) // It can be merged aAttrSet.Put( aMrgSet ); - size_t n = 0, nChildLen = m_pChildList->size(); + size_t n = 0, nChildLen = maChildList.size(); while (n < nChildLen) { - pTmp = (*m_pChildList)[n].get(); + pTmp = maChildList[n].get(); pTmp->aAttrSet.Differentiate( aMrgSet ); - if (!pTmp->m_pChildList && !pTmp->aAttrSet.Count() && !pTmp->nStyleNo) + if (pTmp->maChildList.empty() && !pTmp->aAttrSet.Count() && !pTmp->nStyleNo) { - m_pChildList->erase( m_pChildList->begin() + n ); + maChildList.erase( maChildList.begin() + n ); --nChildLen; continue; } ++n; } - if (m_pChildList->empty()) - { - m_pChildList.reset(); - } } void SvxRTFItemStackType::SetRTFDefaults( const SfxItemSet& rDefaults ) { @@ -1121,63 +1159,4 @@ void SvxRTFItemStackType::SetRTFDefaults( const SfxItemSet& rDefaults ) } } -RTFPlainAttrMapIds::RTFPlainAttrMapIds( const SfxItemPool& rPool ) -{ - nCaseMap = rPool.GetTrueWhich( SID_ATTR_CHAR_CASEMAP, false ); - nBgColor = rPool.GetTrueWhich( SID_ATTR_BRUSH_CHAR, false ); - nColor = rPool.GetTrueWhich( SID_ATTR_CHAR_COLOR, false ); - nContour = rPool.GetTrueWhich( SID_ATTR_CHAR_CONTOUR, false ); - nCrossedOut = rPool.GetTrueWhich( SID_ATTR_CHAR_STRIKEOUT, false ); - nEscapement = rPool.GetTrueWhich( SID_ATTR_CHAR_ESCAPEMENT, false ); - nFont = rPool.GetTrueWhich( SID_ATTR_CHAR_FONT, false ); - nFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_FONTHEIGHT, false ); - nKering = rPool.GetTrueWhich( SID_ATTR_CHAR_KERNING, false ); - nLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_LANGUAGE, false ); - nPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_POSTURE, false ); - nShadowed = rPool.GetTrueWhich( SID_ATTR_CHAR_SHADOWED, false ); - nUnderline = rPool.GetTrueWhich( SID_ATTR_CHAR_UNDERLINE, false ); - nOverline = rPool.GetTrueWhich( SID_ATTR_CHAR_OVERLINE, false ); - nWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_WEIGHT, false ); - nWordlineMode = rPool.GetTrueWhich( SID_ATTR_CHAR_WORDLINEMODE, false ); - nAutoKerning = rPool.GetTrueWhich( SID_ATTR_CHAR_AUTOKERN, false ); - - nCJKFont = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONT, false ); - nCJKFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT, false ); - nCJKLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE, false ); - nCJKPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_POSTURE, false ); - nCJKWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT, false ); - nCTLFont = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONT, false ); - nCTLFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT, false ); - nCTLLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE, false ); - nCTLPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_POSTURE, false ); - nCTLWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT, false ); - nEmphasis = rPool.GetTrueWhich( SID_ATTR_CHAR_EMPHASISMARK, false ); - nTwoLines = rPool.GetTrueWhich( SID_ATTR_CHAR_TWO_LINES, false ); - nCharScaleX = rPool.GetTrueWhich( SID_ATTR_CHAR_SCALEWIDTH, false ); - nHorzVert = rPool.GetTrueWhich( SID_ATTR_CHAR_ROTATED, false ); - nRelief = rPool.GetTrueWhich( SID_ATTR_CHAR_RELIEF, false ); - nHidden = rPool.GetTrueWhich( SID_ATTR_CHAR_HIDDEN, false ); -} - -RTFPardAttrMapIds ::RTFPardAttrMapIds ( const SfxItemPool& rPool ) -{ - nLinespacing = rPool.GetTrueWhich( SID_ATTR_PARA_LINESPACE, false ); - nAdjust = rPool.GetTrueWhich( SID_ATTR_PARA_ADJUST, false ); - nTabStop = rPool.GetTrueWhich( SID_ATTR_TABSTOP, false ); - nHyphenzone = rPool.GetTrueWhich( SID_ATTR_PARA_HYPHENZONE, false ); - nLRSpace = rPool.GetTrueWhich( SID_ATTR_LRSPACE, false ); - nULSpace = rPool.GetTrueWhich( SID_ATTR_ULSPACE, false ); - nBrush = rPool.GetTrueWhich( SID_ATTR_BRUSH, false ); - nBox = rPool.GetTrueWhich( SID_ATTR_BORDER_OUTER, false ); - nShadow = rPool.GetTrueWhich( SID_ATTR_BORDER_SHADOW, false ); - nOutlineLvl = rPool.GetTrueWhich( SID_ATTR_PARA_OUTLLEVEL, false ); - nSplit = rPool.GetTrueWhich( SID_ATTR_PARA_SPLIT, false ); - nKeep = rPool.GetTrueWhich( SID_ATTR_PARA_KEEP, false ); - nFontAlign = rPool.GetTrueWhich( SID_PARA_VERTALIGN, false ); - nScriptSpace = rPool.GetTrueWhich( SID_ATTR_PARA_SCRIPTSPACE, false ); - nHangPunct = rPool.GetTrueWhich( SID_ATTR_PARA_HANGPUNCTUATION, false ); - nForbRule = rPool.GetTrueWhich( SID_ATTR_PARA_FORBIDDEN_RULES, false ); - nDirection = rPool.GetTrueWhich( SID_ATTR_FRAMEDIRECTION, false ); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/uno/UnoForbiddenCharsTable.cxx b/editeng/source/uno/UnoForbiddenCharsTable.cxx index 474180f2585d..5e77a9252fe0 100644 --- a/editeng/source/uno/UnoForbiddenCharsTable.cxx +++ b/editeng/source/uno/UnoForbiddenCharsTable.cxx @@ -23,6 +23,7 @@ #include <editeng/UnoForbiddenCharsTable.hxx> #include <editeng/forbiddencharacterstable.hxx> #include <i18nlangtag/languagetag.hxx> +#include <utility> #include <vcl/svapp.hxx> using namespace ::com::sun::star; @@ -32,8 +33,8 @@ using namespace ::com::sun::star::lang; using namespace ::com::sun::star::i18n; using namespace ::cppu; -SvxUnoForbiddenCharsTable::SvxUnoForbiddenCharsTable(std::shared_ptr<SvxForbiddenCharactersTable> const & xForbiddenChars) - : mxForbiddenChars(xForbiddenChars) +SvxUnoForbiddenCharsTable::SvxUnoForbiddenCharsTable(std::shared_ptr<SvxForbiddenCharactersTable> xForbiddenChars) + : mxForbiddenChars(std::move(xForbiddenChars)) { } diff --git a/editeng/source/uno/unoedprx.cxx b/editeng/source/uno/unoedprx.cxx index 8cf7d8e62417..20d5df281bce 100644 --- a/editeng/source/uno/unoedprx.cxx +++ b/editeng/source/uno/unoedprx.cxx @@ -52,9 +52,9 @@ public: mnEEIndex(0), mnFieldOffset(0), mnFieldLen(0), - mbInField(false), mnBulletOffset(0), mnBulletLen(0), + mbInField(false), mbInBullet(false) {}; // Get/Set current paragraph @@ -111,9 +111,9 @@ private: sal_Int32 mnEEIndex; sal_Int32 mnFieldOffset; sal_Int32 mnFieldLen; - bool mbInField; sal_Int32 mnBulletOffset; sal_Int32 mnBulletLen; + bool mbInField; bool mbInBullet; }; @@ -530,6 +530,20 @@ void SvxAccessibleTextAdapter::GetPortions( sal_Int32 nPara, std::vector<sal_Int 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"); @@ -613,11 +627,11 @@ SfxItemPool* SvxAccessibleTextAdapter::GetPool() const return mpTextForwarder->GetPool(); } -OUString SvxAccessibleTextAdapter::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor ) +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 ); + return mpTextForwarder->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle ); } void SvxAccessibleTextAdapter::FieldClicked( const SvxFieldItem& rField ) @@ -793,7 +807,7 @@ bool SvxAccessibleTextAdapter::GetIndexAtPoint( const Point& rPoint, sal_Int32& aBulletInfo.bVisible && aBulletInfo.nType != SVX_NUM_BITMAP ) { - if( aBulletInfo.aBounds.IsInside( rPoint) ) + if( aBulletInfo.aBounds.Contains( rPoint) ) { OutputDevice* pOutDev = GetRefDevice(); @@ -815,32 +829,30 @@ bool SvxAccessibleTextAdapter::GetIndexAtPoint( const Point& rPoint, sal_Int32& } } - if( aIndex.InField() ) - { - OutputDevice* pOutDev = GetRefDevice(); + if( !aIndex.InField() ) + return true; - DBG_ASSERT(pOutDev!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device"); + OutputDevice* pOutDev = GetRefDevice(); - if( !pOutDev ) - return false; + DBG_ASSERT(pOutDev!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device"); - ESelection aSelection = MakeEESelection( aIndex ); - SvxFont aFont = EditEngine::CreateSvxFontFromItemSet( mpTextForwarder->GetAttribs( aSelection ) ); - AccessibleStringWrap aStringWrap( *pOutDev, - aFont, - mpTextForwarder->GetText( aSelection ) ); + if( !pOutDev ) + return false; - tools::Rectangle aRect = mpTextForwarder->GetCharBounds( nPara, aIndex.GetEEIndex() ); - Point aPoint = rPoint; - aPoint.Move( -aRect.Left(), -aRect.Top() ); + ESelection aSelection = MakeEESelection( aIndex ); + SvxFont aFont = EditEngine::CreateSvxFontFromItemSet( mpTextForwarder->GetAttribs( aSelection ) ); + AccessibleStringWrap aStringWrap( *pOutDev, + aFont, + mpTextForwarder->GetText( aSelection ) ); - DBG_ASSERT(aIndex.GetIndex() + aStringWrap.GetIndexAtPoint( rPoint ) >= 0, - "SvxAccessibleTextIndex::SetIndex: index value overflow"); + tools::Rectangle aRect = mpTextForwarder->GetCharBounds( nPara, aIndex.GetEEIndex() ); + Point aPoint = rPoint; + aPoint.Move( -aRect.Left(), -aRect.Top() ); - nIndex = (aIndex.GetIndex() + aStringWrap.GetIndexAtPoint( aPoint )); - return true; - } + DBG_ASSERT(aIndex.GetIndex() + aStringWrap.GetIndexAtPoint( rPoint ) >= 0, + "SvxAccessibleTextIndex::SetIndex: index value overflow"); + nIndex = (aIndex.GetIndex() + aStringWrap.GetIndexAtPoint( aPoint )); return true; } @@ -1055,7 +1067,7 @@ bool SvxAccessibleTextAdapter::HaveTextBullet( sal_Int32 nPara ) const aBulletInfo.nType != SVX_NUM_BITMAP ); } -bool SvxAccessibleTextAdapter::IsEditable( const ESelection& rSel ) +bool SvxAccessibleTextAdapter::IsEditable( const ESelection& rSel ) const { SvxAccessibleTextIndex aStartIndex; SvxAccessibleTextIndex aEndIndex; diff --git a/editeng/source/uno/unofdesc.cxx b/editeng/source/uno/unofdesc.cxx index 0cfd7a710dcf..0022e16597af 100644 --- a/editeng/source/uno/unofdesc.cxx +++ b/editeng/source/uno/unofdesc.cxx @@ -192,12 +192,10 @@ void SvxUnoFontDescriptor::setPropertyToDefault( SfxItemSet& rSet ) uno::Any SvxUnoFontDescriptor::getPropertyDefault( SfxItemPool* pPool ) { - SfxItemSet aSet( - *pPool, - svl::Items< + SfxItemSetFixed< EE_CHAR_FONTINFO, EE_CHAR_FONTHEIGHT, EE_CHAR_WEIGHT, EE_CHAR_ITALIC, - EE_CHAR_WLM, EE_CHAR_WLM>{}); + EE_CHAR_WLM, EE_CHAR_WLM> aSet(*pPool); uno::Any aAny; @@ -210,13 +208,13 @@ uno::Any SvxUnoFontDescriptor::getPropertyDefault( SfxItemPool* pPool ) !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)); + aSet.Put(pPool->GetUserOrPoolDefaultItem(EE_CHAR_FONTINFO)); + aSet.Put(pPool->GetUserOrPoolDefaultItem(EE_CHAR_FONTHEIGHT)); + aSet.Put(pPool->GetUserOrPoolDefaultItem(EE_CHAR_ITALIC)); + aSet.Put(pPool->GetUserOrPoolDefaultItem(EE_CHAR_UNDERLINE)); + aSet.Put(pPool->GetUserOrPoolDefaultItem(EE_CHAR_WEIGHT)); + aSet.Put(pPool->GetUserOrPoolDefaultItem(EE_CHAR_STRIKEOUT)); + aSet.Put(pPool->GetUserOrPoolDefaultItem(EE_CHAR_WLM)); awt::FontDescriptor aDesc; diff --git a/editeng/source/uno/unofield.cxx b/editeng/source/uno/unofield.cxx index c2b0aa5bdd8d..6f2e84a9577d 100644 --- a/editeng/source/uno/unofield.cxx +++ b/editeng/source/uno/unofield.cxx @@ -17,8 +17,14 @@ * 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> @@ -71,73 +77,61 @@ static const SfxItemPropertySet* ImplGetFieldItemPropertySet( sal_Int32 mnId ) { static const SfxItemPropertyMapEntry aExDateTimeFieldPropertyMap_Impl[] = { - { u"" UNO_TC_PROP_DATE_TIME, WID_DATE, ::cppu::UnoType<util::DateTime>::get(), 0, 0 }, - { u"" UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 }, - { u"" UNO_TC_PROP_IS_DATE, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 }, - { u"" UNO_TC_PROP_NUMFORMAT, WID_INT32, ::cppu::UnoType<sal_Int32>::get(), 0, 0 }, - { u"", 0, css::uno::Type(), 0, 0 } + { 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[] = { - { u"" UNO_TC_PROP_IS_DATE, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 }, - { u"", 0, css::uno::Type(), 0, 0 } + { 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[] = { - - { u"" UNO_TC_PROP_URL_FORMAT, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, - { u"" UNO_TC_PROP_URL_REPRESENTATION, WID_STRING1, ::cppu::UnoType<OUString>::get(), 0, 0 }, - { u"" UNO_TC_PROP_URL_TARGET, WID_STRING2, ::cppu::UnoType<OUString>::get(), 0, 0 }, - { u"" UNO_TC_PROP_URL, WID_STRING3, ::cppu::UnoType<OUString>::get(), 0, 0 }, - { u"", 0, css::uno::Type(), 0, 0 } + { 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 SfxItemPropertyMapEntry aEmptyPropertyMap_Impl[] = - { - { u"", 0, css::uno::Type(), 0, 0 } - }; - static const SfxItemPropertySet aEmptyPropertySet_Impl(aEmptyPropertyMap_Impl); + static const SfxItemPropertySet aEmptyPropertySet_Impl({}); static const SfxItemPropertyMapEntry aExtFileFieldPropertyMap_Impl[] = { - { u"" UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 }, - { u"" UNO_TC_PROP_FILE_FORMAT, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, - { u"" UNO_TC_PROP_CURRENT_PRESENTATION, WID_STRING1, ::cppu::UnoType<OUString>::get(), 0, 0 }, - { u"", 0, css::uno::Type(), 0, 0 } + { 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[] = { - { u"" UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 }, - { u"" UNO_TC_PROP_CURRENT_PRESENTATION, WID_STRING1,::cppu::UnoType<OUString>::get(), 0, 0 }, - { u"" UNO_TC_PROP_AUTHOR_CONTENT, WID_STRING2,::cppu::UnoType<OUString>::get(), 0, 0 }, - { u"" UNO_TC_PROP_AUTHOR_FORMAT, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, - { u"" UNO_TC_PROP_AUTHOR_FULLNAME, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 }, - { u"", 0, css::uno::Type(), 0, 0 } + { 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[] = { - { u"" UNO_TC_PROP_MEASURE_KIND, WID_INT16, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, - { u"", 0, css::uno::Type(), 0, 0 } + { 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[] = { - { u"" UNO_TC_PROP_NAME, WID_STRING1, cppu::UnoType<OUString>::get(), 0, 0 }, - { u"" UNO_TC_PROP_CURRENT_PRESENTATION, WID_STRING2, cppu::UnoType<OUString>::get(), 0, 0 }, - { u"" UNO_TC_PROP_IS_FIXED, WID_BOOL1, cppu::UnoType<bool>::get(), 0, 0 }, - { u"" UNO_TC_PROP_NUMFORMAT, WID_INT32, cppu::UnoType<sal_Int32>::get(), 0, 0 }, - { u"" UNO_TC_PROP_IS_FIXED_LANGUAGE, WID_BOOL2, cppu::UnoType<bool>::get(), 0, 0 }, - { u"", 0, css::uno::Type(), 0, 0 } + { 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); @@ -229,21 +223,6 @@ static tools::Time setTime( util::DateTime const & rDate ) -const css::uno::Sequence< sal_Int8 > & SvxUnoTextField::getUnoTunnelId() noexcept -{ - static const UnoTunnelIdInit theSvxUnoTextFieldUnoTunnelId; - return theSvxUnoTextFieldUnoTunnelId.getSeq(); -} - -sal_Int64 SAL_CALL SvxUnoTextField::getSomething( const css::uno::Sequence< sal_Int8 >& rId ) -{ - if( isUnoTunnelId<SvxUnoTextField>(rId) ) - { - return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); - } - return 0; -} - SvxUnoTextField::SvxUnoTextField( sal_Int32 nServiceId ) noexcept : OComponentHelper( m_aMutex ) , mpPropSet(nullptr) @@ -310,9 +289,9 @@ SvxUnoTextField::SvxUnoTextField( sal_Int32 nServiceId ) noexcept } } -SvxUnoTextField::SvxUnoTextField( uno::Reference< text::XTextRange > const & xAnchor, const OUString& rPresentation, const SvxFieldData* pData ) noexcept +SvxUnoTextField::SvxUnoTextField( uno::Reference< text::XTextRange > xAnchor, const OUString& rPresentation, const SvxFieldData* pData ) noexcept : OComponentHelper( m_aMutex ) -, mxAnchor( xAnchor ) +, mxAnchor(std::move( xAnchor )) , mpPropSet(nullptr) , mnServiceId(text::textfield::Type::UNSPECIFIED) , mpImpl( new SvxUnoFieldData_Impl ) @@ -393,7 +372,7 @@ SvxUnoTextField::SvxUnoTextField( uno::Reference< text::XTextRange > const & xAn break; default: - SAL_WARN("editeng", "Id service unknown: " << mnServiceId); + SAL_INFO("editeng", "Id service unknown: " << mnServiceId); break; } } @@ -557,7 +536,6 @@ uno::Any SAL_CALL SvxUnoTextField::queryAggregation( const uno::Type & rType ) else QUERYINT( text::XTextContent ); else QUERYINT( text::XTextField ); else QUERYINT( lang::XServiceInfo ); - else QUERYINT( lang::XUnoTunnel ); else return OComponentHelper::queryAggregation( rType ); @@ -654,7 +632,7 @@ OUString SAL_CALL SvxUnoTextField::getPresentation( sal_Bool bShowCommand ) // Interface text::XTextContent void SAL_CALL SvxUnoTextField::attach( const uno::Reference< text::XTextRange >& xTextRange ) { - SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRange>( xTextRange ); + SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xTextRange ); if(pRange == nullptr) throw lang::IllegalArgumentException(); @@ -672,6 +650,7 @@ uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextField::getAnchor() void SAL_CALL SvxUnoTextField::dispose() { OComponentHelper::dispose(); + mxAnchor.clear(); } void SAL_CALL SvxUnoTextField::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) @@ -753,10 +732,10 @@ uno::Any SAL_CALL SvxUnoTextField::getPropertyValue( const OUString& PropertyNam SolarMutexGuard aGuard; if (PropertyName == UNO_TC_PROP_ANCHOR) - return uno::makeAny(mxAnchor); + return uno::Any(mxAnchor); if (PropertyName == UNO_TC_PROP_TEXTFIELD_TYPE) - return uno::makeAny(mnServiceId); + return uno::Any(mnServiceId); uno::Any aValue; @@ -897,63 +876,63 @@ sal_Bool SAL_CALL SvxUnoTextField::supportsService( const OUString& ServiceName return cppu::supportsService( this, ServiceName ); } -uno::Reference< uno::XInterface > SvxUnoTextCreateTextField( const OUString& ServiceSpecifier ) +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. - OUString aFieldType; - if( (ServiceSpecifier.startsWith( "com.sun.star.text.textfield.", &aFieldType )) || - (ServiceSpecifier.startsWith( "com.sun.star.text.TextField.", &aFieldType )) ) + 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 == "DateTime" ) + if ( aFieldType == u"DateTime" ) { nId = text::textfield::Type::DATE; } - else if ( aFieldType == "URL" ) + else if ( aFieldType == u"URL" ) { nId = text::textfield::Type::URL; } - else if ( aFieldType == "PageNumber" ) + else if ( aFieldType == u"PageNumber" ) { nId = text::textfield::Type::PAGE; } - else if ( aFieldType == "PageCount" ) + else if ( aFieldType == u"PageCount" ) { nId = text::textfield::Type::PAGES; } - else if ( aFieldType == "SheetName" ) + else if ( aFieldType == u"SheetName" ) { nId = text::textfield::Type::TABLE; } - else if ( aFieldType == "FileName" ) + else if ( aFieldType == u"FileName" ) { nId = text::textfield::Type::EXTENDED_FILE; } - else if (aFieldType == "docinfo.Title" || - aFieldType == "DocInfo.Title" ) + else if (aFieldType == u"docinfo.Title" || + aFieldType == u"DocInfo.Title" ) { nId = text::textfield::Type::DOCINFO_TITLE; } - else if ( aFieldType == "Author" ) + else if ( aFieldType == u"Author" ) { nId = text::textfield::Type::AUTHOR; } - else if ( aFieldType == "Measure" ) + else if ( aFieldType == u"Measure" ) { nId = text::textfield::Type::MEASURE; } - else if (aFieldType == "DocInfo.Custom") + else if (aFieldType == u"DocInfo.Custom") { nId = text::textfield::Type::DOCINFO_CUSTOM; } if (nId != text::textfield::Type::UNSPECIFIED) - xRet = static_cast<cppu::OWeakObject *>(new SvxUnoTextField( nId )); + xRet = getXWeak(new SvxUnoTextField( nId )); } return xRet; diff --git a/editeng/source/uno/unofored.cxx b/editeng/source/uno/unofored.cxx index de8cab5ef060..fa2fa96118bf 100644 --- a/editeng/source/uno/unofored.cxx +++ b/editeng/source/uno/unofored.cxx @@ -124,6 +124,20 @@ void SvxEditEngineForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32 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 ); @@ -148,12 +162,12 @@ bool SvxEditEngineForwarder::IsValid() const { // cannot reliably query EditEngine state // while in the middle of an update - return rEditEngine.GetUpdateMode(); + return rEditEngine.IsUpdateLayout(); } -OUString SvxEditEngineForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor ) +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 ); + return rEditEngine.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle ); } void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem& rField ) @@ -214,7 +228,7 @@ SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ES { // ... and its different to this one than the state is don't care if(*pParaItem != *(attrib.pAttr)) - return SfxItemState::DONTCARE; + return SfxItemState::INVALID; } else pParaItem = attrib.pAttr; @@ -234,7 +248,7 @@ SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ES if( bEmpty ) eParaState = SfxItemState::DEFAULT; else if( bGaps ) - eParaState = SfxItemState::DONTCARE; + eParaState = SfxItemState::INVALID; else eParaState = SfxItemState::SET; @@ -242,7 +256,7 @@ SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ES if( pLastItem ) { if( (pParaItem == nullptr) || (*pLastItem != *pParaItem) ) - return SfxItemState::DONTCARE; + return SfxItemState::INVALID; } else { @@ -267,7 +281,7 @@ SfxItemState SvxEditEngineForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 n LanguageType SvxEditEngineForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const { - return rEditEngine.GetLanguage(nPara, nIndex); + return rEditEngine.GetLanguage(nPara, nIndex).nLang; } sal_Int32 SvxEditEngineForwarder::GetFieldCount( sal_Int32 nPara ) const @@ -294,7 +308,7 @@ tools::Rectangle SvxEditEngineForwarder::GetCharBounds( sal_Int32 nPara, sal_Int tools::Long tmp = aSize.Width(); aSize.setWidth(aSize.Height()); aSize.setHeight(tmp); - bool bIsVertical( rEditEngine.IsVertical() ); + bool bIsVertical( rEditEngine.IsEffectivelyVertical() ); // #108900# Handle virtual position one-past-the end of the string if( nIndex >= rEditEngine.GetTextLen(nPara) ) @@ -338,17 +352,17 @@ tools::Rectangle SvxEditEngineForwarder::GetCharBounds( sal_Int32 nPara, sal_Int tools::Rectangle SvxEditEngineForwarder::GetParaBounds( sal_Int32 nPara ) const { const Point aPnt = rEditEngine.GetDocPosTopLeft( nPara ); - sal_uLong nWidth; - sal_uLong nHeight; + sal_uInt32 nWidth; + sal_uInt32 nHeight; - if( rEditEngine.IsVertical() ) + 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_uLong nTextWidth = rEditEngine.GetTextHeight(); + sal_uInt32 nTextWidth = rEditEngine.GetTextHeight(); return tools::Rectangle( nTextWidth - aPnt.Y() - nWidth, 0, nTextWidth - aPnt.Y(), nHeight ); } @@ -380,7 +394,7 @@ bool SvxEditEngineForwarder::GetIndexAtPoint( const Point& rPos, sal_Int32& nPar aSize.setHeight(tmp); Point aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos, aSize, - rEditEngine.IsVertical() )); + rEditEngine.IsEffectivelyVertical() )); EPosition aDocPos = rEditEngine.FindDocPosition( aEEPos ); diff --git a/editeng/source/uno/unofored_internal.hxx b/editeng/source/uno/unofored_internal.hxx index f58b8aa98b55..cadb19415951 100644 --- a/editeng/source/uno/unofored_internal.hxx +++ b/editeng/source/uno/unofored_internal.hxx @@ -20,6 +20,7 @@ #pragma once #include <editeng/editeng.hxx> +#include <svl/poolitem.hxx> SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ESelection& rSel, sal_uInt16 nWhich ); diff --git a/editeng/source/uno/unoforou.cxx b/editeng/source/uno/unoforou.cxx index 144126d25e08..8772ff9a77fa 100644 --- a/editeng/source/uno/unoforou.cxx +++ b/editeng/source/uno/unoforou.cxx @@ -94,18 +94,18 @@ static SfxItemSet ImplOutlinerForwarderGetAttribs( const ESelection& rSel, EditE SfxItemSet SvxOutlinerForwarder::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const { - if( mpAttribsCache && ( EditEngineAttribs::All == nOnlyHardAttrib ) ) + if( moAttribsCache && ( EditEngineAttribs::All == nOnlyHardAttrib ) ) { // have we the correct set in cache? if( maAttribCacheSelection == rSel ) { // yes! just return the cache - return *mpAttribsCache; + return *moAttribsCache; } else { // no, we need delete the old cache - mpAttribsCache.reset(); + moAttribsCache.reset(); } } @@ -117,7 +117,7 @@ SfxItemSet SvxOutlinerForwarder::GetAttribs( const ESelection& rSel, EditEngineA if( EditEngineAttribs::All == nOnlyHardAttrib ) { - mpAttribsCache.reset(new SfxItemSet( aSet )); + moAttribsCache.emplace( aSet ); maAttribCacheSelection = rSel; } @@ -130,31 +130,31 @@ SfxItemSet SvxOutlinerForwarder::GetAttribs( const ESelection& rSel, EditEngineA SfxItemSet SvxOutlinerForwarder::GetParaAttribs( sal_Int32 nPara ) const { - if( mpParaAttribsCache ) + if( moParaAttribsCache ) { // have we the correct set in cache? if( nPara == mnParaAttribsCache ) { // yes! just return the cache - return *mpParaAttribsCache; + return *moParaAttribsCache; } else { // no, we need delete the old cache - mpParaAttribsCache.reset(); + moParaAttribsCache.reset(); } } - mpParaAttribsCache.reset(new SfxItemSet( rOutliner.GetParaAttribs( nPara ) )); + moParaAttribsCache.emplace( rOutliner.GetParaAttribs( nPara ) ); mnParaAttribsCache = nPara; EditEngine& rEditEngine = const_cast<EditEngine&>(rOutliner.GetEditEngine()); SfxStyleSheet* pStyle = rEditEngine.GetStyleSheet( nPara ); if( pStyle ) - mpParaAttribsCache->SetParent( &(pStyle->GetItemSet() ) ); + moParaAttribsCache->SetParent( &(pStyle->GetItemSet() ) ); - return *mpParaAttribsCache; + return *moParaAttribsCache; } void SvxOutlinerForwarder::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) @@ -186,6 +186,20 @@ void SvxOutlinerForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& 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(); @@ -217,9 +231,9 @@ void SvxOutlinerForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelec rOutliner.QuickSetAttribs( rSet, rSel ); } -OUString SvxOutlinerForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor ) +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 ); + return rOutliner.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle ); } void SvxOutlinerForwarder::FieldClicked( const SvxFieldItem& /*rField*/ ) @@ -230,7 +244,7 @@ bool SvxOutlinerForwarder::IsValid() const { // cannot reliably query outliner state // while in the middle of an update - return rOutliner.GetUpdateMode(); + return rOutliner.IsUpdateLayout(); } SfxItemState SvxOutlinerForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const @@ -247,8 +261,8 @@ SfxItemState SvxOutlinerForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 nWh void SvxOutlinerForwarder::flushCache() { - mpAttribsCache.reset(); - mpParaAttribsCache.reset(); + moAttribsCache.reset(); + moParaAttribsCache.reset(); } LanguageType SvxOutlinerForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const @@ -541,7 +555,7 @@ void SvxOutlinerForwarder::CopyText(const SvxTextForwarder& rSource) const SvxOutlinerForwarder* pSourceForwarder = dynamic_cast< const SvxOutlinerForwarder* >( &rSource ); if( !pSourceForwarder ) return; - std::unique_ptr<OutlinerParaObject> pNewOutlinerParaObject = pSourceForwarder->rOutliner.CreateParaObject(); + std::optional<OutlinerParaObject> pNewOutlinerParaObject = pSourceForwarder->rOutliner.CreateParaObject(); rOutliner.SetText( *pNewOutlinerParaObject ); } diff --git a/editeng/source/uno/unoipset.cxx b/editeng/source/uno/unoipset.cxx index cdc1bac825df..8782217fd394 100644 --- a/editeng/source/uno/unoipset.cxx +++ b/editeng/source/uno/unoipset.cxx @@ -31,15 +31,7 @@ using namespace ::com::sun::star; -struct SvxIDPropertyCombine -{ - sal_uInt16 nWID; - sal_uInt8 memberId; - uno::Any aAny; -}; - - -SvxItemPropertySet::SvxItemPropertySet( const SfxItemPropertyMapEntry* pMap, SfxItemPool& rItemPool ) +SvxItemPropertySet::SvxItemPropertySet( std::span<const SfxItemPropertyMapEntry> pMap, SfxItemPool& rItemPool ) : m_aPropertyMap( pMap ), mrItemPool( rItemPool ) { @@ -48,35 +40,6 @@ SvxItemPropertySet::SvxItemPropertySet( const SfxItemPropertyMapEntry* pMap, Sfx SvxItemPropertySet::~SvxItemPropertySet() { - ClearAllUsrAny(); -} - - -uno::Any* SvxItemPropertySet::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 SvxItemPropertySet::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 SvxItemPropertySet::ClearAllUsrAny() -{ - aCombineList.clear(); } @@ -100,7 +63,7 @@ uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pM SfxItemPool* pPool = rSet.GetPool(); (void)rSet.GetItemState( pMap->nWID, bSearchInParent, &pItem ); if( nullptr == pItem && pPool ) - pItem = &(pPool->GetDefaultItem( pMap->nWID )); + pItem = &(pPool->GetUserOrPoolDefaultItem( pMap->nWID )); const MapUnit eMapUnit = pPool ? pPool->GetMetric(pMap->nWID) : MapUnit::Map100thMM; sal_uInt8 nMemberId = pMap->nMemberId; @@ -155,7 +118,7 @@ void SvxItemPropertySet::setPropertyValue( const SfxItemPropertyMapEntry* pMap, return; } - pItem = &pPool->GetDefaultItem( pMap->nWID ); + pItem = &pPool->GetUserOrPoolDefaultItem( pMap->nWID ); } uno::Any aValue(rVal); @@ -179,15 +142,15 @@ void SvxItemPropertySet::setPropertyValue( const SfxItemPropertyMapEntry* pMap, { // Set new item in item set pNewItem->SetWhich(pMap->nWID); - rSet.Put(*pNewItem); + rSet.Put(std::move(pNewItem)); } } -uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pMap ) const +uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pMap, SvxItemPropertySetUsrAnys& rAnys ) const { // Already entered a value? Then finish quickly - uno::Any* pUsrAny = GetUsrAnyForID(*pMap); + uno::Any* pUsrAny = rAnys.GetUsrAnyForID(*pMap); if(pUsrAny) return *pUsrAny; @@ -197,13 +160,13 @@ uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pM if( eMapUnit == MapUnit::Map100thMM ) nMemberId &= (~CONVERT_TWIPS); uno::Any aVal; - SfxItemSet aSet( mrItemPool, {{pMap->nWID, pMap->nWID}}); + 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)); + aSet.Put(mrItemPool.GetUserOrPoolDefaultItem(pMap->nWID)); } if(aSet.Count()) @@ -213,7 +176,7 @@ uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pM if(eState >= SfxItemState::DEFAULT && pItem) { pItem->QueryValue( aVal, nMemberId ); - const_cast<SvxItemPropertySet*>(this)->AddUsrAnyForID(aVal, *pMap); + rAnys.AddUsrAnyForID(aVal, *pMap); } } @@ -236,11 +199,11 @@ uno::Any SvxItemPropertySet::getPropertyValue( const SfxItemPropertyMapEntry* pM } -void SvxItemPropertySet::setPropertyValue( const SfxItemPropertyMapEntry* pMap, const uno::Any& rVal ) const +void SvxItemPropertySet::setPropertyValue( const SfxItemPropertyMapEntry* pMap, const uno::Any& rVal, SvxItemPropertySetUsrAnys& rAnys ) { - uno::Any* pUsrAny = GetUsrAnyForID(*pMap); + uno::Any* pUsrAny = rAnys.GetUsrAnyForID(*pMap); if(!pUsrAny) - const_cast<SvxItemPropertySet*>(this)->AddUsrAnyForID(rVal, *pMap); + rAnys.AddUsrAnyForID(rVal, *pMap); else *pUsrAny = rVal; } @@ -335,4 +298,36 @@ void SvxUnoConvertFromMM( const MapUnit eDestinationMapUnit, uno::Any & rMetric } } +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 index 9f861b7f9c2a..8a5518567053 100644 --- a/editeng/source/uno/unonrule.cxx +++ b/editeng/source/uno/unonrule.cxx @@ -28,6 +28,7 @@ #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> @@ -41,7 +42,6 @@ #include <editeng/unofdesc.hxx> #include <editeng/unonrule.hxx> #include <editeng/editids.hrc> -#include <editeng/numdef.hxx> #include <o3tl/enumarray.hxx> #include <o3tl/temporary.hxx> #include <memory> @@ -50,7 +50,6 @@ using ::com::sun::star::util::XCloneable; using ::com::sun::star::ucb::XAnyCompare; -using namespace ::std; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; @@ -67,7 +66,7 @@ const SvxAdjust aUnoToSvxAdjust[] = SvxAdjust::Block }; -const o3tl::enumarray<SvxAdjust, unsigned short> aSvxToUnoAdjust +const o3tl::enumarray<SvxAdjust, sal_Int16> aSvxToUnoAdjust { text::HoriOrientation::LEFT, text::HoriOrientation::RIGHT, @@ -89,10 +88,8 @@ static unsigned short ConvertUnoAdjust( SvxAdjust eAdjust ) return aSvxToUnoAdjust[eAdjust]; } -UNO3_GETIMPLEMENTATION_IMPL( SvxUnoNumberingRules ); - -SvxUnoNumberingRules::SvxUnoNumberingRules(const SvxNumRule& rRule) -: maRule( rRule ) +SvxUnoNumberingRules::SvxUnoNumberingRules(SvxNumRule aRule) +: maRule(std::move( aRule )) { } @@ -183,26 +180,23 @@ Sequence<beans::PropertyValue> SvxUnoNumberingRules::getNumberingRuleByIndex(sal 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; + pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_NUMBERINGTYPE, -1, aVal, beans::PropertyState_DIRECT_VALUE); } { SvxAdjust eAdj = rFmt.GetNumAdjust(); aVal <<= ConvertUnoAdjust(eAdj); - pArray[nIdx++] = beans::PropertyValue( UNO_NAME_NRULE_ADJUST, -1, aVal, beans::PropertyState_DIRECT_VALUE); + 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; + pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_PREFIX, -1, aVal, beans::PropertyState_DIRECT_VALUE); } { aVal <<= rFmt.GetSuffix(); - beans::PropertyValue aSuffixProp( UNO_NAME_NRULE_SUFFIX, -1, aVal, beans::PropertyState_DIRECT_VALUE); - pArray[nIdx++] = aSuffixProp; + pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_SUFFIX, -1, aVal, beans::PropertyState_DIRECT_VALUE); } if(SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType()) @@ -210,8 +204,7 @@ Sequence<beans::PropertyValue> SvxUnoNumberingRules::getNumberingRuleByIndex(sal sal_UCS4 nCode = rFmt.GetBulletChar(); OUString aStr( &nCode, 1 ); aVal <<= aStr; - beans::PropertyValue aBulletProp( "BulletChar", -1, aVal, beans::PropertyState_DIRECT_VALUE); - pArray[nIdx++] = aBulletProp; + pArray[nIdx++] = beans::PropertyValue("BulletChar", -1, aVal, beans::PropertyState_DIRECT_VALUE); } if( rFmt.GetBulletFont() ) @@ -219,7 +212,7 @@ Sequence<beans::PropertyValue> SvxUnoNumberingRules::getNumberingRuleByIndex(sal 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); + pArray[nIdx++] = beans::PropertyValue(UNO_NAME_NRULE_BULLET_FONT, -1, aVal, beans::PropertyState_DIRECT_VALUE); } { @@ -232,8 +225,7 @@ Sequence<beans::PropertyValue> SvxUnoNumberingRules::getNumberingRuleByIndex(sal 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; + pArray[nIdx++] = beans::PropertyValue("GraphicBitmap", -1, aVal, beans::PropertyState_DIRECT_VALUE); } } @@ -241,8 +233,7 @@ Sequence<beans::PropertyValue> SvxUnoNumberingRules::getNumberingRuleByIndex(sal 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; + pArray[nIdx++] = beans::PropertyValue("GraphicSize", -1, aVal, beans::PropertyState_DIRECT_VALUE); } aVal <<= static_cast<sal_Int16>(rFmt.GetStart()); @@ -474,7 +465,7 @@ void SvxUnoNumberingRules::setNumberingRuleByIndex(const Sequence<beans::Propert const SvxNumRule& SvxGetNumRule( Reference< XIndexReplace > const & xRule ) { - SvxUnoNumberingRules* pRule = comphelper::getUnoTunnelImplementation<SvxUnoNumberingRules>( xRule ); + SvxUnoNumberingRules* pRule = dynamic_cast<SvxUnoNumberingRules*>( xRule.get() ); if( pRule == nullptr ) throw IllegalArgumentException(); @@ -488,7 +479,7 @@ css::uno::Reference< css::container::XIndexReplace > SvxCreateNumRule(const SvxN namespace { -class SvxUnoNumberingRulesCompare : public ::cppu::WeakAggImplHelper1< XAnyCompare > +class SvxUnoNumberingRulesCompare : public ::cppu::WeakImplHelper< XAnyCompare > { public: virtual sal_Int16 SAL_CALL compare( const Any& Any1, const Any& Any2 ) override; @@ -504,37 +495,34 @@ sal_Int16 SAL_CALL SvxUnoNumberingRulesCompare::compare( const Any& Any1, const sal_Int16 SvxUnoNumberingRules::Compare( const Any& Any1, const Any& Any2 ) { Reference< XIndexReplace > x1( Any1, UNO_QUERY ), x2( Any2, UNO_QUERY ); - if( x1.is() && x2.is() ) - { - if( x1.get() == x2.get() ) - return 0; + if( !x1 || !x2 ) + return -1; - SvxUnoNumberingRules* pRule1 = comphelper::getUnoTunnelImplementation<SvxUnoNumberingRules>( x1 ); - if( pRule1 ) - { - SvxUnoNumberingRules* pRule2 = comphelper::getUnoTunnelImplementation<SvxUnoNumberingRules>( x2 ); - if( pRule2 ) - { - const SvxNumRule& rRule1 = pRule1->getNumRule(); - const SvxNumRule& rRule2 = pRule2->getNumRule(); + if( x1.get() == x2.get() ) + return 0; - const sal_uInt16 nLevelCount1 = rRule1.GetLevelCount(); - const sal_uInt16 nLevelCount2 = rRule2.GetLevelCount(); + SvxUnoNumberingRules* pRule1 = dynamic_cast<SvxUnoNumberingRules*>( x1.get() ); + if( !pRule1 ) + return -1; + SvxUnoNumberingRules* pRule2 = dynamic_cast<SvxUnoNumberingRules*>( x2.get() ); + if( !pRule2 ) + return -1; - if( nLevelCount1 == 0 || nLevelCount2 == 0 ) - return -1; + const SvxNumRule& rRule1 = pRule1->getNumRule(); + const SvxNumRule& rRule2 = pRule2->getNumRule(); - for( sal_uInt16 i = 0; (i < nLevelCount1) && (i < nLevelCount2); i++ ) - { - if( rRule1.GetLevel(i) != rRule2.GetLevel(i) ) - return -1; - } - return 0; - } - } - } + const sal_uInt16 nLevelCount1 = rRule1.GetLevelCount(); + const sal_uInt16 nLevelCount2 = rRule2.GetLevelCount(); - return -1; + 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 diff --git a/editeng/source/uno/unotext.cxx b/editeng/source/uno/unotext.cxx index 20d901e0d300..b5f329e62050 100644 --- a/editeng/source/uno/unotext.cxx +++ b/editeng/source/uno/unotext.cxx @@ -28,7 +28,6 @@ #include <svl/itemset.hxx> #include <svl/itempool.hxx> #include <svl/eitem.hxx> -#include <rtl/instance.hxx> #include <tools/debug.hxx> #include <editeng/unoprnms.hxx> @@ -42,6 +41,7 @@ #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> @@ -71,7 +71,7 @@ ESelection toESelection(const text::TextRangeSelection& rSel) #define QUERYINT( xint ) \ if( rType == cppu::UnoType<xint>::get() ) \ - return uno::makeAny(uno::Reference< xint >(this)) + return uno::Any(uno::Reference< xint >(this)) const SvxItemPropertySet* ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() { @@ -79,7 +79,7 @@ const SvxItemPropertySet* ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() return &aTextCursorSvxPropertySet; } -const SfxItemPropertyMapEntry* ImplGetSvxTextPortionPropertyMap() +std::span<const SfxItemPropertyMapEntry> ImplGetSvxTextPortionPropertyMap() { // Propertymap for an Outliner Text static const SfxItemPropertyMapEntry aSvxTextPortionPropertyMap[] = @@ -88,11 +88,10 @@ const SfxItemPropertyMapEntry* ImplGetSvxTextPortionPropertyMap() SVX_UNOEDIT_FONT_PROPERTIES, SVX_UNOEDIT_OUTLINER_PROPERTIES, SVX_UNOEDIT_PARA_PROPERTIES, - { u"TextField", EE_FEATURE_FIELD, cppu::UnoType<text::XTextField>::get(), beans::PropertyAttribute::READONLY, 0 }, - { u"TextPortionType", WID_PORTIONTYPE, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 }, - { u"TextUserDefinedAttributes", EE_CHAR_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, - { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, - { u"", 0, css::uno::Type(), 0, 0 } + { 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; } @@ -108,7 +107,7 @@ static const SfxItemPropertySet* ImplGetSvxTextPortionSfxPropertySet() return &aSvxTextPortionSfxPropertySet; } -const SfxItemPropertyMapEntry* ImplGetSvxUnoOutlinerTextCursorPropertyMap() +std::span<const SfxItemPropertyMapEntry> ImplGetSvxUnoOutlinerTextCursorPropertyMap() { // Propertymap for an Outliner Text static const SfxItemPropertyMapEntry aSvxUnoOutlinerTextCursorPropertyMap[] = @@ -117,9 +116,8 @@ const SfxItemPropertyMapEntry* ImplGetSvxUnoOutlinerTextCursorPropertyMap() SVX_UNOEDIT_FONT_PROPERTIES, SVX_UNOEDIT_OUTLINER_PROPERTIES, SVX_UNOEDIT_PARA_PROPERTIES, - { u"TextUserDefinedAttributes", EE_CHAR_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, - { u"ParaUserDefinedAttributes", EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, - { u"", 0, css::uno::Type(), 0, 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 aSvxUnoOutlinerTextCursorPropertyMap; @@ -313,10 +311,10 @@ uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextRangeBase::getStart() { CheckSelection( maSelection, pForwarder ); - SvxUnoTextBase* pText = comphelper::getUnoTunnelImplementation<SvxUnoTextBase>( getText() ); + SvxUnoTextBase* pText = comphelper::getFromUnoTunnel<SvxUnoTextBase>( getText() ); if(pText == nullptr) - throw uno::RuntimeException(); + throw uno::RuntimeException("Failed to retrieve a valid text base object from the Uno Tunnel"); rtl::Reference<SvxUnoTextRange> pRange = new SvxUnoTextRange( *pText ); xRange = pRange; @@ -341,10 +339,10 @@ uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextRangeBase::getEnd() { CheckSelection( maSelection, pForwarder ); - SvxUnoTextBase* pText = comphelper::getUnoTunnelImplementation<SvxUnoTextBase>( getText() ); + SvxUnoTextBase* pText = comphelper::getFromUnoTunnel<SvxUnoTextBase>( getText() ); if(pText == nullptr) - throw uno::RuntimeException(); + throw uno::RuntimeException("Failed to retrieve a valid text base object from the Uno Tunnel"); rtl::Reference<SvxUnoTextRange> pNew = new SvxUnoTextRange( *pText ); xRet = pNew; @@ -433,7 +431,30 @@ void SvxUnoTextRangeBase::_setPropertyValue( const OUString& PropertyName, const ESelection aSel( GetSelection() ); bool bParaAttrib = (pMap->nWID >= EE_PARA_START) && ( pMap->nWID <= EE_PARA_END ); - if( nPara == -1 && !bParaAttrib ) + 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 @@ -509,7 +530,7 @@ bool SvxUnoTextRangeBase::SetPropertyValueHelper( const SfxItemPropertyMapEntry* return !aValue.hasValue() || ((aValue >>= xRule) && !xRule.is()); } - case WID_NUMLEVEL: + case EE_PARA_OUTLLEVEL: { SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr; if(pForwarder && pSelection) @@ -521,7 +542,8 @@ bool SvxUnoTextRangeBase::SetPropertyValueHelper( const SfxItemPropertyMapEntry* if(! pForwarder->SetDepth( pSelection->nStartPara, nLevel ) ) throw lang::IllegalArgumentException(); - return true; + // If valid, then not yet finished. Also needs to be added to paragraph props. + return nLevel < -1 || nLevel > 9; } } } @@ -583,7 +605,7 @@ uno::Any SAL_CALL SvxUnoTextRangeBase::getPropertyValue(const OUString& Property aSel.Start.PositionInParagraph = rSel.nStartPos; aSel.End.Paragraph = rSel.nEndPara; aSel.End.PositionInParagraph = rSel.nEndPos; - return uno::makeAny(aSel); + return uno::Any(aSel); } return _getPropertyValue( PropertyName ); @@ -601,16 +623,16 @@ uno::Any SvxUnoTextRangeBase::_getPropertyValue(const OUString& PropertyName, sa const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName ); if( pMap ) { - std::unique_ptr<SfxItemSet> pAttribs; + std::optional<SfxItemSet> oAttribs; if( nPara != -1 ) - pAttribs = pForwarder->GetParaAttribs( nPara ).Clone(); + oAttribs.emplace(pForwarder->GetParaAttribs( nPara ).CloneAsValue()); else - pAttribs = pForwarder->GetAttribs( GetSelection() ).Clone(); + oAttribs.emplace(pForwarder->GetAttribs( GetSelection() ).CloneAsValue()); // Replace Dontcare with Default, so that one always has a mirror - pAttribs->ClearInvalidItems(); + oAttribs->ClearInvalidItems(); - getPropertyValue( pMap, aAny, *pAttribs ); + getPropertyValue( pMap, aAny, *oAttribs ); return aAny; } @@ -633,9 +655,10 @@ void SvxUnoTextRangeBase::getPropertyValue( const SfxItemPropertyMapEntry* pMap, // 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 ) ); + 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; @@ -653,6 +676,12 @@ void SvxUnoTextRangeBase::getPropertyValue( const SfxItemPropertyMapEntry* pMap, } 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 ); @@ -675,18 +704,18 @@ bool SvxUnoTextRangeBase::GetPropertyValueHelper( SfxItemSet const & rSet, cons { SfxItemState eState = rSet.GetItemState( EE_PARA_NUMBULLET ); if( eState != SfxItemState::SET && eState != SfxItemState::DEFAULT) - throw uno::RuntimeException(); + throw uno::RuntimeException("Invalid item state for paragraph numbering/bullet. Expected SET or DEFAULT."); const SvxNumBulletItem* pBulletItem = rSet.GetItem( EE_PARA_NUMBULLET ); if( pBulletItem == nullptr ) - throw uno::RuntimeException(); + throw uno::RuntimeException("Unable to retrieve paragraph numbering/bullet item."); aAny <<= SvxCreateNumRule( pBulletItem->GetNumRule() ); } break; - case WID_NUMLEVEL: + case EE_PARA_OUTLLEVEL: { SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr; if(pForwarder && pSelection) @@ -747,6 +776,10 @@ void SAL_CALL SvxUnoTextRangeBase::setPropertyValues( const uno::Sequence< OUStr 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; @@ -770,11 +803,13 @@ void SvxUnoTextRangeBase::_setPropertyValues( const uno::Sequence< OUString >& a nEndPara = aSel.nEndPara; } - std::unique_ptr<SfxItemSet> pOldAttrSet; - std::unique_ptr<SfxItemSet> pNewAttrSet; + std::optional<SfxItemSet> pOldAttrSet; + std::optional<SfxItemSet> pNewAttrSet; + + std::optional<SfxItemSet> pOldParaSet; + std::optional<SfxItemSet> pNewParaSet; - std::unique_ptr<SfxItemSet> pOldParaSet; - std::unique_ptr<SfxItemSet> pNewParaSet; + std::optional<OUString> aStyleName; for( ; nCount; nCount--, pPropertyNames++, pValues++ ) { @@ -784,13 +819,16 @@ void SvxUnoTextRangeBase::_setPropertyValues( const uno::Sequence< OUString >& a { bool bParaAttrib = (pMap->nWID >= EE_PARA_START) && ( pMap->nWID <= EE_PARA_END ); - if( (nPara == -1) && !bParaAttrib ) + if (pMap->nWID == WID_PARASTYLENAME) { - if( nullptr == pNewAttrSet ) + aStyleName.emplace((*pValues).get<OUString>()); + } + else if( (nPara == -1) && !bParaAttrib ) + { + if( !pNewAttrSet ) { - const SfxItemSet aSet( pForwarder->GetAttribs( aSel ) ); - pOldAttrSet.reset(new SfxItemSet( aSet )); - pNewAttrSet.reset(new SfxItemSet( *pOldAttrSet->GetPool(), pOldAttrSet->GetRanges() )); + pOldAttrSet.emplace( pForwarder->GetAttribs( aSel ) ); + pNewAttrSet.emplace( *pOldAttrSet->GetPool(), pOldAttrSet->GetRanges() ); } setPropertyValue( pMap, *pValues, GetSelection(), *pOldAttrSet, *pNewAttrSet ); @@ -806,11 +844,11 @@ void SvxUnoTextRangeBase::_setPropertyValues( const uno::Sequence< OUString >& a } else { - if( nullptr == pNewParaSet ) + if( !pNewParaSet ) { const SfxItemSet & rSet = pForwarder->GetParaAttribs( nTempPara ); - pOldParaSet.reset(new SfxItemSet( rSet )); - pNewParaSet.reset(new SfxItemSet( *pOldParaSet->GetPool(), pOldParaSet->GetRanges() )); + pOldParaSet.emplace( rSet ); + pNewParaSet.emplace( *pOldParaSet->GetPool(), pOldParaSet->GetRanges() ); } setPropertyValue( pMap, *pValues, GetSelection(), *pOldParaSet, *pNewParaSet ); @@ -830,7 +868,7 @@ void SvxUnoTextRangeBase::_setPropertyValues( const uno::Sequence< OUString >& a bool bNeedsUpdate = false; - if( pNewParaSet ) + if( pNewParaSet || aStyleName ) { if( pNewParaSet->Count() ) { @@ -839,6 +877,8 @@ void SvxUnoTextRangeBase::_setPropertyValues( const uno::Sequence< OUString >& a SfxItemSet aSet( pForwarder->GetParaAttribs( nTempPara ) ); aSet.Put( *pNewParaSet ); pForwarder->SetParaAttribs( nTempPara, aSet ); + if (aStyleName) + pForwarder->SetStyleSheet(nTempPara, *aStyleName); nTempPara++; } bNeedsUpdate = true; @@ -880,13 +920,13 @@ uno::Sequence< uno::Any > SvxUnoTextRangeBase::_getPropertyValues( const uno::Se SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr; if( pForwarder ) { - std::unique_ptr<SfxItemSet> pAttribs; + std::optional<SfxItemSet> oAttribs; if( nPara != -1 ) - pAttribs = pForwarder->GetParaAttribs( nPara ).Clone(); + oAttribs.emplace(pForwarder->GetParaAttribs( nPara ).CloneAsValue()); else - pAttribs = pForwarder->GetAttribs( GetSelection() ).Clone(); + oAttribs.emplace(pForwarder->GetAttribs( GetSelection() ).CloneAsValue() ); - pAttribs->ClearInvalidItems(); + oAttribs->ClearInvalidItems(); const OUString* pPropertyNames = aPropertyNames.getConstArray(); uno::Any* pValues = aValues.getArray(); @@ -896,7 +936,7 @@ uno::Sequence< uno::Any > SvxUnoTextRangeBase::_getPropertyValues( const uno::Se const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( *pPropertyNames ); if( pMap ) { - getPropertyValue( pMap, *pValues, *pAttribs ); + getPropertyValue( pMap, *pValues, *oAttribs ); } } } @@ -950,8 +990,8 @@ beans::PropertyState SvxUnoTextRangeBase::_getPropertyState(const SfxItemPropert switch( eTempItemState ) { case SfxItemState::DISABLED: - case SfxItemState::DONTCARE: - eItemState = SfxItemState::DONTCARE; + case SfxItemState::INVALID: + eItemState = SfxItemState::INVALID; bItemStateSet = true; break; @@ -979,9 +1019,9 @@ beans::PropertyState SvxUnoTextRangeBase::_getPropertyState(const SfxItemPropert } break; - case WID_NUMLEVEL: case WID_NUMBERINGSTARTVALUE: case WID_PARAISNUMBERINGRESTART: + case WID_PARASTYLENAME: eItemState = SfxItemState::SET; bItemStateSet = true; break; @@ -1003,7 +1043,7 @@ beans::PropertyState SvxUnoTextRangeBase::_getPropertyState(const SfxItemPropert { switch( eItemState ) { - case SfxItemState::DONTCARE: + case SfxItemState::INVALID: case SfxItemState::DISABLED: return beans::PropertyState_AMBIGUOUS_VALUE; case SfxItemState::SET: @@ -1037,23 +1077,23 @@ uno::Sequence< beans::PropertyState > SvxUnoTextRangeBase::_getPropertyStates(co SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr; if( pForwarder ) { - std::unique_ptr<SfxItemSet> pSet; + std::optional<SfxItemSet> pSet; if( nPara != -1 ) { - pSet.reset(new SfxItemSet( pForwarder->GetParaAttribs( nPara ) )); + pSet.emplace( pForwarder->GetParaAttribs( nPara ) ); } else { ESelection aSel( GetSelection() ); CheckSelection( aSel, pForwarder ); - pSet.reset(new SfxItemSet( pForwarder->GetAttribs( aSel, EditEngineAttribs::OnlyHard ) )); + 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.get(), pMap, *pState++) ) + if( !_getOnePropertyStates(*pSet, pMap, *pState++) ) { throw beans::UnknownPropertyException(rName); } @@ -1063,96 +1103,150 @@ uno::Sequence< beans::PropertyState > SvxUnoTextRangeBase::_getPropertyStates(co return aRet; } -bool SvxUnoTextRangeBase::_getOnePropertyStates(const SfxItemSet* pSet, const SfxItemPropertyMapEntry* pMap, beans::PropertyState& rState) +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; - if(pSet && pMap) + switch( pMap->nWID ) { - SfxItemState eItemState = SfxItemState::DEFAULT; - bool bItemStateSet(false); - - switch( pMap->nWID ) - { - case WID_FONTDESC: + case WID_FONTDESC: + { + const sal_uInt16* pWhichId = aSvxUnoFontDescriptorWhichMap; + while( *pWhichId ) { - const sal_uInt16* pWhichId = aSvxUnoFontDescriptorWhichMap; - while( *pWhichId ) - { - const SfxItemState eTempItemState(pSet->GetItemState( *pWhichId )); + const SfxItemState eTempItemState(rSet.GetItemState( *pWhichId )); - switch( eTempItemState ) + switch( eTempItemState ) + { + case SfxItemState::DISABLED: + case SfxItemState::INVALID: + eItemState = SfxItemState::INVALID; + bItemStateSet = true; + break; + + case SfxItemState::DEFAULT: + if( !bItemStateSet ) { - case SfxItemState::DISABLED: - case SfxItemState::DONTCARE: - eItemState = SfxItemState::DONTCARE; + eItemState = SfxItemState::DEFAULT; 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; } + break; - pWhichId++; + case SfxItemState::SET: + if( !bItemStateSet ) + { + eItemState = SfxItemState::SET; + bItemStateSet = true; + } + break; + default: + bUnknownPropertyFound = true; + break; } + + pWhichId++; } - break; + } + break; - case WID_NUMLEVEL: - case WID_NUMBERINGSTARTVALUE: - case WID_PARAISNUMBERINGRESTART: - eItemState = SfxItemState::SET; - bItemStateSet = true; - break; + case WID_NUMBERINGSTARTVALUE: + case WID_PARAISNUMBERINGRESTART: + case WID_PARASTYLENAME: + eItemState = SfxItemState::SET; + bItemStateSet = true; + break; - default: - if(0 != pMap->nWID) - { - eItemState = pSet->GetItemState( pMap->nWID, false ); - bItemStateSet = true; - } - break; - } + default: + if(0 != pMap->nWID) + { + eItemState = rSet.GetItemState( pMap->nWID, false ); + bItemStateSet = true; + } + break; + } - if( bUnknownPropertyFound ) - return false; + if( bUnknownPropertyFound ) + return false; - if(bItemStateSet) + if(bItemStateSet) + { + if (pMap->nWID == EE_CHAR_COLOR) { - switch( eItemState ) + // 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) { - case SfxItemState::SET: - rState = beans::PropertyState_DIRECT_VALUE; + 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 SfxItemState::DEFAULT: - rState = beans::PropertyState_DEFAULT_VALUE; + 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; -// case SfxItemState::DONTCARE: -// case SfxItemState::DISABLED: - default: - rState = beans::PropertyState_AMBIGUOUS_VALUE; } } - else + + switch( eItemState ) { - rState = beans::PropertyState_AMBIGUOUS_VALUE; + case SfxItemState::SET: + rState = beans::PropertyState_DIRECT_VALUE; + break; + case SfxItemState::DEFAULT: + rState = beans::PropertyState_DEFAULT_VALUE; + break; +// case SfxItemState::INVALID: +// case SfxItemState::DISABLED: + default: + rState = beans::PropertyState_AMBIGUOUS_VALUE; } } + else + { + rState = beans::PropertyState_AMBIGUOUS_VALUE; + } return true; } @@ -1191,12 +1285,6 @@ void SvxUnoTextRangeBase::_setPropertyToDefault(SvxTextForwarder* pForwarder, co { SvxUnoFontDescriptor::setPropertyToDefault( aSet ); } - else if( pMap->nWID == WID_NUMLEVEL ) - { - // #101004# Call interface method instead of unsafe cast - pForwarder->SetDepth( maSelection.nStartPara, -1 ); - return; - } else if( pMap->nWID == WID_NUMBERINGSTARTVALUE ) { pForwarder->SetNumberingStartValue( maSelection.nStartPara, -1 ); @@ -1239,7 +1327,7 @@ uno::Any SAL_CALL SvxUnoTextRangeBase::getPropertyDefault( const OUString& aProp case WID_FONTDESC: return SvxUnoFontDescriptor::getPropertyDefault( pPool ); - case WID_NUMLEVEL: + case EE_PARA_OUTLLEVEL: { uno::Any aAny; return aAny; @@ -1256,8 +1344,8 @@ uno::Any SAL_CALL SvxUnoTextRangeBase::getPropertyDefault( const OUString& aProp // Get Default from ItemPool if(SfxItemPool::IsWhich(pMap->nWID)) { - SfxItemSet aSet( *pPool, {{pMap->nWID, pMap->nWID}}); - aSet.Put(pPool->GetDefaultItem(pMap->nWID)); + SfxItemSet aSet( *pPool, pMap->nWID, pMap->nWID ); + aSet.Put(pPool->GetUserOrPoolDefaultItem(pMap->nWID)); return SvxItemPropertySet::getPropertyValue(pMap, aSet, true, false ); } } @@ -1329,13 +1417,13 @@ bool SvxUnoTextRangeBase::IsCollapsed() noexcept maSelection.nStartPos == maSelection.nEndPos ); } -bool SvxUnoTextRangeBase::GoLeft(sal_Int16 nCount, bool Expand) noexcept +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_uInt16 nNewPos = maSelection.nEndPos; - sal_Int32 nNewPar = maSelection.nEndPara; + sal_Int32 nNewPos = maSelection.nEndPos; + sal_Int32 nNewPar = maSelection.nEndPara; bool bOk = true; SvxTextForwarder* pForwarder = nullptr; @@ -1367,43 +1455,44 @@ bool SvxUnoTextRangeBase::GoLeft(sal_Int16 nCount, bool Expand) noexcept return bOk; } -bool SvxUnoTextRangeBase::GoRight(sal_Int16 nCount, bool Expand) noexcept +bool SvxUnoTextRangeBase::GoRight(sal_Int32 nCount, bool Expand) noexcept { - SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr; - if( pForwarder ) - { - CheckSelection( maSelection, pForwarder ); + if (!mpEditSource) + return false; + SvxTextForwarder* pForwarder = mpEditSource->GetTextForwarder(); + if( !pForwarder ) + return false; - sal_Int32 nNewPos = maSelection.nEndPos + nCount; //! Overflow??? - sal_Int32 nNewPar = maSelection.nEndPara; + CheckSelection( maSelection, pForwarder ); - 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 ); - } - } + sal_Int32 nNewPos = maSelection.nEndPos + nCount; + sal_Int32 nNewPar = maSelection.nEndPara; - if (bOk) + 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 { - maSelection.nEndPara = nNewPar; - maSelection.nEndPos = nNewPos; + nNewPos -= nThisLen+1; + ++nNewPar; + nThisLen = pForwarder->GetTextLen( nNewPar ); } + } - if (!Expand) - CollapseToEnd(); - - return bOk; + if (bOk) + { + maSelection.nEndPara = nNewPar; + maSelection.nEndPos = nNewPos; } - return false; + + if (!Expand) + CollapseToEnd(); + + return bOk; } void SvxUnoTextRangeBase::GotoStart(bool Expand) noexcept @@ -1455,8 +1544,8 @@ uno::Sequence< OUString > SvxUnoTextRangeBase::getSupportedServiceNames_Static() // XTextRangeCompare sal_Int16 SAL_CALL SvxUnoTextRangeBase::compareRegionStarts( const uno::Reference< text::XTextRange >& xR1, const uno::Reference< text::XTextRange >& xR2 ) { - SvxUnoTextRangeBase* pR1 = comphelper::getUnoTunnelImplementation<SvxUnoTextRangeBase>( xR1 ); - SvxUnoTextRangeBase* pR2 = comphelper::getUnoTunnelImplementation<SvxUnoTextRangeBase>( xR2 ); + SvxUnoTextRangeBase* pR1 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR1 ); + SvxUnoTextRangeBase* pR2 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR2 ); if( (pR1 == nullptr) || (pR2 == nullptr) ) throw lang::IllegalArgumentException(); @@ -1479,8 +1568,8 @@ sal_Int16 SAL_CALL SvxUnoTextRangeBase::compareRegionStarts( const uno::Referenc sal_Int16 SAL_CALL SvxUnoTextRangeBase::compareRegionEnds( const uno::Reference< text::XTextRange >& xR1, const uno::Reference< text::XTextRange >& xR2 ) { - SvxUnoTextRangeBase* pR1 = comphelper::getUnoTunnelImplementation<SvxUnoTextRangeBase>( xR1 ); - SvxUnoTextRangeBase* pR2 = comphelper::getUnoTunnelImplementation<SvxUnoTextRangeBase>( xR2 ); + SvxUnoTextRangeBase* pR1 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR1 ); + SvxUnoTextRangeBase* pR2 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR2 ); if( (pR1 == nullptr) || (pR2 == nullptr) ) throw lang::IllegalArgumentException(); @@ -1516,13 +1605,13 @@ uno::Any SAL_CALL SvxUnoTextRange::queryAggregation( const uno::Type & rType ) { QUERYINT( text::XTextRange ); else if( rType == cppu::UnoType<beans::XMultiPropertyStates>::get()) - return uno::makeAny(uno::Reference< beans::XMultiPropertyStates >(this)); + return uno::Any(uno::Reference< beans::XMultiPropertyStates >(this)); else if( rType == cppu::UnoType<beans::XPropertySet>::get()) - return uno::makeAny(uno::Reference< beans::XPropertySet >(this)); + 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::makeAny(uno::Reference< beans::XMultiPropertySet >(this)); + return uno::Any(uno::Reference< beans::XMultiPropertySet >(this)); else QUERYINT( lang::XServiceInfo ); else QUERYINT( lang::XTypeProvider ); else QUERYINT( lang::XUnoTunnel ); @@ -1549,36 +1638,19 @@ void SAL_CALL SvxUnoTextRange::release() // XTypeProvider -namespace -{ - struct theSvxUnoTextRangeTypes : - public rtl::StaticWithInit<uno::Sequence<uno::Type>, theSvxUnoTextRangeTypes> - { - uno::Sequence<uno::Type> operator () () - { - uno::Sequence< uno::Type > aTypeSequence; - - aTypeSequence.realloc( 9 ); // !DANGER! keep this updated - uno::Type* pTypes = aTypeSequence.getArray(); - - *pTypes++ = cppu::UnoType<text::XTextRange>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertyStates>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertyState>::get(); - *pTypes++ = cppu::UnoType<lang::XServiceInfo>::get(); - *pTypes++ = cppu::UnoType<lang::XTypeProvider>::get(); - *pTypes++ = cppu::UnoType<lang::XUnoTunnel>::get(); - *pTypes++ = cppu::UnoType<text::XTextRangeCompare>::get(); - - return aTypeSequence; - } - }; -} - uno::Sequence< uno::Type > SAL_CALL SvxUnoTextRange::getTypes() { - return theSvxUnoTextRangeTypes::get(); + 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() @@ -1636,7 +1708,7 @@ 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::makeAny(uno::Reference< text::XTextRange >(static_cast<text::XText*>(this))); + return uno::Any(uno::Reference< text::XTextRange >(static_cast<text::XText*>(this))); QUERYINT(container::XEnumerationAccess ); QUERYINT( container::XElementAccess ); QUERYINT( beans::XMultiPropertyStates ); @@ -1658,42 +1730,25 @@ uno::Any SAL_CALL SvxUnoTextBase::queryAggregation( const uno::Type & rType ) // XTypeProvider -namespace -{ - struct theSvxUnoTextBaseTypes : - public rtl::StaticWithInit<uno::Sequence<uno::Type>, theSvxUnoTextBaseTypes> - { - uno::Sequence<uno::Type> operator () () - { - uno::Sequence< uno::Type > aTypeSequence; - - aTypeSequence.realloc( 15 ); // !DANGER! keep this updated - uno::Type* pTypes = aTypeSequence.getArray(); - - *pTypes++ = cppu::UnoType<text::XText>::get(); - *pTypes++ = cppu::UnoType<container::XEnumerationAccess>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertyStates>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertyState>::get(); - *pTypes++ = cppu::UnoType<text::XTextRangeMover>::get(); - *pTypes++ = cppu::UnoType<text::XTextAppend>::get(); - *pTypes++ = cppu::UnoType<text::XTextCopy>::get(); - *pTypes++ = cppu::UnoType<text::XParagraphAppend>::get(); - *pTypes++ = cppu::UnoType<text::XTextPortionAppend>::get(); - *pTypes++ = cppu::UnoType<lang::XServiceInfo>::get(); - *pTypes++ = cppu::UnoType<lang::XTypeProvider>::get(); - *pTypes++ = cppu::UnoType<lang::XUnoTunnel>::get(); - *pTypes++ = cppu::UnoType<text::XTextRangeCompare>::get(); - - return aTypeSequence; - } - }; -} - uno::Sequence< uno::Type > SAL_CALL SvxUnoTextBase::getTypes() { - return theSvxUnoTextBaseTypes::get(); + 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() @@ -1724,7 +1779,7 @@ uno::Reference< text::XTextCursor > SAL_CALL SvxUnoTextBase::createTextCursorByR if( aTextPosition.is() ) { - SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRangeBase>( aTextPosition ); + SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( aTextPosition ); if(pRange) xCursor = createTextCursorBySelection( pRange->GetSelection() ); } @@ -1739,14 +1794,7 @@ void SAL_CALL SvxUnoTextBase::insertString( const uno::Reference< text::XTextRan if( !xRange.is() ) return; - if (GetEditSource()) - { - ESelection aSelection; - ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() ); - SetSelection( aSelection ); - } - - SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRange>( xRange ); + SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange ); if(!pRange) return; @@ -1761,6 +1809,13 @@ void SAL_CALL SvxUnoTextBase::insertString( const uno::Reference< text::XTextRan 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 ) @@ -1786,7 +1841,7 @@ void SAL_CALL SvxUnoTextBase::insertControlCharacter( const uno::Reference< text } case text::ControlCharacter::LINE_BREAK: { - SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRange>( xRange ); + SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange ); if(pRange) { ESelection aRange = pRange->GetSelection(); @@ -1817,7 +1872,7 @@ void SAL_CALL SvxUnoTextBase::insertControlCharacter( const uno::Reference< text } case text::ControlCharacter::APPEND_PARAGRAPH: { - SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRange>( xRange ); + SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange ); if(pRange) { ESelection aRange = pRange->GetSelection(); @@ -1829,7 +1884,8 @@ void SAL_CALL SvxUnoTextBase::insertControlCharacter( const uno::Reference< text aRange.nEndPos = aRange.nStartPos; pRange->SetSelection( aRange ); - pRange->setString( "\x0D" ); + static constexpr OUStringLiteral CR = u"\x0D"; + pRange->setString( CR ); aRange.nStartPos = 0; aRange.nStartPara += 1; @@ -1874,14 +1930,14 @@ void SAL_CALL SvxUnoTextBase::insertTextContent( const uno::Reference< text::XTe GetEditSource()->UpdateData(); uno::Reference<beans::XPropertySet> xPropSetContent(xContent, uno::UNO_QUERY); - if (!xContent.is()) + if (!xPropSetContent.is()) throw lang::IllegalArgumentException(); - xPropSetContent->setPropertyValue(UNO_TC_PROP_ANCHOR, uno::makeAny(xRange)); + 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::makeAny(aSel)); + xPropSet->setPropertyValue(UNO_TR_PROP_SELECTION, uno::Any(aSel)); } void SAL_CALL SvxUnoTextBase::removeTextContent( const uno::Reference< text::XTextContent >& ) @@ -1929,6 +1985,10 @@ void SAL_CALL SvxUnoTextBase::setString( const OUString& aString ) 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; @@ -1973,14 +2033,14 @@ static void SvxPropertyValuesToItemSet( SfxItemSet &rItemSet, const uno::Sequence< beans::PropertyValue >& rPropertyValues, const SfxItemPropertySet *pPropSet, - SvxTextForwarder *pForwarder /*needed for WID_NUMLEVEL*/, - sal_Int32 nPara /*needed for WID_NUMLEVEL*/) + 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, static_cast < cppu::OWeakObject * > ( nullptr ) ); + 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) @@ -1988,8 +2048,8 @@ static void SvxPropertyValuesToItemSet( 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, static_cast < cppu::OWeakObject * > ( nullptr ) ); - //throw PropertyVetoException ("Property is read-only: " + rProp.Name, static_cast < cppu::OWeakObject * > ( 0 ) ); + throw uno::RuntimeException("Property is read-only: " + rProp.Name ); + //throw PropertyVetoException ("Property is read-only: " + rProp.Name ); if (pEntry->nWID == WID_FONTDESC) { @@ -1997,18 +2057,6 @@ static void SvxPropertyValuesToItemSet( if (rProp.Value >>= aDesc) SvxUnoFontDescriptor::FillItemSet( aDesc, rItemSet ); } - else if (pEntry->nWID == WID_NUMLEVEL) - { - if (pForwarder) - { - sal_Int16 nLevel = -1; - rProp.Value >>= nLevel; - - // #101004# Call interface method instead of unsafe cast - if (!pForwarder->SetDepth( nPara, nLevel )) - throw lang::IllegalArgumentException(); - } - } else if (pEntry->nWID == WID_NUMBERINGSTARTVALUE ) { if( pForwarder ) @@ -2074,11 +2122,43 @@ uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::finishParagraph( } uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::insertTextPortion( - const OUString& /*rText*/, - const uno::Sequence< beans::PropertyValue >& /*rCharAndParaProps*/, - const uno::Reference< text::XTextRange>& /*rTextRange*/ ) + 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; } @@ -2129,16 +2209,15 @@ void SvxUnoTextBase::copyText( SvxTextForwarder *pTextForwarder = pEditSource ? pEditSource->GetTextForwarder() : nullptr; if( !pTextForwarder ) return; - if( xUT.is() ) + if (auto pSource = comphelper::getFromUnoTunnel<SvxUnoTextBase>(xUT)) { - SvxUnoTextBase* pSource = reinterpret_cast<SvxUnoTextBase*>(sal::static_int_cast<sal_uIntPtr>( - xUT->getSomething( SvxUnoTextBase::getUnoTunnelId()))); SvxEditSource *pSourceEditSource = pSource->GetEditSource(); SvxTextForwarder *pSourceTextForwarder = pSourceEditSource ? pSourceEditSource->GetTextForwarder() : nullptr; if( pSourceTextForwarder ) { pTextForwarder->CopyText( *pSourceTextForwarder ); pEditSource->UpdateData(); + SetSelection(pSource->GetSelection()); } } else @@ -2171,20 +2250,14 @@ uno::Sequence< OUString > SAL_CALL SvxUnoTextBase::getSupportedServiceNames_Stat const uno::Sequence< sal_Int8 > & SvxUnoTextBase::getUnoTunnelId() noexcept { - static const UnoTunnelIdInit theSvxUnoTextBaseUnoTunnelId; + static const comphelper::UnoIdInit theSvxUnoTextBaseUnoTunnelId; return theSvxUnoTextBaseUnoTunnelId.getSeq(); } sal_Int64 SAL_CALL SvxUnoTextBase::getSomething( const uno::Sequence< sal_Int8 >& rId ) { - if( isUnoTunnelId<SvxUnoTextBase>(rId) ) - { - return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this)); - } - else - { - return SvxUnoTextRangeBase::getSomething( rId ); - } + return comphelper::getSomethingImpl( + rId, this, comphelper::FallbackToGetSomethingOf<SvxUnoTextRangeBase>{}); } SvxUnoText::SvxUnoText( const SvxItemPropertySet* _pSet ) noexcept @@ -2245,20 +2318,14 @@ uno::Sequence< sal_Int8 > SAL_CALL SvxUnoText::getImplementationId( ) const uno::Sequence< sal_Int8 > & SvxUnoText::getUnoTunnelId() noexcept { - static const UnoTunnelIdInit theSvxUnoTextUnoTunnelId; + static const comphelper::UnoIdInit theSvxUnoTextUnoTunnelId; return theSvxUnoTextUnoTunnelId.getSeq(); } sal_Int64 SAL_CALL SvxUnoText::getSomething( const uno::Sequence< sal_Int8 >& rId ) { - if( isUnoTunnelId<SvxUnoText>(rId) ) - { - return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this)); - } - else - { - return SvxUnoTextBase::getSomething( rId ); - } + return comphelper::getSomethingImpl(rId, this, + comphelper::FallbackToGetSomethingOf<SvxUnoTextBase>{}); } @@ -2320,6 +2387,15 @@ 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; @@ -2351,7 +2427,7 @@ void SvxDummyTextSource::QuickInsertLineBreak( const ESelection& ) { }; -OUString SvxDummyTextSource::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>& ) +OUString SvxDummyTextSource::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>&, std::optional<FontLineStyle>& ) { return OUString(); } diff --git a/editeng/source/uno/unotext2.cxx b/editeng/source/uno/unotext2.cxx index f7a2d462e3b3..54714027b388 100644 --- a/editeng/source/uno/unotext2.cxx +++ b/editeng/source/uno/unotext2.cxx @@ -24,7 +24,6 @@ #include <o3tl/safeint.hxx> #include <vcl/svapp.hxx> -#include <rtl/instance.hxx> #include <editeng/unotext.hxx> #include <comphelper/sequence.hxx> @@ -35,7 +34,7 @@ using namespace ::com::sun::star; #define QUERYINT( xint ) \ if( rType == cppu::UnoType<xint>::get() ) \ - return uno::makeAny(uno::Reference< xint >(this)) + return uno::Any(uno::Reference< xint >(this)) // SvxUnoTextContentEnumeration @@ -48,6 +47,9 @@ SvxUnoTextContentEnumeration::SvxUnoTextContentEnumeration( const SvxUnoTextBase 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() ); @@ -109,7 +111,7 @@ uno::Any SvxUnoTextContentEnumeration::nextElement() uno::Reference< text::XTextContent > xRef( maContents.at(mnNextParagraph) ); mnNextParagraph++; - return uno::makeAny( xRef ); + return uno::Any( xRef ); } @@ -119,7 +121,6 @@ SvxUnoTextContent::SvxUnoTextContent( const SvxUnoTextBase& rText, sal_Int32 nPa : SvxUnoTextRangeBase(rText) , mnParagraph(nPara) , mrParentText(rText) -, maDisposeListeners(maDisposeContainerMutex) , mbDisposing( false ) { mxParentText = const_cast<SvxUnoTextBase*>(&rText); @@ -132,7 +133,6 @@ SvxUnoTextContent::SvxUnoTextContent( const SvxUnoTextContent& rContent ) noexce , lang::XTypeProvider() , cppu::OWeakAggObject() , mrParentText(rContent.mrParentText) -, maDisposeListeners(maDisposeContainerMutex) , mbDisposing( false ) { mxParentText = rContent.mxParentText; @@ -181,38 +181,21 @@ void SAL_CALL SvxUnoTextContent::release() noexcept // XTypeProvider -namespace -{ - struct theSvxUnoTextContentTypes : - public rtl::StaticWithInit<uno::Sequence<uno::Type>, theSvxUnoTextContentTypes> - { - uno::Sequence<uno::Type> operator () () - { - uno::Sequence< uno::Type > aTypeSequence; - - aTypeSequence.realloc( 11 ); // !DANGER! keep this updated - uno::Type* pTypes = aTypeSequence.getArray(); - - *pTypes++ = cppu::UnoType<text::XTextRange>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertyStates>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertyState>::get(); - *pTypes++ = cppu::UnoType<text::XTextRangeCompare>::get(); - *pTypes++ = cppu::UnoType<text::XTextContent>::get(); - *pTypes++ = cppu::UnoType<container::XEnumerationAccess>::get(); - *pTypes++ = cppu::UnoType<lang::XServiceInfo>::get(); - *pTypes++ = cppu::UnoType<lang::XTypeProvider>::get(); - *pTypes++ = cppu::UnoType<lang::XUnoTunnel>::get(); - - return aTypeSequence; - } - }; -} - uno::Sequence< uno::Type > SAL_CALL SvxUnoTextContent::getTypes() { - return theSvxUnoTextContentTypes::get(); + 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() @@ -250,20 +233,28 @@ void SAL_CALL SvxUnoTextContent::dispose() lang::EventObject aEvt; aEvt.Source = *static_cast<OWeakAggObject*>(this); - maDisposeListeners.disposeAndClear(aEvt); + { + 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 ) { - maDisposeListeners.addInterface(xListener); + std::unique_lock aGuard(maDisposeContainerMutex); + maDisposeListeners.addInterface(aGuard, xListener); } void SAL_CALL SvxUnoTextContent::removeEventListener( const uno::Reference< lang::XEventListener >& aListener ) { - maDisposeListeners.removeInterface(aListener); + std::unique_lock aGuard(maDisposeContainerMutex); + maDisposeListeners.removeInterface(aGuard, aListener); } // XEnumerationAccess @@ -444,7 +435,7 @@ uno::Any SAL_CALL SvxUnoTextRangeEnumeration::nextElement() uno::Reference< text::XTextRange > xRange = maPortions.at(mnNextPortion); mnNextPortion++; - return uno::makeAny( xRange ); + return uno::Any( xRange ); } SvxUnoTextCursor::SvxUnoTextCursor( const SvxUnoTextBase& rText ) noexcept @@ -472,7 +463,7 @@ SvxUnoTextCursor::~SvxUnoTextCursor() noexcept uno::Any SAL_CALL SvxUnoTextCursor::queryAggregation( const uno::Type & rType ) { if( rType == cppu::UnoType<text::XTextRange>::get()) - return uno::makeAny(uno::Reference< text::XTextRange >(static_cast<SvxUnoTextRangeBase *>(this))); + return uno::Any(uno::Reference< text::XTextRange >(static_cast<SvxUnoTextRangeBase *>(this))); else QUERYINT( text::XTextCursor ); else QUERYINT( beans::XMultiPropertyStates ); else QUERYINT( beans::XPropertySet ); @@ -501,38 +492,21 @@ void SAL_CALL SvxUnoTextCursor::release() noexcept OWeakAggObject::release(); } -namespace -{ - struct theSvxUnoTextCursorTypes : - public rtl::StaticWithInit<uno::Sequence<uno::Type>, theSvxUnoTextCursorTypes> - { - uno::Sequence<uno::Type> operator () () - { - uno::Sequence< uno::Type > aTypeSequence; - - aTypeSequence.realloc( 10 ); // !DANGER! keep this updated - uno::Type* pTypes = aTypeSequence.getArray(); - - *pTypes++ = cppu::UnoType<text::XTextRange>::get(); - *pTypes++ = cppu::UnoType<text::XTextCursor>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertySet>::get(); - *pTypes++ = cppu::UnoType<beans::XMultiPropertyStates>::get(); - *pTypes++ = cppu::UnoType<beans::XPropertyState>::get(); - *pTypes++ = cppu::UnoType<text::XTextRangeCompare>::get(); - *pTypes++ = cppu::UnoType<lang::XServiceInfo>::get(); - *pTypes++ = cppu::UnoType<lang::XTypeProvider>::get(); - *pTypes++ = cppu::UnoType<lang::XUnoTunnel>::get(); - - return aTypeSequence; - } - }; -} - // XTypeProvider uno::Sequence< uno::Type > SAL_CALL SvxUnoTextCursor::getTypes() { - return theSvxUnoTextCursorTypes::get(); + 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() @@ -588,7 +562,7 @@ void SAL_CALL SvxUnoTextCursor::gotoRange( const uno::Reference< text::XTextRang if( !xRange.is() ) return; - SvxUnoTextRangeBase* pRange = comphelper::getUnoTunnelImplementation<SvxUnoTextRangeBase>( xRange ); + SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xRange ); if( !pRange ) return; diff --git a/editeng/source/uno/unoviwou.cxx b/editeng/source/uno/unoviwou.cxx index cbad84836610..19f38794e8c6 100644 --- a/editeng/source/uno/unoviwou.cxx +++ b/editeng/source/uno/unoviwou.cxx @@ -24,7 +24,7 @@ #include <editeng/outliner.hxx> SvxDrawOutlinerViewForwarder::SvxDrawOutlinerViewForwarder( OutlinerView& rOutl ) : - mrOutlinerView ( rOutl ), maTextShapeTopLeft() + mrOutlinerView ( rOutl ) { } diff --git a/editeng/source/xml/xmltxtexp.cxx b/editeng/source/xml/xmltxtexp.cxx index b6f3f5cf14b0..0ebb3819b350 100644 --- a/editeng/source/xml/xmltxtexp.cxx +++ b/editeng/source/xml/xmltxtexp.cxx @@ -31,7 +31,7 @@ #include <com/sun/star/uno/Sequence.hxx> #include <xmloff/xmlmetae.hxx> #include <comphelper/processfactory.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <unotools/streamwrap.hxx> #include <xmloff/xmlexp.hxx> #include <editeng/unoedsrc.hxx> @@ -48,9 +48,7 @@ using namespace com::sun::star; using namespace com::sun::star::container; -using namespace com::sun::star::document; using namespace com::sun::star::uno; -using namespace com::sun::star::awt; using namespace com::sun::star::lang; using namespace com::sun::star::xml::sax; using namespace cppu; @@ -135,12 +133,12 @@ uno::Reference< uno::XInterface > SAL_CALL SvxSimpleUnoModel::createInstance( co || aServiceSpecifier == "com.sun.star.text.TextField.DateTime" ) { - return static_cast<cppu::OWeakObject *>(new SvxUnoTextField( text::textfield::Type::DATE )); + return cppu::getXWeak(new SvxUnoTextField( text::textfield::Type::DATE )); } if( aServiceSpecifier == "com.sun.star.text.TextField.URL" ) { - return static_cast<cppu::OWeakObject *>(new SvxUnoTextField(text::textfield::Type::URL)); + return cppu::getXWeak(new SvxUnoTextField(text::textfield::Type::URL)); } return SvxUnoTextCreateTextField( aServiceSpecifier ); @@ -275,11 +273,10 @@ SvxXMLTextExportComponent::SvxXMLTextExportComponent( { SVX_UNOEDIT_CHAR_PROPERTIES, SVX_UNOEDIT_FONT_PROPERTIES, - { u"" UNO_NAME_NUMBERING_RULES, EE_PARA_NUMBULLET, cppu::UnoType<css::container::XIndexReplace>::get(), 0, 0 }, - { u"" UNO_NAME_NUMBERING, EE_PARA_BULLETSTATE,cppu::UnoType<bool>::get(), 0, 0 }, - { u"" UNO_NAME_NUMBERING_LEVEL, EE_PARA_OUTLLEVEL, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_NUMBERING_RULES, EE_PARA_NUMBULLET, cppu::UnoType<css::container::XIndexReplace>::get(), 0, 0 }, + { UNO_NAME_NUMBERING, EE_PARA_BULLETSTATE,cppu::UnoType<bool>::get(), 0, 0 }, + { UNO_NAME_NUMBERING_LEVEL, EE_PARA_OUTLLEVEL, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, SVX_UNOEDIT_PARA_PROPERTIES, - { u"", 0, css::uno::Type(), 0, 0 } }; static SvxItemPropertySet aSvxXMLTextExportComponentPropertySet( SvxXMLTextExportComponentPropertyMap, EditEngine::GetGlobalItemPool() ); @@ -305,7 +302,7 @@ void SvxWriteXML( EditEngine& rEditEngine, SvStream& rStream, const ESelection& uno::Reference<io::XOutputStream> xOut( new utl::OOutputStreamWrapper( rStream ) ); /* testcode - static const OUStringLiteral aURL( u"file:///e:/test.xml" ); + static constexpr OUStringLiteral aURL( u"file:///e:/test.xml" ); SvFileStream aStream(aURL, StreamMode::WRITE | StreamMode::TRUNC); xOut = new utl::OOutputStreamWrapper(aStream); */ diff --git a/editeng/source/xml/xmltxtimp.cxx b/editeng/source/xml/xmltxtimp.cxx index e45c505e1675..9d91124100a0 100644 --- a/editeng/source/xml/xmltxtimp.cxx +++ b/editeng/source/xml/xmltxtimp.cxx @@ -21,6 +21,7 @@ #include <comphelper/processfactory.hxx> #include <unotools/streamwrap.hxx> #include <svl/itemprop.hxx> +#include <utility> #include <xmloff/xmlimp.hxx> #include <xmloff/xmlictxt.hxx> #include <xmloff/xmltoken.hxx> @@ -37,9 +38,7 @@ #include <unomodel.hxx> using namespace com::sun::star; -using namespace com::sun::star::document; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::sax; using namespace com::sun::star::text; using namespace cppu; @@ -50,7 +49,7 @@ namespace { class SvxXMLTextImportContext : public SvXMLImportContext { public: - SvxXMLTextImportContext( SvXMLImport& rImport, const uno::Reference< XText >& xText ); + SvxXMLTextImportContext( SvXMLImport& rImport, uno::Reference< XText > xText ); virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 nElement, @@ -62,8 +61,8 @@ private: } -SvxXMLTextImportContext::SvxXMLTextImportContext( SvXMLImport& rImport, const uno::Reference< XText >& xText ) -: SvXMLImportContext( rImport ), mxText( xText ) +SvxXMLTextImportContext::SvxXMLTextImportContext( SvXMLImport& rImport, uno::Reference< XText > xText ) +: SvXMLImportContext( rImport ), mxText(std::move( xText )) { } @@ -93,7 +92,7 @@ class SvxXMLXTextImportComponent : public SvXMLImport public: SvxXMLXTextImportComponent( const css::uno::Reference< css::uno::XComponentContext >& rContext, - const uno::Reference< XText > & rText ); + uno::Reference< XText > xText ); virtual SvXMLImportContext* CreateFastContext(sal_Int32 nElement, const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& xAttrList ) override; @@ -120,9 +119,9 @@ SvXMLImportContext *SvxXMLXTextImportComponent::CreateFastContext( SvxXMLXTextImportComponent::SvxXMLXTextImportComponent( const css::uno::Reference< css::uno::XComponentContext >& xContext, - const uno::Reference< XText > & xText ) + uno::Reference< XText > xText ) : SvXMLImport(xContext, ""), - mxText( xText ) + mxText(std::move( xText )) { GetTextImport()->SetCursor( mxText->createTextCursor() ); SvXMLImport::setTargetDocument(new SvxSimpleUnoModel); @@ -137,11 +136,10 @@ EditPaM SvxReadXML( EditEngine& rEditEngine, SvStream& rStream, const ESelection SVX_UNOEDIT_CHAR_PROPERTIES, SVX_UNOEDIT_FONT_PROPERTIES, // bullets & numbering props, tdf#128046 - { u"" UNO_NAME_NUMBERING_RULES, EE_PARA_NUMBULLET, cppu::UnoType<css::container::XIndexReplace>::get(), 0, 0 }, - { u"" UNO_NAME_NUMBERING, EE_PARA_BULLETSTATE,cppu::UnoType<bool>::get(), 0, 0 }, - { u"" UNO_NAME_NUMBERING_LEVEL, EE_PARA_OUTLLEVEL, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, + { UNO_NAME_NUMBERING_RULES, EE_PARA_NUMBULLET, cppu::UnoType<css::container::XIndexReplace>::get(), 0, 0 }, + { UNO_NAME_NUMBERING, EE_PARA_BULLETSTATE,cppu::UnoType<bool>::get(), 0, 0 }, + { UNO_NAME_NUMBERING_LEVEL, EE_PARA_OUTLLEVEL, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, SVX_UNOEDIT_PARA_PROPERTIES, - { u"", 0, css::uno::Type(), 0, 0 } }; static SvxItemPropertySet aSvxXMLTextImportComponentPropertySet( SvxXMLTextImportComponentPropertyMap, EditEngine::GetGlobalItemPool() ); @@ -169,7 +167,7 @@ EditPaM SvxReadXML( EditEngine& rEditEngine, SvStream& rStream, const ESelection uno::Reference<io::XInputStream> xInputStream = new utl::OInputStreamWrapper( rStream ); /* testcode - static const OUStringLiteral aURL( u"file:///e:/test.xml" ); + static constexpr OUStringLiteral aURL( u"file:///e:/test.xml" ); SfxMedium aMedium( aURL, StreamMode::READ | STREAM_NOCREATE, sal_True ); uno::Reference<io::XOutputStream> xOut( new utl::OOutputStreamWrapper( *aMedium.GetOutStream() ) ); |