<commit_before>/* -*- 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 <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>

#include <vcl/menu.hxx>
#include <vcl/settings.hxx>
#include <svl/intitem.hxx>
#include <svl/stritem.hxx>
#include <svl/style.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <unotools/intlwrapper.hxx>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/theUICommandDescription.hpp>

#include <sfx2/sfxhelp.hxx>
#include <sfx2/app.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/templdlg.hxx>
#include "templdgi.hxx"
#include "tplcitem.hxx"
#include "sfxtypes.hxx"
#include <sfx2/styfitem.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/newstyle.hxx>
#include <sfx2/tplpitem.hxx>
#include <sfx2/sfxresid.hxx>

#include "templdlg.hrc"
#include <sfx2/sfx.hrc>
#include "dialog.hrc"
#include "arrdecl.hxx"
#include <sfx2/docfilt.hxx>
#include <sfx2/docfac.hxx>
#include <sfx2/doctempl.hxx>
#include <sfx2/module.hxx>
#include <sfx2/imgmgr.hxx>
#include "helpid.hrc"
#include "appdata.hxx"
#include <sfx2/viewfrm.hxx>

#include <comphelper/string.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::uno;


// Window is now created dynamically. So here margins, etc.

#define SFX_TEMPLDLG_HFRAME         3
#define SFX_TEMPLDLG_VTOPFRAME      3

#define SFX_TEMPLDLG_VBOTFRAME      3
#define SFX_TEMPLDLG_MIDHSPACE      3
#define SFX_TEMPLDLG_MIDVSPACE      3
#define SFX_TEMPLDLG_FILTERHEIGHT   100

static sal_uInt16 nLastItemId = USHRT_MAX;

// filter box has maximum 14 entries visible
#define MAX_FILTER_ENTRIES          14



TYPEINIT0(SfxCommonTemplateDialog_Impl);
TYPEINIT1(SfxTemplateDialog_Impl,SfxCommonTemplateDialog_Impl);


class SfxCommonTemplateDialog_Impl::DeletionWatcher : private boost::noncopyable
{
    typedef void (DeletionWatcher::* bool_type)();

public:
    explicit DeletionWatcher(SfxCommonTemplateDialog_Impl& rDialog)
        : m_pDialog(&rDialog)
        , m_pPrevious(m_pDialog->impl_setDeletionWatcher(this))
    {
    }

    ~DeletionWatcher()
    {
        if (m_pDialog)
            m_pDialog->impl_setDeletionWatcher(m_pPrevious);
    }

    // Signal that the dialog was deleted
    void signal()
    {
        m_pDialog = 0;
        if (m_pPrevious)
            m_pPrevious->signal();
    }

    // Return true if the dialog was deleted
    operator bool_type() const
    {
        return m_pDialog ? 0 : &DeletionWatcher::signal;
    }

private:
    SfxCommonTemplateDialog_Impl* m_pDialog;
    DeletionWatcher *const m_pPrevious; /// let's add more epicycles!
};

void DropListBox_Impl::MouseButtonDown( const MouseEvent& rMEvt )
{
    nModifier = rMEvt.GetModifier();

    bool bHitEmptySpace = ( NULL == GetEntry( rMEvt.GetPosPixel(), true ) );
    if( bHitEmptySpace && ( rMEvt.GetClicks() == 2 ) && rMEvt.IsMod1() )
        Control::MouseButtonDown( rMEvt );
    else
        SvTreeListBox::MouseButtonDown( rMEvt );
}

sal_Int8 DropListBox_Impl::AcceptDrop( const AcceptDropEvent& rEvt )

/*  [Description: ]
    Drop is enabled as long as it is allowed to create a new style by example, i.e. to
    create a style out of the current selection.
*/

{
    if ( IsDropFormatSupported( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) )
    {
        // special case: page styles are allowed to create new styles by example
        // but not allowed to be created by drag and drop
        if (pDialog->GetActualFamily() == SFX_STYLE_FAMILY_PAGE ||
                pDialog->bNewByExampleDisabled)
            return DND_ACTION_NONE;
        else
            return DND_ACTION_COPY;
    }
    return SvTreeListBox::AcceptDrop( rEvt );
}



sal_Int8 DropListBox_Impl::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
    sal_Int8 nRet = DND_ACTION_NONE;
    SfxObjectShell* pDocShell = pDialog->GetObjectShell();
    TransferableDataHelper aHelper( rEvt.maDropEvent.Transferable );
    sal_uInt32 nFormatCount = aHelper.GetFormatCount();
    if ( pDocShell )
    {
        bool bFormatFound = false;

        for ( sal_uInt32 i = 0; i < nFormatCount; ++i )
        {
            SotFormatStringId nId = aHelper.GetFormat(i);
            TransferableObjectDescriptor aDesc;

            if ( aHelper.GetTransferableObjectDescriptor( nId, aDesc ) )
            {
                if ( aDesc.maClassName == pDocShell->GetFactory().GetClassId() )
                {
                    PostUserEvent( LINK( this, DropListBox_Impl, OnAsyncExecuteDrop ), 0 );

                    bFormatFound = true;
                    nRet =  rEvt.mnAction;
                    break;
                }
            }
        }

        if ( !bFormatFound )
            return SvTreeListBox::ExecuteDrop( rEvt );
    }

    return nRet;
}


IMPL_LINK_NOARG(DropListBox_Impl, OnAsyncExecuteDrop)
{
    pDialog->ActionSelect( SID_STYLE_NEW_BY_EXAMPLE );
    return 0;
}

bool DropListBox_Impl::Notify( NotifyEvent& rNEvt )
{
    bool nRet = false;
    if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
    {
        const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
        if(!rKeyCode.GetModifier())
        {
            if( pDialog->bCanDel && KEY_DELETE == rKeyCode.GetCode())
            {
                pDialog->DeleteHdl( NULL );
                nRet =  true;
            }
            else if( KEY_RETURN == rKeyCode.GetCode())
            {
                GetDoubleClickHdl().Call(this);
                nRet = true;
            }
        }
    }
    if(!nRet)
        nRet = SvTreeListBox::Notify( rNEvt );
    return nRet;
}





SfxActionListBox::SfxActionListBox
(
    SfxCommonTemplateDialog_Impl* pParent,
    WinBits nWinBits
)

