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


Quelle  chardlg.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 <vcl/idle.hxx>
#include <svtools/ctrltool.hxx>
#include <sfx2/objsh.hxx>
#include <svx/svxids.hrc>
#include <svtools/unitconv.hxx>
#include <svl/cjkoptions.hxx>
#include <svl/ctloptions.hxx>
#include <chardlg.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/postitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/crossedoutitem.hxx>
#include <editeng/contouritem.hxx>
#include <editeng/langitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/shdditem.hxx>
#include <editeng/escapementitem.hxx>
#include <editeng/wrlmitem.hxx>
#include <editeng/cmapitem.hxx>
#include <editeng/kernitem.hxx>
#include <editeng/flstitem.hxx>
#include <editeng/autokernitem.hxx>
#include <editeng/nhypitem.hxx>
#include <editeng/colritem.hxx>
#include <dialmgr.hxx>
#include <sfx2/htmlmode.hxx>
#include <svx/cuicharmap.hxx>
#include "chardlg.h"
#include <editeng/emphasismarkitem.hxx>
#include <editeng/charreliefitem.hxx>
#include <editeng/twolinesitem.hxx>
#include <editeng/charhiddenitem.hxx>
#include <editeng/charscaleitem.hxx>
#include <editeng/charrotateitem.hxx>
#include <officecfg/Office/Common.hxx>
#include <strings.hrc>
#include <twolines.hrc>
#include <svl/intitem.hxx>
#include <svx/flagsdef.hxx>
#include <FontFeatures.hxx>
#include <FontFeaturesDialog.hxx>
#include <sal/log.hxx>
#include <osl/diagnose.h>
#include <o3tl/unit_conversion.hxx>
#include <o3tl/string_view.hxx>

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

// static ----------------------------------------------------------------

const WhichRangesContainer SvxCharNamePage::pNameRanges(svl::Items<
    SID_ATTR_CHAR_FONT, SID_ATTR_CHAR_WEIGHT,
    SID_ATTR_CHAR_FONTHEIGHT, SID_ATTR_CHAR_FONTHEIGHT,
    SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
    SID_ATTR_CHAR_LANGUAGE, SID_ATTR_CHAR_LANGUAGE,
    SID_ATTR_CHAR_CJK_FONT, SID_ATTR_CHAR_CJK_WEIGHT,
    SID_ATTR_CHAR_CTL_FONT, SID_ATTR_CHAR_CTL_WEIGHT
>);

const WhichRangesContainer SvxCharEffectsPage::pEffectsRanges(svl::Items<
    SID_ATTR_CHAR_SHADOWED, SID_ATTR_CHAR_UNDERLINE,
    SID_ATTR_CHAR_COLOR, SID_ATTR_CHAR_COLOR,
    SID_ATTR_CHAR_CASEMAP, SID_ATTR_CHAR_CASEMAP,
    SID_ATTR_FLASH, SID_ATTR_FLASH,
    SID_ATTR_CHAR_EMPHASISMARK, SID_ATTR_CHAR_EMPHASISMARK,
    SID_ATTR_CHAR_RELIEF, SID_ATTR_CHAR_RELIEF,
    SID_ATTR_CHAR_HIDDEN, SID_ATTR_CHAR_HIDDEN,
    SID_ATTR_CHAR_OVERLINE, SID_ATTR_CHAR_OVERLINE
>);

const WhichRangesContainer SvxCharPositionPage::pPositionRanges(svl::Items<
    SID_ATTR_CHAR_KERNING, SID_ATTR_CHAR_KERNING,
    SID_ATTR_CHAR_ESCAPEMENT, SID_ATTR_CHAR_ESCAPEMENT,
    SID_ATTR_CHAR_AUTOKERN, SID_ATTR_CHAR_AUTOKERN,
    SID_ATTR_CHAR_ROTATED, SID_ATTR_CHAR_SCALEWIDTH,
    SID_ATTR_CHAR_WIDTH_FIT_TO_LINE, SID_ATTR_CHAR_WIDTH_FIT_TO_LINE
>);

const WhichRangesContainer SvxCharTwoLinesPage::pTwoLinesRanges(svl::Items<
    SID_ATTR_CHAR_TWO_LINES, SID_ATTR_CHAR_TWO_LINES
>);

// C-Function ------------------------------------------------------------

static bool StateToAttr( TriState aState )
{
    return ( TRISTATE_TRUE == aState );
}

namespace
{
    void setPrevFontEscapement(SvxFont& _rFont,sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
    {
        _rFont.SetPropr( nProp );
        _rFont.SetProprRel( nEscProp );
        _rFont.SetEscapement( nEsc );
    }
}

inline SvxFont& SvxCharBasePage::GetPreviewFont()
{
    return m_aPreviewWin.GetFont();
}

inline SvxFont& SvxCharBasePage::GetPreviewCJKFont()
{
    return m_aPreviewWin.GetCJKFont();
}

inline SvxFont& SvxCharBasePage::GetPreviewCTLFont()
{
    return m_aPreviewWin.GetCTLFont();
}

SvxCharBasePage::SvxCharBasePage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OUString& rID, const SfxItemSet& rItemset)
    : SfxTabPage(pPage, pController, rUIXMLDescription, rID, &rItemset)
    , m_bPreviewBackgroundToCharacter( false )
{
}

SvxCharBasePage::~SvxCharBasePage()
{
}

void SvxCharBasePage::ActivatePage(const SfxItemSet& rSet)
{
    m_aPreviewWin.SetFromItemSet(rSet, m_bPreviewBackgroundToCharacter);
}

void SvxCharBasePage::SetPrevFontWidthScale( const SfxItemSet& rSet )
{
    sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_SCALEWIDTH );
    if (rSet.GetItemState(nWhich)>=SfxItemState::DEFAULT)
    {
        const SvxCharScaleWidthItem &rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
        m_aPreviewWin.SetFontWidthScale(rItem.GetValue());
    }
}

void SvxCharBasePage::SetPrevFontEscapement( sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc )
{
    setPrevFontEscapement(GetPreviewFont(),nProp,nEscProp,nEsc);
    setPrevFontEscapement(GetPreviewCJKFont(),nProp,nEscProp,nEsc);
    setPrevFontEscapement(GetPreviewCTLFont(),nProp,nEscProp,nEsc);
    m_aPreviewWin.Invalidate();
}


// SvxCharNamePage_Impl --------------------------------------------------

struct SvxCharNamePage_Impl
{
    Idle            m_aUpdateIdle { "cui SvxCharNamePage_Impl m_aUpdateIdle" };
    OUString        m_aNoStyleText;
    std::unique_ptr<FontList> m_pFontList;
    int             m_nExtraEntryPos;
    bool            m_bInSearchMode;

    SvxCharNamePage_Impl()
        : m_nExtraEntryPos(std::numeric_limits<int>::max())
        , m_bInSearchMode(false)

    {
        m_aUpdateIdle.SetPriority( TaskPriority::LOWEST );
    }
};

// class SvxCharNamePage -------------------------------------------------

SvxCharNamePage::SvxCharNamePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
    : SvxCharBasePage(pPage, pController, u"cui/ui/charnamepage.ui"_ustr, u"CharNamePage"_ustr, rInSet)
    , m_pImpl(new SvxCharNamePage_Impl)
    // Western
    , m_xWestern(m_xBuilder->weld_notebook(u"nbWestern"_ustr))
    , m_xWestFontNameFT(m_xBuilder->weld_label(u"lbWestFontname"_ustr))
    , m_xWestFontStyleFT(m_xBuilder->weld_label(u"lbWestStyle"_ustr))
    , m_xWestFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box(u"cbWestStyle"_ustr)))
    , m_xWestFontSizeFT(m_xBuilder->weld_label(u"lbWestSize"_ustr))
    , m_xWestFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box(u"cbWestSize"_ustr)))
    , m_xWestFontLanguageFT(m_xBuilder->weld_label(u"lbWestLanguage"_ustr))
    , m_xWestFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"cbWestLanguage"_ustr)))
    , m_xWestFontFeaturesButton(m_xBuilder->weld_button(u"btnWestFeatures"_ustr))
    , m_xWestFontTypeFT(m_xBuilder->weld_label(u"lbWestFontinfo"_ustr))
    , m_xCJK_CTL(m_xBuilder->weld_notebook(u"nbCJKCTL"_ustr))
    // CJK
    , m_xEastFontNameFT(m_xBuilder->weld_label(u"lbCJKFontname"_ustr))
    , m_xEastFontStyleFT(m_xBuilder->weld_label(u"lbCJKStyle"_ustr))
    , m_xEastFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box(u"cbCJKStyle"_ustr)))
    , m_xEastFontSizeFT(m_xBuilder->weld_label(u"lbCJKSize"_ustr))
    , m_xEastFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box(u"cbCJKSize"_ustr)))
    , m_xEastFontLanguageFT(m_xBuilder->weld_label(u"lbCJKLanguage"_ustr))
    , m_xEastFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"cbCJKLanguage"_ustr)))
    , m_xEastFontFeaturesButton(m_xBuilder->weld_button(u"btnCJKFeatures"_ustr))
    , m_xEastFontTypeFT(m_xBuilder->weld_label(u"lbCJKFontinfo"_ustr))
    // CTL
    , m_xCTLFontNameFT(m_xBuilder->weld_label(u"lbCTLFontname"_ustr))
    // tree
    , m_xCTLFontStyleFT(m_xBuilder->weld_label(u"lbCTLStyle"_ustr))
    , m_xCTLFontStyleLB(new FontStyleBox(m_xBuilder->weld_combo_box(u"cbCTLStyle"_ustr)))
    , m_xCTLFontSizeFT(m_xBuilder->weld_label(u"lbCTLSize"_ustr))
    , m_xCTLFontSizeLB(new FontSizeBox(m_xBuilder->weld_combo_box(u"cbCTLSize"_ustr)))
    , m_xCTLFontLanguageFT(m_xBuilder->weld_label(u"lbCTLLanguage"_ustr))
    , m_xCTLFontLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"cbCTLLanguage"_ustr)))
    , m_xCTLFontFeaturesButton(m_xBuilder->weld_button(u"btnCTLFeatures"_ustr))
    , m_xCTLFontTypeFT(m_xBuilder->weld_label(u"lbCTLFontinfo"_ustr))

    , m_xVDev(*Application::GetDefaultDevice(), DeviceFormat::WITH_ALPHA)
{
    m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWin));
