1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "baside2.hxx"
21 #include <baside3.hxx>
23 #include <iderdll.hxx>
24 #include "moduldlg.hxx"
25 #include <docsignature.hxx>
26 #include <officecfg/Office/BasicIDE.hxx>
29 #include <strings.hrc>
31 #include <basic/basmgr.hxx>
32 #include <basic/basrdll.hxx>
33 #include <basic/sbmeth.hxx>
34 #include <com/sun/star/script/ModuleType.hpp>
35 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
36 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
37 #include <com/sun/star/ui/dialogs/FilePicker.hpp>
38 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
39 #include <comphelper/string.hxx>
40 #include <sfx2/dinfdlg.hxx>
41 #include <sfx2/dispatch.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <sfx2/printer.hxx>
44 #include <sfx2/request.hxx>
45 #include <sot/exchange.hxx>
46 #include <svl/aeitem.hxx>
47 #include <svl/srchitem.hxx>
48 #include <svl/visitem.hxx>
49 #include <svl/whiter.hxx>
50 #include <svx/svxids.hrc>
51 #include <vcl/settings.hxx>
52 #include <vcl/weld.hxx>
53 #include <vcl/xtextedt.hxx>
54 #include <toolkit/helper/vclunohelper.hxx>
65 long const nLeftMargin
= 1700;
66 long const nRightMargin
= 900;
67 long const nTopMargin
= 2000;
68 long const nBottomMargin
= 1000;
69 long const nBorder
= 300;
72 short const ValidWindow
= 0x1234;
74 // What (who) are OW and MTF? Compare to baside3.cxx where an
75 // identically named variable, used in the same way, has the value
76 // "*.*" on Windows, "*" otherwise. Is that what should be done here,
79 #if defined(OW) || defined(MTF)
80 char const FilterMask_All
[] = "*";
82 char const FilterMask_All
[] = "*.*";
85 } // end anonymous namespace
87 using namespace ::com::sun::star
;
88 using namespace ::com::sun::star::uno
;
89 using namespace ::com::sun::star::ui::dialogs
;
91 using namespace comphelper
;
96 void lcl_PrintHeader( Printer
* pPrinter
, sal_uInt16 nPages
, sal_uInt16 nCurPage
, const OUString
& rTitle
, bool bOutput
)
98 Size
const aSz
= pPrinter
->GetOutputSize();
100 const Color
aOldLineColor( pPrinter
->GetLineColor() );
101 const Color
aOldFillColor( pPrinter
->GetFillColor() );
102 const vcl::Font
aOldFont( pPrinter
->GetFont() );
104 pPrinter
->SetLineColor( COL_BLACK
);
105 pPrinter
->SetFillColor();
107 vcl::Font
aFont( aOldFont
);
108 aFont
.SetWeight( WEIGHT_BOLD
);
109 aFont
.SetAlignment( ALIGN_BOTTOM
);
110 pPrinter
->SetFont( aFont
);
112 long nFontHeight
= pPrinter
->GetTextHeight();
114 // 1st Border => line, 2+3 Border = free space
115 long nYTop
= Print::nTopMargin
- 3*Print::nBorder
- nFontHeight
;
117 long nXLeft
= Print::nLeftMargin
- Print::nBorder
;
118 long nXRight
= aSz
.Width() - Print::nRightMargin
+ Print::nBorder
;
121 pPrinter
->DrawRect(tools::Rectangle(
122 Point(nXLeft
, nYTop
),
123 Size(nXRight
- nXLeft
, aSz
.Height() - nYTop
- Print::nBottomMargin
+ Print::nBorder
)
127 long nY
= Print::nTopMargin
- 2*Print::nBorder
;
128 Point
aPos(Print::nLeftMargin
, nY
);
130 pPrinter
->DrawText( aPos
, rTitle
);
133 aFont
.SetWeight( WEIGHT_NORMAL
);
134 pPrinter
->SetFont( aFont
);
135 aPos
.AdjustX(pPrinter
->GetTextWidth( rTitle
) );
139 OUString aPageStr
= " [" + IDEResId(RID_STR_PAGE
) + " " + OUString::number( nCurPage
) + "]";
140 pPrinter
->DrawText( aPos
, aPageStr
);
144 nY
= Print::nTopMargin
- Print::nBorder
;
147 pPrinter
->DrawLine( Point( nXLeft
, nY
), Point( nXRight
, nY
) );
149 pPrinter
->SetFont( aOldFont
);
150 pPrinter
->SetFillColor( aOldFillColor
);
151 pPrinter
->SetLineColor( aOldLineColor
);
154 void lcl_ConvertTabsToSpaces( OUString
& rLine
)
156 if ( !rLine
.isEmpty() )
158 OUStringBuffer
aResult( rLine
);
160 sal_Int32 nMax
= aResult
.getLength();
161 while ( nPos
< nMax
)
163 if ( aResult
[nPos
] == '\t' )
165 // not 4 Blanks, but at 4 TabPos:
166 OUStringBuffer aBlanker
;
167 string::padToLength(aBlanker
, ( 4 - ( nPos
% 4 ) ), ' ');
168 aResult
.remove( nPos
, 1 );
169 aResult
.insert( nPos
, aBlanker
.makeStringAndClear() );
170 nMax
= aResult
.getLength();
174 rLine
= aResult
.makeStringAndClear();
180 ModulWindow::ModulWindow (ModulWindowLayout
* pParent
, ScriptDocument
const& rDocument
,
181 const OUString
& aLibName
, const OUString
& aName
, OUString
const & aModule
)
182 : BaseWindow(pParent
, rDocument
, aLibName
, aName
)
183 , m_rLayout(*pParent
)
184 , m_nValid(ValidWindow
)
185 , m_aXEditorWindow(VclPtr
<ComplexEditorWindow
>::Create(this))
188 m_aXEditorWindow
->Show();
192 SbModuleRef
const & ModulWindow::XModule()
194 // ModuleWindows can now be created as a result of the
195 // modules getting created via the api. This is a result of an
196 // elementInserted event from the BasicLibrary container.
197 // However the SbModule is also created from a different listener to
198 // the same event ( in basmgr ) Therefore it is possible when we look
199 // for m_xModule it may not yet be available, here we keep trying to access
200 // the module until such time as it exists
202 if ( !m_xModule
.is() )
204 BasicManager
* pBasMgr
= GetDocument().getBasicManager();
207 StarBASIC
* pBasic
= pBasMgr
->GetLib( GetLibName() );
211 m_xModule
= pBasic
->FindModule( GetName() );
218 ModulWindow::~ModulWindow()
223 void ModulWindow::dispose()
227 m_aXEditorWindow
.disposeAndClear();
228 BaseWindow::dispose();
232 void ModulWindow::GetFocus()
234 if (m_nValid
!= ValidWindow
)
236 m_aXEditorWindow
->GetEdtWindow().GrabFocus();
237 // don't call basic calls because focus is somewhere else...
240 void ModulWindow::DoInit()
243 GetVScrollBar()->Hide();
244 GetHScrollBar()->Show();
245 GetEditorWindow().InitScrollBars();
248 void ModulWindow::Paint(vcl::RenderContext
& /*rRenderContext*/, const tools::Rectangle
&)
252 void ModulWindow::Resize()
254 m_aXEditorWindow
->SetPosSizePixel( Point( 0, 0 ), GetOutputSizePixel() );
257 void ModulWindow::CheckCompileBasic()
259 if ( XModule().is() )
261 // never compile while running!
262 bool const bRunning
= StarBASIC::IsRunning();
263 bool const bModified
= ( !m_xModule
->IsCompiled() ||
264 ( GetEditEngine() && GetEditEngine()->IsModified() ) );
266 if ( !bRunning
&& bModified
)
270 GetShell()->GetViewFrame()->GetWindow().EnterWait();
274 AssertValidEditEngine();
275 GetEditorWindow().SetSourceInBasic();
278 bool bWasModified
= GetBasic()->IsModified();
280 bDone
= m_xModule
->Compile();
282 GetBasic()->SetModified(false);
286 GetBreakPoints().SetBreakPointsInBasic( m_xModule
.get() );
289 GetShell()->GetViewFrame()->GetWindow().LeaveWait();
291 m_aStatus
.bError
= !bDone
;
292 m_aStatus
.bIsRunning
= false;
297 void ModulWindow::BasicExecute()
299 // #116444# check security settings before macro execution
300 ScriptDocument
aDocument( GetDocument() );
301 if ( aDocument
.isDocument() )
303 if ( !aDocument
.allowMacros() )
305 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(GetFrameWeld(),
306 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_CANNOTRUNMACRO
)));
314 if ( XModule().is() && m_xModule
->IsCompiled() && !m_aStatus
.bError
)
316 if ( GetBreakPoints().size() )
317 m_aStatus
.nBasicFlags
= m_aStatus
.nBasicFlags
| BasicDebugFlags::Break
;
319 if ( !m_aStatus
.bIsRunning
)
321 DBG_ASSERT( m_xModule
.is(), "No Module!" );
322 AddStatus( BASWIN_RUNNINGBASIC
);
323 sal_uInt16 nStart
, nEnd
;
324 TextSelection aSel
= GetEditView()->GetSelection();
325 // Init cursor to top
326 const sal_uInt32 nCurMethodStart
= aSel
.GetStart().GetPara() + 1;
327 SbMethod
* pMethod
= nullptr;
328 // first Macro, else blind "Main" (ExtSearch?)
329 for ( sal_uInt16 nMacro
= 0; nMacro
< m_xModule
->GetMethods()->Count(); nMacro
++ )
331 SbMethod
* pM
= static_cast<SbMethod
*>(m_xModule
->GetMethods()->Get( nMacro
));
332 assert(pM
&& "Method?");
333 pM
->GetLineRange( nStart
, nEnd
);
334 if ( nCurMethodStart
>= nStart
&& nCurMethodStart
<= nEnd
)
336 // matched a method to the cursor position
343 // If not in a method then prompt the user
344 ChooseMacro( uno::Reference
< frame::XModel
>() );
349 pMethod
->SetDebugFlags( m_aStatus
.nBasicFlags
);
350 BasicDLL::SetDebugMode( true );
351 RunMethod( pMethod
);
352 BasicDLL::SetDebugMode( false );
353 // if cancelled during Interactive=false
354 BasicDLL::EnableBreak( true );
356 ClearStatus( BASWIN_RUNNINGBASIC
);
359 m_aStatus
.bIsRunning
= false; // cancel of Reschedule()
363 void ModulWindow::CompileBasic()
367 XModule().is() && m_xModule
->IsCompiled();
370 void ModulWindow::BasicRun()
372 m_aStatus
.nBasicFlags
= BasicDebugFlags::NONE
;
376 void ModulWindow::BasicStepOver()
378 m_aStatus
.nBasicFlags
= BasicDebugFlags::StepInto
| BasicDebugFlags::StepOver
;
383 void ModulWindow::BasicStepInto()
385 m_aStatus
.nBasicFlags
= BasicDebugFlags::StepInto
;
389 void ModulWindow::BasicStepOut()
391 m_aStatus
.nBasicFlags
= BasicDebugFlags::StepOut
;
396 void ModulWindow::BasicStop()
399 m_aStatus
.bIsRunning
= false;
402 void ModulWindow::LoadBasic()
404 Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
405 Reference
< XFilePicker3
> xFP
= FilePicker::createWithMode(xContext
, TemplateDescription::FILEOPEN_SIMPLE
);
407 if ( !m_sCurPath
.isEmpty() )
408 xFP
->setDisplayDirectory ( m_sCurPath
);
410 xFP
->appendFilter( "BASIC" , "*.bas" );
411 xFP
->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES
), FilterMask_All
);
412 xFP
->setCurrentFilter( "BASIC" );
414 if( xFP
->execute() == RET_OK
)
416 Sequence
< OUString
> aPaths
= xFP
->getSelectedFiles();
417 m_sCurPath
= aPaths
[0];
418 SfxMedium
aMedium( m_sCurPath
, StreamMode::READ
| StreamMode::SHARE_DENYWRITE
| StreamMode::NOCREATE
);
419 SvStream
* pStream
= aMedium
.GetInStream();
422 AssertValidEditEngine();
423 sal_uInt32 nLines
= CalcLineCount( *pStream
);
424 // nLines*4: ReadText/Formatting/Highlighting/Formatting
425 GetEditorWindow().CreateProgress( IDEResId(RID_STR_GENERATESOURCE
), nLines
*4 );
426 GetEditEngine()->SetUpdateMode( false );
427 GetEditView()->Read( *pStream
);
428 GetEditEngine()->SetUpdateMode( true );
429 GetEditorWindow().Update();
430 GetEditorWindow().ForceSyntaxTimeout();
431 GetEditorWindow().DestroyProgress();
432 ErrCode nError
= aMedium
.GetError();
434 ErrorHandler::HandleError( nError
);
438 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(GetFrameWeld(),
439 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_COULDNTREAD
)));
446 void ModulWindow::SaveBasicSource()
448 Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
449 Reference
< XFilePicker3
> xFP
= FilePicker::createWithMode(xContext
, TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD
);
451 Reference
< XFilePickerControlAccess
> xFPControl(xFP
, UNO_QUERY
);
452 xFPControl
->enableControl(ExtendedFilePickerElementIds::CHECKBOX_PASSWORD
, false);
455 xFPControl
->setValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION
, 0, aValue
);
457 if ( !m_sCurPath
.isEmpty() )
458 xFP
->setDisplayDirectory ( m_sCurPath
);
460 xFP
->appendFilter( "BASIC", "*.bas" );
461 xFP
->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES
), FilterMask_All
);
462 xFP
->setCurrentFilter( "BASIC" );
464 if( xFP
->execute() == RET_OK
)
466 Sequence
< OUString
> aPaths
= xFP
->getSelectedFiles();
467 m_sCurPath
= aPaths
[0];
468 SfxMedium
aMedium( m_sCurPath
, StreamMode::WRITE
| StreamMode::SHARE_DENYWRITE
| StreamMode::TRUNC
);
469 SvStream
* pStream
= aMedium
.GetOutStream();
473 AssertValidEditEngine();
474 GetEditEngine()->Write( *pStream
);
477 ErrCode nError
= aMedium
.GetError();
479 ErrorHandler::HandleError( nError
);
483 std::unique_ptr
<weld::MessageDialog
> xErrorBox(Application::CreateMessageDialog(GetFrameWeld(),
484 VclMessageType::Warning
, VclButtonsType::Ok
, IDEResId(RID_STR_COULDNTWRITE
)));
490 void ModulWindow::ImportDialog()
492 const ScriptDocument
& rDocument
= GetDocument();
493 OUString aLibName
= GetLibName();
494 implImportDialog(GetFrameWeld(), m_sCurPath
, rDocument
, aLibName
);
497 void ModulWindow::ToggleBreakPoint( sal_uLong nLine
)
499 DBG_ASSERT( XModule().is(), "No Modul!" );
501 if ( XModule().is() )
504 if ( m_aStatus
.bError
)
509 BreakPoint
* pBrk
= GetBreakPoints().FindBreakPoint( nLine
);
510 if ( pBrk
) // remove
512 m_xModule
->ClearBP( static_cast<sal_uInt16
>(nLine
) );
513 delete GetBreakPoints().remove( pBrk
);
517 if ( m_xModule
->SetBP( static_cast<sal_uInt16
>(nLine
)) )
519 GetBreakPoints().InsertSorted( new BreakPoint( nLine
) );
520 if ( StarBASIC::IsRunning() )
522 for ( sal_uInt16 nMethod
= 0; nMethod
< m_xModule
->GetMethods()->Count(); nMethod
++ )
524 SbMethod
* pMethod
= static_cast<SbMethod
*>(m_xModule
->GetMethods()->Get( nMethod
));
525 assert(pMethod
&& "Method not found! (NULL)");
526 pMethod
->SetDebugFlags( pMethod
->GetDebugFlags() | BasicDebugFlags::Break
);
534 void ModulWindow::UpdateBreakPoint( const BreakPoint
& rBrk
)
536 DBG_ASSERT( XModule().is(), "No Module!" );
538 if ( XModule().is() )
543 m_xModule
->SetBP( static_cast<sal_uInt16
>(rBrk
.nLine
) );
545 m_xModule
->ClearBP( static_cast<sal_uInt16
>(rBrk
.nLine
) );
550 void ModulWindow::BasicToggleBreakPoint()
552 AssertValidEditEngine();
554 TextSelection aSel
= GetEditView()->GetSelection();
555 aSel
.GetStart().GetPara()++; // Basic lines start at 1!
556 aSel
.GetEnd().GetPara()++;
558 for ( sal_uInt32 nLine
= aSel
.GetStart().GetPara(); nLine
<= aSel
.GetEnd().GetPara(); ++nLine
)
560 ToggleBreakPoint( nLine
);
563 m_aXEditorWindow
->GetBrkWindow().Invalidate();
567 void ModulWindow::BasicToggleBreakPointEnabled()
569 AssertValidEditEngine();
571 TextView
* pView
= GetEditView();
574 TextSelection aSel
= pView
->GetSelection();
575 BreakPointList
& rList
= GetBreakPoints();
577 for ( sal_uInt32 nLine
= ++aSel
.GetStart().GetPara(), nEnd
= ++aSel
.GetEnd().GetPara(); nLine
<= nEnd
; ++nLine
)
579 BreakPoint
* pBrk
= rList
.FindBreakPoint( nLine
);
582 pBrk
->bEnabled
= !pBrk
->bEnabled
;
583 UpdateBreakPoint( *pBrk
);
587 GetBreakPointWindow().Invalidate();
592 void ModulWindow::ManageBreakPoints()
594 BreakPointWindow
& rBrkWin
= GetBreakPointWindow();
595 ScopedVclPtrInstance
< BreakPointDialog
> aBrkDlg( &rBrkWin
, GetBreakPoints() );
597 rBrkWin
.Invalidate();
601 bool ModulWindow::BasicErrorHdl( StarBASIC
const * pBasic
)
603 GetShell()->GetViewFrame()->ToTop();
605 // Return value: BOOL
608 sal_uInt16 nErrorLine
= StarBASIC::GetLine() - 1;
609 sal_uInt16 nErrCol1
= StarBASIC::GetCol1();
610 sal_uInt16 nErrCol2
= StarBASIC::GetCol2();
611 if ( nErrCol2
!= 0xFFFF )
614 AssertValidEditEngine();
615 GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine
, nErrCol1
), TextPaM( nErrorLine
, nErrCol2
) ) );
617 // if other basic, the IDE should try to display the correct module
618 bool const bMarkError
= pBasic
== GetBasic();
620 m_aXEditorWindow
->GetBrkWindow().SetMarkerPos(nErrorLine
, true);
623 Reference
< awt::XWindow
> xWindow
= VCLUnoHelper::GetInterface( this );
625 ErrorHandler::HandleError( StarBASIC::GetErrorCode() );
628 VclPtr
<vcl::Window
> pWindow
= VCLUnoHelper::GetWindow( xWindow
);
633 m_aXEditorWindow
->GetBrkWindow().SetNoMarker();
637 BasicDebugFlags
ModulWindow::BasicBreakHdl()
639 // Return value: sal_uInt16 => see SB-Debug-Flags
640 sal_uInt16 nErrorLine
= StarBASIC::GetLine();
643 BreakPoint
* pBrk
= GetBreakPoints().FindBreakPoint( nErrorLine
);
647 if ( pBrk
->nHitCount
<= pBrk
->nStopAfter
&& GetBasic()->IsBreak() )
648 return m_aStatus
.nBasicFlags
; // go on...
651 nErrorLine
--; // EditEngine starts at 0, Basic at 1
653 AssertValidEditEngine();
654 GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine
, 0 ), TextPaM( nErrorLine
, 0 ) ) );
655 m_aXEditorWindow
->GetBrkWindow().SetMarkerPos( nErrorLine
);
657 m_rLayout
.UpdateDebug(false);
659 m_aStatus
.bIsInReschedule
= true;
660 m_aStatus
.bIsRunning
= true;
662 AddStatus( BASWIN_INRESCHEDULE
);
664 InvalidateDebuggerSlots();
666 while( m_aStatus
.bIsRunning
)
667 Application::Yield();
669 m_aStatus
.bIsInReschedule
= false;
670 m_aXEditorWindow
->GetBrkWindow().SetNoMarker();
672 ClearStatus( BASWIN_INRESCHEDULE
);
674 return m_aStatus
.nBasicFlags
;
677 void ModulWindow::BasicAddWatch()
679 AssertValidEditEngine();
681 if ( !GetEditView()->HasSelection() )
684 OUString aWord
= GetEditEngine()->GetWord( GetEditView()->GetSelection().GetEnd(), &aWordStart
);
685 if ( !aWord
.isEmpty() )
687 TextSelection
aSel( aWordStart
);
688 aSel
.GetEnd().GetIndex() += aWord
.getLength();
689 GetEditView()->SetSelection( aSel
);
696 TextSelection aSel
= GetEditView()->GetSelection();
697 if ( aSel
.GetStart().GetPara() == aSel
.GetEnd().GetPara() ) // single line selection
698 m_rLayout
.BasicAddWatch(GetEditView()->GetSelected());
703 void ModulWindow::EditMacro( const OUString
& rMacroName
)
705 DBG_ASSERT( XModule().is(), "No Module!" );
707 if ( XModule().is() )
711 if ( !m_aStatus
.bError
)
713 sal_uInt16 nStart
, nEnd
;
714 SbMethod
* pMethod
= static_cast<SbMethod
*>(m_xModule
->Find( rMacroName
, SbxClassType::Method
));
717 pMethod
->GetLineRange( nStart
, nEnd
);
723 TextSelection
aSel( TextPaM( nStart
, 0 ), TextPaM( nStart
, 0 ) );
724 AssertValidEditEngine();
725 TextView
* pView
= GetEditView();
726 // scroll if applicable so that first line is at the top
727 long nVisHeight
= GetOutputSizePixel().Height();
728 if ( pView
->GetTextEngine()->GetTextHeight() > nVisHeight
)
730 long nMaxY
= pView
->GetTextEngine()->GetTextHeight() - nVisHeight
;
731 long nOldStartY
= pView
->GetStartDocPos().Y();
732 long nNewStartY
= static_cast<long>(nStart
) * pView
->GetTextEngine()->GetCharHeight();
733 nNewStartY
= std::min( nNewStartY
, nMaxY
);
734 pView
->Scroll( 0, -(nNewStartY
-nOldStartY
) );
735 pView
->ShowCursor( false );
736 GetEditVScrollBar().SetThumbPos( pView
->GetStartDocPos().Y() );
738 pView
->SetSelection( aSel
);
740 pView
->GetWindow()->GrabFocus();
746 void ModulWindow::StoreData()
748 // StoreData is called when the BasicManager is destroyed or
749 // this window is closed.
750 // => interrupts undesired!
751 GetEditorWindow().SetSourceInBasic();
754 bool ModulWindow::CanClose()
759 bool ModulWindow::AllowUndo()
761 return GetEditorWindow().CanModify();
764 void ModulWindow::UpdateData()
766 DBG_ASSERT( XModule().is(), "No Module!" );
767 // UpdateData is called when the source has changed from outside
768 // => interrupts undesired!
770 if ( XModule().is() )
772 SetModule( m_xModule
->GetSource32() );
776 TextSelection aSel
= GetEditView()->GetSelection();
777 setTextEngineText(*GetEditEngine(), m_xModule
->GetSource32());
778 GetEditView()->SetSelection( aSel
);
779 GetEditEngine()->SetModified( false );
780 MarkDocumentModified( GetDocument() );
785 sal_Int32
ModulWindow::countPages( Printer
* pPrinter
)
787 return FormatAndPrint( pPrinter
, -1 );
790 void ModulWindow::printPage( sal_Int32 nPage
, Printer
* pPrinter
)
792 FormatAndPrint( pPrinter
, nPage
);
795 /* implementation note: this is totally inefficient for the XRenderable interface
796 usage since the whole "document" will be format for every page. Should this ever
797 become a problem we should
798 - format only once for every new printer
799 - keep an index list for each page which is the starting paragraph
801 sal_Int32
ModulWindow::FormatAndPrint( Printer
* pPrinter
, sal_Int32 nPrintPage
)
803 AssertValidEditEngine();
805 MapMode
eOldMapMode( pPrinter
->GetMapMode() );
806 vcl::Font
aOldFont( pPrinter
->GetFont() );
808 vcl::Font
aFont( GetEditEngine()->GetFont() );
809 aFont
.SetAlignment( ALIGN_BOTTOM
);
810 aFont
.SetTransparent( true );
811 aFont
.SetFontSize( Size( 0, 360 ) );
812 pPrinter
->SetFont( aFont
);
813 pPrinter
->SetMapMode(MapMode(MapUnit::Map100thMM
));
815 OUString
aTitle( CreateQualifiedName() );
817 sal_Int32 nLineHeight
= pPrinter
->GetTextHeight();
823 Size aPaperSz
= pPrinter
->GetOutputSize();
824 aPaperSz
.AdjustWidth( -(Print::nLeftMargin
+ Print::nRightMargin
) );
825 aPaperSz
.AdjustHeight( -(Print::nTopMargin
+ Print::nBottomMargin
) );
827 // nLinepPage is not correct if there's a line break
828 sal_Int32 nLinespPage
= aPaperSz
.Height()/nLineHeight
;
829 long nXTextWidth
= pPrinter
->approximate_char_width();
831 sal_Int32 nCharspLine
= aPaperSz
.Width() / std::max
<long>(nXTextWidth
, 1);
832 const sal_uInt32 nParas
= GetEditEngine()->GetParagraphCount();
834 sal_Int32 nPages
= nParas
/nLinespPage
+1;
835 sal_Int32 nCurPage
= 1;
837 lcl_PrintHeader( pPrinter
, nPages
, nCurPage
, aTitle
, nPrintPage
== 0 );
838 Point
aPos( Print::nLeftMargin
, Print::nTopMargin
);
839 for ( sal_uInt32 nPara
= 0; nPara
< nParas
; ++nPara
)
841 OUString
aLine( GetEditEngine()->GetText( nPara
) );
842 lcl_ConvertTabsToSpaces( aLine
);
843 sal_Int32 nLines
= aLine
.getLength()/nCharspLine
+1;
844 for (sal_Int32 nLine
= 0; nLine
< nLines
; ++nLine
)
846 sal_Int32 nBeginIndex
= nLine
*nCharspLine
;
847 sal_Int32 nCopyCount
= std::min
<sal_Int32
>(nCharspLine
, aLine
.getLength()-nBeginIndex
);
848 OUString aTmpLine
= aLine
.copy(nBeginIndex
, nCopyCount
);
849 aPos
.AdjustY(nLineHeight
);
850 if ( aPos
.Y() > ( aPaperSz
.Height() + Print::nTopMargin
) )
853 lcl_PrintHeader( pPrinter
, nPages
, nCurPage
, aTitle
, nCurPage
-1 == nPrintPage
);
854 aPos
= Point(Print::nLeftMargin
, Print::nTopMargin
+ nLineHeight
);
856 if( nCurPage
-1 == nPrintPage
)
857 pPrinter
->DrawText( aPos
, aTmpLine
);
859 aPos
.AdjustY(10 ); // nParaSpace
862 pPrinter
->SetFont( aOldFont
);
863 pPrinter
->SetMapMode( eOldMapMode
);
868 void ModulWindow::ExecuteCommand (SfxRequest
& rReq
)
870 AssertValidEditEngine();
871 switch (rReq
.GetSlot())
877 KeyEvent
aFakeDelete(0, KEY_DELETE
);
878 (void)GetEditView()->KeyInput(aFakeDelete
);
884 TextSelection
aSel( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL
, TEXT_INDEX_ALL
) );
885 TextView
* pView
= GetEditView();
886 pView
->SetSelection( aSel
);
887 pView
->GetWindow()->GrabFocus();
895 case SID_BASICCOMPILE
:
900 case SID_BASICSTEPOVER
:
905 case SID_BASICSTEPINTO
:
910 case SID_BASICSTEPOUT
:
920 case SID_BASICSAVEAS
:
925 case SID_IMPORT_DIALOG
:
930 case SID_BASICIDE_MATCHGROUP
:
932 GetEditView()->MatchGroup();
935 case SID_BASICIDE_TOGGLEBRKPNT
:
937 BasicToggleBreakPoint();
940 case SID_BASICIDE_MANAGEBRKPNTS
:
945 case SID_BASICIDE_TOGGLEBRKPNTENABLED
:
947 BasicToggleBreakPointEnabled();
950 case SID_BASICIDE_ADDWATCH
:
955 case SID_BASICIDE_REMOVEWATCH
:
957 m_rLayout
.BasicRemoveWatch();
964 GetEditView()->Cut();
965 if (SfxBindings
* pBindings
= GetBindingsPtr())
966 pBindings
->Invalidate( SID_DOC_MODIFIED
);
972 GetEditView()->Copy();
979 GetEditView()->Paste();
980 if (SfxBindings
* pBindings
= GetBindingsPtr())
981 pBindings
->Invalidate( SID_DOC_MODIFIED
);
985 case SID_BASICIDE_BRKPNTSCHANGED
:
987 GetBreakPointWindow().Invalidate();
992 const SfxBoolItem
* pItem
= rReq
.GetArg
<SfxBoolItem
>(rReq
.GetSlot());
993 bool bLineNumbers
= pItem
&& pItem
->GetValue();
994 m_aXEditorWindow
->SetLineNumberDisplay(bLineNumbers
);
996 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
997 officecfg::Office::BasicIDE::EditorSettings::LineNumbering::set(bLineNumbers
, batch
);
1001 case SID_BASICIDE_DELETECURRENT
:
1003 if (QueryDelModule(m_aName
, GetFrameWeld()))
1004 if (m_aDocument
.removeModule(m_aLibName
, m_aName
))
1005 MarkDocumentModified(m_aDocument
);
1008 case FID_SEARCH_OFF
:
1013 GotoLineDialog
aGotoDlg(GetFrameWeld());
1014 if (aGotoDlg
.run() == RET_OK
)
1016 if (sal_Int32
const nLine
= aGotoDlg
.GetLineNumber())
1018 TextSelection
const aSel(TextPaM(nLine
- 1, 0), TextPaM(nLine
- 1, 0));
1019 GetEditView()->SetSelection(aSel
);
1027 void ModulWindow::ExecuteGlobal (SfxRequest
& rReq
)
1029 switch (rReq
.GetSlot())
1033 DocumentSignature
aSignature(m_aDocument
);
1034 if (aSignature
.supportsSignatures())
1036 aSignature
.signScriptingContent(rReq
.GetFrameWeld());
1037 if (SfxBindings
* pBindings
= GetBindingsPtr())
1038 pBindings
->Invalidate(SID_SIGNATURE
);
1046 void ModulWindow::GetState( SfxItemSet
&rSet
)
1048 SfxWhichIter
aIter(rSet
);
1049 for ( sal_uInt16 nWh
= aIter
.FirstWhich(); nWh
!= 0; nWh
= aIter
.NextWhich() )
1055 if ( !GetEditView() || !GetEditView()->HasSelection() )
1056 rSet
.DisableItem( nWh
);
1059 rSet
.DisableItem( nWh
);
1064 if ( !GetEditView() || !GetEditView()->HasSelection() )
1065 rSet
.DisableItem( nWh
);
1070 if ( !IsPasteAllowed() )
1071 rSet
.DisableItem( nWh
);
1074 rSet
.DisableItem( nWh
);
1077 case SID_BASICIDE_STAT_POS
:
1079 TextView
* pView
= GetEditView();
1082 TextSelection aSel
= pView
->GetSelection();
1083 OUString aPos
= IDEResId( RID_STR_LINE
) +
1085 OUString::number(aSel
.GetEnd().GetPara()+1) +
1087 IDEResId( RID_STR_COLUMN
) +
1089 OUString::number(aSel
.GetEnd().GetIndex()+1);
1090 SfxStringItem
aItem( SID_BASICIDE_STAT_POS
, aPos
);
1095 case SID_BASICIDE_STAT_TITLE
:
1097 // search for current procedure name (Sub or Function)
1098 TextView
* pView
= GetEditView();
1103 TextSelection aSel
= pView
->GetSelection();
1105 sal_uInt32 i
= aSel
.GetStart().GetPara();
1108 OUString aCurrLine
= GetEditEngine()->GetText( i
);
1110 if (GetEditorWindow().GetProcedureName(aCurrLine
, sProcType
, sProcName
))
1114 OUString aTitle
= CreateQualifiedName();
1115 if (!sProcName
.isEmpty())
1116 aTitle
+= "." + sProcName
;
1118 SfxStringItem
aTitleItem( SID_BASICIDE_STAT_TITLE
, aTitle
);
1119 rSet
.Put( aTitleItem
);
1123 case SID_ATTR_INSERT
:
1125 TextView
* pView
= GetEditView();
1128 SfxBoolItem
aItem( SID_ATTR_INSERT
, pView
->IsInsertMode() );
1135 bool bLineNumbers
= ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1136 rSet
.Put(SfxBoolItem(nWh
, bLineNumbers
));
1141 if ( !GetEditView() )
1142 rSet
.DisableItem( nWh
);
1149 void ModulWindow::DoScroll( ScrollBar
* pCurScrollBar
)
1151 if ( ( pCurScrollBar
== GetHScrollBar() ) && GetEditView() )
1153 // don't scroll with the value but rather use the Thumb-Pos for the VisArea:
1154 long nDiff
= GetEditView()->GetStartDocPos().X() - pCurScrollBar
->GetThumbPos();
1155 GetEditView()->Scroll( nDiff
, 0 );
1156 GetEditView()->ShowCursor( false );
1157 pCurScrollBar
->SetThumbPos( GetEditView()->GetStartDocPos().X() );
1162 bool ModulWindow::IsModified()
1164 return GetEditEngine() && GetEditEngine()->IsModified();
1167 OUString
ModulWindow::GetSbModuleName()
1169 OUString aModuleName
;
1170 if ( XModule().is() )
1171 aModuleName
= m_xModule
->GetName();
1175 OUString
ModulWindow::GetTitle()
1177 return GetSbModuleName();
1180 void ModulWindow::ShowCursor( bool bOn
)
1182 if ( GetEditEngine() )
1184 TextView
* pView
= GetEditEngine()->GetActiveView();
1188 pView
->ShowCursor();
1190 pView
->HideCursor();
1195 void ModulWindow::AssertValidEditEngine()
1197 if ( !GetEditEngine() )
1198 GetEditorWindow().CreateEditEngine();
1201 void ModulWindow::Activating ()
1203 bool bLineNumbers
= ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1204 m_aXEditorWindow
->SetLineNumberDisplay(bLineNumbers
);
1208 void ModulWindow::Deactivating()
1213 sal_uInt16
ModulWindow::StartSearchAndReplace( const SvxSearchItem
& rSearchItem
, bool bFromStart
)
1218 // one could also relinquish syntaxhighlighting/formatting instead of the stupid replace-everything...
1219 AssertValidEditEngine();
1220 TextView
* pView
= GetEditView();
1224 aSel
= pView
->GetSelection();
1225 if ( !rSearchItem
.GetBackward() )
1226 pView
->SetSelection( TextSelection() );
1228 pView
->SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL
, TEXT_INDEX_ALL
), TextPaM( TEXT_PARA_ALL
, TEXT_INDEX_ALL
) ) );
1231 bool const bForward
= !rSearchItem
.GetBackward();
1232 sal_uInt16 nFound
= 0;
1233 if ( ( rSearchItem
.GetCommand() == SvxSearchCmd::FIND
) ||
1234 ( rSearchItem
.GetCommand() == SvxSearchCmd::FIND_ALL
) )
1236 nFound
= pView
->Search( rSearchItem
.GetSearchOptions() , bForward
) ? 1 : 0;
1238 else if ( ( rSearchItem
.GetCommand() == SvxSearchCmd::REPLACE
) ||
1239 ( rSearchItem
.GetCommand() == SvxSearchCmd::REPLACE_ALL
) )
1241 if ( !IsReadOnly() )
1243 bool const bAll
= rSearchItem
.GetCommand() == SvxSearchCmd::REPLACE_ALL
;
1244 nFound
= pView
->Replace( rSearchItem
.GetSearchOptions() , bAll
, bForward
);
1248 if ( bFromStart
&& !nFound
)
1249 pView
->SetSelection( aSel
);
1254 svl::IUndoManager
* ModulWindow::GetUndoManager()
1256 if ( GetEditEngine() )
1257 return &GetEditEngine()->GetUndoManager();
1261 SearchOptionFlags
ModulWindow::GetSearchOptions()
1263 SearchOptionFlags nOptions
= SearchOptionFlags::SEARCH
|
1264 SearchOptionFlags::WHOLE_WORDS
|
1265 SearchOptionFlags::BACKWARDS
|
1266 SearchOptionFlags::REG_EXP
|
1267 SearchOptionFlags::EXACT
|
1268 SearchOptionFlags::SELECTION
|
1269 SearchOptionFlags::SIMILARITY
;
1271 if ( !IsReadOnly() )
1273 nOptions
|= SearchOptionFlags::REPLACE
;
1274 nOptions
|= SearchOptionFlags::REPLACE_ALL
;
1280 void ModulWindow::BasicStarted()
1282 if ( XModule().is() )
1284 m_aStatus
.bIsRunning
= true;
1285 BreakPointList
& rList
= GetBreakPoints();
1288 rList
.ResetHitCount();
1289 rList
.SetBreakPointsInBasic( m_xModule
.get() );
1290 for ( sal_uInt16 nMethod
= 0; nMethod
< m_xModule
->GetMethods()->Count(); nMethod
++ )
1292 SbMethod
* pMethod
= static_cast<SbMethod
*>(m_xModule
->GetMethods()->Get( nMethod
));
1293 assert(pMethod
&& "Method not found! (NULL)");
1294 pMethod
->SetDebugFlags( pMethod
->GetDebugFlags() | BasicDebugFlags::Break
);
1300 void ModulWindow::BasicStopped()
1302 m_aStatus
.bIsRunning
= false;
1303 GetBreakPointWindow().SetNoMarker();
1306 EntryDescriptor
ModulWindow::CreateEntryDescriptor()
1308 ScriptDocument
aDocument( GetDocument() );
1309 OUString
aLibName( GetLibName() );
1310 LibraryLocation eLocation
= aDocument
.getLibraryLocation( aLibName
);
1311 OUString
aModName( GetName() );
1312 OUString aLibSubName
;
1313 if( m_xBasic
.is() && aDocument
.isInVBAMode() && XModule().is() )
1315 switch( m_xModule
->GetModuleType() )
1317 case script::ModuleType::DOCUMENT
:
1319 aLibSubName
= IDEResId( RID_STR_DOCUMENT_OBJECTS
);
1320 uno::Reference
< container::XNameContainer
> xLib
= aDocument
.getOrCreateLibrary( E_SCRIPTS
, aLibName
);
1324 ModuleInfoHelper::getObjectName( xLib
, aModName
, sObjName
);
1325 if( !sObjName
.isEmpty() )
1327 aModName
+= " (" + sObjName
+ ")";
1332 case script::ModuleType::FORM
:
1333 aLibSubName
= IDEResId( RID_STR_USERFORMS
);
1335 case script::ModuleType::NORMAL
:
1336 aLibSubName
= IDEResId( RID_STR_NORMAL_MODULES
);
1338 case script::ModuleType::CLASS
:
1339 aLibSubName
= IDEResId( RID_STR_CLASS_MODULES
);
1343 return EntryDescriptor( aDocument
, eLocation
, aLibName
, aLibSubName
, aModName
, OBJ_TYPE_MODULE
);
1346 void ModulWindow::SetReadOnly (bool b
)
1348 if ( GetEditView() )
1349 GetEditView()->SetReadOnly( b
);
1352 bool ModulWindow::IsReadOnly()
1354 return GetEditView() && GetEditView()->IsReadOnly();
1357 bool ModulWindow::IsPasteAllowed()
1359 bool bPaste
= false;
1362 Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= GetClipboard();
1363 if ( xClipboard
.is() )
1366 Reference
< datatransfer::XTransferable
> xTransf
;
1368 SolarMutexReleaser aReleaser
;
1369 // get clipboard content
1370 xTransf
= xClipboard
->getContents();
1374 datatransfer::DataFlavor aFlavor
;
1375 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING
, aFlavor
);
1376 if ( xTransf
->isDataFlavorSupported( aFlavor
) )
1384 void ModulWindow::OnNewDocument ()
1386 bool bLineNumbers
= ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
1387 m_aXEditorWindow
->SetLineNumberDisplay(bLineNumbers
);
1390 char const* ModulWindow::GetHid () const
1392 return HID_BASICIDE_MODULWINDOW
;
1394 ItemType
ModulWindow::GetType () const
1399 bool ModulWindow::HasActiveEditor () const
1401 return !IsSuspended();
1405 void ModulWindow::UpdateModule ()
1407 OUString
const aModule
= getTextEngineText(*GetEditEngine());
1409 // update module in basic
1410 assert(m_xModule
.is());
1412 // update module in module window
1415 // update module in library
1416 OSL_VERIFY(m_aDocument
.updateModule(m_aLibName
, m_aName
, aModule
));
1418 GetEditEngine()->SetModified(false);
1419 MarkDocumentModified(m_aDocument
);
1422 ModulWindowLayout::ModulWindowLayout (vcl::Window
* pParent
, ObjectCatalog
& rObjectCatalog_
) :
1425 aWatchWindow(VclPtr
<WatchWindow
>::Create(this)),
1426 aStackWindow(VclPtr
<StackWindow
>::Create(this)),
1427 rObjectCatalog(rObjectCatalog_
)
1430 ModulWindowLayout::~ModulWindowLayout()
1435 void ModulWindowLayout::dispose()
1437 aWatchWindow
.disposeAndClear();
1438 aStackWindow
.disposeAndClear();
1443 void ModulWindowLayout::UpdateDebug (bool bBasicStopped
)
1445 aWatchWindow
->UpdateWatches(bBasicStopped
);
1446 aStackWindow
->UpdateCalls();
1449 void ModulWindowLayout::Paint (vcl::RenderContext
& rRenderContext
, tools::Rectangle
const&)
1451 rRenderContext
.DrawText(Point(), IDEResId(RID_STR_NOMODULE
));
1454 void ModulWindowLayout::Activating (BaseWindow
& rChild
)
1456 assert(dynamic_cast<ModulWindow
*>(&rChild
));
1457 pChild
= &static_cast<ModulWindow
&>(rChild
);
1458 aWatchWindow
->Show();
1459 aStackWindow
->Show();
1460 rObjectCatalog
.Show();
1461 rObjectCatalog
.SetLayoutWindow(this);
1462 rObjectCatalog
.UpdateEntries();
1463 Layout::Activating(rChild
);
1464 aSyntaxColors
.SetActiveEditor(&pChild
->GetEditorWindow());
1467 void ModulWindowLayout::Deactivating ()
1469 aSyntaxColors
.SetActiveEditor(nullptr);
1470 Layout::Deactivating();
1471 aWatchWindow
->Hide();
1472 aStackWindow
->Hide();
1473 rObjectCatalog
.Hide();
1477 void ModulWindowLayout::GetState (SfxItemSet
&rSet
, unsigned nWhich
)
1481 case SID_SHOW_PROPERTYBROWSER
:
1482 rSet
.Put(SfxVisibilityItem(nWhich
, false));
1485 case SID_BASICIDE_CHOOSEMACRO
:
1486 rSet
.Put(SfxVisibilityItem(nWhich
, true));
1491 void ModulWindowLayout::BasicAddWatch (OUString
const& rWatchStr
)
1493 aWatchWindow
->AddWatch(rWatchStr
);
1496 void ModulWindowLayout::BasicRemoveWatch ()
1498 aWatchWindow
->RemoveSelectedWatch();
1501 void ModulWindowLayout::OnFirstSize (long const nWidth
, long const nHeight
)
1503 AddToLeft(&rObjectCatalog
, Size(nWidth
* 0.20, nHeight
* 0.75));
1504 AddToBottom(aWatchWindow
.get(), Size(nWidth
* 0.67, nHeight
* 0.25));
1505 AddToBottom(aStackWindow
.get(), Size(nWidth
* 0.33, nHeight
* 0.25));
1508 ModulWindowLayout::SyntaxColors::SyntaxColors () :
1511 aConfig
.AddListener(this);
1516 ModulWindowLayout::SyntaxColors::~SyntaxColors ()
1518 aConfig
.RemoveListener(this);
1522 void ModulWindowLayout::SyntaxColors::ConfigurationChanged (utl::ConfigurationBroadcaster
*, ConfigurationHints
)
1527 // when a new configuration has to be set
1528 void ModulWindowLayout::SyntaxColors::NewConfig (bool bFirst
)
1532 TokenType eTokenType
;
1533 svtools::ColorConfigEntry eEntry
;
1537 { TokenType::Unknown
, svtools::FONTCOLOR
},
1538 { TokenType::Identifier
, svtools::BASICIDENTIFIER
},
1539 { TokenType::Whitespace
, svtools::FONTCOLOR
},
1540 { TokenType::Number
, svtools::BASICNUMBER
},
1541 { TokenType::String
, svtools::BASICSTRING
},
1542 { TokenType::EOL
, svtools::FONTCOLOR
},
1543 { TokenType::Comment
, svtools::BASICCOMMENT
},
1544 { TokenType::Error
, svtools::BASICERROR
},
1545 { TokenType::Operator
, svtools::BASICOPERATOR
},
1546 { TokenType::Keywords
, svtools::BASICKEYWORD
},
1549 Color aDocColor
= aConfig
.GetColorValue(svtools::DOCCOLOR
).nColor
;
1550 if (bFirst
|| aDocColor
!= m_aBackgroundColor
)
1552 m_aBackgroundColor
= aDocColor
;
1553 if (!bFirst
&& pEditor
)
1555 pEditor
->SetBackground(Wallpaper(m_aBackgroundColor
));
1556 pEditor
->Invalidate();
1560 Color aFontColor
= aConfig
.GetColorValue(svtools::FONTCOLOR
).nColor
;
1561 if (bFirst
|| aFontColor
!= m_aFontColor
)
1563 m_aFontColor
= aFontColor
;
1564 if (!bFirst
&& pEditor
)
1565 pEditor
->ChangeFontColor(m_aFontColor
);
1568 bool bChanged
= false;
1569 for (unsigned i
= 0; i
!= SAL_N_ELEMENTS(vIds
); ++i
)
1571 Color
const aColor
= aConfig
.GetColorValue(vIds
[i
].eEntry
).nColor
;
1572 Color
& rMyColor
= aColors
[vIds
[i
].eTokenType
];
1573 if (bFirst
|| aColor
!= rMyColor
)
1579 if (bChanged
&& !bFirst
&& pEditor
)
1580 pEditor
->UpdateSyntaxHighlighting();
1583 } // namespace basctl
1585 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */