Resolves: tdf#156067 merge special char dialog/popup logic

there was some cut and paste done to create the popup
at some point, so put it back together and reuse the
"delete recent" etc which is missing from the popup case

Change-Id: Idc33d83ea04b46b0255e77bcecf565dc8174e426
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153647
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
diff --git a/cui/source/dialogs/cuicharmap.cxx b/cui/source/dialogs/cuicharmap.cxx
index c075c123..4c4df2f 100644
--- a/cui/source/dialogs/cuicharmap.cxx
+++ b/cui/source/dialogs/cuicharmap.cxx
@@ -58,38 +58,7 @@ SvxCharacterMap::SvxCharacterMap(weld::Widget* pParent, const SfxItemSet* pSet,
    , m_xVirDev(VclPtr<VirtualDevice>::Create())
    , isSearchMode(true)
    , m_xFrame(std::move(xFrame))
    , m_aRecentCharView{SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev)}
    , m_aFavCharView{SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev)}
    , m_aCharmapContents(*m_xBuilder, m_xVirDev)
    , m_aShowChar(m_xVirDev)
    , m_xOKBtn(m_xFrame.is() ? m_xBuilder->weld_button("insert") : m_xBuilder->weld_button("ok"))
    , m_xFontText(m_xBuilder->weld_label("fontft"))
@@ -101,41 +70,7 @@ SvxCharacterMap::SvxCharacterMap(weld::Widget* pParent, const SfxItemSet* pSet,
    , m_xDecimalCodeText(m_xBuilder->weld_entry("decimalvalue"))
    , m_xFavouritesBtn(m_xBuilder->weld_button("favbtn"))
    , m_xCharName(m_xBuilder->weld_label("charname"))
    , m_xRecentGrid(m_xBuilder->weld_widget("viewgrid"))
    , m_xFavGrid(m_xBuilder->weld_widget("favgrid"))
    , m_xShowChar(new weld::CustomWeld(*m_xBuilder, "showchar", m_aShowChar))
    , m_xRecentCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar1", m_aRecentCharView[0]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar2", m_aRecentCharView[1]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar3", m_aRecentCharView[2]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar4", m_aRecentCharView[3]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar5", m_aRecentCharView[4]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar6", m_aRecentCharView[5]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar7", m_aRecentCharView[6]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar8", m_aRecentCharView[7]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar9", m_aRecentCharView[8]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar10", m_aRecentCharView[9]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar11", m_aRecentCharView[10]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar12", m_aRecentCharView[11]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar13", m_aRecentCharView[12]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar14", m_aRecentCharView[13]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar15", m_aRecentCharView[14]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar16", m_aRecentCharView[15])}
    , m_xFavCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar1", m_aFavCharView[0]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar2", m_aFavCharView[1]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar3", m_aFavCharView[2]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar4", m_aFavCharView[3]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar5", m_aFavCharView[4]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar6", m_aFavCharView[5]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar7", m_aFavCharView[6]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar8", m_aFavCharView[7]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar9", m_aFavCharView[8]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar10", m_aFavCharView[9]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar11", m_aFavCharView[10]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar12", m_aFavCharView[11]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar13", m_aFavCharView[12]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar14", m_aFavCharView[13]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar15", m_aFavCharView[14]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar16", m_aFavCharView[15])}
    , m_xShowSet(new SvxShowCharSet(m_xBuilder->weld_scrolled_window("showscroll", true), m_xVirDev))
    , m_xShowSetArea(new weld::CustomWeld(*m_xBuilder, "showcharset", *m_xShowSet))
    , m_xSearchSet(new SvxSearchCharSet(m_xBuilder->weld_scrolled_window("searchscroll", true), m_xVirDev))
@@ -149,9 +84,6 @@ SvxCharacterMap::SvxCharacterMap(weld::Widget* pParent, const SfxItemSet* pSet,
    m_xCharName->set_size_request(m_aShowChar.get_preferred_size().Width(), m_xCharName->get_text_height() * 4);
    //lock the size request of this widget to the width of the original .ui string
    m_xHexCodeText->set_size_request(m_xHexCodeText->get_preferred_size().Width(), -1);
    //so things don't jump around if all the children are hidden
    m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height());
    m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height());

    init();

@@ -222,236 +154,14 @@ void SvxCharacterMap::DisableFontSelection()
    m_xFontLB->set_sensitive(false);
}


void SvxCharacterMap::getRecentCharacterList()
IMPL_LINK_NOARG(SvxCharacterMap, UpdateFavHdl, void*, void)
{
    //retrieve recent character list
    const css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
    for (OUString const & s : rRecentCharList)
    {
        maRecentCharList.push_back(s);
    }

    //retrieve recent character font list
    const css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() );
    for (OUString const & s : rRecentCharFontList)
    {
        maRecentCharFontList.push_back(s);
    }

    // tdf#135997: make sure that the two lists are same length
    const auto nCommonLength = std::min(maRecentCharList.size(), maRecentCharFontList.size());
    maRecentCharList.resize(nCommonLength);
    maRecentCharFontList.resize(nCommonLength);
}


void SvxCharacterMap::getFavCharacterList()
{
    maFavCharList.clear();
    maFavCharFontList.clear();
    //retrieve recent character list
    const css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() );
    for (const OUString& s : rFavCharList)
    {
        maFavCharList.push_back(s);
    }

    //retrieve recent character font list
    const css::uno::Sequence< OUString > rFavCharFontList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::get() );
    for (const OUString& s : rFavCharFontList)
    {
        maFavCharFontList.push_back(s);
    }

    // tdf#135997: make sure that the two lists are same length
    const auto nCommonLength = std::min(maFavCharList.size(), maFavCharFontList.size());
    maFavCharList.resize(nCommonLength);
    maFavCharFontList.resize(nCommonLength);
}

static std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
findInPair(std::u16string_view str1, const std::deque<OUString>& rContainer1,
           std::u16string_view str2, const std::deque<OUString>& rContainer2)
{
    assert(rContainer1.size() == rContainer2.size());

    for (auto it1 = std::find(rContainer1.begin(), rContainer1.end(), str1);
         it1 != rContainer1.end(); it1 = std::find(std::next(it1), rContainer1.end(), str1))
    {
        auto it2 = rContainer2.begin() + (it1 - rContainer1.begin());
        if (*it2 == str2)
            return { it1, it2 };
    }
    return { rContainer1.end(), rContainer2.end() };
}

std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
SvxCharacterMap::getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const
{
    return findInPair(sTitle, maRecentCharList, rFont, maRecentCharFontList);
}

std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
SvxCharacterMap::getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const
{
    return findInPair(sTitle, maFavCharList, rFont, maFavCharFontList);
}


void SvxCharacterMap::updateRecentCharControl()
{
    assert(maRecentCharList.size() == maRecentCharFontList.size());

    int i = 0;
    for ( std::deque< OUString >::iterator it = maRecentCharList.begin(), it2 = maRecentCharFontList.begin();
        it != maRecentCharList.end() && it2 != maRecentCharFontList.end();
        ++it, ++it2, i++)
    {
        m_aRecentCharView[i].SetText(*it);
        vcl::Font rFont = m_aRecentCharView[i].GetFont();
        rFont.SetFamilyName( *it2 );
        m_aRecentCharView[i].SetFont(rFont);
        m_aRecentCharView[i].Show();
    }

    for(; i < 16 ; i++)
    {
        m_aRecentCharView[i].SetText(OUString());
        m_aRecentCharView[i].Hide();
    }
}

void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
{
    // if recent char to be added is already in list, remove it
    if( const auto& [itChar, itChar2] = getRecentChar(sTitle, rFont);
        itChar != maRecentCharList.end() &&  itChar2 != maRecentCharFontList.end() )
    {
        maRecentCharList.erase( itChar );
        maRecentCharFontList.erase( itChar2);
    }

    if (maRecentCharList.size() == 16)
    {
        maRecentCharList.pop_back();
        maRecentCharFontList.pop_back();
    }

    maRecentCharList.push_front(sTitle);
    maRecentCharFontList.push_front(rFont);

    css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
    auto aRecentCharListRange = asNonConstRange(aRecentCharList);
    css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
    auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);

    for (size_t i = 0; i < maRecentCharList.size(); ++i)
    {
        aRecentCharListRange[i] = maRecentCharList[i];
        aRecentCharFontListRange[i] = maRecentCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
    officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
    batch->commit();

    updateRecentCharControl();
}


void SvxCharacterMap::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
{
    // if Fav char to be added is already in list, remove it
    if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
        itChar != maFavCharList.end() &&  itChar2 != maFavCharFontList.end() )
    {
        maFavCharList.erase( itChar );
        maFavCharFontList.erase( itChar2);
    }

    if (maFavCharList.size() == 16)
    {
        maFavCharList.pop_back();
        maFavCharFontList.pop_back();
    }

    maFavCharList.push_back(sTitle);
    maFavCharFontList.push_back(rFont);

    css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
    auto aFavCharListRange = asNonConstRange(aFavCharList);
    css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
    auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);

    for (size_t i = 0; i < maFavCharList.size(); ++i)
    {
        aFavCharListRange[i] = maFavCharList[i];
        aFavCharFontListRange[i] = maFavCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
    batch->commit();
}


void SvxCharacterMap::updateFavCharControl()
{
    assert(maFavCharList.size() == maFavCharFontList.size());

    int i = 0;
    for ( std::deque< OUString >::iterator it = maFavCharList.begin(), it2 = maFavCharFontList.begin();
        it != maFavCharList.end() && it2 != maFavCharFontList.end();
        ++it, ++it2, i++)
    {
        m_aFavCharView[i].SetText(*it);
        vcl::Font rFont = m_aFavCharView[i].GetFont();
        rFont.SetFamilyName( *it2 );
        m_aFavCharView[i].SetFont(rFont);
        m_aFavCharView[i].Show();
    }

    for(; i < 16 ; i++)
    {
        m_aFavCharView[i].SetText(OUString());
        m_aFavCharView[i].Hide();
    }
    m_xShowSet->getFavCharacterList();
    m_xSearchSet->getFavCharacterList();
    // tdf#109214 - redraw highlight of the favorite characters
    m_xShowSet->Invalidate();
}

void SvxCharacterMap::deleteFavCharacterFromList(std::u16string_view sTitle, std::u16string_view rFont)
{
    // if Fav char is found, remove it
    if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
        itChar != maFavCharList.end() &&  itChar2 != maFavCharFontList.end() )
    {
        maFavCharList.erase( itChar );
        maFavCharFontList.erase( itChar2);
    }

    css::uno::Sequence< OUString > aFavCharList(maFavCharList.size());
    auto aFavCharListRange = asNonConstRange(aFavCharList);
    css::uno::Sequence< OUString > aFavCharFontList(maFavCharFontList.size());
    auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);

    for (size_t i = 0; i < maFavCharList.size(); ++i)
    {
        aFavCharListRange[i] = maFavCharList[i];
        aFavCharFontListRange[i] = maFavCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
    batch->commit();
}

void SvxCharacterMap::init()
{
    aFont = m_xVirDev->GetFont();
@@ -549,25 +259,10 @@ void SvxCharacterMap::init()
        m_xOKBtn->set_sensitive(true);
    }

    getRecentCharacterList();
    updateRecentCharControl();

    getFavCharacterList();
    updateFavCharControl();

    bool bHasInsert = m_xFrame.is();

    for(int i = 0; i < 16; i++)
    {
        m_aRecentCharView[i].SetHasInsert(bHasInsert);
        m_aRecentCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl));
        m_aRecentCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, RecentClearClickHdl));
        m_aRecentCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, RecentClearAllClickHdl));
        m_aFavCharView[i].SetHasInsert(bHasInsert);
        m_aFavCharView[i].setMouseClickHdl(LINK(this,SvxCharacterMap, CharClickHdl));
        m_aFavCharView[i].setClearClickHdl(LINK(this,SvxCharacterMap, FavClearClickHdl));
        m_aFavCharView[i].setClearAllClickHdl(LINK(this,SvxCharacterMap, FavClearAllClickHdl));
    }
    m_aCharmapContents.init(m_xFrame.is(),
                            LINK(this, SvxCharacterMap, CharClickHdl),
                            LINK(this, SvxCharacterMap, UpdateFavHdl),
                            Link<void*, void>());

    setCharName(90);

@@ -575,13 +270,6 @@ void SvxCharacterMap::init()
    m_xSearchText->connect_changed(LINK(this, SvxCharacterMap, SearchUpdateHdl));
}

bool SvxCharacterMap::isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
{
    const auto& [itChar, itFont] = getFavChar(sTitle, rFont);
    return itChar != maFavCharList.end() && itFont != maFavCharFontList.end();
}


void SvxCharacterMap::setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont)
{
    if(sTitle.empty() || rFont.empty())
@@ -592,16 +280,14 @@ void SvxCharacterMap::setFavButtonState(std::u16string_view sTitle, std::u16stri
    else
        m_xFavouritesBtn->set_sensitive(true);

    if (isFavChar(sTitle, rFont))
    if (m_aCharmapContents.isFavChar(sTitle, rFont))
    {
        m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_REMOVE_FAVORITES));
    }
    else
    {
        if(maFavCharList.size() == 16)
        {
        if (m_aCharmapContents.FavCharListIsFull())
            m_xFavouritesBtn->set_sensitive(false);
        }

        m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
    }
@@ -656,7 +342,7 @@ void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph)
        };
        comphelper::dispatchCommand(".uno:InsertSymbol", m_xFrame, aArgs);

        updateRecentCharacterList(sGlyph, aFont.GetFamilyName());
        m_aCharmapContents.updateRecentCharacterList(sGlyph, aFont.GetFamilyName());

    } else {
        sal_UCS4 cChar = sGlyph.iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
@@ -783,70 +469,6 @@ IMPL_LINK_NOARG(SvxCharacterMap, SubsetSelectHdl, weld::ComboBox&, void)
    }
}

IMPL_LINK(SvxCharacterMap, RecentClearClickHdl, SvxCharView*, rView, void)
{
    const OUString& sTitle = rView->GetText();
    OUString sFont = rView->GetFont().GetFamilyName();

    // if recent char to be added is already in list, remove it
    if( const auto& [itChar, itChar2] = getRecentChar(sTitle, sFont);
        itChar != maRecentCharList.end() &&  itChar2 != maRecentCharFontList.end() )
    {
        maRecentCharList.erase( itChar );
        maRecentCharFontList.erase( itChar2);
    }

    css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size());
    auto aRecentCharListRange = asNonConstRange(aRecentCharList);
    css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size());
    auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);

    for (size_t i = 0; i < maRecentCharList.size(); ++i)
    {
        aRecentCharListRange[i] = maRecentCharList[i];
        aRecentCharFontListRange[i] = maRecentCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
    officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
    batch->commit();

    updateRecentCharControl();
}

IMPL_LINK_NOARG(SvxCharacterMap, RecentClearAllClickHdl, SvxCharView*, void)
{
    maRecentCharList.clear();
    maRecentCharFontList.clear();

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::RecentCharacters::RecentCharacterList::set({ }, batch);
    officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set({ }, batch);
    batch->commit();

    updateRecentCharControl();
}

IMPL_LINK(SvxCharacterMap, FavClearClickHdl, SvxCharView*, rView, void)
{
    deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
    updateFavCharControl();
}

IMPL_LINK_NOARG(SvxCharacterMap, FavClearAllClickHdl, SvxCharView*, void)
{
    maFavCharList.clear();
    maFavCharFontList.clear();

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set({ }, batch);
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set({ }, batch);
    batch->commit();

    updateFavCharControl();
}

IMPL_LINK_NOARG(SvxCharacterMap, SearchFieldGetFocusHdl, weld::Widget&, void)
{
    m_xOKBtn->set_sensitive(false);
@@ -955,7 +577,7 @@ IMPL_LINK_NOARG(SvxCharacterMap, InsertClickHdl, weld::Button&, void)
    insertCharToDoc(sChar);
    // Need to update recent character list, when OK button does not insert
    if(!m_xFrame.is())
        updateRecentCharacterList(sChar, aFont.GetFamilyName());
        m_aCharmapContents.updateRecentCharacterList(sChar, aFont.GetFamilyName());
    m_xDialog->response(RET_OK);
}