/*  [Description]

    ListBox class that starts a PopupMenu (designer specific) in the
    command handler.
*/

:       DropListBox_Impl(pParent->GetWindow(), nWinBits, pParent)

{
    EnableContextMenuHandling();
}



PopupMenu* SfxActionListBox::CreateContextMenu( void )
{

    if( !( GetSelectionCount() > 0 ) )
    {
        pDialog->EnableEdit( false );
        pDialog->EnableDel( false );
    }
    return pDialog->CreateContextMenu();
}


//===== SfxTemplatePanelControl ===============================================
SfxTemplatePanelControl::SfxTemplatePanelControl (
    SfxBindings* pBindings,
    vcl::Window* pParentWindow)
    : DockingWindow(pParentWindow, SfxResId(DLG_STYLE_DESIGNER) ),
      pImpl(new SfxTemplateDialog_Impl(pBindings, this)),
      mpBindings(pBindings)
{
    OSL_ASSERT(mpBindings!=NULL);

    pImpl->updateNonFamilyImages();

    SetStyle(GetStyle() & ~WB_DOCKABLE);
}




SfxTemplatePanelControl::~SfxTemplatePanelControl (void)
{
    delete pImpl;
}




void SfxTemplatePanelControl::DataChanged( const DataChangedEvent& _rDCEvt )
{
    if ( ( DataChangedEventType::SETTINGS == _rDCEvt.GetType() ) &&
         ( AllSettingsFlags::STYLE & _rDCEvt.GetFlags() ) )
    {
        pImpl->updateFamilyImages();
        pImpl->updateNonFamilyImages();
    }

    DockingWindow::DataChanged( _rDCEvt );
}




void SfxTemplatePanelControl::Update()
{
    pImpl->Update();
}




void SfxTemplatePanelControl::Resize()
{
    if(pImpl)
        pImpl->Resize();
    DockingWindow::Resize();
}


void SfxTemplatePanelControl::FreeResource (void)
{
    DockingWindow::FreeResource();
}


SfxChildAlignment SfxTemplatePanelControl::CheckAlignment(SfxChildAlignment eActAlign,SfxChildAlignment eAlign)
{
    switch (eAlign)
    {
        case SFX_ALIGN_TOP:
        case SFX_ALIGN_HIGHESTTOP:
        case SFX_ALIGN_LOWESTTOP:
        case SFX_ALIGN_BOTTOM:
        case SFX_ALIGN_LOWESTBOTTOM:
        case SFX_ALIGN_HIGHESTBOTTOM:
            return eActAlign;

        case SFX_ALIGN_LEFT:
        case SFX_ALIGN_RIGHT:
        case SFX_ALIGN_FIRSTLEFT:
        case SFX_ALIGN_LASTLEFT:
        case SFX_ALIGN_FIRSTRIGHT:
        case SFX_ALIGN_LASTRIGHT:
            return eAlign;

        default:
            return eAlign;
    }
}


void SfxTemplatePanelControl::StateChanged( StateChangedType nStateChange )
{
    if ( nStateChange == StateChangedType::INITSHOW )
    {
        SfxViewFrame *pFrame = mpBindings->GetDispatcher_Impl()->GetFrame();
        vcl::Window* pEditWin = pFrame->GetViewShell()->GetWindow();

        Size aSize = pEditWin->GetSizePixel();
        Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
        aPoint = GetParent()->ScreenToOutputPixel( aPoint );
        Size aWinSize = GetSizePixel();
        aPoint.X() += aSize.Width() - aWinSize.Width() - 20;
        aPoint.Y() += aSize.Height() / 2 - aWinSize.Height() / 2;
        //      SetFloatingPos( aPoint );
    }

    DockingWindow::StateChanged( nStateChange );
}



void StyleTreeListBox_Impl::MakeExpanded_Impl(ExpandedEntries_t& rEntries) const
{
    SvTreeListEntry *pEntry;
    for(pEntry=(SvTreeListEntry*)FirstVisible();pEntry;pEntry=(SvTreeListEntry*)NextVisible(pEntry))
    {
        if(IsExpanded(pEntry))
        {
            rEntries.push_back(GetEntryText(pEntry));
        }
    }
}

PopupMenu* StyleTreeListBox_Impl::CreateContextMenu()
{
    return pDialog->CreateContextMenu();
}

bool StyleTreeListBox_Impl::DoubleClickHdl()

/*  [Description]

    DoubleClick-Handler; calls the link.
    SV virtual method.
*/
{
    aDoubleClickLink.Call(this);
    return false;
}



void StyleTreeListBox_Impl::Command( const CommandEvent& rCEvt )

/*  [Description]

    Command Handler; this executes a PopupMenu (designer-specific)
    SV virtual method.
*/
{
    SvTreeListBox::Command(rCEvt);
}



bool StyleTreeListBox_Impl::Notify( NotifyEvent& rNEvt )
{
    // handle <RETURN> as double click

    bool nRet = false;
    if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
    {
        const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
        if ( !rKeyCode.GetModifier() && KEY_RETURN == rKeyCode.GetCode() )
        {
            aDoubleClickLink.Call( this );
            nRet = true;
        }
    }

    if ( !nRet )
        nRet = DropListBox_Impl::Notify( rNEvt );

    return nRet;
}



TriState StyleTreeListBox_Impl::NotifyMoving(SvTreeListEntry*  pTarget,
                                         SvTreeListEntry*  pEntry,
                                         SvTreeListEntry*& rpNewParent,
                                         sal_uIntPtr& lPos)
/*  [Description]

    NotifyMoving Handler; This leads via a link on the event to the dialog.
    SV virtual method.
*/
{
    if(!pTarget || !pEntry)
        return TRISTATE_FALSE;
    aParent = GetEntryText(pTarget);
    aStyle  = GetEntryText(pEntry);
    const bool bRet = (bool)aDropLink.Call(this);
    rpNewParent = pTarget;
    lPos=0;
    IntlWrapper aIntlWrapper( Application::GetSettings().GetLanguageTag() );
    const CollatorWrapper* pCollator = aIntlWrapper.getCaseCollator();
    for(SvTreeListEntry *pTmpEntry=FirstChild(pTarget);
        pTmpEntry && pCollator->compareString(
            GetEntryText(pTmpEntry),GetEntryText(pEntry)) < 0;
        pTmpEntry=NextSibling(pTmpEntry),lPos++) ;

    return bRet ? TRISTATE_INDET : TRISTATE_FALSE;
}

