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