@@ -963,23 +585,23 @@ IMPL_LINK_NOARG(SvxCharacterMap, FavSelectHdl, weld::Button&, void)
{
    if (m_xFavouritesBtn->get_label().match(CuiResId(RID_CUISTR_ADD_FAVORITES)))
    {
        updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
        m_aCharmapContents.updateFavCharacterList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
        setFavButtonState(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
    }
    else
    {
        deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
        m_aCharmapContents.deleteFavCharacterFromList(m_aShowChar.GetText(), m_aShowChar.GetFont().GetFamilyName());
        m_xFavouritesBtn->set_label(CuiResId(RID_CUISTR_ADD_FAVORITES));
        m_xFavouritesBtn->set_sensitive(false);
    }

    updateFavCharControl();
    m_aCharmapContents.updateFavCharControl();
}

IMPL_LINK_NOARG(SvxCharacterMap, FavClickHdl, SvxShowCharSet*, void)
{
    getFavCharacterList();
    updateFavCharControl();
    m_aCharmapContents.getFavCharacterList();
    m_aCharmapContents.updateFavCharControl();
}

IMPL_LINK_NOARG(SvxCharacterMap, CharHighlightHdl, SvxShowCharSet*, void)
diff --git a/include/cui/cuicharmap.hxx b/include/cui/cuicharmap.hxx
index 431ce6d..8b85b18 100644
--- a/include/cui/cuicharmap.hxx
+++ b/include/cui/cuicharmap.hxx
@@ -83,13 +83,9 @@ private:
    std::unique_ptr<const SubsetMap> pSubsetMap;
    bool isSearchMode;
    css::uno::Reference<css::frame::XFrame> m_xFrame;
    std::deque<OUString> maRecentCharList;
    std::deque<OUString> maRecentCharFontList;
    std::deque<OUString> maFavCharList;
    std::deque<OUString> maFavCharFontList;

    SvxCharView m_aRecentCharView[16];
    SvxCharView m_aFavCharView[16];
    SfxCharmapContainer m_aCharmapContents;

    SvxShowText m_aShowChar;

    std::unique_ptr<weld::Button> m_xOKBtn;
@@ -102,11 +98,7 @@ private:
    std::unique_ptr<weld::Entry> m_xDecimalCodeText;
    std::unique_ptr<weld::Button> m_xFavouritesBtn;
    std::unique_ptr<weld::Label> m_xCharName;
    std::unique_ptr<weld::Widget> m_xRecentGrid;
    std::unique_ptr<weld::Widget> m_xFavGrid;
    std::unique_ptr<weld::CustomWeld> m_xShowChar;
    std::unique_ptr<weld::CustomWeld> m_xRecentCharView[16];
    std::unique_ptr<weld::CustomWeld> m_xFavCharView[16];
    std::unique_ptr<SvxShowCharSet> m_xShowSet;
    std::unique_ptr<weld::CustomWeld> m_xShowSetArea;
    std::unique_ptr<SvxSearchCharSet> m_xSearchSet;
@@ -135,14 +127,11 @@ private:
    DECL_DLLPRIVATE_LINK(DecimalCodeChangeHdl, weld::Entry&, void);
    DECL_DLLPRIVATE_LINK(HexCodeChangeHdl, weld::Entry&, void);
    DECL_DLLPRIVATE_LINK(CharClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(RecentClearClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(FavClearClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(RecentClearAllClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(FavClearAllClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(InsertClickHdl, weld::Button&, void);
    DECL_DLLPRIVATE_LINK(FavSelectHdl, weld::Button&, void);
    DECL_DLLPRIVATE_LINK(SearchUpdateHdl, weld::Entry&, void);
    DECL_DLLPRIVATE_LINK(SearchFieldGetFocusHdl, weld::Widget&, void);
    DECL_DLLPRIVATE_LINK(UpdateFavHdl, void*, void);

    static void fillAllSubsets(weld::ComboBox& rListBox);
    void selectCharByCode(Radix radix);
@@ -164,30 +153,13 @@ public:
    void SetChar(sal_UCS4);
    sal_UCS4 GetChar() const;

    void getRecentCharacterList(); //gets both recent char and recent char font list
    void updateRecentCharacterList(const OUString& rChar, const OUString& rFont);

    void getFavCharacterList(); //gets both Fav char and Fav char font list
    void updateFavCharacterList(const OUString& rChar, const OUString& rFont);
    void deleteFavCharacterFromList(std::u16string_view rChar, std::u16string_view rFont);
    bool isFavChar(std::u16string_view sTitle, std::u16string_view rFont);

    void updateRecentCharControl();
    void insertCharToDoc(const OUString& sChar);

    void updateFavCharControl();
    void setFavButtonState(std::u16string_view sTitle, std::u16string_view rFont);

    void setCharName(sal_UCS4 nDecimalValue);

    void toggleSearchView(bool state);

private:
    std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
    getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const;

    std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
    getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const;
};

#endif
diff --git a/include/sfx2/charwin.hxx b/include/sfx2/charwin.hxx
index a2beabc..515aa64 100644
--- a/include/sfx2/charwin.hxx
+++ b/include/sfx2/charwin.hxx
@@ -24,6 +24,7 @@
#include <vcl/customweld.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weld.hxx>
#include <deque>

class SFX2_DLLPUBLIC SvxCharView final : public weld::CustomWidgetController
{
@@ -67,6 +68,63 @@ public:
    void ContextMenuSelect(std::u16string_view rIdent);
};

class SFX2_DLLPUBLIC SfxCharmapContainer
{
    std::deque<OUString>   m_aRecentCharList;
    std::deque<OUString>   m_aRecentCharFontList;
    std::deque<OUString>   m_aFavCharList;
    std::deque<OUString>   m_aFavCharFontList;

    SvxCharView m_aRecentCharView[16];
    SvxCharView m_aFavCharView[16];
    std::unique_ptr<weld::CustomWeld> m_xRecentCharView[16];
    std::unique_ptr<weld::CustomWeld> m_xFavCharView[16];

    std::unique_ptr<weld::Widget> m_xRecentGrid;
    std::unique_ptr<weld::Widget> m_xFavGrid;

    Link<SvxCharView*, void> m_aMouseClickHdl;
    Link<void*, void> m_aUpdateFavHdl;
    Link<void*, void> m_aUpdateRecentHdl;

    DECL_DLLPRIVATE_LINK(CharClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(RecentClearClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(FavClearClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(RecentClearAllClickHdl, SvxCharView*, void);
    DECL_DLLPRIVATE_LINK(FavClearAllClickHdl, SvxCharView*, void);

public:
    SfxCharmapContainer(weld::Builder& rBuilder, const VclPtr<VirtualDevice>& rVirDev);

    void            init(bool bHasInsert, const Link<SvxCharView*,void> &rMouseClickHdl,
                         const Link<void*,void> &rUpdateFavHdl,
                         const Link<void*,void> &rUpdateRecentHdl);

    void            getFavCharacterList();
    void            updateFavCharControl();

    void            getRecentCharacterList(); //gets both recent char and recent char font list
    void            updateRecentCharControl();

    void            updateRecentCharacterList(const OUString& sTitle, const OUString& rFont);
    void            updateFavCharacterList(const OUString& sTitle, const OUString& rFont);
    void            deleteFavCharacterFromList(std::u16string_view sTitle, std::u16string_view rFont);

    bool            isFavChar(std::u16string_view sTitle, std::u16string_view rFont);
    bool            hasRecentChars() const;

    bool            FavCharListIsFull() const;

    void            GrabFocusToFirstFavorite();

private:
    std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
    getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const;

    std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
    getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const;
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sfx2/inc/charmapcontrol.hxx b/sfx2/inc/charmapcontrol.hxx
index e2c1e1e..c604515 100644
--- a/sfx2/inc/charmapcontrol.hxx
+++ b/sfx2/inc/charmapcontrol.hxx
@@ -41,26 +41,14 @@ private:

    ScopedVclPtr<VirtualDevice> m_xVirDev;

    std::deque<OUString>   m_aRecentCharList;
    std::deque<OUString>   m_aRecentCharFontList;
    std::deque<OUString>   m_aFavCharList;
    std::deque<OUString>   m_aFavCharFontList;
    SfxCharmapContainer m_aCharmapContents;

    SvxCharView m_aRecentCharView[16];
    SvxCharView m_aFavCharView[16];
    std::unique_ptr<weld::Label> m_xRecentLabel;
    std::unique_ptr<weld::Button> m_xDlgBtn;
    std::unique_ptr<weld::CustomWeld> m_xRecentCharView[16];
    std::unique_ptr<weld::CustomWeld> m_xFavCharView[16];

    DECL_LINK(CharClickHdl, SvxCharView*, void);
    DECL_LINK(OpenDlgHdl, weld::Button&, void);

    void            getFavCharacterList();
    void            updateFavCharControl();

    void            getRecentCharacterList(); //gets both recent char and recent char font list
    void            updateRecentCharControl();
    DECL_LINK(UpdateRecentHdl, void*, void);
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/control/charmapcontrol.cxx b/sfx2/source/control/charmapcontrol.cxx
index a79da74..359b81c 100644
--- a/sfx2/source/control/charmapcontrol.cxx
+++ b/sfx2/source/control/charmapcontrol.cxx
@@ -27,97 +27,127 @@

using namespace css;

SfxCharmapCtrl::SfxCharmapCtrl(CharmapPopup* pControl, weld::Widget* pParent)
    : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "sfx/ui/charmapcontrol.ui", "charmapctrl")
    , m_xControl(pControl)
    , m_xVirDev(VclPtr<VirtualDevice>::Create())
    , m_aRecentCharView{SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev),
                        SvxCharView(m_xVirDev)}
    , m_aFavCharView{SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev),
                     SvxCharView(m_xVirDev)}
    , m_xRecentLabel(m_xBuilder->weld_label("label2"))
    , m_xDlgBtn(m_xBuilder->weld_button("specialchardlg"))
    , m_xRecentCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar1", m_aRecentCharView[0]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar2", m_aRecentCharView[1]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar3", m_aRecentCharView[2]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar4", m_aRecentCharView[3]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar5", m_aRecentCharView[4]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar6", m_aRecentCharView[5]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar7", m_aRecentCharView[6]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar8", m_aRecentCharView[7]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar9", m_aRecentCharView[8]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar10", m_aRecentCharView[9]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar11", m_aRecentCharView[10]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar12", m_aRecentCharView[11]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar13", m_aRecentCharView[12]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar14", m_aRecentCharView[13]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar15", m_aRecentCharView[14]),
                        std::make_unique<weld::CustomWeld>(*m_xBuilder, "viewchar16", m_aRecentCharView[15])}
    , m_xFavCharView{std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar1", m_aFavCharView[0]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar2", m_aFavCharView[1]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar3", m_aFavCharView[2]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar4", m_aFavCharView[3]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar5", m_aFavCharView[4]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar6", m_aFavCharView[5]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar7", m_aFavCharView[6]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar8", m_aFavCharView[7]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar9", m_aFavCharView[8]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar10", m_aFavCharView[9]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar11", m_aFavCharView[10]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar12", m_aFavCharView[11]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar13", m_aFavCharView[12]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar14", m_aFavCharView[13]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar15", m_aFavCharView[14]),
                     std::make_unique<weld::CustomWeld>(*m_xBuilder, "favchar16", m_aFavCharView[15])}
SfxCharmapContainer::SfxCharmapContainer(weld::Builder& rBuilder, const VclPtr<VirtualDevice>& rVirDev)
    : m_aRecentCharView{SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev),
                        SvxCharView(rVirDev)}
    , m_aFavCharView{SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev),
                     SvxCharView(rVirDev)}
    , m_xRecentCharView{std::make_unique<weld::CustomWeld>(rBuilder, "viewchar1", m_aRecentCharView[0]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar2", m_aRecentCharView[1]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar3", m_aRecentCharView[2]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar4", m_aRecentCharView[3]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar5", m_aRecentCharView[4]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar6", m_aRecentCharView[5]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar7", m_aRecentCharView[6]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar8", m_aRecentCharView[7]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar9", m_aRecentCharView[8]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar10", m_aRecentCharView[9]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar11", m_aRecentCharView[10]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar12", m_aRecentCharView[11]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar13", m_aRecentCharView[12]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar14", m_aRecentCharView[13]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar15", m_aRecentCharView[14]),
                        std::make_unique<weld::CustomWeld>(rBuilder, "viewchar16", m_aRecentCharView[15])}
    , m_xFavCharView{std::make_unique<weld::CustomWeld>(rBuilder, "favchar1", m_aFavCharView[0]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar2", m_aFavCharView[1]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar3", m_aFavCharView[2]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar4", m_aFavCharView[3]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar5", m_aFavCharView[4]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar6", m_aFavCharView[5]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar7", m_aFavCharView[6]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar8", m_aFavCharView[7]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar9", m_aFavCharView[8]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar10", m_aFavCharView[9]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar11", m_aFavCharView[10]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar12", m_aFavCharView[11]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar13", m_aFavCharView[12]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar14", m_aFavCharView[13]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar15", m_aFavCharView[14]),
                     std::make_unique<weld::CustomWeld>(rBuilder, "favchar16", m_aFavCharView[15])}
    , m_xRecentGrid(rBuilder.weld_widget("viewgrid"))
    , m_xFavGrid(rBuilder.weld_widget("favgrid"))
{
    for(int i = 0; i < 16; i++)
    {
        m_aRecentCharView[i].setMouseClickHdl(LINK(this,SfxCharmapCtrl, CharClickHdl));
        m_aFavCharView[i].setMouseClickHdl(LINK(this,SfxCharmapCtrl, CharClickHdl));
    }
    //so things don't jump around if all the children are hidden
    m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height());
    m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height());
}

    m_xDlgBtn->connect_clicked(LINK(this, SfxCharmapCtrl, OpenDlgHdl));
void SfxCharmapContainer::init(bool bHasInsert, const Link<SvxCharView*,void> &rMouseClickHdl,
                               const Link<void*, void>& rUpdateFavHdl,
                               const Link<void*, void>& rUpdateRecentHdl)
{
    m_aUpdateFavHdl = rUpdateFavHdl;
    m_aUpdateRecentHdl = rUpdateRecentHdl;

    getRecentCharacterList();
    updateRecentCharControl();
    getFavCharacterList();
    updateFavCharControl();

    for(int i = 0; i < 16; i++)
    {
        m_aRecentCharView[i].SetHasInsert(bHasInsert);
        m_aRecentCharView[i].setMouseClickHdl(rMouseClickHdl);
        m_aRecentCharView[i].setClearClickHdl(LINK(this, SfxCharmapContainer, RecentClearClickHdl));
        m_aRecentCharView[i].setClearAllClickHdl(LINK(this, SfxCharmapContainer, RecentClearAllClickHdl));
        m_aFavCharView[i].SetHasInsert(bHasInsert);
        m_aFavCharView[i].setMouseClickHdl(rMouseClickHdl);
        m_aFavCharView[i].setClearClickHdl(LINK(this, SfxCharmapContainer, FavClearClickHdl));
        m_aFavCharView[i].setClearAllClickHdl(LINK(this, SfxCharmapContainer, FavClearAllClickHdl));
    }
}

SfxCharmapCtrl::SfxCharmapCtrl(CharmapPopup* pControl, weld::Widget* pParent)
    : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "sfx/ui/charmapcontrol.ui", "charmapctrl")
    , m_xControl(pControl)
    , m_xVirDev(VclPtr<VirtualDevice>::Create())
    , m_aCharmapContents(*m_xBuilder, m_xVirDev)
    , m_xRecentLabel(m_xBuilder->weld_label("label2"))
    , m_xDlgBtn(m_xBuilder->weld_button("specialchardlg"))
{
    m_aCharmapContents.init(false, LINK(this, SfxCharmapCtrl, CharClickHdl),
                            Link<void*,void>(), LINK(this, SfxCharmapCtrl, UpdateRecentHdl));

    m_xDlgBtn->connect_clicked(LINK(this, SfxCharmapCtrl, OpenDlgHdl));
}