bool  StyleTreeListBox_Impl::ExpandingHdl()

/*  [Description]

    ExpandingHdl Handler; the current entry is noticed.
    SV virtual method.

    [Cross-reference]
    <StyleTreeListBox_Impl::ExpandedHdl()>
*/
{
    pCurEntry = GetCurEntry();
    return true;
}



void  StyleTreeListBox_Impl::ExpandedHdl()

/*  [Description]

    ExpandedHdl Handler;
    SV virtual method.

    [Cross-reference]
    <StyleTreeListBox_Impl::ExpandingHdl()>
*/

{
    SvTreeListEntry *pEntry = GetHdlEntry();
    if(!IsExpanded(pEntry) && pCurEntry != GetCurEntry())
        SelectAll( false );
    pCurEntry = 0;
}



StyleTreeListBox_Impl::StyleTreeListBox_Impl(
    SfxCommonTemplateDialog_Impl* pParent, WinBits nWinStyle) :
    DropListBox_Impl(pParent->GetWindow(), nWinStyle, pParent),
    pCurEntry(0)

/*  [Description]

    Constructor StyleTreeListBox_Impl
*/
{
    EnableContextMenuHandling();
}

/*  [Description]

    Internal structure for the establishment of the hierarchical view
*/
class StyleTree_Impl;
typedef std::vector<StyleTree_Impl*> StyleTreeArr_Impl;

class StyleTree_Impl
{
private:
    OUString aName;
    OUString aParent;
    StyleTreeArr_Impl pChildren;

public:

    bool HasParent() const { return !aParent.isEmpty(); }

    StyleTree_Impl(const OUString &rName, const OUString &rParent):
        aName(rName), aParent(rParent), pChildren(0) {}
    ~StyleTree_Impl();
    void Put(StyleTree_Impl* pIns, sal_uIntPtr lPos=ULONG_MAX);
    sal_uIntPtr Count();

    OUString getName() { return aName; }
    OUString getParent() { return aParent; }
    StyleTree_Impl *operator[](size_t idx) const { return pChildren[idx]; }
};

sal_uIntPtr StyleTree_Impl::Count()
{
    return pChildren.size();
}

StyleTree_Impl::~StyleTree_Impl()
{
    for(StyleTreeArr_Impl::const_iterator it = pChildren.begin(); it != pChildren.end(); ++it)
        delete *it;
}

void StyleTree_Impl::Put(StyleTree_Impl* pIns, sal_uIntPtr lPos)
{
    if ( ULONG_MAX == lPos )
        pChildren.push_back( pIns );
    else
        pChildren.insert( pChildren.begin() + (sal_uInt16)lPos, pIns );
}



StyleTreeArr_Impl &MakeTree_Impl(StyleTreeArr_Impl &rArr)
{
    const sal_uInt16 nCount = rArr.size();

    comphelper::string::NaturalStringSorter aSorter(
        ::comphelper::getProcessComponentContext(),
        Application::GetSettings().GetLanguageTag().getLocale());

    // Arrange all under their Parents
    sal_uInt16 i;
    for(i = 0; i < nCount; ++i)
    {
        StyleTree_Impl* pEntry = rArr[i];
        if(pEntry->HasParent())
        {
            for(sal_uInt16 j = 0; j < nCount; ++j)
            {
                StyleTree_Impl* pCmp = rArr[j];
                if(pCmp->getName() == pEntry->getParent())
                {
                    // Paste initial filter
                    sal_uInt16 nPos;
                    for( nPos = 0 ; nPos < pCmp->Count() &&
                             aSorter.compare((*pCmp)[nPos]->getName(), pEntry->getName()) < 0 ; nPos++)
                    {};
                    pCmp->Put(pEntry,nPos);
                    break;
                }
            }
        }
    }

    for(i = 0; i < rArr.size(); )
    {
        if(rArr[i]->HasParent())
            rArr.erase(rArr.begin() + i);
        else
            ++i;
    }
    return rArr;
}




inline bool IsExpanded_Impl( const ExpandedEntries_t& rEntries,
                             const OUString &rStr)
{
    for (size_t n = 0; n < rEntries.size(); ++n)
    {
        if (rEntries[n] == rStr)
            return true;
    }
    return false;
}



SvTreeListEntry* FillBox_Impl(SvTreeListBox *pBox,
                                 StyleTree_Impl* pEntry,
                                 const ExpandedEntries_t& rEntries,
                                 SvTreeListEntry* pParent = 0)
{
    SvTreeListEntry* pNewEntry = pBox->InsertEntry(pEntry->getName(), pParent);
    for(sal_uInt16 i = 0; i < pEntry->Count(); ++i)
        FillBox_Impl(pBox, (*pEntry)[i], rEntries, pNewEntry);
    return pNewEntry;
}


// Constructor

SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl( SfxBindings* pB, vcl::Window* pW, bool ) :
    mbIgnoreSelect( false ),
    pBindings               ( pB ),
    pWindow                 ( pW ),
    pModule                 ( NULL ),
    pIdle                   ( NULL ),
    m_pStyleFamiliesId      ( NULL ),
    pStyleFamilies          ( NULL ),
    pStyleSheetPool         ( NULL ),
    pTreeBox                ( NULL ),
    pCurObjShell            ( NULL ),
    xModuleManager          ( frame::ModuleManager::create(::comphelper::getProcessComponentContext()) ),
    m_pDeletionWatcher      ( NULL ),

    aFmtLb                  ( this, WB_BORDER | WB_TABSTOP | WB_SORT | WB_QUICK_SEARCH ),
    aFilterLb               ( pW, WB_BORDER | WB_DROPDOWN | WB_TABSTOP ),

    nActFamily              ( 0xffff ),
    nActFilter              ( 0 ),
    nAppFilter              ( 0 ),

    bDontUpdate             ( false ),
    bIsWater                ( false ),
    bEnabled                ( true ),
    bUpdate                 ( false ),
    bUpdateFamily           ( false ),
    bCanEdit                ( false ),
    bCanDel                 ( false ),
    bCanNew                 ( true ),
    bCanHide                ( true ),
    bCanShow                ( false ),
    bWaterDisabled          ( false ),
    bNewByExampleDisabled   ( false ),
    bUpdateByExampleDisabled( false ),
    bTreeDrag               ( true ),
    bHierarchical           ( false ),
    m_bWantHierarchical     ( false ),
    bBindingUpdate          ( true )
{
    aFmtLb.SetAccessibleName(SfxResId(STR_STYLE_ELEMTLIST).toString());
    aFmtLb.SetHelpId( HID_TEMPLATE_FMT );
    aFilterLb.SetHelpId( HID_TEMPLATE_FILTER );
    aFmtLb.SetStyle( aFmtLb.GetStyle() | WB_SORT | WB_HIDESELECTION );
    vcl::Font aFont = aFmtLb.GetFont();
    aFont.SetWeight( WEIGHT_NORMAL );
    aFmtLb.SetFont( aFont );

    memset(pBoundItems, 0, sizeof(pBoundItems));
    memset(pFamilyState, 0, sizeof(pFamilyState));
}

