Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  unotext.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <vcl/svapp.hxx>
#include <com/sun/star/text/ControlCharacter.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/text/TextRangeSelection.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/container/XNameContainer.hpp>

#include <svl/itemset.hxx>
#include <svl/itempool.hxx>
#include <svl/eitem.hxx>
#include <tools/debug.hxx>

#include <editeng/unoprnms.hxx>
#include <editeng/unotext.hxx>
#include <editeng/unoedsrc.hxx>
#include <editeng/unonrule.hxx>
#include <editeng/unofdesc.hxx>
#include <editeng/unofield.hxx>
#include <editeng/flditem.hxx>
#include <editeng/numitem.hxx>
#include <editeng/editeng.hxx>
#include <editeng/outliner.hxx>
#include <editeng/unoipset.hxx>
#include <editeng/colritem.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/servicehelper.hxx>
#include <cppuhelper/supportsservice.hxx>

#include <editeng/unonames.hxx>

#include <initializer_list>
#include <memory>
#include <string_view>

using namespace ::cppu;
using namespace ::com::sun::star;

namespace {

ESelection toESelection(const text::TextRangeSelection& rSel)
{
    ESelection aESel;
    aESel.start.nPara = rSel.Start.Paragraph;
    aESel.start.nIndex = rSel.Start.PositionInParagraph;
    aESel.end.nPara = rSel.End.Paragraph;
    aESel.end.nIndex = rSel.End.PositionInParagraph;
    return aESel;
}

}

#define QUERYINT( xint ) \
    if( rType == cppu::UnoType<xint>::get() ) \
        return uno::Any(uno::Reference< xint >(this))

const SvxItemPropertySet* ImplGetSvxUnoOutlinerTextCursorSvxPropertySet()
{
    static SvxItemPropertySet aTextCursorSvxPropertySet( ImplGetSvxUnoOutlinerTextCursorPropertyMap(), EditEngine::GetGlobalItemPool() );
    return &aTextCursorSvxPropertySet;
}

std::span<const SfxItemPropertyMapEntry> ImplGetSvxTextPortionPropertyMap()
{
    // Propertymap for an Outliner Text
    static const SfxItemPropertyMapEntry aSvxTextPortionPropertyMap[] =
    {
        SVX_UNOEDIT_CHAR_PROPERTIES,
        SVX_UNOEDIT_FONT_PROPERTIES,
        SVX_UNOEDIT_OUTLINER_PROPERTIES,
        SVX_UNOEDIT_PARA_PROPERTIES,
        { u"TextField"_ustr,                     EE_FEATURE_FIELD,   cppu::UnoType<text::XTextField>::get(),   beans::PropertyAttribute::READONLY, 0 },
        { u"TextPortionType"_ustr,               WID_PORTIONTYPE,    ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 },
        { u"TextUserDefinedAttributes"_ustr,     EE_CHAR_XMLATTRIBS,     cppu::UnoType<css::container::XNameContainer>::get(),        0,     0},
        { u"ParaUserDefinedAttributes"_ustr,     EE_PARA_XMLATTRIBS,     cppu::UnoType<css::container::XNameContainer>::get(),        0,     0},
    };
    return aSvxTextPortionPropertyMap;
}
const SvxItemPropertySet* ImplGetSvxTextPortionSvxPropertySet()
{
    static SvxItemPropertySet aSvxTextPortionPropertySet( ImplGetSvxTextPortionPropertyMap(), EditEngine::GetGlobalItemPool() );
    return &aSvxTextPortionPropertySet;
}

static const SfxItemPropertySet* ImplGetSvxTextPortionSfxPropertySet()
{
    static SfxItemPropertySet aSvxTextPortionSfxPropertySet( ImplGetSvxTextPortionPropertyMap() );
    return &aSvxTextPortionSfxPropertySet;
}

std::span<const SfxItemPropertyMapEntry> ImplGetSvxUnoOutlinerTextCursorPropertyMap()
{
    // Propertymap for an Outliner Text
    static const SfxItemPropertyMapEntry aSvxUnoOutlinerTextCursorPropertyMap[] =
    {
        SVX_UNOEDIT_CHAR_PROPERTIES,
        SVX_UNOEDIT_FONT_PROPERTIES,
        SVX_UNOEDIT_OUTLINER_PROPERTIES,
        SVX_UNOEDIT_PARA_PROPERTIES,
        { u"TextUserDefinedAttributes"_ustr,         EE_CHAR_XMLATTRIBS,     cppu::UnoType<css::container::XNameContainer>::get(),        0,     0},
        { u"ParaUserDefinedAttributes"_ustr,         EE_PARA_XMLATTRIBS,     cppu::UnoType<css::container::XNameContainer>::get(),        0,     0},
    };

    return aSvxUnoOutlinerTextCursorPropertyMap;
}
static const SfxItemPropertySet* ImplGetSvxUnoOutlinerTextCursorSfxPropertySet()
{
    static SfxItemPropertySet aTextCursorSfxPropertySet( ImplGetSvxUnoOutlinerTextCursorPropertyMap() );
    return &aTextCursorSfxPropertySet;
}


// helper for Item/Property conversion


void GetSelection( struct ESelection& rSel, SvxTextForwarder const * pForwarder ) noexcept
{
    DBG_ASSERT( pForwarder, "I need a valid SvxTextForwarder!" );
    if( pForwarder )
    {
        sal_Int32 nParaCount = pForwarder->GetParagraphCount();
        if(nParaCount>0)
            nParaCount--;

        rSel = ESelection( 0,0, nParaCount, pForwarder->GetTextLen( nParaCount ));
    }
}

void CheckSelection( struct ESelection& rSel, SvxTextForwarder const * pForwarder ) noexcept
{
    DBG_ASSERT( pForwarder, "I need a valid SvxTextForwarder!" );
    if( !pForwarder )
        return;

    if (rSel.start.nPara == EE_PARA_MAX)
    {
        ::GetSelection( rSel, pForwarder );
    }
    else
    {
        ESelection aMaxSelection;
        GetSelection( aMaxSelection, pForwarder );

        // check start position
        if (rSel.start.nPara < aMaxSelection.start.nPara)
        {
            rSel.start = aMaxSelection.start;
        }
        else if (rSel.start.nPara > aMaxSelection.end.nPara)
        {
            rSel.start = aMaxSelection.end;
        }
        else if (rSel.start.nIndex > pForwarder->GetTextLen(rSel.start.nPara))
        {
            rSel.start.nIndex = pForwarder->GetTextLen(rSel.start.nPara);
        }

        // check end position
        if (rSel.end.nPara < aMaxSelection.start.nPara)
        {
            rSel.end = aMaxSelection.start;
        }
        else if (rSel.end.nPara > aMaxSelection.end.nPara)
        {
            rSel.end = aMaxSelection.end;
        }
        else if (rSel.end.nIndex > pForwarder->GetTextLen(rSel.end.nPara))
        {
            rSel.end.nIndex = pForwarder->GetTextLen(rSel.end.nPara);
        }
    }
}

static void CheckSelection( struct ESelection& rSel, SvxEditSource *pEdit ) noexcept
{
    if (!pEdit)
        return;
    CheckSelection( rSel, pEdit->GetTextForwarder() );
}




UNO3_GETIMPLEMENTATION_IMPL( SvxUnoTextRangeBase );

SvxUnoTextRangeBase::SvxUnoTextRangeBase(const SvxItemPropertySet* _pSet)
    : mpPropSet(_pSet)
{
}

SvxUnoTextRangeBase::SvxUnoTextRangeBase(const SvxEditSource* pSource, const SvxItemPropertySet* _pSet)
: mpPropSet(_pSet)
{
    SolarMutexGuard aGuard;

    assert(pSource && "SvxUnoTextRangeBase: I need a valid SvxEditSource!");

    mpEditSource = pSource->Clone();
    if (mpEditSource != nullptr)
    {
        ESelection aSelection;
        ::GetSelection( aSelection, mpEditSource->GetTextForwarder() );
        SetSelection( aSelection );

        mpEditSource->addRange( this );
    }
}