SfxCharmapCtrl::~SfxCharmapCtrl()
{
}

void SfxCharmapCtrl::getFavCharacterList()
void SfxCharmapContainer::getFavCharacterList()
{
    m_aFavCharList.clear();
    m_aFavCharFontList.clear();

    //retrieve recent character list
    const css::uno::Sequence< OUString > rFavCharList( officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::get() );
    m_aFavCharList.insert( m_aFavCharList.end(), rFavCharList.begin(), rFavCharList.end() );
@@ -132,7 +162,7 @@ void SfxCharmapCtrl::getFavCharacterList()
    m_aFavCharFontList.resize(nCommonLength);
}

void SfxCharmapCtrl::updateFavCharControl()
void SfxCharmapContainer::updateFavCharControl()
{
    assert(m_aFavCharList.size() == m_aFavCharFontList.size());

@@ -153,10 +183,15 @@ void SfxCharmapCtrl::updateFavCharControl()
        m_aFavCharView[i].SetText(OUString());
        m_aFavCharView[i].Hide();
    }

    m_aUpdateFavHdl.Call(nullptr);
}

void SfxCharmapCtrl::getRecentCharacterList()
void SfxCharmapContainer::getRecentCharacterList()
{
    m_aRecentCharList.clear();
    m_aRecentCharFontList.clear();

    //retrieve recent character list
    const css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() );
    m_aRecentCharList.insert( m_aRecentCharList.end(), rRecentCharList.begin(), rRecentCharList.end() );