sal_uInt16 SfxCommonTemplateDialog_Impl::StyleNrToInfoOffset(sal_uInt16 nId)
{
    const SfxStyleFamilyItem *pItem = pStyleFamilies->at( nId );
    return SfxTemplate::SfxFamilyIdToNId(pItem->GetFamily())-1;
}

void SfxTemplateDialog_Impl::EnableEdit(bool bEnable)
{
    SfxCommonTemplateDialog_Impl::EnableEdit( bEnable );
    if( !bEnable || !bUpdateByExampleDisabled )
        EnableItem( SID_STYLE_UPDATE_BY_EXAMPLE, bEnable);
}



void SfxCommonTemplateDialog_Impl::ReadResource()
{
    // Read global user resource
    for(sal_uInt16 i = 0; i < MAX_FAMILIES; ++i)
        pFamilyState[i] = 0;

    SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
    pCurObjShell = pViewFrame->GetObjectShell();
    pModule = pCurObjShell ? pCurObjShell->GetModule() : NULL;
    ResMgr* pMgr = pModule ? pModule->GetResMgr() : NULL;
    if (pMgr)
    {
        ResId aFamId( DLG_STYLE_DESIGNER, *pMgr );
        aFamId.SetRT(RSC_SFX_STYLE_FAMILIES);
        m_pStyleFamiliesId = new ResId( aFamId.GetId(), *pMgr );
        m_pStyleFamiliesId->SetRT(RSC_SFX_STYLE_FAMILIES);
        if (pMgr->IsAvailable(aFamId))
            pStyleFamilies = new SfxStyleFamilies( aFamId );
    }
    if (!pStyleFamilies)
        pStyleFamilies = new SfxStyleFamilies;

    nActFilter = pCurObjShell ? static_cast< sal_uInt16 >( LoadFactoryStyleFilter( pCurObjShell ) ) : SFXSTYLEBIT_ALL;
    if ( pCurObjShell && SFXSTYLEBIT_ALL == nActFilter )
        nActFilter = pCurObjShell->GetAutoStyleFilterIndex();

    // Paste in the toolbox
    // reverse order, since always inserted at the head
    size_t nCount = pStyleFamilies->size();

    pBindings->ENTERREGISTRATIONS();

    size_t i;
    for(i = 0; i < nCount; ++i)
    {
        sal_uInt16 nSlot = 0;
        switch( (sal_uInt16)pStyleFamilies->at( i )->GetFamily() )
        {
            case SFX_STYLE_FAMILY_CHAR: nSlot = SID_STYLE_FAMILY1; break;
            case SFX_STYLE_FAMILY_PARA: nSlot = SID_STYLE_FAMILY2; break;
            case SFX_STYLE_FAMILY_FRAME:nSlot = SID_STYLE_FAMILY3; break;
            case SFX_STYLE_FAMILY_PAGE: nSlot = SID_STYLE_FAMILY4; break;
            case SFX_STYLE_FAMILY_PSEUDO: nSlot = SID_STYLE_FAMILY5; break;
            default: OSL_FAIL("unknown StyleFamily"); break;
        }
        pBoundItems[i] =
            new SfxTemplateControllerItem(nSlot, *this, *pBindings);
    }
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_WATERCAN, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_NEW_BY_EXAMPLE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_UPDATE_BY_EXAMPLE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_NEW, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_DRAGHIERARCHIE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_EDIT, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_DELETE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_FAMILY, *this, *pBindings);
    pBindings->LEAVEREGISTRATIONS();

    for(; i < COUNT_BOUND_FUNC; ++i)
        pBoundItems[i] = 0;

    StartListening(*pBindings);

// Insert in the reverse order of occurrence in the Style Families. This is for
// the toolbar of the designer. The list box of the catalog respects the
// correct order by itself.

// Sequences: the order of Resource = the order of Toolbar for example list box.
// Order of ascending SIDs: Low SIDs are displayed first when templates of
// several families are active.

    // in the Writer the UpdateStyleByExample Toolbox button is removed and
    // the NewStyle button gets a PopupMenu
    if(nCount > 4)
        ReplaceUpdateButtonByMenu();

    for( ; nCount--; )
    {
        const SfxStyleFamilyItem *pItem = pStyleFamilies->at( nCount );
        sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId( pItem->GetFamily() );
        InsertFamilyItem( nId, pItem );
    }

    LoadedFamilies();

    sal_uInt16 nStart = SID_STYLE_FAMILY1;
    sal_uInt16 nEnd = SID_STYLE_FAMILY4;

    for ( i = nStart; i <= nEnd; i++ )
        pBindings->Update(i);
}

void SfxCommonTemplateDialog_Impl::ClearResource()
{
    ClearFamilyList();
    impl_clear();
}

