summaryrefslogtreecommitdiffstats
path: root/basctl/source/basicide/baside2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'basctl/source/basicide/baside2.cxx')
-rw-r--r--basctl/source/basicide/baside2.cxx1603
1 files changed, 1603 insertions, 0 deletions
diff --git a/basctl/source/basicide/baside2.cxx b/basctl/source/basicide/baside2.cxx
new file mode 100644
index 000000000..f73c70ef7
--- /dev/null
+++ b/basctl/source/basicide/baside2.cxx
@@ -0,0 +1,1603 @@
+/* -*- 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 <basobj.hxx>
+#include <basidesh.hxx>
+#include "brkdlg.hxx"
+#include <iderdll.hxx>
+#include <iderid.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/datatransfer/clipboard/XClipboard.hpp>
+#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/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <comphelper/SetFlagContextHelper.hxx>
+#include <comphelper/string.hxx>
+#include <svl/srchdefs.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sot/exchange.hxx>
+#include <svl/eitem.hxx>
+#include <svl/srchitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/visitem.hxx>
+#include <svl/whiter.hxx>
+#include <svx/svxids.hrc>
+#include <tools/debug.hxx>
+#include <utility>
+#include <vcl/locktoplevels.hxx>
+#include <vcl/errinf.hxx>
+#include <vcl/event.hxx>
+#include <vcl/print.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/textview.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/xtextedt.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <cassert>
+#include <osl/diagnose.h>
+#include <officecfg/Office/Common.hxx>
+
+namespace basctl
+{
+
+namespace
+{
+
+namespace Print
+{
+ tools::Long const nLeftMargin = 1700;
+ tools::Long const nRightMargin = 900;
+ tools::Long const nTopMargin = 2000;
+ tools::Long const nBottomMargin = 1000;
+ tools::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
+constexpr OUStringLiteral FilterMask_All = u"*.*";
+#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 );
+
+ tools::Long nFontHeight = pPrinter->GetTextHeight();
+
+ // 1st Border => line, 2+3 Border = free space
+ tools::Long nYTop = Print::nTopMargin - 3*Print::nBorder - nFontHeight;
+
+ tools::Long nXLeft = Print::nLeftMargin - Print::nBorder;
+ tools::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)
+ ));
+
+
+ tools::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() )
+ return;
+
+ 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 aModule)
+ : BaseWindow(pParent, rDocument, aLibName, aName)
+ , m_rLayout(*pParent)
+ , m_nValid(ValidWindow)
+ , m_aXEditorWindow(VclPtr<ComplexEditorWindow>::Create(this))
+ , m_aModule(std::move(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() )
+ return;
+
+ // never compile while running!
+ bool const bRunning = StarBASIC::IsRunning();
+ bool const bModified = ( !m_xModule->IsCompiled() ||
+ ( GetEditEngine() && GetEditEngine()->IsModified() ) );
+
+ if ( bRunning || !bModified )
+ return;
+
+ bool bDone = false;
+
+ GetShell()->GetViewFrame()->GetWindow().EnterWait();
+
+ AssertValidEditEngine();
+ GetEditorWindow().SetSourceInBasic();
+
+ bool bWasModified = GetBasic()->IsModified();
+
+ {
+ // tdf#106529: only use strict compilation mode when compiling from the IDE
+ css::uno::ContextLayer layer(comphelper::NewFlagContext("BasicStrict"));
+ 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() );
+ bool bMacrosDisabled = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
+ if (bMacrosDisabled || (aDocument.isDocument() && !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 )
+ return;
+
+ 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_uInt32 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(GetFrameWeld(), uno::Reference<frame::XModel>());
+ return;
+ }
+ 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()
+{
+ sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, this->GetFrameWeld());
+ aDlg.SetContext(sfx2::FileDialogHelper::BasicImportSource);
+ Reference<XFilePicker3> xFP = aDlg.GetFilePicker();
+
+ xFP->appendFilter( "BASIC" , "*.bas" );
+ xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
+ xFP->setCurrentFilter( "BASIC" );
+
+ if( aDlg.Execute() != ERRCODE_NONE )
+ return;
+
+ Sequence< OUString > aPaths = xFP->getSelectedFiles();
+ SfxMedium aMedium( aPaths[0], 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 );
+ // tdf#139196 - import macros using either default or utf-8 text encoding
+ pStream->StartReadingUnicodeText(RTL_TEXTENCODING_UTF8);
+ if (pStream->Tell() == 3)
+ pStream->SetStreamCharSet(RTL_TEXTENCODING_UTF8);
+ GetEditView()->Read( *pStream );
+ GetEditEngine()->SetUpdateMode( true );
+ GetEditorWindow().PaintImmediately();
+ 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()
+{
+ sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD,
+ FileDialogFlags::NONE, this->GetFrameWeld());
+ aDlg.SetContext(sfx2::FileDialogHelper::BasicExportSource);
+ const Reference<XFilePicker3>& xFP = aDlg.GetFilePicker();
+
+ Reference< XFilePickerControlAccess > xFPControl(xFP, UNO_QUERY);
+ xFPControl->enableControl(ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, false);
+ Any aValue;
+ aValue <<= true;
+ xFPControl->setValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue);
+
+ xFP->appendFilter( "BASIC", "*.bas" );
+ xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
+ xFP->setCurrentFilter( "BASIC" );
+
+ if( aDlg.Execute() != ERRCODE_NONE )
+ return;
+
+ Sequence< OUString > aPaths = xFP->getSelectedFiles();
+ SfxMedium aMedium( aPaths[0], StreamMode::WRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC );
+ SvStream* pStream = aMedium.GetOutStream();
+ if ( pStream )
+ {
+ EnterWait();
+ AssertValidEditEngine();
+ // tdf#139196 - export macros using utf-8 including BOM
+ pStream->SetStreamCharSet(RTL_TEXTENCODING_UTF8);
+ pStream->WriteUChar(0xEF).WriteUChar(0xBB).WriteUChar(0xBF);
+ 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(), rDocument, aLibName);
+}
+
+void ModulWindow::ToggleBreakPoint( sal_uInt16 nLine )
+{
+ DBG_ASSERT( XModule().is(), "No Module!" );
+
+ if ( !XModule().is() )
+ return;
+
+ CheckCompileBasic();
+ if ( m_aStatus.bError )
+ {
+ return;
+ }
+
+ BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nLine );
+ if ( pBrk ) // remove
+ {
+ m_xModule->ClearBP( nLine );
+ GetBreakPoints().remove( pBrk );
+ }
+ else // create one
+ {
+ if ( m_xModule->SetBP( nLine ))
+ {
+ GetBreakPoints().InsertSorted( BreakPoint( nLine ) );
+ if ( StarBASIC::IsRunning() )
+ {
+ for (sal_uInt32 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 )
+ return;
+
+ 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();
+ BreakPointDialog aBrkDlg(rBrkWin.GetFrameWeld(), GetBreakPoints());
+ aBrkDlg.run();
+ rBrkWin.Invalidate();
+}
+
+void 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.
+ TopLevelWindowLocker aBusy;
+ aBusy.incBusy(nullptr);
+
+ ErrorHandler::HandleError(StarBASIC::GetErrorCode(), GetFrameWeld());
+
+ aBusy.decBusy();
+
+ // #i47002#
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if ( !pWindow )
+ return;
+
+ if ( bMarkError )
+ m_aXEditorWindow->GetBrkWindow().SetNoMarker();
+ return;
+}
+
+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::IsQuit())
+ 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() )
+ {
+ // tdf#57307 - expand selection to include connector punctuations
+ TextSelection aSel;
+ OUString aWord = GetEditEngine()->GetWord( GetEditView()->GetSelection().GetEnd(), &aSel.GetStart(), &aSel.GetEnd() );
+ if ( !aWord.isEmpty() )
+ 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() )
+ return;
+
+ CheckCompileBasic();
+
+ if ( m_aStatus.bError )
+ return;
+
+ sal_uInt16 nStart, nEnd;
+ SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->Find( rMacroName, SbxClassType::Method ));
+ if ( !pMethod )
+ return;
+
+ 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
+ tools::Long nVisHeight = GetOutputSizePixel().Height();
+ if ( pView->GetTextEngine()->GetTextHeight() > nVisHeight )
+ {
+ tools::Long nMaxY = pView->GetTextEngine()->GetTextHeight() - nVisHeight;
+ tools::Long nOldStartY = pView->GetStartDocPos().Y();
+ tools::Long nNewStartY = static_cast<tools::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::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() )
+ return;
+
+ 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;
+ tools::Long nXTextWidth = pPrinter->approximate_digit_width();
+
+ sal_Int32 nCharspLine = aPaperSz.Width() / std::max<tools::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()))
+ {
+ // tdf#134551 don't delete the window if last module is removed until this block
+ // is complete
+ VclPtr<ModulWindow> xKeepRef(this);
+ 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:
+ tools::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() )
+ return;
+
+ m_aStatus.bIsRunning = true;
+ BreakPointList& rList = GetBreakPoints();
+ if ( rList.size() )
+ {
+ rList.ResetHitCount();
+ rList.SetBreakPointsInBasic( m_xModule.get() );
+ for (sal_uInt32 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);
+}
+
+OString 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 (tools::Long const nWidth, tools::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 != std::size(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: */