/* -*- 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 <comphelper/string.hxx>
#include <scitems.hxx>
 
#include <i18nutil/transliteration.hxx>
#include <editeng/adjustitem.hxx>
#include <svx/clipfmtitem.hxx>
#include <editeng/colritem.hxx>
#include <editeng/contouritem.hxx>
#include <editeng/crossedoutitem.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/editeng.hxx>
#include <editeng/editview.hxx>
#include <editeng/escapementitem.hxx>
#include <editeng/flditem.hxx>
#include <editeng/flstitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/lspcitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/urlfieldhelper.hxx>
#include <editeng/editund2.hxx>
#include <svx/hlnkitem.hxx>
#include <svx/svdoutl.hxx>
#include <svx/sdooitm.hxx>
#include <editeng/postitem.hxx>
#include <editeng/scriptsetitem.hxx>
#include <editeng/shdditem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/writingmodeitem.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/namedcolor.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <svtools/cliplistener.hxx>
#include <vcl/transfer.hxx>
#include <svl/stritem.hxx>
#include <svl/whiter.hxx>
#include <svl/languageoptions.hxx>
#include <svl/cjkoptions.hxx>
#include <svl/ctloptions.hxx>
 
#include <svx/svxdlg.hxx>
#include <vcl/EnumContext.hxx>
#include <vcl/unohelp2.hxx>
 
#include <sc.hrc>
#include <globstr.hrc>
#include <scresid.hxx>
#include <scmod.hxx>
#include <drtxtob.hxx>
#include <viewdata.hxx>
#include <document.hxx>
#include <drawview.hxx>
#include <viewutil.hxx>
#include <tabvwsh.hxx>
#include <gridwin.hxx>
 
#define ShellClass_ScDrawTextObjectBar
#include <scslots.hxx>
 
using namespace ::com::sun::star;
 
SFX_IMPL_INTERFACE(ScDrawTextObjectBar, SfxShell)
 
void ScDrawTextObjectBar::InitInterface_Impl()
{
    GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
                                            SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
                                            ToolbarId::Text_Toolbox_Sc);
 
    GetStaticInterface()->RegisterPopupMenu(u"drawtext"_ustr);
 
    GetStaticInterface()->RegisterChildWindow(ScGetFontWorkId());
}
 
 
// disable not wanted accelerators
 
void ScDrawTextObjectBar::StateDisableItems( SfxItemSet &rSet )
{
    SfxWhichIter aIter(rSet);
    sal_uInt16 nWhich = aIter.FirstWhich();
 
    while (nWhich)
    {
        rSet.DisableItem( nWhich );
        nWhich = aIter.NextWhich();
    }
}
 
ScDrawTextObjectBar::ScDrawTextObjectBar(ScViewData& rData) :
    SfxShell(rData.GetViewShell()),
    mrViewData(rData),
    bPastePossible(false)
{
    SetPool( mrViewData.GetScDrawView()->GetDefaultAttr().GetPool() );
 
    //  At the switching-over the UndoManager is changed to edit mode
    SfxUndoManager* pMgr = mrViewData.GetSfxDocShell()->GetUndoManager();
    SetUndoManager( pMgr );
    if ( !mrViewData.GetDocument().IsUndoEnabled() )
    {
        pMgr->SetMaxUndoActionCount( 0 );
    }
 
    SetName(u"DrawText"_ustr);
    SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::DrawText));
}
 
ScDrawTextObjectBar::~ScDrawTextObjectBar()
{
    if ( mxClipEvtLstnr.is() )
    {
        mxClipEvtLstnr->RemoveListener( mrViewData.GetActiveWin() );
 
        //  The listener may just now be waiting for the SolarMutex and call the link
        //  afterwards, in spite of RemoveListener. So the link has to be reset, too.
        mxClipEvtLstnr->ClearCallbackLink();
    }
}
 
//          Functions
 
void ScDrawTextObjectBar::Execute( SfxRequest &rReq )
{
    ScDrawView* pView = mrViewData.GetScDrawView();
    OutlinerView* pOutView = pView->GetTextEditOutlinerView();
    Outliner* pOutliner = pView->GetTextEditOutliner();
 
    if (!pOutView || !pOutliner)
    {
        ExecuteGlobal( rReq );              // on whole objects
        return;
    }
 
    const SfxItemSet* pReqArgs = rReq.GetArgs();
    sal_uInt16 nSlot = rReq.GetSlot();
    switch ( nSlot )
    {
        case SID_COPY:
            pOutView->Copy();
            break;
 
        case SID_CUT:
            pOutView->Cut();
            break;
 
        case SID_PASTE:
            pOutView->PasteSpecial();
            break;
 
        case SID_CLIPBOARD_FORMAT_ITEMS:
            {
                SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
                const SfxPoolItem* pItem;
                if ( pReqArgs && pReqArgs->GetItemState(nSlot, true, &pItem) == SfxItemState::SET )
                    if (auto pIntItem = dynamic_cast<const SfxUInt32Item*>( pItem))
                        nFormat = static_cast<SotClipboardFormatId>(pIntItem->GetValue());
 
                if ( nFormat != SotClipboardFormatId::NONE )
                {
                    if (nFormat == SotClipboardFormatId::STRING)
                        pOutView->Paste();
                    else
                        pOutView->PasteSpecial(nFormat);
                }
            }
            break;
 
        case SID_PASTE_SPECIAL:
            ExecutePasteContents( rReq );
            break;
 
        case SID_PASTE_UNFORMATTED:
            pOutView->Paste();
            break;
 
        case SID_SELECTALL:
            {
                sal_Int32 nCount = pOutliner->GetParagraphCount();
                ESelection aSel( 0,0,nCount,0 );
                pOutView->SetSelection( aSel );
            }
            break;
 
        case SID_CHARMAP:
            {
                auto const attribs = pOutView->GetAttribs();
                const SvxFontItem& rItem = attribs.Get(EE_CHAR_FONTINFO);
 
                OUString aString;
                std::shared_ptr<SvxFontItem> aNewItem(std::make_shared<SvxFontItem>(EE_CHAR_FONTINFO));
 
                const SfxItemSet *pArgs = rReq.GetArgs();
                const SfxPoolItem* pItem = nullptr;
                if( pArgs )
                    pArgs->GetItemState(SID_CHARMAP, false, &pItem);
 
                if ( pItem )
                {
                    aString = static_cast<const SfxStringItem*>(pItem)->GetValue();
                    const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_ATTR_SPECIALCHAR, false);
                    if ( pFontItem )
                    {
                        const OUString& aFontName(pFontItem->GetValue());
                        vcl::Font aFont(aFontName, Size(1,1)); // Size only because of CTOR
                        aNewItem = std::make_shared<SvxFontItem>(
                            aFont.GetFamilyTypeMaybeAskConfig(), aFont.GetFamilyName(),
                            aFont.GetStyleName(), aFont.GetPitchMaybeAskConfig(),
                            aFont.GetCharSet(), ATTR_FONT);
                    }
                    else
                    {
                        aNewItem.reset(rItem.Clone());
                    }
                }
                else
                    ScViewUtil::ExecuteCharMap(rItem, *mrViewData.GetViewShell());
 
                if ( !aString.isEmpty() )
                {
                    SfxItemSet aSet( pOutliner->GetEmptyItemSet() );
                    // tdf#125054 set and force to needed WhichID
                    aSet.PutAsTargetWhich( *aNewItem, EE_CHAR_FONTINFO );
 
                    //  If nothing is selected, then SetAttribs of the View selects a word
                    pOutView->GetOutliner().QuickSetAttribs( aSet, pOutView->GetSelection() );
                    pOutView->InsertText(aString);
                }
 
                Invalidate( SID_ATTR_CHAR_FONT );
            }
            break;
 
        case SID_HYPERLINK_SETLINK:
            if( pReqArgs )
            {
                if ( const SvxHyperlinkItem* pHyper = pReqArgs->GetItemIfSet( SID_HYPERLINK_SETLINK) )
                {
                    const OUString& rName = pHyper->GetName();
                    const OUString& rURL      = pHyper->GetURL();
                    const OUString& rTarget   = pHyper->GetTargetFrame();
                    SvxLinkInsertMode eMode = pHyper->GetInsertMode();
 
                    bool bDone = false;
                    if (eMode == HLINK_DEFAULT || eMode == HLINK_FIELD)
                    {
                        pOutView->SelectFieldAtCursor();
 
                        //  insert new field
                        SvxURLField aURLField( rURL, rName, SvxURLFormat::Repr );
                        aURLField.SetTargetFrame( rTarget );
                        SvxFieldItem aURLItem( aURLField, EE_FEATURE_FIELD );
                        pOutView->InsertField( aURLItem );
 
                        bDone = true;
                    }
 
                    if (!bDone)
                        ExecuteGlobal( rReq );      // normal at View
 
                    //  If "text" is received by InsertURL of ViewShell, then the DrawShell is turned off !!!
                }
            }
            break;
 
        case SID_OPEN_HYPERLINK:
            {
                const SvxFieldItem* pFieldItem
                    = pOutView->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true);
                const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
                if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
                {
                    ScGlobal::OpenURL(pURLField->GetURL(), pURLField->GetTargetFrame(), true);
                }
            }
            break;
 
        case SID_INSERT_HYPERLINK:
            mrViewData.GetViewShell()->GetViewFrame().GetDispatcher()->Execute(SID_HYPERLINK_DIALOG);
            break;
 
        case SID_EDIT_HYPERLINK:
            {
                // Ensure the field is selected first
                pOutView->SelectFieldAtCursor();
                mrViewData.GetViewShell()->GetViewFrame().GetDispatcher()->Execute(SID_HYPERLINK_DIALOG);
            }
            break;
 
        case SID_COPY_HYPERLINK_LOCATION:
            {
                const SvxFieldItem* pFieldItem
                    = pOutView->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true);
                const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
                if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
                {
                    uno::Reference<datatransfer::clipboard::XClipboard> xClipboard
                        = pOutView->GetWindow()->GetClipboard();
                    vcl::unohelper::TextDataObject::CopyStringTo(pURLField->GetURL(), xClipboard);
                }
            }
            break;
 
        case SID_REMOVE_HYPERLINK:
            {
                URLFieldHelper::RemoveURLField(pOutView->GetEditView());
            }
            break;
 
        case SID_ENABLE_HYPHENATION:
        case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
        case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
            pView->ScEndTextEdit(); // end text edit before switching direction
            ExecuteGlobal( rReq );
            // restore consistent state between shells and functions:
            mrViewData.GetDispatcher().Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
            break;
 
        case SID_THES:
            {
                OUString aReplaceText;
                const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
                if (pItem2)
                    aReplaceText = pItem2->GetValue();
                if (!aReplaceText.isEmpty())
                    ReplaceTextWithSynonym( pOutView->GetEditView(), aReplaceText );
            }
            break;
 
        case SID_THESAURUS:
            {
                pOutView->StartThesaurus(rReq.GetFrameWeld());
            }
            break;
    }
}
 
void ScDrawTextObjectBar::GetState( SfxItemSet& rSet )
{
    SfxViewFrame& rViewFrm = mrViewData.GetViewShell()->GetViewFrame();
    bool bHasFontWork = rViewFrm.HasChildWindow(SID_FONTWORK);
    bool bDisableFontWork = false;
 
    if (IsNoteEdit())
    {
        // #i21255# notes now support rich text formatting (#i74140# but not fontwork)
        bDisableFontWork = true;
    }
 
    if ( bDisableFontWork )
        rSet.DisableItem( SID_FONTWORK  );
    else
        rSet.Put(SfxBoolItem(SID_FONTWORK, bHasFontWork));
 
    if ( rSet.GetItemState( SID_HYPERLINK_GETLINK ) != SfxItemState::UNKNOWN )
    {
        SvxHyperlinkItem aHLinkItem;
        aHLinkItem.SetShowName(false);
        SdrView* pView = mrViewData.GetScDrawView();
        OutlinerView* pOutView = pView->GetTextEditOutlinerView();
        if ( pOutView )
        {
            bool bField = false;
            const SvxFieldItem* pFieldItem = pOutView->GetFieldAtSelection();
            const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
            if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
            {
                aHLinkItem.SetName( pURLField->GetRepresentation() );
                aHLinkItem.SetURL( pURLField->GetURL() );
                aHLinkItem.SetTargetFrame( pURLField->GetTargetFrame() );
                bField = true;
            }
 
            if (!bField)
            {
                // use selected text as name for urls
                OUString sReturn = pOutView->GetSelected();
                sal_Int32 nLen = std::min<sal_Int32>(sReturn.getLength(), 255);
                sReturn = sReturn.copy(0, nLen);
                aHLinkItem.SetName(comphelper::string::stripEnd(sReturn, ' '));
            }
        }
        rSet.Put(aHLinkItem);
    }
 
    if (rSet.GetItemState(SID_OPEN_HYPERLINK) != SfxItemState::UNKNOWN
        || rSet.GetItemState(SID_INSERT_HYPERLINK) != SfxItemState::UNKNOWN
        || rSet.GetItemState(SID_EDIT_HYPERLINK) != SfxItemState::UNKNOWN
        || rSet.GetItemState(SID_COPY_HYPERLINK_LOCATION) != SfxItemState::UNKNOWN
        || rSet.GetItemState(SID_REMOVE_HYPERLINK) != SfxItemState::UNKNOWN)
    {
        OutlinerView* pOutView = mrViewData.GetScDrawView()->GetTextEditOutlinerView();
        if (!URLFieldHelper::IsCursorAtURLField(pOutView, /*AlsoCheckBeforeCursor=*/true))
        {
            rSet.DisableItem( SID_OPEN_HYPERLINK );
            rSet.DisableItem( SID_EDIT_HYPERLINK );
            rSet.DisableItem( SID_COPY_HYPERLINK_LOCATION );
            rSet.DisableItem( SID_REMOVE_HYPERLINK );
        }
        else
        {
            rSet.DisableItem( SID_INSERT_HYPERLINK );
        }
    }
 
    if( rSet.GetItemState( SID_TRANSLITERATE_HALFWIDTH ) != SfxItemState::UNKNOWN )
        ScViewUtil::HideDisabledSlot( rSet, rViewFrm.GetBindings(), SID_TRANSLITERATE_HALFWIDTH );
    if( rSet.GetItemState( SID_TRANSLITERATE_FULLWIDTH ) != SfxItemState::UNKNOWN )
        ScViewUtil::HideDisabledSlot( rSet, rViewFrm.GetBindings(), SID_TRANSLITERATE_FULLWIDTH );
    if( rSet.GetItemState( SID_TRANSLITERATE_HIRAGANA ) != SfxItemState::UNKNOWN )
        ScViewUtil::HideDisabledSlot( rSet, rViewFrm.GetBindings(), SID_TRANSLITERATE_HIRAGANA );
    if( rSet.GetItemState( SID_TRANSLITERATE_KATAKANA ) != SfxItemState::UNKNOWN )
        ScViewUtil::HideDisabledSlot( rSet, rViewFrm.GetBindings(), SID_TRANSLITERATE_KATAKANA );
 
    if ( rSet.GetItemState( SID_ENABLE_HYPHENATION ) != SfxItemState::UNKNOWN )
    {
        SdrView* pView = mrViewData.GetScDrawView();
        SfxItemSet aAttrs(pView->GetModel().GetItemPool());
        pView->GetAttributes( aAttrs );
        if( aAttrs.GetItemState( EE_PARA_HYPHENATE ) >= SfxItemState::DEFAULT )
        {
            bool bValue = aAttrs.Get( EE_PARA_HYPHENATE ).GetValue();
            rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) );
        }
    }
 
    if ( rSet.GetItemState( SID_THES ) != SfxItemState::UNKNOWN  ||
         rSet.GetItemState( SID_THESAURUS ) != SfxItemState::UNKNOWN )
    {
        SdrView * pView = mrViewData.GetScDrawView();
        OutlinerView* pOutView = pView->GetTextEditOutlinerView();
 
        OUString        aStatusVal;
        LanguageType    nLang = LANGUAGE_NONE;
        bool bIsLookUpWord = false;
        if ( pOutView )
        {
            EditView& rEditView = pOutView->GetEditView();
            bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, rEditView );
        }
        rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
 
        // disable thesaurus main menu and context menu entry if there is nothing to look up
        bool bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang );
        if (!bIsLookUpWord || !bCanDoThesaurus)
            rSet.DisableItem( SID_THES );
        if (!bCanDoThesaurus)
            rSet.DisableItem( SID_THESAURUS );
    }
 
    if (GetObjectShell()->isContentExtractionLocked())
    {
        rSet.DisableItem(SID_COPY);
        rSet.DisableItem(SID_CUT);
    }
}
 
IMPL_LINK( ScDrawTextObjectBar, ClipboardChanged, TransferableDataHelper*, pDataHelper, void )
{
    bPastePossible = ( pDataHelper->HasFormat( SotClipboardFormatId::STRING ) || pDataHelper->HasFormat( SotClipboardFormatId::RTF )
        || pDataHelper->HasFormat( SotClipboardFormatId::RICHTEXT ) );
 
    SfxBindings& rBindings = mrViewData.GetBindings();
    rBindings.Invalidate( SID_PASTE );
    rBindings.Invalidate( SID_PASTE_SPECIAL );
    rBindings.Invalidate( SID_PASTE_UNFORMATTED );
    rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
}
 
void ScDrawTextObjectBar::GetClipState( SfxItemSet& rSet )
{
    SdrView* pView = mrViewData.GetScDrawView();
    if ( !pView->GetTextEditOutlinerView() )
    {
        GetGlobalClipState( rSet );
        return;
    }
 
    if ( !mxClipEvtLstnr.is() )
    {
        // create listener
        mxClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScDrawTextObjectBar, ClipboardChanged ) );
        vcl::Window* pWin = mrViewData.GetActiveWin();
        mxClipEvtLstnr->AddListener( pWin );
 
        // get initial state
        TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mrViewData.GetActiveWin() ) );
        bPastePossible = ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) || aDataHelper.HasFormat( SotClipboardFormatId::RTF )
            || aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) );
    }
 
    SfxWhichIter aIter( rSet );
    sal_uInt16 nWhich = aIter.FirstWhich();
    while (nWhich)
    {
        switch (nWhich)
        {
            case SID_PASTE:
            case SID_PASTE_SPECIAL:
            case SID_PASTE_UNFORMATTED:
                if( !bPastePossible )
                    rSet.DisableItem( nWhich );
                break;
            case SID_CLIPBOARD_FORMAT_ITEMS:
                if ( bPastePossible )
                {
                    SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
                    TransferableDataHelper aDataHelper(
                            TransferableDataHelper::CreateFromSystemClipboard( mrViewData.GetActiveWin() ) );
 
                    if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) )
                        aFormats.AddClipbrdFormat( SotClipboardFormatId::STRING );
                    if ( aDataHelper.HasFormat( SotClipboardFormatId::RTF ) )
                        aFormats.AddClipbrdFormat( SotClipboardFormatId::RTF );
                    if ( aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) )
                        aFormats.AddClipbrdFormat( SotClipboardFormatId::RICHTEXT );
                    if (aDataHelper.HasFormat(SotClipboardFormatId::HTML_SIMPLE))
                        aFormats.AddClipbrdFormat(SotClipboardFormatId::HTML_SIMPLE);
 
                    rSet.Put( aFormats );
                }
                else
                    rSet.DisableItem( nWhich );
                break;
        }
        nWhich = aIter.NextWhich();
    }
}
 
//          Attributes
 
void ScDrawTextObjectBar::ExecuteToggle( SfxRequest &rReq )
{
    //  Underline
 
    SdrView* pView = mrViewData.GetScDrawView();
 
    sal_uInt16 nSlot = rReq.GetSlot();
 
    SfxItemSet aSet( pView->GetDefaultAttr() );
 
    SfxItemSet aViewAttr(pView->GetModel().GetItemPool());
    pView->GetAttributes(aViewAttr);
 
    //  Underline
    FontLineStyle eOld = aViewAttr.Get(EE_CHAR_UNDERLINE).GetLineStyle();
    FontLineStyle eNew = eOld;
    switch (nSlot)
    {
        case SID_ULINE_VAL_NONE:
            eNew = LINESTYLE_NONE;
            break;
        case SID_ULINE_VAL_SINGLE:
            eNew = ( eOld == LINESTYLE_SINGLE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
            break;
        case SID_ULINE_VAL_DOUBLE:
            eNew = ( eOld == LINESTYLE_DOUBLE ) ? LINESTYLE_NONE : LINESTYLE_DOUBLE;
            break;
        case SID_ULINE_VAL_DOTTED:
            eNew = ( eOld == LINESTYLE_DOTTED ) ? LINESTYLE_NONE : LINESTYLE_DOTTED;
            break;
        default:
            break;
    }
    aSet.Put( SvxUnderlineItem( eNew, EE_CHAR_UNDERLINE ) );
 
    pView->SetAttributes( aSet );
    rReq.Done();
    mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
}
 
static void lcl_RemoveFields( OutlinerView& rOutView )
{
    //! Outliner should have RemoveFields with a selection
 
    Outliner& rOutliner = rOutView.GetOutliner();
 
    ESelection aOldSel = rOutView.GetSelection();
    ESelection aSel = aOldSel;
    aSel.Adjust();
    sal_Int32 nNewEnd = aSel.end.nIndex;
 
    bool bUpdate = rOutliner.IsUpdateLayout();
    bool bChanged = false;
 
    //! GetPortions and GetAttribs should be const!
    EditEngine& rEditEng = const_cast<EditEngine&>(rOutliner.GetEditEngine());
 
    sal_Int32 nParCount = rOutliner.GetParagraphCount();
    for (sal_Int32 nPar=0; nPar<nParCount; nPar++)
        if (nPar >= aSel.start.nPara && nPar <= aSel.end.nPara)
        {
            std::vector<sal_Int32> aPortions;
            rEditEng.GetPortions( nPar, aPortions );
 
            for ( size_t nPos = aPortions.size(); nPos; )
            {
                --nPos;
                sal_Int32 nEnd = aPortions[ nPos ];
                sal_Int32 nStart = nPos ? aPortions[ nPos - 1 ] : 0;
                // fields are single characters
                if ( nEnd == nStart+1 &&
                     ( nPar > aSel.start.nPara || nStart >= aSel.start.nIndex ) &&
                     ( nPar < aSel.end.nPara   || nEnd   <= aSel.end.nIndex ) )
                {
                    ESelection aFieldSel( nPar, nStart, nPar, nEnd );
                    SfxItemSet aSet = rEditEng.GetAttribs( aFieldSel );
                    if ( aSet.GetItemState( EE_FEATURE_FIELD ) == SfxItemState::SET )
                    {
                        if (!bChanged)
                        {
                            if (bUpdate)
                                rOutliner.SetUpdateLayout( false );
                            OUString aName = ScResId( STR_UNDO_DELETECONTENTS );
                            ViewShellId nViewShellId(-1);
                            if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
                                nViewShellId = pViewSh->GetViewShellId();
                            rOutliner.GetUndoManager().EnterListAction( aName, aName, 0, nViewShellId );
                            bChanged = true;
                        }
 
                        OUString aFieldText = rEditEng.GetText( aFieldSel );
                        rOutliner.QuickInsertText( aFieldText, aFieldSel );
                        if (nPar == aSel.end.nPara)
                        {
                            nNewEnd = nNewEnd + aFieldText.getLength();
                            --nNewEnd;
                        }
                    }
                }
            }
        }
 
    if (bUpdate && bChanged)
    {
        rOutliner.GetUndoManager().LeaveListAction();
        rOutliner.SetUpdateLayout( true );
    }
 
    if ( aOldSel == aSel )          // aSel is adjusted
        aOldSel.end.nIndex = nNewEnd;
    else
        aOldSel.start.nIndex = nNewEnd;        // if aOldSel is backwards
    rOutView.SetSelection( aOldSel );
}
 
void ScDrawTextObjectBar::ExecuteAttr( SfxRequest &rReq )
{
    SdrView*            pView = mrViewData.GetScDrawView();
    const SfxItemSet*   pArgs = rReq.GetArgs();
    sal_uInt16          nSlot = rReq.GetSlot();
 
    SfxItemSet aEditAttr( pView->GetModel().GetItemPool() );
    pView->GetAttributes( aEditAttr );
    SfxItemSet  aNewAttr( *aEditAttr.GetPool(), aEditAttr.GetRanges() );
 
    bool bSet = true;
    switch ( nSlot )
    {
        case SID_ALIGNLEFT:
        case SID_ALIGN_ANY_LEFT:
        case SID_ATTR_PARA_ADJUST_LEFT:
            aNewAttr.Put( SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ) );
            break;
 
        case SID_ALIGNCENTERHOR:
        case SID_ALIGN_ANY_HCENTER:
        case SID_ATTR_PARA_ADJUST_CENTER:
            aNewAttr.Put( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) );
            break;
 
        case SID_ALIGNRIGHT:
        case SID_ALIGN_ANY_RIGHT:
        case SID_ATTR_PARA_ADJUST_RIGHT:
            aNewAttr.Put( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
            break;
 
        case SID_ALIGNBLOCK:
        case SID_ALIGN_ANY_JUSTIFIED:
        case SID_ATTR_PARA_ADJUST_BLOCK:
            aNewAttr.Put( SvxAdjustItem( SvxAdjust::Block, EE_PARA_JUST ) );
            break;
 
        case SID_ALIGN_ANY_START:
        case SID_ATTR_PARA_ADJUST_START:
            aNewAttr.Put( SvxAdjustItem( SvxAdjust::ParaStart, EE_PARA_JUST ) );
            break;
 
        case SID_ALIGN_ANY_END:
        case SID_ATTR_PARA_ADJUST_END:
            aNewAttr.Put( SvxAdjustItem( SvxAdjust::ParaEnd, EE_PARA_JUST ) );
            break;
 
        case SID_ATTR_PARA_LINESPACE_10:
            {
                SvxLineSpacingItem aItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL );
                aItem.SetPropLineSpace( 100 );
                aNewAttr.Put( aItem );
            }
            break;
 
        case SID_ATTR_PARA_LINESPACE_15:
            {
                SvxLineSpacingItem aItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL );
                aItem.SetPropLineSpace( 150 );
                aNewAttr.Put( aItem );
            }
            break;
 
        case SID_ATTR_PARA_LINESPACE_20:
            {
                SvxLineSpacingItem aItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL );
                aItem.SetPropLineSpace( 200 );
                aNewAttr.Put( aItem );
            }
            break;
 
        case SID_SET_SUPER_SCRIPT:
            {
                SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
                SvxEscapement eEsc = aEditAttr.Get(EE_CHAR_ESCAPEMENT).GetEscapement();
 
                if( eEsc == SvxEscapement::Superscript )
                    aItem.SetEscapement( SvxEscapement::Off );
                else
                    aItem.SetEscapement( SvxEscapement::Superscript );
                aNewAttr.Put( aItem );
            }
            break;
 
        case SID_SET_SUB_SCRIPT:
            {
                SvxEscapementItem aItem(EE_CHAR_ESCAPEMENT);
                SvxEscapement eEsc = aEditAttr.Get(EE_CHAR_ESCAPEMENT).GetEscapement();
 
                if( eEsc == SvxEscapement::Subscript )
                    aItem.SetEscapement( SvxEscapement::Off );
                else
                    aItem.SetEscapement( SvxEscapement::Subscript );
                aNewAttr.Put( aItem );
            }
            break;
 
        case SID_TABLE_VERT_NONE:
        case SID_TABLE_VERT_CENTER:
        case SID_TABLE_VERT_BOTTOM:
            {
                SdrTextVertAdjust eTVA = SDRTEXTVERTADJUST_TOP;
                if (nSlot == SID_TABLE_VERT_CENTER)
                    eTVA = SDRTEXTVERTADJUST_CENTER;
                else if (nSlot == SID_TABLE_VERT_BOTTOM)
                    eTVA = SDRTEXTVERTADJUST_BOTTOM;
                aNewAttr.Put(SdrTextVertAdjustItem(eTVA));
            }
            break;
 
        case SID_PARASPACE_INCREASE:
        case SID_PARASPACE_DECREASE:
        {
            SvxULSpaceItem aULSpace( aEditAttr.Get( EE_PARA_ULSPACE ) );
            sal_uInt16 nUpper = aULSpace.GetUpper();
            sal_uInt16 nLower = aULSpace.GetLower();
 
            if ( nSlot == SID_PARASPACE_INCREASE )
            {
                nUpper += 100;
                nLower += 100;
            }
            else
            {
                nUpper = std::max< sal_Int16 >( nUpper - 100, 0 );
                nLower = std::max< sal_Int16 >( nLower - 100, 0 );
            }
 
            aULSpace.SetUpper( nUpper );
            aULSpace.SetLower( nLower );
            aNewAttr.Put( aULSpace );
        }
        break;
 
        default:
            bSet = false;
    }
 
    bool bDone = true;
    bool bArgsInReq = ( pArgs != nullptr );
 
    if ( !bArgsInReq )
    {
        switch ( nSlot )
        {
            case SID_CELL_FORMAT_RESET:
            case SID_TEXT_STANDARD:
            {
                OutlinerView* pOutView = pView->IsTextEdit() ?
                                pView->GetTextEditOutlinerView() : nullptr;
                if ( pOutView )
                    pOutView->DrawText_ToEditView( tools::Rectangle() );
 
                SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END> aEmptyAttr( *aEditAttr.GetPool() );
                SfxItemSetFixed<SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_MINFRAMEHEIGHT,
                                SDRATTR_TEXT_MAXFRAMEHEIGHT, SDRATTR_TEXT_MAXFRAMEWIDTH> aSizeAttr(*aEditAttr.GetPool());
 
                aSizeAttr.Put(pView->GetAttrFromMarked(true));
                pView->SetAttributes( aEmptyAttr, true );
 
                if (IsNoteEdit())
                {
                    pView->SetAttributes(aSizeAttr, false);
                    pView->GetTextEditObject()->AdjustTextFrameWidthAndHeight();
                }
 
                if ( pOutView )
                {
                    lcl_RemoveFields( *pOutView );
                    pOutView->ShowCursor();
                }
 
                rReq.Done( aEmptyAttr );
                mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
                bDone = false; // already happened here
            }
            break;
 
            case SID_GROW_FONT_SIZE:
            case SID_SHRINK_FONT_SIZE:
            {
                OutlinerView* pOutView = pView->IsTextEdit() ?
                    pView->GetTextEditOutlinerView() : nullptr;
                if ( pOutView )
                {
                    if (SfxObjectShell* pObjSh = SfxObjectShell::Current())
                    {
                        const SvxFontListItem* pFontListItem = pObjSh->GetItem( SID_ATTR_CHAR_FONTLIST );
                        const FontList* pFontList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
                        pOutView->GetEditView().ChangeFontSize( nSlot == SID_GROW_FONT_SIZE, pFontList );
                        mrViewData.GetBindings().Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
                    }
                    bDone = false;
                }
            }
            break;
 
            case SID_CHAR_DLG_EFFECT:
            case SID_CHAR_DLG:                      // dialog button
            case SID_ATTR_CHAR_FONT:                // Controller not shown
            case SID_ATTR_CHAR_FONTHEIGHT:
                bDone = ExecuteCharDlg( aEditAttr, aNewAttr , nSlot);
                break;
 
            case SID_PARA_DLG:
                bDone = ExecuteParaDlg( aEditAttr, aNewAttr );
                break;
 
            case SID_ATTR_CHAR_WEIGHT:
                aNewAttr.Put( aEditAttr.Get( EE_CHAR_WEIGHT ) );
                break;
 
            case SID_ATTR_CHAR_POSTURE:
                aNewAttr.Put( aEditAttr.Get( EE_CHAR_ITALIC ) );
                break;
 
            case SID_ATTR_CHAR_UNDERLINE:
                aNewAttr.Put( aEditAttr.Get( EE_CHAR_UNDERLINE ) );
                break;
 
            case SID_ATTR_CHAR_OVERLINE:
                aNewAttr.Put( aEditAttr.Get( EE_CHAR_OVERLINE ) );
                break;
 
            case SID_ATTR_CHAR_CONTOUR:
                aNewAttr.Put( aEditAttr.Get( EE_CHAR_OUTLINE ) );
                break;
 
            case SID_ATTR_CHAR_SHADOWED:
                aNewAttr.Put( aEditAttr.Get( EE_CHAR_SHADOW ) );
                break;
 
            case SID_ATTR_CHAR_STRIKEOUT:
                aNewAttr.Put( aEditAttr.Get( EE_CHAR_STRIKEOUT ) );
                break;
 
            case SID_DRAWTEXT_ATTR_DLG:
                {
                    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
                    VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateTextTabDialog(mrViewData.GetDialogParent(), &aEditAttr, pView));
                    auto xRequest = std::make_shared<SfxRequest>(rReq);
                    rReq.Ignore(); // the 'old' request is not relevant any more
                    pDlg->StartExecuteAsync(
                        [this, pDlg, pArgs, aNewAttr, bSet, xRequest=std::move(xRequest), pView] (sal_Int32 nResult) mutable -> void
                        {
                            if ( RET_OK == nResult )
                                aNewAttr.Put( *pDlg->GetOutputItemSet() );
 
                            pDlg->disposeOnce();
 
                            SfxBindings& rBindings = mrViewData.GetBindings();
                            rBindings.Invalidate( SID_TABLE_VERT_NONE );
                            rBindings.Invalidate( SID_TABLE_VERT_CENTER );
                            rBindings.Invalidate( SID_TABLE_VERT_BOTTOM );
 
                            if ( bSet || RET_OK == nResult )
                            {
                                xRequest->Done( aNewAttr );
                                pArgs = xRequest->GetArgs();
                            }
                            if (pArgs)
                            {
                                // use args directly
                                pView->SetAttributes( *pArgs );
                                mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
                            }
                        }
                    );
                }
                break;
            case SID_ATTR_CHAR_COLOR:
            case SID_ATTR_CHAR_BACK_COLOR:
            {
                const sal_uInt16 nEEWhich = GetPool().GetWhichIDFromSlotID(nSlot);
                const std::optional<NamedColor> oColor
                    = mrViewData.GetDocShell()->GetRecentColor(nSlot);
                if (oColor.has_value())
                {
                    const model::ComplexColor aCol = (*oColor).getComplexColor();
                    aNewAttr.Put(SvxColorItem(aCol.getFinalColor(), aCol, nEEWhich));
                }
                break;
            }
        }
    }
 
    if ( bSet || bDone )
    {
        rReq.Done( aNewAttr );
        pArgs = rReq.GetArgs();
    }
 
    if ( !pArgs )
        return;
 
    if ( bArgsInReq &&
        ( nSlot == SID_ATTR_CHAR_FONT || nSlot == SID_ATTR_CHAR_FONTHEIGHT ||
          nSlot == SID_ATTR_CHAR_WEIGHT || nSlot == SID_ATTR_CHAR_POSTURE ) )
    {
        // font items from toolbox controller have to be applied for the right script type
 
        // #i78017 establish the same behaviour as in Writer
        SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
        if (nSlot == SID_ATTR_CHAR_FONT)
            nScript = pView->GetScriptType();
 
        SfxItemPool& rPool = GetPool();
        SvxScriptSetItem aSetItem( nSlot, rPool );
        sal_uInt16 nWhich = rPool.GetWhichIDFromSlotID( nSlot );
        aSetItem.PutItemForScriptType( nScript, pArgs->Get( nWhich ) );
 
        pView->SetAttributes( aSetItem.GetItemSet() );
    }
    else if( nSlot == SID_ATTR_PARA_LRSPACE )
    {
        sal_uInt16 nId = SID_ATTR_PARA_LRSPACE;
        const SvxLRSpaceItem& rItem = static_cast<const SvxLRSpaceItem&>(
            pArgs->Get( nId ));
        SfxItemSetFixed<EE_PARA_LRSPACE, EE_PARA_LRSPACE> aAttr( GetPool() );
        nId = EE_PARA_LRSPACE;
        SvxLRSpaceItem aLRSpaceItem(rItem.GetLeft(), rItem.GetRight(),
                                    rItem.GetTextFirstLineOffset(), nId);
        aAttr.Put( aLRSpaceItem );
        pView->SetAttributes( aAttr );
    }
    else if( nSlot == SID_ATTR_PARA_LINESPACE )
    {
        SvxLineSpacingItem aLineSpaceItem = static_cast<const SvxLineSpacingItem&>(pArgs->Get(
                                                            GetPool().GetWhichIDFromSlotID(nSlot)));
        SfxItemSetFixed<EE_PARA_SBL, EE_PARA_SBL> aAttr( GetPool() );
        aAttr.Put( aLineSpaceItem );
        pView->SetAttributes( aAttr );
    }
    else if( nSlot == SID_ATTR_PARA_ULSPACE )
    {
        SvxULSpaceItem aULSpaceItem = static_cast<const SvxULSpaceItem&>(pArgs->Get(
                                                            GetPool().GetWhichIDFromSlotID(nSlot)));
        SfxItemSetFixed<EE_PARA_ULSPACE, EE_PARA_ULSPACE> aAttr( GetPool() );
        aULSpaceItem.SetWhich(EE_PARA_ULSPACE);
        aAttr.Put( aULSpaceItem );
        pView->SetAttributes( aAttr );
    }
    else
    {
        // use args directly
        pView->SetAttributes( *pArgs );
    }
    mrViewData.GetScDrawView()->InvalidateDrawTextAttrs();
}
 
void ScDrawTextObjectBar::GetAttrState( SfxItemSet& rDestSet )
{
    if ( IsNoteEdit() )
    {
        // issue 21255 - Notes now support rich text formatting.
    }
 
    bool bDisableCTLFont = !::SvtCTLOptions::IsCTLFontEnabled();
    bool bDisableVerticalText = !SvtCJKOptions::IsVerticalTextEnabled();
 
    SdrView* pView = mrViewData.GetScDrawView();
    SfxItemSet aAttrSet(pView->GetModel().GetItemPool());
    pView->GetAttributes(aAttrSet);
 
    //  direct attributes
 
    rDestSet.Put( aAttrSet );
 
    //  choose font info according to selection script type
 
    SvtScriptType nScript = pView->GetScriptType();
 
    // #i55929# input-language-dependent script type (depends on input language if nothing selected)
    SvtScriptType nInputScript = nScript;
    OutlinerView* pOutView = pView->GetTextEditOutlinerView();
    if (pOutView && !pOutView->GetSelection().HasRange())
    {
        LanguageType nInputLang = mrViewData.GetActiveWin()->GetInputLanguage();
        if (nInputLang != LANGUAGE_DONTKNOW && nInputLang != LANGUAGE_SYSTEM)
            nInputScript = SvtLanguageOptions::GetScriptTypeOfLanguage( nInputLang );
    }
 
    // #i55929# according to spec, nInputScript is used for font and font height only
    if ( rDestSet.GetItemState( EE_CHAR_FONTINFO ) != SfxItemState::UNKNOWN )
        ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_FONTINFO, nInputScript );
    if ( rDestSet.GetItemState( EE_CHAR_FONTHEIGHT ) != SfxItemState::UNKNOWN )
        ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_FONTHEIGHT, nInputScript );
    if ( rDestSet.GetItemState( EE_CHAR_WEIGHT ) != SfxItemState::UNKNOWN )
        ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_WEIGHT, nScript );
    if ( rDestSet.GetItemState( EE_CHAR_ITALIC ) != SfxItemState::UNKNOWN )
        ScViewUtil::PutItemScript( rDestSet, aAttrSet, EE_CHAR_ITALIC, nScript );
    //  Alignment
 
    SvxAdjust eAdj = aAttrSet.Get(EE_PARA_JUST).GetAdjust();
    switch( eAdj )
    {
    case SvxAdjust::Left:
        {
            rDestSet.Put( SfxBoolItem( SID_ALIGNLEFT, true ) );
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_LEFT, true ) );
        }
        break;
    case SvxAdjust::Center:
        {
            rDestSet.Put( SfxBoolItem( SID_ALIGNCENTERHOR, true ) );
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_CENTER, true ) );
        }
        break;
    case SvxAdjust::Right:
        {
            rDestSet.Put( SfxBoolItem( SID_ALIGNRIGHT, true ) );
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_RIGHT, true ) );
        }
        break;
    case SvxAdjust::Block:
        {
            rDestSet.Put( SfxBoolItem( SID_ALIGNBLOCK, true ) );
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_BLOCK, true ) );
        }
        break;
    case SvxAdjust::ParaStart:
        {
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_START, true ) );
        }
        break;
    case SvxAdjust::ParaEnd:
        {
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_ADJUST_END, true ) );
        }
        break;
        default:
        {
            // added to avoid warnings
        }
    }
    // pseudo slots for Format menu
    rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_LEFT,      eAdj == SvxAdjust::Left ) );
    rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_HCENTER,   eAdj == SvxAdjust::Center ) );
    rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_RIGHT,     eAdj == SvxAdjust::Right ) );
    rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_START,     eAdj == SvxAdjust::ParaStart ) );
    rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_END,       eAdj == SvxAdjust::ParaEnd ) );
    rDestSet.Put( SfxBoolItem( SID_ALIGN_ANY_JUSTIFIED, eAdj == SvxAdjust::Block ) );
 
    SvxLRSpaceItem aLR = aAttrSet.Get( EE_PARA_LRSPACE );
    aLR.SetWhich(SID_ATTR_PARA_LRSPACE);
    rDestSet.Put(aLR);
    Invalidate( SID_ATTR_PARA_LRSPACE );
    SfxItemState eState = aAttrSet.GetItemState( EE_PARA_LRSPACE );
    if ( eState == SfxItemState::INVALID )
        rDestSet.InvalidateItem(SID_ATTR_PARA_LRSPACE);
    //xuxu for Line Space
    SvxLineSpacingItem aLineSP = aAttrSet.Get( EE_PARA_SBL );
    aLineSP.SetWhich(SID_ATTR_PARA_LINESPACE);
    rDestSet.Put(aLineSP);
    Invalidate(SID_ATTR_PARA_LINESPACE);
    eState = aAttrSet.GetItemState( EE_PARA_SBL );
    if ( eState == SfxItemState::INVALID )
        rDestSet.InvalidateItem(SID_ATTR_PARA_LINESPACE);
    //xuxu for UL Space
    SvxULSpaceItem aULSP = aAttrSet.Get( EE_PARA_ULSPACE );
    aULSP.SetWhich(SID_ATTR_PARA_ULSPACE);
    rDestSet.Put(aULSP);
    Invalidate(SID_ATTR_PARA_ULSPACE);
    Invalidate(SID_PARASPACE_INCREASE);
    Invalidate(SID_PARASPACE_DECREASE);
    eState = aAttrSet.GetItemState( EE_PARA_ULSPACE );
    if( eState >= SfxItemState::DEFAULT )
    {
        if ( !aULSP.GetUpper() && !aULSP.GetLower() )
            rDestSet.DisableItem( SID_PARASPACE_DECREASE );
    }
    else
    {
        rDestSet.DisableItem( SID_PARASPACE_INCREASE );
        rDestSet.DisableItem( SID_PARASPACE_DECREASE );
        rDestSet.InvalidateItem(SID_ATTR_PARA_ULSPACE);
    }
 
    //  Line spacing
 
    sal_uInt16 nLineSpace = aAttrSet.Get( EE_PARA_SBL ).GetPropLineSpace();
    switch( nLineSpace )
    {
        case 100:
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LINESPACE_10, true ) );
            break;
        case 150:
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LINESPACE_15, true ) );
            break;
        case 200:
            rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LINESPACE_20, true ) );
            break;
    }
 
    //  super-/subscript
    SvxEscapement eEsc = aAttrSet.Get(EE_CHAR_ESCAPEMENT).GetEscapement();
    rDestSet.Put(SfxBoolItem(SID_SET_SUPER_SCRIPT, eEsc == SvxEscapement::Superscript));
    rDestSet.Put(SfxBoolItem(SID_SET_SUB_SCRIPT, eEsc == SvxEscapement::Subscript));
 
    //  Underline
    eState = aAttrSet.GetItemState( EE_CHAR_UNDERLINE );
    if ( eState == SfxItemState::INVALID )
    {
        rDestSet.InvalidateItem( SID_ULINE_VAL_NONE );
        rDestSet.InvalidateItem( SID_ULINE_VAL_SINGLE );
        rDestSet.InvalidateItem( SID_ULINE_VAL_DOUBLE );
        rDestSet.InvalidateItem( SID_ULINE_VAL_DOTTED );
    }
    else
    {
        FontLineStyle eUnderline = aAttrSet.Get(EE_CHAR_UNDERLINE).GetLineStyle();
        rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_SINGLE, eUnderline == LINESTYLE_SINGLE));
        rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_DOUBLE, eUnderline == LINESTYLE_DOUBLE));
        rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_DOTTED, eUnderline == LINESTYLE_DOTTED));
        rDestSet.Put(SfxBoolItem(SID_ULINE_VAL_NONE, eUnderline == LINESTYLE_NONE));
    }
 
    //  horizontal / vertical
 
    bool bLeftToRight = true;
 
    SdrOutliner* pOutl = pView->GetTextEditOutliner();
    if( pOutl )
    {
        if( pOutl->IsVertical() )
            bLeftToRight = false;
    }
    else
        bLeftToRight = aAttrSet.Get( SDRATTR_TEXTDIRECTION ).GetValue() == css::text::WritingMode_LR_TB;
 
    if ( bDisableVerticalText )
    {
        rDestSet.DisableItem( SID_TEXTDIRECTION_LEFT_TO_RIGHT );
        rDestSet.DisableItem( SID_TEXTDIRECTION_TOP_TO_BOTTOM );
    }
    else
    {
        rDestSet.Put( SfxBoolItem( SID_TEXTDIRECTION_LEFT_TO_RIGHT, bLeftToRight ) );
        rDestSet.Put( SfxBoolItem( SID_TEXTDIRECTION_TOP_TO_BOTTOM, !bLeftToRight ) );
    }
 
    //  left-to-right or right-to-left
 
    if ( !bLeftToRight || bDisableCTLFont )
    {
        //  disabled if vertical
        rDestSet.DisableItem( SID_ATTR_PARA_LEFT_TO_RIGHT );
        rDestSet.DisableItem( SID_ATTR_PARA_RIGHT_TO_LEFT );
    }
    else if ( aAttrSet.GetItemState( EE_PARA_WRITINGDIR ) == SfxItemState::INVALID )
    {
        rDestSet.InvalidateItem( SID_ATTR_PARA_LEFT_TO_RIGHT );
        rDestSet.InvalidateItem( SID_ATTR_PARA_RIGHT_TO_LEFT );
    }
    else
    {
        SvxFrameDirection eAttrDir = aAttrSet.Get( EE_PARA_WRITINGDIR ).GetValue();
        if ( eAttrDir == SvxFrameDirection::Environment )
        {
            //  get "environment" direction from page style
            if ( mrViewData.GetDocument().GetEditTextDirection( mrViewData.CurrentTabForData() ) == EEHorizontalTextDirection::R2L )
                eAttrDir = SvxFrameDirection::Horizontal_RL_TB;
            else
                eAttrDir = SvxFrameDirection::Horizontal_LR_TB;
        }
        rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_LEFT_TO_RIGHT, ( eAttrDir == SvxFrameDirection::Horizontal_LR_TB ) ) );
        rDestSet.Put( SfxBoolItem( SID_ATTR_PARA_RIGHT_TO_LEFT, ( eAttrDir == SvxFrameDirection::Horizontal_RL_TB ) ) );
    }
}
 
void ScDrawTextObjectBar::ExecuteTrans( const SfxRequest& rReq )
{
    TransliterationFlags nType = ScViewUtil::GetTransliterationType( rReq.GetSlot() );
    if ( nType == TransliterationFlags::NONE )
        return;
 
    ScDrawView* pView = mrViewData.GetScDrawView();
    OutlinerView* pOutView = pView->GetTextEditOutlinerView();
    if ( pOutView )
    {
        //  change selected text in object
        pOutView->TransliterateText( nType );
    }
    else
    {
        //! apply to whole objects?
    }
}
 
void ScDrawTextObjectBar::GetStatePropPanelAttr(SfxItemSet &rSet)
{
    SfxWhichIter    aIter( rSet );
    sal_uInt16          nWhich = aIter.FirstWhich();
 
    SdrView*            pView = mrViewData.GetScDrawView();
 
    SfxItemSet aEditAttr(pView->GetModel().GetItemPool());
    pView->GetAttributes(aEditAttr);
    //SfxItemSet    aAttrs( *aEditAttr.GetPool(), aEditAttr.GetRanges() );
 
    while ( nWhich )
    {
        sal_uInt16 nSlotId = SfxItemPool::IsWhich(nWhich)
            ? GetPool().GetSlotId(nWhich)
            : nWhich;
        switch ( nSlotId )
        {
            case SID_TABLE_VERT_NONE:
            case SID_TABLE_VERT_CENTER:
            case SID_TABLE_VERT_BOTTOM:
                bool bContour = false;
                SfxItemState eConState = aEditAttr.GetItemState( SDRATTR_TEXT_CONTOURFRAME );
                if( eConState != SfxItemState::INVALID )
                {
                    bContour = aEditAttr.Get( SDRATTR_TEXT_CONTOURFRAME ).GetValue();
                }
                if (bContour) break;
 
                SfxItemState eVState = aEditAttr.GetItemState( SDRATTR_TEXT_VERTADJUST );
                //SfxItemState eHState = aAttrs.GetItemState( SDRATTR_TEXT_HORZADJUST );
 
                //if(SfxItemState::INVALID != eVState && SfxItemState::INVALID != eHState)
                if(SfxItemState::INVALID != eVState)
                {
                    SdrTextVertAdjust eTVA = aEditAttr.Get(SDRATTR_TEXT_VERTADJUST).GetValue();
                    bool bSet = (nSlotId == SID_TABLE_VERT_NONE && eTVA == SDRTEXTVERTADJUST_TOP) ||
                            (nSlotId == SID_TABLE_VERT_CENTER && eTVA == SDRTEXTVERTADJUST_CENTER) ||
                            (nSlotId == SID_TABLE_VERT_BOTTOM && eTVA == SDRTEXTVERTADJUST_BOTTOM);
                    rSet.Put(SfxBoolItem(nSlotId, bSet));
                }
                else
                {
                    rSet.Put(SfxBoolItem(nSlotId, false));
                }
                break;
        }
        nWhich = aIter.NextWhich();
    }
}
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

V530 The return value of function 'Execute' is required to be utilized.

V530 The return value of function 'Execute' is required to be utilized.

V530 The return value of function 'Execute' is required to be utilized.