#ifdef IOS
    m_xPreviewWin->hide();
#endif
    m_pImpl->m_aNoStyleText = CuiResId( RID_CUISTR_CHARNAME_NOSTYLE );

    std::unique_ptr<weld::EntryTreeView> xWestFontName = m_xBuilder->weld_entry_tree_view(u"gdWestern"_ustr, u"edWestFontName"_ustr, u"trWestFontName"_ustr);
    std::unique_ptr<weld::EntryTreeView> xCJKFontName = m_xBuilder->weld_entry_tree_view(u"gdCJK"_ustr, u"edCJKFontName"_ustr, u"trCJKFontName"_ustr);
    std::unique_ptr<weld::EntryTreeView> xCTLFontName = m_xBuilder->weld_entry_tree_view(u"gdCTL"_ustr, u"edCTLFontName"_ustr, u"trCTLFontName"_ustr);

    // 7 lines in the treeview
    xWestFontName->set_height_request_by_rows(7);
    xCJKFontName->set_height_request_by_rows(7);
    xCTLFontName->set_height_request_by_rows(7);

    m_xWestFontNameLB = std::move(xWestFontName);
    m_xEastFontNameLB = std::move(xCJKFontName);
    m_xCTLFontNameLB = std::move(xCTLFontName);

    bool bShowCJK = SvtCJKOptions::IsCJKFontEnabled();
    bool bShowCTL = SvtCTLOptions::IsCTLFontEnabled();
    bool bShowNonWestern = bShowCJK || bShowCTL;
    if (!bShowNonWestern)
    {
        m_xCJK_CTL->hide();
        m_xWestern->set_show_tabs(false); //hide single tab in case of Western only
    }
    else if (!bShowCJK) m_xCJK_CTL->remove_page(u"nbCJK"_ustr);
    else if (!bShowCTL) m_xCJK_CTL->remove_page(u"nbCTL"_ustr);


    //In MacOSX the standard dialogs name font-name, font-style as
    //Family, Typeface
    //In GNOME the standard dialogs name font-name, font-style as
    //Family, Style
    //In Windows the standard dialogs name font-name, font-style as
    //Font, Style
#ifdef _WIN32
    OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FONT));
#else
    OUString sFontFamilyString(CuiResId(RID_CUISTR_CHARNAME_FAMILY));
#endif
    m_xWestFontNameFT->set_label(sFontFamilyString);
    m_xCTLFontNameFT->set_label(sFontFamilyString);
    m_xEastFontNameFT->set_label(sFontFamilyString);

#ifdef MACOSX
    OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_TYPEFACE));
#else
    OUString sFontStyleString(CuiResId(RID_CUISTR_CHARNAME_STYLE));
#endif
    m_xWestFontStyleFT->set_label(sFontStyleString);
    m_xEastFontStyleFT->set_label(sFontStyleString);
    m_xCTLFontStyleFT->set_label(sFontStyleString);

    m_xWestFontLanguageLB->SetLanguageList(SvxLanguageListFlags::WESTERN, truefalsetruetrue,
                                             LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN);
    m_xEastFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CJK, truefalsetruetrue,
                                            LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN);
    m_xCTLFontLanguageLB->SetLanguageList(SvxLanguageListFlags::CTL, truefalsetruetrue,
                                            LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX);
    int nVisibleChars = 15;
    // read-only combobox / HasEntry asserts on set_width_char()
    m_xWestFontLanguageLB->set_width_chars(nVisibleChars);
    m_xEastFontLanguageLB->set_width_chars(nVisibleChars);
    m_xCTLFontLanguageLB->set_width_chars(nVisibleChars);

    Initialize();
}

SvxCharNamePage::~SvxCharNamePage()
{
    m_pImpl.reset();
    m_xCTLFontStyleLB.reset();
    m_xEastFontLanguageLB.reset();
    m_xWestFontStyleLB.reset();
    m_xCTLFontSizeLB.reset();
    m_xEastFontSizeLB.reset();
    m_xWestFontSizeLB.reset();
    m_xWestFontLanguageLB.reset();
    m_xPreviewWin.reset();
    m_xCTLFontLanguageLB.reset();
    m_xEastFontLanguageLB.reset();
}

void SvxCharNamePage::Initialize()
{
    // to handle the changes of the other pages
    SetExchangeSupport();

    Link<weld::ComboBox&,void> aLink = LINK(this, SvxCharNamePage, FontModifyComboBoxHdl_Impl);
    m_xWestFontNameLB->connect_changed(aLink);
    m_xWestFontStyleLB->connect_changed(aLink);
    m_xWestFontSizeLB->connect_changed(aLink);
    m_xWestFontLanguageLB->connect_changed(aLink);

    m_xWestFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));

    m_xEastFontNameLB->connect_changed(aLink);
    m_xEastFontStyleLB->connect_changed(aLink);
    m_xEastFontSizeLB->connect_changed(aLink);
    m_xEastFontLanguageLB->connect_changed(aLink);
    m_xEastFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));

    m_xCTLFontNameLB->connect_changed(aLink);
    m_xCTLFontStyleLB->connect_changed(aLink);
    m_xCTLFontSizeLB->connect_changed(aLink);
    m_xCTLFontLanguageLB->connect_changed(aLink);
    m_xCTLFontFeaturesButton->connect_clicked(LINK(this, SvxCharNamePage, FontFeatureButtonClicked));

    m_pImpl->m_aUpdateIdle.SetInvokeHandler( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) );
}

const FontList* SvxCharNamePage::GetFontList() const
{
    if ( !m_pImpl->m_pFontList )
    {
        /* #110771# SvxFontListItem::GetFontList can return NULL */
        if (SfxObjectShell* pDocSh = SfxObjectShell::Current())
        {
            const SfxPoolItem* pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST );
            if ( pItem != nullptr )
            {
                DBG_ASSERT(nullptr != static_cast<const SvxFontListItem*>(pItem)->GetFontList(),
                           "Where is the font list?");
                m_pImpl->m_pFontList = static_cast<const SvxFontListItem*>(pItem )->GetFontList()->Clone();
            }
        }
        if(!m_pImpl->m_pFontList)
        {
            m_pImpl->m_pFontList.reset(new FontList( Application::GetDefaultDevice() ));
        }
    }

    return m_pImpl->m_pFontList.get();
}


namespace
{
    FontMetric calcFontMetrics(  SvxFont& _rFont,
                    SvxCharNamePage const * _pPage,
                    const weld::ComboBox* _pFontNameLB,
                    const FontStyleBox* _pFontStyleLB,
                    const FontSizeBox* _pFontSizeLB,
                    const SvxLanguageBox* _pLanguageLB,
                    const FontList* _pFontList,
                    sal_uInt16 _nFontWhich,
                    sal_uInt16 _nFontHeightWhich)
    {
        Size aSize = _rFont.GetFontSize();
        aSize.setWidth( 0 );
        FontMetric aFontMetrics;
        OUString sFontName(_pFontNameLB->get_active_text());
        bool bFontAvailable = _pFontList->IsAvailable( sFontName );
        if (bFontAvailable  || _pFontNameLB->get_value_changed_from_saved())
            aFontMetrics = _pFontList->Get(sFontName, _pFontStyleLB->get_active_text());
        else
        {
            //get the font from itemset
            SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontWhich );
            if ( eState >= SfxItemState::DEFAULT )
            {
                const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(&( _pPage->GetItemSet().Get( _nFontWhich ) ));
                aFontMetrics.SetFamilyName(pFontItem->GetFamilyName());
                aFontMetrics.SetStyleName(pFontItem->GetStyleName());
                aFontMetrics.SetFamily(pFontItem->GetFamily());
                aFontMetrics.SetPitch(pFontItem->GetPitch());
                aFontMetrics.SetCharSet(pFontItem->GetCharSet());
            }
        }
        if ( _pFontSizeLB->IsRelative() )
        {
            DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" );
            const SvxFontHeightItem& rOldItem = static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nFontHeightWhich ));

            // old value, scaled
            tools::Long nHeight;
            if ( _pFontSizeLB->IsPtRelative() )
                nHeight = rOldItem.GetHeight()
                          + o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
                                          o3tl::Length::twip) / 10;
            else
                nHeight = static_cast<tools::Long>(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100);

            // conversion twips for the example-window
            aSize.setHeight(
                ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) );
        }
        else if ( !_pFontSizeLB->get_active_text().isEmpty() )
            aSize.setHeight(o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt,
                                          o3tl::Length::twip) / 10);
        else
            aSize.setHeight( 200 );   // default 10pt
        aFontMetrics.SetFontSize( aSize );

        _rFont.SetLanguage(_pLanguageLB->get_active_id());

        _rFont.SetFamily( aFontMetrics.GetFamilyTypeMaybeAskConfig() );
        _rFont.SetFamilyName( aFontMetrics.GetFamilyName() );
        _rFont.SetStyleName( aFontMetrics.GetStyleName() );
        _rFont.SetPitch( aFontMetrics.GetPitchMaybeAskConfig() );
        _rFont.SetCharSet( aFontMetrics.GetCharSet() );
        _rFont.SetWeight( aFontMetrics.GetWeightMaybeAskConfig() );
        _rFont.SetItalic( aFontMetrics.GetItalicMaybeAskConfig() );
        _rFont.SetFontSize( aFontMetrics.GetFontSize() );

        return aFontMetrics;
    }
}