SvxUnoTextRangeBase::SvxUnoTextRangeBase(const SvxUnoTextRangeBase& rRange)
:   text::XTextRange()
,   beans::XPropertySet()
,   beans::XMultiPropertySet()
,   beans::XMultiPropertyStates()
,   beans::XPropertyState()
,   lang::XServiceInfo()
,   text::XTextRangeCompare()
,   lang::XUnoTunnel()
,   osl::DebugBase<SvxUnoTextRangeBase>()
,   mpPropSet(rRange.getPropertySet())
{
    SolarMutexGuard aGuard;

    if (rRange.mpEditSource)
        mpEditSource = rRange.mpEditSource->Clone();

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        maSelection  = rRange.maSelection;
        CheckSelection( maSelection, pForwarder );
    }

    if( mpEditSource )
        mpEditSource->addRange( this );
}

SvxUnoTextRangeBase::~SvxUnoTextRangeBase() noexcept
{
    if( mpEditSource )
        mpEditSource->removeRange( this );
}

void SvxUnoTextRangeBase::SetEditSource( SvxEditSource* pSource ) noexcept
{
    DBG_ASSERT(pSource,"SvxUnoTextRangeBase: I need a valid SvxEditSource!");
    DBG_ASSERT(mpEditSource==nullptr,"SvxUnoTextRangeBase::SetEditSource called while SvxEditSource already set" );

    mpEditSource.reset( pSource );

    maSelection.start.nPara = EE_PARA_MAX;

    if( mpEditSource )
        mpEditSource->addRange( this );
}

/** puts a field item with a copy of the given FieldData into the itemset
    corresponding with this range */

void SvxUnoTextRangeBase::attachField( std::unique_ptr<SvxFieldData> pData ) noexcept
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        SvxFieldItem aField( std::move(pData), EE_FEATURE_FIELD );
        pForwarder->QuickInsertField( std::move(aField), maSelection );
    }
}

void SvxUnoTextRangeBase::SetSelection( const ESelection& rSelection ) noexcept
{
    SolarMutexGuard aGuard;

    maSelection = rSelection;
    CheckSelection( maSelection, mpEditSource.get() );
}

// Interface XTextRange ( XText )

uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextRangeBase::getStart()
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( !pForwarder )
        return nullptr;

    CheckSelection( maSelection, pForwarder );

    SvxUnoTextBase* pText = comphelper::getFromUnoTunnel<SvxUnoTextBase>( getText() );

    if(pText == nullptr)
        throw uno::RuntimeException(u"Failed to retrieve a valid text base object from the Uno Tunnel"_ustr);

    rtl::Reference<SvxUnoTextRange> pRange = new SvxUnoTextRange( *pText );

    ESelection aNewSel = maSelection;
    aNewSel.CollapseToStart();
    pRange->SetSelection( aNewSel );

    return pRange;
}

uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextRangeBase::getEnd()
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( !pForwarder )
        return nullptr;

    CheckSelection( maSelection, pForwarder );

    SvxUnoTextBase* pText = comphelper::getFromUnoTunnel<SvxUnoTextBase>( getText() );

    if(pText == nullptr)
        throw uno::RuntimeException(u"Failed to retrieve a valid text base object from the Uno Tunnel"_ustr);

    rtl::Reference<SvxUnoTextRange> pNew = new SvxUnoTextRange( *pText );

    ESelection aNewSel = maSelection;
    aNewSel.CollapseToEnd();
    pNew->SetSelection( aNewSel );
    return pNew;
}

OUString SAL_CALL SvxUnoTextRangeBase::getString()
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        CheckSelection( maSelection, pForwarder );

        return pForwarder->GetText( maSelection );
    }
    else
    {
        return OUString();
    }
}

void SAL_CALL SvxUnoTextRangeBase::setString(const OUString& aString)
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( !pForwarder )
        return;

    CheckSelection( maSelection, pForwarder );

    OUString aConverted(convertLineEnd(aString, LINEEND_LF));  // Simply count the number of line endings

    pForwarder->QuickInsertText( aConverted, maSelection );
    mpEditSource->UpdateData();

    //  Adapt selection
    //! It would be easier if the EditEngine would return the selection
    //! on QuickInsertText...
    CollapseToStart();

    sal_Int32 nLen = aConverted.getLength();
    if (nLen)
        GoRight( nLen, true );
}

// Interface beans::XPropertySet
uno::Reference< beans::XPropertySetInfo > SAL_CALL SvxUnoTextRangeBase::getPropertySetInfo()
{
    return mpPropSet->getPropertySetInfo();
}

void SAL_CALL SvxUnoTextRangeBase::setPropertyValue(const OUString& PropertyNameconst uno::Any& aValue)
{
    if (PropertyName == UNO_TR_PROP_SELECTION)
    {
        text::TextRangeSelection aSel = aValue.get<text::TextRangeSelection>();
        SetSelection(toESelection(aSel));

        return;
    }

    _setPropertyValue( PropertyName, aValue );
}

void SvxUnoTextRangeBase::_setPropertyValue( const OUString& PropertyName, const uno::Any& aValue, sal_Int32 nPara )
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        CheckSelection( maSelection, pForwarder );

        const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName );
        if ( pMap )
        {
            ESelection aSel( GetSelection() );
            bool bParaAttrib = (pMap->nWID >= EE_PARA_START) && ( pMap->nWID <= EE_PARA_END );

            if (pMap->nWID == WID_PARASTYLENAME)
            {
                OUString aStyle = aValue.get<OUString>();

                sal_Int32 nEndPara;

                if( nPara == -1 )
                {
                    nPara = aSel.start.nPara;
                    nEndPara = aSel.end.nPara;
                }
                else
                {
                    // only one paragraph
                    nEndPara = nPara;
                }

                while( nPara <= nEndPara )
                {
                    pForwarder->SetStyleSheet(nPara, aStyle);
                    nPara++;
                }
            }
            else if ( nPara == -1 && !bParaAttrib )
            {
                SfxItemSet aOldSet( pForwarder->GetAttribs( aSel ) );
                // we have a selection and no para attribute
                SfxItemSet aNewSet( *aOldSet.GetPool(), aOldSet.GetRanges() );

                setPropertyValue( pMap, aValue, maSelection, aOldSet, aNewSet );


                pForwarder->QuickSetAttribs( aNewSet, GetSelection() );
            }
            else
            {
                sal_Int32 nEndPara;

                if( nPara == -1 )
                {
                    nPara = aSel.start.nPara;
                    nEndPara = aSel.end.nPara;
                }
                else
                {
                    // only one paragraph
                    nEndPara = nPara;
                }

                while( nPara <= nEndPara )
                {
                    // we have a paragraph
                    SfxItemSet aSet( pForwarder->GetParaAttribs( nPara ) );
                    setPropertyValue( pMap, aValue, maSelection, aSet, aSet );
                    pForwarder->SetParaAttribs( nPara, aSet );
                    nPara++;
                }
            }

            GetEditSource()->UpdateData();
            return;
        }
    }

    throw beans::UnknownPropertyException(PropertyName);
}

void SvxUnoTextRangeBase::setPropertyValue( const SfxItemPropertyMapEntry* pMap, const uno::Any& rValue, const ESelection& rSelection, const SfxItemSet& rOldSet, SfxItemSet& rNewSet )
{
    if(!SetPropertyValueHelper( pMap, rValue, rNewSet, &rSelection, GetEditSource() ))
    {
        // For parts of composite items with multiple properties (eg background)
        // must be taken from the document before the old item.
        rNewSet.Put(rOldSet.Get(pMap->nWID));  // Old Item in new Set
        SvxItemPropertySet::setPropertyValue(pMap, rValue, rNewSet, false );
    }
}

