xref: /core/basctl/source/basicide/baside2.cxx (revision 62f3f3d9)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "baside2.hxx"
21 #include <baside3.hxx>
22 #include "brkdlg.hxx"
23 #include <iderdll.hxx>
24 #include "moduldlg.hxx"
25 #include <docsignature.hxx>
26 #include <officecfg/Office/BasicIDE.hxx>
27 
28 #include <helpids.h>
29 #include <strings.hrc>
30 
31 #include <basic/basmgr.hxx>
32 #include <basic/basrdll.hxx>
33 #include <basic/sbmeth.hxx>
34 #include <com/sun/star/script/ModuleType.hpp>
35 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
36 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
37 #include <com/sun/star/ui/dialogs/FilePicker.hpp>
38 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
39 #include <comphelper/SetFlagContextHelper.hxx>
40 #include <comphelper/string.hxx>
41 #include <svl/srchdefs.hxx>
42 #include <svtools/ehdl.hxx>
43 #include <sfx2/dinfdlg.hxx>
44 #include <sfx2/dispatch.hxx>
45 #include <sfx2/docfile.hxx>
46 #include <sfx2/printer.hxx>
47 #include <sfx2/request.hxx>
48 #include <sfx2/viewfrm.hxx>
49 #include <sot/exchange.hxx>
50 #include <svl/aeitem.hxx>
51 #include <svl/srchitem.hxx>
52 #include <svl/visitem.hxx>
53 #include <svl/whiter.hxx>
54 #include <svx/svxids.hrc>
55 #include <vcl/dialog.hxx>
56 #include <vcl/event.hxx>
57 #include <vcl/settings.hxx>
58 #include <vcl/svapp.hxx>
59 #include <vcl/textview.hxx>
60 #include <vcl/weld.hxx>
61 #include <vcl/xtextedt.hxx>
62 #include <toolkit/helper/vclunohelper.hxx>
63 #include <cassert>
64 #include <osl/diagnose.h>
65 #include <officecfg/Office/Common.hxx>
66 
67 namespace basctl
68 {
69 
70 namespace
71 {
72 
73 namespace Print
74 {
75     long const nLeftMargin = 1700;
76     long const nRightMargin = 900;
77     long const nTopMargin = 2000;
78     long const nBottomMargin = 1000;
79     long const nBorder = 300;
80 }
81 
82 short const ValidWindow = 0x1234;
83 
84 // What (who) are OW and MTF? Compare to baside3.cxx where an
85 // identically named variable, used in the same way, has the value
86 // "*.*" on Windows, "*" otherwise. Is that what should be done here,
87 // too?
88 
89 #if defined(OW) || defined(MTF)
90 char const FilterMask_All[] = "*";
91 #else
92 char const FilterMask_All[] = "*.*";
93 #endif
94 
95 } // end anonymous namespace
96 
97 using namespace ::com::sun::star;
98 using namespace ::com::sun::star::uno;
99 using namespace ::com::sun::star::ui::dialogs;
100 using namespace utl;
101 using namespace comphelper;
102 
103 namespace
104 {
105 
106 void lcl_PrintHeader( Printer* pPrinter, sal_uInt16 nPages, sal_uInt16 nCurPage, const OUString& rTitle, bool bOutput )
107 {
108     Size const aSz = pPrinter->GetOutputSize();
109 
110     const Color aOldLineColor( pPrinter->GetLineColor() );
111     const Color aOldFillColor( pPrinter->GetFillColor() );
112     const vcl::Font aOldFont( pPrinter->GetFont() );
113 
114     pPrinter->SetLineColor( COL_BLACK );
115     pPrinter->SetFillColor();
116 
117     vcl::Font aFont( aOldFont );
118     aFont.SetWeight( WEIGHT_BOLD );
119     aFont.SetAlignment( ALIGN_BOTTOM );
120     pPrinter->SetFont( aFont );
121 
122     long nFontHeight = pPrinter->GetTextHeight();
123 
124     // 1st Border => line, 2+3 Border = free space
125     long nYTop = Print::nTopMargin - 3*Print::nBorder - nFontHeight;
126 
127     long nXLeft = Print::nLeftMargin - Print::nBorder;
128     long nXRight = aSz.Width() - Print::nRightMargin + Print::nBorder;
129 
130     if( bOutput )
131         pPrinter->DrawRect(tools::Rectangle(
132             Point(nXLeft, nYTop),
133             Size(nXRight - nXLeft, aSz.Height() - nYTop - Print::nBottomMargin + Print::nBorder)
134         ));
135 
136 
137     long nY = Print::nTopMargin - 2*Print::nBorder;
138     Point aPos(Print::nLeftMargin, nY);
139     if( bOutput )
140         pPrinter->DrawText( aPos, rTitle );
141     if ( nPages != 1 )
142     {
143         aFont.SetWeight( WEIGHT_NORMAL );
144         pPrinter->SetFont( aFont );
145         aPos.AdjustX(pPrinter->GetTextWidth( rTitle ) );
146 
147         if( bOutput )
148         {
149             OUString aPageStr = " [" + IDEResId(RID_STR_PAGE) + " " + OUString::number( nCurPage ) + "]";
150             pPrinter->DrawText( aPos, aPageStr );
151         }
152     }
153 
154     nY = Print::nTopMargin - Print::nBorder;
155 
156     if( bOutput )
157         pPrinter->DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) );
158 
159     pPrinter->SetFont( aOldFont );
160     pPrinter->SetFillColor( aOldFillColor );
161     pPrinter->SetLineColor( aOldLineColor );
162 }
163 
164 void lcl_ConvertTabsToSpaces( OUString& rLine )
165 {
166     if ( !rLine.isEmpty() )
167     {
168         OUStringBuffer aResult( rLine );
169         sal_Int32 nPos = 0;
170         sal_Int32 nMax = aResult.getLength();
171         while ( nPos < nMax )
172         {
173             if ( aResult[nPos] == '\t' )
174             {
175                 // not 4 Blanks, but at 4 TabPos:
176                 OUStringBuffer aBlanker;
177                 string::padToLength(aBlanker, ( 4 - ( nPos % 4 ) ), ' ');
178                 aResult.remove( nPos, 1 );
179                 aResult.insert( nPos, aBlanker.makeStringAndClear() );
180                 nMax = aResult.getLength();
181             }
182             ++nPos;
183         }
184         rLine = aResult.makeStringAndClear();
185     }
186 }
187 
188 } // namespace
189 
190 ModulWindow::ModulWindow (ModulWindowLayout* pParent, ScriptDocument const& rDocument,
191                           const OUString& aLibName, const OUString& aName, OUString const & aModule)
192     : BaseWindow(pParent, rDocument, aLibName, aName)
193     , m_rLayout(*pParent)
194     , m_nValid(ValidWindow)
195     , m_aXEditorWindow(VclPtr<ComplexEditorWindow>::Create(this))
196     , m_aModule(aModule)
197 {
198     m_aXEditorWindow->Show();
199     SetBackground();
200 }
201 
202 SbModuleRef const & ModulWindow::XModule()
203 {
204     // ModuleWindows can now be created as a result of the
205     // modules getting created via the api. This is a result of an
206     // elementInserted event from the BasicLibrary container.
207     // However the SbModule is also created from a different listener to
208     // the same event ( in basmgr ) Therefore it is possible when we look
209     // for m_xModule it may not yet be available, here we keep trying to access
210     // the module until such time as it exists
211 
212     if ( !m_xModule.is() )
213     {
214         BasicManager* pBasMgr = GetDocument().getBasicManager();
215         if ( pBasMgr )
216         {
217             StarBASIC* pBasic = pBasMgr->GetLib( GetLibName() );
218             if ( pBasic )
219             {
220                 m_xBasic = pBasic;
221                 m_xModule = pBasic->FindModule( GetName() );
222             }
223         }
224     }
225     return m_xModule;
226 }
227 
228 ModulWindow::~ModulWindow()
229 {
230     disposeOnce();
231 }
232 
233 void ModulWindow::dispose()
234 {
235     m_nValid = 0;
236     StarBASIC::Stop();
237     m_aXEditorWindow.disposeAndClear();
238     BaseWindow::dispose();
239 }
240 
241 
242 void ModulWindow::GetFocus()
243 {
244     if (m_nValid != ValidWindow)
245         return;
246     m_aXEditorWindow->GetEdtWindow().GrabFocus();
247     // don't call basic calls because focus is somewhere else...
248 }
249 
250 void ModulWindow::DoInit()
251 {
252     if (GetVScrollBar())
253         GetVScrollBar()->Hide();
254     GetHScrollBar()->Show();
255     GetEditorWindow().InitScrollBars();
256 }
257 
258 void ModulWindow::Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle&)
259 {
260 }
261 
262 void ModulWindow::Resize()
263 {
264     m_aXEditorWindow->SetPosSizePixel( Point( 0, 0 ), GetOutputSizePixel() );
265 }
266 
267 void ModulWindow::CheckCompileBasic()
268 {
269     if ( XModule().is() )
270     {
271         // never compile while running!
272         bool const bRunning = StarBASIC::IsRunning();
273         bool const bModified = ( !m_xModule->IsCompiled() ||
274             ( GetEditEngine() && GetEditEngine()->IsModified() ) );
275 
276         if ( !bRunning && bModified )
277         {
278             bool bDone = false;
279 
280             GetShell()->GetViewFrame()->GetWindow().EnterWait();
281 
282             AssertValidEditEngine();
283             GetEditorWindow().SetSourceInBasic();
284 
285             bool bWasModified = GetBasic()->IsModified();
286 
287             {
288                 // tdf#106529: only use strict compilation mode when compiling from the IDE
289                 css::uno::ContextLayer layer(comphelper::NewFlagContext("BasicStrict"));
290                 bDone = m_xModule->Compile();
291             }
292             if ( !bWasModified )
293                 GetBasic()->SetModified(false);
294 
295             if ( bDone )
296             {
297                 GetBreakPoints().SetBreakPointsInBasic( m_xModule.get() );
298             }
299 
300             GetShell()->GetViewFrame()->GetWindow().LeaveWait();
301 
302             m_aStatus.bError = !bDone;
303             m_aStatus.bIsRunning = false;
304         }
305     }
306 }
307 
308 void ModulWindow::BasicExecute()
309 {
310     // #116444# check security settings before macro execution
311     ScriptDocument aDocument( GetDocument() );
312     bool bMacrosDisabled = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
313     if (bMacrosDisabled || (aDocument.isDocument() && !aDocument.allowMacros()))
314     {
315         std::unique_ptr<weld::MessageDialog> xBox(
316             Application::CreateMessageDialog(GetFrameWeld(), VclMessageType::Warning,
317                                              VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO)));
318         xBox->run();
319         return;
320     }
321 
322     CheckCompileBasic();
323 
324     if ( XModule().is() && m_xModule->IsCompiled() && !m_aStatus.bError )
325     {
326         if ( GetBreakPoints().size() )
327             m_aStatus.nBasicFlags = m_aStatus.nBasicFlags | BasicDebugFlags::Break;
328 
329         if ( !m_aStatus.bIsRunning )
330         {
331             DBG_ASSERT( m_xModule.is(), "No Module!" );
332             AddStatus( BASWIN_RUNNINGBASIC );
333             sal_uInt16 nStart, nEnd;
334             TextSelection aSel = GetEditView()->GetSelection();
335             // Init cursor to top
336             const sal_uInt32 nCurMethodStart = aSel.GetStart().GetPara() + 1;
337             SbMethod* pMethod = nullptr;
338             // first Macro, else blind "Main" (ExtSearch?)
339             for ( sal_uInt32 nMacro = 0; nMacro < m_xModule->GetMethods()->Count32(); nMacro++ )
340             {
341                 SbMethod* pM = static_cast<SbMethod*>(m_xModule->GetMethods()->Get32( nMacro ));
342                 assert(pM && "Method?");
343                 pM->GetLineRange( nStart, nEnd );
344                 if (  nCurMethodStart >= nStart && nCurMethodStart <= nEnd )
345                 {
346                     // matched a method to the cursor position
347                     pMethod = pM;
348                     break;
349                 }
350             }
351             if ( !pMethod )
352             {
353                 // If not in a method then prompt the user
354                 ChooseMacro(GetFrameWeld(), uno::Reference<frame::XModel>());
355                 return;
356             }
357             pMethod->SetDebugFlags(m_aStatus.nBasicFlags);
358             BasicDLL::SetDebugMode(true);
359             RunMethod(pMethod);
360             BasicDLL::SetDebugMode(false);
361             // if cancelled during Interactive=false
362             BasicDLL::EnableBreak(true);
363             ClearStatus( BASWIN_RUNNINGBASIC );
364         }
365         else
366             m_aStatus.bIsRunning = false; // cancel of Reschedule()
367     }
368 }
369 
370 void ModulWindow::CompileBasic()
371 {
372     CheckCompileBasic();
373 
374     XModule().is() && m_xModule->IsCompiled();
375 }
376 
377 void ModulWindow::BasicRun()
378 {
379     m_aStatus.nBasicFlags = BasicDebugFlags::NONE;
380     BasicExecute();
381 }
382 
383 void ModulWindow::BasicStepOver()
384 {
385     m_aStatus.nBasicFlags = BasicDebugFlags::StepInto | BasicDebugFlags::StepOver;
386     BasicExecute();
387 }
388 
389 
390 void ModulWindow::BasicStepInto()
391 {
392     m_aStatus.nBasicFlags = BasicDebugFlags::StepInto;
393     BasicExecute();
394 }
395 
396 void ModulWindow::BasicStepOut()
397 {
398     m_aStatus.nBasicFlags = BasicDebugFlags::StepOut;
399     BasicExecute();
400 }
401 
402 
403 void ModulWindow::BasicStop()
404 {
405     StarBASIC::Stop();
406     m_aStatus.bIsRunning = false;
407 }
408 
409 void ModulWindow::LoadBasic()
410 {
411     Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
412     Reference < XFilePicker3 > xFP = FilePicker::createWithMode(xContext, TemplateDescription::FILEOPEN_SIMPLE);
413 
414     if ( !m_sCurPath.isEmpty() )
415         xFP->setDisplayDirectory ( m_sCurPath );
416 
417     xFP->appendFilter( "BASIC" , "*.bas" );
418     xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
419     xFP->setCurrentFilter( "BASIC" );
420 
421     if( xFP->execute() == RET_OK )
422     {
423         Sequence< OUString > aPaths = xFP->getSelectedFiles();
424         m_sCurPath = aPaths[0];
425         SfxMedium aMedium( m_sCurPath, StreamMode::READ | StreamMode::SHARE_DENYWRITE | StreamMode::NOCREATE );
426         SvStream* pStream = aMedium.GetInStream();
427         if ( pStream )
428         {
429             AssertValidEditEngine();
430             sal_uInt32 nLines = CalcLineCount( *pStream );
431             // nLines*4: ReadText/Formatting/Highlighting/Formatting
432             GetEditorWindow().CreateProgress( IDEResId(RID_STR_GENERATESOURCE), nLines*4 );
433             GetEditEngine()->SetUpdateMode( false );
434             GetEditView()->Read( *pStream );
435             GetEditEngine()->SetUpdateMode( true );
436             GetEditorWindow().Update();
437             GetEditorWindow().ForceSyntaxTimeout();
438             GetEditorWindow().DestroyProgress();
439             ErrCode nError = aMedium.GetError();
440             if ( nError )
441                 ErrorHandler::HandleError( nError );
442         }
443         else
444         {
445             std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
446                                                       VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTREAD)));
447             xBox->run();
448         }
449     }
450 }
451 
452 
453 void ModulWindow::SaveBasicSource()
454 {
455     Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
456     Reference < XFilePicker3 > xFP = FilePicker::createWithMode(xContext, TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD);
457 
458     Reference< XFilePickerControlAccess > xFPControl(xFP, UNO_QUERY);
459     xFPControl->enableControl(ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, false);
460     Any aValue;
461     aValue <<= true;
462     xFPControl->setValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue);
463 
464     if ( !m_sCurPath.isEmpty() )
465         xFP->setDisplayDirectory ( m_sCurPath );
466 
467     xFP->appendFilter( "BASIC", "*.bas" );
468     xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
469     xFP->setCurrentFilter( "BASIC" );
470 
471     if( xFP->execute() == RET_OK )
472     {
473         Sequence< OUString > aPaths = xFP->getSelectedFiles();
474         m_sCurPath = aPaths[0];
475         SfxMedium aMedium( m_sCurPath, StreamMode::WRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC );
476         SvStream* pStream = aMedium.GetOutStream();
477         if ( pStream )
478         {
479             EnterWait();
480             AssertValidEditEngine();
481             GetEditEngine()->Write( *pStream );
482             aMedium.Commit();
483             LeaveWait();
484             ErrCode nError = aMedium.GetError();
485             if ( nError )
486                 ErrorHandler::HandleError( nError );
487         }
488         else
489         {
490             std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(GetFrameWeld(),
491                                                            VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTWRITE)));
492             xErrorBox->run();
493         }
494     }
495 }
496 
497 void ModulWindow::ImportDialog()
498 {
499     const ScriptDocument& rDocument = GetDocument();
500     OUString aLibName = GetLibName();
501     implImportDialog(GetFrameWeld(), m_sCurPath, rDocument, aLibName);
502 }
503 
504 void ModulWindow::ToggleBreakPoint( sal_uLong nLine )
505 {
506     DBG_ASSERT( XModule().is(), "No Module!" );
507 
508     if ( XModule().is() )
509     {
510         CheckCompileBasic();
511         if ( m_aStatus.bError )
512         {
513             return;
514         }
515 
516         BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nLine );
517         if ( pBrk ) // remove
518         {
519             m_xModule->ClearBP( static_cast<sal_uInt16>(nLine) );
520             GetBreakPoints().remove( pBrk );
521         }
522         else // create one
523         {
524             if ( m_xModule->SetBP( static_cast<sal_uInt16>(nLine)) )
525             {
526                 GetBreakPoints().InsertSorted( BreakPoint( nLine ) );
527                 if ( StarBASIC::IsRunning() )
528                 {
529                     for ( sal_uInt32 nMethod = 0; nMethod < m_xModule->GetMethods()->Count32(); nMethod++ )
530                     {
531                         SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->GetMethods()->Get32( nMethod ));
532                         assert(pMethod && "Method not found! (NULL)");
533                         pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
534                     }
535                 }
536             }
537         }
538     }
539 }
540 
541 void ModulWindow::UpdateBreakPoint( const BreakPoint& rBrk )
542 {
543     DBG_ASSERT( XModule().is(), "No Module!" );
544 
545     if ( XModule().is() )
546     {
547         CheckCompileBasic();
548 
549         if ( rBrk.bEnabled )
550             m_xModule->SetBP( rBrk.nLine );
551         else
552             m_xModule->ClearBP( rBrk.nLine );
553     }
554 }
555 
556 
557 void ModulWindow::BasicToggleBreakPoint()
558 {
559     AssertValidEditEngine();
560 
561     TextSelection aSel = GetEditView()->GetSelection();
562     aSel.GetStart().GetPara()++;    // Basic lines start at 1!
563     aSel.GetEnd().GetPara()++;
564 
565     for ( sal_uInt32 nLine = aSel.GetStart().GetPara(); nLine <= aSel.GetEnd().GetPara(); ++nLine )
566     {
567         ToggleBreakPoint( nLine );
568     }
569 
570     m_aXEditorWindow->GetBrkWindow().Invalidate();
571 }
572 
573 
574 void ModulWindow::BasicToggleBreakPointEnabled()
575 {
576     AssertValidEditEngine();
577 
578     TextView* pView = GetEditView();
579     if ( pView )
580     {
581         TextSelection aSel = pView->GetSelection();
582         BreakPointList& rList = GetBreakPoints();
583 
584         for ( sal_uInt32 nLine = ++aSel.GetStart().GetPara(), nEnd = ++aSel.GetEnd().GetPara(); nLine <= nEnd; ++nLine )
585         {
586             BreakPoint* pBrk = rList.FindBreakPoint( nLine );
587             if ( pBrk )
588             {
589                 pBrk->bEnabled = !pBrk->bEnabled;
590                 UpdateBreakPoint( *pBrk );
591             }
592         }
593 
594         GetBreakPointWindow().Invalidate();
595     }
596 }
597 
598 void ModulWindow::ManageBreakPoints()
599 {
600     BreakPointWindow& rBrkWin = GetBreakPointWindow();
601     BreakPointDialog aBrkDlg(rBrkWin.GetFrameWeld(), GetBreakPoints());
602     aBrkDlg.run();
603     rBrkWin.Invalidate();
604 }
605 
606 void ModulWindow::BasicErrorHdl( StarBASIC const * pBasic )
607 {
608     GetShell()->GetViewFrame()->ToTop();
609 
610     // Return value: BOOL
611     //  FALSE:  cancel
612     //  TRUE:   go on...
613     sal_uInt16 nErrorLine = StarBASIC::GetLine() - 1;
614     sal_uInt16 nErrCol1 = StarBASIC::GetCol1();
615     sal_uInt16 nErrCol2 = StarBASIC::GetCol2();
616     if ( nErrCol2 != 0xFFFF )
617         nErrCol2++;
618 
619     AssertValidEditEngine();
620     GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, nErrCol1 ), TextPaM( nErrorLine, nErrCol2 ) ) );
621 
622     // if other basic, the IDE should try to display the correct module
623     bool const bMarkError = pBasic == GetBasic();
624     if ( bMarkError )
625         m_aXEditorWindow->GetBrkWindow().SetMarkerPos(nErrorLine, true);
626 
627     // #i47002#
628     Reference< awt::XWindow > xWindow = VCLUnoHelper::GetInterface( this );
629 
630     // tdf#118572 make a currently running dialog, regardless of what its modal
631     // to, insensitive to user input until after this error dialog goes away.
632     auto xDialog = Dialog::GetMostRecentExecutingDialog();
633     const bool bToggleEnableInput = xDialog && xDialog->IsInputEnabled();
634     if (bToggleEnableInput)
635         xDialog->EnableInput(false);
636     ErrorHandler::HandleError(StarBASIC::GetErrorCode(), GetFrameWeld());
637     if (bToggleEnableInput)
638         xDialog->EnableInput(true);
639 
640     // #i47002#
641     VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
642     if ( !pWindow )
643         return;
644 
645     if ( bMarkError )
646         m_aXEditorWindow->GetBrkWindow().SetNoMarker();
647     return;
648 }
649 
650 BasicDebugFlags ModulWindow::BasicBreakHdl()
651 {
652     // Return value: sal_uInt16 => see SB-Debug-Flags
653     sal_uInt16 nErrorLine = StarBASIC::GetLine();
654 
655 
656     BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nErrorLine );
657     if ( pBrk )
658     {
659         pBrk->nHitCount++;
660         if ( pBrk->nHitCount <= pBrk->nStopAfter && GetBasic()->IsBreak() )
661             return m_aStatus.nBasicFlags; // go on...
662     }
663 
664     nErrorLine--;   // EditEngine starts at 0, Basic at 1
665 
666     AssertValidEditEngine();
667     GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, 0 ), TextPaM( nErrorLine, 0 ) ) );
668     m_aXEditorWindow->GetBrkWindow().SetMarkerPos( nErrorLine );
669 
670     m_rLayout.UpdateDebug(false);
671 
672     m_aStatus.bIsInReschedule = true;
673     m_aStatus.bIsRunning = true;
674 
675     AddStatus( BASWIN_INRESCHEDULE );
676 
677     InvalidateDebuggerSlots();
678 
679     while( m_aStatus.bIsRunning )
680         Application::Yield();
681 
682     m_aStatus.bIsInReschedule = false;
683     m_aXEditorWindow->GetBrkWindow().SetNoMarker();
684 
685     ClearStatus( BASWIN_INRESCHEDULE );
686 
687     return m_aStatus.nBasicFlags;
688 }
689 
690 void ModulWindow::BasicAddWatch()
691 {
692     AssertValidEditEngine();
693     bool bAdd = true;
694     if ( !GetEditView()->HasSelection() )
695     {
696         TextPaM aWordStart;
697         OUString aWord = GetEditEngine()->GetWord( GetEditView()->GetSelection().GetEnd(), &aWordStart );
698         if ( !aWord.isEmpty() )
699         {
700             TextSelection aSel( aWordStart );
701             aSel.GetEnd().GetIndex() += aWord.getLength();
702             GetEditView()->SetSelection( aSel );
703         }
704         else
705             bAdd = false;
706     }
707     if ( bAdd )
708     {
709         TextSelection aSel = GetEditView()->GetSelection();
710         if ( aSel.GetStart().GetPara() == aSel.GetEnd().GetPara() ) // single line selection
711             m_rLayout.BasicAddWatch(GetEditView()->GetSelected());
712     }
713 }
714 
715 
716 void ModulWindow::EditMacro( const OUString& rMacroName )
717 {
718     DBG_ASSERT( XModule().is(), "No Module!" );
719 
720     if ( XModule().is() )
721     {
722         CheckCompileBasic();
723 
724         if ( !m_aStatus.bError )
725         {
726             sal_uInt16 nStart, nEnd;
727             SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->Find( rMacroName, SbxClassType::Method ));
728             if ( pMethod )
729             {
730                 pMethod->GetLineRange( nStart, nEnd );
731                 if ( nStart )
732                 {
733                     nStart--;
734                     nEnd--;
735                 }
736                 TextSelection aSel( TextPaM( nStart, 0 ), TextPaM( nStart, 0 ) );
737                 AssertValidEditEngine();
738                 TextView * pView = GetEditView();
739                 // scroll if applicable so that first line is at the top
740                 long nVisHeight = GetOutputSizePixel().Height();
741                 if ( pView->GetTextEngine()->GetTextHeight() > nVisHeight )
742                 {
743                     long nMaxY = pView->GetTextEngine()->GetTextHeight() - nVisHeight;
744                     long nOldStartY = pView->GetStartDocPos().Y();
745                     long nNewStartY = static_cast<long>(nStart) * pView->GetTextEngine()->GetCharHeight();
746                     nNewStartY = std::min( nNewStartY, nMaxY );
747                     pView->Scroll( 0, -(nNewStartY-nOldStartY) );
748                     pView->ShowCursor( false );
749                     GetEditVScrollBar().SetThumbPos( pView->GetStartDocPos().Y() );
750                 }
751                 pView->SetSelection( aSel );
752                 pView->ShowCursor();
753                 pView->GetWindow()->GrabFocus();
754             }
755         }
756     }
757 }
758 
759 void ModulWindow::StoreData()
760 {
761     // StoreData is called when the BasicManager is destroyed or
762     // this window is closed.
763     // => interrupts undesired!
764     GetEditorWindow().SetSourceInBasic();
765 }
766 
767 bool ModulWindow::AllowUndo()
768 {
769     return GetEditorWindow().CanModify();
770 }
771 
772 void ModulWindow::UpdateData()
773 {
774     DBG_ASSERT( XModule().is(), "No Module!" );
775     // UpdateData is called when the source has changed from outside
776     // => interrupts undesired!
777 
778     if ( XModule().is() )
779     {
780         SetModule( m_xModule->GetSource32() );
781 
782         if ( GetEditView() )
783         {
784             TextSelection aSel = GetEditView()->GetSelection();
785             setTextEngineText(*GetEditEngine(), m_xModule->GetSource32());
786             GetEditView()->SetSelection( aSel );
787             GetEditEngine()->SetModified( false );
788             MarkDocumentModified( GetDocument() );
789         }
790     }
791 }
792 
793 sal_Int32 ModulWindow::countPages( Printer* pPrinter )
794 {
795     return FormatAndPrint( pPrinter, -1 );
796 }
797 
798 void ModulWindow::printPage( sal_Int32 nPage, Printer* pPrinter )
799 {
800     FormatAndPrint( pPrinter, nPage );
801 }
802 
803 /* implementation note: this is totally inefficient for the XRenderable interface
804    usage since the whole "document" will be format for every page. Should this ever
805    become a problem we should
806    - format only once for every new printer
807    - keep an index list for each page which is the starting paragraph
808 */
809 sal_Int32 ModulWindow::FormatAndPrint( Printer* pPrinter, sal_Int32 nPrintPage )
810 {
811     AssertValidEditEngine();
812 
813     MapMode eOldMapMode( pPrinter->GetMapMode() );
814     vcl::Font aOldFont( pPrinter->GetFont() );
815 
816     vcl::Font aFont( GetEditEngine()->GetFont() );
817     aFont.SetAlignment( ALIGN_BOTTOM );
818     aFont.SetTransparent( true );
819     aFont.SetFontSize( Size( 0, 360 ) );
820     pPrinter->SetFont( aFont );
821     pPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
822 
823     OUString aTitle( CreateQualifiedName() );
824 
825     sal_Int32 nLineHeight = pPrinter->GetTextHeight();
826     if(nLineHeight == 0)
827     {
828         nLineHeight = 1;
829     }
830 
831     Size aPaperSz = pPrinter->GetOutputSize();
832     aPaperSz.AdjustWidth( -(Print::nLeftMargin + Print::nRightMargin) );
833     aPaperSz.AdjustHeight( -(Print::nTopMargin + Print::nBottomMargin) );
834 
835     // nLinepPage is not correct if there's a line break
836     sal_Int32 nLinespPage = aPaperSz.Height()/nLineHeight;
837     long nXTextWidth = pPrinter->approximate_char_width();
838 
839     sal_Int32 nCharspLine = aPaperSz.Width() / std::max<long>(nXTextWidth, 1);
840     const sal_uInt32 nParas = GetEditEngine()->GetParagraphCount();
841 
842     sal_Int32 nPages = nParas/nLinespPage+1;
843     sal_Int32 nCurPage = 1;
844 
845     lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nPrintPage == 0 );
846     Point aPos( Print::nLeftMargin, Print::nTopMargin );
847     for ( sal_uInt32 nPara = 0; nPara < nParas; ++nPara )
848     {
849         OUString aLine( GetEditEngine()->GetText( nPara ) );
850         lcl_ConvertTabsToSpaces( aLine );
851         sal_Int32 nLines = aLine.getLength()/nCharspLine+1;
852         for (sal_Int32 nLine = 0; nLine < nLines; ++nLine)
853         {
854             sal_Int32 nBeginIndex = nLine*nCharspLine;
855             sal_Int32 nCopyCount = std::min<sal_Int32>(nCharspLine, aLine.getLength()-nBeginIndex);
856             OUString aTmpLine = aLine.copy(nBeginIndex, nCopyCount);
857             aPos.AdjustY(nLineHeight );
858             if ( aPos.Y() > ( aPaperSz.Height() + Print::nTopMargin ) )
859             {
860                 nCurPage++;
861                 lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nCurPage-1 == nPrintPage );
862                 aPos = Point(Print::nLeftMargin, Print::nTopMargin + nLineHeight);
863             }
864             if( nCurPage-1 == nPrintPage )
865                 pPrinter->DrawText( aPos, aTmpLine );
866         }
867         aPos.AdjustY(10 ); // nParaSpace
868     }
869 
870     pPrinter->SetFont( aOldFont );
871     pPrinter->SetMapMode( eOldMapMode );
872 
873     return nCurPage;
874 }
875 
876 void ModulWindow::ExecuteCommand (SfxRequest& rReq)
877 {
878     AssertValidEditEngine();
879     switch (rReq.GetSlot())
880     {
881         case SID_DELETE:
882         {
883             if (!IsReadOnly())
884             {
885                 KeyEvent aFakeDelete(0, KEY_DELETE);
886                 (void)GetEditView()->KeyInput(aFakeDelete);
887             }
888             break;
889         }
890         case SID_SELECTALL:
891         {
892             TextSelection aSel( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) );
893             TextView * pView = GetEditView();
894             pView->SetSelection( aSel );
895             pView->GetWindow()->GrabFocus();
896             break;
897         }
898         case SID_BASICRUN:
899         {
900             BasicRun();
901         }
902         break;
903         case SID_BASICCOMPILE:
904         {
905             CompileBasic();
906         }
907         break;
908         case SID_BASICSTEPOVER:
909         {
910             BasicStepOver();
911         }
912         break;
913         case SID_BASICSTEPINTO:
914         {
915             BasicStepInto();
916         }
917         break;
918         case SID_BASICSTEPOUT:
919         {
920             BasicStepOut();
921         }
922         break;
923         case SID_BASICLOAD:
924         {
925             LoadBasic();
926         }
927         break;
928         case SID_BASICSAVEAS:
929         {
930             SaveBasicSource();
931         }
932         break;
933         case SID_IMPORT_DIALOG:
934         {
935             ImportDialog();
936         }
937         break;
938         case SID_BASICIDE_MATCHGROUP:
939         {
940             GetEditView()->MatchGroup();
941         }
942         break;
943         case SID_BASICIDE_TOGGLEBRKPNT:
944         {
945             BasicToggleBreakPoint();
946         }
947         break;
948         case SID_BASICIDE_MANAGEBRKPNTS:
949         {
950             ManageBreakPoints();
951         }
952         break;
953         case SID_BASICIDE_TOGGLEBRKPNTENABLED:
954         {
955             BasicToggleBreakPointEnabled();
956         }
957         break;
958         case SID_BASICIDE_ADDWATCH:
959         {
960             BasicAddWatch();
961         }
962         break;
963         case SID_BASICIDE_REMOVEWATCH:
964         {
965             m_rLayout.BasicRemoveWatch();
966         }
967         break;
968         case SID_CUT:
969         {
970             if ( !IsReadOnly() )
971             {
972                 GetEditView()->Cut();
973                 if (SfxBindings* pBindings = GetBindingsPtr())
974                     pBindings->Invalidate( SID_DOC_MODIFIED );
975             }
976         }
977         break;
978         case SID_COPY:
979         {
980             GetEditView()->Copy();
981         }
982         break;
983         case SID_PASTE:
984         {
985             if ( !IsReadOnly() )
986             {
987                 GetEditView()->Paste();
988                 if (SfxBindings* pBindings = GetBindingsPtr())
989                     pBindings->Invalidate( SID_DOC_MODIFIED );
990             }
991         }
992         break;
993         case SID_BASICIDE_BRKPNTSCHANGED:
994         {
995             GetBreakPointWindow().Invalidate();
996         }
997         break;
998         case SID_SHOWLINES:
999         {
1000             const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
1001             bool bLineNumbers = pItem && pItem->GetValue();
1002             m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
1003 
1004             std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1005             officecfg::Office::BasicIDE::EditorSettings::LineNumbering::set(bLineNumbers, batch);
1006             batch->commit();
1007         }
1008         break;
1009         case SID_BASICIDE_DELETECURRENT:
1010         {
1011             if (QueryDelModule(m_aName, GetFrameWeld()))
1012                 if (m_aDocument.removeModule(m_aLibName, m_aName))
1013                     MarkDocumentModified(m_aDocument);
1014         }
1015         break;
1016         case FID_SEARCH_OFF:
1017             GrabFocus();
1018             break;
1019         case SID_GOTOLINE:
1020         {
1021             GotoLineDialog aGotoDlg(GetFrameWeld());
1022             if (aGotoDlg.run() == RET_OK)
1023             {
1024                 if (sal_Int32 const nLine = aGotoDlg.GetLineNumber())
1025                 {
1026                     TextSelection const aSel(TextPaM(nLine - 1, 0), TextPaM(nLine - 1, 0));
1027                     GetEditView()->SetSelection(aSel);
1028                 }
1029             }
1030             break;
1031         }
1032     }
1033 }
1034 
1035 void ModulWindow::ExecuteGlobal (SfxRequest& rReq)
1036 {
1037     switch (rReq.GetSlot())
1038     {
1039         case SID_SIGNATURE:
1040         {
1041             DocumentSignature aSignature(m_aDocument);
1042             if (aSignature.supportsSignatures())
1043             {
1044                 aSignature.signScriptingContent(rReq.GetFrameWeld());
1045                 if (SfxBindings* pBindings = GetBindingsPtr())
1046                     pBindings->Invalidate(SID_SIGNATURE);
1047             }
1048         }
1049         break;
1050     }
1051 }
1052 
1053 
1054 void ModulWindow::GetState( SfxItemSet &rSet )
1055 {
1056     SfxWhichIter aIter(rSet);
1057     for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh != 0; nWh = aIter.NextWhich() )
1058     {
1059         switch ( nWh )
1060         {
1061             case SID_CUT:
1062             {
1063                 if ( !GetEditView() || !GetEditView()->HasSelection() )
1064                     rSet.DisableItem( nWh );
1065 
1066                 if ( IsReadOnly() )
1067                     rSet.DisableItem( nWh );
1068             }
1069             break;
1070             case SID_COPY:
1071             {
1072                 if ( !GetEditView() || !GetEditView()->HasSelection() )
1073                     rSet.DisableItem( nWh );
1074             }
1075             break;
1076             case SID_PASTE:
1077             {
1078                 if ( !IsPasteAllowed() )
1079                     rSet.DisableItem( nWh );
1080 
1081                 if ( IsReadOnly() )
1082                     rSet.DisableItem( nWh );
1083             }
1084             break;
1085             case SID_BASICIDE_STAT_POS:
1086             {
1087                 TextView* pView = GetEditView();
1088                 if ( pView )
1089                 {
1090                     TextSelection aSel = pView->GetSelection();
1091                     OUString aPos = IDEResId( RID_STR_LINE ) +
1092                                    " " +
1093                                    OUString::number(aSel.GetEnd().GetPara()+1) +
1094                                    ", " +
1095                                    IDEResId( RID_STR_COLUMN ) +
1096                                    " " +
1097                                    OUString::number(aSel.GetEnd().GetIndex()+1);
1098                     SfxStringItem aItem( SID_BASICIDE_STAT_POS, aPos );
1099                     rSet.Put( aItem );
1100                 }
1101             }
1102             break;
1103             case SID_BASICIDE_STAT_TITLE:
1104             {
1105                 // search for current procedure name (Sub or Function)
1106                 TextView* pView = GetEditView();
1107                 if ( pView )
1108                 {
1109                     OUString sProcName;
1110 
1111                     TextSelection aSel = pView->GetSelection();
1112 
1113                     sal_uInt32 i = aSel.GetStart().GetPara();
1114                     do
1115                     {
1116                         OUString aCurrLine = GetEditEngine()->GetText( i );
1117                         OUString sProcType;
1118                         if (GetEditorWindow().GetProcedureName(aCurrLine, sProcType, sProcName))
1119                             break;
1120                     } while (i--);
1121 
1122                     OUString aTitle = CreateQualifiedName();
1123                     if (!sProcName.isEmpty())
1124                         aTitle += "." + sProcName;
1125 
1126                     SfxStringItem aTitleItem( SID_BASICIDE_STAT_TITLE, aTitle );
1127                     rSet.Put( aTitleItem );
1128                 }
1129             }
1130             break;
1131             case SID_ATTR_INSERT:
1132             {
1133                 TextView* pView = GetEditView();
1134                 if ( pView )
1135                 {
1136                     SfxBoolItem aItem( SID_ATTR_INSERT, pView->IsInsertMode() );
1137                     rSet.Put( aItem );
1138                 }
1139             }
1140             break;
1141             case SID_SHOWLINES:
1142             {
1143                 bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1144                 rSet.Put(SfxBoolItem(nWh, bLineNumbers));
1145                 break;
1146             }
1147             case SID_SELECTALL:
1148             {
1149                 if ( !GetEditView() )
1150                     rSet.DisableItem( nWh );
1151             }
1152             break;
1153         }
1154     }
1155 }
1156 
1157 void ModulWindow::DoScroll( ScrollBar* pCurScrollBar )
1158 {
1159     if ( ( pCurScrollBar == GetHScrollBar() ) && GetEditView() )
1160     {
1161         // don't scroll with the value but rather use the Thumb-Pos for the VisArea:
1162         long nDiff = GetEditView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
1163         GetEditView()->Scroll( nDiff, 0 );
1164         GetEditView()->ShowCursor( false );
1165         pCurScrollBar->SetThumbPos( GetEditView()->GetStartDocPos().X() );
1166 
1167     }
1168 }
1169 
1170 bool ModulWindow::IsModified()
1171 {
1172     return GetEditEngine() && GetEditEngine()->IsModified();
1173 }
1174 
1175 OUString ModulWindow::GetSbModuleName()
1176 {
1177     OUString aModuleName;
1178     if ( XModule().is() )
1179         aModuleName = m_xModule->GetName();
1180     return aModuleName;
1181 }
1182 
1183 OUString ModulWindow::GetTitle()
1184 {
1185     return GetSbModuleName();
1186 }
1187 
1188 void ModulWindow::ShowCursor( bool bOn )
1189 {
1190     if ( GetEditEngine() )
1191     {
1192         TextView* pView = GetEditEngine()->GetActiveView();
1193         if ( pView )
1194         {
1195             if ( bOn )
1196                 pView->ShowCursor();
1197             else
1198                 pView->HideCursor();
1199         }
1200     }
1201 }
1202 
1203 void ModulWindow::AssertValidEditEngine()
1204 {
1205     if ( !GetEditEngine() )
1206         GetEditorWindow().CreateEditEngine();
1207 }
1208 
1209 void ModulWindow::Activating ()
1210 {
1211     bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1212     m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
1213     Show();
1214 }
1215 
1216 void ModulWindow::Deactivating()
1217 {
1218     Hide();
1219 }
1220 
1221 sal_uInt16 ModulWindow::StartSearchAndReplace( const SvxSearchItem& rSearchItem, bool bFromStart )
1222 {
1223     if (IsSuspended())
1224         return 0;
1225 
1226     // one could also relinquish syntaxhighlighting/formatting instead of the stupid replace-everything...
1227     AssertValidEditEngine();
1228     TextView* pView = GetEditView();
1229     TextSelection aSel;
1230     if ( bFromStart )
1231     {
1232         aSel = pView->GetSelection();
1233         if ( !rSearchItem.GetBackward() )
1234             pView->SetSelection( TextSelection() );
1235         else
1236             pView->SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
1237     }
1238 
1239     bool const bForward = !rSearchItem.GetBackward();
1240     sal_uInt16 nFound = 0;
1241     if ( ( rSearchItem.GetCommand() == SvxSearchCmd::FIND ) ||
1242          ( rSearchItem.GetCommand() == SvxSearchCmd::FIND_ALL ) )
1243     {
1244         nFound = pView->Search( rSearchItem.GetSearchOptions() , bForward ) ? 1 : 0;
1245     }
1246     else if ( ( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE ) ||
1247               ( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL ) )
1248     {
1249         if ( !IsReadOnly() )
1250         {
1251             bool const bAll = rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL;
1252             nFound = pView->Replace( rSearchItem.GetSearchOptions() , bAll , bForward );
1253         }
1254     }
1255 
1256     if ( bFromStart && !nFound )
1257         pView->SetSelection( aSel );
1258 
1259     return nFound;
1260 }
1261 
1262 SfxUndoManager* ModulWindow::GetUndoManager()
1263 {
1264     if ( GetEditEngine() )
1265         return &GetEditEngine()->GetUndoManager();
1266     return nullptr;
1267 }
1268 
1269 SearchOptionFlags ModulWindow::GetSearchOptions()
1270 {
1271     SearchOptionFlags nOptions = SearchOptionFlags::SEARCH |
1272                       SearchOptionFlags::WHOLE_WORDS |
1273                       SearchOptionFlags::BACKWARDS |
1274                       SearchOptionFlags::REG_EXP |
1275                       SearchOptionFlags::EXACT |
1276                       SearchOptionFlags::SELECTION |
1277                       SearchOptionFlags::SIMILARITY;
1278 
1279     if ( !IsReadOnly() )
1280     {
1281         nOptions |= SearchOptionFlags::REPLACE;
1282         nOptions |= SearchOptionFlags::REPLACE_ALL;
1283     }
1284 
1285     return nOptions;
1286 }
1287 
1288 void ModulWindow::BasicStarted()
1289 {
1290     if ( XModule().is() )
1291     {
1292         m_aStatus.bIsRunning = true;
1293         BreakPointList& rList = GetBreakPoints();
1294         if ( rList.size() )
1295         {
1296             rList.ResetHitCount();
1297             rList.SetBreakPointsInBasic( m_xModule.get() );
1298             for ( sal_uInt32 nMethod = 0; nMethod < m_xModule->GetMethods()->Count32(); nMethod++ )
1299             {
1300                 SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->GetMethods()->Get32( nMethod ));
1301                 assert(pMethod && "Method not found! (NULL)");
1302                 pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
1303             }
1304         }
1305     }
1306 }
1307 
1308 void ModulWindow::BasicStopped()
1309 {
1310     m_aStatus.bIsRunning = false;
1311     GetBreakPointWindow().SetNoMarker();
1312 }
1313 
1314 EntryDescriptor ModulWindow::CreateEntryDescriptor()
1315 {
1316     ScriptDocument aDocument( GetDocument() );
1317     OUString aLibName( GetLibName() );
1318     LibraryLocation eLocation = aDocument.getLibraryLocation( aLibName );
1319     OUString aModName( GetName() );
1320     OUString aLibSubName;
1321     if( m_xBasic.is() && aDocument.isInVBAMode() && XModule().is() )
1322     {
1323         switch( m_xModule->GetModuleType() )
1324         {
1325             case script::ModuleType::DOCUMENT:
1326             {
1327                 aLibSubName = IDEResId( RID_STR_DOCUMENT_OBJECTS );
1328                 uno::Reference< container::XNameContainer > xLib = aDocument.getOrCreateLibrary( E_SCRIPTS, aLibName );
1329                 if( xLib.is() )
1330                 {
1331                     OUString sObjName;
1332                     ModuleInfoHelper::getObjectName( xLib, aModName, sObjName );
1333                     if( !sObjName.isEmpty() )
1334                     {
1335                         aModName += " (" + sObjName + ")";
1336                     }
1337                 }
1338                 break;
1339             }
1340             case script::ModuleType::FORM:
1341                 aLibSubName = IDEResId( RID_STR_USERFORMS );
1342                 break;
1343             case script::ModuleType::NORMAL:
1344                 aLibSubName = IDEResId( RID_STR_NORMAL_MODULES );
1345                 break;
1346             case script::ModuleType::CLASS:
1347                 aLibSubName = IDEResId( RID_STR_CLASS_MODULES );
1348                 break;
1349         }
1350     }
1351     return EntryDescriptor( aDocument, eLocation, aLibName, aLibSubName, aModName, OBJ_TYPE_MODULE );
1352 }
1353 
1354 void ModulWindow::SetReadOnly (bool b)
1355 {
1356     if ( GetEditView() )
1357         GetEditView()->SetReadOnly( b );
1358 }
1359 
1360 bool ModulWindow::IsReadOnly()
1361 {
1362     return GetEditView() && GetEditView()->IsReadOnly();
1363 }
1364 
1365 bool ModulWindow::IsPasteAllowed()
1366 {
1367     bool bPaste = false;
1368 
1369     // get clipboard
1370     Reference< datatransfer::clipboard::XClipboard > xClipboard = GetClipboard();
1371     if ( xClipboard.is() )
1372     {
1373 
1374         Reference< datatransfer::XTransferable > xTransf;
1375         {
1376             SolarMutexReleaser aReleaser;
1377             // get clipboard content
1378             xTransf = xClipboard->getContents();
1379         }
1380         if ( xTransf.is() )
1381         {
1382             datatransfer::DataFlavor aFlavor;
1383             SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
1384             if ( xTransf->isDataFlavorSupported( aFlavor ) )
1385                 bPaste = true;
1386         }
1387     }
1388 
1389     return bPaste;
1390 }
1391 
1392 void ModulWindow::OnNewDocument ()
1393 {
1394     bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1395     m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
1396 }
1397 
1398 char const* ModulWindow::GetHid () const
1399 {
1400     return HID_BASICIDE_MODULWINDOW;
1401 }
1402 ItemType ModulWindow::GetType () const
1403 {
1404     return TYPE_MODULE;
1405 }
1406 
1407 bool ModulWindow::HasActiveEditor () const
1408 {
1409     return !IsSuspended();
1410 }
1411 
1412 
1413 void ModulWindow::UpdateModule ()
1414 {
1415     OUString const aModule = getTextEngineText(*GetEditEngine());
1416 
1417     // update module in basic
1418     assert(m_xModule.is());
1419 
1420     // update module in module window
1421     SetModule(aModule);
1422 
1423     // update module in library
1424     OSL_VERIFY(m_aDocument.updateModule(m_aLibName, m_aName, aModule));
1425 
1426     GetEditEngine()->SetModified(false);
1427     MarkDocumentModified(m_aDocument);
1428 }
1429 
1430 ModulWindowLayout::ModulWindowLayout (vcl::Window* pParent, ObjectCatalog& rObjectCatalog_) :
1431     Layout(pParent),
1432     pChild(nullptr),
1433     aWatchWindow(VclPtr<WatchWindow>::Create(this)),
1434     aStackWindow(VclPtr<StackWindow>::Create(this)),
1435     rObjectCatalog(rObjectCatalog_)
1436 { }
1437 
1438 ModulWindowLayout::~ModulWindowLayout()
1439 {
1440     disposeOnce();
1441 }
1442 
1443 void ModulWindowLayout::dispose()
1444 {
1445     aWatchWindow.disposeAndClear();
1446     aStackWindow.disposeAndClear();
1447     pChild.clear();
1448     Layout::dispose();
1449 }
1450 
1451 void ModulWindowLayout::UpdateDebug (bool bBasicStopped)
1452 {
1453     aWatchWindow->UpdateWatches(bBasicStopped);
1454     aStackWindow->UpdateCalls();
1455 }
1456 
1457 void ModulWindowLayout::Paint (vcl::RenderContext& rRenderContext, tools::Rectangle const&)
1458 {
1459     rRenderContext.DrawText(Point(), IDEResId(RID_STR_NOMODULE));
1460 }
1461 
1462 void ModulWindowLayout::Activating (BaseWindow& rChild)
1463 {
1464     assert(dynamic_cast<ModulWindow*>(&rChild));
1465     pChild = &static_cast<ModulWindow&>(rChild);
1466     aWatchWindow->Show();
1467     aStackWindow->Show();
1468     rObjectCatalog.Show();
1469     rObjectCatalog.SetLayoutWindow(this);
1470     rObjectCatalog.UpdateEntries();
1471     Layout::Activating(rChild);
1472     aSyntaxColors.SetActiveEditor(&pChild->GetEditorWindow());
1473 }
1474 
1475 void ModulWindowLayout::Deactivating ()
1476 {
1477     aSyntaxColors.SetActiveEditor(nullptr);
1478     Layout::Deactivating();
1479     aWatchWindow->Hide();
1480     aStackWindow->Hide();
1481     rObjectCatalog.Hide();
1482     pChild = nullptr;
1483 }
1484 
1485 void ModulWindowLayout::GetState (SfxItemSet &rSet, unsigned nWhich)
1486 {
1487     switch (nWhich)
1488     {
1489         case SID_SHOW_PROPERTYBROWSER:
1490             rSet.Put(SfxVisibilityItem(nWhich, false));
1491             break;
1492 
1493         case SID_BASICIDE_CHOOSEMACRO:
1494             rSet.Put(SfxVisibilityItem(nWhich, true));
1495             break;
1496     }
1497 }
1498 
1499 void ModulWindowLayout::BasicAddWatch (OUString const& rWatchStr)
1500 {
1501     aWatchWindow->AddWatch(rWatchStr);
1502 }
1503 
1504 void ModulWindowLayout::BasicRemoveWatch ()
1505 {
1506     aWatchWindow->RemoveSelectedWatch();
1507 }
1508 
1509 void ModulWindowLayout::OnFirstSize (long const nWidth, long const nHeight)
1510 {
1511     AddToLeft(&rObjectCatalog, Size(nWidth * 0.20, nHeight * 0.75));
1512     AddToBottom(aWatchWindow.get(), Size(nWidth * 0.67, nHeight * 0.25));
1513     AddToBottom(aStackWindow.get(), Size(nWidth * 0.33, nHeight * 0.25));
1514 }
1515 
1516 ModulWindowLayout::SyntaxColors::SyntaxColors () :
1517     pEditor(nullptr)
1518 {
1519     aConfig.AddListener(this);
1520 
1521     NewConfig(true);
1522 }
1523 
1524 ModulWindowLayout::SyntaxColors::~SyntaxColors ()
1525 {
1526     aConfig.RemoveListener(this);
1527 }
1528 
1529 // virtual
1530 void ModulWindowLayout::SyntaxColors::ConfigurationChanged (utl::ConfigurationBroadcaster*, ConfigurationHints)
1531 {
1532     NewConfig(false);
1533 }
1534 
1535 // when a new configuration has to be set
1536 void ModulWindowLayout::SyntaxColors::NewConfig (bool bFirst)
1537 {
1538     static struct
1539     {
1540         TokenType eTokenType;
1541         svtools::ColorConfigEntry eEntry;
1542     }
1543     const vIds[] =
1544     {
1545         { TokenType::Unknown,     svtools::FONTCOLOR },
1546         { TokenType::Identifier,  svtools::BASICIDENTIFIER },
1547         { TokenType::Whitespace,  svtools::FONTCOLOR },
1548         { TokenType::Number,      svtools::BASICNUMBER },
1549         { TokenType::String,      svtools::BASICSTRING },
1550         { TokenType::EOL,         svtools::FONTCOLOR },
1551         { TokenType::Comment,     svtools::BASICCOMMENT },
1552         { TokenType::Error,       svtools::BASICERROR },
1553         { TokenType::Operator,    svtools::BASICOPERATOR },
1554         { TokenType::Keywords,    svtools::BASICKEYWORD },
1555     };
1556 
1557     Color aDocColor = aConfig.GetColorValue(svtools::DOCCOLOR).nColor;
1558     if (bFirst || aDocColor != m_aBackgroundColor)
1559     {
1560         m_aBackgroundColor = aDocColor;
1561         if (!bFirst && pEditor)
1562         {
1563             pEditor->SetBackground(Wallpaper(m_aBackgroundColor));
1564             pEditor->Invalidate();
1565         }
1566     }
1567 
1568     Color aFontColor = aConfig.GetColorValue(svtools::FONTCOLOR).nColor;
1569     if (bFirst || aFontColor != m_aFontColor)
1570     {
1571         m_aFontColor = aFontColor;
1572         if (!bFirst && pEditor)
1573             pEditor->ChangeFontColor(m_aFontColor);
1574     }
1575 
1576     bool bChanged = false;
1577     for (unsigned i = 0; i != SAL_N_ELEMENTS(vIds); ++i)
1578     {
1579         Color const aColor = aConfig.GetColorValue(vIds[i].eEntry).nColor;
1580         Color& rMyColor = aColors[vIds[i].eTokenType];
1581         if (bFirst || aColor != rMyColor)
1582         {
1583             rMyColor = aColor;
1584             bChanged = true;
1585         }
1586     }
1587     if (bChanged && !bFirst && pEditor)
1588         pEditor->UpdateSyntaxHighlighting();
1589 }
1590 
1591 } // namespace basctl
1592 
1593 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1594