    /* -*- 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 <svl/stritem.hxx>
    #include <sfx2/fcontnr.hxx>
    #include <sfx2/linkmgr.hxx>
    #include <sfx2/dispatch.hxx>
    #include <svl/urihelper.hxx>
    #include <sfx2/docfile.hxx>
    #include <vcl/help.hxx>
    #include <sot/filelist.hxx>
    #include <svl/eitem.hxx>
    #include <svl/urlbmk.hxx>
    #include <vcl/graphicfilter.hxx>
    #include <vcl/settings.hxx>

    #include <svtools/treelistentry.hxx>
    #include <sfx2/docinsert.hxx>
    #include <sfx2/filedlghelper.hxx>

    #include <sfx2/app.hxx>
    #include <swmodule.hxx>
    #include <wrtsh.hxx>
    #include <view.hxx>
    #include <docsh.hxx>
    #include <content.hxx>
    #include <edglbldc.hxx>
    #include <section.hxx>
    #include <tox.hxx>
    #include <cnttab.hxx>
    #include <navipi.hxx>
    #include <navicont.hxx>
    #include <edtwin.hxx>
    #include <uitool.hxx>
    #include <o3tl/make_unique.hxx>

    #include <cmdid.h>
    #include <helpids.h>
    #include <strings.hrc>
    #include <globals.hrc>
    #include <bitmaps.hlst>
    #include <swabstdlg.hxx>
    #include <memory>

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

    // Context menu for GlobalTree
    #define CTX_INSERT_ANY_INDEX 10
    #define CTX_INSERT_FILE     11
    #define CTX_INSERT_NEW_FILE 12
    #define CTX_INSERT_TEXT     13

    #define CTX_UPDATE_SEL      20
    #define CTX_UPDATE_INDEX    21
    #define CTX_UPDATE_LINK     22
    #define CTX_UPDATE_ALL      23

    #define CTX_UPDATE          1
    #define CTX_INSERT          2
    #define CTX_EDIT            3
    #define CTX_DELETE          4
    #define CTX_EDIT_LINK       5

    #define GLOBAL_UPDATE_TIMEOUT 2000

    // TabPos: push to left
    #define  GLBL_TABPOS_SUB 5

    const SfxObjectShell* SwGlobalTree::pShowShell = nullptr;
    static const char* aHelpForMenu[] =
    {
        nullptr,
        HID_GLBLTREE_UPDATE,        //CTX_UPDATE
        HID_GLBLTREE_INSERT,        //CTX_INSERT
        HID_GLBLTREE_EDIT,          //CTX_EDIT
        HID_GLBLTREE_DEL,           //CTX_DELETE
        HID_GLBLTREE_EDIT_LINK,     //CTX_EDIT_LINK
        nullptr,
        nullptr,
        nullptr,
        nullptr,
        HID_GLBLTREE_INS_IDX,       //CTX_INSERT_ANY_INDEX
        HID_GLBLTREE_INS_FILE,      //CTX_INSERT_FILE
        HID_GLBLTREE_INS_NEW_FILE,  //CTX_INSERT_NEW_FILE
        HID_GLBLTREE_INS_TEXT,      //CTX_INSERT_TEXT
        nullptr,
        nullptr,
        nullptr,
        nullptr,
        nullptr,
        nullptr,
        HID_GLBLTREE_UPD_SEL,       //CTX_UPDATE_SEL
        HID_GLBLTREE_UPD_IDX,       //CTX_UPDATE_INDEX
        HID_GLBLTREE_UPD_LINK,      //CTX_UPDATE_LINK
        HID_GLBLTREEUPD_ALL         //CTX_UPDATE_ALL
    };

    class SwGlobalFrameListener_Impl : public SfxListener
    {
        bool bValid;
    public:
        explicit SwGlobalFrameListener_Impl(SfxViewFrame& rFrame)
            : bValid(true)
        {
            StartListening(rFrame);
        }

        virtual void        Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;

        bool                IsValid() const {return bValid;}
    };

    void SwGlobalFrameListener_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
    {
        if( rHint.GetId() == SfxHintId::Dying)
            bValid = false;
    }

    enum GLOBAL_CONTEXT_IDX
    {
        IDX_STR_UPDATE = 0,
        IDX_STR_EDIT_CONTENT = 1,
        IDX_STR_EDIT_INSERT = 2,
        IDX_STR_INDEX = 3,
        IDX_STR_FILE = 4,
        IDX_STR_NEW_FILE = 5,
        IDX_STR_INSERT_TEXT = 6,
        IDX_STR_DELETE = 7,
        IDX_STR_UPDATE_SEL = 8,
        IDX_STR_UPDATE_INDEX = 9,
        IDX_STR_UPDATE_LINK = 10,
        IDX_STR_UPDATE_ALL = 11,
        IDX_STR_BROKEN_LINK = 12,
        IDX_STR_EDIT_LINK = 13
    };

    static const char* GLOBAL_CONTEXT_ARY[] =
    {
        STR_UPDATE,
        STR_EDIT_CONTENT,
        STR_EDIT_INSERT,
        STR_INDEX,
        STR_FILE,
        STR_NEW_FILE,
        STR_INSERT_TEXT,
        STR_DELETE,
        STR_UPDATE_SEL,
        STR_UPDATE_INDEX,
        STR_UPDATE_LINK,
        STR_UPDATE_ALL,
        STR_BROKEN_LINK,
        STR_EDIT_LINK
    };

    SwGlobalTree::SwGlobalTree(vcl::Window* pParent, SwNavigationPI* pDialog)
        : SvTreeListBox(pParent)
        , m_xDialog(pDialog)
        , m_pActiveShell(nullptr)
        , m_pEmphasisEntry(nullptr)
        , m_pDDSource(nullptr)
        , m_pDocContent(nullptr)
        , m_bIsInternalDrag(false)
        , m_bLastEntryEmphasis(false)
    {
        SetDragDropMode(DragDropMode::APP_COPY  |
                        DragDropMode::CTRL_MOVE |
                        DragDropMode::ENABLE_TOP );

        m_aUpdateTimer.SetTimeout(GLOBAL_UPDATE_TIMEOUT);
        m_aUpdateTimer.SetInvokeHandler(LINK(this, SwGlobalTree, Timeout));
        m_aUpdateTimer.Start();
        for (sal_uInt16 i = 0; i < GLOBAL_CONTEXT_COUNT; i++)
        {
            m_aContextStrings[i] = SwResId(GLOBAL_CONTEXT_ARY[i]);
        }
        SetHelpId(HID_NAVIGATOR_GLOB_TREELIST);
        SelectHdl();
        SetDoubleClickHdl(LINK(this, SwGlobalTree, DoubleClickHdl));
        EnableContextMenuHandling();
    }

    SwGlobalTree::~SwGlobalTree()
    {
        disposeOnce();
    }

    void SwGlobalTree::dispose()
    {
        m_pSwGlblDocContents.reset();
        m_pDocInserter.reset();
        m_aUpdateTimer.Stop();
        m_xDialog.clear();
        SvTreeListBox::dispose();
    }

    Size SwGlobalTree::GetOptimalSize() const
    {
        return LogicToPixel(Size(110, 112), MapMode(MapUnit::MapAppFont));
    }

    sal_Int8 SwGlobalTree::ExecuteDrop( const ExecuteDropEvent& rEvt )
    {
        sal_Int8 nRet = DND_ACTION_NONE;
        SvTreeListEntry* pLast = LastVisible();
        if(m_pEmphasisEntry)
        {
            ImplShowTargetEmphasis( Prev(m_pEmphasisEntry), false );
            m_pEmphasisEntry = nullptr;
        }
        else if(m_bLastEntryEmphasis && pLast)
        {
            ImplShowTargetEmphasis( pLast, false);
        }

        SvTreeListEntry* pDropEntry = m_bLastEntryEmphasis ? nullptr : GetEntry(rEvt.maPosPixel);
        if( m_bIsInternalDrag )
        {
            SvTreeListEntry* pDummy = nullptr;
            sal_uLong nInsertionPos = TREELIST_APPEND;
            NotifyMoving( pDropEntry, m_pDDSource, pDummy, nInsertionPos );
        }
        else
        {
            TransferableDataHelper aData( rEvt.maDropEvent.Transferable );

            OUString sFileName;
            const SwGlblDocContent* pCnt = pDropEntry ?
                        static_cast<const SwGlblDocContent*>(pDropEntry->GetUserData()) :
                                nullptr;
            if( aData.HasFormat( SotClipboardFormatId::FILE_LIST ))
            {
                nRet = rEvt.mnAction;
                std::unique_ptr<SwGlblDocContents> pTempContents(new SwGlblDocContents);
                int nAbsContPos = pDropEntry ?
                                    static_cast<int>(GetModel()->GetAbsPos(pDropEntry)):
                                        - 1;
                sal_uLong nEntryCount = GetEntryCount();

                // Get data
                FileList aFileList;
                aData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList );
                for ( size_t n = aFileList.Count(); n--; )
                {
                    sFileName = aFileList.GetFile(n);
                    InsertRegion(pCnt, &sFileName);
                    // The list of contents must be newly fetched after inserting,
                    // to not work on an old content.
                    if(n)
                    {
                        m_pActiveShell->GetGlobalDocContent(*pTempContents);
                        // If the file was successfully inserted,
                        // then the next content must also be fetched.
                        if(nEntryCount < pTempContents->size())
                        {
                            nEntryCount++;
                            nAbsContPos++;
                            pCnt = (*pTempContents)[ nAbsContPos ];
                        }
                    }
                }
            }
            else if( !(sFileName =
                            SwNavigationPI::CreateDropFileName( aData )).isEmpty())
            {
                INetURLObject aTemp(sFileName);
                GraphicDescriptor aDesc(aTemp);
                if( !aDesc.Detect() )   // accept no graphics
                {
                    nRet = rEvt.mnAction;
                    InsertRegion(pCnt, &sFileName);
                }
            }
        }
        m_bLastEntryEmphasis = false;
        return nRet;

    }

    sal_Int8 SwGlobalTree::AcceptDrop( const AcceptDropEvent& rEvt )
    {
        sal_Int8 nRet = rEvt.mnAction;

        //initiate scrolling
        GetDropTarget( rEvt.maPosPixel );
        SvTreeListEntry* pLast = LastVisible();
        if( rEvt.mbLeaving )
        {
            if( m_pEmphasisEntry )
            {
                ImplShowTargetEmphasis( Prev(m_pEmphasisEntry), false );
                m_pEmphasisEntry = nullptr;
            }
            else if(m_bLastEntryEmphasis && pLast)
            {
                ImplShowTargetEmphasis( pLast, false);
            }
            m_bLastEntryEmphasis = false;
        }
        else
        {
            SvTreeListEntry* pDropEntry = GetEntry( rEvt.maPosPixel );
            if(m_bIsInternalDrag)
            {
                if( m_pDDSource != pDropEntry )
                    nRet = rEvt.mnAction;
            }
            else if( IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ) ||
                      IsDropFormatSupported( SotClipboardFormatId::STRING ) ||
                      IsDropFormatSupported( SotClipboardFormatId::FILE_LIST ) ||
                      IsDropFormatSupported( SotClipboardFormatId::SOLK ) ||
                       IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK )||
                       IsDropFormatSupported( SotClipboardFormatId::FILECONTENT ) ||
                       IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR ) ||
                       IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR ) ||
                       IsDropFormatSupported( SotClipboardFormatId::FILENAME ))
                    nRet = DND_ACTION_LINK;

            if(m_pEmphasisEntry && m_pEmphasisEntry != pDropEntry)
                ImplShowTargetEmphasis( Prev(m_pEmphasisEntry), false );
            else if(pLast && m_bLastEntryEmphasis  && pDropEntry)
            {
                ImplShowTargetEmphasis( pLast, false);
                m_bLastEntryEmphasis = false;
            }

            if(pDropEntry)
                ImplShowTargetEmphasis( Prev(pDropEntry), DND_ACTION_NONE != nRet );
            else if(pLast)
            {
                ImplShowTargetEmphasis( pLast, DND_ACTION_NONE != nRet );
                m_bLastEntryEmphasis = true;
            }
            m_pEmphasisEntry = pDropEntry;
        }
        return nRet;
    }

    VclPtr<PopupMenu> SwGlobalTree::CreateContextMenu()
    {
        VclPtr<PopupMenu> pPop;
        if(m_pActiveShell &&
            !m_pActiveShell->GetView().GetDocShell()->IsReadOnly())
        {
            const MenuEnableFlags nEnableFlags = GetEnableFlags();
            pPop = VclPtr<PopupMenu>::Create();
            VclPtrInstance<PopupMenu> pSubPop1;
            VclPtrInstance<PopupMenu> pSubPop2;

            for (sal_uInt16 i = CTX_UPDATE_SEL; i <= CTX_UPDATE_ALL; i++)
            {
                pSubPop2->InsertItem( i, m_aContextStrings[IDX_STR_UPDATE_SEL + i - CTX_UPDATE_SEL] );
                pSubPop2->SetHelpId(i, aHelpForMenu[i]);
            }
            pSubPop2->EnableItem(CTX_UPDATE_SEL, bool(nEnableFlags & MenuEnableFlags::UpdateSel));

            pSubPop1->InsertItem(CTX_INSERT_ANY_INDEX, m_aContextStrings[IDX_STR_INDEX]);
            pSubPop1->SetHelpId(CTX_INSERT_ANY_INDEX, aHelpForMenu[CTX_INSERT_ANY_INDEX]);
            pSubPop1->InsertItem(CTX_INSERT_FILE, m_aContextStrings[IDX_STR_FILE]);
            pSubPop1->SetHelpId(CTX_INSERT_FILE, aHelpForMenu[CTX_INSERT_FILE]);
            pSubPop1->InsertItem(CTX_INSERT_NEW_FILE, m_aContextStrings[IDX_STR_NEW_FILE]);
            pSubPop1->SetHelpId(CTX_INSERT_NEW_FILE, aHelpForMenu[CTX_INSERT_NEW_FILE]);
            pSubPop1->InsertItem(CTX_INSERT_TEXT, m_aContextStrings[IDX_STR_INSERT_TEXT]);
            pSubPop1->SetHelpId(CTX_INSERT_TEXT, aHelpForMenu[CTX_INSERT_TEXT]);

            pPop->InsertItem(CTX_UPDATE, m_aContextStrings[IDX_STR_UPDATE]);
            pPop->SetHelpId(CTX_UPDATE, aHelpForMenu[CTX_UPDATE]);
            pPop->InsertItem(CTX_EDIT, m_aContextStrings[IDX_STR_EDIT_CONTENT]);
            pPop->SetHelpId(CTX_EDIT, aHelpForMenu[CTX_EDIT]);
            if(nEnableFlags&MenuEnableFlags::EditLink)
            {
                pPop->InsertItem(CTX_EDIT_LINK, m_aContextStrings[IDX_STR_EDIT_LINK]);
                pPop->SetHelpId(CTX_EDIT_LINK, aHelpForMenu[CTX_EDIT_LINK]);
            }
            pPop->InsertItem(CTX_INSERT, m_aContextStrings[IDX_STR_EDIT_INSERT]);
            pPop->SetHelpId(CTX_INSERT, aHelpForMenu[CTX_INSERT]);
            pPop->InsertSeparator() ;
            pPop->InsertItem(CTX_DELETE, m_aContextStrings[IDX_STR_DELETE]);
            pPop->SetHelpId(CTX_DELETE, aHelpForMenu[CTX_DELETE]);

            //disabling if applicable
            pSubPop1->EnableItem(CTX_INSERT_ANY_INDEX,  bool(nEnableFlags & MenuEnableFlags::InsertIdx ));
            pSubPop1->EnableItem(CTX_INSERT_TEXT,       bool(nEnableFlags & MenuEnableFlags::InsertText));
            pSubPop1->EnableItem(CTX_INSERT_FILE,       bool(nEnableFlags & MenuEnableFlags::InsertFile));
            pSubPop1->EnableItem(CTX_INSERT_NEW_FILE,   bool(nEnableFlags & MenuEnableFlags::InsertFile));

            pPop->EnableItem(CTX_UPDATE,    bool(nEnableFlags & MenuEnableFlags::Update));
            pPop->EnableItem(CTX_INSERT,    bool(nEnableFlags & MenuEnableFlags::InsertIdx));
            pPop->EnableItem(CTX_EDIT,      bool(nEnableFlags & MenuEnableFlags::Edit));
            pPop->EnableItem(CTX_DELETE,    bool(nEnableFlags & MenuEnableFlags::Delete));

            pPop->SetPopupMenu( CTX_INSERT, pSubPop1 );
            pPop->SetPopupMenu( CTX_UPDATE, pSubPop2 );
        }
        return pPop;
    }

    void SwGlobalTree::TbxMenuHdl(sal_uInt16 nTbxId, ToolBox* pBox)
    {
        const MenuEnableFlags nEnableFlags = GetEnableFlags();
        const OUString sCommand(pBox->GetItemCommand(nTbxId));
        if (sCommand == "insert")
        {
            ScopedVclPtrInstance<PopupMenu> pMenu;
            for (sal_uInt16 i = CTX_INSERT_ANY_INDEX; i <= CTX_INSERT_TEXT; ++i)
            {
                pMenu->InsertItem( i, m_aContextStrings[IDX_STR_INDEX + i - CTX_INSERT_ANY_INDEX] );
                pMenu->SetHelpId(i, aHelpForMenu[i] );
            }
            pMenu->EnableItem(CTX_INSERT_ANY_INDEX, bool(nEnableFlags & MenuEnableFlags::InsertIdx ));
            pMenu->EnableItem(CTX_INSERT_TEXT,      bool(nEnableFlags & MenuEnableFlags::InsertText));
            pMenu->EnableItem(CTX_INSERT_FILE,      bool(nEnableFlags & MenuEnableFlags::InsertFile));
            pMenu->EnableItem(CTX_INSERT_NEW_FILE,  bool(nEnableFlags & MenuEnableFlags::InsertFile));
            pMenu->SetSelectHdl(LINK(this, SwGlobalTree, PopupHdl));
            pMenu->Execute(pBox, pBox->GetItemRect(nTbxId));
            pMenu.disposeAndClear();
            pBox->EndSelection();
            pBox->Invalidate();
        }
        else if (sCommand == "update")
        {
            ScopedVclPtrInstance<PopupMenu> pMenu;
            for (sal_uInt16 i = CTX_UPDATE_SEL; i <= CTX_UPDATE_ALL; i++)
            {
                pMenu->InsertItem( i, m_aContextStrings[IDX_STR_UPDATE_SEL + i - CTX_UPDATE_SEL] );
                pMenu->SetHelpId(i, aHelpForMenu[i] );
            }
            pMenu->EnableItem(CTX_UPDATE_SEL, bool(nEnableFlags & MenuEnableFlags::UpdateSel));
            pMenu->SetSelectHdl(LINK(this, SwGlobalTree, PopupHdl));
            pMenu->Execute(pBox, pBox->GetItemRect(nTbxId));
            pMenu.disposeAndClear();
            pBox->EndSelection();
            pBox->Invalidate();
        }
    }

    MenuEnableFlags  SwGlobalTree::GetEnableFlags() const
    {
        SvTreeListEntry* pEntry = FirstSelected();
        sal_uLong nSelCount = GetSelectionCount();
        sal_uLong nEntryCount = GetEntryCount();
        SvTreeListEntry* pPrevEntry = pEntry ? Prev(pEntry) : nullptr;

        MenuEnableFlags nRet = MenuEnableFlags::NONE;
        if(nSelCount == 1 || !nEntryCount)
            nRet |= MenuEnableFlags::InsertIdx|MenuEnableFlags::InsertFile;
        if(nSelCount == 1)
        {
            nRet |= MenuEnableFlags::Edit;
            if (pEntry && static_cast<SwGlblDocContent*>(pEntry->GetUserData())->GetType() != GLBLDOC_UNKNOWN &&
                        (!pPrevEntry || static_cast<SwGlblDocContent*>(pPrevEntry->GetUserData())->GetType() != GLBLDOC_UNKNOWN))
                nRet |= MenuEnableFlags::InsertText;
            if (pEntry && GLBLDOC_SECTION == static_cast<SwGlblDocContent*>(pEntry->GetUserData())->GetType())
                nRet |= MenuEnableFlags::EditLink;
        }
        else if(!nEntryCount)
        {
            nRet |= MenuEnableFlags::InsertText;
        }
        if(nEntryCount)
            nRet |= MenuEnableFlags::Update|MenuEnableFlags::Delete;
        if(nSelCount)
            nRet |= MenuEnableFlags::UpdateSel;
        return nRet;
    }

    void     SwGlobalTree::RequestHelp( const HelpEvent& rHEvt )
    {
        bool bParent = true;
        Update(true);
        Display(true);
        if( rHEvt.GetMode() & HelpEventMode::QUICK )
        {
            Point aPos( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
            SvTreeListEntry* pEntry = GetEntry( aPos );
            const SwGlblDocContent* pCont = pEntry ?
                                static_cast<const SwGlblDocContent*>(pEntry->GetUserData()) : nullptr;
            if( pCont &&  GLBLDOC_SECTION == pCont->GetType())
            {
                bParent = false;
                SvLBoxTab* pTab;
                SvLBoxItem* pItem = GetItem( pEntry, aPos.X(), &pTab );
                if (pItem && SvLBoxItemType::String == pItem->GetType())
                {
                    const SwSection* pSect = pCont->GetSection();
                    OUString sEntry = pSect->GetLinkFileName().getToken(0, sfx2::cTokenSeparator);
                    if(!pSect->IsConnectFlag())
                        sEntry = m_aContextStrings[IDX_STR_BROKEN_LINK] + sEntry;
                    Point aEntryPos = GetEntryPosition( pEntry );

                    aEntryPos.setX( GetTabPos( pEntry, pTab ) );
                    Size aSize( pItem->GetSize( this, pEntry ) );

                    if((aEntryPos.X() + aSize.Width()) > GetSizePixel().Width())
                        aSize.setWidth( GetSizePixel().Width() - aEntryPos.X() );

                    aEntryPos = OutputToScreenPixel(aEntryPos);
                    tools::Rectangle aItemRect( aEntryPos, aSize );
                    if(Help::IsBalloonHelpEnabled())
                    {
                        aEntryPos.AdjustX(aSize.Width() );
                        Help::ShowBalloon( this, aEntryPos, aItemRect, sEntry );
                    }
                    else
                        Help::ShowQuickHelp( this, aItemRect, sEntry,
                            QuickHelpFlags::Left|QuickHelpFlags::VCenter );
                }
            }
        }

        if(bParent)
            SvTreeListBox::RequestHelp(rHEvt);
    }

    void     SwGlobalTree::SelectHdl()
    {

        sal_uLong nSelCount = GetSelectionCount();
        SvTreeListEntry* pSel = FirstSelected();
        sal_uLong nAbsPos = pSel ? GetModel()->GetAbsPos(pSel) : 0;
        SwNavigationPI* pNavi = GetParentWindow();
        bool bReadonly = !m_pActiveShell ||
                    m_pActiveShell->GetView().GetDocShell()->IsReadOnly();
        pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("edit"),  nSelCount == 1 && !bReadonly);
        pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("insert"),  nSelCount <= 1 && !bReadonly);
        pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("update"),  GetEntryCount() > 0 && !bReadonly);
        pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("up"),
                        nSelCount == 1 && nAbsPos && !bReadonly);
        pNavi->m_aGlobalToolBox->EnableItem(pNavi->m_aGlobalToolBox->GetItemId("down"),
                        nSelCount == 1 && nAbsPos < GetEntryCount() - 1 && !bReadonly);

    }

    void     SwGlobalTree::DeselectHdl()
    {
        SelectHdl();
    }

    DragDropMode SwGlobalTree::NotifyStartDrag( TransferDataContainer& ,
                                                    SvTreeListEntry* pEntry )
    {
        m_bIsInternalDrag = true;
        m_pDDSource = pEntry;
        return DragDropMode::CTRL_MOVE;
    }

    sal_IntPtr SwGlobalTree::GetTabPos( SvTreeListEntry*, SvLBoxTab* pTab)
    {
        return pTab->GetPos() - GLBL_TABPOS_SUB;
    }

    TriState SwGlobalTree::NotifyMoving(   SvTreeListEntry*  pTarget,
                                            SvTreeListEntry*  pSource,
                                            SvTreeListEntry*&,
                                            sal_uLong&
                                        )
    {
        SvTreeList* _pModel = GetModel();
        sal_uLong nSource = _pModel->GetAbsPos(pSource);
        sal_uLong nDest   = pTarget ? _pModel->GetAbsPos(pTarget) : m_pSwGlblDocContents->size();

        if( m_pActiveShell->MoveGlobalDocContent(
                *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
                Update( false ))
            Display();

        return TRISTATE_FALSE;
    }

    TriState SwGlobalTree::NotifyCopying(  SvTreeListEntry*  /*pTarget*/,
                                            SvTreeListEntry*  /*pEntry*/,
                                            SvTreeListEntry*& /*rpNewParent*/,
                                            sal_uLong&        /*rNewChildPos*/
                                        )
    {
        return TRISTATE_FALSE;
    }

    bool SwGlobalTree::NotifyAcceptDrop( SvTreeListEntry* pEntry)
    {
        return pEntry != nullptr;
    }

    void SwGlobalTree::StartDrag( sal_Int8 nAction, const Point& rPt )
    {
        if( 1 == GetSelectionCount() )
            SvTreeListBox::StartDrag( nAction, rPt );
    }

    void SwGlobalTree::DragFinished( sal_Int8 nAction )
    {
        SvTreeListBox::DragFinished( nAction );
        m_bIsInternalDrag = false;
    }

    // If a Ctrl+DoubleClick is executed in an empty area,
    // then the base function of the control should be called.

    void  SwGlobalTree::MouseButtonDown( const MouseEvent& rMEvt )
    {
        Point aPos( rMEvt.GetPosPixel());
        SvTreeListEntry* pEntry = GetEntry( aPos, true );
        if( !pEntry && rMEvt.IsLeft() && rMEvt.IsMod1() && (rMEvt.GetClicks() % 2) == 0)
            Control::MouseButtonDown( rMEvt );
        else
            SvTreeListBox::MouseButtonDown( rMEvt );
    }

    void     SwGlobalTree::GetFocus()
    {
        if(Update( false ))
            Display();
        SvTreeListBox::GetFocus();
    }

    void     SwGlobalTree::KeyInput(const KeyEvent& rKEvt)
    {
        const vcl::KeyCode aCode = rKEvt.GetKeyCode();
        if(aCode.GetCode() == KEY_RETURN)
        {
            switch(aCode.GetModifier())
            {
                case KEY_MOD2:
                    // Switch boxes
                    GetParentWindow()->ToggleTree();
                break;
            }
        }
        else
            SvTreeListBox::KeyInput(rKEvt);
    }

    void SwGlobalTree::Clear()
    {
        m_pEmphasisEntry = nullptr;
        SvTreeListBox::Clear();
    }

    void SwGlobalTree::Display(bool bOnlyUpdateUserData)
    {
        size_t nCount = m_pSwGlblDocContents->size();
        if(bOnlyUpdateUserData && GetEntryCount() == m_pSwGlblDocContents->size())
        {
            SvTreeListEntry* pEntry = First();
            for (size_t i = 0; i < nCount && pEntry; i++)
            {
                SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i];
                pEntry->SetUserData(pCont);
                pEntry = Next(pEntry);
                assert(pEntry || i == nCount - 1);
            }
        }
        else
        {
            SetUpdateMode( false );
            SvTreeListEntry* pOldSelEntry = FirstSelected();
            OUString sEntryName;  // Name of the entry
            sal_uLong nSelPos = TREELIST_ENTRY_NOTFOUND;
            if(pOldSelEntry)
            {
                sEntryName = GetEntryText(pOldSelEntry);
                nSelPos = GetModel()->GetAbsPos(pOldSelEntry);
            }
            Clear();
            if(!m_pSwGlblDocContents)
                Update( false );

            SvTreeListEntry* pSelEntry = nullptr;
            for( size_t i = 0; i < nCount; i++)
            {
                SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i];
                OUString sEntry;
                Image aImage;
                switch( pCont->GetType()  )
                {
                    case GLBLDOC_UNKNOWN:
                    {
                        sEntry = m_aContextStrings[IDX_STR_INSERT_TEXT];
                    }
                    break;
                    case GLBLDOC_TOXBASE:
                    {
                        const SwTOXBase* pBase = pCont->GetTOX();
                        sEntry = pBase->GetTitle();
                        aImage = Image(BitmapEx(RID_BMP_NAVI_INDEX));
                    }
                    break;
                    case GLBLDOC_SECTION:
                    {
                        const SwSection* pSect = pCont->GetSection();
                        sEntry = pSect->GetSectionName();
                        aImage = Image(BitmapEx(RID_BMP_DROP_REGION));
                    }
                    break;
                }
                SvTreeListEntry* pEntry = InsertEntry(sEntry, aImage, aImage,
                            nullptr, false, TREELIST_APPEND, pCont);
                if(sEntry == sEntryName)
                {
                    pSelEntry = pEntry;
                }
            }
            if(pSelEntry)
            {
                Select(pSelEntry);
            }
            else if(nSelPos != TREELIST_ENTRY_NOTFOUND && nSelPos < nCount)
            {
                Select(GetEntry(nSelPos));
            }
            else if(nCount)
                Select(First());
            else
                SelectHdl();
            SetUpdateMode( true );
        }
    }

    void SwGlobalTree::InsertRegion( const SwGlblDocContent* pCont, const OUString* pFileName )
    {
        Sequence< OUString > aFileNames;
        if ( !pFileName )
        {
            m_pDocInserter.reset(new ::sfx2::DocumentInserter(GetFrameWeld(), "swriter", sfx2::DocumentInserter::Mode::InsertMulti));
            m_pDocInserter->StartExecuteModal( LINK( this, SwGlobalTree, DialogClosedHdl ) );
        }
        else if ( !pFileName->isEmpty() )
        {
            aFileNames.realloc(1);
            INetURLObject aFileName;
            aFileName.SetSmartURL( *pFileName );
            aFileNames.getArray()[0] = aFileName.GetMainURL( INetURLObject::DecodeMechanism::NONE );
            InsertRegion( pCont, aFileNames );
        }
    }

    void    SwGlobalTree::EditContent(const SwGlblDocContent* pCont )
    {
        sal_uInt16 nSlot = 0;
        switch( pCont->GetType() )
        {
            case GLBLDOC_UNKNOWN:
                m_pActiveShell->GetView().GetEditWin().GrabFocus();
            break;
            case GLBLDOC_TOXBASE:
            {
                const SwTOXBase* pBase = pCont->GetTOX();
                if(pBase)
                    nSlot = FN_INSERT_MULTI_TOX;
            }
            break;
            case GLBLDOC_SECTION:
            {
                OpenDoc(pCont);

                nSlot = 0;
                pCont = nullptr;
            }
            break;
        }
        if(pCont)
            GotoContent(pCont);
        if(nSlot)
        {
            m_pActiveShell->GetView().GetViewFrame()->GetDispatcher()->Execute(nSlot);
            if(Update( false ))
                Display();
        }
    }

    IMPL_LINK( SwGlobalTree, PopupHdl, Menu* , pMenu, bool)
    {
        ExecuteContextMenuAction( pMenu->GetCurItemId());
        return true;
    }

    void    SwGlobalTree::ExecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry )
    {
        SvTreeListEntry* pEntry = FirstSelected();
        SwGlblDocContent* pCont = pEntry ? static_cast<SwGlblDocContent*>(pEntry->GetUserData()) : nullptr;
        // If a RequestHelp is called during the dialogue,
        // then the content gets lost. Because of that a copy
        // is created in which only the DocPos is set correctly.
        SwGlblDocContent* pContCopy = nullptr;
        if(pCont)
            pContCopy = new SwGlblDocContent(pCont->GetDocPos());
        SfxDispatcher& rDispatch = *m_pActiveShell->GetView().GetViewFrame()->GetDispatcher();
        sal_uInt16 nSlot = 0;
        bool bDeleteContentCopy = true;
        switch( nSelectedPopupEntry )
        {
            case CTX_UPDATE_SEL:
            {
                // Two passes: first update the areas, then the directories.
                SvTreeListEntry* pSelEntry = FirstSelected();
                while( pSelEntry )
                {
                    SwGlblDocContent* pContent = static_cast<SwGlblDocContent*>(pSelEntry->GetUserData());
                    if(GLBLDOC_SECTION == pContent->GetType() &&
                        pContent->GetSection()->IsConnected())
                    {
                        const_cast<SwSection*>(pContent->GetSection())->UpdateNow();
                    }

                    pSelEntry = NextSelected(pSelEntry);
                }
                pSelEntry = FirstSelected();
                while( pSelEntry )
                {
                    SwGlblDocContent* pContent = static_cast<SwGlblDocContent*>(pSelEntry->GetUserData());
                    if(GLBLDOC_TOXBASE == pContent->GetType())
                        m_pActiveShell->UpdateTableOf(*pContent->GetTOX());
                    pSelEntry = NextSelected(pSelEntry);
                }

            }
            break;
            case CTX_UPDATE_INDEX:
            {
                nSlot = FN_UPDATE_TOX;
            }
            break;
            case CTX_UPDATE_LINK:
            case CTX_UPDATE_ALL:
            {
                m_pActiveShell->GetLinkManager().UpdateAllLinks(true, false, nullptr);
                if(CTX_UPDATE_ALL == nSelectedPopupEntry)
                    nSlot = FN_UPDATE_TOX;
                pCont = nullptr;
            }
            break;
            case CTX_EDIT:
            {
                OSL_ENSURE(pCont, "edit without entry ? " );
                if (pCont)
                {
                    EditContent(pCont);
                }
            }
            break;
            case CTX_EDIT_LINK:
            {
                OSL_ENSURE(pCont, "edit without entry ? " );
                if (pCont)
                {
                    SfxStringItem aName(FN_EDIT_REGION,
                            pCont->GetSection()->GetSectionName());
                    rDispatch.ExecuteList(FN_EDIT_REGION, SfxCallMode::ASYNCHRON,
                            { &aName });
                }
            }
            break;
            case CTX_DELETE:
            {
                // If several entries selected, then after each delete the array
                // must be refilled. So you do not have to remember anything,
                // deleting begins at the end.
                SvTreeListEntry* pSelEntry = LastSelected();
                std::unique_ptr<SwGlblDocContents> pTempContents;
                m_pActiveShell->StartAction();
                while(pSelEntry)
                {
                    m_pActiveShell->DeleteGlobalDocContent(
                        pTempContents ? *pTempContents : *m_pSwGlblDocContents,
                                         GetModel()->GetAbsPos(pSelEntry));
                    pSelEntry = PrevSelected(pSelEntry);
                    if(pSelEntry)
                    {
                        pTempContents.reset(new SwGlblDocContents);
                        m_pActiveShell->GetGlobalDocContent(*pTempContents);
                    }
                }
                pTempContents.reset();
                m_pActiveShell->EndAction();
                pCont = nullptr;
            }
            break;
            case CTX_INSERT_ANY_INDEX:
            {
                if(pContCopy)
                {
                    SfxItemSet aSet(
                        m_pActiveShell->GetView().GetPool(),
                        svl::Items<
                            RES_FRM_SIZE, RES_FRM_SIZE,
                            RES_LR_SPACE, RES_LR_SPACE,
                            RES_BACKGROUND, RES_BACKGROUND,
                            RES_COL, RES_COL,
                            SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE,
                            FN_PARAM_TOX_TYPE, FN_PARAM_TOX_TYPE>{});

                    SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
                    ScopedVclPtr<AbstractMultiTOXTabDialog> pDlg(pFact->CreateMultiTOXTabDialog(
                                                            this, aSet,
                                                            *m_pActiveShell,
                                                            nullptr,
                                                            true));
                    if(RET_OK == pDlg->Execute())
                    {
                        SwTOXDescription&  rDesc = pDlg->GetTOXDescription(
                                                    pDlg->GetCurrentTOXType());
                        SwTOXMgr aMgr(m_pActiveShell);
                        SwTOXBase* pToInsert = nullptr;
                        if(aMgr.UpdateOrInsertTOX(rDesc, &pToInsert, pDlg->GetOutputItemSet()))
                            m_pActiveShell->InsertGlobalDocContent( *pContCopy, *pToInsert );
                    }
                    pCont = nullptr;
                }
            }
            break;
            case CTX_INSERT_FILE:
            {
                bDeleteContentCopy = false;
                m_pDocContent = pContCopy;
                InsertRegion( pContCopy );
                pCont = nullptr;
            }
            break;
            case CTX_INSERT_NEW_FILE:
            {
                SfxViewFrame* pGlobFrame = m_pActiveShell->GetView().GetViewFrame();
                SwGlobalFrameListener_Impl aFrameListener(*pGlobFrame);

                sal_uLong nEntryPos = pEntry ? GetModel()->GetAbsPos(pEntry) : sal_uLong(-1);
                // Creating a new doc
                SfxStringItem aFactory(SID_NEWDOCDIRECT,
                                SwDocShell::Factory().GetFilterContainer()->GetName());

                 const SfxFrameItem* pItem = static_cast<const SfxFrameItem*>(
                                rDispatch.ExecuteList(SID_NEWDOCDIRECT,
                                    SfxCallMode::SYNCHRON, { &aFactory }));

                // save at
                SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr;
                SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr;
                if (pViewFrame)
                {
                    const SfxBoolItem* pBool = static_cast<const SfxBoolItem*>(
                            pViewFrame->GetDispatcher()->Execute(
                                    SID_SAVEASDOC, SfxCallMode::SYNCHRON ));
                    SfxObjectShell& rObj = *pViewFrame->GetObjectShell();
                    const SfxMedium* pMedium = rObj.GetMedium();
                    OUString sNewFile(pMedium->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri));
                    // Insert the area with the Doc-Name
                    // Bring the own Doc in the foreground
                    if(aFrameListener.IsValid() && !sNewFile.isEmpty())
                    {
                        pGlobFrame->ToTop();
                        // Due to the update the entries are invalid
                        if(nEntryPos != sal_uLong(-1))
                        {
                            Update( false );
                            Display();
                            Select(GetModel()->GetEntryAtAbsPos(nEntryPos));
                            pEntry = FirstSelected();
                            pCont = pEntry ? static_cast<SwGlblDocContent*>(pEntry->GetUserData()) : nullptr;
                        }
                        else
                        {
                            pEntry = nullptr;
                            pCont = nullptr;
                        }
                        if(pBool->GetValue())
                        {
                            InsertRegion(pCont, &sNewFile);
                            pViewFrame->ToTop();
                        }
                        else
                            pViewFrame->GetDispatcher()->Execute(SID_CLOSEWIN,
                                                    SfxCallMode::SYNCHRON);
                    }
                    else
                    {
                        pViewFrame->ToTop();
                        return;
                    }
                }
            }
            break;
            case CTX_INSERT_TEXT:
            {
                if(pCont)
                    m_pActiveShell->InsertGlobalDocContent(*pCont);
                else
                {
                    m_pActiveShell->SplitNode(); // Empty document
                    m_pActiveShell->Up( false );
                }
                m_pActiveShell->GetView().GetEditWin().GrabFocus();
            }
            break;
            case CTX_UPDATE:
                pCont = nullptr;
            break;
            default:;
            // here nothing happens
        }
        if(pCont)
            GotoContent(pCont);
        if(nSlot)
            rDispatch.Execute(nSlot);
        if(Update( false ))
            Display();
        if ( bDeleteContentCopy )
            delete pContCopy;
    }

    IMPL_LINK_NOARG(SwGlobalTree, Timeout, Timer *, void)
    {
        if(!IsDisposed() && !HasFocus() && Update( false ))
            Display();
    }

    void SwGlobalTree::GotoContent(const SwGlblDocContent* pCont)
    {
        m_pActiveShell->EnterStdMode();

        switch( pCont->GetType()  )
        {
            case GLBLDOC_UNKNOWN:
                m_pActiveShell->GotoGlobalDocContent(*pCont);
            break;
            case GLBLDOC_TOXBASE:
            {
                const OUString sName = pCont->GetTOX()->GetTOXName();
                if (!m_pActiveShell->GotoNextTOXBase(&sName))
                    m_pActiveShell->GotoPrevTOXBase(&sName);
            }
            break;
            case GLBLDOC_SECTION:
            break;
        }

    }

    void    SwGlobalTree::ShowTree()
    {
        m_aUpdateTimer.Start();
        SvTreeListBox::Show();
    }

    void    SwGlobalTree::HideTree()
    {
        m_aUpdateTimer.Stop();
        SvTreeListBox::Hide();
    }

    void    SwGlobalTree::ExecCommand(const OUString &rCmd)
    {
        SvTreeListEntry* pEntry = FirstSelected();
        OSL_ENSURE(pEntry, "It explodes in the next moment");
        if (rCmd == "edit")
        {
            const SwGlblDocContent* pCont = static_cast<const SwGlblDocContent*>(
                                                    pEntry->GetUserData());
            EditContent(pCont);
        }
        else
        {
            if(GetSelectionCount() == 1)
            {
                bool bMove = false;
                sal_uLong nSource = GetModel()->GetAbsPos(pEntry);
                sal_uLong nDest = nSource;
                if (rCmd == "down")
                {
                    sal_uLong nEntryCount = GetEntryCount();
                    bMove = nEntryCount > nSource + 1;
                    nDest+= 2;
                }
                else if (rCmd == "up")
                {
                    if(nSource)
                        bMove = 0 != nSource;
                    nDest--;
                }
                if( bMove && m_pActiveShell->MoveGlobalDocContent(
                    *m_pSwGlblDocContents, nSource, nSource + 1, nDest ) &&
                        Update( false ))
                    Display();
            }
        }
    }

    bool    SwGlobalTree::Update(bool bHard)
    {
        SwView* pActView = GetParentWindow()->GetCreateView();
        bool bRet = false;
        if(pActView && pActView->GetWrtShellPtr())
        {
            const SwWrtShell* pOldShell = m_pActiveShell;
            m_pActiveShell = pActView->GetWrtShellPtr();
            if(m_pActiveShell != pOldShell)
            {
                m_pSwGlblDocContents.reset();
            }
            if(!m_pSwGlblDocContents)
            {
                m_pSwGlblDocContents.reset(new SwGlblDocContents);
                bRet = true;
                m_pActiveShell->GetGlobalDocContent(*m_pSwGlblDocContents);
            }
            else
            {
                bool bCopy = false;
                std::unique_ptr<SwGlblDocContents> pTempContents(new SwGlblDocContents);
                m_pActiveShell->GetGlobalDocContent(*pTempContents);
                if(pTempContents->size() != m_pSwGlblDocContents->size() ||
                        pTempContents->size() != GetEntryCount())
                {
                    bRet = true;
                    bCopy = true;
                }
                else
                {
                    for(size_t i = 0; i < pTempContents->size() && !bCopy; i++)
                    {
                        SwGlblDocContent* pLeft = (*pTempContents)[i];
                        SwGlblDocContent* pRight = (*m_pSwGlblDocContents)[i];
                        GlobalDocContentType eType = pLeft->GetType();
                        SvTreeListEntry* pEntry = GetEntry(i);
                        OUString sTemp = GetEntryText(pEntry);
                        if (
                             eType != pRight->GetType() ||
                             (
                               eType == GLBLDOC_SECTION &&
                               pLeft->GetSection()->GetSectionName() != sTemp
                             ) ||
                             (
                               eType == GLBLDOC_TOXBASE &&
                               pLeft->GetTOX()->GetTitle() != sTemp
                             )
                           )
                        {
                            bCopy = bRet = true;
                        }
                    }
                }
                if(bCopy || bHard)
                {
                    m_pSwGlblDocContents->DeleteAndDestroyAll();
                    m_pSwGlblDocContents->insert( *pTempContents );
                    pTempContents->clear();

                }
            }

        }
        else
        {
            Clear();
            if(m_pSwGlblDocContents)
                m_pSwGlblDocContents->DeleteAndDestroyAll();
        }
        // FIXME: Implement a test for changes!
        return bRet;
    }

    void SwGlobalTree::OpenDoc(const SwGlblDocContent* pCont)
    {
        const OUString sFileName(pCont->GetSection()->GetLinkFileName().getToken(0,
                sfx2::cTokenSeparator));
        bool bFound = false;
        const SfxObjectShell* pCurr = SfxObjectShell::GetFirst();
        while( !bFound && pCurr )
        {
            if(pCurr->GetMedium() &&
               pCurr->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri) == sFileName)
            {
                bFound = true;
                SwGlobalTree::SetShowShell(pCurr);
                Application::PostUserEvent( LINK( this, SwGlobalTree, ShowFrameHdl ), nullptr, true );
                pCurr = nullptr;
            }
            else
                pCurr = SfxObjectShell::GetNext(*pCurr);
        }
        if(!bFound)
        {
            SfxStringItem aURL(SID_FILE_NAME, sFileName);
            SfxBoolItem aReadOnly(SID_DOC_READONLY, false);
            SfxStringItem aTargetFrameName( SID_TARGETNAME, "_blank" );
            SfxStringItem aReferer(SID_REFERER, m_pActiveShell->GetView().GetDocShell()->GetTitle());
            m_pActiveShell->GetView().GetViewFrame()->GetDispatcher()->
                    ExecuteList(SID_OPENDOC, SfxCallMode::ASYNCHRON,
                            { &aURL, &aReadOnly, &aReferer, &aTargetFrameName });
        }
    }

    IMPL_LINK_NOARG( SwGlobalTree, DoubleClickHdl, SvTreeListBox*, bool)
    {
        SvTreeListEntry* pEntry = GetCurEntry();
        SwGlblDocContent* pCont = static_cast<SwGlblDocContent*>(pEntry->GetUserData());
        if(pCont->GetType() == GLBLDOC_SECTION)
            OpenDoc(pCont);
        else
        {
            GotoContent(pCont);
            m_pActiveShell->GetView().GetEditWin().GrabFocus();
        }
        return false;
    }

    SwNavigationPI* SwGlobalTree::GetParentWindow()
    {
        return m_xDialog;
    }

    IMPL_STATIC_LINK_NOARG(SwGlobalTree, ShowFrameHdl, void*, void)
    {
        SfxViewFrame* pFirst = pShowShell ? SfxViewFrame::GetFirst(pShowShell) : nullptr;
        if (pFirst)
            pFirst->ToTop();
        SwGlobalTree::SetShowShell(nullptr);
    }

    void SwGlobalTree::InitEntry(SvTreeListEntry* pEntry,
            const OUString& rStr ,const Image& rImg1,const Image& rImg2,
            SvLBoxButtonKind eButtonKind)
    {
        const size_t nColToHilite = 1; //0==Bitmap;1=="Column1";2=="Column2"
        SvTreeListBox::InitEntry( pEntry, rStr, rImg1, rImg2, eButtonKind );
        SvLBoxString& rCol = static_cast<SvLBoxString&>(pEntry->GetItem( nColToHilite ));
        pEntry->ReplaceItem(o3tl::make_unique<SwLBoxString>(rCol.GetText()), nColToHilite);
    }

    void SwLBoxString::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
                             const SvViewDataEntry* pView, const SvTreeListEntry& rEntry)
    {
        SwGlblDocContent* pCont = static_cast<SwGlblDocContent*>(rEntry.GetUserData());
        if (pCont->GetType() == GLBLDOC_SECTION &&
          !pCont->GetSection()->IsConnectFlag())
        {
            rRenderContext.Push(PushFlags::FONT);
            vcl::Font aOldFont(rRenderContext.GetFont());
            vcl::Font aFont(rRenderContext.GetFont());
            aFont.SetColor(COL_LIGHTRED);
            rRenderContext.SetFont(aFont);
            rRenderContext.DrawText(rPos, GetText());
            rRenderContext.Pop();
        }
        else
            SvLBoxString::Paint(rPos, rDev, rRenderContext, pView, rEntry);
    }

    void    SwGlobalTree::DataChanged( const DataChangedEvent& rDCEvt )
    {
        if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
             (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
        {
            Update(true);
        }
        SvTreeListBox::DataChanged( rDCEvt );
    }

    void SwGlobalTree::InsertRegion( const SwGlblDocContent* _pContent, const Sequence< OUString >& _rFiles )
    {
        sal_Int32 nFiles = _rFiles.getLength();
        if ( !nFiles )
            return;

        bool bMove = false;
        if ( !_pContent )
        {
            SvTreeListEntry* pLast = LastVisible();
            _pContent = static_cast<SwGlblDocContent*>(pLast->GetUserData());
            bMove = true;
        }
        sal_uLong nEntryCount = GetEntryCount();
        const OUString* pFileNames = _rFiles.getConstArray();
        SwWrtShell& rSh = GetParentWindow()->GetCreateView()->GetWrtShell();
        rSh.StartAction();
        // after insertion of the first new content the 'pCont' parameter becomes invalid
        // find the index of the 'anchor' content to always use a current anchor content
        size_t nAnchorContent = m_pSwGlblDocContents->size() - 1;
        if ( !bMove )
        {
            for (size_t nContent = 0; nContent < m_pSwGlblDocContents->size();
                    ++nContent)
            {
                if( *_pContent == *(*m_pSwGlblDocContents)[ nContent ] )
                {
                    nAnchorContent = nContent;
                    break;
                }
            }
        }
        SwGlblDocContents aTempContents;
        for ( sal_Int32 nFile = 0; nFile < nFiles; ++nFile )
        {
            //update the global document content after each inserted document
            rSh.GetGlobalDocContent(aTempContents);
            SwGlblDocContent* pAnchorContent = nullptr;
            OSL_ENSURE(aTempContents.size() > (nAnchorContent + nFile), "invalid anchor content -> last insertion failed");
            if ( aTempContents.size() > (nAnchorContent + nFile) )
                pAnchorContent = aTempContents[nAnchorContent + nFile];
            else
                pAnchorContent = aTempContents.back();
            OUString sFileName(pFileNames[nFile]);
            INetURLObject aFileUrl;
            aFileUrl.SetSmartURL( sFileName );
            OUString sSectionName(aFileUrl.GetLastName(
                INetURLObject::DecodeMechanism::Unambiguous).getToken(0, sfx2::cTokenSeparator));
            sal_uInt16 nSectCount = rSh.GetSectionFormatCount();
            OUString sTempSectionName(sSectionName);
            sal_uInt16 nAddNumber = 0;
            sal_uInt16 nCount = 0;
            // if applicable: add index if the range name is already in use.
            while ( nCount < nSectCount )
            {
                const SwSectionFormat& rFormat = rSh.GetSectionFormat(nCount);
                if ((rFormat.GetSection()->GetSectionName() == sTempSectionName)
                    && rFormat.IsInNodesArr())
                {
                    nCount = 0;
                    nAddNumber++;
                    sTempSectionName = sSectionName + ":" + OUString::number( nAddNumber );
                }
                else
                    nCount++;
            }

            if ( nAddNumber )
                sSectionName = sTempSectionName;

            SwSectionData aSectionData(CONTENT_SECTION, sSectionName);
            aSectionData.SetProtectFlag(true);
            aSectionData.SetHidden(false);

            aSectionData.SetLinkFileName(sFileName);
            aSectionData.SetType(FILE_LINK_SECTION);
            aSectionData.SetLinkFilePassword( OUString() );

            rSh.InsertGlobalDocContent( *pAnchorContent, aSectionData );
        }
        if ( bMove )
        {
            Update( false );
            rSh.MoveGlobalDocContent(
                *m_pSwGlblDocContents, nEntryCount, nEntryCount + nFiles, nEntryCount - nFiles );
        }
        rSh.EndAction();
        Update( false );
        Display();

    }

    IMPL_LINK( SwGlobalTree, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
    {
        if ( ERRCODE_NONE != _pFileDlg->GetError() )
            return;

        std::unique_ptr<SfxMediumList> pMedList(m_pDocInserter->CreateMediumList());
        if ( pMedList )
        {
            Sequence< OUString >aFileNames( pMedList->size() );
            OUString* pFileNames = aFileNames.getArray();
            sal_Int32 nPos = 0;
            for (SfxMedium* pMed : *pMedList)
            {
                OUString sFileName = pMed->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE )
                    + OUStringLiteral1(sfx2::cTokenSeparator)
                    + pMed->GetFilter()->GetFilterName()
                    + OUStringLiteral1(sfx2::cTokenSeparator);
                pFileNames[nPos++] = sFileName;
            }
            pMedList.reset();
            InsertRegion( m_pDocContent, aFileNames );
            DELETEZ( m_pDocContent );
        }
    }

    /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

↑ V547 Expression '0 != nSource' is always true.