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