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