void SvxCharNamePage::UpdatePreview_Impl()
{
    SvxFont& rFont = GetPreviewFont();
    SvxFont& rCJKFont = GetPreviewCJKFont();
    SvxFont& rCTLFont = GetPreviewCTLFont();
    // Font
    const FontList* pFontList = GetFontList();

    FontMetric aWestFontMetric = calcFontMetrics(rFont, this, m_xWestFontNameLB.get(),
        m_xWestFontStyleLB.get(), m_xWestFontSizeLB.get(), m_xWestFontLanguageLB.get(),
        pFontList, GetWhich(SID_ATTR_CHAR_FONT),
        GetWhich(SID_ATTR_CHAR_FONTHEIGHT));

    m_xWestFontTypeFT->set_label(pFontList->GetFontMapText(aWestFontMetric));

    FontMetric aEastFontMetric = calcFontMetrics(rCJKFont, this, m_xEastFontNameLB.get(),
        m_xEastFontStyleLB.get(), m_xEastFontSizeLB.get(), m_xEastFontLanguageLB.get(),
        pFontList, GetWhich(SID_ATTR_CHAR_CJK_FONT),
        GetWhich(SID_ATTR_CHAR_CJK_FONTHEIGHT));

    m_xEastFontTypeFT->set_label(pFontList->GetFontMapText(aEastFontMetric));

    FontMetric aCTLFontMetric = calcFontMetrics(rCTLFont,
        this, m_xCTLFontNameLB.get(), m_xCTLFontStyleLB.get(), m_xCTLFontSizeLB.get(),
        m_xCTLFontLanguageLB.get(), pFontList, GetWhich(SID_ATTR_CHAR_CTL_FONT),
        GetWhich(SID_ATTR_CHAR_CTL_FONTHEIGHT));

    m_xCTLFontTypeFT->set_label(pFontList->GetFontMapText(aCTLFontMetric));

    m_aPreviewWin.Invalidate();
}
void SvxCharNamePage::EnableFeatureButton(const weld::Widget& rNameBox)
{
    OUString sFontName;
    weld::Button* pButton= nullptr;
    if (m_xWestFontNameLB.get() == &rNameBox)
    {
        sFontName = m_xWestFontNameLB->get_active_text();
        pButton= m_xWestFontFeaturesButton.get();
    }
    else if (m_xEastFontNameLB.get() == &rNameBox)
    {
        sFontName = m_xEastFontNameLB->get_active_text();
        pButton=m_xEastFontFeaturesButton.get();
    }
    else if (m_xCTLFontNameLB.get() == &rNameBox)
    {
        sFontName = m_xCTLFontNameLB->get_active_text();
        pButton= m_xCTLFontFeaturesButton.get();
    }
    else
    {
        SAL_WARN( "cui.tabpages""invalid font name box" );
        return;
    }

    bool  bEnable = !getFontFeatureList(sFontName, *m_xVDev).empty();

    pButton->set_sensitive(bEnable);
}

void SvxCharNamePage::FillStyleBox_Impl(const weld::Widget& rNameBox)
{
    const FontList* pFontList = GetFontList();
    assert(pFontList && "no fontlist");

    FontStyleBox* pStyleBox = nullptr;
    OUString sFontName;

    if (m_xWestFontNameLB.get() == &rNameBox)
    {
        pStyleBox = m_xWestFontStyleLB.get();
        sFontName = m_xWestFontNameLB->get_active_text();
    }
    else if (m_xEastFontNameLB.get() == &rNameBox)
    {
        pStyleBox = m_xEastFontStyleLB.get();
        sFontName = m_xEastFontStyleLB->get_active_text();
    }
    else if (m_xCTLFontNameLB.get() == &rNameBox)
    {
        pStyleBox = m_xCTLFontStyleLB.get();
        sFontName = m_xCTLFontNameLB->get_active_text();
    }
    else
    {
        SAL_WARN( "cui.tabpages""invalid font name box" );
        return;
    }

    pStyleBox->Fill(sFontName, pFontList);

    if ( !m_pImpl->m_bInSearchMode )
        return;

    // additional entries for the search:
    // "not bold" and "not italic"
    OUString aEntry = m_pImpl->m_aNoStyleText;
    const char sS[] = "%1";
    aEntry = aEntry.replaceFirst( sS, pFontList->GetBoldStr() );
    m_pImpl->m_nExtraEntryPos = pStyleBox->get_count();
    pStyleBox->append_text( aEntry );
    aEntry = m_pImpl->m_aNoStyleText;
    aEntry = aEntry.replaceFirst( sS, pFontList->GetItalicStr() );
    pStyleBox->append_text(aEntry);
}

void SvxCharNamePage::FillSizeBox_Impl(const weld::Widget& rNameBox)
{
    const FontList* pFontList = GetFontList();
    DBG_ASSERT( pFontList, "no fontlist" );

    FontSizeBox* pSizeBox = nullptr;

    if (m_xWestFontNameLB.get() == &rNameBox)
    {
        pSizeBox = m_xWestFontSizeLB.get();
    }
    else if (m_xEastFontNameLB.get() == &rNameBox)
    {
        pSizeBox = m_xEastFontSizeLB.get();
    }
    else if (m_xCTLFontNameLB.get() == &rNameBox)
    {
        pSizeBox = m_xCTLFontSizeLB.get();
    }
    else
    {
        SAL_WARN( "cui.tabpages""invalid font name box" );
        return;
    }

    pSizeBox->Fill( pFontList );
}

namespace
{
    void FillFontNames(weld::ComboBox& rBox, const FontList& rList)
    {
        // insert fonts
        sal_uInt16 nFontCount = rList.GetFontNameCount();
        std::vector<weld::ComboBoxEntry> aVector;
        aVector.reserve(nFontCount);
        for (sal_uInt16 i = 0; i < nFontCount; ++i)
        {
            const FontMetric& rFontMetric = rList.GetFontName(i);
            aVector.emplace_back(rFontMetric.GetFamilyName());
        }
        rBox.insert_vector(aVector, false);
    }
}