@@ -171,31 +206,6 @@ void SfxCharmapCtrl::getRecentCharacterList()
    m_aRecentCharFontList.resize(nCommonLength);
}

void SfxCharmapCtrl::updateRecentCharControl()
{
    assert(m_aRecentCharList.size() == m_aRecentCharFontList.size());
    int i = 0;
    for ( std::deque< OUString >::iterator it = m_aRecentCharList.begin(), it2 = m_aRecentCharFontList.begin();
        it != m_aRecentCharList.end() && it2 != m_aRecentCharFontList.end();
        ++it, ++it2, i++)
    {
        m_aRecentCharView[i].SetText(*it);
        vcl::Font rFont = m_aRecentCharView[i].GetFont();
        rFont.SetFamilyName( *it2 );
        m_aRecentCharView[i].SetFont(rFont);
        m_aRecentCharView[i].Show();
    }

    for(; i < 16 ; i++)
    {
        m_aRecentCharView[i].SetText(OUString());
        m_aRecentCharView[i].Hide();
    }

    //checking if the characters are recently used or no
    m_xRecentLabel->set_label(m_aRecentCharList.size() > 0 ? SfxResId(STR_RECENT) : SfxResId(STR_NORECENT));
}

IMPL_LINK(SfxCharmapCtrl, CharClickHdl, SvxCharView*, pView, void)
{
    m_xControl->EndPopupMode();
@@ -216,7 +226,257 @@ IMPL_LINK_NOARG(SfxCharmapCtrl, OpenDlgHdl, weld::Button&, void)

void SfxCharmapCtrl::GrabFocus()
{
    m_aCharmapContents.GrabFocusToFirstFavorite();
}

void SfxCharmapContainer::GrabFocusToFirstFavorite()
{
    m_aFavCharView[0].GrabFocus();
}

static std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
findInPair(std::u16string_view str1, const std::deque<OUString>& rContainer1,
           std::u16string_view str2, const std::deque<OUString>& rContainer2)
{
    assert(rContainer1.size() == rContainer2.size());

    for (auto it1 = std::find(rContainer1.begin(), rContainer1.end(), str1);
         it1 != rContainer1.end(); it1 = std::find(std::next(it1), rContainer1.end(), str1))
    {
        auto it2 = rContainer2.begin() + (it1 - rContainer1.begin());
        if (*it2 == str2)
            return { it1, it2 };
    }
    return { rContainer1.end(), rContainer2.end() };
}

std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
SfxCharmapContainer::getRecentChar(std::u16string_view sTitle, std::u16string_view rFont) const
{
    return findInPair(sTitle, m_aRecentCharList, rFont, m_aRecentCharFontList);
}

std::pair<std::deque<OUString>::const_iterator, std::deque<OUString>::const_iterator>
SfxCharmapContainer::getFavChar(std::u16string_view sTitle, std::u16string_view rFont) const
{
    return findInPair(sTitle, m_aFavCharList, rFont, m_aFavCharFontList);
}

void SfxCharmapContainer::updateRecentCharControl()
{
    assert(m_aRecentCharList.size() == m_aRecentCharFontList.size());

    int i = 0;
    for ( std::deque< OUString >::iterator it = m_aRecentCharList.begin(), it2 = m_aRecentCharFontList.begin();
        it != m_aRecentCharList.end() && it2 != m_aRecentCharFontList.end();
        ++it, ++it2, i++)
    {
        m_aRecentCharView[i].SetText(*it);
        vcl::Font rFont = m_aRecentCharView[i].GetFont();
        rFont.SetFamilyName( *it2 );
        m_aRecentCharView[i].SetFont(rFont);
        m_aRecentCharView[i].Show();
    }

    for(; i < 16 ; i++)
    {
        m_aRecentCharView[i].SetText(OUString());
        m_aRecentCharView[i].Hide();
    }

    m_aUpdateRecentHdl.Call(nullptr);
}

void SfxCharmapContainer::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont)
{
    // if recent char to be added is already in list, remove it
    if( const auto& [itChar, itChar2] = getRecentChar(sTitle, rFont);
        itChar != m_aRecentCharList.end() &&  itChar2 != m_aRecentCharFontList.end() )
    {
        m_aRecentCharList.erase( itChar );
        m_aRecentCharFontList.erase( itChar2);
    }

    if (m_aRecentCharList.size() == 16)
    {
        m_aRecentCharList.pop_back();
        m_aRecentCharFontList.pop_back();
    }

    m_aRecentCharList.push_front(sTitle);
    m_aRecentCharFontList.push_front(rFont);

    css::uno::Sequence< OUString > aRecentCharList(m_aRecentCharList.size());
    auto aRecentCharListRange = asNonConstRange(aRecentCharList);
    css::uno::Sequence< OUString > aRecentCharFontList(m_aRecentCharFontList.size());
    auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);

    for (size_t i = 0; i < m_aRecentCharList.size(); ++i)
    {
        aRecentCharListRange[i] = m_aRecentCharList[i];
        aRecentCharFontListRange[i] = m_aRecentCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
    officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
    batch->commit();

    updateRecentCharControl();
}