bool SvxUnoTextRangeBase::SetPropertyValueHelper( const SfxItemPropertyMapEntry* pMap, const uno::Any& aValue, SfxItemSet& rNewSet, const ESelection* pSelection /* = NULL */, SvxEditSource* pEditSource /* = NULL*/ )
{
    switch( pMap->nWID )
    {
    case WID_FONTDESC:
        {
            awt::FontDescriptor aDesc;
            if(aValue >>= aDesc)
            {
                SvxUnoFontDescriptor::FillItemSet( aDesc, rNewSet );
                return true;
            }
        }
        break;

    case EE_PARA_NUMBULLET:
        {
            uno::Reference< container::XIndexReplace > xRule;
            return !aValue.hasValue() || ((aValue >>= xRule) && !xRule.is());
        }

    case EE_PARA_OUTLLEVEL:
        {
            SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
            if(pForwarder && pSelection)
            {
                if (!pForwarder->SupportsOutlineDepth())
                    return false;

                sal_Int16 nLevel = sal_Int16();
                if( aValue >>= nLevel )
                {
                    // #101004# Call interface method instead of unsafe cast
                    if (!pForwarder->SetDepth(pSelection->start.nPara, nLevel))
                        throw lang::IllegalArgumentException();

                    // If valid, then not yet finished. Also needs to be added to paragraph props.
                    return nLevel < -1 || nLevel > 9;
                }
            }
        }
        break;
    case WID_NUMBERINGSTARTVALUE:
        {
            SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
            if(pForwarder && pSelection)
            {
                sal_Int16 nStartValue = -1;
                if( aValue >>= nStartValue )
                {
                    pForwarder->SetNumberingStartValue(pSelection->start.nPara, nStartValue);
                    return true;
                }
            }
        }
        break;
    case WID_PARAISNUMBERINGRESTART:
        {
            SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
            if(pForwarder && pSelection)
            {
                bool bParaIsNumberingRestart = false;
                if( aValue >>= bParaIsNumberingRestart )
                {
                    pForwarder->SetParaIsNumberingRestart( pSelection->start.nPara, bParaIsNumberingRestart );
                    return true;
                }
            }
        }
        break;
    case EE_PARA_BULLETSTATE:
        {
            bool bBullet = true;
            if( aValue >>= bBullet )
            {
                SfxBoolItem aItem( EE_PARA_BULLETSTATE, bBullet );
                rNewSet.Put(aItem);
                return true;
            }
        }
        break;

    default:
        return false;
    }

    throw lang::IllegalArgumentException();
}

uno::Any SAL_CALL SvxUnoTextRangeBase::getPropertyValue(const OUString& PropertyName)
{
    if (PropertyName == UNO_TR_PROP_SELECTION)
    {
        const ESelection& rSel = GetSelection();
        text::TextRangeSelection aSel;
        aSel.Start.Paragraph = rSel.start.nPara;
        aSel.Start.PositionInParagraph = rSel.start.nIndex;
        aSel.End.Paragraph = rSel.end.nPara;
        aSel.End.PositionInParagraph = rSel.end.nIndex;
        return uno::Any(aSel);
    }

    return _getPropertyValue( PropertyName );
}

uno::Any SvxUnoTextRangeBase::_getPropertyValue(const OUString& PropertyName, sal_Int32 nPara )
{
    SolarMutexGuard aGuard;

    uno::Any aAny;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName );
        if( pMap )
        {
            std::optional<SfxItemSet> oAttribs;
            if( nPara != -1 )
                oAttribs.emplace(pForwarder->GetParaAttribs( nPara ));
            else
                oAttribs.emplace(pForwarder->GetAttribs( GetSelection() ));

            //  Replace Dontcare with Default, so that one always has a mirror
            oAttribs->ClearInvalidItems();

            getPropertyValue( pMap, aAny, *oAttribs );

            return aAny;
        }
    }

    throw beans::UnknownPropertyException(PropertyName);
}

void SvxUnoTextRangeBase::getPropertyValue( const SfxItemPropertyMapEntry* pMap, uno::Any& rAny, const SfxItemSet& rSet )
{
    switch( pMap->nWID )
    {
    case EE_FEATURE_FIELD:
    {
        const SvxFieldItem* pItem = nullptr;
        if ( rSet.GetItemState( EE_FEATURE_FIELD, false, &pItem ) == SfxItemState::SET )
        {
            const SvxFieldData* pData = pItem->GetField();
            uno::Reference< text::XTextRange > xAnchor( this );

            // get presentation string for field
            std::optional<Color> pTColor;
            std::optional<Color> pFColor;
            std::optional<FontLineStyle> pFldLineStyle;

            SvxTextForwarder* pForwarder = mpEditSource->GetTextForwarder();
            OUString aPresentation( pForwarder->CalcFieldValue( SvxFieldItem(*pData, EE_FEATURE_FIELD), maSelection.start.nPara, maSelection.start.nIndex, pTColor, pFColor, pFldLineStyle ) );

            uno::Reference< text::XTextField > xField( new SvxUnoTextField( xAnchor, aPresentation, pData ) );
            rAny <<= xField;
        }
        break;
    }
    case WID_PORTIONTYPE:
        if ( rSet.GetItemState( EE_FEATURE_FIELD, false ) == SfxItemState::SET )
        {
            rAny <<= u"TextField"_ustr;
        }
        else
        {
            rAny <<= u"Text"_ustr;
        }
        break;

    case WID_PARASTYLENAME:
        {
            rAny <<= GetEditSource()->GetTextForwarder()->GetStyleSheet(maSelection.start.nPara);
        }
        break;

    default:
        if(!GetPropertyValueHelper( *const_cast<SfxItemSet*>(&rSet), pMap, rAny, &maSelection, GetEditSource() ))
            rAny = SvxItemPropertySet::getPropertyValue(pMap, rSet, truefalse );
    }
}

bool SvxUnoTextRangeBase::GetPropertyValueHelper(  SfxItemSet const & rSet, const SfxItemPropertyMapEntry* pMap, uno::Any& aAny, const ESelection* pSelection /* = NULL */, SvxEditSource* pEditSource /* = NULL */ )
{
    switch( pMap->nWID )
    {
    case WID_FONTDESC:
        {
            awt::FontDescriptor aDesc;
            SvxUnoFontDescriptor::FillFromItemSet( rSet, aDesc );
            aAny <<= aDesc;
        }
        break;

    case EE_PARA_NUMBULLET:
        {
            SfxItemState eState = rSet.GetItemState( EE_PARA_NUMBULLET );
            if( eState != SfxItemState::SET && eState != SfxItemState::DEFAULT)
                throw uno::RuntimeException(u"Invalid item state for paragraph numbering/bullet. Expected SET or DEFAULT."_ustr);

            const SvxNumBulletItem* pBulletItem = rSet.GetItem( EE_PARA_NUMBULLET );

            if( pBulletItem == nullptr )
                throw uno::RuntimeException(u"Unable to retrieve paragraph numbering/bullet item."_ustr);

            aAny <<= SvxCreateNumRule( pBulletItem->GetNumRule() );
        }
        break;

    case EE_PARA_OUTLLEVEL:
        {
            SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
            if(pForwarder && pSelection)
            {
                if (!pForwarder->SupportsOutlineDepth())
                    return false;

                sal_Int16 nLevel = pForwarder->GetDepth(pSelection->start.nPara);
                if( nLevel >= 0 )
                    aAny <<= nLevel;
            }
        }
        break;
    case WID_NUMBERINGSTARTVALUE:
        {
            SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
            if(pForwarder && pSelection)
                aAny <<= pForwarder->GetNumberingStartValue(pSelection->start.nPara);
        }
        break;
    case WID_PARAISNUMBERINGRESTART:
        {
            SvxTextForwarder* pForwarder = pEditSource? pEditSource->GetTextForwarder() : nullptr;
            if(pForwarder && pSelection)
                aAny <<= pForwarder->IsParaIsNumberingRestart(pSelection->start.nPara);
        }
        break;

    case EE_PARA_BULLETSTATE:
        {
            bool bState = false;
            SfxItemState eState = rSet.GetItemState( EE_PARA_BULLETSTATE );
            if( eState == SfxItemState::SET || eState == SfxItemState::DEFAULT )
            {
                const SfxBoolItem* pItem = rSet.GetItem<SfxBoolItem>( EE_PARA_BULLETSTATE );
                bState = pItem->GetValue();
            }

            aAny <<= bState;
        }
        break;
    default:

        return false;
    }

    return true;
}

// is not (yet) supported
void SAL_CALL SvxUnoTextRangeBase::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {}
void SAL_CALL SvxUnoTextRangeBase::removePropertyChangeListener( const OUString& const uno::Reference< beans::XPropertyChangeListener >& ) {}
void SAL_CALL SvxUnoTextRangeBase::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {}
void SAL_CALL SvxUnoTextRangeBase::removeVetoableChangeListener( const OUString& const uno::Reference< beans::XVetoableChangeListener >& ) {}