void SfxCommonTemplateDialog_Impl::impl_clear()
{
    DELETEX(SfxStyleFamilies, pStyleFamilies);
    sal_uInt16 i;<commit_msg>coverity#1266518 Use after free<commit_after>/* -*- 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 <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>

#include <vcl/menu.hxx>
#include <vcl/settings.hxx>
#include <svl/intitem.hxx>
#include <svl/stritem.hxx>
#include <svl/style.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <unotools/intlwrapper.hxx>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/theUICommandDescription.hpp>

#include <sfx2/sfxhelp.hxx>
#include <sfx2/app.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/templdlg.hxx>
#include "templdgi.hxx"
#include "tplcitem.hxx"
#include "sfxtypes.hxx"
#include <sfx2/styfitem.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/newstyle.hxx>
#include <sfx2/tplpitem.hxx>
#include <sfx2/sfxresid.hxx>

#include "templdlg.hrc"
#include <sfx2/sfx.hrc>
#include "dialog.hrc"
#include "arrdecl.hxx"
#include <sfx2/docfilt.hxx>
#include <sfx2/docfac.hxx>
#include <sfx2/doctempl.hxx>
#include <sfx2/module.hxx>
#include <sfx2/imgmgr.hxx>
#include "helpid.hrc"
#include "appdata.hxx"
#include <sfx2/viewfrm.hxx>

#include <comphelper/string.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::uno;


// Window is now created dynamically. So here margins, etc.

#define SFX_TEMPLDLG_HFRAME         3
#define SFX_TEMPLDLG_VTOPFRAME      3

#define SFX_TEMPLDLG_VBOTFRAME      3
#define SFX_TEMPLDLG_MIDHSPACE      3
#define SFX_TEMPLDLG_MIDVSPACE      3
#define SFX_TEMPLDLG_FILTERHEIGHT   100

static sal_uInt16 nLastItemId = USHRT_MAX;

// filter box has maximum 14 entries visible
#define MAX_FILTER_ENTRIES          14



TYPEINIT0(SfxCommonTemplateDialog_Impl);
TYPEINIT1(SfxTemplateDialog_Impl,SfxCommonTemplateDialog_Impl);


class SfxCommonTemplateDialog_Impl::DeletionWatcher : private boost::noncopyable
{
    typedef void (DeletionWatcher::* bool_type)();

public:
    explicit DeletionWatcher(SfxCommonTemplateDialog_Impl& rDialog)
        : m_pDialog(&rDialog)
        , m_pPrevious(m_pDialog->impl_setDeletionWatcher(this))
    {
    }

    ~DeletionWatcher()
    {
        if (m_pDialog)
            m_pDialog->impl_setDeletionWatcher(m_pPrevious);
    }

    // Signal that the dialog was deleted
    void signal()
    {
        m_pDialog = 0;
        if (m_pPrevious)
            m_pPrevious->signal();
    }

    // Return true if the dialog was deleted
    operator bool_type() const
    {
        return m_pDialog ? 0 : &DeletionWatcher::signal;
    }

private:
    SfxCommonTemplateDialog_Impl* m_pDialog;
    DeletionWatcher *const m_pPrevious; /// let's add more epicycles!
};

void DropListBox_Impl::MouseButtonDown( const MouseEvent& rMEvt )
{
    nModifier = rMEvt.GetModifier();

    bool bHitEmptySpace = ( NULL == GetEntry( rMEvt.GetPosPixel(), true ) );
    if( bHitEmptySpace && ( rMEvt.GetClicks() == 2 ) && rMEvt.IsMod1() )
        Control::MouseButtonDown( rMEvt );
    else
        SvTreeListBox::MouseButtonDown( rMEvt );
}

sal_Int8 DropListBox_Impl::AcceptDrop( const AcceptDropEvent& rEvt )

/*  [Description: ]
    Drop is enabled as long as it is allowed to create a new style by example, i.e. to
    create a style out of the current selection.
*/

{
    if ( IsDropFormatSupported( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) )
    {
        // special case: page styles are allowed to create new styles by example
        // but not allowed to be created by drag and drop
        if (pDialog->GetActualFamily() == SFX_STYLE_FAMILY_PAGE ||
                pDialog->bNewByExampleDisabled)
            return DND_ACTION_NONE;
        else
            return DND_ACTION_COPY;
    }
    return SvTreeListBox::AcceptDrop( rEvt );
}



sal_Int8 DropListBox_Impl::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
    sal_Int8 nRet = DND_ACTION_NONE;
    SfxObjectShell* pDocShell = pDialog->GetObjectShell();
    TransferableDataHelper aHelper( rEvt.maDropEvent.Transferable );
    sal_uInt32 nFormatCount = aHelper.GetFormatCount();
    if ( pDocShell )
    {
        bool bFormatFound = false;

        for ( sal_uInt32 i = 0; i < nFormatCount; ++i )
        {
            SotFormatStringId nId = aHelper.GetFormat(i);
            TransferableObjectDescriptor aDesc;

            if ( aHelper.GetTransferableObjectDescriptor( nId, aDesc ) )
            {
                if ( aDesc.maClassName == pDocShell->GetFactory().GetClassId() )
                {
                    PostUserEvent( LINK( this, DropListBox_Impl, OnAsyncExecuteDrop ), 0 );

                    bFormatFound = true;
                    nRet =  rEvt.mnAction;
                    break;
                }
            }
        }

        if ( !bFormatFound )
            return SvTreeListBox::ExecuteDrop( rEvt );
    }

    return nRet;
}


IMPL_LINK_NOARG(DropListBox_Impl, OnAsyncExecuteDrop)
{
    pDialog->ActionSelect( SID_STYLE_NEW_BY_EXAMPLE );
    return 0;
}

bool DropListBox_Impl::Notify( NotifyEvent& rNEvt )
{
    bool nRet = false;
    if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
    {
        const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
        if(!rKeyCode.GetModifier())
        {
            if( pDialog->bCanDel && KEY_DELETE == rKeyCode.GetCode())
            {
                pDialog->DeleteHdl( NULL );
                nRet =  true;
            }
            else if( KEY_RETURN == rKeyCode.GetCode())
            {
                GetDoubleClickHdl().Call(this);
                nRet = true;
            }
        }
    }
    if(!nRet)
        nRet = SvTreeListBox::Notify( rNEvt );
    return nRet;
}





SfxActionListBox::SfxActionListBox
(
    SfxCommonTemplateDialog_Impl* pParent,
    WinBits nWinBits
)

/*  [Description]

    ListBox class that starts a PopupMenu (designer specific) in the
    command handler.
*/

:       DropListBox_Impl(pParent->GetWindow(), nWinBits, pParent)

{
    EnableContextMenuHandling();
}



PopupMenu* SfxActionListBox::CreateContextMenu( void )
{

    if( !( GetSelectionCount() > 0 ) )
    {
        pDialog->EnableEdit( false );
        pDialog->EnableDel( false );
    }
    return pDialog->CreateContextMenu();
}


//===== SfxTemplatePanelControl ===============================================
SfxTemplatePanelControl::SfxTemplatePanelControl (
    SfxBindings* pBindings,
    vcl::Window* pParentWindow)
    : DockingWindow(pParentWindow, SfxResId(DLG_STYLE_DESIGNER) ),
      pImpl(new SfxTemplateDialog_Impl(pBindings, this)),
      mpBindings(pBindings)
{
    OSL_ASSERT(mpBindings!=NULL);

    pImpl->updateNonFamilyImages();

    SetStyle(GetStyle() & ~WB_DOCKABLE);
}




SfxTemplatePanelControl::~SfxTemplatePanelControl (void)
{
    delete pImpl;
}




void SfxTemplatePanelControl::DataChanged( const DataChangedEvent& _rDCEvt )
{
    if ( ( DataChangedEventType::SETTINGS == _rDCEvt.GetType() ) &&
         ( AllSettingsFlags::STYLE & _rDCEvt.GetFlags() ) )
    {
        pImpl->updateFamilyImages();
        pImpl->updateNonFamilyImages();
    }

    DockingWindow::DataChanged( _rDCEvt );
}




void SfxTemplatePanelControl::Update()
{
    pImpl->Update();
}




void SfxTemplatePanelControl::Resize()
{
    if(pImpl)
        pImpl->Resize();
    DockingWindow::Resize();
}


void SfxTemplatePanelControl::FreeResource (void)
{
    DockingWindow::FreeResource();
}


SfxChildAlignment SfxTemplatePanelControl::CheckAlignment(SfxChildAlignment eActAlign,SfxChildAlignment eAlign)
{
    switch (eAlign)
    {
        case SFX_ALIGN_TOP:
        case SFX_ALIGN_HIGHESTTOP:
        case SFX_ALIGN_LOWESTTOP:
        case SFX_ALIGN_BOTTOM:
        case SFX_ALIGN_LOWESTBOTTOM:
        case SFX_ALIGN_HIGHESTBOTTOM:
            return eActAlign;

        case SFX_ALIGN_LEFT:
        case SFX_ALIGN_RIGHT:
        case SFX_ALIGN_FIRSTLEFT:
        case SFX_ALIGN_LASTLEFT:
        case SFX_ALIGN_FIRSTRIGHT:
        case SFX_ALIGN_LASTRIGHT:
            return eAlign;

        default:
            return eAlign;
    }
}


void SfxTemplatePanelControl::StateChanged( StateChangedType nStateChange )
{
    if ( nStateChange == StateChangedType::INITSHOW )
    {
        SfxViewFrame *pFrame = mpBindings->GetDispatcher_Impl()->GetFrame();
        vcl::Window* pEditWin = pFrame->GetViewShell()->GetWindow();

        Size aSize = pEditWin->GetSizePixel();
        Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() );
        aPoint = GetParent()->ScreenToOutputPixel( aPoint );
        Size aWinSize = GetSizePixel();
        aPoint.X() += aSize.Width() - aWinSize.Width() - 20;
        aPoint.Y() += aSize.Height() / 2 - aWinSize.Height() / 2;
        //      SetFloatingPos( aPoint );
    }

    DockingWindow::StateChanged( nStateChange );
}



void StyleTreeListBox_Impl::MakeExpanded_Impl(ExpandedEntries_t& rEntries) const
{
    SvTreeListEntry *pEntry;
    for(pEntry=(SvTreeListEntry*)FirstVisible();pEntry;pEntry=(SvTreeListEntry*)NextVisible(pEntry))
    {
        if(IsExpanded(pEntry))
        {
            rEntries.push_back(GetEntryText(pEntry));
        }
    }
}

PopupMenu* StyleTreeListBox_Impl::CreateContextMenu()
{
    return pDialog->CreateContextMenu();
}

bool StyleTreeListBox_Impl::DoubleClickHdl()

/*  [Description]

    DoubleClick-Handler; calls the link.
    SV virtual method.
*/
{
    aDoubleClickLink.Call(this);
    return false;
}



void StyleTreeListBox_Impl::Command( const CommandEvent& rCEvt )

/*  [Description]

    Command Handler; this executes a PopupMenu (designer-specific)
    SV virtual method.
*/
{
    SvTreeListBox::Command(rCEvt);
}



bool StyleTreeListBox_Impl::Notify( NotifyEvent& rNEvt )
{
    // handle <RETURN> as double click

    bool nRet = false;
    if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
    {
        const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
        if ( !rKeyCode.GetModifier() && KEY_RETURN == rKeyCode.GetCode() )
        {
            aDoubleClickLink.Call( this );
            nRet = true;
        }
    }

    if ( !nRet )
        nRet = DropListBox_Impl::Notify( rNEvt );

    return nRet;
}



TriState StyleTreeListBox_Impl::NotifyMoving(SvTreeListEntry*  pTarget,
                                         SvTreeListEntry*  pEntry,
                                         SvTreeListEntry*& rpNewParent,
                                         sal_uIntPtr& lPos)
/*  [Description]

    NotifyMoving Handler; This leads via a link on the event to the dialog.
    SV virtual method.
*/
{
    if(!pTarget || !pEntry)
        return TRISTATE_FALSE;
    aParent = GetEntryText(pTarget);
    aStyle  = GetEntryText(pEntry);
    const bool bRet = (bool)aDropLink.Call(this);
    rpNewParent = pTarget;
    lPos=0;
    IntlWrapper aIntlWrapper( Application::GetSettings().GetLanguageTag() );
    const CollatorWrapper* pCollator = aIntlWrapper.getCaseCollator();
    for(SvTreeListEntry *pTmpEntry=FirstChild(pTarget);
        pTmpEntry && pCollator->compareString(
            GetEntryText(pTmpEntry),GetEntryText(pEntry)) < 0;
        pTmpEntry=NextSibling(pTmpEntry),lPos++) ;

    return bRet ? TRISTATE_INDET : TRISTATE_FALSE;
}

bool  StyleTreeListBox_Impl::ExpandingHdl()

/*  [Description]

    ExpandingHdl Handler; the current entry is noticed.
    SV virtual method.

    [Cross-reference]
    <StyleTreeListBox_Impl::ExpandedHdl()>
*/
{
    pCurEntry = GetCurEntry();
    return true;
}



void  StyleTreeListBox_Impl::ExpandedHdl()

/*  [Description]

    ExpandedHdl Handler;
    SV virtual method.

    [Cross-reference]
    <StyleTreeListBox_Impl::ExpandingHdl()>
*/

{
    SvTreeListEntry *pEntry = GetHdlEntry();
    if(!IsExpanded(pEntry) && pCurEntry != GetCurEntry())
        SelectAll( false );
    pCurEntry = 0;
}



StyleTreeListBox_Impl::StyleTreeListBox_Impl(
    SfxCommonTemplateDialog_Impl* pParent, WinBits nWinStyle) :
    DropListBox_Impl(pParent->GetWindow(), nWinStyle, pParent),
    pCurEntry(0)

/*  [Description]

    Constructor StyleTreeListBox_Impl
*/
{
    EnableContextMenuHandling();
}

/*  [Description]

    Internal structure for the establishment of the hierarchical view
*/
class StyleTree_Impl;
typedef std::vector<StyleTree_Impl*> StyleTreeArr_Impl;

class StyleTree_Impl
{
private:
    OUString aName;
    OUString aParent;
    StyleTreeArr_Impl pChildren;

public:

    bool HasParent() const { return !aParent.isEmpty(); }

    StyleTree_Impl(const OUString &rName, const OUString &rParent):
        aName(rName), aParent(rParent), pChildren(0) {}
    ~StyleTree_Impl();
    void Put(StyleTree_Impl* pIns, sal_uIntPtr lPos=ULONG_MAX);
    sal_uIntPtr Count();

    OUString getName() { return aName; }
    OUString getParent() { return aParent; }
    StyleTree_Impl *operator[](size_t idx) const { return pChildren[idx]; }
};

sal_uIntPtr StyleTree_Impl::Count()
{
    return pChildren.size();
}

StyleTree_Impl::~StyleTree_Impl()
{
    for(StyleTreeArr_Impl::const_iterator it = pChildren.begin(); it != pChildren.end(); ++it)
        delete *it;
}

void StyleTree_Impl::Put(StyleTree_Impl* pIns, sal_uIntPtr lPos)
{
    if ( ULONG_MAX == lPos )
        pChildren.push_back( pIns );
    else
        pChildren.insert( pChildren.begin() + (sal_uInt16)lPos, pIns );
}



StyleTreeArr_Impl &MakeTree_Impl(StyleTreeArr_Impl &rArr)
{
    const sal_uInt16 nCount = rArr.size();

    comphelper::string::NaturalStringSorter aSorter(
        ::comphelper::getProcessComponentContext(),
        Application::GetSettings().GetLanguageTag().getLocale());

    // Arrange all under their Parents
    sal_uInt16 i;
    for(i = 0; i < nCount; ++i)
    {
        StyleTree_Impl* pEntry = rArr[i];
        if(pEntry->HasParent())
        {
            for(sal_uInt16 j = 0; j < nCount; ++j)
            {
                StyleTree_Impl* pCmp = rArr[j];
                if(pCmp->getName() == pEntry->getParent())
                {
                    // Paste initial filter
                    sal_uInt16 nPos;
                    for( nPos = 0 ; nPos < pCmp->Count() &&
                             aSorter.compare((*pCmp)[nPos]->getName(), pEntry->getName()) < 0 ; nPos++)
                    {};
                    pCmp->Put(pEntry,nPos);
                    break;
                }
            }
        }
    }

    for(i = 0; i < rArr.size(); )
    {
        if(rArr[i]->HasParent())
            rArr.erase(rArr.begin() + i);
        else
            ++i;
    }
    return rArr;
}




inline bool IsExpanded_Impl( const ExpandedEntries_t& rEntries,
                             const OUString &rStr)
{
    for (size_t n = 0; n < rEntries.size(); ++n)
    {
        if (rEntries[n] == rStr)
            return true;
    }
    return false;
}



SvTreeListEntry* FillBox_Impl(SvTreeListBox *pBox,
                                 StyleTree_Impl* pEntry,
                                 const ExpandedEntries_t& rEntries,
                                 SvTreeListEntry* pParent = 0)
{
    SvTreeListEntry* pNewEntry = pBox->InsertEntry(pEntry->getName(), pParent);
    for(sal_uInt16 i = 0; i < pEntry->Count(); ++i)
        FillBox_Impl(pBox, (*pEntry)[i], rEntries, pNewEntry);
    return pNewEntry;
}


// Constructor

SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl( SfxBindings* pB, vcl::Window* pW, bool ) :
    mbIgnoreSelect( false ),
    pBindings               ( pB ),
    pWindow                 ( pW ),
    pModule                 ( NULL ),
    pIdle                   ( NULL ),
    m_pStyleFamiliesId      ( NULL ),
    pStyleFamilies          ( NULL ),
    pStyleSheetPool         ( NULL ),
    pTreeBox                ( NULL ),
    pCurObjShell            ( NULL ),
    xModuleManager          ( frame::ModuleManager::create(::comphelper::getProcessComponentContext()) ),
    m_pDeletionWatcher      ( NULL ),

    aFmtLb                  ( this, WB_BORDER | WB_TABSTOP | WB_SORT | WB_QUICK_SEARCH ),
    aFilterLb               ( pW, WB_BORDER | WB_DROPDOWN | WB_TABSTOP ),

    nActFamily              ( 0xffff ),
    nActFilter              ( 0 ),
    nAppFilter              ( 0 ),

    bDontUpdate             ( false ),
    bIsWater                ( false ),
    bEnabled                ( true ),
    bUpdate                 ( false ),
    bUpdateFamily           ( false ),
    bCanEdit                ( false ),
    bCanDel                 ( false ),
    bCanNew                 ( true ),
    bCanHide                ( true ),
    bCanShow                ( false ),
    bWaterDisabled          ( false ),
    bNewByExampleDisabled   ( false ),
    bUpdateByExampleDisabled( false ),
    bTreeDrag               ( true ),
    bHierarchical           ( false ),
    m_bWantHierarchical     ( false ),
    bBindingUpdate          ( true )
{
    aFmtLb.SetAccessibleName(SfxResId(STR_STYLE_ELEMTLIST).toString());
    aFmtLb.SetHelpId( HID_TEMPLATE_FMT );
    aFilterLb.SetHelpId( HID_TEMPLATE_FILTER );
    aFmtLb.SetStyle( aFmtLb.GetStyle() | WB_SORT | WB_HIDESELECTION );
    vcl::Font aFont = aFmtLb.GetFont();
    aFont.SetWeight( WEIGHT_NORMAL );
    aFmtLb.SetFont( aFont );

    memset(pBoundItems, 0, sizeof(pBoundItems));
    memset(pFamilyState, 0, sizeof(pFamilyState));
}

sal_uInt16 SfxCommonTemplateDialog_Impl::StyleNrToInfoOffset(sal_uInt16 nId)
{
    const SfxStyleFamilyItem *pItem = pStyleFamilies->at( nId );
    return SfxTemplate::SfxFamilyIdToNId(pItem->GetFamily())-1;
}

void SfxTemplateDialog_Impl::EnableEdit(bool bEnable)
{
    SfxCommonTemplateDialog_Impl::EnableEdit( bEnable );
    if( !bEnable || !bUpdateByExampleDisabled )
        EnableItem( SID_STYLE_UPDATE_BY_EXAMPLE, bEnable);
}



void SfxCommonTemplateDialog_Impl::ReadResource()
{
    // Read global user resource
    for(sal_uInt16 i = 0; i < MAX_FAMILIES; ++i)
        pFamilyState[i] = 0;

    SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame();
    pCurObjShell = pViewFrame->GetObjectShell();
    pModule = pCurObjShell ? pCurObjShell->GetModule() : NULL;
    ResMgr* pMgr = pModule ? pModule->GetResMgr() : NULL;
    if (pMgr)
    {
        ResId aFamId( DLG_STYLE_DESIGNER, *pMgr );
        aFamId.SetRT(RSC_SFX_STYLE_FAMILIES);
        m_pStyleFamiliesId = new ResId( aFamId.GetId(), *pMgr );
        m_pStyleFamiliesId->SetRT(RSC_SFX_STYLE_FAMILIES);
        if (pMgr->IsAvailable(aFamId))
            pStyleFamilies = new SfxStyleFamilies( aFamId );
    }
    if (!pStyleFamilies)
        pStyleFamilies = new SfxStyleFamilies;

    nActFilter = pCurObjShell ? static_cast< sal_uInt16 >( LoadFactoryStyleFilter( pCurObjShell ) ) : SFXSTYLEBIT_ALL;
    if ( pCurObjShell && SFXSTYLEBIT_ALL == nActFilter )
        nActFilter = pCurObjShell->GetAutoStyleFilterIndex();

    // Paste in the toolbox
    // reverse order, since always inserted at the head
    size_t nCount = pStyleFamilies->size();

    pBindings->ENTERREGISTRATIONS();

    size_t i;
    for(i = 0; i < nCount; ++i)
    {
        sal_uInt16 nSlot = 0;
        switch( (sal_uInt16)pStyleFamilies->at( i )->GetFamily() )
        {
            case SFX_STYLE_FAMILY_CHAR: nSlot = SID_STYLE_FAMILY1; break;
            case SFX_STYLE_FAMILY_PARA: nSlot = SID_STYLE_FAMILY2; break;
            case SFX_STYLE_FAMILY_FRAME:nSlot = SID_STYLE_FAMILY3; break;
            case SFX_STYLE_FAMILY_PAGE: nSlot = SID_STYLE_FAMILY4; break;
            case SFX_STYLE_FAMILY_PSEUDO: nSlot = SID_STYLE_FAMILY5; break;
            default: OSL_FAIL("unknown StyleFamily"); break;
        }
        pBoundItems[i] =
            new SfxTemplateControllerItem(nSlot, *this, *pBindings);
    }
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_WATERCAN, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_NEW_BY_EXAMPLE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_UPDATE_BY_EXAMPLE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_NEW, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_DRAGHIERARCHIE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_EDIT, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_DELETE, *this, *pBindings);
    pBoundItems[i++] = new SfxTemplateControllerItem(
        SID_STYLE_FAMILY, *this, *pBindings);
    pBindings->LEAVEREGISTRATIONS();

    for(; i < COUNT_BOUND_FUNC; ++i)
        pBoundItems[i] = 0;

    StartListening(*pBindings);

// Insert in the reverse order of occurrence in the Style Families. This is for
// the toolbar of the designer. The list box of the catalog respects the
// correct order by itself.

// Sequences: the order of Resource = the order of Toolbar for example list box.
// Order of ascending SIDs: Low SIDs are displayed first when templates of
// several families are active.

    // in the Writer the UpdateStyleByExample Toolbox button is removed and
    // the NewStyle button gets a PopupMenu
    if(nCount > 4)
        ReplaceUpdateButtonByMenu();

    for( ; nCount--; )
    {
        const SfxStyleFamilyItem *pItem = pStyleFamilies->at( nCount );
        sal_uInt16 nId = SfxTemplate::SfxFamilyIdToNId( pItem->GetFamily() );
        InsertFamilyItem( nId, pItem );
    }

    LoadedFamilies();

    sal_uInt16 nStart = SID_STYLE_FAMILY1;
    sal_uInt16 nEnd = SID_STYLE_FAMILY4;

    for ( i = nStart; i <= nEnd; i++ )
        pBindings->Update(i);
}

void SfxCommonTemplateDialog_Impl::ClearResource()
{
    ClearFamilyList();
    impl_clear();
}

void SfxCommonTemplateDialog_Impl::impl_clear()
{
    delete pStyleFamilies;
    pStyleFamilies = NULL;
    sal_uInt16 i;
{'fraction_non_alphanumeric': 0.10996774688987866, 'fraction_numerical': 0.005726572613379556, 'mean_word_length': 2.797217362326085, 'pattern_counts': {'":': 0, '<': 107, '<?xml version=': 0, '>': 207, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3807229', 'n_tokens_mistral': 15605, 'n_tokens_neox': 15025, 'n_words': 2978}