void SvxCharNamePage::Reset_Impl( const SfxItemSet& rSet, LanguageGroup eLangGrp )
{
    weld::ComboBox* pNameBox = nullptr;
    weld::Label* pStyleLabel = nullptr;
    FontStyleBox* pStyleBox = nullptr;
    weld::Label* pSizeLabel = nullptr;
    FontSizeBox* pSizeBox = nullptr;
    weld::Label* pLangFT = nullptr;
    SvxLanguageBox* pLangBox = nullptr;
    sal_uInt16 nWhich = 0;

    switch ( eLangGrp )
    {
        case Western :
            pNameBox = m_xWestFontNameLB.get();
            pStyleLabel = m_xWestFontStyleFT.get();
            pStyleBox = m_xWestFontStyleLB.get();
            pSizeLabel = m_xWestFontSizeFT.get();
            pSizeBox = m_xWestFontSizeLB.get();
            pLangFT = m_xWestFontLanguageFT.get();
            pLangBox = m_xWestFontLanguageLB.get();
            nWhich = GetWhich( SID_ATTR_CHAR_FONT );
            break;

        case Asian :
            pNameBox = m_xEastFontNameLB.get();
            pStyleLabel = m_xEastFontStyleFT.get();
            pStyleBox = m_xEastFontStyleLB.get();
            pSizeLabel = m_xEastFontSizeFT.get();
            pSizeBox = m_xEastFontSizeLB.get();
            pLangFT = m_xEastFontLanguageFT.get();
            pLangBox = m_xEastFontLanguageLB.get();
            nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONT );
            break;

        case Ctl :
            pNameBox = m_xCTLFontNameLB.get();
            pStyleLabel = m_xCTLFontStyleFT.get();
            pStyleBox = m_xCTLFontStyleLB.get();
            pSizeLabel = m_xCTLFontSizeFT.get();
            pSizeBox = m_xCTLFontSizeLB.get();
            pLangFT = m_xCTLFontLanguageFT.get();
            pLangBox = m_xCTLFontLanguageLB.get();
            nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONT );
            break;
    }

    const FontList* pFontList = GetFontList();
    FillFontNames(*pNameBox, *pFontList);

    const SvxFontItem* pFontItem = nullptr;
    SfxItemState eState = rSet.GetItemState( nWhich );

    if ( eState >= SfxItemState::DEFAULT )
    {
        pFontItem = static_cast<const SvxFontItem*>(&( rSet.Get( nWhich ) ));
        const OUString &rName = pFontItem->GetFamilyName();
        int nIndex = pNameBox->find_text(rName);
        pNameBox->set_active(nIndex);
        // tdf#122992 if it didn't exist in the list, set the entry text to it anyway
        if (nIndex == -1)
            pNameBox->set_entry_text(rName);
    }
    else
    {
        pNameBox->set_active_text( OUString() );
    }

    FillStyleBox_Impl(*pNameBox);

    bool bStyle = false;
    bool bStyleAvailable = true;
    FontItalic eItalic = ITALIC_NONE;
    FontWeight eWeight = WEIGHT_NORMAL;
    switch ( eLangGrp )
    {
        case Western : nWhich = GetWhich( SID_ATTR_CHAR_POSTURE ); break;
        case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_POSTURE ); break;
        case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_POSTURE ); break;
    }
    eState = rSet.GetItemState( nWhich );

    if ( eState >= SfxItemState::DEFAULT )
    {
        const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>(rSet.Get( nWhich ));
        eItalic = rItem.GetValue();
        bStyle = true;
    }
    bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::INVALID);

    switch ( eLangGrp )
    {
        case Western : nWhich = GetWhich( SID_ATTR_CHAR_WEIGHT ); break;
        case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_WEIGHT ); break;
        case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_WEIGHT ); break;
    }
    eState = rSet.GetItemState( nWhich );

    if ( eState >= SfxItemState::DEFAULT )
    {
        const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>(rSet.Get( nWhich ));
        eWeight = rItem.GetValue();
    }
    else
        bStyle = false;
    bStyleAvailable = bStyleAvailable && (eState >= SfxItemState::INVALID);

    // currently chosen font
    if ( bStyle && pFontItem )
    {
        FontMetric aFontMetric = pFontList->Get( pFontItem->GetFamilyName(), eWeight, eItalic );
        pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
    }
    else if ( !m_pImpl->m_bInSearchMode || !bStyle )
    {
        pStyleBox->set_active_text( OUString() );
    }
    else if ( bStyle )
    {
        FontMetric aFontMetric = pFontList->Get( OUString(), eWeight, eItalic );
        pStyleBox->set_active_text( pFontList->GetStyleName( aFontMetric ) );
    }
    if (!bStyleAvailable)
    {
        pStyleBox->set_sensitive(false);
        pStyleLabel->set_sensitive(false);
    }

    FillSizeBox_Impl(*pNameBox);
    switch ( eLangGrp )
    {
        case Western : nWhich = GetWhich( SID_ATTR_CHAR_FONTHEIGHT ); break;
        case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); break;
        case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); break;
    }
    eState = rSet.GetItemState( nWhich );

    if ( pSizeBox->IsRelativeMode() )
    {
        MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
        const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));

        if( rItem.GetProp() != 100 || MapUnit::MapRelative != rItem.GetPropUnit() )
        {
            bool bPtRel = MapUnit::MapPoint == rItem.GetPropUnit();
            pSizeBox->SetPtRelative( bPtRel );
            pSizeBox->set_value( bPtRel ? static_cast<short>(rItem.GetProp()) * 10 : rItem.GetProp() );
        }
        else
        {
            pSizeBox->SetRelative(false);
            pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
        }
    }
    else if ( eState >= SfxItemState::DEFAULT )
    {
        MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
        const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich ));
        pSizeBox->set_value( CalcToPoint( rItem.GetHeight(), eUnit, 10 ) );
    }
    else
    {
        pSizeBox->set_active_or_entry_text(OUString());
        if ( eState <= SfxItemState::DISABLED )
        {
            pSizeBox->set_sensitive(false);
            pSizeLabel->set_sensitive(false);
        }
    }

    switch ( eLangGrp )
    {
        case Western : nWhich = GetWhich( SID_ATTR_CHAR_LANGUAGE ); break;
        case Asian : nWhich = GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); break;
        case Ctl : nWhich = GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); break;
    }
    pLangBox->set_active(-1);
    eState = rSet.GetItemState( nWhich );

    switch ( eState )
    {
        case SfxItemState::UNKNOWN:
            pLangFT->hide();
            pLangBox->hide();
            break;

        case SfxItemState::DISABLED:
            pLangFT->set_sensitive(false);
            pLangBox->set_sensitive(false);
            break;

        case SfxItemState::DEFAULT:
        case SfxItemState::SET:
        {
            const SvxLanguageItem& rItem = static_cast<const SvxLanguageItem&>(rSet.Get( nWhich ));
            LanguageType eLangType = rItem.GetValue();
            DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" );
            if (eLangType != LANGUAGE_DONTKNOW)
                pLangBox->set_active_id(eLangType);
            break;
        }
        case SfxItemState::INVALID:
            break;
    }

    OUString sMapText(pFontList->GetFontMapText(
        pFontList->Get(pNameBox->get_active_text(), pStyleBox->get_active_text())));

    switch (eLangGrp)
    {
        case Western:
            m_xWestFontTypeFT->set_label(sMapText);
            break;
        case Asian:
            m_xEastFontTypeFT->set_label(sMapText);
            break;
        case Ctl:
            m_xCTLFontTypeFT->set_label(sMapText);
            break;
    }

    EnableFeatureButton(*pNameBox);

    // save these settings
    pNameBox->save_value();
    pStyleBox->save_value();
    pSizeBox->save_value();
    pLangBox->save_active_id();
}

