Line data Source code
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 :
21 :
22 : #include "helpid.hrc"
23 : #include "baside2.hrc"
24 :
25 : #include "baside2.hxx"
26 : #include "brkdlg.hxx"
27 : #include "iderdll.hxx"
28 :
29 : #include <basic/sbmeth.hxx>
30 : #include <basic/sbuno.hxx>
31 : #include <com/sun/star/beans/XMultiPropertySet.hpp>
32 : #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
33 : #include <com/sun/star/script/XLibraryContainer2.hpp>
34 : #include <comphelper/string.hxx>
35 : #include <officecfg/Office/Common.hxx>
36 : #include <sfx2/dispatch.hxx>
37 : #include <vcl/msgbox.hxx>
38 : #include <svl/urihelper.hxx>
39 : #include <vcl/xtextedt.hxx>
40 : #include <vcl/txtattr.hxx>
41 : #include <vcl/settings.hxx>
42 : #include <svtools/textwindowpeer.hxx>
43 : #include <svtools/treelistentry.hxx>
44 : #include <vcl/taskpanelist.hxx>
45 : #include <vcl/help.hxx>
46 :
47 : #include <vector>
48 : #include <com/sun/star/reflection/theCoreReflection.hpp>
49 :
50 : namespace basctl
51 : {
52 :
53 : using namespace ::com::sun::star;
54 : using namespace ::com::sun::star::uno;
55 :
56 : namespace
57 : {
58 :
59 : sal_uInt16 const NoMarker = 0xFFFF;
60 : long const nBasePad = 2;
61 : long const nCursorPad = 5;
62 :
63 : long nVirtToolBoxHeight; // inited in WatchWindow, used in Stackwindow
64 : long nHeaderBarHeight;
65 :
66 : // Returns pBase converted to SbxVariable if valid and is not an SbxMethod.
67 0 : SbxVariable* IsSbxVariable (SbxBase* pBase)
68 : {
69 0 : if (SbxVariable* pVar = dynamic_cast<SbxVariable*>(pBase))
70 0 : if (!dynamic_cast<SbxMethod*>(pVar))
71 0 : return pVar;
72 0 : return 0;
73 : }
74 :
75 0 : Image GetImage (unsigned nId)
76 : {
77 0 : static ImageList const aImagesNormal(IDEResId(RID_IMGLST_LAYOUT));
78 0 : return aImagesNormal.GetImage(nId);
79 : }
80 :
81 : int const nScrollLine = 12;
82 : int const nScrollPage = 60;
83 : int const DWBORDER = 3;
84 :
85 : char const cSuffixes[] = "%&!#@$";
86 :
87 : } // namespace
88 :
89 :
90 : /**
91 : * Helper functions to get/set text in TextEngine using
92 : * the stream interface.
93 : *
94 : * get/setText() only supports tools Strings limited to 64K).
95 : */
96 0 : OUString getTextEngineText (ExtTextEngine& rEngine)
97 : {
98 0 : SvMemoryStream aMemStream;
99 0 : aMemStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
100 0 : aMemStream.SetLineDelimiter( LINEEND_LF );
101 0 : rEngine.Write( aMemStream );
102 0 : sal_Size nSize = aMemStream.Tell();
103 0 : OUString aText( static_cast<const sal_Char*>(aMemStream.GetData()),
104 0 : nSize, RTL_TEXTENCODING_UTF8 );
105 0 : return aText;
106 : }
107 :
108 0 : void setTextEngineText (ExtTextEngine& rEngine, OUString const& aStr)
109 : {
110 0 : rEngine.SetText(OUString());
111 0 : OString aUTF8Str = OUStringToOString( aStr, RTL_TEXTENCODING_UTF8 );
112 0 : SvMemoryStream aMemStream( const_cast<char *>(aUTF8Str.getStr()), aUTF8Str.getLength(),
113 0 : StreamMode::READ );
114 0 : aMemStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
115 0 : aMemStream.SetLineDelimiter( LINEEND_LF );
116 0 : rEngine.Read(aMemStream);
117 0 : }
118 :
119 : namespace
120 : {
121 :
122 0 : void lcl_DrawIDEWindowFrame(DockingWindow* pWin, vcl::RenderContext& rRenderContext)
123 : {
124 0 : if (pWin->IsFloatingMode())
125 0 : return;
126 :
127 0 : Size aSz = rRenderContext.GetOutputSizePixel();
128 0 : const Color aOldLineColor(rRenderContext.GetLineColor());
129 0 : rRenderContext.SetLineColor(Color(COL_WHITE));
130 : // White line on top
131 0 : rRenderContext.DrawLine(Point(0, 0), Point(aSz.Width(), 0));
132 : // Black line at bottom
133 0 : rRenderContext.SetLineColor(Color(COL_BLACK));
134 0 : rRenderContext.DrawLine(Point(0, aSz.Height() - 1),
135 0 : Point(aSz.Width(), aSz.Height() - 1));
136 0 : rRenderContext.SetLineColor(aOldLineColor);
137 : }
138 :
139 0 : void lcl_SeparateNameAndIndex( const OUString& rVName, OUString& rVar, OUString& rIndex )
140 : {
141 0 : rVar = rVName;
142 0 : rIndex.clear();
143 0 : sal_Int32 nIndexStart = rVar.indexOf( '(' );
144 0 : if ( nIndexStart != -1 )
145 : {
146 0 : sal_Int32 nIndexEnd = rVar.indexOf( ')', nIndexStart );
147 0 : if ( nIndexStart != -1 )
148 : {
149 0 : rIndex = rVar.copy( nIndexStart+1, nIndexEnd-nIndexStart-1 );
150 0 : rVar = rVar.copy( 0, nIndexStart );
151 0 : rVar = comphelper::string::stripEnd(rVar, ' ');
152 0 : rIndex = comphelper::string::strip(rIndex, ' ');
153 : }
154 : }
155 :
156 0 : if ( !rVar.isEmpty() )
157 : {
158 0 : sal_uInt16 nLastChar = rVar.getLength()-1;
159 0 : if ( strchr( cSuffixes, rVar[ nLastChar ] ) )
160 0 : rVar = rVar.replaceAt( nLastChar, 1, "" );
161 : }
162 0 : if ( !rIndex.isEmpty() )
163 : {
164 0 : sal_uInt16 nLastChar = rIndex.getLength()-1;
165 0 : if ( strchr( cSuffixes, rIndex[ nLastChar ] ) )
166 0 : rIndex = rIndex.replaceAt( nLastChar, 1, "" );
167 : }
168 0 : }
169 :
170 : } // namespace
171 :
172 :
173 :
174 : // EditorWindow
175 :
176 :
177 :
178 : class EditorWindow::ChangesListener:
179 : public cppu::WeakImplHelper1< beans::XPropertiesChangeListener >
180 : {
181 : public:
182 0 : explicit ChangesListener(EditorWindow & editor): editor_(editor) {}
183 :
184 : private:
185 0 : virtual ~ChangesListener() {}
186 :
187 0 : virtual void SAL_CALL disposing(lang::EventObject const &) throw (RuntimeException, std::exception) SAL_OVERRIDE
188 : {
189 0 : osl::MutexGuard g(editor_.mutex_);
190 0 : editor_.notifier_.clear();
191 0 : }
192 :
193 0 : virtual void SAL_CALL propertiesChange(
194 : Sequence< beans::PropertyChangeEvent > const &) throw (RuntimeException, std::exception) SAL_OVERRIDE
195 : {
196 0 : SolarMutexGuard g;
197 0 : editor_.ImplSetFont();
198 0 : }
199 :
200 : EditorWindow & editor_;
201 : };
202 :
203 0 : class EditorWindow::ProgressInfo : public SfxProgress
204 : {
205 : public:
206 0 : ProgressInfo (SfxObjectShell* pObjSh, OUString const& rText, sal_uLong nRange) :
207 : SfxProgress(pObjSh, rText, nRange),
208 0 : nCurState(0)
209 0 : { }
210 :
211 0 : void StepProgress ()
212 : {
213 0 : SetState(++nCurState);
214 0 : }
215 :
216 : private:
217 : sal_uLong nCurState;
218 : };
219 :
220 0 : EditorWindow::EditorWindow (vcl::Window* pParent, ModulWindow* pModulWindow) :
221 : Window(pParent, WB_BORDER),
222 : pEditView(0),
223 : pEditEngine(0),
224 : rModulWindow(*pModulWindow),
225 : nCurTextWidth(0),
226 : aHighlighter(HIGHLIGHT_BASIC),
227 : bHighlightning(false),
228 : bDoSyntaxHighlight(true),
229 : bDelayHighlight(true),
230 0 : pCodeCompleteWnd(VclPtr<CodeCompleteWindow>::Create(this))
231 : {
232 0 : SetBackground(Wallpaper(GetSettings().GetStyleSettings().GetFieldColor()));
233 0 : SetPointer( Pointer( PointerStyle::Text ) );
234 0 : SetHelpId( HID_BASICIDE_EDITORWINDOW );
235 :
236 0 : listener_ = new ChangesListener(*this);
237 : Reference< beans::XMultiPropertySet > n(
238 : officecfg::Office::Common::Font::SourceViewFont::get(),
239 0 : UNO_QUERY_THROW);
240 : {
241 0 : osl::MutexGuard g(mutex_);
242 0 : notifier_ = n;
243 : }
244 0 : Sequence< OUString > s(2);
245 0 : s[0] = "FontHeight";
246 0 : s[1] = "FontName";
247 0 : n->addPropertiesChangeListener(s, listener_.get());
248 0 : }
249 :
250 :
251 0 : EditorWindow::~EditorWindow()
252 : {
253 0 : disposeOnce();
254 0 : }
255 :
256 0 : void EditorWindow::dispose()
257 : {
258 0 : Reference< beans::XMultiPropertySet > n;
259 : {
260 0 : osl::MutexGuard g(mutex_);
261 0 : n = notifier_;
262 : }
263 0 : if (n.is()) {
264 0 : n->removePropertiesChangeListener(listener_.get());
265 : }
266 :
267 0 : aSyntaxIdle.Stop();
268 :
269 0 : if ( pEditEngine )
270 : {
271 0 : EndListening( *pEditEngine );
272 0 : pEditEngine->RemoveView(pEditView.get());
273 : }
274 0 : pCodeCompleteWnd.disposeAndClear();
275 0 : vcl::Window::dispose();
276 0 : }
277 :
278 0 : OUString EditorWindow::GetWordAtCursor()
279 : {
280 0 : OUString aWord;
281 :
282 0 : if ( pEditView )
283 : {
284 0 : TextEngine* pTextEngine = pEditView->GetTextEngine();
285 0 : if ( pTextEngine )
286 : {
287 : // check first, if the cursor is at a help URL
288 0 : const TextSelection& rSelection = pEditView->GetSelection();
289 0 : const TextPaM& rSelStart = rSelection.GetStart();
290 0 : const TextPaM& rSelEnd = rSelection.GetEnd();
291 0 : OUString aText = pTextEngine->GetText( rSelEnd.GetPara() );
292 0 : CharClass aClass( ::comphelper::getProcessComponentContext() , Application::GetSettings().GetLanguageTag() );
293 0 : sal_Int32 nSelStart = rSelStart.GetIndex();
294 0 : sal_Int32 nSelEnd = rSelEnd.GetIndex();
295 0 : sal_Int32 nLength = aText.getLength();
296 0 : sal_Int32 nStart = 0;
297 0 : sal_Int32 nEnd = nLength;
298 0 : while ( nStart < nLength )
299 : {
300 0 : OUString aURL( URIHelper::FindFirstURLInText( aText, nStart, nEnd, aClass ) );
301 0 : INetURLObject aURLObj( aURL );
302 0 : if ( aURLObj.GetProtocol() == INetProtocol::VndSunStarHelp
303 0 : && nSelStart >= nStart && nSelStart <= nEnd && nSelEnd >= nStart && nSelEnd <= nEnd )
304 : {
305 0 : aWord = aURL;
306 0 : break;
307 : }
308 0 : nStart = nEnd;
309 0 : nEnd = nLength;
310 0 : }
311 :
312 : // Not the selected range, but at the CursorPosition,
313 : // if a word is partially selected.
314 0 : if ( aWord.isEmpty() )
315 0 : aWord = pTextEngine->GetWord( rSelEnd );
316 :
317 : // Can be empty when full word selected, as Cursor behing it
318 0 : if ( aWord.isEmpty() && pEditView->HasSelection() )
319 0 : aWord = pTextEngine->GetWord( rSelStart );
320 : }
321 : }
322 :
323 0 : return aWord;
324 : }
325 :
326 0 : void EditorWindow::RequestHelp( const HelpEvent& rHEvt )
327 : {
328 0 : bool bDone = false;
329 :
330 : // Should have been activated at some point
331 0 : if ( pEditEngine )
332 : {
333 0 : if ( rHEvt.GetMode() & HelpEventMode::CONTEXT )
334 : {
335 0 : OUString aKeyword = GetWordAtCursor();
336 0 : Application::GetHelp()->SearchKeyword( aKeyword );
337 0 : bDone = true;
338 : }
339 0 : else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
340 : {
341 0 : OUString aHelpText;
342 0 : Point aTopLeft;
343 0 : if ( StarBASIC::IsRunning() )
344 : {
345 0 : Point aWindowPos = rHEvt.GetMousePosPixel();
346 0 : aWindowPos = ScreenToOutputPixel( aWindowPos );
347 0 : Point aDocPos = GetEditView()->GetDocPos( aWindowPos );
348 0 : TextPaM aCursor = GetEditView()->GetTextEngine()->GetPaM(aDocPos, false);
349 0 : TextPaM aStartOfWord;
350 0 : OUString aWord = GetEditView()->GetTextEngine()->GetWord( aCursor, &aStartOfWord );
351 0 : if ( !aWord.isEmpty() && !comphelper::string::isdigitAsciiString(aWord) )
352 : {
353 0 : sal_uInt16 nLastChar = aWord.getLength() - 1;
354 0 : if ( strchr( cSuffixes, aWord[ nLastChar ] ) )
355 0 : aWord = aWord.replaceAt( nLastChar, 1, "" );
356 0 : SbxBase* pSBX = StarBASIC::FindSBXInCurrentScope( aWord );
357 0 : if (SbxVariable const* pVar = IsSbxVariable(pSBX))
358 : {
359 0 : SbxDataType eType = pVar->GetType();
360 0 : if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
361 : // might cause a crash e. g. at the selections-object
362 : // Type == Object does not mean pVar == Object!
363 : ; // aHelpText = ((SbxObject*)pVar)->GetClassName();
364 0 : else if ( eType & SbxARRAY )
365 : ; // aHelpText = "{...}";
366 0 : else if ( (sal_uInt8)eType != (sal_uInt8)SbxEMPTY )
367 : {
368 0 : aHelpText = pVar->GetName();
369 0 : if ( aHelpText.isEmpty() ) // name is not copied with the passed parameters
370 0 : aHelpText = aWord;
371 0 : aHelpText += "=";
372 0 : aHelpText += pVar->GetOUString();
373 : }
374 : }
375 0 : if ( !aHelpText.isEmpty() )
376 : {
377 0 : aTopLeft = GetEditView()->GetTextEngine()->PaMtoEditCursor( aStartOfWord ).BottomLeft();
378 0 : aTopLeft = GetEditView()->GetWindowPos( aTopLeft );
379 0 : aTopLeft.X() += 5;
380 0 : aTopLeft.Y() += 5;
381 0 : aTopLeft = OutputToScreenPixel( aTopLeft );
382 : }
383 0 : }
384 : }
385 0 : Help::ShowQuickHelp( this, Rectangle( aTopLeft, Size( 1, 1 ) ), aHelpText, QuickHelpFlags::Top|QuickHelpFlags::Left);
386 0 : bDone = true;
387 : }
388 : }
389 :
390 0 : if ( !bDone )
391 0 : Window::RequestHelp( rHEvt );
392 0 : }
393 :
394 :
395 0 : void EditorWindow::Resize()
396 : {
397 : // ScrollBars, etc. happens in Adjust...
398 0 : if ( pEditView )
399 : {
400 0 : long nVisY = pEditView->GetStartDocPos().Y();
401 :
402 0 : pEditView->ShowCursor();
403 0 : Size aOutSz( GetOutputSizePixel() );
404 0 : long nMaxVisAreaStart = pEditView->GetTextEngine()->GetTextHeight() - aOutSz.Height();
405 0 : if ( nMaxVisAreaStart < 0 )
406 0 : nMaxVisAreaStart = 0;
407 0 : if ( pEditView->GetStartDocPos().Y() > nMaxVisAreaStart )
408 : {
409 0 : Point aStartDocPos( pEditView->GetStartDocPos() );
410 0 : aStartDocPos.Y() = nMaxVisAreaStart;
411 0 : pEditView->SetStartDocPos( aStartDocPos );
412 0 : pEditView->ShowCursor();
413 0 : rModulWindow.GetBreakPointWindow().GetCurYOffset() = aStartDocPos.Y();
414 0 : rModulWindow.GetLineNumberWindow().GetCurYOffset() = aStartDocPos.Y();
415 : }
416 0 : InitScrollBars();
417 0 : if ( nVisY != pEditView->GetStartDocPos().Y() )
418 0 : Invalidate();
419 : }
420 0 : }
421 :
422 :
423 0 : void EditorWindow::MouseMove( const MouseEvent &rEvt )
424 : {
425 0 : if ( pEditView )
426 0 : pEditView->MouseMove( rEvt );
427 0 : }
428 :
429 :
430 0 : void EditorWindow::MouseButtonUp( const MouseEvent &rEvt )
431 : {
432 0 : if ( pEditView )
433 : {
434 0 : pEditView->MouseButtonUp( rEvt );
435 0 : if (SfxBindings* pBindings = GetBindingsPtr())
436 : {
437 0 : pBindings->Invalidate( SID_BASICIDE_STAT_POS );
438 0 : pBindings->Invalidate( SID_BASICIDE_STAT_TITLE );
439 : }
440 : }
441 0 : }
442 :
443 0 : void EditorWindow::MouseButtonDown( const MouseEvent &rEvt )
444 : {
445 0 : GrabFocus();
446 0 : if ( pEditView )
447 0 : pEditView->MouseButtonDown( rEvt );
448 0 : if( pCodeCompleteWnd->IsVisible() )
449 : {
450 0 : if( pEditView->GetSelection() != pCodeCompleteWnd->GetTextSelection() )
451 : {//selection changed, code complete window should be hidden
452 0 : pCodeCompleteWnd->GetListBox()->HideAndRestoreFocus();
453 : }
454 : }
455 0 : }
456 :
457 0 : void EditorWindow::Command( const CommandEvent& rCEvt )
458 : {
459 0 : if ( pEditView )
460 : {
461 0 : pEditView->Command( rCEvt );
462 0 : if ( ( rCEvt.GetCommand() == CommandEventId::Wheel ) ||
463 0 : ( rCEvt.GetCommand() == CommandEventId::StartAutoScroll ) ||
464 0 : ( rCEvt.GetCommand() == CommandEventId::AutoScroll ) )
465 : {
466 0 : HandleScrollCommand( rCEvt, rModulWindow.GetHScrollBar(), &rModulWindow.GetEditVScrollBar() );
467 0 : } else if ( rCEvt.GetCommand() == CommandEventId::ContextMenu ) {
468 0 : SfxDispatcher* pDispatcher = GetDispatcher();
469 0 : if ( pDispatcher )
470 : {
471 0 : SfxDispatcher::ExecutePopup();
472 : }
473 0 : if( pCodeCompleteWnd->IsVisible() ) // hide the code complete window
474 0 : pCodeCompleteWnd->ClearAndHide();
475 : }
476 : }
477 0 : }
478 :
479 0 : bool EditorWindow::ImpCanModify()
480 : {
481 0 : bool bCanModify = true;
482 0 : if ( StarBASIC::IsRunning() && rModulWindow.GetBasicStatus().bIsRunning )
483 : {
484 : // If in Trace-mode, abort the trace or refuse input
485 : // Remove markers in the modules in Notify at Basic::Stoped
486 0 : if ( ScopedVclPtr<QueryBox>::Create( nullptr, WB_OK_CANCEL, IDEResId(RID_STR_WILLSTOPPRG).toString() )->Execute() == RET_OK )
487 : {
488 0 : rModulWindow.GetBasicStatus().bIsRunning = false;
489 0 : StopBasic();
490 : }
491 : else
492 0 : bCanModify = false;
493 : }
494 0 : return bCanModify;
495 : }
496 :
497 0 : void EditorWindow::KeyInput( const KeyEvent& rKEvt )
498 : {
499 0 : if ( !pEditView ) // Happens in Win95
500 0 : return;
501 :
502 : #if OSL_DEBUG_LEVEL > 1
503 : Range aRange = rModulWindow.GetHScrollBar()->GetRange(); (void)aRange;
504 : long nVisSz = rModulWindow.GetHScrollBar()->GetVisibleSize(); (void)nVisSz;
505 : long nPapSz = rModulWindow.GetHScrollBar()->GetPageSize(); (void)nPapSz;
506 : long nLinSz = rModulWindow.GetHScrollBar()->GetLineSize(); (void)nLinSz;
507 : long nThumb = rModulWindow.GetHScrollBar()->GetThumbPos(); (void)nThumb;
508 : #endif
509 0 : bool const bWasModified = pEditEngine->IsModified();
510 : // see if there is an accelerator to be processed first
511 0 : bool bDone = SfxViewShell::Current()->KeyInput( rKEvt );
512 :
513 0 : if( pCodeCompleteWnd->IsVisible() && CodeCompleteOptions::IsCodeCompleteOn() )
514 : {
515 0 : pCodeCompleteWnd->GetListBox()->KeyInput(rKEvt);
516 0 : if( rKEvt.GetKeyCode().GetCode() == KEY_UP
517 0 : || rKEvt.GetKeyCode().GetCode() == KEY_DOWN
518 0 : || rKEvt.GetKeyCode().GetCode() == KEY_TAB
519 0 : || rKEvt.GetKeyCode().GetCode() == KEY_POINT)
520 0 : return;
521 : }
522 :
523 0 : if( (rKEvt.GetKeyCode().GetCode() == KEY_SPACE ||
524 0 : rKEvt.GetKeyCode().GetCode() == KEY_TAB ||
525 0 : rKEvt.GetKeyCode().GetCode() == KEY_RETURN ) && CodeCompleteOptions::IsAutoCorrectOn() )
526 : {
527 0 : HandleAutoCorrect();
528 : }
529 :
530 0 : if( rKEvt.GetCharCode() == '"' && CodeCompleteOptions::IsAutoCloseQuotesOn() )
531 : {//autoclose double quotes
532 0 : HandleAutoCloseDoubleQuotes();
533 : }
534 :
535 0 : if( rKEvt.GetCharCode() == '(' && CodeCompleteOptions::IsAutoCloseParenthesisOn() )
536 : {//autoclose parenthesis
537 0 : HandleAutoCloseParen();
538 : }
539 :
540 0 : if( rKEvt.GetKeyCode().GetCode() == KEY_RETURN && CodeCompleteOptions::IsProcedureAutoCompleteOn() )
541 : {//autoclose implementation
542 0 : HandleProcedureCompletion();
543 : }
544 :
545 0 : if( rKEvt.GetKeyCode().GetCode() == KEY_POINT && CodeCompleteOptions::IsCodeCompleteOn() )
546 : {
547 0 : HandleCodeCompletion();
548 : }
549 0 : if ( !bDone && ( !TextEngine::DoesKeyChangeText( rKEvt ) || ImpCanModify() ) )
550 : {
551 0 : if ( ( rKEvt.GetKeyCode().GetCode() == KEY_TAB ) && !rKEvt.GetKeyCode().IsMod1() &&
552 0 : !rKEvt.GetKeyCode().IsMod2() && !GetEditView()->IsReadOnly() )
553 : {
554 0 : TextSelection aSel( pEditView->GetSelection() );
555 0 : if ( aSel.GetStart().GetPara() != aSel.GetEnd().GetPara() )
556 : {
557 0 : bDelayHighlight = false;
558 0 : if ( !rKEvt.GetKeyCode().IsShift() )
559 0 : pEditView->IndentBlock();
560 : else
561 0 : pEditView->UnindentBlock();
562 0 : bDelayHighlight = true;
563 0 : bDone = true;
564 : }
565 : }
566 0 : if ( !bDone )
567 0 : bDone = pEditView->KeyInput( rKEvt );
568 : }
569 0 : if ( !bDone )
570 : {
571 0 : Window::KeyInput( rKEvt );
572 : }
573 : else
574 : {
575 0 : if (SfxBindings* pBindings = GetBindingsPtr())
576 : {
577 0 : pBindings->Invalidate( SID_BASICIDE_STAT_POS );
578 0 : pBindings->Invalidate( SID_BASICIDE_STAT_TITLE );
579 0 : if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_CURSOR )
580 : {
581 0 : pBindings->Update( SID_BASICIDE_STAT_POS );
582 0 : pBindings->Update( SID_BASICIDE_STAT_TITLE );
583 : }
584 0 : if ( !bWasModified && pEditEngine->IsModified() )
585 : {
586 0 : pBindings->Invalidate( SID_SAVEDOC );
587 0 : pBindings->Invalidate( SID_DOC_MODIFIED );
588 0 : pBindings->Invalidate( SID_UNDO );
589 : }
590 0 : if ( rKEvt.GetKeyCode().GetCode() == KEY_INSERT )
591 0 : pBindings->Invalidate( SID_ATTR_INSERT );
592 : }
593 : }
594 : }
595 :
596 0 : void EditorWindow::HandleAutoCorrect()
597 : {
598 0 : TextSelection aSel = GetEditView()->GetSelection();
599 0 : sal_uLong nLine = aSel.GetStart().GetPara();
600 0 : sal_uInt16 nIndex = aSel.GetStart().GetIndex();
601 0 : OUString aLine( pEditEngine->GetText( nLine ) ); // the line being modified
602 0 : const OUString& sActSubName = GetActualSubName( nLine ); // the actual procedure
603 :
604 0 : std::vector<HighlightPortion> aPortions;
605 0 : aHighlighter.getHighlightPortions( aLine, aPortions );
606 :
607 0 : if( aPortions.empty() )
608 0 : return;
609 :
610 0 : HighlightPortion& r = aPortions.back();
611 0 : if( nIndex != aPortions.size()-1 )
612 : {//cursor is not standing at the end of the line
613 0 : for (std::vector<HighlightPortion>::iterator i(aPortions.begin());
614 0 : i != aPortions.end(); ++i)
615 : {
616 0 : if( i->nEnd == nIndex )
617 : {
618 0 : r = *i;
619 0 : break;
620 : }
621 : }
622 : }
623 :
624 0 : OUString sStr = aLine.copy( r.nBegin, r.nEnd - r.nBegin );
625 : //if WS or empty string: stop, nothing to do
626 0 : if( ( r.tokenType == TT_WHITESPACE ) || sStr.isEmpty() )
627 0 : return;
628 : //create the appropriate TextSelection, and update the cache
629 0 : TextPaM aStart( nLine, r.nBegin );
630 0 : TextPaM aEnd( nLine, r.nBegin + sStr.getLength() );
631 0 : TextSelection sTextSelection( aStart, aEnd );
632 0 : rModulWindow.UpdateModule();
633 0 : rModulWindow.GetSbModule()->GetCodeCompleteDataFromParse( aCodeCompleteCache );
634 : // correct the last entered keyword
635 0 : if( r.tokenType == TT_KEYWORDS )
636 : {
637 0 : sStr = sStr.toAsciiLowerCase();
638 0 : if( !SbModule::GetKeywordCase(sStr).isEmpty() )
639 : // if it is a keyword, get its correct case
640 0 : sStr = SbModule::GetKeywordCase(sStr);
641 : else
642 : // else capitalize first letter/select the correct one, and replace
643 0 : sStr = sStr.replaceAt( 0, 1, OUString(sStr[0]).toAsciiUpperCase() );
644 :
645 0 : pEditEngine->ReplaceText( sTextSelection, sStr );
646 0 : pEditView->SetSelection( aSel );
647 : }
648 0 : if( r.tokenType == TT_IDENTIFIER )
649 : {// correct variables
650 0 : if( !aCodeCompleteCache.GetCorrectCaseVarName( sStr, sActSubName ).isEmpty() )
651 : {
652 0 : sStr = aCodeCompleteCache.GetCorrectCaseVarName( sStr, sActSubName );
653 0 : pEditEngine->ReplaceText( sTextSelection, sStr );
654 0 : pEditView->SetSelection( aSel );
655 : }
656 : else
657 : {
658 : //autocorrect procedures
659 0 : SbxArray* pArr = rModulWindow.GetSbModule()->GetMethods();
660 0 : for( sal_uInt32 i=0; i < pArr->Count32(); ++i )
661 : {
662 0 : if( pArr->Get32(i)->GetName().equalsIgnoreAsciiCase( sStr ) )
663 : {
664 0 : sStr = pArr->Get32(i)->GetName(); //if found, get the correct case
665 0 : pEditEngine->ReplaceText( sTextSelection, sStr );
666 0 : pEditView->SetSelection( aSel );
667 0 : return;
668 : }
669 : }
670 : }
671 0 : }
672 : }
673 :
674 0 : TextSelection EditorWindow::GetLastHighlightPortionTextSelection()
675 : {//creates a text selection from the highlight portion on the cursor
676 0 : sal_uLong nLine = GetEditView()->GetSelection().GetStart().GetPara();
677 0 : sal_uInt16 nIndex = GetEditView()->GetSelection().GetStart().GetIndex();
678 0 : OUString aLine( pEditEngine->GetText( nLine ) ); // the line being modified
679 0 : std::vector<HighlightPortion> aPortions;
680 0 : aHighlighter.getHighlightPortions( aLine, aPortions );
681 :
682 : assert(!aPortions.empty());
683 0 : HighlightPortion& r = aPortions.back();
684 0 : if( nIndex != aPortions.size()-1 )
685 : {//cursor is not standing at the end of the line
686 0 : for (std::vector<HighlightPortion>::iterator i(aPortions.begin());
687 0 : i != aPortions.end(); ++i)
688 : {
689 0 : if( i->nEnd == nIndex )
690 : {
691 0 : r = *i;
692 0 : break;
693 : }
694 : }
695 : }
696 :
697 0 : if( aPortions.size() == 0 )
698 0 : return TextSelection();
699 :
700 0 : OUString sStr = aLine.copy( r.nBegin, r.nEnd - r.nBegin );
701 0 : TextPaM aStart( nLine, r.nBegin );
702 0 : TextPaM aEnd( nLine, r.nBegin + sStr.getLength() );
703 0 : return TextSelection( aStart, aEnd );
704 : }
705 :
706 0 : void EditorWindow::HandleAutoCloseParen()
707 : {
708 0 : TextSelection aSel = GetEditView()->GetSelection();
709 0 : sal_uLong nLine = aSel.GetStart().GetPara();
710 0 : OUString aLine( pEditEngine->GetText( nLine ) ); // the line being modified
711 :
712 0 : if( aLine.getLength() > 0 && aLine[aSel.GetEnd().GetIndex()-1] != '(' )
713 : {
714 0 : GetEditView()->InsertText(OUString(")"));
715 : //leave the cursor on it's place: inside the parenthesis
716 0 : TextPaM aEnd(nLine, aSel.GetEnd().GetIndex());
717 0 : GetEditView()->SetSelection( TextSelection( aEnd, aEnd ) );
718 0 : }
719 0 : }
720 :
721 0 : void EditorWindow::HandleAutoCloseDoubleQuotes()
722 : {
723 0 : TextSelection aSel = GetEditView()->GetSelection();
724 0 : sal_uLong nLine = aSel.GetStart().GetPara();
725 0 : OUString aLine( pEditEngine->GetText( nLine ) ); // the line being modified
726 :
727 0 : std::vector<HighlightPortion> aPortions;
728 0 : aHighlighter.getHighlightPortions( aLine, aPortions );
729 :
730 0 : if( aPortions.empty() )
731 0 : return;
732 :
733 0 : if( aLine.getLength() > 0 && !aLine.endsWith("\"") && (aPortions.back().tokenType != TT_STRING) )
734 : {
735 0 : GetEditView()->InsertText(OUString("\""));
736 : //leave the cursor on it's place: inside the two double quotes
737 0 : TextPaM aEnd(nLine, aSel.GetEnd().GetIndex());
738 0 : GetEditView()->SetSelection( TextSelection( aEnd, aEnd ) );
739 0 : }
740 : }
741 :
742 0 : void EditorWindow::HandleProcedureCompletion()
743 : {
744 :
745 0 : TextSelection aSel = GetEditView()->GetSelection();
746 0 : sal_uLong nLine = aSel.GetStart().GetPara();
747 0 : OUString aLine( pEditEngine->GetText( nLine ) );
748 :
749 0 : bool bFoundName = false;
750 0 : OUString sProcType;
751 0 : OUString sProcName;
752 :
753 0 : bFoundName = GetProcedureName(aLine, sProcType, sProcName);
754 :
755 0 : if (!bFoundName)
756 0 : return;
757 :
758 0 : OUString sText("\nEnd ");
759 0 : aSel = GetEditView()->GetSelection();
760 0 : if( sProcType.equalsIgnoreAsciiCase("function") )
761 0 : sText += "Function\n";
762 0 : if( sProcType.equalsIgnoreAsciiCase("sub") )
763 0 : sText += "Sub\n";
764 :
765 0 : if( nLine+1 == pEditEngine->GetParagraphCount() )
766 : {
767 0 : pEditView->InsertText( sText );//append to the end
768 0 : GetEditView()->SetSelection(aSel);
769 : }
770 : else
771 : {
772 0 : for( sal_uLong i = nLine+1; i < pEditEngine->GetParagraphCount(); ++i )
773 : {//searching forward for end token, or another sub/function definition
774 0 : OUString aCurrLine = pEditEngine->GetText( i );
775 0 : std::vector<HighlightPortion> aCurrPortions;
776 0 : aHighlighter.getHighlightPortions( aCurrLine, aCurrPortions );
777 :
778 0 : if( aCurrPortions.size() >= 3 )
779 : {//at least 3 tokens: (sub|function) whitespace idetifier ....
780 0 : HighlightPortion& r = aCurrPortions.front();
781 0 : OUString sStr = aCurrLine.copy(r.nBegin, r.nEnd - r.nBegin);
782 :
783 0 : if( r.tokenType == 9 )
784 : {
785 0 : if( sStr.equalsIgnoreAsciiCase("sub") || sStr.equalsIgnoreAsciiCase("function") )
786 : {
787 0 : pEditView->InsertText( sText );//append to the end
788 0 : GetEditView()->SetSelection(aSel);
789 0 : break;
790 : }
791 0 : if( sStr.equalsIgnoreAsciiCase("end") )
792 0 : break;
793 0 : }
794 : }
795 0 : }
796 0 : }
797 : }
798 :
799 0 : bool EditorWindow::GetProcedureName(OUString& rLine, OUString& rProcType, OUString& rProcName) const
800 : {
801 0 : std::vector<HighlightPortion> aPortions;
802 0 : aHighlighter.getHighlightPortions(rLine, aPortions);
803 :
804 0 : if( aPortions.empty() )
805 0 : return false;
806 :
807 0 : bool bFoundType = false;
808 0 : bool bFoundName = false;
809 :
810 0 : for (std::vector<HighlightPortion>::iterator i(aPortions.begin());
811 0 : i != aPortions.end(); ++i)
812 : {
813 0 : OUString sTokStr = rLine.copy(i->nBegin, i->nEnd - i->nBegin);
814 :
815 0 : if( i->tokenType == 9 && ( sTokStr.equalsIgnoreAsciiCase("sub")
816 0 : || sTokStr.equalsIgnoreAsciiCase("function")) )
817 : {
818 0 : rProcType = sTokStr;
819 0 : bFoundType = true;
820 : }
821 0 : if( i->tokenType == 1 && bFoundType )
822 : {
823 0 : rProcName = sTokStr;
824 0 : bFoundName = true;
825 0 : break;
826 : }
827 0 : }
828 :
829 0 : if( !bFoundType || !bFoundName )
830 0 : return false;// no sub/function keyword or there is no identifier
831 :
832 0 : return true;
833 :
834 : }
835 :
836 0 : void EditorWindow::HandleCodeCompletion()
837 : {
838 0 : rModulWindow.UpdateModule();
839 0 : rModulWindow.GetSbModule()->GetCodeCompleteDataFromParse(aCodeCompleteCache);
840 0 : TextSelection aSel = GetEditView()->GetSelection();
841 0 : sal_uLong nLine = aSel.GetStart().GetPara();
842 0 : OUString aLine( pEditEngine->GetText( nLine ) ); // the line being modified
843 0 : std::vector< OUString > aVect; //vector to hold the base variable+methods for the nested reflection
844 :
845 0 : std::vector<HighlightPortion> aPortions;
846 0 : aLine = aLine.copy(0, aSel.GetEnd().GetIndex());
847 0 : aHighlighter.getHighlightPortions( aLine, aPortions );
848 0 : if( !aPortions.empty() )
849 : {//use the syntax highlighter to grab out nested reflection calls, eg. aVar.aMethod("aa").aOtherMethod ..
850 0 : for( std::vector<HighlightPortion>::reverse_iterator i(
851 0 : aPortions.rbegin());
852 0 : i != aPortions.rend(); ++i)
853 : {
854 0 : if( i->tokenType == TT_WHITESPACE ) // a whitespace: stop; if there is no ws, it goes to the beginning of the line
855 0 : break;
856 0 : if( i->tokenType == TT_IDENTIFIER || i->tokenType == TT_KEYWORDS ) // extract the identifiers(methods, base variable)
857 : /* an example: Dim aLocVar2 as com.sun.star.beans.PropertyValue
858 : * here, aLocVar2.Name, and PropertyValue's Name field is treated as a keyword(?!)
859 : * */
860 0 : aVect.insert( aVect.begin(), aLine.copy(i->nBegin, i->nEnd - i->nBegin) );
861 : }
862 :
863 0 : if( aVect.size() == 0 )//nothing to do
864 0 : return;
865 0 : OUString sBaseName = aVect[0];//variable name
866 0 : OUString sVarType = aCodeCompleteCache.GetVarType( sBaseName );
867 0 : if( !sVarType.isEmpty() && CodeCompleteOptions::IsAutoCorrectOn() )
868 : {//correct variable name, if autocorrection on
869 0 : const OUString& sStr = aCodeCompleteCache.GetCorrectCaseVarName( sBaseName, GetActualSubName(nLine) );
870 0 : if( !sStr.isEmpty() )
871 : {
872 0 : TextPaM aStart(nLine, aSel.GetStart().GetIndex() - sStr.getLength() );
873 0 : TextSelection sTextSelection(aStart, TextPaM(nLine, aSel.GetStart().GetIndex()));
874 0 : pEditEngine->ReplaceText( sTextSelection, sStr );
875 0 : pEditView->SetSelection( aSel );
876 0 : }
877 : }
878 :
879 0 : UnoTypeCodeCompletetor aTypeCompletor( aVect, sVarType );
880 :
881 0 : if( aTypeCompletor.CanCodeComplete() )
882 : {
883 0 : std::vector< OUString > aEntryVect;//entries to be inserted into the list
884 0 : std::vector< OUString > aFieldVect = aTypeCompletor.GetXIdlClassFields();//fields
885 0 : aEntryVect.insert(aEntryVect.end(), aFieldVect.begin(), aFieldVect.end() );
886 0 : if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
887 : {// if extended types on, reflect classes, else just the structs (XIdlClass without methods)
888 0 : std::vector< OUString > aMethVect = aTypeCompletor.GetXIdlClassMethods();//methods
889 0 : aEntryVect.insert(aEntryVect.end(), aMethVect.begin(), aMethVect.end() );
890 : }
891 0 : if( aEntryVect.size() > 0 )
892 0 : SetupAndShowCodeCompleteWnd( aEntryVect, aSel );
893 0 : }
894 0 : }
895 : }
896 :
897 0 : void EditorWindow::SetupAndShowCodeCompleteWnd( const std::vector< OUString >& aEntryVect, TextSelection aSel )
898 : {
899 : // clear the listbox
900 0 : pCodeCompleteWnd->ClearListBox();
901 : // fill the listbox
902 0 : for(size_t l = 0; l < aEntryVect.size(); ++l)
903 : {
904 0 : pCodeCompleteWnd->InsertEntry( aEntryVect[l] );
905 : }
906 : // show it
907 0 : pCodeCompleteWnd->Show();
908 0 : pCodeCompleteWnd->ResizeAndPositionListBox();
909 0 : pCodeCompleteWnd->SelectFirstEntry();
910 : // correct text selection, and set it
911 0 : aSel.GetStart().GetIndex() += 1;
912 0 : aSel.GetEnd().GetIndex() += 1;
913 0 : pCodeCompleteWnd->SetTextSelection( aSel );
914 : //give the focus to the EditView
915 0 : pEditView->GetWindow()->GrabFocus();
916 0 : }
917 :
918 0 : void EditorWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
919 : {
920 0 : if (!pEditEngine) // We need it now at latest
921 0 : CreateEditEngine();
922 :
923 0 : pEditView->Paint(rRenderContext, rRect);
924 0 : }
925 :
926 0 : void EditorWindow::LoseFocus()
927 : {
928 0 : SetSourceInBasic();
929 0 : Window::LoseFocus();
930 0 : }
931 :
932 0 : bool EditorWindow::SetSourceInBasic()
933 : {
934 0 : bool bChanged = false;
935 0 : if ( pEditEngine && pEditEngine->IsModified()
936 0 : && !GetEditView()->IsReadOnly() ) // Added for #i60626, otherwise
937 : // any read only bug in the text engine could lead to a crash later
938 : {
939 0 : if ( !StarBASIC::IsRunning() ) // Not at runtime!
940 : {
941 0 : rModulWindow.UpdateModule();
942 0 : bChanged = true;
943 : }
944 : }
945 0 : return bChanged;
946 : }
947 :
948 : // Returns the position of the last character of any of the following
949 : // EOL char combinations: CR, CR/LF, LF, return -1 if no EOL is found
950 0 : sal_Int32 searchEOL( const OUString& rStr, sal_Int32 fromIndex )
951 : {
952 0 : sal_Int32 iRetPos = -1;
953 :
954 0 : sal_Int32 iLF = rStr.indexOf( LINE_SEP, fromIndex );
955 0 : if( iLF != -1 )
956 : {
957 0 : iRetPos = iLF;
958 : }
959 : else
960 : {
961 0 : iRetPos = rStr.indexOf( LINE_SEP_CR, fromIndex );
962 : }
963 0 : return iRetPos;
964 : }
965 :
966 0 : void EditorWindow::CreateEditEngine()
967 : {
968 0 : if (pEditEngine)
969 0 : return;
970 :
971 0 : pEditEngine.reset(new ExtTextEngine);
972 0 : pEditView.reset(new ExtTextView(pEditEngine.get(), this));
973 0 : pEditView->SetAutoIndentMode(true);
974 0 : pEditEngine->SetUpdateMode(false);
975 0 : pEditEngine->InsertView(pEditView.get());
976 :
977 0 : ImplSetFont();
978 :
979 0 : aSyntaxIdle.SetPriority( SchedulerPriority::LOWER );
980 0 : aSyntaxIdle.SetIdleHdl( LINK( this, EditorWindow, SyntaxTimerHdl ) );
981 :
982 0 : bool bWasDoSyntaxHighlight = bDoSyntaxHighlight;
983 0 : bDoSyntaxHighlight = false; // too slow for large texts...
984 0 : OUString aOUSource(rModulWindow.GetModule());
985 0 : sal_Int32 nLines = 0;
986 0 : sal_Int32 nIndex = -1;
987 0 : do
988 : {
989 0 : nLines++;
990 0 : nIndex = searchEOL( aOUSource, nIndex+1 );
991 : }
992 : while (nIndex >= 0);
993 :
994 : // nLines*4: SetText+Formatting+DoHighlight+Formatting
995 : // it could be cut down on one formatting but you would wait even longer
996 : // for the text then if the source code is long...
997 0 : pProgress.reset(new ProgressInfo(GetShell()->GetViewFrame()->GetObjectShell(),
998 : IDEResId(RID_STR_GENERATESOURCE).toString(),
999 0 : nLines * 4));
1000 0 : setTextEngineText(*pEditEngine, aOUSource);
1001 :
1002 0 : pEditView->SetStartDocPos(Point(0, 0));
1003 0 : pEditView->SetSelection(TextSelection());
1004 0 : rModulWindow.GetBreakPointWindow().GetCurYOffset() = 0;
1005 0 : rModulWindow.GetLineNumberWindow().GetCurYOffset() = 0;
1006 0 : pEditEngine->SetUpdateMode(true);
1007 0 : rModulWindow.Update(); // has only been invalidated at UpdateMode = true
1008 :
1009 0 : pEditView->ShowCursor(true, true);
1010 :
1011 0 : StartListening(*pEditEngine);
1012 :
1013 0 : aSyntaxIdle.Stop();
1014 0 : bDoSyntaxHighlight = bWasDoSyntaxHighlight;
1015 :
1016 0 : for (sal_Int32 nLine = 0; nLine < nLines; nLine++)
1017 0 : aSyntaxLineTable.insert(nLine);
1018 0 : ForceSyntaxTimeout();
1019 :
1020 0 : pProgress.reset();
1021 :
1022 0 : pEditView->EraseVirtualDevice();
1023 0 : pEditEngine->SetModified( false );
1024 0 : pEditEngine->EnableUndo( true );
1025 :
1026 0 : InitScrollBars();
1027 :
1028 0 : if (SfxBindings* pBindings = GetBindingsPtr())
1029 : {
1030 0 : pBindings->Invalidate(SID_BASICIDE_STAT_POS);
1031 0 : pBindings->Invalidate(SID_BASICIDE_STAT_TITLE);
1032 : }
1033 :
1034 : DBG_ASSERT(rModulWindow.GetBreakPointWindow().GetCurYOffset() == 0, "CreateEditEngine: Brechpunkte verschoben?");
1035 :
1036 : // set readonly mode for readonly libraries
1037 0 : ScriptDocument aDocument(rModulWindow.GetDocument());
1038 0 : OUString aOULibName(rModulWindow.GetLibName());
1039 0 : Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
1040 0 : if (xModLibContainer.is()
1041 0 : && xModLibContainer->hasByName(aOULibName)
1042 0 : && xModLibContainer->isLibraryReadOnly(aOULibName))
1043 : {
1044 0 : rModulWindow.SetReadOnly(true);
1045 : }
1046 :
1047 0 : if (aDocument.isDocument() && aDocument.isReadOnly())
1048 0 : rModulWindow.SetReadOnly(true);
1049 : }
1050 :
1051 : // virtual
1052 0 : void EditorWindow::DataChanged(DataChangedEvent const & rDCEvt)
1053 : {
1054 0 : Window::DataChanged(rDCEvt);
1055 0 : if (rDCEvt.GetType() == DataChangedEventType::SETTINGS
1056 0 : && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1057 : {
1058 0 : Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
1059 0 : const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
1060 0 : if (!pOldSettings || aColor != pOldSettings->GetStyleSettings().GetFieldColor())
1061 : {
1062 0 : SetBackground(Wallpaper(aColor));
1063 0 : Invalidate();
1064 : }
1065 0 : if (pEditEngine != 0)
1066 : {
1067 0 : aColor = GetSettings().GetStyleSettings().GetFieldTextColor();
1068 0 : if (!pOldSettings || aColor !=
1069 0 : pOldSettings-> GetStyleSettings().GetFieldTextColor())
1070 : {
1071 0 : vcl::Font aFont(pEditEngine->GetFont());
1072 0 : aFont.SetColor(aColor);
1073 0 : pEditEngine->SetFont(aFont);
1074 : }
1075 : }
1076 : }
1077 0 : }
1078 :
1079 0 : void EditorWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1080 : {
1081 0 : if (TextHint const* pTextHint = dynamic_cast<TextHint const*>(&rHint))
1082 : {
1083 0 : TextHint const& rTextHint = *pTextHint;
1084 0 : if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED )
1085 : {
1086 0 : if ( rModulWindow.GetHScrollBar() )
1087 0 : rModulWindow.GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
1088 0 : rModulWindow.GetEditVScrollBar().SetThumbPos( pEditView->GetStartDocPos().Y() );
1089 0 : rModulWindow.GetBreakPointWindow().DoScroll
1090 0 : ( 0, rModulWindow.GetBreakPointWindow().GetCurYOffset() - pEditView->GetStartDocPos().Y() );
1091 0 : rModulWindow.GetLineNumberWindow().DoScroll
1092 0 : ( 0, rModulWindow.GetLineNumberWindow().GetCurYOffset() - pEditView->GetStartDocPos().Y() );
1093 : }
1094 0 : else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
1095 : {
1096 0 : if ( pEditView->GetStartDocPos().Y() )
1097 : {
1098 0 : long nOutHeight = GetOutputSizePixel().Height();
1099 0 : long nTextHeight = pEditEngine->GetTextHeight();
1100 0 : if ( nTextHeight < nOutHeight )
1101 0 : pEditView->Scroll( 0, pEditView->GetStartDocPos().Y() );
1102 :
1103 0 : rModulWindow.GetLineNumberWindow().Invalidate();
1104 : }
1105 :
1106 0 : SetScrollBarRanges();
1107 : }
1108 0 : else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED )
1109 : {
1110 0 : if ( rModulWindow.GetHScrollBar() )
1111 : {
1112 0 : sal_uLong nWidth = pEditEngine->CalcTextWidth();
1113 0 : if ( (long)nWidth != nCurTextWidth )
1114 : {
1115 0 : nCurTextWidth = nWidth;
1116 0 : rModulWindow.GetHScrollBar()->SetRange( Range( 0, (long)nCurTextWidth-1) );
1117 0 : rModulWindow.GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
1118 : }
1119 : }
1120 0 : long nPrevTextWidth = nCurTextWidth;
1121 0 : nCurTextWidth = pEditEngine->CalcTextWidth();
1122 0 : if ( nCurTextWidth != nPrevTextWidth )
1123 0 : SetScrollBarRanges();
1124 : }
1125 0 : else if( rTextHint.GetId() == TEXT_HINT_PARAINSERTED )
1126 : {
1127 0 : ParagraphInsertedDeleted( rTextHint.GetValue(), true );
1128 0 : DoDelayedSyntaxHighlight( rTextHint.GetValue() );
1129 : }
1130 0 : else if( rTextHint.GetId() == TEXT_HINT_PARAREMOVED )
1131 : {
1132 0 : ParagraphInsertedDeleted( rTextHint.GetValue(), false );
1133 : }
1134 0 : else if( rTextHint.GetId() == TEXT_HINT_PARACONTENTCHANGED )
1135 : {
1136 0 : DoDelayedSyntaxHighlight( rTextHint.GetValue() );
1137 : }
1138 0 : else if( rTextHint.GetId() == TEXT_HINT_VIEWSELECTIONCHANGED )
1139 : {
1140 0 : if (SfxBindings* pBindings = GetBindingsPtr())
1141 : {
1142 0 : pBindings->Invalidate( SID_CUT );
1143 0 : pBindings->Invalidate( SID_COPY );
1144 : }
1145 : }
1146 : }
1147 0 : }
1148 :
1149 0 : OUString EditorWindow::GetActualSubName( sal_uLong nLine )
1150 : {
1151 0 : SbxArrayRef pMethods = rModulWindow.GetSbModule()->GetMethods();
1152 0 : for( sal_uInt16 i=0; i < pMethods->Count(); i++ )
1153 : {
1154 0 : SbxVariable* p = PTR_CAST( SbMethod, pMethods->Get( i ) );
1155 0 : SbMethod* pMeth = PTR_CAST( SbMethod, p );
1156 0 : if( pMeth )
1157 : {
1158 : sal_uInt16 l1,l2;
1159 0 : pMeth->GetLineRange(l1,l2);
1160 0 : if( (l1 <= nLine+1) && (nLine+1 <= l2) )
1161 : {
1162 0 : return pMeth->GetName();
1163 : }
1164 : }
1165 : }
1166 0 : return OUString("");
1167 : }
1168 :
1169 0 : void EditorWindow::SetScrollBarRanges()
1170 : {
1171 : // extra method, not InitScrollBars, because for EditEngine events too
1172 0 : if ( !pEditEngine )
1173 0 : return;
1174 :
1175 0 : if ( rModulWindow.GetHScrollBar() )
1176 0 : rModulWindow.GetHScrollBar()->SetRange( Range( 0, nCurTextWidth-1 ) );
1177 :
1178 0 : rModulWindow.GetEditVScrollBar().SetRange( Range( 0, pEditEngine->GetTextHeight()-1 ) );
1179 : }
1180 :
1181 0 : void EditorWindow::InitScrollBars()
1182 : {
1183 0 : if (!pEditEngine)
1184 0 : return;
1185 :
1186 0 : SetScrollBarRanges();
1187 0 : Size aOutSz(GetOutputSizePixel());
1188 0 : rModulWindow.GetEditVScrollBar().SetVisibleSize(aOutSz.Height());
1189 0 : rModulWindow.GetEditVScrollBar().SetPageSize(aOutSz.Height() * 8 / 10);
1190 0 : rModulWindow.GetEditVScrollBar().SetLineSize(GetTextHeight());
1191 0 : rModulWindow.GetEditVScrollBar().SetThumbPos(pEditView->GetStartDocPos().Y());
1192 0 : rModulWindow.GetEditVScrollBar().Show();
1193 :
1194 0 : if (rModulWindow.GetHScrollBar())
1195 : {
1196 0 : rModulWindow.GetHScrollBar()->SetVisibleSize(aOutSz.Width());
1197 0 : rModulWindow.GetHScrollBar()->SetPageSize(aOutSz.Width() * 8 / 10);
1198 0 : rModulWindow.GetHScrollBar()->SetLineSize(GetTextWidth( "x" ) );
1199 0 : rModulWindow.GetHScrollBar()->SetThumbPos(pEditView->GetStartDocPos().X());
1200 0 : rModulWindow.GetHScrollBar()->Show();
1201 : }
1202 : }
1203 :
1204 0 : void EditorWindow::ImpDoHighlight( sal_uLong nLine )
1205 : {
1206 0 : if ( bDoSyntaxHighlight )
1207 : {
1208 0 : OUString aLine( pEditEngine->GetText( nLine ) );
1209 0 : bool const bWasModified = pEditEngine->IsModified();
1210 0 : pEditEngine->RemoveAttribs( nLine, true );
1211 0 : std::vector<HighlightPortion> aPortions;
1212 0 : aHighlighter.getHighlightPortions( aLine, aPortions );
1213 :
1214 0 : for (std::vector<HighlightPortion>::iterator i(aPortions.begin());
1215 0 : i != aPortions.end(); ++i)
1216 : {
1217 0 : Color const aColor = rModulWindow.GetLayout().GetSyntaxColor(i->tokenType);
1218 0 : pEditEngine->SetAttrib(TextAttribFontColor(aColor), nLine, i->nBegin, i->nEnd, true);
1219 : }
1220 :
1221 0 : pEditEngine->SetModified(bWasModified);
1222 : }
1223 0 : }
1224 :
1225 0 : void EditorWindow::UpdateSyntaxHighlighting ()
1226 : {
1227 0 : unsigned nCount = pEditEngine->GetParagraphCount();
1228 0 : for (unsigned i = 0; i < nCount; ++i)
1229 0 : DoDelayedSyntaxHighlight(i);
1230 0 : }
1231 :
1232 0 : void EditorWindow::ImplSetFont()
1233 : {
1234 0 : OUString sFontName(officecfg::Office::Common::Font::SourceViewFont::FontName::get().get_value_or(OUString()));
1235 0 : if (sFontName.isEmpty())
1236 : {
1237 : vcl::Font aTmpFont(OutputDevice::GetDefaultFont(DefaultFontType::FIXED,
1238 0 : Application::GetSettings().GetUILanguageTag().getLanguageType(),
1239 0 : GetDefaultFontFlags::NONE, this));
1240 0 : sFontName = aTmpFont.GetName();
1241 : }
1242 0 : Size aFontSize(0, officecfg::Office::Common::Font::SourceViewFont::FontHeight::get());
1243 0 : vcl::Font aFont(sFontName, aFontSize);
1244 0 : aFont.SetColor(Application::GetSettings().GetStyleSettings().GetFieldTextColor());
1245 0 : SetPointFont(*this, aFont); // FIXME RenderContext
1246 0 : aFont = GetFont();
1247 :
1248 0 : rModulWindow.GetBreakPointWindow().SetFont(aFont);
1249 0 : rModulWindow.GetLineNumberWindow().SetFont(aFont);
1250 :
1251 0 : if (pEditEngine)
1252 : {
1253 0 : bool const bModified = pEditEngine->IsModified();
1254 0 : pEditEngine->SetFont(aFont);
1255 0 : pEditEngine->SetModified(bModified);
1256 0 : }
1257 0 : }
1258 :
1259 0 : void EditorWindow::DoSyntaxHighlight( sal_uLong nPara )
1260 : {
1261 : // because of the DelayedSyntaxHighlight it's possible
1262 : // that this line does not exist anymore!
1263 0 : if ( nPara < pEditEngine->GetParagraphCount() )
1264 : {
1265 : // unfortunately I'm not sure that excactly this line does Modified() ...
1266 0 : if ( pProgress )
1267 0 : pProgress->StepProgress();
1268 0 : ImpDoHighlight( nPara );
1269 : }
1270 0 : }
1271 :
1272 0 : void EditorWindow::DoDelayedSyntaxHighlight( sal_uLong nPara )
1273 : {
1274 : // line is only added to 'Liste' (list), processed in TimerHdl
1275 : // => don't manipulate breaks while EditEngine is formatting
1276 0 : if ( pProgress )
1277 0 : pProgress->StepProgress();
1278 :
1279 0 : if ( !bHighlightning && bDoSyntaxHighlight )
1280 : {
1281 0 : if ( bDelayHighlight )
1282 : {
1283 0 : aSyntaxLineTable.insert( nPara );
1284 0 : aSyntaxIdle.Start();
1285 : }
1286 : else
1287 0 : DoSyntaxHighlight( nPara );
1288 : }
1289 0 : }
1290 :
1291 0 : IMPL_LINK_NOARG_TYPED(EditorWindow, SyntaxTimerHdl, Idle *, void)
1292 : {
1293 : DBG_ASSERT( pEditView, "Noch keine View, aber Syntax-Highlight ?!" );
1294 :
1295 0 : bool const bWasModified = pEditEngine->IsModified();
1296 : //pEditEngine->SetUpdateMode(false);
1297 :
1298 0 : bHighlightning = true;
1299 0 : for ( SyntaxLineSet::const_iterator it = aSyntaxLineTable.begin();
1300 0 : it != aSyntaxLineTable.end(); ++it )
1301 : {
1302 0 : sal_uInt16 nLine = *it;
1303 0 : DoSyntaxHighlight( nLine );
1304 : }
1305 :
1306 : // #i45572#
1307 0 : if ( pEditView )
1308 0 : pEditView->ShowCursor( false, true );
1309 :
1310 0 : pEditEngine->SetModified( bWasModified );
1311 :
1312 0 : aSyntaxLineTable.clear();
1313 0 : bHighlightning = false;
1314 0 : }
1315 :
1316 0 : void EditorWindow::ParagraphInsertedDeleted( sal_uLong nPara, bool bInserted )
1317 : {
1318 0 : if ( pProgress )
1319 0 : pProgress->StepProgress();
1320 :
1321 0 : if ( !bInserted && ( nPara == TEXT_PARA_ALL ) )
1322 : {
1323 0 : rModulWindow.GetBreakPoints().reset();
1324 0 : rModulWindow.GetBreakPointWindow().Invalidate();
1325 0 : rModulWindow.GetLineNumberWindow().Invalidate();
1326 : }
1327 : else
1328 : {
1329 0 : rModulWindow.GetBreakPoints().AdjustBreakPoints( (sal_uInt16)nPara+1, bInserted );
1330 :
1331 0 : long nLineHeight = GetTextHeight();
1332 0 : Size aSz = rModulWindow.GetBreakPointWindow().GetOutputSize();
1333 0 : Rectangle aInvRect( Point( 0, 0 ), aSz );
1334 0 : long nY = nPara*nLineHeight - rModulWindow.GetBreakPointWindow().GetCurYOffset();
1335 0 : aInvRect.Top() = nY;
1336 0 : rModulWindow.GetBreakPointWindow().Invalidate( aInvRect );
1337 :
1338 0 : Size aLnSz(rModulWindow.GetLineNumberWindow().GetWidth(),
1339 0 : GetOutputSizePixel().Height() - 2 * DWBORDER);
1340 0 : rModulWindow.GetLineNumberWindow().SetPosSizePixel(Point(DWBORDER + 19, DWBORDER), aLnSz);
1341 0 : rModulWindow.GetLineNumberWindow().Invalidate();
1342 : }
1343 0 : }
1344 :
1345 0 : void EditorWindow::CreateProgress( const OUString& rText, sal_uLong nRange )
1346 : {
1347 : DBG_ASSERT( !pProgress, "ProgressInfo existiert schon" );
1348 : pProgress.reset(new ProgressInfo(
1349 0 : GetShell()->GetViewFrame()->GetObjectShell(),
1350 : rText,
1351 : nRange
1352 0 : ));
1353 0 : }
1354 :
1355 0 : void EditorWindow::DestroyProgress()
1356 : {
1357 0 : pProgress.reset();
1358 0 : }
1359 :
1360 0 : void EditorWindow::ForceSyntaxTimeout()
1361 : {
1362 0 : aSyntaxIdle.Stop();
1363 0 : aSyntaxIdle.GetIdleHdl().Call(&aSyntaxIdle);
1364 0 : }
1365 :
1366 : // BreakPointWindow
1367 :
1368 0 : BreakPointWindow::BreakPointWindow (vcl::Window* pParent, ModulWindow* pModulWindow)
1369 : : Window(pParent, WB_BORDER)
1370 : , rModulWindow(*pModulWindow)
1371 : , nCurYOffset(0) // memorize nCurYOffset and not take it from EditEngine
1372 : , nMarkerPos(NoMarker)
1373 0 : , bErrorMarker(false)
1374 : {
1375 0 : setBackgroundColor(GetSettings().GetStyleSettings().GetFieldColor());
1376 0 : SetHelpId(HID_BASICIDE_BREAKPOINTWINDOW);
1377 0 : }
1378 :
1379 0 : void BreakPointWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
1380 : {
1381 0 : if (SyncYOffset())
1382 0 : return;
1383 :
1384 0 : Size const aOutSz = rRenderContext.GetOutputSize();
1385 0 : long const nLineHeight = rRenderContext.GetTextHeight();
1386 :
1387 : Image const aBrk[2] =
1388 : {
1389 : GetImage(IMGID_BRKDISABLED),
1390 : GetImage(IMGID_BRKENABLED)
1391 0 : };
1392 :
1393 0 : Size const aBmpSz = rRenderContext.PixelToLogic(aBrk[1].GetSizePixel());
1394 0 : Point const aBmpOff((aOutSz.Width() - aBmpSz.Width()) / 2,
1395 0 : (nLineHeight - aBmpSz.Height()) / 2);
1396 :
1397 0 : for (size_t i = 0, n = GetBreakPoints().size(); i < n; ++i)
1398 : {
1399 0 : BreakPoint& rBrk = *GetBreakPoints().at(i);
1400 0 : size_t const nLine = rBrk.nLine - 1;
1401 0 : size_t const nY = nLine*nLineHeight - nCurYOffset;
1402 0 : rRenderContext.DrawImage(Point(0, nY) + aBmpOff, aBrk[rBrk.bEnabled]);
1403 : }
1404 :
1405 0 : ShowMarker(rRenderContext);
1406 : }
1407 :
1408 0 : void BreakPointWindow::ShowMarker(vcl::RenderContext& rRenderContext)
1409 : {
1410 0 : if (nMarkerPos == NoMarker)
1411 0 : return;
1412 :
1413 0 : Size const aOutSz = GetOutputSize();
1414 0 : long const nLineHeight = GetTextHeight();
1415 :
1416 0 : Image aMarker = GetImage(bErrorMarker ? IMGID_ERRORMARKER : IMGID_STEPMARKER);
1417 :
1418 0 : Size aMarkerSz(aMarker.GetSizePixel());
1419 0 : aMarkerSz = rRenderContext.PixelToLogic(aMarkerSz);
1420 0 : Point aMarkerOff(0, 0);
1421 0 : aMarkerOff.X() = (aOutSz.Width() - aMarkerSz.Width()) / 2;
1422 0 : aMarkerOff.Y() = (nLineHeight - aMarkerSz.Height()) / 2;
1423 :
1424 0 : sal_uLong nY = nMarkerPos * nLineHeight - nCurYOffset;
1425 0 : Point aPos(0, nY);
1426 0 : aPos += aMarkerOff;
1427 :
1428 0 : rRenderContext.DrawImage(aPos, aMarker);
1429 : }
1430 :
1431 0 : void BreakPointWindow::DoScroll( long nHorzScroll, long nVertScroll )
1432 : {
1433 0 : nCurYOffset -= nVertScroll;
1434 0 : Window::Scroll( nHorzScroll, nVertScroll );
1435 0 : }
1436 :
1437 0 : void BreakPointWindow::SetMarkerPos( sal_uInt16 nLine, bool bError )
1438 : {
1439 0 : if ( SyncYOffset() )
1440 0 : Update();
1441 :
1442 0 : nMarkerPos = nLine;
1443 0 : bErrorMarker = bError;
1444 0 : Invalidate();
1445 0 : }
1446 :
1447 0 : void BreakPointWindow::SetNoMarker ()
1448 : {
1449 0 : SetMarkerPos(NoMarker);
1450 0 : }
1451 :
1452 0 : BreakPoint* BreakPointWindow::FindBreakPoint( const Point& rMousePos )
1453 : {
1454 0 : size_t nLineHeight = GetTextHeight();
1455 0 : nLineHeight = nLineHeight > 0 ? nLineHeight : 1;
1456 0 : size_t nYPos = rMousePos.Y() + nCurYOffset;
1457 :
1458 0 : for ( size_t i = 0, n = GetBreakPoints().size(); i < n ; ++i )
1459 : {
1460 0 : BreakPoint* pBrk = GetBreakPoints().at( i );
1461 0 : size_t nLine = pBrk->nLine-1;
1462 0 : size_t nY = nLine*nLineHeight;
1463 0 : if ( ( nYPos > nY ) && ( nYPos < ( nY + nLineHeight ) ) )
1464 0 : return pBrk;
1465 : }
1466 0 : return 0;
1467 : }
1468 :
1469 0 : void BreakPointWindow::MouseButtonDown( const MouseEvent& rMEvt )
1470 : {
1471 0 : if ( rMEvt.GetClicks() == 2 )
1472 : {
1473 0 : Point aMousePos( PixelToLogic( rMEvt.GetPosPixel() ) );
1474 0 : long nLineHeight = GetTextHeight();
1475 0 : if(nLineHeight)
1476 : {
1477 0 : long nYPos = aMousePos.Y() + nCurYOffset;
1478 0 : long nLine = nYPos / nLineHeight + 1;
1479 0 : rModulWindow.ToggleBreakPoint( (sal_uLong)nLine );
1480 0 : Invalidate();
1481 : }
1482 : }
1483 0 : }
1484 :
1485 0 : void BreakPointWindow::Command( const CommandEvent& rCEvt )
1486 : {
1487 0 : if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
1488 : {
1489 0 : Point aPos( rCEvt.IsMouseEvent() ? rCEvt.GetMousePosPixel() : Point(1,1) );
1490 0 : Point aEventPos( PixelToLogic( aPos ) );
1491 0 : BreakPoint* pBrk = rCEvt.IsMouseEvent() ? FindBreakPoint( aEventPos ) : 0;
1492 0 : if ( pBrk )
1493 : {
1494 : // test if break point is enabled...
1495 0 : PopupMenu aBrkPropMenu( IDEResId( RID_POPUP_BRKPROPS ) );
1496 0 : aBrkPropMenu.CheckItem( RID_ACTIV, pBrk->bEnabled );
1497 0 : switch ( aBrkPropMenu.Execute( this, aPos ) )
1498 : {
1499 : case RID_ACTIV:
1500 : {
1501 0 : pBrk->bEnabled = !pBrk->bEnabled;
1502 0 : rModulWindow.UpdateBreakPoint( *pBrk );
1503 0 : Invalidate();
1504 : }
1505 0 : break;
1506 : case RID_BRKPROPS:
1507 : {
1508 0 : ScopedVclPtrInstance< BreakPointDialog > aBrkDlg( this, GetBreakPoints() );
1509 0 : aBrkDlg->SetCurrentBreakPoint( pBrk );
1510 0 : aBrkDlg->Execute();
1511 0 : Invalidate();
1512 : }
1513 0 : break;
1514 0 : }
1515 : }
1516 : else
1517 : {
1518 0 : PopupMenu aBrkListMenu( IDEResId( RID_POPUP_BRKDLG ) );
1519 0 : switch ( aBrkListMenu.Execute( this, aPos ) )
1520 : {
1521 : case RID_BRKDLG:
1522 : {
1523 0 : ScopedVclPtrInstance< BreakPointDialog > aBrkDlg( this, GetBreakPoints() );
1524 0 : aBrkDlg->Execute();
1525 0 : Invalidate();
1526 : }
1527 0 : break;
1528 0 : }
1529 : }
1530 : }
1531 0 : }
1532 :
1533 0 : bool BreakPointWindow::SyncYOffset()
1534 : {
1535 0 : TextView* pView = rModulWindow.GetEditView();
1536 0 : if ( pView )
1537 : {
1538 0 : long nViewYOffset = pView->GetStartDocPos().Y();
1539 0 : if ( nCurYOffset != nViewYOffset )
1540 : {
1541 0 : nCurYOffset = nViewYOffset;
1542 0 : Invalidate();
1543 0 : return true;
1544 : }
1545 : }
1546 0 : return false;
1547 : }
1548 :
1549 : // virtual
1550 0 : void BreakPointWindow::DataChanged(DataChangedEvent const & rDCEvt)
1551 : {
1552 0 : Window::DataChanged(rDCEvt);
1553 0 : if (rDCEvt.GetType() == DataChangedEventType::SETTINGS
1554 0 : && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
1555 : {
1556 0 : Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
1557 0 : const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
1558 0 : if (!pOldSettings || aColor != pOldSettings->GetStyleSettings().GetFieldColor())
1559 : {
1560 0 : setBackgroundColor(aColor);
1561 0 : Invalidate();
1562 : }
1563 : }
1564 0 : }
1565 :
1566 0 : void BreakPointWindow::setBackgroundColor(Color aColor)
1567 : {
1568 0 : SetBackground(Wallpaper(aColor));
1569 0 : }
1570 :
1571 : namespace
1572 : {
1573 : const sal_uInt16 ITEM_ID_VARIABLE = 1;
1574 : const sal_uInt16 ITEM_ID_VALUE = 2;
1575 : const sal_uInt16 ITEM_ID_TYPE = 3;
1576 : }
1577 :
1578 0 : WatchWindow::WatchWindow (Layout* pParent) :
1579 : DockingWindow(pParent),
1580 : aWatchStr( IDEResId( RID_STR_REMOVEWATCH ) ),
1581 : aXEdit( VclPtr<ExtendedEdit>::Create(this, IDEResId( RID_EDT_WATCHEDIT )) ),
1582 : aRemoveWatchButton( VclPtr<ImageButton>::Create(this, IDEResId( RID_IMGBTN_REMOVEWATCH )) ),
1583 : aTreeListBox( VclPtr<WatchTreeListBox>::Create(this, WB_BORDER | WB_3DLOOK | WB_HASBUTTONS | WB_HASLINES | WB_HSCROLL | WB_TABSTOP
1584 : | WB_HASLINESATROOT | WB_HASBUTTONSATROOT) ),
1585 0 : aHeaderBar( VclPtr<HeaderBar>::Create( this, WB_BUTTONSTYLE | WB_BORDER ) )
1586 : {
1587 0 : aXEdit->SetAccessibleName(IDEResId(RID_STR_WATCHNAME).toString());
1588 0 : aTreeListBox->SetAccessibleName(IDEResId(RID_STR_WATCHNAME).toString());
1589 :
1590 0 : long nTextLen = GetTextWidth( aWatchStr ) + DWBORDER + 3;
1591 0 : aXEdit->SetPosPixel( Point( nTextLen, 3 ) );
1592 0 : aXEdit->SetAccHdl( LINK( this, WatchWindow, EditAccHdl ) );
1593 0 : aXEdit->GetAccelerator().InsertItem( 1, vcl::KeyCode( KEY_RETURN ) );
1594 0 : aXEdit->GetAccelerator().InsertItem( 2, vcl::KeyCode( KEY_ESCAPE ) );
1595 0 : aXEdit->Show();
1596 :
1597 0 : aRemoveWatchButton->Disable();
1598 0 : aRemoveWatchButton->SetClickHdl( LINK( this, WatchWindow, ButtonHdl ) );
1599 0 : aRemoveWatchButton->SetPosPixel( Point( nTextLen + aXEdit->GetSizePixel().Width() + 4, 2 ) );
1600 0 : Size aSz( aRemoveWatchButton->GetModeImage().GetSizePixel() );
1601 0 : aSz.Width() += 6;
1602 0 : aSz.Height() += 6;
1603 0 : aRemoveWatchButton->SetSizePixel( aSz );
1604 0 : aRemoveWatchButton->Show();
1605 :
1606 0 : long nRWBtnSize = aRemoveWatchButton->GetModeImage().GetSizePixel().Height() + 10;
1607 0 : nVirtToolBoxHeight = aXEdit->GetSizePixel().Height() + 7;
1608 :
1609 0 : if ( nRWBtnSize > nVirtToolBoxHeight )
1610 0 : nVirtToolBoxHeight = nRWBtnSize;
1611 :
1612 0 : nHeaderBarHeight = 16;
1613 :
1614 0 : aTreeListBox->SetHelpId(HID_BASICIDE_WATCHWINDOW_LIST);
1615 0 : aTreeListBox->EnableInplaceEditing(true);
1616 0 : aTreeListBox->SetSelectHdl( LINK( this, WatchWindow, TreeListHdl ) );
1617 0 : aTreeListBox->SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight + nHeaderBarHeight ) );
1618 0 : aTreeListBox->SetHighlightRange( 1, 5 );
1619 :
1620 0 : Point aPnt( DWBORDER, nVirtToolBoxHeight + 1 );
1621 0 : aHeaderBar->SetPosPixel( aPnt );
1622 0 : aHeaderBar->SetEndDragHdl( LINK( this, WatchWindow, implEndDragHdl ) );
1623 :
1624 0 : long nVarTabWidth = 220;
1625 0 : long nValueTabWidth = 100;
1626 0 : long nTypeTabWidth = 1250;
1627 0 : aHeaderBar->InsertItem( ITEM_ID_VARIABLE, IDEResId(RID_STR_WATCHVARIABLE).toString(), nVarTabWidth );
1628 0 : aHeaderBar->InsertItem( ITEM_ID_VALUE, IDEResId(RID_STR_WATCHVALUE).toString(), nValueTabWidth );
1629 0 : aHeaderBar->InsertItem( ITEM_ID_TYPE, IDEResId(RID_STR_WATCHTYPE).toString(), nTypeTabWidth );
1630 :
1631 : long tabs[ 4 ];
1632 0 : tabs[ 0 ] = 3; // two tabs
1633 0 : tabs[ 1 ] = 0;
1634 0 : tabs[ 2 ] = nVarTabWidth;
1635 0 : tabs[ 3 ] = nVarTabWidth + nValueTabWidth;
1636 0 : aTreeListBox->SvHeaderTabListBox::SetTabs( tabs, MAP_PIXEL );
1637 0 : aTreeListBox->InitHeaderBar( aHeaderBar.get() );
1638 :
1639 0 : aTreeListBox->SetNodeDefaultImages( );
1640 :
1641 0 : aHeaderBar->Show();
1642 :
1643 0 : aTreeListBox->Show();
1644 :
1645 0 : SetText(IDEResId(RID_STR_WATCHNAME).toString());
1646 :
1647 0 : SetHelpId( HID_BASICIDE_WATCHWINDOW );
1648 :
1649 : // make watch window keyboard accessible
1650 0 : GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1651 0 : }
1652 :
1653 :
1654 :
1655 0 : WatchWindow::~WatchWindow()
1656 : {
1657 0 : disposeOnce();
1658 0 : }
1659 :
1660 0 : void WatchWindow::dispose()
1661 : {
1662 0 : aXEdit.disposeAndClear();
1663 0 : aRemoveWatchButton.disposeAndClear();
1664 0 : aHeaderBar.disposeAndClear();
1665 0 : aTreeListBox.disposeAndClear();
1666 0 : if (!IsDisposed())
1667 0 : GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1668 0 : DockingWindow::dispose();
1669 0 : }
1670 :
1671 0 : void WatchWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
1672 : {
1673 0 : rRenderContext.DrawText(Point(DWBORDER, 7), aWatchStr);
1674 0 : lcl_DrawIDEWindowFrame(this, rRenderContext);
1675 0 : }
1676 :
1677 0 : void WatchWindow::Resize()
1678 : {
1679 0 : Size aSz = GetOutputSizePixel();
1680 0 : Size aBoxSz( aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER );
1681 :
1682 0 : if ( aBoxSz.Width() < 4 )
1683 0 : aBoxSz.Width() = 0;
1684 0 : if ( aBoxSz.Height() < 4 )
1685 0 : aBoxSz.Height() = 0;
1686 :
1687 0 : aBoxSz.Height() -= nHeaderBarHeight;
1688 0 : aTreeListBox->SetSizePixel( aBoxSz );
1689 0 : aTreeListBox->GetHScroll()->SetPageSize( aTreeListBox->GetHScroll()->GetVisibleSize() );
1690 :
1691 0 : aBoxSz.Height() = nHeaderBarHeight;
1692 0 : aHeaderBar->SetSizePixel( aBoxSz );
1693 :
1694 0 : Invalidate();
1695 0 : }
1696 :
1697 0 : struct WatchItem
1698 : {
1699 : OUString maName;
1700 : OUString maDisplayName;
1701 : SbxObjectRef mpObject;
1702 : std::vector<OUString> maMemberList;
1703 :
1704 : SbxDimArrayRef mpArray;
1705 : int nDimLevel; // 0 = Root
1706 : int nDimCount;
1707 : std::vector<short> vIndices;
1708 :
1709 : WatchItem* mpArrayParentItem;
1710 :
1711 0 : explicit WatchItem (OUString const& rName):
1712 : maName(rName),
1713 : nDimLevel(0),
1714 : nDimCount(0),
1715 0 : mpArrayParentItem(0)
1716 0 : { }
1717 :
1718 0 : void clearWatchItem ()
1719 : {
1720 0 : maMemberList.clear();
1721 0 : }
1722 :
1723 : WatchItem* GetRootItem();
1724 : SbxDimArray* GetRootArray();
1725 : };
1726 :
1727 0 : WatchItem* WatchItem::GetRootItem()
1728 : {
1729 0 : WatchItem* pItem = mpArrayParentItem;
1730 0 : while( pItem )
1731 : {
1732 0 : if( pItem->mpArray.Is() )
1733 0 : break;
1734 0 : pItem = pItem->mpArrayParentItem;
1735 : }
1736 0 : return pItem;
1737 : }
1738 :
1739 0 : SbxDimArray* WatchItem::GetRootArray()
1740 : {
1741 0 : WatchItem* pRootItem = GetRootItem();
1742 0 : SbxDimArray* pRet = NULL;
1743 0 : if( pRootItem )
1744 0 : pRet = pRootItem->mpArray;
1745 0 : return pRet;
1746 : }
1747 :
1748 0 : void WatchWindow::AddWatch( const OUString& rVName )
1749 : {
1750 0 : OUString aVar, aIndex;
1751 0 : lcl_SeparateNameAndIndex( rVName, aVar, aIndex );
1752 0 : WatchItem* pWatchItem = new WatchItem(aVar);
1753 :
1754 0 : OUString aWatchStr_( aVar );
1755 0 : aWatchStr_ += "\t\t";
1756 0 : SvTreeListEntry* pNewEntry = aTreeListBox->InsertEntry( aWatchStr_, 0, true, TREELIST_APPEND );
1757 0 : pNewEntry->SetUserData( pWatchItem );
1758 :
1759 0 : aTreeListBox->Select(pNewEntry, true);
1760 0 : aTreeListBox->MakeVisible(pNewEntry);
1761 0 : aRemoveWatchButton->Enable();
1762 :
1763 0 : UpdateWatches();
1764 0 : }
1765 :
1766 0 : bool WatchWindow::RemoveSelectedWatch()
1767 : {
1768 0 : SvTreeListEntry* pEntry = aTreeListBox->GetCurEntry();
1769 0 : if ( pEntry )
1770 : {
1771 0 : aTreeListBox->GetModel()->Remove( pEntry );
1772 0 : pEntry = aTreeListBox->GetCurEntry();
1773 0 : if ( pEntry )
1774 0 : aXEdit->SetText( static_cast<WatchItem*>(pEntry->GetUserData())->maName );
1775 : else
1776 0 : aXEdit->SetText( OUString() );
1777 0 : if ( !aTreeListBox->GetEntryCount() )
1778 0 : aRemoveWatchButton->Disable();
1779 0 : return true;
1780 : }
1781 : else
1782 0 : return false;
1783 : }
1784 :
1785 :
1786 0 : IMPL_LINK( WatchWindow, ButtonHdl, ImageButton *, pButton )
1787 : {
1788 0 : if (pButton == aRemoveWatchButton.get())
1789 0 : if (SfxDispatcher* pDispatcher = GetDispatcher())
1790 0 : pDispatcher->Execute(SID_BASICIDE_REMOVEWATCH);
1791 0 : return 0;
1792 : }
1793 :
1794 0 : IMPL_LINK_NOARG(WatchWindow, TreeListHdl)
1795 : {
1796 0 : SvTreeListEntry* pCurEntry = aTreeListBox->GetCurEntry();
1797 0 : if ( pCurEntry && pCurEntry->GetUserData() )
1798 0 : aXEdit->SetText( static_cast<WatchItem*>(pCurEntry->GetUserData())->maName );
1799 :
1800 0 : return 0;
1801 : }
1802 :
1803 0 : IMPL_LINK( WatchWindow, implEndDragHdl, HeaderBar *, pBar )
1804 : {
1805 : (void)pBar;
1806 :
1807 0 : const sal_Int32 TAB_WIDTH_MIN = 10;
1808 : sal_Int32 nMaxWidth =
1809 0 : aHeaderBar->GetSizePixel().getWidth() - 2 * TAB_WIDTH_MIN;
1810 :
1811 0 : sal_Int32 nVariableWith = aHeaderBar->GetItemSize( ITEM_ID_VARIABLE );
1812 0 : if( nVariableWith < TAB_WIDTH_MIN )
1813 0 : aHeaderBar->SetItemSize( ITEM_ID_VARIABLE, TAB_WIDTH_MIN );
1814 0 : else if( nVariableWith > nMaxWidth )
1815 0 : aHeaderBar->SetItemSize( ITEM_ID_VARIABLE, nMaxWidth );
1816 :
1817 0 : sal_Int32 nValueWith = aHeaderBar->GetItemSize( ITEM_ID_VALUE );
1818 0 : if( nValueWith < TAB_WIDTH_MIN )
1819 0 : aHeaderBar->SetItemSize( ITEM_ID_VALUE, TAB_WIDTH_MIN );
1820 0 : else if( nValueWith > nMaxWidth )
1821 0 : aHeaderBar->SetItemSize( ITEM_ID_VALUE, nMaxWidth );
1822 :
1823 0 : if (aHeaderBar->GetItemSize( ITEM_ID_TYPE ) < TAB_WIDTH_MIN)
1824 0 : aHeaderBar->SetItemSize( ITEM_ID_TYPE, TAB_WIDTH_MIN );
1825 :
1826 0 : sal_Int32 nPos = 0;
1827 0 : sal_uInt16 nTabs = aHeaderBar->GetItemCount();
1828 0 : for( sal_uInt16 i = 1 ; i < nTabs ; ++i )
1829 : {
1830 0 : nPos += aHeaderBar->GetItemSize( i );
1831 0 : aTreeListBox->SetTab( i, nPos, MAP_PIXEL );
1832 : }
1833 0 : return 0;
1834 : }
1835 :
1836 0 : IMPL_LINK_TYPED( WatchWindow, EditAccHdl, Accelerator *, pAcc, void )
1837 : {
1838 0 : switch ( pAcc->GetCurKeyCode().GetCode() )
1839 : {
1840 : case KEY_RETURN:
1841 : {
1842 0 : OUString aCurText( aXEdit->GetText() );
1843 0 : if ( !aCurText.isEmpty() )
1844 : {
1845 0 : AddWatch( aCurText );
1846 0 : aXEdit->SetSelection( Selection( 0, 0xFFFF ) );
1847 0 : }
1848 : }
1849 0 : break;
1850 : case KEY_ESCAPE:
1851 : {
1852 0 : aXEdit->SetText( OUString() );
1853 : }
1854 0 : break;
1855 : }
1856 0 : }
1857 :
1858 0 : void WatchWindow::UpdateWatches( bool bBasicStopped )
1859 : {
1860 0 : aTreeListBox->UpdateWatches( bBasicStopped );
1861 0 : }
1862 :
1863 :
1864 :
1865 : // StackWindow
1866 :
1867 :
1868 :
1869 0 : StackWindow::StackWindow (Layout* pParent) :
1870 : DockingWindow(pParent),
1871 : aTreeListBox( VclPtr<SvTreeListBox>::Create(this, WB_BORDER | WB_3DLOOK | WB_HSCROLL | WB_TABSTOP) ),
1872 0 : aStackStr( IDEResId( RID_STR_STACK ) )
1873 : {
1874 0 : aTreeListBox->SetHelpId(HID_BASICIDE_STACKWINDOW_LIST);
1875 0 : aTreeListBox->SetAccessibleName(IDEResId(RID_STR_STACKNAME).toString());
1876 0 : aTreeListBox->SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight ) );
1877 0 : aTreeListBox->SetHighlightRange();
1878 0 : aTreeListBox->SetSelectionMode( NO_SELECTION );
1879 0 : aTreeListBox->InsertEntry( OUString(), 0, false, TREELIST_APPEND );
1880 0 : aTreeListBox->Show();
1881 :
1882 0 : SetText(IDEResId(RID_STR_STACKNAME).toString());
1883 :
1884 0 : SetHelpId( HID_BASICIDE_STACKWINDOW );
1885 :
1886 : // make stack window keyboard accessible
1887 0 : GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1888 0 : }
1889 :
1890 :
1891 :
1892 0 : StackWindow::~StackWindow()
1893 : {
1894 0 : disposeOnce();
1895 0 : }
1896 :
1897 0 : void StackWindow::dispose()
1898 : {
1899 0 : if (!IsDisposed())
1900 0 : GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1901 0 : aTreeListBox.disposeAndClear();
1902 0 : DockingWindow::dispose();
1903 0 : }
1904 :
1905 0 : void StackWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
1906 : {
1907 0 : rRenderContext.DrawText(Point(DWBORDER, 7), aStackStr);
1908 0 : lcl_DrawIDEWindowFrame(this, rRenderContext);
1909 0 : }
1910 :
1911 0 : void StackWindow::Resize()
1912 : {
1913 0 : Size aSz = GetOutputSizePixel();
1914 0 : Size aBoxSz(aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER);
1915 :
1916 0 : if ( aBoxSz.Width() < 4 )
1917 0 : aBoxSz.Width() = 0;
1918 0 : if ( aBoxSz.Height() < 4 )
1919 0 : aBoxSz.Height() = 0;
1920 :
1921 0 : aTreeListBox->SetSizePixel( aBoxSz );
1922 :
1923 0 : Invalidate();
1924 0 : }
1925 :
1926 0 : void StackWindow::UpdateCalls()
1927 : {
1928 0 : aTreeListBox->SetUpdateMode(false);
1929 0 : aTreeListBox->Clear();
1930 :
1931 0 : if (StarBASIC::IsRunning())
1932 : {
1933 0 : SbxError eOld = SbxBase::GetError();
1934 0 : aTreeListBox->SetSelectionMode( SINGLE_SELECTION );
1935 :
1936 0 : sal_Int32 nScope = 0;
1937 0 : SbMethod* pMethod = StarBASIC::GetActiveMethod( nScope );
1938 0 : while ( pMethod )
1939 : {
1940 0 : OUString aEntry( OUString::number(nScope ));
1941 0 : if ( aEntry.getLength() < 2 )
1942 0 : aEntry = " " + aEntry;
1943 0 : aEntry += ": " + pMethod->GetName();
1944 0 : SbxArray* pParams = pMethod->GetParameters();
1945 0 : SbxInfo* pInfo = pMethod->GetInfo();
1946 0 : if ( pParams )
1947 : {
1948 0 : aEntry += "(";
1949 : // 0 is the sub's name...
1950 0 : for ( sal_uInt16 nParam = 1; nParam < pParams->Count(); nParam++ )
1951 : {
1952 0 : SbxVariable* pVar = pParams->Get( nParam );
1953 : assert(pVar && "Parameter?!");
1954 0 : if ( !pVar->GetName().isEmpty() )
1955 : {
1956 0 : aEntry += pVar->GetName();
1957 : }
1958 0 : else if ( pInfo )
1959 : {
1960 0 : const SbxParamInfo* pParam = pInfo->GetParam( nParam );
1961 0 : if ( pParam )
1962 : {
1963 0 : aEntry += pParam->aName;
1964 : }
1965 : }
1966 0 : aEntry += "=";
1967 0 : SbxDataType eType = pVar->GetType();
1968 0 : if( eType & SbxARRAY )
1969 : {
1970 0 : aEntry += "..." ;
1971 : }
1972 0 : else if( eType != SbxOBJECT )
1973 : {
1974 0 : aEntry += pVar->GetOUString();
1975 : }
1976 0 : if ( nParam < ( pParams->Count() - 1 ) )
1977 : {
1978 0 : aEntry += ", ";
1979 : }
1980 : }
1981 0 : aEntry += ")";
1982 : }
1983 0 : aTreeListBox->InsertEntry( aEntry, 0, false, TREELIST_APPEND );
1984 0 : nScope++;
1985 0 : pMethod = StarBASIC::GetActiveMethod( nScope );
1986 0 : }
1987 :
1988 0 : SbxBase::ResetError();
1989 0 : if( eOld != SbxERR_OK )
1990 0 : SbxBase::SetError( eOld );
1991 : }
1992 : else
1993 : {
1994 0 : aTreeListBox->SetSelectionMode( NO_SELECTION );
1995 0 : aTreeListBox->InsertEntry( OUString(), 0, false, TREELIST_APPEND );
1996 : }
1997 :
1998 0 : aTreeListBox->SetUpdateMode(true);
1999 0 : }
2000 :
2001 0 : ComplexEditorWindow::ComplexEditorWindow( ModulWindow* pParent ) :
2002 : Window( pParent, WB_3DLOOK | WB_CLIPCHILDREN ),
2003 : aBrkWindow(VclPtr<BreakPointWindow>::Create(this, pParent)),
2004 : aLineNumberWindow(VclPtr<LineNumberWindow>::Create(this, pParent)),
2005 : aEdtWindow(VclPtr<EditorWindow>::Create(this, pParent)),
2006 0 : aEWVScrollBar( VclPtr<ScrollBar>::Create(this, WB_VSCROLL | WB_DRAG) )
2007 : {
2008 0 : aEdtWindow->Show();
2009 0 : aBrkWindow->Show();
2010 :
2011 0 : aEWVScrollBar->SetLineSize(nScrollLine);
2012 0 : aEWVScrollBar->SetPageSize(nScrollPage);
2013 0 : aEWVScrollBar->SetScrollHdl( LINK( this, ComplexEditorWindow, ScrollHdl ) );
2014 0 : aEWVScrollBar->Show();
2015 0 : }
2016 :
2017 0 : ComplexEditorWindow::~ComplexEditorWindow()
2018 : {
2019 0 : disposeOnce();
2020 0 : }
2021 :
2022 0 : void ComplexEditorWindow::dispose()
2023 : {
2024 0 : aBrkWindow.disposeAndClear();
2025 0 : aLineNumberWindow.disposeAndClear();
2026 0 : aEdtWindow.disposeAndClear();
2027 0 : aEWVScrollBar.disposeAndClear();
2028 0 : vcl::Window::dispose();
2029 0 : }
2030 :
2031 0 : void ComplexEditorWindow::Resize()
2032 : {
2033 0 : Size aOutSz = GetOutputSizePixel();
2034 0 : Size aSz(aOutSz);
2035 0 : aSz.Width() -= 2*DWBORDER;
2036 0 : aSz.Height() -= 2*DWBORDER;
2037 0 : long nBrkWidth = 20;
2038 0 : long nSBWidth = aEWVScrollBar->GetSizePixel().Width();
2039 :
2040 0 : Size aBrkSz(nBrkWidth, aSz.Height());
2041 :
2042 0 : Size aLnSz(aLineNumberWindow->GetWidth(), aSz.Height());
2043 :
2044 0 : if (aLineNumberWindow->IsVisible())
2045 : {
2046 0 : aBrkWindow->SetPosSizePixel( Point( DWBORDER, DWBORDER ), aBrkSz );
2047 0 : aLineNumberWindow->SetPosSizePixel(Point(DWBORDER + aBrkSz.Width() - 1, DWBORDER), aLnSz);
2048 0 : Size aEWSz(aSz.Width() - nBrkWidth - aLineNumberWindow->GetWidth() - nSBWidth + 2, aSz.Height());
2049 0 : aEdtWindow->SetPosSizePixel( Point( DWBORDER + aBrkSz.Width() + aLnSz.Width() - 1, DWBORDER ), aEWSz );
2050 : }
2051 : else
2052 : {
2053 0 : aBrkWindow->SetPosSizePixel( Point( DWBORDER, DWBORDER ), aBrkSz );
2054 0 : Size aEWSz(aSz.Width() - nBrkWidth - nSBWidth + 2, aSz.Height());
2055 0 : aEdtWindow->SetPosSizePixel(Point(DWBORDER + aBrkSz.Width() - 1, DWBORDER), aEWSz);
2056 : }
2057 :
2058 0 : aEWVScrollBar->SetPosSizePixel( Point( aOutSz.Width() - DWBORDER - nSBWidth, DWBORDER ), Size( nSBWidth, aSz.Height() ) );
2059 0 : }
2060 :
2061 0 : IMPL_LINK(ComplexEditorWindow, ScrollHdl, ScrollBar *, pCurScrollBar )
2062 : {
2063 0 : if (aEdtWindow->GetEditView())
2064 : {
2065 : DBG_ASSERT( pCurScrollBar == aEWVScrollBar.get(), "Wer scrollt hier ?" );
2066 0 : long nDiff = aEdtWindow->GetEditView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
2067 0 : aEdtWindow->GetEditView()->Scroll( 0, nDiff );
2068 0 : aBrkWindow->DoScroll( 0, nDiff );
2069 0 : aLineNumberWindow->DoScroll(0, nDiff);
2070 0 : aEdtWindow->GetEditView()->ShowCursor(false, true);
2071 0 : pCurScrollBar->SetThumbPos( aEdtWindow->GetEditView()->GetStartDocPos().Y() );
2072 : }
2073 :
2074 0 : return 0;
2075 : }
2076 :
2077 0 : void ComplexEditorWindow::DataChanged(DataChangedEvent const & rDCEvt)
2078 : {
2079 0 : Window::DataChanged(rDCEvt);
2080 0 : if (rDCEvt.GetType() == DataChangedEventType::SETTINGS
2081 0 : && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))
2082 : {
2083 0 : Color aColor(GetSettings().GetStyleSettings().GetFaceColor());
2084 0 : const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
2085 0 : if (!pOldSettings || aColor != pOldSettings->GetStyleSettings().GetFaceColor())
2086 : {
2087 0 : SetBackground(Wallpaper(aColor));
2088 0 : Invalidate();
2089 : }
2090 : }
2091 0 : }
2092 :
2093 0 : void ComplexEditorWindow::SetLineNumberDisplay(bool b)
2094 : {
2095 0 : aLineNumberWindow->Show(b);
2096 0 : Resize();
2097 0 : }
2098 :
2099 : uno::Reference< awt::XWindowPeer >
2100 0 : EditorWindow::GetComponentInterface(bool bCreate)
2101 : {
2102 : uno::Reference< awt::XWindowPeer > xPeer(
2103 0 : Window::GetComponentInterface(false));
2104 0 : if (!xPeer.is() && bCreate)
2105 : {
2106 : // Make sure edit engine and view are available:
2107 0 : if (!pEditEngine)
2108 0 : CreateEditEngine();
2109 :
2110 0 : xPeer = svt::createTextWindowPeer(*GetEditView());
2111 0 : SetComponentInterface(xPeer);
2112 : }
2113 0 : return xPeer;
2114 : }
2115 :
2116 :
2117 :
2118 : // WatchTreeListBox
2119 :
2120 :
2121 :
2122 0 : WatchTreeListBox::WatchTreeListBox( vcl::Window* pParent, WinBits nWinBits )
2123 0 : : SvHeaderTabListBox( pParent, nWinBits )
2124 0 : {}
2125 :
2126 0 : WatchTreeListBox::~WatchTreeListBox()
2127 : {
2128 0 : disposeOnce();
2129 0 : }
2130 :
2131 0 : void WatchTreeListBox::dispose()
2132 : {
2133 : // Destroy user data
2134 0 : SvTreeListEntry* pEntry = First();
2135 0 : while ( pEntry )
2136 : {
2137 0 : delete static_cast<WatchItem*>(pEntry->GetUserData());
2138 0 : pEntry->SetUserData(NULL);
2139 0 : pEntry = Next( pEntry );
2140 : }
2141 0 : SvHeaderTabListBox::dispose();
2142 0 : }
2143 :
2144 0 : void WatchTreeListBox::SetTabs()
2145 : {
2146 0 : SvHeaderTabListBox::SetTabs();
2147 0 : sal_uInt16 nTabCount_ = aTabs.size();
2148 0 : for( sal_uInt16 i = 0 ; i < nTabCount_ ; i++ )
2149 : {
2150 0 : SvLBoxTab* pTab = aTabs[i];
2151 0 : if( i == 2 )
2152 0 : pTab->nFlags |= SvLBoxTabFlags::EDITABLE;
2153 : else
2154 0 : pTab->nFlags &= ~SvLBoxTabFlags::EDITABLE;
2155 : }
2156 0 : }
2157 :
2158 0 : void WatchTreeListBox::RequestingChildren( SvTreeListEntry * pParent )
2159 : {
2160 0 : if( !StarBASIC::IsRunning() )
2161 0 : return;
2162 :
2163 0 : if( GetChildCount( pParent ) > 0 )
2164 0 : return;
2165 :
2166 0 : SvTreeListEntry* pEntry = pParent;
2167 0 : WatchItem* pItem = static_cast<WatchItem*>(pEntry->GetUserData());
2168 :
2169 0 : SbxDimArray* pArray = pItem->mpArray;
2170 0 : SbxDimArray* pRootArray = pItem->GetRootArray();
2171 0 : bool bArrayIsRootArray = false;
2172 0 : if( !pArray && pRootArray )
2173 : {
2174 0 : pArray = pRootArray;
2175 0 : bArrayIsRootArray = true;
2176 : }
2177 :
2178 0 : SbxObject* pObj = pItem->mpObject;
2179 0 : if( pObj )
2180 : {
2181 0 : createAllObjectProperties( pObj );
2182 0 : SbxArray* pProps = pObj->GetProperties();
2183 0 : sal_uInt16 nPropCount = pProps->Count();
2184 0 : if ( nPropCount >= 3 &&
2185 0 : pProps->Get( nPropCount -1 )->GetName().equalsIgnoreAsciiCase( "Dbg_Methods" ) &&
2186 0 : pProps->Get( nPropCount -2 )->GetName().equalsIgnoreAsciiCase( "Dbg_Properties" ) &&
2187 0 : pProps->Get( nPropCount -3 )->GetName().equalsIgnoreAsciiCase( "Dbg_SupportedInterfaces" ) )
2188 : {
2189 0 : nPropCount -= 3;
2190 : }
2191 0 : pItem->maMemberList.reserve(nPropCount);
2192 :
2193 0 : for( sal_uInt16 i = 0 ; i < nPropCount ; ++i )
2194 : {
2195 0 : SbxVariable* pVar = pProps->Get( i );
2196 :
2197 0 : pItem->maMemberList.push_back(pVar->GetName());
2198 0 : OUString const& rName = pItem->maMemberList.back();
2199 0 : SvTreeListEntry* pChildEntry = SvTreeListBox::InsertEntry( rName, pEntry );
2200 0 : pChildEntry->SetUserData(new WatchItem(rName));
2201 : }
2202 0 : if( nPropCount > 0 )
2203 : {
2204 0 : UpdateWatches();
2205 : }
2206 : }
2207 0 : else if( pArray )
2208 : {
2209 0 : sal_uInt16 nElementCount = 0;
2210 :
2211 : // Loop through indices of current level
2212 0 : int nParentLevel = bArrayIsRootArray ? pItem->nDimLevel : 0;
2213 0 : int nThisLevel = nParentLevel + 1;
2214 : sal_Int32 nMin, nMax;
2215 0 : pArray->GetDim32( nThisLevel, nMin, nMax );
2216 0 : for( sal_Int32 i = nMin ; i <= nMax ; i++ )
2217 : {
2218 0 : WatchItem* pChildItem = new WatchItem(pItem->maName);
2219 :
2220 : // Copy data and create name
2221 :
2222 0 : OUString aIndexStr = "(";
2223 0 : pChildItem->mpArrayParentItem = pItem;
2224 0 : pChildItem->nDimLevel = nThisLevel;
2225 0 : pChildItem->nDimCount = pItem->nDimCount;
2226 0 : pChildItem->vIndices.resize(pChildItem->nDimCount);
2227 : sal_Int32 j;
2228 0 : for( j = 0 ; j < nParentLevel ; j++ )
2229 : {
2230 0 : short n = pChildItem->vIndices[j] = pItem->vIndices[j];
2231 0 : aIndexStr += OUString::number( n ) + ",";
2232 : }
2233 0 : pChildItem->vIndices[nParentLevel] = sal::static_int_cast<short>( i );
2234 0 : aIndexStr += OUString::number( i ) + ")";
2235 :
2236 0 : OUString aDisplayName;
2237 0 : WatchItem* pArrayRootItem = pChildItem->GetRootItem();
2238 0 : if( pArrayRootItem && pArrayRootItem->mpArrayParentItem )
2239 0 : aDisplayName = pItem->maDisplayName;
2240 : else
2241 0 : aDisplayName = pItem->maName;
2242 0 : aDisplayName += aIndexStr;
2243 0 : pChildItem->maDisplayName = aDisplayName;
2244 :
2245 0 : SvTreeListEntry* pChildEntry = SvTreeListBox::InsertEntry( aDisplayName, pEntry );
2246 0 : nElementCount++;
2247 0 : pChildEntry->SetUserData( pChildItem );
2248 0 : }
2249 0 : if( nElementCount > 0 )
2250 : {
2251 0 : UpdateWatches();
2252 : }
2253 : }
2254 : }
2255 :
2256 0 : SbxBase* WatchTreeListBox::ImplGetSBXForEntry( SvTreeListEntry* pEntry, bool& rbArrayElement )
2257 : {
2258 0 : SbxBase* pSBX = NULL;
2259 0 : rbArrayElement = false;
2260 :
2261 0 : WatchItem* pItem = static_cast<WatchItem*>(pEntry->GetUserData());
2262 0 : OUString aVName( pItem->maName );
2263 :
2264 0 : SvTreeListEntry* pParentEntry = GetParent( pEntry );
2265 0 : WatchItem* pParentItem = pParentEntry ? static_cast<WatchItem*>(pParentEntry->GetUserData()) : NULL;
2266 0 : if( pParentItem )
2267 : {
2268 0 : SbxObject* pObj = pParentItem->mpObject;
2269 : SbxDimArray* pArray;
2270 0 : if( pObj )
2271 : {
2272 0 : pSBX = pObj->Find( aVName, SbxCLASS_DONTCARE );
2273 0 : if (SbxVariable const* pVar = IsSbxVariable(pSBX))
2274 : {
2275 : // Force getting value
2276 0 : SbxValues aRes;
2277 0 : aRes.eType = SbxVOID;
2278 0 : pVar->Get( aRes );
2279 : }
2280 : }
2281 : // Array?
2282 0 : else if( (pArray = pItem->GetRootArray()) != NULL )
2283 : {
2284 0 : rbArrayElement = true;
2285 0 : if( pParentItem->nDimLevel + 1 == pParentItem->nDimCount )
2286 0 : pSBX = pArray->Get(pItem->vIndices.empty() ? 0 : &*pItem->vIndices.begin());
2287 : }
2288 : }
2289 : else
2290 : {
2291 0 : pSBX = StarBASIC::FindSBXInCurrentScope( aVName );
2292 : }
2293 0 : return pSBX;
2294 : }
2295 :
2296 0 : bool WatchTreeListBox::EditingEntry( SvTreeListEntry* pEntry, Selection& )
2297 : {
2298 0 : WatchItem* pItem = static_cast<WatchItem*>(pEntry->GetUserData());
2299 :
2300 0 : bool bEdit = false;
2301 0 : if ( StarBASIC::IsRunning() && StarBASIC::GetActiveMethod() && !SbxBase::IsError() )
2302 : {
2303 : // No out of scope entries
2304 : bool bArrayElement;
2305 0 : SbxBase* pSbx = ImplGetSBXForEntry( pEntry, bArrayElement );
2306 0 : if (IsSbxVariable(pSbx) || bArrayElement)
2307 : {
2308 : // Accept no objects and only end nodes of arrays for editing
2309 0 : if( !pItem->mpObject && (pItem->mpArray == NULL || pItem->nDimLevel == pItem->nDimCount) )
2310 : {
2311 0 : aEditingRes = SvHeaderTabListBox::GetEntryText( pEntry, ITEM_ID_VALUE-1 );
2312 0 : aEditingRes = comphelper::string::strip(aEditingRes, ' ');
2313 0 : bEdit = true;
2314 : }
2315 : }
2316 : }
2317 :
2318 0 : return bEdit;
2319 : }
2320 :
2321 0 : bool WatchTreeListBox::EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText )
2322 : {
2323 0 : OUString aResult = comphelper::string::strip(rNewText, ' ');
2324 :
2325 0 : sal_uInt16 nResultLen = aResult.getLength();
2326 0 : sal_Unicode cFirst = aResult[0];
2327 0 : sal_Unicode cLast = aResult[ nResultLen - 1 ];
2328 0 : if( cFirst == '\"' && cLast == '\"' )
2329 0 : aResult = aResult.copy( 1, nResultLen - 2 );
2330 :
2331 0 : return aResult != aEditingRes && ImplBasicEntryEdited(pEntry, aResult);
2332 : }
2333 :
2334 0 : bool WatchTreeListBox::ImplBasicEntryEdited( SvTreeListEntry* pEntry, const OUString& rResult )
2335 : {
2336 : bool bArrayElement;
2337 0 : SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
2338 :
2339 0 : if (SbxVariable* pVar = IsSbxVariable(pSBX))
2340 : {
2341 0 : SbxDataType eType = pVar->GetType();
2342 0 : if ( (sal_uInt8)eType != (sal_uInt8)SbxOBJECT
2343 0 : && ( eType & SbxARRAY ) == 0 )
2344 : {
2345 : // If the type is variable, the conversion of the SBX does not matter,
2346 : // else the string is converted.
2347 0 : pVar->PutStringExt( rResult );
2348 : }
2349 : }
2350 :
2351 0 : if ( SbxBase::IsError() )
2352 : {
2353 0 : SbxBase::ResetError();
2354 : }
2355 :
2356 0 : UpdateWatches();
2357 :
2358 : // The text should never be taken/copied 1:1,
2359 : // as the UpdateWatches will be lost
2360 0 : return false;
2361 : }
2362 :
2363 :
2364 : namespace
2365 : {
2366 :
2367 0 : void implCollapseModifiedObjectEntry( SvTreeListEntry* pParent, WatchTreeListBox* pThis )
2368 : {
2369 0 : pThis->Collapse( pParent );
2370 :
2371 0 : SvTreeList* pModel = pThis->GetModel();
2372 : SvTreeListEntry* pDeleteEntry;
2373 0 : while( (pDeleteEntry = pThis->SvTreeListBox::GetEntry( pParent, 0 )) != NULL )
2374 : {
2375 0 : implCollapseModifiedObjectEntry( pDeleteEntry, pThis );
2376 :
2377 0 : delete static_cast<WatchItem*>(pDeleteEntry->GetUserData());
2378 0 : pModel->Remove( pDeleteEntry );
2379 : }
2380 0 : }
2381 :
2382 0 : OUString implCreateTypeStringForDimArray( WatchItem* pItem, SbxDataType eType )
2383 : {
2384 0 : OUString aRetStr = getBasicTypeName( eType );
2385 :
2386 0 : SbxDimArray* pArray = pItem->mpArray;
2387 0 : if( !pArray )
2388 0 : pArray = pItem->GetRootArray();
2389 0 : if( pArray )
2390 : {
2391 0 : int nDimLevel = pItem->nDimLevel;
2392 0 : int nDims = pItem->nDimCount;
2393 0 : if( nDimLevel < nDims )
2394 : {
2395 0 : aRetStr += "(";
2396 0 : for( int i = nDimLevel ; i < nDims ; i++ )
2397 : {
2398 : short nMin, nMax;
2399 0 : pArray->GetDim( sal::static_int_cast<short>( i+1 ), nMin, nMax );
2400 0 : aRetStr += OUString::number(nMin) + " to " + OUString::number(nMax);
2401 0 : if( i < nDims - 1 )
2402 0 : aRetStr += ", ";
2403 : }
2404 0 : aRetStr += ")";
2405 : }
2406 : }
2407 0 : return aRetStr;
2408 : }
2409 :
2410 0 : void implEnableChildren( SvTreeListEntry* pEntry, bool bEnable )
2411 : {
2412 0 : if( bEnable )
2413 : {
2414 : pEntry->SetFlags(
2415 0 : (pEntry->GetFlags() & ~SvTLEntryFlags(SvTLEntryFlags::NO_NODEBMP | SvTLEntryFlags::HAD_CHILDREN))
2416 0 : | SvTLEntryFlags::CHILDREN_ON_DEMAND );
2417 : }
2418 : else
2419 : {
2420 0 : pEntry->SetFlags( pEntry->GetFlags() & ~SvTLEntryFlags::CHILDREN_ON_DEMAND );
2421 : }
2422 0 : }
2423 :
2424 : } // namespace
2425 :
2426 0 : void WatchTreeListBox::UpdateWatches( bool bBasicStopped )
2427 : {
2428 0 : SbMethod* pCurMethod = StarBASIC::GetActiveMethod();
2429 :
2430 0 : SbxError eOld = SbxBase::GetError();
2431 0 : setBasicWatchMode( true );
2432 :
2433 0 : SvTreeListEntry* pEntry = First();
2434 0 : while ( pEntry )
2435 : {
2436 0 : WatchItem* pItem = static_cast<WatchItem*>(pEntry->GetUserData());
2437 : DBG_ASSERT( !pItem->maName.isEmpty(), "Var? - Must not be empty!" );
2438 0 : OUString aWatchStr;
2439 0 : OUString aTypeStr;
2440 0 : if ( pCurMethod )
2441 : {
2442 : bool bArrayElement;
2443 0 : SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
2444 :
2445 : // Array? If no end node create type string
2446 0 : if( bArrayElement && pItem->nDimLevel < pItem->nDimCount )
2447 : {
2448 0 : SbxDimArray* pRootArray = pItem->GetRootArray();
2449 0 : SbxDataType eType = pRootArray->GetType();
2450 0 : aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
2451 0 : implEnableChildren( pEntry, true );
2452 : }
2453 :
2454 0 : bool bCollapse = false;
2455 0 : if (SbxVariable const* pVar = IsSbxVariable(pSBX))
2456 : {
2457 : // extra treatment of arrays
2458 0 : SbxDataType eType = pVar->GetType();
2459 0 : if ( eType & SbxARRAY )
2460 : {
2461 : // consider multidimensinal arrays!
2462 0 : if (SbxDimArray* pNewArray = dynamic_cast<SbxDimArray*>(pVar->GetObject()))
2463 : {
2464 0 : SbxDimArray* pOldArray = pItem->mpArray;
2465 :
2466 0 : bool bArrayChanged = false;
2467 0 : if( pNewArray != NULL && pOldArray != NULL )
2468 : {
2469 : // Compare Array dimensions to see if array has changed
2470 : // Can be a copy, so comparing pointers does not work
2471 0 : sal_uInt16 nOldDims = pOldArray->GetDims();
2472 0 : sal_uInt16 nNewDims = pNewArray->GetDims();
2473 0 : if( nOldDims != nNewDims )
2474 : {
2475 0 : bArrayChanged = true;
2476 : }
2477 : else
2478 : {
2479 0 : for( int i = 0 ; i < nOldDims ; i++ )
2480 : {
2481 : short nOldMin, nOldMax;
2482 : short nNewMin, nNewMax;
2483 :
2484 0 : pOldArray->GetDim( sal::static_int_cast<short>( i+1 ), nOldMin, nOldMax );
2485 0 : pNewArray->GetDim( sal::static_int_cast<short>( i+1 ), nNewMin, nNewMax );
2486 0 : if( nOldMin != nNewMin || nOldMax != nNewMax )
2487 : {
2488 0 : bArrayChanged = true;
2489 0 : break;
2490 : }
2491 : }
2492 0 : }
2493 : }
2494 0 : else if( pNewArray == NULL || pOldArray == NULL )
2495 : {
2496 0 : bArrayChanged = true;
2497 : }
2498 0 : if( pNewArray )
2499 : {
2500 0 : implEnableChildren( pEntry, true );
2501 : }
2502 : // #i37227 Clear always and replace array
2503 0 : if( pNewArray != pOldArray )
2504 : {
2505 0 : pItem->clearWatchItem();
2506 0 : if( pNewArray )
2507 : {
2508 0 : implEnableChildren( pEntry, true );
2509 :
2510 0 : pItem->mpArray = pNewArray;
2511 0 : sal_uInt16 nDims = pNewArray->GetDims();
2512 0 : pItem->nDimLevel = 0;
2513 0 : pItem->nDimCount = nDims;
2514 : }
2515 : }
2516 0 : if( bArrayChanged && pOldArray != NULL )
2517 : {
2518 0 : bCollapse = true;
2519 : }
2520 0 : aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
2521 : }
2522 : else
2523 : {
2524 0 : aWatchStr += "<?>";
2525 : }
2526 : }
2527 0 : else if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
2528 : {
2529 0 : if (SbxObject* pObj = dynamic_cast<SbxObject*>(pVar->GetObject()))
2530 : {
2531 0 : if (pItem->mpObject && !pItem->maMemberList.empty())
2532 : {
2533 0 : bool bObjChanged = false; // Check if member list has changed
2534 0 : SbxArray* pProps = pObj->GetProperties();
2535 0 : sal_uInt16 nPropCount = pProps->Count();
2536 0 : for( sal_uInt16 i = 0 ; i < nPropCount - 3 ; i++ )
2537 : {
2538 0 : SbxVariable* pVar_ = pProps->Get( i );
2539 0 : OUString aName( pVar_->GetName() );
2540 0 : if( pItem->maMemberList[i] != aName )
2541 : {
2542 0 : bObjChanged = true;
2543 0 : break;
2544 : }
2545 0 : }
2546 0 : if( bObjChanged )
2547 : {
2548 0 : bCollapse = true;
2549 : }
2550 : }
2551 :
2552 0 : pItem->mpObject = pObj;
2553 0 : implEnableChildren( pEntry, true );
2554 0 : aTypeStr = getBasicObjectTypeName( pObj );
2555 : }
2556 : else
2557 : {
2558 0 : aWatchStr = "Null";
2559 0 : if( pItem->mpObject != NULL )
2560 : {
2561 0 : bCollapse = true;
2562 0 : pItem->clearWatchItem();
2563 :
2564 0 : implEnableChildren( pEntry, false );
2565 : }
2566 : }
2567 : }
2568 : else
2569 : {
2570 0 : if( pItem->mpObject != NULL )
2571 : {
2572 0 : bCollapse = true;
2573 0 : pItem->clearWatchItem();
2574 :
2575 0 : implEnableChildren( pEntry, false );
2576 : }
2577 :
2578 0 : bool bString = ((sal_uInt8)eType == (sal_uInt8)SbxSTRING);
2579 0 : OUString aStrStr( "\"" );
2580 0 : if( bString )
2581 : {
2582 0 : aWatchStr += aStrStr;
2583 : }
2584 0 : aWatchStr += pVar->GetOUString();
2585 0 : if( bString )
2586 : {
2587 0 : aWatchStr += aStrStr;
2588 0 : }
2589 : }
2590 0 : if( aTypeStr.isEmpty() )
2591 : {
2592 0 : if( !pVar->IsFixed() )
2593 : {
2594 0 : aTypeStr = "Variant/";
2595 : }
2596 0 : aTypeStr += getBasicTypeName( pVar->GetType() );
2597 : }
2598 : }
2599 0 : else if( !bArrayElement )
2600 : {
2601 0 : aWatchStr += "<Out of Scope>";
2602 : }
2603 :
2604 0 : if( bCollapse )
2605 : {
2606 0 : implCollapseModifiedObjectEntry( pEntry, this );
2607 : }
2608 :
2609 : }
2610 0 : else if( bBasicStopped )
2611 : {
2612 0 : if( pItem->mpObject || pItem->mpArray )
2613 : {
2614 0 : implCollapseModifiedObjectEntry( pEntry, this );
2615 0 : pItem->mpObject = NULL;
2616 : }
2617 : }
2618 :
2619 0 : SvHeaderTabListBox::SetEntryText( aWatchStr, pEntry, ITEM_ID_VALUE-1 );
2620 0 : SvHeaderTabListBox::SetEntryText( aTypeStr, pEntry, ITEM_ID_TYPE-1 );
2621 :
2622 0 : pEntry = Next( pEntry );
2623 0 : }
2624 :
2625 : // Force redraw
2626 0 : Invalidate();
2627 :
2628 0 : SbxBase::ResetError();
2629 0 : if( eOld != SbxERR_OK )
2630 0 : SbxBase::SetError( eOld );
2631 0 : setBasicWatchMode( false );
2632 0 : }
2633 :
2634 0 : CodeCompleteListBox::CodeCompleteListBox( CodeCompleteWindow* pPar )
2635 : : ListBox(pPar, WB_SORT | WB_BORDER ),
2636 0 : pCodeCompleteWindow( pPar )
2637 : {
2638 0 : SetDoubleClickHdl(LINK(this, CodeCompleteListBox, ImplDoubleClickHdl));
2639 0 : SetSelectHdl(LINK(this, CodeCompleteListBox, ImplSelectHdl));
2640 0 : }
2641 :
2642 0 : CodeCompleteListBox::~CodeCompleteListBox()
2643 : {
2644 0 : disposeOnce();
2645 0 : }
2646 :
2647 0 : void CodeCompleteListBox::dispose()
2648 : {
2649 0 : pCodeCompleteWindow.clear();
2650 0 : ListBox::dispose();
2651 0 : }
2652 :
2653 0 : IMPL_LINK_NOARG(CodeCompleteListBox, ImplDoubleClickHdl)
2654 : {
2655 0 : InsertSelectedEntry();
2656 0 : return 0;
2657 : }
2658 :
2659 0 : IMPL_LINK_NOARG(CodeCompleteListBox, ImplSelectHdl)
2660 : {//give back the focus to the parent
2661 0 : pCodeCompleteWindow->pParent->GrabFocus();
2662 0 : return 0;
2663 : }
2664 :
2665 0 : ExtTextView* CodeCompleteListBox::GetParentEditView()
2666 : {
2667 0 : return pCodeCompleteWindow->pParent->GetEditView();
2668 : }
2669 :
2670 0 : void CodeCompleteListBox::InsertSelectedEntry()
2671 : {
2672 0 : if( !aFuncBuffer.toString().isEmpty() )
2673 : {
2674 : // if the user typed in something: remove, and insert
2675 0 : GetParentEditView()->SetSelection( pCodeCompleteWindow->pParent->GetLastHighlightPortionTextSelection() );
2676 0 : GetParentEditView()->DeleteSelected();
2677 :
2678 0 : if( !GetSelectEntry().isEmpty() )
2679 : {//if the user selected something
2680 0 : GetParentEditView()->InsertText( GetSelectEntry(), false );
2681 : }
2682 : }
2683 : else
2684 : {
2685 0 : if( !GetSelectEntry().isEmpty() )
2686 : {//if the user selected something
2687 0 : GetParentEditView()->InsertText( GetSelectEntry(), false );
2688 : }
2689 : }
2690 0 : HideAndRestoreFocus();
2691 0 : }
2692 :
2693 0 : void CodeCompleteListBox::SetMatchingEntries()
2694 : {
2695 0 : for(sal_Int32 i=0; i< GetEntryCount(); ++i)
2696 : {
2697 0 : OUString sEntry = GetEntry(i);
2698 0 : if( sEntry.startsWithIgnoreAsciiCase( aFuncBuffer.toString() ) )
2699 : {
2700 0 : SelectEntry(sEntry);
2701 0 : break;
2702 : }
2703 0 : }
2704 0 : }
2705 :
2706 0 : void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
2707 : {
2708 0 : sal_Unicode aChar = rKeyEvt.GetKeyCode().GetCode();
2709 0 : if( (( aChar >= KEY_A ) && ( aChar <= KEY_Z ))
2710 0 : || ((aChar >= KEY_0) && (aChar <= KEY_9)) )
2711 : {
2712 0 : aFuncBuffer.append(rKeyEvt.GetCharCode());
2713 0 : SetMatchingEntries();
2714 : }
2715 : else
2716 : {
2717 0 : switch( aChar )
2718 : {
2719 : case KEY_ESCAPE: // hide, do nothing
2720 0 : HideAndRestoreFocus();
2721 0 : break;
2722 : case KEY_RIGHT:
2723 : {
2724 0 : TextSelection aTextSelection( GetParentEditView()->GetSelection() );
2725 0 : if( aTextSelection.GetEnd().GetPara() != pCodeCompleteWindow->GetTextSelection().GetEnd().GetPara()-1 )
2726 : {
2727 0 : HideAndRestoreFocus();
2728 : }
2729 0 : break;
2730 : }
2731 : case KEY_LEFT:
2732 : {
2733 0 : TextSelection aTextSelection( GetParentEditView()->GetSelection() );
2734 0 : if( aTextSelection.GetStart().GetIndex()-1 < pCodeCompleteWindow->GetTextSelection().GetStart().GetIndex() )
2735 : {//leave the cursor where it is
2736 0 : HideAndRestoreFocus();
2737 : }
2738 0 : break;
2739 : }
2740 : case KEY_TAB:
2741 : {
2742 0 : TextSelection aTextSelection = pCodeCompleteWindow->pParent->GetLastHighlightPortionTextSelection();
2743 0 : OUString sTypedText = pCodeCompleteWindow->pParent->GetEditEngine()->GetText(aTextSelection);
2744 0 : if( !aFuncBuffer.isEmpty() )
2745 : {
2746 0 : sal_Int32 nInd = GetSelectEntryPos();
2747 0 : if( nInd != LISTBOX_ENTRY_NOTFOUND )
2748 : {//if there is something selected
2749 0 : bool bFound = false;
2750 0 : if( nInd == GetEntryCount() )
2751 0 : nInd = 0;
2752 0 : for( sal_Int32 i = nInd; i != GetEntryCount(); ++i )
2753 : {
2754 0 : OUString sEntry = GetEntry(i);
2755 0 : if( sEntry.startsWithIgnoreAsciiCase( aFuncBuffer.toString() )
2756 0 : && (aFuncBuffer.toString() != sTypedText) && (i != nInd) )
2757 : {
2758 0 : SelectEntry( sEntry );
2759 0 : bFound = true;
2760 0 : break;
2761 : }
2762 0 : }
2763 0 : if( !bFound )
2764 0 : SetMatchingEntries();
2765 :
2766 0 : GetParentEditView()->SetSelection( aTextSelection );
2767 0 : GetParentEditView()->DeleteSelected();
2768 0 : GetParentEditView()->InsertText( GetSelectEntry(), false );
2769 : }
2770 : }
2771 0 : break;
2772 : }
2773 : case KEY_SPACE:
2774 0 : HideAndRestoreFocus();
2775 0 : break;
2776 : case KEY_BACKSPACE: case KEY_DELETE:
2777 0 : if( !aFuncBuffer.toString().isEmpty() )
2778 : {
2779 : //if there was something inserted by tab: add it to aFuncBuffer
2780 0 : TextSelection aSel( GetParentEditView()->GetSelection() );
2781 0 : TextPaM aEnd( GetParentEditView()->CursorEndOfLine(pCodeCompleteWindow->GetTextSelection().GetEnd()) );
2782 0 : GetParentEditView()->SetSelection(TextSelection(pCodeCompleteWindow->GetTextSelection().GetStart(), aEnd ) );
2783 0 : OUString aTabInsertedStr( GetParentEditView()->GetSelected() );
2784 0 : GetParentEditView()->SetSelection( aSel );
2785 :
2786 0 : if( !aTabInsertedStr.isEmpty() && aTabInsertedStr != aFuncBuffer.toString() )
2787 : {
2788 0 : aFuncBuffer.makeStringAndClear();
2789 0 : aFuncBuffer = aFuncBuffer.append(aTabInsertedStr);
2790 : }
2791 0 : aFuncBuffer = aFuncBuffer.remove(aFuncBuffer.getLength()-1, 1);
2792 0 : SetMatchingEntries();
2793 : }
2794 : else
2795 0 : pCodeCompleteWindow->ClearAndHide();
2796 0 : break;
2797 : case KEY_RETURN:
2798 0 : InsertSelectedEntry();
2799 0 : break;
2800 : case KEY_UP: case KEY_DOWN:
2801 0 : NotifyEvent nEvt( MouseNotifyEvent::KEYINPUT, NULL, &rKeyEvt );
2802 0 : PreNotify(nEvt);
2803 0 : break;
2804 : }
2805 : }
2806 0 : ListBox::KeyInput(rKeyEvt);
2807 0 : }
2808 :
2809 0 : void CodeCompleteListBox::HideAndRestoreFocus()
2810 : {
2811 0 : pCodeCompleteWindow->Hide();
2812 0 : pCodeCompleteWindow->pParent->GrabFocus();
2813 0 : }
2814 :
2815 0 : CodeCompleteWindow::CodeCompleteWindow( EditorWindow* pPar )
2816 : : Window( pPar ),
2817 : pParent( pPar ),
2818 0 : pListBox( VclPtr<CodeCompleteListBox>::Create(this) )
2819 : {
2820 0 : SetSizePixel( Size(151,151) ); //default, later it changes
2821 0 : InitListBox();
2822 0 : }
2823 :
2824 0 : CodeCompleteWindow::~CodeCompleteWindow()
2825 : {
2826 0 : disposeOnce();
2827 0 : }
2828 :
2829 0 : void CodeCompleteWindow::dispose()
2830 : {
2831 0 : pListBox.disposeAndClear();
2832 0 : pParent.clear();
2833 0 : vcl::Window::dispose();
2834 0 : }
2835 :
2836 0 : void CodeCompleteWindow::InitListBox()
2837 : {
2838 0 : pListBox->SetSizePixel( Size(150,150) ); //default, this will adopt the line length
2839 0 : pListBox->Show();
2840 0 : pListBox->EnableQuickSelection( false );
2841 0 : }
2842 :
2843 0 : void CodeCompleteWindow::InsertEntry( const OUString& aStr )
2844 : {
2845 0 : pListBox->InsertEntry( aStr );
2846 0 : }
2847 :
2848 0 : void CodeCompleteWindow::ClearListBox()
2849 : {
2850 0 : pListBox->Clear();
2851 0 : pListBox->aFuncBuffer.makeStringAndClear();
2852 0 : }
2853 :
2854 0 : void CodeCompleteWindow::SetTextSelection( const TextSelection& aSel )
2855 : {
2856 0 : aTextSelection = aSel;
2857 0 : }
2858 :
2859 :
2860 0 : void CodeCompleteWindow::ResizeAndPositionListBox()
2861 : {
2862 0 : if( pListBox->GetEntryCount() >= 1 )
2863 : {// if there is at least one element inside
2864 : // calculate basic position: under the current line
2865 0 : Rectangle aRect = static_cast<TextEngine*>(pParent->GetEditEngine())->PaMtoEditCursor( pParent->GetEditView()->GetSelection().GetEnd() , false );
2866 0 : long nViewYOffset = pParent->GetEditView()->GetStartDocPos().Y();
2867 0 : Point aPos = aRect.BottomRight();// this variable will be used later (if needed)
2868 0 : aPos.Y() = (aPos.Y() - nViewYOffset) + nBasePad;
2869 :
2870 0 : OUString aLongestEntry = pListBox->GetEntry( 0 );// grab the longest one: max search
2871 0 : for( sal_Int32 i=1; i< pListBox->GetEntryCount(); ++i )
2872 : {
2873 0 : if( pListBox->GetEntry( i ).getLength() > aLongestEntry.getLength() )
2874 0 : aLongestEntry = pListBox->GetEntry( i );
2875 : }
2876 : // get column/line count
2877 0 : const sal_uInt16& nColumns = aLongestEntry.getLength();
2878 0 : const sal_uInt16 nLines = static_cast<sal_uInt16>( std::min( (sal_Int32) 6, pListBox->GetEntryCount() ));
2879 :
2880 0 : Size aSize = pListBox->CalcBlockSize( nColumns, nLines );
2881 : //set the size
2882 0 : SetSizePixel( aSize );
2883 : //1 px smaller, to see the border
2884 0 : aSize.setWidth( aSize.getWidth() - 1 );
2885 0 : aSize.setHeight( aSize.getHeight() - 1 );
2886 0 : pListBox->SetSizePixel( aSize );
2887 :
2888 : //calculate position
2889 0 : const Rectangle aVisArea( pParent->GetEditView()->GetStartDocPos(), pParent->GetOutputSizePixel() );//the visible area
2890 0 : const Point& aBottomPoint = aVisArea.BottomRight();
2891 :
2892 0 : if( aVisArea.TopRight().getY() + aPos.getY() + aSize.getHeight() > aBottomPoint.getY() )
2893 : {//clipped at the bottom: move it up
2894 0 : const long& nParentFontHeight = pParent->GetEditEngine()->GetFont().GetHeight();//parent's font (in the IDE): needed for height
2895 0 : aPos.Y() -= aSize.getHeight() + nParentFontHeight + nCursorPad;
2896 : }
2897 :
2898 0 : if( aVisArea.TopLeft().getX() + aPos.getX() + aSize.getWidth() > aBottomPoint.getX() )
2899 : {//clipped at the right side, move it a bit left
2900 0 : aPos.X() -= aSize.getWidth() + aVisArea.TopLeft().getX();
2901 : }
2902 : //set the position
2903 0 : SetPosPixel( aPos );
2904 : }
2905 0 : }
2906 :
2907 0 : void CodeCompleteWindow::SelectFirstEntry()
2908 : {
2909 0 : if( pListBox->GetEntryCount() > 0 )
2910 : {
2911 0 : pListBox->SelectEntryPos( 0 );
2912 : }
2913 0 : }
2914 :
2915 0 : void CodeCompleteWindow::ClearAndHide()
2916 : {
2917 0 : ClearListBox();
2918 0 : pListBox->HideAndRestoreFocus();
2919 0 : }
2920 :
2921 0 : UnoTypeCodeCompletetor::UnoTypeCodeCompletetor( const std::vector< OUString >& aVect, const OUString& sVarType )
2922 0 : : bCanComplete( true )
2923 : {
2924 0 : if( aVect.size() == 0 || sVarType.isEmpty() )
2925 : {
2926 0 : bCanComplete = false;//invalid parameters, nothing to code complete
2927 0 : return;
2928 : }
2929 :
2930 : try
2931 : {
2932 : // Get the base class for reflection:
2933 0 : xClass = css::reflection::theCoreReflection::get(
2934 0 : comphelper::getProcessComponentContext())->forName(sVarType);
2935 : }
2936 0 : catch( const Exception& )
2937 : {
2938 0 : bCanComplete = false;
2939 0 : return;
2940 : }
2941 :
2942 0 : unsigned int j = 1;//start from aVect[1]: aVect[0] is the variable name
2943 0 : OUString sMethName;
2944 :
2945 0 : while( j != aVect.size() )
2946 : {
2947 0 : sMethName = aVect[j];
2948 :
2949 0 : if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
2950 : {
2951 0 : if( !CheckMethod(sMethName) && !CheckField(sMethName) )
2952 : {
2953 0 : bCanComplete = false;
2954 0 : break;
2955 : }
2956 : }
2957 : else
2958 : {
2959 0 : if( !CheckField(sMethName) )
2960 : {
2961 0 : bCanComplete = false;
2962 0 : break;
2963 : }
2964 : }
2965 :
2966 0 : ++j;
2967 0 : }
2968 : }
2969 :
2970 0 : std::vector< OUString > UnoTypeCodeCompletetor::GetXIdlClassMethods() const
2971 : {
2972 0 : std::vector< OUString > aRetVect;
2973 0 : if( bCanComplete && ( xClass != NULL ) )
2974 : {
2975 0 : Sequence< Reference< reflection::XIdlMethod > > aMethods = xClass->getMethods();
2976 0 : if( aMethods.getLength() != 0 )
2977 : {
2978 0 : for(sal_Int32 l = 0; l < aMethods.getLength(); ++l)
2979 : {
2980 0 : aRetVect.push_back( OUString(aMethods[l]->getName()) );
2981 : }
2982 0 : }
2983 : }
2984 0 : return aRetVect;//this is empty when cannot code complete
2985 : }
2986 :
2987 0 : std::vector< OUString > UnoTypeCodeCompletetor::GetXIdlClassFields() const
2988 : {
2989 0 : std::vector< OUString > aRetVect;
2990 0 : if( bCanComplete && ( xClass != NULL ) )
2991 : {
2992 0 : Sequence< Reference< reflection::XIdlField > > aFields = xClass->getFields();
2993 0 : if( aFields.getLength() != 0 )
2994 : {
2995 0 : for(sal_Int32 l = 0; l < aFields.getLength(); ++l)
2996 : {
2997 0 : aRetVect.push_back( OUString(aFields[l]->getName()) );
2998 : }
2999 0 : }
3000 : }
3001 0 : return aRetVect;//this is empty when cannot code complete
3002 : }
3003 :
3004 :
3005 0 : bool UnoTypeCodeCompletetor::CheckField( const OUString& sFieldName )
3006 : {// modifies xClass!!!
3007 0 : Reference< reflection::XIdlField> xField = xClass->getField( sFieldName );
3008 0 : if( xField != NULL )
3009 : {
3010 0 : xClass = xField->getType();
3011 0 : if( xClass != NULL )
3012 : {
3013 0 : return true;
3014 : }
3015 : }
3016 0 : return false;
3017 : }
3018 :
3019 0 : bool UnoTypeCodeCompletetor::CheckMethod( const OUString& sMethName )
3020 : {// modifies xClass!!!
3021 0 : Reference< reflection::XIdlMethod> xMethod = xClass->getMethod( sMethName );
3022 0 : if( xMethod != NULL ) //method OK, check return type
3023 : {
3024 0 : xClass = xMethod->getReturnType();
3025 0 : if( xClass != NULL )
3026 : {
3027 0 : return true;
3028 : }
3029 : }
3030 0 : return false;
3031 : }
3032 :
3033 0 : } // namespace basctl
3034 :
3035 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|