void SfxCharmapContainer::updateFavCharacterList(const OUString& sTitle, const OUString& rFont)
{
    // if Fav char to be added is already in list, remove it
    if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
        itChar != m_aFavCharList.end() &&  itChar2 != m_aFavCharFontList.end() )
    {
        m_aFavCharList.erase( itChar );
        m_aFavCharFontList.erase( itChar2);
    }

    if (m_aFavCharList.size() == 16)
    {
        m_aFavCharList.pop_back();
        m_aFavCharFontList.pop_back();
    }

    m_aFavCharList.push_back(sTitle);
    m_aFavCharFontList.push_back(rFont);

    css::uno::Sequence< OUString > aFavCharList(m_aFavCharList.size());
    auto aFavCharListRange = asNonConstRange(aFavCharList);
    css::uno::Sequence< OUString > aFavCharFontList(m_aFavCharFontList.size());
    auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);

    for (size_t i = 0; i < m_aFavCharList.size(); ++i)
    {
        aFavCharListRange[i] = m_aFavCharList[i];
        aFavCharFontListRange[i] = m_aFavCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
    batch->commit();
}

void SfxCharmapContainer::deleteFavCharacterFromList(std::u16string_view sTitle, std::u16string_view rFont)
{
    // if Fav char is found, remove it
    if( const auto& [itChar, itChar2] = getFavChar(sTitle, rFont);
        itChar != m_aFavCharList.end() &&  itChar2 != m_aFavCharFontList.end() )
    {
        m_aFavCharList.erase( itChar );
        m_aFavCharFontList.erase( itChar2);
    }

    css::uno::Sequence< OUString > aFavCharList(m_aFavCharList.size());
    auto aFavCharListRange = asNonConstRange(aFavCharList);
    css::uno::Sequence< OUString > aFavCharFontList(m_aFavCharFontList.size());
    auto aFavCharFontListRange = asNonConstRange(aFavCharFontList);

    for (size_t i = 0; i < m_aFavCharList.size(); ++i)
    {
        aFavCharListRange[i] = m_aFavCharList[i];
        aFavCharFontListRange[i] = m_aFavCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set(aFavCharList, batch);
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set(aFavCharFontList, batch);
    batch->commit();
}

bool SfxCharmapContainer::isFavChar(std::u16string_view sTitle, std::u16string_view rFont)
{
    const auto& [itChar, itFont] = getFavChar(sTitle, rFont);
    return itChar != m_aFavCharList.end() && itFont != m_aFavCharFontList.end();
}

IMPL_LINK(SfxCharmapContainer, CharClickHdl, SvxCharView*, pView, void)
{
    m_aMouseClickHdl.Call(pView);
}

IMPL_LINK(SfxCharmapContainer, RecentClearClickHdl, SvxCharView*, rView, void)
{
    const OUString& sTitle = rView->GetText();
    OUString sFont = rView->GetFont().GetFamilyName();

    // if recent char to be added is already in list, remove it
    if( const auto& [itChar, itChar2] = getRecentChar(sTitle, sFont);
        itChar != m_aRecentCharList.end() &&  itChar2 != m_aRecentCharFontList.end() )
    {
        m_aRecentCharList.erase( itChar );
        m_aRecentCharFontList.erase( itChar2);
    }

    css::uno::Sequence< OUString > aRecentCharList(m_aRecentCharList.size());
    auto aRecentCharListRange = asNonConstRange(aRecentCharList);
    css::uno::Sequence< OUString > aRecentCharFontList(m_aRecentCharFontList.size());
    auto aRecentCharFontListRange = asNonConstRange(aRecentCharFontList);

    for (size_t i = 0; i < m_aRecentCharList.size(); ++i)
    {
        aRecentCharListRange[i] = m_aRecentCharList[i];
        aRecentCharFontListRange[i] = m_aRecentCharFontList[i];
    }

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch);
    officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch);
    batch->commit();

    updateRecentCharControl();
}

