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