// XMultiPropertySet
void SAL_CALL SvxUnoTextRangeBase::setPropertyValues( const uno::Sequence< OUString >&&nbsp;aPropertyNames, const uno::Sequence< uno::Any >& aValues )
{
    _setPropertyValues( aPropertyNames, aValues );
}

void SvxUnoTextRangeBase::_setPropertyValues( const uno::Sequence< OUString >& aPropertyNames, const uno::Sequence< uno::Any >& aValues, sal_Int32 nPara )
{
    if (aPropertyNames.getLength() != aValues.getLength())
        throw lang::IllegalArgumentException(u"lengths do not match"_ustr,
                                             static_cast<css::beans::XPropertySet*>(this), -1);

    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( !pForwarder )
        return;

    CheckSelection( maSelection, pForwarder );

    ESelection aSel( GetSelection() );

    const OUString* pPropertyNames = aPropertyNames.getConstArray();
    const uno::Any* pValues = aValues.getConstArray();
    sal_Int32 nCount = aPropertyNames.getLength();

    sal_Int32 nEndPara = nPara;
    sal_Int32 nTempPara = nPara;

    if( nTempPara == -1 )
    {
        nTempPara = aSel.start.nPara;
        nEndPara = aSel.end.nPara;
    }

    std::optional<SfxItemSet> pOldAttrSet;
    std::optional<SfxItemSet> pNewAttrSet;

    std::optional<SfxItemSet> pOldParaSet;
    std::optional<SfxItemSet> pNewParaSet;

    std::optional<OUString> aStyleName;

    for( ; nCount; nCount--, pPropertyNames++, pValues++ )
    {
        const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( *pPropertyNames );

        if( pMap )
        {
            bool bParaAttrib = (pMap->nWID >= EE_PARA_START) && ( pMap->nWID <= EE_PARA_END );

            if (pMap->nWID == WID_PARASTYLENAME)
            {
                aStyleName.emplace((*pValues).get<OUString>());
            }
            else if( (nPara == -1) && !bParaAttrib )
            {
                if( !pNewAttrSet )
                {
                    pOldAttrSet.emplace( pForwarder->GetAttribs( aSel ) );
                    pNewAttrSet.emplace( *pOldAttrSet->GetPool(), pOldAttrSet->GetRanges() );
                }

                setPropertyValue( pMap, *pValues, GetSelection(), *pOldAttrSet, *pNewAttrSet );

                if( pMap->nWID >= EE_ITEMS_START && pMap->nWID <= EE_ITEMS_END )
                {
                    const SfxPoolItem* pItem;
                    if( pNewAttrSet->GetItemState( pMap->nWID, true, &pItem ) == SfxItemState::SET )
                    {
                        pOldAttrSet->Put( *pItem );
                    }
                }
            }
            else
            {
                if( !pNewParaSet )
                {
                    pOldParaSet.emplace( pForwarder->GetParaAttribs( nTempPara ) );
                    pNewParaSet.emplace( *pOldParaSet->GetPool(), pOldParaSet->GetRanges() );
                }

                setPropertyValue( pMap, *pValues, GetSelection(), *pOldParaSet, *pNewParaSet );

                if( pMap->nWID >= EE_ITEMS_START && pMap->nWID <= EE_ITEMS_END )
                {
                    const SfxPoolItem* pItem;
                    if( pNewParaSet->GetItemState( pMap->nWID, true, &pItem ) == SfxItemState::SET )
                    {
                        pOldParaSet->Put( *pItem );
                    }
                }

            }
        }
    }

    bool bNeedsUpdate = false;

    if( pNewParaSet || aStyleName )
    {
        if( pNewParaSet->Count() )
        {
            while( nTempPara <= nEndPara )
            {
                SfxItemSet aSet( pForwarder->GetParaAttribs( nTempPara ) );
                aSet.Put( *pNewParaSet );
                pForwarder->SetParaAttribs( nTempPara, aSet );
                if (aStyleName)
                    pForwarder->SetStyleSheet(nTempPara, *aStyleName);
                nTempPara++;
            }
            bNeedsUpdate = true;
        }

        pNewParaSet.reset();
        pOldParaSet.reset();
    }

    if( pNewAttrSet )
    {
        if( pNewAttrSet->Count() )
        {
            pForwarder->QuickSetAttribs( *pNewAttrSet, GetSelection() );
            bNeedsUpdate = true;
        }
        pNewAttrSet.reset();
        pOldAttrSet.reset();
    }

    if( bNeedsUpdate )
        GetEditSource()->UpdateData();
}

uno::Sequence< uno::Any > SAL_CALL SvxUnoTextRangeBase::getPropertyValues( const uno::Sequence< OUString >& aPropertyNames )
{
    return _getPropertyValues( aPropertyNames );
}

uno::Sequence< uno::Any > SvxUnoTextRangeBase::_getPropertyValues( const uno::Sequence< OUString >& aPropertyNames, sal_Int32 nPara )
{
    SolarMutexGuard aGuard;

    sal_Int32 nCount = aPropertyNames.getLength();


    uno::Sequence< uno::Any > aValues( nCount );

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        std::optional<SfxItemSet> oAttribs;
        if( nPara != -1 )
            oAttribs.emplace(pForwarder->GetParaAttribs( nPara ));
        else
            oAttribs.emplace(pForwarder->GetAttribs( GetSelection() ));

        oAttribs->ClearInvalidItems();

        const OUString* pPropertyNames = aPropertyNames.getConstArray();
        uno::Any* pValues = aValues.getArray();

        for( ; nCount; nCount--, pPropertyNames++, pValues++ )
        {
            const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( *pPropertyNames );
            if( pMap )
            {
                getPropertyValue( pMap, *pValues, *oAttribs );
            }
        }
    }

    return aValues;
}

void SAL_CALL SvxUnoTextRangeBase::addPropertiesChangeListener( const uno::Sequence< OUString >& , const uno::Reference< beans::XPropertiesChangeListener >& )
{
}

void SAL_CALL SvxUnoTextRangeBase::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& )
{
}

void SAL_CALL SvxUnoTextRangeBase::firePropertiesChangeEvent( const uno::Sequence< OUString >& , const uno::Reference< beans::XPropertiesChangeListener >& )
{
}

// beans::XPropertyState
beans::PropertyState SAL_CALL SvxUnoTextRangeBase::getPropertyState( const OUString&&nbsp;PropertyName )
{
    return _getPropertyState( PropertyName );
}

const sal_uInt16 aSvxUnoFontDescriptorWhichMap[] = { EE_CHAR_FONTINFO, EE_CHAR_FONTHEIGHT, EE_CHAR_ITALIC,
                                                  EE_CHAR_UNDERLINE, EE_CHAR_WEIGHT, EE_CHAR_STRIKEOUT, EE_CHAR_CASEMAP,
                                                  EE_CHAR_WLM, 0 };

beans::PropertyState SvxUnoTextRangeBase::_getPropertyState(const SfxItemPropertyMapEntry* pMap, sal_Int32 nPara)
{
    if ( pMap )
    {
        SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
        if( pForwarder )
        {
            SfxItemState eItemState(SfxItemState::DEFAULT);
            bool bItemStateSet(false);

            switch( pMap->nWID )
            {
            case WID_FONTDESC:
                {
                    const sal_uInt16* pWhichId = aSvxUnoFontDescriptorWhichMap;
                    while( *pWhichId )
                    {
                        const SfxItemState eTempItemState(nPara != -1
                            ? pForwarder->GetItemState( nPara, *pWhichId )
                            : pForwarder->GetItemState( GetSelection(), *pWhichId ));

                        switch( eTempItemState )
                        {
                        case SfxItemState::DISABLED:
                        case SfxItemState::INVALID:
                            eItemState = SfxItemState::INVALID;
                            bItemStateSet = true;
                            break;

                        case SfxItemState::DEFAULT:
                            if( !bItemStateSet )
                            {
                                eItemState = SfxItemState::DEFAULT;
                                bItemStateSet = true;
                            }
                            break;

                        case SfxItemState::SET:
                            if( !bItemStateSet )
                            {
                                eItemState = SfxItemState::SET;
                                bItemStateSet = true;
                            }
                            break;
                        default:
                            throw beans::UnknownPropertyException();
                        }

                        pWhichId++;
                    }
                }
                break;

            case WID_NUMBERINGSTARTVALUE:
            case WID_PARAISNUMBERINGRESTART:
            case WID_PARASTYLENAME:
                eItemState = SfxItemState::SET;
                bItemStateSet = true;
                break;

            default:
                if(0 != pMap->nWID)
                {
                    if( nPara != -1 )
                        eItemState = pForwarder->GetItemState( nPara, pMap->nWID );
                    else
                        eItemState = pForwarder->GetItemState( GetSelection(), pMap->nWID );

                    bItemStateSet = true;
                }
                break;
            }

            if(bItemStateSet)
            {
                switch( eItemState )
                {
                case SfxItemState::INVALID:
                case SfxItemState::DISABLED:
                    return beans::PropertyState_AMBIGUOUS_VALUE;
                case SfxItemState::SET:
                    return beans::PropertyState_DIRECT_VALUE;
                case SfxItemState::DEFAULT:
                    return beans::PropertyState_DEFAULT_VALUE;
                defaultbreak;
                }
            }
        }
    }
    throw beans::UnknownPropertyException();
}