IMPL_LINK_NOARG(SfxCharmapContainer, RecentClearAllClickHdl, SvxCharView*, void)
{
    m_aRecentCharList.clear();
    m_aRecentCharFontList.clear();

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::RecentCharacters::RecentCharacterList::set({ }, batch);
    officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set({ }, batch);
    batch->commit();

    updateRecentCharControl();
}

IMPL_LINK(SfxCharmapContainer, FavClearClickHdl, SvxCharView*, rView, void)
{
    deleteFavCharacterFromList(rView->GetText(), rView->GetFont().GetFamilyName());
    updateFavCharControl();
}

IMPL_LINK_NOARG(SfxCharmapContainer, FavClearAllClickHdl, SvxCharView*, void)
{
    m_aFavCharList.clear();
    m_aFavCharFontList.clear();

    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterList::set({ }, batch);
    officecfg::Office::Common::FavoriteCharacters::FavoriteCharacterFontList::set({ }, batch);
    batch->commit();

    updateFavCharControl();
}

bool SfxCharmapContainer::FavCharListIsFull() const
{
    return m_aFavCharList.size() == 16;
}

bool SfxCharmapContainer::hasRecentChars() const
{
    return !m_aRecentCharList.empty();
}

IMPL_LINK_NOARG(SfxCharmapCtrl, UpdateRecentHdl, void*, void)
{
    //checking if the characters are recently used or no
    m_xRecentLabel->set_label(m_aCharmapContents.hasRecentChars() ? SfxResId(STR_RECENT) : SfxResId(STR_NORECENT));
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/uiconfig/ui/charmapcontrol.ui b/sfx2/uiconfig/ui/charmapcontrol.ui
index f1d0128..28a080a 100644
--- a/sfx2/uiconfig/ui/charmapcontrol.ui
+++ b/sfx2/uiconfig/ui/charmapcontrol.ui
@@ -27,7 +27,7 @@
        </child>
        <child>
          <!-- n-columns=1 n-rows=1 -->
          <object class="GtkGrid" id="grid1">
          <object class="GtkGrid" id="favgrid">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">start</property>
@@ -268,7 +268,7 @@
        </child>
        <child>
          <!-- n-columns=1 n-rows=1 -->
          <object class="GtkGrid" id="grid2">
          <object class="GtkGrid" id="viewgrid">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">start</property>