bool SvxCharNamePage::FillItemSet_Impl( SfxItemSet& rSet, LanguageGroup eLangGrp )
{
    bool bModified = false;

    weld::ComboBox* pNameBox = nullptr;
    FontStyleBox* pStyleBox = nullptr;
    FontSizeBox* pSizeBox = nullptr;
    SvxLanguageBox* pLangBox = nullptr;
    sal_uInt16 nWhich = 0;
    sal_uInt16 nSlot = 0;

    switch ( eLangGrp )
    {
        case Western :
            pNameBox = m_xWestFontNameLB.get();
            pStyleBox = m_xWestFontStyleLB.get();
            pSizeBox = m_xWestFontSizeLB.get();
            pLangBox = m_xWestFontLanguageLB.get();
            nSlot = SID_ATTR_CHAR_FONT;
            break;

        case Asian :
            pNameBox = m_xEastFontNameLB.get();
            pStyleBox = m_xEastFontStyleLB.get();
            pSizeBox = m_xEastFontSizeLB.get();
            pLangBox = m_xEastFontLanguageLB.get();
            nSlot = SID_ATTR_CHAR_CJK_FONT;
            break;

        case Ctl :
            pNameBox = m_xCTLFontNameLB.get();
            pStyleBox = m_xCTLFontStyleLB.get();
            pSizeBox = m_xCTLFontSizeLB.get();
            pLangBox = m_xCTLFontLanguageLB.get();
            nSlot = SID_ATTR_CHAR_CTL_FONT;
            break;
    }

    nWhich = GetWhich( nSlot );
    const SfxPoolItem* pItem = nullptr;
    const SfxItemSet& rOldSet = GetItemSet();
    const SfxPoolItem* pOld = nullptr;

    const SfxItemSet* pExampleSet = GetDialogExampleSet();

    bool bChanged = true;
    const OUString aFontName  = pNameBox->get_active_text();
    const FontList* pFontList = GetFontList();
    OUString aStyleBoxText = pStyleBox->get_active_text();
    int nEntryPos = pStyleBox->find_text(aStyleBoxText);
    if (nEntryPos >= m_pImpl->m_nExtraEntryPos)
        aStyleBoxText.clear();
    FontMetric aInfo( pFontList->Get( aFontName, aStyleBoxText ) );
    SvxFontItem aFontItem( aInfo.GetFamilyTypeMaybeAskConfig(), aInfo.GetFamilyName(), aInfo.GetStyleName(),
                           aInfo.GetPitchMaybeAskConfig(), aInfo.GetCharSet(), nWhich );
    pOld = GetOldItem( rSet, nSlot );

    if ( pOld )
    {
        const SvxFontItem& rItem = *static_cast<const SvxFontItem*>(pOld);

        if ( rItem.GetFamilyName() == aFontItem.GetFamilyName() )
            bChanged = false;
    }

    if ( !bChanged )
        bChanged = pNameBox->get_saved_value().isEmpty();

    if ( !bChanged && pExampleSet &&
         pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
         static_cast<const SvxFontItem*>(pItem)->GetFamilyName() != aFontItem.GetFamilyName() )
        bChanged = true;

    if ( bChanged && !aFontName.isEmpty() )
    {
        rSet.Put( aFontItem );
        bModified = true;
    }
    else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
        rSet.ClearItem( nWhich );


    bChanged = true;
    switch ( eLangGrp )
    {
        case Western : nSlot = SID_ATTR_CHAR_WEIGHT; break;
        case Asian : nSlot = SID_ATTR_CHAR_CJK_WEIGHT; break;
        case Ctl : nSlot = SID_ATTR_CHAR_CTL_WEIGHT; break;
    }
    nWhich = GetWhich( nSlot );
    FontWeight eWeight = aInfo.GetWeightMaybeAskConfig();
    if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
        eWeight = WEIGHT_NORMAL;
    SvxWeightItem aWeightItem( eWeight, nWhich );
    pOld = GetOldItem( rSet, nSlot );

    if ( pOld )
    {
        const SvxWeightItem& rItem = *static_cast<const SvxWeightItem*>(pOld);

        if ( rItem.GetValue() == aWeightItem.GetValue() )
            bChanged = false;
    }

    if ( !bChanged )
    {
        bChanged = pStyleBox->get_saved_value().isEmpty();

        if ( m_pImpl->m_bInSearchMode && bChanged &&
             aInfo.GetWeightMaybeAskConfig() == WEIGHT_NORMAL && aInfo.GetItalicMaybeAskConfig() != ITALIC_NONE )
            bChanged = false;
    }

    if ( !bChanged && pExampleSet &&
         pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
         static_cast<const SvxWeightItem*>(pItem)->GetValue() != aWeightItem.GetValue() )
        bChanged = true;

    if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
        bChanged = ( nEntryPos == m_pImpl->m_nExtraEntryPos );

    OUString aText( pStyleBox->get_active_text() ); // Tristate, then text empty

    if ( bChanged && !aText.isEmpty() )
    {
        rSet.Put( aWeightItem );
        bModified = true;
    }
    else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
        rSet.InvalidateItem(nWhich);

    bChanged = true;
    switch ( eLangGrp )
    {
        case Western : nSlot = SID_ATTR_CHAR_POSTURE; break;
        case Asian : nSlot = SID_ATTR_CHAR_CJK_POSTURE; break;
        case Ctl : nSlot = SID_ATTR_CHAR_CTL_POSTURE; break;
    }
    nWhich = GetWhich( nSlot );
    FontItalic eItalic = aInfo.GetItalicMaybeAskConfig();
    if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
        eItalic = ITALIC_NONE;
    SvxPostureItem aPostureItem( eItalic, nWhich );
    pOld = GetOldItem( rSet, nSlot );

    if ( pOld )
    {
        const SvxPostureItem& rItem = *static_cast<const SvxPostureItem*>(pOld);

        if ( rItem.GetValue() == aPostureItem.GetValue() )
            bChanged = false;
    }

    if ( !bChanged )
    {
        bChanged = pStyleBox->get_saved_value().isEmpty();

        if ( m_pImpl->m_bInSearchMode && bChanged &&
             aInfo.GetItalicMaybeAskConfig() == ITALIC_NONE && aInfo.GetWeightMaybeAskConfig() != WEIGHT_NORMAL )
            bChanged = false;
    }

    if ( !bChanged && pExampleSet &&
         pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET &&
         static_cast<const SvxPostureItem*>(pItem)->GetValue() != aPostureItem.GetValue() )
        bChanged = true;

    if ( nEntryPos >= m_pImpl->m_nExtraEntryPos )
        bChanged = ( nEntryPos == ( m_pImpl->m_nExtraEntryPos + 1 ) );

    if ( bChanged && !aText.isEmpty() )
    {
        rSet.Put( aPostureItem );
        bModified = true;
    }
    else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
        rSet.InvalidateItem(nWhich);

    // FontSize
    tools::Long nSize = pSizeBox->get_value();

    if ( pSizeBox->get_active_text().isEmpty() )   // GetValue() returns the min-value
        nSize = 0;
    tools::Long nSavedSize = pSizeBox->get_saved_value();
    const bool bRel = pSizeBox->IsRelative();

    switch ( eLangGrp )
    {
        case Western : nSlot = SID_ATTR_CHAR_FONTHEIGHT; break;
        case Asian : nSlot = SID_ATTR_CHAR_CJK_FONTHEIGHT; break;
        case Ctl : nSlot = SID_ATTR_CHAR_CTL_FONTHEIGHT; break;
    }
    nWhich = GetWhich( nSlot );
    const SvxFontHeightItem* pOldHeight = static_cast<const SvxFontHeightItem*>(GetOldItem( rSet, nSlot ));
    bChanged = ( nSize != nSavedSize );

    if ( !bChanged && pExampleSet &&
         pExampleSet->GetItemState( nWhich, false, &pItem ) == SfxItemState::SET )
    {
        float fSize = static_cast<float>(nSize) / 10;
        tools::Long nVal = CalcToUnit( fSize, rSet.GetPool()->GetMetric( nWhich ) );
        if ( static_cast<const SvxFontHeightItem*>(pItem)->GetHeight() != static_cast<sal_uInt32>(nVal) )
            bChanged = true;
    }

    if ( bChanged || !pOldHeight ||
         bRel != ( MapUnit::MapRelative != pOldHeight->GetPropUnit() || 100 != pOldHeight->GetProp() ) )
    {
        MapUnit eUnit = rSet.GetPool()->GetMetric( nWhich );
        if ( pSizeBox->IsRelative() )
        {
            DBG_ASSERT( GetItemSet().GetParent(), "No parent set" );
            const SvxFontHeightItem& rOldItem =
                static_cast<const SvxFontHeightItem&>(GetItemSet().GetParent()->Get( nWhich ));

            SvxFontHeightItem aHeight( 240, 100, nWhich );
            if ( pSizeBox->IsPtRelative() )
                aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>( nSize / 10 ), MapUnit::MapPoint, eUnit );
            else
                aHeight.SetHeight( rOldItem.GetHeight(), static_cast<sal_uInt16>(nSize) );
            rSet.Put( aHeight );
        }
        else
        {
            float fSize = static_cast<float>(nSize) / 10;
            rSet.Put( SvxFontHeightItem( CalcToUnit( fSize, eUnit ), 100, nWhich ) );
        }
        bModified = true;
    }
    else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
        rSet.InvalidateItem(nWhich);

    bChanged = true;
    switch ( eLangGrp )
    {
        case Western : nSlot = SID_ATTR_CHAR_LANGUAGE; break;
        case Asian : nSlot = SID_ATTR_CHAR_CJK_LANGUAGE; break;
        case Ctl : nSlot = SID_ATTR_CHAR_CTL_LANGUAGE; break;
    }

    // For language list boxes acting as ComboBox, check for, add and select an
    // edited entry.
    switch (pLangBox->GetEditedAndValid())
    {
        case SvxLanguageBox::EditedAndValid::No:
            ;   // nothing to do
        break;
        case SvxLanguageBox::EditedAndValid::Valid:
            {
                SvxLanguageBox* ppBoxes[3]
                    = {m_xWestFontLanguageLB.get(), m_xEastFontLanguageLB.get(), m_xCTLFontLanguageLB.get()};
                SvxLanguageBox* pBox = pLangBox->SaveEditedAsEntry(ppBoxes);
                if (pBox != pLangBox)
                {
                    // Get item from corresponding slot.
                    if (pBox == m_xWestFontLanguageLB.get())
                        nSlot = SID_ATTR_CHAR_LANGUAGE;
                    else if (pBox == m_xEastFontLanguageLB.get())
                        nSlot = SID_ATTR_CHAR_CJK_LANGUAGE;
                    else if (pBox == m_xCTLFontLanguageLB.get())
                        nSlot = SID_ATTR_CHAR_CTL_LANGUAGE;
                    pLangBox = pBox;
                }
            }
        break;
        case SvxLanguageBox::EditedAndValid::Invalid:
            pLangBox->set_active_id(pLangBox->get_saved_active_id());
        break;
    }

    nWhich = GetWhich( nSlot );
    pOld = GetOldItem( rSet, nSlot );

    int nLangPos = pLangBox->get_active();
    LanguageType eLangType = pLangBox->get_active_id();

    if (pOld)
    {
        const SvxLanguageItem& rItem = *static_cast<const SvxLanguageItem*>(pOld);
        if (nLangPos == -1 || eLangType == rItem.GetValue())
            bChanged = false;
    }

    if (!bChanged)
        bChanged = pLangBox->get_active_id_changed_from_saved();

    if (bChanged && nLangPos != -1)
    {
        rSet.Put(SvxLanguageItem(eLangType, nWhich));
        bModified = true;
    }
    else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
        rSet.InvalidateItem(nWhich);

    return bModified;
}

IMPL_LINK_NOARG(SvxCharNamePage, UpdateHdl_Impl, Timer *, void)
{
    UpdatePreview_Impl();
}

IMPL_LINK(SvxCharNamePage, FontModifyComboBoxHdl_Impl, weld::ComboBox&, rBox, void)
{
    FontModifyHdl_Impl(rBox);
}

IMPL_LINK(SvxCharNamePage, FontFeatureButtonClicked, weld::Button&, rButton, void)
{
    OUString sFontName;
    weld::ComboBox* pNameBox = nullptr;

    if (&rButton == m_xWestFontFeaturesButton.get())
    {
        pNameBox = m_xWestFontNameLB.get();
        sFontName = GetPreviewFont().GetFamilyName();
    }
    else if (&rButton == m_xEastFontFeaturesButton.get())
    {
        pNameBox = m_xEastFontNameLB.get();
        sFontName = GetPreviewCJKFont().GetFamilyName();
    }
    else if (&rButton == m_xCTLFontFeaturesButton.get())
    {
        pNameBox = m_xCTLFontNameLB.get();
        sFontName = GetPreviewCTLFont().GetFamilyName();
    }

    if (!sFontName.isEmpty() && pNameBox)
    {
        cui::FontFeaturesDialog aDialog(GetFrameWeld(), sFontName);
        if (aDialog.run() == RET_OK)
        {
            pNameBox->set_entry_text(aDialog.getResultFontName());
            UpdatePreview_Impl();
        }
    }
}

void SvxCharNamePage::FontModifyHdl_Impl(const weld::Widget& rNameBox)
{
    m_pImpl->m_aUpdateIdle.Start();

    if (m_xWestFontNameLB.get() == &rNameBox || m_xEastFontNameLB.get() == &rNameBox || m_xCTLFontNameLB.get() == &rNameBox)
    {
        FillStyleBox_Impl(rNameBox);
        FillSizeBox_Impl(rNameBox);
        EnableFeatureButton(rNameBox);
    }
}

void SvxCharNamePage::ActivatePage( const SfxItemSet& rSet )
{
    SvxCharBasePage::ActivatePage( rSet );

    UpdatePreview_Impl();       // instead of asynchronous calling in ctor
}

DeactivateRC SvxCharNamePage::DeactivatePage( SfxItemSet* _pSet )
{
    if ( _pSet )
        FillItemSet( _pSet );
    return DeactivateRC::LeavePage;
}

std::unique_ptr<SfxTabPage> SvxCharNamePage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet)
{
    return std::make_unique<SvxCharNamePage>(pPage, pController, *rSet );
}

void SvxCharNamePage::Reset( const SfxItemSet* rSet )
{
    Reset_Impl( *rSet, Western );
    Reset_Impl( *rSet, Asian );
    Reset_Impl( *rSet, Ctl );

    SetPrevFontWidthScale( *rSet );
    UpdatePreview_Impl();
}

void  SvxCharNamePage::ChangesApplied()
{
    m_xWestFontNameLB->save_value();
    m_xWestFontStyleLB->save_value();
    m_xWestFontSizeLB->save_value();
    m_xWestFontLanguageLB->save_active_id();
    m_xEastFontNameLB->save_value();
    m_xEastFontStyleLB->save_value();
    m_xEastFontSizeLB->save_value();
    m_xEastFontLanguageLB->save_active_id();
    m_xCTLFontNameLB->save_value();
    m_xCTLFontStyleLB->save_value();
    m_xCTLFontSizeLB->save_value();
    m_xCTLFontLanguageLB->save_active_id();
}

bool SvxCharNamePage::FillItemSet( SfxItemSet* rSet )
{
    bool bModified = FillItemSet_Impl( *rSet, Western );
    bModified |= FillItemSet_Impl( *rSet, Asian );
    bModified |= FillItemSet_Impl( *rSet, Ctl );
    return bModified;
}

void SvxCharNamePage::SetFontList( const SvxFontListItem& rItem )
{
    m_pImpl->m_pFontList = rItem.GetFontList()->Clone();
}

namespace
{
    void enableRelativeMode( SvxCharNamePage const * _pPage, FontSizeBox* _pFontSizeLB, sal_uInt16 _nHeightWhich )
    {
        _pFontSizeLB->EnableRelativeMode( 5, 995 ); // min 5%, max 995%, step 5

        const SvxFontHeightItem& rHeightItem =
            static_cast<const SvxFontHeightItem&>(_pPage->GetItemSet().GetParent()->Get( _nHeightWhich ));
        MapUnit eUnit = _pPage->GetItemSet().GetPool()->GetMetric( _nHeightWhich );
        short nCurHeight =
            static_castshort >( CalcToPoint( rHeightItem.GetHeight(), eUnit, 1 ) * 10 );

        // based on the current height:
        //      - negative until minimum of 2 pt
        //      - positive until maximum of 999 pt
        _pFontSizeLB->EnablePtRelativeMode( sal::static_int_cast< short >(-(nCurHeight - 20)), (9999 - nCurHeight) );
    }
}

void SvxCharNamePage::EnableRelativeMode()
{
    DBG_ASSERT( GetItemSet().GetParent(), "RelativeMode, but no ParentSet!" );
    enableRelativeMode(this,m_xWestFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_FONTHEIGHT ));
    enableRelativeMode(this,m_xEastFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ));
    enableRelativeMode(this,m_xCTLFontSizeLB.get(),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ));
}

void SvxCharNamePage::EnableSearchMode()
{
    m_pImpl->m_bInSearchMode = true;
}

void SvxCharNamePage::DisableControls( sal_uInt16 nDisable )
{
    if ( DISABLE_HIDE_LANGUAGE & nDisable )
    {
        if ( m_xWestFontLanguageFT ) m_xWestFontLanguageFT->hide();
        if ( m_xWestFontLanguageLB ) m_xWestFontLanguageLB->hide();
        if ( m_xEastFontLanguageFT ) m_xEastFontLanguageFT->hide();
        if ( m_xEastFontLanguageLB ) m_xEastFontLanguageLB->hide();
        if ( m_xCTLFontLanguageFT ) m_xCTLFontLanguageFT->hide();
        if ( m_xCTLFontLanguageLB ) m_xCTLFontLanguageLB->hide();
    }
}

void SvxCharNamePage::PageCreated(const SfxAllItemSet& aSet)
{
    const SvxFontListItem* pFontListItem = aSet.GetItem<SvxFontListItem>(SID_ATTR_CHAR_FONTLIST, false);
    const SfxUInt32Item* pFlagItem = aSet.GetItem<SfxUInt32Item>(SID_FLAG_TYPE, false);
    const SfxUInt16Item* pDisableItem = aSet.GetItem<SfxUInt16Item>(SID_DISABLE_CTL, false);
    if (pFontListItem)
        SetFontList(*pFontListItem);

    if (pFlagItem)
    {
        sal_uInt32 nFlags=pFlagItem->GetValue();
        if ( ( nFlags & SVX_RELATIVE_MODE ) == SVX_RELATIVE_MODE )
            EnableRelativeMode();
        if ( ( nFlags & SVX_PREVIEW_CHARACTER ) == SVX_PREVIEW_CHARACTER )
            // the writer uses SID_ATTR_BRUSH as font background
            m_bPreviewBackgroundToCharacter = true;
    }
    if (pDisableItem)
        DisableControls(pDisableItem->GetValue());
}
// class SvxCharEffectsPage ----------------------------------------------

SvxCharEffectsPage::SvxCharEffectsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInSet)
    : SvxCharBasePage(pPage, pController, u"cui/ui/effectspage.ui"_ustr, u"EffectsPage"_ustr, rInSet)
    , m_bOrigFontColor(false)
    , m_bNewFontColor(false)
    , m_bEnableNoneFontColor(false)
    , m_xFontColorFT(m_xBuilder->weld_label(u"fontcolorft"_ustr))
    , m_xFontColorLB(new ColorListBox(m_xBuilder->weld_menu_button(u"fontcolorlb"_ustr),
        [this]{ return GetDialogController()->getDialog(); }))
    , m_xFontTransparencyFT(m_xBuilder->weld_label(u"fonttransparencyft"_ustr))
    , m_xFontTransparencyMtr(
          m_xBuilder->weld_metric_spin_button(u"fonttransparencymtr"_ustr, FieldUnit::PERCENT))
    , m_xEffectsFT(m_xBuilder->weld_label(u"effectsft"_ustr))
    , m_xEffectsLB(m_xBuilder->weld_combo_box(u"effectslb"_ustr))
    , m_xReliefFT(m_xBuilder->weld_label(u"reliefft"_ustr))
    , m_xReliefLB(m_xBuilder->weld_combo_box(u"relieflb"_ustr))
    , m_xOutlineBtn(m_xBuilder->weld_check_button(u"outlinecb"_ustr))
    , m_xShadowBtn(m_xBuilder->weld_check_button(u"shadowcb"_ustr))
    , m_xHiddenBtn(m_xBuilder->weld_check_button(u"hiddencb"_ustr))
    , m_xOverlineLB(m_xBuilder->weld_combo_box(u"overlinelb"_ustr))
    , m_xOverlineColorFT(m_xBuilder->weld_label(u"overlinecolorft"_ustr))
    , m_xOverlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button(u"overlinecolorlb"_ustr),
        [this]{ return GetDialogController()->getDialog(); }))
    , m_xStrikeoutLB(m_xBuilder->weld_combo_box(u"strikeoutlb"_ustr))
    , m_xUnderlineLB(m_xBuilder->weld_combo_box(u"underlinelb"_ustr))
    , m_xUnderlineColorFT(m_xBuilder->weld_label(u"underlinecolorft"_ustr))
    , m_xUnderlineColorLB(new ColorListBox(m_xBuilder->weld_menu_button(u"underlinecolorlb"_ustr),
        [this]{ return GetDialogController()->getDialog(); }))
    , m_xIndividualWordsBtn(m_xBuilder->weld_check_button(u"individualwordscb"_ustr))
    , m_xEmphasisFT(m_xBuilder->weld_label(u"emphasisft"_ustr))
    , m_xEmphasisLB(m_xBuilder->weld_combo_box(u"emphasislb"_ustr))
    , m_xPositionFT(m_xBuilder->weld_label(u"positionft"_ustr))
    , m_xPositionLB(m_xBuilder->weld_combo_box(u"positionlb"_ustr))
    , m_xA11yWarningFT(m_xBuilder->weld_label(u"a11ywarning"_ustr))
{
    m_xPreviewWin.reset(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreviewWin));
#ifdef IOS
    m_xPreviewWin->hide();
#endif
    m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
    m_xOverlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
    m_xUnderlineColorLB->SetSlotId(SID_ATTR_CHAR_COLOR);
    Initialize();
}

void SvxCharEffectsPage::EnableNoneFontColor()
{
    m_xFontColorLB->SetSlotId(SID_ATTR_CHAR_COLOR, true);
    m_bEnableNoneFontColor = true;
}

SvxCharEffectsPage::~SvxCharEffectsPage()
{
    m_xUnderlineColorLB.reset();
    m_xOverlineColorLB.reset();
    m_xFontTransparencyMtr.reset();
    m_xFontColorLB.reset();
}

void SvxCharEffectsPage::Initialize()
{
    // to handle the changes of the other pages
    SetExchangeSupport();

    // HTML-Mode
    const SfxUInt16Item* pHtmlModeItem = GetItemSet().GetItemIfSet( SID_HTML_MODE, false );
    if ( !pHtmlModeItem)
    {
        if (SfxObjectShell* pShell = SfxObjectShell::Current())
           pHtmlModeItem = pShell->GetItem( SID_HTML_MODE );
    }
    if (pHtmlModeItem)
    {
        sal_uInt16 nHtmlMode = pHtmlModeItem->GetValue();
        if ( ( nHtmlMode & HTMLMODE_ON ) == HTMLMODE_ON )
        {
            //!!! hide some controls please
        }
    }

    m_xFontColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
    m_xFontTransparencyMtr->connect_value_changed(
        LINK(this, SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl));

    // handler
    Link<weld::ComboBox&,void> aLink = LINK( this, SvxCharEffectsPage, SelectListBoxHdl_Impl );
    m_xUnderlineLB->connect_changed( aLink );
    m_xUnderlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
    m_xOverlineLB->connect_changed( aLink );
    m_xOverlineColorLB->SetSelectHdl(LINK(this, SvxCharEffectsPage, ColorBoxSelectHdl_Impl));
    m_xStrikeoutLB->connect_changed( aLink );
    m_xEmphasisLB->connect_changed( aLink );
    m_xPositionLB->connect_changed( aLink );
    m_xEffectsLB->connect_changed( aLink );
    m_xReliefLB->connect_changed( aLink );

    m_xUnderlineLB->set_active( 0 );
    m_xOverlineLB->set_active( 0 );
    m_xStrikeoutLB->set_active( 0 );
    m_xEmphasisLB->set_active( 0 );
    m_xPositionLB->set_active( 0 );
    SelectHdl_Impl(nullptr);
    SelectHdl_Impl(m_xEmphasisLB.get());

    m_xEffectsLB->set_active( 0 );

    m_xHiddenBtn->connect_toggled(LINK(this, SvxCharEffectsPage, HiddenBtnClickHdl));
    m_xIndividualWordsBtn->connect_toggled(LINK(this, SvxCharEffectsPage, CbClickHdl_Impl));
    m_xOutlineBtn->connect_toggled(LINK(this, SvxCharEffectsPage, OutlineBtnClickHdl));
    m_xShadowBtn->connect_toggled(LINK(this, SvxCharEffectsPage, ShadowBtnClickHdl));

    if ( !SvtCJKOptions::IsAsianTypographyEnabled() )
    {
        m_xEmphasisFT->hide();
        m_xEmphasisLB->hide();
        m_xPositionFT->hide();
        m_xPositionLB->hide();
    }

    m_xA11yWarningFT->set_visible(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get());
}

void SvxCharEffectsPage::UpdatePreview_Impl()
{
    SvxFont& rFont = GetPreviewFont();
    SvxFont& rCJKFont = GetPreviewCJKFont();
    SvxFont& rCTLFont = GetPreviewCTLFont();

    const Color& rSelectedColor = m_xFontColorLB->GetSelectEntryColor();
    rFont.SetColor(rSelectedColor);
    rCJKFont.SetColor(rSelectedColor);
    rCTLFont.SetColor(rSelectedColor);
    m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO

    FontLineStyle eUnderline = static_cast<FontLineStyle>(m_xUnderlineLB->get_active_id().toInt32());
    FontLineStyle eOverline = static_cast<FontLineStyle>(m_xOverlineLB->get_active_id().toInt32());
    FontStrikeout eStrikeout = static_cast<FontStrikeout>(m_xStrikeoutLB->get_active_id().toInt32());
    rFont.SetUnderline( eUnderline );
    rCJKFont.SetUnderline( eUnderline );
    rCTLFont.SetUnderline( eUnderline );
    m_aPreviewWin.SetTextLineColor( m_xUnderlineColorLB->GetSelectEntryColor() );
    rFont.SetOverline( eOverline );
    rCJKFont.SetOverline( eOverline );
    rCTLFont.SetOverline( eOverline );
    m_aPreviewWin.SetOverlineColor( m_xOverlineColorLB->GetSelectEntryColor() );
    rFont.SetStrikeout( eStrikeout );
    rCJKFont.SetStrikeout( eStrikeout );
    rCTLFont.SetStrikeout( eStrikeout );

    auto nEmphasis = m_xEmphasisLB->get_active();
    if (nEmphasis != -1)
    {
        bool bUnder = (CHRDLG_POSITION_UNDER == m_xPositionLB->get_active_id().toInt32());
        FontEmphasisMark eMark = static_cast<FontEmphasisMark>(nEmphasis);
        eMark |= bUnder ? FontEmphasisMark::PosBelow : FontEmphasisMark::PosAbove;
        rFont.SetEmphasisMark( eMark );
        rCJKFont.SetEmphasisMark( eMark );
        rCTLFont.SetEmphasisMark( eMark );
    }

    auto nRelief = m_xReliefLB->get_active();
    if (nRelief != -1)
    {
        rFont.SetRelief( static_cast<FontRelief>(nRelief) );
        rCJKFont.SetRelief( static_cast<FontRelief>(nRelief) );
        rCTLFont.SetRelief( static_cast<FontRelief>(nRelief) );
    }

    rFont.SetOutline( StateToAttr( m_xOutlineBtn->get_state() ) );
    rCJKFont.SetOutline( rFont.IsOutline() );
    rCTLFont.SetOutline( rFont.IsOutline() );

    rFont.SetShadow( StateToAttr( m_xShadowBtn->get_state() ) );
    rCJKFont.SetShadow( rFont.IsShadow() );
    rCTLFont.SetShadow( rFont.IsShadow() );

    auto nCapsPos = m_xEffectsLB->get_active();
    if (nCapsPos != -1)
    {
        SvxCaseMap eCaps = static_cast<SvxCaseMap>(nCapsPos);
        rFont.SetCaseMap( eCaps );
        rCJKFont.SetCaseMap( eCaps );
        // #i78474# small caps do not exist in CTL fonts
        rCTLFont.SetCaseMap( eCaps == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaps );
    }

    bool bWordLine = StateToAttr( m_xIndividualWordsBtn->get_state() );
    rFont.SetWordLineMode( bWordLine );
    rCJKFont.SetWordLineMode( bWordLine );
    rCTLFont.SetWordLineMode( bWordLine );

    m_aPreviewWin.Invalidate();
}

void SvxCharEffectsPage::SetCaseMap_Impl( SvxCaseMap eCaseMap )
{
    if ( SvxCaseMap::End > eCaseMap )
        m_xEffectsLB->set_active(
            sal::static_int_cast< sal_Int32 >( eCaseMap ) );
    else
    {
        // not mapped
        m_xEffectsLB->set_active(-1);
    }

    UpdatePreview_Impl();
}

void SvxCharEffectsPage::ResetColor_Impl( const SfxItemSet& rSet )
{
    sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
    SfxItemState eState = rSet.GetItemState( nWhich );

    m_bOrigFontColor = false;
    switch ( eState )
    {
        case SfxItemState::UNKNOWN:
            m_xFontColorFT->hide();
            m_xFontColorLB->hide();
            break;

        case SfxItemState::DISABLED:
            m_xFontColorFT->set_sensitive(false);
            m_xFontColorLB->set_sensitive(false);
            break;

        case SfxItemState::INVALID:
            //Related: tdf#106080 if there is no font color, then allow "none"
            //as a color so the listbox can display that state.
            EnableNoneFontColor();
            m_xFontColorLB->SetNoSelection();
            break;

        case SfxItemState::DEFAULT:
        case SfxItemState::SET:
        {
            SvxFont& rFont = GetPreviewFont();
            SvxFont& rCJKFont = GetPreviewCJKFont();
            SvxFont& rCTLFont = GetPreviewCTLFont();

            const SvxColorItem& rItem = static_cast<const SvxColorItem&>(rSet.Get( nWhich ));
            Color aColor = rItem.GetValue();
            rFont.SetColor(aColor);
            rCJKFont.SetColor(aColor);
            rCTLFont.SetColor(aColor);
            m_aPreviewWin.AutoCorrectFontColor(); // handle color COL_AUTO

            m_aPreviewWin.Invalidate();

            Color aRGBColor = aColor;
            if (aRGBColor.IsTransparent() && aColor != COL_AUTO)
            {
                aRGBColor.SetAlpha(255);
            }
            m_xFontColorLB->SelectEntry(aRGBColor);

            if (m_xFontTransparencyMtr->get_visible() && aColor != COL_AUTO)
            {
                double fTransparency = (255 - aColor.GetAlpha()) * 100.0 / 255;
                m_xFontTransparencyMtr->set_value(basegfx::fround(fTransparency),
                                                  FieldUnit::PERCENT);
            }

            m_aOrigFontColor = aColor;
            m_bOrigFontColor = true;
            break;
        }
    }
    m_bNewFontColor = false;
}

bool SvxCharEffectsPage::FillItemSetColor_Impl( SfxItemSet& rSet )
{
    sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_COLOR );
    const SfxItemSet& rOldSet = GetItemSet();

    NamedColor aSelectedColor;
    bool bChanged = m_bNewFontColor;

    if (bChanged)
    {
        aSelectedColor = m_xFontColorLB->GetSelectedEntryThemedColor();

        if (m_xFontTransparencyMtr->get_value_changed_from_saved())
        {
            double fTransparency
                = m_xFontTransparencyMtr->get_value(FieldUnit::PERCENT) * 255.0 / 100;
            aSelectedColor.m_aColor.SetAlpha(255 - static_cast<sal_uInt8>(basegfx::fround(fTransparency)));
        }

        if (m_bOrigFontColor)
            bChanged = aSelectedColor.m_aColor != m_aOrigFontColor;
        if (m_bEnableNoneFontColor && bChanged && aSelectedColor.m_aColor == COL_NONE_COLOR)
            bChanged = false;
    }

    if (bChanged)
    {
        SvxColorItem aItem(aSelectedColor.m_aColor, aSelectedColor.getComplexColor(), nWhich);
        rSet.Put(aItem);
    }
    else if ( SfxItemState::DEFAULT == rOldSet.GetItemState( nWhich, false ) )
        rSet.InvalidateItem(nWhich);

    return bChanged;
}

IMPL_LINK( SvxCharEffectsPage, SelectListBoxHdl_Impl, weld::ComboBox&, rBox, void )
{
    SelectHdl_Impl(&rBox);
}

void SvxCharEffectsPage::SelectHdl_Impl(const weld::ComboBox* pBox)
{
    if (m_xEmphasisLB.get() == pBox)
    {
        auto nEPos = m_xEmphasisLB->get_active();
        bool bEnable = nEPos > 0;
        m_xPositionFT->set_sensitive( bEnable );
        m_xPositionLB->set_sensitive( bEnable );
    }
    else if (m_xReliefLB.get() == pBox)
    {
        bool bEnable = ( pBox->get_active() == 0 );
        m_xOutlineBtn->set_sensitive( bEnable );
        m_xShadowBtn->set_sensitive( bEnable );
    }
    else if (m_xPositionLB.get() != pBox)
    {
        auto nUPos = m_xUnderlineLB->get_active();
        bool bUEnable = nUPos > 0;
        m_xUnderlineColorFT->set_sensitive(bUEnable);
        m_xUnderlineColorLB->set_sensitive(bUEnable);

        auto nOPos = m_xOverlineLB->get_active();
        bool bOEnable = nOPos > 0;
        m_xOverlineColorFT->set_sensitive(bOEnable);
        m_xOverlineColorLB->set_sensitive(bOEnable);

        auto nSPos = m_xStrikeoutLB->get_active();
        m_xIndividualWordsBtn->set_sensitive( bUEnable || bOEnable || nSPos > 0);
    }
    UpdatePreview_Impl();
}

IMPL_LINK(SvxCharEffectsPage, CbClickHdl_Impl, weld::Toggleable&, rToggle, void)
{
    m_aIndividualWordsState.ButtonToggled(rToggle);
    UpdatePreview_Impl();
    UpdatePreview_Impl();
}

IMPL_LINK(SvxCharEffectsPage, ColorBoxSelectHdl_Impl, ColorListBox&, rBox, void)
{
    if (m_xFontColorLB.get() == &rBox)
        m_bNewFontColor = true;
    UpdatePreview_Impl();
}

IMPL_LINK_NOARG(SvxCharEffectsPage, ModifyFontTransparencyHdl_Impl, weld::MetricSpinButton&, void)
{
    m_bNewFontColor = true;
}

DeactivateRC SvxCharEffectsPage::DeactivatePage( SfxItemSet* _pSet )
{
    if ( _pSet )
        FillItemSet( _pSet );
    return DeactivateRC::LeavePage;
}

std::unique_ptr<SfxTabPage> SvxCharEffectsPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
{
    return std::make_unique<SvxCharEffectsPage>( pPage, pController, *rSet );
}

void SvxCharEffectsPage::Reset( const SfxItemSet* rSet )
{
    SvxFont& rFont = GetPreviewFont();
    SvxFont& rCJKFont = GetPreviewCJKFont();
    SvxFont& rCTLFont = GetPreviewCTLFont();

    bool bEnable = false;

    // Underline
    sal_uInt16 nWhich = GetWhich( SID_ATTR_CHAR_UNDERLINE );
    rFont.SetUnderline( LINESTYLE_NONE );
    rCJKFont.SetUnderline( LINESTYLE_NONE );
    rCTLFont.SetUnderline( LINESTYLE_NONE );

    m_xUnderlineLB->set_active( 0 );
    SfxItemState eState = rSet->GetItemState( nWhich );

    if ( eState >= SfxItemState::INVALID )
    {
        if ( eState == SfxItemState::INVALID )
            m_xUnderlineLB->set_active(-1);
        else
        {
            const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>(rSet->Get( nWhich ));
            FontLineStyle eUnderline = rItem.GetValue();
            rFont.SetUnderline( eUnderline );
            rCJKFont.SetUnderline( eUnderline );
            rCTLFont.SetUnderline( eUnderline );

            if ( eUnderline != LINESTYLE_NONE )
            {
                auto nPos = m_xUnderlineLB->find_id(OUString::number(eUnderline));
                if (nPos != -1)
                {
                    m_xUnderlineLB->set_active(nPos);
                    bEnable = true;
                }
                Color aColor = rItem.GetColor();
                m_xUnderlineColorLB->SelectEntry(aColor);
            }
            else
            {
                m_xUnderlineColorLB->SelectEntry(COL_AUTO);
                m_xUnderlineColorLB->set_sensitive(false);
            }
        }
    }

    // Overline
    nWhich = GetWhich( SID_ATTR_CHAR_OVERLINE );
    rFont.SetOverline( LINESTYLE_NONE );
    rCJKFont.SetOverline( LINESTYLE_NONE );
    rCTLFont.SetOverline( LINESTYLE_NONE );

    m_xOverlineLB->set_active( 0 );
    eState = rSet->GetItemState( nWhich );

    if ( eState >= SfxItemState::INVALID )
    {
        if ( eState == SfxItemState::INVALID )
            m_xOverlineLB->set_active(-1);
        else
        {
            const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>(rSet->Get( nWhich ));
            FontLineStyle eOverline = rItem.GetValue();
            rFont.SetOverline( eOverline );
            rCJKFont.SetOverline( eOverline );
            rCTLFont.SetOverline( eOverline );

            if ( eOverline != LINESTYLE_NONE )
            {
                auto nPos = m_xOverlineLB->find_id(OUString::number(eOverline));
                if (nPos != -1)
                {
                    m_xOverlineLB->set_active(nPos);
                    bEnable = true;
                }
                Color aColor = rItem.GetColor();
                m_xOverlineColorLB->SelectEntry(aColor);
            }
            else
            {
                m_xOverlineColorLB->SelectEntry(COL_AUTO);
                m_xOverlineColorLB->set_sensitive(false);
            }
        }
    }

    //  Strikeout
    nWhich = GetWhich( SID_ATTR_CHAR_STRIKEOUT );
    rFont.SetStrikeout( STRIKEOUT_NONE );
    rCJKFont.SetStrikeout( STRIKEOUT_NONE );
    rCTLFont.SetStrikeout( STRIKEOUT_NONE );

    m_xStrikeoutLB->set_active( 0 );
    eState = rSet->GetItemState( nWhich );

    if ( eState >= SfxItemState::INVALID )
    {
        if ( eState == SfxItemState::INVALID )
            m_xStrikeoutLB->set_active(-1);
        else
        {
            const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>(rSet->Get( nWhich ));
            FontStrikeout eStrikeout = rItem.GetValue();
            rFont.SetStrikeout( eStrikeout );
            rCJKFont.SetStrikeout( eStrikeout );
            rCTLFont.SetStrikeout( eStrikeout );

            if ( eStrikeout != STRIKEOUT_NONE )
            {
                auto nPos = m_xStrikeoutLB->find_id(OUString::number(eStrikeout));
                if (nPos != -1)
                {
                    m_xStrikeoutLB->set_active(nPos);
                    bEnable = true;
                }
            }
        }
    }

    // WordLineMode
    nWhich = GetWhich( SID_ATTR_CHAR_WORDLINEMODE );
    eState = rSet->GetItemState( nWhich );

    switch ( eState )
    {
        case SfxItemState::UNKNOWN:
            m_aIndividualWordsState.bTriStateEnabled = false;
            m_xIndividualWordsBtn->hide();
            break;

        case SfxItemState::DISABLED:
            m_aIndividualWordsState.bTriStateEnabled = false;
            m_xIndividualWordsBtn->set_sensitive(false);
            break;

        case SfxItemState::INVALID:
--> --------------------

--> maximum size reached

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

Messung V0.5
C=94 H=98 G=95

¤ Dauer der Verarbeitung: 0.30 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