beans::PropertyState SvxUnoTextRangeBase::_getPropertyState(std::u16string_view PropertyName, sal_Int32 nPara /* = -1 */)
{
    SolarMutexGuard aGuard;

    return _getPropertyState( mpPropSet->getPropertyMapEntry( PropertyName ), nPara);
}

uno::Sequence< beans::PropertyState > SAL_CALL SvxUnoTextRangeBase::getPropertyStates( const uno::Sequence< OUString >& aPropertyName )
{
    return _getPropertyStates( aPropertyName );
}

uno::Sequence< beans::PropertyState > SvxUnoTextRangeBase::_getPropertyStates(const uno::Sequence< OUString >& PropertyName, sal_Int32 nPara /* = -1 */)
{
    uno::Sequence< beans::PropertyState > aRet( PropertyName.getLength() );

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        std::optional<SfxItemSet> pSet;
        if( nPara != -1 )
        {
            pSet.emplace( pForwarder->GetParaAttribs( nPara ) );
        }
        else
        {
            ESelection aSel( GetSelection() );
            CheckSelection( aSel, pForwarder );
            pSet.emplace( pForwarder->GetAttribs( aSel, EditEngineAttribs::OnlyHard ) );
        }

        beans::PropertyState* pState = aRet.getArray();
        forconst OUString& rName : PropertyName )
        {
            const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( rName );
            if( !_getOnePropertyStates(*pSet, pMap, *pState++) )
            {
                throw beans::UnknownPropertyException(rName);
            }
        }
    }

    return aRet;
}

bool SvxUnoTextRangeBase::_getOnePropertyStates(const SfxItemSet& rSet, const SfxItemPropertyMapEntry* pMap, beans::PropertyState& rState)
{
    if (!pMap)
        return true;
    SfxItemState eItemState = SfxItemState::DEFAULT;
    bool bItemStateSet(false);

    bool bUnknownPropertyFound = false;
    switch( pMap->nWID )
    {
        case WID_FONTDESC:
            {
                const sal_uInt16* pWhichId = aSvxUnoFontDescriptorWhichMap;
                while( *pWhichId )
                {
                    const SfxItemState eTempItemState(rSet.GetItemState( *pWhichId ));

                    switch( eTempItemState )
                    {
                    case SfxItemState::DISABLED:
                    case SfxItemState::INVALID:
                        eItemState = SfxItemState::INVALID;
                        bItemStateSet = true;
                        break;

                    case SfxItemState::DEFAULT:
                        if( !bItemStateSet )
                        {
                            eItemState = SfxItemState::DEFAULT;
                            bItemStateSet = true;
                        }
                        break;

                    case SfxItemState::SET:
                        if( !bItemStateSet )
                        {
                            eItemState = SfxItemState::SET;
                            bItemStateSet = true;
                        }
                        break;
                    default:
                        bUnknownPropertyFound = true;
                        break;
                    }

                    pWhichId++;
                }
            }
            break;

        case WID_NUMBERINGSTARTVALUE:
        case WID_PARAISNUMBERINGRESTART:
        case WID_PARASTYLENAME:
            eItemState = SfxItemState::SET;
            bItemStateSet = true;
            break;

        default:
            if(0 != pMap->nWID)
            {
                eItemState = rSet.GetItemState( pMap->nWID, false );
                bItemStateSet = true;
            }
            break;
    }

    if( bUnknownPropertyFound )
        return false;

    if(bItemStateSet)
    {
        if (pMap->nWID == EE_CHAR_COLOR)
        {
            // Theme & effects can be DEFAULT_VALUE, even if the same pool item has a color
            // which is a DIRECT_VALUE.
            const SvxColorItem* pColor = rSet.GetItem<SvxColorItem>(EE_CHAR_COLOR);
            if (!pColor)
            {
                SAL_WARN("editeng""Missing EE_CHAR_COLOR SvxColorItem");
                return false;
            }
            switch (pMap->nMemberId)
            {
                case MID_COLOR_THEME_INDEX:
                    if (!pColor->getComplexColor().isValidThemeType())
                    {
                        eItemState = SfxItemState::DEFAULT;
                    }
                    break;
                case MID_COLOR_LUM_MOD:
                {
                    sal_Int16 nLumMod = 10000;
                    for (auto const& rTransform : pColor->getComplexColor().getTransformations())
                    {
                        if (rTransform.meType == model::TransformationType::LumMod)
                            nLumMod = rTransform.mnValue;
                    }
                    if (nLumMod == 10000)
                    {
                        eItemState = SfxItemState::DEFAULT;
                    }
                    break;
                }
                case MID_COLOR_LUM_OFF:
                {
                    sal_Int16 nLumOff = 0;
                    for (auto const& rTransform : pColor->getComplexColor().getTransformations())
                    {
                        if (rTransform.meType == model::TransformationType::LumOff)
                            nLumOff = rTransform.mnValue;
                    }
                    if (nLumOff == 0)
                    {
                        eItemState = SfxItemState::DEFAULT;
                    }
                    break;
                }
                case MID_COMPLEX_COLOR:
                    if (pColor->getComplexColor().getType() == model::ColorType::Unused)
                    {
                        eItemState = SfxItemState::DEFAULT;
                    }
                    break;
            }
        }

        switch( eItemState )
        {
            case SfxItemState::SET:
                rState = beans::PropertyState_DIRECT_VALUE;
                break;
            case SfxItemState::DEFAULT:
                rState = beans::PropertyState_DEFAULT_VALUE;
                break;
//                  case SfxItemState::INVALID:
//                  case SfxItemState::DISABLED:
            default:
                rState = beans::PropertyState_AMBIGUOUS_VALUE;
        }
    }
    else
    {
        rState = beans::PropertyState_AMBIGUOUS_VALUE;
    }
    return true;
}

void SAL_CALL SvxUnoTextRangeBase::setPropertyToDefault( const OUString& PropertyName )
{
    _setPropertyToDefault( PropertyName );
}

void SvxUnoTextRangeBase::_setPropertyToDefault(const OUString& PropertyName, sal_Int32 nPara /* = -1 */)
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;

    if( pForwarder )
    {
        const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( PropertyName );
        if ( pMap )
        {
            CheckSelection( maSelection, mpEditSource->GetTextForwarder() );
            _setPropertyToDefault( pForwarder, pMap, nPara );
            return;
        }
    }

    throw beans::UnknownPropertyException(PropertyName);
}

void SvxUnoTextRangeBase::_setPropertyToDefault(SvxTextForwarder* pForwarder, const SfxItemPropertyMapEntry* pMap, sal_Int32 nPara )
{
    do
    {
        SfxItemSet aSet(*pForwarder->GetPool());

        if( pMap->nWID == WID_FONTDESC )
        {
            SvxUnoFontDescriptor::setPropertyToDefault( aSet );
        }
        else if( pMap->nWID == WID_NUMBERINGSTARTVALUE )
        {
            pForwarder->SetNumberingStartValue(maSelection.start.nPara, -1);
        }
        else if( pMap->nWID == WID_PARAISNUMBERINGRESTART )
        {
            pForwarder->SetParaIsNumberingRestart(maSelection.start.nPara, false);
        }
        else
        {
            aSet.InvalidateItem( pMap->nWID );
        }

        if(nPara != -1)
            pForwarder->SetParaAttribs( nPara, aSet );
        else
            pForwarder->QuickSetAttribs( aSet, GetSelection() );

        GetEditSource()->UpdateData();

        return;
    }
    while(false);
}

uno::Any SAL_CALL SvxUnoTextRangeBase::getPropertyDefault( const OUString& aPropertyName )
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( pForwarder )
    {
        const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry( aPropertyName );
        if( pMap )
        {
            SfxItemPool* pPool = pForwarder->GetPool();

            switch( pMap->nWID )
            {
            case WID_FONTDESC:
                return SvxUnoFontDescriptor::getPropertyDefault( pPool );

            case EE_PARA_OUTLLEVEL:
                {
                    uno::Any aAny;
                    return aAny;
                }

            case WID_NUMBERINGSTARTVALUE:
                return uno::Any( sal_Int16(-1) );

            case WID_PARAISNUMBERINGRESTART:
                return uno::Any( false );

            default:
                {
                    // Get Default from ItemPool
                    if(SfxItemPool::IsWhich(pMap->nWID))
                    {
                        SfxItemSet aSet( *pPool, pMap->nWID, pMap->nWID );
                        aSet.Put(pPool->GetUserOrPoolDefaultItem(pMap->nWID));
                        return SvxItemPropertySet::getPropertyValue(pMap, aSet, truefalse );
                    }
                }
            }
        }
    }
    throw beans::UnknownPropertyException(aPropertyName);
}

// beans::XMultiPropertyStates
void SAL_CALL SvxUnoTextRangeBase::setAllPropertiesToDefault()
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;

    if( pForwarder )
    {
        for (const SfxItemPropertyMapEntry* entry : mpPropSet->getPropertyMap().getPropertyEntries())
        {
            _setPropertyToDefault( pForwarder, entry, -1 );
        }
    }
}

void SAL_CALL SvxUnoTextRangeBase::setPropertiesToDefault( const uno::Sequence< OUString >& aPropertyNames )
{
    forconst OUString& rName : aPropertyNames )
    {
        setPropertyToDefault( rName );
    }
}

uno::Sequence< uno::Any > SAL_CALL SvxUnoTextRangeBase::getPropertyDefaults( const uno::Sequence< OUString >& aPropertyNames )
{
    uno::Sequence< uno::Any > ret( aPropertyNames.getLength() );
    uno::Any* pDefaults = ret.getArray();

    forconst OUString& rName : aPropertyNames )
    {
        *pDefaults++ = getPropertyDefault( rName );
    }

    return ret;
}

// internal
void SvxUnoTextRangeBase::CollapseToStart() noexcept
{
    CheckSelection( maSelection, mpEditSource.get() );

    maSelection.CollapseToStart();
}

void SvxUnoTextRangeBase::CollapseToEnd() noexcept
{
    CheckSelection( maSelection, mpEditSource.get() );

    maSelection.CollapseToEnd();
}

bool SvxUnoTextRangeBase::IsCollapsed() noexcept
{
    CheckSelection( maSelection, mpEditSource.get() );

    return !maSelection.HasRange();
}

bool SvxUnoTextRangeBase::GoLeft(sal_Int32 nCount, bool Expand) noexcept
{
    CheckSelection( maSelection, mpEditSource.get() );

    //  #75098# use end position, as in Writer (start is anchor, end is cursor)
    sal_Int32 nNewPos = maSelection.end.nIndex;
    sal_Int32 nNewPar = maSelection.end.nPara;

    bool bOk = true;
    SvxTextForwarder* pForwarder = nullptr;
    while ( nCount > nNewPos && bOk )
    {
        if ( nNewPar == 0 )
            bOk = false;
        else
        {
            if ( !pForwarder )
                pForwarder = mpEditSource->GetTextForwarder();  // first here, it is necessary...
            assert(pForwarder);
            --nNewPar;
            nCount -= nNewPos + 1;
            nNewPos = pForwarder->GetTextLen( nNewPar );
        }
    }

    if ( bOk )
    {
        nNewPos = nNewPos - nCount;
        maSelection.start.nPara = nNewPar;
        maSelection.start.nIndex  = nNewPos;
    }

    if (!Expand)
        CollapseToStart();

    return bOk;
}

bool SvxUnoTextRangeBase::GoRight(sal_Int32 nCount, bool Expand)  noexcept
{
    if (!mpEditSource)
        return false;
    SvxTextForwarder* pForwarder = mpEditSource->GetTextForwarder();
    if( !pForwarder )
        return false;

    CheckSelection( maSelection, pForwarder );

    sal_Int32 nNewPos = maSelection.end.nIndex + nCount;
    sal_Int32 nNewPar = maSelection.end.nPara;

    bool bOk = true;
    sal_Int32 nParCount = pForwarder->GetParagraphCount();
    sal_Int32 nThisLen = pForwarder->GetTextLen( nNewPar );
    while ( nNewPos > nThisLen && bOk )
    {
        if ( nNewPar + 1 >= nParCount )
            bOk = false;
        else
        {
            nNewPos -= nThisLen+1;
            ++nNewPar;
            nThisLen = pForwarder->GetTextLen( nNewPar );
        }
    }

    if (bOk)
    {
        maSelection.end.nPara = nNewPar;
        maSelection.end.nIndex  = nNewPos;
    }

    if (!Expand)
        CollapseToEnd();

    return bOk;
}

void SvxUnoTextRangeBase::GotoStart(bool Expand) noexcept
{
    maSelection.start.nPara = 0;
    maSelection.start.nIndex  = 0;

    if (!Expand)
        CollapseToStart();
}

void SvxUnoTextRangeBase::GotoEnd(bool Expand) noexcept
{
    CheckSelection( maSelection, mpEditSource.get() );

    SvxTextForwarder* pForwarder = mpEditSource ? mpEditSource->GetTextForwarder() : nullptr;
    if( !pForwarder )
        return;

    sal_Int32 nPar = pForwarder->GetParagraphCount();
    if (nPar)
        --nPar;

    maSelection.end.nPara = nPar;
    maSelection.end.nIndex = pForwarder->GetTextLen(nPar);

    if (!Expand)
        CollapseToEnd();
}

// lang::XServiceInfo
sal_Bool SAL_CALL SvxUnoTextRangeBase::supportsService( const OUString& ServiceName )
{
    return cppu::supportsService( this, ServiceName );
}

uno::Sequence< OUString > SAL_CALL SvxUnoTextRangeBase::getSupportedServiceNames()
{
    return getSupportedServiceNames_Static();
}

uno::Sequence< OUString > SvxUnoTextRangeBase::getSupportedServiceNames_Static()
{
    return { u"com.sun.star.style.CharacterProperties"_ustr,
             u"com.sun.star.style.CharacterPropertiesComplex"_ustr,
             u"com.sun.star.style.CharacterPropertiesAsian"_ustr };
}

// XTextRangeCompare
sal_Int16 SAL_CALL SvxUnoTextRangeBase::compareRegionStarts( const uno::Reference< text::XTextRange >& xR1, const uno::Reference< text::XTextRange >& xR2 )
{
    SvxUnoTextRangeBase* pR1 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR1 );
    SvxUnoTextRangeBase* pR2 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR2 );

    if( (pR1 == nullptr) || (pR2 == nullptr) )
        throw lang::IllegalArgumentException();

    const ESelection& r1 = pR1->maSelection;
    const ESelection& r2 = pR2->maSelection;

    return r1.start == r2.start ? 0 : r1.start < r2.start ? 1 : -1;
}

sal_Int16 SAL_CALL SvxUnoTextRangeBase::compareRegionEnds( const uno::Reference< text::XTextRange >& xR1, const uno::Reference< text::XTextRange >& xR2 )
{
    SvxUnoTextRangeBase* pR1 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR1 );
    SvxUnoTextRangeBase* pR2 = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xR2 );

    if( (pR1 == nullptr) || (pR2 == nullptr) )
        throw lang::IllegalArgumentException();

    const ESelection& r1 = pR1->maSelection;
    const ESelection& r2 = pR2->maSelection;

    return r1.end == r2.end ? 0 : r1.end < r2.end ? 1 : -1;
}

