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