    /* -*- 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 "baside2.hxx"
    #include <baside3.hxx>
    #include "brkdlg.hxx"
    #include <iderdll.hxx>
    #include "moduldlg.hxx"
    #include <docsignature.hxx>
    #include <officecfg/Office/BasicIDE.hxx>

    #include <helpids.h>
    #include <strings.hrc>

    #include <basic/basmgr.hxx>
    #include <basic/basrdll.hxx>
    #include <basic/sbmeth.hxx>
    #include <com/sun/star/script/ModuleType.hpp>
    #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
    #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
    #include <com/sun/star/ui/dialogs/FilePicker.hpp>
    #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
    #include <comphelper/string.hxx>
    #include <sfx2/dinfdlg.hxx>
    #include <sfx2/dispatch.hxx>
    #include <sfx2/docfile.hxx>
    #include <sfx2/printer.hxx>
    #include <sfx2/request.hxx>
    #include <sot/exchange.hxx>
    #include <svl/aeitem.hxx>
    #include <svl/srchitem.hxx>
    #include <svl/visitem.hxx>
    #include <svl/whiter.hxx>
    #include <svx/svxids.hrc>
    #include <vcl/settings.hxx>
    #include <vcl/weld.hxx>
    #include <vcl/xtextedt.hxx>
    #include <toolkit/helper/vclunohelper.hxx>
    #include <cassert>

    namespace basctl
    {

    namespace
    {

    namespace Print
    {
        long const nLeftMargin = 1700;
        long const nRightMargin = 900;
        long const nTopMargin = 2000;
        long const nBottomMargin = 1000;
        long const nBorder = 300;
    }

    short const ValidWindow = 0x1234;

    // What (who) are OW and MTF? Compare to baside3.cxx where an
    // identically named variable, used in the same way, has the value
    // "*.*" on Windows, "*" otherwise. Is that what should be done here,
    // too?

    #if defined(OW) || defined(MTF)
    char const FilterMask_All[] = "*";
    #else
    char const FilterMask_All[] = "*.*";
    #endif

    } // end anonymous namespace

    using namespace ::com::sun::star;
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::ui::dialogs;
    using namespace utl;
    using namespace comphelper;

    namespace
    {

    void lcl_PrintHeader( Printer* pPrinter, sal_uInt16 nPages, sal_uInt16 nCurPage, const OUString& rTitle, bool bOutput )
    {
        Size const aSz = pPrinter->GetOutputSize();

        const Color aOldLineColor( pPrinter->GetLineColor() );
        const Color aOldFillColor( pPrinter->GetFillColor() );
        const vcl::Font aOldFont( pPrinter->GetFont() );

        pPrinter->SetLineColor( COL_BLACK );
        pPrinter->SetFillColor();

        vcl::Font aFont( aOldFont );
        aFont.SetWeight( WEIGHT_BOLD );
        aFont.SetAlignment( ALIGN_BOTTOM );
        pPrinter->SetFont( aFont );

        long nFontHeight = pPrinter->GetTextHeight();

        // 1st Border => line, 2+3 Border = free space
        long nYTop = Print::nTopMargin - 3*Print::nBorder - nFontHeight;

        long nXLeft = Print::nLeftMargin - Print::nBorder;
        long nXRight = aSz.Width() - Print::nRightMargin + Print::nBorder;

        if( bOutput )
            pPrinter->DrawRect(tools::Rectangle(
                Point(nXLeft, nYTop),
                Size(nXRight - nXLeft, aSz.Height() - nYTop - Print::nBottomMargin + Print::nBorder)
            ));

        long nY = Print::nTopMargin - 2*Print::nBorder;
        Point aPos(Print::nLeftMargin, nY);
        if( bOutput )
            pPrinter->DrawText( aPos, rTitle );
        if ( nPages != 1 )
        {
            aFont.SetWeight( WEIGHT_NORMAL );
            pPrinter->SetFont( aFont );
            aPos.AdjustX(pPrinter->GetTextWidth( rTitle ) );

            if( bOutput )
            {
                OUString aPageStr = " [" + IDEResId(RID_STR_PAGE) + " " + OUString::number( nCurPage ) + "]";
                pPrinter->DrawText( aPos, aPageStr );
            }
        }

        nY = Print::nTopMargin - Print::nBorder;

        if( bOutput )
            pPrinter->DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) );

        pPrinter->SetFont( aOldFont );
        pPrinter->SetFillColor( aOldFillColor );
        pPrinter->SetLineColor( aOldLineColor );
    }

    void lcl_ConvertTabsToSpaces( OUString& rLine )
    {
        if ( !rLine.isEmpty() )
        {
            OUStringBuffer aResult( rLine );
            sal_Int32 nPos = 0;
            sal_Int32 nMax = aResult.getLength();
            while ( nPos < nMax )
            {
                if ( aResult[nPos] == '\t' )
                {
                    // not 4 Blanks, but at 4 TabPos:
                    OUStringBuffer aBlanker;
                    string::padToLength(aBlanker, ( 4 - ( nPos % 4 ) ), ' ');
                    aResult.remove( nPos, 1 );
                    aResult.insert( nPos, aBlanker.makeStringAndClear() );
                    nMax = aResult.getLength();
                }
                ++nPos;
            }
            rLine = aResult.makeStringAndClear();
        }
    }

    } // namespace

    ModulWindow::ModulWindow (ModulWindowLayout* pParent, ScriptDocument const& rDocument,
                              const OUString& aLibName, const OUString& aName, OUString const & aModule)
        : BaseWindow(pParent, rDocument, aLibName, aName)
        , m_rLayout(*pParent)
        , m_nValid(ValidWindow)
        , m_aXEditorWindow(VclPtr<ComplexEditorWindow>::Create(this))
        , m_aModule(aModule)
    {
        m_aXEditorWindow->Show();
        SetBackground();
    }

    SbModuleRef const & ModulWindow::XModule()
    {
        // ModuleWindows can now be created as a result of the
        // modules getting created via the api. This is a result of an
        // elementInserted event from the BasicLibrary container.
        // However the SbModule is also created from a different listener to
        // the same event ( in basmgr ) Therefore it is possible when we look
        // for m_xModule it may not yet be available, here we keep trying to access
        // the module until such time as it exists

        if ( !m_xModule.is() )
        {
            BasicManager* pBasMgr = GetDocument().getBasicManager();
            if ( pBasMgr )
            {
                StarBASIC* pBasic = pBasMgr->GetLib( GetLibName() );
                if ( pBasic )
                {
                    m_xBasic = pBasic;
                    m_xModule = pBasic->FindModule( GetName() );
                }
            }
        }
        return m_xModule;
    }

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

    void ModulWindow::dispose()
    {
        m_nValid = 0;
        StarBASIC::Stop();
        m_aXEditorWindow.disposeAndClear();
        BaseWindow::dispose();
    }

    void ModulWindow::GetFocus()
    {
        if (m_nValid != ValidWindow)
            return;
        m_aXEditorWindow->GetEdtWindow().GrabFocus();
        // don't call basic calls because focus is somewhere else...
    }

    void ModulWindow::DoInit()
    {
        if (GetVScrollBar())
            GetVScrollBar()->Hide();
        GetHScrollBar()->Show();
        GetEditorWindow().InitScrollBars();
    }

    void ModulWindow::Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle&)
    {
    }

    void ModulWindow::Resize()
    {
        m_aXEditorWindow->SetPosSizePixel( Point( 0, 0 ), GetOutputSizePixel() );
    }

    void ModulWindow::CheckCompileBasic()
    {
        if ( XModule().is() )
        {
            // never compile while running!
            bool const bRunning = StarBASIC::IsRunning();
            bool const bModified = ( !m_xModule->IsCompiled() ||
                ( GetEditEngine() && GetEditEngine()->IsModified() ) );

            if ( !bRunning && bModified )
            {
                bool bDone = false;

                GetShell()->GetViewFrame()->GetWindow().EnterWait();

                if( bModified )
                {
                    AssertValidEditEngine();
                    GetEditorWindow().SetSourceInBasic();
                }

                bool bWasModified = GetBasic()->IsModified();

                bDone = m_xModule->Compile();
                if ( !bWasModified )
                    GetBasic()->SetModified(false);

                if ( bDone )
                {
                    GetBreakPoints().SetBreakPointsInBasic( m_xModule.get() );
                }

                GetShell()->GetViewFrame()->GetWindow().LeaveWait();

                m_aStatus.bError = !bDone;
                m_aStatus.bIsRunning = false;
            }
        }
    }

    void ModulWindow::BasicExecute()
    {
        // #116444# check security settings before macro execution
        ScriptDocument aDocument( GetDocument() );
        if ( aDocument.isDocument() )
        {
            if ( !aDocument.allowMacros() )
            {
                std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
                                                          VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO)));
                xBox->run();
                return;
            }
        }

        CheckCompileBasic();

        if ( XModule().is() && m_xModule->IsCompiled() && !m_aStatus.bError )
        {
            if ( GetBreakPoints().size() )
                m_aStatus.nBasicFlags = m_aStatus.nBasicFlags | BasicDebugFlags::Break;

            if ( !m_aStatus.bIsRunning )
            {
                DBG_ASSERT( m_xModule.is(), "No Module!" );
                AddStatus( BASWIN_RUNNINGBASIC );
                sal_uInt16 nStart, nEnd;
                TextSelection aSel = GetEditView()->GetSelection();
                // Init cursor to top
                const sal_uInt32 nCurMethodStart = aSel.GetStart().GetPara() + 1;
                SbMethod* pMethod = nullptr;
                // first Macro, else blind "Main" (ExtSearch?)
                for ( sal_uInt16 nMacro = 0; nMacro < m_xModule->GetMethods()->Count(); nMacro++ )
                {
                    SbMethod* pM = static_cast<SbMethod*>(m_xModule->GetMethods()->Get( nMacro ));
                    assert(pM && "Method?");
                    pM->GetLineRange( nStart, nEnd );
                    if (  nCurMethodStart >= nStart && nCurMethodStart <= nEnd )
                    {
                        // matched a method to the cursor position
                        pMethod = pM;
                        break;
                    }
                }
                if ( !pMethod )
                {
                    // If not in a method then prompt the user
                    ChooseMacro( uno::Reference< frame::XModel >() );
                    return;
                }
                if ( pMethod )
                {
                    pMethod->SetDebugFlags( m_aStatus.nBasicFlags );
                    BasicDLL::SetDebugMode( true );
                    RunMethod( pMethod );
                    BasicDLL::SetDebugMode( false );
                    // if cancelled during Interactive=false
                    BasicDLL::EnableBreak( true );
                }
                ClearStatus( BASWIN_RUNNINGBASIC );
            }
            else
                m_aStatus.bIsRunning = false; // cancel of Reschedule()
        }
    }

    void ModulWindow::CompileBasic()
    {
        CheckCompileBasic();

        XModule().is() && m_xModule->IsCompiled();
    }

    void ModulWindow::BasicRun()
    {
        m_aStatus.nBasicFlags = BasicDebugFlags::NONE;
        BasicExecute();
    }

    void ModulWindow::BasicStepOver()
    {
        m_aStatus.nBasicFlags = BasicDebugFlags::StepInto | BasicDebugFlags::StepOver;
        BasicExecute();
    }

    void ModulWindow::BasicStepInto()
    {
        m_aStatus.nBasicFlags = BasicDebugFlags::StepInto;
        BasicExecute();
    }

    void ModulWindow::BasicStepOut()
    {
        m_aStatus.nBasicFlags = BasicDebugFlags::StepOut;
        BasicExecute();
    }

    void ModulWindow::BasicStop()
    {
        StarBASIC::Stop();
        m_aStatus.bIsRunning = false;
    }

    void ModulWindow::LoadBasic()
    {
        Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
        Reference < XFilePicker3 > xFP = FilePicker::createWithMode(xContext, TemplateDescription::FILEOPEN_SIMPLE);

        if ( !m_sCurPath.isEmpty() )
            xFP->setDisplayDirectory ( m_sCurPath );

        xFP->appendFilter( "BASIC" , "*.bas" );
        xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
        xFP->setCurrentFilter( "BASIC" );

        if( xFP->execute() == RET_OK )
        {
            Sequence< OUString > aPaths = xFP->getSelectedFiles();
            m_sCurPath = aPaths[0];
            SfxMedium aMedium( m_sCurPath, StreamMode::READ | StreamMode::SHARE_DENYWRITE | StreamMode::NOCREATE );
            SvStream* pStream = aMedium.GetInStream();
            if ( pStream )
            {
                AssertValidEditEngine();
                sal_uInt32 nLines = CalcLineCount( *pStream );
                // nLines*4: ReadText/Formatting/Highlighting/Formatting
                GetEditorWindow().CreateProgress( IDEResId(RID_STR_GENERATESOURCE), nLines*4 );
                GetEditEngine()->SetUpdateMode( false );
                GetEditView()->Read( *pStream );
                GetEditEngine()->SetUpdateMode( true );
                GetEditorWindow().Update();
                GetEditorWindow().ForceSyntaxTimeout();
                GetEditorWindow().DestroyProgress();
                ErrCode nError = aMedium.GetError();
                if ( nError )
                    ErrorHandler::HandleError( nError );
            }
            else
            {
                std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
                                                          VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTREAD)));
                xBox->run();
            }
        }
    }

    void ModulWindow::SaveBasicSource()
    {
        Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
        Reference < XFilePicker3 > xFP = FilePicker::createWithMode(xContext, TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD);

        Reference< XFilePickerControlAccess > xFPControl(xFP, UNO_QUERY);
        xFPControl->enableControl(ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, false);
        Any aValue;
        aValue <<= true;
        xFPControl->setValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue);

        if ( !m_sCurPath.isEmpty() )
            xFP->setDisplayDirectory ( m_sCurPath );

        xFP->appendFilter( "BASIC", "*.bas" );
        xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
        xFP->setCurrentFilter( "BASIC" );

        if( xFP->execute() == RET_OK )
        {
            Sequence< OUString > aPaths = xFP->getSelectedFiles();
            m_sCurPath = aPaths[0];
            SfxMedium aMedium( m_sCurPath, StreamMode::WRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC );
            SvStream* pStream = aMedium.GetOutStream();
            if ( pStream )
            {
                EnterWait();
                AssertValidEditEngine();
                GetEditEngine()->Write( *pStream );
                aMedium.Commit();
                LeaveWait();
                ErrCode nError = aMedium.GetError();
                if ( nError )
                    ErrorHandler::HandleError( nError );
            }
            else
            {
                std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(GetFrameWeld(),
                                                               VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTWRITE)));
                xErrorBox->run();
            }
        }
    }

    void ModulWindow::ImportDialog()
    {
        const ScriptDocument& rDocument = GetDocument();
        OUString aLibName = GetLibName();
        implImportDialog(GetFrameWeld(), m_sCurPath, rDocument, aLibName);
    }

    void ModulWindow::ToggleBreakPoint( sal_uLong nLine )
    {
        DBG_ASSERT( XModule().is(), "No Module!" );

        if ( XModule().is() )
        {
            CheckCompileBasic();
            if ( m_aStatus.bError )
            {
                return;
            }

            BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nLine );
            if ( pBrk ) // remove
            {
                m_xModule->ClearBP( static_cast<sal_uInt16>(nLine) );
                GetBreakPoints().remove( pBrk );
            }
            else // create one
            {
                if ( m_xModule->SetBP( static_cast<sal_uInt16>(nLine)) )
                {
                    GetBreakPoints().InsertSorted( BreakPoint( nLine ) );
                    if ( StarBASIC::IsRunning() )
                    {
                        for ( sal_uInt16 nMethod = 0; nMethod < m_xModule->GetMethods()->Count(); nMethod++ )
                        {
                            SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->GetMethods()->Get( nMethod ));
                            assert(pMethod && "Method not found! (NULL)");
                            pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
                        }
                    }
                }
            }
        }
    }

    void ModulWindow::UpdateBreakPoint( const BreakPoint& rBrk )
    {
        DBG_ASSERT( XModule().is(), "No Module!" );

        if ( XModule().is() )
        {
            CheckCompileBasic();

            if ( rBrk.bEnabled )
                m_xModule->SetBP( rBrk.nLine );
            else
                m_xModule->ClearBP( rBrk.nLine );
        }
    }

    void ModulWindow::BasicToggleBreakPoint()
    {
        AssertValidEditEngine();

        TextSelection aSel = GetEditView()->GetSelection();
        aSel.GetStart().GetPara()++;    // Basic lines start at 1!
        aSel.GetEnd().GetPara()++;

        for ( sal_uInt32 nLine = aSel.GetStart().GetPara(); nLine <= aSel.GetEnd().GetPara(); ++nLine )
        {
            ToggleBreakPoint( nLine );
        }

        m_aXEditorWindow->GetBrkWindow().Invalidate();
    }

    void ModulWindow::BasicToggleBreakPointEnabled()
    {
        AssertValidEditEngine();

        TextView* pView = GetEditView();
        if ( pView )
        {
            TextSelection aSel = pView->GetSelection();
            BreakPointList& rList = GetBreakPoints();

            for ( sal_uInt32 nLine = ++aSel.GetStart().GetPara(), nEnd = ++aSel.GetEnd().GetPara(); nLine <= nEnd; ++nLine )
            {
                BreakPoint* pBrk = rList.FindBreakPoint( nLine );
                if ( pBrk )
                {
                    pBrk->bEnabled = !pBrk->bEnabled;
                    UpdateBreakPoint( *pBrk );
                }
            }

            GetBreakPointWindow().Invalidate();
        }
    }

    void ModulWindow::ManageBreakPoints()
    {
        BreakPointWindow& rBrkWin = GetBreakPointWindow();
        ScopedVclPtrInstance< BreakPointDialog > aBrkDlg( &rBrkWin, GetBreakPoints() );
        aBrkDlg->Execute();
        rBrkWin.Invalidate();
    }

    bool ModulWindow::BasicErrorHdl( StarBASIC const * pBasic )
    {
        GetShell()->GetViewFrame()->ToTop();

        // Return value: BOOL
        //  FALSE:  cancel
        //  TRUE:   go on....
        sal_uInt16 nErrorLine = StarBASIC::GetLine() - 1;
        sal_uInt16 nErrCol1 = StarBASIC::GetCol1();
        sal_uInt16 nErrCol2 = StarBASIC::GetCol2();
        if ( nErrCol2 != 0xFFFF )
            nErrCol2++;

        AssertValidEditEngine();
        GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, nErrCol1 ), TextPaM( nErrorLine, nErrCol2 ) ) );

        // if other basic, the IDE should try to display the correct module
        bool const bMarkError = pBasic == GetBasic();
        if ( bMarkError )
            m_aXEditorWindow->GetBrkWindow().SetMarkerPos(nErrorLine, true);

        // #i47002#
        Reference< awt::XWindow > xWindow = VCLUnoHelper::GetInterface( this );

        // tdf#118572 make a currently running dialog, regardless of what its modal
        // to, insensitive to user input until after this error dialog goes away.
        auto xDialog = Dialog::GetMostRecentExecutingDialog();
        const bool bToggleEnableInput = xDialog && xDialog->IsInputEnabled();
        if (bToggleEnableInput)
            xDialog->EnableInput(false);
        ErrorHandler::HandleError(StarBASIC::GetErrorCode(), GetFrameWeld());
        if (bToggleEnableInput)
            xDialog->EnableInput(true);

        // #i47002#
        VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
        if ( !pWindow )
            return false;

        if ( bMarkError )
            m_aXEditorWindow->GetBrkWindow().SetNoMarker();
        return false;
    }

    BasicDebugFlags ModulWindow::BasicBreakHdl()
    {
        // Return value: sal_uInt16 => see SB-Debug-Flags
        sal_uInt16 nErrorLine = StarBASIC::GetLine();

        BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nErrorLine );
        if ( pBrk )
        {
            pBrk->nHitCount++;
            if ( pBrk->nHitCount <= pBrk->nStopAfter && GetBasic()->IsBreak() )
                return m_aStatus.nBasicFlags; // go on...
        }

        nErrorLine--;   // EditEngine starts at 0, Basic at 1

        AssertValidEditEngine();
        GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, 0 ), TextPaM( nErrorLine, 0 ) ) );
        m_aXEditorWindow->GetBrkWindow().SetMarkerPos( nErrorLine );

        m_rLayout.UpdateDebug(false);

        m_aStatus.bIsInReschedule = true;
        m_aStatus.bIsRunning = true;

        AddStatus( BASWIN_INRESCHEDULE );

        InvalidateDebuggerSlots();

        while( m_aStatus.bIsRunning )
            Application::Yield();

        m_aStatus.bIsInReschedule = false;
        m_aXEditorWindow->GetBrkWindow().SetNoMarker();

        ClearStatus( BASWIN_INRESCHEDULE );

        return m_aStatus.nBasicFlags;
    }

    void ModulWindow::BasicAddWatch()
    {
        AssertValidEditEngine();
        bool bAdd = true;
        if ( !GetEditView()->HasSelection() )
        {
            TextPaM aWordStart;
            OUString aWord = GetEditEngine()->GetWord( GetEditView()->GetSelection().GetEnd(), &aWordStart );
            if ( !aWord.isEmpty() )
            {
                TextSelection aSel( aWordStart );
                aSel.GetEnd().GetIndex() += aWord.getLength();
                GetEditView()->SetSelection( aSel );
            }
            else
                bAdd = false;
        }
        if ( bAdd )
        {
            TextSelection aSel = GetEditView()->GetSelection();
            if ( aSel.GetStart().GetPara() == aSel.GetEnd().GetPara() ) // single line selection
                m_rLayout.BasicAddWatch(GetEditView()->GetSelected());
        }
    }

    void ModulWindow::EditMacro( const OUString& rMacroName )
    {
        DBG_ASSERT( XModule().is(), "No Module!" );

        if ( XModule().is() )
        {
            CheckCompileBasic();

            if ( !m_aStatus.bError )
            {
                sal_uInt16 nStart, nEnd;
                SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->Find( rMacroName, SbxClassType::Method ));
                if ( pMethod )
                {
                    pMethod->GetLineRange( nStart, nEnd );
                    if ( nStart )
                    {
                        nStart--;
                        nEnd--;
                    }
                    TextSelection aSel( TextPaM( nStart, 0 ), TextPaM( nStart, 0 ) );
                    AssertValidEditEngine();
                    TextView * pView = GetEditView();
                    // scroll if applicable so that first line is at the top
                    long nVisHeight = GetOutputSizePixel().Height();
                    if ( pView->GetTextEngine()->GetTextHeight() > nVisHeight )
                    {
                        long nMaxY = pView->GetTextEngine()->GetTextHeight() - nVisHeight;
                        long nOldStartY = pView->GetStartDocPos().Y();
                        long nNewStartY = static_cast<long>(nStart) * pView->GetTextEngine()->GetCharHeight();
                        nNewStartY = std::min( nNewStartY, nMaxY );
                        pView->Scroll( 0, -(nNewStartY-nOldStartY) );
                        pView->ShowCursor( false );
                        GetEditVScrollBar().SetThumbPos( pView->GetStartDocPos().Y() );
                    }
                    pView->SetSelection( aSel );
                    pView->ShowCursor();
                    pView->GetWindow()->GrabFocus();
                }
            }
        }
    }

    void ModulWindow::StoreData()
    {
        // StoreData is called when the BasicManager is destroyed or
        // this window is closed.
        // => interrupts undesired!
        GetEditorWindow().SetSourceInBasic();
    }

    bool ModulWindow::CanClose()
    {
        return true;
    }

    bool ModulWindow::AllowUndo()
    {
        return GetEditorWindow().CanModify();
    }

    void ModulWindow::UpdateData()
    {
        DBG_ASSERT( XModule().is(), "No Module!" );
        // UpdateData is called when the source has changed from outside
        // => interrupts undesired!

        if ( XModule().is() )
        {
            SetModule( m_xModule->GetSource32() );

            if ( GetEditView() )
            {
                TextSelection aSel = GetEditView()->GetSelection();
                setTextEngineText(*GetEditEngine(), m_xModule->GetSource32());
                GetEditView()->SetSelection( aSel );
                GetEditEngine()->SetModified( false );
                MarkDocumentModified( GetDocument() );
            }
        }
    }

    sal_Int32 ModulWindow::countPages( Printer* pPrinter )
    {
        return FormatAndPrint( pPrinter, -1 );
    }

    void ModulWindow::printPage( sal_Int32 nPage, Printer* pPrinter )
    {
        FormatAndPrint( pPrinter, nPage );
    }

    /* implementation note: this is totally inefficient for the XRenderable interface
       usage since the whole "document" will be format for every page. Should this ever
       become a problem we should
       - format only once for every new printer
       - keep an index list for each page which is the starting paragraph
    */
    sal_Int32 ModulWindow::FormatAndPrint( Printer* pPrinter, sal_Int32 nPrintPage )
    {
        AssertValidEditEngine();

        MapMode eOldMapMode( pPrinter->GetMapMode() );
        vcl::Font aOldFont( pPrinter->GetFont() );

        vcl::Font aFont( GetEditEngine()->GetFont() );
        aFont.SetAlignment( ALIGN_BOTTOM );
        aFont.SetTransparent( true );
        aFont.SetFontSize( Size( 0, 360 ) );
        pPrinter->SetFont( aFont );
        pPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));

        OUString aTitle( CreateQualifiedName() );

        sal_Int32 nLineHeight = pPrinter->GetTextHeight();
        if(nLineHeight == 0)
        {
            nLineHeight = 1;
        }

        Size aPaperSz = pPrinter->GetOutputSize();
        aPaperSz.AdjustWidth( -(Print::nLeftMargin + Print::nRightMargin) );
        aPaperSz.AdjustHeight( -(Print::nTopMargin + Print::nBottomMargin) );

        // nLinepPage is not correct if there's a line break
        sal_Int32 nLinespPage = aPaperSz.Height()/nLineHeight;
        long nXTextWidth = pPrinter->approximate_char_width();

        sal_Int32 nCharspLine = aPaperSz.Width() / std::max<long>(nXTextWidth, 1);
        const sal_uInt32 nParas = GetEditEngine()->GetParagraphCount();

        sal_Int32 nPages = nParas/nLinespPage+1;
        sal_Int32 nCurPage = 1;

        lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nPrintPage == 0 );
        Point aPos( Print::nLeftMargin, Print::nTopMargin );
        for ( sal_uInt32 nPara = 0; nPara < nParas; ++nPara )
        {
            OUString aLine( GetEditEngine()->GetText( nPara ) );
            lcl_ConvertTabsToSpaces( aLine );
            sal_Int32 nLines = aLine.getLength()/nCharspLine+1;
            for (sal_Int32 nLine = 0; nLine < nLines; ++nLine)
            {
                sal_Int32 nBeginIndex = nLine*nCharspLine;
                sal_Int32 nCopyCount = std::min<sal_Int32>(nCharspLine, aLine.getLength()-nBeginIndex);
                OUString aTmpLine = aLine.copy(nBeginIndex, nCopyCount);
                aPos.AdjustY(nLineHeight );
                if ( aPos.Y() > ( aPaperSz.Height() + Print::nTopMargin ) )
                {
                    nCurPage++;
                    lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nCurPage-1 == nPrintPage );
                    aPos = Point(Print::nLeftMargin, Print::nTopMargin + nLineHeight);
                }
                if( nCurPage-1 == nPrintPage )
                    pPrinter->DrawText( aPos, aTmpLine );
            }
            aPos.AdjustY(10 ); // nParaSpace
        }

        pPrinter->SetFont( aOldFont );
        pPrinter->SetMapMode( eOldMapMode );

        return nCurPage;
    }

    void ModulWindow::ExecuteCommand (SfxRequest& rReq)
    {
        AssertValidEditEngine();
        switch (rReq.GetSlot())
        {
            case SID_DELETE:
            {
                if (!IsReadOnly())
                {
                    KeyEvent aFakeDelete(0, KEY_DELETE);
                    (void)GetEditView()->KeyInput(aFakeDelete);
                }
                break;
            }
            case SID_SELECTALL:
            {
                TextSelection aSel( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) );
                TextView * pView = GetEditView();
                pView->SetSelection( aSel );
                pView->GetWindow()->GrabFocus();
                break;
            }
            case SID_BASICRUN:
            {
                BasicRun();
            }
            break;
            case SID_BASICCOMPILE:
            {
                CompileBasic();
            }
            break;
            case SID_BASICSTEPOVER:
            {
                BasicStepOver();
            }
            break;
            case SID_BASICSTEPINTO:
            {
                BasicStepInto();
            }
            break;
            case SID_BASICSTEPOUT:
            {
                BasicStepOut();
            }
            break;
            case SID_BASICLOAD:
            {
                LoadBasic();
            }
            break;
            case SID_BASICSAVEAS:
            {
                SaveBasicSource();
            }
            break;
            case SID_IMPORT_DIALOG:
            {
                ImportDialog();
            }
            break;
            case SID_BASICIDE_MATCHGROUP:
            {
                GetEditView()->MatchGroup();
            }
            break;
            case SID_BASICIDE_TOGGLEBRKPNT:
            {
                BasicToggleBreakPoint();
            }
            break;
            case SID_BASICIDE_MANAGEBRKPNTS:
            {
                ManageBreakPoints();
            }
            break;
            case SID_BASICIDE_TOGGLEBRKPNTENABLED:
            {
                BasicToggleBreakPointEnabled();
            }
            break;
            case SID_BASICIDE_ADDWATCH:
            {
                BasicAddWatch();
            }
            break;
            case SID_BASICIDE_REMOVEWATCH:
            {
                m_rLayout.BasicRemoveWatch();
            }
            break;
            case SID_CUT:
            {
                if ( !IsReadOnly() )
                {
                    GetEditView()->Cut();
                    if (SfxBindings* pBindings = GetBindingsPtr())
                        pBindings->Invalidate( SID_DOC_MODIFIED );
                }
            }
            break;
            case SID_COPY:
            {
                GetEditView()->Copy();
            }
            break;
            case SID_PASTE:
            {
                if ( !IsReadOnly() )
                {
                    GetEditView()->Paste();
                    if (SfxBindings* pBindings = GetBindingsPtr())
                        pBindings->Invalidate( SID_DOC_MODIFIED );
                }
            }
            break;
            case SID_BASICIDE_BRKPNTSCHANGED:
            {
                GetBreakPointWindow().Invalidate();
            }
            break;
            case SID_SHOWLINES:
            {
                const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
                bool bLineNumbers = pItem && pItem->GetValue();
                m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);

                std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
                officecfg::Office::BasicIDE::EditorSettings::LineNumbering::set(bLineNumbers, batch);
                batch->commit();
            }
            break;
            case SID_BASICIDE_DELETECURRENT:
            {
                if (QueryDelModule(m_aName, GetFrameWeld()))
                    if (m_aDocument.removeModule(m_aLibName, m_aName))
                        MarkDocumentModified(m_aDocument);
            }
            break;
            case FID_SEARCH_OFF:
                GrabFocus();
                break;
            case SID_GOTOLINE:
            {
                GotoLineDialog aGotoDlg(GetFrameWeld());
                if (aGotoDlg.run() == RET_OK)
                {
                    if (sal_Int32 const nLine = aGotoDlg.GetLineNumber())
                    {
                        TextSelection const aSel(TextPaM(nLine - 1, 0), TextPaM(nLine - 1, 0));
                        GetEditView()->SetSelection(aSel);
                    }
                }
                break;
            }
        }
    }

    void ModulWindow::ExecuteGlobal (SfxRequest& rReq)
    {
        switch (rReq.GetSlot())
        {
            case SID_SIGNATURE:
            {
                DocumentSignature aSignature(m_aDocument);
                if (aSignature.supportsSignatures())
                {
                    aSignature.signScriptingContent(rReq.GetFrameWeld());
                    if (SfxBindings* pBindings = GetBindingsPtr())
                        pBindings->Invalidate(SID_SIGNATURE);
                }
            }
            break;
        }
    }

    void ModulWindow::GetState( SfxItemSet &rSet )
    {
        SfxWhichIter aIter(rSet);
        for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh != 0; nWh = aIter.NextWhich() )
        {
            switch ( nWh )
            {
                case SID_CUT:
                {
                    if ( !GetEditView() || !GetEditView()->HasSelection() )
                        rSet.DisableItem( nWh );

                    if ( IsReadOnly() )
                        rSet.DisableItem( nWh );
                }
                break;
                case SID_COPY:
                {
                    if ( !GetEditView() || !GetEditView()->HasSelection() )
                        rSet.DisableItem( nWh );
                }
                break;
                case SID_PASTE:
                {
                    if ( !IsPasteAllowed() )
                        rSet.DisableItem( nWh );

                    if ( IsReadOnly() )
                        rSet.DisableItem( nWh );
                }
                break;
                case SID_BASICIDE_STAT_POS:
                {
                    TextView* pView = GetEditView();
                    if ( pView )
                    {
                        TextSelection aSel = pView->GetSelection();
                        OUString aPos = IDEResId( RID_STR_LINE ) +
                                       " " +
                                       OUString::number(aSel.GetEnd().GetPara()+1) +
                                       ", " +
                                       IDEResId( RID_STR_COLUMN ) +
                                       " " +
                                       OUString::number(aSel.GetEnd().GetIndex()+1);
                        SfxStringItem aItem( SID_BASICIDE_STAT_POS, aPos );
                        rSet.Put( aItem );
                    }
                }
                break;
                case SID_BASICIDE_STAT_TITLE:
                {
                    // search for current procedure name (Sub or Function)
                    TextView* pView = GetEditView();
                    if ( pView )
                    {
                        OUString sProcName;

                        TextSelection aSel = pView->GetSelection();

                        sal_uInt32 i = aSel.GetStart().GetPara();
                        do
                        {
                            OUString aCurrLine = GetEditEngine()->GetText( i );
                            OUString sProcType;
                            if (GetEditorWindow().GetProcedureName(aCurrLine, sProcType, sProcName))
                                break;
                        } while (i--);

                        OUString aTitle = CreateQualifiedName();
                        if (!sProcName.isEmpty())
                            aTitle += "." + sProcName;

                        SfxStringItem aTitleItem( SID_BASICIDE_STAT_TITLE, aTitle );
                        rSet.Put( aTitleItem );
                    }
                }
                break;
                case SID_ATTR_INSERT:
                {
                    TextView* pView = GetEditView();
                    if ( pView )
                    {
                        SfxBoolItem aItem( SID_ATTR_INSERT, pView->IsInsertMode() );
                        rSet.Put( aItem );
                    }
                }
                break;
                case SID_SHOWLINES:
                {
                    bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
                    rSet.Put(SfxBoolItem(nWh, bLineNumbers));
                    break;
                }
                case SID_SELECTALL:
                {
                    if ( !GetEditView() )
                        rSet.DisableItem( nWh );
                }
                break;
            }
        }
    }

    void ModulWindow::DoScroll( ScrollBar* pCurScrollBar )
    {
        if ( ( pCurScrollBar == GetHScrollBar() ) && GetEditView() )
        {
            // don't scroll with the value but rather use the Thumb-Pos for the VisArea:
            long nDiff = GetEditView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
            GetEditView()->Scroll( nDiff, 0 );
            GetEditView()->ShowCursor( false );
            pCurScrollBar->SetThumbPos( GetEditView()->GetStartDocPos().X() );

        }
    }

    bool ModulWindow::IsModified()
    {
        return GetEditEngine() && GetEditEngine()->IsModified();
    }

    OUString ModulWindow::GetSbModuleName()
    {
        OUString aModuleName;
        if ( XModule().is() )
            aModuleName = m_xModule->GetName();
        return aModuleName;
    }

    OUString ModulWindow::GetTitle()
    {
        return GetSbModuleName();
    }

    void ModulWindow::ShowCursor( bool bOn )
    {
        if ( GetEditEngine() )
        {
            TextView* pView = GetEditEngine()->GetActiveView();
            if ( pView )
            {
                if ( bOn )
                    pView->ShowCursor();
                else
                    pView->HideCursor();
            }
        }
    }

    void ModulWindow::AssertValidEditEngine()
    {
        if ( !GetEditEngine() )
            GetEditorWindow().CreateEditEngine();
    }

    void ModulWindow::Activating ()
    {
        bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
        m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
        Show();
    }

    void ModulWindow::Deactivating()
    {
        Hide();
    }

    sal_uInt16 ModulWindow::StartSearchAndReplace( const SvxSearchItem& rSearchItem, bool bFromStart )
    {
        if (IsSuspended())
            return 0;

        // one could also relinquish syntaxhighlighting/formatting instead of the stupid replace-everything...
        AssertValidEditEngine();
        TextView* pView = GetEditView();
        TextSelection aSel;
        if ( bFromStart )
        {
            aSel = pView->GetSelection();
            if ( !rSearchItem.GetBackward() )
                pView->SetSelection( TextSelection() );
            else
                pView->SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
        }

        bool const bForward = !rSearchItem.GetBackward();
        sal_uInt16 nFound = 0;
        if ( ( rSearchItem.GetCommand() == SvxSearchCmd::FIND ) ||
             ( rSearchItem.GetCommand() == SvxSearchCmd::FIND_ALL ) )
        {
            nFound = pView->Search( rSearchItem.GetSearchOptions() , bForward ) ? 1 : 0;
        }
        else if ( ( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE ) ||
                  ( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL ) )
        {
            if ( !IsReadOnly() )
            {
                bool const bAll = rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL;
                nFound = pView->Replace( rSearchItem.GetSearchOptions() , bAll , bForward );
            }
        }

        if ( bFromStart && !nFound )
            pView->SetSelection( aSel );

        return nFound;
    }

    SfxUndoManager* ModulWindow::GetUndoManager()
    {
        if ( GetEditEngine() )
            return &GetEditEngine()->GetUndoManager();
        return nullptr;
    }

    SearchOptionFlags ModulWindow::GetSearchOptions()
    {
        SearchOptionFlags nOptions = SearchOptionFlags::SEARCH |
                          SearchOptionFlags::WHOLE_WORDS |
                          SearchOptionFlags::BACKWARDS |
                          SearchOptionFlags::REG_EXP |
                          SearchOptionFlags::EXACT |
                          SearchOptionFlags::SELECTION |
                          SearchOptionFlags::SIMILARITY;

        if ( !IsReadOnly() )
        {
            nOptions |= SearchOptionFlags::REPLACE;
            nOptions |= SearchOptionFlags::REPLACE_ALL;
        }

        return nOptions;
    }

    void ModulWindow::BasicStarted()
    {
        if ( XModule().is() )
        {
            m_aStatus.bIsRunning = true;
            BreakPointList& rList = GetBreakPoints();
            if ( rList.size() )
            {
                rList.ResetHitCount();
                rList.SetBreakPointsInBasic( m_xModule.get() );
                for ( sal_uInt16 nMethod = 0; nMethod < m_xModule->GetMethods()->Count(); nMethod++ )
                {
                    SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->GetMethods()->Get( nMethod ));
                    assert(pMethod && "Method not found! (NULL)");
                    pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
                }
            }
        }
    }

    void ModulWindow::BasicStopped()
    {
        m_aStatus.bIsRunning = false;
        GetBreakPointWindow().SetNoMarker();
    }

    EntryDescriptor ModulWindow::CreateEntryDescriptor()
    {
        ScriptDocument aDocument( GetDocument() );
        OUString aLibName( GetLibName() );
        LibraryLocation eLocation = aDocument.getLibraryLocation( aLibName );
        OUString aModName( GetName() );
        OUString aLibSubName;
        if( m_xBasic.is() && aDocument.isInVBAMode() && XModule().is() )
        {
            switch( m_xModule->GetModuleType() )
            {
                case script::ModuleType::DOCUMENT:
                {
                    aLibSubName = IDEResId( RID_STR_DOCUMENT_OBJECTS );
                    uno::Reference< container::XNameContainer > xLib = aDocument.getOrCreateLibrary( E_SCRIPTS, aLibName );
                    if( xLib.is() )
                    {
                        OUString sObjName;
                        ModuleInfoHelper::getObjectName( xLib, aModName, sObjName );
                        if( !sObjName.isEmpty() )
                        {
                            aModName += " (" + sObjName + ")";
                        }
                    }
                    break;
                }
                case script::ModuleType::FORM:
                    aLibSubName = IDEResId( RID_STR_USERFORMS );
                    break;
                case script::ModuleType::NORMAL:
                    aLibSubName = IDEResId( RID_STR_NORMAL_MODULES );
                    break;
                case script::ModuleType::CLASS:
                    aLibSubName = IDEResId( RID_STR_CLASS_MODULES );
                    break;
            }
        }
        return EntryDescriptor( aDocument, eLocation, aLibName, aLibSubName, aModName, OBJ_TYPE_MODULE );
    }

    void ModulWindow::SetReadOnly (bool b)
    {
        if ( GetEditView() )
            GetEditView()->SetReadOnly( b );
    }

    bool ModulWindow::IsReadOnly()
    {
        return GetEditView() && GetEditView()->IsReadOnly();
    }

    bool ModulWindow::IsPasteAllowed()
    {
        bool bPaste = false;

        // get clipboard
        Reference< datatransfer::clipboard::XClipboard > xClipboard = GetClipboard();
        if ( xClipboard.is() )
        {

            Reference< datatransfer::XTransferable > xTransf;
            {
                SolarMutexReleaser aReleaser;
                // get clipboard content
                xTransf = xClipboard->getContents();
            }
            if ( xTransf.is() )
            {
                datatransfer::DataFlavor aFlavor;
                SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
                if ( xTransf->isDataFlavorSupported( aFlavor ) )
                    bPaste = true;
            }
        }

        return bPaste;
    }

    void ModulWindow::OnNewDocument ()
    {
        bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
        m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
    }

    char const* ModulWindow::GetHid () const
    {
        return HID_BASICIDE_MODULWINDOW;
    }
    ItemType ModulWindow::GetType () const
    {
        return TYPE_MODULE;
    }

    bool ModulWindow::HasActiveEditor () const
    {
        return !IsSuspended();
    }

    void ModulWindow::UpdateModule ()
    {
        OUString const aModule = getTextEngineText(*GetEditEngine());

        // update module in basic
        assert(m_xModule.is());

        // update module in module window
        SetModule(aModule);

        // update module in library
        OSL_VERIFY(m_aDocument.updateModule(m_aLibName, m_aName, aModule));

        GetEditEngine()->SetModified(false);
        MarkDocumentModified(m_aDocument);
    }

    ModulWindowLayout::ModulWindowLayout (vcl::Window* pParent, ObjectCatalog& rObjectCatalog_) :
        Layout(pParent),
        pChild(nullptr),
        aWatchWindow(VclPtr<WatchWindow>::Create(this)),
        aStackWindow(VclPtr<StackWindow>::Create(this)),
        rObjectCatalog(rObjectCatalog_)
    { }

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

    void ModulWindowLayout::dispose()
    {
        aWatchWindow.disposeAndClear();
        aStackWindow.disposeAndClear();
        pChild.clear();
        Layout::dispose();
    }

    void ModulWindowLayout::UpdateDebug (bool bBasicStopped)
    {
        aWatchWindow->UpdateWatches(bBasicStopped);
        aStackWindow->UpdateCalls();
    }

    void ModulWindowLayout::Paint (vcl::RenderContext& rRenderContext, tools::Rectangle const&)
    {
        rRenderContext.DrawText(Point(), IDEResId(RID_STR_NOMODULE));
    }

    void ModulWindowLayout::Activating (BaseWindow& rChild)
    {
        assert(dynamic_cast<ModulWindow*>(&rChild));
        pChild = &static_cast<ModulWindow&>(rChild);
        aWatchWindow->Show();
        aStackWindow->Show();
        rObjectCatalog.Show();
        rObjectCatalog.SetLayoutWindow(this);
        rObjectCatalog.UpdateEntries();
        Layout::Activating(rChild);
        aSyntaxColors.SetActiveEditor(&pChild->GetEditorWindow());
    }

    void ModulWindowLayout::Deactivating ()
    {
        aSyntaxColors.SetActiveEditor(nullptr);
        Layout::Deactivating();
        aWatchWindow->Hide();
        aStackWindow->Hide();
        rObjectCatalog.Hide();
        pChild = nullptr;
    }

    void ModulWindowLayout::GetState (SfxItemSet &rSet, unsigned nWhich)
    {
        switch (nWhich)
        {
            case SID_SHOW_PROPERTYBROWSER:
                rSet.Put(SfxVisibilityItem(nWhich, false));
                break;

            case SID_BASICIDE_CHOOSEMACRO:
                rSet.Put(SfxVisibilityItem(nWhich, true));
                break;
        }
    }

    void ModulWindowLayout::BasicAddWatch (OUString const& rWatchStr)
    {
        aWatchWindow->AddWatch(rWatchStr);
    }

    void ModulWindowLayout::BasicRemoveWatch ()
    {
        aWatchWindow->RemoveSelectedWatch();
    }

    void ModulWindowLayout::OnFirstSize (long const nWidth, long const nHeight)
    {
        AddToLeft(&rObjectCatalog, Size(nWidth * 0.20, nHeight * 0.75));
        AddToBottom(aWatchWindow.get(), Size(nWidth * 0.67, nHeight * 0.25));
        AddToBottom(aStackWindow.get(), Size(nWidth * 0.33, nHeight * 0.25));
    }

    ModulWindowLayout::SyntaxColors::SyntaxColors () :
        pEditor(nullptr)
    {
        aConfig.AddListener(this);

        NewConfig(true);
    }

    ModulWindowLayout::SyntaxColors::~SyntaxColors ()
    {
        aConfig.RemoveListener(this);
    }

    // virtual
    void ModulWindowLayout::SyntaxColors::ConfigurationChanged (utl::ConfigurationBroadcaster*, ConfigurationHints)
    {
        NewConfig(false);
    }

    // when a new configuration has to be set
    void ModulWindowLayout::SyntaxColors::NewConfig (bool bFirst)
    {
        static struct
        {
            TokenType eTokenType;
            svtools::ColorConfigEntry eEntry;
        }
        const vIds[] =
        {
            { TokenType::Unknown,     svtools::FONTCOLOR },
            { TokenType::Identifier,  svtools::BASICIDENTIFIER },
            { TokenType::Whitespace,  svtools::FONTCOLOR },
            { TokenType::Number,      svtools::BASICNUMBER },
            { TokenType::String,      svtools::BASICSTRING },
            { TokenType::EOL,         svtools::FONTCOLOR },
            { TokenType::Comment,     svtools::BASICCOMMENT },
            { TokenType::Error,       svtools::BASICERROR },
            { TokenType::Operator,    svtools::BASICOPERATOR },
            { TokenType::Keywords,    svtools::BASICKEYWORD },
        };

        Color aDocColor = aConfig.GetColorValue(svtools::DOCCOLOR).nColor;
        if (bFirst || aDocColor != m_aBackgroundColor)
        {
            m_aBackgroundColor = aDocColor;
            if (!bFirst && pEditor)
            {
                pEditor->SetBackground(Wallpaper(m_aBackgroundColor));
                pEditor->Invalidate();
            }
        }

        Color aFontColor = aConfig.GetColorValue(svtools::FONTCOLOR).nColor;
        if (bFirst || aFontColor != m_aFontColor)
        {
            m_aFontColor = aFontColor;
            if (!bFirst && pEditor)
                pEditor->ChangeFontColor(m_aFontColor);
        }

        bool bChanged = false;
        for (unsigned i = 0; i != SAL_N_ELEMENTS(vIds); ++i)
        {
            Color const aColor = aConfig.GetColorValue(vIds[i].eEntry).nColor;
            Color& rMyColor = aColors[vIds[i].eTokenType];
            if (bFirst || aColor != rMyColor)
            {
                rMyColor = aColor;
                bChanged = true;
            }
        }
        if (bChanged && !bFirst && pEditor)
            pEditor->UpdateSyntaxHighlighting();
    }

    } // namespace basctl

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

↑ V547 Expression 'pMethod' is always true.