SvxUnoTextRange::SvxUnoTextRange(const SvxUnoTextBase& rParent, bool bPortion /* = false */)
:SvxUnoTextRangeBase( rParent.GetEditSource(), bPortion ? ImplGetSvxTextPortionSvxPropertySet() : rParent.getPropertySet() ),
 mbPortion( bPortion )
{
    xParentText =  static_cast<text::XText*>(const_cast<SvxUnoTextBase *>(&rParent));
}

SvxUnoTextRange::~SvxUnoTextRange() noexcept
{
}

uno::Any SAL_CALL SvxUnoTextRange::queryAggregation( const uno::Type & rType )
{
    QUERYINT( text::XTextRange );
    else if( rType == cppu::UnoType<beans::XMultiPropertyStates>::get())
        return uno::Any(uno::Reference< beans::XMultiPropertyStates >(this));
    else if( rType == cppu::UnoType<beans::XPropertySet>::get())
        return uno::Any(uno::Reference< beans::XPropertySet >(this));
    else QUERYINT( beans::XPropertyState );
    else QUERYINT( text::XTextRangeCompare );
    else if( rType == cppu::UnoType<beans::XMultiPropertySet>::get())
        return uno::Any(uno::Reference< beans::XMultiPropertySet >(this));
    else QUERYINT( lang::XServiceInfo );
    else QUERYINT( lang::XTypeProvider );
    else QUERYINT( lang::XUnoTunnel );
    else
        return OWeakAggObject::queryAggregation( rType );
}

uno::Any SAL_CALL SvxUnoTextRange::queryInterface( const uno::Type & rType )
{
    return OWeakAggObject::queryInterface(rType);
}

void SAL_CALL SvxUnoTextRange::acquire()
    noexcept
{
    OWeakAggObject::acquire();
}

void SAL_CALL SvxUnoTextRange::release()
    noexcept
{
    OWeakAggObject::release();
}

// XTypeProvider

uno::Sequence< uno::Type > SAL_CALL SvxUnoTextRange::getTypes()
{
    static const uno::Sequence< uno::Type > TYPES {
            cppu::UnoType<text::XTextRange>::get(),
            cppu::UnoType<beans::XPropertySet>::get(),
            cppu::UnoType<beans::XMultiPropertySet>::get(),
            cppu::UnoType<beans::XMultiPropertyStates>::get(),
            cppu::UnoType<beans::XPropertyState>::get(),
            cppu::UnoType<lang::XServiceInfo>::get(),
            cppu::UnoType<lang::XTypeProvider>::get(),
            cppu::UnoType<lang::XUnoTunnel>::get(),
            cppu::UnoType<text::XTextRangeCompare>::get() };
    return TYPES;
}

uno::Sequence< sal_Int8 > SAL_CALL SvxUnoTextRange::getImplementationId()
{
    return css::uno::Sequence<sal_Int8>();
}

// XTextRange
uno::Reference< text::XText > SAL_CALL SvxUnoTextRange::getText()
{
    return xParentText;
}

// lang::XServiceInfo
OUString SAL_CALL SvxUnoTextRange::getImplementationName()
{
    return u"SvxUnoTextRange"_ustr;
}




SvxUnoTextBase::SvxUnoTextBase(const SvxItemPropertySet* _pSet)
    : SvxUnoTextRangeBase(_pSet)
{
}

SvxUnoTextBase::SvxUnoTextBase(const SvxEditSource* pSource, const SvxItemPropertySet* _pSet, uno::Reference < text::XText > const & xParent)
    : SvxUnoTextRangeBase(pSource, _pSet)
{
    xParentText = xParent;
    ESelection aSelection;
    ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
    SetSelection( aSelection );
}

SvxUnoTextBase::SvxUnoTextBase(const SvxUnoTextBase& rText)
:   SvxUnoTextRangeBase( rText )
, text::XTextAppend()
,   text::XTextCopy()
,   container::XEnumerationAccess()
,   text::XTextRangeMover()
,   lang::XTypeProvider()
{
    xParentText = rText.xParentText;
}

SvxUnoTextBase::~SvxUnoTextBase() noexcept
{
}

// XInterface
uno::Any SAL_CALL SvxUnoTextBase::queryAggregation( const uno::Type & rType )
{
    QUERYINT( text::XText );
    QUERYINT( text::XSimpleText );
    if( rType == cppu::UnoType<text::XTextRange>::get())
        return uno::Any(uno::Reference< text::XTextRange >(static_cast<text::XText*>(this)));
    QUERYINT(container::XEnumerationAccess );
    QUERYINT( container::XElementAccess );
    QUERYINT( beans::XMultiPropertyStates );
    QUERYINT( beans::XPropertySet );
    QUERYINT( beans::XMultiPropertySet );
    QUERYINT( beans::XPropertyState );
    QUERYINT( text::XTextRangeCompare );
    QUERYINT( lang::XServiceInfo );
    QUERYINT( text::XTextRangeMover );
    QUERYINT( text::XTextCopy );
    QUERYINT( text::XTextAppend );
    QUERYINT( text::XParagraphAppend );
    QUERYINT( text::XTextPortionAppend );
    QUERYINT( lang::XTypeProvider );
    QUERYINT( lang::XUnoTunnel );

    return uno::Any();
}

// XTypeProvider

uno::Sequence< uno::Type > SAL_CALL SvxUnoTextBase::getTypes()
{
    static const uno::Sequence< uno::Type > TYPES {
            cppu::UnoType<text::XText>::get(),
            cppu::UnoType<container::XEnumerationAccess>::get(),
            cppu::UnoType<beans::XPropertySet>::get(),
            cppu::UnoType<beans::XMultiPropertySet>::get(),
            cppu::UnoType<beans::XMultiPropertyStates>::get(),
            cppu::UnoType<beans::XPropertyState>::get(),
            cppu::UnoType<text::XTextRangeMover>::get(),
            cppu::UnoType<text::XTextAppend>::get(),
            cppu::UnoType<text::XTextCopy>::get(),
            cppu::UnoType<text::XParagraphAppend>::get(),
            cppu::UnoType<text::XTextPortionAppend>::get(),
            cppu::UnoType<lang::XServiceInfo>::get(),
            cppu::UnoType<lang::XTypeProvider>::get(),
            cppu::UnoType<lang::XUnoTunnel>::get(),
            cppu::UnoType<text::XTextRangeCompare>::get() };
    return TYPES;
}

uno::Sequence< sal_Int8 > SAL_CALL SvxUnoTextBase::getImplementationId()
{
    return css::uno::Sequence<sal_Int8>();
}

uno::Reference< text::XTextCursor > SvxUnoTextBase::createTextCursorBySelection( const ESelection& rSel )
{
    rtl::Reference<SvxUnoTextCursor> pCursor = new SvxUnoTextCursor( *this );
    pCursor->SetSelection( rSel );
    return pCursor;
}

// XSimpleText

uno::Reference< text::XTextCursor > SAL_CALL SvxUnoTextBase::createTextCursor()
{
    SolarMutexGuard aGuard;
    return new SvxUnoTextCursor( *this );
}

uno::Reference< text::XTextCursor > SAL_CALL SvxUnoTextBase::createTextCursorByRange( const uno::Reference< text::XTextRange >& aTextPosition )
{
    SolarMutexGuard aGuard;

    uno::Reference< text::XTextCursor >  xCursor;

    if( aTextPosition.is() )
    {
        SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( aTextPosition );
        if(pRange)
            xCursor = createTextCursorBySelection( pRange->GetSelection() );
    }

    return xCursor;
}

void SAL_CALL SvxUnoTextBase::insertString( const uno::Reference< text::XTextRange >& ;xRange, const OUString& aString, sal_Bool bAbsorb )
{
    SolarMutexGuard aGuard;

    if( !xRange.is() )
        return;

    SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange );
    if(!pRange)
        return;

    // setString on SvxUnoTextRangeBase instead of itself QuickInsertText
    // and UpdateData, so that the selection will be adjusted to
    // SvxUnoTextRangeBase. Actually all cursor objects of this Text must
    // to be statement to be adapted!

    if (!bAbsorb)                   // do not replace -> append on tail
        pRange->CollapseToEnd();

    pRange->setString( aString );

    pRange->CollapseToEnd();

    if (GetEditSource())
    {
        ESelection aSelection;
        ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
        SetSelection( aSelection );
    }
}

void SAL_CALL SvxUnoTextBase::insertControlCharacter( const uno::Reference< text::XTextRange >& xRange, sal_Int16 nControlCharacter, sal_Bool bAbsorb )
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = GetEditSource() ? GetEditSource()->GetTextForwarder() : nullptr;

    if( !pForwarder )
        return;

    ESelection aSelection;
    ::GetSelection( aSelection, pForwarder );
    SetSelection( aSelection );

    switch( nControlCharacter )
    {
    case text::ControlCharacter::PARAGRAPH_BREAK:
    {
        insertString( xRange, u"\x0D"_ustr, bAbsorb );

        return;
    }
    case text::ControlCharacter::LINE_BREAK:
    {
        SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange );
        if(pRange)
        {
            ESelection aRange = pRange->GetSelection();

            if( bAbsorb )
            {
                pForwarder->QuickInsertText( u""_ustr, aRange );

                aRange.CollapseToStart();
            }
            else
            {
                aRange.CollapseToEnd();
            }

            pForwarder->QuickInsertLineBreak( aRange );
            GetEditSource()->UpdateData();

            aRange.end.nIndex += 1;
            if( !bAbsorb )
                aRange.start.nIndex += 1;

            pRange->SetSelection( aRange );
        }
        return;
    }
    case text::ControlCharacter::APPEND_PARAGRAPH:
    {
        SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRange>( xRange );
        if(pRange)
        {
            ESelection aRange = pRange->GetSelection();
//              ESelection aOldSelection = aRange;

            aRange.start.nIndex  = pForwarder->GetTextLen( aRange.start.nPara );

            aRange.CollapseToStart();

            pRange->SetSelection( aRange );
            static constexpr OUStringLiteral CR = u"\x0D";
            pRange->setString( CR );

            aRange.start.nIndex = 0;
            aRange.start.nPara += 1;
            aRange.end.nIndex = 0;
            aRange.end.nPara += 1;

            pRange->SetSelection( aRange );

            return;
        }
        [[fallthrough]];
    }
    default:
        throw lang::IllegalArgumentException();
    }
}

// XText
void SAL_CALL SvxUnoTextBase::insertTextContent( const uno::Reference< text::XTextRange >& xRange, const uno::Reference< text::XTextContent >& xContent, sal_Bool bAbsorb )
{
    SolarMutexGuard aGuard;

    SvxTextForwarder* pForwarder = GetEditSource() ? GetEditSource()->GetTextForwarder() : nullptr;
    if (!pForwarder)
        return;

    uno::Reference<beans::XPropertySet> xPropSet(xRange, uno::UNO_QUERY);
    if (!xPropSet.is())
        throw lang::IllegalArgumentException();

    uno::Any aAny = xPropSet->getPropertyValue(UNO_TR_PROP_SELECTION);
    text::TextRangeSelection aSel = aAny.get<text::TextRangeSelection>();
    if (!bAbsorb)
        aSel.Start = aSel.End;

    std::unique_ptr<SvxFieldData> pFieldData(SvxFieldData::Create(xContent));
    if (!pFieldData)
        throw lang::IllegalArgumentException();

    SvxFieldItem aField( *pFieldData, EE_FEATURE_FIELD );
    pForwarder->QuickInsertField(aField, toESelection(aSel));
    GetEditSource()->UpdateData();

    uno::Reference<beans::XPropertySet> xPropSetContent(xContent, uno::UNO_QUERY);
    if (!xPropSetContent.is())
        throw lang::IllegalArgumentException();

    xPropSetContent->setPropertyValue(UNO_TC_PROP_ANCHOR, uno::Any(xRange));

    aSel.End.PositionInParagraph += 1;
    aSel.Start.PositionInParagraph = aSel.End.PositionInParagraph;
    xPropSet->setPropertyValue(UNO_TR_PROP_SELECTION, uno::Any(aSel));
}

void SAL_CALL SvxUnoTextBase::removeTextContent( const uno::Reference< text::XTextContent >& )
{
}

// XTextRange

uno::Reference< text::XText > SAL_CALL SvxUnoTextBase::getText()
{
    SolarMutexGuard aGuard;

    if (GetEditSource())
    {
        ESelection aSelection;
        ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
        SetSelection( aSelection );
    }

    return static_cast<text::XText*>(this);
}

uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::getStart()
{
    return SvxUnoTextRangeBase::getStart();
}

uno::Reference< text::XTextRange > SAL_CALL SvxUnoTextBase::getEnd()
{
    return SvxUnoTextRangeBase::getEnd();
}

OUString SAL_CALL SvxUnoTextBase::getString()
{
    return SvxUnoTextRangeBase::getString();
}

void SAL_CALL SvxUnoTextBase::setString( const OUString& aString )
{
    SvxUnoTextRangeBase::setString(aString);
}


// XEnumerationAccess
uno::Reference< container::XEnumeration > SAL_CALL SvxUnoTextBase::createEnumeration()
{
    SolarMutexGuard aGuard;

    if (!GetEditSource())
        return uno::Reference< container::XEnumeration >();

    if (maSelection == ESelection(0, 0, 0, 0) || maSelection == ESelection(EE_PARA_MAX, 0, 0, 0))
    {
        ESelection aSelection;
        ::GetSelection( aSelection, GetEditSource()->GetTextForwarder() );
        return new SvxUnoTextContentEnumeration(*this, aSelection);
    }
    else
    {
        return new SvxUnoTextContentEnumeration(*this, maSelection);
    }
}

// XElementAccess ( container::XEnumerationAccess )
uno::Type SAL_CALL SvxUnoTextBase::getElementType(  )
{
    return cppu::UnoType<text::XTextRange>::get();
}

sal_Bool SAL_CALL SvxUnoTextBase::hasElements(  )
{
    SolarMutexGuard aGuard;

    if(GetEditSource())
    {
        SvxTextForwarder* pForwarder = GetEditSource()->GetTextForwarder();
        if(pForwarder)
            return pForwarder->GetParagraphCount() != 0;
    }

    return false;
}

// text::XTextRangeMover
void SAL_CALL SvxUnoTextBase::moveTextRange( const uno::Reference< text::XTextRange >&,&nbsp;sal_Int16 )
{
}

/// @throws lang::IllegalArgumentException
/// @throws beans::UnknownPropertyException
/// @throws uno::RuntimeException
static void SvxPropertyValuesToItemSet(
        SfxItemSet &rItemSet,
        const uno::Sequence< beans::PropertyValue >& rPropertyValues,
        const SfxItemPropertySet *pPropSet,
        SvxTextForwarder *pForwarder,
        sal_Int32 nPara)
{
    for (const beans::PropertyValue& rProp : rPropertyValues)
    {
        const SfxItemPropertyMapEntry *pEntry = pPropSet->getPropertyMap().getByName( rProp.Name );
        if (!pEntry)
            throw beans::UnknownPropertyException( "Unknown property: " + rProp.Name );
        // Note: there is no need to take special care of the properties
        //      TextField (EE_FEATURE_FIELD) and
        //      TextPortionType (WID_PORTIONTYPE)
        //  since they are read-only and thus are already taken care of below.

        if (pEntry->nFlags & beans::PropertyAttribute::READONLY)
            // should be PropertyVetoException which is not yet defined for the new import API's functions
            throw uno::RuntimeException("Property is read-only: " + rProp.Name );
            //throw PropertyVetoException ("Property is read-only: " + rProp.Name );

        if (pEntry->nWID == WID_FONTDESC)
        {
            awt::FontDescriptor aDesc;
            if (rProp.Value >>= aDesc)
                SvxUnoFontDescriptor::FillItemSet( aDesc, rItemSet );
        }
        else if (pEntry->nWID == WID_NUMBERINGSTARTVALUE )
        {
            if( pForwarder )
            {
                sal_Int16 nStartValue = -1;
                if( !(rProp.Value >>= nStartValue) )
                    throw lang::IllegalArgumentException();

                pForwarder->SetNumberingStartValue( nPara, nStartValue );
            }
        }
        else if (pEntry->nWID == WID_PARAISNUMBERINGRESTART )
        {
            if( pForwarder )
            {
                bool bParaIsNumberingRestart = false;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=92 G=93

¤ Dauer der Verarbeitung: 0.33 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge